Oprava parsování Sladovnické v případě chybějících dnů
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful

This commit is contained in:
Martin Berka 2025-10-31 08:59:30 +01:00
parent 7407a3d881
commit ccfe9a9ae1
Signed by: mates
SSH Key Fingerprint: SHA256:HILXS+ahJ33PQ6YDd3ToEV92OujgFG6CUiFQmvgBx0Q

View File

@ -67,7 +67,7 @@ const parseAllergens = (name: string): { cleanName: string, allergens: number[]
if (match) {
const allergenString = match[1];
const allergens = allergenString.split(',').map(num => parseInt(num.trim(), 10)).filter(num => !isNaN(num));
const allergens = allergenString.split(',').map(num => Number.parseInt(num.trim(), 10)).filter(num => !Number.isNaN(num));
const cleanName = name.replace(regex, '').trim();
return { cleanName, allergens };
}
@ -100,18 +100,42 @@ export const getMenuSladovnicka = async (firstDayOfWeek: Date, mock: boolean = f
const html = await getHtml(SLADOVNICKA_URL);
const $ = load(html);
const menuContentElements = $('#daily-menu-content-list').children('[id^="daily-menu-content-"]');
// Prozatím předpokládáme, že budou mít vždy elementy pro všech 5 dní v týdnu, i pokud bude zavřeno
if (menuContentElements.length < 5) {
throw Error("Neočekávaný počet dní v menu Sladovnické: " + menuContentElements.length + ", očekáváno 5 (možná je některý den zavřeno?)");
}
// Nejdříve zjistíme, které dny jsou k dispozici z tab elementů
const tabElements = $('#daily-menu-tab-list').children('button[id^="daily-menu-tab-"]');
const availableDays: { [dayIndex: number]: number } = {}; // mapování dayIndex -> contentIndex
tabElements.each((contentIndex, tabElement) => {
const dayText = $(tabElement).find('.daily-menu-tab__day').text().toLowerCase();
const dayIndex = DAYS_IN_WEEK.indexOf(dayText);
if (dayIndex !== -1 && dayIndex < 5) { // pouze pracovní dny (0-4)
availableDays[dayIndex] = contentIndex;
}
});
const menuContentElements = $('#daily-menu-content-list').children('[id^="daily-menu-content-"]');
const result: Food[][] = [];
// Inicializujeme všechny pracovní dny (0-4) prázdnými poli
for (let dayIndex = 0; dayIndex < 5; dayIndex++) {
const dayChildren = $(menuContentElements[dayIndex]).children();
// Prozatím předpokládáme, že budou mít vždy polévku a hlavní jídla
result[dayIndex] = [];
}
// Projdeme pouze dostupné dny
for (const [dayIndex, contentIndex] of Object.entries(availableDays)) {
const dayIndexNum = Number.parseInt(dayIndex);
const contentIndexNum = contentIndex;
if (contentIndexNum >= menuContentElements.length) {
continue; // Přeskočíme, pokud content element neexistuje
}
const dayChildren = $(menuContentElements[contentIndexNum]).children();
// Ověříme, že má element očekávanou strukturu
if (dayChildren.length < 2) {
throw Error("Neočekávaný počet children v menu Sladovnické pro den " + dayIndex + ": " + dayChildren.length + ", očekávány alespoň 2 (polévka a hlavní jídlo)");
console.warn(`Neočekávaný počet children v menu Sladovnické pro den ${dayIndexNum}: ${dayChildren.length}, očekávány alespoň 2 (polévka a hlavní jídlo)`);
continue;
}
// Parsování polévky
@ -119,7 +143,8 @@ export const getMenuSladovnicka = async (firstDayOfWeek: Date, mock: boolean = f
const soupTable = $(soupElement).find('table tbody tr');
const soupCells = soupTable.children('td');
if (soupCells.length !== 3) {
throw Error("Neočekávaný počet buněk v tabulce polévky: " + soupCells.length + ", ale očekávány byly 3");
console.warn(`Neočekávaný počet buněk v tabulce polévky pro den ${dayIndexNum}: ${soupCells.length}, ale očekávány byly 3`);
continue;
}
const soupAmount = sanitizeText($(soupCells.get(0)).text());
@ -163,8 +188,9 @@ export const getMenuSladovnicka = async (firstDayOfWeek: Date, mock: boolean = f
}
});
result[dayIndex] = currentDayFood;
result[dayIndexNum] = currentDayFood;
}
return result;
}
@ -186,7 +212,7 @@ export const getMenuUMotliku = async (firstDayOfWeek: Date, mock: boolean = fals
// Najdeme první tabulku, nad kterou je v H3 datum začínající co nejdřívějším dnem v aktuálním týdnu
const tables = $('table.table.table-hover.Xtable-striped');
let usedTable;
let usedDate = new Date(firstDayOfWeek.getTime());
let usedDate = new Date(firstDayOfWeek);
for (let i = 0; i < 4; i++) {
const dayOfWeekString = `${usedDate.getDate()}.${usedDate.getMonth() + 1}.`;
for (const tableNode of tables) {
@ -206,7 +232,7 @@ export const getMenuUMotliku = async (firstDayOfWeek: Date, mock: boolean = fals
if (usedTable == null) {
const firstDayOfWeekString = `${firstDayOfWeek.getDate()}.${firstDayOfWeek.getMonth() + 1}.`;
throw Error(`Nepodařilo se najít tabulku pro týden začínající ${firstDayOfWeekString}`);
throw new Error(`Nepodařilo se najít tabulku pro týden začínající ${firstDayOfWeekString}`);
}
const body = usedTable.children().first();
@ -239,11 +265,11 @@ export const getMenuUMotliku = async (firstDayOfWeek: Date, mock: boolean = fals
} else if (foodType === 'Hlavní jídlo') {
isSoup = false;
} else {
throw Error("Neočekáváný typ jídla: " + foodType);
throw new Error("Neočekáváný typ jídla: " + foodType);
}
} else {
if (children.length !== 3) {
throw Error("Neočekávaný počet child elementů pro jídlo: " + children.length + ", očekávány 3");
throw new Error("Neočekávaný počet child elementů pro jídlo: " + children.length + ", očekávány 3");
}
const amount = sanitizeText($(children.get(0)).text());
const name = sanitizeText($(children.get(1)).text());
@ -296,7 +322,7 @@ export const getMenuTechTower = async (firstDayOfWeek: Date, mock: boolean = fal
})
}
if (!font) {
throw Error('Chyba: nenalezen <font> pro obědy v HTML Techtower.');
throw new Error('Chyba: nenalezen <font> pro obědy v HTML Techtower.');
}
const result: Food[][] = [];
@ -442,7 +468,7 @@ export const getMenuSenkSerikova = async (firstDayOfWeek: Date, mock: boolean =
currentDayFood.push({
amount: '-',
name: nameWithoutNumber,
price: $(element).children('div.cena').text().replace(/ /g, '\xA0'),
price: $(element).children('div.cena').text().replaceAll(' ', '\xA0'),
isSoup: $(element).hasClass('polevka'),
});
});