"""EXP, levels and vanity role thresholds.""" from __future__ import annotations import math from .store import _locked_by, _prestige_mult, get_user, _commit # --------------------------------------------------------------------------- # EXP / Level system # --------------------------------------------------------------------------- # EXP awarded per successful action EXP_REWARDS: dict[str, int] = { "daily": 50, "work": 25, "beg": 5, "crime_win": 15, "rob_win": 15, "gamble_win": 10, "heist_win": 25, } def gamble_exp(bet: int) -> int: """Scale EXP for a gambling win by bet size. Returns 0 for bets < 10 coins to close micro-bet EXP farming. 10-99 → 5, 100-999 → 10, 1 000-9 999 → 15, 10 000+ → 20, 100 000+ → 25 (cap). """ return min(25, max(0, int(math.log10(max(1, bet))) * 5)) ECONOMY_ROLE = "ECONOMY" # Vanity role milestones: (min_level, role_name) - highest first LEVEL_ROLES: list[tuple[int, str]] = [ (30, "TipiLEGEND"), (20, "TipiCHAD"), (10, "TipiHUSTLER"), (5, "TipiGRINDER"), (1, "TipiNOOB"), ] def get_level(exp: int) -> int: """Level = max(1, floor(sqrt(exp/10))). Level 5 @ 250 EXP, 10 @ 1000, 20 @ 4000, 30 @ 9000.""" return max(1, int(math.sqrt(max(0, exp) / 10))) def exp_for_level(level: int) -> int: """Minimum cumulative EXP to reach this level. Recurrence: exp_for_level(L) = L*20 - 10 + exp_for_level(L-1), base 0. Closed form: 10*level^2.""" if level <= 1: return 0 return 10 * level * level def level_role_name(level: int) -> str: """Return the vanity role name for a given level.""" for threshold, name in LEVEL_ROLES: if level >= threshold: return name return LEVEL_ROLES[-1][1] @_locked_by(0) async def award_exp(user_id: int, amount: int) -> dict: """Add EXP to a user. Applies prestige exp_mult. Returns old_level, new_level, total exp.""" user = await get_user(user_id) _, exp_mult = _prestige_mult(user) gained = max(1, int(amount * exp_mult)) old_exp = user.get("exp", 0) new_exp = old_exp + gained old_level = get_level(old_exp) new_level = get_level(new_exp) user["exp"] = new_exp user["season_total_exp"] = user.get("season_total_exp", 0) + gained await _commit(user_id, user) return {"old_level": old_level, "new_level": new_level, "exp": new_exp, "gained": gained}