/
eup
/
test
Обзор
Документация
Войти
/
eup
/
test
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
index.html
1 642 строки
75 KB
eup
Create: index.html
07 июн 2026, 12:03
Верифицирован
07 июн 2026, 12:03
a9ce85c
Код
Авторство
О чём код?
<!doctype html> <html lang="ru"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Тренажер ЕГЭ по русскому языку</title> <style> :root { --ink: #17202a; --muted: #687385; --line: #d7dee8; --paper: #f7f8fb; --surface: #ffffff; --blue: #315fbd; --blue-soft: #e9f0ff; --green: #247a5b; --green-soft: #e8f6ef; --red: #b13a3a; --red-soft: #faeaea; --amber: #a76500; --amber-soft: #fff1d8; --violet: #6251b7; --shadow: 0 18px 44px rgba(31, 42, 68, .12); font-family: Inter, "Segoe UI", Roboto, Arial, sans-serif; } * { box-sizing: border-box; } body { margin: 0; color: var(--ink); background: linear-gradient(135deg, rgba(49, 95, 189, .12), transparent 32%), linear-gradient(215deg, rgba(36, 122, 91, .12), transparent 34%), var(--paper); min-height: 100vh; } button, input, select { font: inherit; } button { border: 0; cursor: pointer; } .shell { min-height: 100vh; display: grid; grid-template-columns: minmax(240px, 310px) minmax(0, 1fr); } aside { background: rgba(255, 255, 255, .82); border-right: 1px solid var(--line); padding: 24px; backdrop-filter: blur(14px); } .brand { display: flex; align-items: center; gap: 12px; margin-bottom: 28px; } .mark { width: 44px; height: 44px; display: grid; place-items: center; background: var(--ink); color: #fff; border-radius: 8px; font-weight: 800; letter-spacing: 0; } h1, h2, h3, p { margin: 0; } h1 { font-size: 19px; line-height: 1.15; } .brand p { color: var(--muted); font-size: 13px; margin-top: 4px; } .section-label { color: var(--muted); font-size: 12px; font-weight: 750; text-transform: uppercase; margin: 24px 0 10px; } .nav-list, .stats-list, .mistake-list { display: grid; gap: 8px; } .nav-btn { width: 100%; display: flex; align-items: center; justify-content: space-between; min-height: 44px; padding: 10px 12px; color: var(--ink); background: transparent; border-radius: 8px; text-align: left; } .nav-btn:hover, .nav-btn.active { background: var(--blue-soft); } .nav-btn strong { font-size: 14px; } .count { color: var(--muted); font-size: 12px; border: 1px solid var(--line); border-radius: 999px; padding: 2px 7px; background: #fff; } .stat-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 9px 0; border-bottom: 1px solid var(--line); color: var(--muted); font-size: 14px; } .stat-row b { color: var(--ink); font-size: 15px; } main { padding: 28px; display: grid; grid-template-rows: auto auto 1fr; gap: 18px; min-width: 0; } .topbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; } .title-block h2 { font-size: clamp(24px, 3.2vw, 40px); line-height: 1.05; max-width: 780px; } .title-block p { color: var(--muted); margin-top: 8px; max-width: 720px; line-height: 1.5; } .mode { display: inline-grid; grid-template-columns: 1fr 1fr; padding: 4px; gap: 4px; background: #e6ebf2; border-radius: 8px; min-width: 246px; } .mode button { min-height: 38px; border-radius: 6px; background: transparent; color: var(--muted); font-weight: 750; } .mode button.active { background: #fff; color: var(--ink); box-shadow: 0 2px 8px rgba(33, 42, 56, .1); } .progress-band { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 18px; background: rgba(255, 255, 255, .72); border: 1px solid var(--line); border-radius: 8px; padding: 14px 16px; } .bar { height: 10px; border-radius: 999px; background: #e0e6ee; overflow: hidden; } .bar span { display: block; height: 100%; width: 0%; background: linear-gradient(90deg, var(--green), var(--blue)); transition: width .25s ease; } .progress-text { color: var(--muted); white-space: nowrap; font-size: 14px; } .workspace { display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 340px); gap: 18px; align-items: start; } .panel, .mistakes-panel { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; box-shadow: var(--shadow); } .panel { padding: 26px; min-height: 550px; display: grid; grid-template-rows: auto auto 1fr auto; gap: 22px; } .task-meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; } .pill { display: inline-flex; align-items: center; min-height: 28px; padding: 4px 9px; border-radius: 999px; color: var(--blue); background: var(--blue-soft); font-size: 13px; font-weight: 750; } .task-number { color: var(--muted); font-size: 14px; } .question { font-size: clamp(22px, 3vw, 34px); line-height: 1.2; font-weight: 790; max-width: 900px; } .hint { color: var(--muted); line-height: 1.55; max-width: 760px; } .options { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; align-content: start; } .option { min-height: 62px; padding: 15px 16px; text-align: left; border: 1px solid var(--line); background: #fff; border-radius: 8px; color: var(--ink); font-weight: 700; line-height: 1.25; transition: border-color .18s ease, transform .18s ease, background .18s ease; overflow-wrap: anywhere; } .option:hover { border-color: var(--blue); transform: translateY(-1px); } .option.correct { border-color: var(--green); background: var(--green-soft); color: var(--green); } .option.wrong { border-color: var(--red); background: var(--red-soft); color: var(--red); } .feedback { display: none; border-radius: 8px; padding: 14px 16px; line-height: 1.5; border: 1px solid var(--line); background: #f8fafc; } .feedback.show { display: block; } .feedback.good { background: var(--green-soft); border-color: rgba(36, 122, 91, .35); } .feedback.bad { background: var(--red-soft); border-color: rgba(177, 58, 58, .35); } .actions { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; } .primary, .secondary, .ghost { min-height: 42px; border-radius: 8px; padding: 10px 14px; font-weight: 790; display: inline-flex; align-items: center; justify-content: center; gap: 8px; } .primary { background: var(--ink); color: #fff; } .secondary { background: var(--amber-soft); color: var(--amber); } .ghost { background: #eef2f7; color: var(--ink); } .primary:disabled { opacity: .45; cursor: not-allowed; } .mistakes-panel { padding: 18px; position: sticky; top: 18px; } .mistakes-panel h3 { font-size: 17px; margin-bottom: 6px; } .mistakes-panel > p { color: var(--muted); line-height: 1.45; font-size: 14px; margin-bottom: 16px; } .mistake-item { border-top: 1px solid var(--line); padding: 12px 0; } .mistake-item strong { display: block; font-size: 14px; line-height: 1.35; } .mistake-item span { display: block; color: var(--muted); font-size: 13px; margin-top: 5px; line-height: 1.4; } .empty { padding: 18px; background: #f4f7fa; border-radius: 8px; color: var(--muted); line-height: 1.45; font-size: 14px; } .exam-summary { display: none; padding: 18px; border-radius: 8px; border: 1px solid rgba(98, 81, 183, .24); background: #f0eefc; line-height: 1.5; } .exam-summary.show { display: block; } .kbd { border: 1px solid var(--line); background: #fff; border-radius: 6px; padding: 2px 6px; color: var(--muted); font-size: 12px; white-space: nowrap; } @media (max-width: 980px) { .shell { grid-template-columns: 1fr; } aside { border-right: 0; border-bottom: 1px solid var(--line); } .nav-list { grid-template-columns: repeat(3, 1fr); } .workspace { grid-template-columns: 1fr; } .mistakes-panel { position: static; } } @media (max-width: 720px) { aside, main { padding: 18px; } .topbar, .progress-band { align-items: stretch; grid-template-columns: 1fr; flex-direction: column; } .mode { width: 100%; min-width: 0; } .nav-list, .options { grid-template-columns: 1fr; } .panel { padding: 18px; min-height: 520px; } .progress-text { white-space: normal; } } </style> </head> <body> <div class="shell"> <aside> <div class="brand"> <div class="mark">ЕГЭ</div> <div> <h1>Русский язык</h1> <p>ударения, грамматика, орфография</p> </div> </div> <div class="section-label">Раздел</div> <nav class="nav-list" id="categoryNav" aria-label="Разделы подготовки"></nav> <div class="section-label">Статистика</div> <div class="stats-list"> <div class="stat-row"><span>Решено</span><b id="statTotal">0</b></div> <div class="stat-row"><span>Точность</span><b id="statAccuracy">0%</b></div> <div class="stat-row"><span>Серия</span><b id="statStreak">0</b></div> <div class="stat-row"><span>Лучший раздел</span><b id="statBest">-</b></div> </div> </aside> <main> <div class="topbar"> <div class="title-block"> <h2>Тренажер заданий ЕГЭ по русскому языку</h2> <p>Выбирай раздел, отвечай на вопросы и сразу разбирай правило. В экзамене подсказки скрыты до конца серии.</p> </div> <div class="mode" role="group" aria-label="Режим тренировки"> <button id="trainMode" class="active" type="button">Тренировка</button> <button id="examMode" type="button">Экзамен</button> </div> </div> <div class="progress-band"> <div class="bar" aria-hidden="true"><span id="progressBar"></span></div> <div class="progress-text" id="progressText">Вопрос 1 из 10</div> </div> <div class="workspace"> <section class="panel" aria-live="polite"> <div class="task-meta"> <span class="pill" id="categoryPill">Ударения</span> <span class="task-number" id="taskNumber">Задание 1</span> </div> <div> <div class="question" id="questionText"></div> <p class="hint" id="questionHint"></p> </div> <div class="options" id="options"></div> <div> <div class="feedback" id="feedback"></div> <div class="exam-summary" id="examSummary"></div> </div> <div class="actions"> <button class="ghost" id="restartBtn" type="button">Начать заново</button> <div> <span class="kbd">1-4</span> <span class="kbd">Enter</span> </div> <button class="primary" id="nextBtn" type="button" disabled>Следующее</button> </div> </section> <aside class="mistakes-panel" aria-label="Ошибки"> <h3>Разбор ошибок</h3> <p>Здесь остаются последние промахи. Нажми «Начать заново», чтобы повторить текущий раздел с чистого листа.</p> <div class="mistake-list" id="mistakes"></div> </aside> </div> </main> </div> <script> const bank = { stress: { label: "Ударения", short: "Ударения", description: "Выбери слово с верно выделенной ударной гласной.", tasks: [ { q: "В каком слове ударение поставлено верно?", options: ["дОговор", "договОр", "красИвее", "созЫв"], answer: 2, rule: "Правильно: красИвее. В сравнительной степени прилагательного ударение сохраняется на И: красИвый - красИвее." }, { q: "В каком слове ударение поставлено верно?", options: ["звонИт", "звОнит", "каталОг", "катАлог"], answer: 0, rule: "Правильно: звонИт. В формах глагола звонить ударение падает на окончание: звонИшь, звонИт, звонИм." }, { q: "В каком слове ударение поставлено верно?", options: ["кУхонный", "кухОнный", "облегчИть", "облЕгчить"], answer: 1, rule: "Правильно: кухОнный. Это одно из частотных слов орфоэпического минимума ЕГЭ." }, { q: "В каком слове ударение поставлено верно?", options: ["тОрты", "тортЫ", "аэропОрты", "аэропортЫ"], answer: 0, rule: "Правильно: тОрты. В слове торт ударение остается на первом слоге: тОрты, тОртов." }, { q: "В каком слове ударение поставлено верно?", options: ["начАв", "нАчав", "прИняв", "принЯв"], answer: 0, rule: "Правильно: начАв. В деепричастиях начАв, начАвшись ударение падает на последний слог." }, { q: "В каком слове ударение поставлено верно?", options: ["балОванный", "бАлованный", "экспЕрт", "Эксперт"], answer: 1, rule: "Правильно: бАлованный. Запоминаем также: баловАть, избаловАть, но бАлованный." }, { q: "В каком слове ударение поставлено верно?", options: ["диспансЕр", "диспАнсер", "цемЕнт", "цЕмент"], answer: 0, rule: "Правильно: диспансЕр. Ударение в этом слове падает на последний слог." }, { q: "В каком слове ударение поставлено верно?", options: ["срЕдства", "средствА", "жалюзИ", "жАлюзи"], answer: 2, rule: "Правильно: жалюзИ. Слово несклоняемое, ударение падает на последний слог." }, { q: "В каком слове ударение поставлено верно?", options: ["вероисповЕдание", "вероисповедАние", "намЕрение", "намерЕние"], answer: 0, rule: "Правильно: вероисповЕдание. В ЕГЭ это слово часто проверяет устойчивую орфоэпическую норму." }, { q: "В каком слове ударение поставлено верно?", options: ["ободрИть", "обОдрить", "принудИть", "прИнудить"], answer: 0, rule: "Правильно: ободрИть. В инфинитиве ударение падает на И: ободрИть, укрепИть, облегчИть." }, { q: "В каком слове ударение поставлено верно?", options: ["слИвовый", "сливОвый", "оптОвый", "Оптовый"], answer: 0, rule: "Правильно: слИвовый. Это слово часто встречается в орфоэпическом минимуме." }, { q: "В каком слове ударение поставлено верно?", options: ["шАрфы", "шарфЫ", "бантЫ", "бАнты"], answer: 0, rule: "Правильно: шАрфы. В формах множественного числа ударение сохраняется на первом слоге: шАрфы, шАрфов." }, { q: "В каком слове ударение поставлено верно?", options: ["дОсуха", "досУха", "зАсветло", "засветлО"], answer: 1, rule: "Правильно: досУха. Наречие нужно запомнить как орфоэпическую норму." }, { q: "В каком слове ударение поставлено верно?", options: ["нАчал", "начАл", "прИбыл", "прибЫл"], answer: 1, rule: "Правильно: начАл. В форме мужского рода прошедшего времени ударение падает на последний слог." }, { q: "В каком слове ударение поставлено верно?", options: ["свЁкла", "свеклА", "щавЕль", "щАвель"], answer: 0, rule: "Правильно: свЁкла. Ударение в этом слове падает на первый слог." }, { q: "В каком слове ударение поставлено верно?", options: ["цепОчка", "цЕпочка", "мозаИчный", "мозАичный"], answer: 1, rule: "Правильно: цЕпочка. В слове цепочка ударение падает на первый слог." }, { q: "В каком слове ударение поставлено верно?", options: ["мЕстностей", "местностЕй", "новостЕй", "нОвостей"], answer: 0, rule: "Правильно: мЕстностей. В форме родительного падежа множественного числа ударение остается на первом слоге." }, { q: "В каком слове ударение поставлено верно?", options: ["плодоносИть", "плодонОсить", "исчЕрпать", "исчерпАть"], answer: 0, rule: "Правильно: плодоносИть. Ударение падает на И в инфинитиве." }, { q: "В каком слове ударение поставлено верно?", options: ["квартАл", "квАртал", "премировАть", "премИровать"], answer: 0, rule: "Правильно: квартАл. Во всех значениях слова ударение падает на последний слог." }, { q: "В каком слове ударение поставлено верно?", options: ["лгалА", "лгАла", "клАла", "клалА"], answer: 0, rule: "Правильно: лгалА. В форме женского рода прошедшего времени ударение обычно переходит на окончание." } ] }, grammar: { label: "Грамматика", short: "Грамматика", description: "Найди грамматически правильный вариант.", tasks: [ { q: "Выбери предложение без грамматической ошибки.", options: [ "По приезду в город мы сразу отправились в музей.", "По приезде в город мы сразу отправились в музей.", "Благодаря дождя трава быстро выросла.", "Согласно приказа занятия перенесли." ], answer: 1, rule: "Правильно: по приезде. Производные предлоги по приезде, по окончании, по прибытии требуют предложного падежа." }, { q: "Где правильно построено предложение с деепричастным оборотом?", options: [ "Возвращаясь домой, начался сильный дождь.", "Читая книгу, мне вспомнилось лето.", "Возвращаясь домой, я попал под сильный дождь.", "Подъезжая к станции, у меня слетела шляпа." ], answer: 2, rule: "Действие деепричастия и сказуемого должен выполнять один субъект: я возвращался и я попал." }, { q: "Выбери правильную форму согласования.", options: [ "Пять учеников пришло на консультацию.", "Пять учеников пришли на консультацию.", "Большинство ребят решили задачу.", "Большинство ребят решила задачу." ], answer: 2, rule: "Собирательное слово большинство с зависимым словом во множественном числе часто согласуется по смыслу: большинство ребят решили." }, { q: "В каком предложении нет ошибки в управлении?", options: [ "Уделять внимание на детали.", "Оплатить за проезд.", "Рецензия на книгу.", "Превосходство над соперника." ], answer: 2, rule: "Правильно: рецензия на книгу. Запоминаем управление: уделять внимание деталям, оплатить проезд, превосходство над соперником." }, { q: "Выбери грамматически верное предложение.", options: [ "Все, кто пришел на лекцию, получили конспект.", "Все, кто пришли на лекцию, получили конспект.", "Те, кто опоздал, был предупрежден.", "Каждый, кто участвовали, получил диплом." ], answer: 0, rule: "При местоимении кто сказуемое обычно стоит в единственном числе: кто пришел, кто опоздал." }, { q: "Где правильно употреблена форма числительного?", options: [ "С обоими подругами мы встретились вечером.", "С обеими подругами мы встретились вечером.", "К двумстам пятидесяти учеников обратились организаторы.", "Обоим сестрам подарили книги." ], answer: 1, rule: "С существительными женского рода употребляется обе: обеими подругами, обеим сестрам." }, { q: "Выбери предложение без речевой избыточности.", options: [ "В апреле месяце началась подготовка.", "Главная суть текста понятна.", "Подготовка началась в апреле.", "Он заранее предвидел результат." ], answer: 2, rule: "Апрель уже месяц, суть уже главная по смыслу, предвидеть можно только заранее. Лишние слова создают плеоназм." }, { q: "Где верно оформлена связь между частями сложного предложения?", options: [ "Я понял то, что задание требует внимательности.", "Я понял, что задание требует внимательности.", "Автор утверждает о том, что природа нуждается в защите.", "Докладчик отметил то, что результаты важны." ], answer: 1, rule: "После понял достаточно союза что. Лишнее указательное слово то часто нарушает норму или делает фразу тяжеловесной." }, { q: "Выбери правильный вариант.", options: [ "Согласно расписанию экзамен начнется в десять.", "Согласно расписания экзамен начнется в десять.", "Вопреки прогноза день был ясным.", "Наперекор ожиданий команда победила." ], answer: 0, rule: "Предлоги согласно, вопреки, наперекор требуют дательного падежа: расписанию, прогнозу, ожиданиям." }, { q: "Где правильно построено предложение с однородными членами?", options: [ "Мы любим и интересуемся литературой.", "Он не только прочитал текст, но и сделал план.", "Учитель объяснил и помог ученикам.", "Роман учит и заставляет задуматься о выборе." ], answer: 1, rule: "В двойном союзе не только..., но и... части должны соединять грамматически однородные действия: прочитал и сделал." }, { q: "Выбери предложение без грамматической ошибки.", options: [ "Благодаря поддержке учителя ученики справились с заданием.", "Благодаря поддержки учителя ученики справились с заданием.", "Вследствие снегопадами дороги закрыли.", "По окончанию урока класс вышел." ], answer: 0, rule: "Предлог благодаря требует дательного падежа: благодаря поддержке. Правильно также: по окончании урока." }, { q: "Где правильно построено предложение с причастным оборотом?", options: [ "Дом, стоящий у реки, был построен недавно.", "Стоящий у реки дом был построенный недавно.", "Дом был построен недавно, стоящий у реки.", "У реки дом, построенный был недавно." ], answer: 0, rule: "Причастный оборот должен относиться к определяемому слову и быть грамматически согласован с ним." }, { q: "Выбери правильный вариант управления.", options: [ "Уверенность в победе помогла команде.", "Уверенность о победе помогла команде.", "Преимущество перед соперника было очевидным.", "Характеристика на ученика была подробной." ], answer: 0, rule: "Правильно: уверенность в победе. Нормы управления нужно запоминать словосочетаниями." }, { q: "Где нет ошибки в употреблении паронима?", options: [ "Дипломатичный ответ помог избежать спора.", "Дипломатический человек внимательно слушал.", "Эффектная работа прибора была проверена.", "Экономический расход топлива снизился." ], answer: 0, rule: "Дипломатичный значит тактичный. Дипломатический относится к дипломатии как сфере деятельности." }, { q: "Выбери грамматически верное предложение.", options: [ "Оба берега реки заросли камышом.", "Обе берега реки заросли камышом.", "Обоими ученицами гордился класс.", "Обеим братьям поручили проект." ], answer: 0, rule: "С существительными мужского рода употребляется оба: оба берега. С женским родом - обе." }, { q: "Где правильно построено предложение с косвенной речью?", options: [ "Учитель сказал, что завтра мы пишем работу.", "Учитель сказал, что завтра мы пишете работу.", "Учитель сказал то, что завтра пишем работу.", "Учитель сказал, завтра мы пишем работу." ], answer: 0, rule: "В косвенной речи сохраняется грамматическая связь: учитель сказал, что мы пишем." }, { q: "Выбери предложение без ошибки в согласовании.", options: [ "На столе лежали журнал и две тетради.", "На столе лежало журнал и две тетради.", "Никто из участников не были против.", "Часть учеников опоздали из-за пробки." ], answer: 0, rule: "При однородных подлежащих сказуемое обычно ставится во множественном числе: лежали журнал и тетради." }, { q: "Где нет нарушения лексической сочетаемости?", options: [ "Играть важную роль в проекте.", "Оказывать роль в проекте.", "Иметь большое значение роль.", "Нести важную роль в проекте." ], answer: 0, rule: "Норма: играть роль, иметь значение, оказывать влияние. Смешение устойчивых сочетаний дает речевую ошибку." }, { q: "Выбери правильный вариант.", options: [ "По прибытии поезда пассажиры вышли на платформу.", "По прибытию поезда пассажиры вышли на платформу.", "По завершению проекта команда подвела итоги.", "По приезду делегации началась встреча." ], answer: 0, rule: "В значении 'после чего-либо' употребляется форма предложного падежа: по прибытии, по завершении, по приезде." }, { q: "Где правильно употреблен двойной союз?", options: [ "Не только ученики, но и учителя участвовали в олимпиаде.", "Ученики не только участвовали, а также победили.", "Не только текст был прочитан, но и составили план.", "Он как прочитал правило, так и упражнение." ], answer: 0, rule: "Части двойного союза должны соединять однородные элементы: не только ученики, но и учителя." } ] }, spelling: { label: "Орфография", short: "Орфография", description: "Выбери слово или ряд с правильным написанием.", tasks: [ { q: "В каком ряду во всех словах пишется буква И?", options: [ "пр..оритет, бл..стать, зам..реть", "соб..раться, выж..гать, ст..рать", "пр..мирить друзей, пр..клонить ветку, пр..бывать в город", "расст..лать, зап..рать, выт..реть" ], answer: 1, rule: "СобИраться, выжИгать, стИрать: в корнях с чередованием пишется И, если после корня есть суффикс А." }, { q: "Где НЕ со словом пишется слитно?", options: [ "(не)прочитанная мной книга", "далеко (не)легкое решение", "(не)высокий, а низкий дом", "(не)глубокая речка" ], answer: 3, rule: "Неглубокая пишется слитно, если нет противопоставления с а и зависимых усилителей отрицания; можно заменить синонимом мелкая." }, { q: "В каком слове пишется НН?", options: ["кожа..ый", "глиня..ый", "стари..ый", "серебря..ый"], answer: 2, rule: "Старинный пишется с НН. В прилагательных с суффиксом -инн- пишутся две Н." }, { q: "Выбери правильное написание приставки.", options: ["пребывать дверь", "приувеличить значение", "преодолеть препятствие", "преклеить марку"], answer: 2, rule: "Преодолеть пишется с ПРЕ в значении высокой степени или близости к пере-. Приклеить, прибывать, приувеличить пишутся иначе по смыслу." }, { q: "В каком ряду во всех словах пропущена одна и та же буква?", options: [ "без..нициативный, пред..юльский, сверх..нтересный", "раз..скать, под..грать, сверх..зысканный", "пред..стория, без..дейный, под..тожить", "меж..нститутский, фин..нспектор, спорт..гра" ], answer: 1, rule: "После русских приставок на согласную И в корне часто меняется на Ы: разЫскать, подЫграть, сверхЫзысканный." }, { q: "Где на месте пропуска пишется Ь?", options: ["стереч..", "много туч..", "замуж..", "невтерпеж.."], answer: 0, rule: "В неопределенной форме глагола после шипящих пишется мягкий знак: стеречь, беречь, печь." }, { q: "Выбери слово с буквой О после шипящей.", options: ["ш..рох", "ж..лтый", "ч..рный", "ш..пот"], answer: 0, rule: "Шорох пишется через О. В корне после шипящих под ударением часто пишется Ё, если можно подобрать форму с Е: желтый - желтеть." }, { q: "В каком слове пишется суффикс -ИВ-?", options: ["милост..вый", "алюмини..вый", "лен..вый", "улыбч..вый"], answer: 2, rule: "Ленивый пишется с -ив-. Суффиксы -ив-, -ев- зависят от ударения и традиционного написания: милостивый, алюминиевый, улыбчивый." }, { q: "Где все слова пишутся через дефис?", options: [ "по(русски), кое(кто), еле(еле)", "все(таки), точь(в)точь, бок(о)бок", "по(новому) мосту, когда(нибудь), пол(лимона)", "пол(Европы), супер(игра), из(за)" ], answer: 0, rule: "По-русски, кое-кто, еле-еле пишутся через дефис. В других рядах есть слитные или раздельные написания." }, { q: "В каком слове пишется буква Е?", options: ["вытерп..шь", "кле..щий", "бор..шься", "завис..мый"], answer: 2, rule: "Борешься пишется через Е: глагол бороться относится к I спряжению. Клеящий и зависимый связаны со II спряжением." }, { q: "В каком ряду во всех словах пишется буква А?", options: [ "к..снуться, заг..релый, р..сток", "изл..гать, прик..саться, пл..вец", "р..стение, выр..щенный, ск..кать", "пол..жение, предл..гать, з..ря" ], answer: 2, rule: "Растение, выращенный, скакать пишутся с А по правилам корней с чередованием." }, { q: "Где во всех словах пишется приставка ПРИ-?", options: [ "пр..брежный, пр..клеить, пр..открыть", "пр..красный, пр..одолеть, пр..ступить закон", "пр..дать значение, пр..зидент, пр..града", "пр..бывать в восторге, пр..творить мечту, пр..емник" ], answer: 0, rule: "ПРИ- пишется в значениях близости, присоединения и неполноты действия: прибрежный, приклеить, приоткрыть." }, { q: "В каком слове пишется одна буква Н?", options: ["ветре..ый", "безветре..ый", "листве..ый", "торжестве..ый"], answer: 0, rule: "Ветреный пишется с одной Н. Но в слове безветренный появляется приставка и пишется НН." }, { q: "Где все слова пишутся слитно?", options: [ "(в)следствие болезни, (на)встречу другу, (в)течение часа", "(по)этому пути, (за)то здание, (в)виду дождя", "(не)смотря на дождь, (в)следствие ошибки, (на)подобие шара", "(из)под стола, (по)над рекой, (кое)кто" ], answer: 2, rule: "Несмотря на, вследствие, наподобие пишутся слитно как производные предлоги." }, { q: "В каком слове на месте пропуска пишется буква Ы?", options: ["пред..стория", "меж..нститутский", "дез..нформация", "сверх..нтересный"], answer: 0, rule: "После русских приставок на согласную И меняется на Ы: предыстория. После меж-, сверх- сохраняется И." }, { q: "Где НЕ пишется раздельно?", options: [ "(не)лепый поступок", "(не)широкая дорога", "вовсе (не)интересный фильм", "(не)громкий голос" ], answer: 2, rule: "С усилителями отрицания вовсе не, далеко не, отнюдь не прилагательное пишется с НЕ раздельно." }, { q: "В каком слове пишется буква О?", options: ["деш..вый", "ш..лковый", "крыж..вник", "реш..тка"], answer: 2, rule: "Крыжовник пишется через О. Это словарное слово после шипящей." }, { q: "Где все слова пишутся с Ъ?", options: [ "об..явление, под..езд, с..емка", "в..юга, солов..и, обез..яна", "двух..ярусный, пред..юбилейный, меж..языковой", "сверх..естественный, п..еса, ад..ютант" ], answer: 0, rule: "Разделительный Ъ пишется после приставки на согласную перед Е, Ё, Ю, Я: объявление, подъезд, съемка." }, { q: "В каком ряду во всех словах пишется суффикс -ЕК-?", options: [ "замоч..к, кусоч..к, дружоч..к", "ключ..к, листоч..к, овраж..к", "сыноч..к, платоч..к, кирпич..к", "ореш..к, веноч..к, комоч..к" ], answer: 2, rule: "Суффикс -ек- пишется, если при изменении слова гласная выпадает: сыночек - сыночка, платочек - платочка." }, { q: "Где во всех словах пропущена буква И?", options: [ "та..щий снег, стро..мый дом, слыш..мый звук", "вид..мый берег, завис..щий от погоды, бор..щийся ученик", "кле..щий карандаш, ненавид..щий ложь, дыш..щий ровно", "колебл..мый ветром, знач..мый результат, чита..мый текст" ], answer: 2, rule: "Клеящий, ненавидящий, дышащий связаны с формами II спряжения или исключениями, поэтому пишется И/Я по правилу причастий." } ] } }; const ROUND_SIZE = 20; const BANK_SIZE = 500; const generatedPools = { stress: { correct: [ ["красИвее", "В сравнительной степени прилагательного ударение сохраняется: красИвый - красИвее."], ["звонИт", "В формах глагола звонить ударение падает на окончание: звонИшь, звонИт."], ["кухОнный", "Норма: кухОнный."], ["тОрты", "В формах слова торт ударение остается на первом слоге: тОрты, тОртов."], ["начАв", "В деепричастии начАв ударение падает на последний слог."], ["бАлованный", "Норма: бАлованный, но баловАть."], ["диспансЕр", "В слове диспансЕр ударение падает на последний слог."], ["жалюзИ", "Слово жалюзИ несклоняемое, ударение на последнем слоге."], ["вероисповЕдание", "Норма: вероисповЕдание."], ["ободрИть", "В инфинитиве ободрИть ударение падает на И."], ["слИвовый", "Норма: слИвовый."], ["шАрфы", "Ударение сохраняется на первом слоге: шАрфы."], ["досУха", "Норма: досУха."], ["начАл", "В форме мужского рода прошедшего времени: начАл."], ["свЁкла", "Норма: свЁкла."], ["цЕпочка", "В слове цЕпочка ударение на первом слоге."], ["мЕстностей", "В форме родительного падежа множественного числа: мЕстностей."], ["плодоносИть", "В инфинитиве плодоносИть ударение падает на И."], ["квартАл", "Во всех значениях слова квартАл ударение на последнем слоге."], ["лгалА", "В форме женского рода прошедшего времени: лгалА."], ["каталОг", "Норма: каталОг."], ["щавЕль", "Норма: щавЕль."], ["докумЕнт", "Норма: докумЕнт."], ["экспЕрт", "Норма: экспЕрт."], ["цемЕнт", "Норма: цемЕнт."], ["позвонИт", "В глаголах звонИть, позвонИть ударение падает на окончание."], ["облегчИть", "Норма: облегчИть."], ["укрепИт", "В форме укрепИт ударение падает на И."], ["принЯтый", "Норма: принЯтый."], ["занялА", "В форме женского рода прошедшего времени: занялА."], ["созЫв", "Норма: созЫв."], ["нОгтя", "Норма: нОгтя."], ["сИроты", "Норма: сИроты."], ["намЕрение", "Норма: намЕрение."], ["дОнизу", "Норма: дОнизу."], ["зАсветло", "Норма: зАсветло."], ["опОшлить", "Норма: опОшлить."], ["приручЁнный", "В причастии приручЁнный ударение падает на Ё."], ["снятА", "В кратком причастии женского рода: снятА."], ["вручИт", "Норма: вручИт."] ], wrong: ["дОговор", "звОнит", "катАлог", "тортЫ", "нАчав", "балОванный", "диспАнсер", "жАлюзи", "вероисповедАние", "обОдрить", "сливОвый", "шарфЫ", "дОсуха", "нАчал", "свеклА", "цепОчка", "местностЕй", "плодонОсить", "квАртал", "лгАла", "щАвель", "дОкумент", "Эксперт", "цЕмент", "позвОнит", "облЕгчить", "укрЕпит", "прИнятый", "зАняла", "сОзыв"] }, grammar: { correct: [ ["По приезде в город мы сразу отправились в музей.", "После предлога по в значении 'после' нужна форма предложного падежа: по приезде."], ["Возвращаясь домой, я попал под сильный дождь.", "Действие деепричастия и сказуемого выполняет один субъект."], ["Рецензия на книгу оказалась подробной.", "Норма управления: рецензия на книгу."], ["Все, кто пришел на лекцию, получили конспект.", "При местоимении кто сказуемое обычно стоит в единственном числе."], ["С обеими подругами мы встретились вечером.", "С существительными женского рода употребляется обе."], ["Подготовка началась в апреле.", "В предложении нет речевой избыточности."], ["Я понял, что задание требует внимательности.", "Союза что достаточно, лишнее указательное слово не нужно."], ["Согласно расписанию экзамен начнется в десять.", "Предлог согласно требует дательного падежа."], ["Он не только прочитал текст, но и сделал план.", "Части двойного союза соединяют однородные действия."], ["Дом, стоящий у реки, был построен недавно.", "Причастный оборот согласован с определяемым словом."], ["Уверенность в победе помогла команде.", "Норма управления: уверенность в чем-либо."], ["Дипломатичный ответ помог избежать спора.", "Дипломатичный значит тактичный."], ["Оба берега реки заросли камышом.", "С существительными мужского рода употребляется оба."], ["Учитель сказал, что завтра мы пишем работу.", "Косвенная речь оформлена грамматически верно."], ["На столе лежали журнал и две тетради.", "При однородных подлежащих сказуемое обычно ставится во множественном числе."], ["Играть важную роль в проекте.", "Норма лексической сочетаемости: играть роль."], ["По прибытии поезда пассажиры вышли на платформу.", "Правильно: по прибытии."], ["Не только ученики, но и учителя участвовали в олимпиаде.", "Двойной союз соединяет однородные элементы."], ["Благодаря поддержке учителя ученики справились с заданием.", "Предлог благодаря требует дательного падежа."], ["Большинство ребят решили задачу.", "Возможна форма множественного числа при согласовании по смыслу."] ], wrong: [ "По приезду в город мы сразу отправились в музей.", "Возвращаясь домой, начался сильный дождь.", "Уделять внимание на детали.", "Все, кто пришли на лекцию, получили конспект.", "С обоими подругами мы встретились вечером.", "В апреле месяце началась подготовка.", "Я понял то, что задание требует внимательности.", "Согласно расписания экзамен начнется в десять.", "Мы любим и интересуемся литературой.", "Дом был построен недавно, стоящий у реки.", "Уверенность о победе помогла команде.", "Дипломатический человек внимательно слушал.", "Обе берега реки заросли камышом.", "Учитель сказал, завтра мы пишем работу.", "На столе лежало журнал и две тетради.", "Оказывать роль в проекте.", "По прибытию поезда пассажиры вышли на платформу.", "Ученики не только участвовали, а также победили.", "Благодаря поддержки учителя ученики справились с заданием.", "Большинство ребят решила задачу.", "Оплатить за проезд нужно заранее.", "Превосходство над соперника было заметным.", "Каждый, кто участвовали, получил диплом.", "По окончанию урока класс вышел.", "Автор утверждает о том, что природа нуждается в защите.", "Вопреки прогноза день был ясным.", "Подъезжая к станции, у меня слетела шляпа.", "Главная суть текста понятна.", "Он заранее предвидел результат.", "Обеим братьям поручили проект." ] }, spelling: { correct: [ ["собираться, выжигать, стирать", "В корнях с чередованием пишется И, если после корня есть суффикс А."], ["неглубокая речка", "НЕ пишется слитно, если слово можно заменить синонимом и нет противопоставления."], ["старинный", "В прилагательных с суффиксом -инн- пишется НН."], ["преодолеть препятствие", "ПРЕ- пишется в значении близости к пере- или высокой степени."], ["разыскать, подыграть, сверхызысканный", "После русских приставок на согласную И часто меняется на Ы."], ["стеречь", "В неопределенной форме глагола после шипящих пишется Ь."], ["шорох", "Шорох пишется через О."], ["ленивый", "В слове ленивый пишется суффикс -ив-."], ["по-русски, кое-кто, еле-еле", "Эти слова пишутся через дефис."], ["борешься", "Глагол бороться относится к I спряжению: борешься."], ["растение, выращенный, скакать", "В корнях с чередованием здесь пишется А."], ["прибрежный, приклеить, приоткрыть", "ПРИ- пишется в значениях близости, присоединения и неполноты действия."], ["ветреный", "Ветреный пишется с одной Н."], ["несмотря на дождь, вследствие ошибки, наподобие шара", "Эти производные предлоги пишутся слитно."], ["предыстория", "После русской приставки на согласную И меняется на Ы."], ["вовсе не интересный фильм", "При усилителе отрицания вовсе не пишется раздельно."], ["крыжовник", "Крыжовник пишется через О."], ["объявление, подъезд, съемка", "Разделительный Ъ пишется после приставки на согласную перед Е, Ё, Ю, Я."], ["сыночек, платочек, кирпичик", "Суффиксы -ек-/-ик- проверяются выпадением гласной."], ["клеящий, ненавидящий, дышащий", "В причастиях учитывается спряжение и исключения."] ], wrong: [ "преоритет, блестать, замиреть", "не прочитанная книга без зависимых слов", "кожанный", "преклеить марку", "предистория", "много тучь", "жолтый", "алюминиивый", "все таки, кое кто, еле еле", "клеющий", "коснуться, загарелый, росток", "прекрасный, преодолеть, преступление", "безветреный", "в течении часа как предлог", "межынститутский", "вовсе неинтересный фильм", "дешовый", "въюга", "замочик", "борящийся", "пол лимона", "из под стола", "невысокий, а низкий дом", "серебрянный", "пребывать дверь", "подитожить", "замужь", "шопот", "улыбчевый", "вытерпишь как форма I спряжения" ] } }; function orderedOptions(correct, wrongPool, offset) { const options = [correct]; let cursor = offset; while (options.length < 4) { const candidate = wrongPool[cursor % wrongPool.length]; if (!options.includes(candidate)) options.push(candidate); cursor += 1; } const shift = offset % options.length; const rotated = options.slice(shift).concat(options.slice(0, shift)); return { options: rotated, answer: rotated.indexOf(correct) }; } function generatedTaskFor(categoryKey, index) { const pool = generatedPools[categoryKey]; const correct = pool.correct[index % pool.correct.length]; const built = orderedOptions(correct[0], pool.wrong, index * 3 + Math.floor(index / pool.correct.length)); const labels = { stress: "В каком слове ударение поставлено верно?", grammar: "Выбери грамматически правильный вариант.", spelling: "Выбери правильное написание." }; return { q: `${labels[categoryKey]} Карточка ${index + 1}.`, options: built.options, answer: built.answer, rule: `Правильно: ${correct[0]}. ${correct[1]}` }; } function fillQuestionBank() { Object.entries(bank).forEach(([categoryKey, category]) => { let index = 0; while (category.tasks.length < BANK_SIZE) { category.tasks.push(generatedTaskFor(categoryKey, index)); index += 1; } category.tasks = category.tasks.slice(0, BANK_SIZE); }); } fillQuestionBank(); const state = { category: "stress", mode: "train", index: 0, selected: null, answered: false, examFinished: false, examAnswers: [], questionOrder: [], mistakes: [], stats: JSON.parse(localStorage.getItem("egeRussianStats") || '{"total":0,"correct":0,"streak":0,"byCategory":{}}') }; const els = { nav: document.getElementById("categoryNav"), trainMode: document.getElementById("trainMode"), examMode: document.getElementById("examMode"), progressBar: document.getElementById("progressBar"), progressText: document.getElementById("progressText"), categoryPill: document.getElementById("categoryPill"), taskNumber: document.getElementById("taskNumber"), questionText: document.getElementById("questionText"), questionHint: document.getElementById("questionHint"), options: document.getElementById("options"), feedback: document.getElementById("feedback"), examSummary: document.getElementById("examSummary"), nextBtn: document.getElementById("nextBtn"), restartBtn: document.getElementById("restartBtn"), mistakes: document.getElementById("mistakes"), statTotal: document.getElementById("statTotal"), statAccuracy: document.getElementById("statAccuracy"), statStreak: document.getElementById("statStreak"), statBest: document.getElementById("statBest") }; function sourceTasks() { return bank[state.category].tasks; } function shuffle(items) { const mixed = [...items]; for (let index = mixed.length - 1; index > 0; index -= 1) { const swapIndex = Math.floor(Math.random() * (index + 1)); [mixed[index], mixed[swapIndex]] = [mixed[swapIndex], mixed[index]]; } return mixed; } function buildQuestionOrder() { state.questionOrder = shuffle(sourceTasks().map((_, index) => index)).slice(0, ROUND_SIZE); } function currentTasks() { if (state.questionOrder.length !== Math.min(ROUND_SIZE, sourceTasks().length)) buildQuestionOrder(); return state.questionOrder.map(index => sourceTasks()[index]); } function currentTask() { return currentTasks()[state.index]; } function saveStats() { localStorage.setItem("egeRussianStats", JSON.stringify(state.stats)); } function updateNav() { els.nav.innerHTML = ""; Object.entries(bank).forEach(([key, category]) => { const btn = document.createElement("button"); btn.className = "nav-btn" + (key === state.category ? " active" : ""); btn.type = "button"; btn.innerHTML = `<strong>${category.label}</strong><span class="count">${ROUND_SIZE}/${category.tasks.length}</span>`; btn.addEventListener("click", () => switchCategory(key)); els.nav.appendChild(btn); }); } function switchCategory(key) { state.category = key; resetRound(); } function setMode(mode) { state.mode = mode; els.trainMode.classList.toggle("active", mode === "train"); els.examMode.classList.toggle("active", mode === "exam"); resetRound(); } function resetRound() { state.index = 0; state.selected = null; state.answered = false; state.examFinished = false; state.examAnswers = []; buildQuestionOrder(); els.examSummary.classList.remove("show"); render(); } function answer(optionIndex) { if (state.answered || state.examFinished) return; state.selected = optionIndex; state.answered = true; const task = currentTask(); const correct = optionIndex === task.answer; if (state.mode === "train") { recordResult(correct); if (!correct) addMistake(task, optionIndex); } else { state.examAnswers[state.index] = { selected: optionIndex, correct }; } renderOptions(); renderFeedback(correct); els.nextBtn.disabled = false; } function recordResult(correct) { state.stats.total += 1; state.stats.correct += correct ? 1 : 0; state.stats.streak = correct ? state.stats.streak + 1 : 0; const entry = state.stats.byCategory[state.category] || { total: 0, correct: 0 }; entry.total += 1; entry.correct += correct ? 1 : 0; state.stats.byCategory[state.category] = entry; saveStats(); updateStats(); } function addMistake(task, selected) { state.mistakes.unshift({ category: bank[state.category].short, q: task.q, chosen: task.options[selected], right: task.options[task.answer], rule: task.rule }); state.mistakes = state.mistakes.slice(0, 7); renderMistakes(); } function next() { if (state.examFinished) { resetRound(); return; } if (!state.answered) return; if (state.index < currentTasks().length - 1) { state.index += 1; state.selected = null; state.answered = false; els.nextBtn.disabled = true; render(); return; } if (state.mode === "exam") finishExam(); else resetRound(); } function finishExam() { if (state.examFinished) return; state.examFinished = true; let correctCount = 0; currentTasks().forEach((task, index) => { const result = state.examAnswers[index]; const correct = Boolean(result && result.correct); correctCount += correct ? 1 : 0; recordResult(correct); if (!correct && result) addMistake(task, result.selected); }); els.examSummary.className = "exam-summary show"; els.examSummary.innerHTML = `<strong>Экзамен завершен: ${correctCount} из ${currentTasks().length}.</strong><br>${examAdvice(correctCount)}`; els.nextBtn.textContent = "Повторить"; els.nextBtn.disabled = false; state.answered = true; } function examAdvice(correctCount) { const ratio = correctCount / currentTasks().length; if (ratio >= .9) return "Отличный уровень. Теперь полезно идти в смешанный вариант и тренировать скорость."; if (ratio >= .7) return "База крепкая. Разбери ошибки справа и повтори этот раздел еще один круг."; return "Стоит пройти раздел в режиме тренировки: объяснения после каждого ответа помогут быстрее закрыть пробелы."; } function render() { updateNav(); updateStats(); renderMistakes(); const task = currentTask(); const category = bank[state.category]; els.categoryPill.textContent = category.label; els.taskNumber.textContent = `Задание ${state.index + 1}`; els.questionText.textContent = task.q; els.questionHint.textContent = category.description; els.progressText.textContent = `Вопрос ${state.index + 1} из ${currentTasks().length}`; els.progressBar.style.width = `${((state.index + 1) / currentTasks().length) * 100}%`; els.feedback.className = "feedback"; els.feedback.textContent = ""; els.examSummary.classList.remove("show"); els.nextBtn.textContent = state.index === currentTasks().length - 1 ? (state.mode === "exam" ? "Завершить" : "Заново") : "Следующее"; els.nextBtn.disabled = !state.answered; renderOptions(); } function renderOptions() { const task = currentTask(); els.options.innerHTML = ""; task.options.forEach((option, index) => { const btn = document.createElement("button"); btn.className = "option"; btn.type = "button"; btn.textContent = `${index + 1}. ${option}`; if (state.answered) { const showCorrect = state.mode === "train" || state.examFinished; if (showCorrect && index === task.answer) btn.classList.add("correct"); if (index === state.selected && index !== task.answer) btn.classList.add("wrong"); } btn.addEventListener("click", () => answer(index)); els.options.appendChild(btn); }); } function renderFeedback(correct) { if (state.mode === "exam") { els.feedback.className = "feedback show"; els.feedback.textContent = "Ответ принят. Разбор появится после завершения экзамена."; return; } const task = currentTask(); els.feedback.className = `feedback show ${correct ? "good" : "bad"}`; els.feedback.innerHTML = `<strong>${correct ? "Верно." : "Есть ошибка."}</strong> ${task.rule}`; } function renderMistakes() { if (!state.mistakes.length) { els.mistakes.innerHTML = '<div class="empty">Пока ошибок нет. Хороший момент набрать серию правильных ответов.</div>'; return; } els.mistakes.innerHTML = state.mistakes.map(item => ` <div class="mistake-item"> <strong>${item.category}: ${item.right}</strong> <span>Было выбрано: ${item.chosen}</span> <span>${item.rule}</span> </div> `).join(""); } function updateStats() { const accuracy = state.stats.total ? Math.round((state.stats.correct / state.stats.total) * 100) : 0; const best = Object.entries(state.stats.byCategory) .filter(([, value]) => value.total > 0) .sort((a, b) => (b[1].correct / b[1].total) - (a[1].correct / a[1].total))[0]; els.statTotal.textContent = state.stats.total; els.statAccuracy.textContent = `${accuracy}%`; els.statStreak.textContent = state.stats.streak; els.statBest.textContent = best ? bank[best[0]].short : "-"; } els.trainMode.addEventListener("click", () => setMode("train")); els.examMode.addEventListener("click", () => setMode("exam")); els.nextBtn.addEventListener("click", () => { next(); }); els.restartBtn.addEventListener("click", resetRound); document.addEventListener("keydown", event => { const number = Number(event.key); if (number >= 1 && number <= 4) answer(number - 1); if (event.key === "Enter" && !els.nextBtn.disabled) next(); }); render(); </script> </body> </html>