Greasy Fork is available in English.

超星学习通助手[最强答题][支持图片题]

超星学习通自动自动挂视频、自动答题

// ==UserScript==
// @name         超星学习通助手[最强答题][支持图片题]
// @namespace    tsoil
// @version      3.3.0
// @description  超星学习通自动自动挂视频、自动答题
// @author       tsoil
// @match        *://*.edu.cn/*
// @match        *://*.chaoxing.com/*
// @connect      cx.icodef.com
// @run-at       document-end
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @grant        GM_setClipboard
// @license      MIT
// @original-script https://greasyfork.org/scripts/369625
// @original-author wyn665817
// @original-license MIT
// ==/UserScript==


var setting = {
    time: 5E3
    , audio: 1
    , book: 1
    , course: 0
    , docs: 1
    , face: 1
    , http: '标清'
    , jump: 1
    , line: '公网1'
    , lock: 1
    , rate: '1'
    , read: '65'
    , review: 0
    , scale: 0
    , school: '账号为手机号可以不修改此参数'
    , total: 1
    , username: ''
    , video: 1
    , vol: '0'
    , auto: 0
    , work: 1
    , none: 0
    , password: ''
    , queue: 1

  }
  , _self = unsafeWindow
  , url = location.pathname
  , top = _self;


setting.notice = '公告栏';

var tmpSubmit = 1; //本次
Object.defineProperty(setting, "auto"
  , {
    get: function ()
    {
      if (tmpSubmit >= 2)
      {
        return tmpSubmit === 3;
      }
      return GM_getValue(
        "autosubmit");
    }
    , set: function (value)
    {
      tmpSubmit = value + 2;
    }
  });
if (url != '/studyApp/studying' &&
  top != _self.top) document.domain =
  location.host.replace(/.+?\./, '');

try
{
  while (top != _self.top)
  {
    top = top.parent.document ? top
      .parent : _self.top;
    if (top.location.pathname ==
      '/mycourse/studentstudy') break;
  }
}
catch (err)
{
  // console.log(err);
  top = _self;
}

var $ = _self.jQuery || top.jQuery
  , parent = _self == top ? self : _self
  .parent
  , Ext = _self.Ext || parent.Ext ||
  {}
  , UE = _self.UE
  , vjs = _self.videojs;

String.prototype.toCDB = function ()
{
  return this.replace(/\s/g, '')
    .replace(/[\uff01-\uff5e]/g
      , function (str)
      {
        return String.fromCharCode(str
          .charCodeAt(0) - 65248);
      })
    .replace(/[“”]/g, '"')
    .replace(/[‘’]/g, "'")
    .replace(
      /。/g, '.');
};

// setting.time += Math.ceil(setting.time * Math.random()) - setting.time / 2;
setting.job = [':not(*)'];
setting.normal = ''; // ':visible'

setting.video && setting.job.push(
  'iframe[src*="/video/index.html"]');
setting.book && setting.job.push(
  'iframe[src*="/innerbook/index.html"]'
);
setting.docs && setting.job.push(
  'iframe[src*="/ppt/index.html"]'
  , 'iframe[src*="/pdf/index.html"]');
setting.work && setting.job.push(
  'iframe[src*="/work/index.html"]');
setting.audio && setting.job.push(
  'iframe[src*="/audio/index.html"]');

setting.tip = !setting.queue || top !=
  _self && jobSort($ || Ext.query);


function getIframe(tip, win, job)
{
  if (!$) return Ext.get(frameElement ||
      [])
    .parent()
    .child(
      '.ans-job-icon') || Ext.get([]);
  do {
    win = win ? win.parent : _self;
    job = $(win.frameElement)
      .prevAll(
        '.ans-job-icon');
  } while (!job.length && win.parent
    .frameElement);
  return tip ? win : job;
}


function hookAudio()
{
  _self.alert = console.log;
  var config = arguments[1];
  config.plugins.studyControl
    .enableSwitchWindow = 1;
  config.plugins.seekBarControl
    .enableFastForward = 1;
  if (!setting.queue) delete config
    .plugins.studyControl;
  var player = vjs.apply(this
      , arguments)
    , a =
    '<a href="https://d0.ananas.chaoxing.com/download/' +
    _self.config('objectid') +
    '" target="_blank">'
    , img =
    '<img src="https://d0.ananas.chaoxing.com/download/e363b256c0e9bc5bd8266bf99dd6d6bb" style="margin: 6px 0 0 6px;">';
  player.volume(Math.round(setting
    .vol) / 100 || 0);
  player.playbackRate(setting.rate >
    16 || setting.rate < 0.0625 ? 1 :
    setting.rate);
  Ext.get(player.controlBar.addChild(
        'Button')
      .el_)
    .setHTML(a + img +
      '</a>')
    .dom.title = '下载音频';
  player.on('loadeddata', function ()
  {
    setting.tip && this.play()
      .catch(Ext.emptyFn);
  });
  player.one('firstplay', function ()
  {
    setting.rate === '0' && config
      .plugins.seekBarControl
      .sendLog(this.children_[0]
        , 'ended', Math.floor(this
          .cache_.duration));
  });
  player.on('ended', function ()
  {
    Ext.fly(frameElement)
      .parent()
      .addCls('ans-job-finished');
  });
  return player;
}

function checkPlayer(tip)
{
  _self.videojs = hookVideo;
  hookVideo.xhr = vjs.xhr;
  Ext.isSogou = Ext.isIos = Ext
    .isAndroid = false;
  var data = Ext.decode(_self.config(
    'data')) ||
  {};
  delete data.danmaku;
  data.doublespeed = 1;
  frameElement.setAttribute('data', Ext
    .encode(data));
  if (tip) return;
  _self.supportH5Video = function ()
  {
    return true;
  };
  alert('此浏览器不支持html5播放器,请更换浏览器');
}
if (url == '/mycourse/studentstudy')
{
  _self.checkMobileBrowerLearn = $.noop;
  var classId = location.search.match(
      /cla[zs]{2}id=(\d+)/i)[1] || 0
    , courseId = _self.courseId ||
    location.search.match(
      /courseId=(\d+)/i)[1] || 0;
  setting.lock || $('#coursetree')
    .on(
      'click'
      , '[onclick*=void], [href*=void]'
      , function ()
      {
        _self.getTeacherAjax(courseId
          , classId, $(this)
          .parent()
          .attr('id')
          .slice(3));
      });
}
else if (url ==
  '/ananas/modules/video/index.html' &&
  setting.video)
{
  if (setting.review) _self.greenligth =
    Ext.emptyFn;
  checkPlayer(_self.supportH5Video());
}
else if (url ==
  '/work/doHomeWorkNew' || url ==
  '/api/work' || url ==
  '/work/addStudentWorkNewWeb' || url ==
  '/mooc2/work/dowork')
{
  console.log("进入答题界面!");
  if (!UE)
  {
    var len = ($ || Ext.query || Array)(
        'font:contains(未登录)', document)
      .length;
    setTimeout(len == 1 ? top.location
      .reload : parent.greenligth
      , setting.time);
  }
  else if (setting.work)
  {
    setTimeout(relieveLimit, 0);
    beforeFind();
  }
}
else if (url ==
  '/ananas/modules/audio/index.html' &&
  setting.audio)
{
  if (setting.review) _self.greenligth =
    Ext.emptyFn;
  _self.videojs = hookAudio;
  hookAudio.xhr = vjs.xhr;
}
else if (url ==
  '/ananas/modules/innerbook/index.html' &&
  setting.book && setting.tip)
{
  setTimeout(function ()
  {
    _self.setting ? _self.top
      .onchangepage(_self
        .getFrameAttr('end')) :
      _self.greenligth();
  }, setting.time);
}
else if (url.match(
    /^\/ananas\/modules\/(ppt|pdf)\/index\.html$/
  ) && setting.docs && setting.tip)
{
  setTimeout(function ()
  {
    _self.setting ? _self
      .finishJob() : _self
      .greenligth();
  }, setting.time);
  frameElement.setAttribute('download'
    , 1);
}
else if (url == '/knowledge/cards')
{
  $ && checkToNext();
}
else if (url.match(
    /^\/(course|zt)\/\d+\.html$/))
{
  setTimeout(function ()
  {
    +setting.read && _self
      .sendLogs && $(
        '.course_section:eq(0) .chapterText'
      )
      .click();
  }, setting.time);
}
else if (url ==
  '/ztnodedetailcontroller/visitnodedetail'
)
{
  setting.read *= 60 / $(
      '.course_section')
    .length;
  setting.read && _self.sendLogs &&
    autoRead();
}
else if (url ==
  '/mycourse/studentcourse')
{
  var gv = location.search.match(
    /d=\d+&/g);
  setting.total && $('<a>'
      , {
        href: '/moocAnalysis/chapterStatisticByUser?classI' +
          gv[1] + 'courseI' + gv[0] +
          'userId=' + _self.getCookie(
            '_uid') + '&ut=s'
        , target: '_blank'
        , title: '点击查看章节统计'
        , style: 'margin: 0 25px;'
        , html: '本课程共' + $('.icon')
          .length + '节,剩余' + $(
            'em:not(.openlock)')
          .length + '节未完成'
      })
    .appendTo('.zt_logo')
    .parent()
    .width('auto');
}
else if (url.match(
    /^\/visit\/(courses|interaction)$/
  ))
{
  setting.face && $('.zmodel')
    .on(
      'click', '[onclick^=openFaceTip]'
      , DisplayURL);
}
else if (location.host.match(
    /^passport2/))
{
  setting.username && getSchoolId();
}
else if (location.hostname ==
  'i.mooc.chaoxing.com')
{
  _self.layui.use('layer', function ()
  {
    this.layer.open(
    {
      content: '拖动进度条、倍速播放、秒过会导致不良记录!题库在慢慢补充,搜不到的题目系统会在次日进行自动补充'
      , title: '超星网课助手提示'
      , btn: '我已知悉'
      , offset: 't'
      , closeBtn: 0
    });
  });
}
else if (url ==
  '/widget/pcvote/goStudentVotePage')
{
  $(':checked')
    .click();
  $('.StudentTimu')
    .each(function (
      index)
    {
      var ans = _self.questionlist[
        index].answer;
      $(':radio, :checkbox', this)
        .each(function (num)
        {
          ans[num].isanswer && this
            .click();
        });
      $(':text', this)
        .val(function (
          num)
        {
          return $(ans[num].content)
            .text()
            .trim();
        });
    });
}
else if (url ==
  '/work/selectWorkQuestionYiPiYue')
{
  submitAnswer(getIframe()
    .parent(), $
    .extend(true, [], parent._data));
}

function jobSort($)
{
  var fn = $.fn ? [getIframe(1)
      , 'length'
    ] : [self, 'dom']
    , sel = setting.job.join(
      ', :not(.ans-job-finished) > .ans-job-icon' +
      setting.normal + ' ~ ');
  if ($(sel, fn[0].parent.document)[
      0] == fn[0].frameElement)
    return true;
  if (!getIframe()[fn[1]] || getIframe()
    .parent()
    .is('.ans-job-finished'))
    return null;
  setInterval(function ()
  {
    $(sel, fn[0].parent.document)[
        0] == fn[0].frameElement &&
      fn[0].location.reload();
  }, setting.time);
}

function hookVideo()
{
  _self.alert = console.log;
  var config = arguments[1]
    , line = Ext.Array.filter(Ext.Array
      .map(config.playlines, function (
        value, index)
      {
        return value.label == setting
          .line && index;
      })
      , function (value)
      {
        return Ext.isNumber(value);
      })[0] || 0
    , http = Ext.Array.filter(config
      .sources
      , function (value)
      {
        return value.label == setting
          .http;
      })[0];
  config.playlines.unshift(config
    .playlines[line]);
  config.playlines.splice(line + 1, 1);
  config.plugins
    .videoJsResolutionSwitcher.default =
    http ? http.res : 360;
  config.plugins.studyControl
    .enableSwitchWindow = 1;
  config.plugins.timelineObjects.url =
    '/richvideo/initdatawithviewer?';
  config.plugins.seekBarControl
    .enableFastForward = 1;
  if (!setting.queue) delete config
    .plugins.studyControl;
  // config.preload = setting.tip ? 'auto' : 'none';
  var player = vjs.apply(this
      , arguments)
    , a =
    '<a href="https://d0.ananas.chaoxing.com/download/' +
    _self.config('objectid') +
    '" target="_blank">'
    , img =
    '<img src="https://d0.ananas.chaoxing.com/download/e363b256c0e9bc5bd8266bf99dd6d6bb" style="margin: 6px 0 0 6px;">';
  player.volume(Math.round(setting
    .vol) / 100 || 0);
  Ext.get(player.controlBar.addChild(
        'Button')
      .el_)
    .setHTML(a + img +
      '</a>')
    .dom.title = '下载视频';
  player.on('loadstart', function ()
  {
    setting.tip && this.play()
      .catch(Ext.emptyFn);
    this.playbackRate(setting.rate >
      16 || setting.rate <
      0.0625 ? 1 : setting.rate);
  });
  player.one(['loadedmetadata'
    , 'firstplay'
  ], function ()
  {
    setting.two = setting.rate ===
      '0' && setting.two < 1;
    setting.two && config.plugins
      .seekBarControl.sendLog(this
        .children_[0], 'ended', Math
        .floor(this.cache_.duration)
      );
  });
  player.on('ended', function ()
  {
    Ext.fly(frameElement)
      .parent()
      .addCls('ans-job-finished');
  });
  return player;
}


function relieveLimit()
{
  if (setting.scale) _self
    .UEDITOR_CONFIG.scaleEnabled =
    false;
  $.each(UE.instants, function ()
  {
    var key = this.key;
    this.ready(function ()
    {
      this.destroy();
      UE.getEditor(key);
    });
  });
}



function findAnswer()
{
  if (setting.num >= $('.TiMu')
    .length)
  {
    var arr = setting.lose ? [
      '共有 <font color="red">' +
      setting.lose +
      '</font> 道题目待完善(已深色标注)'
      , saveThis
    ] : ['答题已完成', submitThis];
    setting.div.children('div:eq(0)')
      .data('html', arr[0])
      .siblings(
        'button:eq(0)')
      .hide()
      .click();
    return setTimeout(arr[1], setting
      .time);
  }
  var $TiMu = $('.TiMu')
    .eq(setting
      .num)
    , question = filterImg($TiMu.find(
      '.Zy_TItle:eq(0) .clearfix'))
    .replace(/^【.*?】\s*/, '')
    .replace(
      /\s*(\d+\.\d+分)$/, '')
    .replace(
      /[(]\s*[)]。$/, '')
    .replace(
      /(\s*)。$/, '')
    .replace(
      /[(]\s*[)]$/, '')
    .replace(
      /(\s*)$/, '')
    .replace(/。$/, '')
    , type = $TiMu.find(
      'input[name^=answertype]:eq(0)')
    .val() || '-1';

  console.log($TiMu);

  if (question == "")
  {
    question = filterImg($TiMu.find(
      '.mark_name:eq(0) .colorDeep'
    ));
  }
  console.log($TiMu.find(
    '.mark_name:eq(0) .colorDeep'));

  GM_xmlhttpRequest(
  {
    method: 'POST'
    , url: 'http://cx.icodef.com/wyn-nb?v=2'
    , headers:
    {
      'Content-type': 'application/x-www-form-urlencoded'
      , 'Authorization': ''
    , }
    , data: 'question=' +
      encodeURIComponent(question) +
      '&type=' + type + '&id=' + ($(
          '#workLibraryId')
        .val() ||
        $('#oldWorkId')
        .val())
    , timeout: setting.time
    , onload: function (xhr)
    {
      if (!setting
        .loop)
      {}
      else if (xhr
        .status == 200)
      {
        var obj = $.parseJSON(xhr
          .responseText) ||
        {};
        obj.answer = obj.data;
        if (obj.code)
        {
          setting.div.children(
              'div:eq(0)')
            .text(
              '正在搜索答案...');
          var td =
            '<td style="border: 1px solid;'
            , answer = String(obj
              .answer)
            .replace(
              /&/g, '&')
            .replace(
              /<(?!img)/g, '<');
          obj.answer = /^http/
            .test(answer) ?
            '<img src="' + obj
            .answer + '">' : obj
            .answer;
          $(
              '<tr>' +
              td +
              ' text-align: center;">' +
              $TiMu.find(
                '.Zy_TItle:eq(0) i'
              )
              .text()
              .trim() +
              '</td>' +
              td +
              '" title="点击可复制">' +
              (question.match(
                  '<img') ?
                question :
                question.replace(
                  /&/g, '&')
                .replace(/</g
                  , '<')) +
              '</td>' +
              td +
              '" title="点击可复制">' +
              (/^http/.test(
                  answer) ? obj
                .answer : '') +
              answer + '</td>' +
              '</tr>'
            )
            .appendTo(setting.div
              .find('tbody'))
            .css(
              'background-color'
              , fillAnswer($TiMu
                .find('ul:eq(0)')
                .find('li'), obj
                , type) ? '' :
              'rgba(0, 150, 136, 0.6)'
            );
          setting.data[setting
            .num++] = {
            code: obj.code > 0 ?
              1 : 0
            , question: question
            , option: obj
              .answer
            , type: Number(type)
          };
        }
        else
        {
          setting.div.children(
              'div:eq(0)')
            .html(
              obj.answer ||
              setting.over +
              '服务器繁忙,正在重试...');
        }
        setting.div.children(
            'span')
          .html(obj
            .msg || '');
      }
      else if (xhr.status ==
        403)
      {
        var html = xhr
          .responseText.indexOf(
            '{') ?
          '请求过于频繁,请稍后再试' : $
          .parseJSON(xhr
            .responseText)
          .data;
        setting.div.children(
            'div:eq(0)')
          .data(
            'html', html)
          .siblings(
            'button:eq(0)')
          .click();
      }
      else
      {
        setting.div.children(
            'div:eq(0)')
          .html(
            '题库异常,可能被恶意攻击了...请等待恢复'
          );
      }
    }
    , ontimeout: function ()
    {
      setting.loop && setting.div
        .children('div:eq(0)')
        .html(setting.over +
          '服务器超时,正在重试...');
    }
  });
}

function submitAnswer($job, data)
{
  $job.removeClass('ans-job-finished');
  data = data.length ? $(data) : $(
      '.TiMu')
    .map(function ()
    {
      var title = filterImg($(
        '.Zy_TItle .clearfix'
        , this));
      return {
        question: title.replace(
          /^【.*?】\s*/, '')
        , type: (
        {
          单选题: 0
          , 多选题: 1
          , 填空题: 2
          , 判断题: 3
        })[title.match(
          /^【(.*?)】|$/)[1]]
      };
    });
  data = $.grep(data.map(function (
    index)
  {
    var $TiMu = $('.TiMu')
      .eq(
        index);
    if (!($.isPlainObject(this) &&
        this.type < 4 && $TiMu
        .find('.fr')
        .length))
    {
      return false;
    }
    else if (this.type == 2)
    {
      var $ans = $TiMu.find(
          '.Py_tk, .Py_answer')
        .eq(0);
      if (!$TiMu.find('.cuo')
        .length && this.code)
      {
        return false;
      }
      else if (!$ans.find(
          '.cuo')
        .length)
      {
        this.option = $ans.find(
            '.clearfix')
          .map(
            function ()
            {
              return $(this)
                .text()
                .trim();
            })
          .get()
          .join('#') ||
          '无';
      }
      else if (this.code)
      {
        this.code = -1;
      }
      else
      {
        return false;
      }
    }
    else if (this.type == 3)
    {
      var ans = $TiMu.find(
          '.font20:last')
        .text();
      if ($TiMu.find('.cuo')
        .length)
      {
        this.option = (
        {
          '√': '错误'
          , '×': '正确'
        })[ans] || '无';
      }
      else if (!this.code)
      {
        this.option = (
        {
          '√': '正确'
          , '×': '错误'
        })[ans] || '无';
      }
      else
      {
        return false;
      }
    }
    else
    {
      var text = $TiMu.find(
          '.Py_answer > span:eq(0)'
        )
        .text();
      if ($TiMu.find('.dui')
        .length && this.code && !
        /^A?B?C?D?E?F?G?$/.test(
          this.option))
      {
        return false;
      }
      else if ($TiMu.find(
          '.dui')
        .length || text
        .match('正确答案'))
      {
        text = text.match(
          /[A-G]/gi) || [];
        this.option = $.map(text
            , function (value)
            {
              return filterImg(
                $TiMu.find(
                  '.fl:contains(' +
                  value +
                  ') + a'));
            })
          .join('#') || '无';
        this.key = text.join('');
      }
      else if (this.code)
      {
        this.code = -1;
      }
      else
      {
        return false;
      }
    }
    return this;
  }), function (value)
  {
    return value && value.option !=
      '无';
  });
  setting.curs = $(
      'script:contains(courseName)', top
      .document)
    .text()
    .match(
      /courseName:\'(.+?)\'|$/)[1] || $(
      'h1')
    .text()
    .trim() || '无';
  $job.addClass('ans-job-finished');
}


function fillAnswer($li, obj, type)
{
  var $input = $li.find(
      ':radio, :checkbox')
    , str = String(obj.answer)
    .toCDB() ||
    new Date()
    .toString()
    , data = str.split(/#|\x01|\|/)
    , opt = obj.opt || str
    , state = setting.lose;
  // $li.find(':radio:checked').prop('checked', false);
  obj.code > 0 && $input.each(function (
      index)
    {
      if (this.value == 'true')
      {
        data.join()
          .match(
            /(^|,)(正确|是|对|√|T|ri)(,|$)/
          ) && this.click();
      }
      else if (this.value ==
        'false')
      {
        data.join()
          .match(
            /(^|,)(错误|否|错|×|F|wr)(,|$)/
          ) && this.click();
      }
      else
      {
        var tip = filterImg($li.eq(
              index)
            .find('.after'))
          .toCDB() || new Date()
          .toString();
        Boolean($.inArray(tip, data) +
            1 || (type == '1' && str
              .indexOf(tip) + 1)) ==
          this.checked || this
          .click();
      }
    })
    .each(function ()
    {
      if (!/^A?B?C?D?E?F?G?$/.test(
          opt)) return false;
      Boolean(opt.match(this
          .value)) == this.checked ||
        this.click();
    });
  if (type.match(/^[013]$/))
  {
    $input.is(':checked') || (setting
      .none ? ($input[Math.floor(Math
        .random() * $input.length
      )] || $())
      .click() : setting
      .lose++);
  }
  else if (type.match(
      /^(2|[4-9]|1[08])$/))
  {
    data = String(obj.answer)
      .split(
        /#|\x01|\|/);
    str = $li.end()
      .find('textarea')
      .each(function (index)
      {
        index = (obj.code > 0 && data[
          index]) || '';
        if (obj.code > 0)
        {
          UE.getEditor(this.name)
            .setContent(index.trim());
        }
      })
      .length;
    (obj.code > 0 && data.length ==
      str) || setting.none || setting
      .lose++;
  }
  else
  {
    setting.none || setting.lose++;
  }
  return state == setting.lose;
}


function submitThis()
{
  if (!setting.auto)
  {}
  else if (!$(
      '.Btn_blue_1:visible')
    .length)
  {
    setting.div.children('button:lt(3)')
      .hide()
      .eq(1)
      .click();
    return setting.regl();
  }
  else if ($('#confirmSubWin:visible')
    .length)
  {
    var btn = $('#tipContent + * > a')
      .offset() ||
      {
        top: 0
        , left: 0
      }
      , mouse = document.createEvent(
        'MouseEvents');
    btn = [btn.left + Math.ceil(Math
        .random() * 46), btn.top +
      Math.ceil(Math.random() * 26)
    ];
    mouse.initMouseEvent('click', true
      , true, document.defaultView, 0
      , 0, 0, btn[0], btn[1], false
      , false, false, false, 0, null);
    _self.event = $.extend(true
      , {}
      , mouse);
    delete _self.event.isTrusted;
    _self.form1submit();
  }
  else
  {
    $('.Btn_blue_1')[0].click();
  }
  setTimeout(submitThis, Math.ceil(
      setting.time * Math.random()) *
    2);
}


function beforeFind()
{
  setting.regl = parent.greenligth || $
    .noop;
  if ($.type(parent._data) == 'array')
    return setting.regl();
  var maximize = $(
      '<div style="border: 2px dashed rgb(0, 85, 68); position: fixed; top: 0; right: 0; z-index: 99999; background-color: rgba(70, 196, 38, 0.6); overflow-x: auto;display:none;">◻</div>'
    )
    .appendTo('body')
    .click(
      function ()
      {
        $(setting.div)
          .css("display"
            , "block");
        GM_setValue("minimize", "0");
        $(maximize)
          .css("display"
            , "none");
      });

  setting.div = $(
      '<div style="border: 2px dashed rgb(0, 85, 68); width: 330px; position: fixed; top: 0; right: 0; z-index: 99999; background-color: rgba(70, 196, 38, 0.6); overflow-x: auto;">' +
      '<span style="font-size: medium;"></span>' +
      '<div style="font-size: medium;width:70%;display: inline-block;">正在搜索答案...</div>' +
      '<div style="width:30%;display: inline-block;padding-right: 10px;box-sizing: border-box;text-align: right;"><minimize style="width:20px;font-size:16px;line-height: 12px;font-weight: bold;cursor: context-menu;user-select:none;">一</minimize></div>' +
      '<div id="cx-notice" style="border-top: 1px solid #000;border-bottom: 1px solid #000;margin: 4px 0px;overflow: hidden;">' +
      setting.notice + '</div>' +
      '<button style="margin-right: 10px;">暂停答题</button>' +
      '<button style="margin-right: 10px;">' +
      (setting.auto ? '取消本次自动提交' :
        '开启本次自动提交') + '</button>' +
      '<button style="margin-right: 10px;">重新查询</button>' +
      '<button>折叠面板</button><br>' +
      '<input id="autosubmit" type="checkbox"' +
      (setting.auto ? ' checked' : '') +
      '>自动提交</input>' +
      '<div style="max-height: 300px; overflow-y: auto;">' +
      '<table border="1" style="font-size: 12px;">' +
      '<thead>' +
      '<tr>' +
      '<th style="width: 25px; min-width: 25px;">题号</th>' +
      '<th style="width: 60%; min-width: 130px;">题目(点击可复制)</th>' +
      '<th style="min-width: 130px;">答案(点击可复制)</th>' +
      '</tr>' +
      '</thead>' +
      '<tfoot style="display: none;">' +
      '<tr>' +
      '<th colspan="3">答案提示框 已折叠</th>' +
      '</tr>' +
      '</tfoot>' +
      '<tbody>' +
      '<tr>' +
      '<td colspan="3" style="display: none;"></td>' +
      '</tr>' +
      '</tbody>' +
      '</table>' +
      '</div>' +
      '</div>'
    )
    .appendTo('body')
    .on('click'
      , 'button, td, input'
      , function ()
      {
        var len = $(this)
          .prevAll(
            'button')
          .length;
        if (this.nodeName == 'TD')
        {
          $(this)
            .prev()
            .length &&
            GM_setClipboard($(this)
              .text());
        }
        else if (!$(this)
          .siblings()
          .length)
        {
          $(this)
            .parent()
            .text(
              '正在搜索答案...');
          setting.num++;
        }
        else if (len === 0)
        {
          if (setting.loop)
          {
            clearInterval(setting.loop);
            delete setting.loop;
            len = ['已暂停搜索', '继续答题'];
          }
          else
          {
            setting.loop = setInterval(
              findAnswer, setting.time
            );
            len = ['正在搜索答案...', '暂停答题'];
          }
          setting.div.children(
              'div:eq(0)')
            .html(
              function ()
              {
                return $(this)
                  .data(
                    'html') || len[0];
              })
            .removeData('html');
          $(this)
            .html(len[1]);
        }
        else if (len == 1)
        {
          setting.auto = !setting.auto;
          $(this)
            .html(setting.auto ?
              '取消本次自动提交' : '开启本次自动提交');
        }
        else if (len == 2)
        {
          parent.location.reload();
        }
        else if (len == 3)
        {
          setting.div.find(
              'tbody, tfoot')
            .toggle();
        }
        else if (this.id ==
          "autosubmit")
        {
          // 题目自动提交配置
          console.log(this.checked);
          GM_setValue("autosubmit", this
            .checked);
        }
      })
    .on('click', 'minimize'
      , function ()
      {
        $(this)
          .parent()
          .parent()
          .css(
            "display", "none");
        GM_setValue("minimize", "1");
        $(maximize)
          .css("display"
            , "block");
      })
    .find('table, td, th')
    .css(
      'border', '1px solid')
    .end();

  if (GM_getValue("minimize") == "1")
  {
    $(setting.div)
      .css("display"
        , "none");
    $(maximize)
      .css("display", "block");
  }

  setting.lose = setting.num = 0;
  setting.data = parent._data = [];
  setting.over =
    '<button style="margin-right: 10px;">跳过此题</button>';
  setting.curs = $(
      'script:contains(courseName)', top
      .document)
    .text()
    .match(
      /courseName:\'(.+?)\'|$/)[1] || $(
      'h1')
    .text()
    .trim() || '无';
  setting.loop = setInterval(findAnswer
    , setting.time);
  var tip = (
  {
    undefined: '任务点排队中'
    , null: '等待切换中'
  })[setting.tip];
  tip && setting.div.children(
      'div:eq(0)')
    .data('html', tip)
    .siblings('button:eq(0)')
    .click();

}

function autoRead()
{
  $('html, body')
    .animate(
      {
        scrollTop: $(document)
          .height() - $(window)
          .height()
      }, Math.round(setting.read) * 1E3
      , function ()
      {
        $('.nodeItem.r i')
          .click();
      })
    .one('click', '#top', function (
      event)
    {
      $(event.delegateTarget)
        .stop();
    });
}

function getSchoolId()
{
  var school = /^1\d{10}$/.test(setting
    .username) ? '' : setting.school;
  if (!isNaN(school)) return setTimeout(
    toLogin, setting.time, school);
  if (school == '账号为手机号可以不修改此参数')
    return alert('请修改school参数');
  $.getJSON('/org/searchUnis?filter=' +
    encodeURI(school) + '&product=44'
    , function (data)
    {
      if (!data.result) return alert(
        '学校查询错误');
      var msg = $.grep(data.froms
        , function (value)
        {
          return value.name ==
            school;
        })[0];
      msg ? setTimeout(toLogin
        , setting.time, msg.schoolid
      ) : alert('学校名称不完整');
    });
}

function toLogin(fid)
{
  GM_xmlhttpRequest(
  {
    method: 'GET'
    , url: '/api/login?name=' +
      setting.username + '&pwd=' +
      setting.password +
      '&schoolid=' + fid +
      '&verify=0'
    , onload: function (xhr)
    {
      var obj = $.parseJSON(xhr
        .responseText) ||
      {};
      obj.result ? location.href =
        decodeURIComponent($(
            '#ref, #refer_0x001')
          .val()) : alert(obj
          .errorMsg || 'Error');
    }
  });
}

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 switchCourse()
{
  GM_xmlhttpRequest(
  {
    method: 'GET'
    , url: '/visit/courses/study?isAjax=true&fileId=0&debug='
    , headers:
    {
      'Referer': location.origin +
        '/visit/courses'
      , 'X-Requested-With': 'XMLHttpRequest'
    }
    , onload: function (xhr)
    {
      var list = $('h3 a[target]'
          , xhr.responseText)
        .map(
          function ()
          {
            return $(this)
              .attr(
                'href');
          })
        , index = list.map(
          function (
            index)
          {
            return this.match(top
                .courseId) &&
              index;
          })
        .filter(function ()
        {
          return $.isNumeric(
            this);
        })[0] + 1 || 0;
      setting.course = list[
        index] ? goCourse(list[
        index]) : 0;
    }
  });
}


function goCourse(url)
{
  GM_xmlhttpRequest(
  {
    method: 'GET'
    , url: url
    , onload: function (xhr)
    {
      $.globalEval(
        'location.href = "' + $(
          '.articlename a[href]'
          , xhr.responseText)
        .attr('href') + '";');
    }
  });
}

function toNext()
{
  var $cur = $('#cur' + $(
        '#chapterIdid')
      .val())
    , $tip = $('span.currents ~ span')
    , sel = setting.review ? 'html' :
    '.blue';
  if (!$cur.has(sel)
    .length && $tip
    .length) return $tip.eq(0)
    .click();
  $tip = $(
      '.roundpointStudent, .roundpoint')
    .parent();
  $tip = $tip.slice($tip.index($cur) +
      1)
    .not(':has(' + sel + ')');
  $tip.not(setting.lock ?
      ':has(.lock)' : 'html')
    .find(
      'span')
    .eq(0)
    .click();
  $tip.length || setting.course &&
    switchCourse();
}
function checkToNext()
{
  var $tip = $(setting.job.join(', ')
      , document)
    .prevAll(
      '.ans-job-icon' + setting.normal);
  setInterval(function ()
  {
    $tip.parent(
        ':not(.ans-job-finished)')
      .length || setting.jump &&
      toNext();
  }, setting.time);
}

function DisplayURL()
{
  _self.WAY.box.hide();
  var $li = $(this)
    .closest('li');
  $.get('/visit/goToCourseByFace'
    , {
      courseId: $li.find(
          'input[name=courseId]')
        .val()
      , clazzId: $li.find(
          'input[name=classId]')
        .val()
    }
    , function (data)
    {
      $li.find(
          '[onclick^=openFaceTip]')
        .removeAttr('onclick')
        .attr(
        {
          target: '_blank'
          , href: $(data)
            .filter(
              'script:last')
            .text()
            .match(/n\("(.+?)"/)[1]
        });
      alert('本课程已临时解除面部识别');
    }, 'html');
}

function saveThis()
{
  if (!setting.auto) return setTimeout(
    saveThis, setting.time);
  setting.div.children('button:lt(3)')
    .hide()
    .eq(1)
    .click();
  _self.alert = console.log;
  $('#tempsave')
    .click();
  setting.regl();
}