|
| 1 | +using commonItems; |
| 2 | +using commonItems.Collections; |
| 3 | +using commonItems.Colors; |
| 4 | +using commonItems.Mods; |
| 5 | +using ImperatorToCK3.CK3.Cultures; |
| 6 | +using ImperatorToCK3.Outputter; |
| 7 | +using System; |
| 8 | +using System.Collections.Generic; |
| 9 | +using System.IO; |
| 10 | +using System.Threading.Tasks; |
| 11 | +using Xunit; |
| 12 | + |
| 13 | +namespace ImperatorToCK3.UnitTests.Outputter; |
| 14 | + |
| 15 | +public class CulturesOutputterTests { |
| 16 | + [Fact] |
| 17 | + public async Task OutputCultures_WritesCulturesGroupedByHeritage_AndOrdersParentsBeforeChildren() { |
| 18 | + var tempDir = CreateTempDir(); |
| 19 | + try { |
| 20 | + var outputModPath = Path.Combine(tempDir, "output"); |
| 21 | + var culturesPath = Path.Combine(outputModPath, "common", "culture", "cultures"); |
| 22 | + Directory.CreateDirectory(culturesPath); |
| 23 | + |
| 24 | + var config = new Configuration(); |
| 25 | + var ck3ModFS = new ModFilesystem(outputModPath, Array.Empty<Mod>()); |
| 26 | + |
| 27 | + var ck3ModFlags = new OrderedDictionary<string, bool>(); |
| 28 | + var pillarCollection = new PillarCollection(new ColorFactory(), ck3ModFlags); |
| 29 | + var heritage = new Pillar("heritage_test", new PillarData { Type = "heritage" }); |
| 30 | + var language = new Pillar("language_test", new PillarData { Type = "language" }); |
| 31 | + pillarCollection.AddOrReplace(heritage); |
| 32 | + pillarCollection.AddOrReplace(language); |
| 33 | + |
| 34 | + var cultureCollection = new CultureCollection(new ColorFactory(), pillarCollection, ck3ModFlags); |
| 35 | + |
| 36 | + var nameList = new NameList("test_namelist", new BufferedReader("male_names = { testname }")); |
| 37 | + |
| 38 | + var parentCultureData = new CultureData { |
| 39 | + Color = new Color(1, 2, 3), |
| 40 | + Heritage = heritage, |
| 41 | + Language = language |
| 42 | + }; |
| 43 | + parentCultureData.NameLists.Add(nameList); |
| 44 | + |
| 45 | + var childCultureData = new CultureData { |
| 46 | + Color = new Color(4, 5, 6), |
| 47 | + Heritage = heritage, |
| 48 | + Language = language |
| 49 | + }; |
| 50 | + childCultureData.ParentCultureIds.Add("parent"); |
| 51 | + childCultureData.NameLists.Add(nameList); |
| 52 | + |
| 53 | + var parentCulture = new Culture("parent", parentCultureData); |
| 54 | + var childCulture = new Culture("child", childCultureData); |
| 55 | + |
| 56 | + // Insert child first to ensure ordering logic is exercised. |
| 57 | + cultureCollection.AddOrReplace(childCulture); |
| 58 | + cultureCollection.AddOrReplace(parentCulture); |
| 59 | + |
| 60 | + await CulturesOutputter.OutputCultures(outputModPath, cultureCollection, ck3ModFS, config, new Date(867, 1, 1)); |
| 61 | + |
| 62 | + var outputFile = Path.Combine(culturesPath, "heritage_test.txt"); |
| 63 | + Assert.True(File.Exists(outputFile)); |
| 64 | + |
| 65 | + var output = await File.ReadAllTextAsync(outputFile, TestContext.Current.CancellationToken); |
| 66 | + var parentIndex = output.IndexOf("parent =", StringComparison.Ordinal); |
| 67 | + var childIndex = output.IndexOf("child =", StringComparison.Ordinal); |
| 68 | + Assert.True(parentIndex >= 0); |
| 69 | + Assert.True(childIndex >= 0); |
| 70 | + Assert.True(parentIndex < childIndex); |
| 71 | + } finally { |
| 72 | + TryDeleteDir(tempDir); |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + [Fact] |
| 77 | + public async Task OutputCultures_OutputsCCUParameters_WhenConfigured() { |
| 78 | + var tempDir = CreateTempDir(); |
| 79 | + try { |
| 80 | + var currentDirectory = Directory.GetCurrentDirectory(); |
| 81 | + var configurablesDir = Path.Combine(currentDirectory, "configurables"); |
| 82 | + Directory.CreateDirectory(configurablesDir); |
| 83 | + await File.WriteAllTextAsync( |
| 84 | + Path.Combine(configurablesDir, "ccu_heritage_parameters.txt"), |
| 85 | + """ |
| 86 | + heritage_families = {} |
| 87 | + heritage_groups = { |
| 88 | + MOD_DEPENDENT = { |
| 89 | + IF tfe = { |
| 90 | + heritage_group_nuragic |
| 91 | + } |
| 92 | + } |
| 93 | + } |
| 94 | + """, |
| 95 | + TestContext.Current.CancellationToken |
| 96 | + ); |
| 97 | + await File.WriteAllTextAsync( |
| 98 | + Path.Combine(configurablesDir, "ccu_language_parameters.txt"), |
| 99 | + """ |
| 100 | + language_families = { |
| 101 | + MOD_DEPENDENT = { |
| 102 | + IF tfe = { |
| 103 | + language_family_kra_dai |
| 104 | + } |
| 105 | + } |
| 106 | + } |
| 107 | + language_branches = {} |
| 108 | + language_groups = { |
| 109 | + MOD_DEPENDENT = { |
| 110 | + IF tfe = { |
| 111 | + language_group_tai |
| 112 | + } |
| 113 | + } |
| 114 | + } |
| 115 | + """, |
| 116 | + TestContext.Current.CancellationToken |
| 117 | + ); |
| 118 | + |
| 119 | + var outputModPath = Path.Combine(tempDir, "output"); |
| 120 | + Directory.CreateDirectory(Path.Combine(outputModPath, "common", "scripted_effects")); |
| 121 | + |
| 122 | + var ck3ModRoot = Path.Combine(tempDir, "ck3mod"); |
| 123 | + var scriptedEffectsDir = Path.Combine(ck3ModRoot, "common", "scripted_effects"); |
| 124 | + Directory.CreateDirectory(scriptedEffectsDir); |
| 125 | + var inputScriptedEffectsPath = Path.Combine(scriptedEffectsDir, "ccu_scripted_effects.txt"); |
| 126 | + await File.WriteAllTextAsync(inputScriptedEffectsPath, |
| 127 | + """ |
| 128 | + ccu_initialize_culture = { |
| 129 | + if = { set_variable = { name = heritage_family value = 1 } } |
| 130 | + if = { set_variable = { name = heritage_group value = 2 } } |
| 131 | + if = { set_variable = { name = language_family value = 3 } } |
| 132 | + if = { set_variable = { name = language_group value = 4 } } |
| 133 | + } |
| 134 | + """, |
| 135 | + TestContext.Current.CancellationToken); |
| 136 | + |
| 137 | + var config = new Configuration(); |
| 138 | + config.DetectSpecificCK3Mods([new Mod("The Fallen Eagle", "", dependencies: [])]); |
| 139 | + |
| 140 | + var ck3ModFS = new ModFilesystem(ck3ModRoot, Array.Empty<Mod>()); |
| 141 | + var emptyPillars = new PillarCollection(new ColorFactory(), new OrderedDictionary<string, bool>()); |
| 142 | + var emptyCultures = new CultureCollection(new ColorFactory(), emptyPillars, new OrderedDictionary<string, bool>()); |
| 143 | + |
| 144 | + await CulturesOutputter.OutputCultures(outputModPath, emptyCultures, ck3ModFS, config, new Date(867, 1, 1)); |
| 145 | + |
| 146 | + var outputScriptedEffectsPath = Path.Combine(outputModPath, "common", "scripted_effects", "ccu_scripted_effects.txt"); |
| 147 | + Assert.True(File.Exists(outputScriptedEffectsPath)); |
| 148 | + |
| 149 | + var output = await File.ReadAllTextAsync(outputScriptedEffectsPath, TestContext.Current.CancellationToken); |
| 150 | + Assert.Contains("has_cultural_parameter = heritage_group_nuragic", output, StringComparison.Ordinal); |
| 151 | + Assert.Contains("has_cultural_parameter = language_family_kra_dai", output, StringComparison.Ordinal); |
| 152 | + Assert.Contains("has_cultural_parameter = language_group_tai", output, StringComparison.Ordinal); |
| 153 | + |
| 154 | + // TFE path uses numeric assignment rather than flag assignment. |
| 155 | + Assert.DoesNotContain("value = flag:language_family_kra_dai", output, StringComparison.Ordinal); |
| 156 | + } finally { |
| 157 | + TryDeleteDir(tempDir); |
| 158 | + } |
| 159 | + } |
| 160 | + |
| 161 | + private static string CreateTempDir() { |
| 162 | + var dir = Path.Combine(Path.GetTempPath(), "ImperatorToCK3_UnitTests", "CulturesOutputter", Guid.NewGuid().ToString("N")); |
| 163 | + Directory.CreateDirectory(dir); |
| 164 | + return dir; |
| 165 | + } |
| 166 | + |
| 167 | + private static void TryDeleteDir(string dir) { |
| 168 | + try { |
| 169 | + if (Directory.Exists(dir)) { |
| 170 | + Directory.Delete(dir, recursive: true); |
| 171 | + } |
| 172 | + } catch { |
| 173 | + // Best-effort cleanup only. |
| 174 | + } |
| 175 | + } |
| 176 | +} |
0 commit comments