ekms 7.12.3-beta.5 → 7.12.4-beta.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -160,7 +160,6 @@ const template = {
160
160
  { "context": [['smoothie_ingredient', 1], ['list', 0], ['smoothie_ingredient', 1], ['smoothie', 1]], ordered: true, choose: [1] },
161
161
 
162
162
  { "context": [['list', 0], ['number', 1], ['combo', 1], ['number', 1]], ordered: true, choose: [2,3] },
163
- { "context": [['withModification', 0], ['modification', 1], ['list', 0], ['modification', 1]], ordered: true, choose: [2] },
164
163
 
165
164
 
166
165
  { context: [['comboNumber', 0], ['counting',0]], choose: [0] },
@@ -224,7 +223,7 @@ const template = {
224
223
  {
225
224
  id: 'withModification',
226
225
  level: 0,
227
- isA: ['preposition'],
226
+ before: ['preposition'],
228
227
  generatorp: ({context, gp}) => `with ${gp(context.modifications)}`,
229
228
  bridge: "{ ...next(operator), modifications: after[0], flatten: false }",
230
229
  },
@@ -250,7 +249,7 @@ const template = {
250
249
  {
251
250
  id: 'comboNumber',
252
251
  convolution: true,
253
- before: ['combo'],
252
+ before: ['combo', 'preposition'],
254
253
  bridge: "{ ...next(before[0]), postModifiers: append(before[0].postModifiers, ['comboNumber']), comboNumber: after[0], instance: true, flatten: true }",
255
254
  },
256
255
  {
@@ -297,17 +296,24 @@ const template = {
297
296
  const naArray = api.getAskedForButNotAvailable()
298
297
  naArray.forEach((f) => f.paraphrase = true)
299
298
  const naContext = toContext(naArray)
300
- /*
301
- naContext.isResponse = true
302
- naContext.marker = 'verbatim'
303
- naContext.verbatim = `The following are not menu items: ${gp(naContext)}`
304
- insert(naContext)
305
- */
306
299
  verbatim(`The following are not menu items: ${gp(naContext)}`)
307
300
  // allow other motivation to run
308
301
  context.cascade = true
309
302
  }
310
303
  },
304
+ {
305
+ where: where(),
306
+ match: ({context, api}) => context.marker == 'controlEnd' && api.hasAskedForButNotAvailableModification(),
307
+ apply: ({context, api, gp, toContext, verbatim}) => {
308
+ const naArray = api.getAskedForButNotAvailableModification().map(({ item, modification }) => {
309
+ // return `${gp(item)} can not be modified with ${gp(modification)}.`
310
+ return `XXX can not be modified with ${gp(modification)}.`
311
+ })
312
+ verbatim(naArray.join(' '))
313
+ // allow other motivation to run
314
+ context.cascade = true
315
+ }
316
+ },
311
317
  ]
312
318
  },
313
319
  ({ask, api}) => {
@@ -342,17 +348,26 @@ const template = {
342
348
  {
343
349
  where: where(),
344
350
  oneShot: false,
345
- matchq: (args) => askAbout(args).length > 0,
351
+ matchq: (args) => askAbout(args).length > 0 && args.context.marker == 'controlEnd',
346
352
  applyq: (args) => {
347
353
  args.context.cascade = true
348
354
  const needsDrink = askAbout(args)
355
+ // const details = args.gp({ marker: 'list', value: needsDrink.map((item) => item.food)})
349
356
  if (needsDrink.length > 1) {
350
357
  return `What drinks do you want?`
351
358
  } else {
352
359
  return `What drink do you want?`
353
360
  }
354
361
  },
355
- matchr: (args) => args.isA(args.context.marker, 'drink') && askAbout(args).length > 0,
362
+ matchr: (args) => {
363
+ if (args.isA(args.context.marker, 'drink') && askAbout(args).length > 0) {
364
+ const needsDrink = askAbout(args)
365
+ if (args.api.isAvailableModification(needsDrink[0].food, { ...args.context , id: args.context.value })) {
366
+ return true
367
+ }
368
+ }
369
+ return false
370
+ },
356
371
  applyr: (args) => {
357
372
  // TODO check for is available for all modifications
358
373
  const needsDrink = askAbout(args)
@@ -375,6 +390,31 @@ const template = {
375
390
  ])
376
391
  },
377
392
  {
393
+ operators: [
394
+ "([change] (meal/*) (to/1))",
395
+ ],
396
+ hierarchy: [
397
+ ['meal', 'toAble'],
398
+ ],
399
+ bridges: [
400
+ {
401
+ id: "change",
402
+ isA: ['verby'],
403
+ generatorp: ({context, gp}) => `change ${gp(context.from)} to ${gp(context.to)}`,
404
+ bridge: "{ ...next(operator), from: after[0], to: after[1].toObject }",
405
+ semantic: ({context, api}) => {
406
+ const state = api.state
407
+ for (const item of api.items()) {
408
+ const from = state.getIdCombo(context.from)
409
+ const to = state.getIdCombo(context.to)
410
+ if (item.id == from.id) {
411
+ debugger
412
+ api.modify(item, { id: to.id })
413
+ }
414
+ }
415
+ }
416
+ },
417
+ ],
378
418
  priorities: [
379
419
  { context: [['combo', 0], ['number',1], ['list', 0], ['combo', 0]], ordered: true, choose: [0,1] },
380
420
  { context: [['list', 0], ['combo',0], ['number',1]], ordered: true, choose: [1,2] },
@@ -382,6 +422,12 @@ const template = {
382
422
  { context: [['mango', 0], ['passion',0], ['list', 0]], ordered: true, choose: [0,1] },
383
423
  { context: [['number', 1], ['mango_passion',1], ['list', 0]], ordered: true, choose: [0,1] },
384
424
  { context: [['mango', 0], ['mango_passion',0], ['passion',0], ['list', 0]], ordered: true, choose: [0,1,2] },
425
+
426
+ { context: [['drink', 0], ['list',0], ['combo',0], ['number', 0]], ordered: true, choose: [2,3] },
427
+ { context: [['drink', 1], ['list',0], ['combo',0], ['number', 0]], ordered: true, choose: [2,3] },
428
+ { context: [['withModification', 0], ['modification', 1], ['list', 0], ['modification', 1]], ordered: true, choose: [2] },
429
+ { context: [['withModification', 0], ['modification', 1], ['list', 0], ['combo', 1]], ordered: true, choose: [0] },
430
+ { context: [['combo', 2], ['list', 0], ['combo', 1], ['withModification', 1]], ordered: true, choose: [3] },
385
431
  ],
386
432
  },
387
433
  ],
@@ -392,6 +438,7 @@ class API {
392
438
  this._objects = objects
393
439
  this._objects.items = []
394
440
  this._objects.notAvailable = []
441
+ this._objects.notAvailableModification = []
395
442
  }
396
443
 
397
444
  show() {
@@ -412,6 +459,10 @@ class API {
412
459
  return this._objects.items[item_id]
413
460
  }
414
461
 
462
+ modify(item, changes) {
463
+ Object.assign(this._objects.items[item.item_id], changes)
464
+ }
465
+
415
466
  items() {
416
467
  return this._objects.items
417
468
  }
@@ -430,17 +481,40 @@ class API {
430
481
  return this._objects.notAvailable.length > 0
431
482
  }
432
483
 
484
+ hasAskedForButNotAvailableModification(item) {
485
+ return this._objects.notAvailableModification.length > 0
486
+ }
487
+
433
488
  getAskedForButNotAvailable(item) {
434
489
  const na = this._objects.notAvailable
435
490
  this._objects.notAvailable = []
436
491
  return na
437
492
  }
438
493
 
494
+ getAskedForButNotAvailableModification(item) {
495
+ const na = this._objects.notAvailableModification
496
+ this._objects.notAvailableModification = []
497
+ return na
498
+ }
499
+
439
500
  addAskedForButNotAvailable(item) {
440
501
  this._objects.notAvailable.push(item)
441
502
  }
442
503
 
504
+ addAskedForButNotAvailableModification(item, modification) {
505
+ this._objects.notAvailableModification.push({item, modification})
506
+ }
507
+
508
+ isAvailableModification(food, modification) {
509
+ if (this.isAvailable(modification)) {
510
+ if (this.args.isA(modification.id, 'fry') || this.args.isA(modification.id, 'pop')) {
511
+ return true
512
+ }
513
+ }
514
+ }
515
+
443
516
  isAvailable(item) {
517
+ item.id = item.id || item.value
444
518
  if (item.id == 'chicken_nugget') {
445
519
  if (![4,5,6,10].includes(item.pieces)) {
446
520
  return false
@@ -468,6 +542,10 @@ class API {
468
542
  item.id = 'coca_cola'
469
543
  }
470
544
 
545
+ if (item.id == 'fry') {
546
+ item.id = 'french_fry'
547
+ }
548
+
471
549
  return [
472
550
  "hamburger",
473
551
  "cheeseburger",
@@ -567,17 +645,13 @@ class State {
567
645
  this.api = api
568
646
  }
569
647
 
570
- add(food) {
571
- let quantity = 1
572
- if (food.quantity) {
573
- quantity = food.quantity.value
574
- }
648
+ getIdCombo(food) {
575
649
  let id, combo
576
650
  if (food.comboNumber?.marker == 'numberNumberCombo') {
577
651
  id = this.api.getCombo(food.comboNumber.comboNumber.value)
578
652
  if (!id) {
579
653
  this.api.addAskedForButNotAvailable(food)
580
- return
654
+ return { done: true }
581
655
  }
582
656
  combo = true
583
657
  }
@@ -585,7 +659,7 @@ class State {
585
659
  id = this.api.getCombo(food.comboNumber.value)
586
660
  if (!id) {
587
661
  this.api.addAskedForButNotAvailable(food)
588
- return
662
+ return { done: true }
589
663
  }
590
664
  combo = true
591
665
  } else if (food.marker == 'combo') {
@@ -600,6 +674,20 @@ class State {
600
674
  id = 'chicken_nugget'
601
675
  }
602
676
 
677
+ return { id, combo }
678
+ }
679
+
680
+ add(food) {
681
+ let quantity = 1
682
+ if (food.quantity) {
683
+ quantity = food.quantity.value
684
+ }
685
+
686
+ const { id, combo, done } = this.getIdCombo(food)
687
+ if (done) {
688
+ return
689
+ }
690
+
603
691
  const addSize = (item, data) => {
604
692
  if (item.size) {
605
693
  data.size = item.size.value
@@ -607,15 +695,39 @@ class State {
607
695
  return data
608
696
  }
609
697
 
698
+ const getAvailableChildren = (item) => {
699
+ // see if this is a categories of items
700
+ const descendants = this.api.args.hierarchy.descendants(item.id)
701
+ const available = []
702
+ for (const descendant of descendants) {
703
+ if (this.api.isAvailable({ id: descendant})) {
704
+ available.push(descendant)
705
+ }
706
+ }
707
+ return available
708
+ }
709
+
610
710
  let modifications
711
+ const addsInsteadOfModifications = []
611
712
  if (food.modifications) {
612
713
  modifications = []
613
714
  for (const modification of propertyToArray(food.modifications.modifications)) {
614
715
  if (modification.size) {
615
716
  food.size = modification.size
616
717
  }
617
- addSize(modification, { id: modification.value })
618
- modifications.push(addSize(modification, { id: modification.value }))
718
+
719
+ // if not a modification treat as top level request
720
+ if (!this.api.isAvailableModification(food, { ...modification, id: modification.value })) {
721
+ if (this.api.isAvailable(modification)) {
722
+ //this.add(modification)
723
+ addsInsteadOfModifications.push(modification)
724
+ } else {
725
+ this.api.addAskedForButNotAvailable(modification)
726
+ }
727
+ } else {
728
+ addSize(modification, { id: modification.value })
729
+ modifications.push(addSize(modification, { id: modification.value }))
730
+ }
619
731
  }
620
732
  }
621
733
 
@@ -638,40 +750,8 @@ class State {
638
750
 
639
751
  const item_id = this.api.add(item)
640
752
 
641
- if (false) {
642
- // see if followup for drink is needed
643
-
644
- const hasDrink = (item_id) => {
645
- const item = this.api.get(item_id)
646
- let hasDrink = false
647
- for (let modification of (item.modifications || [])) {
648
- if (!this.api.args.isA(modification.id, 'drink')) {
649
- hasDrink = true
650
- break
651
- }
652
- }
653
- return hasDrink
654
- }
655
- const needsDrink = (item_id) => {
656
- const item = this.api.get(item_id)
657
- return item.needsDrink
658
- }
659
-
660
- if (!hasDrink(item_id) && needsDrink(item_id)) {
661
- this.api.args.ask([
662
- {
663
- where: where(),
664
- matchq: ({objects}) => !hasDrink(item_id) && needsDrink(item_id),
665
- applyq: () => `What drink do you want?`,
666
- matchr: ({context, isA}) => isA(context.marker, 'drink'),
667
- applyr: ({context, objects, api}) => {
668
- // TODO check for is available for all modifications
669
- this.api.addDrink(item_id, { id: context.value })
670
- }
671
- },
672
- ]
673
- )
674
- }
753
+ for (const addIt of addsInsteadOfModifications) {
754
+ this.add(addIt)
675
755
  }
676
756
  }
677
757
  }
@@ -686,7 +766,7 @@ class State {
686
766
  }
687
767
  }
688
768
 
689
- const createConfig = () => {
769
+ const createConfig = (additionalConfig) => {
690
770
  const config = new Config({
691
771
  name: 'fastfood',
692
772
  operators: [
@@ -743,6 +823,9 @@ const createConfig = () => {
743
823
  config.initializer( ({api}) => {
744
824
  api.state = new State(api)
745
825
  })
826
+ if (additionalConfig) {
827
+ additionalConfig(config)
828
+ }
746
829
  config.restart_auto_rebuild()
747
830
  return config
748
831
  }
@@ -751,6 +834,7 @@ knowledgeModule( {
751
834
  module,
752
835
  description: 'fastfood related concepts',
753
836
  createConfig,
837
+ acceptsAdditionalConfig: true,
754
838
  test: {
755
839
  name: './fastfood.test.json',
756
840
  contents: fastfood_tests,