警告:本脚本随着洛谷更新已经失效。

使用方法

一个简单的脚本,向洛谷用户页加入比较功能,让你的洛谷生活更有动力/更酸/更自闭。

按钮位置
按钮位置

样例1
样例1

样例2
样例2

更新日志

0.0.2

  • 修复了签名有表格时引发的问题

代码

一键安装
需要Tampermonkey或者其他的用户脚本管理器
如果插件被正确配置将会弹出安装界面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// ==UserScript==
// @name 洛谷比较器
// @namespace https://su226.github.io/
// @version 0.0.2
// @description 有对比才知道自己多蒻
// @author su226
// @match https://www.luogu.org/space/show?uid=*
// @grant none
// ==/UserScript==
const diffIndex = Object.freeze({
"尚无评定": 0,
"入门难度": 1,
"普及-": 2,
"普及/提高-": 3,
"普及+/提高": 4,
"提高+/省选-": 5,
"省选/NOI-": 6,
"NOI/NOI+/CTSC": 7
});
const diffName = Object.freeze(["尚无评定", "入门难度", "普及-", "普及/提高-", "普及+/提高", "提高+/省选-", "省选/NOI-", "NOI/NOI+/CTSC"]);
const diffColor = Object.freeze(["gray", "red", "orange", "yellow", "green", "bluelight", "purple", "bluedark"]);
const permIndex = Object.freeze({
"封禁账户": 0,
"普通用户": 1,
"特殊权限": 2,
"管理员": 3,
"超级管理员/Root": 4
});
const permName = Object.freeze(["封禁账户", "普通用户", "特殊权限", "管理员", "超级管理员/Root"]);
function parseBignum(a) {
if (a[a.length - 1] == "K") {
return parseFloat(a.substring(0, a.length - 1)) * 1000;
} else if (a == "N/A") {
return NaN;
}
return parseInt(a);
}
function toBignum(a) {
if (a >= 1000) {
return Math.round(a / 100) / 10 + "K";
}
return Math.round(a).toString();
}
function parseUser(doc) {
let data = doc.querySelectorAll("span.lg-right");
let ret = {
username: doc.querySelector(".lg-toolbar h1").textContent.split(" ")[1],
uid: parseInt(data[0].textContent),
regTime: new Date(data[2].textContent.trim()),
permission: permIndex[data[1].textContent]
};
let nums = doc.querySelectorAll(".lg-bignum-num");
if (nums.length == 0) {
Object.assign(ret, {
submissions: NaN,
accepted: NaN,
rank: NaN,
difficulty: [NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN]
});
} else {
let difficulties = [0, 0, 0, 0, 0, 0, 0, 0];
doc.querySelectorAll(".am-u-md-4 tr").forEach(e => {
difficulties[diffIndex[e.children[0].children[0].textContent]] = parseInt(e.children[1].children[0].textContent);
});
Object.assign(ret, {
submissions: parseBignum(nums[0].textContent),
accepted: parseBignum(nums[1].textContent),
rank: parseBignum(nums[2].textContent),
difficulty: difficulties
});
}
return ret;
}
let tos = o => o.toString();
let ge = (a, b) => a >= b || Number.isNaN(b);
let le = (a, b) => a <= b || Number.isNaN(b);
function getTd(d1, d2, fmt, cmp) {
if (fmt == null) {
fmt = tos;
}
if (cmp == null) {
cmp = ge;
}
if (cmp(d1, d2)) {
return `<td><span class="am-badge am-badge-success">${fmt(d1)}</span></td><td>${fmt(d2)}</td>`
}
return `<td>${fmt(d1)}</td><td><span class="am-badge am-badge-success">${fmt(d2)}</span></td>`
}
function compareUsers(me, user) {
function getDiffTd() {
let ret = "";
diffName.forEach((v, k) => {
ret += `<tr><td><span class="am-badge lg-bg-${diffColor[k]}">${v}</span></td>${getTd(me.difficulty[k], user.difficulty[k])}</tr>`;
});
return ret;
}
let curTime = new Date().getTime();
let myDay = Math.ceil((curTime - me.regTime.getTime()) / 86400000);
let userDay = Math.ceil((curTime - user.regTime.getTime()) / 86400000);
if (modalCmp) {
document.body.removeChild(modalCmp);
}
modalCmp = document.createElement("div");
modalCmp.className = "am-modal";
document.body.appendChild(modalCmp);
modalCmp.innerHTML = `
<div class="am-modal-dialog">
<table class="am-table">
<thead>
<tr>
<th style="width:140px"><a href="javascript:;" class="am-close am-close-spin" data-am-modal-close>&times;</a></th>
<th style="width:200px;text-align:center">${me.username}</th>
<th style="width:200px;text-align:center">${user.username}</th>
</tr>
</thead>
<tbody>
<tr><td>UID</td>${getTd(me.uid, user.uid, tos, le)}</tr>
<tr><td>权限</td>${getTd(me.permission, user.permission, o => permName[o])}</tr>
<tr><td>注册天数</td>${getTd(myDay, userDay)}</tr>
<tr><td>提交数</td>${getTd(me.submissions, user.submissions, o => toBignum(o))}</tr>
<tr><td>通过数</td>${getTd(me.accepted, user.accepted, o => toBignum(o))}</tr>
<tr><td>排名</td>${getTd(me.rank, user.rank, o => toBignum(o), le)}</tr>
${getDiffTd()}
</tbody>
</table>
</div>`;
$(modalCmp).modal("open");
}
let btn = document.createElement("button");
btn.textContent = "比较";
btn.className = "am-btn am-btn-sm am-btn-danger";
btn.onclick = () => {
$(modalLoad).modal("open");
let xhr = new XMLHttpRequest();
let myuid = document.querySelector(".avatar").src;
myuid = parseInt(myuid.substring(38, myuid.length - 4));
xhr.open("GET", `https://www.luogu.org/space/show?uid=${myuid}`);
xhr.onload = () => {
$(modalLoad).modal("close");
compareUsers(
parseUser(new DOMParser().parseFromString(xhr.responseText, "text/html")),
parseUser(document));
};
xhr.send();
};
document.querySelector(".lg-summary-content p").appendChild(btn);

let modalCmp;
let modalLoad = document.createElement("div");
modalLoad.className = "am-modal am-modal-loading";
modalLoad.innerHTML = `<div class="am-modal-dialog"><div class="am-modal-hd">正在请求我的数据</div><div class="am-modal-bd"><span class="am-icon-spinner am-icon-spin"></span></div></div>`;
document.body.appendChild(modalLoad);