team04_server/lobby/game/
completion.rs1use rand::seq::IndexedRandom;
2
3use crate::{
4 lobby::state::{LobbyPhase, SharedLobbyState},
5 log,
6 messages::{MessageTx, game_end::GameEnd},
7};
8
9#[must_use = "if true, the game should end"]
10pub async fn completion(lobby: &SharedLobbyState) -> bool {
11 let mut pfx = log::pfx();
12 pfx.lobby(lobby.id());
13 let mut lock = lobby.lock().await;
14 let mut alive_players = lock.clients.players.iter_alive();
15 let mut winner = None;
16 if let Some(potential_winner) = alive_players.next() {
17 if alive_players.next().is_none() {
18 winner = Some(*potential_winner.0);
20 } else {
21 }
23 } else {
24 let max_lives = lock
26 .clients
27 .players
28 .players_all()
29 .map(|p| p.lives)
30 .max()
31 .unwrap();
32 let mut potential_winners = lock
33 .clients
34 .players
35 .iter_all()
36 .filter(|(_id, p)| p.lives == max_lives)
37 .collect::<Vec<_>>();
38 if potential_winners.len() == 1 {
39 winner = Some(*potential_winners[0].0);
40 } else {
41 let max_fights_won = potential_winners
42 .iter()
43 .map(|(_id, p)| p.fights_won)
44 .max()
45 .unwrap();
46 potential_winners.retain(|(_id, p)| p.fights_won == max_fights_won);
47 winner = Some(*potential_winners.choose(&mut rand::rng()).unwrap().0);
49 }
50 }
51 drop(alive_players);
52 lock.phase = LobbyPhase::CompletionPhase;
53 lock.broadcast_gamestate().await;
54 if let Some(winner) = winner {
55 log::info!("player {winner} has won this game!"; log::pfx().lobby(lock.id()));
56 lock.clients
58 .broadcast_message(
59 &GameEnd {
60 winner,
61 global_stats: vec![],
62 player_stats: vec![],
63 }
64 .serialize(),
65 )
66 .await;
67 true
68 } else {
69 false
70 }
71}