!7 static Map theoryForLineMap; static L globalIDList; // msg index to global ID sbool listen = true; static O onUpdate; static L peepHoleWebs; p { if (isMain()) autoRestart(); theoryForLineMap = persistentHashMap('theoryForLineMap); globalIDList = persistentList('globalIDList); if (empty(globalIDList)) loadFullHistory(); if (listen) { print("Listening to chat."); stefansChat_onLine(100, voidfunc(S line) { ChatMsg msg = mapToObject(stefansChat_onLine_fullParams!, ChatMsg); handleChatMsg(msg); pcallF(onUpdate); }); } bot("Chat Theory."); onFileChangeAndNow(1, ai_chatAnalysis_peepHoleFile(), r { peepHoleWebs = ai_chatAnalysis_peepHoleWebs(); }); } svoid loadFullHistory() { int max = 10000; L l = stefansChat_readArchive(max); print("Got " + l(l) + "/" + max); for (ChatMsg msg : l) pcall { handleChatMsg(msg); } } svoid handleChatMsg(ChatMsg msg) { lock dbLock(); //print("Handling " + msg.globalID); listPut(globalIDList, msg.nr, msg.globalID); Web web = theoryForLineMap.get(msg.globalID); if (web != null) ret; // No overwrite for now WebNode n = simpleWeb().newNode(); n.addLabel(/*"Text " +*/ quote(msg.text)); web_addString(n, msg.botMark ? "by bot" : "by user"); web_addStrings(n, ai_categoriesForChatLine(msg.text)); web_addString(n, "Time " + msg.time); web_addString(n, "Should I react?"); n.addLabel("Msg " + msg.globalID); transformers(n); if (web_contentsDifferent(web, n.web)) { if (web != null) print("Overwriting " + msg.globalID); else print("Storing " + msg.globalID); theoryForLineMap.put(msg.globalID, n.web); } } svoid transformers(WebNode n) { for (S text : web_texts(n)) { for (WebNode a : indexedNodes(quote(text))) { WebNode b = web_operand(a, "with"); if (b == null || !web_hasLabel(n, web_unquote(b))) continue; WebNode c = web_operand(b, "transforms to"); if (c != null) web_replaceLabel(n, text, web_unquote(c)); } } } answer { if "show *" ret showWeb(theoryForLineMap.get($1)) != null ? "OK" : "Not found"; if "load full history" ret "OK" with loadFullHistory(); if "size" ret lstr(theoryForLineMap); } static Web lastWeb() { ret theoryForLineMap.get(last(globalIDList)); } static WebNode lastNode() { ret web_firstNode(lastWeb()); } sS html_thoughts() { lock dbLock(); Web web = lastWeb(); if (web == null) ret ""; WebNode node = web_firstNode(web); L texts = web_texts(node); S html = ul_htmlencode(texts); //new LinkedHashSet expect; final new Map expect; for (Web pw : unnull(peepHoleWebs)) { for (WebNode a : web_allNodesNamed(pw, texts)) { WebNode b = web_operand(a, "then"); if (b != null) for (S s : web_texts(b)) putHigherInt(expect, s, 100); b = web_operand(a, "then maybe"); if (b != null) { int percent = 50; pcall { S ratio = web_string(web_getRelation(a, b), 1); percent = ratioToIntPercent(parseFirstInt(ratio), parseSecondInt(ratio)); } for (S s : web_texts(b)) putHigherInt(expect, s, percent); } } } expect.remove("Should I react?"); if (nempty(expect)) html += "Expecting:" + ul_htmlencode( map(keys(expect), func(S key) { int percent = expect.get(key); ret key + (percent >= 100 ? "" : " (" + percent + "%)"); })); ret html; } svoid react { pcall { lock dbLock(); WebNode n = lastNode(); if (n == null) ret; if (web_hasLabel(n, "I should react") && web_hasLabel(n, "greeting")) { web_replaceLabel(n, "I should react", "I reacted"); change(); postToStefansChat("Hello Bozo"); } }}