/// <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 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); }
static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Args = args; Application.ThreadException += Application_ThreadException; Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; if (!mutex.WaitOne(TimeSpan.Zero, true)) { // SteelQuiz is already running - communicate with existing instance! if (Args.Length > 0 && File.Exists(Args[0]) && Args[0].EndsWith(".steelquiz")) { // Load Quiz using (var key = Registry.CurrentUser.CreateSubKey(@"Software\SteelQuiz\Communication", true)) { key.SetValue("QuizToLoadPath", Args[0]); } NativeMethods.PostMessage((IntPtr)NativeMethods.HWND_BROADCAST, NativeMethods.WM_LOAD_QUIZ, IntPtr.Zero, IntPtr.Zero); } else { NativeMethods.PostMessage((IntPtr)NativeMethods.HWND_BROADCAST, NativeMethods.WM_SHOW_ME, IntPtr.Zero, IntPtr.Zero); } Application.Exit(); return; } if (!ConfigManager.LoadConfig()) { return; } if (!File.Exists(ConfigManager.Config.StorageConfig.QuizProgressFile)) { // Create empty quiz progress data file var progressRoot = new QuizProgressDataRoot(MetaData.QUIZ_FILE_FORMAT_VERSION); #if DEBUG var progressRootRaw = JsonConvert.SerializeObject(progressRoot, Formatting.Indented); #else var progressRootRaw = JsonConvert.SerializeObject(progressRoot); #endif File.WriteAllText(ConfigManager.Config.StorageConfig.QuizProgressFile, progressRootRaw); } ++ConfigManager.Config.Statistics.LaunchCount.Data; //ConfigManager.SaveConfig(); ConfigManager.Configure(); Application.Run(new TermsOfUse()); }
/// <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, prog1 will have priority /// </summary> /// <param name="prog1">The first QuizProgDataRoot to merge. This one has priority over prog2</param> /// <param name="prog2">The second QuizProgDataRoot to merge</param> /// <returns></returns> public static QuizProgressDataRoot Merge(QuizProgressDataRoot prog1, QuizProgressDataRoot prog2) { var result = new QuizProgressDataRoot(MetaData.QUIZ_FILE_FORMAT_VERSION); result.QuizAccessTimes = prog1.QuizAccessTimes; result.QuizIdentities = prog1.QuizIdentities; var unfixedQuizProgDataList = new List <QuizProgress>(); foreach (var q in prog1.QuizProgressData) { unfixedQuizProgDataList.Add(q); } foreach (var q in prog2.QuizProgressData) { unfixedQuizProgDataList.Add(q); } // select best ones from duplicates (the progress data with best progress) (and the only one from non-duplicates) var duplicatePairs = unfixedQuizProgDataList.GroupBy(x => x.QuizGUID); foreach (var duplicatePair in duplicatePairs) { var best = duplicatePair.OrderByDescending(x => x.GetLearningProgress()).Take(2); if (best.Count() >= 2 && best.ElementAt(0).GetLearningProgress() == best.ElementAt(1).GetLearningProgress()) { // prioritize prog1 if (prog1.QuizProgressData.Contains(best.ElementAt(0))) { result.QuizProgressData.Add(best.ElementAt(0)); } else if (prog1.QuizProgressData.Contains(best.ElementAt(1))) { result.QuizProgressData.Add(best.ElementAt(1)); } else { throw new Exception("Cannot find duplicate quiz progress data in prog1"); } } else { result.QuizProgressData.Add(best.ElementAt(0)); } } return(result); }