Switch from active/looking to status enum

This commit is contained in:
Kalle
2022-02-25 21:33:33 +02:00
parent 0253a3765d
commit 62e7fc15cb
10 changed files with 103 additions and 45 deletions

View File

@@ -123,13 +123,13 @@ export function otherGroupsForResponse({
lookingForMatch,
ownGroup,
}: {
groups: LFGGroup.FindLooking;
groups: LFGGroup.FindLookingAndOwnActive;
likes: {
given: Set<string>;
received: Set<string>;
};
lookingForMatch: boolean;
ownGroup: Unpacked<LFGGroup.FindLooking>;
ownGroup: Unpacked<LFGGroup.FindLookingAndOwnActive>;
}) {
return groups
.filter(

View File

@@ -16,8 +16,8 @@ export function create({
type,
// TWIN starts looking immediately because it makes no sense
// to pre-add players to the group
// looking: type === "TWIN",
looking: true,
// looking: type === "TWIN" ? "LOOKING" : "PRE-ADD",
status: "LOOKING",
ranked,
members: {
create: {
@@ -145,7 +145,7 @@ export async function matchUp({
},
data: {
matchId: match.id,
looking: false,
status: "MATCH",
},
});
}
@@ -154,10 +154,10 @@ export function findById(id: string) {
return db.lfgGroup.findUnique({ where: { id }, include: { members: true } });
}
export function findActiveByMember(user: { id: string }) {
export function findLookingByMember(user: { id: string }) {
return db.lfgGroup.findFirst({
where: {
active: true,
status: "LOOKING",
members: {
some: {
memberId: user.id,
@@ -180,13 +180,33 @@ export function findActiveByMember(user: { id: string }) {
});
}
export type FindLooking = Prisma.PromiseReturnType<typeof findLooking>;
export function findLooking() {
export type FindLookingAndOwnActive = Prisma.PromiseReturnType<
typeof findLookingAndOwnActive
>;
export function findLookingAndOwnActive(userId?: string) {
const where = userId
? {
OR: [
{
status: "LOOKING" as const,
},
{
members: {
some: {
memberId: userId,
},
},
NOT: {
status: "INACTIVE" as const,
},
},
],
}
: {
status: "LOOKING" as const,
};
return db.lfgGroup.findMany({
where: {
active: true,
looking: true,
},
where,
include: {
members: {
include: {
@@ -217,7 +237,7 @@ export function startLooking(id: string) {
id,
},
data: {
looking: true,
status: "LOOKING",
},
});
}
@@ -228,8 +248,7 @@ export function setInactive(id: string) {
id,
},
data: {
looking: false,
active: false,
status: "INACTIVE",
},
});
}

View File

@@ -52,7 +52,6 @@ export async function reportScore({
const adjustedSkills = adjustSkills({ skills, playerIds });
// https://stackoverflow.com/a/26715934
return db.$transaction([
db.skill.createMany({
data: adjustedSkills.map((s) => ({ ...s, matchId: UNSAFE_matchId })),
@@ -64,9 +63,10 @@ export async function reportScore({
},
},
data: {
active: false,
status: "INACTIVE",
},
}),
// https://stackoverflow.com/a/26715934
db.$executeRawUnsafe(`
update "LfgGroupMatchStage" as lfg set
"winnerGroupId" = lfg2.winner_id

View File

@@ -16,6 +16,7 @@ import * as User from "~/models/User.server";
import { getUser, requireUser, validate } from "~/utils";
import styles from "~/styles/play-add-players.css";
import { isGroupAdmin } from "~/core/play/validators";
import invariant from "tiny-invariant";
export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: styles }];
@@ -24,7 +25,7 @@ export const links: LinksFunction = () => {
export const action: ActionFunction = async ({ context }) => {
const user = requireUser(context);
const group = await LFGGroup.findActiveByMember(user);
const group = await LFGGroup.findLookingByMember(user);
validate(group, "Not a member of active group");
validate(isGroupAdmin({ user, group }), "Not captain of the group");
@@ -43,12 +44,15 @@ export const loader: LoaderFunction = async ({ context }) => {
if (!user) return redirect("/play");
const [ownGroup, trustingUsers] = await Promise.all([
LFGGroup.findActiveByMember(user),
LFGGroup.findLookingByMember(user),
User.findTrusters(user.id),
]);
if (!ownGroup) return redirect("/play");
if (ownGroup.matchId) return redirect(`/play/match/${ownGroup.matchId}`);
if (ownGroup.looking) return redirect("/play/looking");
if (ownGroup.status === "MATCH") {
invariant(ownGroup.matchId, "Unexpected no matchId but status is MATCH");
return redirect(`/play/match/${ownGroup.matchId}`);
}
if (ownGroup.status === "LOOKING") return redirect("/play/looking");
return json<AddPlayersLoaderData>({
inviteCode: ownGroup.inviteCode,

View File

@@ -24,6 +24,7 @@ import * as LFGGroup from "~/models/LFGGroup.server";
import { Button } from "~/components/Button";
import { useUser } from "~/hooks/common";
import { filterExpiredGroups } from "~/core/play/utils";
import invariant from "tiny-invariant";
export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: styles }];
@@ -70,7 +71,7 @@ export const action: ActionFunction = async ({ request, context }) => {
ranked: getRanked(),
});
if (group.looking) {
if (group.status === "LOOKING") {
return redirect("/play/looking");
}
@@ -92,7 +93,7 @@ export interface PlayFrontPageLoader {
export const loader: LoaderFunction = async ({ context }) => {
const user = getUser(context);
const groups = await LFGGroup.findLooking();
const groups = await LFGGroup.findLookingAndOwnActive(user?.id);
const counts = groups.filter(filterExpiredGroups).reduce(
(acc: PlayFrontPageLoader["counts"], group) => {
const memberCount = group.members.length;
@@ -118,8 +119,11 @@ export const loader: LoaderFunction = async ({ context }) => {
g.members.some((m) => m.user.id === user.id)
);
if (!ownGroup) return json<PlayFrontPageLoader>({ counts });
if (ownGroup.matchId) return redirect(`/play/match/${ownGroup.matchId}`);
if (ownGroup.looking) return redirect("/play/looking");
if (ownGroup.status === "MATCH") {
invariant(ownGroup.matchId, "Unexpected no matchId but status is MATCH");
return redirect(`/play/match/${ownGroup.matchId}`);
}
if (ownGroup.status === "LOOKING") return redirect("/play/looking");
return redirect("/play/add-players");
};

View File

@@ -84,9 +84,9 @@ export const action: ActionFunction = async ({ request, context }) => {
});
const user = requireUser(context);
const ownGroup = await LFGGroup.findActiveByMember(user);
const ownGroup = await LFGGroup.findLookingByMember(user);
validate(ownGroup, "No active group");
validate(ownGroup.looking, "Group is not looking");
validate(ownGroup.status === "LOOKING", "Group is not looking");
const validateIsGroupAdmin = () =>
validate(isGroupAdmin({ group: ownGroup, user }), "Not group admin");
@@ -108,7 +108,7 @@ export const action: ActionFunction = async ({ request, context }) => {
if (
!groupToUniteWith ||
groupToUniteWith.members.length !== data.targetGroupSize ||
!groupToUniteWith.looking
groupToUniteWith.status !== "LOOKING"
) {
break;
}
@@ -140,15 +140,18 @@ export const action: ActionFunction = async ({ request, context }) => {
validateIsGroupAdmin();
const groupToMatchUpWith = await LFGGroup.findById(data.targetGroupId);
validate(groupToMatchUpWith, "Invalid targetGroupId");
validate(!ownGroup.matchId, "Already matched up");
validate(ownGroup.status === "LOOKING", "Group not looking");
// fail silently if already matched up or group stopped looking
if (groupToMatchUpWith.matchId || !groupToMatchUpWith.looking) break;
if (groupToMatchUpWith.status !== "LOOKING") {
break;
}
await LFGGroup.matchUp({
groupIds: [ownGroup.id, data.targetGroupId],
ranked: Boolean(groupToMatchUpWith.ranked && ownGroup.ranked),
});
// TODO: redirect here
break;
}
case "UNLIKE": {
@@ -220,15 +223,18 @@ export interface LookingLoaderData {
export const loader: LoaderFunction = async ({ context }) => {
const user = requireUser(context);
const groups = await LFGGroup.findLooking();
const groups = await LFGGroup.findLookingAndOwnActive(user.id);
const ownGroup = groups.find((g) =>
g.members.some((m) => m.user.id === user.id)
);
if (!ownGroup) return redirect("/play");
if (ownGroup.matchId) return redirect(`/play/match/${ownGroup.matchId}`);
if (!ownGroup.looking) return redirect("/play/add-players");
if (ownGroup.status === "MATCH") {
invariant(ownGroup.matchId, "Unexpected no matchId but status is MATCH");
return redirect(`/play/match/${ownGroup.matchId}`);
}
if (ownGroup.status === "PRE_ADD") return redirect("/play/add-players");
const lookingForMatch =
ownGroup.type === "VERSUS" &&

View File

@@ -97,7 +97,7 @@ export const action: ActionFunction = async ({
g.members.some((m) => m.memberId === user.id)
);
validate(ownGroup, "Not own match");
validate(ownGroup.active, "Not active");
validate(ownGroup.status === "MATCH", "Group doesn't have a match");
validate(isGroupAdmin({ group: ownGroup, user }), "Not group admin");
switch (data._action) {

View File

@@ -0,0 +1,23 @@
/*
Warnings:
- You are about to drop the column `active` on the `LfgGroup` table. All the data in the column will be lost.
- You are about to drop the column `looking` on the `LfgGroup` table. All the data in the column will be lost.
*/
-- CreateEnum
CREATE TYPE "LfgGroupStatus" AS ENUM ('PRE_ADD', 'LOOKING', 'MATCH', 'INACTIVE');
-- DropIndex
DROP INDEX "LfgGroup_active_idx";
-- DropIndex
DROP INDEX "LfgGroup_looking_idx";
-- AlterTable
ALTER TABLE "LfgGroup" DROP COLUMN "active",
DROP COLUMN "looking",
ADD COLUMN "status" "LfgGroupStatus" NOT NULL DEFAULT E'INACTIVE';
-- CreateIndex
CREATE INDEX "LfgGroup_status_idx" ON "LfgGroup"("status");

View File

@@ -214,12 +214,18 @@ enum LfgGroupType {
VERSUS
}
enum LfgGroupStatus {
PRE_ADD
LOOKING
MATCH
INACTIVE
}
model LfgGroup {
id String @id @default(uuid())
ranked Boolean?
type LfgGroupType
active Boolean @default(true)
looking Boolean
status LfgGroupStatus @default(INACTIVE)
matchId String?
inviteCode String @default(uuid())
createdAt DateTime @default(now())
@@ -230,9 +236,8 @@ model LfgGroup {
likesReceived LfgGroupLike[] @relation("target")
matches LfgGroupMatchStage[]
@@index([active])
@@index([looking])
@@index([type])
@@index([status])
}
model LfgGroupLike {

View File

@@ -389,8 +389,7 @@ export async function seed(variation?: SeedVariations) {
const amountOfUsers = randomIntFromInterval(1, 3);
await prisma.lfgGroup.create({
data: {
looking: true,
active: true,
status: "LOOKING",
type: "VERSUS",
ranked: i < 12,
members: {
@@ -408,8 +407,7 @@ export async function seed(variation?: SeedVariations) {
for (let i = 0; i < 24; i++) {
await prisma.lfgGroup.create({
data: {
looking: true,
active: true,
status: "LOOKING",
type: "VERSUS",
ranked: i < 12,
members: {
@@ -446,9 +444,8 @@ export async function seed(variation?: SeedVariations) {
return prisma.lfgGroup.create({
data: {
looking: true,
status: "LOOKING",
type: "VERSUS",
active: true,
ranked: true,
members: {
createMany: {