!7 concept Entry { long msgID; S line; S preprocessed; S ruleIDs; // rule(s) used for preprocessing sS _fieldOrder = "msgID originalLine preprocessed"; } set flag DynModule. cmodule InterpretableTest > DynCRUD { transient int maxInterpretablesPerLine = 20; start { dbIndexing(Entry, 'msgID); addCountToName(); //thread { scan(); } } visualize { ret withCenteredButtons(super.visualize(), "Scan", rThread scan); } void fullScan enter { new L list; new Flag interrupted; temp AutoCloseable action = dm_currentAction("Scanning chat", rRaiseFlag(interrupted)); F0 contextMaker = new GazelleContextCache_v2().fill(); L lines = dm_discord_allLines(); for (GazelleLine line : reversed(lines)) { if (!licensed() || interrupted!) break; scanLine(line, +contextMaker); } } void scanLine(GazelleLine line, O... _) { new L list; Collection l = takeFirst(maxInterpretablesPerLine, gazelle_preprocess(line.text, _)); for (GInterpretable intp : l) list.add(unlistedWithValues Entry( msgID := line.msgID, line := line.text, preprocessed := intp.text, ruleIDs := intp.ruleID)); replaceItemsForMessage(line.msgID, list); } void replaceItemsForMessage(long msgID, L items) { deleteConceptsWhere Entry(+msgID); registerAll(items); } }