Achievements

This commit is contained in:
2026-10-21 13:19:43 -04:00
parent f9afa8ccbe
commit a9f578571c
6 changed files with 260 additions and 3 deletions
+58 -1
View File
@@ -325,6 +325,62 @@ def empty_zone_counts():
return {z["name"]: 0 for z in ZONES}
def player_achievements(pid):
"""Derive private achievements from recorded history, including legacy games."""
quiet_target = max(1, state["duration_ms"] // 2)
close_at = spectrum_at = quiet_at = None
visited = set()
longest_quiet = 0
previous_at = state["started_at"]
zone_names = {zone["name"] for zone in ZONES}
extra_rules = [
("red_alert", "Red alert", "Press in the red zone.", "red", None),
("into_the_dark", "Into the dark", "Press in the black zone.", "black", None),
("white_knuckle", "White knuckle", "Press in the white zone.", "white", None),
("photo_finish", "Photo finish", "Press with less than ten seconds remaining.", None, 10000),
("last_second", "Last second", "Press with less than one second remaining.", None, 1000),
]
extra_unlocks = {rule[0]: None for rule in extra_rules}
for press in state["presses"]:
quiet_ms = max(0, press["at"] - previous_at)
previous_at = press["at"] # measure the global gap, not this player's gap
if press["player_id"] != pid:
continue
for achievement_id, _, _, zone, threshold in extra_rules:
qualifies = press["zone"] == zone if zone is not None else 0 < press["remaining_ms"] < threshold
if extra_unlocks[achievement_id] is None and qualifies:
extra_unlocks[achievement_id] = press["at"]
if close_at is None and 0 < press["remaining_ms"] < 60000:
close_at = press["at"]
if press["zone"] in zone_names:
visited.add(press["zone"])
if spectrum_at is None and visited == zone_names:
spectrum_at = press["at"]
longest_quiet = max(longest_quiet, quiet_ms)
if quiet_at is None and quiet_ms >= quiet_target:
quiet_at = press["at"]
return [
{"id": "close_call", "name": "Close call",
"description": "Press with less than one minute remaining.",
"unlocked": close_at is not None, "unlocked_at": close_at,
"progress": int(close_at is not None), "target": 1},
{"id": "full_spectrum", "name": "Full spectrum",
"description": "Press in all six scoring zones.",
"unlocked": spectrum_at is not None, "unlocked_at": spectrum_at,
"progress": len(visited), "target": len(zone_names)},
{"id": "keeping_us_alive", "name": "Keeping us alive",
"description": "Press after nobody has pressed for at least half the game's countdown.",
"unlocked": quiet_at is not None, "unlocked_at": quiet_at,
"progress": min(longest_quiet, quiet_target), "target": quiet_target},
] + [
{"id": achievement_id, "name": name, "description": description,
"unlocked": extra_unlocks[achievement_id] is not None,
"unlocked_at": extra_unlocks[achievement_id],
"progress": int(extra_unlocks[achievement_id] is not None), "target": 1}
for achievement_id, name, description, _, _ in extra_rules
]
def player_summary(pid):
presses = [p for p in state["presses"] if p["player_id"] == pid]
counts = empty_zone_counts()
@@ -350,6 +406,7 @@ def player_summary(pid):
"zone_counts": counts,
"best_remaining_ms": min((p["remaining_ms"] for p in presses), default=None),
"personal_bests": {"closest_call": record(closest), "highest_scoring_press": record(best)},
"achievements": player_achievements(pid),
"ranking": {
"position": position + 1,
"total_players": len(standings),
@@ -403,7 +460,7 @@ def global_stats():
leaderboard = []
for pid in state["players"]:
s = player_summary(pid)
del s["presses"], s["subscribed"], s["personal_bests"], s["ranking"]
del s["presses"], s["subscribed"], s["personal_bests"], s["ranking"], s["achievements"]
leaderboard.append(s)
leaderboard.sort(key=lambda s: (-s["total_points"], s["name"].lower()))
presses = state["presses"]