mirror of
https://github.com/zkldi/Tachi.git
synced 2026-09-30 10:58:07 +03:00
feat: gitadora frontend
This commit is contained in:
@@ -8,7 +8,7 @@ import type {
|
||||
integer,
|
||||
ScoreDocument,
|
||||
SongDocument,
|
||||
UGSRatingsLookup,
|
||||
ProfileRatingLookup,
|
||||
UserGameStats,
|
||||
} from "tachi-common";
|
||||
|
||||
@@ -50,7 +50,7 @@ export interface UGPTStats<I extends IDStrings = IDStrings> {
|
||||
firstScore: ScoreDocument;
|
||||
mostRecentScore: ScoreDocument;
|
||||
totalScores: integer;
|
||||
rankingData: Record<UGSRatingsLookup[I], { ranking: integer; outOf: integer }>;
|
||||
rankingData: Record<ProfileRatingLookup[I], { ranking: integer; outOf: integer }>;
|
||||
}
|
||||
|
||||
export interface ChartQueryReturns {
|
||||
|
||||
@@ -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<UGSRatingsLookup[IDStrings]>;
|
||||
alg: ProfileRatingLookup[IDStrings];
|
||||
setAlg: SetState<ProfileRatingLookup[IDStrings]>;
|
||||
} & GamePT) {
|
||||
const { stats, leaderboard } = data;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ export default function DefaultSongChartInfoFormat({
|
||||
<h5>({FormatDifficulty(chart, game)})</h5>
|
||||
<h6>
|
||||
<DisplayLevelNum
|
||||
game={game}
|
||||
level={chart.level}
|
||||
levelNum={chart.levelNum}
|
||||
prefix="Internal Level: "
|
||||
|
||||
@@ -3,6 +3,7 @@ import Divider from "components/util/Divider";
|
||||
import Loading from "components/util/Loading";
|
||||
import React from "react";
|
||||
import { ImportStates } from "types/import";
|
||||
import ManageImport from "components/tables/dropdowns/components/ManageImport";
|
||||
import ImportInfo from "./ImportInfo";
|
||||
|
||||
export default function ImportStateRenderer({ state: s }: { state: ImportStates }) {
|
||||
@@ -35,6 +36,11 @@ export default function ImportStateRenderer({ state: s }: { state: ImportStates
|
||||
Your import was successful!
|
||||
<Divider />
|
||||
<ImportInfo importID={s.import.importID} />
|
||||
<Divider />
|
||||
<div>
|
||||
<h4>Messed up?</h4>
|
||||
<ManageImport importDoc={s.import} />
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
|
||||
@@ -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({
|
||||
<div className={!alwaysShort ? "d-lg-none" : ""}>
|
||||
{FormatDifficultyShort(chart, game)}
|
||||
</div>
|
||||
<DisplayLevelNum level={chart.level} levelNum={chart.levelNum} />
|
||||
<DisplayLevelNum game={game} level={chart.level} levelNum={chart.levelNum} />
|
||||
{"isHot" in chart.data && chart.data.isHot && (
|
||||
<QuickTooltip tooltipContent="This chart is from the latest version of the game!">
|
||||
<div>
|
||||
@@ -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 (
|
||||
<Muted>
|
||||
{prefix}
|
||||
|
||||
@@ -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 <td>No Data.</td>;
|
||||
}
|
||||
|
||||
return (
|
||||
<td>
|
||||
<strong>
|
||||
<span style={{ color: COLOUR_SET.gold }}>{judgements.perfect}</span>-
|
||||
<span style={{ color: COLOUR_SET.green }}>{judgements.great}</span>-
|
||||
<span style={{ color: COLOUR_SET.blue }}>{judgements.good}</span>-
|
||||
<span style={{ color: COLOUR_SET.purple }}>{judgements.ok}</span>-
|
||||
<span style={{ color: COLOUR_SET.red }}>{judgements.miss}</span>
|
||||
</strong>
|
||||
</td>
|
||||
);
|
||||
}
|
||||
@@ -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 (
|
||||
<>
|
||||
<ScoreCell showScore={false} score={sc} />
|
||||
<GitadoraJudgementCell score={sc} />
|
||||
<LampCell score={sc} />
|
||||
<RatingCell score={sc} rating={rating} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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 (
|
||||
<IIDXCoreCells
|
||||
rating={rating as ScoreCalculatedDataLookup["iidx:SP" | "iidx:DP"]}
|
||||
chart={chart as ChartDocument<"iidx:SP" | "iidx:DP">}
|
||||
sc={sc}
|
||||
/>
|
||||
);
|
||||
} else if (game === "bms") {
|
||||
return <BMSCoreCells sc={sc} rating={rating} />;
|
||||
} else if (game === "sdvx" || game === "usc") {
|
||||
return (
|
||||
<SDVXScoreCoreCells
|
||||
sc={sc}
|
||||
chart={chart as ChartDocument<"sdvx:Single" | "usc:Controller" | "usc:Keyboard">}
|
||||
/>
|
||||
);
|
||||
} else if (game === "museca") {
|
||||
return <MusecaCoreCells sc={sc} rating={rating} />;
|
||||
} else if (game === "wacca") {
|
||||
return <WACCACoreCells sc={sc} rating={rating} />;
|
||||
} else if (game === "popn") {
|
||||
return <PopnCoreCells sc={sc} rating={rating} />;
|
||||
} else if (game === "jubeat") {
|
||||
return <JubeatCoreCells sc={sc} rating={rating} />;
|
||||
} else if (game === "chunithm") {
|
||||
return <CHUNITHMCoreCells sc={sc} rating={rating} />;
|
||||
} else if (game === "gitadora") {
|
||||
return <GenericCoreCells sc={sc} rating={rating} />;
|
||||
} else if (game === "pms") {
|
||||
return <PMSCoreCells sc={sc} rating={rating} />;
|
||||
} else if (game === "itg") {
|
||||
return <ITGCoreCells sc={sc} rating={rating} />;
|
||||
switch (game) {
|
||||
case "iidx":
|
||||
return (
|
||||
<IIDXCoreCells
|
||||
rating={rating as ScoreCalculatedDataLookup["iidx:SP" | "iidx:DP"]}
|
||||
chart={chart as ChartDocument<"iidx:SP" | "iidx:DP">}
|
||||
sc={sc}
|
||||
/>
|
||||
);
|
||||
case "bms":
|
||||
return <BMSCoreCells sc={sc} rating={rating} />;
|
||||
case "sdvx":
|
||||
case "usc":
|
||||
return (
|
||||
<SDVXScoreCoreCells
|
||||
sc={sc}
|
||||
chart={
|
||||
chart as ChartDocument<"sdvx:Single" | "usc:Controller" | "usc:Keyboard">
|
||||
}
|
||||
/>
|
||||
);
|
||||
case "museca":
|
||||
return <MusecaCoreCells sc={sc} rating={rating} />;
|
||||
case "wacca":
|
||||
return <WACCACoreCells sc={sc} rating={rating} />;
|
||||
case "popn":
|
||||
return <PopnCoreCells sc={sc} rating={rating} />;
|
||||
case "jubeat":
|
||||
return <JubeatCoreCells sc={sc} rating={rating} />;
|
||||
case "chunithm":
|
||||
return <CHUNITHMCoreCells sc={sc} rating={rating} />;
|
||||
case "gitadora":
|
||||
return <GitadoraCoreCells sc={sc} rating={rating} />;
|
||||
case "pms":
|
||||
return <PMSCoreCells sc={sc} rating={rating} />;
|
||||
case "itg":
|
||||
return <ITGCoreCells sc={sc} rating={rating} />;
|
||||
}
|
||||
|
||||
return <GenericCoreCells sc={sc} rating={rating} />;
|
||||
}
|
||||
|
||||
@@ -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<UGSRatingsLookup[IDStrings], { ranking: number; outOf: integer }>;
|
||||
rankingData: Record<ProfileRatingLookup[IDStrings], { ranking: number; outOf: integer }>;
|
||||
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(
|
||||
|
||||
@@ -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 (
|
||||
<MiniTable className="table-sm text-center" headers={["Player Stats"]} colSpan={2}>
|
||||
|
||||
@@ -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<I extends IDStrings = IDStrings>(
|
||||
export function useProfileRatingAlg<I extends IDStrings = IDStrings>(
|
||||
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];
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
ShowcaseStatFolder,
|
||||
SongDocument,
|
||||
TableDocument,
|
||||
UGSRatingsLookup,
|
||||
ProfileRatingLookup,
|
||||
UserGameStats,
|
||||
UserGameStatsSnapshot,
|
||||
QuestDocument,
|
||||
@@ -36,7 +36,7 @@ export interface UGPTStatsReturn<I extends IDStrings = IDStrings> {
|
||||
mostRecentScore: ScoreDocument<I>;
|
||||
totalScores: number;
|
||||
rankingData: Record<
|
||||
UGSRatingsLookup[I],
|
||||
ProfileRatingLookup[I],
|
||||
{
|
||||
ranking: integer;
|
||||
outOf: integer;
|
||||
@@ -92,7 +92,7 @@ export interface UGPTChartPBComposition<I extends IDStrings = IDStrings> {
|
||||
}
|
||||
|
||||
export type UGSWithRankingData<I extends IDStrings = IDStrings> = UserGameStats<I> & {
|
||||
__rankingData: Record<UGSRatingsLookup[I], { outOf: number; ranking: number }>;
|
||||
__rankingData: Record<ProfileRatingLookup[I], { outOf: number; ranking: number }>;
|
||||
};
|
||||
|
||||
export interface SongChartsSearch<I extends IDStrings = IDStrings> {
|
||||
|
||||
@@ -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,
|
||||
|
||||
+14
-28
@@ -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<G extends Game = Game> {
|
||||
@@ -49,21 +49,21 @@ interface BaseGamePTConfig<I extends IDStrings> {
|
||||
|
||||
defaultScoreRatingAlg: ScoreCalculatedDataLookup[I];
|
||||
defaultSessionRatingAlg: SessionCalculatedDataLookup[I];
|
||||
defaultProfileRatingAlg: UGSRatingsLookup[I];
|
||||
defaultProfileRatingAlg: ProfileRatingLookup[I];
|
||||
|
||||
scoreRatingAlgs: Array<ScoreCalculatedDataLookup[I]>;
|
||||
sessionRatingAlgs: Array<SessionCalculatedDataLookup[I]>;
|
||||
profileRatingAlgs: Array<UGSRatingsLookup[I]>;
|
||||
profileRatingAlgs: Array<ProfileRatingLookup[I]>;
|
||||
|
||||
scoreRatingAlgDescriptions: Record<ScoreCalculatedDataLookup[I], string>;
|
||||
sessionRatingAlgDescriptions: Record<SessionCalculatedDataLookup[I], string>;
|
||||
profileRatingAlgDescriptions: Record<UGSRatingsLookup[I], string>;
|
||||
profileRatingAlgDescriptions: Record<ProfileRatingLookup[I], string>;
|
||||
|
||||
scoreRatingAlgFormatters: Partial<Record<ScoreCalculatedDataLookup[I], (v: number) => string>>;
|
||||
sessionRatingAlgFormatters: Partial<
|
||||
Record<SessionCalculatedDataLookup[I], (v: number) => string>
|
||||
>;
|
||||
profileRatingAlgFormatters: Partial<Record<UGSRatingsLookup[I], (v: number) => string>>;
|
||||
profileRatingAlgFormatters: Partial<Record<ProfileRatingLookup[I], (v: number) => string>>;
|
||||
|
||||
difficulties: Array<Difficulties[I]>;
|
||||
shortDifficulties: Partial<Record<Difficulties[I], string>>;
|
||||
@@ -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: {
|
||||
|
||||
@@ -80,7 +80,7 @@ export const GitadoraColours: Array<ClassInfo> = [
|
||||
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<ClassInfo> = [
|
||||
|
||||
+4
-4
@@ -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<I extends IDStrings = IDStrings> extends MongoDBD
|
||||
userID: integer;
|
||||
game: IDStringToGame[I];
|
||||
playtype: IDStringToPlaytype[I];
|
||||
ratings: Partial<Record<UGSRatingsLookup[I], number | null>>;
|
||||
ratings: Partial<Record<ProfileRatingLookup[I], number | null>>;
|
||||
classes: Partial<GameClasses<I>>;
|
||||
}
|
||||
|
||||
@@ -1359,7 +1359,7 @@ export interface UGPTSettings<I extends IDStrings = IDStrings> extends MongoDBDo
|
||||
preferences: {
|
||||
preferredScoreAlg: ScoreCalculatedDataLookup[I] | null;
|
||||
preferredSessionAlg: SessionCalculatedDataLookup[I] | null;
|
||||
preferredProfileAlg: UGSRatingsLookup[I] | null;
|
||||
preferredProfileAlg: ProfileRatingLookup[I] | null;
|
||||
stats: Array<ShowcaseStatDetails>;
|
||||
scoreBucket: "grade" | "lamp" | null;
|
||||
defaultTable: string | null;
|
||||
@@ -1372,7 +1372,7 @@ export interface UGPTSettings<I extends IDStrings = IDStrings> extends MongoDBDo
|
||||
export interface UserGameStatsSnapshot<I extends IDStrings = IDStrings>
|
||||
extends MongoDBDocument,
|
||||
UserGameStats<I> {
|
||||
rankings: Record<UGSRatingsLookup[I], { ranking: integer | null; outOf: integer }>;
|
||||
rankings: Record<ProfileRatingLookup[I], { ranking: integer | null; outOf: integer }>;
|
||||
playcount: integer;
|
||||
timestamp: integer;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Vendored
+1
-1
@@ -111,7 +111,7 @@ const staticIndexes: Partial<Record<Databases, Array<Index>>> = {
|
||||
"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)],
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user