diff options
| -rw-r--r-- | public/app.js | 53 | ||||
| -rw-r--r-- | public/index.html | 4 |
2 files changed, 36 insertions, 21 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) => { diff --git a/public/index.html b/public/index.html index 9e937f4..1a4f67d 100644 --- a/public/index.html +++ b/public/index.html @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="color-scheme" content="dark"> <title>pathways</title> - <link rel="stylesheet" href="/app.css?v=4"> + <link rel="stylesheet" href="/app.css?v=5"> </head> <body> <main id="stage"> @@ -16,6 +16,6 @@ <p>four paths, one per direction. walk them.</p> <button id="start">start</button> </div> - <script src="/app.js?v=4"></script> + <script src="/app.js?v=5"></script> </body> </html> |
