Greasy Fork

Greasy Fork is available in English.

Grab Venue in SZU

【使用前先看介绍/有问题可反馈】深大抢馆 (Grab Venue in SZU):抢深圳大学粤海校区体育场馆,目前仅适配了羽毛球项目,了解编程的可以自行修改配置。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Grab Venue in SZU
// @namespace    http://tampermonkey.net/
// @version      1.0.0
// @description  【使用前先看介绍/有问题可反馈】深大抢馆 (Grab Venue in SZU):抢深圳大学粤海校区体育场馆,目前仅适配了羽毛球项目,了解编程的可以自行修改配置。
// @author       cc
// @match        http://ehall.szu.edu.cn/publicapp/sys/tycgyyxt/index.do*
// @grant        none
// ==/UserScript==

(function () {
  const config = {
    DEBUG: false, // 是否开启调试,不要动这个选项
    neededTimeSlot: '19:00-22:00', // 所需时间段
    CQBM: '001', // 场区 ID (可能)
    CGBM: '002', // 场馆 ID (默认羽毛球馆)
    XMDM: '005', // 项目 ID (默认羽毛球)
    CYRS: 4, // 参与人数 (默认 4 人)
    XQWID: null, // 校区 ID,不用修改,由网络请求获取
    startClock: '12:30', // 开始时间
  }

  function inform(msg) {
    msg = `%c${msg}`;
    console.warn(msg, 'background-color: yellow; font-weight: bold;');
  }

  function timeFormat(milliseconds) {
    var unit = parseInt(milliseconds / 1000);
    var second = unit % 60;
    unit = parseInt(unit / 60);
    var minute = unit % 60;
    unit = parseInt(unit / 60);
    var hour = unit % 24;
    var pad = e => e.toString().padStart(2, '0');
    var ans = `${pad(second)} sec`;
    if (minute > 0)
      ans = `${pad(minute)} min ${ans}`;
    if (hour > 0)
      ans = `${pad(hour)} hour ${ans}`;
    return ans;
  }

  function requestVenue(waiting, finished) {
    console.warn('in function requestVenue...');
    if (waiting.length > 0) {
      let WID = waiting[0];
      $.ajax({
        url: 'http://ehall.szu.edu.cn/publicapp/sys/tycgyyxt/sportVenue/getOrderNum.do',
        method: 'POST',
        data: { wid: WID }
      }).then(res => {
        var DHID = res.DHID;
        var YYRQ = getYYRQ();
        var KYYSJD = getHourTimeSlot(config.neededTimeSlot);
        var [START, END] = KYYSJD.split('-');
        var [YYKS, YYJS] = [`${YYRQ} ${START}`, `${YYRQ} ${END}`];
        $.ajax({
          url: 'http://ehall.szu.edu.cn/publicapp/sys/tycgyyxt/sportVenue/insertVenueBookingInfo.do',
          method: 'POST',
          data: {
            DHID: DHID,
            YYRGH: localStorage.ampUserId,
            XQWID: config.XQWID,
            CQBM: config.CQBM,
            CGDM: config.CGBM,
            CDWID: WID,
            XMDM: config.XMDM,
            YYRQ: YYRQ,
            KYYSJD: KYYSJD,
            YYKS: YYKS,
            YYJS: YYJS,
            YYLX: 'YY_TT',
            BCXZRS: 6,
            CYRS: config.CYRS,
            QTYYR: []
          }
        }).then(res => {
          if (res.success) {
            console.warn(res);
            config.neededTimeSlot = nextTimeSlot(config.neededTimeSlot);
            if (!finishBooking(config.neededTimeSlot)) {
              requestVenue(waiting, finished);
            } else {
              inform('all tasks completed.');
            }
          } else {
            finished.push(waiting[0]);
            waiting = waiting.splice(1);
            requestVenue(waiting, finished);
          }
        });
      });
    }
  }

  function getYYRQ() {
    var now = new Date();
    if (config.DEBUG)
      now = new Date(Date.now() + 86400 * 1000);
    var month = `${now.getMonth() + 1}`.padStart(2, '0');
    var date = `${now.getDate()}`.padStart(2, '0');
    return `${now.getFullYear()}-${month}-${date}`;
  }

  function nextHourOf(hour) {
    return `${parseInt(hour.match(/\d+/)[0]) + 1}`.padStart(2, '0') + ':00';
  }

  function getHourTimeSlot(timeSlot) {
    var firstHour = parseInt(timeSlot.match(/\d+/)[0]);
    var START = `${firstHour}`.padStart(2, '0') + ':00';
    var END =  `${firstHour + 1}`.padStart(2, '0') + ':00';
    return `${START}-${END}`
  }

  function nextTimeSlot(timeSlot) {
    var [START, END] = timeSlot.match(/\d+:00/g);
    START = nextHourOf(START);
    return `${START}-${END}`;
  }

  function finishBooking(timeSlot) {
    var [start, end] = timeSlot.match(/\d+:00/g).map(e => parseInt(e.match(/\d+/)[0]));
    return start >= end;
  }

  function isInTimeSlot(neededTimeSlot, timeSlot) {
    var tsRange = timeSlot.match(/\d+:00/g).map(s => parseInt(s.substr(0, 2)));
    let neededTsRange = neededTimeSlot.match(/\d+:00/g).map(s => parseInt(s.substr(0, 2)));
    if (tsRange[0] < neededTsRange[0] || neededTsRange[1] < tsRange[1])
      return false;
    return true;
  }

  function requestWIDs() {
    console.warn('in function requestWIDs...');
    var [START, END] = config.neededTimeSlot.match(/\d{2}:00/g);
    $.ajax({
      url: 'http://ehall.szu.edu.cn/publicapp/sys/tycgyyxt/sportVenue/getCdxx.do',
      method: 'POST',
      data: {
        CGBM: config.CGBM,
        XMDM: config.XMDM,
        TYPE: 'YY_TT',
        START: START,
        END: END,
        YYRQ: getYYRQ(config),
        YYTYPE: '1.0'
      }
    }).then(res => {
      var WIDs = res.map(e => e.id);
      requestVenue(WIDs, []);
    });
  }

  function init() {
    console.warn('in function init...');
    $.ajax({
      url: 'http://ehall.szu.edu.cn/publicapp/sys/tycgyyxt/sportVenue/getSchoolZoneDic.do',
      method: 'POST',
      async: true,
    }).then(res => {
      config.XQWID = res.datas.code.rows[0].id;
    });
  }

  function run() {
    console.warn('in function run...');
    $.ajax({
      url: 'http://ehall.szu.edu.cn/publicapp/sys/tycgyyxt/sportVenue/getSjdByCg.do',
      method: 'POST',
      data: {
        CGBM: config.CGBM,
        XMDM: config.XMDM,
        TYPE: 'YY_TT',
        YYRQ: getYYRQ(config),
        YYTYPE: '1.0'
      },
    }).then(res => {
      var sjd = res.kyysjd.map(e => e.kyysjd);
      var timeslots = sjd.filter(e => isInTimeSlot(config.neededTimeSlot, e));
      if (timeslots.length == 0) {
        console.warn();
      } else {
        requestWIDs(timeslots);
      }
    });
  }

  function standBy() {
    init();
    console.warn('in function standBy...');
    var now = new Date();
    var startHourMinute = config.startClock.split(':').map(e => parseInt(e));
    var startClock = {
      hour: startHourMinute[0],
      minute: startHourMinute[1],
      second: 0
    };
    var currentClock = {
      hour: now.getHours(),
      minute: now.getMinutes(),
      second: now.getSeconds()
    }
    if (currentClock.hour < startClock.hour || (currentClock.hour == startClock.hour && currentClock.minute < startClock.minute)) {
      var diffMillis = ((startClock.hour - currentClock.hour) * 3600 + (startClock.minute - currentClock.minute) * 60 + (startClock.second - currentClock.second)) * 1000;
      console.warn(`Tasks will be executed in ${timeFormat(diffMillis)}.`)
      setTimeout(run, diffMillis);
    } else {
      inform('The time limit is exceeded and the program is no longer executed.');
    }
  }

  standBy();
})();