fix stop
This commit is contained in:
44
js/app.js
44
js/app.js
@ -90,6 +90,47 @@ function formatNumber(num) {
|
||||
return num.toLocaleString();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Combination Calculator
|
||||
// =============================================================================
|
||||
|
||||
function binomial(n, k) {
|
||||
if (k > n) return 0;
|
||||
if (k === 0 || k === n) return 1;
|
||||
let result = 1;
|
||||
for (let i = 0; i < k; i++) {
|
||||
result = result * (n - i) / (i + 1);
|
||||
}
|
||||
return Math.round(result);
|
||||
}
|
||||
|
||||
function calculateTotalCombinations(numCells, serial, parallel) {
|
||||
const totalNeeded = serial * parallel;
|
||||
if (numCells < totalNeeded) return 0;
|
||||
|
||||
let total = 1;
|
||||
let remaining = numCells;
|
||||
|
||||
for (let i = 0; i < serial; i++) {
|
||||
total *= binomial(remaining, parallel);
|
||||
remaining -= parallel;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
function updateMaxIterations() {
|
||||
const serial = parseInt(DOM.cellsSerial.value) || 1;
|
||||
const parallel = parseInt(DOM.cellsParallel.value) || 1;
|
||||
const validCells = AppState.cells.filter(c => c.capacity && c.capacity > 0);
|
||||
|
||||
const totalCombinations = calculateTotalCombinations(validCells.length, serial, parallel);
|
||||
|
||||
// Set max iterations: use total combinations if reasonable, cap at 1,000,000
|
||||
const suggested = Math.min(Math.max(totalCombinations, 1000), 1000000);
|
||||
DOM.maxIterations.value = suggested;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Configuration Management
|
||||
// =============================================================================
|
||||
@ -101,6 +142,7 @@ function updateConfigDisplay() {
|
||||
DOM.configDisplay.textContent = `${serial}S${parallel}P`;
|
||||
DOM.totalCellsNeeded.textContent = total;
|
||||
updateMatchingButtonState();
|
||||
updateMaxIterations();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
@ -196,6 +238,8 @@ function updateCellStats() {
|
||||
? `${Math.round(capacities.reduce((a, b) => a + b, 0) / capacities.length)} mAh` : '-';
|
||||
DOM.statAvgIr.textContent = irs.length > 0
|
||||
? `${(irs.reduce((a, b) => a + b, 0) / irs.length).toFixed(1)} mΩ` : '-';
|
||||
|
||||
updateMaxIterations();
|
||||
}
|
||||
|
||||
function loadExampleData() {
|
||||
|
||||
@ -232,10 +232,14 @@ class ExhaustiveSearch {
|
||||
: [[...this.cells]];
|
||||
|
||||
for (const cellSubset of cellCombos) {
|
||||
if (this.stopped) break;
|
||||
if (this.stopped) {
|
||||
return this.returnBestResult(iteration, totalCombinations);
|
||||
}
|
||||
|
||||
for (const partition of this.generatePartitions(cellSubset, this.parallel, this.serial)) {
|
||||
if (this.stopped) break;
|
||||
if (this.stopped) {
|
||||
return this.returnBestResult(iteration, totalCombinations);
|
||||
}
|
||||
|
||||
const scoreResult = calculateScore(partition, this.capacityWeight, this.irWeight);
|
||||
|
||||
@ -247,7 +251,8 @@ class ExhaustiveSearch {
|
||||
iteration++;
|
||||
this.stats.recordIteration();
|
||||
|
||||
if (iteration % (this.maxIterations * 0.01) === 0) {
|
||||
// Check frequently for stop and send progress updates every 100 iterations
|
||||
if (iteration % 100 === 0) {
|
||||
const stats = this.stats.getStats(iteration, Math.min(totalCombinations, this.maxIterations));
|
||||
|
||||
self.postMessage({
|
||||
@ -265,12 +270,29 @@ class ExhaustiveSearch {
|
||||
}
|
||||
|
||||
if (iteration >= this.maxIterations) {
|
||||
this.stopped = true;
|
||||
break;
|
||||
return this.returnBestResult(iteration, totalCombinations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.returnBestResult(iteration, totalCombinations);
|
||||
}
|
||||
|
||||
returnBestResult(iteration, totalCombinations) {
|
||||
if (!this.bestSolution) {
|
||||
// No solution found yet, create one from first cells
|
||||
const config = [];
|
||||
for (let i = 0; i < this.serial; i++) {
|
||||
config.push(this.cells.slice(i * this.parallel, (i + 1) * this.parallel));
|
||||
}
|
||||
const scoreResult = calculateScore(config, this.capacityWeight, this.irWeight);
|
||||
this.bestSolution = { config, ...scoreResult };
|
||||
this.bestScore = scoreResult.score;
|
||||
}
|
||||
|
||||
const usedLabels = new Set(this.bestSolution.config.flat().map(c => c.label));
|
||||
const excludedCells = this.cells.filter(c => !usedLabels.has(c.label));
|
||||
|
||||
// Final progress update
|
||||
const stats = this.stats.getStats(iteration, Math.min(totalCombinations, this.maxIterations));
|
||||
self.postMessage({
|
||||
@ -286,9 +308,6 @@ class ExhaustiveSearch {
|
||||
}
|
||||
});
|
||||
|
||||
const usedLabels = new Set(this.bestSolution.config.flat().map(c => c.label));
|
||||
const excludedCells = this.cells.filter(c => !usedLabels.has(c.label));
|
||||
|
||||
return {
|
||||
configuration: this.bestSolution.config,
|
||||
score: this.bestScore,
|
||||
|
||||
Reference in New Issue
Block a user