From 92bb9e651c208bfea1b3944f7fe9386e103f72a3 Mon Sep 17 00:00:00 2001 From: Richard Zink Date: Tue, 13 Oct 2026 07:21:06 +0200 Subject: [PATCH] emergency: widen route fallback and include motorway chains --- vendor/clouds3d.js | 57 ++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index 70bf798..9863925 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -3533,16 +3533,17 @@ function nearestEmergencyCity() { return best; } -function emergencyCollectCandidates(sec, startCity, minKm, maxKm, nearLimit) { +function emergencyCollectCandidates(net, netKey, startCity, minKm, maxKm, nearLimit) { var targetKm = (minKm + maxKm) / 2; var out = []; + if (!net || !net.cnts || !net.cnts.length) return out; var k = 0; - for (var ci = 0; ci < sec.cnts.length; ci++) { - var n = sec.cnts[ci]; + for (var ci = 0; ci < net.cnts.length; ci++) { + var n = net.cnts[ci]; if (n < 2) { k += n * 3; continue; } - var firstX = sec.pts[k], firstZ = sec.pts[k + 1], firstD = sec.pts[k + 2]; + var firstX = net.pts[k], firstZ = net.pts[k + 1], firstD = net.pts[k + 2]; var last = k + (n - 1) * 3; - var lastX = sec.pts[last], lastZ = sec.pts[last + 1], lastD = sec.pts[last + 2]; + var lastX = net.pts[last], lastZ = net.pts[last + 1], lastD = net.pts[last + 2]; var len = Math.max(0, lastD - firstD); var lenKm = len * KM_PER_TILE; var dStart = Math.hypot(firstX - startCity.x, firstZ - startCity.z); @@ -3550,7 +3551,7 @@ function emergencyCollectCandidates(sec, startCity, minKm, maxKm, nearLimit) { var near = Math.min(dStart, dEnd); if (near <= nearLimit && lenKm >= minKm && lenKm <= maxKm) { out.push({ - ci: ci, len: len, lenKm: lenKm, near: near, + net: net, netKey: netKey, ci: ci, len: len, lenKm: lenKm, near: near, score: Math.abs(lenKm - targetKm) + near * 18, reverse: dEnd < dStart }); @@ -3560,6 +3561,17 @@ function emergencyCollectCandidates(sec, startCity, minKm, maxKm, nearLimit) { return out; } +function emergencyNetworks() { + var out = []; + if (carGeo && carGeo.secondary && carGeo.secondary.cnts && carGeo.secondary.cnts.length) { + out.push({ net: carGeo.secondary, key: 'secondary' }); + } + if (carGeo && carGeo.motorway && carGeo.motorway.cnts && carGeo.motorway.cnts.length) { + out.push({ net: carGeo.motorway, key: 'motorway' }); + } + return out; +} + function emergencyShuffle(arr) { for (var i = arr.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); @@ -3578,16 +3590,21 @@ function selectEmergencyRoutes() { return; } emergencyStartCity = nearestEmergencyCity(); - var sec = carGeo.secondary; - var pool = emergencyCollectCandidates(sec, emergencyStartCity, EMERGENCY_MIN_KM, EMERGENCY_MAX_KM, 1.2); - var poolMode = 'strict'; - if (!pool.length) { - pool = emergencyCollectCandidates(sec, emergencyStartCity, EMERGENCY_MIN_KM * 0.55, EMERGENCY_MAX_KM * 1.45, 1.8); - poolMode = 'relaxed'; - } - if (!pool.length) { - pool = emergencyCollectCandidates(sec, emergencyStartCity, 10, 160, 3.0); - poolMode = 'fallback'; + var nets = emergencyNetworks(); + var pool = [], poolMode = 'none'; + var passes = [ + { minKm: EMERGENCY_MIN_KM, maxKm: EMERGENCY_MAX_KM, near: 1.2, mode: 'strict' }, + { minKm: EMERGENCY_MIN_KM * 0.55, maxKm: EMERGENCY_MAX_KM * 1.45, near: 1.8, mode: 'relaxed' }, + { minKm: 10, maxKm: 160, near: 3.0, mode: 'fallback' }, + { minKm: 3, maxKm: 220, near: 6.0, mode: 'wide' }, + { minKm: 0.5, maxKm: 400, near: 12.0, mode: 'last-resort' } + ]; + for (var p = 0; p < passes.length && !pool.length; p++) { + for (var ni = 0; ni < nets.length && !pool.length; ni++) { + pool = emergencyCollectCandidates(nets[ni].net, nets[ni].key, emergencyStartCity, + passes[p].minKm, passes[p].maxKm, passes[p].near); + if (pool.length) poolMode = passes[p].mode + ':' + nets[ni].key; + } } pool.sort(function (a, b) { return a.score - b.score; }); var top = pool.slice(0, Math.max(EMERGENCY_COUNT * 8, 24)); @@ -3595,9 +3612,10 @@ function selectEmergencyRoutes() { var used = {}; for (var r = 0; r < top.length && emergencyRoutes.length < EMERGENCY_COUNT; r++) { var cand = top[r]; - if (used[cand.ci]) continue; - used[cand.ci] = true; - var route = emergencyChainAt(sec, cand.ci); + var usedKey = cand.netKey + ':' + cand.ci; + if (used[usedKey]) continue; + used[usedKey] = true; + var route = emergencyChainAt(cand.net, cand.ci); if (cand.reverse) route.reverse(); var len = route.length ? route[route.length - 1].d - route[0].d : 0; if (len <= 0) continue; @@ -3623,6 +3641,7 @@ function selectEmergencyRoutes() { } : null, poolMode: poolMode, candidates: pool.length, + networks: nets.map(function (n) { return { key: n.key, chains: n.net.cnts.length }; }), routes: emergencyRoutes.map(function (r) { return { km: +r.lenKm.toFixed(1), nearKm: +r.nearKm.toFixed(1) }; }) }; }