feat: comparisons in the folder and general touchups

This commit is contained in:
zkldi
2022-11-01 23:07:12 +00:00
parent 1d2f94a8aa
commit ff4236f4e1
4 changed files with 172 additions and 13 deletions
@@ -11,13 +11,14 @@ import useLUGPTSettings from "components/util/useLUGPTSettings";
import React, { useContext, useEffect, useMemo, useState } from "react";
import { Button, Col, Form, Row } from "react-bootstrap";
import { Link } from "react-router-dom";
import { FolderDocument, GetGamePTConfig, PublicUserDocument } from "tachi-common";
import { COLOUR_SET, FolderDocument, GetGamePTConfig, PublicUserDocument } from "tachi-common";
import { UGPTFolderReturns, UGPTStatsReturn } from "types/api-returns";
import { GamePT } from "types/react";
import { ComparePBsDataset } from "types/tables";
import UserSelectModal from "components/util/modal/UserSelectModal";
import UserIcon from "components/util/UserIcon";
import { UserContext } from "context/UserContext";
import MiniTable from "components/tables/components/MiniTable";
export default function RivalCompareFolderPage({
reqUser,
@@ -41,11 +42,11 @@ export default function RivalCompareFolderPage({
// [settings?.rivals.join(",")]
);
if (!data) {
if (!data && !error) {
return <Loading />;
}
let suggestUsers = data;
let suggestUsers = data ?? [];
// if the user viewing this page is logged in and *is not*
// the person this page is for
@@ -57,7 +58,7 @@ export default function RivalCompareFolderPage({
return (
<div>
<Card header="Pick a user to compare against...">
{suggestUsers && (
{suggestUsers.length > 0 && (
<>
<Col xs={12} className="d-flex justify-content-center flex-wrap">
{suggestUsers.map((e) => (
@@ -90,10 +91,11 @@ export default function RivalCompareFolderPage({
excludeMsg="Can't pick the same user!"
/>
<Button
className={suggestUsers.length === 0 ? "d-flex mx-auto" : ""}
variant={selectedUser ? "secondary" : "primary"}
onClick={() => setShow(true)}
>
Pick Other User
Pick{suggestUsers.length > 0 ? " Other" : ""} User
</Button>
</Card>
{selectedUser !== null && folder !== null && (
@@ -180,12 +182,20 @@ function FolderCompare({
<Row>
<UserCard username={reqUser.username} game={game} playtype={playtype} />
<UserCard username={withUser.username} game={game} playtype={playtype} />
<Col xs={12}>
<Divider />
</Col>
<CompareCard
dataset={dataset}
baseUsername={reqUser.username}
otherUsername={withUser.username}
/>
<Col xs={12}>
<Divider />
<Form.Check
checked={shouldIncludeNotPlayed}
onChange={() => setShouldIncludeNotPlayed(!shouldIncludeNotPlayed)}
label="Include charts you haven't both played?"
label="Include charts without plays?"
/>
{gptConfig.supportsESD && (
<Form.Check
@@ -242,3 +252,121 @@ function UserCard({ username, game, playtype }: { username: string } & GamePT) {
</Col>
);
}
function CompareCard({
dataset,
baseUsername,
otherUsername,
}: {
dataset: ComparePBsDataset;
baseUsername: string;
otherUsername: string;
}) {
// this code sucks
let scoreWin = 0;
let scoreDraw = 0;
let scoreLoss = 0;
let lampWin = 0;
let lampDraw = 0;
let lampLoss = 0;
for (const d of dataset) {
if (!d.compare && !d.base) {
scoreDraw++;
lampDraw++;
continue;
}
if (!d.compare) {
scoreWin++;
lampWin++;
continue;
}
if (!d.base) {
scoreLoss++;
lampLoss++;
continue;
}
if (d.base.scoreData.percent > d.compare.scoreData.percent) {
scoreWin++;
} else if (d.base.scoreData.percent < d.compare.scoreData.percent) {
scoreLoss++;
} else {
scoreDraw++;
}
if (d.base.scoreData.lampIndex > d.compare.scoreData.lampIndex) {
lampWin++;
} else if (d.base.scoreData.lampIndex < d.compare.scoreData.lampIndex) {
lampLoss++;
} else {
lampDraw++;
}
}
return (
<Col xs={12}>
<Card>
<Row>
<Col xs={12} lg={6}>
<MiniTable headers={["Score Win/Loss"]} colSpan={23}>
<tr>
<td>{baseUsername} Win</td>
<td style={{ color: COLOUR_SET.green }}>{scoreWin}</td>
<td style={{ color: COLOUR_SET.green }}>
{((100 * scoreWin) / dataset.length).toFixed(2)}%
</td>
</tr>
<tr>
<td>Draw</td>
<td style={{ color: COLOUR_SET.gold }}>{scoreDraw}</td>
<td style={{ color: COLOUR_SET.gold }}>
{((100 * scoreDraw) / dataset.length).toFixed(2)}%
</td>
</tr>
<tr>
<td>{otherUsername} Win</td>
<td style={{ color: COLOUR_SET.red }}>{scoreLoss}</td>
<td style={{ color: COLOUR_SET.red }}>
{((100 * scoreLoss) / dataset.length).toFixed(2)}%
</td>
</tr>
</MiniTable>
</Col>
<Col xs={12} lg={6}>
<MiniTable headers={["Lamp Win/Loss"]} colSpan={23}>
<tr>
<td>{baseUsername} Win</td>
<td style={{ color: COLOUR_SET.green }}>{lampWin}</td>
<td style={{ color: COLOUR_SET.green }}>
{((100 * lampWin) / dataset.length).toFixed(2)}%
</td>
</tr>
<tr>
<td>Draw</td>
<td style={{ color: COLOUR_SET.gold }}>{lampDraw}</td>
<td style={{ color: COLOUR_SET.gold }}>
{((100 * lampDraw) / dataset.length).toFixed(2)}%
</td>
</tr>
<tr>
<td>{otherUsername} Loss</td>
<td style={{ color: COLOUR_SET.red }}>{lampLoss}</td>
<td style={{ color: COLOUR_SET.red }}>
{((100 * lampLoss) / dataset.length).toFixed(2)}%
</td>
</tr>
</MiniTable>
</Col>
</Row>
</Card>
</Col>
);
}
@@ -35,12 +35,12 @@ export default function PBCompareCell({
}
let scoreRenderFn = (k: number) => k.toString();
let shouldShowPercent = false;
switch (game) {
case "chunithm":
case "ddr":
case "gitadora":
case "jubeat":
case "maimai":
case "usc":
case "sdvx":
@@ -48,10 +48,16 @@ export default function PBCompareCell({
case "wacca":
case "museca":
scoreRenderFn = FormatMillions;
shouldShowPercent = false;
break;
case "jubeat":
scoreRenderFn = FormatMillions;
shouldShowPercent = true;
break;
case "bms":
case "iidx":
scoreRenderFn = (k: number) => k.toString();
shouldShowPercent = true;
break;
}
@@ -87,8 +93,12 @@ export default function PBCompareCell({
{compareType === "score" ? (
<>
<strong>{(cmpScore > 0 ? "+" : "") + scoreRenderFn(cmpScore)}</strong>
<br />
<small>({fmtCmpPercent})</small>
{shouldShowPercent && (
<>
<br />
<small>({fmtCmpPercent})</small>
</>
)}
{esdDiff !== undefined && (
<>
<br />
@@ -1,19 +1,21 @@
import { NumericSOV, StrSOV } from "util/sorts";
import { CreatePBCompareSearchParams } from "util/tables/create-search";
import React, { useState } from "react";
import { Game, IDStrings, Playtype } from "tachi-common";
import { ESDCompare } from "tachi-common/lib/esd";
import { ComparePBsDataset } from "types/tables";
import DifficultyCell from "../cells/DifficultyCell";
import PBCompareCell from "../cells/PBCompareCell";
import TitleCell from "../cells/TitleCell";
import SelectableCompareType from "../components/SelectableCompareType";
import TachiTable, { Header, ZTableTHProps } from "../components/TachiTable";
import ShortScoreCoreCells from "../game-core-cells/ShortScoreCoreCells";
import ChartHeader from "../headers/ChartHeader";
import PBCompareCell from "../cells/PBCompareCell";
import SelectableCompareType from "../components/SelectableCompareType";
export default function ComparePBsTable<I extends IDStrings = IDStrings>({
dataset,
game,
playtype,
baseUser,
compareUser,
shouldESD,
@@ -79,6 +81,7 @@ export default function ComparePBsTable<I extends IDStrings = IDStrings>({
entryName="Charts"
defaultReverseSort
defaultSortMode="Vs."
searchFunctions={CreatePBCompareSearchParams(game, playtype)}
rowFunction={(data) => (
<Row data={data} game={game} compareType={compareType} shouldESD={shouldESD} />
)}
+20 -2
View File
@@ -1,14 +1,14 @@
import { HumanFriendlyStrToGradeIndex, HumanFriendlyStrToLampIndex } from "util/str-to-num";
import { ValueGetterOrHybrid } from "util/ztable/search";
import {
BMS_TABLES,
ChartDocument,
Game,
GamePTConfig,
GetGamePTConfig,
IDStrings,
BMS_TABLES,
} from "tachi-common";
import { FolderDataset, PBDataset, ScoreDataset } from "types/tables";
import { ComparePBsDataset, FolderDataset, PBDataset, ScoreDataset } from "types/tables";
import { Playtype } from "types/tachi";
function GetBMSTableVal(chart: ChartDocument<"bms:7K" | "bms:14K">, key: string) {
@@ -88,6 +88,24 @@ export function CreateDefaultPBSearchParams<I extends IDStrings = IDStrings>(
return searchFunctions;
}
export function CreatePBCompareSearchParams<I extends IDStrings = IDStrings>(
game: Game,
playtype: Playtype
) {
const searchFunctions: Record<string, ValueGetterOrHybrid<ComparePBsDataset<I>[0]>> = {
artist: (x) => x.song.artist,
title: (x) => x.song.title,
difficulty: (x) => x.chart.difficulty,
level: (x) => x.chart.levelNum,
};
if (game === "bms") {
HandleBMSNonsense(searchFunctions, playtype, (k) => k);
}
return searchFunctions;
}
export function CreateDefaultFolderSearchParams<I extends IDStrings = IDStrings>(
game: Game,
playtype: Playtype