mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-23 11:57:50 -05:00
351 lines
6.7 KiB
TypeScript
351 lines
6.7 KiB
TypeScript
import type { LfgGroupType, Prisma } from "@prisma/client";
|
|
import { PrismaClientKnownRequestError } from "@prisma/client/runtime";
|
|
import { generateMapListForLfgMatch } from "~/core/play/mapList";
|
|
import { db } from "~/utils/db.server";
|
|
|
|
export function create({
|
|
type,
|
|
ranked,
|
|
user,
|
|
}: {
|
|
type: LfgGroupType;
|
|
ranked?: boolean;
|
|
user: { id: string };
|
|
}) {
|
|
return db.lfgGroup.create({
|
|
data: {
|
|
type,
|
|
// TWIN starts looking immediately because it makes no sense
|
|
// to pre-add players to the group
|
|
status: type === "TWIN" ? "LOOKING" : "PRE_ADD",
|
|
ranked,
|
|
members: {
|
|
create: {
|
|
memberId: user.id,
|
|
captain: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
export async function like({
|
|
likerId,
|
|
targetId,
|
|
}: {
|
|
likerId: string;
|
|
targetId: string;
|
|
}) {
|
|
try {
|
|
// not transaction because doesn't really matter
|
|
// if only one goes through and other not
|
|
await Promise.all([
|
|
db.lfgGroupLike.create({
|
|
data: {
|
|
likerId,
|
|
targetId,
|
|
},
|
|
}),
|
|
db.lfgGroup.update({
|
|
where: { id: likerId },
|
|
data: {
|
|
lastActionAt: new Date(),
|
|
},
|
|
}),
|
|
]);
|
|
} catch (e) {
|
|
// No need for any errors if e.g. duplicate entry was tried or
|
|
// liked user stopped looking
|
|
if (e instanceof PrismaClientKnownRequestError) return;
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
export function unlike({
|
|
likerId,
|
|
targetId,
|
|
}: {
|
|
likerId: string;
|
|
targetId: string;
|
|
}) {
|
|
// not transaction because doesn't really matter
|
|
// if only one goes through and other not
|
|
return Promise.all([
|
|
db.lfgGroupLike.delete({
|
|
where: {
|
|
likerId_targetId: {
|
|
likerId,
|
|
targetId,
|
|
},
|
|
},
|
|
}),
|
|
db.lfgGroup.update({
|
|
where: { id: likerId },
|
|
data: {
|
|
lastActionAt: new Date(),
|
|
},
|
|
}),
|
|
]);
|
|
}
|
|
|
|
export function addMember({
|
|
userId,
|
|
groupId,
|
|
}: {
|
|
userId: string;
|
|
groupId: string;
|
|
}) {
|
|
return db.lfgGroup.update({
|
|
where: { id: groupId },
|
|
data: {
|
|
members: {
|
|
create: {
|
|
memberId: userId,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
export interface UniteGroupsArgs {
|
|
survivingGroupId: string;
|
|
otherGroupId: string;
|
|
removeCaptainsFromOther: boolean;
|
|
unitedGroupIsRanked?: boolean;
|
|
}
|
|
export function uniteGroups({
|
|
survivingGroupId,
|
|
otherGroupId,
|
|
removeCaptainsFromOther,
|
|
unitedGroupIsRanked,
|
|
}: UniteGroupsArgs) {
|
|
return db.$transaction([
|
|
db.lfgGroupMember.updateMany({
|
|
where: { groupId: otherGroupId },
|
|
data: {
|
|
groupId: survivingGroupId,
|
|
captain: removeCaptainsFromOther ? false : undefined,
|
|
// TODO: also reset message
|
|
},
|
|
}),
|
|
db.lfgGroup.delete({ where: { id: otherGroupId } }),
|
|
db.lfgGroupLike.deleteMany({
|
|
where: {
|
|
OR: [{ likerId: survivingGroupId }, { targetId: survivingGroupId }],
|
|
},
|
|
}),
|
|
db.lfgGroup.update({
|
|
where: { id: survivingGroupId },
|
|
data:
|
|
typeof unitedGroupIsRanked === "boolean"
|
|
? { ranked: unitedGroupIsRanked, lastActionAt: new Date() }
|
|
: { lastActionAt: new Date() },
|
|
}),
|
|
]);
|
|
}
|
|
|
|
export async function matchUp({
|
|
groupIds,
|
|
ranked,
|
|
}: {
|
|
groupIds: [string, string];
|
|
ranked?: boolean;
|
|
}) {
|
|
const match = await db.lfgGroupMatch.create({
|
|
data: {
|
|
stages: ranked
|
|
? {
|
|
createMany: {
|
|
data: generateMapListForLfgMatch(),
|
|
},
|
|
}
|
|
: undefined,
|
|
},
|
|
});
|
|
|
|
await db.lfgGroup.updateMany({
|
|
where: {
|
|
id: {
|
|
in: groupIds,
|
|
},
|
|
},
|
|
data: {
|
|
matchId: match.id,
|
|
status: "MATCH",
|
|
},
|
|
});
|
|
|
|
return match;
|
|
}
|
|
|
|
export function findByInviteCode(inviteCode: string) {
|
|
return db.lfgGroup.findFirst({
|
|
where: {
|
|
inviteCode,
|
|
status: "PRE_ADD",
|
|
},
|
|
include: {
|
|
members: {
|
|
include: {
|
|
user: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
export function findById(id: string) {
|
|
return db.lfgGroup.findUnique({ where: { id }, include: { members: true } });
|
|
}
|
|
|
|
export type FindActiveByMember = Prisma.PromiseReturnType<
|
|
typeof findActiveByMember
|
|
>;
|
|
export function findActiveByMember(user: { id: string }) {
|
|
return db.lfgGroup.findFirst({
|
|
where: {
|
|
status: {
|
|
not: "INACTIVE",
|
|
},
|
|
members: {
|
|
some: {
|
|
memberId: user.id,
|
|
},
|
|
},
|
|
},
|
|
include: {
|
|
members: { include: { user: true } },
|
|
likedGroups: {
|
|
select: {
|
|
targetId: true,
|
|
},
|
|
},
|
|
likesReceived: {
|
|
select: {
|
|
likerId: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
export type FindLookingAndOwnActive = Prisma.PromiseReturnType<
|
|
typeof findLookingAndOwnActive
|
|
>["groups"];
|
|
export async function findLookingAndOwnActive(
|
|
userId?: string,
|
|
showPreAddMatch = false
|
|
) {
|
|
const mainFilter = showPreAddMatch
|
|
? {
|
|
NOT: {
|
|
status: "INACTIVE" as const,
|
|
},
|
|
}
|
|
: {
|
|
status: "LOOKING" as const,
|
|
};
|
|
const where = userId
|
|
? {
|
|
OR: [
|
|
mainFilter,
|
|
{
|
|
members: {
|
|
some: {
|
|
memberId: userId,
|
|
},
|
|
},
|
|
NOT: {
|
|
status: "INACTIVE" as const,
|
|
},
|
|
},
|
|
],
|
|
}
|
|
: mainFilter;
|
|
const groups = await db.lfgGroup.findMany({
|
|
where,
|
|
include: {
|
|
members: {
|
|
include: {
|
|
user: {
|
|
include: {
|
|
skill: {
|
|
orderBy: {
|
|
createdAt: "desc",
|
|
},
|
|
distinct: "userId",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
likedGroups: true,
|
|
likesReceived: true,
|
|
},
|
|
orderBy: {
|
|
createdAt: "desc",
|
|
},
|
|
});
|
|
|
|
const ownGroup = groups.find((g) =>
|
|
g.members.some((m) => m.user.id === userId)
|
|
);
|
|
|
|
return { groups, ownGroup };
|
|
}
|
|
|
|
export function startLooking(id: string) {
|
|
return db.lfgGroup.update({
|
|
where: {
|
|
id,
|
|
},
|
|
data: {
|
|
status: "LOOKING",
|
|
},
|
|
});
|
|
}
|
|
|
|
export function setInactive(id: string) {
|
|
return db.lfgGroup.update({
|
|
where: {
|
|
id,
|
|
},
|
|
data: {
|
|
status: "INACTIVE",
|
|
},
|
|
});
|
|
}
|
|
|
|
export function leaveGroup({
|
|
groupId,
|
|
memberId,
|
|
}: {
|
|
groupId: string;
|
|
memberId: string;
|
|
}) {
|
|
// delete many so we don't throw in case
|
|
// the group was just integrated into another
|
|
// group
|
|
return db.lfgGroupMember.deleteMany({
|
|
where: {
|
|
groupId,
|
|
memberId,
|
|
// no escaping group if match has been formed
|
|
group: {
|
|
matchId: null,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
export function unexpire(groupId: string) {
|
|
return db.lfgGroup.update({
|
|
where: {
|
|
id: groupId,
|
|
},
|
|
data: {
|
|
lastActionAt: new Date(),
|
|
},
|
|
});
|
|
}
|