refactor: rename ViewModel to QuizViewModel

This commit is contained in:
2025-08-24 20:41:59 +02:00
parent c8f634a2ee
commit ff20ca6b27
3 changed files with 58 additions and 58 deletions

View File

@@ -7,7 +7,7 @@
import Foundation import Foundation
class ViewModel: ObservableObject { class QuizViewModel: ObservableObject {
@Published var questions: [QuizQuestion] = [] @Published var questions: [QuizQuestion] = []
@Published var selectedCategory: String? = nil @Published var selectedCategory: String? = nil

View File

@@ -12,7 +12,7 @@ struct EstimationQuestionView: View {
let maxValue: Double let maxValue: Double
let correctValue: Double let correctValue: Double
let unit: String let unit: String
let viewModel: ViewModel let viewModel: QuizViewModel
@Binding var value: Double @Binding var value: Double
@Binding var submitted: Bool @Binding var submitted: Bool

View File

@@ -10,7 +10,7 @@ import AudioToolbox
struct QuizView: View { struct QuizView: View {
@StateObject var viewModel = ViewModel() @StateObject var quizViewModel = QuizViewModel()
@AppStorage("globalScore") var score: Int = 0 @AppStorage("globalScore") var score: Int = 0
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) var dismiss
@@ -19,29 +19,29 @@ struct QuizView: View {
var body: some View { var body: some View {
VStack { VStack {
if viewModel.isQuizFinished { if quizViewModel.isQuizFinished {
QuizFinishedView( QuizFinishedView(
score: viewModel.score, score: quizViewModel.score,
total: viewModel.questions.count, total: quizViewModel.questions.count,
isNewHighscore: viewModel.isNewHighscore, isNewHighscore: quizViewModel.isNewHighscore,
onPlayAgain: { restartQuiz() }, onPlayAgain: { restartQuiz() },
onBackToCategories: { dismiss() } onBackToCategories: { dismiss() }
) )
.onAppear { .onAppear {
AudioServicesPlaySystemSound(1322) AudioServicesPlaySystemSound(1322)
score += viewModel.score score += quizViewModel.score
// Highscore prüfen/setzen // Highscore prüfen/setzen
viewModel.isNewHighscore = viewModel.updateHighscoreIfNeeded() quizViewModel.isNewHighscore = quizViewModel.updateHighscoreIfNeeded()
} }
.onDisappear { .onDisappear {
viewModel.isQuizFinished = false quizViewModel.isQuizFinished = false
} }
} else if let frage = viewModel.currentQuestion { } else if let frage = quizViewModel.currentQuestion {
QuizHeader( QuizHeader(
score: viewModel.score, score: quizViewModel.score,
currentIndex: viewModel.currentQuestionIndex, currentIndex: quizViewModel.currentQuestionIndex,
total: viewModel.questions.count, total: quizViewModel.questions.count,
colorForStep: { idx in colorForAnswer(at: idx) } colorForStep: { idx in colorForAnswer(at: idx) }
) )
@@ -56,29 +56,29 @@ struct QuizView: View {
let correctV = frage.correctValue { let correctV = frage.correctValue {
// Estimation // Estimation
EstimationQuestionView( EstimationQuestionView(
questionID: viewModel.currentQuestionIndex, // <- neu questionID: quizViewModel.currentQuestionIndex, // <- neu
minValue: minV, minValue: minV,
maxValue: maxV, maxValue: maxV,
correctValue: correctV, correctValue: correctV,
unit: frage.unit ?? "", unit: frage.unit ?? "",
viewModel: viewModel, viewModel: quizViewModel,
value: $viewModel.estimationValue, value: $quizViewModel.estimationValue,
submitted: $viewModel.estimationSubmitted, submitted: $quizViewModel.estimationSubmitted,
gainedPoints: $viewModel.estimationPoints gainedPoints: $quizViewModel.estimationPoints
) { gained in ) { gained in
viewModel.score += gained quizViewModel.score += gained
viewModel.answeredCount += 1 quizViewModel.answeredCount += 1
viewModel.selectedAnswers[viewModel.currentQuestionIndex] = 0 quizViewModel.selectedAnswers[quizViewModel.currentQuestionIndex] = 0
viewModel.isAnswered = true quizViewModel.isAnswered = true
} }
if viewModel.estimationSubmitted { if quizViewModel.estimationSubmitted {
Button { Button {
viewModel.loadNextQuestion() quizViewModel.loadNextQuestion()
viewModel.estimationSubmitted = false quizViewModel.estimationSubmitted = false
viewModel.isAnswered = false quizViewModel.isAnswered = false
viewModel.selectedAnswerIndex = nil quizViewModel.selectedAnswerIndex = nil
viewModel.estimationPoints = 0 quizViewModel.estimationPoints = 0
} label: { } label: {
Text("Nächste Frage") Text("Nächste Frage")
.font(.headline) .font(.headline)
@@ -96,22 +96,22 @@ struct QuizView: View {
MultipleChoiceQuestionView( MultipleChoiceQuestionView(
answers: frage.answers, answers: frage.answers,
correctIndex: frage.correctAnswer, correctIndex: frage.correctAnswer,
selectedIndex: $viewModel.selectedAnswerIndex, selectedIndex: $quizViewModel.selectedAnswerIndex,
isAnswered: $viewModel.isAnswered, isAnswered: $quizViewModel.isAnswered,
onAnswer: { index in onAnswer: { index in
print("Selected:", index) print("Selected:", index)
print("Correct:", frage.correctAnswer) print("Correct:", frage.correctAnswer)
viewModel.incrementScore(selectedIndex: index) quizViewModel.incrementScore(selectedIndex: index)
viewModel.answeredCount += 1 quizViewModel.answeredCount += 1
viewModel.selectedAnswers[viewModel.currentQuestionIndex] = index quizViewModel.selectedAnswers[quizViewModel.currentQuestionIndex] = index
}, },
buttonColor: { idx, correct in buttonColor: { idx, correct in
buttonColor(for: idx, correctIndex: correct) buttonColor(for: idx, correctIndex: correct)
}, },
onNext: { onNext: {
viewModel.loadNextQuestion() quizViewModel.loadNextQuestion()
viewModel.selectedAnswerIndex = nil quizViewModel.selectedAnswerIndex = nil
viewModel.isAnswered = false quizViewModel.isAnswered = false
} }
) )
} }
@@ -120,20 +120,20 @@ struct QuizView: View {
} }
} }
.onAppear { .onAppear {
viewModel.loadQuestions(questions: questions, for: category) quizViewModel.loadQuestions(questions: questions, for: category)
} }
.navigationBarBackButtonHidden(!viewModel.isQuizFinished) .navigationBarBackButtonHidden(!quizViewModel.isQuizFinished)
.toolbar { .toolbar {
if !viewModel.isQuizFinished { if !quizViewModel.isQuizFinished {
ToolbarItem(placement: .navigationBarLeading) { ToolbarItem(placement: .navigationBarLeading) {
Button("Abbrechen") { Button("Abbrechen") {
viewModel.showExitAlert = true quizViewModel.showExitAlert = true
} }
.foregroundColor(.red) .foregroundColor(.red)
} }
} }
} }
.alert("Quiz verlassen?", isPresented: $viewModel.showExitAlert) { .alert("Quiz verlassen?", isPresented: $quizViewModel.showExitAlert) {
Button("Quiz verlassen", role: .destructive) { Button("Quiz verlassen", role: .destructive) {
dismiss() dismiss()
} }
@@ -145,11 +145,11 @@ struct QuizView: View {
} }
private func buttonColor(for index: Int, correctIndex: Int) -> Color { private func buttonColor(for index: Int, correctIndex: Int) -> Color {
guard viewModel.isAnswered else { return .blue } guard quizViewModel.isAnswered else { return .blue }
if index == correctIndex { if index == correctIndex {
return .green return .green
} else if index == viewModel.selectedAnswerIndex { } else if index == quizViewModel.selectedAnswerIndex {
return .red return .red
} else { } else {
return .gray return .gray
@@ -157,34 +157,34 @@ struct QuizView: View {
} }
private func restartQuiz() { private func restartQuiz() {
viewModel.currentQuestionIndex = 0 quizViewModel.currentQuestionIndex = 0
viewModel.score = 0 quizViewModel.score = 0
viewModel.isQuizFinished = false quizViewModel.isQuizFinished = false
viewModel.selectedAnswerIndex = nil quizViewModel.selectedAnswerIndex = nil
viewModel.isAnswered = false quizViewModel.isAnswered = false
viewModel.answeredCount = 0 quizViewModel.answeredCount = 0
viewModel.selectedAnswers = Array(repeating: nil, count: viewModel.questions.count) quizViewModel.selectedAnswers = Array(repeating: nil, count: quizViewModel.questions.count)
} }
private func colorForAnswer(at index: Int) -> Color { private func colorForAnswer(at index: Int) -> Color {
if index == viewModel.currentQuestionIndex, if index == quizViewModel.currentQuestionIndex,
viewModel.selectedAnswers[index] == nil { quizViewModel.selectedAnswers[index] == nil {
return Color.blue // aktuelle Frage return Color.blue // aktuelle Frage
} }
guard index < viewModel.selectedAnswers.count, guard index < quizViewModel.selectedAnswers.count,
index < viewModel.questions.count else { index < quizViewModel.questions.count else {
return Color.gray.opacity(0.3) // unbeantwortet return Color.gray.opacity(0.3) // unbeantwortet
} }
// Prüfen ob die Frage beantwortet wurde // Prüfen ob die Frage beantwortet wurde
let question = viewModel.questions[index] let question = quizViewModel.questions[index]
if question.isEstimation { if question.isEstimation {
// Bei Estimation-Fragen: Grün wenn beantwortet // Bei Estimation-Fragen: Grün wenn beantwortet
return viewModel.selectedAnswers[index] != nil ? .green : Color.gray.opacity(0.3) return quizViewModel.selectedAnswers[index] != nil ? .green : Color.gray.opacity(0.3)
} else { } else {
// Bei Multiple-Choice: Grün wenn richtig, rot wenn falsch // Bei Multiple-Choice: Grün wenn richtig, rot wenn falsch
if let selected = viewModel.selectedAnswers[index] { if let selected = quizViewModel.selectedAnswers[index] {
let correct = question.correctAnswer let correct = question.correctAnswer
return selected == correct ? .green : .red return selected == correct ? .green : .red
} else { } else {