/// <summary> /// Saves QuizAccessTimes and QuizIdentities to the progress data file. /// </summary> public static void SaveQuizAccessData() { Directory.CreateDirectory(APP_CFG_DIR); QuizProgressDataRoot dataRoot; string dataRaw; if (File.Exists(ConfigManager.Config.StorageConfig.QuizProgressFile)) { dataRaw = AtomicIO.AtomicRead(ConfigManager.Config.StorageConfig.QuizProgressFile); dataRoot = JsonConvert.DeserializeObject <QuizProgressDataRoot>(dataRaw); if (dataRoot.FileFormatVersion == null || new Version(dataRoot.FileFormatVersion).CompareTo(MetaData.GetLatestQuizVersion()) < 0) { // Existing quiz file has an older file format - backup before upgrade BackupProgress(); } dataRoot.FileFormatVersion = MetaData.QUIZ_FILE_FORMAT_VERSION; } else { dataRoot = new QuizProgressDataRoot(MetaData.QUIZ_FILE_FORMAT_VERSION); } dataRoot.QuizAccessTimes = QuizAccessTimes; dataRoot.QuizIdentities = QuizIdentities; #if DEBUG dataRaw = JsonConvert.SerializeObject(dataRoot, Formatting.Indented); #else dataRaw = JsonConvert.SerializeObject(dataRoot); #endif AtomicIO.AtomicWrite(ConfigManager.Config.StorageConfig.QuizProgressFile, dataRaw); }
/// <summary> /// Merges two QuizProgDataRoots into one, by adding all quiz progress datas into one. If duplicates exist, the one with best progress will be selected. /// If same, progressFile1 will have priority /// </summary> /// <param name="progressFile1">The path to the first quiz progress data file. This one has priority over progressFile2</param> /// <param name="progressFile2">The path to the second quiz progress data file.</param> /// <param name="savePath">The path where the merged file should be saved</param> /// <returns>True if the merge was successful, otherwise false</returns> public static bool Merge(string progressFile1, string progressFile2, string savePath) { BackupHelper.BackupFile(progressFile1, Path.Combine(Path.GetDirectoryName(progressFile1), "SteelQuiz Progress Backups"), false); BackupHelper.BackupFile(progressFile2, Path.Combine(Path.GetDirectoryName(progressFile2), "SteelQuiz Progress Backups"), false); if (File.Exists(savePath) && savePath != progressFile1 && savePath != progressFile2) { BackupHelper.BackupFile(savePath, Path.Combine(Path.GetDirectoryName(savePath), "SteelQuiz Progress Backups")); } QuizProgressDataRoot prog1; QuizProgressDataRoot prog2; try { prog1 = JsonConvert.DeserializeObject <QuizProgressDataRoot>(AtomicIO.AtomicRead(progressFile1)); prog2 = JsonConvert.DeserializeObject <QuizProgressDataRoot>(AtomicIO.AtomicRead(progressFile2)); } catch (AtomicException ex) { MessageBox.Show("Could not load progress data files:\r\n\r\n" + ex.ToString(), "SteelQuiz", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } QuizProgressDataRoot merged = Merge(prog1, prog2); #if DEBUG AtomicIO.AtomicWrite(savePath, JsonConvert.SerializeObject(merged, Formatting.Indented)); #else AtomicIO.AtomicWrite(savePath, JsonConvert.SerializeObject(merged)); #endif return(true); }
/// <summary> /// Saves the quiz progress data contained in the specified quiz. /// </summary> /// <param name="quiz">The Quiz object containing the progress data</param> public static void SaveQuizProgress(Quiz quiz) { string dataRaw = AtomicIO.AtomicRead(ConfigManager.Config.StorageConfig.QuizProgressFile); var dataRoot = JsonConvert.DeserializeObject <QuizProgressDataRoot>(dataRaw); if (dataRoot.FileFormatVersion == null || new Version(dataRoot.FileFormatVersion).CompareTo(MetaData.GetLatestQuizVersion()) < 0) { // Existing quiz file has an older file format - backup before upgrade BackupProgress(); } dataRoot.FileFormatVersion = MetaData.QUIZ_FILE_FORMAT_VERSION; var data = dataRoot.QuizProgressData.Where(x => x.QuizGUID == quiz.GUID).FirstOrDefault(); if (data != null) { dataRoot.QuizProgressData[dataRoot.QuizProgressData.IndexOf(data)] = quiz.ProgressData; } else { dataRoot.QuizProgressData.Add(quiz.ProgressData); } #if DEBUG dataRaw = JsonConvert.SerializeObject(dataRoot, Formatting.Indented); #else dataRaw = JsonConvert.SerializeObject(dataRoot); #endif AtomicIO.AtomicWrite(ConfigManager.Config.StorageConfig.QuizProgressFile, dataRaw); }
/// <summary> /// Retrieves the quiz progress data object for the specified quiz. /// </summary> /// <param name="quiz">The quiz whose quiz progress data to load.</param> /// <returns>The QuizProgData object belonging to the quiz.</returns> private static QuizProgress LoadQuizProgressData(Quiz quiz) { string dataRaw = AtomicIO.AtomicRead(ConfigManager.Config.StorageConfig.QuizProgressFile); var dataRoot = JsonConvert.DeserializeObject <QuizProgressDataRoot>(dataRaw); var progress = dataRoot.QuizProgressData.Where(x => x.QuizGUID == quiz.GUID).FirstOrDefault(); if (progress != null) { // Remove cards from CurrentCards that has been deleted from the quiz progress.CurrentCards = progress.CurrentCards.Where(x => quiz.Cards.Select(y => y.Guid).Contains(x)).ToList(); // Remove progress from cards that have been removed from the quiz progress.CardProgress = progress.CardProgress.Where(x => quiz.Cards.Select(y => y.Guid).Contains(x.CardGuid)).ToList(); // Issue #45 fix - "Learning Progress still 100 % after adding card to quiz without having answered it" foreach (var card in quiz.Cards) { if (!progress.CardProgress.Select(x => x.CardGuid).Contains(card.Guid)) { // CardProgress does not exist for card, create it progress.CardProgress.Add(new CardProgress(card.Guid)); } } } return(progress); }
/// <summary> /// Loads QuizAccessTimes and QuizIdentities from the progress data file. /// </summary> public static void LoadQuizAccessData() { if (!File.Exists(ConfigManager.Config.StorageConfig.QuizProgressFile)) { return; } string dataRaw = AtomicIO.AtomicRead(ConfigManager.Config.StorageConfig.QuizProgressFile); var dataRoot = JsonConvert.DeserializeObject <QuizProgressDataRoot>(dataRaw); QuizAccessTimes = dataRoot.QuizAccessTimes; QuizIdentities = dataRoot.QuizIdentities; }
private static Quiz InternalLoadQuiz(string path) { if (!File.Exists(path)) { throw new FileNotFoundException("Quiz file does not exist!"); } string quizRaw = AtomicIO.AtomicRead(path); Quiz quiz = JsonConvert.DeserializeObject <Quiz>(quizRaw); Version quizVersion; if (quiz.FileFormatVersion == null) { quizVersion = null; } else { quizVersion = new Version(quiz.FileFormatVersion); } quiz.FileFormatVersion = MetaData.QUIZ_FILE_FORMAT_VERSION; if (quizVersion != null && quizVersion.CompareTo(MetaData.GetLatestQuizVersion()) > 0) { throw new VersionNotSupportedException(VersionNotSupportedException.NotSupportedReason.AppVersionTooOld); } quiz.QuizIdentity = new QuizIdentity(quiz.GUID, path); quiz.ProgressData = LoadQuizProgressData(quiz); if (quiz.ProgressData == null) { // Progress data for quiz does not exist - create new quiz.ProgressData = new QuizProgress(quiz); } QuizIdentities[quiz.GUID] = quiz.QuizIdentity; QuizAccessTimes[quiz.GUID] = DateTime.Now; SaveQuizAccessData(); if (quizVersion.CompareTo(new Version(4, 0, 0, 1)) < 0) { SaveQuiz(quiz, path); } return(quiz); }
public static bool LoadConfig() { Directory.CreateDirectory(QuizCore.APP_CFG_DIR); if (!File.Exists(CONFIG_FILE)) { Config = new Config(); SaveConfig(); return(true); } bool corrupt = false; try { Config = JsonConvert.DeserializeObject <Config>(AtomicIO.AtomicRead(CONFIG_FILE)); } catch (AtomicException) { corrupt = true; } if (Config == null) { corrupt = true; } if (corrupt) { var msg = MessageBox.Show("The configuration file for SteelQuiz is corrupt, and must be reset. Reset configuration?", "SteelQuiz", MessageBoxButtons.YesNo, MessageBoxIcon.Error); if (msg == DialogResult.Yes) { BackupConfig(); File.Delete(CONFIG_FILE); return(LoadConfig()); } else { return(false); } } return(true); }
private void bgw_quizSearcher_DoWork(object sender, DoWorkEventArgs e) { foreach (var searchDir in GetSearchDirs()) { try { foreach (var file in Directory.EnumerateFiles(searchDir.Path, $"*.{QuizCore.QUIZ_EXTENSION}", searchDir.Recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)) { if (bgw_quizSearcher.CancellationPending) { e.Cancel = true; break; } string rawQuiz; try { rawQuiz = AtomicIO.AtomicRead(file); } catch (AtomicException) { continue; } var quiz = JsonConvert.DeserializeObject <Quiz>(rawQuiz); if (quiz != null && quiz.GUID == QuizGuid) { NewQuizPath = file; break; } } } catch { continue; } } }
private void btn_specifyManually_Click(object sender, EventArgs e) { if (ofd_quiz.ShowDialog() == DialogResult.OK) { string rawQuiz = null; try { rawQuiz = AtomicIO.AtomicRead(ofd_quiz.FileName); } catch (AtomicException ex) { MessageBox.Show("Could not read file:\r\n" + ex.ToString(), "Atomic Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } var quiz = JsonConvert.DeserializeObject <Quiz>(rawQuiz); if (quiz.GUID == QuizGuid) { NewQuizPath = ofd_quiz.FileName; if (bgw_quizSearcher.IsBusy) { bgw_quizSearcher.CancelAsync(); } else { DialogResult = DialogResult.OK; } } else { MessageBox.Show("The selected quiz is not the right one. SteelQuiz is looking for the following quiz:\r\n\r\n" + $"Old name: {Path.GetFileNameWithoutExtension(OldQuizPath)}\r\nGuid: {QuizGuid.ToString()}", "Guid does not match", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
public static void SaveConfig() { Directory.CreateDirectory(QuizCore.APP_CFG_DIR); AtomicIO.AtomicWrite(CONFIG_FILE, JsonConvert.SerializeObject(Config, Formatting.Indented)); }
public static void SaveQuiz(Quiz quiz, string path) { string quizRaw = JsonConvert.SerializeObject(quiz, Formatting.Indented); AtomicIO.AtomicWrite(path, quizRaw); }