From 9a53a2c4bad1acac3169ddaee58af85f997e6bd7 Mon Sep 17 00:00:00 2001 From: Leonid Kozarin Date: Mon, 29 Apr 2024 23:03:05 +0300 Subject: [PATCH] Paying off debt with awards won in battles --- locales/en.yml | 3 ++- locales/ru.yml | 3 ++- src/handlers/perks.rs | 8 ++++---- src/handlers/pvp.rs | 31 ++++++++++++++++++++++++++++--- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/locales/en.yml b/locales/en.yml index a2d9c4e..0d3c209 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -25,10 +25,11 @@ commands: description: "Fight with your friend's dick!" results: start: "%{name} challenged the chat with a bet of %{bet} cm!" - finish: "The winner is %{winner_name}! His dick is now %{winner_length} cm long. The loser's one is %{loser_length}." + finish: "The winner is %{winner_name}! His dick is now %{winner_length} cm long. The loser's one is %{loser_length}.\nThe bet was %{bet} cm." position: winner: "%{name}'s position in the top is %{pos}." loser: "%{name}'s position in the top is %{pos}." + withheld: "%{payout} cm were withheld from the winner to pay off the loan." button: "Attack!" errors: no_args: "Call the command with a number of centimeters you're willing to bet." diff --git a/locales/ru.yml b/locales/ru.yml index aaedeb0..e1f63b7 100644 --- a/locales/ru.yml +++ b/locales/ru.yml @@ -25,10 +25,11 @@ commands: description: "Сражайся с пипирками друзей!" results: start: "%{name} бросил чату вызов со ставкой %{bet} см!" - finish: "Победитель — %{winner_name}! Его пипирик теперь равен %{winner_length} см, а проигравшего — %{loser_length} см." + finish: "Победитель — %{winner_name}! Его пипирик теперь равен %{winner_length} см, а проигравшего — %{loser_length} см.\nСтавка была %{bet} см." position: winner: "%{name} занимает %{pos} место в топе." loser: "%{name} занимает %{pos} место в топе." + withheld: "%{payout} см было удержано с победителя для погашения задолженности." button: "Атаковать!" errors: no_args: "Вызови команду с числом сантиметров, которые готов поставить." diff --git a/src/handlers/perks.rs b/src/handlers/perks.rs index 6f9dc54..65494a1 100644 --- a/src/handlers/perks.rs +++ b/src/handlers/perks.rs @@ -33,7 +33,7 @@ impl Perk for HelpPussiesPerk { let current_deepness = change_intent.current_length.abs() .to_f64().expect("conversion is always Some"); - let change = (self.coefficient * current_deepness).ceil() as i32; + let change = (self.coefficient * current_deepness).round() as i32; AdditionalChange(change) } @@ -74,7 +74,7 @@ impl Perk for LoanPayoutPerk { let payout = if change_intent.base_increment.is_positive() { let base_increment = change_intent.base_increment as f32; - let payout = (base_increment * payout_coefficient).ceil() as u16; + let payout = (base_increment * payout_coefficient).round() as u16; payout.min(debt) } else { 0 @@ -153,12 +153,12 @@ mod test { .debt; assert_eq!(debt, 9); - assert_eq!(perk.apply(&dick_id, change_intent_positive_increment_small).await.0, -1); + assert_eq!(perk.apply(&dick_id, change_intent_positive_increment_small).await.0, 0); assert_eq!(perk.apply(&dick_id, change_intent_negative_increment).await.0, 0); let debt = loans.get_active_loan(USER_ID, &CHAT_ID_KIND) .await.expect("couldn't fetch the active loan") .expect("loan must be found") .debt; - assert_eq!(debt, 8); + assert_eq!(debt, 9); } } diff --git a/src/handlers/pvp.rs b/src/handlers/pvp.rs index 4cb67e3..737bfb1 100644 --- a/src/handlers/pvp.rs +++ b/src/handlers/pvp.rs @@ -11,7 +11,7 @@ use teloxide::types::{CallbackQuery, ChatId, ChosenInlineResult, InlineKeyboardB use crate::handlers::{CallbackResult, ensure_lang_code, HandlerResult, reply_html, utils}; use crate::{metrics, repo}; use crate::config::{AppConfig, BattlesFeatureToggles}; -use crate::repo::{ChatIdPartiality, Repositories}; +use crate::repo::{ChatIdPartiality, GrowthResult, Repositories}; const CALLBACK_PREFIX: &str = "pvp:"; @@ -221,11 +221,20 @@ async fn pvp_impl_attack(p: BattleParams, initiator: UserId, acceptor: UserInfo, let acceptor_uid = acceptor.clone().into(); let (winner, loser) = choose_winner(initiator, acceptor_uid); let (loser_res, winner_res) = p.repos.dicks.move_length(&p.chat_id, loser, winner, bet).await?; + + let (winner_res, withheld_part) = pay_for_loan_if_needed(&p, winner, bet).await + .inspect_err(|e| log::error!("couldn't pay for a loan from a battle award: {e}")) + .ok().flatten() + .map(|(res, withheld)| { + let withheld_part = format!("\n\n{}", t!("commands.pvp.results.withheld", locale = &p.lang_code, payout = withheld)); + (res, withheld_part) + }) + .unwrap_or((winner_res, String::default())); let winner_info = get_user_info(&p.repos.users, winner, &acceptor).await?; let loser_info = get_user_info(&p.repos.users, loser, &acceptor).await?; let main_part = t!("commands.pvp.results.finish", locale = &p.lang_code, - winner_name = winner_info.name, winner_length = winner_res.new_length, loser_length = loser_res.new_length); + winner_name = winner_info.name, winner_length = winner_res.new_length, loser_length = loser_res.new_length, bet = bet); let text = if let (Some(winner_pos), Some(loser_pos)) = (winner_res.pos_in_top, loser_res.pos_in_top) { let winner_pos = t!("commands.pvp.results.position.winner", locale = &p.lang_code, name = winner_info.name, pos = winner_pos); let loser_pos = t!("commands.pvp.results.position.loser", locale = &p.lang_code, name = loser_info.name, pos = loser_pos); @@ -233,7 +242,7 @@ async fn pvp_impl_attack(p: BattleParams, initiator: UserId, acceptor: UserInfo, } else { main_part }; - CallbackResult::EditMessage(text, None) + CallbackResult::EditMessage(format!("{text}{withheld_part}"), None) } else if enough_acceptor { let text = t!("commands.pvp.errors.not_enough.initiator", locale = &p.lang_code); CallbackResult::EditMessage(text, None) @@ -279,3 +288,19 @@ async fn get_user_info(users: &repo::Users, user_uid: UserId, acceptor: &UserInf }; Ok(user) } + +async fn pay_for_loan_if_needed(p: &BattleParams, winner_id: UserId, award: u16) -> anyhow::Result> { + let chat_id_kind = p.chat_id.kind(); + let loan = match p.repos.loans.get_active_loan(winner_id, &chat_id_kind).await? { + Some(loan) => loan, + None => return Ok(None) + }; + let payout = (loan.payout_ratio * award as f32).round() as u16; + let payout = payout.min(loan.debt); + + p.repos.loans.pay(winner_id, &chat_id_kind, payout).await?; + + let withheld = -(payout as i32); + let growth_res = p.repos.dicks.create_or_grow(winner_id, &p.chat_id, withheld).await?; + Ok(Some((growth_res, payout))) +}