nonebot-plugin-osubot 6.22.3__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 (100) hide show
  1. nonebot_plugin_osubot/api.py +12 -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 +1 -0
  92. nonebot_plugin_osubot/schema/user.py +1 -0
  93. {nonebot_plugin_osubot-6.22.3.dist-info → nonebot_plugin_osubot-6.26.4.dist-info}/METADATA +18 -17
  94. {nonebot_plugin_osubot-6.22.3.dist-info → nonebot_plugin_osubot-6.26.4.dist-info}/RECORD +95 -55
  95. nonebot_plugin_osubot-6.26.4.dist-info/WHEEL +4 -0
  96. nonebot_plugin_osubot/data/osu/1849145.osz +0 -0
  97. nonebot_plugin_osubot/data/osu/1849145.zip +0 -0
  98. nonebot_plugin_osubot/draw/templates/t.html +0 -58
  99. nonebot_plugin_osubot/schema/sayo_beatmap.py +0 -59
  100. nonebot_plugin_osubot-6.22.3.dist-info/WHEEL +0 -4
@@ -0,0 +1,33 @@
1
+ function BananaShower(data, beatmap) {
2
+ Spinner.call(this, data, beatmap);
3
+
4
+ this.endTime = data[5] | 0;
5
+ this.duration = this.endTime - this.time;
6
+
7
+ this.nested = [];
8
+ }
9
+ BananaShower.prototype = Object.create(Spinner.prototype);
10
+ BananaShower.prototype.constructor = BananaShower;
11
+ BananaShower.ID = 8;
12
+ Catch.prototype.hitObjectTypes[BananaShower.ID] = BananaShower;
13
+ BananaShower.prototype.buildNested = function() {
14
+ this.nested = [];
15
+ let spacing = this.duration;
16
+ while (spacing > 100) spacing /= 2;
17
+ if (spacing <= 0) return;
18
+ let time = this.time;
19
+ let i = 0;
20
+ while (time <= this.endTime) {
21
+ this.nested.push(new PalpableCatchHitObject({
22
+ type: "Banana",
23
+ time,
24
+ x: 0,
25
+ color: 'rgb(255,240,0)',
26
+ radius: this.beatmap.bananaRadius,
27
+ }, this.beatmap));
28
+
29
+ time += spacing;
30
+ i++;
31
+ }
32
+ return this;
33
+ };
@@ -0,0 +1,211 @@
1
+ function Catch(osu) {
2
+ Beatmap.call(this, osu);
3
+
4
+ let savedDefaultColor = window.localStorage.getItem("DefaultColor");
5
+ this.useDefaultColor = (savedDefaultColor) ? parseInt(savedDefaultColor) : 0;
6
+
7
+ let savedColorChange = window.localStorage.getItem("ColorChange");
8
+ this.colorChange = (savedColorChange) ? parseInt(savedColorChange) : 0;
9
+
10
+ if (this.Colors.length && !this.useDefaultColor) {
11
+ this.Colors.push(this.Colors.shift());
12
+ }
13
+ else {
14
+ this.Colors = Catch.DEFAULT_COLORS;
15
+ }
16
+
17
+ this.circleRadius = this.circleDiameter / 2 - 4;
18
+ this.smallRadius = this.circleRadius / 2;
19
+ this.tinyRadius = this.smallRadius / 2;
20
+ this.bananaRadius = this.circleRadius * 0.8;
21
+
22
+ this.CATCHER_HEIGHT = Beatmap.HEIGHT / 8;
23
+ this.FALLOUT_TIME = (this.CATCHER_HEIGHT / Beatmap.HEIGHT) * this.approachTime;
24
+
25
+ var combo = 1,
26
+ comboIndex = -1,
27
+ setComboIndex = 1;
28
+ for (var i = 0; i < this.HitObjects.length; i++) {
29
+ let hitObject = this.HitObjects[i];
30
+ if (hitObject instanceof BananaShower) {
31
+ setComboIndex = 1;
32
+ }
33
+ else if (hitObject.newCombo || setComboIndex) {
34
+ combo = 1;
35
+ comboIndex = ((comboIndex + 1) + hitObject.comboSkip) % this.Colors.length;
36
+ setComboIndex = 0;
37
+ }
38
+ hitObject.combo = combo++;
39
+ hitObject.color = (this.colorChange) ? this.Colors[i % this.Colors.length] : this.Colors[comboIndex];
40
+
41
+ if (hitObject instanceof JuiceStream || hitObject instanceof BananaShower) {
42
+ hitObject.buildNested();
43
+ }
44
+ }
45
+
46
+ this.CATCHER_BASE_SIZE = 106.75;
47
+ this.ALLOWED_CATCH_RANGE = 0.8;
48
+ this.HYPER_DASH_TRANSITION_DURATION = 180;
49
+ this.calculateScale = 1.0 - 0.7 * (this.CircleSize - 5) / 5;
50
+ this.catchWidth = this.CATCHER_BASE_SIZE * Math.abs(this.calculateScale) * this.ALLOWED_CATCH_RANGE;
51
+ this.halfCatcherWidth = this.catchWidth / 2;
52
+ this.halfCatcherWidth /= this.ALLOWED_CATCH_RANGE;
53
+ this.BASE_DASH_SPEED = 1;
54
+ this.BASE_WALK_SPEED = 0.5;
55
+
56
+ // sliders & spins xoffset
57
+ this.RNG_SEED = 1337;
58
+ var rng = new LegacyRandom(this.RNG_SEED);
59
+
60
+ for (var i = 0; i < this.HitObjects.length; i++) {
61
+ let hitObject = this.HitObjects[i];
62
+ // console.log(hitObject.nested)
63
+ if (hitObject instanceof BananaShower) {
64
+ hitObject.nested.forEach(banana => {
65
+ banana.x += (rng.NextDouble() * Beatmap.MAX_X);
66
+ rng.Next(); // osu!stable retrieved a random banana type
67
+ rng.Next(); // osu!stable retrieved a random banana rotation
68
+ rng.Next(); // osu!stable retrieved a random banana colour
69
+ });
70
+ }
71
+ else if (hitObject instanceof JuiceStream) {
72
+ hitObject.nested.forEach(item => {
73
+ if (item.type === "TinyDroplet") item.x += Math.clamp(rng.Next(-20, 20), -item.x, Beatmap.MAX_X - item.x);
74
+ else if (item.type === "Droplet") rng.Next(); // osu!stable retrieved a random droplet rotation
75
+ });
76
+ }
77
+ }
78
+
79
+ // catch objects
80
+ this.palpableObjects = [];
81
+ this.fullCatchObjects = [];
82
+ for (var i = 0; i < this.HitObjects.length; i++) {
83
+ let hitObject = this.HitObjects[i];
84
+ if (hitObject instanceof Fruit) {
85
+ let pch = new PalpableCatchHitObject({
86
+ type: "Fruit",
87
+ time: hitObject.time,
88
+ x: hitObject.position.x,
89
+ color: hitObject.color,
90
+ radius: this.circleRadius,
91
+ }, this);
92
+
93
+ this.palpableObjects.push(pch);
94
+ this.fullCatchObjects.push(pch);
95
+ }
96
+ else if (hitObject instanceof BananaShower) {
97
+ hitObject.nested.forEach(banana => {
98
+ this.fullCatchObjects.push(banana);
99
+ });
100
+ }
101
+ else if (hitObject instanceof JuiceStream) {
102
+ hitObject.nested.forEach(item => {
103
+ this.fullCatchObjects.push(item);
104
+ if (item.type != "TinyDroplet") this.palpableObjects.push(item);
105
+ });
106
+ }
107
+ }
108
+
109
+ this.palpableObjects.sort((a, b) => a.time - b.time);
110
+ this.fullCatchObjects.sort((a, b) => a.time - b.time);
111
+
112
+ // hyperdash
113
+ let lastDirection = 0;
114
+ let lastExcess = this.halfCatcherWidth;
115
+
116
+ for (let i = 0; i < this.palpableObjects.length - 1; i++) {
117
+ var currentObject = this.palpableObjects[i];
118
+ var nextObject = this.palpableObjects[i + 1];
119
+
120
+ currentObject.hyperDash = false;
121
+
122
+ let thisDirection = nextObject.x > currentObject.x ? 1 : -1;
123
+ let timeToNext = nextObject.time - currentObject.time - 1000 / 60 / 4; // 1/4th of a frame of grace time, taken from osu-stable
124
+ let distanceToNext = Math.abs(nextObject.x - currentObject.x) - (lastDirection == thisDirection ? lastExcess : this.halfCatcherWidth);
125
+ let distanceToHyper = timeToNext * this.BASE_DASH_SPEED - distanceToNext;
126
+
127
+ if (distanceToHyper < 0) {
128
+ currentObject.hyperDash = true;
129
+ lastExcess = this.halfCatcherWidth;
130
+ }
131
+ else {
132
+ lastExcess = Math.clamp(distanceToHyper, 0, this.halfCatcherWidth);
133
+ }
134
+
135
+ lastDirection = thisDirection;
136
+ }
137
+
138
+ }
139
+ Catch.prototype = Object.create(Beatmap.prototype, {
140
+ approachTime: { // droptime
141
+ get: function () {
142
+ return this.ApproachRate < 5
143
+ ? 1800 - this.ApproachRate * 120
144
+ : 1200 - (this.ApproachRate - 5) * 150;
145
+ }
146
+ },
147
+ // https://github.com/itdelatrisu/opsu/commit/8892973d98e04ebaa6656fe2a23749e61a122705
148
+ circleDiameter: {
149
+ get: function () {
150
+ return 108.848 - this.CircleSize * 8.9646;
151
+ }
152
+ }
153
+ });
154
+ Catch.prototype.constructor = Catch;
155
+ Catch.prototype.hitObjectTypes = {};
156
+ Catch.ID = 2;
157
+ Beatmap.modes[Catch.ID] = Catch;
158
+ Catch.DEFAULT_COLORS = [
159
+ 'rgb(255,210,128)',
160
+ 'rgb(128,255,128)',
161
+ 'rgb(128,191,255)',
162
+ 'rgb(191,128,255)'
163
+ ];
164
+ Catch.prototype.update = function (ctx) {
165
+ ctx.translate((Beatmap.WIDTH - Beatmap.MAX_X) / 2, (Beatmap.HEIGHT - Beatmap.MAX_Y) / 2);
166
+ };
167
+ Catch.prototype.draw = function (time, ctx) {
168
+ if (typeof this.tmp.first == 'undefined') {
169
+ this.tmp.first = 0;
170
+ this.tmp.last = -1;
171
+ }
172
+
173
+ while (this.tmp.first < this.fullCatchObjects.length) {
174
+ var catchHitObject = this.fullCatchObjects[this.tmp.first];
175
+ if (time <= catchHitObject.time + this.FALLOUT_TIME) {
176
+ break;
177
+ }
178
+ this.tmp.first++;
179
+ }
180
+ while (this.tmp.last + 1 < this.fullCatchObjects.length &&
181
+ time >= this.fullCatchObjects[this.tmp.last + 1].time - this.approachTime * 1.1) {
182
+ this.tmp.last++;
183
+ }
184
+ for (var i = this.tmp.last; i >= this.tmp.first; i--) {
185
+ var catchHitObject = this.fullCatchObjects[i];
186
+ if (time > catchHitObject.time + this.FALLOUT_TIME) {
187
+ continue;
188
+ }
189
+ catchHitObject.draw(time, ctx);
190
+ }
191
+ };
192
+ Catch.prototype.processBG = function (ctx) {
193
+ let xoffset = (Beatmap.WIDTH - Beatmap.MAX_X) / 2;
194
+ let yoffset = (Beatmap.HEIGHT - Beatmap.MAX_Y) / 2;
195
+ // line
196
+ ctx.beginPath();
197
+ ctx.moveTo(-xoffset, Beatmap.HEIGHT - this.CATCHER_HEIGHT - yoffset);
198
+ ctx.lineTo(Beatmap.WIDTH - xoffset, Beatmap.HEIGHT - this.CATCHER_HEIGHT - yoffset);
199
+ ctx.strokeStyle = '#fff';
200
+ ctx.lineWidth = 1;
201
+ ctx.stroke();
202
+ // plate
203
+ let plateHeight = 20;
204
+ ctx.beginPath();
205
+ ctx.rect(Beatmap.WIDTH / 2 - this.catchWidth / 2 - xoffset, Beatmap.HEIGHT - this.CATCHER_HEIGHT - plateHeight / 2 - yoffset, this.catchWidth, plateHeight);
206
+ ctx.strokeStyle = '#fff';
207
+ ctx.lineWidth = 8;
208
+ ctx.stroke();
209
+ ctx.fillStyle = '#fff';
210
+ ctx.fill();
211
+ };
@@ -0,0 +1,21 @@
1
+ function Fruit(data, beatmap)
2
+ {
3
+ HitObject.call(this, data, beatmap);
4
+ }
5
+ Fruit.prototype = Object.create(HitObject.prototype, {
6
+ newCombo: {
7
+ get: function()
8
+ {
9
+ return this.flag & 4;
10
+ }
11
+ },
12
+ comboSkip: {
13
+ get: function()
14
+ {
15
+ return this.flag >> 4;
16
+ }
17
+ }
18
+ });
19
+ Fruit.prototype.constructor = Fruit;
20
+ Fruit.ID = 1;
21
+ Catch.prototype.hitObjectTypes[Fruit.ID] = Fruit;
@@ -0,0 +1,176 @@
1
+ function JuiceStream(data, beatmap)
2
+ {
3
+ Slider.call(this, data, beatmap);
4
+
5
+ var points = data[5].split('|');
6
+ var sliderType = points[0];
7
+ points[0] = this.position;
8
+ for (var i = 1; i < points.length; i++)
9
+ {
10
+ points[i] = new Point(points[i].split(':'));
11
+ }
12
+ this.repeat = data[6] | 0;
13
+ this.pixelLength = +data[7];
14
+
15
+ this.timingPoint = this.beatmap.timingPointAt(this.time);
16
+ this.beatLength = this.timingPoint.beatLength;
17
+ this.timingPointStart = this.timingPoint.time;
18
+
19
+ this.sliderTime = this.beatLength * ( this.pixelLength / this.beatmap.SliderMultiplier ) / 100;
20
+ this.velocityFactor = 100 * this.beatmap.SliderMultiplier / this.beatLength;
21
+ this.tickDistanceFactor = 100 * this.beatmap.SliderMultiplier / this.beatmap.SliderTickRate;
22
+ this.velocity = this.velocityFactor * this.timingPoint.sliderVelocity;
23
+ this.tickDistance = this.tickDistanceFactor * this.timingPoint.sliderVelocity;
24
+
25
+ this.endTime = this.time + this.sliderTime * this.repeat;
26
+ this.duration = this.endTime - this.time;
27
+
28
+ this.spanCount = parseInt(this.repeat);
29
+
30
+ this.curve = Curve.parse(sliderType, points, this.pixelLength);
31
+
32
+ this.endPosition = this.curve.pointAt(1);
33
+
34
+ this.max_length = 100000;
35
+ let length = Math.min(this.max_length, this.pixelLength);
36
+ this.tickDistance = Math.clamp(this.tickDistance, 0, length);
37
+ this.minDistanceFromEnd = this.velocity * 10;
38
+
39
+ this.events = [];
40
+ this.events.push({type: "head", time: this.time, pathProgress: 0});
41
+ if (this.tickDistance != 0) {
42
+ for (let span = 0; span < this.spanCount; span++) {
43
+ let spanStartTime = this.time + span * this.sliderTime;
44
+ let reversed = span % 2 == 1;
45
+ let ticks = this.generateTicks(span, spanStartTime, this.sliderTime, reversed, length, this.tickDistance, this.minDistanceFromEnd);
46
+ if (reversed) ticks = ticks.reverse();
47
+ this.events.push(...ticks);
48
+ if (span < this.spanCount - 1)
49
+ {
50
+ this.events.push({
51
+ type: "repeat",
52
+ time: spanStartTime + this.sliderTime,
53
+ pathProgress: (span + 1) % 2
54
+ });
55
+ }
56
+ }
57
+ }
58
+
59
+ let legacyLastTickOffset = 36;
60
+ let finalSpanIndex = this.spanCount - 1;
61
+ let finalSpanStartTime = this.time + finalSpanIndex * this.sliderTime;
62
+ let finalSpanEndTime = Math.max(this.time + this.duration / 2, (finalSpanStartTime + this.sliderTime) - legacyLastTickOffset);
63
+ let finalProgress = (finalSpanEndTime - finalSpanStartTime) / this.sliderTime;
64
+
65
+ if (this.spanCount % 2 == 0) finalProgress = 1 - finalProgress;
66
+
67
+ this.events.push({
68
+ type: "legacyLastTick",
69
+ time: finalSpanEndTime,
70
+ pathProgress: finalProgress
71
+ });
72
+
73
+ this.events.push({
74
+ type: "tail",
75
+ time: this.endTime,
76
+ pathProgress: this.spanCount % 2
77
+ });
78
+
79
+ this.nested = [];
80
+ }
81
+ JuiceStream.prototype = Object.create(Slider.prototype);
82
+ JuiceStream.prototype.constructor = JuiceStream;
83
+ JuiceStream.ID = 2;
84
+ Catch.prototype.hitObjectTypes[JuiceStream.ID] = JuiceStream;
85
+ JuiceStream.prototype.generateTicks = function(spanIndex, spanStartTime, spanDuration, reversed, length, tickDistance, minDistanceFromEnd) {
86
+ let ticks = [];
87
+ for (let d = tickDistance; d <= length; d += tickDistance) {
88
+ if (d >= length - minDistanceFromEnd)
89
+ break;
90
+
91
+ let pathProgress = d / length;
92
+ let timeProgress = reversed ? 1 - pathProgress : pathProgress;
93
+
94
+ ticks.push({type: "tick", time: spanStartTime + timeProgress * spanDuration, pathProgress});
95
+ }
96
+ return ticks;
97
+ }
98
+
99
+ JuiceStream.prototype.buildNested = function() {
100
+ this.nested = [];
101
+
102
+ let lastEvent = null;
103
+ for(let i = 0; i < this.events.length; i++) {
104
+ // generate tiny droplets since the last point
105
+ if (lastEvent != null)
106
+ {
107
+ let sinceLastTick = this.events[i].time - lastEvent.time;
108
+ if (sinceLastTick > 80)
109
+ {
110
+ let timeBetweenTiny = sinceLastTick;
111
+ while (timeBetweenTiny > 100) timeBetweenTiny /= 2;
112
+ for (let t = timeBetweenTiny; t < sinceLastTick; t += timeBetweenTiny) {
113
+ let repeat = (t + lastEvent.time - this.time) * this.repeat / this.duration;
114
+ repeat %= 2;
115
+ if (repeat > 1) repeat = 2 - repeat;
116
+ var point = this.curve.pointAt(repeat);
117
+ this.nested.push(new PalpableCatchHitObject({
118
+ type: "TinyDroplet",
119
+ time: t + lastEvent.time,
120
+ x: point.x,
121
+ // x: this.curve.pointAt(lastEvent.pathProgress + (t / sinceLastTick) * (this.events[i].pathProgress - lastEvent.pathProgress)).x,
122
+ color: this.color,
123
+ radius: this.beatmap.tinyRadius,
124
+ }, this.beatmap));
125
+ }
126
+ }
127
+ }
128
+
129
+ // this also includes LegacyLastTick and this is used for TinyDroplet generation above.
130
+ // this means that the final segment of TinyDroplets are increasingly mistimed where LegacyLastTickOffset is being applied.
131
+ lastEvent = this.events[i];
132
+
133
+ switch (this.events[i].type)
134
+ {
135
+ case "tick":
136
+ this.nested.push(new PalpableCatchHitObject({
137
+ type: "Droplet",
138
+ time: this.events[i].time,
139
+ x: this.curve.pointAt(this.events[i].pathProgress).x,
140
+ color: this.color,
141
+ radius: this.beatmap.smallRadius,
142
+ }, this.beatmap));
143
+ break;
144
+
145
+ case "head":
146
+ case "tail":
147
+ case "repeat":
148
+ this.nested.push(new PalpableCatchHitObject({
149
+ type: "Fruit",
150
+ time: this.events[i].time,
151
+ x: this.curve.pointAt(this.events[i].pathProgress).x,
152
+ color: this.color,
153
+ radius: this.beatmap.circleRadius,
154
+ }, this.beatmap));
155
+ break;
156
+ }
157
+ }
158
+
159
+ /* TODO BUG!!!
160
+ * 在预览 #4057684 时第一个滑条出现了
161
+ * PalpableCatchHitObject {beatmap: Catch, type: 'TinyDroplet', time: 464.57142857142895, …}
162
+ * PalpableCatchHitObject {beatmap: Catch, type: 'Droplet', time: 464.571428571429, …}
163
+ * 物件数量偏差导致后续随机数错误
164
+ * 暂时找不到原因,可能因为计算精度问题,临时手动将其剔除
165
+ */
166
+ let tmp_droplets = this.nested.filter((item) => item.type === "Droplet");
167
+ this.nested = this.nested.filter((item) => {
168
+ if (item.type != "TinyDroplet") return true;
169
+ for (let td = 0; td < tmp_droplets.length; td++) {
170
+ if (Math.abs(item.time - tmp_droplets[td].time) < 0.01) return false;
171
+ }
172
+ return true;
173
+ });
174
+
175
+ return this;
176
+ }
@@ -0,0 +1,21 @@
1
+ function HitNote(data, beatmap)
2
+ {
3
+ HitObject.call(this, data, beatmap);
4
+
5
+ this.column = Math.max(1, Math.min((this.position.x / this.beatmap.columnSize + 1) | 0, this.beatmap.keyCount)) - 1;
6
+ }
7
+ HitNote.prototype = Object.create(HitObject.prototype);
8
+ HitNote.prototype.constructor = HitNote;
9
+ HitNote.ID = 1;
10
+ Mania.prototype.hitObjectTypes[HitNote.ID] = HitNote;
11
+ HitNote.prototype.draw = function(scroll, ctx)
12
+ {
13
+ ctx.beginPath();
14
+ ctx.rect(this.position.x, this.beatmap.calcY(this.position.y, scroll) - Mania.COLUMN_WIDTH / 3,
15
+ Mania.COLUMN_WIDTH, Mania.COLUMN_WIDTH / 3);
16
+ ctx.fillStyle = this.color;
17
+ ctx.fill();
18
+ ctx.strokeStyle = '#ccc';
19
+ ctx.lineWidth = 1;
20
+ ctx.stroke();
21
+ };
@@ -0,0 +1,37 @@
1
+ function HoldNote(data, beatmap)
2
+ {
3
+ HitNote.call(this, data, beatmap);
4
+
5
+ this.endTime = data[5].split(':')[0] | 0;
6
+ }
7
+ HoldNote.prototype = Object.create(HitNote.prototype);
8
+ HoldNote.prototype.constructor = HoldNote;
9
+ HoldNote.ID = 128;
10
+ Mania.prototype.hitObjectTypes[HoldNote.ID] = HoldNote;
11
+ HoldNote.WIDTH_SCALE = 0.8;
12
+ HoldNote.OPACITY = 0.88;
13
+ HoldNote.prototype.draw = function(scroll, ctx)
14
+ {
15
+ var sy = this.beatmap.calcY(this.position.y, scroll) - Mania.COLUMN_WIDTH / 3,
16
+ ey = this.beatmap.calcY(this.endPosition.y, scroll) - Mania.COLUMN_WIDTH / 3;
17
+
18
+ var w = Mania.COLUMN_WIDTH * HoldNote.WIDTH_SCALE;
19
+ ctx.globalAlpha = HoldNote.OPACITY;
20
+ ctx.beginPath();
21
+ ctx.rect(this.position.x + (Mania.COLUMN_WIDTH - w) / 2, ey, w, sy - ey);
22
+ ctx.fillStyle = this.color;
23
+ ctx.fill();
24
+ ctx.globalAlpha = 1;
25
+
26
+ ctx.beginPath();
27
+ ctx.rect(this.position.x, sy, Mania.COLUMN_WIDTH, Mania.COLUMN_WIDTH / 3);
28
+ ctx.fill();
29
+ ctx.strokeStyle = '#ccc';
30
+ ctx.lineWidth = 1;
31
+ ctx.stroke();
32
+
33
+ ctx.beginPath();
34
+ ctx.rect(this.position.x, ey, Mania.COLUMN_WIDTH, Mania.COLUMN_WIDTH / 3);
35
+ ctx.fill();
36
+ ctx.stroke();
37
+ };
@@ -0,0 +1,164 @@
1
+ function Mania(osu)
2
+ {
3
+ Scroll.call(this, osu);
4
+
5
+
6
+ this.scrollSpeed = Mania.SCROLL_SPEED;
7
+ //this.columnStart = Mania.COLUMN_START;
8
+ this.columnStart = (Beatmap.WIDTH - Mania.COLUMN_WIDTH * this.keyCount) / 2
9
+
10
+ for (var i = 0; i < this.keyCount; i++)
11
+ {
12
+ this.Colors[i] = Mania.DEFAULT_COLORS[i & 1];
13
+ }
14
+ var p = this.keyCount / 2;
15
+ if (this.keyCount & 1)
16
+ {
17
+ this.Colors[p | 0] = Mania.DEFAULT_COLORS[2];
18
+ }
19
+ else
20
+ {
21
+ this.Colors = this.Colors.slice(0, p).concat(this.Colors.slice(p - 1));
22
+ }
23
+
24
+
25
+ for (var i = 0; i < this.HitObjects.length; i++)
26
+ {
27
+ var hitObject = this.HitObjects[i];
28
+ hitObject.color = this.Colors[hitObject.column];
29
+ hitObject.position.x = Mania.COLUMN_WIDTH * hitObject.column;
30
+ hitObject.position.y = this.scrollAt(hitObject.time);
31
+ hitObject.endPosition.y = this.scrollAt(hitObject.endTime);
32
+ }
33
+ }
34
+ Mania.prototype = Object.create(Scroll.prototype, {
35
+ keyCount: {
36
+ get: function()
37
+ {
38
+ return this.CircleSize;
39
+ }
40
+ },
41
+ columnSize: {
42
+ get: function()
43
+ {
44
+ return Beatmap.MAX_X / this.keyCount;
45
+ }
46
+ }
47
+ });
48
+ Mania.prototype.constructor = Mania;
49
+ Mania.prototype.hitObjectTypes = {};
50
+ Mania.ID = 3;
51
+ Beatmap.modes[Mania.ID] = Mania;
52
+ Mania.DEFAULT_COLORS = [
53
+ '#5bf',
54
+ '#ccc',
55
+ '#da2'
56
+ ];
57
+ Mania.COLUMN_START = 130;
58
+ Mania.HIT_POSITION = 400;
59
+ Mania.COLUMN_WIDTH = 30;
60
+ let savedSpeed = window.localStorage.getItem("SCROLL_SPEED");
61
+ Mania.SCROLL_SPEED = (savedSpeed) ? parseInt(savedSpeed) : 20;
62
+ Mania.prototype.calcY = function(y, scroll)
63
+ {
64
+ return Mania.HIT_POSITION - (y - scroll) * this.scrollSpeed * 0.035;
65
+ };
66
+ Mania.prototype.update = function(ctx)
67
+ {
68
+ ctx.translate(this.columnStart, 0);
69
+ };
70
+ Mania.prototype.draw = function(time, ctx)
71
+ {
72
+ if (typeof this.tmp.first == 'undefined')
73
+ {
74
+ this.tmp.first = 0;
75
+ this.tmp.last = -1;
76
+ this.tmp.barLine = 0;
77
+ }
78
+
79
+ var scroll = this.scrollAt(time);
80
+ while (this.tmp.first < this.HitObjects.length &&
81
+ time > this.HitObjects[this.tmp.first].endTime)
82
+ {
83
+ this.tmp.first++;
84
+ }
85
+ while (this.tmp.last + 1 < this.HitObjects.length)
86
+ {
87
+ var hitObject = this.HitObjects[this.tmp.last + 1];
88
+ if (this.calcY(hitObject.position.y, scroll) < -Mania.COLUMN_WIDTH)
89
+ {
90
+ break;
91
+ }
92
+ this.tmp.last++;
93
+ }
94
+ while (this.tmp.barLine < this.barLines.length &&
95
+ this.calcY(this.barLines[this.tmp.barLine], scroll) > Beatmap.MAX_Y)
96
+ {
97
+ this.tmp.barLine++;
98
+ }
99
+ for (var i = this.tmp.barLine; i < this.barLines.length && this.calcY(this.barLines[i], scroll) > -Mania.COLUMN_WIDTH; i++)
100
+ {
101
+ var barLine = this.calcY(this.barLines[i], scroll);
102
+ ctx.beginPath();
103
+ ctx.moveTo(0, barLine);
104
+ ctx.lineTo(Mania.COLUMN_WIDTH * this.keyCount, barLine);
105
+ ctx.strokeStyle = '#fff';
106
+ ctx.lineWidth = 1;
107
+ ctx.stroke();
108
+ }
109
+ for (var i = this.tmp.first; i <= this.tmp.last; i++)
110
+ {
111
+ var hitObject = this.HitObjects[i];
112
+ if (time > hitObject.endTime)
113
+ {
114
+ continue;
115
+ }
116
+ hitObject.draw(scroll, ctx);
117
+ }
118
+ ctx.clearRect(0, Mania.HIT_POSITION, Beatmap.WIDTH, Beatmap.HEIGHT - Mania.HIT_POSITION);
119
+ };
120
+ Mania.prototype.processBG = function(ctx)
121
+ {
122
+ ctx.beginPath();
123
+ ctx.rect(0, 0, Mania.COLUMN_WIDTH * this.keyCount, Beatmap.HEIGHT);
124
+ ctx.strokeStyle = '#ddd';
125
+ ctx.lineWidth = 8;
126
+ ctx.stroke();
127
+ ctx.fillStyle = '#000';
128
+ ctx.fill();
129
+
130
+ for (var i = 0; i < this.keyCount; i++)
131
+ {
132
+ var x = Mania.COLUMN_WIDTH * i;
133
+
134
+ ctx.beginPath();
135
+ ctx.moveTo(x, 0);
136
+ ctx.lineTo(x, Mania.HIT_POSITION);
137
+ ctx.strokeStyle = '#fff';
138
+ ctx.lineWidth = 1;
139
+ ctx.stroke();
140
+
141
+ ctx.beginPath();
142
+ ctx.rect(x, Mania.HIT_POSITION, Mania.COLUMN_WIDTH, Beatmap.HEIGHT - Mania.HIT_POSITION);
143
+ ctx.fillStyle = this.Colors[i];
144
+ ctx.fill();
145
+ ctx.strokeStyle = '#fff';
146
+ ctx.lineWidth = 3;
147
+ ctx.stroke();
148
+ }
149
+ var x = Mania.COLUMN_WIDTH * this.keyCount;
150
+ ctx.beginPath();
151
+ ctx.moveTo(x, 0);
152
+ ctx.lineTo(x, Mania.HIT_POSITION);
153
+ ctx.strokeStyle = '#fff';
154
+ ctx.lineWidth = 1;
155
+ ctx.stroke();
156
+ // HIT POSITION
157
+ ctx.beginPath();
158
+ ctx.rect(0, Mania.HIT_POSITION, Mania.COLUMN_WIDTH * this.keyCount, Mania.COLUMN_WIDTH / 3);
159
+ ctx.strokeStyle = '#fff';
160
+ ctx.lineWidth = 2;
161
+ ctx.stroke();
162
+ ctx.fillStyle = '#568';
163
+ ctx.fill();
164
+ };