ekms 9.6.0-beta.14 → 9.6.0-beta.15

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.
@@ -57,7 +57,7 @@
57
57
  "verb",
58
58
  "article"
59
59
  ],
60
- "bridge": "{ ...next(before[0]), property: after, postModifiers: append([after[0].marker], before[0].modifiers), [after[0].marker.id]: after[0] }"
60
+ "bridge": "{ ...after, condition: before[0], property: after[0], interpolate: [{ property: 'condition' }, { property: 'property' }] }"
61
61
  },
62
62
  {
63
63
  "id": "comparable",
@@ -5364,7 +5364,7 @@
5364
5364
  "verb",
5365
5365
  "article"
5366
5366
  ],
5367
- "bridge": "{ ...next(before[0]), property: after, postModifiers: append([after[0].marker], before[0].modifiers), [after[0].marker.id]: after[0] }"
5367
+ "bridge": "{ ...after, condition: before[0], property: after[0], interpolate: [{ property: 'condition' }, { property: 'property' }] }"
5368
5368
  },
5369
5369
  {
5370
5370
  "id": "comparable",
@@ -24,6 +24,8 @@
24
24
  "(([amount]) [unit])",
25
25
  "((@<=quantity || context.possession == true) [convertToUnits|in] (unit))",
26
26
  "(([number]) [degree])",
27
+ "([useUnits|use] (unit))",
28
+ "([preferredUnits] (quantity))",
27
29
  {
28
30
  "pattern": "([length])",
29
31
  "scope": "testing"
@@ -61,11 +63,29 @@
61
63
  ],
62
64
  "bridges": [
63
65
  {
64
- "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:104",
66
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:198",
67
+ "id": "preferredUnits",
68
+ "isA": [
69
+ "verb"
70
+ ],
71
+ "bridge": "{ ...next(operator), quantity: after[0], operator: operator, interpolate: [{ property: 'operator' }, { property: 'quantity' }] }",
72
+ "semantic": "async ({context, e, api, toArray, resolveResponse}) => {\n const preferredUnits = api.getPreferredUnits(context.quantity)\n if (!preferredUnits) {\n return\n }\n const from = context.quantity;\n const value = await e({ marker: 'convertToUnits', from, to: preferredUnits })\n resolveResponse(context, value.evalue)\n }"
73
+ },
74
+ {
75
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:213",
76
+ "id": "useUnits",
77
+ "isA": [
78
+ "verb"
79
+ ],
80
+ "bridge": "{ ...next(operator), units: after[0], operator: operator, interpolate: [{ property: 'operator' }, { property: 'units' }] }",
81
+ "semantic": "({context, api}) => {\n api.setPreferredUnits(context.units)\n }"
82
+ },
83
+ {
84
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:222",
65
85
  "id": "dimension"
66
86
  },
67
87
  {
68
- "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:108",
88
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:226",
69
89
  "id": "quantity",
70
90
  "isA": [
71
91
  "noun"
@@ -86,7 +106,7 @@
86
106
  "id": "amount"
87
107
  },
88
108
  {
89
- "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:123",
109
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:241",
90
110
  "id": "degree",
91
111
  "words": [
92
112
  {
@@ -106,7 +126,7 @@
106
126
  "bridge": "{ marker: next(operator('quantity')), dead: true, unit: after[0], amount: before[0] }"
107
127
  },
108
128
  {
109
- "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:137",
129
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:255",
110
130
  "id": "convertToUnits",
111
131
  "bridge": "{ ...next(operator), from: before[0], to: after[0] }",
112
132
  "isA": [
@@ -130,7 +150,7 @@
130
150
  ]
131
151
  ],
132
152
  "generatorp": "async ({context, g}) => `${await g(context.from)} ${context.word} ${await g(context.to)}`",
133
- "evaluator": "async ({context, kms, e, error, toArray, gp, gr, toList}) => {\n const from = context.from;\n const tos = toArray(context.to);\n let evalue;\n let efrom = from\n if (!from.unit) {\n efrom = (await e(from)).evalue\n }\n async function convert(to) {\n if (to.value == efrom.unit.value) {\n evalue = efrom.amount\n evalue.evalue = efrom.amount.value\n } else {\n const formula = kms.formulas.api.get(to, [efrom.unit])\n if (!formula) {\n const reason = { marker: 'reason', focusableForPhrase: true, evalue: { marker: 'noconversion', from: efrom.unit, to } }\n kms.stm.api.mentioned({ context: reason })\n error(reason)\n }\n kms.stm.api.setVariable(efrom.unit.value, efrom.amount)\n evalue = await e(formula)\n }\n return evalue\n }\n\n let evalues = []\n for (const to of tos) {\n evalues.push({ value: await convert(to), to: structuredClone(to) })\n }\n evalues.sort((a, b) => a.evalue - b.evalue )\n\n let fractionalPart = 0\n let scale = 1\n for (const evalue of evalues) {\n const value = toFinalValue(evalue) * scale\n const integerPart = Math.trunc(value)\n fractionalPart = Math.abs(value - integerPart)\n evalue.value.evalue = integerPart\n scale = fractionalPart / value * scale\n }\n // evalues[evalues.length-1].value.evalue = Number((integerPart * (1+scale)).toFixed(4))\n evalues[evalues.length-1].value.evalue += fractionalPart\n evalues[evalues.length-1].value.evalue = Number(evalues[evalues.length-1].value.evalue.toFixed(4))\n\n // remove the zeros\n evalues = evalues.filter( (evalue) => evalue.value.evalue )\n\n /*\n '{\n \"marker\":\"dimension\",\n \"unit\":{\"marker\":\"unit\",\"range\":{\"start\":19,\"end\":25},\"word\":\"celcius\",\"text\":\"celcius\",\"value\":\"celcius\",\"unknown\":true,\"types\":[\"unit\",\"unknown\"]},\n \"value\":10,\n \"amount\":{\"word\":\"degrees\",\"number\":\"many\",\"text\":\"10 degrees\",\"marker\":\"degree\",\"range\":{\"start\":8,\"end\":17},\"value\":10,\"amount\":{\"value\":10,\"text\":\"10\",\"marker\":\"number\",\"word\":\"10\",\"range\":{\"start\":8,\"end\":9},\"types\":[\"number\"]}},\n \"text\":\"10 degrees celcius\",\"range\":{\"start\":8,\"end\":25}}'\n */\n evalues = evalues.map((evalue) => {\n const number = evalue.value.evalue == 1 ? 'one' : 'many'\n evalue.to.number = number\n return { \n paraphrase: true,\n marker: 'quantity',\n level: 1,\n unit: evalue.to,\n amount: { evalue: evalue.value, paraphrase: undefined }\n }\n })\n if (evalues.length > 1) {\n context.evalue = toList(evalues)\n } else {\n context.evalue = evalues[0]\n }\n }"
153
+ "evaluator": "async ({context, api, toArray, resolveEvaluate}) => {\n const from = context.from;\n const tos = toArray(context.to);\n resolveEvaluate(context, await api.convertToUnits(context, from, tos))\n }"
134
154
  },
135
155
  {
136
156
  "id": "unit",
@@ -22678,6 +22698,8 @@
22678
22698
  "(([amount]) [unit])",
22679
22699
  "((@<=quantity || context.possession == true) [convertToUnits|in] (unit))",
22680
22700
  "(([number]) [degree])",
22701
+ "([useUnits|use] (unit))",
22702
+ "([preferredUnits] (quantity))",
22681
22703
  {
22682
22704
  "pattern": "([length])",
22683
22705
  "scope": "testing"
@@ -22709,16 +22731,32 @@
22709
22731
  ],
22710
22732
  "generators": [
22711
22733
  {
22712
- "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:97"
22734
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:191"
22713
22735
  }
22714
22736
  ],
22715
22737
  "bridges": [
22716
22738
  {
22717
- "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:104",
22739
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:198",
22740
+ "id": "preferredUnits",
22741
+ "isA": [
22742
+ "verb"
22743
+ ],
22744
+ "bridge": "{ ...next(operator), quantity: after[0], operator: operator, interpolate: [{ property: 'operator' }, { property: 'quantity' }] }"
22745
+ },
22746
+ {
22747
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:213",
22748
+ "id": "useUnits",
22749
+ "isA": [
22750
+ "verb"
22751
+ ],
22752
+ "bridge": "{ ...next(operator), units: after[0], operator: operator, interpolate: [{ property: 'operator' }, { property: 'units' }] }"
22753
+ },
22754
+ {
22755
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:222",
22718
22756
  "id": "dimension"
22719
22757
  },
22720
22758
  {
22721
- "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:108",
22759
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:226",
22722
22760
  "id": "quantity",
22723
22761
  "isA": [
22724
22762
  "noun"
@@ -22737,7 +22775,7 @@
22737
22775
  "id": "amount"
22738
22776
  },
22739
22777
  {
22740
- "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:123",
22778
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:241",
22741
22779
  "id": "degree",
22742
22780
  "words": [
22743
22781
  {
@@ -22756,7 +22794,7 @@
22756
22794
  "bridge": "{ marker: next(operator('quantity')), dead: true, unit: after[0], amount: before[0] }"
22757
22795
  },
22758
22796
  {
22759
- "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:137",
22797
+ "where": "/home/dev/code/theprogrammablemind/kms/common/dimension.js:255",
22760
22798
  "id": "convertToUnits",
22761
22799
  "bridge": "{ ...next(operator), from: before[0], to: after[0] }",
22762
22800
  "isA": [
@@ -35,6 +35,26 @@ class API {
35
35
  initialize({ config, objects }) {
36
36
  this._config = config
37
37
  this._objects = objects
38
+ objects.preferredUnits = []
39
+ }
40
+
41
+ getPreferredUnits(quantity) {
42
+ for (const unit of this._objects.preferredUnits) {
43
+ if (quantity.unit.marker == 'unitPerUnit') {
44
+ if (quantity.unit.numerator.dimension == unit.numerator.dimension &&
45
+ quantity.unit.denominator.dimension == unit.denominator.dimension) {
46
+ return unit
47
+ }
48
+ } else if (unit.dimension) {
49
+ if (unit.dimension == quantity.unit.dimension) {
50
+ return unit
51
+ }
52
+ }
53
+ }
54
+ }
55
+
56
+ setPreferredUnits(units) {
57
+ this._objects.preferredUnits.unshift(units)
38
58
  }
39
59
 
40
60
  setMeasurementSystem(measurementSystem) {
@@ -69,6 +89,78 @@ class API {
69
89
  })
70
90
  }
71
91
  }
92
+
93
+ async convertToUnits(context, from, tos) {
94
+ const {kms, e, error, toArray, gp, gr, toList} = this.args
95
+ let evalue;
96
+ let efrom = from
97
+ if (!from.unit) {
98
+ efrom = (await e(from)).evalue
99
+ }
100
+ async function convert(to) {
101
+ if (to.value == efrom.unit.value) {
102
+ evalue = efrom.amount
103
+ evalue.evalue = efrom.amount.value
104
+ } else {
105
+ const formula = kms.formulas.api.get(to, [efrom.unit])
106
+ if (!formula) {
107
+ const reason = { marker: 'reason', focusableForPhrase: true, evalue: { marker: 'noconversion', from: efrom.unit, to } }
108
+ kms.stm.api.mentioned({ context: reason })
109
+ error(reason)
110
+ }
111
+ kms.stm.api.setVariable(efrom.unit.value, efrom.amount)
112
+ evalue = await e(formula)
113
+ }
114
+ return evalue
115
+ }
116
+
117
+ let evalues = []
118
+ for (const to of tos) {
119
+ evalues.push({ value: await convert(to), to: structuredClone(to) })
120
+ }
121
+ evalues.sort((a, b) => a.evalue - b.evalue )
122
+
123
+ let fractionalPart = 0
124
+ let scale = 1
125
+ for (const evalue of evalues) {
126
+ const value = toFinalValue(evalue) * scale
127
+ const integerPart = Math.trunc(value)
128
+ fractionalPart = Math.abs(value - integerPart)
129
+ evalue.value.evalue = integerPart
130
+ scale = fractionalPart / value * scale
131
+ }
132
+ // evalues[evalues.length-1].value.evalue = Number((integerPart * (1+scale)).toFixed(4))
133
+ evalues[evalues.length-1].value.evalue += fractionalPart
134
+ evalues[evalues.length-1].value.evalue = Number(evalues[evalues.length-1].value.evalue.toFixed(4))
135
+
136
+ // remove the zeros
137
+ evalues = evalues.filter( (evalue) => evalue.value.evalue )
138
+
139
+ /*
140
+ '{
141
+ "marker":"dimension",
142
+ "unit":{"marker":"unit","range":{"start":19,"end":25},"word":"celcius","text":"celcius","value":"celcius","unknown":true,"types":["unit","unknown"]},
143
+ "value":10,
144
+ "amount":{"word":"degrees","number":"many","text":"10 degrees","marker":"degree","range":{"start":8,"end":17},"value":10,"amount":{"value":10,"text":"10","marker":"number","word":"10","range":{"start":8,"end":9},"types":["number"]}},
145
+ "text":"10 degrees celcius","range":{"start":8,"end":25}}'
146
+ */
147
+ evalues = evalues.map((evalue) => {
148
+ const number = evalue.value.evalue == 1 ? 'one' : 'many'
149
+ evalue.to.number = number
150
+ return {
151
+ paraphrase: true,
152
+ marker: 'quantity',
153
+ level: 1,
154
+ unit: evalue.to,
155
+ amount: { evalue: evalue.value, paraphrase: undefined }
156
+ }
157
+ })
158
+ if (evalues.length > 1) {
159
+ return toList(evalues)
160
+ } else {
161
+ return evalues[0]
162
+ }
163
+ }
72
164
  }
73
165
 
74
166
  // eg, dimension == length; meters == unit; 2 meters == quantity
@@ -83,6 +175,8 @@ const config = {
83
175
  "((@<=quantity || context.possession == true) [convertToUnits|in] (unit))",
84
176
 
85
177
  "(([number]) [degree])",
178
+ "([useUnits|use] (unit))",
179
+ "([preferredUnits] (quantity))",
86
180
  { pattern: "([length])", scope: "testing" },
87
181
  ],
88
182
  priorities: [
@@ -100,6 +194,30 @@ const config = {
100
194
  },
101
195
  ],
102
196
  bridges: [
197
+ {
198
+ where: where(),
199
+ id: "preferredUnits",
200
+ isA: ['verb'],
201
+ bridge: "{ ...next(operator), quantity: after[0], operator: operator, interpolate: [{ property: 'operator' }, { property: 'quantity' }] }",
202
+ semantic: async ({context, e, api, toArray, resolveResponse}) => {
203
+ const preferredUnits = api.getPreferredUnits(context.quantity)
204
+ if (!preferredUnits) {
205
+ return
206
+ }
207
+ const from = context.quantity;
208
+ const value = await e({ marker: 'convertToUnits', from, to: preferredUnits })
209
+ resolveResponse(context, value.evalue)
210
+ }
211
+ },
212
+ {
213
+ where: where(),
214
+ id: "useUnits",
215
+ isA: ['verb'],
216
+ bridge: "{ ...next(operator), units: after[0], operator: operator, interpolate: [{ property: 'operator' }, { property: 'units' }] }",
217
+ semantic: ({context, api}) => {
218
+ api.setPreferredUnits(context.units)
219
+ }
220
+ },
103
221
  {
104
222
  where: where(),
105
223
  id: "dimension",
@@ -142,77 +260,10 @@ const config = {
142
260
  after: [['possession', 0], ['possession', 1]],
143
261
  generatorp: async ({context, g}) => `${await g(context.from)} ${context.word} ${await g(context.to)}`,
144
262
  // evaluator: ({context, kms, error}) => {
145
- evaluator: async ({context, kms, e, error, toArray, gp, gr, toList}) => {
263
+ evaluator: async ({context, api, toArray, resolveEvaluate}) => {
146
264
  const from = context.from;
147
265
  const tos = toArray(context.to);
148
- let evalue;
149
- let efrom = from
150
- if (!from.unit) {
151
- efrom = (await e(from)).evalue
152
- }
153
- async function convert(to) {
154
- if (to.value == efrom.unit.value) {
155
- evalue = efrom.amount
156
- evalue.evalue = efrom.amount.value
157
- } else {
158
- const formula = kms.formulas.api.get(to, [efrom.unit])
159
- if (!formula) {
160
- const reason = { marker: 'reason', focusableForPhrase: true, evalue: { marker: 'noconversion', from: efrom.unit, to } }
161
- kms.stm.api.mentioned({ context: reason })
162
- error(reason)
163
- }
164
- kms.stm.api.setVariable(efrom.unit.value, efrom.amount)
165
- evalue = await e(formula)
166
- }
167
- return evalue
168
- }
169
-
170
- let evalues = []
171
- for (const to of tos) {
172
- evalues.push({ value: await convert(to), to: structuredClone(to) })
173
- }
174
- evalues.sort((a, b) => a.evalue - b.evalue )
175
-
176
- let fractionalPart = 0
177
- let scale = 1
178
- for (const evalue of evalues) {
179
- const value = toFinalValue(evalue) * scale
180
- const integerPart = Math.trunc(value)
181
- fractionalPart = Math.abs(value - integerPart)
182
- evalue.value.evalue = integerPart
183
- scale = fractionalPart / value * scale
184
- }
185
- // evalues[evalues.length-1].value.evalue = Number((integerPart * (1+scale)).toFixed(4))
186
- evalues[evalues.length-1].value.evalue += fractionalPart
187
- evalues[evalues.length-1].value.evalue = Number(evalues[evalues.length-1].value.evalue.toFixed(4))
188
-
189
- // remove the zeros
190
- evalues = evalues.filter( (evalue) => evalue.value.evalue )
191
-
192
- /*
193
- '{
194
- "marker":"dimension",
195
- "unit":{"marker":"unit","range":{"start":19,"end":25},"word":"celcius","text":"celcius","value":"celcius","unknown":true,"types":["unit","unknown"]},
196
- "value":10,
197
- "amount":{"word":"degrees","number":"many","text":"10 degrees","marker":"degree","range":{"start":8,"end":17},"value":10,"amount":{"value":10,"text":"10","marker":"number","word":"10","range":{"start":8,"end":9},"types":["number"]}},
198
- "text":"10 degrees celcius","range":{"start":8,"end":25}}'
199
- */
200
- evalues = evalues.map((evalue) => {
201
- const number = evalue.value.evalue == 1 ? 'one' : 'many'
202
- evalue.to.number = number
203
- return {
204
- paraphrase: true,
205
- marker: 'quantity',
206
- level: 1,
207
- unit: evalue.to,
208
- amount: { evalue: evalue.value, paraphrase: undefined }
209
- }
210
- })
211
- if (evalues.length > 1) {
212
- context.evalue = toList(evalues)
213
- } else {
214
- context.evalue = evalues[0]
215
- }
266
+ resolveEvaluate(context, await api.convertToUnits(context, from, tos))
216
267
  },
217
268
  },
218
269
  {
@@ -286,6 +337,7 @@ knowledgeModule({
286
337
  objects: [
287
338
  { km: 'properties' },
288
339
  { path: ['measurementSystem'] },
340
+ { path: ['preferredUnits'] },
289
341
  ],
290
342
  context: [
291
343
  defaultContextCheck({ marker: 'metric_system', exported: true }),