mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-12 14:16:04 -05:00
Submit score
This commit is contained in:
@@ -2,16 +2,14 @@ import { Mode } from "@prisma/client";
|
||||
import clsx from "clsx";
|
||||
import clone from "just-clone";
|
||||
import { useState } from "react";
|
||||
import { Form } from "remix";
|
||||
import { scoreValid } from "~/core/play/validators";
|
||||
import { Button } from "../Button";
|
||||
import { ModeImage } from "../ModeImage";
|
||||
|
||||
const NO_RESULT = "NO_RESULT";
|
||||
|
||||
export function MapList({
|
||||
mapList,
|
||||
canSubmitScore,
|
||||
groupIds,
|
||||
}: {
|
||||
interface MapListProps {
|
||||
mapList: {
|
||||
name: string;
|
||||
mode: Mode;
|
||||
@@ -21,8 +19,11 @@ export function MapList({
|
||||
our: string;
|
||||
their: string;
|
||||
};
|
||||
}) {
|
||||
const [winners, setWinners] = useState<string[]>([]);
|
||||
}
|
||||
export function MapList({ mapList, canSubmitScore, groupIds }: MapListProps) {
|
||||
const [winners, setWinners] = useState<string[]>(
|
||||
new Array(5).fill(null).map(() => "5f31654d-977b-402b-817a-6f20cd933aa5")
|
||||
);
|
||||
|
||||
const updateWinners = (winnerId: string, index: number) => {
|
||||
const newWinners = clone(winners);
|
||||
@@ -39,11 +40,6 @@ export function MapList({
|
||||
setWinners(newWinners);
|
||||
};
|
||||
|
||||
// TODO: not properly handling scores getting reported after conclusion
|
||||
const warningText = scoreValid(winners, mapList.length)
|
||||
? undefined
|
||||
: "Report more maps to submit the score";
|
||||
|
||||
return (
|
||||
<ol className="play-match__stages">
|
||||
<h2 className="play-match__map-list-header">Map list</h2>
|
||||
@@ -75,7 +71,46 @@ export function MapList({
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
<div className="play-match__error-text">{warningText}</div>
|
||||
{canSubmitScore && <Submitter mapList={mapList} winners={winners} />}
|
||||
</ol>
|
||||
);
|
||||
}
|
||||
|
||||
function Submitter({
|
||||
mapList,
|
||||
winners,
|
||||
}: {
|
||||
mapList: MapListProps["mapList"];
|
||||
winners: string[];
|
||||
}) {
|
||||
// TODO: not properly handling scores getting reported after conclusion
|
||||
const warningText = scoreValid(winners, mapList.length)
|
||||
? undefined
|
||||
: "Report more maps to submit the score";
|
||||
|
||||
if (warningText) {
|
||||
return <div className="play-match__error-text">{warningText}</div>;
|
||||
}
|
||||
|
||||
const ids = Array.from(new Set(winners));
|
||||
const score = winners.reduce(
|
||||
(acc: [number, number], winnerId) => {
|
||||
if (winnerId === ids[0]) acc[0]++;
|
||||
else acc[1]++;
|
||||
|
||||
return acc;
|
||||
},
|
||||
[0, 0]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="play-match__score-submit-button">
|
||||
<Form method="post">
|
||||
<input type="hidden" name="winnerIds" value={JSON.stringify(winners)} />
|
||||
<Button type="submit" name="_action" value="REPORT_SCORE">
|
||||
Submit {score.join("-")}
|
||||
</Button>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,3 +18,27 @@ export function findById(id: string) {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function reportScore({
|
||||
matchId,
|
||||
winnerIds,
|
||||
}: {
|
||||
matchId: string;
|
||||
winnerIds: string[];
|
||||
}) {
|
||||
// https://stackoverflow.com/a/26715934
|
||||
return db.$executeRawUnsafe(`
|
||||
update "LfgGroupMatchStage" as lfg set
|
||||
"winnerGroupId" = lfg2.winner_id
|
||||
from (values
|
||||
${winnerIds
|
||||
.map((winnerId, i) => `('${matchId}', ${i + 1}, '${winnerId}')`)
|
||||
.join(",")}
|
||||
) as lfg2(lfg_group_match_id, "order", winner_id)
|
||||
where lfg2.lfg_group_match_id = lfg."lfgGroupMatchId" and lfg2.order = lfg.order;
|
||||
`);
|
||||
// 1) update scores DONE
|
||||
// 2) update skill
|
||||
// 3) update team skill?
|
||||
// 4) if already reported error if different
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
makeTitle,
|
||||
parseRequestFormData,
|
||||
requireUser,
|
||||
safeJSONParse,
|
||||
UserLean,
|
||||
validate,
|
||||
} from "~/utils";
|
||||
@@ -52,7 +53,11 @@ const matchActionSchema = z.union([
|
||||
_action: z.literal("LOOK_AGAIN"),
|
||||
}),
|
||||
z.object({
|
||||
_action: z.literal("PLACEHOLDER"),
|
||||
_action: z.literal("REPORT_SCORE"),
|
||||
winnerIds: z.preprocess(
|
||||
safeJSONParse,
|
||||
z.array(z.string().uuid()).min(5).max(9)
|
||||
),
|
||||
}),
|
||||
]);
|
||||
|
||||
@@ -67,7 +72,14 @@ export const action: ActionFunction = async ({ request, context }) => {
|
||||
validate(ownGroup, "No active group");
|
||||
|
||||
switch (data._action) {
|
||||
case "PLACEHOLDER":
|
||||
case "REPORT_SCORE": {
|
||||
validate(ownGroup.matchId, "No match for the group");
|
||||
await LFGMatch.reportScore({
|
||||
matchId: ownGroup.matchId,
|
||||
winnerIds: data.winnerIds,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "LOOK_AGAIN": {
|
||||
validate(!ownGroup.ranked, "Score reporting required");
|
||||
await LFGGroup.setInactive(ownGroup.id);
|
||||
|
||||
@@ -115,3 +115,9 @@
|
||||
margin-block-start: var(--s-4);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.play-match__score-submit-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-block-start: var(--s-4);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user