diff options
| author | Martin Hafskjold Thoresen <martin@vind.ai> | 2025-01-04 22:43:08 +0100 |
|---|---|---|
| committer | Martin Hafskjold Thoresen <martin@vind.ai> | 2025-01-04 22:43:08 +0100 |
| commit | c5fce19c22ec32129a8b8135c35798e430c5fc53 (patch) | |
| tree | 885e8bca1c70d65eb4945aa0ba1277fa2232a043 /src/main.rs | |
| parent | fc991e417d0b8ebc87557b9c0817c1f9ed6e7a1b (diff) | |
| download | musicgame-c5fce19c22ec32129a8b8135c35798e430c5fc53.tar.gz musicgame-c5fce19c22ec32129a8b8135c35798e430c5fc53.zip | |
Working end-to-end game logic
Just need the sound playing now
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 74 |
1 files changed, 66 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)) |
