diff --git a/lootalot_db/src/lib.rs b/lootalot_db/src/lib.rs index b8f2af0..3cfa983 100644 --- a/lootalot_db/src/lib.rs +++ b/lootalot_db/src/lib.rs @@ -15,6 +15,12 @@ pub mod models; //mod updates; mod schema; +pub use models::{ + item::{Item, LootManager}, + claim::{Claim, Claims}, + player::{Player, Players}, +}; + /// The connection used pub type DbConnection = SqliteConnection; /// A pool of connections @@ -226,13 +232,9 @@ impl<'q> AsAdmin<'q> { /// /// Takes the player name and starting wealth (in gold value). pub fn add_player(self, name: &str, start_wealth: f32) -> ActionResult<()> { - diesel::insert_into(schema::players::table) - .values(&models::player::NewPlayer::create(name, start_wealth)) - .execute(self.0) - .map(|rows_updated| match rows_updated { - 1 => (), - _ => panic!("RuntimeError: AddPlayer did not make expected changes"), - }) + models::player::Players(self.0) + .add(name, start_wealth)?; + Ok(()) } /// Adds a list of items to the group loot @@ -280,8 +282,8 @@ pub fn create_pool() -> Pool { .expect("Failed to create pool.") } -#[cfg(test)] -mod tests { +#[cfg(none)] +mod tests_old { use super::*; type TestConnection = DbConnection; diff --git a/lootalot_db/src/models/claim.rs b/lootalot_db/src/models/claim.rs index cb10adf..3a1c826 100644 --- a/lootalot_db/src/models/claim.rs +++ b/lootalot_db/src/models/claim.rs @@ -37,6 +37,11 @@ pub struct Claims<'q>(pub &'q DbConnection); impl<'q> Claims<'q> { + pub fn all(&self) -> QueryResult> { + claims::table + .load(self.0) + } + /// Finds a single claim by association of player and loot ids. pub fn find(&self, player_id: i32, loot_id: i32) -> QueryResult { claims::table @@ -50,6 +55,11 @@ impl<'q> Claims<'q> { // We need to validate that the claimed item exists // AND is actually owned by group (id 0) let _item = models::item::LootManager(self.0, 0).find(loot_id)?; + // We also check if claims does not already exists + if let Ok(_) = self.find(player_id, loot_id) { + return Err(diesel::result::Error::RollbackTransaction); + } + let claim = NewClaim::new(player_id, loot_id); diesel::insert_into(claims::table) .values(&claim) @@ -99,3 +109,61 @@ impl NewClaim { Self { player_id, loot_id } } } + +#[cfg(test)] +mod tests { + use super::*; + + type TestResult = Result<(), diesel::result::Error>; + + fn test_connection() -> Result { + let conn = DbConnection::establish(":memory:") + .map_err(|_| diesel::result::Error::NotFound)?; + diesel_migrations::run_pending_migrations(&conn) + .map_err(|_| diesel::result::Error::NotFound)?; + let manager = models::player::Players(&conn); + manager.add("Player1", 0.0)?; + manager.add("Player2", 0.0)?; + crate::LootManager(&conn, 0) + .add_from(&crate::Item{ id: 0, name: "Epee".to_string(), base_price: 30 })?; + crate::LootManager(&conn, 1) + .add_from(&crate::Item{ id: 0, name: "Arc".to_string(), base_price: 20 })?; + Ok(conn) + } + + #[test] + fn add_claim() -> TestResult { + let conn = test_connection()?; + Claims(&conn).add(1, 1)?; + assert_eq!(Claims(&conn).all()?.len(), 1); + Ok(()) + } + + #[test] + fn cannot_duplicate_by_adding() -> TestResult { + let conn = test_connection()?; + Claims(&conn).add(1, 1)?; + let res = Claims(&conn).add(1, 1); + assert_eq!(res.is_err(), true); + assert_eq!(Claims(&conn).all()?.len(), 1); + Ok(()) + } + + #[test] + fn remove_claim() -> TestResult { + let conn = test_connection()?; + let claim = Claims(&conn).add(1, 1)?; + claim.remove(&conn); + assert_eq!(Claims(&conn).all()?.len(), 0); + Ok(()) + } + + #[test] + fn cannot_only_claim_from_group() -> TestResult { + let conn = test_connection()?; + let claim = Claims(&conn).add(1, 2); + assert_eq!(claim.is_err(), true); + assert_eq!(Claims(&conn).all()?.len(), 0); + Ok(()) + } +} diff --git a/lootalot_db/src/models/player.rs b/lootalot_db/src/models/player.rs index f61e3af..c9fb23f 100644 --- a/lootalot_db/src/models/player.rs +++ b/lootalot_db/src/models/player.rs @@ -22,6 +22,25 @@ pub struct Player { pub pp: i32, } +pub struct Players<'q>(pub &'q DbConnection); + +impl<'q> Players<'q> { + + pub fn all(&self) -> QueryResult> { + players::table + .load(self.0) + } + + pub fn add(&self, name: &str, wealth: f32) -> QueryResult { + diesel::insert_into(players::table) + .values(&NewPlayer::create(name, wealth)) + .execute(self.0)?; + players::table + .order(players::dsl::id.desc()) + .first(self.0) + } +} + pub struct AsPlayer<'q>(pub &'q DbConnection, pub i32); impl<'q> AsPlayer<'q> {