mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-11-14 16:58:11 -06:00
Use Series.findByEventName everywhere a series is matched by event name
This commit is contained in:
@@ -33,6 +33,7 @@ import * as SQMatchRepository from "~/features/sendouq-match/SQMatchRepository.s
|
||||
import * as SplatoonRotationRepository from "~/features/splatoon-rotations/SplatoonRotationRepository.server";
|
||||
import { getViewerTimezone } from "~/features/timezone/timezone-context.server";
|
||||
import { eventLeaderboards } from "~/features/tournament-organization/core/leaderboards.server";
|
||||
import * as Series from "~/features/tournament-organization/core/Series";
|
||||
import type {
|
||||
BuildAbilitiesTuple,
|
||||
MainWeaponId,
|
||||
@@ -3467,13 +3468,12 @@ async function seriesWinOf(result: {
|
||||
}) {
|
||||
if (result.organizationId === null) return null;
|
||||
|
||||
const series = (
|
||||
await FeedRepository.findSeriesByOrganizationId(result.organizationId)
|
||||
).find((s) =>
|
||||
s.substringMatches.some((sub) =>
|
||||
result.name.toLowerCase().includes(sub.toLowerCase()),
|
||||
const series = Series.findByEventName({
|
||||
series: await FeedRepository.findSeriesByOrganizationId(
|
||||
result.organizationId,
|
||||
),
|
||||
);
|
||||
eventName: result.name,
|
||||
});
|
||||
if (!series) return null;
|
||||
|
||||
return {
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
} from "~/utils/kysely.server";
|
||||
import { toDBBoolean } from "~/utils/sql";
|
||||
import { mySlugify } from "~/utils/urls";
|
||||
import * as Series from "./core/Series";
|
||||
import { TOURNAMENT_SERIES_EVENTS_PER_PAGE } from "./tournament-organization-constants";
|
||||
|
||||
interface CreateArgs {
|
||||
@@ -544,11 +545,7 @@ export async function findAllSeriesWinsByUserId({
|
||||
eb.and([
|
||||
eb("CalendarEvent.organizationId", "=", organizationId),
|
||||
eb("CalendarEvent.hidden", "=", 0),
|
||||
eb.or(
|
||||
substringMatches.map((match) =>
|
||||
eb("CalendarEvent.name", "like", `%${match}%`),
|
||||
),
|
||||
),
|
||||
calendarEventNameMatchesSeries(substringMatches)(eb),
|
||||
]);
|
||||
|
||||
const tournamentWins = await db
|
||||
@@ -772,12 +769,9 @@ export function update({
|
||||
|
||||
for (const s of insertedSeries) {
|
||||
const matchingTiers = finalizedTournaments
|
||||
.filter((t) => {
|
||||
const eventNameLower = t.name.toLowerCase();
|
||||
return s.substringMatches.some((match) =>
|
||||
eventNameLower.includes(match.toLowerCase()),
|
||||
);
|
||||
})
|
||||
.filter((t) =>
|
||||
Series.matchesEventName({ series: s, eventName: t.name }),
|
||||
)
|
||||
.filter((t) => t.tier !== null)
|
||||
.map((t) => t.tier);
|
||||
|
||||
@@ -932,12 +926,7 @@ export async function updateSeriesTierHistory({
|
||||
.where("organizationId", "=", organizationId)
|
||||
.execute();
|
||||
|
||||
const eventNameLower = eventName.toLowerCase();
|
||||
const matchingSeries = series.find((s) =>
|
||||
s.substringMatches.some((match) =>
|
||||
eventNameLower.includes(match.toLowerCase()),
|
||||
),
|
||||
);
|
||||
const matchingSeries = Series.findByEventName({ series, eventName });
|
||||
|
||||
if (!matchingSeries) return;
|
||||
|
||||
|
||||
18
app/features/tournament-organization/core/Series.test.ts
Normal file
18
app/features/tournament-organization/core/Series.test.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import * as Series from "./Series";
|
||||
|
||||
describe("Series.findByEventName", () => {
|
||||
const series = [
|
||||
{ id: 1, substringMatches: ["low ink"] },
|
||||
{ id: 2, substringMatches: ["Swim Or Sink", "sos"] },
|
||||
];
|
||||
|
||||
test.each([
|
||||
{ why: "lower-cased match", eventName: "Low Ink November", expected: 1 },
|
||||
{ why: "mixed-case match", eventName: "swim or sink 42", expected: 2 },
|
||||
{ why: "second substring", eventName: "SOS #12", expected: 2 },
|
||||
{ why: "no match", eventName: "In The Zone 40", expected: undefined },
|
||||
])("$why", ({ eventName, expected }) => {
|
||||
expect(Series.findByEventName({ series, eventName })?.id).toBe(expected);
|
||||
});
|
||||
});
|
||||
@@ -6,11 +6,22 @@ export function findByEventName<T extends { substringMatches: string[] }>({
|
||||
series: T[];
|
||||
eventName: string;
|
||||
}) {
|
||||
const eventNameLower = eventName.toLowerCase();
|
||||
|
||||
return series.find((oneSeries) =>
|
||||
oneSeries.substringMatches.some((substringMatch) =>
|
||||
eventNameLower.includes(substringMatch.toLowerCase()),
|
||||
),
|
||||
matchesEventName({ series: oneSeries, eventName }),
|
||||
);
|
||||
}
|
||||
|
||||
/** Whether one of the series' substrings appears in the event's name. */
|
||||
export function matchesEventName({
|
||||
series,
|
||||
eventName,
|
||||
}: {
|
||||
series: { substringMatches: string[] };
|
||||
eventName: string;
|
||||
}) {
|
||||
const eventNameLower = eventName.toLowerCase();
|
||||
|
||||
return series.substringMatches.some((substringMatch) =>
|
||||
eventNameLower.includes(substringMatch.toLowerCase()),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import * as R from "remeda";
|
||||
import { cache, ttl } from "~/utils/cache.server";
|
||||
import { dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import * as TournamentOrganizationRepository from "../TournamentOrganizationRepository.server";
|
||||
import * as Series from "./Series";
|
||||
|
||||
const CACHE_KEY = "series-team-counts";
|
||||
/** How old an edition can be and still say something about the next one. */
|
||||
@@ -33,12 +34,10 @@ export async function lookup() {
|
||||
const series = seriesByOrganizationId.get(tournament.organizationId);
|
||||
if (!series) return tournament.teamCount;
|
||||
|
||||
const nameLower = tournament.name.toLowerCase();
|
||||
const match = series.find((candidate) =>
|
||||
candidate.substringMatches.some((substring) =>
|
||||
nameLower.includes(substring.toLowerCase()),
|
||||
),
|
||||
);
|
||||
const match = Series.findByEventName({
|
||||
series,
|
||||
eventName: tournament.name,
|
||||
});
|
||||
if (!match) return tournament.teamCount;
|
||||
|
||||
return Math.max(
|
||||
@@ -71,9 +70,7 @@ async function seriesTeamCounts() {
|
||||
.filter(
|
||||
(tournament) =>
|
||||
tournament.organizationId === row.organizationId &&
|
||||
row.substringMatches.some((substring) =>
|
||||
tournament.name.toLowerCase().includes(substring.toLowerCase()),
|
||||
),
|
||||
Series.matchesEventName({ series: row, eventName: tournament.name }),
|
||||
)
|
||||
.slice(-EDITIONS_CONSIDERED)
|
||||
.map((tournament) => tournament.teamCount);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { calculateTentativeTier } from "~/features/tournament/core/tiering";
|
||||
import * as TrophyRepository from "~/features/trophies/TrophyRepository.server";
|
||||
import type { SerializeFrom } from "~/utils/remix";
|
||||
import { eventLeaderboards } from "../core/leaderboards.server";
|
||||
import * as Series from "../core/Series";
|
||||
import * as TournamentOrganizationRepository from "../TournamentOrganizationRepository.server";
|
||||
import { TOURNAMENT_SERIES_LEADERBOARD_SIZE } from "../tournament-organization-constants";
|
||||
import { tournamentOrganizationSearchParams } from "../tournament-organization-search-params";
|
||||
@@ -27,9 +28,12 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
|
||||
|
||||
const seriesId =
|
||||
_seriesId ??
|
||||
organization.series.find((s) =>
|
||||
s.substringMatches.some((match) => source?.toLowerCase().includes(match)),
|
||||
)?.id;
|
||||
(source
|
||||
? Series.findByEventName({
|
||||
series: organization.series,
|
||||
eventName: source,
|
||||
})?.id
|
||||
: undefined);
|
||||
|
||||
const seriesInfo = async () => {
|
||||
const series = seriesId
|
||||
|
||||
Reference in New Issue
Block a user