diff --git a/generate_audio.py b/generate_audio.py
new file mode 100644
index 0000000..253ef5d
--- /dev/null
+++ b/generate_audio.py
@@ -0,0 +1,105 @@
+import os
+import asyncio
+import edge_tts
+
+# Zoznam všetkých unikátnych slov podľa aktualizovaného kánonu PSP
+words = [
+ # B
+ "by", "aby", "byľ", "bystrý", "Bystrica", "Bytča", "byť", "nábytok", "bývať", "byt",
+ "bydlisko", "príbytok", "dobytok", "kobyla", "obyčaj", "býk", "bylina", "bydlo", "dobyť",
+ "odbyt", "byvol", "bytosť", "bývalý", "úbytok", "prebytok", "zbytočný",
+ # Votrelci B
+ "bič", "bicykel", "bitka", "biela",
+
+ # M
+ "my", "mykať sa", "mýliť sa", "myslieť", "myšlienka", "myseľ", "umývať sa", "mydlo",
+ "myš", "šmýkať sa", "hmyz", "žmýkať", "priemysel", "Myjava", "mýto", "mys", "zamykať",
+ "pomykov", "hmýriť sa", "šmyk", "priesmyk", "omyl", "zmysel", "pomyje",
+ # Votrelci M
+ "miska", "minúta", "milý", "minca",
+
+ # P
+ "pýcha", "pýšiť sa", "pyšný", "prepych", "pykať", "pýr", "pysk", "pytliak", "kopyto",
+ "pýtať sa", "opýtať sa", "pyžamo",
+ # Votrelci P
+ "pivo", "píšťalka", "pilot", "pieseň",
+
+ # R
+ "ryba", "rýchly", "rys", "ryť", "rýpať", "hrýzť", "kryť", "skryť", "koryto", "korytnačka",
+ "strýko", "ryža", "bryndza", "rýdzi", "rýľ", "ryčať", "ryha", "kryha", "poryv", "trýzniť",
+ # Votrelci R
+ "rieka", "ringloty", "rizoto", "ríbezľa",
+
+ # S
+ "syn", "syr", "sýty", "nasýtiť sa", "sypať", "sypký", "syseľ", "syčať", "sýkorka",
+ "sychravý", "osýpky", "vysychať", "sykať",
+ # Votrelci S
+ "sito", "sirup", "sivý", "silný",
+
+ # V
+ "vysoký", "zvyk", "vy", "vykať", "výr", "výskať", "vyť", "vy-", "vyžla", "vydra",
+ "vyhňa", "výsosť", "zvyšok", "výťah",
+ # Votrelci V
+ "vidly", "víla", "víťaz", "vietor",
+
+ # Z
+ "jazyk", "jazykový", "jazyčnica", "nazývať sa", "ozývať sa", "prezývať", "vyzývať", "pozývať",
+ # Votrelci Z
+ "zima", "zips", "zisk", "zrkadlo"
+]
+
+# Odstránenie duplicít so zachovaním poradia
+unique_words = []
+seen = set()
+for w in words:
+ lower_w = w.strip().lower()
+ if lower_w not in seen:
+ seen.add(lower_w)
+ unique_words.append(w.strip())
+
+output_dir = os.path.join("src", "Ypsilonkovo", "wwwroot", "audio", "words")
+os.makedirs(output_dir, exist_ok=True)
+
+VOICE = "sk-SK-ViktoriaNeural"
+
+async def generate_word(word):
+ hex_name = word.lower().encode("utf-8").hex()
+ file_path = os.path.join(output_dir, f"{hex_name}.mp3")
+
+ # Špeciálna optimalizácia pre krátke slová ako "by"
+ # Ak pošleme text s bodkou, intonácia prirodzene spadne a znie ako krátke "by" a nie "bý"
+ spoken_text = word
+ rate = "-5%" # Jemne pomalšie a pokojnejšie pre deti
+
+ if word.lower() == "by":
+ spoken_text = "by."
+ rate = "+8%" # Krátke, úsečné a jasné 'by' namiesto dlhého 'bý'
+ elif word.lower() == "byť":
+ spoken_text = "byť."
+ rate = "+5%"
+ elif word.lower() == "vy-":
+ spoken_text = "predpona vy."
+ else:
+ spoken_text = f"{word}."
+
+ communicate = edge_tts.Communicate(spoken_text, VOICE, rate=rate)
+ await communicate.save(file_path)
+ print(f"Generated: {hex_name}.mp3")
+
+async def generate_welcome():
+ welcome_path = os.path.join(output_dir, "welcome_female.mp3")
+ text = "Ahoj! Som víla Ypsilka, tvoja sprievodkyňa kráľovstvom Ypsilonkovo. Poďme sa spolu hravo naučiť vybrané slová!"
+ communicate = edge_tts.Communicate(text, VOICE, rate="-4%")
+ await communicate.save(welcome_path)
+ print("Generated: welcome_female.mp3 with Ypsilka")
+
+async def main():
+ print(f"Generating {len(unique_words)} words with {VOICE}...")
+ for w in unique_words:
+ await generate_word(w)
+ await asyncio.sleep(0.05) # Jemný rozostup
+ await generate_welcome()
+ print("All audio files generated successfully!")
+
+if __name__ == "__main__":
+ asyncio.run(main())
diff --git a/src/Ypsilonkovo.sln b/src/Ypsilonkovo.sln
new file mode 100644
index 0000000..ec3cbea
--- /dev/null
+++ b/src/Ypsilonkovo.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ypsilonkovo", "Ypsilonkovo\Ypsilonkovo.csproj", "{81F32E05-72D4-4D68-A11F-2BB2B032503E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Debug|x64.Build.0 = Debug|Any CPU
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Debug|x86.Build.0 = Debug|Any CPU
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Release|x64.ActiveCfg = Release|Any CPU
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Release|x64.Build.0 = Release|Any CPU
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Release|x86.ActiveCfg = Release|Any CPU
+ {81F32E05-72D4-4D68-A11F-2BB2B032503E}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/Ypsilonkovo.slnx b/src/Ypsilonkovo.slnx
new file mode 100644
index 0000000..47d19f3
--- /dev/null
+++ b/src/Ypsilonkovo.slnx
@@ -0,0 +1,3 @@
+
Ktoré slovo sem nepatrí (píše sa s mäkkým i alebo je falošné)?
+@feedbackMessage
+ +Získal si @score bodov z @(totalRounds * 100).
+ +Škriatok Mäkkýš musel pred tebou zutekať!
+Dobrá práca! Precvič si to ešte raz a získaj plný počet hviezd.
+@q.Explanation
+ + ++ Oslobodil si provinciu @Category.Title a získal Zlatú Pečať! +
+ ++ Nevadí! Zopakuj si vláčik slov a hádanky a skús vyzvať škriatka znova. +
+ +Klikni na tlačidlo alebo priamo na vagónik, aby ti ho slovenský hlas zreteľne prečítal.
+ + +Jeden vagónik sa stratil! Pozri sa na predchádzajúce slová a doplň ten správny.
+ + +Vyber správne slovo:
+Klikaj na slová v správnom poradí, v akom idú vybrané slová za sebou.
+ + +Vláčik má všetky vagóny v správnom poradí.
+ +Ktoré vybrané slovo skrýva tento význam?
++ Príklad vo vete: „@current.ExampleSentence“ +
+ +Uhádol si @correctCount z @totalQuestions významov slov.
+ +Teraz už presne vieš, čo jednotlivé vybrané slová znamenajú v bežnom živote.
+
+ + Zákerný škriatok Mäkkýš rozhádzal pravopis a pomiešal vybrané slová s mäkkým I! + Tvoji sprievodcovia 🧚♀️ Víla Ypsilka a 🧙♂️ Škriatok Ypsík ťa prevedú provinciami, pomôžu ti opraviť mosty a stať sa Veľkým Strážcom Ypsilonu! +
+Vyber si provinciu a začni memorovať a hrať sa:
+@cat.Subtitle
+@cat.Description
++ Namiesto bifľovania celého radu naraz sa slová učia v miniskupinách (chunking po 3-5 slovách) sprevádzané rytmickým zvončekom a hlasovým prečítaním. +
++ Deti okamžite rozoznávajú slová s mäkkým I (*bič, miska, pivo, sirup*), ktoré do vybraných slov nepatria, čím sa buduje silný pravopisný reflex. +
++ Deti často zlyhávajú, pretože nepoznajú význam slov ako *byľ, vyžla, poryv, pomyje*. Vizuálny lexikón a hádanky im významy prirodzene vysvetlia. +
+Prehľad všetkých vybraných slov kráľovstva Ypsilonkovo s významami a slovenským hlasom
+Skús upraviť filter alebo hľadaný text.
+Sorry, the content you are looking for does not exist.
\ No newline at end of file diff --git a/src/Ypsilonkovo/Pages/ProvinceGame.razor b/src/Ypsilonkovo/Pages/ProvinceGame.razor new file mode 100644 index 0000000..3de80c8 --- /dev/null +++ b/src/Ypsilonkovo/Pages/ProvinceGame.razor @@ -0,0 +1,221 @@ +@page "/province/{letter}" +@inject WordRepository Repository +@inject StorageService Storage +@inject NavigationManager Nav +@inject AudioService Audio + +@if (category == null) +{ +@category.Subtitle
++ Nauč sa slová v rytme, doplň chýbajúci vagón a poskladaj celý rad od začiatku po koniec. +
++ Škriatok Mäkkýš zamiešal medzi vybrané slová slová s mäkkým I. Odhaľ ich rýchlo! +
++ Hádanky o tom, čo vybrané slová znamenajú v skutočnom svete. Spoznaj aj staré archaizmy! +
++ Prever si všetko, čo si sa naučil. Poraz škriatka a získaj Zlatú Pečať provincie! +
+
+
+ Otvárame brány kráľovstva vybraných slov...
+ +`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\n\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n\n// Abbreviations\n//\n// 1. Add the correct text decoration in Chrome, Edge, Opera, and Safari.\n// 2. Add explicit cursor to indicate changed behavior.\n// 3. Prevent the text-decoration to be skipped.\n\nabbr[title] {\n text-decoration: underline dotted; // 1\n cursor: help; // 2\n text-decoration-skip-ink: none; // 3\n}\n\n\n// Address\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\n\n// Lists\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\n// 1. Undo browser default\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // 1\n}\n\n\n// Blockquote\n\nblockquote {\n margin: 0 0 1rem;\n}\n\n\n// Strong\n//\n// Add the correct font weight in Chrome, Edge, and Safari\n\nb,\nstrong {\n font-weight: $font-weight-bolder;\n}\n\n\n// Small\n//\n// Add the correct font size in all browsers\n\nsmall {\n @include font-size($small-font-size);\n}\n\n\n// Mark\n\nmark {\n padding: $mark-padding;\n color: var(--#{$prefix}highlight-color);\n background-color: var(--#{$prefix}highlight-bg);\n}\n\n\n// Sub and Sup\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n\nsub,\nsup {\n position: relative;\n @include font-size($sub-sup-font-size);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n// Links\n\na {\n color: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-opacity, 1));\n text-decoration: $link-decoration;\n\n &:hover {\n --#{$prefix}link-color-rgb: var(--#{$prefix}link-hover-color-rgb);\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n &,\n &:hover {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n// Code\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-code;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\n// 1. Remove browser default top margin\n// 2. Reset browser default of `1em` to use `rem`s\n// 3. Don't allow content to break outside\n\npre {\n display: block;\n margin-top: 0; // 1\n margin-bottom: 1rem; // 2\n overflow: auto; // 3\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\ncode {\n @include font-size($code-font-size);\n color: var(--#{$prefix}code-color);\n word-wrap: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n\n kbd {\n padding: 0;\n @include font-size(1em);\n font-weight: $nested-kbd-font-weight;\n }\n}\n\n\n// Figures\n//\n// Apply a consistent margin strategy (matches our type styles).\n\nfigure {\n margin: 0 0 1rem;\n}\n\n\n// Images and content\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\n\n// Tables\n//\n// Prevent double borders\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: $table-cell-padding-y;\n padding-bottom: $table-cell-padding-y;\n color: $table-caption-color;\n text-align: left;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `