From d5e62efd485e5ae00d84361e3ab9df628eb1c849 Mon Sep 17 00:00:00 2001
From: Kalle <38327916+Sendouc@users.noreply.github.com>
Date: Sat, 29 Jan 2022 11:33:01 +0200
Subject: [PATCH] Seeded groups data to frontend
---
app/constants.ts | 1 +
app/models/LFGGroup.server.ts | 42 ++++++++++++++++++---
app/routes/play/looking.tsx | 62 ++++++++++++++++++++++++++++++-
app/utils/schemas.ts | 1 +
prisma/schema.prisma | 2 +
prisma/seed/script.ts | 70 +++++++++++++++++++++++++++++++++++
6 files changed, 170 insertions(+), 8 deletions(-)
diff --git a/app/constants.ts b/app/constants.ts
index 8232c5fcb..df9ba17aa 100644
--- a/app/constants.ts
+++ b/app/constants.ts
@@ -70,6 +70,7 @@ export const NZAP_TEST_DISCORD_ID = "455039198672453645";
export const NZAP_TEST_AVATAR = "f809176af93132c3db5f0a5019e96339";
export const ROOM_PASS_LENGTH = 4;
+export const LFG_GROUP_FULL_SIZE = 4;
export const TOURNAMENT_TEAM_ROSTER_MIN_SIZE = 4;
export const TOURNAMENT_TEAM_ROSTER_MAX_SIZE = 6;
/** How many minutes before the start of the tournament check-in closes */
diff --git a/app/models/LFGGroup.server.ts b/app/models/LFGGroup.server.ts
index beb316304..192c1c4a5 100644
--- a/app/models/LFGGroup.server.ts
+++ b/app/models/LFGGroup.server.ts
@@ -38,18 +38,48 @@ export function findActiveByMember(user: { id: string }) {
},
},
include: {
- members: true
- }
+ members: true,
+ },
+ });
+}
+
+export function findLookingByType(type: LfgGroupType, ranked: boolean | null) {
+ return db.lfgGroup.findMany({
+ where: {
+ type,
+ looking: true,
+ // For ranked groups we show both ranked and unranked options
+ ranked: ranked === false ? false : undefined,
+ },
+ select: {
+ id: true,
+ ranked: true,
+ members: {
+ select: {
+ user: {
+ select: {
+ discordAvatar: true,
+ discordDiscriminator: true,
+ discordName: true,
+ discordId: true,
+ },
+ },
+ },
+ },
+ },
+ orderBy: {
+ createdAt: "desc",
+ },
});
}
export function startLooking(id: string) {
return db.lfgGroup.update({
where: {
- id
+ id,
},
data: {
- looking: true
- }
- })
+ looking: true,
+ },
+ });
}
diff --git a/app/routes/play/looking.tsx b/app/routes/play/looking.tsx
index ce4983052..e88b696f9 100644
--- a/app/routes/play/looking.tsx
+++ b/app/routes/play/looking.tsx
@@ -1,3 +1,61 @@
-export default function LookingPage() {
- return
Looking...
;
+import { json, LoaderFunction, redirect, useLoaderData } from "remix";
+import { LFG_GROUP_FULL_SIZE } from "~/constants";
+import * as LFGGroup from "~/models/LFGGroup.server";
+import { requireUser } from "~/utils";
+
+interface LookingLoaderData {
+ groups: {
+ id: string;
+ members?: {
+ discordId: string;
+ discordAvatar: string | null;
+ discordName: string;
+ discordDiscriminator: string;
+ }[];
+ }[];
+}
+
+export const loader: LoaderFunction = async ({ context }) => {
+ const user = requireUser(context);
+ const ownGroup = await LFGGroup.findActiveByMember(user);
+ if (!ownGroup) return redirect("/play");
+ if (!ownGroup.looking) return redirect("/play/add-players");
+
+ const groups = await LFGGroup.findLookingByType(
+ ownGroup.type,
+ ownGroup.ranked
+ );
+
+ // For example if we have a group of 3 and group type is QUAD we only want to consider groups of size 1
+ // .. if we have a group size of 2 then we can consider groups of size 1 or 2 and so on
+ const maxGroupSizeToConsider = (() => {
+ if (ownGroup.type === "TWIN") return 1;
+
+ return LFG_GROUP_FULL_SIZE - ownGroup.members.length;
+ })();
+
+ const lookingForMatch = ownGroup.members.length === LFG_GROUP_FULL_SIZE;
+ return json({
+ groups: groups
+ .filter((group) => group.members.length <= maxGroupSizeToConsider)
+ .map((group) => ({
+ id: group.id,
+ // When looking for a match ranked groups are censored
+ // and instead we only reveal their approximate skill level
+ members:
+ group.ranked && lookingForMatch
+ ? undefined
+ : group.members.map((member) => member.user),
+ })),
+ });
+};
+
+export default function LookingPage() {
+ const data = useLoaderData();
+
+ return (
+
+
{JSON.stringify(data, null, 2)}
+
+ );
}
diff --git a/app/utils/schemas.ts b/app/utils/schemas.ts
index c6a72baa4..174a4b9ac 100644
--- a/app/utils/schemas.ts
+++ b/app/utils/schemas.ts
@@ -13,6 +13,7 @@ export const SeedVariationsSchema = z.enum([
"check-in",
"match",
"tournament-start",
+ "looking",
]);
export type LoggedInUser = NonNullable<
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 2e232954e..66e294818 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -225,6 +225,8 @@ model LfgGroup {
likesReceived LfgGroupLike[] @relation("target")
@@index([active])
+ @@index([looking])
+ @@index([type])
}
model LfgGroupLike {
diff --git a/prisma/seed/script.ts b/prisma/seed/script.ts
index ecd6fdc80..e1d4d6467 100644
--- a/prisma/seed/script.ts
+++ b/prisma/seed/script.ts
@@ -16,6 +16,7 @@ import { createTournamentRounds } from "../../app/services/tournament";
import invariant from "tiny-invariant";
import { SeedVariations } from "~/utils/schemas";
import { v4 as uuidv4 } from "uuid";
+import clone from "just-clone";
const prisma = new PrismaClient();
const mapListDE = `{"losers":[[{"id":4647,"name":"Kelp Dome","mode":"SZ"},{"id":4658,"name":"Blackbelly Skatepark","mode":"TC"},{"id":4645,"name":"Manta Maria","mode":"CB"}],[{"id":4624,"name":"Inkblot Art Academy","mode":"RM"},{"id":4707,"name":"Ancho-V Games","mode":"SZ"},{"id":4618,"name":"Humpback Pump Track","mode":"TC"}],[{"id":4692,"name":"Camp Triggerfish","mode":"SZ"},{"id":4665,"name":"MakoMart","mode":"CB"},{"id":4634,"name":"Moray Towers","mode":"RM"}],[{"id":4609,"name":"Musselforge Fitness","mode":"RM"},{"id":4647,"name":"Kelp Dome","mode":"SZ"},{"id":4678,"name":"Arowana Mall","mode":"TC"}],[{"id":4705,"name":"New Albacore Hotel","mode":"CB"},{"id":4644,"name":"Manta Maria","mode":"RM"},{"id":4707,"name":"Ancho-V Games","mode":"SZ"}],[{"id":4657,"name":"Blackbelly Skatepark","mode":"SZ"},{"id":4690,"name":"Piranha Pit","mode":"CB"},{"id":4682,"name":"Goby Arena","mode":"SZ"},{"id":4678,"name":"Arowana Mall","mode":"TC"},{"id":4624,"name":"Inkblot Art Academy","mode":"RM"}]],"winners":[[{"id":4677,"name":"Arowana Mall","mode":"SZ"},{"id":4665,"name":"MakoMart","mode":"CB"},{"id":4618,"name":"Humpback Pump Track","mode":"TC"}],[{"id":4624,"name":"Inkblot Art Academy","mode":"RM"},{"id":4683,"name":"Goby Arena","mode":"TC"},{"id":4692,"name":"Camp Triggerfish","mode":"SZ"}],[{"id":4647,"name":"Kelp Dome","mode":"SZ"},{"id":4634,"name":"Moray Towers","mode":"RM"},{"id":4707,"name":"Ancho-V Games","mode":"SZ"},{"id":4610,"name":"Musselforge Fitness","mode":"CB"},{"id":4658,"name":"Blackbelly Skatepark","mode":"TC"}],[{"id":4644,"name":"Manta Maria","mode":"RM"},{"id":4677,"name":"Arowana Mall","mode":"SZ"},{"id":4690,"name":"Piranha Pit","mode":"CB"},{"id":4682,"name":"Goby Arena","mode":"SZ"},{"id":4618,"name":"Humpback Pump Track","mode":"TC"}],[{"id":4624,"name":"Inkblot Art Academy","mode":"RM"},{"id":4707,"name":"Ancho-V Games","mode":"SZ"},{"id":4610,"name":"Musselforge Fitness","mode":"CB"},{"id":4657,"name":"Blackbelly Skatepark","mode":"SZ"},{"id":4693,"name":"Camp Triggerfish","mode":"TC"},{"id":4664,"name":"MakoMart","mode":"RM"},{"id":4647,"name":"Kelp Dome","mode":"SZ"}],[{"id":4617,"name":"Humpback Pump Track","mode":"SZ"},{"id":4635,"name":"Moray Towers","mode":"CB"},{"id":4682,"name":"Goby Arena","mode":"SZ"},{"id":4644,"name":"Manta Maria","mode":"RM"},{"id":4678,"name":"Arowana Mall","mode":"TC"},{"id":4692,"name":"Camp Triggerfish","mode":"SZ"},{"id":4705,"name":"New Albacore Hotel","mode":"CB"}]]}`;
@@ -45,6 +46,9 @@ export async function seed(variation?: SeedVariations) {
await prisma.tournament.deleteMany();
await prisma.organization.deleteMany();
await prisma.trustRelationships.deleteMany();
+ await prisma.lfgGroupLike.deleteMany();
+ await prisma.lfgGroupMember.deleteMany();
+ await prisma.lfgGroup.deleteMany();
await prisma.user.deleteMany();
await prisma.stage.deleteMany();
@@ -61,12 +65,21 @@ export async function seed(variation?: SeedVariations) {
await trustRelationship(nzapUserCreated.id, adminUserCreated.id);
await stages();
await tournamentAddMaps(tournament.id);
+
+ const userIdsInTheSystem = (await prisma.user.findMany({})).map(
+ (u) => u.id
+ );
+ await lookingLfgGroups(userIdsInTheSystem);
+
if (variation === "match" || variation === "tournament-start") {
await tournamentRoundsCreate();
}
if (variation === "match") {
await advanceRound();
}
+ if (variation === "looking") {
+ await ownGroup();
+ }
async function adminUser() {
return prisma.user.create({
@@ -357,6 +370,63 @@ export async function seed(variation?: SeedVariations) {
return result;
}
+ async function lookingLfgGroups(userIds: string[]) {
+ function randomIntFromInterval(min: number, max: number) {
+ // min and max included
+ return Math.floor(Math.random() * (max - min + 1) + min);
+ }
+
+ const userIdsStack = clone(userIds);
+ for (let i = 0; i < 24; i++) {
+ const amountOfUsers = randomIntFromInterval(1, 3);
+ await prisma.lfgGroup.create({
+ data: {
+ looking: true,
+ active: true,
+ type: "VERSUS",
+ ranked: i < 12,
+ members: {
+ createMany: {
+ data: new Array(amountOfUsers).fill(null).map((_, i) => ({
+ memberId: userIdsStack.shift()!,
+ captain: i === 0,
+ })),
+ },
+ },
+ },
+ });
+ }
+ }
+
+ async function ownGroup() {
+ const groups = await prisma.lfgGroup.findMany({});
+ return prisma.lfgGroup.create({
+ data: {
+ looking: true,
+ type: "VERSUS",
+ active: true,
+ ranked: true,
+ members: {
+ createMany: {
+ data: [
+ {
+ memberId: ADMIN_TEST_UUID,
+ },
+ { memberId: NZAP_TEST_UUID },
+ ],
+ },
+ },
+ likesReceived: {
+ createMany: {
+ data: new Array(10).fill(null).map((_) => ({
+ likerId: groups.shift()!.id,
+ })),
+ },
+ },
+ },
+ });
+ }
+
async function tournamentRoundsCreate() {
const stages = await prisma.stage.findMany({});
await createTournamentRounds({