Skip to content

Commit

Permalink
feat: Ongeki support (#1013)
Browse files Browse the repository at this point in the history
* feat: initial ongeki support

* feat: initial ongeki seeds

* chore: link to a basic score exporter

* fix: unhardcode the colSpan of score dropdowns

Fixes ongeki and doesn't break chunithm

* fix: make bellCount optional to match judgements and damage

* docs: add a page for Ongeki

* feat: ongeki seeder

* feat: implement isHot

Also restore Arcaea to test.conf.json5 (it was a mistake)

* fix: add isHot to the seeder

* fix: proper handling of re:masters

Also change non-full-bell from an empty string to "NONE", for clarity

* docs: document the re:master fix

* feat: update rg-stats to 0.5.5

enables ongeki calcs

* chore: lockfile

* fix: get rid of scales as they're unused

* fix: update name->NAME

* minrelevantvalue should be one of the values?

* fix: add property that must be there?

* fix: jesus christ the tests are loud

* better docs on mrv

* fix: remove platdelta, make platscore optional

* fix: grade B tests oh my god

* fix: rating check

* fix: pb merge check

* fix: pb merge check #2

* fix: use nowrap in all lamp cells

* fix: tidy up platcell

* fix: all of these MUST be part of scoreID

* fix: remove unused code

* feat: remove note counts & isHot

* chore: bump rg-stats

---------

Co-authored-by: zkldi <20380519+zkldi@users.noreply.github.com>
  • Loading branch information
nyairobi and zkrising authored May 8, 2024
1 parent 6e87ab2 commit 4a80b1f
Show file tree
Hide file tree
Showing 39 changed files with 82,721 additions and 51 deletions.
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"react-router-bootstrap": "^0.25.0",
"react-router-dom": "5.1.2",
"react-select": "^5.6.1",
"rg-stats": "0.5.4",
"rg-stats": "0.5.6",
"sync-fetch": "^0.3.1",
"tachi-common": "workspace:../common",
"vite-plugin-html": "^3.2.0"
Expand Down
17 changes: 16 additions & 1 deletion client/src/app/pages/dashboard/import/ImportPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,22 @@ function ImportInfoDisplayer({ game }: { game: Game }) {
key="SL-ITG"
/>
);
} // else if (game === "jubeat") {
} else if (game === 'ongeki') {
Content.unshift(
<ImportInfoCard
name="ARTEMiS Exporter"
href="ongeki-artemis-exporter"
desc="Export your scores from an ARTEMiS instance."
moreInfo={
<>
This is a script that exports scores from an ARTEMiS instance. <br />
Note: You will need direct access to the server instance.
</>
}
key="ARTEMiS Exporter"
/>
);
}// else if (game === "jubeat") {
// Content.unshift(
// <ImportTypeInfoCard key="api/cg-dev-jubeat" importType="api/cg-dev-jubeat" />,
// <ImportTypeInfoCard key="api/cg-prod-jubeat" importType="api/cg-prod-jubeat" />
Expand Down
27 changes: 27 additions & 0 deletions client/src/app/pages/dashboard/import/OngekiArtemisExportPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import useSetSubheader from "components/layout/header/useSetSubheader";
import Divider from "components/util/Divider";
import ExternalLink from "components/util/ExternalLink";
import { TachiConfig } from "lib/config";
import React from "react";

export default function OngekiArtemisExport() {
useSetSubheader(["Import Scores", "O.N.G.E.K.I. ARTEMiS Exporter"]);

return (
<div>
<h1 className="text-center mb-4">What is the ARTEMiS Exporter?</h1>
<div>
The Artemis Exporter is a script that will export your O.N.G.E.K.I. scores from an
ARTEMiS instance to a BATCH-MANUAL JSON for import to {TachiConfig.NAME}. You will
need direct access to the server instance.
</div>
<Divider />
<h1 className="text-center my-4">Setup Instructions</h1>
Instructions are available on{" "}
<ExternalLink href="https://gist.github.com/nyairobi/ffdf9e674f31987b1ffbd38d31b55f6c">
the GitHub gist
</ExternalLink>
.
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { APIFetchV1 } from "util/api";
import { Reverse } from "util/misc";
import { Reverse, UppercaseFirst } from "util/misc";
import DistributionTable from "components/game/folder/FolderDistributionTable";
import Card from "components/layout/page/Card";
import DebounceSearch from "components/util/DebounceSearch";
Expand All @@ -14,7 +14,13 @@ import useUGPTBase from "components/util/useUGPTBase";
import { UserContext } from "context/UserContext";
import { GPT_CLIENT_IMPLEMENTATIONS } from "lib/game-implementations";
import React, { useContext, useMemo, useState } from "react";
import { FolderDocument, GetGPTString, GetGamePTConfig, GetScoreMetricConf } from "tachi-common";
import {
FolderDocument,
GetGPTString,
GetGamePTConfig,
GetScoreMetricConf,
GetScoreMetrics,
} from "tachi-common";
import { ConfEnumScoreMetric } from "tachi-common/types/metrics";
import { FolderStatsInfo, UGPTFolderSearch } from "types/api-returns";
import { UGPT } from "types/react";
Expand Down Expand Up @@ -130,12 +136,12 @@ export function FolderInfoComponent({
<div className="row text-center">
<div className="col-12">
<div className="btn-group">
<SelectButton value={metric} setValue={setMetric} id="grade">
<Icon type="sort-alpha-up" /> Grades
</SelectButton>
<SelectButton value={metric} setValue={setMetric} id="lamp">
<Icon type="lightbulb" /> Lamps
</SelectButton>
{GetScoreMetrics(gptConfig, "ENUM").map((e) => (
<SelectButton value={metric} setValue={setMetric} id={e}>
{/* @ts-expect-error this access is legal zzz */}
<Icon type={gptImpl.enumIcons[e]} /> {UppercaseFirst(e)}s
</SelectButton>
))}
</div>
<Divider />
{dataset}
Expand Down
5 changes: 5 additions & 0 deletions client/src/app/routes/ImportRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import ChunithmSiteImportPage from "app/pages/dashboard/import/ChunithmSiteImpor
import SaekawaPage from "app/pages/dashboard/import/SaekawaPage";
import AquaArtemisExport from "app/pages/dashboard/import/AquaArtemisExportPage";
import ChunithmMYTExport from "app/pages/dashboard/import/ChunithmMYTExportPage";
import OngekiArtemisExport from "app/pages/dashboard/import/OngekiArtemisExportPage";

export default function ImportRoutes() {
const { user } = useContext(UserContext);
Expand Down Expand Up @@ -224,6 +225,10 @@ export default function ImportRoutes() {
<Route exact path="/import/kt-maimaidx-site-importer">
<MaimaiDXSiteImportPage />
</Route>

<Route exact path="/import/ongeki-artemis-exporter">
<OngekiArtemisExport />
</Route>
</>
)}
</Route>
Expand Down
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 @@ -28,6 +28,7 @@ const GPT_UTILS: Record<GPTString, Array<GPTUtility>> = {
"wacca:Single": [],
"maimaidx:Single": [],
"maimai:Single": [],
"ongeki:Single": [],
};

export function GetGPTUtils(game: Game, playtype: Playtype) {
Expand Down
1 change: 1 addition & 0 deletions client/src/components/tables/cells/BMSOrPMSLampCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default function BMSOrPMSLampCell({
<td
style={{
backgroundColor: ChangeOpacity(GetEnumColour(score, "lamp"), 0.2),
whiteSpace: "nowrap",
}}
>
<strong>{score.scoreData.lamp}</strong>
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/tables/cells/IIDXLampCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ChangeOpacity } from "util/color-opacity";
import { IsNotNullish } from "util/misc";
import { GetEnumColour } from "lib/game-implementations";
import React from "react";
import { ChartDocument, GetGPTString, PBScoreDocument, ScoreDocument } from "tachi-common";
import { ChartDocument, PBScoreDocument, ScoreDocument } from "tachi-common";

export default function IIDXLampCell({
sc,
Expand Down Expand Up @@ -62,6 +62,7 @@ export default function IIDXLampCell({
<td
style={{
backgroundColor: ChangeOpacity(GetEnumColour(sc, "lamp"), 0.2),
whiteSpace: "nowrap",
}}
>
<strong>{sc.scoreData.lamp}</strong>
Expand Down
1 change: 1 addition & 0 deletions client/src/components/tables/cells/LampCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default function LampCell({ lamp, colour }: { lamp: string; colour: strin
<td
style={{
backgroundColor: ChangeOpacity(colour, 0.2),
whiteSpace: "nowrap",
}}
>
<strong>{lamp}</strong>
Expand Down
42 changes: 42 additions & 0 deletions client/src/components/tables/cells/OngekiJudgementCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { IsNullish } from "util/misc";
import React from "react";
import { COLOUR_SET, PBScoreDocument, ScoreDocument } from "tachi-common";

export default function OngekiJudgementCell({
score,
}: {
score: ScoreDocument<"ongeki:Single"> | PBScoreDocument<"ongeki:Single">;
}) {
const judgements = score.scoreData.judgements;

if (
IsNullish(judgements.miss) ||
IsNullish(judgements.hit) ||
IsNullish(judgements.break) ||
IsNullish(judgements.cbreak)
) {
return <td>No Data.</td>;
}

return (
<td>
<strong>
<div>
<span style={{ color: COLOUR_SET.gold }}>{judgements.cbreak}</span>-
<span style={{ color: COLOUR_SET.orange }}>{judgements.break}</span>-
<span style={{ color: COLOUR_SET.vibrantBlue }}>{judgements.hit}</span>-
<span style={{ color: COLOUR_SET.gray }}>{judgements.miss}</span>
</div>
<div>
<span style={{ color: COLOUR_SET.vibrantYellow }}>
{score.scoreData.optional.bellCount ?? "?"}/
{score.scoreData.optional.totalBellCount ?? "?"}
</span>
<span style={{ color: COLOUR_SET.red, marginLeft: "0.5em" }}>
{score.scoreData.optional.damage ?? "?"}
</span>
</div>
</strong>
</td>
);
}
38 changes: 38 additions & 0 deletions client/src/components/tables/cells/OngekiLampCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ChangeOpacity } from "util/color-opacity";
import React from "react";

export default function OngekiLampCell({
lamp1,
lamp2,
colour,
}: {
lamp1: string;
lamp2: string;
colour: string;
}) {
let content = <div>{lamp1}</div>;

if (lamp2 !== "NONE") {
if (lamp1 === "CLEAR") {
content = <div>{lamp2}</div>;
} else {
content = (
<span>
<div>{lamp1}</div>
<div>{lamp2}</div>
</span>
);
}
}

return (
<td
style={{
backgroundColor: ChangeOpacity(colour, 0.2),
whiteSpace: "nowrap",
}}
>
<strong>{content}</strong>
</td>
);
}
1 change: 1 addition & 0 deletions client/src/components/tables/cells/PopnLampCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default function PopnLampCell({
GPT_CLIENT_IMPLEMENTATIONS["popn:9B"].enumColours.lamp[score.scoreData.lamp],
0.2
),
whiteSpace: "nowrap",
}}
>
<strong>{score.scoreData.lamp}</strong>
Expand Down
1 change: 1 addition & 0 deletions client/src/components/tables/cells/SDVXLampCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default function SDVXLampCell({
<td
style={{
backgroundColor: ChangeOpacity(GetEnumColour(score, "lamp"), 0.2),
whiteSpace: "nowrap",
}}
>
<strong>{score.scoreData.lamp === "FAILED" ? "PLAYED" : score.scoreData.lamp}</strong>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import TimestampCell from "components/tables/cells/TimestampCell";
import ScoreCoreCells from "components/tables/game-core-cells/ScoreCoreCells";
import useScoreRatingAlg from "components/util/useScoreRatingAlg";
import React, { useContext, useEffect, useState } from "react";
import { ChartDocument, PBScoreDocument, ScoreDocument } from "tachi-common";
import { ChartDocument, GetGPTString, PBScoreDocument, ScoreDocument } from "tachi-common";
import { UGPTChartPBComposition } from "types/api-returns";
import { SetState } from "types/react";
import { UserContext } from "context/UserContext";
import { GPT_CLIENT_IMPLEMENTATIONS } from "lib/game-implementations";
import CommentContainer from "./CommentContainer";
import JudgementTable from "./JudgementTable";
import PBNote from "./PBNote";
Expand All @@ -22,13 +23,14 @@ export function ScoreInfo({
chart: ChartDocument;
}) {
const rating = useScoreRatingAlg(score.game, score.playtype);
const gptImpl = GPT_CLIENT_IMPLEMENTATIONS[GetGPTString(score.game, chart.playtype)];

return (
<div className="col-12">
<table className="table">
<thead>
<tr>
<td colSpan={3}>Score Info</td>
<td colSpan={gptImpl.scoreHeaders.length}>Score Info</td>
<td>{UppercaseFirst(rating)}</td>
<td>Timestamp</td>
</tr>
Expand Down
Loading

0 comments on commit 4a80b1f

Please sign in to comment.