works on resolve_claims

This commit is contained in:
2019-10-14 15:27:49 +02:00
parent 0df875d6a6
commit b2e319dc15
4 changed files with 65 additions and 42 deletions

View File

@@ -247,13 +247,7 @@ impl<'q> AsAdmin<'q> {
/// ///
/// When a player gets an item, it's debt is increased by this item sell value /// When a player gets an item, it's debt is increased by this item sell value
pub fn resolve_claims(self) -> ActionResult<()> { pub fn resolve_claims(self) -> ActionResult<()> {
// Fetch all claims, grouped by items. let data = models::claim::Claims(self.0).grouped_by_loot()?;
let loot = models::item::Loot::owned_by(0).load(self.0)?;
let claims = schema::claims::table
.load::<models::Claim>(self.0)?
.grouped_by(&loot);
// For each claimed item
let data = loot.into_iter().zip(claims).collect::<Vec<_>>();
dbg!(&data); dbg!(&data);
for (loot, claims) in data { for (loot, claims) in data {
@@ -262,18 +256,12 @@ impl<'q> AsAdmin<'q> {
let claim = claims.get(0).unwrap(); let claim = claims.get(0).unwrap();
let player_id = claim.player_id; let player_id = claim.player_id;
self.0.transaction(|| { self.0.transaction(|| {
use schema::looted::dsl::*; loot.set_owner(claim.player_id)
diesel::update(looted.find(claim.loot_id))
.set(owner_id.eq(player_id))
.execute(self.0)?; .execute(self.0)?;
diesel::delete(schema::claims::table.find(claim.id)) models::player::AsPlayer(self.0, player_id)
.execute(self.0)?; .update_debt(loot.sell_value())?;
{ models::claim::Claims(self.0).remove(player_id, claim.loot_id)?;
use schema::players::dsl::*; Ok(())
diesel::update(players.find(player_id))
.set(debt.eq(debt + (loot.base_price / 2)))
.execute(self.0)
}
})?; })?;
}, },
_ => (), _ => (),

View File

@@ -22,49 +22,65 @@ pub struct Claims<'q>(pub &'q DbConnection);
impl<'q> Claims<'q> { impl<'q> Claims<'q> {
/// Finds a single claim by id. /// Finds a single claim by association of player and loot ids.
pub fn find(&self, player_id: i32, loot_id: i32) -> QueryResult<Claim> { pub fn find(&self, player_id: i32, loot_id: i32) -> QueryResult<Claim> {
Ok(
claims::table claims::table
.filter(claims::dsl::player_id.eq(player_id)) .filter(claims::dsl::player_id.eq(player_id))
.filter(claims::dsl::loot_id.eq(loot_id)) .filter(claims::dsl::loot_id.eq(loot_id))
.first(self.0)? .first(self.0)
)
} }
/// Adds a claim in database and returns it /// Adds a claim in database and returns it
pub fn add(self, player_id: i32, loot_id: i32) -> QueryResult<Claim> { pub fn add(self, player_id: i32, loot_id: i32) -> QueryResult<Claim> {
// We need to validate that the claimed item exists, and is actually owned by group (id 0) // We need to validate that the claimed item exists
let exists: bool = diesel::select(Loot::exists(loot_id)).get_result(self.0)?; // AND is actually owned by group (id 0)
if !exists { let _item = models::item::LootManager(self.0, 0).find(loot_id)?;
return Err(diesel::result::Error::NotFound);
};
let claim = NewClaim::new(player_id, loot_id); let claim = NewClaim::new(player_id, loot_id);
diesel::insert_into(claims::table) diesel::insert_into(claims::table)
.values(&claim) .values(&claim)
.execute(self.0)?; .execute(self.0)?;
// Return the created claim // Return the created claim
Ok(claims::table.order(claims::dsl::id.desc()).first::<Claim>(self.0)?) claims::table
.order(claims::dsl::id.desc())
.first::<Claim>(self.0)
} }
/// Removes a claim from database, returning it /// Removes a claim from database, returning it
pub fn remove(self, req_player_id: i32, req_loot_id: i32) -> QueryResult<Claim> { pub fn remove(self, player_id: i32, loot_id: i32) -> QueryResult<Claim> {
let claim = self.find(req_player_id, req_loot_id)?; let claim = self.find(player_id, loot_id)?;
diesel::delete(claims::table.find(claim.id)) diesel::delete(claims::table.find(claim.id))
.execute(self.0)?; .execute(self.0)?;
Ok(claim) Ok(claim)
} }
pub fn filtered_by_loot(&self, loot_id: i32) -> QueryResult<Vec<Claim>> {
claims::table
.filter(claims::dsl::loot_id.eq(loot_id))
.load(self.0)
}
pub(crate) fn grouped_by_loot(&self) -> QueryResult<Vec<(models::item::Loot, Vec<Claim>)>> {
let loot = models::item::Loot::owned_by(0).load(self.0)?;
let claims = claims::table
.load(self.0)?
.grouped_by(&loot);
Ok(
loot.into_iter()
.zip(claims)
.collect::<Vec<_>>()
)
}
} }
#[derive(Insertable, Debug)] #[derive(Insertable, Debug)]
#[table_name = "claims"] #[table_name = "claims"]
pub(crate) struct NewClaim { struct NewClaim {
player_id: i32, player_id: i32,
loot_id: i32, loot_id: i32,
} }
impl NewClaim { impl NewClaim {
pub(crate) fn new(player_id: i32, loot_id: i32) -> Self { fn new(player_id: i32, loot_id: i32) -> Self {
Self { player_id, loot_id } Self { player_id, loot_id }
} }
} }

View File

@@ -10,11 +10,7 @@ type ItemColumns = (looted::id, looted::name, looted::base_price);
const ITEM_COLUMNS: ItemColumns = (looted::id, looted::name, looted::base_price); const ITEM_COLUMNS: ItemColumns = (looted::id, looted::name, looted::base_price);
type OwnedBy = Select<OwnedLoot, ItemColumns>; type OwnedBy = Select<OwnedLoot, ItemColumns>;
/// Represents a unique item in inventory /// Represents a basic item
///
/// It is also used as a public representation of Loot, since owner
/// information is implicit.
/// Or maybe this is a little too confusing ??
#[derive(Debug, Queryable, Serialize, Deserialize, Clone)] #[derive(Debug, Queryable, Serialize, Deserialize, Clone)]
pub struct Item { pub struct Item {
pub id: i32, pub id: i32,
@@ -47,7 +43,10 @@ impl<'q> Inventory<'q> {
type WithOwner = Eq<looted::owner_id, i32>; type WithOwner = Eq<looted::owner_id, i32>;
type OwnedLoot = Filter<looted::table, WithOwner>; type OwnedLoot = Filter<looted::table, WithOwner>;
/// Represents an item that has been looted
/// Represents an item that has been looted,
/// hence has an owner.
#[derive(Identifiable, Debug, Queryable, Serialize)] #[derive(Identifiable, Debug, Queryable, Serialize)]
#[table_name = "looted"] #[table_name = "looted"]
pub(super) struct Loot { pub(super) struct Loot {
@@ -63,13 +62,24 @@ impl Loot {
looted::table.filter(looted::owner_id.eq(id)) looted::table.filter(looted::owner_id.eq(id))
} }
fn owns(player: i32, item: i32) -> Exists<Find<OwnedLoot, i32>> {
exists(Loot::owned_by(player).find(item))
}
pub(super) fn exists(id: i32) -> Exists<Find<looted::table, i32>> { pub(super) fn exists(id: i32) -> Exists<Find<looted::table, i32>> {
exists(looted::table.find(id)) exists(looted::table.find(id))
} }
pub(crate) fn set_owner(&self, owner: i32) -> () {
diesel::update(looted::table.find(self.id))
.set(looted::dsl::owner_id.eq(owner))
}
/// TODO: should belong inside Item impl
pub(crate) fn value(&self) -> i32 {
self.base_price
}
/// TODO: should belong inside Item impl
pub(crate) fn sell_value(&self) -> i32 {
self.base_price / 2
}
} }
/// Manager for a player's loot /// Manager for a player's loot

View File

@@ -45,6 +45,15 @@ impl<'q> AsPlayer<'q> {
.execute(self.0)?; .execute(self.0)?;
Ok(difference) Ok(difference)
} }
pub fn update_debt(&self, value_in_gp: i32) -> QueryResult<()> {
diesel::update(players::table.find(self.1))
.set(players::dsl::debt.eq(
players::dsl::debt + value_in_gp
))
.execute(self.0)?;
Ok(())
}
} }