Skip to main content

server/services/action/
discard_cards_to_crib.rs

1use crate::{
2    domain::{Card, GameCommand, GameId, UserId},
3    error::{ServerError, bug},
4    server_state::ServerState,
5    services::queries::get_game,
6};
7
8/// Discards a set of cards from a player's hand to the crib in a game.
9///
10/// This function updates the game state to move the specified cards
11/// from the user's hand into the crib. It validates that the action
12/// is allowed for the given user and game.
13///
14/// # Parameters
15///
16/// - `server_state`: The shared server state containing the game and database.
17/// - `user_id`: The ID of the user performing the discard.
18/// - `game_id`: The ID of the game in which the discard occurs.
19/// - `cards`: The cards to discard into the crib.
20///
21/// # Returns
22///
23/// Returns `Ok(())` if the discard was successful. Returns a `ServerError` if
24/// the action is forbidden, the game is not found, or another internal error occurs.
25pub async fn discard_cards_to_crib(
26    server_state: ServerState,
27    user_id: UserId,
28    game_id: GameId,
29    cards: Vec<Card>,
30) -> Result<(), ServerError> {
31    if let Some(game) = get_game(server_state.clone(), game_id).await? {
32        let player = game
33            .validate_user(user_id)
34            .ok_or(ServerError::Forbidden("discard cards to crib".into()))?;
35
36        let aggregate_id = game_id.value().to_string();
37
38        let command = GameCommand::DiscardCards { player, cards };
39
40        server_state
41            .cqrs
42            .execute(&aggregate_id, command)
43            .await
44            .map_err(bug!())?;
45
46        Ok(())
47    } else {
48        Err(ServerError::NotFound)
49    }
50}