mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-13 09:48:27 +03:00
More Large Commits
This commit is contained in:
@@ -166,6 +166,7 @@ function LastSession({ reqUser, game, playtype }: { reqUser: PublicUserDocument
|
||||
{...data}
|
||||
game={game}
|
||||
playtype={playtype}
|
||||
reqUser={reqUser}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
@@ -183,9 +184,11 @@ function RecentSessionScoreInfo({
|
||||
sessionData,
|
||||
game,
|
||||
playtype,
|
||||
reqUser,
|
||||
}: {
|
||||
session: SessionDocument;
|
||||
sessionData: SessionReturns;
|
||||
reqUser: PublicUserDocument;
|
||||
} & GamePT) {
|
||||
const highlightedScores = sessionData.scores.find(e => e.highlight);
|
||||
|
||||
@@ -250,7 +253,7 @@ function RecentSessionScoreInfo({
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 mt-4">
|
||||
<IIDXScoreTable dataset={dataset as any} pageLen={5} />
|
||||
<IIDXScoreTable dataset={dataset as any} pageLen={5} reqUser={reqUser} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -199,7 +199,7 @@ function ScoresOverview({ reqUser, game, playtype }: { reqUser: PublicUserDocume
|
||||
style={{ height: 500 }}
|
||||
{...{ isLoading, dataset: data, error }}
|
||||
>
|
||||
<IIDXScoreTable dataset={data!} />
|
||||
<IIDXScoreTable dataset={data!} reqUser={reqUser} />
|
||||
</LoadingWrapper>
|
||||
) : (
|
||||
<ScoresSearch {...{ reqUser, game, playtype, search }} />
|
||||
@@ -221,7 +221,7 @@ function ScoresSearch({
|
||||
|
||||
return (
|
||||
<LoadingWrapper style={{ height: 500 }} {...{ isLoading, error, dataset: data }}>
|
||||
<IIDXScoreTable dataset={data!} />
|
||||
<IIDXScoreTable dataset={data!} reqUser={reqUser} />
|
||||
</LoadingWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,6 @@ export default function IIDXPBTable({
|
||||
<IIDXPBDropdown
|
||||
chart={pb.__related.chart}
|
||||
reqUser={reqUser}
|
||||
pb={pb}
|
||||
game={"iidx"}
|
||||
playtype={"SP"}
|
||||
/>
|
||||
|
||||
@@ -4,36 +4,28 @@ import IIDXLampCell from "components/tables/cells/IIDXLampCell";
|
||||
import ScoreCell from "components/tables/cells/ScoreCell";
|
||||
import TimestampCell from "components/tables/cells/TimestampCell";
|
||||
import MiniTable from "components/tables/components/MiniTable";
|
||||
import AsyncLoader from "components/util/AsyncLoader";
|
||||
import ExternalLink from "components/util/ExternalLink";
|
||||
import Icon from "components/util/Icon";
|
||||
import Loading from "components/util/Loading";
|
||||
import SelectButton from "components/util/SelectButton";
|
||||
import SelectNav from "components/util/SelectNav";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { Nav } from "react-bootstrap";
|
||||
import { useQuery } from "react-query";
|
||||
import {
|
||||
ChartDocument,
|
||||
Lamps,
|
||||
PBScoreDocument,
|
||||
PublicUserDocument,
|
||||
ScoreDocument,
|
||||
} from "tachi-common";
|
||||
import { ChartDocument, PBScoreDocument, PublicUserDocument } from "tachi-common";
|
||||
import { UGPTChartPBComposition } from "types/api-returns";
|
||||
import { GamePT } from "types/react";
|
||||
import { APIFetchV1 } from "util/api";
|
||||
import { IsScore } from "util/asserts";
|
||||
import DropdownStructure from "./components/DropdownStructure";
|
||||
import { IIDXGraphsComponent, ModsTable, ScoreInfo } from "./components/IIDXScoreDropdownParts";
|
||||
import JudgementTable from "./components/JudgementTable";
|
||||
type LampTypes = "NORMAL" | "EASY" | "HARD" | "EX_HARD";
|
||||
import PBNote from "./components/PBNote";
|
||||
|
||||
export default function IIDXPBDropdown({
|
||||
pb,
|
||||
game,
|
||||
playtype,
|
||||
reqUser,
|
||||
chart,
|
||||
}: {
|
||||
pb: PBScoreDocument<"iidx:SP" | "iidx:DP">;
|
||||
reqUser: PublicUserDocument;
|
||||
chart: ChartDocument<"iidx:SP">;
|
||||
} & GamePT) {
|
||||
@@ -67,36 +59,30 @@ export default function IIDXPBDropdown({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="p-2">
|
||||
<div className="row h-100 mb-0 align-items-center">
|
||||
<div className="col-3 col-xl-2">
|
||||
<div className="btn-group-vertical">
|
||||
<SelectButton setValue={setView} value={view} id="pb">
|
||||
<Icon type="trophy" />
|
||||
PB Info
|
||||
</SelectButton>
|
||||
<SelectButton setValue={setView} value={view} id="scorePB">
|
||||
<Icon type="star-half-alt" />
|
||||
Best Score
|
||||
</SelectButton>
|
||||
<SelectButton setValue={setView} value={view} id="lampPB">
|
||||
<Icon type="lightbulb" />
|
||||
Best Lamp
|
||||
</SelectButton>
|
||||
<SelectButton setValue={setView} value={view} id="history" disabled>
|
||||
<Icon type="history" />
|
||||
Play History
|
||||
</SelectButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-9 col-xl-10">
|
||||
<div className="row mb-0">
|
||||
{view === "history" ? <></> : <DocumentDisplay pbData={data} view={view} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DropdownStructure
|
||||
buttons={
|
||||
<>
|
||||
<SelectButton setValue={setView} value={view} id="pb">
|
||||
<Icon type="trophy" />
|
||||
PB Info
|
||||
</SelectButton>
|
||||
<SelectButton setValue={setView} value={view} id="scorePB">
|
||||
<Icon type="star-half-alt" />
|
||||
Best Score
|
||||
</SelectButton>
|
||||
<SelectButton setValue={setView} value={view} id="lampPB">
|
||||
<Icon type="lightbulb" />
|
||||
Best Lamp
|
||||
</SelectButton>
|
||||
<SelectButton setValue={setView} value={view} id="history" disabled>
|
||||
<Icon type="history" />
|
||||
Play History
|
||||
</SelectButton>
|
||||
</>
|
||||
}
|
||||
>
|
||||
{view === "history" ? <></> : <DocumentDisplay pbData={data} view={view} />}
|
||||
</DropdownStructure>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -105,7 +91,7 @@ function DocumentDisplay({
|
||||
view,
|
||||
}: {
|
||||
pbData: UGPTChartPBComposition<"iidx:SP">;
|
||||
view: "pb" | "scorePB" | "lampPB" | "bpPB" | "history";
|
||||
view: "pb" | "scorePB" | "lampPB" | "bpPB";
|
||||
}) {
|
||||
const idMap = {
|
||||
scorePB: pbData.pb.composedFrom.scorePB,
|
||||
@@ -122,134 +108,26 @@ function DocumentDisplay({
|
||||
return pbData.scores.filter(e => e.scoreID === idMap[view])[0];
|
||||
}, [view]);
|
||||
|
||||
const [lamp, setLamp] = useState(LampToKey(currentDoc.scoreData.lamp));
|
||||
|
||||
let gaugeStatus: "none" | "single" | "gsm" = "none";
|
||||
|
||||
if (currentDoc.scoreData.hitMeta.gsm) {
|
||||
gaugeStatus = "gsm";
|
||||
} else if (currentDoc.scoreData.hitMeta.gaugeHistory) {
|
||||
gaugeStatus = "single";
|
||||
}
|
||||
|
||||
const shouldDisable = (r: LampTypes) => {
|
||||
if (gaugeStatus === "gsm") {
|
||||
return false;
|
||||
} else if (gaugeStatus === "single") {
|
||||
return r !== LampToKey(currentDoc.scoreData.lamp);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
// @ts-expect-error temp
|
||||
currentDoc.comment = "THIS IS AN EXAMPLE COMMENT.";
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="col-9">
|
||||
<div className="row">
|
||||
<div className="col-12 d-flex justify-content-center">
|
||||
<Nav variant="pills">
|
||||
<SelectNav
|
||||
id="EASY"
|
||||
value={lamp}
|
||||
setValue={setLamp}
|
||||
disabled={shouldDisable("EASY")}
|
||||
>
|
||||
Easy
|
||||
</SelectNav>
|
||||
<SelectNav
|
||||
id="NORMAL"
|
||||
value={lamp}
|
||||
setValue={setLamp}
|
||||
disabled={shouldDisable("NORMAL")}
|
||||
>
|
||||
Normal
|
||||
</SelectNav>
|
||||
<SelectNav
|
||||
id="HARD"
|
||||
value={lamp}
|
||||
setValue={setLamp}
|
||||
disabled={shouldDisable("HARD")}
|
||||
>
|
||||
Hard
|
||||
</SelectNav>
|
||||
<SelectNav
|
||||
id="EX_HARD"
|
||||
value={lamp}
|
||||
setValue={setLamp}
|
||||
disabled={shouldDisable("EX_HARD")}
|
||||
>
|
||||
Ex Hard
|
||||
</SelectNav>
|
||||
</Nav>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
{gaugeStatus === "gsm" ? (
|
||||
<GraphComponent
|
||||
type={lamp}
|
||||
values={currentDoc.scoreData.hitMeta.gsm![lamp]}
|
||||
/>
|
||||
) : gaugeStatus === "single" ? (
|
||||
<GraphComponent
|
||||
type={lamp}
|
||||
values={currentDoc.scoreData.hitMeta.gaugeHistory!}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
style={{ height: "200px" }}
|
||||
>
|
||||
<span className="text-muted">No gauge data :(</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{view !== "pb" ? (
|
||||
<IIDXGraphsComponent score={currentDoc} />
|
||||
{IsScore(currentDoc) ? (
|
||||
<>
|
||||
<div className="col-12">
|
||||
<table className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td colSpan={100}>Score Info</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<ScoreCell
|
||||
score={currentDoc}
|
||||
game="iidx"
|
||||
playtype="SP"
|
||||
/>
|
||||
<DeltaCell
|
||||
game="iidx"
|
||||
playtype="SP"
|
||||
score={currentDoc.scoreData.score}
|
||||
percent={currentDoc.scoreData.percent}
|
||||
grade={currentDoc.scoreData.grade}
|
||||
/>
|
||||
<IIDXLampCell sc={currentDoc} />
|
||||
<TimestampCell time={currentDoc.timeAchieved} />
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{pbData.pb.composedFrom.lampPB === pbData.pb.composedFrom.scorePB && (
|
||||
<ScoreInfo score={currentDoc} />
|
||||
{currentDoc.comment && (
|
||||
<div className="col-12">
|
||||
<small>
|
||||
Looks like your best lamp and your best score was the same
|
||||
score!
|
||||
</small>
|
||||
<em>"{currentDoc.comment}"</em>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div className="col-12">
|
||||
<small>
|
||||
Your PB is the combination of your best score and your best lamp.
|
||||
Read more{" "}
|
||||
<ExternalLink href="https://tachi.readthedocs.io/en/latest/user/pbs-scores/">
|
||||
{" "}
|
||||
here.
|
||||
</ExternalLink>
|
||||
</small>
|
||||
<PBNote />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -260,74 +138,8 @@ function DocumentDisplay({
|
||||
playtype="SP"
|
||||
judgements={currentDoc.scoreData.judgements}
|
||||
/>
|
||||
{/* @ts-expect-error temp */}
|
||||
<ModsTable view={view} doc={currentDoc} />
|
||||
{IsScore(currentDoc) && <ModsTable score={currentDoc} />}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ModsTable({
|
||||
view,
|
||||
doc,
|
||||
}: {
|
||||
view: "pb" | "lampPB" | "scorePB" | "bpPB";
|
||||
doc: PBScoreDocument<"iidx:SP"> | ScoreDocument<"iidx:SP">;
|
||||
}) {
|
||||
if (view === "pb") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sc = doc as ScoreDocument<"iidx:SP">;
|
||||
|
||||
if (!sc.scoreMeta.assist && !sc.scoreMeta.random) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<MiniTable className="text-center table-sm" headers={["Mods"]} colSpan={2}>
|
||||
{sc.scoreMeta.random && (
|
||||
<tr>
|
||||
<td>Note</td>
|
||||
<td>{sc.scoreMeta.random}</td>
|
||||
</tr>
|
||||
)}
|
||||
{sc.scoreMeta.assist && (
|
||||
<tr>
|
||||
<td>Assist</td>
|
||||
<td>{sc.scoreMeta.assist}</td>
|
||||
</tr>
|
||||
)}
|
||||
</MiniTable>
|
||||
);
|
||||
}
|
||||
|
||||
function GraphComponent({ type, values }: { type: LampTypes; values: (number | null)[] }) {
|
||||
return (
|
||||
<IIDXLampChart
|
||||
height="200px"
|
||||
mobileHeight="175px"
|
||||
type={type}
|
||||
data={[
|
||||
{
|
||||
id: type,
|
||||
data: values.map((e, i) => ({ x: i, y: e ?? 0 })),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function LampToKey(lamp: Lamps["iidx:SP"]): LampTypes {
|
||||
if (lamp === "CLEAR") {
|
||||
return "NORMAL";
|
||||
} else if (lamp === "EASY CLEAR") {
|
||||
return "EASY";
|
||||
} else if (lamp === "HARD CLEAR") {
|
||||
return "HARD";
|
||||
} else if (lamp === "EX HARD CLEAR") {
|
||||
return "EX_HARD";
|
||||
}
|
||||
|
||||
return "NORMAL";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import Icon from "components/util/Icon";
|
||||
import Loading from "components/util/Loading";
|
||||
import SelectButton from "components/util/SelectButton";
|
||||
import React, { useState } from "react";
|
||||
import { UGPTChartPBComposition } from "types/api-returns";
|
||||
import { GamePT } from "types/react";
|
||||
import { APIFetchV1 } from "util/api";
|
||||
import DropdownStructure from "./components/DropdownStructure";
|
||||
import { PublicUserDocument, ChartDocument, ScoreDocument } from "tachi-common";
|
||||
import { useQuery } from "react-query";
|
||||
import { IsScore } from "util/asserts";
|
||||
import { IIDXGraphsComponent, ScoreInfo, ModsTable } from "./components/IIDXScoreDropdownParts";
|
||||
import JudgementTable from "./components/JudgementTable";
|
||||
import PBNote from "./components/PBNote";
|
||||
|
||||
export default function IIDXScoreDropdown({
|
||||
thisScore,
|
||||
game,
|
||||
playtype,
|
||||
reqUser,
|
||||
chart,
|
||||
}: {
|
||||
thisScore: ScoreDocument<"iidx:SP" | "iidx:DP">;
|
||||
reqUser: PublicUserDocument;
|
||||
chart: ChartDocument<"iidx:SP">;
|
||||
} & GamePT) {
|
||||
const [view, setView] = useState<"vsPB" | "moreInfo" | "history">("moreInfo");
|
||||
|
||||
const { isLoading, error, data } = useQuery(
|
||||
`/users/${reqUser.id}/games/${game}/${playtype}/pbs/${chart.chartID}?getComposition=true`,
|
||||
async () => {
|
||||
const res = await APIFetchV1<UGPTChartPBComposition<"iidx:SP">>(
|
||||
`/users/${reqUser.id}/games/${game}/${playtype}/pbs/${chart.chartID}?getComposition=true`
|
||||
);
|
||||
|
||||
if (!res.success) {
|
||||
throw new Error(res.description);
|
||||
}
|
||||
|
||||
return res.body;
|
||||
}
|
||||
);
|
||||
|
||||
if (error) {
|
||||
return <>An error has occured. Nice.</>;
|
||||
}
|
||||
|
||||
if (isLoading || !data) {
|
||||
return (
|
||||
<div style={{ height: "200px" }} className="d-flex align-items-center">
|
||||
<Loading />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
let content = null;
|
||||
|
||||
thisScore.comment = "THIS IS AN EXAMPLE COMMENT.";
|
||||
|
||||
if (view === "moreInfo") {
|
||||
content = (
|
||||
<>
|
||||
<div className="col-9">
|
||||
<div className="row">
|
||||
<IIDXGraphsComponent score={thisScore} />
|
||||
{thisScore.comment && (
|
||||
<div className="col-12">
|
||||
<em>"{thisScore.comment}"</em>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-3 align-self-center">
|
||||
<JudgementTable
|
||||
game="iidx"
|
||||
playtype="SP"
|
||||
judgements={thisScore.scoreData.judgements}
|
||||
/>
|
||||
{IsScore(thisScore) && <ModsTable score={thisScore} />}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownStructure
|
||||
buttons={
|
||||
<>
|
||||
<SelectButton setValue={setView} value={view} id="moreInfo">
|
||||
<Icon type="chart-bar" />
|
||||
This Score
|
||||
</SelectButton>
|
||||
<SelectButton setValue={setView} value={view} id="vsPB">
|
||||
<Icon type="balance-scale-right" />
|
||||
Versus PB
|
||||
</SelectButton>
|
||||
<SelectButton setValue={setView} value={view} id="history" disabled>
|
||||
<Icon type="history" />
|
||||
Play History
|
||||
</SelectButton>
|
||||
</>
|
||||
}
|
||||
>
|
||||
{content}
|
||||
</DropdownStructure>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from "react";
|
||||
import { JustChildren } from "types/react";
|
||||
|
||||
export default function DropdownStructure({
|
||||
buttons,
|
||||
children,
|
||||
}: {
|
||||
buttons: React.ReactNode;
|
||||
} & JustChildren) {
|
||||
return (
|
||||
<div className="p-2">
|
||||
<div className="row h-100 mb-0 align-items-center">
|
||||
<div className="col-3 col-xl-2">
|
||||
<div className="btn-group-vertical">{buttons}</div>
|
||||
</div>
|
||||
|
||||
<div className="col-9 col-xl-10">
|
||||
<div className="row mb-0">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
import DeltaCell from "components/tables/cells/DeltaCell";
|
||||
import IIDXLampCell from "components/tables/cells/IIDXLampCell";
|
||||
import ScoreCell from "components/tables/cells/ScoreCell";
|
||||
import TimestampCell from "components/tables/cells/TimestampCell";
|
||||
import SelectNav from "components/util/SelectNav";
|
||||
import React, { useState } from "react";
|
||||
import { ScoreDocument, PBScoreDocument, Lamps } from "tachi-common";
|
||||
import { Nav } from ".pnpm/react-bootstrap@1.0.1_react-dom@16.12.0+react@17.0.2/node_modules/react-bootstrap";
|
||||
import IIDXLampChart from "components/charts/IIDXLampChart";
|
||||
import MiniTable from "components/tables/components/MiniTable";
|
||||
|
||||
export function ScoreInfo({ score }: { score: ScoreDocument<"iidx:SP" | "iidx:DP"> }) {
|
||||
return (
|
||||
<div className="col-12">
|
||||
<table className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td colSpan={100}>Score Info</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<ScoreCell score={score} game="iidx" playtype="SP" />
|
||||
<DeltaCell
|
||||
game="iidx"
|
||||
playtype="SP"
|
||||
score={score.scoreData.score}
|
||||
percent={score.scoreData.percent}
|
||||
grade={score.scoreData.grade}
|
||||
/>
|
||||
<IIDXLampCell sc={score} />
|
||||
<TimestampCell time={score.timeAchieved} />
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ModsTable({ score }: { score: ScoreDocument<"iidx:SP" | "iidx:DP"> }) {
|
||||
if (!score.scoreMeta.assist && !score.scoreMeta.random) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<MiniTable className="text-center table-sm" headers={["Mods"]} colSpan={2}>
|
||||
{score.scoreMeta.random && (
|
||||
<tr>
|
||||
<td>Note</td>
|
||||
<td>
|
||||
{Array.isArray(score.scoreMeta.random)
|
||||
? score.scoreMeta.random.join(" | ")
|
||||
: score.scoreMeta.random}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{score.scoreMeta.assist && (
|
||||
<tr>
|
||||
<td>Assist</td>
|
||||
<td>{score.scoreMeta.assist}</td>
|
||||
</tr>
|
||||
)}
|
||||
</MiniTable>
|
||||
);
|
||||
}
|
||||
|
||||
type LampTypes = "NORMAL" | "EASY" | "HARD" | "EX_HARD";
|
||||
|
||||
export function IIDXGraphsComponent({
|
||||
score,
|
||||
}: {
|
||||
score: ScoreDocument<"iidx:SP" | "iidx:DP"> | PBScoreDocument<"iidx:SP" | "iidx:DP">;
|
||||
}) {
|
||||
const [lamp, setLamp] = useState(LampToKey(score.scoreData.lamp));
|
||||
|
||||
let gaugeStatus: "none" | "single" | "gsm" = "none";
|
||||
|
||||
if (score.scoreData.hitMeta.gsm) {
|
||||
gaugeStatus = "gsm";
|
||||
} else if (score.scoreData.hitMeta.gaugeHistory) {
|
||||
gaugeStatus = "single";
|
||||
}
|
||||
|
||||
const shouldDisable = (r: LampTypes) => {
|
||||
if (gaugeStatus === "gsm") {
|
||||
return false;
|
||||
} else if (gaugeStatus === "single") {
|
||||
return r !== LampToKey(score.scoreData.lamp);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="col-12 d-flex justify-content-center">
|
||||
<Nav variant="pills">
|
||||
<SelectNav
|
||||
id="EASY"
|
||||
value={lamp}
|
||||
setValue={setLamp}
|
||||
disabled={shouldDisable("EASY")}
|
||||
>
|
||||
Easy
|
||||
</SelectNav>
|
||||
<SelectNav
|
||||
id="NORMAL"
|
||||
value={lamp}
|
||||
setValue={setLamp}
|
||||
disabled={shouldDisable("NORMAL")}
|
||||
>
|
||||
Normal
|
||||
</SelectNav>
|
||||
<SelectNav
|
||||
id="HARD"
|
||||
value={lamp}
|
||||
setValue={setLamp}
|
||||
disabled={shouldDisable("HARD")}
|
||||
>
|
||||
Hard
|
||||
</SelectNav>
|
||||
<SelectNav
|
||||
id="EX_HARD"
|
||||
value={lamp}
|
||||
setValue={setLamp}
|
||||
disabled={shouldDisable("EX_HARD")}
|
||||
>
|
||||
Ex Hard
|
||||
</SelectNav>
|
||||
</Nav>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
{gaugeStatus === "gsm" ? (
|
||||
<GraphComponent type={lamp} values={score.scoreData.hitMeta.gsm![lamp]} />
|
||||
) : gaugeStatus === "single" ? (
|
||||
<GraphComponent type={lamp} values={score.scoreData.hitMeta.gaugeHistory!} />
|
||||
) : (
|
||||
<div
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
style={{ height: "200px" }}
|
||||
>
|
||||
<span className="text-muted">No gauge data :(</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function GraphComponent({ type, values }: { type: LampTypes; values: (number | null)[] }) {
|
||||
return (
|
||||
<IIDXLampChart
|
||||
height="200px"
|
||||
mobileHeight="175px"
|
||||
type={type}
|
||||
data={[
|
||||
{
|
||||
id: type,
|
||||
data: values.map((e, i) => ({ x: i, y: e ?? 0 })),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function LampToKey(lamp: Lamps["iidx:SP"]): LampTypes {
|
||||
if (lamp === "CLEAR") {
|
||||
return "NORMAL";
|
||||
} else if (lamp === "EASY CLEAR") {
|
||||
return "EASY";
|
||||
} else if (lamp === "HARD CLEAR") {
|
||||
return "HARD";
|
||||
} else if (lamp === "EX HARD CLEAR") {
|
||||
return "EX_HARD";
|
||||
}
|
||||
|
||||
return "NORMAL";
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import ExternalLink from "components/util/ExternalLink";
|
||||
import React from "react";
|
||||
|
||||
export default function PBNote() {
|
||||
return (
|
||||
<small>
|
||||
Your PB is the combination of your best score and your best lamp. Read more{" "}
|
||||
<ExternalLink href="https://tachi.readthedocs.io/en/latest/user/pbs-scores/">
|
||||
{" "}
|
||||
here.
|
||||
</ExternalLink>
|
||||
</small>
|
||||
);
|
||||
}
|
||||
@@ -6,7 +6,12 @@ import BPICell from "../cells/BPICell";
|
||||
import { NumericSOV, StrSOV } from "util/sorts";
|
||||
import SelectableRating from "../components/SelectableRating";
|
||||
import { ScoreDataset } from "types/tables";
|
||||
import { GetGamePTConfig, integer, ScoreCalculatedDataLookup } from "tachi-common";
|
||||
import {
|
||||
GetGamePTConfig,
|
||||
integer,
|
||||
ScoreCalculatedDataLookup,
|
||||
PublicUserDocument,
|
||||
} from "tachi-common";
|
||||
import TachiTable, { ZTableTHProps } from "../components/TachiTable";
|
||||
import DifficultyCell from "../cells/DifficultyCell";
|
||||
import ScoreCell from "../cells/ScoreCell";
|
||||
@@ -14,11 +19,15 @@ import DeltaCell from "../cells/DeltaCell";
|
||||
import { HumanFriendlyStrToGradeIndex, HumanFriendlyStrToLampIndex } from "util/str-to-num";
|
||||
import { nanoid } from "nanoid";
|
||||
import IIDXLampCell from "../cells/IIDXLampCell";
|
||||
import DropdownRow from "../components/DropdownRow";
|
||||
import IIDXScoreDropdown from "../pbs/dropdowns/IIDXScoreDropdown";
|
||||
|
||||
export default function IIDXScoreTable({
|
||||
reqUser,
|
||||
dataset,
|
||||
pageLen,
|
||||
}: {
|
||||
reqUser: PublicUserDocument;
|
||||
dataset: ScoreDataset<"iidx:SP">;
|
||||
pageLen?: integer;
|
||||
}) {
|
||||
@@ -73,7 +82,17 @@ export default function IIDXScoreTable({
|
||||
},
|
||||
}}
|
||||
rowFunction={sc => (
|
||||
<tr key={sc.chartID}>
|
||||
<DropdownRow
|
||||
dropdown={
|
||||
<IIDXScoreDropdown
|
||||
chart={sc.__related.chart}
|
||||
game="iidx"
|
||||
playtype={sc.playtype}
|
||||
reqUser={reqUser}
|
||||
thisScore={sc}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<DifficultyCell chart={sc.__related.chart} game={"iidx"} />
|
||||
<TitleCell song={sc.__related.song} chart={sc.__related.chart} game="iidx" />
|
||||
<ScoreCell score={sc} game="iidx" playtype="SP" />
|
||||
@@ -95,7 +114,7 @@ export default function IIDXScoreTable({
|
||||
</td>
|
||||
)}
|
||||
<TimestampCell time={sc.timeAchieved} />
|
||||
</tr>
|
||||
</DropdownRow>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user