Mix and match players in interesting pairings

const participants = [
{ id: 1, name : 'player1'},
{ id: 2, name : 'player2'},
{ id: 3, name : 'player3'},
{ id: 4, name : 'player4'},
{ id: 5, name : 'player5'},
{ id: 6, name : 'player6'},
{ id: 7, name : 'player7'},
{ id: 8, name : 'player8'},
{ id: 9, name : 'player9'},
{ id: 10, name : 'player10'},
{ id: 11, name : 'player11'},
{ id: 12, name : 'player12'},
{ id: 13, name : 'player13'},
{ id: 14, name : 'player14'},
{ id: 15, name : 'player15'},
{ id: 16, name : 'player16'}]

I am looking to organize games with 2 players versus 2 players. Each round will consist of 4 matches with 2 vs 2 players.

A player cannot be paired with someone they have already played with before.

I aim to create a function that will randomly assign the matchups for all the games.

The format I am looking for is similar to the following but for all matches in the tournament:

The players will participate in 4 matches simultaneously, then switch partners and begin 4 new matches.

matches = [{ team1: [{ id: 1, name : 'player1'},{ id: 2, name : 'player2'}], team2 :[{ id: 3, name : 'player3'},{ id: 4, name : 'player4'}] }]

Answer №1

To generate all possible combinations for the maximum number of game rounds (ensuring that each player competes against every other player exactly once), I sought inspiration from .

// Utilizing: https://stackoverflow.com/a/12646864/9487478
const shuffleArray = (array) => {
  let shuffledArray = [...array];
  for (let i = shuffledArray.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]];
  }
  return shuffledArray;
}

// Note: The total players must be an even number.
let createGames = (playerArr) => {
  let players = [...playerArr];
  const teamsPerRound = [], 
        rounds = mod = players.length - 1,
        gamesPerRound = 4,
        // Helper array to track player confrontations.
        confrontations = Array(players.length).fill().map(x => Array(players.length).fill(0));        
    
  // Drawing inspiration from: https://math.stackexchange.com/a/3094469
  // Creating unique teams where each player appears only once within a round.
  for (let i = 0; i < rounds; i++) {
    let team = [[
      players.length - 1, 
      (players.length + i) % mod
    ]];
    for (let k = 1; k < (players.length / 2); k++) {
      team.push([
        (players.length + i + k) % mod,
        (players.length + i - k) % mod
      ]);
    }
    teamsPerRound.push(team);
    console.log(`Teams-Round ${i+1}`, JSON.stringify(team));
  }

  
  // Shuffle teams per round for randomness before creating the games.
  const games = shuffleArray(teamsPerRound).map(teams => {
    let roundMatches = [];
    teams = shuffleArray(teams);
    for (let i = 0; i < teams.length/2; i++) {
      let first = teams[i], second = teams[teams.length - 1 - i];

      roundMatches.push({
        team1: first.map(x => ({...players[x]})),
        team2: second.map(x => ({...players[x]}))
      })
      
      // Tracking player confrontations.
      first.forEach(x => second.forEach(y => (confrontations[x][y]++, confrontations[y][x]++)));
    }
    return roundMatches;
  });
    
  confrontations.forEach((x,i) => console.log(`Confrontations (playerIndex: ${i})`, JSON.stringify(x), x.reduce((acc, val) => acc += val)));

  return games;
}

var players = [
  { id: 1, name : 'player1'},
  { id: 2, name : 'player2'},
  { id: 3, name : 'player3'},
  { id: 4, name : 'player4'},
  { id: 5, name : 'player5'},
  { id: 6, name : 'player6'},
  { id: 7, name : 'player7'},
  { id: 8, name : 'player8'},
  { id: 9, name : 'player9'},
  { id: 10, name : 'player10'},
  { id: 11, name : 'player11'},
  { id: 12, name : 'player12'},
  { id: 13, name : 'player13'},
  { id: 14, name : 'player14'},
  { id: 15, name : 'player15'},
  { id: 16, name : 'player16'}
];

const games = createGames(players);

console.log("Match-ups", games);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Adding an active class to dynamic tabs in Vue.js navigation

I'm currently facing a challenge in adding an active class to a specific element for tabs navigation using vue.js. One of the obstacles I'm encountering is my limited experience with Vue, as well as the fact that the navigation items are being ge ...

What is the best way to add a list to a JSON array?

I'm interested in learning how to create a loop using for each and for both methods. I want to access the id "list" in order to append li elements. HTML <div id="list"> <ul> <li>Mainland China</li> ...

Transforming raw data into an object in Angular: A step-by-step guide

Does anyone have tips on converting this raw data from a websocket message into an object for use in an Angular and Ionic project? var data = message.payload; console.log(data); After logging 'data' to the console, here is the result: ...

How can I display the output from Geocoder in a text box using the ArcGIS JavaScript API?

I am trying to customize the Geocoder text box in the ArcGIS JavaScript API by overriding the default search result. Although I have written some code for this purpose, I am not satisfied with the results. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...

Trigger a JavaScript function using PHP and retrieve the output

My goal is to execute a javascript function from a PHP script by passing a variable to the javascript function and then displaying only the response in the PHP script. I want to ensure that when a client views the source code of my php file, they can only ...

Transform a string into a JSON entity

Can JavaScript be used to convert a string such as this: "Product : Bike , 2005 : $12000,2006 : $13000,2007 : $14000,2008 : $15000" into a JSON object like the one below: { "Product":"Bike", "2005" : $12000, "2006" : $13000, "2007" : $14 ...

Issue with playing audio file using HowlerJS

Having trouble playing a .mp3 file in my project directory with Howler. I'm not sure if there's an error in my src. When I tried playing an online hosted audio file, it worked fine. I've placed the audio file in the same directory as Slideon ...

The functionality of the JQuery $.post method may be compatible with Firefox but may encounter issues when

I've encountered an issue with my website where certain functions that update the database using $.post work perfectly in Firefox, but fail to function properly in Internet Explorer. I'm struggling to identify the root cause of this problem. Here ...

I'm having trouble assigning a value to an array and can't seem to pinpoint the mistake in my code on line 31

My data file is structured in the format <0:00> - <19321>, <1:00> - <19324>, all the way up to <24:00> - <19648>. For each hour, the total power used so far is logged. I'm tasked with calculating the power used, det ...

Concealing certain columns when the table exceeds a certain size

Hello everyone, I am just starting out in the world of React and web applications. Please feel free to reach out if anything is unclear to you. Here is the table structure that I currently have: <div> <table id="mytableid" className=&qu ...

How can JQuery be used to implement "scrolling" buttons and automatically update the main page with fresh data?

I am attempting to achieve the following: 1 - Use jQuery to update index.html with the content from output.html (only update when there are differences in data, and ideally only update the parts that have changed). 2 - Add two buttons in the header ...

Send your information to a JSONP endpoint

Can data be posted to JsonP instead of passing it in the querystring as a GET request? I have a large amount of data that needs to be sent to a cross-domain service, and sending it via the querystring is not feasible due to its size. What other alternati ...

Is there a way to incorporate the ::after or ::before pseudo-elements into an image tag?

While working on my project, I attempted to incorporate the ::after tag (I had used ::before as well) for an image within an img tag. However, I am facing difficulties as it doesn't seem to be working. Any advice or guidance would be greatly appreciat ...

Managing the closure of a Chrome packaged application

Is there a way to execute code before a Chrome packaged app closes? I have tried the following methods without success: chrome.app.window.current().onClosed chrome.runtime.onSuspend window unload event For instance: chrome.runtime.onSuspend.addListene ...

Encountering CORS Issue when attempting to upload a file from an external URL using Angular

I am attempting to upload a file from an external URL, but I keep encountering a CORS error when trying to access the external URL. await fetch(url).then(function (res) { response = res; }).catch(function () { setTimeout(() => { this.toaster. ...

Harness the power of Actions SDK to enhance your Google Assistant experience

I'm struggling to get my custom Actions SDK working on my own server. The actions I've created show up in Google Assistant, but the functionality isn't there - it just closes without any errors being displayed. Here's a snippet of my co ...

Tips for styling the output of var_dump with an array

I currently have a script that retrieves an array from an API URL. <?php $url = 'https://api.example.com/v1/w'; $data = file_get_contents($url); $data = json ...

Is the background color change function with AJAX not functioning properly when using array values?

Let me simplify my issue. I have an AJAX call to fetch a JSON array with "aht_value". Based on this value, I am creating a color gradient from green to red (creating a heat map). The values are being output correctly. The issue: The problem lies within m ...

Exploring AngularJS with Filtering for Advanced Search Results

Currently, I have a search box that successfully searches values in a table using my code. <tr ng-repeat="b in bugs | filter:searchText"> Now, I want to take it one step further by allowing users to search specific columns if they include a colon i ...

Validation in AngularJS - Setting minimum length for textarea using ng-minlength

I am currently tackling a project that heavily relies on AngularJS for the front-end. Here's what I am dealing with: The validation requirement I am aiming for is as follows: The Next button should remain disabled unless the reason provided is at le ...