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

372
LINES

< > BotCompany Repo | #1003886 // Random Main (v8)

JavaX fragment (include)

static S generatorsID;

static JTable table, chatTable;
static JTextArea chat;
static JTextField input;
static L<S> log = synchroList();
static L<S> recommendations;
static L<Thread> thinkThreads = synchroList();
static JLabel status;

static int listDelay = 2000;
static int maxLineLength = 1000;
static int maxLongStringLength = 100*1000;

static Bool thinking;
static new Thinker thinker;

static S systemPrefix = "[system]";

static S dialog = "new";

svoid randomMain {
  //substanceLAF("EmeraldDusk"); // Too dark!
  substanceLAF("ChallengerDeep");

  table = tableWithTooltips();
  chat = autoScroll(wordWrapTextArea());
  chatTable = tableWithTooltips();
  input = new JTextField;
  status = new JLabel(" ");
  
  JFrame frame = showFrame(vgrid(centerAndSouth(
    jtabs(1, "Chat", chat, "Details", chatTable),
    input), centerAndSouth(table, status)));
  //setFrameIconLater(frame, "#1003593");
  
  onEnter(input, r {
    post();
  });
  
  onDoubleClick(table, voidfunc(int row) {
    chooseSuggestion(row);
  });
  
  for (int i = 1; i <= 12; i++) {
    final int _i = i;
    registerFunctionKey(frame, i, r {
      chooseSuggestionForEditing(_i-1);
    });
    registerShiftFunctionKey(frame, i, r {
      chooseSuggestion(_i-1);
    });
  }
  
  onUpdate(input, r { updateOnce(); });
  
  loadDialog();
  logEvent("Starting");
  
  updateOnce();
  
  input.requestFocus();
  
  if (isAction(last(log)) && confirmYesNo(input, "Run action? " + last(log)))
    action(last(log));
}

static S getInput() {
  ret joinLines(" # ", input.getText().trim());
}

sv post() {
  postAsUser(getInput(), null);
}

static void postAsUser(S i, Map infos) {
  if (inputAllowedByUser(i))
    post(i, infos);
}

svoid chooseSuggestionForEditing(int row) {
  Map<S, S> map = getTableLineAsMap(table, row);
  if (map == null) ret;
  rankToTop(map);
  S s = trim(unnull(map.get("Suggestion")));
  logEvent("Suggestion chosen for editing", mapPlus(map, "Row", row+1, "Input", getInput(), "Top Suggesters", topSuggesters()));
  input.setText(s);
  input.selectAll();
  input.requestFocus();
}

svoid rankToTop(Map map) {
  // Table cells have been structure'd by dataToTable
  thinker.rankToTop(first((L<S>) unstructure(getString(map, "Suggesters"))));
}

svoid chooseSuggestion(int row) {
  Map<S, S> map = getTableLineAsMap(table, row);
  if (map == null) ret;
  rankToTop(map);
  S s = trim(unnull(map.get("Suggestion")));
  if (empty(s)) ret;

  //logEvent("Suggestion chosen", mapPlus(map, "Row", row+1, "Input", getInput(), "Top Suggesters", topSuggesters));
  input.setText(s);
  postAsUser(s, mapPlus(map, "Index", row+1));
}

static L topSuggesters() {
  int n = 20;
  n = min(n, tableRows(table));
  new L topSuggesters;
  for (int i = 0; i < n; i++)
    topSuggesters.add(getTableLineAsMap(table, i));
  //if (empty(topSuggesters)) topSuggesters = null;
  ret topSuggesters;
}

svoid logEvent(S type) {
  logEvent(type, litmap());
}

svoid logEvent(S type, Map map) {
  logStructure(new File(dialogDir(), "event.log"),
    ll(type, chatTime(), map));
}

static bool inputAllowedByUser(S i) {
  ret !swic(i, systemPrefix);
}

// may be called from other thread
static void postSystemMessage(final S msg) {
  if (empty(msg)) ret;
  awtIfNecessary {
    post(systemPrefix + " " + msg, litmap("By", "System"));
  }
}

static void post(S i, Map infos) {
  try {
    i = trim(i);
    if (empty(i)) ret;
    //i = escapeNewLines(i);
    infos = mapPlus(infos, "Top Suggesters", topSuggesters());
    
    bool tooLong = l(i) > maxLongStringLength;
    
    if (l(i) > maxLineLength) {
      S id = saveLongString(i);
      i = substring(i, 0, maxLineLength) + "... [" + (tooLong ? "too " : "") + "long text " + id + "]";
    }
  } catch e {
    printStackTrace(e);
    i = systemPrefix + " " + exceptionToStringShort(e);
  }
  
  S s = i + "\n";
  chat.append(escapeNewLines(i) + "\n");
  appendToFile(logFile(), "[" + chatTime() + "] " + s);
  logEvent("Posting", litmap("Text", i, "Infos", infos));
  log.add(i);
  updateChatTable();
  input.selectAll();
  updateOnce();
  try {
    action(i);
  } catch e {
    printStackTrace(e);
    postSystemMessage(exceptionToStringShort(e));
  }
}

static S dropActionPrefix(S s) {
  if (s == null) null;
  s = dropBracketPrefix(s); // e.g. "[bot]"
  if (!s.startsWith("!")) null;
  ret s.substring(1);
}

static bool isAction(S s) {
  ret dropActionPrefix(s) != null;
}

static void action(S s) {
  s = dropActionPrefix(s);
  if (s == null) ret;

  final S _s = s;
  thread "Action" {
    loading {
      try {
        genLog_set(getLog()); // 'case user needs it
        randomsOwnCmds(_s);
        actionImpl(_s); // user must provide this
      } catch e {
        printStackTrace(e);
        postSystemMessage("Error - " + exceptionToStringShort(e));
      }
    }
  }
}

static volatile bool again;

// This logic is bad...
static void fillList(bool force) {
  bool t = force || shouldUpdateList();
  if (neq(t, thinking)) {
    thinking = t;
    setFrameIcon(table, t ? "#1003603" : "#1003593");
  }
  
  if (!t) {
    if (!force)
      againl8r();
  } else {
    if (nempty(thinkThreads)) { again = true; ret; }
    fillListImpl();
  }
}

static void fillListImpl() {
  thread "Fill List" {
    try {
      thinkThreads.add(currentThread());
      final new L<S> data;
      thinker.makeListData(cloneList(log), getInput(), data);
      
      awt {
        pcall {
          dataToTable_uneditable(table, data);
          tableColumnMaxWidth(table, 0, 30); // "Key" column
        }
        againl8r();
      }
    } finally {
      thinkThreads.remove(currentThread());
    if (again) { again = false; fillListImpl(); }
    }
  }
}

static void updateOnce() { fillList(true); }

static void againl8r() {
  swingAfter(table, listDelay, r { fillList(false); });
}

static bool shouldUpdateList() {
  bool result = false;
  S text = " ";
  if (getFrame(table).isFocused()) {
    result = !mouseInComponent(table);
    text = result ? " Thinking... "
      : "Not thinking cause you got the mouse in there";
  }
  status.setText(text);
  ret result;
}

// also called from outside
static L<S> loadLog() {
  log.clear();
  log.addAll(collect(scanEventLogForPosts(dialogDir()), "text"));
  ret log;
}

synchronized static L<S> getLastFromLog(int n) {
  ret cloneList(getLast(log, n));
}

synchronized static L<S> getLog() {
  ret cloneList(log);
}

static File dialogDir() {
  ret prepareProgramFile(dialog);
}

static File logFile() {
  ret new File(dialogDir(), "log.txt");
}

static void switchDialog(final S name) {
  swingAndWait(r {
    dialog = name;
    loadDialog();
  });
}

static void loadDialog() {
  loadLog();
  thinker = new Thinker;
  thinker.startUp(log);
  chat.setText(joinLines(log));
  updateChatTable();
}

static void randomsOwnCmds(S s) {
  new Matches m;
  if "dialog *" {
    switchDialog(m.unq(0));
    // TODO: show current dialog somewhere else
    //postSystemMessage("OK, dialog switched to " + quote(dialog));
  }
  
  if "gen"
    generators = null;
  
  if "delete"
    updateChatTable();
}

static void updateChatTable() {
  assertAWT();
  new L data;
  L<L> l = scanLog_safeUnstructure(new File(dialogDir(), "event.log"));
  for (int i = 0; i < l(l); i++) pcall {
    L a = l.get(i), prev = get(l, i-1);
    if (firstIs(a, "Posting")) {
      Map map = cast get(a, 2);
      S text = getString(map, "Text").trim();
      if (eq(text, "!delete")) { removeLast(data); continue; }
      S idx = "";
      Map infos = cast map.get("Infos");
      if (infos != null && infos.containsKey("Index"))
        idx = str(infos.get("Index"));
      else pcall {
        //printStruct("prev: ", prev);
        if (prev != null && firstIs(prev, "Suggestion chosen for editing")) {
          Map m = getMap(prev, 2);
          S suggestion = getString(m, "Suggestion");
          //print("Suggestion: " + structure(suggestion));
          idx = str(get(m, "Row"));
          if (neq(suggestion, text))
            idx += "?";
        }
      }
      data.add(litorderedmap("Text", escapeNewLines(text), "SI" /* Suggestion Index */, idx));
    }
  }
  dataToTable_uneditable(chatTable, data);
  tableColumnMaxWidth(chatTable, 1, 40); // enough for 2 digits and a "?"
  scrollTableDown(chatTable);
}

static synchronized S saveLongString(S s) {
  s = substring(s, 0, maxLongStringLength);
  S id;
  File f;
  do {
    id = randomID(10);
    f = getProgramFile("long-strings/" + id);
  } while (f.exists());
  
  saveTextFile(f, s);
  ret id;
}

static O generators;

static void makeGenerators(L<Gen> l, L<S> log) {
  synchronized(main.class) {
    if (!isSnippetID(generatorsID)) fail("No generators ID set");
    if (generators == null)
      generators = hotwire(generatorsID);
  }
  new L l2;
  call(generators, "makeGenerators", l2, log);
  l.addAll((L) quickImport(l2));
}

Author comment

Began life as a copy of #1003813

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: #1003886
Snippet name: Random Main (v8)
Eternal ID of this version: #1003886/1
Text MD5: d3d0c7e391bfd4326bf51a6c9bc744a4
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-04 14:02:14
Source code size: 9213 bytes / 372 lines
Pitched / IR pitched: No / No
Views / Downloads: 745 / 895
Referenced in: #1003887 - "Random" v8
#1004031 - Random Main v9