Scope the leaderboard to a selectable game
Elo ratings are stored per game type, so the leaderboard now always requests /api/leaderboard?game_type=<id> and shows only that game's players, Elo, wins, matches and points instead of mixing all games' aggregates with the default game's rating. - api::leaderboard takes the game type; - a "Game" dropdown next to the heading lists every registered game and reloads the board on change (stale in-flight responses are dropped); - move fallback_game_types() from the lobby to model.rs so both the lobby and leaderboard selectors work when /api/game-types fails.
This commit is contained in:
@@ -408,6 +408,38 @@ pub struct GameTypesPage {
|
||||
pub results: Vec<GameTypeInfo>,
|
||||
}
|
||||
|
||||
/// The games to show in the lobby's and leaderboard's game selectors when
|
||||
/// the `/api/game-types` fetch fails: match creation and per-game views
|
||||
/// must still work.
|
||||
pub fn fallback_game_types() -> Vec<GameTypeInfo> {
|
||||
vec![
|
||||
GameTypeInfo {
|
||||
id: "scopone_scientifico".to_string(),
|
||||
name: "Scopone scientifico".to_string(),
|
||||
description: String::new(),
|
||||
min_players: 4,
|
||||
max_players: 4,
|
||||
options_schema: serde_json::Value::Null,
|
||||
},
|
||||
GameTypeInfo {
|
||||
id: "briscola".to_string(),
|
||||
name: "Briscola".to_string(),
|
||||
description: String::new(),
|
||||
min_players: 2,
|
||||
max_players: 2,
|
||||
options_schema: serde_json::Value::Null,
|
||||
},
|
||||
GameTypeInfo {
|
||||
id: "briscola_a_quattro".to_string(),
|
||||
name: "Briscola a quattro".to_string(),
|
||||
description: String::new(),
|
||||
min_players: 4,
|
||||
max_players: 4,
|
||||
options_schema: serde_json::Value::Null,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
/// One configured OIDC login provider (GET /api/auth/providers).
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||
pub struct AuthProvider {
|
||||
@@ -1142,6 +1174,18 @@ mod tests {
|
||||
assert_eq!("?", suit_name("?"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fallback_game_types_cover_the_registered_games() {
|
||||
let types = fallback_game_types();
|
||||
let ids: Vec<&str> = types.iter().map(|g| g.id.as_str()).collect();
|
||||
assert_eq!(
|
||||
vec!["scopone_scientifico", "briscola", "briscola_a_quattro"],
|
||||
ids
|
||||
);
|
||||
// The lobby's first game (the creation default) must exist.
|
||||
assert_eq!("scopone_scientifico", types[0].id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn game_view_parses_briscola_payload() {
|
||||
let g: GameView = serde_json::from_value(json!({
|
||||
|
||||
Reference in New Issue
Block a user