Files
davisfe.cz/scripts/fix_storage_levels.ts
David Fencl a67a2247c3
continuous-integration/drone/push Build encountered an error
feat: import new reservoir data, add lake management scripts, and update overview UI components
2026-06-06 20:14:36 +02:00

102 lines
3.8 KiB
TypeScript

import axios from 'axios';
import * as cheerio from 'cheerio';
import https from 'https';
import fs from 'fs';
import path from 'path';
import { lakesConfig } from './lakesConfig';
async function fixStorageLevels() {
const agent = new https.Agent({ rejectUnauthorized: false });
const updatedConfig = [...lakesConfig];
for (let i = 0; i < updatedConfig.length; i++) {
const lake = updatedConfig[i];
const parts = lake.id.split('|');
if (parts.length !== 2) continue;
const internalId = parts[0];
const oid = parts[1];
const url = `https://www.pvl.cz/portal/nadrze/cz/pc/Mereni.aspx?id=${internalId}&oid=${oid}`;
try {
const response = await axios.get(url, {
httpsAgent: agent,
headers: { 'User-Agent': 'Mozilla/5.0' }
});
const $ = cheerio.load(response.data);
let storageLevelFound: number | null = null;
let maxVol: number | null = null;
$('table').each((_, tbl) => {
const text = $(tbl).text();
// Parse storage level
if (text.includes('Hladina zásobního prostoru:')) {
$(tbl).find('tr').each((_, row) => {
const rowText = $(row).text().replace(/\\s+/g, ' ');
if (rowText.includes('Hladina zásobního prostoru:')) {
const val = parseFloat(rowText.replace('Hladina zásobního prostoru:', '').replace('[m n.m.]', '').replace(',', '.').trim());
if (!isNaN(val)) storageLevelFound = val;
}
});
}
// Parse current volume
if (text.includes('Aktuální hodnoty') && text.includes('Objem')) {
$(tbl).find('tr').each((_, row) => {
const rowText = $(row).text().replace(/\\s+/g, ' ');
if (rowText.includes('Objem [mil. m3]')) {
const valStr = $(row).find('td').eq(1).text().trim().replace(',', '.');
const val = parseFloat(valStr);
if (!isNaN(val)) maxVol = val;
}
});
}
});
if (storageLevelFound !== null) {
updatedConfig[i].storageLevel = storageLevelFound;
} else {
// if PVL doesn't have it, remove our fake guess so we fallback to maxLevel
delete updatedConfig[i].storageLevel;
}
// Fix maxVolume if current volume exceeds it
if (maxVol && updatedConfig[i].maxVolume && maxVol > updatedConfig[i].maxVolume!) {
updatedConfig[i].maxVolume = Math.ceil(maxVol * 1.05 * 10) / 10;
} else if (maxVol && !updatedConfig[i].maxVolume) {
updatedConfig[i].maxVolume = Math.ceil(maxVol * 1.05 * 10) / 10;
}
console.log(`Updated ${lake.text}: storageLevel=${storageLevelFound}, currVol=${maxVol} -> newMaxVol=${updatedConfig[i].maxVolume}`);
} catch (err: any) {
console.error(`Failed for ${lake.text}: ${err.message}`);
}
}
let newContent = `export interface LakeConfig {
id: string;
text: string;
priority?: boolean;
coords: [number, number];
maxVolume?: number;
minLevel?: number;
maxLevel?: number;
storageLevel?: number;
navigationForbidden?: boolean;
}
export const lakesConfig: LakeConfig[] = [
`;
updatedConfig.forEach((l, idx) => {
newContent += ` { id: "${l.id}", text: "${l.text}", ${l.priority ? 'priority: true, ' : ''}coords: [${l.coords[0].toFixed(4)}, ${l.coords[1].toFixed(4)}], maxVolume: ${l.maxVolume}, minLevel: ${l.minLevel}, maxLevel: ${l.maxLevel}, ${l.storageLevel ? 'storageLevel: ' + l.storageLevel + ', ' : ''}navigationForbidden: ${l.navigationForbidden} }${idx === updatedConfig.length - 1 ? '' : ','}\n`;
});
newContent += `];\n`;
fs.writeFileSync(path.resolve('./scripts/lakesConfig.ts'), newContent);
console.log("lakesConfig.ts updated with precise storage levels!");
}
fixStorageLevels();