From 653c7d93e9f8ecae78bdd2d884cce59041b11202 Mon Sep 17 00:00:00 2001 From: Arnaud Bailly Date: Thu, 10 Oct 2024 18:23:02 +0200 Subject: Improve leaderboard to add timestamp and result --- rust/src/lambda.rs | 5 ++-- rust/src/web.rs | 62 ++++++++++++++++++++--------------------- rust/templates/leaderboard.html | 38 +++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 36 deletions(-) diff --git a/rust/src/lambda.rs b/rust/src/lambda.rs index 4027a62..30f9f43 100644 --- a/rust/src/lambda.rs +++ b/rust/src/lambda.rs @@ -1,11 +1,10 @@ use proptest::{ - arbitrary::{any, any_with, arbitrary_with}, + arbitrary::any, prelude::*, strategy::{Strategy, ValueTree}, test_runner::TestRunner, }; -use rand::{rngs::SmallRng, Rng, RngCore, SeedableRng}; -use serde::{Deserialize, Serialize}; +use rand::Rng; use std::collections::HashMap; use crate::ast::*; diff --git a/rust/src/web.rs b/rust/src/web.rs index 291801a..0bf36a5 100644 --- a/rust/src/web.rs +++ b/rust/src/web.rs @@ -1,13 +1,10 @@ -use actix_web::{ - get, middleware::Logger, post, web, App, HttpResponse, HttpServer, Responder, - Result as ActixResult, -}; +use actix_web::{get, middleware::Logger, post, web, App, HttpResponse, HttpServer, Responder}; +use chrono::{DateTime, Utc}; use clap::Parser; use futures::lock::Mutex; use handlebars::{DirectorySourceOptions, Handlebars}; use log::info; use proptest::test_runner::{Config, RngAlgorithm, TestRng, TestRunner}; -use rand::Rng; use serde::{Deserialize, Serialize}; use std::time::Duration; use std::{collections::HashMap, sync::Arc}; @@ -27,6 +24,8 @@ struct Registration { struct ClientData { name: String, grade: u8, + last_query: DateTime, + success: bool, } impl ClientData { @@ -34,6 +33,14 @@ impl ClientData { ClientData { name: client.name.clone(), grade: client.grade, + last_query: client + .results + .last() + .map_or(chrono::offset::Utc::now(), |q| q.timestamp), + success: client + .results + .last() + .map_or(false, |q| matches!(q.result, TestResult::TestSucceeded)), } } } @@ -47,17 +54,6 @@ trait AppState: Send + Sync { fn register(&mut self, registration: &Registration) -> RegistrationResult; } -fn make_leaderboard(clients: Vec) -> Leaderboard { - let clients = clients - .iter() - .map(|c| ClientData { - name: c.name.clone(), - grade: c.grade, - }) - .collect(); - Leaderboard { clients } -} - #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] enum RegistrationResult { RegistrationSuccess { id: String, url: String }, @@ -71,10 +67,16 @@ struct Client { url: String, grade: u8, runner: TestRunner, - results: Vec, + results: Vec, delay: std::time::Duration, } +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] +struct Test { + timestamp: DateTime, + result: TestResult, +} + #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] enum TestResult { TestFailed(String), @@ -132,11 +134,8 @@ impl Client { ) } - fn check_result( - &mut self, - expected: &String, - response: &Result, - ) -> TestResult { + fn check_result(&mut self, expected: &String, response: &Result) -> Test { + let timestamp = chrono::offset::Utc::now(); let result = match response { Ok(expr) => { let vals = parse(expr); @@ -162,8 +161,9 @@ impl Client { } Err(res) => res.clone(), }; - self.results.push(result.clone()); - result + let test = Test { result, timestamp }; + self.results.push(test.clone()); + test } } @@ -226,9 +226,9 @@ async fn eval(input: String) -> impl Responder { .map(|v| format!("{}", v)) .collect::>() .join("\n"); - HttpResponse::Ok().body(format!("{}", output)) + HttpResponse::Ok().body(output.to_string()) } - Err(e) => HttpResponse::BadRequest().body(format!("{}", e)), + Err(e) => HttpResponse::BadRequest().body(e.to_string()), } } @@ -243,6 +243,7 @@ async fn leaderboard( let client = client.lock().await; client_data.push(ClientData::from(&client)); } + client_data.sort_by(|a, b| b.grade.cmp(&a.grade)); let body = hb .render( @@ -357,7 +358,6 @@ mod app_tests { #[actix_web::test] async fn post_registration_returns_success_with_unique_id() { - let id = "0123456789abcdef0123456789abcdef".to_string(); let state = Arc::new(Mutex::new(State::new())); // FIXME should only be called once, move to setup env_logger::init(); @@ -679,9 +679,9 @@ mod app_tests { let expected = "1".to_string(); let response = Ok("1".to_string()); - let result = client.check_result(&expected, &response); + let test = client.check_result(&expected, &response); - assert_eq!(TestResult::TestSucceeded, result); + assert_eq!(TestResult::TestSucceeded, test.result); assert_eq!(2, client.grade); } @@ -691,9 +691,9 @@ mod app_tests { let expected = "1".to_string(); let response = Ok("2".to_string()); - let result = client.check_result(&expected, &response); + let test = client.check_result(&expected, &response); - assert_eq!(TestResult::TestFailed("2".to_string()), result); + assert_eq!(TestResult::TestFailed("2".to_string()), test.result); assert_eq!(1, client.grade); } diff --git a/rust/templates/leaderboard.html b/rust/templates/leaderboard.html index f062323..82992d1 100644 --- a/rust/templates/leaderboard.html +++ b/rust/templates/leaderboard.html @@ -2,14 +2,48 @@ + Leaderboard + + +

Leaderboard

- + {{#each this.clients}} - + {{/each}}
NameGrade
NameGradeLast test
{{this.name}}{{this.grade}}
{{this.name}}{{this.grade}}{{this.last_query}}
-- cgit v1.2.3