From 17c1d971d4508f4c4a8871861a760f0e7bd2d6cf Mon Sep 17 00:00:00 2001 From: MasterAkulon Date: Fri, 27 Mar 2026 11:17:15 +0300 Subject: [PATCH] feat: complete try coding --- script.js | 156 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 119 insertions(+), 37 deletions(-) diff --git a/script.js b/script.js index 847da9a..71a4125 100644 --- a/script.js +++ b/script.js @@ -60,6 +60,37 @@ return false; } + function findCodingQuiz() { + const quizzes = document.querySelectorAll('section.quiz_type_coding'); + for (const quiz of quizzes) { + if (handledQuizzes.has(quiz)) continue; + if (quiz.classList.contains('quiz_answered')) { handledQuizzes.add(quiz); continue; } + const runBtn = quiz.querySelector('button.quiz__coding-footer-action-button'); + if (!runBtn) { handledQuizzes.add(quiz); continue; } + if (quiz.offsetParent !== null) return quiz; + } + return null; + } + + async function handleCodingQuiz(quiz) { + console.log('💻 Квиз с кодом — запускаем...'); + const runBtn = quiz.querySelector('button.quiz__coding-footer-action-button'); + runBtn.click(); + + // Ждём пока квиз пометится как решённый + const startTime = Date.now(); + while (Date.now() - startTime < 60000) { + await sleep(CHECK_INTERVAL); + if (quiz.classList.contains('quiz_answered') || !quiz.querySelector('button.quiz__coding-footer-action-button')) { + console.log('✓ Код выполнен'); + break; + } + } + handledQuizzes.add(quiz); + await sleep(CLICK_DELAY); + return true; + } + function findQuizForm() { const forms = document.querySelectorAll(QUIZ_FORM_SELECTOR); for (const form of forms) { @@ -184,11 +215,20 @@ async function handleQuizForm(form) { console.log('❓ Квиз...'); - const firstRadio = form.querySelector('input[type="radio"]'); - if (firstRadio) { - firstRadio.click(); - console.log('✓ Выбран первый вариант'); - await sleep(300); + const checkboxes = form.querySelectorAll('input[type="checkbox"]'); + if (checkboxes.length > 0) { + for (const cb of checkboxes) { + if (!cb.checked) cb.click(); + await sleep(100); + } + console.log(`✓ Выбраны все чекбоксы (${checkboxes.length})`); + } else { + const firstRadio = form.querySelector('input[type="radio"]'); + if (firstRadio) { + firstRadio.click(); + console.log('✓ Выбран первый вариант'); + await sleep(300); + } } const submitBtn = form.querySelector(QUIZ_SUBMIT_SELECTOR); @@ -228,6 +268,9 @@ while (Date.now() - startTime < timeout) { if (!isRunning) return null; + const codingQuiz = findCodingQuiz(); + if (codingQuiz) return { type: 'coding', element: codingQuiz }; + const quiz = findQuizForm(); if (quiz) return { type: 'quiz', element: quiz }; @@ -248,6 +291,14 @@ async function processLesson() { while (isRunning) { + let codingQuiz = findCodingQuiz(); + if (codingQuiz) { + scrollToElement(codingQuiz); + await sleep(300); + await handleCodingQuiz(codingQuiz); + continue; + } + let quiz = findQuizForm(); if (quiz) { scrollToElement(quiz); @@ -280,6 +331,13 @@ return null; } + if (result.type === 'coding') { + scrollToElement(result.element); + await sleep(300); + await handleCodingQuiz(result.element); + continue; + } + if (result.type === 'quiz') { scrollToElement(result.element); await sleep(300); @@ -331,6 +389,7 @@ break; } + await sleep(1000); scrollToElement(nextLessonBtn); await sleep(300); nextLessonBtn.click(); @@ -451,32 +510,35 @@ } async function handleTrainerPage() { - console.log('💡 Загружаем исходник страницы для поиска решения...'); - const answerPanes = await fetchAnswerPanes(); + if (!document.querySelector('button.trainer-footer__solution-button')) { + console.log('💡 Загружаем исходник страницы для поиска решения...'); + const answerPanes = await fetchAnswerPanes(); - if (!answerPanes || answerPanes.length === 0) { - console.log('ℹ️ Авторского решения нет для этой задачи'); - return false; - } + if (!answerPanes || answerPanes.length === 0) { + console.log('ℹ️ Авторского решения нет для этой задачи'); + return false; + } - const solution = answerPanes[0].content; - if (!solution) { - console.log('ℹ️ Контент решения пустой'); - return false; - } + const solution = answerPanes[0].content; + if (!solution) { + console.log('ℹ️ Контент решения пустой'); + return false; + } - console.log(`💡 Найдено решение (${answerPanes[0].name}), вставляем...`); - insertSolutionIntoMonaco(solution); + console.log(`💡 Найдено решение (${answerPanes[0].name}), вставляем...`); + insertSolutionIntoMonaco(solution); + await sleep(CLICK_DELAY); - await sleep(CLICK_DELAY); - - const checkBtn = document.querySelector('button.trainer-footer__check-button'); - if (checkBtn) { - checkBtn.click(); - console.log('✅ Нажата кнопка "Проверить", ждём результата...'); + const checkBtn = document.querySelector('button.trainer-footer__check-button'); + if (checkBtn) { + checkBtn.click(); + console.log('✅ Нажата кнопка "Проверить", ждём результата...'); + } else { + console.log('⚠️ Кнопка "Проверить" не найдена'); + return true; + } } else { - console.log('⚠️ Кнопка "Проверить" не найдена'); - return true; + console.log('ℹ️ Задача уже решена'); } // Ждём кнопку "Далее" без ограничения по времени @@ -495,21 +557,41 @@ return true; } + async function dispatch() { + // Сброс состояния при каждом вызове + isRunning = true; + clickedButtons = new WeakSet(); + handledQuizzes = new WeakSet(); + handledFeedbacks = new WeakSet(); + + const path = window.location.pathname; + console.log(`🔄 Страница: ${path}`); + + if (path.includes('/profile/associated-programs-android-st-v2')) { + const found = handleAssociatedProgramsPage(); + if (found) await handleCourseModal(); + } else if (path.includes('/trainer/') && window.monaco?.editor.getEditors().length > 0) { + await handleTrainerPage(); + } else if (path.includes('/trainer/') || path.includes('/topics/')) { + await run(); + } + } + + // Перехват SPA-навигации + const _pushState = history.pushState.bind(history); + history.pushState = function(...args) { + _pushState(...args); + setTimeout(() => dispatch(), PAGE_LOAD_DELAY); + }; + window.addEventListener('popstate', () => { + setTimeout(() => dispatch(), PAGE_LOAD_DELAY); + }); + window.stopAutoClick = function() { isRunning = false; console.log('⏹ Остановлено'); }; console.log('💡 Для остановки: stopAutoClick()'); - - if (window.location.pathname.includes('/profile/associated-programs-android-st-v2')) { - const found = handleAssociatedProgramsPage(); - if (found) { - await handleCourseModal(); - } - } else if (window.location.pathname.includes('/trainer/') && window.monaco?.editor.getEditors().length > 0) { - await handleTrainerPage(); - } else { - run(); - } + await dispatch(); })(); \ No newline at end of file