From 3dcd56cf7530d1d1586a3af34b2af9c1cb973cbb Mon Sep 17 00:00:00 2001 From: Jebzou <22751386+Jebzou@users.noreply.github.com> Date: Mon, 9 Feb 2026 22:23:36 +0100 Subject: [PATCH 1/9] Reworked the reworked logic --- .../Extensions/QuestIdentifierExtensions.cs | 33 --------- .../Types/Quests/IQuestIdentifier.cs | 7 -- .../Types/Quests/QuestProgressResetType.cs | 7 -- .../Serialization/Quests/QuestMetadata.cs | 2 +- ElectronicObserver/Data/Quest/ProgressData.cs | 10 ++- ElectronicObserver/Data/QuestData.cs | 74 +++++++++++++++++-- ElectronicObserver/Data/QuestManager.cs | 3 +- .../Data/Translation/QuestsMetadata.cs | 9 ++- .../QuestTrackerManager/Models/QuestModel.cs | 41 +--------- .../Window/Wpf/Quest/QuestViewModel.cs | 3 +- 10 files changed, 91 insertions(+), 98 deletions(-) delete mode 100644 ElectronicObserver.Core/Types/Extensions/QuestIdentifierExtensions.cs delete mode 100644 ElectronicObserver.Core/Types/Quests/IQuestIdentifier.cs delete mode 100644 ElectronicObserver.Core/Types/Quests/QuestProgressResetType.cs diff --git a/ElectronicObserver.Core/Types/Extensions/QuestIdentifierExtensions.cs b/ElectronicObserver.Core/Types/Extensions/QuestIdentifierExtensions.cs deleted file mode 100644 index 7430f1b11..000000000 --- a/ElectronicObserver.Core/Types/Extensions/QuestIdentifierExtensions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Core.Types.Quests; -using ElectronicObserver.Core.Types.Serialization.Quests; - -namespace ElectronicObserver.Core.Types.Extensions; - -public static class QuestIdentifierExtensions -{ - public static bool ProgressResetsDaily(this IQuestIdentifier questData, List questsMetadata) - { - // Dailies - if (questData.QuestResetType is QuestResetType.Daily) return true; - - return questData.QuestID switch - { - // Quests that are not daily but only appear on some days : - 211 => true, // 空母3 - 212 => true, // 輸送5 - - // Some PVP quests - 311 => true, - 330 => true, - 337 => true, - 339 => true, - 341 => true, - 342 => true, - 348 => true, - - // Special cases - _ => questsMetadata.Find(quest => quest.ApiId == questData.QuestID)?.QuestProgressResetType is QuestProgressResetType.Daily, - }; - } -} diff --git a/ElectronicObserver.Core/Types/Quests/IQuestIdentifier.cs b/ElectronicObserver.Core/Types/Quests/IQuestIdentifier.cs deleted file mode 100644 index d2a11555b..000000000 --- a/ElectronicObserver.Core/Types/Quests/IQuestIdentifier.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ElectronicObserver.Core.Types.Quests; - -public interface IQuestIdentifier -{ - public int QuestID { get; } - public QuestResetType QuestResetType { get; } -} diff --git a/ElectronicObserver.Core/Types/Quests/QuestProgressResetType.cs b/ElectronicObserver.Core/Types/Quests/QuestProgressResetType.cs deleted file mode 100644 index 58c0ac928..000000000 --- a/ElectronicObserver.Core/Types/Quests/QuestProgressResetType.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ElectronicObserver.Core.Types.Quests; - -public enum QuestProgressResetType -{ - Unknown = 0, - Daily = 1, -} diff --git a/ElectronicObserver.Core/Types/Serialization/Quests/QuestMetadata.cs b/ElectronicObserver.Core/Types/Serialization/Quests/QuestMetadata.cs index 939a65a1f..fc31f641f 100644 --- a/ElectronicObserver.Core/Types/Serialization/Quests/QuestMetadata.cs +++ b/ElectronicObserver.Core/Types/Serialization/Quests/QuestMetadata.cs @@ -13,5 +13,5 @@ public record QuestMetadata public DateTime? EndTime { get; set; } [JsonPropertyName("resetType")] - public QuestProgressResetType? QuestProgressResetType { get; set; } + public QuestResetType? QuestProgressResetType { get; set; } } diff --git a/ElectronicObserver/Data/Quest/ProgressData.cs b/ElectronicObserver/Data/Quest/ProgressData.cs index bc3e22ad6..5cc734412 100644 --- a/ElectronicObserver/Data/Quest/ProgressData.cs +++ b/ElectronicObserver/Data/Quest/ProgressData.cs @@ -9,7 +9,7 @@ namespace ElectronicObserver.Data.Quest; /// 任務の進捗を管理する基底クラスです。 /// [DataContract(Name = "ProgressData")] -public abstract class ProgressData : IIdentifiable, IQuestIdentifier +public abstract class ProgressData : IIdentifiable { /// @@ -198,6 +198,14 @@ public virtual void ApplyTemporaryProgress(QuestData q) } } + public QuestResetType GetProgressResetType() => TryGetQuest()?.GetProgressResetType() ?? QuestResetType.Unknown; + + private QuestData? TryGetQuest() + { + if (!KCDatabase.Instance.Quest.Quests.ContainsKey(QuestID)) return null; + + return KCDatabase.Instance.Quest[QuestID]; + } /// /// この任務の達成に必要な条件を表す文字列を返します。 diff --git a/ElectronicObserver/Data/QuestData.cs b/ElectronicObserver/Data/QuestData.cs index 88d7c63d4..68650a3f9 100644 --- a/ElectronicObserver/Data/QuestData.cs +++ b/ElectronicObserver/Data/QuestData.cs @@ -1,12 +1,14 @@ -using ElectronicObserver.Core.Types.Data; +using System.Collections.Generic; +using ElectronicObserver.Core.Types.Data; using ElectronicObserver.Core.Types.Quests; +using ElectronicObserver.Core.Types.Serialization.Quests; namespace ElectronicObserver.Data; /// /// 任務のデータを保持します。 /// -public class QuestData : ResponseWrapper, IIdentifiable, IQuestIdentifier +public class QuestData : ResponseWrapper, IIdentifiable { /// @@ -25,8 +27,6 @@ public class QuestData : ResponseWrapper, IIdentifiable, IQuestIdentifier /// public int Type => (int)RawData.api_type; - public QuestResetType QuestResetType => (QuestResetType)Type; - /// /// 周期アイコン種別 /// 1=単発, 2=デイリー, 3=ウィークリー, 6=マンスリー, 7=他(輸送5と空母3,クォータリー), 100+x=イヤーリー(x月-) @@ -88,7 +88,71 @@ public int State /// public int Progress => (int)RawData.api_progress_flag; - + public QuestResetType GetProgressResetType() + { + Dictionary questsMetadata = KCDatabase.Instance.Translation.QuestsMetadata.QuestsMetadataList; + + if (questsMetadata.TryGetValue(QuestID, out QuestMetadata? metadata) && metadata.QuestProgressResetType is { } resetType) + { + return resetType; + } + + return Type switch + { + 1 => QuestResetType.Daily, + 2 => QuestResetType.Weekly, + 3 => QuestResetType.Monthly, + 4 => QuestResetType.Never, + 5 => LabelType switch + { + // 2, 3, 6 should never happen + 2 => QuestResetType.Daily, + 3 => QuestResetType.Weekly, + 6 => QuestResetType.Monthly, + 7 => ID switch + { + // BD4 - 3 carriers + 211 => QuestResetType.Daily, + // BD6 - 5 transports + 212 => QuestResetType.Daily, + + // this will be incorrect if they add any new odd daily quests + _ => QuestResetType.Quarterly + }, + 101 => QuestResetType.January, + 102 => QuestResetType.February, + 103 => QuestResetType.March, + 104 => QuestResetType.April, + 105 => QuestResetType.May, + 106 => QuestResetType.June, + 107 => QuestResetType.July, + 108 => QuestResetType.August, + 109 => QuestResetType.September, + 110 => QuestResetType.October, + 111 => QuestResetType.November, + 112 => QuestResetType.December, + + _ => QuestResetType.Unknown + }, + + _ => QuestResetType.Unknown + }; + /* + return questData.QuestID switch + { + // Some PVP quests + 311 => true, + 330 => true, + 337 => true, + 339 => true, + 341 => true, + 342 => true, + 348 => true, + + // Special cases + _ => questsMetadata.Find(quest => quest.ApiId == questData.QuestID)?.QuestProgressResetType is QuestProgressResetType.Daily, + };*/ + } public int ID => QuestID; public override string ToString() => $"[{QuestID}] {Name}"; diff --git a/ElectronicObserver/Data/QuestManager.cs b/ElectronicObserver/Data/QuestManager.cs index 8648c5521..f153b16d1 100644 --- a/ElectronicObserver/Data/QuestManager.cs +++ b/ElectronicObserver/Data/QuestManager.cs @@ -3,6 +3,7 @@ using ElectronicObserver.Core; using ElectronicObserver.Core.Types.Data; using ElectronicObserver.Core.Types.Extensions; +using ElectronicObserver.Core.Types.Quests; namespace ElectronicObserver.Data; @@ -56,7 +57,7 @@ public override void LoadFromResponse(string apiname, dynamic data) //周期任務削除 if (DateTimeHelper.IsCrossedDay(progress.LastUpdateTime, 5, 0, 0)) { - progress.Progresses.RemoveAll(p => p.ProgressResetsDaily(KCDatabase.Instance.Translation.QuestsMetadata.QuestsMetadataList)); + progress.Progresses.RemoveAll(p => p.GetProgressResetType() is QuestResetType.Daily); Quests.RemoveAll(q => q.Type == 1 || q.QuestID == 211 /* 空母3 */ || q.QuestID == 212 /* 輸送5 */ || q.QuestID == 311 /* 演習勝利7 */ ); } if (DateTimeHelper.IsCrossedWeek(progress.LastUpdateTime, DayOfWeek.Monday, 5, 0, 0)) diff --git a/ElectronicObserver/Data/Translation/QuestsMetadata.cs b/ElectronicObserver/Data/Translation/QuestsMetadata.cs index 1297a8edd..218226897 100644 --- a/ElectronicObserver/Data/Translation/QuestsMetadata.cs +++ b/ElectronicObserver/Data/Translation/QuestsMetadata.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using ElectronicObserver.Core.Types.Serialization.Quests; namespace ElectronicObserver.Data.Translation; @@ -8,7 +9,7 @@ public class QuestsMetadata : TranslationBase { private string QuestMetadataPath => Path.Join(DataAndTranslationManager.DataFolder, "QuestsMetadata.json"); - public List QuestsMetadataList { get; private set; } = []; + public Dictionary QuestsMetadataList { get; private set; } = []; public sealed override void Initialize() { @@ -25,6 +26,10 @@ private void LoadDictionary(string path) QuestsMetadataList.Clear(); List? json = Load>(path); - if (json != null) QuestsMetadataList = json; + + if (json is { } list) + { + QuestsMetadataList = list.ToDictionary(item => item.ApiId, item => item); + } } } diff --git a/ElectronicObserver/Window/Dialog/QuestTrackerManager/Models/QuestModel.cs b/ElectronicObserver/Window/Dialog/QuestTrackerManager/Models/QuestModel.cs index 76c01b8f4..6bc1a1f91 100644 --- a/ElectronicObserver/Window/Dialog/QuestTrackerManager/Models/QuestModel.cs +++ b/ElectronicObserver/Window/Dialog/QuestTrackerManager/Models/QuestModel.cs @@ -14,46 +14,7 @@ public record QuestModel([property: Key(0)] int Id) [IgnoreMember] public QuestCategory Category => (QuestCategory)(TryGetQuest()?.Category ?? 0); [IgnoreMember] public int State => TryGetQuest()?.State ?? 0; [IgnoreMember] - public QuestResetType ResetType => TryGetQuest()?.Type switch - { - 1 => QuestResetType.Daily, - 2 => QuestResetType.Weekly, - 3 => QuestResetType.Monthly, - 4 => QuestResetType.Never, - 5 => TryGetQuest()?.LabelType switch - { - // 2, 3, 6 should never happen - 2 => QuestResetType.Daily, - 3 => QuestResetType.Weekly, - 6 => QuestResetType.Monthly, - 7 => TryGetQuest()?.ID switch - { - // BD4 - 3 carriers - 211 => QuestResetType.Daily, - // BD6 - 5 transports - 212 => QuestResetType.Daily, - - // this will be incorrect if they add any new odd daily quests - _ => QuestResetType.Quarterly - }, - 101 => QuestResetType.January, - 102 => QuestResetType.February, - 103 => QuestResetType.March, - 104 => QuestResetType.April, - 105 => QuestResetType.May, - 106 => QuestResetType.June, - 107 => QuestResetType.July, - 108 => QuestResetType.August, - 109 => QuestResetType.September, - 110 => QuestResetType.October, - 111 => QuestResetType.November, - 112 => QuestResetType.December, - - _ => QuestResetType.Unknown - }, - - _ => QuestResetType.Unknown - }; + public QuestResetType ResetType => TryGetQuest()?.GetProgressResetType() ?? QuestResetType.Unknown; [IgnoreMember] public string Display => $"{Code}: {Name} (ID: {Id})"; diff --git a/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs b/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs index e3b66b722..ef842331a 100644 --- a/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs +++ b/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs @@ -13,6 +13,7 @@ using DynaJson; using ElectronicObserver.Core.Services; using ElectronicObserver.Core.Types.Extensions; +using ElectronicObserver.Core.Types.Quests; using ElectronicObserver.Data; using ElectronicObserver.Data.Quest; using ElectronicObserver.Resource; @@ -418,7 +419,7 @@ private void Updated() row.QuestView_NameToolTip += $"\r\n{tracker?.GroupConditions.Display}"; } - if (q.Type != 1 && q.ProgressResetsDaily(KCDatabase.Instance.Translation.QuestsMetadata.QuestsMetadataList)) + if (q.Type != 1 && q.GetProgressResetType() is QuestResetType.Daily) { row.QuestView_NameToolTip += "\r\n"; row.QuestView_NameToolTipExtra = $"{FormQuest.QuestView_ProgressResetsDaily}"; From e7694fd09742ab0858458e1058cf5220fa21a3e0 Mon Sep 17 00:00:00 2001 From: Jebzou <22751386+Jebzou@users.noreply.github.com> Date: Mon, 9 Feb 2026 22:28:35 +0100 Subject: [PATCH 2/9] Removed hardcoded quest ids --- ElectronicObserver/Data/QuestData.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/ElectronicObserver/Data/QuestData.cs b/ElectronicObserver/Data/QuestData.cs index 68650a3f9..c2db9abb0 100644 --- a/ElectronicObserver/Data/QuestData.cs +++ b/ElectronicObserver/Data/QuestData.cs @@ -137,21 +137,6 @@ public QuestResetType GetProgressResetType() _ => QuestResetType.Unknown }; - /* - return questData.QuestID switch - { - // Some PVP quests - 311 => true, - 330 => true, - 337 => true, - 339 => true, - 341 => true, - 342 => true, - 348 => true, - - // Special cases - _ => questsMetadata.Find(quest => quest.ApiId == questData.QuestID)?.QuestProgressResetType is QuestProgressResetType.Daily, - };*/ } public int ID => QuestID; From bf50da5e74fd8d32fcce09404496dea7b46a3c14 Mon Sep 17 00:00:00 2001 From: Jebzou <22751386+Jebzou@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:34:13 +0100 Subject: [PATCH 3/9] Display quest end time --- .../Translations/FormQuestTranslationViewModel.cs | 1 + ElectronicObserver/Window/GeneralRes.en.resx | 3 +++ ElectronicObserver/Window/GeneralRes.resx | 3 +++ .../Window/Wpf/Quest/QuestViewModel.cs | 15 ++++++++++++++- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ElectronicObserver/ViewModels/Translations/FormQuestTranslationViewModel.cs b/ElectronicObserver/ViewModels/Translations/FormQuestTranslationViewModel.cs index 33b6bcb14..dca063cda 100644 --- a/ElectronicObserver/ViewModels/Translations/FormQuestTranslationViewModel.cs +++ b/ElectronicObserver/ViewModels/Translations/FormQuestTranslationViewModel.cs @@ -9,6 +9,7 @@ public class FormQuestTranslationViewModel : TranslationBaseViewModel public string QuestView_Name => GeneralRes.QuestName.Replace("_", "__").Replace("&", "_"); public string QuestView_Progress => GeneralRes.Progress.Replace("_", "__").Replace("&", "_"); public string QuestView_ProgressResetsDaily => GeneralRes.ProgressResetsDaily; + public string QuestView_EndsOn => GeneralRes.QuestEndsOn; public string MenuMain_QuestFilter => QuestResources.MenuMain_QuestFilter.Replace("_", "__").Replace("&", "_"); public string ShowInProgressOnly => GeneralRes.ShowInProgressOnly.Replace("_", "__").Replace("&", "_"); diff --git a/ElectronicObserver/Window/GeneralRes.en.resx b/ElectronicObserver/Window/GeneralRes.en.resx index f806bcd30..605e86e2b 100644 --- a/ElectronicObserver/Window/GeneralRes.en.resx +++ b/ElectronicObserver/Window/GeneralRes.en.resx @@ -851,4 +851,7 @@ Please click here to restart. Progress resets daily + + Ends on {0:f} + \ No newline at end of file diff --git a/ElectronicObserver/Window/GeneralRes.resx b/ElectronicObserver/Window/GeneralRes.resx index 6b10fa094..29344ce95 100644 --- a/ElectronicObserver/Window/GeneralRes.resx +++ b/ElectronicObserver/Window/GeneralRes.resx @@ -850,4 +850,7 @@ デイリーリセット + + ??? (Ends on {0:f}) + \ No newline at end of file diff --git a/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs b/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs index ef842331a..e6919587a 100644 --- a/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs +++ b/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs @@ -14,6 +14,7 @@ using ElectronicObserver.Core.Services; using ElectronicObserver.Core.Types.Extensions; using ElectronicObserver.Core.Types.Quests; +using ElectronicObserver.Core.Types.Serialization.Quests; using ElectronicObserver.Data; using ElectronicObserver.Data.Quest; using ElectronicObserver.Resource; @@ -419,10 +420,22 @@ private void Updated() row.QuestView_NameToolTip += $"\r\n{tracker?.GroupConditions.Display}"; } + row.QuestView_NameToolTipExtra = ""; + if (q.Type != 1 && q.GetProgressResetType() is QuestResetType.Daily) + { + row.QuestView_NameToolTipExtra += $"{FormQuest.QuestView_ProgressResetsDaily}"; + } + + if (KCDatabase.Instance.Translation.QuestsMetadata.QuestsMetadataList.TryGetValue(q.ID, out QuestMetadata? metadata) && metadata.EndTime is DateTime endTime) + { + endTime = endTime - TimeSpan.FromHours(9) + TimeZoneInfo.Local.BaseUtcOffset; + row.QuestView_NameToolTipExtra += string.Format(FormQuest.QuestView_EndsOn, endTime); + } + + if (row.QuestView_NameToolTipExtra?.Length > 0) { row.QuestView_NameToolTip += "\r\n"; - row.QuestView_NameToolTipExtra = $"{FormQuest.QuestView_ProgressResetsDaily}"; } } { From 905a4dad711b047f94b77e10e30d6803e10cf9e2 Mon Sep 17 00:00:00 2001 From: Jebzou <22751386+Jebzou@users.noreply.github.com> Date: Tue, 10 Feb 2026 08:08:00 +0100 Subject: [PATCH 4/9] Add ending quest list to info view --- ElectronicObserver/Data/QuestData.cs | 13 ++++++++- ElectronicObserver/Window/GeneralRes.en.resx | 3 ++ ElectronicObserver/Window/GeneralRes.resx | 3 ++ .../InformationView/InformationViewModel.cs | 29 ++++++++++++++++++- .../Window/Wpf/Quest/QuestViewModel.cs | 3 +- 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/ElectronicObserver/Data/QuestData.cs b/ElectronicObserver/Data/QuestData.cs index c2db9abb0..9e44eee58 100644 --- a/ElectronicObserver/Data/QuestData.cs +++ b/ElectronicObserver/Data/QuestData.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using ElectronicObserver.Core.Types.Data; using ElectronicObserver.Core.Types.Quests; using ElectronicObserver.Core.Types.Serialization.Quests; @@ -139,6 +140,16 @@ public QuestResetType GetProgressResetType() }; } + public DateTime? GetEndDateTime() + { + if (KCDatabase.Instance.Translation.QuestsMetadata.QuestsMetadataList.TryGetValue(QuestID, out QuestMetadata? metadata) && metadata.EndTime is { } endTime) + { + return endTime - TimeSpan.FromHours(9) + TimeZoneInfo.Local.BaseUtcOffset; + } + + return null; + } + public int ID => QuestID; public override string ToString() => $"[{QuestID}] {Name}"; } diff --git a/ElectronicObserver/Window/GeneralRes.en.resx b/ElectronicObserver/Window/GeneralRes.en.resx index 605e86e2b..a4808a811 100644 --- a/ElectronicObserver/Window/GeneralRes.en.resx +++ b/ElectronicObserver/Window/GeneralRes.en.resx @@ -854,4 +854,7 @@ Please click here to restart. Ends on {0:f} + + Quests that ends on {0:f} + \ No newline at end of file diff --git a/ElectronicObserver/Window/GeneralRes.resx b/ElectronicObserver/Window/GeneralRes.resx index 29344ce95..74abe2dd2 100644 --- a/ElectronicObserver/Window/GeneralRes.resx +++ b/ElectronicObserver/Window/GeneralRes.resx @@ -853,4 +853,7 @@ ??? (Ends on {0:f}) + + ??? (Quests that ends on {0:f}) + \ No newline at end of file diff --git a/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs b/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs index cc3fdb710..2de3026fd 100644 --- a/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs +++ b/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; @@ -6,6 +7,7 @@ using ElectronicObserver.Core.Types; using ElectronicObserver.Data; using ElectronicObserver.Data.DiscordRPC; +using ElectronicObserver.Data.PoiDbSubmission.PoiDbBattleSubmission; using ElectronicObserver.Observer; using ElectronicObserver.Resource; using ElectronicObserver.Utility.Data; @@ -46,6 +48,7 @@ public InformationViewModel() : base("Info", "Information", IconContent.FormInfo o.ApiReqMap_Next.ResponseReceived += Updated; o.ApiReqPractice_Battle.ResponseReceived += Updated; o.ApiGetMember_SortieConditions.ResponseReceived += Updated; + o.ApiGetMember_QuestList.ResponseReceived += (_, _) => QuestListUpdated(); o.ApiReqMission_Start.RequestReceived += Updated; Utility.Configuration.Instance.ConfigurationChanged += ConfigurationChanged; @@ -162,6 +165,30 @@ private void Updated(string apiname, dynamic data) } } + + private void QuestListUpdated() + { + StringBuilder info = new(); + KCDatabase db = KCDatabase.Instance; + + IEnumerable> questListByEndDate = db.Quest.Quests.Values + .OrderBy(q => q.ID) + .Where(q => q.GetEndDateTime() is not null) + .GroupBy(q => (DateTime)q.GetEndDateTime()!); + + foreach (IGrouping questByEndDate in questListByEndDate) + { + info.AppendLine(string.Format(GeneralRes.QuestListEndsOn, questByEndDate.Key)); + + foreach (QuestData quest in questByEndDate) + { + info.AppendLine($"{quest.Code}: {quest.Name}"); + } + } + + Text = info.ToString(); + } + private string GetPracticeEnemyInfo(dynamic data) { StringBuilder sb = new(); diff --git a/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs b/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs index e6919587a..3b02b17d4 100644 --- a/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs +++ b/ElectronicObserver/Window/Wpf/Quest/QuestViewModel.cs @@ -427,9 +427,8 @@ private void Updated() row.QuestView_NameToolTipExtra += $"{FormQuest.QuestView_ProgressResetsDaily}"; } - if (KCDatabase.Instance.Translation.QuestsMetadata.QuestsMetadataList.TryGetValue(q.ID, out QuestMetadata? metadata) && metadata.EndTime is DateTime endTime) + if (q.GetEndDateTime() is DateTime endTime) { - endTime = endTime - TimeSpan.FromHours(9) + TimeZoneInfo.Local.BaseUtcOffset; row.QuestView_NameToolTipExtra += string.Format(FormQuest.QuestView_EndsOn, endTime); } From 7f54a9e3b6fe25bc8018d6861b22bef63a3be548 Mon Sep 17 00:00:00 2001 From: Jebzou <22751386+Jebzou@users.noreply.github.com> Date: Tue, 10 Feb 2026 18:39:24 +0100 Subject: [PATCH 5/9] Reworked update code --- .../Types/MaintenanceState.cs | 9 + .../Types/SoftwareUpdateData.cs | 71 +++++++ .../Types/TranslationUpdateData.cs | 24 +++ .../DataIssueLogs/FitBonusIssueReporter.cs | 2 +- .../WrongUpgradesCostIssueReporter.cs | 2 +- .../WrongUpgradesIssueReporter.cs | 2 +- .../ElectronicObserverApiService.cs | 2 +- ElectronicObserver/Utility/SoftwareUpdater.cs | 192 ++++-------------- .../ViewModels/FormMainViewModel.cs | 10 +- 9 files changed, 153 insertions(+), 161 deletions(-) create mode 100644 ElectronicObserver.Core/Types/MaintenanceState.cs create mode 100644 ElectronicObserver.Core/Types/SoftwareUpdateData.cs create mode 100644 ElectronicObserver.Core/Types/TranslationUpdateData.cs diff --git a/ElectronicObserver.Core/Types/MaintenanceState.cs b/ElectronicObserver.Core/Types/MaintenanceState.cs new file mode 100644 index 000000000..d5a0b5532 --- /dev/null +++ b/ElectronicObserver.Core/Types/MaintenanceState.cs @@ -0,0 +1,9 @@ +namespace ElectronicObserver.Core.Types; + +public enum MaintenanceState +{ + None = 0, + EventStart = 1, + EventEnd = 2, + Regular = 3 +}; diff --git a/ElectronicObserver.Core/Types/SoftwareUpdateData.cs b/ElectronicObserver.Core/Types/SoftwareUpdateData.cs new file mode 100644 index 000000000..d8bd8c445 --- /dev/null +++ b/ElectronicObserver.Core/Types/SoftwareUpdateData.cs @@ -0,0 +1,71 @@ +using System; +using System.Text.Json.Serialization; + +namespace ElectronicObserver.Core.Types; + +public class SoftwareUpdateData +{ + [JsonPropertyName("bld_date")] + public string BuildDateRaw + { + set => BuildDate = DateTimeHelper.CSVStringToTime(value); + } + + public DateTime BuildDate { get; private set; } + + [JsonPropertyName("ver")] + public string AppVersion { get; set; } = "0.0.0.0"; + + [JsonPropertyName("url")] + public string AppDownloadUrl { get; set; } = ""; + + [JsonPropertyName("ApiServer")] + public string AppApiServerUrl { get; set; } = ""; + + [JsonPropertyName("nodes")] + public int Destination { get; set; } + + [JsonPropertyName("QuestTrackers")] + public int QuestTrackers { get; set; } + + [JsonPropertyName("QuestsMetadata")] + public int QuestsMetadata { get; set; } + + [JsonPropertyName("Locks")] + public int EventLocks { get; set; } + + [JsonPropertyName("FitBonuses")] + public int FitBonuses { get; set; } + + [JsonPropertyName("EquipmentUpgrades")] + public int EquipmentUpgrades { get; set; } + + [JsonPropertyName("MaintStart")] + public string MaintenanceStartRaw + { + set => MaintenanceStart = DateTimeHelper.CSVStringToTime(value); + } + + public DateTime MaintenanceStart { get; set; } + + [JsonPropertyName("MaintEnd")] + public string? MaintenanceEndRaw + { + set => MaintenanceEnd = value switch + { + not null => DateTimeHelper.CSVStringToTime(value), + _ => null, + }; + } + + public DateTime? MaintenanceEnd { get; set; } + + [JsonPropertyName("MaintInfoLink")] + public string MaintenanceInformationLink { get; set; } = ""; + + /// + /// 1=event start, 2=event end, 3=regular maintenance + /// + [JsonPropertyName("MaintEventState")] + public MaintenanceState EventState { get; set; } +} diff --git a/ElectronicObserver.Core/Types/TranslationUpdateData.cs b/ElectronicObserver.Core/Types/TranslationUpdateData.cs new file mode 100644 index 000000000..a960f5e80 --- /dev/null +++ b/ElectronicObserver.Core/Types/TranslationUpdateData.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; + +namespace ElectronicObserver.Core.Types; + +public class TranslationUpdateData +{ + [JsonPropertyName("equipment")] + public string Equipment { get; set; } = ""; + + [JsonPropertyName("expedition")] + public string Expedition { get; set; } = ""; + + [JsonPropertyName("operation")] + public string Operation { get; set; } = ""; + + [JsonPropertyName("quest")] + public string Quest { get; set; } = ""; + + [JsonPropertyName("ship")] + public string Ship { get; set; } = ""; + + [JsonPropertyName("Locks")] + public int LockTranslations { get; set; } +} diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/FitBonusIssueReporter.cs b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/FitBonusIssueReporter.cs index 8286d45e7..591f21d6e 100644 --- a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/FitBonusIssueReporter.cs +++ b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/FitBonusIssueReporter.cs @@ -72,7 +72,7 @@ private void ReportIssue(IShipData ship, FitBonusValue theoricalBonus, FitBonusV { FitBonusIssueModel issue = new FitBonusIssueModel() { - DataVersion = SoftwareUpdater.CurrentVersion.FitBonuses, + DataVersion = SoftwareUpdater.CurrentDataVersion.FitBonuses, SoftwareVersion = SoftwareInformation.VersionEnglish, SoftwareDataSource = Configuration.Config.Control.UpdateRepoURL.ToString(), diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesCostIssueReporter.cs b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesCostIssueReporter.cs index 522a41d26..cd8f24259 100644 --- a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesCostIssueReporter.cs +++ b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesCostIssueReporter.cs @@ -104,7 +104,7 @@ public void ProcessUpgradeCostResponse(string _, dynamic data) return new() { SoftwareVersion = SoftwareInformation.VersionEnglish, - DataVersion = SoftwareUpdater.CurrentVersion.EquipmentUpgrades, + DataVersion = SoftwareUpdater.CurrentDataVersion.EquipmentUpgrades, SoftwareDataSource = Configuration.Config.Control.UpdateRepoURL.ToString(), EquipmentId = Equipment.EquipmentId, diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesIssueReporter.cs b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesIssueReporter.cs index b3670e100..c616b3051 100644 --- a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesIssueReporter.cs +++ b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesIssueReporter.cs @@ -34,7 +34,7 @@ public void ProcessUpgradeList(string _, dynamic data) { EquipmentUpgradeIssueModel report = new() { - DataVersion = SoftwareUpdater.CurrentVersion.EquipmentUpgrades, + DataVersion = SoftwareUpdater.CurrentDataVersion.EquipmentUpgrades, SoftwareVersion = SoftwareInformation.VersionEnglish, SoftwareDataSource = Configuration.Config.Control.UpdateRepoURL.ToString(), diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/ElectronicObserverApiService.cs b/ElectronicObserver/Utility/ElectronicObserverApi/ElectronicObserverApiService.cs index cc1d155ac..653b94501 100644 --- a/ElectronicObserver/Utility/ElectronicObserverApi/ElectronicObserverApiService.cs +++ b/ElectronicObserver/Utility/ElectronicObserverApi/ElectronicObserverApiService.cs @@ -19,7 +19,7 @@ public class ElectronicObserverApiService(ElectronicObserverApiTranslationViewMo private string Url => Configuration.Config.Debug.ElectronicObserverApiUrl switch { { Length: >0 } => Configuration.Config.Debug.ElectronicObserverApiUrl, - _ => SoftwareUpdater.CurrentVersion.AppApiServerUrl, + _ => SoftwareUpdater.CurrentDataVersion.AppApiServerUrl, }; private ElectronicObserverApiTranslationViewModel Translations { get; } = translations; diff --git a/ElectronicObserver/Utility/SoftwareUpdater.cs b/ElectronicObserver/Utility/SoftwareUpdater.cs index 0f79d0c84..26d54e401 100644 --- a/ElectronicObserver/Utility/SoftwareUpdater.cs +++ b/ElectronicObserver/Utility/SoftwareUpdater.cs @@ -2,15 +2,13 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Net; using System.Net.Http; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using DynaJson; -using ElectronicObserver.Core; +using ElectronicObserver.Core.Types; using ElectronicObserver.Data; using ElectronicObserver.Data.Translation; -using ElectronicObserver.Utility.Mathematics; using ElectronicObserver.ViewModels.Translations; namespace ElectronicObserver.Utility; @@ -21,8 +19,12 @@ public class SoftwareUpdater Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ElectronicObserver"); private static bool WaitForRestart { get; set; } - public static UpdateData CurrentVersion { get; set; } = new UpdateData(); - public static UpdateData LatestVersion { get; set; } = new UpdateData(); + + public static SoftwareUpdateData CurrentDataVersion { get; set; } = new(); + public static SoftwareUpdateData LatestDataVersion { get; set; } = new(); + + public static TranslationUpdateData CurrentTranslationVersion { get; set; } = new(); + public static TranslationUpdateData LatestTranslationVersion { get; set; } = new(); private static Uri DataUpdateURL => new($"{Configuration.Config.Control.UpdateRepoURL}/update.json"); @@ -46,7 +48,7 @@ public static async Task UpdateSoftware() if (!Directory.Exists(AppDataFolder)) Directory.CreateDirectory(AppDataFolder); - var url = LatestVersion.AppDownloadUrl; + var url = LatestDataVersion.AppDownloadUrl; if (url != string.Empty) { try @@ -109,12 +111,6 @@ public static async Task CheckUpdateAsync() { await ReadRemoteAndLocalUpdateData(); - /*if (Configuration.Config.Life.CheckUpdateInformation == true && SoftwareInformation.UpdateTime < LatestVersion.BuildDate) - { - FormMain.Instance.Update_Available(LatestVersion.AppVersion); - UpdateSoftware(); - }*/ - List<(string FileName, DataType Type)> downloadList = GetDownloadList(); bool needReload = downloadList.Count > 0; @@ -140,15 +136,8 @@ public static async Task CheckUpdateAsync() Logger.Add(2, SoftwareInformationResources.TranslationFilesUpdated); } - CurrentVersion = LatestVersion; - } - catch (JsonParserException e) - { - // file exist but isn't valid json - // file gets corrupted somehow? - File.Delete(TranslationUpdateFile); - File.Delete(DataUpdateFile); - await CheckUpdateAsync(); + CurrentDataVersion = LatestDataVersion; + CurrentTranslationVersion = LatestTranslationVersion; } catch (Exception e) { @@ -160,50 +149,50 @@ public static async Task CheckUpdateAsync() { List<(string FileName, DataType Type)> downloadList = []; - if (CurrentVersion.Equipment != LatestVersion.Equipment) + if (CurrentTranslationVersion.Equipment != LatestTranslationVersion.Equipment) downloadList.Add(("equipment.json", DataType.Translation)); - if (CurrentVersion.Expedition != LatestVersion.Expedition) + if (CurrentTranslationVersion.Expedition != LatestTranslationVersion.Expedition) downloadList.Add(("expedition.json", DataType.Translation)); - if (CurrentVersion.Destination != LatestVersion.Destination) + if (CurrentDataVersion.Destination != LatestDataVersion.Destination) downloadList.Add((("destination.json", DataType.Data))); - if (CurrentVersion.Operation != LatestVersion.Operation) + if (CurrentTranslationVersion.Operation != LatestTranslationVersion.Operation) downloadList.Add(("operation.json", DataType.Translation)); - if (CurrentVersion.Quest != LatestVersion.Quest) + if (CurrentTranslationVersion.Quest != LatestTranslationVersion.Quest) downloadList.Add(("quest.json", DataType.Translation)); - if (CurrentVersion.Ship != LatestVersion.Ship) + if (CurrentTranslationVersion.Ship != LatestTranslationVersion.Ship) downloadList.Add(("ship.json", DataType.Translation)); - if (CurrentVersion.QuestTrackers < LatestVersion.QuestTrackers) + if (CurrentDataVersion.QuestTrackers < LatestDataVersion.QuestTrackers) { downloadList.Add(("QuestTrackers.json", DataType.Data)); } - if (CurrentVersion.TimeLimitedQuest < LatestVersion.TimeLimitedQuest) + if (CurrentDataVersion.QuestsMetadata < LatestDataVersion.QuestsMetadata) { - downloadList.Add(("TimeLimitedQuests.json", DataType.Data)); + downloadList.Add(("QuestsMetadata.json", DataType.Data)); } - if (CurrentVersion.EventLocks < LatestVersion.EventLocks) + if (CurrentDataVersion.EventLocks < LatestDataVersion.EventLocks) { downloadList.Add(("Locks.json", DataType.Data)); } - if (CurrentVersion.LockTranslations < LatestVersion.LockTranslations) + if (CurrentTranslationVersion.LockTranslations < LatestTranslationVersion.LockTranslations) { downloadList.Add(("Locks.json", DataType.Translation)); } - if (CurrentVersion.FitBonuses < LatestVersion.FitBonuses) + if (CurrentDataVersion.FitBonuses < LatestDataVersion.FitBonuses) { downloadList.Add(("FitBonuses.json", DataType.Data)); } - if (CurrentVersion.EquipmentUpgrades < LatestVersion.EquipmentUpgrades) + if (CurrentDataVersion.EquipmentUpgrades < LatestDataVersion.EquipmentUpgrades) { downloadList.Add(("EquipmentUpgrades.json", DataType.Data)); } @@ -228,10 +217,7 @@ private static async Task ReadRemoteAndLocalUpdateData() if (updateDataReceived) { - var jsonData = JsonObject.Parse(dataUpdateData); - var jsonTranslations = JsonObject.Parse(translationUpdateData); - - LatestVersion = ParseUpdate(jsonData, jsonTranslations); + (LatestDataVersion, LatestTranslationVersion) = ParseUpdate(dataUpdateData, translationUpdateData); } bool filesDoesntExist = !File.Exists(DataUpdateFile) || !File.Exists(TranslationUpdateFile); @@ -241,13 +227,14 @@ private static async Task ReadRemoteAndLocalUpdateData() await File.WriteAllTextAsync(DataUpdateFile, dataUpdateData); await File.WriteAllTextAsync(TranslationUpdateFile, translationUpdateData); - CurrentVersion = new UpdateData(); + CurrentDataVersion = new(); + CurrentTranslationVersion = new(); } else { string dataFileContent = File.ReadAllText(DataUpdateFile); string translationFileContent = File.ReadAllText(TranslationUpdateFile); - CurrentVersion = ParseUpdate(JsonObject.Parse(dataFileContent), JsonObject.Parse(translationFileContent)); + (CurrentDataVersion, CurrentTranslationVersion) = ParseUpdate(dataFileContent, translationFileContent); } } @@ -256,7 +243,7 @@ private static async Task DownloadUpdater() try { using HttpClient client = new(); - ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + var url = @"https://raw.githubusercontent.com/ElectronicObserverEN/Data/master/Data/EOUpdater.exe"; var updaterFile = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"\EOUpdater.exe"; @@ -285,7 +272,7 @@ private static async Task DownloadUpdate(string url) { using HttpClient client = new(); string tempFile = AppDataFolder + @"\latest.zip"; ; - ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + Console.WriteLine(SoftwareInformationResources.DownloadingUpdate); Progress progress = new(); @@ -305,97 +292,27 @@ private static async Task DownloadUpdate(string url) } } - internal static UpdateData ParseUpdate(dynamic dataJson, dynamic translationJson) + private static (SoftwareUpdateData, TranslationUpdateData) ParseUpdate(string dataJson, string translationJson) { - var data = new UpdateData(); try { - DateTime buildDate = DateTimeHelper.CSVStringToTime(dataJson.bld_date); - var appVersion = (string)dataJson.ver; - var downloadUrl = (string)dataJson.url; - - string apiServerUrl = dataJson.ApiServer() switch - { - true => (string)dataJson.ApiServer, - _ => "", - }; - - var eqVersion = (string)translationJson.equipment; - var expedVersion = (string)translationJson.expedition; - string destVersion = dataJson.nodes.ToString(); - var opVersion = (string)translationJson.operation; - var questVersion = (string)translationJson.quest; - var shipVersion = (string)translationJson.ship; - int lockTranslationsVersion = (int)translationJson.Locks; - - int fitBonusesVersion = dataJson.FitBonuses() switch - { - true => (int)dataJson.FitBonuses, - _ => 0, - }; + SoftwareUpdateData? data = JsonSerializer.Deserialize(dataJson); + TranslationUpdateData? translations = JsonSerializer.Deserialize(translationJson); - int questTrackersVersion = dataJson.QuestTrackers() switch + if (data is not null && translations is not null) { - true => (int)dataJson.QuestTrackers, - _ => 0, - }; - - int timeLimitedQuestsVersion = dataJson.TimeLimitedQuest() switch - { - true => (int)dataJson.TimeLimitedQuest, - _ => 0, - }; - - int eventLocksVersion = (int)dataJson.Locks; - - int equipmentUpgradesVersion = dataJson.EquipmentUpgrades() switch - { - true => (int)dataJson.EquipmentUpgrades, - _ => 0, - }; - - DateTime maintenanceStartDate = DateTimeHelper.CSVStringToTime(dataJson.MaintStart); - - DateTime? maintenanceEndDate = dataJson.MaintEnd switch - { - null => null, - _ => DateTimeHelper.CSVStringToTime(dataJson.MaintEnd), - }; - - var eventState = (MaintenanceState)(int)dataJson.MaintEventState; - string maintenanceInformationLink = (string)dataJson.MaintInfoLink; - - data = new UpdateData - { - BuildDate = buildDate, - AppVersion = appVersion, - AppDownloadUrl = downloadUrl, - AppApiServerUrl = apiServerUrl, - Equipment = eqVersion, - Expedition = expedVersion, - Destination = destVersion, - Operation = opVersion, - Quest = questVersion, - Ship = shipVersion, - QuestTrackers = questTrackersVersion, - TimeLimitedQuest = timeLimitedQuestsVersion, - EventLocks = eventLocksVersion, - LockTranslations = lockTranslationsVersion, - MaintenanceStart = maintenanceStartDate, - MaintenanceEnd = maintenanceEndDate, - EventState = eventState, - FitBonuses = fitBonusesVersion, - EquipmentUpgrades = equipmentUpgradesVersion, - MaintenanceInformationLink = maintenanceInformationLink - }; + return (data, translations); + } } catch (Exception e) { Logger.Add(3, SoftwareInformationResources.FailedToParseUpdateData + e.ToString()); } - return data; - } + return (new(), new()); + } + + private static string GetFullPath(string fileName, DataType type) => type switch { DataType.Translation => Path.Combine("Translations", DataAndTranslationManager.CurrentTranslationLanguage, fileName), @@ -431,32 +348,3 @@ public static async Task DownloadData(string filename, DataType type) } } } - -public class UpdateData -{ - public DateTime BuildDate { get; set; } - public string AppVersion { get; set; } = "0.0.0.0"; - public string AppDownloadUrl { get; set; } = ""; - public string AppApiServerUrl { get; set; } = ""; - public string Equipment { get; set; } = ""; - public string Expedition { get; set; } = ""; - public string Destination { get; set; } = ""; - public string Operation { get; set; } = ""; - public string Quest { get; set; } = ""; - public string Ship { get; set; } = ""; - public int QuestTrackers { get; set; } - public int TimeLimitedQuest { get; set; } - public int EventLocks { get; set; } - public int LockTranslations { get; set; } - public int FitBonuses { get; set; } - public int EquipmentUpgrades { get; set; } - public DateTime MaintenanceStart { get; set; } - public DateTime? MaintenanceEnd { get; set; } - public string MaintenanceInformationLink { get; set; } = ""; - - /// - /// 1=event start, 2=event end, 3=regular maintenance - /// - public MaintenanceState EventState { get; set; } -} -public enum MaintenanceState { None = 0, EventStart = 1, EventEnd = 2, Regular = 3 }; diff --git a/ElectronicObserver/ViewModels/FormMainViewModel.cs b/ElectronicObserver/ViewModels/FormMainViewModel.cs index 929f303bd..034940b80 100644 --- a/ElectronicObserver/ViewModels/FormMainViewModel.cs +++ b/ElectronicObserver/ViewModels/FormMainViewModel.cs @@ -1665,7 +1665,7 @@ private void OpenReleaseNotes() #region Maintenance timer [RelayCommand] private void OpenMaintenanceInformationLink() - => OpenLink(SoftwareUpdater.LatestVersion.MaintenanceInformationLink); + => OpenLink(SoftwareUpdater.LatestDataVersion.MaintenanceInformationLink); #endregion private void CallPumpkinHead(string apiname, dynamic data) @@ -1770,7 +1770,7 @@ private void UIUpdateTimer_Tick(object sender, EventArgs e) DateTime now = DateTimeHelper.GetJapanStandardTimeNow(); MaintenanceText = GetMaintenanceText(FormMain, now); - UpdateAvailable = SoftwareInformation.UpdateTime < SoftwareUpdater.LatestVersion.BuildDate; + UpdateAvailable = SoftwareInformation.UpdateTime < SoftwareUpdater.LatestDataVersion.BuildDate; DownloadProgressString = SoftwareUpdater.DownloadProgressString; @@ -1858,10 +1858,10 @@ private void UIUpdateTimer_Tick(object sender, EventArgs e) private static string GetMaintenanceText(FormMainTranslationViewModel formMain, DateTime now) { TimeSpan maintTimer = new(0); - MaintenanceState eventState = SoftwareUpdater.LatestVersion.EventState; + MaintenanceState eventState = SoftwareUpdater.LatestDataVersion.EventState; - DateTime maintStartDate = SoftwareUpdater.LatestVersion.MaintenanceStart; - DateTime? maintEndDate = SoftwareUpdater.LatestVersion.MaintenanceEnd; + DateTime maintStartDate = SoftwareUpdater.LatestDataVersion.MaintenanceStart; + DateTime? maintEndDate = SoftwareUpdater.LatestDataVersion.MaintenanceEnd; if (eventState != MaintenanceState.None) { From a2f5e98a5fe7cef2db3e4870db93fff4dc5355e7 Mon Sep 17 00:00:00 2001 From: Jebzou <22751386+Jebzou@users.noreply.github.com> Date: Tue, 10 Feb 2026 18:46:11 +0100 Subject: [PATCH 6/9] using --- .../Window/Wpf/InformationView/InformationViewModel.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs b/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs index 2de3026fd..d1c9c630b 100644 --- a/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs +++ b/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs @@ -7,7 +7,6 @@ using ElectronicObserver.Core.Types; using ElectronicObserver.Data; using ElectronicObserver.Data.DiscordRPC; -using ElectronicObserver.Data.PoiDbSubmission.PoiDbBattleSubmission; using ElectronicObserver.Observer; using ElectronicObserver.Resource; using ElectronicObserver.Utility.Data; From 705ec954fd4daa4fea28ce43a2a6992aba9a19b2 Mon Sep 17 00:00:00 2001 From: Jebzou <22751386+Jebzou@users.noreply.github.com> Date: Tue, 10 Feb 2026 18:52:55 +0100 Subject: [PATCH 7/9] Sonar --- ElectronicObserver.Core/Types/SoftwareUpdateData.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ElectronicObserver.Core/Types/SoftwareUpdateData.cs b/ElectronicObserver.Core/Types/SoftwareUpdateData.cs index d8bd8c445..b5a6a94f2 100644 --- a/ElectronicObserver.Core/Types/SoftwareUpdateData.cs +++ b/ElectronicObserver.Core/Types/SoftwareUpdateData.cs @@ -9,6 +9,7 @@ public class SoftwareUpdateData public string BuildDateRaw { set => BuildDate = DateTimeHelper.CSVStringToTime(value); + get => throw new NotSupportedException(); } public DateTime BuildDate { get; private set; } @@ -44,6 +45,7 @@ public string BuildDateRaw public string MaintenanceStartRaw { set => MaintenanceStart = DateTimeHelper.CSVStringToTime(value); + get => throw new NotSupportedException(); } public DateTime MaintenanceStart { get; set; } @@ -55,7 +57,8 @@ public string? MaintenanceEndRaw { not null => DateTimeHelper.CSVStringToTime(value), _ => null, - }; + }; + get => throw new NotSupportedException(); } public DateTime? MaintenanceEnd { get; set; } From 608ef381eec659d7d682bc96ad6da922c50b71c4 Mon Sep 17 00:00:00 2001 From: myangelkamikaze <40002167+myangelkamikaze@users.noreply.github.com> Date: Wed, 11 Feb 2026 04:22:37 +0900 Subject: [PATCH 8/9] translations --- ElectronicObserver/Window/GeneralRes.en.resx | 4 ++-- ElectronicObserver/Window/GeneralRes.resx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ElectronicObserver/Window/GeneralRes.en.resx b/ElectronicObserver/Window/GeneralRes.en.resx index a4808a811..197f677a1 100644 --- a/ElectronicObserver/Window/GeneralRes.en.resx +++ b/ElectronicObserver/Window/GeneralRes.en.resx @@ -852,9 +852,9 @@ Please click here to restart. Progress resets daily - Ends on {0:f} + Ends on {0} - Quests that ends on {0:f} + Quests that end on {0} \ No newline at end of file diff --git a/ElectronicObserver/Window/GeneralRes.resx b/ElectronicObserver/Window/GeneralRes.resx index 74abe2dd2..ccb137989 100644 --- a/ElectronicObserver/Window/GeneralRes.resx +++ b/ElectronicObserver/Window/GeneralRes.resx @@ -851,9 +851,9 @@ デイリーリセット - ??? (Ends on {0:f}) + {0}で終わる - ??? (Quests that ends on {0:f}) + {0}で終わるクエスト \ No newline at end of file From 0b48a43e2b0bd1415a93c4d5a7c0faba95100cb4 Mon Sep 17 00:00:00 2001 From: Jebzou <22751386+Jebzou@users.noreply.github.com> Date: Tue, 10 Feb 2026 20:47:59 +0100 Subject: [PATCH 9/9] converter --- .../Types/CsvDateConverter.cs | 22 ++++++++++++++ .../Types/CsvNullableDateConverter.cs | 22 ++++++++++++++ .../Types/SoftwareUpdateData.cs | 30 +++---------------- 3 files changed, 48 insertions(+), 26 deletions(-) create mode 100644 ElectronicObserver.Core/Types/CsvDateConverter.cs create mode 100644 ElectronicObserver.Core/Types/CsvNullableDateConverter.cs diff --git a/ElectronicObserver.Core/Types/CsvDateConverter.cs b/ElectronicObserver.Core/Types/CsvDateConverter.cs new file mode 100644 index 000000000..52a0bde08 --- /dev/null +++ b/ElectronicObserver.Core/Types/CsvDateConverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace ElectronicObserver.Core.Types; + +public class CsvDateConverter : JsonConverter +{ + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + string? raw = reader.GetString(); + + if (raw is null) return new(); + + return DateTimeHelper.CSVStringToTime(raw); + } + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss")); + } +} diff --git a/ElectronicObserver.Core/Types/CsvNullableDateConverter.cs b/ElectronicObserver.Core/Types/CsvNullableDateConverter.cs new file mode 100644 index 000000000..1d73087c5 --- /dev/null +++ b/ElectronicObserver.Core/Types/CsvNullableDateConverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace ElectronicObserver.Core.Types; + +public class CsvNullableDateConverter : JsonConverter +{ + public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + string? raw = reader.GetString(); + + if (raw is null) return null; + + return DateTimeHelper.CSVStringToTime(raw); + } + + public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) + { + writer.WriteStringValue(value?.ToString("yyyy-MM-dd HH:mm:ss")); + } +} diff --git a/ElectronicObserver.Core/Types/SoftwareUpdateData.cs b/ElectronicObserver.Core/Types/SoftwareUpdateData.cs index b5a6a94f2..0476bfdef 100644 --- a/ElectronicObserver.Core/Types/SoftwareUpdateData.cs +++ b/ElectronicObserver.Core/Types/SoftwareUpdateData.cs @@ -6,13 +6,8 @@ namespace ElectronicObserver.Core.Types; public class SoftwareUpdateData { [JsonPropertyName("bld_date")] - public string BuildDateRaw - { - set => BuildDate = DateTimeHelper.CSVStringToTime(value); - get => throw new NotSupportedException(); - } - - public DateTime BuildDate { get; private set; } + [JsonConverter(typeof(CsvDateConverter))] + public DateTime BuildDate { get; set; } [JsonPropertyName("ver")] public string AppVersion { get; set; } = "0.0.0.0"; @@ -42,33 +37,16 @@ public string BuildDateRaw public int EquipmentUpgrades { get; set; } [JsonPropertyName("MaintStart")] - public string MaintenanceStartRaw - { - set => MaintenanceStart = DateTimeHelper.CSVStringToTime(value); - get => throw new NotSupportedException(); - } - + [JsonConverter(typeof(CsvDateConverter))] public DateTime MaintenanceStart { get; set; } [JsonPropertyName("MaintEnd")] - public string? MaintenanceEndRaw - { - set => MaintenanceEnd = value switch - { - not null => DateTimeHelper.CSVStringToTime(value), - _ => null, - }; - get => throw new NotSupportedException(); - } - + [JsonConverter(typeof(CsvNullableDateConverter))] public DateTime? MaintenanceEnd { get; set; } [JsonPropertyName("MaintInfoLink")] public string MaintenanceInformationLink { get; set; } = ""; - /// - /// 1=event start, 2=event end, 3=regular maintenance - /// [JsonPropertyName("MaintEventState")] public MaintenanceState EventState { get; set; } }