Erlaube das Hinzufügen von Teilnehmern ohne Klasse und normalisiere die Anzahl der Gruppen auf mindestens 1 in der Turnierverwaltung
This commit is contained in:
@@ -9,6 +9,7 @@ vi.mock('../utils/userUtils.js', async () => {
|
||||
});
|
||||
|
||||
import sequelize from '../database.js';
|
||||
import { Op } from 'sequelize';
|
||||
import '../models/index.js';
|
||||
|
||||
import tournamentService from '../services/tournamentService.js';
|
||||
@@ -73,4 +74,93 @@ describe('tournamentService', () => {
|
||||
const matches = await tournamentService.getTournamentMatches('token', club.id, tournament.id);
|
||||
expect(matches.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('erlaubt Teilnehmer ohne Klasse', async () => {
|
||||
const club = await Club.create({ name: 'Tournament Club' });
|
||||
const memberA = await createMember(club.id, {
|
||||
firstName: 'Clara',
|
||||
lastName: 'C',
|
||||
email: 'clara@example.com',
|
||||
gender: 'female',
|
||||
});
|
||||
|
||||
const tournament = await tournamentService.addTournament('token', club.id, 'Sommercup', '2025-06-01');
|
||||
|
||||
// ohne Klasse: legacy-Aufruf (3. Argument = tournamentId)
|
||||
await tournamentService.addParticipant('token', club.id, tournament.id, memberA.id);
|
||||
await expect(
|
||||
tournamentService.addParticipant('token', club.id, tournament.id, memberA.id)
|
||||
).rejects.toThrow('Teilnehmer bereits hinzugefügt');
|
||||
|
||||
const participantsNoClass = await tournamentService.getParticipants('token', club.id, tournament.id, null);
|
||||
expect(participantsNoClass).toHaveLength(1);
|
||||
expect(participantsNoClass[0].classId).toBe(null);
|
||||
expect(participantsNoClass[0].clubMemberId).toBe(memberA.id);
|
||||
});
|
||||
|
||||
it('normalisiert numberOfGroups=0 auf mindestens 1 Gruppe', async () => {
|
||||
const club = await Club.create({ name: 'Tournament Club' });
|
||||
const tournament = await tournamentService.addTournament('token', club.id, 'Gruppen-Test', '2025-07-01');
|
||||
|
||||
await tournamentService.createGroups('token', club.id, tournament.id, 0);
|
||||
const groups = await TournamentGroup.findAll({ where: { tournamentId: tournament.id } });
|
||||
expect(groups).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('legt bei numberOfGroups=4 genau 4 Gruppen an (ohne Klassen)', async () => {
|
||||
const club = await Club.create({ name: 'Tournament Club' });
|
||||
const tournament = await tournamentService.addTournament('token', club.id, 'Gruppen-4er', '2025-08-01');
|
||||
|
||||
await tournamentService.createGroups('token', club.id, tournament.id, 4);
|
||||
const groups = await TournamentGroup.findAll({ where: { tournamentId: tournament.id } });
|
||||
expect(groups).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('verteilt bei "zufällig verteilen" möglichst gleichmäßig (Differenz <= 1)', async () => {
|
||||
const club = await Club.create({ name: 'Tournament Club' });
|
||||
const tournament = await tournamentService.addTournament('token', club.id, 'Fill-Groups-Balanced', '2025-10-01');
|
||||
|
||||
// 10 Teilnehmer, 4 Gruppen => erwartete Größen: 3/3/2/2 (beliebige Reihenfolge)
|
||||
const members = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
// createMember Factory braucht eindeutige Emails
|
||||
members.push(
|
||||
await createMember(club.id, {
|
||||
firstName: `P${i}`,
|
||||
lastName: 'T',
|
||||
email: `p${i}@example.com`,
|
||||
gender: i % 2 === 0 ? 'male' : 'female',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
for (const m of members) {
|
||||
await tournamentService.addParticipant('token', club.id, tournament.id, m.id);
|
||||
}
|
||||
|
||||
// Seeded-Balancing triggern: markiere mehrere als gesetzt
|
||||
// (wir testen hier explizit, dass diese Optimierung die Größen-Balance NICHT kaputt machen darf)
|
||||
const tmRows = await TournamentMember.findAll({ where: { tournamentId: tournament.id } });
|
||||
const seededIds = tmRows.slice(0, 5).map(r => r.id);
|
||||
await TournamentMember.update({ seeded: true }, { where: { id: { [Op.in]: seededIds } } });
|
||||
|
||||
await tournamentService.setModus('token', club.id, tournament.id, 'groups', 4, 1);
|
||||
await tournamentService.createGroups('token', club.id, tournament.id, 4);
|
||||
await tournamentService.fillGroups('token', club.id, tournament.id);
|
||||
|
||||
const groups = await TournamentGroup.findAll({ where: { tournamentId: tournament.id } });
|
||||
expect(groups).toHaveLength(4);
|
||||
|
||||
const membersWithGroups = await TournamentMember.findAll({ where: { tournamentId: tournament.id } });
|
||||
const countsByGroupId = membersWithGroups.reduce((m, tm) => {
|
||||
m[tm.groupId] = (m[tm.groupId] || 0) + 1;
|
||||
return m;
|
||||
}, {});
|
||||
|
||||
const sizes = groups.map(g => countsByGroupId[g.id] || 0);
|
||||
const min = Math.min(...sizes);
|
||||
const max = Math.max(...sizes);
|
||||
expect(max - min).toBeLessThanOrEqual(1);
|
||||
expect(sizes.reduce((a, b) => a + b, 0)).toBe(10);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user