优学院刷课

优学院自动8倍速观看视频,自动答题

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         优学院刷课
// @namespace    http://tampermonkey.net/
// @version      2.1.0
// @description  优学院自动8倍速观看视频,自动答题
// @author       xiaobu
// @match        ua.ulearning.cn/learnCourse/learnCourse.html?*
// @match        ua.ulearning.cn//learnCourse/learnCourse.html?*
// ==/UserScript==


(function () {

    // 优学院
    const youxueyuan = {
        $startBtn: null,  // 开始按钮
        $stopBtn: null,   // 暂停按钮
        timer: null,      // 定时器

        // 初始化
        init() {
            this.$startBtn = $('<button class="btn-hollow" style="z-index:99999;position:relative">开始刷课</button>');
            this.$stopBtn = $('<button  class="btn-hollow" style="z-index:99999;position:relative">暂停刷课</button>');

            let $erviceMask = $('<div class="custom-service custom-service-mask"></div>');
            $('.custom-service').parent().append($erviceMask);
            $('.custom-service').eq(0).remove();
            $erviceMask.append(this.$startBtn).append(this.$stopBtn);
            this.$stopBtn.hide();
            this.bindEvent();
            // 初始化日志管理器
            log.init();
        },

        // 绑定事件
        bindEvent() {
            this.$startBtn.click(() => {
                this.logic();
                this.timer = setInterval(() => { this.logic() }, 1500);
                this.$startBtn.hide();
                this.$stopBtn.show();
            });
            this.$stopBtn.click(() => {
                clearInterval(this.timer);
                this.$stopBtn.hide();
                this.$startBtn.show();
                // 暂停视频播放
                if ($(".file-media").length > 0) {
                    let $allVideos = $(".file-media");
                    for (let i = 0; i < $allVideos.length; i++) {
                        if ($('.mejs__button.mejs__playpause-button button').eq(i).attr('title') == 'Pause') {
                            $('.mejs__button.mejs__playpause-button button')[i].click();
                        }
                    }
                }
                // 显示日志
                log.showLogs();
            })
        },

        // 刷课主逻辑
        logic() {
            // 如果页面中弹出了框框
            if ($('.modal.fade.in').length > 0) {
                switch ($('.modal.fade.in').attr('id')) {
                    case 'statModal': {
                        $("#statModal .btn-hollow").eq(-1).click();
                        break;
                    }
                    case 'alertModal': {
                        if ($("#alertModal .btn-hollow").length > 0) {
                            $("#alertModal .btn-hollow").eq(-1).click();
                        }
                        else {
                            $("#alertModal .btn-submit").click();
                        }
                        break;
                    }
                    default: {
                        log.addLog('出现了未知对话框');
                    }
                }
                return;
            }

            // 如果页面中有视频
            if ($(".file-media").length > 0) {
                let $allVideos = $(".file-media");
                let i = 0;
                for (; i < $allVideos.length; i++) {
                    // 这个视频还没有看完并且不是播放状态
                    if (!$("[data-bind='text: $root.i18nMessageText().finished']").get(i)) {
                        // 视频不是播放状态
                        if ($('.mejs__button.mejs__playpause-button button').eq(i).attr('title') == 'Play') {
                            $(".mejs__speed-selector-input")[i * 4].value = 8.00;
                            $(".mejs__speed-selector-input")[i * 4].click();
                            $('.mejs__button.mejs__speed-button button')[i].innerText = '8.00x'
                            $('.mejs__button.mejs__playpause-button button')[i].click();
                        }
                        break;
                    }
                }
                if (i == $allVideos.length) {
                    $('.next-page-btn.cursor').click();
                }
                return;
            }

            // 如果是做题界面
            if ($('.question-setting-panel').length > 0) {

                // 修正当前状态
                let $submitBtn = $('.question-operation-area button').eq(0);
                if ($submitBtn.text() == '重做') {
                    $submitBtn.click();
                    return;
                }

                // 获取当前页面 ID
                let parentId = $('.page-name.active').parent().attr('id').substring(4);

                // 开始同步答题
                let $questions = $('.question-element-node');
                for (let i = 0; i < $questions.length; i++) {
                    respondent.answer(parentId, $questions.eq(i));
                }

                // 提交答案
                $submitBtn.click();
                setTimeout(() => {
                    $('.next-page-btn.cursor').click();
                }, 300);

                return;
            }

            // 下一页
            $('.next-page-btn.cursor').click();
        },
    }

    // 答题器
    const respondent = {
        parentId: null,      // 页面ID
        questionId: null,    // 当前解答问题的ID
        $questionNode: null, // 当前解答问题的根节点

        // 回答问题
        // @param parentId     页面ID
        // @param questionNode 问题根节点
        answer(parentId, $questionNode, callback) {
            this.parentId = parentId;
            this.$questionNode = $questionNode;
            this.questionId = this.$questionNode.find('.question-wrapper').attr('id').substring(8);

            let questionType = $questionNode.find('.question-type-tag').text().trim();
            switch (questionType) {
                case '多选题': {
                    this._answerMultiSelect();
                    break;
                }
                case '单选题': {
                    this._answerSelect();
                    break;
                }
                case '判断题': {
                    this._answerJudge();
                    break;
                }
                case '填空题': {
                    this._answerInput();
                    break;
                }
                case '简答题': {
                    this._answerSimpleQuestion();
                    break;
                }
                case '综合题': {
                    break;
                }
                default: {
                    log.addLog('出现了未知题型');
                }
            }
            if (callback && typeof callback == 'function') callback();
        },

        // 解答多选题
        _answerMultiSelect() {
            // 多选题需要清空当前答案
            let $selected = this.$questionNode.find('.checkbox.selected');
            for (let i = 0; i < $selected.length; i++) {
                $selected.eq(i).click();
            }
            // 获取答案并选择
            let $emptySelected = this.$questionNode.find('.checkbox');
            let answerArray = this._syncGetAnswer().correctAnswerList;
            for (let i = 0; i < answerArray.length; i++) {
                let index = answerArray[i].charCodeAt() - 'A'.charCodeAt();
                $emptySelected.eq(index).click();
            }
        },

        // 解答单选题
        _answerSelect() {
            let $emptySelected = this.$questionNode.find('.checkbox');
            let answerArray = this._syncGetAnswer().correctAnswerList;
            for (let i = 0; i < answerArray.length; i++) {
                let index = answerArray[i].charCodeAt() - 'A'.charCodeAt();
                $emptySelected.eq(index).click();
            }
        },

        // 解答判断题
        _answerJudge() {
            let questionAnswer = this._syncGetAnswer().correctAnswerList[0];
            if (questionAnswer) {
                this.$questionNode.find('.choice-btn.right-btn').click();
            }
            else {
                this.$questionNode.find('.choice-btn.wrong-btn').click();
            }
        },

        // 解答填空题
        _answerInput() {
            let $emptyInput = this.$questionNode.find('.blank-input');
            let inputAnswers = this._syncGetAnswer().correctAnswerList;
            for (let i = 0; i < inputAnswers.length; i++) {
                $emptyInput.eq(i).val(inputAnswers[i]);
            }
        },

        // 解答简答题
        _answerSimpleQuestion() {
            let $emptyInput = this.$questionNode.find('.form-control');
            let inputAnswers = this._syncGetAnswer().correctAnswerList;
            for (let i = 0; i < inputAnswers.length; i++) {
                let answerText = inputAnswers[i].replace(/【答案要点】/g, '');
                $emptyInput.eq(i).val(answerText);
                $emptyInput.change();
            }
        },

        // 同步获取答案
        _syncGetAnswer() {
            return $.ajax({
                url: 'https://api.ulearning.cn/questionAnswer/' + this.questionId + '?parentId=' + this.parentId,
                async: false,
                error: () => {
                    log.addLog('请求答案接口出错');
                }
            }).responseJSON;
        }
    }


    // 日志管理器
    const log = {
        logs: '',
        $modal: $(`
<div class="modal" id="alertModal" tabindex="-1" role="dialog" style="display: none;background-color:rgba(0,0,0,.5)">
    <div class="modal-dialog" role="document" style="width:800px;margin-top:20px">
        <div class="modal-content">
            <i class="iconfont close-btn log-close-btn" data-dismiss="modal" aria-label="Close"></i>
            <div class="modal-image">
                <img src="./img/incomplete.png">
            </div>
            <div class="modal-body">
                <div class="modal-info">
                    <h4>本次刷课出现了意外情况,请将本提示截图并联系作者!</h4>
                    <div class="content log-content" style="text-align:left">
                    </div>
                </div>
                <div class="modal-operation">
                    <button class="btn-submit log-close-btn" type="button">我明白了</button>
                </div>
            </div>
        </div>
    </div>
</div>
`),
        // 初始化日志管理器
        init() {
            $('body').append(this.$modal);
            this.$modal.find('.log-close-btn').click(() => {
                this.$modal.hide();
            })
        },
        // 添加日志
        addLog(info) {
            this.logs += '<span>时间:' + new Date().toJSON() + ' 信息:' + info + '</span><br>';
        },
        // 显示所有日志信息
        showLogs() {
            if (this.logs) {
                this.$modal.find('.log-content').empty();
                this.$modal.find('.log-content').append($('<div>' + this.logs + '</div>'));
                this.$modal.show();
            }
        }
    }

    youxueyuan.init();

})();