Files
Ypsilonkovo/src/Ypsilonkovo/Components/BossChallenge.razor
T
2026-09-04 13:47:23 +02:00

274 lines
10 KiB
Plaintext

@inject AudioService Audio
<div class="boss-container">
<!-- Horný panel súboja -->
<div class="card p-4 rounded-4 shadow-sm mb-4 border-0 text-white"
style="background: linear-gradient(135deg, #475569, #0f172a);">
<div class="d-flex flex-wrap justify-content-between align-items-center gap-3">
<!-- Hráč -->
<div class="d-flex align-items-center gap-3">
<div class="fs-1 bg-primary rounded-circle p-2 px-3 shadow">🛡️</div>
<div>
<h5 class="fw-bold m-0">Strážca Ypsilonu</h5>
<div class="d-flex gap-1 fs-5 mt-1">
@for (int i = 0; i < 3; i++)
{
<span>@(i < playerHp ? "❤️" : "🖤")</span>
}
</div>
</div>
</div>
<div class="text-center">
<span class="badge bg-danger fs-5 px-4 py-2 rounded-pill shadow animate-pulse">
⚡ FINÁLNY SÚBOJ: PROVINCIA @Category.Letter ⚡
</span>
</div>
<!-- Škriatok Mäkkýš -->
<div class="d-flex align-items-center gap-3 text-end">
<div>
<h5 class="fw-bold m-0 text-warning">Škriatok Mäkkýš</h5>
<div class="progress mt-1 shadow-sm" style="width: 140px; height: 16px; background-color: rgba(255,255,255,0.2);">
<div class="progress-bar bg-danger" style="width: @(bossHp * 20)%;"></div>
</div>
</div>
<div class="fs-1 bg-danger rounded-circle p-2 px-3 shadow">🧙‍♂️</div>
</div>
</div>
</div>
@if (!isBossDefeated && playerHp > 0)
{
var q = questions[currentQIndex];
<div class="card p-4 rounded-4 shadow-sm text-center bg-white border-0">
<div class="mb-4">
<span class="badge bg-secondary px-3 py-1 rounded-pill mb-2">Otázka @(currentQIndex + 1) z @questions.Count</span>
<h3 class="fw-bold text-dark mt-2">@q.QuestionText</h3>
</div>
<div class="row g-3 justify-content-center">
@foreach (var opt in q.Options)
{
<div class="col-12 col-md-6">
<button class="btn btn-lg w-100 p-4 rounded-4 shadow-sm text-center fw-bold transition-transform hover-scale
@(isAnswered ? (opt == q.CorrectOption ? "btn-success" : (opt == selectedOption ? "btn-danger" : "btn-light")) : "btn-light border-2")"
style="font-size: 1.25rem;"
disabled="@isAnswered"
@onclick="() => CheckAnswer(opt)">
@opt
</button>
</div>
}
</div>
@if (isAnswered)
{
<div class="mt-4 p-3 rounded-4 @(isCorrect ? "bg-success bg-opacity-10 text-success" : "bg-danger bg-opacity-10 text-danger")">
<h5 class="fw-bold m-0">@(isCorrect ? "💥 Zásah! Škriatok stratil život!" : "🛡️ Jáj! Škriatok ťa prekabátil!")</h5>
<p class="m-0 mt-1">@q.Explanation</p>
<button class="btn btn-lg @(isCorrect ? "btn-success" : "btn-primary") rounded-pill px-5 shadow mt-3"
@onclick="NextQuestion">
Ďalej ➡️
</button>
</div>
}
</div>
}
else if (isBossDefeated)
{
<!-- Víťazstvo nad bossom -->
<div class="card p-5 rounded-4 shadow text-center bg-white border-0">
<span class="fs-1">👑</span>
<h1 class="fw-bold text-success mt-2">Škriatok Mäkkýš bol porazený!</h1>
<p class="fs-5 text-muted">
Oslobodil si provinciu <strong>@Category.Title</strong> a získal Zlatú Pečať!
</p>
<div class="my-4 p-4 rounded-4 bg-warning bg-opacity-25 d-inline-block">
<span class="fs-1">🎖️</span>
<h3 class="fw-bold text-dark m-0">Zlatá Pečať Ypsilonu (@Category.Letter)</h3>
</div>
<div class="mt-3">
<button class="btn btn-lg btn-success rounded-pill px-5 shadow" @onclick="FinishBoss">
Návrat na mapu kráľovstva 🗺️
</button>
</div>
</div>
}
else
{
<!-- Prehra hráča -->
<div class="card p-5 rounded-4 shadow text-center bg-white border-0">
<span class="fs-1">💔</span>
<h2 class="fw-bold text-danger mt-2">Škriatok Mäkkýš ťa tentoraz premohol!</h2>
<p class="fs-5 text-muted">
Nevadí! Zopakuj si vláčik slov a hádanky a skús vyzvať škriatka znova.
</p>
<div class="mt-4">
<button class="btn btn-lg btn-primary rounded-pill px-5 shadow" @onclick="RestartBoss">
🔄 Skúsiť znova
</button>
</div>
</div>
}
</div>
@code {
[Parameter] public LetterCategory Category { get; set; } = new();
[Parameter] public EventCallback<bool> OnDefeated { get; set; }
private class BossQuestion
{
public string QuestionText { get; set; } = string.Empty;
public List<string> Options { get; set; } = new();
public string CorrectOption { get; set; } = string.Empty;
public string Explanation { get; set; } = string.Empty;
}
private int playerHp = 3;
private int bossHp = 5;
private int currentQIndex = 0;
private bool isBossDefeated = false;
private bool isAnswered = false;
private bool isCorrect = false;
private string? selectedOption = null;
private List<BossQuestion> questions = new();
protected override void OnInitialized()
{
RestartBoss();
}
private void RestartBoss()
{
playerHp = 3;
bossHp = 5;
currentQIndex = 0;
isBossDefeated = false;
isAnswered = false;
selectedOption = null;
BuildQuestions();
}
private void BuildQuestions()
{
questions.Clear();
var rnd = new Random();
var words = Category.Words.OrderBy(_ => rnd.Next()).ToList();
// 1. Doplň chýbajúce slovo v reťazci
if (Category.Words.Count >= 3)
{
var w1 = Category.Words[0].Word;
var w2 = Category.Words[1].Word;
var w3 = Category.Words[2].Word;
questions.Add(new BossQuestion
{
QuestionText = $"Ktoré slovo nasleduje za sebou: „{w1}“, „{w2}“, [ ??? ] ?",
Options = new List<string> { w3, words.Last().Word, "bicykel" }.OrderBy(_ => rnd.Next()).ToList(),
CorrectOption = w3,
Explanation = $"Presne tak! Rad pokračuje slovom '{w3}'."
});
}
// 2. Chyť votrelca
var alien = Category.AlienPool.FirstOrDefault(a => a.IsAlien)?.Word ?? "bicykel";
var validW = words.First().Word;
var validW2 = words.Skip(1).First().Word;
questions.Add(new BossQuestion
{
QuestionText = "Ktoré z týchto slov je votrelec a NIE JE vybrané slovo?",
Options = new List<string> { alien, validW, validW2 }.OrderBy(_ => rnd.Next()).ToList(),
CorrectOption = alien,
Explanation = $"Výborne! Slovo '{alien}' nepatrí medzi vybrané slová."
});
// 3. Význam slova
var targetWord = words.FirstOrDefault(w => w.IsArchaicOrDifficult) ?? words.First();
var otherWord = words.FirstOrDefault(w => w.Word != targetWord.Word) ?? words.Last();
questions.Add(new BossQuestion
{
QuestionText = $"Čo znamená vybrané slovo „{targetWord.Word}“?",
Options = new List<string> { targetWord.Meaning, otherWord.Meaning, "Žlté auto na preteky" }.OrderBy(_ => rnd.Next()).ToList(),
CorrectOption = targetWord.Meaning,
Explanation = $"Správne! {targetWord.Word} znamená: {targetWord.Meaning}."
});
// 4. Doplnenie do vety
var sentenceWord = words.Skip(2).FirstOrDefault() ?? words.First();
var sentence = sentenceWord.ExampleSentence.Replace(sentenceWord.Word, "______", StringComparison.OrdinalIgnoreCase);
questions.Add(new BossQuestion
{
QuestionText = $"Doplň správne slovo do vety: „{sentence}“",
Options = new List<string> { sentenceWord.Word, words.Last().Word, "slnko" }.OrderBy(_ => rnd.Next()).ToList(),
CorrectOption = sentenceWord.Word,
Explanation = $"Skvelá pamäť! Patrí tam slovo '{sentenceWord.Word}'."
});
// 5. Finálna otázka
var lastWord = words.Last();
questions.Add(new BossQuestion
{
QuestionText = $"Aké písmeno po {Category.Letter} sa píše v slove „{lastWord.Word}“?",
Options = new List<string> { "Tvrdé Y/Ý", "Mäkké I/Í", "Dvojhláska Ô" }.OrderBy(_ => rnd.Next()).ToList(),
CorrectOption = "Tvrdé Y/Ý",
Explanation = $"Presne tak! Vybrané slová sa vždy píšu s tvrdým Y/Ý."
});
}
private async Task CheckAnswer(string opt)
{
isAnswered = true;
selectedOption = opt;
var q = questions[currentQIndex];
if (opt == q.CorrectOption)
{
isCorrect = true;
bossHp--;
await Audio.PlaySuccessAsync();
}
else
{
isCorrect = false;
playerHp--;
await Audio.PlayWrongAsync();
}
}
private async Task NextQuestion()
{
isAnswered = false;
selectedOption = null;
if (bossHp <= 0)
{
isBossDefeated = true;
await Audio.PlayFanfareAsync();
return;
}
if (playerHp <= 0)
{
return;
}
currentQIndex++;
if (currentQIndex >= questions.Count)
{
// Ak prešiel všetky otázky a prežil, boss padol
isBossDefeated = true;
await Audio.PlayFanfareAsync();
}
}
private async Task FinishBoss()
{
await OnDefeated.InvokeAsync(true);
}
}