sokolov-sbs-flowserver/flow/get_departures.js
2025-08-07 21:49:01 +02:00

613 lines
37 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<Array<any>>} 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<Array<any>>} 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
];
}