tpmkms
Version:
Reusable libraries for Entodicton, a natural language to json converter
206 lines (191 loc) • 6.44 kB
JavaScript
const { knowledgeModule, where, Digraph } = require('./runtime').theprogrammablemind
const { defaultContextCheck } = require('./helpers')
const hierarchy = require('./hierarchy.js')
const formulas = require('./formulas.js')
const testing = require('./testing.js')
const tests = require('./dimension.test.json')
const instance = require('./dimension.instance.json')
/*
x celcius equals x*9/5 + 32 fahrenheit
x fahrenheit equals (x-32)*5/9 + 32 fahrenheit
10 celcius + 5
10 C
use a digraph for calculating convertions
can you convert between all units of length
configure the conversions for length
"square kilometers" is a phrase
for weight what can you convert between
what can you convert between for weight
what is the conversion between pounds and kilograms
*/
class API {
initialize({ config }) {
this._config = config
}
setup( {dimension, units} ) {
const config = this._config
// for example, setup temperature concept
config.addOperator(`([${dimension}])`)
config.addBridge({
id: dimension,
isA: ['dimension'],
generatorp: async ({context, g}) => context.amount ? `${await g(context.amount)} ${await g(context.unit)}` : context.word,
})
// for example, celcius and fahrenheit
for (const unit of units) {
config.addOperator(`([${unit}])`)
config.addBridge({
id: unit,
isA: ['unit'],
})
}
}
}
const api = new API()
const config = {
name: 'dimension',
operators: [
"([dimension])",
"([unit])",
// "(([unit]) [kindOfDimension|of] ([dimension]))",
"((amount/1 || number/1) [amountOfDimension|] ([unit]))",
"(([amount]) [unit])",
"((dimension/1) [convertToUnits|in] (unit/1))",
"(([number]) [degree])",
{ pattern: "([length])", development: true },
],
priorities: [
// TODO this should have been calculated
{ "context": [['amountOfDimension', 0], ['convertToUnits', 0], ], "choose": [0] },
],
hierarchy: [
{ child: 'convertToUnits', parent: 'testingValue', development: true },
],
generators: [
{
where: where(),
match: ({context}) => context.marker == 'noconversion',
apply: async ({context, gp}) => `there is no conversion between ${await gp(context.from)} and ${await gp(context.to)}`,
},
],
bridges: [
{
where: where(),
id: "dimension",
bridge: "{ ...next(operator) }",
isA: [],
generatorpr: {
match: ({context}) => context.amount,
apply: async ({context, gp, gr}) => `${await gr(context.amount)} ${await gp(context.unit)}`,
},
},
{
id: "length",
isA: ['dimension'],
bridge: "{ ...next(operator) }",
development: true
},
{ id: "amount", },
/*
{
id: "kindOfDimension",
bridge: "{ ...next(operator), subclass: before[0], class: after[0], value: concat(before[0].marker.id, after[0].marker.id) }",
// bridge: "{ ...next(operator), subclass: before[0], class: after[0], value: concat(before[0].marker, after[0].marker) }",
isA: ['preposition'],
generatorp: ({context, gp}) => `${gp(context.subclass)} ${context.word} ${gp(context.class)}`,
},
*/
{
where: where(),
id: "degree",
words: [{ word: 'degrees', number: 'many' }],
isA: ['amount'],
generatorp: async ({context, g}) => (context.amount) ? `${await g(context.amount)} ${context.word}` : context.word,
bridge: "{ ...next(operator), value: before[0].value, amount: before[0] }",
},
{
id: "amountOfDimension",
convolution: true,
bridge: "{ marker: operator('dimension'), unit: after[0], value: before[0].value, amount: before[0] }"
},
{
where: where(),
id: "convertToUnits",
bridge: "{ ...next(operator), from: before[0], to: after[0] }",
isA: ['expression', 'queryable'],
localHierarchy: [['unknown', 'dimension']],
after: [['possession', 0], ['possession', 1]],
generatorp: async ({context, g}) => `${await g(context.from)} ${context.word} ${await g(context.to)}`,
// evaluator: ({context, kms, error}) => {
evaluator: async ({context, kms, e, error}) => {
/*
error(({context, e}) => {
context.evalue = 'dont know...'
})
*/
const from = context.from;
const to = context.to;
let evalue;
let efrom = from
if (!from.unit) {
efrom = (await e(from)).evalue
}
if (to.value == efrom.unit.value) {
evalue = efrom.amount
} else {
const formula = kms.formulas.api.get(to, [efrom.unit])
if (!formula) {
const reason = { marker: 'reason', focusableForPhrase: true, evalue: { marker: 'noconversion', from: efrom.unit, to } }
kms.stm.api.mentioned({ context: reason })
error(reason)
}
kms.stm.api.setVariable(efrom.unit.value, efrom.amount)
evalue = await e(formula)
}
/*
'{
"marker":"dimension",
"unit":{"marker":"unit","range":{"start":19,"end":25},"word":"celcius","text":"celcius","value":"celcius","unknown":true,"types":["unit","unknown"]},
"value":10,
"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"]}},
"text":"10 degrees celcius","range":{"start":8,"end":25}}'
*/
context.evalue = {
paraphrase: true,
marker: 'dimension',
level: 1,
unit: to,
amount: { evalue, paraphrase: undefined }
}
},
},
{
id: "unit",
isA: ['number'],
},
],
};
const template = {
configs: [
"dimension and unit are concepts",
config,
],
}
knowledgeModule({
config: { name: 'dimension' },
includes: [hierarchy, formulas, testing],
api: () => new API(),
module,
description: 'Used to define numeric temperature such as currency, temperature or weight',
template: { template, instance },
test: {
name: './dimension.test.json',
contents: tests,
checks: {
objects: [{ km: 'properties' }],
checks: {
context: defaultContextCheck(),
},
},
},
})