Skip to content

Commit

Permalink
Handle missing areas when loading states (#1504
Browse files Browse the repository at this point in the history
  • Loading branch information
IhateTrains authored Aug 25, 2023
1 parent e91befd commit 18941f6
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,10 @@ public void NameDefaultsToBlank() {

[Fact]
public void StateCanBeSet() {
var stateCollection = new StateCollection {new State(1, new StateData())};
var reader = new BufferedReader("state = 1");

var province = Province.Parse(reader, 42, states, countries);
var province = Province.Parse(reader, 42, stateCollection, countries);
Assert.NotNull(province.State);
Assert.Equal((ulong)1, province.State.Id);
}
Expand Down
38 changes: 24 additions & 14 deletions ImperatorToCK3.UnitTests/Imperator/States/StateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,43 @@ public class StateTests {
private static readonly ModFilesystem irModFS = new(ImperatorRoot, new Mod[] { });
private static readonly ProvinceCollection provinces = new();
private static readonly AreaCollection areas = new();
private static readonly CountryCollection countries = new() {new Country(69)};
private static readonly CountryCollection countries = new() {new Country(69), new Country(70)};

public StateTests() {
areas.LoadAreas(irModFS, provinces);
}

[Fact]
public void StateCanBeInitialized() {
var stateReader = new BufferedReader("""
area="test_area"
capital=2
country=69
var stateCollection = new StateCollection();
var statesReader = new BufferedReader("""
1 = {
area="test_area"
capital=2
country=69
}
2 = {
area="test_area"
capital=3
country=70
}
""");
var state = new State(1, stateReader, areas, countries);
Assert.Equal("test_area", state.Area.Id);
Assert.Equal((ulong)69, state.Country.Id);
stateCollection.LoadStates(statesReader, areas, countries);
var state1 = stateCollection[1];
Assert.Equal("test_area", state1.Area.Id);
Assert.Equal((ulong)69, state1.Country.Id);
Assert.Equal((ulong)2, state1.CapitalProvince.Id);
var state2 = stateCollection[2];
Assert.Equal("test_area", state2.Area.Id);
Assert.Equal((ulong)70, state2.Country.Id);
Assert.Equal((ulong)3, state2.CapitalProvince.Id);
}

[Fact]
public void ProvincesCanBeRetrievedAfterProvincesInitialization() {
var states = new StateCollection();
var stateReader = new BufferedReader("""
area="test_area"
capital=2
country=69
""");
var state = new State(1, stateReader, areas, countries);
var stateData = new StateData {Area = areas["test_area"], CapitalProvinceId = 2, Country = countries[69]};
var state = new State(1, stateData);
states.Add(state);

var provincesReader = new BufferedReader("""
Expand Down
23 changes: 8 additions & 15 deletions ImperatorToCK3/Imperator/States/State.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using commonItems;
using commonItems.Collections;
using ImperatorToCK3.CommonUtils;
using ImperatorToCK3.Imperator.Countries;
using ImperatorToCK3.Imperator.Geography;
using ImperatorToCK3.Imperator.Provinces;
Expand All @@ -11,23 +9,18 @@ namespace ImperatorToCK3.Imperator.States;

public class State : IIdentifiable<ulong> {
public ulong Id { get; }
private ulong capitalProvinceId;
public Area Area { get; private set; } = null!;
public Country Country { get; private set; } = null!;
private readonly ulong capitalProvinceId;
public Area Area { get; }
public Country Country { get; }

public State(ulong id, BufferedReader stateReader, IdObjectCollection<string, Area> areas, CountryCollection countries) {
public State(ulong id, StateData stateData) {
Id = id;

var parser = new Parser();
parser.RegisterKeyword("capital", reader => capitalProvinceId = reader.GetULong());
parser.RegisterKeyword("area", reader => Area = areas[reader.GetString()]);
parser.RegisterKeyword("country", reader => Country = countries[reader.GetULong()]);
parser.IgnoreAndStoreUnregisteredItems(IgnoredKeywords);
parser.ParseStream(stateReader);

capitalProvinceId = stateData.CapitalProvinceId;
Area = stateData.Area!;
Country = stateData.Country!;
}

public Province CapitalProvince => Area.Provinces.First(p => p.Id == capitalProvinceId);
public IEnumerable<Province> Provinces => Area.Provinces.Where(p => p.State?.Id == Id);

public static IgnoredKeywordsSet IgnoredKeywords { get; } = new();
}
41 changes: 38 additions & 3 deletions ImperatorToCK3/Imperator/States/StateCollection.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,58 @@
using commonItems;
using commonItems.Collections;
using ImperatorToCK3.CommonUtils;
using ImperatorToCK3.Imperator.Countries;
using ImperatorToCK3.Imperator.Geography;

namespace ImperatorToCK3.Imperator.States;

public class StateCollection : IdObjectCollection<ulong, State> {
public void LoadStates(BufferedReader statesDbReader, IdObjectCollection<string, Area> areas, CountryCollection countries) {
stateDataParser.RegisterKeyword("capital", reader => stateData.CapitalProvinceId = reader.GetULong());
stateDataParser.RegisterKeyword("area", reader => {
var areaId = reader.GetString();
if (!areas.TryGetValue(areaId, out var area)) {
Logger.Warn($"Unrecognized area found when loading states: {areaId}");
return;
}
stateData.Area = area;
});
stateDataParser.RegisterKeyword("country", reader => {
var countryId = reader.GetULong();
if (!countries.TryGetValue(countryId, out var country)) {
Logger.Warn($"Unrecognized country found when loading states: {countryId}");
return;
}
stateData.Country = country;
});
stateDataParser.IgnoreAndStoreUnregisteredItems(IgnoredStateKeywords);

var parser = new Parser();
parser.RegisterRegex(CommonRegexes.Integer, (reader, stateIdStr) => {
var strOfItem = reader.GetStringOfItem();
if (!strOfItem.IsArrayOrObject()) {
return;
}
var stateReader = new BufferedReader(strOfItem.ToString());
AddOrReplace(new State(ulong.Parse(stateIdStr), stateReader, areas, countries));
var stateId = ulong.Parse(stateIdStr);
stateData = new StateData();
stateDataParser.ParseStream(new BufferedReader(strOfItem.ToString()));
if (stateData.Area is null) {
Logger.Warn($"State {stateId} has no area defined!");
return;
}
if (stateData.Country is null) {
Logger.Warn($"State {stateId} has no country defined!");
return;
}
AddOrReplace(new State(stateId, stateData));
});
parser.IgnoreAndLogUnregisteredItems();
parser.ParseStream(statesDbReader);
}

private StateData stateData = new();
private readonly Parser stateDataParser = new();

public static IgnoredKeywordsSet IgnoredStateKeywords { get; } = new();
}
10 changes: 10 additions & 0 deletions ImperatorToCK3/Imperator/States/StateData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using ImperatorToCK3.Imperator.Countries;
using ImperatorToCK3.Imperator.Geography;

namespace ImperatorToCK3.Imperator.States;

public record StateData {
public ulong CapitalProvinceId { get; set; }
public Area? Area { get; set; }
public Country? Country { get; set; }
}
2 changes: 1 addition & 1 deletion ImperatorToCK3/Imperator/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public World(Configuration config, ConverterVersion converterVersion): this(conf
statesBlocParser.RegisterKeyword("state_database", statesReader => States.LoadStates(statesReader, Areas, Countries));
statesBlocParser.IgnoreAndLogUnregisteredItems();
statesBlocParser.ParseStream(reader);
Logger.Debug($"Ignored state keywords: {State.IgnoredKeywords}");
Logger.Debug($"Ignored state keywords: {StateCollection.IgnoredStateKeywords}");
Logger.Info($"Loaded {States.Count} states.");
Logger.IncrementProgress();
});
Expand Down

0 comments on commit 18941f6

Please sign in to comment.