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.
Files changed (97) hide show
  1. nonebot_plugin_osubot/api.py +13 -7
  2. nonebot_plugin_osubot/config.py +10 -10
  3. nonebot_plugin_osubot/draw/bmap.py +20 -22
  4. nonebot_plugin_osubot/draw/bp.py +3 -13
  5. nonebot_plugin_osubot/draw/catch_preview.py +2 -16
  6. nonebot_plugin_osubot/draw/echarts.py +8 -1
  7. nonebot_plugin_osubot/draw/info.py +59 -207
  8. nonebot_plugin_osubot/draw/info_templates/index.html +507 -0
  9. nonebot_plugin_osubot/draw/info_templates/output.css +2 -0
  10. nonebot_plugin_osubot/draw/map.py +9 -11
  11. nonebot_plugin_osubot/draw/osu_preview.py +50 -0
  12. nonebot_plugin_osubot/draw/osu_preview_templates/css/style.css +258 -0
  13. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/README.md +109 -0
  14. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js +3 -0
  15. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js.map +1 -0
  16. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js +3 -0
  17. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js.map +1 -0
  18. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/beatmap.js +211 -0
  19. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/hitobject.js +29 -0
  20. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/point.js +55 -0
  21. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/scroll.js +45 -0
  22. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/timingpoint.js +35 -0
  23. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/LegacyRandom.js +81 -0
  24. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/PalpableCatchHitObject.js +53 -0
  25. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/bananashower.js +33 -0
  26. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/catch.js +211 -0
  27. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/fruit.js +21 -0
  28. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/juicestream.js +176 -0
  29. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/hitnote.js +21 -0
  30. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/holdnote.js +37 -0
  31. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/mania.js +164 -0
  32. nonebot_plugin_osubot/draw/osu_preview_templates/js/preview.js +61 -0
  33. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/bezier2.js +33 -0
  34. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/catmullcurve.js +34 -0
  35. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/centripetalcatmullrom.js +30 -0
  36. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/circumstancedcircle.js +47 -0
  37. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curve.js +25 -0
  38. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curvetype.js +17 -0
  39. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/equaldistancemulticurve.js +70 -0
  40. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/linearbezier.js +40 -0
  41. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/hitcircle.js +85 -0
  42. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/slider.js +120 -0
  43. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/spinner.js +56 -0
  44. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/standard.js +170 -0
  45. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/donkat.js +40 -0
  46. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/drumroll.js +34 -0
  47. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/shaker.js +58 -0
  48. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/taiko.js +120 -0
  49. nonebot_plugin_osubot/draw/osu_preview_templates/js/util.js +61 -0
  50. nonebot_plugin_osubot/draw/osu_preview_templates/pic.html +110 -0
  51. nonebot_plugin_osubot/draw/rating.py +6 -3
  52. nonebot_plugin_osubot/draw/score.py +23 -81
  53. nonebot_plugin_osubot/draw/taiko_preview.py +14 -13
  54. nonebot_plugin_osubot/draw/templates/bpa_chart.html +1 -1
  55. nonebot_plugin_osubot/draw/utils.py +162 -16
  56. nonebot_plugin_osubot/file.py +184 -31
  57. nonebot_plugin_osubot/mania/__init__.py +9 -10
  58. nonebot_plugin_osubot/matcher/__init__.py +2 -0
  59. nonebot_plugin_osubot/matcher/bp_analyze.py +14 -9
  60. nonebot_plugin_osubot/matcher/guess.py +250 -294
  61. nonebot_plugin_osubot/matcher/map_convert.py +21 -13
  62. nonebot_plugin_osubot/matcher/medal.py +1 -1
  63. nonebot_plugin_osubot/matcher/osudl.py +5 -4
  64. nonebot_plugin_osubot/matcher/pr.py +0 -4
  65. nonebot_plugin_osubot/matcher/preview.py +10 -3
  66. nonebot_plugin_osubot/matcher/recommend.py +7 -12
  67. nonebot_plugin_osubot/mods.py +62 -61
  68. nonebot_plugin_osubot/network/first_response.py +1 -1
  69. nonebot_plugin_osubot/osufile/mods/AP.png +0 -0
  70. nonebot_plugin_osubot/osufile/mods/CL.png +0 -0
  71. nonebot_plugin_osubot/osufile/mods/DT.png +0 -0
  72. nonebot_plugin_osubot/osufile/mods/EZ.png +0 -0
  73. nonebot_plugin_osubot/osufile/mods/FI.png +0 -0
  74. nonebot_plugin_osubot/osufile/mods/FL.png +0 -0
  75. nonebot_plugin_osubot/osufile/mods/HD.png +0 -0
  76. nonebot_plugin_osubot/osufile/mods/HR.png +0 -0
  77. nonebot_plugin_osubot/osufile/mods/HT.png +0 -0
  78. nonebot_plugin_osubot/osufile/mods/MR.png +0 -0
  79. nonebot_plugin_osubot/osufile/mods/NC.png +0 -0
  80. nonebot_plugin_osubot/osufile/mods/NF.png +0 -0
  81. nonebot_plugin_osubot/osufile/mods/PF.png +0 -0
  82. nonebot_plugin_osubot/osufile/mods/RX.png +0 -0
  83. nonebot_plugin_osubot/osufile/mods/SD.png +0 -0
  84. nonebot_plugin_osubot/osufile/mods/SO.png +0 -0
  85. nonebot_plugin_osubot/osufile/mods/TD.png +0 -0
  86. nonebot_plugin_osubot/osufile/mods/V2.png +0 -0
  87. nonebot_plugin_osubot/pp.py +7 -0
  88. nonebot_plugin_osubot/schema/__init__.py +0 -2
  89. nonebot_plugin_osubot/schema/beatmapsets.py +42 -0
  90. nonebot_plugin_osubot/schema/draw_info.py +54 -0
  91. nonebot_plugin_osubot/schema/score.py +2 -0
  92. nonebot_plugin_osubot/schema/user.py +1 -0
  93. {nonebot_plugin_osubot-6.22.1.dist-info → nonebot_plugin_osubot-6.26.4.dist-info}/METADATA +18 -17
  94. {nonebot_plugin_osubot-6.22.1.dist-info → nonebot_plugin_osubot-6.26.4.dist-info}/RECORD +95 -52
  95. nonebot_plugin_osubot-6.26.4.dist-info/WHEEL +4 -0
  96. nonebot_plugin_osubot/schema/sayo_beatmap.py +0 -59
  97. 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
- average_scores.append(sum([entry.score for entry in game.scores]) / len(game.scores))
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
- average_scores.append(sum([entry.score for entry in game.scores]) / len(game.scores))
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
- median_scores.append(median([entry.score for entry in game.scores]))
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