По запросу 'Round-robin tournament algorithm' нашел всё-таки образец, который смог транслировать в JS. Вот моя реализация только для четного количества команд (для нечетного предлагается добавить в массив фантомного участника):
// На входе - массив с командами и опционально - необходимый тур
function schedule(array, round) { // если тур не указан - создаётся всё расписание целиком
if (!round) {
var teams = array.length,
// точка, после которой команды будут меняться местами "дома - гость"
halfTour = (teams - 1),
totalRounds = halfTour * 2,
matchesPerRound = teams / 2,
matches = [],
rounds = [],
round,
match,
home,
away,
swap,
currentRoundText;
for (round = 0; round < totalRounds; round++) {
currentRoundText = [(round + 1)];
matches = [];
for (match = 0; match < matchesPerRound; match++) {
home = (round + match) % (teams - 1);
away = (teams - 1 - match + round) % (teams - 1);
if (match === 0) {
away = teams - 1;
}
if (round >= halfTour) {
swap = home;
home = away;
away = swap;
}
currentRoundText += ('[' + array[home]+ ' ' + array[away] + ']');
matches.push([array[home], array[away]]);
}
console.log(currentRoundText);
rounds.push(matches);
}
return rounds;
}
// Если раунд указан, просчитывается весь турнир и берется нужный элемент массива
return schedule(array)[round - 1];
}