import cells

This commit is contained in:
2026-01-03 12:40:41 +01:00
parent 93984968c3
commit 3826694c15
3 changed files with 326 additions and 10 deletions

142
js/app.js
View File

@ -27,6 +27,7 @@ const DOM = {
cellTbody: document.getElementById('cell-tbody'),
btnAddCell: document.getElementById('btn-add-cell'),
btnLoadExample: document.getElementById('btn-load-example'),
btnImport: document.getElementById('btn-import'),
btnClearAll: document.getElementById('btn-clear-all'),
statCount: document.getElementById('stat-count'),
statAvgCap: document.getElementById('stat-avg-cap'),
@ -62,7 +63,11 @@ const DOM = {
btnExportCsv: document.getElementById('btn-export-csv'),
btnCopyResults: document.getElementById('btn-copy-results'),
shortcutsDialog: document.getElementById('shortcuts-dialog'),
btnCloseShortcuts: document.getElementById('btn-close-shortcuts')
btnCloseShortcuts: document.getElementById('btn-close-shortcuts'),
importDialog: document.getElementById('import-dialog'),
importTextarea: document.getElementById('import-textarea'),
btnImportConfirm: document.getElementById('btn-import-confirm'),
btnImportCancel: document.getElementById('btn-import-cancel')
};
// =============================================================================
@ -261,6 +266,132 @@ function loadExampleData() {
exampleCells.forEach(cell => addCell(cell));
}
// =============================================================================
// Import Functionality
// =============================================================================
function openImportDialog() {
DOM.importTextarea.value = '';
DOM.importDialog.showModal();
DOM.importTextarea.focus();
}
function closeImportDialog() {
DOM.importDialog.close();
}
function parseImportData(text) {
const lines = text.split('\n').map(line => line.trim()).filter(line => line.length > 0);
const cells = [];
let importedCount = 0;
let skippedCount = 0;
for (const line of lines) {
// Support both semicolon and comma as separators
const parts = line.split(/[;,]/).map(p => p.trim());
if (parts.length === 0) {
skippedCount++;
continue;
}
let label = null;
let capacity = null;
let ir = null;
// Parse based on number of columns
if (parts.length === 1) {
// Format: capacity
capacity = parseFloat(parts[0]);
} else if (parts.length === 2) {
// Could be: label; capacity OR capacity; ir
// Check if first part starts with a letter (indicates label)
if (/^[a-zA-Z]/.test(parts[0])) {
// Format: label; capacity
label = parts[0];
capacity = parseFloat(parts[1]);
} else {
// Format: capacity; ir
capacity = parseFloat(parts[0]);
ir = parseFloat(parts[1]);
}
} else if (parts.length === 3) {
// Format: label; capacity; ir
label = parts[0];
capacity = parseFloat(parts[1]);
ir = parseFloat(parts[2]);
} else {
// Too many columns, skip
skippedCount++;
continue;
}
// Validate capacity
if (isNaN(capacity) || capacity <= 0) {
skippedCount++;
continue;
}
// Validate label if provided
if (label) {
// Must start with letter and be max 16 chars
if (!/^[a-zA-Z]/.test(label) || label.length > 16) {
skippedCount++;
continue;
}
}
// Validate IR if provided
if (ir !== null && (isNaN(ir) || ir < 0)) {
ir = null; // Invalid IR, ignore it
}
cells.push({
label: label,
capacity: capacity,
ir: ir
});
importedCount++;
}
return { cells, importedCount, skippedCount };
}
function importCells() {
const text = DOM.importTextarea.value;
if (!text.trim()) {
alert('Please paste some data to import.');
return;
}
const { cells, importedCount, skippedCount } = parseImportData(text);
if (cells.length === 0) {
alert('No valid cells found in the input. Please check the format.');
return;
}
//Remove all cells
AppState.cells = [];
AppState.cellIdCounter = 0;
DOM.cellTbody.innerHTML = '';
updateCellStats();
updateMatchingButtonState();
// Add all imported cells
cells.forEach(cell => addCell(cell));
// Show summary
let message = `Successfully imported ${importedCount} cell(s).`;
if (skippedCount > 0) {
message += `\n${skippedCount} line(s) were skipped due to invalid format.`;
}
alert(message);
closeImportDialog();
}
// =============================================================================
// Weight Sliders
// =============================================================================
@ -564,7 +695,11 @@ function setupKeyboardShortcuts() {
if (e.altKey && e.key === 'a') { e.preventDefault(); addCell(); }
if (e.altKey && e.key === 's') { e.preventDefault(); if (!DOM.btnStartMatching.disabled) startMatching(); }
if (e.altKey && e.key === 'e') { e.preventDefault(); loadExampleData(); }
if (e.key === 'Escape') { if (AppState.isRunning) stopMatching(); if (DOM.shortcutsDialog.open) DOM.shortcutsDialog.close(); }
if (e.key === 'Escape') {
if (AppState.isRunning) stopMatching();
if (DOM.shortcutsDialog.open) DOM.shortcutsDialog.close();
if (DOM.importDialog.open) closeImportDialog();
}
if (e.key === '?' && !e.target.matches('input, textarea')) { e.preventDefault(); DOM.shortcutsDialog.showModal(); }
});
}
@ -574,6 +709,7 @@ function initEventListeners() {
DOM.cellsParallel.addEventListener('input', updateConfigDisplay);
DOM.btnAddCell.addEventListener('click', () => addCell());
DOM.btnLoadExample.addEventListener('click', loadExampleData);
DOM.btnImport.addEventListener('click', openImportDialog);
DOM.btnClearAll.addEventListener('click', clearAllCells);
DOM.weightCapacity.addEventListener('input', () => updateWeights('capacity'));
DOM.weightIr.addEventListener('input', () => updateWeights('ir'));
@ -583,6 +719,8 @@ function initEventListeners() {
DOM.btnExportCsv.addEventListener('click', exportCsv);
DOM.btnCopyResults.addEventListener('click', copyResults);
DOM.btnCloseShortcuts.addEventListener('click', () => DOM.shortcutsDialog.close());
DOM.btnImportConfirm.addEventListener('click', importCells);
DOM.btnImportCancel.addEventListener('click', closeImportDialog);
}
// =============================================================================