From 342a66475d3802f06f8b4b21009197316bfd7dbf Mon Sep 17 00:00:00 2001 From: Artus Date: Sun, 8 Dec 2019 14:54:45 +0100 Subject: [PATCH] fixes bugs in group sell --- lootalot_db/src/lib.rs | 29 +++++---- lootalot_db/src/models/player/mod.rs | 6 ++ lootalot_db/src/models/player/wealth.rs | 14 +---- src/api.rs | 79 ++++++++++++------------- 4 files changed, 65 insertions(+), 63 deletions(-) diff --git a/lootalot_db/src/lib.rs b/lootalot_db/src/lib.rs index 157cd77..484062d 100644 --- a/lootalot_db/src/lib.rs +++ b/lootalot_db/src/lib.rs @@ -204,35 +204,42 @@ pub fn resolve_claims(conn: &DbConnection) -> QueryResult<()> { /// /// # Returns /// -/// A Wealth update with the amount of money actually shared +/// A Wealth update with the amount of money shared with players pub fn split_and_share( conn: &DbConnection, amount: i32, - players: &Vec, + players: Vec, ) -> UpdateResult { + let players = match players.is_empty() { + true => Players(conn) + .all_except_group()? + .iter() + .map(|p| p.id) + .collect(), + false => players + }; let share = ( amount / (players.len() + 1) as i32 // +1 share for the group ) as f64; conn.transaction(|| { - // What we actually give, negative value - let mut diff = 0.0; - for p in players { - let player = Players(conn).find(*p)?; + let mut shared_total = 0.0; + for id in players { + let player = Players(conn).find(id)?; // Take debt into account match share - player.debt as f64 { rest if rest > 0.0 => { - AsPlayer(conn, *p).update_debt(-player.debt)?; - AsPlayer(conn, *p).update_wealth(rest)?; + AsPlayer(conn, id).update_debt(-player.debt)?; + AsPlayer(conn, id).update_wealth(rest)?; AsPlayer(conn, 0).update_wealth(-rest)?; - diff -= rest; + shared_total += rest; } _ => { - AsPlayer(conn, *p).update_debt(-share as i32)?; + AsPlayer(conn, id).update_debt(-share as i32)?; } } } - Ok(Update::Wealth(Wealth::from_gp(diff))) + Ok(Update::Wealth(Wealth::from_gp(shared_total))) }) } diff --git a/lootalot_db/src/models/player/mod.rs b/lootalot_db/src/models/player/mod.rs index 20ebc6f..7232c88 100644 --- a/lootalot_db/src/models/player/mod.rs +++ b/lootalot_db/src/models/player/mod.rs @@ -35,6 +35,12 @@ impl<'q> Players<'q> { players::table.load(self.0) } + /// Get all non-group players + pub fn all_except_group(&self) -> QueryResult> { + use diesel::dsl::not; + players::table.filter(not(players::id.eq(0))).load(self.0) + } + /// Find a player by id pub fn find(&self, id: i32) -> QueryResult { players::table.find(id).first(self.0) diff --git a/lootalot_db/src/models/player/wealth.rs b/lootalot_db/src/models/player/wealth.rs index 3d0274f..cda4588 100644 --- a/lootalot_db/src/models/player/wealth.rs +++ b/lootalot_db/src/models/player/wealth.rs @@ -69,12 +69,7 @@ impl std::ops::Sub for Wealth { /// What needs to be added to 'other' so that /// the result equals 'self' fn sub(self, other: Self) -> Self { - Wealth { - cp: self.cp - other.cp, - sp: self.sp - other.sp, - gp: self.gp - other.gp, - pp: self.pp - other.pp, - } + Wealth::from_gp(self.to_gp() - other.to_gp()) } } @@ -82,12 +77,7 @@ impl std::ops::Add for Wealth { type Output = Self; fn add(self, other: Self) -> Self { - Wealth { - cp: self.cp + other.cp, - sp: self.sp + other.sp, - gp: self.gp + other.gp, - pp: self.pp + other.pp - } + Wealth::from_gp(self.to_gp() + other.to_gp()) } } diff --git a/src/api.rs b/src/api.rs index 866231d..04a593d 100644 --- a/src/api.rs +++ b/src/api.rs @@ -122,7 +122,7 @@ pub fn execute( None } ApiActions::FetchPlayers => { - response.set_value(Value::PlayerList(db::Players(conn).all()?)); + response.set_value(Value::PlayerList(db::Players(conn).all_except_group()?)); None } ApiActions::FetchInventory => { @@ -167,9 +167,7 @@ pub fn execute( if has_enough_gold { let mut gains: Vec = Vec::with_capacity(params.items.len()); for (item_id, price_mod) in params.items.into_iter() { - if let Ok((item, diff)) = - db::buy_item_from_shop(conn, id, item_id, price_mod) - { + if let Ok((item, diff)) = db::buy_item_from_shop(conn, id, item_id, price_mod) { response.push_update(item); gains.push(diff); } else { @@ -195,46 +193,47 @@ pub fn execute( // Behavior differs if player is group or regular. // Group sells item like players then split the total amount among players. ApiActions::SellItems(id, params) => { - let mut gains: Vec = Vec::with_capacity(params.items.len()); - for (loot_id, price_mod) in params.items.iter() { - if let Ok((deleted, diff)) = - db::sell_item_transaction(conn, id, *loot_id, *price_mod) - { - response.push_update(deleted); - gains.push(diff); - } else { - response.push_error(format!("Erreur lors de la vente (loot_id : {})", loot_id)); - } - } - let sold_items = gains.len(); - let total_amount = gains - .into_iter() - .fold(db::Wealth::from_gp(0.0), |acc, i| acc + i); - match id { - 0 => { - let players = params - .players - .unwrap_or(db::Players(conn).all()?.into_iter().map(|p| p.id).collect()); - if let Update::Wealth(shared) = - db::split_and_share(conn, total_amount.to_gp() as i32, &players)? + conn.transaction(|| -> Result, diesel::result::Error> { + let mut gains: Vec = Vec::with_capacity(params.items.len()); + for (loot_id, price_mod) in params.items.iter() { + if let Ok((deleted, diff)) = + db::sell_item_transaction(conn, id, *loot_id, *price_mod) { + response.push_update(deleted); + gains.push(diff); + } else { + response + .push_error(format!("Erreur lors de la vente (loot_id : {})", loot_id)); + } + } + let sold_items = gains.len(); + let total_amount = gains + .into_iter() + .fold(db::Wealth::from_gp(0.0), |acc, i| acc + i); + match id { + 0 => { + let players = params.players.unwrap_or_default(); + if let Update::Wealth(shared) = + db::split_and_share(conn, total_amount.to_gp() as i32, players)? + { + response.notify(format!( + "Les objets ont été vendus, les joueurs ont reçu (au total) {} po", + shared.to_gp() + )); + response.push_update(Update::Wealth(total_amount - shared)); + }; + } + _ => { response.notify(format!( - "Les objets ont été vendus, les joueurs ont reçu (au total) {} po", - shared.to_gp() + "{} objet(s) vendu(s) pour {} po", + sold_items, + total_amount.to_gp() )); - response.push_update(Update::Wealth(db::Wealth::from_gp(total_amount.to_gp() - shared.to_gp()))); - }; + response.push_update(Update::Wealth(total_amount)); + } } - _ => { - response.notify(format!( - "{} objet(s) vendu(s) pour {} po", - sold_items, - total_amount.to_gp() - )); - response.push_update(Update::Wealth(total_amount)); - } - } - Some((id, "Vente d'objets")) + Ok(Some((id, "Vente d'objets"))) + })? } ApiActions::ClaimItem(id, item) => { response.push_update(db::Claims(conn).add(id, item)?);