Skip to content

Commit

Permalink
feat:
Browse files Browse the repository at this point in the history
* add pwl for single creature fetch (base,weak,elite);
* update dockerfile to avoid warnings
* rename OptionalData to ResponseDataModifiers
  • Loading branch information
RakuJa committed Jul 11, 2024
1 parent 0e02d27 commit cabe17d
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 34 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Stage 1: Build the Rust project
FROM rust:1-alpine as builder
FROM rust:1-alpine AS builder

# Set the working directory in the container
WORKDIR /app
Expand Down
13 changes: 6 additions & 7 deletions src/db/bestiary_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::models::creature::creature_metadata::creature_role::CreatureRoleEnum;
use crate::models::creature::creature_metadata::type_enum::CreatureTypeEnum;
use crate::models::creature::creature_metadata::variant_enum::CreatureVariant;
use crate::models::pf_version_enum::PathfinderVersionEnum;
use crate::models::response_data::OptionalData;
use crate::models::response_data::ResponseDataModifiers;
use crate::models::routers_validator_structs::{CreatureFieldFilters, OrderEnum};
use crate::AppState;
use anyhow::Result;
Expand All @@ -22,25 +22,24 @@ pub async fn get_creature_by_id(
app_state: &AppState,
id: i64,
variant: &CreatureVariant,
optional_data: &OptionalData,
response_data_mods: &ResponseDataModifiers,
) -> Option<Creature> {
let creature = creature_fetcher::fetch_creature_by_id(&app_state.conn, optional_data, id)
creature_fetcher::fetch_creature_by_id(&app_state.conn, variant, response_data_mods, id)
.await
.ok()?;
Some(creature.convert_creature_to_variant(variant))
.ok()
}

pub async fn get_weak_creature_by_id(
app_state: &AppState,
id: i64,
optional_data: &OptionalData,
optional_data: &ResponseDataModifiers,
) -> Option<Creature> {
get_creature_by_id(app_state, id, &CreatureVariant::Weak, optional_data).await
}
pub async fn get_elite_creature_by_id(
app_state: &AppState,
id: i64,
optional_data: &OptionalData,
optional_data: &ResponseDataModifiers,
) -> Option<Creature> {
get_creature_by_id(app_state, id, &CreatureVariant::Elite, optional_data).await
}
Expand Down
19 changes: 13 additions & 6 deletions src/db/data_providers/creature_fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::models::item::armor_struct::Armor;
use crate::models::item::item_struct::Item;
use crate::models::item::shield_struct::Shield;
use crate::models::item::weapon_struct::Weapon;
use crate::models::response_data::OptionalData;
use crate::models::response_data::ResponseDataModifiers;
use crate::models::scales_struct::ability_scales::AbilityScales;
use crate::models::scales_struct::ac_scales::AcScales;
use crate::models::scales_struct::area_dmg_scales::AreaDmgScales;
Expand Down Expand Up @@ -430,34 +430,41 @@ pub async fn fetch_traits_associated_with_creatures(conn: &Pool<Sqlite>) -> Resu

pub async fn fetch_creature_by_id(
conn: &Pool<Sqlite>,
optional_data: &OptionalData,
variant: &CreatureVariant,
response_data_mods: &ResponseDataModifiers,
id: i64,
) -> Result<Creature> {
let core_data = fetch_creature_core_data(conn, id).await?;
let level = core_data.essential.level;
let archive_link = core_data.derived.archive_link.clone();
Ok(Creature {
let cr = Creature {
core_data,
variant_data: CreatureVariantData {
variant: CreatureVariant::Base,
level,
archive_link,
},
extra_data: if optional_data.extra_data.is_some_and(|x| x) {
extra_data: if response_data_mods.extra_data.is_some_and(|x| x) {
Some(fetch_creature_extra_data(conn, id).await?)
} else {
None
},
combat_data: if optional_data.combat_data.is_some_and(|x| x) {
combat_data: if response_data_mods.combat_data.is_some_and(|x| x) {
Some(fetch_creature_combat_data(conn, id).await?)
} else {
None
},
spell_caster_data: if optional_data.spell_casting_data.is_some_and(|x| x) {
spell_caster_data: if response_data_mods.spell_casting_data.is_some_and(|x| x) {
Some(fetch_creature_spell_caster_data(conn, id).await?)
} else {
None
},
}
.convert_creature_to_variant(variant);
Ok(if response_data_mods.is_pwl_on.unwrap_or(false) {
cr
} else {
cr.convert_creature_to_pwl()
})
}

Expand Down
26 changes: 26 additions & 0 deletions src/models/creature/creature_component/creature_combat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,29 @@ pub struct CreatureCombatData {
pub saving_throws: SavingThrows,
pub ac: i8,
}

impl CreatureCombatData {
fn add_mod_to_saving_throws_and_ac_and_wp_to_hit(self, modifier: i64) -> CreatureCombatData {
let mut com_data = self;
let weapons: Vec<Weapon> = com_data
.weapons
.into_iter()
.map(|mut wp| {
wp.weapon_data.to_hit_bonus =
wp.weapon_data.to_hit_bonus.map(|to_hit| to_hit - modifier);
wp
})
.collect();
com_data.ac = (com_data.ac as i64 - modifier) as i8;
com_data.saving_throws.fortitude -= modifier;
com_data.saving_throws.reflex -= modifier;
com_data.saving_throws.will -= modifier;
com_data.weapons = weapons;
com_data
}

/// Lowers saving throws, weapon to hit bonus, and ac by the given pwl_mod
pub fn convert_from_base_to_pwl(self, pwl_mod: u64) -> CreatureCombatData {
self.add_mod_to_saving_throws_and_ac_and_wp_to_hit(-(pwl_mod as i64))
}
}
23 changes: 23 additions & 0 deletions src/models/creature/creature_component/creature_extra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,26 @@ pub struct CreatureExtraData {
pub perception: i8,
pub perception_detail: Option<String>,
}

impl CreatureExtraData {
fn add_mod_to_perception_and_skill_mods(self, modifier: i64) -> CreatureExtraData {
let mut ex_data = self;
// we should never have a pwl much greater than perception (pwl=lvl)
ex_data.perception = (ex_data.perception as i64 + modifier) as i8;

ex_data.skills = ex_data
.skills
.into_iter()
.map(|mut skill| {
skill.modifier += modifier;
skill
})
.collect();

ex_data
}
/// Lowers skill and perception by the given pwl_mod
pub fn convert_from_base_to_pwl(self, pwl_mod: u64) -> CreatureExtraData {
self.add_mod_to_perception_and_skill_mods(-(pwl_mod as i64))
}
}
23 changes: 23 additions & 0 deletions src/models/creature/creature_component/creature_spell_caster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,26 @@ pub struct CreatureSpellCasterData {
pub spells: Vec<Spell>,
pub spell_caster_entry: SpellCasterEntry,
}

impl CreatureSpellCasterData {
pub fn add_mod_to_spellcaster_atk_and_dc(self, pwl_mod: i64) -> CreatureSpellCasterData {
let mut spell_data = self;

spell_data.spell_caster_entry.spell_casting_atk_mod = spell_data
.spell_caster_entry
.spell_casting_atk_mod
.map(|x| x - pwl_mod);

spell_data.spell_caster_entry.spell_casting_dc_mod = spell_data
.spell_caster_entry
.spell_casting_dc_mod
.map(|x| x - pwl_mod);

spell_data.clone()
}

/// Lowers spell caster atk and dc
pub fn convert_from_base_to_pwl(self, pwl_mod: u64) -> CreatureSpellCasterData {
self.add_mod_to_spellcaster_atk_and_dc(-(pwl_mod as i64))
}
}
20 changes: 20 additions & 0 deletions src/models/creature/creature_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,26 @@ impl Creature {
cr.spell_caster_data = self.spell_caster_data;
cr
}

pub fn convert_creature_to_pwl(self) -> Creature {
let pwl_mod = if self.core_data.essential.level >= 0 {
self.core_data.essential.level as u64
} else {
0
};

Creature {
core_data: self.core_data,
variant_data: self.variant_data,
extra_data: self.extra_data.map(|x| x.convert_from_base_to_pwl(pwl_mod)),
combat_data: self
.combat_data
.map(|x| x.convert_from_base_to_pwl(pwl_mod)),
spell_caster_data: self
.spell_caster_data
.map(|x| x.convert_from_base_to_pwl(pwl_mod)),
}
}
pub fn from_core(core: CreatureCoreData) -> Creature {
let level = core.essential.level;
let archive_link = core.derived.archive_link.clone();
Expand Down
3 changes: 2 additions & 1 deletion src/models/response_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use utoipa::{IntoParams, ToSchema};
use validator::Validate;

#[derive(Serialize, Deserialize, IntoParams, Default, Eq, PartialEq, Hash, Clone, Validate)]
pub struct OptionalData {
pub struct ResponseDataModifiers {
pub is_pwl_on: Option<bool>,
pub extra_data: Option<bool>,
pub combat_data: Option<bool>,
pub spell_casting_data: Option<bool>,
Expand Down
33 changes: 21 additions & 12 deletions src/routes/bestiary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::models::creature::creature_metadata::alignment_enum::AlignmentEnum;
use crate::models::creature::creature_metadata::creature_role::CreatureRoleEnum;
use crate::models::creature::creature_metadata::type_enum::CreatureTypeEnum;
use crate::models::creature::creature_metadata::variant_enum::CreatureVariant;
use crate::models::response_data::OptionalData;
use crate::models::response_data::ResponseCreature;
use crate::models::response_data::ResponseDataModifiers;
use crate::models::routers_validator_structs::OrderEnum;
use crate::models::shared::rarity_enum::RarityEnum;
use crate::models::shared::size_enum::SizeEnum;
Expand Down Expand Up @@ -283,7 +283,7 @@ pub async fn get_creature_roles_list() -> Result<impl Responder> {
tag = "bestiary",
params(
("creature_id" = String, Path, description = "id of the creature to fetch"),
OptionalData,
ResponseDataModifiers,
),
responses(
(status=200, description = "Successful Response", body = ResponseCreature),
Expand All @@ -294,10 +294,11 @@ pub async fn get_creature_roles_list() -> Result<impl Responder> {
pub async fn get_creature(
data: web::Data<AppState>,
creature_id: web::Path<String>,
optional_data: Query<OptionalData>,
response_data_mods: Query<ResponseDataModifiers>,
) -> Result<impl Responder> {
Ok(web::Json(
bestiary_service::get_creature(&data, sanitize_id(&creature_id)?, &optional_data.0).await,
bestiary_service::get_creature(&data, sanitize_id(&creature_id)?, &response_data_mods.0)
.await,
))
}

Expand All @@ -307,7 +308,7 @@ pub async fn get_creature(
tag = "bestiary",
params(
("creature_id" = String, Path, description = "id of the creature to fetch"),
OptionalData
ResponseDataModifiers
),
responses(
(status=200, description = "Successful Response", body = ResponseCreature),
Expand All @@ -318,11 +319,15 @@ pub async fn get_creature(
pub async fn get_elite_creature(
data: web::Data<AppState>,
creature_id: web::Path<String>,
response_data: Query<OptionalData>,
response_data_mods: Query<ResponseDataModifiers>,
) -> Result<impl Responder> {
Ok(web::Json(
bestiary_service::get_elite_creature(&data, sanitize_id(&creature_id)?, &response_data.0)
.await,
bestiary_service::get_elite_creature(
&data,
sanitize_id(&creature_id)?,
&response_data_mods.0,
)
.await,
))
}

Expand All @@ -332,7 +337,7 @@ pub async fn get_elite_creature(
tag = "bestiary",
params(
("creature_id" = String, Path, description = "id of the creature to fetch"),
OptionalData,
ResponseDataModifiers,
),
responses(
(status=200, description = "Successful Response", body = ResponseCreature),
Expand All @@ -343,11 +348,15 @@ pub async fn get_elite_creature(
pub async fn get_weak_creature(
data: web::Data<AppState>,
creature_id: web::Path<String>,
response_data: Query<OptionalData>,
response_data_mods: Query<ResponseDataModifiers>,
) -> Result<impl Responder> {
Ok(web::Json(
bestiary_service::get_weak_creature(&data, sanitize_id(&creature_id)?, &response_data.0)
.await,
bestiary_service::get_weak_creature(
&data,
sanitize_id(&creature_id)?,
&response_data_mods.0,
)
.await,
))
}

Expand Down
14 changes: 7 additions & 7 deletions src/services/bestiary_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::models::creature::creature_filter_enum::CreatureFilter;
use crate::models::creature::creature_metadata::creature_role::CreatureRoleEnum;
use crate::models::creature::creature_metadata::variant_enum::CreatureVariant;
use crate::models::creature::creature_struct::Creature;
use crate::models::response_data::{OptionalData, ResponseCreature};
use crate::models::response_data::{ResponseCreature, ResponseDataModifiers};
use crate::models::routers_validator_structs::CreatureFieldFilters;
use crate::services::url_calculator::bestiary_next_url_calculator;
use crate::AppState;
Expand All @@ -24,33 +24,33 @@ pub struct BestiaryResponse {
pub async fn get_creature(
app_state: &AppState,
id: i64,
optional_data: &OptionalData,
response_data_mods: &ResponseDataModifiers,
) -> HashMap<String, Option<ResponseCreature>> {
hashmap! {
String::from("results") =>
bestiary_proxy::get_creature_by_id(app_state, id, &CreatureVariant::Base, optional_data).await.map(ResponseCreature::from)
bestiary_proxy::get_creature_by_id(app_state, id, &CreatureVariant::Base, response_data_mods).await.map(ResponseCreature::from)
}
}

pub async fn get_elite_creature(
app_state: &AppState,
id: i64,
optional_data: &OptionalData,
response_data_mods: &ResponseDataModifiers,
) -> HashMap<String, Option<ResponseCreature>> {
hashmap! {
String::from("results") =>
bestiary_proxy::get_elite_creature_by_id(app_state, id, optional_data).await.map(ResponseCreature::from)
bestiary_proxy::get_elite_creature_by_id(app_state, id, response_data_mods).await.map(ResponseCreature::from)
}
}

pub async fn get_weak_creature(
app_state: &AppState,
id: i64,
optional_data: &OptionalData,
response_data_mods: &ResponseDataModifiers,
) -> HashMap<String, Option<ResponseCreature>> {
hashmap! {
String::from("results") =>
bestiary_proxy::get_weak_creature_by_id(app_state, id, optional_data).await.map(ResponseCreature::from)
bestiary_proxy::get_weak_creature_by_id(app_state, id, response_data_mods).await.map(ResponseCreature::from)
}
}

Expand Down

0 comments on commit cabe17d

Please sign in to comment.