This commit is contained in:
zkldi
2021-08-04 01:16:53 +01:00
parent cea6035b1b
commit 35dead4ec4
10 changed files with 365 additions and 32 deletions
+74 -29
View File
@@ -143,7 +143,7 @@ dependencies:
resolve: 1.12.0
resolve-url-loader: 3.1.0
socicon: 3.0.5
tachi-common: github.com/zkldi/tachi-common/353c7dcee5ca01dc25324cbb0e8404e5bf80ce1d_typescript@4.3.5
tachi-common: github.com/zkldi/tachi-common/3cf854daeeec2a40f96db1c31a27d5c03c658a55_typescript@4.3.5
devDependencies:
'@types/humanize-duration': 3.25.1
@@ -215,14 +215,14 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.14.5
'@babel/generator': 7.14.8
'@babel/generator': 7.14.9
'@babel/helper-compilation-targets': 7.14.5_@babel+core@7.14.8
'@babel/helper-module-transforms': 7.14.8
'@babel/helpers': 7.14.8
'@babel/parser': 7.14.8
'@babel/parser': 7.14.9
'@babel/template': 7.14.5
'@babel/traverse': 7.14.8
'@babel/types': 7.14.8
'@babel/traverse': 7.14.9
'@babel/types': 7.14.9
convert-source-map: 1.8.0
debug: 4.3.2
gensync: 1.0.0-beta.2
@@ -297,6 +297,15 @@ packages:
source-map: 0.5.7
dev: false
/@babel/generator/7.14.9:
resolution: {integrity: sha512-4yoHbhDYzFa0GLfCzLp5GxH7vPPMAHdZjyE7M/OajM9037zhx0rf+iNsJwp4PT0MSFpwjG7BsHEbPkBQpZ6cYA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.14.9
jsesc: 2.5.2
source-map: 0.5.7
dev: false
/@babel/helper-annotate-as-pure/7.14.5:
resolution: {integrity: sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==}
engines: {node: '>=6.9.0'}
@@ -493,10 +502,10 @@ packages:
'@babel/helper-replace-supers': 7.14.5
'@babel/helper-simple-access': 7.14.8
'@babel/helper-split-export-declaration': 7.14.5
'@babel/helper-validator-identifier': 7.14.8
'@babel/helper-validator-identifier': 7.14.9
'@babel/template': 7.14.5
'@babel/traverse': 7.14.8
'@babel/types': 7.14.8
'@babel/traverse': 7.14.9
'@babel/types': 7.14.9
transitivePeerDependencies:
- supports-color
dev: false
@@ -547,7 +556,7 @@ packages:
resolution: {integrity: sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.14.8
'@babel/types': 7.14.9
dev: false
/@babel/helper-skip-transparent-expression-wrappers/7.14.5:
@@ -573,6 +582,11 @@ packages:
resolution: {integrity: sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==}
engines: {node: '>=6.9.0'}
/@babel/helper-validator-identifier/7.14.9:
resolution: {integrity: sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==}
engines: {node: '>=6.9.0'}
dev: false
/@babel/helper-validator-option/7.14.5:
resolution: {integrity: sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==}
engines: {node: '>=6.9.0'}
@@ -606,8 +620,8 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/template': 7.14.5
'@babel/traverse': 7.14.8
'@babel/types': 7.14.8
'@babel/traverse': 7.14.9
'@babel/types': 7.14.9
transitivePeerDependencies:
- supports-color
dev: false
@@ -632,6 +646,12 @@ packages:
hasBin: true
dev: false
/@babel/parser/7.14.9:
resolution: {integrity: sha512-RdUTOseXJ8POjjOeEBEvNMIZU/nm4yu2rufRkcibzkkg7DmQvXU8v3M4Xk9G7uuI86CDGkKcuDWgioqZm+mScQ==}
engines: {node: '>=6.0.0'}
hasBin: true
dev: false
/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.14.5_@babel+core@7.6.0:
resolution: {integrity: sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ==}
engines: {node: '>=6.9.0'}
@@ -1879,20 +1899,6 @@ packages:
'@babel/helper-plugin-utils': 7.14.5
dev: false
/@babel/plugin-transform-react-jsx/7.14.5_@babel+core@7.14.8:
resolution: {integrity: sha512-7RylxNeDnxc1OleDm0F5Q/BSL+whYRbOAR+bwgCxIr0L32v7UFh/pz1DLMZideAUxKT6eMoS2zQH6fyODLEi8Q==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.14.8
'@babel/helper-annotate-as-pure': 7.14.5
'@babel/helper-module-imports': 7.14.5
'@babel/helper-plugin-utils': 7.14.5
'@babel/plugin-syntax-jsx': 7.14.5_@babel+core@7.14.8
'@babel/types': 7.14.8
dev: false
/@babel/plugin-transform-react-jsx/7.14.5_@babel+core@7.6.0:
resolution: {integrity: sha512-7RylxNeDnxc1OleDm0F5Q/BSL+whYRbOAR+bwgCxIr0L32v7UFh/pz1DLMZideAUxKT6eMoS2zQH6fyODLEi8Q==}
engines: {node: '>=6.9.0'}
@@ -1921,6 +1927,20 @@ packages:
'@babel/types': 7.14.8
dev: false
/@babel/plugin-transform-react-jsx/7.14.9_@babel+core@7.14.8:
resolution: {integrity: sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.14.8
'@babel/helper-annotate-as-pure': 7.14.5
'@babel/helper-module-imports': 7.14.5
'@babel/helper-plugin-utils': 7.14.5
'@babel/plugin-syntax-jsx': 7.14.5_@babel+core@7.14.8
'@babel/types': 7.14.9
dev: false
/@babel/plugin-transform-react-pure-annotations/7.14.5_@babel+core@7.6.0:
resolution: {integrity: sha512-3X4HpBJimNxW4rhUy/SONPyNQHp5YRr0HhJdT2OH1BRp0of7u3Dkirc7x9FRJMKMqTBI079VZ1hzv7Ouuz///g==}
engines: {node: '>=6.9.0'}
@@ -2408,6 +2428,23 @@ packages:
- supports-color
dev: false
/@babel/traverse/7.14.9:
resolution: {integrity: sha512-bldh6dtB49L8q9bUyB7bC20UKgU+EFDwKJylwl234Kv+ySZeMD31Xeht6URyueQ6LrRRpF2tmkfcZooZR9/e8g==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.14.5
'@babel/generator': 7.14.9
'@babel/helper-function-name': 7.14.5
'@babel/helper-hoist-variables': 7.14.5
'@babel/helper-split-export-declaration': 7.14.5
'@babel/parser': 7.14.9
'@babel/types': 7.14.9
debug: 4.3.2
globals: 11.12.0
transitivePeerDependencies:
- supports-color
dev: false
/@babel/types/7.14.5:
resolution: {integrity: sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==}
engines: {node: '>=6.9.0'}
@@ -2424,6 +2461,14 @@ packages:
to-fast-properties: 2.0.0
dev: false
/@babel/types/7.14.9:
resolution: {integrity: sha512-u0bLTnv3DFHeaQLYzb7oRJ1JHr1sv/SYDM7JSqHFFLwXG1wTZRughxFI5NCP8qBEo1rVVsn7Yg2Lvw49nne/Ow==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.14.9
to-fast-properties: 2.0.0
dev: false
/@csstools/convert-colors/1.4.0:
resolution: {integrity: sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==}
engines: {node: '>=4.0.0'}
@@ -7162,7 +7207,7 @@ packages:
'@babel/core': 7.14.8
'@babel/plugin-proposal-object-rest-spread': 7.14.7_@babel+core@7.14.8
'@babel/plugin-transform-destructuring': 7.14.7_@babel+core@7.14.8
'@babel/plugin-transform-react-jsx': 7.14.5_@babel+core@7.14.8
'@babel/plugin-transform-react-jsx': 7.14.9_@babel+core@7.14.8
caller-path: 2.0.0
find-cache-dir: 3.3.1
make-dir: 3.1.0
@@ -12799,9 +12844,9 @@ packages:
yargs-parser: 18.1.3
dev: false
github.com/zkldi/tachi-common/353c7dcee5ca01dc25324cbb0e8404e5bf80ce1d_typescript@4.3.5:
resolution: {tarball: https://codeload.github.com/zkldi/tachi-common/tar.gz/353c7dcee5ca01dc25324cbb0e8404e5bf80ce1d}
id: github.com/zkldi/tachi-common/353c7dcee5ca01dc25324cbb0e8404e5bf80ce1d
github.com/zkldi/tachi-common/3cf854daeeec2a40f96db1c31a27d5c03c658a55_typescript@4.3.5:
resolution: {tarball: https://codeload.github.com/zkldi/tachi-common/tar.gz/3cf854daeeec2a40f96db1c31a27d5c03c658a55}
id: github.com/zkldi/tachi-common/3cf854daeeec2a40f96db1c31a27d5c03c658a55
name: tachi-common
version: 0.1.0
dependencies:
+1
View File
@@ -57,6 +57,7 @@ export default function LoginPage() {
setTimeout(() => {
setUser(userRJ.body);
localStorage.setItem("isLoggedIn", "true");
history.goBack();
}, 500);
+1
View File
@@ -77,6 +77,7 @@ export default function RegisterPage() {
setTimeout(() => {
setUser(rj.body);
localStorage.setItem("isLoggedIn", "true");
history.goBack();
}, 500);
@@ -0,0 +1,63 @@
import React from "react";
import { ResponsiveLine, Serie } from "@nivo/line";
import { TACHI_CHART_THEME } from "util/constants/chart-theme";
import { ColourConfig } from "lib/config";
export default function IIDXLampChart({
width = "100%",
height = "100%",
mobileHeight = "100%",
mobileWidth = width,
data,
axisBottom,
axisLeft,
curve,
...props
}: {
mobileHeight?: number | string;
mobileWidth?: number | string;
width?: number | string;
height?: number | string;
data: Serie[];
} & ResponsiveLine["props"]) {
return (
<>
<div className="d-block d-md-none" style={{ height: mobileHeight, width: mobileWidth }}>
<ResponsiveLine
data={data}
margin={{ top: 30, bottom: 50, left: 30, right: 0 }}
axisBottom={axisBottom}
motionConfig="stiff"
crosshairType="x"
yScale={{ type: "linear", min: 0, max: 100 }}
axisLeft={axisLeft}
enablePoints={false}
colors={[ColourConfig.primary]}
useMesh={true}
theme={TACHI_CHART_THEME}
curve={curve}
legends={[]}
{...props}
/>
</div>
<div className="d-none d-md-block" style={{ height, width }}>
<ResponsiveLine
data={data}
margin={{ top: 30, bottom: 50, left: 30, right: 0 }}
axisBottom={axisBottom}
motionConfig="stiff"
crosshairType="x"
yScale={{ type: "linear", min: 0, max: 100 }}
axisLeft={axisLeft}
enablePoints={false}
colors={[ColourConfig.primary]}
useMesh={true}
theme={TACHI_CHART_THEME}
curve={curve}
legends={[]}
{...props}
/>
</div>
</>
);
}
@@ -89,6 +89,7 @@ export function UserProfileDropdown({ user }: { user: PublicUserDocument }) {
toast.success("Logged out.");
setTimeout(() => {
setUser(null);
localStorage.removeItem("isLoggedIn");
}, 500);
}
}}
@@ -14,6 +14,11 @@ export function LoadingScreen({ children }: JustChildren) {
const { setUser } = useContext(UserContext);
useEffect(() => {
if (!localStorage.getItem("isLoggedIn")) {
setLoading(false);
return;
}
const timeout = setTimeout(
() =>
setBroke(
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useEffect, useMemo, useState } from "react";
import { Collapse } from "react-bootstrap";
import { JustChildren } from "types/react";
@@ -7,13 +7,32 @@ export default function DropdownRow({
dropdown,
}: { dropdown: React.ReactNode } & JustChildren) {
const [showDropdown, setShowDropdown] = useState(false);
const [renderDropdown, setRenderDropdown] = useState(false);
useEffect(() => {
if (!renderDropdown && showDropdown) {
setRenderDropdown(true);
} else if (renderDropdown && !showDropdown) {
setTimeout(() => {
if (renderDropdown && !showDropdown) {
setRenderDropdown(false);
}
}, 300);
}
}, [showDropdown]);
return (
<>
<tr onClick={() => setShowDropdown(!showDropdown)}>{children}</tr>
<tr className="expandable-pseudo-row">
<td colSpan={100}>
<Collapse in={showDropdown}>
<div className="tr-dropdown-container">{dropdown}</div>
{renderDropdown ? (
<div className="tr-dropdown-container">{dropdown}</div>
) : (
<div></div>
)}
</Collapse>
</td>
</tr>
@@ -16,6 +16,7 @@ import DeltaCell from "../cells/DeltaCell";
import { HumanFriendlyStrToGradeIndex, HumanFriendlyStrToLampIndex } from "util/str-to-num";
import { nanoid } from "nanoid";
import DropdownRow from "../components/DropdownRow";
import IIDXPBDropdown from "./dropdowns/IIDXPBDropdown";
export default function IIDXPBTable({
dataset,
@@ -83,7 +84,7 @@ export default function IIDXPBTable({
defaultSortMode={indexCol ? "#" : undefined}
rowFunction={pb => (
<DropdownRow
dropdown={<div style={{ height: "200px" }}>{pb.chartID}</div>}
dropdown={<IIDXPBDropdown pb={pb} game={"iidx"} playtype={"SP"} />}
key={pb.chartID}
>
{indexCol && <IndexCell index={pb.__related.index} />}
@@ -0,0 +1,174 @@
import IIDXLampChart from "components/charts/IIDXLampChart";
import MiniTable from "components/tables/components/MiniTable";
import Icon from "components/util/Icon";
import SelectButton from "components/util/SelectButton";
import { nanoid } from "nanoid";
import React, { useMemo, useState } from "react";
import { Nav, Tab, Tabs } from "react-bootstrap";
import { GetGamePTConfig, Lamps, PBScoreDocument } from "tachi-common";
import { GamePT } from "types/react";
import JudgementTable from "./components/JudgementTable";
export default function IIDXPBDropdown({
pb,
game,
playtype,
}: { pb: PBScoreDocument<"iidx:SP" | "iidx:DP"> } & GamePT) {
const [view, setView] = useState<"pb" | "scorePB" | "lampPB" | "bpPB" | "history">("pb");
const currentDoc = useMemo(() => {
if (view === "pb") {
return pb;
}
return pb;
}, [view]);
let gaugeStatus: "none" | "single" | "gsm" = "none";
if (currentDoc.scoreData.hitMeta.gsm) {
gaugeStatus = "gsm";
} else if (currentDoc.scoreData.hitMeta.gaugeHistory) {
gaugeStatus = "single";
}
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">
<Icon type="history" />
Play History
</SelectButton>
</div>
</div>
<div className="col-9 col-xl-10">
<div className="row mb-0">
<div className="col-9">
{gaugeStatus === "none" ? (
<div className="d-flex h-100 align-items-center justify-content-center">
<span className="text-muted">No gauge data :(</span>
</div>
) : (
<div className="d-flex justify-content-center">
<Tab.Container
defaultActiveKey={LampToKey(pb.scoreData.lamp)}
id={nanoid()}
>
<div className="col-12">
<Nav>
{gaugeStatus === "gsm" ? (
<>
<Nav.Link
eventKey="easy"
title="Easy"
></Nav.Link>
<Nav.Link
eventKey="normal"
title="Normal"
></Nav.Link>
<Nav.Link
eventKey="hard"
title="Hard"
></Nav.Link>
<Nav.Link eventKey="exhard" title="Ex Hard">
<GraphComponent
type="exhard"
values={
currentDoc.scoreData.hitMeta
.gsm!.EX_HARD
}
/>
</Nav.Link>
</>
) : (
<Nav.Item>
<Nav.Link
eventKey={LampToKey(pb.scoreData.lamp)}
>
{LampToName(pb.scoreData.lamp)}
</Nav.Link>
</Nav.Item>
)}
</Nav>
<GraphComponent
type="exhard"
values={currentDoc.scoreData.hitMeta.gaugeHistory!}
/>
</div>
</Tab.Container>
</div>
)}
</div>
<div className="col-3">
<JudgementTable
game={"iidx"}
playtype="SP"
judgements={currentDoc.scoreData.judgements}
/>
</div>
</div>
</div>
</div>
</div>
);
}
function GraphComponent({ type, values }: { type: LampTypes; values: (number | null)[] }) {
console.log(values);
return (
<IIDXLampChart
data={[
{
id: type,
data: values.map((e, i) => ({ x: i, y: e ?? 0 })),
},
]}
/>
);
}
type LampTypes = "normal" | "easy" | "hard" | "exhard";
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 "exhard";
}
return "normal";
}
function LampToName(lamp: Lamps["iidx:SP"]) {
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,23 @@
import MiniTable from "components/tables/components/MiniTable";
import React from "react";
import { GetGamePTConfig, ScoreDocument } from "tachi-common";
import { GamePT } from "types/react";
export default function JudgementTable({
game,
playtype,
judgements,
}: { judgements: ScoreDocument["scoreData"]["judgements"] } & GamePT) {
const gptConfig = GetGamePTConfig(game, playtype);
return (
<MiniTable className="text-center table-sm" headers={["Judgements"]} colSpan={2}>
{gptConfig.judgements.map(j => (
<tr key={j}>
<td>{j.toUpperCase()}</td>
<td>{judgements[j] ?? "No Data."}</td>
</tr>
))}
</MiniTable>
);
}