117 lines
3.4 KiB
Swift
117 lines
3.4 KiB
Swift
//
|
|
// ViewModel.swift
|
|
// QuizApp
|
|
//
|
|
// Created by Paul on 03.08.25.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
class ViewModel: ObservableObject {
|
|
|
|
private var allQuestionsByCategory: [String: [QuizQuestion]] = [:]
|
|
@Published var questions: [QuizQuestion] = []
|
|
@Published var selectedCategory: String? = nil
|
|
@Published var currentQuestionIndex: Int = 0
|
|
@Published var score: Int = 0
|
|
@Published var isQuizFinished: Bool = false
|
|
@Published var answeredCount: Int = 0
|
|
@Published var selectedAnswers: [Int?] = []
|
|
|
|
|
|
var progress: Double {
|
|
guard !questions.isEmpty else { return 0.0 }
|
|
return Double(answeredCount) / Double(questions.count)
|
|
}
|
|
|
|
var currentQuestion: QuizQuestion? {
|
|
guard currentQuestionIndex < questions.count else { return nil }
|
|
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
|
|
} else {
|
|
isQuizFinished = true
|
|
}
|
|
}
|
|
|
|
func loadQuestions(for category: String) {
|
|
selectedCategory = category
|
|
questions = allQuestionsByCategory[category] ?? []
|
|
currentQuestionIndex = 0
|
|
score = 0
|
|
isQuizFinished = false
|
|
answeredCount = 0
|
|
selectedAnswers = Array(repeating: nil, count: questions.count)
|
|
print(selectedAnswers)
|
|
}
|
|
|
|
|
|
func incrementScore(selectedIndex: Int) {
|
|
if let correct = currentQuestion?.correctAnswer, selectedIndex == correct {
|
|
score += 1
|
|
}
|
|
}
|
|
|
|
func pointsForEstimation(
|
|
guess: Double,
|
|
correct: Double,
|
|
maxPoints: Int = 1,
|
|
|
|
) -> Int {
|
|
let absError = abs(guess - correct) // Absolute Abweichung
|
|
let relError = absError / abs(correct) // Relative Abweichung
|
|
|
|
if relError <= 0.1 {
|
|
return maxPoints
|
|
} else {
|
|
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] ?? [:]
|
|
}
|
|
}
|