You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm trying to use cwtools to programmatically edit Clausewitz files.
Running the tests in CWToolsCSTests, I've noticed that the tests fail to modify the leaves.
//Parse event file
// var parsed = CWTools.Parser.CKParser.parseEventFile("./testevent.txt");
var text = File.ReadAllText("./testevent.txt");
var parsed = CWTools.CSharp.Parsers.ParseScriptFile("testevent.txt", text);
var eventFile = parsed.GetResult();
//"Process" result into nicer format
// var processed = CK2Process.processEventFile(eventFile);
var processed = CWTools.CSharp.Parsers.ProcessStatements("testevent.txt", "./testevent.txt", eventFile);
//Find interesting event
var myEvent = processed.Nodes.FirstOrDefault(x => x.TagText("id") == "test.1");
//Add is_triggered_only = true
var leaf = new Leaf(KeyValueItem.NewKeyValueItem(Key.NewKey("is_triggered_only"), Value.NewBool(true), Operator.Equals), FSharpOption<range>.None);
myEvent.AllChildren.Add(Child.NewLeafC(leaf));
The last line results in a no-op, as the list refuses to be modified and C# won't tell me why. Any ideas on how to circumvent this?
You're right, the interface has changed since then so that snippet doesn't work.
I've updated it so it works again.
Basically, most of the properties return read-only copies as F# has immutable data by default. There are four ways you can actually modify the data structure:
SetTag which will look for the key and replace it, or add it if it isn't there
AllChildren's setter, which takes a C# List and replaces all current children with it
All's setter, which takes an F# List and replaces all current children with it it
`AllArray', which returns a mutable array (but not resizable), or the setter which replaces all current children with it
For "Leaf", both the Key and Value have setters. For "Node", the Key has a setter too.
//Add is_triggered_only = true
var leaf = new Leaf(KeyValueItem.NewKeyValueItem(Key.NewKey("is_triggered_only"), Value.NewBool(true), Operator.Equals), FSharpOption<range>.None);
myEvent.SetTag(leaf.Key, Child.NewLeafC(leaf));
// or
// var newChildren = myEvent.AllChildren;
// newChildren.Add(Leaf.Create(KeyValueItem.NewKeyValueItem(Key.NewKey("is_triggered_only"), Value.NewBool(true), Operator.Equals), range.Zero));
// myEvent.AllChildren = newChildren;
Speaking of serializing, I have another question. I'm trying to modify a Crusader Kings III file programmatically and iteratively, and since the file is quite big I'd like to pickle the parsed data between runs. Is there a way to do so?
varprocessed=CWTools.CSharp.Parsers.ProcessStatements("testevent.txt","./testevent.txt",eventFile);varserialized_processed=JsonSerializer.Serialize(processed);// <--- Fails here: System.NotSupportedException: 'F# discriminated union serialization is not supported. Consider authoring a custom converter for the type.'vardeserialized_processed=JsonSerializer.Deserialize<Node>(serialized_processed);File.AppendAllText("./serialized_node.txt",serialized_processed);
Activity
tboby commentedon Jul 11, 2023
Hi!
You're right, the interface has changed since then so that snippet doesn't work.
I've updated it so it works again.
Basically, most of the properties return read-only copies as F# has immutable data by default. There are four ways you can actually modify the data structure:
SetTagwhich will look for the key and replace it, or add it if it isn't thereAllChildren's setter, which takes a C# List and replaces all current children with itAll's setter, which takes an F# List and replaces all current children with it itFor "Leaf", both the Key and Value have setters. For "Node", the Key has a setter too.
Hope that helps a little!
Nadav-Ruskin commentedon Jul 13, 2023
Thank you for the in-depth answer!
Speaking of serializing, I have another question. I'm trying to modify a Crusader Kings III file programmatically and iteratively, and since the file is quite big I'd like to pickle the parsed data between runs. Is there a way to do so?