ekms 9.6.3-beta.2 → 9.6.3-beta.21

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.
Files changed (55) hide show
  1. package/common/actions.instance.json +130 -5
  2. package/common/actions.js +54 -4
  3. package/common/actions.test.json +31359 -322
  4. package/common/angle.instance.json +58 -834
  5. package/common/articles.js +1 -2
  6. package/common/compass.instance.json +3 -18
  7. package/common/concept.js +2 -1
  8. package/common/conjunction.js +11 -17
  9. package/common/dialogues.js +3 -3
  10. package/common/dimension.instance.json +4 -69
  11. package/common/dimension.js +5 -5
  12. package/common/drone.instance.json +14985 -2538
  13. package/common/drone.js +276 -61
  14. package/common/drone.test.json +412474 -28440
  15. package/common/drone_v1.instance.json +324 -44
  16. package/common/drone_v1.js +9 -9
  17. package/common/edible.instance.json +72 -0
  18. package/common/fastfood.instance.json +5 -72
  19. package/common/fastfood.js +1 -1
  20. package/common/formulas.instance.json +0 -5
  21. package/common/formulas.js +1 -1
  22. package/common/gdefaults.js +16 -5
  23. package/common/helpers/conjunction.js +2 -0
  24. package/common/helpers/formulas.js +6 -0
  25. package/common/helpers/properties.js +9 -7
  26. package/common/helpers.js +9 -5
  27. package/common/hierarchy.js +2 -0
  28. package/common/length.instance.json +555 -5686
  29. package/common/math.instance.json +10 -12
  30. package/common/math.js +6 -5
  31. package/common/menus.instance.json +0 -35
  32. package/common/meta.js +1 -1
  33. package/common/nameable.js +7 -9
  34. package/common/ordinals.js +51 -5
  35. package/common/pipboy.instance.json +0 -85
  36. package/common/pipboy.js +1 -1
  37. package/common/pressure.instance.json +28 -370
  38. package/common/properties.js +4 -3
  39. package/common/rates.instance.json +1 -1
  40. package/common/rates.js +3 -3
  41. package/common/reminders.js +1 -1
  42. package/common/reports.instance.json +9 -176
  43. package/common/reports.js +2 -2
  44. package/common/scorekeeper.js +1 -1
  45. package/common/sdefaults.js +40 -5
  46. package/common/stm.js +50 -42
  47. package/common/temperature.instance.json +648 -2303
  48. package/common/time.instance.json +7376 -1965
  49. package/common/time.js +22 -1
  50. package/common/time.test.json +13239 -0
  51. package/common/ui.instance.json +0 -5
  52. package/common/ui.js +1 -1
  53. package/common/weight.instance.json +329 -1834
  54. package/common/wp.instance.json +88 -70
  55. package/package.json +3 -3
package/common/drone.js CHANGED
@@ -1,4 +1,4 @@
1
- const { knowledgeModule, where } = require('./runtime').theprogrammablemind
1
+ const { knowledgeModule, where, debug } = require('./runtime').theprogrammablemind
2
2
  const { conjugateVerb } = require('./english_helpers')
3
3
  const { OverrideCheck, defaultContextCheckProperties, defaultContextCheck, getValue, setValue } = require('./helpers')
4
4
  const drone_tests = require('./drone.test.json')
@@ -14,6 +14,33 @@ const help = require('./help')
14
14
  const { rotateDelta, degreesToRadians, radiansToDegrees, cartesianToPolar, smallestRotate } = require('./helpers/drone')
15
15
 
16
16
  /*
17
+ NEED TO CHECK ON ACTUAL DRONE
18
+
19
+ patrol back and forth 2 times
20
+
21
+ DONE fix DO so it can do all the stuff partol can do <<<<<<<<<<<<<<<<<<<
22
+ start again. start a new path
23
+ the last 3 points are called path 1
24
+ go forward 1 meter and then turn north
25
+ go forward 1 meter and turn north
26
+
27
+
28
+ stopping 2 seconds at each point
29
+ patrols x do that again
30
+ DONE go to the end of the patrol
31
+ DONE patrol x three times
32
+ patrol x continuously
33
+ patrol x for 5 minutes
34
+ go to the start
35
+ DONE node drone -q 'north 1 meter\neast 1 meter\ncall that route 2\nwhat is the second point of route 2' -g -
36
+
37
+ go to the start along the path / following the path
38
+ pausing 1 second at the first point and 5 at the last
39
+
40
+ DONE go to the second point of route 1
41
+ DONE do route 1 pausing 10 seconds at each point
42
+
43
+ what is the drone's position
17
44
  DONE go back
18
45
  go back another point
19
46
  go back again
@@ -21,12 +48,22 @@ go back to the start
21
48
  go back 2 points along route 1
22
49
  go to the start of route 2
23
50
 
51
+ go forward 1 foot\nturn left\ngo forward again\n
52
+ do it again
53
+ do route 1 skipping point 2
54
+
55
+ TODO should there be two hierarchy one as a concept car is a vehicle and one as a word car is a noun
56
+
24
57
  turn left\nturn back
25
58
 
26
- do route 1 pausing 10 seconds at each point
59
+ DONE do route 1 pausing 10 seconds at each point
60
+ do route 1 pausing 1 second at point 1 and 2 seconds for the rest
27
61
 
28
62
  forward 1 foot\nwest 1 foot\ngo back to the start <<<<<<<< turn the longer way not he shorter way
29
63
  forward 1 foot\nwest 1 foot\ncall the path route 1\ngo to the start of route 1\npatrol route 1\npatrol route 1 <<<<< does the patrol more than once
64
+ call that route 1
65
+ what are the paths
66
+ list the paths
30
67
 
31
68
  ?? elipses of the verb go or some kind of conjunction?!?!?
32
69
  go forward 1 meter turn right forward 2 meters stop
@@ -269,6 +306,22 @@ class API {
269
306
  const overrideMethods = Object.getOwnPropertyNames(API.prototype).filter(key => typeof API.prototype[key] === 'function' && key.endsWith('Drone'));
270
307
  this.overrideCheck = new OverrideCheck(API, overrideMethods)
271
308
  this.overriden = this.constructor !== API
309
+ this.startPoint = { x: 0, y: 0 }
310
+ this.startAngle = Math.PI/2
311
+ this.startCompass = 'north'
312
+ }
313
+
314
+ setStartPoint(point) {
315
+ this.startPoint = point
316
+ }
317
+
318
+ setStartAngle(angleInRadians, compass) {
319
+ this.startAngle = angleInRadians
320
+ this.startCompass = compass
321
+ }
322
+
323
+ setSpeed(metersPerSecond) {
324
+ this._objects.current.speed = metersPerSecond
272
325
  }
273
326
 
274
327
  initialize({ objects }) {
@@ -276,11 +329,11 @@ class API {
276
329
  this.overrideCheck.check(this)
277
330
  }
278
331
 
279
- if (!this.minimumSpeedDrone()) {
332
+ if (this.minimumSpeedDrone() == null) {
280
333
  throw new Error(`minimumSpeedDrone is not returning a positive number. Its returning ${this.minimumSpeedDrone()}`)
281
334
  }
282
335
 
283
- if (!this.maximumSpeedDrone()) {
336
+ if (this.maximumSpeedDrone() == null) {
284
337
  throw new Error(`maximumSpeedDrone is not returning a positive number. Its returning ${this.maximumSpeedDrone()}`)
285
338
  }
286
339
 
@@ -289,17 +342,17 @@ class API {
289
342
  delete this.testDate
290
343
 
291
344
  objects.current = {
292
- angleInRadians: Math.PI/2,
345
+ angleInRadians: this.startAngle,
293
346
  path: [],
294
347
  speed: this.minimumSpeedDrone(),
295
348
  ordinal: 0, // ordinal of the current point or the current point that the recent movement started at
296
- compass: 'north', // for now assume the drone start out point north. i will make that part of the conversation later
349
+ compass: this.startCompass,
297
350
  direction: 'forward',
298
351
  }
299
352
  objects.history = []
300
353
  objects.sonicTest = 5
301
354
 
302
- this.args.mentioned({ marker: 'point', ordinal: this.nextOrdinal(), point: { x: 0, y: 0 }, description: "start" })
355
+ this.args.remember({ marker: 'point', ordinal: this.nextOrdinal(), point: this.startPoint, description: "start" })
303
356
  }
304
357
 
305
358
  currentOrdinal() {
@@ -318,7 +371,7 @@ class API {
318
371
  return null // in motion
319
372
  }
320
373
  const ordinal = this.currentOrdinal()
321
- const lastPoint = await this.args.mentions({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })
374
+ const lastPoint = await this.args.recall({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })
322
375
  if (!current.startTime && !current.endTime && !current.durationInSeconds) {
323
376
  return lastPoint // did not move
324
377
  }
@@ -344,7 +397,7 @@ class API {
344
397
  return
345
398
  }
346
399
  const ordinal = this.nextOrdinal()
347
- this.args.mentioned({ marker: 'point', ordinal, point })
400
+ this.args.remember({ marker: 'point', ordinal, point })
348
401
  this._objects.current.endTime = null
349
402
  this._objects.current.startTime = null
350
403
  }
@@ -378,9 +431,13 @@ class API {
378
431
  const unitsOfUser = objects.current.speedUnitsOfUser
379
432
  const minimumValueInDroneUnits = await fragments("number meters per second", { number: { marker: 'integer', value: minimumSpeed } })
380
433
  // const valueInUsersUnits = await fragments("quantity in meters", { quantity: minimumValueInDroneUnits, meter: unitsOfUser })
381
- const valueInUsersUnits = await quantityInMeters(minimumValueInDroneUnits, unitsOfUser )
382
- const evaluated = await e(valueInUsersUnits)
383
- say(`The drone cannot go that slow. The minimum speed is ${await gr(evaluated.evalue)}`)
434
+ if (unitsOfUser) {
435
+ const valueInUsersUnits = await quantityInMeters(minimumValueInDroneUnits, unitsOfUser )
436
+ const evaluated = await e(valueInUsersUnits)
437
+ say(`The drone cannot go that slow. The minimum speed is ${await gr(evaluated.evalue)}`)
438
+ } else {
439
+ say(`The drone cannot go that fast. The minimum speed is ${await gr(minimumValueInDroneUnits)}`)
440
+ }
384
441
  objects.runCommand = false
385
442
  objects.current.speed = minimumSpeed
386
443
  return
@@ -392,9 +449,13 @@ class API {
392
449
  const unitsOfUser = objects.current.speedUnitsOfUser
393
450
  const maximumValueInDroneUnits = await fragments("number meters per second", { number: { marker: 'integer', value: maximumSpeed } })
394
451
  // const valueInUsersUnits = await fragments("quantity in meters", { quantity: maximumValueInDroneUnits, meter: unitsOfUser })
395
- const valueInUsersUnits = await quantityInMeters(maximumValueInDroneUnits, unitsOfUser )
396
- const evaluated = await e(valueInUsersUnits)
397
- say(`The drone cannot go that fast. The maximum speed is ${await gr(evaluated.evalue)}`)
452
+ if (unitsOfUser) {
453
+ const valueInUsersUnits = await quantityInMeters(maximumValueInDroneUnits, unitsOfUser)
454
+ const evaluated = await e(valueInUsersUnits)
455
+ say(`The drone cannot go that fast. The maximum speed is ${await gr(evaluated.evalue)}`)
456
+ } else {
457
+ say(`The drone cannot go that fast. The maximum speed is ${await gr(maximumValueInDroneUnits)}`)
458
+ }
398
459
  objects.runCommand = false
399
460
  objects.current.speed = minimumSpeed
400
461
  return
@@ -409,16 +470,19 @@ class API {
409
470
  }
410
471
 
411
472
  if (objects.current.path.length > 0) {
412
- if (objects.current.timeRepeats) {
413
- this.startRepeats(objects.current.timeRepeats)
414
- }
415
- let currentPoint = (await this.args.mentions({ context: { marker: 'point' } })).point
473
+ let currentPoint = (await this.args.recall({ context: { marker: 'point' } })).point
416
474
  this._objects.history.push({ marker: 'history', debug: 'doing path' })
417
- for (const pathComponent of objects.current.path) {
418
- if (pathComponent.marker == 'pause') {
475
+ for (const [pathIndex, pathComponent] of objects.current.path.entries()) {
476
+ if (pathComponent.repeatStart) {
477
+ if (objects.current.timeRepeats) {
478
+ this.startRepeats(objects.current.timeRepeats)
479
+ }
480
+ } else if (pathComponent.marker == 'pause') {
419
481
  this.pause(pathComponent.pauseSeconds, { batched: true })
420
482
  } else {
421
- const destinationPoint = pathComponent.point
483
+ const points = this.args.toArray(pathComponent)
484
+ // const destinationPoint = pathComponent.point
485
+ const destinationPoint = points[0].point || points[0]
422
486
  if (currentPoint.x == destinationPoint.x && currentPoint.y == destinationPoint.y) {
423
487
  // already there
424
488
  } else {
@@ -427,12 +491,12 @@ class API {
427
491
  // const angleDelta = (destinationAngleInRadians - objects.current.angleInRadians)
428
492
  const angleDelta = rotateDelta(objects.current.angleInRadians, destinationAngleInRadians)
429
493
  await this.rotate(angleDelta, { batched: true })
430
- if (!pathComponent .aimOnly) {
494
+ if (!pathComponent.aimOnly) {
431
495
  await this.forward(objects.current.speed, { batched: true })
432
496
  await stopAtDistance("forward", polar.radius)
497
+ currentPoint = destinationPoint
433
498
  }
434
499
  }
435
- currentPoint = destinationPoint
436
500
  }
437
501
  }
438
502
  if (objects.current.timeRepeats) {
@@ -544,7 +608,7 @@ class API {
544
608
  } else {
545
609
  ordinal = this.currentOrdinal() - 1
546
610
  }
547
- const lastPoint = await this.args.mentions({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })
611
+ const lastPoint = await this.args.recall({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })
548
612
  if (!lastPoint) {
549
613
  this.args.say(`There is no previous point to go back to`)
550
614
  return
@@ -558,8 +622,9 @@ class API {
558
622
  const current = objects.current
559
623
  current.backAndForth = true
560
624
  const ordinal = this.currentOrdinal()
561
- const currentPoint = await this.args.mentions({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })
562
- const lastPoint = await this.args.mentions({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal-1 })
625
+ const currentPoint = await this.args.recall({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })
626
+ const lastPoint = await this.args.recall({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal-1 })
627
+ current.path.push({ repeatStart: true })
563
628
  current.path.push(lastPoint)
564
629
  current.path.push(currentPoint)
565
630
  objects.runCommand = true
@@ -752,6 +817,7 @@ const template = {
752
817
  "number radians",
753
818
  "40 degrees in radians",
754
819
  "path",
820
+ "forward",
755
821
  ],
756
822
  configs: [
757
823
  "arm, claw and drone are concepts",
@@ -759,9 +825,25 @@ const template = {
759
825
  "around, forward, left, right, back, forth and backward are directions",
760
826
  "paths are nameable and memorable",
761
827
  "start and end are properties of path",
828
+ ({apis}) => {
829
+ apis('properties').addHierarchyWatcher({
830
+ match: ({childId}) => childId == 'point',
831
+ apply: ({config, childId}) => {
832
+ config.updateBridge(childId, ({ bridge }) => {
833
+ if (!bridge.init) {
834
+ bridge.init = {}
835
+ }
836
+ bridge.init['notConjunctableWith'] = ['quantity']
837
+ })
838
+ }
839
+ })
840
+ },
841
+
762
842
  "start and end are points",
843
+ "rest and remaining are concepts",
763
844
  {
764
845
  hierarchy: [
846
+ ['point', 'distributable'],
765
847
  ['thisitthat', 'path'],
766
848
  ['path', 'action'],
767
849
  ],
@@ -815,14 +897,45 @@ const template = {
815
897
  "([lower] (@<= arm || @<=claw))",
816
898
  "([open] (claw))",
817
899
  "([close] (claw))",
900
+ "([startPath|start] (path))",
818
901
  "([pathComponent])",
819
902
  "(<another> (point))",
820
903
  // "([turn] (direction))",
821
904
  // "([pause] ([number]))",
822
905
  "([stop] ([drone|])?)",
823
906
  "([toPoint|to] (point))",
907
+ "([atPoint|at] (point))",
908
+ // "([forRest|for] (rest/* || remaining/*))",
909
+ "((context.unit.dimension == 'time') [timeAtPoint|] (atPoint))",
910
+ // "((context.unit.dimension == 'time') [timeForRest|] (forRest))",
824
911
  ],
825
912
  bridges: [
913
+ {
914
+ id: 'startPath',
915
+ isA: ['verb'],
916
+ bridge: "{ ...next(operator), path: after[0], operator: operator, interpolate: [{ property: 'operator' }, { property: 'path' }] }",
917
+ check: defaultContextCheckProperties(['path']),
918
+ semantic: async ({context, remember, recall, verbatim, g}) => {
919
+ const point = await recall({ context: { marker: 'point' } })
920
+ remember(context)
921
+ remember(point) // put the last point before the startPath so when the new path is generated this is the start point
922
+ verbatim(`New path started from ${await g(point)}`)
923
+ },
924
+ },
925
+ {
926
+ id: 'timeAtPoint',
927
+ before: ['verb'],
928
+ after: ['preposition'],
929
+ convolution: true,
930
+ bridge: "{ ...next(operator), time: before[0], point: after[0], operator: operator, interpolate: [{ property: 'time' }, { property: 'point' }] }",
931
+ check: defaultContextCheckProperties(['time', 'point']),
932
+ },
933
+ {
934
+ id: 'atPoint',
935
+ isA: ['preposition'],
936
+ bridge: "{ ...next(operator), point: after[0], operator: operator, interpolate: [{ property: 'operator' }, { property: 'point' }] }",
937
+ check: defaultContextCheckProperties(['point']),
938
+ },
826
939
  {
827
940
  id: 'another',
828
941
  bridge: `{
@@ -831,6 +944,7 @@ const template = {
831
944
  after: after[0],
832
945
  interpolate: [ { property: 'another' }, { property: 'after' } ]
833
946
  }`,
947
+ check: defaultContextCheckProperties(['another', 'after']),
834
948
  },
835
949
  {
836
950
  id: 'pathComponent',
@@ -838,22 +952,61 @@ const template = {
838
952
  },
839
953
  {
840
954
  id: 'patrol',
841
- isA: ['verb'],
955
+ isA: ['verb', 'repeatable'],
842
956
  bridge: `{
843
- ...next(operator), operator: operator, path: after[0], interpolate: [{ property: 'operator'}, { property: 'path' }]
957
+ ...next(operator), operator: operator, path: after[0], interpolate: append(default(operator.interpolate, [{ property: 'operator'}]), [{ property: 'path' }])
844
958
  }`,
845
- semantic: async ({context, e, toEValue, objects}) => {
959
+ check: defaultContextCheckProperties(['path']),
960
+ semantic: async ({context, e, toArray, fragments, toEValue, toFinalValue, recall, objects}) => {
846
961
  const evaluated = await(e(context.path))
847
962
  const path = toEValue(evaluated)
963
+
964
+ // TODO put this in a common place for use by do+patrol
965
+
966
+ // ordinal to pause time in seconds
967
+ const pauseTimeInSeconds = {}
968
+ if (context.pause) {
969
+ const timeAtPoints = toArray(context.pause.timeAtPoint)
970
+ for (const timeAtPoint of timeAtPoints) {
971
+ const instantiation = await fragments("quantity in seconds", { quantity: timeAtPoint.time })
972
+ const result = await e(instantiation)
973
+ const seconds = toFinalValue(toFinalValue(result).amount)
974
+
975
+ const points = await recall({ context: timeAtPoint.point.point, frameOfReference: path })
976
+ for (const point of toArray(points)) {
977
+ pauseTimeInSeconds[point.ordinal] = seconds
978
+ }
979
+ }
980
+ }
981
+
982
+ // get to the start of the patrol
983
+ objects.current.path.push(path.points[0])
984
+ objects.current.path.push({ aimOnly: true, ...path.points[1] })
985
+ objects.current.path.push({ repeatStart: true })
848
986
  for (const point of path.points) {
849
987
  objects.current.path.push(point)
988
+ if (pauseTimeInSeconds[point.ordinal]) {
989
+ objects.current.path.push({ marker: 'pause', pauseSeconds: pauseTimeInSeconds[point.ordinal] })
990
+ }
991
+ }
992
+ if (context.repeats) {
993
+ objects.current.timeRepeats = toFinalValue(context.repeats.repeats)
850
994
  }
851
995
  // if the patrol does not start and end at the same spot then
852
996
  // go back to the start along the same path
997
+
998
+
999
+ // if the start is not the end of the patrol then go backwards along the patrol
853
1000
  if (JSON.stringify(path.points[0].point) !== JSON.stringify(path.points[path.points.length-1].point)) {
854
- for (const point of [...path.points].reverse()) {
1001
+ for (const point of [...path.points].reverse().slice(1)) {
855
1002
  objects.current.path.push(point)
1003
+ if (pauseTimeInSeconds[point.ordinal]) {
1004
+ objects.current.path.push({ marker: 'pause', pauseSeconds: pauseTimeInSeconds[point.ordinal] })
1005
+ }
856
1006
  }
1007
+
1008
+ const secondPoint = path.points[1]
1009
+ objects.current.path.push({ ...secondPoint, aimOnly: true })
857
1010
  }
858
1011
  objects.runCommand = true
859
1012
  }
@@ -881,6 +1034,7 @@ const template = {
881
1034
  bridge: `{
882
1035
  ...next(operator), operator: operator, object: after[0], interpolate: [{ property: 'operator'}, { property: 'object' }]
883
1036
  }`,
1037
+ check: defaultContextCheckProperties(['object']),
884
1038
  semantic: ({api}) => {
885
1039
  api.armAction('up')
886
1040
  }
@@ -891,6 +1045,7 @@ const template = {
891
1045
  bridge: `{
892
1046
  ...next(operator), operator: operator, object: after[0], interpolate: [{ property: 'operator'}, { property: 'object' }]
893
1047
  }`,
1048
+ check: defaultContextCheckProperties(['object']),
894
1049
  semantic: ({api}) => {
895
1050
  api.armAction('down')
896
1051
  }
@@ -901,6 +1056,7 @@ const template = {
901
1056
  bridge: `{
902
1057
  ...next(operator), operator: operator, object: after[0], interpolate: [{ property: 'operator'}, { property: 'object' }]
903
1058
  }`,
1059
+ check: defaultContextCheckProperties(['object']),
904
1060
  semantic: ({api}) => {
905
1061
  api.clawAction('open')
906
1062
  }
@@ -911,6 +1067,7 @@ const template = {
911
1067
  bridge: `{
912
1068
  ...next(operator), operator: operator, object: after[0], interpolate: [{ property: 'operator'}, { property: 'object' }]
913
1069
  }`,
1070
+ check: defaultContextCheckProperties(['object']),
914
1071
  semantic: ({api}) => {
915
1072
  api.clawAction('close')
916
1073
  }
@@ -918,7 +1075,7 @@ const template = {
918
1075
  {
919
1076
  id: 'back',
920
1077
  isA: ['noun'],
921
- semantic: async ({objects, mentions, api, e, context, say}) => {
1078
+ semantic: async ({objects, api, e, context, say}) => {
922
1079
  await api.back()
923
1080
  }
924
1081
  },
@@ -931,6 +1088,7 @@ const template = {
931
1088
  isA: ['preposition'],
932
1089
  after: [['propertyOf', 1]],
933
1090
  bridge: "{ ...next(operator), operator: operator, point: after[0], interpolate: [{ property: 'operator' }, { property: 'point' }] }",
1091
+ check: defaultContextCheckProperties(['point']),
934
1092
  semantic: async ({objects, api, e, context}) => {
935
1093
  objects.runCommand = true
936
1094
  const point = await e(context.point)
@@ -941,11 +1099,11 @@ const template = {
941
1099
  id: "go",
942
1100
  level: 0,
943
1101
  // convolution: true,
944
- isA: ['verb', 'action'],
1102
+ isA: ['verb', 'action', 'repeatable'],
945
1103
  words: [
946
1104
  ...conjugateVerb('go'),
947
1105
  ],
948
- check: defaultContextCheckProperties(['direction', 'distance', 'to']),
1106
+ check: defaultContextCheckProperties(['direction', 'distance', 'to', 'points']),
949
1107
  bridge: `{
950
1108
  ...next(operator),
951
1109
  distance: distance?,
@@ -953,7 +1111,7 @@ const template = {
953
1111
  points: points?,
954
1112
  to: to?,
955
1113
  operator: operator,
956
- interpolate: [{ property: 'operator' }, { property: 'direction' }, { property: 'points' }, { property: 'to' }, { property: 'distance' }]
1114
+ interpolate: append(default(operator.interpolate, [{ property: 'operator' }]), [{ property: 'direction' }, { property: 'points' }, { property: 'to' }, { property: 'distance' }])
957
1115
  }`,
958
1116
  selector: {
959
1117
  arguments: {
@@ -964,7 +1122,7 @@ const template = {
964
1122
  },
965
1123
  },
966
1124
  semantic: async (args) => {
967
- const {context, objects, e, toArray, toEValue} = args
1125
+ const {api, toFinalValue, context, objects, e, toArray, toEValue} = args
968
1126
  if (context.distance) {
969
1127
  await handleDistance(args, context.distance)
970
1128
  }
@@ -978,25 +1136,32 @@ const template = {
978
1136
  objects.current.direction = context.direction.marker
979
1137
  }
980
1138
  }
1139
+ if (context.repeats) {
1140
+ objects.current.timeRepeats = toFinalValue(context.repeats.repeats)
1141
+ }
981
1142
  if (context.to) {
982
1143
  const evaluation = await e(context.to.point)
983
1144
  const point = toEValue(evaluation)
984
1145
  objects.current.path.push(point)
985
1146
  }
986
1147
  objects.runCommand = true
1148
+ await api.sendCommand()
987
1149
  },
988
1150
  },
989
1151
  {
990
1152
  id: 'turn',
991
- isA: ['verb'],
1153
+ isA: ['verb', 'action', 'repeatable'],
1154
+ before: ['thenAction'],
992
1155
  words: ['turn'],
993
1156
  bridge: `{
994
1157
  ...next(operator),
995
1158
  direction: direction,
996
- repeats: repeats?,
1159
+ operator: operator,
997
1160
  angle: angle?,
998
- interpolate: [{ context: operator }, { property: 'direction' }, { property: 'angle' }, { property: 'repeats' }] }
1161
+ interpolate: append(default(operator.interpolate, [{ property: 'operator'}]), [{ property: 'direction' }, { property: 'angle' }])
1162
+ }
999
1163
  `,
1164
+ check: defaultContextCheckProperties(['direction', 'angle']),
1000
1165
  selector: {
1001
1166
  arguments: {
1002
1167
  direction: "(@<= 'direction')",
@@ -1032,6 +1197,9 @@ const template = {
1032
1197
  return
1033
1198
  }
1034
1199
  }
1200
+ if (context.repeats) {
1201
+ objects.current.timeRepeats = toFinalValue(context.repeats.repeats)
1202
+ }
1035
1203
  current.justTurn = true
1036
1204
  objects.runCommand = true
1037
1205
  await api.sendCommand()
@@ -1041,17 +1209,24 @@ const template = {
1041
1209
  {
1042
1210
  id: 'pause',
1043
1211
  isA: ['verb'],
1044
- words: ['pause'],
1045
- bridge: "{ ...operator, time: or(time?, forTime), interpolate: [{ context: operator }, { property: 'time' }] }",
1046
- check: defaultContextCheckProperties(['time']),
1212
+ words: [
1213
+ ...conjugateVerb('pause'),
1214
+ ],
1215
+ bridge: "{ ...next(operator), timeAtPoint: timeAtPoint?, time: or(time?, forTime?), operator: operator, atPoint: atPoint?, interpolate: [{ property: 'operator' }, { property: 'time' }, { property: 'forTime' }, { property: 'atPoint' }, { property: 'timeAtPoint' } ] }",
1216
+ check: defaultContextCheckProperties(['timeAtPoint']),
1047
1217
  selector: {
1048
1218
  arguments: {
1049
1219
  forTime: "(@<= 'forQuantity' && context.quantity.unit.dimension == 'time')",
1050
1220
  time: "(@<= 'quantity' && context.unit.dimension == 'time')",
1221
+ atPoint: "(@<= 'atPoint')",
1222
+ timeAtPoint: "(@<= 'timeAtPoint')",
1051
1223
  },
1052
1224
  },
1053
- semantic: async ({context, mentioned, api, e, fragments, toFinalValue}) => {
1225
+ semantic: async ({context, remember, api, e, fragments, toFinalValue}) => {
1054
1226
  let time = context.time
1227
+ if (!time) {
1228
+ return
1229
+ }
1055
1230
  if (time.marker == 'forQuantity') {
1056
1231
  time = time.quantity
1057
1232
  }
@@ -1059,10 +1234,22 @@ const template = {
1059
1234
  const result = await e(instantiation)
1060
1235
  const seconds = toFinalValue(toFinalValue(result).amount)
1061
1236
  context.pauseSeconds = seconds
1062
- mentioned(context)
1237
+ remember(context)
1063
1238
  api.pause(seconds)
1064
1239
  }
1065
1240
  },
1241
+ {
1242
+ id: 'pause',
1243
+ level: 1,
1244
+ bridge: "{ ...repeatable, pause: operator, checks: append(repeatable.checks, ['pause']), repeatable: repeatable, interpolate: [{ property: 'repeatable' }, { property: 'pause', byPosition: true }] }",
1245
+ selector: {
1246
+ loose: "repeatable",
1247
+ arguments: {
1248
+ repeatable: "(@<= 'repeatable')",
1249
+ },
1250
+ },
1251
+ check: defaultContextCheckProperties(['repeatable', 'repeats'])
1252
+ },
1066
1253
  {
1067
1254
  id: 'stop',
1068
1255
  isA: ['verb'],
@@ -1070,7 +1257,7 @@ const template = {
1070
1257
  1: "{ marker: 'drone' }",
1071
1258
  },
1072
1259
  bridge: "{ ...next(operator), object: after[0], interpolate: [{ context: operator }, { property: 'object' }] }",
1073
- semantic: async ({mentioned, context, objects, api, say}) => {
1260
+ semantic: async ({context, objects, api, say}) => {
1074
1261
  await api.stop()
1075
1262
  await api.markCurrentPoint()
1076
1263
  }
@@ -1089,18 +1276,13 @@ const template = {
1089
1276
  semantics: [
1090
1277
  {
1091
1278
  match: ({context}) => context.marker == 'doAction',
1092
- apply: async ({context, e, toEValue, objects}) => {
1093
- const evaluated = await(e(context.action))
1094
- const path = toEValue(evaluated)
1095
- for (const point of path.points) {
1096
- objects.current.path.push(point)
1097
- }
1098
- objects.runCommand = true
1279
+ apply: async ({context, fragments, e, s, toEValue, toFinalValue, objects}) => {
1280
+ await s({ ...context, marker: 'patrol', path: context.action})
1099
1281
  }
1100
1282
  },
1101
1283
  {
1102
1284
  match: ({context, contextHierarchy}) => {
1103
- if (!context.pullFromContext || !context.evaluate || contextHierarchy.under(['doAction', 'evaluate'])) {
1285
+ if (!context.pullFromContext || !context.evaluate || contextHierarchy.under(['doAction', 'evaluate', 'patrol']) || context.instance) {
1104
1286
  return false
1105
1287
  }
1106
1288
 
@@ -1108,13 +1290,18 @@ const template = {
1108
1290
  return true
1109
1291
  }
1110
1292
  },
1111
- apply: async ({context, frameOfReference, toArray, fragments, stm, objects, mentioned, mentions, resolveEvaluate, _continue, contextHierarchy}) => {
1112
- const pathComponents = toArray(await mentions({ context: { marker: 'pathComponent' }, all: true }))
1293
+ apply: async ({context, frameOfReference, toArray, fragments, objects, remember, recall, resolveEvaluate, _continue, contextHierarchy}) => {
1294
+ const pathComponents = toArray(await recall({
1295
+ context: { marker: 'pathComponent' },
1296
+ all: true,
1297
+ stopCondition: (context) => context.marker == 'startPath',
1298
+ }))
1113
1299
  const path = (await fragments('path')).contexts()[0]
1114
1300
  delete path.value
1301
+ path.instance = true
1115
1302
  path.points = pathComponents.reverse()
1116
1303
  frameOfReference(path, { mentioned: 'points', reversed: true })
1117
- await mentioned(path)
1304
+ await remember(path)
1118
1305
 
1119
1306
  _continue() // let the call pick the object out from the stm
1120
1307
  },
@@ -1129,18 +1316,21 @@ const template = {
1129
1316
  return true
1130
1317
  }
1131
1318
  },
1132
- apply: async ({context, e, fragments, stm, toEValue, toArray, objects, mentioned, mentions, resolveEvaluate, _continue, contextHierarchy}) => {
1319
+ apply: async ({frameOfReference, context, e, fragments, stm, toEValue, toArray, objects, remember, recall, resolveEvaluate, _continue, contextHierarchy}) => {
1133
1320
  const evaluated = await e({...context, notUnderCall: true})
1134
1321
  const pointsContext = toEValue(evaluated)
1135
1322
  const pathComponents = toArray(pointsContext)
1136
1323
 
1137
1324
  const path = (await fragments('path')).contexts()[0]
1138
1325
  delete path.value
1139
- path.points = pathComponents.reverse()
1140
- await mentioned(path)
1326
+ path.instance = true
1327
+ path.points = [...pathComponents]
1328
+ frameOfReference(path, { mentioned: 'points', reversed: true })
1329
+ await remember(path)
1141
1330
  resolveEvaluate(context, path)
1142
1331
  },
1143
1332
  },
1333
+ /*
1144
1334
  {
1145
1335
  match: ({context}) => context.marker == 'thenTime',
1146
1336
  apply: async ({objects, api}) => {
@@ -1149,10 +1339,11 @@ const template = {
1149
1339
  }
1150
1340
  },
1151
1341
  },
1342
+ */
1152
1343
  {
1153
1344
  match: ({context}) => context.evaluate && ['start', 'end'].includes(context.marker) && context.objects && context.objects[1].marker == 'path',
1154
- apply: async ({gp, s, context, objects, fragments, resolveEvaluate, api, mentions}) => {
1155
- const path = await mentions({ context: context.objects[1] })
1345
+ apply: async ({gp, s, context, objects, fragments, resolveEvaluate, api, recall}) => {
1346
+ const path = await recall({ context: context.objects[1] })
1156
1347
  if (!path?.points) {
1157
1348
  return
1158
1349
  }
@@ -1163,6 +1354,29 @@ const template = {
1163
1354
  }
1164
1355
  }
1165
1356
  },
1357
+ {
1358
+ match: ({context, contextHierarchy}) =>
1359
+ context.evaluate &&
1360
+ ['start', 'end', 'point'].includes(context.marker) &&
1361
+ !context.propertyOf &&
1362
+ contextHierarchy.under('go') &&
1363
+ !contextHierarchy.under('call'),
1364
+ apply: async ({gp, s, toArray, context, objects, fragments, resolveEvaluate, api, recall}) => {
1365
+ const path = await recall({ context: { marker: 'path' } })
1366
+ if (!path?.points) {
1367
+ return
1368
+ }
1369
+
1370
+ if (context.marker == 'start') {
1371
+ resolveEvaluate(context, path?.points[0])
1372
+ } else if (context.marker == 'end') {
1373
+ resolveEvaluate(context, path?.points[path?.points.length-1])
1374
+ } else {
1375
+ const points = await recall({ context, frameOfReference: path })
1376
+ resolveEvaluate(context, toArray(points)[0])
1377
+ }
1378
+ }
1379
+ },
1166
1380
  {
1167
1381
  match: ({context}) => context.marker == 'speed' && context.evaluate,
1168
1382
  apply: async ({gp, s, context, objects, fragments, resolveEvaluate, api}) => {
@@ -1238,6 +1452,7 @@ knowledgeModule( {
1238
1452
  defaultContextCheck({ marker: 'path', exported: true,
1239
1453
  extra: [
1240
1454
  'points',
1455
+ 'instance',
1241
1456
  {
1242
1457
  property: 'namespaced',
1243
1458
  check: [