""" Vykreslí Suguru puzzle do PDF z dat v MySQL tabulce puzzles. """ import json import os import sys from pathlib import Path sys.stdout.reconfigure(encoding="utf-8") sys.path.insert(0, str(Path(__file__).parent.parent.parent / "Knihovny")) from reportlab.lib import colors from reportlab.lib.pagesizes import A4 from reportlab.lib.units import cm from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfgen.canvas import Canvas from mysql_db import connect_mysql _fonts_dir = os.path.join(os.environ.get("WINDIR", r"C:\Windows"), "Fonts") pdfmetrics.registerFont(TTFont("Arial", os.path.join(_fonts_dir, "arial.ttf"))) pdfmetrics.registerFont(TTFont("ArialBold", os.path.join(_fonts_dir, "arialbd.ttf"))) OUTPUT = Path(__file__).parent / "test_suguru.pdf" def parse_puzzle(puzzle_str: str, grid_size: int): colors_str, clues_str = puzzle_str.split("|") rows = grid_size cols = len(colors_str) // rows color_map = [] clues = [] for r in range(rows): color_row = [] clue_row = [] for c_ in range(cols): idx = r * cols + c_ color_row.append(colors_str[idx]) ch = clues_str[idx] clue_row.append(int(ch) if ch != "." else 0) color_map.append(color_row) clues.append(clue_row) return color_map, clues, rows, cols def parse_solution(solution_str: str, rows: int, cols: int) -> list[list[int]]: return [[int(solution_str[r * cols + c]) for c in range(cols)] for r in range(rows)] def draw_suguru(c: Canvas, x0: float, y0: float, cell: float, color_map: list, clues: list, rows: int, cols: int, title: str = "", solution: list | None = None): num_font = max(cell * 0.5, 7) thin = 0.4 thick = 2.2 if title: c.setFont("ArialBold", 12) c.drawString(x0, y0 + 5, title) # Bílé pozadí c.setFillColor(colors.white) c.rect(x0, y0 - rows * cell, cols * cell, rows * cell, fill=1, stroke=0) # Čísla — nápovědy (zadání) nebo řešení for r in range(rows): for co in range(cols): cx = x0 + co * cell + cell / 2 cy = y0 - (r + 1) * cell + cell * 0.3 if clues[r][co] > 0: c.setFillColor(colors.black) c.setFont("ArialBold", num_font) c.drawCentredString(cx, cy, str(clues[r][co])) elif solution: c.setFillColor(colors.Color(0.4, 0.4, 0.4)) c.setFont("Arial", num_font) c.drawCentredString(cx, cy, str(solution[r][co])) # Tenké vnitřní čáry c.setStrokeColor(colors.Color(0.75, 0.75, 0.75)) c.setLineWidth(thin) for i in range(1, rows): c.line(x0, y0 - i * cell, x0 + cols * cell, y0 - i * cell) for i in range(1, cols): c.line(x0 + i * cell, y0, x0 + i * cell, y0 - rows * cell) # Tlusté hrany mezi různými skupinami c.setStrokeColor(colors.black) c.setLineWidth(thick) # Vnější okraj c.rect(x0, y0 - rows * cell, cols * cell, rows * cell, fill=0, stroke=1) # Horizontální hrany for r in range(rows - 1): seg_start = None for co in range(cols): border = color_map[r][co] != color_map[r + 1][co] if border and seg_start is None: seg_start = co elif not border and seg_start is not None: c.line(x0 + seg_start * cell, y0 - (r + 1) * cell, x0 + co * cell, y0 - (r + 1) * cell) seg_start = None if seg_start is not None: c.line(x0 + seg_start * cell, y0 - (r + 1) * cell, x0 + cols * cell, y0 - (r + 1) * cell) # Vertikální hrany for co in range(cols - 1): seg_start = None for r in range(rows): border = color_map[r][co] != color_map[r][co + 1] if border and seg_start is None: seg_start = r elif not border and seg_start is not None: c.line(x0 + (co + 1) * cell, y0 - seg_start * cell, x0 + (co + 1) * cell, y0 - r * cell) seg_start = None if seg_start is not None: c.line(x0 + (co + 1) * cell, y0 - seg_start * cell, x0 + (co + 1) * cell, y0 - rows * cell) def main(): conn = connect_mysql(database="puzzle") cur = conn.cursor() cur.execute( "SELECT difficulty, puzzle, solution, extra FROM puzzles " "WHERE game_type='suguru' AND puzzle_date='2026-05-08' " "ORDER BY FIELD(difficulty, '6x6', '8x8', '10x10') " "LIMIT 1" ) row = cur.fetchone() cur.close() conn.close() if not row: print("Žádná data.") return difficulty, puzzle_str, solution_str, extra_json = row extra = json.loads(extra_json) grid_size = extra["grid_size"] color_map, clues, rows, cols = parse_puzzle(puzzle_str, grid_size) solution = parse_solution(solution_str, rows, cols) page_w, page_h = A4 board_cm = 11 cell = board_cm * cm / max(rows, cols) board_w = cols * cell board_h = rows * cell c = Canvas(str(OUTPUT), pagesize=A4) # Zadání x0 = (page_w - board_w) / 2 y0 = page_h - 2 * cm draw_suguru(c, x0, y0, cell, color_map, clues, rows, cols, f"Suguru {difficulty} — 2026-05-08") # Řešení y0_sol = y0 - board_h - 3 * cm draw_suguru(c, x0, y0_sol, cell, color_map, clues, rows, cols, "Řešení", solution=solution) c.save() print(f"PDF uloženo: {OUTPUT}") if __name__ == "__main__": main()