1use crate::prelude::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct ESCurrencyUnit {
8 pub currency_id: Uuid,
9 pub amount: i64,
10}
11
12#[declare]
13pub type CurrencyId = uuid::Uuid;
14
15#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, JsonSchema, Tsify)]
36#[tsify(from_wasm_abi, into_wasm_abi)]
37pub enum CurrencySource {
38 EntityDeath,
39 ItemSell,
40 AutoItemSell,
41 QuestClaim,
42 QuestsTrackReward,
43 VassalTaskCompletion,
44 ReferralLvlUp,
45 ReferralDailyReward,
46 GiftClaim,
47 ArenaTicketBuy,
48 ClaimVassalReward,
49 ClaimSuzerainReward,
50 ArenaMatchmakingRefresh,
51 GachaLevelUp,
52 PetCaseLevelUp,
53 #[default]
57 BundleClaim,
58 AdReward,
59 ProgressPassClaim,
60 Cheat,
61 MailReward,
65 DungeonReward,
66 OfferBuy,
67 ChapterReward,
68 NewUserGrant,
69 PvpArenaReward,
70 PvpVassalReward,
71 AfkReward,
72 DailyReset,
73 RatingReward,
74 CoreReset,
75}
76
77impl serde::Serialize for CurrencySource {
78 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
79 where
80 S: serde::Serializer,
81 {
82 let (idx, name) = match self {
92 Self::EntityDeath => (0u32, "EntityDeath"),
93 Self::ItemSell => (1, "ItemSell"),
94 Self::AutoItemSell => (2, "AutoItemSell"),
95 Self::QuestClaim => (3, "QuestClaim"),
96 Self::QuestsTrackReward => (4, "QuestsTrackReward"),
97 Self::VassalTaskCompletion => (5, "VassalTaskCompletion"),
98 Self::ReferralLvlUp => (6, "ReferralLvlUp"),
99 Self::ReferralDailyReward => (7, "ReferralDailyReward"),
100 Self::GiftClaim => (8, "GiftClaim"),
101 Self::ArenaTicketBuy => (9, "ArenaTicketBuy"),
102 Self::ClaimVassalReward => (10, "ClaimVassalReward"),
103 Self::ClaimSuzerainReward => (11, "ClaimSuzerainReward"),
104 Self::ArenaMatchmakingRefresh => (12, "ArenaMatchmakingRefresh"),
105 Self::GachaLevelUp => (13, "GachaLevelUp"),
106 Self::PetCaseLevelUp => (14, "PetCaseLevelUp"),
107 Self::BundleClaim => (15, "BundleClaim"),
108 Self::AdReward => (16, "AdReward"),
109 Self::Cheat => (18, "Cheat"),
112 Self::MailReward
114 | Self::DungeonReward
115 | Self::OfferBuy
116 | Self::ChapterReward
117 | Self::NewUserGrant
118 | Self::PvpArenaReward
119 | Self::PvpVassalReward
120 | Self::AfkReward
121 | Self::DailyReset
122 | Self::RatingReward
123 | Self::CoreReset
124 | Self::ProgressPassClaim => (15, "BundleClaim"),
125 };
126 serializer.serialize_unit_variant("CurrencySource", idx, name)
127 }
128}
129
130#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Tsify)]
131#[tsify(from_wasm_abi, into_wasm_abi)]
132pub enum CurrencyConsumer {
133 AbilityCaseOpen,
134 AbilityCaseSlotUpgrade,
135 ItemCaseOpen,
136 GiftSend,
137 DungeonRaid,
138 DungeonFightEnd,
139 ClassLevelUp,
140 OfferBuy,
141 ItemCaseUpgrade,
142 CaseUpgradeSpeedUp,
143 CaseUpgradeSkip,
144 ArenaFight,
145 ArenaMatchmakingRefresh,
146 ArenaTicketBuy,
147 SkinBuy,
148 AfkInstantReward,
149 StatueRoll,
150 TalentUpgrade,
151 TalentUpgradeSkip,
152 PetCaseOpen,
153 CoreUpgrade,
155}
156
157#[derive(
158 Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Tsify, i18n::Translate,
159)]
160pub struct Currency {
161 #[schemars(schema_with = "id_schema")]
162 pub id: CurrencyId,
163 #[schemars(title = "Название")]
164 #[translate]
165 pub name: i18n::I18nString,
166 #[schemars(title = "Описание")]
167 #[translate]
168 pub description: i18n::I18nString,
169 #[schemars(title = "URL картинки", schema_with = "webp_url_schema")]
170 pub icon_url: String,
171 #[schemars(title = "Иконка", schema_with = "asset_currency_icon_schema")]
172 pub icon_path: String,
173}
174
175#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, JsonSchema, Tsify, Default)]
176pub struct CurrencyUnit {
177 #[schemars(schema_with = "currency_link_id_schema")]
178 pub currency_id: CurrencyId,
179 #[schemars(title = "Количество")]
180 pub amount: i64,
181}
182
183impl PartialOrd for CurrencyUnit {
184 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
185 Some(self.cmp(other))
186 }
187}
188
189impl Ord for CurrencyUnit {
190 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
191 match self.currency_id.cmp(&other.currency_id) {
192 std::cmp::Ordering::Equal => self.amount.cmp(&other.amount),
193 ordering => ordering,
194 }
195 }
196}
197
198pub fn increase_currencies(
199 currencies_to_increase: &mut Vec<CurrencyUnit>,
200 currencies_to_add: &[CurrencyUnit],
201) {
202 for add_currency in currencies_to_add {
203 if let Some(unit) = currencies_to_increase
204 .iter_mut()
205 .find(|unit| unit.currency_id == add_currency.currency_id)
206 {
207 unit.amount += add_currency.amount;
208 } else {
209 currencies_to_increase.push(add_currency.clone());
210 }
211 }
212}
213
214pub fn decrease_currencies(
215 currencies_to_decrease: &mut [CurrencyUnit],
216 currencies_to_subtract: &[CurrencyUnit],
217) -> anyhow::Result<()> {
218 for subtract_currency in currencies_to_subtract {
219 if let Some(unit) = currencies_to_decrease
220 .iter_mut()
221 .find(|unit| unit.currency_id == subtract_currency.currency_id)
222 {
223 if unit.amount < subtract_currency.amount {
224 anyhow::bail!(
225 "Required currency {subtract_currency:?} is bigger than available {unit:?}"
226 )
227 }
228
229 unit.amount -= subtract_currency.amount;
230 } else {
231 anyhow::bail!("Given currency {subtract_currency:?} isn't present in currencies")
232 }
233 }
234 Ok(())
235}
236
237pub fn force_decrease_currencies(
238 currencies_to_decrease: &mut Vec<CurrencyUnit>,
239 currencies_to_subtract: &[CurrencyUnit],
240) -> anyhow::Result<()> {
241 for subtract_currency in currencies_to_subtract {
242 if let Some(unit) = currencies_to_decrease
243 .iter_mut()
244 .find(|unit| unit.currency_id == subtract_currency.currency_id)
245 {
246 unit.amount -= subtract_currency.amount;
247 }
248 }
249
250 currencies_to_decrease.retain(|unit| unit.amount != 0);
251
252 Ok(())
253}
254
255pub fn check_can_decrease_currencies(
256 available_currencies: &[CurrencyUnit],
257 required_currencies: &[CurrencyUnit],
258) -> bool {
259 for subtract_currency in required_currencies {
260 if let Some(unit) = available_currencies
261 .iter()
262 .find(|unit| unit.currency_id == subtract_currency.currency_id)
263 {
264 if unit.amount < subtract_currency.amount {
265 return false;
266 }
267 } else {
268 return false;
269 }
270 }
271 true
272}
273
274pub fn from_es_currencies(es_currencies: &[ESCurrencyUnit]) -> Vec<CurrencyUnit> {
275 let mut result = vec![];
276 for es_currency in es_currencies.iter() {
277 result.push(CurrencyUnit {
278 currency_id: es_currency.currency_id,
279 amount: es_currency.amount,
280 });
281 }
282 result
283}