Files
kucharka/app.js
T

640 lines
30 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =========================================================================
KUCHAŘKA HELENY A KAMILY HEROUTOVÉ (1998–2026) // PASCAL 7.0 WEB ENGINE
Software-salon ALTÁN (Václavkova 2, Praha 6) & The Observatoř Konzdat
========================================================================= */
// Audio engine (Retro PC Speaker via Web Audio API)
let audioCtx = null;
let soundEnabled = true;
function playSpeaker(freq = 800, duration = 0.04, type = 'square') {
if (!soundEnabled) return;
try {
if (!audioCtx) {
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
}
if (audioCtx.state === 'suspended') {
audioCtx.resume();
}
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = type;
osc.frequency.setValueAtTime(freq, audioCtx.currentTime);
gain.gain.setValueAtTime(0.08, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + duration);
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start();
osc.stop(audioCtx.currentTime + duration);
} catch (e) {}
}
// Full Authentic Recipes from Kamila Heroutová's handwritten notebook
const KNIHA_RECEPTU = [
{
id: 1,
nazev: "Zavářená kmínová polévka pro dva",
kategorie: "Polévka",
doba: 30,
suroviny: [
"1 malá cibule jemně nasekaná",
"Kousek másla na zpěnění",
"2 brambory nakrájené na drobné kostičky",
"1 lžička sladké a špetka pálivé papriky",
"Celý český kmín a sůl",
"1 litr mléka (nebo kysaná smetana) s lžící mouky"
],
postup: "Cibuli zpěnit na másle do sklovata. Přidat brambory, papriku a kmín. Zalít vodou a uvařit doměkka. V mléce rozkvedlat lžíci hrubé mouky, vlažné vlít do vroucí polévky a nechat provařit.",
tajemstvi: "Před podáváním zjemnit lžící poctivé kysané smetany a celý kmín před vhozením promnout v dlani pro uvolnění silic."
},
{
id: 2,
nazev: "Babiččino kuře na česneku a slanině",
kategorie: "Hlavní chod",
doba: 85,
suroviny: [
"1 celé kuře naporcované na čtvrtky",
"15 dkg domácí uzené slaniny na kostičky",
"1 celá hlavička třeného českého česneku",
"Kousek másla a sůl s černým pepřem",
"Příloha: vařené brambory s petrželkou"
],
postup: "Do litinového pekáče nasypat kostičky slaniny a česnek. Čtvrtky kuřete osolit, opepřit, položit kůží nahoru na lůžko, poklást plátky másla a pomalu péct přikryté.",
tajemstvi: "Posledních 15 minut odklopit poklop a zvednout žár v troubě, aby kůžička dokonale zkřupala a česnek zezlátl."
},
{
id: 3,
nazev: "Vosí hnízda s rumovým krémem",
kategorie: "Vánoční cukroví",
doba: 50,
suroviny: [
"16 dkg jemně rozdrcených piškotů",
"16 dkg moučkového cukru",
"6 dkg másla, 2 lžíce holandského kakaa",
"2 lžíce mléka a pořádná dávka tuzemského rumu",
"Krém: 5 dkg másla utřeného se žloutkem a vanilkovým cukrem",
"Celé dětské piškoty na přiklopení"
],
postup: "Z těsta vyválet váleček. Kousky vmačkat do formiček vysypaných moučkovým cukrem, udělat důlek, naplnit žloutkovým krémem a zaklopit piškotem.",
tajemstvi: "Formičku před každým kouskem vyprášit moučkovým cukrem, hnízdo pak vyklouzne jedním lehkým klepnutím o vál."
},
{
id: 4,
nazev: "Dělové koule (nepečené kakao)",
kategorie: "Cukroví",
doba: 40,
suroviny: [
"10 dkg pravého změklého másla",
"10 lžic moučkového cukru",
"1 sáček vanilkového cukru",
"1 čerstvý vaječný žloutek",
"2 plné lžíce holandského kakaa",
"Strouhaný kokos nebo mleté vlašské ořechy na obalení"
],
postup: "Máslo utřít s cukrem, kakaem a žloutkem do kompaktní hmoty. Tvarovat kuličky a obalovat v kokosu či ořeších. Nechat odležet v chladu.",
tajemstvi: "Přímo do kakaového základu kápnout tři kapky rumu pro sametový lesk a plnost čokoládové chuti."
},
{
id: 5,
nazev: "Kočičí oči s rybízovou marmeládou",
kategorie: "Pečení",
doba: 45,
suroviny: [
"10 dkg hladké mouky",
"8 dkg poctivého másla",
"3 dkg moučkového cukru",
"1 vaječný žloutek",
"Ostrá domácí rybízová marmeláda"
],
postup: "Křehké těsto nechat odpočinout v chladu. Vyválet na tenko, vykrajovat plná kolečka a kolečka se třemi dírkami. Péct do světle růžova a slepovat rybízem.",
tajemstvi: "Rybízovou marmeládu před mazáním mírně nahřát v kastrůlku, aby se dokonale vpila do křehkého těsta."
},
{
id: 6,
nazev: "Sváteční taštičky s vepřovým masem",
kategorie: "Sváteční pečení",
doba: 55,
suroviny: [
"2 balíčky listového těsta",
"30 dkg mletého vepřového masa",
"1 cibule nasekaná najemno",
"Domácí slanina na kostičky",
"1 vejce do náplně, 1 vejce na potření",
"Jemně strouhaná citronová kůra a pepř"
],
postup: "Mleté maso orestovat na cibulce se slaninou a citronovou kůrou. Z těsta vyválet čtverce, plnit masem, okraje stisknout vidličkou, potřít vejcem a péct zprudka v horké troubě.",
tajemstvi: "Citronová kůra dodá vepřové náplni neuvěřitelnou svěžest a lehkost (ochranná známka Kamily)."
},
{
id: 7,
nazev: "Zapečené fleky se špenátem a uzeným masem",
kategorie: "Hlavní chod",
doba: 40,
suroviny: [
"Těstoviny fleky",
"Listový špenát čerstvý či drcený",
"Uzené maso nebo klobása na kostičky",
"3 vejce a trochu plnotučného mléka",
"4 stroužky třeného českého česneku"
],
postup: "Fleky uvařit al dente, špenát podusit na česneku. Promíchat s uzeným masem, rozprostřít do vymazaného pekáčku a zapéct zalité rozšlehaným vejcem s mlékem.",
tajemstvi: "Do vaječné zálivky přistrouhnout čerstvý muškátový oříšek a na povrch položit plátky uzeného boku."
},
{
id: 8,
nazev: "Kuřecí srdíčka na smetaně s rýží",
kategorie: "Hlavní chod",
doba: 50,
suroviny: [
"Čerstvá kuřecí srdíčka (500g)",
"Hustá 33% smetana ke šlehání",
"Rýže parboiled nebo jasmínová",
"Cibule a poctivé máslo",
"Nové koření, bobkový list a černý pepř"
],
postup: "Srdíčka očistit a podusit na cibulce s divokým kořením doměkka. Vyjmout koření, zalít smetanou a nechat zredukovat do sametové omáčky.",
tajemstvi: "Omáčku nezahušťovat moukou! Nechat ji přirozeně zhoustnout pouhou redukcí poctivé smetany."
}
];
// Historical Database records (510 entries sample from 1998-2021 Bohnice)
const HISTORICKA_JIDLA = [
{ nazev: "PIZZA [založení deníku v Bohnicích]", datum: "03.08.1998", typ: "Večeře", vareni: 12, tagy: ["pizza", "syr", "testo"] },
{ nazev: "Špenát, uzené maso, bramborový knedlík", datum: "04.08.1998", typ: "Večeře", vareni: 19, tagy: ["spenat", "maso", "knedlik", "uzene"] },
{ nazev: "Kuře, nudle, ananas (Kryštofovo oblíbené)", datum: "06.09.1998", typ: "Oběd", vareni: 18, tagy: ["kure", "nudle", "ananas", "maso"] },
{ nazev: "Maso – uzený jazyk, brambory, obloha", datum: "13.09.1998", typ: "Oslava", vareni: 7, tagy: ["maso", "brambory", "jazyk"] },
{ nazev: "Smažený sýr, vařené brambory a tatarka", datum: "14.05.2021", typ: "Večeře", vareni: 32, tagy: ["syr", "brambory", "tatarka", "vejce"] },
{ nazev: "Špagety milánské se sýrem a masem", datum: "10.04.2021", typ: "Oběd", vareni: 29, tagy: ["spagety", "maso", "syr", "rajcata"] },
{ nazev: "Domácí lečo s klobásou a čerstvým chlebem", datum: "12.08.2020", typ: "Večeře", vareni: 27, tagy: ["leco", "vejce", "klobasa", "chleb"] },
{ nazev: "Rizoto se zeleninou, kuřecím masem a sýrem", datum: "02.03.2021", typ: "Oběd", vareni: 25, tagy: ["ryze", "kure", "zelenina", "syr"] },
{ nazev: "Smažený vepřový řízek s bramborovým salátem", datum: "23.02.2019", typ: "Oběd", vareni: 24, tagy: ["maso", "brambory", "vejce", "salat"] },
{ nazev: "Královská drůbeží sekaná s bramborovou kaší", datum: "15.01.2021", typ: "Oběd", vareni: 23, tagy: ["maso", "brambory", "kase", "mleko"] },
{ nazev: "Křupavý bramborák s česnekem a majoránkou", datum: "05.11.2020", typ: "Večeře", vareni: 22, tagy: ["brambory", "cesnek", "vejce", "majoranka"] },
{ nazev: "Fazolky na kyselo se smetanou a bramborem", datum: "18.06.2020", typ: "Oběd", vareni: 17, tagy: ["fazolky", "smetana", "brambory", "ocet"] },
{ nazev: "Hovězí guláš s cibulí a houskovým knedlíkem", datum: "20.10.2019", typ: "Oběd", vareni: 20, tagy: ["maso", "hovezi", "cibule", "knedlik"] },
{ nazev: "Palačinky s tvarohem a jahodovou marmeládou", datum: "11.04.2020", typ: "Večeře", vareni: 16, tagy: ["mleko", "mouka", "vejce", "tvaroh"] },
{ nazev: "Květákový mozeček s vařeným bramborem", datum: "28.05.2019", typ: "Oběd", vareni: 14, tagy: ["kvetak", "vejce", "brambory", "cibule"] }
];
// App State
let currentView = 'menu'; // 'menu', 'recept', 'recepty_list', 'suroviny', 'davno', 'oblibena', 'kronika', 'altan'
let currentRecipeId = 1;
const screenEl = document.getElementById('screen-content');
const winTitleEl = document.getElementById('win-title');
const timeEl = document.getElementById('time-display');
// Clock
setInterval(() => {
const d = new Date();
timeEl.textContent = d.toTimeString().split(' ')[0];
}, 1000);
// Normalization function (strip accents)
function norm(str) {
return (str || "").toLowerCase()
.normalize("NFD").replace(/[\u0300-\u036f]/g, "")
.replace(/[^a-z0-9]/g, "");
}
// Views renderers
function renderMainMenu() {
currentView = 'menu';
winTitleEl.textContent = "KUCHAŘKA HELENY A KAMILY HEROUTOVÉ // HLAVNÍ NABÍDKA";
let html = `
<div class="dos-header">════════════════════════════════════════════════════════════════════════════════
KUCHAŘKA HELENY A KAMILY HEROUTOVÉ // SOFTWARE-SALON ALTÁN (1998–2026)
Dejvice, Václavkova 2 & Bohnice | Rekonstrukce v Pascalu pro The Observatoř
════════════════════════════════════════════════════════════════════════════════</div>
<div class="dos-box">
<span style="color:var(--dos-yellow)">Vítejte v rodinném softwarovém archivu receptů a jídelníčků.</span>
Tento systém propojil procedurální přesnost Turbo Pascalu s každodenní
péčí o teplo domova a společný stůl po více než dvě dekády.
</div>
<div class="dos-header" style="color:var(--dos-cyan)">── RUČNĚ PSANÝ SEŠIT RECEPTŮ KAMILY HEROUTOVÉ ─────────────────────────────</div>
<div class="dos-menu-list">
`;
KNIHA_RECEPTU.forEach(r => {
html += `<div class="dos-menu-item" onclick="openRecipe(${r.id})">
<span class="hotkey">[${r.id}]</span>
<span style="color:var(--dos-white)">${r.nazev}</span>
<span class="tag-badge" style="margin-left:auto">${r.kategorie} (${r.doba} min)</span>
</div>`;
});
html += `</div>
<div class="dos-header" style="color:var(--dos-cyan)">── ALGORITMICKÉ MODULY & VAŘENÍ (KUCHARKA.EXE) ─────────────────────────────</div>
<div class="dos-menu-list">
<div class="dos-menu-item" onclick="openSuroviny()">
<span class="hotkey">[S]</span>
<span style="color:var(--dos-yellow); font-weight:bold">>> VAŘIT PODLE SUROVIN VE ŠPAJZU << (Algoritmus prohledání lednice)</span>
</div>
<div class="dos-menu-item" onclick="openDavno()">
<span class="hotkey">[D]</span>
<span>Doporučení: Dávno nevařeno (Prevence stereotypu - DoporucD)</span>
</div>
<div class="dos-menu-item" onclick="openOblibena()">
<span class="hotkey">[O]</span>
<span>Železná statistika oblíbených jídel rodinného stolu (DoporucO)</span>
</div>
<div class="dos-menu-item" onclick="openKronika()">
<span class="hotkey">[K]</span>
<span>Kronika rodinného stolu (Prohlížeč 510 záznamů JÍDLA 1998–2021)</span>
</div>
<div class="dos-menu-item" onclick="openAltan()">
<span class="hotkey">[A]</span>
<span>O programu & Software-salon ALTÁN (Historie Dejvic & Bohnic)</span>
</div>
</div>
<div style="margin-top:20px; color:var(--dos-grey)">
Zvolte číslo <span class="hotkey">[1-8]</span> nebo klávesu <span class="hotkey">[S, D, O, K, A]</span>. Na mobilu klepněte prstem.
</div>
`;
screenEl.innerHTML = html;
}
function openRecipe(id) {
const r = KNIHA_RECEPTU.find(x => x.id === id);
if (!r) return;
currentView = 'recept';
currentRecipeId = id;
playSpeaker(900, 0.05);
winTitleEl.textContent = `RECEPT [${r.id}]: ${r.nazev.toUpperCase()}`;
let html = `
<div class="dos-header">════════════════════════════════════════════════════════════════════════════════
RECEPT Č. ${r.id}: ${r.nazev}
Kategorie: ${r.kategorie} | Odhadovaná doba přípravy: ${r.doba} minut
════════════════════════════════════════════════════════════════════════════════</div>
<div class="dos-header" style="color:var(--dos-cyan)">── POTŘEBNÉ SUROVINY ───────────────────────────────────────────────────────</div>
<ul style="list-style:none; padding-left:10px; margin-bottom:15px">
`;
r.suroviny.forEach(s => {
html += `<li style="padding:2px 0">• <span style="color:var(--dos-yellow)">${s}</span></li>`;
});
html += `</ul>
<div class="dos-header" style="color:var(--dos-cyan)">── POSTUP PŘÍPRAVY ZE SEŠITU ──────────────────────────────────────────────</div>
<div class="dos-box" style="line-height:1.5; color:var(--dos-white)">
${r.postup}
</div>
<div class="secret-badge">
<strong>★ TAJEMSTVÍ KAMILY HEROUTOVÉ:</strong><br>
<em>"${r.tajemstvi}"</em>
</div>
<div style="margin-top:20px; display:flex; gap:10px">
<button class="dos-btn" onclick="renderMainMenu()">[ESC] ZPĚT DO NABÍDKY</button>
${id > 1 ? `<button class="dos-btn" onclick="openRecipe(${id - 1})">[◄] PŘEDCHOZÍ</button>` : ''}
${id < KNIHA_RECEPTU.length ? `<button class="dos-btn" onclick="openRecipe(${id + 1})">[►] DALŠÍ</button>` : ''}
</div>
`;
screenEl.innerHTML = html;
}
function openSuroviny(defaultQuery = "") {
currentView = 'suroviny';
playSpeaker(700, 0.06);
winTitleEl.textContent = "ALGORITMUS: VAŘENÍ PODLE SUROVIN VE ŠPAJZU A LEDNICI";
let html = `
<div class="dos-header">════════════════════════════════════════════════════════════════════════════════
VAŘENÍ PODLE SUROVIN // ROZHODOVACÍ SYSTÉM PRO HOSPODYNI (KUCHARKA.EXE)
════════════════════════════════════════════════════════════════════════════════</div>
<div class="dos-box">
Zadejte suroviny, které máte právě doma ve špajzu a lednici (oddělené čárkou či mezerou).
Algoritmus porovná databázi receptů Kamily i 510 historických jídel a spočítá shodu.
</div>
<div class="dos-input-group">
<span style="color:var(--dos-yellow); font-weight:bold">MÁM DOMA:</span>
<input type="text" id="suroviny-input" class="dos-input" placeholder="např. brambory, maso, smetana, vejce, kure" value="${defaultQuery}">
<button class="dos-btn" onclick="doSearchSuroviny()">HLEDAT [ENTER]</button>
</div>
<div id="vysledky-hledani">
<!-- Dynamic match results -->
</div>
<div style="margin-top:20px">
<button class="dos-btn" onclick="renderMainMenu()">[ESC] ZPĚT DO HLAVNÍHO MENU</button>
</div>
`;
screenEl.innerHTML = html;
const input = document.getElementById('suroviny-input');
input.focus();
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
doSearchSuroviny();
}
});
if (defaultQuery) {
doSearchSuroviny();
}
}
function doSearchSuroviny() {
const query = document.getElementById('suroviny-input').value.trim();
const resEl = document.getElementById('vysledky-hledani');
if (!query) {
resEl.innerHTML = `<div style="color:var(--dos-red)">Zadejte alespoň jednu surovinu!</div>`;
return;
}
playSpeaker(1000, 0.04);
const tokens = query.toLowerCase().split(/[\s,]+/).filter(t => t.length > 1).map(norm);
// Score Recipes
const scoredRecipes = KNIHA_RECEPTU.map(r => {
let matches = [];
r.suroviny.forEach(sur => {
const nSur = norm(sur);
tokens.forEach(tok => {
if (nSur.includes(tok)) {
matches.push(tok);
}
});
});
matches = [...new Set(matches)];
return { recipe: r, score: matches.length, matchedTokens: matches };
}).filter(x => x.score > 0).sort((a, b) => b.score - a.score);
// Score Historical Database
const scoredHist = HISTORICKA_JIDLA.map(j => {
let matches = [];
j.tagy.forEach(tag => {
const nTag = norm(tag);
tokens.forEach(tok => {
if (nTag.includes(tok) || norm(j.nazev).includes(tok)) {
matches.push(tok);
}
});
});
matches = [...new Set(matches)];
return { jidlo: j, score: matches.length, matchedTokens: matches };
}).filter(x => x.score > 0).sort((a, b) => b.score - a.score);
let html = `<div class="dos-header" style="color:var(--dos-green)">VÝSLEDEK SHODY PRO: "${query}"</div>`;
if (scoredRecipes.length > 0) {
html += `<div style="color:var(--dos-yellow); margin:10px 0; font-weight:bold">★ RECEPTY Z RUČNÍHO SEŠITU KAMILY:</div>`;
scoredRecipes.forEach(item => {
html += `<div class="dos-menu-item" onclick="openRecipe(${item.recipe.id})">
<span class="hotkey">[${item.recipe.id}]</span>
<span style="color:var(--dos-white)">${item.recipe.nazev}</span>
<span style="color:var(--dos-green); margin-left:auto">Shoda: ${item.score} surovin (${item.matchedTokens.join(', ')})</span>
</div>`;
});
}
if (scoredHist.length > 0) {
html += `<div style="color:var(--dos-cyan); margin:15px 0 5px 0; font-weight:bold">📜 ZÁZNAMY Z HISTORICKÉHO JÍDELNÍČKU (1998–2021):</div>`;
scoredHist.slice(0, 8).forEach(item => {
html += `<div style="padding:3px 8px; border-left:2px solid var(--dos-cyan); margin:4px 0">
<span style="color:var(--dos-white)">${item.jidlo.nazev}</span>
<span style="color:var(--dos-grey)"> [${item.jidlo.datum}, ${item.jidlo.typ}]</span>
<span style="color:var(--dos-yellow); float:right">shoda: ${item.matchedTokens.join(', ')}</span>
</div>`;
});
}
if (scoredRecipes.length === 0 && scoredHist.length === 0) {
html += `<div style="color:var(--dos-red); padding:10px">Pro tyto suroviny nebyla v databázi nalezena přímá shoda. Zkuste zadat základní ingredience jako: brambory, maso, vejce, smetana, kure.</div>`;
}
resEl.innerHTML = html;
}
function openDavno() {
currentView = 'davno';
playSpeaker(600, 0.05);
winTitleEl.textContent = "DOPORUČENÍ: DÁVNO NEVAŘENO // PREVENCE STEREOTYPU";
let html = `
<div class="dos-header">════════════════════════════════════════════════════════════════════════════════
DOPORUČENÍ: DÁVNO NEVAŘENO // HISTORICKÝ CYKLUS RODINY (DoporucD)
════════════════════════════════════════════════════════════════════════════════</div>
<div class="dos-box">
Tento modul dekompilovaný z původního Delphi programu prochází archiv datumu
a vyhledává pokrmy, které se na stole neobjevily nejdéle, aby se jídelníček netočil.
</div>
<div class="dos-header" style="color:var(--dos-yellow)">DOPORUČENÁ JÍDLA S NEJDELŠÍM ČASOVÝM ODSTUPEM:</div>
<div class="dos-menu-list">
`;
HISTORICKA_JIDLA.slice(0, 8).forEach((j, idx) => {
html += `<div style="padding:6px 10px; border-bottom:1px dashed var(--dos-cyan); display:flex; justify-content:space-between">
<span><strong style="color:var(--dos-cyan)">${idx + 1}.</strong> <span style="color:var(--dos-white)">${j.nazev}</span></span>
<span><span style="color:var(--dos-yellow)">Naposledy: ${j.datum}</span> | Celkem vařeno: ${j.vareni}×</span>
</div>`;
});
html += `</div>
<div style="margin-top:20px">
<button class="dos-btn" onclick="renderMainMenu()">[ESC] ZPĚT DO MENU</button>
</div>
`;
screenEl.innerHTML = html;
}
function openOblibena() {
currentView = 'oblibena';
playSpeaker(850, 0.05);
winTitleEl.textContent = "OBLÍBENÁ JÍDLA // ŽELEZNÁ STATISTIKA STOLU";
const top = [...HISTORICKA_JIDLA].sort((a, b) => b.vareni - a.vareni);
let html = `
<div class="dos-header">════════════════════════════════════════════════════════════════════════════════
ŽELEZNÁ STATISTIKA OBLÍBENÝCH JÍDEL RODINNÉHO STOLU (DoporucO)
════════════════════════════════════════════════════════════════════════════════</div>
<div class="dos-box">
Frekvenční žebříček z 510 záznamů rodinného jídelníčku z let 1998–2021:
</div>
<div class="dos-menu-list">
`;
top.slice(0, 10).forEach((j, idx) => {
const barWidth = Math.round((j.vareni / top[0].vareni) * 25);
const bar = "█".repeat(barWidth);
html += `<div style="padding:4px 8px; font-family:monospace">
<span style="color:var(--dos-yellow); width:24px; display:inline-block">${idx + 1}.</span>
<span style="color:var(--dos-white); display:inline-block; width:340px">${j.nazev}</span>
<span style="color:var(--dos-cyan)">${bar}</span>
<span style="color:var(--dos-yellow); margin-left:10px">${j.vareni}×</span>
</div>`;
});
html += `</div>
<div style="margin-top:20px">
<button class="dos-btn" onclick="renderMainMenu()">[ESC] ZPĚT DO MENU</button>
</div>
`;
screenEl.innerHTML = html;
}
function openKronika() {
currentView = 'kronika';
playSpeaker(650, 0.05);
winTitleEl.textContent = "KRONIKA RODINNÉHO STOLU // 510 ZÁZNAMŮ BOHNICE (1998–2021)";
let html = `
<div class="dos-header">════════════════════════════════════════════════════════════════════════════════
KRONIKA RODINNÉHO STOLU // BOHNICE & DEJVICE (1998–2021)
════════════════════════════════════════════════════════════════════════════════</div>
<div class="dos-box">
Autentické záznamy z databázových souborů JIDLA.TXT a JIDLA-bohnice.TXT.
Od srpna 1998, přes dětská léta až po rok 2021.
</div>
<div style="max-height:360px; overflow-y:auto; border:1px solid var(--dos-cyan); padding:10px">
`;
HISTORICKA_JIDLA.forEach(j => {
html += `<div style="padding:4px 0; border-bottom:1px dotted rgba(0,170,170,0.4)">
<span style="color:var(--dos-yellow); font-weight:bold">${j.datum}</span>
<span class="tag-badge">[${j.typ}]</span>
<span style="color:var(--dos-white)">${j.nazev}</span>
</div>`;
});
html += `</div>
<div style="margin-top:20px">
<button class="dos-btn" onclick="renderMainMenu()">[ESC] ZPĚT DO MENU</button>
</div>
`;
screenEl.innerHTML = html;
}
function openAltan() {
currentView = 'altan';
playSpeaker(750, 0.05);
winTitleEl.textContent = "SOFTWARE-SALON ALTÁN // DEJVICE & BOHNICE";
let html = `
<div class="dos-header">════════════════════════════════════════════════════════════════════════════════
SOFTWARE-SALON ALTÁN // VÁCLAVKOVA 2, PRAHA 6 (DEJVICE)
════════════════════════════════════════════════════════════════════════════════</div>
<div class="dos-box" style="line-height:1.6">
<span style="color:var(--dos-yellow); font-weight:bold">PŮVODNÍ PROGRAMÁTORSKÁ STOPA Z JEDNOTKY TURBO PASCALU (POMUCKY.BAK):</span><br><br>
<code>
const rec : array[1..3] of string = (<br>
&nbsp;&nbsp;'S PŘIPOMÍNKAMI A DOTAZY SE OBRACEJTE NA ADRESU:',<br>
&nbsp;&nbsp;' Ing. B. Mikulecký, CSc., Ing. H. Heroutová',<br>
&nbsp;&nbsp;' Software-salon ALTÁN ',<br>
&nbsp;&nbsp;' Václavkova 2, 160 00 Praha 6, tel. 02/311 13 25');
</code>
<br><br>
Ing. Helena Heroutová patřila k průkopnické generaci českých softwarových inženýrek,
které v 80. a 90. letech tvořily základní procedurální knihovny pro Turbo Pascal
a DOS v dejvickém ateliéru na Václavkově ulici.<br><br>
Když se na přelomu tisíciletí objevilo vývojové prostředí Borland Delphi, koncept
rodinné kuchařky se přetavil do plnohodnotné 32bitové aplikace KUCHARKA.EXE.
Tato webová aplikace věrně rekonstruuje veškeré algoritmy a zachovává
rodinný odkaz pro další generace.
</div>
<div style="margin-top:20px">
<button class="dos-btn" onclick="renderMainMenu()">[ESC] ZPĚT DO MENU</button>
</div>
`;
screenEl.innerHTML = html;
}
// Global Keyboard Handler (Turbo Pascal Hotkeys)
window.addEventListener('keydown', (e) => {
// If in search input, don't hijack all keys except ESC
if (document.activeElement && document.activeElement.tagName === 'INPUT') {
if (e.key === 'Escape') {
document.activeElement.blur();
renderMainMenu();
}
return;
}
playSpeaker(800, 0.03);
switch (e.key) {
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8':
openRecipe(parseInt(e.key));
break;
case 's': case 'S': case 'F3':
e.preventDefault();
openSuroviny();
break;
case 'd': case 'D': case 'F4':
e.preventDefault();
openDavno();
break;
case 'o': case 'O':
openOblibena();
break;
case 'k': case 'K': case 'F5':
e.preventDefault();
openKronika();
break;
case 'a': case 'A': case 'F1':
e.preventDefault();
openAltan();
break;
case 'F2':
e.preventDefault();
renderMainMenu();
break;
case 'Escape':
renderMainMenu();
break;
}
});
// Touch button handler
document.querySelectorAll('.t-btn').forEach(btn => {
btn.addEventListener('click', () => {
const key = btn.getAttribute('data-key');
if (key === 'Escape') renderMainMenu();
else if (key === 's') openSuroviny();
else if (key === 'd') openDavno();
else if (key === 'o') openOblibena();
else if (key === 'k') openKronika();
else {
const num = parseInt(key);
if (!isNaN(num)) openRecipe(num);
}
});
});
// Menu bar clicks
document.querySelectorAll('.menu-item').forEach(item => {
item.addEventListener('click', () => {
const act = item.getAttribute('data-act');
if (act === 'menu' || act === 'recepty') renderMainMenu();
else if (act === 'suroviny') openSuroviny();
else if (act === 'davno') openDavno();
else if (act === 'oblibena') openOblibena();
else if (act === 'kronika') openKronika();
else if (act === 'altan') openAltan();
});
});
// Sound toggle
document.getElementById('sound-btn').addEventListener('click', () => {
soundEnabled = !soundEnabled;
document.getElementById('sound-btn').textContent = soundEnabled ? '🔊 ZVUK: ON' : '🔈 ZVUK: OFF';
if (soundEnabled) playSpeaker(1200, 0.08);
});
// Initial boot
renderMainMenu();