From b079a2f99df0b3de99040f20831fe007958cb21e Mon Sep 17 00:00:00 2001 From: aamoghS Date: Wed, 18 Feb 2026 17:44:45 -0500 Subject: [PATCH 1/2] new --- packages/api/src/routers/judge.ts | 6 ++++++ packages/db/src/schemas/hackathons.ts | 4 ++++ packages/db/src/schemas/judge.ts | 3 +++ sites/mainweb/app/(portal)/judge/page.tsx | 8 ++++++-- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/api/src/routers/judge.ts b/packages/api/src/routers/judge.ts index 00c134c..5c95204 100644 --- a/packages/api/src/routers/judge.ts +++ b/packages/api/src/routers/judge.ts @@ -609,6 +609,9 @@ export const judgeRouter = createTRPCRouter({ teamMembers: z.string().max(500).optional(), projectUrl: z.string().url().optional(), repoUrl: z.string().url().optional(), + tracks: z.array(z.string()).optional(), + challenges: z.array(z.string()).optional(), + isCreateX: z.boolean().default(false), }) ) .mutation(async ({ ctx, input }) => { @@ -631,6 +634,9 @@ export const judgeRouter = createTRPCRouter({ tableNumber: z.number().min(1), category: z.string().max(100).optional(), teamMembers: z.string().max(500).optional(), + tracks: z.array(z.string()).optional(), + challenges: z.array(z.string()).optional(), + isCreateX: z.boolean().default(false), }) ), }) diff --git a/packages/db/src/schemas/hackathons.ts b/packages/db/src/schemas/hackathons.ts index 81456a3..aee7e5d 100644 --- a/packages/db/src/schemas/hackathons.ts +++ b/packages/db/src/schemas/hackathons.ts @@ -101,6 +101,10 @@ export const hackathonProjects = pgTable("hackathon_project", { name: text("name").notNull(), description: text("description").notNull(), technologies: text("technologies").array(), + tracks: text("tracks").array(), // Enum: GEN-AI, SPORTS, FINANCE, HEALTH, CYBER, NONE + challenges: text("challenges").array(), // Enum: AGG, ASSURANT, AWS, CAPONE, GROWTH, MLH_MONGODB, MLH_STREAMLIT, MLH_TECH, MLH_CLOUDFLARE, MLH_REACH_CAPITAL + isCreateX: boolean("is_create_x").default(false), + teamMembers: text("team_members").array(), // Store names/emails if not fully linked githubUrl: text("github_url"), demoUrl: text("demo_url"), videoUrl: text("video_url"), diff --git a/packages/db/src/schemas/judge.ts b/packages/db/src/schemas/judge.ts index f984314..6de0657 100644 --- a/packages/db/src/schemas/judge.ts +++ b/packages/db/src/schemas/judge.ts @@ -44,6 +44,9 @@ export const judgingProjects = pgTable("judging_project", { description: text("description"), tableNumber: integer("table_number").notNull(), category: text("category"), // e.g., "AI", "Web3", "Health", "Sustainability" + tracks: text("tracks").array(), + challenges: text("challenges").array(), + isCreateX: boolean("is_create_x").default(false), teamMembers: text("team_members"), // comma-separated or JSON string projectUrl: text("project_url"), repoUrl: text("repo_url"), diff --git a/sites/mainweb/app/(portal)/judge/page.tsx b/sites/mainweb/app/(portal)/judge/page.tsx index 0bfc32e..70168b5 100644 --- a/sites/mainweb/app/(portal)/judge/page.tsx +++ b/sites/mainweb/app/(portal)/judge/page.tsx @@ -328,7 +328,9 @@ export default function JudgePage() {

{project.name}

- {project.teamMembers &&

{project.teamMembers}

} + {project.teamMembers &&

{project.teamMembers}

} + +
@@ -398,7 +400,9 @@ export default function JudgePage() {

{project.name}

- {project.teamMembers &&

{project.teamMembers}

} + {project.teamMembers &&

{project.teamMembers}

} + +
From 4decaddebfd30c1fff8087fd3d393c0607acafd4 Mon Sep 17 00:00:00 2001 From: aamoghS Date: Wed, 18 Feb 2026 18:29:29 -0500 Subject: [PATCH 2/2] pushing --- packages/api/src/routers/hackathon.ts | 14 +++ packages/api/src/routers/judge.ts | 41 ++++++- packages/db/src/schemas/judge.ts | 1 + .../app/(portal)/admin-judging/page.tsx | 110 ++++++++++++++++++ sites/mainweb/app/(portal)/judge/page.tsx | 5 + 5 files changed, 167 insertions(+), 4 deletions(-) diff --git a/packages/api/src/routers/hackathon.ts b/packages/api/src/routers/hackathon.ts index bd5da5e..94aa956 100644 --- a/packages/api/src/routers/hackathon.ts +++ b/packages/api/src/routers/hackathon.ts @@ -267,6 +267,13 @@ export const hackathonRouter = createTRPCRouter({ const participants = await ctx.db!.query.hackathonParticipants.findMany({ where: eq(hackathonParticipants.hackathonId, input.hackathonId), + columns: { + id: true, + hackathonId: true, + userId: true, + teamId: true, + registrationStatus: true, + }, with: { user: { columns: { @@ -357,6 +364,13 @@ export const hackathonRouter = createTRPCRouter({ team: { with: { participants: { + columns: { + id: true, + hackathonId: true, + userId: true, + teamId: true, + registrationStatus: true, + }, with: { user: { columns: { diff --git a/packages/api/src/routers/judge.ts b/packages/api/src/routers/judge.ts index 5c95204..17750bf 100644 --- a/packages/api/src/routers/judge.ts +++ b/packages/api/src/routers/judge.ts @@ -389,6 +389,9 @@ export const judgeRouter = createTRPCRouter({ tableNumber: project.tableNumber, category: project.category, teamMembers: project.teamMembers, + tracks: project.tracks, + challenges: project.challenges, + isCreateX: project.isCreateX, }, totalScore, voteCount, @@ -554,6 +557,7 @@ export const judgeRouter = createTRPCRouter({ judgeId: z.string().uuid(), hackathonId: z.string().uuid(), isLead: z.boolean().optional(), + track: z.string().optional(), }) ) .mutation(async ({ ctx, input }) => { @@ -577,17 +581,28 @@ export const judgeRouter = createTRPCRouter({ judgeId: input.judgeId, hackathonId: input.hackathonId, isLead: input.isLead || false, + track: input.track, }) .returning(); - const projects = await ctx.db!.query.judgingProjects.findMany({ + // Fetch all projects for this hackathon + const allProjects = await ctx.db!.query.judgingProjects.findMany({ where: eq(judgingProjects.hackathonId, input.hackathonId), orderBy: [asc(judgingProjects.tableNumber)], }); - if (projects.length > 0) { + // Filter based on track if assigned + const assignedProjects = input.track + ? allProjects.filter((p) => { + const inTracks = p.tracks?.includes(input.track!) ?? false; + const inChallenges = p.challenges?.includes(input.track!) ?? false; + return inTracks || inChallenges; + }) + : allProjects; + + if (assignedProjects.length > 0) { await ctx.db!.insert(judgeQueue).values( - projects.map((p, idx) => ({ + assignedProjects.map((p, idx) => ({ judgeId: input.judgeId, hackathonId: input.hackathonId, projectId: p.id, @@ -691,11 +706,29 @@ export const judgeRouter = createTRPCRouter({ ) ); - let projects = await ctx.db!.query.judgingProjects.findMany({ + // Get judge assignment to check for track restriction + const assignment = await ctx.db!.query.judgeAssignments.findFirst({ + where: and( + eq(judgeAssignments.judgeId, input.judgeId), + eq(judgeAssignments.hackathonId, input.hackathonId) + ), + }); + + // Fetch all projects (or filter in query if possible, but JS filter matches assignToHackathon logic) + const allProjects = await ctx.db!.query.judgingProjects.findMany({ where: eq(judgingProjects.hackathonId, input.hackathonId), orderBy: [asc(judgingProjects.tableNumber)], }); + // Filter based on track if assigned + let projects = (assignment?.track) + ? allProjects.filter((p) => { + const inTracks = p.tracks?.includes(assignment.track!) ?? false; + const inChallenges = p.challenges?.includes(assignment.track!) ?? false; + return inTracks || inChallenges; + }) + : allProjects; + if (input.shuffle) { projects = shuffleArray(projects); } diff --git a/packages/db/src/schemas/judge.ts b/packages/db/src/schemas/judge.ts index 6de0657..a6718a9 100644 --- a/packages/db/src/schemas/judge.ts +++ b/packages/db/src/schemas/judge.ts @@ -28,6 +28,7 @@ export const judgeAssignments = pgTable("judge_assignment", { .references(() => hackathons.id, { onDelete: "cascade" }), assignedAt: timestamp("assigned_at").defaultNow().notNull(), isLead: boolean("is_lead").notNull().default(false), + track: text("track"), // Optional: if set, judge only sees projects in this track/challenge }, (table) => [ index("assignment_judge_id_idx").on(table.judgeId), index("assignment_hackathon_id_idx").on(table.hackathonId), diff --git a/sites/mainweb/app/(portal)/admin-judging/page.tsx b/sites/mainweb/app/(portal)/admin-judging/page.tsx index 93c78de..197bcc2 100644 --- a/sites/mainweb/app/(portal)/admin-judging/page.tsx +++ b/sites/mainweb/app/(portal)/admin-judging/page.tsx @@ -227,6 +227,116 @@ export default function AdminResultsPage() { )} + {/* Projected Winners Section */} + {rankings && rankings.rankings.length > 0 && ( +
+

+ Projected Winners +

+ + {/* Logic Calculation */} + {(() => { + // 1. Identify Overall Winners (Top 3) + // Sort by total score descending + const sortedByScore = [...rankings.rankings].sort((a, b) => b.totalScore - a.totalScore); + const overallWinners = sortedByScore.slice(0, 3); + const overallWinnerIds = new Set(overallWinners.map(r => r.project.id)); + + // 2. Identify Track Winners (Top 1 per Track, excluding Overall) + // Get all unique tracks + const allTracks = Array.from(new Set(rankings.rankings.flatMap(r => r.project.tracks || []))); + const trackWinners: Record = {}; + const usedWinnerIds = new Set(overallWinnerIds); + + allTracks.forEach(track => { + // Find highest scoring project in this track that hasn't won yet + const candidate = sortedByScore.find(r => + r.project.tracks?.includes(track) && !usedWinnerIds.has(r.project.id) + ); + + if (candidate) { + trackWinners[track] = candidate; + usedWinnerIds.add(candidate.project.id); + } + }); + + // 3. Identify Challenge (Sponsor) Winners (Top 1 per Challenge, NO exclusions) + const allChallenges = Array.from(new Set(rankings.rankings.flatMap(r => r.project.challenges || []))); + const challengeWinners: Record = {}; + + allChallenges.forEach(challenge => { + const candidate = sortedByScore.find(r => r.project.challenges?.includes(challenge)); + if (candidate) { + challengeWinners[challenge] = candidate; + } + }); + + return ( +
+ {/* Overall Winners */} +
+ {overallWinners.map((w, i) => ( + +

+ {i === 0 ? 'Grand Prize' : i === 1 ? '2nd Place' : '3rd Place'} +

+

{w.project.name}

+

{w.totalScore}

+

ID: {w.project.id.slice(-6).toUpperCase()}

+
+ ))} +
+ + {/* Track Winners */} + {Object.keys(trackWinners).length > 0 && ( +
+

+ Track Winners (Excl. Overall) +

+
+ {Object.entries(trackWinners).map(([track, w]) => ( +
+

{track}

+

{w.project.name}

+

{w.totalScore}

+
+ ))} +
+
+ )} + + {/* Challenge Winners */} + {Object.keys(challengeWinners).length > 0 && ( +
+

+ Challenge Winners (Sponsors) +

+
+ {Object.entries(challengeWinners).map(([challenge, w]) => ( +
+

{challenge}

+

{w.project.name}

+
+

{w.totalScore}

+ {overallWinnerIds.has(w.project.id) && ( + Also Overall + )} +
+
+ ))} +
+
+ )} +
+ ); + })()} +
+ )} + + {/* Rankings Table Logic... */} {/* Rankings Table */}
diff --git a/sites/mainweb/app/(portal)/judge/page.tsx b/sites/mainweb/app/(portal)/judge/page.tsx index 70168b5..446ffa7 100644 --- a/sites/mainweb/app/(portal)/judge/page.tsx +++ b/sites/mainweb/app/(portal)/judge/page.tsx @@ -327,6 +327,11 @@ export default function JudgePage() {
+ {assignments?.[0]?.track && ( +
+ Track: {assignments[0].track} +
+ )}

{project.name}

{project.teamMembers &&

{project.teamMembers}

}