simple-roundrobin
Version:
A simple round-robin tournament scheduler
73 lines (72 loc) • 2.55 kB
JavaScript
;
const createMatch = (home, away, randomizeHome = true, roundNumber) => {
const match = randomizeHome && Math.random() < 0.5
? { home: away, away: home }
: { home, away };
return roundNumber ? { ...match, roundNumber } : match;
};
const rotateTeams = (teams) => {
const newTeams = [...teams];
const lastTeam = newTeams.pop();
if (lastTeam) {
newTeams.splice(1, 0, lastTeam);
}
return newTeams;
};
const reverseSchedule = (rounds) => rounds.map(round => round.map(match => ({
home: match.away,
away: match.home,
roundNumber: match.roundNumber
})));
const scheduleGenerator = (legs, initialRounds) => {
const additionalLegs = legs / 2;
const reverseInitialRounds = reverseSchedule(initialRounds);
const initial = [...initialRounds, ...reverseInitialRounds];
return Array.from({ length: additionalLegs }, () => initial).flat();
};
const validateTeamNames = (teams) => {
const seen = new Set();
teams.forEach(team => {
if (typeof team !== 'string' || team.trim() === '') {
throw new Error(`Invalid team name: ${team}`);
}
if (seen.has(team)) {
throw new Error(`Duplicate team name: ${team}`);
}
seen.add(team);
});
};
const validateInput = (input) => {
const { clubs, legs = 1 } = input;
if (!Array.isArray(clubs)) {
throw new Error("Clubs must be an array!");
}
validateTeamNames(clubs);
if ((legs % 2 !== 0 && legs > 1) || legs < 1) {
throw new Error('Legs value must be "1" or an even number.');
}
if (clubs.length === 0) {
throw new Error("Clubs array cannot be empty.");
}
if (clubs.length % 2 !== 0) {
throw new Error("Number of clubs must be even.");
}
};
const generateRoundRobin = (input) => {
const { clubs, legs = 1, randomizeHome = true } = input;
validateInput(input);
let teamsArray = [...clubs];
const initialRounds = [];
for (let i = 0; i < teamsArray.length - 1; i++) {
const currentRound = [];
for (let j = 0; j < teamsArray.length / 2; j++) {
const teamOne = teamsArray[j];
const teamTwo = teamsArray[teamsArray.length - 1 - j];
currentRound.push(createMatch(teamOne, teamTwo, randomizeHome, i + 1));
}
initialRounds.push(currentRound);
teamsArray = rotateTeams(teamsArray);
}
return legs === 1 ? initialRounds : scheduleGenerator(legs, initialRounds);
};
module.exports = generateRoundRobin;