essences/
ratings.rs

1use crate::{bundles::BundleId, characters, mail::MailTemplateId, prelude::*};
2use strum_macros::{Display, EnumIter, EnumString};
3
4#[declare]
5pub type RatingId = Uuid;
6
7#[derive(
8    Clone,
9    Debug,
10    Serialize,
11    Deserialize,
12    JsonSchema,
13    EnumString,
14    Display,
15    PartialEq,
16    Eq,
17    EnumIter,
18    Tsify,
19    Hash,
20)]
21pub enum RatingType {
22    Arena,
23    Power,
24    PvE,
25}
26
27#[derive(
28    Clone,
29    Copy,
30    Debug,
31    Serialize,
32    Deserialize,
33    JsonSchema,
34    EnumString,
35    Display,
36    PartialEq,
37    Eq,
38    EnumIter,
39    Tsify,
40    Hash,
41)]
42pub enum RatingRewardPeriod {
43    Daily,
44    Weekly,
45}
46
47#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Tsify)]
48pub struct RatingRewardAvailability {
49    /// Rating whose reward indicators this row controls.
50    pub rating_type: RatingType,
51    /// Whether an unclaimed reward from the latest completed UTC day exists.
52    pub daily_available: bool,
53    /// Whether an unclaimed reward from the latest completed UTC week exists.
54    pub weekly_available: bool,
55}
56
57#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, JsonSchema, Tsify)]
58pub struct RatingRangeReward {
59    #[schemars(title = "Бандл награды", schema_with = "bundle_id_schema")]
60    pub bundle_id: BundleId,
61
62    #[schemars(
63        title = "Legacy-шаблон письма",
64        description = "Используется только для преобразования уже созданных WeeklyReward событий; новые награды не отправляются почтой",
65        schema_with = "option_mail_id_schema"
66    )]
67    pub legacy_mail_template_id: Option<MailTemplateId>,
68
69    #[schemars(title = "Место, с которого начинается диапазон")]
70    pub diapason_start: i64,
71
72    #[schemars(
73        title = "Место, на котором заканчивается диапазон. Если отсутствует - значит от старта до конца"
74    )]
75    pub diapason_end: Option<i64>,
76}
77
78#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, JsonSchema, Tsify)]
79pub struct RatingSettings {
80    #[schemars(schema_with = "id_schema")]
81    pub id: RatingId,
82
83    #[schemars(title = "Вид рейтинга")]
84    pub rating_type: RatingType,
85
86    #[schemars(
87        title = "Все места рейтинга c наградой",
88        description = "Набор позиций рейтинга, описывающий все места и награды; для Power список должен быть пустым"
89    )]
90    pub weekly_rating_range_rewards: Vec<RatingRangeReward>,
91
92    #[schemars(
93        title = "Ежедневные награды рейтинга",
94        description = "Награды за последний завершённый UTC-день; для Power список должен быть пустым"
95    )]
96    pub daily_rating_range_rewards: Vec<RatingRangeReward>,
97}
98
99// TODO move to game config impl somewhere
100pub fn get_rating_ranges_by_type(
101    rating_type: RatingType,
102    period: RatingRewardPeriod,
103    ratings_settings: &Vec<RatingSettings>,
104) -> Vec<RatingRangeReward> {
105    for settings in ratings_settings {
106        if rating_type == settings.rating_type {
107            return match period {
108                RatingRewardPeriod::Daily => settings.daily_rating_range_rewards.clone(),
109                RatingRewardPeriod::Weekly => settings.weekly_rating_range_rewards.clone(),
110            };
111        }
112    }
113    vec![]
114}
115
116#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, Eq, PartialEq, JsonSchema, Tsify)]
117#[tsify(into_wasm_abi, from_wasm_abi)]
118pub struct RatingLeaderboardRequest {
119    pub character_id: uuid::Uuid,
120    pub rating_type: RatingType,
121    pub limit: i64,
122    pub offset: i64,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, JsonSchema, Tsify)]
126#[tsify(into_wasm_abi, from_wasm_abi)]
127pub enum RatingLeaderboardResponse {
128    Ok {
129        leaderboard: Vec<RatingRankingItem>,
130        character_ranking: Box<RatingRankingItem>,
131        /// When the current ratings season ends: the next ISO-week start
132        /// (Monday 00:00:00 UTC) strictly after the moment the response was
133        /// built. Matches the weekly ratings rewards cron, which rolls over
134        /// on the ISO-week boundary.
135        season_end: chrono::DateTime<chrono::Utc>,
136    },
137    Error {
138        code: String,
139        message: String,
140        /// See `Ok::season_end`; carried on both variants so the client can
141        /// always read it from the response.
142        season_end: chrono::DateTime<chrono::Utc>,
143    },
144}
145
146#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Tsify)]
147pub struct RatingRankingItem {
148    pub user: crate::users::User,
149    pub character: characters::Character,
150    pub place: u64,
151}