emergency: randomize route selection near start city
This commit is contained in:
1 parent
a6c0418153
commit
8f085e0db0
1 file changed
+53
-38
Vendored
+53
-38
@@ -3533,19 +3533,9 @@ function nearestEmergencyCity() {
|
|||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectEmergencyRoutes() {
|
function emergencyCollectCandidates(sec, startCity, minKm, maxKm, nearLimit) {
|
||||||
emergencyRoutes = [];
|
var targetKm = (minKm + maxKm) / 2;
|
||||||
emergencyVehicles = [];
|
var out = [];
|
||||||
emergencyCount = 0;
|
|
||||||
emergencyLastT = null;
|
|
||||||
if (!EMERGENCY_ON || !carGeo || !carGeo.secondary || !carGeo.secondary.cnts || !carGeo.secondary.cnts.length) {
|
|
||||||
window.__emergencyDbg = { enabled: EMERGENCY_ON, startCity: null, routes: 0 };
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
emergencyStartCity = nearestEmergencyCity();
|
|
||||||
var sec = carGeo.secondary;
|
|
||||||
var targetKm = (EMERGENCY_MIN_KM + EMERGENCY_MAX_KM) / 2;
|
|
||||||
var candidates = [];
|
|
||||||
var k = 0;
|
var k = 0;
|
||||||
for (var ci = 0; ci < sec.cnts.length; ci++) {
|
for (var ci = 0; ci < sec.cnts.length; ci++) {
|
||||||
var n = sec.cnts[ci];
|
var n = sec.cnts[ci];
|
||||||
@@ -3555,11 +3545,11 @@ function selectEmergencyRoutes() {
|
|||||||
var lastX = sec.pts[last], lastZ = sec.pts[last + 1], lastD = sec.pts[last + 2];
|
var lastX = sec.pts[last], lastZ = sec.pts[last + 1], lastD = sec.pts[last + 2];
|
||||||
var len = Math.max(0, lastD - firstD);
|
var len = Math.max(0, lastD - firstD);
|
||||||
var lenKm = len * KM_PER_TILE;
|
var lenKm = len * KM_PER_TILE;
|
||||||
var dStart = Math.hypot(firstX - emergencyStartCity.x, firstZ - emergencyStartCity.z);
|
var dStart = Math.hypot(firstX - startCity.x, firstZ - startCity.z);
|
||||||
var dEnd = Math.hypot(lastX - emergencyStartCity.x, lastZ - emergencyStartCity.z);
|
var dEnd = Math.hypot(lastX - startCity.x, lastZ - startCity.z);
|
||||||
var near = Math.min(dStart, dEnd);
|
var near = Math.min(dStart, dEnd);
|
||||||
if (near < 1.2 && lenKm >= EMERGENCY_MIN_KM * 0.55 && lenKm <= EMERGENCY_MAX_KM * 1.45) {
|
if (near <= nearLimit && lenKm >= minKm && lenKm <= maxKm) {
|
||||||
candidates.push({
|
out.push({
|
||||||
ci: ci, len: len, lenKm: lenKm, near: near,
|
ci: ci, len: len, lenKm: lenKm, near: near,
|
||||||
score: Math.abs(lenKm - targetKm) + near * 18,
|
score: Math.abs(lenKm - targetKm) + near * 18,
|
||||||
reverse: dEnd < dStart
|
reverse: dEnd < dStart
|
||||||
@@ -3567,35 +3557,58 @@ function selectEmergencyRoutes() {
|
|||||||
}
|
}
|
||||||
k += n * 3;
|
k += n * 3;
|
||||||
}
|
}
|
||||||
candidates.sort(function (a, b) { return a.score - b.score; });
|
return out;
|
||||||
if (!candidates.length) {
|
|
||||||
var best = null, k2 = 0;
|
|
||||||
for (var ci2 = 0; ci2 < sec.cnts.length; ci2++) {
|
|
||||||
var n2 = sec.cnts[ci2];
|
|
||||||
if (n2 < 2) { k2 += n2 * 3; continue; }
|
|
||||||
var f2 = k2, l2 = k2 + (n2 - 1) * 3;
|
|
||||||
var len2 = Math.max(0, sec.pts[l2 + 2] - sec.pts[f2 + 2]);
|
|
||||||
var near2 = Math.min(
|
|
||||||
Math.hypot(sec.pts[f2] - emergencyStartCity.x, sec.pts[f2 + 1] - emergencyStartCity.z),
|
|
||||||
Math.hypot(sec.pts[l2] - emergencyStartCity.x, sec.pts[l2 + 1] - emergencyStartCity.z));
|
|
||||||
if (near2 < 2.5 && (!best || len2 > best.len)) best = { ci: ci2, len: len2, lenKm: len2 * KM_PER_TILE, near: near2, reverse: false };
|
|
||||||
k2 += n2 * 3;
|
|
||||||
}
|
}
|
||||||
if (best) candidates.push(best);
|
|
||||||
|
function emergencyShuffle(arr) {
|
||||||
|
for (var i = arr.length - 1; i > 0; i--) {
|
||||||
|
var j = Math.floor(Math.random() * (i + 1));
|
||||||
|
var t = arr[i]; arr[i] = arr[j]; arr[j] = t;
|
||||||
}
|
}
|
||||||
for (var r = 0; r < Math.min(EMERGENCY_COUNT, candidates.length); r++) {
|
return arr;
|
||||||
var route = emergencyChainAt(sec, candidates[r].ci);
|
}
|
||||||
if (candidates[r].reverse) route.reverse();
|
|
||||||
|
function selectEmergencyRoutes() {
|
||||||
|
emergencyRoutes = [];
|
||||||
|
emergencyVehicles = [];
|
||||||
|
emergencyCount = 0;
|
||||||
|
emergencyLastT = null;
|
||||||
|
if (!EMERGENCY_ON || !carGeo || !carGeo.secondary || !carGeo.secondary.cnts || !carGeo.secondary.cnts.length) {
|
||||||
|
window.__emergencyDbg = { enabled: EMERGENCY_ON, startCity: null, candidates: 0, routes: 0 };
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
pool.sort(function (a, b) { return a.score - b.score; });
|
||||||
|
var top = pool.slice(0, Math.max(EMERGENCY_COUNT * 8, 24));
|
||||||
|
emergencyShuffle(top);
|
||||||
|
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);
|
||||||
|
if (cand.reverse) route.reverse();
|
||||||
var len = route.length ? route[route.length - 1].d - route[0].d : 0;
|
var len = route.length ? route[route.length - 1].d - route[0].d : 0;
|
||||||
if (len <= 0) continue;
|
if (len <= 0) continue;
|
||||||
emergencyRoutes.push({ pts: route, len: len, lenKm: len * KM_PER_TILE, nearKm: candidates[r].near * KM_PER_TILE });
|
emergencyRoutes.push({ pts: route, len: len, lenKm: len * KM_PER_TILE, nearKm: cand.near * KM_PER_TILE });
|
||||||
}
|
}
|
||||||
for (var v = 0; v < emergencyRoutes.length; v++) {
|
for (var v = 0; v < emergencyRoutes.length; v++) {
|
||||||
emergencyVehicles.push({
|
emergencyVehicles.push({
|
||||||
route: v,
|
route: v,
|
||||||
d: emergencyRoutes[v].len * (0.08 + 0.72 * ((v * 0.371) % 1)),
|
d: emergencyRoutes[v].len * (0.05 + 0.85 * Math.random()),
|
||||||
dir: ((v % 2) === 0) ? 1 : -1,
|
dir: Math.random() < 0.5 ? 1 : -1,
|
||||||
seed: (v * 0.6180339887) % 1
|
seed: Math.random()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
emergencyCount = emergencyVehicles.length;
|
emergencyCount = emergencyVehicles.length;
|
||||||
@@ -3608,6 +3621,8 @@ function selectEmergencyRoutes() {
|
|||||||
pop: emergencyStartCity.pop,
|
pop: emergencyStartCity.pop,
|
||||||
km: +(emergencyStartCity.dist * KM_PER_TILE).toFixed(1)
|
km: +(emergencyStartCity.dist * KM_PER_TILE).toFixed(1)
|
||||||
} : null,
|
} : null,
|
||||||
|
poolMode: poolMode,
|
||||||
|
candidates: pool.length,
|
||||||
routes: emergencyRoutes.map(function (r) { return { km: +r.lenKm.toFixed(1), nearKm: +r.nearKm.toFixed(1) }; })
|
routes: emergencyRoutes.map(function (r) { return { km: +r.lenKm.toFixed(1), nearKm: +r.nearKm.toFixed(1) }; })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user