83 lines
3.4 KiB
Markdown
83 lines
3.4 KiB
Markdown
# DailyStr8ts — technické poznámky
|
||
|
||
## Přehled skriptů
|
||
|
||
| Skript | Popis |
|
||
|--------|-------|
|
||
| `stahni_str8ts.py` | Stahuje denní puzzle jako PDF z webu, odesílá emailem |
|
||
| `preskumaj_str8ts.py` | Průzkumný — vytáhne `gameLevels` z JS kontextu stránky |
|
||
| `vykresli_puzzle.py` | Generuje vlastní PDF z dat v MySQL (reportlab, vektorové) |
|
||
| `vykresli_velikosti.py` | Testovací — jedno puzzle v 17 velikostech (18–2 cm) |
|
||
| `create_puzzles_table.sql` | DDL pro tabulku `puzzle.puzzles` |
|
||
|
||
## Stahování z webu (`stahni_str8ts.py`)
|
||
|
||
**Výstup:** `U:\Dropbox\!!!Days\Downloads Z230\yyyy-mm-dd Daily Str8ts puzzle.pdf`
|
||
|
||
**Příjemci:** vladimir.buzalka@buzalka.cz, alica.buzalkova@buzalka.cz
|
||
|
||
Stránka `game.php` má funkci `Game.printDaily()` která:
|
||
1. Vytvoří skrytý `<iframe id="printFrame">` v DOM
|
||
2. Zapíše do něj puzzle HTML přes `contentWindow.document.write()` — všechny 3 obtížnosti (Easy, Medium, Hard)
|
||
3. Data `gameLevels` jsou načtena při page load — žádný extra AJAX není potřeba
|
||
4. Zavolá `contentWindow.print()` → Chrome print dialog
|
||
|
||
**Řešení v skriptu:**
|
||
- Načteme `game.php` (headless Chromium)
|
||
- Zavoláme `Game.printDaily()` přes JS evaluate
|
||
- Přečteme `iframe.contentDocument.documentElement.outerHTML`
|
||
- Přidáme `<base href="https://www.solitaire.org/daily-str8ts/">` pro obrázky
|
||
- Načteme HTML do nové stránky a uložíme jako `page.pdf()`
|
||
|
||
## Datová struktura `gameLevels`
|
||
|
||
JS objekt `gameLevels` obsahuje puzzle pro všechny dny roku, klíčované jako `gameLevels[difficulty]["MM-DD"]`.
|
||
|
||
Každý záznam má 3 stringy po 81 znacích (9×9 mřížka, po řádcích):
|
||
|
||
| Pole | Význam |
|
||
|------|--------|
|
||
| `puzzle` | Zadání: `1`–`9` = předvyplněné číslo, `.` = prázdná buňka |
|
||
| `bw` | Mapa barev: `0` = bílá buňka, `1` = černá buňka |
|
||
| `solution` | Řešení: `1`–`9` = číslo, `.` = černá bez čísla |
|
||
|
||
## MySQL tabulka `puzzle.puzzles`
|
||
|
||
Univerzální tabulka pro Str8ts, Sudoku i další puzzle typy.
|
||
|
||
```sql
|
||
CREATE TABLE puzzles (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
game_type VARCHAR(30) NOT NULL, -- 'str8ts', 'sudoku', 'killer_sudoku'
|
||
difficulty VARCHAR(20) NOT NULL, -- 'easy', 'medium', 'hard'
|
||
puzzle_date DATE NOT NULL,
|
||
puzzle VARCHAR(200) NOT NULL, -- zadání (81 znaků pro 9×9)
|
||
solution VARCHAR(200) DEFAULT NULL,
|
||
extra JSON DEFAULT NULL, -- specifika typu (bw mapa, cage definice...)
|
||
source VARCHAR(100) DEFAULT NULL,
|
||
fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
UNIQUE KEY uq_puzzle (game_type, difficulty, puzzle_date)
|
||
);
|
||
```
|
||
|
||
Pro Str8ts se do `extra` ukládá `{"bw": "001100011..."}`.
|
||
|
||
## Generování vlastního PDF (`vykresli_puzzle.py`)
|
||
|
||
- Knihovna: **reportlab** — vektorová grafika, plynule škálovatelná
|
||
- Zvolená velikost: **11×11 cm**, 2 puzzle nad sebou na A4
|
||
- Černé buňky: `c.rect(fill=1)`, žlutá čísla na černé, černá čísla na bílé
|
||
- Str8ts nemá 3×3 bloky → všechny čáry mřížky stejně silné
|
||
|
||
## Co nefunguje (neopakovat)
|
||
|
||
- `page.pdf()` na hlavní stránce → uvítací obrazovka, ne puzzle
|
||
- `context.expect_page()` → žádný popup se neotevírá
|
||
- Override `window.print` → Game volá `contentWindow.print()`, ne `window.print()`
|
||
|
||
## Co zbývá
|
||
|
||
- Zabudovat extrakci + MySQL insert do `stahni_str8ts.py`
|
||
- Nahradit stahované PDF z webu vlastním generovaným
|
||
- Rozšířit na další typy puzzle (Sudoku, Killer Sudoku)
|