use rocket::serde::{Deserialize, Serialize}; use sqlx::{FromRow, SqlitePool}; use crate::tera::board::boathouse::FormBoathouseToAdd; use super::boat::Boat; #[derive(Debug, Serialize, Deserialize)] pub struct BoathousePlace { boat: Boat, boathouse_id: i64, } #[derive(Debug, Serialize, Deserialize)] pub struct BoathouseRack { boats: [Option; 12], } impl BoathouseRack { fn new() -> Self { let boats = [ None, None, None, None, None, None, None, None, None, None, None, None, ]; Self { boats } } async fn add(&mut self, db: &SqlitePool, boathouse: Boathouse) { self.boats[boathouse.level as usize] = Some(BoathousePlace { boat: Boat::find_by_id(db, boathouse.boat_id as i32) .await .unwrap(), boathouse_id: boathouse.id, }); } } #[derive(Debug, Serialize, Deserialize)] pub struct BoathouseSide { mountain: BoathouseRack, water: BoathouseRack, } impl BoathouseSide { fn new() -> Self { Self { mountain: BoathouseRack::new(), water: BoathouseRack::new(), } } async fn add(&mut self, db: &SqlitePool, boathouse: Boathouse) { match boathouse.side.as_str() { "mountain" => self.mountain.add(db, boathouse).await, "water" => self.water.add(db, boathouse).await, _ => panic!("db constraint failed"), } } } #[derive(Debug, Serialize, Deserialize)] pub struct BoathouseAisles { mountain: BoathouseSide, middle: BoathouseSide, water: BoathouseSide, } impl BoathouseAisles { fn new() -> Self { Self { mountain: BoathouseSide::new(), middle: BoathouseSide::new(), water: BoathouseSide::new(), } } async fn add(&mut self, db: &SqlitePool, boathouse: Boathouse) { match boathouse.aisle.as_str() { "water" => self.water.add(db, boathouse).await, "middle" => self.middle.add(db, boathouse).await, "mountain" => self.mountain.add(db, boathouse).await, _ => panic!("db constraint failed"), }; } pub async fn from(db: &SqlitePool, boathouses: Vec) -> Self { let mut ret = BoathouseAisles::new(); for boathouse in boathouses { ret.add(db, boathouse).await; } ret } } #[derive(FromRow, Debug, Serialize, Deserialize)] pub struct Boathouse { pub id: i64, pub boat_id: i64, pub aisle: String, pub side: String, pub level: i64, } impl Boathouse { pub async fn get(db: &SqlitePool) -> BoathouseAisles { let boathouses = sqlx::query_as!( Boathouse, "SELECT id, boat_id, aisle, side, level FROM boathouse" ) .fetch_all(db) .await .unwrap(); //TODO: fixme BoathouseAisles::from(db, boathouses).await } pub async fn create(db: &SqlitePool, data: FormBoathouseToAdd) -> Result<(), String> { sqlx::query!( "INSERT INTO boathouse(boat_id, aisle, side, level) VALUES (?,?,?,?)", data.boat_id, data.aisle, data.side, data.level ) .execute(db) .await .map_err(|e| e.to_string())?; Ok(()) } pub async fn find_by_id(db: &SqlitePool, id: i32) -> Option { sqlx::query_as!(Self, "SELECT * FROM boathouse WHERE id like ?", id) .fetch_one(db) .await .ok() } pub async fn delete(&self, db: &SqlitePool) { sqlx::query!("DELETE FROM boathouse WHERE id=?", self.id) .execute(db) .await .unwrap(); //Okay, because we can only create a Boat of a valid id } }