Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HotFix: pp and graph #157

Merged
merged 6 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 39 additions & 14 deletions packages/tosu/src/entities/BeatmapPpData/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,7 @@ export class BeatmapPPData extends AbstractEntity {

const { menuData, allTimesData } = this.osuInstance.getServices([
'menuData',
'allTimesData',
'beatmapPpData'
'allTimesData'
]);

const mapPath = path.join(
Expand Down Expand Up @@ -280,7 +279,6 @@ export class BeatmapPPData extends AbstractEntity {
parseHitObjects: true,

parseColours: false,
parseDifficulty: false,
parseEditor: false,
parseGeneral: false,
parseStoryboard: false,
Expand Down Expand Up @@ -322,22 +320,45 @@ export class BeatmapPPData extends AbstractEntity {
return;
}

const offset = strains.sectionLength;
const firstObj = this.timings.firstObj / attributes.clockRate;
const lastObj = this.timings.full / attributes.clockRate;
const mp3Length = menuData.MP3Length / attributes.clockRate;

const beatmapParseTime = performance.now();
wLogger.debug(
`BPPD(updateMapMetadata) [${(
beatmapParseTime - calculationTime
).toFixed(2)}ms] Spend on parsing beatmap`
);

const LEFT_OFFSET = Math.floor(firstObj / offset);
let strainsAmount = 0;
switch (strains.mode) {
case 0:
strainsAmount = strains.aim?.length || 0;
break;

case 1:
strainsAmount = strains.color?.length || 0;
break;

case 2:
strainsAmount = strains.movement?.length || 0;
break;

case 3:
strainsAmount = strains.strains?.length || 0;
break;
}

const sectionOffsetTime = strains.sectionLength;
const firstObjectTime =
this.timings.firstObj / attributes.clockRate;
const lastObjectTime =
firstObjectTime + strainsAmount * sectionOffsetTime;
const mp3LengthTime = menuData.MP3Length / attributes.clockRate;

const LEFT_OFFSET = Math.floor(firstObjectTime / sectionOffsetTime);
const RIGHT_OFFSET =
mp3Length >= lastObj
? Math.ceil((mp3Length - lastObj) / offset)
mp3LengthTime >= lastObjectTime
? Math.ceil(
(mp3LengthTime - lastObjectTime) / sectionOffsetTime
)
: 0;

const updateWithOffset = (
Expand Down Expand Up @@ -410,19 +431,23 @@ export class BeatmapPPData extends AbstractEntity {
);

for (let i = 0; i < LEFT_OFFSET; i++) {
resultStrains.xaxis.push(i * offset);
resultStrains.xaxis.push(i * sectionOffsetTime);
}

const total =
resultStrains.series[0].data.length -
LEFT_OFFSET -
RIGHT_OFFSET;
let lastTime = 0;
for (let i = 0; i < total; i++) {
resultStrains.xaxis.push(firstObj + i * offset);
lastTime = firstObjectTime + i * sectionOffsetTime;
resultStrains.xaxis.push(lastTime);
}

for (let i = 0; i < RIGHT_OFFSET; i++) {
resultStrains.xaxis.push(lastObj + i * offset);
resultStrains.xaxis.push(
lastObjectTime + i * sectionOffsetTime
);
}

const endTime = performance.now();
Expand Down
101 changes: 69 additions & 32 deletions packages/tosu/src/entities/GamePlayData/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export class GamePlayData extends AbstractEntity {
isDefaultState: boolean = true;
isKeyOverlayDefaultState: boolean = true;

PerformanceAttributes?: rosu.PerformanceAttributes | rosu.Beatmap;
PerformanceAttributes: rosu.PerformanceAttributes;
GradualPerformance: rosu.GradualPerformance | null;

Retries: number;
PlayerName: string;
Expand Down Expand Up @@ -58,6 +59,7 @@ export class GamePlayData extends AbstractEntity {
private cachedkeys: string = '';

previousState: string = '';
previousPassedObjects = 0;

constructor(osuInstance: OsuInstance) {
super(osuInstance);
Expand Down Expand Up @@ -112,6 +114,9 @@ export class GamePlayData extends AbstractEntity {
};
this.isReplayUiHidden = false;

this.previousPassedObjects = 0;
this.GradualPerformance = null;

// below is gata that shouldn't be reseted on retry
if (isRetry === true) {
return;
Expand Down Expand Up @@ -548,6 +553,7 @@ export class GamePlayData extends AbstractEntity {
}

private updateStarsAndPerformance() {
const t1 = performance.now();
if (!config.calculatePP) {
wLogger.debug(
'GD(updateStarsAndPerformance) pp calculation disabled'
Expand Down Expand Up @@ -577,52 +583,83 @@ export class GamePlayData extends AbstractEntity {
return;
}

const scoreParams = {
passedObjects: calculatePassedObjects(
this.Mode,
this.Hit300,
this.Hit100,
this.Hit50,
this.HitMiss,
this.HitKatu,
this.HitGeki
),
combo: this.MaxCombo,
mods: this.Mods,
misses: this.HitMiss,
n50: this.Hit50,
n100: this.Hit100,
n300: this.Hit300
};

const currentState = `${menuData.MD5}:${menuData.MenuGameMode}:${this.Mods}:${menuData.MP3Length}`;

const isUpdate = this.previousState !== currentState;
if (isUpdate) {
this.previousState = currentState;

// update precalculated attributes
if (
isUpdate ||
!this.GradualPerformance ||
!this.PerformanceAttributes
) {
if (this.GradualPerformance) this.GradualPerformance.free();
if (this.PerformanceAttributes) this.PerformanceAttributes.free();

const calculate = new rosu.Performance(scoreParams).calculate(
const difficulty = new rosu.Difficulty({ mods: this.Mods });
this.GradualPerformance = new rosu.GradualPerformance(
difficulty,
currentBeatmap
);
this.PerformanceAttributes = calculate;

this.PerformanceAttributes = new rosu.Performance({
mods: this.Mods
}).calculate(currentBeatmap);

this.previousState = currentState;
}

const curPerformance = new rosu.Performance(scoreParams).calculate(
this.PerformanceAttributes!
if (!this.GradualPerformance && !this.PerformanceAttributes) return;

const passedObjects = calculatePassedObjects(
this.Mode,
this.Hit300,
this.Hit100,
this.Hit50,
this.HitMiss,
this.HitKatu,
this.HitGeki
);

const offset = passedObjects - this.previousPassedObjects;
if (offset <= 0) return;

const scoreParams: rosu.ScoreState = {
maxCombo: this.MaxCombo,
misses: this.HitMiss,
n50: this.Hit50,
n100: this.Hit100,
n300: this.Hit300,
nKatu: this.HitKatu,
nGeki: this.HitGeki
};

const curPerformance = this.GradualPerformance.nth(
scoreParams,
offset - 1
)!;

const fcPerformance = new rosu.Performance({
mods: this.Mods,
misses: 0,
accuracy: this.Accuracy
}).calculate(this.PerformanceAttributes!);
}).calculate(this.PerformanceAttributes);
const t2 = performance.now();

if (curPerformance) {
beatmapPpData.updateCurrentAttributes(
curPerformance.difficulty.stars,
curPerformance.pp
);
}

if (fcPerformance) {
beatmapPpData.updateFcPP(fcPerformance.pp);
}

this.PerformanceAttributes = curPerformance;
this.previousPassedObjects = passedObjects;

beatmapPpData.updateCurrentAttributes(
curPerformance.difficulty.stars,
curPerformance.pp
wLogger.debug(
`GD(updateStarsAndPerformance) [${(t2 - t1).toFixed(2)}ms] elapsed time`
);
beatmapPpData.updateFcPP(fcPerformance.pp);
}
}
24 changes: 6 additions & 18 deletions packages/tosu/src/entities/ResultsScreenData/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ import rosu from 'rosu-pp-js';

import { AbstractEntity } from '@/entities/AbstractEntity';
import { OsuInstance } from '@/objects/instanceManager/osuInstance';
import {
calculateAccuracy,
calculateGrade,
calculatePassedObjects
} from '@/utils/calculators';
import { calculateAccuracy, calculateGrade } from '@/utils/calculators';
import { netDateBinaryToDate } from '@/utils/converters';
import { OsuMods } from '@/utils/osuMods.types';

Expand Down Expand Up @@ -159,29 +155,21 @@ export class ResultsScreenData extends AbstractEntity {
return;
}

const scoreParams = {
passedObjects: calculatePassedObjects(
this.Mode,
this.Hit300,
this.Hit100,
this.Hit50,
this.HitMiss,
this.HitKatu,
this.HitGeki
),
const scoreParams: rosu.PerformanceArgs = {
combo: this.MaxCombo,
mods: this.Mods,
nMisses: this.HitMiss,
misses: this.HitMiss,
n50: this.Hit50,
n100: this.Hit100,
n300: this.Hit300
n300: this.Hit300,
nKatu: this.HitKatu,
nGeki: this.HitGeki
};

const curPerformance = new rosu.Performance(scoreParams).calculate(
currentBeatmap
);
const fcPerformance = new rosu.Performance({
combo: curPerformance.difficulty.maxCombo,
mods: this.Mods,
misses: 0,
accuracy: this.Accuracy
Expand Down
2 changes: 1 addition & 1 deletion packages/tosu/src/entities/TourneyUserProfileData/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class TourneyUserProfileData extends AbstractEntity {
wLogger.debug('TUPD(updateState) Slot is not equiped');

this.resetState();
gamePlayData.init();
gamePlayData.init(undefined, 'tourney');
return;
}

Expand Down
26 changes: 18 additions & 8 deletions packages/tosu/src/objects/instanceManager/osuInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ export class OsuInstance {
case 5:
// Reset Gameplay/ResultScreen data on joining to songSelect
if (!gamePlayData.isDefaultState) {
gamePlayData.init();
gamePlayData.init(undefined, '4,5');
resultsScreenData.init();
beatmapPpData.resetCurrentAttributes();
}
Expand All @@ -316,8 +316,8 @@ export class OsuInstance {
this.previousTime = allTimesData.PlayTime;

if (
allTimesData.PlayTime < 0 &&
!gamePlayData.isDefaultState
allTimesData.PlayTime <
Math.min(50, beatmapPpData.timings.firstObj)
) {
gamePlayData.init(true, 'not-default');
break;
Expand All @@ -338,7 +338,7 @@ export class OsuInstance {
break;

default:
gamePlayData.init();
gamePlayData.init(undefined, 'default');
resultsScreenData.init();
break;
}
Expand Down Expand Up @@ -400,7 +400,8 @@ export class OsuInstance {
'menuData',
'allTimesData',
'gamePlayData',
'beatmapPpData'
'beatmapPpData',
'resultsScreenData'
]);

this.updateMapMetadata(entities);
Expand All @@ -411,12 +412,21 @@ export class OsuInstance {
allTimesData: AllTimesData;
gamePlayData: GamePlayData;
beatmapPpData: BeatmapPPData;
resultsScreenData: ResultsScreenData;
}) {
const { menuData, allTimesData, gamePlayData, beatmapPpData } = entries;
const {
menuData,
allTimesData,
gamePlayData,
beatmapPpData,
resultsScreenData
} = entries;
const currentMods =
allTimesData.Status === 2 || allTimesData.Status === 7
allTimesData.Status === 2
? gamePlayData.Mods
: allTimesData.MenuMods;
: allTimesData.Status === 7
? resultsScreenData.Mods
: allTimesData.MenuMods;

const currentState = `${menuData.MD5}:${menuData.MenuGameMode}:${currentMods}:${menuData.MP3Length}`;

Expand Down
Loading