use std::collections::HashMap; use sqlx::FromRow; use super::{prelude::*, util::PartyError}; api_routes!(); #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] #[serde(crate = "rocket::serde")] pub struct EventOutcome { points: HashMap, } #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, FromRow)] #[serde(crate = "rocket::serde")] pub struct FreeForAllGame {} #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, FromRow)] #[serde(crate = "rocket::serde")] pub struct TeamGame {} #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, FromRow)] #[serde(crate = "rocket::serde")] pub struct Test {} // # Event // // An event in which participants can win or lose points #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] #[serde(crate = "rocket::serde")] pub enum Event { FreeForAllGame(FreeForAllGame), TeamGame(TeamGame), Test(Test), } pub struct EventRecord { id: i64, name: String, event_type: String, event_id: i64, } macro_rules! dispatch { ($event:ident) => { dispatch!($event, free_for_all_game => FreeForAllGame, team_game => TeamGame, test => Test, ) }; ($event:ident, $($event_type:ident => $event_struct:ident),* $(,)?) => { match $event.event_type.as_str() { $(stringify!($event_type) => dispatch_run!($event_type, $event_struct),)* _ => return Err(PartyError::Unknown("invalid event type".into())), } }; } macro_rules! reverse_dispatch { ($event:ident) => { reverse_dispatch!($event, FreeForAllGame => free_for_all_game, TeamGame => team_game, Test => test, ) }; ($event:ident, $($event_struct:ident => $event_type:ident),* $(,)?) => { match $event { $(Event::$event_struct(e) => reverse_dispatch_run!($event_type, $event_struct, e),)* } }; } impl EventRecord { pub async fn get(db: &mut Connection, id: i64) -> Result { Ok(sqlx::query_as!( EventRecord, "SELECT id, name, event_type, event_id FROM events WHERE id = ?", id ) .fetch_one(&mut **db) .await?) } pub async fn remove(&self, db: &mut Connection) -> Result<(), PartyError> { macro_rules! dispatch_run { ($event_type:ident, $event_struct:ident) => {{ sqlx::query(&format!( "DELETE FROM events_{} WHERE id = {}", stringify!($event_type), self.event_id )) .fetch_one(&mut **db) .await?; }}; } dispatch!(self); sqlx::query!("DELETE FROM events WHERE id = ?", self.id) .execute(&mut **db) .await?; Ok(()) } } impl Event { pub async fn register( &self, db: &mut Connection, name: String, ) -> Result { let event_id = match self { Self::FreeForAllGame(e) => { unimplemented!() /* sqlx::query!("INSERT INTO events_free_for_all_game () VALUES ()") .execute(&mut **db) .await? .last_insert_rowid() */ } Self::TeamGame(e) => { unimplemented!() /* sqlx::query!("INSERT INTO events_team_game () VALUES ()") .execute(&mut **db) .await? .last_insert_rowid() */ } Self::Test(e) => sqlx::query!("INSERT INTO events_test () VALUES ()") .execute(&mut **db) .await? .last_insert_rowid(), }; macro_rules! reverse_dispatch_run { ($event_type:ident, $event_struct:ident, $inner:ident) => { sqlx::query!( "INSERT INTO events (name, event_type, event_id) VALUES (?, ?, ?)", stringify!($event_type), name, event_id ) .execute(&mut **db) .await? }; } let id = reverse_dispatch!(self).last_insert_rowid(); Ok(EventRecord::get(db, id).await?) } pub async fn get(db: &mut Connection, record: EventRecord) -> Result { macro_rules! dispatch_run { ($event_type:ident, $event_struct:ident) => { Event::$event_struct( sqlx::query_as::<_, $event_struct>(&format!( "SELECT id, name, event_type, event_id FROM events_{} WHERE id = {}", stringify!($event_type), record.event_id )) .fetch_one(&mut **db) .await?, ) }; } Ok(dispatch!(record)) } } #[openapi(tag = "Event")] #[post("//stop")] pub fn stop_event(id: i64) -> Result, PartyError> { todo!() }