MosswartOverlord/static/index.html
Erik c03b1c19f2 feat: combat stats backend + frontend (Mag-Tools style)
Backend:
- db_async.py: new combat_stats + combat_stats_sessions tables
- main.py: combat_stats message handler with DB upsert (lifetime +
  session snapshots), in-memory live_combat_stats dict, broadcast
  to browser clients.
- REST: GET /combat-stats and GET /combat-stats/{character_name}

Frontend:
- index.html: new "Combat Stats" sidebar link
- script.js: full Combat Stats window with two panels:
  - Top: monster list (name, kills, dmg recv, dmg given) with
    clickable rows and "All" aggregate, matching CombatTrackerGUI.cs
  - Bottom: damage breakdown grid matching CombatTrackerGUIInfo.cs
    layout — element × attack type matrix (Mel/Msl + Magic columns),
    Attacks (hit%), Evades (%), Resists (%), A.Surges (%), C.Surges (%),
    normal Avg/Max, Crits (%), Crit Avg/Max, Total Damage.
  - Session / Lifetime toggle button
- style.css: combat-stats-toggle styles

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 09:42:11 +02:00

161 lines
5 KiB
HTML

<!--
Dereth Tracker Single-Page Application
Displays live player locations, trails, and statistics on a map.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Dereth Tracker</title>
<!-- Link to main stylesheet -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Version display -->
<div id="versionDisplay" style="position:fixed;top:4px;left:4px;z-index:9999;color:#fff;font-size:0.65rem;font-family:monospace;opacity:0.7;"></div>
<!-- Sidebar for active players list and filters -->
<aside id="sidebar">
<h2 id="activePlayersHeader">Active Mosswart Enjoyers</h2>
<!-- Server Status -->
<div id="serverStatus" class="server-status-container">
<h3>Coldeve Server Status</h3>
<div class="status-indicator">
<span class="status-dot" id="statusDot"></span>
<span id="statusText">Checking...</span>
</div>
<div class="status-details">
<div>Players: <span id="playerCount">-</span></div>
<div>Latency: <span id="latencyMs">-</span> ms</div>
<div>Uptime: <span id="uptime">-</span></div>
<div>Last Restart: <span id="lastRestart">-</span></div>
</div>
</div>
<!-- Total rares counter -->
<div id="totalRaresCounter" class="total-rares-counter">
🔥 Total Rares: <span id="totalRaresCount">Loading...</span>
</div>
<!-- Server KPH counter -->
<div id="serverKphCounter" class="server-kph-counter">
⚡ Server KPH: <span id="serverKphCount">Loading...</span>
</div>
<!-- Total kills counter -->
<div id="totalKillsCounter" class="total-kills-counter">
⚔️ Total Kills: <span id="totalKillsCount">Loading...</span>
</div>
<!-- Heat map toggle -->
<div class="heatmap-toggle">
<label>
<input type="checkbox" id="heatmapToggle">
🔥 Show Spawn Heat Map
</label>
</div>
<!-- Portal toggle -->
<div class="portal-toggle">
<label>
<input type="checkbox" id="portalToggle">
🌀 Show Portals
</label>
</div>
<!-- Inventory search link -->
<div class="inventory-search-link">
<a href="#" id="inventorySearchBtn" onclick="openInventorySearch()">
📦 Inventory Search
</a>
</div>
<!-- Suitbuilder link -->
<div class="suitbuilder-link">
<a href="#" id="suitbuilderBtn" onclick="openSuitbuilder()">
🛡️ Suitbuilder
</a>
</div>
<!-- Player Debug link -->
<div class="debug-link">
<a href="#" id="playerDebugBtn" onclick="openPlayerDebug()">
🔍 Player Debug
</a>
</div>
<!-- Quest Status link -->
<div class="quest-status-link">
<a href="#" id="questStatusBtn" onclick="openQuestStatus()">
⏰ Quest Status
</a>
</div>
<!-- Player Dashboard link -->
<div class="player-dashboard-link">
<a href="#" id="playerDashboardBtn" onclick="openPlayerDashboard()">
👥 Player Dashboard
</a>
</div>
<!-- Issues Board link -->
<div class="quest-status-link">
<a href="#" id="issuesBoardBtn" onclick="showIssuesWindow()">
📋 Issues Board
</a>
</div>
<!-- Vital Sharing Network link -->
<div class="quest-status-link">
<a href="#" id="vitalSharingBtn" onclick="showVitalSharingWindow()">
🤝 Vital Sharing
</a>
</div>
<!-- Combat Stats link -->
<div class="quest-status-link">
<a href="#" id="combatStatsBtn" onclick="showCombatStatsWindow()">
Combat Stats
</a>
</div>
<!-- Container for sort and filter controls -->
<div id="sortButtons" class="sort-buttons"></div>
<!-- Text input to filter active players by name -->
<input type="text" id="playerFilter" class="player-filter" placeholder="Filter players..." />
<ul id="playerList"></ul>
<!-- User info section (populated by script.js after /me fetch) -->
<div id="userInfo" class="user-info" style="display:none;">
<span id="currentUsername" class="user-info-name"></span>
<a href="#" id="adminLink" class="user-info-admin" style="display:none;" onclick="window.open('/admin/users','_blank')">Admin</a>
<a href="/logout" class="user-info-logout">Logout</a>
</div>
</aside>
<!-- Epic rare notifications container -->
<div id="rareNotifications" class="rare-notifications"></div>
<!-- Fireworks container -->
<div id="fireworksContainer" class="fireworks-container"></div>
<!-- Main map container showing terrain and player data -->
<div id="mapContainer">
<div id="mapGroup">
<img id="map" src="dereth.png" alt="Dereth map">
<canvas id="heatmapCanvas"></canvas>
<svg id="trails"></svg>
<div id="dots"></div>
<div id="portals"></div>
</div>
<div id="tooltip" class="tooltip"></div>
<div id="coordinates" class="coordinates"></div>
</div>
<!-- Main JavaScript file for WebSocket communication and UI logic -->
<script src="script.js" defer></script>
</body>
</html>