CSV funktionert
This commit is contained in:
@@ -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}`);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -176,3 +176,39 @@ textarea {
|
||||
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;
|
||||
}
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user