From a97031e71781e1e23320d5dd76461db105db13c1 Mon Sep 17 00:00:00 2001 From: 283375 Date: Mon, 18 Sep 2023 09:25:15 +0800 Subject: [PATCH] wip(calc): world step calculation --- src/arcaea_offline/calculate/world_step.py | 150 +++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 src/arcaea_offline/calculate/world_step.py diff --git a/src/arcaea_offline/calculate/world_step.py b/src/arcaea_offline/calculate/world_step.py new file mode 100644 index 0000000..656080b --- /dev/null +++ b/src/arcaea_offline/calculate/world_step.py @@ -0,0 +1,150 @@ +from decimal import Decimal +from typing import Literal, Optional, Union + + +class PlayResults: + def __init__( + self, + *, + potential: Union[Decimal, str, float, int], + partner_step: Union[Decimal, str, float, int], + ): + self.__potential = potential + self.__partner_step = partner_step + + @property + def potential(self): + return Decimal(self.__potential) + + @property + def partner_step(self): + return Decimal(self.__partner_step) + + +class PartnerBonus: + def __init__( + self, + *, + step_bonus: Union[Decimal, str, float, int] = Decimal("1.0"), + final_multiplier: Union[Decimal, str, float, int] = Decimal("1.0"), + ): + self.__step_bonus = step_bonus + self.__final_multiplier = final_multiplier + + @property + def step_bonus(self): + return Decimal(self.__step_bonus) + + @property + def final_multiplier(self): + return Decimal(self.__final_multiplier) + + +AwakenedIlithPartnerBonus = PartnerBonus(step_bonus="6.0") +AwakenedEtoPartnerBonus = PartnerBonus(step_bonus="7.0") +AwakenedLunaPartnerBonus = PartnerBonus(step_bonus="7.0") + + +class AwakenedAyuPartnerBonus(PartnerBonus): + def __init__(self, step_bonus: Union[Decimal, str, float, int]): + super().__init__(step_bonus=step_bonus) + + +AmaneBelowExPartnerBonus = PartnerBonus(final_multiplier="0.5") + + +class MithraTerceraPartnerBonus(PartnerBonus): + def __init__(self, step_bonus: int): + super().__init__(step_bonus=step_bonus) + + +MayaPartnerBonus = PartnerBonus(final_multiplier="2.0") + + +class StepBooster: + def final_value(self) -> Decimal: + raise NotImplementedError() + + +class LegacyMapStepBooster(StepBooster): + def __init__( + self, + stamina: Literal[2, 4, 6], + fragments: Literal[100, 250, 500, None], + ): + self.stamina = stamina + self.fragments = fragments + + @property + def stamina(self): + return self.__stamina + + @stamina.setter + def stamina(self, value: Literal[2, 4, 6]): + if value not in [2, 4, 6]: + raise ValueError("stamina can only be one of [2, 4, 6]") + self.__stamina = value + + @property + def fragments(self): + return self.__fragments + + @fragments.setter + def fragments(self, value: Literal[100, 250, 500, None]): + if value not in [100, 250, 500, None]: + raise ValueError("fragments can only be one of [100, 250, 500, None]") + self.__fragments = value + + def final_value(self) -> Decimal: + stamina_multiplier = Decimal(self.stamina) + if self.fragments is None: + fragments_multiplier = Decimal(1) + elif self.fragments == 100: + fragments_multiplier = Decimal("1.1") + elif self.fragments == 250: + fragments_multiplier = Decimal("1.25") + elif self.fragments == 500: + fragments_multiplier = Decimal("1.5") + return stamina_multiplier * fragments_multiplier + + +class MemoriesStepBooster(StepBooster): + def final_value(self) -> Decimal: + return Decimal("4.0") + + +def calculate_step_original( + play_results: PlayResults, + *, + partner_bonus: Optional[PartnerBonus] = None, + booster: Optional[StepBooster] = None, +): + ptt = play_results.potential + step = play_results.partner_step + if partner_bonus: + partner_bonus_step = partner_bonus.step_bonus + partner_bonus_multiplier = partner_bonus.final_multiplier + else: + partner_bonus_step = Decimal("0") + partner_bonus_multiplier = Decimal("1.0") + + play_result = (Decimal("2.45") * ptt.sqrt() + Decimal("2.5")) * (step / 50) + play_result += partner_bonus_step + play_result *= partner_bonus_multiplier + if booster: + play_result *= booster.final_value() + + return play_result + + +def calculate_step( + play_results: PlayResults, + *, + partner_bonus: Optional[PartnerBonus] = None, + booster: Optional[StepBooster] = None, +): + play_result_original = calculate_step_original( + play_results, partner_bonus=partner_bonus, booster=booster + ) + + return round(play_result_original, 1)