lan-party-backend/src/api/event.rs

182 lines
5.1 KiB
Rust

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<i64, i64>,
}
#[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<Db>, id: i64) -> Result<Self, PartyError> {
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<Db>) -> 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<Db>,
name: String,
) -> Result<EventRecord, PartyError> {
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<Db>, record: EventRecord) -> Result<Self, PartyError> {
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("/<id>/stop")]
pub fn stop_event(id: i64) -> Result<Json<EventOutcome>, PartyError> {
todo!()
}