dal-engine-core-js-lib-dev 0.0.0 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  import Base from "../Base";
2
+ import MissingAttributes from "../Errors/MissingAttributes";
2
3
  import ENGINE_TYPES from "../TYPES";
3
4
  import Participant from "./Participant";
4
5
  /**
@@ -14,16 +15,34 @@ class Behavior extends Base {
14
15
  super();
15
16
  this.type = ENGINE_TYPES.BEHAVIOR;
16
17
  this.participants = [];
18
+ this.abstractionIds = [];
17
19
  this.invalidWorldState = false;
18
- if (typeof args === "object" && args !== null) {
19
- if (Object.hasOwn(args, "uid")) {
20
- this.loadBehaviorFromJSON(args);
21
- } else {
22
- this.name = args.name;
23
- }
20
+ if (typeof args === "object" && Object.hasOwn(args, "uid")) {
21
+ this.loadBehaviorFromJSON(args);
22
+ } else {
23
+ this.loadArgs(args);
24
24
  }
25
25
  }
26
26
 
27
+ /**
28
+ * Loads the provided arguments.
29
+ * @throws {MissingAttributes} Thrown when required attr is not present.
30
+ * @param {Object} args
31
+ */
32
+ loadArgs (args) {
33
+ const expectedAttributes = ["name"];
34
+ if (typeof args !== "object" || args === null || Array.isArray(args)) {
35
+ // Not an object, so all attributes are missing.
36
+ throw new MissingAttributes("Behavior", expectedAttributes);
37
+ }
38
+ expectedAttributes.forEach((attr) => {
39
+ if (!(attr in args)) {
40
+ throw new MissingAttributes("Behavior", attr);
41
+ }
42
+ this[attr] = args[attr];
43
+ });
44
+ }
45
+
27
46
  /**
28
47
  * Loads the behavior from a JSON object.
29
48
  * @param {Object} behaviorJSON
@@ -54,17 +73,21 @@ class Behavior extends Base {
54
73
  * @param {*} value
55
74
  */
56
75
  setParticipantValue (participantName, value) {
57
- for (let i = 0; i < this.participants.length; i++) {
58
- const participant = this.participants[i];
59
- if (participant.name === participantName) {
60
- participant.value = value;
61
- const violation = participant.enforceInvariants();
62
- if (violation) {
63
- this.invalidWorldState = true;
64
- }
65
- }
76
+ const participant = this.participants.find(obj => obj.name === participantName);
77
+ participant.value = value;
78
+ const violation = participant.enforceInvariants();
79
+ if (violation) {
80
+ this.invalidWorldState = true;
66
81
  }
67
82
  }
83
+
84
+ /**
85
+ * Maps the abstraction id from execution to the behavior.
86
+ * @param {String} abstractionId
87
+ */
88
+ addMapping (abstractionId) {
89
+ this.abstractionIds.push(abstractionId);
90
+ }
68
91
  }
69
92
 
70
93
  export default Behavior;
@@ -1,5 +1,7 @@
1
1
  import Base from "../Base";
2
+ import MissingAttributes from "../Errors/MissingAttributes";
2
3
  import ENGINE_TYPES from "../TYPES";
4
+
3
5
  /**
4
6
  * Class representing a Invariant in the design.
5
7
  */
@@ -12,17 +14,35 @@ class Invariant extends Base {
12
14
  constructor (args) {
13
15
  super();
14
16
  this.type = ENGINE_TYPES.INVARIANT;
15
- this.invariantViolated = false
16
- if (typeof args === "object" && args !== null) {
17
- if (Object.hasOwn(args, "uid")) {
18
- this.loadInvariantFromJSON(args);
19
- } else {
20
- this.name = args.name;
21
- this.rule = args.rule;
22
- }
17
+ this.invariantViolated = false;
18
+ this.invariantType = null;
19
+ this.traceId = null;
20
+ if (typeof args === "object" && Object.hasOwn(args, "uid")) {
21
+ this.loadInvariantFromJSON(args);
22
+ } else {
23
+ this.loadArgs(args);
23
24
  }
24
25
  }
25
26
 
27
+ /**
28
+ * Loads the provided arguments.
29
+ * @throws {MissingAttributes} Thrown when required attr is not present.
30
+ * @param {Object} args
31
+ */
32
+ loadArgs (args) {
33
+ const expectedAttributes = ["name", "rule"];
34
+ if (typeof args !== "object" || args === null || Array.isArray(args)) {
35
+ // Not an object, so all attributes are missing.
36
+ throw new MissingAttributes("Invariant", expectedAttributes);
37
+ }
38
+ expectedAttributes.forEach((attr) => {
39
+ if (!(attr in args)) {
40
+ throw new MissingAttributes("Invariant", attr);
41
+ }
42
+ this[attr] = args[attr];
43
+ });
44
+ }
45
+
26
46
  /**
27
47
  * Loads the participant from a JSON object.
28
48
  * @param {Object} invariantJSON
@@ -56,7 +76,6 @@ class Invariant extends Base {
56
76
  enforceMinLength (value) {
57
77
  if ("keys" in this.rule) {
58
78
  for (let i = 0; i < this.rule["keys"].length; i++) {
59
- console.log(this.rule["keys"][i], value)
60
79
  value = value[this.rule["keys"][i]];
61
80
  }
62
81
  };
@@ -64,6 +83,46 @@ class Invariant extends Base {
64
83
  this.invariantViolated = true;
65
84
  }
66
85
  }
86
+
87
+
88
+ /**
89
+ * Sets the invariant type.
90
+ *
91
+ * The two types of invariants are: Intrinsic and Substrate
92
+ *
93
+ * Substrate invariants are learnt by the design from the
94
+ * environment.
95
+ *
96
+ * Intrinsic invariants are arrived at naturally from the
97
+ * designs control flow, data dependencies and semantic assumptions.
98
+ *
99
+ * @param {String} invariantType
100
+ */
101
+ setInvariantType (invariantType) {
102
+ // TODO: Add validation for invariantType.
103
+ this.invariantType = invariantType;
104
+ }
105
+
106
+ /**
107
+ * This function adds the trace id which can be used for
108
+ * automated testing.
109
+ *
110
+ * Substrate invariants correspond to a trace that represents
111
+ * an environment that reveals a limitation of the substrate,
112
+ * thus motivating the invariant. It is also the environment
113
+ * in which an implementation can prove that it respects this
114
+ * invariant.
115
+ *
116
+ * Intrisinc invariants correspond to a trace that represents
117
+ * a factory default environment that enables the implementation
118
+ * to prove that it respects the invariant.
119
+ *
120
+ * @param {String} traceId ID of trace used for automated testing.
121
+ */
122
+ setTraceId (traceId) {
123
+ // TODO: Add validation for traceId.
124
+ this.traceId = traceId;
125
+ }
67
126
  }
68
127
 
69
128
  export default Invariant;
@@ -1,6 +1,8 @@
1
1
  import Base from "../Base";
2
+ import MissingAttributes from "../Errors/MissingAttributes";
2
3
  import ENGINE_TYPES from "../TYPES";
3
4
  import Invariant from "./Invariant";
5
+
4
6
  /**
5
7
  * Class representing a participant in the design.
6
8
  */
@@ -14,16 +16,34 @@ class Participant extends Base {
14
16
  super();
15
17
  this.type = ENGINE_TYPES.INVARIANT;
16
18
  this.invariants = [];
19
+ this.abstractionId = null;
17
20
  this.invariantViolated = false;
18
- if (typeof args === "object" && args !== null) {
19
- if (Object.hasOwn(args, "uid")) {
20
- this.loadParticipantFromJSON(args);
21
- } else {
22
- this.name = args.name;
23
- }
21
+ if (typeof args === "object" && Object.hasOwn(args, "uid")) {
22
+ this.loadParticipantFromJSON(args);
23
+ } else {
24
+ this.loadArgs(args);
24
25
  }
25
26
  }
26
27
 
28
+ /**
29
+ * Loads the provided arguments.
30
+ * @throws {MissingAttributes} Thrown when required attr is not present.
31
+ * @param {Object} args
32
+ */
33
+ loadArgs (args) {
34
+ const expectedAttributes = ["name"];
35
+ if (typeof args !== "object" || args === null || Array.isArray(args)) {
36
+ // Not an object, so all attributes are missing.
37
+ throw new MissingAttributes("Participant", expectedAttributes);
38
+ }
39
+ expectedAttributes.forEach((attr) => {
40
+ if (!(attr in args)) {
41
+ throw new MissingAttributes("Participant", attr);
42
+ }
43
+ this[attr] = args[attr];
44
+ });
45
+ }
46
+
27
47
  /**
28
48
  * Loads the participant from a JSON object.
29
49
  * @param {Object} participantJSON
@@ -71,6 +91,18 @@ class Participant extends Base {
71
91
  }
72
92
  return this.invariantViolated;
73
93
  }
94
+
95
+ /**
96
+ * Map the abstraction ID from the execution to the participant.
97
+ *
98
+ * This abstraction id will be used to assign a value to the
99
+ * participant from the execution using the logged abstraction id.
100
+ *
101
+ * @param {String} abstractionId
102
+ */
103
+ mapAbstraction (abstractionId) {
104
+ this.abstractionId = abstractionId;
105
+ }
74
106
  }
75
107
 
76
108
  export default Participant;
@@ -4,6 +4,7 @@ import {describe, expect, it} from "vitest";
4
4
 
5
5
  import {DALEngine} from "../src/DALEngine.js";
6
6
  import InvalidTransitionError from "../src/Errors/InvalidTransitionError.js";
7
+ import MissingAttributes from "../src/Errors/MissingAttributes.js";
7
8
  import UnknownBehaviorError from "../src/Errors/UnknownBehaviorError.js";
8
9
  import ENGINE_TYPES from "../src/TYPES.js";
9
10
 
@@ -13,41 +14,46 @@ describe("DALEngine", () => {
13
14
  expect(dalInstance.name).toBe("Library Manager");
14
15
  });
15
16
 
16
- it("adds node to graph", () => {
17
+ it(" throws on missing attributes", () => {
18
+ expect(() => {new DALEngine()}).toThrow(MissingAttributes);
17
19
  const d = new DALEngine({name: "Library Manager"});
18
- const behavior1 = d.createBehavior({name: "AcceptBookFromUser"});
19
- const behavior2 = d.createBehavior({name: "AddBookToBasket"});
20
- const goToBehaviors = [behavior2];
20
+ expect(() => {d.createBehavior()}).toThrow(MissingAttributes);
21
+ expect(() => {d.createBehavior({})}).toThrow(MissingAttributes);
22
+ expect(() => {d.createBehavior({"rule": "adsf"})}).toThrow(MissingAttributes);
23
+ expect(() => {d.createInvariant({"name": "asdf"})}).toThrow(MissingAttributes);
24
+ expect(() => {d.createParticipant()}).toThrow(MissingAttributes);
25
+ expect(() => {d.createParticipant({})}).toThrow(MissingAttributes);
26
+ });
21
27
 
22
- const node = d.graph.addNode(behavior1, goToBehaviors)
28
+ it("adds node to graph", () => {
29
+ const d = new DALEngine({name: "Library Manager"});
30
+ const goToBehaviorIds = ["AddBookToBasket"];
31
+ const node = d.addNode("AcceptBookFromUser", goToBehaviorIds)
23
32
 
24
33
  const nodeType = node.type;
25
34
  expect(nodeType).toBe(ENGINE_TYPES.GRAPH_NODE);
26
- expect(node.behavior).toStrictEqual(behavior1);
27
- expect(node.goToBehaviors).toStrictEqual([behavior2]);
28
-
29
- const foundNode = d.graph.findNode("AcceptBookFromUser");
30
- expect(foundNode).toStrictEqual(node);
35
+ expect(node.behavior.name).toStrictEqual("AcceptBookFromUser");
36
+ expect(node.goToBehaviorsIds).toStrictEqual(goToBehaviorIds);
31
37
  });
32
38
 
33
39
  it("find node that was added using behavior name", () => {
34
40
  const d = new DALEngine({name: "Library Manager"});
35
- const behavior1 = d.createBehavior({name: "AcceptBookFromUser"});
36
- const behavior2 = d.createBehavior({name: "AddBookToBasket"});
37
- const node = d.graph.addNode(behavior1, [behavior2])
41
+ const node = d.addNode("AcceptBookFromUser", []);
38
42
 
39
- const foundNode = d.graph.findNode("AcceptBookFromUser");
43
+ expect(() => {d.getNode("AcceptBookFrmUser")}).toThrow(UnknownBehaviorError);
44
+
45
+ const foundNode = d.getNode("AcceptBookFromUser");
40
46
  expect(foundNode).toStrictEqual(node);
41
47
  });
42
48
 
43
49
  it("find node and check if observed behavior is valid transition", () => {
44
50
  const d = new DALEngine({name: "Library Manager"});
45
- const behavior1 = d.createBehavior({name: "AcceptBookFromUser"});
46
- const behavior2 = d.createBehavior({name: "AddBookToBasket"});
47
- const behavior3 = d.createBehavior({name: "AnotherBehavior"});
48
- d.graph.addNode(behavior1, [behavior2, behavior3])
49
- d.graph.addNode(behavior2, [])
50
- d.graph.addNode(behavior3, [])
51
+ const node1 = d.addNode("AcceptBookFromUser", []);
52
+ const node2 = d.addNode("AddBookToBasket", []);
53
+ d.addNode("AnotherBehavior", []);
54
+
55
+ node1.addGoToBehavior("AddBookToBasket");
56
+ node2.addGoToBehavior("AnotherBehavior");
51
57
 
52
58
  // Misspell behavior name to trigger unknown behavior error
53
59
  expect(() => {
@@ -55,20 +61,20 @@ describe("DALEngine", () => {
55
61
  }).toThrow(UnknownBehaviorError);
56
62
 
57
63
  d.graph.setCurrentBehavior("AcceptBookFromUser");
58
- expect(d.graph.currentNode.behavior).toBe(behavior1);
64
+ expect(d.graph.currentNode).toBe(node1);
59
65
 
60
66
  d.graph.goToBehavior("AddBookToBasket")
61
- expect(d.graph.currentNode.behavior).toBe(behavior2);
67
+ expect(d.graph.currentNode).toBe(node2);
62
68
 
63
69
  // Reset current behavior so transition is valid
64
70
  d.graph.setCurrentBehavior("AcceptBookFromUser");
65
- d.graph.goToBehavior("AnotherBehavior")
66
- expect(d.graph.currentNode.behavior).toBe(behavior3);
71
+ d.graph.goToBehavior("AddBookToBasket")
72
+ expect(d.graph.currentNode).toBe(node2);
67
73
 
68
74
  // Raises error because current behavior is "AnotherBehavior"
69
75
  // and it does not transition to itself.
70
76
  expect(() => {
71
- d.graph.goToBehavior("AnotherBehavior")
77
+ d.graph.goToBehavior("AddBookToBasket")
72
78
  }).toThrow(InvalidTransitionError);
73
79
 
74
80
  // Reset the current behavior and then go to a behavior
@@ -82,7 +88,16 @@ describe("DALEngine", () => {
82
88
  it("add invariant to participant", () => {
83
89
  const d = new DALEngine({name: "Library Manager"});
84
90
  const book = d.createParticipant({name: "book"});
85
- const invariant = d.createInvariant({name: "minLength"});
91
+ const invariant = d.createInvariant(
92
+ {
93
+ "name": "MinLengthConstraint",
94
+ "rule": {
95
+ "type": "minLength",
96
+ "keys": ["value", "name"],
97
+ "value": 1,
98
+ },
99
+ }
100
+ );
86
101
 
87
102
  book.addInvariant(invariant);
88
103
 
@@ -105,13 +120,15 @@ describe("DALEngine", () => {
105
120
  );
106
121
  book.addInvariant(invariant);
107
122
 
108
- const behavior1 = d.createBehavior({name: "AcceptBookFromUser"});
109
- behavior1.addParticpant(book);
110
- const behavior2 = d.createBehavior({name: "AddBookToBasket"});
111
- const behavior3 = d.createBehavior({name: "AnotherBehavior"});
112
- d.graph.addNode(behavior1, [behavior2, behavior3]);
113
- d.graph.addNode(behavior2, []);
114
- d.graph.addNode(behavior3, []);
123
+
124
+ const node1 = d.addNode("AcceptBookFromUser", []);
125
+ d.addNode("AddBookToBasket", []);
126
+ d.addNode("AnotherBehavior", []);
127
+
128
+ node1.addGoToBehavior("AddBookToBasket");
129
+ node1.addGoToBehavior("AnotherBehavior");
130
+
131
+ node1.behavior.addParticpant(book);
115
132
 
116
133
  const filePath = resolve(__dirname, "./temp/inspectSerializeTemp.json")
117
134
  await writeFile(filePath, d.serialize())
@@ -3,8 +3,17 @@ import {resolve} from "path"
3
3
  import {describe, expect, it} from "vitest";
4
4
 
5
5
  import {DALEngine} from "../src/DALEngine.js";
6
+ import MissingAttributes from "../src/Errors/MissingAttributes.js";
6
7
 
7
8
  describe("invariantTests", () => {
9
+
10
+ it("invariant throws on missing attributes", () => {
11
+ let d = new DALEngine({name: "Library Manager"});
12
+ expect(() => {d.createInvariant({"name": "asdf"})}).toThrow(MissingAttributes);
13
+ expect(() => {d.createInvariant({})}).toThrow(MissingAttributes);
14
+ expect(() => {d.createInvariant()}).toThrow(MissingAttributes);
15
+ });
16
+
8
17
  it("test invariant directly through participants", async () => {
9
18
  let d = new DALEngine({name: "Library Manager"});
10
19
 
@@ -63,28 +72,27 @@ describe("invariantTests", () => {
63
72
  ));
64
73
 
65
74
  // Create behavior and participant
66
- const behavior1 = d.createBehavior({name: "AcceptBookFromUser"});
67
- behavior1.addParticpant(book);
68
- d.graph.addNode(behavior1, []);
75
+ const node1 = d.addNode("AcceptBookFromUser", []);
76
+ node1.behavior.addParticpant(book);
69
77
 
70
78
  // Add value that respects invariant and expect valid world state
71
- behavior1.setParticipantValue("book", {
79
+ node1.behavior.setParticipantValue("book", {
72
80
  "uid": 1,
73
81
  "value": {
74
82
  "name": "Harry Potter and Chamber of Secrets",
75
83
  },
76
84
  })
77
- expect(behavior1.invalidWorldState).toBe(false);
85
+ expect(node1.behavior.invalidWorldState).toBe(false);
78
86
 
79
87
 
80
88
  // Add value that violates invariant and expect invalid world state
81
- behavior1.setParticipantValue("book", {
89
+ node1.behavior.setParticipantValue("book", {
82
90
  "uid": 1,
83
91
  "value": {
84
92
  "name": "",
85
93
  },
86
94
  })
87
- expect(behavior1.invalidWorldState).toBe(true);
95
+ expect(node1.behavior.invalidWorldState).toBe(true);
88
96
 
89
97
  // Write to file for inspection
90
98
  const filePath = resolve(__dirname, "./temp/invariantBehaviorTemp.json")
@@ -0,0 +1,31 @@
1
+ import {readFile, unlink, writeFile} from "fs/promises"
2
+ import {resolve} from "path"
3
+ import {describe, expect, it} from "vitest";
4
+
5
+ import {DALEngine} from "../src/DALEngine.js";
6
+
7
+ describe("SimpleDesignTest", () => {
8
+
9
+ it("create simple design", async () => {
10
+ const d = new DALEngine({name: "Library Manager"});
11
+ d.addNode("AcceptChoiceToAddBookToBasket", ["AcceptBookFromUser"]);
12
+ d.addNode("AcceptBookFromUser", ["AddBookToBasket"]);
13
+ d.addNode("AddBookToBasket", []);
14
+ d.addNode("AcceptChoiceToAuditLibrary", ["GenerateAuditReport"]);
15
+ d.addNode("GenerateAuditReport", ["HandAuditToUser"]);
16
+ d.addNode("HandAuditToUser", []);
17
+
18
+ d.addNode("AcceptChoiceToPlaceBooksOnShelf", ["GetBookFromBasket"]);
19
+ d.addNode("GetBookFromBasket", ["GetFirstLetterOfBookName"]);
20
+ d.addNode("GetFirstLetterOfBookName", ["CreateSlotOnBookShelf", "AddBookToShelf"]);
21
+ d.addNode("CreateSlotOnBookShelf", ["AddBookToShelf"]);
22
+ d.addNode("AddBookToShelf", ["GetBookFromBasket"]);
23
+
24
+ const filePath = resolve(__dirname, "./simple_design_temp.json")
25
+ await writeFile(filePath, d.serialize())
26
+
27
+ // Output can be viewed using https://mermaid.live/
28
+ const filePath2 = resolve(__dirname, "./temp/simple_design_mermaid.txt")
29
+ await writeFile(filePath2, d.graph.exportAsMermaid())
30
+ });
31
+ });
@@ -0,0 +1 @@
1
+ {"uid":"0f4433c4-abd7-43da-96e3-6809863c93ab","type":5,"nodes":[{"uid":"1b0751a9-c46e-4fa6-ae7f-cf6204fdd83b","type":6,"goToBehaviorsIds":["AcceptBookFromUser"],"behavior":{"uid":"e336a950-f89c-43a6-b3c4-09df32f64831","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptChoiceToAddBookToBasket"}},{"uid":"deb11624-0fae-4d1b-9d22-d421dea1d712","type":6,"goToBehaviorsIds":["AddBookToBasket"],"behavior":{"uid":"65b253bb-c4f2-4dee-8f36-648f73b3300c","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptBookFromUser"}},{"uid":"f914f2c9-86e3-4c54-a926-b6c9c425cf9f","type":6,"goToBehaviorsIds":[],"behavior":{"uid":"76b6962c-24b1-4999-9719-5ac2e4f1c022","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AddBookToBasket"}},{"uid":"84912fd4-c193-4b7d-ad62-cdc6b254d529","type":6,"goToBehaviorsIds":["GenerateAuditReport"],"behavior":{"uid":"76f3d5a5-2e64-4bea-8beb-70d0d38e0645","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptChoiceToAuditLibrary"}},{"uid":"4056410c-37c5-4ffa-8766-2ecd7a079617","type":6,"goToBehaviorsIds":["HandAuditToUser"],"behavior":{"uid":"f6a6e7d4-0151-4881-8d57-fb327620fd4a","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GenerateAuditReport"}},{"uid":"e6de6529-7d64-40f4-8787-c0e1c1c324eb","type":6,"goToBehaviorsIds":[],"behavior":{"uid":"8a3efec4-1068-4ee5-b66d-715bcc7b6d79","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"HandAuditToUser"}},{"uid":"91b71f6c-e384-4c31-9d39-4eae95e61872","type":6,"goToBehaviorsIds":["GetBookFromBasket"],"behavior":{"uid":"9caee137-24b9-4314-b5a7-e4a7f6e93256","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptChoiceToPlaceBooksOnShelf"}},{"uid":"4ea36149-15cf-4e6d-8770-cfd6bdc9645d","type":6,"goToBehaviorsIds":["GetFirstLetterOfBookName"],"behavior":{"uid":"1477b094-eb0a-4c2c-88b2-35ba99155f1e","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GetBookFromBasket"}},{"uid":"bd6116de-8cd9-41b2-a256-fab5d979d80e","type":6,"goToBehaviorsIds":["CreateSlotOnBookShelf","AddBookToShelf"],"behavior":{"uid":"36b0483d-d831-4478-a34e-c091db38370d","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GetFirstLetterOfBookName"}},{"uid":"54948771-65b7-40cb-8331-85f5b7d6cbf1","type":6,"goToBehaviorsIds":["AddBookToShelf"],"behavior":{"uid":"1fcd8aa4-6f25-4406-a0bc-ba43912ec572","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"CreateSlotOnBookShelf"}},{"uid":"ff292a3c-e556-44de-9a47-9510ef0910e4","type":6,"goToBehaviorsIds":["GetBookFromBasket"],"behavior":{"uid":"b736147d-faf3-4718-86c2-a2e8ffa8fb51","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AddBookToShelf"}}]}