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

548
LINES

< > BotCompany Repo | #1004031 // Random Main v9

JavaX fragment (include)

1  
sbool assisting;
2  
static S generatorsID;
3  
4  
static JFrame frame;
5  
static JTable table, chatTable;
6  
//static JTextArea chat;
7  
static JTextField input;
8  
static L<S> log = synchroList();
9  
static L<S> recommendations;
10  
static L<Thread> thinkThreads = synchroList();
11  
static JLabel status;
12  
static S lastInput;
13  
static Map matchingSuggestion;
14  
static Map<S, ImmL<S>> allLogs = synchroMap();
15  
static JFrame analyzersFrame;
16  
static S dialogImageID;
17  
static JFrame dialogImageFrame;
18  
19  
static int listDelay = 2000;
20  
static int maxLineLength = 1000;
21  
static int maxLongStringLength = 100*1000;
22  
23  
static Bool thinking;
24  
static new Thinker thinker;
25  
static bool showCPU = true;
26  
27  
static S systemPrefix = "[system]";
28  
29  
static S dialog = "new";
30  
31  
svoid randomMain {
32  
  //substanceLAF("EmeraldDusk"); // Too dark!
33  
  //substanceLAF("ChallengerDeep"); // So purple!
34  
  //substance("MistAqua");
35  
  substance("Moderate");
36  
37  
  table = tableWithTooltips();
38  
  //chat = autoScroll(wordWrapTextArea());
39  
  chatTable = tableWithTooltips();
40  
  input = new JTextField;
41  
  status = new JLabel(" ");
42  
  
43  
  S title = assisting ? "Assistance - " + autoFrameTitle() : autoFrameTitle();
44  
  frame = showFrame(title, vgrid(centerAndSouth(
45  
    //jtabs(1, "Chat", chat, "Details", chatTable),
46  
    chatTable,
47  
    input), centerAndSouth(table, status)));
48  
  //setFrameIconLater(frame, "#1003593");
49  
  
50  
  addMenu(frame, "Random",
51  
    "Delete last line (!delete)", r { post("!delete"); },
52  
    "Reload generators (!gen)", r { post("!gen"); },
53  
    "Restart app (!restart)", r { post("!restart"); },
54  
    "Restart Java engine (!fresh)", r { post("!fresh"); },
55  
    "Execute Java code (!j ...)", r { setInput("!j 1+2"); },
56  
    "Switch dialog (!dialog ...)", r { setInput("!dialog bla"); },
57  
    "Restore last input", r { if (nempty(lastInput)) setInput(lastInput); },
58  
    "Show raw dialog", r { showText("Raw Dialog", rawDialog()); },
59  
  );
60  
  
61  
  makeDialogsMenu();
62  
  
63  
  onEnter(input, r {
64  
    post();
65  
  });
66  
  
67  
  onDoubleClick(table, voidfunc(int row) {
68  
    chooseSuggestion(row);
69  
  });
70  
  
71  
  for (int i = 1; i <= 12; i++) {
72  
    final int _i = i;
73  
    registerFunctionKey(frame, i, r {
74  
      chooseSuggestionForEditing(_i-1);
75  
    });
76  
    registerShiftFunctionKey(frame, i, r {
77  
      chooseSuggestion(_i-1);
78  
    });
79  
    registerCtrlFunctionKey(frame, i, r {
80  
      // post user input and then choose suggestion for editing
81  
      Map<S, S> map = getTableLineAsMap(table, _i-1);
82  
      if (map == null) ret;
83  
      rankToTop(map);
84  
      S s = trim(unnull(map.get("Suggestion")));
85  
      logEvent("Suggestion chosen for editing with pre-post", mapPlus(map, "Row", _i, "Input", getInput(), "Top Suggesters", topSuggesters()));
86  
      post();
87  
      setInput(s);
88  
    });
89  
  }
90  
  
91  
  onDoubleClickOrEnter(chatTable, voidfunc(int row) {
92  
    L line = getTableLine(chatTable, row);
93  
    if (line != null)
94  
      setInput(getString(line, 0));
95  
  });
96  
  
97  
  onUpdate(input, r { updateOnce(); });
98  
  
99  
  loadDialog();
100  
  logEvent("Starting");
101  
  
102  
  updateOnce();
103  
  
104  
  input.requestFocus();
105  
  
106  
  if (isAction(last(log)) && confirmYesNo(input, "Run action? " + last(log)))
107  
    action(last(log));
108  
}
109  
110  
static S getInput() {
111  
  ret joinLines(" # ", input.getText().trim());
112  
}
113  
114  
sv post() {
115  
  postAsUser(getInput(), null);
116  
}
117  
118  
static void postAsUser(S i, Map infos) {
119  
  if (inputAllowedByUser(i))
120  
    post(i, infos);
121  
}
122  
123  
svoid chooseSuggestionForEditing(int row) {
124  
  Map<S, S> map = getTableLineAsMap(table, row);
125  
  if (map == null) ret;
126  
  rankToTop(map);
127  
  S s = trim(unnull(map.get("Suggestion")));
128  
  logEvent("Suggestion chosen for editing", mapPlus(map, "Row", row+1, "Input", getInput(), "Top Suggesters", topSuggesters()));
129  
  setInput(s);
130  
}
131  
132  
svoid setInput(final S s) {
133  
  awtIfNecessary {
134  
    lastInput = input.getText();
135  
    input.setText(s);
136  
    input.selectAll();
137  
    input.requestFocus();
138  
  }
139  
}
140  
141  
svoid rankToTop(Map map) {
142  
  rankToTop(map, false);
143  
}
144  
145  
svoid rankToTop(Map map, bool removeISuggesters) {
146  
  if (map == null) ret;
147  
  O s = map.get("Suggesters");
148  
  // Table cells have been structure'd by dataToTable
149  
  L<S> sugg = s instanceof L ? (L) s : (L) unstructure((S) s);
150  
  
151  
  // These are cheaters!
152  
  if (removeISuggesters)
153  
    sugg = rejectWhere(func(S s) { s.endsWith("/i") }, sugg);
154  
  
155  
  thinker.rankToTop(first(sugg));
156  
}
157  
158  
svoid chooseSuggestion(int row) {
159  
  Map<S, S> map = getTableLineAsMap(table, row);
160  
  if (map == null) ret;
161  
  rankToTop(map);
162  
  S s = trim(unnull(map.get("Suggestion")));
163  
  if (empty(s)) ret;
164  
  
165  
  //logEvent("Suggestion chosen", mapPlus(map, "Row", row+1, "Input", getInput(), "Top Suggesters", topSuggesters));
166  
  setInput(s);
167  
  postAsUser(s, mapPlus(map, "Index", row+1));
168  
}
169  
170  
static L topSuggesters() {
171  
  int n = 20;
172  
  n = min(n, tableRows(table));
173  
  new L topSuggesters;
174  
  for (int i = 0; i < n; i++)
175  
    topSuggesters.add(getTableLineAsMap(table, i));
176  
  //if (empty(topSuggesters)) topSuggesters = null;
177  
  ret topSuggesters;
178  
}
179  
180  
svoid logEvent(S type) {
181  
  logEvent(type, litmap());
182  
}
183  
184  
svoid logEvent(S type, Map map) {
185  
  logStructure(new File(dialogDir(), "event.log"),
186  
    ll(type, chatTime(), map));
187  
}
188  
189  
static bool inputAllowedByUser(S i) {
190  
  ret !swic(i, systemPrefix);
191  
}
192  
193  
// may be called from other thread
194  
static void postSystemMessage(final S msg) {
195  
  if (empty(msg)) ret;
196  
  awtIfNecessary {
197  
    post(systemPrefix + " " + msg, litmap("By", "System"));
198  
  }
199  
}
200  
201  
static void post(S i) {
202  
  post(i, null);
203  
}
204  
205  
static void post(S i, Map infos) {
206  
  try {
207  
    i = trim(i);
208  
    if (empty(i)) ret;
209  
    //i = escapeNewLines(i);
210  
    
211  
    if (infos == null) {
212  
      infos = matchingSuggestion;
213  
      if (infos != null)
214  
        print("Ranking to top: " + struct(infos));
215  
      rankToTop(infos, true);
216  
    }
217  
    infos = mapPlus(infos, "Top Suggesters", topSuggesters());
218  
    
219  
    bool tooLong = l(i) > maxLongStringLength;
220  
    
221  
    if (l(i) > maxLineLength) {
222  
      S id = saveLongString(i);
223  
      i = substring(i, 0, maxLineLength) + "... [" + (tooLong ? "too " : "") + "long text " + id + "]";
224  
    }
225  
  } catch e {
226  
    printStackTrace(e);
227  
    i = systemPrefix + " " + exceptionToStringShort(e);
228  
  }
229  
  
230  
  S s = i + "\n";
231  
  //chat.append(escapeNewLines(i) + "\n");
232  
  appendToFile(logFile(), "[" + chatTime() + "] " + s);
233  
  logEvent("Posting", litmap("Text", i, "Infos", infos));
234  
  log.add(i);
235  
  updateChatTable();
236  
  input.selectAll();
237  
  updateOnce();
238  
  try {
239  
    action(i);
240  
  } catch e {
241  
    printStackTrace(e);
242  
    postSystemMessage(exceptionToStringShort(e));
243  
  }
244  
}
245  
246  
static S dropActionPrefix(S s) {
247  
  if (s == null) null;
248  
  s = dropBracketPrefix(s); // e.g. "[bot]"
249  
  if (!s.startsWith("!")) null;
250  
  ret s.substring(1);
251  
}
252  
253  
static bool isAction(S s) {
254  
  ret dropActionPrefix(s) != null;
255  
}
256  
257  
static void action(S s) {
258  
  s = dropActionPrefix(s);
259  
  if (s == null) ret;
260  
261  
  final S _s = s;
262  
  thread "Action" {
263  
    JWindow _loading_window = showLoadingAnimation();
264  
    try {
265  
      genLog_set(getLog()); // 'case user needs it
266  
      gOtherLogs_set(getOtherLogs()); // ditto
267  
      randomsOwnCmds(_s);
268  
      systemCommands(_s, mc());
269  
    } catch e {
270  
      printStackTrace(e);
271  
      postSystemMessage("Error - " + exceptionToStringShort(e));
272  
    } finally {
273  
      genLog_clear();
274  
      gOtherLogs_clear();
275  
      disposeWindow(_loading_window);
276  
    }
277  
  }
278  
}
279  
280  
static volatile bool again;
281  
282  
// This logic is bad...
283  
static void fillList(bool force) {
284  
  bool t = force || shouldUpdateList();
285  
  if (neq(t, thinking)) {
286  
    thinking = t;
287  
    setFrameIcon(table, t ? "#1003603" : "#1003593");
288  
  }
289  
  
290  
  if (!t) {
291  
    if (!force)
292  
      againl8r();
293  
  } else {
294  
    if (nempty(thinkThreads)) { again = true; ret; }
295  
    fillListImpl();
296  
  }
297  
}
298  
299  
static void addKeys(L<Map> data) {
300  
  for (int i = 0; i < l(data); i++) {
301  
    int k = i+1;
302  
    S key = k <= 12 ? "F" + k : null;
303  
    Map m = litorderedmap("Key", key);
304  
    m.putAll(data.get(i));
305  
    data.set(i, m);
306  
  }
307  
}
308  
309  
static void removeMatchingLine(L<Map> data) {
310  
  S input = getInput();
311  
  matchingSuggestion = null;
312  
  for (int i = 0; i < l(data); i++)
313  
    if (eq(input, data.get(i).get("Suggestion"))) {
314  
      matchingSuggestion = mapPlus(data.get(i), "Index", i+1);
315  
      data.remove(i);
316  
      ret;
317  
    }
318  
}
319  
320  
static void fillListImpl() {
321  
  thread "Fill List" {
322  
    try {
323  
      thinkThreads.add(currentThread());
324  
      final new L<Map> data;
325  
      
326  
      thinker.makeListData(cloneList(log), getInput(), getOtherLogs(), data);
327  
      
328  
      awt {
329  
        pcall {
330  
          removeMatchingLine(data);
331  
          addKeys(data);
332  
          dataToTable_uneditable(table, data);
333  
          tableColumnMaxWidth(table, 0, 30); // "Key" column
334  
        }
335  
        againl8r();
336  
      }
337  
    } finally {
338  
      thinkThreads.remove(currentThread());
339  
    if (again) { again = false; fillListImpl(); }
340  
    }
341  
  }
342  
}
343  
344  
static void updateOnce() { fillList(true); }
345  
346  
static void againl8r() {
347  
  swingAfter(table, listDelay, r { fillList(false); });
348  
}
349  
350  
static bool shouldUpdateList() {
351  
  bool result = false;
352  
  S text = " ";
353  
  if (getFrame(table).isFocused()) {
354  
    result = !mouseInComponent(table);
355  
    text = result ? " Thinking..." + (showCPU /*&& thinker.load != 0*/ ? " (" + thinker.load + "% CPU)" : "")
356  
      : "Not thinking cause you got the mouse in there";
357  
  }
358  
  status.setText(text);
359  
  ret result;
360  
}
361  
362  
// also called from outside
363  
static L<S> loadLog() {
364  
  log.clear();
365  
  log.addAll(scanEventLogForText(dialogDir()));
366  
  ret log;
367  
}
368  
369  
static void loadAllLogs() {
370  
  allLogs.clear();
371  
  for (File f : findAllFiles(getProgramDir()))
372  
    if (f.getName().equals("event.log"))
373  
      allLogs.put(f.getParentFile().getName(), new ImmL(scanEventLogForText(f)));
374  
}
375  
376  
synchronized static L<S> getLastFromLog(int n) {
377  
  ret cloneList(getLast(log, n));
378  
}
379  
380  
synchronized static L<S> getLog() {
381  
  ret cloneList(log);
382  
}
383  
384  
static File dialogDir() {
385  
  ret prepareProgramFile(dialog);
386  
}
387  
388  
static File logFile() {
389  
  ret new File(dialogDir(), "log.txt");
390  
}
391  
392  
static void switchDialog(final S name) {
393  
  swingAndWait(r {
394  
    dialog = name;
395  
    touchFile(new File(dialogDir(), "event.log"));
396  
    loadDialog();
397  
    loadAllLogs();
398  
    makeDialogsMenu();
399  
    setFrameTitle(dialog + " - " + getProgramTitle());
400  
401  
    // show special stuff for dialog, like an image
402  
    dialogImageID = trim(readTextFile(new File(dialogDir(), "image-id.txt")));
403  
    showDialogImage();
404  
  });
405  
}
406  
407  
static void loadDialog() {
408  
  loadLog();
409  
  thinker = new Thinker;
410  
  thinker.startUp(log);
411  
  //chat.setText(joinLines(log));
412  
  updateChatTable();
413  
}
414  
415  
static void randomsOwnCmds(S s) {
416  
  new Matches m;
417  
  
418  
  if "dialog *" {
419  
    switchDialog(m.unq(0));
420  
    // TODO: show current dialog somewhere else
421  
    //postSystemMessage("OK, dialog switched to " + quote(dialog));
422  
  }
423  
  
424  
  if "gen"
425  
    generators = null;
426  
  
427  
  if "delete"
428  
    updateChatTable();
429  
    
430  
  if "analyzers"
431  
    showAnalyzers();
432  
    
433  
  if (matchOneOf(s, m, "img *", "image *")) {
434  
    S imageID = m.fsi(0);
435  
    saveTextFile(new File(dialogDir(), "image-id.txt"), imageID);
436  
    dialogImageID = imageID;
437  
    showDialogImage();
438  
  }
439  
  
440  
  if (matchOneOf(s, m, "img", "image")) {
441  
    if (empty(dialogImageID))
442  
      postSystemMessage("No image set for this dialog");
443  
    else
444  
      postSystemMessage("Image for this dialog: " + fsI(dialogImageID));
445  
  }
446  
}
447  
448  
static void showAnalyzers() {
449  
  if (analyzersFrame == null)
450  
    analyzersFrame = showFrame("Analyzers");
451  
}
452  
453  
static void updateChatTable() {
454  
  awtIfNecessary {
455  
    new L data;
456  
    L<L> l = scanLog_safeUnstructure(new File(dialogDir(), "event.log"));
457  
    for (int i = 0; i < l(l); i++) pcall {
458  
      L a = l.get(i), prev = get(l, i-1);
459  
      if (firstIs(a, "Posting")) {
460  
        Map map = cast get(a, 2);
461  
        S text = getString(map, "Text").trim();
462  
        if (eq(text, "!delete")) { removeLast(data); continue; }
463  
        S idx = "";
464  
        Map infos = cast map.get("Infos");
465  
        if (infos != null && infos.containsKey("Index"))
466  
          idx = str(infos.get("Index"));
467  
        else pcall {
468  
          //printStruct("prev: ", prev);
469  
          if (prev != null && firstIs(prev, "Suggestion chosen for editing")) {
470  
            Map m = getMap(prev, 2);
471  
            S suggestion = getString(m, "Suggestion");
472  
            //print("Suggestion: " + structure(suggestion));
473  
            idx = str(get(m, "Row"));
474  
            if (neq(suggestion, text))
475  
              idx += "?";
476  
          }
477  
        }
478  
        data.add(litorderedmap("Text", escapeNewLines(text), "Sugg." /* Suggestion Index */, idx));
479  
      }
480  
    }
481  
    dataToTable_uneditable(chatTable, data);
482  
    tableColumnMaxWidth(chatTable, 1, 40); // enough for 2 digits and a "?"
483  
    scrollTableDownIn(chatTable, 50);
484  
  }
485  
}
486  
487  
static synchronized S saveLongString(S s) {
488  
  s = substring(s, 0, maxLongStringLength);
489  
  S id;
490  
  File f;
491  
  do {
492  
    id = randomID(10);
493  
    f = getProgramFile("long-strings/" + id);
494  
  } while (f.exists());
495  
  
496  
  saveTextFile(f, s);
497  
  ret id;
498  
}
499  
500  
static O generators;
501  
502  
static void makeGenerators(L<Gen> l) {
503  
  synchronized(main.class) {
504  
    if (!isSnippetID(generatorsID)) fail("No generators ID set");
505  
    if (generators == null)
506  
      generators = hotwire(generatorsID);
507  
  }
508  
  new L l2;
509  
  callOpt(generators, "makeGenerators", l2);
510  
  callOpt(generators, "deterministicGenerators", l2);
511  
  l.addAll((L) quickImport(l2));
512  
}
513  
514  
static S rawDialog() {
515  
  ret fromLines(log);
516  
}
517  
518  
static void makeDialogsMenu() {
519  
  new L items;
520  
  for (File dir : listDirs(getProgramDir()))
521  
    if (containsFile(dir, "event.log")) {
522  
      fS dialog = dir.getName();
523  
      items.add(dialog);
524  
      items.add(r { switchDialog(dialog); });
525  
    }
526  
    
527  
  addMenu(frame, "Dialogs", items);
528  
}
529  
530  
static L<ImmL<S>> getOtherLogs() {
531  
  // TODO: sort by latest or smth?
532  
  ret valuesList(mapMinus(allLogs, dialog));
533  
}      
534  
535  
static void hideDialogImage() {
536  
  if (dialogImageFrame != null) {
537  
    disposeFrame(dialogImageFrame);
538  
    dialogImageFrame = null;
539  
  }
540  
}
541  
542  
static void showDialogImage() {
543  
  hideDialogImage();
544  
  if (nempty(dialogImageID)) {
545  
  S title = getSnippetTitle(dialogImageID) + " [" + fsI(dialogImageID) + "/" + dialog + "]";
546  
    dialogImageFrame = getFrame(showImage(dialogImageID, title));
547  
  }
548  
}

Author comment

Began life as a copy of #1003886

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: #1004031
Snippet name: Random Main v9
Eternal ID of this version: #1004031/1
Text MD5: c5e17d570973834cab9d8fa386574b8b
Author: stefan
Category: javax / talking robots
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-08-13 13:39:36
Source code size: 14436 bytes / 548 lines
Pitched / IR pitched: No / No
Views / Downloads: 617 / 965
Referenced in: [show references]