1 | // adapters are immutable! (plus returns a modified clone) |
2 | abstract sclass Adapter { |
3 | abstract bool canMatch(S in, S out); |
4 | Adapter plus(S in, S out) { ret this; } |
5 | S get(S in) { ret in; } |
6 | abstract double size(); |
7 | } |
8 | |
9 | // node in flight (+ optional adapter) |
10 | sclass InFlight { |
11 | OccTree2 node; |
12 | Adapter adapter; |
13 | |
14 | *(OccTree2 *node) {} |
15 | *(OccTree2 *node, Adapter *adapter) {} |
16 | |
17 | E adapted() { |
18 | // TODO: security when rewriting states |
19 | ret adapter == null ? node.e : new E(adapter.get(node.e.text()), node.e.type()); |
20 | } |
21 | } |
22 | |
23 | sclass LooseBot { |
24 | sbool debug, repeat = true; |
25 | OccTree2 tree; |
26 | new L<InFlight> nodes; |
27 | new L<L> rewindStack; |
28 | O newAdapter; |
29 | O grabber; // func(S -> E) |
30 | |
31 | // WordAdapter now default |
32 | *(OccTree2 tree) { this(tree, func { new WordAdapter }); } |
33 | *(OccTree2 *tree, O *newAdapter) {} |
34 | *(S theme) { this(makeOccTree(theme)); } |
35 | *(S theme, O newAdapter) { this(makeOccTree(theme), newAdapter); } |
36 | |
37 | Adapter makeAdapter() { |
38 | ret newAdapter == null ? null : (Adapter) call(newAdapter); |
39 | } |
40 | |
41 | void take(E in) { |
42 | remember(); |
43 | |
44 | // try starting over from beginning of tree too |
45 | if (repeat) setAdd(nodes, new InFlight(tree, makeAdapter())); |
46 | |
47 | new L<InFlight> l; |
48 | |
49 | // try grabber |
50 | if (grabber != null && in.q()) try { |
51 | E grabbed = cast callFunction(grabber, in.text()); |
52 | if (grabbed != null) { |
53 | if (debug) |
54 | print("Grabber worked! " + in.text() + " => " + grabbed); |
55 | |
56 | // make a mini tree with Q + A so it is matched in |
57 | // next call to getSingleOutput() |
58 | OccTree2 node = new OccTree2(in); |
59 | node.next.add(new OccTree2(grabbed)); |
60 | |
61 | l.add(new InFlight(node)); |
62 | } else |
63 | if (debug) |
64 | print("Grabber didnt't return anything. " + in.text()); |
65 | } catch e { |
66 | if (debug) printStackTrace(e); |
67 | } |
68 | |
69 | for (InFlight flight : nodes) |
70 | for (OccTree2 n : flight.node.next) |
71 | if (eq(n.e.type(), in.type()) && (flight.adapter != null |
72 | ? flight.adapter.canMatch(n.e.text(), in.text()) |
73 | : matchE(n.e, in))) { |
74 | l.add(new InFlight(n, flight.adapter == null ? null |
75 | : flight.adapter.plus(n.e.text(), in.text()))); |
76 | } |
77 | nodes = l; |
78 | } |
79 | |
80 | void remember() { |
81 | if (rewindStack != null) |
82 | rewindStack.add(cloneList(nodes)); |
83 | } |
84 | |
85 | E getSingleOutput() { |
86 | remember(); |
87 | new L<InFlight> l; |
88 | for (InFlight flight : nodes) |
89 | for (OccTree2 n : flight.node.next) |
90 | if (n.e.a() || isCommand(n.e)) |
91 | l.add(new InFlight(n, flight.adapter)); |
92 | if (empty(l)) { rewind(); null; } |
93 | nodes = l; |
94 | ret first(nodes).adapted(); |
95 | } |
96 | |
97 | void rewind() { |
98 | nodes = popLast(rewindStack); |
99 | } |
100 | |
101 | bool isCommand(E e) { |
102 | ret !isInput(e); |
103 | } |
104 | |
105 | // see Dialog Optimizer |
106 | bool isInput(E e) { |
107 | ret e.q() |
108 | || e.state() && matchStart("result is ", e.text()); |
109 | } |
110 | |
111 | void noRewind() { |
112 | rewindStack = null; |
113 | } |
114 | |
115 | bool matchE(E a, E b) { |
116 | // standard NL matching |
117 | ret eq(a.type(), b.type()) && match(a.text(), b.text()); |
118 | } |
119 | |
120 | S nodesToString(L<InFlight> nodes) { |
121 | new L<S> l; |
122 | l.add(n(l(nodes), "node") + "\n"); |
123 | for (InFlight flight : nodes) { |
124 | l.add(str(flight.node.e)); |
125 | if (flight.adapter != null) |
126 | l.add(" " + flight.adapter); |
127 | } |
128 | ret rtrim(fromLines(l)); |
129 | } |
130 | |
131 | S thoughts() { |
132 | new L<S> l; |
133 | l.add(nodesToString(nodes)); |
134 | if (rewindStack != null) { |
135 | l.add("\nHistory\n"); |
136 | for (L<InFlight> nodes : reversedList(rewindStack)) |
137 | l.add(indent(nodesToString(nodes))); |
138 | } |
139 | ret fromLines(l); |
140 | } |
141 | } |
142 | |
143 | sclass WordAdapter extends Adapter { |
144 | new Map<S, S> wordMap; |
145 | |
146 | L<S> tok(S s) { |
147 | ret nlTok2(dropPunctuation2(s)); |
148 | } |
149 | |
150 | bool canMatch(S in, S out) { |
151 | L<S> t1 = tok(in), t2 = tok(out); |
152 | ret l(t1) == l(t2); |
153 | } |
154 | |
155 | Adapter plus(S in, S out) { |
156 | L<S> t1 = tok(in), t2 = tok(out); |
157 | if (l(t1) != l(t2)) ret this; |
158 | |
159 | WordAdapter a = cast nuObject(getClass()); |
160 | a.wordMap = cloneMap(wordMap); |
161 | for (int i = 1; i < l(t1); i += 2) { |
162 | S w1 = t1.get(i), w2 = t2.get(i); |
163 | if (!eqic(w1, w2)) |
164 | // just overwrite - be flexible! |
165 | a.wordMap.put(w1.toLowerCase(), w2.toLowerCase()); |
166 | } |
167 | ret a; |
168 | } |
169 | |
170 | S get(S s) { |
171 | L<S> tok = nlTok2(s); |
172 | for (int i = 1; i < l(tok); i += 2) { |
173 | S w = lookupToken(tok.get(i)); |
174 | if (nempty(w)) |
175 | tok.set(i, w); |
176 | } |
177 | ret join(tok); |
178 | } |
179 | |
180 | S lookupToken(S s) { |
181 | ret wordMap.get(s.toLowerCase()); |
182 | } |
183 | |
184 | double size() { |
185 | ret l(wordMap); |
186 | } |
187 | |
188 | public S toString() { |
189 | ret structure(wordMap); |
190 | } |
191 | } |
192 | |
193 | sclass WordAdapter2 extends WordAdapter { |
194 | new Map<S, S> wordMap; |
195 | |
196 | L<S> tok(S s) { |
197 | ret nlTok2(s); |
198 | } |
199 | } |
Began life as a copy of #1003413
download show line numbers debug dex old transpilations
Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1003526 |
Snippet name: | LooseBot v6 (with modified isCommand) |
Eternal ID of this version: | #1003526/1 |
Text MD5: | d15b197a4ac77ba95829a13c049b3a4f |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-07-11 01:46:56 |
Source code size: | 4945 bytes / 199 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 529 / 908 |
Referenced in: | [show references] |