diff --git a/src/components/CutStats.js b/src/components/CutStats.js new file mode 100644 index 0000000..3ec301c --- /dev/null +++ b/src/components/CutStats.js @@ -0,0 +1,38 @@ +import { useSettingsStore } from "../store/overlaySettingsStore"; +import { useSongDataStore } from "../store/songDataStore"; +import styles from "../styles/cutStats.module.css"; + +export default function CutStats() { + const [showScoreInfo] = useSettingsStore((store) => [store.showScoreInfo]); + const [saberA, saberB, isLoading] = useSongDataStore((store) => [ + store.saberA, + store.saberB, + store.isLoading, + ]); + + if (isLoading) { + return null; + } + + if (!showScoreInfo) { + return null; + } + + return ( +
+

Average Cut

+
+
+

{saberA.averagePreSwing.toFixed(2)}

+

{saberA.averagePostSwing.toFixed(2)}

+

{saberA.cutDistanceScore.toFixed(2)}

+
+
+

{saberB.averagePreSwing.toFixed(2)}

+

{saberB.averagePostSwing.toFixed(2)}

+

{saberB.cutDistanceScore.toFixed(2)}

+
+
+
+ ); +} diff --git a/src/components/ScoreStats.js b/src/components/ScoreStats.js index 314b500..c4f7e89 100644 --- a/src/components/ScoreStats.js +++ b/src/components/ScoreStats.js @@ -1,16 +1,16 @@ +import { getFormattedScorePercent } from "../helpers/map/mapHelpers"; import { useSettingsStore } from "../store/overlaySettingsStore"; import { useSongDataStore } from "../store/songDataStore"; import styles from "../styles/scoreStats.module.css"; export default function ScoreStats() { const [showScoreInfo] = useSettingsStore((store) => [store.showScoreInfo]); - const [percentage, currentScore, currentPP, saberA, saberB, isLoading] = + const [percentage, currentScore, currentPP, combo, isLoading] = useSongDataStore((store) => [ store.percentage, store.currentScore, store.currentPP, - store.saberA, - store.saberB, + store.combo, store.isLoading, ]); @@ -24,27 +24,30 @@ export default function ScoreStats() { return (
+

+ {currentScore.toLocaleString("en-us", { + maximumFractionDigits: 0, + minimumFractionDigits: 0, + })} +

-

{percentage}

-

- {currentScore.toLocaleString("en-us", { - maximumFractionDigits: 2, - minimumFractionDigits: 2, - })} -

- {currentPP !== undefined ?

{currentPP.toFixed(0)}pp

: null} -
-

Average Cut

-
-
-

{saberA.averagePreSwing.toFixed(2)}

-

{saberA.averagePostSwing.toFixed(2)}

-

{saberA.cutDistanceScore.toFixed(2)}

-
-
-

{saberB.averagePreSwing.toFixed(2)}

-

{saberB.averagePostSwing.toFixed(2)}

-

{saberB.cutDistanceScore.toFixed(2)}

+
+

Combo: {combo}

+

+ + {getFormattedScorePercent(percentage)} + + {percentage}% +

+ {currentPP !== undefined ?

{currentPP.toFixed(0)}pp

: null}
diff --git a/src/helpers/map/mapHelpers.ts b/src/helpers/map/mapHelpers.ts index 2951dd0..678daa5 100644 --- a/src/helpers/map/mapHelpers.ts +++ b/src/helpers/map/mapHelpers.ts @@ -1,3 +1,31 @@ export function getMapHashFromLevelId(levelId: string): string { return levelId.replace("custom_level_", ""); } + +/** + * Formats the score. + * eg: 91% = SS + * + * @param percent The percentage of the current score + */ +export function getFormattedScorePercent(percent: number): string { + if (percent >= 90) { + return "SS"; + } + if (percent >= 80) { + return "S"; + } + if (percent >= 65) { + return "A"; + } + if (percent >= 50) { + return "B"; + } + if (percent >= 35) { + return "C"; + } + if (percent >= 20) { + return "D"; + } + return "E"; +} diff --git a/src/helpers/websocketClient.ts b/src/helpers/websocketClient.ts index 497175c..1b4b492 100644 --- a/src/helpers/websocketClient.ts +++ b/src/helpers/websocketClient.ts @@ -3,7 +3,6 @@ import { useDataStore } from "../store/overlayDataStore"; import { useSettingsStore } from "../store/overlaySettingsStore"; import { usePlayerDataStore } from "../store/playerDataStore"; import { useSongDataStore } from "../store/songDataStore"; -import Utils from "../utils/utils"; import { getMapHashFromLevelId } from "./map/mapHelpers"; const ip = useSettingsStore.getState().socketAddr; @@ -29,7 +28,9 @@ export function connectClient(attempt: number = 1) { }; client.onclose = () => { console.log( - `Unable to connect to HTTPSiraStatus, retrying in ${retryTime} seconds. (Attempt: ${attempt})` + `Unable to connect to HTTPSiraStatus, retrying in ${ + retryTime / 1000 + } seconds. (Attempt: ${attempt})` ); setTimeout(() => { @@ -71,15 +72,8 @@ const handlers: any = { } = data.status.beatmap; state.reset(); state.setInSong(true); + state.setCombo(data.status.performance.combo); useDataStore.setState({ loadedDuringSong: true }); - state.updateMapData( - getMapHashFromLevelId(levelId), - difficultyEnum, - characteristic, - songName, - songSubName || levelAuthorName, - length - ); const { score, relativeScore } = data.status.performance; let finalScore = score; @@ -89,7 +83,17 @@ const handlers: any = { const percent = relativeScore * 100; state.setCurrentScore(finalScore); - state.setPercent(percent.toFixed(2) + "%"); + state.setPercent(percent.toFixed(2)); + state.setPp(percent); + + state.updateMapData( + getMapHashFromLevelId(levelId), + difficultyEnum, + characteristic, + songName, + songSubName || levelAuthorName, + length + ); } }, @@ -128,19 +132,9 @@ const handlers: any = { const percent = relativeScore * 100; state.setCurrentScore(finalScore); - state.setPercent(percent.toFixed(2) + "%"); - - const leaderboardType = useSettingsStore.getState().leaderboardType; - let currentPP = Utils.calculatePP( - state.mapStarCount, - percent, - leaderboardType - ); - if (currentPP === undefined) { - return; - } - - state.setPp(currentPP); + state.setPercent(percent.toFixed(2)); + state.setCombo(data.status.performance.combo); + state.setPp(percent); }, noteFullyCut: (data: any) => { diff --git a/src/pages/overlay.js b/src/pages/overlay.js index ee82f07..5049329 100644 --- a/src/pages/overlay.js +++ b/src/pages/overlay.js @@ -1,6 +1,7 @@ import axios from "axios"; import { NextSeo } from "next-seo"; import { useEffect } from "react"; +import CutStats from "../components/CutStats"; import PlayerStats from "../components/PlayerStats"; import ScoreStats from "../components/ScoreStats"; import SongInfo from "../components/SongInfo"; @@ -59,6 +60,7 @@ export default function Overlay(props) {
+
diff --git a/src/store/songDataStore.ts b/src/store/songDataStore.ts index ac602f2..2146746 100644 --- a/src/store/songDataStore.ts +++ b/src/store/songDataStore.ts @@ -21,6 +21,7 @@ interface SongDataState { currentSongTime: number; currentScore: number; percentage: string; + combo: number; currentPP: number | undefined; saberA: { cutDistanceScore: number; @@ -45,7 +46,8 @@ interface SongDataState { setPaused: (paused: boolean) => void; setCurrentScore: (score: number) => void; setPercent: (percent: string) => void; - setPp: (pp: number) => void; + setCombo: (combo: number) => void; + setPp: (percent: number) => void; setInSong: (isInSong: boolean) => void; setSaberData: (saberType: string, cutData: any) => void; } @@ -67,6 +69,7 @@ export const useSongDataStore = create()((set) => ({ currentSongTime: 0, currentScore: 0, percentage: "100%", + combo: 0, currentPP: undefined, saberA: { cutDistanceScore: 0.0, @@ -133,6 +136,10 @@ export const useSongDataStore = create()((set) => ({ set({ percentage: percent }); }, + setCombo: (combo: number) => { + set({ combo: combo }); + }, + setSaberData: (saberType: string, saberData: any) => { if (saberType === "saberA") { set({ saberA: saberData }); @@ -141,7 +148,14 @@ export const useSongDataStore = create()((set) => ({ } }, - setPp: (pp: number) => { + setPp: (percent: number) => { + const leaderboardType = useSettingsStore.getState().leaderboardType; + const mapStarCount = useSongDataStore.getState().mapStarCount; + + let pp = Utils.calculatePP(mapStarCount, percent, leaderboardType); + if (pp === undefined) { + return; + } set({ currentPP: pp }); }, @@ -165,6 +179,7 @@ export const useSongDataStore = create()((set) => ({ currentSongTime: 0, currentScore: 0, percentage: "100%", + combo: 0, currentPP: undefined, saberA: { cutDistanceScore: 0.0, diff --git a/src/styles/cutStats.module.css b/src/styles/cutStats.module.css new file mode 100644 index 0000000..e3f98fc --- /dev/null +++ b/src/styles/cutStats.module.css @@ -0,0 +1,44 @@ +.cutStats { + text-align: center; + position: fixed; + top: 0; + right: 0; + margin-top: 5px; + margin-right: 5px; + min-width: 135px; + + display: flex; + justify-content: right; + flex-direction: column; +} + +.cutStats p { + font-size: 38px; + line-height: 1.2em; +} + +.cutStatsLeft { + text-align: right; + margin-right: 3px; +} + +.cutStatsRight { + text-align: left; +} + +.cutStatsAverageCut { + font-weight: bold; +} + +.cutStatsHands { + display: flex; + justify-content: center; +} + +.cutStatsHands p { + min-width: 68px; +} + +.cutStatsHands div { + padding-left: 10px; +} diff --git a/src/styles/overlay.module.css b/src/styles/overlay.module.css index 40a964e..0f08423 100644 --- a/src/styles/overlay.module.css +++ b/src/styles/overlay.module.css @@ -3,6 +3,7 @@ color: white; font-size: xx-large; line-height: 1.4em !important; + height: fit-content; } .main p { diff --git a/src/styles/scoreStats.module.css b/src/styles/scoreStats.module.css index a5f6764..249a05a 100644 --- a/src/styles/scoreStats.module.css +++ b/src/styles/scoreStats.module.css @@ -1,50 +1,19 @@ .scoreStats { - text-align: center; position: fixed; - top: 0; - right: 0; - margin-top: 5px; - margin-right: 5px; + margin-top: -5px; + margin-left: 10px; min-width: 135px; display: flex; - justify-content: right; flex-direction: column; - align-items: right; } .scoreStats p { font-size: 38px; - line-height: 1.2em; -} - -.scoreStatsLeft { - text-align: right; - margin-right: 3px; -} - -.scoreStatsRight { - text-align: left; -} - -.scoreStatsAverageCut { - font-weight: bold; -} - -.scoreStatsHands { - display: flex; - justify-content: center; -} - -.scoreStatsHands p { - min-width: 68px; -} - -.scoreStatsHands div { - padding-left: 10px; + line-height: 1.1em; + font-size: 35px; } .scoreStatsInfo { margin-right: 10px; - text-align: right; }