- // ==UserScript==
- // @name Enhanced ioihw20
- // @description Showing problem owners and real names on ioihw20.duck-ac.cn
- // @license MIT
- // @version 0.2.1
- // @author Cekavis
- // @match https://ioihw20.duck-ac.cn/*
- // @grant GM_addStyle
- // @namespace https://gf.qytechs.cn/users/696898
- // ==/UserScript==
-
- GM_addStyle (`
- body > div > div.uoj-content > div.table-responsive > table > thead > tr > th:nth-child(1){
- width: 8em !important;
- }
- `);
-
- (function() {
- 'use strict';
-
- let dict = {
- 'ioi2021_00': '虞皓翔',
- 'ioi2021_01': '马耀华',
- 'ioi2021_02': '彭博',
- 'ioi2021_03': '屠学畅',
- 'ioi2021_04': '黄子宽',
- 'ioi2021_05': '彭思进',
- 'ioi2021_06': '胡昊',
- 'ioi2021_07': '邓明扬',
- 'ioi2021_08': '周欣',
- 'ioi2021_09': '陈雨昕',
- 'ioi2021_10': '叶卓睿',
- 'ioi2021_11': '魏衍芃',
- 'ioi2021_12': '林昊翰',
- 'ioi2021_13': '李白天',
- 'ioi2021_14': '代晨昕',
- 'ioi2021_15': '张隽恺',
- 'ioi2021_16': '徐哲安',
- 'ioi2021_17': '郭城志',
- 'ioi2021_18': '徐舟子',
- 'ioi2021_19': '周镇东',
- 'ioi2021_20': '张好风',
- 'ioi2021_21': '袁浩天',
- 'ioi2021_22': '魏辰轩',
- 'ioi2021_23': '邱天异',
- 'ioi2021_24': '张博为',
- 'ioi2021_25': '陈峻宇',
- 'ioi2021_26': '孙诺舟',
- 'ioi2021_27': '蒋凌宇',
- 'ioi2021_28': '潘佳奇',
- 'ioi2021_29': '钱易',
- 'ioi2021_30': '张庭川',
- 'ioi2021_31': '丁晓漫',
- 'ioi2021_32': '左骏驰',
- 'ioi2021_33': '万天航',
- 'ioi2021_34': '施良致',
- 'ioi2021_35': '刘宇豪',
- 'ioi2021_36': '李泽清',
- 'ioi2021_37': '林立',
- 'ioi2021_38': '戴傅聪',
- 'ioi2021_39': '王泽远',
- 'ioi2021_40': '陈胤戬',
- 'ioi2021_41': '陆宏',
- 'ioi2021_42': '吕秋实',
- 'ioi2021_43': '欧阳宇鹏',
- 'ioi2021_44': '张记僖',
- 'ioi2021_45': '吴孟周',
- 'ioi2021_46': '曹原',
- 'ioi2021_47': '陈亮舟',
- 'ioi2021_48': '卢宸昊',
- 'ioi2021_49': '曾庆之',
- 'ioi2021_50': '万成章',
- 'ioi2021_51': '张景行',
- 'ioi2021_52': '戴江齐',
- 'ioi2021_53': '郑路明',
- 'ioi2021_54': '周航锐',
- 'ioi2021_55': '曹越',
- 'ioi2021_56': '冯施源',
- 'ioi2021_57': '罗恺',
- 'ioi2021_58': '冷滟泽',
- 'ioi2021_59': '杨珖',
- 'ioi2021_60': '陶立宇',
- 'ioi2021_61': '陈于思',
- 'ioi2021_62': '王相文',
- 'ioi2021_63': '孙嘉伟',
- 'ioi2021_64': '孙若凡',
- 'ioi2021_65': '宣毅鸣',
- 'ioi2021_66': '谢濡键',
- 'ioi2021_67': '孙从博',
- 'ioi2021_68': '许庭强',
- 'ioi2021_69': '周子衡',
- 'ioi2021_70': '苏焜',
- 'ioi2021_71': '管晏如',
- 'ioi2021_72': '陈永志',
- 'ioi2021_73': '蔡欣然',
- 'ioi2021_74': '韩豫葳',
- 'ioi2021_75': '张湫阳',
- 'ioi2021_76': '丁其安',
- 'ioi2021_77': '翁伟捷',
- 'ioi2021_78': '吴家庆',
- 'ioi2021_79': '潘逸飞',
- 'ioi2021_80': '谢琳涵'
- }
-
- $('td').each(function () {
- console.log(this.innerHTML);
- if(this.innerHTML.match(/#\d+\./)) {
- let pid = this.innerHTML.match(/\#\d+/)[0]
- let uid = Math.floor((pid.substr(1)-101)/4)
- console.log(pid, uid)
- if(0<=uid && uid<=50){
- if(uid<10) uid = "0" + uid;
- let name = dict["ioi2021_"+uid]
- this.innerHTML = this.innerHTML.replace(pid, '<span style="color:#A0A0A0;font-size:80%">(' + name + ')</span>' + pid)
- }
- }
- })
- $('h1').each(function () {
- console.log(this.innerHTML);
- if(this.innerHTML.match(/#\d+\./)) {
- let pid = this.innerHTML.match(/\#\d+/)[0]
- let uid = Math.floor((pid.substr(1)-101)/4)
- console.log(pid, uid)
- if(0<=uid && uid<=50){
- if(uid<10) uid = "0" + uid;
- let name = dict["ioi2021_"+uid]
- this.innerHTML = this.innerHTML.replace(pid, '<span style="color:#A0A0A0;font-size:80%">(' + name + ')</span>' + pid)
- }
- }
- })
- $('td').each(function () {
- console.log(this.innerHTML);
- if(this.innerHTML.match(/#\d+/)==this.innerHTML) {
- let pid = this.innerHTML.match(/\#\d+/)[0]
- let uid = Math.floor((pid.substr(1)-101)/4)
- console.log(pid, uid)
- if(0<=uid && uid<=50){
- if(uid<10) uid = "0" + uid;
- let name = dict["ioi2021_"+uid]
- this.innerHTML = this.innerHTML.replace(pid, '<span style="color:#A0A0A0;font-size:80%">(' + name + ')</span>' + pid)
- }
- }
- })
-
- $('*').each(function() {
- if(this.innerHTML.match(/^ioi2021_[0-9]+$/g)) {
- let uid = this.innerHTML.match(/ioi2021_[0-9]+/g)[0]
- let name = dict[uid]
- console.log(uid, name)
- this.innerHTML = '<span style="font-weight:normal">' + name + '</span>';
- }
- })
-
- })();
-
- const config = {
- url: {
- codeforces: 'https://www.codeforces.com',
- },
- };
-
- const userlist = [
- "虞皓翔",
- "马耀华",
- "彭博",
- "屠学畅",
- "黄子宽",
- "彭思进",
- "胡昊",
- "邓明扬",
- "周欣",
- "陈雨昕",
- "叶卓睿",
- "魏衍芃",
- "林昊翰",
- "李白天",
- "代晨昕",
- "张隽恺",
- "徐哲安",
- "郭城志",
- "徐舟子",
- "周镇东",
- "张好风",
- "袁浩天",
- "魏辰轩",
- "邱天异",
- "张博为",
- "陈峻宇",
- "孙诺舟",
- "蒋凌宇",
- "潘佳奇",
- "钱易",
- "张庭川",
- "丁晓漫",
- "左骏驰",
- "万天航",
- "施良致",
- "刘宇豪",
- "李泽清",
- "林立",
- "戴傅聪",
- "王泽远",
- "陈胤戬",
- "陆宏",
- "吕秋实",
- "欧阳宇鹏",
- "张记僖",
- "吴孟周",
- "曹原",
- "陈亮舟",
- "卢宸昊",
- "曾庆之",
- "万成章",
- "张景行",
- "戴江齐",
- "郑路明",
- "周航锐",
- "曹越",
- "冯施源",
- "罗恺",
- "冷滟泽",
- "杨珖",
- "陶立宇",
- "陈于思",
- "王相文",
- "孙嘉伟",
- "孙若凡",
- "宣毅鸣",
- "谢濡键",
- "孙从博",
- "许庭强",
- "周子衡",
- "苏焜",
- "管晏如",
- "陈永志",
- "蔡欣然",
- "韩豫葳",
- "张湫阳",
- "丁其安",
- "翁伟捷",
- "吴家庆",
- "潘逸飞",
- "谢琳涵",
- ];
-
- const problemShortcutList = [
- 'UC', 'DG', 'RB',
- 'HC', 'IB', 'FJ',
- 'GK', 'UH', 'QH',
- 'EE', 'DJ', 'IH',
- 'HL', 'MI', 'EJ',
- 'MB', 'UI', 'ED',
- 'AA', 'BG', 'ML',
- 'CF', 'TE', 'QG',
- 'PH', 'UJ', 'BB',
- 'CI', 'SD', 'NG',
- 'DK', 'LD', 'IJ',
- 'NC', 'BJ', 'FK',
- 'CH', 'NJ', 'RH',
- 'QF', 'BE', 'KI',
- 'AC', 'PG', 'HM',
- 'PJ', 'ID', 'EG',
- 'SI', 'KC', 'GI',
- 'OG', 'CK', 'DB',
- 'QE', 'GH', 'NI',
- 'OL', 'KA', 'MG',
- 'SG', 'NL', 'KH',
- 'QJ', 'KG', 'AB',
- 'KD', 'IL', 'NF',
- 'CM', 'NE', 'HD',
- 'DH', 'EC', 'BM',
- 'LC', 'CD', 'JI',
- 'DL', 'ME', 'PE',
- 'LI', 'AI', 'RJ',
- 'SF', 'II', 'HG',
- 'RE', 'LL', 'OA',
- 'FB', 'QD', 'DA',
- 'TC', 'AE', 'CB',
- 'GF', 'AG', 'JC',
- 'PA', 'TH', 'EH',
- 'AJ', 'TK', 'EI',
- 'UL', 'AF', 'SK',
- 'BH', 'RD', 'OK',
- 'FC', 'JD', 'OE',
- 'TF', 'FF', 'DD',
- 'CJ', 'HK', 'MJ',
- 'FG', 'GL', 'AL',
- 'FI', 'IC', 'QC',
- 'MD', 'OJ', 'HI',
- 'KK', 'JH', 'OB',
- 'BK', 'GJ', 'KE',
- 'CA', 'IK', 'LE',
- 'RI', 'LK', 'PD',
- 'JE', 'LB', 'HB',
- 'BL', 'RG', 'AH',
- 'AK', 'GG', 'JG',
- ];
-
- const problemSourceIdList = [
- 101221, 101239, 101242, 101471, 102482, 102511, 101630,
- 101190, 100851, 100553, 100307, 101620, 101173, 101480,
- 100543, 100299, 101612, 101142, 100801, 100531, 100269
- ];
-
- const colors = [
- 'black',
- 'green',
- 'yellow',
- 'red',
- ];
-
- const db = {
- load() {
- return JSON.parse(localStorage.getItem('hw') || '[]');
- },
- dump(data) {
- localStorage.setItem('hw', JSON.stringify(data || []));
- },
- update(pid, status) {
- let data = db.load();
- data[pid] = status;
- db.dump(data);
- },
- query(pid) {
- return db.load()[pid] || 0;
- },
- };
-
- const dbWinner = {
- update(winner) {
- localStorage.setItem('hw-winner', String(winner));
- },
- query() {
- let plain = localStorage.getItem('hw-winner');
- if (isNaN(parseInt(plain))) {
- return -1;
- } else {
- return parseInt(plain);
- }
- }
- };
-
- function getProblemInfo(problemId) {
- let problemType = problemId == 1 ? '测试题' : (problemId < 300 && problemId % 4 ? '作业题' : '自选题');
-
- let shortcut, shortcutId, contestId
- if (problemId >= 101) {
- shortcutId = problemId - 101 - ((problemId - 101) >> 2);
- shortcut = problemShortcutList[shortcutId];
- contestId = problemType == '作业题' ? problemSourceIdList[shortcut.charCodeAt(0) - 65] : -1;
- }
-
- let authorId, authorName;
- if (problemId == 1) authorName = 'root';
- else {
- authorId = (problemId - 101) >> 2;
- authorName = 'ioi2021_' + (problemId < 300 ? (authorId < 10 ? '0' : '') + String(authorId) : problemId - 300 + 49 );
- }
-
- return {
- problemType,
- authorId,
- authorName,
- shortcut,
- shortcutId,
- contestId
- };
- }
-
- function getUserInfo(id) {
- function strMatch(source, reg_exp, default_value) {
- let match_result = source.match(reg_exp);
- if (match_result) {
- return match_result[1];
- } else {
- console.log("[Warning] string doesn't match!");
- return default_value;
- }
- }
- id = id < 10 ? '0' + String(id) : String(id);
- return $.get({
- url: `https://ioihw20.duck-ac.cn/user/profile/ioi2021_${id}`,
- }).then((res) => {
- let motto = strMatch(res, /<h4 class="list-group-item-heading">格言<\/h4>\s+<p class="list-group-item-text">(.*?)<\/p>/s, "<error>");
-
- let regex = /"\/problem\/(\d+)"/g, match, count = 0;
- while (match = regex.exec(res)) {
- let problemId = parseInt(match[1]);
- let { problemType } = getProblemInfo(problemId);
- count += problemType == '作业题';
- }
-
- return {
- id,
- motto,
- count,
- };
- });
- }
-
- async function render() {
- $('*').each(function () {
- if (this.innerHTML.match(/^ioi2021_[0-9]+$/g)) {
- let uid = parseInt(this.innerHTML.match(/ioi2021_[0-9]+/g)[0].slice(8));
- let name = userlist[uid];
- if (uid == dbWinner.query()) {
- name += '<sup><span style="color: red">卷王</span></sup>';
- }
- if (name) {
- console.log(uid, name);
- this.innerHTML = '<span style="font-weight: normal">' + name + '</span>';
- }
- }
- });
-
- if (location.pathname.startsWith('/problems')) {
- $(".table tr td:first-child").each(function () {
- let pid = this.innerHTML.slice(1);
- let status = db.query(pid);
- this.style.color = colors[status];
- if (status) {
- this.style['font-weight'] = 'bold';
- } else {
- this.style['font-weight'] = 'normal';
- }
- console.log(pid, status);
- });
- }
- }
-
- async function mainRender() {
- $('.navbar .navbar-nav').append('<li><a href="/ranklist">排行榜</a></li>')
-
- if (location.pathname == '/ranklist') {
- document.title = document.title.replace('比赛排行榜', '排行榜');
-
- let userListPromised = [];
- $('.pagination').remove();
- $('.table tbody tr').remove();
- for (let userId = 0; userId < 81; userId++) {
- userListPromised.push(getUserInfo(userId));
- }
- let userList = await Promise.all(userListPromised);
- userList.sort((firstUser, secondUser) => {
- console.log(firstUser, secondUser);
- if (firstUser.count == secondUser.count) {
- return parseInt(firstUser.id) - parseInt(secondUser.id);
- }
- return secondUser.count - firstUser.count;
- });
- if (userList.length) {
- dbWinner.update(userList[0].id);
- }
- console.log(userList);
- $('.table thead tr th:last-child').text('通过数');
- for (let user of userList) {
- console.log(user);
- let $tr = $('<tr></tr>');
- $tr.append(`<td>${user.id}</td>`);
- $tr.append(`<td><a class="uoj-username" href="https://ioihw20.duck-ac.cn/user/profile/ioi2021_${user.id}" style="color:rgb(75,175,178)">ioi2021_${user.id}</a></td>`);
- $tr.append(`<td>${user.motto}</td>`);
- $tr.append(`<td>${user.count}</td>`);
- $('.table tbody').append($tr);
- }
- }
-
- if (location.pathname.startsWith('/problem/')) {
- let problemId = parseInt(location.href.substr(location.href.lastIndexOf("problem/") + 8, 3), 10);
- let { problemType, authorName, shortcut, shortcutId, contestId } = getProblemInfo(problemId);
-
- if (problemType == '作业题') {
- $(".nav-tabs").eq(0).append(`<li>
- <span style="display:block;padding:10px 15px;">
- Source:
- <a target="_blank" rel="noopener noreferrer" href="${config.url.codeforces}/gym/${contestId}/problem/${shortcut[1]}">
- ${shortcut}
- </a>
- <a target="_blank" rel="noopener noreferrer" href="${config.url.codeforces}/gym/${contestId}">
- (${contestId})
- </a>
- </span>
- </li>`);
- }
- }
-
- render();
- }
-
- if (location.pathname.startsWith('/problems')) {
- $(".table tr td:first-child").click(function () {
- let pid = this.innerHTML.slice(1);
- let status = db.query(pid);
- status = (status + 1) % colors.length;
- db.update(pid, status);
- render();
- });
- }
-
- mainRender();