// ==UserScript==
// @name 🦁超星学习通AIIT全自动小助手🐑🐑
// @namespace http://tampermonkey.net/
// @version 1.1.1
// @description 超星全自动刷课,支持章节、作业、考试等多项任务点。
// @author 阿宽
// @run-at document-end
// @match *://*.chaoxing.com/*
// @match *://*.edu.cn/*
// @match *://*.nbdlib.cn/*
// @match *://*.hnsyu.net/*
// @connect 121.62.16.77
// @connect cx.icodef.com
// @connect sso.chaoxing.com
// @connect mooc1-api.chaoxing.com
// @connect mooc1-1.chaoxing.com
// @connect mooc1-2.chaoxing.com
// @connect mooc1.chaoxing.com
// @connect fystat-ans.chaoxing.com
// @grant unsafeWindow
// @grant GM_info
// @grant GM_getResourceText
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @antifeature ads
// @require https://greasyfork.org/scripts/455606-layx-js/code/layxjs.js?version=1122546
// @require https://lib.baomitu.com/jquery/3.6.0/jquery.min.js
// @require https://cdn.jsdelivr.net/gh/photopea/Typr.js@15aa12ffa6cf39e8788562ea4af65b42317375fb/src/Typr.min.js
// @require https://cdn.jsdelivr.net/gh/photopea/Typr.js@f4fcdeb8014edc75ab7296bd85ac9cde8cb30489/src/Typr.U.min.js
// @require https://cdn.bootcdn.net/ajax/libs/blueimp-md5/2.18.0/js/md5.min.js
// @resource layxcss https://greasyfork.org/scripts/455605-layx/code/layx.user.css
// @resource ttf https://www.forestpolice.org/ttf/2.0/table.json
// ==/UserScript==
// 默认配置
var defaultConfig = {
// 默认请求头
ua: 'Dalvik/2.1.0 (Linux; U; Android 12; M2102K1AC Build/SKQ1.211006.001) (schild:1b39227c6f3c3b7d95c59ad476567cdb) (device:M2102K1AC) Language/zh_CN com.chaoxing.mobile/ChaoXingStudy_3_6.1.0_android_phone_906_100 (@Kalimdor)_cc0454aaa3b7439daf7cebe7e43f62ba',
// 公共间隔
interval: 3000,
// 答案模糊匹配率。0-1之间,越大越严格
matchRate: 0.8,
// 答案正确率,满足此正确率则提交,否则自动提交失效
autoSubmitRate: 0.9,
// 是否开启自动提交
autoSubmit: true,
// 是否开启自动答题
autoAnswer: true,
// api接口
api:'http://121.62.16.77:996/',
// 是否开启自动播放视频
autoPlayVideo: true,
// 是否开启调试模式(正常用户不用理会这个参数)
debugger: true,
script_info : GM_info.script,
},_self = unsafeWindow,top = _self;
function log(msg) {
if (defaultConfig.debugger) {
console.log(msg);
}
}
(function () {
'use strict';
// 工具类
var utils = {
// 通知消息
notify: function (level, msg) {
let data={
level: level,
msg: msg
}
return JSON.stringify(data);
},
// 章节递归排序
sortData: function (data) {
let arr = [];
data.forEach(item=>{
if(item.parentnodeid == 0){
arr.push(item);
}else{
data.forEach(item2=>{
if(item2.id == item.parentnodeid){
if(item2.children){
item2.children.push(item);
}else{
item2.children = [];
item2.children.push(item);
}
}
})
}
})
return arr;
},
// 转一维数组
toOneArray: function (arr) {
let newArr = [];
arr.forEach(item=>{
newArr.push(item);
if(item.children){
newArr = newArr.concat(this.toOneArray(item.children));
}
})
return newArr;
},
// 睡眠
sleep: function (time) {
return new Promise(resolve => setTimeout(resolve, time));
},
// 获取url参数
getUrlParam: function (name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
},
// 生成url参数
toQueryString: function (obj) {
return obj ? Object.keys(obj).sort().map(function (key) {
var val = obj[key];
if (Array.isArray(val)) {
return val.sort().map(function (val2) {
return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
}).join('&');
}
return encodeURIComponent(key) + '=' + encodeURIComponent(val);
}).join('&') : '';
return obj ? Object.keys(obj).sort().map(function (key) {
var val = obj[key];
if (Array.isArray(val)) {
return val.sort().map(function (val2) {
return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
}).join('&');
}
return encodeURIComponent(key) + '=' + encodeURIComponent(val);
}).join('&') : '';
},
// input中获取参数
getInputParam: function (name) {
let input = document.getElementsByName(name)[0];
if (input) {
return input.value;
}
return null;
},
// 获取视频enc
getVideoEnc: function (clazzid,uid,jobid,objectId,playingTime,duration) {
return md5( "["+clazzid+"]["+uid+"]["+jobid+"]["+objectId+"]["+(playingTime * 1000)+"][d_yHJ!$pdA~5]["+(duration * 1000)+"][0_"+duration+"]");
},
// 伪造userAgent
getUserAgent: function () {
},
random_str: function(len=32) {
let $chars = 'qwertyuioplkjhgfdsazxcvbnm1234567890';
let maxPos = $chars.length;
let str = '';
for (let i = 0; i < len; i++) {
str += $chars.charAt(Math.floor(Math.random() * maxPos));
}
return str;
} ,
// 获取当前时间戳
getTimestamp: function() {
return new Date().getTime();
}
// 去除html
,removeHtml: function(html) {
html = html.replace(/<((?!img|sub|sup|br)[^>]+)>/g, '');
html = html.replace(/ /g, ' ').replace(/\s+/g, ' ').trim();
// 将所有br转换为换行
html = html.replace(/<br\s*\/?>/g, '\n');
html = html.replace(/(^\s*)|(\s*$)/g, '');
html = html.replace(/(^\n*)|(\n*$)/g, '');
return html;
},
// 修改默认配置
setConfig: function(config) {
for (var key in config) {
defaultConfig[key] = config[key];
GM_setValue(key, config[key]);
}
}
// 根据时间缓存数据
,cache: function(key, value, time) {
var cache = GM_getValue(key);
if (cache) {
if (cache.time + time > utils.getTimestamp()) {
return cache.value;
}
}
GM_setValue(key, {value: value, time: utils.getTimestamp()});
return value;
},
// 匹配选项索引
matchIndex: function(options,answer) {
var matchArr=[];
for(var i=0;i<answer.length;i++){
for(var j=0;j<options.length;j++){
if(answer[i]==options[j]){
matchArr.push(j);
}
}
}
return matchArr;
}
// 字符串相似度计算
,similarity: function(s, t) {
var l = s.length > t.length ? s.length : t.length;
var n = s.length;
var m = t.length;
var d = [];
var i;
var j;
var s_i;
var t_j;
var 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] = this.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
}
}
return (1 - d[n][m] / l).toFixed(2);
}
// 获取最小值
,min: function() {
var min = arguments[0];
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] < min) {
min = arguments[i];
}
}
return min;
}
// 获取最大值
,max: function() {
var max = arguments[0];
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
// 模糊匹配选项索引
,fuzzyMatchIndex: function(options,answer) {
//由于无匹配项,选择最相似答案
var matchArr=[];
for(var i=0;i<answer.length;i++){
var max=0;
var index=0;
for(var j=0;j<options.length;j++){
var similarity=utils.similarity(answer[i],options[j]);
console.log(similarity);
if(similarity>max){
max=similarity;
index=j;
}
}
if(max>defaultConfig.matchRate){
matchArr.push(index);
}
}
return matchArr;
}
// 字符串判断
,strContain: function(str,arr) {
for(var i=0;i<arr.length;i++){
if(str.indexOf(arr[i])>-1){
return true;
}
}
return false;
}
};
// 协议封装
var api = {
// 监控验证码
monitorVerify: function (responseText) {
return new Promise((resolve, reject) => {
// 判断responseText是否是json
try {
let obj = JSON.parse(responseText);
let divHtml='<img src="'+obj.verify_png_path+'"/> <input type="text" class="code_input" placeholder="请输入图中的验证码" /><button id="code_btn">验证</button>';
// layx.html('verify','Hello Layx!',divHtml);
layx.prompt(divHtml,"请输入验证码",function(id,value,textarea, button, event){
let url=obj.verify_path+"&ucode="+value;
window.open(url);
});
} catch (error) {
window.open("https://mooc1-api.chaoxing.com/antispiderShowVerify.ac?app=1&ucode=ckfx");
}
});
},
// 默认请求
async defaultRequest(url, method, data={},ua=defaultConfig.ua) {
try {
const response = await new Promise((resolve, reject) => {
GM_xmlhttpRequest({
url,
method,
headers: {
'User-Agent': ua,
'X-Requested-With': 'XMLHttpRequest',
'Sec-Fetch-Site': 'same-origin',
"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"
},
data: utils.toQueryString(data),
onload(response) {
resolve(response);
},
onerror(response) {
reject(response);
},
});
});
if (response.responseText!=null&&response.responseText.indexOf('输入验证码') !== -1) {
await this.monitorVerify(response.responseText);
return await this.defaultRequest(url, method, data);
}
return response;
} catch (err) {
return Promise.reject(err);
}
},
// 获取课程列表
getCourseList:async function () {
let result = await api.defaultRequest("https://mooc1-api.chaoxing.com/mycourse/backclazzdata?view=json&mcode=", 'GET');
return JSON.parse(result.responseText);
},
// 获取课程章节
getCourseChapter:async function (courseId,classId) {
let result = await api.defaultRequest("https://mooc1-api.chaoxing.com/gas/clazz?id="+classId+"&personid="+courseId+"&fields=id,bbsid,classscore,isstart,allowdownload,chatid,name,state,isfiled,visiblescore,begindate,coursesetting.fields(id,courseid,hiddencoursecover,coursefacecheck),course.fields(id,name,infocontent,objectid,app,bulletformat,mappingcourseid,imageurl,teacherfactor,jobcount,knowledge.fields(id,name,indexOrder,parentnodeid,status,layer,label,jobcount,begintime,endtime,attachment.fields(id,type,objectid,extension).type(video)))&view=json", 'GET');
return JSON.parse(result.responseText);
},
// 获取章节列表
// nodes: 一维数组,每个元素为章节id
getChapterList:async function (courseid,clazzid,nodes,userid,cpi) {
let data={
"view":"json",
"nodes":nodes,
"clazzid":clazzid,
"userid":userid,
"cpi":cpi,
"courseid":courseid,
"time":(new Date()).valueOf()
}
let result = await api.defaultRequest("https://mooc1-api.chaoxing.com/job/myjobsnodesmap", 'post',data);
return JSON.parse(result.responseText);
},
// 获取课程配置
getCourseConfig:async function (courseId,classId,cpi) {
let result = await api.defaultRequest("https://mooc1-api.chaoxing.com/course/phone/get-course-setting?clazzId="+classId+"&courseId="+courseId+"&cpi="+cpi, 'GET');
return JSON.parse(result.responseText);
},
// 获取单个章节信息
getChapterInfo:async function (id,courseid) {
let data={
"id":id,
"courseid":courseid,
"fields":"id,parentnodeid,indexorder,label,layer,name,begintime,createtime,lastmodifytime,status,jobUnfinishedCount,clickcount,openlock,card.fields(id,knowledgeid,title,knowledgeTitile,description,cardorder).contentcard(all)",
"view":"json",
}
let url = "https://mooc1-api.chaoxing.com/gas/knowledge?"+utils.toQueryString(data);
let result = await api.defaultRequest(url, 'get');
return JSON.parse(result.responseText);
},
// 获取单个章节详情
getChapterDetail:async function (courseid,clazzid,knowledgeid,num,cpi) {
let url = "https://mooc1-api.chaoxing.com/knowledge/cards?clazzid="+clazzid+"&courseid="+courseid+"&knowledgeid="+knowledgeid+"&num="+num+"&isPhone=1&control=true&cpi="+cpi;
let result = await api.defaultRequest(url, 'get');
return result.responseText;
},
// 上传学习记录
uploadStudyLog:async function (courseid,clazzid,knowledgeid,cpi) {
// 取当前域名
let url = `${location.origin}/mooc2-ans/mycourse/studentcourse?courseid=${courseid}&clazzid=${clazzid}&cpi=${cpi}&ut=s&t=${utils.getTimestamp()}`
let text=await this.defaultRequest(url,'get',{},navigator.userAgent);
let match = text.responseText.match(/encode=([\w]+)/);
log(match);
if (match) {
const encode = match[1];
let url = `https://fystat-ans.chaoxing.com/log/setlog?personid=${cpi}&courseId=${courseid}&classId=${clazzid}&encode=${encode}&chapterId=${knowledgeid}`;
let result = await api.defaultRequest(url, 'get',{},navigator.userAgent);
return result.responseText;
}
return false;
},
// 文档学习
docStudy:async function (jobid,knowledgeid,courseid,clazzid,jtoken) {
let url = "https://mooc1-api.chaoxing.com/ananas/job/document?jobid="+jobid+"&knowledgeid="+knowledgeid+"&courseid="+courseid+"&clazzid="+clazzid+"&jtoken="+jtoken+"&_dc="+new Date().valueOf();
let result = await api.defaultRequest(url, 'get');
return JSON.parse(result.responseText);
},
// 视频学习
videoStudy:async function (data,cpi,dtoken) {
let url = "https://mooc1-api.chaoxing.com/multimedia/log/a/"+cpi+"/"+dtoken+"?"+utils.toQueryString(data);
let result = await api.defaultRequest(url, 'get');
return JSON.parse(result.responseText);
},
// 视频配置获取
getVideoConfig:async function (objectId) {
let url = "https://mooc1-1.chaoxing.com/ananas/status/"+objectId+"?k=&flag=normal&";
let result = await api.defaultRequest(url, 'get');
return JSON.parse(result.responseText);
},
// 解锁章节
unlockChapter:async function (courseid,clazzid,knowledgeid,userid,cpi) {
let url = `https://mooc1-api.chaoxing.com/job/submitstudy?node=${knowledgeid}&userid=${userid}&clazzid=${clazzid}&courseid=${courseid}&personid=${cpi}&view=json`;
log(url);
let result = await api.defaultRequest(url, 'get');
return result.status;
}
};
// 接口封装
var ServerApi = {
// 搜索
search:function (data) {
/**
* 如果你想请求我们的接口,请以下面的格式发送请求
* 请求地址:看默认配置
* 请求方式:POST
* 请求参数:
* param type int 0:单选题 (必填) 1:多选题 2:判断题 等等(与超星一致)
* param question string 题目 (必填)
* param options array 选项 (必填) json字符串 ["选项1","选项2"]
* param workType string 测验类型 (必填) zj:章节测验 zy:作业 ks:考试
* param courseId string 课程id (必填)
*
* header:
* v string 脚本版本号 (必填)
* referer string 当前答题页面地址 (必填)
* Content-Type string application/json (必填)
*
* ps:以上参数必填,否则会无法搜索到题目,另外不保证题库质量,不保证对接稳定性
*/
data.key=defaultConfig.kami||'';
$(".layx_status").html("阿宽提醒:正在搜索答案");
var url = defaultConfig.api + 'answer?z='+data.workType+'&t='+data.type;
return new Promise(function (resolve, reject) {
GM_xmlhttpRequest({
method: 'post',
url: url,
data: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
'v': defaultConfig.script_info.version,
'referer': location.href,
't': utils.getTimestamp()
},
onload: function (response) {
resolve(response);
},
onerror: function (response) {
reject(response);
},
ontimeout: function (response) {
reject(response);
}
});
});
},
// 公告3
// 公告3
get_msg: function(){
//var url = '';
return new Promise(function(resolve, reject) {
GM_xmlhttpRequest({
method: 'get',
url: url,
headers: {
'referer': location.href,
},
onload: function(response) {
try {
let reqData=JSON.parse(response.responseText);
resolve(reqData.msg);
} catch (e) {
resolve(defaultConfig.notice);
}
},
onerror: function() {
resolve(defaultConfig.notice);
}
});
});
}
// 第三方搜题接口
,searchOther:function (data) {
return new Promise(function (resolve, reject) {
GM_xmlhttpRequest({
method: 'post',
url: defaultConfig.otherApi,
data: 'question=' + encodeURIComponent(data.question),
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
},
onload: function (response) {
try
{
var res = JSON.parse(response.responseText);
if (res.code == 1) {
let data=res.data;
// 去除javascript:void(0);
data=data.replace(/javascript:void\(0\);/g,'');
// 去除前后空格
data=data.replace(/(^\s*)|(\s*$)/g, "");
// 去除前后换行
data=data.replace(/(^\n*)|(\n*$)/g, "");
if(utils.strContain(data,["叛逆","公众号","李恒雅","一之"])){
resolve([]);
}else{
resolve(data.split("#"));
}
} else {
reject([]);
}
}
catch (e)
{
reject([]);
}
},
onerror: function () {
reject([]);
},
ontimeout: function () {
reject([]);
}
});
});
}
// 秘钥验证
,checkKey:function (key) {
return new Promise(function (resolve, reject) {
GM_xmlhttpRequest({
method: 'post',
url: defaultConfig.api + 'key',
data: 'key=' + key,
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
},
onload: function (response) {
try
{
var res = JSON.parse(response.responseText);
if (res.code == 200) {
resolve(res.data);
} else {
reject(res.msg);
}
}
catch (e)
{
reject("秘钥验证失败");
}
},
onerror: function () {
reject("秘钥验证失败");
},
ontimeout: function () {
reject("秘钥验证超时");
}
});
});
}
}
// 页面操作函数
var page = {
// 页面初始化
init:async function () {
GM_addStyle(GM_getResourceText("layxcss"));
switch (location.pathname) {
case '/exam-ans/exam/test/reVersionTestStartNew':
case '/exam/test/reVersionTestStartNew':
if(location.href.includes('newMooc=true')){
await this.layx("ks");
layx.setSize('ks',{
width: 350,
height: 500
})
this.layx_status_msg("阿宽提醒:初始化完成");
let reqData=page.getQuestion("3");
this.layx_status_msg("阿宽提醒:自动答题中.....");
defaultConfig.loop=setInterval(function(){
page.startAsk(reqData);
},defaultConfig.interval);
break;
}else{
let url=location.href;
// 如果url中没有newMooc=false,则添加
if(!url.includes('newMooc=false')){
url=url+'&newMooc=true';
}else{
url=url.replace('newMooc=false','newMooc=true');
}
// 跳转到新版考试
location.href=url;
break;
}
// 课程页面主页
case '/mycourse/stu':
await this.layx();
this.layx_log("阿宽提醒:初始化完成","info");
this.mainTask();
break;
case '/work/doHomeWorkNew':
// 判断是否包含
if(document.body.innerHTML.indexOf("阿宽提醒:此作业已被老师")!=-1){
window.parent.postMessage(utils.notify("error","阿宽提醒:作业已被删除"), '*');
}
// 判断是章节还是旧版作业
if(location.href.includes('oldWorkId')){
page.decode();
await page.layx("zj",{
closeMenu:false,
// 最大化
maxMenu:true,
});
layx.setTitle('zj','🔥超星学习通AIIT全自动小助手-作业答题界面(本窗口禁止关闭)');
// closeMenu:false
// await utils.sleep(5000);
//
defaultConfig.workinx=0;
defaultConfig.succ=0;
defaultConfig.fail=0;
layx.setSize('zj',{
width: 600,
height: 300
})
// layx_log 隐藏
$("#layx_log").hide();
if(defaultConfig.autoAnswer)
{
this.layx_status_msg("阿宽提醒:正在自动答题中");
defaultConfig.loop=setInterval(function(){
page.startChapter();
},defaultConfig.interval);
}
}else{
layx.msg('阿宽提醒:不支持旧版作业',{dialogIcon:'help'});
}
break;
case '/work/selectWorkQuestionYiPiYue':
window.parent.postMessage(utils.notify("success","阿宽提醒:作业已完成"), '*');
case '/mooc2/work/dowork':
// 新版作业
await this.layx('zy');
this.layx_status_msg("阿宽提醒:初始化完成");
$("#layx_log").hide();
defaultConfig.workinx=0;
defaultConfig.succ=0;
defaultConfig.fail=0;
layx.setSize('zy',{
width: 600,
height: 300
});
if(defaultConfig.autoAnswer)
{
this.layx_status_msg("阿宽提醒:正在自动答题中");
defaultConfig.loop=setInterval(function(){
page.startWork();
},defaultConfig.interval);
}
break;
}
},
// layx主弹窗
layx: async function (id="abcde",option={}) {
let configs={
position:'lb',
width:300,
height:500,
// storeStatus: true,
borderRadius: "20px",
skin: 'asphalt',
opacity: 1,
maxMenu: false,
statusBar: "<div id='layx_status_msg'>阿宽提醒:助手正在初始化</div>",
style:layx.multiLine(function(){
/*
#layx_div{
background-color: #F5F7FA;
color: #000;
height: 100%;
width: 100%;
overflow: auto;
}
#layx_msg{
background-color: #fff;
padding: 20px;
border-bottom: 1px solid #ccc;
border-radius: 5px;
margin: 10px;
}
#layx_log{
height: 60%;
padding: 15px;
color: red;
}
#layx_content{
height: 5%;
}
.layx_success{
color: #67C23A;
font-weight: bold;
}
.layx_error{
color: #F56C6C;
font-weight: bold;
}
.layx_info{
color: black;
font-weight: bold;
}
#layx_status_msg{
color: #EE3B3B;
font-weight: bold;
}
*/
})
};
// 如果option不为空合并
if(option){
configs=Object.assign(configs,option);
}
// 公告缓存十分钟
var notice = '<img src="https://hashx.cn/i/2023/03/01/nuor3u.jpg" alt="公告" height="200"<div style="top:1" id="layx_div" ><div id="layx_msg" style="text-align:center;">\t📰本脚本仅供ATTT学习研究,请勿使用于非法用途!📰</div> <div id="layx_msg" style="text-align:center;">\t🧧阿宽主页地址:https://bl7c.cn/iDWxa🧧</div>'
var notice1 = '🐑🐑超星学习通AIIT全自动小助手🐑🐑';
// layx的html
let htmlStr = `<div id="layx_div"><div id="layx_msg">${notice}</div><div id="layx_content"></div><div id="layx_log">运行日志:</div></div>`;
layx.html(id,'🦁超星学习通AIIT全自动小助手🐑🐑',htmlStr,configs)
},
// layx_log 日志框写入 等级 level 内容 msg
layx_log: function(msg,level="info"){
let log = document.getElementById("layx_log");
// 判断layx_log元素最多容纳多少行
let maxLine = Math.floor(log.offsetHeight/20);
// 判断layx_log长度,超过20行则删除第一行
if(log.children.length>maxLine){
log.removeChild(log.children[0]);
}
// 取当前时间
let time = new Date().toLocaleTimeString();
let str="<p>"+time+" "+"<span class='"+"layx_"+level+"'>"+msg+"</span></p>";
log.innerHTML+=str;
},
// layx_status_msg 状态栏写入
layx_status_msg: function(msg){
let log = document.getElementById("layx_status_msg");
log.innerHTML=msg;
},
// 主任务
mainTask: async function () {
// 获取课程配置
let pz={};
pz.courseid = utils.getUrlParam("courseid"),
pz.clazzid = utils.getUrlParam("clazzid"),
pz.cpi = utils.getUrlParam("cpi"),
pz.userid = utils.getInputParam("userId");
let data = await api.getCourseChapter(pz.courseid,pz.clazzid);
let courseData=data.data[0].course.data[0];
let chapterData=utils.toOneArray(utils.sortData(courseData.knowledge.data));
let statusTask=false;//默认非闯关模式
// 判断是否为闯关模式 格局chapterData中的status判断
for (let i = 0; i < chapterData.length; i++) {
if(chapterData[i].status=="task"){
statusTask=true;
this.layx_log("阿宽提醒:检测到为闯关模式,将以闯关形式完成任务","info");
break;
}
}
let chapterInfo=await api.getChapterList(pz.courseid,pz.clazzid,chapterData.map(
(item)=>{
return item.id;
}
).join(","),pz.userid , pz.cpi);
let unfinishcount = Object.values(chapterInfo).reduce((total, current) => {
return total + current.unfinishcount;
}, 0);
this.layx_log(`[${courseData['name']}-${courseData['teacherfactor']}]阿宽获取到${chapterData.length}个章节,共计${courseData.jobcount}个任务,待完成${unfinishcount}个任务`,"info");
// chapterData遍历
for (let i = 0; i < chapterData.length; i++) {
if(unfinishcount==0){
break;
}
if(statusTask){
let unlock=await api.unlockChapter(pz.courseid,pz.clazzid,chapterData[i].id,pz.userid,pz.cpi);
}
let setlog=await api.uploadStudyLog(pz.courseid,pz.clazzid,chapterData[i].id,pz.cpi);
setlog&&this.layx_log("阿宽提醒:上传学习日志成功","success");
let item = chapterData[i];
log(item);
this.layx_log(`阿宽提醒:开始完成章节[${item.label}${item.name}]`,"info");
if(chapterInfo[item.id].unfinishcount==0){
this.layx_log("阿宽提醒:章节已完成,跳过","success");
await utils.sleep(defaultConfig.interval);
continue;
}
let chapterOne=await api.getChapterInfo(item.id,pz.courseid);
for(let item3 of chapterOne.data[0].card.data){
let chapterDetail=await api.getChapterDetail(pz.courseid,pz.clazzid,item3.knowledgeid,item3.cardorder,pz.cpi);
if(chapterDetail.indexOf("阿宽提醒:章节未开放")!= -1){
this.layx_log("阿宽提醒:章节未开放异常(一般都是章节作业正确率不够,自行完成作业后继续)","error");
await utils.sleep(defaultConfig.interval);
continue;
}
let regex = /mArg\s*=\s*({.*?});/;
let match = regex.exec(chapterDetail);
if (match) {
let jsonStr = match[1];
let mArg = JSON.parse(jsonStr);
let taskDefaultConfig = mArg.defaults;
for(let task of mArg.attachments){
if(!task.type){
continue;
}
await this.finishTask(task,item3,pz,taskDefaultConfig);
await utils.sleep(defaultConfig.interval);
}
}
await utils.sleep(defaultConfig.interval);
}
// break;
// 延时
await utils.sleep(defaultConfig.interval);
}
this.layx_status_msg("阿宽提醒:任务已全部完成")
// 任务全部完成
this.layx_log("阿宽提醒:章节全部完成(若仍有知识点未完成请刷新页面)","success")
},
// 完成任务
finishTask: async function (task,item3,pz,taskDefaultConfig) {
return new Promise(async (resolve, reject) => {
this.layx_status_msg(`正在完成[${task.property.name||task.property.title}]`);
this.layx_log("["+(task.property.name||task.property.title)+"]阿宽提醒:开始完成任务","info");
log(task);
log(item3);
switch (task.type) {
case "video":
let videoData=await api.getVideoConfig(task.objectId);
let videoStatus = await this.finishVideo(task,videoData,pz);
if(videoStatus==true){
this.layx_log("["+task.property.name+"]阿宽提醒:视频已完成","success");
}else{
this.layx_log("["+task.property.name+"]阿宽提醒:视频异常跳过,正常情况无视即可","error");
}
resolve();
break;
case "document":
let result = await api.docStudy(task.property.jobid,item3.knowledgeid,pz.courseid,pz.clazzid,task.jtoken);
result.status?this.layx_log("["+task.property.name+"]阿宽提醒:文档已完成","success"):this.layx_log("["+task.property.name+"]阿宽提醒:文档异常(正常不用理会)","error");
resolve();
break;
case "workid":
let url =`https://mooc1.chaoxing.com/api/work?api=1&workId=${task.jobid.replace('work-', '')}&jobid=${task.property.jobid||""}&needRedirect=true&knowledgeid=${item3.knowledgeid}&ktoken=${taskDefaultConfig.ktoken}&cpi=${taskDefaultConfig.cpi}&ut=s&clazzId=${taskDefaultConfig.clazzId}&type=&enc=${task.enc}&utenc=undefined&courseid=${taskDefaultConfig.courseid}`;
log(url);
layx.iframe('workiframe', '超星学习通ATTT小助手-章节作业答题界面(禁止关闭-答题结束自动关闭)', url,{
event:{
onload:{
after: function (layxWindow, winform) {
log(winform);
}
}
}
})
await this.finishWork();
// 关闭窗口
layx.destroy('workiframe');
resolve();
break;
default:
this.layx_log("阿宽提醒:未知任务类型"+task.type,"error");
resolve();
break;
}
});
},
// 完成视频
finishVideo: async function (task,videoData,pz) {
return new Promise(async (resolve, reject) => {
let data ={
"otherInfo": task.otherInfo.replace(/&cour.*$/,""),
"courseId": pz.courseid,
"playingTime": "0",
"duration": videoData.duration,
"akid": "null",
"jobid": task.property.jobid||task.property._jobid,//
"clipTime": "0_"+videoData.duration,
"clazzId": pz.clazzid,
"objectId": videoData.objectid,
"userid": pz.userid,
"isdrag": "3",
"enc": "",
"rt": task.property.rt||"0.9",
"dtype": task.property.module.includes('audio')?'Audio':'Video',
"view": "json"
}
let time = 0,result;
const intervalTime = 60000; // 每60秒更新一次进度
while (true) {
data.isdrag = time < data.duration ? 3 : 4;
data.playingTime = time >= data.duration ? data.duration : time;
this.layx_status_msg("阿宽提醒:当前进度:" + data.playingTime + "/" + data.duration + "s " + "每60秒会更新一次进度");
data.enc = utils.getVideoEnc(data.clazzId, data.userid, data.jobid, data.objectId, data.playingTime, data.duration);
result = await api.videoStudy(data, pz.cpi, videoData.dtoken);
log(data.objectId,result);
if(time >= data.duration || result.isPassed==true){
break;
}
time += 60;
await utils.sleep(intervalTime);
}
resolve(result.isPassed);
});
},
// 完成作业
finishWork: async function () {
return new Promise(async (resolve, reject) => {
_self.addEventListener('message', function(event) {
console.log(event.data);
let res=JSON.parse(event.data);
if(res.level=="success"){
page.layx_log("阿宽提醒:作业已完成","success");
resolve();
}else{
page.layx_log(res.msg,"error");
resolve();
}
});
});
},
// 请求合并
requestMerge: function (data) {
data.id=_self["uid"];
var promiseArr = [];
promiseArr.push(
// search 修改成功返回的数据
ServerApi.search(data).then(function (response) {
try {
let result = JSON.parse(response.responseText);
switch (result.code) {
case 200:
return result.data.answer;
case 401:
return result.msg;
case 403:
return "频率过快,请稍后再试";
case 404:
return "参数错误";
case 500:
return "服务器错误";
default:
log(result);
page.getScore2(result.data);
return result.msg;
}
}
catch (e){
return "请求异常";
}
})
.catch(function (error){
switch (error.status) {
case 403:
$(".layx_status").html("请求被拒绝,等待重试");
let msg;
try {
msg=JSON.parse(error.responseText).msg;
}
catch (e) {
msg="请求频率过快,请稍后重试";
}
$("#layx_msg").html(msg);
break;
case 404:
$(".layx_status").html("请求地址错误,任务结束");
// 删除定时器
clearInterval(defaultConfig.loop);
break;
default:
$(".layx_status").html("请求错误,等待重试");
break;
}
})
);
if(defaultConfig.otherApi){
promiseArr.push(ServerApi.searchOther(data).catch(function (e) {return [];}));
}
return Promise.all(promiseArr);
},
// 清空所有选中答案以及答案框
clear: function() {
// 清空所有选中答案
$(".answerBg, .textDIV, .eidtDiv").each(function(){
($(this).find(".check_answer").length|| $(this).find(".check_answer_dx").length)&&$(this).click();
});
$(".answerBg, .textDIV, .eidtDiv").find('textarea').each(function(){
_self.UE.getEditor($(this).attr('name')).ready(function() {
this.setContent("");
});
});
},
// 清空当前题目
clearCurrent: function(item) {
// 清空所有选中答案
$(item).find(".answerBg, .textDIV, .eidtDiv").each(function(){
($(this).find(".check_answer").length|| $(this).find(".check_answer_dx").length)&&$(this).click();
});
$(item).find(".answerBg, .textDIV, .eidtDiv").find('textarea').each(function(){
_self.UE.getEditor($(this).attr('name')).ready(function() {
this.setContent("");
});
});
$(item).find(':radio, :checkbox').prop('checked', false);
$(item).find('textarea').each(function(){
_self.UE.getEditor($(this).attr('name')).ready(function() {
this.setContent("");
});
});
},
/**
* 解密字体
* 作者wyn
* 原地址:https://bbs.tampermonkey.net.cn/forum.php?mod=viewthread&tid=2303&highlight=%E5%AD%97%E4%BD%93%E8%A7%A3%E5%AF%86
*/
decode: function() {
var $tip = $('style:contains(font-cxsecret)');
if (!$tip.length) return;
var font = $tip.text().match(/base64,([\w\W]+?)'/)[1];
font = Typr.parse(this.base64ToUint8Array(font))[0];
var table = JSON.parse(GM_getResourceText('ttf'));
var match = {};
for (var i = 19968; i < 40870; i++) { // 中文[19968, 40869]
$tip = Typr.U.codeToGlyph(font, i);
if (!$tip) continue;
$tip = Typr.U.glyphToPath(font, $tip);
$tip = md5(JSON.stringify($tip)).slice(24); // 8位即可区分
match[i] = table[$tip];
}
// 替换加密字体
$('.font-cxsecret').html(function (index, html) {
$.each(match, function (key, value) {
key = String.fromCharCode(key);
key = new RegExp(key, 'g');
value = String.fromCharCode(value);
html = html.replace(key, value);
});
return html;
}).removeClass('font-cxsecret'); // 移除字体加密
},
base64ToUint8Array(base64) {
var data = window.atob(base64);
var buffer = new Uint8Array(data.length);
for (var i = 0; i < data.length; ++i) {
buffer[i] = data.charCodeAt(i);
}
return buffer;
},
// 获取题目数据
getQuestion: function(type,html='') {
String.prototype.cl = function () {
return this.replace(/[0-9]{1,3}.\s/ig, '').replace(/(^\s*)|(\s*$)/g, "").replace(/^【.*?】\s*/, '').replace(/\[(.*?)\]\s*/, '').replace(/\s*(\d+\.\d+分)$/, '');
};
let questionHtml,questionText,questionType,questionTypeId,optionHtml,tokenHtml,workType,optionText,index;
switch (type) {
case '1':
// 章节
workType="zj"
questionHtml = $(html).find(".clearfix .fontLabel");
questionText=utils.removeHtml(questionHtml[0].innerHTML).cl();
questionTypeId=$(html).find("input[name^=answertype]:eq(0)").val();
optionHtml=$(html).find('ul:eq(0) li .after');
tokenHtml=html.innerHTML;
optionText = [];
optionHtml.each(function (index, item) {
optionText.push(utils.removeHtml(item.innerHTML));
});
break;
case '2':
// 作业
workType="zy"
questionHtml = $(html).find(".mark_name");
index = questionHtml[0].innerHTML.indexOf('</span>');
questionText = utils.removeHtml(questionHtml[0].innerHTML.substring(index + 7)).cl();
questionType = questionHtml[0].getElementsByTagName('span')[0].innerHTML.replace('(','').replace(')','').split(',')[0];
questionTypeId=$(html).find("input[name^=answertype]:eq(0)").val();
optionHtml = $(html).find(".answer_p");
tokenHtml = html.innerHTML;
optionText = [];
for (let i = 0; i < optionHtml.length; i++) {
optionText.push(utils.removeHtml(optionHtml[i].innerHTML));
}
break;
case '3':
// 考试
workType="ks"
questionHtml = document.getElementsByClassName('mark_name colorDeep');
index = questionHtml[0].innerHTML.indexOf('</span>');
questionText = utils.removeHtml(questionHtml[0].innerHTML.substring(index + 7)).cl();
questionType = questionHtml[0].getElementsByTagName('span')[0].innerHTML.replace('(','').replace(')','').split(',')[0];
questionTypeId=$("input[name^=type]:eq(1)").val();
optionHtml = document.getElementsByClassName('answer_p');
tokenHtml = document.getElementsByClassName('mark_table')[0].innerHTML;
optionText = [];
for (let i = 0; i < optionHtml.length; i++) {
optionText.push(utils.removeHtml(optionHtml[i].innerHTML));
}
if(!defaultConfig.hidden){
let layx_content = document.getElementById('layx_content');
layx_content.innerHTML = '<div class="question_content"><span class="question_type">' + questionType + '</span>' + questionText + '</div><div class="option"></div><div class="answer">阿宽正在为你获取答案中..</div>';
let option = document.getElementsByClassName('option')[0];
for (let i = 0; i < optionText.length; i++) {
option.innerHTML += '<div class="option_item">' + String.fromCharCode(65 + i) + '、' + optionText[i] + '</div>';
}
let answer = document.getElementsByClassName('answer')[0];
answer.innerHTML = '阿宽正在为你获取答案中...';
}
break;
}
return {
"question": questionText,
"options": optionText,
"type": questionTypeId,
"questionData": tokenHtml,
"workType": workType
}
},
// 考试答案填写
setAnswer: function(type,options,answer) {
switch (type) {
case '0':// 单选
case '1':// 多选
this.clear();
// 获取匹配选项
var matchArr=utils.matchIndex(options,answer);
for(var i=0;i<matchArr.length;i++){
$(".answerBg").eq(matchArr[i]).click();
// 将匹配的选项标绿
$(".option_item").eq(matchArr[i]).css("color","green").css("font-weight","bold");
}
return matchArr.length>0;
case '3':// 判断
answer=answer[0];
answer&&this.clear();
$(".answerBg").each(function(){
if($(this).find(".num_option").attr("data")=="true"){
answer.match(/(^|,)(True|true|正确|是|对|√|T|ri)(,|$)/) && $(this).click()
}else{
answer.match(/(^|,)(False|false|错误|否|错|×|F|wr)(,|$)/) && $(this).click()
}
});
return ($(".answerBg").find(".check_answer").length>0|| $(".answerBg").find(".check_answer_dx").length>0);
case '2':// 填空
case '9':// 程序填空
case '4':// 简答
case '5':
case '6':
case '7':
// 填空数和答案对比
var blankNum=$(".answerBg, .textDIV, .eidtDiv").find('textarea').length;
if(blankNum!=answer.length){
return false;
}
this.clear();
$(".answerBg, .textDIV, .eidtDiv").find('textarea').each(function(index){
_self.UE.getEditor($(this).attr('name')).ready(function() {
this.setContent(answer[index]);
});
});
return true;
default:
return false;
}
},
// 作业答案填写
setWorkAnswer: function(type,options,answer,inx) {
let item = $(".questionLi").eq(inx);
switch (type) {
case '0':// 单选
case '1':// 多选
this.clearCurrent(item);
// 获取匹配选项
var matchArr=utils.matchIndex(options,answer);
for(var i=0;i<matchArr.length;i++){
item.find(".answerBg").eq(matchArr[i]).click();
// 将匹配的选项标绿
$(".option_item").eq(matchArr[i]).css("color","green").css("font-weight","bold");
}
return matchArr.length>0;
case '3':// 判断
answer=answer[0];
answer&&this.clearCurrent(item);
item.find(".answerBg").each(function(){
if($(this).find(".num_option").attr("data")=="true"){
answer.match(/(^|,)(True|true|正确|是|对|√|T|ri)(,|$)/) && $(this).click()
}else{
answer.match(/(^|,)(False|false|错误|否|错|×|F|wr)(,|$)/) && $(this).click()
}
});
return ($(".answerBg").find(".check_answer").length>0|| $(".answerBg").find(".check_answer_dx").length>0);
case '2':// 填空
case '9':// 程序填空
case '4':// 简答
case '5':
case '6':
case '7':
// 填空数和答案对比
var blankNum=item.find('textarea').length;
if(blankNum!=answer.length){
return false;
}
page.clearCurrent(item);
item.find('textarea').each(function(index){
_self.UE.getEditor($(this).attr('name')).ready(function() {
this.setContent(answer[index]);
});
});
return true;
default:
return false;
}
},
// 章节答案填写
setChapterAnswer: function(type,options,answer,inx) {
let item = $(".TiMu").eq(inx);
switch (type) {
case '0':// 单选
case '1':// 多选
// 获取匹配选项
page.clearCurrent(item);
var matchArr=utils.matchIndex(options,answer);
if(matchArr.length>0){
for(var i=0;i<matchArr.length;i++){
item.find('ul:eq(0) li :radio,:checkbox,textarea').eq(matchArr[i]).click();
// 将匹配的选项标绿
$(".option_item").eq(matchArr[i]).css("color","green").css("font-weight","bold");
}
return true;
}
else{
// 无匹配
matchArr=utils.fuzzyMatchIndex(options,answer);
for(var i=0;i<matchArr.length;i++){
item.find('ul:eq(0) li :radio,:checkbox,textarea').eq(matchArr[i]).click();
// 将匹配的选项标绿
$(".option_item").eq(matchArr[i]).css("color","green").css("font-weight","bold");
}
return matchArr.length>0;
}
case '3':// 判断
answer=answer[0];
answer&&page.clearCurrent(item);
item.find('ul:eq(0) li :radio,:checkbox,textarea').each(function(){
if($(this).val()=="true"){
answer.match(/(^|,)(True|true|正确|是|对|√|T|ri)(,|$)/) && $(this).click()
}else{
answer.match(/(^|,)(False|false|错误|否|错|×|F|wr)(,|$)/) && $(this).click()
}
});
// item中的radio或checkbox是否有选中
return item.find('ul:eq(0) li :radio,:checkbox,textarea').is(':checked');
case '2':// 填空
case '9':// 程序填空
case '4':// 简答
case '5':
case '6':
case '7':
// 填空数和答案对比
var blankNum=item.find('textarea').length;
if(blankNum!=answer.length){
return false;
}
page.clearCurrent(item);
item.find('textarea').each(function(index){
_self.UE.getEditor($(this).attr('name')).ready(function() {
this.setContent(answer[index]);
});
});
return true;
default:
return false;
}
},
// 开始考试答题
startAsk: async function(data) {
let answer,answerArr,pd=false;
answer = document.getElementsByClassName('answer')[0];
answerArr = await page.requestMerge(data);
// 遍历数组
for (let i = 0; i < answerArr.length; i++) {
let item = answerArr[i];
// 如果为[]或者字符串则跳过
if(item.length == 0||typeof(item)=="string"){
continue;
}
pd=page.setAnswer(data.type,data.options,item);
if(pd){
answer.innerHTML = '答案:' + item.join('<br />');
answer.style.color = 'green';
break;
}
}
if(!pd){
answer.innerHTML = answerArr[0]||'暂无答案-联系阿宽';
this.layx_status_msg("答案匹配失败,等待切换");
}else{
this.layx_status_msg("已答题,等待切换");
}
// 清除定时器
clearInterval(defaultConfig.loop);
// 自动切换
setTimeout(() => {
$('.nextDiv .jb_btn:contains("下一题")').click();
}, defaultConfig.interval);
},
// 开始作业答题
startWork: async function() {
let layx_content = document.getElementById('layx_content');
let questionList=document.getElementsByClassName('questionLi');
let inx=defaultConfig.workinx;
if(defaultConfig.workinx==0){
// layx_content 加table
layx_content.innerHTML = '<table id="qlist" class="table table-bordered"><thead><tr><th>题号</th><th>题目</th><th>答案</th><th>阿宽</th></tr></thead><tbody></tbody></table>';
// 表格内容左对齐
$("#qlist").css("text-align","left");
// 表格第一列宽度
$("#qlist").find("th").eq(0).css("width","10%");
// 表格第二列宽度
$("#qlist").find("th").eq(1).css("width","50%");
// 表格第三列宽度
$("#qlist").find("th").eq(2).css("width","30%");
$("#qlist").find("th").eq(2).css("width","10%");
// 表格每行高度
$("#qlist").find("tr").css("height","30px");
}
else if(defaultConfig.workinx>=questionList.length){
// 删除定时器
this.layx_status_msg(`答题完成 - 已答${defaultConfig.succ}题,未答${defaultConfig.fail}题`);
clearInterval(defaultConfig.loop);
return;
}
layx.setTitle("main",`答题进度:${inx+1}/${questionList.length} 成功${defaultConfig.succ}题 失败${defaultConfig.fail}题`);
async function startWorkTask(workinx){
let questionDiv = questionList[workinx];
let data = page.getQuestion("2",questionDiv);
// 获取#qlist 的 tbody
let tbody = document.getElementById('qlist').getElementsByTagName('tbody')[0];
let tr = document.createElement('tr');
// tr下边框
$(tr).css("border-bottom","1px solid #ddd");
let td1 = document.createElement('td');
let td2 = document.createElement('td');
let td3 = document.createElement('td');
td1.innerHTML = '<a href="javascript:void(0)" onclick="document.getElementsByClassName(\'questionLi\')['+workinx+'].scrollIntoView();">'+(workinx+1)+'</a>';
td2.innerHTML = '<a href="javascript:void(0)" onclick="document.getElementsByClassName(\'questionLi\')['+workinx+'].scrollIntoView();">'+data.question+'</a>';
let answerArr = await page.requestMerge(data);
let pd=false;
// 遍历数组
for (let i = 0; i < answerArr.length; i++) {
let item = answerArr[i];
// 如果为[]或者字符串则跳过
if(item.length == 0||typeof(item)=="string"){
continue;
}
pd=page.setWorkAnswer(data.type,data.options,item,inx);
if(pd){
td3.innerHTML = item.join('<br />');
td3.style.color = 'green';
defaultConfig.succ++;
break;
}
}
if(!pd){
td3.innerHTML = answerArr[0]||'暂无答案-联系阿宽';
//增加一个重试按钮
let aBtn = document.createElement("a");
aBtn.innerHTML = "重试并且-Call阿宽";
aBtn.style.color = "blue";
aBtn.style.marginLeft = "10px";
aBtn.onclick = function(){
startWorkTask(workinx);
}
//鼠标光标
aBtn.style.cursor = "pointer";
td3.appendChild(aBtn);
$(tr).css("color","red");
$(".layx_status").html("答案匹配失败,等待切换");
}
pd&&page.layx_status_msg("已答题,等待切换");
// tr数量
let trNum=tbody.getElementsByTagName("tr").length;
// 如果trNum大于workinx则替换对应td
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
if(trNum>workinx){
tbody.replaceChild(tr,tbody.getElementsByTagName("tr")[workinx]);
}else{
tbody.appendChild(tr);
}
}
await startWorkTask(defaultConfig.workinx);
defaultConfig.workinx++;
},
// 开始章节答题
startChapter: async function() {
let layx_content = document.getElementById('layx_content');
let questionList=document.getElementsByClassName('TiMu');
let inx=defaultConfig.workinx;
if(defaultConfig.workinx==0){
layx_content.innerHTML = '<table id="qlist" class="table table-bordered"><thead><tr><th>题号</th><th>题目</th><th>答案</th><th>阿宽</th></tr></thead><tbody></tbody></table>';
$("#qlist").css("text-align","left");
$("#qlist").find("th").eq(0).css("width","10%");
$("#qlist").find("th").eq(1).css("width","50%");
$("#qlist").find("th").eq(2).css("width","30%");
$("#qlist").find("th").eq(3).css("width","10%");
$("#qlist").find("tr").css("height","30px");
}
else if(defaultConfig.workinx>=questionList.length){
this.layx_status_msg(`答题完成 - 已答${defaultConfig.succ}题,未答${defaultConfig.fail}题 ${defaultConfig.autoSubmit?"【准备自动提交】":"【未开启自动提交,请手动操作】"}`);
let z=defaultConfig.succ/questionList.length;
if(defaultConfig.autoSubmit){
let btnOffset,
mouse = document.createEvent('MouseEvents');
if(z>=defaultConfig.autoSubmitRate){
if ($('#confirmSubWin:visible').length) {
btnOffset = $('a[onclick="noSubmit();"]').offset() || {top: 0, left: 0},
btnOffset = [btnOffset.left + Math.ceil(Math.random() * 46), btnOffset.top + Math.ceil(Math.random() * 26)];
mouse.initMouseEvent('click', true, true, document.defaultView, 0, 0, 0, btnOffset[0], btnOffset[1], false, false, false, false, 0, null);
_self.event = $.extend(true, {}, mouse);
delete _self.event.isTrusted;
_self.form1submit();
} else {
btnOffset = $('.Btn_blue_1')[0].click();
}
setTimeout(submitThis, Math.ceil(defaultConfig.interval * Math.random()) * 2);
}else{
if(tempSave){
return;
}
var a = "402588557,402588558,402588559,";
$("#answerwqbid").val(a);
$("#pyFlag").val("1");
setMultiChoiceAnswer()
setConnLineAnswer();
setSortQuesAnswer();
setCompoundQuesAnswer();
setProceduralQuesAnswer();
setBType();
tempSave=true;
$("#tempsave").text('阿宽正在暂存...');
if ($(".oralTestQue").length > 0) {
setOralTestAnswer();
var checkOralTest = setInterval(function () {
if( $(".oralTestQue").length == oralTestEndNum) {
clearInterval(checkOralTest)
saveWork()
}
},1000);
} else {
saveWork()
}
window.parent.postMessage(utils.notify("error","正确率不够,阿宽已帮你暂存"), '*');
}
}
clearInterval(defaultConfig.loop);
return;
}
this.layx_status_msg("阿宽提醒:答题进度:"+(inx+1)+"/"+questionList.length+" 成功"+defaultConfig.succ+"题"+" 失败"+defaultConfig.fail+"题");
async function startWorkTask(workinx){
let questionDiv = questionList[workinx];
let data = page.getQuestion("1",questionDiv);
let tbody = document.getElementById('qlist').getElementsByTagName('tbody')[0];
let tr = document.createElement('tr');
$(tr).css("border-bottom","1px solid #ddd");
let td1 = document.createElement('td');
let td2 = document.createElement('td');
let td3 = document.createElement('td');
td1.innerHTML = '<a href="javascript:void(0)" onclick="document.getElementsByClassName(\'TiMu\')['+workinx+'].scrollIntoView();">'+(workinx+1)+'</a>';
td2.innerHTML = '<a href="javascript:void(0)" onclick="document.getElementsByClassName(\'TiMu\')['+workinx+'].scrollIntoView();">'+data.question+'</a>';
let answerArr = await page.requestMerge(data);
let pd=false;
// 遍历数组
for (let i = 0; i < answerArr.length; i++) {
let item = answerArr[i];
// 如果为[]或者字符串则跳过
if(item==undefined||item.length == 0||typeof(item)=="string"){
continue;
}
pd=page.setChapterAnswer(data.type,data.options,item,inx);
if(pd){
td3.innerHTML = item.join('<br />');
td3.style.color = 'green';
defaultConfig.succ++;
break;
}
}
if(!pd){
td3.innerHTML = answerArr[0]||'暂无答案-联系阿宽';
//增加一个重试按钮
let aBtn = document.createElement("a");
aBtn.innerHTML = "重试并且-Call阿宽";
aBtn.style.color = "blue";
aBtn.style.marginLeft = "10px";
aBtn.onclick = function(){
startWorkTask(workinx);
}
//鼠标光标
aBtn.style.cursor = "pointer";
td3.appendChild(aBtn);
page.layx_status_msg("答案匹配失败,等待切换");
}else{
page.layx_status_msg("已答题,等待切换");
}
// tr数量
let trNum=tbody.getElementsByTagName("tr").length;
// 如果trNum大于workinx则替换对应td
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
if(trNum>workinx){
tbody.replaceChild(tr,tbody.getElementsByTagName("tr")[workinx]);
}else{
tbody.appendChild(tr);
}
}
startWorkTask(defaultConfig.workinx);
defaultConfig.workinx++;
},
// 获取作业分数
getScore2: function(data) {
if(data.url==undefined){
return;
}
let url=data.url
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function(response) {
let html = response.responseText;
let document1,questionList,questionListHtml;
document1 = new DOMParser().parseFromString(html, "text/html");
questionList = document1.getElementsByClassName('Py-mian1');
questionListHtml = [];
for (let i = 0; i < questionList.length; i++) {
if(i===0){
continue;
}
let questionTitle = utils.removeHtml(questionList[i].getElementsByClassName('Py-m1-title')[0].innerHTML);
let questionType = questionTitle.match(/\[(.*?)\]/)[1];
if(questionType==="单选题"||questionType==="多选题"){
// 正则去除开头[单选题]
questionTitle = questionTitle.replace(/[0-9]{1,3}.\s/ig, '').replace(/(^\s*)|(\s*$)/g, "").replace(/^【.*?】\s*/, '').replace(/\[(.*?)\]\s*/, '').replace(/\s*(\d+\.\d+分)$/, '');
let optionHtml=$(questionList[i]).find('ul.answerList li.clearfix');
let optionText = [];
optionHtml.each(function (index, item) {
let abcd=String.fromCharCode(65 + index)+".";
let optionTemp=utils.removeHtml(item.innerHTML);
if(optionTemp.indexOf(abcd)==0){
optionTemp=optionTemp.replace(abcd,"").trim();
}
optionText.push(optionTemp);
});
questionListHtml.push({
"question":questionTitle,
"type":defaultConfig.types[questionType],
"options":optionText,
"questionData":questionList[i].innerHTML
})
}
}
let postData={
"questionList":questionListHtml,
"url":url
}
log(postData);
GM_xmlhttpRequest({
method: "POST",
url: data.url1,
data:JSON.stringify(postData),
headers: {
"Content-Type": "application/json"
},
onload: function(resonse) {
let succ="ok";
}
});
}
});
},
};
// 初始化
page.init();
}
)();