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

206
LINES

< > BotCompany Repo | #1027518 // Chat Bot Frontend [with command translations, e.g. for Scenarios]

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

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

1  
!7
2  
3  
concept Cmd {
4  
  S patterns; // for mmo_parsePattern
5  
  S exampleInputs; // line-separated
6  
  S cmd; // a star pattern recognized by the backend
7  
  S questionsForArguments; // line-separated
8  
  S conditions;
9  
  int index;
10  
  bool autoGenerated;
11  
  
12  
  LS translatableFields() { ret splitAtSpace("patterns exampleInputs cmd questionsForArguments"); }
13  
  
14  
  transient MMOPattern parsedPattern;
15  
  void change { parsedPattern = null; super.change(); }
16  
  
17  
  MMOPattern parsedPattern() {
18  
    if (parsedPattern == null) parsedPattern = mmo_parsePattern(patterns);
19  
    ret parsedPattern;
20  
  }
21  
  
22  
  sS _fieldOrder = "autoGenerated exampleInputs patterns cmd questionsForArguments conditions";
23  
}
24  
25  
concept Replacement {
26  
  S in, out; // word to replace and which word to replace it with
27  
  S except; // IDs of Cmd concepts to skip
28  
  
29  
  sS _fieldOrder = "in out except";
30  
}
31  
32  
concept Mishearing {
33  
  S in, out;
34  
}
35  
36  
cmodule ChatBotFrontend > DynCRUD<Cmd> {
37  
  switchable S backendModuleLibID = "#1027443/Scenarios";
38  
  O currentAttractor;
39  
  transient CRUD<Replacement> replacementsCRUD = new(Replacement);
40  
  transient CRUD<Mishearing> mishearingsCRUD = new(Mishearing);
41  
  
42  
  class HandleArgument implements IF1<S> {
43  
    S cmd;
44  
    LS argQuestions;
45  
    new LS arguments;
46  
47  
    *() {}
48  
    *(S *cmd, LS *argQuestions) {}
49  
50  
    // process an argument
51  
    public S get(S arg) {
52  
      arguments.add(arg);
53  
      if (l(arguments) >= countAsteriskTokens(cmd))
54  
        ret sendToBackend(format_quoteAll(cmd, asObjectArray(arguments)));
55  
      else
56  
        ret handleQuestionWithArguments(this);
57  
    }
58  
59  
    S currentQuestion() {
60  
      ret or2(_get(argQuestions, l(arguments)), "Need argument");
61  
    }
62  
  }
63  
64  
  runnable class Cancel { setField(currentAttractor := null); }
65  
66  
  class UndoHandler implements IF1<Bool, S> {
67  
    public S get(Bool yes) {
68  
      if (!yes) ret "OK"; // user said no
69  
      ret (S) sendToBackend("undo");
70  
    }
71  
  }
72  
73  
  start {
74  
    dm_watchFieldAndNow backendModuleLibID(r {
75  
      dm_setModuleName("Frontend for " + dm_moduleName(backend()))
76  
    });
77  
    
78  
    crud.multiLineFields = litset("exampleInputs", "questionsForArguments");
79  
    crud.sorter = func(Cl<Cmd> l) -> L<Cmd> { sortByField index(l) };
80  
    crud.formFixer = 48;
81  
  }
82  
83  
  S handleCommand(Cmd cmd) {
84  
    if (cmd == null) null;
85  
 
86  
    print("handleCommand " + cmd.cmd);
87  
    
88  
    if (match("undo after confirm", cmd.cmd)) {
89  
      O undo = dm_call(backend(), 'lastUndo);
90  
      if (undo == null) ret "Nothing to undo";
91  
      new WaitForAnswer_YesNo attractor;
92  
      attractor.question = "Undo " + undo + "?";
93  
      setField(currentAttractor := attractor);
94  
      print("Set attractor to: " + attractor);
95  
      attractor.processAnswer = new UndoHandler;
96  
      attractor.cancelSilently = new Cancel;
97  
      ret attractor.question;
98  
    }
99  
    
100  
    if (hasAsteriskTokens(cmd.cmd))
101  
      ret handleQuestionWithArguments(
102  
        new HandleArgument(cmd.cmd, tlft(cmd.questionsForArguments)));
103  
    else
104  
      ret sendToBackend(cmd.cmd);
105  
  }
106  
107  
  S handleQuestionWithArguments(HandleArgument handler) {
108  
    new WaitForName attractor;
109  
    attractor.question = handler.currentQuestion();
110  
    setField(currentAttractor := attractor);
111  
    print("Set attractor to: " + attractor);
112  
    attractor.processName = handler;
113  
    attractor.cancelSilently = new Cancel;
114  
    ret attractor.question;
115  
  }
116  
117  
  S sendToBackend(S cmd) {
118  
    ret (S) dm_call(backend(), 'answer, cmd);
119  
  }
120  
  
121  
  S backend() {
122  
    ret dm_require(backendModuleLibID);
123  
  }
124  
  
125  
  visual {
126  
    JComponent mainCRUD = super.visualize();
127  
128  
    addComponents(crud.buttons,
129  
      jbutton("Talk to me", rThread talkToMe),
130  
      jPopDownButton_noText(
131  
        "Apply replacements", rThread applyReplacements,
132  
        "Consistency check", rThread consistencyCheck));
133  
134  
    ret jtabs(
135  
      "Commands" := mainCRUD,
136  
      "Replacements" := replacementsCRUD.visualize(),
137  
      "Mishearings" := mishearingsCRUD.visualize());
138  
  }
139  
140  
  void talkToMe enter { dm_showConversationPopupForModule(); }
141  
142  
  void consistencyCheck enter {
143  
    reindex();
144  
    L<Cmd> cmds = list(Cmd);
145  
    L<MMOConsistencyError> errors = mmo_consistencyCheck(
146  
      map(cmds, cmd -> pair(cmd.exampleInputs, cmd.patterns)));
147  
    if (empty(errors)) infoBox("No consistency problems");
148  
    else
149  
      dm_showText(n2(errors, "consistency problem"), lines(errors));
150  
  }
151  
152  
  void reindex {
153  
    int index = 1;
154  
    for (Cmd cmd : conceptsSortedByFields Cmd('autoGenerated, 'index))
155  
      cset(cmd, index := index++);
156  
  }
157  
  
158  
  void applyReplacements {
159  
    deleteConceptsWhere Cmd(autoGenerated := true);
160  
    for (Cmd cmd)
161  
      for (Replacement r) {
162  
        if (jcontains(r.except, str(cmd.id))) continue;
163  
        SS map = litcimap(r.in, r.out, plural(r.in), plural(r.out));
164  
        Cmd cmd2 = shallowCloneUnlisted(cmd);
165  
        cset(cmd2, autoGenerated := true);
166  
        for (S field : cmd.translatableFields())
167  
          cset(cmd2, field, fixAOrAn(replacePhrases(map, getString(cmd, field))));
168  
        if (anyFieldsDifferent(cmd, cmd2, cmd.translatableFields()))
169  
          registerConcept(cmd2);
170  
      }
171  
    consistencyCheck();
172  
  }
173  
  
174  
  // API
175  
  
176  
  // for initial fill of translation table. probably doesn't catch many patterns usually
177  
  void copyCommandsFromBackend() {
178  
    for (S cmd : allIfQuotedPatterns(loadSnippet(beforeSlash(backendModuleLibID))))
179  
      uniqConcept(+cmd);
180  
  }
181  
  
182  
  S answer(S s) {
183  
    S s1 = s;
184  
    s = replacePhrases(fieldToFieldIndexCI('in, 'out, list(Mishearing)), s);
185  
    if (neq(s, s1)) print("Corrected to: " + s);
186  
    if (currentAttractor != null) {
187  
      print("Sending to attractor " + currentAttractor + ": " + s);
188  
      S a = strOrNull(call(currentAttractor, 'answer, s));
189  
      if (a != null) {
190  
        print("Attractor said: " + a);
191  
        ret a;
192  
      }
193  
    }
194  
    L<Cmd> cmds = filter(conceptsSortedByField Cmd('index),
195  
      c -> nempty(c.patterns) && checkCondition(c));
196  
    Cmd cmd = mmo_matchMultiWithTypos(1, cmds, c -> c.parsedPattern(), s);
197  
    if (cmd != null) ret handleCommand(cmd);
198  
    ret sendToBackend(s);
199  
  }
200  
  
201  
  bool checkCondition(Cmd cmd) {
202  
    if (match("have scenario", cmd.conditions))
203  
      ret print("have scenario", dm_call(backend(), 'selectedScenario)) != null;
204  
    true;
205  
  }
206  
}

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: #1027518
Snippet name: Chat Bot Frontend [with command translations, e.g. for Scenarios]
Eternal ID of this version: #1027518/86
Text MD5: 8ee6614dcc555cedfe6a2fed609a73bf
Transpilation MD5: ef037be1a965005ac41b40bdd80ea89f
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-24 11:29:17
Source code size: 6365 bytes / 206 lines
Pitched / IR pitched: No / No
Views / Downloads: 253 / 1528
Version history: 85 change(s)
Referenced in: [show references]