188 lines
5.7 KiB
Markdown
188 lines
5.7 KiB
Markdown
# 04 – Resultate & Report (Ausgabe-Dateien)
|
||
|
||
> Schema-Referenz für alle Artefakte der Test-Suite und Aufbau des generierten `report.html`.
|
||
> Diese Dateien werden **zur Laufzeit erzeugt** und **nicht versioniert** (→ `.gitignore`).
|
||
|
||
---
|
||
|
||
## 1. Übersicht der Artefakte
|
||
|
||
| Datei | Erzeugt von | Zweck |
|
||
|---|---|---|
|
||
| `audit-result.json` | `tests/audit.mjs` | Raw-Reports der 3 Audits + Assertions + Page-Errors + Summary |
|
||
| `selfplay-results.json` | `tests/selfplay.mjs` | Episoden-Log + Win-Rate + Aggregates |
|
||
| `perf-result.json` | `tests/perf-test.mjs` | FPS, Heap, Setup-Metadaten |
|
||
| `report.html` | `tests/report.mjs` | Zusammengefasster, menschlich lesbarer CI-Report |
|
||
| `audit-final.png` | `tests/audit.mjs` | Finaler Screenshot des Headless-Browsers |
|
||
|
||
> `report.mjs` liest die drei `*-result.json` und rendert daraus ein einzelnes `report.html`.
|
||
> Fehlt eine JSON-Datei, zeigt `report.html` für die entsprechende Sektion „no data".
|
||
|
||
---
|
||
|
||
## 2. `audit-result.json`
|
||
|
||
```json
|
||
{
|
||
"timestamp": "2026-08-28T19:20:00.000Z",
|
||
"self": {
|
||
"connectivity": [
|
||
{ "level": 0, "name": "…", "reachable": true }
|
||
],
|
||
"attacks": [
|
||
{ "id": "sniper", "projectiles": 12, "hits": 10 }
|
||
],
|
||
"skills": [
|
||
{ "id": "…", "rank": 4 }
|
||
],
|
||
"placement": { "wall": true, "path": true },
|
||
"autoWave": true,
|
||
"endlessTransition": true
|
||
},
|
||
"extension": {
|
||
"mortarSplashTargets": 2,
|
||
"teslaAoE": { "targets": 5, "frozen": true },
|
||
"rewardDedup": true,
|
||
"blockerAltPath": true,
|
||
"blockerClosedPath": true
|
||
},
|
||
"redesign": {
|
||
"sniperPriority": true,
|
||
"quantumBeam": { "aligned": 3, "offLineUnharmed": true },
|
||
"nanoSpawner": { "limit": true, "damage": true, "cleanup": true }
|
||
},
|
||
"pageErrors": [],
|
||
"assertions": [
|
||
{ "name": "self.connectivity.allReachable", "pass": true },
|
||
{ "name": "self.attacks.noZeroProjectiles", "pass": true },
|
||
{ "name": "self.skills.allRank4", "pass": true }
|
||
],
|
||
"summary": {
|
||
"total": 12,
|
||
"pass": 12,
|
||
"fail": 0
|
||
}
|
||
}
|
||
```
|
||
|
||
> **Exit-Code-Kopplung:** `audit.mjs` beendet sich mit `1`, sobald `summary.fail > 0`
|
||
> oder `pageErrors` nicht leer ist. Ein harter Crash im Browser führt zu `2`.
|
||
|
||
---
|
||
|
||
## 3. `selfplay-results.json`
|
||
|
||
```json
|
||
{
|
||
"timestamp": "2026-08-28T19:30:00.000Z",
|
||
"episodes": [
|
||
{
|
||
"placed": 40,
|
||
"towerCount": 40,
|
||
"maxKills": 120,
|
||
"waveReached": 8,
|
||
"totalUpgrades": 64,
|
||
"finalState": "victory",
|
||
"finalKills": 120,
|
||
"finalLeaked": 0,
|
||
"finalLives": 20
|
||
}
|
||
],
|
||
"summary": {
|
||
"total": 10,
|
||
"wins": 8,
|
||
"losses": 2,
|
||
"winRate": 80.0,
|
||
"avgKills": 118,
|
||
"avgWaves": 7.4
|
||
}
|
||
}
|
||
```
|
||
|
||
**Felder:**
|
||
|
||
| Feld | Bedeutung |
|
||
|---|---|
|
||
| `placed` | Anzahl tatsächlich platzierter Türme in der Episode |
|
||
| `towerCount` | Endgültige Turm-Anzahl (inkl. Spawner) |
|
||
| `maxKills` | Höchststand an Kills während der Simulation |
|
||
| `waveReached` | Letzt erreichte Wave |
|
||
| `totalUpgrades` | Anzahl gekaufter Skill-Upgrades |
|
||
| `finalState` | `victory` \| `defeat` |
|
||
| `winRate` | `wins / total × 100` |
|
||
|
||
---
|
||
|
||
## 4. `perf-result.json`
|
||
|
||
```json
|
||
{
|
||
"timestamp": "2026-08-28T19:45:00.000Z",
|
||
"durationMs": 15000,
|
||
"fps": 58,
|
||
"targetFps": 55,
|
||
"pass": true,
|
||
"heap": { "usedMB": 48.3, "totalMB": 96.0 },
|
||
"setup": {
|
||
"levelIdx": 10,
|
||
"levelName": "…",
|
||
"placed": 50,
|
||
"enemies": 40,
|
||
"state": "playing"
|
||
}
|
||
}
|
||
```
|
||
|
||
| Feld | Bedeutung |
|
||
|---|---|
|
||
| `fps` | Gemittelte Frames pro Sekunde während `durationMs` |
|
||
| `targetFps` | Zielwert (Default `55`) – `pass` = `fps >= targetFps` |
|
||
| `heap.usedMB` | `performance.memory.usedJSHeapSize` / 1048576 |
|
||
| `heap.totalMB` | `performance.memory.totalJSHeapSize` / 1048576 |
|
||
|
||
> Heap-Messung benötigt Chromium (`performance.memory`). In nicht-Chromium-Browsern ist
|
||
> `heap` ggf. `null` → `report.mjs` blendet dann die Heap-Spalte aus.
|
||
|
||
---
|
||
|
||
## 5. `report.html`
|
||
|
||
`report.mjs` rendert eine statische, single-file HTML-Seite:
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────┐
|
||
│ Aegis Labyrinth – Test & Audit Report │
|
||
│ Timestamp: 2026-08-28 19:45 │
|
||
├──────────────────────────────────────────────────────────────────┤
|
||
│ ✔ AUDIT pass 12/12 self ✔ extension ✔ redesign ✔ │
|
||
│ ✔ SELF-PLAY winRate 80% (8/10) avgKills 118 │
|
||
│ ✔ PERFORMANCE 58 fps (target 55) heap 48.3 / 96.0 MB │
|
||
├──────────────────────────────────────────────────────────────────┤
|
||
│ Assertion-Details (expandierbare Liste) │
|
||
│ Page-Errors (leer) │
|
||
└──────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**Verhalten:**
|
||
|
||
- Jede Sektion hat einen Ampel-Status: grün (pass) / gelb (teilweise) / rot (fail).
|
||
- Fehlende Quelldatei → Sektion wird als „no data" (grau) gerendert, statt zu crashen.
|
||
- Kein externes JS/CSS → `report.html` ist vollständig offline-viewbar.
|
||
|
||
---
|
||
|
||
## 6. .gitignore (Empfehlung)
|
||
|
||
```gitignore
|
||
# Test-Artefakte (werden zur Laufzeit erzeugt)
|
||
audit-result.json
|
||
selfplay-results.json
|
||
perf-result.json
|
||
report.html
|
||
audit-final.png
|
||
|
||
# Externe Game-Source (manuell in die Root legen)
|
||
Aegis-Labyrinth.html
|
||
|
||
# Node
|
||
node_modules/ |