@rian8337/osu-difficulty-calculator 4.0.0-beta.92 → 4.0.0-beta.93
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/index.js +52 -13
- package/package.json +2 -2
- package/typings/index.d.ts +38 -10
package/dist/index.js
CHANGED
|
@@ -223,8 +223,17 @@ class Skill {
|
|
|
223
223
|
get objectDifficulties() {
|
|
224
224
|
return this._objectDifficulties;
|
|
225
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* The start times of {@link DifficultyHitObject}s, populated by {@link Skill.process}.
|
|
228
|
+
*
|
|
229
|
+
* Indices correspond to {@link objectDifficulties}.
|
|
230
|
+
*/
|
|
231
|
+
get objectTimes() {
|
|
232
|
+
return this._objectTimes;
|
|
233
|
+
}
|
|
226
234
|
constructor(mods) {
|
|
227
235
|
this._objectDifficulties = [];
|
|
236
|
+
this._objectTimes = [];
|
|
228
237
|
this.mods = mods;
|
|
229
238
|
}
|
|
230
239
|
/**
|
|
@@ -240,6 +249,7 @@ class Skill {
|
|
|
240
249
|
const difficultyValue = this.processInternal(current);
|
|
241
250
|
this.saveToHitObject(current, difficultyValue);
|
|
242
251
|
this._objectDifficulties.push(difficultyValue);
|
|
252
|
+
this._objectTimes.push(current.startTime);
|
|
243
253
|
}
|
|
244
254
|
/**
|
|
245
255
|
* Saves the calculated difficulty to a {@link DifficultyHitObject}.
|
|
@@ -276,6 +286,12 @@ class VariableLengthStrainSkill extends Skill {
|
|
|
276
286
|
this.currentSectionEnd = 0;
|
|
277
287
|
this.totalLength = 0;
|
|
278
288
|
this.strainPeaks = [];
|
|
289
|
+
/**
|
|
290
|
+
* The peaks of this skill in chronological order, used for graphing purposes.
|
|
291
|
+
*
|
|
292
|
+
* Unlike {@link strainPeaks}, this is never trimmed, as it does not contribute to {@link difficultyValue}.
|
|
293
|
+
*/
|
|
294
|
+
this.chronologicalPeaks = [];
|
|
279
295
|
/**
|
|
280
296
|
* Stores previous strains so that, if a difficult {@link DifficultyHitObject} is followed by an easier
|
|
281
297
|
* {@link DifficultyHitObject}, the difficult one gets a full strain instead of being cut short.
|
|
@@ -294,7 +310,10 @@ class VariableLengthStrainSkill extends Skill {
|
|
|
294
310
|
return 11 / (1 - this.decayWeight);
|
|
295
311
|
}
|
|
296
312
|
get peaks() {
|
|
297
|
-
return this.
|
|
313
|
+
return this.chronologicalPeaks.concat({
|
|
314
|
+
time: this.currentSectionEnd,
|
|
315
|
+
value: this.currentSectionPeak,
|
|
316
|
+
});
|
|
298
317
|
}
|
|
299
318
|
static difficultyToPerformance(difficulty) {
|
|
300
319
|
return 4 * Math.pow(difficulty, 3);
|
|
@@ -442,6 +461,10 @@ class VariableLengthStrainSkill extends Skill {
|
|
|
442
461
|
*/
|
|
443
462
|
saveCurrentPeak(sectionLength) {
|
|
444
463
|
this.addStrainPeakInPlace(new StrainPeak(this.currentSectionPeak, sectionLength));
|
|
464
|
+
this.chronologicalPeaks.push({
|
|
465
|
+
time: this.currentSectionBegin + sectionLength,
|
|
466
|
+
value: this.currentSectionPeak,
|
|
467
|
+
});
|
|
445
468
|
this.totalLength += sectionLength;
|
|
446
469
|
// Remove from the front of our strain peaks if there is any which are too deep to contribute to difficulty.
|
|
447
470
|
// `maxStoredSections` dictates for us how many sections will preserve at least 99.999% of difficulty.
|
|
@@ -1095,6 +1118,7 @@ class StrainSkill extends Skill {
|
|
|
1095
1118
|
this.reducedSectionBaseline = 0.75;
|
|
1096
1119
|
this._objectStrains = [];
|
|
1097
1120
|
this.strainPeaks = [];
|
|
1121
|
+
this.strainPeakTimes = [];
|
|
1098
1122
|
this.sectionLength = 400;
|
|
1099
1123
|
this.currentStrain = 0;
|
|
1100
1124
|
this.currentSectionPeak = 0;
|
|
@@ -1107,7 +1131,9 @@ class StrainSkill extends Skill {
|
|
|
1107
1131
|
return this._objectStrains;
|
|
1108
1132
|
}
|
|
1109
1133
|
get peaks() {
|
|
1110
|
-
return this.
|
|
1134
|
+
return this.strainPeaks
|
|
1135
|
+
.map((value, i) => ({ time: this.strainPeakTimes[i], value }))
|
|
1136
|
+
.concat({ time: this.currentSectionEnd, value: this.currentSectionPeak });
|
|
1111
1137
|
}
|
|
1112
1138
|
/**
|
|
1113
1139
|
* Converts a difficulty value to a performance value.
|
|
@@ -1175,6 +1201,7 @@ class StrainSkill extends Skill {
|
|
|
1175
1201
|
*/
|
|
1176
1202
|
saveCurrentPeak() {
|
|
1177
1203
|
this.strainPeaks.push(this.currentSectionPeak);
|
|
1204
|
+
this.strainPeakTimes.push(this.currentSectionEnd);
|
|
1178
1205
|
}
|
|
1179
1206
|
/**
|
|
1180
1207
|
* Sets the initial strain level for a new section.
|
|
@@ -1278,7 +1305,7 @@ class DroidFlashlight extends DroidSkill {
|
|
|
1278
1305
|
return sum;
|
|
1279
1306
|
}
|
|
1280
1307
|
calculateAdjustedDifficulty(current) {
|
|
1281
|
-
let difficulty = Math.pow(DroidFlashlightEvaluator.evaluateDifficultyOf(current, this.mods), 0.
|
|
1308
|
+
let difficulty = Math.pow(DroidFlashlightEvaluator.evaluateDifficultyOf(current, this.mods), 0.9);
|
|
1282
1309
|
if (this.mods.has(osuBase.ModRelax)) {
|
|
1283
1310
|
difficulty *= 0.7;
|
|
1284
1311
|
}
|
|
@@ -1322,7 +1349,10 @@ class HarmonicSkill extends Skill {
|
|
|
1322
1349
|
return this._noteWeightSum;
|
|
1323
1350
|
}
|
|
1324
1351
|
get peaks() {
|
|
1325
|
-
return this.objectDifficulties
|
|
1352
|
+
return this.objectDifficulties.map((value, i) => ({
|
|
1353
|
+
time: this.objectTimes[i],
|
|
1354
|
+
value,
|
|
1355
|
+
}));
|
|
1326
1356
|
}
|
|
1327
1357
|
static difficultyToPerformance(difficulty) {
|
|
1328
1358
|
return 4 * Math.pow(difficulty, 3);
|
|
@@ -3161,9 +3191,15 @@ class DroidRhythmEvaluator {
|
|
|
3161
3191
|
// Scale down the difficulty if the object is doubletappable.
|
|
3162
3192
|
effectiveRatio *=
|
|
3163
3193
|
1 - prevObject.getDoubletapness(currentObject) * 0.75;
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3194
|
+
if (island.deltaCount > 1) {
|
|
3195
|
+
rhythmComplexitySum +=
|
|
3196
|
+
Math.sqrt(effectiveRatio * startRatio) *
|
|
3197
|
+
currentHistoricalDecay;
|
|
3198
|
+
}
|
|
3199
|
+
else {
|
|
3200
|
+
// Constant difficulty for single-note islands.
|
|
3201
|
+
rhythmComplexitySum += 0.7 * currentHistoricalDecay;
|
|
3202
|
+
}
|
|
3167
3203
|
startRatio = effectiveRatio;
|
|
3168
3204
|
previousIsland = island;
|
|
3169
3205
|
if (prevDelta + deltaDifferenceEpsilon < currentDelta) {
|
|
@@ -3419,9 +3455,10 @@ class DroidDifficultyCalculator extends DifficultyCalculator {
|
|
|
3419
3455
|
attributes.sliderCount = playableBeatmap.hitObjects.sliders;
|
|
3420
3456
|
attributes.spinnerCount = playableBeatmap.hitObjects.spinners;
|
|
3421
3457
|
attributes.overallDifficulty = playableBeatmap.difficulty.od;
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3458
|
+
// Cap at 32-bit signed integer since that's the maximum score that can be submitted
|
|
3459
|
+
// to the game's leaderboards.
|
|
3460
|
+
attributes.maximumScore = Math.min(beatmap.maxDroidScore(playableBeatmap.mods) +
|
|
3461
|
+
DroidScoreUtils.calculateMaximumSpinnerBonus(playableBeatmap), 2147483647);
|
|
3425
3462
|
this.populateAimAttributes(attributes, skills, objects);
|
|
3426
3463
|
this.populateTapAttributes(attributes, skills, objects);
|
|
3427
3464
|
this.populateRhythmAttributes(attributes, skills);
|
|
@@ -3494,8 +3531,9 @@ class DroidDifficultyCalculator extends DifficultyCalculator {
|
|
|
3494
3531
|
attributes.aimDifficultSliderCount = aim.countDifficultSliders();
|
|
3495
3532
|
attributes.aimDifficultStrainCount =
|
|
3496
3533
|
aim.countTopWeightedStrains(aimDifficultyValue);
|
|
3497
|
-
const
|
|
3498
|
-
const
|
|
3534
|
+
const aimNoSliderDifficultyValue = aimNoSlider.difficultyValue();
|
|
3535
|
+
const aimNoSliderTopWeightedSliderCount = aimNoSlider.countTopWeightedSliders(aimNoSliderDifficultyValue);
|
|
3536
|
+
const aimNoSliderDifficultStrainCount = aimNoSlider.countTopWeightedStrains(aimNoSliderDifficultyValue);
|
|
3499
3537
|
attributes.aimTopWeightedSliderFactor =
|
|
3500
3538
|
aimNoSliderTopWeightedSliderCount /
|
|
3501
3539
|
Math.max(1, aimNoSliderDifficultStrainCount -
|
|
@@ -3530,7 +3568,8 @@ class DroidDifficultyCalculator extends DifficultyCalculator {
|
|
|
3530
3568
|
}
|
|
3531
3569
|
if (attributes.aimDifficulty > 0) {
|
|
3532
3570
|
attributes.sliderFactor =
|
|
3533
|
-
this.calculateAimDifficultyRating(
|
|
3571
|
+
this.calculateAimDifficultyRating(aimNoSliderDifficultyValue) /
|
|
3572
|
+
this.calculateAimDifficultyRating(aimDifficultyValue);
|
|
3534
3573
|
}
|
|
3535
3574
|
else {
|
|
3536
3575
|
attributes.sliderFactor = 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rian8337/osu-difficulty-calculator",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.93",
|
|
4
4
|
"description": "A module for calculating osu!standard beatmap difficulty and performance value with respect to the current difficulty and performance algorithm.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"osu",
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"publishConfig": {
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "9eee7ed61799bd3d1a9510e0491e7433932ba190"
|
|
42
42
|
}
|
package/typings/index.d.ts
CHANGED
|
@@ -336,6 +336,20 @@ declare abstract class DifficultyAttributes implements IDifficultyAttributes {
|
|
|
336
336
|
toString(): string;
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Represents a strain peak at a specific point in time.
|
|
341
|
+
*/
|
|
342
|
+
interface TimedStrainPeak {
|
|
343
|
+
/**
|
|
344
|
+
* The time at which this peak occurs, in milliseconds.
|
|
345
|
+
*/
|
|
346
|
+
readonly time: number;
|
|
347
|
+
/**
|
|
348
|
+
* The strain value of this peak.
|
|
349
|
+
*/
|
|
350
|
+
readonly value: number;
|
|
351
|
+
}
|
|
352
|
+
|
|
339
353
|
/**
|
|
340
354
|
* Represents the strain peaks of various calculated difficulties.
|
|
341
355
|
*/
|
|
@@ -343,19 +357,19 @@ interface StrainPeaks {
|
|
|
343
357
|
/**
|
|
344
358
|
* The strain peaks of aim difficulty if sliders are considered.
|
|
345
359
|
*/
|
|
346
|
-
aimWithSliders: readonly
|
|
360
|
+
aimWithSliders: readonly TimedStrainPeak[];
|
|
347
361
|
/**
|
|
348
362
|
* The strain peaks of aim difficulty if sliders are not considered.
|
|
349
363
|
*/
|
|
350
|
-
aimWithoutSliders: readonly
|
|
364
|
+
aimWithoutSliders: readonly TimedStrainPeak[];
|
|
351
365
|
/**
|
|
352
366
|
* The strain peaks of speed difficulty.
|
|
353
367
|
*/
|
|
354
|
-
speed: readonly
|
|
368
|
+
speed: readonly TimedStrainPeak[];
|
|
355
369
|
/**
|
|
356
370
|
* The strain peaks of flashlight difficulty.
|
|
357
371
|
*/
|
|
358
|
-
flashlight: readonly
|
|
372
|
+
flashlight: readonly TimedStrainPeak[];
|
|
359
373
|
}
|
|
360
374
|
|
|
361
375
|
/**
|
|
@@ -363,9 +377,9 @@ interface StrainPeaks {
|
|
|
363
377
|
*/
|
|
364
378
|
interface IHasPeakDifficulty {
|
|
365
379
|
/**
|
|
366
|
-
* The peak difficulties calculated by this `Skill
|
|
380
|
+
* The peak difficulties calculated by this `Skill`, in chronological order.
|
|
367
381
|
*/
|
|
368
|
-
get peaks(): readonly
|
|
382
|
+
get peaks(): readonly TimedStrainPeak[];
|
|
369
383
|
}
|
|
370
384
|
|
|
371
385
|
/**
|
|
@@ -377,10 +391,17 @@ declare abstract class Skill {
|
|
|
377
391
|
*/
|
|
378
392
|
protected readonly mods: ModMap;
|
|
379
393
|
private _objectDifficulties;
|
|
394
|
+
private _objectTimes;
|
|
380
395
|
/**
|
|
381
396
|
* The difficulties of {@link DifficultyHitObject}s, populated by {@link Skill.process}.
|
|
382
397
|
*/
|
|
383
398
|
protected get objectDifficulties(): readonly number[];
|
|
399
|
+
/**
|
|
400
|
+
* The start times of {@link DifficultyHitObject}s, populated by {@link Skill.process}.
|
|
401
|
+
*
|
|
402
|
+
* Indices correspond to {@link objectDifficulties}.
|
|
403
|
+
*/
|
|
404
|
+
protected get objectTimes(): readonly number[];
|
|
384
405
|
constructor(mods: ModMap);
|
|
385
406
|
/**
|
|
386
407
|
* Calculates the strain value of a hitobject and stores the value in it.
|
|
@@ -1263,7 +1284,8 @@ declare abstract class StrainSkill extends Skill implements IHasPeakDifficulty {
|
|
|
1263
1284
|
*/
|
|
1264
1285
|
get objectStrains(): readonly number[];
|
|
1265
1286
|
protected readonly strainPeaks: number[];
|
|
1266
|
-
|
|
1287
|
+
private readonly strainPeakTimes;
|
|
1288
|
+
get peaks(): readonly TimedStrainPeak[];
|
|
1267
1289
|
private readonly sectionLength;
|
|
1268
1290
|
private currentStrain;
|
|
1269
1291
|
private currentSectionPeak;
|
|
@@ -1531,7 +1553,13 @@ declare abstract class VariableLengthStrainSkill extends Skill implements IHasPe
|
|
|
1531
1553
|
private currentSectionEnd;
|
|
1532
1554
|
private totalLength;
|
|
1533
1555
|
private readonly strainPeaks;
|
|
1534
|
-
|
|
1556
|
+
/**
|
|
1557
|
+
* The peaks of this skill in chronological order, used for graphing purposes.
|
|
1558
|
+
*
|
|
1559
|
+
* Unlike {@link strainPeaks}, this is never trimmed, as it does not contribute to {@link difficultyValue}.
|
|
1560
|
+
*/
|
|
1561
|
+
private readonly chronologicalPeaks;
|
|
1562
|
+
get peaks(): readonly TimedStrainPeak[];
|
|
1535
1563
|
/**
|
|
1536
1564
|
* Stores previous strains so that, if a difficult {@link DifficultyHitObject} is followed by an easier
|
|
1537
1565
|
* {@link DifficultyHitObject}, the difficult one gets a full strain instead of being cut short.
|
|
@@ -1706,7 +1734,7 @@ declare abstract class HarmonicSkill extends Skill implements IHasPeakDifficulty
|
|
|
1706
1734
|
* Values closer to 1 decay faster, whilst lower values give more weight to easier {@link DifficultyHitObject}s.
|
|
1707
1735
|
*/
|
|
1708
1736
|
protected readonly decayExponent: number;
|
|
1709
|
-
get peaks(): readonly
|
|
1737
|
+
get peaks(): readonly TimedStrainPeak[];
|
|
1710
1738
|
static difficultyToPerformance(difficulty: number): number;
|
|
1711
1739
|
difficultyValue(): number;
|
|
1712
1740
|
/**
|
|
@@ -1878,4 +1906,4 @@ declare class OsuSpeed extends OsuSkill {
|
|
|
1878
1906
|
}
|
|
1879
1907
|
|
|
1880
1908
|
export { DifficultyAttributes, DifficultyCalculator, DifficultyHitObject, DroidAgilityEvaluator, DroidAim, DroidDifficultyAttributes, DroidDifficultyCalculator, DroidDifficultyHitObject, DroidFlashlight, DroidFlashlightEvaluator, DroidFlowAimEvaluator, DroidPerformanceCalculator, DroidReading, DroidReadingEvaluator, DroidRhythm, DroidRhythmEvaluator, DroidSnapAimEvaluator, DroidTap, DroidTapEvaluator, ExtendedDroidDifficultyAttributes, OsuAim, OsuAimEvaluator, OsuDifficultyAttributes, OsuDifficultyCalculator, OsuDifficultyHitObject, OsuFlashlight, OsuFlashlightEvaluator, OsuPerformanceCalculator, OsuRhythmEvaluator, OsuSpeed, OsuSpeedEvaluator, PerformanceCalculator };
|
|
1881
|
-
export type { CacheableDifficultyAttributes, DifficultSlider, HighStrainSection, IDifficultyAttributes, IDroidDifficultyAttributes, IExtendedDroidDifficultyAttributes, IOsuDifficultyAttributes, PerformanceCalculationOptions, StrainPeaks };
|
|
1909
|
+
export type { CacheableDifficultyAttributes, DifficultSlider, HighStrainSection, IDifficultyAttributes, IDroidDifficultyAttributes, IExtendedDroidDifficultyAttributes, IOsuDifficultyAttributes, PerformanceCalculationOptions, StrainPeaks, TimedStrainPeak };
|