use super::load_character; use crate::db::{Dao, TenebrousDbConn}; use crate::errors::Error; use crate::models::characters::Character; use crate::models::proto::cofd::api::DefaultCharacterIdentifier; use crate::models::proto::cofd::cofd_sheet::Skill; use crate::models::proto::cofd::*; use crate::models::proto::{cofd::api::*, cofd::*, Proto}; use crate::models::users::User; use std::collections::btree_map::{Entry, OccupiedEntry}; fn find_skill_entry<'a>( sheet: &'a mut CofdSheet, skill_name: &'a str, ) -> Option> { let all_skills = vec![ &mut sheet.mental_skills, &mut sheet.physical_skills, &mut sheet.social_skills, ]; // Search all skill lists for this value using "workaround" to // break value from for loops. let skill: Option> = 'l: loop { for skill_map in all_skills { if let Entry::Occupied(entry) = skill_map.entry(skill_name.to_owned()) { break 'l Some(entry); } } break None; }; skill } fn find_skill<'a>(sheet: &'a mut CofdSheet, skill_name: &'a str) -> Option<&'a mut Skill> { find_skill_entry(sheet, skill_name).map(|entry| entry.into_mut()) } #[post("/rpc/cofd/update_basic_info", data = "")] pub(super) async fn update_basic_info<'a>( req: Proto, conn: TenebrousDbConn<'_>, user: Option<&User>, ) -> Result, Error> { let mut character = load_character(&conn, user, &req.character.owner(), req.character.id()).await?; let mut sheet: CofdSheet = character.try_deserialize()?; println!("name will now be {}", req.name); character.character_name = req.name.clone(); //Should probably remove name from the sheet? sheet.name = req.name.clone(); sheet.gender = req.gender.clone(); sheet.concept = req.concept.clone(); sheet.chronicle = req.chronicle.clone(); sheet.age = req.age; character.update_data(&sheet)?; conn.update_character(&character).await?; println!("Updated basic info"); Ok(Proto(ApiResult::success())) } #[post("/rpc/cofd/update_attribute_value", data = "")] pub(super) async fn update_attribute_value( req: Proto, conn: TenebrousDbConn<'_>, logged_in_user: Option<&User>, ) -> Result, Error> { let mut character = load_character( &conn, logged_in_user, &req.character.owner(), req.character.id(), ) .await?; let mut sheet: CofdSheet = character.try_deserialize()?; let value = req.attribute_value; match req.attribute_name.to_lowercase().as_ref() { "strength" => Ok(sheet.strength = value), "dexterity" => Ok(sheet.dexterity = value), "stamina" => Ok(sheet.stamina = value), "intelligence" => Ok(sheet.intelligence = value), "wits" => Ok(sheet.wits = value), "resolve" => Ok(sheet.resolve = value), "presence" => Ok(sheet.presence = value), "manipulation" => Ok(sheet.manipulation = value), "composure" => Ok(sheet.composure = value), _ => Err(Error::InvalidInput), }?; character.update_data(&sheet)?; conn.update_character_sheet(&character).await?; Ok(Proto(ApiResult { success: true, error: "".to_string(), })) } #[patch("/rpc/cofd/update_skill", data = "")] pub(super) async fn update_skill<'a>( skill_update: Proto, conn: TenebrousDbConn<'_>, logged_in_user: Option<&User>, ) -> Result<&'a str, Error> { let mut character = load_character( &conn, logged_in_user, &skill_update.character.owner(), skill_update.character.id(), ) .await?; let mut sheet: CofdSheet = character.try_deserialize()?; let updated_skill: &Skill = skill_update.skill.as_ref().ok_or(Error::InvalidInput)?; let skill_entry = find_skill_entry(&mut sheet, &updated_skill.name); skill_entry .map(|mut entry| entry.insert(updated_skill.clone())) .ok_or(Error::InvalidInput)?; println!( "updated skill {} with {:?}", updated_skill.name, skill_update.skill ); character.update_data(&sheet)?; conn.update_character_sheet(&character).await?; Ok("lol") } #[post("/rpc/cofd/update_skill_value", data = "")] pub(super) async fn update_skill_value<'a>( req: Proto, conn: TenebrousDbConn<'_>, logged_in_user: Option<&User>, ) -> Result, Error> { let mut character = load_character( &conn, logged_in_user, &req.character.owner(), req.character.id(), ) .await?; let mut sheet: CofdSheet = character.try_deserialize()?; let mut skill: Option<&mut Skill> = find_skill(&mut sheet, &req.skill_name); if let Some(ref mut s) = skill { s.dots = req.skill_value; } println!("updated skill value"); character.update_data(&sheet)?; conn.update_character_sheet(&character).await?; Ok(Proto(ApiResult { success: true, error: "".to_string(), })) } #[post("/rpc/cofd/update_merits", data = "")] pub(super) async fn update_merits<'a>( req: Proto, conn: TenebrousDbConn<'_>, logged_in_user: Option<&User>, ) -> Result, Error> { let mut character = load_character( &conn, logged_in_user, &req.character.owner(), req.character.id(), ) .await?; let mut sheet: CofdSheet = character.try_deserialize()?; sheet.merits = req.merits.clone(); println!("updated merits"); character.update_data(&sheet)?; conn.update_character_sheet(&character).await?; Ok(Proto(ApiResult::success())) } #[post("/rpc/cofd/update_items", data = "")] pub(super) async fn update_items<'a>( req: Proto, conn: TenebrousDbConn<'_>, logged_in_user: Option<&User>, ) -> Result, Error> { let mut character = load_character( &conn, logged_in_user, &req.character.owner(), req.character.id(), ) .await?; let mut sheet: CofdSheet = character.try_deserialize()?; sheet.items = req.items.clone(); println!("updated items"); character.update_data(&sheet)?; conn.update_character_sheet(&character).await?; Ok(Proto(ApiResult::success())) } #[put("/rpc/cofd/add_condition", data = "")] pub(super) fn add_condition<'a>(info: Proto) -> &'a str { "lol" } #[delete("/rpc/cofd/remove_condition", data = "")] pub(super) fn remove_condition<'a>(info: Proto) -> &'a str { "lol" }