tpmkms
Version:
Reusable libraries for Entodicton, a natural language to json converter
207 lines (184 loc) • 8.79 kB
JavaScript
const pluralize = require('pluralize')
const deepEqual = require('deep-equal')
const { chooseNumber, zip } = require('../helpers.js')
const { compose, translationMapping, translationMappingToInstantiatorMappings } = require('./meta.js')
class API {
initialize({ objects }) {
this._objects = objects
this._objects.valueToWords = []
this._objects.defaultTypesForHierarchy = new Set([])
}
addDefaultTypesForObjectHierarchy(types) {
for (const type of types) {
this._objects.defaultTypesForHierarchy.add(type)
}
}
setupObjectHierarchy(config, id, { include_concept=true } = {}) {
const types = [...this._objects.defaultTypesForHierarchy]
if (include_concept) {
types.push('concept');
}
for (const type of types) {
config.addHierarchy(id, type)
}
}
// for example, "crew member" or "photon torpedo"
// TODO account for modifier a complex phrase for example "hot (chicken strips)"
kindOfConcept({ config, modifiers, object }) {
// TODO make the modifiers objects then below for add words for modifiers only do if !unknown
// const objectId = pluralize.singular(object)
const objectId = this.args.kms.dialogues.api.toScopedId(object)
// const modifierIds = modifiers.map( (modifier) => pluralize.singular(modifier) )
const modifierIds = modifiers.map( (modifier) => this.args.kms.dialogues.api.toScopedId(modifier) )
const modifiersObjectId = `${modifierIds.join("_")}_${objectId}`
const toWord = (object) => {
if (typeof object == 'string') {
return object
}
return object.text
}
const objectWord = toWord(object)
// const objectWord = object
// TODO call evaluator to pick up overrides
const objectSingular = pluralize.singular(objectWord)
const objectPlural = pluralize.plural(objectWord)
// config.addOperator({ pattern: `(${modifierIds.map((modifierId) => `(${modifierId}/*)`).join(' ')} [${modifiersObjectId}] (${objectId}/0))`, allowDups: true })
if (false) {
config.addOperator({ pattern: `(${modifierIds.map((modifierId) => `(${modifierId}/*)`).join(' ')} [${modifiersObjectId}] (${objectId}/*))`, allowDups: true })
} else {
config.addOperator({ pattern: `(${modifierIds.map((modifierId) => `(@==${modifierId})`).join(' ')} [${modifiersObjectId}] (@==${objectId}))`, allowDups: true })
}
// config.addOperator({ pattern: `(<${modifierId}|> ([${objectId}|]))`, allowDups: true })
// config.addOperator({ pattern: `([${modifierObjectId}|])`, allowDups: true })
const objectModifierConcept = `${objectId}_modifier`
if (!config.exists(objectModifierConcept)) {
config.addOperator({ pattern: `([${objectModifierConcept}|])`, allowDups: true })
config.addBridge({ id: objectModifierConcept, bridge: `{ ...next(operator) }`, allowDups: true })
}
modifierIds.forEach((modifierId) => {
if (!config.exists(modifierId)) {
config.addOperator({ pattern: `([${modifierId}|])`, allowDups: true })
}
config.addHierarchy(modifierId, objectModifierConcept)
config.addHierarchy(objectModifierConcept, 'adjective')
})
if (!config.exists(objectId)) {
config.addOperator({ pattern: `([${objectId}|])`, allowDups: true })
}
if (object.unknown || object.marker !== objectId) {
config.addWord(objectSingular, { id: objectId, initial: `{ value: '${objectId}', number: 'one' }`})
config.addWord(objectPlural, { id: objectId, initial: `{ value: '${objectId}', number: 'many' }`})
}
zip(modifiers, modifierIds).forEach(([modifier, modifierId]) => {
// config.addWord(modifier, { id: modifierId, initial: `{ value: '${modifierId}' }`})
// TODO call evaluator to pick up overrides
if (modifier.unknown) {
const modifierWord = modifier.word
if (pluralize.isSingular(modifierWord)) {
config.addWord(pluralize.singular(modifierWord), { id: modifierId, initial: `{ value: '${modifierId}', number: 'one' }`})
}
if (pluralize.isPlural(modifierWord)) {
config.addWord(pluralize.plural(modifierWord), { id: modifierId, initial: `{ value: '${modifierId}', number: 'many' }`})
}
}
})
// modifierds.forEach((modifierId) => config.addWord(modifierId, { id: modifierId, initial: `{ value: '${modifierId}' }`}))
modifierIds.forEach((modifierId) => config.addBridge({ id: modifierId, level: 0, bridge: `{ ...next(operator), value: or(operator.value, '${modifierId}') }`, allowDups: true }))
config.addBridge({ id: objectId, level: 0, bridge: `{ ...next(operator), value: '${objectId}' }`, allowDups: true })
// config.addBridge({ id: modifierObjectId, level: 0, bridge: `{ ...next(operator), value: '${modifierObjectId}' }`, allowDups: true })
const modifierProperties = modifierIds.map((modifierId, index) => `'modifier_${modifierId}': before[${index}]`).join(', ')
const modifierList = modifierIds.map((modifierId) => `'modifier_${modifierId}'`).join(', ')
config.addBridge({
id: modifiersObjectId,
level: 0,
convolution: true,
isA: [{ parent: 'adjective', instance: true }],
// isA: ['adjective'],
before: ['verb'],
bridge: `{ ...after[0], ${modifierProperties}, atomic: true, dead: true, marker: next(operator('${modifiersObjectId}')), value: '${modifiersObjectId}', modifiers: append([${modifierList}], after[0].modifiers)}`,
allowDups: true })
{
const word = {
"marker": modifiersObjectId,
"modifiers": modifierIds,
"types": [
modifiersObjectId,
],
"value": modifiersObjectId,
"word": objectId,
}
modifierIds.forEach((modifierId) => {
word[modifierId] = {
"marker": modifierId,
"value": modifierId,
"word": modifierId,
}
})
this.addWord(word)
}
this.setupObjectHierarchy(config, objectId);
modifierIds.forEach((modifierId) => this.setupObjectHierarchy(config, modifierId, { include_concept: false }))
this.setupObjectHierarchy(config, modifiersObjectId);
if (config.getBridge('hierarchyAble')) {
config.addHierarchy(objectId, 'hierarchyAble')
config.addHierarchy(modifiersObjectId, 'hierarchyAble')
}
config.addHierarchy(modifiersObjectId, objectId)
modifierIds.forEach((modifierId) => config.addPriority({ "context": [[modifierId, 0], ['article', 0]], "choose": [0] }))
config.addPriority({ "context": [[objectId, 0], ['article', 0], ], "choose": [0] })
// maybe remove the next line
modifierIds.forEach((modifierId) => config.addPriority({ context: [[modifiersObjectId, 0], [modifierId, 0], ], generalize: false, choose: [0] }))
config.addPriority({ "context": [[modifiersObjectId, 0], [objectId, 0], ], choose: [0] })
config.addPriority({ context: [['list', 0]].concat(modifierIds.map((id) => [id, 0])).concat([[objectId, 0]]), ordered: true, choose: [1,2] })
if (config.exists('number')) {
// config.addPriority({ context: [['list', 0], ['number', 0]].concat(modifierIds.map((id) => [id, 0])).concat([[objectId, 0]]), ordered: true, choose: [2,3] })
if (modifierIds.length > 1) {
const choose = []
for (let i = 0; i < modifierIds.length; ++i) {
choose.push(i+2)
}
config.addPriority({ context: [['list', 0], ['number', 0]].concat(modifierIds.map((id) => [id, 0])).concat([[objectId, 0]]), ordered: true, choose })
}
config.addPriority({ context: [['list', 0], ['number', 1], [modifiersObjectId, 1]], ordered: true, choose: [1,2] })
}
}
addWord(context) {
if (!context || !context.value || !context.word) {
return
}
this.addWordToValue(context.value, context)
}
addWordToValue(value, word) {
if (!this._objects.valueToWords[value]) {
this._objects.valueToWords[value] = []
}
word = Object.assign({}, word)
delete word.evalue
word.paraphrase = true
if (this._objects.valueToWords[value].some( (entry) => deepEqual(entry, word) )) {
return
}
const words = this._objects.valueToWords[value]
if (!words.includes(word)) {
words.push(word)
}
}
getWordForValue(value, { number } = {}) {
let context;
if (!this._objects.valueToWords[value]) {
context = { marker: value, value: value, number, word: value, paraphrase: true }
} else {
context = this._objects.valueToWords[value][0]
}
if (context.word) {
context.word = (number == 'many') ? pluralize.plural(context.word) : pluralize.singular(context.word)
}
return context
}
getWordsForValue(value) {
return this._objects.valueToWords[value]
}
}
module.exports = {
API
}