impls undoable events
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user