diff --git a/Elwig/Helpers/Billing/BillingData.cs b/Elwig/Helpers/Billing/BillingData.cs index 0073b42..4230287 100644 --- a/Elwig/Helpers/Billing/BillingData.cs +++ b/Elwig/Helpers/Billing/BillingData.cs @@ -252,11 +252,11 @@ namespace Elwig.Helpers.Billing { return curve; } - protected static void CollapsePaymentData(JsonObject data, IEnumerable vaributes, bool useDefault = true) { + protected static (Dictionary>, Dictionary>) GetReverseKeys(JsonObject data, bool strict = true) { Dictionary> rev1 = []; Dictionary> rev2 = []; foreach (var (k, v) in data) { - if (k == "default" || k.StartsWith('/') || !k.Contains('/') || v is not JsonValue val) { + if (k == "default" || (strict && (k.StartsWith('/') || !k.Contains('/'))) || v is not JsonValue val) { continue; } else if (val.TryGetValue(out var dec)) { rev2[dec] = rev2.GetValueOrDefault(dec) ?? []; @@ -266,6 +266,11 @@ namespace Elwig.Helpers.Billing { rev1[cur].Add(k); } } + return (rev1, rev2); + } + + protected static void CollapsePaymentData(JsonObject data, IEnumerable vaributes, bool useDefault = true) { + var (rev1, rev2) = GetReverseKeys(data); if (!data.ContainsKey("default")) { foreach (var (v, ks) in rev1) { if ((ks.Count >= vaributes.Count() * 0.5 && useDefault) || ks.Count == vaributes.Count()) { @@ -322,6 +327,32 @@ namespace Elwig.Helpers.Billing { data.Add(k.Replace("/-", "-"), val); } } + + (rev1, rev2) = GetReverseKeys(data, false); + var keyVaributes = data + .Select(e => e.Key.Split('-')[0]) + .Where(e => e.Length > 0 && e != "default") + .Distinct() + .ToList(); + foreach (var idx in keyVaributes) { + var len = data.Count(e => e.Key == idx || (e.Key.Length > idx.Length && e.Key.StartsWith(idx) && e.Key[idx.Length] == '-')); + foreach (var (v, ks) in rev1) { + var myKs = ks.Where(k => k == idx || (k.Length > idx.Length && k.StartsWith(idx) && k[idx.Length] == '-' && !data.ContainsKey(k[idx.Length..]))).ToList(); + if (myKs.Count == len) { + foreach (var k in myKs) { + if (k != idx) data.Remove(k); + } + } + } + foreach (var (v, ks) in rev2) { + var myKs = ks.Where(k => k == idx || (k.Length > idx.Length && k.StartsWith(idx) && k[idx.Length] == '-' && !data.ContainsKey(k[idx.Length..]))).ToList(); + if (myKs.Count == len) { + foreach (var k in myKs) { + if (k != idx) data.Remove(k); + } + } + } + } } public static JsonObject FromGraphEntries( diff --git a/Tests/HelperTests/BillingDataTest.cs b/Tests/HelperTests/BillingDataTest.cs index 954ee66..bf987e6 100644 --- a/Tests/HelperTests/BillingDataTest.cs +++ b/Tests/HelperTests/BillingDataTest.cs @@ -556,7 +556,7 @@ namespace Tests.HelperTests { } [Test] - public void TestWrite_06_Cultivation() { + public void TestWrite_06_Cultivation_1() { List entries = [ new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() { [73] = 0.5m, @@ -604,7 +604,84 @@ namespace Tests.HelperTests { } [Test] - public void TestWrite_07_AttributeAndCultivation() { + public void TestWrite_07_Cultivation_2() { + List entries = [ + new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() { + [73] = 0.6m, + [84] = 1.0m + }, null), GetSelection(["GV/-", "GV/-B"])), + new GraphEntry(2, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() { + [73] = 0.75m, + }, null), GetSelection(["ZW/-", "ZW/-B"])), + new GraphEntry(2, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() { + [73] = 0.8m, + }, null), GetSelection(["BP/-", "BP/-B"])), + ]; + var data = BillingData.FromGraphEntries(entries); + Assert.That(data.ToJsonString(JsonOpts), Is.EqualTo(""" + { + "mode": "elwig", + "version": 1, + "payment": { + "GV": "curve:1", + "ZW": 0.75, + "BP": 0.8 + }, + "curves": [ + { + "id": 1, + "mode": "oe", + "data": { + "73oe": 0.6, + "84oe": 1 + } + } + ] + } + """)); + } + + [Test] + public void TestWrite_08_Cultivation_3() { + List entries = [ + new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() { + [73] = 0.6m, + [84] = 1.0m + }, null), GetSelection(["GV/-", "GV/-B"])), + new GraphEntry(2, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() { + [73] = 0.75m, + }, null), GetSelection(["BP/-B", "ZW/-B", "FV/-B"])), + new GraphEntry(2, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() { + [73] = 0.8m, + }, null), GetSelection(["BP/-", "ZW/-", "FV/-", "WR/-", "BL/-"])), + ]; + var data = BillingData.FromGraphEntries(entries); + Assert.That(data.ToJsonString(JsonOpts), Is.EqualTo(""" + { + "mode": "elwig", + "version": 1, + "payment": { + "default": 0.8, + "GV": "curve:1", + "GV-B": "curve:1", + "-B": 0.75 + }, + "curves": [ + { + "id": 1, + "mode": "oe", + "data": { + "73oe": 0.6, + "84oe": 1 + } + } + ] + } + """)); + } + + [Test] + public void TestWrite_09_AttributeAndCultivation() { List entries = [ new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() { [73] = 0.75m,