didier/database/crud/currency.py

274 lines
7.1 KiB
Python
Raw Normal View History

2022-07-23 20:59:02 +02:00
from datetime import date
2024-03-01 14:18:58 +01:00
from typing import List, Optional, Union
2022-06-30 21:17:48 +02:00
2024-03-01 14:18:58 +01:00
from sqlalchemy import select
2022-06-30 21:17:48 +02:00
from sqlalchemy.ext.asyncio import AsyncSession
from database.crud import users
from database.exceptions import currency as exceptions
2024-03-01 14:18:58 +01:00
from database.schemas import Bank, BankSavings, NightlyData
2022-07-11 22:23:38 +02:00
from database.utils.math.currency import (
capacity_upgrade_price,
2024-03-01 14:18:58 +01:00
interest_rate,
2022-07-11 22:23:38 +02:00
interest_upgrade_price,
rob_upgrade_price,
2024-03-01 14:18:58 +01:00
savings_cap,
2022-07-11 22:23:38 +02:00
)
__all__ = [
"add_dinks",
2024-03-01 14:18:58 +01:00
"apply_daily_interest",
2022-07-11 22:23:38 +02:00
"claim_nightly",
2024-02-20 18:20:41 +01:00
"deduct_dinks",
"gamble_dinks",
2022-07-11 22:23:38 +02:00
"get_bank",
"get_nightly_data",
2024-03-01 14:18:58 +01:00
"save",
2022-07-11 22:23:38 +02:00
"upgrade_capacity",
"upgrade_interest",
"upgrade_rob",
"withdraw",
2022-07-11 22:23:38 +02:00
"NIGHTLY_AMOUNT",
]
2022-06-30 21:17:48 +02:00
NIGHTLY_AMOUNT = 420
async def get_bank(session: AsyncSession, user_id: int) -> Bank:
"""Get a user's bank info"""
2022-08-29 20:49:29 +02:00
user = await users.get_or_add_user(session, user_id)
2022-06-30 21:17:48 +02:00
return user.bank
2024-03-01 14:18:58 +01:00
async def get_savings(session: AsyncSession, user_id: int) -> BankSavings:
"""Get a user's savings info"""
user = await users.get_or_add_user(session, user_id)
return user.savings
2022-07-03 19:26:30 +02:00
async def get_nightly_data(session: AsyncSession, user_id: int) -> NightlyData:
"""Get a user's nightly info"""
2022-08-29 20:49:29 +02:00
user = await users.get_or_add_user(session, user_id)
2022-07-03 19:26:30 +02:00
return user.nightly_data
2024-03-01 14:18:58 +01:00
async def save(
session: AsyncSession,
user_id: int,
amount: Union[str, int],
*,
bank: Optional[Bank] = None,
savings: Optional[BankSavings] = None
) -> int:
"""Invest some of your Dinks"""
2024-02-20 18:20:41 +01:00
bank = bank or await get_bank(session, user_id)
2024-03-01 14:18:58 +01:00
savings = savings or await get_savings(session, user_id)
2022-07-03 18:35:30 +02:00
if amount == "all":
amount = bank.dinks
2024-02-20 16:21:51 +01:00
if bank.dinks <= 0:
return 0
2022-07-03 19:26:30 +02:00
# Don't allow investing more dinks than you own
amount = min(bank.dinks, int(amount))
2022-07-03 18:35:30 +02:00
2024-03-01 14:18:58 +01:00
# Don't allow exceeding the limit
limit = savings_cap(bank.capacity_level)
if savings.saved >= limit:
raise exceptions.SavingsCapExceeded
if savings.saved + amount > limit:
amount = max(0, limit - savings.saved)
2022-07-03 18:35:30 +02:00
bank.dinks -= amount
2024-03-01 14:18:58 +01:00
savings.saved += amount
2022-07-03 18:35:30 +02:00
session.add(bank)
2024-03-01 14:18:58 +01:00
session.add(savings)
2022-07-03 18:35:30 +02:00
await session.commit()
return amount
2024-02-20 18:20:41 +01:00
async def withdraw(session: AsyncSession, user_id: int, amount: Union[str, int], *, bank: Optional[Bank] = None) -> int:
2024-03-01 14:18:58 +01:00
"""Withdraw your saved Dinks"""
2024-02-20 18:20:41 +01:00
bank = bank or await get_bank(session, user_id)
2024-03-01 14:18:58 +01:00
savings = await get_savings(session, user_id)
if amount == "all":
2024-03-01 14:18:58 +01:00
amount = savings.saved
# Don't allow withdrawing more dinks than you own
2024-03-01 14:18:58 +01:00
amount = min(savings.saved, int(amount))
bank.dinks += amount
2024-03-01 14:18:58 +01:00
savings.saved -= amount
savings.daily_minimum = min(savings.daily_minimum, savings.saved)
2024-02-20 18:20:41 +01:00
session.add(bank)
2024-03-01 14:18:58 +01:00
session.add(savings)
await session.commit()
2024-03-01 14:18:58 +01:00
return amount
2024-02-20 18:20:41 +01:00
async def add_dinks(session: AsyncSession, user_id: int, amount: int, *, bank: Optional[Bank] = None):
2022-06-30 21:17:48 +02:00
"""Increase the Dinks counter for a user"""
2024-02-20 18:20:41 +01:00
bank = bank or await get_bank(session, user_id)
2022-06-30 21:17:48 +02:00
bank.dinks += amount
session.add(bank)
await session.commit()
2024-02-20 18:20:41 +01:00
async def deduct_dinks(session: AsyncSession, user_id: int, amount: int, *, bank: Optional[Bank] = None) -> int:
"""Decrease the Dinks counter for a user"""
bank = bank or await get_bank(session, user_id)
deducted_amount = min(amount, bank.dinks)
bank.dinks -= deducted_amount
session.add(bank)
await session.commit()
return deducted_amount
async def claim_nightly(session: AsyncSession, user_id: int, *, bank: Optional[Bank] = None):
2022-06-30 21:17:48 +02:00
"""Claim daily Dinks"""
2022-07-03 19:26:30 +02:00
nightly_data = await get_nightly_data(session, user_id)
2022-06-30 21:17:48 +02:00
2022-07-23 20:59:02 +02:00
now = date.today()
2022-06-30 21:17:48 +02:00
2022-07-23 20:59:02 +02:00
if nightly_data.last_nightly is not None and nightly_data.last_nightly == now:
2022-06-30 21:17:48 +02:00
raise exceptions.DoubleNightly
2024-02-20 18:20:41 +01:00
bank = bank or await get_bank(session, user_id)
2022-06-30 21:17:48 +02:00
bank.dinks += NIGHTLY_AMOUNT
nightly_data.last_nightly = now
session.add(bank)
session.add(nightly_data)
await session.commit()
2022-07-03 17:44:16 +02:00
2024-02-20 18:20:41 +01:00
async def upgrade_capacity(session: AsyncSession, user_id: int, *, bank: Optional[Bank] = None) -> int:
2022-07-03 17:44:16 +02:00
"""Upgrade capacity level"""
2024-02-20 18:20:41 +01:00
bank = bank or await get_bank(session, user_id)
2022-07-03 17:44:16 +02:00
upgrade_price = capacity_upgrade_price(bank.capacity_level)
# Can't afford this upgrade
if upgrade_price > bank.dinks:
raise exceptions.NotEnoughDinks
bank.dinks -= upgrade_price
bank.capacity_level += 1
2022-07-03 18:35:30 +02:00
session.add(bank)
await session.commit()
2022-07-03 17:44:16 +02:00
return bank.capacity_level
2024-02-20 18:20:41 +01:00
async def upgrade_interest(session: AsyncSession, user_id: int, *, bank: Optional[Bank] = None) -> int:
2022-07-03 17:44:16 +02:00
"""Upgrade interest level"""
2024-02-20 18:20:41 +01:00
bank = bank or await get_bank(session, user_id)
2022-07-03 17:44:16 +02:00
upgrade_price = interest_upgrade_price(bank.interest_level)
# Can't afford this upgrade
if upgrade_price > bank.dinks:
raise exceptions.NotEnoughDinks
bank.dinks -= upgrade_price
bank.interest_level += 1
2022-07-03 18:35:30 +02:00
session.add(bank)
await session.commit()
2022-07-03 17:44:16 +02:00
return bank.interest_level
2024-02-20 18:20:41 +01:00
async def upgrade_rob(session: AsyncSession, user_id: int, *, bank: Optional[Bank] = None) -> int:
2022-07-03 17:44:16 +02:00
"""Upgrade rob level"""
2024-02-20 18:20:41 +01:00
bank = bank or await get_bank(session, user_id)
2022-07-03 17:44:16 +02:00
upgrade_price = rob_upgrade_price(bank.rob_level)
# Can't afford this upgrade
if upgrade_price > bank.dinks:
raise exceptions.NotEnoughDinks
bank.dinks -= upgrade_price
bank.rob_level += 1
2022-07-03 18:35:30 +02:00
session.add(bank)
await session.commit()
2022-07-03 17:44:16 +02:00
return bank.rob_level
async def gamble_dinks(
2024-02-20 18:20:41 +01:00
session: AsyncSession,
user_id: int,
amount: Union[str, int],
payout_factor: int,
won: bool,
*,
bank: Optional[Bank] = None
) -> int:
2024-02-20 16:21:51 +01:00
"""Gamble some of your Didier Dinks"""
2024-02-20 18:20:41 +01:00
bank = bank or await get_bank(session, user_id)
if amount == "all":
amount = bank.dinks
2024-02-20 16:21:51 +01:00
if bank.dinks <= 0:
return 0
2024-02-12 20:16:52 +01:00
amount = min(int(amount), bank.dinks)
sign = 1 if won else -1
factor = (payout_factor - 1) if won else 1
2024-02-20 18:20:41 +01:00
await add_dinks(session, user_id, sign * amount * factor, bank=bank)
return amount * factor
2024-02-20 16:21:51 +01:00
2024-02-20 18:20:41 +01:00
async def rob(
session: AsyncSession,
amount: int,
robber_id: int,
robbed_id: int,
*,
robber_bank: Optional[Bank] = None,
robbed_bank: Optional[Bank] = None
):
2024-02-20 16:21:51 +01:00
"""Rob another user's Didier Dinks"""
2024-02-20 18:20:41 +01:00
robber = robber_bank or await get_bank(session, robber_id)
robbed = robbed_bank or await get_bank(session, robbed_id)
2024-02-20 16:21:51 +01:00
robber.dinks += amount
robbed.dinks -= amount
session.add(robber)
session.add(robbed)
await session.commit()
2024-03-01 14:18:58 +01:00
async def apply_daily_interest(session: AsyncSession):
"""Apply daily interest rates to all accounts with saved Dinks"""
statement = select(BankSavings)
all_savings: List[BankSavings] = list((await session.execute(statement)).scalars().all())
for savings_account in all_savings:
if savings_account.saved == 0:
continue
bank = await get_bank(session, savings_account.user_id)
rate = interest_rate(bank.interest_level)
savings_account.saved = float(savings_account.saved * rate)
savings_account.daily_minimum = savings_account.saved
session.add(savings_account)
await session.commit()