AtCoder Auto Pager

Support finding a page on AtCoder standings

  1. // ==UserScript==
  2. // @name AtCoder Auto Pager
  3. // @namespace https://github.com/mihatsu-s/
  4. // @version 1.1.0
  5. // @description Support finding a page on AtCoder standings
  6. // @author Mihatsu
  7. // @license MIT
  8. // @supportURL https://github.com/mihatsu-s/atcoder-auto-pager/issues
  9. // @match https://atcoder.jp/contests/*/standings
  10. // @match https://atcoder.jp/contests/*/standings?*
  11. // @match https://atcoder.jp/contests/*/standings/
  12. // @match https://atcoder.jp/contests/*/standings/?*
  13. // @match https://atcoder.jp/contests/*/standings/virtual
  14. // @match https://atcoder.jp/contests/*/standings/virtual?*
  15. // @match https://atcoder.jp/contests/*/standings/virtual/
  16. // @match https://atcoder.jp/contests/*/standings/virtual/?*
  17. // @match https://atcoder.jp/contests/*/results
  18. // @match https://atcoder.jp/contests/*/results?*
  19. // @match https://atcoder.jp/contests/*/results/
  20. // @match https://atcoder.jp/contests/*/results/?*
  21. // @exclude https://atcoder.jp/*/json
  22. // ==/UserScript==
  23.  
  24. /******/ (() => { // webpackBootstrap
  25. /******/ "use strict";
  26. /******/ var __webpack_modules__ = ({
  27.  
  28. /***/ 426:
  29. /***/ ((module, __webpack_exports__, __webpack_require__) => {
  30.  
  31. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  32. /* harmony export */ "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
  33. /* harmony export */ });
  34. /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(645);
  35. /* 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__);
  36. // Imports
  37.  
  38. var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0___default()(function(i){return i[1]});
  39. // Module
  40. ___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\n.auto-pager-input.watching {\n background-color: #cef;\n border-color: #9bd;\n color: #17f;\n}\n", ""]);
  41. // Exports
  42. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
  43.  
  44.  
  45. /***/ }),
  46.  
  47. /***/ 645:
  48. /***/ ((module) => {
  49.  
  50.  
  51.  
  52. /*
  53. MIT License http://www.opensource.org/licenses/mit-license.php
  54. Author Tobias Koppers @sokra
  55. */
  56. // css base code, injected by the css-loader
  57. // eslint-disable-next-line func-names
  58. module.exports = function (cssWithMappingToString) {
  59. var list = []; // return the list of modules as css string
  60.  
  61. list.toString = function toString() {
  62. return this.map(function (item) {
  63. var content = cssWithMappingToString(item);
  64.  
  65. if (item[2]) {
  66. return "@media ".concat(item[2], " {").concat(content, "}");
  67. }
  68.  
  69. return content;
  70. }).join("");
  71. }; // import a list of modules into the list
  72. // eslint-disable-next-line func-names
  73.  
  74.  
  75. list.i = function (modules, mediaQuery, dedupe) {
  76. if (typeof modules === "string") {
  77. // eslint-disable-next-line no-param-reassign
  78. modules = [[null, modules, ""]];
  79. }
  80.  
  81. var alreadyImportedModules = {};
  82.  
  83. if (dedupe) {
  84. for (var i = 0; i < this.length; i++) {
  85. // eslint-disable-next-line prefer-destructuring
  86. var id = this[i][0];
  87.  
  88. if (id != null) {
  89. alreadyImportedModules[id] = true;
  90. }
  91. }
  92. }
  93.  
  94. for (var _i = 0; _i < modules.length; _i++) {
  95. var item = [].concat(modules[_i]);
  96.  
  97. if (dedupe && alreadyImportedModules[item[0]]) {
  98. // eslint-disable-next-line no-continue
  99. continue;
  100. }
  101.  
  102. if (mediaQuery) {
  103. if (!item[2]) {
  104. item[2] = mediaQuery;
  105. } else {
  106. item[2] = "".concat(mediaQuery, " and ").concat(item[2]);
  107. }
  108. }
  109.  
  110. list.push(item);
  111. }
  112. };
  113.  
  114. return list;
  115. };
  116.  
  117. /***/ }),
  118.  
  119. /***/ 379:
  120. /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  121.  
  122.  
  123.  
  124. var isOldIE = function isOldIE() {
  125. var memo;
  126. return function memorize() {
  127. if (typeof memo === 'undefined') {
  128. // Test for IE <= 9 as proposed by Browserhacks
  129. // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
  130. // Tests for existence of standard globals is to allow style-loader
  131. // to operate correctly into non-standard environments
  132. // @see https://github.com/webpack-contrib/style-loader/issues/177
  133. memo = Boolean(window && document && document.all && !window.atob);
  134. }
  135.  
  136. return memo;
  137. };
  138. }();
  139.  
  140. var getTarget = function getTarget() {
  141. var memo = {};
  142. return function memorize(target) {
  143. if (typeof memo[target] === 'undefined') {
  144. var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself
  145.  
  146. if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {
  147. try {
  148. // This will throw an exception if access to iframe is blocked
  149. // due to cross-origin restrictions
  150. styleTarget = styleTarget.contentDocument.head;
  151. } catch (e) {
  152. // istanbul ignore next
  153. styleTarget = null;
  154. }
  155. }
  156.  
  157. memo[target] = styleTarget;
  158. }
  159.  
  160. return memo[target];
  161. };
  162. }();
  163.  
  164. var stylesInDom = [];
  165.  
  166. function getIndexByIdentifier(identifier) {
  167. var result = -1;
  168.  
  169. for (var i = 0; i < stylesInDom.length; i++) {
  170. if (stylesInDom[i].identifier === identifier) {
  171. result = i;
  172. break;
  173. }
  174. }
  175.  
  176. return result;
  177. }
  178.  
  179. function modulesToDom(list, options) {
  180. var idCountMap = {};
  181. var identifiers = [];
  182.  
  183. for (var i = 0; i < list.length; i++) {
  184. var item = list[i];
  185. var id = options.base ? item[0] + options.base : item[0];
  186. var count = idCountMap[id] || 0;
  187. var identifier = "".concat(id, " ").concat(count);
  188. idCountMap[id] = count + 1;
  189. var index = getIndexByIdentifier(identifier);
  190. var obj = {
  191. css: item[1],
  192. media: item[2],
  193. sourceMap: item[3]
  194. };
  195.  
  196. if (index !== -1) {
  197. stylesInDom[index].references++;
  198. stylesInDom[index].updater(obj);
  199. } else {
  200. stylesInDom.push({
  201. identifier: identifier,
  202. updater: addStyle(obj, options),
  203. references: 1
  204. });
  205. }
  206.  
  207. identifiers.push(identifier);
  208. }
  209.  
  210. return identifiers;
  211. }
  212.  
  213. function insertStyleElement(options) {
  214. var style = document.createElement('style');
  215. var attributes = options.attributes || {};
  216.  
  217. if (typeof attributes.nonce === 'undefined') {
  218. var nonce = true ? __webpack_require__.nc : 0;
  219.  
  220. if (nonce) {
  221. attributes.nonce = nonce;
  222. }
  223. }
  224.  
  225. Object.keys(attributes).forEach(function (key) {
  226. style.setAttribute(key, attributes[key]);
  227. });
  228.  
  229. if (typeof options.insert === 'function') {
  230. options.insert(style);
  231. } else {
  232. var target = getTarget(options.insert || 'head');
  233.  
  234. if (!target) {
  235. throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");
  236. }
  237.  
  238. target.appendChild(style);
  239. }
  240.  
  241. return style;
  242. }
  243.  
  244. function removeStyleElement(style) {
  245. // istanbul ignore if
  246. if (style.parentNode === null) {
  247. return false;
  248. }
  249.  
  250. style.parentNode.removeChild(style);
  251. }
  252. /* istanbul ignore next */
  253.  
  254.  
  255. var replaceText = function replaceText() {
  256. var textStore = [];
  257. return function replace(index, replacement) {
  258. textStore[index] = replacement;
  259. return textStore.filter(Boolean).join('\n');
  260. };
  261. }();
  262.  
  263. function applyToSingletonTag(style, index, remove, obj) {
  264. var css = remove ? '' : obj.media ? "@media ".concat(obj.media, " {").concat(obj.css, "}") : obj.css; // For old IE
  265.  
  266. /* istanbul ignore if */
  267.  
  268. if (style.styleSheet) {
  269. style.styleSheet.cssText = replaceText(index, css);
  270. } else {
  271. var cssNode = document.createTextNode(css);
  272. var childNodes = style.childNodes;
  273.  
  274. if (childNodes[index]) {
  275. style.removeChild(childNodes[index]);
  276. }
  277.  
  278. if (childNodes.length) {
  279. style.insertBefore(cssNode, childNodes[index]);
  280. } else {
  281. style.appendChild(cssNode);
  282. }
  283. }
  284. }
  285.  
  286. function applyToTag(style, options, obj) {
  287. var css = obj.css;
  288. var media = obj.media;
  289. var sourceMap = obj.sourceMap;
  290.  
  291. if (media) {
  292. style.setAttribute('media', media);
  293. } else {
  294. style.removeAttribute('media');
  295. }
  296.  
  297. if (sourceMap && typeof btoa !== 'undefined') {
  298. css += "\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), " */");
  299. } // For old IE
  300.  
  301. /* istanbul ignore if */
  302.  
  303.  
  304. if (style.styleSheet) {
  305. style.styleSheet.cssText = css;
  306. } else {
  307. while (style.firstChild) {
  308. style.removeChild(style.firstChild);
  309. }
  310.  
  311. style.appendChild(document.createTextNode(css));
  312. }
  313. }
  314.  
  315. var singleton = null;
  316. var singletonCounter = 0;
  317.  
  318. function addStyle(obj, options) {
  319. var style;
  320. var update;
  321. var remove;
  322.  
  323. if (options.singleton) {
  324. var styleIndex = singletonCounter++;
  325. style = singleton || (singleton = insertStyleElement(options));
  326. update = applyToSingletonTag.bind(null, style, styleIndex, false);
  327. remove = applyToSingletonTag.bind(null, style, styleIndex, true);
  328. } else {
  329. style = insertStyleElement(options);
  330. update = applyToTag.bind(null, style, options);
  331.  
  332. remove = function remove() {
  333. removeStyleElement(style);
  334. };
  335. }
  336.  
  337. update(obj);
  338. return function updateStyle(newObj) {
  339. if (newObj) {
  340. if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) {
  341. return;
  342. }
  343.  
  344. update(obj = newObj);
  345. } else {
  346. remove();
  347. }
  348. };
  349. }
  350.  
  351. module.exports = function (list, options) {
  352. options = options || {}; // Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
  353. // tags it will allow on a page
  354.  
  355. if (!options.singleton && typeof options.singleton !== 'boolean') {
  356. options.singleton = isOldIE();
  357. }
  358.  
  359. list = list || [];
  360. var lastIdentifiers = modulesToDom(list, options);
  361. return function update(newList) {
  362. newList = newList || [];
  363.  
  364. if (Object.prototype.toString.call(newList) !== '[object Array]') {
  365. return;
  366. }
  367.  
  368. for (var i = 0; i < lastIdentifiers.length; i++) {
  369. var identifier = lastIdentifiers[i];
  370. var index = getIndexByIdentifier(identifier);
  371. stylesInDom[index].references--;
  372. }
  373.  
  374. var newLastIdentifiers = modulesToDom(newList, options);
  375.  
  376. for (var _i = 0; _i < lastIdentifiers.length; _i++) {
  377. var _identifier = lastIdentifiers[_i];
  378.  
  379. var _index = getIndexByIdentifier(_identifier);
  380.  
  381. if (stylesInDom[_index].references === 0) {
  382. stylesInDom[_index].updater();
  383.  
  384. stylesInDom.splice(_index, 1);
  385. }
  386. }
  387.  
  388. lastIdentifiers = newLastIdentifiers;
  389. };
  390. };
  391.  
  392. /***/ })
  393.  
  394. /******/ });
  395. /************************************************************************/
  396. /******/ // The module cache
  397. /******/ var __webpack_module_cache__ = {};
  398. /******/
  399. /******/ // The require function
  400. /******/ function __webpack_require__(moduleId) {
  401. /******/ // Check if module is in cache
  402. /******/ if(__webpack_module_cache__[moduleId]) {
  403. /******/ return __webpack_module_cache__[moduleId].exports;
  404. /******/ }
  405. /******/ // Create a new module (and put it into the cache)
  406. /******/ var module = __webpack_module_cache__[moduleId] = {
  407. /******/ id: moduleId,
  408. /******/ // no module.loaded needed
  409. /******/ exports: {}
  410. /******/ };
  411. /******/
  412. /******/ // Execute the module function
  413. /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
  414. /******/
  415. /******/ // Return the exports of the module
  416. /******/ return module.exports;
  417. /******/ }
  418. /******/
  419. /************************************************************************/
  420. /******/ /* webpack/runtime/compat get default export */
  421. /******/ (() => {
  422. /******/ // getDefaultExport function for compatibility with non-harmony modules
  423. /******/ __webpack_require__.n = (module) => {
  424. /******/ var getter = module && module.__esModule ?
  425. /******/ () => (module['default']) :
  426. /******/ () => (module);
  427. /******/ __webpack_require__.d(getter, { a: getter });
  428. /******/ return getter;
  429. /******/ };
  430. /******/ })();
  431. /******/
  432. /******/ /* webpack/runtime/define property getters */
  433. /******/ (() => {
  434. /******/ // define getter functions for harmony exports
  435. /******/ __webpack_require__.d = (exports, definition) => {
  436. /******/ for(var key in definition) {
  437. /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
  438. /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
  439. /******/ }
  440. /******/ }
  441. /******/ };
  442. /******/ })();
  443. /******/
  444. /******/ /* webpack/runtime/hasOwnProperty shorthand */
  445. /******/ (() => {
  446. /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
  447. /******/ })();
  448. /******/
  449. /************************************************************************/
  450. var __webpack_exports__ = {};
  451. // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
  452. (() => {
  453.  
  454. // EXTERNAL MODULE: ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js
  455. var injectStylesIntoStyleTag = __webpack_require__(379);
  456. var injectStylesIntoStyleTag_default = /*#__PURE__*/__webpack_require__.n(injectStylesIntoStyleTag);
  457. // EXTERNAL MODULE: ./node_modules/css-loader/dist/cjs.js!./src/style.css
  458. var style = __webpack_require__(426);
  459. ;// CONCATENATED MODULE: ./src/style.css
  460.  
  461.  
  462. var options = {};
  463.  
  464. options.insert = "head";
  465. options.singleton = false;
  466.  
  467. var update = injectStylesIntoStyleTag_default()(style/* default */.Z, options);
  468.  
  469.  
  470.  
  471. /* harmony default export */ const src_style = (style/* default.locals */.Z.locals || {});
  472. ;// CONCATENATED MODULE: ./src/lib/dom-util.ts
  473. var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
  474. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  475. return new (P || (P = Promise))(function (resolve, reject) {
  476. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  477. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  478. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  479. step((generator = generator.apply(thisArg, _arguments || [])).next());
  480. });
  481. };
  482. function sleep(time) {
  483. return new Promise(resolve => {
  484. setTimeout(resolve, time);
  485. });
  486. }
  487. function asyncQuerySelector(selectors) {
  488. return __awaiter(this, void 0, void 0, function* () {
  489. while (true) {
  490. const result = document.querySelector(selectors);
  491. if (result)
  492. return result;
  493. yield sleep(200);
  494. }
  495. });
  496. }
  497. function waitForVueJsNextTick() {
  498. return new Promise(resolve => {
  499. Vue.nextTick(resolve);
  500. });
  501. }
  502.  
  503. ;// CONCATENATED MODULE: ./src/lib/general-util.ts
  504. function observeProperties(obj, propertyNames, callback, interval = 100) {
  505. function getValues() {
  506. return propertyNames.map(key => obj[key]);
  507. }
  508. function arrayEquals(a, b) {
  509. if (a.length !== b.length)
  510. return false;
  511. for (let i = 0, imax = a.length; i < imax; ++i) {
  512. if (a[i] !== b[i])
  513. return false;
  514. }
  515. return true;
  516. }
  517. let previousValue = getValues();
  518. setInterval(() => {
  519. const currentValue = getValues();
  520. if (!arrayEquals(currentValue, previousValue)) {
  521. callback();
  522. previousValue = currentValue;
  523. }
  524. }, interval);
  525. }
  526.  
  527. ;// CONCATENATED MODULE: ./src/feature/text-to-ordering-target.ts
  528. function textToNumber(text) {
  529. let value = NaN;
  530. if (!text.match(/^,|,$|,,|\..*,|[eE].*,|,.*[eE]/)) {
  531. value = Number(text.replace(/,/g, ""));
  532. }
  533. if (isNaN(value)) {
  534. throw new Error(`Cannot convert '${text}' to a number.`);
  535. }
  536. return value;
  537. }
  538. function mmssToSeconds(text) {
  539. const parts = text.split(":").map(Number);
  540. if (parts.length !== 2
  541. || !isFinite(parts[1]) || parts[1] < 0 || parts[1] >= 60
  542. || !isFinite(parts[0]) || parts[0] % 1 !== 0) {
  543. throw new Error(`Cannot interpret '${text} as a time'`);
  544. }
  545. return parts[0] * 60 + parts[1];
  546. }
  547. /**
  548. * @returns a value treated as a first entry in the default compareFn
  549. */
  550. function veryFirstStandingsEntry(desc) {
  551. return {
  552. Rank: desc ? Infinity : -Infinity,
  553. Rating: desc ? -Infinity : Infinity,
  554. OldRating: desc ? -Infinity : Infinity,
  555. TotalResult: {
  556. Count: 1,
  557. Score: desc ? -Infinity : Infinity,
  558. Elapsed: desc ? Infinity : -Infinity,
  559. },
  560. TaskResults: {},
  561. };
  562. }
  563. /**
  564. * @returns a value treated as a first entry in the default compareFn
  565. */
  566. function veryFirstResultsEntry(desc) {
  567. return {
  568. Rank: desc ? Infinity : -Infinity,
  569. Place: desc ? Infinity : -Infinity,
  570. Performance: desc ? -Infinity : Infinity,
  571. OldRating: desc ? -Infinity : Infinity,
  572. Difference: desc ? -Infinity : Infinity,
  573. NewRating: desc ? -Infinity : Infinity,
  574. Rating: desc ? -Infinity : Infinity,
  575. };
  576. }
  577. var TextToOrderingTarget;
  578. (function (TextToOrderingTarget) {
  579. let Standings;
  580. (function (Standings) {
  581. function numeric(key) {
  582. return function (text, desc) {
  583. const res = veryFirstStandingsEntry(desc);
  584. res[key] = textToNumber(text);
  585. return res;
  586. };
  587. }
  588. Standings.numeric = numeric;
  589. /**
  590. * @param taskAlphabet Set null for the total score
  591. */
  592. function score(taskAlphabet) {
  593. return function (text, desc, showInLogScale, taskInfo) {
  594. // set default value
  595. let elapsed = desc ? -Infinity : Infinity; // most bottom
  596. let point = 0;
  597. if (taskAlphabet !== null && taskAlphabet in taskInfo) {
  598. point = taskInfo[taskAlphabet].maximumScore;
  599. }
  600. else {
  601. // sum of all tasks point
  602. for (const alphabet in taskInfo) {
  603. point += taskInfo[alphabet].maximumScore;
  604. }
  605. }
  606. const parts = text.split(/\s/).filter(s => !!s);
  607. // read a time
  608. try {
  609. elapsed = mmssToSeconds(parts[parts.length - 1]) * 1e9;
  610. parts.pop();
  611. }
  612. catch (_a) { }
  613. // read a point
  614. if (parts.length === 1) {
  615. point = 0;
  616. let pointText = parts[0];
  617. try {
  618. point = textToNumber(pointText);
  619. if (showInLogScale) {
  620. point = 100 * Math.exp(point * LOG_BASE);
  621. }
  622. else {
  623. point *= 100;
  624. }
  625. }
  626. catch (e) {
  627. if (taskAlphabet === null) {
  628. // convert task alphabets to point
  629. function testTaskExistance(alphabet) {
  630. if (!(alphabet in taskInfo)) {
  631. throw new Error(`Task '${alphabet}' does not exist`);
  632. }
  633. }
  634. function addTaskPoint(alphabet) {
  635. testTaskExistance(alphabet);
  636. point += taskInfo[alphabet].maximumScore;
  637. }
  638. pointText = pointText.toUpperCase();
  639. if (pointText[0] === "-") {
  640. const firstTaskAlphabet = Object.keys(taskInfo).sort()[0];
  641. pointText = firstTaskAlphabet + pointText;
  642. }
  643. if (pointText[pointText.length - 1] === "-") {
  644. const lastTaskAlphabet = Object.keys(taskInfo).sort((a, b) => a < b ? 1 : a > b ? -1 : 0)[0];
  645. pointText += lastTaskAlphabet;
  646. }
  647. for (let i = 0, imax = pointText.length; i < imax; ++i) {
  648. if (pointText[i + 1] === "-") {
  649. testTaskExistance(pointText[i]);
  650. testTaskExistance(pointText[i + 2]);
  651. for (let j = pointText.charCodeAt(i), jmax = pointText.charCodeAt(i + 2); j <= jmax; ++j) {
  652. addTaskPoint(String.fromCharCode(j));
  653. }
  654. i += 2;
  655. }
  656. else {
  657. addTaskPoint(pointText[i]);
  658. }
  659. }
  660. }
  661. else {
  662. throw e;
  663. }
  664. }
  665. }
  666. else if (parts.length >= 2) {
  667. throw new Error(`'${text}' is not a score specifier (format: '[point] [time]')`);
  668. }
  669. const res = veryFirstStandingsEntry(desc);
  670. if (taskAlphabet === null) {
  671. res.TotalResult = {
  672. Count: 1,
  673. Score: point,
  674. Elapsed: elapsed,
  675. };
  676. }
  677. else {
  678. res.TaskResults[taskInfo[taskAlphabet].screenName] = {
  679. Count: 1,
  680. Score: point,
  681. Elapsed: elapsed,
  682. };
  683. }
  684. return res;
  685. };
  686. }
  687. Standings.score = score;
  688. })(Standings = TextToOrderingTarget.Standings || (TextToOrderingTarget.Standings = {}));
  689. ;
  690. let Results;
  691. (function (Results) {
  692. function numeric(key) {
  693. return function (text, desc) {
  694. const res = veryFirstResultsEntry(desc);
  695. res[key] = textToNumber(text);
  696. return res;
  697. };
  698. }
  699. Results.numeric = numeric;
  700. })(Results = TextToOrderingTarget.Results || (TextToOrderingTarget.Results = {}));
  701. ;
  702. })(TextToOrderingTarget || (TextToOrderingTarget = {}));
  703.  
  704. ;// CONCATENATED MODULE: ./src/feature/pager/base.ts
  705. class Pager {
  706. constructor(paginationFn, orderFn) {
  707. this.paginationFn = paginationFn;
  708. this.orderFn = orderFn;
  709. }
  710. convertTargetText(fn, ...args) {
  711. try {
  712. return fn(...args);
  713. }
  714. catch (e) {
  715. throw new TargetTextConvertionError(e);
  716. }
  717. }
  718. }
  719. class TargetTextConvertionError extends Error {
  720. }
  721.  
  722. ;// CONCATENATED MODULE: ./src/lib/math-util.ts
  723. function binarySearch(array, compareFn, target) {
  724. const test = arguments.length >= 3 ?
  725. (n) => compareFn(array[n], target) >= 0 :
  726. (n) => compareFn(array[n]);
  727. let low = 0, high = array.length;
  728. if (test(0))
  729. return 0;
  730. while (high - low > 1) {
  731. const mid = (high + low) >> 1;
  732. if (test(mid)) {
  733. high = mid;
  734. }
  735. else {
  736. low = mid;
  737. }
  738. }
  739. return high;
  740. }
  741. function linearPrediction(x1, y1, x2, y2, x) {
  742. return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
  743. }
  744.  
  745. ;// CONCATENATED MODULE: ./src/lib/atcoder/info-reader.ts
  746. function readTaskScore(pageSource) {
  747. const match = pageSource.match(/(?:配点|Score).*<var>(\d+)<\/var>/);
  748. if (match) {
  749. const score = Number(match[1]);
  750. if (!isNaN(score)) {
  751. return score;
  752. }
  753. }
  754. throw new Error("Cannot read the score point");
  755. }
  756. function readRatedRange(pageSource) {
  757. const match = pageSource.match(/>[\s\r\n]*(?:Rated対象|Rated Range)[\s\r\n]*:([^<>]*)</);
  758. if (match) {
  759. const text = match[1].replace(/[\s\r\n]/g, "").toLowerCase();
  760. if (text === "-") {
  761. return [-Infinity, -Infinity];
  762. }
  763. else if (text === "all") {
  764. return [-Infinity, Infinity];
  765. }
  766. const parts = text.split(/-|~/);
  767. if (parts.length === 2) {
  768. const parsed = [
  769. parts[0] === "" ? -Infinity : Number(parts[0]),
  770. parts[1] === "" ? Infinity : Number(parts[1])
  771. ];
  772. if (!isNaN(parsed[0]) && !isNaN(parsed[1])) {
  773. return parsed;
  774. }
  775. }
  776. }
  777. throw new Error("Cannot read the rated range");
  778. }
  779.  
  780. ;// CONCATENATED MODULE: ./src/lib/atcoder/time.ts
  781. function internalTimeToJsDate(internalTime) {
  782. return internalTime.toDate();
  783. }
  784.  
  785. ;// CONCATENATED MODULE: ./src/lib/net-util.ts
  786. var net_util_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
  787. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  788. return new (P || (P = Promise))(function (resolve, reject) {
  789. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  790. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  791. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  792. step((generator = generator.apply(thisArg, _arguments || [])).next());
  793. });
  794. };
  795. class FetchResponseError extends Error {
  796. constructor(res) {
  797. super();
  798. this.res = res;
  799. }
  800. }
  801. function fetchText(input, init) {
  802. return net_util_awaiter(this, void 0, void 0, function* () {
  803. const res = yield fetch(input, init);
  804. if (res.status !== 200) {
  805. throw new FetchResponseError(res);
  806. }
  807. return yield res.text();
  808. });
  809. }
  810.  
  811. ;// CONCATENATED MODULE: ./src/feature/get-task-info.ts
  812. var get_task_info_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
  813. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  814. return new (P || (P = Promise))(function (resolve, reject) {
  815. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  816. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  817. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  818. step((generator = generator.apply(thisArg, _arguments || [])).next());
  819. });
  820. };
  821.  
  822.  
  823.  
  824. let cache = null;
  825. let previousStandings = null;
  826. let maximumScoreRecord = {};
  827. function getAndRecordMaximumScore(taskAlphabet, taskScreenName) {
  828. return get_task_info_awaiter(this, void 0, void 0, function* () {
  829. maximumScoreRecord[taskAlphabet] = null;
  830. const url = location.href.replace(/(?<=\/contests\/[^\/]*\/).*$/, "tasks/" + taskScreenName);
  831. try {
  832. const score = readTaskScore(yield fetchText(url)) * 100;
  833. maximumScoreRecord[taskAlphabet] = score;
  834. if (cache) {
  835. cache[taskAlphabet].maximumScore = score;
  836. }
  837. }
  838. catch (e) {
  839. console.error(`Cannot get the score point from ${url}`);
  840. }
  841. });
  842. }
  843. let contestStartTimerEnabled = false;
  844. function generateTaskInfo(standings) {
  845. const started = contestIsStarted();
  846. if (!started) {
  847. if (!contestStartTimerEnabled) {
  848. contestStartTimerEnabled = true;
  849. const timerId = setInterval(() => {
  850. if (contestIsStarted()) {
  851. for (const task of standings.TaskInfo) {
  852. getAndRecordMaximumScore(task.Assignment, task.TaskScreenName);
  853. }
  854. clearInterval(timerId);
  855. }
  856. }, 1000);
  857. }
  858. }
  859. const result = {};
  860. for (const info of standings.TaskInfo) {
  861. const alphabet = info.Assignment;
  862. const screenName = info.TaskScreenName;
  863. let maximumScore = 0;
  864. if (started) {
  865. if (alphabet in maximumScoreRecord && maximumScoreRecord[alphabet] !== null) {
  866. maximumScore = maximumScoreRecord[alphabet];
  867. }
  868. else {
  869. if (!(alphabet in maximumScoreRecord)) {
  870. // Do not wait (request only)
  871. getAndRecordMaximumScore(alphabet, screenName);
  872. }
  873. for (const entry of standings.StandingsData) {
  874. const taskResults = entry.TaskResults;
  875. if (screenName in taskResults) {
  876. maximumScore = Math.max(maximumScore, taskResults[screenName].Score);
  877. }
  878. }
  879. }
  880. }
  881. result[alphabet] = { screenName, maximumScore };
  882. }
  883. return result;
  884. }
  885. function getTaskInfo() {
  886. const currentStandings = vueStandings.standings;
  887. // Check if standings has been updated
  888. if (cache && currentStandings === previousStandings)
  889. return cache;
  890. previousStandings = currentStandings;
  891. return cache = generateTaskInfo(currentStandings);
  892. }
  893. ;
  894. function contestIsStarted() {
  895. return internalTimeToJsDate(getServerTime()).getTime() >= internalTimeToJsDate(startTime).getTime();
  896. }
  897.  
  898. ;// CONCATENATED MODULE: ./src/feature/pager/standings-order.ts
  899. var standings_order_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
  900. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  901. return new (P || (P = Promise))(function (resolve, reject) {
  902. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  903. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  904. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  905. step((generator = generator.apply(thisArg, _arguments || [])).next());
  906. });
  907. };
  908.  
  909.  
  910.  
  911. class StandingsOrderPager extends Pager {
  912. constructor(paginationFn, orderFn, orderBy, textToOrderingTarget) {
  913. super(paginationFn, orderFn);
  914. this.paginationFn = paginationFn;
  915. this.orderFn = orderFn;
  916. this.orderBy = orderBy;
  917. this.textToOrderingTarget = textToOrderingTarget;
  918. }
  919. exec(text) {
  920. return standings_order_awaiter(this, void 0, void 0, function* () {
  921. const target = this.convertTargetText(this.textToOrderingTarget, text, vueStandings.desc, vueStandings.showInLogScale, getTaskInfo());
  922. this.orderFn(this.orderBy); // Do not wait for DOM updated
  923. const array = vueStandings.orderedStandings;
  924. if (array.length === 0)
  925. return;
  926. const index = Math.min(binarySearch(array, vueStandings.comp, target), array.length - 1);
  927. yield this.paginationFn(Math.floor(index / vueStandings.perPage) + 1);
  928. });
  929. }
  930. }
  931. class TaskInfo {
  932. }
  933.  
  934. ;// CONCATENATED MODULE: ./src/feature/pager/results-order.ts
  935. var results_order_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
  936. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  937. return new (P || (P = Promise))(function (resolve, reject) {
  938. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  939. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  940. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  941. step((generator = generator.apply(thisArg, _arguments || [])).next());
  942. });
  943. };
  944.  
  945.  
  946. class ResultsOrderPager extends Pager {
  947. constructor(paginationFn, orderFn, orderBy, textToOrderingTarget) {
  948. super(paginationFn, orderFn);
  949. this.paginationFn = paginationFn;
  950. this.orderFn = orderFn;
  951. this.orderBy = orderBy;
  952. this.textToOrderingTarget = textToOrderingTarget;
  953. }
  954. exec(text) {
  955. return results_order_awaiter(this, void 0, void 0, function* () {
  956. const target = this.convertTargetText(this.textToOrderingTarget, text, vueResults.desc);
  957. this.orderFn(this.orderBy); // Do not wait for DOM updated
  958. const array = vueResults.orderedResults;
  959. if (array.length === 0)
  960. return;
  961. const index = Math.min(binarySearch(array, vueResults.comp, target), array.length - 1);
  962. yield this.paginationFn(Math.floor(index / vueResults.perPage) + 1);
  963. });
  964. }
  965. }
  966.  
  967. ;// CONCATENATED MODULE: ./src/feature/rank-to-rated-rank.ts
  968. var rank_to_rated_rank_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
  969. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  970. return new (P || (P = Promise))(function (resolve, reject) {
  971. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  972. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  973. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  974. step((generator = generator.apply(thisArg, _arguments || [])).next());
  975. });
  976. };
  977.  
  978.  
  979. let rank_to_rated_rank_cache = null;
  980. let rank_to_rated_rank_previousStandings = null;
  981. function getRankToRatedRankMap() {
  982. const currentStandings = vueStandings.standings;
  983. // Check if standings has been updated
  984. if (rank_to_rated_rank_cache && currentStandings === rank_to_rated_rank_previousStandings)
  985. return rank_to_rated_rank_cache;
  986. rank_to_rated_rank_previousStandings = currentStandings;
  987. return rank_to_rated_rank_cache = generateRankToRatedRankMap(currentStandings);
  988. }
  989. function generateRankToRatedRankMap(standings) {
  990. const data = standings.StandingsData;
  991. const res0 = calculateRatedRanks(data, e => e.IsRated && e.TotalResult.Count > 0);
  992. if (res0.ratedNum === 0 && ratedRange !== null) {
  993. const res1 = calculateRatedRanks(data, e => ratedRange[0] <= e.OldRating && e.OldRating <= ratedRange[1] && e.TotalResult.Count > 0);
  994. return res1.map;
  995. }
  996. else {
  997. return res0.map;
  998. }
  999. }
  1000. function calculateRatedRanks(data, ratedFn) {
  1001. const size = data.length;
  1002. const result = Array(size);
  1003. let ratedRank = 0;
  1004. let ratedNumOfCurrentRank = 0;
  1005. let unrateds = [];
  1006. let _ratedAdded = 0;
  1007. for (let i = 0; i < size; ++i) {
  1008. const rank = data[i].Rank;
  1009. if (ratedFn(data[i])) {
  1010. ratedNumOfCurrentRank += 1;
  1011. }
  1012. else {
  1013. unrateds.push(rank);
  1014. }
  1015. if (i === size - 1 || data[i + 1].Rank !== rank) {
  1016. if (i === size - 1 && ratedNumOfCurrentRank === 0) {
  1017. ratedNumOfCurrentRank = 1;
  1018. _ratedAdded = 1;
  1019. }
  1020. if (ratedNumOfCurrentRank > 0) {
  1021. result[rank] = ((ratedRank + 1) + (ratedRank + ratedNumOfCurrentRank)) / 2;
  1022. const unratedsNum = unrateds.filter(r => r !== rank).length;
  1023. function unratedSubRankToRatedRank(subRank) {
  1024. return ratedRank;
  1025. // return ratedRank + subRank / (unratedsNum + 1);
  1026. }
  1027. let unratedSubRank = 0;
  1028. let unratedNumOfCurrentSubRank = 0;
  1029. for (let j = 0; j < unratedsNum; ++j) {
  1030. const rank = unrateds[j];
  1031. unratedNumOfCurrentSubRank += 1;
  1032. if (j === unratedsNum - 1 || unrateds[j + 1] !== rank) {
  1033. const subRank = ((unratedSubRank + 1) + (unratedSubRank + unratedNumOfCurrentSubRank)) / 2;
  1034. result[rank] = unratedSubRankToRatedRank(subRank);
  1035. unratedSubRank += unratedNumOfCurrentSubRank;
  1036. unratedNumOfCurrentSubRank = 0;
  1037. }
  1038. }
  1039. unrateds = [];
  1040. ratedRank += ratedNumOfCurrentRank;
  1041. ratedNumOfCurrentRank = 0;
  1042. }
  1043. }
  1044. }
  1045. return {
  1046. map: result,
  1047. ratedNum: ratedRank - _ratedAdded
  1048. };
  1049. }
  1050. let ratedRange = null;
  1051. (() => rank_to_rated_rank_awaiter(void 0, void 0, void 0, function* () {
  1052. const contestUrl = location.href.replace(/(?<=\/contests\/[^\/]+)\/.*$/g, "");
  1053. try {
  1054. ratedRange = readRatedRange(yield fetchText(contestUrl));
  1055. }
  1056. catch (e) {
  1057. console.error(`Cannot get the rated range from ${contestUrl}`);
  1058. }
  1059. }))();
  1060.  
  1061. ;// CONCATENATED MODULE: ./src/feature/pager/ac-predictor.ts
  1062. var ac_predictor_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
  1063. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  1064. return new (P || (P = Promise))(function (resolve, reject) {
  1065. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  1066. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  1067. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  1068. step((generator = generator.apply(thisArg, _arguments || [])).next());
  1069. });
  1070. };
  1071.  
  1072.  
  1073.  
  1074.  
  1075. // Get ac-predictor's internal function
  1076. let predictor_onRankInput = null;
  1077. let predictor_onPerfInput = null;
  1078. const addEventListener_raw = HTMLInputElement.prototype.addEventListener;
  1079. HTMLInputElement.prototype.addEventListener =
  1080. function (type, fn, ...args) {
  1081. if (type === "keyup") {
  1082. if (this.id === "predictor-input-rank") {
  1083. predictor_onRankInput = fn;
  1084. }
  1085. else if (this.id === "predictor-input-perf") {
  1086. predictor_onPerfInput = fn;
  1087. }
  1088. }
  1089. addEventListener_raw.call(this, type, fn, ...args);
  1090. };
  1091. class AcPredictorPager extends Pager {
  1092. constructor(paginationFn, orderFn, headerRow, beforePaginationFn) {
  1093. super(paginationFn, orderFn);
  1094. this.paginationFn = paginationFn;
  1095. this.orderFn = orderFn;
  1096. this.headerRow = headerRow;
  1097. this.beforePaginationFn = beforePaginationFn;
  1098. }
  1099. exec(text) {
  1100. return ac_predictor_awaiter(this, void 0, void 0, function* () {
  1101. const target = this.convertTargetText(textToNumber, text);
  1102. yield this.orderFn("rank");
  1103. if (predictor_onRankInput && predictor_onPerfInput) {
  1104. yield this.paginateBasedOnPredictor(target);
  1105. }
  1106. else {
  1107. yield this.paginateBasedOnDOM(target);
  1108. }
  1109. });
  1110. }
  1111. paginateBasedOnDOM(target) {
  1112. return ac_predictor_awaiter(this, void 0, void 0, function* () {
  1113. if (vueStandings.pages === 0)
  1114. return;
  1115. const desc = vueStandings.desc;
  1116. if (!desc)
  1117. target *= -1;
  1118. let columnNumber = -1;
  1119. this.headerRow.querySelectorAll("th").forEach((th, i) => {
  1120. if (th.textContent.replace(/\s/g, "") === "perf") {
  1121. columnNumber = i;
  1122. }
  1123. });
  1124. if (columnNumber < 0)
  1125. throw new Error('Cannot find perf column');
  1126. const tbody = this.headerRow.parentElement.parentElement.querySelector("tbody");
  1127. // Search page binarily
  1128. let low = null;
  1129. let high = null;
  1130. while (true) {
  1131. let [v0, v1] = this.readCurrentPagePerf(tbody, columnNumber);
  1132. if (!desc) {
  1133. v0 *= -1;
  1134. v1 *= -1;
  1135. }
  1136. if (v0 < target && target <= v1) {
  1137. break;
  1138. }
  1139. else if (target <= v0) {
  1140. // too high
  1141. if (vueStandings.page === 1)
  1142. break;
  1143. high = { page: vueStandings.page, value: (v0 + v1) / 2 };
  1144. }
  1145. else {
  1146. // too low
  1147. if (vueStandings.page === vueStandings.pages)
  1148. break;
  1149. low = { page: vueStandings.page, value: (v0 + v1) / 2 };
  1150. }
  1151. let nextPage;
  1152. let endNext = false;
  1153. if (high && low) {
  1154. if (high.page - low.page <= 1) {
  1155. // goal
  1156. nextPage = high.page;
  1157. endNext = true;
  1158. }
  1159. else if ( /* v0 !== v1 */false) {}
  1160. else {
  1161. // Use midpoint
  1162. nextPage = Math.ceil((high.page + low.page) / 2);
  1163. }
  1164. if (nextPage >= high.page) {
  1165. nextPage = high.page - 1;
  1166. }
  1167. else if (nextPage <= low.page) {
  1168. nextPage = low.page + 1;
  1169. }
  1170. }
  1171. else if (high) {
  1172. nextPage = 1;
  1173. }
  1174. else if (low) {
  1175. nextPage = vueStandings.pages;
  1176. }
  1177. yield this.paginationFn(nextPage);
  1178. if (endNext)
  1179. break;
  1180. }
  1181. });
  1182. }
  1183. readPerfFromTableCell(cell) {
  1184. if (!cell)
  1185. return 0;
  1186. const text = cell.textContent.replace(/\s/g, "");
  1187. const value = Number(text);
  1188. return isNaN(value) ? 0 : value;
  1189. }
  1190. readCurrentPagePerf(tbody, perfColumnIndex) {
  1191. const rows = [];
  1192. let infoRowIndex = -1;
  1193. let warningRowIndex = -1;
  1194. tbody.childNodes.forEach(node => {
  1195. if (node instanceof HTMLTableRowElement
  1196. && !node.classList.contains("standings-fa")
  1197. && !node.classList.contains("standings-statistics")) {
  1198. rows.push(node);
  1199. if (node.classList.contains("info"))
  1200. infoRowIndex = rows.length - 1;
  1201. if (node.classList.contains("warning"))
  1202. warningRowIndex = rows.length - 1;
  1203. }
  1204. });
  1205. if (rows.length > vueStandings.perPage || vueStandings.page === vueStandings.pages) {
  1206. if (infoRowIndex < 0 && warningRowIndex >= 0) {
  1207. rows.splice(warningRowIndex, 1);
  1208. }
  1209. else if (infoRowIndex >= 0) {
  1210. rows.splice(infoRowIndex, 1);
  1211. }
  1212. }
  1213. return [rows[0], rows[rows.length - 1]].map(row => this.readPerfFromTableCell(row.children[perfColumnIndex]));
  1214. }
  1215. paginateBasedOnPredictor(target) {
  1216. return ac_predictor_awaiter(this, void 0, void 0, function* () {
  1217. const standings = vueStandings.orderedStandings;
  1218. if (standings.length === 0)
  1219. return;
  1220. const desc = vueStandings.desc;
  1221. const ratedRankMap = getRankToRatedRankMap();
  1222. const maxPerf = this.rankToPerf(1);
  1223. const index = binarySearch(standings, entry => {
  1224. const ratedRank = ratedRankMap[entry.EntireRank];
  1225. const perf = entry.TotalResult.Count === 0
  1226. ? -Infinity
  1227. : Math.round(this.positivizeRating(Math.min(this.rankToPerf(ratedRank), maxPerf)));
  1228. return desc ? (perf >= target) : (perf <= target);
  1229. });
  1230. yield this.paginationFn(Math.floor(index / vueStandings.perPage) + 1);
  1231. });
  1232. }
  1233. rankToPerf(rank) {
  1234. if (this.beforePaginationFn) {
  1235. this.beforePaginationFn();
  1236. }
  1237. const predictorElements = [
  1238. "predictor-input-rank",
  1239. "predictor-input-perf",
  1240. "predictor-input-rate",
  1241. ].map(s => this.headerRow.ownerDocument.getElementById(s));
  1242. const temp = predictorElements.map(e => e.value);
  1243. predictorElements[0].value = rank.toString();
  1244. predictor_onRankInput();
  1245. const result = Number(predictorElements[1].value);
  1246. temp.forEach((v, i) => {
  1247. predictorElements[i].value = v;
  1248. });
  1249. return result;
  1250. }
  1251. perfToRank(perf) {
  1252. if (this.beforePaginationFn) {
  1253. this.beforePaginationFn();
  1254. }
  1255. const predictorElements = [
  1256. "predictor-input-rank",
  1257. "predictor-input-perf",
  1258. "predictor-input-rate",
  1259. ].map(s => this.headerRow.ownerDocument.getElementById(s));
  1260. const temp = predictorElements.map(e => e.value);
  1261. predictorElements[1].value = perf.toString();
  1262. predictor_onPerfInput();
  1263. const result = Number(predictorElements[0].value);
  1264. temp.forEach((v, i) => {
  1265. predictorElements[i].value = v;
  1266. });
  1267. return result;
  1268. }
  1269. positivizeRating(rating) {
  1270. if (rating >= 400.0)
  1271. return rating;
  1272. return 400.0 * Math.exp((rating - 400.0) / 400.0);
  1273. }
  1274. unpositivizeRating(rating) {
  1275. if (rating >= 400.0)
  1276. return rating;
  1277. return 400.0 + 400.0 * Math.log(rating / 400.0);
  1278. }
  1279. }
  1280.  
  1281. ;// CONCATENATED MODULE: ./src/index.ts
  1282. var src_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
  1283. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  1284. return new (P || (P = Promise))(function (resolve, reject) {
  1285. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  1286. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  1287. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  1288. step((generator = generator.apply(thisArg, _arguments || [])).next());
  1289. });
  1290. };
  1291.  
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298.  
  1299.  
  1300. var CLASS_NAMES;
  1301. (function (CLASS_NAMES) {
  1302. CLASS_NAMES.input = "auto-pager-input";
  1303. CLASS_NAMES.active = "active";
  1304. CLASS_NAMES.error = "error";
  1305. CLASS_NAMES.watching = "watching";
  1306. })(CLASS_NAMES || (CLASS_NAMES = {}));
  1307. (() => src_awaiter(void 0, void 0, void 0, function* () {
  1308. function getPagerFromHeaderCell(headerCell) {
  1309. const title = headerCell.textContent.replace(/\s/g, "");
  1310. if (tableType === "results") {
  1311. let rule = null;
  1312. if (title === "順位" || title === "Rank") {
  1313. rule = {
  1314. orderBy: "Place",
  1315. converter: TextToOrderingTarget.Results.numeric("Place"),
  1316. };
  1317. }
  1318. if (title === "パフォーマンス" || title === "Performance") {
  1319. rule = {
  1320. orderBy: "Performance",
  1321. converter: TextToOrderingTarget.Results.numeric("Performance"),
  1322. };
  1323. }
  1324. if (title === "旧Rating" || title === "OldRating") {
  1325. rule = {
  1326. orderBy: "OldRating",
  1327. converter: TextToOrderingTarget.Results.numeric("OldRating"),
  1328. };
  1329. }
  1330. if (title === "差分" || title === "Diff") {
  1331. rule = {
  1332. orderBy: "Difference",
  1333. converter: TextToOrderingTarget.Results.numeric("Difference"),
  1334. };
  1335. }
  1336. if (title === "新Rating" || title === "NewRating") {
  1337. rule = {
  1338. orderBy: "NewRating",
  1339. converter: TextToOrderingTarget.Results.numeric("NewRating"),
  1340. };
  1341. }
  1342. if (rule) {
  1343. return new ResultsOrderPager(goToPage, changeOrder, rule.orderBy, rule.converter);
  1344. }
  1345. }
  1346. else {
  1347. let rule = null;
  1348. if (title === "順位" || title === "Rank") {
  1349. rule = {
  1350. orderBy: "rank",
  1351. converter: TextToOrderingTarget.Standings.numeric("Rank"),
  1352. };
  1353. }
  1354. if (title === "得点" || title === "Score") {
  1355. rule = {
  1356. orderBy: "score",
  1357. converter: TextToOrderingTarget.Standings.score(null),
  1358. };
  1359. }
  1360. const taskInfo = getTaskInfo();
  1361. if (title in taskInfo) {
  1362. rule = {
  1363. orderBy: "task-" + taskInfo[title].screenName,
  1364. converter: TextToOrderingTarget.Standings.score(title),
  1365. };
  1366. }
  1367. if (rule) {
  1368. return new StandingsOrderPager(goToPage, changeOrder, rule.orderBy, rule.converter);
  1369. }
  1370. if (title === "perf") {
  1371. return new AcPredictorPager(goToPage, changeOrder, headerRow, () => {
  1372. if (perfColumnInputElement) {
  1373. keepPerfInputState(perfColumnInputElement);
  1374. }
  1375. });
  1376. }
  1377. }
  1378. return null;
  1379. }
  1380. function addInputElementToHeaderCell(headerCell) {
  1381. const document = headerCell.ownerDocument;
  1382. const div = document.createElement("div");
  1383. const input = document.createElement("input");
  1384. div.append(input);
  1385. headerCell.append(div);
  1386. input.classList.add(CLASS_NAMES.input);
  1387. input.addEventListener("click", e => {
  1388. e.stopPropagation();
  1389. });
  1390. return input;
  1391. }
  1392. function columnInit(headerCell) {
  1393. const pager = getPagerFromHeaderCell(headerCell);
  1394. if (pager === null)
  1395. return;
  1396. const input = addInputElementToHeaderCell(headerCell);
  1397. input.addEventListener("input", () => src_awaiter(this, void 0, void 0, function* () {
  1398. input.classList.remove(CLASS_NAMES.active);
  1399. input.classList.remove(CLASS_NAMES.error);
  1400. if (watching && watching.element === input) {
  1401. input.classList.remove(CLASS_NAMES.watching);
  1402. watching = null;
  1403. }
  1404. }));
  1405. input.addEventListener("keypress", (e) => src_awaiter(this, void 0, void 0, function* () {
  1406. if (e.code === "Enter") {
  1407. yield execPagerFromInputElement(input, pager, tableType === "standings" && e.ctrlKey);
  1408. }
  1409. }));
  1410. if (pager instanceof AcPredictorPager) {
  1411. perfColumnInputElement = input;
  1412. if (__perfInputState) {
  1413. input.focus();
  1414. input.value = __perfInputState.value;
  1415. input.selectionStart = __perfInputState.selectionStart;
  1416. input.selectionEnd = __perfInputState.selectionEnd;
  1417. input.classList.add(CLASS_NAMES.active);
  1418. setTimeout(() => {
  1419. __perfInputState = null;
  1420. }, 0);
  1421. }
  1422. if (watching && watching.perf !== null) {
  1423. input.classList.add(CLASS_NAMES.watching);
  1424. input.value = watching.perf.value;
  1425. watching = {
  1426. element: input,
  1427. pager: watching.perf.pager,
  1428. perf: watching.perf,
  1429. };
  1430. }
  1431. }
  1432. }
  1433. function execPagerFromInputElement(input, pager, watch = false) {
  1434. return src_awaiter(this, void 0, void 0, function* () {
  1435. if (input.value.replace(/\s/g, "") === "")
  1436. return;
  1437. input.classList.remove(CLASS_NAMES.error);
  1438. input.classList.add(CLASS_NAMES.active);
  1439. input.classList.remove(CLASS_NAMES.watching);
  1440. const preWatching = watching;
  1441. if (watch) {
  1442. input.classList.add(CLASS_NAMES.watching);
  1443. watching = {
  1444. element: input,
  1445. pager,
  1446. perf: pager instanceof AcPredictorPager ? { value: input.value, pager } : null,
  1447. };
  1448. }
  1449. else if (watching && watching.element === input) {
  1450. watching = null;
  1451. }
  1452. try {
  1453. yield pager.exec(input.value);
  1454. }
  1455. catch (e) {
  1456. input.classList.remove(CLASS_NAMES.active);
  1457. input.classList.remove(CLASS_NAMES.watching);
  1458. input.classList.add(CLASS_NAMES.error);
  1459. if (watch)
  1460. watching = preWatching;
  1461. if (e instanceof TargetTextConvertionError) {
  1462. // TODO: Show error message
  1463. // console.error(e);
  1464. }
  1465. else {
  1466. throw e;
  1467. }
  1468. }
  1469. });
  1470. }
  1471. function goToPage(page) {
  1472. return src_awaiter(this, void 0, void 0, function* () {
  1473. if (page === vueObject.page)
  1474. return;
  1475. if (document.activeElement === perfColumnInputElement) {
  1476. keepPerfInputState(perfColumnInputElement);
  1477. }
  1478. vueObject.page = page;
  1479. vueObject.watchIndex = -1;
  1480. yield waitForVueJsNextTick();
  1481. });
  1482. }
  1483. function changeOrder(orderBy, desc = null) {
  1484. return src_awaiter(this, void 0, void 0, function* () {
  1485. if (orderBy === vueObject.orderBy) {
  1486. if (desc === null || desc === vueObject.desc)
  1487. return;
  1488. }
  1489. else {
  1490. if (desc === null)
  1491. desc = false;
  1492. }
  1493. if (document.activeElement === perfColumnInputElement) {
  1494. keepPerfInputState(perfColumnInputElement);
  1495. }
  1496. vueObject.orderBy = orderBy;
  1497. if (desc !== null)
  1498. vueObject.desc = desc;
  1499. yield waitForVueJsNextTick();
  1500. });
  1501. }
  1502. let watching = null;
  1503. let perfColumnInputElement = null;
  1504. let __perfInputState = null;
  1505. function keepPerfInputState(input) {
  1506. __perfInputState = {
  1507. value: input.value,
  1508. selectionStart: input.selectionStart,
  1509. selectionEnd: input.selectionEnd,
  1510. };
  1511. }
  1512. function resetPagers() {
  1513. for (const input of headerRow.querySelectorAll("." + CLASS_NAMES.input)) {
  1514. if (headerRow.ownerDocument.activeElement === input)
  1515. continue;
  1516. input.classList.remove(CLASS_NAMES.active);
  1517. input.classList.remove(CLASS_NAMES.error);
  1518. input.classList.remove(CLASS_NAMES.watching);
  1519. input.value = "";
  1520. }
  1521. if (watching && watching.element !== headerRow.ownerDocument.activeElement) {
  1522. watching = null;
  1523. }
  1524. }
  1525. // main
  1526. const headerRow = (yield asyncQuerySelector("#vue-standings thead tr, #vue-results thead tr"));
  1527. const tableType = typeof vueStandings === "undefined" ? "results" : "standings";
  1528. const vueObject = tableType === "standings" ? vueStandings : vueResults;
  1529. // Launch auto-pager for each column
  1530. headerRow.querySelectorAll("th").forEach(columnInit);
  1531. new MutationObserver(mutations => {
  1532. for (const mutation of mutations) {
  1533. for (const node of mutation.addedNodes) {
  1534. if (node instanceof HTMLElement)
  1535. columnInit(node);
  1536. }
  1537. }
  1538. }).observe(headerRow, { childList: true });
  1539. // Detect pagination
  1540. observeProperties(vueObject, ["page", "orderBy", "desc"], () => {
  1541. resetPagers();
  1542. });
  1543. if (tableType === "standings") {
  1544. // Detect updating
  1545. observeProperties(vueStandings, ["standings"], () => {
  1546. if (watching) {
  1547. execPagerFromInputElement(watching.element, watching.pager, true);
  1548. }
  1549. });
  1550. }
  1551. }))();
  1552.  
  1553. })();
  1554.  
  1555. /******/ })()
  1556. ;