changes
@@ -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")
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,19 +157,32 @@
|
||||
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);
|
||||
|
||||
SelectedLevel = level;
|
||||
private void ConfirmAndStartPendingLevel()
|
||||
{
|
||||
if (PendingLevel != null)
|
||||
{
|
||||
SelectedLevel = PendingLevel;
|
||||
PendingLevel = null;
|
||||
CurrentScreen = ScreenType.Battle;
|
||||
IsTransitioning = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelPendingLevel()
|
||||
{
|
||||
PendingLevel = null;
|
||||
IsTransitioning = false;
|
||||
CurrentScreen = ScreenType.WorldMap;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task HandleLevelCompleted(Level completedLevel)
|
||||
{
|
||||
@@ -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
|
||||
|
||||
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 994 KiB |
|
After Width: | Height: | Size: 999 KiB |
|
After Width: | Height: | Size: 1007 KiB |
|
After Width: | Height: | Size: 991 KiB |
|
After Width: | Height: | Size: 837 KiB |
|
After Width: | Height: | Size: 841 KiB |
|
After Width: | Height: | Size: 848 KiB |
|
After Width: | Height: | Size: 835 KiB |
|
After Width: | Height: | Size: 802 KiB |
|
After Width: | Height: | Size: 805 KiB |
|
After Width: | Height: | Size: 810 KiB |
|
After Width: | Height: | Size: 797 KiB |
|
After Width: | Height: | Size: 895 KiB |
|
After Width: | Height: | Size: 901 KiB |
|
After Width: | Height: | Size: 915 KiB |
|
After Width: | Height: | Size: 903 KiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 959 KiB |
|
After Width: | Height: | Size: 968 KiB |
|
After Width: | Height: | Size: 966 KiB |
|
After Width: | Height: | Size: 914 KiB |
|
After Width: | Height: | Size: 822 KiB |
|
After Width: | Height: | Size: 829 KiB |
|
After Width: | Height: | Size: 826 KiB |
|
After Width: | Height: | Size: 784 KiB |
|
After Width: | Height: | Size: 766 KiB |
|
After Width: | Height: | Size: 771 KiB |
|
After Width: | Height: | Size: 770 KiB |
|
After Width: | Height: | Size: 730 KiB |
|
After Width: | Height: | Size: 851 KiB |
|
After Width: | Height: | Size: 861 KiB |
|
After Width: | Height: | Size: 870 KiB |
|
After Width: | Height: | Size: 844 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |