Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

221
LINES

< > BotCompany Repo | #1003413 // LooseBot v5 (with adapters + grabbers)

JavaX fragment (include)

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  
  double size() { ret 0; }
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  
  
34  
  // main constructor
35  
  *(OccTree2 *tree, O *newAdapter) {
36  
    expandEllipsis(tree);
37  
  }
38  
  
39  
  *(S theme) { this(makeOccTree(theme)); }
40  
  *(S theme, O newAdapter) { this(makeOccTree(theme), newAdapter); }
41  
  
42  
  Adapter makeAdapter() {
43  
    ret newAdapter == null ? null : (Adapter) call(newAdapter);
44  
  }
45  
  
46  
  void take(E in) {
47  
    remember();
48  
    
49  
    // try starting over from beginning of tree too
50  
    if (repeat) setAdd(nodes, new InFlight(tree, makeAdapter()));
51  
    
52  
    new L<InFlight> l;
53  
    
54  
    // try grabber
55  
    if (grabber != null && in.q()) try {
56  
      E grabbed = cast callFunction(grabber, in.text());
57  
      if (grabbed != null) {
58  
        if (debug)
59  
          print("Grabber worked! " + in.text() + " => " + grabbed);
60  
          
61  
        // make a mini tree with Q + A so it is matched in
62  
        // next call to getSingleOutput()
63  
        OccTree2 node = new OccTree2(in);
64  
        node.next.add(new OccTree2(grabbed));
65  
        
66  
        l.add(new InFlight(node));
67  
      } else
68  
        if (debug)
69  
          print("Grabber didnt't return anything. " + in.text());
70  
    } catch e {
71  
      if (debug) printStackTrace(e);
72  
    }
73  
    
74  
    for (InFlight flight : nodes)
75  
      for (OccTree2 n : flight.node.next)
76  
        if (eq(n.e.type(), in.type()) && (flight.adapter != null
77  
          ? flight.adapter.canMatch(n.e.text(), in.text())
78  
          : matchE(n.e, in))) {
79  
          l.add(new InFlight(n, flight.adapter == null ? null
80  
            : flight.adapter.plus(n.e.text(), in.text())));
81  
        }
82  
        
83  
    nodes = l;
84  
  }
85  
  
86  
  L<E> possibleNextInput() {
87  
    new HashSet<E> l;
88  
    if (repeat) l.add(tree.e);
89  
    
90  
    L<InFlight> ns = cloneList(nodes);
91  
    if (repeat) setAdd(ns, new InFlight(tree, makeAdapter()));
92  
    for (InFlight flight : ns)
93  
      for (OccTree2 n : flight.node.next)
94  
        l.add(new InFlight(n, flight.adapter).adapted());
95  
    ret asList(l);
96  
  }
97  
  
98  
  void remember() {
99  
    if (rewindStack != null)
100  
      rewindStack.add(cloneList(nodes));
101  
  }
102  
  
103  
  E getSingleOutput() {
104  
    remember();
105  
    new L<InFlight> l;
106  
    for (InFlight flight : nodes)
107  
      for (OccTree2 n : flight.node.next)
108  
        if (n.e.a() || isCommand(n.e))
109  
          l.add(new InFlight(n, flight.adapter));
110  
    if (empty(l)) { rewind(); null; }
111  
    nodes = l;
112  
    ret first(nodes).adapted();
113  
  }
114  
  
115  
  void rewind() {
116  
    nodes = popLast(rewindStack);
117  
  }
118  
  
119  
  bool isCommand(E e) {
120  
    ret e.state() && matchStart("bot", e.state);
121  
  }
122  
  
123  
  void noRewind() {
124  
    rewindStack = null;
125  
  }
126  
  
127  
  bool matchE(E a, E b) {
128  
    // standard NL matching
129  
    ret eq(a.type(), b.type()) && match(a.text(), b.text());
130  
  }
131  
  
132  
  S nodesToString(L<InFlight> nodes) {
133  
    new L<S> l;
134  
    l.add(n(l(nodes), "node"));
135  
    for (InFlight flight : nodes) {
136  
      l.add(str(flight.node.e));
137  
      if (flight.adapter != null)
138  
        l.add("  " + flight.adapter);
139  
    }
140  
    ret rtrim(fromLines(l));
141  
  }
142  
  
143  
  S thoughts() {
144  
    new L<S> l;
145  
    l.add("Expecting input:\n");
146  
    for (E e : possibleNextInput())
147  
      if (e != null)
148  
        l.add("  " + e);
149  
    l.add("");
150  
    l.add(nodesToString(nodes));
151  
    if (rewindStack != null) {
152  
      l.add("\nHistory\n");
153  
      for (L<InFlight> nodes : reversedList(rewindStack))
154  
        l.add(indent(nodesToString(nodes)));
155  
    }
156  
    ret fromLines(l);
157  
  }
158  
  
159  
  LooseBot debugOn() {
160  
    debug = true;
161  
    ret this;
162  
  }
163  
}
164  
165  
sclass WordAdapter extends Adapter {
166  
  new Map<S, S> wordMap;
167  
  
168  
  L<S> tok(S s) {
169  
    ret nlTok2(dropPunctuation2(s));
170  
  }
171  
  
172  
  bool canMatch(S in, S out) {
173  
    L<S> t1 = tok(in), t2 = tok(out);
174  
    ret l(t1) == l(t2);
175  
  }
176  
  
177  
  Adapter plus(S in, S out) {
178  
    L<S> t1 = tok(in), t2 = tok(out);
179  
    if (l(t1) != l(t2)) ret this;
180  
    
181  
    WordAdapter a = cast nuObject(getClass());
182  
    a.wordMap = cloneMap(wordMap);
183  
    for (int i = 1; i < l(t1); i += 2) {
184  
      S w1 = t1.get(i), w2 = t2.get(i);
185  
      if (!eqic(w1, w2))
186  
        // just overwrite - be flexible!
187  
        a.wordMap.put(w1.toLowerCase(), w2.toLowerCase());
188  
    }
189  
    ret a;
190  
  }
191  
  
192  
  S get(S s) {
193  
    L<S> tok = nlTok2(s);
194  
    for (int i = 1; i < l(tok); i += 2) {
195  
      S w = lookupToken(tok.get(i));
196  
      if (nempty(w))
197  
        tok.set(i, w);
198  
    }
199  
    ret join(tok);
200  
  }
201  
  
202  
  S lookupToken(S s) {
203  
    ret wordMap.get(s.toLowerCase());
204  
  }
205  
  
206  
  double size() {
207  
    ret l(wordMap);
208  
  }
209  
  
210  
  public S toString() {
211  
    ret structure(wordMap);
212  
  }
213  
}
214  
215  
sclass WordAdapter2 extends WordAdapter {
216  
  new Map<S, S> wordMap;
217  
  
218  
  L<S> tok(S s) {
219  
    ret nlTok2(s);
220  
  }
221  
}

Author comment

Began life as a copy of #1003412

download  show line numbers  debug dex  old transpilations   

Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, ddnzoavkxhuk, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1003413
Snippet name: LooseBot v5 (with adapters + grabbers)
Eternal ID of this version: #1003413/1
Text MD5: 07e5514dfe4696e4ee1a82920e0c27a5
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-07-20 00:49:18
Source code size: 5466 bytes / 221 lines
Pitched / IR pitched: No / No
Views / Downloads: 530 / 1647
Referenced in: [show references]