From 8d835fe650ab9073cfb95074d5435476ab23e1db Mon Sep 17 00:00:00 2001 From: Aaron Diaz Date: Wed, 16 Oct 2024 01:24:31 -0600 Subject: [PATCH] Minor improvements --- .../admin/participant/identities/generate.ts | 58 ++++++++++++++----- src/types/participation.schema.ts | 2 +- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/pages/api/admin/participant/identities/generate.ts b/src/pages/api/admin/participant/identities/generate.ts index 6230055..b7cc81b 100644 --- a/src/pages/api/admin/participant/identities/generate.ts +++ b/src/pages/api/admin/participant/identities/generate.ts @@ -1,12 +1,9 @@ import { findMostRecentOfmi, findParticipants } from "@/lib/ofmi"; -import { - ContestantParticipationInput, - ContestantParticipationInputSchema, -} from "@/types/participation.schema"; +import { VolunteerParticipationInputSchema } from "@/types/participation.schema"; import { Value } from "@sinclair/typebox/build/cjs/value"; import { NextApiRequest, NextApiResponse } from "next"; import countries from "@/lib/address/iso-3166-countries.json"; -import { capitalizeInitials, getMexStateCode } from "@/utils"; +import { capitalizeInitials, filterNull, getMexStateCode } from "@/utils"; async function generateIdentitiesHandler( req: NextApiRequest, @@ -14,15 +11,48 @@ async function generateIdentitiesHandler( ): Promise { const ofmi = await findMostRecentOfmi(); const allParticipants = await findParticipants(ofmi); - const onlyContestants = allParticipants.filter((participant) => { - return Value.Check( - ContestantParticipationInputSchema, - participant.userParticipation, - ); - }); + const onlyContestants = filterNull( + allParticipants.map((participant) => { + if ( + Value.Check( + VolunteerParticipationInputSchema, + participant.userParticipation, + ) + ) { + return null; + } + return { + ofmiEdition: participant.ofmiEdition, + user: participant.user, + userParticipation: participant.userParticipation, + }; + }), + ); + + const states = new Map(); + + const getMaxContestantsCount = ( + contestants: typeof onlyContestants, + ): number => { + let maxi = 0; + const states = new Map(); + // Mexican contestants are divided by their state + // International contestants are divided by their country + // Among all these different groups, find the one with the greatest amount of participants. + // This is done to make sure participant usernames are as short as possible. + for (const contestant of contestants) { + let state = contestant.userParticipation.schoolCountry; + if (state === "Mexico") { + state = contestant.userParticipation.schoolState; + } + const count = (states.get(state) || 0) + 1; + maxi = Math.max(maxi, count); + states.set(state, count); + } + return maxi; + }; - const states = new Map(); - const minDigits = Math.log10(onlyContestants.length); + const minDigits = Math.log10(getMaxContestantsCount(onlyContestants)); const generateUsername = (state: string): string => { const rawNumber = (states.get(state) || 0) + 1; @@ -34,7 +64,7 @@ async function generateIdentitiesHandler( onlyContestants.map((contestant) => { const { user, userParticipation } = contestant; - const participation = userParticipation as ContestantParticipationInput; + const participation = userParticipation; const country = countries.find((country) => { return country.name === participation.schoolCountry; }) || { diff --git a/src/types/participation.schema.ts b/src/types/participation.schema.ts index 5fc7238..29556f4 100644 --- a/src/types/participation.schema.ts +++ b/src/types/participation.schema.ts @@ -87,7 +87,7 @@ export const ContestantParticipationInputSchema = Type.Object({ schoolState: Type.String({ minLength: 1 }), }); -const VolunteerParticipationInputSchema = Type.Object({ +export const VolunteerParticipationInputSchema = Type.Object({ role: Type.Literal(ParticipationRole.VOLUNTEER), educationalLinkageOptIn: Type.Boolean(), fundraisingOptIn: Type.Boolean(),