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

229
LINES

< > BotCompany Repo | #1003575 // LooseBot v6 (with generic adapters)

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

Author comment

Began life as a copy of #1003413

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1003575
Snippet name: LooseBot v6 (with generic adapters)
Eternal ID of this version: #1003575/1
Text MD5: 0174bb8b912c2c411b624bfcc5bc9b0c
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:54:32
Source code size: 5649 bytes / 229 lines
Pitched / IR pitched: No / No
Views / Downloads: 504 / 462
Referenced in: [show references]