Skip to content

Commit

Permalink
fix api file saving #406
Browse files Browse the repository at this point in the history
  • Loading branch information
myangelkamikaze committed Oct 18, 2023
1 parent 46e1a45 commit edc8d53
Showing 1 changed file with 75 additions and 60 deletions.
135 changes: 75 additions & 60 deletions ElectronicObserver/Services/ApiFileService/ApiFileService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using ElectronicObserver.KancolleApi.Types.ApiPort.Port;
using ElectronicObserver.KancolleApi.Types.ApiReqMap.Start;
using ElectronicObserver.KancolleApi.Types.ApiReqMission.Result;
using ElectronicObserver.Utility;
using ElectronicObserverTypes;
using Microsoft.EntityFrameworkCore;

Expand Down Expand Up @@ -63,8 +64,15 @@ private async Task ProcessApiDataAsync()
// basically while (true)
while (await ApiProcessingChannel.Reader.WaitToReadAsync())
{
ApiFileData apiFile = await ApiProcessingChannel.Reader.ReadAsync();
await SaveApiData(apiFile.ApiName, apiFile.RequestBody, apiFile.ResponseBody);
try
{
ApiFileData apiFile = await ApiProcessingChannel.Reader.ReadAsync();
await SaveApiData(apiFile.ApiName, apiFile.RequestBody, apiFile.ResponseBody);
}
catch (Exception e)
{
Logger.Add(3, $"Api file saving error: {e.GetBaseException().Message} {e.StackTrace}");
}
}
}

Expand Down Expand Up @@ -100,10 +108,10 @@ private async Task SaveApiData(string apiName, string requestBody, string respon
await db.ApiFiles.AddAsync(requestFile);
await db.ApiFiles.AddAsync(responseFile);

await db.SaveChangesAsync();
await ProcessSortieData(db, requestFile, responseFile);
await ProcessExpeditionData(db, requestFile, responseFile);

await ProcessSortieData(requestFile, responseFile);
await ProcessExpeditionData(requestFile, responseFile);
await db.SaveChangesAsync();
}

public async Task Add(string apiName, string requestBody, string responseBody)
Expand Down Expand Up @@ -166,8 +174,14 @@ private static string TrimPort(string apiName, string responseBody)
return responseBody;
}

private async Task ProcessSortieData(ApiFile requestFile, ApiFile responseFile)
private async Task ProcessSortieData(ElectronicObserverContext db, ApiFile requestFile, ApiFile responseFile)
{
if (requestFile.Name is "api_req_map/start")
{
await CreateNewSortie(db, requestFile, responseFile);
return;
}

if (requestFile.Name is "api_port/port")
{
if (CurrentSortieId is int sortieId)
Expand All @@ -179,86 +193,88 @@ private async Task ProcessSortieData(ApiFile requestFile, ApiFile responseFile)
return;
}

await using ElectronicObserverContext db = new();
SortieRecord? sortieRecord = CurrentSortieId switch
{
int id => await db.Sorties.FirstOrDefaultAsync(s => s.Id == id),
_ => null,
};

if (requestFile.Name is "api_req_map/start")
if (sortieRecord is null)
{
if (sortieRecord is not null)
{
// todo: log bug - SortieRecord should always be null before a sortie starts
}
// this should be all apis that are not related to a sortie
// apis related to sortie are all api calls that happen between
// "api_req_map/start" and "api_port/port"
// can also happen if there's an error when parsing "api_req_map/start"
return;
}

ApiReqMapStartRequest? request = null;
ApiResponse<ApiReqMapStartResponse>? response = null;
sortieRecord.ApiFiles.Add(requestFile);
sortieRecord.ApiFiles.Add(responseFile);

try
{
request = JsonSerializer.Deserialize<ApiReqMapStartRequest>(requestFile.Content);
response = JsonSerializer.Deserialize<ApiResponse<ApiReqMapStartResponse>>(responseFile.Content);
}
catch
{
// todo: report failed parsing
}
await db.SaveChangesAsync();
}

if (request is null) return;
if (response is null) return;
if (!int.TryParse(request.ApiDeckId, out int fleetId)) return;
private async Task CreateNewSortie(ElectronicObserverContext db, ApiFile requestFile, ApiFile responseFile)
{
if (CurrentSortieId is not null)
{
// todo: log bug - CurrentSortieId should always be null before a sortie starts
}

MapInfoData? map = KcDatabase.MapInfo.Values
.Where(m => m.MapAreaID == response.ApiData.ApiMapareaId)
.FirstOrDefault(m => m.MapInfoID == response.ApiData.ApiMapinfoNo);
ApiReqMapStartRequest? request = null;
ApiResponse<ApiReqMapStartResponse>? response = null;

if (map is null) return;
try
{
request = JsonSerializer.Deserialize<ApiReqMapStartRequest>(requestFile.Content);
response = JsonSerializer.Deserialize<ApiResponse<ApiReqMapStartResponse>>(responseFile.Content);
}
catch
{
// todo: report failed parsing
}

SortieMapData mapData = new()
{
RequiredDefeatedCount = map.RequiredDefeatedCount,
MapHPMax = map.MapHPMax,
MapHPCurrent = map.MapHPCurrent,
};
if (request is null) return;
if (response is null) return;
if (!int.TryParse(request.ApiDeckId, out int fleetId)) return;

int nodeSupportFleetId = KcDatabase.Fleet.NodeSupportFleetId(map.MapAreaID) ?? 0;
int bossSupportFleetId = KcDatabase.Fleet.BossSupportFleetId(map.MapAreaID) ?? 0;
MapInfoData? map = KcDatabase.MapInfo.Values
.Where(m => m.MapAreaID == response.ApiData.ApiMapareaId)
.FirstOrDefault(m => m.MapInfoID == response.ApiData.ApiMapinfoNo);

SortieFleetData fleetData = MakeSortieFleet(KcDatabase, fleetId, nodeSupportFleetId,
bossSupportFleetId, map);
if (map is null) return;

sortieRecord = new()
{
World = response.ApiData.ApiMapareaId,
Map = response.ApiData.ApiMapinfoNo,
FleetData = fleetData,
MapData = mapData,
};
SortieMapData mapData = new()
{
RequiredDefeatedCount = map.RequiredDefeatedCount,
MapHPMax = map.MapHPMax,
MapHPCurrent = map.MapHPCurrent,
};

await db.Sorties.AddAsync(sortieRecord);
await db.SaveChangesAsync();
int nodeSupportFleetId = KcDatabase.Fleet.NodeSupportFleetId(map.MapAreaID) ?? 0;
int bossSupportFleetId = KcDatabase.Fleet.BossSupportFleetId(map.MapAreaID) ?? 0;

CurrentSortieId = sortieRecord.Id;
}
SortieFleetData fleetData = MakeSortieFleet(KcDatabase, fleetId, nodeSupportFleetId,
bossSupportFleetId, map);

if (sortieRecord is null)
SortieRecord sortieRecord = new()
{
// this should be all apis that are not related to a sortie
// apis related to sortie are all api calls that happen between
// "api_req_map/start" and "api_port/port"
// can also happen if there's an error when parsing "api_req_map/start"
return;
}
World = response.ApiData.ApiMapareaId,
Map = response.ApiData.ApiMapinfoNo,
FleetData = fleetData,
MapData = mapData,
};

sortieRecord.ApiFiles.Add(requestFile);
sortieRecord.ApiFiles.Add(responseFile);

await db.Sorties.AddAsync(sortieRecord);
await db.SaveChangesAsync();

CurrentSortieId = sortieRecord.Id;
}

private async Task ProcessExpeditionData(ApiFile requestFile, ApiFile responseFile)
private async Task ProcessExpeditionData(ElectronicObserverContext db, ApiFile requestFile, ApiFile responseFile)
{
if (requestFile.Name is not "api_req_mission/result") return;

Expand All @@ -279,7 +295,6 @@ private async Task ProcessExpeditionData(ApiFile requestFile, ApiFile responseFi
if (response is null) return;
if (!int.TryParse(request.ApiDeckId, out int fleetId)) return;

await using ElectronicObserverContext db = new();
IFleetData f = KCDatabase.Instance.Fleet[fleetId];

SortieFleet fleet = new()
Expand Down

0 comments on commit edc8d53

Please sign in to comment.