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

178 lines
4.2 KiB
Rust
Raw Normal View History

2022-08-29 17:17:31 +02:00
use std::collections::HashMap;
2022-08-29 20:08:16 +02:00
use futures::TryStreamExt;
use rocket::serde::json::json;
use rocket_db_pools::mongodb::{bson::to_bson, options::InsertOneOptions};
use serde_json::Value;
2022-08-29 17:17:31 +02:00
use super::{prelude::*, util::PartyError};
2022-08-29 20:08:16 +02:00
api_routes!(
create_event,
stop_event,
get_event,
update_event,
get_all_events,
event_outcome,
);
2022-08-29 17:17:31 +02:00
2022-08-29 20:08:16 +02:00
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
2022-08-29 17:17:31 +02:00
#[serde(crate = "rocket::serde")]
pub struct EventOutcome {
2022-08-29 20:08:16 +02:00
points: HashMap<String, i64>,
2022-08-29 17:17:31 +02:00
}
2022-08-29 20:08:16 +02:00
/// # Event
///
/// An event in which participants can win or lose points
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
2022-08-29 17:17:31 +02:00
#[serde(crate = "rocket::serde")]
2022-08-29 20:08:16 +02:00
pub struct Event {
/// Unique identifier of the event. This will be randomly generated and cannot be modified.
#[serde(default = "uuid")]
id: String,
/// Has this event concluded?
concluded: bool,
/// Event type
event_type: EventType,
}
2022-08-29 17:17:31 +02:00
2022-08-29 20:08:16 +02:00
impl Event {
pub fn outcome(&self) -> EventOutcome {
match self.event_type {
_ => EventOutcome::default(),
}
}
2022-08-29 17:17:31 +02:00
2022-08-29 20:08:16 +02:00
pub fn conclude(&self) {}
2022-08-29 17:17:31 +02:00
}
2022-08-29 20:08:16 +02:00
fn uuid() -> String {
uuid::Uuid::new_v4().to_string()
2022-08-29 17:17:31 +02:00
}
2022-08-29 20:08:16 +02:00
/// # EventType
///
/// Enumeration of all different types of events
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
#[serde(crate = "rocket::serde")]
pub enum EventType {
FreeForAllGame {},
TeamGame {},
Test {},
2022-08-29 17:17:31 +02:00
}
2022-08-29 20:08:16 +02:00
/// # Create event
///
/// If an `id` is supplied, it will be replaced by a randomly generated
/// one.
///
/// Returns the created event. #[openapi(tag = "Event")]
#[openapi(tag = "Event")]
#[post("/", data = "<event>")]
pub async fn create_event(
_api_key: ApiKey,
db: Connection<Db>,
mut event: Json<Event>,
) -> Result<Json<Event>, PartyError> {
event.id = uuid();
event.concluded = false;
db.events().insert_one(&*event, None).await?;
Ok(event)
2022-08-29 17:17:31 +02:00
}
2022-08-29 20:08:16 +02:00
/// # Update event
///
/// Update the supplied values in the event with the given id. The `id` of an event cannot be
/// changed and `concluded` will always be false.
#[openapi(tag = "Event")]
#[post("/<id>", data = "<event>")]
pub async fn update_event(
_api_key: ApiKey,
db: Connection<Db>,
id: String,
mut event: Json<Value>, // Use serde_json::Value to allow a partial struct
) -> Result<Status, PartyError> {
if let Some(i) = event.get_mut("id") {
*i = json! { &id };
2022-08-29 17:17:31 +02:00
}
2022-08-29 20:08:16 +02:00
if let Some(i) = event.get_mut("concluded") {
*i = json! { false };
2022-08-29 17:17:31 +02:00
}
2022-08-29 20:08:16 +02:00
db.users()
.update_one(doc! { "id": &id }, doc! { "$set": to_bson(&*event)? }, None)
.await?;
2022-08-29 17:17:31 +02:00
2022-08-29 20:08:16 +02:00
Ok(Status::Ok)
}
2022-08-29 17:17:31 +02:00
2022-08-29 20:08:16 +02:00
/// # Get event
///
/// Returns the event with the given id
#[openapi(tag = "Event")]
#[get("/<id>")]
pub async fn get_event(
_api_key: ApiKey,
db: Connection<Db>,
id: String,
) -> Result<Json<Event>, PartyError> {
Ok(Json(
db.events()
.find_one(doc! { "id": &id }, None)
.await?
.ok_or(PartyError::EventNotFound(id))?,
))
}
2022-08-29 17:17:31 +02:00
2022-08-29 20:08:16 +02:00
/// # Get events
///
/// Returns the event with the given id
#[openapi(tag = "Event")]
#[get("/")]
pub async fn get_all_events(
_api_key: ApiKey,
db: Connection<Db>,
) -> Result<Json<Vec<Event>>, PartyError> {
Ok(Json(
db.events().find(doc! {}, None).await?.try_collect().await?,
))
}
2022-08-29 17:17:31 +02:00
2022-08-29 20:08:16 +02:00
/// # Get outcome
///
/// Returns the outcome of a concluded event.
#[openapi(tag = "Event")]
#[get("/<id>/outcome")]
pub async fn event_outcome(
_api_key: ApiKey,
db: Connection<Db>,
id: String,
) -> Result<Json<EventOutcome>, PartyError> {
let event = db
.events()
.find_one(doc! { "id": &id }, None)
.await?
.ok_or(PartyError::EventNotFound(id.clone()))?;
Ok(Json(event.outcome()))
2022-08-29 17:17:31 +02:00
}
2022-08-29 20:08:16 +02:00
/// # Stop event
2022-08-29 17:17:31 +02:00
#[openapi(tag = "Event")]
#[post("/<id>/stop")]
2022-08-29 20:08:16 +02:00
pub async fn stop_event(
_api_key: ApiKey,
db: Connection<Db>,
id: String,
) -> Result<Json<EventOutcome>, PartyError> {
let event = db
.events()
.find_one(doc! { "id": &id }, None)
.await?
.ok_or(PartyError::EventNotFound(id.clone()))?;
event.conclude();
db.users()
.update_one(doc! { "id": &id }, doc! { "concluded": true }, None)
.await?;
Ok(Json(event.outcome()))
2022-08-29 17:17:31 +02:00
}