Updated query parameters for spells
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
"ritual": false,
|
||||
"casting_time": {
|
||||
"amount": 1,
|
||||
"type": "action"
|
||||
"unit": "action"
|
||||
},
|
||||
"range": {
|
||||
"type": "point",
|
||||
@@ -49,7 +49,7 @@
|
||||
"ritual": false,
|
||||
"casting_time": {
|
||||
"amount": 1,
|
||||
"type": "action"
|
||||
"unit": "action"
|
||||
},
|
||||
"range": {
|
||||
"type": "self"
|
||||
@@ -88,7 +88,7 @@
|
||||
"ritual": false,
|
||||
"casting_time": {
|
||||
"amount": 1,
|
||||
"type": "action"
|
||||
"unit": "action"
|
||||
},
|
||||
"range": {
|
||||
"type": "touch"
|
||||
@@ -134,7 +134,7 @@
|
||||
"ritual": false,
|
||||
"casting_time": {
|
||||
"amount": 1,
|
||||
"type": "action"
|
||||
"unit": "action"
|
||||
},
|
||||
"range": {
|
||||
"type": "point",
|
||||
@@ -177,7 +177,7 @@
|
||||
"ritual": false,
|
||||
"casting_time": {
|
||||
"amount": 1,
|
||||
"type": "action"
|
||||
"unit": "action"
|
||||
},
|
||||
"range": {
|
||||
"type": "point",
|
||||
@@ -232,7 +232,7 @@
|
||||
"ritual": false,
|
||||
"casting_time": {
|
||||
"amount": 1,
|
||||
"type": "action"
|
||||
"unit": "action"
|
||||
},
|
||||
"range": {
|
||||
"type": "point",
|
||||
@@ -276,7 +276,7 @@
|
||||
"ritual": false,
|
||||
"casting_time": {
|
||||
"amount": 1,
|
||||
"type": "action"
|
||||
"unit": "action"
|
||||
},
|
||||
"range": {
|
||||
"type": "point",
|
||||
@@ -315,7 +315,7 @@
|
||||
"ritual": false,
|
||||
"casting_time": {
|
||||
"amount": 1,
|
||||
"type": "action"
|
||||
"unit": "action"
|
||||
},
|
||||
"range": {
|
||||
"type": "point",
|
||||
@@ -359,7 +359,7 @@
|
||||
"ritual": false,
|
||||
"casting_time": {
|
||||
"amount": 1,
|
||||
"type": "action"
|
||||
"unit": "action"
|
||||
},
|
||||
"range": {
|
||||
"type": "point",
|
||||
@@ -391,5 +391,41 @@
|
||||
"The spell creates more than one beam when you reach higher levels: two beams at 5th level, three beams at 11th level, and four beams at 17th level. You can direct the beams at the same target or at different ones. Make a separate attack roll for each beam."
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Encode Thoughts",
|
||||
"school": "enchantment",
|
||||
"level": 0,
|
||||
"ritual": true,
|
||||
"casting_time": {
|
||||
"amount": 1,
|
||||
"unit": "action"
|
||||
},
|
||||
"range": {
|
||||
"type": "self"
|
||||
},
|
||||
"components": {
|
||||
"verbal": false,
|
||||
"somatic": true,
|
||||
"material": false
|
||||
},
|
||||
"durations": [
|
||||
{
|
||||
"type": "timed",
|
||||
"amount": 8,
|
||||
"unit": "hours"
|
||||
}
|
||||
],
|
||||
"classes": ["wizard"],
|
||||
"sources": [
|
||||
{ "source": "GGR", "page": 47 }
|
||||
],
|
||||
"description": {
|
||||
"entries": [
|
||||
"Putting a finger to your head, you pull a memory, an idea, or a message from your mind and transform it into a tangible string of glowing energy called a thought strand, which persists for the duration or until you cast this spell again. The thought strand appears in an unoccupied space within 5 feet of you as a Tiny, weightless, semisolid object that can be held and carried like a ribbon. It is otherwise stationary.",
|
||||
"If you cast this spell while concentrating on a spell or an ability that allows you to read or manipulate the thoughts of others (such as {@spell detect thoughts} or {@spell modify memory}), you can transform the thoughts or memories you read, rather than your own, into a thought strand.",
|
||||
"Casting this spell while holding a thought strand allows you to instantly receive whatever memory, idea, or message the thought strand contains. (Casting {@spell detect thoughts} on the strand has the same effect.)"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,5 +1,15 @@
|
||||
CREATE TABLE IF NOT EXISTS spells (
|
||||
id INTEGER GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL,
|
||||
school TEXT NOT NULL,
|
||||
level INTEGER NOT NULL,
|
||||
ritual BOOLEAN DEFAULT FALSE,
|
||||
concentration BOOLEAN DEFAULT FALSE,
|
||||
classes TEXT[] NOT NULL,
|
||||
damage_inflict TEXT[] NOT NULL,
|
||||
damage_resist TEXT[] NOT NULL,
|
||||
conditions TEXT[] NOT NULL,
|
||||
saving_throw TEXT[] NOT NULL,
|
||||
attack_type TEXT,
|
||||
data JSONB NOT NULL
|
||||
);
|
||||
@@ -1,4 +1,4 @@
|
||||
// use std::str::FromStr;
|
||||
use std::str::FromStr;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
@@ -17,30 +17,30 @@ pub enum AbilityType {
|
||||
Charisma
|
||||
}
|
||||
|
||||
// impl AbilityType {
|
||||
// pub fn to_string(&self) -> String {
|
||||
// match self {
|
||||
// AbilityType::Strength => "Strength".to_string(),
|
||||
// AbilityType::Dexterity => "Dexterity".to_string(),
|
||||
// AbilityType::Constitution => "Constitution".to_string(),
|
||||
// AbilityType::Intelligence => "Intelligence".to_string(),
|
||||
// AbilityType::Wisdom => "Wisdom".to_string(),
|
||||
// AbilityType::Charisma => "Charisma".to_string()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl AbilityType {
|
||||
pub fn to_string(&self) -> String {
|
||||
match self {
|
||||
AbilityType::Strength => "Strength".to_string(),
|
||||
AbilityType::Dexterity => "Dexterity".to_string(),
|
||||
AbilityType::Constitution => "Constitution".to_string(),
|
||||
AbilityType::Intelligence => "Intelligence".to_string(),
|
||||
AbilityType::Wisdom => "Wisdom".to_string(),
|
||||
AbilityType::Charisma => "Charisma".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl FromStr for AbilityType {
|
||||
// type Err = ();
|
||||
// fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// match s {
|
||||
// "Strength" => Ok(AbilityType::Strength),
|
||||
// "Dexterity" => Ok(AbilityType::Dexterity),
|
||||
// "Constitution" => Ok(AbilityType::Constitution),
|
||||
// "Intelligence" => Ok(AbilityType::Intelligence),
|
||||
// "Wisdom" => Ok(AbilityType::Wisdom),
|
||||
// "Charisma" => Ok(AbilityType::Charisma),
|
||||
// _ => Err(())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl FromStr for AbilityType {
|
||||
type Err = ();
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"Strength" => Ok(AbilityType::Strength),
|
||||
"Dexterity" => Ok(AbilityType::Dexterity),
|
||||
"Constitution" => Ok(AbilityType::Constitution),
|
||||
"Intelligence" => Ok(AbilityType::Intelligence),
|
||||
"Wisdom" => Ok(AbilityType::Wisdom),
|
||||
"Charisma" => Ok(AbilityType::Charisma),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// use std::str::FromStr;
|
||||
use std::str::FromStr;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
||||
@@ -36,48 +36,48 @@ pub enum ConditionType {
|
||||
Unconscious
|
||||
}
|
||||
|
||||
// impl ConditionType {
|
||||
// pub fn to_string(&self) -> String {
|
||||
// match self {
|
||||
// ConditionType::Blinded => "Blinded".to_string(),
|
||||
// ConditionType::Charmed => "Charmed".to_string(),
|
||||
// ConditionType::Deafened => "Deafened".to_string(),
|
||||
// ConditionType::Exhaustion => "Exhaustion".to_string(),
|
||||
// ConditionType::Frightened => "Frightened".to_string(),
|
||||
// ConditionType::Grappled => "Grappled".to_string(),
|
||||
// ConditionType::Incapacitated => "Incapacitated".to_string(),
|
||||
// ConditionType::Invisible => "Invisible".to_string(),
|
||||
// ConditionType::Paralyzed => "Paralyzed".to_string(),
|
||||
// ConditionType::Petrified => "Petrified".to_string(),
|
||||
// ConditionType::Poisoned => "Poisoned".to_string(),
|
||||
// ConditionType::Prone => "Prone".to_string(),
|
||||
// ConditionType::Restrained => "Restrained".to_string(),
|
||||
// ConditionType::Stunned => "Stunned".to_string(),
|
||||
// ConditionType::Unconscious => "Unconscious".to_string()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl ConditionType {
|
||||
pub fn to_string(&self) -> String {
|
||||
match self {
|
||||
ConditionType::Blinded => "Blinded".to_string(),
|
||||
ConditionType::Charmed => "Charmed".to_string(),
|
||||
ConditionType::Deafened => "Deafened".to_string(),
|
||||
ConditionType::Exhaustion => "Exhaustion".to_string(),
|
||||
ConditionType::Frightened => "Frightened".to_string(),
|
||||
ConditionType::Grappled => "Grappled".to_string(),
|
||||
ConditionType::Incapacitated => "Incapacitated".to_string(),
|
||||
ConditionType::Invisible => "Invisible".to_string(),
|
||||
ConditionType::Paralyzed => "Paralyzed".to_string(),
|
||||
ConditionType::Petrified => "Petrified".to_string(),
|
||||
ConditionType::Poisoned => "Poisoned".to_string(),
|
||||
ConditionType::Prone => "Prone".to_string(),
|
||||
ConditionType::Restrained => "Restrained".to_string(),
|
||||
ConditionType::Stunned => "Stunned".to_string(),
|
||||
ConditionType::Unconscious => "Unconscious".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl FromStr for ConditionType {
|
||||
// type Err = ();
|
||||
// fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// match s {
|
||||
// "Blinded" => Ok(ConditionType::Blinded),
|
||||
// "Charmed" => Ok(ConditionType::Charmed),
|
||||
// "Deafened" => Ok(ConditionType::Deafened),
|
||||
// "Exhaustion" => Ok(ConditionType::Exhaustion),
|
||||
// "Frightened" => Ok(ConditionType::Frightened),
|
||||
// "Grappled" => Ok(ConditionType::Grappled),
|
||||
// "Incapacitated" => Ok(ConditionType::Incapacitated),
|
||||
// "Invisible" => Ok(ConditionType::Invisible),
|
||||
// "Paralyzed" => Ok(ConditionType::Paralyzed),
|
||||
// "Petrified" => Ok(ConditionType::Petrified),
|
||||
// "Poisoned" => Ok(ConditionType::Poisoned),
|
||||
// "Prone" => Ok(ConditionType::Prone),
|
||||
// "Restrained" => Ok(ConditionType::Restrained),
|
||||
// "Stunned" => Ok(ConditionType::Stunned),
|
||||
// "Unconscious" => Ok(ConditionType::Unconscious),
|
||||
// _ => Err(())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl FromStr for ConditionType {
|
||||
type Err = ();
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"Blinded" => Ok(ConditionType::Blinded),
|
||||
"Charmed" => Ok(ConditionType::Charmed),
|
||||
"Deafened" => Ok(ConditionType::Deafened),
|
||||
"Exhaustion" => Ok(ConditionType::Exhaustion),
|
||||
"Frightened" => Ok(ConditionType::Frightened),
|
||||
"Grappled" => Ok(ConditionType::Grappled),
|
||||
"Incapacitated" => Ok(ConditionType::Incapacitated),
|
||||
"Invisible" => Ok(ConditionType::Invisible),
|
||||
"Paralyzed" => Ok(ConditionType::Paralyzed),
|
||||
"Petrified" => Ok(ConditionType::Petrified),
|
||||
"Poisoned" => Ok(ConditionType::Poisoned),
|
||||
"Prone" => Ok(ConditionType::Prone),
|
||||
"Restrained" => Ok(ConditionType::Restrained),
|
||||
"Stunned" => Ok(ConditionType::Stunned),
|
||||
"Unconscious" => Ok(ConditionType::Unconscious),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,16 @@ diesel::table! {
|
||||
spells (id) {
|
||||
id -> Integer,
|
||||
name -> Text,
|
||||
school -> Text,
|
||||
level -> Integer,
|
||||
ritual -> Bool,
|
||||
concentration -> Bool,
|
||||
classes -> Array<Text>,
|
||||
damage_inflict -> Array<Text>,
|
||||
damage_resist -> Array<Text>,
|
||||
conditions -> Array<Text>,
|
||||
saving_throw -> Array<Text>,
|
||||
attack_type -> Nullable<Text>,
|
||||
data -> Jsonb
|
||||
}
|
||||
}
|
||||
@@ -3,29 +3,39 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{db::{schema::spells::{self}, classes::AbilityType, conditions::ConditionType}, error_handler::ServiceError};
|
||||
|
||||
use super::{SchoolType, CastingTime, CastingType, SpellAttackType, SpellDamageType, Range, Area, Components, Duration, Source, Description};
|
||||
use super::{SchoolType, CastingTime, CastingType, SpellAttackType, SpellDamageType, Range, Area, Components, Duration, Source, Description, DurationType};
|
||||
|
||||
#[derive(Queryable, QueryableByName)]
|
||||
#[diesel(table_name = spells)]
|
||||
pub struct QuerySpell {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub school: String,
|
||||
pub level: i32,
|
||||
pub ritual: bool,
|
||||
pub concentration: bool,
|
||||
pub classes: Vec<String>,
|
||||
pub damage_inflict: Vec<String>,
|
||||
pub damage_resist: Vec<String>,
|
||||
pub conditions: Vec<String>,
|
||||
pub saving_throw: Vec<String>,
|
||||
pub attack_type: Option<String>,
|
||||
pub data: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct QueryFilters {
|
||||
pub by_name: Option<String>,
|
||||
pub by_schools: Option<Vec<SchoolType>>,
|
||||
pub by_schools: Option<Vec<String>>,
|
||||
pub by_levels: Option<Vec<i32>>,
|
||||
pub by_ritual: Option<bool>,
|
||||
pub by_concentration: Option<bool>,
|
||||
pub by_classes: Option<Vec<String>>,
|
||||
pub by_damage_inflict: Option<Vec<SpellDamageType>>,
|
||||
pub by_damage_resist: Option<Vec<SpellDamageType>>,
|
||||
pub by_conditions: Option<Vec<ConditionType>>,
|
||||
pub by_saving_throw: Option<Vec<AbilityType>>,
|
||||
pub by_attack_type: Option<SpellAttackType>,
|
||||
pub by_damage_inflict: Option<Vec<String>>,
|
||||
pub by_damage_resist: Option<Vec<String>>,
|
||||
pub by_conditions: Option<Vec<String>>,
|
||||
pub by_saving_throw: Option<Vec<String>>,
|
||||
pub by_attack_type: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for QueryFilters {
|
||||
@@ -53,15 +63,85 @@ impl QuerySpell {
|
||||
// Limit query to page and limit
|
||||
let offset = (page - 1) * limit;
|
||||
query = query.offset(offset as i64);
|
||||
// Apply filters
|
||||
if let Some(name) = filters.by_name.to_owned() {
|
||||
if let Some(name) = &filters.by_name {
|
||||
query = query.filter(spells::name.ilike(format!("%{}%", name)));
|
||||
}
|
||||
if let Some(schools) = &filters.by_schools {
|
||||
query = query.filter(spells::school.eq_any(schools.iter().map(|school| school.to_string()).collect::<Vec<String>>()));
|
||||
}
|
||||
if let Some(levels) = &filters.by_levels {
|
||||
query = query.filter(spells::level.eq_any(levels));
|
||||
}
|
||||
if let Some(ritual) = filters.by_ritual {
|
||||
query = query.filter(spells::ritual.eq(ritual));
|
||||
}
|
||||
if let Some(concentration) = filters.by_concentration {
|
||||
query = query.filter(spells::concentration.eq(concentration));
|
||||
}
|
||||
if let Some(classes) = &filters.by_classes {
|
||||
query = query.filter(spells::classes.overlaps_with(classes));
|
||||
}
|
||||
if let Some(damage_inflict) = &filters.by_damage_inflict {
|
||||
query = query.filter(spells::damage_inflict.overlaps_with(damage_inflict.iter().map(|damage_inflict| damage_inflict.to_string()).collect::<Vec<String>>()));
|
||||
}
|
||||
if let Some(damage_resist) = &filters.by_damage_resist {
|
||||
query = query.filter(spells::damage_resist.overlaps_with(damage_resist.iter().map(|damage_resist| damage_resist.to_string()).collect::<Vec<String>>()));
|
||||
}
|
||||
if let Some(conditions) = &filters.by_conditions {
|
||||
query = query.filter(spells::conditions.overlaps_with(conditions.iter().map(|condition| condition.to_string()).collect::<Vec<String>>()));
|
||||
}
|
||||
if let Some(saving_throw) = &filters.by_saving_throw {
|
||||
query = query.filter(spells::saving_throw.overlaps_with(saving_throw.iter().map(|saving_throw| saving_throw.to_string()).collect::<Vec<String>>()));
|
||||
}
|
||||
if let Some(attack_type) = &filters.by_attack_type {
|
||||
query = query.filter(spells::attack_type.eq(attack_type.to_string()));
|
||||
}
|
||||
|
||||
let spells = query.load::<QuerySpell>(&mut conn)?;
|
||||
Ok(spells)
|
||||
}
|
||||
|
||||
pub fn get_count(filters: &QueryFilters) -> Result<i64, ServiceError> {
|
||||
let mut conn = crate::db::connection()?;
|
||||
let mut query = spells::table.count().into_boxed();
|
||||
if let Some(name) = &filters.by_name {
|
||||
query = query.filter(spells::name.ilike(format!("%{}%", name)));
|
||||
}
|
||||
if let Some(schools) = &filters.by_schools {
|
||||
query = query.filter(spells::school.eq_any(schools.iter().map(|school| school.to_string()).collect::<Vec<String>>()));
|
||||
}
|
||||
if let Some(levels) = &filters.by_levels {
|
||||
query = query.filter(spells::level.eq_any(levels));
|
||||
}
|
||||
if let Some(ritual) = filters.by_ritual {
|
||||
query = query.filter(spells::ritual.eq(ritual));
|
||||
}
|
||||
if let Some(concentration) = filters.by_concentration {
|
||||
query = query.filter(spells::concentration.eq(concentration));
|
||||
}
|
||||
if let Some(classes) = &filters.by_classes {
|
||||
query = query.filter(spells::classes.overlaps_with(classes));
|
||||
}
|
||||
if let Some(damage_inflict) = &filters.by_damage_inflict {
|
||||
query = query.filter(spells::damage_inflict.overlaps_with(damage_inflict.iter().map(|damage_inflict| damage_inflict.to_string()).collect::<Vec<String>>()));
|
||||
}
|
||||
if let Some(damage_resist) = &filters.by_damage_resist {
|
||||
query = query.filter(spells::damage_resist.overlaps_with(damage_resist.iter().map(|damage_resist| damage_resist.to_string()).collect::<Vec<String>>()));
|
||||
}
|
||||
if let Some(conditions) = &filters.by_conditions {
|
||||
query = query.filter(spells::conditions.overlaps_with(conditions.iter().map(|condition| condition.to_string()).collect::<Vec<String>>()));
|
||||
}
|
||||
if let Some(saving_throw) = &filters.by_saving_throw {
|
||||
query = query.filter(spells::saving_throw.overlaps_with(saving_throw.iter().map(|saving_throw| saving_throw.to_string()).collect::<Vec<String>>()));
|
||||
}
|
||||
if let Some(attack_type) = &filters.by_attack_type {
|
||||
query = query.filter(spells::attack_type.eq(attack_type.to_string()));
|
||||
}
|
||||
|
||||
let count = query.get_result(&mut conn)?;
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
pub fn get_by_id(id: i32) -> Result<Self, ServiceError> {
|
||||
let mut conn = crate::db::connection()?;
|
||||
let spell = spells::table
|
||||
@@ -70,17 +150,6 @@ impl QuerySpell {
|
||||
Ok(spell)
|
||||
}
|
||||
|
||||
pub fn get_count(filters: &QueryFilters) -> Result<i64, ServiceError> {
|
||||
let mut conn = crate::db::connection()?;
|
||||
let mut query = spells::table.count().into_boxed();
|
||||
if let Some(name) = filters.by_name.to_owned() {
|
||||
query = query.filter(spells::name.ilike(format!("%{}%", name)));
|
||||
}
|
||||
|
||||
let count = query.get_result(&mut conn)?;
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
pub fn delete(id: i32) -> Result<Self, ServiceError> {
|
||||
let mut conn = crate::db::connection()?;
|
||||
let spell = diesel::delete(spells::table.filter(spells::id.eq(id))).get_result(&mut conn)?;
|
||||
@@ -92,6 +161,16 @@ impl QuerySpell {
|
||||
#[diesel(table_name = spells)]
|
||||
pub struct InsertSpell {
|
||||
pub name: String,
|
||||
pub school: String,
|
||||
pub level: i32,
|
||||
pub ritual: bool,
|
||||
pub concentration: bool,
|
||||
pub classes: Vec<String>,
|
||||
pub damage_inflict: Vec<String>,
|
||||
pub damage_resist: Vec<String>,
|
||||
pub conditions: Vec<String>,
|
||||
pub saving_throw: Vec<String>,
|
||||
pub attack_type: Option<String>,
|
||||
pub data: serde_json::Value
|
||||
}
|
||||
|
||||
@@ -174,13 +253,38 @@ impl Into<InsertSpell> for Spell {
|
||||
fn into(self) -> InsertSpell {
|
||||
return InsertSpell {
|
||||
name: self.name.to_string(),
|
||||
school: self.school.to_string(),
|
||||
level: self.level,
|
||||
ritual: self.ritual,
|
||||
concentration: self.durations.iter().any(|duration| match duration.duration_type {
|
||||
DurationType::Concentration => true,
|
||||
_ => false
|
||||
}),
|
||||
classes: self.classes.iter().map(|class| class.to_string()).collect::<Vec<String>>(),
|
||||
damage_inflict: match &self.damage_inflict {
|
||||
Some(damage_inflict) => damage_inflict.iter().map(|damage_inflict| damage_inflict.to_string()).collect(),
|
||||
None => vec![]
|
||||
},
|
||||
damage_resist: match &self.damage_resist {
|
||||
Some(damage_resist) => damage_resist.iter().map(|damage_resist| damage_resist.to_string()).collect(),
|
||||
None => vec![]
|
||||
},
|
||||
conditions: match &self.conditions {
|
||||
Some(conditions) => conditions.iter().map(|condition| condition.to_string()).collect(),
|
||||
None => vec![]
|
||||
},
|
||||
saving_throw: match &self.saving_throw {
|
||||
Some(saving_throw) => saving_throw.iter().map(|saving_throw| saving_throw.to_string()).collect(),
|
||||
None => vec![]
|
||||
},
|
||||
attack_type: self.attack_type.as_ref().map(|attack_type| attack_type.to_string()),
|
||||
data: match serde_json::to_value(&self) {
|
||||
Ok(data) => data,
|
||||
Err(err) => {
|
||||
log::error!("Failed to serialize spell description: {}", err);
|
||||
log::error!("Failed to serialize spell: {}", err);
|
||||
serde_json::Value::Null
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use actix_web::{get, post, put, delete, web, HttpResponse, HttpRequest, ResponseError};
|
||||
use log::error;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use crate::{db::{spells::{QuerySpell, QueryFilters}, GetResponse, Metadata}, error_handler::ServiceError};
|
||||
@@ -8,6 +9,16 @@ use super::{Spell, InsertSpell};
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct GetAllParams {
|
||||
name: Option<String>,
|
||||
schools: Option<String>,
|
||||
levels: Option<String>,
|
||||
ritual: Option<bool>,
|
||||
concentration: Option<bool>,
|
||||
classes: Option<String>,
|
||||
damage_inflict: Option<String>,
|
||||
damage_resist: Option<String>,
|
||||
conditions: Option<String>,
|
||||
saving_throw: Option<String>,
|
||||
attack_type: Option<String>,
|
||||
limit: Option<i32>,
|
||||
page: Option<i32>,
|
||||
}
|
||||
@@ -23,6 +34,43 @@ async fn get_all(req: HttpRequest) -> HttpResponse {
|
||||
};
|
||||
let mut filters = QueryFilters::default();
|
||||
filters.by_name = params.name.clone();
|
||||
filters.by_schools = match ¶ms.schools {
|
||||
Some(schools) => Some(schools.split(",").map(|s| s.to_string()).collect()),
|
||||
None => None
|
||||
};
|
||||
filters.by_levels = match ¶ms.levels {
|
||||
Some(levels) => Some(levels.split(",").map(|s| match s.to_string().parse::<i32>() {
|
||||
Ok(level) => level,
|
||||
Err(_) => 0
|
||||
}).collect()),
|
||||
None => None
|
||||
};
|
||||
filters.by_ritual = params.ritual;
|
||||
filters.by_concentration = params.concentration;
|
||||
filters.by_classes = match ¶ms.classes {
|
||||
Some(classes) => Some(classes.split(",").map(|s| s.to_string()).collect()),
|
||||
None => None
|
||||
};
|
||||
filters.by_damage_inflict = match ¶ms.damage_inflict {
|
||||
Some(damage_inflict) => Some(damage_inflict.split(",").map(|s| s.to_string()).collect()),
|
||||
None => None
|
||||
};
|
||||
filters.by_damage_resist = match ¶ms.damage_resist {
|
||||
Some(damage_resist) => Some(damage_resist.split(",").map(|s| s.to_string()).collect()),
|
||||
None => None
|
||||
};
|
||||
filters.by_conditions = match ¶ms.conditions {
|
||||
Some(conditions) => Some(conditions.split(",").map(|s| s.to_string()).collect()),
|
||||
None => None
|
||||
};
|
||||
filters.by_saving_throw = match ¶ms.saving_throw {
|
||||
Some(saving_throw) => Some(saving_throw.split(",").map(|s| s.to_string()).collect()),
|
||||
None => None
|
||||
};
|
||||
filters.by_attack_type = match ¶ms.attack_type {
|
||||
Some(attack_type) => Some(attack_type.split(",").map(|s| s.to_string()).collect()),
|
||||
None => None
|
||||
};
|
||||
// Limit must be between 1 and 100
|
||||
let limit = std::cmp::min(std::cmp::max(params.limit.unwrap_or(20), 1), 100);
|
||||
let total_count = QuerySpell::get_count(&filters).unwrap();
|
||||
@@ -46,7 +94,10 @@ async fn get_all(req: HttpRequest) -> HttpResponse {
|
||||
})
|
||||
})
|
||||
},
|
||||
Err(err) => ResponseError::error_response(&err)
|
||||
Err(err) => {
|
||||
error!("{:?}", err.message);
|
||||
ResponseError::error_response(&err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +115,10 @@ async fn get_by_id(id: web::Path<String>) -> HttpResponse {
|
||||
data: Spell::from(spell),
|
||||
metadata: None
|
||||
}),
|
||||
Err(err) => ResponseError::error_response(&err)
|
||||
Err(err) => {
|
||||
error!("{:?}", err.message);
|
||||
ResponseError::error_response(&err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +126,10 @@ async fn get_by_id(id: web::Path<String>) -> HttpResponse {
|
||||
async fn create(spell: web::Json<Spell>) -> HttpResponse {
|
||||
match InsertSpell::insert(spell.into_inner().into()) {
|
||||
Ok(spell) => HttpResponse::Created().json(Spell::from(spell)),
|
||||
Err(err) => ResponseError::error_response(&err)
|
||||
Err(err) => {
|
||||
error!("{:?}", err.message);
|
||||
ResponseError::error_response(&err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +144,10 @@ async fn update(id: web::Path<String>, spell: web::Json<Spell>) -> HttpResponse
|
||||
};
|
||||
match web::block(move || InsertSpell::update(id, spell.into_inner().into())).await.unwrap() {
|
||||
Ok(spell) => HttpResponse::Ok().json(Spell::from(spell)),
|
||||
Err(err) => ResponseError::error_response(&err)
|
||||
Err(err) => {
|
||||
error!("{:?}", err.message);
|
||||
ResponseError::error_response(&err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +162,10 @@ async fn delete(id: web::Path<String>) -> HttpResponse {
|
||||
};
|
||||
match web::block(move || QuerySpell::delete(id)).await.unwrap() {
|
||||
Ok(spell) => HttpResponse::Ok().json(Spell::from(spell)),
|
||||
Err(err) => ResponseError::error_response(&err)
|
||||
Err(err) => {
|
||||
error!("{:?}", err.message);
|
||||
ResponseError::error_response(&err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// use std::str::FromStr;
|
||||
use std::str::FromStr;
|
||||
use serde::{Deserialize, Serialize, ser::SerializeMap};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
@@ -21,43 +21,43 @@ pub enum SchoolType {
|
||||
Transmutation
|
||||
}
|
||||
|
||||
// impl SchoolType {
|
||||
// pub fn to_string(&self) -> String {
|
||||
// match self {
|
||||
// SchoolType::Abjuration => "abjuration".to_string(),
|
||||
// SchoolType::Conjuration => "conjuration".to_string(),
|
||||
// SchoolType::Divination => "divination".to_string(),
|
||||
// SchoolType::Enchantment => "enchantment".to_string(),
|
||||
// SchoolType::Evocation => "evocation".to_string(),
|
||||
// SchoolType::Illusion => "illusion".to_string(),
|
||||
// SchoolType::Necromancy => "necromancy".to_string(),
|
||||
// SchoolType::Transmutation => "transmutation".to_string()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl SchoolType {
|
||||
pub fn to_string(&self) -> String {
|
||||
match self {
|
||||
SchoolType::Abjuration => "abjuration".to_string(),
|
||||
SchoolType::Conjuration => "conjuration".to_string(),
|
||||
SchoolType::Divination => "divination".to_string(),
|
||||
SchoolType::Enchantment => "enchantment".to_string(),
|
||||
SchoolType::Evocation => "evocation".to_string(),
|
||||
SchoolType::Illusion => "illusion".to_string(),
|
||||
SchoolType::Necromancy => "necromancy".to_string(),
|
||||
SchoolType::Transmutation => "transmutation".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl FromStr for SchoolType {
|
||||
// type Err = ();
|
||||
impl FromStr for SchoolType {
|
||||
type Err = ();
|
||||
|
||||
// fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// match s {
|
||||
// "abjuration" => Ok(SchoolType::Abjuration),
|
||||
// "conjuration" => Ok(SchoolType::Conjuration),
|
||||
// "divination" => Ok(SchoolType::Divination),
|
||||
// "enchantment" => Ok(SchoolType::Enchantment),
|
||||
// "evocation" => Ok(SchoolType::Evocation),
|
||||
// "illusion" => Ok(SchoolType::Illusion),
|
||||
// "necromancy" => Ok(SchoolType::Necromancy),
|
||||
// "transmutation" => Ok(SchoolType::Transmutation),
|
||||
// _ => Err(())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"abjuration" => Ok(SchoolType::Abjuration),
|
||||
"conjuration" => Ok(SchoolType::Conjuration),
|
||||
"divination" => Ok(SchoolType::Divination),
|
||||
"enchantment" => Ok(SchoolType::Enchantment),
|
||||
"evocation" => Ok(SchoolType::Evocation),
|
||||
"illusion" => Ok(SchoolType::Illusion),
|
||||
"necromancy" => Ok(SchoolType::Necromancy),
|
||||
"transmutation" => Ok(SchoolType::Transmutation),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CastingTime {
|
||||
pub amount: i32,
|
||||
#[serde(rename = "type")]
|
||||
#[serde(rename = "unit")]
|
||||
pub casting_type: CastingType
|
||||
}
|
||||
|
||||
@@ -110,26 +110,26 @@ pub enum SpellAttackType {
|
||||
Ranged,
|
||||
}
|
||||
|
||||
// impl SpellAttackType {
|
||||
// pub fn to_string(&self) -> String {
|
||||
// match self {
|
||||
// SpellAttackType::Melee => "melee".to_string(),
|
||||
// SpellAttackType::Ranged => "ranged".to_string()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl SpellAttackType {
|
||||
pub fn to_string(&self) -> String {
|
||||
match self {
|
||||
SpellAttackType::Melee => "melee".to_string(),
|
||||
SpellAttackType::Ranged => "ranged".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl FromStr for SpellAttackType {
|
||||
// type Err = ();
|
||||
impl FromStr for SpellAttackType {
|
||||
type Err = ();
|
||||
|
||||
// fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// match s {
|
||||
// "melee" => Ok(SpellAttackType::Melee),
|
||||
// "ranged" => Ok(SpellAttackType::Ranged),
|
||||
// _ => Err(())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"melee" => Ok(SpellAttackType::Melee),
|
||||
"ranged" => Ok(SpellAttackType::Ranged),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum SpellDamageType {
|
||||
@@ -161,48 +161,48 @@ pub enum SpellDamageType {
|
||||
Thunder
|
||||
}
|
||||
|
||||
// impl SpellDamageType {
|
||||
// pub fn to_string(&self) -> String {
|
||||
// match self {
|
||||
// SpellDamageType::Acid => "acid".to_string(),
|
||||
// SpellDamageType::Bludgeoning => "bludgeoning".to_string(),
|
||||
// SpellDamageType::Cold => "cold".to_string(),
|
||||
// SpellDamageType::Fire => "fire".to_string(),
|
||||
// SpellDamageType::Force => "force".to_string(),
|
||||
// SpellDamageType::Lightning => "lightning".to_string(),
|
||||
// SpellDamageType::Necrotic => "necrotic".to_string(),
|
||||
// SpellDamageType::Piercing => "piercing".to_string(),
|
||||
// SpellDamageType::Poison => "poison".to_string(),
|
||||
// SpellDamageType::Psychic => "psychic".to_string(),
|
||||
// SpellDamageType::Radiant => "radiant".to_string(),
|
||||
// SpellDamageType::Slashing => "slashing".to_string(),
|
||||
// SpellDamageType::Thunder => "thunder".to_string()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl SpellDamageType {
|
||||
pub fn to_string(&self) -> String {
|
||||
match self {
|
||||
SpellDamageType::Acid => "acid".to_string(),
|
||||
SpellDamageType::Bludgeoning => "bludgeoning".to_string(),
|
||||
SpellDamageType::Cold => "cold".to_string(),
|
||||
SpellDamageType::Fire => "fire".to_string(),
|
||||
SpellDamageType::Force => "force".to_string(),
|
||||
SpellDamageType::Lightning => "lightning".to_string(),
|
||||
SpellDamageType::Necrotic => "necrotic".to_string(),
|
||||
SpellDamageType::Piercing => "piercing".to_string(),
|
||||
SpellDamageType::Poison => "poison".to_string(),
|
||||
SpellDamageType::Psychic => "psychic".to_string(),
|
||||
SpellDamageType::Radiant => "radiant".to_string(),
|
||||
SpellDamageType::Slashing => "slashing".to_string(),
|
||||
SpellDamageType::Thunder => "thunder".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl FromStr for SpellDamageType {
|
||||
// type Err = ();
|
||||
impl FromStr for SpellDamageType {
|
||||
type Err = ();
|
||||
|
||||
// fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// match s {
|
||||
// "acid" => Ok(SpellDamageType::Acid),
|
||||
// "bludgeoning" => Ok(SpellDamageType::Bludgeoning),
|
||||
// "cold" => Ok(SpellDamageType::Cold),
|
||||
// "fire" => Ok(SpellDamageType::Fire),
|
||||
// "force" => Ok(SpellDamageType::Force),
|
||||
// "lightning" => Ok(SpellDamageType::Lightning),
|
||||
// "necrotic" => Ok(SpellDamageType::Necrotic),
|
||||
// "piercing" => Ok(SpellDamageType::Piercing),
|
||||
// "poison" => Ok(SpellDamageType::Poison),
|
||||
// "psychic" => Ok(SpellDamageType::Psychic),
|
||||
// "radiant" => Ok(SpellDamageType::Radiant),
|
||||
// "slashing" => Ok(SpellDamageType::Slashing),
|
||||
// "thunder" => Ok(SpellDamageType::Thunder),
|
||||
// _ => Err(())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"acid" => Ok(SpellDamageType::Acid),
|
||||
"bludgeoning" => Ok(SpellDamageType::Bludgeoning),
|
||||
"cold" => Ok(SpellDamageType::Cold),
|
||||
"fire" => Ok(SpellDamageType::Fire),
|
||||
"force" => Ok(SpellDamageType::Force),
|
||||
"lightning" => Ok(SpellDamageType::Lightning),
|
||||
"necrotic" => Ok(SpellDamageType::Necrotic),
|
||||
"piercing" => Ok(SpellDamageType::Piercing),
|
||||
"poison" => Ok(SpellDamageType::Poison),
|
||||
"psychic" => Ok(SpellDamageType::Psychic),
|
||||
"radiant" => Ok(SpellDamageType::Radiant),
|
||||
"slashing" => Ok(SpellDamageType::Slashing),
|
||||
"thunder" => Ok(SpellDamageType::Thunder),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Range {
|
||||
|
||||
Reference in New Issue
Block a user