From de58fa6687c39b3c8dd64e2b9ca81d5081f86608 Mon Sep 17 00:00:00 2001 From: MasterAkulon Date: Fri, 27 Mar 2026 10:40:45 +0300 Subject: [PATCH] feat: add excises solver --- script.js | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 2 deletions(-) diff --git a/script.js b/script.js index 28b0a43..c4dce03 100644 --- a/script.js +++ b/script.js @@ -1,4 +1,4 @@ -(function autoClickSequential() { +(async function autoClickSequential() { // Настройки const CLICK_DELAY = 800; const CHECK_INTERVAL = 500; @@ -335,11 +335,169 @@ console.log(`🖱️ Кнопок нажато: ${clickCount}`); } + function handleAssociatedProgramsPage() { + const cards = document.querySelectorAll('button.card.course-card'); + for (const card of cards) { + const isCompleted = card.querySelector('.course-card__info-item_active'); + if (!isCompleted) { + const title = card.querySelector('.course-card__title')?.textContent?.trim() || '(без названия)'; + console.log(`🎯 Найдена непройденная программа: "${title}"`); + card.click(); + return true; + } + } + console.log('✅ Все программы пройдены'); + return false; + } + + async function waitForModal() { + return new Promise(resolve => { + const startTime = Date.now(); + const interval = setInterval(() => { + const el = document.querySelector('#portals .skills-modal_visible'); + if (el) { clearInterval(interval); resolve(el); } + else if (Date.now() - startTime > MAX_WAIT_TIME) { clearInterval(interval); resolve(null); } + }, CHECK_INTERVAL); + }); + } + + async function handleCourseModal() { + console.log('🔍 Ищем непройденную тему в модалке...'); + const modal = await waitForModal(); + if (!modal) { console.log('⚠️ Модальное окно не появилось'); return false; } + + // Шаг 1.js: найти и кликнуть первую тему без course-navigation-topic_solved + const topics = modal.querySelectorAll('a.course-navigation-topic'); + let clickedTopic = false; + for (const topic of topics) { + if (!topic.classList.contains('course-navigation-topic_solved')) { + const title = topic.querySelector('.course-navigation-item__title')?.textContent?.trim() || '(без названия)'; + console.log(`📂 Тема: "${title}"`); + topic.click(); + clickedTopic = true; + break; + } + } + if (!clickedTopic) { console.log('✅ Все темы пройдены'); return false; } + + // Шаг 2: ждём пока появятся уроки внутри темы + await sleep(CLICK_DELAY); + const startTime = Date.now(); + let lesson = null; + while (Date.now() - startTime < MAX_WAIT_TIME) { + const lessons = modal.querySelectorAll('a.course-navigation-lesson'); + for (const l of lessons) { + if (!l.classList.contains('course-navigation-lesson_status_solved')) { + lesson = l; + break; + } + } + if (lesson) break; + await sleep(CHECK_INTERVAL); + } + + if (!lesson) { console.log('⚠️ Непройденный урок не найден'); return false; } + + const lessonTitle = lesson.querySelector('.course-navigation-item__title')?.textContent?.trim() || '(без названия)'; + console.log(`📚 Урок: "${lessonTitle}"`); + lesson.click(); + return true; + } + + function insertSolutionIntoMonaco(code) { + const editors = window.monaco.editor.getEditors(); + if (!editors || editors.length === 0) { + console.log('⚠️ Monaco редактор не найден'); + return false; + } + const editor = editors[0]; + const model = editor.getModel(); + if (!model) { + console.log('⚠️ Monaco модель не найдена'); + return false; + } + const fullRange = model.getFullModelRange(); + editor.executeEdits('auto-solution', [{ + range: fullRange, + text: code, + forceMoveMarkers: true, + }]); + editor.focus(); + console.log('✅ Решение вставлено в редактор'); + return true; + } + + async function fetchAnswerPanes() { + const html = await fetch(window.location.href).then(r => r.text()); + const match = html.match(/"answer_panes":(\[.*?\]),"has_author_solution"/); + if (!match) return null; + try { + return JSON.parse(match[1]); + } catch (e) { + return null; + } + } + + async function handleTrainerPage() { + console.log('💡 Загружаем исходник страницы для поиска решения...'); + const answerPanes = await fetchAnswerPanes(); + + if (!answerPanes || answerPanes.length === 0) { + console.log('ℹ️ Авторского решения нет для этой задачи'); + return false; + } + + const solution = answerPanes[0].content; + if (!solution) { + console.log('ℹ️ Контент решения пустой'); + return false; + } + + console.log(`💡 Найдено решение (${answerPanes[0].name}), вставляем...`); + insertSolutionIntoMonaco(solution); + + await sleep(CLICK_DELAY); + + const checkBtn = document.querySelector('button.trainer-footer__check-button'); + if (checkBtn) { + checkBtn.click(); + console.log('✅ Нажата кнопка "Проверить", ждём результата...'); + } else { + console.log('⚠️ Кнопка "Проверить" не найдена'); + return true; + } + + // Ждём кнопку "Далее" без ограничения по времени + let nextBtn = null; + let elapsed = 0; + while (!nextBtn) { + await sleep(CHECK_INTERVAL); + elapsed += CHECK_INTERVAL; + nextBtn = document.querySelector('button.trainer-footer__solution-button'); + if (elapsed % 10000 === 0) { + console.log(`⏳ Ожидаем результат проверки... (${elapsed / 1000}с)`); + } + } + nextBtn.click(); + console.log('➡️ Нажата кнопка "Далее"'); + return true; + } + window.stopAutoClick = function() { isRunning = false; console.log('⏹ Остановлено'); }; console.log('💡 Для остановки: stopAutoClick()'); - run(); + + 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/')) { + await handleTrainerPage(); + } else { + run(); + } })(); \ No newline at end of file