diff options
| -rw-r--r-- | src/main.rs | 74 | ||||
| -rw-r--r-- | static/style.css | 13 |
2 files changed, 79 insertions, 8 deletions
diff --git a/src/main.rs b/src/main.rs index a4224d7..92bda43 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,7 +65,6 @@ struct Notes { struct Round { author: UserId, - notes: Notes, guesses: HashMap<UserId, String>, /// [true] means the judge has accepted it. Missing means they haven't done anything correct: HashMap<UserId, bool>, @@ -76,6 +75,7 @@ struct Game { // If we've started or not is_started: bool, + is_finished: bool, /// All users that are in the game. active_users: HashSet<UserId>, @@ -137,12 +137,6 @@ impl Game { }; self.rounds.push(Round { author: uid, - notes: self - .submissions - .get(&uid) - .context("get users submission") - .unwrap() - .clone(), guesses: HashMap::new(), correct: HashMap::new(), }); @@ -189,6 +183,13 @@ impl Game { r.correct.insert(uid, mark); } + fn scoring(&mut self) { + self.broadcast_screen(self.screen_scoring()) + .context("broadcast scoring screen") + .unwrap(); + self.is_finished = true; + } + fn screen_submitted(&self) -> Markup { html! { h1 { "Submitted!" } @@ -290,7 +291,40 @@ impl Game { (self.guess_li(u)) } } - button { "Done" } + button hx-post=(format!("/game/{}/judge", self.id)) { "Done" } + } + } + + fn screen_scoring(&self) -> Markup { + let mut scores = HashMap::new(); + + for u in &self.active_users { + scores.insert(u, 0); + } + + for r in &self.rounds { + for (u, yes) in r.correct.iter() { + if *yes { + if let Some(n) = scores.get_mut(u) { + *n += 1; + } else { + warn!(u=?u, "Tried to give points to inactive user"); + } + } + } + } + let mut v = scores.into_iter().collect::<Vec<_>>(); + v.sort_by_key(|t| -t.1); + + html! { + h1 { "Leaderboard" } + ol { + @for (uid, score) in v { + li { span { (uid.0) ": " (score) " points" } } + } + } + + a href="/" { "Back" } } } @@ -332,6 +366,7 @@ impl ServerState { let g = Game { id: gid, is_started: false, + is_finished: false, active_users: HashSet::new(), submissions: HashMap::new(), next_rounds: Vec::new(), @@ -436,6 +471,8 @@ async fn get_game( let g = game.lock().await; if !g.is_started { g.screen_lobby() + } else if g.is_finished { + g.screen_scoring() } else if g.rounds.len() == 0 { if g.submissions.contains_key(&uid) { g.screen_submitted() @@ -556,6 +593,26 @@ async fn mark_guess( g.guess_li(guess_id).into_string().into_response() } +/// Judge is done judging all submissions +async fn submit_judge(Path(gid): Path<u64>, State(st): State<Server>) -> Response { + let glock = { + if let Some(g) = st.lock().await.games.get(&gid) { + g.clone() + } else { + return (StatusCode::NOT_FOUND).into_response(); + } + }; + let mut g = glock.lock().await; + + if g.next_rounds.is_empty() { + g.scoring(); + } else { + g.new_round(); + } + + StatusCode::OK.into_response() +} + async fn game_ws( ws: WebSocketUpgrade, Path(gid): Path<u64>, @@ -677,6 +734,7 @@ async fn main() -> Result<()> { .route("/game/{gid}/guess", post(guess_tune)) .route("/game/{gid}/submit", post(submit_game)) .route("/game/{gid}/mark/{uid}/{status}", post(mark_guess)) + .route("/game/{gid}/judge", post(submit_judge)) .route("/game/{gid}/ws", get(game_ws)) .nest_service("/static", ServeDir::new("static")) .layer(CatchPanicLayer::custom(handle_panic)) diff --git a/static/style.css b/static/style.css index e61cc02..3b9ba9d 100644 --- a/static/style.css +++ b/static/style.css @@ -3,3 +3,16 @@ body { } + +#guesslist { + list-style: none; + [data-accept="none"] { + background: #aaa; + } + [data-accept="true"] { + background: #00ff00; + } + [data-accept="false"] { + background: #ff0000; + } +} |
