80 KiB
80 KiB
📋 Задачи проекта: study.qpid.pro (Backlog & Execution Queue)
Список задач для последовательной реализации в рамках принципов Ponytail (максимальная надёжность, нативные средства платформы, zero-dependency, высокая скорость).
🚀 Очередь реализации (Пошаговый план)
1. 📑 Полноценный рендеринг Markdown (.md) в читалке
- Блоки кода (Fenced Code Blocks
```language):- Выделение блоков кода в контейнер
<pre><code class="language-...">. - Моноширинный шрифт (
JetBrains Mono,Consolas), сохранение отступов и табуляции (white-space: pre). - Тёмная подложка, горизонтальный скролл при переполнении, отключение красной строки (
text-indent: 0). - Кнопка «Копировать код» в шапке блока.
- Отключение создания интерактивных словарных спанов
<span class="reader-word">для кода, чтобы синтаксис не ломал форматирование.
- Выделение блоков кода в контейнер
- Инлайн-код (
`variable`):- Оборачивание в нативный тег
<code class="reader-inline-code">с бейджик-стилем.
- Оборачивание в нативный тег
- Списки и цитаты:
- Преобразование маркированных (
-,*) и нумерованных (1.) списков в<ul><li>/<ol><li>. - Преобразование цитат (
>) в<blockquote>с акцентной левой границей. - Слова внутри списков и цитат остаются кликабельными (интерактивный клик-перевод работает!).
- Преобразование маркированных (
- Заголовки Markdown (
##,###):- Конвертация в
<h3>,<h4>с удалением сырых решёток#.
- Конвертация в
- Таблицы Markdown (
| col | col |):- Адаптивные таблицы с рамками, стилизацией заголовков
<thead>, зебра-подсветкой строк и горизонтальным скроллом на мобильных. - Каждая ячейка поддерживает интерактивные слова для изучения и инлайн-код.
- Адаптивные таблицы с рамками, стилизацией заголовков
- HTML-блоки и теги в Markdown (
<p align="center">,<h1>,<em>,<strong>,<sub>,<br>):- Нативный парсинг через встроенный
DOMParserбез внешних библиотек. - Устранена утечка сырых тегов (
<picture>,<source>,<p align=...>) в словарные слова.
- Нативный парсинг через встроенный
- Ссылки и изображения (
[text](url),,<img>):- Поддержка бейджей shields.io, тренд-графиков и внешних картинок.
- Автоматическое скрытие битых/отсутствующих локальных путей (
assets/...) через обработчикonerror.
- Точное позиционирование окна перевода у курсора/слова (Popup Positioning):
- Исправлен баг двойного смещения координат: убран
window.scrollYприposition: fixed. - Окно перенесено в корень
<body>для исключения искажений контекста позиционирования. - Плавное отслеживание скролла через
requestAnimationFrameс автозакрытием при уходе слова за границы экрана или под липкую шапку.
- Исправлен баг двойного смещения координат: убран
- Стилизация в CSS (
app/static/css/style.css):- Добавлены стили для
.reader-content-body pre,code,blockquote,ul,ol,.reader-table,.reader-heading,.reader-link,.reader-img.
- Добавлены стили для
2. 🗜️ Сжатие статического трафика (GZipMiddleware)
- Подключить
GZipMiddleware(minimum_size=1000)вapp/main.py. - Сократить объём передаваемых файлов
app.js(111.8 КБ -> 21.5 КБ),index.html(55.2 КБ -> 10.3 КБ) иstyle.css(58.2 КБ -> 9.4 КБ) на 81.7% (суммарно с 225.2 КБ до 41.2 КБ). - Проверить заголовки
Content-Encoding: gzipв ответах и добавить регрессионный тест вtests/test_api.py.
3. 🛡️ Дедупликация слов и защита от повторного добавления (Reader + API)
- Проверка дубликатов на бэкенде (
POST /api/cards):- Проверка слова без учёта регистра
lower(trim(term)). - При повторном добавлении не создаётся дубликат, а дополняется контекстное предложение и объединяются теги, возвращается
already_exists: True.
- Проверка слова без учёта регистра
- Индикация в читалке и карточке поиска:
- В читалке при клике на слово и в карточке поиска выводится бейдж
⭐ В библиотеке. - Кнопка «+ В словарь» заменяется на бейдж
⭐ Слово уже в библиотекес опциональной кнопкой+ Добавить эту цитату к карточке.
- В читалке при клике на слово и в карточке поиска выводится бейдж
- Индекс целостности в SQLite:
- Создан
UNIQUE INDEX idx_vocab_user_term_nocase ON vocabulary_cards(user_id, term COLLATE NOCASE);гарантирующий отсутствие дубликатов на уровне движка БД заO(\log N).
- Создан
- Слияние существующих дубликатов в базе:
- Объединены дубликаты
admired(ID 5 и ID 7) иsuddenly/Suddenly(ID 2 и ID 9) с объединением контекстных предложений, слиянием тегов и сохранением прогресса SRS.
- Объединены дубликаты
4. 📱 Мобильная оптимизация и адаптивная верстка (iPhone 12 / iOS Safari)
- Системный фундамент iOS и сброс ограничений (Core Foundation):
- Метатег
viewport: добавленviewport-fit=coverдля поддержки выреза (notch) и нижней панели iPhone. - Устранение бага принудительного авто-зума: установлен
font-size: 16pxдля<input>,<textarea>,<select>на экранах≤ 768px. - Внедрены динамические единицы
100dvh(Dynamic Viewport Height) и безопасные отступыenv(safe-area-inset-top)/env(safe-area-inset-bottom). - Защита от горизонтального сдвига (
overflow-x: hiddenнаhtml,bodyи#app-shell).
- Метатег
- Мобильная навигация: переход к нативному паттерну (App Header + Bottom Tab Bar):
- Компактная верхняя шапка для смартфонов: логотип
📖 Notes, переключатель темы🌓, кнопка вызова профиля⚙️. - Фиксированная нижняя панель вкладок (Bottom Tab Bar) с нативным iOS UX:
- 🔍 Словарь (Поиск и словарь)
- 🎓 Тренажёр (SRS с бейджем количества повторений)
- 📚 Читалка (Библиотека книг)
- 📊 Прогресс (Статистика и стрик)
- ⚙️ Меню (Смена пароля, экспорт, выход)
- Полное сохранение десктопного
navbarбез изменений на больших экранах (> 768px).
- Компактная верхняя шапка для смартфонов: логотип
- Адаптация экрана словаря и карточек (Dictionary & Cards View):
- Поле поиска/перевода на полную ширину экрана с кнопкой «Перевести».
- Скрытие неактуальных десктопных подсказок горячих клавиш (
<kbd>Ctrl+Enter</kbd>) на мобильных устройствах. - Вертикальная раскладка полей метаданных при редактировании карточки.
- Горизонтальный скролл чипсов коллекций и тегов (
overflow-x: auto; white-space: nowrap; -webkit-overflow-scrolling: touch). - Увеличенные зоны нажатия (Touch Targets ≥ 44px) для кнопок действий над карточкой.
- Интерактивная читалка и переход к Mobile Bottom Sheet:
- Трансформация всплывающего попапа перевода (
reader-word-popup) в нативную выдвижную нижнюю шторку (Bottom Sheet) на смартфонах с ручкой перетаскиванияsheet-drag-handle. - Двухстрочный адаптивный тулбар читалки (навигация по главам + размер шрифта
A-/A+и подсветка). - Сетка библиотеки
bookshelf-gridв одну колонку на экранах≤ 640px.
- Трансформация всплывающего попапа перевода (
- Тренажёр интервальных повторений (SRS Trainer):
- Ограничение высоты карточки SRS (
max-height: 48dvh), чтобы карточка и кнопки оценки гарантированно помещались без вертикального скролла на 390px. - Кнопки оценки (Снова / Трудно / Хорошо / Легко) в сетку 2×2 с высотой от 48px и четкими цветовыми акцентами.
- Вертикальный список вариантов в режиме квиза (4 варианта) на всю ширину экрана.
- Ограничение высоты карточки SRS (
- Модальные окна (Статистика, Пароль, Экспорт):
- Метрики статистики в сетку 2×2 вместо сжатых 4 колонок.
- Плавный горизонтальный скролл календаря активности (Heatmap).
- Разворачивание модальных окон в адаптивный мобильный слой с удобной кнопкой закрытия.
5. 🔤 Кастомизация оформления читалки (Типографика, темы, отступы, LocalStorage)
- Панель настроек оформления текста (
Aa):- Кнопка вызова настроек в тулбаре читалки: поповер на ПК и выдвижная шторка (Bottom Sheet) на смартфонах.
- Настройка размера шрифта и степпер:
- Степпер
A-/A+с индикатором точного размера (от 14px до 34px).
- Степпер
- Семейство шрифтов (Font Family):
- Переключение в 1 клик между
Sans(системный),Serif(книжный с засечками),Mono(моноширинный).
- Переключение в 1 клик между
- Межстрочный интервал (Line Height):
- Компактный (1.35), Оптимальный (1.65), Широкий (1.95).
- Поля и ширина колонки (Margins & Max Width):
- Узкие поля (940px), Стандарт (760px), Книжная колонка (600px).
- Цветовые темы читалки (Themes):
- 🌙 Тёмная (Dark Slate), 📜 Сепия (Тёплый пергамент), ☀️ Светлая (Чистый лист), 🖤 OLED (Абсолютный чёрный).
- Выравнивание текста (Text Alignment):
- По левому краю / По ширине (Justified).
- Автосохранение и персистентность:
- Мгновенное реактивное применение стилей через CSS-переменные без перезагрузки и сохранение настроек в
localStorage.
- Мгновенное реактивное применение стилей через CSS-переменные без перезагрузки и сохранение настроек в
6. 🔄 Комплексная переработка навигации, роутинга и честного прогресса чтения (Completed)
- 6.1. Нативная маршрутизация окон (URL Hash Router & Zero-Flicker F5):
- Внедрение хэш-роутинга:
#dictionary,#srs,#bookshelf,#reader/:book_id,#reader/:book_id/ch/:chapter_idx. - Синхронное переключение
viewпри старте скрипта (до любых сетевых запросов авторизации): если в URL#reader/..., сразу скрывать#dictionary-viewи показывать скелетон читалки, устраняя мигание словарем. - Развязка асинхронных вызовов:
loadBookshelf()больше не должен принудительно гаситьreaderInterface, если уже инициировано открытие книги черезopenBook(). - Поддержка нативной истории браузера (кнопки «Назад» / «Вперёд» на мыши, клавиатуре и мобильных свайпах).
- Автоматическая синхронизация активного экрана в URL и
localStorage.
- Внедрение хэш-роутинга:
- 6.2. Честный непрерывный расчет прогресса книги и главы (Weighted Reading Progress):
- Устранение бага ложных «100%»: полная ликвидация формулы
(current_ch + 1) / total_ch, выдававшей 100% на первой странице одноглавных документов. - Прогресс текущей главы в реальном времени: непрерывный расчет от вертикального скролла (
scrollTop / (scrollHeight - clientHeight) * 100) от 0% до 100%. - Взвешенный общий прогресс книги: расчет по объему слов прочитанных глав + точная доля текущей главы:
\text{TotalProgress} = \frac{\sum_{i=0}^{\text{cur}-1} \text{words}(ch_i) + \text{words}(ch_{\text{cur}}) \times \frac{\text{ChapterPct}}{100}}{\text{TotalWords}} \times 100\% - Для документа на 1000 слов прогресс будет плавно расти: 0%
\rightarrow15%\rightarrow50%\rightarrow100%. - Отображение честного суммарного прогресса на карточках книг в библиотеке и в тулбаре читалки.
- Устранение бага ложных «100%»: полная ликвидация формулы
- 6.3. Интеллектуальный парсинг глав и оглавление (Smart Chapter & ToC Detection):
- Расширение детектора глав в
app/reader.py:- Markdown-заголовки всех уровней (
#,##,###,####). - Нумерованные разделы и модули (
1.,1.1,2.0,Section 1,Part 1,Раздел 1). - Выделенные строки в верхнем регистре (ALL CAPS) от 3 до 60 символов, обрамленные пустыми строками (
INTRODUCTION,ETHERNET BASICS). - Жирные заголовки в начале абзацев (
**Chapter 1**,**Глава 1**).
- Markdown-заголовки всех уровней (
- Адаптивный порог авто-разбивки: снижение порога чанкования текста без явных глав с 3000 до 800–1000 слов, чтобы даже небольшие статьи имели логическое деление на части.
- Интерактивное оглавление со статусами прочтения:
✔ Прочитано,▶ В процессе (45%),○ Не начато.
- Расширение детектора глав в
- 6.4. Устойчивая фиксация позиции чтения (Paragraph Anchor + Scroll):
- Сохранение не только пикселей
scrollTop, но и индекса первого видимого абзаца (anchor_paragraph_idx). - Устойчивость к изменению шрифта
Aaи ориентации экрана: восстановление скролла к конкретному предложению/абзацу, а не слепым пикселям. - Фиксация скролл-контейнера
#reader-scroll-areaс аппаратным ускорением на мобильных.
- Сохранение не только пикселей
- 6.5. Сквозное чтение и бесшовная автоподгрузка (Continuous Book View & Seamless Infinite Append):
- Режим «Вся книга целиком» (
flowMode: 'continuous'): объединение всех глав книги в один непрерывный свиток со стильными разделителями глав без необходимости перелистывания. - Режим «По главам» с автоподгрузкой (
autoLoadNext: true): бесшовное присоединение следующей главы снизу при приближении к концу текущей главы. - Навигационный блок завершения главы: эргономичные кнопки «◀ Назад» и «Следующая: [Название] ▶» прямо под текстом (без необходимости тянуться наверх).
- Настройка режима чтения («По главам» / «Вся книга») и переключатель автоподгрузки добавлены в панель настроек
Aaс автосохранением вlocalStorage. - Карточка завершения книги (
🎉 Книга прочитана!) с быстрыми ссылками на тренировку слов и возврат в библиотеку.
- Режим «Вся книга целиком» (
7. 📑 Поддержка чтения PDF (Cisco CCNA, O'Reilly & Tech Books с оглавлением и текстовым слоем) (Completed)
- Легковесный Pure-Python парсер (
pypdf, Zero C-Dependency):- Подключение
pypdf(< 400 КБ, чистый Python, без раздувания Docker-образа и без системных библиотекpoppler-utils/mupdf).
- Подключение
- Извлечение оглавления и закладок PDF (
reader.outline):- Извлечение авторского оглавления (ToC / Bookmarks), стандартного для книг Cisco Press (CCNA Official Cert Guide), O'Reilly и Wiley.
- Разбивка книги на логические главы и разделы (
Part I,Chapter 1,Chapter 2) точно по оглавлению автора.
- Fallback-разбивка при отсутствии оглавления:
- При отсутствии PDF-закладок — автоопределение заголовков через regex (
Chapter \d+,Глава \d+) или группировка страниц порциями по ~12–15 страниц.
- При отсутствии PDF-закладок — автоопределение заголовков через regex (
- Очистка шума и колонтитулов:
- Фильтрация повторяющихся верхних/нижних колонтитулов («CCNA 200-301 Official Cert Guide», «Page 45 of 900»).
- Сохранение CLI/Console блоков:
- Распознавание консольного вывода и команд сетевого оборудования (
Router# show ip interface brief,Switch(config)#) и оборачивание в блоки кода Markdown для читалки с кнопкой «Копировать».
- Распознавание консольного вывода и команд сетевого оборудования (
- Защита от сканов без OCR (Scanned PDF Guard):
- Валидация наличия текстового слоя: если суммарный объём извлечённого текста < 100 слов, возврат информативной ошибки с предложением использовать текстовый PDF или OCR.
- Интеграция в интерфейс читалки:
- Разрешение загрузки
.pdfв<input type="file" accept=".epub,.pdf,.txt,.md">. - Обновление кнопки в библиотеке:
📁 Загрузить EPUB / PDF / TXT.
- Разрешение загрузки
7.1. 🖼️ Извлечение и отображение схем, топологий и диаграмм из PDF / EPUB (Planned)
- Извлечение бинарных изображений на диск:
- При парсинге PDF/EPUB извлекать графические объекты (
page.images/ архивы изображений) на файловую систему в изолированную директорию книги:data/books/{book_id}/images/{img_name}. - Избегать раздувания базы данных SQLite: база хранит только текст и метаданные, бинарная графика хранится на диске.
- При парсинге PDF/EPUB извлекать графические объекты (
- Кэширующий медиа-эндпоинт:
- Создать эндпоинт
GET /api/books/{book_id}/images/{image_name}с заголовками кэширования (Cache-Control: public, max-age=31536000, immutable).
- Создать эндпоинт
- Встраивание в текст читалки:
- Привязывать иллюстрации к соответствующей странице/главе через Markdown-теги:
. - Интерактивный просмотр и зум схем по клику в читалке.
- Привязывать иллюстрации к соответствующей странице/главе через Markdown-теги:
8. 🔌 Пул соединений HTTP (httpx.AsyncClient с Keep-Alive) (Completed)
- В
app/dictionary.pyсоздать синглтон-клиентget_http_client()с пулом соединений:limits = httpx.Limits(max_keepalive_connections=10, max_connections=20, keepalive_expiry=60.0) - Заменить вызовы
async with httpx.AsyncClient()в парсерах на переиспользуемый клиент. - Устранить 5 повторных TCP/TLS хэндшейков на каждое слово, сократив задержку внешних запросов на 300–600 мс.
- Добавить вызов
close_http_client()вlifespanFastAPI при остановке приложения для чистого закрытия открытых сокетов. - Добавить юнит-тесты
test_http_connection_poolingвtests/test_api.py(22/22 passed).
9. 🗄️ Тюнинг SQLite PRAGMA и составных индексов
- В
app/database.py:- Вынесен
PRAGMA journal_mode=WAL;в однократную инициализациюinit_db()и миграции (устранены повторные блокировки и запись заголовка файла на каждый HTTP-запрос). - Включены высокопроизводительные параметры памяти Linux для каждого соединения:
conn.execute("PRAGMA synchronous = NORMAL;") conn.execute("PRAGMA mmap_size = 268435456;") # 256MB memory-mapped I/O conn.execute("PRAGMA cache_size = -32000;") # 32MB RAM page cache conn.execute("PRAGMA temp_store = MEMORY;") # временные таблицы и сортировки в ОЗУ conn.execute("PRAGMA foreign_keys = ON;")
- Вынесен
- Zero-copy чтение страниц: включён
mmap_size = 256MB, позволяющий ядру Linux отдавать страницы SQLite напрямую из системного дискового кэша без лишних системных вызововread()и копирования в буферы пользовательского пространства. - Составные индексы (Composite Indexes) для ускорения частых выборок:
vocabulary_cards:idx_vocab_user_created ON (user_id, created_at DESC)— мгновенная пагинация списка слов без сортировки в памяти.idx_vocab_user_srs_state ON (user_id, srs_state, srs_next_review)— выборка очереди интервальных повторений SRS (/api/srs/queue).idx_vocab_user_srs_created ON (user_id, srs_state, created_at DESC)— выборка новых слов для интервального повторения.idx_vocab_collection ON (user_id, collection)— мгновенная фильтрация по коллекциям.idx_vocab_user_term_nocase ON (user_id, term COLLATE NOCASE)— предотвращение дубликатов заO(\log N).
srs_logs:idx_srs_card ON (card_id)— устранение full table scan при каскадном удалении карточек (ON DELETE CASCADE).idx_srs_reviewed ON (user_id, reviewed_at)— выборка журнала повторений и расчёт тепловой карты активности.
books:idx_books_user_updated ON (user_id, updated_at DESC)— сортировка списка книг библиотеки по дате чтения.
sessions:idx_sessions_user ON (user_id)— ускорение валидации сессий и каскадной очистки.
- Добавлен регрессионный тест
test_sqlite_pragma_tuning_and_composite_indexesвtests/test_api.py(23/23 тестов успешно).
10. ✂️ Де-блоатинг внешних парсеров (YAGNI)
- Удалён сетевой опрос Datamuse (
fetch_datamuse):- Устранена зависимость от
api.datamuse.com, которая дублировала определения и перегружала выдачу зашифрованными метками тегов и рифмами. - Сокращено число исходящих HTTP-запросов на каждый поиск слова на 20% (с 5 до 4 параллельных вызовов).
- Устранена зависимость от
- Переход на современный REST API Wiktionary:
fetch_wiktionary_wikitextпереведён на легковесный эндпоинтhttps://en.wiktionary.org/w/rest.php/v1/page/{word}(скорость ответа 0.3с вместо 0.5с у legacyaction=parse).- Добавлена строгая изоляция англоязычной секции
==English==, исключившая утечку переводов и IPA из других языков (например, французское слово chat больше не заносит «кот» в английский словарь). - Реализован автоматический fallback с сохранением регистра (для слов с заглавной буквы в начале предложений).
- Нормализация определений и примеров:
fetch_wiktionary_definitionsдополнен декодированием HTML-сущностей (html.unescape) и нормализацией пробельных символов.
- Добавлен регрессионный тест
test_debloat_dictionary_and_wiktionary_rest_parserвtests/test_api.py(24/24 тестов успешно).
11. 📚 Локальный оффлайн-словарь (99%+ покрытия со словоформами, SQLite 10–20 МБ) (Completed)
- Создана в SQLite таблица:
CREATE TABLE IF NOT EXISTS offline_dictionary ( term TEXT PRIMARY KEY COLLATE NOCASE, translation TEXT NOT NULL, phonetic TEXT DEFAULT '', pos TEXT DEFAULT '' ); CREATE INDEX IF NOT EXISTS idx_offline_dict_term ON offline_dictionary(term COLLATE NOCASE); - Высококачественная база на 141 772 словарных статьи (
data/offline_dict.tsv.gz, сжатый размер всего 2.48 МБ):- Построена генератором
scripts/build_offline_dict.py. - Интегрированы FreeDict TEI XML (54k+ базовых лемм с IPA и частями речи) и очищенный русско-английский Wiktionary DSL (55k+ лемм).
- Включены все формы неправильных глаголов (16k+ форм: 3rd person singular, past, past participle, present participle).
- Включены множественные числа существительных (18k+ форм: regular & irregular plurals, например men, women, hypotheses, criteria).
- Включены регулярные инфлексии глаголов (50k+ форм: -ed, -ing, -s).
- Добавлен словарь IT и сетевой терминологии Cisco/O'Reilly (packet, switch, router, throughput, bandwidth, latency, subnet, vlan).
- Построена генератором
- Архитектура Zero Daemon:
- Нативный SQLite с
PRAGMA mmap_size = 256MBиPRAGMA cache_size = -32000(32MB RAM page cache). - Никаких внешних сервисов (Redis/Postgres) — чтение за 0.015–0.030 мс прямо из оперативной памяти ядра Linux.
- Автоматический сидинг базы при инициализации (
_seed_offline_dictionary()вapp/database.py) пачками по 10 000 строк занимает < 0.7 секунды.
- Нативный SQLite с
- Иерархическая логика словарного поиска в
app/dictionary.py:dictionary_cache\rightarrowмгновенный возврат при повторном запросе.offline_dictionary\rightarrowмгновенный ответ за 0.02 мс с источникомsource: "offline".- Только при отсутствии слова в базе (или для длинных предложений > 4 слов)
\rightarrowfallback-запрос во внешнюю сеть (Wiktionary REST / MyMemory).
- Исключено исчерпание квот MyMemory (100 запросов/день) — 99%+ запросов обслуживаются локально.
- Добавлен регрессионный юнит-тест
test_offline_dictionary_lookup_and_coverageвtests/test_api.py(25/25 тестов успешно, 100% green).
12. 🧩 Модульность фронтенда на нативных ES-модулях (без Webpack/Vite) (Completed)
- Перевести
app/static/js/app.jsна нативный браузерный синтаксис<script type="module">. - Выделить модули с нативным
import/export:modules/api.js— централизованный клиент сетевых вызовов с авто-интерцептором токена.modules/ui.js— тосты, модальные окна, темы оформления, утилиты экранирования и шафла.modules/dictionary.js— поиск, карточки, коллекции, теги, пакетные операции, модалки редактирования и экспорта.modules/srs.js— алгоритм SM-2, 5 режимов тренировки (флэшкарты, квиз, тайпинг, клоуз, диктант), статистика KPI и гитхаб-хитмап.modules/reader.js— книжная полка, читалка, блок-парсер, виртуализация глав, интерактивный попап слова, настройки Aa.app.js— главный оркестратор, роутер хэшей#dictionary,#srs,#reader/book/:id, префлайт вида без мерцания, мобильный таббар.
- Сохранить полное отсутствие внешних сборщиков (0 npm-пакетов, чистая платформа, нативные ES6 модули браузера).
- Обновлен Service Worker (
sw.js) с прекэшированием всех модулей и версией кэшаnotes-v5.0.
13. 🌐 Контекстный перевод предложений в читалке (In-Context Sentence Translator) (Completed)
- Кнопка
🌐 Перевести предложениев попапе слова читалки (рядом с контекстной цитатой). - Интеллектуальный перевод всей фразы целиком с сохранением смысла книги через локальный ИИ (устраняет ловушку оторванных значений слов вроде draft, address, run).
- Разбор и точное значение целевого слова именно в данном контексте (
word_meaning). - Мгновенный кэш переводов предложений в SQLite (
sentence_translations) с SHA-256 хешированием за 0.01 мс. - Возможность сохранить правильный контекстный перевод прямо в карточку словаря («Вставить в карточку»).
- Развёрнут локальный контейнер Ollama с моделями Qwen 2.5 (
qwen2.5:1.5bиqwen2.5:3b) с автоматической выгрузкой из памяти при простое (OLLAMA_KEEP_ALIVE=5m) и 100% автономностью без внешних API.
14. 🔗 Детектор фразовых глаголов и идиом в читалке (Multi-Word / Phrasal Verb Detector) (Completed)
- База частых английских фразовых глаголов и коллокаций (A2–B2: take off, run out of, look forward to, figure out, set up, carry out, turn off, put up with и др.).
- При клике на слово в читалке — автоматический анализ контекстного окна (1–3 слова до и после + разделяемые фразовые глаголы turn it off).
- При обнаружении устойчивой связки — карточка связки прямо в окне перевода слова (took off
\rightarrow«взлетать, снимать», а не «взял»). - Поддержка переключения между одиночным словом и фразовым глаголом в 1 клик.
- Сохранение готовой устойчивой связки в личный словарь в один клик (в отдельную коллекцию «Фразовые глаголы & Идиомы» с тегом
#phrasal-verbs).
15. 🎯 Уровневые тесты CEFR (A1, A2, B1, B2) с авто-добавлением ошибок в активный словарь (Completed)
- Эталонная база вопросов Oxford 3000/5000 (160 отобранных тестовых единиц: по 40 на каждый уровень A1, A2, B1, B2) в модуле
app/cefr.py. - Быстрый и удобный мобильный формат: 1-тап выбор ключевого узла (Cloze Tap):
- Естественные контекстные предложения с пропуском
___. - Подсказка значения слова на русском языке и часть речи.
- 4 сбалансированных варианта ответа одинаковой части речи и уровня сложности (исключены грамматические подсказки).
- Мгновенная тактильная реакция: зеленая/красная подсветка, автоподстановка правильного слова в пропуск, раскрытие транскрипции IPA и пояснения.
- Естественные контекстные предложения с пропуском
- Автоматический двухсторонний захват пробелов (Dual Gap Ingestion):
- При ошибке
\rightarrowавтоматически в словарь SRS со статусом «В процессе» (learning) добавляются ОБА слова:- Истинное целевое слово (правильный ответ).
- Выбранный дистрактор (слово, на которое кликнул пользователь, с его переводом и транскрипцией).
- Срочный срок повторения (
srs_next_review = now), коллекцияУровни CEFR ({level})и теги#level-{level},#cefr-test,#test-mistake.
- При ошибке
- Интерактивный разбор всех вариантов (Options Breakdown & 1-Tap Add):
- Карточки всех 4 вариантов ответа с переводом из оффлайн-словаря и частью речи.
- Автоматическая маркировка добавленных слов (
✓ В словаре (SRS)/✓ В библиотеке). - Быстрая кнопка
+ В словарьдля любых оставшихся незнакомых вариантов вопроса в 1 тап.
- Расширенная база вопросов (Oxford 3000/5000):
- Банк расширен со 160 до 260 эталонных вопросов (по 65 вопросов на каждый уровень A1, A2, B1, B2).
- Наглядный прогресс-трекер:
- Экран обзора со шкалами освоения каждого уровня (A1 Beginner, A2 Elementary, B1 Intermediate, B2 Upper-Intermediate).
- Счётчики: процент закрытия уровня, освоено, ошибок, слов в тренировке SRS.
- Режим «Работа над ошибками» (быстрый прогон только ошибочных вопросов).
- Возможность сброса прогресса уровня.
- Добавлен регрессионный тест
test_cefr_testing_and_gap_ingestionвtests/test_api.py(29/29 тестов успешно, 100% green).
16. 📖 Оффлайн-модуль грамматики Мерфи и бумажная тетрадь (Murphy Engine & Handwritten Journaling)
- Индексация юнитов Essential Grammar in Use (A1–A2) и English Grammar in Use (B1–B2) в SQLite (
grammar_units). - Поддержка «Вечернего вайба глубокого погружения» (Deep Work Mode): 5–7 минутные микро-уроки.
- Компактная выжимка правил на контрастах жизненных ситуаций (I do vs I am doing, I did vs I have done и т.д.).
- 5 интерактивных упражнений с удобным 1-тап выбором на телефоне и мгновенным разбором логики ошибок.
- Интервальное повторение грамматики в SRS: ошибки из упражнений Мерфи автоматически улетают в карточки утреннего повторения SRS (
srs_state = 'learning', тегиgrammar,murphy-unit-{N})! - Блок работы с бумажной тетрадью (мышечная и зрительная память):
- Золотая формула правила для записи цветной ручкой/маркером.
- Обязательное составление 2–3 личных примеров от руки из своей реальной жизни.
- Интерактивный чекбокс:
[✓] Записал от руки в тетрадьс мгновенной синхронизацией в SQLite.
16.2. ⚡ Фоновые задачи и генерация тестов CEFR из загруженных книг (Background Tasks & Book Mining)
- Zero-Daemon менеджер фоновых задач (
app/tasks.py):- Таблица SQLite
background_tasks(id, user_id, task_type, status, progress_current, progress_total, message, params_json, result_json, error_message). - Асинхронное исполнение через чистый
asyncio.create_taskбез Celery, Redis и внешних брокеров (100% Ponytail). - Кооперативная отмена задач (
cancel_task,is_task_cancelled). - Эндпоинты API:
POST /api/tasks/mine-books,GET /api/tasks/active,GET /api/tasks/{task_id},POST /api/tasks/{task_id}/cancel.
- Таблица SQLite
- Движок анализа и майнинга предложений из книг (
app/miner.py):- Разбиение текста глав на чистые предложения с защитой английских инициалов и сокращений (
Mr.,Mrs.,Dr.,Prof.,St.,Jr.). - Сопоставление с лексической шкалой Oxford 3000/5000 (A1..B2) и базой частей речи.
- Подбор грамматически и лексически корректных дистракторов того же уровня CEFR и части речи.
- Формирование 4-вариантных заданий Cloze Tap со скрытием ключевого слова
___. - Защита от дубликатов предложений через
UNIQUE(level, sentence)в SQLite. - Автоматическая очистка русскоязычного глоссария (
clean_translation) от паразитных латинских транслитов Викисловаря.
- Разбиение текста глав на чистые предложения с защитой английских инициалов и сокращений (
- Интерфейс в веб-приложении (PWA):
- Кнопка
⚡ Собрать тесты из книгв шапке тестов CEFR. - Модальное окно с выбором книги (или всей библиотеки), целевого уровня (A1..B2 / ALL) и количества вопросов.
- Интерактивный фоновый баннер со спиннером, живым счетчиком прогресса
X / Y (%)и кнопкой отмены задачи. - Бейджик источника
📖 «Название книги» (Глава)в карточке вопроса и в разборе ответа.
- Кнопка
- Автоматический тест
test_background_tasks_and_book_miningвtests/test_api.py(30/30 тестов успешно пройдены).
🐛 Устранённые дефекты и хотфиксы (Bug Tracker & Hotfixes)
- Баг читалки: Преждевременный обрыв контекстного предложения на точках сокращений (
Mr.,Mrs.,Dr.,Prof.,St.,etc.,e.g.,i.e.,1.5):- Симптом: При клике на слово в предложении с обращением или сокращением (например, «Mr. and Mrs. Dursley were proud...») кнопка перевода предложения («🌐 Перевести предложение») отправляла на перевод лишь обрезок до или после точки («Mr.», «and Mrs.» или «Dursley were proud...»). Если перед словом была точка в обращении, текст дальше не переводился.
- Причина: В функции
extractContextSentence(fullText, word)вapp/static/js/modules/reader.jsиспользовалось наивное регулярное выражение[^.!?\n]*, считавшее абсолютно любую точку концом предложения. - Решение: Реализована безопасная защита списка английских титулов и сокращений (
READER_HONORIFICS) и дробных чисел перед сегментацией. Предложения корректно делятся по терминальным знакам препинания с закрывающими кавычками/скобками ([.!?]['"”’»)]*), гарантируя передачу полного, связного контекста в переводчик и словарь.
17. 🍔 Разгрузка хеддера и единая навигация через боковое меню / Drawer (Unified Navigation & Header Redesign) (Completed)
- Проблема перегруженного хеддера полностью решена:
- Ликвидировано нагромождение из 8+ кнопок в шапке, устранён визуальный шум и горизонтальный сдвиг на планшетах и компактных экранах.
- Устранена разрозненность UX: на десктопе, планшете и смартфоне теперь действует единая система навигации.
- Единый лаконичный Header (Desktop, Tablet, Mobile):
- Слева: Кнопка вызова бокового меню (Бургер
☰/ph-list), кликабельный логотип📖 Notes(возврат в словарь). - Центр: Фокусная кнопка быстрого доступа к главному ежедневному действию (
🎓 Тренажёр SRSс живым счётчиком повторенийsrs-badge) и компактные счетчики базы (Всего: X,Сегодня: +Y). На смартфонах счетчики автоматически скрываются, а кнопка сжимается до компактного бейджа🎓 (N). - Справа: Переключатель темы
🌓, компактная плашка пользователя/аватар👤 user(на смартфонах отображается только иконка аватара).
- Слева: Кнопка вызова бокового меню (Бургер
- Единый выдвижной Drawer (Боковое меню навигации):
- Плавная аппаратная анимация (
transform: translateX,backdrop-filter: blur(4px)). - Карточка профиля с аватаром, именем пользователя и описанием.
- Интерактивный мини-дашборд статистики (Всего в базе, Сегодня, На повторение).
- Логическая группировка пунктов с красивыми иконками:
- Обучение & Чтение: Словарь & Поиск, Тренажёр SRS (с живым бейджем), Читалка & Книги, Тесты CEFR (A1–B2), Грамматика Мерфи & Тетрадь.
- Аналитика: Календарь активности & Статистика (Heatmap).
- Настройки & Профиль: Экспорт словаря, Сменить пароль, Переключение темы, Выход из аккаунта.
- Закрытие по клику вне области (оверлей), кнопке
✕, клавише Esc и свайпу влево на тач-устройствах (Swipe to dismiss). - Блокировка скролла фона (
overflow: hiddenнаbody) при открытом Drawer. - Подсветка активного раздела (
.active), синхронизированная с URL-хэшем и переходами между экранами.
- Плавная аппаратная анимация (
- Оптимизация мобильного режима:
- На нижней панели (Bottom Tab Bar) оставлены 4 ключевых быстрых действия:
📖 Словарь,🎓 Тренажёр,📚 Читалка,☰ Меню. - Тап по
☰ Менюна мобильном открывает единый Drawer, полностью заменив устаревший отдельный модальный слойmobile-menu-modalбез дублирования верстки и стилей.
- На нижней панели (Bottom Tab Bar) оставлены 4 ключевых быстрых действия:
18. 🎧 Автономная нейро-озвучка Piper TTS и аудирование
- Локальный движок Piper TTS:
- Автономный VITS-инференс, 100% оффлайн, ~120 МБ RAM, сверхбыстрый отклик на AMD Ryzen 9 5950X (RTF ~0.11).
- Качественные модели дикторов:
- Английский:
en_US-lessac(чёткий нативный американский диктор). - Русский:
ru_RU-dmitri(естественный русский голос).
- Английский:
- Проактивное фоновое пред-кэширование (Zero Latency):
- При сохранении карточки в словарь (
POST /api/cards) бэкенд в фоне синтезирует слово и всё предложение-контекст. - В читалке при переводе предложения (
POST /api/translate-sentence) аудио фразы пред-кэшируется в фоне.
- При сохранении карточки в словарь (
- Интеграция в интерфейс:
- Карточки SRS (лицевая сторона 🔊, обратная сторона 🔊, и отдельная кнопка озвучки контекста 🔊).
- Викторина SRS (кнопка 🔊 озвучки слова).
- Читалка (кнопка 🔊 у слова в попапе, 🔊 у всего предложения, и 🔊 RU для русского перевода).
- Словарь (кнопка 🔊 в результатах поиска).
- Второй этап: интерактивный тренажёр аудирования (Listening & Q&A) с ситуационными сценариями, вопросами диктора, проверкой понимания на слух и билингвальными транскриптами.
- Мульти-голосовой переключатель: 6 моделей Piper TTS (3 EN: Paula, Ryan, Alan; 3 RU: Irina, Denis, Dmitri) с калибровкой темпа и глубоких пауз на тире/знаках препинания.
19. 🚀 Конструктор комплексного урока & Сессионный раннер (Beta) (Completed)
- Гибкий конфигуратор структуры урока:
- Настройка порядка блоков (стрелки ▲/▼), включение/выключение этапов (Toggle-свитчеры), регулировка объёма (5/10/15/20 слов, 3/5/10 упражнений, 1/2/3 аудио-ситуации).
- Готовые встроенные шаблоны в 1 клик:
- ⚡ «Утренний экспресс (10 мин)» (слова + ретро-тест + 1 ситуация на слух).
- 🎯 «Сбалансированный урок (20 мин)» (слова + закрепление + новая теория Мерфи + 2 ситуации).
- 📖 «Глубокое погружение (30 мин)» (полный стек: слова, грамматика, аудирование и чтение статьи).
- 🎧 «Аудио + Чтение (15 мин)» (понимание на слух и работа с текстом).
- Возможность сохранить любой собственный план в базу SQLite под своим именем.
- Бесшовный сессионный раннер урока:
- Единый режим урока с пошаговым хлебным прогресс-баром (
[1] Слова ➔ [2] Закрепление ➔ [3] Новая тема ➔ [4] Аудио ➔ [5] Чтение ➔ [6] ИИ-Итог). - Таймер сессии, мгновенный автопереход между блоками без кликов по меню.
- Оффлайн-база познавательных микро-статей (Наука, IT, Природа, Космос, История) с кликабельным переводом слов и кнопкой «+ В словарь».
- Умный адаптивный выбор темы грамматики для повторения: «Самая слабая тема (по ошибкам)», «Предыдущая тема» или выбор любого юнита вручную.
- Единый режим урока с пошаговым хлебным прогресс-баром (
- Сквозная телеметрия ошибок & ИИ-дебрифинг (Qwen 2.5 3B):
- Фиксация ошибок на каждом этапе: забытые слова, нарушенные правила Мерфи, пропущенные детали аудирования.
- Обогащение историческим контекстом: сопоставление с прошлыми ошибками в
srs_logsиgrammar_progress. - Итоговый педагогический разбор от Qwen 2.5 3B: итоговая оценка сессии (A+, A, B, C), разбор паттернов ошибок с формулами Мерфи, сильные стороны и персональный фокус на завтра.
- Мгновенный детерминированный fallback: если Ollama занята или выключена, урок завершается моментальным структурированным математическим отчётом без зависаний.
- Интеграция в интерфейс & тесты:
- Отдельный пункт в боковом меню
🚀 Комплексный урок (Beta)и хэш-маршрут#lesson. - Модальное окно истории комплексных уроков с сохранением результатов сессий в
lesson_sessions. - 44/44 проходящих автоматизированных теста в
tests/test_api.py.
- Отдельный пункт в боковом меню
20. 🏗️ Комплексный технический рефакторинг и оптимизация архитектуры (Completed)
- Этап 1: Очистка мертвого кода и оптимизация SQL:
- Удалена старая незавершенная функция
parse_textвapp/reader.py(строки 290–326). - Функция
update_task_progressвapp/tasks.pyпереписана с цикла на единый параметризованный SQL-запросUPDATE tasks SET progress = ?, current_item = ?, ....
- Удалена старая незавершенная функция
- Этап 2: Вынос датасетов в JSON (
data/seeds/*.json):- Из исходников извлечено более 3 100 строк статических данных:
cefr_questions.json(260 вопросов),grammar_units.json(15 юнитов),phrasal_verbs.json(157 глаголов),reading_articles.json(8 статей). - Модули
app/cefr.py,app/grammar.py,app/phrasal.py,app/lessons.pyпереведены на динамическую ленивую загрузку с сохранением полной обратной совместимости.
- Из исходников извлечено более 3 100 строк статических данных:
- Этап 3: Оптимизация сети и локального ИИ:
- Внедрен постоянный пул соединений
httpx.AsyncClientс Keep-Alive (120s) для локальной Ollama вapp/ai.py, управляемый в жизненном цикле приложения (lifespan). - Интегрирована встроенная офлайн-лемматизация (
lemmatize_word) вlookup_term(app/dictionary.py), предотвращающая лишние сетевые запросы при поиске словоформ (starts->start,studying->study).
- Внедрен постоянный пул соединений
- Этап 4: Модуляризация бэкенда FastAPI:
- Монолитный
app/main.pyсокращен с 2 240 до 142 строк. - Создан пакет
app/routers/с 11 тематическими APIRouter:auth.py,cards.py,dictionary.py,srs.py,export.py,reader.py,cefr.py,grammar.py,tasks.py,lessons.py,listening.py.
- Монолитный
- Этап 5: Модуляризация CSS и Service Worker:
- Монолитный
style.css(8 746 строк) разделен на 7 предметных таблиц вapp/static/css/:base.css,components.css,dictionary.css,srs.css,reader.css,grammar_cefr.css,lesson.css. - Мастер-файл
style.cssзагружает стили через@importи содержит полную архитектурную карту. - Обновлен Service Worker (
notes-v6.7) с добавлением всех CSS вPRECACHE_URLSдля полной офлайн-работы PWA.
- Монолитный
- Инфраструктура быстрого переключения и отката:
- Добавлены скрипты
scripts/deploy_beta.shиscripts/rollback_to_main.shдля мгновенного отката или развертывания в 1 клик. - Создан резервный бэкап базы данных
data/notes.db.backup-main-pre-beta.
- Добавлены скрипты
- 100% успешное тестирование:
- Все 44 интеграционных теста
pytest tests/test_api.pyуспешно проходят в Docker-контейнере.
- Все 44 интеграционных теста
🐛 Зафиксированные баги (Ждут команды на исправление)
- BUG-01: Не открывается окно редактирования слова в словаре на главной:
- Симптом: при клике на иконку ✏️ у карточки слова в списке словаря ничего не происходит.
- Диагностика: в
app/static/js/modules/dictionary.jsфункцияopenEditModalищет элемент по id'edit-card-modal'(document.getElementById('edit-card-modal')), в то время как вapp/static/index.htmlмодальное окно объявлено с id'edit-modal'(<div id="edit-modal" class="modal-backdrop hidden">). Из-за несовпадения ID селектор возвращаетnull, и вызовopenModal(null)тихо игнорируется. - Статус: зафиксировано, ожидает команды на исправление.
- BUG-02: Отсутствует возможность прослушать слово и предложение из словаря:
- Симптом: в списке карточек словаря на главной странице нет кнопок 🔊 для воспроизведения аудио слова и контекстного предложения.
- Диагностика: в шаблоне рендеринга
renderCardsList(app/static/js/modules/dictionary.js) внутри.card-topи.card-contextне отрисовываются кнопки аудиовызова с вызовомplayAudio()/playTextSpeech(), хотя модульui.jsполностью поддерживает их воспроизведение. - Статус: зафиксировано, ожидает команды на исправление.
- BUG-03: Спойлер корня слова в переводе грамматических форм в тестах (например,
(прош. вр. от explain)):- Симптом: при добавлении словоформ в словарь (например,
explained) в переводе сохраняются пометки словообразования:объяснять, объяснить (прош. вр. от explain). Во время теста (SRS / Урок) отображение этого перевода напрямую спойлерит английское словоexplain. - Диагностика: в
app/dictionary.pyфункцияclean_russian_translation(строки 235–277) намеренно защищает грамматические пометки вида(прош. вр. от ...), и они попадают в полеcard.translation. Во время тестирования вsrs.jsиlesson.jsэта строка выводится в вопросе теста целиком без фильтрации. - Варианты решения: по умолчанию скрывать пометку под интерактивный кликабельный спойлер
[+ грамматика]или вырезать английский корень из вопроса теста через regex/\s*\([^)]*от\s+[a-zA-Z\x27-]+\)/gi. - Статус: зафиксировано, ожидает команды на исправление.
- Симптом: при добавлении словоформ в словарь (например,
- BUG-04: В квизе «4 варианта» правильный ответ всегда находится на 1-м месте:
- Симптом: в комплексном уроке и SRS при выборе режима «4 варианта» правильный ответ всегда гарантированно оказывается первым вариантом.
- Диагностика: в
app/static/js/modules/ui.js(строка 28) функцияshuffleArray(array)возвращает новый скопированный массив (return arr;), не мутируя оригинал на месте. Вapp/static/js/modules/lesson.js(строка 778) иapp/static/js/modules/srs.js(строка 461) написаноshuffleArray(options);, но результат возврата игнорируется (optionsне перезаписывается), из-за чего правильный ответ, добавленный первым в[correctText, ...], всегда остаётся на позиции 0. - Варианты решения: переписать вызовы на
options = shuffleArray(options);(или сделатьshuffleArrayмутирующим). - Статус: зафиксировано, ожидает команды на исправление.
- BUG-05: Поломка верстки и отображение сырых HTML-тегов/JSON при импорте статей Википедии (например, Linux):
- Симптом: при открытии импортированной из Википедии статьи «Linux» в читалке в 1-й главе («Overview») отображается фрагмент сырого JSON (
"},"title":{"wt":"Linux"}...), а в главе «Pronunciation» — искажённый тег<tdTimes New Roman...и сырые теги цитат{{ cite newsgroup.... - Диагностика:
- В
app/reader.py(clean_wiki_html): MediaWiki Parsoid HTML вставляет метаданные шаблонов в атрибутdata-mw='{"parts":...}'(например, у<span class="mw-empty-elt">и<table class="infobox">). Внутри значения этого атрибута содержатся незаэкранированные угловые скобки (например,<ref name="...">). Регулярное выражение удаления HTML-теговre.sub(r'<[^>]+>', ' ', s)встречает первый же символ>внутри кавычек атрибута, преждевременно обрывает удаление тега, и остаток JSON-строки вываливается в текст статьи. - В
clean_data_tableregex удаления стилейstyle=["'][^"']*["']спотыкается о вложенные одинарные кавычки вstyle="font-family:'Times New Roman'...", оставляя сломанный HTML<tdTimes New Roman.... - В
app/static/js/modules/reader.jsповреждённые теги не распознаются парсером таблиц и выводятся как обычный экранированный текст.
- В
- Варианты решения: предварительно полностью вырезать атрибуты
data-mwиaboutрегулярным выражением или через санитизацию до удаления тегов, улучшить regex очистки стилей таблиц и перезагрузить повреждённые статьи. - Статус: зафиксировано, ожидает команды на исправление.
- Симптом: при открытии импортированной из Википедии статьи «Linux» в читалке в 1-й главе («Overview») отображается фрагмент сырого JSON (
- BUG-06: Не работает поиск и обратный перевод с русского на английский в словаре:
- Симптом: при попытке ввести в поле перевода словаря русское слово (например, «собака» или «яблоко») перевод не находится, возвращается пустой результат или ошибка.
- Диагностика:
- В
app/dictionary.pyфункцияlookup_termжестко закодирована только под направление «English -> Russian»:- В локальной БД поиск ведется только по полю английского слова
WHERE term = ? COLLATE NOCASE(русские переводы хранятся в полеtranslationи по ним поиск не производится). - Во внешнем сервисе
fetch_mymemoryжестко зашит параметрlangpair="en|ru", из-за чего сервис пытается переводить русское слово как английское и возвращает ошибку или пустую строку. - Запросы к Wiktionary и FreeDictionaryAPI идут в англоязычные эндпоинты (
en.wiktionary.org,api.dictionaryapi.dev), где нет русских словарных статей.
- В локальной БД поиск ведется только по полю английского слова
- В интерфейсе
app/static/js/modules/dictionary.jsрезультат выводится в поле карточки без учёта обратного направления перевода (когда найденный английский эквивалент должен статьterm, а введенное русское слово —translation).
- В
- Варианты решения: автоматически определять язык ввода по наличию кириллицы
[\u0400-\u04FF]. При кириллице: переключатьlangpairMyMemory на"ru|en", выполнять обратный поиск вoffline_dictionaryпоtranslation, и корректно заполнять форму добавления карточки (найденное английское слово вterm, русский запрос вtranslation). - Статус: зафиксировано, ожидает команды на исправление.
- BUG-07: Ошибка загрузки этапа аудирования:
undefined is not an object (evaluating 'scenario.topic'):- Симптом: при переходе к шагу аудирования в комплексном уроке возникает ошибка:
Ошибка загрузки этапа: undefined is not an object (evaluating 'scenario.topic'), шаг невозможно пройти. - Диагностика: в
app/static/js/modules/lesson.js(строка 1658) после вызоваapi.listening.getExercise()клиент ожидает полеdata.scenario(const scenario = data.scenario;), в то время как эндпоинтapp/routers/listening.py(строка 47) возвращает объект упражнения напрямую (safe_ex). Из-за этогоscenarioравенundefined, и чтениеscenario.topicвыбрасывает исключениеTypeError. - Варианты решения: использовать
const scenario = data.scenario || data;с опциональной цепочкой (scenario?.topic). - Статус: зафиксировано, ожидает команды на исправление.
- Симптом: при переходе к шагу аудирования в комплексном уроке возникает ошибка:
- BUG-08: Бесконечный спиннер («Анализ ИИ длится бесконечно») на этапе дебрифинга урока:
- Симптом: после прохождения всех этапов урока экран «🤖 Локальный ИИ Qwen 2.5 формирует ваш персональный разбор...» висит бесконечно долго без отображения результата.
- Диагностика:
- Холодный запуск Ollama для модели Qwen 2.5 3B (после разгрузки памяти) занимает ~18.5 секунд только на загрузку весов в RAM. Генерация 450 токенов JSON на CPU суммарно требует 45-60 секунд.
- В
app/ai.py(строка 579) таймаут httpx к Ollama выставлен в 25 секунд (timeout=25.0), из-за чего запрос рвется, а во фронтенде вapi.lessons.submitDebriefнет клиентского таймаута с аварийным выходом. - Короткий TTL (
keep_alive: 5m) приводит к тому, что к моменту окончания 10–15 минутного урока модель гарантированно выгружается из памяти, вызывая холодный старт прямо на финальном шаге.
- Варианты решения:
- Увеличить TTL процесса нейросети с
5mдо1h(OLLAMA_KEEP_ALIVE=1hвdocker-compose.yml,config.pyиai.py) — во время активной учебной сессии модель всегда «горячая» в памяти и отвечает за доли секунды, а при простое > 1 часа память автоматически освобождается. - Добавить жесткий клиентский таймаут (8-10 сек) на фронтенде с мгновенным отображением сверхбыстрого детерминированного отчета (
generate_deterministic_debrief, работающего за 1 мс). - Рассмотреть использование легкой модели
qwen2.5:1.5bдля ультрабыстрого ответа.
- Увеличить TTL процесса нейросети с
- Статус: зафиксировано, ожидает команды на исправление.
⏳ Очередь новых функций (Feature Backlog)
- FEAT-01: 🧘 Фокус-режим в читалке (Focus Mode / Zen Reader — 100% vh & 100% vw):
- Концепция: чистый дзен-режим чтения на весь экран без отвлекающих панелей с сохранением 100% интерактивного перевода.
- Интерфейс и верстка:
- Скрытие шапки сайта (
navbar), тулбара читалки, мобильной панели вкладок (bottom tab bar) и рамок. - Текстовый контейнер расширяется на
100vwи100vh(с учётомenv(safe-area-inset-*)). - Сохраняются все пользовательские настройки типографики (
Aa): размер шрифта, гарнитура (Sans/Serif/Mono), ширина колонки и темы оформления (Dark, Sepia, Light, OLED).
- Скрытие шапки сайта (
- Интерфейс перевода (Zero Loss):
- Клик / тап по любому слову по-прежнему открывает всплывающее окно перевода (десктопный попап или мобильный Bottom Sheet).
- Доступны контекстный ИИ-перевод предложений, словарные статьи и быстрое добавление
+ В словарь.
- Управление и HUD:
- Иконка активации
🧘в тулбаре читалки и поддержка горячей клавишиF. - Ненавязчивый полупрозрачный плавающий оверлей в углу с индикатором прогресса чтения и кнопкой выхода
✕. - Выход по нажатию клавиши
Escape, клику на✕или свайпу/тапу по верхнему краю экрана. - Поддержка нативного Fullscreen API (
document.documentElement.requestFullscreen()) для браузеров на десктопе и Android.
- Иконка активации
- FEAT-02: 📝 Подробные конспекты для тетради и шпаргалки с таблицами (Murphy Detailed Notes & Markdown Tables):
- Полноценные Markdown-таблицы: отображение наглядных сравнительных таблиц в теории грамматики и подсказках (спряжения глаголов, формы неправильных глаголов, маркеры времени, предлоги места/времени).
- Глубокая структурированная теория без воды: развернутые объяснения правил по методике Raymond Murphy с живыми примерами и контрастными парами (вместо сжатых 1-2 предложений), готовые для записи в рабочую тетрадь.
- FEAT-03: 🤖 Интеграция с Google NotebookLM для генерации инфографики и карточек (Низкий приоритет):
- Использование возможностей Google NotebookLM или мультимодальных моделей для автоматической генерации наглядной инфографики и подробных обучающих карточек, «разжевывающих» грамматические нюансы и идиомы.
- FEAT-04: 🎯 Адаптивный объем тренировки (доведение до автоматизма) и умные рекомендации:
- Настраиваемый объем заданий в блоках урока: выбор между 5, 10, 15, 20 заданиями или режим «тренировка до 90% точности / безошибочной серии».
- Персональные рекомендации при низком балле (< 75-80%): алгоритм анализирует ошибки и автоматически предлагает, какие конкретно статьи в читалке изучить и какие юниты грамматики Мерфи повторить.
- FEAT-05: ✍️ Режим активного составления предложений (Sentence Builder / Production Mode):
- Тренировка активного словарного запаса: студенту предлагается слово из личного словаря (например, «установленный» / «installed»), на которое нужно составить и записать предложение на английском.
- Грамматические модификаторы сложности: задание условий по времени и конструкции (например: «составь предложение в Past Simple», «используй Future Continuous», «составь вопрос с предлогом»).
- Проверка через локальную языковую модель с мгновенным разбором правильности, стиля и грамматических ошибок.
- 🌐 Быстрый захват из браузера (Bookmarklet):
- Создать JavaScript-букмарклет для добавления слова/фразы из любого окна браузера в личный словарь
study.qpid.pro(низший приоритет).
- Создать JavaScript-букмарклет для добавления слова/фразы из любого окна браузера в личный словарь
- Нативная автономная озвучка (HTML5 Web Speech API /
speechSynthesis):- Использовать встроенный в браузер синтезатор речи
window.speechSynthesis(en-US, en-GB) как дополнительный резервный фолбэк при работе на мобильных без связи.
- Использовать встроенный в браузер синтезатор речи
- Расширение библиотеки Murphy:
- Добавление следующих 15 юнитов грамматики (юниты 16–30: пассивный залог, косвенная речь, модальные глаголы).
🛠️ Правила и соглашения проекта (Ponytail Rules)
- Stdlib & Native First: стандартная библиотека языка и возможности платформы (браузера, SQLite, Linux) всегда приоритетнее внешних библиотек и микросервисов.
- Меньше кода — меньше багов: удаление кода и упрощение структуры всегда лучше усложнения.
- Безопасность: все мутации данных изолированы по
user_id, пароли защищены PBKDF2 с уникальной солью. - Тестирование: после каждого изменения запуск
pytest tests/test_api.py -v(100% тестов должны быть зелеными).