Atlas: Deploy-Buendel vor Staustufen-Sprint
- Logistik: Musik-Player Playlist-Modus (5 Gruppen, 20 Tracks) - Heli: End-Screen auf .ggs-endscreen, Mission-Bilder, Voice-Lines, Briefing-Audio - Logistik: Layout-Tausch Auftraege+Fahrzeuge links, Karte rechts - Logistik: Tier-1-Staedte ausgebaut, Auto-Timescale-Badge - Logistik: Roadnet/Railnet Dijkstra-Routing, Balance-Updates - Atlas: 5 Atlas-Inbox-Nachrichten (Cards-Pattern, DALL-E-Key, Musik-Playlists) - Status-Updates Heli + Logistik Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
<p>
|
||||
<button id="run-noop">Nur <code>noop</code> (3 Level × 5 Seeds, läuft)</button>
|
||||
<button id="run-all">Alle Strategien (Stubs werfen)</button>
|
||||
<button id="run-corridor" style="background:#b45900;">Balance-Korridor-Check (R-1/R-2/R-3)</button>
|
||||
</p>
|
||||
<div id="results"><p class="legend">Klick auf einen Button.</p></div>
|
||||
</div>
|
||||
@@ -135,6 +136,110 @@ const matrix = await LogistikRunner.runMatrix({
|
||||
|
||||
document.getElementById('run-noop').addEventListener('click', runNoop);
|
||||
document.getElementById('run-all').addEventListener('click', runAll);
|
||||
|
||||
/* ---- Balance-Korridor-Check (siehe balance-corridor.md) ----
|
||||
R-1 (Runway): mathematisch, ohne Run noetig.
|
||||
R-2 (Winnable): pro Level mindestens eine Strategie schafft success.
|
||||
R-3 (Loseable): noop schlaegt 100% fehl; (per Level) auch naive (L2) und greedy (L3).
|
||||
*/
|
||||
function r1Check(cfg) {
|
||||
const vc = cfg.vehicleCount || 1;
|
||||
const rental = cfg.rentalCostPerDay || 0;
|
||||
const idle = cfg.idleCostPerHour || 0;
|
||||
const daily = rental * vc + idle * vc * 12;
|
||||
const needed = 1.5 * daily;
|
||||
const have = cfg.startBudget || 0;
|
||||
return { pass: have >= needed, have, needed, daily };
|
||||
}
|
||||
|
||||
async function runBalanceCorridor() {
|
||||
const root = document.getElementById('results');
|
||||
root.innerHTML = '<p class="legend">…laufe Korridor-Check (3 Level × 3 Strategien × 5 Seeds = 45 Durchläufe)…</p>';
|
||||
|
||||
// R-1: aus level-config (deterministisch, kein Run noetig)
|
||||
const levels = (window.LOGISTIK_LEVELS || []).reduce((m, l) => { m[l.level] = l.params; return m; }, {});
|
||||
const r1 = {};
|
||||
[1,2,3].forEach(lvl => { if (levels[lvl]) r1[lvl] = r1Check(levels[lvl]); });
|
||||
|
||||
// R-2 / R-3: per runMatrix (mit optimal fuer R-2-Hard-Check)
|
||||
const rows = await LogistikRunner.runMatrix({
|
||||
levels: [1,2,3], strategies: ['noop','naive','greedy','optimal'], seeds: [1,2,3,4,5], tolerateErrors: true,
|
||||
});
|
||||
|
||||
// Aggregate per (level, strategy): wieviel von 5 Seeds erfolgreich
|
||||
const agg = {};
|
||||
rows.forEach(r => {
|
||||
const key = r.level + ':' + r.strategy;
|
||||
if (!agg[key]) agg[key] = { total: 0, success: 0, errors: 0, sumBalance: 0 };
|
||||
agg[key].total++;
|
||||
if (r._error) agg[key].errors++;
|
||||
else if (r.successful) { agg[key].success++; agg[key].sumBalance += r.endBalance || 0; }
|
||||
else agg[key].sumBalance += r.endBalance || 0;
|
||||
});
|
||||
|
||||
// Korridor-Verdikte
|
||||
const verdicts = [];
|
||||
[1,2,3].forEach(lvl => {
|
||||
// R-1
|
||||
const r1v = r1[lvl];
|
||||
verdicts.push({
|
||||
rule: 'R-1', level: lvl, pass: r1v && r1v.pass,
|
||||
detail: r1v ? ('startBudget=' + r1v.have + '€ vs benoetigt ' + Math.ceil(r1v.needed) + '€ (Tagesfix ' + r1v.daily + '€)') : 'config fehlt',
|
||||
});
|
||||
// R-2 (Winnable): mind. eine Strategie schafft Median-success.
|
||||
const optimal = agg[lvl + ':optimal'] || { success: 0, total: 5 };
|
||||
const greedy = agg[lvl + ':greedy' ] || { success: 0, total: 5 };
|
||||
const naive = agg[lvl + ':naive' ] || { success: 0, total: 5 };
|
||||
const winnable = optimal.success >= 3 || greedy.success >= 3 || (lvl <= 1 && naive.success >= 3);
|
||||
verdicts.push({
|
||||
rule: 'R-2', level: lvl, pass: winnable,
|
||||
detail: 'naive ' + naive.success + '/' + naive.total
|
||||
+ ' · greedy ' + greedy.success + '/' + greedy.total
|
||||
+ ' · optimal ' + optimal.success + '/' + optimal.total,
|
||||
});
|
||||
// R-3 (Loseable): noop schlaegt zuverlaessig fehl, zusaetzlich level-spezifisch.
|
||||
const noop = agg[lvl + ':noop'] || { success: 0, total: 5 };
|
||||
let loseable = noop.success === 0;
|
||||
let loseDetail = 'noop ' + noop.success + '/' + noop.total;
|
||||
if (lvl >= 2) {
|
||||
// L2: naive soll median-fail
|
||||
loseable = loseable && naive.success <= 2;
|
||||
loseDetail += ' · naive ' + naive.success + '/' + naive.total + ' (darf fast-fail)';
|
||||
}
|
||||
if (lvl === 3) {
|
||||
// L3: greedy soll auch nicht zuverlaessig gewinnen
|
||||
loseable = loseable && greedy.success <= 2;
|
||||
loseDetail += ' · greedy ' + greedy.success + '/' + greedy.total + ' (darf median-fail)';
|
||||
}
|
||||
verdicts.push({
|
||||
rule: 'R-3', level: lvl, pass: loseable,
|
||||
detail: loseDetail,
|
||||
});
|
||||
});
|
||||
|
||||
// Render
|
||||
let html = '<h3 style="margin:14px 0 6px;">Korridor-Verdikte</h3>'
|
||||
+ '<table><thead><tr><th>Regel</th><th>Level</th><th>Status</th><th>Detail</th></tr></thead><tbody>';
|
||||
verdicts.forEach(v => {
|
||||
const cls = v.pass ? 'ok' : 'fail';
|
||||
const lbl = v.pass ? 'PASS' : 'FAIL';
|
||||
html += '<tr><td><code>' + v.rule + '</code></td><td>' + v.level + '</td>'
|
||||
+ '<td class="' + cls + '">' + lbl + '</td>'
|
||||
+ '<td style="font-size:0.85rem;color:#555;">' + v.detail + '</td></tr>';
|
||||
});
|
||||
html += '</tbody></table>';
|
||||
|
||||
html += '<details style="margin-top:14px;"><summary>Roh-Daten (' + rows.length + ' Runs)</summary>'
|
||||
+ renderTable(rows) + '</details>';
|
||||
|
||||
const allPass = verdicts.every(v => v.pass);
|
||||
html += '<p class="legend"><strong>'
|
||||
+ (allPass ? '✅ Alle Korridor-Regeln erfüllt.' : '⚠ Mindestens eine Regel verletzt.')
|
||||
+ '</strong> R-2 prüft jetzt mit <code>optimal</code> (Best-Net-Heuristik).</p>';
|
||||
|
||||
root.innerHTML = html;
|
||||
}
|
||||
document.getElementById('run-corridor').addEventListener('click', runBalanceCorridor);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user