Skip to main content

server/services/action/
go.rs

1use crate::{
2    domain::{GameCommand, GameId, UserId},
3    error::{ServerError, bug},
4    server_state::ServerState,
5    services::queries::get_game,
6};
7
8/// Performs a "go" action for the user in a pegging phase of the game.
9///
10/// In Cribbage, a "go" indicates that the current player cannot play
11/// any card without exceeding the running total. This function updates
12/// the game state accordingly, advancing the turn or ending the pegging
13/// sequence as necessary.
14///
15/// # Parameters
16///
17/// - `server_state`: The shared server state containing the game and database.
18/// - `user_id`: The ID of the user performing the "go".
19/// - `game_id`: The ID of the game in which the action occurs.
20///
21/// # Returns
22///
23/// Returns `Ok(())` if the action was successful. Returns a `ServerError` if
24/// the action is forbidden, the game is not found, or another internal error occurs.
25pub async fn go(
26    server_state: ServerState,
27    user_id: UserId,
28    game_id: GameId,
29) -> Result<(), ServerError> {
30    if let Some(game) = get_game(server_state.clone(), game_id).await? {
31        let player = game
32            .validate_user(user_id)
33            .ok_or(ServerError::Forbidden("go".into()))?;
34
35        let aggregate_id = game_id.value().to_string();
36
37        let command = GameCommand::Go { player };
38
39        server_state
40            .cqrs
41            .execute(&aggregate_id, command)
42            .await
43            .map_err(bug!())?;
44
45        Ok(())
46    } else {
47        Err(ServerError::NotFound)
48    }
49}