From a39dbdbefc08b061d92761b030b570ca5a905584 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 30 Jun 2024 22:52:18 +0300 Subject: [PATCH 1/6] fix: Fix incorrect realtime pp from previous update --- .../tosu/src/entities/GamePlayData/index.ts | 101 ++++++++++++------ 1 file changed, 69 insertions(+), 32 deletions(-) diff --git a/packages/tosu/src/entities/GamePlayData/index.ts b/packages/tosu/src/entities/GamePlayData/index.ts index e3fd1bab..28dd153d 100644 --- a/packages/tosu/src/entities/GamePlayData/index.ts +++ b/packages/tosu/src/entities/GamePlayData/index.ts @@ -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; @@ -58,6 +59,7 @@ export class GamePlayData extends AbstractEntity { private cachedkeys: string = ''; previousState: string = ''; + previousPassedObjects = 0; constructor(osuInstance: OsuInstance) { super(osuInstance); @@ -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; @@ -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' @@ -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); } } From df7a0aaeea02ee64d6a73a7c6bc38da495059088 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 30 Jun 2024 22:52:57 +0300 Subject: [PATCH 2/6] fix: Fix result screen pp --- .../src/entities/ResultsScreenData/index.ts | 24 +++++-------------- .../objects/instanceManager/osuInstance.ts | 18 ++++++++++---- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/packages/tosu/src/entities/ResultsScreenData/index.ts b/packages/tosu/src/entities/ResultsScreenData/index.ts index 70166771..57339675 100644 --- a/packages/tosu/src/entities/ResultsScreenData/index.ts +++ b/packages/tosu/src/entities/ResultsScreenData/index.ts @@ -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'; @@ -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 diff --git a/packages/tosu/src/objects/instanceManager/osuInstance.ts b/packages/tosu/src/objects/instanceManager/osuInstance.ts index c924f511..cfbca8a7 100644 --- a/packages/tosu/src/objects/instanceManager/osuInstance.ts +++ b/packages/tosu/src/objects/instanceManager/osuInstance.ts @@ -400,7 +400,8 @@ export class OsuInstance { 'menuData', 'allTimesData', 'gamePlayData', - 'beatmapPpData' + 'beatmapPpData', + 'resultsScreenData' ]); this.updateMapMetadata(entities); @@ -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}`; From a9a4e0c09fa7afe975457070971e71d81b76f518 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 30 Jun 2024 22:53:19 +0300 Subject: [PATCH 3/6] chore: fix gameplay data resets --- .../tosu/src/entities/TourneyUserProfileData/index.ts | 2 +- packages/tosu/src/objects/instanceManager/osuInstance.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/tosu/src/entities/TourneyUserProfileData/index.ts b/packages/tosu/src/entities/TourneyUserProfileData/index.ts index db33720e..064334ed 100644 --- a/packages/tosu/src/entities/TourneyUserProfileData/index.ts +++ b/packages/tosu/src/entities/TourneyUserProfileData/index.ts @@ -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; } diff --git a/packages/tosu/src/objects/instanceManager/osuInstance.ts b/packages/tosu/src/objects/instanceManager/osuInstance.ts index cfbca8a7..4b8effbb 100644 --- a/packages/tosu/src/objects/instanceManager/osuInstance.ts +++ b/packages/tosu/src/objects/instanceManager/osuInstance.ts @@ -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(); } @@ -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; @@ -338,7 +338,7 @@ export class OsuInstance { break; default: - gamePlayData.init(); + gamePlayData.init(undefined, 'default'); resultsScreenData.init(); break; } From a027b44b076c0ae5cf3c01ed5039f661830cfa0d Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 1 Jul 2024 02:04:20 +0300 Subject: [PATCH 4/6] fix: FIx graph offset on the maps with long sliders at the end --- .../tosu/src/entities/BeatmapPpData/index.ts | 52 ++++++++++++++----- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/packages/tosu/src/entities/BeatmapPpData/index.ts b/packages/tosu/src/entities/BeatmapPpData/index.ts index 99349a3f..3cd979d2 100644 --- a/packages/tosu/src/entities/BeatmapPpData/index.ts +++ b/packages/tosu/src/entities/BeatmapPpData/index.ts @@ -200,8 +200,7 @@ export class BeatmapPPData extends AbstractEntity { const { menuData, allTimesData } = this.osuInstance.getServices([ 'menuData', - 'allTimesData', - 'beatmapPpData' + 'allTimesData' ]); const mapPath = path.join( @@ -322,11 +321,6 @@ 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) [${( @@ -334,10 +328,38 @@ export class BeatmapPPData extends AbstractEntity { ).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 = ( @@ -410,19 +432,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(); From 31821ac4319aa9cadd59c143ea50a03e5f9a7327 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:08:36 +0300 Subject: [PATCH 5/6] chore: fix last obj time --- packages/tosu/src/entities/BeatmapPpData/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/tosu/src/entities/BeatmapPpData/index.ts b/packages/tosu/src/entities/BeatmapPpData/index.ts index 3cd979d2..00dfe68c 100644 --- a/packages/tosu/src/entities/BeatmapPpData/index.ts +++ b/packages/tosu/src/entities/BeatmapPpData/index.ts @@ -279,7 +279,6 @@ export class BeatmapPPData extends AbstractEntity { parseHitObjects: true, parseColours: false, - parseDifficulty: false, parseEditor: false, parseGeneral: false, parseStoryboard: false, From 2c4cd07973bd869cde18c85fe97db32f367f8690 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:55:33 +0300 Subject: [PATCH 6/6] chore: remove useless let --- packages/tosu/src/entities/BeatmapPpData/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/tosu/src/entities/BeatmapPpData/index.ts b/packages/tosu/src/entities/BeatmapPpData/index.ts index 00dfe68c..624baa1c 100644 --- a/packages/tosu/src/entities/BeatmapPpData/index.ts +++ b/packages/tosu/src/entities/BeatmapPpData/index.ts @@ -438,10 +438,10 @@ export class BeatmapPPData extends AbstractEntity { resultStrains.series[0].data.length - LEFT_OFFSET - RIGHT_OFFSET; - let lastTime = 0; for (let i = 0; i < total; i++) { - lastTime = firstObjectTime + i * sectionOffsetTime; - resultStrains.xaxis.push(lastTime); + resultStrains.xaxis.push( + firstObjectTime + i * sectionOffsetTime + ); } for (let i = 0; i < RIGHT_OFFSET; i++) {