chore: automate release checks

This commit is contained in:
Jeremy Brandenburger
2026-04-03 11:34:59 +02:00
parent 8ea3b14860
commit e555bbd321
9 changed files with 405 additions and 114 deletions
+230 -112
View File
@@ -7,7 +7,7 @@
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Exo+2:wght@400;600;700&family=Rajdhani:wght@600;700&family=Share+Tech+Mono&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="styles.css?v=1.0.0">
</head>
<body>
@@ -55,24 +55,47 @@
<!-- ── LOGIN ─────────────────────────────────────────────────── -->
<div id="view-login" class="view view-centered">
<div class="login-box">
<div class="login-header">
<span class="login-logo"></span>
<h1>HELLDIVERS 2</h1>
<p class="login-sub">STRATAGEM TRAINER — SUPER EARTH AUTHORIZED</p>
<div class="login-shell">
<section class="login-intel card">
<div class="eyebrow">Super Earth Command</div>
<h1 class="login-intel-title">Deploy faster. Input cleaner. Win harder.</h1>
<p class="login-intel-copy">
Train every stratagem like a live-fire drill, chase leaderboard position, and challenge active Helldivers in the arena.
</p>
<div class="login-intel-grid">
<div class="intel-stat">
<span class="intel-stat-value">4</span>
<span class="intel-stat-label">Training Modes</span>
</div>
<div class="intel-stat">
<span class="intel-stat-value">1v1</span>
<span class="intel-stat-label">Arena Duels</span>
</div>
<div class="intel-stat">
<span class="intel-stat-value">ELO</span>
<span class="intel-stat-label">Rank Tracking</span>
</div>
</div>
</section>
<div class="login-box">
<div class="login-header">
<span class="login-logo"></span>
<h1>HELLDIVERS 2</h1>
<p class="login-sub">STRATAGEM TRAINER — SUPER EARTH AUTHORIZED</p>
</div>
<form id="login-form" class="login-form" autocomplete="off">
<div class="field">
<label for="login-username">Helldiver ID</label>
<input id="login-username" type="text" placeholder="Username" autocomplete="username" required>
</div>
<div class="field">
<label for="login-password">Access Code</label>
<input id="login-password" type="password" placeholder="Password" autocomplete="current-password" required>
</div>
<p id="login-error" class="error hidden"></p>
<button type="submit" class="btn btn-accent btn-full">AUTHENTICATE</button>
</form>
</div>
<form id="login-form" class="login-form" autocomplete="off">
<div class="field">
<label for="login-username">Helldiver ID</label>
<input id="login-username" type="text" placeholder="Username" autocomplete="username" required>
</div>
<div class="field">
<label for="login-password">Access Code</label>
<input id="login-password" type="password" placeholder="Password" autocomplete="current-password" required>
</div>
<p id="login-error" class="error hidden"></p>
<button type="submit" class="btn btn-accent btn-full">AUTHENTICATE</button>
</form>
</div>
</div>
@@ -105,6 +128,28 @@
<!-- ── DASHBOARD ─────────────────────────────────────────────── -->
<div id="view-dashboard" class="view hidden">
<div class="dashboard-grid">
<div class="card dashboard-briefing">
<div class="briefing-copy">
<div class="eyebrow">Mission Briefing</div>
<h2 class="briefing-title">Your command deck for practice, duels, and rank progress.</h2>
<p class="briefing-text" id="dash-status-line">Loading tactical status...</p>
<div class="briefing-pills">
<span class="status-pill">
<span class="status-pill-label">Online</span>
<strong id="dash-online-count">0</strong>
</span>
<span class="status-pill">
<span class="status-pill-label">Daily</span>
<strong id="dash-daily-focus">Pending</strong>
</span>
</div>
</div>
<div class="briefing-actions">
<button class="btn btn-accent" id="btn-briefing-practice">⚡ Quick Start</button>
<button class="btn btn-muted" id="btn-briefing-lobby">⚔ Open Arena</button>
<button class="btn btn-muted" id="btn-briefing-leaderboard">Hall of Heroes</button>
</div>
</div>
<!-- Hero card -->
<div class="card card-hero dashboard-hero">
@@ -162,14 +207,16 @@
<!-- Recent sessions -->
<div class="card">
<h3 class="card-title">Recent Sessions</h3>
<table class="data-table">
<thead>
<tr><th>Stratagem</th><th>Mode</th><th>Score</th><th>Time</th></tr>
</thead>
<tbody id="dash-recent">
<tr><td colspan="4" class="muted">No sessions yet</td></tr>
</tbody>
</table>
<div class="table-wrap">
<table class="data-table">
<thead>
<tr><th>Stratagem</th><th>Mode</th><th>Score</th><th>Time</th></tr>
</thead>
<tbody id="dash-recent">
<tr><td colspan="4" class="muted">No sessions yet</td></tr>
</tbody>
</table>
</div>
</div>
</div>
@@ -234,72 +281,80 @@
</div>
</div>
<div class="stratagem-display card">
<!-- Stratagem icon -->
<div class="stratagem-icon-wrap">
<img id="practice-icon" class="stratagem-icon-lg" src="" alt="" style="display:none">
<div id="practice-icon-fallback" class="stratagem-icon-fallback"></div>
<div class="practice-focus-shell">
<div class="practice-focus-meta">
<span class="focus-chip">Live Drill</span>
<span class="focus-chip focus-chip-muted">Stay on target</span>
</div>
<div class="stratagem-category" id="practice-category"></div>
<div class="stratagem-name" id="practice-name"></div>
<div class="arrow-sequence" id="practice-sequence"></div>
<div class="practice-hint">Arrow Keys or D-Pad · <kbd>Esc</kbd> to stop</div>
</div>
<div id="practice-feedback" class="gameplay-feedback hidden" aria-live="polite"></div>
<!-- Upcoming queue -->
<div class="stratagem-queue" id="practice-queue"></div>
<div class="stratagem-display card">
<!-- Stratagem icon -->
<div class="stratagem-icon-wrap">
<img id="practice-icon" class="stratagem-icon-lg" src="" alt="" style="display:none">
<div id="practice-icon-fallback" class="stratagem-icon-fallback"></div>
</div>
<div class="stratagem-category" id="practice-category"></div>
<div class="stratagem-name" id="practice-name"></div>
<div class="arrow-sequence arrow-sequence-hero" id="practice-sequence"></div>
<div class="practice-hint">Arrow Keys or D-Pad · <kbd>Esc</kbd> to stop</div>
</div>
<div class="practice-hud">
<!-- Timer ring / lives / elapsed -->
<div class="hud-item" id="hud-timer-wrap">
<div class="hud-label" id="hud-timer-label">TIME</div>
<div class="timer-ring-wrap">
<svg class="timer-ring-svg" viewBox="0 0 80 80">
<circle class="timer-ring-bg" cx="40" cy="40" r="35"/>
<circle class="timer-ring-fill" id="timer-ring-fill" cx="40" cy="40" r="35"
stroke-dasharray="219.9" stroke-dashoffset="0"/>
</svg>
<div class="timer-ring-val" id="practice-timer">30</div>
<!-- Upcoming queue -->
<div class="stratagem-queue" id="practice-queue"></div>
<div class="practice-hud">
<!-- Timer ring / lives / elapsed -->
<div class="hud-item" id="hud-timer-wrap">
<div class="hud-label" id="hud-timer-label">TIME</div>
<div class="timer-ring-wrap">
<svg class="timer-ring-svg" viewBox="0 0 80 80">
<circle class="timer-ring-bg" cx="40" cy="40" r="35"/>
<circle class="timer-ring-fill" id="timer-ring-fill" cx="40" cy="40" r="35"
stroke-dasharray="219.9" stroke-dashoffset="0"/>
</svg>
<div class="timer-ring-val" id="practice-timer">30</div>
</div>
</div>
<!-- Lives (endless mode) -->
<div class="hud-item hidden" id="hud-lives-wrap">
<div class="hud-label">LIVES</div>
<div class="lives-display" id="practice-lives">
<span class="life-icon"></span>
<span class="life-icon"></span>
<span class="life-icon"></span>
</div>
</div>
<div class="hud-item">
<div class="hud-label">SCORE</div>
<div class="hud-value" id="practice-score">0</div>
</div>
<div class="hud-item" id="hud-streak-item">
<div class="hud-label">STREAK</div>
<div class="hud-value accent" id="practice-streak">0</div>
<div class="combo-badge hidden" id="practice-combo">×1.0</div>
</div>
</div>
<!-- Lives (endless mode) -->
<div class="hud-item hidden" id="hud-lives-wrap">
<div class="hud-label">LIVES</div>
<div class="lives-display" id="practice-lives">
<span class="life-icon"></span>
<span class="life-icon"></span>
<span class="life-icon"></span>
<!-- D-Pad -->
<div class="dpad" id="practice-dpad">
<div class="dpad-row">
<button class="dpad-btn" data-dir="up" aria-label="Arrow up"><span class="dir-glyph dir-up" aria-hidden="true"><svg viewBox="0 0 64 64" focusable="false"><path class="dir-line" d="M32 50 L32 18" /><path class="dir-head" d="M32 12 L20 24 H28 V50 H36 V24 H44 Z" /></svg></span></button>
</div>
<div class="dpad-row">
<button class="dpad-btn" data-dir="left" aria-label="Arrow left"><span class="dir-glyph dir-left" aria-hidden="true"><svg viewBox="0 0 64 64" focusable="false"><path class="dir-line" d="M32 50 L32 18" /><path class="dir-head" d="M32 12 L20 24 H28 V50 H36 V24 H44 Z" /></svg></span></button>
<div class="dpad-center"></div>
<button class="dpad-btn" data-dir="right" aria-label="Arrow right"><span class="dir-glyph dir-right" aria-hidden="true"><svg viewBox="0 0 64 64" focusable="false"><path class="dir-line" d="M32 50 L32 18" /><path class="dir-head" d="M32 12 L20 24 H28 V50 H36 V24 H44 Z" /></svg></span></button>
</div>
<div class="dpad-row">
<button class="dpad-btn" data-dir="down" aria-label="Arrow down"><span class="dir-glyph dir-down" aria-hidden="true"><svg viewBox="0 0 64 64" focusable="false"><path class="dir-line" d="M32 50 L32 18" /><path class="dir-head" d="M32 12 L20 24 H28 V50 H36 V24 H44 Z" /></svg></span></button>
</div>
</div>
<div class="hud-item">
<div class="hud-label">SCORE</div>
<div class="hud-value" id="practice-score">0</div>
</div>
<div class="hud-item" id="hud-streak-item">
<div class="hud-label">STREAK</div>
<div class="hud-value accent" id="practice-streak">0</div>
<div class="combo-badge hidden" id="practice-combo">×1.0</div>
</div>
<button class="btn btn-muted btn-sm" id="btn-stop-practice">■ Stop Training</button>
</div>
<!-- D-Pad -->
<div class="dpad" id="practice-dpad">
<div class="dpad-row">
<button class="dpad-btn" data-dir="up" aria-label="Arrow up"></button>
</div>
<div class="dpad-row">
<button class="dpad-btn" data-dir="left" aria-label="Arrow left"></button>
<div class="dpad-center"></div>
<button class="dpad-btn" data-dir="right" aria-label="Arrow right"></button>
</div>
<div class="dpad-row">
<button class="dpad-btn" data-dir="down" aria-label="Arrow down"></button>
</div>
</div>
<button class="btn btn-muted btn-sm" id="btn-stop-practice">■ Stop Training</button>
</div>
</div>
@@ -406,27 +461,38 @@
<div style="text-align:center;margin-bottom:8px">
<img id="match-icon" class="stratagem-icon-md" src="" alt="" style="display:none">
</div>
<div class="match-sequences">
<div class="match-seq-col">
<div class="match-seq-label">YOU</div>
<div class="arrow-sequence" id="match-me-sequence"></div>
<div class="match-focus-shell">
<div id="match-feedback" class="gameplay-feedback hidden" aria-live="polite"></div>
<div class="match-sequences">
<div class="match-seq-col">
<div class="match-seq-label">YOU</div>
<div class="duel-progress">
<div class="duel-progress-bar"><div class="duel-progress-fill" id="match-me-progress-fill" style="width:0%"></div></div>
<div class="duel-progress-text" id="match-me-progress-text">0 / 0</div>
</div>
<div class="arrow-sequence arrow-sequence-hero arrow-sequence-duel" id="match-me-sequence"></div>
</div>
<div class="match-seq-col">
<div class="match-seq-label">OPPONENT</div>
<div class="duel-progress">
<div class="duel-progress-bar"><div class="duel-progress-fill duel-progress-fill-opp" id="match-opp-progress-fill" style="width:0%"></div></div>
<div class="duel-progress-text" id="match-opp-progress-text">0 / 0</div>
</div>
<div class="arrow-sequence arrow-sequence-hero arrow-sequence-duel" id="match-opp-sequence"></div>
</div>
</div>
<div class="match-seq-col">
<div class="match-seq-label">OPPONENT</div>
<div class="arrow-sequence" id="match-opp-sequence"></div>
</div>
</div>
<div class="dpad" id="match-dpad">
<div class="dpad-row">
<button class="dpad-btn" data-dir="up" aria-label="Arrow up"></button>
</div>
<div class="dpad-row">
<button class="dpad-btn" data-dir="left" aria-label="Arrow left"></button>
<div class="dpad-center"></div>
<button class="dpad-btn" data-dir="right" aria-label="Arrow right"></button>
</div>
<div class="dpad-row">
<button class="dpad-btn" data-dir="down" aria-label="Arrow down"></button>
<div class="dpad" id="match-dpad">
<div class="dpad-row">
<button class="dpad-btn" data-dir="up" aria-label="Arrow up"><span class="dir-glyph dir-up" aria-hidden="true"><svg viewBox="0 0 64 64" focusable="false"><path class="dir-line" d="M32 50 L32 18" /><path class="dir-head" d="M32 12 L20 24 H28 V50 H36 V24 H44 Z" /></svg></span></button>
</div>
<div class="dpad-row">
<button class="dpad-btn" data-dir="left" aria-label="Arrow left"><span class="dir-glyph dir-left" aria-hidden="true"><svg viewBox="0 0 64 64" focusable="false"><path class="dir-line" d="M32 50 L32 18" /><path class="dir-head" d="M32 12 L20 24 H28 V50 H36 V24 H44 Z" /></svg></span></button>
<div class="dpad-center"></div>
<button class="dpad-btn" data-dir="right" aria-label="Arrow right"><span class="dir-glyph dir-right" aria-hidden="true"><svg viewBox="0 0 64 64" focusable="false"><path class="dir-line" d="M32 50 L32 18" /><path class="dir-head" d="M32 12 L20 24 H28 V50 H36 V24 H44 Z" /></svg></span></button>
</div>
<div class="dpad-row">
<button class="dpad-btn" data-dir="down" aria-label="Arrow down"><span class="dir-glyph dir-down" aria-hidden="true"><svg viewBox="0 0 64 64" focusable="false"><path class="dir-line" d="M32 50 L32 18" /><path class="dir-head" d="M32 12 L20 24 H28 V50 H36 V24 H44 Z" /></svg></span></button>
</div>
</div>
</div>
</div>
@@ -451,14 +517,16 @@
</div>
<div class="card">
<table class="data-table">
<thead id="leaderboard-thead">
<tr><th>#</th><th>Helldiver</th><th>Rank</th><th>Total Score</th><th>Sessions</th><th>Match W/Total</th></tr>
</thead>
<tbody id="leaderboard-table-body">
<tr><td colspan="6" class="muted">Loading...</td></tr>
</tbody>
</table>
<div class="table-wrap">
<table class="data-table">
<thead id="leaderboard-thead">
<tr><th>#</th><th>Helldiver</th><th>Rank</th><th>Total Score</th><th>Sessions</th><th>Match W/Total</th></tr>
</thead>
<tbody id="leaderboard-table-body">
<tr><td colspan="6" class="muted">Loading...</td></tr>
</tbody>
</table>
</div>
</div>
</div>
@@ -466,6 +534,29 @@
<div id="view-admin" class="view hidden">
<div class="page-header">
<h2 class="page-title">ADMIN PANEL</h2>
<p class="page-sub">User control, password operations, role management, and live system activity</p>
</div>
<div class="admin-overview" id="admin-overview">
<div class="card admin-stat-card">
<div class="card-title">Helldivers</div>
<div class="admin-stat-value" id="admin-total-users"></div>
<div class="admin-stat-meta">Registered accounts</div>
</div>
<div class="card admin-stat-card">
<div class="card-title">Admins</div>
<div class="admin-stat-value" id="admin-total-admins"></div>
<div class="admin-stat-meta">Users with command access</div>
</div>
<div class="card admin-stat-card">
<div class="card-title">Temp Passwords</div>
<div class="admin-stat-value" id="admin-temp-passwords"></div>
<div class="admin-stat-meta">Accounts requiring password change</div>
</div>
<div class="card admin-stat-card">
<div class="card-title">Practice Sessions</div>
<div class="admin-stat-value" id="admin-practice-sessions"></div>
<div class="admin-stat-meta">Total runs recorded</div>
</div>
</div>
<div class="admin-layout">
<div class="card">
@@ -484,12 +575,35 @@
<p id="admin-error" class="error hidden"></p>
<button class="btn btn-accent" id="btn-create-user">Create User</button>
<div id="new-pw-display" class="pw-display hidden"></div>
<div class="divider"></div>
<div class="admin-spotlight">
<div class="admin-spotlight-label">Top performer</div>
<div class="admin-spotlight-value" id="admin-top-user"></div>
<div class="admin-spotlight-meta" id="admin-top-user-meta">Loading tactical data...</div>
</div>
</div>
<div class="card">
<h3 class="card-title">Active Helldivers</h3>
<div class="admin-users-header">
<h3 class="card-title">User Management</h3>
<input id="admin-user-search" class="admin-search" type="text" placeholder="Search user">
</div>
<div id="admin-users" class="admin-user-list">Loading...</div>
</div>
</div>
<div class="admin-activity-grid">
<div class="card">
<h3 class="card-title">Recent Practice Activity</h3>
<div id="admin-recent-practice" class="admin-activity-list">
<span class="muted">Loading...</span>
</div>
</div>
<div class="card">
<h3 class="card-title">Recent Matches</h3>
<div id="admin-recent-matches" class="admin-activity-list">
<span class="muted">Loading...</span>
</div>
</div>
</div>
</div>
<!-- ── PRACTICE SETTINGS MODAL ──────────────────────────────── -->
@@ -566,6 +680,9 @@
</div>
<div class="summary-grid" id="summary-grid"></div>
<div style="height:1px;background:var(--border);margin:16px 0"></div>
<h4 style="font-family:var(--font-heading);font-size:0.85rem;letter-spacing:.06em;color:var(--text-muted);margin-bottom:8px">PERFORMANCE ANALYSIS</h4>
<div id="summary-insights" class="summary-insights"></div>
<div style="height:1px;background:var(--border);margin:16px 0"></div>
<h4 style="font-family:var(--font-heading);font-size:0.85rem;letter-spacing:.06em;color:var(--text-muted);margin-bottom:8px">TOP STRATAGEMS</h4>
<div id="summary-top-stratagems"></div>
<div class="modal-actions">
@@ -577,10 +694,11 @@
<!-- ── Danger vignette (≤5s) ──────────────────────────────────── -->
<div id="danger-vignette" class="danger-vignette hidden"></div>
<div id="gameplay-countdown" class="gameplay-countdown hidden" aria-live="assertive"></div>
<!-- Toast notifications -->
<div id="toast-container"></div>
<script src="app.js"></script>
<script src="app.js?v=1.0.0"></script>
</body>
</html>