|
# retoor <retoor@molodetz.nl>
|
|
|
|
from __future__ import annotations
|
|
|
|
from devplacepy.utils import generate_uid
|
|
|
|
from .. import economy
|
|
from .common import GameError, _farms, _iso, _now, _plots, _update_farm
|
|
|
|
|
|
def get_farm(user_uid: str) -> dict | None:
|
|
return _farms().find_one(user_uid=user_uid)
|
|
|
|
|
|
def ensure_farm(user_uid: str) -> dict:
|
|
farm = get_farm(user_uid)
|
|
if farm:
|
|
return farm
|
|
now = _iso(_now())
|
|
uid = generate_uid()
|
|
_farms().insert(
|
|
{
|
|
"uid": uid,
|
|
"user_uid": user_uid,
|
|
"coins": economy.STARTING_COINS,
|
|
"xp": 0,
|
|
"level": 1,
|
|
"ci_tier": 1,
|
|
"plot_count": economy.STARTING_PLOTS,
|
|
"total_harvests": 0,
|
|
"created_at": now,
|
|
"updated_at": now,
|
|
}
|
|
)
|
|
for slot_index in range(economy.STARTING_PLOTS):
|
|
_create_plot(uid, user_uid, slot_index, now)
|
|
return get_farm(user_uid)
|
|
|
|
|
|
def _create_plot(farm_uid: str, user_uid: str, slot_index: int, now: str) -> None:
|
|
_plots().insert(
|
|
{
|
|
"uid": generate_uid(),
|
|
"farm_uid": farm_uid,
|
|
"user_uid": user_uid,
|
|
"slot_index": slot_index,
|
|
"crop_key": "",
|
|
"planted_at": "",
|
|
"ready_at": "",
|
|
"watered_by": "[]",
|
|
"created_at": now,
|
|
"updated_at": now,
|
|
}
|
|
)
|
|
|
|
|
|
def get_plots(farm_uid: str) -> list[dict]:
|
|
rows = list(_plots().find(farm_uid=farm_uid))
|
|
rows.sort(key=lambda row: row.get("slot_index", 0))
|
|
return rows
|
|
|
|
|
|
def _plot_at(farm_uid: str, slot_index: int) -> dict | None:
|
|
return _plots().find_one(farm_uid=farm_uid, slot_index=slot_index)
|
|
|
|
|
|
def buy_plot(user: dict) -> dict:
|
|
farm = ensure_farm(user["uid"])
|
|
plot_count = int(farm.get("plot_count", economy.STARTING_PLOTS))
|
|
if plot_count >= economy.MAX_PLOTS:
|
|
raise GameError("All plots are already unlocked.")
|
|
cost = economy.plot_cost(plot_count)
|
|
coins = int(farm.get("coins", 0))
|
|
if coins < cost:
|
|
raise GameError("Not enough coins for a new plot.")
|
|
_create_plot(farm["uid"], user["uid"], plot_count, _iso(_now()))
|
|
_update_farm(farm["uid"], {"coins": coins - cost, "plot_count": plot_count + 1})
|
|
return {"plot_count": plot_count + 1, "spent": cost}
|
|
|
|
|
|
def upgrade_ci(user: dict) -> dict:
|
|
farm = ensure_farm(user["uid"])
|
|
ci_tier = int(farm.get("ci_tier", 1))
|
|
next_tier = economy.next_ci_tier(ci_tier)
|
|
if not next_tier:
|
|
raise GameError("CI is already at the top tier.")
|
|
coins = int(farm.get("coins", 0))
|
|
if coins < next_tier.upgrade_cost:
|
|
raise GameError("Not enough coins to upgrade CI.")
|
|
_update_farm(
|
|
farm["uid"],
|
|
{"coins": coins - next_tier.upgrade_cost, "ci_tier": next_tier.tier},
|
|
)
|
|
return {"ci_tier": next_tier.tier, "spent": next_tier.upgrade_cost}
|
|
|
|
|
|
def leaderboard(limit: int = 25) -> list[dict]:
|
|
farms = sorted(
|
|
_farms().find(),
|
|
key=economy.farm_score,
|
|
reverse=True,
|
|
)[:limit]
|
|
if not farms:
|
|
return []
|
|
from devplacepy.database import get_users_by_uids
|
|
|
|
users = get_users_by_uids([farm["user_uid"] for farm in farms])
|
|
entries = []
|
|
for rank, farm in enumerate(farms, start=1):
|
|
owner = users.get(farm["user_uid"])
|
|
if not owner:
|
|
continue
|
|
entries.append(
|
|
{
|
|
"rank": rank,
|
|
"username": owner.get("username", ""),
|
|
"level": int(farm.get("level", 1)),
|
|
"xp": int(farm.get("xp", 0)),
|
|
"coins": int(farm.get("coins", 0)),
|
|
"total_harvests": int(farm.get("total_harvests", 0)),
|
|
"prestige": int(farm.get("prestige") or 0),
|
|
"score": economy.farm_score(farm),
|
|
}
|
|
)
|
|
return entries
|