grocery-app/backend/services/location-map-layout.service.js
2026-06-03 12:09:22 -07:00

72 lines
2.4 KiB
JavaScript

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,
};