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,170 @@
|
|
|
1
|
+
function Standard(osu)
|
|
2
|
+
{
|
|
3
|
+
Beatmap.call(this, osu);
|
|
4
|
+
|
|
5
|
+
let savedDefaultColor = window.localStorage.getItem("DefaultColor");
|
|
6
|
+
this.useDefaultColor = (savedDefaultColor) ? parseInt(savedDefaultColor) : 0;
|
|
7
|
+
|
|
8
|
+
let savedColorChange = window.localStorage.getItem("ColorChange");
|
|
9
|
+
this.colorChange = (savedColorChange) ? parseInt(savedColorChange) : 0;
|
|
10
|
+
|
|
11
|
+
if (this.Colors.length && !this.useDefaultColor) {
|
|
12
|
+
this.Colors.push(this.Colors.shift());
|
|
13
|
+
}
|
|
14
|
+
else
|
|
15
|
+
{
|
|
16
|
+
this.Colors = Standard.DEFAULT_COLORS;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
var combo = 1,
|
|
20
|
+
comboIndex = -1,
|
|
21
|
+
setComboIndex = 1;
|
|
22
|
+
for (var i = 0; i < this.HitObjects.length; i++)
|
|
23
|
+
{
|
|
24
|
+
var hitObject = this.HitObjects[i];
|
|
25
|
+
if (hitObject instanceof Spinner)
|
|
26
|
+
{
|
|
27
|
+
setComboIndex = 1;
|
|
28
|
+
}
|
|
29
|
+
else if (hitObject.newCombo || setComboIndex)
|
|
30
|
+
{
|
|
31
|
+
combo = 1;
|
|
32
|
+
comboIndex = ((comboIndex + 1) + hitObject.comboSkip) % this.Colors.length;
|
|
33
|
+
setComboIndex = 0;
|
|
34
|
+
}
|
|
35
|
+
hitObject.combo = combo++;
|
|
36
|
+
hitObject.color = (this.colorChange) ? this.Colors[i % this.Colors.length] : this.Colors[comboIndex];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
// calculate stacks
|
|
41
|
+
// https://gist.github.com/peppy/1167470
|
|
42
|
+
for (var i = this.HitObjects.length - 1; i > 0; i--)
|
|
43
|
+
{
|
|
44
|
+
var hitObject = this.HitObjects[i];
|
|
45
|
+
if (hitObject.stack != 0 || hitObject instanceof Spinner)
|
|
46
|
+
{
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
for (var n = i - 1; n >= 0; n--)
|
|
51
|
+
{
|
|
52
|
+
var hitObjectN = this.HitObjects[n];
|
|
53
|
+
if (hitObjectN instanceof Spinner)
|
|
54
|
+
{
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (hitObject.time - hitObjectN.endTime > this.approachTime * this.StackLeniency)
|
|
59
|
+
{
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (hitObject.position.distanceTo(hitObjectN.endPosition) < Standard.STACK_LENIENCE)
|
|
64
|
+
{
|
|
65
|
+
if (hitObjectN instanceof Slider)
|
|
66
|
+
{
|
|
67
|
+
var offset = hitObject.stack - hitObjectN.stack + 1;
|
|
68
|
+
for (var j = n + 1; j <= i; j++)
|
|
69
|
+
{
|
|
70
|
+
var hitObjectJ = this.HitObjects[j];
|
|
71
|
+
if (hitObjectJ.position.distanceTo(hitObjectN.endPosition) < Standard.STACK_LENIENCE)
|
|
72
|
+
{
|
|
73
|
+
hitObjectJ.stack -= offset;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
hitObjectN.stack = hitObject.stack + 1;
|
|
80
|
+
hitObject = hitObjectN;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this.circleRadius = this.circleDiameter / 2;
|
|
86
|
+
this.circleBorder = this.circleRadius / 8;
|
|
87
|
+
this.shadowBlur = this.circleRadius / 15;
|
|
88
|
+
}
|
|
89
|
+
Standard.prototype = Object.create(Beatmap.prototype, {
|
|
90
|
+
approachTime: {
|
|
91
|
+
get: function()
|
|
92
|
+
{
|
|
93
|
+
return this.ApproachRate < 5
|
|
94
|
+
? 1800 - this.ApproachRate * 120
|
|
95
|
+
: 1200 - (this.ApproachRate - 5) * 150;
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
// https://github.com/itdelatrisu/opsu/commit/8892973d98e04ebaa6656fe2a23749e61a122705
|
|
99
|
+
circleDiameter: {
|
|
100
|
+
get: function()
|
|
101
|
+
{
|
|
102
|
+
return 108.848 - this.CircleSize * 8.9646;
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
stackOffset: {
|
|
106
|
+
get: function()
|
|
107
|
+
{
|
|
108
|
+
return this.circleDiameter / 20;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
Standard.prototype.constructor = Standard;
|
|
113
|
+
Standard.prototype.hitObjectTypes = {};
|
|
114
|
+
Standard.ID = 0;
|
|
115
|
+
Beatmap.modes[Standard.ID] = Standard;
|
|
116
|
+
Standard.DEFAULT_COLORS = [
|
|
117
|
+
'rgb(0,202,0)',
|
|
118
|
+
'rgb(18,124,255)',
|
|
119
|
+
'rgb(242,24,57)',
|
|
120
|
+
'rgb(255,255,0)'
|
|
121
|
+
];
|
|
122
|
+
Standard.STACK_LENIENCE = 3;
|
|
123
|
+
Standard.prototype.update = function(ctx)
|
|
124
|
+
{
|
|
125
|
+
ctx.shadowColor = '#666';
|
|
126
|
+
ctx.lineCap = 'round';
|
|
127
|
+
ctx.lineJoin = 'round';
|
|
128
|
+
try
|
|
129
|
+
{
|
|
130
|
+
// this code will fail in Firefox(<~ 44)
|
|
131
|
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=941146
|
|
132
|
+
ctx.font = this.circleRadius + 'px "Comic Sans MS", cursive, sans-serif';
|
|
133
|
+
}
|
|
134
|
+
catch (e) {}
|
|
135
|
+
ctx.textAlign = 'center';
|
|
136
|
+
ctx.textBaseline = 'middle';
|
|
137
|
+
ctx.translate((Beatmap.WIDTH - Beatmap.MAX_X) / 2, (Beatmap.HEIGHT - Beatmap.MAX_Y) / 2);
|
|
138
|
+
};
|
|
139
|
+
Standard.prototype.draw = function(time, ctx)
|
|
140
|
+
{
|
|
141
|
+
if (typeof this.tmp.first == 'undefined')
|
|
142
|
+
{
|
|
143
|
+
this.tmp.first = 0;
|
|
144
|
+
this.tmp.last = -1;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
while (this.tmp.first < this.HitObjects.length)
|
|
148
|
+
{
|
|
149
|
+
var hitObject = this.HitObjects[this.tmp.first];
|
|
150
|
+
if (time <= hitObject.endTime + hitObject.__proto__.constructor.FADE_OUT_TIME)
|
|
151
|
+
{
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
this.tmp.first++;
|
|
155
|
+
}
|
|
156
|
+
while (this.tmp.last + 1 < this.HitObjects.length &&
|
|
157
|
+
time >= this.HitObjects[this.tmp.last + 1].time - this.approachTime)
|
|
158
|
+
{
|
|
159
|
+
this.tmp.last++;
|
|
160
|
+
}
|
|
161
|
+
for (var i = this.tmp.last; i >= this.tmp.first; i--)
|
|
162
|
+
{
|
|
163
|
+
var hitObject = this.HitObjects[i];
|
|
164
|
+
if (time > hitObject.endTime + hitObject.__proto__.constructor.FADE_OUT_TIME)
|
|
165
|
+
{
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
hitObject.draw(time, ctx);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
function DonKat(data, beatmap)
|
|
2
|
+
{
|
|
3
|
+
HitCircle.call(this, data, beatmap);
|
|
4
|
+
|
|
5
|
+
}
|
|
6
|
+
DonKat.prototype = Object.create(HitCircle.prototype, {
|
|
7
|
+
don: {
|
|
8
|
+
get: function()
|
|
9
|
+
{
|
|
10
|
+
return !this.kai | 0;
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
kai: {
|
|
14
|
+
get: function()
|
|
15
|
+
{
|
|
16
|
+
return ((this.hitSound & 10) != 0) | 0;
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
dai: {
|
|
20
|
+
get: function()
|
|
21
|
+
{
|
|
22
|
+
return this.hitSound & 4;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
DonKat.prototype.constructor = DonKat;
|
|
27
|
+
DonKat.ID = 1;
|
|
28
|
+
Taiko.prototype.hitObjectTypes[DonKat.ID] = DonKat;
|
|
29
|
+
DonKat.prototype.draw = function(scroll, ctx)
|
|
30
|
+
{
|
|
31
|
+
var diam = Taiko.DIAMETER * (this.dai ? 1.5 : 1);
|
|
32
|
+
var border = 3;
|
|
33
|
+
ctx.beginPath();
|
|
34
|
+
ctx.arc(this.beatmap.calcX(this.position.x, scroll), 0, diam / 2 - border / 2, -Math.PI, Math.PI);
|
|
35
|
+
ctx.fillStyle = Taiko.DEFAULT_COLORS[this.kai];
|
|
36
|
+
ctx.fill();
|
|
37
|
+
ctx.strokeStyle = '#fff';
|
|
38
|
+
ctx.lineWidth = border;
|
|
39
|
+
ctx.stroke();
|
|
40
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
function Drumroll(data, beatmap)
|
|
2
|
+
{
|
|
3
|
+
Slider.call(this, data, beatmap);
|
|
4
|
+
|
|
5
|
+
}
|
|
6
|
+
Drumroll.prototype = Object.create(Slider.prototype, {});
|
|
7
|
+
Drumroll.prototype.constructor = Drumroll;
|
|
8
|
+
Drumroll.ID = 2;
|
|
9
|
+
Taiko.prototype.hitObjectTypes[Drumroll.ID] = Drumroll;
|
|
10
|
+
Drumroll.prototype.draw = function(scroll, ctx)
|
|
11
|
+
{
|
|
12
|
+
var diam = Taiko.DIAMETER;
|
|
13
|
+
var border = 3;
|
|
14
|
+
|
|
15
|
+
ctx.beginPath();
|
|
16
|
+
ctx.moveTo(this.beatmap.calcX(this.position.x, scroll), 0);
|
|
17
|
+
ctx.lineTo(this.beatmap.calcX(this.endPosition.x, scroll), 0);
|
|
18
|
+
|
|
19
|
+
ctx.strokeStyle = '#333';
|
|
20
|
+
ctx.lineWidth = diam;
|
|
21
|
+
ctx.stroke();
|
|
22
|
+
|
|
23
|
+
ctx.strokeStyle = Taiko.DEFAULT_COLORS[2];
|
|
24
|
+
ctx.lineWidth = diam - border;
|
|
25
|
+
ctx.stroke();
|
|
26
|
+
|
|
27
|
+
ctx.beginPath();
|
|
28
|
+
ctx.arc(this.beatmap.calcX(this.position.x, scroll), 0, diam / 2 - border / 2, -Math.PI, Math.PI);
|
|
29
|
+
ctx.fillStyle = Taiko.DEFAULT_COLORS[2];
|
|
30
|
+
ctx.fill();
|
|
31
|
+
ctx.strokeStyle = '#fff';
|
|
32
|
+
ctx.lineWidth = border;
|
|
33
|
+
ctx.stroke();
|
|
34
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
function Shaker(data, beatmap)
|
|
2
|
+
{
|
|
3
|
+
Spinner.call(this, data, beatmap);
|
|
4
|
+
|
|
5
|
+
}
|
|
6
|
+
Shaker.prototype = Object.create(Spinner.prototype, {});
|
|
7
|
+
Shaker.prototype.constructor = Shaker;
|
|
8
|
+
Shaker.ID = 8;
|
|
9
|
+
Taiko.prototype.hitObjectTypes[Shaker.ID] = Shaker;
|
|
10
|
+
Shaker.prototype.draw = function(scroll, ctx)
|
|
11
|
+
{
|
|
12
|
+
var ds = this.beatmap.calcX(this.position.x, scroll);
|
|
13
|
+
if (ds > 0)
|
|
14
|
+
{
|
|
15
|
+
var diam = Taiko.DIAMETER * 1.5;
|
|
16
|
+
var border = 3;
|
|
17
|
+
ctx.beginPath();
|
|
18
|
+
ctx.arc(this.beatmap.calcX(this.position.x, scroll), 0, diam / 2 - border / 2, -Math.PI, Math.PI);
|
|
19
|
+
ctx.fillStyle = Taiko.DEFAULT_COLORS[2];
|
|
20
|
+
ctx.fill();
|
|
21
|
+
ctx.strokeStyle = '#fff';
|
|
22
|
+
ctx.lineWidth = border;
|
|
23
|
+
ctx.stroke();
|
|
24
|
+
}
|
|
25
|
+
else
|
|
26
|
+
{
|
|
27
|
+
ctx.save();
|
|
28
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
29
|
+
ctx.translate(Beatmap.WIDTH / 2, Beatmap.HEIGHT / 2);
|
|
30
|
+
// Spinner
|
|
31
|
+
ctx.beginPath();
|
|
32
|
+
ctx.arc(0, 0,
|
|
33
|
+
Spinner.RADIUS - Spinner.BORDER_WIDTH / 2, -Math.PI, Math.PI);
|
|
34
|
+
ctx.globalCompositeOperation = 'destination-over';
|
|
35
|
+
ctx.shadowBlur = 0;
|
|
36
|
+
ctx.fillStyle = 'rgba(0,0,0,.4)';
|
|
37
|
+
ctx.fill();
|
|
38
|
+
// Border
|
|
39
|
+
ctx.shadowBlur = Spinner.BORDER_WIDTH;
|
|
40
|
+
ctx.strokeStyle = '#fff';
|
|
41
|
+
ctx.lineWidth = Spinner.BORDER_WIDTH;
|
|
42
|
+
ctx.stroke();
|
|
43
|
+
// Approach
|
|
44
|
+
if (ds < 0 && scroll <= this.endPosition.x)
|
|
45
|
+
{
|
|
46
|
+
var scale = 1 + ds / this.beatmap.calcX(this.endPosition.x, this.position.x);
|
|
47
|
+
ctx.beginPath();
|
|
48
|
+
ctx.arc(0, 0,
|
|
49
|
+
(Spinner.RADIUS - Spinner.BORDER_WIDTH / 2) * scale, -Math.PI, Math.PI);
|
|
50
|
+
ctx.globalCompositeOperation = 'source-over';
|
|
51
|
+
ctx.shadowBlur = 3;
|
|
52
|
+
ctx.strokeStyle = '#fff';
|
|
53
|
+
ctx.lineWidth = (Spinner.BORDER_WIDTH / 2) * scale;
|
|
54
|
+
ctx.stroke();
|
|
55
|
+
}
|
|
56
|
+
ctx.restore();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
function Taiko(osu)
|
|
2
|
+
{
|
|
3
|
+
Scroll.call(this, osu);
|
|
4
|
+
|
|
5
|
+
for (var i = 0; i < this.HitObjects.length; i++)
|
|
6
|
+
{
|
|
7
|
+
var hitObject = this.HitObjects[i];
|
|
8
|
+
hitObject.position.x = this.scrollAt(hitObject.time);
|
|
9
|
+
hitObject.endPosition.x = this.scrollAt(hitObject.endTime);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
Taiko.prototype = Object.create(Scroll.prototype, {
|
|
13
|
+
|
|
14
|
+
});
|
|
15
|
+
Taiko.prototype.constructor = Taiko;
|
|
16
|
+
Taiko.prototype.hitObjectTypes = {};
|
|
17
|
+
Taiko.ID = 1;
|
|
18
|
+
Beatmap.modes[Taiko.ID] = Taiko;
|
|
19
|
+
Taiko.DEFAULT_COLORS = [
|
|
20
|
+
'#eb452c',
|
|
21
|
+
'#438eac',
|
|
22
|
+
'#fcb806'
|
|
23
|
+
];
|
|
24
|
+
Taiko.DIAMETER = 56;
|
|
25
|
+
Taiko.prototype.calcX = function(x, scroll)
|
|
26
|
+
{
|
|
27
|
+
return (x - scroll) * 20 * (260) / 1000 / (this.SliderMultiplier * 8);
|
|
28
|
+
};
|
|
29
|
+
Taiko.prototype.update = function(ctx)
|
|
30
|
+
{
|
|
31
|
+
ctx.shadowColor = '#666';
|
|
32
|
+
ctx.lineCap = 'round';
|
|
33
|
+
ctx.lineJoin = 'round';
|
|
34
|
+
ctx.textAlign = 'center';
|
|
35
|
+
ctx.textBaseline = 'middle';
|
|
36
|
+
ctx.translate(160, 200);
|
|
37
|
+
};
|
|
38
|
+
Taiko.prototype.draw = function(time, ctx)
|
|
39
|
+
{
|
|
40
|
+
if (typeof this.tmp.first == 'undefined')
|
|
41
|
+
{
|
|
42
|
+
this.tmp.first = 0;
|
|
43
|
+
this.tmp.last = -1;
|
|
44
|
+
this.tmp.barLine = 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
var scroll = this.scrollAt(time);
|
|
48
|
+
while (this.tmp.first < this.HitObjects.length &&
|
|
49
|
+
time > this.HitObjects[this.tmp.first].endTime)
|
|
50
|
+
{
|
|
51
|
+
this.tmp.first++;
|
|
52
|
+
}
|
|
53
|
+
while (this.tmp.last + 1 < this.HitObjects.length)
|
|
54
|
+
{
|
|
55
|
+
var hitObject = this.HitObjects[this.tmp.last + 1];
|
|
56
|
+
if (this.calcX(hitObject.position.x, scroll) > Beatmap.WIDTH)
|
|
57
|
+
{
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
this.tmp.last++;
|
|
61
|
+
}
|
|
62
|
+
while (this.tmp.barLine < this.barLines.length &&
|
|
63
|
+
this.calcX(this.barLines[this.tmp.barLine], scroll) < -Taiko.DIAMETER)
|
|
64
|
+
{
|
|
65
|
+
this.tmp.barLine++;
|
|
66
|
+
}
|
|
67
|
+
for (var i = this.tmp.barLine; i < this.barLines.length && this.calcX(this.barLines[i], scroll) < Beatmap.WIDTH; i++)
|
|
68
|
+
{
|
|
69
|
+
var barLine = this.calcX(this.barLines[i], scroll);
|
|
70
|
+
ctx.beginPath();
|
|
71
|
+
ctx.moveTo(barLine, -Taiko.DIAMETER);
|
|
72
|
+
ctx.lineTo(barLine, Taiko.DIAMETER);
|
|
73
|
+
ctx.strokeStyle = '#fff';
|
|
74
|
+
ctx.lineWidth = 1;
|
|
75
|
+
ctx.stroke();
|
|
76
|
+
}
|
|
77
|
+
for (var i = this.tmp.last; i >= this.tmp.first; i--)
|
|
78
|
+
{
|
|
79
|
+
var hitObject = this.HitObjects[i];
|
|
80
|
+
if (time > hitObject.endTime)
|
|
81
|
+
{
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
hitObject.draw(scroll, ctx);
|
|
85
|
+
}
|
|
86
|
+
ctx.clearRect(-160, -200, Taiko.DIAMETER * 2, 400);
|
|
87
|
+
};
|
|
88
|
+
Taiko.prototype.processBG = function(ctx)
|
|
89
|
+
{
|
|
90
|
+
var offset = - Taiko.DIAMETER;
|
|
91
|
+
//ctx.drawImage(ctx.canvas, -160, offset, ctx.canvas.width, ctx.canvas.height);
|
|
92
|
+
//ctx.beginPath();
|
|
93
|
+
//ctx.rect(0, 0, Beatmap.WIDTH, offset);
|
|
94
|
+
//ctx.fillStyle = '#000';
|
|
95
|
+
//ctx.fill();
|
|
96
|
+
|
|
97
|
+
// rail
|
|
98
|
+
ctx.beginPath();
|
|
99
|
+
ctx.rect(-160, offset, Beatmap.WIDTH, Taiko.DIAMETER * 2);
|
|
100
|
+
ctx.strokeStyle = '#ddd';
|
|
101
|
+
ctx.lineWidth = 8;
|
|
102
|
+
ctx.stroke();
|
|
103
|
+
ctx.fillStyle = '#000';
|
|
104
|
+
ctx.fill();
|
|
105
|
+
|
|
106
|
+
// drum
|
|
107
|
+
ctx.beginPath();
|
|
108
|
+
ctx.rect(-160, offset, Taiko.DIAMETER * 2, Taiko.DIAMETER * 2);
|
|
109
|
+
ctx.fillStyle = '#ff0080';
|
|
110
|
+
ctx.fill();
|
|
111
|
+
|
|
112
|
+
var border = 6;
|
|
113
|
+
ctx.beginPath();
|
|
114
|
+
ctx.arc(0, 0, Taiko.DIAMETER / 2, -Math.PI, Math.PI);
|
|
115
|
+
ctx.fillStyle = 'rgba(255,255,255,.2)';
|
|
116
|
+
ctx.fill();
|
|
117
|
+
ctx.strokeStyle = 'rgba(255,255,255,.2)';
|
|
118
|
+
ctx.lineWidth = border;
|
|
119
|
+
ctx.stroke();
|
|
120
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Math.hypot = Math.hypot || function()
|
|
2
|
+
{
|
|
3
|
+
var power = 0;
|
|
4
|
+
for (var i = 0; i < arguments.length; i++)
|
|
5
|
+
{
|
|
6
|
+
power += arguments[i] * arguments[i];
|
|
7
|
+
}
|
|
8
|
+
return Math.sqrt(power);
|
|
9
|
+
};
|
|
10
|
+
Math.lerp = Math.lerp || function(a, b, t)
|
|
11
|
+
{
|
|
12
|
+
if (a instanceof Point)
|
|
13
|
+
{
|
|
14
|
+
return new Point(Math.lerp(a.x, b.x, t), Math.lerp(a.y, b.y, t));
|
|
15
|
+
}
|
|
16
|
+
return a + (b - a) * t;
|
|
17
|
+
};
|
|
18
|
+
/** Calculate point C's direction by line AB
|
|
19
|
+
* @return {Number}
|
|
20
|
+
* 1 C is counter-clockwise to AB
|
|
21
|
+
* 0 C is parallel to AB
|
|
22
|
+
* -1 C is clockwise to AB
|
|
23
|
+
*/
|
|
24
|
+
Math.ccw = function(a, b, c)
|
|
25
|
+
{
|
|
26
|
+
var ret = (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
|
|
27
|
+
if (ret > 0)
|
|
28
|
+
{
|
|
29
|
+
return 1;
|
|
30
|
+
}
|
|
31
|
+
if (ret < 0)
|
|
32
|
+
{
|
|
33
|
+
return -1;
|
|
34
|
+
}
|
|
35
|
+
return 0;
|
|
36
|
+
};
|
|
37
|
+
Math.clamp = function(num, min, max) {
|
|
38
|
+
if (num < min) return min;
|
|
39
|
+
if (num > max) return max;
|
|
40
|
+
return num;
|
|
41
|
+
}
|
|
42
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#Polyfill
|
|
43
|
+
if (!HTMLCanvasElement.prototype.toBlob)
|
|
44
|
+
{
|
|
45
|
+
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
|
|
46
|
+
value: function (callback, type, quality)
|
|
47
|
+
{
|
|
48
|
+
|
|
49
|
+
var binStr = atob(this.toDataURL(type, quality).split(',')[1]),
|
|
50
|
+
len = binStr.length,
|
|
51
|
+
arr = new Uint8Array(len);
|
|
52
|
+
|
|
53
|
+
for (var i = 0; i < len; i++)
|
|
54
|
+
{
|
|
55
|
+
arr[i] = binStr.charCodeAt(i);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
callback(new Blob([ arr ], { type: type || 'image/png' }));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
7
|
+
<base href="{{ base_url }}">
|
|
8
|
+
<meta name="robots" content="nofollow, noindex, noarchive">
|
|
9
|
+
<title>gif生成测试 网址后加#bid</title>
|
|
10
|
+
</head>
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
<body class="h">
|
|
14
|
+
<img id="img"></img>
|
|
15
|
+
|
|
16
|
+
<script src="js/util.js"></script>
|
|
17
|
+
|
|
18
|
+
<script src="js/beatmap/beatmap.js"></script>
|
|
19
|
+
<script src="js/beatmap/timingpoint.js"></script>
|
|
20
|
+
<script src="js/beatmap/hitobject.js"></script>
|
|
21
|
+
<script src="js/beatmap/point.js"></script>
|
|
22
|
+
<script src="js/beatmap/scroll.js"></script>
|
|
23
|
+
|
|
24
|
+
<script src="js/standard/standard.js"></script>
|
|
25
|
+
<script src="js/standard/hitcircle.js"></script>
|
|
26
|
+
<script src="js/standard/slider.js"></script>
|
|
27
|
+
<script src="js/standard/curve/curve.js"></script>
|
|
28
|
+
<script src="js/standard/curve/equaldistancemulticurve.js"></script>
|
|
29
|
+
<script src="js/standard/curve/linearbezier.js"></script>
|
|
30
|
+
<script src="js/standard/curve/catmullcurve.js"></script>
|
|
31
|
+
<script src="js/standard/curve/curvetype.js"></script>
|
|
32
|
+
<script src="js/standard/curve/bezier2.js"></script>
|
|
33
|
+
<script src="js/standard/curve/centripetalcatmullrom.js"></script>
|
|
34
|
+
<script src="js/standard/curve/circumstancedcircle.js"></script>
|
|
35
|
+
<script src="js/standard/spinner.js"></script>
|
|
36
|
+
|
|
37
|
+
<script src="js/taiko/taiko.js"></script>
|
|
38
|
+
<script src="js/taiko/donkat.js"></script>
|
|
39
|
+
<script src="js/taiko/drumroll.js"></script>
|
|
40
|
+
<script src="js/taiko/shaker.js"></script>
|
|
41
|
+
|
|
42
|
+
<script src="js/catch/LegacyRandom.js"></script>
|
|
43
|
+
<script src="js/catch/catch.js"></script>
|
|
44
|
+
<script src="js/catch/fruit.js"></script>
|
|
45
|
+
<script src="js/catch/bananashower.js"></script>
|
|
46
|
+
<script src="js/catch/juicestream.js"></script>
|
|
47
|
+
<script src="js/catch/PalpableCatchHitObject.js"></script>
|
|
48
|
+
|
|
49
|
+
<script src="js/mania/mania.js"></script>
|
|
50
|
+
<script src="js/mania/hitnote.js"></script>
|
|
51
|
+
<script src="js/mania/holdnote.js"></script>
|
|
52
|
+
|
|
53
|
+
<script src="js/preview.js"></script>
|
|
54
|
+
<script src="gif.js/gif.js"></script>
|
|
55
|
+
|
|
56
|
+
<script>
|
|
57
|
+
const scaleValue = 0.5;
|
|
58
|
+
const durationValue = 10000;
|
|
59
|
+
const qualityValue = 10;
|
|
60
|
+
const timeSpanValue = 50;
|
|
61
|
+
|
|
62
|
+
const createImg = function () {
|
|
63
|
+
let preview = new Preview(scaleValue);
|
|
64
|
+
const osufile = `{{ osu_file }}`;
|
|
65
|
+
preview.load(osufile, function () {
|
|
66
|
+
let actualStartTime;
|
|
67
|
+
const previewEndTime = preview.previewTime + durationValue;
|
|
68
|
+
if (previewEndTime <= preview.endTime) {
|
|
69
|
+
// 使用谱面预览时间
|
|
70
|
+
actualStartTime = preview.previewTime;
|
|
71
|
+
} else {
|
|
72
|
+
// 预览时间加上持续时间超过谱面结束时间,使用用户指定的开始时间
|
|
73
|
+
actualStartTime = preview.startTime;
|
|
74
|
+
}
|
|
75
|
+
const actualEndTime = durationValue === -1 ? preview.endTime : Math.min(actualStartTime + durationValue, preview.endTime);
|
|
76
|
+
let gif = new GIF({
|
|
77
|
+
workers: 4,
|
|
78
|
+
workerScript: "{{ worker_data_uri }}",
|
|
79
|
+
quality: qualityValue,
|
|
80
|
+
width: preview.screen.width * scaleValue,
|
|
81
|
+
height: preview.screen.height * scaleValue,
|
|
82
|
+
//transparent: "0x000000",
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const totalFrames = Math.ceil((actualEndTime - actualStartTime) / timeSpanValue);
|
|
86
|
+
let currentFrame = 0;
|
|
87
|
+
|
|
88
|
+
// 添加帧
|
|
89
|
+
while (currentFrame <= totalFrames) {
|
|
90
|
+
const t = actualStartTime + currentFrame * timeSpanValue;
|
|
91
|
+
preview.at(t);
|
|
92
|
+
|
|
93
|
+
gif.addFrame(preview.ctx, {
|
|
94
|
+
copy: true,
|
|
95
|
+
delay: timeSpanValue
|
|
96
|
+
});
|
|
97
|
+
currentFrame++;
|
|
98
|
+
}
|
|
99
|
+
gif.on('finished', function (blob) {
|
|
100
|
+
document.getElementById("img").src = URL.createObjectURL(blob);
|
|
101
|
+
});
|
|
102
|
+
gif.render();
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
window.addEventListener('hashchange', createImg);
|
|
106
|
+
createImg();
|
|
107
|
+
</script>
|
|
108
|
+
</body>
|
|
109
|
+
|
|
110
|
+
</html>
|
|
@@ -348,7 +348,8 @@ class PlayerRatingCalculation:
|
|
|
348
348
|
if user_info is None:
|
|
349
349
|
continue
|
|
350
350
|
if entry.user_id == user_id:
|
|
351
|
-
|
|
351
|
+
# Optimize: calculate sum directly instead of creating list
|
|
352
|
+
average_scores.append(sum(entry.score for entry in game.scores) / len(game.scores))
|
|
352
353
|
user_scores.append(entry.score)
|
|
353
354
|
number_of_games_by_user += 1
|
|
354
355
|
|
|
@@ -397,7 +398,8 @@ class PlayerRatingCalculation:
|
|
|
397
398
|
if entry.user_id == user_id:
|
|
398
399
|
for mod in entry.mods:
|
|
399
400
|
all_played_mods.add(mod)
|
|
400
|
-
|
|
401
|
+
# Optimize: calculate sum directly instead of creating list
|
|
402
|
+
average_scores.append(sum(entry.score for entry in game.scores) / len(game.scores))
|
|
401
403
|
user_scores.append(entry.score)
|
|
402
404
|
number_of_games_by_user += 1
|
|
403
405
|
# 获取加时赛数据
|
|
@@ -454,7 +456,8 @@ class PlayerRatingCalculation:
|
|
|
454
456
|
if user_info is None:
|
|
455
457
|
continue
|
|
456
458
|
if entry.user_id == user_id:
|
|
457
|
-
|
|
459
|
+
# Optimize: calculate median directly instead of creating list
|
|
460
|
+
median_scores.append(median(entry.score for entry in game.scores))
|
|
458
461
|
user_scores.append(entry.score)
|
|
459
462
|
number_of_games_by_user += 1
|
|
460
463
|
|