diff --git a/CloudMaster/Features/Course/Views/CourseView.swift b/CloudMaster/Features/Course/Views/CourseView.swift index 68abf64..6109303 100644 --- a/CloudMaster/Features/Course/Views/CourseView.swift +++ b/CloudMaster/Features/Course/Views/CourseView.swift @@ -1,8 +1,9 @@ import SwiftUI + struct CourseView: View { @State private var isLoading = false @State private var downloadProgress: [Course: Progress] = [:] - @State private var userTrainingData = UserTrainingData() + @State private var showingNotificationSettings = false @State private var notificationsEnabled = false @State private var showingInfoPopup = false @@ -10,6 +11,8 @@ struct CourseView: View { @StateObject private var viewModel = DownloadViewModel() @StateObject private var questionLoader: QuestionLoader + @ObservedObject var userTrainingStore = UserTrainingStore.shared + @Environment(\.colorScheme) var colorScheme let course: Course @@ -37,7 +40,7 @@ struct CourseView: View { HStack { Image(systemName: "clock") .foregroundColor(.blue) - Text(formatTimeSpent(userTrainingData.timeSpent)) + Text(formatTimeSpent(userTrainingStore.trainingData[course.shortName]?.timeSpent ?? 0)) .font(.subheadline) } .padding(.top, 20) @@ -101,7 +104,7 @@ struct CourseView: View { } } .onAppear { - loadUserTrainingData(for: course) + loadUserTrainingData() checkNotificationSettings() if questionLoader.questions.isEmpty { downloadCourse() @@ -154,12 +157,8 @@ struct CourseView: View { } } - func loadUserTrainingData(for course: Course) { - if let data = UserDefaults.standard.data(forKey: course.shortName) { - if let decodedData = try? JSONDecoder().decode(UserTrainingData.self, from: data) { - userTrainingData = decodedData - } - } + func loadUserTrainingData() { + _ = userTrainingStore.loadTrainingData(forCourse: course.shortName) } func formatTimeSpent(_ time: TimeInterval) -> String { @@ -234,5 +233,4 @@ struct CourseInformationPopup: View { } .padding() } - } diff --git a/CloudMaster/Features/Settings/Views/SettingsView.swift b/CloudMaster/Features/Settings/Views/SettingsView.swift index 381f89f..14ae021 100644 --- a/CloudMaster/Features/Settings/Views/SettingsView.swift +++ b/CloudMaster/Features/Settings/Views/SettingsView.swift @@ -12,7 +12,7 @@ struct SettingsView: View { Section(header: Text("Training Data Management")) { Button(action: { showAlertWith(title: "Delete Trainingsdata", message: "Are you sure you want to delete all training data?", action: { - UserTrainingStore.shared.resetTrainingData() + UserTrainingStore.shared.deleteAllTrainingData() }) }) { Text("Delete Training data") diff --git a/CloudMaster/Features/Training/Models/UserTrainingData.swift b/CloudMaster/Features/Training/Models/UserTrainingData.swift index cc76584..fd6837d 100644 --- a/CloudMaster/Features/Training/Models/UserTrainingData.swift +++ b/CloudMaster/Features/Training/Models/UserTrainingData.swift @@ -1,13 +1,18 @@ import Foundation +import SwiftUI -struct UserTrainingData: Codable { +struct UserTrainingData: Codable, Identifiable { + var id = UUID() + let shortName: String + var timeSpent: TimeInterval var correctAnswers: Int var wrongAnswers: Int var questionAttempts: [UUID: Int] // Mapping question ID to the number of attempts var questionStats: [UUID: QuestionStats] // Mapping question ID to the stats - init() { + init(shortName: String) { + self.shortName = shortName self.timeSpent = 0 self.correctAnswers = 0 self.wrongAnswers = 0 @@ -16,6 +21,7 @@ struct UserTrainingData: Codable { } mutating func updateStats(for questionID: UUID, correctChoices: Set, selectedChoices: Set) { + // Update question attempts if let attempts = questionAttempts[questionID] { questionAttempts[questionID] = attempts + 1 @@ -38,7 +44,6 @@ struct UserTrainingData: Codable { self.questionStats[questionID] = QuestionStats(timesViewed: 1, timesCorrect: timesCorrect, timesIncorrect: timesIncorrect) } } - } struct QuestionStats: Codable { @@ -47,33 +52,42 @@ struct QuestionStats: Codable { var timesIncorrect: Int } -class UserTrainingStore { +class UserTrainingStore: ObservableObject { static let shared = UserTrainingStore() - private let userDefaultsKey = "userTrainingData" + private let userDefaultsKeyPrefix = "userTrainingData_" - private init() { - loadTrainingData() - } + private init() {} - var trainingData: UserTrainingData = UserTrainingData() + @Published var trainingData: [String: UserTrainingData] = [:] - func loadTrainingData() { - if let data = UserDefaults.standard.data(forKey: userDefaultsKey) { - if let decodedData = try? JSONDecoder().decode(UserTrainingData.self, from: data) { - trainingData = decodedData - } + func loadTrainingData(forCourse shortName: String) -> UserTrainingData { + if let data = UserDefaults.standard.data(forKey: userDefaultsKeyPrefix + shortName), + let decodedData = try? JSONDecoder().decode(UserTrainingData.self, from: data) { + trainingData[shortName] = decodedData + return decodedData + } else { + let newTrainingData = UserTrainingData(shortName: shortName) + trainingData[shortName] = newTrainingData + return newTrainingData } } - func saveTrainingData() { - if let data = try? JSONEncoder().encode(trainingData) { - UserDefaults.standard.set(data, forKey: userDefaultsKey) + func saveTrainingData(_ data: UserTrainingData) { + trainingData[data.shortName] = data + if let encoded = try? JSONEncoder().encode(data) { + UserDefaults.standard.set(encoded, forKey: userDefaultsKeyPrefix + data.shortName) } } - func resetTrainingData() { - trainingData = UserTrainingData() - saveTrainingData() - UserDefaults.standard.removeObject(forKey: userDefaultsKey) + func deleteTrainingData(forCourse shortName: String) { + trainingData.removeValue(forKey: shortName) + UserDefaults.standard.removeObject(forKey: userDefaultsKeyPrefix + shortName) + } + + func deleteAllTrainingData() { + trainingData.keys.forEach { shortName in + UserDefaults.standard.removeObject(forKey: userDefaultsKeyPrefix + shortName) + } + trainingData.removeAll() } } diff --git a/CloudMaster/Features/Training/Views/TrainingView.swift b/CloudMaster/Features/Training/Views/TrainingView.swift index 67b9e22..8a88a11 100644 --- a/CloudMaster/Features/Training/Views/TrainingView.swift +++ b/CloudMaster/Features/Training/Views/TrainingView.swift @@ -4,11 +4,12 @@ struct TrainingView: View { @State private var currentQuestionIndex = 0 @State private var selectedChoices: Set = [] @State private var showResult = false - @State private var userTrainingData = UserTrainingStore.shared.trainingData @State private var startTime: Date? @State private var isBookmarked: Bool = false @Environment(\.presentationMode) var presentationMode + @ObservedObject var userTrainingStore = UserTrainingStore.shared + let course: Course @StateObject private var questionLoader: QuestionLoader @@ -94,6 +95,7 @@ struct TrainingView: View { .navigationBarHidden(true) .onAppear { startTime = Date() + loadUserTrainingData() updateBookmarkState() // Ensure bookmark state is updated when the view appears } .onDisappear { @@ -160,10 +162,14 @@ struct TrainingView: View { } func updateUserTrainingData(for question: Question) { + guard var userTrainingData = userTrainingStore.trainingData[course.shortName] else { return } + if let startTime = startTime { userTrainingData.timeSpent += Date().timeIntervalSince(startTime) } - + + print(userTrainingData.timeSpent) + let correctChoices = Set(question.choices.filter { $0.correct }.map { $0.id }) let userCorrectChoices = selectedChoices.intersection(correctChoices) @@ -171,19 +177,17 @@ struct TrainingView: View { userTrainingData.wrongAnswers += selectedChoices.subtracting(correctChoices).count userTrainingData.updateStats(for: question.id, correctChoices: correctChoices, selectedChoices: selectedChoices) + + userTrainingStore.saveTrainingData(userTrainingData) } - func loadUserTrainingData(for course: Course) { - if let data = UserDefaults.standard.data(forKey: course.shortName) { - if let decodedData = try? JSONDecoder().decode(UserTrainingData.self, from: data) { - userTrainingData = decodedData - } - } + func loadUserTrainingData() { + _ = userTrainingStore.loadTrainingData(forCourse: course.shortName) } func saveUserTrainingData() { - if let data = try? JSONEncoder().encode(userTrainingData) { - UserDefaults.standard.set(data, forKey: course.shortName) + if let userTrainingData = userTrainingStore.trainingData[course.shortName] { + userTrainingStore.saveTrainingData(userTrainingData) } } } diff --git a/CloudMaster/Utilities/QuestionLoader.swift b/CloudMaster/Utilities/QuestionLoader.swift index 482921d..f1ef11d 100644 --- a/CloudMaster/Utilities/QuestionLoader.swift +++ b/CloudMaster/Utilities/QuestionLoader.swift @@ -79,7 +79,9 @@ class QuestionLoader: ObservableObject { } private func reorderQuestions(_ questions: [Question]) -> [Question] { - let trainingData = UserTrainingStore.shared.trainingData + guard let trainingData = UserTrainingStore.shared.trainingData[questions.first?.id.uuidString ?? ""] else { + return questions + } let newQuestions = questions.filter { trainingData.questionStats[$0.id] == nil } let incorrectQuestions = questions.filter {