!7 set flag DynModule. sclass Entry { //S originalRule, replacements, modifiedRule; S rule; S judgement = ""; S struct; sS _fieldOrder = "rule judgement struct"; } cmodule TestRuleEngine2 > DynObjectTable { S input, processedInput; transient ReliableSingleThread rstCalc = dm_rstWithPostDelay(this, r calc, 500); start { set fieldsInOrder; //hideFields = litset('struct); } visualize { JComponent tf = dm_textField('input); onChangeAndNow(tf, rstCalc); ret northCenterAndSouthWithMargins( centerAndEastWithMargin( tf, jbutton("Make rule...", rThread makeRule)), super.visualize(), rightAlignedButtons( tableDependentButton(table(), "Mark good", rMark('good)), tableDependentButton(table(), "Mark bad", rMark('bad)), tableDependentButton(table(), "Mark funny", rMark('funny)) )); } Runnable rMark(fS judgement) { ret rThread { Entry e = selected(); e.judgement = judgement; fireDataChanged(); saveEntry(e); }; } void calc { S input = this.input; final new RuleEngine2 engine; engine.addRules2(dm_allRulesFromRulesModuleWithCommentsAndIDs()); L l = ai_ruleEngine2_rulesForInput_3(engine, input); l = sortByMethodDesc qualitySum(l); setList(map(l, func(RuleEngine2_MatchedRule r) -> Entry { S modifiedRule = engine.formatForUser(r.applyMapping().asText()); ret nu(Entry, rule := modifiedRule, struct := struct(r)); })); processedInput = input; } void saveEntry(Entry e) { dm_requireAndCall("#1021413/AppliedRules", 'uniqConcept, litobjarrayAsObject( modifiedRule := e.rule, judgement := e.judgement, matchedRuleStruct := e.struct)); } void makeRule { final JTextField tf1 = jtextfield(input); final JTextField tf2 = jtextfield(input); showFormTitled("Make a rule", "When", tf1, "Then", tf2, r { Pair p = dm_gazelle_addRule(gtt(tf1), gtt(tf2)); infoBox(p.b ? "Rule " + p.a + " added" : "Rule already there: " + p.a); }); } }