From 2cb547e16ab9760211ba2686a1d5dc2fe47dc1ab Mon Sep 17 00:00:00 2001 From: jeff Date: Fri, 1 Jan 2021 00:40:48 +0000 Subject: [PATCH] Implement updating skills on the backend. --- proto/cofd_api.proto | 5 +++++ src/routes/api.rs | 49 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/proto/cofd_api.proto b/proto/cofd_api.proto index 7a14bcb..b84ee9c 100644 --- a/proto/cofd_api.proto +++ b/proto/cofd_api.proto @@ -44,6 +44,11 @@ message Skills { repeated CofdSheet.Skill social_skills = 3; } +message SkillUpdate { + string name = 1; + CofdSheet.Skill skill = 2; +} + //Add a Condition to a Chronicles of Darkness character sheet. message Condition { string name = 1; diff --git a/src/routes/api.rs b/src/routes/api.rs index 95454db..06d45c8 100644 --- a/src/routes/api.rs +++ b/src/routes/api.rs @@ -1,12 +1,12 @@ use crate::db::{Dao, TenebrousDbConn}; use crate::errors::Error; use crate::models::characters::{Character, CharacterDataType, DynCharacterData, Visibility}; -use crate::models::proto::{cofd::*, Proto}; +use crate::models::proto::cofd::*; use crate::models::users::User; use rocket_contrib::templates::Template; use serde::Serialize; use std::borrow::Cow; -use std::collections::HashMap; +use std::collections::btree_map::{Entry, OccupiedEntry}; pub(crate) fn routes() -> Vec { routes![ @@ -46,6 +46,7 @@ async fn load_character( /// Protobuf-based REST endpoints for editing a character. mod cofd { use super::*; + use crate::models::proto::cofd::cofd_sheet::Skill; use crate::models::proto::{cofd::api::*, cofd::*, Proto}; #[post("/cofd///basic-info", data = "")] @@ -100,14 +101,48 @@ mod cofd { Ok("lol") } - #[post("/cofd///skills", data = "")] - pub(super) fn update_skills<'a>( + #[patch("/cofd///skills", data = "")] + pub(super) async fn update_skills<'a>( owner: String, character_id: i32, - info: Proto, + skill_update: Proto, conn: TenebrousDbConn<'_>, - ) -> &'a str { - "lol" + logged_in_user: Option<&User>, + ) -> Result<&'a str, Error> { + let mut character = load_character(&conn, logged_in_user, owner, character_id).await?; + let mut sheet: CofdSheet = character.try_deserialize()?; + let skill: &Skill = skill_update.skill.as_ref().ok_or(Error::InvalidInput)?; + + 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_entry: Option> = 'l: loop { + for skill_map in all_skills { + if let Entry::Occupied(entry) = skill_map.entry(skill_update.name.clone()) { + break 'l Some(entry); + } + } + + break None; + }; + + skill_entry + .map(|mut entry| entry.insert(skill.clone())) + .ok_or(Error::InvalidInput)?; + + println!( + "updated skill {} with {:?}", + skill_update.name, skill_update.skill + ); + + character.update_data(sheet)?; + conn.update_character_sheet(&character).await?; + Ok("lol") } #[put("/cofd///conditions", data = "")]