mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-03-21 18:04:39 -05:00
Unify db type files
This commit is contained in:
parent
3d5de9e44a
commit
c0ec15b7de
|
|
@ -1,6 +1,6 @@
|
|||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import type { User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { BLANK_IMAGE_URL, discordAvatarUrl } from "~/utils/urls";
|
||||
|
||||
const dimensions = {
|
||||
|
|
@ -21,7 +21,7 @@ function _Avatar({
|
|||
alt = "",
|
||||
...rest
|
||||
}: {
|
||||
user?: Pick<User, "discordId" | "discordAvatar">;
|
||||
user?: Pick<Tables["User"], "discordId" | "discordAvatar">;
|
||||
url?: string;
|
||||
className?: string;
|
||||
alt?: string;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
import clsx from "clsx";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import type {
|
||||
Build,
|
||||
BuildWeapon,
|
||||
GearType,
|
||||
UserWithPlusTier,
|
||||
} from "~/db/types";
|
||||
import type { GearType, Tables, UserWithPlusTier } from "~/db/tables";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import type { BuildWeaponWithTop500Info } from "~/features/builds/queries/buildsBy.server";
|
||||
import { useIsMounted } from "~/hooks/useIsMounted";
|
||||
|
|
@ -41,7 +36,7 @@ import { TrashIcon } from "./icons/Trash";
|
|||
|
||||
interface BuildProps {
|
||||
build: Pick<
|
||||
Build,
|
||||
Tables["Build"],
|
||||
| "id"
|
||||
| "title"
|
||||
| "description"
|
||||
|
|
@ -55,7 +50,7 @@ interface BuildProps {
|
|||
unsortedAbilities: BuildAbilitiesTuple;
|
||||
modes: ModeShort[] | null;
|
||||
weapons: Array<{
|
||||
weaponSplId: BuildWeapon["weaponSplId"];
|
||||
weaponSplId: Tables["BuildWeapon"]["weaponSplId"];
|
||||
minRank: number | null;
|
||||
maxPower: number | null;
|
||||
}>;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import clsx from "clsx";
|
|||
import Fuse, { type IFuseOptions } from "fuse.js";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { GearType } from "~/db/types";
|
||||
import type { GearType } from "~/db/tables";
|
||||
import type { SerializedMapPoolEvent } from "~/features/calendar/routes/map-pool-events";
|
||||
import { useAllEventsWithMapPools } from "~/hooks/swr";
|
||||
import type { MainWeaponId } from "~/modules/in-game-lists";
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Image } from "~/components/Image";
|
||||
import type { CalendarEvent } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { SerializedMapPoolEvent } from "~/features/calendar/routes/map-pool-events";
|
||||
import { MapPool } from "~/features/map-list-generator/core/map-pool";
|
||||
import { BANNED_MAPS } from "~/features/sendouq-settings/banned-maps";
|
||||
|
|
@ -26,11 +26,11 @@ export type MapPoolSelectorProps = {
|
|||
handleRemoval?: () => void;
|
||||
handleMapPoolChange: (
|
||||
mapPool: MapPool,
|
||||
event?: Pick<CalendarEvent, "id" | "name">,
|
||||
event?: Pick<Tables["CalendarEvent"], "id" | "name">,
|
||||
) => void;
|
||||
className?: string;
|
||||
recentEvents?: SerializedMapPoolEvent[];
|
||||
initialEvent?: Pick<CalendarEvent, "id" | "name">;
|
||||
initialEvent?: Pick<Tables["CalendarEvent"], "id" | "name">;
|
||||
title?: string;
|
||||
modesToInclude?: ModeShort[];
|
||||
info?: React.ReactNode;
|
||||
|
|
@ -376,7 +376,7 @@ function detectTemplate(mapPool: MapPool): MapPoolTemplateValue {
|
|||
type MapPoolTemplateSelectProps = {
|
||||
value: MapPoolTemplateValue;
|
||||
handleChange: (newValue: MapPoolTemplateValue) => void;
|
||||
recentEvents?: Pick<CalendarEvent, "id" | "name">[];
|
||||
recentEvents?: Pick<Tables["CalendarEvent"], "id" | "name">[];
|
||||
};
|
||||
|
||||
function MapPoolTemplateSelect({
|
||||
|
|
@ -428,7 +428,7 @@ function MapPoolTemplateSelect({
|
|||
type TemplateEventSelectionProps = {
|
||||
handleEventChange: (
|
||||
mapPool: MapPool,
|
||||
event?: Pick<CalendarEvent, "id" | "name">,
|
||||
event?: Pick<Tables["CalendarEvent"], "id" | "name">,
|
||||
) => void;
|
||||
initialEvent?: SerializedMapPoolEvent;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ import { dateToDatabaseTimestamp } from "~/utils/dates";
|
|||
import invariant from "~/utils/invariant";
|
||||
import { mySlugify } from "~/utils/urls";
|
||||
import type { Tables, UserMapModePreferences } from "../tables";
|
||||
import type { Art, UserSubmittedImage } from "../types";
|
||||
import {
|
||||
ADMIN_TEST_AVATAR,
|
||||
AMOUNT_OF_CALENDAR_EVENTS,
|
||||
|
|
@ -1950,12 +1949,12 @@ function arts() {
|
|||
validatedAt: dateToDatabaseTimestamp(new Date()),
|
||||
url: getUrl(),
|
||||
submitterUserId: userId,
|
||||
}) as UserSubmittedImage
|
||||
}) as Tables["UserSubmittedImage"]
|
||||
).id,
|
||||
authorId: userId,
|
||||
isShowcase: i === 0 ? 1 : 0,
|
||||
description: Math.random() > 0.5 ? faker.lorem.paragraph() : null,
|
||||
}) as Art;
|
||||
}) as Tables["Art"];
|
||||
|
||||
if (i === 1) {
|
||||
for (
|
||||
|
|
@ -2204,7 +2203,7 @@ async function playedMatches() {
|
|||
skills: newSkills,
|
||||
differences,
|
||||
groupMatchId: match.id,
|
||||
oldMatchMemento: { users: {}, groups: {} },
|
||||
oldMatchMemento: { users: {}, groups: {}, pools: [] },
|
||||
});
|
||||
setGroupAsInactive(groupAlpha);
|
||||
setGroupAsInactive(groupBravo);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ import type {
|
|||
SqlBool,
|
||||
Updateable,
|
||||
} from "kysely";
|
||||
import type {
|
||||
persistedTags,
|
||||
tags,
|
||||
} from "~/features/calendar/calendar-constants";
|
||||
import type { TieredSkill } from "~/features/mmr/tiered.server";
|
||||
import type { Notification as NotificationValue } from "~/features/notifications/notifications-types";
|
||||
import type { TEAM_MEMBER_ROLES } from "~/features/team/team-constants";
|
||||
|
|
@ -17,7 +21,6 @@ import type {
|
|||
ModeShort,
|
||||
StageId,
|
||||
} from "~/modules/in-game-lists";
|
||||
import type { GroupSkillDifference, UserSkillDifference } from "./types";
|
||||
|
||||
export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
|
||||
? ColumnType<S, I | undefined, U>
|
||||
|
|
@ -103,10 +106,12 @@ export interface Build {
|
|||
updatedAt: Generated<number>;
|
||||
}
|
||||
|
||||
export type GearType = "HEAD" | "CLOTHES" | "SHOES";
|
||||
|
||||
export interface BuildAbility {
|
||||
ability: Ability;
|
||||
buildId: number;
|
||||
gearType: string;
|
||||
gearType: GearType;
|
||||
slotIndex: number;
|
||||
}
|
||||
|
||||
|
|
@ -121,6 +126,9 @@ export type CalendarEventAvatarMetadata = {
|
|||
textColor: string;
|
||||
};
|
||||
|
||||
export type PersistedCalendarEventTag = keyof typeof persistedTags;
|
||||
export type CalendarEventTag = keyof typeof tags;
|
||||
|
||||
export interface CalendarEvent {
|
||||
authorId: number;
|
||||
bracketUrl: string;
|
||||
|
|
@ -189,6 +197,27 @@ export interface GroupLike {
|
|||
isRechallenge: number | null;
|
||||
}
|
||||
|
||||
type CalculatingSkill = {
|
||||
calculated: false;
|
||||
matchesCount: number;
|
||||
matchesCountNeeded: number;
|
||||
/** Freshly calculated skill */
|
||||
newSp?: number;
|
||||
};
|
||||
export type UserSkillDifference =
|
||||
| {
|
||||
calculated: true;
|
||||
spDiff: number;
|
||||
}
|
||||
| CalculatingSkill;
|
||||
export type GroupSkillDifference =
|
||||
| {
|
||||
calculated: true;
|
||||
oldSp: number;
|
||||
newSp: number;
|
||||
}
|
||||
| CalculatingSkill;
|
||||
|
||||
export type ParsedMemento = {
|
||||
users: Record<
|
||||
number,
|
||||
|
|
@ -359,7 +388,7 @@ export interface PlusVotingResult {
|
|||
export interface ReportedWeapon {
|
||||
groupMatchMapId: number | null;
|
||||
userId: number;
|
||||
weaponSplId: number;
|
||||
weaponSplId: MainWeaponId;
|
||||
}
|
||||
|
||||
export interface Skill {
|
||||
|
|
@ -492,6 +521,23 @@ export interface TournamentGroup {
|
|||
stageId: number;
|
||||
}
|
||||
|
||||
export const TournamentMatchStatus = {
|
||||
/** The two matches leading to this one are not completed yet. */
|
||||
Locked: 0,
|
||||
|
||||
/** One participant is ready and waiting for the other one. */
|
||||
Waiting: 1,
|
||||
|
||||
/** Both participants are ready to start. */
|
||||
Ready: 2,
|
||||
|
||||
/** The match is running. */
|
||||
Running: 3,
|
||||
|
||||
/** The match is completed. */
|
||||
Completed: 4,
|
||||
};
|
||||
|
||||
export interface TournamentMatch {
|
||||
// TODO: remove
|
||||
bestOf: Generated<3 | 5 | 7>;
|
||||
|
|
@ -503,7 +549,7 @@ export interface TournamentMatch {
|
|||
opponentTwo: ColumnType<ParticipantResult, string, string>;
|
||||
roundId: number;
|
||||
stageId: number;
|
||||
status: number;
|
||||
status: (typeof TournamentMatchStatus)[keyof typeof TournamentMatchStatus];
|
||||
// used only for swiss because it's the only stage type where matches are not created in advance
|
||||
createdAt: Generated<number>;
|
||||
}
|
||||
|
|
@ -807,6 +853,11 @@ export interface User {
|
|||
preferences: ColumnType<UserPreferences | null, string | null, string | null>;
|
||||
}
|
||||
|
||||
/** Represents User joined with PlusTier table */
|
||||
export type UserWithPlusTier = Tables["User"] & {
|
||||
plusTier: PlusTier["tier"] | null;
|
||||
};
|
||||
|
||||
export interface UserResultHighlight {
|
||||
teamId: number;
|
||||
userId: number;
|
||||
|
|
@ -815,7 +866,7 @@ export interface UserResultHighlight {
|
|||
export interface UserSubmittedImage {
|
||||
id: GeneratedAlways<number>;
|
||||
submitterUserId: number | null;
|
||||
url: string | null;
|
||||
url: string;
|
||||
validatedAt: number | null;
|
||||
}
|
||||
|
||||
|
|
@ -837,12 +888,12 @@ export interface UserFriendCode {
|
|||
export interface Video {
|
||||
eventId: number | null;
|
||||
id: GeneratedAlways<number>;
|
||||
submitterUserId: number | null;
|
||||
title: string | null;
|
||||
type: string | null;
|
||||
submitterUserId: number;
|
||||
title: string;
|
||||
type: "SCRIM" | "TOURNAMENT" | "MATCHMAKING" | "CAST" | "SENDOUQ";
|
||||
validatedAt: number | null;
|
||||
youtubeDate: number | null;
|
||||
youtubeId: string | null;
|
||||
youtubeDate: number;
|
||||
youtubeId: string;
|
||||
}
|
||||
|
||||
export interface VideoMatch {
|
||||
|
|
@ -872,7 +923,7 @@ export interface XRankPlacement {
|
|||
playerId: number;
|
||||
power: number;
|
||||
rank: number;
|
||||
region: string;
|
||||
region: "WEST" | "JPN";
|
||||
title: string;
|
||||
weaponSplId: MainWeaponId;
|
||||
year: number;
|
||||
|
|
|
|||
602
app/db/types.ts
602
app/db/types.ts
|
|
@ -1,602 +0,0 @@
|
|||
import type {
|
||||
persistedTags,
|
||||
tags,
|
||||
} from "~/features/calendar/calendar-constants";
|
||||
import type { TieredSkill } from "~/features/mmr/tiered.server";
|
||||
import type { TEAM_MEMBER_ROLES } from "~/features/team/team-constants";
|
||||
import type {
|
||||
Ability,
|
||||
MainWeaponId,
|
||||
ModeShort,
|
||||
RankedModeShort,
|
||||
StageId,
|
||||
} from "~/modules/in-game-lists";
|
||||
|
||||
export interface User {
|
||||
id: number;
|
||||
discordId: string;
|
||||
/** Discord display name aka global name (non-unique) */
|
||||
discordName: string;
|
||||
username: string;
|
||||
discordAvatar: string | null;
|
||||
/** Discord username (unique) */
|
||||
discordUniqueName: string | null;
|
||||
showDiscordUniqueName: number;
|
||||
twitch: string | null;
|
||||
youtubeId: string | null;
|
||||
bio: string | null;
|
||||
css: string | null;
|
||||
country: string | null;
|
||||
customUrl: string | null;
|
||||
stickSens: number | null;
|
||||
motionSens: number | null;
|
||||
inGameName: string | null;
|
||||
patronTier: number | null;
|
||||
patronSince: number | null;
|
||||
/** Used to overwrite normal patron giving process and force give the patron status till this date */
|
||||
patronTill: number | null;
|
||||
isVideoAdder: number;
|
||||
isArtist: number;
|
||||
favoriteBadgeId: number | null;
|
||||
commissionsOpen: number;
|
||||
commissionText: string | null;
|
||||
banned: number;
|
||||
vc: "YES" | "NO" | "LISTEN_ONLY";
|
||||
languages: string | null;
|
||||
}
|
||||
|
||||
/** User table after joined with PlusTier table */
|
||||
export interface UserWithPlusTier extends User {
|
||||
plusTier: PlusTier["tier"] | null;
|
||||
}
|
||||
|
||||
export interface UserWeapon {
|
||||
userId: number;
|
||||
weaponSplId: MainWeaponId;
|
||||
createdAt: number;
|
||||
order: number;
|
||||
isFavorite: number;
|
||||
}
|
||||
|
||||
export interface LogInLink {
|
||||
code: string;
|
||||
expiresAt: number;
|
||||
userId: number;
|
||||
}
|
||||
|
||||
export interface PlusSuggestion {
|
||||
id: number;
|
||||
text: string;
|
||||
authorId: number;
|
||||
suggestedId: number;
|
||||
month: number;
|
||||
year: number;
|
||||
tier: number;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
export interface PlusVote {
|
||||
month: number;
|
||||
year: number;
|
||||
tier: number;
|
||||
authorId: number;
|
||||
votedId: number;
|
||||
score: number;
|
||||
validAfter: number;
|
||||
}
|
||||
|
||||
export interface PlusVotingResult {
|
||||
votedId: number;
|
||||
tier: number;
|
||||
score: number;
|
||||
month: number;
|
||||
year: number;
|
||||
wasSuggested: number;
|
||||
passedVoting: number;
|
||||
}
|
||||
|
||||
export interface PlusTier {
|
||||
userId: number;
|
||||
tier: number;
|
||||
}
|
||||
|
||||
export interface Badge {
|
||||
id: number;
|
||||
code: string;
|
||||
displayName: string;
|
||||
hue?: number;
|
||||
}
|
||||
|
||||
/** View that is union of TournamentBadgeOwner and Patreon badges */
|
||||
export interface BadgeOwner {
|
||||
badgeId: number;
|
||||
userId: number;
|
||||
}
|
||||
|
||||
export interface TournamentBadgeOwner {
|
||||
badgeId: number;
|
||||
userId: number;
|
||||
}
|
||||
|
||||
export interface BadgeManager {
|
||||
badgeId: number;
|
||||
userId: number;
|
||||
}
|
||||
|
||||
export interface CalendarEvent {
|
||||
id: number;
|
||||
name: string;
|
||||
authorId: number;
|
||||
tags: string | null;
|
||||
description: string | null;
|
||||
discordInviteCode: string | null;
|
||||
// generated column
|
||||
discordUrl: string | null;
|
||||
bracketUrl: string;
|
||||
participantCount: number | null;
|
||||
tournamentId: number | null;
|
||||
}
|
||||
|
||||
export type PersistedCalendarEventTag = keyof typeof persistedTags;
|
||||
export type CalendarEventTag = keyof typeof tags;
|
||||
|
||||
export interface CalendarEventDate {
|
||||
id: number;
|
||||
eventId: number;
|
||||
startTime: number;
|
||||
}
|
||||
|
||||
export interface CalendarEventResultTeam {
|
||||
id: number;
|
||||
eventId: number;
|
||||
name: string;
|
||||
placement: number;
|
||||
}
|
||||
|
||||
export interface CalendarEventResultPlayer {
|
||||
teamId: number;
|
||||
userId: number | null;
|
||||
name: string | null;
|
||||
}
|
||||
|
||||
export interface UserResultHighlight {
|
||||
teamId: number;
|
||||
userId: number;
|
||||
}
|
||||
|
||||
export interface CalendarEventBadge {
|
||||
eventId: number;
|
||||
badgeId: number;
|
||||
}
|
||||
|
||||
export interface Build {
|
||||
id: number;
|
||||
ownerId: number;
|
||||
title: string;
|
||||
/** Private builds are only visible on the user builds page to the owner only */
|
||||
private: number | null;
|
||||
description: string | null;
|
||||
modes: string | null;
|
||||
headGearSplId: number;
|
||||
clothesGearSplId: number;
|
||||
shoesGearSplId: number;
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
export interface BuildWeapon {
|
||||
buildId: number;
|
||||
weaponSplId: MainWeaponId;
|
||||
}
|
||||
|
||||
export type GearType = "HEAD" | "CLOTHES" | "SHOES";
|
||||
|
||||
export interface BuildAbility {
|
||||
buildId: number;
|
||||
gearType: "HEAD" | "CLOTHES" | "SHOES";
|
||||
ability: Ability;
|
||||
slotIndex: 0 | 1 | 2 | 3;
|
||||
abilityPoints: number; // 3 or 10
|
||||
}
|
||||
|
||||
export interface MapPoolMap {
|
||||
calendarEventId: number | null; // Part of tournament's map pool
|
||||
tournamentTeamId: number | null; // Part of team's map pool
|
||||
tieBreakerCalendarEventId: number | null; // Part of the tournament's tiebreaker pool
|
||||
stageId: StageId;
|
||||
mode: ModeShort;
|
||||
}
|
||||
|
||||
// AUTO = style where teams pick their map pool ahead of time and the map lists are automatically made for each round
|
||||
// could also have the traditional style where TO picks the maps later
|
||||
type TournamentMapPickingStyle =
|
||||
| "AUTO_ALL"
|
||||
| "AUTO_SZ"
|
||||
| "AUTO_TC"
|
||||
| "AUTO_RM"
|
||||
| "AUTO_CB";
|
||||
|
||||
// TODO: later also e.g. RR_TO_DE where we also need an additional field
|
||||
// describing how many teams advance
|
||||
export type TournamentFormat = "SE" | "DE";
|
||||
|
||||
export interface Tournament {
|
||||
id: number;
|
||||
mapPickingStyle: TournamentMapPickingStyle;
|
||||
format: TournamentFormat;
|
||||
}
|
||||
|
||||
export interface TournamentTeam {
|
||||
id: number;
|
||||
name: string;
|
||||
createdAt: number;
|
||||
seed: number | null;
|
||||
tournamentId: number;
|
||||
inviteCode: string;
|
||||
prefersNotToHost: number;
|
||||
}
|
||||
|
||||
export interface TournamentTeamCheckIn {
|
||||
tournamentTeamId: number;
|
||||
checkedInAt: number;
|
||||
}
|
||||
|
||||
export interface TournamentTeamMember {
|
||||
tournamentTeamId: number;
|
||||
userId: number;
|
||||
isOwner: number;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
/** A stage is an intermediate phase in a tournament.
|
||||
* Supported stage types are round-robin, single elimination and double elimination. */
|
||||
export interface TournamentStage {
|
||||
id: number;
|
||||
tournamentId: number;
|
||||
name: string;
|
||||
type: "round_robin" | "single_elimination" | "double_elimination";
|
||||
settings: string; // json
|
||||
number: number;
|
||||
createdAt: number | null;
|
||||
}
|
||||
|
||||
/** A group is a logical structure used to group multiple rounds together.
|
||||
|
||||
- In round-robin stages, a group is a pool.
|
||||
- In elimination stages, a group is a bracket.
|
||||
- A single elimination stage can have one or two groups:
|
||||
- The unique bracket.
|
||||
- If enabled, the Consolation Final.
|
||||
- A double elimination stage can have two or three groups:
|
||||
- Upper and lower brackets.
|
||||
- If enabled, the Grand Final. */
|
||||
export interface TournamentGroup {
|
||||
id: number;
|
||||
stageId: number;
|
||||
/** In double elimination 1 = Winners, 2 = Losers, 3 = Grand Finals+Bracket Reset */
|
||||
number: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A round is a logical structure used to group multiple matches together.
|
||||
|
||||
- In round-robin stages, a round can be viewed as a day or just as a list of matches that can be played at the same time.
|
||||
- In elimination stages, a round is a round of a bracket, e.g. 8th finals, semi-finals, etc.
|
||||
*/
|
||||
export interface TournamentRound {
|
||||
id: number;
|
||||
stageId: number;
|
||||
groupId: number;
|
||||
number: number;
|
||||
}
|
||||
|
||||
export enum Status {
|
||||
/** The two matches leading to this one are not completed yet. */
|
||||
Locked = 0,
|
||||
|
||||
/** One participant is ready and waiting for the other one. */
|
||||
Waiting = 1,
|
||||
|
||||
/** Both participants are ready to start. */
|
||||
Ready = 2,
|
||||
|
||||
/** The match is running. */
|
||||
Running = 3,
|
||||
|
||||
/** The match is completed. */
|
||||
Completed = 4,
|
||||
}
|
||||
|
||||
/** A match between two participants (more participants are not allowed).
|
||||
* Participants can be teams or individuals. */
|
||||
export interface TournamentMatch {
|
||||
id: number;
|
||||
bestOf: 3 | 5 | 7;
|
||||
roundId: number;
|
||||
stageId: number;
|
||||
groupId: number;
|
||||
number: number;
|
||||
opponentOne: string; // json
|
||||
opponentTwo: string; // json
|
||||
status: Status;
|
||||
chatCode: string | null;
|
||||
}
|
||||
|
||||
export interface TournamentMatchGameResult {
|
||||
id: number;
|
||||
matchId: number;
|
||||
number: number;
|
||||
stageId: StageId;
|
||||
mode: ModeShort;
|
||||
/** serialized TournamentMaplistSource */
|
||||
source: string;
|
||||
winnerTeamId: number;
|
||||
reporterId: number;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
export interface TournamentMatchGameResultParticipant {
|
||||
matchGameResultId: number;
|
||||
userId: number;
|
||||
}
|
||||
|
||||
export interface TournamentSub {
|
||||
userId: number;
|
||||
tournamentId: number;
|
||||
canVc: number;
|
||||
bestWeapons: string;
|
||||
okWeapons: string | null;
|
||||
message: string | null;
|
||||
visibility: "+1" | "+2" | "+3" | "ALL";
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
export interface Skill {
|
||||
id: number;
|
||||
mu: number;
|
||||
sigma: number;
|
||||
ordinal: number;
|
||||
userId: number | null;
|
||||
/** e.g. 12-24-44-1024 for "team skills" */
|
||||
identifier: string | null;
|
||||
matchesCount: number;
|
||||
/** Tournament that caused the skill to change */
|
||||
tournamentId: number | null;
|
||||
/** Group match that caused the skill to change */
|
||||
groupMatchId: number | null;
|
||||
season: number;
|
||||
}
|
||||
|
||||
export interface SkillTeamUser {
|
||||
userId: number;
|
||||
skillId: number;
|
||||
}
|
||||
|
||||
export interface MapResult {
|
||||
mode: ModeShort;
|
||||
stageId: StageId;
|
||||
userId: number;
|
||||
wins: number;
|
||||
losses: number;
|
||||
season: number;
|
||||
}
|
||||
|
||||
export interface PlayerResult {
|
||||
ownerUserId: number;
|
||||
otherUserId: number;
|
||||
mapWins: number;
|
||||
mapLosses: number;
|
||||
setWins: number;
|
||||
setLosses: number;
|
||||
type: "MATE" | "ENEMY";
|
||||
season: number;
|
||||
}
|
||||
|
||||
export interface TournamentResult {
|
||||
tournamentId: number;
|
||||
userId: number;
|
||||
placement: number;
|
||||
participantCount: number;
|
||||
tournamentTeamId: number;
|
||||
isHighlight: number;
|
||||
}
|
||||
|
||||
export interface TrustRelationship {
|
||||
trustGiverUserId: number;
|
||||
trustReceiverUserId: number;
|
||||
}
|
||||
|
||||
export interface UserSubmittedImage {
|
||||
id: number;
|
||||
validatedAt: number | null;
|
||||
url: string;
|
||||
submitterUserId: number;
|
||||
}
|
||||
|
||||
export interface Team {
|
||||
id: number;
|
||||
name: string;
|
||||
customUrl: string;
|
||||
inviteCode: string;
|
||||
css: string | null;
|
||||
bio: string | null;
|
||||
avatarImgId: number | null;
|
||||
bannerImgId: number | null;
|
||||
createdAt: number;
|
||||
deletedAt: number | null;
|
||||
}
|
||||
|
||||
export type MemberRole = (typeof TEAM_MEMBER_ROLES)[number];
|
||||
|
||||
export interface TeamMember {
|
||||
teamId: number;
|
||||
userId: number;
|
||||
role: MemberRole | null;
|
||||
isOwner: number;
|
||||
createdAt: number;
|
||||
leftAt: number | null;
|
||||
}
|
||||
|
||||
export interface Video {
|
||||
id: number;
|
||||
title: string;
|
||||
type: "SCRIM" | "TOURNAMENT" | "MATCHMAKING" | "CAST" | "SENDOUQ";
|
||||
youtubeDate: number;
|
||||
eventId: number | null;
|
||||
youtubeId: string;
|
||||
submitterUserId: number;
|
||||
validatedAt: number | null;
|
||||
}
|
||||
|
||||
export interface VideoMatch {
|
||||
id: number;
|
||||
videoId: number;
|
||||
startsAt: number;
|
||||
stageId: StageId;
|
||||
mode: ModeShort;
|
||||
}
|
||||
|
||||
export interface VideoMatchPlayer {
|
||||
videoMatchId: number;
|
||||
playerUserId: number | null;
|
||||
playerName: string | null;
|
||||
weaponSplId: MainWeaponId;
|
||||
player: number;
|
||||
}
|
||||
|
||||
export interface XRankPlacement {
|
||||
id: number;
|
||||
weaponSplId: MainWeaponId;
|
||||
name: string;
|
||||
nameDiscriminator: string;
|
||||
power: number;
|
||||
rank: number;
|
||||
title: string;
|
||||
badges: string; // badge id's separated by comma
|
||||
bannerSplId: number;
|
||||
playerId: number;
|
||||
month: number;
|
||||
year: number;
|
||||
mode: RankedModeShort;
|
||||
region: "WEST" | "JPN";
|
||||
}
|
||||
|
||||
export interface SplatoonPlayer {
|
||||
id: number;
|
||||
userId: number;
|
||||
splId: string;
|
||||
}
|
||||
|
||||
export interface Art {
|
||||
id: number;
|
||||
imgId: number;
|
||||
authorId: number;
|
||||
isShowcase: number;
|
||||
description: string | null;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
export interface ArtTag {
|
||||
id: number;
|
||||
name: string;
|
||||
authorId: number;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
export interface TaggedArt {
|
||||
artId: number;
|
||||
tagId: number;
|
||||
}
|
||||
|
||||
export interface ArtUserMetadata {
|
||||
artId: number;
|
||||
userId: number;
|
||||
}
|
||||
|
||||
export interface Group {
|
||||
id: number;
|
||||
teamId: number | null;
|
||||
createdAt: number;
|
||||
latestActionAt: number;
|
||||
inviteCode: string;
|
||||
chatCode: string | null;
|
||||
status: "PREPARING" | "ACTIVE" | "INACTIVE";
|
||||
}
|
||||
|
||||
export interface GroupMember {
|
||||
groupId: number;
|
||||
userId: number;
|
||||
role: "OWNER" | "MANAGER" | "REGULAR";
|
||||
note: string | null;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
export interface GroupLike {
|
||||
likerGroupId: number;
|
||||
targetGroupId: number;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
type CalculatingSkill = {
|
||||
calculated: false;
|
||||
matchesCount: number;
|
||||
matchesCountNeeded: number;
|
||||
/** Freshly calculated skill */
|
||||
newSp?: number;
|
||||
};
|
||||
export type UserSkillDifference =
|
||||
| {
|
||||
calculated: true;
|
||||
spDiff: number;
|
||||
}
|
||||
| CalculatingSkill;
|
||||
export type GroupSkillDifference =
|
||||
| {
|
||||
calculated: true;
|
||||
oldSp: number;
|
||||
newSp: number;
|
||||
}
|
||||
| CalculatingSkill;
|
||||
export type ParsedMemento = {
|
||||
users: Record<
|
||||
User["id"],
|
||||
{
|
||||
plusTier?: PlusTier["tier"];
|
||||
skill?: TieredSkill;
|
||||
skillDifference?: UserSkillDifference;
|
||||
}
|
||||
>;
|
||||
groups: Record<
|
||||
Group["id"],
|
||||
{
|
||||
tier?: TieredSkill["tier"];
|
||||
skillDifference?: GroupSkillDifference;
|
||||
}
|
||||
>;
|
||||
};
|
||||
export interface GroupMatch {
|
||||
id: number;
|
||||
alphaGroupId: number;
|
||||
bravoGroupId: number;
|
||||
createdAt: number;
|
||||
reportedAt: number | null;
|
||||
reportedByUserId: number | null;
|
||||
chatCode: string | null;
|
||||
memento: string | null;
|
||||
}
|
||||
|
||||
export interface GroupMatchMap {
|
||||
id: number;
|
||||
matchId: number;
|
||||
index: number;
|
||||
mode: ModeShort;
|
||||
stageId: StageId;
|
||||
/** serialized TournamentMaplistSource */
|
||||
source: string;
|
||||
winnerGroupId: number | null;
|
||||
}
|
||||
|
||||
export interface ReportedWeapon {
|
||||
groupMatchMapId: number | null;
|
||||
weaponSplId: MainWeaponId;
|
||||
userId: User["id"];
|
||||
}
|
||||
|
|
@ -1,21 +1,21 @@
|
|||
import type { Art, User, UserSubmittedImage } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
export interface ListedArt {
|
||||
id: Art["id"];
|
||||
createdAt: Art["createdAt"];
|
||||
url: UserSubmittedImage["url"];
|
||||
description?: Art["description"];
|
||||
id: Tables["Art"]["id"];
|
||||
createdAt: Tables["Art"]["createdAt"];
|
||||
url: Tables["UserSubmittedImage"]["url"];
|
||||
description?: Tables["Art"]["description"];
|
||||
tags?: string[];
|
||||
linkedUsers?: Array<{
|
||||
discordId: User["discordId"];
|
||||
username: User["username"];
|
||||
customUrl: User["customUrl"];
|
||||
discordId: Tables["User"]["discordId"];
|
||||
username: Tables["User"]["username"];
|
||||
customUrl: Tables["User"]["customUrl"];
|
||||
}>;
|
||||
author?: {
|
||||
discordId: User["discordId"];
|
||||
username: User["username"];
|
||||
discordAvatar: User["discordAvatar"];
|
||||
commissionsOpen?: User["commissionsOpen"];
|
||||
discordId: Tables["User"]["discordId"];
|
||||
username: Tables["User"]["username"];
|
||||
discordAvatar: Tables["User"]["discordAvatar"];
|
||||
commissionsOpen?: Tables["User"]["commissionsOpen"];
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Art, ArtTag, UserSubmittedImage } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import invariant from "~/utils/invariant";
|
||||
|
||||
const addImgStm = sql.prepare(/* sql */ `
|
||||
|
|
@ -92,9 +92,9 @@ const removeUserMetadataStm = sql.prepare(/* sql */ `
|
|||
"artId" = @artId
|
||||
`);
|
||||
|
||||
type TagsToAdd = Array<Partial<Pick<ArtTag, "name" | "id">>>;
|
||||
type AddNewArtArgs = Pick<Art, "authorId" | "description"> &
|
||||
Pick<UserSubmittedImage, "url" | "validatedAt"> & {
|
||||
type TagsToAdd = Array<Partial<Pick<Tables["ArtTag"], "name" | "id">>>;
|
||||
type AddNewArtArgs = Pick<Tables["Art"], "authorId" | "description"> &
|
||||
Pick<Tables["UserSubmittedImage"], "url" | "validatedAt"> & {
|
||||
linkedUsers: number[];
|
||||
tags: TagsToAdd;
|
||||
};
|
||||
|
|
@ -104,12 +104,12 @@ export const addNewArt = sql.transaction((args: AddNewArtArgs) => {
|
|||
authorId: args.authorId,
|
||||
url: args.url,
|
||||
validatedAt: args.validatedAt,
|
||||
}) as UserSubmittedImage;
|
||||
}) as Tables["UserSubmittedImage"];
|
||||
const art = addArtStm.get({
|
||||
authorId: args.authorId,
|
||||
description: args.description,
|
||||
imgId: img.id,
|
||||
}) as Art;
|
||||
}) as Tables["Art"];
|
||||
|
||||
for (const userId of args.linkedUsers) {
|
||||
addArtUserMetadataStm.run({ artId: art.id, userId });
|
||||
|
|
@ -123,7 +123,7 @@ export const addNewArt = sql.transaction((args: AddNewArtArgs) => {
|
|||
const newTag = addArtTagStm.get({
|
||||
name: tag.name,
|
||||
authorId: args.authorId,
|
||||
}) as ArtTag;
|
||||
}) as Tables["ArtTag"];
|
||||
tagId = newTag.id;
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +133,10 @@ export const addNewArt = sql.transaction((args: AddNewArtArgs) => {
|
|||
return art.id;
|
||||
});
|
||||
|
||||
type EditArtArgs = Pick<Art, "authorId" | "description" | "isShowcase"> & {
|
||||
type EditArtArgs = Pick<
|
||||
Tables["Art"],
|
||||
"authorId" | "description" | "isShowcase"
|
||||
> & {
|
||||
linkedUsers: number[];
|
||||
artId: number;
|
||||
tags: TagsToAdd;
|
||||
|
|
@ -166,7 +169,7 @@ export const editArt = sql.transaction((args: EditArtArgs) => {
|
|||
const newTag = addArtTagStm.get({
|
||||
name: tag.name,
|
||||
authorId: args.authorId,
|
||||
}) as ArtTag;
|
||||
}) as Tables["ArtTag"];
|
||||
tagId = newTag.id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { ArtTag } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
select
|
||||
|
|
@ -9,6 +9,6 @@ const stm = sql.prepare(/* sql */ `
|
|||
"ArtTag"
|
||||
`);
|
||||
|
||||
export function allArtTags(): Array<Pick<ArtTag, "id" | "name">> {
|
||||
export function allArtTags(): Array<Pick<Tables["ArtTag"], "id" | "name">> {
|
||||
return stm.all() as any;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Art, ArtTag, User, UserSubmittedImage } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { parseDBArray } from "~/utils/sql";
|
||||
|
||||
const findArtStm = sql.prepare(/* sql */ `
|
||||
|
|
@ -26,12 +26,12 @@ const findTagsStm = sql.prepare(/* sql */ `
|
|||
`);
|
||||
|
||||
interface FindArtById {
|
||||
isShowcase: Art["isShowcase"];
|
||||
description: Art["description"];
|
||||
url: UserSubmittedImage["url"];
|
||||
authorId: Art["authorId"];
|
||||
linkedUsers: User["id"][];
|
||||
tags: Array<Pick<ArtTag, "id" | "name">>;
|
||||
isShowcase: Tables["Art"]["isShowcase"];
|
||||
description: Tables["Art"]["description"];
|
||||
url: Tables["UserSubmittedImage"]["url"];
|
||||
authorId: Tables["Art"]["authorId"];
|
||||
linkedUsers: Tables["User"]["id"][];
|
||||
tags: Array<Pick<Tables["ArtTag"], "id" | "name">>;
|
||||
}
|
||||
|
||||
export function findArtById(artId: number): FindArtById | null {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { ArtTag } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { ListedArt } from "../art-types";
|
||||
|
||||
const showcaseArtsStm = sql.prepare(/* sql */ `
|
||||
|
|
@ -55,7 +55,7 @@ const showcaseArtsByTagStm = sql.prepare(/* sql */ `
|
|||
|
||||
`);
|
||||
|
||||
export function showcaseArtsByTag(tagId: ArtTag["id"]): ListedArt[] {
|
||||
export function showcaseArtsByTag(tagId: Tables["ArtTag"]["id"]): ListedArt[] {
|
||||
const encounteredUserIds = new Set<number>();
|
||||
|
||||
return showcaseArtsByTagStm
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { redirect } from "@remix-run/node";
|
||||
import type { User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { userIsBanned } from "~/features/ban/core/banned.server";
|
||||
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
||||
import { SUSPENDED_PAGE } from "~/utils/urls";
|
||||
|
|
@ -9,7 +9,7 @@ import { authSessionStorage } from "./session.server";
|
|||
export async function getUserId(
|
||||
request: Request,
|
||||
redirectIfBanned = true,
|
||||
): Promise<Pick<User, "id"> | undefined> {
|
||||
): Promise<Pick<Tables["User"], "id"> | undefined> {
|
||||
const session = await authSessionStorage.getSession(
|
||||
request.headers.get("Cookie"),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { nanoid } from "nanoid";
|
||||
import { sql } from "~/db/sql";
|
||||
import type { LogInLink } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
|
|
@ -26,5 +26,5 @@ export function createLogInLink(userId: number) {
|
|||
new Date(Date.now() + LOG_IN_LINK_VALID_FOR),
|
||||
),
|
||||
code: nanoid(LOG_IN_LINK_LENGTH),
|
||||
}) as LogInLink;
|
||||
}) as Tables["LogInLink"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import type { TFunction } from "i18next";
|
||||
import { SPLATOON_3_XP_BADGE_VALUES } from "~/constants";
|
||||
import type { Badge as BadgeDBType } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
export function badgeExplanationText(
|
||||
t: TFunction<"badges", undefined>,
|
||||
badge: Pick<BadgeDBType, "displayName" | "code"> & { count?: number },
|
||||
badge: Pick<Tables["Badge"], "displayName" | "code"> & { count?: number },
|
||||
) {
|
||||
if (badge.code === "patreon") return t("patreon");
|
||||
if (badge.code === "patreon_plus") {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { Dialog } from "~/components/Dialog";
|
|||
import { Label } from "~/components/Label";
|
||||
import { UserSearch } from "~/components/UserSearch";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import type { User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { requireUserId } from "~/features/auth/core/user.server";
|
||||
import { notify } from "~/features/notifications/core/notify.server";
|
||||
|
|
@ -321,7 +321,7 @@ function getOwnerDifferences(
|
|||
oldOwners: BadgeRepository.FindOwnersByBadgeIdItem[],
|
||||
) {
|
||||
const result: Array<{
|
||||
id: User["id"];
|
||||
id: Tables["User"]["id"];
|
||||
type: "added" | "removed";
|
||||
difference: number;
|
||||
username: string;
|
||||
|
|
@ -353,7 +353,7 @@ function getOwnerDifferences(
|
|||
}
|
||||
|
||||
function countArrayToDuplicatedIdsArray(
|
||||
owners: Array<{ id: User["id"]; count: number }>,
|
||||
owners: Array<{ id: Tables["User"]["id"]; count: number }>,
|
||||
) {
|
||||
return owners.flatMap((o) => new Array(o.count).fill(null).map(() => o.id));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type {
|
||||
Build,
|
||||
BuildAbility,
|
||||
BuildWeapon,
|
||||
UserWithPlusTier,
|
||||
} from "~/db/types";
|
||||
import type { Tables, UserWithPlusTier } from "~/db/tables";
|
||||
import { type ModeShort, weaponIdToAltId } from "~/modules/in-game-lists";
|
||||
import type {
|
||||
BuildAbilitiesTuple,
|
||||
|
|
@ -120,7 +115,7 @@ export function buildsByWeaponId({
|
|||
weaponId,
|
||||
limit,
|
||||
}: {
|
||||
weaponId: BuildWeapon["weaponSplId"];
|
||||
weaponId: Tables["BuildWeapon"]["weaponSplId"];
|
||||
limit: number;
|
||||
}) {
|
||||
const [altWeaponId, altWeaponIdTwo] = (() => {
|
||||
|
|
@ -144,17 +139,17 @@ export function buildsByWeaponId({
|
|||
}
|
||||
|
||||
type BuildsByUserRow = Pick<
|
||||
Build,
|
||||
Tables["Build"],
|
||||
| "id"
|
||||
| "title"
|
||||
| "description"
|
||||
| "modes"
|
||||
| "headGearSplId"
|
||||
| "clothesGearSplId"
|
||||
| "shoesGearSplId"
|
||||
| "updatedAt"
|
||||
| "private"
|
||||
> & {
|
||||
modes: string;
|
||||
weapons: string;
|
||||
abilities: string;
|
||||
};
|
||||
|
|
@ -170,14 +165,14 @@ function augmentBuild<T>({
|
|||
modes: rawModes,
|
||||
abilities: rawAbilities,
|
||||
...row
|
||||
}: T & { modes: Build["modes"]; weapons: string; abilities: string }) {
|
||||
}: T & { modes: string; weapons: string; abilities: string }) {
|
||||
const modes = rawModes ? (JSON.parse(rawModes) as ModeShort[]) : null;
|
||||
const weapons = (
|
||||
JSON.parse(rawWeapons) as Array<BuildWeaponWithTop500Info>
|
||||
).sort((a, b) => a.weaponSplId - b.weaponSplId);
|
||||
const abilities = dbAbilitiesToArrayOfArrays(
|
||||
JSON.parse(rawAbilities) as Array<
|
||||
Pick<BuildAbility, "ability" | "gearType" | "slotIndex">
|
||||
Pick<Tables["BuildAbility"], "ability" | "gearType" | "slotIndex">
|
||||
>,
|
||||
);
|
||||
|
||||
|
|
@ -190,9 +185,15 @@ function augmentBuild<T>({
|
|||
};
|
||||
}
|
||||
|
||||
const gearOrder: Array<BuildAbility["gearType"]> = ["HEAD", "CLOTHES", "SHOES"];
|
||||
const gearOrder: Array<Tables["BuildAbility"]["gearType"]> = [
|
||||
"HEAD",
|
||||
"CLOTHES",
|
||||
"SHOES",
|
||||
];
|
||||
function dbAbilitiesToArrayOfArrays(
|
||||
abilities: Array<Pick<BuildAbility, "ability" | "gearType" | "slotIndex">>,
|
||||
abilities: Array<
|
||||
Pick<Tables["BuildAbility"], "ability" | "gearType" | "slotIndex">
|
||||
>,
|
||||
): BuildAbilitiesTuple {
|
||||
const sorted = abilities
|
||||
.slice()
|
||||
|
|
|
|||
|
|
@ -2,8 +2,13 @@ import type { Expression, ExpressionBuilder, Transaction } from "kysely";
|
|||
import { sql } from "kysely";
|
||||
import { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
||||
import { db } from "~/db/sql";
|
||||
import type { DB, Tables, TournamentSettings } from "~/db/tables";
|
||||
import type { CalendarEventTag, PersistedCalendarEventTag } from "~/db/types";
|
||||
import type {
|
||||
CalendarEventTag,
|
||||
DB,
|
||||
PersistedCalendarEventTag,
|
||||
Tables,
|
||||
TournamentSettings,
|
||||
} from "~/db/tables";
|
||||
import { MapPool } from "~/features/map-list-generator/core/map-pool";
|
||||
import * as Progression from "~/features/tournament-bracket/core/Progression";
|
||||
import { databaseTimestampNow, dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import type { ActionFunction } from "@remix-run/node";
|
||||
import { redirect } from "@remix-run/node";
|
||||
import { z } from "zod";
|
||||
import { TOURNAMENT_STAGE_TYPES } from "~/db/tables";
|
||||
import type { CalendarEventTag, PersistedCalendarEventTag } from "~/db/types";
|
||||
import {
|
||||
type CalendarEventTag,
|
||||
type PersistedCalendarEventTag,
|
||||
TOURNAMENT_STAGE_TYPES,
|
||||
} from "~/db/tables";
|
||||
import { requireUser } from "~/features/auth/core/user.server";
|
||||
import * as CalendarRepository from "~/features/calendar/CalendarRepository.server";
|
||||
import * as ShowcaseTournaments from "~/features/front-page/core/ShowcaseTournaments.server";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { CalendarEventTag, PersistedCalendarEventTag } from "~/db/types";
|
||||
import type { CalendarEventTag, PersistedCalendarEventTag } from "~/db/tables";
|
||||
|
||||
export const persistedTags = {
|
||||
SPECIAL: {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next";
|
|||
import { Badge } from "~/components/Badge";
|
||||
import { Button } from "~/components/Button";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import type { CalendarEventTag } from "~/db/types";
|
||||
import type { CalendarEventTag } from "~/db/tables";
|
||||
import type * as CalendarRepository from "../CalendarRepository.server";
|
||||
import { tags as allTags } from "../calendar-constants";
|
||||
|
||||
|
|
|
|||
|
|
@ -19,8 +19,7 @@ import { RequiredHiddenInput } from "~/components/RequiredHiddenInput";
|
|||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { Badge as BadgeType, CalendarEventTag } from "~/db/types";
|
||||
import type { CalendarEventTag, Tables } from "~/db/tables";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { MapPool } from "~/features/map-list-generator/core/map-pool";
|
||||
import * as Progression from "~/features/tournament-bracket/core/Progression";
|
||||
|
|
@ -641,7 +640,7 @@ function BadgesAdder() {
|
|||
|
||||
if (managedBadges.length === 0) return input;
|
||||
|
||||
const handleBadgeDelete = (badgeId: BadgeType["id"]) => {
|
||||
const handleBadgeDelete = (badgeId: Tables["Badge"]["id"]) => {
|
||||
setBadges(badges.filter((badge) => badge.id !== badgeId));
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -43,10 +43,6 @@ import {
|
|||
} from "~/utils/urls";
|
||||
import { actualNumber, safeSplit } from "~/utils/zod";
|
||||
import { Label } from "../../../components/Label";
|
||||
import type {
|
||||
CalendarEventTag,
|
||||
PersistedCalendarEventTag,
|
||||
} from "../../../db/types";
|
||||
import { metaTags } from "../../../utils/remix";
|
||||
import * as CalendarRepository from "../CalendarRepository.server";
|
||||
import { calendarEventTagSchema } from "../actions/calendar.new.server";
|
||||
|
|
@ -55,6 +51,7 @@ import { closeByWeeks } from "../calendar-utils";
|
|||
import { Tags } from "../components/Tags";
|
||||
import "~/styles/calendar.css";
|
||||
import { SendouSwitch } from "~/components/elements/Switch";
|
||||
import type { CalendarEventTag, PersistedCalendarEventTag } from "~/db/tables";
|
||||
|
||||
export const meta: MetaFunction = (args) => {
|
||||
const data = args.data as SerializeFrom<typeof loader> | null;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { nanoid } from "nanoid";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ReconnectingWebSocket from "reconnecting-websocket";
|
||||
import type { User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { logger } from "~/utils/logger";
|
||||
|
|
@ -17,7 +17,10 @@ import { useChatAutoScroll } from "../chat-hooks";
|
|||
import type { ChatMessage } from "../chat-types";
|
||||
import { messageTypeToSound, soundEnabled, soundVolume } from "../chat-utils";
|
||||
|
||||
type ChatUser = Pick<User, "username" | "discordId" | "discordAvatar"> & {
|
||||
type ChatUser = Pick<
|
||||
Tables["User"],
|
||||
"username" | "discordId" | "discordAvatar"
|
||||
> & {
|
||||
chatNameColor: string | null;
|
||||
title?: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { UserSubmittedImage } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { ImageUploadType } from "../upload-types";
|
||||
|
||||
const addImgStm = sql.prepare(/* sql */ `
|
||||
|
|
@ -48,7 +48,7 @@ export const addNewImage = sql.transaction(
|
|||
submitterUserId,
|
||||
url,
|
||||
validatedAt,
|
||||
}) as UserSubmittedImage;
|
||||
}) as Tables["UserSubmittedImage"];
|
||||
|
||||
if (type === "team-pfp") {
|
||||
updateTeamAvatarStm.run({ avatarImgId: img.id, teamId: teamId ?? null });
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { UserSubmittedImage } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
select
|
||||
|
|
@ -20,7 +20,7 @@ const stm = sql.prepare(/* sql */ `
|
|||
`);
|
||||
|
||||
type UnvalidatedImage = Pick<
|
||||
UserSubmittedImage,
|
||||
Tables["UserSubmittedImage"],
|
||||
"id" | "url" | "submitterUserId"
|
||||
>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { User, XRankPlacement } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { MainWeaponId } from "~/modules/in-game-lists";
|
||||
import { DEFAULT_LEADERBOARD_MAX_SIZE } from "../leaderboards-constants";
|
||||
|
||||
|
|
@ -41,13 +41,13 @@ const weaponStm = getStm(/* sql */ `
|
|||
export interface XPLeaderboardItem {
|
||||
entryId: number;
|
||||
power: number;
|
||||
id: User["id"];
|
||||
name: XRankPlacement["name"];
|
||||
playerId: XRankPlacement["playerId"];
|
||||
username: User["username"] | null;
|
||||
discordAvatar: User["discordAvatar"] | null;
|
||||
discordId: User["discordId"] | null;
|
||||
customUrl: User["customUrl"] | null;
|
||||
id: Tables["User"]["id"];
|
||||
name: Tables["XRankPlacement"]["name"];
|
||||
playerId: Tables["XRankPlacement"]["playerId"];
|
||||
username: Tables["User"]["username"] | null;
|
||||
discordAvatar: Tables["User"]["discordAvatar"] | null;
|
||||
discordId: Tables["User"]["discordId"] | null;
|
||||
customUrl: Tables["User"]["customUrl"] | null;
|
||||
placementRank: number;
|
||||
weaponSplId: MainWeaponId;
|
||||
}
|
||||
|
|
@ -57,7 +57,7 @@ export function allXPLeaderboard(): XPLeaderboardItem[] {
|
|||
}
|
||||
|
||||
export function modeXPLeaderboard(
|
||||
mode: XRankPlacement["mode"],
|
||||
mode: Tables["XRankPlacement"]["mode"],
|
||||
): XPLeaderboardItem[] {
|
||||
return modeStm.all({ mode }) as any[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { seasonObject } from "~/features/mmr/season";
|
||||
import type { MainWeaponId } from "~/modules/in-game-lists";
|
||||
import { dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
|
|
@ -26,7 +26,10 @@ const stm = sql.prepare(/* sql */ `
|
|||
group by "q1"."userId"
|
||||
`);
|
||||
|
||||
export type SeasonPopularUsersWeapon = Record<User["id"], MainWeaponId>;
|
||||
export type SeasonPopularUsersWeapon = Record<
|
||||
Tables["User"]["id"],
|
||||
MainWeaponId
|
||||
>;
|
||||
|
||||
export function seasonPopularUsersWeapon(
|
||||
season: number,
|
||||
|
|
@ -39,7 +42,7 @@ export function seasonPopularUsersWeapon(
|
|||
ends: dateToDatabaseTimestamp(ends),
|
||||
}) as Array<{
|
||||
count: number;
|
||||
userId: User["id"];
|
||||
userId: Tables["User"]["id"];
|
||||
weaponSplId: MainWeaponId;
|
||||
}>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { PlusTier, User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { ordinalToSp } from "~/features/mmr/mmr-utils";
|
||||
import { MATCHES_COUNT_NEEDED_FOR_LEADERBOARD } from "../leaderboards-constants";
|
||||
|
||||
|
|
@ -36,14 +36,14 @@ const stm = sql.prepare(/* sql */ `
|
|||
export interface UserSPLeaderboardItem {
|
||||
entryId: number;
|
||||
power: number;
|
||||
id: User["id"];
|
||||
username: User["username"];
|
||||
discordAvatar: User["discordAvatar"];
|
||||
discordId: User["discordId"];
|
||||
customUrl: User["customUrl"];
|
||||
id: Tables["User"]["id"];
|
||||
username: Tables["User"]["username"];
|
||||
discordAvatar: Tables["User"]["discordAvatar"];
|
||||
discordId: Tables["User"]["discordId"];
|
||||
customUrl: Tables["User"]["customUrl"];
|
||||
plusSkippedForSeasonNth: number | null;
|
||||
/** Plus tier player is on track to join */
|
||||
pendingPlusTier?: PlusTier["tier"];
|
||||
pendingPlusTier?: Tables["PlusTier"]["tier"];
|
||||
placementRank: number;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { MapPoolMap } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { ModeShort } from "../../../../modules/in-game-lists";
|
||||
import type { MapPool } from "../map-pool";
|
||||
import type { MapPoolObject } from "../map-pool-serializer/types";
|
||||
|
|
@ -16,7 +16,7 @@ export function mapPoolToNonEmptyModes(mapPool: MapPool) {
|
|||
}
|
||||
|
||||
export function mapPoolListToMapPoolObject(
|
||||
mapPoolList: Array<Pick<MapPoolMap, "stageId" | "mode">>,
|
||||
mapPoolList: Array<Pick<Tables["MapPoolMap"], "stageId" | "mode">>,
|
||||
) {
|
||||
const result: MapPoolObject = {
|
||||
TW: [],
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { MapPoolMap } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import {
|
||||
type ModeShort,
|
||||
type StageId,
|
||||
|
|
@ -14,7 +14,9 @@ import type {
|
|||
ReadonlyMapPoolObject,
|
||||
} from "./map-pool-serializer/types";
|
||||
|
||||
export type DbMapPoolList = Array<Pick<MapPoolMap, "stageId" | "mode">>;
|
||||
export type DbMapPoolList = Array<
|
||||
Pick<Tables["MapPoolMap"], "stageId" | "mode">
|
||||
>;
|
||||
|
||||
export class MapPool {
|
||||
private source: string | ReadonlyMapPoolObject;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import { Label } from "~/components/Label";
|
|||
import { Main } from "~/components/Main";
|
||||
import { MapPoolSelector, MapPoolStages } from "~/components/MapPoolSelector";
|
||||
import { EditIcon } from "~/components/icons/Edit";
|
||||
import type { CalendarEvent } from "~/db/types";
|
||||
import { getUserId } from "~/features/auth/core/user.server";
|
||||
import * as CalendarRepository from "~/features/calendar/CalendarRepository.server";
|
||||
import { type ModeWithStage, stageIds } from "~/modules/in-game-lists";
|
||||
|
|
@ -27,6 +26,7 @@ import { mapPoolToNonEmptyModes } from "../core/map-list-generator/utils";
|
|||
import { MapPool } from "../core/map-pool";
|
||||
import "~/styles/maps.css";
|
||||
import { SendouSwitch } from "~/components/elements/Switch";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { metaTags } from "~/utils/remix";
|
||||
|
||||
const AMOUNT_OF_MAPS_IN_MAP_LIST = stageIds.length * 2;
|
||||
|
|
@ -155,7 +155,7 @@ function useSearchParamPersistedMapPool() {
|
|||
|
||||
const handleMapPoolChange = (
|
||||
newMapPool: MapPool,
|
||||
event?: Pick<CalendarEvent, "id" | "name">,
|
||||
event?: Pick<Tables["CalendarEvent"], "id" | "name">,
|
||||
) => {
|
||||
setMapPool(newMapPool);
|
||||
setSearchParams(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Skill } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
select
|
||||
|
|
@ -26,7 +26,7 @@ export function findCurrentSkillByUserId({
|
|||
season: number;
|
||||
}) {
|
||||
return stm.get({ userId, season }) as Pick<
|
||||
Skill,
|
||||
Tables["Skill"],
|
||||
"mu" | "sigma" | "matchesCount"
|
||||
> | null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Skill } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
select
|
||||
|
|
@ -26,7 +26,7 @@ export function findCurrentTeamSkillByIdentifier({
|
|||
season: number;
|
||||
}) {
|
||||
return stm.get({ identifier, season }) as Pick<
|
||||
Skill,
|
||||
Tables["Skill"],
|
||||
"mu" | "sigma" | "matchesCount"
|
||||
> | null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Skill } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const userStm = sql.prepare(/* sql */ `
|
||||
select
|
||||
|
|
@ -51,6 +51,6 @@ export function orderedMMRBySeason({
|
|||
const stm = type === "team" ? teamStm : userStm;
|
||||
|
||||
return stm.all({ season }) as Array<
|
||||
Pick<Skill, "ordinal" | "matchesCount" | "userId" | "identifier">
|
||||
Pick<Tables["Skill"], "ordinal" | "matchesCount" | "userId" | "identifier">
|
||||
>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { Skill } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { cache, syncCached } from "~/utils/cache.server";
|
||||
import { MATCHES_COUNT_NEEDED_FOR_LEADERBOARD } from "../leaderboards/leaderboards-constants";
|
||||
import { USER_SKILLS_CACHE_KEY } from "../sendouq/q-constants";
|
||||
|
|
@ -71,7 +71,7 @@ export type SkillTierInterval = ReturnType<
|
|||
>["intervals"][number];
|
||||
|
||||
function skillTierIntervals(
|
||||
orderedPoints: Array<Pick<Skill, "ordinal" | "matchesCount">>,
|
||||
orderedPoints: Array<Pick<Tables["Skill"], "ordinal" | "matchesCount">>,
|
||||
type: "user" | "team",
|
||||
) {
|
||||
const LEADERBOARD_MIN_ENTRIES_FOR_LEVIATHAN =
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
PLUS_TIERS,
|
||||
PlUS_SUGGESTION_FIRST_COMMENT_MAX_LENGTH,
|
||||
} from "~/constants";
|
||||
import type { UserWithPlusTier } from "~/db/types";
|
||||
import type { UserWithPlusTier } from "~/db/tables";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { requireUser } from "~/features/auth/core/user.server";
|
||||
import { notify } from "~/features/notifications/core/notify.server";
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { FormWithConfirm } from "~/components/FormWithConfirm";
|
|||
import { RelativeTime } from "~/components/RelativeTime";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import { PLUS_TIERS } from "~/constants";
|
||||
import type { PlusSuggestion, User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { requireUser } from "~/features/auth/core/user.server";
|
||||
import * as PlusSuggestionRepository from "~/features/plus-suggestions/PlusSuggestionRepository.server";
|
||||
|
|
@ -366,7 +366,7 @@ export function PlusSuggestionComments({
|
|||
}: {
|
||||
suggestion: PlusSuggestionRepository.FindAllByMonthItem;
|
||||
deleteButtonArgs?: {
|
||||
user?: Pick<User, "id" | "discordId">;
|
||||
user?: Pick<Tables["User"], "id" | "discordId">;
|
||||
suggestions: PlusSuggestionRepository.FindAllByMonthItem[];
|
||||
tier: string;
|
||||
suggested: PlusSuggestionRepository.FindAllByMonthItem["suggested"];
|
||||
|
|
@ -425,7 +425,7 @@ function CommentDeleteButton({
|
|||
suggestedUsername,
|
||||
isFirstSuggestion = false,
|
||||
}: {
|
||||
suggestionId: PlusSuggestion["id"];
|
||||
suggestionId: Tables["PlusSuggestion"]["id"];
|
||||
tier: string;
|
||||
suggestedUsername: string;
|
||||
isFirstSuggestion?: boolean;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import type { PlusVote } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
export interface MonthYear {
|
||||
month: number;
|
||||
year: number;
|
||||
}
|
||||
|
||||
export type PlusVoteFromFE = Pick<PlusVote, "votedId" | "score">;
|
||||
export type PlusVoteFromFE = Pick<Tables["PlusVote"], "votedId" | "score">;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from "react";
|
||||
import { PLUS_DOWNVOTE, PLUS_UPVOTE } from "~/constants";
|
||||
import type { User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type * as PlusVotingRepository from "~/features/plus-voting/PlusVotingRepository.server";
|
||||
import invariant from "~/utils/invariant";
|
||||
import type { PlusVoteFromFE } from "./types";
|
||||
|
|
@ -13,7 +13,7 @@ interface VotingLocalStorageData {
|
|||
year: number;
|
||||
votes: PlusVoteFromFE[];
|
||||
/** User id -> order for sorting */
|
||||
usersForVotingOrder: Record<User["id"], number>;
|
||||
usersForVotingOrder: Record<Tables["User"]["id"], number>;
|
||||
}
|
||||
|
||||
export function usePlusVoting(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import type {
|
|||
} from "@remix-run/node";
|
||||
import { Link, useLoaderData } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import type { UserWithPlusTier } from "~/db/types";
|
||||
import { getUser } from "~/features/auth/core/user.server";
|
||||
import * as PlusVotingRepository from "~/features/plus-voting/PlusVotingRepository.server";
|
||||
import { lastCompletedVoting } from "~/features/plus-voting/core";
|
||||
|
|
@ -15,6 +14,7 @@ import { PLUS_SERVER_DISCORD_URL, userPage } from "~/utils/urls";
|
|||
import { isAtLeastFiveDollarTierPatreon } from "~/utils/users";
|
||||
|
||||
import "~/styles/plus-history.css";
|
||||
import type { UserWithPlusTier } from "~/db/tables";
|
||||
import { metaTags } from "~/utils/remix";
|
||||
|
||||
export const meta: MetaFunction = (args) => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
||||
import { db } from "~/db/sql";
|
||||
import type { ParsedMemento, Tables } from "~/db/tables";
|
||||
import type { UserSkillDifference } from "~/db/types";
|
||||
import type { ParsedMemento, Tables, UserSkillDifference } from "~/db/tables";
|
||||
import type { MainWeaponId } from "~/modules/in-game-lists";
|
||||
import { COMMON_USER_FIELDS, userChatNameColor } from "~/utils/kysely.server";
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import { SpeakerXIcon } from "~/components/icons/SpeakerX";
|
|||
import { StarIcon } from "~/components/icons/Star";
|
||||
import { StarFilledIcon } from "~/components/icons/StarFilled";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import type { GroupMember as GroupMemberType, ParsedMemento } from "~/db/types";
|
||||
import type { ParsedMemento, Tables } from "~/db/tables";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { MATCHES_COUNT_NEEDED_FOR_LEADERBOARD } from "~/features/leaderboards/leaderboards-constants";
|
||||
import { ordinalToRoundedSp } from "~/features/mmr/mmr-utils";
|
||||
|
|
@ -55,7 +55,7 @@ export function GroupCard({
|
|||
}: {
|
||||
group: Omit<LookingGroup, "createdAt" | "chatCode">;
|
||||
action?: "LIKE" | "UNLIKE" | "GROUP_UP" | "MATCH_UP" | "MATCH_UP_RECHALLENGE";
|
||||
ownRole?: GroupMemberType["role"] | "PREVIEWER";
|
||||
ownRole?: Tables["GroupMember"]["role"] | "PREVIEWER";
|
||||
ownGroup?: boolean;
|
||||
isExpired?: boolean;
|
||||
displayOnly?: boolean;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import type { Tables } from "~/db/tables";
|
||||
import type { Group } from "~/db/types";
|
||||
import { TIERS } from "~/features/mmr/mmr-constants";
|
||||
import { defaultOrdinal } from "~/features/mmr/mmr-utils";
|
||||
import type {
|
||||
|
|
@ -467,7 +466,7 @@ function resolveGroupSkill({
|
|||
}
|
||||
|
||||
export function groupExpiryStatus(
|
||||
group?: Pick<Group, "latestActionAt">,
|
||||
group?: Pick<Tables["Group"], "latestActionAt">,
|
||||
): null | GroupExpiryStatus {
|
||||
if (!group) return null;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { GroupMember } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { LookingGroup } from "../q-types";
|
||||
|
||||
// logic is that team who is bigger decides the settings
|
||||
|
|
@ -31,6 +31,6 @@ export function groupAfterMorph({
|
|||
return ourGroup;
|
||||
}
|
||||
|
||||
export function hasGroupManagerPerms(role: GroupMember["role"]) {
|
||||
export function hasGroupManagerPerms(role: Tables["GroupMember"]["role"]) {
|
||||
return role === "OWNER" || role === "MANAGER";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
import type { Rating } from "node_modules/openskill/dist/types";
|
||||
import { ordinal } from "openskill";
|
||||
import type {
|
||||
Group,
|
||||
GroupMatch,
|
||||
GroupSkillDifference,
|
||||
Skill,
|
||||
User,
|
||||
Tables,
|
||||
UserSkillDifference,
|
||||
} from "~/db/types";
|
||||
} from "~/db/tables";
|
||||
import { MATCHES_COUNT_NEEDED_FOR_LEADERBOARD } from "~/features/leaderboards/leaderboards-constants";
|
||||
import {
|
||||
ordinalToSp,
|
||||
|
|
@ -25,13 +22,13 @@ import { roundToNDecimalPlaces } from "~/utils/number";
|
|||
|
||||
export type MementoSkillDifferences = {
|
||||
users: Record<
|
||||
User["id"],
|
||||
Tables["User"]["id"],
|
||||
{
|
||||
skillDifference?: UserSkillDifference;
|
||||
}
|
||||
>;
|
||||
groups: Record<
|
||||
Group["id"],
|
||||
Tables["Group"]["id"],
|
||||
{
|
||||
skillDifference?: GroupSkillDifference;
|
||||
}
|
||||
|
|
@ -45,15 +42,15 @@ export function calculateMatchSkills({
|
|||
winnerGroupId,
|
||||
loserGroupId,
|
||||
}: {
|
||||
groupMatchId: GroupMatch["id"];
|
||||
winner: User["id"][];
|
||||
loser: User["id"][];
|
||||
winnerGroupId: Group["id"];
|
||||
loserGroupId: Group["id"];
|
||||
groupMatchId: Tables["GroupMatch"]["id"];
|
||||
winner: Tables["User"]["id"][];
|
||||
loser: Tables["User"]["id"][];
|
||||
winnerGroupId: Tables["Group"]["id"];
|
||||
loserGroupId: Tables["Group"]["id"];
|
||||
}) {
|
||||
const newSkills: Array<
|
||||
Pick<
|
||||
Skill,
|
||||
Tables["Skill"],
|
||||
"groupMatchId" | "identifier" | "mu" | "season" | "sigma" | "userId"
|
||||
>
|
||||
> = [];
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { MapResult, PlayerResult } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { currentOrPreviousSeason } from "~/features/mmr/season";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { winnersArrayToWinner } from "../q-utils";
|
||||
|
|
@ -16,7 +16,7 @@ export function summarizeMaps({
|
|||
const season = currentOrPreviousSeason(new Date())?.nth;
|
||||
invariant(typeof season === "number", "No ranked season for skills");
|
||||
|
||||
const result: Array<MapResult> = [];
|
||||
const result: Array<Tables["MapResult"]> = [];
|
||||
|
||||
const playedMaps = match.mapList.slice(0, winners.length);
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ export function summarizePlayerResults({
|
|||
const season = currentOrPreviousSeason(new Date())?.nth;
|
||||
invariant(typeof season === "number", "No ranked season for skills");
|
||||
|
||||
const result: Array<PlayerResult> = [];
|
||||
const result: Array<Tables["PlayerResult"]> = [];
|
||||
|
||||
const addMapResult = ({
|
||||
outcome,
|
||||
|
|
|
|||
|
|
@ -1,18 +1,11 @@
|
|||
import type { Tables } from "~/db/tables";
|
||||
import type {
|
||||
Group,
|
||||
GroupMember,
|
||||
ParsedMemento,
|
||||
PlusTier,
|
||||
User,
|
||||
} from "~/db/types";
|
||||
import type { ParsedMemento, Tables } from "~/db/tables";
|
||||
import type { MainWeaponId, ModeShort } from "~/modules/in-game-lists";
|
||||
import type { TieredSkill } from "../mmr/tiered.server";
|
||||
import type { GroupForMatch } from "../sendouq-match/QMatchRepository.server";
|
||||
|
||||
export type LookingGroup = {
|
||||
id: number;
|
||||
createdAt: Group["createdAt"];
|
||||
createdAt: Tables["Group"]["createdAt"];
|
||||
tier?: TieredSkill["tier"];
|
||||
tierRange?: {
|
||||
range?: [TieredSkill["tier"], TieredSkill["tier"]];
|
||||
|
|
@ -23,7 +16,7 @@ export type LookingGroup = {
|
|||
isLiked?: boolean;
|
||||
isRechallenge?: boolean;
|
||||
team?: GroupForMatch["team"];
|
||||
chatCode?: Group["chatCode"];
|
||||
chatCode?: Tables["Group"]["chatCode"];
|
||||
mapModePreferences?: Array<NonNullable<Tables["User"]["mapModePreferences"]>>;
|
||||
futureMatchModes?: Array<ModeShort>;
|
||||
rechallengeMatchModes?: Array<ModeShort>;
|
||||
|
|
@ -34,14 +27,14 @@ export type LookingGroup = {
|
|||
username: string;
|
||||
discordAvatar: string | null;
|
||||
noScreen?: number;
|
||||
customUrl?: User["customUrl"];
|
||||
plusTier?: PlusTier["tier"];
|
||||
role: GroupMember["role"];
|
||||
note?: GroupMember["note"];
|
||||
customUrl?: Tables["User"]["customUrl"];
|
||||
plusTier?: Tables["PlusTier"]["tier"];
|
||||
role: Tables["GroupMember"]["role"];
|
||||
note?: Tables["GroupMember"]["note"];
|
||||
weapons?: MainWeaponId[];
|
||||
skill?: TieredSkill | "CALCULATING";
|
||||
vc?: User["vc"];
|
||||
inGameName?: User["inGameName"];
|
||||
vc?: Tables["User"]["vc"];
|
||||
inGameName?: Tables["User"]["inGameName"];
|
||||
languages: string[];
|
||||
chatNameColor: string | null;
|
||||
skillDifference?: ParsedMemento["users"][number]["skillDifference"];
|
||||
|
|
@ -54,7 +47,7 @@ export type LookingGroup = {
|
|||
};
|
||||
|
||||
export type LookingGroupWithInviteCode = LookingGroup & {
|
||||
inviteCode: Group["inviteCode"];
|
||||
inviteCode: Tables["Group"]["inviteCode"];
|
||||
members: NonNullable<LookingGroup["members"]>;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { Group } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { stageIds } from "~/modules/in-game-lists";
|
||||
import { rankedModesShort } from "~/modules/in-game-lists/modes";
|
||||
import { databaseTimestampToDate } from "~/utils/dates";
|
||||
|
|
@ -13,7 +13,7 @@ import type { MapPool } from "../map-list-generator/core/map-pool";
|
|||
import { SENDOUQ } from "./q-constants";
|
||||
|
||||
function groupRedirectLocation(
|
||||
group?: Pick<Group, "status"> & { matchId?: number },
|
||||
group?: Pick<Tables["Group"], "status"> & { matchId?: number },
|
||||
) {
|
||||
if (group?.status === "PREPARING") return SENDOUQ_PREPARING_PAGE;
|
||||
if (group?.matchId) return sendouQMatchPage(group.matchId);
|
||||
|
|
@ -26,7 +26,7 @@ export function groupRedirectLocationByCurrentLocation({
|
|||
group,
|
||||
currentLocation,
|
||||
}: {
|
||||
group?: Pick<Group, "status"> & { matchId?: number };
|
||||
group?: Pick<Tables["Group"], "status"> & { matchId?: number };
|
||||
currentLocation: "default" | "preparing" | "looking" | "match";
|
||||
}) {
|
||||
const newLocation = groupRedirectLocation(group);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { MapResult } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const addMapResultDeltaStm = sql.prepare(/* sql */ `
|
||||
insert into "MapResult" (
|
||||
|
|
@ -25,7 +25,7 @@ const addMapResultDeltaStm = sql.prepare(/* sql */ `
|
|||
|
||||
export function addMapResults(
|
||||
results: Array<
|
||||
Pick<MapResult, "losses" | "wins" | "userId" | "mode" | "stageId">
|
||||
Pick<Tables["MapResult"], "losses" | "wins" | "userId" | "mode" | "stageId">
|
||||
>,
|
||||
) {
|
||||
for (const result of results) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { GroupMember } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
insert into "GroupMember" (
|
||||
|
|
@ -20,7 +20,7 @@ export function addMember({
|
|||
}: {
|
||||
groupId: number;
|
||||
userId: number;
|
||||
role?: GroupMember["role"];
|
||||
role?: Tables["GroupMember"]["role"];
|
||||
}) {
|
||||
stm.run({ groupId, userId, role });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { PlayerResult } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const addPlayerResultDeltaStm = sql.prepare(/* sql */ `
|
||||
insert into "PlayerResult" (
|
||||
|
|
@ -29,7 +29,7 @@ const addPlayerResultDeltaStm = sql.prepare(/* sql */ `
|
|||
"setLosses" = "setLosses" + @setLosses
|
||||
`);
|
||||
|
||||
export function addPlayerResults(results: Array<PlayerResult>) {
|
||||
export function addPlayerResults(results: Array<Tables["PlayerResult"]>) {
|
||||
for (const result of results) {
|
||||
addPlayerResultDeltaStm.run({
|
||||
ownerUserId: result.ownerUserId,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { ordinal } from "openskill";
|
||||
import { sql } from "~/db/sql";
|
||||
import type { ParsedMemento, Skill } from "~/db/types";
|
||||
import type { ParsedMemento, Tables } from "~/db/tables";
|
||||
import { identifierToUserIds } from "~/features/mmr/mmr-utils";
|
||||
import type { MementoSkillDifferences } from "../core/skills.server";
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ export function addSkills({
|
|||
}: {
|
||||
groupMatchId: number;
|
||||
skills: Pick<
|
||||
Skill,
|
||||
Tables["Skill"],
|
||||
"groupMatchId" | "identifier" | "mu" | "season" | "sigma" | "userId"
|
||||
>[];
|
||||
oldMatchMemento: ParsedMemento;
|
||||
|
|
@ -66,7 +66,7 @@ export function addSkills({
|
|||
const insertedSkill = stm.get({
|
||||
...skill,
|
||||
ordinal: ordinal(skill),
|
||||
}) as Skill;
|
||||
}) as Tables["Skill"];
|
||||
|
||||
if (insertedSkill.identifier) {
|
||||
for (const userId of identifierToUserIds(insertedSkill.identifier)) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { nanoid } from "nanoid";
|
||||
import { sql } from "~/db/sql";
|
||||
import type { ParsedMemento } from "~/db/tables";
|
||||
import type { GroupMatch } from "~/db/types";
|
||||
import type { ParsedMemento, Tables } from "~/db/tables";
|
||||
import type { TournamentMapListMap } from "~/modules/tournament-map-list-generator";
|
||||
import { syncGroupTeamId } from "./syncGroupTeamId.server";
|
||||
|
||||
|
|
@ -53,7 +52,7 @@ export const createMatch = sql.transaction(
|
|||
bravoGroupId,
|
||||
chatCode: nanoid(10),
|
||||
memento: JSON.stringify(memento),
|
||||
}) as GroupMatch;
|
||||
}) as Tables["GroupMatch"];
|
||||
|
||||
for (const [i, { mode, source, stageId }] of mapList.entries()) {
|
||||
createMatchMapStm.run({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Group, GroupMember } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import invariant from "~/utils/invariant";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
|
|
@ -21,11 +21,11 @@ const stm = sql.prepare(/* sql */ `
|
|||
`);
|
||||
|
||||
type ActiveGroup = Pick<
|
||||
Group,
|
||||
Tables["Group"],
|
||||
"id" | "status" | "latestActionAt" | "chatCode"
|
||||
> & {
|
||||
matchId?: number;
|
||||
role: GroupMember["role"];
|
||||
role: Tables["GroupMember"]["role"];
|
||||
};
|
||||
|
||||
export function findCurrentGroupByUserId(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Group, GroupMember } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { parseDBJsonArray } from "~/utils/sql";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
|
|
@ -25,8 +25,12 @@ const stm = sql.prepare(/* sql */ `
|
|||
|
||||
export function findGroupByInviteCode(inviteCode: string): {
|
||||
id: number;
|
||||
status: Group["status"];
|
||||
members: { id: number; username: string; role: GroupMember["role"] }[];
|
||||
status: Tables["Group"]["status"];
|
||||
members: {
|
||||
id: number;
|
||||
username: string;
|
||||
role: Tables["GroupMember"]["role"];
|
||||
}[];
|
||||
} | null {
|
||||
const row = stm.get({ inviteCode }) as any;
|
||||
if (!row) return null;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { GroupMatch, GroupMatchMap, ParsedMemento } from "~/db/types";
|
||||
import type { ParsedMemento, Tables } from "~/db/tables";
|
||||
import { parseDBJsonArray } from "~/utils/sql";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
|
|
@ -30,17 +30,20 @@ const stm = sql.prepare(/* sql */ `
|
|||
`);
|
||||
|
||||
export interface MatchById {
|
||||
id: GroupMatch["id"];
|
||||
alphaGroupId: GroupMatch["alphaGroupId"];
|
||||
bravoGroupId: GroupMatch["bravoGroupId"];
|
||||
createdAt: GroupMatch["createdAt"];
|
||||
reportedAt: GroupMatch["reportedAt"];
|
||||
reportedByUserId: GroupMatch["reportedByUserId"];
|
||||
chatCode: GroupMatch["chatCode"];
|
||||
id: Tables["GroupMatch"]["id"];
|
||||
alphaGroupId: Tables["GroupMatch"]["alphaGroupId"];
|
||||
bravoGroupId: Tables["GroupMatch"]["bravoGroupId"];
|
||||
createdAt: Tables["GroupMatch"]["createdAt"];
|
||||
reportedAt: Tables["GroupMatch"]["reportedAt"];
|
||||
reportedByUserId: Tables["GroupMatch"]["reportedByUserId"];
|
||||
chatCode: Tables["GroupMatch"]["chatCode"];
|
||||
isLocked: boolean;
|
||||
memento: ParsedMemento;
|
||||
mapList: Array<
|
||||
Pick<GroupMatchMap, "id" | "mode" | "stageId" | "source" | "winnerGroupId">
|
||||
Pick<
|
||||
Tables["GroupMatchMap"],
|
||||
"id" | "mode" | "stageId" | "source" | "winnerGroupId"
|
||||
>
|
||||
>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { GroupMember } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql*/ `
|
||||
with "MostRecentGroupMatch" as (
|
||||
|
|
@ -25,7 +25,10 @@ const stm = sql.prepare(/* sql*/ `
|
|||
"MostRecentGroupMatch"."createdAt" > unixepoch() - 60 * 60 * 2
|
||||
`);
|
||||
|
||||
export type RecentMatchPlayer = Pick<GroupMember, "groupId" | "userId">;
|
||||
export type RecentMatchPlayer = Pick<
|
||||
Tables["GroupMember"],
|
||||
"groupId" | "userId"
|
||||
>;
|
||||
|
||||
export function findRecentMatchPlayersByUserId(userId: number) {
|
||||
return stm.all({ userId }) as Array<RecentMatchPlayer>;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { GroupMember } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
select
|
||||
|
|
@ -13,7 +13,7 @@ const stm = sql.prepare(/* sql */ `
|
|||
|
||||
export const groupSuccessorOwner = (groupId: number) => {
|
||||
const rows = stm.all({ groupId }) as Array<
|
||||
Pick<GroupMember, "role" | "userId">
|
||||
Pick<Tables["GroupMember"], "role" | "userId">
|
||||
>;
|
||||
|
||||
if (rows.length === 0) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { nanoid } from "nanoid";
|
||||
import { sql } from "~/db/sql";
|
||||
import type { GroupMember, User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { deleteLikesByGroupId } from "./deleteLikesByGroupId.server";
|
||||
|
||||
const findToBeDeletedGroupNonRegularsStm = sql.prepare(/* sql */ `
|
||||
|
|
@ -41,7 +41,7 @@ export const morphGroups = sql.transaction(
|
|||
}) => {
|
||||
const toBeDeletedGroupNonRegulars = findToBeDeletedGroupNonRegularsStm
|
||||
.all({ groupId: otherGroupId })
|
||||
.map((row: any) => row.userId) as Array<User["id"]>;
|
||||
.map((row: any) => row.userId) as Array<Tables["User"]["id"]>;
|
||||
|
||||
deleteLikesByGroupId(survivingGroupId);
|
||||
|
||||
|
|
@ -52,11 +52,8 @@ export const morphGroups = sql.transaction(
|
|||
});
|
||||
|
||||
for (const userId of newMembers) {
|
||||
const role: GroupMember["role"] = toBeDeletedGroupNonRegulars.includes(
|
||||
userId,
|
||||
)
|
||||
? "MANAGER"
|
||||
: "REGULAR";
|
||||
const role: Tables["GroupMember"]["role"] =
|
||||
toBeDeletedGroupNonRegulars.includes(userId) ? "MANAGER" : "REGULAR";
|
||||
updateGroupMemberStm.run({
|
||||
newGroupId: survivingGroupId,
|
||||
oldGroupId: otherGroupId,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { GroupMatch } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
|
||||
const updateMatchStm = sql.prepare(/* sql */ `
|
||||
|
|
@ -35,7 +35,7 @@ export const reportScore = ({
|
|||
reportedAt: dateToDatabaseTimestamp(new Date()),
|
||||
reportedByUserId,
|
||||
matchId,
|
||||
}) as GroupMatch;
|
||||
}) as Tables["GroupMatch"];
|
||||
|
||||
clearMatchMapWinnersStm.run({ matchId });
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { GroupMatchMap, ReportedWeapon } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
select
|
||||
|
|
@ -15,8 +15,8 @@ const stm = sql.prepare(/* sql */ `
|
|||
|
||||
export function reportedWeaponsByMatchId(matchId: number) {
|
||||
const rows = stm.all({ matchId }) as Array<
|
||||
ReportedWeapon & {
|
||||
mapIndex: GroupMatchMap["index"];
|
||||
Tables["ReportedWeapon"] & {
|
||||
mapIndex: Tables["GroupMatchMap"]["index"];
|
||||
groupMatchMapId: number;
|
||||
}
|
||||
>;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { add } from "date-fns";
|
||||
import { sql } from "~/db/sql";
|
||||
import type { ParsedMemento } from "~/db/tables";
|
||||
import type { GroupMatch, GroupMatchMap, User } from "~/db/types";
|
||||
import type { ParsedMemento, Tables } from "~/db/tables";
|
||||
import { seasonObject } from "~/features/mmr/season";
|
||||
import { MATCHES_PER_SEASONS_PAGE } from "~/features/user-page/user-page-constants";
|
||||
import type { MainWeaponId } from "~/modules/in-game-lists";
|
||||
|
|
@ -98,25 +97,25 @@ const weaponsStm = sql.prepare(/* sql */ `
|
|||
`);
|
||||
|
||||
interface SeasonMatchByUserId {
|
||||
id: GroupMatch["id"];
|
||||
alphaGroupId: GroupMatch["alphaGroupId"];
|
||||
bravoGroupId: GroupMatch["bravoGroupId"];
|
||||
winnerGroupIds: Array<GroupMatchMap["winnerGroupId"]>;
|
||||
createdAt: GroupMatch["createdAt"];
|
||||
id: Tables["GroupMatch"]["id"];
|
||||
alphaGroupId: Tables["GroupMatch"]["alphaGroupId"];
|
||||
bravoGroupId: Tables["GroupMatch"]["bravoGroupId"];
|
||||
winnerGroupIds: Array<Tables["GroupMatchMap"]["winnerGroupId"]>;
|
||||
createdAt: Tables["GroupMatch"]["createdAt"];
|
||||
isLocked: number;
|
||||
spDiff: number | null;
|
||||
groupAlphaMembers: Array<{
|
||||
id: User["id"];
|
||||
username: User["username"];
|
||||
discordId: User["discordId"];
|
||||
discordAvatar: User["discordAvatar"];
|
||||
id: Tables["User"]["id"];
|
||||
username: Tables["User"]["username"];
|
||||
discordId: Tables["User"]["discordId"];
|
||||
discordAvatar: Tables["User"]["discordAvatar"];
|
||||
weaponSplId?: MainWeaponId;
|
||||
}>;
|
||||
groupBravoMembers: Array<{
|
||||
id: User["id"];
|
||||
username: User["username"];
|
||||
discordId: User["discordId"];
|
||||
discordAvatar: User["discordAvatar"];
|
||||
id: Tables["User"]["id"];
|
||||
username: Tables["User"]["username"];
|
||||
discordId: Tables["User"]["discordId"];
|
||||
discordAvatar: Tables["User"]["discordAvatar"];
|
||||
weaponSplId?: MainWeaponId;
|
||||
}>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { MapResult } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { ModeShort, StageId } from "~/modules/in-game-lists";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
|
|
@ -19,7 +19,7 @@ export function seasonStagesByUserId({
|
|||
userId: number;
|
||||
season: number;
|
||||
}) {
|
||||
const rows = stm.all({ userId, season }) as Array<MapResult>;
|
||||
const rows = stm.all({ userId, season }) as Array<Tables["MapResult"]>;
|
||||
|
||||
return rows.reduce(
|
||||
(acc, cur) => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { PlayerResult, User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
select
|
||||
|
|
@ -30,7 +30,7 @@ export function seasonsMatesEnemiesByUserId({
|
|||
}: {
|
||||
userId: number;
|
||||
season: number;
|
||||
type: PlayerResult["type"];
|
||||
type: Tables["PlayerResult"]["type"];
|
||||
}) {
|
||||
const rows = stm.all({ userId, season, type }) as any[];
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ export function seasonsMatesEnemiesByUserId({
|
|||
setWins: number;
|
||||
setLosses: number;
|
||||
user: Pick<
|
||||
User,
|
||||
Tables["User"],
|
||||
"id" | "username" | "discordAvatar" | "discordId" | "customUrl"
|
||||
>;
|
||||
}>;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Group } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
update "Group"
|
||||
|
|
@ -7,6 +7,6 @@ const stm = sql.prepare(/* sql */ `
|
|||
where "id" = @groupId
|
||||
`);
|
||||
|
||||
export function setGroupAsActive(groupId: Group["id"]) {
|
||||
export function setGroupAsActive(groupId: Tables["Group"]["id"]) {
|
||||
stm.run({ groupId });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { GroupMember } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
update "GroupMember"
|
||||
|
|
@ -8,9 +8,9 @@ const stm = sql.prepare(/* sql */ `
|
|||
`);
|
||||
|
||||
export function updateNote(args: {
|
||||
note: GroupMember["note"];
|
||||
groupId: GroupMember["groupId"];
|
||||
userId: GroupMember["userId"];
|
||||
note: Tables["GroupMember"]["note"];
|
||||
groupId: Tables["GroupMember"]["groupId"];
|
||||
userId: Tables["GroupMember"]["userId"];
|
||||
}) {
|
||||
stm.run(args);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import { DiscordIcon } from "~/components/icons/Discord";
|
|||
import { RefreshArrowsIcon } from "~/components/icons/RefreshArrows";
|
||||
import { ScaleIcon } from "~/components/icons/Scale";
|
||||
import { sql } from "~/db/sql";
|
||||
import type { GroupMember, ReportedWeapon } from "~/db/types";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { getUserId, requireUser } from "~/features/auth/core/user.server";
|
||||
import * as ChatSystemMessage from "~/features/chat/ChatSystemMessage.server";
|
||||
|
|
@ -113,6 +112,7 @@ import { reportedWeaponsByMatchId } from "../queries/reportedWeaponsByMatchId.se
|
|||
import { setGroupAsInactive } from "../queries/setGroupAsInactive.server";
|
||||
import "../q.css";
|
||||
import { SendouSwitch } from "~/components/elements/Switch";
|
||||
import type { ReportedWeapon, Tables } from "~/db/tables";
|
||||
import { metaTags } from "~/utils/remix";
|
||||
|
||||
export const meta: MetaFunction = (args) => {
|
||||
|
|
@ -751,7 +751,7 @@ function AfterMatchActions({
|
|||
setShowWeaponsForm,
|
||||
}: {
|
||||
ownGroupId: number;
|
||||
role: GroupMember["role"];
|
||||
role: Tables["GroupMember"]["role"];
|
||||
reportedAt: number;
|
||||
showWeaponsForm: boolean;
|
||||
setShowWeaponsForm: (show: boolean) => void;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import { SubmitButton } from "~/components/SubmitButton";
|
|||
import { UserIcon } from "~/components/icons/User";
|
||||
import { UsersIcon } from "~/components/icons/Users";
|
||||
import { sql } from "~/db/sql";
|
||||
import type { GroupMember } from "~/db/types";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { getUserId, requireUser } from "~/features/auth/core/user.server";
|
||||
import type { RankingSeason } from "~/features/mmr/season";
|
||||
|
|
@ -67,6 +66,7 @@ import { deleteLikesByGroupId } from "../queries/deleteLikesByGroupId.server";
|
|||
import { findCurrentGroupByUserId } from "../queries/findCurrentGroupByUserId.server";
|
||||
import { findGroupByInviteCode } from "../queries/findGroupByInviteCode.server";
|
||||
import "../q.css";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { metaTags } from "~/utils/remix";
|
||||
|
||||
export const handle: SendouRouteHandle = {
|
||||
|
|
@ -402,7 +402,7 @@ function JoinTeamDialog({
|
|||
close: () => void;
|
||||
members: {
|
||||
username: string;
|
||||
role: GroupMember["role"];
|
||||
role: Tables["GroupMember"]["role"];
|
||||
}[];
|
||||
}) {
|
||||
const { t } = useTranslation(["q"]);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import type { UserWithPlusTier } from "~/db/types";
|
||||
import type { UserWithPlusTier } from "~/db/tables";
|
||||
import { getUserId } from "~/features/auth/core/user.server";
|
||||
import { sumArray } from "~/utils/number";
|
||||
import * as TeamRepository from "../TeamRepository.server";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { User, XRankPlacement } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const query = (byPlayer?: boolean) => /* sql */ `
|
||||
select
|
||||
|
|
@ -48,7 +48,7 @@ const ofMonthStm = sql.prepare(query());
|
|||
const byPlayerStm = sql.prepare(query(true));
|
||||
|
||||
export type FindPlacement = Pick<
|
||||
XRankPlacement,
|
||||
Tables["XRankPlacement"],
|
||||
| "id"
|
||||
| "weaponSplId"
|
||||
| "name"
|
||||
|
|
@ -60,15 +60,17 @@ export type FindPlacement = Pick<
|
|||
| "playerId"
|
||||
| "mode"
|
||||
> &
|
||||
Pick<User, "customUrl" | "discordId">;
|
||||
Pick<Tables["User"], "customUrl" | "discordId">;
|
||||
|
||||
export function findPlacementsOfMonth(
|
||||
args: Pick<XRankPlacement, "mode" | "region" | "month" | "year">,
|
||||
args: Pick<Tables["XRankPlacement"], "mode" | "region" | "month" | "year">,
|
||||
) {
|
||||
return ofMonthStm.all(args) as Array<FindPlacement>;
|
||||
}
|
||||
|
||||
export function findPlacementsByPlayerId(playerId: XRankPlacement["playerId"]) {
|
||||
export function findPlacementsByPlayerId(
|
||||
playerId: Tables["XRankPlacement"]["playerId"],
|
||||
) {
|
||||
const results = byPlayerStm.all({ playerId }) as Array<FindPlacement>;
|
||||
if (!results) return null;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import { useLoaderData, useSearchParams } from "@remix-run/react";
|
|||
import { nanoid } from "nanoid";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Main } from "~/components/Main";
|
||||
import type { XRankPlacement } from "~/db/types";
|
||||
import type { RankedModeShort } from "~/modules/in-game-lists";
|
||||
import { rankedModesShort } from "~/modules/in-game-lists/modes";
|
||||
import invariant from "~/utils/invariant";
|
||||
|
|
@ -16,6 +15,7 @@ import { monthYears } from "../queries/monthYears";
|
|||
import type { MonthYear } from "../top-search-utils";
|
||||
|
||||
import "../top-search.css";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
export const handle: SendouRouteHandle = {
|
||||
breadcrumb: () => ({
|
||||
|
|
@ -152,7 +152,7 @@ export default function XSearchPage() {
|
|||
|
||||
interface SelectOption {
|
||||
id: string;
|
||||
region: XRankPlacement["region"];
|
||||
region: Tables["XRankPlacement"]["region"];
|
||||
mode: RankedModeShort;
|
||||
span: {
|
||||
from: MonthYear;
|
||||
|
|
|
|||
|
|
@ -2,13 +2,7 @@
|
|||
|
||||
import { nanoid } from "nanoid";
|
||||
import { sql } from "~/db/sql";
|
||||
import type { TournamentRoundMaps } from "~/db/tables";
|
||||
import type {
|
||||
TournamentGroup,
|
||||
TournamentMatch,
|
||||
TournamentRound,
|
||||
TournamentStage,
|
||||
} from "~/db/types";
|
||||
import type { Tables, TournamentRoundMaps } from "~/db/tables";
|
||||
import type {
|
||||
Group as GroupType,
|
||||
Match as MatchType,
|
||||
|
|
@ -54,20 +48,20 @@ const stage_updateSettingsStm = sql.prepare(/*sql*/ `
|
|||
`);
|
||||
|
||||
export class Stage {
|
||||
id?: TournamentStage["id"];
|
||||
tournamentId: TournamentStage["tournamentId"];
|
||||
number: TournamentStage["number"];
|
||||
name: TournamentStage["name"];
|
||||
id?: Tables["TournamentStage"]["id"];
|
||||
tournamentId: Tables["TournamentStage"]["tournamentId"];
|
||||
number: Tables["TournamentStage"]["number"];
|
||||
name: Tables["TournamentStage"]["name"];
|
||||
type: StageType["type"];
|
||||
settings: TournamentStage["settings"];
|
||||
settings: Tables["TournamentStage"]["settings"];
|
||||
|
||||
constructor(
|
||||
id: TournamentStage["id"] | undefined,
|
||||
tournamentId: TournamentStage["tournamentId"],
|
||||
number: TournamentStage["number"],
|
||||
name: TournamentStage["name"],
|
||||
id: Tables["TournamentStage"]["id"] | undefined,
|
||||
tournamentId: Tables["TournamentStage"]["tournamentId"],
|
||||
number: Tables["TournamentStage"]["number"],
|
||||
name: Tables["TournamentStage"]["name"],
|
||||
type: StageType["type"],
|
||||
settings: TournamentStage["settings"],
|
||||
settings: Tables["TournamentStage"]["settings"],
|
||||
) {
|
||||
this.id = id;
|
||||
this.tournamentId = tournamentId;
|
||||
|
|
@ -92,7 +86,7 @@ export class Stage {
|
|||
return true;
|
||||
}
|
||||
|
||||
static #convertStage(rawStage: TournamentStage): StageType {
|
||||
static #convertStage(rawStage: Tables["TournamentStage"]): StageType {
|
||||
return {
|
||||
id: rawStage.id,
|
||||
name: rawStage.name,
|
||||
|
|
@ -104,7 +98,7 @@ export class Stage {
|
|||
};
|
||||
}
|
||||
|
||||
static getById(id: TournamentStage["id"]): StageType {
|
||||
static getById(id: Tables["TournamentStage"]["id"]): StageType {
|
||||
const stage = stage_getByIdStm.get({ id }) as any;
|
||||
if (!stage) return stage;
|
||||
return Stage.#convertStage(stage);
|
||||
|
|
@ -117,8 +111,8 @@ export class Stage {
|
|||
}
|
||||
|
||||
static updateSettings(
|
||||
id: TournamentStage["id"],
|
||||
settings: TournamentStage["settings"],
|
||||
id: Tables["TournamentStage"]["id"],
|
||||
settings: Tables["TournamentStage"]["settings"],
|
||||
) {
|
||||
stage_updateSettingsStm.run({ id, settings });
|
||||
|
||||
|
|
@ -155,21 +149,21 @@ const group_insertStm = sql.prepare(/*sql*/ `
|
|||
`);
|
||||
|
||||
export class Group {
|
||||
id?: TournamentGroup["id"];
|
||||
stageId: TournamentGroup["stageId"];
|
||||
number: TournamentGroup["number"];
|
||||
id?: Tables["TournamentGroup"]["id"];
|
||||
stageId: Tables["TournamentGroup"]["stageId"];
|
||||
number: Tables["TournamentGroup"]["number"];
|
||||
|
||||
constructor(
|
||||
id: TournamentGroup["id"] | undefined,
|
||||
stageId: TournamentGroup["stageId"],
|
||||
number: TournamentGroup["number"],
|
||||
id: Tables["TournamentGroup"]["id"] | undefined,
|
||||
stageId: Tables["TournamentGroup"]["stageId"],
|
||||
number: Tables["TournamentGroup"]["number"],
|
||||
) {
|
||||
this.id = id;
|
||||
this.stageId = stageId;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
static #convertGroup(rawGroup: TournamentGroup): GroupType {
|
||||
static #convertGroup(rawGroup: Tables["TournamentGroup"]): GroupType {
|
||||
return {
|
||||
id: rawGroup.id,
|
||||
number: rawGroup.number,
|
||||
|
|
@ -177,21 +171,21 @@ export class Group {
|
|||
};
|
||||
}
|
||||
|
||||
static getById(id: TournamentGroup["id"]): GroupType {
|
||||
static getById(id: Tables["TournamentGroup"]["id"]): GroupType {
|
||||
const group = group_getByIdStm.get({ id }) as any;
|
||||
if (!group) return group;
|
||||
return Group.#convertGroup(group);
|
||||
}
|
||||
|
||||
static getByStageId(stageId: TournamentStage["id"]): GroupType[] {
|
||||
static getByStageId(stageId: Tables["TournamentStage"]["id"]): GroupType[] {
|
||||
return (group_getByStageIdStm.all({ stageId }) as any[]).map(
|
||||
Group.#convertGroup,
|
||||
);
|
||||
}
|
||||
|
||||
static getByStageAndNumber(
|
||||
stageId: TournamentStage["id"],
|
||||
number: TournamentGroup["number"],
|
||||
stageId: Tables["TournamentStage"]["id"],
|
||||
number: Tables["TournamentGroup"]["number"],
|
||||
): GroupType {
|
||||
const group = group_getByStageAndNumberStm.get({ stageId, number }) as any;
|
||||
if (!group) return group;
|
||||
|
|
@ -245,17 +239,17 @@ const round_insertStm = sql.prepare(/*sql*/ `
|
|||
`);
|
||||
|
||||
export class Round {
|
||||
id?: TournamentRound["id"];
|
||||
stageId: TournamentRound["stageId"];
|
||||
groupId: TournamentRound["groupId"];
|
||||
number: TournamentRound["number"];
|
||||
id?: Tables["TournamentRound"]["id"];
|
||||
stageId: Tables["TournamentRound"]["stageId"];
|
||||
groupId: Tables["TournamentRound"]["groupId"];
|
||||
number: Tables["TournamentRound"]["number"];
|
||||
maps: Pick<TournamentRoundMaps, "count" | "type">;
|
||||
|
||||
constructor(
|
||||
id: TournamentRound["id"] | undefined,
|
||||
stageId: TournamentRound["stageId"],
|
||||
groupId: TournamentRound["groupId"],
|
||||
number: TournamentRound["number"],
|
||||
id: Tables["TournamentRound"]["id"] | undefined,
|
||||
stageId: Tables["TournamentRound"]["stageId"],
|
||||
groupId: Tables["TournamentRound"]["groupId"],
|
||||
number: Tables["TournamentRound"]["number"],
|
||||
maps: Pick<TournamentRoundMaps, "count" | "type">,
|
||||
) {
|
||||
this.id = id;
|
||||
|
|
@ -278,7 +272,7 @@ export class Round {
|
|||
}
|
||||
|
||||
static #convertRound(
|
||||
rawRound: TournamentRound & { maps?: string | null },
|
||||
rawRound: Tables["TournamentRound"] & { maps?: string | null },
|
||||
): RoundType {
|
||||
const parsedMaps = rawRound.maps ? JSON.parse(rawRound.maps) : null;
|
||||
|
||||
|
|
@ -297,28 +291,28 @@ export class Round {
|
|||
};
|
||||
}
|
||||
|
||||
static getByStageId(stageId: TournamentStage["id"]): RoundType[] {
|
||||
static getByStageId(stageId: Tables["TournamentStage"]["id"]): RoundType[] {
|
||||
return (round_getByStageIdStm.all({ stageId }) as any[]).map(
|
||||
Round.#convertRound,
|
||||
);
|
||||
}
|
||||
|
||||
static getByGroupId(groupId: TournamentGroup["id"]): RoundType[] {
|
||||
static getByGroupId(groupId: Tables["TournamentGroup"]["id"]): RoundType[] {
|
||||
return (round_getByGroupIdStm.all({ groupId }) as any[]).map(
|
||||
Round.#convertRound,
|
||||
);
|
||||
}
|
||||
|
||||
static getByGroupAndNumber(
|
||||
groupId: TournamentGroup["id"],
|
||||
number: TournamentRound["number"],
|
||||
groupId: Tables["TournamentGroup"]["id"],
|
||||
number: Tables["TournamentRound"]["number"],
|
||||
): RoundType {
|
||||
const round = round_getByGroupAndNumberStm.get({ groupId, number }) as any;
|
||||
if (!round) return round;
|
||||
return Round.#convertRound(round);
|
||||
}
|
||||
|
||||
static getById(id: TournamentRound["id"]): RoundType {
|
||||
static getById(id: Tables["TournamentRound"]["id"]): RoundType {
|
||||
const round = round_getByIdStm.get({ id }) as any;
|
||||
if (!round) return round;
|
||||
return Round.#convertRound(round);
|
||||
|
|
@ -380,27 +374,27 @@ const match_updateStm = sql.prepare(/*sql*/ `
|
|||
`);
|
||||
|
||||
export class Match {
|
||||
id?: TournamentMatch["id"];
|
||||
roundId: TournamentMatch["roundId"];
|
||||
stageId: TournamentMatch["stageId"];
|
||||
groupId: TournamentMatch["groupId"];
|
||||
number: TournamentMatch["number"];
|
||||
opponentOne: TournamentMatch["opponentOne"];
|
||||
opponentTwo: TournamentMatch["opponentTwo"];
|
||||
status: TournamentMatch["status"];
|
||||
id?: Tables["TournamentMatch"]["id"];
|
||||
roundId: Tables["TournamentMatch"]["roundId"];
|
||||
stageId: Tables["TournamentMatch"]["stageId"];
|
||||
groupId: Tables["TournamentMatch"]["groupId"];
|
||||
number: Tables["TournamentMatch"]["number"];
|
||||
opponentOne: string;
|
||||
opponentTwo: string;
|
||||
status: Tables["TournamentMatch"]["status"];
|
||||
|
||||
constructor(
|
||||
id: TournamentMatch["id"] | undefined,
|
||||
status: TournamentMatch["status"],
|
||||
stageId: TournamentMatch["stageId"],
|
||||
groupId: TournamentMatch["groupId"],
|
||||
roundId: TournamentMatch["roundId"],
|
||||
number: TournamentMatch["number"],
|
||||
id: Tables["TournamentMatch"]["id"] | undefined,
|
||||
status: Tables["TournamentMatch"]["status"],
|
||||
stageId: Tables["TournamentMatch"]["stageId"],
|
||||
groupId: Tables["TournamentMatch"]["groupId"],
|
||||
roundId: Tables["TournamentMatch"]["roundId"],
|
||||
number: Tables["TournamentMatch"]["number"],
|
||||
_unknown1: null,
|
||||
_unknown2: null,
|
||||
_unknown3: null,
|
||||
opponentOne: TournamentMatch["opponentOne"],
|
||||
opponentTwo: TournamentMatch["opponentTwo"],
|
||||
opponentOne: string,
|
||||
opponentTwo: string,
|
||||
) {
|
||||
this.id = id;
|
||||
this.roundId = roundId;
|
||||
|
|
@ -413,7 +407,9 @@ export class Match {
|
|||
}
|
||||
|
||||
static #convertMatch(
|
||||
rawMatch: TournamentMatch & {
|
||||
rawMatch: Tables["TournamentMatch"] & {
|
||||
opponentOne: string;
|
||||
opponentTwo: string;
|
||||
opponentOnePointsTotal: number | null;
|
||||
opponentTwoPointsTotal: number | null;
|
||||
lastGameFinishedAt: number | null;
|
||||
|
|
@ -446,27 +442,27 @@ export class Match {
|
|||
};
|
||||
}
|
||||
|
||||
static getById(id: TournamentMatch["id"]): MatchType {
|
||||
static getById(id: Tables["TournamentMatch"]["id"]): MatchType {
|
||||
const match = match_getByIdStm.get({ id }) as any;
|
||||
if (!match) return match;
|
||||
return Match.#convertMatch(match);
|
||||
}
|
||||
|
||||
static getByRoundId(roundId: TournamentRound["id"]): MatchType[] {
|
||||
static getByRoundId(roundId: Tables["TournamentRound"]["id"]): MatchType[] {
|
||||
return (match_getByRoundIdStm.all({ roundId }) as any[]).map(
|
||||
Match.#convertMatch,
|
||||
);
|
||||
}
|
||||
|
||||
static getByStageId(stageId: TournamentStage["id"]): MatchType[] {
|
||||
static getByStageId(stageId: Tables["TournamentStage"]["id"]): MatchType[] {
|
||||
return (match_getByStageIdStm.all({ stageId }) as any[]).map(
|
||||
Match.#convertMatch,
|
||||
);
|
||||
}
|
||||
|
||||
static getByRoundAndNumber(
|
||||
roundId: TournamentRound["id"],
|
||||
number: TournamentMatch["number"],
|
||||
roundId: Tables["TournamentRound"]["id"],
|
||||
number: Tables["TournamentMatch"]["number"],
|
||||
): MatchType {
|
||||
const match = match_getByRoundAndNumberStm.get({ roundId, number }) as any;
|
||||
if (!match) return match;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
import shuffle from "just-shuffle";
|
||||
import type { Rating } from "node_modules/openskill/dist/types";
|
||||
import { ordinal } from "openskill";
|
||||
import type {
|
||||
MapResult,
|
||||
PlayerResult,
|
||||
Skill,
|
||||
TournamentResult,
|
||||
} from "~/db/types";
|
||||
import {
|
||||
identifierToUserIds,
|
||||
rate,
|
||||
|
|
@ -21,13 +15,16 @@ import type { Standing } from "./Bracket";
|
|||
|
||||
export interface TournamentSummary {
|
||||
skills: Omit<
|
||||
Skill,
|
||||
Tables["Skill"],
|
||||
"tournamentId" | "id" | "ordinal" | "season" | "groupMatchId"
|
||||
>[];
|
||||
seedingSkills: Tables["SeedingSkill"][];
|
||||
mapResultDeltas: Omit<MapResult, "season">[];
|
||||
playerResultDeltas: Omit<PlayerResult, "season">[];
|
||||
tournamentResults: Omit<TournamentResult, "tournamentId" | "isHighlight">[];
|
||||
mapResultDeltas: Omit<Tables["MapResult"], "season">[];
|
||||
playerResultDeltas: Omit<Tables["PlayerResult"], "season">[];
|
||||
tournamentResults: Omit<
|
||||
Tables["TournamentResult"],
|
||||
"tournamentId" | "isHighlight"
|
||||
>[];
|
||||
}
|
||||
|
||||
type UserIdToTeamId = Record<number, number>;
|
||||
|
|
@ -294,7 +291,7 @@ function mapResultDeltas(
|
|||
const result: TournamentSummary["mapResultDeltas"] = [];
|
||||
|
||||
const addMapResult = (
|
||||
mapResult: Pick<MapResult, "stageId" | "mode" | "userId"> & {
|
||||
mapResult: Pick<Tables["MapResult"], "stageId" | "mode" | "userId"> & {
|
||||
type: "win" | "loss";
|
||||
},
|
||||
) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { ordinal } from "openskill";
|
||||
import { sql } from "~/db/sql";
|
||||
import type { Skill } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { identifierToUserIds } from "~/features/mmr/mmr-utils";
|
||||
import type { TournamentSummary } from "../core/summarizer.server";
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ export const addSummary = sql.transaction(
|
|||
identifier: skill.identifier ?? null,
|
||||
matchesCount: skill.matchesCount,
|
||||
season: season ?? null,
|
||||
}) as Skill;
|
||||
}) as Tables["Skill"];
|
||||
|
||||
if (insertedSkill.identifier) {
|
||||
for (const userId of identifierToUserIds(insertedSkill.identifier)) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { TournamentMatch, TournamentRound } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
select
|
||||
|
|
@ -13,8 +13,8 @@ const stm = sql.prepare(/* sql */ `
|
|||
`);
|
||||
|
||||
interface BestOfByTournamentId {
|
||||
roundId: TournamentRound["id"];
|
||||
bestOf: TournamentMatch["bestOf"];
|
||||
roundId: Tables["TournamentRound"]["id"];
|
||||
bestOf: Tables["TournamentMatch"]["bestOf"];
|
||||
}
|
||||
|
||||
export function bestOfsByTournamentId(tournamentId: number) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { MapPoolMap } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/*sql*/ `
|
||||
select
|
||||
|
|
@ -12,5 +12,7 @@ const stm = sql.prepare(/*sql*/ `
|
|||
`);
|
||||
|
||||
export function findMapPoolByTeamId(teamId: number) {
|
||||
return stm.all({ teamId }) as Array<Pick<MapPoolMap, "stageId" | "mode">>;
|
||||
return stm.all({ teamId }) as Array<
|
||||
Pick<Tables["MapPoolMap"], "stageId" | "mode">
|
||||
>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { TournamentRoundMaps } from "~/db/tables";
|
||||
import type {
|
||||
Tournament,
|
||||
TournamentMatch,
|
||||
TournamentTeamMember,
|
||||
User,
|
||||
} from "~/db/types";
|
||||
import type { Tables, TournamentRoundMaps } from "~/db/tables";
|
||||
import type { Match } from "~/modules/brackets-model";
|
||||
import { parseDBArray } from "~/utils/sql";
|
||||
|
||||
|
|
@ -57,10 +51,12 @@ export type FindMatchById = ReturnType<typeof findMatchById>;
|
|||
export const findMatchById = (id: number) => {
|
||||
const row = stm.get({ id }) as
|
||||
| ((Pick<
|
||||
TournamentMatch,
|
||||
"id" | "groupId" | "opponentOne" | "opponentTwo" | "bestOf" | "chatCode"
|
||||
Tables["TournamentMatch"],
|
||||
"id" | "groupId" | "bestOf" | "chatCode"
|
||||
> &
|
||||
Pick<Tournament, "mapPickingStyle"> & { players: string }) & {
|
||||
Pick<Tables["Tournament"], "mapPickingStyle"> & { players: string }) & {
|
||||
opponentOne: string;
|
||||
opponentTwo: string;
|
||||
roundId: number;
|
||||
roundMaps: string | null;
|
||||
})
|
||||
|
|
@ -81,13 +77,13 @@ export const findMatchById = (id: number) => {
|
|||
opponentTwo: JSON.parse(row.opponentTwo) as Match["opponent2"],
|
||||
players: (
|
||||
parseDBArray(row.players) as Array<{
|
||||
id: User["id"];
|
||||
username: User["username"];
|
||||
tournamentTeamId: TournamentTeamMember["tournamentTeamId"];
|
||||
inGameName: User["inGameName"];
|
||||
discordId: User["discordId"];
|
||||
customUrl: User["customUrl"];
|
||||
discordAvatar: User["discordAvatar"];
|
||||
id: Tables["User"]["id"];
|
||||
username: Tables["User"]["username"];
|
||||
tournamentTeamId: Tables["TournamentTeamMember"]["tournamentTeamId"];
|
||||
inGameName: Tables["User"]["inGameName"];
|
||||
discordId: Tables["User"]["discordId"];
|
||||
customUrl: Tables["User"]["customUrl"];
|
||||
discordAvatar: Tables["User"]["discordAvatar"];
|
||||
chatNameColor: string | null;
|
||||
}>
|
||||
).filter((player) => player.id),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { TournamentMatchGameResult } from "~/db/types";
|
||||
import { parseDBArray } from "~/utils/sql";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
|
|
@ -27,17 +26,17 @@ const stm = sql.prepare(/* sql */ `
|
|||
`);
|
||||
|
||||
interface FindResultsByMatchIdResult {
|
||||
id: TournamentMatchGameResult["id"];
|
||||
winnerTeamId: TournamentMatchGameResult["winnerTeamId"];
|
||||
stageId: TournamentMatchGameResult["stageId"];
|
||||
mode: TournamentMatchGameResult["mode"];
|
||||
id: Tables["TournamentMatchGameResult"]["id"];
|
||||
winnerTeamId: Tables["TournamentMatchGameResult"]["winnerTeamId"];
|
||||
stageId: Tables["TournamentMatchGameResult"]["stageId"];
|
||||
mode: Tables["TournamentMatchGameResult"]["mode"];
|
||||
participants: Array<
|
||||
Pick<
|
||||
Tables["TournamentMatchGameResultParticipant"],
|
||||
"tournamentTeamId" | "userId"
|
||||
>
|
||||
>;
|
||||
createdAt: TournamentMatchGameResult["createdAt"];
|
||||
createdAt: Tables["TournamentMatchGameResult"]["createdAt"];
|
||||
opponentOnePoints: Tables["TournamentMatchGameResult"]["opponentOnePoints"];
|
||||
opponentTwoPoints: Tables["TournamentMatchGameResult"]["opponentTwoPoints"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { MapPoolMap } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/*sql*/ `
|
||||
select
|
||||
|
|
@ -17,6 +17,6 @@ const stm = sql.prepare(/*sql*/ `
|
|||
|
||||
export function findTieBreakerMapPoolByTournamentId(tournamentId: number) {
|
||||
return stm.all({ tournamentId }) as Array<
|
||||
Pick<MapPoolMap, "stageId" | "mode">
|
||||
Pick<Tables["MapPoolMap"], "stageId" | "mode">
|
||||
>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { TournamentMatchGameResult } from "~/db/types";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
insert into "TournamentMatchGameResult"
|
||||
|
|
@ -13,5 +12,5 @@ const stm = sql.prepare(/* sql */ `
|
|||
export function insertTournamentMatchGameResult(
|
||||
args: Omit<Tables["TournamentMatchGameResult"], "id" | "createdAt">,
|
||||
) {
|
||||
return stm.get(args) as TournamentMatchGameResult;
|
||||
return stm.get(args) as Tables["TournamentMatchGameResult"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
select
|
||||
|
|
@ -26,7 +26,7 @@ const stm = sql.prepare(/* sql */ `
|
|||
`);
|
||||
|
||||
export type PlayerThatPlayedByTeamId = Pick<
|
||||
User,
|
||||
Tables["User"],
|
||||
"id" | "username" | "discordAvatar" | "discordId" | "customUrl" | "country"
|
||||
> & { tournamentTeamId: number };
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import type { TFunction } from "i18next";
|
||||
import type { TournamentRoundMaps } from "~/db/tables";
|
||||
import type { TournamentMatch } from "~/db/types";
|
||||
import type { Tables, TournamentRoundMaps } from "~/db/tables";
|
||||
import type { TournamentManagerDataSet } from "~/modules/brackets-manager/types";
|
||||
import type { ModeShort, StageId } from "~/modules/in-game-lists";
|
||||
import type { TournamentMaplistSource } from "~/modules/tournament-map-list-generator";
|
||||
|
|
@ -28,7 +27,7 @@ const NUM_MAP = {
|
|||
"9": ["9", "6", "8"],
|
||||
"0": ["0", "8"],
|
||||
};
|
||||
export function resolveRoomPass(matchId: TournamentMatch["id"]) {
|
||||
export function resolveRoomPass(matchId: Tables["TournamentMatch"]["id"]) {
|
||||
let pass = "5";
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const { shuffle } = seededRandom(`${matchId}-${i}`);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { TournamentSub } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
delete from "TournamentSub"
|
||||
|
|
@ -9,7 +9,7 @@ const stm = sql.prepare(/* sql */ `
|
|||
`);
|
||||
|
||||
export function deleteSub(
|
||||
args: Pick<TournamentSub, "userId" | "tournamentId">,
|
||||
args: Pick<Tables["TournamentSub"], "userId" | "tournamentId">,
|
||||
) {
|
||||
stm.run(args);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { TournamentSub, UserWithPlusTier } from "~/db/types";
|
||||
import type { Tables, UserWithPlusTier } from "~/db/tables";
|
||||
import type { MainWeaponId } from "~/modules/in-game-lists";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
|
|
@ -31,13 +31,13 @@ const stm = sql.prepare(/* sql */ `
|
|||
`);
|
||||
|
||||
export interface SubByTournamentId {
|
||||
canVc: TournamentSub["canVc"];
|
||||
canVc: Tables["TournamentSub"]["canVc"];
|
||||
bestWeapons: MainWeaponId[];
|
||||
okWeapons: MainWeaponId[] | null;
|
||||
message: TournamentSub["message"];
|
||||
visibility: TournamentSub["visibility"];
|
||||
createdAt: TournamentSub["createdAt"];
|
||||
userId: TournamentSub["userId"];
|
||||
message: Tables["TournamentSub"]["message"];
|
||||
visibility: Tables["TournamentSub"]["visibility"];
|
||||
createdAt: Tables["TournamentSub"]["createdAt"];
|
||||
userId: Tables["TournamentSub"]["userId"];
|
||||
username: UserWithPlusTier["username"];
|
||||
discordAvatar: UserWithPlusTier["discordAvatar"];
|
||||
discordId: UserWithPlusTier["discordId"];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { TournamentSub } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
insert into "TournamentSub" (
|
||||
|
|
@ -30,6 +30,6 @@ const stm = sql.prepare(/* sql */ `
|
|||
"visibility" = @visibility
|
||||
`);
|
||||
|
||||
export function upsertSub(args: Omit<TournamentSub, "createdAt">) {
|
||||
export function upsertSub(args: Omit<Tables["TournamentSub"], "createdAt">) {
|
||||
stm.run(args);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Link } from "@remix-run/react";
|
|||
import clsx from "clsx";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { ModeImage, StageImage } from "~/components/Image";
|
||||
import type { MapPoolMap, User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import type { TournamentDataTeam } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
import { databaseTimestampToDate } from "~/utils/dates";
|
||||
|
|
@ -18,10 +18,10 @@ export function TeamWithRoster({
|
|||
activePlayers,
|
||||
}: {
|
||||
team: TournamentDataTeam;
|
||||
mapPool?: Array<Pick<MapPoolMap, "stageId" | "mode">> | null;
|
||||
mapPool?: Array<Pick<Tables["MapPoolMap"], "stageId" | "mode">> | null;
|
||||
seed?: number;
|
||||
teamPageUrl?: string;
|
||||
activePlayers?: User["id"][];
|
||||
activePlayers?: Tables["User"]["id"][];
|
||||
}) {
|
||||
const user = useUser();
|
||||
const tournament = useTournament();
|
||||
|
|
@ -136,7 +136,7 @@ function FreshAccountEmoji({ discordId }: { discordId: string }) {
|
|||
function TeamMapPool({
|
||||
mapPool,
|
||||
}: {
|
||||
mapPool: Array<Pick<MapPoolMap, "stageId" | "mode">>;
|
||||
mapPool: Array<Pick<Tables["MapPoolMap"], "stageId" | "mode">>;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import type { Tables } from "~/db/tables";
|
||||
import type { User } from "~/db/types";
|
||||
import type { ModeShort, StageId } from "~/modules/in-game-lists";
|
||||
import type { TournamentMaplistSource } from "~/modules/tournament-map-list-generator";
|
||||
import { sourceTypes } from "~/modules/tournament-map-list-generator";
|
||||
|
|
@ -31,7 +30,7 @@ export interface PlayedSet {
|
|||
/** Team's roster that played in this set */
|
||||
roster: Array<
|
||||
Pick<
|
||||
User,
|
||||
Tables["User"],
|
||||
"id" | "username" | "discordAvatar" | "discordId" | "customUrl"
|
||||
>
|
||||
>;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { TournamentTeam, User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
update TournamentTeamMember
|
||||
|
|
@ -11,9 +11,9 @@ const stm = sql.prepare(/* sql */ `
|
|||
|
||||
export const changeTeamOwner = sql.transaction(
|
||||
(args: {
|
||||
tournamentTeamId: TournamentTeam["id"];
|
||||
oldCaptainId: User["id"];
|
||||
newCaptainId: User["id"];
|
||||
tournamentTeamId: Tables["TournamentTeam"]["id"];
|
||||
oldCaptainId: Tables["User"]["id"];
|
||||
newCaptainId: Tables["User"]["id"];
|
||||
}) => {
|
||||
stm.run({
|
||||
tournamentTeamId: args.tournamentTeamId,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type {
|
||||
CalendarEvent,
|
||||
CalendarEventDate,
|
||||
Tournament,
|
||||
User,
|
||||
} from "~/db/types";
|
||||
|
||||
const stm = sql.prepare(/*sql*/ `
|
||||
select
|
||||
|
|
@ -29,13 +23,13 @@ select
|
|||
`);
|
||||
|
||||
type FindByIdentifierRow = (Pick<
|
||||
CalendarEvent,
|
||||
Tables["CalendarEvent"],
|
||||
"bracketUrl" | "name" | "description" | "authorId"
|
||||
> &
|
||||
Pick<Tournament, "id" | "mapPickingStyle"> &
|
||||
Pick<User, "discordId" | "username"> &
|
||||
Pick<CalendarEventDate, "startTime">) & {
|
||||
eventId: CalendarEvent["id"];
|
||||
Pick<Tables["Tournament"], "id" | "mapPickingStyle"> &
|
||||
Pick<Tables["User"], "discordId" | "username"> &
|
||||
Pick<Tables["CalendarEventDate"], "startTime">) & {
|
||||
eventId: Tables["CalendarEvent"]["id"];
|
||||
} & { settings: string };
|
||||
|
||||
export function findByIdentifier(identifier: string | number) {
|
||||
|
|
@ -59,7 +53,7 @@ export function findByIdentifier(identifier: string | number) {
|
|||
}
|
||||
|
||||
function resolveEarliestStartTime(
|
||||
rows: Pick<CalendarEventDate, "startTime">[],
|
||||
rows: Pick<Tables["CalendarEventDate"], "startTime">[],
|
||||
) {
|
||||
return Math.min(...rows.map((row) => row.startTime));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { MapPoolMap } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { parseDBArray } from "~/utils/sql";
|
||||
|
||||
const stm = sql.prepare(/*sql*/ `
|
||||
|
|
@ -20,7 +20,7 @@ const stm = sql.prepare(/*sql*/ `
|
|||
|
||||
interface FindMapPoolsByTournamentIdItem {
|
||||
tournamentTeamId: number;
|
||||
mapPool: Array<Pick<MapPoolMap, "mode" | "stageId">>;
|
||||
mapPool: Array<Pick<Tables["MapPoolMap"], "mode" | "stageId">>;
|
||||
}
|
||||
|
||||
export function findMapPoolsByTournamentId(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { TournamentTeam, TournamentTeamCheckIn } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/*sql*/ `
|
||||
select
|
||||
|
|
@ -20,8 +20,8 @@ const stm = sql.prepare(/*sql*/ `
|
|||
`);
|
||||
|
||||
type FindOwnTeam =
|
||||
| (Pick<TournamentTeam, "id" | "name" | "inviteCode"> &
|
||||
Pick<TournamentTeamCheckIn, "checkedInAt">)
|
||||
| (Pick<Tables["TournamentTeam"], "id" | "name" | "inviteCode"> &
|
||||
Pick<Tables["TournamentTeamCheckIn"], "checkedInAt">)
|
||||
| null;
|
||||
|
||||
export function findOwnTournamentTeam({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Tournament } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/*sql*/ `
|
||||
select 1
|
||||
|
|
@ -7,6 +7,8 @@ const stm = sql.prepare(/*sql*/ `
|
|||
where "TournamentResult"."tournamentId" = @tournamentId
|
||||
`);
|
||||
|
||||
export default function hasTournamentFinalized(tournamentId: Tournament["id"]) {
|
||||
export default function hasTournamentFinalized(
|
||||
tournamentId: Tables["Tournament"]["id"],
|
||||
) {
|
||||
return Boolean(stm.get({ tournamentId }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { Tournament } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
||||
const stm = sql.prepare(/*sql*/ `
|
||||
select 1
|
||||
|
|
@ -7,6 +7,8 @@ const stm = sql.prepare(/*sql*/ `
|
|||
where "TournamentStage"."tournamentId" = @tournamentId
|
||||
`);
|
||||
|
||||
export default function hasTournamentStarted(tournamentId: Tournament["id"]) {
|
||||
export default function hasTournamentStarted(
|
||||
tournamentId: Tables["Tournament"]["id"],
|
||||
) {
|
||||
return Boolean(stm.get({ tournamentId }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { TournamentMatchGameResult, User } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { ModeShort, StageId } from "~/modules/in-game-lists";
|
||||
import { removeDuplicatesByProperty } from "~/utils/arrays";
|
||||
import { parseDBArray } from "~/utils/sql";
|
||||
|
|
@ -89,12 +89,15 @@ export interface SetHistoryByTeamIdItem {
|
|||
groupNumber: number;
|
||||
matches: {
|
||||
stageId: StageId;
|
||||
source: TournamentMatchGameResult["source"];
|
||||
source: Tables["TournamentMatchGameResult"]["source"];
|
||||
mode: ModeShort;
|
||||
wasWinner: number;
|
||||
}[];
|
||||
players: Array<
|
||||
Pick<User, "id" | "username" | "discordAvatar" | "discordId" | "customUrl">
|
||||
Pick<
|
||||
Tables["User"],
|
||||
"id" | "username" | "discordAvatar" | "discordId" | "customUrl"
|
||||
>
|
||||
>;
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +113,7 @@ export function setHistoryByTeamId(
|
|||
// TODO: there is probably a way to do this in SQL
|
||||
players: removeDuplicatesByProperty(
|
||||
parseDBArray(row.players),
|
||||
(u: Pick<User, "id">) => u.id,
|
||||
(u: Pick<Tables["User"], "id">) => u.id,
|
||||
),
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { sql } from "~/db/sql";
|
||||
import type { TournamentTeam } from "~/db/types";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { MapPool } from "~/features/map-list-generator/core/map-pool";
|
||||
|
||||
const deleteCounterpickMapsByTeamIdStm = sql.prepare(/* sql */ `
|
||||
|
|
@ -21,7 +21,7 @@ export const upsertCounterpickMaps = sql.transaction(
|
|||
tournamentTeamId,
|
||||
mapPool,
|
||||
}: {
|
||||
tournamentTeamId: TournamentTeam["id"];
|
||||
tournamentTeamId: Tables["TournamentTeam"]["id"];
|
||||
mapPool: MapPool;
|
||||
}) => {
|
||||
deleteCounterpickMapsByTeamIdStm.run({ tournamentTeamId });
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import type { Params } from "@remix-run/react";
|
||||
import type { Tournament } from "~/db/types";
|
||||
import type { ModeShort, StageId } from "~/modules/in-game-lists";
|
||||
import { rankedModesShort } from "~/modules/in-game-lists/modes";
|
||||
import { weekNumberToDate } from "~/utils/dates";
|
||||
|
|
@ -23,7 +22,7 @@ export function tournamentIdFromParams(params: Params<string>) {
|
|||
}
|
||||
|
||||
export function modesIncluded(
|
||||
tournament: Pick<Tournament, "mapPickingStyle">,
|
||||
tournament: Pick<Tables["Tournament"], "mapPickingStyle">,
|
||||
): ModeShort[] {
|
||||
switch (tournament.mapPickingStyle) {
|
||||
case "AUTO_SZ": {
|
||||
|
|
@ -45,7 +44,7 @@ export function modesIncluded(
|
|||
}
|
||||
|
||||
export function isOneModeTournamentOf(
|
||||
tournament: Pick<Tournament, "mapPickingStyle">,
|
||||
tournament: Pick<Tables["Tournament"], "mapPickingStyle">,
|
||||
) {
|
||||
return modesIncluded(tournament).length === 1
|
||||
? modesIncluded(tournament)[0]
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ import { db, sql as dbDirect } from "~/db/sql";
|
|||
import type {
|
||||
BuildSort,
|
||||
DB,
|
||||
Tables,
|
||||
TablesInsertable,
|
||||
UserPreferences,
|
||||
} from "~/db/tables";
|
||||
import type { User } from "~/db/types";
|
||||
import { dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import invariant from "~/utils/invariant";
|
||||
import type { CommonUser } from "~/utils/kysely.server";
|
||||
|
|
@ -744,7 +744,7 @@ export function updateBuildSorting({
|
|||
}
|
||||
|
||||
export type UpdatePatronDataArgs = Array<
|
||||
Pick<User, "discordId" | "patronTier" | "patronSince">
|
||||
Pick<Tables["User"], "discordId" | "patronTier" | "patronSince">
|
||||
>;
|
||||
export function updatePatronData(users: UpdatePatronDataArgs) {
|
||||
return db.transaction().execute(async (trx) => {
|
||||
|
|
@ -792,7 +792,7 @@ export const updateMany = dbDirect.transaction(
|
|||
(
|
||||
argsArr: Array<
|
||||
Pick<
|
||||
User,
|
||||
Tables["User"],
|
||||
"discordAvatar" | "discordName" | "discordUniqueName" | "discordId"
|
||||
>
|
||||
>,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import { SubmitButton } from "~/components/SubmitButton";
|
|||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import { PlusIcon } from "~/components/icons/Plus";
|
||||
import { BUILD } from "~/constants";
|
||||
import type { GearType } from "~/db/types";
|
||||
import {
|
||||
validatedBuildFromSearchParams,
|
||||
validatedWeaponIdFromSearchParams,
|
||||
|
|
@ -35,6 +34,7 @@ import type { SendouRouteHandle } from "~/utils/remix.server";
|
|||
import { modeImageUrl } from "~/utils/urls";
|
||||
import type { UserPageLoaderData } from "./u.$identifier";
|
||||
|
||||
import type { GearType } from "~/db/tables";
|
||||
import { action } from "../actions/u.$identifier.builds.new.server";
|
||||
import { loader } from "../loaders/u.$identifier.builds.new.server";
|
||||
export { loader, action };
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import { StarIcon } from "~/components/icons/Star";
|
|||
import { StarFilledIcon } from "~/components/icons/StarFilled";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import { USER } from "~/constants";
|
||||
import type { User } from "~/db/types";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { requireUser, requireUserId } from "~/features/auth/core/user.server";
|
||||
import * as TournamentTeamRepository from "~/features/tournament/TournamentTeamRepository.server";
|
||||
|
|
@ -56,6 +55,7 @@ import { userParamsSchema } from "../user-page-schemas.server";
|
|||
import type { UserPageLoaderData } from "./u.$identifier";
|
||||
import "~/styles/u-edit.css";
|
||||
import { SendouSwitch } from "~/components/elements/Switch";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { clearTournamentDataCache } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
|
||||
export const userEditActionSchema = z
|
||||
|
|
@ -555,7 +555,9 @@ function WeaponPoolSelect() {
|
|||
);
|
||||
}
|
||||
|
||||
function BioTextarea({ initialValue }: { initialValue: User["bio"] }) {
|
||||
function BioTextarea({
|
||||
initialValue,
|
||||
}: { initialValue: Tables["User"]["bio"] }) {
|
||||
const { t } = useTranslation("user");
|
||||
const [value, setValue] = React.useState(initialValue ?? "");
|
||||
|
||||
|
|
@ -664,7 +666,7 @@ function CommissionsOpenToggle({
|
|||
function CommissionTextArea({
|
||||
initialValue,
|
||||
}: {
|
||||
initialValue: User["commissionText"];
|
||||
initialValue: Tables["User"]["commissionText"];
|
||||
}) {
|
||||
const { t } = useTranslation(["user"]);
|
||||
const [value, setValue] = React.useState(initialValue ?? "");
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user