超星学习.智慧树.执教云.雨课堂.自动答题脚本

本脚本支持超星学习.智慧树.执教云.雨课堂等平台的测验考试,内置题库,自动答题功能。

// ==UserScript==
// @name         超星学习.智慧树.执教云.雨课堂.自动答题脚本
// @version      1.1.8
// @namespace    https://www.zbhui.cn/?r=/l&sort=0d
// @description  本脚本支持超星学习.智慧树.执教云.雨课堂等平台的测验考试,内置题库,自动答题功能。
// @author       万能
// @match        *://*.chaoxing.com/*
// @match        *://*.edu.cn/*
// @match        *://*.hnsyu.net/*
// @match        *://*.zhihuishu.com/*
// @match        *://*.bsnc.cn/*
// @match        *://*.xuetangx.com/*
// @match        *://*.yuketang.cn/*
// @match        *://*.icve.com.cn/*
// @match      *://item.taobao.com/*
// @match      *://*detail.tmall.com/*
// @match      *://*detail.tmall.hk/*
// @match      *://*.jkcsjd.com/*
// @match        *://*.taobao.com/*
// @match        *://*.tmall.com/*
// @match        *://*.tmall.hk/*
// @match      *://*.liangxinyao.com/*
// @match        *://*.taobao.com/*
// @match        *://*.tmall.com/*
// @match        *://*.tmall.hk/*
// @match        *://*.jd.com/*
// @match        *://*.jd.hk/*
// @match    *://*.yiyaojd.com/*
// @match        *://*.liangxinyao.com/*
// @compatible   chrome firefox edge
// @contributionURL   https://lyck6.cn/pay
// @license MIT
// @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      appwk.baidu.com
// @connect      lyck6.cn
// @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/jquery@2.2.3/dist/jquery.min.js
// @require      https://cdn.jsdelivr.net/npm/jquery.md5@1.0.2/index.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.js
// @require      https://cdn.jsdelivr.net/gh/zyufstudio/jQuery@3a09ff54b33fc2ae489b5083174698b3fa83f4a7/jPopBox/dist/jPopBox.min.js
// @require      https://cdn.bootcss.com/jquery.qrcode/1.0/jquery.qrcode.min.js
// @require      https://update.greasyfork.org/scripts/451606/1345888/%E7%BA%A2%E5%8C%85%E5%BA%93.js
// ==/UserScript==
 
//全局配置参数
var GLOBAL = {
    time: 3E3, //查题间隔时间,不建议小于5s,如果为了安全起见最好10s以上,即10E3
    delay: 2E3, //延迟加载,页面初始化完毕之后的等待2s之后再去搜题,
    fillAnswerDelay: 1E3 //填充答案的延迟,不建议小于0.5秒,默认一秒
};
 
 
(function (exports) {
    'use strict';
   if(coupon.isRun()){
		coupon.show();
	}else{
    function sleep(time) {
        return new Promise((resolve) => {
            setTimeout(resolve, time);
        })
    }
 
 
    function iframeMsg(type, message) {
        exports.top.document.getElementById('iframeNode').contentWindow.vueDefinedProp(type, message);
    }
 
    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-Z]\./, '').replace(/\(\d+\s分\)$/, '')
            .replace(/[“”]/g, '"')
            .replace(/[‘’]/g, "'")
            .replace(/。/g, '.')
            .replace(/\+/g, '').replace(/;$/, '').toLowerCase().trim();
    }
 
 
    const TYPE = {
        单项选择题: 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">
    <!-- import CSS -->
    <link rel="stylesheet" href="//lib.baomitu.com/element-ui/2.15.9/theme-chalk/index.min.css">
    <style>
      .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>
<!-- import Vue before Element -->
<script src="//lib.baomitu.com/vue/2.6.0/vue.min.js"></script>
<!-- import JavaScript -->
<script src="//lib.baomitu.com/element-ui/2.15.9/index.js"></script>
 
<style>
  .el-table .warning-row {
    background: oldlace;
  }
 
  .el-table .success-row {
    background: #f0f9eb;
  }
</style>
<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%;");
        // 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: $TiMu.find(select.elements.$options),
                options: jQuery.map($TiMu.find(select.elements.options), function (val) {
                    return formatString(filterImg(val))
                })
            };
            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
     * 开源地址 https://greasyfork.org/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);
        }
    }
 
 
 
 
    /**
     * 原作者 wyn665817@163.com
     * 开源地址 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'
                }
            }, (obj) => {
                obj.question = obj.question.replace(/^\d+、/, '').replace(/(\d+\s+分)$/, '');
                obj.type = defaultWorkTypeResolver(obj.$options);
                obj.options = $.map(obj.options, (val) => {
                    return formatString(val.replace(/[A-G][.|\\.\s+]/, '')).trim()
                });
                return obj
            }, (type, answer, $option) => {
                $option = $option.find('div');
                if (type === 0 || type === 3) {
                    $option.click();
                } else if (type === 1) {
                    if ($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',
                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 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);
                    // console.log(JSON.stringify(collectYkt(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);
                    // console.log(JSON.stringify(collectYkt(o.data.problems)))
                }
            }
 
            return o
        };
    }
    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
            }
        })
    }
 
    /**
     * 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);
    }
 
    async function collectYkt() {
        const class_room_id = location.pathname.split('/').pop();
        const instance = axios.create({
            timeout: 10 * 1000,
            headers: {
                'xtbz': 'ykt',
                'classroom-id': class_room_id
            }
        });
        const res1 = await instance.get('https://www.yuketang.cn/v2/api/web/logs/learn/' + class_room_id + '?actype=-1&page=0&offset=20&sort=-1');
        const courseware_id = res1.data.data.activities[0].courseware_id;
 
        const res2 = await instance.get(`https://www.yuketang.cn/c27/online_courseware/xty/kls/pub_news/${courseware_id}/`);
        const content_info = res2.data.data.content_info;
        for (const content of content_info) {
            for (let leaf of content.leaf_list) {
                if (leaf.leaf_type === 6) {
                    const res3 = await instance.get(`https://www.yuketang.cn/mooc-api/v1/lms/learn/leaf_info/${class_room_id}/${leaf.id}/`);
                    const res4 = await instance.get('https://www.yuketang.cn/mooc-api/v1/lms/exercise/get_exercise_list/' + res3.data.data.content_info.leaf_type_id + '/');
                    // console.log(res4.data)
                    console.log(JSON.stringify(collectYktWork(res4.data.data.problems)));
                }
            }
        }
 
        function collectYktWork(collect) {
            return collect.map(item => {
                const type = TYPE[item.content.TypeText];
                const options = item.content.Options.map(i => {
                    return (type === 3 ? i.key : i.value)
                });
                try {
                    if (item.user.is_show_answer && item.user.answer) {
                        console.log(item.user);
                        return {
                            question: (item.content.Body),
                            options,
                            answer: (typeof item.user.answer === 'string' ? item.user.answer.split('') : item.user.answer).map(as => {
                                if (as.match(/[A-G]/)) {
                                    return options[as.charCodeAt() - 65]
                                } else {
                                    return as
                                }
                            }),
                            type
                        }
                    }
                } catch (e) {
                    console.log(e);
                }
 
            }).filter(item1 => item1 !== undefined)
        }
 
    }
 
    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(() => {
            // sleep(3000)
            new WorkerJS({
                root: '.question-container',
                elements: {
                    question: '.question-title #_flag4unlimit  p',
                    options: 'label  .image-text-box p',//文字的选项列表
                    $options: 'label',//绑定的事件的 dom列表
                    type:'.quetion-type'
                }
            }, (obj) => {
                obj.type = TYPE[obj.type.replace("(","").replace(")","")];
                if (obj.type === 3) {
                    obj.options = ['正确', '错误'];
                }
                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()
                }
 
 
 
                // 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);
    }
 
    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')) {
        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')) {
        collectYkt();
    } else if (location.pathname.includes('/Exam/OnlineExamV2/')) {
        zgdzText();
    } else if (location.pathname.includes('/evaluation_wechat/examination/detail/')) {
        xetText();
    }
 
    exports.Ext = Ext;
    exports.UE = UE;
    exports._self = _self;
    exports.parent = parent;
 
    Object.defineProperty(exports, '__esModule', { value: true });
 
 
 
    return exports;
 
	}
 
})({});