@ -5,9 +5,9 @@ use tokio::sync::{mpsc, RwLock};
use std ::{ collections ::HashMap , convert ::TryInto , sync ::Arc } ;
use std ::{ collections ::HashMap , convert ::TryInto , sync ::Arc } ;
use super ::grpc ::common ::{ HasNewStatus , LastStatusTimestamp , Name } ;
use super ::grpc ::common ::{ HasNewStatus , LastStatusTimestamp , Name } ;
use super ::grpc ::game ::MessageStatus ;
use super ::grpc ::lobby ::lobby_server ::Lobby ;
use super ::grpc ::lobby ::lobby_server ::Lobby ;
use super ::grpc ::lobby ::{ LobbyStatus , SingleVote , Vote } ;
use super ::grpc ::lobby ::{ LobbyStatus , SingleVote , Vote } ;
use super ::grpc ::game ::MessageStatus ;
pub use super ::grpc ::lobby ::lobby_server ::LobbyServer ;
pub use super ::grpc ::lobby ::lobby_server ::LobbyServer ;
@ -18,137 +18,143 @@ use super::client_id;
use crate ::{ db , games ::RunningGame } ;
use crate ::{ db , games ::RunningGame } ;
pub struct LobbyService {
pub struct LobbyService {
conn : RwLock < db ::DbClient > ,
conn : RwLock < db ::DbClient > ,
games : Arc < Vec < crate ::games ::Game > > ,
games : Arc < Vec < crate ::games ::Game > > ,
voting : votes ::VotingSystem ,
voting : votes ::VotingSystem ,
running_games : Arc < RwLock < HashMap < u32 , RwLock < ( u32 , RunningGame , Modifiable < Option < MessageStatus > > ) > > > > ,
running_games :
Arc < RwLock < HashMap < u32 , RwLock < ( u32 , RunningGame , Modifiable < Option < MessageStatus > > ) > > > > ,
}
}
impl LobbyService {
impl LobbyService {
pub fn new (
pub fn new (
conn : db ::DbClient ,
conn : db ::DbClient ,
voting : votes ::VotingSystem ,
voting : votes ::VotingSystem ,
games : Arc < Vec < crate ::games ::Game > > ,
games : Arc < Vec < crate ::games ::Game > > ,
running_games : Arc < RwLock < HashMap < u32 , RwLock < ( u32 , RunningGame , Modifiable < Option < MessageStatus > > ) > > > > ,
running_games : Arc <
) -> Self {
RwLock < HashMap < u32 , RwLock < ( u32 , RunningGame , Modifiable < Option < MessageStatus > > ) > > > ,
Self {
> ,
conn : RwLock ::new ( conn ) ,
) -> Self {
voting ,
Self {
running_games ,
conn : RwLock ::new ( conn ) ,
games ,
voting ,
}
running_games ,
}
games ,
}
}
}
}
#[ tonic::async_trait ]
#[ tonic::async_trait ]
impl Lobby for LobbyService {
impl Lobby for LobbyService {
async fn vote ( & self , request : Request < SingleVote > ) -> Result < Response < ( ) > , Status > {
async fn vote ( & self , request : Request < SingleVote > ) -> Result < Response < ( ) > , Status > {
let uuid = client_id ::get ( request . metadata ( ) ) . map_err ( | x | match x {
let uuid = client_id ::get ( request . metadata ( ) ) . map_err ( | x | match x {
client_id ::Error ::NotSet = > Status ::failed_precondition ( "client_id must be set" ) ,
client_id ::Error ::NotSet = > Status ::failed_precondition ( "client_id must be set" ) ,
client_id ::Error ::MalformedUuid = > Status ::failed_precondition ( "malformed client_id" ) ,
client_id ::Error ::MalformedUuid = > Status ::failed_precondition ( "malformed client_id" ) ,
} ) ? ;
} ) ? ;
let req = request . into_inner ( ) ;
let req = request . into_inner ( ) ;
self . voting . vote ( uuid , req . game ) . await ;
self . voting . vote ( uuid , req . game ) . await ;
Ok ( Response ::new ( ( ) ) )
Ok ( Response ::new ( ( ) ) )
}
}
async fn ready ( & self , request : Request < ( ) > ) -> Result < Response < ( ) > , Status > {
async fn ready ( & self , request : Request < ( ) > ) -> Result < Response < ( ) > , Status > {
let uuid = client_id ::get ( request . metadata ( ) ) . map_err ( | x | match x {
let uuid = client_id ::get ( request . metadata ( ) ) . map_err ( | x | match x {
client_id ::Error ::NotSet = > Status ::failed_precondition ( "client_id must be set" ) ,
client_id ::Error ::NotSet = > Status ::failed_precondition ( "client_id must be set" ) ,
client_id ::Error ::MalformedUuid = > Status ::failed_precondition ( "malformed client_id" ) ,
client_id ::Error ::MalformedUuid = > Status ::failed_precondition ( "malformed client_id" ) ,
} ) ? ;
} ) ? ;
if let Some ( Some ( winner ) ) = self . voting . ready ( uuid ) . await {
if let Some ( Some ( winner ) ) = self . voting . ready ( uuid ) . await {
let mut conn = self . conn . write ( ) . await ;
let mut conn = self . conn . write ( ) . await ;
let lobby = conn . get_lobby_for_user ( uuid ) . await . unwrap ( ) ;
let lobby = conn . get_lobby_for_user ( uuid ) . await . unwrap ( ) ;
log ::info ! ( "[{}] Starting a game ({})" , lobby , winner ) ;
log ::info ! ( "[{}] Starting a game ({})" , lobby , winner ) ;
let user_count = conn . get_uuids_in_lobby_where_user_is ( uuid ) . await ;
let user_count = conn . get_uuids_in_lobby_where_user_is ( uuid ) . await ;
let game = self . games [ winner as usize ] . run ( & user_count ) ;
let game = self . games [ winner as usize ] . run ( & user_count ) ;
self . running_games
self . running_games
. write ( )
. write ( )
. await
. await
. insert ( lobby , RwLock ::new ( ( winner , game , Modifiable ::new ( None ) ) ) ) ;
. insert ( lobby , RwLock ::new ( ( winner , game , Modifiable ::new ( None ) ) ) ) ;
}
log ::info ! ( "[{}] Started a game ({})" , lobby , winner ) ;
Ok ( Response ::new ( ( ) ) )
}
}
log ::info ! ( "Player {} is ready" , uuid ) ;
async fn poll_status (
Ok ( Response ::new ( ( ) ) )
& self ,
}
request : Request < LastStatusTimestamp > ,
) -> Result < Response < HasNewStatus > , Status > {
async fn poll_status (
// let uuid = client_id::get(request.metadata()).map_err(|x| match x {
& self ,
// client_id::Error::NotSet => Status::failed_precondition("client_id must be set"),
request : Request < LastStatusTimestamp > ,
// client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"),
) -> Result < Response < HasNewStatus > , Status > {
// })?;
// let uuid = client_id::get(request.metadata()).map_err(|x| match x {
// let mut conn = self.conn.acquire().await;
// client_id::Error::NotSet => Status::failed_precondition("client_id must be set"),
// client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"),
let inner = request . into_inner ( ) ;
// })?;
let time = inner
// let mut conn = self.conn.acquire().await;
. time
. ok_or ( Status ::failed_precondition ( "timestamp musn't be null" ) ) ?
let inner = request . into_inner ( ) ;
. try_into ( )
let time = inner
. unwrap ( ) ;
. time
Ok ( Response ::new ( HasNewStatus {
. ok_or ( Status ::failed_precondition ( "timestamp musn't be null" ) ) ?
value : self . voting . has_new_status ( & inner . lobby , time ) . await ,
. try_into ( )
} ) )
. unwrap ( ) ;
}
Ok ( Response ::new ( HasNewStatus {
value : self . voting . has_new_status ( & inner . lobby , time ) . await ,
async fn get_status ( & self , request : Request < ( ) > ) -> Result < Response < LobbyStatus > , Status > {
} ) )
let uuid = client_id ::get ( request . metadata ( ) ) . map_err ( | x | match x {
}
client_id ::Error ::NotSet = > Status ::failed_precondition ( "client_id must be set" ) ,
client_id ::Error ::MalformedUuid = > Status ::failed_precondition ( "malformed client_id" ) ,
async fn get_status ( & self , request : Request < ( ) > ) -> Result < Response < LobbyStatus > , Status > {
} ) ? ;
let uuid = client_id ::get ( request . metadata ( ) ) . map_err ( | x | match x {
let mut conn = self . conn . write ( ) . await ;
client_id ::Error ::NotSet = > Status ::failed_precondition ( "client_id must be set" ) ,
if let Some ( l ) = conn . get_lobby_for_user ( uuid ) . await {
client_id ::Error ::MalformedUuid = > Status ::failed_precondition ( "malformed client_id" ) ,
let ( votes , is_starting ) = self . voting . status ( & l ) . await . unwrap_or_default ( ) ;
} ) ? ;
let names = conn . get_users_in_lobby_where_user_is ( uuid ) . await ;
let mut conn = self . conn . write ( ) . await ;
// log::info!("Users: {:?}", names);
if let Some ( l ) = conn . get_lobby_for_user ( uuid ) . await {
Ok ( Response ::new ( LobbyStatus {
let ( votes , is_starting ) = self . voting . status ( & l ) . await . unwrap_or_default ( ) ;
names : names . into_iter ( ) . map ( | x | Name { name : x } ) . collect ( ) ,
let names = conn . get_users_in_lobby_where_user_is ( uuid ) . await ;
votes : votes
// log::info!("Users: {:?}", names);
. into_iter ( )
Ok ( Response ::new ( LobbyStatus {
. map ( | ( player , game , ready ) | Vote {
names : names . into_iter ( ) . map ( | x | Name { name : x } ) . collect ( ) ,
player ,
votes : votes
game ,
. into_iter ( )
ready ,
. map ( | ( player , game , ready ) | Vote {
} )
player ,
. collect ( ) ,
game ,
is_starting ,
ready ,
} ) )
} )
} else {
. collect ( ) ,
Err ( Status ::failed_precondition ( "User isn't in a lobby" ) )
is_starting ,
}
} ) )
}
} else {
Err ( Status ::failed_precondition ( "User isn't in a lobby" ) )
async fn leave (
}
& self ,
}
request : tonic ::Request < ( ) > ,
) -> Result < tonic ::Response < ( ) > , tonic ::Status > {
async fn leave (
let uuid = client_id ::get ( request . metadata ( ) ) . map_err ( | x | match x {
& self ,
client_id ::Error ::NotSet = > Status ::failed_precondition ( "client_id must be set" ) ,
request : tonic ::Request < ( ) > ,
client_id ::Error ::MalformedUuid = > Status ::failed_precondition ( "malformed client_id" ) ,
) -> Result < tonic ::Response < ( ) > , tonic ::Status > {
} ) ? ;
let uuid = client_id ::get ( request . metadata ( ) ) . map_err ( | x | match x {
let mut conn = self . conn . write ( ) . await ;
client_id ::Error ::NotSet = > Status ::failed_precondition ( "client_id must be set" ) ,
if let Some ( l ) = conn . get_lobby_for_user ( uuid ) . await {
client_id ::Error ::MalformedUuid = > Status ::failed_precondition ( "malformed client_id" ) ,
// log::info!("Updating lobby status");
} ) ? ;
self . voting . updated_users ( & l ) . await ;
let mut conn = self . conn . write ( ) . await ;
// log::info!("Updated lobby status");
if let Some ( l ) = conn . get_lobby_for_user ( uuid ) . await {
}
// log::info!("Updating lobby status");
conn . leave_lobby ( uuid ) . await ;
self . voting . updated_users ( & l ) . await ;
Ok ( Response ::new ( ( ) ) )
// log::info!("Updated lobby status");
}
}
conn . leave_lobby ( uuid ) . await ;
type usersStream = mpsc ::UnboundedReceiver < Result < Name , Status > > ;
Ok ( Response ::new ( ( ) ) )
}
async fn users ( & self , request : Request < ( ) > ) -> Result < Response < Self ::usersStream > , Status > {
let uuid = client_id ::get ( request . metadata ( ) ) . map_err ( | x | match x {
type usersStream = mpsc ::UnboundedReceiver < Result < Name , Status > > ;
client_id ::Error ::NotSet = > Status ::failed_precondition ( "client_id must be set" ) ,
client_id ::Error ::MalformedUuid = > Status ::failed_precondition ( "malformed client_id" ) ,
async fn users ( & self , request : Request < ( ) > ) -> Result < Response < Self ::usersStream > , Status > {
} ) ? ;
let uuid = client_id ::get ( request . metadata ( ) ) . map_err ( | x | match x {
let ( sender , receiver ) = mpsc ::unbounded_channel ( ) ;
client_id ::Error ::NotSet = > Status ::failed_precondition ( "client_id must be set" ) ,
let mut conn = self . conn . write ( ) . await ;
client_id ::Error ::MalformedUuid = > Status ::failed_precondition ( "malformed client_id" ) ,
for name in conn . get_users_in_lobby_where_user_is ( uuid ) . await {
} ) ? ;
sender . send ( Ok ( Name { name } ) ) . unwrap ( ) ;
let ( sender , receiver ) = mpsc ::unbounded_channel ( ) ;
}
let mut conn = self . conn . write ( ) . await ;
Ok ( Response ::new ( receiver ) )
for name in conn . get_users_in_lobby_where_user_is ( uuid ) . await {
}
sender . send ( Ok ( Name { name } ) ) . unwrap ( ) ;
}
Ok ( Response ::new ( receiver ) )
}
}
}