From 4e0ca92c77ef2b3a6ac49f0e65e5f47b33593124 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Thu, 21 Aug 2025 22:42:34 +0200 Subject: [PATCH] Add failing test --- processor/surgical_json_test.go | 322 ++++++++++++++++++++++++++++++++ 1 file changed, 322 insertions(+) diff --git a/processor/surgical_json_test.go b/processor/surgical_json_test.go index f64f8ea..a3732f0 100644 --- a/processor/surgical_json_test.go +++ b/processor/surgical_json_test.go @@ -184,6 +184,328 @@ modified = true } } +func TestSurgicalJSONPreservesFormatting2(t *testing.T) { + // Test that surgical editing preserves the original formatting structure + content := ` +{ + "RowStruct": "/Script/Icarus.ProcessorRecipe", + "Defaults": { + "bForceDisableRecipe": false, + "Requirement": { + "RowName": "None", + "DataTableName": "D_Talents" + }, + "SessionRequirement": { + "RowName": "None", + "DataTableName": "D_CharacterFlags" + }, + "CharacterRequirement": { + "RowName": "None", + "DataTableName": "D_CharacterFlags" + }, + "RequiredMillijoules": 2500, + "RecipeSets": [], + "ResourceCostMultipliers": [], + "Inputs": [ + { + "Element": { + "RowName": "None", + "DataTableName": "D_ItemsStatic" + }, + "Count": 1, + "DynamicProperties": [] + } + ], + "Container": { + "Value": "None" + }, + "ResourceInputs": [], + "bSelectOutputItemRandomly": false, + "bContainsContainer": false, + "ItemIconOverride": { + "ItemStaticData": { + "RowName": "None", + "DataTableName": "D_ItemsStatic" + }, + "ItemDynamicData": [], + "ItemCustomStats": [], + "CustomProperties": { + "StaticWorldStats": [], + "StaticWorldHeldStats": [], + "Stats": [], + "Alterations": [], + "LivingItemSlots": [] + }, + "DatabaseGUID": "", + "ItemOwnerLookupId": -1, + "RuntimeTags": { + "GameplayTags": [] + } + }, + "Outputs": [ + { + "Element": { + "RowName": "None", + "DataTableName": "D_ItemTemplate" + }, + "Count": 1, + "DynamicProperties": [] + } + ], + "ResourceOutputs": [], + "Refundable": "Inherit", + "ExperienceMultiplier": 1, + "Audio": { + "RowName": "None", + "DataTableName": "D_CraftingAudioData" + } + }, + "Rows": [ + { + "Name": "Biofuel1", + "RecipeSets": [ + { + "RowName": "Composter", + "DataTableName": "D_RecipeSets" + } + ], + "Inputs": [ + { + "Element": { + "RowName": "Raw_Meat", + "DataTableName": "D_ItemsStatic" + }, + "Count": 2, + "DynamicProperties": [] + }, + { + "Element": { + "RowName": "Tree_Sap", + "DataTableName": "D_ItemsStatic" + }, + "Count": 1, + "DynamicProperties": [] + } + ], + "Outputs": [], + "Audio": { + "RowName": "Composter" + }, + "ResourceOutputs": [ + { + "Type": { + "Value": "Biofuel" + }, + "RequiredUnits": 100 + } + ] + } + ] +} + ` + + expected := ` +{ + "RowStruct": "/Script/Icarus.ProcessorRecipe", + "Defaults": { + "bForceDisableRecipe": false, + "Requirement": { + "RowName": "None", + "DataTableName": "D_Talents" + }, + "SessionRequirement": { + "RowName": "None", + "DataTableName": "D_CharacterFlags" + }, + "CharacterRequirement": { + "RowName": "None", + "DataTableName": "D_CharacterFlags" + }, + "RequiredMillijoules": 2500, + "RecipeSets": [], + "ResourceCostMultipliers": [], + "Inputs": [ + { + "Element": { + "RowName": "None", + "DataTableName": "D_ItemsStatic" + }, + "Count": 1, + "DynamicProperties": [] + } + ], + "Container": { + "Value": "None" + }, + "ResourceInputs": [], + "bSelectOutputItemRandomly": false, + "bContainsContainer": false, + "ItemIconOverride": { + "ItemStaticData": { + "RowName": "None", + "DataTableName": "D_ItemsStatic" + }, + "ItemDynamicData": [], + "ItemCustomStats": [], + "CustomProperties": { + "StaticWorldStats": [], + "StaticWorldHeldStats": [], + "Stats": [], + "Alterations": [], + "LivingItemSlots": [] + }, + "DatabaseGUID": "", + "ItemOwnerLookupId": -1, + "RuntimeTags": { + "GameplayTags": [] + } + }, + "Outputs": [ + { + "Element": { + "RowName": "None", + "DataTableName": "D_ItemTemplate" + }, + "Count": 1, + "DynamicProperties": [] + } + ], + "ResourceOutputs": [], + "Refundable": "Inherit", + "ExperienceMultiplier": 1, + "Audio": { + "RowName": "None", + "DataTableName": "D_CraftingAudioData" + } + }, + "Rows": [ + { + "Name": "Biofuel1", + "RecipeSets": [ + { + "RowName": "Composter", + "DataTableName": "D_RecipeSets" + } + ], + "Inputs": [ + { + "Element": { + "RowName": "Raw_Meat", + "DataTableName": "D_ItemsStatic" + }, + "Count": 2, + "DynamicProperties": [] + } + ], + "Outputs": [], + "Audio": { + "RowName": "Composter" + }, + "ResourceOutputs": [ + { + "Type": { + "Value": "Biofuel" + }, + "RequiredUnits": 100 + } + ] + } + ] +} + ` + + command := utils.ModifyCommand{ + Name: "test", + Lua: ` + -- Define regex patterns for matching recipe names + local function matchesPattern(name, pattern) + local matches = re(pattern, name) + -- Check if matches table has any content (index 0 or 1 should exist if there's a match) + return matches and (matches[0] or matches[1]) + end + + -- Selection pattern for recipes that get multiplied + local selectionPattern = "(?-s)(Bulk_)?(Pistol|Rifle).*?Round.*?|(Carbon|Composite)_Paste.*|(Gold|Copper)_Wire|(Ironw|Copper)_Nail|(Platinum|Steel|Cold_Steel|Titanium)_Ingot|.*?Shotgun_Shell.*?|.*_Arrow|.*_Bolt|.*_Fertilizer_?\\d*|.*_Grenade|.*_Pill|.*_Tonic|Aluminum|Ammo_Casing|Animal_Fat|Carbon_Fiber|Composites|Concrete_Mix|Cured_Leather_?\\d?|Electronics|Epoxy_?\\d?|Glass\\d?|Gunpowder\\w*|Health_.*|Titanium_Plate|Organic_Resin|Platinum_Sheath|Refined_[a-zA-Z]+|Rope|Shotgun_Casing|Steel_Bloom\\d?|Tree_Sap\\w*" + + -- Ingot pattern for recipes that get count set to 1 + local ingotPattern = "(?-s)(Platinum|Steel|Cold_Steel|Titanium)_Ingot|Aluminum|Refined_[a-zA-Z]+|Glass\\d?" + + local factor = 16 + local bonus = 0.5 + + for _, row in ipairs(data.Rows) do + local recipeName = row.Name + + -- Special case: Biofuel recipes - remove Tree_Sap input + if string.find(recipeName, "Biofuel") then + if row.Inputs then + for i = #row.Inputs, 1, -1 do + local input = row.Inputs[i] + if input.Element and input.Element.RowName and string.find(input.Element.RowName, "Tree_Sap") then + table.remove(row.Inputs, i) + print("Removing input 'Tree_Sap' from processor recipe '" .. recipeName .. "'") + end + end + end + end + + -- Ingot recipes: set input and output counts to 1 + if matchesPattern(recipeName, ingotPattern) then + if row.Inputs then + for _, input in ipairs(row.Inputs) do + input.Count = 1 + end + end + if row.Outputs then + for _, output in ipairs(row.Outputs) do + output.Count = 1 + end + end + end + + -- Selected recipes: multiply inputs by factor, outputs by factor * (1 + bonus) + if matchesPattern(recipeName, selectionPattern) then + if row.Inputs then + for _, input in ipairs(row.Inputs) do + local oldCount = input.Count + input.Count = input.Count * factor + print("Recipe " .. recipeName .. " Input.Count: " .. oldCount .. " -> " .. input.Count) + end + end + + if row.Outputs then + for _, output in ipairs(row.Outputs) do + local oldCount = output.Count + output.Count = math.floor(output.Count * factor * (1 + bonus)) + print("Recipe " .. recipeName .. " Output.Count: " .. oldCount .. " -> " .. output.Count) + end + end + end + end +`, + } + + commands, err := ProcessJSON(content, command, "test.json") + if err != nil { + t.Fatalf("ProcessJSON failed: %v", err) + } + + if len(commands) == 0 { + t.Fatal("Expected at least one command") + } + + // Apply the commands + result := content + for _, cmd := range commands { + result = result[:cmd.From] + cmd.With + result[cmd.To:] + } + + // Check that the result matches expected (preserves formatting and changes weight) + if result != expected { + t.Errorf("Expected:\n%s\n\nGot:\n%s", expected, result) + } +} + func TestRetardedJSONEditing(t *testing.T) { original := `{ "RowStruct": "/Script/Icarus.ItemableData",