From ccb925b89adeeae695cc51a789408a685837e033 Mon Sep 17 00:00:00 2001 From: Asger Geel Weirsoee Date: Tue, 20 Oct 2026 21:59:53 +0200 Subject: [PATCH] =?UTF-8?q?Spionen:=20et=20stikord=20m=C3=A5=20ikke=20inde?= =?UTF-8?q?holde=20ordet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fra QA: sammensatte ord med ordet i (pingvinunge, hundehus, pizzabager, togskinne) blev godtaget, og så stod ordet på storskærmen for spionen. Nu afvises et stikord fra en, der kender ordet, hvis ordet står inde i det (ord på tre bogstaver eller flere; "is" ville ellers ramme alt for meget). Prisen er, at et andet ord, der tilfældigvis indeholder ordet, også afvises ("hvalp" til "hval"); en lækage er værre end en afvisning. Co-Authored-By: Claude Opus 5.5 --- spionen/engine.py | 9 ++++++++- spionen/tests/test_engine.py | 8 ++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/spionen/engine.py b/spionen/engine.py index 7d2917a..6ed2955 100644 --- a/spionen/engine.py +++ b/spionen/engine.py @@ -130,6 +130,13 @@ def same_word(a: str, b: str, typos: bool = True) -> bool: return typos and levenshtein(x, y) <= typo_allowance(y) +def contains_word(clue: str, word: str) -> bool: + """Står ordet inde i stikordet (sammensatte ord: "hundehus", "pizzabager")? Kun for ord på tre bogstaver eller + flere, ellers ville fx "is" ramme alt for meget.""" + w = squash(word) + return len(w) >= 3 and w in squash(clue) + + def clean_text(text: str, code: str, what: str, max_len: int) -> str: text = sanitize(str(text or "")).lower() if not text or len(text) > max_len or not normalize(text): @@ -372,7 +379,7 @@ class Game: if " " in clue: raise GameError("clue_invalid", "Skriv kun ét ord.") spy = member_id in self.spies - if not spy and same_word(clue, self.word, typos=False): + if not spy and (same_word(clue, self.word, typos=False) or contains_word(clue, self.word)): raise GameError("clue_is_word", "Det er jo ordet selv. Find på noget andet.") theme_words = [w for w in re.split(r"[\s-]+", self.theme["name"]) if len(squash(w)) >= 3] if any(same_word(clue, w, typos=False) for w in theme_words) or same_word(clue, self.theme["name"], typos=False): diff --git a/spionen/tests/test_engine.py b/spionen/tests/test_engine.py index d173511..616929f 100644 --- a/spionen/tests/test_engine.py +++ b/spionen/tests/test_engine.py @@ -103,10 +103,14 @@ class ClueTests(TestCase): self.assertEqual(e.exception.code, code) def test_word_and_inflections_are_refused_but_near_words_are_fine(self): - for text in ("kat", "Katten", "kattene"): + for text in ("kat", "Katten", "kattene", "kattekilling", "missekat"): self.bad(self.agent, text, "clue_is_word") + self.g.word = "hund" + self.bad(self.agent, "hundehus", "clue_is_word") # sammensat: ordet stod på skærmen + self.g.word = "is" + self.g.submit_clue(self.agent, "vis", 1) # korte ord: kun ordet selv og bøjninger self.g.word = "hval" - self.g.submit_clue(self.agent, "hvalp", 1) # et andet ord, ikke en stavefejl + self.bad(self.agent, "hvalp", "clue_is_word") # ordet står i det; prisen for at fange "hvalfangst" self.g.word = "slot" self.g.submit_clue(self.agent, "plot", 1)