tpmkms 9.8.0 → 9.9.0

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 (95) hide show
  1. package/common/actions.instance.json +10 -8
  2. package/common/actions.js +13 -11
  3. package/common/angle.instance.json +25 -17
  4. package/common/animals.instance.json +54 -28
  5. package/common/askfor.instance.json +89 -192
  6. package/common/askfor.js +49 -12
  7. package/common/asking.js +13 -5
  8. package/common/avatar.js +3 -3
  9. package/common/can.instance.json +32 -20
  10. package/common/can.js +2 -2
  11. package/common/colors.instance.json +44 -16
  12. package/common/colors.js +1 -1
  13. package/common/comparable.instance.json +25 -22
  14. package/common/compass.instance.json +9 -3
  15. package/common/concept.instance.json +14 -6
  16. package/common/concept.js +2 -0
  17. package/common/conjunction.js +17 -9
  18. package/common/control.js +10 -18
  19. package/common/countable.js +4 -3
  20. package/common/crew.instance.json +95 -27
  21. package/common/dateTimeSelectors.instance.json +4 -4
  22. package/common/dateTimeSelectors.js +4 -7
  23. package/common/dates.instance.json +52 -28
  24. package/common/dates.js +16 -11
  25. package/common/debug.instance.json +48 -0
  26. package/common/debug.js +50 -0
  27. package/common/debug.test.json +1 -0
  28. package/common/dialogues.js +126 -70
  29. package/common/dimension.instance.json +239 -495
  30. package/common/dimension.js +51 -9
  31. package/common/drone.instance.json +395 -84
  32. package/common/drone.js +43 -50
  33. package/common/drone_v1.instance.json +36 -12
  34. package/common/drone_v1.js +14 -9
  35. package/common/edible.instance.json +96 -32
  36. package/common/emotions.instance.json +15 -1
  37. package/common/evaluate.js +10 -13
  38. package/common/fastfood.instance.json +282 -100
  39. package/common/fastfood.js +30 -15
  40. package/common/formulas.instance.json +162 -24
  41. package/common/formulas.js +18 -9
  42. package/common/gdefaults.js +20 -96
  43. package/common/helpers/concept.js +2 -9
  44. package/common/helpers/conjunction.js +11 -1
  45. package/common/helpers/dialogues.js +48 -24
  46. package/common/helpers/gdefaults.js +15 -5
  47. package/common/helpers/properties.js +125 -326
  48. package/common/helpers.js +28 -58
  49. package/common/hierarchy.js +71 -41
  50. package/common/kirk.instance.json +3 -1
  51. package/common/latin.instance.json +10 -10
  52. package/common/latin.js +5 -5
  53. package/common/length.instance.json +247 -61
  54. package/common/math.instance.json +144 -5
  55. package/common/math.js +18 -5
  56. package/common/menus.instance.json +29 -11
  57. package/common/menus.js +8 -5
  58. package/common/meta.js +14 -13
  59. package/common/nameable.js +9 -5
  60. package/common/numbers.instance.json +5 -3
  61. package/common/numbers.js +28 -28
  62. package/common/ordering.instance.json +53 -4
  63. package/common/ordinals.js +25 -25
  64. package/common/people.instance.json +66 -12
  65. package/common/percentages.js +4 -2
  66. package/common/pipboy.instance.json +89 -44
  67. package/common/pipboy.js +21 -14
  68. package/common/pokemon.instance.json +39 -13
  69. package/common/pressure.instance.json +14 -6
  70. package/common/properties.instance.json +2370 -511
  71. package/common/properties.js +496 -78
  72. package/common/punctuation.js +1 -0
  73. package/common/rates.instance.json +2 -2
  74. package/common/rates.js +3 -3
  75. package/common/reminders.instance.json +16 -0
  76. package/common/reminders.js +24 -20
  77. package/common/reports.instance.json +11 -12
  78. package/common/reports.js +12 -12
  79. package/common/scorekeeper.js +20 -10
  80. package/common/sdefaults.js +30 -9
  81. package/common/spock.instance.json +3 -1
  82. package/common/stm.js +16 -21
  83. package/common/temperature.instance.json +19 -11
  84. package/common/testing.js +2 -2
  85. package/common/time.instance.json +104 -47
  86. package/common/time.js +9 -8
  87. package/common/ui.instance.json +4 -2
  88. package/common/ui.js +5 -5
  89. package/common/weight.instance.json +86 -21
  90. package/common/weight.js +5 -1
  91. package/common/words.js +113 -2
  92. package/common/wp.instance.json +125 -18
  93. package/common/wp.js +6 -2
  94. package/main.js +2 -0
  95. package/package.json +7 -3
@@ -3,7 +3,7 @@ const { conjugateVerb } = require('../english_helpers')
3
3
  const { unflatten, flattens, Digraph } = require('../runtime').theprogrammablemind
4
4
  const _ = require('lodash')
5
5
  const deepEqual = require('deep-equal')
6
- const { chooseNumber, removeProp } = require('../helpers.js')
6
+ const { chooseNumber } = require('../helpers.js')
7
7
  const { Frankenhash } = require('./frankenhash.js')
8
8
  const { compose, translationMapping, translationMappingToInstantiatorMappings } = require('./meta.js')
9
9
 
@@ -117,9 +117,14 @@ class API {
117
117
  id: edAble.operator,
118
118
  level: 0,
119
119
  localHierarchy,
120
+ isEd: true,
120
121
  bridge: `{
121
122
  ...before,
122
123
  marker: operator('${after[0].tag}'),
124
+ isEdProperties: ['${after[0].tag}', '${before[0].tag}'],
125
+ relationBacked: ${relation ? true : false},
126
+ orderingArgs: ${JSON.stringify(ordering)},
127
+ relationArgs: ${JSON.stringify([...before, ...after])},
123
128
  constraints: [
124
129
  {
125
130
  property: '${after[0].tag}',
@@ -129,95 +134,28 @@ class API {
129
134
  {
130
135
  ...next(operator),
131
136
  constrained: true,
137
+ beforeTag: "${before[0].tag}",
138
+ afterTag: "${after[0].tag}",
132
139
  ${before[0].tag}: default(after[0].object, after[0]),
133
140
  ${after[0].tag}: { ...before[0] }
134
141
  }
135
142
  }
136
143
  ] }`,
137
- deferred: `{ ...next(operator), 'isEd': true, subject: 'ownee', '${after[0].tag}': { operator: operator, number: operator.number, ...before[0] }, ${before[0].tag}: after[0].object }` })
144
+ deferred: `{
145
+ ...next(operator),
146
+ isEd: true,
147
+ subject: 'ownee',
148
+ beforeTag: "${before[0].tag}",
149
+ afterTag: "${after[0].tag}",
150
+ '${after[0].tag}': { operator: operator, number: operator.number, ...before[0] },
151
+ ${before[0].tag}: after[0].object
152
+ }`
153
+ })
138
154
  // TODO have a prepositions category and underPrep category
139
155
  config.addHierarchy(edAble.operator, 'isEdAble')
140
156
  config.addHierarchy(before[0].id, 'isEder')
141
157
  config.addHierarchy(after[0].id, 'isEdee')
142
158
  config.addHierarchy('isEdee', 'queryable')
143
- config.addSemantic({
144
- notes: 'semantic for setting value with constraint',
145
- match: ({context, isA}) => isA(context.marker, after[0].tag) && context.evaluate && context.constraints,
146
- // match: ({context, isA}) => context.marker == after[0].tag && context.evaluate,
147
- apply: async ({km, context, e, log, isA}) => {
148
- const constraint = context.constraints[0];
149
- const value = constraint.constraint;
150
- let property = constraint.property;
151
- const properties = constraint.properties;
152
- for (const p of properties) {
153
- if (value[p].concept) {
154
- property = p
155
- constraint.property = p; // set what is used
156
- }
157
- }
158
- // value.marker = 'owns'
159
- // value.greg = true
160
- // value.ownee.query = true
161
- value.query = true
162
- const instance = await e(value)
163
- if (instance.verbatim) {
164
- context.evalue = { verbatim: instance.verbatim }
165
- return
166
- }
167
- if (instance.evalue.marker == 'answerNotKnown') {
168
- context.evalue = instance.evalue
169
- return
170
- }
171
- const selected = instance.evalue.value.map( (r) => r[property] )
172
- context.constraints = undefined;
173
- context.evalue = { marker: 'list', listable: true, value: selected }
174
- },
175
- })
176
- config.addGenerator({
177
- notes: 'generator for constraint',
178
- match: ({context}) => context.marker == edAble.operator && context.paraphrase && context.constrained,
179
- apply: async ({context, g}) => {
180
- if (context[before[0].tag].marker == 'by') {
181
- // the cat wendy owned
182
- return `${await g({...context[after[0].tag], paraphrase: true})} ${edAble.word} ${await g({...context[before[0].tag], paraphrase: true})}`
183
- } else {
184
- // the cat owned by wendy
185
- return `${await g({...context[after[0].tag], paraphrase: true})} ${edAble.word} ${['by', await g({...context[before[0].tag], paraphrase: true})].filter((t) => t).join(' ')}`
186
- }
187
- },
188
- })
189
- config.addGenerator({
190
- match: ({context}) => {
191
- if (context.marker == operator && context.paraphrase) {
192
- if (context['do']) {
193
- const left = context['do'].left
194
- if (context[left]) {
195
- // who owns X should not be 'does who own x' but instead 'who owns x'
196
- if (context[left].query) {
197
- return true;
198
- }
199
- }
200
- }
201
- }
202
-
203
- return false;
204
- },
205
- apply: async ({context, g}) => {
206
- const chosen = chooseNumber(context, word.singular, word.plural)
207
- return `${await g(context[before[0].tag])} ${chosen} ${await g(context[after[0].tag])}`
208
- }
209
- })
210
- config.addGenerator({
211
- match: ({context}) => context.marker == edAble.operator && context.isEd,
212
- apply: async ({context, g}) => {
213
- const chosen = chooseNumber(context[after[0].tag], 'is', 'are')
214
- if (context[before[0].tag].evalue && context[before[0].tag].evalue.marker == 'answerNotKnown') {
215
- return await g(context[before[0].tag])
216
- }
217
- return `${await g(context[after[0].tag])} ${chosen} ${edAble.word} by ${await g(context[before[0].tag])}`
218
- }
219
- })
220
-
221
159
  {
222
160
  const whoIsWhatVerbedBy = `${before[0].tag}var is ${after[0].tag}var ${edAble.word} by`
223
161
  const thisIsVerbedByThat = `${after[0].tag}var is ${edAble.word} by ${before[0].tag}var`
@@ -226,25 +164,16 @@ class API {
226
164
  // config.addFragments([whoIsWhatVerbedBy])
227
165
  config.addFragments([
228
166
  whoIsWhatVerbedBy,
229
- {
230
- /*
231
- hierarchy: [
232
- ['owneevar', 'ownee']
233
- ],
234
- */
235
- query: thisIsVerbedByThat
236
- },
167
+ thisIsVerbedByThat,
237
168
  ])
238
169
 
239
- // config.addHierarchy({ child: 'owneeVar', parent: 'isEdee', maybe: true})
240
- // config.addHierarchy({ child: 'ownerVar', parent: 'isEder', maybe: true})
241
- // config.addFragments([`${before[0].tag}Var is ${after[0].tag}Var ${edAble.word} by`, `${after[0].tag}Var is ${edAble.word} by ${before[0].tag}Var`])
242
- // config.addFragments(["ownerVar is owneeVar owned by", "owneeVar is owned by ownerVar"])
243
-
244
170
  const generator = {
245
171
  notes: `generator for who/what is X owned by`,
246
- // match: ({context, hierarchy}) => hierarchy.isA(context.marker, 'is') && context.one && context.one.marker == 'ownee' && context.one.constraints && context.one.constraints[0] && context.one.constraints[0].constraint.marker == 'owned' && context.one.constraints[0].constraint.owner.implicit,
247
- match: ({context, hierarchy}) => hierarchy.isA(context.marker, 'is') && context.one && context.one.marker == after[0].tag && context.one.constraints && context.one.constraints[0] && context.one.constraints[0].constraint.marker == edAble.operator && context.one.constraints[0].constraint[before[0].tag].implicit,
172
+ match: ({context, hierarchy}) =>
173
+ hierarchy.isA(context.marker, 'is') &&
174
+ context.one?.isEdProperties &&
175
+ context.one?.constraints[0].constraint.beforeTag &&
176
+ context.one?.constraints[0].constraint[context.one.constraints[0].constraint.beforeTag].implicit,
248
177
  apply: async ({context, fragments, g, gs, callId}) => {
249
178
  const isToFromM = [{"from":["one"],"to":["two"]},{"from":["two"],"to":["one"]}]
250
179
  const fromF = (await fragments(whoIsWhatVerbedBy)).contexts()[0]
@@ -259,7 +188,6 @@ class API {
259
188
  '[{"from":["two"],"to":["owner"]},{"from":["one"],"to":["ownee"]},{"from":["number"],"to":["number"]}]'
260
189
  */
261
190
  const tmPrime = compose(isToFromM, tm)
262
- // const from = context.one.constraints[0].constraint
263
191
  const from = context
264
192
  const im = translationMappingToInstantiatorMappings(tmPrime, from, to)
265
193
  const translation = await toF.instantiate(im)
@@ -291,7 +219,7 @@ class API {
291
219
  config,
292
220
  localHierarchy=[],
293
221
  relation,
294
- ordering,
222
+ ordering={},
295
223
  doAble,
296
224
  flatten,
297
225
  can,
@@ -343,23 +271,12 @@ class API {
343
271
  config.addOperator({ pattern: `(${beforeOperators} [${operator}|] ${afterOperators})`, allowDups: true })
344
272
  }
345
273
 
346
- if (false) {
347
- for (const argument of before.concat(after)) {
348
- if (create.includes(argument.id)) {
349
- // config.addHierarchy('unknown', argument.id)
350
- // config.addHierarchy('what', argument.id)
351
- config.addHierarchy(argument.id, 'unknown')
352
- config.addHierarchy(argument.id, 'what')
353
- }
354
- }
355
- } else {
356
- for (const argument of before.concat(after)) {
357
- if (create.includes(argument.id)) {
358
- // config.addHierarchy(argument.id, 'unknown')
359
- // config.addHierarchy(argument.id, 'what')
360
- localHierarchy.push([argument.id, 'unknown'])
361
- localHierarchy.push([argument.id, 'what'])
362
- }
274
+ for (const argument of before.concat(after)) {
275
+ if (create.includes(argument.id)) {
276
+ // config.addHierarchy(argument.id, 'unknown')
277
+ // config.addHierarchy(argument.id, 'what')
278
+ localHierarchy.push([argument.id, 'unknown'])
279
+ localHierarchy.push([argument.id, 'what'])
363
280
  }
364
281
  }
365
282
 
@@ -404,7 +321,20 @@ class API {
404
321
  id: operator,
405
322
  level: 0,
406
323
  localHierarchy: [...localHierarchy, ['object', 'unknown']],
407
- bridge: `{ ... next(operator) ${flattenProperty} ${doParams} ${beforeArgs} ${afterArgs}, operator: { ...operator, evaluateWord: true, imperative: ${imperative}, isVerb: true, number: 'one' }, unflatten: ${JSON.stringify(unflattenArgs)}, focusable: ${JSON.stringify(focusable)}, interpolate: ${interpolate} }`,
324
+ bridge: `{
325
+ ...next(operator)
326
+ ${flattenProperty}
327
+ ${doParams}
328
+ ${beforeArgs}
329
+ ${afterArgs},
330
+ relationBacked: ${relation ? true : false},
331
+ orderingArgs: ${JSON.stringify(ordering)},
332
+ relationArgs: ${JSON.stringify([...before, ...after])},
333
+ operator: { ...operator, evaluateWord: true, imperative: ${imperative}, isVerb: true, number: 'one' },
334
+ unflatten: ${JSON.stringify(unflattenArgs)},
335
+ focusable: ${JSON.stringify(focusable)},
336
+ interpolate: ${interpolate}
337
+ }`,
408
338
  allowDups: true
409
339
  })
410
340
  if (words.length > 0) {
@@ -462,201 +392,12 @@ class API {
462
392
  config.addAssociation({ context: [[afterIds[0], 1], ['canPassive', 0], ['beCanPassive', 0], [operator, 0], ['byCanPassive', 0], [beforeIds[0], 0]], choose: 1 })
463
393
  }
464
394
 
465
- if (false) {
466
- config.addGenerator({
467
- notes: 'ordering generator for paraphrase',
468
- match: ({context}) => context.marker == operator && context.paraphrase && !context.query,
469
- apply: async ({context, gp, g}) => {
470
- const beforeGenerator = []
471
- for (const arg of before) {
472
- beforeGenerator.push(await g(context[arg.tag]))
473
- }
474
- const afterGenerator = []
475
- for (const arg of after) {
476
- afterGenerator.push(await gp(context[arg.tag]))
477
- }
478
- const word = context.word
479
- const sub = []
480
- if (context.subphrase) {
481
- sub.push(['that'])
482
- }
483
- return beforeGenerator.concat(sub).concat([word]).concat(afterGenerator).join(' ')
484
- }
485
- })
486
- }
487
-
488
- if (true) {
489
- config.addGenerator({
490
- notes: 'ordering generator for response',
491
- match: ({context}) => context.marker == operator && context.evalue && context.isResponse,
492
- apply: async ({context, s, g, km, flatten}) => {
493
- const brief = km("dialogues").api.getBrief()
494
-
495
- let { evalue } = context
496
- let yesno = ''
497
- let hasVariables = false
498
- if (context.focusable) {
499
- for (const f of context.focusable) {
500
- if (context[f].query) {
501
- hasVariables = true
502
- break
503
- }
504
- }
505
- }
506
-
507
- // if (!context.do?.query || evalue.truthValueOnly || context.truthValueOnly || brief) {
508
- if (evalue.truthValueOnly || context.truthValueOnly || context.wantsTruthValue || !hasVariables) {
509
- function any(value, test) {
510
- if (test(value)) {
511
- return true
512
- }
513
- const values = flatten(['list'], value)
514
- for (const value of values) {
515
- if (test(value)) {
516
- return true
517
- }
518
- }
519
- }
520
- if (any(evalue, (value) => value.truthValue)) {
521
- yesno = 'yes'
522
- } else if (evalue.truthValue === false || context.truthValueOnly) {
523
- yesno = 'no'
524
- }
525
- }
526
- if (evalue.truthValueOnly) {
527
- return `${yesno}`
528
- } else {
529
- if (context.voice) {
530
- evalue = await s({ ...evalue, toVoice: context.voice, flatten: false})
531
- }
532
-
533
- const details = await g(Object.assign({}, evalue, { paraphrase: true }))
534
- if (yesno) {
535
- return `${yesno} ${details}`
536
- }
537
- else {
538
- return details
539
- }
540
- }
541
- }
542
- })
543
- }
544
-
545
- if (ordering) {
546
- config.addSemantic({
547
- notes: 'ordering setter',
548
- // TODO use hierarchy for operator
549
- match: ({context}) => context.marker == operator,
550
- apply: ({context, km}) => {
551
- //const api = km('ordering').api
552
- // api.setCategory(ordering.name, context[ordering.object].value, context[ordering.category].value, context)
553
- const propertiesAPI = km('properties').api
554
- context.ordering = ordering.name
555
- const fcontexts = flattens(['list'], [context])
556
- for (const fcontext of fcontexts) {
557
- fcontext.paraphrase = true
558
- fcontext[ordering.object].paraphrase = true
559
- fcontext[ordering.category].paraphrase = true
560
- }
561
- propertiesAPI.relation_add(fcontexts)
562
- }
563
- })
564
- config.addSemantic({
565
- notes: 'ordering query',
566
- match: ({context}) => context.marker == operator && context.query,
567
- apply: ({context, km}) => {
568
- const api = km('ordering').api
569
- const propertiesAPI = km('properties').api
570
- context.ordering = ordering.name
571
- const matches = propertiesAPI.relation_get(context, ['ordering', ordering.object, ordering.category])
572
- if (matches.length > 0 || (typeof context.query == 'boolean' && context.query)) {
573
- // does greg like bananas
574
- if (matches.length == 0) {
575
- const response = _.clone(context)
576
- response.isResponse = true
577
- response.query = undefined
578
- context.evalue = { marker: 'list', listable: true, value: [response] }
579
- } else {
580
- context.evalue = { marker: 'list', listable: true, value: unflatten(matches) }
581
- context.evalue.isResponse = true
582
- }
583
- context.evalue.truthValue = matches.length > 0
584
- context.evalue.truth = { marker: 'yesno', value: matches.length > 0, isResponse: true, focus: true }
585
- context.evalue.focusable = ['truth']
586
- if (!context.evalue.truthValue) {
587
- context.evalue.truthValueOnly = true
588
- }
589
-
590
- // ADD this line back and remove it to check
591
- // context.response = { marker: 'list', listable: true, value: [response], isResponse: true }
592
- // Object.assign(context, { marker: 'list', listable: true, value: responses, focusable: ['value'], paraphrase: true, truthValue: matches.length > 0 })
593
- } else {
594
- // see if anything is preferred greg
595
- // what does greg like
596
- const matches = propertiesAPI.relation_get(context, ['ordering', ordering.object])
597
- if (matches.length == 0) {
598
- // Object.assign(context, { marker: 'idontknow', query: _.clone(context) })
599
- context.evalue = { marker: 'idontknow', query: _.clone(context), isResponse: true }
600
- } else {
601
- context.evalue = { marker: 'list', listable: true, value: matches, isResponse: true }
602
- }
603
- context.isResponse = true
604
- context.evalue.truthValue = matches.length > 0 && matches[0].marker == ordering.marker
605
- }
606
- }
607
- })
608
- }
609
-
610
395
  if (ordering || relation || doAble) {
611
396
  config.addHierarchy(operator, 'canBeQuestion')
612
397
  config.addHierarchy(operator, 'ifAble')
613
398
  config.addHierarchy(operator, 'orAble')
614
399
  }
615
400
 
616
- if (relation) {
617
- config.addSemantic({
618
- notes: `setter for ${operator}`,
619
- match: ({context}) => context.marker == operator && !context.toVoice,
620
- apply: ({context, km, hierarchy, config}) => {
621
- const api = km('properties').api
622
- // add types for arguments
623
- for (const argument of context.focusable || []) {
624
- const value = api.toValue(context[argument])
625
- if (value) {
626
- const minimas = hierarchy.minima(context[argument].types)
627
- for (const type of minimas) {
628
- if (config.exists(value)) {
629
- config.addHierarchy(value, type);
630
- }
631
- }
632
- }
633
- }
634
- api.relation_add(context)
635
- }
636
- })
637
- config.addSemantic({
638
- notes: `getter for ${operator}`,
639
- match: ({context}) => context.marker == operator && context.query,
640
- apply: ({context, km, callId}) => {
641
- const api = km('properties').api
642
- context.evalue = {
643
- marker: 'list',
644
- listable: true,
645
- value: unflatten(api.relation_get(context, before.concat(after).map( (arg) => arg.tag ) ))
646
- }
647
- context.evalue.isResponse = true
648
- context.isResponse = true
649
- if (context.evalue.value.length == 0) {
650
- context.evalue.marker = 'answerNotKnown';
651
- context.evalue.listable = true
652
- context.evalue.value = [];
653
- } else {
654
- // context.evalue.truthValue = true
655
- }
656
- }
657
- })
658
- }
659
-
660
401
  if (semanticApply) {
661
402
  config.addSemantic({
662
403
  notes: `override semantic apply for ${operator}`,
@@ -675,8 +416,6 @@ class API {
675
416
  }
676
417
 
677
418
  relation_add (relations) {
678
- removeProp(relations, (val, prop, obj) => prop === 'range')
679
-
680
419
  if (!Array.isArray(relations)) {
681
420
  relations = [relations]
682
421
  }
@@ -725,6 +464,64 @@ class API {
725
464
  return value
726
465
  }
727
466
 
467
+ async relation_unify_helper (args, template, value) {
468
+ const matches = (t, v) => {
469
+ if (typeof t == 'string' || typeof v == 'string') {
470
+ return t == v
471
+ }
472
+
473
+ if (!t || !v) {
474
+ return null
475
+ }
476
+
477
+ if (t.query) {
478
+ return true
479
+ }
480
+
481
+ if (t.concept) {
482
+ // const api = args.km('properties').api
483
+ if (v.unknown && !t.value) {
484
+ return true;
485
+ }
486
+ return this.isA(v.value, t.value)
487
+ }
488
+
489
+ /* wtf
490
+ if (!t.value && !v.value) {
491
+ return this.isA(v.value, t.value);
492
+ }
493
+ */
494
+
495
+ return t.value && v.value && t.value == v.value
496
+ }
497
+
498
+ for (const arg of args) {
499
+ const u = await this.args.unify(template[arg], value[arg])
500
+ if (u) {
501
+ continue
502
+ }
503
+ if (!matches(template[arg], value[arg])) {
504
+ return null
505
+ }
506
+ }
507
+ return value
508
+ }
509
+
510
+ async relation_unify (context, args) {
511
+ const andTheAnswerIs = []
512
+ for (const relation of this._objects.relations) {
513
+ if (await this.relation_unify_helper(args, context, relation)) {
514
+ const queriedArgs = args.filter( (arg) => context[arg].query )
515
+ if (queriedArgs.length == 1) {
516
+ relation[queriedArgs[0]] = { ...relation[queriedArgs[0]], focus: true }
517
+ }
518
+
519
+ andTheAnswerIs.push(Object.assign({}, relation, { paraphrase: true }))
520
+ }
521
+ }
522
+ return andTheAnswerIs
523
+ }
524
+
728
525
  relation_get (context, args) {
729
526
  const andTheAnswerIs = []
730
527
  for (const relation of this._objects.relations) {
@@ -747,7 +544,7 @@ class API {
747
544
  }
748
545
  }
749
546
  */
750
-
547
+ /*
751
548
  setShared(path, handler) {
752
549
  if (!handler) {
753
550
  handler = new Object({
@@ -763,6 +560,7 @@ class API {
763
560
  this.propertiesFH.setInitHandler( { path, handler } )
764
561
  return handler
765
562
  }
563
+ */
766
564
 
767
565
  setReadOnly(path) {
768
566
  const handler = new Object({
@@ -778,12 +576,6 @@ class API {
778
576
  this.propertiesFH.setHandler(path, handler)
779
577
  }
780
578
 
781
- /*
782
- async getObject(object) {
783
- return this.propertiesFH.getValue([object])
784
- }
785
- */
786
-
787
579
  getHandler(object, property) {
788
580
  return this.propertiesFH.getHandler([object, property])
789
581
  }
@@ -798,23 +590,23 @@ class API {
798
590
  return this._km("stm").api.getVariable(context) || context.value;
799
591
  }
800
592
 
801
- async getProperty(object, property, g) {
593
+ async getProperty(object, property) {
802
594
  object = this.toValue(object)
803
595
  property = this.toValue(property)
804
596
  const handler = this.propertiesFH.getHandler([object, property])
805
597
  if (handler) {
806
598
  return await handler.getValue([object, property])
807
599
  }
808
- return await this.getPropertyDirectly(object, property, g)
600
+ return await this.getPropertyDirectly(object, property)
809
601
  }
810
602
 
811
- async getPropertyDirectly(object, property, g) {
603
+ async getPropertyDirectly(object, property) {
812
604
  if (property == 'property') {
813
605
  const objectProps = await this.propertiesFH.getValue([object])
814
606
  const values = []
815
607
  for (const key of Object.keys(objectProps)) {
816
608
  if (objectProps[key].has) {
817
- values.push(`${await g(key)}: ${await g({ ...objectProps[key].value, paraphrase: true })}`)
609
+ values.push({ marker: 'labelledValue', label: key, value: objectProps[key].value, useColon: true })
818
610
  }
819
611
  }
820
612
  return { marker: 'list', listable: true, value: values }
@@ -828,27 +620,34 @@ class API {
828
620
  }
829
621
 
830
622
  setProperty(object, property, value, has, skipHandler) {
623
+ const objectId = object.value
624
+ const propertyId = property.value
625
+
831
626
  if (!skipHandler) {
832
- const handler = this.propertiesFH.getHandler([object, property])
627
+ const handler = this.propertiesFH.getHandler([objectId, propertyId])
833
628
  if (handler) {
834
- return handler.setValue([object, property], value, has)
629
+ return handler.setValue([objectId, propertyId], value, has)
835
630
  }
836
631
  }
837
- this.propertiesFH.setValue([object, property], value, has)
632
+ this.propertiesFH.setValue([objectId, propertyId], value, has)
633
+
838
634
  if (has && value) {
839
- let values = this._objects.property[property] || []
635
+ let values = this._objects.property[propertyId] || []
840
636
  if (!values.includes(value)) {
841
637
  values = values.concat(value)
842
638
  }
843
- this._objects.property[property] = values
844
- // this._objects.property[property] = (this.objects.property[property] || []).concat(value)
639
+ this._objects.property[propertyId] = values
640
+ // this._objects.property[propertyId] = (this.objects.property[propertyId] || []).concat(value)
845
641
  // "mccoy's rank is doctor",
846
642
  // infer doctor is a type of rank
847
- this.rememberIsA(value.value, property);
643
+ this.rememberIsA(value.value, propertyId);
848
644
  }
849
- if (!this._objects.concepts.includes(object)) {
850
- this._objects.concepts.push(pluralize.singular(object))
645
+
646
+ if (!this._objects.concepts.includes(objectId)) {
647
+ this._objects.concepts.push(pluralize.singular(objectId))
851
648
  }
649
+
650
+ this.relation_add({ marker: 'propertyRelation', object, property, value, focusable: ['object', 'property', 'value'] })
852
651
  }
853
652
 
854
653
  async knownObject(object) {