From d4ea2254e6ec61c3e1aa22afd92cfebf0e8c7281 Mon Sep 17 00:00:00 2001 From: Andrew Savinykh <658865+AndrewSav@users.noreply.github.com> Date: Mon, 6 May 2024 13:41:18 +1200 Subject: [PATCH] add more debug logging, fixed a few typos --- CHANGELOG.md | 10 +- Remnant2SaveAnalyzer/App.config | 9 + Remnant2SaveAnalyzer/Logger.cs | 218 +++++----- .../Properties/Settings.Designer.cs | 36 ++ .../Properties/Settings.settings | 9 + .../Remnant2SaveAnalyzer.csproj | 2 +- Remnant2SaveAnalyzer/RemnantSave.cs | 407 ++++++++++-------- .../Views/Pages/SettingsPage.xaml | 27 ++ .../Views/Pages/WorldAnalyzerPage.xaml.cs | 2 +- .../locales/Strings.Designer.cs | 45 ++ Remnant2SaveAnalyzer/locales/Strings.resx | 15 + 11 files changed, 493 insertions(+), 287 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89397e6..4600693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,14 @@ # Changelog - -## 0.0.4 (unreleased) +## 0.0.5 (unreleased) - Add ability to hide already looted items for those item, where it can be detected - work in progress - Add ability to hide items unobtainable in the current run without reroll - work in progress -- Add more debug logging - work in progress -- Fixed a few typos +## 0.0.4 (6 May 2024) +- Add option to log save data for debugging purposes +- Add option to dump analyzer data structures in json for debugging purposes +- Add option to log performance metrics for debugging purposes +- Fixed a few typos ## 0.0.3 (3 May 2024) diff --git a/Remnant2SaveAnalyzer/App.config b/Remnant2SaveAnalyzer/App.config index 8b3d984..91d2e29 100644 --- a/Remnant2SaveAnalyzer/App.config +++ b/Remnant2SaveAnalyzer/App.config @@ -178,6 +178,15 @@ True + + False + + + False + + + False + \ No newline at end of file diff --git a/Remnant2SaveAnalyzer/Logger.cs b/Remnant2SaveAnalyzer/Logger.cs index d8306bd..47e1754 100644 --- a/Remnant2SaveAnalyzer/Logger.cs +++ b/Remnant2SaveAnalyzer/Logger.cs @@ -1,111 +1,111 @@ -using Remnant2SaveAnalyzer.Views.Windows; -using System; -using System.Collections.Generic; -using System.IO; - -namespace Remnant2SaveAnalyzer -{ - internal static class Logger - { - public static event EventHandler? MessageLogged; - - static Logger() - { - if (Properties.Settings.Default.CreateLogFile) - { - CreateLog(); - } - Properties.Settings.Default.PropertyChanged += Default_PropertyChanged; - } - - public static List Messages { get; } = []; - - private static void Default_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) - { - if (e.PropertyName != "CreateLogFile") - { - return; - } - if (!Properties.Settings.Default.CreateLogFile) - { - return; - } - CreateLog(); - } - - private static void CreateLog() - { - File.WriteAllText("log.txt", DateTime.Now + ": Version " + typeof(MainWindow).Assembly.GetName().Version + "\r\n"); - } - - public static void Log(object? message, LogType logType, bool silent = false) - { - message ??= "null"; - if (!silent) - { - MessageLogged?.Invoke(null, new(message.ToString() ?? "", logType)); - } - Messages.Add(new(message.ToString() ?? "", logType)); - if (Properties.Settings.Default.CreateLogFile) - { - StreamWriter writer = File.AppendText("log.txt"); - writer.WriteLine($"{DateTime.Now}[{logType}]: {message}"); - writer.Close(); - } - //Debug.WriteLine(message); - } - - public static void Log(object message) - { - Log(message, LogType.Normal); +using Remnant2SaveAnalyzer.Views.Windows; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Remnant2SaveAnalyzer +{ + internal static class Logger + { + public static event EventHandler? MessageLogged; + + static Logger() + { + if (Properties.Settings.Default.CreateLogFile) + { + CreateLog(); + } + Properties.Settings.Default.PropertyChanged += Default_PropertyChanged; + } + + public static List Messages { get; } = []; + + private static void Default_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (e.PropertyName != "CreateLogFile") + { + return; + } + if (!Properties.Settings.Default.CreateLogFile) + { + return; + } + CreateLog(); } - public static void LogSilent(object message) - { - Log(message, LogType.Normal, true); - } - - public static void Success(object message) - { - Log(message, LogType.Success); - } - - public static void Error(object message) - { - Log(message, LogType.Error); - } - - public static void Warn(object message) - { - Log(message, LogType.Warning); - } - - public static void WarnSilent(string message) - { - Log(message, LogType.Warning, true); - } - } - - public enum LogType - { - Normal, - Success, - Error, - Warning, - } - - public class MessageLoggedEventArgs(string message, LogType logType) : EventArgs - { - public string Message { get; set; } = message; - public LogType LogType { get; set;} = logType; - - public MessageLoggedEventArgs(string message) : this(message, LogType.Normal) - { - } - } - public class LogMessage(string message, LogType logType) - { - public string Message { get; set; } = message; - public LogType LogType { get; set; } = logType; - } -} + private static void CreateLog() + { + File.WriteAllText("log.txt", DateTime.Now + ": Version " + typeof(MainWindow).Assembly.GetName().Version + "\r\n"); + } + + public static void Log(object? message, LogType logType, bool silent = false) + { + message ??= "null"; + if (!silent) + { + MessageLogged?.Invoke(null, new(message.ToString() ?? "", logType)); + } + Messages.Add(new(message.ToString() ?? "", logType)); + if (Properties.Settings.Default.CreateLogFile) + { + StreamWriter writer = File.AppendText("log.txt"); + writer.WriteLine($"{DateTime.Now} [{logType}]: {message}"); + writer.Close(); + } + //Debug.WriteLine(message); + } + + public static void Log(object message) + { + Log(message, LogType.Normal); + } + + public static void LogSilent(object message) + { + Log(message, LogType.Normal, true); + } + + public static void Success(object message) + { + Log(message, LogType.Success); + } + + public static void Error(object message) + { + Log(message, LogType.Error); + } + + public static void Warn(object message) + { + Log(message, LogType.Warning); + } + + public static void WarnSilent(string message) + { + Log(message, LogType.Warning, true); + } + } + + public enum LogType + { + Normal, + Success, + Error, + Warning, + } + + public class MessageLoggedEventArgs(string message, LogType logType) : EventArgs + { + public string Message { get; set; } = message; + public LogType LogType { get; set;} = logType; + + public MessageLoggedEventArgs(string message) : this(message, LogType.Normal) + { + } + } + public class LogMessage(string message, LogType logType) + { + public string Message { get; set; } = message; + public LogType LogType { get; set; } = logType; + } +} diff --git a/Remnant2SaveAnalyzer/Properties/Settings.Designer.cs b/Remnant2SaveAnalyzer/Properties/Settings.Designer.cs index 8c43c38..c462194 100644 --- a/Remnant2SaveAnalyzer/Properties/Settings.Designer.cs +++ b/Remnant2SaveAnalyzer/Properties/Settings.Designer.cs @@ -706,5 +706,41 @@ public bool ShowItemsWithNoPrerequisites { this["ShowItemsWithNoPrerequisites"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool ReportPerformance { + get { + return ((bool)(this["ReportPerformance"])); + } + set { + this["ReportPerformance"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool ReportPlayerInfo { + get { + return ((bool)(this["ReportPlayerInfo"])); + } + set { + this["ReportPlayerInfo"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool DumpAnalyzerJson { + get { + return ((bool)(this["DumpAnalyzerJson"])); + } + set { + this["DumpAnalyzerJson"] = value; + } + } } } diff --git a/Remnant2SaveAnalyzer/Properties/Settings.settings b/Remnant2SaveAnalyzer/Properties/Settings.settings index 9358f4d..da60127 100644 --- a/Remnant2SaveAnalyzer/Properties/Settings.settings +++ b/Remnant2SaveAnalyzer/Properties/Settings.settings @@ -173,5 +173,14 @@ True + + False + + + False + + + False + \ No newline at end of file diff --git a/Remnant2SaveAnalyzer/Remnant2SaveAnalyzer.csproj b/Remnant2SaveAnalyzer/Remnant2SaveAnalyzer.csproj index a41cb70..a10c585 100644 --- a/Remnant2SaveAnalyzer/Remnant2SaveAnalyzer.csproj +++ b/Remnant2SaveAnalyzer/Remnant2SaveAnalyzer.csproj @@ -17,7 +17,7 @@ - + diff --git a/Remnant2SaveAnalyzer/RemnantSave.cs b/Remnant2SaveAnalyzer/RemnantSave.cs index b7533d7..9f22682 100644 --- a/Remnant2SaveAnalyzer/RemnantSave.cs +++ b/Remnant2SaveAnalyzer/RemnantSave.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using lib.remnant2.analyzer.Model; using lib.remnant2.analyzer; using Newtonsoft.Json; -using Wpf.Ui.Controls; +using Remnant2SaveAnalyzer.Properties; namespace Remnant2SaveAnalyzer { @@ -97,195 +98,257 @@ public void UpdateCharacters() bool first = _remnantDataset == null; _remnantDataset = Analyzer.Analyze(_savePath, _remnantDataset); - if (first && _remnantDataset.DebugMessages.Count > 0) + if (first) { - Logger.WarnSilent("BEGIN Analyser warnings"); - foreach (string message in _remnantDataset.DebugMessages) + ReportAnalyzerDebugMessages(); + if (Settings.Default.ReportPerformance) + { + ReportAnalyzerPerformanceMetrics(); + } + + if (Settings.Default.ReportPlayerInfo) { - Logger.WarnSilent(message); + ReportPlayerInfo(); } - Logger.Warn("There were some analyzer warnings"); + if (Settings.Default.DumpAnalyzerJson) + { + DumpAnalyzerJson(); + } } - /* - if (_remnantDataset.DebugPerformance.Count > 0) + } + } + + private void ReportAnalyzerDebugMessages() + { + if (_remnantDataset is { DebugMessages.Count: > 0 }) + { + Logger.WarnSilent("BEGIN Analyser warnings"); + foreach (string message in _remnantDataset.DebugMessages) + { + Logger.WarnSilent(" " + message); + } + Logger.Warn("There were some analyzer warnings"); + } + } + + private void ReportAnalyzerPerformanceMetrics() + { + if (_remnantDataset is { DebugPerformance.Count: > 0 }) + { + Logger.LogSilent("BEGIN Performance metrics"); + foreach (KeyValuePair message in _remnantDataset.DebugPerformance) + { + Logger.LogSilent($" {message.Key}; {message.Value}"); + } + Logger.LogSilent("END Performance metrics"); + } + } + + private void DumpAnalyzerJson() + { + JsonSerializer serializer = new() + { + Formatting = Formatting.Indented, + ContractResolver = new Exporter.IgnorePropertiesResolver([ + "Dataset", + "Parent", + "ProfileSaveFile", + "ProfileNavigator", + "WorldSaveFile", + "WorldNavigator", + "Character" + ]), + NullValueHandling = NullValueHandling.Ignore + }; + + using StreamWriter sw = new(@"analyzer.json"); + using JsonWriter writer = new JsonTextWriter(sw); + serializer.Serialize(writer, _remnantDataset); + } + + private void ReportPlayerInfo() + { + Debug.Assert(_remnantDataset != null, nameof(_remnantDataset) + " != null"); + Logger.LogSilent($"Active character save: save_{_remnantDataset.ActiveCharacterIndex}.sav"); + + // Account Awards ------------------------------------------------------------ + Logger.LogSilent("BEGIN Account Awards"); + foreach (string award in _remnantDataset.AccountAwards) + { + if (award.StartsWith("AccountAward_")) { - Logger.WarnSilent("BEGIN Performance metrics"); - foreach (KeyValuePair message in _remnantDataset.DebugPerformance) + LootItem? lootItem = ItemDb.GetItemByIdOrDefault(award); + if (lootItem == null) + { + Logger.WarnSilent($" UnknownMarker account award: {award}"); + } + else { - Logger.WarnSilent($"{message.Key}; {message.Value}"); + Logger.LogSilent($" Account award: {lootItem.Name}"); } - Logger.WarnSilent("END Performance metrics"); } - */ - if (first) + } + foreach (Dictionary m in ItemDb.Db.Where(x => x["Type"] == "award" && !_remnantDataset.AccountAwards.Exists(y => y == x["Id"]))) + { + Logger.LogSilent($" Missing {Utils.Capitalize(m["Type"])}: {m["Name"]}"); + } + Logger.LogSilent("END Account Awards"); + + for (int index = 0; index < _remnantDataset.Characters.Count; index++) + { + // Character ------------------------------------------------------------ + var character = _remnantDataset.Characters[index]; + int acquired = character.Profile.AcquiredItems; + int missing = character.Profile.MissingItems.Count; + int total = acquired + missing; + Logger.LogSilent($"Character {index+1} (save_{character.Index}), Acquired Items: {acquired}, Missing Items: {missing}, Total: {total}"); + Logger.LogSilent($"Is Hardcore: {character.Profile.IsHardcore}"); + Logger.LogSilent($"Trait Rank: {character.Profile.TraitRank}"); + Logger.LogSilent($"Last Saved Trait Points: {character.Profile.LastSavedTraitPoints}"); + Logger.LogSilent($"Power Level: {character.Profile.PowerLevel}"); + Logger.LogSilent($"Item Level: {character.Profile.ItemLevel}"); + Logger.LogSilent($"Gender: {character.Profile.Gender}"); + + // Inventory ------------------------------------------------------------ + Logger.LogSilent($"BEGIN Inventory, Character {index+1} (save_{character.Index}), mode: inventory"); + + IEnumerable lootItems = character.Profile.Inventory + .Select(ItemDb.GetItemByProfileId) + .Where(x => x != null)!; + + IEnumerable absent = character.Profile.Inventory.Where(x => ItemDb.GetItemByProfileId(x) == null); + foreach (string s in absent) + { + if (!Utils.IsKnownInventoryItem(Utils.GetNameFromProfileId(s))) + { + + Logger.WarnSilent($" Inventory item not found in database: {s}"); + } + } + + List> itemTypes = [.. lootItems + .GroupBy(x => x.Type) + .OrderBy(x=> x.Key)]; + + foreach (IGrouping type in itemTypes) { - Logger.LogSilent($"Active character save: save_{_remnantDataset.ActiveCharacterIndex}.sav"); + Logger.LogSilent(" " + Utils.Capitalize(type.Key)+":"); + if (!type.Any()) + { + Logger.LogSilent(" None"); + } + foreach (LootItem lootItem in type.OrderBy(x => x.Name)) + { + Logger.LogSilent(" " + lootItem.Name); + } + } + + Logger.LogSilent($"END Inventory, Character {index+1} (save_{character.Index}), mode: inventory"); + + + // Campaign ------------------------------------------------------------ + Logger.LogSilent($"Save play time: {Utils.FormatPlaytime(character.Save.Playtime)}"); + foreach (Zone z in character.Save.Campaign.Zones) + { + Logger.LogSilent($"Campaign story: {z.Story}"); + } + Logger.LogSilent($"Campaign difficulty: {character.Save.Campaign.Difficulty}"); + Logger.LogSilent($"Campaign play time: {Utils.FormatPlaytime(character.Save.Campaign.Playtime)}"); + + // Campaign Quest Inventory ------------------------------------------------------------ + Logger.LogSilent($"BEGIN Quest inventory, Character {index+1} (save_{character.Index}), mode: campaign"); + lootItems = character.Save.Campaign.QuestInventory.Select(ItemDb.GetItemByProfileId).Where(x => x != null).OrderBy(x => x!.Name)!; + absent = character.Save.Campaign.QuestInventory.Where(x => ItemDb.GetItemByProfileId(x) == null); + foreach (string s in absent) + { + Logger.WarnSilent($" Quest item not found in database: {s}"); + } + + foreach (LootItem lootItem in lootItems) + { + Logger.LogSilent(" " + lootItem.Name); + } + Logger.LogSilent($"END Quest inventory, Character {index+1} (save_{character.Index}), mode: campaign"); + + if (character.Save.Adventure != null) + { + // Adventure ------------------------------------------------------------ + Logger.LogSilent($"Adventure story: {character.Save.Adventure.Zones[0].Story}"); + Logger.LogSilent($"Adventure difficulty: {character.Save.Adventure.Difficulty}"); + Logger.LogSilent($"Adventure play time: {Utils.FormatPlaytime(character.Save.Adventure.Playtime)}"); + + // Adventure Quest Inventory ------------------------------------------------------------ + Logger.LogSilent($"BEGIN Quest inventory, Character {index+1} (save_{character.Index}), mode: adventure"); + lootItems = character.Save.Adventure.QuestInventory.Select(ItemDb.GetItemByProfileId).Where(x => x != null).OrderBy(x => x!.Name)!; + absent = character.Save.Adventure.QuestInventory.Where(x => ItemDb.GetItemByProfileId(x) == null); + foreach (string s in absent) + { + Logger.WarnSilent($" Quest item not found in database: {s}"); + } - foreach (string award in _remnantDataset.AccountAwards) + foreach (LootItem lootItem in lootItems) { - if (award.StartsWith("AccountAward_")) - { - LootItem? lootItem = ItemDb.GetItemByIdOrDefault(award); - if (lootItem == null) - { - Logger.WarnSilent($"UnknownMarker account award: {award}"); - } - else - { - Logger.LogSilent($"Account award: {lootItem.Name}"); - } - } + Logger.LogSilent(" " + lootItem.Name); } - for (int index = 0; index < _remnantDataset.Characters.Count; index++) + Logger.LogSilent($"END Quest inventory, Character {index+1} (save_{character.Index}), mode: adventure"); + } + + // Cass shop ------------------------------------------------------------ + Logger.LogSilent($"BEGIN Cass shop, Character {index+1} (save_{character.Index})"); + foreach (LootItem lootItem in character.Save.CassShop) + { + Logger.LogSilent(" " + lootItem.Name); + } + Logger.LogSilent($"END Cass shop, Character {index+1} (save_{character.Index})"); + + // Quest log ------------------------------------------------------------ + Logger.LogSilent($"BEGIN Quest log, Character {index+1} (save_{character.Index})"); + lootItems = character.Save.QuestCompletedLog + .Select(x => ItemDb.GetItemByIdOrDefault($"Quest_{x}")).Where(x => x != null)!; + absent = character.Save.QuestCompletedLog.Where(x => ItemDb.GetItemByIdOrDefault($"Quest_{x}") == null); + foreach (string s in absent) + { + Logger.WarnSilent($" Quest not found in database: {s}"); + } + foreach (LootItem lootItem in lootItems) + { + Logger.LogSilent($" {lootItem.Name} ({lootItem.Item["Subtype"]})"); + } + Logger.LogSilent($"END Quest log, Character {index+1} (save_{character.Index})"); + + // Achievements ------------------------------------------------------------ + Logger.LogSilent($"BEGIN Achievements for Character {index+1} (save_{character.Index})"); + foreach (ObjectiveProgress objective in character.Profile.Objectives) + { + if (objective.Type == "achievement") { - var character = _remnantDataset.Characters[index]; - int acquired = character.Profile.AcquiredItems; - int missing = character.Profile.MissingItems.Count; - int total = acquired + missing; - Logger.LogSilent($"Character {index+1} (save_{character.Index}), Acquired Items: {acquired}, Missing Items: {missing}, Total: {total}"); - Logger.LogSilent($"Is Hardcore: {character.Profile.IsHardcore}"); - Logger.LogSilent($"Trait Rank: {character.Profile.TraitRank}"); - Logger.LogSilent($"Last Saved Trait Points: {character.Profile.LastSavedTraitPoints}"); - Logger.LogSilent($"Power Level: {character.Profile.PowerLevel}"); - Logger.LogSilent($"Item Level: {character.Profile.ItemLevel}"); - Logger.LogSilent($"Gender: {character.Profile.Gender}"); - Logger.LogSilent($"BEGIN Inventory, Character {index+1} (save_{character.Index}), mode: inventory"); - - IEnumerable lootItems = character.Profile.Inventory - .Select(ItemDb.GetItemByProfileId) - .Where(x => x != null)!; -; - - IEnumerable absent = character.Profile.Inventory.Where(x => ItemDb.GetItemByProfileId(x) == null); - foreach (string s in absent) - { - //Logger.WarnSilent($"Inventory item not found in database: {s}"); - } - - List> itemTypes = [.. lootItems - .GroupBy(x => x.Type) - .OrderBy(x=> x.Key)]; - - foreach (IGrouping type in itemTypes) - { - Logger.LogSilent(Utils.Capitalize(type.Key)+":"); - if (!type.Any()) - { - Logger.LogSilent(" None"); - } - foreach (LootItem lootItem in type.OrderBy(x => x.Name)) - { - Logger.LogSilent(" " + lootItem.Name); - } - } - - Logger.LogSilent($"END Inventory, Character {index+1} (save_{character.Index}), mode: inventory"); - - Logger.LogSilent($"Save play time: {Utils.FormatPlaytime(character.Save.Playtime)}"); - foreach (Zone z in character.Save.Campaign.Zones) - { - Logger.LogSilent($"Campaign story: {z.Story}"); - } - Logger.LogSilent($"Campaign difficulty: {character.Save.Campaign.Difficulty}"); - Logger.LogSilent($"Campaign play time: {Utils.FormatPlaytime(character.Save.Campaign.Playtime)}"); - Logger.LogSilent($"BEGIN Quest inventory, Character {index+1} (save_{character.Index}), mode: campaign"); - lootItems = character.Save.Campaign.QuestInventory.Select(ItemDb.GetItemByProfileId).Where(x => x != null).OrderBy(x => x!.Name)!; - absent = character.Save.Campaign.QuestInventory.Where(x => ItemDb.GetItemByProfileId(x) == null); - foreach (string s in absent) - { - Logger.WarnSilent($"Quest item not found in database: {s}"); - } - - foreach (LootItem lootItem in lootItems) - { - Logger.LogSilent(lootItem.Name); - } - Logger.LogSilent($"END Quest inventory, Character {index+1} (save_{character.Index}), mode: campaign"); - - if (character.Save.Adventure != null) - { - Logger.LogSilent($"Adventure story: {character.Save.Adventure.Zones[0].Story}"); - Logger.LogSilent($"Adventure difficulty: {character.Save.Adventure.Difficulty}"); - Logger.LogSilent($"Adventure play time: {Utils.FormatPlaytime(character.Save.Adventure.Playtime)}"); - Logger.LogSilent($"BEGIN Quest inventory, Character {index+1} (save_{character.Index}), mode: adventure"); - lootItems = character.Save.Adventure.QuestInventory.Select(ItemDb.GetItemByProfileId).Where(x => x != null).OrderBy(x => x!.Name)!; - absent = character.Save.Adventure.QuestInventory.Where(x => ItemDb.GetItemByProfileId(x) == null); - foreach (string s in absent) - { - Logger.WarnSilent($"Quest item not found in database: {s}"); - } - - foreach (LootItem lootItem in lootItems) - { - Logger.LogSilent(lootItem.Name); - } - - Logger.LogSilent($"END Quest inventory, Character {index+1} (save_{character.Index}), mode: adventure"); - } - - Logger.LogSilent($"BEGIN Cass shop, Character {index+1} (save_{character.Index})"); - foreach (LootItem lootItem in character.Save.CassShop) - { - Logger.LogSilent(lootItem.Name); - } - Logger.LogSilent($"END Cass shop, Character {index+1} (save_{character.Index})"); - - Logger.LogSilent($"BEGIN Quest log, Character {index+1} (save_{character.Index})"); - lootItems = character.Save.QuestCompletedLog - .Select(x => ItemDb.GetItemByIdOrDefault($"Quest_{x}")).Where(x => x != null)!; - absent = character.Save.QuestCompletedLog.Where(x => ItemDb.GetItemByIdOrDefault($"Quest_{x}") == null); - foreach (string s in absent) - { - Logger.WarnSilent($"Quest not found in database: {s}"); - } - foreach (LootItem lootItem in lootItems) - { - Logger.LogSilent($"{lootItem.Name} ({lootItem.Item["Subtype"]})"); - } - Logger.LogSilent($"END Quest log, Character {index+1} (save_{character.Index})"); - - Logger.LogSilent($"BEGIN Achievements for Character {index+1} (save_{character.Index})"); - foreach (ObjectiveProgress objective in character.Profile.Objectives) - { - if (objective.Type == "achievement") - { - Logger.LogSilent($"{Utils.Capitalize(objective.Type)}: {objective.Description} - {objective.Progress}"); - } - } - Logger.LogSilent($"END Achievements for Character {index+1} (save_{character.Index})"); - Logger.LogSilent($"BEGIN Challenges for Character {index+1} (save_{character.Index})"); - foreach (ObjectiveProgress objective in character.Profile.Objectives) - { - if (objective.Type == "challenge") - { - Logger.LogSilent($"{Utils.Capitalize(objective.Type)}: {objective.Description} - {objective.Progress}"); - } - } - Logger.LogSilent($"END Challenges for Character {index+1} (save_{character.Index})"); + Logger.LogSilent($" {Utils.Capitalize(objective.Type)}: {objective.Description} - {objective.Progress}"); } - /* - JsonSerializer serializer = new() + } + + foreach (Dictionary m in ItemDb.Db.Where(x => x["Type"] == "achievement" && !character.Profile.Objectives.Exists(y => y.Id == x["Id"]))) + { + Logger.LogSilent($" Missing {Utils.Capitalize(m["Type"])}: {m["Name"]}"); + } + + Logger.LogSilent($"END Achievements for Character {index+1} (save_{character.Index})"); + + // Challenges ------------------------------------------------------------ + Logger.LogSilent($"BEGIN Challenges for Character {index+1} (save_{character.Index})"); + foreach (ObjectiveProgress objective in character.Profile.Objectives) + { + if (objective.Type == "challenge") { - Formatting = Formatting.Indented, - ContractResolver = new Analyzer.IgnorePropertiesResolver([ - "Dataset", - "Parent", - "ProfileSaveFile", - "ProfileNavigator", - "WorldSaveFile", - "WorldNavigator", - "Character" - ]), - NullValueHandling = NullValueHandling.Ignore - }; - - using StreamWriter sw = new(@"d:\test.json"); - using JsonWriter writer = new JsonTextWriter(sw); - serializer.Serialize(writer, _remnantDataset); - */ + Logger.LogSilent($" {Utils.Capitalize(objective.Type)}: {objective.Description} - {objective.Progress}"); + } + } + foreach (Dictionary m in ItemDb.Db.Where(x => x["Type"] == "challenge" && !character.Profile.Objectives.Exists(y => y.Id == x["Id"]))) + { + Logger.LogSilent($" Missing {Utils.Capitalize(m["Type"])}: {m["Name"]}"); } + Logger.LogSilent($"END Challenges for Character {index+1} (save_{character.Index})"); } } diff --git a/Remnant2SaveAnalyzer/Views/Pages/SettingsPage.xaml b/Remnant2SaveAnalyzer/Views/Pages/SettingsPage.xaml index d0a93ed..ea8a9e9 100644 --- a/Remnant2SaveAnalyzer/Views/Pages/SettingsPage.xaml +++ b/Remnant2SaveAnalyzer/Views/Pages/SettingsPage.xaml @@ -275,6 +275,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Remnant2SaveAnalyzer/Views/Pages/WorldAnalyzerPage.xaml.cs b/Remnant2SaveAnalyzer/Views/Pages/WorldAnalyzerPage.xaml.cs index 512f109..18141cf 100644 --- a/Remnant2SaveAnalyzer/Views/Pages/WorldAnalyzerPage.xaml.cs +++ b/Remnant2SaveAnalyzer/Views/Pages/WorldAnalyzerPage.xaml.cs @@ -188,7 +188,7 @@ private void SavePlaintextButton_Click(object sender, RoutedEventArgs e) Logger.Error(Loc.T("export_save_invalid_folder_error")); return; } - Analyzer.Export(openFolderDialog.SelectedPath, _save.SaveFolderPath, Properties.Settings.Default.ExportCopy, Properties.Settings.Default.ExportDecoded, Properties.Settings.Default.ExportJson); + Exporter.Export(openFolderDialog.SelectedPath, _save.SaveFolderPath, Properties.Settings.Default.ExportCopy, Properties.Settings.Default.ExportDecoded, Properties.Settings.Default.ExportJson); Logger.Success(Loc.T($"Exported save files successfully to {openFolderDialog.SelectedPath}")); } catch (Exception ex) { diff --git a/Remnant2SaveAnalyzer/locales/Strings.Designer.cs b/Remnant2SaveAnalyzer/locales/Strings.Designer.cs index 1231648..4ecdbad 100644 --- a/Remnant2SaveAnalyzer/locales/Strings.Designer.cs +++ b/Remnant2SaveAnalyzer/locales/Strings.Designer.cs @@ -294,6 +294,15 @@ public static string chkCreateLogFile_ToolTip { } } + /// + /// Looks up a localized string similar to Dump Analyzer data structures to analyzer.json . + /// + public static string chkDumpAnalyzerJson { + get { + return ResourceManager.GetString("chkDumpAnalyzerJson", resourceCulture); + } + } + /// /// Looks up a localized string similar to When exporting, export copies of saves. /// @@ -348,6 +357,24 @@ public static string chkOpacity_note_Text { } } + /// + /// Looks up a localized string similar to Log Performance metrics. + /// + public static string chkReportPerformance { + get { + return ResourceManager.GetString("chkReportPerformance", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Log Player debug info. + /// + public static string chkReportPlayerInfo { + get { + return ResourceManager.GetString("chkReportPlayerInfo", resourceCulture); + } + } + /// /// Looks up a localized string similar to Show zone connections. /// @@ -546,6 +573,24 @@ public static string Date { } } + /// + /// Looks up a localized string similar to Debug. + /// + public static string Debug { + get { + return ResourceManager.GetString("Debug", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enabling these could cause performance degradation and flood the logs. + /// + public static string debug_note { + get { + return ResourceManager.GetString("debug_note", resourceCulture); + } + } + /// /// Looks up a localized string similar to Delete. /// diff --git a/Remnant2SaveAnalyzer/locales/Strings.resx b/Remnant2SaveAnalyzer/locales/Strings.resx index 4754961..618f74b 100644 --- a/Remnant2SaveAnalyzer/locales/Strings.resx +++ b/Remnant2SaveAnalyzer/locales/Strings.resx @@ -534,4 +534,19 @@ Show campaign/adventure items with a missing prerequisite that did not roll in the compaign/adventure + + Dump Analyzer data structures to analyzer.json + + + Log Performance metrics + + + Log Player debug info + + + Debug + + + Enabling these could cause performance degradation and flood the logs + \ No newline at end of file