impls undoable events

This commit is contained in:
2019-10-28 15:27:26 +01:00
parent 0ac2bce183
commit e9f535ac86
5 changed files with 128 additions and 21 deletions

View File

@@ -20,6 +20,7 @@ pub use models::{
claim::{Claim, Claims},
item::{Item, LootManager, Inventory},
player::{Player, Wealth, Players, AsPlayer},
history::Event,
};
/// The connection used
@@ -53,11 +54,18 @@ pub enum Update {
impl Update {
/// Change back what has been updated
fn undo(self) -> QueryResult<()> {
fn undo(&self, conn: &DbConnection, id: i32) -> QueryResult<()> {
match self {
Update::Wealth(diff) => {},
Update::ItemAdded(item) => {},
Update::ItemRemoved(item) => {},
Update::Wealth(diff) => {
AsPlayer(conn, id).update_wealth(-diff.to_gp())?;
},
Update::ItemAdded(item) => {
LootManager(conn, id).remove(item.id)?;
},
Update::ItemRemoved(item) => {
LootManager(conn, id).add_from(&item)?;
},
// Unused for now
Update::ClaimAdded(claim) => {},
Update::ClaimRemoved(claim) => {},
};
@@ -191,6 +199,12 @@ pub fn split_and_share(conn: &DbConnection, amount: i32, players: Vec<i32>) -> Q
}
/// Reverts the last action stored for player
pub fn undo_last_action(conn: &DbConnection, id: i32) -> QueryResult<Event> {
let last_event = models::history::get_last_of_player(conn, id)?;
last_event.undo(conn)
}
#[cfg(none)]
mod tests_old {

View File

@@ -9,6 +9,9 @@ use crate::{DbConnection, QueryResult, Update};
#[derive(Debug, FromSqlRow)]
pub struct UpdateList(Vec<Update>);
// TODO: decide if updates is really optionnal or not
// (like if storing an event without update is usefull ?)
/// An event in history
#[derive(Debug, Queryable)]
pub struct Event {
@@ -19,6 +22,26 @@ pub struct Event {
updates: Option<UpdateList>,
}
impl Event {
pub fn name(&self) -> &str {
&self.text
}
/// TODO: why a move here ??
/// Undo all updates in a single transaction
pub fn undo(self, conn: &DbConnection) -> QueryResult<Self> {
conn.transaction(move || {
if let Some(ref updates) = self.updates {
for update in updates.0.iter() {
update.undo(conn, self.player_id)?;
}
diesel::delete(history::table.find(self.id)).execute(conn)?;
}
Ok(self)
})
}
}
impl<DB: Backend> FromSql<Text, DB> for UpdateList
where
String: FromSql<Text, DB>,
@@ -38,7 +61,11 @@ struct NewEvent<'a> {
updates: Option<String>,
}
/// Insert a new event
///
/// # Warning
/// This actually swallow up conversion errors
pub fn insert_event(conn: &DbConnection, id: i32, text: &str, updates: &Vec<Update>) -> QueryResult<Event> {
diesel::insert_into(history::table)
.values(&NewEvent {

View File

@@ -22,7 +22,7 @@ fn unpack_gold_value(gold: f64) -> (i32, i32, i32, i32) {
///
/// Values are held as individual pieces counts.
/// Allows conversion from and to a floating amount of gold pieces.
#[derive(Queryable, AsChangeset, Serialize, Deserialize, Debug)]
#[derive(Queryable, AsChangeset, Serialize, Deserialize, PartialEq, Copy, Clone, Debug)]
#[table_name = "players"]
pub struct Wealth {
pub cp: i32,
@@ -116,4 +116,52 @@ mod tests {
}
}
#[test]
fn test_negative_wealth() {
use super::Wealth;
assert_eq!(
Wealth{ cp: 3, sp: 2, gp: 1, pp: 0 } + Wealth{ cp: -8, pp: 0, sp: 0, gp: 0 },
Wealth::from_gp(1.23 - 0.08)
)
}
#[test]
fn test_negative_wealth_inverse() {
use super::Wealth;
assert_eq!(
(Wealth{ cp: 3, sp: 2, gp: 1, pp: 0 } + Wealth{ cp: -8, pp: 0, sp: 0, gp: 0 }).to_gp(),
1.23 - 0.08
)
}
#[test]
fn test_diff_adding() {
use super::Wealth;
/// Let say we add 0.08 gp
/// 1.23 + 0.08 gold is 1.31, diff is cp: -2, sp: +1
let old = Wealth::from_gp(1.23);
let new = Wealth::from_gp(1.31);
let diff = new - old;
assert_eq!(diff.as_tuple(), (-2, 1, 0, 0));
assert_eq!(diff.to_gp(), 0.08);
assert_eq!(new - diff, old);
}
#[test]
fn test_diff_subbing() {
use super::Wealth;
/// Let say we sub 0.08 gp
/// 1.31 - 0.08 gold is 1.23, diff is cp: +2, sp: -1
let old = Wealth::from_gp(1.31);
let new = Wealth::from_gp(1.23);
let diff = new - old;
assert_eq!(diff.as_tuple(), (2, -1, 0, 0));
assert_eq!(diff.to_gp(), -0.08);
assert_eq!(new - diff, old);
}
}