switch to web app

This commit is contained in:
2025-12-20 15:06:53 +01:00
parent 52cd4ea0ec
commit f600897ee8
7 changed files with 2682 additions and 10 deletions

284
index.html Normal file
View File

@ -0,0 +1,284 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LiXX Cell Pack Matcher</title>
<link rel="stylesheet" href="css/styles.css">
<link rel="icon" href="data/favicon.svg" type="image/svg+xml">
</head>
<body>
<div class="container">
<header>
<div class="logo">
<svg viewBox="0 0 48 48" width="40" height="40" aria-hidden="true">
<rect x="4" y="8" width="40" height="32" rx="4" fill="none" stroke="currentColor"
stroke-width="2" />
<rect x="44" y="18" width="4" height="12" rx="1" fill="currentColor" />
<rect x="10" y="14" width="8" height="20" rx="2" fill="var(--accent)" />
<rect x="20" y="14" width="8" height="20" rx="2" fill="var(--accent)" />
<rect x="30" y="14" width="8" height="20" rx="2" fill="var(--accent)" />
</svg>
<h1>LiXX Cell Pack Matcher</h1>
</div>
<p class="subtitle">Optimal cell matching for lithium battery packs</p>
</header>
<main>
<!-- Configuration Section -->
<section class="card" aria-labelledby="config-heading">
<h2 id="config-heading">Pack Configuration</h2>
<div class="config-grid">
<div class="form-group">
<label for="cells-serial">Series (S)</label>
<input type="number" id="cells-serial" min="1" max="42" value="6"
aria-describedby="serial-help">
<small id="serial-help">Number of cells in series</small>
</div>
<div class="form-group">
<label for="cells-parallel">Parallel (P)</label>
<input type="number" id="cells-parallel" min="1" max="42" value="2"
aria-describedby="parallel-help">
<small id="parallel-help">Number of cells in parallel</small>
</div>
<div class="form-group">
<label for="config-display">Configuration</label>
<output id="config-display" class="config-badge">6S2P</output>
<small>Total: <span id="total-cells-needed">12</span> cells</small>
</div>
</div>
</section>
<!-- Cell Input Section -->
<section class="card" aria-labelledby="cells-heading">
<h2 id="cells-heading">Cell Data</h2>
<div class="cell-input-header">
<p>Enter cell data: Label, Capacity (mAh), Internal Resistance (mΩ, optional)</p>
<div class="button-group">
<button type="button" id="btn-add-cell" class="btn btn-secondary">
<span aria-hidden="true">+</span> Add Cell
</button>
<button type="button" id="btn-load-example" class="btn btn-ghost">
Load Example
</button>
<button type="button" id="btn-clear-all" class="btn btn-ghost btn-danger">
Clear All
</button>
</div>
</div>
<div class="cell-table-wrapper">
<table class="cell-table" id="cell-table" role="grid">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Label</th>
<th scope="col">Capacity (mAh)</th>
<th scope="col">IR (mΩ)</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody id="cell-tbody">
<!-- Cells will be added dynamically -->
</tbody>
</table>
</div>
<div class="cell-stats" id="cell-stats" aria-live="polite">
<span>Cells: <strong id="stat-count">0</strong></span>
<span>Avg Capacity: <strong id="stat-avg-cap">-</strong></span>
<span>Avg IR: <strong id="stat-avg-ir">-</strong></span>
</div>
</section>
<!-- Algorithm Settings -->
<section class="card" aria-labelledby="algo-heading">
<h2 id="algo-heading">Matching Settings</h2>
<div class="settings-grid">
<div class="form-group">
<label for="weight-capacity">Capacity Weight</label>
<input type="range" id="weight-capacity" min="0" max="100" value="70"
aria-describedby="weight-cap-value">
<output id="weight-cap-value">70%</output>
</div>
<div class="form-group">
<label for="weight-ir">IR Weight</label>
<input type="range" id="weight-ir" min="0" max="100" value="30"
aria-describedby="weight-ir-value">
<output id="weight-ir-value">30%</output>
</div>
<div class="form-group">
<label for="algorithm-select">Algorithm</label>
<select id="algorithm-select">
<option value="genetic">Genetic Algorithm (Fast)</option>
<option value="simulated-annealing">Simulated Annealing</option>
<option value="exhaustive">Exhaustive (Small packs only)</option>
</select>
</div>
<div class="form-group">
<label for="max-iterations">Max Iterations</label>
<input type="number" id="max-iterations" min="100" max="100000" value="5000">
</div>
</div>
<button type="button" id="btn-start-matching" class="btn btn-primary btn-large">
<span class="btn-icon" aria-hidden="true"></span>
Start Matching
</button>
</section>
<!-- Progress Section -->
<section class="card" id="progress-section" hidden aria-labelledby="progress-heading">
<h2 id="progress-heading">Matching Progress</h2>
<div class="progress-container">
<div class="progress-bar">
<div class="progress-fill" id="progress-fill" style="width: 0%"></div>
</div>
<div class="progress-stats">
<span>Iteration: <strong id="progress-iteration">0</strong></span>
<span>Best Score: <strong id="progress-score">-</strong></span>
<span>Time: <strong id="progress-time">0s</strong></span>
</div>
</div>
<button type="button" id="btn-stop-matching" class="btn btn-secondary">
Stop
</button>
</section>
<!-- Results Section -->
<section class="card" id="results-section" hidden aria-labelledby="results-heading">
<h2 id="results-heading">Matching Results</h2>
<!-- Warning Banner -->
<div class="warning-banner" role="alert">
<div class="warning-icon" aria-hidden="true">⚠️</div>
<div class="warning-content">
<strong>Safety Warning - Used Lithium Cells</strong>
<ul>
<li>Used cells may have hidden defects not detectable by capacity/IR testing</li>
<li>Internal resistance mismatch >20% can reduce cycle life by up to 40%
<a href="https://doi.org/10.1016/j.jpowsour.2013.11.064" target="_blank"
rel="noopener">(Shi et al., 2013)</a>
</li>
<li>Always use a BMS with cell-level monitoring and balancing</li>
<li>Use only same model of cell in a pack.</li>
<li>Never charge unattended; use fireproof storage</li>
<li>Cells with significantly different ages may degrade unpredictably</li>
</ul>
</div>
</div>
<!-- Results Summary -->
<div class="results-summary" id="results-summary">
<div class="result-metric">
<span class="metric-value" id="result-score">-</span>
<span class="metric-label">Match Score</span>
</div>
<div class="result-metric">
<span class="metric-value" id="result-cap-variance">-</span>
<span class="metric-label">Capacity CV%</span>
</div>
<div class="result-metric">
<span class="metric-value" id="result-ir-variance">-</span>
<span class="metric-label">IR CV%</span>
</div>
<div class="result-metric">
<span class="metric-value" id="result-pack-capacity">-</span>
<span class="metric-label">Pack Capacity</span>
</div>
</div>
<!-- Visual Pack Layout -->
<div class="pack-visualization" id="pack-visualization">
<h3>Pack Layout</h3>
<div class="pack-grid" id="pack-grid">
<!-- Generated dynamically -->
</div>
<div class="pack-legend">
<span><span class="legend-color" style="background: var(--cell-low)"></span> Lower
Capacity</span>
<span><span class="legend-color" style="background: var(--cell-mid)"></span> Average</span>
<span><span class="legend-color" style="background: var(--cell-high)"></span> Higher
Capacity</span>
</div>
</div>
<!-- Detailed Results Table -->
<div class="results-table-wrapper">
<h3>Parallel Group Details</h3>
<table class="results-table" id="results-table">
<thead>
<tr>
<th>Group</th>
<th>Cells</th>
<th>Total Capacity</th>
<th>Avg IR</th>
<th>Deviation</th>
</tr>
</thead>
<tbody id="results-tbody">
<!-- Generated dynamically -->
</tbody>
</table>
</div>
<!-- Excluded Cells -->
<div class="excluded-cells" id="excluded-cells-section" hidden>
<h3>Excluded Cells</h3>
<p id="excluded-cells-list"></p>
</div>
<!-- Export Buttons -->
<div class="export-buttons">
<button type="button" id="btn-export-json" class="btn btn-secondary">
Export JSON
</button>
<button type="button" id="btn-export-csv" class="btn btn-secondary">
Export CSV
</button>
<button type="button" id="btn-copy-results" class="btn btn-secondary">
Copy to Clipboard
</button>
</div>
</section>
</main>
<footer>
<p>
<a href="https://git.mosad.xyz/localhorst/LiXX_Cell_Pack_Matcher" target="_blank" rel="noopener">Git</a>
·
Based on research by
<a href="https://doi.org/10.1016/j.jpowsour.2013.11.064" target="_blank" rel="noopener">Shi et al.,
2013</a>
</p>
<p class="disclaimer">
This tool is for educational purposes. Always consult professional guidance for battery pack assembly.
</p>
</footer>
</div>
<!-- Keyboard Shortcuts Modal -->
<dialog id="shortcuts-dialog">
<h2>Keyboard Shortcuts</h2>
<dl class="shortcuts-list">
<dt><kbd>Alt</kbd> + <kbd>A</kbd></dt>
<dd>Add new cell</dd>
<dt><kbd>Alt</kbd> + <kbd>S</kbd></dt>
<dd>Start matching</dd>
<dt><kbd>Alt</kbd> + <kbd>E</kbd></dt>
<dd>Load example data</dd>
<dt><kbd>Esc</kbd></dt>
<dd>Stop matching / Close dialog</dd>
<dt><kbd>?</kbd></dt>
<dd>Show this help</dd>
</dl>
<button type="button" class="btn btn-primary" id="btn-close-shortcuts">Close</button>
</dialog>
<script src="js/matching-algorithms.js"></script>
<script src="js/app.js"></script>
</body>
</html>