- Runde 2 og finalen: speakeren læser svarene op ét ad gangen (med hjernen en overbevisende kommentar pr. svar), i samme takt på storskærm og telefoner - Emoji-reaktioner fra telefonerne, der må spammes; de flyver op på storskærmen og tælles på svaret i fokus - Opsummeringen følger speakeren: "lad os rydde op", eksplosioner, så pointene - Speakeren kommenterer, hvordan løgnene skrider frem, uden at røbe indhold, og driller dem, der falder for svage løgne - Reglerne forklares med kort og stemme før rummets første spil - "Lyv for mig" låser forslaget i feltet (halve point), og feltet bliver ikke længere kæmpestort - Svar vises med versaler, og spillernes løgne gemmes med små bogstaver, så store forbogstaver ikke afslører dem - Løgne og navne renses: kun bogstaver, tal og lidt tegnsætning - Valgfrit workspace-id til Anthropic-brugernøgler Claude-Session: https://claude.ai/code/session_01JmhJG6JnhXfzNiKv8f2vHu
This commit is contained in:
@@ -16,6 +16,16 @@ def bank(n_cats=5, per_cat=6):
|
||||
return qs
|
||||
|
||||
|
||||
|
||||
def setUpModule():
|
||||
from fupogfakta.engine import Game
|
||||
Game.show_rules = False # reglerne testes for sig (RulesTests)
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
from fupogfakta.engine import Game
|
||||
Game.show_rules = True
|
||||
|
||||
class GameTestCase(SimpleTestCase):
|
||||
def setUp(self):
|
||||
self.now = 1000.0
|
||||
@@ -229,3 +239,84 @@ class FullGameTests(GameTestCase):
|
||||
self.g.kick(self.g.chooser_id, self.now)
|
||||
self.assertEqual(self.g.phase, "intro")
|
||||
self.assertEqual(len(self.g.players), 2)
|
||||
|
||||
|
||||
class PresentAndReactionTests(GameTestCase):
|
||||
def _to_round2_lie(self):
|
||||
a, b, c = self.join("A", "B", "C")
|
||||
self.g.start(None, self.now)
|
||||
self.g.round_idx, self.g.q_idx = 1, 0 # spring direkte til runde 2 (oplæsning)
|
||||
self.g._begin_question(self.now)
|
||||
self.through_category()
|
||||
return a, b, c
|
||||
|
||||
def test_round2_reads_answers_before_guessing(self):
|
||||
a, b, c = self._to_round2_lie()
|
||||
for p, lie in [(a, "katte"), (b, "hunde"), (c, "heste")]:
|
||||
self.g.submit_lie(p.id, lie, self.now)
|
||||
self.assertEqual(self.g.phase, "present")
|
||||
with self.assertRaises(GameError): # ingen gæt under oplæsningen
|
||||
self.g.guess(a.id, self.g.answers[0].id, self.now)
|
||||
snap = self.g.snapshot(self.now, viewer=a)
|
||||
self.assertEqual(len(snap["present"]["steps_ms"]), len(self.g.answers))
|
||||
self.g.tick(self.g.deadline)
|
||||
self.assertEqual(self.g.phase, "guess")
|
||||
|
||||
def test_reactions_are_rate_limited_and_follow_the_featured_answer(self):
|
||||
a, b, c = self._to_round2_lie()
|
||||
for p, lie in [(a, "katte"), (b, "hunde"), (c, "heste")]:
|
||||
self.g.submit_lie(p.id, lie, self.now)
|
||||
t = self.g.present_started_at + (self.g.present_intro_ms + 100) / 1000 # første svar i fokus
|
||||
first = self.g.answers[0].id
|
||||
sent = [self.g.react(b.id, "😂", t) for _ in range(10)]
|
||||
self.assertEqual(sum(1 for r in sent if r), engine.REACT_PER_SECOND)
|
||||
self.assertEqual(self.g.reactions[first], engine.REACT_PER_SECOND)
|
||||
self.assertIsNone(self.g.react(b.id, "💩", t + 2)) # kun de faste emojis
|
||||
self.assertIsNotNone(self.g.react(b.id, "🔥", t + 2)) # spanden er tom igen efter et sekund
|
||||
|
||||
|
||||
class RulesTests(GameTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.g.show_rules = True
|
||||
|
||||
def test_rules_before_first_game_only(self):
|
||||
a, b = self.join("Asger", "Sus")
|
||||
self.g.start(a.id, self.now)
|
||||
self.assertEqual(self.g.phase, "rules")
|
||||
snap = self.g.snapshot(self.now, viewer=a)
|
||||
self.assertEqual(len(snap["rules"]["items"]), len(engine.RULES))
|
||||
self.assertNotIn("say", snap["rules"]["items"][0]) # replikken er til speakeren, kortet har sin egen tekst
|
||||
self.g.hold_rules(self.now, max_wait=3) # speakeren laver lyd: ingen tidslinje endnu
|
||||
self.g.tick(self.now + 3) # lyden blev aldrig klar: kortene vises uden stemme
|
||||
self.assertEqual(self.g.phase, "rules")
|
||||
self.g.tick(self.g.deadline)
|
||||
self.assertEqual(self.g.phase, "category")
|
||||
# spil igen: ingen regler
|
||||
self.g.phase = "final"
|
||||
self.g.play_again(a.id, self.now)
|
||||
self.assertEqual(self.g.phase, "category")
|
||||
|
||||
|
||||
class SanitizeTests(GameTestCase):
|
||||
def test_lies_are_cleaned_and_lowercased(self):
|
||||
a, b = self.join("Asger", "Sus")
|
||||
self.g.start(a.id, self.now)
|
||||
self.through_category()
|
||||
with self.assertRaises(GameError) as e:
|
||||
self.g.submit_lie(a.id, "😂🔥", self.now) # kun emojis: intet tilbage
|
||||
self.assertEqual(e.exception.code, "lie_invalid")
|
||||
with self.assertRaises(GameError):
|
||||
self.g.submit_lie(a.id, "x" * (engine.MAX_LIE + 1), self.now)
|
||||
self.g.submit_lie(a.id, " Røde Krager 🐦!! ", self.now)
|
||||
self.assertEqual(self.g.lies[a.id], "røde krager")
|
||||
|
||||
def test_sanitize_and_names(self):
|
||||
self.assertEqual(engine.sanitize("Rock'n'roll & co."), "Rock'n'roll & co")
|
||||
self.assertEqual(engine.sanitize("full width 12"), "full width 12")
|
||||
self.assertEqual(engine.sanitize("a\tb\nc"), "a b c")
|
||||
p = self.g.join("Bo 👑")
|
||||
self.assertEqual(p.name, "Bo")
|
||||
with self.assertRaises(GameError) as e:
|
||||
self.g.join("🎉🎉")
|
||||
self.assertEqual(e.exception.code, "name_invalid")
|
||||
|
||||
Reference in New Issue
Block a user