feat: add excises solver

This commit is contained in:
MasterAkulon 2026-03-27 10:40:45 +03:00
parent cc3e2c1b10
commit de58fa6687

162
script.js
View file

@ -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();
}
})();