Хронологика
Журнальная головоломка, которая каждый раз новая. MVP за четыре дня, чтобы проверить спрос, с генератором, который отсеивает поля, нерешаемые без угадывания.
- Роль
- Автор
- Период
- 2026 — сейчас
- Статус
- Live
- Код
- Закрыт
Задача
В журнале «Панорама Кросс» есть «Хронологика»: в поле из букв спрятана цитата, её буквы не касаются друг друга, а стрелки по краям говорят, сколько букв в каждой линии. Хотелось играть в неё в браузере, и каждый раз в новую.
Главное требование: решение должно быть не просто единственным, до него должно получаться дойти рассуждением, без угадывания. MVP собран за четыре дня, чтобы проверить спрос, прежде чем вкладываться дальше.
Что я сделал
- 01
Генератор полей
Форма, места для букв, наполнитель, подсказки и стрелки. Любое поле воспроизводится по сиду, а стрелки расставляются паросочетанием (алгоритм Куна).
- 02
Решатель, который думает как человек
Шесть приёмов, которыми решают журнальную версию. Поле попадает в игру, только если решатель прошёл его до конца, а сложность задаётся списком приёмов.
- 03
CP-SAT как проверка проверяющего
Сначала единственность решения доказывал CP-SAT из OR-Tools, но ни одно из 64 одобренных им полей человеческий решатель не прошёл. Теперь CP-SAT независимо перепроверяет каждое поле перед сохранением, за 3–160 мс.
- 04
Цитаты без нагрузки на источник
Только пути из robots.txt, пара страниц раз в ~10 минут с паузами. Головоломки готовятся заранее, и на 3 000 сбор останавливается.
- 05
Статистика для проверки спроса
Визиты и решённые поля считаются по дням, полностью обезличенно и без cookies. Отчёт каждый день приходит в Telegram.
- 06
Весь стек за четыре дня
FastAPI и PostgreSQL, генерация в фоне на Taskiq, фронтенд на React. Образы собирает GitHub Actions, сайт работает за Traefik и nginx с HSTS.
Стек
- OR-Tools
- FastAPI
- PostgreSQL
- React
- Python
- TypeScript
- SQLAlchemy
- Alembic
- Dishka
- Taskiq
- Redis
- Tailwind
- pytest
- testcontainers
- mypy
- ruff
- Docker Compose
- Traefik
- nginx
- GitHub Actions