concept AppliedRule { S globalID = aGlobalID(); S ruleID; S modifiedRule; S outText; S judgement; S comments; S varMap; S matchedRuleStruct; S intention, context; } abstract sclass DynAppliedRules extends DynCRUD { start { dbIndexing(AppliedRule, 'ruleID, AppliedRule, 'context, AppliedRule, 'globalID); for (AppliedRule r : list()) fixEntry(r); dm_registerAs('gazelleFeedbackCRUD); addCountToName(); } enhanceFrame { internalFrameIcon(f, gazelle_frameIcon()); } void fixEntry(AppliedRule r) { if (r.ruleID == null) { S ruleID = "?"; pcall { ruleID = gazelle_ruleIDFromMatchedRuleStruct(r.matchedRuleStruct); } cset(r, +ruleID); } if (r.varMap == null) { S varMap = ""; pcall { varMap = sfu(gazelle_varMapFromMatchedRuleStruct(r.matchedRuleStruct); } cset(r, +varMap); } if (r.outText == null) { S outText = ""; pcall { outText = gazelle_outTextFromMatchedRuleStruct(r.matchedRuleStruct); } cset(r, +outText); } if (r.modifiedRule == null) { S modifiedRule = ""; pcall { modifiedRule = gazelle_modifiedRuleFromMatchedRuleStruct(r.matchedRuleStruct); } cset(r, +modifiedRule); } } // API AppliedRule getFeedback(S globalID) { ret conceptWhere AppliedRule(+globalID); } L feedbackForRule(S ruleID) { ret asList(conceptsWhere AppliedRule(+ruleID)); } Map stats() { ret multiSetToMap(collectMultiSet ruleID(concepts())); } Map statsByJudgement() { new MultiSet ms; for (AppliedRule r : concepts()) ms.add(r.ruleID + "/" + r.judgement); ret multiSetToMap(ms); } AppliedRule uniqConcept(O... params) { AppliedRule r = super.uniqConcept(params); fixEntry(r); ret r; } Cl applicationsForContext(S context) { ret conceptsWhere(AppliedRule, +context); } Cl allGoodFeedback() { ret conceptsWhere(AppliedRule, judgement := 'good); } }