// ==UserScript==
// @name 依涵学习通作业助手
// @namespace https://www.yihanstudio.com/
// @version 1.0.1
// @description 开发中,目前支持新版学习通作业和老版考试答题功能,第一遍答题后会请求第二个接口答题,实现答题率在95%以上;
// @author ZhouChaoHan
// @match *://*.chaoxing.com/*
// @grant GM_xmlhttpRequest
// @license MIT
// ==/UserScript==
var unknowQuestionAnswerArray = []
function strSimilarity2Number(s, t) {
var n = s.length,
m = t.length,
d = [];
var i, j, s_i, t_j, cost;
if (n == 0) return m;
if (m == 0) return n;
for (i = 0; i <= n; i++) {
d[i] = [];
d[i][0] = i;
}
for (j = 0; j <= m; j++) {
d[0][j] = j;
}
for (i = 1; i <= n; i++) {
s_i = s.charAt(i - 1);
for (j = 1; j <= m; j++) {
t_j = t.charAt(j - 1);
if (s_i == t_j) {
cost = 0;
} else {
cost = 1;
}
d[i][j] = Minimum(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
}
}
return d[n][m];
}
function Minimum(a, b, c) {
return a < b ? (a < c ? a : c) : (b < c ? b : c);
}
//两字符串相似度匹配
function strSimilarity2Percent(s, t) {
var l = s.length > t.length ? s.length : t.length;
var d = strSimilarity2Number(s, t);
return parseInt((1 - d / l).toFixed(4) * 100);
}
function isInArray(ary,str){
for(let i=0;i<ary.length;i++){
if(ary[i].trim() == str.trim()){return true;}
}
return false;
}
//单选题选择
function choiseAnswerOptionType1(options,answer){
let fs = 0;
let ary = [];
for (let j = 0; j < options.length; j++) {
let option = $(options[j]); //选项体
let optionName = option.find(".answer_p").text().trim(); //选项文字
optionName = optionName.replace(/[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]/g,"");
answer = answer.replace(/[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]/g,"").trim();
let lsfs = strSimilarity2Percent(optionName, answer);
if (lsfs >= 70 && lsfs > fs) {
fs = lsfs;
ary.push(option);
}
}
if(ary.length == 0){
return false;
}
if(!ary[ary.length-1].find(".check_answer").attr("data")){
ary[ary.length-1].click();
return true;
}else{
return true;
}
return false;
}
//多选题选择
function choiseAnswerOptionType2(options,answers){
let choiseNum = 0;
let lsAnswers = answers.replace(/\s/g,"").split("#");
if(lsAnswers.length <= 1){
lsAnswers = answers.replace(/\s/g,"").split(/[^\u4e00-\u9fa5^\w]/g);
}
for(let i=0;i<options.length;i++){
let option = $(options[i]); //选项体
let optionName = option.find(".answer_p").text().trim(); //选项文字
optionName = optionName.replace(/[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]/g,"");
for(let j=0;j<lsAnswers.length;j++){
let answer = lsAnswers[j];//答案
answer = answer.replace(/[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]/g,"").trim();
if(optionName == answer){
if(!option.find(".check_answer_dx").attr("data")){
option.click();
}
choiseNum++;
}
}
}
if(choiseNum > 0){
return true;
}
return false;
}
//填空题填空
function writeTextAnswerType3(textareas,answers){
let writeNum = 0;
let lsAnswers = answers.replace(/\s/g,"").split("#");
if(lsAnswers.length <= 1){
lsAnswers = answers.replace(/\s/g,"").split(/[^\u4e00-\u9fa5^\w]/g);
}
if(textareas.length == lsAnswers.length){
for(let i=0;i<textareas.length;i++){
UE.getEditor(textareas[i].name).setContent(lsAnswers[i]);
}
return true;
}
return false;
}
//判断题选择
function choiseAnswerOptionType4(options,answer){
let zq = ["正确","是","true","True","T","对","√","ri"];
let cw = ["错误","否","false","False","F","错","×","wr"];
let lsAnswer = null;
if(isInArray(zq,answer.trim())){lsAnswer = true;}
if(isInArray(cw,answer.trim())){lsAnswer = false;}
for (let j = 0; j < options.length; j++) {
let lsOption = null;
let option = $(options[j]); //选项体
let optionName = option.find(".answer_p").text().trim(); //选项文字
if(isInArray(zq,optionName)){lsOption = true;}
if(isInArray(cw,optionName)){lsOption = false;}
if(lsAnswer != null && lsOption != null && lsOption == lsAnswer){
if(!option.find(".check_answer").attr("data")){
option.click();
}
return true;
}else{
continue;
}
}
return false;
}
function getAnswer(questionName,isFirst){
return new Promise(res => {
let qType = $(".Cy_TItle").next().val() || '-1';
let courseId = location.search.match(/courseId=(\d+)/i)[1];
let classId= location.search.match(/classId=(\d+)/i)[1];
let knowledgeId=0
try {
knowledgeId= location.search.match(/knowledgeid=(\d+)/i)[1];
} catch (err) {
}
GM_xmlhttpRequest({
method: 'POST',
url: isFirst ? "http://onlinecoursekiller.online/OnlineCourseKiller/killer" : "http://s.jiaoyu139.com:886/get?ua=cx&v=1&keyword="+questionName+"&courseid="+courseId+"&type="+qType+"&classid="+classId+"&knowledgeid="+knowledgeId,
headers: {
'Content-type': 'application/x-www-form-urlencoded'
},
data: isFirst ? "q=" + questionName : "",
timeout: 5000,
onload: function(xhr) {
if (xhr.status == 200) {
if(isFirst == true){
let answer = JSON.parse(xhr.response);
if (answer.success === "true") {
$('<tr>' +
'<td style="border: 1px solid;">0</td>' +
'<td style="border: 1px solid;">' + questionName + '</td>' +
'<td style="border: 1px solid;">' + answer.answer + '</td>' +
'</tr>').appendTo(".question-table-tbody").css('background-color','');
}else{
$('<tr>' +
'<td style="border: 1px solid;">0</td>' +
'<td style="border: 1px solid;">' + questionName + '</td>' +
'<td style="border: 1px solid;">' + answer.answer + '</td>' +
'</tr>').appendTo(".question-table-tbody").css('background-color', 'rgba(200 ,0 ,0, 0.6)');
}
}else{
let answer = JSON.parse(xhr.response);
if (answer.code == 1) {
$('<tr>' +
'<td style="border: 1px solid;">1</td>' +
'<td style="border: 1px solid;">' + questionName + '</td>' +
'<td style="border: 1px solid;">' + answer.data.answer + '</td>' +
'</tr>').appendTo(".question-table-tbody").css('background-color','');
}else{
$('<tr>' +
'<td style="border: 1px solid;">1</td>' +
'<td style="border: 1px solid;">' + questionName + '</td>' +
'<td style="border: 1px solid;">' + answer.data.answer + '</td>' +
'</tr>').appendTo(".question-table-tbody").css('background-color', 'rgba(200 ,0 ,0, 0.6)');
}
}
var divscll = document.getElementById('question-scdiv');
divscll.scrollTop = divscll.scrollHeight;
}else{
getAnswer(questionName,isFirst);
}
setTimeout(() => {
res();
}, 200);
},
ontimeout: function() {
}
});
});
}
function findAnswer(isFirst,questionName, type, question) {
return new Promise(res => {
let qType = question.find('input[name^=answertype]:eq(0)').val() || '-1';
let courseId = location.search.match(/courseId=(\d+)/i)[1];
let classId= location.search.match(/classId=(\d+)/i)[1];
let knowledgeId=0
try {
knowledgeId= location.search.match(/knowledgeid=(\d+)/i)[1];
} catch (err) {
}
GM_xmlhttpRequest({
method: 'POST',
url: isFirst ? "http://onlinecoursekiller.online/OnlineCourseKiller/killer" : "http://s.jiaoyu139.com:886/get?ua=cx&v=1&keyword="+questionName+"&courseid="+courseId+"&type="+qType+"&workid="+($('#workId').val() || $('#oldWorkId').val())+"&classid="+classId+"&knowledgeid="+knowledgeId,
headers: {
'Content-type': 'application/x-www-form-urlencoded'
},
data: isFirst ? "q=" + questionName : "",
timeout: 5000,
onload: function(xhr) {
if (xhr.status == 200) {
if(isFirst == true){
let answer = JSON.parse(xhr.response);
if (answer.success === "true") {
let tf = false;
//1.2.4获取选项组
if (type == 1 || type == 2 || type == 4) {
let answerOptions = question.find(".stem_answer .clearfix");
if(type == 1){
tf = choiseAnswerOptionType1(answerOptions,answer.answer);
}else if(type == 2){
tf = choiseAnswerOptionType2(answerOptions,answer.answer);
}else if(type == 4){
tf = choiseAnswerOptionType4(answerOptions,answer.answer);
}
} else if (type == 3) {
//填空题
let textareas = question.find("textarea");
tf = writeTextAnswerType3(textareas,answer.answer);
}
if(tf == false){
$('<tr>' +
'<td style="border: 1px solid;">' + questionName + '</td>' +
'<td style="border: 1px solid;">' + answer.answer + '</td>' +
'</tr>').appendTo(".question-table-tbody").css('background-color', 'rgba(200 ,0 ,0, 0.6)');
question.attr("noGetAnswer","no");
question.css('background-color', 'rgba(200 ,0 ,0, 0.6)');
unknowQuestionAnswerArray.push(question);
}else{
$('<tr>' +
'<td style="border: 1px solid;">' + questionName + '</td>' +
'<td style="border: 1px solid;">' + answer.answer + '</td>' +
'</tr>').appendTo(".question-table-tbody").css('background-color','');
question.css('background-color', 'rgba(0 ,200 ,0, 0.6)');
}
}else{
$('<tr>' +
'<td style="border: 1px solid;">' + questionName + '</td>' +
'<td style="border: 1px solid;">' + answer.answer + '</td>' +
'</tr>').appendTo(".question-table-tbody").css('background-color', 'rgba(200 ,0 ,0, 0.6)');
//未获取到答案
question.attr("noGetAnswer","no");
question.css('background-color', 'rgba(200 ,0 ,0, 0.6)');
unknowQuestionAnswerArray.push(question);
}
}else{
let answer = JSON.parse(xhr.response);
if (answer.code == 1) {
let tf = false;
if (type == 1 || type == 2 || type == 4) {
let answerOptions = question.find(".stem_answer .clearfix");
if(type == 1){
tf = choiseAnswerOptionType1(answerOptions,answer.data.answer);
}else if(type == 2){
tf = choiseAnswerOptionType2(answerOptions,answer.data.answer);
}else if(type == 4){
tf = choiseAnswerOptionType4(answerOptions,answer.data.answer);
}
} else if (type == 3) {
//填空题
let textareas = question.find("textarea");
tf = writeTextAnswerType3(textareas,answer.data.answer);
}
if(tf == true && question.attr("noGetAnswer") == "no"){
question.css('background-color', 'rgba(0 ,200 ,0, 0.6)');
}
}
}
var divscll = document.getElementById('question-scdiv');
divscll.scrollTop = divscll.scrollHeight;
}else{
findAnswer(isFirst,questionName, type, question);
}
setTimeout(() => {
res();
}, 200);
},
ontimeout: function() {
}
});
});
}
(async function() {
'use strict';
$(document).on("click", "#hideButton", function() {
$(".question-showdiv").show();
$(".question-div").hide();
});
$(document).on("click", "#showButton", function() {
$(".question-div").show();
$(".question-showdiv").hide();
});
$(".clearfix").click(function(){
if($(this).parent().parent().attr("noGetAnswer") == "no"){
$(this).parent().parent().css('background-color', 'rgba(0 ,0 ,0, 0)');
}
});
var url = location.pathname;
console.log(url);
if (url === "/mooc2/work/dowork") {
console.log("进入作业")
let div = $(
'<div class="question-showdiv" style="display: none;position: fixed;top: ' + $(".subNav")
.height() +
'px;right: 10px;height: 100px;width: 300px;">' +
'<div style="font-size: medium;">已隐藏</div>' +
'<button id="showButton">取消隐藏</button>' +
'</div>' +
'<div class="question-div" style="position: fixed;top: ' + $(".subNav").height() +
'px;right: 10px;height: 500px;width: 300px;z-index: 99999;background-color: rgba(190, 231, 233 ,0.9);border: 2px dashed rgb(190 ,231 ,233);">' +
'<div style="font-size: medium;height:20px;" id="question">正在搜索答案...</div>' +
'<button id="hideButton" style="height:20px;">隐藏显示</button>' +
'<div style="max-height: 460px; overflow-y: auto;" id="question-scdiv">'+
'<table border="1" style="font-size: 12px;overflow-y: auto;">' +
'<thead>' +
'<tr>' +
'<th style="width: 60%; min-width: 130px;">题目(点击可复制)</th>' +
'<th style="min-width: 130px;">答案(点击可复制)</th>' +
'</tr>' +
'</thead>' +
'<tbody class="question-table-tbody">' +
'</tbody>' +
'</table>' +
'</div>'+
'</div>'
);
$("body").append(div);
//获取题目组
var questions = $(".questionLi");
if (questions.length === parseInt($(".infoHead span:eq(0)").text().split(':')[1])) {
console.log("共" + questions.length + "题");
for (let i = 0; i < questions.length; i++) {
let question = $(questions[i]); //题目体
let type = 0;
if (question.attr("typename").trim() === "单选题") {
type = 1
} else if (question.attr("typename").trim() === "多选题") {
type = 2
} else if (question.attr("typename").trim() === "填空题") {
type = 3
} else if (question.attr("typename").trim() === "判断题") {
type = 4
}
//获取题目
let questionName = question.find(".mark_name").text(); //题目文字
questionName = questionName.substring(questionName.indexOf(")") + 1).trim();
//查找答案
await findAnswer(true, questionName, type, question);
}
if(unknowQuestionAnswerArray.length > 0){
//二次查找答案
for(let i=0;i<unknowQuestionAnswerArray.length;i++){
let question = $(unknowQuestionAnswerArray[i]); //题目体
let type = 0;
if (question.attr("typename").trim() === "单选题") {
type = 1
} else if (question.attr("typename").trim() === "多选题") {
type = 2
} else if (question.attr("typename").trim() === "填空题") {
type = 3
} else if (question.attr("typename").trim() === "判断题") {
type = 4
}
//获取题目
let questionName = question.find(".mark_name").text(); //题目文字
questionName = questionName.substring(questionName.indexOf(")") + 1).trim();
await findAnswer(false, questionName, type, question);
}
}
}
}else if(url === "/exam/test/reVersionTestStartNew"){
console.log("进入考试")
let div = $(
'<div class="question-showdiv" style="display: none;position: fixed;top: 10px;right: 10px;height: 100px;width: 300px;">' +
'<div style="font-size: medium;">已隐藏</div>' +
'<button id="showButton">取消隐藏</button>' +
'</div>' +
'<div class="question-div" style="position: fixed;top: 10px;right: 10px;height: 500px;width: 300px;z-index: 99999;background-color: rgba(190, 231, 233 ,0.9);border: 2px dashed rgb(190 ,231 ,233);">' +
'<div style="font-size: medium;height:20px;" id="question">正在搜索答案...</div>' +
'<button id="hideButton" style="height:20px;">隐藏显示</button>' +
'<div style="max-height: 460px; overflow-y: auto;" id="question-scdiv">'+
'<table border="1" style="font-size: 12px;overflow-y: auto;">' +
'<thead>' +
'<tr>' +
'<th>接口</th>' +
'<th style="width: 60%; min-width: 130px;">题目(点击可复制)</th>' +
'<th style="min-width: 130px;">答案(点击可复制)</th>' +
'</tr>' +
'</thead>' +
'<tbody class="question-table-tbody">' +
'</tbody>' +
'</table>' +
'</div>'+
'</div>'
);
$("body").append(div);
let thisQuestionName = $(".Cy_TItle div:eq(0)").text().trim().replace(/\(.*?\)/g,'').replace(/\(.*?\)/g,'').replace(/([^)]+)/g,'');
getAnswer(thisQuestionName,true);
getAnswer(thisQuestionName,false);
}
})();