refactor: extract category logic into CategorySelectionViewModel
This commit is contained in:
@@ -1,7 +1,44 @@
|
||||
//
|
||||
// CategorySelectionViewModel..swift
|
||||
// CategorySelectionViewModel.swift
|
||||
// QuizApp
|
||||
//
|
||||
// Created by Paul Nowotka on 23.08.25.
|
||||
// Created by Paul on 23.08.25.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class CategorySelectionViewModel: ObservableObject {
|
||||
private var allQuestionsByCategory: [String: [QuizQuestion]] = [:]
|
||||
|
||||
var availableCategories: [String] {
|
||||
return Array(allQuestionsByCategory.keys).sorted()
|
||||
}
|
||||
|
||||
init() {
|
||||
loadQuestions()
|
||||
}
|
||||
|
||||
private func loadQuestions() {
|
||||
guard let url = Bundle.main.url(forResource: "questions", withExtension: "json") else {
|
||||
print("questions.json nicht gefunden")
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let data = try Data(contentsOf: url)
|
||||
allQuestionsByCategory = try JSONDecoder().decode([String: [QuizQuestion]].self, from: data)
|
||||
print("Fragen für Kategorienauswahl geladen")
|
||||
} catch {
|
||||
print("Fehler beim Laden der Kategorien: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func highscore(for category: String) -> Int {
|
||||
let dict = UserDefaults.standard.dictionary(forKey: "categoryHighscores") as? [String: Int] ?? [:]
|
||||
return dict[category] ?? 0
|
||||
}
|
||||
|
||||
func questions(for category: String) -> [QuizQuestion] {
|
||||
return allQuestionsByCategory[category] ?? []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import Foundation
|
||||
|
||||
class ViewModel: ObservableObject {
|
||||
|
||||
private var allQuestionsByCategory: [String: [QuizQuestion]] = [:]
|
||||
@Published var questions: [QuizQuestion] = []
|
||||
@Published var selectedCategory: String? = nil
|
||||
@Published var currentQuestionIndex: Int = 0
|
||||
@@ -36,27 +35,6 @@ class ViewModel: ObservableObject {
|
||||
return questions[currentQuestionIndex]
|
||||
}
|
||||
|
||||
var availableCategories: [String] {
|
||||
return Array(allQuestionsByCategory.keys).sorted()
|
||||
}
|
||||
|
||||
|
||||
init() {
|
||||
guard let url = Bundle.main.url(forResource: "questions", withExtension: "json") else {
|
||||
questions = []
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let data = try Data(contentsOf: url)
|
||||
allQuestionsByCategory = try JSONDecoder().decode([String: [QuizQuestion]].self, from: data)
|
||||
print("Fragen geladen")
|
||||
} catch {
|
||||
print("Fehler beim Laden des Inhalts: \(error)")
|
||||
allQuestionsByCategory = [:]
|
||||
}
|
||||
}
|
||||
|
||||
func loadNextQuestion() {
|
||||
if currentQuestionIndex + 1 < questions.count {
|
||||
currentQuestionIndex += 1
|
||||
@@ -65,18 +43,17 @@ class ViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func loadQuestions(for category: String) {
|
||||
func loadQuestions(questions: [QuizQuestion], for category: String) {
|
||||
selectedCategory = category
|
||||
questions = allQuestionsByCategory[category] ?? []
|
||||
self.questions = questions
|
||||
currentQuestionIndex = 0
|
||||
score = 0
|
||||
isQuizFinished = false
|
||||
answeredCount = 0
|
||||
selectedAnswers = Array(repeating: nil, count: questions.count)
|
||||
print(selectedAnswers)
|
||||
print("Fragen für Quiz geladen: \(questions.count) Fragen")
|
||||
}
|
||||
|
||||
|
||||
func incrementScore(selectedIndex: Int) {
|
||||
if let correct = currentQuestion?.correctAnswer, selectedIndex == correct {
|
||||
score += 1
|
||||
@@ -86,8 +63,7 @@ class ViewModel: ObservableObject {
|
||||
func pointsForEstimation(
|
||||
guess: Double,
|
||||
correct: Double,
|
||||
maxPoints: Int = 1,
|
||||
|
||||
maxPoints: Int = 1
|
||||
) -> Int {
|
||||
let absError = abs(guess - correct) // Absolute Abweichung
|
||||
let relError = absError / abs(correct) // Relative Abweichung
|
||||
@@ -99,11 +75,6 @@ class ViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
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 }
|
||||
@@ -116,8 +87,4 @@ class ViewModel: ObservableObject {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func allHighscores() -> [String: Int] {
|
||||
UserDefaults.standard.dictionary(forKey: "categoryHighscores") as? [String: Int] ?? [:]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
import SwiftUI
|
||||
|
||||
struct CategorySelectionView: View {
|
||||
@StateObject private var viewModel = ViewModel()
|
||||
@StateObject private var categoryViewModel = CategorySelectionViewModel()
|
||||
@AppStorage("globalScore") var globalScore: Int = 0
|
||||
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
VStack(spacing: 24) {
|
||||
@@ -67,8 +66,8 @@ struct CategorySelectionView: View {
|
||||
|
||||
// Liste der Kategorien
|
||||
VStack(spacing: 12) {
|
||||
ForEach(viewModel.availableCategories, id: \.self) { category in
|
||||
NavigationLink(destination: QuizView(viewModel: viewModel, category: category)) {
|
||||
ForEach(categoryViewModel.availableCategories, id: \.self) { category in
|
||||
NavigationLink(destination: QuizView(questions: categoryViewModel.questions(for: category), category: category)) {
|
||||
HStack {
|
||||
Image(systemName: "play.circle.fill")
|
||||
.foregroundColor(.blue)
|
||||
@@ -78,7 +77,7 @@ struct CategorySelectionView: View {
|
||||
Text(category)
|
||||
.font(.headline)
|
||||
.foregroundColor(.primary)
|
||||
Text("Highscore: \(viewModel.highscore(for: category))")
|
||||
Text("Highscore: \(categoryViewModel.highscore(for: category))")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
@@ -10,10 +10,11 @@ import AudioToolbox
|
||||
|
||||
struct QuizView: View {
|
||||
|
||||
@ObservedObject var viewModel = ViewModel()
|
||||
@StateObject var viewModel = ViewModel()
|
||||
@AppStorage("globalScore") var score: Int = 0
|
||||
@Environment(\.dismiss) var dismiss
|
||||
|
||||
let questions: [QuizQuestion] // Neue Property
|
||||
let category: String
|
||||
|
||||
var body: some View {
|
||||
@@ -119,7 +120,7 @@ struct QuizView: View {
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
viewModel.loadQuestions(for: category)
|
||||
viewModel.loadQuestions(questions: questions, for: category)
|
||||
}
|
||||
.navigationBarBackButtonHidden(!viewModel.isQuizFinished)
|
||||
.toolbar {
|
||||
|
||||
Reference in New Issue
Block a user