From de8547749cf65b5bd628b2736c923f08f8730d15 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 11 Aug 2025 19:08:28 +0200 Subject: [PATCH] feat: replace Leaderboard with Highscore --- QuizApp/ViewModels/ViewModel.swift | 22 ++++++++ QuizApp/Views/CategorySelectionView.swift | 62 +++-------------------- QuizApp/Views/QuizFinishedView.swift | 29 +++++------ QuizApp/Views/QuizView.swift | 49 +++--------------- 4 files changed, 48 insertions(+), 114 deletions(-) diff --git a/QuizApp/ViewModels/ViewModel.swift b/QuizApp/ViewModels/ViewModel.swift index 3c4340d..9f298bf 100644 --- a/QuizApp/ViewModels/ViewModel.swift +++ b/QuizApp/ViewModels/ViewModel.swift @@ -91,4 +91,26 @@ class ViewModel: ObservableObject { return 0 } } + + func highscore(for category: String) -> Int { + let dict = UserDefaults.standard.dictionary(forKey: "categoryHighscores") as? [String: Int] ?? [:] + return dict[category] ?? 0 + } + + @discardableResult + func updateHighscoreIfNeeded() -> Bool { + guard let category = selectedCategory else { return false } + var dict = UserDefaults.standard.dictionary(forKey: "categoryHighscores") as? [String: Int] ?? [:] + let oldScore = dict[category] ?? 0 + if score > oldScore { + dict[category] = score + UserDefaults.standard.set(dict, forKey: "categoryHighscores") + return true + } + return false + } + + func allHighscores() -> [String: Int] { + UserDefaults.standard.dictionary(forKey: "categoryHighscores") as? [String: Int] ?? [:] + } } diff --git a/QuizApp/Views/CategorySelectionView.swift b/QuizApp/Views/CategorySelectionView.swift index 165c408..af806c9 100644 --- a/QuizApp/Views/CategorySelectionView.swift +++ b/QuizApp/Views/CategorySelectionView.swift @@ -10,11 +10,7 @@ import SwiftUI struct CategorySelectionView: View { @StateObject private var viewModel = ViewModel() @AppStorage("globalScore") var globalScore: Int = 0 - @State private var boardData: [[String: Any]] = [] - private func loadBoardData() { - boardData = UserDefaults.standard.array(forKey: "leaderboard") as? [[String: Any]] ?? [] - } var body: some View { NavigationStack { @@ -78,9 +74,14 @@ struct CategorySelectionView: View { .foregroundColor(.blue) .font(.title2) - Text(category) - .font(.headline) - .foregroundColor(.primary) + VStack(alignment: .leading, spacing: 4) { + Text(category) + .font(.headline) + .foregroundColor(.primary) + Text("Highscore: \(viewModel.highscore(for: category))") + .font(.caption) + .foregroundColor(.secondary) + } Spacer() @@ -103,58 +104,11 @@ struct CategorySelectionView: View { } .padding(.horizontal) - // Scoreboard - Text("Leaderboard") - .font(.title2) - .fontWeight(.semibold) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal) - if !boardData.isEmpty { - VStack(spacing: 8) { - ForEach(Array(boardData.prefix(5).enumerated()), id: \.offset) { index, scoreData in - HStack { - Text("\(index + 1).") - .font(.headline) - .foregroundColor(index < 3 ? .orange : .primary) - .frame(width: 25, alignment: .leading) - - Text(scoreData["name"] as? String ?? "Unbekannt") - .font(.body) - .foregroundColor(.primary) - - Spacer() - - Text("\(scoreData["score"] as? Int ?? 0) Punkte") - .font(.body) - .fontWeight(.medium) - .foregroundColor(.blue) - } - .padding(.horizontal, 16) - .padding(.vertical, 8) - .background( - RoundedRectangle(cornerRadius: 12) - .fill(Color(.systemGray6)) - .overlay( - RoundedRectangle(cornerRadius: 12) - .stroke(Color(.systemGray4), lineWidth: 1) - ) - - ) - } - } - .padding(.horizontal) - } else { - Text("Keine Leadboard Daten...") - } - Spacer() } .background(Color.white) .navigationBarHidden(true) .navigationTitle("Quiz-Auswahl") - .onAppear { - loadBoardData() - } } } } diff --git a/QuizApp/Views/QuizFinishedView.swift b/QuizApp/Views/QuizFinishedView.swift index df2d3d7..cfbe7ee 100644 --- a/QuizApp/Views/QuizFinishedView.swift +++ b/QuizApp/Views/QuizFinishedView.swift @@ -10,41 +10,36 @@ import SwiftUI struct QuizFinishedView: View { let score: Int let total: Int - @Binding var playerName: String + let isNewHighscore: Bool let onPlayAgain: () -> Void let onBackToCategories: () -> Void - let onSaveScore: () -> Void - + var body: some View { VStack(spacing: 20) { Text("🎉 Quiz beendet!") .font(.title) - + Text("Dein Ergebnis: \(score) von \(total) Punkten") .font(.headline) - + + if isNewHighscore { + Text("🔥 Neuer Highscore!") + .font(.headline) + .foregroundColor(.orange) + } + Button("Nochmal spielen", action: onPlayAgain) .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(10) - + Button("Zurück zur Kategorieauswahl", action: onBackToCategories) .padding() .background(Color.gray) .foregroundColor(.white) .cornerRadius(10) - - TextField("Dein Name:", text: $playerName) - .textFieldStyle(RoundedBorderTextFieldStyle()) - .padding(.horizontal) - - Button("Score speichern", action: onSaveScore) - .padding() - .background(playerName.isEmpty ? Color.gray : Color.green) - .foregroundColor(.white) - .cornerRadius(10) - .disabled(playerName.isEmpty) } } } + diff --git a/QuizApp/Views/QuizView.swift b/QuizApp/Views/QuizView.swift index eae5043..4090856 100644 --- a/QuizApp/Views/QuizView.swift +++ b/QuizApp/Views/QuizView.swift @@ -19,8 +19,7 @@ struct QuizView: View { @State private var selectedAnswerIndex: Int? = nil @State private var isAnswered = false @State private var showExitAlert = false - @State private var playerName: String = "" - @State private var scoreIsSaved = false + @State private var isNewHighscore = false @State private var estimationValue: Double = 0 @State private var estimationSubmitted: Bool = false @@ -32,17 +31,15 @@ struct QuizView: View { QuizFinishedView( score: viewModel.score, total: viewModel.questions.count, - playerName: $playerName, + isNewHighscore: isNewHighscore, onPlayAgain: { restartQuiz() }, - onBackToCategories: { dismiss() }, - onSaveScore: { - saveScore() - dismiss() - } + onBackToCategories: { dismiss() } ) .onAppear { AudioServicesPlaySystemSound(1322) score += viewModel.score + // Highscore prüfen/setzen + isNewHighscore = viewModel.updateHighscoreIfNeeded() } .onDisappear { viewModel.isQuizFinished = false @@ -131,10 +128,7 @@ struct QuizView: View { } } .onAppear { - // Fragen für die Kategorie - if viewModel.selectedCategory != category { - viewModel.loadQuestions(for: category) - } + viewModel.loadQuestions(for: category) } .navigationBarBackButtonHidden(!viewModel.isQuizFinished) .toolbar { @@ -206,37 +200,6 @@ struct QuizView: View { } } } - - private func saveScore() { - // Bestehende Scores laden - var savedScores = UserDefaults.standard.array(forKey: "leaderboard") as? [[String: Any]] ?? [] - - // Neuen Score hinzufügen - let newScore: [String: Any] = [ - "name": playerName, - "score": viewModel.score, - "date": Date() - ] - - savedScores.append(newScore) - - // Nach Score sortieren - savedScores.sort { score1, score2 in - let score1Value = score1["score"] as? Int ?? 0 - let score2Value = score2["score"] as? Int ?? 0 - return score1Value > score2Value - } - - // Nur die besten 10 Scores behalten - if savedScores.count > 5 { - savedScores = Array(savedScores.prefix(10)) - } - - UserDefaults.standard.set(savedScores, forKey: "leaderboard") - scoreIsSaved = true - - print("Score gespeichert: \(playerName) - \(viewModel.score) Punkte") - } } #Preview {