forked from retoor/devplacepy
update
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from devplacepy.database import get_table
|
||||
|
||||
from .. import economy
|
||||
from .common import GameError, _iso, _iso_week, _lvl, _now, conditional_update_farm
|
||||
from .farm import ensure_farm, get_farm
|
||||
|
||||
TREASURY_UID = "treasury-main"
|
||||
|
||||
|
||||
def _treasury():
|
||||
return get_table("game_treasury")
|
||||
|
||||
|
||||
def ensure_treasury() -> dict:
|
||||
row = _treasury().find_one(uid=TREASURY_UID)
|
||||
if row:
|
||||
return row
|
||||
_treasury().insert(
|
||||
{
|
||||
"uid": TREASURY_UID,
|
||||
"balance": 0,
|
||||
"collected_total": 0,
|
||||
"granted_total": 0,
|
||||
"updated_at": _iso(_now()),
|
||||
}
|
||||
)
|
||||
return _treasury().find_one(uid=TREASURY_UID)
|
||||
|
||||
|
||||
def treasury_balance() -> int:
|
||||
row = _treasury().find_one(uid=TREASURY_UID)
|
||||
return int(row.get("balance") or 0) if row else 0
|
||||
|
||||
|
||||
def _treasury_update(set_clause: str, where_clause: str, params: dict) -> int:
|
||||
from sqlalchemy import text
|
||||
|
||||
from devplacepy.database import db
|
||||
|
||||
sql = (
|
||||
f"UPDATE game_treasury SET {set_clause}, updated_at = :updated_at "
|
||||
f"WHERE uid = :treasury_uid AND ({where_clause})"
|
||||
)
|
||||
bind = {**params, "updated_at": _iso(_now()), "treasury_uid": TREASURY_UID}
|
||||
with db:
|
||||
result = db.executable.execute(text(sql), bind)
|
||||
return result.rowcount
|
||||
|
||||
|
||||
def credit_treasury(amount: int) -> None:
|
||||
if amount <= 0:
|
||||
return
|
||||
ensure_treasury()
|
||||
_treasury_update(
|
||||
set_clause=(
|
||||
"balance = COALESCE(balance, 0) + :amount, "
|
||||
"collected_total = COALESCE(collected_total, 0) + :amount"
|
||||
),
|
||||
where_clause="1 = 1",
|
||||
params={"amount": amount},
|
||||
)
|
||||
|
||||
|
||||
def _debit_treasury(amount: int) -> bool:
|
||||
ensure_treasury()
|
||||
rows = _treasury_update(
|
||||
set_clause=(
|
||||
"balance = COALESCE(balance, 0) - :amount, "
|
||||
"granted_total = COALESCE(granted_total, 0) + :amount"
|
||||
),
|
||||
where_clause="COALESCE(balance, 0) >= :amount",
|
||||
params={"amount": amount},
|
||||
)
|
||||
return rows > 0
|
||||
|
||||
|
||||
def _refund_treasury(amount: int) -> None:
|
||||
if amount <= 0:
|
||||
return
|
||||
_treasury_update(
|
||||
set_clause=(
|
||||
"balance = COALESCE(balance, 0) + :amount, "
|
||||
"granted_total = COALESCE(granted_total, 0) - :amount"
|
||||
),
|
||||
where_clause="1 = 1",
|
||||
params={"amount": amount},
|
||||
)
|
||||
|
||||
|
||||
def grant_status(farm: dict, now: datetime) -> dict:
|
||||
week = _iso_week(now)
|
||||
if farm.get("last_grant_week") == week:
|
||||
return {"available": False, "amount": 0, "reason": "Grant already claimed this week."}
|
||||
if _lvl(farm, "prestige") > economy.GRANT_MAX_PRESTIGE:
|
||||
return {
|
||||
"available": False,
|
||||
"amount": 0,
|
||||
"reason": f"Grants support farms up to prestige {economy.GRANT_MAX_PRESTIGE}.",
|
||||
}
|
||||
if int(farm.get("coins", 0)) >= economy.GRANT_WEALTH_CEILING:
|
||||
return {
|
||||
"available": False,
|
||||
"amount": 0,
|
||||
"reason": f"Grants support farms below {economy.GRANT_WEALTH_CEILING} coins.",
|
||||
}
|
||||
if _lvl(farm, "harvests_week") < economy.GRANT_MIN_WEEK_HARVESTS:
|
||||
return {
|
||||
"available": False,
|
||||
"amount": 0,
|
||||
"reason": (
|
||||
f"Harvest at least {economy.GRANT_MIN_WEEK_HARVESTS} builds this week to qualify."
|
||||
),
|
||||
}
|
||||
amount = economy.grant_amount(treasury_balance())
|
||||
if amount <= 0:
|
||||
return {
|
||||
"available": False,
|
||||
"amount": 0,
|
||||
"reason": "The treasury is empty - refactor fees fill it.",
|
||||
}
|
||||
return {"available": True, "amount": amount, "reason": ""}
|
||||
|
||||
|
||||
def claim_grant(user: dict) -> dict:
|
||||
farm = ensure_farm(user["uid"])
|
||||
now = _now()
|
||||
status = grant_status(farm, now)
|
||||
if not status["available"]:
|
||||
raise GameError(status["reason"])
|
||||
amount = status["amount"]
|
||||
week = _iso_week(now)
|
||||
if not _debit_treasury(amount):
|
||||
raise GameError("The treasury is empty - refactor fees fill it.")
|
||||
rows = conditional_update_farm(
|
||||
farm["uid"],
|
||||
set_clause=(
|
||||
"coins = coins + :amount, "
|
||||
"last_grant_week = :week, "
|
||||
"lifetime_coins_earned = COALESCE(lifetime_coins_earned, 0) + :amount"
|
||||
),
|
||||
where_clause=(
|
||||
"(last_grant_week IS NULL OR last_grant_week != :week) AND coins < :ceiling"
|
||||
),
|
||||
params={"amount": amount, "week": week, "ceiling": economy.GRANT_WEALTH_CEILING},
|
||||
)
|
||||
if rows == 0:
|
||||
_refund_treasury(amount)
|
||||
farm = get_farm(user["uid"])
|
||||
if farm and farm.get("last_grant_week") == week:
|
||||
raise GameError("Grant already claimed this week.")
|
||||
raise GameError("Your farm changed - refresh and try again.")
|
||||
return {"amount": amount, "week": week}
|
||||
Reference in New Issue
Block a user