nonebot-plugin-osubot 6.24.0__py3-none-any.whl → 6.24.1__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.

Potentially problematic release.


This version of nonebot-plugin-osubot might be problematic. Click here for more details.

Files changed (46) hide show
  1. nonebot_plugin_osubot/draw/osu_preview.py +64 -0
  2. nonebot_plugin_osubot/draw/osu_preview_templates/css/style.css +258 -0
  3. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/README.md +109 -0
  4. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js +3 -0
  5. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js.map +1 -0
  6. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js +3 -0
  7. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js.map +1 -0
  8. nonebot_plugin_osubot/draw/osu_preview_templates/index.html +437 -0
  9. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/beatmap.js +211 -0
  10. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/hitobject.js +29 -0
  11. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/point.js +55 -0
  12. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/scroll.js +45 -0
  13. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/timingpoint.js +35 -0
  14. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/LegacyRandom.js +81 -0
  15. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/PalpableCatchHitObject.js +53 -0
  16. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/bananashower.js +33 -0
  17. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/catch.js +211 -0
  18. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/fruit.js +21 -0
  19. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/juicestream.js +176 -0
  20. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/hitnote.js +21 -0
  21. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/holdnote.js +37 -0
  22. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/mania.js +164 -0
  23. nonebot_plugin_osubot/draw/osu_preview_templates/js/preview.js +61 -0
  24. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/bezier2.js +33 -0
  25. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/catmullcurve.js +34 -0
  26. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/centripetalcatmullrom.js +30 -0
  27. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/circumstancedcircle.js +47 -0
  28. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curve.js +25 -0
  29. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curvetype.js +17 -0
  30. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/equaldistancemulticurve.js +70 -0
  31. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/linearbezier.js +40 -0
  32. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/hitcircle.js +85 -0
  33. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/slider.js +120 -0
  34. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/spinner.js +56 -0
  35. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/standard.js +170 -0
  36. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/donkat.js +40 -0
  37. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/drumroll.js +34 -0
  38. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/shaker.js +58 -0
  39. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/taiko.js +120 -0
  40. nonebot_plugin_osubot/draw/osu_preview_templates/js/util.js +61 -0
  41. nonebot_plugin_osubot/draw/osu_preview_templates/pic.html +115 -0
  42. nonebot_plugin_osubot/matcher/preview.py +7 -0
  43. nonebot_plugin_osubot/pp.py +7 -0
  44. {nonebot_plugin_osubot-6.24.0.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/METADATA +2 -2
  45. {nonebot_plugin_osubot-6.24.0.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/RECORD +46 -5
  46. {nonebot_plugin_osubot-6.24.0.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,211 @@
1
+ function Beatmap(osu)
2
+ {
3
+ // for temporary vars that need for drawing
4
+ this.tmp = {};
5
+
6
+ // [General]
7
+ this.StackLeniency = 0.7;
8
+ this.PreviewTime = -1;
9
+
10
+ // [Metadata]
11
+ this.Title = '';
12
+ this.TitleUnicode = undefined;
13
+ this.Artist = '';
14
+ this.ArtistUnicode = undefined;
15
+ this.Creator = '';
16
+ this.Version = undefined;
17
+
18
+ // [Difficulty]
19
+ this.CircleSize = 5;
20
+ this.OverallDifficulty = 5;
21
+ this.ApproachRate = undefined;
22
+ this.SliderMultiplier = 1.4;
23
+ this.SliderTickRate = 1;
24
+
25
+ // [TimingPoints]
26
+ this.TimingPoints = [];
27
+
28
+ // [Colours]
29
+ this.Colors = [];
30
+
31
+ // [HitObjects]
32
+ this.HitObjects = [];
33
+
34
+
35
+ var stream = osu.replace(/\r\n?/g, '\n').split('\n').reverse(),
36
+ currentSection, line;
37
+ while (typeof (line = stream.pop()) != 'undefined')
38
+ {
39
+ // skip comments
40
+ if (/^\/\//.test(line))
41
+ {
42
+ continue;
43
+ }
44
+
45
+ if (/^\[/.test(line))
46
+ {
47
+ currentSection = line.slice(1, line.indexOf(']'));
48
+ continue;
49
+ }
50
+
51
+ switch (currentSection)
52
+ {
53
+ case 'General':
54
+ case 'Metadata':
55
+ case 'Difficulty':
56
+ {
57
+ // let [key, ...value] = line.split(':');
58
+ var data = line.split(':'),
59
+ key = data.shift(),
60
+ value = data.join(':');
61
+ if (key in this)
62
+ {
63
+ this[key] = parseFloat(value) == value ? +value : value;
64
+ }
65
+ break;
66
+ }
67
+ case 'TimingPoints':
68
+ {
69
+ try
70
+ {
71
+ this.TimingPoints.push(new TimingPoint(line));
72
+ }
73
+ catch (e) {}
74
+ break;
75
+ }
76
+ case 'Colours':
77
+ {
78
+ // let [key, value] = line.split(':');
79
+ var data = line.split(':');
80
+ if (/^Combo\d+/.test(data[0]))
81
+ {
82
+ this.Colors.push('rgb(' + data[1] + ')');
83
+ }
84
+ break;
85
+ }
86
+ case 'HitObjects':
87
+ {
88
+ try
89
+ {
90
+ this.HitObjects.push(HitObject.parse(line, this));
91
+ }
92
+ catch (e) { console.log(e); }
93
+ break;
94
+ }
95
+ }
96
+ }
97
+ this.HitObjects.sort((a, b) => a.time - b.time);
98
+ }
99
+ Object.defineProperties(Beatmap.prototype, {
100
+ Version: {
101
+ get: function()
102
+ {
103
+ return typeof this._Version == 'undefined' || /^$/.test(this._Version)
104
+ ? 'Normal'
105
+ : this._Version;
106
+ },
107
+ set: function(value)
108
+ {
109
+ this._Version = value;
110
+ }
111
+ },
112
+ ApproachRate: {
113
+ get: function()
114
+ {
115
+ return typeof this._ApproachRate == 'undefined'
116
+ ? this.OverallDifficulty
117
+ : this._ApproachRate;
118
+ },
119
+ set: function(value)
120
+ {
121
+ this._ApproachRate = value;
122
+ }
123
+ },
124
+ hitObjectTypeMask: {
125
+ get: function()
126
+ {
127
+ if (typeof this._hitObjectTypeMask == 'undefined')
128
+ {
129
+ this._hitObjectTypeMask = Object.keys(this.hitObjectTypes).reduce(function(a, b)
130
+ {
131
+ return a | b;
132
+ });
133
+ }
134
+ return this._hitObjectTypeMask;
135
+ }
136
+ }
137
+ });
138
+ Beatmap.prototype.hitObjectTypes = undefined;
139
+ Beatmap.prototype.update = undefined;
140
+ Beatmap.prototype.draw = undefined;
141
+ Beatmap.prototype.processBG = undefined;
142
+ Beatmap.WIDTH = 640;
143
+ Beatmap.HEIGHT = 480;
144
+ Beatmap.MAX_X = 512;
145
+ Beatmap.MAX_Y = 384;
146
+ Beatmap.modes = {};
147
+ Beatmap.parse = function(osu)
148
+ {
149
+ if (!/^osu/.test(osu))
150
+ {
151
+ throw 'target is not a beatmap file';
152
+ }
153
+
154
+ // default mode is standard(id: 0)
155
+ var mode = +((osu.match(/[\r\n]Mode.*?:(.*?)[\r\n]/) || [])[1]) || 0;
156
+ if (!(mode in Beatmap.modes))
157
+ {
158
+ throw 'we do not support this beatmap mode';
159
+ }
160
+
161
+ return new Beatmap.modes[mode](osu);
162
+ };
163
+ Beatmap.prototype.timingPointIndexAt = function(time)
164
+ {
165
+ var begin = 0,
166
+ end = this.TimingPoints.length - 1;
167
+ while (begin <= end)
168
+ {
169
+ var mid = (begin + end) / 2 | 0;
170
+ if (time >= this.TimingPoints[mid].time)
171
+ {
172
+ if (mid + 1 == this.TimingPoints.length ||
173
+ time < this.TimingPoints[mid + 1].time)
174
+ {
175
+ return mid;
176
+ }
177
+ begin = mid + 1;
178
+ }
179
+ else
180
+ {
181
+ end = mid - 1;
182
+ }
183
+ }
184
+ return 0;
185
+ };
186
+ Beatmap.prototype.timingPointAt = function(time)
187
+ {
188
+ return this.TimingPoints[this.timingPointIndexAt(time)];
189
+ };
190
+ Beatmap.prototype.refresh = function()
191
+ {
192
+ this.tmp = {};
193
+ };
194
+ Beatmap.prototype.toString = function()
195
+ {
196
+ var unicode = JSON.parse(localStorage['osu_tool'] || '{"unicode":false}')['unicode'];
197
+ return [
198
+ (unicode ?
199
+ [
200
+ this.ArtistUnicode || this.Artist,
201
+ this.TitleUnicode || this.Title
202
+ ] :
203
+ [
204
+ this.Artist,
205
+ this.Title
206
+ ]
207
+ ).join(' - '),
208
+ ' (', this.Creator, ')',
209
+ ' [', this.Version || 'Normal' , ']'
210
+ ].join('');
211
+ };
@@ -0,0 +1,29 @@
1
+ function HitObject(data, beatmap)
2
+ {
3
+ this.beatmap = beatmap;
4
+
5
+ this.position = new Point(data);
6
+ this.endPosition = this.position.clone();
7
+ this.time = data[2] | 0;
8
+ this.endTime = this.time;
9
+ this.flag = data[3] | 0;
10
+ this.hitSound = data[4] | 0;
11
+ }
12
+ HitObject.prototype.draw = undefined;
13
+ HitObject.parse = function(line, beatmap)
14
+ {
15
+ var data = line.split(',');
16
+ if (data.length < 5)
17
+ {
18
+ throw 'invalid data: ' + line;
19
+ }
20
+
21
+ var type = data[3] & beatmap.hitObjectTypeMask;
22
+ if (!(type in beatmap.hitObjectTypes))
23
+ {
24
+ // throw 'we do not support this hitobject type';
25
+ return new HitObject(data, beatmap);
26
+ }
27
+
28
+ return new beatmap.hitObjectTypes[type](data, beatmap);
29
+ };
@@ -0,0 +1,55 @@
1
+ function Point()
2
+ {
3
+ if (arguments.length >= 2)
4
+ {
5
+ this.x = +arguments[0];
6
+ this.y = +arguments[1];
7
+ }
8
+ else if (arguments.length == 1)
9
+ {
10
+ this.x = +arguments[0][0];
11
+ this.y = +arguments[0][1];
12
+ }
13
+ else
14
+ {
15
+ this.x = 0;
16
+ this.y = 0;
17
+ }
18
+ }
19
+ Point.prototype.distanceTo = function(point)
20
+ {
21
+ return Math.hypot(point.x - this.x, point.y - this.y);
22
+ };
23
+ Point.prototype.equalTo = function(point)
24
+ {
25
+ return point instanceof Point &&
26
+ this.x == point.x && this.y == point.y;
27
+ };
28
+ Point.prototype.angleTo = function(point)
29
+ {
30
+ return Math.atan2(point.y - this.y, point.x - this.x);
31
+ };
32
+ Point.prototype.clone = function()
33
+ {
34
+ return new Point(this.x, this.y);
35
+ };
36
+ Point.prototype.translate = function(n)
37
+ {
38
+ if (n instanceof Point)
39
+ {
40
+ this.x += n.x;
41
+ this.y += n.y;
42
+ }
43
+ else
44
+ {
45
+ this.x += n;
46
+ this.y += n;
47
+ }
48
+ return this;
49
+ };
50
+ Point.prototype.scale = function(n)
51
+ {
52
+ this.x *= n;
53
+ this.y *= n;
54
+ return this;
55
+ };
@@ -0,0 +1,45 @@
1
+ function Scroll(osu)
2
+ {
3
+ Beatmap.call(this, osu);
4
+
5
+ // dp for numerous call to this.scrollAt
6
+ this.scrollAtTimingPointIndex = [ 0 ];
7
+ var currentIdx = this.timingPointIndexAt(0),
8
+ current = this.TimingPoints[currentIdx],
9
+ base = this.TimingPoints[0],
10
+ scrollVelocity = base.beatLength / current.beatLength;
11
+ this.scrollAtTimingPointIndex[currentIdx] = current.time * scrollVelocity;
12
+ while (++currentIdx < this.TimingPoints.length)
13
+ {
14
+ var next = this.TimingPoints[currentIdx];
15
+ this.scrollAtTimingPointIndex[currentIdx] = (next.time - current.time) * scrollVelocity +
16
+ this.scrollAtTimingPointIndex[currentIdx - 1];
17
+ current = next;
18
+ scrollVelocity = base.beatLength / current.beatLength;
19
+ }
20
+
21
+ this.barLines = [];
22
+ var endTime = (this.HitObjects.length ? this.HitObjects[this.HitObjects.length - 1].endTime : 0) + 1;
23
+ for (var i = 0; i < this.TimingPoints.length; i++)
24
+ {
25
+ var current = this.TimingPoints[i],
26
+ base = current.parent || current,
27
+ barLength = base.beatLength * base.meter,
28
+ next = this.TimingPoints[i + 1],
29
+ barLineLimit = next ? (next.parent || next).time : endTime;
30
+ for (var barTime = base.time; barTime < barLineLimit; barTime += barLength)
31
+ {
32
+ this.barLines.push(this.scrollAt(barTime));
33
+ }
34
+ }
35
+ }
36
+ Scroll.prototype = Object.create(Beatmap.prototype);
37
+ Scroll.prototype.constructor = Scroll;
38
+ Scroll.prototype.scrollAt = function(time)
39
+ {
40
+ var currentIdx = this.timingPointIndexAt(time),
41
+ current = this.TimingPoints[currentIdx],
42
+ base = this.TimingPoints[0],
43
+ scrollVelocity = base.beatLength / current.beatLength;
44
+ return (time - current.time) * scrollVelocity + this.scrollAtTimingPointIndex[currentIdx];
45
+ };
@@ -0,0 +1,35 @@
1
+ function TimingPoint(line)
2
+ {
3
+ var data = line.split(',');
4
+ if (data.length < 2)
5
+ {
6
+ throw 'invalid data';
7
+ }
8
+
9
+ this.time = data[0] | 0;
10
+ this.beatLength = +data[1];
11
+ this.meter = (data[2] | 0) || 4;
12
+ this.kiai = (data[7] | 0) % 2;
13
+
14
+ // this is non-inherited timingPoint
15
+ if (this.beatLength >= 0)
16
+ {
17
+ TimingPoint.parent = this;
18
+ this.sliderVelocity = 1;
19
+ }
20
+ else
21
+ {
22
+ this.parent = TimingPoint.parent;
23
+ this.sliderVelocity = -100 / this.beatLength;
24
+ this.beatLength = this.parent.beatLength / this.sliderVelocity;
25
+ this.meter = this.parent.meter;
26
+ }
27
+ }
28
+ Object.defineProperties(TimingPoint.prototype, {
29
+ bpm: {
30
+ get: function()
31
+ {
32
+ return 60000 / this.beatLength;
33
+ }
34
+ }
35
+ });
@@ -0,0 +1,81 @@
1
+ class LegacyRandom{
2
+ constructor(x) {
3
+ this.int_to_real = 1 / 2147483648;
4
+ this.int_mask = 0x7FFFFFFF;
5
+ this.x = x || Date.now();
6
+ this.x = this.ToUInt(this.x);
7
+ this._X = this.x;
8
+ this.y = 842502087;
9
+ this._Y = this.y;
10
+ this.z = 3579807591;
11
+ this._Z = this.z;
12
+ this.w = 273326509;
13
+ this._W = this.w;
14
+
15
+ this.bitBuffer;
16
+ this.bitIndex = 32;
17
+ }
18
+
19
+ ToInt(num) {
20
+ if (num > 2147483647) return this.ToInt(num - 4294967296);
21
+ else if (num < -2147483648) return this.ToInt(4294967296 + num);
22
+ else return parseInt(num);
23
+ }
24
+
25
+ ToUInt(num) {
26
+ if (num > 4294967296) return this.ToUInt(num - 4294967296);
27
+ if (num < 0) return this.ToUInt(4294967296 + num);
28
+ else return num;
29
+ }
30
+
31
+ NextUInt() {
32
+ let t = this.ToUInt(this._X ^ this.ToUInt(this._X << 11));
33
+ this._X = this._Y;
34
+ this._Y = this._Z;
35
+ this._Z = this._W;
36
+ let tmp = this.ToUInt(this._W >>> 19);
37
+ tmp = this.ToUInt(this._W ^ tmp);
38
+ tmp = this.ToUInt(tmp ^ t);
39
+ let tmp2 = this.ToUInt(t >>> 8);
40
+ this._W = this.ToUInt(tmp ^ tmp2);
41
+ return this._W;
42
+ }
43
+
44
+ Next() {
45
+ if (arguments.length <= 0) {
46
+ return this.ToInt(this.int_mask & this.NextUInt());
47
+ }
48
+ else if (arguments.length === 1) { // upperBound
49
+ return this.ToInt(this.NextDouble() * arguments[0]);
50
+ }
51
+ else { // lowerBound, upperBound
52
+ return this.ToInt(arguments[0] + this.NextDouble() * (arguments[1] - arguments[0]));
53
+ }
54
+ }
55
+
56
+ NextDouble() {
57
+ return this.int_to_real * this.Next();
58
+ }
59
+
60
+ NextBool() {
61
+ if (this.bitIndex == 32)
62
+ {
63
+ this.bitBuffer = this.NextUInt();
64
+ this.bitIndex = 1;
65
+
66
+ return ((this.bitBuffer & 1) == 1);
67
+ }
68
+
69
+ this.bitIndex++;
70
+ this.bitBuffer = this.bitBuffer >>> 1;
71
+ return ((this.bitBuffer & 1) == 1);
72
+ }
73
+ }
74
+ /*
75
+ let rng = new LegacyRandom(1337);
76
+ for(let i = 0; i < 1000; i++)
77
+ {
78
+ rng.NextDouble();
79
+ }
80
+ console.log(rng.NextDouble());
81
+ */
@@ -0,0 +1,53 @@
1
+ function PalpableCatchHitObject(data, beatmap)
2
+ {
3
+ this.beatmap = beatmap;
4
+ this.type = data.type;
5
+ this.time = data.time;
6
+ this.x = data.x;
7
+ this.color = data.color;
8
+ this.radius = data.radius;
9
+ this.hyperDash = false;
10
+ }
11
+ PalpableCatchHitObject.prototype.draw = function(time, ctx)
12
+ {
13
+ var dt = this.time - time;
14
+ if (dt >= -this.beatmap.FALLOUT_TIME) {
15
+ if (this.type === "Banana") this.drawBanana({x: this.x, y: (1 - dt / this.beatmap.approachTime) * Beatmap.HEIGHT - this.beatmap.CATCHER_HEIGHT}, ctx);
16
+ else {
17
+ if (this.hyperDash) this.drawDashCircle({x: this.x, y: (1 - dt / this.beatmap.approachTime) * Beatmap.HEIGHT - this.beatmap.CATCHER_HEIGHT}, ctx);
18
+ this.drawCircle({x: this.x, y: (1 - dt / this.beatmap.approachTime) * Beatmap.HEIGHT - this.beatmap.CATCHER_HEIGHT}, ctx);
19
+ }
20
+ }
21
+ };
22
+ PalpableCatchHitObject.prototype.drawCircle = function(position, ctx)
23
+ {
24
+ ctx.save();
25
+ ctx.beginPath();
26
+ ctx.arc(position.x, position.y, this.radius, -Math.PI, Math.PI);
27
+ ctx.shadowBlur = 0;
28
+ ctx.fillStyle = this.color;
29
+ ctx.fill();
30
+ ctx.restore();
31
+ };
32
+ PalpableCatchHitObject.prototype.drawBanana = function(position, ctx)
33
+ {
34
+ ctx.save();
35
+ ctx.beginPath();
36
+ ctx.shadowBlur = 0;
37
+ ctx.arc(position.x, position.y, this.radius * 0.9, -Math.PI, Math.PI);
38
+ ctx.lineWidth = this.radius * 0.2;
39
+ ctx.strokeStyle = this.color;
40
+ ctx.stroke();
41
+ ctx.restore();
42
+ };
43
+ PalpableCatchHitObject.prototype.drawDashCircle = function(position, ctx)
44
+ {
45
+ ctx.save();
46
+ ctx.beginPath();
47
+ ctx.shadowBlur = 0;
48
+ ctx.arc(position.x, position.y, this.radius * 1.1, -Math.PI, Math.PI);
49
+ ctx.lineWidth = this.radius * 0.2;
50
+ ctx.strokeStyle = 'rgb(255,0,0)';
51
+ ctx.stroke();
52
+ ctx.restore();
53
+ };
@@ -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
+ };