Commit Graph

902 Commits

Author SHA1 Message Date
Maxim Dolgolyov 696c9f23a0 feat(math-ct): ЦТ 2013 V1 — 30 заданий (4 с PNG-изображениями) 2026-06-02 12:19:22 +03:00
Maxim Dolgolyov 5e6531176e feat(phys-ct): ЦТ 2018+2017 V1 — 60 заданий физики, 38 PNG-изображений 2026-06-02 12:04:41 +03:00
Maxim Dolgolyov 21b45fa6d5 feat(phys-ct): ЦТ 2018 V1 — 30 заданий физики (A1-A18 + B1-B12), 21 PNG-изображение 2026-06-02 11:57:04 +03:00
Maxim Dolgolyov 7fcf9a9615 feat(phys-ct): ЦТ 2020 V1 — 31 задание физики (A1-A20 + B1-B12), 20 PNG-изображений 2026-06-02 11:44:27 +03:00
Maxim Dolgolyov 188bf94a12 feat(phys-ct): ЦТ 2021 V1 — 32 задания физики (A1-A18 + B1-B14), 18 PNG-изображений 2026-06-02 11:34:19 +03:00
Maxim Dolgolyov 276b13a35f feat(phys-ct): ЦЭ,ЦТ 2025 V1 — 30 заданий физики (A1-A10 + B1-B20), 15 PNG-изображений 2026-06-02 11:26:13 +03:00
Maxim Dolgolyov 5d5190711e feat(math-ct): ЦТ 2014 V1 — 29 заданий (5 с PNG-изображениями) 2026-06-02 10:51:21 +03:00
Maxim Dolgolyov 8d231860af feat(math-ct): ЦТ 2015 V1 — 30 заданий (5 с PNG-изображениями) 2026-06-02 10:43:43 +03:00
Maxim Dolgolyov cf21c5797c feat(math-ct): ЦТ 2016 V1 — 30 заданий (5 с PNG-изображениями) 2026-06-02 10:32:49 +03:00
Maxim Dolgolyov 26524f9278 feat(math-ct): ЦТ 2017 V1 — 30 заданий (7 с PNG-изображениями) 2026-06-02 10:19:58 +03:00
Maxim Dolgolyov 21b7b4d9c9 feat(math-ct): ЦТ 2018 V1 — 30 заданий (6 с PNG-изображениями) 2026-06-02 10:01:02 +03:00
Maxim Dolgolyov 44e262b025 feat(math-ct): ЦТ 2020 V1 — 32 задания (5 с PNG-изображениями) + инфраструктура PDF→PNG 2026-06-02 09:44:23 +03:00
Maxim Dolgolyov f2b0db4d9a docs(search): правило ast-index vs vex (когда что) + ссылки в CLAUDE.md
- .claude/rules/search-tools.md — матрица: ast-index (символы/usages/callers/outline),
  vex (semantic/similar/pattern/duplicates/show)
- usages/callers по JS — только ast-index (vex пропускает)
- CLAUDE.md и ast-index.md ссылаются на новое правило

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 21:02:12 +03:00
Maxim Dolgolyov fe122b7681 feat(admin): журнал событий безопасности (Tier 1-2) + аудит чувствительных действий (Tier 3)
- security_events (миграция 047) + utils/securityLog.js (defensive, lazy stmt)
- Tier 1: login.success/fail, register, password.change в authController
- Tier 2: 403 (роль/разрешение) в middleware/auth, rate_limited в rateLimit
- Tier 3: audit() на выдачу доступа (access), начисление/сброс XP (gam), модерацию аватаров
- API GET/DELETE /api/admin/security-log (фильтр по категории + поиск, прунинг по дням)
- Frontend: вкладка «Безопасность» в admin.html + loadSecurityLog, расширены ACTION_LABELS

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 15:28:21 +03:00
Maxim Dolgolyov 30626e0928 fix(phys-fx): EnergyLevels — разрывная шкала, верхняя зона n=2..6 растянута, маркер разрыва оси 2026-06-01 12:31:44 +03:00
Maxim Dolgolyov 7df33e533e style(phys-fx): редизайн EnergyLevels — белый фон, цветные полосы серий, info-box, glow на активных уровнях 2026-06-01 12:27:20 +03:00
Maxim Dolgolyov 3807c424c9 fix(physics8-ch1): ползунок Ветер выходил за границы — grid minmax(0,1fr) + min-width:0 на скрубберах 2026-06-01 12:12:23 +03:00
Maxim Dolgolyov 3ac72dde12 fix(physics8-ch1): LaTeX в option-элементах заменён на Unicode — λ/кДж/кг и Tпл/°C 2026-06-01 12:10:19 +03:00
Maxim Dolgolyov a8eb4849c0 fix(physics8-hub): удалён дублирующий footer 2026-06-01 11:42:31 +03:00
Maxim Dolgolyov 1a6d4a76c3 fix(phys7 ch1): §7 формула цены деления не рендерилась — \dfrac был разорван между $-спанами (единый KaTeX + ре-рендер) 2026-06-01 11:35:00 +03:00
Maxim Dolgolyov c6835cf30c feat(phys7): наполнены боковые Шпаргалки реальным контентом (47 шпаргалок по 5 главам) 2026-06-01 11:24:40 +03:00
Maxim Dolgolyov 03ed4bb387 fix(phys7): убраны ложные заглушки боковой Шпаргалки и Подсказки (контент глав готов)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 11:14:03 +03:00
Maxim Dolgolyov 2b012f247c fix(phys8 ch1): §1 не открывался — присваивание svg.dataset=obj падало в strict-режиме (заменено на expando _body) 2026-06-01 11:03:39 +03:00
Maxim Dolgolyov 6ae7e1877e fix(phys8): восстановлен <!doctype>, JS-блок интерактивов возвращён в <script> (ch1-3) 2026-06-01 10:53:42 +03:00
Maxim Dolgolyov e88cd431ca style(notifications): редизайн dropdown — иконки по типу, левый акцент у непрочитанных, sticky-шапка 2026-06-01 10:47:06 +03:00
Maxim Dolgolyov 8641bb6954 style(flashcards): переработка стат-бара — большое цветное число, тихий градиент фона, иконка в подписи 2026-06-01 10:07:31 +03:00
Maxim Dolgolyov de205a598d style(flashcards): редизайн — цветные заголовки колод, улучшенные карточки изучения, стат-бар с иконками 2026-06-01 10:06:06 +03:00
Maxim Dolgolyov 2d83896a9a fix(dashboard): hero-аватар показывает загруженную картинку, а не только инициалы 2026-06-01 10:00:46 +03:00
Maxim Dolgolyov 7d478c1c1b style(dashboard): редизайн sticky-шапки
- Аватар: 48px + violet glow shadow
- Шапка: высота 68px, blur 16px, border rgba(violet .1), box-shadow
- Статы: пилл-обёртка с фиолетовым тинтом и бордером; разделители между кольцами
- Stat rings: горизонтальный layout SVG(36px) + sr-val + sr-label; значение вынесено из SVG наружу — читается крупно цветным шрифтом

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:51:39 +03:00
Maxim Dolgolyov 57ffbc8ae6 style(dashboard): улучшен визуал гамификационной полосы
- Фон: radial-gradient пятно за бейджем уровня + inset highlight
- Бейдж уровня: 56px, гло-тень + внешнее кольцо rgba
- Progress bar: 10px, 3-стоп градиент + box-shadow свечение
- Разделитель border-left между прогрессом и чипами
- Чипы: белый фон с тенью, увеличен padding, крупнее шрифт

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:47:28 +03:00
Maxim Dolgolyov b22a1fad3c style(dashboard): улучшен визуал карточки питомца
- Тёплый кремовый градиент фона вместо чистого белого
- Декоративный SVG-фон: рассыпанные искры/звёздочки
- Тег-пилл с янтарным оттенком
- Glow-эффект drop-shadow вокруг спрайта питомца
- Progress bar 7px с оранжевым свечением
- Цветные чипы: стрик → огненный, цель → изумрудный, настроение → фиолетовый
- Кнопка «Ухаживать» — градиент жёлтый→оранжевый с тенью

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:40:50 +03:00
Maxim Dolgolyov 5b103ab606 refactor(lab): превью симуляций вынесены в общий lab-previews.js (единый источник)
~45 SVG-превью (P_*) и хелперы _grid/_axes/_svg вынесены из lab-glue.js в
общий /js/lab-previews.js: window.LabPreviews (карта id→SVG, 40 симуляций) +
window.__LabP (по имени, lab-glue берёт алиасы оттуда). SIMS не тронут.
lab.html подключает lab-previews.js перед lab-glue.js. Теперь дашборд берёт
настоящие превью симуляций из того же источника → «Лаборатория дня» крутит
весь каталог, а не 6 захардкоженных. Дублирование 6 превью устранено.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:34:29 +03:00
Maxim Dolgolyov ed8323cbb9 style(dashboard): улучшен визуал карточки «Продолжить чтение»
- Декоративный SVG-фон (открытая книга) поверх градиента
- Тег-пилл с frosted-glass эффектом
- Progress bar 7px с белым свечением
- Мета и процент сгруппированы слева, кнопка — справа с тенью
- Градиент обогащён третьим стопом (#8b3010)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:33:50 +03:00
Maxim Dolgolyov 927b39b0d6 feat(dashboard): «Лаборатория дня» синхронизирована с каталогом /api/lab/sims
Раньше карточка использовала захардкоженный список из 6 симуляций и не знала
о каталоге. Теперь ежедневный выбор берётся из /api/lab/sims: только включённые
симуляции, у которых есть превью (приоритет featured), title/категория — из БД,
поэтому переименование/выключение/рекомендация в админке отражаются автоматически.
Время/уровень/цель — из curated-карты по id (в каталоге их нет) c дефолтами.
Фолбэк на статичный список, если API недоступен. Заодно исправлен mismatch
isoprocess→molphys (href теперь = id симуляции).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:20:10 +03:00
Maxim Dolgolyov ec2a207fb8 feat(classroom): тумблер «Вызов на урок» в профиле + интеграция мелодии в LS.sfx
Мелодию-вызов перевёл с кастомного Web Audio на общий движок звуков LS.sfx:
- длинный вестминстерский бой теперь в sound.js (звук lesson_start);
- api.js лениво подгружает sound.js на любой странице и играет lesson_start
  по SSE classroom_started (вместо собственного синтезатора);
- отдельный pref lessonCall + тумблер «Вызов на урок» и кнопка прослушивания
  в профиле (Настройки → Звуки); уважает мастер-тумблер и громкость;
- lesson_start выведен из категории classroom (управляется своим тумблером);
- разблокировка AudioContext по первому жесту перенесена в sound.js.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:11:44 +03:00
Maxim Dolgolyov 63ceeaabc2 feat(classroom): мелодия-вызов длиннее — полный вестминстерский бой (5 фраз)
Расширил перезвон с одной нисходящей фразы до полного боя из 5 фраз по 4 ноты
(G4/C5/D5/E5) с паузами между фразами и протяжной финальной нотой (~7-8 с).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:03:52 +03:00
Maxim Dolgolyov 7d8e2220ff feat(classroom): мелодия-«вызов на урок» при старте урока у ученика
Короткий нисходящий перезвон (E5-D5-C5-G4, Вестминстер-lite) через Web Audio,
без аудиофайлов: колоколообразный тембр с мягким затуханием. Играет только на
реальном событии SSE classroom_started (не при заходе в середине урока).
AudioContext разблокируется на первом действии пользователя (автоплей-политика).
Отключение: localStorage ls_cr_chime='off'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:01:28 +03:00
Maxim Dolgolyov 86a08348e0 feat(classroom): выделить вход в онлайн-урок — акцент в сайдбаре + липкий баннер
Пункт «Онлайн-урок» в сайдбаре теперь визуально выделен (акцентная иконка),
а когда урок идёт — пульсирующий бейдж «В эфире» (и точка-пульс в свёрнутом
режиме). Вместо легко пропускаемой всплывашки снизу — липкий баннер сверху
на любой странице с кнопкой «Войти», пока урок активен. Состояние берётся из
SSE classroom_started/ended + проверки /api/classroom/my/active при загрузке
(чтобы баннер появлялся и при заходе в середине урока). Для учеников.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 08:59:21 +03:00
Maxim Dolgolyov 0b2e7c8880 fix(exam-prep): стилизованное окно завершения пробника вместо нативного confirm
Окно подтверждения завершения пробника использовало нативный confirm()
(и alert() при ошибке) — без стилей. Заменено на LS.confirm (стилизованный
модал) и LS.toast для ошибки завершения.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 08:47:12 +03:00
Maxim Dolgolyov 536261ceb5 fix(whiteboard): фон annotate-режима очищается сразу, не после первого штриха
setAnnotateMode менял _annotateMode и вызывал render(), но не помечал
статический слой грязным (_staticDirty). Фон рисуется в статич. слое и
перерисовывается только при _staticDirty=true, поэтому непрозрачный фон
доски оставался поверх учебника/симуляции до первого штриха. Ставим
_staticDirty=true при смене режима.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 08:43:32 +03:00
Maxim Dolgolyov 9512e33783 merge: feature/chemistry-8 → master 2026-05-31 16:22:19 +03:00
Maxim Dolgolyov dc3f2a8100 merge: feature/lab-content-engine → master 2026-05-31 16:22:19 +03:00
Maxim Dolgolyov 06b23c36dd fix(dashboard): пустой виджет карточек — кнопка ведёт на /flashcards
Кнопка «Создать карточку» в пустом состоянии вызывала click() по FAB,
но исходный клик всплывал до document-листенера, который сразу закрывал
поп-ап — внешне ничего не происходило. Заменено на ссылку на /flashcards.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 16:10:34 +03:00
Maxim Dolgolyov 0d2ddee874 feat(dashboard): карточка чтения берёт данные и цвет из «Учебников»
Источник — /api/textbooks (как страница «Учебники»):
- учебник в процессе (есть прочитанные §) → «Продолжить чтение» с
  прогресс-баром и «N из M § прочитано», ссылка на last_para;
- иначе первый учебник каталога → «Начать чтение», «M § · новый учебник»;
- фон карточки = градиент обложки по t.color (TB_COVER — зеркало
  .tb-cover из textbooks.html), полная синхронизация цвета.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:32:00 +03:00
Maxim Dolgolyov a34137c41c fix(profile): добавлен CSS рейтинга (кнопки/строки были без стилей)
Классы .lb-tab/.lb-tabs/.lb-row/.lb-list/.lb-avatar и др. отсутствовали
в profile.html — карточка рейтинга рендерилась голой. Добавлены стили
под дизайн-систему профиля.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:29:12 +03:00
Maxim Dolgolyov 6551990e8e fix(dashboard): иконка испытания «Марафонец» (running → footprints)
Иконка Lucide 'running' не существует, поэтому createIcons() оставлял
<i> пустым — у испытания типа 'tests' не было иконки. Заменено на
валидную 'footprints'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 12:20:33 +03:00
Maxim Dolgolyov 4fed35fec8 feat(dashboard): карточка чтения наполняется данными (фон+инфо учебника)
Раньше при отсутствии начатого курса карточка оставалась статичной
заглушкой («Учебники»). Теперь:
- при прогрессе — «Продолжить чтение»: курс, урок, прогресс-бар, %;
- иначе — рекомендованный учебник из /api/courses: название, описание,
  число параграфов;
- фон-градиент карточки по предмету (SUBJ_GRADIENT, как обложки).
Синтаксис всех инлайн-скриптов проверен (0 ошибок).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:18:40 +03:00
Maxim Dolgolyov eaba6b7389 fix(profile): рейтинг виден всегда (пустое состояние вместо скрытия)
Раньше карточка пряталась при отсутствии данных API — выглядело как
«рейтинга нет». Теперь всегда видна: либо список, либо подсказка
«Пока нет данных рейтинга».

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:11:47 +03:00
Maxim Dolgolyov 2addb8ec02 fix(dashboard): Активность видна всегда + ряд одинаковой высоты
- loadActivityWidget показывает блок всегда (пустое состояние рисует
  renderHeatmap), даже при 0 сессий и при ошибке истории.
- .bottom-grid: align-items stretch + height 100% — карточки ряда
  (Активность/Мои сдачи/Испытания) одной высоты.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:02:32 +03:00
Maxim Dolgolyov e6120c6fc8 fix(profile): добавлена разметка карточки рейтинга (JS был без markup)
Контейнер lb-section не попал в файл ранее — loadLeaderboard молча
выходил. Теперь рейтинг реально виден в табе «Достижения».

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:01:22 +03:00