Files
2026-07-10 15:45:37 +02:00

113 lines
4.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[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 &middot; 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 &middot; Sternwarte Welzheim &middot; 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); });