diff --git a/Cargo.toml b/Cargo.toml index f9b523f..25dee57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,21 @@ path = "src/main.rs" unsafe_code = "forbid" deprecated = "allow" +[lints.clippy] +struct_field_names = {level = "allow", priority = 2} +module_name_repetitions = {level = "allow", priority = 2} +# We are ok with losing some data without wrapping. We are not ok with wrapping +# Ex: 128.12 => 128 is ok, 128 => 0 is not. +cast_possible_truncation = {level = "allow", priority = 2} +cast_precision_loss = {level = "allow", priority = 2} + +future_not_send = {level = "allow", priority = 2} + +pedantic = {level = "warn", priority = 1} +nursery = {level= "warn", priority = 1} +# unwrap_used = {level = "warn", priority = 1} + + [dependencies] actix-web = "4.9.0" actix-cors = "0.7.0" @@ -40,8 +55,8 @@ sqlx = { version = "0.8.2", features = ["runtime-async-std", "sqlite"] } cached = { version = "0.54.0", features = ["async"] } anyhow = "1.0.93" -serde = { version = "1.0.215", features = ["derive"] } -serde_json = "1.0.133" +serde = { version = "1.0.214", features = ["derive"] } +serde_json = "1.0.132" strum = {version="0.26.3", features = ["derive"]} fastrand = "2.2.0" counter = "0.6.0" diff --git a/build/main.rs b/build/main.rs index c40d67c..bfc7afa 100644 --- a/build/main.rs +++ b/build/main.rs @@ -27,5 +27,5 @@ async fn main() { .expect("Could not populate the db, something went wrong.."); creature_core_db_init::cleanup_db(&conn) .await - .expect("Could not clean up the db. Dirty state detected, closing..") + .expect("Could not clean up the db. Dirty state detected, closing.."); } diff --git a/src/db/bestiary_proxy.rs b/src/db/bestiary_proxy.rs index 8c6ce22..dfa07b2 100644 --- a/src/db/bestiary_proxy.rs +++ b/src/db/bestiary_proxy.rs @@ -109,7 +109,7 @@ pub async fn get_paginated_creatures( let curr_slice: Vec = filtered_list .iter() .skip(pagination.paginated_request.cursor as usize) - .take(pagination.paginated_request.page_size as usize) + .take(pagination.paginated_request.page_size.unsigned_abs() as usize) .cloned() .collect(); @@ -125,8 +125,7 @@ pub async fn get_creatures_passing_all_filters( let mut creature_vec = Vec::new(); let level_vec = key_value_filters .get(&CreatureFilter::Level) - .unwrap_or(&HashSet::new()) - .clone(); + .map_or_else(HashSet::new, std::clone::Clone::clone); let modified_filters = prepare_filters_for_db_communication(key_value_filters, fetch_weak, fetch_elite); for core in @@ -163,9 +162,9 @@ pub async fn get_all_possible_values_of_filter( let mut x = match field { CreatureFilter::Size => runtime_fields_values.list_of_sizes, CreatureFilter::Rarity => runtime_fields_values.list_of_rarities, - CreatureFilter::Ranged => vec![true.to_string(), false.to_string()], - CreatureFilter::Melee => vec![true.to_string(), false.to_string()], - CreatureFilter::SpellCaster => vec![true.to_string(), false.to_string()], + CreatureFilter::Ranged | CreatureFilter::Melee | CreatureFilter::SpellCaster => { + vec![true.to_string(), false.to_string()] + } CreatureFilter::Family => runtime_fields_values.list_of_families, CreatureFilter::Traits => runtime_fields_values.list_of_traits, CreatureFilter::Sources => runtime_fields_values.list_of_sources, @@ -240,21 +239,22 @@ async fn get_list(app_state: &AppState, variant: CreatureVariant) -> Vec creatures.into_iter().map(Creature::from_core).collect(), _ => creatures .into_iter() - .map(|cr| Creature::from_core_with_variant(cr, variant.clone())) + .map(|cr| Creature::from_core_with_variant(cr, variant)) .collect(), }; } vec![] } -pub fn order_list_by_level(creature_list: Vec) -> HashMap> { +pub fn order_list_by_level(creature_list: &[Creature]) -> HashMap> { let mut ordered_by_level = HashMap::new(); - creature_list.iter().for_each(|creature| { + + for creature in creature_list { ordered_by_level .entry(creature.variant_data.level) .or_insert_with(Vec::new) .push(creature.clone()); - }); + } ordered_by_level } diff --git a/src/db/cr_core_initializer.rs b/src/db/cr_core_initializer.rs index a4c5c60..690ddb1 100644 --- a/src/db/cr_core_initializer.rs +++ b/src/db/cr_core_initializer.rs @@ -29,7 +29,7 @@ pub async fn update_creature_core_table(conn: &Pool) -> Result<()> { hp: cr.hp, base_level: cr.level, size: cr.size, - family: cr.family.unwrap_or(String::from("-")), + family: cr.family.unwrap_or_else(|| String::from("-")), rarity: cr.rarity, license: cr.license, remaster: cr.remaster, diff --git a/src/db/data_providers/creature_fetcher.rs b/src/db/data_providers/creature_fetcher.rs index e866929..017faa5 100644 --- a/src/db/data_providers/creature_fetcher.rs +++ b/src/db/data_providers/creature_fetcher.rs @@ -246,7 +246,7 @@ async fn fetch_creature_weapons(conn: &Pool, creature_id: i64) -> Result el.weapon_data.damage_data = fetch_weapon_damage_data(conn, el.weapon_data.id) .await .unwrap_or(vec![]); - result_vec.push(el) + result_vec.push(el); } Ok(result_vec) } @@ -277,7 +277,7 @@ async fn fetch_creature_armors(conn: &Pool, creature_id: i64) -> Result< el.armor_data.property_runes = fetch_armor_runes(conn, el.armor_data.id) .await .unwrap_or(vec![]); - result_vec.push(el) + result_vec.push(el); } Ok(result_vec) } @@ -304,7 +304,7 @@ async fn fetch_creature_shields(conn: &Pool, creature_id: i64) -> Result .await .unwrap_or(vec![]); el.item_core.quantity = fetch_shield_quantity(conn, creature_id, el.shield_data.id).await; - result_vec.push(el) + result_vec.push(el); } Ok(result_vec) } @@ -326,7 +326,7 @@ async fn fetch_creature_items(conn: &Pool, creature_id: i64) -> Result, creature_id: i64) -> Result, creature_id: i64, item_id: i64) -> i64 { - match sqlx::query!( + sqlx::query!( "SELECT quantity FROM ITEM_CREATURE_ASSOCIATION_TABLE WHERE creature_id == ($1) AND item_id == ($2)", creature_id, @@ -342,17 +342,14 @@ async fn fetch_item_quantity(conn: &Pool, creature_id: i64, item_id: i64 ) .fetch_one(conn) .await - { - Ok(r) => r.quantity, - Err(_) => 1, - } + .map_or(1, |q| q.quantity) } /// Quantities are present ONLY for creature's weapons. /// It needs to be fetched from the association table. /// It defaults to 1 if error are found async fn fetch_weapon_quantity(conn: &Pool, creature_id: i64, weapon_id: i64) -> i64 { - match sqlx::query!( + sqlx::query!( "SELECT quantity FROM WEAPON_CREATURE_ASSOCIATION_TABLE WHERE creature_id == ($1) AND weapon_id == ($2)", creature_id, @@ -360,17 +357,14 @@ async fn fetch_weapon_quantity(conn: &Pool, creature_id: i64, weapon_id: ) .fetch_one(conn) .await - { - Ok(r) => r.quantity, - Err(_) => 1, - } + .map_or(1, |r| r.quantity) } /// Quantities are present ONLY for creature's shields. /// It needs to be fetched from the association table. /// It defaults to 1 if error are found async fn fetch_shield_quantity(conn: &Pool, creature_id: i64, shield_id: i64) -> i64 { - match sqlx::query!( + sqlx::query!( "SELECT quantity FROM SHIELD_CREATURE_ASSOCIATION_TABLE WHERE creature_id == ($1) AND shield_id == ($2)", creature_id, @@ -378,17 +372,14 @@ async fn fetch_shield_quantity(conn: &Pool, creature_id: i64, shield_id: ) .fetch_one(conn) .await - { - Ok(r) => r.quantity, - Err(_) => 1, - } + .map_or(1, |r| r.quantity) } /// Quantities are present ONLY for creature's armors. /// It needs to be fetched from the association table. /// It defaults to 1 if error are found async fn fetch_armor_quantity(conn: &Pool, creature_id: i64, armor_id: i64) -> i64 { - match sqlx::query!( + sqlx::query!( "SELECT quantity FROM ARMOR_CREATURE_ASSOCIATION_TABLE WHERE creature_id == ($1) AND armor_id == ($2)", creature_id, @@ -396,10 +387,7 @@ async fn fetch_armor_quantity(conn: &Pool, creature_id: i64, armor_id: i ) .fetch_one(conn) .await - { - Ok(r) => r.quantity, - Err(_) => 1, - } + .map_or(1, |r| r.quantity) } async fn fetch_creature_actions(conn: &Pool, creature_id: i64) -> Result> { @@ -639,12 +627,12 @@ pub async fn fetch_creature_combat_data( shields, resistances: resistances .iter() - .map(|x| (x.name.clone(), x.value as i16)) + .map(|x| (x.name.clone(), i16::try_from(x.value).unwrap_or(0))) .collect(), immunities: immunities.iter().map(|x| x.name.clone()).collect(), weaknesses: weaknesses .iter() - .map(|x| (x.name.clone(), x.value as i16)) + .map(|x| (x.name.clone(), i16::try_from(x.value).unwrap_or(0))) .collect(), saving_throws, ac: creature_ac, diff --git a/src/db/data_providers/raw_query_builder.rs b/src/db/data_providers/raw_query_builder.rs index dff7882..b6aec3a 100644 --- a/src/db/data_providers/raw_query_builder.rs +++ b/src/db/data_providers/raw_query_builder.rs @@ -62,12 +62,12 @@ pub fn prepare_filtered_get_creatures_core( | CreatureFilter::Ranged | CreatureFilter::SpellCaster => { if !simple_core_query.is_empty() { - simple_core_query.push_str(" AND ") + simple_core_query.push_str(" AND "); } simple_core_query.push_str( prepare_in_statement_for_generic_type(key.to_string().as_str(), value.iter()) .as_str(), - ) + ); } CreatureFilter::Family | CreatureFilter::Alignment @@ -75,7 +75,7 @@ pub fn prepare_filtered_get_creatures_core( | CreatureFilter::Rarity | CreatureFilter::CreatureTypes => { if !simple_core_query.is_empty() { - simple_core_query.push_str(" AND ") + simple_core_query.push_str(" AND "); } simple_core_query.push_str( prepare_case_insensitive_in_statement( @@ -83,24 +83,24 @@ pub fn prepare_filtered_get_creatures_core( value.iter().cloned(), ) .as_str(), - ) + ); } CreatureFilter::Traits => { - trait_query.push_str(prepare_creature_trait_filter(value.iter().cloned()).as_str()) + trait_query.push_str(prepare_creature_trait_filter(value.iter().cloned()).as_str()); } CreatureFilter::CreatureRoles => { if !simple_core_query.is_empty() { - simple_core_query.push_str(" AND ") + simple_core_query.push_str(" AND "); } simple_core_query - .push_str(prepare_bounded_or_check(value, ACCURACY_THRESHOLD, 100).as_str()) + .push_str(prepare_bounded_or_check(value, ACCURACY_THRESHOLD, 100).as_str()); } - _ => (), + CreatureFilter::Sources => (), // Never given as value to filter } } let mut where_query = simple_core_query.to_string(); if !trait_query.is_empty() { - where_query.push_str(format!(" AND id IN ({trait_query}) GROUP BY cc.id").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}"); @@ -198,7 +198,7 @@ where if result_string.ends_with(',') { result_string.remove(result_string.len() - 1); } - result_string.push(')') + result_string.push(')'); } result_string } @@ -224,7 +224,7 @@ where if result_string.ends_with(',') { result_string.remove(result_string.len() - 1); } - result_string.push(')') + result_string.push(')'); } result_string } @@ -272,8 +272,8 @@ fn prepare_item_filter_statement(shop_filter_vectors: &ItemTableFieldsFilter) -> prepare_case_insensitive_in_statement("source", shop_filter_vectors.source_filter.iter()), prepare_bounded_check( &String::from("level"), - shop_filter_vectors.min_level as i64, - shop_filter_vectors.max_level as i64, + i64::from(shop_filter_vectors.min_level), + i64::from(shop_filter_vectors.max_level), ), ] .into_iter() @@ -283,7 +283,7 @@ fn prepare_item_filter_statement(shop_filter_vectors: &ItemTableFieldsFilter) -> if filters_query.is_empty() { remaster_query } else { - format!("{} AND {}", remaster_query, filters_query) + format!("{remaster_query} AND {filters_query}") } } @@ -301,14 +301,11 @@ where if whitelist_query.is_empty() && blacklist_query.is_empty() { String::new() } else if whitelist_query.is_empty() { - format!("id NOT IN ({})", blacklist_query) + format!("id NOT IN ({blacklist_query})") } else if blacklist_query.is_empty() { - format!("id IN ({})", whitelist_query) + format!("id IN ({whitelist_query})") } else { - format!( - "id IN ({}) AND id NOT IN ({})", - whitelist_query, blacklist_query - ) + format!("id IN ({whitelist_query}) AND id NOT IN ({blacklist_query})") } } @@ -320,7 +317,7 @@ fn prepare_get_id_matching_item_type_query(item_type: &ItemTypeEnum) -> String { // There is no need for an and statement here, we already fetch from the "private" table. // Item instead contains a lot of item_type (it's the base for weapon/shield/etc) ItemTypeEnum::Weapon | ItemTypeEnum::Armor | ItemTypeEnum::Shield => { - ("base_item_id", "".to_string()) + ("base_item_id", String::new()) } }; let tass_item_id_field = match item_type { diff --git a/src/db/data_providers/shop_fetcher.rs b/src/db/data_providers/shop_fetcher.rs index 9da37cb..17f0166 100644 --- a/src/db/data_providers/shop_fetcher.rs +++ b/src/db/data_providers/shop_fetcher.rs @@ -157,10 +157,7 @@ pub async fn fetch_weapons( el.item_core.traits = fetch_item_traits(conn, el.item_core.id).await?; el.weapon_data.property_runes = fetch_weapon_runes(conn, el.weapon_data.id).await?; el.weapon_data.damage_data = fetch_weapon_damage_data(conn, el.weapon_data.id).await?; - result_vec.push(Weapon { - item_core: el.item_core, - weapon_data: el.weapon_data, - }) + result_vec.push(el); } Ok(result_vec) } @@ -187,10 +184,7 @@ pub async fn fetch_armors(conn: &Pool, cursor: u32, page_size: i16) -> R for mut el in x { el.item_core.traits = fetch_item_traits(conn, el.item_core.id).await?; el.armor_data.property_runes = fetch_armor_runes(conn, el.armor_data.id).await?; - result_vec.push(Armor { - item_core: el.item_core, - armor_data: el.armor_data, - }) + result_vec.push(el); } Ok(result_vec) } @@ -219,10 +213,7 @@ pub async fn fetch_shields( let mut result_vec = Vec::new(); for mut el in x { el.item_core.traits = fetch_item_traits(conn, el.item_core.id).await?; - result_vec.push(Shield { - item_core: el.item_core, - shield_data: el.shield_data, - }) + result_vec.push(el); } Ok(result_vec) } @@ -267,7 +258,7 @@ pub async fn fetch_items_with_filters( + filters.n_of_weapons + filters.n_of_armors + filters.n_of_consumables; - if items.len() as i64 >= n_of_items_to_return { + if i64::try_from(items.len()).unwrap_or(i64::MAX) >= n_of_items_to_return { debug!("Result vector is the correct size, no more operations needed"); return Ok(items); } @@ -284,7 +275,7 @@ pub async fn fetch_items_with_filters( fn fill_item_vec_to_len(item_vec: &[&Item], desired_len: i64) -> Vec { let mut og_vec: Vec = item_vec.iter().map(|x| (*x).clone()).collect(); - for _ in 0..(item_vec.len() as i64 - desired_len) { + for _ in 0..(i64::try_from(item_vec.len()).unwrap_or(i64::MAX) - desired_len) { if let Some(x) = item_vec.get(fastrand::usize(0..item_vec.len())) { og_vec.push((*x).clone()); } diff --git a/src/db/shop_proxy.rs b/src/db/shop_proxy.rs index 7487068..2291c57 100644 --- a/src/db/shop_proxy.rs +++ b/src/db/shop_proxy.rs @@ -67,7 +67,7 @@ pub async fn get_paginated_items( let curr_slice: Vec = filtered_list .iter() .skip(pagination.paginated_request.cursor as usize) - .take(pagination.paginated_request.page_size as usize) + .take(pagination.paginated_request.page_size.unsigned_abs() as usize) .cloned() .collect(); @@ -104,7 +104,7 @@ async fn get_list(app_state: &AppState) -> Vec { weapon_data: None, armor_data: None, shield_data: None, - }) + }); } for el in get_all_weapons_from_db(app_state).await.unwrap_or(vec![]) { response_vec.push(ResponseItem { @@ -112,7 +112,7 @@ async fn get_list(app_state: &AppState) -> Vec { weapon_data: Some(el.weapon_data), armor_data: None, shield_data: None, - }) + }); } for el in get_all_armors_from_db(app_state).await.unwrap_or(vec![]) { response_vec.push(ResponseItem { @@ -120,7 +120,7 @@ async fn get_list(app_state: &AppState) -> Vec { weapon_data: None, armor_data: Some(el.armor_data), shield_data: None, - }) + }); } for el in get_all_shields_from_db(app_state).await.unwrap() { response_vec.push(ResponseItem { @@ -128,7 +128,7 @@ async fn get_list(app_state: &AppState) -> Vec { weapon_data: None, armor_data: None, shield_data: Some(el.shield_data), - }) + }); } response_vec } @@ -136,18 +136,17 @@ async fn get_list(app_state: &AppState) -> Vec { /// Gets all the runtime sources. It will cache the result #[once(sync_writes = true)] pub async fn get_all_sources(app_state: &AppState) -> Vec { - match get_all_items_from_db(app_state).await { - Ok(v) => v - .into_iter() - .map(|x| x.source) - .unique() - .filter(|x| !x.is_empty()) - .sorted() - .collect(), - Err(_) => { - vec![] - } - } + get_all_items_from_db(app_state).await.map_or_else( + |_| vec![], + |v| { + v.into_iter() + .map(|x| x.source) + .unique() + .filter(|x| !x.is_empty()) + .sorted() + .collect() + }, + ) } /// Gets all the runtime traits. It will cache the result diff --git a/src/lib.rs b/src/lib.rs index dac3402..6e597da 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,10 @@ use std::num::NonZero; use utoipa::OpenApi; use utoipa_swagger_ui::SwaggerUi; +#[derive(OpenApi)] +#[openapi(paths(index))] +struct ApiDoc; + #[derive(Clone)] pub struct AppState { conn: Pool, @@ -65,19 +69,19 @@ fn get_service_startup_state() -> StartupState { } fn get_service_port() -> u16 { - match env::var("SERVICE_PORT").ok() { - None => 25566, - Some(port) => port.parse::().unwrap_or(25566), - } + env::var("SERVICE_PORT") + .ok() + .map_or(25566, |port| port.parse().unwrap_or(25566)) } fn get_service_workers() -> usize { let available_cpus = usize::from(std::thread::available_parallelism().unwrap_or(NonZero::new(1).unwrap())); - match env::var("N_OF_SERVICE_WORKERS").ok() { - None => available_cpus, - Some(n_of_workers) => n_of_workers.parse::().unwrap_or(available_cpus), - } + env::var("N_OF_SERVICE_WORKERS") + .ok() + .map_or(available_cpus, |n_of_workers| { + n_of_workers.parse().unwrap_or(available_cpus) + }) } fn init_docs(openapi: &mut utoipa::openapi::OpenApi) { @@ -104,11 +108,7 @@ pub async fn start( } InitializeLogResponsibility::Delegated => {} // do nothing, someone else has already initialized them } - let db_url = if let Some(x) = db_location { - x - } else { - get_service_db_url() - }; + let db_url = db_location.map_or_else(get_service_db_url, |x| x); let service_ip = get_service_ip(); let service_port = get_service_port(); let startup_state: StartupState = get_service_startup_state(); @@ -139,10 +139,6 @@ pub async fn start( ); // Swagger initialization - #[derive(OpenApi)] - #[openapi(paths(index))] - struct ApiDoc; - let mut openapi = ApiDoc::openapi(); init_docs(&mut openapi); diff --git a/src/models/creature/creature_component/creature_combat.rs b/src/models/creature/creature_component/creature_combat.rs index fa8c8a4..a396583 100644 --- a/src/models/creature/creature_component/creature_combat.rs +++ b/src/models/creature/creature_component/creature_combat.rs @@ -38,7 +38,7 @@ pub struct CreatureCombatData { } impl CreatureCombatData { - fn add_mod_to_saving_throws_and_ac_and_wp_to_hit(self, modifier: i64) -> CreatureCombatData { + fn add_mod_to_saving_throws_and_ac_and_wp_to_hit(self, modifier: i64) -> Self { let mut com_data = self; let weapons: Vec = com_data .weapons @@ -49,7 +49,7 @@ impl CreatureCombatData { wp }) .collect(); - com_data.ac = (com_data.ac as i64 + modifier) as i8; + com_data.ac = (i64::from(com_data.ac) + modifier) as i8; com_data.saving_throws.fortitude += modifier; com_data.saving_throws.reflex += modifier; com_data.saving_throws.will += modifier; @@ -57,7 +57,7 @@ impl CreatureCombatData { com_data } - fn add_mod_to_dmg(self, modifier: i64) -> CreatureCombatData { + fn add_mod_to_dmg(self, modifier: i64) -> Self { let mut com_data = self; let weapons: Vec = com_data .weapons @@ -82,16 +82,18 @@ impl CreatureCombatData { 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)) + /// 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) -> Self { + self.add_mod_to_saving_throws_and_ac_and_wp_to_hit( + -i64::try_from(pwl_mod).unwrap_or(i64::MAX), + ) } /// Increase/Decrease the damage of its Strikes and other offensive abilities by 2. /// If the creature has limits on how many times or how often it can use an ability /// (such as a spellcaster’s spells or a dragon’s breath), decrease the damage by 4 instead. /// Increase/Decrease the creature’s AC, attack modifiers, DCs, saving throws by 2. - pub fn convert_from_base_to_variant(self, variant: &CreatureVariant) -> CreatureCombatData { + pub fn convert_from_base_to_variant(self, variant: CreatureVariant) -> Self { let modifier = variant.to_adjustment_modifier(); self.add_mod_to_saving_throws_and_ac_and_wp_to_hit(modifier) .add_mod_to_dmg(modifier) diff --git a/src/models/creature/creature_component/creature_core.rs b/src/models/creature/creature_component/creature_core.rs index 04f6c97..6820b3a 100644 --- a/src/models/creature/creature_component/creature_core.rs +++ b/src/models/creature/creature_component/creature_core.rs @@ -61,14 +61,14 @@ impl<'r> FromRow<'r, SqliteRow> for EssentialData { let rarity: String = row.try_get("rarity")?; let size: String = row.try_get("size")?; let alignment: String = row.try_get("alignment")?; - Ok(EssentialData { + Ok(Self { id: row.try_get("id")?, aon_id: row.try_get("aon_id").ok(), name: row.try_get("name")?, hp: row.try_get("hp")?, base_level: row.try_get("level")?, size: SizeEnum::from(size), - family: row.try_get("family").unwrap_or(String::from("-")), + family: row.try_get("family").unwrap_or_else(|_| String::from("-")), rarity: RarityEnum::from(rarity), license: row.try_get("license")?, remaster: row.try_get("remaster")?, @@ -81,7 +81,7 @@ impl<'r> FromRow<'r, SqliteRow> for EssentialData { impl<'r> FromRow<'r, SqliteRow> for DerivedData { fn from_row(row: &'r SqliteRow) -> Result { - Ok(DerivedData { + Ok(Self { archive_link: row.try_get("archive_link").ok(), is_melee: row.try_get("is_melee")?, is_ranged: row.try_get("is_ranged")?, @@ -99,7 +99,7 @@ impl<'r> FromRow<'r, SqliteRow> for DerivedData { impl<'r> FromRow<'r, SqliteRow> for CreatureCoreData { fn from_row(row: &'r SqliteRow) -> Result { - Ok(CreatureCoreData { + Ok(Self { essential: EssentialData::from_row(row)?, derived: DerivedData::from_row(row)?, traits: vec![], diff --git a/src/models/creature/creature_component/creature_extra.rs b/src/models/creature/creature_component/creature_extra.rs index 85d0349..9301db3 100644 --- a/src/models/creature/creature_component/creature_extra.rs +++ b/src/models/creature/creature_component/creature_extra.rs @@ -45,10 +45,10 @@ pub struct CreatureExtraData { } impl CreatureExtraData { - fn add_mod_to_perception_and_skill_mods(self, modifier: i64) -> CreatureExtraData { + fn add_mod_to_perception_and_skill_mods(self, modifier: i64) -> Self { 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.perception = (i64::from(ex_data.perception) + modifier) as i8; ex_data.skills = ex_data .skills @@ -61,13 +61,13 @@ impl CreatureExtraData { 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)) + /// Lowers skill and perception by the given `pwl_mod` + pub fn convert_from_base_to_pwl(self, pwl_mod: u64) -> Self { + self.add_mod_to_perception_and_skill_mods(-i64::try_from(pwl_mod).unwrap_or(i64::MAX)) } /// Increase/Decrease Perception, and skill modifiers by 2. - pub fn convert_from_base_to_variant(self, variant: &CreatureVariant) -> CreatureExtraData { + pub fn convert_from_base_to_variant(self, variant: CreatureVariant) -> Self { self.add_mod_to_perception_and_skill_mods(variant.to_adjustment_modifier()) } } diff --git a/src/models/creature/creature_component/creature_spell_caster.rs b/src/models/creature/creature_component/creature_spell_caster.rs index 3adfa65..1f2b46e 100644 --- a/src/models/creature/creature_component/creature_spell_caster.rs +++ b/src/models/creature/creature_component/creature_spell_caster.rs @@ -11,7 +11,7 @@ pub struct CreatureSpellCasterData { } impl CreatureSpellCasterData { - pub fn add_mod_to_spellcaster_atk_and_dc(self, modifier: i64) -> CreatureSpellCasterData { + pub fn add_mod_to_spellcaster_atk_and_dc(self, modifier: i64) -> Self { let mut spell_data = self; spell_data.spell_caster_entry.spell_casting_atk_mod = spell_data @@ -28,17 +28,14 @@ impl CreatureSpellCasterData { } /// 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)) + pub fn convert_from_base_to_pwl(self, pwl_mod: u64) -> Self { + self.add_mod_to_spellcaster_atk_and_dc(-i64::try_from(pwl_mod).unwrap_or(i64::MAX)) } /// Increase/Decrease the damage of its Strikes and other offensive abilities by 2. /// If the creature has limits on how many times or how often it can use an ability /// (such as a spellcaster’s spells or a dragon’s breath), decrease the damage by 4 instead. - pub fn convert_from_base_to_variant( - self, - variant: &CreatureVariant, - ) -> CreatureSpellCasterData { + pub fn convert_from_base_to_variant(self, variant: CreatureVariant) -> Self { self.add_mod_to_spellcaster_atk_and_dc(variant.to_adjustment_modifier()) } } diff --git a/src/models/creature/creature_filter_enum.rs b/src/models/creature/creature_filter_enum.rs index 36ca0a9..6a2b21e 100644 --- a/src/models/creature/creature_filter_enum.rs +++ b/src/models/creature/creature_filter_enum.rs @@ -33,43 +33,43 @@ pub enum CreatureFilter { impl fmt::Display for CreatureFilter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - CreatureFilter::Level => { + Self::Level => { write!(f, "level") } - CreatureFilter::Family => { + Self::Family => { write!(f, "family") } - CreatureFilter::Size => { + Self::Size => { write!(f, "size") } - CreatureFilter::Rarity => { + Self::Rarity => { write!(f, "rarity") } - CreatureFilter::Melee => { + Self::Melee => { write!(f, "is_melee") } - CreatureFilter::Ranged => { + Self::Ranged => { write!(f, "is_ranged") } - CreatureFilter::SpellCaster => { + Self::SpellCaster => { write!(f, "is_spell_caster") } - CreatureFilter::Traits => { + Self::Traits => { write!(f, "traits") } - CreatureFilter::CreatureTypes => { + Self::CreatureTypes => { write!(f, "cr_type") } - CreatureFilter::CreatureRoles => { + Self::CreatureRoles => { write!(f, "creature_roles") } - CreatureFilter::Alignment => { + Self::Alignment => { write!(f, "alignment") } - CreatureFilter::PathfinderVersion => { + Self::PathfinderVersion => { write!(f, "remaster") } - CreatureFilter::Sources => { + Self::Sources => { write!(f, "sources") } } diff --git a/src/models/creature/creature_metadata/alignment_enum.rs b/src/models/creature/creature_metadata/alignment_enum.rs index ac44b66..2460a97 100644 --- a/src/models/creature/creature_metadata/alignment_enum.rs +++ b/src/models/creature/creature_metadata/alignment_enum.rs @@ -56,10 +56,10 @@ 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 { + fn from(tuple: (&Vec, bool)) -> Self { // If remaster then it's always no alignment if tuple.1 { - return AlignmentEnum::No; + return Self::No; } let string_traits: Vec = tuple.0.iter().map(|x| x.to_uppercase()).collect(); let is_good = string_traits.contains(&"GOOD".to_string()); @@ -68,41 +68,41 @@ impl From<(&Vec, bool)> for AlignmentEnum { let is_lawful = string_traits.contains(&"LAWFUL".to_string()); if is_good { if is_chaos { - return AlignmentEnum::Cg; + return Self::Cg; } if is_lawful { - return AlignmentEnum::Lg; + return Self::Lg; } - return AlignmentEnum::Ng; + return Self::Ng; } if is_evil { if is_chaos { - return AlignmentEnum::Ce; + return Self::Ce; } if is_lawful { - return AlignmentEnum::Le; + return Self::Le; } - return AlignmentEnum::Ne; + return Self::Ne; } if is_chaos { - return AlignmentEnum::Cn; + return Self::Cn; } if is_lawful { - return AlignmentEnum::Ln; + return Self::Ln; } - AlignmentEnum::N + Self::N } } impl From for AlignmentEnum { fn from(value: String) -> Self { - AlignmentEnum::from_str(value.as_str()).unwrap_or_default() + Self::from_str(value.as_str()).unwrap_or_default() } } impl From<&String> for AlignmentEnum { fn from(value: &String) -> Self { - AlignmentEnum::from_str(value.as_str()).unwrap_or_default() + Self::from_str(value.as_str()).unwrap_or_default() } } @@ -110,35 +110,35 @@ impl FromStr for AlignmentEnum { type Err = (); fn from_str(s: &str) -> Result { match s.to_uppercase().as_str() { - "CE" => Ok(AlignmentEnum::Ce), - "CN" => Ok(AlignmentEnum::Cn), - "CG" => Ok(AlignmentEnum::Cg), - "NE" => Ok(AlignmentEnum::Ne), - "N" => Ok(AlignmentEnum::N), - "NG" => Ok(AlignmentEnum::Ng), - "LE" => Ok(AlignmentEnum::Le), - "LN" => Ok(AlignmentEnum::Ln), - "LG" => Ok(AlignmentEnum::Lg), - "ANY" => Ok(AlignmentEnum::Any), - _ => Ok(AlignmentEnum::No), + "CE" => Ok(Self::Ce), + "CN" => Ok(Self::Cn), + "CG" => Ok(Self::Cg), + "NE" => Ok(Self::Ne), + "N" => Ok(Self::N), + "NG" => Ok(Self::Ng), + "LE" => Ok(Self::Le), + "LN" => Ok(Self::Ln), + "LG" => Ok(Self::Lg), + "ANY" => Ok(Self::Any), + _ => Ok(Self::No), } } } impl Clone for AlignmentEnum { - fn clone(&self) -> AlignmentEnum { + fn clone(&self) -> Self { match self { - AlignmentEnum::Ce => AlignmentEnum::Ce, - AlignmentEnum::Cn => AlignmentEnum::Cn, - AlignmentEnum::Cg => AlignmentEnum::Cg, - AlignmentEnum::Ne => AlignmentEnum::Ne, - AlignmentEnum::N => AlignmentEnum::N, - AlignmentEnum::Ng => AlignmentEnum::Ng, - AlignmentEnum::Le => AlignmentEnum::Le, - AlignmentEnum::Ln => AlignmentEnum::Ln, - AlignmentEnum::Lg => AlignmentEnum::Lg, - AlignmentEnum::No => AlignmentEnum::No, - AlignmentEnum::Any => AlignmentEnum::Any, + Self::Ce => Self::Ce, + Self::Cn => Self::Cn, + Self::Cg => Self::Cg, + Self::Ne => Self::Ne, + Self::N => Self::N, + Self::Ng => Self::Ng, + Self::Le => Self::Le, + Self::Ln => Self::Ln, + Self::Lg => Self::Lg, + Self::No => Self::No, + Self::Any => Self::Any, } } } diff --git a/src/models/creature/creature_metadata/creature_role.rs b/src/models/creature/creature_metadata/creature_role.rs index 88e98e9..9e1ffa9 100644 --- a/src/models/creature/creature_metadata/creature_role.rs +++ b/src/models/creature/creature_metadata/creature_role.rs @@ -40,13 +40,13 @@ fn get_dmg_from_regex(raw_str: &str) -> Option { impl CreatureRoleEnum { pub fn to_db_column(&self) -> String { match self { - CreatureRoleEnum::Brute => String::from("brute_percentage"), - CreatureRoleEnum::MagicalStriker => String::from("magical_striker_percentage"), - CreatureRoleEnum::SkillParagon => String::from("skill_paragon_percentage"), - CreatureRoleEnum::Skirmisher => String::from("skirmisher_percentage"), - CreatureRoleEnum::Sniper => String::from("sniper_percentage"), - CreatureRoleEnum::Soldier => String::from("soldier_percentage"), - CreatureRoleEnum::SpellCaster => String::from("spell_caster_percentage"), + Self::Brute => String::from("brute_percentage"), + Self::MagicalStriker => String::from("magical_striker_percentage"), + Self::SkillParagon => String::from("skill_paragon_percentage"), + Self::Skirmisher => String::from("skirmisher_percentage"), + Self::Sniper => String::from("sniper_percentage"), + Self::Soldier => String::from("soldier_percentage"), + Self::SpellCaster => String::from("spell_caster_percentage"), } } pub fn from_creature_with_given_scales( @@ -55,55 +55,47 @@ impl CreatureRoleEnum { cr_combat: &CreatureCombatData, cr_spells: &CreatureSpellCasterData, scales: &CreatureScales, - ) -> BTreeMap { + ) -> BTreeMap { let mut roles = BTreeMap::new(); roles.insert( Self::Brute, - is_brute(cr_core, cr_extra, cr_combat, scales) - .map(|x| (x * 100.).round() as i64) - .unwrap_or(0), + is_brute(cr_core, cr_extra, cr_combat, scales).map_or(0, |x| (x * 100.).round() as i64), ); roles.insert( Self::MagicalStriker, is_magical_striker(cr_core, cr_spells, cr_combat, scales) - .map(|x| (x * 100.).round() as i64) - .unwrap_or(0), + .map_or(0, |x| (x * 100.).round() as i64), ); roles.insert( Self::SkillParagon, is_skill_paragon(cr_core, cr_extra, cr_combat, scales) - .map(|x| (x * 100.).round() as i64) - .unwrap_or(0), + .map_or(0, |x| (x * 100.).round() as i64), ); roles.insert( Self::Skirmisher, is_skirmisher(cr_core, cr_extra, cr_combat, scales) - .map(|x| (x * 100.).round() as i64) - .unwrap_or(0), + .map_or(0, |x| (x * 100.).round() as i64), ); roles.insert( Self::Sniper, is_sniper(cr_core, cr_extra, cr_combat, scales) - .map(|x| (x * 100.).round() as i64) - .unwrap_or(0), + .map_or(0, |x| (x * 100.).round() as i64), ); roles.insert( Self::Soldier, is_soldier(cr_core, cr_extra, cr_combat, scales) - .map(|x| (x * 100.).round() as i64) - .unwrap_or(0), + .map_or(0, |x| (x * 100.).round() as i64), ); roles.insert( Self::SpellCaster, is_spellcaster(cr_core, cr_spells, cr_combat, cr_extra, scales) - .map(|x| (x * 100.).round() as i64) - .unwrap_or(0), + .map_or(0, |x| (x * 100.).round() as i64), ); roles } pub fn list() -> Vec { - CreatureRoleEnum::iter().map(|x| x.to_string()).collect() + Self::iter().map(|x| x.to_string()).collect() } } // Brute @@ -117,7 +109,7 @@ fn is_brute( let lvl = cr_core.base_level; let per_scales = scales.perception_scales.get(&lvl)?; // low Perception; - score += calculate_ub_distance(per_scales.moderate, cr_extra.perception as i64 + 1); + score += calculate_ub_distance(per_scales.moderate, i64::from(cr_extra.perception) + 1); let ability_scales = scales.ability_scales.get(&lvl)?; // high or extreme Str modifier, score += calculate_lb_distance(ability_scales.high, cr_extra.ability_scores.strength); @@ -143,7 +135,7 @@ fn is_brute( score += calculate_ub_distance(saving_scales.moderate, cr_combat.saving_throws.will + 1); let ac_scales = scales.ac_scales.get(&lvl)?; // moderate or low AC; - score += calculate_ub_distance(ac_scales.high, cr_combat.ac as i64 + 1); + score += calculate_ub_distance(ac_scales.high, i64::from(cr_combat.ac) + 1); // high HP; let hp_scales = scales.hp_scales.get(&lvl)?; score += calculate_lb_distance(hp_scales.high_lb, cr_core.hp); @@ -172,7 +164,7 @@ fn is_brute( .min(); score += wp_distance.unwrap_or(MISSING_FIELD_DISTANCE); - Some(f64::E().powf(-0.2 * (score as f64))) + Some(f64::E().powf(-0.2 * f64::from(score))) } // Sniper @@ -188,7 +180,7 @@ fn is_sniper( // high Perception (chosen moderate // !!!This is a critical stat, upping it will half creature result!!! // ); - score += calculate_lb_distance(per_scales.moderate, cr_extra.perception as i64); + score += calculate_lb_distance(per_scales.moderate, i64::from(cr_extra.perception)); let ability_scales = scales.ability_scales.get(&lvl)?; // high Dex modifier (chosen moderate); score += calculate_lb_distance(ability_scales.moderate, cr_extra.ability_scores.dexterity); @@ -217,7 +209,7 @@ fn is_sniper( }) .min(); score += wp_distance.unwrap_or(MISSING_FIELD_DISTANCE); - Some(f64::E().powf(-0.2 * (score as f64))) + Some(f64::E().powf(-0.2 * f64::from(score))) } // Skirmisher fn is_skirmisher( @@ -243,10 +235,10 @@ fn is_skirmisher( score += cr_extra .speeds .values() - .map(|speed_value| calculate_lb_distance(30, *speed_value as i64)) + .map(|speed_value| calculate_lb_distance(30, i64::from(*speed_value))) .min() .unwrap_or(MISSING_FIELD_DISTANCE); - Some(f64::E().powf(-0.2 * (score as f64))) + Some(f64::E().powf(-0.2 * f64::from(score))) } // Soldier pub fn is_soldier( @@ -262,7 +254,7 @@ pub fn is_soldier( score += calculate_lb_distance(ability_scales.high, cr_extra.ability_scores.strength); let ac_scales = scales.ac_scales.get(&lvl)?; // high to extreme AC; - score += calculate_lb_distance(ac_scales.high, cr_combat.ac as i64); + score += calculate_lb_distance(ac_scales.high, i64::from(cr_combat.ac)); let saving_scales = scales.saving_throw_scales.get(&lvl)?; // high Fortitude; score += calculate_lb_distance(saving_scales.high, cr_combat.saving_throws.fortitude); @@ -295,7 +287,7 @@ pub fn is_soldier( }) { score += 3; } - Some(f64::E().powf(-0.2 * (score as f64))) + Some(f64::E().powf(-0.2 * f64::from(score))) } // Magical Striker @@ -333,11 +325,12 @@ pub fn is_magical_striker( score += MISSING_FIELD_DISTANCE; } if (cr_spell.spells.len() as f64) < (cr_core.base_level as f64 / 2.).ceil() - 1. { - score += - (((cr_core.base_level as f64 / 2.).ceil() as i64) - 1 - (cr_spell.spells.len() as i64)) - .unsigned_abs() as u16; + score += (((cr_core.base_level as f64 / 2.).ceil() as i64) + - 1 + - (i64::try_from(cr_spell.spells.len()).unwrap_or(i64::MAX))) + .unsigned_abs() as u16; } - Some(f64::E().powf(-0.2 * (score as f64))) + Some(f64::E().powf(-0.2 * f64::from(score))) } // Skill Paragon @@ -371,13 +364,16 @@ fn is_skill_paragon( // many skills at moderate or high and potentially one or two extreme skills; // Many is kinda up in the air, I'll set 70% - let cr_skill_amount = cr_extra.skills.len() as i64 * 70 / 100; + let cr_skill_amount = i64::try_from(cr_extra.skills.len()).unwrap_or(i64::MAX) / 100 * 70; // if there aren't at least 70% of skill in the moderate-high range - score += (cr_extra - .skills - .iter() - .filter(|x| x.modifier >= saving_scales.moderate) - .count() as i64 + score += (i64::try_from( + cr_extra + .skills + .iter() + .filter(|x| x.modifier >= saving_scales.moderate) + .count(), + ) + .unwrap_or(i64::MAX) - cr_skill_amount) .unsigned_abs() as u16; // at least two special ability to use the creature's skills in combat @@ -394,7 +390,7 @@ fn is_skill_paragon( { score += MISSING_FIELD_DISTANCE; } - Some(f64::E().powf(-0.2 * (score as f64))) + Some(f64::E().powf(-0.2 * f64::from(score))) } // Spellcaster fn is_spellcaster( @@ -427,8 +423,9 @@ fn is_spellcaster( ); // prepared or spontaneous spells up to half the creature’s level (rounded up) if (cr_spell.spells.len() as f64) < (cr_core.base_level as f64 / 2.).ceil() { - score += (((cr_core.base_level as f64 / 2.).ceil() as i64) - (cr_spell.spells.len() as i64)) - .unsigned_abs() as u16; + score += (((cr_core.base_level as f64 / 2.).ceil() as i64) + - i64::try_from(cr_spell.spells.len()).unwrap_or(i64::MAX)) + .unsigned_abs() as u16; } let ability_scales = scales.ability_scales.get(&lvl)?; // high or extreme modifier for the corresponding mental ability; @@ -438,20 +435,20 @@ fn is_spellcaster( .max(cr_extra.ability_scores.intelligence) .max(cr_extra.ability_scores.charisma); score += calculate_lb_distance(ability_scales.high, best_mental_ability); - Some(f64::E().powf(-0.2 * (score as f64))) + Some(f64::E().powf(-0.2 * f64::from(score))) } impl FromStr for CreatureRoleEnum { type Err = (); fn from_str(s: &str) -> Result { match s.to_uppercase().as_str() { - "BRUTE" => Ok(CreatureRoleEnum::Brute), - "MAGICAL STRIKER" | "MAGICALSTRIKER" => Ok(CreatureRoleEnum::MagicalStriker), - "SKILL PARAGON" | "SKILLPARAGON" => Ok(CreatureRoleEnum::SkillParagon), - "SKIRMISHER" => Ok(CreatureRoleEnum::Skirmisher), - "SNIPER" => Ok(CreatureRoleEnum::Sniper), - "SOLDIER" => Ok(CreatureRoleEnum::Soldier), - "SPELLCASTER" | "SPELL CASTER" => Ok(CreatureRoleEnum::SpellCaster), + "BRUTE" => Ok(Self::Brute), + "MAGICAL STRIKER" | "MAGICALSTRIKER" => Ok(Self::MagicalStriker), + "SKILL PARAGON" | "SKILLPARAGON" => Ok(Self::SkillParagon), + "SKIRMISHER" => Ok(Self::Skirmisher), + "SNIPER" => Ok(Self::Sniper), + "SOLDIER" => Ok(Self::Soldier), + "SPELLCASTER" | "SPELL CASTER" => Ok(Self::SpellCaster), _ => Err(()), } } @@ -460,25 +457,25 @@ impl FromStr for CreatureRoleEnum { impl fmt::Display for CreatureRoleEnum { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - CreatureRoleEnum::Brute => { + Self::Brute => { write!(f, "Brute") } - CreatureRoleEnum::MagicalStriker => { + Self::MagicalStriker => { write!(f, "Magical Striker") } - CreatureRoleEnum::SkillParagon => { + Self::SkillParagon => { write!(f, "Skill Paragon") } - CreatureRoleEnum::Skirmisher => { + Self::Skirmisher => { write!(f, "Skirmisher") } - CreatureRoleEnum::Sniper => { + Self::Sniper => { write!(f, "Sniper") } - CreatureRoleEnum::Soldier => { + Self::Soldier => { write!(f, "Soldier") } - CreatureRoleEnum::SpellCaster => { + Self::SpellCaster => { write!(f, "SpellCaster") } } @@ -487,7 +484,7 @@ impl fmt::Display for CreatureRoleEnum { /// Calculate value distance from upper bound, lower than ub value will /// yield 0 -fn calculate_ub_distance(ub: i64, value: i64) -> u16 { +const fn calculate_ub_distance(ub: i64, value: i64) -> u16 { if value > ub { (value - ub).unsigned_abs() as u16 } else { @@ -495,9 +492,9 @@ fn calculate_ub_distance(ub: i64, value: i64) -> u16 { } } -/// Calculate value distance from lower bound, higher than lb value will +/// Calculate value distance from lower bound, `value` higher than `lb` will /// yield 0 -fn calculate_lb_distance(lb: i64, value: i64) -> u16 { +const fn calculate_lb_distance(lb: i64, value: i64) -> u16 { if value < lb { (lb - value).unsigned_abs() as u16 } else { @@ -506,7 +503,7 @@ fn calculate_lb_distance(lb: i64, value: i64) -> u16 { } /// Calculates value distance from bounds, it will exclude upper bound -fn calculate_dist(lb: i64, ub: i64, value: i64) -> u16 { +const fn calculate_dist(lb: i64, ub: i64, value: i64) -> u16 { if value < lb { (lb - value).unsigned_abs() as u16 } else if value >= ub { diff --git a/src/models/creature/creature_metadata/type_enum.rs b/src/models/creature/creature_metadata/type_enum.rs index f778fed..a304443 100644 --- a/src/models/creature/creature_metadata/type_enum.rs +++ b/src/models/creature/creature_metadata/type_enum.rs @@ -30,19 +30,19 @@ pub enum CreatureTypeEnum { impl From for CreatureTypeEnum { fn from(value: String) -> Self { - CreatureTypeEnum::from_str(value.as_str()).unwrap_or_default() + Self::from_str(value.as_str()).unwrap_or_default() } } impl From> for CreatureTypeEnum { fn from(value: Option) -> Self { - CreatureTypeEnum::from_str(value.unwrap_or_default().as_str()).unwrap_or_default() + Self::from_str(value.unwrap_or_default().as_str()).unwrap_or_default() } } impl From<&Option> for CreatureTypeEnum { fn from(value: &Option) -> Self { - CreatureTypeEnum::from_str(value.clone().unwrap_or_default().as_str()).unwrap_or_default() + Self::from_str(value.clone().unwrap_or_default().as_str()).unwrap_or_default() } } @@ -50,18 +50,17 @@ impl FromStr for CreatureTypeEnum { type Err = (); fn from_str(s: &str) -> Result { match s.to_uppercase().as_str() { - "MONSTER" => Ok(CreatureTypeEnum::Monster), - "NPC" => Ok(CreatureTypeEnum::Npc), - _ => Ok(CreatureTypeEnum::Monster), + "NPC" => Ok(Self::Npc), + _ => Ok(Self::Monster), } } } impl Clone for CreatureTypeEnum { - fn clone(&self) -> CreatureTypeEnum { + fn clone(&self) -> Self { match self { - CreatureTypeEnum::Monster => CreatureTypeEnum::Monster, - CreatureTypeEnum::Npc => CreatureTypeEnum::Npc, + Self::Monster => Self::Monster, + Self::Npc => Self::Npc, } } } diff --git a/src/models/creature/creature_metadata/variant_enum.rs b/src/models/creature/creature_metadata/variant_enum.rs index 2d9f491..c32d186 100644 --- a/src/models/creature/creature_metadata/variant_enum.rs +++ b/src/models/creature/creature_metadata/variant_enum.rs @@ -5,7 +5,18 @@ use strum::Display; use utoipa::ToSchema; #[derive( - Serialize, Deserialize, ToSchema, Display, Eq, Hash, PartialEq, Ord, PartialOrd, Default, + Copy, + Clone, + Serialize, + Deserialize, + ToSchema, + Display, + Eq, + Hash, + PartialEq, + Ord, + PartialOrd, + Default, )] pub enum CreatureVariant { Weak, @@ -14,30 +25,20 @@ pub enum CreatureVariant { Base, } -impl Clone for CreatureVariant { - fn clone(&self) -> CreatureVariant { - match self { - CreatureVariant::Elite => CreatureVariant::Elite, - CreatureVariant::Weak => CreatureVariant::Weak, - CreatureVariant::Base => CreatureVariant::Base, - } - } -} - impl CreatureVariant { - pub fn to_adjustment_modifier(&self) -> i64 { + pub const fn to_adjustment_modifier(self) -> i64 { match self { - CreatureVariant::Weak => -2, - CreatureVariant::Elite => 2, - CreatureVariant::Base => 0, + Self::Weak => -2, + Self::Elite => 2, + Self::Base => 0, } } - pub fn get_variant_level(&self, base_lvl: i64) -> i64 { + pub const fn get_variant_level(self, base_lvl: i64) -> i64 { match self { //Decrease the creature’s level by 1; if the creature is level 1, // instead decrease its level by 2. - CreatureVariant::Weak => { + Self::Weak => { if base_lvl == 1 { base_lvl - 2 } else { @@ -46,22 +47,22 @@ impl CreatureVariant { } //Increase the creature’s level by 1; if the creature is level –1 or 0, // instead increase its level by 2. - CreatureVariant::Elite => { + Self::Elite => { if base_lvl == -1 || base_lvl == 0 { base_lvl + 2 } else { base_lvl + 1 } } - CreatureVariant::Base => base_lvl, + Self::Base => base_lvl, } } - pub fn get_variant_hp(&self, base_hp: i64, starting_lvl: i64) -> i64 { + pub fn get_variant_hp(self, base_hp: i64, starting_lvl: i64) -> i64 { let hp_mod_map = match self { - CreatureVariant::Weak => hp_decrease_by_level(), - CreatureVariant::Elite => hp_increase_by_level(), - CreatureVariant::Base => { + Self::Weak => hp_decrease_by_level(), + Self::Elite => hp_increase_by_level(), + Self::Base => { hashmap! {} } }; @@ -72,15 +73,15 @@ impl CreatureVariant { .keys() .filter(|lvl| starting_lvl >= **lvl) .max() - .unwrap_or(hp_mod_map.keys().next().unwrap_or(&0)); + .unwrap_or_else(|| hp_mod_map.keys().next().unwrap_or(&0)); let hp_mod = *hp_mod_map.get(desired_key).unwrap_or(&0); (base_hp + hp_mod).max(1) } - pub fn get_variant_archive_link(&self, archive_link: Option) -> Option { + pub fn get_variant_archive_link(self, archive_link: Option) -> Option { match self { - CreatureVariant::Base => archive_link, - _ => add_boolean_query(&archive_link, &self.to_string(), true), + Self::Base => archive_link, + _ => add_boolean_query(Option::from(&archive_link), &self.to_string(), true), } } } diff --git a/src/models/creature/creature_struct.rs b/src/models/creature/creature_struct.rs index 6b66fd7..7d5c318 100644 --- a/src/models/creature/creature_struct.rs +++ b/src/models/creature/creature_struct.rs @@ -23,28 +23,28 @@ impl Creature { /// Decrease the creature’s HP based on its starting level. /// Decrease the creature’s AC, attack modifiers, DCs, saving throws, Perception, and skill modifiers by 2. /// Decrease the damage of its Strikes and other offensive abilities by 2. If the creature has limits on how many times or how often it can use an ability (such as a spellcaster’s spells or a dragon’s breath), decrease the damage by 4 instead. - pub fn convert_creature_to_variant(self, variant: CreatureVariant) -> Creature { - let mut cr = Self::from_core_with_variant(self.core_data, variant.clone()); + pub fn convert_creature_to_variant(self, variant: CreatureVariant) -> Self { + let mut cr = Self::from_core_with_variant(self.core_data, variant); cr.extra_data = self .extra_data - .map(|x| x.convert_from_base_to_variant(&variant)); + .map(|x| x.convert_from_base_to_variant(variant)); cr.combat_data = self .combat_data - .map(|x| x.convert_from_base_to_variant(&variant)); + .map(|x| x.convert_from_base_to_variant(variant)); cr.spell_caster_data = self .spell_caster_data - .map(|x| x.convert_from_base_to_variant(&variant)); + .map(|x| x.convert_from_base_to_variant(variant)); cr } - pub fn convert_creature_to_pwl(self) -> Creature { + pub fn convert_creature_to_pwl(self) -> Self { let pwl_mod = if self.core_data.essential.base_level >= 0 { - self.core_data.essential.base_level as u64 + self.core_data.essential.base_level.unsigned_abs() } else { 0 }; - Creature { + Self { 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)), @@ -56,7 +56,7 @@ impl Creature { .map(|x| x.convert_from_base_to_pwl(pwl_mod)), } } - pub fn from_core(core: CreatureCoreData) -> Creature { + pub fn from_core(core: CreatureCoreData) -> Self { let level = core.essential.base_level; let archive_link = core.derived.archive_link.clone(); Self { @@ -75,7 +75,7 @@ impl Creature { pub fn from_core_with_variant( mut core: CreatureCoreData, creature_variant: CreatureVariant, - ) -> Creature { + ) -> Self { let variant_hp = creature_variant.get_variant_hp(core.essential.hp, core.essential.base_level); let variant_archive_link = diff --git a/src/models/encounter_structs.rs b/src/models/encounter_structs.rs index 862a3e8..337696c 100644 --- a/src/models/encounter_structs.rs +++ b/src/models/encounter_structs.rs @@ -78,7 +78,7 @@ pub enum EncounterChallengeEnum { impl From for String { fn from(value: EncounterChallengeEnum) -> Self { - String::from(match value { + Self::from(match value { EncounterChallengeEnum::Trivial => "TRIVIAL", EncounterChallengeEnum::Low => "LOW", EncounterChallengeEnum::Moderate => "MODERATE", @@ -90,14 +90,14 @@ impl From for String { } impl EncounterChallengeEnum { - pub fn rand() -> EncounterChallengeEnum { - match fastrand::usize(0..EncounterChallengeEnum::COUNT) { - 0 => EncounterChallengeEnum::Trivial, - 1 => EncounterChallengeEnum::Low, - 2 => EncounterChallengeEnum::Moderate, - 3 => EncounterChallengeEnum::Severe, - 4 => EncounterChallengeEnum::Extreme, - _ => EncounterChallengeEnum::Impossible, + pub fn rand() -> Self { + match fastrand::usize(0..Self::COUNT) { + 0 => Self::Trivial, + 1 => Self::Low, + 2 => Self::Moderate, + 3 => Self::Severe, + 4 => Self::Extreme, + _ => Self::Impossible, } } } @@ -149,6 +149,7 @@ pub enum AdventureGroupEnum { MookSquad, } +#[derive(Copy, Clone)] pub struct ExpRange { pub lower_bound: i64, pub upper_bound: i64, diff --git a/src/models/item/armor_struct.rs b/src/models/item/armor_struct.rs index a0dbadf..ad3d92a 100644 --- a/src/models/item/armor_struct.rs +++ b/src/models/item/armor_struct.rs @@ -33,7 +33,7 @@ pub struct ArmorData { impl<'r> FromRow<'r, SqliteRow> for Armor { fn from_row(row: &'r SqliteRow) -> Result { let item_core = Item::from_row(row)?; - Ok(Armor { + Ok(Self { item_core, armor_data: ArmorData { id: row.try_get("armor_id")?, diff --git a/src/models/item/item_metadata/type_enum.rs b/src/models/item/item_metadata/type_enum.rs index 3b19242..57f8e42 100644 --- a/src/models/item/item_metadata/type_enum.rs +++ b/src/models/item/item_metadata/type_enum.rs @@ -34,22 +34,22 @@ impl ItemTypeEnum { /// It returns the generic table name of the given item type. fn to_db_table_name(&self) -> String { String::from(match self { - ItemTypeEnum::Consumable | ItemTypeEnum::Equipment => "ITEM", - ItemTypeEnum::Weapon => "WEAPON", - ItemTypeEnum::Armor => "ARMOR", - ItemTypeEnum::Shield => "SHIELD", + Self::Consumable | Self::Equipment => "ITEM", + Self::Weapon => "WEAPON", + Self::Armor => "ARMOR", + Self::Shield => "SHIELD", }) } } impl Clone for ItemTypeEnum { - fn clone(&self) -> ItemTypeEnum { + fn clone(&self) -> Self { match self { - ItemTypeEnum::Consumable => ItemTypeEnum::Consumable, - ItemTypeEnum::Equipment => ItemTypeEnum::Equipment, - ItemTypeEnum::Armor => ItemTypeEnum::Armor, - ItemTypeEnum::Weapon => ItemTypeEnum::Weapon, - ItemTypeEnum::Shield => ItemTypeEnum::Shield, + Self::Consumable => Self::Consumable, + Self::Equipment => Self::Equipment, + Self::Armor => Self::Armor, + Self::Weapon => Self::Weapon, + Self::Shield => Self::Shield, } } } @@ -58,11 +58,11 @@ impl FromStr for ItemTypeEnum { type Err = (); fn from_str(s: &str) -> Result { match s.to_uppercase().as_str() { - "CONSUMABLE" => Ok(ItemTypeEnum::Consumable), - "EQUIPMENT" => Ok(ItemTypeEnum::Equipment), - "WEAPON" => Ok(ItemTypeEnum::Weapon), - "ARMOR" => Ok(ItemTypeEnum::Armor), - "SHIELD" => Ok(ItemTypeEnum::Shield), + "CONSUMABLE" => Ok(Self::Consumable), + "EQUIPMENT" => Ok(Self::Equipment), + "WEAPON" => Ok(Self::Weapon), + "ARMOR" => Ok(Self::Armor), + "SHIELD" => Ok(Self::Shield), _ => Err(()), } } @@ -71,19 +71,19 @@ impl FromStr for ItemTypeEnum { impl Display for ItemTypeEnum { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - ItemTypeEnum::Consumable => { + Self::Consumable => { write!(f, "consumable") } - ItemTypeEnum::Equipment => { + Self::Equipment => { write!(f, "equipment") } - ItemTypeEnum::Weapon => { + Self::Weapon => { write!(f, "weapon") } - ItemTypeEnum::Armor => { + Self::Armor => { write!(f, "armor") } - ItemTypeEnum::Shield => { + Self::Shield => { write!(f, "shield") } } @@ -103,11 +103,11 @@ pub enum WeaponTypeEnum { } impl Clone for WeaponTypeEnum { - fn clone(&self) -> WeaponTypeEnum { + fn clone(&self) -> Self { match self { - WeaponTypeEnum::Ranged => WeaponTypeEnum::Ranged, - WeaponTypeEnum::Melee => WeaponTypeEnum::Melee, - WeaponTypeEnum::Generic => WeaponTypeEnum::Generic, + Self::Ranged => Self::Ranged, + Self::Melee => Self::Melee, + Self::Generic => Self::Generic, } } } @@ -116,9 +116,9 @@ impl FromStr for WeaponTypeEnum { type Err = (); fn from_str(s: &str) -> Result { match s.to_uppercase().as_str() { - "RANGED" => Ok(WeaponTypeEnum::Ranged), - "MELEE" => Ok(WeaponTypeEnum::Melee), - "GENERIC" => Ok(WeaponTypeEnum::Generic), + "RANGED" => Ok(Self::Ranged), + "MELEE" => Ok(Self::Melee), + "GENERIC" => Ok(Self::Generic), _ => Err(()), } } @@ -127,13 +127,13 @@ impl FromStr for WeaponTypeEnum { impl Display for WeaponTypeEnum { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - WeaponTypeEnum::Melee => { + Self::Melee => { write!(f, "melee") } - WeaponTypeEnum::Ranged => { + Self::Ranged => { write!(f, "ranged") } - WeaponTypeEnum::Generic => { + Self::Generic => { write!(f, "generic") } } diff --git a/src/models/item/item_struct.rs b/src/models/item/item_struct.rs index a35559b..07f8328 100644 --- a/src/models/item/item_struct.rs +++ b/src/models/item/item_struct.rs @@ -55,7 +55,7 @@ impl<'r> FromRow<'r, SqliteRow> for Item { let size: String = row.try_get("size")?; let type_str: String = row.try_get("item_type")?; let bulk: f64 = row.try_get("bulk")?; - Ok(Item { + Ok(Self { id: row.try_get("id")?, name: row.try_get("name")?, bulk: OrderedFloat::from(bulk), diff --git a/src/models/item/shield_struct.rs b/src/models/item/shield_struct.rs index f42a497..8820a34 100644 --- a/src/models/item/shield_struct.rs +++ b/src/models/item/shield_struct.rs @@ -24,7 +24,7 @@ pub struct ShieldData { impl<'r> FromRow<'r, SqliteRow> for Shield { fn from_row(row: &'r SqliteRow) -> Result { let item_core = Item::from_row(row)?; - Ok(Shield { + Ok(Self { item_core, shield_data: ShieldData { id: row.try_get("shield_id")?, diff --git a/src/models/item/weapon_struct.rs b/src/models/item/weapon_struct.rs index 9969741..d25de54 100644 --- a/src/models/item/weapon_struct.rs +++ b/src/models/item/weapon_struct.rs @@ -36,7 +36,7 @@ impl<'r> FromRow<'r, SqliteRow> for Weapon { fn from_row(row: &'r SqliteRow) -> Result { let item_core = Item::from_row(row)?; let wp_type = WeaponTypeEnum::from_str(row.try_get("weapon_type")?); - Ok(Weapon { + Ok(Self { item_core, weapon_data: WeaponData { id: row.try_get("weapon_id")?, @@ -61,11 +61,7 @@ impl Weapon { .iter() .map(|x| { let b = x.bonus_dmg as f64; - if let Some(dice) = x.clone().dice { - dice.get_avg_dmg(b) - } else { - 0 - } + x.clone().dice.map_or(0, |dice| dice.get_avg_dmg(b)) }) .sum() } @@ -82,7 +78,7 @@ pub struct DamageData { impl<'r> FromRow<'r, SqliteRow> for DamageData { fn from_row(row: &'r SqliteRow) -> Result { - Ok(DamageData { + Ok(Self { id: row.try_get("id")?, bonus_dmg: row.try_get("bonus_dmg")?, dmg_type: row.try_get("dmg_type").ok(), diff --git a/src/models/pf_version_enum.rs b/src/models/pf_version_enum.rs index 8e607fd..0ec2ba2 100644 --- a/src/models/pf_version_enum.rs +++ b/src/models/pf_version_enum.rs @@ -20,9 +20,9 @@ impl PathfinderVersionEnum { match self { // The db column is a boolean called "remaster" so we translate the enum to // FALSE if legacy, TRUE if remaster and TRUE, FALSE if both - PathfinderVersionEnum::Legacy => vec![String::from("FALSE")], - PathfinderVersionEnum::Remaster => vec![String::from("TRUE")], - PathfinderVersionEnum::Any => { + Self::Legacy => vec![String::from("FALSE")], + Self::Remaster => vec![String::from("TRUE")], + Self::Any => { vec![String::from("TRUE"), String::from("FALSE")] } } diff --git a/src/models/response_data.rs b/src/models/response_data.rs index 45d892d..908a87c 100644 --- a/src/models/response_data.rs +++ b/src/models/response_data.rs @@ -19,7 +19,7 @@ pub struct ResponseDataModifiers { pub spell_casting_data: Option, } -#[derive(Serialize, Deserialize, Clone, ToSchema, Hash, PartialEq)] +#[derive(Serialize, Deserialize, Clone, ToSchema, Hash, PartialEq, Eq)] pub struct ResponseCreature { pub core_data: CreatureCoreData, pub variant_data: CreatureVariantData, diff --git a/src/models/routers_validator_structs.rs b/src/models/routers_validator_structs.rs index 37ade05..837e6a1 100644 --- a/src/models/routers_validator_structs.rs +++ b/src/models/routers_validator_structs.rs @@ -92,7 +92,7 @@ pub struct PaginatedRequest { impl Default for PaginatedRequest { fn default() -> Self { - PaginatedRequest { + Self { cursor: 0, page_size: 100, } @@ -109,16 +109,17 @@ pub struct Dice { } impl Dice { - /// Dice roll will roll n dices with each roll in the range of 1<=result<=dice_size. - /// It returns the sum of n_of_dices rolls. + /// Dice roll will roll n dices with each roll in the range of 1<=result<=`dice_size`. + /// It returns the sum of `n_of_dices` rolls. /// IT SHOULD NEVER BE <1, OTHERWISE WE BREAK THE CONTRACT OF THE METHOD. - pub fn roll(&self) -> i64 { - let mut roll_result = 0; - for _ in 0..self.n_of_dices { + pub fn roll(&self) -> u16 { + let mut roll_result = 0_u16; + let n_of_dices = u16::from(self.n_of_dices); + for _ in 0..n_of_dices { // gen_range panics if n<2 (1..1), panic! // so we directly return 1 if that's the case - roll_result += if self.dice_size > 1 { - fastrand::i64(1..=self.dice_size as i64) + roll_result += if n_of_dices > 1 { + fastrand::u16(1..=n_of_dices) } else { 1 } @@ -133,27 +134,27 @@ impl Dice { // M = max value of the dice // N = number of dices // B = bonus dmg - let m = self.dice_size as f64; - let n = self.n_of_dices as f64; + let m = f64::from(self.dice_size); + let n = f64::from(self.n_of_dices); let b = bonus_dmg; - let avg: f64 = (((m + 1.) / 2.) * n) + b; + let avg: f64 = ((m + 1.) / 2.).mul_add(n, b); avg.floor() as i64 } - pub fn from_optional_dice_number_and_size( + pub const fn from_optional_dice_number_and_size( n_of_dices: Option, dice_size: Option, - ) -> Option { + ) -> Option { match (n_of_dices, dice_size) { - (Some(n), Some(s)) => Some(Dice { + (Some(n), Some(s)) => Some(Self { n_of_dices: n, dice_size: s, }), - (None, Some(s)) => Some(Dice { + (None, Some(s)) => Some(Self { n_of_dices: 1, dice_size: s, }), - (Some(n), None) => Some(Dice { + (Some(n), None) => Some(Self { n_of_dices: n, dice_size: 1, }), diff --git a/src/models/shared/rarity_enum.rs b/src/models/shared/rarity_enum.rs index 0841261..46dfb46 100644 --- a/src/models/shared/rarity_enum.rs +++ b/src/models/shared/rarity_enum.rs @@ -21,7 +21,7 @@ pub enum RarityEnum { impl From for RarityEnum { fn from(value: String) -> Self { - RarityEnum::from_str(value.as_str()).unwrap_or_default() + Self::from_str(value.as_str()).unwrap_or_default() } } @@ -29,22 +29,22 @@ impl FromStr for RarityEnum { type Err = (); fn from_str(s: &str) -> Result { match s.to_uppercase().as_str() { - "COMMON" => Ok(RarityEnum::Common), - "UNCOMMON" => Ok(RarityEnum::Uncommon), - "RARE" => Ok(RarityEnum::Rare), - "UNIQUE" => Ok(RarityEnum::Unique), + "COMMON" => Ok(Self::Common), + "UNCOMMON" => Ok(Self::Uncommon), + "RARE" => Ok(Self::Rare), + "UNIQUE" => Ok(Self::Unique), _ => Err(()), } } } impl Clone for RarityEnum { - fn clone(&self) -> RarityEnum { + fn clone(&self) -> Self { match self { - RarityEnum::Common => RarityEnum::Common, - RarityEnum::Uncommon => RarityEnum::Uncommon, - RarityEnum::Rare => RarityEnum::Rare, - RarityEnum::Unique => RarityEnum::Unique, + Self::Common => Self::Common, + Self::Uncommon => Self::Uncommon, + Self::Rare => Self::Rare, + Self::Unique => Self::Unique, } } } diff --git a/src/models/shared/size_enum.rs b/src/models/shared/size_enum.rs index f8a255a..18ddbdf 100644 --- a/src/models/shared/size_enum.rs +++ b/src/models/shared/size_enum.rs @@ -24,21 +24,21 @@ pub enum SizeEnum { } impl Clone for SizeEnum { - fn clone(&self) -> SizeEnum { + fn clone(&self) -> Self { match self { - SizeEnum::Tiny => SizeEnum::Tiny, - SizeEnum::Small => SizeEnum::Small, - SizeEnum::Medium => SizeEnum::Medium, - SizeEnum::Large => SizeEnum::Large, - SizeEnum::Huge => SizeEnum::Huge, - SizeEnum::Gargantuan => SizeEnum::Gargantuan, + Self::Tiny => Self::Tiny, + Self::Small => Self::Small, + Self::Medium => Self::Medium, + Self::Large => Self::Large, + Self::Huge => Self::Huge, + Self::Gargantuan => Self::Gargantuan, } } } impl From for SizeEnum { fn from(value: String) -> Self { - SizeEnum::from_str(value.as_str()).unwrap_or_default() + Self::from_str(value.as_str()).unwrap_or_default() } } @@ -46,12 +46,12 @@ impl FromStr for SizeEnum { type Err = (); fn from_str(s: &str) -> Result { match s.to_uppercase().as_str() { - "TINY" => Ok(SizeEnum::Tiny), - "SMALL" => Ok(SizeEnum::Small), - "MEDIUM" => Ok(SizeEnum::Medium), - "LARGE" => Ok(SizeEnum::Large), - "HUGE" => Ok(SizeEnum::Huge), - "GARGANTUAN" => Ok(SizeEnum::Gargantuan), + "TINY" => Ok(Self::Tiny), + "SMALL" => Ok(Self::Small), + "MEDIUM" => Ok(Self::Medium), + "LARGE" => Ok(Self::Large), + "HUGE" => Ok(Self::Huge), + "GARGANTUAN" => Ok(Self::Gargantuan), _ => Err(()), } } diff --git a/src/models/shop_structs.rs b/src/models/shop_structs.rs index 7a191e7..833f33e 100644 --- a/src/models/shop_structs.rs +++ b/src/models/shop_structs.rs @@ -30,7 +30,7 @@ pub struct ShopTemplateData { impl From for ShopTemplateData { fn from(template_enum: ShopTemplateEnum) -> Self { let (e_p, w_p, a_p, s_p) = template_enum.get_equippable_percentages(); - ShopTemplateData { + Self { name: template_enum.to_string(), description: template_enum.get_description(), equipment_percentage: e_p, @@ -68,17 +68,17 @@ pub enum ShopTemplateEnum { impl ShopTemplateEnum { /// Returns percentage of equipment, weapons, armor, shield for the given template - pub fn get_equippable_percentages(&self) -> (u8, u8, u8, u8) { + pub const fn get_equippable_percentages(&self) -> (u8, u8, u8, u8) { match self { - ShopTemplateEnum::Blacksmith => (10, 40, 25, 25), - ShopTemplateEnum::Alchemist => (100, 0, 0, 0), - ShopTemplateEnum::General => (70, 10, 10, 10), + Self::Blacksmith => (10, 40, 25, 25), + Self::Alchemist => (100, 0, 0, 0), + Self::General => (70, 10, 10, 10), } } pub fn get_allowed_item_types(&self) -> Vec { match self { - ShopTemplateEnum::Blacksmith => { + Self::Blacksmith | Self::General => { vec![ ItemTypeEnum::Armor, ItemTypeEnum::Shield, @@ -87,30 +87,15 @@ impl ShopTemplateEnum { ItemTypeEnum::Equipment, ] } - ShopTemplateEnum::Alchemist => { + Self::Alchemist => { vec![ItemTypeEnum::Consumable, ItemTypeEnum::Equipment] } - ShopTemplateEnum::General => { - vec![ - ItemTypeEnum::Armor, - ItemTypeEnum::Shield, - ItemTypeEnum::Weapon, - ItemTypeEnum::Consumable, - ItemTypeEnum::Equipment, - ] - } } } pub fn get_allowed_item_rarities(&self) -> Vec { match self { - ShopTemplateEnum::Blacksmith => { - vec![RarityEnum::Common, RarityEnum::Uncommon, RarityEnum::Rare] - } - ShopTemplateEnum::Alchemist => { - vec![RarityEnum::Common, RarityEnum::Uncommon, RarityEnum::Rare] - } - ShopTemplateEnum::General => { + Self::Blacksmith | Self::Alchemist | Self::General => { vec![RarityEnum::Common, RarityEnum::Uncommon, RarityEnum::Rare] } } @@ -119,10 +104,10 @@ impl ShopTemplateEnum { pub fn get_traits_whitelist(&self) -> Vec { // For future-proof, right now contains 0 logic match self { - ShopTemplateEnum::Blacksmith => { + Self::Blacksmith | Self::General => { vec![] } - ShopTemplateEnum::Alchemist => { + Self::Alchemist => { vec![ "Alchemical".to_string(), "Bomb".to_string(), @@ -130,21 +115,12 @@ impl ShopTemplateEnum { "Potion".to_string(), ] } - ShopTemplateEnum::General => { - vec![] - } } } - pub fn get_traits_blacklist(&self) -> Vec { + pub const fn get_traits_blacklist(&self) -> Vec { match self { - ShopTemplateEnum::Blacksmith => { - vec![] - } - ShopTemplateEnum::Alchemist => { - vec![] - } - ShopTemplateEnum::General => { + Self::Blacksmith | Self::Alchemist | Self::General => { vec![] } } @@ -152,13 +128,11 @@ impl ShopTemplateEnum { pub fn get_description(&self) -> String { String::from(match self { - ShopTemplateEnum::Blacksmith => { + Self::Blacksmith => { "Mainly weapons, armors and shields, sometimes equipment and consumables" } - ShopTemplateEnum::Alchemist => { - "Only equipment and consumables, no weapons, armors or shields" - } - ShopTemplateEnum::General => "All kinds of items", + Self::Alchemist => "Only equipment and consumables, no weapons, armors or shields", + Self::General => "All kinds of items", }) } } diff --git a/src/routes/bestiary.rs b/src/routes/bestiary.rs index 8a0ff22..2cf142a 100644 --- a/src/routes/bestiary.rs +++ b/src/routes/bestiary.rs @@ -319,7 +319,7 @@ pub async fn get_creature_types_list( )] #[get("/creature_roles")] pub async fn get_creature_roles_list() -> actix_web::Result { - Ok(web::Json(bestiary_service::get_creature_roles_list().await)) + Ok(web::Json(bestiary_service::get_creature_roles_list())) } #[utoipa::path( diff --git a/src/routes/encounter.rs b/src/routes/encounter.rs index 152411b..d2496c4 100644 --- a/src/routes/encounter.rs +++ b/src/routes/encounter.rs @@ -53,7 +53,7 @@ pub fn init_docs(doc: &mut utoipa::openapi::OpenApi) { pub async fn get_encounter_info( web::Json(body): web::Json, ) -> Result { - Ok(web::Json(encounter_service::get_encounter_info(body))) + Ok(web::Json(encounter_service::get_encounter_info(&body))) } #[utoipa::path( diff --git a/src/routes/shop.rs b/src/routes/shop.rs index da830e7..d96acc5 100644 --- a/src/routes/shop.rs +++ b/src/routes/shop.rs @@ -200,5 +200,5 @@ pub async fn get_items_traits_list(data: web::Data) -> actix_web::Resu )] #[get("/templates_data")] pub async fn get_templates_data() -> actix_web::Result { - Ok(web::Json(shop_service::get_shop_templates_data().await)) + Ok(web::Json(shop_service::get_shop_templates_data())) } diff --git a/src/services/bestiary_service.rs b/src/services/bestiary_service.rs index 566fffd..a1b8282 100644 --- a/src/services/bestiary_service.rs +++ b/src/services/bestiary_service.rs @@ -6,7 +6,7 @@ use crate::models::creature::creature_metadata::variant_enum::CreatureVariant; use crate::models::creature::creature_struct::Creature; 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::services::url_calculator::bestiary_next_url; use crate::AppState; use anyhow::Result; use serde::{Deserialize, Serialize}; @@ -95,7 +95,7 @@ pub async fn get_creature_types_list(app_state: &AppState) -> Vec { .await } -pub async fn get_creature_roles_list() -> Vec { +pub fn get_creature_roles_list() -> Vec { CreatureRoleEnum::list() } fn convert_result_to_bestiary_response( @@ -110,8 +110,9 @@ fn convert_result_to_bestiary_response( BestiaryResponse { results: Some(cr.into_iter().map(ResponseCreature::from).collect()), count: cr_length, - next: if cr_length >= pagination.paginated_request.page_size as usize { - Some(bestiary_next_url_calculator( + next: if cr_length >= pagination.paginated_request.page_size.unsigned_abs() as usize + { + Some(bestiary_next_url( field_filters, pagination, cr_length as u32, diff --git a/src/services/encounter_handler/difficulty_utilities.rs b/src/services/encounter_handler/difficulty_utilities.rs index dab2df6..0a768fb 100644 --- a/src/services/encounter_handler/difficulty_utilities.rs +++ b/src/services/encounter_handler/difficulty_utilities.rs @@ -1,6 +1,9 @@ use crate::models::encounter_structs::{EncounterChallengeEnum, ExpRange}; -pub fn scale_difficulty_exp(base_difficulty: &EncounterChallengeEnum, party_size: i64) -> ExpRange { +pub const fn scale_difficulty_exp( + base_difficulty: &EncounterChallengeEnum, + party_size: i64, +) -> ExpRange { // Given the base difficulty and the party size, it scales the base difficulty. // Useful when a party is not the canon 4 party member. let party_deviation = party_size - 4; @@ -17,7 +20,7 @@ pub fn scale_difficulty_exp(base_difficulty: &EncounterChallengeEnum, party_size } } -fn convert_difficulty_enum_to_base_xp_budget(diff: &EncounterChallengeEnum) -> i64 { +const fn convert_difficulty_enum_to_base_xp_budget(diff: &EncounterChallengeEnum) -> i64 { match diff { EncounterChallengeEnum::Trivial => 40, EncounterChallengeEnum::Low => 60, @@ -28,7 +31,7 @@ fn convert_difficulty_enum_to_base_xp_budget(diff: &EncounterChallengeEnum) -> i } } -fn convert_difficulty_enum_to_xp_adjustment(diff: &EncounterChallengeEnum) -> i64 { +const fn convert_difficulty_enum_to_xp_adjustment(diff: &EncounterChallengeEnum) -> i64 { match diff { EncounterChallengeEnum::Trivial => 10, EncounterChallengeEnum::Low => 15, @@ -39,13 +42,14 @@ fn convert_difficulty_enum_to_xp_adjustment(diff: &EncounterChallengeEnum) -> i6 } } -fn get_next_difficulty(diff: &EncounterChallengeEnum) -> EncounterChallengeEnum { +const fn get_next_difficulty(diff: &EncounterChallengeEnum) -> EncounterChallengeEnum { match diff { EncounterChallengeEnum::Trivial => EncounterChallengeEnum::Low, EncounterChallengeEnum::Low => EncounterChallengeEnum::Moderate, EncounterChallengeEnum::Moderate => EncounterChallengeEnum::Severe, EncounterChallengeEnum::Severe => EncounterChallengeEnum::Extreme, - EncounterChallengeEnum::Extreme => EncounterChallengeEnum::Impossible, - EncounterChallengeEnum::Impossible => EncounterChallengeEnum::Impossible, + EncounterChallengeEnum::Extreme | EncounterChallengeEnum::Impossible => { + EncounterChallengeEnum::Impossible + } } } diff --git a/src/services/encounter_handler/encounter_calculator.rs b/src/services/encounter_handler/encounter_calculator.rs index da256d9..16741e0 100644 --- a/src/services/encounter_handler/encounter_calculator.rs +++ b/src/services/encounter_handler/encounter_calculator.rs @@ -6,10 +6,10 @@ use std::ops::Neg; use strum::IntoEnumIterator; fn calculate_max_lvl_diff(lvl_and_exp_map: &HashMap) -> i64 { - match lvl_and_exp_map.keys().min() { - None => panic!("No valid lvl and exp map was passed. Abort"), - Some(max_lvl_diff) => *max_lvl_diff, - } + lvl_and_exp_map.keys().min().map_or_else( + || panic!("No valid lvl and exp map was passed. Abort"), + |max_lvl_diff| *max_lvl_diff, + ) } fn calculate_lvl_and_exp_map(is_pwl_on: bool) -> HashMap { @@ -78,7 +78,8 @@ pub fn calculate_encounter_scaling_difficulty( for curr_diff in EncounterChallengeEnum::iter() { diff_scaled_exp_map.insert( curr_diff.clone(), - scale_difficulty_exp(&curr_diff, party_size as i64).lower_bound, + scale_difficulty_exp(&curr_diff, i64::try_from(party_size).unwrap_or(i64::MAX)) + .lower_bound, ); } diff_scaled_exp_map @@ -125,12 +126,15 @@ pub fn calculate_lvl_combination_for_encounter( is_pwl_on: bool, ) -> HashSet> { // Given an encounter difficulty it calculates all possible encounter permutations - let exp_range = scale_difficulty_exp(difficulty, party_levels.len() as i64); + let exp_range = scale_difficulty_exp( + difficulty, + i64::try_from(party_levels.len()).unwrap_or(i64::MAX), + ); let party_avg: f64 = party_levels.iter().sum::() as f64 / party_levels.len() as f64; calculate_lvl_combinations_for_given_exp( exp_range, party_avg.floor() as i64, - calculate_lvl_and_exp_map(is_pwl_on), + &calculate_lvl_and_exp_map(is_pwl_on), ) } @@ -139,8 +143,8 @@ pub fn filter_combinations_outside_range( lower_bound: Option, upper_bound: Option, ) -> HashSet> { - let mut lower = lower_bound.unwrap_or(0) as i64; - let mut upper = upper_bound.unwrap_or(0) as i64; + let mut lower = i64::from(lower_bound.unwrap_or(0)); + let mut upper = i64::from(upper_bound.unwrap_or(0)); if lower != 0 && upper == 0 { upper = lower; } else if lower == 0 && upper != 0 { @@ -148,13 +152,13 @@ pub fn filter_combinations_outside_range( } else if lower == 0 && upper == 0 { return combinations; } - let mut filtered_combo = HashSet::new(); - combinations.iter().for_each(|curr_combo| { - if curr_combo.len() >= lower as usize && curr_combo.len() <= upper as usize { - filtered_combo.insert(curr_combo.clone()); - } - }); - filtered_combo + combinations + .into_iter() + .filter(|curr_combo| { + curr_combo.len() >= lower.unsigned_abs() as usize + && curr_combo.len() <= upper.unsigned_abs() as usize + }) + .collect::>>() } fn convert_lvl_diff_into_exp( @@ -163,34 +167,37 @@ fn convert_lvl_diff_into_exp( lvl_and_exp_map: &HashMap, ) -> i64 { let lvl_diff_rounded_down = lvl_diff.floor() as i64; - lvl_and_exp_map - .get(&lvl_diff_rounded_down) - .map(|value| value.abs()) - .unwrap_or( + lvl_and_exp_map.get(&lvl_diff_rounded_down).map_or_else( + || { if lvl_diff_rounded_down < calculate_max_lvl_diff(lvl_and_exp_map) { 0 } else { // To avoid the party of 50 level 1 pg destroying a lvl 20 - scale_difficulty_exp(&EncounterChallengeEnum::Impossible, party_size as i64) - .lower_bound - }, - ) + scale_difficulty_exp( + &EncounterChallengeEnum::Impossible, + i64::try_from(party_size).unwrap_or(i64::MAX), + ) + .lower_bound + } + }, + |value| value.abs(), + ) } fn calculate_lvl_combinations_for_given_exp( experience_range: ExpRange, party_lvl: i64, - lvl_and_exp_map: HashMap, + lvl_and_exp_map: &HashMap, ) -> HashSet> { // Given an encounter experience it calculates all possible encounter permutations - let exp_list = lvl_and_exp_map.values().copied().collect(); - find_combinations(exp_list, experience_range) + let exp_list = lvl_and_exp_map.values().copied().collect::>(); + find_combinations(&exp_list, experience_range) .iter() .map(|curr_combination| { curr_combination .iter() - .map(|curr_exp| convert_exp_to_lvl_diff(*curr_exp, &lvl_and_exp_map)) - .filter(|a| a.is_some()) + .map(|curr_exp| convert_exp_to_lvl_diff(*curr_exp, lvl_and_exp_map)) + .filter(Option::is_some) .map(|lvl_diff| party_lvl + lvl_diff.unwrap()) .collect() }) @@ -206,11 +213,11 @@ fn convert_exp_to_lvl_diff(experience: i64, lvl_and_exp_map: &HashMap) .find_map(|(key, &exp)| if exp == experience { Some(*key) } else { None }) } -fn find_combinations(candidates: Vec, target_range: ExpRange) -> Vec> { +fn find_combinations(candidates: &[i64], target_range: ExpRange) -> Vec> { // Find all the combination of numbers in the candidates vector // that sums up to the target. I.e coin changing problem fn backtrack( - candidates: &Vec, + candidates: &[i64], lb_target: i64, ub_target: i64, start: usize, @@ -250,7 +257,7 @@ fn find_combinations(candidates: Vec, target_range: ExpRange) -> Vec EncounterInfoResponse { +pub fn get_encounter_info(enc_params: &EncounterParams) -> EncounterInfoResponse { let enc_exp = encounter_calculator::calculate_encounter_exp( &enc_params.party_levels, &enc_params.enemy_levels, @@ -67,8 +68,8 @@ pub async fn generate_random_encounter( count: 0, encounter_info: EncounterInfoResponse { experience: 0, - challenge: Default::default(), - encounter_exp_levels: Default::default(), + challenge: EncounterChallengeEnum::default(), + encounter_exp_levels: BTreeMap::default(), }, } }) @@ -82,13 +83,12 @@ async fn calculate_random_encounter( ) -> Result { let is_pwl_on = enc_data.is_pwl_on; let filtered_lvl_combinations = get_lvl_combinations(&enc_data, &party_levels); - let unique_levels = HashSet::from_iter( - filtered_lvl_combinations - .clone() - .into_iter() - .flatten() - .map(|lvl| lvl.to_string()), - ); + let unique_levels = filtered_lvl_combinations + .clone() + .into_iter() + .flatten() + .map(|lvl| lvl.to_string()) + .collect::>(); ensure!( !unique_levels.is_empty(), "There are no valid levels to chose from. Encounter could not be built" @@ -118,7 +118,7 @@ async fn calculate_random_encounter( "No creatures have been fetched" ); let chosen_encounter = - choose_random_creatures_combination(filtered_creatures, filtered_lvl_combinations)?; + choose_random_creatures_combination(&filtered_creatures, filtered_lvl_combinations)?; Ok(RandomEncounterGeneratorResponse { count: chosen_encounter.len(), @@ -129,7 +129,7 @@ async fn calculate_random_encounter( .map(ResponseCreature::from) .collect(), ), - encounter_info: get_encounter_info(EncounterParams { + encounter_info: get_encounter_info(&EncounterParams { party_levels, enemy_levels: chosen_encounter .iter() @@ -141,7 +141,7 @@ async fn calculate_random_encounter( } fn choose_random_creatures_combination( - filtered_creatures: Vec, + filtered_creatures: &[Creature], lvl_combinations: HashSet>, ) -> Result> { // Chooses an id combination, could be (1, 1, 2). Admits duplicates @@ -150,8 +150,8 @@ fn choose_random_creatures_combination( creatures_ordered_by_level .keys() .for_each(|key| list_of_levels.push(*key)); - let existing_levels = filter_non_existing_levels(list_of_levels, lvl_combinations); - let tmp = Vec::from_iter(existing_levels.iter()); + let existing_levels = filter_non_existing_levels(&list_of_levels, lvl_combinations); + let tmp = existing_levels.iter().collect::>(); ensure!( !tmp.is_empty(), "No valid level combinations to randomly choose from" @@ -177,7 +177,7 @@ fn choose_random_creatures_combination( filled_vec_of_creatures.iter(), required_number_of_creatures_with_level, ) { - result_vec.push(curr_chosen_creature.clone()) + result_vec.push(curr_chosen_creature.clone()); } } Ok(result_vec) @@ -210,7 +210,7 @@ fn fill_vector_if_it_does_not_contain_enough_elements( } fn filter_non_existing_levels( - creatures_levels: Vec, + creatures_levels: &[i64], level_combinations: HashSet>, ) -> HashSet> { // Removes the vec with levels that are not found in any creature @@ -238,31 +238,41 @@ fn build_filter_map(filter_enum: FilterStruct) -> HashMap>(), ); }; if let Some(vec) = filter_enum.sizes { filter_map.insert( CreatureFilter::Size, - HashSet::from_iter(vec.iter().map(|el| el.to_string())), + vec.iter() + .map(std::string::ToString::to_string) + .collect::>(), ); }; if let Some(vec) = filter_enum.alignments { filter_map.insert( CreatureFilter::Alignment, - HashSet::from_iter(vec.iter().map(|x| x.to_string())), + vec.iter() + .map(std::string::ToString::to_string) + .collect::>(), ); }; if let Some(vec) = filter_enum.creature_types { filter_map.insert( CreatureFilter::CreatureTypes, - HashSet::from_iter(vec.iter().map(|el| el.to_string())), + vec.iter() + .map(std::string::ToString::to_string) + .collect::>(), ); }; if let Some(vec) = filter_enum.creature_roles { filter_map.insert( CreatureFilter::CreatureRoles, - HashSet::from_iter(vec.iter().map(|el| el.to_db_column())), + vec.iter() + .map(CreatureRoleEnum::to_db_column) + .collect::>(), ); }; filter_map.insert(CreatureFilter::Level, filter_enum.lvl_combinations); @@ -283,11 +293,10 @@ async fn get_filtered_creatures( } fn get_lvl_combinations(enc_data: &RandomEncounterData, party_levels: &[i64]) -> HashSet> { - if let Some(adv_group) = enc_data.adventure_group.as_ref() { - get_adventure_group_lvl_combinations(adv_group, party_levels) - } else { - get_standard_lvl_combinations(enc_data, party_levels) - } + enc_data.adventure_group.as_ref().map_or_else( + || get_standard_lvl_combinations(enc_data, party_levels), + |adv_group| get_adventure_group_lvl_combinations(adv_group, party_levels), + ) } fn get_standard_lvl_combinations( @@ -297,7 +306,7 @@ fn get_standard_lvl_combinations( let enc_diff = enc_data .challenge .clone() - .unwrap_or(EncounterChallengeEnum::rand()); + .unwrap_or_else(EncounterChallengeEnum::rand); let lvl_combinations = encounter_calculator::calculate_lvl_combination_for_encounter( &enc_diff, party_levels, @@ -314,7 +323,8 @@ fn get_adventure_group_lvl_combinations( adv_group: &AdventureGroupEnum, party_levels: &[i64], ) -> HashSet> { - let party_avg = party_levels.iter().sum::() / party_levels.len() as i64; + let party_avg = + party_levels.iter().sum::() / i64::try_from(party_levels.len()).unwrap_or(i64::MAX); let mut result = HashSet::new(); result.insert(match adv_group { AdventureGroupEnum::BossAndLackeys => { diff --git a/src/services/shop_service.rs b/src/services/shop_service.rs index 92ab770..961c1ae 100644 --- a/src/services/shop_service.rs +++ b/src/services/shop_service.rs @@ -1,11 +1,11 @@ use crate::db::shop_proxy; use crate::models::response_data::ResponseItem; -use crate::models::routers_validator_structs::ItemFieldFilters; +use crate::models::routers_validator_structs::{Dice, ItemFieldFilters}; use crate::models::shop_structs::{ ItemTableFieldsFilter, RandomShopData, ShopFilterQuery, ShopPaginatedRequest, ShopTemplateData, ShopTemplateEnum, }; -use crate::services::url_calculator::shop_next_url_calculator; +use crate::services::url_calculator::shop_next_url; use crate::AppState; use anyhow::{bail, Context}; use num_traits::ToPrimitive; @@ -45,17 +45,24 @@ pub async fn generate_random_shop_listing( app_state: &AppState, shop_data: &RandomShopData, ) -> ShopListingResponse { - let (type_filter, rarity_filter) = if let Some(x) = shop_data.shop_template.clone() { - (x.get_allowed_item_types(), x.get_allowed_item_rarities()) - } else { - ( - shop_data.type_filter.clone().unwrap_or_default(), - shop_data.rarity_filter.clone().unwrap_or_default(), - ) - }; + let (type_filter, rarity_filter) = shop_data.shop_template.clone().map_or_else( + || { + ( + shop_data.type_filter.clone().unwrap_or_default(), + shop_data.rarity_filter.clone().unwrap_or_default(), + ) + }, + |x| (x.get_allowed_item_types(), x.get_allowed_item_rarities()), + ); let shop_type = shop_data.shop_template.clone().unwrap_or_default(); - let n_of_consumables: i64 = shop_data.consumable_dices.iter().map(|x| x.roll()).sum(); - let n_of_equippables: i64 = shop_data.equippable_dices.iter().map(|x| x.roll()).sum(); + let n_of_consumables = i64::from( + shop_data + .consumable_dices + .iter() + .map(Dice::roll) + .sum::(), + ); + let n_of_equippables = shop_data.equippable_dices.iter().map(Dice::roll).sum(); // The request is correct, but will result in an empty list. if n_of_consumables == 0 && n_of_equippables == 0 { return ShopListingResponse::default(); @@ -85,7 +92,7 @@ pub async fn generate_random_shop_listing( }, ) { - match shop_proxy::get_filtered_items( + (shop_proxy::get_filtered_items( app_state, &ShopFilterQuery { item_table_fields_filter: ItemTableFieldsFilter { @@ -117,19 +124,19 @@ pub async fn generate_random_shop_listing( n_of_shields, }, ) - .await - { - Ok(result) => { - let n_of_items = result.len(); - ShopListingResponse { - results: Some(result.into_iter().map(ResponseItem::from).collect()), - count: n_of_items, - next: None, - total: n_of_items, - } - } - Err(_) => ShopListingResponse::default(), - } + .await) + .map_or_else( + |_| ShopListingResponse::default(), + |result| { + let n_of_items = result.len(); + ShopListingResponse { + results: Some(result.into_iter().map(ResponseItem::from).collect()), + count: n_of_items, + next: None, + total: n_of_items, + } + }, + ) } else { ShopListingResponse::default() } @@ -143,8 +150,10 @@ pub async fn get_traits_list(app_state: &AppState) -> Vec { shop_proxy::get_all_traits(app_state).await } -pub async fn get_shop_templates_data() -> Vec { - ShopTemplateEnum::iter().map(|x| x.into()).collect() +pub fn get_shop_templates_data() -> Vec { + ShopTemplateEnum::iter() + .map(std::convert::Into::into) + .collect() } fn convert_result_to_shop_response( @@ -159,12 +168,10 @@ fn convert_result_to_shop_response( ShopListingResponse { results: Some(item), count: n_of_items, - next: if n_of_items >= pagination.paginated_request.page_size as usize { - Some(shop_next_url_calculator( - field_filters, - pagination, - n_of_items as u32, - )) + next: if n_of_items + >= pagination.paginated_request.page_size.unsigned_abs() as usize + { + Some(shop_next_url(field_filters, pagination, n_of_items as u32)) } else { None }, @@ -178,24 +185,24 @@ fn convert_result_to_shop_response( /// Gets the n of: equipment, weapons, armors, shields (in this order). /// Changing order is considered a BREAKING CHANGE. pub fn calculate_n_of_equippable_values( - n_of_equippables: i64, + n_of_equippables: u16, percentages: (u8, u8, u8, u8), ) -> anyhow::Result<(i64, i64, i64, i64)> { let (e_p, w_p, a_p, s_p) = percentages; - let sum_of_percentages = (e_p + w_p + a_p + s_p) as f64; + let sum_of_percentages = f64::from(e_p + w_p + a_p + s_p); if sum_of_percentages > 100. { bail!("Percentages sum value is higher than 100. Incorrect values.") } - let f_n_of_equippables = n_of_equippables as f64; + let f_n_of_equippables = f64::from(n_of_equippables); let (e_v, w_v, a_v, s_v) = if sum_of_percentages == 0. { (25., 25., 25., 25.) } else { ( //Simpler form: (f_n_of_equippables * ((w_p as f64 * 100.) / sum_of_percentages)) / 100., - (f_n_of_equippables * e_p as f64) / sum_of_percentages, - (f_n_of_equippables * w_p as f64) / sum_of_percentages, - (f_n_of_equippables * a_p as f64) / sum_of_percentages, - (f_n_of_equippables * s_p as f64) / sum_of_percentages, + (f_n_of_equippables * f64::from(e_p)) / sum_of_percentages, + (f_n_of_equippables * f64::from(w_p)) / sum_of_percentages, + (f_n_of_equippables * f64::from(a_p)) / sum_of_percentages, + (f_n_of_equippables * f64::from(s_p)) / sum_of_percentages, ) }; @@ -216,7 +223,7 @@ mod tests { #[case(10, (10,10,10,10), (3,3,3,3))] #[case(1, (10,10,10,10), (1,1,1,1))] fn calculate_equippable_values_rounded_over_desired_total_case( - #[case] input_n_of_equippables: i64, + #[case] input_n_of_equippables: u16, #[case] input_percentages: (u8, u8, u8, u8), #[case] expected: (i64, i64, i64, i64), ) { @@ -228,7 +235,7 @@ mod tests { #[rstest] #[case(0, (0,0,0,0), (25, 25, 25, 25))] fn calculate_equippable_values_with_all_0( - #[case] input_n_of_equippables: i64, + #[case] input_n_of_equippables: u16, #[case] input_percentages: (u8, u8, u8, u8), #[case] expected: (i64, i64, i64, i64), ) { @@ -241,7 +248,7 @@ mod tests { #[case(0, (10,10,10,10), (0,0,0,0))] #[case(0, (10,20,10,0), (0,0,0,0))] fn calculate_equippable_values_zero_as_n_of_equippables( - #[case] input_n_of_equippables: i64, + #[case] input_n_of_equippables: u16, #[case] input_percentages: (u8, u8, u8, u8), #[case] expected: (i64, i64, i64, i64), ) { @@ -255,7 +262,7 @@ mod tests { #[case(10, (10,10,0,0), (5,5,0,0))] #[case(10, (10,10,10,0), (4,4,4,0))] fn calculate_equippable_values_with_missing_percentages( - #[case] input_n_of_equippables: i64, + #[case] input_n_of_equippables: u16, #[case] input_percentages: (u8, u8, u8, u8), #[case] expected: (i64, i64, i64, i64), ) { diff --git a/src/services/url_calculator.rs b/src/services/url_calculator.rs index 20af47b..db46249 100644 --- a/src/services/url_calculator.rs +++ b/src/services/url_calculator.rs @@ -2,7 +2,7 @@ use crate::models::bestiary_structs::BestiaryPaginatedRequest; use crate::models::routers_validator_structs::{CreatureFieldFilters, ItemFieldFilters}; use crate::models::shop_structs::ShopPaginatedRequest; -pub fn shop_next_url_calculator( +pub fn shop_next_url( field_filters: &ItemFieldFilters, pagination: &ShopPaginatedRequest, next_cursor: u32, @@ -25,10 +25,10 @@ pub fn shop_next_url_calculator( .clone() .unwrap_or_default() ); - format!("{}{}{}", base_url, filter_query, pagination_query) + format!("{base_url}{filter_query}{pagination_query}") } -pub fn bestiary_next_url_calculator( +pub fn bestiary_next_url( field_filters: &CreatureFieldFilters, pagination: &BestiaryPaginatedRequest, next_cursor: u32, @@ -51,12 +51,12 @@ pub fn bestiary_next_url_calculator( .clone() .unwrap_or_default() ); - format!("{}{}{}", base_url, filter_query, pagination_query) + format!("{base_url}{filter_query}{pagination_query}") } -pub fn add_boolean_query(url: &Option, key: &String, value: bool) -> Option { +pub fn add_boolean_query(url: Option<&String>, key: &String, value: bool) -> Option { url.as_ref() - .map(|base_url| format!("{}&{}={}", base_url, key, value)) + .map(|base_url| format!("{base_url}&{key}={value}")) } fn creature_filter_query_calculator(field_filters: &CreatureFieldFilters) -> String { @@ -64,34 +64,34 @@ fn creature_filter_query_calculator(field_filters: &CreatureFieldFilters) -> Str field_filters .name_filter .clone() - .map(|name| format!("name_filter={}", name)), + .map(|name| format!("name_filter={name}")), field_filters .role_threshold - .map(|threshold| format!("role_threshold={}", threshold)), + .map(|threshold| format!("role_threshold={threshold}")), field_filters .min_hp_filter - .map(|hp| format!("min_hp_filter={}", hp)), + .map(|hp| format!("min_hp_filter={hp}")), field_filters .max_hp_filter - .map(|hp| format!("max_hp_filter={}", hp)), + .map(|hp| format!("max_hp_filter={hp}")), field_filters .min_level_filter - .map(|lvl| format!("min_level_filter={}", lvl)), + .map(|lvl| format!("min_level_filter={lvl}")), field_filters .max_level_filter - .map(|lvl| format!("max_level_filter={}", lvl)), + .map(|lvl| format!("max_level_filter={lvl}")), field_filters .is_melee_filter - .map(|is| format!("is_melee_filter={}", is)), + .map(|is| format!("is_melee_filter={is}")), field_filters .is_ranged_filter - .map(|is| format!("is_ranged_filter={}", is)), + .map(|is| format!("is_ranged_filter={is}")), field_filters .is_spell_caster_filter - .map(|is| format!("is_spell_caster_filter={}", is)), + .map(|is| format!("is_spell_caster_filter={is}")), ] .iter() - .filter_map(|opt| opt.clone()) + .filter_map(std::clone::Clone::clone) .collect(); match queries.len() { 0 => String::new(), @@ -103,43 +103,43 @@ fn shop_filter_query_calculator(field_filters: &ItemFieldFilters) -> String { let queries: Vec = [ field_filters .min_bulk_filter - .map(|bulk| format!("min_bulk_filter={}", bulk)), + .map(|bulk| format!("min_bulk_filter={bulk}")), field_filters .max_bulk_filter - .map(|bulk| format!("max_bulk_filter={}", bulk)), + .map(|bulk| format!("max_bulk_filter={bulk}")), field_filters .min_hardness_filter - .map(|hn| format!("min_hardness_filter={}", hn)), + .map(|hn| format!("min_hardness_filter={hn}")), field_filters .max_hardness_filter - .map(|hn| format!("max_hardness_filter={}", hn)), + .map(|hn| format!("max_hardness_filter={hn}")), field_filters .min_hp_filter - .map(|hp| format!("min_hp_filter={}", hp)), + .map(|hp| format!("min_hp_filter={hp}")), field_filters .max_hp_filter - .map(|hp| format!("max_hp_filter={}", hp)), + .map(|hp| format!("max_hp_filter={hp}")), field_filters .min_level_filter - .map(|lvl| format!("min_level_filter={}", lvl)), + .map(|lvl| format!("min_level_filter={lvl}")), field_filters .max_level_filter - .map(|lvl| format!("max_level_filter={}", lvl)), + .map(|lvl| format!("max_level_filter={lvl}")), field_filters .min_price_filter - .map(|price| format!("min_price_filter={}", price)), + .map(|price| format!("min_price_filter={price}")), field_filters .max_price_filter - .map(|price| format!("max_price_filter={}", price)), + .map(|price| format!("max_price_filter={price}")), field_filters .min_n_of_uses_filter - .map(|uses| format!("min_n_of_uses_filter={}", uses)), + .map(|uses| format!("min_n_of_uses_filter={uses}")), field_filters .max_n_of_uses_filter - .map(|uses| format!("max_n_of_uses_filter={}", uses)), + .map(|uses| format!("max_n_of_uses_filter={uses}")), ] .iter() - .filter_map(|opt| opt.clone()) + .filter_map(std::clone::Clone::clone) .collect(); match queries.len() { 0 => String::new(),