nonebot-plugin-osubot 6.22.1__py3-none-any.whl → 6.26.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nonebot_plugin_osubot/api.py +13 -7
- nonebot_plugin_osubot/config.py +10 -10
- nonebot_plugin_osubot/draw/bmap.py +20 -22
- nonebot_plugin_osubot/draw/bp.py +3 -13
- nonebot_plugin_osubot/draw/catch_preview.py +2 -16
- nonebot_plugin_osubot/draw/echarts.py +8 -1
- nonebot_plugin_osubot/draw/info.py +59 -207
- nonebot_plugin_osubot/draw/info_templates/index.html +507 -0
- nonebot_plugin_osubot/draw/info_templates/output.css +2 -0
- nonebot_plugin_osubot/draw/map.py +9 -11
- nonebot_plugin_osubot/draw/osu_preview.py +50 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/css/style.css +258 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/README.md +109 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js +3 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js.map +1 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js +3 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js.map +1 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/beatmap.js +211 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/hitobject.js +29 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/point.js +55 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/scroll.js +45 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/timingpoint.js +35 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/LegacyRandom.js +81 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/PalpableCatchHitObject.js +53 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/bananashower.js +33 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/catch.js +211 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/fruit.js +21 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/juicestream.js +176 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/hitnote.js +21 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/holdnote.js +37 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/mania.js +164 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/preview.js +61 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/bezier2.js +33 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/catmullcurve.js +34 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/centripetalcatmullrom.js +30 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/circumstancedcircle.js +47 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curve.js +25 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curvetype.js +17 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/equaldistancemulticurve.js +70 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/linearbezier.js +40 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/hitcircle.js +85 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/slider.js +120 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/spinner.js +56 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/standard.js +170 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/donkat.js +40 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/drumroll.js +34 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/shaker.js +58 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/taiko.js +120 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/util.js +61 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/pic.html +110 -0
- nonebot_plugin_osubot/draw/rating.py +6 -3
- nonebot_plugin_osubot/draw/score.py +23 -81
- nonebot_plugin_osubot/draw/taiko_preview.py +14 -13
- nonebot_plugin_osubot/draw/templates/bpa_chart.html +1 -1
- nonebot_plugin_osubot/draw/utils.py +162 -16
- nonebot_plugin_osubot/file.py +184 -31
- nonebot_plugin_osubot/mania/__init__.py +9 -10
- nonebot_plugin_osubot/matcher/__init__.py +2 -0
- nonebot_plugin_osubot/matcher/bp_analyze.py +14 -9
- nonebot_plugin_osubot/matcher/guess.py +250 -294
- nonebot_plugin_osubot/matcher/map_convert.py +21 -13
- nonebot_plugin_osubot/matcher/medal.py +1 -1
- nonebot_plugin_osubot/matcher/osudl.py +5 -4
- nonebot_plugin_osubot/matcher/pr.py +0 -4
- nonebot_plugin_osubot/matcher/preview.py +10 -3
- nonebot_plugin_osubot/matcher/recommend.py +7 -12
- nonebot_plugin_osubot/mods.py +62 -61
- nonebot_plugin_osubot/network/first_response.py +1 -1
- nonebot_plugin_osubot/osufile/mods/AP.png +0 -0
- nonebot_plugin_osubot/osufile/mods/CL.png +0 -0
- nonebot_plugin_osubot/osufile/mods/DT.png +0 -0
- nonebot_plugin_osubot/osufile/mods/EZ.png +0 -0
- nonebot_plugin_osubot/osufile/mods/FI.png +0 -0
- nonebot_plugin_osubot/osufile/mods/FL.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HR.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HT.png +0 -0
- nonebot_plugin_osubot/osufile/mods/MR.png +0 -0
- nonebot_plugin_osubot/osufile/mods/NC.png +0 -0
- nonebot_plugin_osubot/osufile/mods/NF.png +0 -0
- nonebot_plugin_osubot/osufile/mods/PF.png +0 -0
- nonebot_plugin_osubot/osufile/mods/RX.png +0 -0
- nonebot_plugin_osubot/osufile/mods/SD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/SO.png +0 -0
- nonebot_plugin_osubot/osufile/mods/TD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/V2.png +0 -0
- nonebot_plugin_osubot/pp.py +7 -0
- nonebot_plugin_osubot/schema/__init__.py +0 -2
- nonebot_plugin_osubot/schema/beatmapsets.py +42 -0
- nonebot_plugin_osubot/schema/draw_info.py +54 -0
- nonebot_plugin_osubot/schema/score.py +2 -0
- nonebot_plugin_osubot/schema/user.py +1 -0
- {nonebot_plugin_osubot-6.22.1.dist-info → nonebot_plugin_osubot-6.26.4.dist-info}/METADATA +18 -17
- {nonebot_plugin_osubot-6.22.1.dist-info → nonebot_plugin_osubot-6.26.4.dist-info}/RECORD +95 -52
- nonebot_plugin_osubot-6.26.4.dist-info/WHEEL +4 -0
- nonebot_plugin_osubot/schema/sayo_beatmap.py +0 -59
- nonebot_plugin_osubot-6.22.1.dist-info/WHEEL +0 -4
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8"/>
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
6
|
+
<title>Osu! 用户信息</title>
|
|
7
|
+
<link href="./output.css" rel="stylesheet"/>
|
|
8
|
+
<style>
|
|
9
|
+
:root {
|
|
10
|
+
--level-tier-iron: #bab3ab, #bab3ab;
|
|
11
|
+
--level-tier-bronze: #b88f7a, #855c47;
|
|
12
|
+
--level-tier-silver: #e0e0eb, #a3a3c2;
|
|
13
|
+
--level-tier-gold: #f0e4a8, #e0c952;
|
|
14
|
+
--level-tier-platinum: #a8f0ef, #52e0df;
|
|
15
|
+
--level-tier-rhodium: #d9f8d3, #a0cf96;
|
|
16
|
+
--level-tier-radiant: #97dcff, #ed82ff;
|
|
17
|
+
--level-tier-lustrous: #ffe600, #ed82ff;
|
|
18
|
+
--rank-value-default-colour: #cccccc, #999999;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
body {
|
|
22
|
+
background: #1a1a2e;
|
|
23
|
+
margin: 0;
|
|
24
|
+
padding: 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.score-rank {
|
|
28
|
+
display: flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: center;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.user-level {
|
|
34
|
+
position: relative;
|
|
35
|
+
display: flex;
|
|
36
|
+
align-items: center;
|
|
37
|
+
justify-content: center;
|
|
38
|
+
width: 50px;
|
|
39
|
+
height: 50px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.user-level-bg {
|
|
43
|
+
position: absolute;
|
|
44
|
+
inset: 0;
|
|
45
|
+
clip-path: path(
|
|
46
|
+
"m 25,2.7 a 9.3,9.3 0 0 1 4.7,1.2 l 11.3,6.5 a 9.3,9.3 0 0 1 4.6,8.1 v 13.0 a 9.3,9.3 0 0 1 -4.6,8.1 L 29.7,46.1 a 9.3,9.3 0 0 1 -9.3,0 L 9.1,39.6 A 9.3,9.3 0 0 1 4.4,31.5 v -13.0 A 9.3,9.3 0 0 1 9.1,10.4 L 20.4,3.9 A 9.3,9.3 0 0 1 25,2.7 M 25,0.0 A 11.9,11.9 0 0 0 19.0,1.6 L 7.7,8.1 A 12.0,12.0 0 0 0 1.7,18.5 v 13.0 a 12.0,12.0 0 0 0 6.0,10.4 l 11.3,6.5 a 12.0,12.0 0 0 0 12.0,0 l 11.3,-6.5 a 12.0,12.0 0 0 0 6.0,-10.4 v -13.0 A 12.0,12.0 0 0 0 42.3,8.1 L 31.0,1.6 A 11.9,11.9 0 0 0 25.0,0 Z"
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.user-level-text {
|
|
51
|
+
position: absolute;
|
|
52
|
+
color: white;
|
|
53
|
+
font-weight: bold;
|
|
54
|
+
font-size: 14px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.score-rank svg {
|
|
58
|
+
width: 32px;
|
|
59
|
+
height: 16px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.rank-value {
|
|
63
|
+
--colour: var(--rank-value-default-colour);
|
|
64
|
+
font-size: 1.25rem;
|
|
65
|
+
line-height: 1.75rem;
|
|
66
|
+
font-weight: 700;
|
|
67
|
+
background-clip: text;
|
|
68
|
+
-webkit-background-clip: text;
|
|
69
|
+
color: transparent;
|
|
70
|
+
background-image: linear-gradient(var(--colour));
|
|
71
|
+
}
|
|
72
|
+
</style>
|
|
73
|
+
</head>
|
|
74
|
+
<body class="">
|
|
75
|
+
<div
|
|
76
|
+
id="userInfo"
|
|
77
|
+
class="min-h-screen bg-cover bg-center bg-no-repeat flex flex-col gap-2 h-full
|
|
78
|
+
relative
|
|
79
|
+
before:content-['']
|
|
80
|
+
before:absolute
|
|
81
|
+
before:inset-0
|
|
82
|
+
before:bg-black
|
|
83
|
+
before:opacity-70
|
|
84
|
+
z-0
|
|
85
|
+
max-w-[440px]"
|
|
86
|
+
style="background-image: url({{bg}})"
|
|
87
|
+
></div>
|
|
88
|
+
<script>
|
|
89
|
+
function getGlobalTier(user) {
|
|
90
|
+
const rank = user.statistics?.global_rank;
|
|
91
|
+
const percent = user.statistics?.global_rank_percent;
|
|
92
|
+
|
|
93
|
+
if (rank == null || percent == null) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (rank <= 100) {
|
|
98
|
+
return 'lustrous';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return percent < 0.0005 ? 'radiant'
|
|
102
|
+
: percent < 0.0025 ? 'rhodium'
|
|
103
|
+
: percent < 0.005 ? 'platinum'
|
|
104
|
+
: percent < 0.025 ? 'gold'
|
|
105
|
+
: percent < 0.05 ? 'silver'
|
|
106
|
+
: percent < 0.25 ? 'bronze'
|
|
107
|
+
: percent < 0.5 ? 'iron'
|
|
108
|
+
: null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function getRankDisplay(user) {
|
|
112
|
+
const tier = getGlobalTier(user);
|
|
113
|
+
const currentTier = tier ?? 'base';
|
|
114
|
+
|
|
115
|
+
let tierVar = '';
|
|
116
|
+
if (tier != null) {
|
|
117
|
+
tierVar = `--colour: var(--level-tier-${tier})`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let classes = 'rank-value';
|
|
121
|
+
if (currentTier === 'base' || currentTier === 'iron') {
|
|
122
|
+
classes += ' rank-value--' + currentTier;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const rank = user.statistics?.global_rank;
|
|
126
|
+
const displayValue = rank != null ? `#${rank.toLocaleString()}` : 'N/A';
|
|
127
|
+
|
|
128
|
+
return `<div class="${classes}" style="${tierVar}">${displayValue}</div>`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// SVG 评级图标组件
|
|
132
|
+
function getScoreRankSVG(rank) {
|
|
133
|
+
const svgs = {
|
|
134
|
+
xh: `
|
|
135
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="16" viewBox="0 0 32 16" fill="none">
|
|
136
|
+
<g clip-path="url(#clip0)">
|
|
137
|
+
<rect width="32" height="16" rx="8" fill="#CE1C9D"/>
|
|
138
|
+
<path d="M5.3393 11.4417V13.0801H13.0065C15.4769 13.0801 16.4241 12.0305 16.4241 10.5457C16.4241 8.77928 15.0929 8.12648 13.0321 7.96008L9.0001 7.64008C7.5665 7.52488 7.2337 7.26888 7.2337 6.78248C7.2337 6.19368 7.7201 5.96328 8.5777 5.96328H15.8609V4.32488H8.7441C6.9393 4.32488 5.3777 4.97768 5.3777 6.83368C5.3777 8.44648 6.5553 9.15048 8.5265 9.30408L12.7633 9.63688C14.0177 9.73928 14.5425 10.0337 14.5425 10.6225C14.5425 11.1089 14.1969 11.4417 13.1217 11.4417H5.3393ZM15.7568 11.4417V13.0801H23.424C25.8944 13.0801 26.8416 12.0305 26.8416 10.5457C26.8416 8.77928 25.5104 8.12648 23.4496 7.96008L19.4176 7.64008C17.984 7.52488 17.6512 7.26888 17.6512 6.78248C17.6512 6.19368 18.1376 5.96328 18.9952 5.96328H26.2784V4.32488H19.1616C17.3568 4.32488 15.7952 4.97768 15.7952 6.83368C15.7952 8.44648 16.9728 9.15048 18.944 9.30408L23.1808 9.63688C24.4352 9.73928 24.96 10.0337 24.96 10.6225C24.96 11.1089 24.6144 11.4417 23.5392 11.4417H15.7568Z" fill="#5E244E" fill-opacity="0.5"/>
|
|
139
|
+
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="32" height="16">
|
|
140
|
+
<rect width="32" height="16" rx="8" fill="#DE31AE"/>
|
|
141
|
+
</mask>
|
|
142
|
+
<g mask="url(#mask0)">
|
|
143
|
+
<path d="M16 -9L33.3205 21H-1.32051L16 -9Z" fill="#DE31AE"/>
|
|
144
|
+
<path d="M27.5 3L33.9952 14.25H21.0048L27.5 3Z" fill="#C30B90"/>
|
|
145
|
+
<path d="M7.5 -2L11.3971 4.75H3.60289L7.5 -2Z" fill="#BE0089"/>
|
|
146
|
+
<path d="M9.5 13L13.3971 19.75H5.60289L9.5 13Z" fill="#BE0089"/>
|
|
147
|
+
</g>
|
|
148
|
+
<path d="M5.3393 11.4417V13.0801H13.0065C15.4769 13.0801 16.4241 12.0305 16.4241 10.5457C16.4241 8.77928 15.0929 8.12648 13.0321 7.96008L9.0001 7.64008C7.5665 7.52488 7.2337 7.26888 7.2337 6.78248C7.2337 6.19368 7.7201 5.96328 8.5777 5.96328H15.8609V4.32488H8.7441C6.9393 4.32488 5.3777 4.97768 5.3777 6.83368C5.3777 8.44648 6.5553 9.15048 8.5265 9.30408L12.7633 9.63688C14.0177 9.73928 14.5425 10.0337 14.5425 10.6225C14.5425 11.1089 14.1969 11.4417 13.1217 11.4417H5.3393ZM15.7568 11.4417V13.0801H23.424C25.8944 13.0801 26.8416 12.0305 26.8416 10.5457C26.8416 8.77928 25.5104 8.12648 23.4496 7.96008L19.4176 7.64008C17.984 7.52488 17.6512 7.26888 17.6512 6.78248C17.6512 6.19368 18.1376 5.96328 18.9952 5.96328H26.2784V4.32488H19.1616C17.3568 4.32488 15.7952 4.97768 15.7952 6.83368C15.7952 8.44648 16.9728 9.15048 18.944 9.30408L23.1808 9.63688C24.4352 9.73928 24.96 10.0337 24.96 10.6225C24.96 11.1089 24.6144 11.4417 23.5392 11.4417H15.7568Z" fill="#5E244E" fill-opacity="0.5"/>
|
|
149
|
+
<path d="M5.3393 10.4417V12.0801H13.0065C15.4769 12.0801 16.4241 11.0305 16.4241 9.54568C16.4241 7.77928 15.0929 7.12648 13.0321 6.96008L9.0001 6.64008C7.5665 6.52488 7.2337 6.26888 7.2337 5.78248C7.2337 5.19368 7.7201 4.96328 8.5777 4.96328H15.8609V3.32488H8.7441C6.9393 3.32488 5.3777 3.97768 5.3777 5.83368C5.3777 7.44648 6.5553 8.15048 8.5265 8.30408L12.7633 8.63688C14.0177 8.73928 14.5425 9.03368 14.5425 9.62248C14.5425 10.1089 14.1969 10.4417 13.1217 10.4417H5.3393ZM15.7568 10.4417V12.0801H23.424C25.8944 12.0801 26.8416 11.0305 26.8416 9.54568C26.8416 7.77928 25.5104 7.12648 23.4496 6.96008L19.4176 6.64008C17.984 6.52488 17.6512 6.26888 17.6512 5.78248C17.6512 5.19368 18.1376 4.96328 18.9952 4.96328H26.2784V3.32488H19.1616C17.3568 3.32488 15.7952 3.97768 15.7952 5.83368C15.7952 7.44648 16.9728 8.15048 18.944 8.30408L23.1808 8.63688C24.4352 8.73928 24.96 9.03368 24.96 9.62248C24.96 10.1089 24.6144 10.4417 23.5392 10.4417H15.7568Z" fill="url(#paint0_linear)"/>
|
|
150
|
+
</g>
|
|
151
|
+
<defs>
|
|
152
|
+
<linearGradient id="paint0_linear" x1="16" y1="2.08008" x2="16" y2="16.0001" gradientUnits="userSpaceOnUse">
|
|
153
|
+
<stop stop-color="white"/>
|
|
154
|
+
<stop offset="1" stop-color="#AADFF0"/>
|
|
155
|
+
</linearGradient>
|
|
156
|
+
<clipPath id="clip0">
|
|
157
|
+
<rect width="32" height="16" fill="white"/>
|
|
158
|
+
</clipPath>
|
|
159
|
+
</defs>
|
|
160
|
+
</svg>
|
|
161
|
+
`,
|
|
162
|
+
ss: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="16" viewBox="0 0 32 16" fill="none">
|
|
163
|
+
<g clip-path="url(#clip1)">
|
|
164
|
+
<rect width="32" height="16" rx="8" fill="#CE1C9D"/>
|
|
165
|
+
<path d="M5.3393 11.4417V13.0801H13.0065C15.4769 13.0801 16.4241 12.0305 16.4241 10.5457C16.4241 8.77928 15.0929 8.12648 13.0321 7.96008L9.0001 7.64008C7.5665 7.52488 7.2337 7.26888 7.2337 6.78248C7.2337 6.19368 7.7201 5.96328 8.5777 5.96328H15.8609V4.32488H8.7441C6.9393 4.32488 5.3777 4.97768 5.3777 6.83368C5.3777 8.44648 6.5553 9.15048 8.5265 9.30408L12.7633 9.63688C14.0177 9.73928 14.5425 10.0337 14.5425 10.6225C14.5425 11.1089 14.1969 11.4417 13.1217 11.4417H5.3393ZM15.7568 11.4417V13.0801H23.424C25.8944 13.0801 26.8416 12.0305 26.8416 10.5457C26.8416 8.77928 25.5104 8.12648 23.4496 7.96008L19.4176 7.64008C17.984 7.52488 17.6512 7.26888 17.6512 6.78248C17.6512 6.19368 18.1376 5.96328 18.9952 5.96328H26.2784V4.32488H19.1616C17.3568 4.32488 15.7952 4.97768 15.7952 6.83368C15.7952 8.44648 16.9728 9.15048 18.944 9.30408L23.1808 9.63688C24.4352 9.73928 24.96 10.0337 24.96 10.6225C24.96 11.1089 24.6144 11.4417 23.5392 11.4417H15.7568Z" fill="#5E244E" fill-opacity="0.5"/>
|
|
166
|
+
<mask id="mask1" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="32" height="16">
|
|
167
|
+
<rect width="32" height="16" rx="8" fill="#DE31AE"/>
|
|
168
|
+
</mask>
|
|
169
|
+
<g mask="url(#mask1)">
|
|
170
|
+
<path d="M16 -9L33.3205 21H-1.32051L16 -9Z" fill="#DE31AE"/>
|
|
171
|
+
<path d="M27.5 3L33.9952 14.25H21.0048L27.5 3Z" fill="#C30B90"/>
|
|
172
|
+
<path d="M7.5 -2L11.3971 4.75H3.60289L7.5 -2Z" fill="#BE0089"/>
|
|
173
|
+
<path d="M9.5 13L13.3971 19.75H5.60289L9.5 13Z" fill="#BE0089"/>
|
|
174
|
+
</g>
|
|
175
|
+
<path d="M5.3393 11.4417V13.0801H13.0065C15.4769 13.0801 16.4241 12.0305 16.4241 10.5457C16.4241 8.77928 15.0929 8.12648 13.0321 7.96008L9.0001 7.64008C7.5665 7.52488 7.2337 7.26888 7.2337 6.78248C7.2337 6.19368 7.7201 5.96328 8.5777 5.96328H15.8609V4.32488H8.7441C6.9393 4.32488 5.3777 4.97768 5.3777 6.83368C5.3777 8.44648 6.5553 9.15048 8.5265 9.30408L12.7633 9.63688C14.0177 9.73928 14.5425 10.0337 14.5425 10.6225C14.5425 11.1089 14.1969 11.4417 13.1217 11.4417H5.3393ZM15.7568 11.4417V13.0801H23.424C25.8944 13.0801 26.8416 12.0305 26.8416 10.5457C26.8416 8.77928 25.5104 8.12648 23.4496 7.96008L19.4176 7.64008C17.984 7.52488 17.6512 7.26888 17.6512 6.78248C17.6512 6.19368 18.1376 5.96328 18.9952 5.96328H26.2784V4.32488H19.1616C17.3568 4.32488 15.7952 4.97768 15.7952 6.83368C15.7952 8.44648 16.9728 9.15048 18.944 9.30408L23.1808 9.63688C24.4352 9.73928 24.96 10.0337 24.96 10.6225C24.96 11.1089 24.6144 11.4417 23.5392 11.4417H15.7568Z" fill="#5E244E" fill-opacity="0.5"/>
|
|
176
|
+
<path d="M5.3393 10.4417V12.0801H13.0065C15.4769 12.0801 16.4241 11.0305 16.4241 9.54568C16.4241 7.77928 15.0929 7.12648 13.0321 6.96008L9.0001 6.64008C7.5665 6.52488 7.2337 6.26888 7.2337 5.78248C7.2337 5.19368 7.7201 4.96328 8.5777 4.96328H15.8609V3.32488H8.7441C6.9393 3.32488 5.3777 3.97768 5.3777 5.83368C5.3777 7.44648 6.5553 8.15048 8.5265 8.30408L12.7633 8.63688C14.0177 8.73928 14.5425 9.03368 14.5425 9.62248C14.5425 10.1089 14.1969 10.4417 13.1217 10.4417H5.3393ZM15.7568 10.4417V12.0801H23.424C25.8944 12.0801 26.8416 11.0305 26.8416 9.54568C26.8416 7.77928 25.5104 7.12648 23.4496 6.96008L19.4176 6.64008C17.984 6.52488 17.6512 6.26888 17.6512 5.78248C17.6512 5.19368 18.1376 4.96328 18.9952 4.96328H26.2784V3.32488H19.1616C17.3568 3.32488 15.7952 3.97768 15.7952 5.83368C15.7952 7.44648 16.9728 8.15048 18.944 8.30408L23.1808 8.63688C24.4352 8.73928 24.96 9.03368 24.96 9.62248C24.96 10.1089 24.6144 10.4417 23.5392 10.4417H15.7568Z" fill="#5E244E"/>
|
|
177
|
+
<path d="M5.3393 10.4417V12.0801H13.0065C15.4769 12.0801 16.4241 11.0305 16.4241 9.54568C16.4241 7.77928 15.0929 7.12648 13.0321 6.96008L9.0001 6.64008C7.5665 6.52488 7.2337 6.26888 7.2337 5.78248C7.2337 5.19368 7.7201 4.96328 8.5777 4.96328H15.8609V3.32488H8.7441C6.9393 3.32488 5.3777 3.97768 5.3777 5.83368C5.3777 7.44648 6.5553 8.15048 8.5265 8.30408L12.7633 8.63688C14.0177 8.73928 14.5425 9.03368 14.5425 9.62248C14.5425 10.1089 14.1969 10.4417 13.1217 10.4417H5.3393ZM15.7568 10.4417V12.0801H23.424C25.8944 12.0801 26.8416 11.0305 26.8416 9.54568C26.8416 7.77928 25.5104 7.12648 23.4496 6.96008L19.4176 6.64008C17.984 6.52488 17.6512 6.26888 17.6512 5.78248C17.6512 5.19368 18.1376 4.96328 18.9952 4.96328H26.2784V3.32488H19.1616C17.3568 3.32488 15.7952 3.97768 15.7952 5.83368C15.7952 7.44648 16.9728 8.15048 18.944 8.30408L23.1808 8.63688C24.4352 8.73928 24.96 9.03368 24.96 9.62248C24.96 10.1089 24.6144 10.4417 23.5392 10.4417H15.7568Z" fill="url(#paint1_linear)"/>
|
|
178
|
+
</g>
|
|
179
|
+
<defs>
|
|
180
|
+
<linearGradient id="paint1_linear" x1="16" y1="2.08008" x2="16" y2="16.0001" gradientUnits="userSpaceOnUse">
|
|
181
|
+
<stop stop-color="#FFE7A8"/>
|
|
182
|
+
<stop offset="1" stop-color="#FFB800"/>
|
|
183
|
+
</linearGradient>
|
|
184
|
+
<clipPath id="clip1">
|
|
185
|
+
<rect width="32" height="16" fill="white"/>
|
|
186
|
+
</clipPath>
|
|
187
|
+
</defs>
|
|
188
|
+
</svg>`,
|
|
189
|
+
x: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="16" viewBox="0 0 32 16" fill="none">
|
|
190
|
+
<g clip-path="url(#clip2)">
|
|
191
|
+
<rect width="32" height="16" rx="8" fill="#00A8B5"/>
|
|
192
|
+
<path d="M10.548 11.4417V13.0801H18.2153C20.6857 13.0801 21.6329 12.0305 21.6329 10.5457C21.6329 8.77928 20.3017 8.12648 18.2409 7.96008L14.2088 7.64008C12.7752 7.52488 12.4424 7.26888 12.4424 6.78248C12.4424 6.19368 12.9288 5.96328 13.7864 5.96328H21.0697V4.32488H13.9528C12.148 4.32488 10.5864 4.97768 10.5864 6.83368C10.5864 8.44648 11.764 9.15048 13.7352 9.30408L17.9721 9.63688C19.2265 9.73928 19.7513 10.0337 19.7513 10.6225C19.7513 11.1089 19.4057 11.4417 18.3305 11.4417H10.548Z" fill="#095056" fill-opacity="0.5"/>
|
|
193
|
+
<mask id="mask2" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="32" height="16">
|
|
194
|
+
<rect width="32" height="16" rx="8" fill="#02B5C3"/>
|
|
195
|
+
</mask>
|
|
196
|
+
<g mask="url(#mask2)">
|
|
197
|
+
<path d="M16 -9L33.3205 21H-1.32051L16 -9Z" fill="#02B5C3"/>
|
|
198
|
+
<path d="M27.5 3L33.9952 14.25H21.0048L27.5 3Z" fill="#009DAA"/>
|
|
199
|
+
<path d="M7.5 -2L11.3971 4.75H3.60289L7.5 -2Z" fill="#0096A2"/>
|
|
200
|
+
<path d="M9.5 13L13.3971 19.75H5.60289L9.5 13Z" fill="#0096A2"/>
|
|
201
|
+
</g>
|
|
202
|
+
<path d="M10.548 11.4417V13.0801H18.2153C20.6857 13.0801 21.6329 12.0305 21.6329 10.5457C21.6329 8.77928 20.3017 8.12648 18.2409 7.96008L14.2088 7.64008C12.7752 7.52488 12.4424 7.26888 12.4424 6.78248C12.4424 6.19368 12.9288 5.96328 13.7864 5.96328H21.0697V4.32488H13.9528C12.148 4.32488 10.5864 4.97768 10.5864 6.83368C10.5864 8.44648 11.764 9.15048 13.7352 9.30408L17.9721 9.63688C19.2265 9.73928 19.7513 10.0337 19.7513 10.6225C19.7513 11.1089 19.4057 11.4417 18.3305 11.4417H10.548Z" fill="#095056" fill-opacity="0.5"/>
|
|
203
|
+
<path d="M10.548 10.4417V12.0801H18.2153C20.6857 12.0801 21.6329 11.0305 21.6329 9.54568C21.6329 7.77928 20.3017 7.12648 18.2409 6.96008L14.2088 6.64008C12.7752 6.52488 12.4424 6.26888 12.4424 5.78248C12.4424 5.19368 12.9288 4.96328 13.7864 4.96328H21.0697V3.32488H13.9528C12.148 3.32488 10.5864 3.97768 10.5864 5.83368C10.5864 7.44648 11.764 8.15048 13.7352 8.30408L17.9721 8.63688C19.2265 8.73928 19.7513 9.03368 19.7513 9.62248C19.7513 10.1089 19.4057 10.4417 18.3305 10.4417H10.548Z" fill="url(#paint2_linear)"/>
|
|
204
|
+
</g>
|
|
205
|
+
<defs>
|
|
206
|
+
<linearGradient id="paint2_linear" x1="16" y1="2.08008" x2="16" y2="16.0001" gradientUnits="userSpaceOnUse">
|
|
207
|
+
<stop stop-color="white"/>
|
|
208
|
+
<stop offset="1" stop-color="#AADFF0"/>
|
|
209
|
+
</linearGradient>
|
|
210
|
+
<clipPath id="clip2">
|
|
211
|
+
<rect width="32" height="16" fill="white"/>
|
|
212
|
+
</clipPath>
|
|
213
|
+
</defs>
|
|
214
|
+
</svg>`,
|
|
215
|
+
s: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="16" viewBox="0 0 32 16" fill="none">
|
|
216
|
+
<g clip-path="url(#clip3)">
|
|
217
|
+
<rect width="32" height="16" rx="8" fill="#00A8B5"/>
|
|
218
|
+
<path d="M10.548 11.4417V13.0801H18.2153C20.6857 13.0801 21.6329 12.0305 21.6329 10.5457C21.6329 8.77928 20.3017 8.12648 18.2409 7.96008L14.2088 7.64008C12.7752 7.52488 12.4424 7.26888 12.4424 6.78248C12.4424 6.19368 12.9288 5.96328 13.7864 5.96328H21.0697V4.32488H13.9528C12.148 4.32488 10.5864 4.97768 10.5864 6.83368C10.5864 8.44648 11.764 9.15048 13.7352 9.30408L17.9721 9.63688C19.2265 9.73928 19.7513 10.0337 19.7513 10.6225C19.7513 11.1089 19.4057 11.4417 18.3305 11.4417H10.548Z" fill="#095056" fill-opacity="0.5"/>
|
|
219
|
+
<mask id="mask3" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="32" height="16">
|
|
220
|
+
<rect width="32" height="16" rx="8" fill="#02B5C3"/>
|
|
221
|
+
</mask>
|
|
222
|
+
<g mask="url(#mask3)">
|
|
223
|
+
<path d="M16 -9L33.3205 21H-1.32051L16 -9Z" fill="#02B5C3"/>
|
|
224
|
+
<path d="M27.5 3L33.9952 14.25H21.0048L27.5 3Z" fill="#009DAA"/>
|
|
225
|
+
<path d="M7.5 -2L11.3971 4.75H3.60289L7.5 -2Z" fill="#0096A2"/>
|
|
226
|
+
<path d="M9.5 13L13.3971 19.75H5.60289L9.5 13Z" fill="#0096A2"/>
|
|
227
|
+
</g>
|
|
228
|
+
<path d="M10.548 11.4417V13.0801H18.2153C20.6857 13.0801 21.6329 12.0305 21.6329 10.5457C21.6329 8.77928 20.3017 8.12648 18.2409 7.96008L14.2088 7.64008C12.7752 7.52488 12.4424 7.26888 12.4424 6.78248C12.4424 6.19368 12.9288 5.96328 13.7864 5.96328H21.0697V4.32488H13.9528C12.148 4.32488 10.5864 4.97768 10.5864 6.83368C10.5864 8.44648 11.764 9.15048 13.7352 9.30408L17.9721 9.63688C19.2265 9.73928 19.7513 10.0337 19.7513 10.6225C19.7513 11.1089 19.4057 11.4417 18.3305 11.4417H10.548Z" fill="#095056" fill-opacity="0.5"/>
|
|
229
|
+
<path d="M10.548 10.4417V12.0801H18.2153C20.6857 12.0801 21.6329 11.0305 21.6329 9.54568C21.6329 7.77928 20.3017 7.12648 18.2409 6.96008L14.2088 6.64008C12.7752 6.52488 12.4424 6.26888 12.4424 5.78248C12.4424 5.19368 12.9288 4.96328 13.7864 4.96328H21.0697V3.32488H13.9528C12.148 3.32488 10.5864 3.97768 10.5864 5.83368C10.5864 7.44648 11.764 8.15048 13.7352 8.30408L17.9721 8.63688C19.2265 8.73928 19.7513 9.03368 19.7513 9.62248C19.7513 10.1089 19.4057 10.4417 18.3305 10.4417H10.548Z" fill="url(#paint3_linear)"/>
|
|
230
|
+
</g>
|
|
231
|
+
<defs>
|
|
232
|
+
<linearGradient id="paint3_linear" x1="16" y1="2.08008" x2="16" y2="16.0001" gradientUnits="userSpaceOnUse">
|
|
233
|
+
<stop stop-color="#FFE7A8"/>
|
|
234
|
+
<stop offset="1" stop-color="#FFB800"/>
|
|
235
|
+
</linearGradient>
|
|
236
|
+
<clipPath id="clip3">
|
|
237
|
+
<rect width="32" height="16" fill="white"/>
|
|
238
|
+
</clipPath>
|
|
239
|
+
</defs>
|
|
240
|
+
</svg>`,
|
|
241
|
+
a: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="16" viewBox="0 0 32 16" fill="none">
|
|
242
|
+
<g clip-path="url(#clip4)">
|
|
243
|
+
<rect width="32" height="16" rx="8" fill="#7CCE14"/>
|
|
244
|
+
<mask id="mask4" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="32" height="16">
|
|
245
|
+
<rect width="32" height="16" rx="8" fill="#88DA20"/>
|
|
246
|
+
</mask>
|
|
247
|
+
<g mask="url(#mask4)">
|
|
248
|
+
<path d="M16 -9L33.3205 21H-1.32051L16 -9Z" fill="#88DA20"/>
|
|
249
|
+
<path d="M27.5 3L33.9952 14.25H21.0048L27.5 3Z" fill="#72C904"/>
|
|
250
|
+
<path d="M7.5 -2L11.3971 4.75H3.60289L7.5 -2Z" fill="#69BB00"/>
|
|
251
|
+
<path d="M9.5 13L13.3971 19.75H5.60289L9.5 13Z" fill="#69BB00"/>
|
|
252
|
+
</g>
|
|
253
|
+
<path d="M18.5418 5.49208C18.0138 4.47208 17.4018 3.75208 15.9978 3.75208C14.5938 3.75208 13.9698 4.47208 13.4538 5.49208L10.0938 12.0801H11.9298L12.9738 10.0521H19.0218L20.0658 12.0801H21.9138L18.5418 5.49208ZM18.2298 8.52808H13.7538L15.1458 5.84008C15.3258 5.49208 15.5538 5.27608 15.9978 5.27608C16.4418 5.27608 16.6698 5.49208 16.8498 5.84008L18.2298 8.52808Z" fill="#275227"/>
|
|
254
|
+
</g>
|
|
255
|
+
<defs>
|
|
256
|
+
<clipPath id="clip4">
|
|
257
|
+
<rect width="32" height="16" fill="white"/>
|
|
258
|
+
</clipPath>
|
|
259
|
+
</defs>
|
|
260
|
+
</svg>`,
|
|
261
|
+
};
|
|
262
|
+
return svgs[rank] || "";
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function getUserLevelHTML(level) {
|
|
266
|
+
const tierGradients = {
|
|
267
|
+
iron: "linear-gradient(#bab3ab, #bab3ab)",
|
|
268
|
+
bronze: "linear-gradient(#b88f7a, #855c47)",
|
|
269
|
+
silver: "linear-gradient(#e0e0eb, #a3a3c2)",
|
|
270
|
+
gold: "linear-gradient(#f0e4a8, #e0c952)",
|
|
271
|
+
platinum: "linear-gradient(#a8f0ef, #52e0df)",
|
|
272
|
+
rhodium: "linear-gradient(#d9f8d3, #a0cf96)",
|
|
273
|
+
radiant: "linear-gradient(#97dcff, #ed82ff)",
|
|
274
|
+
lustrous: "linear-gradient(#ffe600, #ed82ff)",
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
let tier = "iron";
|
|
278
|
+
if (level >= 110) tier = "lustrous";
|
|
279
|
+
else if (level >= 105) tier = "radiant";
|
|
280
|
+
else if (level >= 100) tier = "rhodium";
|
|
281
|
+
else if (level >= 80) tier = "platinum";
|
|
282
|
+
else if (level >= 60) tier = "gold";
|
|
283
|
+
else if (level >= 40) tier = "silver";
|
|
284
|
+
else if (level >= 20) tier = "bronze";
|
|
285
|
+
|
|
286
|
+
return `
|
|
287
|
+
<div class="user-level" title="Level ${level}">
|
|
288
|
+
<div class="user-level-bg" style="background: ${tierGradients[tier]}"></div>
|
|
289
|
+
<span class="user-level-text">${level}</span>
|
|
290
|
+
</div>
|
|
291
|
+
`;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// 用户数据,由Jinja2模板注入
|
|
295
|
+
const userData = {{user_json}};
|
|
296
|
+
|
|
297
|
+
function displayUserInfo(user) {
|
|
298
|
+
const userInfoDiv = document.getElementById("userInfo");
|
|
299
|
+
|
|
300
|
+
userInfoDiv.innerHTML = `
|
|
301
|
+
<div id="display" class="flex flex-col gap-2 p-2 relative z-10">
|
|
302
|
+
<div class="flex flex-row justify-between items-center">
|
|
303
|
+
<h2 class="text-2xl font-bold text-white">玩家信息</h2>
|
|
304
|
+
<h2 class="text-2xl font-bold text-white">${user.mode}</h2>
|
|
305
|
+
</div>
|
|
306
|
+
<!-- 用户基本信息 -->
|
|
307
|
+
<div class="flex flex-row gap-4 bg-white/20 rounded-lg p-2">
|
|
308
|
+
<div class="max-w-[100px] flex-shrink-0">
|
|
309
|
+
<img src="https://a.ppy.sh/${user.id}" alt="user" class="rounded-lg">
|
|
310
|
+
</div>
|
|
311
|
+
<div class="flex flex-col flex-grow justify-around min-w-0 text-white">
|
|
312
|
+
<div class="text-xl truncate">${user.username}</div>
|
|
313
|
+
${
|
|
314
|
+
user.team
|
|
315
|
+
? `
|
|
316
|
+
<div class="flex flex-row items-center gap-2">
|
|
317
|
+
<img src="${user.team.flag_url}" alt="team" class="w-[35px]">
|
|
318
|
+
<p class="text-xl truncate">${user.team.name}</p>
|
|
319
|
+
</div>
|
|
320
|
+
`
|
|
321
|
+
: ""
|
|
322
|
+
}
|
|
323
|
+
<div class="flex flex-row justify-between">
|
|
324
|
+
<div class="flex flex-row text-xl gap-2 items-center">
|
|
325
|
+
<img src="${flagUrl(user.country_code)}" alt="country" class="w-[25px]">
|
|
326
|
+
<p>#${user.statistics?.country_rank || 0} ${user.country_rank_change?user.country_rank_change:""}</p>
|
|
327
|
+
</div>
|
|
328
|
+
${
|
|
329
|
+
user.statistics?.variants
|
|
330
|
+
? `
|
|
331
|
+
<div class="hidden sm:flex flex-col">
|
|
332
|
+
<div class="text-xs">
|
|
333
|
+
4k: ${user.statistics?.variants?.find((key) => key.variant === "4k")?.pp || 0} /
|
|
334
|
+
#${user.statistics?.variants?.find((key) => key.variant === "4k")?.global_rank || 0} / ${user.country_code} #${user.statistics?.variants?.find((key) => key.variant == "4k")?.country_rank || 0}
|
|
335
|
+
</div>
|
|
336
|
+
<div class="text-xs">
|
|
337
|
+
7k: ${user.statistics?.variants?.find((key) => key.variant === "7k")?.pp || 0} /
|
|
338
|
+
#${user.statistics?.variants?.find((key) => key.variant === "7k")?.global_rank || 0} / ${user.country_code} #${user.statistics?.variants?.find((key) => key.variant == "7k")?.country_rank || 0}
|
|
339
|
+
</div>
|
|
340
|
+
</div>
|
|
341
|
+
`
|
|
342
|
+
: ""
|
|
343
|
+
}
|
|
344
|
+
</div>
|
|
345
|
+
</div>
|
|
346
|
+
</div>
|
|
347
|
+
|
|
348
|
+
<!-- 徽章 -->
|
|
349
|
+
${
|
|
350
|
+
user.badges && user.badges.length > 0
|
|
351
|
+
? `
|
|
352
|
+
<div class="flex flex-row bg-white/20 rounded-lg p-2 gap-2 flex-wrap">
|
|
353
|
+
${user.badges
|
|
354
|
+
.map((badge) => {
|
|
355
|
+
return `
|
|
356
|
+
<div>
|
|
357
|
+
<img src="${badge.image_url}" alt="${badge.description}" class="w-[75px]">
|
|
358
|
+
</div>
|
|
359
|
+
`;
|
|
360
|
+
})
|
|
361
|
+
.join("")}
|
|
362
|
+
</div>
|
|
363
|
+
`
|
|
364
|
+
: ""
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
<!-- 等级进度 -->
|
|
368
|
+
<div class="flex flex-row bg-white/20 rounded-lg p-2 justify-between items-center gap-4 text-white">
|
|
369
|
+
<div class="flex-grow">
|
|
370
|
+
<div class="text-sm mb-1">等级</div>
|
|
371
|
+
<div class="w-full bg-gray-700 rounded-full h-2">
|
|
372
|
+
<div class="bg-pink-400 h-2 rounded-full" style="width: ${user.statistics?.level.progress}%"></div>
|
|
373
|
+
</div>
|
|
374
|
+
<div class="text-xs mt-1">${user.statistics?.level.progress}%</div>
|
|
375
|
+
</div>
|
|
376
|
+
${getUserLevelHTML(user.statistics?.level.current || 0)}
|
|
377
|
+
</div>
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
<!-- 排名和评级 -->
|
|
381
|
+
<div class="flex flex-row bg-white/20 rounded-lg p-2 justify-between flex-wrap gap-2 text-white">
|
|
382
|
+
<div class="flex flex-col">
|
|
383
|
+
<div>世界排名</div>
|
|
384
|
+
${getRankDisplay(user)}
|
|
385
|
+
${user.rank_change ?
|
|
386
|
+
`<span class="text-sm">
|
|
387
|
+
${user.rank_change}
|
|
388
|
+
</span>` : ""}
|
|
389
|
+
</div>
|
|
390
|
+
<div class="flex flex-col">
|
|
391
|
+
<div>PP</div>
|
|
392
|
+
<div class="text-xl">${user.statistics?.pp.toLocaleString()}</div>
|
|
393
|
+
${user.pp_change ?
|
|
394
|
+
`<span class="text-sm">
|
|
395
|
+
${user.pp_change}
|
|
396
|
+
</span>` : ""}
|
|
397
|
+
</div>
|
|
398
|
+
<div class="flex flex-row gap-2">
|
|
399
|
+
<div class="flex flex-col items-center gap-1">
|
|
400
|
+
<div class="score-rank">${getScoreRankSVG("xh")}</div>
|
|
401
|
+
<div>${user.statistics?.grade_counts.ssh}</div>
|
|
402
|
+
</div>
|
|
403
|
+
<div class="flex flex-col items-center gap-1">
|
|
404
|
+
<div class="score-rank">${getScoreRankSVG("ss")}</div>
|
|
405
|
+
<div>${user.statistics?.grade_counts.ss}</div>
|
|
406
|
+
</div>
|
|
407
|
+
<div class="flex flex-col items-center gap-1">
|
|
408
|
+
<div class="score-rank">${getScoreRankSVG("x")}</div>
|
|
409
|
+
<div>${user.statistics?.grade_counts.sh}</div>
|
|
410
|
+
</div>
|
|
411
|
+
<div class="flex flex-col items-center gap-1">
|
|
412
|
+
<div class="score-rank">${getScoreRankSVG("s")}</div>
|
|
413
|
+
<div>${user.statistics?.grade_counts.s}</div>
|
|
414
|
+
</div>
|
|
415
|
+
<div class="flex flex-col items-center gap-1">
|
|
416
|
+
<div class="score-rank">${getScoreRankSVG("a")}</div>
|
|
417
|
+
<div>${user.statistics?.grade_counts.a}</div>
|
|
418
|
+
</div>
|
|
419
|
+
</div>
|
|
420
|
+
</div>
|
|
421
|
+
|
|
422
|
+
<!-- 详细统计 -->
|
|
423
|
+
<div class="flex flex-col gap-2 bg-white/20 rounded-lg p-2 text-white">
|
|
424
|
+
<div class="flex flex-row justify-between">
|
|
425
|
+
<div>Ranked 谱面总分</div>
|
|
426
|
+
<div>${user.statistics?.ranked_score.toLocaleString()}</div>
|
|
427
|
+
</div>
|
|
428
|
+
<div class="flex flex-row justify-between">
|
|
429
|
+
<div>准确率</div>
|
|
430
|
+
<div>${user.statistics?.hit_accuracy.toFixed(2)}%${user.acc_change?user.acc_change:""}</div>
|
|
431
|
+
</div>
|
|
432
|
+
<div class="flex flex-row justify-between">
|
|
433
|
+
<div>游戏次数</div>
|
|
434
|
+
<div>${user.statistics?.play_count.toLocaleString()}${user.pc_change?user.pc_change:""}</div>
|
|
435
|
+
</div>
|
|
436
|
+
<div class="flex flex-row justify-between">
|
|
437
|
+
<div>总分</div>
|
|
438
|
+
<div>${user.statistics?.total_score.toLocaleString()}</div>
|
|
439
|
+
</div>
|
|
440
|
+
<div class="flex flex-row justify-between">
|
|
441
|
+
<div>总命中次数</div>
|
|
442
|
+
<div>${user.statistics?.total_hits.toLocaleString()}${user.hits_change?user.hits_change:""}</div>
|
|
443
|
+
</div>
|
|
444
|
+
<div class="flex flex-row justify-between">
|
|
445
|
+
<div>游玩时间</div>
|
|
446
|
+
<div>${formatPlayTime(user.statistics?.play_time)}</div>
|
|
447
|
+
</div>
|
|
448
|
+
<div class="flex flex-row justify-between">
|
|
449
|
+
<div>每次游玩击打数</div>
|
|
450
|
+
<div>${(user.statistics?.total_hits / (user.statistics?.play_count || 1)).toFixed(2)}</div>
|
|
451
|
+
</div>
|
|
452
|
+
<div class="flex flex-row justify-between">
|
|
453
|
+
<div>最大连击</div>
|
|
454
|
+
<div>${user.statistics?.maximum_combo.toLocaleString()}</div>
|
|
455
|
+
</div>
|
|
456
|
+
<div class="flex flex-row justify-between">
|
|
457
|
+
<div>回放被观看次数</div>
|
|
458
|
+
<div>${user.statistics?.replays_watched_by_others.toLocaleString()}</div>
|
|
459
|
+
</div>
|
|
460
|
+
</div>
|
|
461
|
+
<span class="text-center text-sm text-white">${user.footer}</span>
|
|
462
|
+
</div>
|
|
463
|
+
`;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function flagUrl(countryCode) {
|
|
467
|
+
const chars = countryCode.toUpperCase().split("");
|
|
468
|
+
const hexEmojiChars = chars.map((chr) =>
|
|
469
|
+
(chr.codePointAt(0) + 127397).toString(16),
|
|
470
|
+
);
|
|
471
|
+
const baseFileName = hexEmojiChars.join("-");
|
|
472
|
+
return `https://osu.ppy.sh/assets/images/flags/${baseFileName}.svg`;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function formatPlayTime(seconds) {
|
|
476
|
+
// 检查输入,如果为 null/undefined/0,返回默认值
|
|
477
|
+
if (!seconds || seconds <= 0) {
|
|
478
|
+
return "0秒";
|
|
479
|
+
}
|
|
480
|
+
const units = [
|
|
481
|
+
{ unit: "天", seconds: 86400 }, // 24 * 60 * 60
|
|
482
|
+
{ unit: "小时", seconds: 3600 },
|
|
483
|
+
{ unit: "分钟", seconds: 60 },
|
|
484
|
+
{ unit: "秒", seconds: 1 }
|
|
485
|
+
];
|
|
486
|
+
|
|
487
|
+
let remainingSeconds = seconds;
|
|
488
|
+
let resultParts = [];
|
|
489
|
+
|
|
490
|
+
for (const { unit, seconds } of units) {
|
|
491
|
+
const value = Math.floor(remainingSeconds / seconds);
|
|
492
|
+
|
|
493
|
+
if (value > 0) {
|
|
494
|
+
const formattedValue = (unit === "天") ? value : String(value);
|
|
495
|
+
resultParts.push(`${formattedValue}${unit}`);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
remainingSeconds %= seconds;
|
|
499
|
+
}
|
|
500
|
+
return resultParts.join('');
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// 页面加载时渲染用户信息
|
|
504
|
+
displayUserInfo(userData);
|
|
505
|
+
</script>
|
|
506
|
+
</body>
|
|
507
|
+
</html>
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight:initial;--tw-content:""}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-blue-600:oklch(54.6% .245 262.881);--color-pink-400:oklch(71.8% .202 349.761);--color-pink-600:oklch(59.2% .249 .584);--color-gray-700:oklch(37.3% .034 259.733);--color-black:#000;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-bold:700;--radius-lg:.5rem;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.relative{position:relative}.z-0{z-index:0}.z-10{z-index:10}.mt-1{margin-top:calc(var(--spacing)*1)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.flex{display:flex}.hidden{display:none}.h-2{height:calc(var(--spacing)*2)}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-\[25px\]{width:25px}.w-\[35px\]{width:35px}.w-\[43px\]{width:43px}.w-\[45px\]{width:45px}.w-\[50px\]{width:50px}.w-\[53px\]{width:53px}.w-\[54px\]{width:54px}.w-\[66px\]{width:66px}.w-\[72px\]{width:72px}.w-\[73px\]{width:73px}.w-\[74px\]{width:74px}.w-\[75px\]{width:75px}.w-\[76px\]{width:76px}.w-\[86px\]{width:86px}.w-full{width:100%}.max-w-\[100px\]{max-width:100px}.max-w-\[365px\]{max-width:365px}.max-w-\[390px\]{max-width:390px}.max-w-\[410px\]{max-width:410px}.max-w-\[418px\]{max-width:418px}.max-w-\[425px\]{max-width:425px}.max-w-\[430px\]{max-width:430px}.max-w-\[440px\]{max-width:440px}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-gray-700{background-color:var(--color-gray-700)}.bg-pink-400{background-color:var(--color-pink-400)}.bg-pink-600{background-color:var(--color-pink-600)}.bg-white\/20{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.bg-white\/20{background-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.bg-cover{background-size:cover}.bg-center{background-position:50%}.bg-no-repeat{background-repeat:no-repeat}.p-2{padding:calc(var(--spacing)*2)}.p-4{padding:calc(var(--spacing)*4)}.text-center{text-align:center}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-white{color:var(--color-white)}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:inset-0:before{content:var(--tw-content);inset:calc(var(--spacing)*0)}.before\:bg-black:before{content:var(--tw-content);background-color:var(--color-black)}.before\:opacity-20:before{content:var(--tw-content);opacity:.2}.before\:opacity-30:before{content:var(--tw-content);opacity:.3}.before\:opacity-40:before{content:var(--tw-content);opacity:.4}.before\:opacity-50:before{content:var(--tw-content);opacity:.5}.before\:opacity-70:before{content:var(--tw-content);opacity:.7}.before\:content-\[\'\'\]:before{--tw-content:"";content:var(--tw-content)}@media (min-width:40rem){.sm\:flex{display:flex}}}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}
|
|
@@ -12,7 +12,7 @@ from ..schema import Beatmap
|
|
|
12
12
|
from ..schema.score import Mod
|
|
13
13
|
from ..beatmap_stats_moder import with_mods
|
|
14
14
|
from ..file import map_path, download_osu, get_projectimg
|
|
15
|
-
from .utils import crop_bg, is_close, stars_diff, draw_fillet, calc_songlen
|
|
15
|
+
from .utils import crop_bg, is_close, stars_diff, draw_fillet, calc_songlen, get_map_difficulty_arrays
|
|
16
16
|
from .static import (
|
|
17
17
|
Image,
|
|
18
18
|
MapBg,
|
|
@@ -23,6 +23,7 @@ from .static import (
|
|
|
23
23
|
Torus_SemiBold_25,
|
|
24
24
|
osufile,
|
|
25
25
|
extra_30,
|
|
26
|
+
Stars,
|
|
26
27
|
)
|
|
27
28
|
|
|
28
29
|
|
|
@@ -68,7 +69,7 @@ async def draw_map_info(mapid: int, mods: list[str], is_lazer) -> BytesIO:
|
|
|
68
69
|
# 模式
|
|
69
70
|
draw.text((50, 65), IconLs[FGM[mapinfo.mode]], font=extra_30, anchor="lt")
|
|
70
71
|
# 难度星星
|
|
71
|
-
stars_bg = stars_diff(ss_pp_info.difficulty.stars)
|
|
72
|
+
stars_bg = stars_diff(ss_pp_info.difficulty.stars, Stars)
|
|
72
73
|
stars_img = stars_bg.resize((80, 30))
|
|
73
74
|
im.alpha_composite(stars_img, (90, 65))
|
|
74
75
|
if ss_pp_info.difficulty.stars < 6.5:
|
|
@@ -84,13 +85,7 @@ async def draw_map_info(mapid: int, mods: list[str], is_lazer) -> BytesIO:
|
|
|
84
85
|
fill=color,
|
|
85
86
|
)
|
|
86
87
|
# cs, ar, od, hp
|
|
87
|
-
mapdiff =
|
|
88
|
-
original_mapdiff = [
|
|
89
|
-
original_mapinfo.cs,
|
|
90
|
-
original_mapinfo.drain,
|
|
91
|
-
original_mapinfo.accuracy,
|
|
92
|
-
original_mapinfo.ar,
|
|
93
|
-
]
|
|
88
|
+
mapdiff, original_mapdiff = get_map_difficulty_arrays(mapinfo, original_mapinfo)
|
|
94
89
|
|
|
95
90
|
for num, (original, new) in enumerate(zip(original_mapdiff, mapdiff)):
|
|
96
91
|
if is_close(new, original):
|
|
@@ -155,8 +150,11 @@ async def draw_map_info(mapid: int, mods: list[str], is_lazer) -> BytesIO:
|
|
|
155
150
|
if mods:
|
|
156
151
|
for mods_num, s_mods in enumerate(mods):
|
|
157
152
|
mods_bg = osufile / "mods" / f"{s_mods.acronym}.png"
|
|
158
|
-
|
|
159
|
-
|
|
153
|
+
try:
|
|
154
|
+
mods_img = Image.open(mods_bg).convert("RGBA")
|
|
155
|
+
im.alpha_composite(mods_img, (700 + 50 * mods_num, 295))
|
|
156
|
+
except FileNotFoundError:
|
|
157
|
+
pass
|
|
160
158
|
# mapper
|
|
161
159
|
icon_url = f"https://a.ppy.sh/{mapinfo.user_id}"
|
|
162
160
|
user_icon = await get_projectimg(icon_url)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from nonebot_plugin_htmlrender import get_new_page
|
|
5
|
+
|
|
6
|
+
from .utils import load_osu_file_and_setup_template
|
|
7
|
+
|
|
8
|
+
template_path = str(Path(__file__).parent / "osu_preview_templates")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
async def draw_osu_preview(beatmap_id, beatmapset_id) -> bytes:
|
|
12
|
+
osu_file, template = await load_osu_file_and_setup_template(template_path, beatmap_id, beatmapset_id)
|
|
13
|
+
img_selector = "img"
|
|
14
|
+
base_url = Path(template_path).as_uri() + "/"
|
|
15
|
+
worker_script_path = Path(template_path) / "gif.js" / "gif.worker.js"
|
|
16
|
+
|
|
17
|
+
# 读取 worker 脚本内容
|
|
18
|
+
with open(worker_script_path, encoding="utf-8") as f:
|
|
19
|
+
worker_script_content = f.read()
|
|
20
|
+
worker_base64 = base64.b64encode(worker_script_content.encode("utf-8")).decode("utf-8")
|
|
21
|
+
worker_data_uri = f"data:application/javascript;base64,{worker_base64}"
|
|
22
|
+
async with get_new_page(2) as page:
|
|
23
|
+
await page.goto(f"file://{template_path}")
|
|
24
|
+
await page.set_content(
|
|
25
|
+
await template.render_async(osu_file=osu_file, base_url=base_url, worker_data_uri=worker_data_uri),
|
|
26
|
+
wait_until="networkidle",
|
|
27
|
+
)
|
|
28
|
+
await page.wait_for_function(
|
|
29
|
+
f"() => document.querySelector('{img_selector}') &&"
|
|
30
|
+
f" document.querySelector('{img_selector}').src.startsWith('blob:')",
|
|
31
|
+
timeout=60000,
|
|
32
|
+
)
|
|
33
|
+
blob_url = await page.locator(img_selector).get_attribute("src")
|
|
34
|
+
base64_data = await page.evaluate(
|
|
35
|
+
"""async (url) => {
|
|
36
|
+
const response = await fetch(url);
|
|
37
|
+
const blob = await response.blob();
|
|
38
|
+
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
const reader = new FileReader();
|
|
41
|
+
reader.onloadend = () => {
|
|
42
|
+
resolve(reader.result.split(',')[1]);
|
|
43
|
+
};
|
|
44
|
+
reader.readAsDataURL(blob);
|
|
45
|
+
});
|
|
46
|
+
}""",
|
|
47
|
+
blob_url,
|
|
48
|
+
)
|
|
49
|
+
gif_bytes = base64.b64decode(base64_data)
|
|
50
|
+
return gif_bytes
|