commit 89a3fe97bf6d6b9a7293d881ef3b8ccf9fb4bdf8 Author: sascha.koenig Date: Mon May 4 09:20:44 2026 +0200 first commit diff --git a/data.json b/data.json new file mode 100644 index 0000000..a3955d1 --- /dev/null +++ b/data.json @@ -0,0 +1,531 @@ +{ + "surcharges": { + "304": { + "month": "Apr. 2026", + "value": 2663 + }, + "316": { + "month": "Apr. 2026", + "value": 4591 + }, + "444": { + "month": "Apr. 2026", + "value": 2817 + } + }, + "history": [ + { + "m": "Jan 2021", + "y": 2021, + "ss": 620, + "lz304": 1910, + "lz316": 2722, + "lz444": 1253 + }, + { + "m": "Feb 2021", + "y": 2021, + "ss": 650, + "lz304": 2064, + "lz316": 2905, + "lz444": 1366 + }, + { + "m": "Mrz 2021", + "y": 2021, + "ss": 700, + "lz304": 2222, + "lz316": 3146, + "lz444": 1480 + }, + { + "m": "Apr 2021", + "y": 2021, + "ss": 760, + "lz304": 2224, + "lz316": 3181, + "lz444": 1609 + }, + { + "m": "Mai 2021", + "y": 2021, + "ss": 810, + "lz304": 2146, + "lz316": 3054, + "lz444": 1589 + }, + { + "m": "Jun 2021", + "y": 2021, + "ss": 870, + "lz304": 2226, + "lz316": 3193, + "lz444": 1636 + }, + { + "m": "Jul 2021", + "y": 2021, + "ss": 920, + "lz304": 2281, + "lz316": 3482, + "lz444": 1868 + }, + { + "m": "Aug 2021", + "y": 2021, + "ss": 960, + "lz304": 2429, + "lz316": 3829, + "lz444": 2078 + }, + { + "m": "Sep 2021", + "y": 2021, + "ss": 1000, + "lz304": 2599, + "lz316": 4020, + "lz444": 2153 + }, + { + "m": "Okt 2021", + "y": 2021, + "ss": 1050, + "lz304": 2628, + "lz316": 4109, + "lz444": 2212 + }, + { + "m": "Nov 2021", + "y": 2021, + "ss": 1080, + "lz304": 2624, + "lz316": 4060, + "lz444": 2195 + }, + { + "m": "Dez 2021", + "y": 2021, + "ss": 1100, + "lz304": 2770, + "lz316": 4256, + "lz444": 2279 + }, + { + "m": "Jan 2022", + "y": 2022, + "ss": 1150, + "lz304": 2905, + "lz316": 4403, + "lz444": 2347 + }, + { + "m": "Feb 2022", + "y": 2022, + "ss": 1280, + "lz304": 2971, + "lz316": 4510, + "lz444": 2335 + }, + { + "m": "Mrz 2022", + "y": 2022, + "ss": 1380, + "lz304": 3192, + "lz316": 4794, + "lz444": 2347 + }, + { + "m": "Apr 2022", + "y": 2022, + "ss": 1300, + "lz304": 3899, + "lz316": 5734, + "lz444": 2516 + }, + { + "m": "Mai 2022", + "y": 2022, + "ss": 1150, + "lz304": 4614, + "lz316": 6671, + "lz444": 2761 + }, + { + "m": "Jun 2022", + "y": 2022, + "ss": 1000, + "lz304": 3852, + "lz316": 5674, + "lz444": 2810 + }, + { + "m": "Jul 2022", + "y": 2022, + "ss": 880, + "lz304": 3770, + "lz316": 5534, + "lz444": 2618 + }, + { + "m": "Aug 2022", + "y": 2022, + "ss": 820, + "lz304": 3277, + "lz316": 4916, + "lz444": 2495 + }, + { + "m": "Sep 2022", + "y": 2022, + "ss": 790, + "lz304": 3101, + "lz316": 4612, + "lz444": 2333 + }, + { + "m": "Okt 2022", + "y": 2022, + "ss": 760, + "lz304": 3174, + "lz316": 4801, + "lz444": 2465 + }, + { + "m": "Nov 2022", + "y": 2022, + "ss": 740, + "lz304": 3211, + "lz316": 5020, + "lz444": 2570 + }, + { + "m": "Dez 2022", + "y": 2022, + "ss": 715, + "lz304": 3224, + "lz316": 5076, + "lz444": 2478 + }, + { + "m": "Jan 2023", + "y": 2023, + "ss": 700, + "lz304": 3502, + "lz316": 5608, + "lz444": 2580 + }, + { + "m": "Feb 2023", + "y": 2023, + "ss": 730, + "lz304": 3587, + "lz316": 6100, + "lz444": 2939 + }, + { + "m": "Mrz 2023", + "y": 2023, + "ss": 770, + "lz304": 3484, + "lz316": 6566, + "lz444": 3499 + }, + { + "m": "Apr 2023", + "y": 2023, + "ss": 810, + "lz304": 3174, + "lz316": 6048, + "lz444": 3485 + }, + { + "m": "Mai 2023", + "y": 2023, + "ss": 855, + "lz304": 3031, + "lz316": 5048, + "lz444": 2778 + }, + { + "m": "Jun 2023", + "y": 2023, + "ss": 845, + "lz304": 3007, + "lz316": 4862, + "lz444": 2628 + }, + { + "m": "Jul 2023", + "y": 2023, + "ss": 810, + "lz304": 2858, + "lz316": 4657, + "lz444": 2640 + }, + { + "m": "Aug 2023", + "y": 2023, + "ss": 785, + "lz304": 2651, + "lz316": 4392, + "lz444": 2519 + }, + { + "m": "Sep 2023", + "y": 2023, + "ss": 755, + "lz304": 2629, + "lz316": 4465, + "lz444": 2543 + }, + { + "m": "Okt 2023", + "y": 2023, + "ss": 730, + "lz304": 2640, + "lz316": 4507, + "lz444": 2629 + }, + { + "m": "Nov 2023", + "y": 2023, + "ss": 710, + "lz304": 2573, + "lz316": 4334, + "lz444": 2599 + }, + { + "m": "Dez 2023", + "y": 2023, + "ss": 700, + "lz304": 2466, + "lz316": 4048, + "lz444": 2452 + }, + { + "m": "Jan 2024", + "y": 2024, + "ss": 730, + "lz304": 2384, + "lz316": 3793, + "lz444": 2339 + }, + { + "m": "Feb 2024", + "y": 2024, + "ss": 755, + "lz304": 2341, + "lz316": 3890, + "lz444": 2459 + }, + { + "m": "Mrz 2024", + "y": 2024, + "ss": 770, + "lz304": 2424, + "lz316": 3962, + "lz444": 2458 + }, + { + "m": "Apr 2024", + "y": 2024, + "ss": 750, + "lz304": 2543, + "lz316": 4159, + "lz444": 2461 + }, + { + "m": "Mai 2024", + "y": 2024, + "ss": 735, + "lz304": 2594, + "lz316": 4200, + "lz444": 2495 + }, + { + "m": "Jun 2024", + "y": 2024, + "ss": 715, + "lz304": 2776, + "lz316": 4505, + "lz444": 2574 + }, + { + "m": "Jul 2024", + "y": 2024, + "ss": 705, + "lz304": 2752, + "lz316": 4578, + "lz444": 2654 + }, + { + "m": "Aug 2024", + "y": 2024, + "ss": 695, + "lz304": 2547, + "lz316": 4297, + "lz444": 2651 + }, + { + "m": "Sep 2024", + "y": 2024, + "ss": 680, + "lz304": 2418, + "lz316": 4044, + "lz444": 2555 + }, + { + "m": "Okt 2024", + "y": 2024, + "ss": 670, + "lz304": 2385, + "lz316": 3989, + "lz444": 2506 + }, + { + "m": "Nov 2024", + "y": 2024, + "ss": 675, + "lz304": 2514, + "lz316": 4156, + "lz444": 2534 + }, + { + "m": "Dez 2024", + "y": 2024, + "ss": 720, + "lz304": 2477, + "lz316": 4135, + "lz444": 2623 + }, + { + "m": "Jan 2025", + "y": 2025, + "ss": 730, + "lz304": 2538, + "lz316": 4205, + "lz444": 2659 + }, + { + "m": "Feb 2025", + "y": 2025, + "ss": 730, + "lz304": 2542, + "lz316": 4226, + "lz444": 2686 + }, + { + "m": "Mrz 2025", + "y": 2025, + "ss": 720, + "lz304": 2522, + "lz316": 4181, + "lz444": 2652 + }, + { + "m": "Apr 2025", + "y": 2025, + "ss": 715, + "lz304": 2510, + "lz316": 4144, + "lz444": 2602 + }, + { + "m": "Mai 2025", + "y": 2025, + "ss": 705, + "lz304": 2382, + "lz316": 3916, + "lz444": 2502 + }, + { + "m": "Jun 2025", + "y": 2025, + "ss": 700, + "lz304": 2280, + "lz316": 3748, + "lz444": 2386 + }, + { + "m": "Jul 2025", + "y": 2025, + "ss": 695, + "lz304": 2243, + "lz316": 3751, + "lz444": 2437 + }, + { + "m": "Aug 2025", + "y": 2025, + "ss": 690, + "lz304": 2201, + "lz316": 3708, + "lz444": 2433 + }, + { + "m": "Sep 2025", + "y": 2025, + "ss": 685, + "lz304": 2260, + "lz316": 3841, + "lz444": 2510 + }, + { + "m": "Okt 2025", + "y": 2025, + "ss": 685, + "lz304": 2261, + "lz316": 3927, + "lz444": 2572 + }, + { + "m": "Nov 2025", + "y": 2025, + "ss": 692, + "lz304": 2297, + "lz316": 3936, + "lz444": 2550 + }, + { + "m": "Dez 2025", + "y": 2025, + "ss": 720, + "lz304": 2322, + "lz316": 3943, + "lz444": 2552 + }, + { + "m": "Jan 2026", + "y": 2026, + "ss": 780, + "lz304": 2303, + "lz316": 3815, + "lz444": 2478 + }, + { + "m": "Feb 2026", + "y": 2026, + "ss": null, + "lz304": 2541, + "lz316": 4179, + "lz444": 2522 + }, + { + "m": "Mrz 2026", + "y": 2026, + "ss": null, + "lz304": 2571, + "lz316": 4367, + "lz444": 2637 + }, + { + "m": "Apr 2026", + "y": 2026, + "ss": null, + "lz304": 2663, + "lz316": 4591, + "lz444": 2817 + } + ], + "baseSS": 780 +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..1e6a083 --- /dev/null +++ b/index.html @@ -0,0 +1,2607 @@ + + + + + + AZ INTEC — Precision Strip Basispreis Index + + + + + + +
+ + + diff --git a/server.js b/server.js new file mode 100644 index 0000000..620ebda --- /dev/null +++ b/server.js @@ -0,0 +1,75 @@ +const http = require('http'); +const fs = require('fs'); +const path = require('path'); + +const ROOT = __dirname; +const DATA_FILE = path.join(ROOT, 'data.json'); +const PORT = Number(process.env.PORT) || 8080; + +const TYPES = { + '.html': 'text/html; charset=utf-8', + '.js': 'text/javascript; charset=utf-8', + '.json': 'application/json; charset=utf-8', + '.css': 'text/css; charset=utf-8', + '.svg': 'image/svg+xml', +}; + +function send(res, status, body, type = 'text/plain; charset=utf-8') { + res.writeHead(status, { 'Content-Type': type }); + res.end(body); +} + +function readBody(req) { + return new Promise((resolve, reject) => { + let body = ''; + req.on('data', (chunk) => { + body += chunk; + if (body.length > 2_000_000) { + req.destroy(); + reject(new Error('Request body too large')); + } + }); + req.on('end', () => resolve(body)); + req.on('error', reject); + }); +} + +const server = http.createServer(async (req, res) => { + try { + const url = new URL(req.url, `http://${req.headers.host}`); + + if (req.method === 'POST' && url.pathname === '/api/data') { + const body = await readBody(req); + const data = JSON.parse(body); + + if (!data || typeof data !== 'object' || !data.surcharges || !Array.isArray(data.history)) { + return send(res, 400, JSON.stringify({ error: 'Invalid data format' }), 'application/json; charset=utf-8'); + } + + fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2) + '\n'); + return send(res, 200, JSON.stringify({ ok: true }), 'application/json; charset=utf-8'); + } + + if (req.method !== 'GET' && req.method !== 'HEAD') { + return send(res, 405, 'Method not allowed'); + } + + const requestPath = url.pathname === '/' ? '/index.html' : url.pathname; + const filePath = path.normalize(path.join(ROOT, requestPath)); + + if (!filePath.startsWith(ROOT)) return send(res, 403, 'Forbidden'); + if (!fs.existsSync(filePath) || !fs.statSync(filePath).isFile()) return send(res, 404, 'Not found'); + + const type = TYPES[path.extname(filePath)] || 'application/octet-stream'; + res.writeHead(200, { 'Content-Type': type }); + if (req.method === 'HEAD') return res.end(); + fs.createReadStream(filePath).pipe(res); + } catch (err) { + console.error(err); + send(res, 500, JSON.stringify({ error: err.message }), 'application/json; charset=utf-8'); + } +}); + +server.listen(PORT, () => { + console.log(`AZ INTEC Index läuft auf http://localhost:${PORT}`); +});