moves db logic inside model's managers

This commit is contained in:
2019-10-13 16:02:47 +02:00
parent 068b2e7169
commit 0df875d6a6
6 changed files with 183 additions and 116 deletions

View File

@@ -70,7 +70,7 @@ impl<'q> DbApi<'q> {
///
/// TODO: remove limit used for debug
pub fn fetch_inventory(self) -> QueryResult<Vec<models::Item>> {
Ok(schema::items::table.limit(100).load::<models::Item>(self.0)?)
models::item::Inventory(self.0).all()
}
/// Fetch all existing claims
pub fn fetch_claims(self) -> QueryResult<Vec<models::Claim>> {
@@ -120,7 +120,7 @@ impl<'q> AsPlayer<'q> {
/// assert_eq!(format!("{:?}", loot), "[]".to_string());
/// ```
pub fn loot(self) -> QueryResult<Vec<models::Item>> {
Ok(models::Item::owned_by(self.id).load(self.conn)?)
models::item::LootManager(self.conn, self.id).all()
}
/// Buy a batch of items and add them to this player chest
///
@@ -137,23 +137,17 @@ impl<'q> AsPlayer<'q> {
let mut added_items: Vec<models::Item> = Vec::with_capacity(params.len());
for (item_id, price_mod) in params.into_iter() {
if let Ok((item, diff)) = self.conn.transaction(|| {
use schema::looted::dsl::*;
let item = schema::items::table.find(item_id).first::<models::Item>(self.conn)?;
let new_item = models::item::NewLoot::to_player(self.id, &item);
diesel::insert_into(schema::looted::table)
.values(&new_item)
.execute(self.conn)?;
let added_item = models::Item::owned_by(self.id)
.order(id.desc())
.first(self.conn)?;
// Find item in inventory
let item = models::item::Inventory(self.conn).find(*item_id)?;
let new_item = models::item::LootManager(self.conn, self.id)
.add_from(&item)?;
let sell_price = match price_mod {
Some(modifier) => item.base_price as f32 * modifier,
None => item.base_price as f32
};
DbApi::with_conn(self.conn)
.as_player(self.id)
models::player::AsPlayer(self.conn, self.id)
.update_wealth(-sell_price)
.map(|diff| (added_item, diff))
.map(|diff| (new_item, diff.as_tuple()))
}) {
cumulated_diff.push(diff);
added_items.push(item);
@@ -175,25 +169,15 @@ impl<'q> AsPlayer<'q> {
let mut all_results: Vec<(i32, i32, i32, i32)> = Vec::with_capacity(params.len());
for (loot_id, price_mod) in params.into_iter() {
let res = self.conn.transaction(|| {
use schema::looted::dsl::*;
let loot = looted
.find(loot_id)
.first::<models::Loot>(self.conn)?;
if loot.owner != self.id {
// If the item does not belong to player,
// it can't be what we're looking for
return Err(diesel::result::Error::NotFound);
}
let mut sell_value = loot.base_price as f32 / 2.0;
let deleted = models::item::LootManager(self.conn, self.id).remove(*loot_id)?;
let mut sell_value = deleted.base_price as f32 / 2.0;
if let Some(modifier) = price_mod {
sell_value *= modifier;
}
let _deleted = diesel::delete(looted.find(loot_id))
.execute(self.conn)?;
DbApi::with_conn(self.conn).as_player(self.id).update_wealth(sell_value)
models::player::AsPlayer(self.conn, self.id).update_wealth(sell_value)
});
if let Ok(diff) = res {
all_results.push(diff)
all_results.push(diff.as_tuple())
} else {
// TODO: need to find a better way to deal with errors
return Err(diesel::result::Error::NotFound)
@@ -209,54 +193,27 @@ impl<'q> AsPlayer<'q> {
///
/// Value can be negative to substract wealth.
pub fn update_wealth(self, value_in_gp: f32) -> ActionResult<(i32, i32, i32, i32)> {
use schema::players::dsl::*;
let current_wealth = players
.find(self.id)
.select((cp, sp, gp, pp))
.first::<models::Wealth>(self.conn)?;
// TODO: improve thisdiesel dependant transaction
// should be move inside a WealthUpdate method
let updated_wealth = models::Wealth::from_gp(current_wealth.to_gp() + value_in_gp);
// Difference in coins that is sent back
let (old, new) = (current_wealth.as_tuple(), updated_wealth.as_tuple());
let diff = (new.0 - old.0, new.1 - old.1, new.2 - old.2, new.3 - old.3);
diesel::update(players)
.filter(id.eq(self.id))
.set(&updated_wealth)
.execute(self.conn)
.map(|r| match r {
1 => diff,
_ => panic!("RuntimeError: UpdateWealth did no changes at all!"),
})
models::player::AsPlayer(self.conn, self.id)
.update_wealth(value_in_gp)
.map(|w| w.as_tuple())
}
/// Put a claim on a specific item
pub fn claim(self, item: i32) -> ActionResult<()> {
let exists: bool = diesel::select(models::Loot::exists(item)).get_result(self.conn)?;
if !exists {
return Err(diesel::result::Error::NotFound);
};
let claim = models::claim::NewClaim::new(self.id, item);
diesel::insert_into(schema::claims::table)
.values(&claim)
.execute(self.conn)
.map(|rows_updated| match rows_updated {
1 => (),
_ => panic!("RuntimeError: Claim did no change at all!"),
models::claim::Claims(self.conn)
.add(self.id, item)
.map(|claim| {
dbg!("created");
dbg!(claim);
})
}
/// Withdraw claim
pub fn unclaim(self, item: i32) -> ActionResult<()> {
use schema::claims::dsl::*;
diesel::delete(
claims
.filter(loot_id.eq(item))
.filter(player_id.eq(self.id)),
)
.execute(self.conn)
.and_then(|rows_updated| match rows_updated {
1 => Ok(()),
0 => Err(diesel::result::Error::NotFound),
_ => panic!("RuntimeError: UnclaimItem did not make expected changes"),
models::claim::Claims(self.conn)
.remove(self.id, item)
.map(|c| {
dbg!("deleted");
dbg!(c);
})
}
}
@@ -279,19 +236,9 @@ impl<'q> AsAdmin<'q> {
}
/// Adds a list of items to the group loot
///
/// This offers complete control other created items, so that unique
/// items can be easily added. A user interface shall deal with
/// filling theses values for known items in inventory.
///
/// # Params
/// List of (name, base_price) values for the new items
pub fn add_loot(self, items: Vec<models::item::Item>) -> ActionResult<()> {
for item_desc in items.iter() {
let new_item = models::item::NewLoot::to_group(item_desc);
diesel::insert_into(schema::looted::table)
.values(&new_item)
.execute(self.0)?;
models::item::LootManager(self.0, 0).add_from(item_desc)?;
}
Ok(())
}
@@ -301,7 +248,7 @@ impl<'q> AsAdmin<'q> {
/// When a player gets an item, it's debt is increased by this item sell value
pub fn resolve_claims(self) -> ActionResult<()> {
// Fetch all claims, grouped by items.
let loot = models::Loot::owned_by(0).load(self.0)?;
let loot = models::item::Loot::owned_by(0).load(self.0)?;
let claims = schema::claims::table
.load::<models::Claim>(self.0)?
.grouped_by(&loot);