CSV funktionert

This commit is contained in:
ChK
2026-04-05 07:51:37 +02:00
parent 74ae3f2bf8
commit d2096eca70
4 changed files with 156 additions and 2 deletions

View File

@@ -84,16 +84,107 @@ function renderResult(result) {
renderTree(treeEl, result, "result", true);
}
async function fetchCSV() {
const res = await fetch("/api/latest-snapshot");
if (!res.ok) throw new Error("Fehler beim Laden des Snapshots");
let data;
if (res.headers.get("content-type")?.includes("application/json")) {
data = await res.json();
} else {
const csvData = await res.text();
data = {
filename: "latest.csv",
mtime: new Date().toISOString(),
content: csvData
};
}
const lines = data.content.trim().split(/\r?\n/).filter(Boolean);
if (lines.length < 2) {
throw new Error("Keine oder unvollständige Daten");
}
const headers = lines[0].split(",").map(h => h.trim());
const rows = lines.slice(1).map(line => {
const cells = line.split(",");
const obj = {};
headers.forEach((h, i) => {
const raw = (cells[i] ?? "").trim();
const numeric = Number(raw);
obj[h] = raw !== "" && Number.isFinite(numeric) ? numeric : raw;
});
return obj;
});
return { data, headers, rows };
}
async function renderSnapshot() {
const table = document.getElementById("snapshot-table");
if (!table) return;
try {
const { data, headers, rows } = await fetchCSV();
// Info anzeigen
const infoEl = document.getElementById("snapshot-info");
if (infoEl) {
infoEl.textContent = `Datei: ${data.filename}, Geändert: ${new Date(data.mtime).toLocaleString()}, Zeilen: ${rows.length}`;
}
// Tabelle leeren
table.innerHTML = "";
// Header
const thead = document.createElement("thead");
const headerRow = document.createElement("tr");
headers.forEach(h => {
const th = document.createElement("th");
th.textContent = h;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
table.appendChild(thead);
// Body
const tbody = document.createElement("tbody");
rows.forEach(row => {
const tr = document.createElement("tr");
headers.forEach(h => {
const td = document.createElement("td");
let value = row[h];
if (typeof value === 'number') {
if (h === 'id' || h === 'seen_by') {
value = Math.round(value);
} else {
value = value.toFixed(1);
}
}
td.textContent = value;
tr.appendChild(td);
});
tbody.appendChild(tr);
});
table.appendChild(tbody);
} catch (err) {
console.error("Fehler beim Rendern des Snapshots:", err);
}
}
async function onCalculateClick() {
clearTextarea("analysis-log");
clearTextarea("result-json");
clearElement("result-tree");
clearElement("snapshot-table");
appendLog("Starte Berechnung...");
try {
const result = await window.calculate();
renderResult(result);
await renderSnapshot();
appendLog("Result angezeigt.");
} catch (err) {
appendLog(`Fehler: ${err.message}`);

View File

@@ -74,7 +74,13 @@
<!-- SNAPSHOT (vorbereitet, aber leer) -->
<div class="section full">
<h2>Neuester Snapshot</h2>
<h2>Snapshot CSV</h2>
<div id="snapshot-info"></div>
<table id="snapshot-table"></table>
</div>
<div class="section full">
<h2>Snapshot Image</h2>
<div id="snapshot-info"></div>
<table id="snapshot-table"></table>
</div>

View File

@@ -175,4 +175,40 @@ textarea {
#result-tree .tree-leaf {
margin-left: 18px;
white-space: pre-wrap;
}
/* ===== SNAPSHOT TABLE ===== */
#snapshot-table {
width: 100%;
border-collapse: collapse;
margin-top: 12px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
line-height: 1.2;
}
#snapshot-table th,
#snapshot-table td {
padding: 4px 8px;
text-align: left;
}
#snapshot-table th {
background: #1e293b;
color: var(--accent);
font-weight: bold;
border-bottom: 1px solid #334155;
}
#snapshot-table td {
border: none;
}
#snapshot-table tbody tr:nth-child(even) {
background: #0f172a;
}
#snapshot-table tbody tr:hover {
background: #1e293b;
}

View File

@@ -185,6 +185,10 @@ app.get('/api/events', (req, res) => {
});
});
//snapshot_video0_1775319258906_two_cam.csv
//snapshot_video0_1775319258906_two_cam_annotated.jpg
// Neuester Snapshot-Endpunkt
app.get('/api/latest-snapshot', (req, res) => {
const snapshotsDir = path.join(path.resolve('public'), 'snapshots');
@@ -197,18 +201,35 @@ app.get('/api/latest-snapshot', (req, res) => {
path: path.join(snapshotsDir, file),
mtime: fs.statSync(path.join(snapshotsDir, file)).mtime
})).sort((a, b) => b.mtime - a.mtime);
if (csvFiles.length === 0) {
return res.status(404).json({ error: 'Keine CSV-Dateien gefunden' });
}
const latestFile = csvFiles[0];
const baseName = path.basename(latestFile.name, path.extname(latestFile.name));
const imageFilename = `${baseName}_annotated.jpg`;
const imagePath = path.join(snapshotsDir, imageFilename);
fs.readFile(latestFile.path, 'utf8', (err, data) => {
if (err) {
return res.status(500).json({ error: 'Fehler beim Lesen der Datei' });
}
res.json({
const response = {
filename: latestFile.name,
mtime: latestFile.mtime.toISOString(),
content: data
};
fs.readFile(imagePath, { encoding: 'base64' }, (jpgErr, jpgBase64) => {
if (!jpgErr && jpgBase64) {
response.imageFile = {
filename: imageFilename,
mimeType: 'image/jpeg',
contentBase64: jpgBase64
};
}
res.json(response);
});
});
});