--- import { spotPath, type Activity } from "../lib/api"; const { items } = Astro.props as { items: Activity[] }; const groups = [...items.reduce((result, item) => { const group = result.get(item.waterbody_slug) ?? []; group.push(item); result.set(item.waterbody_slug, group); return result; }, new Map()).values()]; const plotPoints = (group: Activity[]) => { const minX = Math.min(...group.map(item => item.x), 0); const maxX = Math.max(...group.map(item => item.x), 1); const minY = Math.min(...group.map(item => item.y), 0); const maxY = Math.max(...group.map(item => item.y), 1); const xRange = Math.max(1, maxX - minX); const yRange = Math.max(1, maxY - minY); const occupied = new Set(); return group.map(item => { const targetColumn = Math.min(19, Math.max(2, Math.round(((item.x - minX) / xRange) * 16) + 2)); const targetRow = Math.min(19, Math.max(2, Math.round((1 - (item.y - minY) / yRange) * 16) + 2)); let column = targetColumn; let row = targetRow; for (let distance = 0; occupied.has(`${column}:${row}`) && distance < 20; distance += 1) { column = ((targetColumn - 2 + distance + 1) % 18) + 2; row = ((targetRow - 2 + Math.floor((distance + 1) / 18)) % 18) + 2; } occupied.add(`${column}:${row}`); return { item, column, row }; }); }; ---
Режим схемы

Горячие точки по водоёмам

Для каждого водоёма своя координатная сетка `x:y`. Совпадающие точки разнесены, чтобы каждая оставалась доступной.

{groups.map(group =>

{group[0].waterbody} {group.length} {group.length === 1 ? "точка" : "точки"}

{plotPoints(group).map(({ item, column, row }) => {item.x}:{item.y}{item.fish})}
)}