# Квантик-ассистент — дизайн-документ > Статус: **дизайн** (код не пишем). Движок подсказок: **правиловый/эвристический** (без LLM). > Цель: превратить существующего питомца «Квантик» в сквозного ассистента, который > помогает работать в системе, подсказывает и проактивно напоминает. --- ## 1. Цель и принципы Маленький плавающий компаньон (тот же Квантик) присутствует на всех страницах и: 1. **Подсказывает по контексту страницы** — что тут можно, неочевидные фичи. 2. **Проактивно напоминает** — из реальных данных (домашка, карточки, урок, серия, квесты). 3. **Радуется успехам** — левелап, ачивка, серия, тест на 100%. 4. **Ведёт новичка** — короткий тур по разделам при первом входе. 5. **Отвечает «как сделать X»** — поиск по справке/FAQ (LLM — за рамками, точка расширения). Принципы: - **Единая личность** — имя/цвет/настроение из `/api/pet`, лицо — `pet-sprite.js`. Никакого второго персонажа. - **Не назойливый** — один пузырь за раз, дневной лимит, кулдауны, «понял / не показывать», тихий режим, выключаемость. - **Детерминированный** — правила и шаблоны на реальных данных, предсказуемо и офлайн. - **Без эмоджи в коде** — только inline SVG `.ic` (правило проекта). Тексты подсказок — тоже без эмоджи. - **Лёгкий** — не грузит страницы, ленивая инициализация, минимум сетевых запросов. Не-цели (сейчас): свободный диалог/LLM; голос; геймификация поверх (ачивки за общение — позже, Ф4). --- ## 2. Что уже есть (фундамент) - **Питомец «Квантик»**: 8 уровней по XP, настроение (`_mood` от серии/дней без входа), аксессуары (`_accessories`: hat/glasses/crown/star), монеты, поглаживание/кормёжка, **дневные квесты** (`_quests`), недельный XP, лента активности, прогноз настроения (`_moodForecast`), цвета, магазин фонов. - **`GET /api/pet`** (`petController.getPet`) уже отдаёт: `petName, petLevel, petColor, mood, daysSinceLogin, accessories, xp, level, streakCurrent, streakBest, coins, quests[], moodForecast, recentActivity[], weeklyXP[], xpForNextLevel`. → почти весь контекст для подсказок берётся отсюда. - **`pet-sprite.js`** — `window.PetSprite.render(level, mood, accessories, colorKey, streak)` → SVG. Переиспользуем как «лицо» ассистента (мини-версия в пузыре). - Показ: страница `/pet` + виджет на `/dashboard`. - **Онбординга/туров/подсказок в системе нет** — строим с нуля, конфликтов не будет. - **Точка инъекции:** глобальные скрипты подключаются на каждой app-странице (`api.js`, `sidebar.js`, `search.js`, `notifications.js`, `mobile.js`). `sidebar.js` есть везде → он догружает `assistant.js` одной строкой, HTML страниц не трогаем. - Питомец — фича за `requireFeature('pet')` (см. `server.js`). --- ## 3. Архитектура ``` sidebar.js (на каждой странице) └─ догружает /js/assistant.js (если фича включена и не отключено юзером) ├─ Assistant.boot() │ ├─ собирает ctx (page + данные) │ ├─ прогоняет реестр правил → выбирает 1 подсказку по приоритету/кулдауну │ └─ рисует компаньона + пузырь (лицо = PetSprite.render) ├─ assistant-rules.js — реестр правил (данные, не логика) └─ состояние/капы — localStorage (+ опц. сервер в Ф1+) ``` ### 3.1. Компоненты (файлы — создаём в фазах, не сейчас) - `frontend/js/assistant.js` — движок + UI (стили инжектит сам, как `board-clip.js`). - `frontend/js/assistant-rules.js` — каталог правил (отдельно, чтобы правила правились без движка). - `js/sidebar.js` — +строка ленивой загрузки ассистента. - `frontend/profile.html` — настройки (вкл/выкл, частота, сброс подсказок). - (Ф1) `backend/src/routes/assistant.js` + `controllers/assistantController.js` — `GET /api/assistant/context`. - (Ф1, опц.) миграция: серверная отметка «видел подсказку» для кросс-девайс (иначе только localStorage). ### 3.2. Движок: контекст и правила **Контекст `ctx`** (собирается при загрузке страницы): ```js { path, page, // page — нормализованный id ('textbook','classroom','exam-prep',...) role, // student | teacher | admin isFirstVisit, // нет ни одной отметки о показе pet, // кэш /api/pet (мин. TTL, чтобы не дёргать на каждой странице) data: { // лениво/из /api/assistant/context (Ф1) homeworkDue: [{title, deadline, status}], dueCards: , // карточек к повторению activeLesson: {courseId, title, pct} | null, weakTopics: [...], quests: [...] // из /api/pet }, events: [...], // свежие левелап/ачивка (детект по дельте) now } ``` **Форма правила:** ```js { id: 'textbook-clip', scope: 'page' | 'proactive' | 'celebration', when: (ctx) => boolean, // условие показа priority: 50, // больше = важнее (celebration > proactive > page) cooldownDays: 7, // не чаще раза в N дней maxShows: 3, // пожизненный лимит показов suppressOn: ['exam-run','board-draw'], // не мешать в фокусных режимах text: (ctx) => 'Можно вырезать кусок страницы в «Мои материалы».', action: (ctx) => ({ label: 'Показать', url: null, run: fn }) | null, petMood: 'happy' // настроение лица (опц.) } ``` **Алгоритм выбора:** отфильтровать `when && !suppressed && подходит по кулдауну/лимиту`, отсортировать по `scope`-весу + `priority`, взять **одно**. Показ — по триггеру (см. 3.3). ### 3.3. Анти-назойливость (критично) - **1 пузырь** на экране за раз. - Триггеры показа: page-подсказка — через 6–8 с на странице **или** по наведению на компаньона; proactive — раз в сессию на категорию; celebration — сразу по событию. - **Дневной лимит** проактивных подсказок (по умолчанию 3). - **Кулдаун** на правило + **пожизненный maxShows**. - Кнопки в пузыре: «Понятно» (скрыть), «Не показывать» (навсегда для этого правила). - **Тихий режим** и глобальный выключатель в профиле. - **Не мешать в фокусе:** скрывать на странице запущенного теста, во время рисования на доске, на онлайн-уроке (`suppressOn`). - `prefers-reduced-motion` — без анимаций/конфетти. ### 3.4. Хранение состояния - localStorage: `asst_off` (вкл/выкл), `asst_freq`, `asst_seen:{ruleId}={count,lastTs}`, `asst_mute_until`, `asst_pet_level`/`asst_ach_seen` (для детекта событий). - (Опц., Ф1) сервер: таблица `assistant_seen(user_id, rule_id, count, last_at)` для кросс-девайс — иначе подсказки повторятся на другом устройстве. Решить в Открытых вопросах. --- ## 4. Каталог правил (черновик) ### 4.1. Контекстные (scope: page) — «что тут можно» | id | страница | текст (суть) | действие | |----|----------|--------------|----------| | textbook-clip | /textbook | Вырежи кусок страницы картинкой в «Мои материалы» | подсветить кнопку «Вырезать область» | | textbook-deeplink | /textbook | Можно делиться ссылкой прямо на параграф | — | | board-tools | /classroom, /board | Лассо, фигуры, формулы KaTeX, линейка — попробуй панель | — | | exam-modes | /exam-prep | Режимы: экзамен / тренировка / случайный | — | | lab-sims | /lab | Симуляции запускаются прямо тут, без установки | — | | flashcards-katex | /flashcards | Формулы вводятся через KaTeX-палитру | — | | materials-folders | /my-materials | Раскладывай материалы по папкам и аннотируй фото | — | | dashboard-widgets | /dashboard | Виджеты дашборда можно настроить под себя | — | ### 4.2. Проактивные (scope: proactive) — из реальных данных | id | условие | текст | действие | |----|---------|-------|----------| | hw-due-soon | есть домашка с дедлайном < 24ч и не сдана | Домашка «X» — дедлайн скоро | → /homework | | hw-overdue | есть просроченная несданная | Просрочена домашка «X» | → /homework | | cards-due | dueCards > 0 | К повторению N карточек | → /flashcards | | lesson-continue | есть незаконченный урок | Продолжи «X» (N%) | → /course?id=... | | streak-risk | streakCurrent ≥ 1 и сегодня нет активности (вечер) | Серия N дней под угрозой — закрепи | → /exam-prep | | quest-nudge | есть незакрытый дневной квест | Добей квест: «X» | → соответствующий раздел | | weak-topic | низкий средний по теме | Подтяни тему «X» | → тест/учебник по теме | ### 4.3. Поздравления (scope: celebration) — по событию | id | триггер | реакция | |----|---------|---------| | levelup | pet.level вырос с прошлой проверки | Квантик ecstatic + «Уровень N!» | | achievement | новая ачивка | поздравление + название | | streak-milestone | серия достигла 3/7/14/30 | поздравление + аксессуар-намёк | | test-perfect | тест на 100% (из recentActivity) | поздравление | > Эмоджи в существующих квестах (`⭐📝🔥` в `petController._quests`) заменить на inline SVG `.ic` > при интеграции — для соответствия правилу проекта. --- ## 5. Источники данных (всё уже в системе) | Нужно | Откуда | |-------|--------| | настроение/серия/квесты/прогноз/уровень | `GET /api/pet` | | домашка + дедлайны | assignments (как на дашборде: `asgn-row urgent/over`) | | карточки к повторению | flashcards SRS (`LS.fc*`) | | незаконченный урок | `/api/courses` (`doneCount/lessonCount`) / `lesson_progress` | | слабые темы | analytics по `test_sessions` | | левелап/ачивки | дельта `/api/pet` (level, xp) + список ачивок | **Рекомендация (Ф1):** один эндпоинт `GET /api/assistant/context` собирает компактный бандл (`homeworkDue, dueCards, activeLesson, weakTopics`), чтобы не дёргать 4 API с клиента. --- ## 6. UI / UX - **Компаньон:** мини-Квантик (≈48–56px) в правом-нижнем углу (на мобиле — выше `mob-bar`, не перекрывая). Лёгкое «дыхание»; при наличии подсказки — мягкий пульс/бейдж. - **Пузырь:** speech-bubble над компаньоном: текст (1–2 строки) + опц. кнопка действия + «Понятно» + «Не показывать». Закрытие: кнопка, клик вне, Esc. - **Состояния:** idle / has-hint / bubble-open / celebrating (конфетти + ecstatic) / hidden. - **Стиль:** дизайн-система `ls.css` (переменные `--violet/--text/--text-3`), inline SVG `.ic`, тёмная тема, без эмоджи. Тон: дружелюбный, на «ты», кратко. - **A11y:** `aria-live="polite"` на пузыре, фокус/Esc, уважение `prefers-reduced-motion`. - **Перетаскивание/сворачивание** компаньона (запоминать позицию) — опц., Ф2. --- ## 7. Настройки и приватность - Профиль: переключатель «Ассистент Квантик», частота (обычная/низкая), «Сбросить подсказки». - Фича-флаг: reuse `pet` **или** новый `assistant` (решить — см. Открытые вопросы). - Роли: ученики — основной сценарий; учителям — отдельный набор подсказок (Ф4); по умолчанию для admin, возможно, выключен. - Никакой персональной телеметрии наружу; состояние — локально (+опц. своя таблица). --- ## 8. Фазы - **Ф0 — каркас:** `assistant.js` + `assistant-rules.js`, плавающий Квантик (лицо из `pet-sprite`), пузырь, dismissal/кулдауны/лимиты, вкл/выкл, инъекция через `sidebar.js`, 5–6 правил §4.1. - **Ф1 — проактив:** `GET /api/assistant/context` + правила §4.2 + поздравления §4.3 (детект событий). - **Ф2 — онбординг-тур** новичка по разделам + все контекстные подсказки + «не показывать снова» + (опц.) перетаскивание/сворачивание. - **Ф3 — «Спроси Квантика»:** окно с поиском по справке/FAQ (использует `search.js`). Точка расширения под LLM — **за рамками этого плана**. - **Ф4 — персонализация:** частота/тон, режим для учителей, ачивки за взаимодействие, на страницах учебника (серверный inject) тоже. --- ## 9. Затрагиваемые файлы (при будущей реализации) - + `frontend/js/assistant.js`, `frontend/js/assistant-rules.js` - ~ `js/sidebar.js` (одна строка-загрузчик) - ~ `frontend/profile.html` (настройки) - (Ф1) + `backend/src/routes/assistant.js`, `backend/src/controllers/assistantController.js`, mount в `server.js` (+ возможный фича-флаг `assistant`) - (Ф1, опц.) + миграция `assistant_seen` - ~ `petController._quests` — заменить эмоджи на `.ic` при интеграции --- ## 10. Открытые вопросы (обсудить перед Ф0) 1. **Фича-флаг:** переиспользуем `pet` или заводим отдельный `assistant`? (ассистент шире питомца). 2. **Кому по умолчанию вкл:** всем ученикам? учителям? admin — выкл? 3. **Кросс-девайс «видел»:** localStorage достаточно, или нужна серверная таблица `assistant_seen`? 4. **Учебник (серверный рендер):** включать ассистента и там (через inject) сразу или в Ф4? 5. **Тон/частота по умолчанию:** насколько активно напоминать (консервативно vs заметно)? 6. **«Спроси Квантика» (Ф3):** только справка/FAQ, или сразу закладываем место под локальную модель? --- ## 11. Риски - **Назойливость** — главный риск; смягчается лимитами/кулдаунами/тихим режимом (§3.3). - **Перекрытие UI** (особенно мобайл, существующие FAB вроде «Вырезать область», `flashcard-fab.js`) — согласовать z-index и позиции, не накладываться. - **Лишние запросы** — кэш `/api/pet`, один бандл-эндпоинт, ленивая инициализация. - **Рассинхрон личности** — всегда брать имя/цвет/настроение из одного источника (`/api/pet`).