Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion ElectronicObserver/Data/KCDatabase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ElectronicObserver.Data.Battle;
using DynaJson;
using ElectronicObserver.Data.Battle;
using ElectronicObserver.Data.Quest;
using ElectronicObserver.Data.Translation;
using ElectronicObserver.Data.TsunDbSubmission;
Expand Down Expand Up @@ -206,8 +207,41 @@ private KCDatabase()
TsunDbSubmission = new TsunDbSubmissionManager();
FleetPreset = new FleetPresetManager();
Translation = new DataAndTranslationManager();

#if DEBUG
// data needed for loading old event battles via local api loader
// the values don't really matter, they just need to exist
for (int i = 56; i <= 59; i++)
{
AddWorld(i);
}
#endif
}

private void AddWorld(int world)
{
string json = $$"""{"api_id":{{world}},"api_name":"","api_type":1}""";
dynamic elem = JsonObject.Parse(json);

MapAreaData item = new();
item.LoadFromResponse("api_start2/getData", elem);
MapArea.Add(item);

for (int i = 1; i <= 7; i++)
{
AddMap(world, i);
}
}

private void AddMap(int world, int map)
{
string json = $$"""{"api_id":{{world}}{{map}},"api_maparea_id":{{world}},"api_no":{{map}},"api_name":"","api_level":6,"api_opetext":"","api_infotext":"","api_item":[32,34,0,0],"api_max_maphp":300,"api_required_defeat_count":null,"api_sally_flag":[1,0,0]}""";
dynamic elem = JsonObject.Parse(json);

MapInfoData item = new();
item.LoadFromResponse("api_start2/getData", elem);
MapInfo.Add(item);
}

public void Load()
{
Expand Down
174 changes: 165 additions & 9 deletions ElectronicObserver/Window/Dialog/DialogLocalAPILoader2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,31 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Windows.Forms;
using ElectronicObserver.Database;
using ElectronicObserver.Database.KancolleApi;
using ElectronicObserver.Database.Sortie;
using ElectronicObserver.KancolleApi.Types;
using ElectronicObserver.KancolleApi.Types.ApiPort.Port;
using ElectronicObserver.KancolleApi.Types.Models;
using ElectronicObserver.Observer;
using ElectronicObserver.Utility;
using ElectronicObserver.ViewModels;
using Microsoft.EntityFrameworkCore;

namespace ElectronicObserver.Window.Dialog;

public partial class DialogLocalAPILoader2 : Form
{
private JsonSerializerOptions JsonSerializerOptions { get; } = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
};

private SortieRecord? SortieRecord { get; }
private List<ApiFile> ApiFilesBeforeSortie { get; set; } = [];

private string CurrentPath { get; set; }

Expand All @@ -24,6 +40,11 @@ public DialogLocalAPILoader2()
Translate();
}

public DialogLocalAPILoader2(SortieRecord sortieRecord) : this()
{
SortieRecord = sortieRecord;
}

public void Translate()
{
APIView_FileName.HeaderText = LocalAPILoader2Resources.APIView_FileName;
Expand All @@ -44,7 +65,14 @@ public void Translate()

private void DialogLocalAPILoader2_Load(object sender, EventArgs e)
{
LoadFiles(Utility.Configuration.Config.Connection.SaveDataPath);
if (SortieRecord is null)
{
LoadFiles(Utility.Configuration.Config.Connection.SaveDataPath);
}
else
{
LoadSortieRecordFiles(SortieRecord);
}
}


Expand Down Expand Up @@ -101,14 +129,19 @@ private void ViewMenu_Delete_Click(object sender, EventArgs e)

private void ButtonExecuteNext_Click(object sender, EventArgs e)
{

if (APIView.SelectedRows.Count == 1)
{

var row = APIView.SelectedRows[0];
DataGridViewRow row = APIView.SelectedRows[0];
int index = APIView.SelectedRows[0].Index;

ExecuteAPI((string)row.Cells[APIView_FileName.Index].Value);
if (SortieRecord is null)
{
ExecuteAPI((string)row.Cells[APIView_FileName.Index].Value);
}
else
{
ExecuteSortieRecordApi((string)row.Cells[APIView_FileName.Index].Value);
}

APIView.ClearSelection();
if (index < APIView.Rows.Count - 1)
Expand Down Expand Up @@ -154,6 +187,45 @@ private void LoadFiles(string path)

}

private void LoadSortieRecordFiles(SortieRecord sortieRecord)
{
if (sortieRecord.ApiFiles.Count is 0) return;

APIView.Rows.Clear();

List<DataGridViewRow> rows = [];

int firstSortieApiFileId = sortieRecord.ApiFiles.MinBy(f => f.Id)!.Id;

ElectronicObserverContext db = new();
db.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

int lastPortFileIdBeforeSortieId = db.ApiFiles
.Where(f => f.Id < firstSortieApiFileId)
.Where(f => f.Name == "api_port/port")
.OrderByDescending(f => f.Id)
.First()
.Id;

ApiFilesBeforeSortie = db.ApiFiles
.Where(f => f.Id < firstSortieApiFileId)
.Where(f => f.Id >= lastPortFileIdBeforeSortieId)
.ToList();

foreach (string file in ApiFilesBeforeSortie.Concat(sortieRecord.ApiFiles).Select(f => $"{f.Id} {f.ApiFileType} {f.Name}"))
{
DataGridViewRow row = new();
row.CreateCells(APIView);

row.SetValues(file);
rows.Add(row);
}

APIView.Rows.AddRange([.. rows]);
APIView.Sort(APIView_FileName, ListSortDirection.Ascending);

}


//filename format: yyyyMMdd_hhmmssff[Q|S]@apipath@apiname.json
private string GetAPIName(string fileName)
Expand Down Expand Up @@ -211,15 +283,85 @@ private void ExecuteAPI(string filename)

}

private void ExecuteSortieRecordApi(string filename)
{
Debug.Assert(SortieRecord is not null);

string[] values = filename.Split(" ");

int recordId = int.Parse(values[0]);
ApiFileType apiFileType = Enum.Parse<ApiFileType>(values[1]);
string apiName = values[2];

if (!APIObserver.Instance.APIList.ContainsKey(apiName)) return;

ApiFile apiFile = ApiFilesBeforeSortie.Concat(SortieRecord.ApiFiles).First(f => f.Id == recordId);

if (apiFile.Name is "api_port/port")
{
string? savedPortResponseJson = LoadApiResponse("api_port/port");

if (savedPortResponseJson is not null)
{
ApiResponse<ApiPortPortResponse> savedPortResponse = JsonSerializer
.Deserialize<ApiResponse<ApiPortPortResponse>>(savedPortResponseJson[7..])
?? throw new NotImplementedException();

ApiResponse<ApiPortPortResponse> apiFilePortResponse = JsonSerializer
.Deserialize<ApiResponse<ApiPortPortResponse>>(apiFile.Content)
?? throw new NotImplementedException();

apiFilePortResponse.ApiData.ApiShip = savedPortResponse.ApiData.ApiShip;
apiFilePortResponse.ApiData.ApiLog = savedPortResponse.ApiData.ApiLog;
apiFilePortResponse.ApiData.ApiNdock = savedPortResponse.ApiData.ApiNdock;

apiFilePortResponse.ApiData.ApiDeckPort = SortieRecord.FleetData.Fleets
.Select((f, i) => f switch
{
null => null,

_ => new FleetDataDto
{
ApiId = i + 1,
ApiShip = f.Ships.Select(s => s.DropId ?? 0).ToList(),
ApiMission = [0, 0, 0, 0],
},
})
.OfType<FleetDataDto>()
.ToList();

apiFile.Content = JsonSerializer.Serialize(apiFilePortResponse, JsonSerializerOptions);
}
}

switch (apiFileType)
{
case ApiFileType.Request:
Dictionary<string, string> queryParameters = JsonSerializer
.Deserialize<Dictionary<string, string>>(apiFile.Content)
?? throw new NotImplementedException();

string queryString = string.Join("&", queryParameters.Select(kvp => $"{kvp.Key}={kvp.Value}"));
APIObserver.Instance.LoadRequest("/kcsapi/" + apiName, queryString);
break;

case ApiFileType.Response:
APIObserver.Instance.LoadResponse("/kcsapi/" + apiName, $"svdata={apiFile.Content}");
break;
}
}

private void APICaller_DoWork(object sender, DoWorkEventArgs e)
{
if (e.Argument is not IEnumerable<string?> files) return;

var files = e.Argument as IOrderedEnumerable<string>;
var act = new Action<string>(ExecuteAPI);
Action<string> act = SortieRecord switch
{
null => ExecuteAPI,
_ => ExecuteSortieRecordApi,
};

foreach (var file in files)
foreach (string? file in files)
{
Invoke(act, file);
System.Threading.Thread.Sleep(10); //ゆるして
Expand Down Expand Up @@ -375,7 +517,7 @@ private void APIView_CellMouseDoubleClick(object sender, DataGridViewCellMouseEv
{
try
{
ProcessStartInfo psi = new ProcessStartInfo
ProcessStartInfo psi = new()
{
FileName = CurrentPath + "\\" + APIView.SelectedCells.OfType<DataGridViewCell>().First().Value,
UseShellExecute = true
Expand All @@ -387,4 +529,18 @@ private void APIView_CellMouseDoubleClick(object sender, DataGridViewCellMouseEv
Utility.Logger.Add(1, string.Format(LocalAPILoader2Resources.FailedToStart, ex.GetType().Name, ex.Message));
}
}

private static string? LoadApiResponse(string apiName)
{
Configuration.ConfigurationData config = Configuration.Config;

if (string.IsNullOrEmpty(config.Connection.SaveDataPath)) return null;
if (!Directory.Exists(config.Connection.SaveDataPath)) return null;

string filePath = Path.Combine(config.Connection.SaveDataPath, "kcsapi", apiName);

if (!File.Exists(filePath)) return null;

return File.ReadAllText(filePath);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using ElectronicObserver.Database.DataMigration;
using ElectronicObserver.Services;
using ElectronicObserver.Utility;
using ElectronicObserver.Window.Dialog;
using ElectronicObserver.Window.Tools.SortieRecordViewer.DataExport;
using ElectronicObserver.Window.Tools.SortieRecordViewer.SortieCostViewer;
using Microsoft.EntityFrameworkCore;
Expand Down Expand Up @@ -77,6 +78,13 @@ public partial class SortieRecordViewerViewModel : WindowViewModelBase

private SortieCostConfigurationViewModel SortieCostConfiguration { get; } = new();

public bool IsDebug =>
#if DEBUG
true;
#else
false;
#endif

public SortieRecordViewerViewModel()
{
ToolService = Ioc.Default.GetRequiredService<ToolService>();
Expand Down Expand Up @@ -471,4 +479,15 @@ private void OpenSortieCost()

new SortieCostViewerWindow(sortieCost).Show();
}

[RelayCommand]
private async Task OpenLocalApiLoader()
{
if (!IsDebug) return;
if (SelectedSortie is null) return;

await SelectedSortie.Model.EnsureApiFilesLoaded(Db);

new DialogLocalAPILoader2(SelectedSortie.Model).Show();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@
<MenuItem Command="{Binding CopySmokerDataCsvCommand}" Header="{Binding SortieRecordViewer.SmokeScreenCsv}" />
<MenuItem Command="{Binding ExportBattleRanksCommand}" Header="{x:Static translations:CsvExportResources.CombatRankPrediction}" />
</MenuItem>
<MenuItem
Command="{Binding OpenLocalApiLoaderCommand}"
Header="Local api loader"
Visibility="{Binding IsDebug, Converter={StaticResource BooleanToVisibilityConverter}}"
/>
</ContextMenu>
</DataGrid.ContextMenu>

Expand Down