Greasy Fork

Greasy Fork is available in English.

【万能】全平台自动答题脚本

支持【超星学习通】【智慧树】【职教云系列】【雨课堂】【继续教育类】【小鹅通】【安徽继续教育】【国地质大学远程与继续教育学院】等平台的测验考试,内置题库,自动答题功能全聚合。

当前为 2022-09-23 提交的版本,查看 最新版本

// ==UserScript==
// @name        【万能】全平台自动答题脚本
// @version      4.1.8
// @namespace    自动答题
// @description  支持【超星学习通】【智慧树】【职教云系列】【雨课堂】【继续教育类】【小鹅通】【安徽继续教育】【国地质大学远程与继续教育学院】等平台的测验考试,内置题库,自动答题功能全聚合。
// @author       万能
// @match        *://*/*
// @compatible   chrome firefox edge
// @grant        GM_info
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @grant        GM_getResourceText
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @run-at       document-end
// @connect      yuketang.cn
// @connect      app.itihey.com
// @connect      appwk.baidu.com
// @resource     Vue http://lib.baomitu.com/vue/2.6.0/vue.min.js
// @resource     ElementUi http://lib.baomitu.com/element-ui/2.15.9/index.js
// @resource     ElementUiCss https://lib.baomitu.com/element-ui/2.15.9/theme-chalk/index.min.css
// @resource     Table https://www.forestpolice.org/ttf/2.0/table.json
// @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.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/index.min.js
// @require      https://lib.baomitu.com/axios/0.27.2/axios.min.js
// @require      https://cdn.jsdelivr.net/gh/zyufstudio/jQuery@3a09ff54b33fc2ae489b5083174698b3fa83f4a7/jPopBox/dist/jPopBox.min.js
// @connect      lyck6.cn
// @contributionURL   https://lyck6.cn/pay
// @antifeature  payment 解锁付费题库需捐助
// ==/UserScript==

//全局配置参数
var GLOBAL = {
    time: 3E3, //查题间隔时间,不建议小于5s,如果为了安全起见最好10s以上,即10E3
    delay: 2E3, //延迟加载,页面初始化完毕之后的等待2s之后再去搜题,
    fillAnswerDelay: 1E3 //填充答案的延迟,不建议小于0.5秒,默认一秒
};


(function (exports) {
   'use strict';

   function sleep(time) {
       return new Promise((resolve) => {
           setTimeout(resolve, time);
       })
   }


   function iframeMsg(type, message) {
       try{
           exports.top.document.getElementById('iframeNode').contentWindow.vueDefinedProp(type, message);
       }catch (e) {
           
       }
      
   }

   function filterImg(dom) {
       return $(dom).clone().find("img[src]").replaceWith(function () {
           return $("<p></p>").text('<img src="' + $(this).attr("src") + '">');
       }).end().find("iframe[src]").replaceWith(function () {
           return $("<p></p>").text('<iframe src="' + $(this).attr("src") + '"></irame>');
       }).end().text().trim();
   }

   // 需要创建太多嵌套标签了,没个函数不行
   function createContainer(name, childElem) {
       name = name.toLowerCase();
       let elem = exports.top.document.createElement(name);
       elem.style.display = 'block';
       // id 改成驼峰式
       elem.id = name.replace('hcsearche', 'hcSearche').replace(/\-[a-z]/g, function (w) {
           return w.replace('-', '').toUpperCase();
       });
       if (childElem) {
           if (Array.isArray(childElem) === false)
               childElem = [childElem];
           for (let i = 0; i < childElem.length; i++)
               elem.appendChild(childElem[i]);
       }
       return elem;
   }


   function dragModel(drag) {
       const TOP = exports.top;
       //获取drag元素
       // let drag = document.getElementById("drag")
       //当鼠标按下时
       drag.onmousedown = function (e) {
           drag.style.cursor = 'move';
           //做到浏览器兼容
           e = e || window.event;
           let diffX = e.clientX - drag.offsetLeft;
           let diffY = e.clientY - drag.offsetTop;
           //当拉着box移动时
           exports.top.onmousemove = function (e) {

               // 浏览器兼容
               e = e || top.event;
               let left = e.clientX - diffX;
               let top = e.clientY - diffY;

               if (left < 0) {
                   left = 0;
               } else if (left > TOP.innerWidth * 0.95 - drag.offsetWidth) {
                   left = TOP.innerWidth * 0.95 - drag.offsetWidth;
               }

               if (top < 0) {
                   top = 0;
               } else if (top > TOP.innerHeight - drag.offsetHeight) {
                   top = TOP.innerHeight - drag.offsetHeight;
               }

               console.log(drag.style.left);
               console.log(drag.style.top);
               drag.style.left = left + 'px';
               drag.style.top = top + 'px';
           };

           // 当鼠标抬起时
           exports.top.onmouseup = function (e) {
               drag.style.cursor = 'default';
               this.onmousemove = null;
               this.onmouseup = null;
           };
       };
   }

   function defaultWorkTypeResolver($options) {
       function count(selector) {
           let c = 0;
           // $options.each(fun)
           for (const option of $options || []) {
               if ($(option).find(selector) !== null) {
                   c++;
               }
           }
           return c;
       }

       return count('[type="radio"]') === 2
           ? 3
           : count('[type="radio"]') > 2
               ? 0
               : count('[type="checkbox"]') > 2
                   ? 1
                   : count('textarea') >= 1
                       ? 4
                       : undefined;
   }

   function formatAnswer(res) {
       let msg = res.msg, num = res.data.num;
       let success = res.code === 200;
       if (res.code === 104) {
           msg = '积分不足请关闭收费答题答题功能\n或者请点击【获取积分】进行充值';
       }
       return {
           success,
           msg,
           num,
           list: res.data.list
       }
   }

   /**
    * 相似度对比
    * @param s 文本1
    * @param t 文本2
    * @param f 小数位精确度,默认2位
    * @returns {string|number|*} 百分数前的数值,最大100. 比如 :90.32
    */

   // similar("我不知道啊,不行","我不知道啊,不行",1)
   // xsd("我不知道啊不行", "我也不知道啊不行")

   function similar(s, t, f) {
       if (!s || !t) {
           return 0
       }
       if (s === t) {
           return 100;
       }
       var l = s.length > t.length ? s.length : t.length;
       var n = s.length;
       var m = t.length;
       var d = [];
       f = f || 2;
       var min = function (a, b, c) {
           return a < b ? (a < c ? a : c) : (b < c ? b : c)
       };
       var i, j, si, tj, 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++) {
           si = s.charAt(i - 1);
           for (j = 1; j <= m; j++) {
               tj = t.charAt(j - 1);
               if (si === tj) {
                   cost = 0;
               } else {
                   cost = 1;
               }
               d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
           }
       }
       let res = (1 - d[n][m] / l) * 100;
       return res.toFixed(f)

   }

   function answerSimilar(src, list) {
       return $.map(list, function (val) {
           return similar(formatString(val), formatString(src), 2)
       })
   }


   /** 判断答案是否为A-Z的文本, 并且字符序号依次递增, 并且 每个字符是否都只出现了一次 */
   function isPlainAnswer(answer) {
       if (answer.length > 8 || !/[A-Z]/.test(answer)) {
           return false;
       }
       let counter = {};
       let min = 0;
       for (let i = 0; i < answer.length; i++) {
           if (answer.charCodeAt(i) < min) {
               return false;
           }
           min = answer.charCodeAt(i);
           counter[min] = (counter[min] || 0) + 1;
       }
       return true;
   }

   /**
    *
    * @param list 获取的答案列表
    * @param data 发送请求的data
    * @param $options 选项的dom
    * @param handler 执行的函数
    */
   async function defaultQuestionResolve(list, data, handler) {
       console.log(data);
       //最后的选项 集合
       let targetOptionsList = [];
       for (const answers of list) {
           console.log('当前答案', JSON.stringify(answers));
           if (data.type === 4 || data.type === 2) {
               let ans = answers.length > data.$options.length ? answers.slice(0, data.$options.length) : answers;
               ans.forEach((val, index) => {
                   handler(data.type, val, data.$options.eq(index));
               });
               return {ok: true, ans: answers.join('===='), question: data.question};
           } else if (data.type === 3) {
               if (answers.join().match(/(^|,)(正确|是|对|√|T|ri|false)(,|$)/)) {
                   if (data.options[0].match(/(^|,)(正确|是|对|√|T|ri|true)(,|$)/)) {
                       handler(data.type, '', data.$options.eq(0));
                   } else if (data.options[0].match(/(^|,)(错误|否|错|×|F|不是|wr|false)(,|$)/)) {
                       handler(data.type, '', data.$options.eq(1));
                   }


                   return {ok: true, ans: '正确', question: data.question};
               } else if (answers.join().match(/(^|,)(错误|否|错|×|F|不是|wr|false)(,|$)/)) {
                   if (data.options[0].match(/(^|,)(正确|是|对|√|T|ri|true)(,|$)/)) {
                       handler(data.type, '', data.$options.eq(1));
                   } else if (data.options[0].match(/(^|,)(错误|否|错|×|F|不是|wr|false)(,|$)/)) {
                       handler(data.type, '', data.$options.eq(0));
                   }

                   handler(data.type, '', data.$options.eq(1));
                   return {ok: true, ans: '错误', question: data.question};
               }
           } else if (data.type === 0 || data.type === 1) {
               let targetOptions = new Set();
               //选项内容
               for (const ans of answers) {
                   if (ans.length === 1 && isPlainAnswer(ans)) {
                       const index = ans.charCodeAt(0) - 65;
                       targetOptions.add(data.$options.eq(index));
                   }
               }
               //文字内容
               answers.forEach((val, index) => {
                   val = formatString(val);
                   //精确匹配
                   let optIndex = $.inArray(val, data.options);
                   if (optIndex >= 0) {
                       targetOptions.add(data.$options.eq(optIndex));
                   } else {
                       if ((targetOptions.size > 1 && data.type === 1)) {
                           console.log('多选题已经有合适的选项,不进行模糊匹配');
                       } else {
                           //模糊匹配
                           const ratings = answerSimilar(val, data.options);
                           /**  找出最相似的选项 */
                           let max = 0;
                           ratings.forEach((rating, i) => {
                               if (rating > max) {
                                   max = rating;
                                   optIndex = i;
                               }
                           });
                           if (optIndex !== -1 && max > 60) {
                               /** 经自定义的处理器进行处理 */
                               targetOptions.add(data.$options.eq(optIndex));
                           }
                       }
                   }
               });
               //已经判断完毕
               targetOptionsList.push(targetOptions);
           }
       }
       console.log(targetOptionsList);
       let set = new Set();//最后的set集合
       let index = 0;//取用的第几个答案
       if (data.type === 0) {
           for (let targetOptionsListElement of targetOptionsList) {
               if (targetOptionsListElement && targetOptionsListElement.size === 1) {
                   set = targetOptionsListElement;
                   index = targetOptionsList.indexOf(targetOptionsListElement);
                   break;
               }
           }
       } else if (data.type === 1) {
           for (let targetOptionsListElement of targetOptionsList) {
               if (targetOptionsListElement && targetOptionsListElement.size > set.size) {
                   set = targetOptionsListElement;
                   index = targetOptionsList.indexOf(targetOptionsListElement);
               }
           }
       }
       console.log(set);
       if (set.size > 0) {
           let items = Array.from(set);
           //set 遍历无法设置延迟,转为list后循环
           for (let i in items) {
               setTimeout(() => {
                   handler(data.type, '', items[i]);
               }, i * GLOBAL.fillAnswerDelay);
           }
           await sleep(GLOBAL.fillAnswerDelay * set.size);
           return {ok: true, ans: list[index].join('===='), question: data.question};
       } else {
           return {ok: false, question: data.question, ans: list.join('====')};
       }

   }

   //HTML反转义
   function HTMLDecode(text) {
       var temp = document.createElement("div");
       temp.innerHTML = text;
       var output = temp.innerText || temp.textContent;
       temp = null;
       return output;
   }

   function formatString(src) {
       return (src.includes('img') ? src : HTMLDecode(src)).replace(/\s+/, ' ').replace(/[\uff01-\uff5e]/g, function (str) {
           return String.fromCharCode(str.charCodeAt(0) - 65248);
       }).replace(/^[A-Za-z][\.、]/, '').replace(/\(\d+\s分\)$/, '')
           .replace(/[“”]/g, '"')
           .replace(/^\d+、/, '')
           .replace(/(\d+\s+分)$/, '')
           .replace(/[‘’]/g, "'")
           .replace(/。/g, '.')
           .replace(/\+/g, '').replace(/;$/, '').toLowerCase().trim();
   }


   const TYPE = {
       multichoice: 1,
       singlechoice:0,
       bijudgement:3,
       单项选择题: 0,
       单选题: 0,
       多选题: 1,
       填空题: 2,
       判断题: 3,
       简答题: 4,
       名词解释: 5,
       论述题: 6,
       计算题: 7,
       其它: 8,
       分录题: 9,
       资料题: 10,
       连线题: 11,
       排序题: 13,
       完形填空: 14,
       阅读理解: 15,
       口语题: 18,
       听力题: 19,
   };

   /**
    * 图片url 转 base64
    * @param url
    * @returns {Promise<unknown>}
    */
   const url2Base64 = (url) => new Promise((resolve, reject) => {
       GM_xmlhttpRequest({
           url: url,
           responseType: 'blob',
           onload: function (r) {
               // "s".replaceAll()
               const fileReader = new FileReader();
               fileReader.readAsDataURL(r.response);
               fileReader.onload = (e) => {
                   resolve(e.target.result);
               };
           }
       });
   });

   /**
    * 图片透明背景转白色
    * @param base64
    * @returns {Promise<unknown>}
    */
   const imgHandle = (base64) => new Promise((resolve, reject) => {
       const canvas = document.createElement("canvas");
       const context = canvas.getContext("2d");

       const image = new Image();
       image.setAttribute("crossOrigin", 'Anonymous');
       image.src = base64;
       image.onload = function () {
           canvas.width = image.width;
           canvas.height = image.height;
           context.fillStyle = "#fff"; /// set white fill style
           context.fillRect(0, 0, canvas.width, canvas.height);
           context.drawImage(image, 0, 0);
           canvas.toBlob((blob) => {
               resolve(blob);
           });
       };
   });


   const imgOcr = (blob) => new Promise((resolve, reject) => {
       var fd = new FormData();
       fd.append("image", blob, "1.png");
       GM_xmlhttpRequest({
           url: "https://appwk.baidu.com/naapi/api/totxt",
           method: "POST",
           responseType: 'json',
           data: fd,
           onload: function (r) {
               const res = r.response.words_result.map(item => {
                   return item.words
               }).join('');
               resolve(res);
           }
       });
   });

   const yuketangOcr = async url => {
       //将图片下载转 base64
       const base64 = await url2Base64(url);
       //图片转白色背景
       const img_blob = await imgHandle(base64);
       //识别图片
       const res = await imgOcr(img_blob);
       return res
   };

   function showPanel() {
       let html =
           `
        <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
      `+GM_getResourceText('ElementUiCss')+`
      .el-table .warning-row {
        background: oldlace;
      }
      .el-table .success-row {
        background: #f0f9eb;
      }
      *{
        padding: 0px;
        margin: 0px;
      }
      .el-form-item{
        display: flex;
        justify-content: center
      }
    </style>
</head>
<body>
<div id="app">
    <div id="drag_auto_answer" style="position: absolute;">
        <el-main
                class="onlinekf"
                style="min-width: 328px;margin-top: 0px;margin-left: 0px;border: 0px solid #666;width: 100%;background-color: #ffffff; padding: 15px 0px 0px; z-index: 99999;">
            <el-row>
                <el-form>
                    <el-form-item label="请输入手机号" style="margin-top: -20px">
                        <el-input v-model="opt.token" placeholder="请输入内容" style="max-width: 130px" size="mini"></el-input>
                        <el-button  @click="btnClick(opt.token,'opt.confim')" size="mini" type="warning">确定</el-button>
                    </el-form-item>
                </el-form>
            </el-row>
            <el-row style="margin-top: -20px;margin-bottom: 5px;display: flex">
                <el-alert
                        style="display: block"
                        :title="tip"
                        :closable="false"
                        type="success">
                    <el-button v-if="need_jump" @click="btnClick(opt.jump,'opt.jump')" size="mini" type="info">跳过本题</el-button>
                    <el-button v-if="!hidden" @click="btnClick(opt.auto_jump,'opt.auto_jump')" size="mini" type="warning">{{opt.auto_jump ? '停止自动切换': '开启自动切换'}}</el-button>
                </el-alert>
            </el-row>
            <el-row style="display: flex;flex-flow: wrap;width: 100%;align-items: flex-start;">
                <el-button v-if="!hidden" @click="btnClick(opt.stop,'opt.stop')" size="mini" type="success" style="margin-left: 5px">{{!opt.stop ? '暂停答题': '继续答题'}}</el-button>
                <el-button size="mini" type="info" style="margin-left: 5px">重新查询</el-button>
                <el-button @click="btnClick(opt.start_pay,'opt.start_pay')" size="mini" type="primary" style="margin-left: 5px">{{opt.start_pay ?'关闭收费题库' : '开启收费题库'}}</el-button>
                <el-button size="mini" type="danger" style="margin-left: 5px"><a style="text-decoration:none;color: aliceblue" target="_blank" href="https://lyck6.cn/pay" >获取积分</a></el-button>
            </el-row>

            <el-table size="mini" :data="tableData" style="width: 100%;margin-top: 5px" :row-class-name="tableRowClassName">
                <el-table-column prop="index" label="题号" width="45"></el-table-column>
                <el-table-column prop="question" label="问题" width="130"></el-table-column>
                <el-table-column prop="answer" label="答案" width="130"></el-table-column>
            </el-table>
        </el-main>
    </div>
</div>
</body>
<script>`+GM_getResourceText('Vue')+`</script>
<script>`+GM_getResourceText('ElementUi')+`</script>
<script>
    new Vue({
        el: '#app',
        data: function () {
            return {
                hidden: false,
                need_jump: false,
                tip: '正在搜索',
                opt:{
                    token: '` + GM_getValue('token') + `',
                    auto_jump: ` + GM_getValue('auto_jump') + `,
                    stop: false,
                    start_pay: ` + GM_getValue('start_pay') + `
                },
                input: '',
                visible: false,
                tableData: []
            }
        },
        mounted() {
        },
        created(){
            /**
            *  油猴脚本 给 iframe 通信的方法
            * @param type 消息类型
            * @param receiveParams 消息参数
            */
            window['vueDefinedProp'] = (type,receiveParams) => {
                //**
                if (type === 'push'){
                    let length = this.tableData.length
                    this.tableData.push({index: length + 1,question: receiveParams.question,answer: receiveParams.answer,ok:receiveParams.ok})
                }else if (type === 'clear'){
                    this.tableData = []
                }else if (type === 'tip'){
                    if (receiveParams.type && receiveParams.type === 'jump'){
                         window.parent.postMessage({"type": 'jump'}, '*');
                    }else if (receiveParams.type && receiveParams.type === 'error'){
                         this.need_jump = true
                    }else if (receiveParams.type && receiveParams.type === 'hidden'){
                         this.hidden = true
                    }else if (receiveParams.type && receiveParams.type === 'stop'){
                         this.opt.stop = true
                    }
                   
                    this.tip = receiveParams.tip
                }
            }
        },
        methods: {
            tableRowClassName({row, rowIndex}) {
                return row.ok ? 'success-row': 'warning-row'
            },
            btnClick(e,type){
                if (type === 'opt.stop'){//暂停搜索
                    this.opt.stop = !this.opt.stop
                    this.tip = this.opt.stop? '已暂停搜索': '继续搜索'
                     window.parent.postMessage({type: 'stop',val:this.opt.stop}, '*');
                }else if (type === 'opt.start_pay'){
                    this.opt.start_pay = ! this.opt.start_pay
                     window.parent.postMessage({type: 'start_pay',flag:this.opt.start_pay}, '*');
                }else if (type === 'opt.auto_jump'){//开启自动切换
                    this.opt.auto_jump = ! this.opt.auto_jump
                    window.parent.postMessage({type: 'auto_jump',flag:this.opt.auto_jump}, '*');
                }else if (type === 'opt.jump'){//跳过本题
                    window.parent.postMessage({type: 'jump'}, '*');
                    this.need_jump = false
                }else if (type === 'opt.confim'){
                    window.parent.postMessage({type: 'confim',token:e}, '*');
                }
            }
        }
    })
</script>
</html>
`;
       addModal2(html);
   }
   function addModal2(html, newPos, footerChildNode = false) {
       // // // header link
       let headersNode = createContainer('headers-node');
       let adNode = exports.top.document.createElement('img');
       adNode.setAttribute('src', 'http://lyck6.cn/img/6.png');
       adNode.setAttribute("draggable", "false");
       adNode.setAttribute("width", "98%");
       adNode.setAttribute("height", "121px");
       adNode.setAttribute("style", "display: block;margin-bottom: -2%;padding-left: 1%;width: 98%;height: 121px");
       // linkNode.setAttribu/te('data-seindex', 0);
       // linkNode.setAttribute('data-seclass', 'baidu');
       // linkNode.innerHTML =
       // linkNode.setAttribute('data-securrent', 'true');
       // linkNode.style.color = '#586069';
       //
       // linkNode.addEventListener('click', function () {
       //     window.open('https://www.itihey.com')
       // });
       //
       headersNode.appendChild(adNode);


       // iframe
       let iframeNode = exports.top.document.createElement('iframe');
       iframeNode.id = 'iframeNode';
       iframeNode.setAttribute('width', '100%');
       iframeNode.setAttribute("height", "350px");
       iframeNode.setAttribute('frameborder', '0');
       iframeNode.srcdoc = html;

       // let headerNode = createContainer('hcsearche-modal-header', [linksNode]);
       // let bodyNode = createContainer('hcsearche-modal-body', iframeNode);
       //
       // let footerNode = createContainer('hcsearche-modal-footer', footerChildNode);
       //
       let contentNode = createContainer('content-modal', [headersNode, iframeNode]);

       let modal = renderModal(contentNode);
       // return model
       dragModel(modal);
   }


   // 搜索窗口可以根据设置决定是相对文档还是相对窗口定位
   function renderModal(childElem, newPos) {
       //不是自动关闭就是绝对定位 或者依据用户设置
       return render('modal', 'model-id', childElem);
   }

   function render(tagName, elemId, childElem, isFixed, newPos) {
       // console.log('开始渲染 model', isFixed)
       let doc = exports.top.document;
       let elem = doc.getElementById(elemId);
       if (elem) {
           elem.innerHTML = '';
       } else {
           elem = doc.createElement(tagName);
           elem.id = elemId;
           doc.body.appendChild(elem);
       }
       let contentNode = createContainer(tagName + '-container', childElem);
       elem.appendChild(contentNode);
       // class ID same
       elem.classList.add(elemId);
       // let X = false;
       // let Y = false;
       // if (!newPos) {
       //     X = elem.style.left.replace('px', '');
       //     console.log(X, "X")
       //     Y = elem.style.top.replace('px', '');
       // }
       // if (!X) {
       //     let pos = getXY(elem.offsetWidth, elem.offsetHeight);
       //     X = pos.X;
       //     Y = pos.Y;
       //     // 相对文档定位时需要将文档滚动距离加上
       //     if (!isFixed) {
       //         Y += window.pageYOffset;
       //     }
       // }
       elem.style.zIndex = '9999999';
       // elem.style.width = '430px'
       // elem.style.height = '660px'
       elem.style.position = 'fixed';
       elem.style.left = '30px';
       elem.style.top = '30px';
       setTimeout(function () {
           elem.classList.add(elemId + '-show');
       }, 10);
       return elem;
   }

   async function searchAnswer(data) {
       return new Promise((resolve, reject) => {
           GM_xmlhttpRequest({
               method: "POST",
               url: "https://lyck6.cn/api/autoAnswer/" + (GM_getValue('start_pay') ? GM_getValue('token') : 0),
               headers: {
                   "Content-Type": "application/json;charset=utf-8",
                   "Version": GM_info.script.version
               },
               data: JSON.stringify(data),
               timeout: 10 * 1000,
               onload: function (r) {
                   console.log(r.responseText);
                   resolve(JSON.parse(r.responseText));
               },
               onerror: function (e) {
                   reject(e);
               }
           });
       })
   }

   /**
    * 自动答题核心代码
    */

   /**
    *
    * @param select 选择的元素{
    *             root: '.questionLi',
    *             elements: {
    *                 question: 'h3 div',
    *                 options: '.answerBg .answer_p, .textDIV, .eidtDiv',
    *                 type: 'input[name^=type]:eq(0)'
    *             }
    *         }
    * @param searchHander 规范化 题目 选项 类型
    * @param fillHander 填充答案的函数
    * @param onFinish 答题完成之后的回调函数 need_jump是否需要跳转
    * @constructor
    */

   var WorkerJS = function (select, searchHander, fillHander, onFinish = function (need_jump) {
   }, fillFinish = function () {
   }) {

       GLOBAL.index = 0;
       /**
        * 根据传入的 元素进行初始化
        */
       this.init = async function ($TiMu, select) {
           let question = formatString(filterImg($TiMu.find(select.elements.question)));
           let data = {
               question: question.length === 0 ? $TiMu.find(select.elements.question) : question,
               $options: select.elements.$options ? $TiMu.find(select.elements.$options) : undefined,
               options: select.elements.options? jQuery.map($TiMu.find(select.elements.options), function (val) {
                   return formatString(filterImg(val))
               }):undefined
           };
           data.type = select.elements.type ? ($TiMu.find(select.elements.type).text() || $TiMu.find(select.elements.type).val()) : $TiMu;

           return await searchHander(data)

       };

       this.fillAnswer = async function () {
           let arr = jQuery(select.root);
           console.log(arr.length);
           GLOBAL.setInterval = async () => {
               console.log('当前index', GLOBAL.index);
               if (GLOBAL.index >= arr.length) {
                   clearInterval(GLOBAL.loop);
                   delete GLOBAL.loop;
                   let auto_jump = GM_getValue('auto_jump') === undefined || GM_getValue('auto_jump');

                   //答题事件监听,如果完成还要继续重新运行则返回 true
                   const next = onFinish(auto_jump);
                   if (next) {
                       GLOBAL.index = 0;
                       setTimeout(() => {
                           this.fillAnswer();
                       }, GLOBAL.time);
                   }


                   if (auto_jump) {
                       iframeMsg('tip', {type: 'jump', tip: '自动答题已完成,即将切换下一题'});
                       //如果在5秒内 没有切换就是答题完成了
                       next || setTimeout(() => {
                           iframeMsg('tip', {type: 'hidden', tip: '自动答题已完成,请检查提交'});
                       }, GLOBAL.time);
                   } else {
                       iframeMsg('tip', {tip: '自动答题已完成' + (arr.length === 1 ? ',请手动切换' : '请检查提交')});
                   }

                   return true
               }
               try {
                   let data = await this.init(jQuery(arr[GLOBAL.index++]), select);// arr[GLOBAL.index]
                   if (!data) return
                   iframeMsg('tip', {tip: '准备答第' + (GLOBAL.index) + '题'});
                   //格式化返回答案 成为二维数组
                   const formatAns = data.answer ? {
                       success: true,
                       num: '免费',
                       list: [data.answer]
                   } : formatAnswer(await searchAnswer({question: data.question}));
                   if (formatAns.success) {
                       //解析答案
                       iframeMsg('tip', {tip: '准备填充答案,' + (formatAns.num.includes('免费题库') ? '免费题库不扣积分' : '剩余积分:' + formatAns.num)});
                       let r = await defaultQuestionResolve(formatAns.list, data, fillHander);
                       iframeMsg('push', {index: GLOBAL.index, question: r.question, answer: r.ans, ok: r.ok});
                   } else {
                       iframeMsg('tip', {tip: formatAns.msg});
                   }

               } catch (e) {
                   iframeMsg('tip', {type: 'error', tip: '发生异常' + e});
               } finally {
                   fillFinish();
               }

           };

           GLOBAL.loop = setInterval(GLOBAL.setInterval, GLOBAL.time);
           console.log('GLOBAL.loop', GLOBAL.loop);
       };
   };

   /**
    * 借鉴 网页限制解除(改)
    * 原作者 qxin i
    * 开源地址 http://greasyfork.icu/zh-CN/scripts/28497-%E7%BD%91%E9%A1%B5%E9%99%90%E5%88%B6%E8%A7%A3%E9%99%A4-%E6%94%B9/code
    */
   // 初始化 init func  这里才是核心
   function init() {
       rule = rwl_userData.rules.rule_def;
       hook_eventNames = rule.hook_eventNames.split("|");
       // TODO Allowed to return value
       unhook_eventNames = rule.unhook_eventNames.split("|");
       eventNames = hook_eventNames.concat(unhook_eventNames);

       if (rule.dom0) {
           setInterval(clearLoop, 10 * 1000);
           setTimeout(clearLoop, 1500);
           window.addEventListener('load', clearLoop, true);
           clearLoop();
       }

       // hook addEventListener //导致搜索跳转失效的原因
       if (rule.hook_addEventListener) {
           EventTarget.prototype.addEventListener = addEventListener;
           document.addEventListener = addEventListener;
           if (hasFrame) {
               for (let i = 0; i < hasFrame.length; i++) {
                   hasFrame[i].contentWindow.document.addEventListener = addEventListener;
               }
           }
       }

       // hook preventDefault
       if (rule.hook_preventDefault) {
           Event.prototype.preventDefault = function () {
               if (hook_eventNames.indexOf(this.type) < 0) {
                   Event_preventDefault.apply(this, arguments);
               }
           };

           if (hasFrame) {
               for (let i = 0; i < hasFrame.length; i++) {
                   hasFrame[i].contentWindow.Event.prototype.preventDefault = function () {
                       if (hook_eventNames.indexOf(this.type) < 0) {
                           Event_preventDefault.apply(this, arguments);
                       }
                   };
               }
           }
       }

       // Hook set returnValue
       if (rule.hook_set_returnValue) {
           Event.prototype.__defineSetter__('returnValue', function () {
               if (this.returnValue !== true && hook_eventNames.indexOf(this.type) >= 0) {
                   this.returnValue = true;
               }
           });
       }
   }

   // Hook addEventListener proc
   function addEventListener(type, func, useCapture) {
       var _addEventListener = this === document ? document_addEventListener : EventTarget_addEventListener;
       if (hook_eventNames.indexOf(type) >= 0) {
           _addEventListener.apply(this, [type, returnTrue, useCapture]);
       } else if (unhook_eventNames.indexOf(type) >= 0) {
           var funcsName = storageName + type + (useCapture ? 't' : 'f');

           if (this[funcsName] === undefined) {
               this[funcsName] = [];
               _addEventListener.apply(this, [type, useCapture ? unhook_t : unhook_f, useCapture]);
           }

           this[funcsName].push(func);
       } else {
           _addEventListener.apply(this, arguments);
       }
   }

   // 清理循环
   function clearLoop() {
       rule = clear(); // 对于动态生成的节点,随时检测
       var elements = getElements();

       for (var i in elements) {
           for (var j in eventNames) {
               var name = 'on' + eventNames[j];
               if (Object.prototype.toString.call(elements[i]) == "[object String]") {
                   continue;
               }
               if (elements[i][name] !== null && elements[i][name] !== onxxx) {
                   if (unhook_eventNames.indexOf(eventNames[j]) >= 0) {
                       elements[i][storageName + name] = elements[i][name];
                       elements[i][name] = onxxx;
                   } else {
                       elements[i][name] = null;
                   }
               }
           }
       }

       document.onmousedown = function () {
           return true;
       };
   }

   // 返回true的函数
   function returnTrue(e) {
       return true;
   }

   function unhook_t(e) {
       return unhook(e, this, storageName + e.type + 't');
   }

   function unhook_f(e) {
       return unhook(e, this, storageName + e.type + 'f');
   }

   function unhook(e, self, funcsName) {
       var list = self[funcsName];
       for (var i in list) {
           list[i](e);
       }

       e.returnValue = true;
       return true;
   }

   function onxxx(e) {
       var name = storageName + 'on' + e.type;
       this[name](e);

       e.returnValue = true;
       return true;
   }

   // 获取所有元素 包括document
   function getElements() {
       var elements = Array.prototype.slice.call(document.getElementsByTagName('*'));
       elements.push(document);

       // 循环所有 frame 窗口
       var frames = document.querySelectorAll("frame");
       if (frames) {
           hasFrame = frames;
           var frames_element;
           for (let i = 0; i < frames.length; i++) {
               frames_element = Array.prototype.slice.call(frames[i].contentWindow.document.querySelectorAll("*"));
               elements.push(frames[i].contentWindow.document);
               elements = elements.concat(frames_element);
           }
       }
       return elements;
   }


   var settingData = {
       "status": 1,
       "version": 0.1,
       "message": "",
       "positionTop": "0",
       "positionLeft": "0",
       "positionRight": "auto",
       "addBtn": false,
       "connectToTheServer": false,
       "waitUpload": [],
       "currentURL": "null",
       "shortcut": 3,
       // 域名规则列表
       "rules": {},
       "data": []
   };

   var rwl_userData = null;
   var rule = null;
   var hasFrame = false;

   // 储存名称
   var storageName = "storageName";
   // 要处理的 event 列表
   var hook_eventNames, unhook_eventNames, eventNames;
   // 储存被 Hook 的函数
   var EventTarget_addEventListener = EventTarget.prototype.addEventListener;
   var document_addEventListener = document.addEventListener;
   var Event_preventDefault = Event.prototype.preventDefault;

   // 查看本地是否存在旧数据
   rwl_userData = GM_getValue("rwl_userData");
   if (!rwl_userData) {
       rwl_userData = settingData;
   }
   // 自动更新数据
   for (let value in settingData) {
       if (!rwl_userData.hasOwnProperty(value)) {
           rwl_userData[value] = settingData[value];
           GM_setValue("rwl_userData", rwl_userData);
       }
   }




   /**
    * 原作者 [email protected]
    * 开源地址 https://scriptcat.org/script-show-page/432/code
    * 特别感谢 wyn大佬 提供的 字典匹配表
    */
   function removeF() {
       var md5 = $.md5;
       // 判断是否存在加密字体
       var $tip = $('style:contains(font-cxsecret)');
       if (!$tip.length) return;

   // 解析font-cxsecret字体
       var font = $tip.text().match(/base64,([\w\W]+?)'/)[1];
       font = Typr.parse(base64ToUint8Array(font))[0];

   // 匹配解密字体
       var table = JSON.parse(GM_getResourceText('Table'));
       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'); // 移除字体加密

       function 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;
       }
   }


   function start() {

       setInterval(function () {
           try {removeF();} catch (e) {}
           try {init();} catch (e) {}

       }, 500);
   }

   function chaoxingOldExam() {
       showPanel();
       setTimeout(() => {
           new WorkerJS({
               root: '.TiMu',
               elements: {
                   question: '.Cy_TItle .clearfix',
                   options: '.Cy_ulTop .clearfix',//文字的选项列表
                   $options: ':radio, :checkbox, .Cy_ulTk textarea',//绑定的事件的 dom列表
                   type: '[name^=type]:not([id])'
               }
           }, (obj) => {
               obj.type = parseInt(obj.type);
               if (obj.type === 3) {
                   obj.options = ['正确', '错误'];
               }
               return obj
           }, (type, answer, $option) => {
               if (type === 0 || type === 3 || type === 1) {
                   $option.get(0).click();
               } else if (type === 4 || type === 2) {
                   UE.getEditor($option.attr('name')).setContent(answer);
               }
           }, (auto_jump) => {
               auto_jump && setInterval(function() {
                   const btn = $('.saveYl:contains(下一题)').offset();
                   var mouse = document.createEvent('MouseEvents'),
                       arr = [btn.left + Math.ceil(Math.random() * 80), btn.top + Math.ceil(Math.random() * 26)];
                   mouse.initMouseEvent('click', true, true, document.defaultView, 0, 0, 0, arr[0], arr[1], false, false, false, false, 0, null);
                   _self.event = $.extend(true, {}, mouse);
                   delete _self.event.isTrusted;
                   _self.getTheNextQuestion(1);
               }, Math.ceil(GLOBAL.time * Math.random()) * 2);
           }).fillAnswer();
       }, GLOBAL.delay);
   }


   /**
    * 超星章节测验,新版旧版通用
    */
   function chaoxingQuiz() {
       removeF();
       showPanel();
       setTimeout(() => {
           new WorkerJS({
               root: '.clearfix .TiMu',
               elements: {
                   question: '.Zy_TItle .clearfix',
                   options: 'ul:eq(0) li .after',//文字的选项列表
                   $options: 'ul:eq(0) li :radio,:checkbox,textarea',//绑定的事件的 dom列表
                   type: 'input[name^=answertype]'
               }
           }, (obj) => {
               obj.question = obj.question.replace(/\s+/g,'');
               obj.type = parseInt(obj.type);
               if (obj.type === 3) {
                   obj.options = ['正确', '错误'];
               }
               return obj
           }, (type, answer, $option) => {
               if (type === 0 || type === 3 || type === 1) {
                   $option.get(0).click();
               } else if (type === 4 || type === 2) {
                   UE.getEditor($option.attr('name')).setContent(answer);
               }
           }).fillAnswer();
       }, GLOBAL.delay);
   }

   function chaoxingNewWork() {
       showPanel();
       setTimeout(() => {
           let cxWork = new WorkerJS({
               root: '.questionLi',
               elements: {
                   question: 'h3',
                   options: '.stem_answer .answerBg .answer_p, .textDIV, .eidtDiv',
                   $options: '.stem_answer .answerBg, .textDIV, .eidtDiv',
                   type: 'input[type^=hidden]:eq(0)'
               }
           }, (obj) => {
               obj.type = parseInt(obj.type);
               //多选题清楚样式,清楚已经保存的结果
               obj.type === 1 && $.each(obj.$options, (index, val) => {
                   $(val).find('.check_answer,.check_answer_dx').length === 1 && $(val).click();
               });
               return obj
           }, (type, answer, $option) => {
               if (type === 0 || type === 1 || type === 3) {
                   if ($option.find('.check_answer,.check_answer_dx').length === 0) {
                       $option.click();
                   }
               } else if (type === 4 || type === 2) {
                   UE.getEditor($option.find('textarea').attr('name')).setContent(answer);
               }
           }, (auto_jump) => {
               /**
                * 答题成功之后要跳转了
                */
               auto_jump && setTimeout(() => {
                   $('.nextDiv .jb_btn:contains("下一题")').click();
               }, GLOBAL.time / 5);
           });
           cxWork.fillAnswer();
       }, GLOBAL.delay);
   }


   function chaoxingNewExam(i) {
       showPanel();
       setTimeout(() => {
           let cxWork = new WorkerJS({
               root: '.questionLi',
               elements: {
                   question: 'h3 div',
                   options: '.answerBg .answer_p, .textDIV, .eidtDiv',
                   $options: '.answerBg, .textDIV, .eidtDiv',
                   type: 'input[name^=type]:eq(' + i + ')'
               }
           }, (obj) => {
               obj.type = parseInt(obj.type);
               //多选题清楚样式,清楚已经保存的结果
               obj.type === 1 && $.each(obj.$options, (index, val) => {
                   $(val).find('.check_answer,.check_answer_dx').length === 1 && $(val).click();
               });
               return obj
           }, (type, answer, $option) => {
               if (type === 0 || type === 1 || type === 3) {
                   if ($option.find('.check_answer,.check_answer_dx').length === 0) {
                       $option.click();
                   }
               } else if (type === 4 || type === 2) {
                   UE.getEditor($option.find('textarea').attr('name')).setContent(answer);
               }
           }, (auto_jump) => {
               /**
                * 答题成功之后要跳转了
                */
               auto_jump && setTimeout(() => {
                   $('.nextDiv .jb_btn:contains("下一题")').click();
               }, GLOBAL.time / 5);
           });
           cxWork.fillAnswer();
       }, GLOBAL.delay);
   }

   function ZjyExam() {
       showPanel();
       setTimeout(() => {
           GM_xmlhttpRequest({
               method: "GET",
               url: 'https://lyck6.cn/api/init/zjy?id='+unsafeWindow.examRecordId,
               timeout: 10 * 1000,
               onload: function (r) {
                   console.log('初始化',r.responseText);
               }
           });
           new WorkerJS({
               root: '.q_content',
               elements: {
                   question: '.divQuestionTitle',
                   options: '.questionOptions .q_option',
                   $options: '.questionOptions .q_option div'
               }
           }, (obj) => {
               obj.type = TYPE[obj.type.next().attr('answertype')];
               obj.type = obj.type ? obj.type : defaultWorkTypeResolver(obj.$options);
               obj.options = $.map(obj.options, (val) => {
                   return formatString(val.replace(/[A-G][.|\\.\s+]/, '')).trim()
               });

               obj.type === 1 && obj.$options.map((index,item)=>{
                   $(item).attr('class') === 'checkbox_on' && $(item).click();
               });
               return obj
           }, (type, answer, $option) => {
               // $option = $option.find('div')
               if (type === 0 || type === 3) {
                   $option.click();
               } else if (type === 1) {
                   $option.attr('class') === 'checkbox_on' || $option.click();
               }
           }, () => {
               /**
                * 答题完成的监听
                */
               if ($('.paging_next').attr('style').includes('block')) {
                   //如果有下一页
                   $('.paging_next').click();
                   return true
               }

           }).fillAnswer();
       }, GLOBAL.delay);
   }

   function mooc_icve_com_cn() {
       showPanel();
       setTimeout(() => {
           new WorkerJS({
               root: '.e-q-r',
               elements: {
                   question: '.e-q-q .ErichText',
                   options: '.e-a-g li .ErichText',
                   $options: 'li',
                   type: '.quiz-type'
               }
           }, (obj) => {
               obj.type = TYPE[obj.type.replaceAll(/\s+/g,'')];
               return obj
           }, (type, answer, $option) => {
               if (type === 0 || type === 3) {
                   $option.click();
               } else if (type === 1) {
                   if (!$option.attr('class').includes('checked')) {
                       $option.click();
                   }
               }
           }, () => {
               /**
                * 答题完成的监听
                */
               // if ($('.paging_next').attr('style').includes('block')) {
               //     //如果有下一页
               //     $('.paging_next').click()
               //     return true
               // }

           }).fillAnswer();
       }, GLOBAL.delay);
   }

   function zjyold() {
       showPanel();
       setTimeout(() => {
           new WorkerJS({
               root: '.e-q-r',
               elements: {
                   question: '.e-q-q .ErichText',
                   options: '.e-a-g li,li .ErichText',
                   $options: '.e-a-g li',
                   type: '.quiz-type'
               }
           }, (obj) => {
               obj.type = TYPE[obj.type.replaceAll(/\s+/g,'')];
               obj.options = obj.options.map(i=>{
                   return i.replace(/^[ab]\)\s+/,'').replace(/^[a-z]\s+/,'').trim()
               });
               return obj
           }, (type, answer, $option) => {
               if (type === 0 || type === 3) {
                   $option.click();
               } else if (type === 1) {
                   if (!$option.attr('class').includes('checked')) {
                       $option.click();
                   }
               }
           }).fillAnswer();
       }, GLOBAL.delay);
   }

   function zhsExam() {
       console.log("我走到这;zhsExam");
       showPanel();
       setTimeout(() => {
           // sleep(3000)
           new WorkerJS({
               root: '.examPaper_subject',
               elements: {
                   question: '.subject_describe div',
                   options: '.subject_node .nodeLab .node_detail',//文字的选项列表
                   $options: '.subject_node .nodeLab',//绑定的事件的 dom列表
                   type: '.subject_type span:eq(0)'
               }
           }, (obj) => {

               obj.question = obj.question.get(0).__vue__._data.shadowDom.textContent;
               obj.type = TYPE[obj.type.match('【(.*)】')[1]];
               //多选题清楚样式,清楚已经保存的结果
               obj.type === 1 && $.each(obj.$options, (index, val) => {
                   $(val).find('.node_detail').hasClass('onChecked') && $(val).click();
               });
               if ($(".yidun_popup").hasClass('yidun_popup--light')){
                   console.log('我到这了',GLOBAL.loop);
                   iframeMsg('tip', {type: 'stop', tip: '答题暂停,请自行通过验证'});
                   clearInterval(GLOBAL.loop);
                   delete GLOBAL.loop;
                   return undefined
               }

               return obj
           }, (type, answer, $option) => {
               // fill answer
               if (type === 0 || type === 3 || type === 1) {
                   $option.click();
                   // $('.el-button:contains(下一题)').click()
               }


               // if (type === 0 || type === 1 || type === 3) {
               //     if ($option.find('.check_answer,.check_answer_dx').length === 0) {
               //         $option.click()
               //     }
               // } else if (type === 4 || type === 2) {
               //     UE.getEditor($option.find('textarea').attr('name')).setContent(answer)
               // }
           }, () => {
               setTimeout(() => {
                   $('.el-button:contains(保存)').click();
               }, GLOBAL.time / 3);
           }, () => {
               setTimeout(() => {
                   $('.el-button:contains(下一题)').click();
               }, GLOBAL.time / 3);
           }).fillAnswer();
       }, GLOBAL.delay*1.5);
   }

   function zhsIntegral() {
       showPanel();
       setTimeout(() => {
           // sleep(3000)
           let zhsIn = new WorkerJS({
               root: '.questionBox:eq(0)',
               elements: {
                   question: '.questionContent',
                   options: '.optionUl label .el-radio__label',//文字的选项列表
                   $options: '.optionUl label',//绑定的事件的 dom列表
                   type: '.questionTit'
               }
           }, (obj) => {
               obj.type = TYPE[obj.type.match('【(.*)】')[1]];
               //多选题清楚样式,清楚已经保存的结果
               obj.type === 1 && $.each(obj.$options, (index, val) => {
                   $(val).find('.el-radio__input').hasClass('is-checked') && $(val).click();
               });
               obj.options = obj.options.map(item=>{
                   return formatString(item.replaceAll(/^[a-zA-Z]\./g,''))
               });
               if ($(".yidun_popup").hasClass('yidun_popup--light')){
                   console.log('我到这了',GLOBAL.loop);
                   iframeMsg('tip', {type: 'stop', tip: '答题暂停,请自行通过验证'});
                   clearInterval(GLOBAL.loop);
                   delete GLOBAL.loop;
                   return undefined
               }

               return obj
           }, (type, answer, $option) => {
               // fill answer
               if (type === 0 || type === 3 || type === 1) {
                   $option.click();
                   // $('.el-button:contains(下一题)').click()
               }


               // if (type === 0 || type === 1 || type === 3) {
               //     if ($option.find('.check_answer,.check_answer_dx').length === 0) {
               //         $option.click()
               //     }
               // } else if (type === 4 || type === 2) {
               //     UE.getEditor($option.find('textarea').attr('name')).setContent(answer)
               // }
           }, () => {
               if ($('.Nextbtndiv .Topicswitchingbtn-gray:contains(下一题)').hasClass('Topicswitchingbtn-gray')) return false
               setTimeout(() => {
                   $('.Nextbtndiv .Topicswitchingbtn:contains(下一题)').click();
               }, GLOBAL.time / 5);
               return true
           });
           zhsIn.fillAnswer();
       }, GLOBAL.delay);
   }

   function ybkExam() {
       console.log("我走到这;ybkExam");
       showPanel();
       setTimeout(() => {
           // sleep(3000)
           new WorkerJS({
               root: '.topic-item',
               elements: {
                   question: '.t-con .t-subject',
                   options: '.t-option  .el-radio__label .option-content',//文字的选项列表
                   $options: '.t-option .el-radio__input .nodeLab',//绑定的事件的 dom列表
                   type: '.t-info .t-type'
               }
           }, (obj) => {
               obj.type = TYPE[obj.type];
               return obj
           }, (type, answer, $option) => {
               // fill answer
               if (type === 0 || type === 3 || type === 1) {
                   $option.click();
                   // $('.el-button:contains(下一题)').click()
               }


               // if (type === 0 || type === 1 || type === 3) {
               //     if ($option.find('.check_answer,.check_answer_dx').length === 0) {
               //         $option.click()
               //     }
               // } else if (type === 4 || type === 2) {
               //     UE.getEditor($option.find('textarea').attr('name')).setContent(answer)
               // }
           }).fillAnswer();
       }, GLOBAL.delay*1.5);
   }

   function uploadAnswer(data) {
       GM_xmlhttpRequest({
           method: "POST",
           url: 'https://app.itihey.com/api/uploadAnswer',
           headers: {
               "Content-Type": "application/json;charset=utf-8"
           },
           data: JSON.stringify(data),
           timeout: 10 * 1000,
           onload: function (r) {
               console.log(r.responseText);

           }
       });
   }

   function collectXiaoETong() {
       const split = location.pathname.split('/');
       axios.post('https://app5oicyne21998.h5.xiaoeknow.com/evaluation_wechat/exam/review_detail', `bizData%5Bcontent_app_id%5D=&bizData%5Bexam_id%5D=${split[4]}&bizData%5Bparticipate_id%5D=${split[5]}`).then(res => {
           const result = parseXiaoETong(res.data.data.result);
           uploadAnswer(result);
       });
   }


   function collectAnHuiJiXuJiaoYu() {
       const data = location.href.split('?')[1];
       axios.post('https://main.ahjxjy.cn/study/assignment/getAssignment', `${data}&&page=1`).then(res => {
           for (const re of res.data.list) {
               if (re.statusInt === 2) {
                   axios.post('https://main.ahjxjy.cn/study/assignment/loadOnlineAssignment', `${data}&cellId=${re.cellId}`).then(res => {
                       const arr = [];
                       const result = parseAnHuiJx(res.data.data);
                       for (let resultElement of result) {
                           arr.push(...resultElement);
                       }
                       uploadAnswer(arr);
                   });
               }
           }
       });
   }

   function hookJSON() {
       const parse = JSON.parse;
       JSON.parse = function (s) {
           const o = parse(s);
           if (location.pathname === '/study/works/works.html') {
               if (o.paper) {
                   GLOBAL.json = parseIcve(o.paper.PaperQuestions);
               }
           } else if (location.pathname === '/study/exam/exam.html') {
               if (o.array) {
                   let arr = [];
                   for (let arrayElement of o.array) {
                       arr.push(...arrayElement.Questions);
                   }
                   GLOBAL.json = parseIcve(arr);
               }
           } else if (location.pathname.includes('/v2/web/cloud/student/exercise/')) {
               if (o.data && o.data.problems) {
                   GLOBAL.json = parseYkt(o.data.problems);
               }
           } else if (location.host === 'examination.xuetangx.com' && location.pathname.includes('/exam/')) {
               if (o.data && o.data.problems) {
                   GLOBAL.json = parseYktExam(o.data.problems);
               }
           } else if (location.pathname.includes('/study/html/content/studying/')) {
               if (o.data && o.status === 2 && o.state !== "doing") {
                   GLOBAL.finish = true;
                   const result  = parseAnHuiJx(o.data);
                   for (let resultElement of result) {
                       uploadAnswer(resultElement);
                   }
               }
           }
           return o
       };
   }


   function parseAnHuiJx(problems) {
       return problems.map(item => {
           let type = TYPE[item.name];
           return item.list.map(q => {
               //选项内容
               const options = type === 1 || type === 0 ? q.options.map(o => {
                   return formatString(((o.content)))
               }) : [];
               //答案
               let answer = [];
               if (type === 1 || type === 0){
                   answer = q.answers.split(',').map(a=>{
                       return options[parseInt(a)]
                   });
               }else if (type === 3){
                   answer = [q.answers.replace('false','错误').replace('true','正确')];
               }
               return {
                   answer,
                   type,
                   question: formatString(((q.content))),
                   options
               }
           })
       })
   }


   function parseYkt(problems) {
       return problems.map(item => {
           const type = TYPE[item.content.TypeText];
           if (type === 2 || type === 4) {
               return {
                   question: filterImg($(item.content.Body)),
                   type
               }
           }
           return {
               question: formatString(item.content.Body),
               options: item.content.Options.map(i => {
                   return formatString(type === 3 ? i.key : i.value)
               }),
               type
           }
       })
   }

   function parseYktExam(problems) {
       return problems.map(item => {
           const type = TYPE[item.TypeText];
           if (type === 2 || type === 4) {
               return {
                   question: formatString(item.Body),
                   type
               }
           }
           return {
               question: formatString(item.Body),
               options: item.Options.map(i => {
                   return formatString(type === 3 ? i.key : i.value)
               }),
               type
           }
       })
   }

   function parseIcve(questions) {
       return questions.map(item => {
           const options = item.Selects.map(opt => {
               return formatString(opt)
           });
           const type = TYPE[item.ACHType.QuestionTypeName];
           const answer = item.Answers.map(key => {
               if (type === 0 || type === 1) {
                   return options[key.charCodeAt() - 65]
               } else if (type === 3) {
                   return key === '1' ? '正确' : '错误'
               }

           });
           const answerKey = (type === 0 || type === 1) ? item.Answers : answer;
           return {
               id: item.Id,
               question: item.ContentText,
               answerKey,
               options,
               answer,
               type
           }
       })
   }

   function parseXiaoETong(obj) {
       return obj.map(item => {
           //获取选项列表
           let answer = [];
           if (item.type === 0 || item.type === 1) {
               answer = item.answer.map(a => {
                   for (let optionElement of item.option) {
                       if (optionElement.id === a) return formatString(optionElement.content)
                   }
               });
           } else if (item.type === 3) {
               answer = item.answer.map(a => {
                   return a.replace('1', "正确").replace('0', '错误')
               });
           }else if (item.type === 4) {
               answer = item.answer;
           }

           return {
               question: formatString(item.content),
               answer,
               options: item.option ? item.option.map(opt => {
                   return formatString(opt.content)
               }) : [],
               type: item.type
           }
       })
   }

   /**
    * http://www.icve.com.cn/study/works/works.html
    */
   function icve_works() {
       hookJSON();

       function get_element(id) {
           for (let jsonElement of GLOBAL.json) {
               if (jsonElement.id === id) {
                   return jsonElement
               }
           }
       }

       showPanel();
       setTimeout(() => {
           console.log(GLOBAL.json);
           new WorkerJS({
               root: '.questions',
               elements: {
                   question: '.tigan',
                   options: 'label ',//文字的选项列表
                   $options: '.dy_input',//绑定的事件的 dom列表
                   type: 'input[name^=paperItemId]'
               }
           }, (obj) => {
               const ele = get_element(obj.type);
               obj.question = ele.question;
               obj.answer = ele.answerKey ? ele.answerKey : ele.answer;
               obj.type = ele.type;
               return obj
           }, (type, answer, $option) => {
               if (type === 0 || type === 3 || type === 1) {
                   $option.get(0).click();
               } else if (type === 4 || type === 2) {
                   UE.getEditor($option.attr('name')).setContent(answer);
               }
           }).fillAnswer();
       }, GLOBAL.delay);
   }

   function yktOldExam() {
       showPanel();
       setTimeout(() => {
           new WorkerJS({
               root: '.problem_item',
               elements: {
                   question: '.notBullet:eq(0)',
                   options: '.notBullet:gt(0)',//文字的选项列表
                   $options: '.problembullet',//绑定的事件的 dom列表
               }
           }, async (obj) => {
               const $item = obj.type;

               var tmp = $item.find('.ptype').clone();
               tmp.children().remove();
               obj.type = TYPE[tmp.text().replaceAll(/\s+/g, '')];
               obj.question = await yuketangOcr(obj.question.attr('data-background'));

               if (obj.$options.length === 2) {
                   obj.options = ['正确', '错误'];
               } else {
                   const opt = [];
                   for (const tmpElement of $item.find('.notBullet:gt(0)')) {
                       opt.push(await yuketangOcr(jQuery(tmpElement).attr('data-background')));
                   }
                   obj.options = opt;
               }

               return obj

           }, (type, answer, $option) => {
               console.log($option);
               // fill answer
               if (type === 0 || type === 3 || type === 1) {
                   if (!$option.hasClass('is-checked')) {
                       $option.click();
                   }
                   // $('.el-button:contains(下一题)').click()
               }


               // if (type === 0 || type === 1 || type === 3) {
               //     if ($option.find('.check_answer,.check_answer_dx').length === 0) {
               //         $option.click()
               //     }
               // } else if (type === 4 || type === 2) {
               //     UE.getEditor($option.find('textarea').attr('name')).setContent(answer)
               // }
           }).fillAnswer();
       }, GLOBAL.delay * 1.5);
   }


   function yktExam() {

       hookJSON();
       showPanel();
       setTimeout(() => {
           console.log(GLOBAL.json);
           // sleep(3000)
           // $('.')
           new WorkerJS({
               root: '.exam-main--body .subject-item',
               elements: {
                   question: '.item-body .problem-body ,p',
                   options: '.item-body ul li',//文字的选项列表
                   $options: '.item-body ul label, .blank-item-dynamic',//绑定的事件的 dom列表
                   type: '.item-type'
               }
           }, async (obj) => {
               console.log(obj);
               const ele = GLOBAL.json[GLOBAL.index-1];
               // obj.$options = document.querySelector('.subject-item')
               obj.type = ele.type;
               obj.options = ele.options;
               obj.question = ele.question;
               if (obj.type === 1){
                   for (let val of obj.$options) {
                       jQuery(val).hasClass('is-checked') && jQuery(val).click();
                       await sleep(500);
                   }
               }
               return obj

           }, (type, answer, $option) => {
               console.log($option);
               // fill answer
               if (type === 0 || type === 3 || type === 1) {
                   if (!$option.hasClass('is-checked')) {
                       $option.click();
                   }
                   // $('.el-button:contains(下一题)').click()
               } else if (type === 4 || type === 2) {
                   UE.getEditor($option).setContent(answer);
               }


               // if (type === 0 || type === 1 || type === 3) {
               //     if ($option.find('.check_answer,.check_answer_dx').length === 0) {
               //         $option.click()
               //     }
               // } else if (type === 4 || type === 2) {
               //     UE.getEditor($option.find('textarea').attr('name')).setContent(answer)
               // }
           }).fillAnswer();
       }, GLOBAL.delay * 1.5);
   }


   function yktText() {

       hookJSON();
       showPanel();
       setTimeout(() => {
           console.log(GLOBAL.json);
           // sleep(3000)
           // $('.')
           new WorkerJS({
               root: '.container-problem .subject-item',
               elements: {
                   // question: '.item-body .problem-body ,p',
                   // options: '.item-body ul li',//文字的选项列表
                   $options: '.item-body ul label',//绑定的事件的 dom列表
                   type: '.item-type'
               }
           }, async (obj) => {
               console.log(obj);
               //测验题号
               const index = obj.type.trim().match(/^(\d+)/)[1];
               obj.index = index - 1;
               const ele = GLOBAL.json[obj.index];
               obj.type = ele.type;
               obj.options = ele.options;
               obj.question = ele.question;
               if (obj.type === 1) {
                   for (let val of obj.$options) {
                       jQuery(val).hasClass('is-checked') && jQuery(val).click();
                       await sleep(500);
                   }
               }
               console.log(obj);
               return obj

           }, (type, answer, $option) => {
               console.log($option);
               // fill answer
               if (type === 0 || type === 3 || type === 1) {
                   if (!$option.hasClass('is-checked')) {
                       $option.click();
                   }
                   // $('.el-button:contains(下一题)').click()
               }


               // if (type === 0 || type === 1 || type === 3) {
               //     if ($option.find('.check_answer,.check_answer_dx').length === 0) {
               //         $option.click()
               //     }
               // } else if (type === 4 || type === 2) {
               //     UE.getEditor($option.find('textarea').attr('name')).setContent(answer)
               // }
           }, (need_jump) => {
               if ($('.el-button--text:contains(下一题)').hasClass('is-disabled')) return false
               // if (ne)
               need_jump && setTimeout(() => {
                   $('.el-button--text:contains(下一题)').click();
               }, GLOBAL.time / 3);
               return need_jump
           }).fillAnswer();
       }, GLOBAL.delay * 1.5);
   }

   function zgdzText() {
       console.log("我走到这;zgdzText");
       showPanel();
       setTimeout(() => {
           // sleep(3000)
           new WorkerJS({
               root: '.stViewItem',
               elements: {
                   question: '.stViewHead  div',
                   options: '.stViewCont  .stViewOption a',//文字的选项列表
                   $options: '.stViewCont  .stViewOption a,input',//绑定的事件的 dom列表
               }
           }, (obj) => {
               obj.type = TYPE[obj.type.parents().find('.E_E_L_I_C_R_C_T_SubType').eq(0).text().replace(/\(共\d+分\)/,'')];
               obj.options = obj.options.map(i=>{
                   return i.replace(/\([A-Za-z]\)/,'').trim()
               });
               return obj
           }, (type, answer, $option) => {
               // fill answer
               if (type === 0 || type === 3 || type === 1) {
                   $option.click();
                   // $('.el-button:contains(下一题)').click()
               }else if (type === 4 || type === 2) {
                   $option.val(answer);
               }


               // if (type === 0 || type === 1 || type === 3) {
               //     if ($option.find('.check_answer,.check_answer_dx').length === 0) {
               //         $option.click()
               //     }
               // } else if (type === 4 || type === 2) {
               //     UE.getEditor($option.find('textarea').attr('name')).setContent(answer)
               // }
           }).fillAnswer();
       }, GLOBAL.delay*1.5);
   }

   function xetText() {
       showPanel();
       setTimeout(() => {
           new WorkerJS({
               root: '.question-title,.title__text',
               elements: {
                   question: '#detail_div',
                   options: 'label  .image-text-box p',//文字的选项列表
                   $options: 'label,.simulation_inp',//绑定的事件的 dom列表
               }
           }, (obj) => {
               const $item = obj.type;

               obj.$options = $item.parent().next().find('.option-item,.checking-option__container,.fill_blank');
               obj.type = TYPE[$item.next().text().replace(/\s+/, '').replace("(", "").replace(")", "")];
               if (obj.type === 2){
                   obj.$options = $item.parent().parent();
                   // console.log(obj.$options)
               }
               if (obj.type === 3) {
                   obj.options = ['正确', '错误'];
               } else {
                   obj.options = jQuery.map($item.parent().next().find('.option-item #detail_div'), function (val) {
                       return formatString(filterImg(val))
                   });
               }
               console.log(obj);
               return obj
           }, (type, answer, $option) => {
               if (type === 0) {
                   $option.html().includes('single-exam-radio-active') || $option.click();
               } else if (type === 1) {
                   $option.html().includes('check-i-active') || $option.click();
               } else if (type === 3) {
                   $option.click();
               } else if (type === 2) {
                   const vue = $option.get(0).__vue__;
                   vue.content[0] = answer;
                   vue.emitAnswer();
                   $option.find('.simulation_inp').text(answer);
               }
           }).fillAnswer();
       }, GLOBAL.delay * 2);
   }

   function anHuiText() {
       hookJSON();
       showPanel();
       setTimeout(() => {
           if (GLOBAL.finish){
               iframeMsg('tip', {type: 'hidden', tip: '本页面已做完,无需自动答题'});

               return
           }
           new WorkerJS({
               root: '.e-q',
               elements: {
                   question: '.e-q-q .ErichText',
                   options: '.e-a-g li',
                   $options: '.e-a-g li'
               }
           }, (obj) => {
               const $item = obj.type;
               obj.type = TYPE[$item.parent().prev().find('.e-text').text()];
               obj.options = obj.options.map(i => {
                   return formatString(i.replaceAll(/^[ab]\)\s+/g, '').replaceAll(/^[a-z]\s+/g, '').replaceAll(/^[a-z]、\s+/g, '').trim())
               });
               return obj
           }, (type, answer, $option) => {
               if (type === 0 || type === 3) {
                   $option.click();
               } else if (type === 1) {
                   if (!$option.attr('class').includes('checked')) {
                       $option.click();
                   }
               }
           }).fillAnswer();
       }, GLOBAL.delay);
   }

   var _self = unsafeWindow;
   exports.top = _self;
   // _self.$ = jQuery

   try {
       while (exports.top !== _self.top) {
           exports.top = exports.top.parent.document ? exports.top.parent : _self.top;
           if (exports.top.location.pathname === '/mycourse/studentstudy') break;
       }
   } catch (err) {
       exports.top = _self;
   }
   // console.log('顶部窗口链接',top.location.href)
   var parent = _self === exports.top ? self : _self.parent,
       Ext = _self.Ext || parent.Ext || {},
       UE = _self.UE;


   /**
    * 顶层窗口监听 iframeNode 的参数
    */
   exports.top.addEventListener("message", (event => {
       console.log('监听器的', GLOBAL);
       if (event.data.type === 'jump') ; else if (event.data.type === 'stop') {
           if (event.data.val) {
               let intv = setInterval(() => {
                   if (GLOBAL.loop) {
                       clearInterval(GLOBAL.loop);
                       delete GLOBAL.loop;
                       clearInterval(intv);
                   }

               }, 20);

           } else {
               GLOBAL.loop = setInterval(GLOBAL.setInterval, GLOBAL.time);
           }
       } else if (event.data.type === 'start_pay') {
           GM_setValue('start_pay', event.data.flag);
           iframeMsg('tip', {tip: '已' + (event.data.flag ? '开启' : '关闭') + '请求收费题库,已实时生效'});
       } else if (event.data.type === 'auto_jump') {
           GM_setValue('auto_jump', event.data.flag);
           iframeMsg('tip', {tip: '已' + (event.data.flag ? '开启' : '关闭') + '自动切换,页面刷新后生效'});
       } else if (event.data.type === 'confim') {
           GM_setValue('token', event.data.token);
       } else if (event.data.type === 'jump') {
           GLOBAL.index++;
           iframeMsg('tip', {tip: '准备答第' + (GLOBAL.index + 1) + '题'});
       }
       // GM_getValue
   }), false);

   /**
    * 类似于老板键,上箭头隐藏,下箭头显示
    */
   $(document).keydown(function (event) {
       if (event.keyCode === 38) {
           $('#model-id').hide();
       } else if (event.keyCode === 40) {
           $('#model-id').show();
       }
   });
   // yuketangOcr('https://qn-s0.yuketang.cn/Fmx0luZ4H0Kntw9_9Uctwj4I-iRi').then(res=>console.log(res))

   setTimeout(() => {
       start();
   }, GLOBAL.time);
   if (location.pathname === '/exam/examflow_index.action') {
       ZjyExam();
   } else if (location.pathname === '/study/homework/do.html') {
       zjyold();
   }else if ((location.pathname === '/exam/test/reVersionTestStartNew' || location.pathname === '/exam-ans/exam/test/reVersionTestStartNew') && location.href.includes('newMooc=true')) {
       chaoxingNewExam(1);
   } else if ((location.pathname === '/exam/test/reVersionTestStartNew' || location.pathname === '/exam-ans/exam/test/reVersionTestStartNew') && !location.href.includes('newMooc=true')) {
       chaoxingOldExam();
   } else if (location.pathname === '/work/doHomeWorkNew') {
       chaoxingQuiz();
   } else if (location.pathname === '/mooc2/exam/preview' || location.pathname === '/exam-ans/mooc2/exam/preview') {
       chaoxingNewExam(0);
   } else if (location.pathname === '/mooc2/work/dowork') {
       chaoxingNewWork();
   } else if (location.pathname === '/study/workExam/testWork/preview.html' || location.pathname === '/study/workExam/homeWork/preview.html' || location.pathname === '/study/workExam/onlineExam/preview.html') {
       mooc_icve_com_cn();
   } else if (location.pathname === '/stuExamWeb.html' && location.href.includes('/webExamList/dohomework/')) {
       zhsExam();
   } else if (location.pathname === '/stuExamWeb.html' && location.href.includes('/webExamList/doexamination/')) {
       zhsExam();
   } else if (location.href.includes('/atHomeworkExam/stu/homeworkQ/exerciseList') || location.href.includes('atHomeworkExam/stu/examQ/examexercise')) {
       zhsIntegral();
   } else if (location.pathname === '/web/index.php') {
       ybkExam();
   } else if (location.pathname === '/study/works/works.html' || location.pathname === '/study/exam/exam.html') {
       icve_works();
   } else if (location.pathname.includes('/v2/web/cloud/student/exercise/')) {
       yktText();
   } else if (location.host === 'examination.xuetangx.com' && location.pathname.includes('/exam/')) {
       yktExam();
   } else if (location.pathname.includes('/v/quiz/quiz_result')) {
       const intv = setInterval(() => {
           if ($('#cover').attr('style').includes('display: none;')) {
               clearInterval(intv);
               yktOldExam();
           }
       }, 2000);

   } else if (location.pathname.includes('/v2/web/studentLog')) ; else if (location.pathname.includes('/Exam/OnlineExamV2/')) {
       zgdzText();
   } else if (location.pathname.includes('/evaluation_wechat/examination/detail/')) {
       xetText();
   }else if (location.pathname.includes('/evaluation_wechat/examination/review')){
       collectXiaoETong();
   }else if (location.pathname.includes('/study/html/content/studying/')){
       anHuiText();
   }else if (location.pathname === ('/study/html/content/assignment/')){
       collectAnHuiJiXuJiaoYu();
   }

   exports.Ext = Ext;
   exports.UE = UE;
   exports._self = _self;
   exports.parent = parent;

   Object.defineProperty(exports, '__esModule', { value: true });

   return exports;

})({});