fix: oprava pro aktuální podobu TechTower
CI / Generate TypeScript types (push) Successful in 11s
CI / Server unit tests (push) Successful in 21s
CI / Build server (push) Successful in 23s
CI / Build client (push) Successful in 33s
CI / Playwright E2E tests (push) Successful in 1m21s
CI / Build and push Docker image (push) Successful in 49s
CI / Notify (push) Successful in 2s

This commit is contained in:
2026-06-03 10:04:36 +02:00
parent a26d6cf85c
commit 318d188495
2 changed files with 105 additions and 64 deletions
+97 -42
View File
@@ -314,53 +314,108 @@ export const getMenuTechTower = async (firstDayOfWeek: Date, mock: boolean = fal
}
const result: Food[][] = [];
const siblings = thirdTry
// Čtvrtý pokus (detekce): thirdTry našel <font>, ale nový formát má každý den v jednom <p>
// s položkami oddělenými <br> místo separátních <p> pro každou položku
const fourthTry = thirdTry && $(font).parent().siblings('p').toArray().some(el => {
const firstChild = $(el).contents().first();
return firstChild.is('strong') && DAYS_IN_WEEK.includes(firstChild.text().trim().toLocaleLowerCase());
});
const siblings = (fourthTry || thirdTry)
? $(font).parent().siblings('p')
: secondTry
? $(font).parent().parent().parent().siblings('p')
: $(font).parent().parent().siblings();
let parsing = false;
let currentDayIndex = 0;
for (let i = 0; i < siblings.length; i++) {
const text = $(siblings.get(i)).text().trim().replace('\t', '').replace('\n', ' ');
if (DAYS_IN_WEEK.includes(text.toLocaleLowerCase())) {
// Zjistíme aktuální index
currentDayIndex = DAYS_IN_WEEK.indexOf(text.toLocaleLowerCase());
if (!parsing) {
// Našli jsme libovolný den v týdnu a ještě neparsujeme, tak začneme
parsing = true;
}
} else if (parsing) {
if (text.length == 0) {
// Prázdná řádka - bývá na zcela náhodných místech ¯\_(ツ)_/¯
continue;
}
let price = 'na\xA0váhu';
let nameRaw = text.replace('•', '');
if (text.toLowerCase().endsWith('kč')) {
const tmp = text.replace('\xA0', ' ').split(' ');
const split = [tmp.slice(0, -2).join(' ')].concat(tmp.slice(-2));
price = `${split.slice(1)[0]}\xA0Kč`
nameRaw = split[0].replace('•', '');
} else if (text.toLowerCase().endsWith(',-')) {
const tmp = text.replace('\xA0', ' ').split(' ');
const split = [tmp.slice(0, -1).join(' ')].concat(tmp.slice(-1));
price = `${split.slice(1)[0].replace(',-', '')}\xA0Kč`
nameRaw = split[0].replace('•', '');
}
if (nameRaw.endsWith('')|| nameRaw.endsWith('—')) {
nameRaw = nameRaw.slice(0, -1).trim();
}
const parsed = parseAllergens(nameRaw);
result[currentDayIndex] ??= [];
result[currentDayIndex].push({
amount: '-',
name: parsed.cleanName,
price,
isSoup: isTextSoupName(parsed.cleanName),
allergens: parsed.allergens.length > 0 ? parsed.allergens : undefined,
})
if (fourthTry) {
siblings.each((_, el) => {
const $el = $(el);
const firstChild = $el.contents().first();
if (!firstChild.is('strong')) return;
const dayName = firstChild.text().trim().toLocaleLowerCase();
if (!DAYS_IN_WEEK.includes(dayName)) return;
const dayIndex = DAYS_IN_WEEK.indexOf(dayName);
result[dayIndex] ??= [];
const elHtml = $el.html() ?? '';
const itemLines = elHtml.split(/<br\s*\/?>/i).slice(1)
.map(part => $(`<span>${part}</span>`).text().trim())
.filter(line => line.length > 0);
for (const text of itemLines) {
let price = 'na\xA0váhu';
let nameRaw = text.replace('•', '');
if (text.toLowerCase().endsWith('kč')) {
const tmp = text.replace('\xA0', ' ').split(' ');
const split = [tmp.slice(0, -2).join(' ')].concat(tmp.slice(-2));
price = `${split.slice(1)[0]}\xA0Kč`;
nameRaw = split[0].replace('•', '');
} else if (text.toLowerCase().endsWith(',-')) {
const tmp = text.replace('\xA0', ' ').split(' ');
const split = [tmp.slice(0, -1).join(' ')].concat(tmp.slice(-1));
price = `${split.slice(1)[0].replace(',-', '')}\xA0Kč`;
nameRaw = split[0].replace('•', '');
}
if (nameRaw.endsWith('') || nameRaw.endsWith('—')) {
nameRaw = nameRaw.slice(0, -1).trim();
}
const parsed = parseAllergens(nameRaw);
result[dayIndex].push({
amount: '-',
name: parsed.cleanName,
price,
isSoup: isTextSoupName(parsed.cleanName),
allergens: parsed.allergens.length > 0 ? parsed.allergens : undefined,
});
}
});
} else {
let parsing = false;
let currentDayIndex = 0;
for (let i = 0; i < siblings.length; i++) {
const text = $(siblings.get(i)).text().trim().replace('\t', '').replace('\n', ' ');
if (DAYS_IN_WEEK.includes(text.toLocaleLowerCase())) {
// Zjistíme aktuální index
currentDayIndex = DAYS_IN_WEEK.indexOf(text.toLocaleLowerCase());
if (!parsing) {
// Našli jsme libovolný den v týdnu a ještě neparsujeme, tak začneme
parsing = true;
}
} else if (parsing) {
if (text.length == 0) {
// Prázdná řádka - bývá na zcela náhodných místech ¯\_(ツ)_/¯
continue;
}
let price = 'na\xA0váhu';
let nameRaw = text.replace('•', '');
if (text.toLowerCase().endsWith('kč')) {
const tmp = text.replace('\xA0', ' ').split(' ');
const split = [tmp.slice(0, -2).join(' ')].concat(tmp.slice(-2));
price = `${split.slice(1)[0]}\xA0Kč`
nameRaw = split[0].replace('•', '');
} else if (text.toLowerCase().endsWith(',-')) {
const tmp = text.replace('\xA0', ' ').split(' ');
const split = [tmp.slice(0, -1).join(' ')].concat(tmp.slice(-1));
price = `${split.slice(1)[0].replace(',-', '')}\xA0Kč`
nameRaw = split[0].replace('•', '');
}
if (nameRaw.endsWith('')|| nameRaw.endsWith('—')) {
nameRaw = nameRaw.slice(0, -1).trim();
}
const parsed = parseAllergens(nameRaw);
result[currentDayIndex] ??= [];
result[currentDayIndex].push({
amount: '-',
name: parsed.cleanName,
price,
isSoup: isTextSoupName(parsed.cleanName),
allergens: parsed.allergens.length > 0 ? parsed.allergens : undefined,
})
}
}
}
+8 -22
View File
@@ -1,29 +1,15 @@
<!DOCTYPE html>
<html>
<body>
<div class="outer-container">
<div class="header-section"><!-- font.parent().parent() -->
<p><!-- font.parent() -->
<font class="wsw-41">Obědy 12.5.-16.5.2025</font>
</p>
<div class="b b-text cf">
<div class="b-c b-text-c cf">
<p class="wnd-align-center"><font class="wsw-41 wnd-font-size-120"><strong>Jídelní lístek 12.5.-16.5.2025</strong></font></p>
<p class="wnd-align-center"><strong>Pondělí</strong><br>Polévka dne 1<br>Svíčková na smetaně s knedlíkem 1,3,7 — 149 Kč<br>Smažený sýr s bramborami 1,3 — 139 Kč</p>
<p class="wnd-align-center"><strong>Úterý</strong><br>Česnečka 1<br>Vepřový guláš s houskovým knedlíkem 1,3 — 145 Kč</p>
<p class="wnd-align-center"><strong>Středa</strong><br>Hovězí vývar s nudlemi 1<br>Kuřecí řízek s bramborami 1 — 139 Kč</p>
<p class="wnd-align-center"><strong>Čtvrtek</strong><br>Dršťková polévka 1<br>Segedínský guláš s knedlíkem 1,3 — 145 Kč</p>
<p class="wnd-align-center"><strong>Pátek</strong><br>Rajská polévka s rýží 1<br>Rizoto s kuřecím masem a zeleninou 1 — 139 Kč</p>
</div>
<!-- níže jsou sourozenci .header-section = výsledek $(font).parent().parent().siblings() -->
<p>Pondělí</p>
<p>• Polévka dne 1</p>
<p>• Svíčková na smetaně s knedlíkem 1, 3, 7 149&nbsp;</p>
<p>• Smažený sýr s bramborami 1, 3 139&nbsp;</p>
<p>Úterý</p>
<p>• Česnečka 1</p>
<p>• Vepřový guláš s houskovým knedlíkem 1, 3 145&nbsp;</p>
<p>Středa</p>
<p>• Hovězí vývar s nudlemi 1</p>
<p>• Kuřecí řízek s bramborami 1 139&nbsp;</p>
<p>Čtvrtek</p>
<p>• Dršťková polévka 1</p>
<p>• Segedínský guláš s knedlíkem 1, 3 145&nbsp;</p>
<p>Pátek</p>
<p>• Rajská polévka s rýží 1</p>
<p>• Rizoto s kuřecím masem a zeleninou 1 139&nbsp;</p>
</div>
</body>
</html>