@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.
- package/dist/beatmap/Beatmap.js +83 -6
- package/dist/beatmap/hitobjects/sliderObjects/SliderHead.js +10 -0
- package/dist/beatmap/hitobjects/sliderObjects/SliderRepeat.js +21 -0
- package/dist/beatmap/hitobjects/sliderObjects/SliderTail.js +10 -0
- package/dist/tools/MapInfo.js +3 -48
- package/dist/utils/MapStats.js +12 -3
- package/package.json +2 -2
- package/typings/index.d.ts +30 -1
package/dist/beatmap/Beatmap.js
CHANGED
|
@@ -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;
|
package/dist/tools/MapInfo.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
package/dist/utils/MapStats.js
CHANGED
|
@@ -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
|
|
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
|
|
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": "
|
|
44
|
+
"gitHead": "5dee4c74e815dfee236e912ce40a6a7d363d62be"
|
|
45
45
|
}
|
package/typings/index.d.ts
CHANGED
|
@@ -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
|
*
|