aboutsummaryrefslogtreecommitdiff
path: root/public/app.js
diff options
context:
space:
mode:
authordax <me@dax.ist>2026-08-04 08:11:30 +0000
committerdax <me@dax.ist>2026-08-04 08:11:30 +0000
commit2ed3e870b70ab1991e5cda8a89d4c6a583d6f4e3 (patch)
tree89aad4131199dea4a553ec8454f30bb2ab882cf7 /public/app.js
parent3782ab9a448361355a7e619383bdf368a8b8492d (diff)
pathways: space-aware photo pick - use walk next when fit is close, substitute better-fitting walked photo on bad fit (FIT_TOLERANCE)
Diffstat (limited to 'public/app.js')
-rw-r--r--public/app.js53
1 files changed, 34 insertions, 19 deletions
diff --git a/public/app.js b/public/app.js
index 4325292..6c69f92 100644
--- a/public/app.js
+++ b/public/app.js
@@ -7,6 +7,7 @@ const splash = $("#splash")
const startBtn = $("#start")
const GAP = 10
+const FIT_TOLERANCE = 350
const ARROW_SVG = {
N: '<svg viewBox="0 0 24 24"><path d="M5 15l7-8 7 8" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
E: '<svg viewBox="0 0 24 24"><path d="M9 5l8 7-8 7" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
@@ -104,9 +105,9 @@ function packGap(rect, w, h) {
return sum
}
-function placeRect(w, h, from, dir) {
+function bestPlacement(w, h, from, dir) {
const base = baseRect(w, h, from, dir)
- if (!collides(base)) return base
+ if (!collides(base)) return { rect: base, cost: 0 }
const xs = new Set([base.x])
const ys = new Set([base.y])
@@ -134,7 +135,12 @@ function placeRect(w, h, from, dir) {
}
}
}
- return best
+ return best ? { rect: best, cost: bestCost } : null
+}
+
+function placeRect(w, h, from, dir) {
+ const p = bestPlacement(w, h, from, dir)
+ return p ? p.rect : null
}
function addTile(info, rect) {
@@ -218,24 +224,33 @@ async function moveFrom(id, dir) {
const ex = exits && exits.find((e) => e.dir === dir)
if (!ex) return
const from = tiles.get(id).rect
- let targetId = null
- if (!rectOf.has(ex.next.id)) {
- targetId = ex.next.id
- } else {
- for (const wid of ex.walk) {
- if (!rectOf.has(wid)) {
- targetId = wid
- break
- }
+ const seen = new Set()
+ const candIds = []
+ const addCand = (cid) => {
+ if (cid && !seen.has(cid) && !rectOf.has(cid)) {
+ seen.add(cid)
+ candIds.push(cid)
}
}
- if (targetId == null) return
- const info = photoInfo.get(targetId) || (tiles.get(targetId) && tiles.get(targetId).info)
- if (!info) return
- const rect = placeRect(tileW(info), tileH(info), from, dir)
- if (!rect) return
- addTile(info, rect)
- setCurrent(targetId, rect)
+ addCand(ex.next && ex.next.id)
+ for (const wid of ex.walk) {
+ if (candIds.length >= 4) break
+ addCand(wid)
+ }
+ const scored = []
+ for (const cid of candIds) {
+ const info = photoInfo.get(cid) || (tiles.get(cid) && tiles.get(cid).info)
+ if (!info) continue
+ const p = bestPlacement(tileW(info), tileH(info), from, dir)
+ if (p) scored.push({ id: cid, info, rect: p.rect, cost: p.cost })
+ }
+ if (!scored.length) return
+ scored.sort((a, b) => a.cost - b.cost)
+ const best = scored[0]
+ const next = ex.next && !rectOf.has(ex.next.id) ? scored.find((s) => s.id === ex.next.id) : null
+ const chosen = next && next.cost - best.cost <= FIT_TOLERANCE ? next : best
+ addTile(chosen.info, chosen.rect)
+ setCurrent(chosen.id, chosen.rect)
}
stage.addEventListener("pointerover", (e) => {