fixes bugs in group sell

This commit is contained in:
2019-12-08 14:54:45 +01:00
parent 108470c5d1
commit 342a66475d
4 changed files with 65 additions and 63 deletions

View File

@@ -204,35 +204,42 @@ pub fn resolve_claims(conn: &DbConnection) -> QueryResult<()> {
/// ///
/// # Returns /// # 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( pub fn split_and_share(
conn: &DbConnection, conn: &DbConnection,
amount: i32, amount: i32,
players: &Vec<i32>, players: Vec<i32>,
) -> UpdateResult { ) -> UpdateResult {
let players = match players.is_empty() {
true => Players(conn)
.all_except_group()?
.iter()
.map(|p| p.id)
.collect(),
false => players
};
let share = ( let share = (
amount / (players.len() + 1) as i32 amount / (players.len() + 1) as i32
// +1 share for the group // +1 share for the group
) as f64; ) as f64;
conn.transaction(|| { conn.transaction(|| {
// What we actually give, negative value let mut shared_total = 0.0;
let mut diff = 0.0; for id in players {
for p in players { let player = Players(conn).find(id)?;
let player = Players(conn).find(*p)?;
// Take debt into account // Take debt into account
match share - player.debt as f64 { match share - player.debt as f64 {
rest if rest > 0.0 => { rest if rest > 0.0 => {
AsPlayer(conn, *p).update_debt(-player.debt)?; AsPlayer(conn, id).update_debt(-player.debt)?;
AsPlayer(conn, *p).update_wealth(rest)?; AsPlayer(conn, id).update_wealth(rest)?;
AsPlayer(conn, 0).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)))
}) })
} }

View File

@@ -35,6 +35,12 @@ impl<'q> Players<'q> {
players::table.load(self.0) players::table.load(self.0)
} }
/// Get all non-group players
pub fn all_except_group(&self) -> QueryResult<Vec<Player>> {
use diesel::dsl::not;
players::table.filter(not(players::id.eq(0))).load(self.0)
}
/// Find a player by id /// Find a player by id
pub fn find(&self, id: i32) -> QueryResult<Player> { pub fn find(&self, id: i32) -> QueryResult<Player> {
players::table.find(id).first(self.0) players::table.find(id).first(self.0)

View File

@@ -69,12 +69,7 @@ impl std::ops::Sub for Wealth {
/// What needs to be added to 'other' so that /// What needs to be added to 'other' so that
/// the result equals 'self' /// the result equals 'self'
fn sub(self, other: Self) -> Self { fn sub(self, other: Self) -> Self {
Wealth { Wealth::from_gp(self.to_gp() - other.to_gp())
cp: self.cp - other.cp,
sp: self.sp - other.sp,
gp: self.gp - other.gp,
pp: self.pp - other.pp,
}
} }
} }
@@ -82,12 +77,7 @@ impl std::ops::Add for Wealth {
type Output = Self; type Output = Self;
fn add(self, other: Self) -> Self { fn add(self, other: Self) -> Self {
Wealth { Wealth::from_gp(self.to_gp() + other.to_gp())
cp: self.cp + other.cp,
sp: self.sp + other.sp,
gp: self.gp + other.gp,
pp: self.pp + other.pp
}
} }
} }

View File

@@ -122,7 +122,7 @@ pub fn execute(
None None
} }
ApiActions::FetchPlayers => { ApiActions::FetchPlayers => {
response.set_value(Value::PlayerList(db::Players(conn).all()?)); response.set_value(Value::PlayerList(db::Players(conn).all_except_group()?));
None None
} }
ApiActions::FetchInventory => { ApiActions::FetchInventory => {
@@ -167,9 +167,7 @@ pub fn execute(
if has_enough_gold { if has_enough_gold {
let mut gains: Vec<db::Wealth> = Vec::with_capacity(params.items.len()); let mut gains: Vec<db::Wealth> = Vec::with_capacity(params.items.len());
for (item_id, price_mod) in params.items.into_iter() { for (item_id, price_mod) in params.items.into_iter() {
if let Ok((item, diff)) = if let Ok((item, diff)) = db::buy_item_from_shop(conn, id, item_id, price_mod) {
db::buy_item_from_shop(conn, id, item_id, price_mod)
{
response.push_update(item); response.push_update(item);
gains.push(diff); gains.push(diff);
} else { } else {
@@ -195,6 +193,7 @@ pub fn execute(
// Behavior differs if player is group or regular. // Behavior differs if player is group or regular.
// Group sells item like players then split the total amount among players. // Group sells item like players then split the total amount among players.
ApiActions::SellItems(id, params) => { ApiActions::SellItems(id, params) => {
conn.transaction(|| -> Result<Option<(i32, &str)>, diesel::result::Error> {
let mut gains: Vec<db::Wealth> = Vec::with_capacity(params.items.len()); let mut gains: Vec<db::Wealth> = Vec::with_capacity(params.items.len());
for (loot_id, price_mod) in params.items.iter() { for (loot_id, price_mod) in params.items.iter() {
if let Ok((deleted, diff)) = if let Ok((deleted, diff)) =
@@ -203,7 +202,8 @@ pub fn execute(
response.push_update(deleted); response.push_update(deleted);
gains.push(diff); gains.push(diff);
} else { } else {
response.push_error(format!("Erreur lors de la vente (loot_id : {})", loot_id)); response
.push_error(format!("Erreur lors de la vente (loot_id : {})", loot_id));
} }
} }
let sold_items = gains.len(); let sold_items = gains.len();
@@ -212,17 +212,15 @@ pub fn execute(
.fold(db::Wealth::from_gp(0.0), |acc, i| acc + i); .fold(db::Wealth::from_gp(0.0), |acc, i| acc + i);
match id { match id {
0 => { 0 => {
let players = params let players = params.players.unwrap_or_default();
.players
.unwrap_or(db::Players(conn).all()?.into_iter().map(|p| p.id).collect());
if let Update::Wealth(shared) = if let Update::Wealth(shared) =
db::split_and_share(conn, total_amount.to_gp() as i32, &players)? db::split_and_share(conn, total_amount.to_gp() as i32, players)?
{ {
response.notify(format!( response.notify(format!(
"Les objets ont été vendus, les joueurs ont reçu (au total) {} po", "Les objets ont été vendus, les joueurs ont reçu (au total) {} po",
shared.to_gp() shared.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 - shared));
}; };
} }
_ => { _ => {
@@ -234,7 +232,8 @@ pub fn execute(
response.push_update(Update::Wealth(total_amount)); response.push_update(Update::Wealth(total_amount));
} }
} }
Some((id, "Vente d'objets")) Ok(Some((id, "Vente d'objets")))
})?
} }
ApiActions::ClaimItem(id, item) => { ApiActions::ClaimItem(id, item) => {
response.push_update(db::Claims(conn).add(id, item)?); response.push_update(db::Claims(conn).add(id, item)?);