您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Support finding a page on AtCoder standings
当前为
// ==UserScript== // @name AtCoder Auto Pager // @namespace https://github.com/mihatsu-s/ // @version 1.0.1 // @description Support finding a page on AtCoder standings // @author Mihatsu // @license MIT // @supportURL https://github.com/mihatsu-s/atcoder-auto-pager/issues // @match https://atcoder.jp/contests/*/standings // @match https://atcoder.jp/contests/*/standings?* // @match https://atcoder.jp/contests/*/standings/ // @match https://atcoder.jp/contests/*/standings/?* // @match https://atcoder.jp/contests/*/standings/virtual // @match https://atcoder.jp/contests/*/standings/virtual?* // @match https://atcoder.jp/contests/*/standings/virtual/ // @match https://atcoder.jp/contests/*/standings/virtual/?* // @match https://atcoder.jp/contests/*/results // @match https://atcoder.jp/contests/*/results?* // @match https://atcoder.jp/contests/*/results/ // @match https://atcoder.jp/contests/*/results/?* // @exclude https://atcoder.jp/*/json // ==/UserScript== /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ 426: /***/ ((module, __webpack_exports__, __webpack_require__) => { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "Z": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(645); /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0__); // Imports var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0___default()(function(i){return i[1]}); // Module ___CSS_LOADER_EXPORT___.push([module.id, "#vue-standings thead th, #vue-results thead th {\n vertical-align: middle;\n}\n\n.auto-pager-input {\n width: 100%;\n font-size: 80%;\n font-weight: normal;\n border: 1px solid #ccc;\n border-radius: 2px;\n}\n\n.auto-pager-input.error {\n background-color: #fcc;\n}\n\n.auto-pager-input.active {\n background-color: #cfc;\n border-color: #6c6;\n color: #093;\n}\n", ""]); // Exports /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___); /***/ }), /***/ 645: /***/ ((module) => { /* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ // css base code, injected by the css-loader // eslint-disable-next-line func-names module.exports = function (cssWithMappingToString) { var list = []; // return the list of modules as css string list.toString = function toString() { return this.map(function (item) { var content = cssWithMappingToString(item); if (item[2]) { return "@media ".concat(item[2], " {").concat(content, "}"); } return content; }).join(""); }; // import a list of modules into the list // eslint-disable-next-line func-names list.i = function (modules, mediaQuery, dedupe) { if (typeof modules === "string") { // eslint-disable-next-line no-param-reassign modules = [[null, modules, ""]]; } var alreadyImportedModules = {}; if (dedupe) { for (var i = 0; i < this.length; i++) { // eslint-disable-next-line prefer-destructuring var id = this[i][0]; if (id != null) { alreadyImportedModules[id] = true; } } } for (var _i = 0; _i < modules.length; _i++) { var item = [].concat(modules[_i]); if (dedupe && alreadyImportedModules[item[0]]) { // eslint-disable-next-line no-continue continue; } if (mediaQuery) { if (!item[2]) { item[2] = mediaQuery; } else { item[2] = "".concat(mediaQuery, " and ").concat(item[2]); } } list.push(item); } }; return list; }; /***/ }), /***/ 379: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { var isOldIE = function isOldIE() { var memo; return function memorize() { if (typeof memo === 'undefined') { // Test for IE <= 9 as proposed by Browserhacks // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805 // Tests for existence of standard globals is to allow style-loader // to operate correctly into non-standard environments // @see https://github.com/webpack-contrib/style-loader/issues/177 memo = Boolean(window && document && document.all && !window.atob); } return memo; }; }(); var getTarget = function getTarget() { var memo = {}; return function memorize(target) { if (typeof memo[target] === 'undefined') { var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) { try { // This will throw an exception if access to iframe is blocked // due to cross-origin restrictions styleTarget = styleTarget.contentDocument.head; } catch (e) { // istanbul ignore next styleTarget = null; } } memo[target] = styleTarget; } return memo[target]; }; }(); var stylesInDom = []; function getIndexByIdentifier(identifier) { var result = -1; for (var i = 0; i < stylesInDom.length; i++) { if (stylesInDom[i].identifier === identifier) { result = i; break; } } return result; } function modulesToDom(list, options) { var idCountMap = {}; var identifiers = []; for (var i = 0; i < list.length; i++) { var item = list[i]; var id = options.base ? item[0] + options.base : item[0]; var count = idCountMap[id] || 0; var identifier = "".concat(id, " ").concat(count); idCountMap[id] = count + 1; var index = getIndexByIdentifier(identifier); var obj = { css: item[1], media: item[2], sourceMap: item[3] }; if (index !== -1) { stylesInDom[index].references++; stylesInDom[index].updater(obj); } else { stylesInDom.push({ identifier: identifier, updater: addStyle(obj, options), references: 1 }); } identifiers.push(identifier); } return identifiers; } function insertStyleElement(options) { var style = document.createElement('style'); var attributes = options.attributes || {}; if (typeof attributes.nonce === 'undefined') { var nonce = true ? __webpack_require__.nc : 0; if (nonce) { attributes.nonce = nonce; } } Object.keys(attributes).forEach(function (key) { style.setAttribute(key, attributes[key]); }); if (typeof options.insert === 'function') { options.insert(style); } else { var target = getTarget(options.insert || 'head'); if (!target) { throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid."); } target.appendChild(style); } return style; } function removeStyleElement(style) { // istanbul ignore if if (style.parentNode === null) { return false; } style.parentNode.removeChild(style); } /* istanbul ignore next */ var replaceText = function replaceText() { var textStore = []; return function replace(index, replacement) { textStore[index] = replacement; return textStore.filter(Boolean).join('\n'); }; }(); function applyToSingletonTag(style, index, remove, obj) { var css = remove ? '' : obj.media ? "@media ".concat(obj.media, " {").concat(obj.css, "}") : obj.css; // For old IE /* istanbul ignore if */ if (style.styleSheet) { style.styleSheet.cssText = replaceText(index, css); } else { var cssNode = document.createTextNode(css); var childNodes = style.childNodes; if (childNodes[index]) { style.removeChild(childNodes[index]); } if (childNodes.length) { style.insertBefore(cssNode, childNodes[index]); } else { style.appendChild(cssNode); } } } function applyToTag(style, options, obj) { var css = obj.css; var media = obj.media; var sourceMap = obj.sourceMap; if (media) { style.setAttribute('media', media); } else { style.removeAttribute('media'); } if (sourceMap && typeof btoa !== 'undefined') { css += "\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), " */"); } // For old IE /* istanbul ignore if */ if (style.styleSheet) { style.styleSheet.cssText = css; } else { while (style.firstChild) { style.removeChild(style.firstChild); } style.appendChild(document.createTextNode(css)); } } var singleton = null; var singletonCounter = 0; function addStyle(obj, options) { var style; var update; var remove; if (options.singleton) { var styleIndex = singletonCounter++; style = singleton || (singleton = insertStyleElement(options)); update = applyToSingletonTag.bind(null, style, styleIndex, false); remove = applyToSingletonTag.bind(null, style, styleIndex, true); } else { style = insertStyleElement(options); update = applyToTag.bind(null, style, options); remove = function remove() { removeStyleElement(style); }; } update(obj); return function updateStyle(newObj) { if (newObj) { if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) { return; } update(obj = newObj); } else { remove(); } }; } module.exports = function (list, options) { options = options || {}; // Force single-tag solution on IE6-9, which has a hard limit on the # of <style> // tags it will allow on a page if (!options.singleton && typeof options.singleton !== 'boolean') { options.singleton = isOldIE(); } list = list || []; var lastIdentifiers = modulesToDom(list, options); return function update(newList) { newList = newList || []; if (Object.prototype.toString.call(newList) !== '[object Array]') { return; } for (var i = 0; i < lastIdentifiers.length; i++) { var identifier = lastIdentifiers[i]; var index = getIndexByIdentifier(identifier); stylesInDom[index].references--; } var newLastIdentifiers = modulesToDom(newList, options); for (var _i = 0; _i < lastIdentifiers.length; _i++) { var _identifier = lastIdentifiers[_i]; var _index = getIndexByIdentifier(_identifier); if (stylesInDom[_index].references === 0) { stylesInDom[_index].updater(); stylesInDom.splice(_index, 1); } } lastIdentifiers = newLastIdentifiers; }; }; /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(__webpack_module_cache__[moduleId]) { /******/ return __webpack_module_cache__[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ id: moduleId, /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ /******/ (() => { /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = (module) => { /******/ var getter = module && module.__esModule ? /******/ () => (module['default']) : /******/ () => (module); /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. (() => { // EXTERNAL MODULE: ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js var injectStylesIntoStyleTag = __webpack_require__(379); var injectStylesIntoStyleTag_default = /*#__PURE__*/__webpack_require__.n(injectStylesIntoStyleTag); // EXTERNAL MODULE: ./node_modules/css-loader/dist/cjs.js!./src/style.css var style = __webpack_require__(426); ;// CONCATENATED MODULE: ./src/style.css var options = {}; options.insert = "head"; options.singleton = false; var update = injectStylesIntoStyleTag_default()(style/* default */.Z, options); /* harmony default export */ const src_style = (style/* default.locals */.Z.locals || {}); ;// CONCATENATED MODULE: ./src/lib/dom-util.ts var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; function sleep(time) { return new Promise(resolve => { setTimeout(resolve, time); }); } function asyncQuerySelector(selectors) { return __awaiter(this, void 0, void 0, function* () { while (true) { const result = document.querySelector(selectors); if (result) return result; yield sleep(200); } }); } function waitForVueJsNextTick() { return new Promise(resolve => { Vue.nextTick(resolve); }); } ;// CONCATENATED MODULE: ./src/lib/general-util.ts function observeProperties(obj, propertyNames, callback, interval = 100) { function getValues() { return propertyNames.map(key => obj[key]); } function arrayEquals(a, b) { if (a.length !== b.length) return false; for (let i = 0, imax = a.length; i < imax; ++i) { if (a[i] !== b[i]) return false; } return true; } let previousValue = getValues(); setInterval(() => { const currentValue = getValues(); if (!arrayEquals(currentValue, previousValue)) { callback(); previousValue = currentValue; } }, interval); } ;// CONCATENATED MODULE: ./src/feature/text-to-ordering-target.ts function textToNumber(text) { let value = NaN; if (!text.match(/^,|,$|,,|\..*,|[eE].*,|,.*[eE]/)) { value = Number(text.replace(/,/g, "")); } if (isNaN(value)) { throw new Error(`Cannot convert '${text}' to a number.`); } return value; } function mmssToSeconds(text) { const parts = text.split(":").map(Number); if (parts.length !== 2 || !isFinite(parts[1]) || parts[1] < 0 || parts[1] >= 60 || !isFinite(parts[0]) || parts[0] % 1 !== 0) { throw new Error(`Cannot interpret '${text} as a time'`); } return parts[0] * 60 + parts[1]; } /** * @returns a value treated as a first entry in the default compareFn */ function veryFirstStandingsEntry(desc) { return { Rank: desc ? Infinity : -Infinity, Rating: desc ? -Infinity : Infinity, OldRating: desc ? -Infinity : Infinity, TotalResult: { Count: 1, Score: desc ? -Infinity : Infinity, Elapsed: desc ? Infinity : -Infinity, }, TaskResults: {}, }; } /** * @returns a value treated as a first entry in the default compareFn */ function veryFirstResultsEntry(desc) { return { Rank: desc ? Infinity : -Infinity, Place: desc ? Infinity : -Infinity, Performance: desc ? -Infinity : Infinity, OldRating: desc ? -Infinity : Infinity, Difference: desc ? -Infinity : Infinity, NewRating: desc ? -Infinity : Infinity, Rating: desc ? -Infinity : Infinity, }; } var TextToOrderingTarget; (function (TextToOrderingTarget) { let Standings; (function (Standings) { function numeric(key) { return function (text, desc) { const res = veryFirstStandingsEntry(desc); res[key] = textToNumber(text); return res; }; } Standings.numeric = numeric; /** * @param taskAlphabet Set null for the total score */ function score(taskAlphabet) { return function (text, desc, showInLogScale, taskInfo) { // set default value let elapsed = desc ? -Infinity : Infinity; // most bottom let point = 0; if (taskAlphabet !== null && taskAlphabet in taskInfo) { point = taskInfo[taskAlphabet].maximumScore; } else { // sum of all tasks point for (const alphabet in taskInfo) { point += taskInfo[alphabet].maximumScore; } } const parts = text.split(/\s/).filter(s => !!s); // read a time try { elapsed = mmssToSeconds(parts[parts.length - 1]) * 1e9; parts.pop(); } catch (_a) { } // read a point if (parts.length === 1) { point = 0; let pointText = parts[0]; try { point = textToNumber(pointText); if (showInLogScale) { point = 100 * Math.exp(point * LOG_BASE); } else { point *= 100; } } catch (e) { if (taskAlphabet === null) { // convert task alphabets to point function testTaskExistance(alphabet) { if (!(alphabet in taskInfo)) { throw new Error(`Task '${alphabet}' does not exist`); } } function addTaskPoint(alphabet) { testTaskExistance(alphabet); point += taskInfo[alphabet].maximumScore; } pointText = pointText.toUpperCase(); if (pointText[0] === "-") { const firstTaskAlphabet = Object.keys(taskInfo).sort()[0]; pointText = firstTaskAlphabet + pointText; } if (pointText[pointText.length - 1] === "-") { const lastTaskAlphabet = Object.keys(taskInfo).sort((a, b) => a < b ? 1 : a > b ? -1 : 0)[0]; pointText += lastTaskAlphabet; } for (let i = 0, imax = pointText.length; i < imax; ++i) { if (pointText[i + 1] === "-") { testTaskExistance(pointText[i]); testTaskExistance(pointText[i + 2]); for (let j = pointText.charCodeAt(i), jmax = pointText.charCodeAt(i + 2); j <= jmax; ++j) { addTaskPoint(String.fromCharCode(j)); } i += 2; } else { addTaskPoint(pointText[i]); } } } else { throw e; } } } else if (parts.length >= 2) { throw new Error(`'${text}' is not a score specifier (format: '[point] [time]')`); } const res = veryFirstStandingsEntry(desc); if (taskAlphabet === null) { res.TotalResult = { Count: 1, Score: point, Elapsed: elapsed, }; } else { res.TaskResults[taskInfo[taskAlphabet].screenName] = { Count: 1, Score: point, Elapsed: elapsed, }; } return res; }; } Standings.score = score; })(Standings = TextToOrderingTarget.Standings || (TextToOrderingTarget.Standings = {})); ; let Results; (function (Results) { function numeric(key) { return function (text, desc) { const res = veryFirstResultsEntry(desc); res[key] = textToNumber(text); return res; }; } Results.numeric = numeric; })(Results = TextToOrderingTarget.Results || (TextToOrderingTarget.Results = {})); ; })(TextToOrderingTarget || (TextToOrderingTarget = {})); ;// CONCATENATED MODULE: ./src/feature/pager/base.ts class Pager { constructor(paginationFn, orderFn) { this.paginationFn = paginationFn; this.orderFn = orderFn; } convertTargetText(fn, ...args) { try { return fn(...args); } catch (e) { throw new TargetTextConvertionError(e); } } } class TargetTextConvertionError extends Error { } ;// CONCATENATED MODULE: ./src/lib/math-util.ts function binarySearch(array, compareFn, target) { const test = arguments.length >= 3 ? (n) => compareFn(array[n], target) >= 0 : (n) => compareFn(array[n]); let low = 0, high = array.length; if (test(0)) return 0; while (high - low > 1) { const mid = (high + low) >> 1; if (test(mid)) { high = mid; } else { low = mid; } } return high; } function linearPrediction(x1, y1, x2, y2, x) { return y1 + (y2 - y1) * (x - x1) / (x2 - x1); } ;// CONCATENATED MODULE: ./src/lib/atcoder/info-reader.ts function readTaskScore(pageSource) { const match = pageSource.match(/(?:配点|Score).*<var>(\d+)<\/var>/); if (match) { const score = Number(match[1]); if (!isNaN(score)) { return score; } } throw new Error("Cannot read the score point"); } function readRatedRange(pageSource) { const match = pageSource.match(/>[\s\r\n]*(?:Rated対象|Rated Range)[\s\r\n]*:([^<>]*)</); if (match) { const text = match[1].replace(/[\s\r\n]/g, "").toLowerCase(); if (text === "-") { return [-Infinity, -Infinity]; } else if (text === "all") { return [-Infinity, Infinity]; } const parts = text.split(/-|~/); if (parts.length === 2) { const parsed = [ parts[0] === "" ? -Infinity : Number(parts[0]), parts[1] === "" ? Infinity : Number(parts[1]) ]; if (!isNaN(parsed[0]) && !isNaN(parsed[1])) { return parsed; } } } throw new Error("Cannot read the rated range"); } ;// CONCATENATED MODULE: ./src/lib/atcoder/time.ts function internalTimeToJsDate(internalTime) { return internalTime.toDate(); } ;// CONCATENATED MODULE: ./src/lib/net-util.ts var net_util_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; class FetchResponseError extends Error { constructor(res) { super(); this.res = res; } } function fetchText(input, init) { return net_util_awaiter(this, void 0, void 0, function* () { const res = yield fetch(input, init); if (res.status !== 200) { throw new FetchResponseError(res); } return yield res.text(); }); } ;// CONCATENATED MODULE: ./src/feature/get-task-info.ts var get_task_info_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; let cache = null; let previousStandings = null; let maximumScoreRecord = {}; function getAndRecordMaximumScore(taskAlphabet, taskScreenName) { return get_task_info_awaiter(this, void 0, void 0, function* () { maximumScoreRecord[taskAlphabet] = null; const url = location.href.replace(/(?<=\/contests\/[^\/]*\/).*$/, "tasks/" + taskScreenName); try { const score = readTaskScore(yield fetchText(url)) * 100; maximumScoreRecord[taskAlphabet] = score; if (cache) { cache[taskAlphabet].maximumScore = score; } } catch (e) { console.error(`Cannot get the score point from ${url}`); } }); } let contestStartTimerEnabled = false; function generateTaskInfo(standings) { const started = contestIsStarted(); if (!started) { if (!contestStartTimerEnabled) { contestStartTimerEnabled = true; const timerId = setInterval(() => { if (contestIsStarted()) { for (const task of standings.TaskInfo) { getAndRecordMaximumScore(task.Assignment, task.TaskScreenName); } clearInterval(timerId); } }, 1000); } } const result = {}; for (const info of standings.TaskInfo) { const alphabet = info.Assignment; const screenName = info.TaskScreenName; let maximumScore = 0; if (started) { if (alphabet in maximumScoreRecord && maximumScoreRecord[alphabet] !== null) { maximumScore = maximumScoreRecord[alphabet]; } else { if (!(alphabet in maximumScoreRecord)) { // Do not wait (request only) getAndRecordMaximumScore(alphabet, screenName); } for (const entry of standings.StandingsData) { const taskResults = entry.TaskResults; if (screenName in taskResults) { maximumScore = Math.max(maximumScore, taskResults[screenName].Score); } } } } result[alphabet] = { screenName, maximumScore }; } return result; } function getTaskInfo() { const currentStandings = vueStandings.standings; // Check if standings has been updated if (cache && currentStandings === previousStandings) return cache; previousStandings = currentStandings; return cache = generateTaskInfo(currentStandings); } ; function contestIsStarted() { return internalTimeToJsDate(getServerTime()).getTime() >= internalTimeToJsDate(startTime).getTime(); } ;// CONCATENATED MODULE: ./src/feature/pager/standings-order.ts var standings_order_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; class StandingsOrderPager extends Pager { constructor(paginationFn, orderFn, orderBy, textToOrderingTarget) { super(paginationFn, orderFn); this.paginationFn = paginationFn; this.orderFn = orderFn; this.orderBy = orderBy; this.textToOrderingTarget = textToOrderingTarget; } exec(text) { return standings_order_awaiter(this, void 0, void 0, function* () { const target = this.convertTargetText(this.textToOrderingTarget, text, vueStandings.desc, vueStandings.showInLogScale, getTaskInfo()); this.orderFn(this.orderBy); // Do not wait for DOM updated const array = vueStandings.orderedStandings; if (array.length === 0) return; const index = Math.min(binarySearch(array, vueStandings.comp, target), array.length - 1); yield this.paginationFn(Math.floor(index / vueStandings.perPage) + 1); }); } } class TaskInfo { } ;// CONCATENATED MODULE: ./src/feature/pager/results-order.ts var results_order_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; class ResultsOrderPager extends Pager { constructor(paginationFn, orderFn, orderBy, textToOrderingTarget) { super(paginationFn, orderFn); this.paginationFn = paginationFn; this.orderFn = orderFn; this.orderBy = orderBy; this.textToOrderingTarget = textToOrderingTarget; } exec(text) { return results_order_awaiter(this, void 0, void 0, function* () { const target = this.convertTargetText(this.textToOrderingTarget, text, vueResults.desc); this.orderFn(this.orderBy); // Do not wait for DOM updated const array = vueResults.orderedResults; if (array.length === 0) return; const index = Math.min(binarySearch(array, vueResults.comp, target), array.length - 1); yield this.paginationFn(Math.floor(index / vueResults.perPage) + 1); }); } } ;// CONCATENATED MODULE: ./src/feature/rank-to-rated-rank.ts var rank_to_rated_rank_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; let rank_to_rated_rank_cache = null; let rank_to_rated_rank_previousStandings = null; function getRankToRatedRankMap() { const currentStandings = vueStandings.standings; // Check if standings has been updated if (rank_to_rated_rank_cache && currentStandings === rank_to_rated_rank_previousStandings) return rank_to_rated_rank_cache; rank_to_rated_rank_previousStandings = currentStandings; return rank_to_rated_rank_cache = generateRankToRatedRankMap(currentStandings); } function generateRankToRatedRankMap(standings) { const data = standings.StandingsData; const res0 = calculateRatedRanks(data, e => e.IsRated && e.TotalResult.Count > 0); if (res0.ratedNum === 0 && ratedRange !== null) { const res1 = calculateRatedRanks(data, e => ratedRange[0] <= e.OldRating && e.OldRating <= ratedRange[1] && e.TotalResult.Count > 0); return res1.map; } else { return res0.map; } } function calculateRatedRanks(data, ratedFn) { const size = data.length; const result = Array(size); let ratedRank = 0; let ratedNumOfCurrentRank = 0; let unrateds = []; let _ratedAdded = 0; for (let i = 0; i < size; ++i) { const rank = data[i].Rank; if (ratedFn(data[i])) { ratedNumOfCurrentRank += 1; } else { unrateds.push(rank); } if (i === size - 1 || data[i + 1].Rank !== rank) { if (i === size - 1 && ratedNumOfCurrentRank === 0) { ratedNumOfCurrentRank = 1; _ratedAdded = 1; } if (ratedNumOfCurrentRank > 0) { result[rank] = ((ratedRank + 1) + (ratedRank + ratedNumOfCurrentRank)) / 2; const unratedsNum = unrateds.filter(r => r !== rank).length; function unratedSubRankToRatedRank(subRank) { return ratedRank; // return ratedRank + subRank / (unratedsNum + 1); } let unratedSubRank = 0; let unratedNumOfCurrentSubRank = 0; for (let j = 0; j < unratedsNum; ++j) { const rank = unrateds[j]; unratedNumOfCurrentSubRank += 1; if (j === unratedsNum - 1 || unrateds[j + 1] !== rank) { const subRank = ((unratedSubRank + 1) + (unratedSubRank + unratedNumOfCurrentSubRank)) / 2; result[rank] = unratedSubRankToRatedRank(subRank); unratedSubRank += unratedNumOfCurrentSubRank; unratedNumOfCurrentSubRank = 0; } } unrateds = []; ratedRank += ratedNumOfCurrentRank; ratedNumOfCurrentRank = 0; } } } return { map: result, ratedNum: ratedRank - _ratedAdded }; } let ratedRange = null; (() => rank_to_rated_rank_awaiter(void 0, void 0, void 0, function* () { const contestUrl = location.href.replace(/(?<=\/contests\/[^\/]+)\/.*$/g, ""); try { ratedRange = readRatedRange(yield fetchText(contestUrl)); } catch (e) { console.error(`Cannot get the rated range from ${contestUrl}`); } }))(); ;// CONCATENATED MODULE: ./src/feature/pager/ac-predictor.ts var ac_predictor_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; // Get ac-predictor's internal function let predictor_onRankInput = null; let predictor_onPerfInput = null; const addEventListener_raw = HTMLInputElement.prototype.addEventListener; HTMLInputElement.prototype.addEventListener = function (type, fn, ...args) { if (type === "keyup") { if (this.id === "predictor-input-rank") { predictor_onRankInput = fn; } else if (this.id === "predictor-input-perf") { predictor_onPerfInput = fn; } if (predictor_onRankInput && predictor_onPerfInput) { HTMLInputElement.prototype.addEventListener = addEventListener_raw; } } addEventListener_raw.call(this, type, fn, ...args); }; class AcPredictorPager extends Pager { constructor(paginationFn, orderFn, headerRow, beforePaginationFn) { super(paginationFn, orderFn); this.paginationFn = paginationFn; this.orderFn = orderFn; this.headerRow = headerRow; this.beforePaginationFn = beforePaginationFn; } exec(text) { return ac_predictor_awaiter(this, void 0, void 0, function* () { const target = this.convertTargetText(textToNumber, text); yield this.orderFn("rank"); if (predictor_onRankInput && predictor_onPerfInput) { yield this.paginateBasedOnPredictor(target); } else { yield this.paginateBasedOnDOM(target); } }); } paginateBasedOnDOM(target) { return ac_predictor_awaiter(this, void 0, void 0, function* () { if (vueStandings.pages === 0) return; const desc = vueStandings.desc; if (!desc) target *= -1; let columnNumber = -1; this.headerRow.querySelectorAll("th").forEach((th, i) => { if (th.textContent.replace(/\s/g, "") === "perf") { columnNumber = i; } }); if (columnNumber < 0) throw new Error('Cannot find perf column'); const tbody = this.headerRow.parentElement.parentElement.querySelector("tbody"); // Search page binarily let low = null; let high = null; while (true) { let [v0, v1] = this.readCurrentPagePerf(tbody, columnNumber); if (!desc) { v0 *= -1; v1 *= -1; } if (v0 < target && target <= v1) { break; } else if (target <= v0) { // too high if (vueStandings.page === 1) break; high = { page: vueStandings.page, value: (v0 + v1) / 2 }; } else { // too low if (vueStandings.page === vueStandings.pages) break; low = { page: vueStandings.page, value: (v0 + v1) / 2 }; } let nextPage; let endNext = false; if (high && low) { if (high.page - low.page <= 1) { // goal nextPage = high.page; endNext = true; } else if ( /* v0 !== v1 */false) {} else { // Use midpoint nextPage = Math.ceil((high.page + low.page) / 2); } if (nextPage >= high.page) { nextPage = high.page - 1; } else if (nextPage <= low.page) { nextPage = low.page + 1; } } else if (high) { nextPage = 1; } else if (low) { nextPage = vueStandings.pages; } yield this.paginationFn(nextPage); if (endNext) break; } }); } readPerfFromTableCell(cell) { if (!cell) return 0; const text = cell.textContent.replace(/\s/g, ""); const value = Number(text); return isNaN(value) ? 0 : value; } readCurrentPagePerf(tbody, perfColumnIndex) { const rows = []; let infoRowIndex = -1; let warningRowIndex = -1; tbody.childNodes.forEach(node => { if (node instanceof HTMLTableRowElement && !node.classList.contains("standings-fa") && !node.classList.contains("standings-statistics")) { rows.push(node); if (node.classList.contains("info")) infoRowIndex = rows.length - 1; if (node.classList.contains("warning")) warningRowIndex = rows.length - 1; } }); if (rows.length > vueStandings.perPage || vueStandings.page === vueStandings.pages) { if (infoRowIndex < 0 && warningRowIndex >= 0) { rows.splice(warningRowIndex, 1); } else if (infoRowIndex >= 0) { rows.splice(infoRowIndex, 1); } } return [rows[0], rows[rows.length - 1]].map(row => this.readPerfFromTableCell(row.children[perfColumnIndex])); } paginateBasedOnPredictor(target) { return ac_predictor_awaiter(this, void 0, void 0, function* () { const standings = vueStandings.orderedStandings; if (standings.length === 0) return; const desc = vueStandings.desc; const ratedRankMap = getRankToRatedRankMap(); const maxPerf = this.rankToPerf(1); const index = binarySearch(standings, entry => { const ratedRank = ratedRankMap[entry.EntireRank]; const perf = entry.TotalResult.Count === 0 ? -Infinity : Math.round(this.positivizeRating(Math.min(this.rankToPerf(ratedRank), maxPerf))); return desc ? (perf >= target) : (perf <= target); }); yield this.paginationFn(Math.floor(index / vueStandings.perPage) + 1); }); } rankToPerf(rank) { if (this.beforePaginationFn) { this.beforePaginationFn(); } const predictorElements = [ "predictor-input-rank", "predictor-input-perf", "predictor-input-rate", ].map(s => this.headerRow.ownerDocument.getElementById(s)); const temp = predictorElements.map(e => e.value); predictorElements[0].value = rank.toString(); predictor_onRankInput(); const result = Number(predictorElements[1].value); temp.forEach((v, i) => { predictorElements[i].value = v; }); return result; } perfToRank(perf) { if (this.beforePaginationFn) { this.beforePaginationFn(); } const predictorElements = [ "predictor-input-rank", "predictor-input-perf", "predictor-input-rate", ].map(s => this.headerRow.ownerDocument.getElementById(s)); const temp = predictorElements.map(e => e.value); predictorElements[1].value = perf.toString(); predictor_onPerfInput(); const result = Number(predictorElements[0].value); temp.forEach((v, i) => { predictorElements[i].value = v; }); return result; } positivizeRating(rating) { if (rating >= 400.0) return rating; return 400.0 * Math.exp((rating - 400.0) / 400.0); } unpositivizeRating(rating) { if (rating >= 400.0) return rating; return 400.0 + 400.0 * Math.log(rating / 400.0); } } ;// CONCATENATED MODULE: ./src/index.ts var src_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var CLASS_NAMES; (function (CLASS_NAMES) { CLASS_NAMES.input = "auto-pager-input"; CLASS_NAMES.active = "active"; CLASS_NAMES.error = "error"; })(CLASS_NAMES || (CLASS_NAMES = {})); (() => src_awaiter(void 0, void 0, void 0, function* () { function getPagerFromHeaderCell(headerCell) { const title = headerCell.textContent.replace(/\s/g, ""); if (tableType === "results") { let rule = null; if (title === "順位" || title === "Rank") { rule = { orderBy: "Place", converter: TextToOrderingTarget.Results.numeric("Place"), }; } if (title === "パフォーマンス" || title === "Performance") { rule = { orderBy: "Performance", converter: TextToOrderingTarget.Results.numeric("Performance"), }; } if (title === "旧Rating" || title === "OldRating") { rule = { orderBy: "OldRating", converter: TextToOrderingTarget.Results.numeric("OldRating"), }; } if (title === "差分" || title === "Diff") { rule = { orderBy: "Difference", converter: TextToOrderingTarget.Results.numeric("Difference"), }; } if (title === "新Rating" || title === "NewRating") { rule = { orderBy: "NewRating", converter: TextToOrderingTarget.Results.numeric("NewRating"), }; } if (rule) { return new ResultsOrderPager(goToPage, changeOrder, rule.orderBy, rule.converter); } } else { let rule = null; if (title === "順位" || title === "Rank") { rule = { orderBy: "rank", converter: TextToOrderingTarget.Standings.numeric("Rank"), }; } if (title === "得点" || title === "Score") { rule = { orderBy: "score", converter: TextToOrderingTarget.Standings.score(null), }; } const taskInfo = getTaskInfo(); if (title in taskInfo) { rule = { orderBy: "task-" + taskInfo[title].screenName, converter: TextToOrderingTarget.Standings.score(title), }; } if (rule) { return new StandingsOrderPager(goToPage, changeOrder, rule.orderBy, rule.converter); } if (title === "perf") { return new AcPredictorPager(goToPage, changeOrder, headerRow, () => { if (perfColumnInputElement) { keepPerfInputState(perfColumnInputElement); } }); } } return null; } function addInputElementToHeaderCell(headerCell) { const document = headerCell.ownerDocument; const div = document.createElement("div"); const input = document.createElement("input"); div.append(input); headerCell.append(div); input.classList.add(CLASS_NAMES.input); input.addEventListener("click", e => { e.stopPropagation(); }); return input; } function columnInit(headerCell) { const pager = getPagerFromHeaderCell(headerCell); if (pager === null) return; const input = addInputElementToHeaderCell(headerCell); input.addEventListener("input", () => src_awaiter(this, void 0, void 0, function* () { input.classList.remove(CLASS_NAMES.active); input.classList.remove(CLASS_NAMES.error); })); input.addEventListener("keypress", (e) => src_awaiter(this, void 0, void 0, function* () { if (e.code === "Enter") { yield execPagerFromInputElement(input, pager); } })); if (pager instanceof AcPredictorPager) { perfColumnInputElement = input; if (__perfInputState) { input.focus(); input.value = __perfInputState.value; input.selectionStart = __perfInputState.selectionStart; input.selectionEnd = __perfInputState.selectionEnd; input.classList.add(CLASS_NAMES.active); setTimeout(() => { __perfInputState = null; }, 0); } } } function execPagerFromInputElement(input, pager) { return src_awaiter(this, void 0, void 0, function* () { if (input.value.replace(/\s/g, "") === "") return; try { input.classList.add(CLASS_NAMES.active); yield pager.exec(input.value); } catch (e) { input.classList.remove(CLASS_NAMES.active); input.classList.add(CLASS_NAMES.error); if (e instanceof TargetTextConvertionError) { // TODO: Show error message // console.error(e); } else { throw e; } } }); } function goToPage(page) { return src_awaiter(this, void 0, void 0, function* () { if (page === vueObject.page) return; if (document.activeElement === perfColumnInputElement) { keepPerfInputState(perfColumnInputElement); } vueObject.page = page; vueObject.watchIndex = -1; yield waitForVueJsNextTick(); }); } function changeOrder(orderBy, desc = null) { return src_awaiter(this, void 0, void 0, function* () { if (orderBy === vueObject.orderBy) { if (desc === null || desc === vueObject.desc) return; } else { if (desc === null) desc = false; } if (document.activeElement === perfColumnInputElement) { keepPerfInputState(perfColumnInputElement); } vueObject.orderBy = orderBy; if (desc !== null) vueObject.desc = desc; yield waitForVueJsNextTick(); }); } let perfColumnInputElement = null; let __perfInputState = null; function keepPerfInputState(input) { __perfInputState = { value: input.value, selectionStart: input.selectionStart, selectionEnd: input.selectionEnd, }; } function resetPagers() { for (const input of headerRow.querySelectorAll("." + CLASS_NAMES.input)) { if (input.ownerDocument.activeElement === input) continue; input.classList.remove(CLASS_NAMES.active); input.classList.remove(CLASS_NAMES.error); input.value = ""; } } // main const headerRow = (yield asyncQuerySelector("#vue-standings thead tr, #vue-results thead tr")); const tableType = typeof vueStandings === "undefined" ? "results" : "standings"; const vueObject = tableType === "standings" ? vueStandings : vueResults; // Launch auto-pager for each column headerRow.querySelectorAll("th").forEach(columnInit); new MutationObserver(mutations => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node instanceof HTMLElement) columnInit(node); } } }).observe(headerRow, { childList: true }); // Detect pagination observeProperties(vueObject, ["page", "orderBy", "desc"], () => { resetPagers(); }); }))(); })(); /******/ })() ;