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

287
LINES

< > BotCompany Repo | #1027661 // Chat Bot Frontend v2 backup

JavaX source code (Dynamic Module) [tags: use-pretranspiled] - run with: Stefan's OS

Uses 911K of libraries. Click here for Pure Java version (20571L/112K).

1  
!7
2  
3  
!include once #1027578 // Named
4  
5  
// Note: db_mainConcepts() doesn't work (because of cases), always use cc!
6  
7  
concept BotName > Named {} // e.g. for finding the module in Cruddie
8  
9  
concept Cmd > ConceptWithGlobalID {
10  
  S patterns; // for mmo_parsePattern
11  
  S exampleInputs; // line-separated
12  
  S cmd; // a star pattern recognized by the backend
13  
  S questionsForArguments; // line-separated
14  
  S conditions;
15  
  int index;
16  
  bool autoGenerated;
17  
  
18  
  LS translatableFields() { ret splitAtSpace("patterns exampleInputs cmd questionsForArguments"); }
19  
  
20  
  sS importableFields() { ret "cmd conditions exampleInputs globalID index patterns questionsForArguments"; }
21  
  
22  
  transient MMOPattern parsedPattern;
23  
  void change { parsedPattern = null; super.change(); }
24  
  
25  
  MMOPattern parsedPattern() {
26  
    if (parsedPattern == null) parsedPattern = mmo_parsePattern(patterns);
27  
    ret parsedPattern;
28  
  }
29  
  
30  
  sS _fieldOrder = "autoGenerated exampleInputs patterns cmd questionsForArguments conditions";
31  
}
32  
33  
concept Replacement {
34  
  S in, out; // word to replace and which word to replace it with
35  
  S except; // IDs of Cmd concepts to skip
36  
  
37  
  sS _fieldOrder = "in out except";
38  
}
39  
40  
concept Mishearing {
41  
  S in, out;
42  
}
43  
44  
cmodule ChatBotFrontend > DynCRUD<Cmd> {
45  
  switchable S backendModuleID;
46  
  switchable S baseThingName = "$thing";
47  
  O currentAttractor;
48  
  transient CRUD<Replacement> replacementsCRUD, mishearingsCRUD;
49  
  
50  
  class HandleArgument implements IF1<S> {
51  
    S cmd;
52  
    LS argQuestions;
53  
    new LS arguments;
54  
55  
    *() {}
56  
    *(S *cmd, LS *argQuestions) {}
57  
58  
    // process an argument
59  
    public S get(S arg) {
60  
      arguments.add(arg);
61  
      if (l(arguments) >= countAsteriskTokens(cmd))
62  
        ret sendToBackend(format_quoteAll(cmd, asObjectArray(arguments)));
63  
      else
64  
        ret handleQuestionWithArguments(this);
65  
    }
66  
67  
    S currentQuestion() {
68  
      ret or2(_get(argQuestions, l(arguments)), "Need argument");
69  
    }
70  
  }
71  
72  
  runnable class Cancel { setField(currentAttractor := null); }
73  
74  
  class UndoHandler implements IF1<Bool, S> {
75  
    public S get(Bool yes) {
76  
      if (!yes) ret "OK"; // user said no
77  
      ret (S) sendToBackend("undo");
78  
    }
79  
  }
80  
81  
  void start {
82  
    cc = dm_handleCaseIDField();
83  
    super.start();
84  
    dm_watchFieldAndNow backendModuleID(r updateModuleName);
85  
    
86  
    crud.multiLineFields = litset("exampleInputs", "questionsForArguments");
87  
    crud.sorter = func(Cl<Cmd> l) -> L<Cmd> { sortByField index(l) };
88  
    crud.formFixer = 48;
89  
    
90  
    replacementsCRUD = new CRUD(cc, Replacement);
91  
    mishearingsCRUD = new CRUD(cc, Mishearing);
92  
    
93  
    dm_vmBus_onMessage_q objectTypesChanged((module, names) -> {
94  
      if (dm_isSame(module, backend()))
95  
        importReplacements();
96  
    });
97  
  }
98  
  
99  
  void importReplacements() {
100  
    LS names = cast dm_call(backend(), 'objectTypes);
101  
    print("Got names: " + names);
102  
    if (names != null) {
103  
      deleteConcepts(cc, Replacement);
104  
      for (S name : names)
105  
        if (neqic(name, baseThingName))
106  
          cnew(cc, Replacement, in := baseThingName, out := name);
107  
    }
108  
    applyReplacements();
109  
  }
110  
111  
  S handleCommand(Cmd cmd) {
112  
    if (cmd == null) null;
113  
 
114  
    print("handleCommand " + cmd.cmd);
115  
    
116  
    if (match("undo after confirm", cmd.cmd)) {
117  
      O undo = dm_call(backend(), 'lastUndo);
118  
      if (undo == null) ret "Nothing to undo";
119  
      new WaitForAnswer_YesNo attractor;
120  
      attractor.question = "Undo " + undo + "?";
121  
      setField(currentAttractor := attractor);
122  
      print("Set attractor to: " + attractor);
123  
      attractor.processAnswer = new UndoHandler;
124  
      attractor.cancelSilently = new Cancel;
125  
      ret attractor.question;
126  
    }
127  
    
128  
    if (hasAsteriskTokens(cmd.cmd))
129  
      ret handleQuestionWithArguments(
130  
        new HandleArgument(cmd.cmd, tlft(cmd.questionsForArguments)));
131  
    else
132  
      ret sendToBackend(cmd.cmd);
133  
  }
134  
135  
  S handleQuestionWithArguments(HandleArgument handler) {
136  
    new WaitForName attractor;
137  
    attractor.question = handler.currentQuestion();
138  
    setField(currentAttractor := attractor);
139  
    print("Set attractor to: " + attractor);
140  
    attractor.processName = handler;
141  
    attractor.cancelSilently = new Cancel;
142  
    ret attractor.question;
143  
  }
144  
145  
  S sendToBackend(S cmd) {
146  
    ret (S) dm_call(backend(), 'answer, cmd);
147  
  }
148  
  
149  
  S backend() {
150  
    ret backendModuleID;
151  
  }
152  
  
153  
  visual {
154  
    JComponent mainCRUD = super.visualize();
155  
156  
    addComponents(crud.buttons,
157  
      jbutton("Talk to me", rThread talkToMe),
158  
      jPopDownButton_noText(
159  
        "Apply replacements", rThread applyReplacements,
160  
        "Import replacements", rThread importReplacements,
161  
        "Consistency check", rThread consistencyCheck,
162  
        "Import commands from snippet...", rThread importCmdsFromSnippet));
163  
164  
    ret jtabs(
165  
      "Commands" := mainCRUD,
166  
      "Replacements" := replacementsCRUD.visualize(),
167  
      "Mishearings" := mishearingsCRUD.visualize());
168  
  }
169  
170  
  void talkToMe enter { dm_showConversationPopupForModule(); }
171  
172  
  void consistencyCheck enter {
173  
    reindex();
174  
    L<Cmd> cmds = list(Cmd);
175  
    L<MMOConsistencyError> errors = mmo_consistencyCheck(
176  
      map(cmds, cmd -> pair(cmd.exampleInputs, cmd.patterns)));
177  
    if (empty(errors)) infoBox("No consistency problems");
178  
    else
179  
      dm_showText(n2(errors, "consistency problem"), lines(errors));
180  
  }
181  
182  
  void reindex {
183  
    int index = 1;
184  
    for (Cmd cmd : conceptsSortedByFields(cc, Cmd, 'autoGenerated, 'index))
185  
      cset(cmd, index := index++);
186  
  }
187  
  
188  
  void applyReplacements {
189  
    deleteConceptsWhere(cc, Cmd, autoGenerated := true);
190  
    for (Cmd cmd)
191  
      for (Replacement r) {
192  
        if (jcontains(r.except, str(cmd.id))) continue;
193  
        SS map = litcimap(r.in, r.out, plural(r.in), plural(r.out));
194  
        Cmd cmd2 = shallowCloneUnlisted(cmd);
195  
        cset(cmd2, autoGenerated := true, globalID := aGlobalIDObject());
196  
        for (S field : cmd.translatableFields())
197  
          cset(cmd2, field, fixAOrAn(replacePhrases(map, getString(cmd, field))));
198  
        if (anyFieldsDifferent(cmd, cmd2, cmd.translatableFields()))
199  
          registerConcept(cc, cmd2);
200  
      }
201  
    consistencyCheck();
202  
  }
203  
  
204  
  // API
205  
  
206  
  // for initial fill of translation table. probably doesn't catch many patterns usually
207  
  void copyCommandsFromBackend() {
208  
    for (S cmd : allIfQuotedPatterns(loadSnippet(beforeSlash(dm_moduleLibID(backend())))))
209  
      uniqConcept(+cmd);
210  
  }
211  
  
212  
  S answer(S s) {
213  
    S s1 = s;
214  
    s = replacePhrases(fieldToFieldIndexCI('in, 'out, list(Mishearing)), s);
215  
    if (neq(s, s1)) print("Corrected to: " + s);
216  
    if (currentAttractor != null) {
217  
      print("Sending to attractor " + currentAttractor + ": " + s);
218  
      S a = strOrNull(call(currentAttractor, 'answer, s));
219  
      if (a != null) {
220  
        print("Attractor said: " + a);
221  
        ret a;
222  
      }
223  
    }
224  
    L<Cmd> cmds = filter(conceptsSortedByField(cc, Cmd, 'index),
225  
      c -> nempty(c.patterns) && checkCondition(c));
226  
    Cmd cmd = mmo_matchMultiWithTypos(1, cmds, c -> c.parsedPattern(), s);
227  
    if (cmd != null) ret handleCommand(cmd);
228  
    ret sendToBackend(s);
229  
  }
230  
  
231  
  bool checkCondition(Cmd cmd) {
232  
    true;
233  
  }
234  
  
235  
  // e.g. from snippet #1027616
236  
  void importCmds(S src) {
237  
    L l = dynShortNamed Cmd(safeUnstructList(src));
238  
    int imported = 0;
239  
    for (O o : l) {
240  
      S id = getString globalID(o);
241  
      if (empty(id)) continue;
242  
      ++imported;
243  
      GlobalID globalID = GlobalID(id);
244  
      Cmd cmd = uniq_sync(cc, Cmd, +globalID);
245  
      for (S field : splitAtSpace(Cmd.importableFields()))
246  
        cSmartSet(cmd, field, getOpt(o, field));
247  
    }
248  
    topLeftInfoBox("Imported/updated " + nEntries(imported));
249  
    if (imported != 0)
250  
      importReplacements();
251  
  }
252  
  
253  
  void importCmdsFromSnippet(S snippetID) {
254  
    print("Importing cmds from " + snippetID);
255  
    importCmds(loadSnippet(snippetID));
256  
  }
257  
  
258  
  // import if we have no cmds yet
259  
  void importCmdsFromSnippetIfEmpty(S snippetID) {
260  
    if (conceptCount() == 0)
261  
      importCmdsFromSnippet(snippetID);
262  
  }
263  
  
264  
  void importCmdsFromSnippet enter {
265  
    selectSnippetID("Commands to import", vf<S> importCmdsFromSnippet);
266  
  }
267  
  
268  
  void connectToBackend(S backendModuleID) {
269  
    setField(+backendModuleID);
270  
  }
271  
  
272  
  void setBotName(S name) {
273  
    cset(uniq(cc, BotName), +name);
274  
    updateModuleName();
275  
  }
276  
  
277  
  // may return null or empty string
278  
  S botName() {
279  
    ret getString name(conceptWhere(cc, BotName));
280  
  }
281  
  
282  
  void updateModuleName enter {
283  
    S name = botName();
284  
    if (empty(name)) name = dm_moduleName(backend());
285  
    dm_setModuleName("Frontend for " + name);
286  
  }
287  
}

Author comment

Began life as a copy of #1027602

download  show line numbers  debug dex  old transpilations   

Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv

No comments. add comment

Snippet ID: #1027661
Snippet name: Chat Bot Frontend v2 backup
Eternal ID of this version: #1027661/1
Text MD5: daa04656d3e46badf660de40898e4945
Transpilation MD5: ed4641f26d58b57ac018eb6b19fa15c5
Author: stefan
Category: javax
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2020-03-29 21:27:20
Source code size: 8784 bytes / 287 lines
Pitched / IR pitched: No / No
Views / Downloads: 102 / 151
Referenced in: [show references]