// ==UserScript==
// @name 奥鹏自动答题脚本--基于youngyy版本修改
// @namespace http://tampermonkey.net/
// @version 2022.5.15
// @description 自动从接口获取答案并自动填写[需要答两次(默认全选程序生成的错误答案),生成错题本后才会生效]
// @author hhq
// @require https://code.jquery.com/jquery-3.6.0.js
// @match https://learn.open.com.cn/StudentCenter/OnLineJob/TestPaper*
// @match http://learn.open.com.cn/StudentCenter/MyWork/UndoneWork*
// @license MIT
// @grant none
// ==/UserScript==
// 源代码版本 https://greasyfork.org/zh-CN/scripts/441072-%E5%A5%A5%E9%B9%8F%E8%87%AA%E5%8A%A8%E7%AD%94%E9%A2%98%E8%84%9A%E6%9C%AC
// 基于原作者 youngyy 的源代码修改而来,获取答案的思路很nice
// 添加加了点统计信息,部分提示,默认选择错误答案
// 解决题目相同但选项不同的问题
// 全局问题
let question;
// 错题本
let wrongList = [];
// 错题本中不包含的题
// let okList = [];
let get_point = false;
let getHomework = "homeworkapi.open.com.cn/getHomework";
// 封装ajax
function addXMLRequestCallback(callback) {
let oldSend, i;
if (XMLHttpRequest.callbacks) {
XMLHttpRequest.callbacks.push(callback);
} else {
XMLHttpRequest.callbacks = [callback];
oldSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function () {
for (i = 0; i < XMLHttpRequest.callbacks.length; i++) {
XMLHttpRequest.callbacks[i](this);
}
try {
oldSend.apply(this, arguments);
} catch (e) {
console.log(e);
}
}
}
}
// 获取url参数信息
function getQueryVariable(variable) {
const query = window.location.search.substring(1);
const vars = query.split("&");
for (let i = 0; i < vars.length; i++) {
const pair = vars[i].split("=");
if (pair[0] === variable) {
return pair[1];
}
}
return false;
}
function req(url, callback) {
$.ajax({
url: url,
type: 'GET',
dataType: 'json',
success(data) {
callback(data)
},
error(e) {
log('请求失败,1秒后重新请求.地址' + url);
setTimeout(() => {
req(url, callback);
}, 1000)
}
});
}
// 根据错题本获取正确答案
function initquestion(question) {
//自动答题开始
intiTotal();
$("#total_msg").text("自动答题中,请勿操作...")
// 找出的问题数组
let questionList = question.data.paperInfo.Items;
let wrongGetTotal = 0;
wrongList.forEach(item => {
let bust = (new Date()).getTime();
let t = (new Date()).getTime() + 20;
req(`https://learn.open.com.cn/StudentCenter/OnlineJob/GetQuestionDetail?bust=${bust}&itemBankId=${item.ItemBankId}&questionId=${item.QuestionId}&_=${t}`, (data) => {
wrongGetTotal++;
if (wrongGetTotal >= wrongList.length) {
//自动答题结束
// alert('自动答题结束');
$("#total_msg").text("自动答题结束");
}
if (data.status === 1) {
alert(data.message)
return
}
let wrongData = data.data;
selectRightAnswer(questionList, wrongData)
})
})
}
function selectRightAnswer(questionList, wrongData, isSub) {
const choicesList = wrongData.Choices;
//遍历当前题目,查找该错题
questionList.forEach(row => {
//题目跟错题匹配
if (wrongData.I2 === row.I2 ) {
// 存在子题目
if (row.Sub.length > 0) {
wrongData.Sub.forEach(wrongSub => {
selectRightAnswer(row.Sub, wrongSub, true)
})
}
//无答案
if (choicesList.length <= 0) {
if (!isSub) {
writeTotal++;
showTotal();
}
return;
}
//验证选项也相同
if (identical(wrongData.I6, row.I6)) {
if (!isSub) {
writeTotal++;
showTotal();
}
// console.log('存在的错题')
// console.log(data)
// 获取答案选项
const select = $(`div [itemid="${row.I1}"] li`);
selectRightColor(select, isSub);
// 取消默认选中的 以及包含Choosed 样式的
for (let i = 0; i < select.length; i++) {
if (select.eq(i).hasClass("Choosed")) {
select.eq(i).click()
}
}
// 根据数据判断勾选答案
for (let i = 0; i < choicesList.length; i++) {
if (choicesList[i].IsCorrect) {
select.eq(i).click()
}
}
}
}
})
}
//判断一维数组是否相同
function identical(a, b) {
if (!($.isArray(a) && $.isArray(b) && a.length === b.length)) {
return false;
}
for (let i = 0, len = a.length; i < len; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
//全部选择不存在的答案
function selectError(data) {
let list = (data.answerInfo === "")? data.paperInfo.Items : data.answerInfo.Items;
for (let i = 0, len = list.length; i < len; i++) {
errorInit(list[i]);
}
}
function errorInit(row, isSub) {
// 存在子选项时,处理子选项
if (row.Sub.length > 0) {
let sub = row.Sub;
for (let i = 0, len = sub.length; i < len; i++) {
errorInit(sub[i], true);
}
return;
}
let CancelRadius = '';
let Choosed = '';
let itemSelect = row.I15;
//生成错误项
if ($(`div [itemid="${row.I1}"] li i`).hasClass('Cancel-Radius')) {
CancelRadius = 'Cancel-Radius';
}
if (itemSelect.length > 0 && itemSelect[itemSelect.length - 1] >= $(`div [itemid="${row.I1}"] li`).length) {
Choosed = 'Choosed';
}
$(`div [itemid="${row.I1}"] ul`).append(`<li class="Item-Option ${Choosed}"><i class="${CancelRadius}">错</i>错误答案</li>`);
// 获取答案选项
let select = $(`div [itemid="${row.I1}"] li`);
selectAlertColor(select, isSub);
// 取消默认选中的 以及包含Choosed 样式的
for (let i = 0, len = itemSelect.length; i < len; i++) {
select.eq(itemSelect[i]).click();
}
select.eq(-1).click();
}
//添加颜色
function selectRightColor(select, isSub) {
if (isSub) {
select.parents('.Subject-Description').find('.Subject-Title').attr('style', 'background-color: #none;');
} else {
select.parents('.Subject-Area').find('.Subject-Title').attr('style', 'background-color: #none;');
}
}
function selectAlertColor(select, isSub) {
if (isSub) {
select.parents('.Subject-Description').find('.Subject-Title').attr('style', 'background-color: #ff4949;');
} else {
select.parents('.Subject-Area').find('.Subject-Title').attr('style', 'background-color: #ff4949;');
}
}
//统计信息
let questionTotal = 0;
let wrongTotal = 0;
let writeTotal = 0;
function showTotal() {
$("#total_text").html(
`当前考试${questionTotal}题,已自动答题${writeTotal}题(错题库共${wrongTotal}题)
<br>若自动答题数太少可根据考试机会多提交几次,扩大错题库
<br><span style="color: #ff4949;">红色标记为不存在错题库中的题目,最后一次考试机会中请手动选择答案后提交</span>
`
)
}
function intiTotal() {
questionTotal = question.data.paperInfo.Items.length;
wrongTotal = wrongList.length;
}
function intiMsg() {
$('.Top-Test-Info.fixed').css('z-index', '5');
$(".Top-Test-Info").append('<div id="total_msg" style="color: #23cfad;"></div>').append('<div id="total_text"></div>')
}
(function () {
'use strict';
let url = window.location.href;
if (url.includes("StudentCenter/OnLineJob/TestPaper")) {
console.log("开始答题");
addXMLRequestCallback(xhr => {
xhr.addEventListener("load", () => {
if (xhr.responseURL.includes(getHomework)) {
if (!get_point) {
if (xhr.readyState === 4 && xhr.status === 200) {
// 查询到接口后阻止继续监听
get_point = true
window.question = question = JSON.parse(xhr.responseText);
// 默认选中一个错误的答案
selectError(question.data)
intiMsg();
$("#total_msg").text("生成错误答案...");
let bust = (new Date()).getTime();
let rangeKey = JSON.parse(question.data.stuHomeWorkInfo.rangeKey);
let courseExerciseId = getQueryVariable('courseExerciseId');
let t = (new Date()).getTime();
// 获取错题记录
let allWrongList = `https://learn.open.com.cn/StudentCenter/OnlineJob/GetWrongQuestions?bust=${bust}&courseid=${rangeKey.CourseId}&courseExerciseId=${courseExerciseId}&studentHomeworkId=${question.data.stuHomeWorkInfo.studentHomeworkId}&homeCourseId=${question.data.homeWorkInfo.courseId}&_=${t}`
req(allWrongList, (dataasd) => {
if (dataasd.status === 0) {
// alert('点击开始自动答题');
wrongList = dataasd.data.Rows
initquestion(question);
} else {
alert(dataasd.message + "\n需要先答一次,生成错题本后才会生效\n本次将会默认全选程序生成的错误答案,提交答案后在重新做一次即可")
$("#total_msg").text("\n需要先答一次,生成错题本后才会生效\n本次将会默认全选程序生成的错误答案,提交答案后在重新做一次即可")
$(".Subject-Description").attr('style', '');
}
})
}
}
}
});
});
}
})();