diff --git a/ElectronicObserver/Data/PoiDbSubmission/FormDataExtensions.cs b/ElectronicObserver/Data/PoiDbSubmission/FormDataExtensions.cs deleted file mode 100644 index 598de57ff..000000000 --- a/ElectronicObserver/Data/PoiDbSubmission/FormDataExtensions.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Linq; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace ElectronicObserver.Data.PoiDbSubmission; - -public static class FormDataExtensions -{ - private static JsonSerializerOptions JsonSerializerOptions { get; } = new() - { - ReferenceHandler = ReferenceHandler.IgnoreCycles - }; - - /// - /// Specific for air def submission. - [return: NotNullIfNotNull(nameof(metaToken))] - public static Dictionary? ToKeyValue(this object? metaToken, bool objectAsString = false) - { - JsonElement jsonElement = JsonSerializer.SerializeToElement(metaToken, JsonSerializerOptions); - - return ToKeyValue(jsonElement, "", objectAsString); - } - - private static Dictionary? ToKeyValue(this JsonElement element, - string parentPath, bool objectAsString) - { - switch (element.ValueKind) - { - case JsonValueKind.Object when objectAsString && !string.IsNullOrEmpty(parentPath): - { - return new Dictionary { { parentPath, element.ToString() } }; - } - - case JsonValueKind.Object: - { - Dictionary contentData = new(); - foreach (JsonProperty property in element.EnumerateObject()) - { - string path = parentPath switch - { - "" => property.Name, - _ => $"{parentPath}[{property.Name}]", - }; - - Dictionary? childContent = property.Value.ToKeyValue(path, objectAsString); - if (childContent != null) - { - contentData = contentData - .Concat(childContent) - .ToDictionary(k => k.Key, v => v.Value); - } - } - - return contentData; - } - - case JsonValueKind.Array: - { - Dictionary contentData = new(); - foreach ((JsonElement item, int index) in element.EnumerateArray().Select((e, i) => (e, i))) - { - Dictionary? childContent = item.ToKeyValue($"{parentPath}[{index}]", objectAsString); - if (childContent != null) - { - contentData = contentData - .Concat(childContent) - .ToDictionary(k => k.Key, v => v.Value); - } - } - - return contentData; - } - - case JsonValueKind.String when DateTime.TryParse(element.GetString(), out DateTime date): - { - string value = date.ToString("o", CultureInfo.InvariantCulture); - - return new Dictionary { { parentPath, value } }; - } - - case JsonValueKind.String or JsonValueKind.Number or JsonValueKind.True or JsonValueKind.False: - { - string value = element.ToString(); - - return new Dictionary { { parentPath, value } }; - } - - default: return null; - } - } -} - diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbAirDefenseSubmission/PoiDbAirDefenseSubmissionService.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiDbAirDefenseSubmission/PoiDbAirDefenseSubmissionService.cs index a0f331c31..d6aa9c15e 100644 --- a/ElectronicObserver/Data/PoiDbSubmission/PoiDbAirDefenseSubmission/PoiDbAirDefenseSubmissionService.cs +++ b/ElectronicObserver/Data/PoiDbSubmission/PoiDbAirDefenseSubmission/PoiDbAirDefenseSubmissionService.cs @@ -86,6 +86,12 @@ private void SubmitData(JsonNode apiDestructionBattle) foreach ((string key, JsonNode? value) in apiDestructionBattle.AsObject()) { + if (key is "api_air_base_attack") + { + dictionarySubmission.Add(key, value?.ToJsonString()); + continue; + } + dictionarySubmission.Add(key, value); } diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbFriendFleetSubmission/Body.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiDbFriendFleetSubmission/Body.cs deleted file mode 100644 index 8956a6113..000000000 --- a/ElectronicObserver/Data/PoiDbSubmission/PoiDbFriendFleetSubmission/Body.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Collections.Generic; -using System.Text.Json.Nodes; -using System.Text.Json.Serialization; - -namespace ElectronicObserver.Data.PoiDbSubmission.PoiDbFriendFleetSubmission; - -public class Body -{ - [JsonPropertyName("maparea_id")] - public required int World { get; init; } - - [JsonPropertyName("mapinfo_no")] - public required int Map { get; init; } - - [JsonPropertyName("curCellId")] - public required int Cell { get; init; } - - [JsonPropertyName("mapLevel")] - public required int MapLevel { get; init; } - - [JsonPropertyName("friendly_status")] - public required FriendlyStatus FriendlyStatus { get; init; } - - [JsonPropertyName("api_friendly_battle")] - public required JsonNode ApiFriendlyBattle { get; init; } - - [JsonPropertyName("escapeList")] - public required List EscapeList { get; init; } - - [JsonPropertyName("formation")] - public required int Formation { get; init; } - - [JsonPropertyName("enemy")] - public required Dictionary Enemy { get; init; } - - [JsonPropertyName("deck1")] - public required List Deck1 { get; init; } - - [JsonPropertyName("deck2")] - public required List? Deck2 { get; init; } - - [JsonPropertyName("version")] - public required string Version { get; init; } -} diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbFriendFleetSubmission/PoiDbFriendFleetSubmissionData.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiDbFriendFleetSubmission/PoiDbFriendFleetSubmissionData.cs index 90184dc9d..18d46cfd0 100644 --- a/ElectronicObserver/Data/PoiDbSubmission/PoiDbFriendFleetSubmission/PoiDbFriendFleetSubmissionData.cs +++ b/ElectronicObserver/Data/PoiDbSubmission/PoiDbFriendFleetSubmission/PoiDbFriendFleetSubmissionData.cs @@ -1,9 +1,44 @@ -using System.Text.Json.Serialization; +using System.Collections.Generic; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; namespace ElectronicObserver.Data.PoiDbSubmission.PoiDbFriendFleetSubmission; public class PoiDbFriendFleetSubmissionData { - [JsonPropertyName("body")] - public required Body Body { get; init; } + [JsonPropertyName("maparea_id")] + public required int World { get; init; } + + [JsonPropertyName("mapinfo_no")] + public required int Map { get; init; } + + [JsonPropertyName("curCellId")] + public required int Cell { get; init; } + + [JsonPropertyName("mapLevel")] + public required int MapLevel { get; init; } + + [JsonPropertyName("friendly_status")] + public required FriendlyStatus FriendlyStatus { get; init; } + + [JsonPropertyName("api_friendly_battle")] + public required JsonNode ApiFriendlyBattle { get; init; } + + [JsonPropertyName("escapeList")] + public required List EscapeList { get; init; } + + [JsonPropertyName("formation")] + public required int Formation { get; init; } + + [JsonPropertyName("enemy")] + public required Dictionary Enemy { get; init; } + + [JsonPropertyName("deck1")] + public required List Deck1 { get; init; } + + [JsonPropertyName("deck2")] + public required List? Deck2 { get; init; } + + [JsonPropertyName("version")] + public required string Version { get; init; } } diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbFriendFleetSubmission/PoiDbFriendFleetSubmissionService.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiDbFriendFleetSubmission/PoiDbFriendFleetSubmissionService.cs index 1ff6ac70b..59e9af50b 100644 --- a/ElectronicObserver/Data/PoiDbSubmission/PoiDbFriendFleetSubmission/PoiDbFriendFleetSubmissionService.cs +++ b/ElectronicObserver/Data/PoiDbSubmission/PoiDbFriendFleetSubmission/PoiDbFriendFleetSubmissionService.cs @@ -193,38 +193,35 @@ private void SubmitData() { PoiDbFriendFleetSubmissionData submissionData = new() { - Body = new() + World = world, + Map = map, + Cell = cell, + MapLevel = eventDifficulty, + FriendlyStatus = new() { - World = world, - Map = map, - Cell = cell, - MapLevel = eventDifficulty, - FriendlyStatus = new() - { - FirenumBefore = TorchesBefore, - Firenum = TorchesAfter, - Flag = friendFleetRequestFlag, - Type = friendFleetRequestType, - NowMaphp = mapInfo.ApiEventmap?.ApiNowMaphp ?? 0, - MaxMaphp = mapInfo.ApiEventmap?.ApiNowMaphp ?? 0, - Version = Version, - }, - ApiFriendlyBattle = ApiFriendlyBattle, - EscapeList = EscapeList, - Formation = playerFormation, - Enemy = Enemy, - Deck1 = Deck1, - Deck2 = Deck2, + FirenumBefore = TorchesBefore, + Firenum = TorchesAfter, + Flag = friendFleetRequestFlag, + Type = friendFleetRequestType, + NowMaphp = mapInfo.ApiEventmap?.ApiNowMaphp ?? 0, + MaxMaphp = mapInfo.ApiEventmap?.ApiNowMaphp ?? 0, Version = Version, }, + ApiFriendlyBattle = ApiFriendlyBattle, + EscapeList = EscapeList, + Formation = playerFormation, + Enemy = Enemy, + Deck1 = Deck1, + Deck2 = Deck2, + Version = Version, }; - Dictionary> dictionarySubmission = JsonSerializer - .Deserialize>>(JsonSerializer.Serialize(submissionData))!; + Dictionary dictionarySubmission = JsonSerializer + .Deserialize>(JsonSerializer.Serialize(submissionData))!; foreach ((string key, JsonNode? value) in ApiFriendlyInfo.AsObject()) { - dictionarySubmission["body"].Add(key, value); + dictionarySubmission.Add(key, value); } Task.Run(async () => diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbQuestSubmission/Form.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiDbQuestSubmission/Form.cs deleted file mode 100644 index 017210184..000000000 --- a/ElectronicObserver/Data/PoiDbSubmission/PoiDbQuestSubmission/Form.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; -using System.Text.Json.Nodes; -using System.Text.Json.Serialization; -using ElectronicObserver.KancolleApi.Types.Models; - -namespace ElectronicObserver.Data.PoiDbSubmission.PoiDbQuestSubmission; - -public class Form -{ - [JsonPropertyName("current")] - public required int CompletedQuestId { get; init; } - - [JsonPropertyName("after")] - public required List NewQuestIds { get; init; } - - /// - /// Should be but we're skipping deserialization to avoid data loss. - /// - [JsonPropertyName("detail")] - public required List NewQuestData { get; init; } - - [JsonPropertyName("version")] - public required string Version { get; init; } -} diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbQuestSubmission/PoiDbQuestSubmissionData.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiDbQuestSubmission/PoiDbQuestSubmissionData.cs index 02a954e19..109e79321 100644 --- a/ElectronicObserver/Data/PoiDbSubmission/PoiDbQuestSubmission/PoiDbQuestSubmissionData.cs +++ b/ElectronicObserver/Data/PoiDbSubmission/PoiDbQuestSubmission/PoiDbQuestSubmissionData.cs @@ -1,9 +1,24 @@ -using System.Text.Json.Serialization; +using System.Collections.Generic; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; +using ElectronicObserver.KancolleApi.Types.Models; namespace ElectronicObserver.Data.PoiDbSubmission.PoiDbQuestSubmission; public class PoiDbQuestSubmissionData { - [JsonPropertyName("form")] - public required Form Form { get; init; } + [JsonPropertyName("current")] + public required int CompletedQuestId { get; init; } + + [JsonPropertyName("after")] + public required List NewQuestIds { get; init; } + + /// + /// Should be but we're skipping deserialization to avoid data loss. + /// + [JsonPropertyName("detail")] + public required List NewQuestData { get; init; } + + [JsonPropertyName("version")] + public required string Version { get; init; } } diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbQuestSubmission/PoiDbQuestSubmissionService.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiDbQuestSubmission/PoiDbQuestSubmissionService.cs index 74e5e3d68..64ef6c4d0 100644 --- a/ElectronicObserver/Data/PoiDbSubmission/PoiDbQuestSubmission/PoiDbQuestSubmissionService.cs +++ b/ElectronicObserver/Data/PoiDbSubmission/PoiDbQuestSubmission/PoiDbQuestSubmissionService.cs @@ -131,13 +131,10 @@ private void SubmitData() PoiDbQuestSubmissionData submissionData = new() { - Form = new() - { - CompletedQuestId = completedQuestId, - NewQuestIds = newlyUnlockedQuestIds, - NewQuestData = newQuestData, - Version = Version, - } + CompletedQuestId = completedQuestId, + NewQuestIds = newlyUnlockedQuestIds, + NewQuestData = newQuestData, + Version = Version, }; Task.Run(async () => diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteEquipment.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteEquipment.cs new file mode 100644 index 000000000..68abede19 --- /dev/null +++ b/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteEquipment.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; + +namespace ElectronicObserver.Data.PoiDbSubmission.PoiDbRouteSubmission; + +public class PoiDbRouteEquipment +{ + [JsonPropertyName("api_id")] + public required int ApiId { get; init; } + + [JsonPropertyName("api_slotitem_id")] + public required int ApiSlotitemId { get; init; } + + [JsonPropertyName("api_locked")] + public required int ApiLocked { get; init; } + + [JsonPropertyName("api_level")] + public required int ApiLevel { get; init; } + + [JsonPropertyName("api_alv")] + public required int ApiAlv { get; init; } +} diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteShip.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteShip.cs new file mode 100644 index 000000000..016a9931e --- /dev/null +++ b/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteShip.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; + +namespace ElectronicObserver.Data.PoiDbSubmission.PoiDbRouteSubmission; + +public class PoiDbRouteShip +{ + [JsonPropertyName("api_ship_id")] + public required int ApiShipId { get; init; } + + [JsonPropertyName("api_lv")] + public required int ApiLv { get; init; } + + [JsonPropertyName("api_sally_area")] + public required int? ApiSallyArea { get; init; } + + [JsonPropertyName("api_soku")] + public required int ApiSoku { get; init; } + + [JsonPropertyName("api_slotitem_ex")] + public required int ApiSlotitemEx { get; init; } + + [JsonPropertyName("api_slotitem_level")] + public required int ApiSlotitemLevel { get; init; } +} diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteSubmissionData.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteSubmissionData.cs index 27cce46ed..1214a74b7 100644 --- a/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteSubmissionData.cs +++ b/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteSubmissionData.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Text.Json.Nodes; using System.Text.Json.Serialization; namespace ElectronicObserver.Data.PoiDbSubmission.PoiDbRouteSubmission; @@ -7,14 +6,20 @@ namespace ElectronicObserver.Data.PoiDbSubmission.PoiDbRouteSubmission; public class PoiDbRouteSubmissionData { [JsonPropertyName("deck1")] - public required List> Deck1 { get; init; } + public required List Deck1 { get; init; } [JsonPropertyName("deck2")] - public required List>? Deck2 { get; init; } + public required List? Deck2 { get; init; } + /// + /// The type here is either or -1 /> + /// [JsonPropertyName("slot1")] public required List> Slot1 { get; init; } + /// + /// The type here is either or -1 /> + /// [JsonPropertyName("slot2")] public required List>? Slot2 { get; init; } diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteSubmissionService.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteSubmissionService.cs index 25814885b..faa7d1606 100644 --- a/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteSubmissionService.cs +++ b/ElectronicObserver/Data/PoiDbSubmission/PoiDbRouteSubmission/PoiDbRouteSubmissionService.cs @@ -3,7 +3,6 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.Json; -using System.Text.Json.Nodes; using System.Threading.Tasks; using ElectronicObserver.KancolleApi.Types.ApiGetMember.Mapinfo; using ElectronicObserver.KancolleApi.Types.ApiReqMap.Next; @@ -135,36 +134,34 @@ private void SubmitData() if (World is not int world) return; if (Map is not int map) return; - List> deck1 = Fleet1.MembersInstance! + List deck1 = Fleet1.MembersInstance! .OfType() - .Select(Extensions.MakeShip) - .Select(FilterShipValues) + .Select(MakeShip) .ToList(); List> slot1 = Fleet1.MembersInstance! .OfType() - .Select(s => s.AllSlotInstance + .Select(s => s.SlotInstance .Select(e => e switch { - null => (object)JsonValue.Create(-1), - _ => FilterEquipmentValues(e.MakeEquipment()), + null => (object)-1, + _ => MakeEquipment(e), }) .ToList()) .ToList(); - List>? deck2 = Fleet2?.MembersInstance! + List? deck2 = Fleet2?.MembersInstance! .OfType() - .Select(Extensions.MakeShip) - .Select(FilterShipValues) + .Select(MakeShip) .ToList(); List>? slot2 = Fleet2?.MembersInstance! .OfType() - .Select(s => s.AllSlotInstance + .Select(s => s.SlotInstance .Select(e => e switch { - null => (object)JsonValue.Create(-1), - _ => FilterEquipmentValues(e.MakeEquipment()), + null => (object)-1, + _ => MakeEquipment(e), }) .ToList()) .ToList(); @@ -224,33 +221,30 @@ private void SubmitData() } } - private static Dictionary FilterShipValues(JsonNode node) + private static PoiDbRouteShip MakeShip(IShipData ship) => new() { - return node - .AsObject() - .Where(kvp => RelevantKey(kvp.Key)) - .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); - - // the last 2 keys seem to be extra data added by poi? - static bool RelevantKey(string key) => key is - "api_ship_id" or - "api_lv" or - "api_soku" or - "api_slotitem_ex" or - "api_slotitem_level"; - } - - private static Dictionary FilterEquipmentValues(JsonNode node) + ApiShipId = ship.ShipID, + ApiLv = ship.Level, + ApiSallyArea = ship.SallyArea switch + { + > 0 => ship.SallyArea, + _ => null, + }, + ApiSoku = ship.Speed, + ApiSlotitemEx = ship.ExpansionSlotInstance?.EquipmentID ?? -1, + ApiSlotitemLevel = ship.ExpansionSlotInstance?.Level ?? -1, + }; + + public static PoiDbRouteEquipment MakeEquipment(IEquipmentData equipment) => new() { - return node - .AsObject() - .Where(kvp => RelevantKey(kvp.Key)) - .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); - - static bool RelevantKey(string key) => key is - "api_id" or - "api_slotitem_id" or - "api_locked" or - "api_level"; - } + ApiId = equipment.MasterID, + ApiSlotitemId = equipment.EquipmentID, + ApiLocked = equipment.IsLocked switch + { + true => 1, + false => 0, + }, + ApiLevel = equipment.Level, + ApiAlv = equipment.AircraftLevel, + }; } diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiHttpClient.cs b/ElectronicObserver/Data/PoiDbSubmission/PoiHttpClient.cs index 2b1a3f20a..33ed20efc 100644 --- a/ElectronicObserver/Data/PoiDbSubmission/PoiHttpClient.cs +++ b/ElectronicObserver/Data/PoiDbSubmission/PoiHttpClient.cs @@ -11,22 +11,11 @@ namespace ElectronicObserver.Data.PoiDbSubmission; -/// -/// I got the battle and air_base_attack endpoints working -/// couldn't get next_way_v2 working and can't get any info on what's wrong -/// -/// battle endpoint seems to use json but doesn't work without UnsafeRelaxedJsonEscaping -/// -/// air_base_attack endpoint seems to use FormUrlEncodedContent -/// -/// next_way_v2 seems to use MultipartFormDataContent -/// -/// not sure about the other endpoints, but probably MultipartFormDataContent -/// public class PoiHttpClient { private static JsonSerializerOptions JsonSerializerOptions { get; } = new() { + // the default encoder doesn't like Japanese characters apparently Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping, }; @@ -69,7 +58,7 @@ public async Task Battle(PoiDbBattleSubmissionData submission) await EnsureSuccessStatusCode(response); } - public async Task FriendFleet(Dictionary> submission) + public async Task FriendFleet(Dictionary submission) { using HttpClient client = MakeHttpClient(); @@ -81,9 +70,7 @@ public async Task AirDefense(Dictionary submission) { using HttpClient client = MakeHttpClient(); - FormUrlEncodedContent body = GetFormUrlEncoded(submission, true); - - HttpResponseMessage response = await client.PostAsync("air_base_attack", body); + HttpResponseMessage response = await client.PostAsJsonAsync("air_base_attack", submission, JsonSerializerOptions); await EnsureSuccessStatusCode(response); } @@ -91,24 +78,7 @@ public async Task Route(PoiDbRouteSubmissionData submission) { using HttpClient client = MakeHttpClient(); - MultipartFormDataContent formData = GetMultipartFormData(submission); - - HttpResponseMessage response = await client.PostAsync("next_way_v2", formData); + HttpResponseMessage response = await client.PostAsJsonAsync("next_way_v2", submission, JsonSerializerOptions); await EnsureSuccessStatusCode(response); } - - private static MultipartFormDataContent GetMultipartFormData(object data) - { - return new() - { - GetFormUrlEncoded(data), - }; - } - - private static FormUrlEncodedContent GetFormUrlEncoded(object data, bool objectAsString = false) - { - Dictionary formData = data.ToKeyValue(objectAsString); - return new(formData); - } - }