chore: km_berechnen Tool (BEO-Entfernungen/Fahrkosten-Recherche) hinzugefügt
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
// Erzeugt eine PDF-Tabelle aller BEOs mit Wohnort und Straßenentfernung (km)
|
||||
// zur Sternwarte Welzheim — zum Versand an die BEOs zur Verifizierung.
|
||||
//
|
||||
// Daten kommen über den PHP-Proxy (cmd GET_BEOS). Das HTML wird mit Headless-
|
||||
// Chrome nach PDF gerendert.
|
||||
// node --env-file=.env erzeuge-pdf.mjs
|
||||
//
|
||||
// Ergebnis: beo-entfernungen.html und beo-entfernungen.pdf
|
||||
|
||||
import { writeFile } from 'node:fs/promises';
|
||||
import { execFile } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join } from 'node:path';
|
||||
|
||||
const execFileP = promisify(execFile);
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const HTML_FILE = join(__dirname, 'beo-entfernungen.html');
|
||||
const PDF_FILE = join(__dirname, 'beo-entfernungen.pdf');
|
||||
|
||||
const PHP_DB_URL = process.env.PHP_DB_URL || 'http://localhost:8080/DB4js_all.php';
|
||||
const CHROME = process.env.CHROME_PATH ||
|
||||
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
|
||||
|
||||
async function callProxy(cmd, params = {}) {
|
||||
const headers = { 'Content-Type': 'application/json' };
|
||||
if (process.env.API_USER && process.env.API_PASS) {
|
||||
const token = Buffer.from(`${process.env.API_USER}:${process.env.API_PASS}`).toString('base64');
|
||||
headers.Authorization = `Basic ${token}`;
|
||||
}
|
||||
const res = await fetch(PHP_DB_URL, {
|
||||
method: 'POST', headers, body: JSON.stringify({ cmd, ...params }),
|
||||
});
|
||||
const json = await res.json();
|
||||
if (json && !Array.isArray(json) && json.error) throw new Error(`DB4js ${cmd}: ${json.error}`);
|
||||
return json;
|
||||
}
|
||||
|
||||
const esc = (s) => String(s ?? '').replace(/[&<>]/g, (c) => ({ '&': '&', '<': '<', '>': '>' }[c]));
|
||||
|
||||
function fullName(r) {
|
||||
return [r.vorname, r.name].map((x) => (x || '').trim()).filter(Boolean).join(' ');
|
||||
}
|
||||
|
||||
function buildHtml(rows) {
|
||||
const stand = new Date().toLocaleDateString('de-DE', { day: '2-digit', month: 'long', year: 'numeric' });
|
||||
const body = rows.map((r, i) => `
|
||||
<tr>
|
||||
<td class="nr">${i + 1}</td>
|
||||
<td>${esc(fullName(r))}</td>
|
||||
<td>${esc(r.ort)}</td>
|
||||
<td class="km">${r.km == null || r.km === '' ? '—' : esc(r.km)}</td>
|
||||
</tr>`).join('');
|
||||
|
||||
return `<!doctype html>
|
||||
<html lang="de"><head><meta charset="utf-8"><title>BEO-Entfernungen</title>
|
||||
<style>
|
||||
@page { size: A4; margin: 18mm 16mm; }
|
||||
* { box-sizing: border-box; }
|
||||
body { font-family: -apple-system, "Helvetica Neue", Arial, sans-serif; color: #1a1a1a; font-size: 11pt; }
|
||||
h1 { font-size: 17pt; margin: 0 0 2mm; }
|
||||
.sub { color: #555; font-size: 10pt; margin: 0 0 5mm; }
|
||||
.intro { font-size: 10pt; line-height: 1.45; margin: 0 0 6mm; }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
thead th { text-align: left; font-size: 9.5pt; text-transform: uppercase; letter-spacing: .04em;
|
||||
color: #444; border-bottom: 1.5pt solid #333; padding: 2mm 2mm; }
|
||||
tbody td { padding: 1.8mm 2mm; border-bottom: 0.4pt solid #ccc; vertical-align: bottom; }
|
||||
tbody tr:nth-child(even) { background: #f6f6f6; }
|
||||
.nr { color: #999; width: 8mm; text-align: right; }
|
||||
.km { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; font-weight: 600; width: 22mm; }
|
||||
th.km { text-align: right; }
|
||||
.foot { margin-top: 7mm; font-size: 8.5pt; color: #777; }
|
||||
</style></head>
|
||||
<body>
|
||||
<h1>Entfernungen der BEOs zur Sternwarte Welzheim</h1>
|
||||
<p class="sub">Einfache Straßenentfernung in Kilometern · Stand: ${stand}</p>
|
||||
<p class="intro">
|
||||
Die folgende Tabelle listet die einfache Straßenentfernung (Auto) von deinem
|
||||
Wohnort zur Sternwarte Welzheim. Die Werte wurden automatisch über
|
||||
OpenStreetMap / OSRM ermittelt. <strong>Bitte prüfe deinen Wert und melde
|
||||
ihn in jedem Fall zurück</strong> – auch wenn er stimmt.
|
||||
</p>
|
||||
<table>
|
||||
<thead><tr>
|
||||
<th class="nr">#</th><th>Name</th><th>Wohnort</th><th class="km">km</th>
|
||||
</tr></thead>
|
||||
<tbody>${body}
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="foot">${rows.length} Beobachter · Sternwarte Welzheim · automatisch erzeugt</p>
|
||||
</body></html>`;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const rows = await callProxy('GET_BEOS', { what: 'id,vorname,name,ort,km' });
|
||||
rows.sort((a, b) => (a.name || '').localeCompare(b.name || '', 'de'));
|
||||
|
||||
const html = buildHtml(rows);
|
||||
await writeFile(HTML_FILE, html, 'utf8');
|
||||
|
||||
await execFileP(CHROME, [
|
||||
'--headless=new',
|
||||
'--disable-gpu',
|
||||
'--no-pdf-header-footer',
|
||||
`--print-to-pdf=${PDF_FILE}`,
|
||||
HTML_FILE,
|
||||
]);
|
||||
|
||||
console.log(`PDF erzeugt: ${PDF_FILE} (${rows.length} BEOs)`);
|
||||
}
|
||||
|
||||
main().catch((err) => { console.error('Fehler:', err.message); process.exit(1); });
|
||||
Reference in New Issue
Block a user