@ -1,10 +1,11 @@
// use sqlx::{pool::PoolConnection, prelude::*, query, query_as, SqliteConnection, SqlitePool};
// use sqlx::{pool::PoolConnection, prelude::*, query, query_as, SqliteConnection, SqlitePool};
// use tokio::stream::StreamExt;
// use tokio::stream::StreamExt;
use tokio ::task ::spawn ;
use rusqlite ::{ params , Connection , Error as SqliteError } ;
use server_client ::encapsulate ;
use fallible_iterator ::FallibleIterator ;
use fallible_iterator ::FallibleIterator ;
use rusqlite ::{ params , Connection , Error as SqliteError , ErrorCode } ;
use server_client ::encapsulate ;
use tokio ::task ::spawn ;
use tonic ::Status ;
use uuid ::Uuid ;
use uuid ::Uuid ;
use std ::convert ::TryInto ;
use std ::convert ::TryInto ;
@ -22,6 +23,8 @@ pub async fn start() -> DbClient {
client
client
}
}
type Result < T > = std ::result ::Result < T , Status > ;
pub struct Db {
pub struct Db {
conn : Connection ,
conn : Connection ,
}
}
@ -33,37 +36,53 @@ impl Db {
}
}
// type LobbyId = (i32,);
// type LobbyId = (i32,);
// FIXME: return Results intead of crashing
#[ encapsulate(pub async ordered) ]
#[ encapsulate(pub async ordered) ]
impl Db {
impl Db {
pub fn load_setup ( & mut self ) {
pub fn load_setup ( & mut self ) {
self . conn . execute_batch ( include_str ! ( "setup.sql" ) ) . unwrap ( )
self . conn . execute_batch ( include_str ! ( "setup.sql" ) ) . unwrap ( )
}
}
pub fn add_user ( & mut self , name : String ) -> Uuid {
pub fn add_user ( & mut self , name : String ) -> Result < Uuid > {
loop {
let uuid = Uuid ::new_v4 ( ) ;
let uuid = Uuid ::new_v4 ( ) ;
// println!("{:?}", uuid.as_bytes().to_vec());
// println!("{:?}", uuid.as_bytes().to_vec());
self . conn
let res = self . conn . execute (
. execute (
"INSERT INTO Users(uuid, name) VALUES(?, ?)" ,
"INSERT INTO Users(uuid, name) VALUES(?, ?)" ,
params ! [ uuid . as_bytes ( ) . to_vec ( ) , name . to_string ( ) ] ,
params ! [ uuid . as_bytes ( ) . to_vec ( ) , name . to_string ( ) ] ,
)
) ; // Server crashes if uuids collide
. unwrap ( ) ; // Server crashes if uuids collide
uuid
if let Err ( e ) = res {
match e {
SqliteError ::SqliteFailure (
rusqlite ::ffi ::Error {
code : ErrorCode ::ConstraintViolation ,
extended_code : _ ,
} ,
_ ,
) = > {
log ::error ! ( "add_user db error (constraint violation): {}" , e ) ;
return Err ( Status ::internal ( e . to_string ( ) ) ) ;
}
e = > {
log ::error ! ( "add_user db error: {}" , e ) ;
return Err ( Status ::internal ( e . to_string ( ) ) ) ;
}
}
}
}
// pub async fn users(&mut self) -> Vec<types::User> {
return Ok ( uuid ) ;
// query_as::<_, types::User>("SELECT UUID, Name FROM Users")
}
// .fetch_all(&mut self.conn)
}
// .await
// FIXME: return Results intead of crashing
// .unwrap()
// }
pub fn get_users_in_lobby_where_user_is ( & mut self , uuid : Uuid ) -> Vec < String > {
pub fn get_users_in_lobby_where_user_is ( & mut self , uuid : Uuid ) -> Vec < String > {
let mut prepared = self . conn . prepare_cached ( "SELECT Name FROM Users WHERE UUID in (SELECT UserId FROM UsersInLobbies WHERE LobbyId = (SELECT LobbyId FROM UsersInLobbies WHERE UserId = ?))" ) . unwrap ( ) ;
let mut prepared = self . conn . prepare_cached ( "SELECT Name FROM Users WHERE UUID in (SELECT UserId FROM UsersInLobbies WHERE LobbyId = (SELECT LobbyId FROM UsersInLobbies WHERE UserId = ?))" ) . unwrap ( ) ;
prepared . query ( params ! [ uuid . as_bytes ( ) . to_vec ( ) ] ) . and_then ( | r | r . map ( | r | r . get ( 0 ) ) . collect ( ) ) . unwrap ( )
prepared
. query ( params ! [ uuid . as_bytes ( ) . to_vec ( ) ] )
. and_then ( | r | r . map ( | r | r . get ( 0 ) ) . collect ( ) )
. unwrap ( )
}
}
// FIXME: return Results intead of crashing
pub fn create_lobby ( & mut self , public : bool ) -> u32 {
pub fn create_lobby ( & mut self , public : bool ) -> u32 {
let id = rand ::random ( ) ;
let id = rand ::random ( ) ;
@ -76,7 +95,7 @@ impl Db {
. unwrap ( ) ; // Server crashes if ids collide
. unwrap ( ) ; // Server crashes if ids collide
id
id
}
}
// FIXME: return Results intead of crashing
pub fn join_lobby ( & mut self , user : Uuid , lobby : u32 ) {
pub fn join_lobby ( & mut self , user : Uuid , lobby : u32 ) {
self . conn
self . conn
. execute (
. execute (
@ -86,7 +105,7 @@ impl Db {
. unwrap ( ) ; // Server crashes if ids collide
. unwrap ( ) ; // Server crashes if ids collide
log ::info ! ( "{} joined the lobby {}" , user , lobby ) ;
log ::info ! ( "{} joined the lobby {}" , user , lobby ) ;
}
}
// FIXME: return Results intead of crashing
pub fn leave_lobby ( & mut self , user : Uuid ) {
pub fn leave_lobby ( & mut self , user : Uuid ) {
log ::info ! ( "{} leaving the lobby" , user ) ;
log ::info ! ( "{} leaving the lobby" , user ) ;
self . delete_vote ( user ) ;
self . delete_vote ( user ) ;
@ -103,18 +122,20 @@ impl Db {
log ::info ! ( "Deleted {} lobbies ({})" , lines , id as u32 )
log ::info ! ( "Deleted {} lobbies ({})" , lines , id as u32 )
}
}
}
}
// FIXME: return Results intead of crashing
pub fn disconnect ( & mut self , user : Uuid ) {
pub fn disconnect ( & mut self , user : Uuid ) {
// self.leave_lobby(user).await;
// self.leave_lobby(user).await;
log ::info ! ( "{} disconnecting" , user ) ;
log ::info ! ( "{} disconnecting" , user ) ;
self . conn . execute (
self . conn
. execute (
"DELETE FROM Users WHERE UUID = ?" ,
"DELETE FROM Users WHERE UUID = ?" ,
params ! [ user . as_bytes ( ) . to_vec ( ) ] ,
params ! [ user . as_bytes ( ) . to_vec ( ) ] ,
) . unwrap ( ) ;
)
. unwrap ( ) ;
// log::error!("Disconnect DB result{:?}", r);
// log::error!("Disconnect DB result{:?}", r);
}
}
// FIXME: return Results intead of crashing
pub fn get_lobby_for_user ( & mut self , user : Uuid ) -> Option < u32 > {
pub fn get_lobby_for_user ( & mut self , user : Uuid ) -> Option < u32 > {
match self . conn . query_row (
match self . conn . query_row (
"SELECT LobbyID from UsersInLobbies WHERE UserID = ?" ,
"SELECT LobbyID from UsersInLobbies WHERE UserID = ?" ,
@ -129,42 +150,61 @@ impl Db {
}
}
. unwrap ( )
. unwrap ( )
}
}
// FIXME: return Results intead of crashing
pub fn get_public_lobbies ( & mut self ) -> Vec < u32 > {
pub fn get_public_lobbies ( & mut self ) -> Vec < u32 > {
let mut prepared = self
let mut prepared = self
. conn
. conn
. prepare ( "SELECT ID FROM Lobbies WHERE Public = TRUE" ) . unwrap ( ) ;
. prepare ( "SELECT ID FROM Lobbies WHERE Public = TRUE" )
prepared . query ( params ! [ ] ) . and_then ( | r | r . map ( | r | r . get ::< _ , i32 > ( 0 ) . map ( | x | x as u32 ) ) . collect ( ) ) . unwrap ( )
. unwrap ( ) ;
prepared
. query ( params ! [ ] )
. and_then ( | r | r . map ( | r | r . get ::< _ , i32 > ( 0 ) . map ( | x | x as u32 ) ) . collect ( ) )
. unwrap ( )
}
}
// FIXME: return Results intead of crashing
fn delete_vote ( & mut self , user : Uuid ) {
fn delete_vote ( & mut self , user : Uuid ) {
self . conn . execute (
self . conn
. execute (
"DELETE FROM Votes WHERE UserId = ?" ,
"DELETE FROM Votes WHERE UserId = ?" ,
params ! [ user . as_bytes ( ) . to_vec ( ) ] ,
params ! [ user . as_bytes ( ) . to_vec ( ) ] ,
) . unwrap ( ) ;
)
. unwrap ( ) ;
}
}
// FIXME: return Results intead of crashing
pub fn vote ( & mut self , user : Uuid , game : u32 ) {
pub fn vote ( & mut self , user : Uuid , game : u32 ) {
self . delete_vote ( user ) ;
self . delete_vote ( user ) ;
self . conn . execute (
self . conn
. execute (
"INSERT INTO Votes(UserID, GameID) VALUES(?, ?)" ,
"INSERT INTO Votes(UserID, GameID) VALUES(?, ?)" ,
params ! [ user . as_bytes ( ) . to_vec ( ) , game as i32 ] ,
params ! [ user . as_bytes ( ) . to_vec ( ) , game as i32 ] ,
) . unwrap ( ) ;
)
. unwrap ( ) ;
}
}
// FIXME: return Results intead of crashing
pub fn vote_ready ( & mut self , user : Uuid ) {
pub fn vote_ready ( & mut self , user : Uuid ) {
self . delete_vote ( user ) ;
self . delete_vote ( user ) ;
self . conn . execute (
self . conn
. execute (
"UPDATE Votes SET Ready = TRUE WHERE UserID = ?" ,
"UPDATE Votes SET Ready = TRUE WHERE UserID = ?" ,
params ! [ user . as_bytes ( ) . to_vec ( ) ] ,
params ! [ user . as_bytes ( ) . to_vec ( ) ] ,
) . unwrap ( ) ;
)
. unwrap ( ) ;
}
}
// FIXME: return Results intead of crashing
pub fn get_votes ( & mut self , lobby : u32 ) -> Vec < ( String , u32 , bool ) > {
pub fn get_votes ( & mut self , lobby : u32 ) -> Vec < ( String , u32 , bool ) > {
let mut prepared = self . conn . prepare_cached ( "SELECT Users.Name, Votes.GameID, Votes.Ready FROM Votes JOIN Users ON Users.UUID = Votes.UserID WHERE Votes.UserID IN (SELECT UserID FROM UsersInLobbies WHERE LobbyID = ?)" ) . unwrap ( ) ;
let mut prepared = self . conn . prepare_cached ( "SELECT Users.Name, Votes.GameID, Votes.Ready FROM Votes JOIN Users ON Users.UUID = Votes.UserID WHERE Votes.UserID IN (SELECT UserID FROM UsersInLobbies WHERE LobbyID = ?)" ) . unwrap ( ) ;
prepared . query ( params ! [ lobby as i32 ] ) . and_then ( | r | r . map ( | r | r . try_into ( ) . map ( | ( s , n , b ) : ( String , i32 , bool ) | ( s , n as u32 , b ) ) ) . collect ( ) ) . unwrap ( )
prepared
. query ( params ! [ lobby as i32 ] )
. and_then ( | r | {
r . map ( | r | {
r . try_into ( )
. map ( | ( s , n , b ) : ( String , i32 , bool ) | ( s , n as u32 , b ) )
} )
. collect ( )
} )
. unwrap ( )
}
}
// FIXME: return Results intead of crashing
pub fn is_poll_finished ( & mut self , lobby : u32 ) -> bool {
pub fn is_poll_finished ( & mut self , lobby : u32 ) -> bool {
self . conn . query_row (
self . conn . query_row (
"SELECT (SELECT COUNT(*) FROM UsersInLobbies where LobbyID = ?) = (SELECT COUNT(*) FROM Votes WHERE UserID IN (SELECT UserID FROM UsersInLobbies WHERE LobbyID = ?) AND Ready = TRUE)" ,
"SELECT (SELECT COUNT(*) FROM UsersInLobbies where LobbyID = ?) = (SELECT COUNT(*) FROM Votes WHERE UserID IN (SELECT UserID FROM UsersInLobbies WHERE LobbyID = ?) AND Ready = TRUE)" ,
@ -172,7 +212,7 @@ impl Db {
| r | r . get ( 0 )
| r | r . get ( 0 )
) . unwrap ( )
) . unwrap ( )
}
}
// FIXME: return Results intead of crashing
pub fn delete_votes ( & mut self , lobby : u32 ) {
pub fn delete_votes ( & mut self , lobby : u32 ) {
self . conn
self . conn
. execute ( "DELETE FROM Votes WHERE UserId IN (SELECT UserID FROM UsersInLobbies WHERE LobbyID = ?)" , params ! [ lobby as i32 ] ) . unwrap ( ) ;
. execute ( "DELETE FROM Votes WHERE UserId IN (SELECT UserID FROM UsersInLobbies WHERE LobbyID = ?)" , params ! [ lobby as i32 ] ) . unwrap ( ) ;