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

609
LINES

< > BotCompany Repo | #1004308 // Random Main v10

JavaX fragment (include)

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

Author comment

Began life as a copy of #1004031

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1004308
Snippet name: Random Main v10
Eternal ID of this version: #1004308/2
Text MD5: 706da8b26d71ac5b611cf1bf27251849
Author: stefan
Category: javax / talking robots
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2020-07-02 11:52:57
Source code size: 16821 bytes / 609 lines
Pitched / IR pitched: No / No
Views / Downloads: 1076 / 1598
Version history: 1 change(s)
Referenced in: [show references]