///|
test "sample an explicit concurrent scenario" {
let view = @bpmn.Bpmn::new(
"P",
[@bpmn.Node::new("A", Task), @bpmn.Node::new("B", Task)],
[
@bpmn.Flow::new("AB", "A", "B", condition="amount > 0"),
@bpmn.Flow::new("BA", "B", "A"),
],
)
let catalog = @animation.Catalog::bpmn(view).catalog.unwrap()
let a = catalog.flow("AB").unwrap().key
let b = catalog.flow("BA").unwrap().key
let motion = @animation.Motion::serial([
@animation.Motion::parallel([Step(a, 1000L), Step(b, 500L)]),
Step(a, 1000L),
])
let plan = @animation.PlaybackPlan::scenario(catalog, motion).plan.unwrap()
assert_eq(plan.duration_ms, 2000L)
assert_eq(plan.sample_at(250L).active.length(), 2)
assert_eq(plan.sample_at(1000L).active[0].ordinal, 2)
assert_true(plan.sample_at(2000L).finished)
assert_eq(
catalog.flow("AB").unwrap().flow.unwrap().condition,
Some("amount > 0"),
)
}///|
test "choose a bounded sequence loop" {
let message = @sequence.Event::Message(
@sequence.Message::new("A", "A", "retry"),
)
let sequence = @sequence.Sequence::new([@sequence.Participant::new("A")], [
Frame(
@sequence.Frame::new(
Loop,
@sequence.Section::new([message], label="retry condition"),
),
),
])
let catalog = @animation.Catalog::sequence(sequence, view_id="Retry").catalog.unwrap()
let selection = @animation.Selection::new(
catalog.frames[0].key,
Repetitions(2),
)
let plan = @animation.PlaybackPlan::sequence(catalog, selections=[selection]).plan.unwrap()
assert_eq(plan.steps.length(), 2)
assert_eq(plan.steps[0].occurrence.path, [0, 0, 0])
assert_eq(plan.steps[0].occurrence.key, plan.steps[1].occurrence.key)
assert_eq(plan.steps[1].ordinal, 1)
}///|
test "play a bidirectional swimlane return" {
let view = @swimlane.Swimlane::new(
"Review",
[@swimlane.Node::new("A"), @swimlane.Node::new("B")],
[@swimlane.Connection::new("AB", "A", "B", source_marker=Arrow)],
)
let catalog = @animation.Catalog::swimlane(view).catalog.unwrap()
guard catalog.graph.route("B", "A") is Found(route) else {
fail("missing return")
}
assert_eq(route.reversed, [true])
let plan = @animation.PlaybackPlan::route(catalog, route).plan.unwrap()
assert_true(plan.sample_at(250L).active[0].reversed)
}pub struct Catalog {
view_id : String
source : Diagram
occurrences : ReadOnlyArray[Occurrence]
frames : ReadOnlyArray[FrameInfo]
controls : ReadOnlyArray[Control]
graph : Graph
// private fields
}pub struct FrameInfo {
key : String
path : ReadOnlyArray[Int]
kind : FrameKind
sections : ReadOnlyArray[SectionInfo]
} derive(Eq, Debug)pub struct Occurrence {
key : String
index : Int
kind : OccurrenceKind
path : ReadOnlyArray[Int]
source : SourceIdentity?
flow : Flow?
message : Message?
swimlane_connection : Connection?
} derive(Eq, Debug)pub(all) enum OccurrenceKind {
Bpmn(ConnectionKind)
SequenceMessage
Swimlane(FlowDirection)
} derive(Eq, Debug)pub struct PlaybackPlan {
view_id : String
mode : PlaybackMode
duration_ms : Int64
steps : ReadOnlyArray[ScheduledStep]
// private fields
} derive(Eq, Debug)fn PlaybackPlan::illustrative(catalog : Catalog, duration_ms? : Int64, kinds? : ArrayView[ConnectionKind], limits? : Limits) -> PlanResultfn PlaybackPlan::route(catalog : Catalog, route : Route, duration_ms? : Int64, limits? : Limits) -> PlanResultfn PlaybackPlan::sequence(catalog : Catalog, selections? : ArrayView[Selection], duration_ms? : Int64, limits? : Limits) -> PlanResultpub(all) enum ReachabilityResult {
Complete(ReadOnlyArray[GraphNode])
Failed(QueryFailure)
} derive(Eq, Debug)pub struct ScheduledStep {
ordinal : Int
occurrence : Occurrence
start_ms : Int64
duration_ms : Int64
concurrent_groups : ReadOnlyArray[Int]
reversed : Bool
} derive(Eq, Debug)