Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Refactor Creature response according to new db and remastered #48

Merged
merged 5 commits into from
Mar 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ __pycache__/
*.py[cod]
*$py.class

# PyCharm
# RustRover
.idea

# Development environment
venv
# db
database.db
.env

# Generated by Cargo
# will have compiled files and executables
Expand All @@ -22,4 +23,4 @@ Cargo.lock
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
*.pdb
15 changes: 8 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ publish = false
unsafe_code = "forbid"

[dependencies]
actix-web = "4.4.1"
actix-web = "4.5.1"
actix-cors = "0.7.0"
actix-web-validator = "5.0.1"
validator = {version="0.16.1", features = ["derive"]}
Expand All @@ -32,13 +32,14 @@ utoipa-swagger-ui = { version = "6.0.0", features = ["actix-web"] }
sqlx = { version = "0.7.3", features = ["runtime-async-std", "sqlite"] }
mini-moka = "0.10.3"

anyhow = "1.0.79"
serde = { version = "1.0.196", features = ["derive"] }
serde_json = "1.0.113"
anyhow = "1.0.80"
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.114"
strum = {version="0.26.1", features = ["derive"]}
rand = "0.8.5"
rand = "0.9.0-alpha.0"
counter = "0.5.7"
dotenvy = "0.15.7"

env_logger = "0.11.1"
log = "0.4.20"
env_logger = "0.11.2"
log = "0.4.21"
maplit = "1.0.2"
49 changes: 27 additions & 22 deletions src/db/db_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,17 @@ pub fn from_db_data_to_filter_cache(
};
}
for curr_creature in data {
let id = curr_creature.id.to_string();
let lvl = curr_creature.variant_level.to_string();
let family = if curr_creature.family.is_some() {
curr_creature.family.unwrap()
let id = curr_creature.core_data.id.to_string();
let lvl = curr_creature.variant_data.level.to_string();
let family = if curr_creature.core_data.family.is_some() {
curr_creature.core_data.family.unwrap()
} else {
"-".to_string()
};
let alignment = curr_creature.alignment.to_string();
let size = curr_creature.size.to_string();
let rarity = curr_creature.rarity.to_string();
let creature_type = curr_creature.creature_type.to_string();
let alignment = curr_creature.core_data.alignment.to_string();
let size = curr_creature.core_data.size.to_string();
let rarity = curr_creature.core_data.rarity.to_string();
let creature_type = curr_creature.core_data.creature_type.to_string();

if !fields_values_cache.list_of_ids.contains(&id) {
fields_values_cache.list_of_ids.push(id);
Expand All @@ -56,21 +56,26 @@ pub fn from_db_data_to_filter_cache(
fields_values_cache.list_of_families.push(family);
}

curr_creature.traits.iter().for_each(|single_trait| {
if !fields_values_cache.list_of_traits.contains(single_trait) {
fields_values_cache
.list_of_traits
.push(single_trait.to_string())
}
});
curr_creature
.core_data
.traits
.iter()
.for_each(|single_trait| {
if !fields_values_cache.list_of_traits.contains(single_trait) {
fields_values_cache
.list_of_traits
.push(single_trait.to_string())
}
});

curr_creature.sources.iter().for_each(|single_source| {
if !fields_values_cache.list_of_sources.contains(single_source) {
fields_values_cache
.list_of_sources
.push(single_source.to_string())
}
});
if !fields_values_cache
.list_of_sources
.contains(&curr_creature.core_data.source)
{
fields_values_cache
.list_of_sources
.push(curr_creature.core_data.source.clone());
}

if !fields_values_cache.list_of_alignments.contains(&alignment) {
fields_values_cache.list_of_alignments.push(alignment);
Expand Down
218 changes: 134 additions & 84 deletions src/db/db_communicator.rs
Original file line number Diff line number Diff line change
@@ -1,100 +1,150 @@
use crate::models::creature::Creature;
use crate::models::creature_metadata_enums::{
AlignmentEnum, CreatureTypeEnum, CreatureVariant, RarityEnum, SizeEnum,
};
use crate::services::url_calculator::generate_archive_link;
use log::warn;
use serde::{Deserialize, Serialize};
use sqlx::{Error, FromRow, Pool, Sqlite};
use std::str::FromStr;
use crate::models::db::raw_creature::RawCreature;
use crate::models::db::raw_immunity::RawImmunity;
use crate::models::db::raw_language::RawLanguage;
use crate::models::db::raw_resistance::RawResistance;
use crate::models::db::raw_sense::RawSense;
use crate::models::db::raw_speed::RawSpeed;
use crate::models::db::raw_trait::RawTrait;
use crate::models::db::raw_weakness::RawWeakness;
use crate::models::items::spell::Spell;
use crate::models::items::weapon::Weapon;
use anyhow::Result;
use sqlx::{Error, Pool, Sqlite};

#[derive(Serialize, Deserialize, FromRow)]
pub struct RawCreature {
id: i32,
aon_id: i32,
name: String,
hp: i16,
level: i8,
alignment: String,
size: String,
family: Option<String>,
rarity: String,
is_melee: i8,
is_ranged: i8,
is_spell_caster: i8,
creature_type: String,
async fn from_raw_vec_to_creature(conn: &Pool<Sqlite>, raw_vec: Vec<RawCreature>) -> Vec<Creature> {
let mut creature_list = Vec::new();
for el in raw_vec {
let immunities = get_creature_immunities(conn, el.id)
.await
.unwrap_or_default();
let languages = get_creature_languages(conn, el.id)
.await
.unwrap_or_default();
let resistances = get_creature_resistances(conn, el.id)
.await
.unwrap_or_default();
let senses = get_creature_senses(conn, el.id).await.unwrap_or_default();
let speeds = get_creature_speeds(conn, el.id).await.unwrap_or_default();
let traits = get_creature_traits(conn, el.id).await.unwrap_or_default();
let weaknesses = get_creature_weaknesses(conn, el.id)
.await
.unwrap_or_default();
let spells = get_creature_spells(conn, el.id).await.unwrap_or_default();
let weapons = get_creature_weapons(conn, el.id).await.unwrap_or_default();
creature_list.push(Creature::from((
el,
traits,
weapons,
spells,
immunities,
languages,
resistances,
senses,
speeds,
weaknesses,
)));
}
creature_list
}

#[derive(Serialize, Deserialize, FromRow)]
pub struct CreatureTrait {
name: String,
async fn get_creature_immunities(
conn: &Pool<Sqlite>,
creature_id: i64,
) -> Result<Vec<RawImmunity>> {
Ok(sqlx::query_as!(
RawImmunity,
"SELECT * FROM IMMUNITY_TABLE INTERSECT SELECT immunity_id FROM IMMUNITY_CREATURE_ASSOCIATION_TABLE WHERE creature_id == ($1)",
creature_id
).fetch_all(conn).await?)
}

#[derive(Serialize, Deserialize, FromRow)]
pub struct CreatureSource {
name: String,
async fn get_creature_languages(conn: &Pool<Sqlite>, creature_id: i64) -> Result<Vec<RawLanguage>> {
Ok(sqlx::query_as!(
RawLanguage,
"SELECT * FROM LANGUAGE_TABLE INTERSECT SELECT language_id FROM LANGUAGE_CREATURE_ASSOCIATION_TABLE WHERE creature_id == ($1)",
creature_id
).fetch_all(conn).await?)
}

async fn from_raw_vec_to_creature(conn: &Pool<Sqlite>, raw_vec: Vec<RawCreature>) -> Vec<Creature> {
let mut creature_list = Vec::new();
for el in raw_vec {
creature_list.push(from_raw_to_creature(conn, &el).await);
}
creature_list
async fn get_creature_resistances(
conn: &Pool<Sqlite>,
creature_id: i64,
) -> Result<Vec<RawResistance>> {
Ok(sqlx::query_as!(
RawResistance,
"SELECT name, value FROM RESISTANCE_TABLE WHERE creature_id == ($1)",
creature_id
)
.fetch_all(conn)
.await?)
}

async fn from_raw_to_creature(conn: &Pool<Sqlite>, raw: &RawCreature) -> Creature {
let creature_type = CreatureTypeEnum::from_str(raw.creature_type.as_str()).unwrap_or_default();
let alignment_enum = AlignmentEnum::from_str(raw.alignment.as_str()).unwrap_or_default();
let size_enum = SizeEnum::from_str(raw.size.as_str()).unwrap_or_default();
let rarity_enum = RarityEnum::from_str(raw.rarity.as_str()).unwrap_or_default();
let archive_link = generate_archive_link(raw.aon_id, &creature_type);
async fn get_creature_senses(conn: &Pool<Sqlite>, creature_id: i64) -> Result<Vec<RawSense>> {
Ok(sqlx::query_as!(
RawSense,
"SELECT * FROM SENSE_TABLE INTERSECT SELECT sense_id FROM SENSE_CREATURE_ASSOCIATION_TABLE WHERE creature_id == ($1)",
creature_id
).fetch_all(conn).await?)
}

let sources = sqlx::query_as::<_, CreatureSource>(
&format!("SELECT * FROM source_table INTERSECT SELECT source_id FROM SOURCE_ASSOCIATION_TABLE WHERE creature_id == {}", raw.id)
).fetch_all(conn).await.unwrap_or_default();
async fn get_creature_speeds(conn: &Pool<Sqlite>, creature_id: i64) -> Result<Vec<RawSpeed>> {
Ok(sqlx::query_as!(
RawSpeed,
"SELECT name, value FROM SPEED_TABLE WHERE creature_id == ($1)",
creature_id
)
.fetch_all(conn)
.await?)
}

let traits = sqlx::query_as::<_, CreatureTrait>(
&format!("SELECT * FROM trait_table INTERSECT SELECT trait_id FROM TRAIT_ASSOCIATION_TABLE WHERE creature_id == {}", raw.id)
).fetch_all(conn).await.unwrap_or_default();
Creature {
id: raw.id,
aon_id: raw.aon_id,
name: raw.name.clone(),
hp: raw.hp,
base_level: raw.level,
variant_level: raw.level,
alignment: alignment_enum,
size: size_enum,
family: raw.family.clone(),
rarity: rarity_enum,
is_melee: raw.is_melee != 0,
is_ranged: raw.is_ranged != 0,
is_spell_caster: raw.is_spell_caster != 0,
sources: sources
.into_iter()
.map(|curr_source| curr_source.name)
.collect(),
traits: traits
.into_iter()
.map(|curr_trait| curr_trait.name)
.collect(),
creature_type,
archive_link: archive_link.clone(),
variant_archive_link: archive_link,
variant: CreatureVariant::Base,
}
async fn get_creature_weaknesses(
conn: &Pool<Sqlite>,
creature_id: i64,
) -> Result<Vec<RawWeakness>> {
Ok(sqlx::query_as!(
RawWeakness,
"SELECT name, value FROM WEAKNESS_TABLE WHERE creature_id == ($1)",
creature_id
)
.fetch_all(conn)
.await?)
}

async fn get_creature_traits(conn: &Pool<Sqlite>, creature_id: i64) -> Result<Vec<RawTrait>> {
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?)
}

async fn get_creature_weapons(conn: &Pool<Sqlite>, creature_id: i64) -> Result<Vec<Weapon>> {
Ok(sqlx::query_as!(
Weapon,
"SELECT * FROM WEAPON_TABLE WHERE creature_id == ($1)",
creature_id
)
.fetch_all(conn)
.await?)
}

async fn get_creature_spells(conn: &Pool<Sqlite>, creature_id: i64) -> Result<Vec<Spell>> {
Ok(sqlx::query_as!(
Spell,
"SELECT * FROM SPELL_TABLE WHERE creature_id == ($1)",
creature_id
)
.fetch_all(conn)
.await?)
}

pub async fn fetch_creatures(conn: &Pool<Sqlite>) -> Result<Vec<Creature>, Error> {
let creatures = sqlx::query_as::<_, RawCreature>("SELECT * FROM CREATURE_TABLE ORDER BY name")
.fetch_all(conn)
.await;
match creatures {
Ok(creature_list) => Ok(from_raw_vec_to_creature(conn, creature_list).await),
Err(err) => {
warn!("Error converting data from db {}", err);
Err(err)
}
}
Ok(from_raw_vec_to_creature(
conn,
sqlx::query_as!(RawCreature, "SELECT * FROM CREATURE_TABLE ORDER BY name")
.fetch_all(conn)
.await?,
)
.await)
}
Loading
Loading