aboutsummaryrefslogtreecommitdiff
path: root/src/lib/logic/matchmaking.js
diff options
context:
space:
mode:
authorKaran Jayachandra <mail@karanjayachandra.com>2026-08-30 22:43:21 +0200
committerKaran Jayachandra <mail@karanjayachandra.com>2026-08-30 22:43:21 +0200
commitfc8d8ab8d0da95ec79056f59e14a150df6fcea89 (patch)
tree33f8050b2f2920c0f1b884a205a8aa4c81d7687c /src/lib/logic/matchmaking.js
parentd37ebfda883bcd03b146a85bc3e5a4657d0abd73 (diff)
Moved to sveltemain
Diffstat (limited to 'src/lib/logic/matchmaking.js')
-rw-r--r--src/lib/logic/matchmaking.js113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/lib/logic/matchmaking.js b/src/lib/logic/matchmaking.js
new file mode 100644
index 0000000..eb8be2e
--- /dev/null
+++ b/src/lib/logic/matchmaking.js
@@ -0,0 +1,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;
+}