{ "version": 3, "sources": ["../../../server/tournaments/generator-round-robin.ts"], "sourcesContent": ["interface Match {\n\tstate: string;\n\tscore?: number[];\n\tresult?: string;\n}\n\nimport { Utils } from '../../lib/utils';\nimport type { TournamentPlayer } from './index';\n\nexport class RoundRobin {\n\treadonly name: string;\n\treadonly isDrawingSupported: boolean;\n\treadonly isDoubles: boolean;\n\tisBracketFrozen: boolean;\n\tplayers: TournamentPlayer[];\n\tmatches: (Match | null)[][];\n\ttotalPendingMatches: number;\n\tperPlayerPendingMatches: number;\n\tmatchesPerPlayer?: number;\n\tconstructor(isDoubles: string) {\n\t\tthis.name = \"Round Robin\";\n\t\tthis.isDrawingSupported = true;\n\t\tthis.isDoubles = !!isDoubles;\n\t\tthis.isBracketFrozen = false;\n\t\tthis.players = [];\n\n\t\tthis.matches = [];\n\t\tthis.totalPendingMatches = -1;\n\t\tthis.perPlayerPendingMatches = -1;\n\n\t\tif (isDoubles) this.name = \"Double \" + this.name;\n\t}\n\n\tgetPendingBracketData(players: TournamentPlayer[]) {\n\t\treturn {\n\t\t\ttype: 'table',\n\t\t\ttableHeaders: {\n\t\t\t\tcols: players.slice(0),\n\t\t\t\trows: players.slice(0),\n\t\t\t},\n\t\t\ttableContents: players.map(\n\t\t\t\t(p1, row) => players.map((p2, col) => {\n\t\t\t\t\tif (!this.isDoubles && col >= row) return null;\n\t\t\t\t\tif (p1 === p2) return null;\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstate: 'unavailable',\n\t\t\t\t\t};\n\t\t\t\t})\n\t\t\t),\n\t\t\tscores: players.map(player => 0),\n\t\t};\n\t}\n\tgetBracketData() {\n\t\tconst players = this.players;\n\t\treturn {\n\t\t\ttype: 'table',\n\t\t\ttableHeaders: {\n\t\t\t\tcols: players.slice(0),\n\t\t\t\trows: players.slice(0),\n\t\t\t},\n\t\t\ttableContents: players.map(\n\t\t\t\t(p1, row) => players.map((p2, col) => {\n\t\t\t\t\tif (!this.isDoubles && col >= row) return null;\n\t\t\t\t\tif (p1 === p2) return null;\n\t\t\t\t\tconst match = this.matches[row][col];\n\t\t\t\t\tif (!match) return null;\n\n\t\t\t\t\tconst cell: any = {\n\t\t\t\t\t\tstate: match.state,\n\t\t\t\t\t};\n\t\t\t\t\tif (match.state === 'finished' && match.score) {\n\t\t\t\t\t\tcell.result = match.result;\n\t\t\t\t\t\tcell.score = match.score.slice(0);\n\t\t\t\t\t}\n\t\t\t\t\treturn cell;\n\t\t\t\t})\n\t\t\t),\n\t\t\tscores: players.map(player => player.score),\n\t\t};\n\t}\n\tfreezeBracket(players: TournamentPlayer[]) {\n\t\tthis.players = players;\n\t\tthis.isBracketFrozen = true;\n\n\t\tthis.matches = players.map(\n\t\t\t(p1, row) => players.map((p2, col) => {\n\t\t\t\tif (!this.isDoubles && col >= row) return null;\n\t\t\t\tif (p1 === p2) return null;\n\n\t\t\t\treturn { state: 'available' };\n\t\t\t})\n\t\t);\n\t\tthis.matchesPerPlayer = players.length - 1;\n\t\t// total matches = total players * matches per player / players per match\n\t\t// alternatively: the (playercount)th triangular number\n\t\tthis.totalPendingMatches = players.length * this.matchesPerPlayer / 2;\n\t\tif (this.isDoubles) {\n\t\t\tthis.totalPendingMatches *= 2;\n\t\t\tthis.matchesPerPlayer *= 2;\n\t\t}\n\t}\n\n\tdisqualifyUser(user: TournamentPlayer) {\n\t\tif (!this.isBracketFrozen) return 'BracketNotFrozen';\n\n\t\tconst playerIndex = this.players.indexOf(user);\n\n\t\tfor (const [col, match] of this.matches[playerIndex].entries()) {\n\t\t\tif (!match || match.state !== 'available') continue;\n\t\t\tconst p2 = this.players[col];\n\t\t\tmatch.state = 'finished';\n\t\t\tmatch.result = 'loss';\n\t\t\tmatch.score = [0, 1];\n\t\t\tp2.score += 1;\n\t\t\tp2.games += 1;\n\t\t\tthis.totalPendingMatches--;\n\t\t\tif (this.matchesPerPlayer && p2.games === this.matchesPerPlayer) {\n\t\t\t\tp2.sendRoom(`|tournament|update|{\"isJoined\":false}`);\n\t\t\t\tp2.game.updatePlayer(p2, null);\n\t\t\t}\n\t\t}\n\n\t\tfor (const [row, challenges] of this.matches.entries()) {\n\t\t\tconst match = challenges[playerIndex];\n\t\t\tif (!match || match.state !== 'available') continue;\n\t\t\tconst p1 = this.players[row];\n\t\t\tmatch.state = 'finished';\n\t\t\tmatch.result = 'win';\n\t\t\tmatch.score = [1, 0];\n\t\t\tp1.score += 1;\n\t\t\tp1.games += 1;\n\t\t\tthis.totalPendingMatches--;\n\t\t\tif (this.matchesPerPlayer && p1.games === this.matchesPerPlayer) {\n\t\t\t\tp1.sendRoom(`|tournament|update|{\"isJoined\":false}`);\n\t\t\t\tp1.game.updatePlayer(p1, null);\n\t\t\t}\n\t\t}\n\n\t\tuser.game.updatePlayer(user, null);\n\t}\n\n\tgetAvailableMatches() {\n\t\tif (!this.isBracketFrozen) return 'BracketNotFrozen';\n\n\t\tconst matches: [TournamentPlayer, TournamentPlayer][] = [];\n\t\tfor (const [row, challenges] of this.matches.entries()) {\n\t\t\tconst p1 = this.players[row];\n\t\t\tfor (const [col, match] of challenges.entries()) {\n\t\t\t\tconst p2 = this.players[col];\n\t\t\t\tif (!match) continue;\n\t\t\t\tif (match.state === 'available' && !p1.isBusy && !p2.isBusy) {\n\t\t\t\t\tmatches.push([p1, p2]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn matches;\n\t}\n\tsetMatchResult([p1, p2]: [TournamentPlayer, TournamentPlayer], result: string, score: number[]) {\n\t\tif (!this.isBracketFrozen) return 'BracketNotFrozen';\n\n\t\tif (!['win', 'loss', 'draw'].includes(result)) return 'InvalidMatchResult';\n\n\t\tconst row = this.players.indexOf(p1);\n\t\tconst col = this.players.indexOf(p2);\n\t\tif (row < 0 || col < 0) return 'UserNotAdded';\n\n\t\tconst match = this.matches[row][col];\n\t\tif (!match || match.state !== 'available') return 'InvalidMatch';\n\n\t\tmatch.state = 'finished';\n\t\tmatch.result = result;\n\t\tmatch.score = score.slice(0);\n\t\tthis.totalPendingMatches--;\n\t\tif (this.matchesPerPlayer) {\n\t\t\tif (p1.games === this.matchesPerPlayer) {\n\t\t\t\tp1.sendRoom(`|tournament|update|{\"isJoined\":false}`);\n\t\t\t\tp1.game.updatePlayer(p1, null);\n\t\t\t}\n\t\t\tif (p2.games === this.matchesPerPlayer) {\n\t\t\t\tp2.sendRoom(`|tournament|update|{\"isJoined\":false}`);\n\t\t\t\tp2.game.updatePlayer(p2, null);\n\t\t\t}\n\t\t}\n\t}\n\n\tisTournamentEnded() {\n\t\treturn this.isBracketFrozen && this.totalPendingMatches === 0;\n\t}\n\n\tgetResults() {\n\t\tif (!this.isTournamentEnded()) return 'TournamentNotEnded';\n\n\t\tconst sortedScores = Utils.sortBy([...this.players], p => -p.score);\n\n\t\tconst results: TournamentPlayer[][] = [];\n\t\tlet currentScore = sortedScores[0].score;\n\t\tlet currentRank: TournamentPlayer[] = [];\n\t\tresults.push(currentRank);\n\t\tfor (const player of sortedScores) {\n\t\t\tif (player.score < currentScore) {\n\t\t\t\tcurrentScore = player.score;\n\t\t\t\tcurrentRank = [];\n\t\t\t\tresults.push(currentRank);\n\t\t\t}\n\t\t\tcurrentRank.push(player);\n\t\t}\n\t\treturn results;\n\t}\n}\n"], "mappings": "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", "names": [] }