feat: add award winner resolver with tiebreak logic and tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt
2026-04-06 16:34:44 -04:00
parent de12b232d9
commit 4d68392ada
2 changed files with 84 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
/**
* Resolve the winner of a PICK_WINNER award given all votes and the chair's userId.
* Logic: count votes per project. If one project has the most, it wins.
* If tied, the chair's pick wins among the tied projects.
*/
export function resolveAwardWinner(
votes: Array<{ userId: string; projectId: string }>,
chairUserId: string
): string {
if (votes.length === 0) {
throw new Error('Cannot resolve winner with no votes')
}
// Tally votes per project
const tally = new Map<string, number>()
for (const v of votes) {
tally.set(v.projectId, (tally.get(v.projectId) || 0) + 1)
}
const maxVotes = Math.max(...tally.values())
const topProjects = [...tally.entries()]
.filter(([, count]) => count === maxVotes)
.map(([pid]) => pid)
if (topProjects.length === 1) {
return topProjects[0]
}
// Tie: chair's pick wins if among tied projects
const chairVote = votes.find((v) => v.userId === chairUserId)
if (chairVote && topProjects.includes(chairVote.projectId)) {
return chairVote.projectId
}
// Chair voted for a non-tied project — pick alphabetically for stability
return topProjects.sort()[0]
}