# 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