diff --git a/bot/src/utils/returnTypes.ts b/bot/src/utils/returnTypes.ts index 90f1a6ba6..eca063164 100644 --- a/bot/src/utils/returnTypes.ts +++ b/bot/src/utils/returnTypes.ts @@ -8,7 +8,7 @@ import type { integer, ScoreDocument, SongDocument, - UGSRatingsLookup, + ProfileRatingLookup, UserGameStats, } from "tachi-common"; @@ -50,7 +50,7 @@ export interface UGPTStats { firstScore: ScoreDocument; mostRecentScore: ScoreDocument; totalScores: integer; - rankingData: Record; + rankingData: Record; } export interface ChartQueryReturns { diff --git a/client/src/app/pages/dashboard/users/games/_game/_playtype/LeaderboardsPage.tsx b/client/src/app/pages/dashboard/users/games/_game/_playtype/LeaderboardsPage.tsx index d6bc8f23a..4cba7d98a 100644 --- a/client/src/app/pages/dashboard/users/games/_game/_playtype/LeaderboardsPage.tsx +++ b/client/src/app/pages/dashboard/users/games/_game/_playtype/LeaderboardsPage.tsx @@ -19,7 +19,7 @@ import { IDStrings, integer, UserDocument, - UGSRatingsLookup, + ProfileRatingLookup, UserGameStats, } from "tachi-common"; import { GameClassSets } from "tachi-common/game-classes"; @@ -84,8 +84,8 @@ function LeaderboardsPageContent({ }: { reqUser: UserDocument; data: LeaderboardsData; - alg: UGSRatingsLookup[IDStrings]; - setAlg: SetState; + alg: ProfileRatingLookup[IDStrings]; + setAlg: SetState; } & GamePT) { const { stats, leaderboard } = data; diff --git a/client/src/components/game/songs/DefaultSongInfoFormat.tsx b/client/src/components/game/songs/DefaultSongInfoFormat.tsx index 3b7d09660..3c0fd269e 100644 --- a/client/src/components/game/songs/DefaultSongInfoFormat.tsx +++ b/client/src/components/game/songs/DefaultSongInfoFormat.tsx @@ -21,6 +21,7 @@ export default function DefaultSongChartInfoFormat({
({FormatDifficulty(chart, game)})
+ +
+

Messed up?

+ +
) : ( <> diff --git a/client/src/components/tables/cells/DifficultyCell.tsx b/client/src/components/tables/cells/DifficultyCell.tsx index b935330e6..5d76139b0 100644 --- a/client/src/components/tables/cells/DifficultyCell.tsx +++ b/client/src/components/tables/cells/DifficultyCell.tsx @@ -54,6 +54,7 @@ export default function DifficultyCell({ style={{ backgroundColor: ChangeOpacity(gptConfig.difficultyColours[chart.difficulty]!, 0.2), minWidth: "80px", + maxWidth: "100px", }} > {!alwaysShort && ( @@ -62,7 +63,7 @@ export default function DifficultyCell({
{FormatDifficultyShort(chart, game)}
- + {"isHot" in chart.data && chart.data.isHot && (
@@ -88,10 +89,12 @@ export function DisplayLevelNum({ level, levelNum, prefix, + game, }: { levelNum: number; level: string; prefix?: string; + game: Game; }) { // Don't display levelnum if its identical to the level, the decimal places in the // level end with .0, or the levelNum itself is 0. @@ -99,6 +102,11 @@ export function DisplayLevelNum({ return null; } + // or if it's gitadora + if (game === "gitadora") { + return null; + } + return ( {prefix} diff --git a/client/src/components/tables/cells/GitadoraJudgementCell.tsx b/client/src/components/tables/cells/GitadoraJudgementCell.tsx new file mode 100644 index 000000000..90919e3e4 --- /dev/null +++ b/client/src/components/tables/cells/GitadoraJudgementCell.tsx @@ -0,0 +1,35 @@ +import { IsNullish } from "util/misc"; +import React from "react"; +import { COLOUR_SET, PBScoreDocument, ScoreDocument } from "tachi-common"; + +export default function GitadoraJudgementCell({ + score, +}: { + score: + | ScoreDocument<"gitadora:Dora" | "gitadora:Gita"> + | PBScoreDocument<"gitadora:Dora" | "gitadora:Gita">; +}) { + const judgements = score.scoreData.judgements; + + if ( + IsNullish(judgements.perfect) || + IsNullish(judgements.great) || + IsNullish(judgements.good) || + IsNullish(judgements.ok) || + IsNullish(judgements.miss) + ) { + return No Data.; + } + + return ( + + + {judgements.perfect}- + {judgements.great}- + {judgements.good}- + {judgements.ok}- + {judgements.miss} + + + ); +} diff --git a/client/src/components/tables/game-core-cells/GitadoraCoreCells.tsx b/client/src/components/tables/game-core-cells/GitadoraCoreCells.tsx new file mode 100644 index 000000000..ffe6faf1f --- /dev/null +++ b/client/src/components/tables/game-core-cells/GitadoraCoreCells.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import { PBScoreDocument, ScoreDocument } from "tachi-common"; +import GitadoraJudgementCell from "../cells/GitadoraJudgementCell"; +import LampCell from "../cells/LampCell"; +import RatingCell from "../cells/RatingCell"; +import ScoreCell from "../cells/ScoreCell"; + +export default function GitadoraCoreCells({ + sc, + rating, +}: { + sc: + | ScoreDocument<"gitadora:Gita" | "gitadora:Dora"> + | PBScoreDocument<"gitadora:Gita" | "gitadora:Dora">; + rating: keyof ScoreDocument["calculatedData"]; +}) { + return ( + <> + + + + + + ); +} diff --git a/client/src/components/tables/game-core-cells/ITGCoreCells.tsx b/client/src/components/tables/game-core-cells/ITGCoreCells.tsx index bc7bab776..11481fa7f 100644 --- a/client/src/components/tables/game-core-cells/ITGCoreCells.tsx +++ b/client/src/components/tables/game-core-cells/ITGCoreCells.tsx @@ -2,9 +2,6 @@ import React from "react"; import { PBScoreDocument, ScoreDocument } from "tachi-common"; import ITGJudgementCell from "../cells/ITGJudgementCell"; import LampCell from "../cells/LampCell"; -import MillionsScoreCell from "../cells/MillionsScoreCell"; -import PopnJudgementCell from "../cells/PopnJudgementCell"; -import PopnLampCell from "../cells/PopnLampCell"; import RatingCell from "../cells/RatingCell"; import ScoreCell from "../cells/ScoreCell"; diff --git a/client/src/components/tables/game-core-cells/ScoreCoreCells.tsx b/client/src/components/tables/game-core-cells/ScoreCoreCells.tsx index a8818cdc9..0b1b1491a 100644 --- a/client/src/components/tables/game-core-cells/ScoreCoreCells.tsx +++ b/client/src/components/tables/game-core-cells/ScoreCoreCells.tsx @@ -18,6 +18,7 @@ import PMSCoreCells from "./PMSCoreCells"; import PopnCoreCells from "./PopnCoreCells"; import SDVXScoreCoreCells from "./SDVXCoreCells"; import WACCACoreCells from "./WACCACoreCells"; +import GitadoraCoreCells from "./GitadoraCoreCells"; export default function ScoreCoreCells({ game, @@ -32,40 +33,42 @@ export default function ScoreCoreCells({ }) { const sc = score as any; // lazy hack - if (game === "iidx") { - return ( - } - sc={sc} - /> - ); - } else if (game === "bms") { - return ; - } else if (game === "sdvx" || game === "usc") { - return ( - } - /> - ); - } else if (game === "museca") { - return ; - } else if (game === "wacca") { - return ; - } else if (game === "popn") { - return ; - } else if (game === "jubeat") { - return ; - } else if (game === "chunithm") { - return ; - } else if (game === "gitadora") { - return ; - } else if (game === "pms") { - return ; - } else if (game === "itg") { - return ; + switch (game) { + case "iidx": + return ( + } + sc={sc} + /> + ); + case "bms": + return ; + case "sdvx": + case "usc": + return ( + + } + /> + ); + case "museca": + return ; + case "wacca": + return ; + case "popn": + return ; + case "jubeat": + return ; + case "chunithm": + return ; + case "gitadora": + return ; + case "pms": + return ; + case "itg": + return ; } - - return ; } diff --git a/client/src/components/user/UGPTRankingData.tsx b/client/src/components/user/UGPTRankingData.tsx index 17be1fa39..38d2f9067 100644 --- a/client/src/components/user/UGPTRankingData.tsx +++ b/client/src/components/user/UGPTRankingData.tsx @@ -2,7 +2,7 @@ import { UppercaseFirst } from "util/misc"; import { useProfileRatingAlg } from "components/util/useScoreRatingAlg"; import React from "react"; import { Link } from "react-router-dom"; -import { IDStrings, integer, UGSRatingsLookup } from "tachi-common"; +import { IDStrings, integer, ProfileRatingLookup } from "tachi-common"; import { GamePT } from "types/react"; export default function RankingData({ @@ -11,7 +11,7 @@ export default function RankingData({ userID, playtype, }: { - rankingData: Record; + rankingData: Record; userID: integer; } & GamePT) { const alg = useProfileRatingAlg(game, playtype); @@ -19,7 +19,7 @@ export default function RankingData({ const extendData = []; for (const k in rankingData) { - const key = k as UGSRatingsLookup[IDStrings]; + const key = k as ProfileRatingLookup[IDStrings]; if (key !== alg) { extendData.push( diff --git a/client/src/components/user/UGPTStatsOverview.tsx b/client/src/components/user/UGPTStatsOverview.tsx index 5f6a8233e..239f83b23 100644 --- a/client/src/components/user/UGPTStatsOverview.tsx +++ b/client/src/components/user/UGPTStatsOverview.tsx @@ -8,7 +8,7 @@ import { GetGamePTConfig, IDStrings, ScoreCalculatedDataLookup, - UGSRatingsLookup, + ProfileRatingLookup, UserGameStats, } from "tachi-common"; import { GameClassSets } from "tachi-common/game-classes"; @@ -16,7 +16,7 @@ import { GameClassSets } from "tachi-common/game-classes"; export default function UGPTRatingsTable({ ugs }: { ugs: UserGameStats }) { const gptConfig = GetGamePTConfig(ugs.game, ugs.playtype); - const ratings = Object.entries(ugs.ratings) as [UGSRatingsLookup[IDStrings], number][]; + const ratings = Object.entries(ugs.ratings) as [ProfileRatingLookup[IDStrings], number][]; return ( diff --git a/client/src/components/util/useScoreRatingAlg.tsx b/client/src/components/util/useScoreRatingAlg.tsx index f5782ab65..9f370639c 100644 --- a/client/src/components/util/useScoreRatingAlg.tsx +++ b/client/src/components/util/useScoreRatingAlg.tsx @@ -4,7 +4,7 @@ import { IDStrings, ScoreCalculatedDataLookup, SessionCalculatedDataLookup, - UGSRatingsLookup, + ProfileRatingLookup, } from "tachi-common"; import { Playtype } from "tachi-common"; import useLUGPTSettings from "./useLUGPTSettings"; @@ -42,14 +42,14 @@ export function useSessionRatingAlg( export function useProfileRatingAlg( game: Game, playtype: Playtype -): UGSRatingsLookup[I] { +): ProfileRatingLookup[I] { const { settings } = useLUGPTSettings(); if (!settings?.preferences.preferredProfileAlg) { const gptConfig = GetGamePTConfig(game, playtype); - return gptConfig.defaultProfileRatingAlg as UGSRatingsLookup[I]; + return gptConfig.defaultProfileRatingAlg as ProfileRatingLookup[I]; } - return settings.preferences.preferredProfileAlg as UGSRatingsLookup[I]; + return settings.preferences.preferredProfileAlg as ProfileRatingLookup[I]; } diff --git a/client/src/types/api-returns.ts b/client/src/types/api-returns.ts index 057157623..682438e60 100644 --- a/client/src/types/api-returns.ts +++ b/client/src/types/api-returns.ts @@ -22,7 +22,7 @@ import { ShowcaseStatFolder, SongDocument, TableDocument, - UGSRatingsLookup, + ProfileRatingLookup, UserGameStats, UserGameStatsSnapshot, QuestDocument, @@ -36,7 +36,7 @@ export interface UGPTStatsReturn { mostRecentScore: ScoreDocument; totalScores: number; rankingData: Record< - UGSRatingsLookup[I], + ProfileRatingLookup[I], { ranking: integer; outOf: integer; @@ -92,7 +92,7 @@ export interface UGPTChartPBComposition { } export type UGSWithRankingData = UserGameStats & { - __rankingData: Record; + __rankingData: Record; }; export interface SongChartsSearch { diff --git a/client/src/util/misc.ts b/client/src/util/misc.ts index d6d67eb16..3cc9bf615 100644 --- a/client/src/util/misc.ts +++ b/client/src/util/misc.ts @@ -16,6 +16,7 @@ import { QuestDocument, QuestSubscriptionDocument, SessionCalculatedDataLookup, + ProfileRatingLookup, } from "tachi-common"; import fjsh from "fast-json-stable-hash"; @@ -74,6 +75,25 @@ export function FormatGPTRating( return value.toFixed(2); } +export function FormatGPTProfileRating( + game: Game, + playtype: Playtype, + key: ProfileRatingLookup[IDStrings], + value: number | null +) { + if (value === null) { + return "No Data."; + } + + const gptConfig = GetGamePTConfig(game, playtype); + + if (gptConfig.profileRatingAlgFormatters[key]) { + return gptConfig.profileRatingAlgFormatters[key]!(value); + } + + return value.toFixed(2); +} + export function FormatGPTSessionRating( game: Game, playtype: Playtype, diff --git a/common/src/config/config.ts b/common/src/config/config.ts index be4f0074c..c7c78c6ac 100644 --- a/common/src/config/config.ts +++ b/common/src/config/config.ts @@ -16,23 +16,23 @@ import { WaccaColours, WaccaStageUps, } from "../game-classes"; -import { FormatInt, FormatSieglindeBMS, FormatSieglindePMS } from "../utils/util"; +import { FormatSieglindeBMS, FormatSieglindePMS } from "../utils/util"; import type { GPTTierlists } from ".."; import type { ClassInfo, GameClassSets } from "../game-classes"; import type { ESDJudgementFormat } from "../lib/esd"; import type { Difficulties, - Game, GPTSupportedVersions, + Game, Grades, IDStrings, JudgementLookup, Lamps, Playtype, Playtypes, + ProfileRatingLookup, ScoreCalculatedDataLookup, SessionCalculatedDataLookup, - UGSRatingsLookup, } from "../types"; export interface GameConfig { @@ -49,21 +49,21 @@ interface BaseGamePTConfig { defaultScoreRatingAlg: ScoreCalculatedDataLookup[I]; defaultSessionRatingAlg: SessionCalculatedDataLookup[I]; - defaultProfileRatingAlg: UGSRatingsLookup[I]; + defaultProfileRatingAlg: ProfileRatingLookup[I]; scoreRatingAlgs: Array; sessionRatingAlgs: Array; - profileRatingAlgs: Array; + profileRatingAlgs: Array; scoreRatingAlgDescriptions: Record; sessionRatingAlgDescriptions: Record; - profileRatingAlgDescriptions: Record; + profileRatingAlgDescriptions: Record; scoreRatingAlgFormatters: Partial string>>; sessionRatingAlgFormatters: Partial< Record string> >; - profileRatingAlgFormatters: Partial string>>; + profileRatingAlgFormatters: Partial string>>; difficulties: Array; shortDifficulties: Partial>; @@ -1291,16 +1291,9 @@ const GAME_PT_CONFIGS: GamePTConfigs = { skill: "The average of your best 10 skill ratings this session.", }, - scoreRatingAlgFormatters: { - skill: FormatInt, - }, - profileRatingAlgFormatters: { - skill: FormatInt, - naiveSkill: FormatInt, - }, - sessionRatingAlgFormatters: { - skill: FormatInt, - }, + scoreRatingAlgFormatters: {}, + profileRatingAlgFormatters: {}, + sessionRatingAlgFormatters: {}, difficulties: [ "BASIC", @@ -1330,7 +1323,7 @@ const GAME_PT_CONFIGS: GamePTConfigs = { MASTER: COLOUR_SET.purple, "BASS BASIC": COLOUR_SET.vibrantBlue, "BASS ADVANCED": COLOUR_SET.vibrantOrange, - "BASS EXTREME": "todo", // colourset vibrant red + "BASS EXTREME": COLOUR_SET.vibrantRed, "BASS MASTER": COLOUR_SET.vibrantPurple, }, @@ -1397,16 +1390,9 @@ const GAME_PT_CONFIGS: GamePTConfigs = { skill: "The average of your best 10 skill ratings this session.", }, - scoreRatingAlgFormatters: { - skill: FormatInt, - }, - profileRatingAlgFormatters: { - skill: FormatInt, - naiveSkill: FormatInt, - }, - sessionRatingAlgFormatters: { - skill: FormatInt, - }, + scoreRatingAlgFormatters: {}, + profileRatingAlgFormatters: {}, + sessionRatingAlgFormatters: {}, difficulties: ["BASIC", "ADVANCED", "EXTREME", "MASTER"], shortDifficulties: { diff --git a/common/src/game-classes.ts b/common/src/game-classes.ts index fbb15b1e6..c683baa50 100644 --- a/common/src/game-classes.ts +++ b/common/src/game-classes.ts @@ -80,7 +80,7 @@ export const GitadoraColours: Array = [ mouseoverCSS("GOLD", "金", "Gold", "gold"), // @todo #11 Come up with CSS for Gitadora's rainbow icon. - mouseoverCSS("RAINBOW", "虹", "Rainbow", "todo"), + mouseoverCSS("RAINBOW", "虹", "Rainbow", ""), ]; export const BMSGenocideDans: Array = [ diff --git a/common/src/types.ts b/common/src/types.ts index d304caa75..377d0b69a 100644 --- a/common/src/types.ts +++ b/common/src/types.ts @@ -600,7 +600,7 @@ export interface UserDocument extends MongoDBDocument { authLevel: UserAuthLevels; } -export interface UGSRatingsLookup { +export interface ProfileRatingLookup { "iidx:SP": "BPI" | "ktLampRating"; "iidx:DP": "BPI" | "ktLampRating"; "popn:9B": "naiveClassPoints"; @@ -624,7 +624,7 @@ export interface UserGameStats extends MongoDBD userID: integer; game: IDStringToGame[I]; playtype: IDStringToPlaytype[I]; - ratings: Partial>; + ratings: Partial>; classes: Partial>; } @@ -1359,7 +1359,7 @@ export interface UGPTSettings extends MongoDBDo preferences: { preferredScoreAlg: ScoreCalculatedDataLookup[I] | null; preferredSessionAlg: SessionCalculatedDataLookup[I] | null; - preferredProfileAlg: UGSRatingsLookup[I] | null; + preferredProfileAlg: ProfileRatingLookup[I] | null; stats: Array; scoreBucket: "grade" | "lamp" | null; defaultTable: string | null; @@ -1372,7 +1372,7 @@ export interface UGPTSettings extends MongoDBDo export interface UserGameStatsSnapshot extends MongoDBDocument, UserGameStats { - rankings: Record; + rankings: Record; playcount: integer; timestamp: integer; } diff --git a/common/src/utils/util.ts b/common/src/utils/util.ts index 847449236..f967f378d 100644 --- a/common/src/utils/util.ts +++ b/common/src/utils/util.ts @@ -4,7 +4,7 @@ import type { Grades, integer, PBScoreDocument } from "../types"; import type { PrudenceError } from "prudence"; export function FormatInt(v: number): string { - return v.toString(); + return Math.floor(v).toFixed(0); } export function FormatDifficulty(chart: ChartDocument, game: Game): string { @@ -22,6 +22,15 @@ export function FormatDifficulty(chart: ChartDocument, game: Game): string { return `${itgChart.data.difficultyTag} ${itgChart.level}`; } + if (game === "gitadora") { + const gptConfig = GetGamePTConfig(game, chart.playtype); + + const shortDiff = gptConfig.shortDifficulties[chart.difficulty] ?? chart.difficulty; + + // gitadora should always use short diffs. they just look better. + return `${shortDiff} ${chart.level}`; + } + const gameConfig = GetGameConfig(game); if (gameConfig.validPlaytypes.length > 1) { diff --git a/server/src/external/mongo/indexes.ts b/server/src/external/mongo/indexes.ts index c30e506dd..a2601c442 100644 --- a/server/src/external/mongo/indexes.ts +++ b/server/src/external/mongo/indexes.ts @@ -111,7 +111,7 @@ const staticIndexes: Partial>> = { "charts-sdvx": [index({ "data.inGameID": 1, difficulty: 1 })], "charts-museca": [index({ "data.inGameID": 1, difficulty: 1 }, UNIQUE)], "charts-chunithm": [index({ "data.inGameID": 1, difficulty: 1 }, UNIQUE)], - "charts-gitadora": [index({ "data.inGameID": 1, difficulty: 1 }, UNIQUE)], + "charts-gitadora": [index({ "data.inGameID": 1, difficulty: 1, playtype: 1 }, UNIQUE)], "charts-wacca": [index({ isHot: 1 })], "charts-usc": [index({ "data.hashSHA1": 1, playtype: 1 }, UNIQUE)], "charts-jubeat": [index({ "data.inGameID": 1, difficulty: 1 }, UNIQUE)], diff --git a/server/src/lib/score-import/framework/common/score-utils.ts b/server/src/lib/score-import/framework/common/score-utils.ts index e582c5449..12595c7df 100644 --- a/server/src/lib/score-import/framework/common/score-utils.ts +++ b/server/src/lib/score-import/framework/common/score-utils.ts @@ -91,6 +91,9 @@ export function GenericCalculatePercent(game: Game, score: number, chart?: Chart case "jubeat": throw new Error(`Cannot calculate percent for jubeat. Music Rate must be provided.`); + + // gitadora's score is just a percent + // this is a hack: we need a refactor for this. case "gitadora": case "itg": return score; diff --git a/server/src/lib/score-import/import-types/common/batch-manual/converter.ts b/server/src/lib/score-import/import-types/common/batch-manual/converter.ts index 83f2d5740..a6aa68b0e 100644 --- a/server/src/lib/score-import/import-types/common/batch-manual/converter.ts +++ b/server/src/lib/score-import/import-types/common/batch-manual/converter.ts @@ -362,7 +362,7 @@ export async function ResolveMatchTypeToKTData( ); } - const identifier = data.identifier; + const identifier = Number(data.identifier); const difficulty = AssertStrAsDifficulty(data.difficulty, game, context.playtype); diff --git a/server/src/utils/user.ts b/server/src/utils/user.ts index 7f5f33d49..b7ee1fcc3 100644 --- a/server/src/utils/user.ts +++ b/server/src/utils/user.ts @@ -10,7 +10,7 @@ import type { integer, Playtype, UserDocument, - UGSRatingsLookup, + ProfileRatingLookup, UserGameStats, } from "tachi-common"; @@ -192,7 +192,7 @@ export async function GetAllRankings(stats: UserGameStats) { export async function GetUsersRankingAndOutOf( stats: UserGameStats, - alg?: UGSRatingsLookup[IDStrings] + alg?: ProfileRatingLookup[IDStrings] ) { const gptConfig = GetGamePTConfig(stats.game, stats.playtype);