From f705218bfd9872758a45f49b816b10087945debd Mon Sep 17 00:00:00 2001 From: Liam Date: Sat, 14 Sep 2024 18:40:39 +0100 Subject: [PATCH] add hover transition to the footer --- pnpm-lock.yaml | 244 ++++++++++-------- src/common/database/types/beatsaver-map.ts | 2 +- src/common/leaderboards.ts | 8 +- .../model/score/impl/scoresaber-score.ts | 57 ++++ src/common/model/score/modifier.ts | 18 ++ src/common/model/score/score.ts | 116 +++++++++ .../beatsaver/beat-saver-account-token.ts} | 2 +- .../beat-saver-map-metadata-token.ts} | 2 +- .../beatsaver/beat-saver-map-stats-token.ts} | 2 +- .../token/beatsaver/beat-saver-map-token.ts | 24 ++ .../scoresaber/score-saber-badge-token.ts} | 2 +- .../score-saber-difficulty-token.ts} | 2 +- ...re-saber-leaderboard-player-info-token.ts} | 2 +- ...ore-saber-leaderboard-scores-page-token.ts | 14 + .../score-saber-leaderboard-token.ts} | 8 +- .../scoresaber/score-saber-metadata-token.ts} | 2 +- .../score-saber-player-score-token.ts | 14 + .../score-saber-player-scores-page-token.ts | 14 + .../score-saber-player-search-token.ts | 8 + .../scoresaber/score-saber-player-token.ts} | 10 +- .../score-saber-score-stats-token.ts} | 2 +- .../scoresaber/score-saber-score-token.ts} | 10 +- src/common/service/impl/beatsaver.ts | 2 +- src/common/service/impl/scoresaber.ts | 24 +- .../service/types/beatsaver/beatsaver-map.ts | 24 -- .../scoresaber-leaderboard-scores-page.ts | 14 - .../scoresaber/scoresaber-player-score.ts | 14 - .../scoresaber-player-scores-page.ts | 14 - .../scoresaber/scoresaber-player-search.ts | 8 - src/common/{workers => worker}/worker.ts | 0 src/common/{workers => worker}/workers.ts | 2 +- src/components/footer.tsx | 2 +- src/components/input/search-player.tsx | 4 +- .../leaderboard/leaderboard-player.tsx | 4 +- .../leaderboard/leaderboard-score-stats.tsx | 21 +- .../leaderboard/leaderboard-score.tsx | 8 +- .../leaderboard/leaderboard-scores.tsx | 8 +- src/components/player/player-data.tsx | 8 +- src/components/player/player-header.tsx | 12 +- src/components/player/player-rank-chart.tsx | 4 +- src/components/player/player-scores.tsx | 10 +- src/components/player/player-stats.tsx | 20 +- src/components/score/score-buttons.tsx | 4 +- src/components/score/score-info.tsx | 4 +- src/components/score/score-rank-info.tsx | 4 +- src/components/score/score-stats.tsx | 32 ++- src/components/score/score.tsx | 4 +- tsconfig.json | 1 - 48 files changed, 527 insertions(+), 288 deletions(-) create mode 100644 src/common/model/score/impl/scoresaber-score.ts create mode 100644 src/common/model/score/modifier.ts create mode 100644 src/common/model/score/score.ts rename src/common/{service/types/beatsaver/beatsaver-account.ts => model/token/beatsaver/beat-saver-account-token.ts} (93%) rename src/common/{service/types/beatsaver/beatsaver-map-metadata.ts => model/token/beatsaver/beat-saver-map-metadata-token.ts} (89%) rename src/common/{service/types/beatsaver/beatsaver-map-stats.ts => model/token/beatsaver/beat-saver-map-stats-token.ts} (90%) create mode 100644 src/common/model/token/beatsaver/beat-saver-map-token.ts rename src/common/{service/types/scoresaber/scoresaber-badge.ts => model/token/scoresaber/score-saber-badge-token.ts} (76%) rename src/common/{service/types/scoresaber/scoresaber-difficulty.ts => model/token/scoresaber/score-saber-difficulty-token.ts} (63%) rename src/common/{service/types/scoresaber/scoresaber-leaderboard-player-info.ts => model/token/scoresaber/score-saber-leaderboard-player-info-token.ts} (64%) create mode 100644 src/common/model/token/scoresaber/score-saber-leaderboard-scores-page-token.ts rename src/common/{service/types/scoresaber/scoresaber-leaderboard.ts => model/token/scoresaber/score-saber-leaderboard-token.ts} (66%) rename src/common/{service/types/scoresaber/scoresaber-metadata.ts => model/token/scoresaber/score-saber-metadata-token.ts} (79%) create mode 100644 src/common/model/token/scoresaber/score-saber-player-score-token.ts create mode 100644 src/common/model/token/scoresaber/score-saber-player-scores-page-token.ts create mode 100644 src/common/model/token/scoresaber/score-saber-player-search-token.ts rename src/common/{service/types/scoresaber/scoresaber-player.ts => model/token/scoresaber/score-saber-player-token.ts} (79%) rename src/common/{service/types/scoresaber/scoresaber-score-stats.ts => model/token/scoresaber/score-saber-score-stats-token.ts} (91%) rename src/common/{service/types/scoresaber/scoresaber-score.ts => model/token/scoresaber/score-saber-score-token.ts} (53%) delete mode 100644 src/common/service/types/beatsaver/beatsaver-map.ts delete mode 100644 src/common/service/types/scoresaber/scoresaber-leaderboard-scores-page.ts delete mode 100644 src/common/service/types/scoresaber/scoresaber-player-score.ts delete mode 100644 src/common/service/types/scoresaber/scoresaber-player-scores-page.ts delete mode 100644 src/common/service/types/scoresaber/scoresaber-player-search.ts rename src/common/{workers => worker}/worker.ts (100%) rename src/common/{workers => worker}/workers.ts (75%) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f2ee6b6..668851a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,28 +16,28 @@ importers: version: 2.1.5(react@18.3.1) '@hookform/resolvers': specifier: ^3.9.0 - version: 3.9.0(react-hook-form@7.53.0) + version: 3.9.0(react-hook-form@7.53.0(react@18.3.1)) '@radix-ui/react-avatar': specifier: ^1.1.0 - version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-icons': specifier: ^1.3.0 version: 1.3.0(react@18.3.1) '@radix-ui/react-label': specifier: ^2.1.0 - version: 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + version: 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-scroll-area': specifier: ^1.1.0 - version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': specifier: ^1.1.0 version: 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-toast': specifier: ^1.2.1 - version: 1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + version: 1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tooltip': specifier: ^1.1.2 - version: 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + version: 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tanstack/react-query': specifier: ^5.55.4 version: 5.56.2(react@18.3.1) @@ -61,7 +61,7 @@ importers: version: 1.1.7(@types/react@18.3.5)(dexie@4.0.8)(react@18.3.1) framer-motion: specifier: ^11.5.4 - version: 11.5.4(react-dom@18.3.1)(react@18.3.1) + version: 11.5.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) ky: specifier: ^1.7.2 version: 1.7.2 @@ -70,13 +70,13 @@ importers: version: 0.441.0(react@18.3.1) next: specifier: 14.2.11 - version: 14.2.11(react-dom@18.3.1)(react@18.3.1) + version: 14.2.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-build-id: specifier: ^3.0.0 version: 3.0.0 next-themes: specifier: ^0.3.0 - version: 0.3.0(react-dom@18.3.1)(react@18.3.1) + version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18 version: 18.3.1 @@ -2087,7 +2087,7 @@ snapshots: '@floating-ui/core': 1.6.7 '@floating-ui/utils': 0.2.7 - '@floating-ui/react-dom@2.1.1(react-dom@18.3.1)(react@18.3.1)': + '@floating-ui/react-dom@2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@floating-ui/dom': 1.6.10 react: 18.3.1 @@ -2101,7 +2101,7 @@ snapshots: dependencies: react: 18.3.1 - '@hookform/resolvers@3.9.0(react-hook-form@7.53.0)': + '@hookform/resolvers@3.9.0(react-hook-form@7.53.0(react@18.3.1))': dependencies: react-hook-form: 7.53.0(react@18.3.1) @@ -2199,62 +2199,69 @@ snapshots: '@radix-ui/primitive@1.1.0': {} - '@radix-ui/react-arrow@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-arrow@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 - '@radix-ui/react-avatar@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-avatar@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-context': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 - '@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-context': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 '@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.5)(react@18.3.1)': dependencies: - '@types/react': 18.3.5 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.5 '@radix-ui/react-context@1.1.0(@types/react@18.3.5)(react@18.3.1)': dependencies: - '@types/react': 18.3.5 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.5 '@radix-ui/react-direction@1.1.0(@types/react@18.3.5)(react@18.3.1)': dependencies: - '@types/react': 18.3.5 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.5 - '@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 '@radix-ui/react-icons@1.3.0(react@18.3.1)': dependencies: @@ -2263,161 +2270,178 @@ snapshots: '@radix-ui/react-id@1.1.0(@types/react@18.3.5)(react@18.3.1)': dependencies: '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 react: 18.3.1 - - '@radix-ui/react-label@2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': - dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + optionalDependencies: '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 + + '@radix-ui/react-label@2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 - '@radix-ui/react-popper@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-popper@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/react-dom': 2.1.1(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-arrow': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + '@floating-ui/react-dom': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-context': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-use-rect': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/rect': 1.1.0 - '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 - '@radix-ui/react-portal@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-portal@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 - '@radix-ui/react-presence@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-presence@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 - '@radix-ui/react-primitive@2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-primitive@2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-slot': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 - '@radix-ui/react-scroll-area@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-scroll-area@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.0 '@radix-ui/primitive': 1.1.0 '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-context': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-direction': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 '@radix-ui/react-slot@1.1.0(@types/react@18.3.5)(react@18.3.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.5 - '@radix-ui/react-toast@1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-toast@1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-context': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 + '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 - '@radix-ui/react-tooltip@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-tooltip@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-context': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-id': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.1.0(@types/react@18.3.5)(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 + '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.5)(react@18.3.1)': dependencies: - '@types/react': 18.3.5 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.5 '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.5)(react@18.3.1)': dependencies: '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.5 '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.5)(react@18.3.1)': dependencies: '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.5 '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.5)(react@18.3.1)': dependencies: - '@types/react': 18.3.5 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.5 '@radix-ui/react-use-rect@1.1.0(@types/react@18.3.5)(react@18.3.1)': dependencies: '@radix-ui/rect': 1.1.0 - '@types/react': 18.3.5 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.5 '@radix-ui/react-use-size@1.1.0(@types/react@18.3.5)(react@18.3.1)': dependencies: '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.5)(react@18.3.1) - '@types/react': 18.3.5 react: 18.3.1 - - '@radix-ui/react-visually-hidden@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1)': - dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1) + optionalDependencies: '@types/react': 18.3.5 - '@types/react-dom': 18.3.0 + + '@radix-ui/react-visually-hidden@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.5 + '@types/react-dom': 18.3.0 '@radix-ui/rect@1.1.0': {} @@ -2460,7 +2484,7 @@ snapshots: '@types/semver@7.5.8': {} - '@typescript-eslint/eslint-plugin@7.2.0(@typescript-eslint/parser@7.2.0)(eslint@8.57.0)(typescript@5.6.2)': + '@typescript-eslint/eslint-plugin@7.2.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2)': dependencies: '@eslint-community/regexpp': 4.11.0 '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.6.2) @@ -2475,6 +2499,7 @@ snapshots: natural-compare: 1.4.0 semver: 7.6.3 ts-api-utils: 1.3.0(typescript@5.6.2) + optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color @@ -2487,6 +2512,7 @@ snapshots: '@typescript-eslint/visitor-keys': 7.2.0 debug: 4.3.6 eslint: 8.57.0 + optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color @@ -2503,6 +2529,7 @@ snapshots: debug: 4.3.6 eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.6.2) + optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color @@ -2519,6 +2546,7 @@ snapshots: minimatch: 9.0.3 semver: 7.6.3 ts-api-utils: 1.3.0(typescript@5.6.2) + optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color @@ -2955,15 +2983,16 @@ snapshots: dependencies: '@next/eslint-plugin-next': 14.2.11 '@rushstack/eslint-patch': 1.10.4 - '@typescript-eslint/eslint-plugin': 7.2.0(@typescript-eslint/parser@7.2.0)(eslint@8.57.0)(typescript@5.6.2) + '@typescript-eslint/eslint-plugin': 7.2.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2) '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.6.2) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0) - eslint-plugin-import: 2.30.0(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0) + eslint-plugin-import: 2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.10.0(eslint@8.57.0) eslint-plugin-react: 7.35.2(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) + optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - eslint-import-resolver-webpack @@ -2978,38 +3007,39 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.3.6 enhanced-resolve: 5.17.1 eslint: 8.57.0 - eslint-module-utils: 2.9.0(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) - eslint-plugin-import: 2.30.0(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) + eslint-module-utils: 2.9.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.8.0 is-bun-module: 1.1.0 is-glob: 4.0.3 + optionalDependencies: + eslint-plugin-import: 2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.9.0(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): + eslint-module-utils@2.9.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0): dependencies: - '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.6.2) debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.6.2) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): + eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): dependencies: '@rtsao/scc': 1.1.0 - '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.6.2) array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 array.prototype.flat: 1.3.2 @@ -3018,7 +3048,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.9.0(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) + eslint-module-utils: 2.9.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -3028,6 +3058,8 @@ snapshots: object.values: 1.2.0 semver: 6.3.1 tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.6.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -3195,11 +3227,12 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - framer-motion@11.5.4(react-dom@18.3.1)(react@18.3.1): + framer-motion@11.5.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: + tslib: 2.7.0 + optionalDependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - tslib: 2.7.0 fs.realpath@1.0.0: {} @@ -3571,12 +3604,12 @@ snapshots: next-build-id@3.0.0: {} - next-themes@0.3.0(react-dom@18.3.1)(react@18.3.1): + next-themes@0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@14.2.11(react-dom@18.3.1)(react@18.3.1): + next@14.2.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@next/env': 14.2.11 '@swc/helpers': 0.5.5 @@ -3715,8 +3748,9 @@ snapshots: postcss-load-config@4.0.2(postcss@8.4.45): dependencies: lilconfig: 3.1.2 - postcss: 8.4.45 yaml: 2.5.1 + optionalDependencies: + postcss: 8.4.45 postcss-nested@6.2.0(postcss@8.4.45): dependencies: diff --git a/src/common/database/types/beatsaver-map.ts b/src/common/database/types/beatsaver-map.ts index 6fcaf09..d58eaa5 100644 --- a/src/common/database/types/beatsaver-map.ts +++ b/src/common/database/types/beatsaver-map.ts @@ -1,4 +1,4 @@ -import { BeatSaverMap as BSMap } from "@/common/service/types/beatsaver/beatsaver-map"; +import { BeatSaverMapToken as BSMap } from "@/common/model/token/beatsaver/beat-saver-map-token"; import { Entity } from "dexie"; import Database from "../database"; diff --git a/src/common/leaderboards.ts b/src/common/leaderboards.ts index 980896c..4e9a725 100644 --- a/src/common/leaderboards.ts +++ b/src/common/leaderboards.ts @@ -1,4 +1,4 @@ -import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player"; +import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token"; import { scoresaberService } from "@/common/service/impl/scoresaber"; import { ScoreSort } from "@/common/service/score-sort"; @@ -8,7 +8,11 @@ export const leaderboards = { search: true, }, queries: { - lookupScores: (player: ScoreSaberPlayer, sort: ScoreSort, page: number) => + lookupScores: ( + player: ScoreSaberPlayerToken, + sort: ScoreSort, + page: number, + ) => scoresaberService.lookupPlayerScores({ playerId: player.id, sort: sort, diff --git a/src/common/model/score/impl/scoresaber-score.ts b/src/common/model/score/impl/scoresaber-score.ts new file mode 100644 index 0000000..d293b35 --- /dev/null +++ b/src/common/model/score/impl/scoresaber-score.ts @@ -0,0 +1,57 @@ +import Score from "@/common/model/score/score"; +import { Modifier } from "@/common/model/score/modifier"; +import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token"; + +export default class ScoreSaberScore extends Score { + constructor( + score: number, + weight: number | undefined, + rank: number, + worth: number, + modifiers: Modifier[], + misses: number, + badCuts: number, + fullCombo: boolean, + timestamp: Date, + ) { + super( + score, + weight, + rank, + worth, + modifiers, + misses, + badCuts, + fullCombo, + timestamp, + ); + } + + /** + * Gets a {@link ScoreSaberScore} from a {@link ScoreSaberScoreToken}. + * + * @param token the token to convert + */ + public static fromToken(token: ScoreSaberScoreToken): ScoreSaberScore { + const modifiers: Modifier[] = token.modifiers.split(",").map((mod) => { + mod = mod.toUpperCase(); + const modifier = Modifier[mod as keyof typeof Modifier]; + if (modifier === undefined) { + throw new Error(`Unknown modifier: ${mod}`); + } + return modifier; + }); + + return new ScoreSaberScore( + token.baseScore, + token.weight, + token.rank, + token.pp, + modifiers, + token.missedNotes, + token.badCuts, + token.fullCombo, + new Date(token.timeSet), + ); + } +} diff --git a/src/common/model/score/modifier.ts b/src/common/model/score/modifier.ts new file mode 100644 index 0000000..6c4b05d --- /dev/null +++ b/src/common/model/score/modifier.ts @@ -0,0 +1,18 @@ +/** + * The score modifiers. + */ +export enum Modifier { + DA = "Disappearing Arrows", + FS = "Faster Song", + SF = "Super Fast Song", + SS = "Slower Song", + GN = "Ghost Notes", + NA = "No Arrows", + NO = "No Obstacles", + SA = "Strict Angles", + SC = "Small Notes", + PM = "Pro Mode", + CS = "Fail on Saber Clash", + IF = "One Life", + BE = "Battery Energy", +} diff --git a/src/common/model/score/score.ts b/src/common/model/score/score.ts new file mode 100644 index 0000000..8c04764 --- /dev/null +++ b/src/common/model/score/score.ts @@ -0,0 +1,116 @@ +import { Modifier } from "@/common/model/score/modifier"; + +export default class Score { + /** + * The base score for the score. + * @private + */ + private readonly _score: number; + + /** + * The weight of the score, or undefined if not ranked.s + * @private + */ + private readonly _weight: number | undefined; + + /** + * The rank for the score. + * @private + */ + private readonly _rank: number; + + /** + * The worth of the score (this could be pp, ap, cr, etc.), + * or undefined if not ranked. + * @private + */ + private readonly _worth: number; + + /** + * The modifiers used on the score. + * @private + */ + private readonly _modifiers: Modifier[]; + + /** + * The amount missed notes. + * @private + */ + private readonly _misses: number; + + /** + * The amount of bad cuts. + * @private + */ + private readonly _badCuts: number; + + /** + * Whether every note was hit. + * @private + */ + private readonly _fullCombo: boolean; + + /** + * The time the score was set. + * @private + */ + private readonly _timestamp: Date; + + constructor( + score: number, + weight: number | undefined, + rank: number, + worth: number, + modifiers: Modifier[], + misses: number, + badCuts: number, + fullCombo: boolean, + timestamp: Date, + ) { + this._score = score; + this._weight = weight; + this._rank = rank; + this._worth = worth; + this._modifiers = modifiers; + this._misses = misses; + this._badCuts = badCuts; + this._fullCombo = fullCombo; + this._timestamp = timestamp; + } + + get score(): number { + return this._score; + } + + get weight(): number | undefined { + return this._weight; + } + + get rank(): number { + return this._rank; + } + + get worth(): number { + return this._worth; + } + + get modifiers(): Modifier[] { + return this._modifiers; + } + + get misses(): number { + return this._misses; + } + + get badCuts(): number { + return this._badCuts; + } + + get fullCombo(): boolean { + return this._fullCombo; + } + + get timestamp(): Date { + return this._timestamp; + } +} diff --git a/src/common/service/types/beatsaver/beatsaver-account.ts b/src/common/model/token/beatsaver/beat-saver-account-token.ts similarity index 93% rename from src/common/service/types/beatsaver/beatsaver-account.ts rename to src/common/model/token/beatsaver/beat-saver-account-token.ts index 3fe03a5..128dd33 100644 --- a/src/common/service/types/beatsaver/beatsaver-account.ts +++ b/src/common/model/token/beatsaver/beat-saver-account-token.ts @@ -1,4 +1,4 @@ -export default interface BeatSaverAccount { +export default interface BeatSaverAccountToken { /** * The id of the mapper */ diff --git a/src/common/service/types/beatsaver/beatsaver-map-metadata.ts b/src/common/model/token/beatsaver/beat-saver-map-metadata-token.ts similarity index 89% rename from src/common/service/types/beatsaver/beatsaver-map-metadata.ts rename to src/common/model/token/beatsaver/beat-saver-map-metadata-token.ts index ede765e..e6b41eb 100644 --- a/src/common/service/types/beatsaver/beatsaver-map-metadata.ts +++ b/src/common/model/token/beatsaver/beat-saver-map-metadata-token.ts @@ -1,4 +1,4 @@ -export default interface BeatSaverMapMetadata { +export default interface BeatSaverMapMetadataToken { /** * The bpm of the song. */ diff --git a/src/common/service/types/beatsaver/beatsaver-map-stats.ts b/src/common/model/token/beatsaver/beat-saver-map-stats-token.ts similarity index 90% rename from src/common/service/types/beatsaver/beatsaver-map-stats.ts rename to src/common/model/token/beatsaver/beat-saver-map-stats-token.ts index 86126dc..f4ffa8a 100644 --- a/src/common/service/types/beatsaver/beatsaver-map-stats.ts +++ b/src/common/model/token/beatsaver/beat-saver-map-stats-token.ts @@ -1,4 +1,4 @@ -export default interface BeatSaverMapStats { +export default interface BeatSaverMapStatsToken { /** * The amount of time the map has been played. */ diff --git a/src/common/model/token/beatsaver/beat-saver-map-token.ts b/src/common/model/token/beatsaver/beat-saver-map-token.ts new file mode 100644 index 0000000..5696367 --- /dev/null +++ b/src/common/model/token/beatsaver/beat-saver-map-token.ts @@ -0,0 +1,24 @@ +import BeatSaverAccountToken from "./beat-saver-account-token"; +import BeatSaverMapMetadataToken from "./beat-saver-map-metadata-token"; +import BeatSaverMapStatsToken from "./beat-saver-map-stats-token"; + +export interface BeatSaverMapToken { + id: string; + name: string; + description: string; + uploader: BeatSaverAccountToken; + metadata: BeatSaverMapMetadataToken; + stats: BeatSaverMapStatsToken; + uploaded: string; + automapper: boolean; + ranked: boolean; + qualified: boolean; + // todo: versions + createdAt: string; + updatedAt: string; + lastPublishedAt: string; + tags: string[]; + declaredAi: string; + blRanked: boolean; + blQualified: boolean; +} diff --git a/src/common/service/types/scoresaber/scoresaber-badge.ts b/src/common/model/token/scoresaber/score-saber-badge-token.ts similarity index 76% rename from src/common/service/types/scoresaber/scoresaber-badge.ts rename to src/common/model/token/scoresaber/score-saber-badge-token.ts index c68868a..d0c7412 100644 --- a/src/common/service/types/scoresaber/scoresaber-badge.ts +++ b/src/common/model/token/scoresaber/score-saber-badge-token.ts @@ -1,4 +1,4 @@ -export interface ScoreSaberBadge { +export interface ScoreSaberBadgeToken { /** * The description of the badge. */ diff --git a/src/common/service/types/scoresaber/scoresaber-difficulty.ts b/src/common/model/token/scoresaber/score-saber-difficulty-token.ts similarity index 63% rename from src/common/service/types/scoresaber/scoresaber-difficulty.ts rename to src/common/model/token/scoresaber/score-saber-difficulty-token.ts index d5ffce1..48dada2 100644 --- a/src/common/service/types/scoresaber/scoresaber-difficulty.ts +++ b/src/common/model/token/scoresaber/score-saber-difficulty-token.ts @@ -1,4 +1,4 @@ -export default interface ScoreSaberDifficulty { +export default interface ScoreSaberDifficultyToken { leaderboardId: number; difficulty: number; gameMode: string; diff --git a/src/common/service/types/scoresaber/scoresaber-leaderboard-player-info.ts b/src/common/model/token/scoresaber/score-saber-leaderboard-player-info-token.ts similarity index 64% rename from src/common/service/types/scoresaber/scoresaber-leaderboard-player-info.ts rename to src/common/model/token/scoresaber/score-saber-leaderboard-player-info-token.ts index 81554ee..f450c58 100644 --- a/src/common/service/types/scoresaber/scoresaber-leaderboard-player-info.ts +++ b/src/common/model/token/scoresaber/score-saber-leaderboard-player-info-token.ts @@ -1,4 +1,4 @@ -export default interface ScoreSaberLeaderboardPlayerInfo { +export default interface ScoreSaberLeaderboardPlayerInfoToken { id: string; name: string; profilePicture: string; diff --git a/src/common/model/token/scoresaber/score-saber-leaderboard-scores-page-token.ts b/src/common/model/token/scoresaber/score-saber-leaderboard-scores-page-token.ts new file mode 100644 index 0000000..8220699 --- /dev/null +++ b/src/common/model/token/scoresaber/score-saber-leaderboard-scores-page-token.ts @@ -0,0 +1,14 @@ +import ScoreSaberMetadataToken from "./score-saber-metadata-token"; +import ScoreSaberScoreToken from "./score-saber-score-token"; + +export default interface ScoreSaberLeaderboardScoresPageToken { + /** + * The scores on this page. + */ + scores: ScoreSaberScoreToken[]; + + /** + * The metadata for the page. + */ + metadata: ScoreSaberMetadataToken; +} diff --git a/src/common/service/types/scoresaber/scoresaber-leaderboard.ts b/src/common/model/token/scoresaber/score-saber-leaderboard-token.ts similarity index 66% rename from src/common/service/types/scoresaber/scoresaber-leaderboard.ts rename to src/common/model/token/scoresaber/score-saber-leaderboard-token.ts index 9eb89be..5434a72 100644 --- a/src/common/service/types/scoresaber/scoresaber-leaderboard.ts +++ b/src/common/model/token/scoresaber/score-saber-leaderboard-token.ts @@ -1,13 +1,13 @@ -import ScoreSaberDifficulty from "./scoresaber-difficulty"; +import ScoreSaberDifficultyToken from "./score-saber-difficulty-token"; -export default interface ScoreSaberLeaderboard { +export default interface ScoreSaberLeaderboardToken { id: number; songHash: string; songName: string; songSubName: string; songAuthorName: string; levelAuthorName: string; - difficulty: ScoreSaberDifficulty; + difficulty: ScoreSaberDifficultyToken; maxScore: number; createdDate: string; rankedDate: string; @@ -22,5 +22,5 @@ export default interface ScoreSaberLeaderboard { plays: boolean; dailyPlays: boolean; coverImage: string; - difficulties: ScoreSaberDifficulty[]; + difficulties: ScoreSaberDifficultyToken[]; } diff --git a/src/common/service/types/scoresaber/scoresaber-metadata.ts b/src/common/model/token/scoresaber/score-saber-metadata-token.ts similarity index 79% rename from src/common/service/types/scoresaber/scoresaber-metadata.ts rename to src/common/model/token/scoresaber/score-saber-metadata-token.ts index de63a4b..87778c4 100644 --- a/src/common/service/types/scoresaber/scoresaber-metadata.ts +++ b/src/common/model/token/scoresaber/score-saber-metadata-token.ts @@ -1,4 +1,4 @@ -export default interface ScoreSaberMetadata { +export default interface ScoreSaberMetadataToken { /** * The total amount of returned results. */ diff --git a/src/common/model/token/scoresaber/score-saber-player-score-token.ts b/src/common/model/token/scoresaber/score-saber-player-score-token.ts new file mode 100644 index 0000000..5c623c4 --- /dev/null +++ b/src/common/model/token/scoresaber/score-saber-player-score-token.ts @@ -0,0 +1,14 @@ +import ScoreSaberLeaderboardToken from "./score-saber-leaderboard-token"; +import ScoreSaberScoreToken from "./score-saber-score-token"; + +export default interface ScoreSaberPlayerScoreToken { + /** + * The score of the player score. + */ + score: ScoreSaberScoreToken; + + /** + * The leaderboard the score was set on. + */ + leaderboard: ScoreSaberLeaderboardToken; +} diff --git a/src/common/model/token/scoresaber/score-saber-player-scores-page-token.ts b/src/common/model/token/scoresaber/score-saber-player-scores-page-token.ts new file mode 100644 index 0000000..f6fb8d9 --- /dev/null +++ b/src/common/model/token/scoresaber/score-saber-player-scores-page-token.ts @@ -0,0 +1,14 @@ +import ScoreSaberMetadataToken from "./score-saber-metadata-token"; +import ScoreSaberPlayerScoreToken from "./score-saber-player-score-token"; + +export default interface ScoreSaberPlayerScoresPageToken { + /** + * The scores on this page. + */ + playerScores: ScoreSaberPlayerScoreToken[]; + + /** + * The metadata for the page. + */ + metadata: ScoreSaberMetadataToken; +} diff --git a/src/common/model/token/scoresaber/score-saber-player-search-token.ts b/src/common/model/token/scoresaber/score-saber-player-search-token.ts new file mode 100644 index 0000000..43a3f7a --- /dev/null +++ b/src/common/model/token/scoresaber/score-saber-player-search-token.ts @@ -0,0 +1,8 @@ +import ScoreSaberPlayerToken from "./score-saber-player-token"; + +export interface ScoreSaberPlayerSearchToken { + /** + * The players that were found + */ + players: ScoreSaberPlayerToken[]; +} diff --git a/src/common/service/types/scoresaber/scoresaber-player.ts b/src/common/model/token/scoresaber/score-saber-player-token.ts similarity index 79% rename from src/common/service/types/scoresaber/scoresaber-player.ts rename to src/common/model/token/scoresaber/score-saber-player-token.ts index d655ff9..7a436a5 100644 --- a/src/common/service/types/scoresaber/scoresaber-player.ts +++ b/src/common/model/token/scoresaber/score-saber-player-token.ts @@ -1,7 +1,7 @@ -import { ScoreSaberBadge } from "./scoresaber-badge"; -import ScoreSaberScoreStats from "./scoresaber-score-stats"; +import { ScoreSaberBadgeToken } from "./score-saber-badge-token"; +import ScoreSaberScoreStatsToken from "./score-saber-score-stats-token"; -export default interface ScoreSaberPlayer { +export default interface ScoreSaberPlayerToken { /** * The ID of the player. */ @@ -50,7 +50,7 @@ export default interface ScoreSaberPlayer { /** * The badges the player has. */ - badges: ScoreSaberBadge[] | null; + badges: ScoreSaberBadgeToken[] | null; /** * The previous 50 days of rank history. @@ -60,7 +60,7 @@ export default interface ScoreSaberPlayer { /** * The score stats of the player. */ - scoreStats: ScoreSaberScoreStats; + scoreStats: ScoreSaberScoreStatsToken; /** * The permissions of the player. (bitwise) diff --git a/src/common/service/types/scoresaber/scoresaber-score-stats.ts b/src/common/model/token/scoresaber/score-saber-score-stats-token.ts similarity index 91% rename from src/common/service/types/scoresaber/scoresaber-score-stats.ts rename to src/common/model/token/scoresaber/score-saber-score-stats-token.ts index 996e109..5bd122e 100644 --- a/src/common/service/types/scoresaber/scoresaber-score-stats.ts +++ b/src/common/model/token/scoresaber/score-saber-score-stats-token.ts @@ -1,4 +1,4 @@ -export default interface ScoreSaberScoreStats { +export default interface ScoreSaberScoreStatsToken { /** * The total amount of score accumulated over all scores. */ diff --git a/src/common/service/types/scoresaber/scoresaber-score.ts b/src/common/model/token/scoresaber/score-saber-score-token.ts similarity index 53% rename from src/common/service/types/scoresaber/scoresaber-score.ts rename to src/common/model/token/scoresaber/score-saber-score-token.ts index 75dd416..215a2c1 100644 --- a/src/common/service/types/scoresaber/scoresaber-score.ts +++ b/src/common/model/token/scoresaber/score-saber-score-token.ts @@ -1,9 +1,9 @@ -import ScoreSaberLeaderboard from "./scoresaber-leaderboard"; -import ScoreSaberLeaderboardPlayerInfo from "./scoresaber-leaderboard-player-info"; +import ScoreSaberLeaderboardToken from "./score-saber-leaderboard-token"; +import ScoreSaberLeaderboardPlayerInfoToken from "./score-saber-leaderboard-player-info-token"; -export default interface ScoreSaberScore { +export default interface ScoreSaberScoreToken { id: string; - leaderboardPlayerInfo: ScoreSaberLeaderboardPlayerInfo; + leaderboardPlayerInfo: ScoreSaberLeaderboardPlayerInfoToken; rank: number; baseScore: number; modifiedScore: number; @@ -21,5 +21,5 @@ export default interface ScoreSaberScore { deviceHmd: string; deviceControllerLeft: string; deviceControllerRight: string; - leaderboard: ScoreSaberLeaderboard; + leaderboard: ScoreSaberLeaderboardToken; } diff --git a/src/common/service/impl/beatsaver.ts b/src/common/service/impl/beatsaver.ts index 58c15fb..b98fb82 100644 --- a/src/common/service/impl/beatsaver.ts +++ b/src/common/service/impl/beatsaver.ts @@ -1,7 +1,7 @@ import BeatSaverMap from "@/common/database/types/beatsaver-map"; import { db } from "../../database/database"; import Service from "../service"; -import { BeatSaverMap as BSMap } from "../types/beatsaver/beatsaver-map"; +import { BeatSaverMapToken as BSMap } from "@/common/model/token/beatsaver/beat-saver-map-token"; const API_BASE = "https://api.beatsaver.com"; const LOOKUP_MAP_BY_HASH_ENDPOINT = `${API_BASE}/maps/hash/:query`; diff --git a/src/common/service/impl/scoresaber.ts b/src/common/service/impl/scoresaber.ts index 67d3dd4..3ae0e47 100644 --- a/src/common/service/impl/scoresaber.ts +++ b/src/common/service/impl/scoresaber.ts @@ -1,9 +1,9 @@ import Service from "../service"; import { ScoreSort } from "../score-sort"; -import ScoreSaberLeaderboardScoresPage from "../types/scoresaber/scoresaber-leaderboard-scores-page"; -import ScoreSaberPlayer from "../types/scoresaber/scoresaber-player"; -import ScoreSaberPlayerScoresPage from "../types/scoresaber/scoresaber-player-scores-page"; -import { ScoreSaberPlayerSearch } from "../types/scoresaber/scoresaber-player-search"; +import ScoreSaberLeaderboardScoresPageToken from "@/common/model/token/scoresaber/score-saber-leaderboard-scores-page-token"; +import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token"; +import ScoreSaberPlayerScoresPageToken from "@/common/model/token/scoresaber/score-saber-player-scores-page-token"; +import { ScoreSaberPlayerSearchToken } from "@/common/model/token/scoresaber/score-saber-player-search-token"; const API_BASE = "https://scoresaber.com/api"; const SEARCH_PLAYERS_ENDPOINT = `${API_BASE}/players?search=:query`; @@ -26,10 +26,10 @@ class ScoreSaberService extends Service { async searchPlayers( query: string, useProxy = true, - ): Promise { + ): Promise { const before = performance.now(); this.log(`Searching for players matching "${query}"...`); - const results = await this.fetch( + const results = await this.fetch( useProxy, SEARCH_PLAYERS_ENDPOINT.replace(":query", query), ); @@ -56,10 +56,10 @@ class ScoreSaberService extends Service { async lookupPlayer( playerId: string, useProxy = true, - ): Promise { + ): Promise { const before = performance.now(); this.log(`Looking up player "${playerId}"...`); - const response = await this.fetch( + const response = await this.fetch( useProxy, LOOKUP_PLAYER_ENDPOINT.replace(":id", playerId), ); @@ -94,12 +94,12 @@ class ScoreSaberService extends Service { page: number; search?: string; useProxy?: boolean; - }): Promise { + }): Promise { const before = performance.now(); this.log( `Looking up scores for player "${playerId}", sort "${sort}", page "${page}"${search ? `, search "${search}"` : ""}...`, ); - const response = await this.fetch( + const response = await this.fetch( useProxy, LOOKUP_PLAYER_SCORES_ENDPOINT.replace(":id", playerId) .replace(":limit", 8 + "") @@ -128,12 +128,12 @@ class ScoreSaberService extends Service { leaderboardId: string, page: number, useProxy = true, - ): Promise { + ): Promise { const before = performance.now(); this.log( `Looking up scores for leaderboard "${leaderboardId}", page "${page}"...`, ); - const response = await this.fetch( + const response = await this.fetch( useProxy, LOOKUP_LEADERBOARD_SCORES_ENDPOINT.replace(":id", leaderboardId).replace( ":page", diff --git a/src/common/service/types/beatsaver/beatsaver-map.ts b/src/common/service/types/beatsaver/beatsaver-map.ts deleted file mode 100644 index 599de27..0000000 --- a/src/common/service/types/beatsaver/beatsaver-map.ts +++ /dev/null @@ -1,24 +0,0 @@ -import BeatSaverAccount from "./beatsaver-account"; -import BeatSaverMapMetadata from "./beatsaver-map-metadata"; -import BeatSaverMapStats from "./beatsaver-map-stats"; - -export interface BeatSaverMap { - id: string; - name: string; - description: string; - uploader: BeatSaverAccount; - metadata: BeatSaverMapMetadata; - stats: BeatSaverMapStats; - uploaded: string; - automapper: boolean; - ranked: boolean; - qualified: boolean; - // todo: versions - createdAt: string; - updatedAt: string; - lastPublishedAt: string; - tags: string[]; - declaredAi: string; - blRanked: boolean; - blQualified: boolean; -} diff --git a/src/common/service/types/scoresaber/scoresaber-leaderboard-scores-page.ts b/src/common/service/types/scoresaber/scoresaber-leaderboard-scores-page.ts deleted file mode 100644 index 7070853..0000000 --- a/src/common/service/types/scoresaber/scoresaber-leaderboard-scores-page.ts +++ /dev/null @@ -1,14 +0,0 @@ -import ScoreSaberMetadata from "./scoresaber-metadata"; -import ScoreSaberScore from "./scoresaber-score"; - -export default interface ScoreSaberLeaderboardScoresPage { - /** - * The scores on this page. - */ - scores: ScoreSaberScore[]; - - /** - * The metadata for the page. - */ - metadata: ScoreSaberMetadata; -} diff --git a/src/common/service/types/scoresaber/scoresaber-player-score.ts b/src/common/service/types/scoresaber/scoresaber-player-score.ts deleted file mode 100644 index 29d9952..0000000 --- a/src/common/service/types/scoresaber/scoresaber-player-score.ts +++ /dev/null @@ -1,14 +0,0 @@ -import ScoreSaberLeaderboard from "./scoresaber-leaderboard"; -import ScoreSaberScore from "./scoresaber-score"; - -export default interface ScoreSaberPlayerScore { - /** - * The score of the player score. - */ - score: ScoreSaberScore; - - /** - * The leaderboard the score was set on. - */ - leaderboard: ScoreSaberLeaderboard; -} diff --git a/src/common/service/types/scoresaber/scoresaber-player-scores-page.ts b/src/common/service/types/scoresaber/scoresaber-player-scores-page.ts deleted file mode 100644 index 3b41ec0..0000000 --- a/src/common/service/types/scoresaber/scoresaber-player-scores-page.ts +++ /dev/null @@ -1,14 +0,0 @@ -import ScoreSaberMetadata from "./scoresaber-metadata"; -import ScoreSaberPlayerScore from "./scoresaber-player-score"; - -export default interface ScoreSaberPlayerScoresPage { - /** - * The scores on this page. - */ - playerScores: ScoreSaberPlayerScore[]; - - /** - * The metadata for the page. - */ - metadata: ScoreSaberMetadata; -} diff --git a/src/common/service/types/scoresaber/scoresaber-player-search.ts b/src/common/service/types/scoresaber/scoresaber-player-search.ts deleted file mode 100644 index 7af2e53..0000000 --- a/src/common/service/types/scoresaber/scoresaber-player-search.ts +++ /dev/null @@ -1,8 +0,0 @@ -import ScoreSaberPlayer from "./scoresaber-player"; - -export interface ScoreSaberPlayerSearch { - /** - * The players that were found - */ - players: ScoreSaberPlayer[]; -} diff --git a/src/common/workers/worker.ts b/src/common/worker/worker.ts similarity index 100% rename from src/common/workers/worker.ts rename to src/common/worker/worker.ts diff --git a/src/common/workers/workers.ts b/src/common/worker/workers.ts similarity index 75% rename from src/common/workers/workers.ts rename to src/common/worker/workers.ts index a45f1ec..37d06ea 100644 --- a/src/common/workers/workers.ts +++ b/src/common/worker/workers.ts @@ -1,5 +1,5 @@ import * as Comlink from "comlink"; -import { WorkerApi } from "@/common/workers/worker"; +import { WorkerApi } from "@/common/worker/worker"; export const scoresaberReloadedWorker = () => Comlink.wrap(new Worker(new URL("./worker.ts", import.meta.url))); diff --git a/src/components/footer.tsx b/src/components/footer.tsx index f1932ca..061a7d0 100644 --- a/src/components/footer.tsx +++ b/src/components/footer.tsx @@ -32,7 +32,7 @@ export default function Footer() { return ( {item.name} diff --git a/src/components/input/search-player.tsx b/src/components/input/search-player.tsx index 13c60c9..affbbe1 100644 --- a/src/components/input/search-player.tsx +++ b/src/components/input/search-player.tsx @@ -1,7 +1,7 @@ "use client"; import { scoresaberService } from "@/common/service/impl/scoresaber"; -import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player"; +import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token"; import { formatNumberWithCommas } from "@/common/number-utils"; import { zodResolver } from "@hookform/resolvers/zod"; import Link from "next/link"; @@ -25,7 +25,7 @@ export default function SearchPlayer() { username: "", }, }); - const [results, setResults] = useState(); + const [results, setResults] = useState(); const [loading, setLoading] = useState(false); async function onSubmit({ username }: z.infer) { diff --git a/src/components/leaderboard/leaderboard-player.tsx b/src/components/leaderboard/leaderboard-player.tsx index a7773d1..cef4262 100644 --- a/src/components/leaderboard/leaderboard-player.tsx +++ b/src/components/leaderboard/leaderboard-player.tsx @@ -1,9 +1,9 @@ -import ScoreSaberScore from "@/common/service/types/scoresaber/scoresaber-score"; +import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token"; import Image from "next/image"; import Link from "next/link"; type Props = { - score: ScoreSaberScore; + score: ScoreSaberScoreToken; }; export default function LeaderboardPlayer({ score }: Props) { diff --git a/src/components/leaderboard/leaderboard-score-stats.tsx b/src/components/leaderboard/leaderboard-score-stats.tsx index 184db8b..b45367d 100644 --- a/src/components/leaderboard/leaderboard-score-stats.tsx +++ b/src/components/leaderboard/leaderboard-score-stats.tsx @@ -1,5 +1,5 @@ -import ScoreSaberLeaderboard from "@/common/service/types/scoresaber/scoresaber-leaderboard"; -import ScoreSaberScore from "@/common/service/types/scoresaber/scoresaber-score"; +import ScoreSaberLeaderboardToken from "@/common/model/token/scoresaber/score-saber-leaderboard-token"; +import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token"; import { formatNumberWithCommas } from "@/common/number-utils"; import StatValue from "@/components/stat-value"; import { XMarkIcon } from "@heroicons/react/24/solid"; @@ -8,15 +8,15 @@ import clsx from "clsx"; type Badge = { name: string; create: ( - score: ScoreSaberScore, - leaderboard: ScoreSaberLeaderboard, + score: ScoreSaberScoreToken, + leaderboard: ScoreSaberLeaderboardToken, ) => string | React.ReactNode | undefined; }; const badges: Badge[] = [ { name: "PP", - create: (score: ScoreSaberScore) => { + create: (score: ScoreSaberScoreToken) => { const pp = score.pp; if (pp === 0) { return undefined; @@ -26,14 +26,17 @@ const badges: Badge[] = [ }, { name: "Accuracy", - create: (score: ScoreSaberScore, leaderboard: ScoreSaberLeaderboard) => { + create: ( + score: ScoreSaberScoreToken, + leaderboard: ScoreSaberLeaderboardToken, + ) => { const acc = (score.baseScore / leaderboard.maxScore) * 100; return `${acc.toFixed(2)}%`; }, }, { name: "Full Combo", - create: (score: ScoreSaberScore) => { + create: (score: ScoreSaberScoreToken) => { const fullCombo = score.missedNotes === 0; return ( @@ -55,8 +58,8 @@ const badges: Badge[] = [ ]; type Props = { - score: ScoreSaberScore; - leaderboard: ScoreSaberLeaderboard; + score: ScoreSaberScoreToken; + leaderboard: ScoreSaberLeaderboardToken; }; export default function LeaderboardScoreStats({ score, leaderboard }: Props) { diff --git a/src/components/leaderboard/leaderboard-score.tsx b/src/components/leaderboard/leaderboard-score.tsx index 3827709..251e615 100644 --- a/src/components/leaderboard/leaderboard-score.tsx +++ b/src/components/leaderboard/leaderboard-score.tsx @@ -1,7 +1,7 @@ "use client"; -import ScoreSaberLeaderboard from "@/common/service/types/scoresaber/scoresaber-leaderboard"; -import ScoreSaberScore from "@/common/service/types/scoresaber/scoresaber-score"; +import ScoreSaberLeaderboardToken from "@/common/model/token/scoresaber/score-saber-leaderboard-token"; +import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token"; import LeaderboardPlayer from "./leaderboard-player"; import LeaderboardScoreStats from "./leaderboard-score-stats"; import ScoreRankInfo from "@/components/score/score-rank-info"; @@ -10,12 +10,12 @@ type Props = { /** * The score to display. */ - score: ScoreSaberScore; + score: ScoreSaberScoreToken; /** * The leaderboard to display. */ - leaderboard: ScoreSaberLeaderboard; + leaderboard: ScoreSaberLeaderboardToken; }; export default function LeaderboardScore({ score, leaderboard }: Props) { diff --git a/src/components/leaderboard/leaderboard-scores.tsx b/src/components/leaderboard/leaderboard-scores.tsx index 8e49fff..e7787df 100644 --- a/src/components/leaderboard/leaderboard-scores.tsx +++ b/src/components/leaderboard/leaderboard-scores.tsx @@ -1,8 +1,8 @@ "use client"; import { scoresaberService } from "@/common/service/impl/scoresaber"; -import ScoreSaberLeaderboard from "@/common/service/types/scoresaber/scoresaber-leaderboard"; -import ScoreSaberLeaderboardScoresPage from "@/common/service/types/scoresaber/scoresaber-leaderboard-scores-page"; +import ScoreSaberLeaderboardToken from "@/common/model/token/scoresaber/score-saber-leaderboard-token"; +import ScoreSaberLeaderboardScoresPageToken from "@/common/model/token/scoresaber/score-saber-leaderboard-scores-page-token"; import useWindowDimensions from "@/hooks/use-window-dimensions"; import { useQuery } from "@tanstack/react-query"; import { motion } from "framer-motion"; @@ -12,7 +12,7 @@ import Pagination from "../input/pagination"; import LeaderboardScore from "./leaderboard-score"; type Props = { - leaderboard: ScoreSaberLeaderboard; + leaderboard: ScoreSaberLeaderboardToken; }; export default function LeaderboardScores({ leaderboard }: Props) { @@ -20,7 +20,7 @@ export default function LeaderboardScores({ leaderboard }: Props) { const [currentPage, setCurrentPage] = useState(1); const [currentScores, setCurrentScores] = useState< - ScoreSaberLeaderboardScoresPage | undefined + ScoreSaberLeaderboardScoresPageToken | undefined >(); const { diff --git a/src/components/player/player-data.tsx b/src/components/player/player-data.tsx index 3f3e1ae..23207ac 100644 --- a/src/components/player/player-data.tsx +++ b/src/components/player/player-data.tsx @@ -2,8 +2,8 @@ import { scoresaberService } from "@/common/service/impl/scoresaber"; import { ScoreSort } from "@/common/service/score-sort"; -import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player"; -import ScoreSaberPlayerScoresPage from "@/common/service/types/scoresaber/scoresaber-player-scores-page"; +import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token"; +import ScoreSaberPlayerScoresPageToken from "@/common/model/token/scoresaber/score-saber-player-scores-page-token"; import { useQuery } from "@tanstack/react-query"; import PlayerHeader from "./player-header"; import PlayerRankChart from "./player-rank-chart"; @@ -12,8 +12,8 @@ import PlayerScores from "./player-scores"; const REFRESH_INTERVAL = 5 * 60 * 1000; // 5 minutes type Props = { - initialPlayerData: ScoreSaberPlayer; - initialScoreData?: ScoreSaberPlayerScoresPage; + initialPlayerData: ScoreSaberPlayerToken; + initialScoreData?: ScoreSaberPlayerScoresPageToken; sort: ScoreSort; page: number; }; diff --git a/src/components/player/player-header.tsx b/src/components/player/player-header.tsx index 0d9ed23..23e6527 100644 --- a/src/components/player/player-header.tsx +++ b/src/components/player/player-header.tsx @@ -1,4 +1,4 @@ -import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player"; +import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token"; import { formatNumberWithCommas } from "@/common/number-utils"; import { GlobeAmericasIcon } from "@heroicons/react/24/solid"; import Card from "../card"; @@ -13,29 +13,29 @@ const playerData = [ icon: () => { return ; }, - render: (player: ScoreSaberPlayer) => { + render: (player: ScoreSaberPlayerToken) => { return

#{formatNumberWithCommas(player.rank)}

; }, }, { showWhenInactiveOrBanned: false, - icon: (player: ScoreSaberPlayer) => { + icon: (player: ScoreSaberPlayerToken) => { return ; }, - render: (player: ScoreSaberPlayer) => { + render: (player: ScoreSaberPlayerToken) => { return

#{formatNumberWithCommas(player.countryRank)}

; }, }, { showWhenInactiveOrBanned: true, - render: (player: ScoreSaberPlayer) => { + render: (player: ScoreSaberPlayerToken) => { return

{formatNumberWithCommas(player.pp)}pp

; }, }, ]; type Props = { - player: ScoreSaberPlayer; + player: ScoreSaberPlayerToken; }; export default function PlayerHeader({ player }: Props) { diff --git a/src/components/player/player-rank-chart.tsx b/src/components/player/player-rank-chart.tsx index f614bab..dac2f9e 100644 --- a/src/components/player/player-rank-chart.tsx +++ b/src/components/player/player-rank-chart.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ "use client"; -import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player"; +import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token"; import { formatNumberWithCommas } from "@/common/number-utils"; import { CategoryScale, @@ -86,7 +86,7 @@ export const options: any = { }; type Props = { - player: ScoreSaberPlayer; + player: ScoreSaberPlayerToken; }; export default function PlayerRankChart({ player }: Props) { diff --git a/src/components/player/player-scores.tsx b/src/components/player/player-scores.tsx index 3839716..f03219b 100644 --- a/src/components/player/player-scores.tsx +++ b/src/components/player/player-scores.tsx @@ -11,13 +11,13 @@ import Pagination from "../input/pagination"; import { Button } from "../ui/button"; import { leaderboards } from "@/common/leaderboards"; import { ScoreSort } from "@/common/service/score-sort"; -import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player"; -import ScoreSaberPlayerScoresPage from "@/common/service/types/scoresaber/scoresaber-player-scores-page"; +import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token"; +import ScoreSaberPlayerScoresPageToken from "@/common/model/token/scoresaber/score-saber-player-scores-page-token"; import Score from "@/components/score/score"; type Props = { - initialScoreData?: ScoreSaberPlayerScoresPage; - player: ScoreSaberPlayer; + initialScoreData?: ScoreSaberPlayerScoresPageToken; + player: ScoreSaberPlayerToken; sort: ScoreSort; page: number; }; @@ -88,7 +88,7 @@ export default function PlayerScores({ }); const [previousPage, setPreviousPage] = useState(page); const [currentScores, setCurrentScores] = useState< - ScoreSaberPlayerScoresPage | undefined + ScoreSaberPlayerScoresPageToken | undefined >(initialScoreData); const { diff --git a/src/components/player/player-stats.tsx b/src/components/player/player-stats.tsx index aed9658..320bd83 100644 --- a/src/components/player/player-stats.tsx +++ b/src/components/player/player-stats.tsx @@ -1,57 +1,59 @@ import { formatNumberWithCommas } from "@/common/number-utils"; import StatValue from "@/components/stat-value"; -import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player"; +import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token"; type Badge = { name: string; color?: string; - create: (player: ScoreSaberPlayer) => string | React.ReactNode | undefined; + create: ( + player: ScoreSaberPlayerToken, + ) => string | React.ReactNode | undefined; }; const badges: Badge[] = [ { name: "Ranked Play Count", color: "bg-pp", - create: (player: ScoreSaberPlayer) => { + create: (player: ScoreSaberPlayerToken) => { return formatNumberWithCommas(player.scoreStats.rankedPlayCount); }, }, { name: "Total Ranked Score", color: "bg-pp", - create: (player: ScoreSaberPlayer) => { + create: (player: ScoreSaberPlayerToken) => { return formatNumberWithCommas(player.scoreStats.totalRankedScore); }, }, { name: "Average Ranked Accuracy", color: "bg-pp", - create: (player: ScoreSaberPlayer) => { + create: (player: ScoreSaberPlayerToken) => { return player.scoreStats.averageRankedAccuracy.toFixed(2) + "%"; }, }, { name: "Total Play Count", - create: (player: ScoreSaberPlayer) => { + create: (player: ScoreSaberPlayerToken) => { return formatNumberWithCommas(player.scoreStats.totalPlayCount); }, }, { name: "Total Score", - create: (player: ScoreSaberPlayer) => { + create: (player: ScoreSaberPlayerToken) => { return formatNumberWithCommas(player.scoreStats.totalScore); }, }, { name: "Total Replays Watched", - create: (player: ScoreSaberPlayer) => { + create: (player: ScoreSaberPlayerToken) => { return formatNumberWithCommas(player.scoreStats.replaysWatched); }, }, ]; type Props = { - player: ScoreSaberPlayer; + player: ScoreSaberPlayerToken; }; export default function PlayerStats({ player }: Props) { diff --git a/src/components/score/score-buttons.tsx b/src/components/score/score-buttons.tsx index 99076d0..80e98e0 100644 --- a/src/components/score/score-buttons.tsx +++ b/src/components/score/score-buttons.tsx @@ -1,7 +1,7 @@ "use client"; import { copyToClipboard } from "@/common/browser-utils"; -import ScoreSaberPlayerScore from "@/common/service/types/scoresaber/scoresaber-player-score"; +import ScoreSaberPlayerScoreToken from "@/common/model/token/scoresaber/score-saber-player-score-token"; import BeatSaverMap from "@/common/database/types/beatsaver-map"; import { songNameToYouTubeLink } from "@/common/youtube-utils"; import BeatSaverLogo from "@/components/logos/beatsaver-logo"; @@ -12,7 +12,7 @@ import LeaderboardButton from "./leaderboard-button"; import ScoreButton from "./score-button"; type Props = { - playerScore: ScoreSaberPlayerScore; + playerScore: ScoreSaberPlayerScoreToken; beatSaverMap?: BeatSaverMap; isLeaderboardExpanded: boolean; setIsLeaderboardExpanded: Dispatch>; diff --git a/src/components/score/score-info.tsx b/src/components/score/score-info.tsx index a2bc6ca..d461ccd 100644 --- a/src/components/score/score-info.tsx +++ b/src/components/score/score-info.tsx @@ -1,4 +1,4 @@ -import ScoreSaberLeaderboard from "@/common/service/types/scoresaber/scoresaber-leaderboard"; +import ScoreSaberLeaderboardToken from "@/common/model/token/scoresaber/score-saber-leaderboard-token"; import BeatSaverMap from "@/common/database/types/beatsaver-map"; import { getDifficultyFromScoreSaberDifficulty } from "@/common/scoresaber-utils"; import { songDifficultyToColor } from "@/common/song-utils"; @@ -9,7 +9,7 @@ import clsx from "clsx"; import Image from "next/image"; type Props = { - leaderboard: ScoreSaberLeaderboard; + leaderboard: ScoreSaberLeaderboardToken; beatSaverMap?: BeatSaverMap; }; diff --git a/src/components/score/score-rank-info.tsx b/src/components/score/score-rank-info.tsx index bbc581e..8a309a1 100644 --- a/src/components/score/score-rank-info.tsx +++ b/src/components/score/score-rank-info.tsx @@ -1,10 +1,10 @@ -import ScoreSaberScore from "@/common/service/types/scoresaber/scoresaber-score"; +import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token"; import { formatNumberWithCommas } from "@/common/number-utils"; import { timeAgo } from "@/common/time-utils"; import { GlobeAmericasIcon } from "@heroicons/react/24/solid"; type Props = { - score: ScoreSaberScore; + score: ScoreSaberScoreToken; }; export default function ScoreRankInfo({ score }: Props) { diff --git a/src/components/score/score-stats.tsx b/src/components/score/score-stats.tsx index 7308da1..07c8bfe 100644 --- a/src/components/score/score-stats.tsx +++ b/src/components/score/score-stats.tsx @@ -1,5 +1,5 @@ -import ScoreSaberLeaderboard from "@/common/service/types/scoresaber/scoresaber-leaderboard"; -import ScoreSaberScore from "@/common/service/types/scoresaber/scoresaber-score"; +import ScoreSaberLeaderboardToken from "@/common/model/token/scoresaber/score-saber-leaderboard-token"; +import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token"; import { formatNumberWithCommas } from "@/common/number-utils"; import StatValue from "@/components/stat-value"; import { XMarkIcon } from "@heroicons/react/24/solid"; @@ -9,12 +9,12 @@ import { accuracyToColor } from "@/common/song-utils"; type Badge = { name: string; color?: ( - score: ScoreSaberScore, - leaderboard: ScoreSaberLeaderboard, + score: ScoreSaberScoreToken, + leaderboard: ScoreSaberLeaderboardToken, ) => string | undefined; create: ( - score: ScoreSaberScore, - leaderboard: ScoreSaberLeaderboard, + score: ScoreSaberScoreToken, + leaderboard: ScoreSaberLeaderboardToken, ) => string | React.ReactNode | undefined; }; @@ -24,7 +24,7 @@ const badges: Badge[] = [ color: () => { return "bg-pp"; }, - create: (score: ScoreSaberScore) => { + create: (score: ScoreSaberScoreToken) => { const pp = score.pp; if (pp === 0) { return undefined; @@ -34,18 +34,24 @@ const badges: Badge[] = [ }, { name: "Accuracy", - color: (score: ScoreSaberScore, leaderboard: ScoreSaberLeaderboard) => { + color: ( + score: ScoreSaberScoreToken, + leaderboard: ScoreSaberLeaderboardToken, + ) => { const acc = (score.baseScore / leaderboard.maxScore) * 100; return accuracyToColor(acc); }, - create: (score: ScoreSaberScore, leaderboard: ScoreSaberLeaderboard) => { + create: ( + score: ScoreSaberScoreToken, + leaderboard: ScoreSaberLeaderboardToken, + ) => { const acc = (score.baseScore / leaderboard.maxScore) * 100; return `${acc.toFixed(2)}%`; }, }, { name: "Score", - create: (score: ScoreSaberScore) => { + create: (score: ScoreSaberScoreToken) => { return `${formatNumberWithCommas(score.baseScore)}`; }, }, @@ -59,7 +65,7 @@ const badges: Badge[] = [ }, { name: "Full Combo", - create: (score: ScoreSaberScore) => { + create: (score: ScoreSaberScoreToken) => { const fullCombo = score.missedNotes === 0; return ( @@ -81,8 +87,8 @@ const badges: Badge[] = [ ]; type Props = { - score: ScoreSaberScore; - leaderboard: ScoreSaberLeaderboard; + score: ScoreSaberScoreToken; + leaderboard: ScoreSaberLeaderboardToken; }; export default function ScoreStats({ score, leaderboard }: Props) { diff --git a/src/components/score/score.tsx b/src/components/score/score.tsx index ee364a7..ccce690 100644 --- a/src/components/score/score.tsx +++ b/src/components/score/score.tsx @@ -1,7 +1,7 @@ "use client"; import { beatsaverService } from "@/common/service/impl/beatsaver"; -import ScoreSaberPlayerScore from "@/common/service/types/scoresaber/scoresaber-player-score"; +import ScoreSaberPlayerScoreToken from "@/common/model/token/scoresaber/score-saber-player-score-token"; import BeatSaverMap from "@/common/database/types/beatsaver-map"; import LeaderboardScores from "@/components/leaderboard/leaderboard-scores"; import { useCallback, useEffect, useState } from "react"; @@ -14,7 +14,7 @@ type Props = { /** * The score to display. */ - playerScore: ScoreSaberPlayerScore; + playerScore: ScoreSaberPlayerScoreToken; }; export default function Score({ playerScore }: Props) { diff --git a/tsconfig.json b/tsconfig.json index 16bc772..7c3daba 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,7 +27,6 @@ "**/*.tsx", ".next/types/**/*.ts", "tailwind.config.ts", - "src/components/leaderboard/leaderboard-score-statstsx" ], "exclude": ["node_modules"] }