230 lines
7.9 KiB
Text
230 lines
7.9 KiB
Text
@page "/"
|
|
@using MemoryGame.Models
|
|
@using MemoryGame.Services
|
|
@inject GameService GameService
|
|
@inject NavigationManager Navigation
|
|
|
|
<PageTitle>Memory-Spiel</PageTitle>
|
|
|
|
<div class="memory-game-container">
|
|
@if (!_initialized)
|
|
{
|
|
<div class="loading">
|
|
<h2>Lädt...</h2>
|
|
</div>
|
|
}
|
|
else if (_currentSession == null)
|
|
{
|
|
<div class="start-screen">
|
|
<h1>Memory-Spiel</h1>
|
|
<p class="subtitle">Übe das Zuordnen von Bildern zu Wörtern</p>
|
|
<button class="btn-start" @onclick="StartNewGame">Neues Spiel starten</button>
|
|
</div>
|
|
}
|
|
else if (_currentSession.IsComplete && !_showStatistics)
|
|
{
|
|
<div class="results-screen">
|
|
<h1>Spiel beendet!</h1>
|
|
<div class="results">
|
|
<div class="result-item correct">
|
|
<span class="result-label">Richtig:</span>
|
|
<span class="result-value">@_currentSession.CorrectAnswers</span>
|
|
</div>
|
|
<div class="result-item incorrect">
|
|
<span class="result-label">Falsch:</span>
|
|
<span class="result-value">@_currentSession.IncorrectAnswers</span>
|
|
</div>
|
|
</div>
|
|
<button class="btn-start" @onclick="StartNewGame">Nochmal spielen</button>
|
|
<button class="btn-stats" @onclick="ShowStatistics">Statistik anzeigen</button>
|
|
</div>
|
|
}
|
|
else if (_currentSession.IsComplete && _showStatistics)
|
|
{
|
|
var words = GameService.GetWords()
|
|
.OrderBy(w => w.CorrectCount + w.IncorrectCount == 0 ? 1 : 0)
|
|
.ThenBy(w => w.CorrectCount + w.IncorrectCount == 0
|
|
? 0
|
|
: (double)w.CorrectCount / (w.CorrectCount + w.IncorrectCount))
|
|
.ToList();
|
|
|
|
var playedWords = words.Where(w => w.CorrectCount + w.IncorrectCount > 0).ToList();
|
|
var overallAccuracy = playedWords.Count == 0
|
|
? 0
|
|
: (int)Math.Round(100.0 * playedWords.Sum(w => w.CorrectCount) / playedWords.Sum(w => w.CorrectCount + w.IncorrectCount));
|
|
|
|
<div class="stats-screen">
|
|
<h1>Statistik</h1>
|
|
|
|
<div class="stats-summary">
|
|
@playedWords.Count von @words.Count Wörtern geübt
|
|
@if (playedWords.Count > 0)
|
|
{
|
|
<span> · @overallAccuracy% richtig</span>
|
|
}
|
|
</div>
|
|
|
|
@if (_confirmReset)
|
|
{
|
|
<div class="reset-confirm">
|
|
<span>Alle Statistiken wirklich zurücksetzen?</span>
|
|
<button class="btn-confirm-yes" @onclick="ConfirmReset">Ja, zurücksetzen</button>
|
|
<button class="btn-confirm-no" @onclick="() => _confirmReset = false">Abbrechen</button>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<button class="btn-reset" @onclick="() => _confirmReset = true">Zurücksetzen</button>
|
|
}
|
|
|
|
<button class="btn-start" @onclick="GoToStart">Zurück zum Start</button>
|
|
|
|
<div class="stats-list">
|
|
@foreach (var word in words)
|
|
{
|
|
var total = word.CorrectCount + word.IncorrectCount;
|
|
var accuracy = total == 0 ? 0 : (int)Math.Round(100.0 * word.CorrectCount / total);
|
|
var barClass = total == 0 ? "bar-unplayed" : accuracy >= 70 ? "bar-green" : accuracy >= 40 ? "bar-orange" : "bar-red";
|
|
|
|
<div class="stats-row">
|
|
<img src="@word.ImagePath" alt="@word.Word" class="stats-thumbnail" />
|
|
<div class="stats-word-info">
|
|
<span class="stats-word-name">@word.Word</span>
|
|
<div class="stats-bar-container">
|
|
<div class="stats-bar @barClass" style="width: @(total == 0 ? 0 : accuracy)%"></div>
|
|
</div>
|
|
</div>
|
|
<span class="stats-accuracy">@(total == 0 ? "—" : $"{accuracy}% richtig")</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
var round = _currentSession.CurrentRound;
|
|
if (round != null)
|
|
{
|
|
<div class="game-screen">
|
|
<div class="game-header">
|
|
<div class="round-counter">
|
|
Runde @(_currentSession.CurrentRoundIndex + 1) von @_currentSession.Rounds.Count
|
|
</div>
|
|
</div>
|
|
|
|
@if (round.Type == RoundType.ImageWithWords)
|
|
{
|
|
<div class="question-area">
|
|
<img src="@round.CorrectAnswer.ImagePath" alt="Question image" class="question-image" />
|
|
</div>
|
|
<div class="options-area">
|
|
@foreach (var option in round.Options)
|
|
{
|
|
<button class="option-button word-option" @onclick="() => SelectAnswer(option)">
|
|
@option.Word
|
|
</button>
|
|
}
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="question-area">
|
|
<div class="question-word">@round.CorrectAnswer.Word</div>
|
|
</div>
|
|
<div class="options-area image-options">
|
|
@foreach (var option in round.Options)
|
|
{
|
|
<button class="option-button image-option" @onclick="() => SelectAnswer(option)">
|
|
<img src="@option.ImagePath" alt="@option.Word" />
|
|
</button>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
@if (_showFeedback && round.SelectedAnswer != null)
|
|
{
|
|
<div class="feedback @(_feedbackClass)">
|
|
@_feedbackMessage
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
}
|
|
</div>
|
|
|
|
@code {
|
|
private bool _initialized;
|
|
private GameSession? _currentSession;
|
|
private bool _showFeedback;
|
|
private string _feedbackMessage = "";
|
|
private string _feedbackClass = "";
|
|
private bool _showStatistics;
|
|
private bool _confirmReset;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
await GameService.InitializeAsync();
|
|
_initialized = true;
|
|
}
|
|
|
|
private void StartNewGame()
|
|
{
|
|
_currentSession = GameService.CreateNewGame();
|
|
_showFeedback = false;
|
|
}
|
|
|
|
private async Task SelectAnswer(GameWord selectedWord)
|
|
{
|
|
if (_currentSession?.CurrentRound == null || _showFeedback)
|
|
return;
|
|
|
|
var round = _currentSession.CurrentRound;
|
|
round.SelectedAnswer = selectedWord;
|
|
|
|
_showFeedback = true;
|
|
if (round.IsCorrect)
|
|
{
|
|
_feedbackMessage = "Richtig! ✓";
|
|
_feedbackClass = "correct";
|
|
}
|
|
else
|
|
{
|
|
_feedbackMessage = $"Falsch. Die richtige Antwort ist: {round.CorrectAnswer.Word}";
|
|
_feedbackClass = "incorrect";
|
|
}
|
|
|
|
await GameService.UpdateStatisticsAsync(round);
|
|
StateHasChanged();
|
|
|
|
await Task.Delay(2000);
|
|
|
|
_showFeedback = false;
|
|
_currentSession.CurrentRoundIndex++;
|
|
|
|
if (_currentSession.IsComplete)
|
|
{
|
|
_currentSession.EndTime = DateTimeOffset.UtcNow;
|
|
}
|
|
|
|
StateHasChanged();
|
|
}
|
|
|
|
private void ShowStatistics()
|
|
{
|
|
_showStatistics = true;
|
|
}
|
|
|
|
private void GoToStart()
|
|
{
|
|
_currentSession = null;
|
|
_showStatistics = false;
|
|
_confirmReset = false;
|
|
}
|
|
|
|
private async Task ConfirmReset()
|
|
{
|
|
await GameService.ResetStatisticsAsync();
|
|
_confirmReset = false;
|
|
StateHasChanged();
|
|
}
|
|
}
|