From ea6138a5fb891b60611626aa604f15a36621f771 Mon Sep 17 00:00:00 2001 From: rakuja Date: Wed, 5 Jun 2024 23:59:43 +0200 Subject: [PATCH] refactor: pagination, folder structure, --- src/db/bestiary_proxy.rs | 68 +++++++++++++++---- src/db/cr_core_initializer.rs | 18 ++--- src/db/data_providers/creature_fetcher.rs | 8 +-- src/db/data_providers/shop_fetcher.rs | 10 +-- src/db/shop_proxy.rs | 44 ++++++++---- src/models/bestiary_structs.rs | 40 +++++++++++ .../creature_component/creature_core.rs | 4 +- .../creature_component/filter_struct.rs | 4 +- src/models/creature/creature_metadata/mod.rs | 2 - src/models/creature/items/action.rs | 2 +- src/models/creature/items/weapon.rs | 2 +- src/models/encounter_structs.rs | 4 +- src/models/item/item_struct.rs | 4 +- src/models/mod.rs | 2 + src/models/routers_validator_structs.rs | 16 ++++- src/models/shared/mod.rs | 2 + .../rarity_enum.rs | 0 .../creature_metadata => shared}/size_enum.rs | 0 src/models/shop_structs.rs | 32 ++++++++- src/routes/bestiary.rs | 24 +++++-- src/routes/shop.rs | 23 +++++-- src/services/bestiary_service.rs | 9 +-- src/services/shop_service.rs | 10 +-- src/services/url_calculator.rs | 42 ++++++++++-- 24 files changed, 276 insertions(+), 94 deletions(-) create mode 100644 src/models/bestiary_structs.rs create mode 100644 src/models/shared/mod.rs rename src/models/{creature/creature_metadata => shared}/rarity_enum.rs (100%) rename src/models/{creature/creature_metadata => shared}/size_enum.rs (100%) diff --git a/src/db/bestiary_proxy.rs b/src/db/bestiary_proxy.rs index 4538f5e..080fbe9 100644 --- a/src/db/bestiary_proxy.rs +++ b/src/db/bestiary_proxy.rs @@ -3,6 +3,7 @@ use std::collections::{HashMap, HashSet}; use crate::db::data_providers::creature_fetcher::fetch_traits_associated_with_creatures; use crate::db::data_providers::{creature_fetcher, generic_fetcher}; +use crate::models::bestiary_structs::{BestiaryPaginatedRequest, CreatureSortEnum}; use crate::models::creature::creature_component::creature_core::CreatureCoreData; use crate::models::creature::creature_filter_enum::{CreatureFilter, FieldsUniqueValuesStruct}; use crate::models::creature::creature_metadata::alignment_enum::AlignmentEnum; @@ -11,7 +12,7 @@ use crate::models::creature::creature_metadata::type_enum::CreatureTypeEnum; use crate::models::creature::creature_metadata::variant_enum::CreatureVariant; use crate::models::pf_version_enum::PathfinderVersionEnum; use crate::models::response_data::OptionalData; -use crate::models::routers_validator_structs::{CreatureFieldFilters, PaginatedRequest}; +use crate::models::routers_validator_structs::{CreatureFieldFilters, OrderEnum}; use crate::AppState; use anyhow::Result; use cached::proc_macro::once; @@ -47,21 +48,69 @@ pub async fn get_elite_creature_by_id( pub async fn get_paginated_creatures( app_state: &AppState, filters: &CreatureFieldFilters, - pagination: &PaginatedRequest, + pagination: &BestiaryPaginatedRequest, ) -> Result<(u32, Vec)> { let list = get_list(app_state, CreatureVariant::Base).await; - let filtered_list: Vec = list + let mut filtered_list: Vec = list .into_iter() .filter(|x| Creature::is_passing_filters(x, filters)) .collect(); let total_creature_count = filtered_list.len(); + filtered_list.sort_by(|a, b| { + let cmp = match pagination + .bestiary_sort_data + .sort_by + .clone() + .unwrap_or_default() + { + CreatureSortEnum::Id => a.core_data.essential.id.cmp(&b.core_data.essential.id), + CreatureSortEnum::Name => a.core_data.essential.name.cmp(&b.core_data.essential.name), + CreatureSortEnum::Level => a + .core_data + .essential + .level + .cmp(&b.core_data.essential.level), + CreatureSortEnum::Trait => a + .core_data + .traits + .join(", ") + .cmp(&b.core_data.traits.join(", ")), + CreatureSortEnum::Size => a.core_data.essential.size.cmp(&b.core_data.essential.size), + CreatureSortEnum::Type => a + .core_data + .essential + .cr_type + .cmp(&b.core_data.essential.cr_type), + CreatureSortEnum::Hp => a.core_data.essential.hp.cmp(&b.core_data.essential.hp), + CreatureSortEnum::Rarity => a + .core_data + .essential + .rarity + .cmp(&b.core_data.essential.rarity), + CreatureSortEnum::Family => a + .core_data + .essential + .family + .cmp(&b.core_data.essential.family), + }; + match pagination + .bestiary_sort_data + .order_by + .clone() + .unwrap_or_default() + { + OrderEnum::Ascending => cmp, + OrderEnum::Descending => cmp.reverse(), + } + }); + let curr_slice: Vec = filtered_list .iter() - .skip(pagination.cursor as usize) - .take(pagination.page_size as usize) + .skip(pagination.paginated_request.cursor as usize) + .take(pagination.paginated_request.page_size as usize) .cloned() .collect(); @@ -182,14 +231,7 @@ async fn get_all_keys(app_state: &AppState) -> FieldsUniqueValuesStruct { /// It will cache the result. #[once(sync_writes = true, result = true)] async fn get_all_creatures_from_db(app_state: &AppState) -> Result> { - creature_fetcher::fetch_creatures_core_data( - &app_state.conn, - &PaginatedRequest { - cursor: 0, - page_size: -1, - }, - ) - .await + creature_fetcher::fetch_creatures_core_data(&app_state.conn, 0, -1).await } /// Infallible method, it will expose a vector representing the values fetched from db or empty vec diff --git a/src/db/cr_core_initializer.rs b/src/db/cr_core_initializer.rs index 16e2dc7..c190b5b 100644 --- a/src/db/cr_core_initializer.rs +++ b/src/db/cr_core_initializer.rs @@ -5,10 +5,9 @@ use crate::db::data_providers::creature_fetcher::{ use crate::models::creature::creature_component::creature_core::EssentialData; use crate::models::creature::creature_metadata::alignment_enum::AlignmentEnum; use crate::models::creature::creature_metadata::creature_role::CreatureRoleEnum; -use crate::models::creature::creature_metadata::rarity_enum::RarityEnum; -use crate::models::creature::creature_metadata::size_enum::SizeEnum; use crate::models::creature::creature_metadata::type_enum::CreatureTypeEnum; -use crate::models::routers_validator_structs::PaginatedRequest; +use crate::models::shared::rarity_enum::RarityEnum; +use crate::models::shared::size_enum::SizeEnum; use anyhow::{bail, Result}; use serde::{Deserialize, Serialize}; use sqlx::{FromRow, Pool, Sqlite}; @@ -16,12 +15,8 @@ use sqlx::{FromRow, Pool, Sqlite}; /// Handler for startup, first creature_core initialization. Then it shouldn't be used pub async fn update_creature_core_table(conn: &Pool) -> Result<()> { - let pagination = PaginatedRequest { - cursor: 0, - page_size: -1, - }; let scales = fetch_creature_scales(conn).await?; - for cr in get_creatures_raw_essential_data(conn, &pagination).await? { + for cr in get_creatures_raw_essential_data(conn, 0, -1).await? { let traits = fetch_creature_traits(conn, cr.id).await?; let alignment = AlignmentEnum::from((&traits, cr.remaster)); update_alignment_column_value(conn, alignment.to_string(), cr.id).await?; @@ -143,7 +138,8 @@ async fn update_alignment_column_value( async fn get_creatures_raw_essential_data( conn: &Pool, - paginated_request: &PaginatedRequest, + cursor: u32, + page_size: i16, ) -> Result> { Ok(sqlx::query_as!( RawEssentialData, @@ -151,8 +147,8 @@ async fn get_creatures_raw_essential_data( id, aon_id, name, hp, level, size, family, rarity, license, remaster, source, cr_type FROM CREATURE_TABLE ORDER BY name LIMIT ?,?", - paginated_request.cursor, - paginated_request.page_size + cursor, + page_size ) .fetch_all(conn) .await?) diff --git a/src/db/data_providers/creature_fetcher.rs b/src/db/data_providers/creature_fetcher.rs index 725faf4..720b306 100644 --- a/src/db/data_providers/creature_fetcher.rs +++ b/src/db/data_providers/creature_fetcher.rs @@ -26,7 +26,6 @@ use crate::models::db::raw_speed::RawSpeed; use crate::models::db::raw_trait::RawTrait; use crate::models::db::raw_weakness::RawWeakness; use crate::models::response_data::OptionalData; -use crate::models::routers_validator_structs::PaginatedRequest; use crate::models::scales_struct::ability_scales::AbilityScales; use crate::models::scales_struct::ac_scales::AcScales; use crate::models::scales_struct::area_dmg_scales::AreaDmgScales; @@ -352,12 +351,13 @@ pub async fn fetch_creatures_core_data_with_filters( /// for the search. pub async fn fetch_creatures_core_data( conn: &Pool, - paginated_request: &PaginatedRequest, + cursor: u32, + page_size: i16, ) -> Result> { let cr_core: Vec = sqlx::query_as("SELECT * FROM CREATURE_CORE ORDER BY name LIMIT ?,?") - .bind(paginated_request.cursor) - .bind(paginated_request.page_size) + .bind(cursor) + .bind(page_size) .fetch_all(conn) .await?; Ok(update_creatures_core_with_traits(conn, cr_core).await) diff --git a/src/db/data_providers/shop_fetcher.rs b/src/db/data_providers/shop_fetcher.rs index d569a0e..4d4a618 100644 --- a/src/db/data_providers/shop_fetcher.rs +++ b/src/db/data_providers/shop_fetcher.rs @@ -3,7 +3,6 @@ use crate::db::data_providers::raw_query_builder::prepare_filtered_get_items; use crate::models::db::raw_trait::RawTrait; use crate::models::item::item_metadata::type_enum::ItemTypeEnum; use crate::models::item::item_struct::Item; -use crate::models::routers_validator_structs::PaginatedRequest; use crate::models::shop_structs::ShopFilterQuery; use anyhow::Result; use log::debug; @@ -25,13 +24,10 @@ pub async fn fetch_item_by_id(conn: &Pool, item_id: i64) -> Result Ok(item) } -pub async fn fetch_items( - conn: &Pool, - paginated_request: &PaginatedRequest, -) -> Result> { +pub async fn fetch_items(conn: &Pool, cursor: u32, page_size: i16) -> Result> { let items: Vec = sqlx::query_as("SELECT * FROM ITEM_TABLE ORDER BY name LIMIT ?,?") - .bind(paginated_request.cursor) - .bind(paginated_request.page_size) + .bind(cursor) + .bind(page_size) .fetch_all(conn) .await?; Ok(update_items_with_traits(conn, items).await) diff --git a/src/db/shop_proxy.rs b/src/db/shop_proxy.rs index 3f005ac..4c306f2 100644 --- a/src/db/shop_proxy.rs +++ b/src/db/shop_proxy.rs @@ -2,8 +2,8 @@ use crate::db::data_providers::{generic_fetcher, shop_fetcher}; use crate::models::creature::creature_metadata::type_enum::CreatureTypeEnum; use crate::models::item::item_fields_enum::{FieldsUniqueValuesStruct, ItemField}; use crate::models::item::item_struct::Item; -use crate::models::routers_validator_structs::{ItemFieldFilters, PaginatedRequest}; -use crate::models::shop_structs::ShopFilterQuery; +use crate::models::routers_validator_structs::{ItemFieldFilters, OrderEnum}; +use crate::models::shop_structs::{ItemSortEnum, ShopFilterQuery, ShopPaginatedRequest}; use crate::AppState; use anyhow::Result; use cached::proc_macro::once; @@ -25,21 +25,44 @@ pub async fn get_filtered_items( pub async fn get_paginated_items( app_state: &AppState, filters: &ItemFieldFilters, - pagination: &PaginatedRequest, + pagination: &ShopPaginatedRequest, ) -> Result<(u32, Vec)> { let list = get_list(app_state).await; - let filtered_list: Vec = list + let mut filtered_list: Vec = list .into_iter() .filter(|x| Item::is_passing_filters(x, filters)) .collect(); let total_item_count = filtered_list.len(); + filtered_list.sort_by(|a, b| { + let cmp = match pagination + .shop_sort_data + .sort_by + .clone() + .unwrap_or_default() + { + ItemSortEnum::Id => a.id.cmp(&b.id), + ItemSortEnum::Name => a.name.cmp(&b.name), + ItemSortEnum::Level => a.level.cmp(&b.level), + ItemSortEnum::Type => a.item_type.cmp(&b.item_type), + }; + match pagination + .shop_sort_data + .order_by + .clone() + .unwrap_or_default() + { + OrderEnum::Ascending => cmp, + OrderEnum::Descending => cmp.reverse(), + } + }); + let curr_slice: Vec = filtered_list .iter() - .skip(pagination.cursor as usize) - .take(pagination.page_size as usize) + .skip(pagination.paginated_request.cursor as usize) + .take(pagination.paginated_request.page_size as usize) .cloned() .collect(); @@ -50,14 +73,7 @@ pub async fn get_paginated_items( /// It will cache the result. #[once(sync_writes = true, result = true)] async fn get_all_items_from_db(app_state: &AppState) -> Result> { - shop_fetcher::fetch_items( - &app_state.conn, - &PaginatedRequest { - cursor: 0, - page_size: -1, - }, - ) - .await + shop_fetcher::fetch_items(&app_state.conn, 0, -1).await } /// Infallible method, it will expose a vector representing the values fetched from db or empty vec diff --git a/src/models/bestiary_structs.rs b/src/models/bestiary_structs.rs new file mode 100644 index 0000000..8bcaa50 --- /dev/null +++ b/src/models/bestiary_structs.rs @@ -0,0 +1,40 @@ +use crate::models::routers_validator_structs::{OrderEnum, PaginatedRequest}; +use serde::{Deserialize, Serialize}; +use strum::Display; +use utoipa::{IntoParams, ToSchema}; +use validator::Validate; + +#[derive(Serialize, Deserialize, ToSchema, Default, Eq, PartialEq, Hash, Clone, Display)] +pub enum CreatureSortEnum { + #[serde(alias = "id", alias = "ID")] + Id, + #[default] + #[serde(alias = "name", alias = "NAME")] + Name, + #[serde(alias = "level", alias = "LEVEL")] + Level, + #[serde(alias = "trait", alias = "TRAIT")] + Trait, + #[serde(alias = "size", alias = "SIZE")] + Size, + #[serde(alias = "type", alias = "TYPE")] + Type, + #[serde(alias = "hp", alias = "HP")] + Hp, + #[serde(alias = "rarity", alias = "RARITY")] + Rarity, + #[serde(alias = "family", alias = "FAMILY")] + Family, +} + +#[derive(Serialize, Deserialize, IntoParams, Validate, Eq, PartialEq, Hash, Default)] +pub struct BestiarySortData { + pub sort_by: Option, + pub order_by: Option, +} + +#[derive(Serialize, Deserialize, IntoParams, Validate, Eq, PartialEq, Hash)] +pub struct BestiaryPaginatedRequest { + pub paginated_request: PaginatedRequest, + pub bestiary_sort_data: BestiarySortData, +} diff --git a/src/models/creature/creature_component/creature_core.rs b/src/models/creature/creature_component/creature_core.rs index 61aea0f..5b53e72 100644 --- a/src/models/creature/creature_component/creature_core.rs +++ b/src/models/creature/creature_component/creature_core.rs @@ -1,7 +1,7 @@ use crate::models::creature::creature_metadata::alignment_enum::AlignmentEnum; -use crate::models::creature::creature_metadata::rarity_enum::RarityEnum; -use crate::models::creature::creature_metadata::size_enum::SizeEnum; use crate::models::creature::creature_metadata::type_enum::CreatureTypeEnum; +use crate::models::shared::rarity_enum::RarityEnum; +use crate::models::shared::size_enum::SizeEnum; use serde::{Deserialize, Serialize}; use sqlx::sqlite::SqliteRow; use sqlx::{Error, FromRow, Row}; diff --git a/src/models/creature/creature_component/filter_struct.rs b/src/models/creature/creature_component/filter_struct.rs index 20c0a90..3508484 100644 --- a/src/models/creature/creature_component/filter_struct.rs +++ b/src/models/creature/creature_component/filter_struct.rs @@ -1,9 +1,9 @@ use crate::models::creature::creature_metadata::alignment_enum::AlignmentEnum; use crate::models::creature::creature_metadata::creature_role::CreatureRoleEnum; -use crate::models::creature::creature_metadata::rarity_enum::RarityEnum; -use crate::models::creature::creature_metadata::size_enum::SizeEnum; use crate::models::creature::creature_metadata::type_enum::CreatureTypeEnum; use crate::models::pf_version_enum::PathfinderVersionEnum; +use crate::models::shared::rarity_enum::RarityEnum; +use crate::models::shared::size_enum::SizeEnum; use std::collections::HashSet; pub struct FilterStruct { diff --git a/src/models/creature/creature_metadata/mod.rs b/src/models/creature/creature_metadata/mod.rs index 57a4d9d..2c352e2 100644 --- a/src/models/creature/creature_metadata/mod.rs +++ b/src/models/creature/creature_metadata/mod.rs @@ -1,6 +1,4 @@ pub mod alignment_enum; pub mod creature_role; -pub mod rarity_enum; -pub mod size_enum; pub mod type_enum; pub mod variant_enum; diff --git a/src/models/creature/items/action.rs b/src/models/creature/items/action.rs index 9cca2d4..01a305f 100644 --- a/src/models/creature/items/action.rs +++ b/src/models/creature/items/action.rs @@ -1,4 +1,4 @@ -use crate::models::creature::creature_metadata::rarity_enum::RarityEnum; +use crate::models::shared::rarity_enum::RarityEnum; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; diff --git a/src/models/creature/items/weapon.rs b/src/models/creature/items/weapon.rs index 22939f4..d5c5c19 100644 --- a/src/models/creature/items/weapon.rs +++ b/src/models/creature/items/weapon.rs @@ -1,4 +1,4 @@ -use crate::models::creature::creature_metadata::rarity_enum::RarityEnum; +use crate::models::shared::rarity_enum::RarityEnum; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; diff --git a/src/models/encounter_structs.rs b/src/models/encounter_structs.rs index 009a1ad..1df60c3 100644 --- a/src/models/encounter_structs.rs +++ b/src/models/encounter_structs.rs @@ -1,9 +1,9 @@ use crate::models::creature::creature_metadata::alignment_enum::AlignmentEnum; use crate::models::creature::creature_metadata::creature_role::CreatureRoleEnum; -use crate::models::creature::creature_metadata::rarity_enum::RarityEnum; -use crate::models::creature::creature_metadata::size_enum::SizeEnum; use crate::models::creature::creature_metadata::type_enum::CreatureTypeEnum; use crate::models::pf_version_enum::PathfinderVersionEnum; +use crate::models::shared::rarity_enum::RarityEnum; +use crate::models::shared::size_enum::SizeEnum; use rand::distributions::{Distribution, Standard}; use rand::Rng; use serde::{Deserialize, Serialize}; diff --git a/src/models/item/item_struct.rs b/src/models/item/item_struct.rs index 4ee8331..11a642c 100644 --- a/src/models/item/item_struct.rs +++ b/src/models/item/item_struct.rs @@ -1,7 +1,7 @@ -use crate::models::creature::creature_metadata::rarity_enum::RarityEnum; -use crate::models::creature::creature_metadata::size_enum::SizeEnum; use crate::models::item::item_metadata::type_enum::ItemTypeEnum; use crate::models::routers_validator_structs::ItemFieldFilters; +use crate::models::shared::rarity_enum::RarityEnum; +use crate::models::shared::size_enum::SizeEnum; use serde::{Deserialize, Serialize}; use sqlx::sqlite::SqliteRow; use sqlx::{Error, FromRow, Row}; diff --git a/src/models/mod.rs b/src/models/mod.rs index f4f5499..98926c8 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,3 +1,4 @@ +pub mod bestiary_structs; pub mod creature; pub mod db; pub mod encounter_structs; @@ -6,4 +7,5 @@ pub mod pf_version_enum; pub mod response_data; pub mod routers_validator_structs; pub mod scales_struct; +pub mod shared; pub mod shop_structs; diff --git a/src/models/routers_validator_structs.rs b/src/models/routers_validator_structs.rs index f066f4f..ca86eb8 100644 --- a/src/models/routers_validator_structs.rs +++ b/src/models/routers_validator_structs.rs @@ -1,12 +1,13 @@ use crate::models::creature::creature_metadata::alignment_enum::AlignmentEnum; use crate::models::creature::creature_metadata::creature_role::CreatureRoleEnum; -use crate::models::creature::creature_metadata::rarity_enum::RarityEnum; -use crate::models::creature::creature_metadata::size_enum::SizeEnum; use crate::models::creature::creature_metadata::type_enum::CreatureTypeEnum; use crate::models::item::item_metadata::type_enum::ItemTypeEnum; use crate::models::pf_version_enum::PathfinderVersionEnum; +use crate::models::shared::rarity_enum::RarityEnum; +use crate::models::shared::size_enum::SizeEnum; use rand::Rng; use serde::{Deserialize, Serialize}; +use strum::Display; use utoipa::{IntoParams, ToSchema}; use validator::Validate; @@ -71,7 +72,16 @@ pub struct ItemFieldFilters { pub pathfinder_version: Option, } -#[derive(Serialize, Deserialize, IntoParams, Validate, Eq, PartialEq, Hash)] +#[derive(Serialize, Deserialize, ToSchema, Default, Eq, PartialEq, Hash, Clone, Display)] +pub enum OrderEnum { + #[default] + #[serde(alias = "ascending", alias = "ASCENDING")] + Ascending, + #[serde(alias = "descending", alias = "DESCENDING")] + Descending, +} + +#[derive(Serialize, Deserialize, IntoParams, Validate, Eq, PartialEq, Hash, ToSchema)] pub struct PaginatedRequest { #[validate(range(min = 0))] pub cursor: u32, diff --git a/src/models/shared/mod.rs b/src/models/shared/mod.rs new file mode 100644 index 0000000..9aca27f --- /dev/null +++ b/src/models/shared/mod.rs @@ -0,0 +1,2 @@ +pub mod rarity_enum; +pub mod size_enum; diff --git a/src/models/creature/creature_metadata/rarity_enum.rs b/src/models/shared/rarity_enum.rs similarity index 100% rename from src/models/creature/creature_metadata/rarity_enum.rs rename to src/models/shared/rarity_enum.rs diff --git a/src/models/creature/creature_metadata/size_enum.rs b/src/models/shared/size_enum.rs similarity index 100% rename from src/models/creature/creature_metadata/size_enum.rs rename to src/models/shared/size_enum.rs diff --git a/src/models/shop_structs.rs b/src/models/shop_structs.rs index 9d58672..3fe61ad 100644 --- a/src/models/shop_structs.rs +++ b/src/models/shop_structs.rs @@ -1,8 +1,8 @@ use crate::models::pf_version_enum::PathfinderVersionEnum; -use crate::models::routers_validator_structs::Dice; +use crate::models::routers_validator_structs::{Dice, OrderEnum, PaginatedRequest}; use serde::{Deserialize, Serialize}; -use strum::EnumIter; -use utoipa::ToSchema; +use strum::{Display, EnumIter}; +use utoipa::{IntoParams, ToSchema}; use validator::Validate; #[derive( @@ -37,3 +37,29 @@ pub struct ShopFilterQuery { pub n_of_consumables: i64, pub pathfinder_version: PathfinderVersionEnum, } + +#[derive(Serialize, Deserialize, ToSchema, Default, Eq, PartialEq, Hash, Clone, Display)] +pub enum ItemSortEnum { + #[serde(alias = "id", alias = "ID")] + Id, + #[default] + #[serde(alias = "name", alias = "NAME")] + Name, + #[serde(alias = "level", alias = "LEVEL")] + Level, + #[serde(alias = "type", alias = "TYPE")] + Type, +} + +#[derive(Serialize, Deserialize, IntoParams, Validate, Eq, PartialEq, Hash, Default)] +pub struct ShopSortData { + // Optional here for swagger, kinda bad but w/e + pub sort_by: Option, + pub order_by: Option, +} + +#[derive(Serialize, Deserialize, IntoParams, Validate, Eq, PartialEq, Hash)] +pub struct ShopPaginatedRequest { + pub paginated_request: PaginatedRequest, + pub shop_sort_data: ShopSortData, +} diff --git a/src/routes/bestiary.rs b/src/routes/bestiary.rs index 246cbce..ceab48d 100644 --- a/src/routes/bestiary.rs +++ b/src/routes/bestiary.rs @@ -1,11 +1,12 @@ use crate::models::creature::creature_metadata::alignment_enum::AlignmentEnum; use crate::models::creature::creature_metadata::creature_role::CreatureRoleEnum; -use crate::models::creature::creature_metadata::rarity_enum::RarityEnum; -use crate::models::creature::creature_metadata::size_enum::SizeEnum; use crate::models::creature::creature_metadata::type_enum::CreatureTypeEnum; use crate::models::creature::creature_metadata::variant_enum::CreatureVariant; use crate::models::response_data::OptionalData; use crate::models::response_data::ResponseCreature; +use crate::models::routers_validator_structs::OrderEnum; +use crate::models::shared::rarity_enum::RarityEnum; +use crate::models::shared::size_enum::SizeEnum; use crate::models::creature::creature_component::creature_combat::CreatureCombatData; use crate::models::creature::creature_component::creature_combat::SavingThrows; @@ -24,6 +25,8 @@ use crate::models::creature::items::spell::Spell; use crate::models::creature::items::spell_caster_entry::SpellCasterEntry; use crate::models::creature::items::weapon::Weapon; +use crate::models::bestiary_structs::CreatureSortEnum; +use crate::models::bestiary_structs::{BestiaryPaginatedRequest, BestiarySortData}; use crate::models::routers_validator_structs::{CreatureFieldFilters, PaginatedRequest}; use crate::services::bestiary_service; use crate::services::bestiary_service::BestiaryResponse; @@ -90,7 +93,9 @@ pub fn init_docs(doc: &mut utoipa::openapi::OpenApi) { Skill, CreatureRoleEnum, SpellCasterEntry, - PathfinderVersionEnum + PathfinderVersionEnum, + OrderEnum, + CreatureSortEnum )) )] struct ApiDoc; @@ -103,7 +108,7 @@ pub fn init_docs(doc: &mut utoipa::openapi::OpenApi) { path = "/bestiary/list", tag = "bestiary", params( - CreatureFieldFilters, PaginatedRequest + CreatureFieldFilters, PaginatedRequest, BestiarySortData ), responses( (status=200, description = "Successful Response", body = BestiaryResponse), @@ -115,9 +120,18 @@ pub async fn get_bestiary( data: web::Data, filters: Query, pagination: Query, + sort_data: Query, ) -> Result { Ok(web::Json( - bestiary_service::get_bestiary(&data, &filters.0, &pagination.0).await, + bestiary_service::get_bestiary( + &data, + &filters.0, + &BestiaryPaginatedRequest { + paginated_request: pagination.0, + bestiary_sort_data: sort_data.0, + }, + ) + .await, )) } diff --git a/src/routes/shop.rs b/src/routes/shop.rs index 9e9997a..758d043 100644 --- a/src/routes/shop.rs +++ b/src/routes/shop.rs @@ -1,10 +1,11 @@ use crate::models::item::item_metadata::type_enum::ItemTypeEnum; use crate::models::item::item_struct::Item; use crate::models::response_data::ResponseItem; -use crate::models::routers_validator_structs::Dice; -use crate::models::routers_validator_structs::{ItemFieldFilters, PaginatedRequest}; -use crate::models::shop_structs::RandomShopData; +use crate::models::routers_validator_structs::ItemFieldFilters; +use crate::models::routers_validator_structs::{Dice, PaginatedRequest}; use crate::models::shop_structs::ShopTypeEnum; +use crate::models::shop_structs::{ItemSortEnum, ShopPaginatedRequest}; +use crate::models::shop_structs::{RandomShopData, ShopSortData}; use crate::services::shop_service; use crate::services::shop_service::ShopListingResponse; use crate::AppState; @@ -32,7 +33,8 @@ pub fn init_docs(doc: &mut utoipa::openapi::OpenApi) { Item, RandomShopData, Dice, - ShopTypeEnum + ShopTypeEnum, + ItemSortEnum, )) )] struct ApiDoc; @@ -45,7 +47,7 @@ pub fn init_docs(doc: &mut utoipa::openapi::OpenApi) { path = "/shop/list", tag = "shop", params( - ItemFieldFilters, PaginatedRequest + ItemFieldFilters, PaginatedRequest, ShopSortData ), responses( (status=200, description = "Successful Response", body = ShopListingResponse), @@ -57,9 +59,18 @@ pub async fn get_shop_listing( data: web::Data, filters: Query, pagination: Query, + sort_data: Query, ) -> actix_web::Result { Ok(web::Json( - shop_service::get_shop_listing(&data, &filters.0, &pagination.0).await, + shop_service::get_shop_listing( + &data, + &filters.0, + &ShopPaginatedRequest { + paginated_request: pagination.0, + shop_sort_data: sort_data.0, + }, + ) + .await, )) } diff --git a/src/services/bestiary_service.rs b/src/services/bestiary_service.rs index 0a95313..7f9fe6b 100644 --- a/src/services/bestiary_service.rs +++ b/src/services/bestiary_service.rs @@ -1,10 +1,11 @@ use crate::db::bestiary_proxy; +use crate::models::bestiary_structs::BestiaryPaginatedRequest; use crate::models::creature::creature_filter_enum::CreatureFilter; use crate::models::creature::creature_metadata::creature_role::CreatureRoleEnum; use crate::models::creature::creature_metadata::variant_enum::CreatureVariant; use crate::models::creature::creature_struct::Creature; use crate::models::response_data::{OptionalData, ResponseCreature}; -use crate::models::routers_validator_structs::{CreatureFieldFilters, PaginatedRequest}; +use crate::models::routers_validator_structs::CreatureFieldFilters; use crate::services::url_calculator::bestiary_next_url_calculator; use crate::AppState; use anyhow::Result; @@ -56,7 +57,7 @@ pub async fn get_weak_creature( pub async fn get_bestiary( app_state: &AppState, field_filter: &CreatureFieldFilters, - pagination: &PaginatedRequest, + pagination: &BestiaryPaginatedRequest, ) -> BestiaryResponse { convert_result_to_bestiary_response( field_filter, @@ -99,7 +100,7 @@ pub async fn get_creature_roles_list() -> Vec { } fn convert_result_to_bestiary_response( field_filters: &CreatureFieldFilters, - pagination: &PaginatedRequest, + pagination: &BestiaryPaginatedRequest, result: Result<(u32, Vec)>, ) -> BestiaryResponse { match result { @@ -109,7 +110,7 @@ fn convert_result_to_bestiary_response( BestiaryResponse { results: Some(cr.into_iter().map(ResponseCreature::from).collect()), count: cr_length, - next: if cr_length >= pagination.page_size as usize { + next: if cr_length >= pagination.paginated_request.page_size as usize { Some(bestiary_next_url_calculator( field_filters, pagination, diff --git a/src/services/shop_service.rs b/src/services/shop_service.rs index 3882ee6..2fdc3dd 100644 --- a/src/services/shop_service.rs +++ b/src/services/shop_service.rs @@ -2,8 +2,8 @@ use crate::db::shop_proxy; use crate::models::item::item_fields_enum::ItemField; use crate::models::item::item_struct::Item; use crate::models::response_data::ResponseItem; -use crate::models::routers_validator_structs::{ItemFieldFilters, PaginatedRequest}; -use crate::models::shop_structs::{RandomShopData, ShopFilterQuery}; +use crate::models::routers_validator_structs::ItemFieldFilters; +use crate::models::shop_structs::{RandomShopData, ShopFilterQuery, ShopPaginatedRequest}; use crate::services::url_calculator::shop_next_url_calculator; use crate::AppState; use serde::{Deserialize, Serialize}; @@ -28,7 +28,7 @@ pub async fn get_item(app_state: &AppState, id: i64) -> HashMap ShopListingResponse { convert_result_to_shop_response( field_filter, @@ -87,7 +87,7 @@ pub async fn get_traits_list(app_state: &AppState) -> Vec { fn convert_result_to_shop_response( field_filters: &ItemFieldFilters, - pagination: &PaginatedRequest, + pagination: &ShopPaginatedRequest, result: anyhow::Result<(u32, Vec)>, ) -> ShopListingResponse { match result { @@ -97,7 +97,7 @@ fn convert_result_to_shop_response( ShopListingResponse { results: Some(item.into_iter().map(ResponseItem::from).collect()), count: n_of_items, - next: if n_of_items >= pagination.page_size as usize { + next: if n_of_items >= pagination.paginated_request.page_size as usize { Some(shop_next_url_calculator( field_filters, pagination, diff --git a/src/services/url_calculator.rs b/src/services/url_calculator.rs index c095fc6..ee008b9 100644 --- a/src/services/url_calculator.rs +++ b/src/services/url_calculator.rs @@ -1,28 +1,56 @@ -use crate::models::routers_validator_structs::{ - CreatureFieldFilters, ItemFieldFilters, PaginatedRequest, -}; +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( field_filters: &ItemFieldFilters, - pagination: &PaginatedRequest, + pagination: &ShopPaginatedRequest, next_cursor: u32, ) -> String { let base_url = "https://backbybe.fly.dev/bestiary/list/"; let filter_query = shop_filter_query_calculator(field_filters); - let pagination_query = format!("&cursor={}&page_size={}", next_cursor, pagination.page_size); + let pagination_query = format!( + "&cursor={}&page_size={}&sort_by={}&order_by={}", + next_cursor, + pagination.paginated_request.page_size, + pagination + .shop_sort_data + .sort_by + .clone() + .unwrap_or_default(), + pagination + .shop_sort_data + .order_by + .clone() + .unwrap_or_default() + ); format!("{}{}{}", base_url, filter_query, pagination_query) } pub fn bestiary_next_url_calculator( field_filters: &CreatureFieldFilters, - pagination: &PaginatedRequest, + pagination: &BestiaryPaginatedRequest, next_cursor: u32, ) -> String { let base_url = "https://backbybe.fly.dev/bestiary/list/"; let filter_query = creature_filter_query_calculator(field_filters); - let pagination_query = format!("&cursor={}&page_size={}", next_cursor, pagination.page_size); + let pagination_query = format!( + "&cursor={}&page_size={}&sort_by={}&order_by={}", + next_cursor, + pagination.paginated_request.page_size, + pagination + .bestiary_sort_data + .sort_by + .clone() + .unwrap_or_default(), + pagination + .bestiary_sort_data + .order_by + .clone() + .unwrap_or_default() + ); format!("{}{}{}", base_url, filter_query, pagination_query) }