diff --git a/ElectronicObserver/App.xaml.cs b/ElectronicObserver/App.xaml.cs index b02427928..c1e040b4a 100644 --- a/ElectronicObserver/App.xaml.cs +++ b/ElectronicObserver/App.xaml.cs @@ -15,6 +15,7 @@ using ElectronicObserver.Services; using ElectronicObserver.Utility; using ElectronicObserver.Utility.ElectronicObserverApi; +using ElectronicObserver.Utility.ElectronicObserverApi.DataIssueLogs; using ElectronicObserver.ViewModels.Translations; using ElectronicObserver.Window.Control.ShipFilter; using ElectronicObserver.Window.Dialog.ShipPicker; @@ -308,12 +309,16 @@ private void ConfigureServices() .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() + //.ActivateSingleton() todo uncomment and test with .net 8 // external .AddSingleton(JotTracker()) .BuildServiceProvider(); Ioc.Default.ConfigureServices(services); + + Ioc.Default.GetRequiredService(); // todo remove with .net 8 if the above test is successful } private static Tracker JotTracker() diff --git a/ElectronicObserver/Data/Translation/DataAndTranslationManager.cs b/ElectronicObserver/Data/Translation/DataAndTranslationManager.cs index fc7172391..d42b28ef7 100644 --- a/ElectronicObserver/Data/Translation/DataAndTranslationManager.cs +++ b/ElectronicObserver/Data/Translation/DataAndTranslationManager.cs @@ -28,13 +28,9 @@ public class DataAndTranslationManager public FitBonusData FitBonus { get; private set; } public EquipmentUpgradeData EquipmentUpgrade { get; private set; } - public DataAndTranslationIssueReporter DataAndTranslationIssueReporter { get; } - public DataAndTranslationManager() { Initialize(); - - DataAndTranslationIssueReporter = new(); } public void Initialize() diff --git a/ElectronicObserver/Observer/ObserverRes.resx b/ElectronicObserver/Observer/ObserverRes.resx index 0ca2e0d91..12b2c41c2 100644 --- a/ElectronicObserver/Observer/ObserverRes.resx +++ b/ElectronicObserver/Observer/ObserverRes.resx @@ -1,76 +1,96 @@  + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + + + + + + + + + + + + + + + + + + - + + @@ -89,13 +109,13 @@ text/microsoft-resx - 1.3 + 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 装備シナジーを検出しました: diff --git a/ElectronicObserver/Observer/kcsapi/api_get_member/ship3.cs b/ElectronicObserver/Observer/kcsapi/api_get_member/ship3.cs index 55a884c31..1ef25bb3c 100644 --- a/ElectronicObserver/Observer/kcsapi/api_get_member/ship3.cs +++ b/ElectronicObserver/Observer/kcsapi/api_get_member/ship3.cs @@ -1,17 +1,16 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Text; using ElectronicObserver.Data; +using ElectronicObserver.Utility.Data; +using ElectronicObserverTypes.Serialization.FitBonus; namespace ElectronicObserver.Observer.kcsapi.api_get_member; public class ship3 : APIBase { - public override void OnResponseReceived(dynamic data) { - KCDatabase db = KCDatabase.Instance; //api_ship_data @@ -36,78 +35,16 @@ public override void OnResponseReceived(dynamic data) } } - // 装備シナジー検出カッコカリ - if (!isRemodeled && - ship.MasterShip.ASW.IsDetermined && - ship.MasterShip.Evasion.IsDetermined && - ship.MasterShip.LOS.IsDetermined) + if (!isRemodeled) { - int firepower = ship.FirepowerTotal - ship.FirepowerBase; - int torpedo = ship.TorpedoTotal - ship.TorpedoBase; - int aa = ship.AATotal - ship.AABase; - int armor = ship.ArmorTotal - ship.ArmorBase; - int asw = ship.ASWTotal - (ship.MasterShip.ASW.GetEstParameterMin(ship.Level) + ship.ASWModernized); - int evasion = ship.EvasionTotal - ship.MasterShip.Evasion.GetEstParameterMin(ship.Level); - int los = ship.LOSTotal - ship.MasterShip.LOS.GetEstParameterMin(ship.Level); - int luck = ship.LuckTotal - ship.LuckBase; - int range = ship.MasterShip.Range; - - foreach (var eq in ship.AllSlotInstanceMaster.Where(eq => eq != null)) - { - firepower -= eq.Firepower; - torpedo -= eq.Torpedo; - aa -= eq.AA; - armor -= eq.Armor; - asw -= eq.ASW; - evasion -= eq.Evasion; - los -= eq.LOS; - luck -= eq.Luck; - range = Math.Max(range, eq.Range); - } + FitBonusValue bonus = ship.GetFitBonus(); - range = ship.Range - range; - - if (firepower != 0 || - torpedo != 0 || - aa != 0 || - armor != 0 || - asw != 0 || - evasion != 0 || - los != 0 || - luck != 0 || - range != 0) + if (bonus.HasBonus()) { - var sb = new StringBuilder(); - sb.Append(ObserverRes.DetectedSynergy); - - var a = new List(); - if (firepower != 0) - a.Add(ObserverRes.Firepower + $"{firepower:+#;-#;0}"); - if (torpedo != 0) - a.Add(ObserverRes.Torpedo + $"{torpedo:+#;-#;0}"); - if (aa != 0) - a.Add(ObserverRes.AntiAir + $"{aa:+#;-#;0}"); - if (armor != 0) - a.Add(ObserverRes.Armor + $"{armor:+#;-#;0}"); - if (asw != 0) - a.Add(ObserverRes.Asw + $"{asw:+#;-#;0}"); - if (evasion != 0) - a.Add(ObserverRes.Evasion + $"{evasion:+#;-#;0}"); - if (los != 0) - a.Add(ObserverRes.Los + $"{los:+#;-#;0}"); - if (luck != 0) - a.Add(ObserverRes.Luck + $"{luck:+#;-#;0}"); - if (range != 0) - a.Add(ObserverRes.Range + $"{range:+#;-#;0}"); - - sb.Append(string.Join(", ", a)); - - sb.AppendFormat(" ; {0} [{1}]", - ship.NameWithLevel, - string.Join(", ", ship.AllSlotInstance.Where(eq => eq != null).Select(eq => eq.NameWithLevel))); - - Utility.Logger.Add(2, sb.ToString()); + string fitBonusString = BuildFitBonusString(bonus, ship); + + Utility.Logger.Add(2, fitBonusString); } } } @@ -115,9 +52,63 @@ public override void OnResponseReceived(dynamic data) //api_deck_data db.Fleet.LoadFromResponse(APIName, data.api_deck_data); + base.OnResponseReceived((object)data); + } + private static string BuildFitBonusString(FitBonusValue bonus, ShipData ship) + { + StringBuilder sb = new(); + sb.Append(ObserverRes.DetectedSynergy); - base.OnResponseReceived((object)data); + List bonusList = new(); + + if (bonus.Firepower != 0) + { + bonusList.Add(ObserverRes.Firepower + $"{bonus.Firepower:+#;-#;0}"); + } + + if (bonus.Torpedo != 0) + { + bonusList.Add(ObserverRes.Torpedo + $"{bonus.Torpedo:+#;-#;0}"); + } + + if (bonus.AntiAir != 0) + { + bonusList.Add(ObserverRes.AntiAir + $"{bonus.AntiAir:+#;-#;0}"); + } + + if (bonus.Armor != 0) + { + bonusList.Add(ObserverRes.Armor + $"{bonus.Armor:+#;-#;0}"); + } + + if (bonus.ASW != 0) + { + bonusList.Add(ObserverRes.Asw + $"{bonus.ASW:+#;-#;0}"); + } + + if (bonus.Evasion != 0) + { + bonusList.Add(ObserverRes.Evasion + $"{bonus.Evasion:+#;-#;0}"); + } + + if (bonus.LOS != 0) + { + bonusList.Add(ObserverRes.Los + $"{bonus.LOS:+#;-#;0}"); + } + + if (bonus.Range != 0) + { + bonusList.Add(ObserverRes.Range + $"{bonus.Range:+#;-#;0}"); + } + + sb.Append(string.Join(", ", bonusList)); + + sb.AppendFormat(" ; {0} [{1}]", + ship.NameWithLevel, + string.Join(", ", ship.AllSlotInstance.Where(eq => eq != null).Select(eq => eq.NameWithLevel))); + + return sb.ToString(); } public override string APIName => "api_get_member/ship3"; diff --git a/ElectronicObserver/Utility/Data/EquipmentFitBonus.cs b/ElectronicObserver/Utility/Data/EquipmentFitBonus.cs index 608dfb118..22d67ff2f 100644 --- a/ElectronicObserver/Utility/Data/EquipmentFitBonus.cs +++ b/ElectronicObserver/Utility/Data/EquipmentFitBonus.cs @@ -1,16 +1,62 @@ -using System.Collections.Generic; -using ElectronicObserverTypes; +using System; +using System.Collections.Generic; using System.Linq; -using ElectronicObserverTypes.Serialization.FitBonus; +using ElectronicObserverTypes; using ElectronicObserverTypes.Extensions; +using ElectronicObserverTypes.Serialization.FitBonus; namespace ElectronicObserver.Utility.Data; public static class EquipmentFitBonus { + public static FitBonusValue GetFitBonus(this IShipData ship) + { + FitBonusValue bonus = new() + { + Firepower = ship.FirepowerTotal - ship.FirepowerBase, + Torpedo = ship.TorpedoTotal - ship.TorpedoBase, + AntiAir = ship.AATotal - ship.AABase, + Armor = ship.ArmorTotal - ship.ArmorBase, + ASW = ship.ASWTotal - (ship.MasterShip.ASW.GetEstParameterMin(ship.Level) + ship.ASWModernized), + Evasion = ship.EvasionTotal - ship.MasterShip.Evasion.GetEstParameterMin(ship.Level), + LOS = ship.LOSTotal - ship.MasterShip.LOS.GetEstParameterMin(ship.Level), + Range = ship.MasterShip.Range, + }; + + foreach (IEquipmentDataMaster eq in ship.AllSlotInstanceMaster.Where(eq => eq != null)) + { + bonus.Firepower -= eq.Firepower; + bonus.Torpedo -= eq.Torpedo; + bonus.AntiAir -= eq.AA; + bonus.Armor -= eq.Armor; + bonus.ASW -= eq.ASW; + bonus.Evasion -= eq.Evasion; + bonus.LOS -= eq.LOS; + bonus.Range = Math.Max(bonus.Range, eq.Range); + } + + bonus.Range = ship.Range - bonus.Range; - public static FitBonusValue GetFitBonus(this IShipData ship, IList bonusList) => - GetFitBonuses(ship, bonusList) + if (!ship.MasterShip.ASW.IsDetermined) + { + bonus.ASW = 0; + } + + if (!ship.MasterShip.Evasion.IsDetermined) + { + bonus.Evasion = 0; + } + + if (!ship.MasterShip.LOS.IsDetermined) + { + bonus.LOS = 0; + } + + return bonus; + } + + public static FitBonusValue GetTheoricalFitBonus(this IShipData ship, IList bonusList) => + ship.GetTheoricalFitBonuses(bonusList) .Aggregate( new FitBonusValue(), (bonusA, bonusB) => bonusA + bonusB, @@ -22,17 +68,19 @@ public static FitBonusValue GetFitBonus(this IShipData ship, IList /// + /// /// - public static List GetFitBonuses(this IShipData ship, IList bonusList) - => ship.GetFitBonusList(bonusList).Select(bonus => bonus.FinalBonus).ToList(); + public static List GetTheoricalFitBonuses(this IShipData ship, IList bonusList) + => ship.GetTheoricalFitBonusList(bonusList).Select(bonus => bonus.FinalBonus).ToList(); /// /// Keep in mind that accuracy bonus is included /// /// + /// /// - public static List GetFitBonusList(this IShipData ship, IList bonusList) - { + public static List GetTheoricalFitBonusList(this IShipData ship, IList bonusList) + { IList equipments = ship.AllSlotInstance.Where(eq => eq != null).ToList()!; List distinctEquipments = equipments @@ -47,31 +95,28 @@ public static List GetFitBonusList(this IShipData ship, IList fitBonusThatApplies = bonusList - .Where(fitCondition => + .Where(fitCondition => distinctEquipments.Any(equipment => fitCondition.EquipmentIds?.Contains(equipment) == true) || distinctEquipmentTypes.Any(equipment => fitCondition.EquipmentTypes?.Contains(equipment) == true) ) .ToList(); - List finalBonuses = new List(); + return GetTheoricalFitBonusList(ship, fitBonusThatApplies, equipments); + } + + private static List GetTheoricalFitBonusList(IShipData ship, List fitBonusThatApplies, IList equipments) + { + List finalBonuses = new(); foreach (FitBonusPerEquipment fitPerEquip in fitBonusThatApplies) { foreach (FitBonusData fitData in fitPerEquip.Bonuses) { - FitBonusResult result = new FitBonusResult(); - if (fitPerEquip.EquipmentTypes != null) result.EquipmentTypes.AddRange(fitPerEquip.EquipmentTypes); - if (fitPerEquip.EquipmentIds != null) result.EquipmentIds.AddRange(fitPerEquip.EquipmentIds); + FitBonusResult? result = GetFitBonusResultFromFitData(ship, equipments, fitPerEquip, fitData); - int bonusMultiplier = NumberOfTimeBonusApplies(fitPerEquip, fitData, ship.MasterShip, equipments); - if (bonusMultiplier > 0) + if (result is not null) { - result.FitBonusData = fitData; - if (fitData.Bonuses != null) result.FitBonusValues.Add(bonusMultiplier > 1 ? (fitData.Bonuses * bonusMultiplier) : fitData.Bonuses); - if (fitData.BonusesIfSurfaceRadar != null && ship.HasSurfaceRadar()) result.FitBonusValues.Add(fitData.BonusesIfSurfaceRadar); - if (fitData.BonusesIfAirRadar != null && ship.HasAirRadar(1)) result.FitBonusValues.Add(fitData.BonusesIfAirRadar); - finalBonuses.Add(result); } } @@ -80,6 +125,41 @@ public static List GetFitBonusList(this IShipData ship, IList equipments, FitBonusPerEquipment fitPerEquip, + FitBonusData fitData) + { + FitBonusResult result = new(); + if (fitPerEquip.EquipmentTypes != null) result.EquipmentTypes.AddRange(fitPerEquip.EquipmentTypes); + if (fitPerEquip.EquipmentIds != null) result.EquipmentIds.AddRange(fitPerEquip.EquipmentIds); + + int bonusMultiplier = NumberOfTimeBonusApplies(fitPerEquip, fitData, ship.MasterShip, equipments); + + if (bonusMultiplier <= 0) return null; + + result.FitBonusData = fitData; + + if (fitData.Bonuses != null) + { + result.FitBonusValues.Add(bonusMultiplier switch + { + > 1 => fitData.Bonuses * bonusMultiplier, + _ => fitData.Bonuses, + }); + } + + if (fitData.BonusesIfSurfaceRadar != null && ship.HasSurfaceRadar()) + { + result.FitBonusValues.Add(fitData.BonusesIfSurfaceRadar); + } + + if (fitData.BonusesIfAirRadar != null && ship.HasAirRadar()) + { + result.FitBonusValues.Add(fitData.BonusesIfAirRadar); + } + + return result; + } + private static int NumberOfTimeBonusApplies(FitBonusPerEquipment fitPerEquip, FitBonusData fitBonusData, IShipDataMaster shipMaster, IList equipments) { if (fitBonusData.ShipClasses != null && !fitBonusData.ShipClasses.Contains(shipMaster.ShipClassTyped)) return 0; @@ -99,7 +179,7 @@ private static int NumberOfTimeBonusApplies(FitBonusPerEquipment fitPerEquip, Fi if ((fitBonusData.NumberOfEquipmentTypesRequired ?? 1) > count) return 0; } - List equipmentsThatMatches = new List(); + List equipmentsThatMatches = new(); if (fitPerEquip.EquipmentIds != null) equipmentsThatMatches.AddRange(equipments.Where(eq => fitPerEquip.EquipmentIds.Contains(eq.EquipmentId))); if (fitPerEquip.EquipmentTypes != null) equipmentsThatMatches.AddRange(equipments.Where(eq => fitPerEquip.EquipmentTypes.Contains(eq.MasterEquipment.CategoryType))); diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/DataAndTranslationIssueReporter.cs b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/DataAndTranslationIssueReporter.cs index 96857ace5..db743178d 100644 --- a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/DataAndTranslationIssueReporter.cs +++ b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/DataAndTranslationIssueReporter.cs @@ -5,18 +5,22 @@ namespace ElectronicObserver.Utility.ElectronicObserverApi.DataIssueLogs; public class DataAndTranslationIssueReporter { private WrongUpgradesIssueReporter WrongUpgradesIssueReporter { get; } + private FitBonusIssueReporter FitBonusIssueReporter { get; } - public DataAndTranslationIssueReporter() + public DataAndTranslationIssueReporter(ElectronicObserverApiService api) { - WrongUpgradesIssueReporter = new(); + WrongUpgradesIssueReporter = new(api); + FitBonusIssueReporter = new(api); - SubscribeToAPI(); + SubscribeToApi(); } - private void SubscribeToAPI() + private void SubscribeToApi() { APIObserver api = APIObserver.Instance; api.ApiReqKousyou_RemodelSlotList.ResponseReceived += WrongUpgradesIssueReporter.ProcessUpgradeList; + + api.ApiGetMember_Ship3.ResponseReceived += FitBonusIssueReporter.ProcessShipDataChanged; } } diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/FitBonusIssueReporter.cs b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/FitBonusIssueReporter.cs new file mode 100644 index 000000000..3fd04252f --- /dev/null +++ b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/FitBonusIssueReporter.cs @@ -0,0 +1,107 @@ +using System.Collections.Generic; +using System.Linq; +using ElectronicObserver.Data; +using ElectronicObserver.Utility.Data; +using ElectronicObserver.Utility.ElectronicObserverApi.Models; +using ElectronicObserverTypes; +using ElectronicObserverTypes.Serialization.FitBonus; + +namespace ElectronicObserver.Utility.ElectronicObserverApi.DataIssueLogs; + +public class FitBonusIssueReporter(ElectronicObserverApiService api) +{ + private List AlreadySentIssues { get; } = new(); + + public void ProcessShipDataChanged(string _, dynamic data) + { + if (!api.IsEnabled) return; + + foreach (var elem in data.api_ship_data) + { + int id = (int)elem.api_id; + IShipData ship = KCDatabase.Instance.Ships[id]; + + FitBonusValue theoricalBonus = ship.GetTheoricalFitBonus(KCDatabase.Instance.Translation.FitBonus.FitBonusList); + + if (!ship.MasterShip.ASW.IsDetermined) + { + theoricalBonus.ASW = 0; + } + + if (!ship.MasterShip.Evasion.IsDetermined) + { + theoricalBonus.Evasion = 0; + } + + if (!ship.MasterShip.LOS.IsDetermined) + { + theoricalBonus.LOS = 0; + } + + // There's no way to get accuracy bonus from the API + theoricalBonus.Accuracy = 0; + + FitBonusValue actualBonus = ship.GetFitBonus(); + + if (!actualBonus.Equals(theoricalBonus)) + { + ReportIssue(ship, theoricalBonus, actualBonus); + } + } + } + + private bool CheckIfIssueAlreadySent(FitBonusIssueModel issue) + => AlreadySentIssues.Exists(item => issue.Ship.IsSameShip(item.Ship) && issue.Equipments.SequenceEqual(item.Equipments)); + + private void ReportIssue(IShipData ship, FitBonusValue theoricalBonus, FitBonusValue actualBonus) + { + FitBonusIssueModel issue = new FitBonusIssueModel() + { + DataVersion = SoftwareUpdater.CurrentVersion.FitBonuses, + SoftwareVersion = SoftwareInformation.VersionEnglish, + + ExpectedBonus = theoricalBonus, + ActualBonus = actualBonus, + + Equipments = ship.AllSlotInstance + .Where(eq => eq is not null) + .Cast() + .Select(eq => new EquipmentModel() + { + EquipmentId = eq.EquipmentId, + Level = eq.UpgradeLevel + }) + .ToList(), + + Ship = new() + { + ShipId = ship.MasterShip.ShipId, + Level = ship.Level, + + Firepower = ship.FirepowerTotal, + Torpedo = ship.TorpedoTotal, + AntiAir = ship.AATotal, + Armor = ship.ArmorTotal, + + Evasion = ship.EvasionTotal, + EvasionDetermined = ship.MasterShip.Evasion.IsDetermined, + ASW = ship.ASWTotal, + ASWDetermined = ship.MasterShip.ASW.IsDetermined, + LOS = ship.LOSTotal, + LOSDetermined = ship.MasterShip.LOS.IsDetermined, + + Accuracy = ship.AccuracyTotal, + + Range = ship.MasterShip.Range, + }, + }; + + if (CheckIfIssueAlreadySent(issue)) return; + + AlreadySentIssues.Add(issue); + +#pragma warning disable CS4014 + api.PostJson("FitBonusIssues", issue); +#pragma warning restore CS4014 + } +} diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesIssueReporter.cs b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesIssueReporter.cs index e11fdf35e..e4c569b6e 100644 --- a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesIssueReporter.cs +++ b/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesIssueReporter.cs @@ -1,21 +1,21 @@ using System.Collections.Generic; using System.Linq; using System.Text.Json; -using CommunityToolkit.Mvvm.DependencyInjection; using ElectronicObserver.Data; using ElectronicObserver.KancolleApi.Types.ApiReqKousyou.RemodelSlotlist; using ElectronicObserver.Utility.Data; +using ElectronicObserver.Utility.ElectronicObserverApi.Models; using ElectronicObserver.Utility.Mathematics; using ElectronicObserverTypes; using ElectronicObserverTypes.Serialization.EquipmentUpgrade; namespace ElectronicObserver.Utility.ElectronicObserverApi.DataIssueLogs; -public class WrongUpgradesIssueReporter -{ +public class WrongUpgradesIssueReporter(ElectronicObserverApiService api) +{ public void ProcessUpgradeList(string _, dynamic data) { - ElectronicObserverApiService api = Ioc.Default.GetRequiredService(); + if (!api.IsEnabled) return; // if no helper => ignore int helperId = KCDatabase.Instance.Fleet.Fleets[1].Members[1]; diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/ElectronicObserverApiService.cs b/ElectronicObserver/Utility/ElectronicObserverApi/ElectronicObserverApiService.cs index 0a8b61d8b..7962009c5 100644 --- a/ElectronicObserver/Utility/ElectronicObserverApi/ElectronicObserverApiService.cs +++ b/ElectronicObserver/Utility/ElectronicObserverApi/ElectronicObserverApiService.cs @@ -14,6 +14,8 @@ public class ElectronicObserverApiService private ElectronicObserverApiTranslationViewModel Translations { get; } + public bool IsEnabled => !string.IsNullOrEmpty(Url); + public ElectronicObserverApiService(ElectronicObserverApiTranslationViewModel translations) { Translations = translations; @@ -21,7 +23,7 @@ public ElectronicObserverApiService(ElectronicObserverApiTranslationViewModel tr public async Task PostJson(string route, T data) { - if (string.IsNullOrEmpty(Url)) return; + if (!IsEnabled) return; try { diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/Models/EquipmentModel.cs b/ElectronicObserver/Utility/ElectronicObserverApi/Models/EquipmentModel.cs new file mode 100644 index 000000000..304af5d3c --- /dev/null +++ b/ElectronicObserver/Utility/ElectronicObserverApi/Models/EquipmentModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Text.Json.Serialization; +using ElectronicObserverTypes; + +namespace ElectronicObserver.Utility.ElectronicObserverApi.Models; + +public record EquipmentModel +{ + [JsonPropertyName("equipmentId")] public EquipmentId EquipmentId { get; set; } + + [JsonPropertyName("level")] public UpgradeLevel Level { get; set; } + + public virtual bool Equals(EquipmentModel? other) + { + if (other is null) return false; + + if (other.EquipmentId != EquipmentId) return false; + if (other.Level != Level) return false; + + return true; + } + + public override int GetHashCode() + { + return HashCode.Combine((int)EquipmentId, (int)Level); + } +} diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesAnalytic.cs b/ElectronicObserver/Utility/ElectronicObserverApi/Models/EquipmentUpgradeIssueModel.cs similarity index 89% rename from ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesAnalytic.cs rename to ElectronicObserver/Utility/ElectronicObserverApi/Models/EquipmentUpgradeIssueModel.cs index ff040ae23..469a3c56c 100644 --- a/ElectronicObserver/Utility/ElectronicObserverApi/DataIssueLogs/WrongUpgradesAnalytic.cs +++ b/ElectronicObserver/Utility/ElectronicObserverApi/Models/EquipmentUpgradeIssueModel.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text.Json.Serialization; -namespace ElectronicObserver.Utility.ElectronicObserverApi.DataIssueLogs; +namespace ElectronicObserver.Utility.ElectronicObserverApi.Models; public record EquipmentUpgradeIssueModel { diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/Models/FitBonusIssueModel.cs b/ElectronicObserver/Utility/ElectronicObserverApi/Models/FitBonusIssueModel.cs new file mode 100644 index 000000000..af99a449c --- /dev/null +++ b/ElectronicObserver/Utility/ElectronicObserverApi/Models/FitBonusIssueModel.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; +using ElectronicObserverTypes.Serialization.FitBonus; + +namespace ElectronicObserver.Utility.ElectronicObserverApi.Models; + +public record FitBonusIssueModel +{ + [JsonPropertyName("software_version")] public string SoftwareVersion { get; set; } = ""; + + [JsonPropertyName("data_version")] public int DataVersion { get; set; } + + [JsonPropertyName("expected")] public FitBonusValue ExpectedBonus { get; set; } = new(); + + [JsonPropertyName("actual")] public FitBonusValue ActualBonus { get; set; } = new(); + + [JsonPropertyName("ship")] public ShipModel Ship { get; set; } = new(); + + [JsonPropertyName("equipments")] public List Equipments { get; set; } = new(); +} diff --git a/ElectronicObserver/Utility/ElectronicObserverApi/Models/ShipModel.cs b/ElectronicObserver/Utility/ElectronicObserverApi/Models/ShipModel.cs new file mode 100644 index 000000000..4236b904d --- /dev/null +++ b/ElectronicObserver/Utility/ElectronicObserverApi/Models/ShipModel.cs @@ -0,0 +1,43 @@ +using System; +using System.Text.Json.Serialization; +using ElectronicObserverTypes; + +namespace ElectronicObserver.Utility.ElectronicObserverApi.Models; + +public record ShipModel +{ + [JsonPropertyName("shipId")] public ShipId ShipId { get; set; } + + [JsonPropertyName("level")] public int Level { get; set; } + + [JsonPropertyName("firepower")] public int Firepower { get; set; } + + [JsonPropertyName("torpedo")] public int Torpedo { get; set; } + + [JsonPropertyName("antiAir")] public int AntiAir { get; set; } + + [JsonPropertyName("armor")] public int Armor { get; set; } + + [JsonPropertyName("evasion")] public int Evasion { get; set; } + [JsonPropertyName("evasionKnown")] public bool EvasionDetermined { get; set; } + + [JsonPropertyName("asw")] public int ASW { get; set; } + [JsonPropertyName("aswKnown")] public bool ASWDetermined { get; set; } + + [JsonPropertyName("los")] public int LOS { get; set; } + [JsonPropertyName("losKnown")] public bool LOSDetermined { get; set; } + + [JsonPropertyName("accuracy")] public int Accuracy { get; set; } + + [JsonPropertyName("range")] public int Range { get; set; } + + public bool IsSameShip(ShipModel? otherModel) + { + if (otherModel is null) return false; + + if (ShipId != otherModel.ShipId) return false; + if (Level != otherModel.Level) return false; + + return true; + } +} diff --git a/ElectronicObserver/Window/Tools/ExpChecker/ExpCheckerViewModel.cs b/ElectronicObserver/Window/Tools/ExpChecker/ExpCheckerViewModel.cs index 485d0901a..c3d99cfa4 100644 --- a/ElectronicObserver/Window/Tools/ExpChecker/ExpCheckerViewModel.cs +++ b/ElectronicObserver/Window/Tools/ExpChecker/ExpCheckerViewModel.cs @@ -499,7 +499,7 @@ EquipmentTypes.CarrierBasedTorpedo or .Cast() .ToList(); - mockShip.AswFit = mockShip.GetFitBonus(KCDatabase.Instance.Translation.FitBonus.FitBonusList).ASW; + mockShip.AswFit = mockShip.GetTheoricalFitBonus(KCDatabase.Instance.Translation.FitBonus.FitBonusList).ASW; bool hasEquipment = stack .GroupBy(s => s) diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/GameDataExtensions.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/GameDataExtensions.cs index 7fcba59ff..aaf7dfdd5 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/GameDataExtensions.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/GameDataExtensions.cs @@ -80,7 +80,7 @@ public static class GameDataExtensions if (shipData.Firepower is null) { // old data, need to calculate fits - FitBonusValue fit = ship.GetFitBonus(FitBonusList); + FitBonusValue fit = ship.GetTheoricalFitBonus(FitBonusList); ship.FirepowerFit = fit.Firepower; ship.TorpedoFit = fit.Torpedo; diff --git a/ElectronicObserverCoreTests/FitBonusTest.cs b/ElectronicObserverCoreTests/FitBonusTest.cs index 9cc301c34..c4f44ea9d 100644 --- a/ElectronicObserverCoreTests/FitBonusTest.cs +++ b/ElectronicObserverCoreTests/FitBonusTest.cs @@ -52,7 +52,7 @@ public void FitBonusTest1() Torpedo = 0, }; - FitBonusValue finalBonus = hachijou.GetFitBonus(BonusData.FitBonusList); + FitBonusValue finalBonus = hachijou.GetTheoricalFitBonus(BonusData.FitBonusList); Assert.Equal(expectedBonus, finalBonus); } @@ -92,7 +92,7 @@ public void FitBonusTest2() Range = 0, }; - FitBonusValue finalBonus = yikikaze.GetFitBonus(BonusData.FitBonusList); + FitBonusValue finalBonus = yikikaze.GetTheoricalFitBonus(BonusData.FitBonusList); Assert.Equal(expectedBonus, finalBonus); } @@ -139,7 +139,7 @@ public void FitBonusTest3() Range = 0, }; - FitBonusValue finalBonus = yikikaze.GetFitBonus(BonusData.FitBonusList); + FitBonusValue finalBonus = yikikaze.GetTheoricalFitBonus(BonusData.FitBonusList); Assert.Equal(expectedBonus, finalBonus); } @@ -188,7 +188,7 @@ public void FitBonusTest4() Range = 0, }; - FitBonusValue finalBonus = yamato.GetFitBonus(BonusData.FitBonusList); + FitBonusValue finalBonus = yamato.GetTheoricalFitBonus(BonusData.FitBonusList); Assert.Equal(expectedBonus, finalBonus); } diff --git a/ElectronicObserverCoreTests/OpeningAswTests.cs b/ElectronicObserverCoreTests/OpeningAswTests.cs index 0692c15a9..019bdd184 100644 --- a/ElectronicObserverCoreTests/OpeningAswTests.cs +++ b/ElectronicObserverCoreTests/OpeningAswTests.cs @@ -34,7 +34,7 @@ public void OpeningAswTest1() Assert.False(kamikaze.CanDoOpeningAsw()); - kamikaze.AswFit = kamikaze.GetFitBonus(BonusData.FitBonusList).ASW; + kamikaze.AswFit = kamikaze.GetTheoricalFitBonus(BonusData.FitBonusList).ASW; Assert.True(kamikaze.CanDoOpeningAsw()); } diff --git a/ElectronicObserverTypes/Serialization/FitBonus/FitBonusValue.cs b/ElectronicObserverTypes/Serialization/FitBonus/FitBonusValue.cs index 97053a559..2cc9d6d0c 100644 --- a/ElectronicObserverTypes/Serialization/FitBonus/FitBonusValue.cs +++ b/ElectronicObserverTypes/Serialization/FitBonus/FitBonusValue.cs @@ -1,10 +1,10 @@ -using System.Text.Json.Serialization; +using System; +using System.Text.Json.Serialization; namespace ElectronicObserverTypes.Serialization.FitBonus; public record FitBonusValue { - [JsonPropertyName("houg")] public int Firepower { get; set; } [JsonPropertyName("raig")] public int Torpedo { get; set; } @@ -51,4 +51,50 @@ public record FitBonusValue Accuracy = a.Accuracy + b.Accuracy, Range = a.Range + b.Range }; + + public bool HasBonus() + { + if (Firepower > 0) return true; + if (Torpedo > 0) return true; + if (AntiAir > 0) return true; + if (Armor > 0) return true; + if (Evasion > 0) return true; + if (ASW > 0) return true; + if (LOS > 0) return true; + if (Accuracy > 0) return true; + if (Range > 0) return true; + + return false; + } + + public virtual bool Equals(FitBonusValue? other) + { + if (other is null) return false; + if (Firepower != other.Firepower) return false; + if (Torpedo != other.Torpedo) return false; + if (AntiAir != other.AntiAir) return false; + if (Armor != other.Armor) return false; + if (Evasion != other.Evasion) return false; + if (ASW != other.ASW) return false; + if (LOS != other.LOS) return false; + if (Accuracy != other.Accuracy) return false; + if (Range != other.Range) return false; + + return true; + } + + public override int GetHashCode() + { + HashCode hashCode = new(); + hashCode.Add(Firepower); + hashCode.Add(Torpedo); + hashCode.Add(AntiAir); + hashCode.Add(Armor); + hashCode.Add(Evasion); + hashCode.Add(ASW); + hashCode.Add(LOS); + hashCode.Add(Accuracy); + hashCode.Add(Range); + return hashCode.ToHashCode(); + } }