exports.id = 'getdepartures'; exports.title = 'Get departures'; exports.group = 'Worksys'; exports.color = '#5D9CEC'; exports.version = '0.0.1'; exports.output = 2; exports.input = true; exports.icon = 'cloud-upload'; const { promisifyBuilder } = require('./helper/db_helper'); exports.install = function(instance) { const URL = "https://bezpecne.sokolov.cz/zast/jedn_drogerie.csv"; //const URL = "https://bezpecne.sokolov.cz/zast/sidl_michal.csv"; const CHECK_DEPARTURES_INTERVAL = 1 * 60 * 60000; //raz za hodinu const NUMBER_OF_REQUESTS_BEFORE_LOAD_DEPARTURES_FROM_FILE = 15; const CHECK_NEW_DAY_DEPARTURES_AT = 1 // at 1 at night we check new departures let departuresFromFile = null; let departuresDB = null; let httpBody = null; let attempts = 0; let server_responded = false; async function loadDepartures() { departuresDB = TABLE("departures"); departuresFromFile = await promisifyBuilder(departuresDB.find()); departuresFromFile = departuresFromFile[0].departures; //console.log("cccc", departuresFromFile); } loadDepartures(); instance.on('close', function() { clearInterval(interval1); }) let interval1 = setInterval(getDepartures, CHECK_DEPARTURES_INTERVAL); function getDepartures() { //console.log('getDep called'); let d = new Date(); let hour = d.getHours(); if (hour === CHECK_NEW_DAY_DEPARTURES_AT) server_responded = false; if (d.getHours() === CHECK_NEW_DAY_DEPARTURES_AT || !server_responded) { attempts++; //console.log('attempts: ', attempts); const opt = { url: URL }; opt.callback = function(err, response) { if (err || response.body.includes('Rejected') || response.status === 404) { console.log('errr', err, response.body); //NOTE: if error, we try to refetch departures if (attempts < NUMBER_OF_REQUESTS_BEFORE_LOAD_DEPARTURES_FROM_FILE) { setTimeout(getDepartures, 20000); } else if (attempts === NUMBER_OF_REQUESTS_BEFORE_LOAD_DEPARTURES_FROM_FILE) { const { departures } = processBusData(departuresFromFile); console.log('odchody nacitane zo suboru'); instance.send(0, departures); } return; } attempts = 0; server_responded = true; console.log(response); httpBody = response.body; departuresDB.modify({ departures: httpBody }).callback(function(err, response) { if (err) console.log("Get_departures: error writing to departure.table", err) console.log("Departures written to db for day: ", new Date()); }); const { departures } = processBusData(httpBody); console.log(JSON.stringify(departures)); instance.send(0, departures); } REQUEST(opt); } } setTimeout(getDepartures, 5000); /** * Filters a departure array based on date masks and a specific day index. * * @param {Array>} rawDepartures - The unfiltered departure array. * @param {Object} dateMasks - An object containing date masks (e.g., {X01: "111..."}). * @param {number | null} dayIndex - The 0-based index representing the current day in the mask. * @param {boolean} isInsideDateRange - True if today's date is inside of the overall date range. * @returns {Array>} The filtered departure array. */ const filterDeparturesByDate = (rawDepartures, dateMasks, dayIndex, isInsideDateRange) => { // If today's date is not inside of the overall date range, no departures should be shown. if (!isInsideDateRange) { return []; } // If dayIndex is invalid or no date masks are provided, return the unfiltered array. // You might adjust this default behavior based on specific requirements. if (dayIndex === null || dayIndex < 0 || Object.keys(dateMasks).length === 0) { console.warn("Filtering conditions not fully met (e.g., current day not calculated or no masks). Returning unfiltered departures."); return rawDepartures; } const filtered = rawDepartures.filter(departureItem => { const kodMasky = departureItem[3]; // 'Kód datumové masky' is at index 3 const dateMask = dateMasks[kodMasky]; // Get the mask string (e.g., "111001...") // Check if the mask exists and if the dayIndex is within the mask's length if (dateMask && dayIndex < dateMask.length) { const characterForToday = dateMask[dayIndex]; return characterForToday === '1'; // Keep if the character at the current day's index is '1' } // If mask not found or dayIndex is out of bounds for a specific departure's mask, // it means this departure doesn't have valid mask data for today. // Decide default behavior: return false (discard) or true (keep). // Discarding is safer if valid mask data is required. console.warn(`Departure with mask '${kodMasky}' has invalid or missing mask data for day index ${dayIndex}. Discarding.`); return false; }); return filtered; }; /** * Processes the raw HTTP body to extract departure data, date range analysis, and date masks. * * @param {string} httpBody - The raw HTTP request body string. * @param {string | null} todayOverride - Optional. A date string (e.g., 'YYYY-MM-DD') to use as "today" for analysis. * If null, the current system date will be used. * @returns {Object} An object containing: * - departure: Filtered array of departure times. * - dateAnalysis: Analysis of the date range (start, end, days passed, etc.). * - dateMasks: An object mapping mask codes to their binary strings. */ const processBusData = (httpBody, todayOverride = null) => { // 1. Initial cleanup and splitting of the raw body const cleanedString = httpBody.startsWith('\ufeff') ? httpBody.substring(1) : httpBody; const lines = cleanedString.split('\r\n'); //console.log("*************lines", lines, lines.length, typeof lines); // --- Data structures to be populated --- const rawDepartures = []; // Collects all departures before filtering const dateMasks = {}; let dateAnalysis = { startDate: null, endDate: null, today: null, daysPassed: null, isInsideDateRange: null }; // --- Flags and counters for parsing different sections --- let captureDateMasksMode = false; let departureSectionStartIndex = -1; let foundObdobi = false; // Define "today" for calculation. const todayCalc = todayOverride ? new Date(todayOverride) : new Date(); todayCalc.setUTCHours(0, 0, 0, 0); let linka_ = null; let cas_odjezdu = null; let cilova_obec_spoje = null; let kod_datumovej_masky = null; // --- Iterate through lines to parse all sections --- for (let i = 0; i < lines.length; i++) { const line = lines[i]; const trimmedLine = line.trim(); // --- 1. Parse 'Období' (Date Range Analysis) --- if (!foundObdobi && trimmedLine.startsWith('Období;')) { const parts = trimmedLine.split(';'); if (parts.length >= 3) { const startDateStr = parts[1].trim(); const endDateStr = parts[2].trim(); const parseDateString = (dateStr) => { const [day, month, year] = dateStr.split('.'); return `${year}-${month}-${day}`; }; const parsedStartDate = new Date(parseDateString(startDateStr)); const parsedEndDate = new Date(parseDateString(endDateStr)); if (!isNaN(parsedStartDate.getTime()) && !isNaN(parsedEndDate.getTime())) { parsedStartDate.setUTCHours(0, 0, 0, 0); parsedEndDate.setUTCHours(0, 0, 0, 0); const millisecondsPerDay = 1000 * 60 * 60 * 24; const timeDifference = todayCalc.getTime() - parsedStartDate.getTime(); const daysPassed = Math.floor(timeDifference / millisecondsPerDay); const isInsideDateRange = todayCalc <= parsedEndDate && todayCalc >= parsedStartDate; console.log("is in date range? ", isInsideDateRange); dateAnalysis = { startDate: parsedStartDate.toLocaleDateString('en-GB'), endDate: parsedEndDate.toLocaleDateString('en-GB'), today: todayCalc.toLocaleDateString('en-GB'), daysPassed: daysPassed >= 0 ? daysPassed : 0, isInsideDateRange: isInsideDateRange }; foundObdobi = true; } else { console.error("Warning: Could not parse valid start and/or end dates from 'Období' field."); } } } // --- 2. Parse Date Masks --- if (trimmedLine.includes("Kód datumové masky;Datumová maska")) { captureDateMasksMode = true; continue; } if (captureDateMasksMode && !trimmedLine) { captureDateMasksMode = false; continue; } if (captureDateMasksMode) { const columns = trimmedLine.split(';'); if (columns.length >= 2) { const code = columns[0].trim(); const mask = columns[1].trim(); if (code && mask) { dateMasks[code] = mask; } } } // --- 3. Find Start of Departure Data --- if (trimmedLine.includes("Linka") && trimmedLine.includes("Čas odjezdu") && trimmedLine.includes('Cílová obec spoje') && trimmedLine.includes('Kód datumové masky')) { let structure = trimmedLine.split(";"); linka_ = structure.indexOf("Linka"); cas_odjezdu = structure.indexOf("Čas odjezdu"); cilova_obec_spoje = structure.indexOf("Cílová obec spoje"); kod_datumovej_masky = structure.indexOf("Kód datumové masky"); if (linka_ == -1 || cas_odjezdu == -1 || cilova_obec_spoje == -1 || kod_datumovej_masky == -1) { console.log("subor odchodov neobsahuje pozadovane udaje"); linka_ = 0; cas_odjezdu = 2; cilova_obec_spoje = 4; kod_datumovej_masky = 5; } departureSectionStartIndex = i + 1; continue; } // --- 4. Parse Raw Departure Data --- if (departureSectionStartIndex !== -1 && i >= departureSectionStartIndex) { if (!trimmedLine) { continue; } const columns = trimmedLine.split(';'); if (columns.length >= 6 && columns[0].trim() !== '') { //const linka = parseInt(columns[0].trim(), 10); //let casOdjezdu = columns[2].trim(); //if (casOdjezdu.length === 4) casOdjezdu = "0" + casOdjezdu; //let cilovaObecSpoje = columns[4].trim(); //const kodDatumoveMasky = columns[5].trim(); //cilovaObecSpoje = cilovaObecSpoje.replace(/,,/g, ', '); const linka = parseInt(columns[linka_].trim(), 10); let casOdjezdu = columns[cas_odjezdu].trim(); if (casOdjezdu.length === 4) casOdjezdu = "0" + casOdjezdu; let cilovaObecSpoje = columns[cilova_obec_spoje].trim(); const kodDatumoveMasky = columns[kod_datumovej_masky].trim(); cilovaObecSpoje = cilovaObecSpoje.replace(/,,/g, ', '); if (!isNaN(linka)) { rawDepartures.push([ linka, casOdjezdu, cilovaObecSpoje, kodDatumoveMasky ]); } } } } // --- Final Step: Filter the departures using the new function --- const finalDepartures = filterDeparturesByDate( rawDepartures, dateMasks, dateAnalysis.daysPassed, dateAnalysis.isInsideDateRange ); // console.log('aaaaaaa', JSON.stringify(rawDepartures)); // console.log('aaaFINALaaaa', JSON.stringify(finalDepartures)); return { departures: finalDepartures, // Now 'departures' holds the filtered array rawDepartures: rawDepartures, dateAnalysis: dateAnalysis, dateMasks: dateMasks }; }; //184 total let allDepartures = [[3, "4:09", "Sokolov, Závodu míru", "X01"], [3, "4:24", "Sokolov, Závodu míru", "X02"], [1, "4:50", "Březová, aut.st.", "X02"], [3, "4:52", "Sokolov, Závodu míru", "X02"], [3, "4:56", "Sokolov, Závodu míru", "X03"], [3, "5:02", "Sokolov, Závodu míru", "X02"], [4, "5:05", "Sokolov, Závodu míru", "X02"], [6, "5:07", "Sokolov, sídl.Michal škola", "X04"], [6, "5:07", "Sokolov, Závodu míru", "X05"], [3, "5:09", "Sokolov, Závodu míru", "X04"], [3, "5:22", "Sokolov, Závodu míru", "X02"], [1, "5:23", "Březová, aut.st.", "X02"], [3, "5:31", "Sokolov, sídl.Michal škola", "X04"], [6, "5:34", "Sokolov, sídl.Michal škola", "X04"], [4, "5:37", "Sokolov,Stará ovčárna", "X02"], [3, "5:40", "Sokolov, sídl.Michal", "X05"], [1, "5:47", "Březová, aut.st.", "X03"], [1, "5:51", "Březová, aut.st.", "X02"], [3, "5:57", "Sokolov, Závodu míru", "X03"], [6, "5:59", "Sokolov, sídl.Michal škola", "X04"], [3, "6:00", "Sokolov, Závodu míru", "X02"], [1, "6:13", "Březová, aut.st.", "X02"], [3, "6:16", "Sokolov, Závodu míru", "X04"], [3, "6:19", "Sokolov, Závodu míru", "X05"], [3, "6:24", "Sokolov, sídl.Michal", "X02"], [3, "6:24", "Sokolov, Závodu míru", "X03"], [6, "6:27", "Sokolov, sídl.Michal škola", "X05"], [6, "6:29", "Sokolov, sídl.Michal škola", "X04"], [4, "6:31", "Sokolov, Závodu míru", "X04"], [3, "6:39", "Sokolov, Závodu míru", "X02"], [1, "6:46", "Březová, aut.st.", "X02"], [33, "6:49", "Sokolov, sídl.Michal škola", "X04"], [3, "6:56", "Sokolov,Hrušková", "X04"], [3, "6:56", "Sokolov, Závodu míru", "X06"], [3, "6:59", "Sokolov, Závodu míru", "X02"], [1, "7:01", "Březová, aut.st.", "X03"], [1, "7:05", "Březová, aut.st.", "X02"], [3, "7:19", "Sokolov, Závodu míru", "X01"], [6, "7:23", "Sokolov, sídl.Michal škola", "X04"], [3, "7:27", "Sokolov, sídl.Michal", "X05"], [2, "7:31", "Sokolov, sídl.Michal", "X04"], [3, "7:34", "Sokolov, Závodu míru", "X04"], [4, "7:34", "Sokolov, Závodu míru", "X02"], [1, "7:35", "Březová, aut.st.", "X02"], [3, "7:45", "Sokolov, sídl.Michal", "X02"], [3, "7:51", "Sokolov, Závodu míru", "X03"], [1, "7:55", "Březová, aut.st.", "X02"], [1, "7:57", "Březová, aut.st.", "X03"], [3, "7:58", "Sokolov, Závodu míru", "X04"], [33, "8:01", "Sokolov, sídl.Michal škola", "X04"], [3, "8:13", "Sokolov, Závodu míru", "X05"], [3, "8:15", "Sokolov, Závodu míru", "X07"], [1, "8:18", "Březová, aut.st.", "X02"], [33, "8:29", "Sokolov, sídl.Michal škola", "X02"], [3, "8:34", "Sokolov, Závodu míru", "X02"], [3, "8:50", "Sokolov,Stará ovčárna", "X02"], [3, "8:51", "Sokolov, Závodu míru", "X03"], [33, "8:54", "Sokolov, sídl.Michal škola", "X02"], [1, "8:57", "Březová, aut.st.", "X03"], [3, "9:04", "Sokolov, Závodu míru", "X02"], [1, "9:09", "Březová, aut.st.", "X02"], [3, "9:20", "Sokolov, Závodu míru", "X03"], [3, "9:24", "Sokolov, Závodu míru", "X02"], [33, "9:34", "Sokolov, sídl.Michal škola", "X02"], [4, "9:41", "Sokolov, sídl.Michal", "X02"], [1, "9:44", "Březová, aut.st.", "X03"], [3, "9:45", "Sokolov, Závodu míru", "X02"], [3, "9:51", "Sokolov, Závodu míru", "X03"], [1, "9:58", "Březová, aut.st.", "X02"], [3, "9:59", "Sokolov, Závodu míru", "X02"], [7, "10:14", "Březová, aut.st.", "X02"], [3, "10:19", "Sokolov, Závodu míru", "X03"], [33, "10:24", "Sokolov, sídl.Michal škola", "X02"], [3, "10:40", "Sokolov, Závodu míru", "X02"], [1, "10:55", "Březová, aut.st.", "X02"], [3, "10:55", "Sokolov, Závodu míru", "X02"], [1, "10:57", "Březová, aut.st.", "X03"], [3, "11:02", "Sokolov, Závodu míru", "X03"], [3, "11:17", "Sokolov, Závodu míru", "X02"], [3, "11:29", "Sokolov, Závodu míru", "X03"], [33, "11:29", "Sokolov, sídl.Michal škola", "X02"], [3, "11:44", "Sokolov, Závodu míru", "X02"], [1, "11:46", "Březová, aut.st.", "X02"], [1, "11:49", "Březová, aut.st.", "X03"], [3, "11:51", "Sokolov, Závodu míru", "X03"], [33, "11:56", "Sokolov, sídl.Michal škola", "X02"], [3, "12:07", "Sokolov, Závodu míru", "X02"], [3, "12:19", "Sokolov, Závodu míru", "X03"], [3, "12:24", "Sokolov, Závodu míru", "X02"], [1, "12:33", "Březová, aut.st.", "X02"], [3, "12:44", "Sokolov, Závodu míru", "X02"], [3, "12:51", "Sokolov, Závodu míru", "X03"], [1, "12:57", "Březová, aut.st.", "X03"], [3, "12:59", "Sokolov, Závodu míru", "X02"], [6, "12:59", "Sokolov, sídl.Michal škola", "X04"], [33, "13:04", "Sokolov, sídl.Michal škola", "X02"], [1, "13:06", "Březová, aut.st.", "X02"], [3, "13:15", "Sokolov, Závodu míru", "X02"], [2, "13:17", "Sokolov, sídl.Michal", "X02"], [1, "13:22", "Březová, aut.st.", "X02"], [3, "13:24", "Sokolov,Stará ovčárna", "X02"], [3, "13:28", "Sokolov, Závodu míru", "X03"], [33, "13:34", "Sokolov, sídl.Michal škola", "X02"], [1, "13:48", "Březová, aut.st.", "X02"], [3, "13:51", "Sokolov, Závodu míru", "X03"], [1, "13:59", "Březová, aut.st.", "X03"], [6, "13:59", "Sokolov, sídl.Michal škola", "X02"], [33, "14:04", "Sokolov, sídl.Michal škola", "X02"], [4, "14:06", "Sokolov,Stará ovčárna", "X02"], [3, "14:09", "Sokolov, Závodu míru", "X02"], [1, "14:10", "Březová, aut.st.", "X02"], [3, "14:19", "Sokolov, Závodu míru", "X03"], [3, "14:21", "Sokolov, Závodu míru", "X02"], [1, "14:34", "Březová, aut.st.", "X02"], [6, "14:34", "Sokolov, sídl.Michal škola", "X02"], [4, "14:42", "Sokolov, Závodu míru", "X02"], [3, "14:43", "Sokolov, Závodu míru", "X02"], [33, "14:46", "Sokolov, sídl.Michal škola", "X02"], [1, "14:51", "Březová, aut.st.", "X03"], [3, "14:51", "Sokolov, Závodu míru", "X03"], [3, "14:52", "Sokolov, Závodu míru", "X02"], [1, "15:09", "Březová, aut.st.", "X02"], [33, "15:09", "Sokolov, sídl.Michal škola", "X02"], [3, "15:13", "Sokolov, Závodu míru", "X02"], [6, "15:14", "Sokolov, sídl.Michal škola", "X02"], [3, "15:20", "Sokolov, Závodu míru", "X03"], [3, "15:26", "Sokolov,Hrušková", "X04"], [1, "15:31", "Březová, aut.st.", "X02"], [3, "15:34", "Sokolov, Závodu míru", "X02"], [3, "15:39", "Sokolov, Závodu míru", "X02"], [33, "15:39", "Sokolov, sídl.Michal škola", "X02"], [3, "15:51", "Sokolov, Závodu míru", "X03"], [7, "15:54", "Březová, aut.st.", "X02"], [1, "15:57", "Březová, aut.st.", "X03"], [3, "16:00", "Sokolov, sídl.Michal škola", "X04"], [4, "16:08", "Sokolov, Závodu míru", "X02"], [3, "16:14", "Sokolov, Závodu míru", "X02"], [33, "16:16", "Sokolov, sídl.Michal škola", "X02"], [1, "16:21", "Březová, aut.st.", "X02"], [3, "16:28", "Sokolov, Závodu míru", "X03"], [7, "16:29", "Březová, aut.st.", "X02"], [3, "16:37", "Sokolov, Závodu míru", "X02"], [6, "16:44", "Sokolov, sídl.Michal škola", "X04"], [3, "16:48", "Sokolov, Závodu míru", "X02"], [3, "16:50", "Sokolov, Závodu míru", "X03"], [4, "16:51", "Sokolov, Závodu míru", "X04"], [1, "16:57", "Březová, aut.st.", "X03"], [7, "16:59", "Březová, aut.st.", "X02"], [3, "17:12", "Sokolov,Stará ovčárna", "X02"], [3, "17:17", "Sokolov, Závodu míru", "X03"], [3, "17:18", "Sokolov, Závodu míru", "X02"], [3, "17:34", "Sokolov, Závodu míru", "X02"], [1, "17:38", "Březová, aut.st.", "X02"], [3, "17:51", "Sokolov, Závodu míru", "X03"], [3, "17:57", "Sokolov, Závodu míru", "X02"], [3, "18:14", "Sokolov, Závodu míru", "X02"], [3, "18:21", "Sokolov, Závodu míru", "X02"], [3, "18:21", "Sokolov,Stará ovčárna", "X03"], [1, "18:24", "Březová, aut.st.", "X03"], [1, "18:26", "Březová, aut.st.", "X02"], [3, "18:34", "Sokolov, Závodu míru", "X02"], [3, "18:51", "Sokolov, Závodu míru", "X03"], [3, "18:54", "Sokolov, Závodu míru", "X02"], [1, "19:08", "Březová, aut.st.", "X02"], [3, "19:14", "Sokolov, Závodu míru", "X03"], [3, "19:19", "Sokolov, Závodu míru", "X02"], [3, "19:34", "Sokolov, Závodu míru", "X02"], [1, "19:53", "Březová, aut.st.", "X02"], [3, "19:54", "Sokolov, Závodu míru", "X03"], [3, "19:56", "Sokolov, Závodu míru", "X02"], [1, "19:57", "Březová, aut.st.", "X03"], [3, "20:19", "Sokolov, Závodu míru", "X02"], [1, "20:28", "Březová, aut.st.", "X03"], [3, "20:49", "Sokolov, Závodu míru", "X01"], [1, "20:55", "Březová, aut.st.", "X02"], [3, "21:09", "Sokolov, Závodu míru", "X02"], [1, "21:23", "Březová, aut.st.", "X03"], [3, "21:24", "Sokolov,Stará ovčárna", "X02"], [3, "21:27", "Sokolov, Závodu míru", "X03"], [1, "21:38", "Březová, aut.st.", "X02"], [3, "22:05", "Sokolov, Závodu míru", "X03"], [3, "22:12", "Sokolov,Stará ovčárna", "X02"], [1, "22:28", "Březová, aut.st.", "X02"], [3, "22:41", "Sokolov, Závodu míru", "X02"]]; let httpBody1 = { body: 'Sloupec1;Sloupec2;Sloupec3;Sloupec4;Sloupec5;Sloupec7\r\n' + 'Export odjezdů ze dne;22.04.2025;08:32;;;\r\n' + 'Zastávka;Sokolov,,ul.Jednoty drogerie;;;;\r\n' + 'Období;24.03.2025;31.05.2025;;;\r\n' + ';;;;;\r\n' + 'Kód datumové masky;Datumová maska;;;;\r\n' + 'X01;111111111111111111111111111111111111111111111111111111111111111111111;;;;\r\n' + 'X02;111110011111001111100111100001111001110100111010011111001111100111110;;;;\r\n' + 'X03;000001100000110000011000011110000110001011000101100000110000011000001;;;;\r\n' + 'X04;111110011111001111100111000001111001110100111010011111001111100111110;;;;\r\n' + 'X05;000000000000000000000000100000000000000000000000000000000000000000000;;;;\r\n' + 'X06;000001100000110000011000111110000110001011000101100000110000011000001;;;;\r\n' + 'X07;111111111111111111111111011111111111111111111111111111111111111111111;;;;\r\n' + ';;;;;\r\n' + 'Linka;Spoj;Čas odjezdu;Nástupiště;Cílová obec spoje;Kód datumové masky\r\n' + '3;;4:09;;Sokolov,,Závodu míru;X01\r\n' + '3;;4:24;;Sokolov,,Závodu míru;X02\r\n' + '1;;4:50;;Březová,,aut.st.;X02\r\n' + '3;;4:52;;Sokolov,,Závodu míru;X02\r\n' + '3;;4:56;;Sokolov,,Závodu míru;X03\r\n' + '3;;5:02;;Sokolov,,Závodu míru;X02\r\n' + '4;;5:05;;Sokolov,,Závodu míru;X02\r\n' + '6;;5:07;;Sokolov,,sídl.Michal škola;X04\r\n' + '6;;5:07;;Sokolov,,Závodu míru;X05\r\n' + '3;;5:09;;Sokolov,,Závodu míru;X04\r\n' + '3;;5:22;;Sokolov,,Závodu míru;X02\r\n' + '1;;5:23;;Březová,,aut.st.;X02\r\n' + '3;;5:31;;Sokolov,,sídl.Michal škola;X04\r\n' + '6;;5:34;;Sokolov,,sídl.Michal škola;X04\r\n' + '4;;5:37;;Sokolov,Stará ovčárna;X02\r\n' + '3;;5:40;;Sokolov,,sídl.Michal;X05\r\n' + '1;;5:47;;Březová,,aut.st.;X03\r\n' + '1;;5:51;;Březová,,aut.st.;X02\r\n' + '3;;5:57;;Sokolov,,Závodu míru;X03\r\n' + '6;;5:59;;Sokolov,,sídl.Michal škola;X04\r\n' + '3;;6:00;;Sokolov,,Závodu míru;X02\r\n' + '1;;6:13;;Březová,,aut.st.;X02\r\n' + '3;;6:16;;Sokolov,,Závodu míru;X04\r\n' + '3;;6:19;;Sokolov,,Závodu míru;X05\r\n' + '3;;6:24;;Sokolov,,sídl.Michal;X02\r\n' + '3;;6:24;;Sokolov,,Závodu míru;X03\r\n' + '6;;6:27;;Sokolov,,sídl.Michal škola;X05\r\n' + '6;;6:29;;Sokolov,,sídl.Michal škola;X04\r\n' + '4;;6:31;;Sokolov,,Závodu míru;X04\r\n' + '3;;6:39;;Sokolov,,Závodu míru;X02\r\n' + '1;;6:46;;Březová,,aut.st.;X02\r\n' + '33;;6:49;;Sokolov,,sídl.Michal škola;X04\r\n' + '3;;6:56;;Sokolov,Hrušková;X04\r\n' + '3;;6:56;;Sokolov,,Závodu míru;X06\r\n' + '3;;6:59;;Sokolov,,Závodu míru;X02\r\n' + '1;;7:01;;Březová,,aut.st.;X03\r\n' + '1;;7:05;;Březová,,aut.st.;X02\r\n' + '3;;7:19;;Sokolov,,Závodu míru;X01\r\n' + '6;;7:23;;Sokolov,,sídl.Michal škola;X04\r\n' + '3;;7:27;;Sokolov,,sídl.Michal;X05\r\n' + '2;;7:31;;Sokolov,,sídl.Michal;X04\r\n' + '3;;7:34;;Sokolov,,Závodu míru;X04\r\n' + '4;;7:34;;Sokolov,,Závodu míru;X02\r\n' + '1;;7:35;;Březová,,aut.st.;X02\r\n' + '3;;7:45;;Sokolov,,sídl.Michal;X02\r\n' + '3;;7:51;;Sokolov,,Závodu míru;X03\r\n' + '1;;7:55;;Březová,,aut.st.;X02\r\n' + '1;;7:57;;Březová,,aut.st.;X03\r\n' + '3;;7:58;;Sokolov,,Závodu míru;X04\r\n' + '33;;8:01;;Sokolov,,sídl.Michal škola;X04\r\n' + '3;;8:13;;Sokolov,,Závodu míru;X05\r\n' + '3;;8:15;;Sokolov,,Závodu míru;X07\r\n' + '1;;8:18;;Březová,,aut.st.;X02\r\n' + '33;;8:29;;Sokolov,,sídl.Michal škola;X02\r\n' + '3;;8:34;;Sokolov,,Závodu míru;X02\r\n' + '3;;8:50;;Sokolov,Stará ovčárna;X02\r\n' + '3;;8:51;;Sokolov,,Závodu míru;X03\r\n' + '33;;8:54;;Sokolov,,sídl.Michal škola;X02\r\n' + '1;;8:57;;Březová,,aut.st.;X03\r\n' + '3;;9:04;;Sokolov,,Závodu míru;X02\r\n' + '1;;9:09;;Březová,,aut.st.;X02\r\n' + '3;;9:20;;Sokolov,,Závodu míru;X03\r\n' + '3;;9:24;;Sokolov,,Závodu míru;X02\r\n' + '33;;9:34;;Sokolov,,sídl.Michal škola;X02\r\n' + '4;;9:41;;Sokolov,,sídl.Michal;X02\r\n' + '1;;9:44;;Březová,,aut.st.;X03\r\n' + '3;;9:45;;Sokolov,,Závodu míru;X02\r\n' + '3;;9:51;;Sokolov,,Závodu míru;X03\r\n' + '1;;9:58;;Březová,,aut.st.;X02\r\n' + '3;;9:59;;Sokolov,,Závodu míru;X02\r\n' + '7;;10:14;;Březová,,aut.st.;X02\r\n' + '3;;10:19;;Sokolov,,Závodu míru;X03\r\n' + '33;;10:24;;Sokolov,,sídl.Michal škola;X02\r\n' + '3;;10:40;;Sokolov,,Závodu míru;X02\r\n' + '1;;10:55;;Březová,,aut.st.;X02\r\n' + '3;;10:55;;Sokolov,,Závodu míru;X02\r\n' + '1;;10:57;;Březová,,aut.st.;X03\r\n' + '3;;11:02;;Sokolov,,Závodu míru;X03\r\n' + '3;;11:17;;Sokolov,,Závodu míru;X02\r\n' + '3;;11:29;;Sokolov,,Závodu míru;X03\r\n' + '33;;11:29;;Sokolov,,sídl.Michal škola;X02\r\n' + '3;;11:44;;Sokolov,,Závodu míru;X02\r\n' + '1;;11:46;;Březová,,aut.st.;X02\r\n' + '1;;11:49;;Březová,,aut.st.;X03\r\n' + '3;;11:51;;Sokolov,,Závodu míru;X03\r\n' + '33;;11:56;;Sokolov,,sídl.Michal škola;X02\r\n' + '3;;12:07;;Sokolov,,Závodu míru;X02\r\n' + '3;;12:19;;Sokolov,,Závodu míru;X03\r\n' + '3;;12:24;;Sokolov,,Závodu míru;X02\r\n' + '1;;12:33;;Březová,,aut.st.;X02\r\n' + '3;;12:44;;Sokolov,,Závodu míru;X02\r\n' + '3;;12:51;;Sokolov,,Závodu míru;X03\r\n' + '1;;12:57;;Březová,,aut.st.;X03\r\n' + '3;;12:59;;Sokolov,,Závodu míru;X02\r\n' + '6;;12:59;;Sokolov,,sídl.Michal škola;X04\r\n' + '33;;13:04;;Sokolov,,sídl.Michal škola;X02\r\n' + '1;;13:06;;Březová,,aut.st.;X02\r\n' + '3;;13:15;;Sokolov,,Závodu míru;X02\r\n' + '2;;13:17;;Sokolov,,sídl.Michal;X02\r\n' + '1;;13:22;;Březová,,aut.st.;X02\r\n' + '3;;13:24;;Sokolov,Stará ovčárna;X02\r\n' + '3;;13:28;;Sokolov,,Závodu míru;X03\r\n' + '33;;13:34;;Sokolov,,sídl.Michal škola;X02\r\n' + '1;;13:48;;Březová,,aut.st.;X02\r\n' + '3;;13:51;;Sokolov,,Závodu míru;X03\r\n' + '1;;13:59;;Březová,,aut.st.;X03\r\n' + '6;;13:59;;Sokolov,,sídl.Michal škola;X02\r\n' + '33;;14:04;;Sokolov,,sídl.Michal škola;X02\r\n' + '4;;14:06;;Sokolov,Stará ovčárna;X02\r\n' + '3;;14:09;;Sokolov,,Závodu míru;X02\r\n' + '1;;14:10;;Březová,,aut.st.;X02\r\n' + '3;;14:19;;Sokolov,,Závodu míru;X03\r\n' + '3;;14:21;;Sokolov,,Závodu míru;X02\r\n' + '1;;14:34;;Březová,,aut.st.;X02\r\n' + '6;;14:34;;Sokolov,,sídl.Michal škola;X02\r\n' + '4;;14:42;;Sokolov,,Závodu míru;X02\r\n' + '3;;14:43;;Sokolov,,Závodu míru;X02\r\n' + '33;;14:46;;Sokolov,,sídl.Michal škola;X02\r\n' + '1;;14:51;;Březová,,aut.st.;X03\r\n' + '3;;14:51;;Sokolov,,Závodu míru;X03\r\n' + '3;;14:52;;Sokolov,,Závodu míru;X02\r\n' + '1;;15:09;;Březová,,aut.st.;X02\r\n' + '33;;15:09;;Sokolov,,sídl.Michal škola;X02\r\n' + '3;;15:13;;Sokolov,,Závodu míru;X02\r\n' + '6;;15:14;;Sokolov,,sídl.Michal škola;X02\r\n' + '3;;15:20;;Sokolov,,Závodu míru;X03\r\n' + '3;;15:26;;Sokolov,Hrušková;X04\r\n' + '1;;15:31;;Březová,,aut.st.;X02\r\n' + '3;;15:34;;Sokolov,,Závodu míru;X02\r\n' + '3;;15:39;;Sokolov,,Závodu míru;X02\r\n' + '33;;15:39;;Sokolov,,sídl.Michal škola;X02\r\n' + '3;;15:51;;Sokolov,,Závodu míru;X03\r\n' + '7;;15:54;;Březová,,aut.st.;X02\r\n' + '1;;15:57;;Březová,,aut.st.;X03\r\n' + '3;;16:00;;Sokolov,,sídl.Michal škola;X04\r\n' + '4;;16:08;;Sokolov,,Závodu míru;X02\r\n' + '3;;16:14;;Sokolov,,Závodu míru;X02\r\n' + '33;;16:16;;Sokolov,,sídl.Michal škola;X02\r\n' + '1;;16:21;;Březová,,aut.st.;X02\r\n' + '3;;16:28;;Sokolov,,Závodu míru;X03\r\n' + '7;;16:29;;Březová,,aut.st.;X02\r\n' + '3;;16:37;;Sokolov,,Závodu míru;X02\r\n' + '6;;16:44;;Sokolov,,sídl.Michal škola;X04\r\n' + '3;;16:48;;Sokolov,,Závodu míru;X02\r\n' + '3;;16:50;;Sokolov,,Závodu míru;X03\r\n' + '4;;16:51;;Sokolov,,Závodu míru;X04\r\n' + '1;;16:57;;Březová,,aut.st.;X03\r\n' + '7;;16:59;;Březová,,aut.st.;X02\r\n' + '3;;17:12;;Sokolov,Stará ovčárna;X02\r\n' + '3;;17:17;;Sokolov,,Závodu míru;X03\r\n' + '3;;17:18;;Sokolov,,Závodu míru;X02\r\n' + '3;;17:34;;Sokolov,,Závodu míru;X02\r\n' + '1;;17:38;;Březová,,aut.st.;X02\r\n' + '3;;17:51;;Sokolov,,Závodu míru;X03\r\n' + '3;;17:57;;Sokolov,,Závodu míru;X02\r\n' + '3;;18:14;;Sokolov,,Závodu míru;X02\r\n' + '3;;18:21;;Sokolov,,Závodu míru;X02\r\n' + '3;;18:21;;Sokolov,Stará ovčárna;X03\r\n' + '1;;18:24;;Březová,,aut.st.;X03\r\n' + '1;;18:26;;Březová,,aut.st.;X02\r\n' + '3;;18:34;;Sokolov,,Závodu míru;X02\r\n' + '3;;18:51;;Sokolov,,Závodu míru;X03\r\n' + '3;;18:54;;Sokolov,,Závodu míru;X02\r\n' + '1;;19:08;;Březová,,aut.st.;X02\r\n' + '3;;19:14;;Sokolov,,Závodu míru;X03\r\n' + '3;;19:19;;Sokolov,,Závodu míru;X02\r\n' + '3;;19:34;;Sokolov,,Závodu míru;X02\r\n' + '1;;19:53;;Březová,,aut.st.;X02\r\n' + '3;;19:54;;Sokolov,,Závodu míru;X03\r\n' + '3;;19:56;;Sokolov,,Závodu míru;X02\r\n' + '1;;19:57;;Březová,,aut.st.;X03\r\n' + '3;;20:19;;Sokolov,,Závodu míru;X02\r\n' + '1;;20:28;;Březová,,aut.st.;X03\r\n' + '3;;20:49;;Sokolov,,Závodu míru;X01\r\n' + '1;;20:55;;Březová,,aut.st.;X02\r\n' + '3;;21:09;;Sokolov,,Závodu míru;X02\r\n' + '1;;21:23;;Březová,,aut.st.;X03\r\n' + '3;;21:24;;Sokolov,Stará ovčárna;X02\r\n' + '3;;21:27;;Sokolov,,Závodu míru;X03\r\n' + '1;;21:38;;Březová,,aut.st.;X02\r\n' + '3;;22:05;;Sokolov,,Závodu míru;X03\r\n' + '3;;22:12;;Sokolov,Stará ovčárna;X02\r\n' + '1;;22:28;;Březová,,aut.st.;X02\r\n' + '3;;22:41;;Sokolov,,Závodu míru;X02\r\n', origin: undefined, headers: { 'content-type': 'application/octet-stream', 'last-modified': 'Mon, 05 May 2025 06:17:00 GMT', 'accept-ranges': 'bytes', etag: '"056854f85bddb1:0"', date: 'Tue, 27 May 2025 08:03:15 GMT', connection: 'close', 'content-length': '7779', 'set-cookie': [ 'TS01a3e872=013429363de6e56879fa8c0bcc9065ad2fef2ca60e8eea9a5cc44bd80858a4f8586e2d59ae6d8cf9c6126d3b4d2d9738c850914be7; Path=/; Domain=.bezpecne.sokolov.cz;' ], 'strict-transport-security': 'max-age=31536000; includeSubdomains; preload', 'content-security-policy': 'block-all-mixed-content; upgrade-insecure-requests', 'referrer-policy': 'no-referrer-when-downgrade', 'permissions-policy': 'accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=()', 'x-frame-options': 'SAMEORIGIN', 'x-xss-protection': '1; mode=block', 'access-control-allow-origin': '*' }, status: 200, host: 'bezpecne.sokolov.cz', cookies: undefined } const departures1 = [ [3, "4:09", "Sokolov, Závodu míru", "X01"], [3, "4:24", "Sokolov, Závodu míru", "X02"], [1, "4:50", "Březová, aut.st.", "X02"], [3, "4:52", "Sokolov, Závodu míru", "X02"], [3, "4:56", "Sokolov, Závodu míru", "X03"], [3, "5:02", "Sokolov, Závodu míru", "X02"], [4, "5:05", "Sokolov, Závodu míru", "X02"], [6, "5:07", "Sokolov, sídl.Michal škola", "X04"], [6, "5:07", "Sokolov, Závodu míru", "X05"], [3, "5:09", "Sokolov, Závodu míru", "X04"], [3, "5:22", "Sokolov, Závodu míru", "X02"], [1, "5:23", "Březová, aut.st.", "X02"], [3, "5:31", "Sokolov, sídl.Michal škola", "X04"], [6, "5:34", "Sokolov, sídl.Michal škola", "X04"], [4, "5:37", "Sokolov,Stará ovčárna", "X02"], [3, "5:40", "Sokolov, sídl.Michal", "X05"], [1, "5:47", "Březová, aut.st.", "X03"], [1, "5:51", "Březová, aut.st.", "X02"], [3, "5:57", "Sokolov, Závodu míru", "X03"], [6, "5:59", "Sokolov, sídl.Michal škola", "X04"], [3, "6:00", "Sokolov, Závodu míru", "X02"], [1, "6:13", "Březová, aut.st.", "X02"], [3, "6:16", "Sokolov, Závodu míru", "X04"], [3, "6:19", "Sokolov, Závodu míru", "X05"], [3, "6:24", "Sokolov, sídl.Michal", "X02"], [3, "6:24", "Sokolov, Závodu míru", "X03"], [6, "6:27", "Sokolov, sídl.Michal škola", "X05"], [6, "6:29", "Sokolov, sídl.Michal škola", "X04"], [4, "6:31", "Sokolov, Závodu míru", "X04"], [3, "6:39", "Sokolov, Závodu míru", "X02"], [1, "6:46", "Březová, aut.st.", "X02"], [33, "6:49", "Sokolov, sídl.Michal škola", "X04"], [3, "6:56", "Sokolov,Hrušková", "X04"], [3, "6:56", "Sokolov, Závodu míru", "X06"], [3, "6:59", "Sokolov, Závodu míru", "X02"], [1, "7:01", "Březová, aut.st.", "X03"], [1, "7:05", "Březová, aut.st.", "X02"], [3, "7:19", "Sokolov, Závodu míru", "X01"], [6, "7:23", "Sokolov, sídl.Michal škola", "X04"], [3, "7:27", "Sokolov, sídl.Michal", "X05"], [2, "7:31", "Sokolov, sídl.Michal", "X04"], [3, "7:34", "Sokolov, Závodu míru", "X04"], [4, "7:34", "Sokolov, Závodu míru", "X02"], [1, "7:35", "Březová, aut.st.", "X02"], [3, "7:45", "Sokolov, sídl.Michal", "X02"], [3, "7:51", "Sokolov, Závodu míru", "X03"], [1, "7:55", "Březová, aut.st.", "X02"], [1, "7:57", "Březová, aut.st.", "X03"], [3, "7:58", "Sokolov, Závodu míru", "X04"], // and so on ]; }