0

I have list of players and want to create a round robin generator for chess tournaments with JavaScript. The round robin should be like in this image, shown for 10 teams and 6 teams:

enter image description here

I tried to create separate logic for even and odd round numbers, but I failed to find the best algorithm for that:

var list = [1,2,3,4,5,6,7,8,9,10];
var pairing = []
var size = list.length;
var halfSize = size/2;
var evenOrOdd
if (halfSize % 2 != 1) {
    list.push("BYE")
}
for (var i=0 ; i <= size-1 ; i++) {
    var lastOne = list[size]
    if (isEven(i)) {
        var games = []
        for (var j = 0; j <= halfSize-1; j++) {
            if (j == 0) {
                games.push({"home": list[size-1], "away": list[(i+2)/2-1+j]})
          } else {
                if(list[size-j-i/2]==list[size-2] && i>0){
                    games.push({"home": list[j+i/2], "away": list[0]})
                } else {
                    games.push({"home": list[j+i/2], "away": list[(i+2)/2]})
            }
            }
        }
        pairing.push({"round":i+1,"games":games})
    } else {
    }
}
console.log(pairing)

function isEven(num) {
    if (num % 2 == 0)
        return true;
    return false;
}

The result I get is not like the pairing in the image above, it only produces the first round correctly.

There are some other similar questions that have answers, like Scheduling algorithm for a round-robin tournament?, but they are for football tournaments and I want it for chess tournaments: it has some differences compared with football.

How can I correct my chess tournament generator so it works for any number of players?

trincot
  • 317,000
  • 35
  • 244
  • 286
Sermed mayi
  • 697
  • 7
  • 26
  • Please edit your question and describe what you mean when you say you failed. Are you getting an error? Are you not getting the results you expect (and if so, at what point in your code are you not getting the results you expect and what should the result be?), or is it working and you're seeking some kind of improvement (and if so, what type of improvement? More efficient? Clearer code?) – devlin carnate Jul 13 '21 at 20:36
  • @devlincarnate ok I will do thanks – Sermed mayi Jul 13 '21 at 20:38
  • @Keith thanks ,I found this but it is for football and the chess round robin is not same – Sermed mayi Jul 13 '21 at 20:40

1 Answers1

2

You could use the remainder operator (%) to use modular logic, as clearly one number increases, while the other decreases. The first game is an exception, where the last player is always involved, and the increasing counter is left the same as in the previously generated pair. It also has a swap of sides depending on the parity of the round.

Here is a way to do it using some map and Array.from calls to create the arrays on the fly. The incrementing and decrementing variables are updated while they are used as index:

function generatePairings(players) {
    let n = players.length;
    let mod = n - 1;
    let decr = 0;
    let incr = -1;
    let arr = {length: n / 2 - 1}; // n is assumed to be even
    let props = ["away", "home"];
    let template = { home: players[mod], away: players[mod] };
    return players.slice(1).map((_, i) => ({
        round: i + 1,
        games: [
            { ...template, ...{ [props[i % 2]]: players[incr = (incr + 1) % mod] }}, 
            ...Array.from(arr, () => ({
                home: players[incr = (incr + 1) % mod], 
                away: players[decr = (decr + mod - 1) % mod] 
            }))
        ]
    }));
}

console.log(generatePairings([1,2,3,4,5,6]));

Or with for loops:

function generatePairings(players) {
    let n = players.length;
    let mod = n - 1;
    let decr = 0;
    let incr = -1;
    let gameCount = n / 2; // n is assumed to be even
    let props = ["away", "home"];
    let template = { home: players[mod], away: players[mod] };
    let pairings = [];
    for (let round = 1; round < n; round++) {
        let games = [{ ...template, 
            ...{ [props[round % 2]]: players[incr = (incr + 1) % mod] }
        }];
        for (let k = 1; k < gameCount; k++) {
            games.push({
                home: players[incr = (incr + 1) % mod], 
                away: players[decr = (decr + mod - 1) % mod] 
            });
        }
        pairings.push({ round, games });
    }
    return pairings;
}

console.log(generatePairings([1,2,3,4,5,6]));
trincot
  • 317,000
  • 35
  • 244
  • 286