diff --git a/jobs/czech_words.py b/jobs/czech_words.py new file mode 100644 index 0000000..ac4e700 --- /dev/null +++ b/jobs/czech_words.py @@ -0,0 +1,33 @@ +CZECH_WORDS = [ + "AUTO", "BABIČKA", "BANÁN", "BARVA", "BÁSNIČKA", "BATOH", "BAVLNA", "BAZÉN", + "BEDNA", "BERAN", "BLÁTO", "BLESK", "BLOUDIT", "BOBŘÍK", "BODLÁK", "BOTY", + "BOUDA", "BOUŘKA", "BRÁNA", "BRATR", "BROUK", "BRUSLE", "BUBEN", "BUNDA", + "CESTA", "CIHLA", "CIRKUS", "CITRON", "CUKR", "ČEPICE", "ČERVENÁ", "ČESNEK", + "ČÍSLO", "ČLOVĚK", "DÁREK", "DATEL", "DCERA", "DĚDEČEK", "DEŠTNÍK", "DIVADLO", + "DOKTOR", "DOMOV", "DOPIS", "DORT", "DRAK", "DUBEN", "DŮM", "DVEŘE", + "DŽBÁN", "FARA", "FIALA", "FILM", "FLÉTNA", "FOTBAL", "GUMA", "HAVRAN", + "HLAVA", "HLÍNA", "HNÍZDO", "HODINY", "HOLKA", "HOLUB", "HORA", "HOUSKA", + "HRAD", "HRÁBĚ", "HRANA", "HRAČKA", "HRNEK", "HRUŠKA", "HUDBA", "CHATA", + "CHLÉB", "CHLAP", "CHYBA", "JABLKO", "JAHODA", "JARO", "JAZYK", "JEHLA", + "JEZERO", "JÍDLO", "JITRO", "KABÁT", "KAČNA", "KAKAO", "KÁMEN", "KAPSÁŘ", + "KARTA", "KÁVA", "KILO", "KLADIVO", "KLÍČ", "KLOBOUK", "KLUK", "KNIHA", + "KOČKA", "KOLO", "KOMÁR", "KONEC", "KOPEC", "KOŘEN", "KOST", "KOŠILE", + "KOZA", "KRÁL", "KRÁVA", "KRESLIT", "KREV", "KRK", "KRUH", "KUCHYNĚ", + "KVĚTINA", "LÁSKA", "LAVICE", "LEDEN", "LES", "LÉTO", "LEV", "LÍSTEK", + "LOĎ", "LOUKA", "LŽÍCE", "MÁMA", "MAPA", "MASO", "MĚSTO", "METR", + "MLÉKO", "MLÝN", "MODRÁ", "MOŘE", "MOST", "MOTÝL", "MRAK", "MRKEV", + "MUŽ", "MYŠ", "NÁDRAŽÍ", "NOHA", "NOC", "NOS", "NOVINY", "NŮŽKY", + "OBCHOD", "OBĚD", "OBRAZ", "OCAS", "OKNO", "OKO", "OLEJ", "OPICE", + "OREL", "OVOCE", "PÁTEK", "PES", "PÍSEŇ", "PIVO", "PLÁČ", "PLOT", + "POLE", "POLÉVKA", "POMOC", "POSTEL", "POTOK", "PRÁCE", "PRAHA", "PRASE", + "PRST", "PTÁK", "RÁDIO", "RADOST", "RAKETA", "RÁNO", "RUKA", "RYBA", + "ŘEKA", "ŘEPA", "SÁŇKY", "SEDLO", "SESTRA", "SEŠIT", "SKLO", "SLON", + "SLUNCE", "SNÍH", "SOVA", "SRDCE", "STROM", "STŮL", "SVĚTLO", "ŠKOLA", + "ŠATY", "ŠNEK", "TÁTA", "TELEVIZE", "TETA", "TMA", "TRAVÁ", "TRH", + "TUŽKA", "UCHO", "ULICE", "ÚNOR", "ÚSTA", "VAJÍČKO", "VÁNOCE", "VČELA", + "VEČEŘE", "VEJCE", "VELRYBA", "VESNICE", "VĚTR", "VODA", "VOJÁK", "VOLANT", + "VRÁNA", "VRATA", "VLASY", "VLAK", "VLK", "ZÁHADA", "ZAHRADA", "ZÁMEK", + "ZIMA", "ZLATO", "ZUB", "ZVON", "ŽÁBA", "ŽÁROVKA", "ŽENA", "ŽIDLE", "ŽIVOT", + # special letters to make sure we have them covered: + "WEB", "PIXEL", "TEQUILA", "BRAWL", "BOX", "QÍK" +] \ No newline at end of file diff --git a/jobs/word_search.py b/jobs/word_search.py new file mode 100644 index 0000000..119d6cd --- /dev/null +++ b/jobs/word_search.py @@ -0,0 +1,143 @@ +import random +import time +import textwrap +from jobs.czech_words import CZECH_WORDS + +class WordSearchJob: + def __init__(self): + self.width = 14 + self.height = 14 + self.hidden_phrase = "TAJENKA" + self.words_to_find = [] + self.grid = [] + + def get_name(self): + return "Word Search (Osmismerka)" + + def configure(self): + print("\n--- Configure Word Search ---") + phrase = input("Enter hidden phrase (default: TAJENKA): ").strip().upper() + if phrase: + self.hidden_phrase = "".join(c for c in phrase if c.isalnum()) + else: + self.hidden_phrase = "TAJENKA" + self.width = len(self.hidden_phrase) + 2 + self.height = len(self.hidden_phrase) + 2 + size = int(input(f"Enter size (default: {self.width}): ").strip()) + if size: + self.width = size + self.height = size + if self.width < 5: + self.width = 5 + self.height = 5 + if self.width > 40: + self.width = 40 + self.height = 40 + + def run(self, printer): + # Directions: Right, Down, Diag-Down-Right + directions = [(0, 1), (1, 0), (1, 1)] + target_empty = len(self.hidden_phrase) + + # Retry loop to ensure perfect fill (no leftover letters) + for attempt in range(20): + # Initialize grid + self.grid = [['' for _ in range(self.width)] for _ in range(self.height)] + used_mask = [[False for _ in range(self.width)] for _ in range(self.height)] + + # Filter words that fit in the grid + available_words = [w for w in CZECH_WORDS if len(w) <= self.width and len(w) <= self.height] + random.shuffle(available_words) + + self.words_to_find = [] + + total_cells = self.width * self.height + current_empty = total_cells + + # Try to place words until we reach target_empty + for word in available_words: + if current_empty == target_empty: + break + + placed = False + attempts = 0 + while not placed and attempts < 50: + attempts += 1 + direction = random.choice(directions) + dr, dc = direction + + # Determine bounds + if dr == 0: # Horizontal + r = random.randint(0, self.height - 1) + c = random.randint(0, self.width - len(word)) + elif dc == 0: # Vertical + r = random.randint(0, self.height - len(word)) + c = random.randint(0, self.width - 1) + else: # Diagonal + r = random.randint(0, self.height - len(word)) + c = random.randint(0, self.width - len(word)) + + # Check collision + fits = True + temp_new_cells = 0 + for i, char in enumerate(word): + nr, nc = r + i*dr, c + i*dc + # Cell must be empty OR contain the same letter + if self.grid[nr][nc] != '' and self.grid[nr][nc] != char: + fits = False + break + if self.grid[nr][nc] == '': + temp_new_cells += 1 + + if fits: + # Check if this overfills + if current_empty - temp_new_cells < target_empty: + continue + + # Place it + for i, char in enumerate(word): + nr, nc = r + i*dr, c + i*dc + if self.grid[nr][nc] == '': + current_empty -= 1 + self.grid[nr][nc] = char + used_mask[nr][nc] = True + self.words_to_find.append(word) + placed = True + + if current_empty == target_empty: + break + + # Fill remaining spots with hidden phrase + empty_slots = [] + for r in range(self.height): + for c in range(self.width): + if not used_mask[r][c]: + empty_slots.append((r, c)) + + phrase_idx = 0 + for r, c in empty_slots: + if phrase_idx < len(self.hidden_phrase): + self.grid[r][c] = self.hidden_phrase[phrase_idx] + phrase_idx += 1 + else: + # Fill with random letters if phrase is done (extra filler) + self.grid[r][c] = random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + + # Print Header + printer.text("OSMISMĚRKA\n") + printer.text("Najdi slova a přečti tajenku!\n") + if current_empty != target_empty: + printer.text(f"Tajenka má {len(self.hidden_phrase)} písmen.\n") + printer.text("\n") + + # Print Grid + for r in range(self.height): + line = " ".join(self.grid[r]) + printer.text(line + "\n") + time.sleep(0.05) + + printer.text("\nSlova k hledání:\n") + words_str = ", ".join(sorted(self.words_to_find)) + printer.text(textwrap.fill(words_str, width=42) + "\n") + printer.text("\n\n") + printer.cut() \ No newline at end of file diff --git a/print_server.py b/print_server.py index 314b865..cc965e5 100644 --- a/print_server.py +++ b/print_server.py @@ -10,6 +10,7 @@ from jobs.decimal_division import DecimalDivisionJob from jobs.joke import JokeJob from jobs.maze_multitarget import MazeMultitargetJob from jobs.flush import FlushJob +from jobs.word_search import WordSearchJob # ========================================== # CONFIGURATION @@ -64,6 +65,7 @@ JOBS = [ DecimalDivisionJob(), JokeJob(), MazeMultitargetJob(), + WordSearchJob(), # keep this last: FlushJob() ]