75 lines
2.1 KiB
JavaScript
75 lines
2.1 KiB
JavaScript
function getPieceArea(piece) {
|
|
return piece.width * piece.height
|
|
}
|
|
|
|
function overlapArea(left, right) {
|
|
const overlapWidth = Math.max(0, Math.min(left.x + left.width, right.x + right.width) - Math.max(left.x, right.x))
|
|
const overlapHeight = Math.max(0, Math.min(left.y + left.height, right.y + right.height) - Math.max(left.y, right.y))
|
|
|
|
return overlapWidth * overlapHeight
|
|
}
|
|
|
|
function overlapsCenterZone(lower, upper) {
|
|
const centerWidth = lower.width * 0.5
|
|
const centerHeight = lower.height * 0.5
|
|
const centerBox = {
|
|
x: lower.x + lower.width * 0.25,
|
|
y: lower.y + lower.height * 0.25,
|
|
width: centerWidth,
|
|
height: centerHeight,
|
|
}
|
|
|
|
return overlapArea(centerBox, upper) > 0
|
|
}
|
|
|
|
export function buildOverlapGraph(pieces) {
|
|
const graph = Object.fromEntries(pieces.map((piece) => [piece.id, []]))
|
|
|
|
for (let leftIndex = 0; leftIndex < pieces.length; leftIndex += 1) {
|
|
for (let rightIndex = 0; rightIndex < pieces.length; rightIndex += 1) {
|
|
if (leftIndex === rightIndex) {
|
|
continue
|
|
}
|
|
|
|
const blocker = pieces[leftIndex]
|
|
const blocked = pieces[rightIndex]
|
|
|
|
if (blocker.layer <= blocked.layer) {
|
|
continue
|
|
}
|
|
|
|
const ratio = overlapArea(blocker, blocked) / getPieceArea(blocked)
|
|
|
|
if (ratio >= 0.2 && overlapsCenterZone(blocked, blocker)) {
|
|
graph[blocker.id].push(blocked.id)
|
|
}
|
|
}
|
|
}
|
|
|
|
return graph
|
|
}
|
|
|
|
export function getClickablePieces(boardState) {
|
|
const pieces = (boardState.pieces ?? []).filter((piece) => !piece.removed)
|
|
const indegree = Object.fromEntries(pieces.map((piece) => [piece.id, 0]))
|
|
const graph = boardState.overlapGraph ?? {}
|
|
|
|
for (const blockedIds of Object.values(graph)) {
|
|
for (const blockedId of blockedIds) {
|
|
if (blockedId in indegree) {
|
|
indegree[blockedId] += 1
|
|
}
|
|
}
|
|
}
|
|
|
|
return pieces.filter((piece) => indegree[piece.id] === 0)
|
|
}
|
|
|
|
export function rebuildGraphAfterShuffle(boardState) {
|
|
return buildOverlapGraph(boardState.pieces ?? [])
|
|
}
|
|
|
|
export function rebuildGraphAfterUndo(boardState) {
|
|
return buildOverlapGraph(boardState.pieces ?? [])
|
|
}
|