map generation logic

This commit is contained in:
Kalle (Sendou) 2021-01-27 10:52:38 +02:00
parent 63255cb290
commit c7c340c768
4 changed files with 233 additions and 174 deletions

View File

@ -1,5 +1,5 @@
import { GetAllLadderRegisteredTeamsData } from "prisma/queries/getAllLadderRegisteredTeams";
import useSWR from "swr";
export const useLadderTeams = () =>
useSWR<GetAllLadderRegisteredTeamsData>("/api/play/teams");
export const useLadderTeams = (skip?: boolean) =>
useSWR<GetAllLadderRegisteredTeamsData>(skip ? null : "/api/play/teams");

View File

@ -1,113 +0,0 @@
import { getMySession } from "lib/getMySession";
import { getLadderRounds } from "lib/playFunctions";
import { shuffleArray } from "lib/shuffleArray";
import { NextApiRequest, NextApiResponse } from "next";
import { getAllLadderRegisteredTeamsForMatches } from "prisma/queries/getAllLadderRegisteredTeamsForMatches";
const matchesHandler = async (req: NextApiRequest, res: NextApiResponse) => {
switch (req.method) {
case "POST":
await postHandler(req, res);
break;
default:
res.status(405).end();
}
};
async function postHandler(req: NextApiRequest, res: NextApiResponse) {
const user = await getMySession();
// if (user?.discordId !== ADMIN_DISCORD_ID) {
// return res.status(401).end();
// }
const teams = (await getAllLadderRegisteredTeamsForMatches()).filter(
(team) => team.roster.length === 4
);
if (teams.length < 4) return res.status(400).end();
const matches = getLadderRounds(teams);
// await Promise.all(
// matches.flatMap((round, i) =>
// round.map((match) =>
// prisma.ladderMatch.create({
// data: {
// date: "",
// maplist: {},
// order: i + 1,
// players: {
// create: match.flatMap((team, teamI) =>
// team.roster.map((user) => ({
// userId: user.id,
// team: teamI === 0 ? "ALPHA" : "BRAVO",
// }))
// ),
// },
// },
// })
// )
// )
// );
const eighteenMaps = getMaplist();
res.status(200).json(
matches.flatMap((round, i) =>
round.map((match) => ({
data: {
date: "",
maplist:
i === 0 ? eighteenMaps.slice(0, 9) : eighteenMaps.slice(9, 18),
order: i + 1,
players: {
create: match.flatMap((team, teamI) =>
team.roster.map((user) => ({
userId: user.id,
team: teamI === 0 ? "ALPHA" : "BRAVO",
}))
),
},
},
}))
)
);
}
function getMaplist() {
const modes = shuffleArray(["SZ", "TC", "RM", "CB"]);
const stages = shuffleArray([
"The Reef",
"Musselforge Fitness",
"Starfish Mainstage",
"Humpback Pump Track",
"Inkblot Art Academy",
"Sturgeon Shipyard",
"Manta Maria",
"Snapper Canal",
"Blackbelly Skatepark",
"MakoMart",
"Shellendorf Institute",
"Goby Arena",
"Piranha Pit",
"Camp Triggerfish",
"Wahoo World",
"New Albacore Hotel",
"Ancho-V Games",
"Skipper Pavilion",
//"Moray Towers",
//"Port Mackerel",
//"Walleye Warehouse",
//"Arowana Mall",
//"Kelp Dome"
]);
return stages.map((stage) => {
const mode = modes.pop();
modes.unshift(mode!);
return { stage, mode };
});
}
export default matchesHandler;

View File

@ -1,5 +1,5 @@
import { Box, Flex, HStack } from "@chakra-ui/react";
import { t } from "@lingui/macro";
import { t, Trans } from "@lingui/macro";
import Breadcrumbs from "components/common/Breadcrumbs";
import MyContainer from "components/common/MyContainer";
import SubText from "components/common/SubText";
@ -7,77 +7,214 @@ import TwitterAvatar from "components/common/TwitterAvatar";
import UserAvatar from "components/common/UserAvatar";
import RegisterHeader from "components/play/RegisterHeader";
import { useLadderTeams } from "hooks/play";
import { getLadderRounds } from "lib/playFunctions";
import { shuffleArray } from "lib/shuffleArray";
import { useMyTheme } from "lib/useMyTheme";
import { GetStaticProps } from "next";
import prisma from "prisma/client";
import { getAllLadderRegisteredTeamsForMatches } from "prisma/queries/getAllLadderRegisteredTeamsForMatches";
import { getLadderDay, GetLadderDayData } from "prisma/queries/getLadderDay";
const PlayPage = () => {
interface Props {
ladderDay: GetLadderDayData;
}
const PlayPage: React.FC<Props> = ({ ladderDay }) => {
const { gray } = useMyTheme();
const { data } = useLadderTeams();
const { data } = useLadderTeams(!ladderDay);
console.log({ ladderDay });
return (
<MyContainer>
<Breadcrumbs pages={[{ name: t`Play` }]} />
<Box fontSize="lg" fontWeight="bold">
Next event: testing
{ladderDay ? (
<>Next event: {new Date(ladderDay.date).toLocaleString()}</>
) : (
<>
<Trans>
Next ladder date is not confirmed. Follow this page for updates!
</Trans>
</>
)}
</Box>
<RegisterHeader />
<Box mt={4}>
{data
?.sort((a, b) => b.roster.length - a.roster.length)
.map((team) => {
const teamTuple = team.roster
.filter((member) => member.team)
.map((member) => member.team)
.reduce(
(
acc: [
{ name: string; twitterName: string; nameForUrl: string },
number
][],
cur
) => {
const tuple = acc.find(([{ name }]) => name === cur!.name);
if (tuple) tuple[1]++;
{ladderDay && ladderDay.matches.length === 0 && (
<>
<RegisterHeader />
<Box mt={4}>
{data
?.sort((a, b) => b.roster.length - a.roster.length)
.map((team) => {
const teamTuple = team.roster
.filter((member) => member.team)
.map((member) => member.team)
.reduce(
(
acc: [
{
name: string;
twitterName: string;
nameForUrl: string;
},
number
][],
cur
) => {
const tuple = acc.find(
([{ name }]) => name === cur!.name
);
if (tuple) tuple[1]++;
acc.push([{ ...(cur as any) }, 1]);
return acc;
},
[]
)
.find((tuple) => tuple[1] >= 3);
return (
<Box key={team.id} my={4}>
{teamTuple && team.roster.length === 4 ? (
<Flex fontWeight="bold" align="center">
{teamTuple[0].twitterName && (
<TwitterAvatar
twitterName={teamTuple[0].twitterName}
size="sm"
mr={1}
/>
acc.push([{ ...(cur as any) }, 1]);
return acc;
},
[]
)
.find((tuple) => tuple[1] >= 3);
return (
<Box key={team.id} my={4}>
{teamTuple && team.roster.length === 4 ? (
<Flex fontWeight="bold" align="center">
{teamTuple[0].twitterName && (
<TwitterAvatar
twitterName={teamTuple[0].twitterName}
size="sm"
mr={1}
/>
)}
{teamTuple[0].name}
{teamTuple[1] === 3 && team.roster.length >= 4 && (
<SubText ml={1}>+1</SubText>
)}
</Flex>
) : (
<HStack>
{team.roster.map((member) => (
<UserAvatar key={member.id} user={member} size="sm" />
))}
</HStack>
)}
{teamTuple[0].name}
{teamTuple[1] === 3 && team.roster.length >= 4 && (
<SubText ml={1}>+1</SubText>
)}
</Flex>
) : (
<HStack>
{team.roster.map((member) => (
<UserAvatar key={member.id} user={member} size="sm" />
))}
</HStack>
)}
<Box color={gray} fontSize="sm" mt={2}>
{team.roster
.map((user) => `${user.username}#${user.discriminator}`)
.join(", ")}
</Box>
</Box>
);
})}
</Box>
<Box color={gray} fontSize="sm" mt={2}>
{team.roster
.map((user) => `${user.username}#${user.discriminator}`)
.join(", ")}
</Box>
</Box>
);
})}
</Box>
</>
)}
</MyContainer>
);
};
export const getStaticProps: GetStaticProps<Props> = async () => {
const ladderDay = await getLadderDay();
let ladderDayAfterGeneration: GetLadderDayData | undefined;
if (
ladderDay &&
!ladderDay.matches.length &&
ladderDay.date.getTime() < new Date().getTime()
) {
const teams = (await getAllLadderRegisteredTeamsForMatches()).filter(
(team) => team.roster.length === 4
);
if (teams.length < 4) {
return {
props: { ladderDay: JSON.parse(JSON.stringify(ladderDay)) },
revalidate: 30,
}; // FIX
}
const matches = getLadderRounds(teams);
const eighteenMaps = getMaplist();
const dateWeekFromNow = new Date(ladderDay.date);
dateWeekFromNow.setHours(168);
const createPosts = matches.flatMap((round, i) =>
round.map((match) =>
prisma.ladderMatch.create({
data: {
dayId: ladderDay.id,
maplist:
i === 0 ? eighteenMaps.slice(0, 9) : eighteenMaps.slice(9, 18),
order: i + 1,
players: {
create: match.flatMap((team, teamI) =>
team.roster.map((user) => ({
userId: user.id,
team: teamI === 0 ? "ALPHA" : "BRAVO",
}))
),
},
},
})
)
);
const createLadderDay = prisma.ladderDay.create({
data: { date: dateWeekFromNow },
});
const deleteLadderRegisteredTeams = prisma.ladderRegisteredTeam.deleteMany();
// TODO: is this ok?
await prisma.$transaction([
...createPosts,
createLadderDay,
deleteLadderRegisteredTeams,
] as any);
ladderDayAfterGeneration = await getLadderDay();
}
return {
props: {
ladderDay: JSON.parse(
JSON.stringify(ladderDayAfterGeneration ?? ladderDay)
),
},
revalidate: 30,
};
};
function getMaplist() {
const modes = shuffleArray(["SZ", "TC", "RM", "CB"]);
const stages = shuffleArray([
"The Reef",
"Musselforge Fitness",
"Starfish Mainstage",
"Humpback Pump Track",
"Inkblot Art Academy",
"Sturgeon Shipyard",
"Manta Maria",
"Snapper Canal",
"Blackbelly Skatepark",
"MakoMart",
"Shellendorf Institute",
"Goby Arena",
"Piranha Pit",
"Camp Triggerfish",
"Wahoo World",
"New Albacore Hotel",
"Ancho-V Games",
"Skipper Pavilion",
//"Moray Towers",
//"Port Mackerel",
//"Walleye Warehouse",
//"Arowana Mall",
//"Kelp Dome"
]);
return stages.map((stage) => {
const mode = modes.pop();
modes.unshift(mode!);
return { stage, mode };
});
}
export default PlayPage;

View File

@ -0,0 +1,35 @@
import { Prisma } from "@prisma/client";
import prisma from "prisma/client";
export type GetLadderDayData = Prisma.PromiseReturnType<typeof getLadderDay>;
export const getLadderDay = async () => {
const d = new Date();
d.setHours(d.getHours() - 6);
return prisma.ladderDay.findFirst({
where: { date: { gte: d } },
include: {
matches: {
select: {
order: true,
maplist: true,
teamAScore: true,
teamBScore: true,
players: {
select: {
user: {
select: {
username: true,
discordAvatar: true,
discriminator: true,
discordId: true,
},
},
},
},
},
},
},
});
};