enhance responses from API, integrates with frontend

This commit is contained in:
2019-07-11 14:54:18 +02:00
parent bc65dfcd78
commit e08cd64743
9 changed files with 130 additions and 26 deletions

Binary file not shown.

View File

@@ -14,7 +14,30 @@ mod schema;
pub type DbConnection = SqliteConnection;
pub type Pool = r2d2::Pool<ConnectionManager<DbConnection>>;
pub type QueryResult<T> = Result<T, diesel::result::Error>;
pub type ActionResult = QueryResult<bool>;
pub type ActionResult<R> = QueryResult<ActionStatus<R>>;
#[derive(Serialize, Debug)]
pub struct ActionStatus<R: serde::Serialize> {
/// Has the action made changes ?
executed: bool,
/// Response payload
response: R,
}
impl ActionStatus<()> {
fn ok() -> ActionStatus<()> {
Self {
executed: true,
response: (),
}
}
fn nop() -> ActionStatus<()> {
Self {
executed: false,
response: (),
}
}
}
/// A wrapper providing an API over the database
/// It offers a convenient way to deal with connection
@@ -115,7 +138,8 @@ impl<'q> AsPlayer<'q> {
/// Adds the value in gold to the player's wealth.
///
/// Value can be negative to substract wealth.
pub fn update_wealth(self, value_in_gp: f32) -> ActionResult {
pub fn update_wealth(self, value_in_gp: f32)
-> ActionResult<Option<(i32, i32, i32, i32)>> {
use schema::players::dsl::*;
let current_wealth = players
.find(self.id)
@@ -126,30 +150,54 @@ impl<'q> AsPlayer<'q> {
let update = models::WealthUpdate::from_gp(
current_wealth.to_gp() + value_in_gp
);
// Difference in coins that is sent back
let (old, new) =
(current_wealth.as_tuple(), update.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(&update)
.execute(self.conn)
// TODO: need to work out what this boolean REALLY means
.map(|r| match r { 1 => true, _ => false })
.map(|r| match r {
1 => ActionStatus {
executed: true,
response: Some(diff),
},
_ => ActionStatus {
executed: false,
response: None,
}, })
}
/// Put a claim on a specific item
pub fn claim(self, item: i32) -> ActionResult {
pub fn claim(self, item: i32) -> ActionResult<()> {
// TODO: check that looted item exists
let exists: bool =
diesel::select(models::Loot::exists(item))
.get_result(self.conn)?;
if !exists {
return Ok(ActionStatus::nop())
};
let request = models::NewClaim { player_id: self.id, loot_id: item };
diesel::insert_into(schema::claims::table)
.values(&request)
.execute(self.conn)
.map(|r| match r { 1 => true, _ => false })
.map(|r| match r { 1 => ActionStatus::ok(), _ => ActionStatus::nop() })
}
/// Withdraw claim
pub fn unclaim(self, item: i32) -> ActionResult {
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)
.map(|r| match r { 1 => true, _ => false })
.map(|r| match r { 1 => ActionStatus::ok(), _ => ActionStatus::nop() })
}
}
@@ -158,11 +206,25 @@ pub struct AsAdmin<'q>(&'q DbConnection);
impl<'q> AsAdmin<'q> {
pub fn add_player(self, name: String, start_wealth: f32) -> ActionResult {
pub fn add_player(self, name: String, start_wealth: f32) -> ActionResult<()> {
diesel::insert_into(schema::players::table)
.values(&models::NewPlayer::create(&name, start_wealth))
.execute(self.0)
.map(|r| match r { 1 => true, _ => false })
.map(|r| match r { 1 => ActionStatus::ok(), _ => ActionStatus::nop() })
}
pub fn resolve_claims(self) -> ActionResult<()> {
// Fetch all claims, grouped by items.
let loot = models::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);
// If mutiples claims -> find highest resolve, give to this player
// If only one claim -> give to claiming
Ok(ActionStatus::nop())
}
}

View File

@@ -1,7 +1,9 @@
use diesel::prelude::*;
use crate::schema::claims;
use crate::models::item::Loot;
#[derive(Queryable, Serialize, Debug)]
#[derive(Identifiable, Queryable, Associations, Serialize, Debug)]
#[belongs_to(Loot)]
pub struct Claim {
id: i32,
player_id: i32,

View File

@@ -1,5 +1,6 @@
use diesel::prelude::*;
use diesel::dsl::{Eq, Filter, Select};
use diesel::dsl::{Eq, Filter, Select, exists, Find };
use diesel::expression::exists::Exists;
use crate::schema::{looted, items};
use crate::DbConnection;
@@ -33,8 +34,9 @@ type WithOwner = Eq<looted::owner_id, i32>;
type OwnedLoot = Filter<looted::table, WithOwner>;
/// Represents an item that has been looted
#[derive(Debug, Queryable, Serialize)]
struct Loot {
#[derive(Identifiable, Debug, Queryable, Serialize)]
#[table_name="looted"]
pub(crate) struct Loot {
id: i32,
name: String,
base_value: i32,
@@ -43,10 +45,14 @@ struct Loot {
impl Loot {
/// A filter on Loot that is owned by given player
fn owned_by(id: i32) -> OwnedLoot {
pub(crate) fn owned_by(id: i32) -> OwnedLoot {
looted::table
.filter(looted::owner_id.eq(id))
}
pub(crate) fn exists(id: i32) -> Exists<Find<looted::table, i32>> {
exists(looted::table.find(id))
}
}
type ItemDesc<'a> = (&'a str, i32);

View File

@@ -3,5 +3,6 @@ mod player;
mod claim;
pub use item::Item;
pub(crate) use item::Loot;
pub use player::{Player, NewPlayer, WealthUpdate};
pub use claim::{NewClaim, Claim};

View File

@@ -58,6 +58,10 @@ impl WealthUpdate{
let f = ( self.sp * 10 + self.cp ) as f32 / 100.0;
i as f32 + f
}
pub fn as_tuple(&self) -> (i32, i32, i32, i32) {
(self.cp, self.sp, self.gp, self.pp)
}
}