From beff7cd8322be27e535c1e43e407f9c2cadb6bfc Mon Sep 17 00:00:00 2001 From: FragginWagon Date: Thu, 29 Jan 2026 01:58:23 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20utility=20function=20for=20ca?= =?UTF-8?q?lculating=20group=20sizes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/utilities/group-size-util.js | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 code/websites/pokedex.online/src/utilities/group-size-util.js diff --git a/code/websites/pokedex.online/src/utilities/group-size-util.js b/code/websites/pokedex.online/src/utilities/group-size-util.js new file mode 100644 index 0000000..7f9dcab --- /dev/null +++ b/code/websites/pokedex.online/src/utilities/group-size-util.js @@ -0,0 +1,149 @@ +/** + * groupSizeUtils.js + * ----------------------------------------- + * Utilities for group size calculation and + * print-safe layout generation. + * + * Vanilla ECMAScript, framework-agnostic. + */ + +/** + * Create group definitions with base sizes + * and remainder distribution. + * + * @param {number} totalPlayers + * @param {Array} groupIds + * @returns {Array} + */ +export function calculateGroupSizes(totalPlayers, groupIds) { + if (!Array.isArray(groupIds) || groupIds.length === 0) { + throw new Error('groupIds must be a non-empty array'); + } + + const totalGroups = groupIds.length; + const baseSize = Math.floor(totalPlayers / totalGroups); + const remainder = totalPlayers % totalGroups; + + return groupIds.map(function (id, index) { + return { + id: id, + size: baseSize + (index < remainder ? 1 : 0), + players: [] + }; + }); +} + +/** + * Assign players to groups sequentially + * based on calculated group sizes. + * + * @param {Array} players + * @param {Array} groups + * @returns {Array} + */ +export function assignPlayersToGroups(players, groups) { + var playerIndex = 0; + + groups.forEach(function (group) { + for (var i = 0; i < group.size; i++) { + if (playerIndex >= players.length) break; + + var player = players[playerIndex]; + player.groupId = group.id; + group.players.push(player); + + playerIndex++; + } + }); + + return groups; +} + +/** + * Remove dropped players without rebalancing groups. + * + * @param {Array} groups + * @param {Array} droppedPlayerIds + * @returns {Array} + */ +export function applyDrops(groups, droppedPlayerIds) { + if (!Array.isArray(droppedPlayerIds)) return groups; + + var dropSet = new Set(droppedPlayerIds); + + groups.forEach(function (group) { + group.players = group.players.filter(function (player) { + return !dropSet.has(player.id); + }); + }); + + return groups; +} + +/** + * Calculate print rows for a group. + * + * @param {Object} group + * @param {number} headerRows + * @param {number} spacerRows + * @returns {number} + */ +export function calculateGroupPrintRows(group, headerRows, spacerRows) { + return headerRows + group.players.length + spacerRows; +} + +/** + * Generate print layout with page breaks. + * + * @param {Array} groups + * @param {Object} options + * @param {number} options.rowsPerPage + * @param {number} options.headerRows + * @param {number} options.spacerRows + * @returns {Array} + */ +export function generatePrintLayout(groups, options) { + var rowsPerPage = options.rowsPerPage; + var headerRows = options.headerRows || 1; + var spacerRows = options.spacerRows || 1; + + var pages = []; + var currentPage = { + pageNumber: 1, + groups: [], + usedRows: 0 + }; + + groups.forEach(function (group) { + var groupRows = calculateGroupPrintRows(group, headerRows, spacerRows); + + if (currentPage.usedRows + groupRows > rowsPerPage) { + pages.push(currentPage); + currentPage = { + pageNumber: currentPage.pageNumber + 1, + groups: [], + usedRows: 0 + }; + } + + currentPage.groups.push(group); + currentPage.usedRows += groupRows; + }); + + pages.push(currentPage); + return pages; +} + +/** + * High-level helper that runs the full pipeline. + * + * @param {Array} players + * @param {Array} groupIds + * @param {Object} printOptions + * @returns {Array} + */ +export function buildGroupPrintPages(players, groupIds, printOptions) { + var groups = calculateGroupSizes(players.length, groupIds); + assignPlayersToGroups(players, groups); + return generatePrintLayout(groups, printOptions); +}