Achievements
This commit is contained in:
+126
@@ -225,6 +225,132 @@ class PersistenceTests(unittest.TestCase):
|
||||
self.assertEqual(summary["personal_bests"]["highest_scoring_press"]["points"], 16)
|
||||
self.assertEqual(set(summary["ranking"]["rival"]), {"name", "total_points", "points_to_tie", "points_to_pass"})
|
||||
|
||||
def achievement_game(self):
|
||||
self.game.state = self.sample_state()
|
||||
self.game.state.update(duration_ms=120000, started_at=1000, presses=[])
|
||||
|
||||
def achievement_map(self, pid="alice"):
|
||||
return {a["id"]: a for a in self.game.player_achievements(pid)}
|
||||
|
||||
def test_achievements_start_locked_without_presses(self):
|
||||
self.achievement_game()
|
||||
achievements = self.achievement_map()
|
||||
self.assertEqual(set(achievements), {"close_call", "full_spectrum", "keeping_us_alive", "red_alert", "into_the_dark", "white_knuckle", "photo_finish", "last_second"})
|
||||
for achievement in achievements.values():
|
||||
self.assertFalse(achievement["unlocked"])
|
||||
self.assertIsNone(achievement["unlocked_at"])
|
||||
self.assertEqual(achievement["progress"], 0)
|
||||
self.assertEqual(achievements["full_spectrum"]["target"], 6)
|
||||
self.assertEqual(achievements["keeping_us_alive"]["target"], 60000)
|
||||
|
||||
def test_close_call_strict_boundary_and_first_unlock(self):
|
||||
self.achievement_game()
|
||||
for remaining in (60000, 0, -1):
|
||||
self.game.state["presses"].append({"player_id": "alice", "at": 2000, "remaining_ms": remaining, "zone": "white", "points": 32})
|
||||
self.game.state["presses"].append({"player_id": "bob", "at": 3000, "remaining_ms": 1, "zone": "white", "points": 32})
|
||||
self.assertFalse(self.achievement_map()["close_call"]["unlocked"])
|
||||
self.game.state["presses"].append({"player_id": "alice", "at": 4000, "remaining_ms": 59999, "zone": "white", "points": 32})
|
||||
self.game.state["presses"].append({"player_id": "alice", "at": 5000, "remaining_ms": 1, "zone": "white", "points": 32})
|
||||
close = self.achievement_map()["close_call"]
|
||||
self.assertTrue(close["unlocked"])
|
||||
self.assertEqual(close["unlocked_at"], 4000)
|
||||
self.assertEqual(close["progress"], 1)
|
||||
|
||||
def test_full_spectrum_counts_distinct_personal_zones_only(self):
|
||||
self.achievement_game()
|
||||
for index, zone in enumerate(self.game.ZONES[:-1]):
|
||||
self.game.state["presses"].append({"player_id": "alice", "at": 2000 + index, "remaining_ms": 1000, "zone": zone["name"], "points": zone["points"]})
|
||||
repeated = dict(self.game.state["presses"][0], at=3000)
|
||||
self.game.state["presses"].extend([repeated] * 10)
|
||||
self.game.state["presses"].append({"player_id": "bob", "at": 4000, "remaining_ms": 1000, "zone": "white", "points": 32})
|
||||
spectrum = self.achievement_map()["full_spectrum"]
|
||||
self.assertEqual(spectrum["progress"], 5)
|
||||
self.assertFalse(spectrum["unlocked"])
|
||||
self.game.state["presses"].append({"player_id": "alice", "at": 5000, "remaining_ms": 1000, "zone": "white", "points": 32})
|
||||
spectrum = self.achievement_map()["full_spectrum"]
|
||||
self.assertTrue(spectrum["unlocked"])
|
||||
self.assertEqual(spectrum["unlocked_at"], 5000)
|
||||
self.assertEqual(spectrum["progress"], 6)
|
||||
|
||||
def test_quiet_achievement_uses_global_gaps_and_inclusive_boundary(self):
|
||||
self.achievement_game()
|
||||
self.game.state["presses"] = [
|
||||
{"player_id": "bob", "at": 31000, "remaining_ms": 90000, "zone": "green", "points": 0},
|
||||
{"player_id": "alice", "at": 61000, "remaining_ms": 90000, "zone": "green", "points": 0},
|
||||
]
|
||||
quiet = self.achievement_map()["keeping_us_alive"]
|
||||
self.assertFalse(quiet["unlocked"])
|
||||
self.assertEqual(quiet["progress"], 30000)
|
||||
self.game.state["presses"].append({"player_id": "alice", "at": 120999, "remaining_ms": 60001, "zone": "green", "points": 0})
|
||||
self.assertFalse(self.achievement_map()["keeping_us_alive"]["unlocked"])
|
||||
self.game.state["presses"].append({"player_id": "alice", "at": 180999, "remaining_ms": 60000, "zone": "blue", "points": 2})
|
||||
quiet = self.achievement_map()["keeping_us_alive"]
|
||||
self.assertTrue(quiet["unlocked"])
|
||||
self.assertEqual(quiet["unlocked_at"], 180999)
|
||||
self.assertEqual(quiet["progress"], quiet["target"])
|
||||
|
||||
def test_quiet_achievement_counts_first_press_from_game_start(self):
|
||||
self.achievement_game()
|
||||
self.game.state["presses"] = [{"player_id": "alice", "at": 61000, "remaining_ms": 60000, "zone": "blue", "points": 2}]
|
||||
self.assertEqual(self.achievement_map()["keeping_us_alive"]["unlocked_at"], 61000)
|
||||
self.game.state["duration_ms"] = 86400000
|
||||
self.assertEqual(self.achievement_map()["keeping_us_alive"]["target"], 43200000)
|
||||
self.assertFalse(self.achievement_map()["keeping_us_alive"]["unlocked"])
|
||||
|
||||
def test_achievements_credit_legacy_history_and_survive_restart(self):
|
||||
self.achievement_game()
|
||||
for index, zone in enumerate(self.game.ZONES):
|
||||
self.game.state["presses"].append({"player_id": "alice", "at": 61000 + index * 1000, "remaining_ms": 999, "zone": zone["name"], "points": zone["points"]})
|
||||
expected = self.game.player_achievements("alice")
|
||||
self.assertTrue(all(a["unlocked"] for a in expected))
|
||||
self.write_legacy(self.game.state)
|
||||
self.game.state = self.game.load_state()
|
||||
self.assertEqual(self.game.player_achievements("alice"), expected)
|
||||
self.game.save_state(self.game.state)
|
||||
self.game.state = self.game.load_state()
|
||||
self.assertEqual(self.game.player_achievements("alice"), expected)
|
||||
self.assertFalse(any(a["unlocked"] for a in self.game.player_achievements("bob")))
|
||||
|
||||
def test_achievements_are_private_and_do_not_change_scores(self):
|
||||
request = self.presence_client()
|
||||
self.assertEqual(request(path="/api/me")[0], 401)
|
||||
before = copy.deepcopy(self.game.state)
|
||||
status, summary = request(token="alice-token", path="/api/me")
|
||||
self.assertEqual(status, 200)
|
||||
self.assertEqual(len(summary["achievements"]), 8)
|
||||
self.assertEqual(summary["total_points"], 40)
|
||||
self.assertEqual(self.game.state, before)
|
||||
self.assertNotIn("achievements", self.game.load_state())
|
||||
for row in self.game.public_leaderboard() + self.game.global_stats()["leaderboard"]:
|
||||
self.assertNotIn("achievements", row)
|
||||
|
||||
def test_precision_badges_strict_boundaries_and_first_unlock(self):
|
||||
for achievement_id, threshold in (("photo_finish", 10000), ("last_second", 1000)):
|
||||
with self.subTest(achievement=achievement_id):
|
||||
self.achievement_game()
|
||||
for at, remaining in enumerate((threshold, threshold + 1, 0, -1), start=2000):
|
||||
self.game.state["presses"].append({"player_id": "alice", "at": at, "remaining_ms": remaining, "zone": "green", "points": 0})
|
||||
self.game.state["presses"].append({"player_id": "bob", "at": 3000, "remaining_ms": 1, "zone": "white", "points": 32})
|
||||
self.assertFalse(self.achievement_map()[achievement_id]["unlocked"])
|
||||
for at in (4000, 5000):
|
||||
self.game.state["presses"].append({"player_id": "alice", "at": at, "remaining_ms": threshold - 1, "zone": "white", "points": 32})
|
||||
badge = self.achievement_map()[achievement_id]
|
||||
self.assertTrue(badge["unlocked"])
|
||||
self.assertEqual(badge["unlocked_at"], 4000)
|
||||
self.assertEqual((badge["progress"], badge["target"]), (1, 1))
|
||||
|
||||
def test_zone_badges_require_own_press_in_exact_zone(self):
|
||||
for achievement_id, zone in (("red_alert", "red"), ("into_the_dark", "black"), ("white_knuckle", "white")):
|
||||
with self.subTest(achievement=achievement_id):
|
||||
self.achievement_game()
|
||||
self.game.state["presses"] = [
|
||||
{"player_id": "bob", "at": 2000, "remaining_ms": 1, "zone": zone, "points": 32},
|
||||
{"player_id": "alice", "at": 3000, "remaining_ms": 1, "zone": "green", "points": 0},
|
||||
]
|
||||
self.assertFalse(self.achievement_map()[achievement_id]["unlocked"])
|
||||
self.game.state["presses"].append({"player_id": "alice", "at": 4000, "remaining_ms": 10000, "zone": zone, "points": 8})
|
||||
self.assertEqual(self.achievement_map()[achievement_id]["unlocked_at"], 4000)
|
||||
|
||||
def test_fresh_game_survives_restart_without_creating_json(self):
|
||||
state = self.game.load_state()
|
||||
self.assertEqual(state, self.game.load_state())
|
||||
|
||||
Reference in New Issue
Block a user