diff --git a/lootalot_db/db.sqlite3 b/lootalot_db/db.sqlite3 index 60b70f1..b5eadf0 100644 Binary files a/lootalot_db/db.sqlite3 and b/lootalot_db/db.sqlite3 differ diff --git a/lootalot_db/src/lib.rs b/lootalot_db/src/lib.rs index c53675a..1c0b481 100644 --- a/lootalot_db/src/lib.rs +++ b/lootalot_db/src/lib.rs @@ -6,8 +6,7 @@ extern crate serde_derive; use diesel::prelude::*; use diesel::r2d2::{self, ConnectionManager}; -// Convenience re-export, maybe DbApi should me move here instead ?? -pub use diesel::query_dsl::RunQueryDsl; +use diesel::query_dsl::RunQueryDsl; mod models; mod schema; @@ -101,13 +100,20 @@ impl<'q> AsPlayer<'q> { ) } pub fn update_wealth(self, value: f32) -> ActionResult { - Ok( - false - // TODO: - // models::player::WealthUpdate::from_gp(self.id, value) - // .save_changes(&conn)?; - ) - + use schema::players::dsl::*; + let current_wealth = players.find(self.id) + .select((cp, sp, gp, pp)) + .first::(self.conn)?; + // TODO: improve this + // should be move inside a WealthUpdate method + let update = + models::WealthUpdate::from_gp(current_wealth.to_gp() + value); + diesel::update(players) + .filter(id.eq(self.id)) + .set(&update) + .execute(self.conn) + // TODO: need to work out what this boolean REALLY means + .map(|r| match r { 1 => true, _ => false }) } /// Put a claim on a specific item pub fn claim(self, item: i32) -> ActionResult { diff --git a/lootalot_db/src/models/mod.rs b/lootalot_db/src/models/mod.rs index 912833a..d899110 100644 --- a/lootalot_db/src/models/mod.rs +++ b/lootalot_db/src/models/mod.rs @@ -3,3 +3,4 @@ mod player; pub use item::Item; pub use player::Player; +pub use player::WealthUpdate; diff --git a/lootalot_db/src/models/player.rs b/lootalot_db/src/models/player.rs index b298647..8e26d1e 100644 --- a/lootalot_db/src/models/player.rs +++ b/lootalot_db/src/models/player.rs @@ -1,3 +1,4 @@ +use diesel::prelude::*; use crate::schema::players; use crate::DbConnection; @@ -14,11 +15,31 @@ pub struct Player { } -/// Wealth represented as a single fractionnal amount of gold pieces -#[derive(Identifiable, AsChangeset)] +/// Unpack a floating value in gold pieces to integer +/// values of copper, silver, gold and platinum pieces +/// +/// # Note +/// +/// The conversion is slightly different than standard rules : +/// ``` 1pp = 100gp = 1000sp = 10000 cp ``` +/// +fn unpack_gold_value(gold: f32) -> (i32, i32, i32, i32) { + let rest = (gold.fract() * 100.0).round() as i32; + let gold = gold.trunc() as i32; + let pp = gold / 100; + let gp = gold % 100; + let sp = rest / 10; + let cp = rest % 10; + (cp, sp, gp, pp) +} + +/// Represent an update on a player's wealth +/// +/// The values held here are the amount of pieces to add or +/// substract to player wealth. +#[derive(Queryable, AsChangeset, Debug)] #[table_name="players"] -struct WealthUpdate { - id: i32, +pub struct WealthUpdate { cp: i32, sp: i32, gp: i32, @@ -27,10 +48,15 @@ struct WealthUpdate { impl WealthUpdate{ /// Unpack individual pieces counts from gold value - fn from_gp(id: i32, gp: f32) -> Self { - // TODO: 0,01 pp = 1 gp = 10 sp = 100 cp - let (cp, sp, gp, pp) = (0,0,0,0); - Self { id, cp, sp, gp, pp } + pub fn from_gp(gp: f32) -> Self { + let (cp, sp, gp, pp) = unpack_gold_value(gp); + Self { cp, sp, gp, pp } + } + + pub fn to_gp(&self) -> f32 { + let i = self.pp * 100 + self.gp; + let f = ( self.sp * 10 + self.cp ) as f32 / 100.0; + i as f32 + f } } diff --git a/src/server.rs b/src/server.rs index c282bbf..b10de90 100644 --- a/src/server.rs +++ b/src/server.rs @@ -62,6 +62,13 @@ pub(crate) fn serve() -> std::io::Result<()> { db_call(pool, move |api| api.fetch_players()) }), ) + .route( + "/update-wealth/{player_id}/{amount}", + web::get().to_async(move |pool: AppPool, data: web::Path<(i32, f32)>| { + let (player, gold) = *data; + db_call(pool, move |api| api.as_player(player).update_wealth(gold)) + }), + ) .route( "/loot/{player_id}", web::get().to_async(move |pool: AppPool, player_id: web::Path| {