aboutsummaryrefslogtreecommitdiff
path: root/src/lib/logic/matchmaking.js
blob: eb8be2e680b17f0601736643937c12586ae6b996 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { createRegular, createTeam, createGame } from "./players.js";
import { normalize } from "./normalize.js";

export function shuffle(array) {
  const copy = [...array];
  for (let i = copy.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [copy[i], copy[j]] = [copy[j], copy[i]];
  }
  return copy;
}

export function createPlaceholderGame(id, description = "---", status = true) {
  const player = createRegular(null, null, null, null, description, "");
  const team = createTeam(player, player);
  return createGame(id, status, team, team);
}

export function isPlaceholderGame(game) {
  return ["RESERVED", "---"].includes(game.teamOne.playerOne.firstName);
}

export function createDefaultGames(count) {
  const games = [];
  for (let i = 0; i < count; i++) {
    games.push(createPlaceholderGame(i, "---", true));
  }
  return games;
}

export function addBlockedGames(inactiveCourts) {
  return inactiveCourts.map((court) =>
    createPlaceholderGame(court.id, "RESERVED", false)
  );
}

export function addInactiveGames(unusedCourts) {
  return unusedCourts.map((court) =>
    createPlaceholderGame(court.id, "---", false)
  );
}

export function getPossibleGameCount(activePlayerCount, activeCourtCount) {
  return Math.min(Math.floor(activePlayerCount / 4), activeCourtCount);
}

export function selectPlayers(regulars, guests, count) {
  const combined = shuffle([...regulars, ...guests]);
  combined.sort((a, b) => a.games - b.games);
  const selected = combined.slice(0, count);
  selected.sort((a, b) => a.level - b.level);
  return selected;
}

export function pairPlayersIntoTeams(players) {
  const teamOne = createTeam(players[0], players[3]);
  const teamTwo = createTeam(players[1], players[2]);
  return [teamOne, teamTwo];
}

export function addActiveGames(usedCourts, selectedPlayers) {
  const games = [];
  for (let index = 0; index < usedCourts.length; index++) {
    const startIndex = 4 * index;
    const courtPlayers = selectedPlayers.slice(startIndex, startIndex + 4);
    const [teamOne, teamTwo] = pairPlayersIntoTeams(courtPlayers);
    games.push(createGame(usedCourts[index].id, false, teamOne, teamTwo));
  }
  return games;
}

export function proposeGames({ courts, regulars, guests, skillFactor }) {
  const activeCourts = courts.filter((c) => c.status);
  const inactiveCourts = courts.filter((c) => !c.status);
  const activeRegulars = regulars.filter((r) => r.status);
  const activeGuests = normalize(
    guests.filter((g) => g.status),
    skillFactor
  );

  const blockedGames = addBlockedGames(inactiveCourts);
  const possibleMatches = getPossibleGameCount(
    activeRegulars.length + activeGuests.length,
    activeCourts.length
  );
  const usedCourts = activeCourts.slice(0, possibleMatches);
  const unusedCourts = activeCourts.slice(possibleMatches);
  const inactiveGames = addInactiveGames(unusedCourts);
  const selectedPlayers = selectPlayers(
    activeRegulars,
    activeGuests,
    possibleMatches * 4
  );
  const activeGames = addActiveGames(usedCourts, selectedPlayers);

  return [...blockedGames, ...inactiveGames, ...activeGames].sort(
    (a, b) => a.id - b.id
  );
}

export function collectConfirmedPlayerNames(games) {
  const names = [];
  for (const game of games) {
    if (isPlaceholderGame(game)) continue;
    names.push(
      game.teamOne.playerOne.name,
      game.teamOne.playerTwo.name,
      game.teamTwo.playerOne.name,
      game.teamTwo.playerTwo.name
    );
  }
  return names;
}