tpmkms_4wp 9.3.0-beta.3 → 9.3.0-beta.30

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 (53) hide show
  1. package/common/animals.instance.json +0 -65
  2. package/common/colors.instance.json +28 -70
  3. package/common/comparable.instance.json +0 -15
  4. package/common/concept.test.json +279 -193
  5. package/common/crew.instance.json +0 -166
  6. package/common/dateTimeSelectors.instance.json +67 -0
  7. package/common/dateTimeSelectors.js +85 -0
  8. package/common/dateTimeSelectors.test.json +4529 -0
  9. package/common/dates.instance.json +136 -27
  10. package/common/dates.js +13 -0
  11. package/common/dates.test.json +1787 -0
  12. package/common/dialogues.js +5 -2
  13. package/common/dimension.instance.json +0 -5
  14. package/common/edible.instance.json +56 -160
  15. package/common/emotions.instance.json +0 -5
  16. package/common/evaluate.js +1 -1
  17. package/common/events.js +1 -1
  18. package/common/fastfood.instance.json +228 -727
  19. package/common/fastfood.test.json +16291 -6597
  20. package/common/formulas.instance.json +0 -5
  21. package/common/helpers/dateTimeSelectors.js +80 -0
  22. package/common/helpers/dialogues.js +3 -7
  23. package/common/helpers.js +24 -7
  24. package/common/kirk.instance.json +0 -5
  25. package/common/length.instance.json +0 -75
  26. package/common/math.instance.json +0 -5
  27. package/common/menus.instance.json +0 -35
  28. package/common/numbers.js +1 -1
  29. package/common/numbers.test.json +89 -23
  30. package/common/ordering.instance.json +0 -10
  31. package/common/people.instance.json +0 -40
  32. package/common/percentages.js +1 -1
  33. package/common/pipboy.instance.json +56 -85
  34. package/common/pipboy.test.json +4377 -3386
  35. package/common/pokemon.instance.json +0 -65
  36. package/common/pressure.instance.json +0 -20
  37. package/common/properties.instance.json +0 -5
  38. package/common/reminders.instance.json +105 -6
  39. package/common/reminders.js +171 -44
  40. package/common/reminders.test.json +44724 -19
  41. package/common/reports.instance.json +2 -12
  42. package/common/scorekeeper.test.json +3565 -7550
  43. package/common/spock.instance.json +0 -5
  44. package/common/temperature.instance.json +0 -20
  45. package/common/time.js +63 -30
  46. package/common/time.test.json +4124 -124
  47. package/common/ui.instance.json +0 -5
  48. package/common/ui.js +3 -1
  49. package/common/weight.instance.json +0 -60
  50. package/common/wp.instance.json +56 -70
  51. package/common/wp.test.json +8057 -3867
  52. package/main.js +2 -0
  53. package/package.json +8 -4
@@ -72,11 +72,6 @@
72
72
  "article",
73
73
  false
74
74
  ],
75
- [
76
- "evaluate",
77
- "verb",
78
- false
79
- ],
80
75
  [
81
76
  "every",
82
77
  "article",
@@ -619,11 +614,6 @@
619
614
  "article",
620
615
  false
621
616
  ],
622
- [
623
- "evaluate",
624
- "verb",
625
- false
626
- ],
627
617
  [
628
618
  "every",
629
619
  "article",
@@ -1495,11 +1485,6 @@
1495
1485
  "article",
1496
1486
  false
1497
1487
  ],
1498
- [
1499
- "evaluate",
1500
- "verb",
1501
- false
1502
- ],
1503
1488
  [
1504
1489
  "every",
1505
1490
  "article",
@@ -2991,11 +2976,6 @@
2991
2976
  "article",
2992
2977
  false
2993
2978
  ],
2994
- [
2995
- "evaluate",
2996
- "verb",
2997
- false
2998
- ],
2999
2979
  [
3000
2980
  "every",
3001
2981
  "article",
@@ -3838,11 +3818,6 @@
3838
3818
  "article",
3839
3819
  false
3840
3820
  ],
3841
- [
3842
- "evaluate",
3843
- "verb",
3844
- false
3845
- ],
3846
3821
  [
3847
3822
  "every",
3848
3823
  "article",
@@ -4775,11 +4750,6 @@
4775
4750
  "article",
4776
4751
  false
4777
4752
  ],
4778
- [
4779
- "evaluate",
4780
- "verb",
4781
- false
4782
- ],
4783
4753
  [
4784
4754
  "every",
4785
4755
  "article",
@@ -5892,11 +5862,6 @@
5892
5862
  "type",
5893
5863
  false
5894
5864
  ],
5895
- [
5896
- "evaluate",
5897
- "verb",
5898
- false
5899
- ],
5900
5865
  [
5901
5866
  "every",
5902
5867
  "article",
@@ -7099,11 +7064,6 @@
7099
7064
  "type",
7100
7065
  false
7101
7066
  ],
7102
- [
7103
- "evaluate",
7104
- "verb",
7105
- false
7106
- ],
7107
7067
  [
7108
7068
  "every",
7109
7069
  "article",
@@ -8620,11 +8580,6 @@
8620
8580
  "type",
8621
8581
  false
8622
8582
  ],
8623
- [
8624
- "evaluate",
8625
- "verb",
8626
- false
8627
- ],
8628
8583
  [
8629
8584
  "every",
8630
8585
  "article",
@@ -10146,11 +10101,6 @@
10146
10101
  "type",
10147
10102
  false
10148
10103
  ],
10149
- [
10150
- "evaluate",
10151
- "verb",
10152
- false
10153
- ],
10154
10104
  [
10155
10105
  "every",
10156
10106
  "article",
@@ -11682,11 +11632,6 @@
11682
11632
  "type",
11683
11633
  false
11684
11634
  ],
11685
- [
11686
- "evaluate",
11687
- "verb",
11688
- false
11689
- ],
11690
11635
  [
11691
11636
  "every",
11692
11637
  "article",
@@ -13223,11 +13168,6 @@
13223
13168
  "type",
13224
13169
  false
13225
13170
  ],
13226
- [
13227
- "evaluate",
13228
- "verb",
13229
- false
13230
- ],
13231
13171
  [
13232
13172
  "every",
13233
13173
  "article",
@@ -14729,11 +14669,6 @@
14729
14669
  "type",
14730
14670
  false
14731
14671
  ],
14732
- [
14733
- "evaluate",
14734
- "verb",
14735
- false
14736
- ],
14737
14672
  [
14738
14673
  "every",
14739
14674
  "article",
@@ -243,11 +243,6 @@
243
243
  "article",
244
244
  false
245
245
  ],
246
- [
247
- "evaluate",
248
- "verb",
249
- false
250
- ],
251
246
  [
252
247
  "every",
253
248
  "article",
@@ -1675,11 +1670,6 @@
1675
1670
  "article",
1676
1671
  false
1677
1672
  ],
1678
- [
1679
- "evaluate",
1680
- "verb",
1681
- false
1682
- ],
1683
1673
  [
1684
1674
  "every",
1685
1675
  "article",
@@ -3635,11 +3625,6 @@
3635
3625
  "article",
3636
3626
  false
3637
3627
  ],
3638
- [
3639
- "evaluate",
3640
- "verb",
3641
- false
3642
- ],
3643
3628
  [
3644
3629
  "every",
3645
3630
  "article",
@@ -5311,11 +5296,6 @@
5311
5296
  "article",
5312
5297
  false
5313
5298
  ],
5314
- [
5315
- "evaluate",
5316
- "verb",
5317
- false
5318
- ],
5319
5299
  [
5320
5300
  "every",
5321
5301
  "article",
@@ -59,11 +59,6 @@
59
59
  "article",
60
60
  false
61
61
  ],
62
- [
63
- "evaluate",
64
- "verb",
65
- false
66
- ],
67
62
  [
68
63
  "every",
69
64
  "article",
@@ -2,41 +2,140 @@
2
2
  "configs": [
3
3
  {
4
4
  "operators": [
5
- "([remind] (self/*) (*)*)"
5
+ "([remindable])",
6
+ {
7
+ "pattern": "([addRemindable] (word)*)",
8
+ "development": true
9
+ },
10
+ "([remind] (remindable/*) (!@<= 'dateTimeSelector')*)",
11
+ "([remind:withDateBridge] (remindable/*) (!@<= 'dateTimeSelector')* (dateTimeSelector))",
12
+ "([remind:withDateAndTimeBridge] (remindable/*) (!@<= 'dateTimeSelector')* (dateTimeSelector) (atTime))",
13
+ "([show] ([reminders]))",
14
+ "([delete_reminders|delete,cancel] (number/*))"
6
15
  ],
7
16
  "bridges": [
17
+ {
18
+ "id": "addRemindable",
19
+ "isA": [
20
+ "verb"
21
+ ],
22
+ "development": true,
23
+ "bridge": "{ ...next(operator), arg: after[0], operator: operator, interpolate: '${operator} ${arg}' }",
24
+ "semantic": "({api, context}) => {\n const name = context.arg.map( (word) => word.text ).join(' ')\n api.addRemindable(name)\n }"
25
+ },
26
+ {
27
+ "id": "remindable"
28
+ },
8
29
  {
9
30
  "id": "remind",
10
31
  "isA": [
11
32
  "verb"
12
33
  ],
34
+ "localHierarchy": [
35
+ [
36
+ "self",
37
+ "remindable"
38
+ ]
39
+ ],
13
40
  "bridge": "{ ...next(operator), operator: operator, who: after[0], reminder: after[1], interpolate: '${operator} ${who} ${reminder}' }",
14
- "semantic": "async ({api, gsp, context}) => {\n const text = await gsp(context.reminder.slice(1));\n api.add({ text });\n }"
41
+ "withDateBridge": "{ ...next(operator), operator: operator, who: after[0], reminder: after[1], date: after[2], interpolate: '${operator} ${who} ${reminder} ${date}' }",
42
+ "withDateAndTimeBridge": "{ ...next(operator), operator: operator, who: after[0], reminder: after[1], date: after[2], time: after[3], interpolate: '${operator} ${who} ${reminder} ${date} ${time}' }",
43
+ "semantic": "async ({api, gsp, gp, context}) => {\n const text = await gsp(context.reminder.slice(1));\n const who = { id: context.who.value || context.who.text, text: context.who.text }\n const reminder = { text, dateTimeSelector: context.date, who }\n if (context.date) {\n reminder.dateTimeSelector = context.date\n reminder.dateTimeSelectorText = await gp(context.date)\n }\n // await api.instantiate(reminder)\n await api.add(reminder)\n }"
44
+ },
45
+ {
46
+ "id": "reminders",
47
+ "isA": [
48
+ "noun"
49
+ ]
50
+ },
51
+ {
52
+ "id": "show",
53
+ "isA": [
54
+ "verb"
55
+ ],
56
+ "bridge": "{ ...next(operator), operator: operator, reminders: after[0], interpolate: '${operator} ${reminders}' }",
57
+ "semantic": "({context, api, verbatim}) => {\n verbatim(api.show())\n }"
58
+ },
59
+ {
60
+ "id": "delete_reminders",
61
+ "isA": [
62
+ "verb"
63
+ ],
64
+ "bridge": "{ ...next(operator), operator: operator, reminders: after[0], interpolate: '${operator} ${reminders}' }",
65
+ "semantic": "({context, api, verbatim}) => {\n const s = api.delete_reminder(context.reminders.value)\n if (s) {\n verbatim(s)\n }\n }"
15
66
  }
16
67
  ]
17
68
  },
18
69
  {
19
- "apply": "({ask, api}) => {\n ask([\n {\n where: where(),\n oneShot: false,\n onNevermind: ({verbatim, ...args}) => {\n // this is cross km boundaries from the dialogues km to this one so the api if for dialogs.\n // i need to get the one for fastfood here.\n const api = args.kms.fastfood.api\n const needsDrink = askAbout({ args, api })\n for (const item of needsDrink) {\n api.remove(item)\n }\n },\n\n matchq: (args) => args.api.askAbout(args).length > 0 && args.context.marker == 'controlEnd',\n applyq: (args) => {\n args.context.cascade = false\n const items = askAbout(args)\n const item = items[0]\n debugger;\n debugger\n },\n\n matchr: (args) => {\n if (args.isA(args.context.marker, 'drink') && askAbout(args).length > 0) {\n const needsDrink = askAbout(args)\n if (args.api.isAvailableModification(needsDrink[0].food, { ...args.context , id: args.context.value })) {\n return true\n }\n }\n return false\n },\n applyr: (args) => {\n // TODO check for is available for all modifications\n const needsDrink = askAbout(args)\n const { api, context } = args\n if (isMany(context)) {\n let count = getCount(context) || Number.MAX_SAFE_INTEGER\n for (const item of needsDrink) {\n if (count < 1) {\n break\n }\n count -= 1\n api.addDrink(item.item_id, { id: context.value })\n }\n } else {\n const item_id = needsDrink[0].item_id\n api.addDrink(item_id, { id: context.value })\n }\n }\n },\n ])\n }"
70
+ "apply": "({ask, api}) => {\n ask([\n {\n where: where(),\n oneShot: false,\n onNevermind: ({verbatim, ...args}) => {\n // this is cross km boundaries from the dialogues km to this one so the api if for dialogs.\n // i need to get the one for fastfood here.\n const api = args.kms.fastfood.api\n const needsDrink = askAbout({ args, api })\n for (const item of needsDrink) {\n api.remove(item)\n }\n },\n\n matchq: ({ api, context }) => api.askAbout().length > 0 && context.marker == 'controlEnd',\n applyq: ({ api, context }) => {\n context.cascade = false\n const items = api.askAbout()\n const item = items[0]\n return 'When should I remind you to ' + item.text;\n },\n\n matchr: ({ isA, api, context }) => {\n if ((isA(context.marker, 'onDateValue_dates') || isA(context.marker, 'dateTimeSelector')) && api.askAbout().length > 0) {\n return true\n }\n return false\n },\n applyr: async ({ context, api, gp }) => {\n const items = api.askAbout()\n await api.update({ id: items[0].id, dateTimeSelector: context, dateTimeSelectorText: await gp(context) })\n }\n },\n ])\n }"
20
71
  }
21
72
  ],
22
73
  "resultss": [
23
74
  {
24
75
  "extraConfig": true,
25
76
  "operators": [
26
- "([remind] (self/*) (*)*)"
77
+ "([remindable])",
78
+ {
79
+ "pattern": "([addRemindable] (word)*)",
80
+ "development": true
81
+ },
82
+ "([remind] (remindable/*) (!@<= 'dateTimeSelector')*)",
83
+ "([remind:withDateBridge] (remindable/*) (!@<= 'dateTimeSelector')* (dateTimeSelector))",
84
+ "([remind:withDateAndTimeBridge] (remindable/*) (!@<= 'dateTimeSelector')* (dateTimeSelector) (atTime))",
85
+ "([show] ([reminders]))",
86
+ "([delete_reminders|delete,cancel] (number/*))"
27
87
  ],
28
88
  "bridges": [
89
+ {
90
+ "id": "addRemindable",
91
+ "isA": [
92
+ "verb"
93
+ ],
94
+ "development": true,
95
+ "bridge": "{ ...next(operator), arg: after[0], operator: operator, interpolate: '${operator} ${arg}' }"
96
+ },
97
+ {
98
+ "id": "remindable"
99
+ },
29
100
  {
30
101
  "id": "remind",
31
102
  "isA": [
32
103
  "verb"
33
104
  ],
34
- "bridge": "{ ...next(operator), operator: operator, who: after[0], reminder: after[1], interpolate: '${operator} ${who} ${reminder}' }"
105
+ "localHierarchy": [
106
+ [
107
+ "self",
108
+ "remindable"
109
+ ]
110
+ ],
111
+ "bridge": "{ ...next(operator), operator: operator, who: after[0], reminder: after[1], interpolate: '${operator} ${who} ${reminder}' }",
112
+ "withDateBridge": "{ ...next(operator), operator: operator, who: after[0], reminder: after[1], date: after[2], interpolate: '${operator} ${who} ${reminder} ${date}' }",
113
+ "withDateAndTimeBridge": "{ ...next(operator), operator: operator, who: after[0], reminder: after[1], date: after[2], time: after[3], interpolate: '${operator} ${who} ${reminder} ${date} ${time}' }"
114
+ },
115
+ {
116
+ "id": "reminders",
117
+ "isA": [
118
+ "noun"
119
+ ]
120
+ },
121
+ {
122
+ "id": "show",
123
+ "isA": [
124
+ "verb"
125
+ ],
126
+ "bridge": "{ ...next(operator), operator: operator, reminders: after[0], interpolate: '${operator} ${reminders}' }"
127
+ },
128
+ {
129
+ "id": "delete_reminders",
130
+ "isA": [
131
+ "verb"
132
+ ],
133
+ "bridge": "{ ...next(operator), operator: operator, reminders: after[0], interpolate: '${operator} ${reminders}' }"
35
134
  }
36
135
  ]
37
136
  },
38
137
  {
39
- "apply": "({ask, api}) => {\n ask([\n {\n where: where(),\n oneShot: false,\n onNevermind: ({verbatim, ...args}) => {\n // this is cross km boundaries from the dialogues km to this one so the api if for dialogs.\n // i need to get the one for fastfood here.\n const api = args.kms.fastfood.api\n const needsDrink = askAbout({ args, api })\n for (const item of needsDrink) {\n api.remove(item)\n }\n },\n\n matchq: (args) => args.api.askAbout(args).length > 0 && args.context.marker == 'controlEnd',\n applyq: (args) => {\n args.context.cascade = false\n const items = askAbout(args)\n const item = items[0]\n debugger;\n debugger\n },\n\n matchr: (args) => {\n if (args.isA(args.context.marker, 'drink') && askAbout(args).length > 0) {\n const needsDrink = askAbout(args)\n if (args.api.isAvailableModification(needsDrink[0].food, { ...args.context , id: args.context.value })) {\n return true\n }\n }\n return false\n },\n applyr: (args) => {\n // TODO check for is available for all modifications\n const needsDrink = askAbout(args)\n const { api, context } = args\n if (isMany(context)) {\n let count = getCount(context) || Number.MAX_SAFE_INTEGER\n for (const item of needsDrink) {\n if (count < 1) {\n break\n }\n count -= 1\n api.addDrink(item.item_id, { id: context.value })\n }\n } else {\n const item_id = needsDrink[0].item_id\n api.addDrink(item_id, { id: context.value })\n }\n }\n },\n ])\n }"
138
+ "apply": "({ask, api}) => {\n ask([\n {\n where: where(),\n oneShot: false,\n onNevermind: ({verbatim, ...args}) => {\n // this is cross km boundaries from the dialogues km to this one so the api if for dialogs.\n // i need to get the one for fastfood here.\n const api = args.kms.fastfood.api\n const needsDrink = askAbout({ args, api })\n for (const item of needsDrink) {\n api.remove(item)\n }\n },\n\n matchq: ({ api, context }) => api.askAbout().length > 0 && context.marker == 'controlEnd',\n applyq: ({ api, context }) => {\n context.cascade = false\n const items = api.askAbout()\n const item = items[0]\n return 'When should I remind you to ' + item.text;\n },\n\n matchr: ({ isA, api, context }) => {\n if ((isA(context.marker, 'onDateValue_dates') || isA(context.marker, 'dateTimeSelector')) && api.askAbout().length > 0) {\n return true\n }\n return false\n },\n applyr: async ({ context, api, gp }) => {\n const items = api.askAbout()\n await api.update({ id: items[0].id, dateTimeSelector: context, dateTimeSelectorText: await gp(context) })\n }\n },\n ])\n }"
40
139
  }
41
140
  ],
42
141
  "fragments": [],
@@ -3,26 +3,92 @@ const { defaultContextCheck } = require('./helpers')
3
3
  const reminders_tests = require('./reminders.test.json')
4
4
  const reminders_instance = require('./reminders.instance.json')
5
5
  const selfKM = require('./self')
6
- const dates = require('./dates')
6
+ const dateTimeSelectors = require('./dateTimeSelectors')
7
7
  const helpers = require('./helpers')
8
8
 
9
+ /*
10
+ friday instead
11
+ change it to friday
12
+ delete it
13
+ make it friday instead
14
+ 2 sundays from now
15
+ the sunday after july 1st
16
+ remind every truck driver to whatever tomorrow at 8 am
17
+ */
18
+
9
19
  class API {
10
20
  initialize({ objects }) {
11
21
  this._objects = objects
12
22
  this._objects.reminders = []
13
23
  this._objects.id = 0
24
+ this._objects.current = null
14
25
  }
15
26
 
16
- add(reminder) {
27
+ async add(reminder) {
28
+ await this.instantiate(reminder)
17
29
  const id = ++this._objects.id
18
- this._objects.reminders.push({ ...reminder, id })
30
+ reminder.id = id
31
+ this._objects.reminders.push(reminder)
32
+ this.args.mentioned({ context: reminder })
33
+ this._objects.current = id
34
+ }
35
+
36
+ getCurrent() {
37
+ return this._objects.current
38
+ }
39
+
40
+ // addUser to current
41
+ addUser(user) {
42
+ const reminder = this._objects.reminders.find((r) => r.id == this._objects.current)
43
+ if (reminder) {
44
+ if (Array.isArray(reminder.who)) {
45
+ reminder.who = [...reminder.who, user]
46
+ } else {
47
+ reminder.who = [reminder.who, user]
48
+ }
49
+ }
50
+ }
51
+
52
+ removeUser(user) {
53
+ const reminder = this._objects.reminders.find((r) => r.id == this._objects.current)
54
+ if (reminder) {
55
+ reminder.who = reminder.who.filter((who) => who.remindee_id != user.remindee_id)
56
+ }
57
+ }
58
+
59
+ addRemindable(id, text) {
60
+ if (!text) {
61
+ text = id
62
+ }
63
+ this.args.makeObject({ ...this.args, context: { word: text, value: id, number: 'one', remindee_id: id }, initial: `remindee_id: "${id}"`, types: ['remindable'] })
64
+ }
65
+
66
+ async instantiate(reminder) {
67
+ const value = await this.args.e(reminder.dateTimeSelector)
68
+ reminder.nextISODate = value?.evalue
69
+ }
70
+
71
+ contextToWho(who) {
72
+ if (who.isList) {
73
+ const whos = []
74
+ for (const element of this.args.values(who)) {
75
+ whos.push(this.contextToWho(element))
76
+ }
77
+ return whos
78
+ } else {
79
+ return { id: who.value || who.text, text: who.text, remindee_id: who.remindee_id }
80
+ }
81
+ }
82
+
83
+ // the user of the KM can override this. this can be used to sync the GUI and the LUI
84
+ getCurrent() {
19
85
  }
20
86
 
21
87
  askAbout() {
22
88
  const items = []
23
89
  for (const item of this._objects.reminders) {
24
- if (!item.when) {
25
- items.push({ when: true, text: item.text, id: item.id })
90
+ if (!item.dateTimeSelector) {
91
+ items.push({ when: true, who: item.who, text: item.text, id: item.id })
26
92
  }
27
93
  }
28
94
  return items
@@ -49,14 +115,14 @@ class API {
49
115
  this._objects.reminders = this._objects.reminders.splice(ordinal, 1)
50
116
  }
51
117
 
52
- update(update) {
118
+ async update(update) {
53
119
  for (const item of this._objects.reminders) {
54
120
  if (item.id == update.id) {
55
121
  Object.assign(item, update)
122
+ await this.instantiate(item)
56
123
  return
57
124
  }
58
125
  }
59
-
60
126
  }
61
127
  }
62
128
 
@@ -67,26 +133,85 @@ const template = {
67
133
  configs: [
68
134
  {
69
135
  operators: [
70
- "([remind] (self/*) (*)*)",
71
- "([reminderTime|])",
136
+ "([remindable])",
137
+ { pattern: "([addRemindable] (word)*)", development: true },
138
+ "([remind:justWhoBridge] (remindable/*))",
139
+ "([remind] (remindable/*) (!@<= 'dateTimeSelector' && !@<= 'inAddition')*)",
140
+ "([remind:withDateBridge] (remindable/*) (!@<= 'dateTimeSelector' && !@<= 'inAddition')* (dateTimeSelector))",
141
+ "([remind:withDateAndTimeBridge] (remindable/*) (!@<= 'dateTimeSelector' && !@<= 'inAddition')* (dateTimeSelector) (atTime))",
72
142
  "([show] ([reminders]))",
73
143
  "([delete_reminders|delete,cancel] (number/*))",
144
+ "([add] (remindable/*))",
145
+ "([remove|] (remindable/*))",
146
+ "((verb/*) [inAddition|also,too])",
74
147
  ],
75
148
  bridges: [
76
149
  {
77
- id: 'remind',
150
+ id: 'inAddition',
151
+ after: ['verb'],
152
+ bridge: "{ ...before[0], inAddition: true, verb: before[0], operator: operator, interpolate: '${verb} ${operator}' }",
153
+ },
154
+ {
155
+ id: 'add',
78
156
  isA: ['verb'],
79
- bridge: "{ ...next(operator), operator: operator, who: after[0], reminder: after[1], interpolate: '${operator} ${who} ${reminder}' }",
80
- semantic: async ({api, gsp, context}) => {
81
- const text = await gsp(context.reminder.slice(1));
82
- api.add({ text });
83
- },
157
+ bridge: "{ ...next(operator), arg: after[0], operator: operator, interpolate: '${operator} ${arg}' }",
158
+ semantic: ({api, context}) => {
159
+ api.addUser(api.contextToWho(context.arg))
160
+ }
161
+ },
162
+ {
163
+ id: 'remove',
164
+ words: ['delete', 'remove'],
165
+ isA: ['verb'],
166
+ bridge: "{ ...next(operator), arg: after[0], operator: operator, interpolate: '${operator} ${arg}' }",
167
+ semantic: ({api, context}) => {
168
+ api.removeUser(api.contextToWho(context.arg))
169
+ }
84
170
  },
85
171
  {
86
- id: 'reminderTime',
87
- children: [
88
- 'month_dates',
172
+ id: 'addRemindable',
173
+ isA: ['verb'],
174
+ development: true,
175
+ bridge: "{ ...next(operator), flatten: true, arg: after[0], operator: operator, interpolate: '${operator} ${arg}' }",
176
+ semantic: ({api, context}) => {
177
+ const name = context.arg.map( (word) => word.text ).join(' ')
178
+ api.addRemindable(name)
179
+ }
180
+ },
181
+ {
182
+ id: 'remindable',
183
+ isA: ['listable'],
184
+ },
185
+ {
186
+ id: 'remind',
187
+ isA: ['verb'],
188
+ localHierarchy: [['self', 'remindable']],
189
+ bridge: "{ ...next(operator), operator: operator, who: after[0], reminder: after[1], interpolate: '${operator} ${who} ${reminder}' }",
190
+ justWhoBridge: "{ ...next(operator), bridge: 'justWhoBridge', operator: operator, who: after[0], interpolate: '${operator} ${who}' }",
191
+ withDateBridge: "{ ...next(operator), operator: operator, who: after[0], reminder: after[1], date: after[2], interpolate: '${operator} ${who} ${reminder} ${date}' }",
192
+ withDateAndTimeBridge: "{ ...next(operator), operator: operator, who: after[0], reminder: after[1], date: after[2], time: after[3], interpolate: '${operator} ${who} ${reminder} ${date} ${time}' }",
193
+ semantics: [
194
+ {
195
+ match: ({context}) => context.marker == 'remind' && context.inAddition,
196
+ apply: ({context, api}) => {
197
+ api.addUser(api.contextToWho(context.who))
198
+ }
199
+ },
89
200
  ],
201
+ semantic: async ({api, gsp, gp, context}) => {
202
+ const who = api.contextToWho(context.who)
203
+ let text;
204
+ if (context.reminder) {
205
+ text = await gsp(context.reminder.slice(1));
206
+ }
207
+ const reminder = { text, dateTimeSelector: context.date, who }
208
+ if (context.date) {
209
+ reminder.dateTimeSelector = context.date
210
+ reminder.dateTimeSelectorText = await gp(context.date)
211
+ }
212
+ // await api.instantiate(reminder)
213
+ await api.add(reminder)
214
+ },
90
215
  },
91
216
  {
92
217
  id: 'reminders',
@@ -129,40 +254,32 @@ const template = {
129
254
  },
130
255
 
131
256
  matchq: ({ api, context }) => api.askAbout().length > 0 && context.marker == 'controlEnd',
132
- applyq: ({ api, context }) => {
257
+ applyq: async ({ api, context, gs }) => {
133
258
  context.cascade = false
134
259
  const items = api.askAbout()
135
260
  const item = items[0]
136
- return 'When should I remind you to ' + item.text;
261
+ let who
262
+ if (Array.isArray(item.who)) {
263
+ who = await gs(item.who.map((who) => who.text), ', ', ' and ')
264
+ } else {
265
+ if (item.who.text == 'me') {
266
+ who = 'you'
267
+ } else {
268
+ who = item.who.text
269
+ }
270
+ }
271
+ return `When should I remind ${who} to ${item.text}`
137
272
  },
138
273
 
139
274
  matchr: ({ isA, api, context }) => {
140
- if (isA(context.marker, 'reminderTime') && api.askAbout().length > 0) {
275
+ if ((isA(context.marker, 'onDateValue_dates') || isA(context.marker, 'dateTimeSelector')) && api.askAbout().length > 0) {
141
276
  return true
142
277
  }
143
278
  return false
144
279
  },
145
- applyr: ({ context, api }) => {
280
+ applyr: async ({ context, api, gp }) => {
146
281
  const items = api.askAbout()
147
- api.update({ id: items[0].id, when: context })
148
- // TODO check for is available for all modifications
149
- /*
150
- const needsDrink = askAbout(args)
151
- const { api, context } = args
152
- if (isMany(context)) {
153
- let count = getCount(context) || Number.MAX_SAFE_INTEGER
154
- for (const item of needsDrink) {
155
- if (count < 1) {
156
- break
157
- }
158
- count -= 1
159
- api.addDrink(item.item_id, { id: context.value })
160
- }
161
- } else {
162
- const item_id = needsDrink[0].item_id
163
- api.addDrink(item_id, { id: context.value })
164
- }
165
- */
282
+ await api.update({ id: items[0].id, dateTimeSelector: context, dateTimeSelectorText: await gp(context) })
166
283
  }
167
284
  },
168
285
  ])
@@ -172,7 +289,7 @@ const template = {
172
289
 
173
290
  knowledgeModule( {
174
291
  config: { name: 'reminders' },
175
- includes: [dates, selfKM],
292
+ includes: [dateTimeSelectors, selfKM],
176
293
  api: () => new API(),
177
294
 
178
295
  module,
@@ -181,11 +298,21 @@ knowledgeModule( {
181
298
  name: './reminders.test.json',
182
299
  contents: reminders_tests,
183
300
  checks: {
184
- context: defaultContextCheck(['who', 'reminder']),
301
+ context: defaultContextCheck(['who', 'reminder', 'verbatim']),
185
302
  objects: [
186
303
  {
187
304
  property: 'reminders',
188
- filter: [ 'text', 'when' ],
305
+ filter: [
306
+ 'text',
307
+ 'dateTimeSelectorText',
308
+ 'nextISODate',
309
+ 'who',
310
+ 'stm',
311
+ {
312
+ property: 'dateTimeSelector',
313
+ filter: ['marker', 'text', 'value'],
314
+ },
315
+ ],
189
316
  }
190
317
  ],
191
318
  },