This commit is contained in:
Michal Vrba
2026-09-22 14:07:48 +02:00
parent c999743438
commit a30cc1d9d1
139 changed files with 976 additions and 262 deletions
+185 -11
View File
@@ -107,6 +107,58 @@
}
</div>
<!-- PAUSE & STEP-BY-STEP EXPLANATION MODAL (WHEN ANSWER IS INCORRECT) -->
@if (ShowExplanationModal && ExplanationProblem != null)
{
<div class="explanation-modal-overlay anim-fade-in">
<div class="explanation-parchment-box anim-victory-modal-pop">
<div class="explanation-header">
<span class="explanation-owl-icon">🦉</span>
<span class="explanation-badge">📖 MÚDRA ROZPRÁVKOVÁ RADA</span>
<h2 class="explanation-title">Pozor na chybičku!</h2>
</div>
<div class="explanation-body">
<!-- QUESTION & ANSWERS COMPARISON ROW -->
<div class="explanation-equation-card">
<div class="equation-question-row">
<span class="equation-label">Príklad:</span>
<span class="equation-text">@ExplanationProblem.QuestionText</span>
</div>
<div class="equation-answers-row">
<div class="answer-box user-answer">
<span class="ans-label">Tvoja odpoveď:</span>
<span class="ans-val">@(string.IsNullOrWhiteSpace(ExplanationUserAnswer) ? "Čas vypršal ⏱️" : ExplanationUserAnswer) ❌</span>
</div>
<div class="answer-box correct-answer">
<span class="ans-label">Správny výsledok:</span>
<span class="ans-val">@ExplanationProblem.CorrectAnswer ✅</span>
</div>
</div>
</div>
<!-- STEP BY STEP EXPLANATION -->
<div class="explanation-step-card">
<div class="step-card-header">
<span class="sparkle-icon">💡</span>
<strong>Ako na to (Postup výpočtu):</strong>
</div>
<p class="step-explanation-text">
@ExplanationProblem.Explanation
</p>
</div>
</div>
<div class="explanation-actions">
<button class="btn-grand-celebration btn-explanation-continue" @onclick="DismissExplanation">
@(IsExplanationFromDefense ? "🛡️ ROZUMIEM, POKRAČOVAŤ ➜" : "⚔️ ROZUMIEM, IDEME NA OBRANU! ➜")
</button>
</div>
</div>
</div>
}
<!-- FULLSCREEN VICTORY / DEFEAT CELEBRATION OVERLAY -->
@if (State.IsBattleOver)
{
@@ -213,6 +265,11 @@
private System.Threading.Timer? _timer;
private double RemainingTimeSeconds { get; set; } = 6.0;
private bool ShowExplanationModal { get; set; } = false;
private bool IsExplanationFromDefense { get; set; } = false;
private string ExplanationUserAnswer { get; set; } = string.Empty;
private MathProblem? ExplanationProblem { get; set; }
private Level? NextLevel => DataLoader.GetNextLevel(PlayerGrade, CurrentLevel.Id);
private string? _loadedLevelId;
@@ -241,6 +298,8 @@
private void StartBattle()
{
ShowExplanationModal = false;
ExplanationProblem = null;
BattleEngine.StartBattle(Hero, CurrentLevel, Config);
CurrentInput = string.Empty;
StartTimer();
@@ -249,58 +308,162 @@
private void StartTimer()
{
_timer?.Dispose();
State.ProblemStartTime = DateTime.UtcNow;
RemainingTimeSeconds = State.IsDefensePhase ? Config.Battle.DefenseTestDurationSeconds : Config.Battle.StandardTimeSeconds;
_timer = new System.Threading.Timer(async _ =>
{
if (ShowExplanationModal || State.IsBattleOver) return;
var elapsed = (DateTime.UtcNow - State.ProblemStartTime).TotalSeconds;
double limit = State.IsDefensePhase ? Config.Battle.DefenseTestDurationSeconds : Config.Battle.StandardTimeSeconds;
RemainingTimeSeconds = Math.Max(0, limit - elapsed);
if (RemainingTimeSeconds <= 0)
{
_timer?.Dispose();
await InvokeAsync(async () =>
{
if (State.IsDefensePhase)
{
var prob = State.CurrentProblem;
var result = await BattleEngine.SubmitDefenseAnswerAsync("");
ExplanationProblem = prob;
ExplanationUserAnswer = "Čas vypršal ⏱️";
IsExplanationFromDefense = true;
ShowExplanationModal = true;
StateHasChanged();
}
else
{
var prob = State.CurrentProblem;
var result = await BattleEngine.SubmitAnswerAsync("");
ExplanationProblem = prob;
ExplanationUserAnswer = "Čas vypršal ⏱️";
IsExplanationFromDefense = false;
ShowExplanationModal = true;
StateHasChanged();
}
});
return;
}
await InvokeAsync(StateHasChanged);
}, null, 100, 100);
}
private async Task HandleInputSubmit(string input)
{
if (State.IsBattleOver) return;
if (State.IsBattleOver || ShowExplanationModal) return;
if (State.IsDefensePhase)
{
await BattleEngine.SubmitDefenseAnswerAsync(input);
var problemBeforeSubmit = State.CurrentProblem;
var result = await BattleEngine.SubmitDefenseAnswerAsync(input);
CurrentInput = string.Empty;
if (result is CombatResultType.DefenseFailed or CombatResultType.Defeat)
{
_timer?.Dispose();
ExplanationProblem = problemBeforeSubmit;
ExplanationUserAnswer = input;
IsExplanationFromDefense = true;
ShowExplanationModal = true;
StateHasChanged();
return;
}
}
else
{
await BattleEngine.SubmitAnswerAsync(input);
var problemBeforeSubmit = State.CurrentProblem;
var result = await BattleEngine.SubmitAnswerAsync(input);
CurrentInput = string.Empty;
if (result == CombatResultType.PlayerMissed)
{
_timer?.Dispose();
ExplanationProblem = problemBeforeSubmit;
ExplanationUserAnswer = input;
IsExplanationFromDefense = false;
ShowExplanationModal = true;
StateHasChanged();
return;
}
}
CurrentInput = string.Empty;
await ProcessPostTurn();
}
private async Task HandleChoiceSelected(string choice)
{
if (State.IsBattleOver) return;
if (State.IsBattleOver || ShowExplanationModal) return;
if (State.IsDefensePhase)
{
await BattleEngine.SubmitDefenseAnswerAsync(choice);
var problemBeforeSubmit = State.CurrentProblem;
var result = await BattleEngine.SubmitDefenseAnswerAsync(choice);
if (result is CombatResultType.DefenseFailed or CombatResultType.Defeat)
{
_timer?.Dispose();
ExplanationProblem = problemBeforeSubmit;
ExplanationUserAnswer = choice;
IsExplanationFromDefense = true;
ShowExplanationModal = true;
StateHasChanged();
return;
}
}
else
{
await BattleEngine.SubmitAnswerAsync(choice);
var problemBeforeSubmit = State.CurrentProblem;
var result = await BattleEngine.SubmitAnswerAsync(choice);
if (result == CombatResultType.PlayerMissed)
{
_timer?.Dispose();
ExplanationProblem = problemBeforeSubmit;
ExplanationUserAnswer = choice;
IsExplanationFromDefense = false;
ShowExplanationModal = true;
StateHasChanged();
return;
}
}
await ProcessPostTurn();
}
private async Task DismissExplanation()
{
ShowExplanationModal = false;
if (IsExplanationFromDefense)
{
if (State.IsBattleOver)
{
StateHasChanged();
return;
}
BattleEngine.NextProblem();
StartTimer();
StateHasChanged();
}
else
{
// Start fresh timer for the defense phase problem
StartTimer();
StateHasChanged();
}
}
private async Task ProcessPostTurn()
{
StateHasChanged();
if (!State.IsBattleOver)
{
// Short delay to display attack/hurt animation before next question
await Task.Delay(1000);
await Task.Delay(900);
if (!State.IsDefensePhase)
{
BattleEngine.NextProblem();
@@ -370,8 +533,10 @@
private string GetTimerColorClass()
{
if (RemainingTimeSeconds > 3.0) return "timer-green";
if (RemainingTimeSeconds > 1.5) return "timer-yellow";
double limit = State.IsDefensePhase ? Config.Battle.DefenseTestDurationSeconds : Config.Battle.StandardTimeSeconds;
double ratio = limit > 0 ? (RemainingTimeSeconds / limit) : 0;
if (ratio > 0.45) return "timer-green";
if (ratio > 0.20) return "timer-yellow";
return "timer-red";
}
@@ -400,6 +565,15 @@
private async Task HandleKeyDown(KeyboardEventArgs e)
{
if (ShowExplanationModal)
{
if (e.Key is "Enter" or " " or "Escape")
{
await DismissExplanation();
}
return;
}
if (State.IsBattleOver)
{
if (e.Key == "Enter")
+3 -3
View File
@@ -8,11 +8,11 @@ public class GameConfig
public class BattleConfig
{
public double CriticalTimeSeconds { get; set; } = 3.0;
public double StandardTimeSeconds { get; set; } = 6.0;
public double CriticalTimeSeconds { get; set; } = 4.0;
public double StandardTimeSeconds { get; set; } = 10.0;
public double CriticalDamageMultiplier { get; set; } = 1.5;
public double WeakDamageMultiplier { get; set; } = 0.5;
public double DefenseTestDurationSeconds { get; set; } = 5.0;
public double DefenseTestDurationSeconds { get; set; } = 16.0;
public int DefaultPlayerHp { get; set; } = 5;
public int ComboStreakBonusDmg { get; set; } = 1;
}
+1
View File
@@ -43,6 +43,7 @@ public class MathProblem
public string Operation { get; set; } = "+";
public string DisplayB { get; set; } = string.Empty;
public string CorrectAnswer { get; set; } = string.Empty;
public string Explanation { get; set; } = string.Empty;
public List<string> Choices { get; set; } = new();
public string InputType { get; set; } = "DirectInput";
public bool IsDefenseTest { get; set; } = false;
+67 -18
View File
@@ -51,24 +51,60 @@
}
<!-- FAIRYTALE LEVEL TRANSITION SCREEN -->
@if (IsTransitioning)
@if (IsTransitioning && PendingLevel != null)
{
var hero = DataLoader.GetHero(Profile.SelectedHeroId) ?? DataLoader.Heroes.FirstOrDefault();
var heroAvatar = hero != null ? $"{hero.AssetFolder}_idle_p1.png" : "assets/images/heroes/knight_idle_p1.png";
var enemyAvatar = $"{PendingLevel.Enemy.AssetFolder}_idle_p1.png";
var heroDisplayName = !string.IsNullOrWhiteSpace(Profile.Name) ? Profile.Name : (hero?.Name ?? "Hrdina");
<div class="transition-screen-overlay anim-fade-in">
<div class="transition-parchment-box anim-victory-modal-pop">
<div class="transition-hero-marching">
<img src="@heroAvatar"
class="marching-hero-img anim-hero-march"
alt="Hrdina na ceste" />
<div class="transition-header">
<span class="transition-badge">@(PendingLevel.IsBoss ? "👑 BOSS LEVEL" : "⚔️ NOVÁ VÝZVA")</span>
<h2 class="transition-title">@PendingLevel.Name</h2>
</div>
<h2 class="transition-title">🗺️ Vstupuješ do novej oblasti...</h2>
<p class="transition-target">📍 @TransitionTargetText</p>
<div class="transition-sparkles">
<span class="sparkle">✨</span>
<span class="sparkle">⭐</span>
<span class="sparkle">✨</span>
<div class="transition-faceoff-stage">
<div class="faceoff-card hero-side">
<div class="faceoff-avatar-pedestal">
<img src="@heroAvatar"
class="faceoff-avatar-img anim-hero-march"
alt="@heroDisplayName" />
</div>
<span class="faceoff-name">@heroDisplayName</span>
<span class="faceoff-role">Udatný Počtár</span>
</div>
<div class="faceoff-vs-pill">
<span class="vs-text">VS</span>
<span class="vs-swords">⚔️</span>
</div>
<div class="faceoff-card enemy-side">
<div class="faceoff-avatar-pedestal">
<img src="@enemyAvatar"
class="faceoff-avatar-img anim-enemy-idle"
alt="@PendingLevel.Enemy.Name" />
</div>
<span class="faceoff-name">@PendingLevel.Enemy.Name</span>
<span class="faceoff-hp-badge">❤️ @PendingLevel.Enemy.MaxHp HP</span>
</div>
</div>
<div class="transition-details-card">
<p class="transition-math-info">
🧠 <strong>Úloha:</strong> @(PendingLevel.IsBoss ? "Záverečná skúška vedomostí!" : "Vyrieš matematické príklady a poraz protivníka!")
</p>
</div>
<div class="transition-action-buttons">
<button class="btn-grand-celebration btn-transition-start" @onclick="ConfirmAndStartPendingLevel">
⚔️ VSTÚPIŤ DO BOJA ➜
</button>
<button class="btn-secondary-celebration" @onclick="CancelPendingLevel">
🗺️ Späť na mapu
</button>
</div>
</div>
</div>
@@ -89,9 +125,9 @@
private ScreenType CurrentScreen { get; set; } = ScreenType.Loading;
private PlayerProfile Profile { get; set; } = new();
private Level? SelectedLevel { get; set; }
private Level? PendingLevel { get; set; }
private bool IsTransitioning { get; set; } = false;
private string TransitionTargetText { get; set; } = string.Empty;
protected override async Task OnInitializedAsync()
{
@@ -121,17 +157,30 @@
await Storage.SaveProfileAsync(Profile);
}
private async Task HandleLevelSelected(Level level)
private void HandleLevelSelected(Level level)
{
TransitionTargetText = $"{level.Name} (Protivník: {level.Enemy.Name})";
PendingLevel = level;
IsTransitioning = true;
StateHasChanged();
}
await Task.Delay(850);
private void ConfirmAndStartPendingLevel()
{
if (PendingLevel != null)
{
SelectedLevel = PendingLevel;
PendingLevel = null;
CurrentScreen = ScreenType.Battle;
IsTransitioning = false;
StateHasChanged();
}
}
SelectedLevel = level;
CurrentScreen = ScreenType.Battle;
private void CancelPendingLevel()
{
PendingLevel = null;
IsTransitioning = false;
CurrentScreen = ScreenType.WorldMap;
StateHasChanged();
}
@@ -150,7 +199,7 @@
await Storage.SaveProfileAsync(Profile);
}
await HandleLevelSelected(nextLevel);
HandleLevelSelected(nextLevel);
}
private void UnlockNextLevel(Level completedLevel)
@@ -107,6 +107,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = b.ToString(),
CorrectAnswer = sum.ToString(),
QuestionText = $"{a} + {b} = ?",
Explanation = GetAdditionExplanation(a, b, sum),
InputType = config.InputType
};
@@ -118,6 +119,36 @@ public class MathProblemGenerator : IMathProblemGenerator
return problem;
}
private string GetAdditionExplanation(int a, int b, int sum)
{
if (sum <= 10)
{
return $"Sčítanie: k číslu {a} pridáme {b} a dostaneme {sum}.";
}
if (a < 10 && b < 10 && sum > 10)
{
int toTen = 10 - a;
int rem = b - toTen;
return $"Tip: Rozlož si druhé číslo {b} na {toTen} a {rem}. Najprv doplň do desiatky ({a} + {toTen} = 10) a potom pripočítaj zvyšok (10 + {rem} = {sum})!";
}
if (a >= 10 && b < 10)
{
int unitsA = a % 10;
if (unitsA + b < 10)
{
return $"Sčítaj jednotky: {unitsA} + {b} = {unitsA + b}. Desiatky ({a / 10 * 10}) opíšeme: výsledok je {sum}.";
}
else
{
int toNextTen = 10 - unitsA;
int rem = b - toNextTen;
int nextTen = ((a / 10) + 1) * 10;
return $"Doplň do celej desiatky: {a} + {toNextTen} = {nextTen}, a potom pripočítaj zvyšných {rem}: {nextTen} + {rem} = {sum}!";
}
}
return $"Sčítanie: {a} + {b} = {sum}.";
}
private MathProblem GenerateSubtraction(MathConfig config, int hpPhase)
{
// Phase 4: Possibility of 3-term mixed chain
@@ -135,6 +166,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = "",
CorrectAnswer = res3.ToString(),
QuestionText = $"{a3} - {b3} + {c3} = ?",
Explanation = $"Počítaj postupne zľava doprava: najprv {a3} - {b3} = {a3 - b3}, a potom {a3 - b3} + {c3} = {res3}.",
InputType = config.InputType
};
if (config.InputType == "MultipleChoice")
@@ -184,6 +216,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = b.ToString(),
CorrectAnswer = diff.ToString(),
QuestionText = $"{a} - {b} = ?",
Explanation = GetSubtractionExplanation(a, b, diff),
InputType = config.InputType
};
@@ -195,6 +228,42 @@ public class MathProblemGenerator : IMathProblemGenerator
return problem;
}
private string GetSubtractionExplanation(int a, int b, int diff)
{
if (a <= 10)
{
return $"Odčítanie: od čísla {a} uberieme {b} a zostane nám {diff}.";
}
if (a > 10 && a <= 20 && b < 10)
{
int toTen = a - 10;
if (b <= toTen)
{
return $"Odčítaj jednotky: {toTen} - {b} = {toTen - b}. K desiatke pridáme {toTen - b} a máme {diff}.";
}
else
{
int rem = b - toTen;
return $"Tip: Rozlož si {b} na {toTen} a {rem}. Najprv odčítaj po desiatku ({a} - {toTen} = 10) a potom uber zvyšok (10 - {rem} = {diff})!";
}
}
if (a > 20 && b < 10)
{
int unitsA = a % 10;
if (unitsA >= b)
{
return $"Odčítaj jednotky: {unitsA} - {b} = {unitsA - b}. Desiatky ({a / 10 * 10}) zostávajú: výsledok je {diff}.";
}
else
{
int rem = b - unitsA;
int prevTen = (a / 10) * 10;
return $"Odčítaj najprv {unitsA} do desiatky ({a} - {unitsA} = {prevTen}) a potom odčítaj zvyšných {rem} ({prevTen} - {rem} = {diff})!";
}
}
return $"Odčítanie: {a} - {b} = {diff}.";
}
private MathProblem GenerateMultiplication(MathConfig config, int hpPhase)
{
var factors = config.Factors != null && config.Factors.Count > 0
@@ -232,6 +301,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = factorB.ToString(),
CorrectAnswer = product.ToString(),
QuestionText = $"{factorA} × {factorB} = ?",
Explanation = $"Násobenie: {factorA} × {factorB} znamená {factorB}-krát sčítať číslo {factorA}. Výsledok je {product}.",
InputType = config.InputType
};
@@ -280,6 +350,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = divisor.ToString(),
CorrectAnswer = result.ToString(),
QuestionText = $"{dividend} ÷ {divisor} = ?",
Explanation = $"Delenie: pýtame sa, koľkokrát sa {divisor} zmestí do {dividend}. Keďže {divisor} × {result} = {dividend}, výsledok je {result}!",
InputType = config.InputType
};
@@ -321,6 +392,7 @@ public class MathProblemGenerator : IMathProblemGenerator
}
string comp = leftVal < rightVal ? "<" : (leftVal > rightVal ? ">" : "=");
string compWord = leftVal < rightVal ? "menšie ako" : (leftVal > rightVal ? "väčšie ako" : "rovné");
return new MathProblem
{
@@ -329,6 +401,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = rightStr,
CorrectAnswer = comp,
QuestionText = $"{leftStr} ? {rightStr}",
Explanation = $"Vypočítajme obe strany: ( {leftStr} = {leftVal} ) a ( {rightStr} = {rightVal} ). Keďže {leftVal} je {compWord} {rightVal}, správny znak je {comp}.",
InputType = "MultipleChoice",
Choices = new List<string> { "<", "=", ">" }
};
@@ -343,6 +416,7 @@ public class MathProblemGenerator : IMathProblemGenerator
}
string answer = x < y ? "<" : (x > y ? ">" : "=");
string word = x < y ? "menšie ako" : (x > y ? "väčšie ako" : "rovné");
return new MathProblem
{
@@ -351,6 +425,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = y.ToString(),
CorrectAnswer = answer,
QuestionText = $"{x} ? {y}",
Explanation = $"Porovnanie: Číslo {x} je {word} číslu {y}, preto platí {x} {answer} {y}.",
InputType = "MultipleChoice",
Choices = new List<string> { "<", "=", ">" }
};
@@ -392,11 +467,10 @@ public class MathProblemGenerator : IMathProblemGenerator
private MathProblem GenerateChallengingComparisonDefense(MathConfig config)
{
// Compare expressions: (a + b) ? (c - d)
int valLeft, valRight;
string exprLeft, exprRight;
if (config.MaxA > 100) // Grade 3 large numbers
if (config.MaxA > 100)
{
int a = _rand.Next(10, 50) * 10;
int b = _rand.Next(5, 30) * 10;
@@ -408,7 +482,7 @@ public class MathProblemGenerator : IMathProblemGenerator
valRight = c - d;
exprRight = $"{c} - {d}";
}
else if (config.MaxSum > 20 || config.MaxA > 20) // Grade 2
else if (config.MaxSum > 20 || config.MaxA > 20)
{
int a = _rand.Next(10, 45);
int b = _rand.Next(5, 30);
@@ -420,7 +494,7 @@ public class MathProblemGenerator : IMathProblemGenerator
valRight = c - d;
exprRight = $"{c} - {d}";
}
else // Grade 1
else
{
int a = _rand.Next(2, 9);
int b = _rand.Next(2, 9);
@@ -433,7 +507,6 @@ public class MathProblemGenerator : IMathProblemGenerator
exprRight = $"{c} - {d}";
}
// Sometimes create equal expressions
if (_rand.Next(3) == 0)
{
valRight = valLeft;
@@ -442,6 +515,7 @@ public class MathProblemGenerator : IMathProblemGenerator
}
string answer = valLeft < valRight ? "<" : (valLeft > valRight ? ">" : "=");
string compWord = valLeft < valRight ? "menšie ako" : (valLeft > valRight ? "väčšie ako" : "rovné");
return new MathProblem
{
@@ -450,6 +524,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = exprRight,
CorrectAnswer = answer,
QuestionText = $"Porovnaj výrazy:\n( {exprLeft} ) ? ( {exprRight} )",
Explanation = $"Ľavá strana: {exprLeft} = {valLeft}. Pravá strana: {exprRight} = {valRight}. Keďže {valLeft} je {compWord} {valRight}, správny znak je {answer}.",
InputType = "MultipleChoice",
Choices = new List<string> { "<", "=", ">" },
IsDefenseTest = true
@@ -461,8 +536,9 @@ public class MathProblemGenerator : IMathProblemGenerator
bool isAdd = _rand.Next(2) == 0;
int missing, known, result;
string equation;
string explanation;
if (config.MaxSum > 100 || config.MaxA > 100) // Grade 3
if (config.MaxSum > 100 || config.MaxA > 100)
{
known = _rand.Next(10, 50) * 10;
missing = _rand.Next(10, 40) * 10;
@@ -470,15 +546,17 @@ public class MathProblemGenerator : IMathProblemGenerator
{
result = known + missing;
equation = _rand.Next(2) == 0 ? $"{known} + ❓ = {result}" : $"❓ + {known} = {result}";
explanation = $"Neznáme číslo nájdeme odčítaním: {result} - {known} = {missing}.";
}
else
{
result = known;
int total = known + missing;
equation = $"{total} - ❓ = {result}";
explanation = $"Neznáme číslo zistíme odčítaním výsledku od celku: {total} - {result} = {missing}.";
}
}
else if (config.MaxSum > 20 || config.MaxA > 20) // Grade 2
else if (config.MaxSum > 20 || config.MaxA > 20)
{
known = _rand.Next(12, 50);
missing = _rand.Next(8, 35);
@@ -486,15 +564,17 @@ public class MathProblemGenerator : IMathProblemGenerator
{
result = known + missing;
equation = _rand.Next(2) == 0 ? $"{known} + ❓ = {result}" : $"❓ + {known} = {result}";
explanation = $"Neznáme číslo nájdeme odčítaním: {result} - {known} = {missing}.";
}
else
{
result = known;
int total = known + missing;
equation = $"{total} - ❓ = {result}";
explanation = $"Neznáme číslo zistíme odčítaním výsledku od celku: {total} - {result} = {missing}.";
}
}
else // Grade 1
else
{
known = _rand.Next(3, 10);
missing = _rand.Next(3, 10);
@@ -502,12 +582,14 @@ public class MathProblemGenerator : IMathProblemGenerator
{
result = known + missing;
equation = _rand.Next(2) == 0 ? $"{known} + ❓ = {result}" : $"❓ + {known} = {result}";
explanation = $"Neznáme číslo nájdeme odčítaním: {result} - {known} = {missing}.";
}
else
{
result = known;
int total = known + missing;
equation = $"{total} - ❓ = {result}";
explanation = $"Neznáme číslo zistíme odčítaním: {total} - {result} = {missing}.";
}
}
@@ -518,6 +600,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = "",
CorrectAnswer = missing.ToString(),
QuestionText = $"Doplň chýbajúce číslo ❓:\n{equation}",
Explanation = explanation,
InputType = "MultipleChoice",
Choices = GenerateNumericChoices(missing, 1, 1000),
IsDefenseTest = true
@@ -529,7 +612,7 @@ public class MathProblemGenerator : IMathProblemGenerator
int a, b, c, result;
string expr;
if (config.MaxSum > 100 || config.MaxA > 100) // Grade 3
if (config.MaxSum > 100 || config.MaxA > 100)
{
a = _rand.Next(15, 45) * 10;
b = _rand.Next(10, 30) * 10;
@@ -537,7 +620,7 @@ public class MathProblemGenerator : IMathProblemGenerator
result = a + b - c;
expr = $"{a} + {b} - {c}";
}
else if (config.MaxSum > 20 || config.MaxA > 20) // Grade 2
else if (config.MaxSum > 20 || config.MaxA > 20)
{
a = _rand.Next(15, 50);
b = _rand.Next(10, 30);
@@ -545,7 +628,7 @@ public class MathProblemGenerator : IMathProblemGenerator
result = a + b - c;
expr = $"{a} + {b} - {c}";
}
else // Grade 1
else
{
a = _rand.Next(4, 9);
b = _rand.Next(3, 8);
@@ -561,6 +644,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = "",
CorrectAnswer = result.ToString(),
QuestionText = $"Vypočítaj trojčlenný reťazec:\n{expr} = ?",
Explanation = $"Počítaj po krokoch zľava doprava: najprv {a} + {b} = {a + b}, a potom {a + b} - {c} = {result}.",
InputType = "MultipleChoice",
Choices = GenerateNumericChoices(result, 0, 1000),
IsDefenseTest = true
@@ -585,6 +669,9 @@ public class MathProblemGenerator : IMathProblemGenerator
string equation = isDiv
? $"{product} ÷ ❓ = {factorA}"
: (_rand.Next(2) == 0 ? $"{factorA} × ❓ = {product}" : $"❓ × {factorA} = {product}");
string explanation = isDiv
? $"Neznámeho deliteľa nájdeme delením: {product} ÷ {factorA} = {missing}."
: $"Neznámeho činiteľa nájdeme delením: {product} ÷ {factorA} = {missing}.";
return new MathProblem
{
@@ -593,6 +680,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = "",
CorrectAnswer = missing.ToString(),
QuestionText = $"Nájdi neznáme číslo ❓:\n{equation}",
Explanation = explanation,
InputType = "MultipleChoice",
Choices = GenerateNumericChoices(missing, 1, 10),
IsDefenseTest = true
@@ -617,6 +705,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = "",
CorrectAnswer = result.ToString(),
QuestionText = $"Kombinovaný výpočet (najprv násob!):\n{expr} = ?",
Explanation = $"Násobenie má vždy prednosť! Najprv: {f1} × {f2} = {prod}, a potom: {prod} {(isSub ? "-" : "+")} {add} = {result}.",
InputType = "MultipleChoice",
Choices = GenerateNumericChoices(result, 1, 100),
IsDefenseTest = true
@@ -627,6 +716,7 @@ public class MathProblemGenerator : IMathProblemGenerator
{
bool isCorrect = _rand.Next(2) == 0;
string equation;
string explanation;
if (isMult)
{
@@ -636,6 +726,9 @@ public class MathProblemGenerator : IMathProblemGenerator
int displayed = isCorrect ? prod : (prod + (_rand.Next(2) == 0 ? _rand.Next(1, 4) : -_rand.Next(1, 4)));
if (displayed <= 0) displayed = prod + 2;
equation = $"{a} × {b} = {displayed}";
explanation = isCorrect
? $"Rovnica {equation} je správna, pretože {a} × {b} sa skutočne rovná {prod}."
: $"Rovnica {equation} je nesprávna! Správny výsledok {a} × {b} je {prod} (nie {displayed}).";
}
else
{
@@ -646,6 +739,9 @@ public class MathProblemGenerator : IMathProblemGenerator
int displayed = isCorrect ? sum : (sum + offset);
if (displayed <= 0) displayed = sum + 2;
equation = $"{a} + {b} = {displayed}";
explanation = isCorrect
? $"Rovnica {equation} je správna, pretože {a} + {b} sa skutočne rovná {sum}."
: $"Rovnica {equation} je nesprávna! Správny výsledok {a} + {b} je {sum} (nie {displayed}).";
}
return new MathProblem
@@ -655,6 +751,7 @@ public class MathProblemGenerator : IMathProblemGenerator
DisplayB = "",
CorrectAnswer = isCorrect ? "ÁNO" : "NIE",
QuestionText = $"Je táto rovnica správna?\n{equation}",
Explanation = explanation,
InputType = "MultipleChoice",
Choices = new List<string> { "ÁNO", "NIE" },
IsDefenseTest = true
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 999 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1007 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 837 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 841 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 848 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 895 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 959 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 770 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Some files were not shown because too many files have changed in this diff Show More