diff --git a/Cargo.toml b/Cargo.toml index e097691..c4aeeb6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ build = "build/main.rs" unsafe_code = "forbid" [dependencies] -actix-web = "4.5.1" +actix-web = "4.6.0" actix-cors = "0.7.0" actix-web-validator = "5.0.1" # Cannot be updated until actix-web updates validator dependency diff --git a/build/creature_core_db_init.rs b/build/creature_core_db_init.rs index 700588d..5329bb2 100644 --- a/build/creature_core_db_init.rs +++ b/build/creature_core_db_init.rs @@ -22,7 +22,8 @@ pub async fn create_creature_core_table(conn: &Pool) -> Result<()> { family TEXT NOT NULL DEFAULT '-', license TEXT NOT NULL DEFAULT '', source TEXT NOT NULL DEFAULT '', - remaster BOOL NOT NULL DEFAULT 0 + remaster BOOL NOT NULL DEFAULT 0, + alignment TEXT NOT NULL DEFAULT NO )" ) .execute(conn) diff --git a/src/db/cr_core_initializer.rs b/src/db/cr_core_initializer.rs index 495d911..5852e3e 100644 --- a/src/db/cr_core_initializer.rs +++ b/src/db/cr_core_initializer.rs @@ -1,8 +1,9 @@ use crate::db::data_providers::fetcher::{ fetch_creature_combat_data, fetch_creature_extra_data, fetch_creature_scales, - fetch_creature_spell_caster_data, + fetch_creature_spell_caster_data, fetch_creature_traits, }; use crate::models::creature_component::creature_core::EssentialData; +use crate::models::creature_metadata::alignment_enum::AlignmentEnum; use crate::models::creature_metadata::creature_role::CreatureRoleEnum; use crate::models::creature_metadata::rarity_enum::RarityEnum; use crate::models::creature_metadata::size_enum::SizeEnum; @@ -21,6 +22,9 @@ pub async fn update_creature_core_table(conn: &Pool) -> Result<()> { }; let scales = fetch_creature_scales(conn).await?; for cr in get_creatures_raw_essential_data(conn, &pagination).await? { + let traits = fetch_creature_traits(conn, cr.id).await?; + let alignment = AlignmentEnum::from((&traits, cr.remaster)); + update_alignment_column_value(conn, alignment.to_string(), cr.id).await?; let essential_data = EssentialData { id: cr.id, aon_id: cr.aon_id, @@ -34,6 +38,7 @@ pub async fn update_creature_core_table(conn: &Pool) -> Result<()> { remaster: cr.remaster, source: cr.source, cr_type: CreatureTypeEnum::from(cr.cr_type), + alignment, }; let extra_data = fetch_creature_extra_data(conn, essential_data.id).await?; let combat_data = fetch_creature_combat_data(conn, essential_data.id).await?; @@ -45,6 +50,7 @@ pub async fn update_creature_core_table(conn: &Pool) -> Result<()> { &spell_caster_data, &scales, ); + for (curr_role, curr_percentage) in roles { update_role_column_value(conn, curr_role, curr_percentage, essential_data.id).await?; } @@ -117,6 +123,24 @@ async fn update_role_column_value( Ok(()) } +async fn update_alignment_column_value( + conn: &Pool, + alignment: String, + creature_id: i64, +) -> Result<()> { + let x = sqlx::query!( + "UPDATE CREATURE_CORE SET alignment = ? WHERE id = ?", + alignment, + creature_id + ) + .execute(conn) + .await?; + if x.rows_affected() < 1 { + bail!("Error encountered with creature id: {creature_id}. Could not update alignment: {alignment}") + } + Ok(()) +} + async fn get_creatures_raw_essential_data( conn: &Pool, paginated_request: &PaginatedRequest, diff --git a/src/db/data_providers/fetcher.rs b/src/db/data_providers/fetcher.rs index 1905cbd..b25159e 100644 --- a/src/db/data_providers/fetcher.rs +++ b/src/db/data_providers/fetcher.rs @@ -1,14 +1,12 @@ use crate::db::data_providers::raw_query_builder::prepare_filtered_get_creatures_core; use crate::models::creature::Creature; use crate::models::creature_component::creature_combat::{CreatureCombatData, SavingThrows}; -use crate::models::creature_component::creature_core::{ - CreatureCoreData, DerivedData, EssentialData, -}; +use crate::models::creature_component::creature_core::CreatureCoreData; use crate::models::creature_component::creature_extra::{AbilityScores, CreatureExtraData}; use crate::models::creature_component::creature_spell_caster::CreatureSpellCasterData; use crate::models::creature_component::creature_variant::CreatureVariantData; use crate::models::creature_filter_enum::CreatureFilter; -use crate::models::creature_metadata::alignment_enum::{AlignmentEnum, ALIGNMENT_TRAITS}; +use crate::models::creature_metadata::alignment_enum::ALIGNMENT_TRAITS; use crate::models::creature_metadata::variant_enum::CreatureVariant; use crate::models::db::raw_immunity::RawImmunity; use crate::models::db::raw_language::RawLanguage; @@ -193,12 +191,12 @@ async fn fetch_creature_perception_detail( ) } -async fn fetch_creature_traits(conn: &Pool, creature_id: i64) -> Result> { +pub async fn fetch_creature_traits(conn: &Pool, creature_id: i64) -> Result> { Ok(sqlx::query_as!( RawTrait, "SELECT * FROM TRAIT_TABLE INTERSECT SELECT trait_id FROM TRAIT_CREATURE_ASSOCIATION_TABLE WHERE creature_id == ($1)", creature_id - ).fetch_all(conn).await?) + ).fetch_all(conn).await?.iter().map(|x| x.name.clone()).collect()) } async fn fetch_creature_weapons(conn: &Pool, creature_id: i64) -> Result> { @@ -256,47 +254,19 @@ async fn fetch_creature_core_data( conn: &Pool, creature_id: i64, ) -> Result { - let essential = fetch_creature_essential_data(conn, creature_id).await?; - let derived = fetch_creature_derived_data(conn, creature_id).await?; - let traits = fetch_creature_traits(conn, creature_id) + let mut cr_core: CreatureCoreData = + sqlx::query_as("SELECT * FROM CREATURE_CORE WHERE id = ? ORDER BY name LIMIT 1") + .bind(creature_id) + .fetch_one(conn) + .await?; + cr_core.traits = fetch_creature_traits(conn, creature_id) .await - .unwrap_or_default(); - let is_remaster = essential.remaster; - Ok(CreatureCoreData { - essential, - derived, - traits: traits.iter().map(|x| x.name.clone()).collect(), - alignment: AlignmentEnum::from((&traits, is_remaster)), - }) -} - -async fn fetch_creature_essential_data( - conn: &Pool, - creature_id: i64, -) -> Result { - Ok(sqlx::query_as!( - EssentialData, - "SELECT id, aon_id, name, hp, level, size, family, rarity, - license, remaster, source, cr_type - FROM CREATURE_CORE WHERE id = ? ORDER BY name LIMIT 1", - creature_id, - ) - .fetch_one(conn) - .await?) -} - -async fn fetch_creature_derived_data(conn: &Pool, creature_id: i64) -> Result { - Ok(sqlx::query_as!( - DerivedData, - "SELECT - archive_link, is_melee, is_ranged, is_spell_caster, brute_percentage, - magical_striker_percentage, skill_paragon_percentage, skirmisher_percentage, - sniper_percentage, soldier_percentage, spell_caster_percentage - FROM CREATURE_CORE WHERE id = ? ORDER BY name LIMIT 1", - creature_id, - ) - .fetch_one(conn) - .await?) + .unwrap_or_default() + .iter() + .filter(|x| !ALIGNMENT_TRAITS.contains(&&*x.as_str().to_uppercase())) + .cloned() + .collect(); + Ok(cr_core) } async fn update_creatures_core_with_traits( @@ -304,16 +274,13 @@ async fn update_creatures_core_with_traits( mut creature_core_data: Vec, ) -> Vec { for core in &mut creature_core_data { - let traits = fetch_creature_traits(conn, core.essential.id) + core.traits = fetch_creature_traits(conn, core.essential.id) .await - .unwrap_or_default(); - let is_remaster = core.essential.remaster; - core.traits = traits + .unwrap_or_default() .iter() - .filter(|x| !ALIGNMENT_TRAITS.contains(&&*x.name.as_str().to_uppercase())) - .map(|x| x.name.clone()) + .filter(|x| !ALIGNMENT_TRAITS.contains(&&*x.as_str().to_uppercase())) + .cloned() .collect(); - core.alignment = AlignmentEnum::from((&traits, is_remaster)); } creature_core_data } diff --git a/src/db/data_providers/raw_query_builder.rs b/src/db/data_providers/raw_query_builder.rs index ccf5ae0..e2415a3 100644 --- a/src/db/data_providers/raw_query_builder.rs +++ b/src/db/data_providers/raw_query_builder.rs @@ -11,6 +11,7 @@ pub fn prepare_filtered_get_creatures_core( for (key, value) in key_value_filters { match key { CreatureFilter::Level + | CreatureFilter::PathfinderVersion | CreatureFilter::Melee | CreatureFilter::Ranged | CreatureFilter::SpellCaster => { @@ -22,6 +23,7 @@ pub fn prepare_filtered_get_creatures_core( ) } CreatureFilter::Family + | CreatureFilter::Alignment | CreatureFilter::Size | CreatureFilter::Rarity | CreatureFilter::CreatureTypes => { @@ -33,18 +35,23 @@ pub fn prepare_filtered_get_creatures_core( ) } CreatureFilter::Traits => trait_query.push_str(prepare_trait_filter(value).as_str()), - CreatureFilter::CreatureRoles => simple_core_query - .push_str(prepare_bounded_check(value, 0, ACCURACY_THRESHOLD).as_str()), + CreatureFilter::CreatureRoles => { + if !simple_core_query.is_empty() { + simple_core_query.push_str(" AND ") + } + simple_core_query + .push_str(prepare_bounded_check(value, ACCURACY_THRESHOLD, 100).as_str()) + } } } let mut where_query = simple_core_query.to_string(); if !trait_query.is_empty() { - where_query.push_str(format!("AND id IN ({trait_query})").as_str()); - }; + where_query.push_str(format!(" AND id IN ({trait_query}) GROUP BY cc.id").as_str()) + } if !where_query.is_empty() { where_query = format!("WHERE {where_query}"); } - let query = format!("SELECT * FROM CREATURE_CORE {where_query} ORDER BY RANDOM() LIMIT 20"); + let query = format!("SELECT * FROM CREATURE_CORE cc {where_query} ORDER BY RANDOM() LIMIT 20"); debug!("{}", query); query } @@ -57,12 +64,9 @@ fn prepare_bounded_check( upper_bound: i64, ) -> String { let mut bounded_query = String::new(); - if column_names.is_empty() { - return bounded_query; - } for column in column_names { if !bounded_query.is_empty() { - bounded_query.push_str(" AND "); + bounded_query.push_str(" OR "); } bounded_query.push_str( format!("({column} >= {lower_bound} AND {column} <= {upper_bound})").as_str(), @@ -84,13 +88,15 @@ fn prepare_trait_filter(column_values: &HashSet) -> String { if !in_string.is_empty() { let select_query = "SELECT tcat.creature_id FROM TRAIT_CREATURE_ASSOCIATION_TABLE"; let inner_query = format!("SELECT * FROM TRAIT_TABLE tt WHERE {in_string}"); - return format!("{select_query} tcat RIGHT JOIN ({inner_query}) jt ON tcat.trait_id = jt.name GROUP BY tcat.creature_id"); + return format!( + "{select_query} tcat RIGHT JOIN ({inner_query}) jt ON tcat.trait_id = jt.name" + ); } in_string } /// Prepares an 'in' statement in the following format. Assuming a string value -/// "field in ('el1', 'el2', 'el3')" +/// "UPPER(field) in (UPPER('el1'), UPPER('el2'), UPPER('el3'))" fn prepare_in_statement_for_string_type( column_name: &str, column_values: &HashSet, diff --git a/src/db/proxy.rs b/src/db/proxy.rs index 35689a8..221566a 100644 --- a/src/db/proxy.rs +++ b/src/db/proxy.rs @@ -75,10 +75,9 @@ pub async fn get_creatures_passing_all_filters( fetch_elite: bool, ) -> Result> { let mut creature_vec = Vec::new(); - let empty_set = HashSet::new(); let level_vec = key_value_filters .get(&CreatureFilter::Level) - .unwrap_or(&empty_set) + .unwrap_or(&HashSet::new()) .clone(); let modified_filters = prepare_filters_for_db_communication(key_value_filters, fetch_weak, fetch_elite); diff --git a/src/models/creature.rs b/src/models/creature.rs index 17a7fbb..b3291b4 100644 --- a/src/models/creature.rs +++ b/src/models/creature.rs @@ -5,6 +5,7 @@ use crate::models::creature_component::creature_spell_caster::CreatureSpellCaste use crate::models::creature_component::creature_variant::CreatureVariantData; use crate::models::creature_metadata::creature_role::CreatureRoleEnum; use crate::models::creature_metadata::variant_enum::CreatureVariant; +use crate::models::pf_version_enum::PathfinderVersionEnum; use crate::models::routers_validator_structs::FieldFilters; use serde::{Deserialize, Serialize}; @@ -101,10 +102,9 @@ impl Creature { .size_filter .as_ref() .map_or(true, |size| self.core_data.essential.size == *size); - let alignment_pass = filters - .alignment_filter - .as_ref() - .map_or(true, |alignment| self.core_data.alignment == *alignment); + let alignment_pass = filters.alignment_filter.as_ref().map_or(true, |alignment| { + self.core_data.essential.alignment == *alignment + }); let is_melee_pass = filters .is_melee_filter .map_or(true, |is_melee| self.core_data.derived.is_melee == is_melee); @@ -143,6 +143,12 @@ impl Creature { } }); + let version_pass = match filters.pathfinder_version.clone().unwrap_or_default() { + PathfinderVersionEnum::Legacy => !self.core_data.essential.remaster, + PathfinderVersionEnum::Remaster => self.core_data.essential.remaster, + PathfinderVersionEnum::Any => true, + }; + rarity_pass && size_pass && alignment_pass @@ -151,6 +157,7 @@ impl Creature { && is_spell_caster_pass && type_pass && role_pass + && version_pass } fn check_creature_pass_string_filters(&self, filters: &FieldFilters) -> bool { diff --git a/src/models/creature_component/creature_core.rs b/src/models/creature_component/creature_core.rs index ee54d8a..3b4e6b6 100644 --- a/src/models/creature_component/creature_core.rs +++ b/src/models/creature_component/creature_core.rs @@ -12,7 +12,6 @@ pub struct CreatureCoreData { pub essential: EssentialData, pub derived: DerivedData, pub traits: Vec, - pub alignment: AlignmentEnum, } #[derive(Serialize, Deserialize, Clone, ToSchema, Eq, Hash, PartialEq, FromRow)] pub struct EssentialData { @@ -28,6 +27,7 @@ pub struct EssentialData { pub remaster: bool, pub source: String, pub cr_type: CreatureTypeEnum, + pub alignment: AlignmentEnum, } #[derive(Serialize, Deserialize, Clone, ToSchema, Eq, Hash, PartialEq, FromRow)] @@ -51,6 +51,7 @@ impl<'r> FromRow<'r, SqliteRow> for CreatureCoreData { fn from_row(row: &'r SqliteRow) -> Result { let rarity: String = row.try_get("rarity")?; let size: String = row.try_get("size")?; + let alignment: String = row.try_get("alignment")?; Ok(CreatureCoreData { essential: EssentialData { id: row.try_get("id")?, @@ -65,6 +66,7 @@ impl<'r> FromRow<'r, SqliteRow> for CreatureCoreData { remaster: row.try_get("remaster")?, source: row.try_get("source")?, cr_type: CreatureTypeEnum::from(row.try_get("cr_type").ok()), + alignment: AlignmentEnum::from(alignment), }, derived: DerivedData { archive_link: row.try_get("archive_link").ok(), @@ -80,7 +82,6 @@ impl<'r> FromRow<'r, SqliteRow> for CreatureCoreData { spell_caster_percentage: row.try_get("spell_caster_percentage")?, }, traits: vec![], - alignment: Default::default(), }) } } diff --git a/src/models/creature_component/filter_struct.rs b/src/models/creature_component/filter_struct.rs index 9a9e8b5..1855f53 100644 --- a/src/models/creature_component/filter_struct.rs +++ b/src/models/creature_component/filter_struct.rs @@ -3,6 +3,7 @@ use crate::models::creature_metadata::creature_role::CreatureRoleEnum; use crate::models::creature_metadata::rarity_enum::RarityEnum; use crate::models::creature_metadata::size_enum::SizeEnum; use crate::models::creature_metadata::type_enum::CreatureTypeEnum; +use crate::models::pf_version_enum::PathfinderVersionEnum; use std::collections::HashSet; pub struct FilterStruct { @@ -14,4 +15,5 @@ pub struct FilterStruct { pub creature_types: Option>, pub creature_roles: Option>, pub lvl_combinations: HashSet, + pub pathfinder_version: PathfinderVersionEnum, } diff --git a/src/models/creature_filter_enum.rs b/src/models/creature_filter_enum.rs index 9370348..8627843 100644 --- a/src/models/creature_filter_enum.rs +++ b/src/models/creature_filter_enum.rs @@ -11,8 +11,11 @@ pub enum CreatureFilter { Ranged, SpellCaster, Traits, + Alignment, CreatureTypes, + #[serde(alias = "creature_roles")] CreatureRoles, + PathfinderVersion, } impl fmt::Display for CreatureFilter { @@ -46,7 +49,13 @@ impl fmt::Display for CreatureFilter { write!(f, "cr_type") } CreatureFilter::CreatureRoles => { - write!(f, "CREATUREROLES") + write!(f, "creature_roles") + } + CreatureFilter::Alignment => { + write!(f, "alignment") + } + CreatureFilter::PathfinderVersion => { + write!(f, "remaster") } } } diff --git a/src/models/creature_metadata/alignment_enum.rs b/src/models/creature_metadata/alignment_enum.rs index 8495492..ac44b66 100644 --- a/src/models/creature_metadata/alignment_enum.rs +++ b/src/models/creature_metadata/alignment_enum.rs @@ -1,4 +1,3 @@ -use crate::models::db::raw_trait::RawTrait; use serde::{Deserialize, Serialize}; use std::str::FromStr; use strum::{Display, EnumIter}; @@ -56,17 +55,13 @@ pub enum AlignmentEnum { pub const ALIGNMENT_TRAITS: [&str; 4] = ["GOOD", "EVIL", "CHAOTIC", "LAWFUL"]; -impl From<(&Vec, bool)> for AlignmentEnum { - fn from(tuple: (&Vec, bool)) -> AlignmentEnum { +impl From<(&Vec, bool)> for AlignmentEnum { + fn from(tuple: (&Vec, bool)) -> AlignmentEnum { // If remaster then it's always no alignment if tuple.1 { return AlignmentEnum::No; } - let string_traits: Vec = tuple - .0 - .iter() - .map(|x| x.name.clone().to_uppercase()) - .collect(); + let string_traits: Vec = tuple.0.iter().map(|x| x.to_uppercase()).collect(); let is_good = string_traits.contains(&"GOOD".to_string()); let is_evil = string_traits.contains(&"EVIL".to_string()); let is_chaos = string_traits.contains(&"CHAOTIC".to_string()); @@ -89,6 +84,12 @@ impl From<(&Vec, bool)> for AlignmentEnum { } return AlignmentEnum::Ne; } + if is_chaos { + return AlignmentEnum::Cn; + } + if is_lawful { + return AlignmentEnum::Ln; + } AlignmentEnum::N } } @@ -99,6 +100,12 @@ impl From for AlignmentEnum { } } +impl From<&String> for AlignmentEnum { + fn from(value: &String) -> Self { + AlignmentEnum::from_str(value.as_str()).unwrap_or_default() + } +} + impl FromStr for AlignmentEnum { type Err = (); fn from_str(s: &str) -> Result { @@ -118,43 +125,6 @@ impl FromStr for AlignmentEnum { } } -impl AlignmentEnum { - pub fn to_traits(&self) -> Vec { - match self { - AlignmentEnum::Ce => { - vec![String::from("CHAOTIC"), String::from("EVIL")] - } - AlignmentEnum::Cn => { - vec![String::from("CHAOTIC"), String::from("NEUTRAL")] - } - AlignmentEnum::Cg => { - vec![String::from("CHAOTIC"), String::from("GOOD")] - } - AlignmentEnum::Ne => { - vec![String::from("NEUTRAL"), String::from("EVIL")] - } - AlignmentEnum::N => { - vec![String::from("NEUTRAL")] - } - AlignmentEnum::Ng => { - vec![String::from("NEUTRAL"), String::from("GOOD")] - } - AlignmentEnum::Le => { - vec![String::from("LAWFUL"), String::from("EVIL")] - } - AlignmentEnum::Ln => { - vec![String::from("LAWFUL"), String::from("NEUTRAL")] - } - AlignmentEnum::Lg => { - vec![String::from("LAWFUL"), String::from("GOOD")] - } - AlignmentEnum::No | AlignmentEnum::Any => { - vec![] - } - } - } -} - impl Clone for AlignmentEnum { fn clone(&self) -> AlignmentEnum { match self { diff --git a/src/models/encounter_structs.rs b/src/models/encounter_structs.rs index 7bcb0ba..c34b4ee 100644 --- a/src/models/encounter_structs.rs +++ b/src/models/encounter_structs.rs @@ -3,6 +3,7 @@ use crate::models::creature_metadata::creature_role::CreatureRoleEnum; use crate::models::creature_metadata::rarity_enum::RarityEnum; use crate::models::creature_metadata::size_enum::SizeEnum; use crate::models::creature_metadata::type_enum::CreatureTypeEnum; +use crate::models::pf_version_enum::PathfinderVersionEnum; use rand::distributions::{Distribution, Standard}; use rand::Rng; use serde::{Deserialize, Serialize}; @@ -36,6 +37,7 @@ pub struct RandomEncounterData { pub allow_elite_variants: Option, pub allow_weak_variants: Option, pub is_pwl_on: bool, + pub pathfinder_versions: Option, } #[derive( diff --git a/src/models/mod.rs b/src/models/mod.rs index d14456b..efb2622 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -6,6 +6,7 @@ pub mod creature_metadata; pub mod db; pub mod encounter_structs; pub mod items; +pub mod pf_version_enum; pub mod response_data; pub mod routers_validator_structs; pub mod scales_struct; diff --git a/src/models/pf_version_enum.rs b/src/models/pf_version_enum.rs new file mode 100644 index 0000000..5dcbba6 --- /dev/null +++ b/src/models/pf_version_enum.rs @@ -0,0 +1,10 @@ +use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; + +#[derive(Serialize, Deserialize, Eq, PartialEq, Hash, Default, ToSchema, Clone)] +pub enum PathfinderVersionEnum { + Legacy, + Remaster, + #[default] + Any, +} diff --git a/src/models/routers_validator_structs.rs b/src/models/routers_validator_structs.rs index c89712d..66e660e 100644 --- a/src/models/routers_validator_structs.rs +++ b/src/models/routers_validator_structs.rs @@ -3,6 +3,7 @@ use crate::models::creature_metadata::creature_role::CreatureRoleEnum; use crate::models::creature_metadata::rarity_enum::RarityEnum; use crate::models::creature_metadata::size_enum::SizeEnum; use crate::models::creature_metadata::type_enum::CreatureTypeEnum; +use crate::models::pf_version_enum::PathfinderVersionEnum; use serde::{Deserialize, Serialize}; use utoipa::IntoParams; use validator::Validate; @@ -24,6 +25,7 @@ pub struct FieldFilters { pub is_melee_filter: Option, pub is_ranged_filter: Option, pub is_spell_caster_filter: Option, + pub pathfinder_version: Option, } #[derive(Serialize, Deserialize, IntoParams, Validate, Eq, PartialEq, Hash)] diff --git a/src/routes/bestiary.rs b/src/routes/bestiary.rs index bf40d19..e84fef8 100644 --- a/src/routes/bestiary.rs +++ b/src/routes/bestiary.rs @@ -1,12 +1,3 @@ -use crate::models::creature_metadata::alignment_enum::AlignmentEnum; -use crate::models::creature_metadata::creature_role::CreatureRoleEnum; -use crate::models::creature_metadata::rarity_enum::RarityEnum; -use crate::models::creature_metadata::size_enum::SizeEnum; -use crate::models::creature_metadata::type_enum::CreatureTypeEnum; -use crate::models::creature_metadata::variant_enum::CreatureVariant; -use crate::models::response_data::OptionalData; -use crate::models::response_data::ResponseCreature; - use crate::models::creature_component::creature_combat::CreatureCombatData; use crate::models::creature_component::creature_combat::SavingThrows; use crate::models::creature_component::creature_core::CreatureCoreData; @@ -16,6 +7,15 @@ use crate::models::creature_component::creature_extra::AbilityScores; use crate::models::creature_component::creature_extra::CreatureExtraData; use crate::models::creature_component::creature_spell_caster::CreatureSpellCasterData; use crate::models::creature_component::creature_variant::CreatureVariantData; +use crate::models::creature_metadata::alignment_enum::AlignmentEnum; +use crate::models::creature_metadata::creature_role::CreatureRoleEnum; +use crate::models::creature_metadata::rarity_enum::RarityEnum; +use crate::models::creature_metadata::size_enum::SizeEnum; +use crate::models::creature_metadata::type_enum::CreatureTypeEnum; +use crate::models::creature_metadata::variant_enum::CreatureVariant; +use crate::models::pf_version_enum::PathfinderVersionEnum; +use crate::models::response_data::OptionalData; +use crate::models::response_data::ResponseCreature; use crate::models::items::action::Action; use crate::models::items::skill::Skill; @@ -88,7 +88,8 @@ pub fn init_docs(doc: &mut utoipa::openapi::OpenApi) { Action, Skill, CreatureRoleEnum, - SpellCasterEntry + SpellCasterEntry, + PathfinderVersionEnum )) )] struct ApiDoc; diff --git a/src/services/encounter_service.rs b/src/services/encounter_service.rs index bdda2c7..7c3d3b9 100644 --- a/src/services/encounter_service.rs +++ b/src/services/encounter_service.rs @@ -5,6 +5,7 @@ use crate::models::creature_filter_enum::CreatureFilter; use crate::models::encounter_structs::{ EncounterChallengeEnum, EncounterParams, RandomEncounterData, }; +use crate::models::pf_version_enum::PathfinderVersionEnum; use crate::models::response_data::ResponseCreature; use crate::services::encounter_handler::encounter_calculator; use crate::services::encounter_handler::encounter_calculator::calculate_encounter_scaling_difficulty; @@ -110,6 +111,7 @@ async fn calculate_random_encounter( creature_types: enc_data.creature_types, creature_roles: enc_data.creature_roles, lvl_combinations: unique_levels, + pathfinder_version: enc_data.pathfinder_versions.unwrap_or_default(), }); let filtered_creatures = get_filtered_creatures( @@ -245,8 +247,8 @@ fn build_filter_map(filter_enum: FilterStruct) -> HashMap HashMap vec![String::from("FALSE")].into_iter(), + PathfinderVersionEnum::Remaster => vec![String::from("TRUE")].into_iter(), + PathfinderVersionEnum::Any => { + vec![String::from("TRUE"), String::from("FALSE")].into_iter() + } + }), + ); filter_map }