feat: implement variable team matchups with partner rotation

- Add manual team entry for permanent teams in Matchups tab
- Rename 'Teams' tab to 'Matchups' for clarity
- Implement partner rotation strategies (minimize_repeat, maximize_even, elo_based)
- Track partnerships across rounds to minimize repeat pairings
- Fix unit tests for team configuration and ELO calculations
- Add E2E test for 9+ participant tournaments with variable matchups

Key changes:
- TeamsSection.tsx: Added router.refresh(), manual team entry, and matchup display
- schedule-generator.ts: Enhanced generateVariableRoundRobin to track partnerships
- team-generator.ts: Fixed partnership frequency tracking across rounds
- API routes: Updated to support variable team durability with rotation strategies
This commit is contained in:
2026-04-04 00:24:57 -07:00
parent eeb0f7970a
commit 62ac6d1b79
24 changed files with 3106 additions and 868 deletions
+61
View File
@@ -30,3 +30,64 @@ export async function GET() {
);
}
}
/**
* POST /api/players
*
* Create a new player
* This is a public endpoint (no authentication required)
* Returns 409 if player with same name already exists
*/
export async function POST(request: Request) {
try {
const body = await request.json();
const { name } = body;
// Validate name
if (!name || typeof name !== 'string' || name.trim().length === 0) {
return NextResponse.json(
{ error: "Player name is required" },
{ status: 400 }
);
}
const trimmedName = name.trim();
const normalizedName = trimmedName.toLowerCase();
// Check if player with same name already exists
const existingPlayer = await prisma.player.findUnique({
where: { normalizedName },
});
if (existingPlayer) {
return NextResponse.json(
{ error: `Player "${trimmedName}" already exists` },
{ status: 409 }
);
}
// Create new player
const newPlayer = await prisma.player.create({
data: {
name: trimmedName,
normalizedName,
currentElo: 1000,
gamesPlayed: 0,
wins: 0,
losses: 0,
},
});
return NextResponse.json(
{ success: true, player: newPlayer },
{ status: 201 }
);
} catch (error: unknown) {
console.error("Error creating player:", error);
const message = error instanceof Error ? error.message : "Failed to create player";
return NextResponse.json(
{ error: message },
{ status: 500 }
);
}
}