Greasy Fork

Greasy Fork is available in English.

超星网课助手(考试专版)

自动搜索尔雅MOOC考试答案,支持自动答题、自动切换题目、隐藏答案搜索提示框,支持自定义每个功能的开启或关闭

目前为 2019-01-01 提交的版本,查看 最新版本

// ==UserScript==
// @name         超星网课助手(考试专版)
// @namespace    [email protected]
// @version      1.1.0
// @description  自动搜索尔雅MOOC考试答案,支持自动答题、自动切换题目、隐藏答案搜索提示框,支持自定义每个功能的开启或关闭
// @author       wyn665817
// @match        *://*.chaoxing.com/exam/test/reVersionTestStartNew*
// @connect      forestpolice.org
// @run-at       document-end
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @supportURL   http://greasyfork.icu/zh-CN/scripts/373131/feedback
// @license      MIT
// ==/UserScript==

// 设置修改后,需要刷新或重新打开网课页面才会生效
var setting = {
    // 3E3 == 3000,表示毫秒数
    time: 3E3 // 默认响应速度为3秒,不建议小于2秒
    ,token: '' // 捐助用户可以使用上传选项功能,更精准的匹配答案,此处填写捐助后获取的识别码

    // 1代表开启,0代表关闭
    ,auto: 1 // 自动答题功能,默认开启
    ,retry: 1 // 服务器异常时进行自动重试,默认开启
    ,hide: 0 // 隐藏答案搜索提示框,默认关闭
    ,copy: 1 // 文本编辑器允许粘贴,用于解除简答题题目的粘贴限制,默认开启
    ,scale: 0 // 富文本编辑器高度自动拉伸,用于简答题题目,答题框根据内容自动调整大小,默认关闭

    // 仅开启auto时,修改此处才会生效
    ,jump: 1 // 答题完成后自动切换,默认开启
    ,none: 0 // 未找到答案或无匹配答案时选择默认选项,默认选项即第一个选项,默认关闭

    // 仅开启jump时,修改此处才会生效
    ,other: 0 // 跳过不支持自动答题的题目,默认关闭
},
_self = unsafeWindow,
$ = _self.$,
UE = _self.UE;

setting.text = ['自动答题已完成,', '已选择默认选项,', '该题型不支持自动答题,'];
setting.$ans = $('#submitTest ul:eq(0) .clearfix');
setting.TiMu = [
    $('.TiMu .Cy_TItle .clearfix').text().trim(),
    $('.current').parent().prev().text(),
    $('.cur a').text().trim(),
    setting.token && setting.$ans.map(function() {
        return $(this).text().trim();
    }).get().join('#')
];
setting['单选题'] = function(event) {
    setting.$ans.each(function() {
        var tip = $(this).text().trim() != event;
        setting.check = setting.check || !tip;
        return tip || !$(this).click();
    });
    checkDef();
};
setting['多选题'] = function(event) {
    var index = 0,
    arr = event.split('#'),
    timeId = setInterval(function() {
        if (index < setting.$ans.length) {
            var tip = $.inArray(setting.$ans.eq(index).text().trim(), arr) >= 0;
            setting.check = setting.check || tip;
            $('#submitTest :checkbox').eq(index).prop('checked') == tip || setting.$ans.eq(index).click();
            index++;
        } else {
            clearInterval(timeId);
            checkDef();
        }
    }, setting.time);
};
setting['判断题'] = function(event) {
    var $ul = $('#submitTest ul');
    if (event == '正确' || event == '是') {
        $ul.find('.ri + input').click();
    } else if (event == '错误' || event == '否') {
        $ul.find('.wr + input').click();
    } else {
        setting.check = false;
    }
    checkDef();
};
setting.div = $(
    '<div style="border: 2px dashed rgb(0, 85, 68); width: 350px; position: fixed; top: 0; right: 0; z-index: 99999; background-color: rgba(70, 196, 38, 0.6); overflow: auto;' + (setting.hide ? ' display: none;' : '') + '">' +
        '<span style="font-size: medium;"></span>' +
        '<div style="font-size: medium;">正在搜索答案...</div>' +
        '<button style="margin-right: 10px;">暂停答题</button>' +
        '<button style="margin-right: 10px;' + (setting.auto && setting.jump ? '' : ' display: none;') + '">点击停止本次切换</button>' +
        '<button>重新查询</button>' +
        '<table border="1" style="font-size: 12px;">' +
            '<tr>' +
                '<th width="60%">题目</th>' +
                '<th width="40%">答案</th>' +
            '</tr>' +
        '</table>' +
    '</div>'
).appendTo('body');
setting.$div = setting.div.children('div');
setting.$btn = setting.div.children('button');

setting.$btn.on('click', function() {
    var len = $(this).prevAll('button').length;
    if (len == 0) {
        if (setting.out) {
            clearTimeout(setting.out);
            delete setting.out;
            setting.$div.text('已暂停搜索');
            $(this).text('继续答题');
        } else {
            setting.out = setTimeout(findTiMu, setting.time);
            setting.$div.text('正在搜索答案...');
            $(this).text('暂停答题');
        }
    } else if (len == 1) {
        clearTimeout(setting.timeid);
        setting.jump = 0;
        setting.$div.text((setting.text[setting.tip] || '正在搜索答案,') + '已关闭本次自动切换');
        $(this).hide();
    } else if (len == 2) {
        $('.current')[0].click();
    }
});

$(document).keydown(function(event) {
    if (event.keyCode == 38) {
        setting.div.hide();
    } else if (event.keyCode == 40) {
        setting.div.show();
    }
});

setting.copy && $('input[onpaste]').removeProp('onpaste');
UE && $('textarea').each(function() {
    var editor = $(this).attr('name');
    setting.copy && UE.getEditor(editor).removeListener('beforepaste', _self.myEditor_paste);
    setting.scale && UE.getEditor(editor).ready(function() {
        var $hide = $('textarea').parent(':hidden').show();
        this.destroy();
        $hide.hide();
        UE.getEditor(editor, {
            scaleEnabled: false
        });
    });
});
if (!setting.other || setting[setting.TiMu[1]]) {
    setting.out = setTimeout(findTiMu, setting.time);
} else {
    setting.$btn.eq(0).text('继续答题');
    jumpTimu(setting.tip = 2);
}

function findTiMu() {
    GM_xmlhttpRequest({
        method: 'POST',
        url: 'http://mooc.forestpolice.org/cx/' + (setting.token || 0) + '/' + encodeURIComponent(setting.TiMu[0]),
        headers: {
            'Content-type': 'application/x-www-form-urlencoded'
        },
        data: 'exam=' + encodeURIComponent(setting.TiMu[2]) + '&type=' + encodeURIComponent(setting.TiMu[1]) + '&option=' + encodeURIComponent(setting.TiMu[3]),
        timeout: setting.time * 2,
        onload: function(xhr) {
            if (!setting.out) {
            } else if (xhr.status == 200) {
                var obj = JSON.parse(xhr.responseText);
                if (obj.code) {
                    setting.$btn.eq(0).hide();
                    setting.div.children('table').append(
                        '<tr>' +
                            '<td>' + setting.TiMu[0] + '</td>' +
                            '<td>' + obj.data + '</td>' +
                        '</tr>'
                    );
                    if (!setting[setting.TiMu[1]]) {
                        setting.$div.text('该题型不支持自动答题,请手动完成');
                        setting.$btn.eq(1).hide();
                    } else if (setting.auto) {
                        if (obj.code == 1) {
                            setting.$div.text('答案搜索已完成,正在自动答题...');
                            setting[setting.TiMu[1]](obj.data);
                        } else if (setting.none) {
                            checkDef();
                        } else {
                            setting.$div.text('未找到答案,未开启选择默认选项');
                            setting.$btn.eq(1).hide();
                        }
                    } else {
                        setting.$div.text('答案搜索已完成,未开启自动答题');
                    }
                } else {
                    errorGo(obj.data);
                }
                setting.div.children('span').html(obj.msg);
            } else {
                errorGo('服务器异常');
            }
        },
        ontimeout: function() {
            setting.out && errorGo('服务器超时');
        }
    });
}

function errorGo(err) {
    if (setting.retry) {
        setting.$div.text(err + ',正在重新搜索答案');
        setting.out = setTimeout(findTiMu, setting.time * 2);
    } else {
        setting.$div.text(err + ',未开启自动重试');
    }
}

function checkDef() {
    if (setting.check === false) {
        if (setting.none) {
            $(':radio, :checkbox', '#submitTest')[0].click();
            setting.tip = 1;
        } else {
            setting.$div.text('未找到匹配的答案,未开启选择默认选项');
            setting.$btn.eq(1).hide();
            return;
        }
    } else {
        setting.tip = 0;
    }
    jumpTimu();
}

function jumpTimu() {
    var $next = $('.leftBottom a:contains("下一题")');
    if ($next.hasClass('saveYl01')) {
        setting.$div.text('考试已完成');
    } else {
        var text = '未开启自动切换';
        if (setting.jump) {
            text = '即将切换下一题';
            setting.timeid = setTimeout(function() {
                $next[0].click();
            }, setting.time);
        }
        setting.$div.text(setting.text[setting.tip] + text);
    }
}