'use strict'; /* ─────────────────────────────────────────────────────────────────────────── seed_ctmath_ct2016_v1.js Чистый вариант-пробник для трека exam-prep `ctmath`. Источник: Централизованное тестирование (ЦТ) по математике, 2016, Вариант 1. Формат: Часть А = А1–А18 (закрытые, 5 вариантов), Часть В = В1–В12 (открытые). Всего 30 заданий. Перенабрано вручную в KaTeX по PDF: F:\!Рабочие\ЦТ\Математика\Математика\ЦТ-ЦЭ\ЦТ 2016.pdf (10 вариантов, табл. ответов стр.35). ⚠️ Ответы решены самостоятельно и СВЕРЕНЫ с официальной таблицей ответов (стр. 35, столбец «Вариант 1»): ВСЕ 30 совпали, включая B5=-22, B9=712, B11=56, B12=724. variant=113 (после ЦТ-2015 = 112). Адаптации/реконструкции заданий-«с-картинкой» (смысл/ответ сохранены, авто-проверка): • А2 (∠ по рисунку треугольника) → та же задача с явным условием $MN\parallel BC$ (даёт официальный ответ $33^\circ$); • А3 (числа $0,k,t$ на прямой) → явно $0 html.map((h, i) => [L[i], h]); const TD = 'style="border:1px solid #99a;padding:3px 12px"'; /* ── 30 заданий ─────────────────────────────────────────────────────────── */ const TASKS = [ // ── Часть A: А1–А18 ────────────────────────────────────────────────────── { idx: 1, type: 'mc', topic: 'numbers', subtopic: 'num-divisibility', diff: 1, text: R`Определите наименьшее натуральное число, кратное $2$, которое при делении на $15$ даёт неполное частное, равное $3$.`, opts: mc('$44$', '$50$', '$48$', '$18$', '$46$'), answer: 'д', sol: R`Число имеет вид $15\cdot3+r=45+r$, где $0\le r<15$. Наименьшее чётное получается при $r=1$: это $46$.`, ref: 'Математика, 5 класс, ч. 1, гл. 3' }, { idx: 2, type: 'mc', topic: 'planimetry', subtopic: 'plan-triangles', diff: 2, text: R`В треугольнике $ABC$ точки $M$ и $N$ лежат на сторонах $AB$ и $AC$ соответственно, причём $MN\parallel BC$. Известно, что $\angle ACB=38^\circ$ и $\angle AMN=109^\circ$. Найдите градусную меру угла $BAC$.`, opts: mc('$33^\circ$', '$52^\circ$', '$26^\circ$', '$30^\circ$', '$60^\circ$'), answer: 'а', sol: R`Так как $MN\parallel BC$, то $\angle ABC=\angle AMN=109^\circ$ (соответственные углы). Тогда $\angle BAC=180^\circ-\angle ABC-\angle ACB=180^\circ-109^\circ-38^\circ=33^\circ$.`, ref: 'Геометрия, 7 класс, гл. 3' }, { idx: 3, type: 'mc', topic: 'numbers', subtopic: 'num-real', diff: 1, text: R`На координатной прямой отмечены числа $0$, $k$, $t$, причём $0\dfrac1k$', '$3k>3t$', '$\dfrac{k}{-3}>\dfrac{t}{-3}$', '$k>t$'), answer: 'г', sol: R`При делении неравенства $k\dfrac{t}{-3}$. Остальные утверждения неверны.`, ref: 'Алгебра, 8 класс, гл. 1' }, { idx: 4, type: 'mc', topic: 'expressions', subtopic: 'expr-powers-roots', diff: 2, text: R`Значение выражения $3^{-5}:\left(5\tfrac25\right)^{-3}$ равно:`, opts: mc('$\dfrac{27}{125}$', '$\dfrac{4}{5}$', '$\dfrac{125}{81}$', '$\dfrac{81}{125}$', '$\dfrac{125}{243}$'), answer: 'г', sol: R`$5\tfrac25=\dfrac{27}{5}$. Тогда $3^{-5}:\left(\dfrac{27}{5}\right)^{-3}=3^{-5}\cdot\dfrac{3^{9}}{5^{3}}=\dfrac{3^{4}}{5^{3}}=\dfrac{81}{125}$.`, ref: 'Алгебра, 7 класс, гл. 1, § 4' }, { idx: 5, type: 'mc', topic: 'word-sequences', subtopic: 'seq-progressions', diff: 1, text: R`Укажите формулу $n$-го члена арифметической прогрессии $(a_n)$, если $a_1=2$, $a_2=5$.`, opts: mc('$a_n=-3n+5$', '$a_n=3n+5$', '$a_n=3n-1$', '$a_n=2n+5$', '$a_n=5n+2$'), answer: 'в', sol: R`$d=a_2-a_1=3$, поэтому $a_n=a_1+(n-1)d=2+3(n-1)=3n-1$.`, ref: 'Алгебра, 9 класс, гл. 4' }, { idx: 6, type: 'mc', topic: 'word-sequences', subtopic: 'word-problems', diff: 1, text: R`Величины $a$ и $b$ прямо пропорциональны. Используя данные таблицы, найдите неизвестное значение величины $a$.`, fig: R`
a1,9
b1087,6
`, opts: mc('$32$', '$27$', '$22$', '$14$', '$56$'), answer: 'б', sol: R`При прямой пропорциональности $\dfrac{a}{b}$ постоянно: $\dfrac{a}{108}=\dfrac{1{,}9}{7{,}6}=0{,}25$, откуда $a=27$.`, ref: 'Математика, 6 класс, гл. 2' }, { idx: 7, type: 'mc', topic: 'planimetry', subtopic: 'plan-quadrilaterals', diff: 2, text: R`Найдите площадь (в см²) многоугольника с вершинами $A(2;2)$, $B(9;2)$, $C(9;7)$, $D(3;7)$, $E(2;8)$ (координаты — в сантиметрах).`, opts: mc('$35{,}5$', '$28$', '$36$', '$49$', '$35$'), answer: 'а', sol: R`По формуле площади многоугольника по координатам вершин (формула шнуровки) $2S=\bigl|{-}14+45+42+10-12\bigr|=71$, поэтому $S=35{,}5$ см².`, ref: 'Геометрия, 8 класс, гл. 4' }, { idx: 8, type: 'mc', topic: 'functions', subtopic: 'fn-properties', diff: 2, text: R`Областью значений функции $y=f(x)$ на промежутке $(-5;5)$ является отрезок $[-4;6]$. Найдите сумму всех целых значений, которые принимает функция.`, opts: mc('$12$', '$14$', '$7$', '$10$', '$11$'), answer: 'д', sol: R`Функция принимает все целые значения от $-4$ до $6$. Их сумма $-4-3-2-1+0+1+2+3+4+5+6=11$.`, ref: 'Алгебра, 9 класс, гл. 2' }, { idx: 9, type: 'mc', topic: 'numbers', subtopic: 'num-divisibility', diff: 1, text: R`Найдите значение выражения НОК$(12;18;36)$ + НОД$(39;52)$.`, opts: mc('$26$', '$50$', '$48$', '$72$', '$49$'), answer: 'д', sol: R`НОК$(12;18;36)=36$, НОД$(39;52)=13$. Сумма $36+13=49$.`, ref: 'Математика, 6 класс, гл. 1' }, { idx: 10, type: 'mc', topic: 'stereometry', subtopic: 'ster-angles-distances', diff: 2, text: R`Прямая $a$ пересекает плоскость $\alpha$ в точке $A$ и образует с плоскостью угол $60^\circ$. Точка $B$ лежит на прямой $a$, причём $AB=6\sqrt2$. Найдите расстояние от точки $B$ до плоскости $\alpha$.`, opts: mc('$3\sqrt2$', '$3\sqrt6$', '$3\sqrt3$', '$6\sqrt6$', '$6\sqrt3$'), answer: 'б', sol: R`Расстояние от $B$ до плоскости равно $AB\sin60^\circ=6\sqrt2\cdot\dfrac{\sqrt3}{2}=3\sqrt6$.`, ref: 'Геометрия, 10 класс, разд. 3' }, { idx: 11, type: 'mc', topic: 'word-sequences', subtopic: 'word-problems', diff: 2, text: R`На круговой диаграмме распределения посевных площадей секторам отвечают: ячмень — $63^\circ$, пшеница — $108^\circ$, гречиха — $36^\circ$, рожь — $18^\circ$, остальное — овёс. Сколько гектаров отведено под гречиху, если овсом засеяно на $390$ га больше, чем рожью?`, opts: mc('$110$ га', '$150$ га', '$120$ га', '$160$ га', '$180$ га'), answer: 'в', sol: R`Овёс: $360^\circ-63^\circ-108^\circ-36^\circ-18^\circ=135^\circ$. Разность «овёс минус рожь» $=135^\circ-18^\circ=117^\circ$ отвечает $390$ га, поэтому $1^\circ\to\dfrac{390}{117}=\dfrac{10}{3}$ га. Гречиха: $36^\circ\cdot\dfrac{10}{3}=120$ га.`, ref: 'Математика, 6 класс, гл. 2' }, { idx: 12, type: 'mc', topic: 'planimetry', subtopic: 'plan-triangles', diff: 2, text: R`Длины всех сторон треугольника — целые числа. Если длина одной стороны равна $1$, а другой — $3$, то периметр треугольника равен:`, opts: mc('$7$', '$14$', '$21$', '$6$', '$8$'), answer: 'а', sol: R`По неравенству треугольника третья сторона $c$ удовлетворяет $|3-1|0$.`, answer: '60', sol: R`Основание $\dfrac{1}{15}<1$, поэтому $0<\log_{2}\log_{9}(x+15)<1$, откуда $1<\log_{9}(x+15)<2$, то есть $9Ответ: ${ans}`; if (t.ref) html += `
Учебник: ${t.ref}
`; return html; } /* ── Самопроверка (повтор логики checkAnswerServer из exam-prep.js) ────────── */ const EPS = 1e-6; function srvToNumber(s) { if (s == null) return NaN; let t = String(s).trim().replace(/\$/g, '').replace(/\s+/g, '').replace(',', '.'); const f = t.match(/^(-?\d+(?:\.\d+)?)\s*\/\s*(-?\d+(?:\.\d+)?)$/); if (f) { const n = Number(f[1]), d = Number(f[2]); return d === 0 ? NaN : n / d; } const n = Number(t); return Number.isFinite(n) ? n : NaN; } function checkAnswerServer(userInput, canonical) { if (userInput == null || canonical == null) return false; const c = String(canonical).trim(); if (/^[а-д]$/.test(c)) return String(userInput).trim().toLowerCase() === c.toLowerCase(); if (/^[^;]+;[^;]+$/.test(c)) return false; const cn = srvToNumber(c), un = srvToNumber(userInput); if (Number.isNaN(cn) || Number.isNaN(un)) return false; return Math.abs(cn - un) < EPS; } /* ── Валидация набора ──────────────────────────────────────────────────────── */ const problems = []; if (TASKS.length !== 30) problems.push(`Ожидалось 30 заданий, получено ${TASKS.length}`); const seen = new Set(); for (const t of TASKS) { if (seen.has(t.idx)) problems.push(`Дубль task_idx=${t.idx}`); seen.add(t.idx); if (t.idx < 1 || t.idx > 30) problems.push(`task_idx вне 1..30: ${t.idx}`); if (!['mc', 'open', 'long'].includes(t.type)) problems.push(`#${t.idx}: тип ${t.type}`); if (t.type === 'mc') { if (!Array.isArray(t.opts) || t.opts.length !== 5) problems.push(`#${t.idx}: mc должен иметь 5 вариантов`); if (!t.opts.some(o => o[0] === t.answer)) problems.push(`#${t.idx}: answer "${t.answer}" не среди меток`); } if (!t.text || !t.sol) problems.push(`#${t.idx}: пустой text/sol`); if (t.type !== 'long' && !checkAnswerServer(t.answer, t.answer)) problems.push(`#${t.idx}: answer "${t.answer}" не проходит self-check (Unicode-минус? пробел?)`); if (/−/.test(String(t.answer))) problems.push(`#${t.idx}: Unicode-минус в answer`); } /* ── Экспорт для тестов/тиража (без запуска main при require) ──────────────── */ module.exports = { TASKS, buildSolution, ansShowOf, checkAnswerServer, EXAM, VARIANT, PROV }; if (require.main !== module) return; /* ── Открытие БД ───────────────────────────────────────────────────────────── */ const DB = path.join(__dirname, '..', 'data', 'learnspace.db'); const db = new DatabaseSync(DB); const track = db.prepare(`SELECT exam_key, variants_count FROM exam_tracks WHERE exam_key=?`).get(EXAM); if (!track) { console.error(`✗ Трек '${EXAM}' не найден в exam_tracks. Прерывание.`); process.exit(1); } /* ── DRY-RUN сводка ────────────────────────────────────────────────────────── */ console.log(`\n=== seed_ctmath_ct2016_v1 (${PROV}) variant=${VARIANT} ===`); console.log(`Режим: ${APPLY ? 'APPLY (запись)' : 'DRY-RUN (только проверка)'}\n`); const byType = TASKS.reduce((a, t) => (a[t.type] = (a[t.type] || 0) + 1, a), {}); console.log('Типы:', JSON.stringify(byType), '\n'); console.log('idx | type | subtopic | d | answer'); console.log('----+------+-----------------------+---+----------'); for (const t of TASKS) { console.log(`${String(t.idx).padStart(3)} | ${t.type.padEnd(4)} | ${String(t.subtopic).padEnd(21)} | ${t.diff} | ${String(t.answer)}`); } if (problems.length) { console.error(`\n✗ ПРОБЛЕМЫ (${problems.length}):`); problems.forEach(p => console.error(' - ' + p)); console.error('\nЗапись отменена из-за ошибок валидации.'); db.close(); process.exit(1); } console.log('\n✓ Валидация и self-check ответов пройдены (30/30).'); /* ── APPLY: upsert ─────────────────────────────────────────────────────────── */ if (!APPLY) { console.log('\nDRY-RUN: ничего не записано. Для записи: node backend/scripts/seed_ctmath_ct2016_v1.js --apply\n'); db.close(); process.exit(0); } const upsert = db.prepare(` INSERT INTO exam_tasks (exam_key, variant, task_idx, task_type, text_html, figure_html, opts_json, answer, solution_html, topic, subtopic, difficulty) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(exam_key, variant, task_idx) DO UPDATE SET task_type = excluded.task_type, text_html = excluded.text_html, figure_html = excluded.figure_html, opts_json = excluded.opts_json, answer = excluded.answer, solution_html = excluded.solution_html, topic = excluded.topic, subtopic = excluded.subtopic, difficulty = excluded.difficulty `); let n = 0; db.exec('BEGIN'); try { for (const t of TASKS) { upsert.run( EXAM, VARIANT, t.idx, t.type, t.text, t.fig || null, t.type === 'mc' ? JSON.stringify(t.opts) : null, t.answer, buildSolution(t), t.topic, t.subtopic, t.diff ); n++; } const distinct = db.prepare(`SELECT COUNT(DISTINCT variant) c FROM exam_tasks WHERE exam_key=? AND variant BETWEEN 101 AND 1999`).get(EXAM).c; db.prepare(`UPDATE exam_tracks SET variants_count=? WHERE exam_key=?`).run(distinct, EXAM); db.exec('COMMIT'); console.log(`\n✓ Записано/обновлено ${n} заданий (variant=${VARIANT}).`); console.log(`✓ exam_tracks.variants_count = ${distinct} (различных вариантов).`); console.log(`\nПробник доступен: /exam-prep/ctmath → «Варианты» → «ЦТ-2016».\n`); } catch (e) { db.exec('ROLLBACK'); console.error('\n✗ Ошибка записи, откат транзакции:', e.message); process.exitCode = 1; } db.close();