fix(ct-math): практика возвращала меньше count + перенос заголовков в навигации урока

1) exam-prep practice (strategy=random) возвращал около 0.6 от count: функция
   distributeByDifficulty раскладывает count по 5 уровням сложности, а у трека
   ctmath задания только уровней 1-3 (уровни 4-5 пустые) -> часть выборки терялась
   (20 -> 12, 15 -> 10, 10 -> 6). В pickRandomByDifficulty добавлен добор до count
   из доступных уровней. Трек math9 не затронут (там добор не требуется).
2) lesson.html: .lesson-nav-btn-title был inline-span, поэтому max-width и ellipsis
   игнорировались и длинные заголовки вылезали за кнопку. Добавлен display:block.

Бэкенд-правка требует перезапуска сервера; фронт-правка видна после Ctrl+F5.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-15 12:09:50 +03:00
parent 4b23d768f2
commit 8091b48e1c
2 changed files with 22 additions and 3 deletions
+21 -2
View File
@@ -630,13 +630,15 @@ function pickRandomByDifficulty(examKey, count, excludeSlugs) {
? `AND (subtopic IS NULL OR subtopic NOT IN (${exParams.map(() => '?').join(',')}))`
: '';
const COLS = `id, task_idx, variant, task_type, text_html, figure_html, opts_json,
answer, solution_html, topic, subtopic, difficulty, textbook_slug, textbook_paragraph`;
const out = [];
const seen = new Set();
for (let d = 1; d <= 5; d++) {
const limit = dist[d - 1];
if (limit === 0) continue;
const sql = `
SELECT id, task_idx, variant, task_type, text_html, figure_html, opts_json,
answer, solution_html, topic, subtopic, difficulty, textbook_slug, textbook_paragraph
SELECT ${COLS}
FROM exam_tasks
WHERE exam_key = ? AND task_type IN ('mc','open')
AND difficulty = ?
@@ -646,8 +648,25 @@ function pickRandomByDifficulty(examKey, count, excludeSlugs) {
const args = exParams
? [examKey, d, ...exParams, limit]
: [examKey, d, limit];
for (const r of db.prepare(sql).all(...args)) { if (!seen.has(r.id)) { seen.add(r.id); out.push(r); } }
}
// Backfill to `count` from any difficulty — covers tracks whose tasks don't
// span all 5 difficulty levels (otherwise empty levels would shrink the batch).
if (out.length < count) {
const ids = [...seen];
const notIn = ids.length ? `AND id NOT IN (${ids.map(() => '?').join(',')})` : '';
const sql = `
SELECT ${COLS}
FROM exam_tasks
WHERE exam_key = ? AND task_type IN ('mc','open')
${exClause}
${notIn}
ORDER BY RANDOM()
LIMIT ?`;
const args = [examKey, ...(exParams || []), ...ids, count - out.length];
out.push(...db.prepare(sql).all(...args));
}
out.sort((a, b) => (a.difficulty || 0) - (b.difficulty || 0));
return out;
}
+1 -1
View File
@@ -276,7 +276,7 @@
.lesson-nav-btn-prev { justify-content: flex-start; }
.lesson-nav-btn-next { justify-content: flex-end; margin-left: auto; }
.lesson-nav-btn-label { font-size: 0.7rem; font-weight: 600; color: var(--text-3); display: block; }
.lesson-nav-btn-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 160px; }
.lesson-nav-btn-title { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 160px; }
/* ── complete button ── */
.lesson-complete-wrap {