const DEFAULT_MAP_WIDTH = 1000; const DEFAULT_MAP_HEIGHT = 700; const STARTER_GAP = 28; const STARTER_MIN_OBJECT_WIDTH = 120; const STARTER_MIN_OBJECT_HEIGHT = 80; const STARTER_TARGET_ROW_HEIGHT = 210; function toPositiveInteger(value, fallback) { const parsed = Number.parseInt(String(value), 10); return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback; } function roundToTwo(value) { return Math.round(value * 100) / 100; } function getStarterGrid(zones) { const zoneCount = Array.isArray(zones) ? zones.length : 0; const columnCount = zoneCount <= 4 ? 2 : 3; const rowCount = Math.ceil(Math.max(zoneCount, 1) / columnCount); return { columnCount, rowCount }; } function getStarterMapSize(zones, mapSize = {}) { const { columnCount, rowCount } = getStarterGrid(zones); const currentWidth = toPositiveInteger(mapSize.width, DEFAULT_MAP_WIDTH); const currentHeight = toPositiveInteger(mapSize.height, DEFAULT_MAP_HEIGHT); const requiredWidth = columnCount * STARTER_MIN_OBJECT_WIDTH + STARTER_GAP * (columnCount + 1); const minimumGridHeight = rowCount * STARTER_MIN_OBJECT_HEIGHT + STARTER_GAP * (rowCount + 1); const preferredGridHeight = rowCount * STARTER_TARGET_ROW_HEIGHT; return { width: Math.max(currentWidth, requiredWidth), height: Math.max(currentHeight, minimumGridHeight, preferredGridHeight), }; } function buildStarterObjectsFromZones(zones, width, height) { if (!Array.isArray(zones) || !zones.length) return []; const mapSize = getStarterMapSize(zones, { width, height }); const { columnCount, rowCount } = getStarterGrid(zones); const cellWidth = (mapSize.width - STARTER_GAP * (columnCount + 1)) / columnCount; const cellHeight = (mapSize.height - STARTER_GAP * (rowCount + 1)) / rowCount; return zones.map((zone, index) => { const column = index % columnCount; const row = Math.floor(index / columnCount); return { zone_id: zone.id, type: "zone", label: zone.name, x: roundToTwo(STARTER_GAP + column * (cellWidth + STARTER_GAP)), y: roundToTwo(STARTER_GAP + row * (cellHeight + STARTER_GAP)), width: Math.max(STARTER_MIN_OBJECT_WIDTH, roundToTwo(cellWidth)), height: Math.max(STARTER_MIN_OBJECT_HEIGHT, roundToTwo(cellHeight)), rotation: 0, locked: false, visible: true, sort_order: index + 1, metadata_json: { starter: true }, }; }); } module.exports = { buildStarterObjectsFromZones, getStarterMapSize, };