Decision Capture
Attaches transition capture to a model that is already built, and takes it back off again (§4.8.2).
The problem it solves
Capture used to be declarable only inside decisionElement { … }, which meant that recording a model's decisions required editing the model. That is the wrong place for the decision: whether this run is being recorded is a property of the run, not of the subsystem being simulated. A user with somebody else's model, a script sweeping ten configurations of which two are worth recording, or a tool layer offering a "record decisions" checkbox all need to attach from outside — and none of them can edit the model element.
The shape is the animation layer's
ksl.animation.AnimationCapture is the house pattern for exactly this: construct it just before a run, its init installs everything and records an undo action per installation, and close runs every undo. This is the same object for decisions, and deliberately smaller — animation has to compose filter sinks and walk every element kind in the model; this has one kind to find and one thing to attach.
val model = Model("Inventory")
val room = StockRoom(model, "Room") // a model that never mentions capture
model.numberOfReplications = 30
DecisionCapture.toDirectory(model, outDir).use { model.simulate() }What it does not do
It does not close the sinks it attached — unless it made them itself, which is what toDirectory and rolling do. A sink handed to the DecisionCapture constructor by the caller is the caller's, following ksl.observers.ResponseTrace; close detaches it and stops there.
It cannot be constructed or closed while the model is running. attachTransitionSink refuses that, and this does nothing to route around it: a trajectory that begins mid-episode has no predecessor for its first row.
Parameters
the model whose decision elements are to be captured
chooses a sink for each decision element; return null to skip that element, which is how a caller records two of a model's five decision elements
Constructors
Properties
The elements this capture attached to, in the order it found them.
The sinks it attached, aligned with capturedElements.