Skip to content

Optimize the writing of the generated mod #2010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 25, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using ImperatorToCK3.CK3.Characters;
using ImperatorToCK3.Outputter;
using System.IO;
using System.Text;
using Xunit;

namespace ImperatorToCK3.UnitTests.Outputter;
Expand All @@ -18,10 +19,10 @@ public void PregnancyIsOutputted() {
var pregnantFemale = new Character("1", "Incontinentia", birthDate: "580.1.1", characters) {Female = true};
pregnantFemale.Pregnancies.Add(new Pregnancy(fatherId:"2", motherId: "1", childBirthDate, isBastard:false));

var output = new StringWriter();
CharacterOutputter.OutputCharacter(output, pregnantFemale, conversionDate);
var sb = new StringBuilder();
CharacterOutputter.WriteCharacter(sb, pregnantFemale, conversionDate);

var outputString = output.ToString();
var outputString = sb.ToString();
outputString.Should().Contain("female = yes");
outputString.Should().Contain($"{conceptionDate}={{ effect={{ make_pregnant_no_checks={{ father=character:2 }} }} }}");
}
Expand Down
12 changes: 4 additions & 8 deletions ImperatorToCK3.UnitTests/Outputter/ProvinceOutputterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ public void CultureIsOutputted() {
var province = new Province(1, provReader);

var sb = new StringBuilder();
var sw = new StringWriter(sb);
ProvinceOutputter.OutputProvince(sw, province);
ProvinceOutputter.WriteProvince(sb, province);

var sr = new StringReader(sb.ToString());
Assert.Equal("1={", sr.ReadLine());
Expand All @@ -32,8 +31,7 @@ public void ReligionIsOutputted() {
var province = new Province(1, provReader);

var sb = new StringBuilder();
var sw = new StringWriter(sb);
ProvinceOutputter.OutputProvince(sw, province);
ProvinceOutputter.WriteProvince(sb, province);

var sr = new StringReader(sb.ToString());
Assert.Equal("1={", sr.ReadLine());
Expand All @@ -48,8 +46,7 @@ public void HoldingIsOutputted() {
var province = new Province(1, provReader);

var sb = new StringBuilder();
var sw = new StringWriter(sb);
ProvinceOutputter.OutputProvince(sw, province);
ProvinceOutputter.WriteProvince(sb, province);

var sr = new StringReader(sb.ToString());
Assert.Equal("1={", sr.ReadLine());
Expand All @@ -63,8 +60,7 @@ public void BuildingsAreOutputted() {
var province = new Province(1, provReader);

var sb = new StringBuilder();
var sw = new StringWriter(sb);
ProvinceOutputter.OutputProvince(sw, province);
ProvinceOutputter.WriteProvince(sb, province);

var sr = new StringReader(sb.ToString());
Assert.Equal("1={", sr.ReadLine());
Expand Down
9 changes: 5 additions & 4 deletions ImperatorToCK3/CK3/Characters/DNA.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ImperatorToCK3.CK3.Characters;
Expand Down Expand Up @@ -44,13 +45,13 @@ IDictionary<string, DNAAccessoryGeneValue> accessoryDNAValues
this.accessoryDNAValues = new(accessoryDNAValues);
}

public async Task OutputGenes(StreamWriter output) {
await output.WriteLineAsync("\t\tgenes={");
public void WriteGenes(StringBuilder sb) {
sb.AppendLine("\t\tgenes={");

foreach (var dnaLine in DNALines) {
await output.WriteLineAsync($"\t\t\t{dnaLine}");
sb.AppendLine($"\t\t\t{dnaLine}");
}

await output.WriteLineAsync("\t\t}");
sb.AppendLine("\t\t}");
}
}
25 changes: 14 additions & 11 deletions ImperatorToCK3/CK3/Cultures/Culture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public string Serialize(string indent, bool withBraces) {
}

sb.Append(contentIndent).AppendLine($"color={Color.OutputRgb()}");
if (ParentCultureIds.Any()) {
if (ParentCultureIds.Count != 0) {
sb.Append(contentIndent).AppendLine($"parents={PDXSerializer.Serialize(ParentCultureIds)}");
}
sb.Append(contentIndent).AppendLine($"heritage={Heritage.Id}");
Expand All @@ -76,21 +76,24 @@ public async Task OutputHistory(string outputModPath, Date date) {
return;
}

var historyPath = Path.Combine(outputModPath, "history/cultures", Id + ".txt");
await using var historyWriter = File.CreateText(historyPath);
await historyWriter.WriteLineAsync("# This file was generated by the IRToCK3 converter.");
var historyStrBuilder = new StringBuilder();
historyStrBuilder.AppendLine("# This file was generated by the IRToCK3 converter.");

await historyWriter.WriteLineAsync($"{date} = {{");
historyStrBuilder.AppendLine($"{date} = {{");
foreach (var innovationId in innovationsFromImperator) {
await historyWriter.WriteLineAsync($"\tdiscover_innovation = {innovationId}");
historyStrBuilder.AppendLine($"\tdiscover_innovation = {innovationId}");
}
foreach (var (innovationId, progress) in innovationProgressesFromImperator) {
await historyWriter.WriteLineAsync("\tadd_innovation_progress = {");
await historyWriter.WriteLineAsync($"\t\tculture_innovation = {innovationId}");
await historyWriter.WriteLineAsync($"\t\tprogress = {progress}");
await historyWriter.WriteLineAsync("\t}");
historyStrBuilder.AppendLine("\tadd_innovation_progress = {");
historyStrBuilder.AppendLine($"\t\tculture_innovation = {innovationId}");
historyStrBuilder.AppendLine($"\t\tprogress = {progress}");
historyStrBuilder.AppendLine("\t}");
}
await historyWriter.WriteLineAsync("}");
historyStrBuilder.AppendLine("}");

var historyPath = Path.Combine(outputModPath, "history/cultures", Id + ".txt");
await using var historyWriter = File.CreateText(historyPath);
await historyWriter.WriteAsync(historyStrBuilder.ToString());
}

public void ImportInnovationsFromImperator(ISet<string> irInventions, InnovationMapper innovationMapper) {
Expand Down
74 changes: 40 additions & 34 deletions ImperatorToCK3/Outputter/BookmarkOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,16 @@

await OutputBookmarkGroup(config);

var path = Path.Combine("output", config.OutputModName, "common/bookmarks/bookmarks/00_bookmarks.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(path, Encoding.UTF8);

var provincePositions = world.MapData.ProvincePositions;

await output.WriteLineAsync("bm_converted = {");
var sb = new StringBuilder();
sb.AppendLine("bm_converted = {");

await output.WriteLineAsync("\tgroup = bm_converted");
await output.WriteLineAsync($"\tstart_date = {config.CK3BookmarkDate}");
await output.WriteLineAsync("\tis_playable = yes");
await output.WriteLineAsync("\trecommended = yes");
await output.WriteLineAsync("\tweight = { value = 100 }");
sb.AppendLine("\tgroup = bm_converted");
sb.AppendLine($"\tstart_date = {config.CK3BookmarkDate}");
sb.AppendLine("\tis_playable = yes");
sb.AppendLine("\trecommended = yes");
sb.AppendLine("\tweight = { value = 100 }");

var playerTitles = new List<Title>(world.LandedTitles.Where(title => title.PlayerCountry));
var localizations = new Dictionary<string, LocBlock>();
Expand All @@ -53,10 +51,14 @@
continue;
}

await AddTitleToBookmarkScreen(title, output, holderId, world, localizations, provincePositions, config);
await AddTitleToBookmarkScreen(title, sb, holderId, world, localizations, provincePositions, config);
}

await output.WriteLineAsync("}");
sb.AppendLine("}");

var path = Path.Combine("output", config.OutputModName, "common/bookmarks/bookmarks/00_bookmarks.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(path, Encoding.UTF8);
await output.WriteAsync(sb.ToString());

await Task.WhenAll(
OutputBookmarkLoc(config, localizations),
Expand All @@ -67,7 +69,7 @@

private static async Task AddTitleToBookmarkScreen(
Title title,
StreamWriter output,
StringBuilder sb,
string holderId,
World world,
Dictionary<string, LocBlock> localizations,
Expand All @@ -88,33 +90,33 @@
}
localizations.Add(holderDescLoc.Id, holderDescLoc);

await output.WriteLineAsync("\tcharacter = {");
sb.AppendLine("\tcharacter = {");

await output.WriteLineAsync($"\t\tname = bm_converted_{holder.Id}");
sb.AppendLine($"\t\tname = bm_converted_{holder.Id}");
var dynastyId = holder.GetDynastyId(config.CK3BookmarkDate);
if (dynastyId is not null) {
await output.WriteLineAsync($"\t\tdynasty = {dynastyId}");
sb.AppendLine($"\t\tdynasty = {dynastyId}");
}
await output.WriteLineAsync("\t\tdynasty_splendor_level = 1");
await output.WriteLineAsync($"\t\ttype = {holder.GetAgeSex(config.CK3BookmarkDate)}");
await output.WriteLineAsync($"\t\thistory_id = {holder.Id}");
await output.WriteLineAsync($"\t\tbirth = {holder.BirthDate}");
await output.WriteLineAsync($"\t\ttitle = {title.Id}");
sb.AppendLine("\t\tdynasty_splendor_level = 1");
sb.AppendLine($"\t\ttype = {holder.GetAgeSex(config.CK3BookmarkDate)}");
sb.AppendLine($"\t\thistory_id = {holder.Id}");
sb.AppendLine($"\t\tbirth = {holder.BirthDate}");
sb.AppendLine($"\t\ttitle = {title.Id}");
var gov = title.GetGovernment(config.CK3BookmarkDate);
if (gov is not null) {
await output.WriteLineAsync($"\t\tgovernment = {gov}");
sb.AppendLine($"\t\tgovernment = {gov}");
}

await output.WriteLineAsync($"\t\tculture = {holder.GetCultureId(config.CK3BookmarkDate)}");
sb.AppendLine($"\t\tculture = {holder.GetCultureId(config.CK3BookmarkDate)}");
var faithId = holder.GetFaithId(config.CK3BookmarkDate);
if (!string.IsNullOrEmpty(faithId)) {
await output.WriteLineAsync($"\t\treligion={faithId}");
sb.AppendLine($"\t\treligion={faithId}");
}
await output.WriteLineAsync("\t\tdifficulty = \"BOOKMARK_CHARACTER_DIFFICULTY_EASY\"");
await WritePosition(output, title, config, provincePositions);
await output.WriteLineAsync("\t\tanimation = personality_rational");
sb.AppendLine("\t\tdifficulty = \"BOOKMARK_CHARACTER_DIFFICULTY_EASY\"");
await WritePosition(sb, title, config, provincePositions);
sb.AppendLine("\t\tanimation = personality_rational");

await output.WriteLineAsync("\t}");
sb.AppendLine("\t}");

string templatePath = holder.GetAgeSex(config.CK3BookmarkDate) switch {
"female" => "blankMod/templates/common/bookmark_portraits/female.txt",
Expand Down Expand Up @@ -143,20 +145,24 @@
private static async Task OutputBookmarkLoc(Configuration config, IDictionary<string, LocBlock> localizations) {
var outputName = config.OutputModName;
var baseLocPath = Path.Combine("output", outputName, "localization");

var sb = new StringBuilder();
foreach (var language in ConverterGlobals.SupportedLanguages) {
var locFilePath = Path.Combine(baseLocPath, language, $"converter_bookmark_l_{language}.yml");
await using var locWriter = FileOpeningHelper.OpenWriteWithRetries(locFilePath, Encoding.UTF8);

await locWriter.WriteLineAsync($"l_{language}:");
sb.AppendLine($"l_{language}:");

// title localization
foreach (var locBlock in localizations.Values) {
await locWriter.WriteLineAsync(locBlock.GetYmlLocLineForLanguage(language));
sb.AppendLine(locBlock.GetYmlLocLineForLanguage(language));
}

var locFilePath = Path.Combine(baseLocPath, language, $"converter_bookmark_l_{language}.yml");
await using var locWriter = FileOpeningHelper.OpenWriteWithRetries(locFilePath, Encoding.UTF8);
await locWriter.WriteAsync(sb.ToString());
sb.Clear();
}
}

private static async Task WritePosition(TextWriter output, Title title, Configuration config, IReadOnlyDictionary<ulong, ProvincePosition> provincePositions) {
private static async Task WritePosition(StringBuilder sb, Title title, Configuration config, IReadOnlyDictionary<ulong, ProvincePosition> provincePositions) {

Check warning on line 165 in ImperatorToCK3/Outputter/BookmarkOutputter.cs

View workflow job for this annotation

GitHub Actions / build (self-hosted, linux)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 165 in ImperatorToCK3/Outputter/BookmarkOutputter.cs

View workflow job for this annotation

GitHub Actions / build (macos-14)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 165 in ImperatorToCK3/Outputter/BookmarkOutputter.cs

View workflow job for this annotation

GitHub Actions / test (macos-14)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 165 in ImperatorToCK3/Outputter/BookmarkOutputter.cs

View workflow job for this annotation

GitHub Actions / build (self-hosted, windows)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 165 in ImperatorToCK3/Outputter/BookmarkOutputter.cs

View workflow job for this annotation

GitHub Actions / test_and_check_coverage

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 165 in ImperatorToCK3/Outputter/BookmarkOutputter.cs

View workflow job for this annotation

GitHub Actions / test (self-hosted, windows)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
int count = 0;
double sumX = 0;
double sumY = 0;
Expand All @@ -175,7 +181,7 @@
const double scale = (double)1080 / 4096;
int finalX = (int)(scale * meanX);
int finalY = 1080 - (int)(scale * meanY);
await output.WriteLineAsync($"\t\tposition = {{ {finalX} {finalY} }}");
sb.AppendLine($"\t\tposition = {{ {finalX} {finalY} }}");
}

private static async Task DrawBookmarkMap(Configuration config, List<Title> playerTitles, World ck3World) {
Expand Down
33 changes: 15 additions & 18 deletions ImperatorToCK3/Outputter/CharacterOutputter.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
using commonItems;
using commonItems.Serialization;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Character = ImperatorToCK3.CK3.Characters.Character;

namespace ImperatorToCK3.Outputter;
public static class CharacterOutputter {
public static async Task OutputCharacter(TextWriter output, Character character, Date conversionDate) {
public static void WriteCharacter(StringBuilder sb, Character character, Date conversionDate) {
// Output ID.
await output.WriteLineAsync($"{character.Id}={{");
sb.AppendLine($"{character.Id}={{");

if (character.Dead) {
// Don't output traits and attributes of dead characters (not needed).
Expand Down Expand Up @@ -37,39 +37,36 @@ public static async Task OutputCharacter(TextWriter output, Character character,
}

// Output history.
await output.WriteAsync(PDXSerializer.Serialize(character.History, "\t"));
sb.Append(PDXSerializer.Serialize(character.History, "\t"));

await OutputPregnancies(output, character);
await OutputPrisoners(output, character, conversionDate);
WritePregnancies(sb, character);
WritePrisoners(sb, character, conversionDate);

await output.WriteLineAsync("}");
sb.AppendLine("}");
}

private static async Task OutputPrisoners(TextWriter output, Character character, Date conversionDate) {
private static void WritePrisoners(StringBuilder stringBuilder, Character character, Date conversionDate) {
if (character.PrisonerIds.Count == 0) {
return;
}

await output.WriteLineAsync($"\t{conversionDate}={{");
stringBuilder.AppendLine($"\t{conversionDate}={{");
foreach (var (id, type) in character.PrisonerIds) {
await output.WriteLineAsync($"\t\timprison={{target = character:{id} type={type}}}");
stringBuilder.AppendLine($"\t\timprison={{target = character:{id} type={type}}}");
}
await output.WriteLineAsync("\t}");
stringBuilder.AppendLine("\t}");
}

/// <summary>
/// Outputs unborn children if pregnancy has lasted at most 3 months in Imperator
/// </summary>
private static async Task OutputPregnancies(
TextWriter output,
Character character
) {
private static void WritePregnancies(StringBuilder stringBuilder, Character character) {
foreach (var pregnancy in character.Pregnancies) {
Date conceptionDate = pregnancy.EstimatedConceptionDate;
string fatherReference = $"character:{pregnancy.FatherId}";
await output.WriteAsync($"\t{conceptionDate}={{ effect={{ ");
await output.WriteAsync($"make_pregnant_no_checks={{ father={fatherReference} {(pregnancy.IsBastard ? "known_bastard=yes " : "")}}} ");
await output.WriteLineAsync("} }");
stringBuilder.Append($"\t{conceptionDate}={{ effect={{ ");
stringBuilder.Append($"make_pregnant_no_checks={{ father={fatherReference} {(pregnancy.IsBastard ? "known_bastard=yes " : "")}}} ");
stringBuilder.AppendLine("} }");
}
}
}
Loading
Loading