@ -3,100 +3,112 @@ use super::{
socket_manager ::SocketManager ,
ServiceData ,
} ;
use crate ::{ games ::{ CardId , CardIdx , PileKind , RunningPile } , server ::protos ::{ game ::game_status ::CustomInfoMessage , protocol ::server_client_packet ::Data } } ;
use crate ::{ games ::{ CardId , CardIdx , PileKind , RunningPile } , server ::protos ::{ game ::game_status ::CustomInfoMessage , protocol ::server_client_packet ::{ self , Data } } } ;
use anyhow ::{ anyhow , Result } ;
pub ( super ) async fn get_status ( data : & mut ServiceData ) -> Result < GameStatus > {
pub ( super ) async fn get_status ( data : & mut ServiceData ,
socket_mgr : & SocketManager , ) -> Result < GameStatus > {
let uuid = data . user_id . get ( ) ? ;
log ::info ! ( "Creating a new status for {}" , uuid ) ;
let lobby : u32 = match data . db . get_lobby_for_user ( uuid ) . await {
Some ( l ) = > l ,
None = > return Err ( anyhow ! ( "User isn't in a lobby" ) ) ,
} ;
let games_lock = data . running_games . read ( ) . await ; // This encounters a deadlock
let ( status , name ) = {
let games_lock = data . running_games . read ( ) . await ; // This encounters a deadlock
// log::info!("Locked games");
let game_lock = match games_lock . get ( & lobby ) {
Some ( x ) = > x . read ( ) . await ,
None = > return Err ( anyhow ! ( "User isn't in a lobby with a running game" , ) ) ,
} ;
// log::info!("Locked game");
let game = & game_lock . 1 ;
let mut names = vec ! [ ] ;
for ( uuid , id ) in & game . players {
names . push ( ( data . db . get_name_for_uuid ( * uuid ) . await , * id ) )
}
names . sort_by ( | ( _ , a ) , ( _ , b ) | a . cmp ( b ) ) ;
let names = names
. into_iter ( )
. map ( | ( x , _ ) | super ::protos ::common ::Name { name : x } )
. collect ( ) ;
let status = GameStatus {
current_turn : game . get_current_player ( ) ,
common_piles : Some ( Piles {
piles : game
. piles
. iter ( )
. map ( | ( k , v ) | ( k . clone ( ) , v . clone ( ) ) )
. map ( | ( k , v ) : ( String , RunningPile ) | {
(
k ,
super ::protos ::game ::game_status ::Pile {
cards : v
. cards
. into_iter ( )
. map ( | c | super ::protos ::game ::game_status ::Card {
kind : Some ( CardKind { kind : c . kind } ) ,
visible : true ,
uuid : c . uuid . to_string ( ) ,
} )
. collect ( ) ,
face_down : v . face_down ,
visible : v . visible ,
name : v . name ,
} ,
)
} )
. collect ( ) ,
} ) ,
player_piles : game
. player_piles
. clone ( )
let game_lock = match games_lock . get ( & lobby ) {
Some ( x ) = > x . read ( ) . await ,
None = > return Err ( anyhow ! ( "User isn't in a lobby with a running game" , ) ) ,
} ;
// log::info!("Locked game");
let game = & game_lock . 1 ;
let mut names = vec ! [ ] ;
for ( uuid , id ) in & game . players {
names . push ( ( data . db . get_name_for_uuid ( * uuid ) . await , * id ) )
}
names . sort_by ( | ( _ , a ) , ( _ , b ) | a . cmp ( b ) ) ;
let names = names
. into_iter ( )
. map ( | piles | Piles {
piles : piles
. map ( | ( x , _ ) | super ::protos ::common ::Name { name : x } )
. collect ( ) ;
(
GameStatus {
current_turn : game . get_current_player ( ) ,
common_piles : Some ( Piles {
piles : game
. piles
. iter ( )
. map ( | ( k , v ) | ( k . clone ( ) , v . clone ( ) ) )
. map ( | ( k , v ) : ( String , RunningPile ) | {
(
k ,
super ::protos ::game ::game_status ::Pile {
cards : v
. cards
. into_iter ( )
. map ( | c | super ::protos ::game ::game_status ::Card {
kind : Some ( CardKind { kind : c . kind } ) ,
visible : true ,
uuid : c . uuid . to_string ( ) ,
} )
. collect ( ) ,
face_down : v . face_down ,
visible : v . visible ,
name : v . name ,
} ,
)
} )
. collect ( ) ,
} ) ,
player_piles : game
. player_piles
. clone ( )
. into_iter ( )
. map ( | ( k , v ) | {
(
k ,
super ::protos ::game ::game_status ::Pile {
cards : v
. cards
. into_iter ( )
. map ( | x | super ::protos ::game ::game_status ::Card {
kind : Some ( CardKind { kind : x . kind } ) ,
visible : true ,
uuid : x . uuid . to_string ( ) ,
} )
. collect ( ) ,
face_down : v . face_down ,
visible : v . visible ,
name : v . name ,
} ,
)
. map ( | piles | Piles {
piles : piles
. into_iter ( )
. map ( | ( k , v ) | {
(
k ,
super ::protos ::game ::game_status ::Pile {
cards : v
. cards
. into_iter ( )
. map ( | x | super ::protos ::game ::game_status ::Card {
kind : Some ( CardKind { kind : x . kind } ) ,
visible : true ,
uuid : x . uuid . to_string ( ) ,
} )
. collect ( ) ,
face_down : v . face_down ,
visible : v . visible ,
name : v . name ,
} ,
)
} )
. collect ( ) ,
} )
. collect ( ) ,
} )
. collect ( ) ,
names ,
has_finished : game . has_finished ,
info : None ,
names ,
has_finished : game . has_finished ,
info : None ,
} ,
game . name . clone ( ) ,
)
} ;
log ::info ! ( "Created a new status for {}" , uuid ) ;
if status . has_finished {
log ::info ! ( "Game has finished: {}" , name ) ;
data . running_games . write ( ) . await . remove ( & lobby ) ;
let s = super ::lobby ::get_status ( data ) . await . expect ( "Unexpected error getting lobby status" ) ;
socket_mgr . broadcast_to_lobby ( & mut data . db , data . user_id . 0. unwrap ( ) , server_client_packet ::Data ::LobbyStatus ( s ) ) . await . expect ( "Error sending finished game " ) ;
}
Ok ( status )
}
pub ( super ) async fn query_status ( data : & mut ServiceData , socket_mgr : & SocketManager ) -> Result < ( ) > {
let status = get_status ( data ) . await ? ;
let status = get_status ( data , socket_mgr ) . await ? ;
socket_mgr
. write ( data . user_id . get_ref ( ) ? , Data ::GameStatus ( status ) )
. await
@ -177,10 +189,13 @@ pub(super) async fn on_click(
pile_name : card . pile_name ,
} ;
if let Err ( e ) = game . on_click ( card , game . get_player_for_uuid ( & uuid ) . unwrap ( ) ) {
message = Some ( CustomInfoMessage { title : "Error in game execution" . to_string ( ) , m : e . to_string ( ) } ) ;
message = Some ( CustomInfoMessage {
title : "Error in game execution" . to_string ( ) ,
m : e . to_string ( ) ,
} ) ;
}
} // drop the connection so that the lock is released
let mut status = get_status ( data ) . await ? ;
let mut status = get_status ( data , socket_mgr ) . await ? ;
status . info = message ;
socket_mgr