UNPKG

tpmkms

Version:

Reusable libraries for Entodicton, a natural language to json converter

277 lines (261 loc) 8.83 kB
const { knowledgeModule, where } = require('./runtime').theprogrammablemind const { defaultContextCheck, defaultContextCheckProperties } = require('./helpers') const tell = require('./tell') const dimension = require('./dimension') const helpers = require('./helpers') const time_tests = require('./time.test.json') const instance = require('./time.instance.json') function pad(v, l) { const s = String(v) const n = l - s.length return "0".repeat(n) + s } //"what is the time in 24 hour format" //"what time is it in Paris" //"what time is it in GMT" // what is the time // how many hours are in a day class API { // gets the contexts for doing the happening semantics({context, args, kms}) { const api = kms.time.api const values = args({ types: ['ampm', 'time'], properties: ['one', 'two'] }) const ampm = context[values[0]] let hour = ampm.hour.hour if (ampm.ampm == 'pm') { hour += 12; } const ms = helpers.millisecondsUntilHourOfDay(api.newDate, hour) const promise = new Promise((resolve) => { setTimeout( () => resolve(context), ms); }).then( () => context ) context.event = promise } now() { if (this.args.isProcess || this.args.isTest) { return new Date(2025, 5, 29, 14, 52, 0) } else { return new Date() } } async sleep(ms) { if (this.args.isProcess || this.args.isTest) { await this.args.testLog(`sleep(${ms})`) } else { await new Promise(r => setTimeout(r, ms)); } } newDate() { return new Date() } initialize() { } } const template = { configs: [ "years hours minutes milliseconds and seconds are units of time", "hours = minutes / 60", "minutes = hours * 60", "seconds = minutes * 60", "hours = seconds / 3600", "seconds = hours * 3600", "milliseconds = minutes * 60 * 1000", "minutes = milliseconds / 1000 / 60", "milliseconds = seconds * 1000", "seconds = milliseconds / 1000", "minutes = seconds / 60", "day = hours / 24", "hours = days * 24", { operators: [ "([thenTime|then])", "([repeatable])", "(([timePoint]) [ampm|])", "(([integer]) [timeRepeats|] ([timePoint]))", "([atTime|at] (timePoint))", // "([use] (([timeUnit]) [timeFormat|format]))", "([use] (([quantity]) [timeFormat|format]))", "([hourMinutes|] (integer) (colon) (integer))", ], bridges: [ { id: 'repeatable', check: defaultContextCheckProperties(['repeats']) }, { id: 'thenTime', after: ['verb'], }, { id: 'timeRepeats', level: 0, before: ['verb'], convolution: true, bridge: "{ ...next(operator), repeats: before[0], time: after[0], interpolate: [{ property: 'repeats' }, { property: 'time' }] }", check: defaultContextCheckProperties(['time', 'repeats']) }, { id: 'timeRepeats', level: 1, before: ['verb'], bridge: "{ ...repeatable, repeats: operator, checks: append(repeatable.checks, ['repeats']), repeatable: repeatable, interpolate: [{ property: 'repeatable' }, { property: 'repeats', byPosition: true }] }", selector: { loose: "repeatable", arguments: { repeatable: "(@<= 'repeatable')", }, }, check: defaultContextCheckProperties(['time', 'repeats']), }, { id: 'hourMinutes', isA: ['timePoint'], convolution: true, bridge: "{ ...next(operator), hour: after[0], colon: after[1], minute: after[2], interpolate: '${hour}${colon}${minute}' }", }, { id: "timePoint", words: helpers.words('time'), isA: ['noun'], }, { id: "atTime", words: ['@'], isA: ['preposition'], bridge: "{ ...next(operator), time: after[0], operator: operator, interpolate: '${operator} ${time}' }" }, { id: "ampm", isA: ['adjective'], localHierarchy: [ ['integer', 'timePoint'], ], bridge: "{ ...next(before[0]), marker: if(isA(before[0].marker, 'integer'), operator('timePoint'), before[0].marker), ampm: operator, time: before[0], interpolate: concat(default(before[0].interpolate, '${time}'), ' ${ampm}') }", }, { id: "timeFormat", bridge: "{ ...before[0], ...next(operator), interpolate: [ { context: before[0] }, { context: operator } ] }" }, { id: "use", bridge: "{ ...next(operator), format: after[0], interpolate: [{ context: operator }, { property: 'format' }] }", // generatorp: ({g, context}) => `use ${context.format.quantity.value} hour time` }, ], "words": { "literals": { "am": [{id: "ampm", "initial": "{ ampm: 'am', determined: true }" }], "pm": [{id: "ampm", "initial": "{ ampm: 'pm', determined: true }" }], } }, generators: [ { where: where(), match: ({context}) => context.marker == 'timePoint' && context.evalue && context.format == 12, apply: ({context}) => { let hh = context.evalue.getHours(); let ampm = 'am' if (hh > 12) { hh -= 12; ampm = 'pm' } let ss = context.evalue.getMinutes() ss = pad(ss, 2) return `${hh}:${ss} ${ampm}` } }, { where: where(), match: ({context}) => context.marker == 'timePoint' && context.evalue && context.format == 24, apply: ({g, context}) => { function pad(num, size) { num = num.toString(); while (num.length < size) num = "0" + num; return num; } return `${context.evalue.getHours()}:${pad(context.evalue.getMinutes(), 2)}` } }, { where: where(), match: ({context}) => context.marker == 'response', apply: ({g, context}) => context.text }, ], semantics: [ { where: where(), priority: -1, match: (args) => args.callOnce(args, ({context}) => context.repeats) && args.context.repeats?.repeats, apply: async ({context, e, s, handlerStack}) => { const v = (await e(context.repeats.repeats)).evalue for (let i = 0; i < v; ++i) { if (context.action) { await s(context.action) } else { await s({ ...context, repeats: undefined }) } } } }, { notes: 'evaluate time', where: where(), match: ({objects, context, api}) => context.marker == 'timePoint' && context.evaluate, apply: ({objects, context, api}) => { context.evalue = api.newDate() context.format = objects.format } }, { notes: 'use time format working case', where: where(), match: ({objects, context}) => context.marker == 'use' && context.format && (context.format.amount.value == 12 || context.format.amount.value == 24), apply: ({objects, context}) => { objects.format = context.format.amount.value } }, { notes: 'use time format error case', where: where(), match: ({objects, context}) => context.marker == 'use' && context.format && (context.format.amount.value != 12 && context.format.amount.value != 24), apply: ({objects, context}) => { context.marker = 'response' context.text = 'The hour format is 12 hour or 24 hour' } }, ], } ], } function initializer({api, config, objects, kms, isModule}) { if (!isModule) { kms.time.api.newDate = () => new Date("December 25, 1995 1:59:58 pm" ) } Object.assign(objects, { format: 12 // or 24 }); config.addSemantic({ match: ({context, hierarchy, args}) => context.happening && context.marker == 'is' && args({ types: ['ampm', 'time'], properties: ['one', 'two'] }), apply: api.semantics }) } knowledgeModule({ config: { name: 'time' }, includes: [tell, dimension], api: () => new API(), initializer, module, description: 'Time related concepts', test: { name: './time.test.json', contents: time_tests, checks: { context: [ defaultContextCheck({ extra: ['one', 'two', 'events', 'time', 'timePoint', 'ampm'] }) ], } }, instance, template, })