@rian8337/osu-base 1.2.8 → 1.4.2

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.
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Beatmap = void 0;
4
4
  const Slider_1 = require("./hitobjects/Slider");
5
+ const SliderTick_1 = require("./hitobjects/sliderObjects/SliderTick");
5
6
  /**
6
7
  * Represents a beatmap with advanced information.
7
8
  */
@@ -93,9 +94,7 @@ class Beatmap {
93
94
  */
94
95
  get sliderTicks() {
95
96
  const sliders = (this.objects.filter((v) => v instanceof Slider_1.Slider));
96
- return sliders
97
- .map((v) => v.ticks)
98
- .reduce((acc, value) => acc + value, 0);
97
+ return sliders.reduce((acc, value) => acc + value.ticks, 0);
99
98
  }
100
99
  /**
101
100
  * The amount of sliderends in the beatmap.
@@ -108,9 +107,7 @@ class Beatmap {
108
107
  */
109
108
  get sliderRepeatPoints() {
110
109
  const sliders = (this.objects.filter((v) => v instanceof Slider_1.Slider));
111
- return sliders
112
- .map((v) => v.repeatPoints)
113
- .reduce((acc, value) => acc + value, 0);
110
+ return sliders.reduce((acc, value) => acc + value.repeatPoints, 0);
114
111
  }
115
112
  /**
116
113
  * The maximum combo of the beatmap.
@@ -149,6 +146,86 @@ class Beatmap {
149
146
  difficultyControlPointAt(time) {
150
147
  return this.getTimingPoint(time, this.difficultyTimingPoints);
151
148
  }
149
+ /**
150
+ * Calculates the osu!droid maximum score of the beatmap without taking spinner bonus into account.
151
+ *
152
+ * @param stats The statistics used for calculation.
153
+ */
154
+ maxDroidScore(stats) {
155
+ let scoreMultiplier = 1;
156
+ if (stats.mods.every((m) => m.droidRanked)) {
157
+ let scoreSpeedMultiplier = 1;
158
+ const speedMultiplier = stats.speedMultiplier;
159
+ if (speedMultiplier > 1) {
160
+ scoreSpeedMultiplier += (speedMultiplier - 1) * 0.24;
161
+ }
162
+ else if (speedMultiplier < 1) {
163
+ scoreSpeedMultiplier = Math.pow(0.3, (1 - speedMultiplier) * 4);
164
+ }
165
+ scoreMultiplier =
166
+ stats.mods.reduce((a, v) => a * v.scoreMultiplier, 1) *
167
+ scoreSpeedMultiplier;
168
+ }
169
+ else {
170
+ scoreMultiplier = 0;
171
+ }
172
+ return this.maxScore(1 + this.od / 10 + this.hp / 10 + (this.cs - 3) / 4, scoreMultiplier);
173
+ }
174
+ /**
175
+ * Calculates the osu!standard maximum score of the beatmap without taking spinner bonus into account.
176
+ *
177
+ * @param mods The modifications to calculate for. Defaults to No Mod.
178
+ */
179
+ maxOsuScore(mods = []) {
180
+ const accumulatedDiffPoints = this.cs + this.hp + this.od;
181
+ let difficultyMultiplier = 2;
182
+ switch (true) {
183
+ case accumulatedDiffPoints <= 5:
184
+ difficultyMultiplier = 2;
185
+ break;
186
+ case accumulatedDiffPoints <= 12:
187
+ difficultyMultiplier = 3;
188
+ break;
189
+ case accumulatedDiffPoints <= 17:
190
+ difficultyMultiplier = 4;
191
+ break;
192
+ case accumulatedDiffPoints <= 24:
193
+ difficultyMultiplier = 5;
194
+ break;
195
+ case accumulatedDiffPoints >= 25:
196
+ difficultyMultiplier = 6;
197
+ break;
198
+ }
199
+ return this.maxScore(difficultyMultiplier, mods.reduce((a, v) => a * v.scoreMultiplier, 1));
200
+ }
201
+ /**
202
+ * Calculates the maximum score with a given difficulty and score multiplier.
203
+ *
204
+ * @param difficultyMultiplier The difficulty multiplier.
205
+ * @param scoreMultiplier The score multiplier.
206
+ */
207
+ maxScore(difficultyMultiplier, scoreMultiplier) {
208
+ let combo = 0;
209
+ let score = 0;
210
+ for (const object of this.objects) {
211
+ if (!(object instanceof Slider_1.Slider)) {
212
+ score += Math.floor(300 +
213
+ (300 * combo * difficultyMultiplier * scoreMultiplier) /
214
+ 25);
215
+ ++combo;
216
+ continue;
217
+ }
218
+ const tickCount = object.nestedHitObjects.filter((v) => v instanceof SliderTick_1.SliderTick).length;
219
+ // Apply sliderhead, slider repeats, and slider ticks
220
+ score += 30 * (object.repeatPoints + 1) + 10 * tickCount;
221
+ combo += tickCount + (object.repeatPoints + 1);
222
+ // Apply sliderend
223
+ score += Math.floor(300 +
224
+ (300 * combo * difficultyMultiplier * scoreMultiplier) / 25);
225
+ ++combo;
226
+ }
227
+ return score;
228
+ }
152
229
  /**
153
230
  * Gets the timing point that applies at a given time.
154
231
  *
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SliderHead = void 0;
4
+ const Circle_1 = require("../Circle");
5
+ /**
6
+ * Represents the head of a slider.
7
+ */
8
+ class SliderHead extends Circle_1.Circle {
9
+ }
10
+ exports.SliderHead = SliderHead;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SliderRepeat = void 0;
4
+ const HitObject_1 = require("../HitObject");
5
+ /**
6
+ * Represents a repeat point in a slider.
7
+ */
8
+ class SliderRepeat extends HitObject_1.HitObject {
9
+ constructor(values) {
10
+ super({
11
+ startTime: values.startTime,
12
+ position: values.position,
13
+ });
14
+ this.repeatIndex = values.repeatIndex;
15
+ this.spanDuration = values.spanDuration;
16
+ }
17
+ toString() {
18
+ return `Position: [${this.position.x}, ${this.position.y}], repeat index: ${this.repeatIndex}, span duration: ${this.spanDuration}`;
19
+ }
20
+ }
21
+ exports.SliderRepeat = SliderRepeat;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SliderTail = void 0;
4
+ const Circle_1 = require("../Circle");
5
+ /**
6
+ * Represents the tail of a slider.
7
+ */
8
+ class SliderTail extends Circle_1.Circle {
9
+ }
10
+ exports.SliderTail = SliderTail;
@@ -8,8 +8,6 @@ const request_1 = __importDefault(require("request"));
8
8
  const MapStats_1 = require("../utils/MapStats");
9
9
  const Parser_1 = require("../beatmap/Parser");
10
10
  const rankedStatus_1 = require("../constants/rankedStatus");
11
- const Slider_1 = require("../beatmap/hitobjects/Slider");
12
- const SliderTick_1 = require("../beatmap/hitobjects/sliderObjects/SliderTick");
13
11
  const APIRequestBuilder_1 = require("../utils/APIRequestBuilder");
14
12
  const Precision_1 = require("../utils/Precision");
15
13
  const Utils_1 = require("../utils/Utils");
@@ -179,7 +177,7 @@ class MapInfo {
179
177
  const map = new MapInfo();
180
178
  const result = await apiRequestBuilder.sendRequest();
181
179
  if (result.statusCode !== 200) {
182
- throw new Error("API error");
180
+ throw new Error("osu! API error");
183
181
  }
184
182
  const mapinfo = JSON.parse(result.data.toString("utf-8"))[0];
185
183
  if (!mapinfo) {
@@ -499,55 +497,12 @@ class MapInfo {
499
497
  }
500
498
  }
501
499
  /**
502
- * Calculates the osu!droid maximum score of the beatmap.
500
+ * Calculates the osu!droid maximum score of the beatmap without taking spinner bonus into account.
503
501
  *
504
502
  * This requires .osu file to be downloaded.
505
503
  */
506
504
  maxScore(stats) {
507
- if (!this.map) {
508
- return 0;
509
- }
510
- const difficultyMultiplier = 1 + this.od / 10 + this.hp / 10 + (this.cs - 3) / 4;
511
- // score multiplier
512
- let scoreMultiplier = 1;
513
- if (stats.mods.every((m) => m.droidRanked)) {
514
- let scoreSpeedMultiplier = 1;
515
- const speedMultiplier = stats.speedMultiplier;
516
- if (speedMultiplier > 1) {
517
- scoreSpeedMultiplier += (speedMultiplier - 1) * 0.24;
518
- }
519
- else if (speedMultiplier < 1) {
520
- scoreSpeedMultiplier = Math.pow(0.3, (1 - speedMultiplier) * 4);
521
- }
522
- scoreMultiplier =
523
- stats.mods.reduce((a, v) => a * v.scoreMultiplier, 1) *
524
- scoreSpeedMultiplier;
525
- }
526
- else {
527
- scoreMultiplier = 0;
528
- }
529
- const objects = this.map.objects;
530
- let combo = 0;
531
- let score = 0;
532
- for (let i = 0; i < objects.length; ++i) {
533
- const object = objects[i];
534
- if (!(object instanceof Slider_1.Slider)) {
535
- score += Math.floor(300 +
536
- (300 * combo * difficultyMultiplier * scoreMultiplier) /
537
- 25);
538
- ++combo;
539
- continue;
540
- }
541
- const tickCount = object.nestedHitObjects.filter((v) => v instanceof SliderTick_1.SliderTick).length;
542
- // Apply sliderhead, slider repeats, and slider ticks
543
- score += 30 * (object.repeatPoints + 1) + 10 * tickCount;
544
- combo += tickCount + (object.repeatPoints + 1);
545
- // Apply sliderend
546
- score += Math.floor(300 +
547
- (300 * combo * difficultyMultiplier * scoreMultiplier) / 25);
548
- ++combo;
549
- }
550
- return score;
505
+ return this.map?.maxDroidScore(stats) ?? 0;
551
506
  }
552
507
  /**
553
508
  * Returns a string representative of the class.
@@ -173,9 +173,7 @@ class MapStats {
173
173
  static modifyAR(baseAR, speedMultiplier, statisticsMultiplier) {
174
174
  let ar = baseAR;
175
175
  ar *= statisticsMultiplier;
176
- let arMS = ar < 5.0
177
- ? this.AR0_MS - this.AR_MS_STEP1 * ar
178
- : this.AR5_MS - this.AR_MS_STEP2 * (ar - 5);
176
+ let arMS = this.arToMS(ar);
179
177
  arMS = Math.min(this.AR0_MS, Math.max(this.AR10_MS, arMS));
180
178
  arMS /= speedMultiplier;
181
179
  ar =
@@ -184,6 +182,17 @@ class MapStats {
184
182
  : 5 + (this.AR5_MS - arMS) / this.AR_MS_STEP2;
185
183
  return ar;
186
184
  }
185
+ /**
186
+ * Converts an AR value to its milliseconds value.
187
+ *
188
+ * @param ar The AR to convert.
189
+ * @returns The milliseconds value represented by the AR.
190
+ */
191
+ static arToMS(ar) {
192
+ return ar < 5.0
193
+ ? this.AR0_MS - this.AR_MS_STEP1 * ar
194
+ : this.AR5_MS - this.AR_MS_STEP2 * (ar - 5);
195
+ }
187
196
  /**
188
197
  * Utility function to apply speed and flat multipliers to stats where speed changes apply for OD.
189
198
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rian8337/osu-base",
3
- "version": "1.2.8",
3
+ "version": "1.4.2",
4
4
  "description": "Base module for all osu! related modules.",
5
5
  "keywords": [
6
6
  "osu",
@@ -41,5 +41,5 @@
41
41
  "publishConfig": {
42
42
  "access": "public"
43
43
  },
44
- "gitHead": "3e633e510be04aca9c46b9361524251442049621"
44
+ "gitHead": "5dee4c74e815dfee236e912ce40a6a7d363d62be"
45
45
  }
@@ -159,6 +159,28 @@ declare module "@rian8337/osu-base" {
159
159
  * @param time The time.
160
160
  */
161
161
  difficultyControlPointAt(time: number): DifficultyControlPoint;
162
+ /**
163
+ * Calculates the osu!droid maximum score of the beatmap without taking spinner bonus into account.
164
+ *
165
+ * @param stats The statistics used for calculation.
166
+ */
167
+ maxDroidScore(stats: MapStats): number;
168
+ /**
169
+ * Calculates the osu!standard maximum score of the beatmap without taking spinner bonus into account.
170
+ *
171
+ * @param mods The modifications to calculate for. Defaults to No Mod.
172
+ */
173
+ maxOsuScore(mods?: Mod[]): number;
174
+ /**
175
+ * Calculates the maximum score with a given difficulty and score multiplier.
176
+ *
177
+ * @param difficultyMultiplier The difficulty multiplier.
178
+ * @param scoreMultiplier The score multiplier.
179
+ */
180
+ private maxScore(
181
+ difficultyMultiplier: number,
182
+ scoreMultiplier: number
183
+ ): number;
162
184
  /**
163
185
  * Gets the timing point that applies at a given time.
164
186
  *
@@ -551,7 +573,7 @@ declare module "@rian8337/osu-base" {
551
573
  */
552
574
  get statusColor(): number;
553
575
  /**
554
- * Calculates the osu!droid maximum score of the beatmap.
576
+ * Calculates the osu!droid maximum score of the beatmap without taking spinner bonus into account.
555
577
  *
556
578
  * This requires .osu file to be downloaded.
557
579
  */
@@ -683,6 +705,13 @@ declare module "@rian8337/osu-base" {
683
705
  speedMultiplier: number,
684
706
  statisticsMultiplier: number
685
707
  ): number;
708
+ /**
709
+ * Converts an AR value to its milliseconds value.
710
+ *
711
+ * @param ar The AR to convert.
712
+ * @returns The milliseconds value represented by the AR.
713
+ */
714
+ static arToMS(ar: number): number;
686
715
  /**
687
716
  * Utility function to apply speed and flat multipliers to stats where speed changes apply for OD.
688
717
  *