in der Roademap weitergemacht
This commit is contained in:
+77
-23
@@ -53,12 +53,23 @@
|
||||
padding: .3rem .7rem; margin: .15rem .3rem .15rem 0; font-size: .9rem; }
|
||||
.kennzahl b { color: var(--akzent); }
|
||||
.hinweis { font-size: .8rem; color: #6b6557; }
|
||||
.varianten { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .6rem; }
|
||||
.variante {
|
||||
border: 1px solid var(--rand); border-radius: 6px; background: white;
|
||||
padding: .5rem .8rem; cursor: pointer; font-size: .85rem; text-align: left;
|
||||
color: #2a2a24; min-width: 11rem;
|
||||
}
|
||||
.variante.aktiv { border-color: var(--akzent); background: #e6f0ea;
|
||||
box-shadow: 0 0 0 1px var(--akzent); }
|
||||
.variante b { color: var(--akzent); font-size: 1rem; }
|
||||
.variante .zeile { display: block; color: #6b6557; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Sitz & Platz <small style="font-weight:normal">— Testoberfläche (Meilenstein 1)</small></h1>
|
||||
<p>Session-basiert, nichts wird dauerhaft gespeichert (TTL 24 h). Sitzung: <code id="sitzungsId">wird angelegt…</code></p>
|
||||
<p>Session-basiert, nichts wird dauerhaft gespeichert (TTL 24 h). Sitzung: <code id="sitzungsId">wird angelegt…</code>
|
||||
· <a href="/editor.html" style="color:#d6eade">grafischer Tisch-Editor</a></p>
|
||||
</header>
|
||||
<main>
|
||||
|
||||
@@ -104,12 +115,15 @@
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>3. Sitzordnung berechnen</h2>
|
||||
<p class="hinweis">Jeder Klick startet den genetischen Algorithmus neu und liefert
|
||||
eine neue Variante — die Wertigkeit (0 = perfekt, negativer = schlechter)
|
||||
macht Varianten vergleichbar.</p>
|
||||
<h2>3. Sitzordnung berechnen & Varianten vergleichen</h2>
|
||||
<p class="hinweis">Ein Lauf liefert bis zu drei <em>unterschiedliche</em> gute
|
||||
Sitzordnungen zum Vergleich — die Wertigkeit (0 = perfekt, negativer = schlechter),
|
||||
die Zahl getrennter Gruppen und allein sitzende Personen machen sie vergleichbar.
|
||||
Variante anklicken, um Tische und Raumplan umzuschalten; jeder weitere Klick auf
|
||||
„Berechnen“ startet einen frischen Lauf.</p>
|
||||
<button type="button" id="berechnenKnopf" onclick="berechnen()" disabled>Sitzordnung berechnen</button>
|
||||
<div class="status" id="rechnenStatus"></div>
|
||||
<div class="varianten" id="variantenListe"></div>
|
||||
<div id="kennzahlen"></div>
|
||||
<div id="ergebnisTabellen"></div>
|
||||
<img id="svgBild" alt="" style="display:none">
|
||||
@@ -266,20 +280,22 @@ async function berechnenFreigeben() {
|
||||
} catch (e) { /* Session ggf. abgelaufen — beim Berechnen gemeldet */ }
|
||||
}
|
||||
|
||||
let letzterLauf = null; // Antwort des letzten Berechnen-Laufs (mit Varianten)
|
||||
|
||||
async function berechnen() {
|
||||
const knopf = document.getElementById('berechnenKnopf');
|
||||
knopf.disabled = true;
|
||||
status('rechnenStatus', 'Der genetische Algorithmus läuft…');
|
||||
try {
|
||||
const r = await api('/sitzung/' + sitzung + '/berechnen', { method: 'POST' });
|
||||
status('rechnenStatus', '✓ Variante ' + r.variante + ' berechnet.', 'ok');
|
||||
knopf.textContent = 'Neue Variante berechnen';
|
||||
zeigeErgebnis(r);
|
||||
const svg = await fetch('/sitzung/' + sitzung + '/ergebnis.svg');
|
||||
const svgText = await svg.text();
|
||||
const bild = document.getElementById('svgBild');
|
||||
bild.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svgText);
|
||||
bild.style.display = 'block';
|
||||
const r = await api('/sitzung/' + sitzung + '/berechnen?varianten=3', { method: 'POST' });
|
||||
letzterLauf = r;
|
||||
status('rechnenStatus', '✓ Lauf ' + r.lauf + ': ' + r.varianten.length +
|
||||
(r.varianten.length === 1
|
||||
? ' Variante gefunden (der Lauf konvergierte auf eine Sitzordnung).'
|
||||
: ' unterschiedliche Varianten zum Vergleich.'), 'ok');
|
||||
knopf.textContent = 'Neuen Lauf berechnen';
|
||||
zeigeVariantenListe(r);
|
||||
await zeigeVariante(0);
|
||||
} catch (e) {
|
||||
status('rechnenStatus', 'Fehler: ' + e.message, 'fehler');
|
||||
} finally {
|
||||
@@ -287,15 +303,31 @@ async function berechnen() {
|
||||
}
|
||||
}
|
||||
|
||||
function zeigeErgebnis(r) {
|
||||
const getrennte = r.gruppen.filter(g => g.teilungen > 0).length;
|
||||
function zeigeVariantenListe(r) {
|
||||
document.getElementById('variantenListe').innerHTML = r.varianten.map((v, i) =>
|
||||
'<button type="button" class="variante" data-i="' + i + '" onclick="zeigeVariante(' + i + ')">' +
|
||||
'<b>Variante ' + v.nr + '</b>' +
|
||||
'<span class="zeile">Wertigkeit: ' + v.kennzahlen.wertigkeit + '</span>' +
|
||||
'<span class="zeile">getrennte Gruppen: ' + v.kennzahlen.getrennteGruppen +
|
||||
' (' + v.kennzahlen.teilungenGesamt + ' Teilungen)</span>' +
|
||||
'<span class="zeile">allein sitzend: ' + v.kennzahlen.alleinePersonen + '</span>' +
|
||||
'</button>').join('');
|
||||
}
|
||||
|
||||
async function zeigeVariante(i) {
|
||||
if (!letzterLauf || !letzterLauf.varianten[i]) return;
|
||||
const v = letzterLauf.varianten[i];
|
||||
document.querySelectorAll('#variantenListe .variante').forEach(el =>
|
||||
el.classList.toggle('aktiv', parseInt(el.dataset.i, 10) === i));
|
||||
|
||||
document.getElementById('kennzahlen').innerHTML =
|
||||
'<span class="kennzahl">Wertigkeit: <b>' + r.wertigkeit + '</b></span>' +
|
||||
'<span class="kennzahl">Variante: <b>' + r.variante + '</b></span>' +
|
||||
'<span class="kennzahl">getrennte Gruppen: <b>' + getrennte + '</b></span>';
|
||||
'<span class="kennzahl">Variante: <b>' + v.nr + '</b> (Lauf ' + letzterLauf.lauf + ')</span>' +
|
||||
'<span class="kennzahl">Wertigkeit: <b>' + v.kennzahlen.wertigkeit + '</b></span>' +
|
||||
'<span class="kennzahl">getrennte Gruppen: <b>' + v.kennzahlen.getrennteGruppen + '</b></span>' +
|
||||
'<span class="kennzahl">allein sitzend: <b>' + v.kennzahlen.alleinePersonen + '</b></span>';
|
||||
|
||||
let html = '<table><thead><tr><th>Tisch</th><th>Belegung</th><th>Gäste (Gruppe)</th></tr></thead><tbody>';
|
||||
for (const t of r.tische) {
|
||||
for (const t of v.tische) {
|
||||
const gaeste = t.personen.map(p =>
|
||||
((p.titel ? p.titel + ' ' : '') + p.vorname + ' ' + p.nachname +
|
||||
' <span class="hinweis">(' + p.gruppe + ')</span>')).join(', ');
|
||||
@@ -306,10 +338,19 @@ function zeigeErgebnis(r) {
|
||||
|
||||
html += '<h2 style="margin-top:1rem">Gruppen</h2>' +
|
||||
'<table><thead><tr><th>Gruppe</th><th>Personen</th><th>Teilungen</th><th>Strafpunkte</th></tr></thead><tbody>' +
|
||||
r.gruppen.map(g => '<tr><td>' + g.name + '</td><td>' + g.anzahl + '</td><td>' +
|
||||
v.gruppen.map(g => '<tr><td>' + g.name + '</td><td>' + g.anzahl + '</td><td>' +
|
||||
g.teilungen + '</td><td>' + g.wert + '</td></tr>').join('') +
|
||||
'</tbody></table>';
|
||||
document.getElementById('ergebnisTabellen').innerHTML = html;
|
||||
|
||||
// Raumplan der gewaehlten Variante
|
||||
try {
|
||||
const svg = await fetch('/sitzung/' + sitzung + '/ergebnis.svg?variante=' + v.nr);
|
||||
const svgText = await svg.text();
|
||||
const bild = document.getElementById('svgBild');
|
||||
bild.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svgText);
|
||||
bild.style.display = 'block';
|
||||
} catch (e) { /* SVG optional — Tabellen stehen schon da */ }
|
||||
}
|
||||
|
||||
/* ------------------------------------------------ Start */
|
||||
@@ -317,13 +358,26 @@ window.addEventListener('DOMContentLoaded', async () => {
|
||||
document.getElementById('csvText').value = beispielCSV;
|
||||
presetReihe();
|
||||
try {
|
||||
const r = await api('/sitzung', { method: 'POST' });
|
||||
sitzung = r.id;
|
||||
sitzung = await sitzungHolen();
|
||||
document.getElementById('sitzungsId').textContent = sitzung;
|
||||
} catch (e) {
|
||||
document.getElementById('sitzungsId').textContent = 'Fehler: ' + e.message;
|
||||
}
|
||||
});
|
||||
|
||||
// Session mit dem grafischen Editor (editor.html) ueber localStorage teilen:
|
||||
// eine bestehende, noch gueltige Sitzung wiederverwenden statt jedes Mal
|
||||
// eine neue anzulegen — so wirkt ein im Editor gebautes Layout hier weiter.
|
||||
async function sitzungHolen() {
|
||||
let id = localStorage.getItem('platzSitzung');
|
||||
if (id) {
|
||||
const ok = await fetch('/sitzung/' + id).then(r => r.ok).catch(() => false);
|
||||
if (ok) return id;
|
||||
}
|
||||
const r = await api('/sitzung', { method: 'POST' });
|
||||
localStorage.setItem('platzSitzung', r.id);
|
||||
return r.id;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user