Skip to content

Commit

Permalink
feat: arcaea support (#951)
Browse files Browse the repository at this point in the history
Co-authored-by: beerpiss <[email protected]>
  • Loading branch information
j1nxie and beer-psi authored Oct 11, 2023
1 parent a445bff commit b51be4e
Show file tree
Hide file tree
Showing 32 changed files with 24,599 additions and 21 deletions.
4 changes: 2 additions & 2 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"react-router-bootstrap": "^0.25.0",
"react-router-dom": "5.1.2",
"react-select": "^5.6.1",
"rg-stats": "0.5.2",
"rg-stats": "0.5.4",
"sync-fetch": "^0.3.1",
"tachi-common": "workspace:../common",
"vite-plugin-html": "^3.2.0"
Expand All @@ -89,4 +89,4 @@
"typescript": "4.9.4",
"vite": "^3.0.7"
}
}
}
1 change: 1 addition & 0 deletions client/src/components/gpt-utils/GPTUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { BMSSieglindeInfoTool } from "./tools/BMSSieglindeInfoTool";

// What utils does each game support?
const GPT_UTILS: Record<GPTString, Array<GPTUtility>> = {
"arcaea:Touch": [],
"bms:7K": [BMSCustomTablesTool, BMSSieglindeInfoTool],
"bms:14K": [BMSCustomTablesTool, BMSSieglindeInfoTool],
"chunithm:Single": [],
Expand Down
36 changes: 36 additions & 0 deletions client/src/components/tables/cells/ArcaeaJudgementCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { IsNullish } from "util/misc";
import React from "react";
import { COLOUR_SET, PBScoreDocument, ScoreDocument } from "tachi-common";

export default function ArcaeaJudgementCell({
score,
}: {
score: ScoreDocument<"arcaea:Touch"> | PBScoreDocument<"arcaea:Touch">;
}) {
// even if we dont have judgement data, we know what they got.
if (score.scoreData.lamp === "PURE MEMORY") {
return (
<td>
<strong>
<span style={{ color: COLOUR_SET.vibrantYellow }}>0</span>-
<span style={{ color: COLOUR_SET.red }}>0</span>
</strong>
</td>
);
}

const judgements = score.scoreData.judgements;

if (IsNullish(judgements.far) || IsNullish(judgements.lost)) {
return <td>No Data.</td>;
}

return (
<td>
<strong>
<span style={{ color: COLOUR_SET.vibrantYellow }}>{judgements.far}</span>-
<span style={{ color: COLOUR_SET.red }}>{judgements.lost}</span>
</strong>
</td>
);
}
12 changes: 7 additions & 5 deletions client/src/lib/game-implementations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ import RatingCell from "components/tables/cells/RatingCell";
import ScoreCell from "components/tables/cells/ScoreCell";
import WaccaJudgementCell from "components/tables/cells/WACCAJudgementCell";
import React from "react";
import { CreateRatingSys, bg, bgc } from "./games/_util";
import { CreateRatingSys, bgc } from "./games/_util";
import { BMS_14K_IMPL, BMS_7K_IMPL, PMS_IMPL } from "./games/bms-pms";
import { IIDX_DP_IMPL, IIDX_SP_IMPL } from "./games/iidx";
import { GPTClientImplementation } from "./types";
import { SDVX_IMPL, USC_IMPL } from "./games/sdvx-usc";
import { GITADORA_DORA_IMPL, GITADORA_GITA_IMPL } from "./games/gitadora";
import { ARCAEA_TOUCH_IMPL } from "./games/arcaea";

type GPTClientImplementations = {
[GPT in GPTString]: GPTClientImplementation<GPT>;
Expand Down Expand Up @@ -389,8 +390,8 @@ export const GPT_CLIENT_IMPLEMENTATIONS: GPTClientImplementations = {
background:
"linear-gradient(-45deg, #f0788a, #f48fb1, #9174c2, #79bcf2, #70a173, #f7ff99, #faca7d, #ff9d80, #f0788a)",
color: "var(--bs-dark)",
}
}
},
},
},
difficultyColours: {
Basic: COLOUR_SET.green,
Expand Down Expand Up @@ -706,8 +707,8 @@ export const GPT_CLIENT_IMPLEMENTATIONS: GPTClientImplementations = {
{chart.data.rankedLevel === null
? "Unranked Chart."
: sc.calculatedData.blockRating === null
? "Failed"
: sc.calculatedData.blockRating}
? "Failed"
: sc.calculatedData.blockRating}
</strong>
</td>
) : (
Expand All @@ -716,6 +717,7 @@ export const GPT_CLIENT_IMPLEMENTATIONS: GPTClientImplementations = {
</>
),
},
"arcaea:Touch": ARCAEA_TOUCH_IMPL,
"gitadora:Dora": GITADORA_DORA_IMPL,
"gitadora:Gita": GITADORA_GITA_IMPL,
"bms:14K": BMS_14K_IMPL,
Expand Down
103 changes: 103 additions & 0 deletions client/src/lib/games/arcaea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { NumericSOV } from "util/sorts";
import { GPTClientImplementation } from "lib/types";
import { COLOUR_SET, GPTStrings } from "tachi-common";
import MillionsScoreCell from "components/tables/cells/MillionsScoreCell";
import { GetEnumColour } from "lib/game-implementations";
import ArcaeaJudgementCell from "components/tables/cells/ArcaeaJudgementCell";
import RatingCell from "components/tables/cells/RatingCell";
import LampCell from "components/tables/cells/LampCell";
import React from "react";
import { bgc } from "./_util";

const ARCAEA_DIFFICULTY_COLORS: GPTClientImplementation<GPTStrings["arcaea"]>["difficultyColours"] =
{
Past: COLOUR_SET.paleBlue,
Present: COLOUR_SET.paleGreen,
Future: COLOUR_SET.purple,
Beyond: COLOUR_SET.vibrantRed,
};

const ARCAEA_ENUM_COLORS: GPTClientImplementation<GPTStrings["arcaea"]>["enumColours"] = {
lamp: {
LOST: COLOUR_SET.red,
"EASY CLEAR": COLOUR_SET.green,
CLEAR: COLOUR_SET.purple,
"HARD CLEAR": COLOUR_SET.vibrantRed,
"FULL RECALL": COLOUR_SET.vibrantPurple,
"PURE MEMORY": COLOUR_SET.vibrantBlue,
},
grade: {
D: COLOUR_SET.red,
C: COLOUR_SET.maroon,
B: COLOUR_SET.purple,
A: COLOUR_SET.vibrantPurple,
AA: COLOUR_SET.blue,
EX: COLOUR_SET.vibrantBlue,
"EX+": COLOUR_SET.teal,
},
};

const ARCAEA_COLORS: GPTClientImplementation<GPTStrings["arcaea"]>["classColours"] = {
badge: {
BLUE: bgc("midnightblue", "var(--bs-light)"),
GREEN: bgc("darkgreen", "var(--bs-light)"),
ASH_PURPLE: bgc("indigo", "var(--bs-light)"),
PURPLE: bgc("purple", "var(--bs-light)"),
RED: bgc("darkred", "var(--bs-light)"),
ONE_STAR: bgc("crimson", "var(--bs-light)"),
TWO_STARS: bgc("darkmagenta", "var(--bs-light)"),
THREE_STARS: bgc("firebrick", "var(--bs-light)"),
},
courseBanner: {
PHASE_1: bgc("aliceblue", "var(--bs-dark)"),
PHASE_2: bgc("lightskyblue", "var(--bs-dark)"),
PHASE_3: bgc("lightblue", "var(--bs-dark)"),
PHASE_4: bgc("midnightblue", "var(--bs-light)"),
PHASE_5: bgc("plum", "var(--bs-dark)"),
PHASE_6: bgc("violet", "var(--bs-dark)"),
PHASE_7: bgc("orchid", "var(--bs-dark)"),
PHASE_8: bgc("purple", "var(--bs-light)"),
PHASE_9: bgc("indigo", "var(--bs-light)"),
PHASE_10: bgc("firebrick", "var(--bs-light)"),
PHASE_11: bgc("darkred", "var(--bs-light)"),
},
};

const ARCAEA_SCORE_HEADERS: GPTClientImplementation<GPTStrings["arcaea"]>["scoreHeaders"] = [
["Score", "Score", NumericSOV((x) => x.scoreData.score)],
["Far - Lost", "Far - Lost", NumericSOV((x) => x.scoreData.score)],
["Lamp", "Lamp", NumericSOV((x) => x.scoreData.enumIndexes.lamp)],
];

const ArcaeaCoreCells: GPTClientImplementation<GPTStrings["arcaea"]>["scoreCoreCells"] = ({
sc,
}) => (
<>
<MillionsScoreCell
colour={GetEnumColour(sc, "grade")}
grade={sc.scoreData.grade}
score={sc.scoreData.score}
/>
<ArcaeaJudgementCell score={sc} />
<LampCell lamp={sc.scoreData.lamp} colour={GetEnumColour(sc, "lamp")} />
</>
);

const ArcaeaRatingCell: GPTClientImplementation<GPTStrings["arcaea"]>["ratingCell"] = ({
sc,
rating,
}) => <RatingCell score={sc} rating={rating} />;

export const ARCAEA_TOUCH_IMPL: GPTClientImplementation<"arcaea:Touch"> = {
ratingSystems: [],
enumIcons: {
grade: "sort-alpha-up",
lamp: "lightbulb",
},
enumColours: ARCAEA_ENUM_COLORS,
classColours: ARCAEA_COLORS,
difficultyColours: ARCAEA_DIFFICULTY_COLORS,
scoreHeaders: ARCAEA_SCORE_HEADERS,
scoreCoreCells: ArcaeaCoreCells,
ratingCell: ArcaeaRatingCell,
};
1 change: 1 addition & 0 deletions client/src/util/scales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const scales: Record<Game, number> = {
popn: 4,
jubeat: 5,
itg: 5,
arcaea: 1,
};

export function GetGradeChartExpScale(game: Game) {
Expand Down
3 changes: 3 additions & 0 deletions common/src/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable lines-around-comment */

import { ARCAEA_CONF, ARCAEA_TOUCH_CONF } from "./game-support/arcaea";
import { BMS_14K_CONF, BMS_7K_CONF, BMS_CONF } from "./game-support/bms";
import { CHUNITHM_CONF, CHUNITHM_SINGLE_CONF } from "./game-support/chunithm";
import { GITADORA_CONF, GITADORA_DORA_CONF, GITADORA_GITA_CONF } from "./game-support/gitadora";
Expand Down Expand Up @@ -46,6 +47,7 @@ export const GAME_CONFIGS = {
wacca: WACCA_CONF,
pms: PMS_CONF,
itg: ITG_CONF,
arcaea: ARCAEA_CONF,
} as const satisfies Record<string, INTERNAL_GAME_CONFIG>;

/**
Expand Down Expand Up @@ -92,6 +94,7 @@ export const GAME_PT_CONFIGS = {
"usc:Controller": USC_CONTROLLER_CONF,
"usc:Keyboard": USC_KEYBOARD_CONF,
"itg:Stamina": ITG_STAMINA_CONF,
"arcaea:Touch": ARCAEA_TOUCH_CONF,
} as const satisfies Record<GPTString, INTERNAL_GAME_PT_CONFIG>;

/**
Expand Down
136 changes: 136 additions & 0 deletions common/src/config/game-support/arcaea.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { FAST_SLOW_MAXCOMBO } from "./_common";
import { FmtNum } from "../../utils/util";
import { ClassValue, ToDecimalPlaces, zodNonNegativeInt } from "../config-utils";
import { z } from "zod";
import type { INTERNAL_GAME_CONFIG, INTERNAL_GAME_PT_CONFIG } from "../../types/internals";

export const ARCAEA_CONF = {
name: "Arcaea",
// Potential future controller playtype support?
playtypes: ["Touch"],
songData: z.strictObject({
displayVersion: z.string(),
songPack: z.string(),
}),
} as const satisfies INTERNAL_GAME_CONFIG;

const ArcaeaBadges = [
ClassValue("BLUE", "Blue", "0.00 - 3.49 Potential"),
ClassValue("GREEN", "Green", "3.50 - 6.99 Potential"),
ClassValue("ASH_PURPLE", "Ash Purple", "7.00 - 9.99 Potential"),
ClassValue("PURPLE", "Purple", "10.00 - 10.99 Potential"),
ClassValue("RED", "Red", "11.00 - 11.99 Potential"),
ClassValue("ONE_STAR", "☆", "12.00 - 12.49 Potential"),
ClassValue("TWO_STARS", "☆☆", "12.50 - 12.99 Potential"),
ClassValue("THREE_STARS", "☆☆☆", ">=13.00 Potential"),
];

const ArcaeaClasses = [
ClassValue("PHASE_1", "Phase 1", "First Step in a New World"),
ClassValue("PHASE_2", "Phase 2", "Swept up in a Heartbeat"),
ClassValue("PHASE_3", "Phase 3", "Unceasing Spirit"),
ClassValue("PHASE_4", "Phase 4", "The Eternal Realm of Light"),
ClassValue("PHASE_5", "Phase 5", "The Brutality of Glass"),
ClassValue("PHASE_6", "Phase 6", "In Grief and Great Delight"),
ClassValue("PHASE_7", "Phase 7", "On Fate's Approach"),
ClassValue("PHASE_8", "Phase 8", "The Disfigured Flow of Time"),
ClassValue("PHASE_9", "Phase 9", "Ego's Demise"),
ClassValue("PHASE_10", "Phase 10", "A Torrent of Light and Conflict"),
ClassValue("PHASE_11", "Phase 11", "Radiant Genesis"),
];

export const ARCAEA_TOUCH_CONF = {
providedMetrics: {
score: {
type: "INTEGER",
chartDependentMax: true,
formatter: FmtNum,
description:
"The score value. This is between 0 and 10 million, plus bonus points dependent on how many shiny PUREs you get.",
},
lamp: {
type: "ENUM",
values: ["LOST", "EASY CLEAR", "CLEAR", "HARD CLEAR", "FULL RECALL", "PURE MEMORY"],
minimumRelevantValue: "EASY CLEAR",
description: "The type of clear this was.",
},
},

derivedMetrics: {
grade: {
type: "ENUM",
values: ["D", "C", "B", "A", "AA", "EX", "EX+"],
minimumRelevantValue: "AA",
description: "The grade this score was.",
},
},

defaultMetric: "score",
preferredDefaultEnum: "grade",

optionalMetrics: FAST_SLOW_MAXCOMBO,

scoreRatingAlgs: {
potential: {
description: "Potential as it is implemented in Arcaea.",
formatter: ToDecimalPlaces(2),
},
},
sessionRatingAlgs: {
naivePotential: {
description: "The average of your best 10 potentials this session.",
formatter: ToDecimalPlaces(2),
},
},
profileRatingAlgs: {
naivePotential: {
description:
"The average of your best 30 potential values. This is different to in-game, as it does not take into account your recent scores in any way.",
formatter: ToDecimalPlaces(2),
},
},

defaultScoreRatingAlg: "potential",
defaultSessionRatingAlg: "naivePotential",
defaultProfileRatingAlg: "naivePotential",

difficulties: {
type: "FIXED",
order: ["Past", "Present", "Future", "Beyond"],
shorthand: {
Past: "PST",
Present: "PRS",
Future: "FTR",
Beyond: "BYD",
},
default: "Future",
},

classes: {
badge: {
type: "DERIVED",
values: ArcaeaBadges,
},
courseBanner: {
type: "PROVIDED",
values: ArcaeaClasses,
},
},

orderedJudgements: ["pure", "far", "lost"],

versions: {
mobile: "Mobile",
switch: "Nintendo Switch",
},

chartData: z.strictObject({
inGameID: z.string(),
notecount: zodNonNegativeInt,
}),

preferences: z.strictObject({}),
scoreMeta: z.strictObject({}),

supportedMatchTypes: ["songTitle", "tachiSongID"],
} as const satisfies INTERNAL_GAME_PT_CONFIG;
4 changes: 2 additions & 2 deletions common/src/config/game-support/chunithm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const CHUNITHMClasses = [
ClassValue("DAN_IV", "IV", "Class IV"),
ClassValue("DAN_V", "V", "Class V"),
ClassValue("DAN_INFINITE", "∞", "Infinite Class"),
]
];

export const CHUNITHM_SINGLE_CONF = {
providedMetrics: {
Expand Down Expand Up @@ -133,7 +133,7 @@ export const CHUNITHM_SINGLE_CONF = {
emblem: {
type: "PROVIDED",
values: CHUNITHMClasses,
}
},
},

orderedJudgements: ["jcrit", "justice", "attack", "miss"],
Expand Down
Loading

0 comments on commit b51be4e

Please sign in to comment.