optimise station database by stripping unused info

This commit is contained in:
Florian Stinglmayr 2021-07-29 21:07:53 +02:00
parent 3eccbaa8b8
commit 3b43051200
8 changed files with 202 additions and 5 deletions

View File

@ -1,20 +1,29 @@
using System; using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace NonaBGS.EDDB { namespace NonaBGS.EDDB {
public class API { public class API {
private static readonly string EDDB_SYSTEMS_ARCHIVE = "https://eddb.io/archive/v6/systems_populated.json"; private static readonly string EDDB_SYSTEMS_ARCHIVE = "https://eddb.io/archive/v6/systems_populated.json";
private static readonly string EDDB_STATIONS_ARCHIVE = "https://eddb.io/archive/v6/stations.json";
private string cache_folder = null; private string cache_folder = null;
private readonly WebClient client = new WebClient();
private string systems_file = null; private string systems_file = null;
private string stations_file = null;
private string stations_file_short = null;
public delegate void DatabaseAvailableDelegate(); public delegate void DatabaseAvailableDelegate();
public event DatabaseAvailableDelegate SystemsAvailable; public event DatabaseAvailableDelegate SystemsAvailable;
public event DatabaseAvailableDelegate StationsAvailable;
public string SystemsFile => systems_file; public string SystemsFile => systems_file;
public string StationsFile => stations_file;
public string StationsFileShort => stations_file_short;
public string Cache { public string Cache {
get => cache_folder; get => cache_folder;
@ -28,19 +37,70 @@ namespace NonaBGS.EDDB {
private void Initialise(string cache_folder) { private void Initialise(string cache_folder) {
this.cache_folder = cache_folder; this.cache_folder = cache_folder;
systems_file = Path.Combine(this.cache_folder, "systems_populated.json"); systems_file = Path.Combine(this.cache_folder, "systems_populated.json");
client.DownloadDataCompleted += Client_DownloadDataCompleted; stations_file = Path.Combine(this.cache_folder, "stations.json");
stations_file_short = Path.Combine(this.cache_folder, "stations_short.json");
} }
private void DownloadFile(string url, string file, DatabaseAvailableDelegate notifier) { private void DownloadFile(string url, string file, DatabaseAvailableDelegate notifier) {
WebClient client = new WebClient();
client.DownloadDataCompleted += Client_DownloadDataCompleted;
client.DownloadFileAsync(new Uri(url), file, notifier); client.DownloadFileAsync(new Uri(url), file, notifier);
} }
private void TranslateStations() {
if (!HaveStationsFile) {
return;
}
Dictionary<int, List<string>> systems = new Dictionary<int, List<string>>();
using (var str = new StreamReader(StationsFile)) {
using (var reader = new JsonTextReader(str)) {
JArray obj = (JArray)JToken.ReadFrom(reader);
foreach (JObject child in obj.Children<JObject>()) {
int system_id = child.Value<int>("system_id");
string name = child.Value<string>("name");
if (!systems.ContainsKey(system_id)) {
systems.Add(system_id, new List<string>());
}
systems[system_id].Add(name);
}
}
}
JObject short_stations = new JObject();
foreach(int ids in systems.Keys) {
JArray station_names = new JArray();
foreach(string system in systems[ids]) {
station_names.Add(system);
}
short_stations.Add(ids.ToString(), station_names);
}
using (var outstr = new StreamWriter(stations_file_short)) {
using (var jwriter = new JsonTextWriter(outstr)) {
short_stations.WriteTo(jwriter);
}
}
}
public void Download(bool force) { public void Download(bool force) {
if (!HaveSystemsFile || force) { if (!HaveSystemsFile || force) {
DownloadFile(EDDB_SYSTEMS_ARCHIVE, systems_file, SystemsAvailable); DownloadFile(EDDB_SYSTEMS_ARCHIVE, systems_file, SystemsAvailable);
} else if (HaveSystemsFile) { } else if (HaveSystemsFile) {
SystemsAvailable?.Invoke(); SystemsAvailable?.Invoke();
} }
if (!HaveStationsFile || force) {
DownloadFile(EDDB_STATIONS_ARCHIVE, stations_file, StationsAvailable);
} else if (HaveStationsFile) {
StationsAvailable?.Invoke();
}
} }
public void Download() { public void Download() {
@ -51,6 +111,14 @@ namespace NonaBGS.EDDB {
get { return systems_file != null && File.Exists(systems_file); } get { return systems_file != null && File.Exists(systems_file); }
} }
public bool HaveStationsFile {
get { return stations_file != null && File.Exists(stations_file); }
}
public bool HaveStationsFileShort {
get { return stations_file_short != null && File.Exists(stations_file_short); }
}
public PopulatedSystems MakePopulatedSystems() { public PopulatedSystems MakePopulatedSystems() {
if (!HaveSystemsFile) { if (!HaveSystemsFile) {
throw new InvalidOperationException("no local systems file downloaded"); throw new InvalidOperationException("no local systems file downloaded");
@ -59,6 +127,18 @@ namespace NonaBGS.EDDB {
return PopulatedSystems.FromFile(SystemsFile); return PopulatedSystems.FromFile(SystemsFile);
} }
public Stations MakeStations() {
if (!HaveStationsFile) {
throw new InvalidOperationException("no local systems file downloaded");
}
if (!HaveStationsFileShort) {
TranslateStations();
}
return Stations.FromFile(StationsFileShort);
}
private void Client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) { private void Client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) {
DatabaseAvailableDelegate notifier = e.UserState as DatabaseAvailableDelegate; DatabaseAvailableDelegate notifier = e.UserState as DatabaseAvailableDelegate;
notifier?.Invoke(); notifier?.Invoke();

View File

@ -1,6 +1,6 @@
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
@ -9,6 +9,7 @@ namespace NonaBGS.EDDB {
private string json_file = null; private string json_file = null;
private JArray root = null; private JArray root = null;
private string[] system_names = null; private string[] system_names = null;
private Dictionary<string, int> to_id;
public static PopulatedSystems FromFile(string file) { public static PopulatedSystems FromFile(string file) {
PopulatedSystems pop = new PopulatedSystems(); PopulatedSystems pop = new PopulatedSystems();
@ -16,10 +17,21 @@ namespace NonaBGS.EDDB {
pop.json_file = file; pop.json_file = file;
pop.root = JArray.Parse(content); pop.root = JArray.Parse(content);
pop.Initialise();
return pop; return pop;
} }
private void Initialise() {
MakeSystemNames();
to_id = root.ToDictionary(x => x.Value<string>("name"), x => x.Value<int>("id"));
}
public int ToId(string name) {
return to_id.First(x => string.Compare(x.Key, name, true) == 0).Value;
}
private void MakeSystemNames() { private void MakeSystemNames() {
if (root == null) { if (root == null) {
throw new InvalidDataException("no JSON loaded"); throw new InvalidDataException("no JSON loaded");

51
EDDB/Stations.cs Normal file
View File

@ -0,0 +1,51 @@
using System.Globalization;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Newtonsoft.Json.Linq;
namespace NonaBGS.EDDB {
public class Stations {
private JObject root = null;
private Dictionary<int, List<string>> by_system_id = null;
public JObject JSON => root;
private Stations() {
}
private void Initialise() {
by_system_id = new Dictionary<int, List<string>>();
foreach (var station in root.Properties()) {
int id = int.Parse(station.Name);
var names = root.Value<JArray>(id.ToString()).Values<string>().ToArray();
if (!by_system_id.ContainsKey(id)) {
by_system_id[id] = new List<string>();
}
by_system_id[id].AddRange(names);
}
}
public static Stations FromFile(string filename) {
string alltext = File.ReadAllText(filename);
Stations stations = new Stations {
root = JObject.Parse(alltext),
};
stations.Initialise();
return stations;
}
public string[] StationNamesBySystemId(int systemid, string filter) {
if (!by_system_id.ContainsKey(systemid)) {
return new string[0];
}
return by_system_id[systemid]
.Where(x => CultureInfo.InvariantCulture.CompareInfo.IndexOf(x, filter, CompareOptions.IgnoreCase) > -1)
.ToArray()
;
}
}
}

View File

@ -28,13 +28,16 @@ namespace NonaBGS.Journal {
{ "Mission_Delivery_Retreat_name", "Delivery (Retreat)" }, { "Mission_Delivery_Retreat_name", "Delivery (Retreat)" },
{ "Mission_Delivery_name", "Delivery" }, { "Mission_Delivery_name", "Delivery" },
{ "Mission_Delivery_Agriculture_name", "Delivery (Agriculture)" }, { "Mission_Delivery_Agriculture_name", "Delivery (Agriculture)" },
{ "Mission_Delivery_RankEmp_name", "Delivery (Imperial Rank)" },
{ "Mission_HackMegaship_name", "Hack Megaship" }, { "Mission_HackMegaship_name", "Hack Megaship" },
{ "Mission_MassacreWing_name", "Massacre (Wing)" }, { "Mission_MassacreWing_name", "Massacre (Wing)" },
{ "Mission_OnFoot_Onslaught_MB_name", "On Foot Onslaught" }, { "Mission_OnFoot_Onslaught_MB_name", "On Foot Onslaught" },
{ "Mission_OnFoot_Onslaught_Offline_MB_name", "On Foot Onslaught (Offline)" },
{ "Mission_OnFoot_RebootRestore_MB_name", "On Foot Reboot/Restore" }, { "Mission_OnFoot_RebootRestore_MB_name", "On Foot Reboot/Restore" },
{ "Mission_OnFoot_Reboot_MB_name", "On Foot Reboot" }, { "Mission_OnFoot_Reboot_MB_name", "On Foot Reboot" },
{ "Mission_Rescue_Planet_name", "Planet Rescue" }, { "Mission_Rescue_Planet_name", "Planet Rescue" },
{ "Mission_Salvage_name", "Salvage" }, { "Mission_Salvage_name", "Salvage" },
{ "MISSION_Salvage_CivilUnrest_name", "Salvage (Civil Unrest)" },
{ "MISSION_Salvage_Illegal_name", "Salvage (Illegal)" }, { "MISSION_Salvage_Illegal_name", "Salvage (Illegal)" },
{ "MISSION_Salvage_Retreat_name", "Salvage (Retreat)" }, { "MISSION_Salvage_Retreat_name", "Salvage (Retreat)" },
{ "MISSION_Salvage_Expansion_name", "Salvage (Expansion)" }, { "MISSION_Salvage_Expansion_name", "Salvage (Expansion)" },

View File

@ -32,7 +32,7 @@
<Label Content="System:" HorizontalAlignment="Left" VerticalAlignment="Top"/> <Label Content="System:" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<abc:AutoCompleteTextBox x:Name="system" VerticalAlignment="Center" MinWidth="120" MinHeight="22" KeyDown="Filter_KeyDown"/> <abc:AutoCompleteTextBox x:Name="system" VerticalAlignment="Center" MinWidth="120" MinHeight="22" KeyDown="Filter_KeyDown"/>
<Label Content="Station:" Height="26.2857142857143" VerticalAlignment="Top"/> <Label Content="Station:" Height="26.2857142857143" VerticalAlignment="Top"/>
<abc:AutoCompleteTextBox x:Name="station" Margin="0" VerticalAlignment="Center" MinWidth="120" MinHeight="22" KeyDown="Filter_KeyDown"/> <abc:AutoCompleteTextBox x:Name="station" Margin="0" VerticalAlignment="Center" MinWidth="120" MinHeight="22" KeyDown="Filter_KeyDown" GotFocus="station_GotFocus"/>
<Label Content="Faction:" Height="26.2857142857143" VerticalAlignment="Top"/> <Label Content="Faction:" Height="26.2857142857143" VerticalAlignment="Top"/>
<abc:AutoCompleteTextBox x:Name="faction" Margin="0" VerticalAlignment="Center" MinWidth="120" MinHeight="22" KeyDown="Filter_KeyDown"/> <abc:AutoCompleteTextBox x:Name="faction" Margin="0" VerticalAlignment="Center" MinWidth="120" MinHeight="22" KeyDown="Filter_KeyDown"/>
<Separator Height="26.2857142857143" Margin="0" VerticalAlignment="Top"/> <Separator Height="26.2857142857143" Margin="0" VerticalAlignment="Top"/>

View File

@ -21,6 +21,9 @@ namespace NonaBGS {
private Config config = new Config(); private Config config = new Config();
private API api = null; private API api = null;
private PopulatedSystems systems_db = null;
private Stations stations_db = null;
public Config Config => config; public Config Config => config;
public Report Report => report; public Report Report => report;
@ -53,6 +56,7 @@ namespace NonaBGS {
} }
api.SystemsAvailable += Api_SystemsAvailable; api.SystemsAvailable += Api_SystemsAvailable;
api.StationsAvailable += Api_StationsAvailable;
try { try {
SyncDatabases(); SyncDatabases();
@ -61,9 +65,17 @@ namespace NonaBGS {
} }
} }
private void Api_StationsAvailable() {
try {
stations_db = api.MakeStations();
} catch (Exception e) {
Log(e.Message);
}
}
private void Api_SystemsAvailable() { private void Api_SystemsAvailable() {
try { try {
var systems_db = api.MakePopulatedSystems(); systems_db = api.MakePopulatedSystems();
system.Provider = new SystemSuggestionProvider(systems_db); system.Provider = new SystemSuggestionProvider(systems_db);
} catch (Exception e) { } catch (Exception e) {
Log(e.Message); Log(e.Message);
@ -209,5 +221,23 @@ namespace NonaBGS {
AddObjective(); AddObjective();
} }
} }
private void station_GotFocus(object sender, RoutedEventArgs e) {
try {
if (stations_db == null || systems_db == null) {
return;
}
var sys = system.Text;
if (sys == null || sys.Length <= 0) {
return;
}
int system_id = systems_db.ToId(sys);
station.Provider = new StationSuggestionProvider(stations_db, system_id);
} catch (Exception exc) {
Log(exc.Message);
}
}
} }
} }

View File

@ -0,0 +1,19 @@
using System.Collections;
using AutoCompleteTextBox.Editors;
using NonaBGS.EDDB;
namespace NonaBGS.UI {
public class StationSuggestionProvider : ISuggestionProvider {
private int system_id = 0;
private Stations stations = null;
public StationSuggestionProvider(Stations stations, int system_id) {
this.system_id = system_id;
this.stations = stations;
}
public IEnumerable GetSuggestions(string filter) {
return stations.StationNamesBySystemId(system_id, filter);
}
}
}

View File

@ -74,11 +74,13 @@
<Compile Include="BGS\NonaDiscordLog.cs" /> <Compile Include="BGS\NonaDiscordLog.cs" />
<Compile Include="BGS\SellMicroResources.cs" /> <Compile Include="BGS\SellMicroResources.cs" />
<Compile Include="EDDB\PopulatedSystems.cs" /> <Compile Include="EDDB\PopulatedSystems.cs" />
<Compile Include="EDDB\Stations.cs" />
<Compile Include="Journal\EliteDangerous.cs" /> <Compile Include="Journal\EliteDangerous.cs" />
<Compile Include="Journal\MarketSellEntry.cs" /> <Compile Include="Journal\MarketSellEntry.cs" />
<Compile Include="Journal\MultiSellExplorationDataEntry.cs" /> <Compile Include="Journal\MultiSellExplorationDataEntry.cs" />
<Compile Include="Journal\RedeemVoucherEntry.cs" /> <Compile Include="Journal\RedeemVoucherEntry.cs" />
<Compile Include="Journal\SellMicroResourcesEntry.cs" /> <Compile Include="Journal\SellMicroResourcesEntry.cs" />
<Compile Include="UI\StationSuggestionProvider.cs" />
<Compile Include="UI\SystemSuggestionProvider.cs" /> <Compile Include="UI\SystemSuggestionProvider.cs" />
<Compile Include="Util\AppConfig.cs" /> <Compile Include="Util\AppConfig.cs" />
<Compile Include="Util\Config.cs" /> <Compile Include="Util\Config.cs" />