!7 p { useLocalMechListCopies(); } html { uri = dropPrefix("/", uri); Pair, LS> p = ai_activeRulesAndFacts(); L rules = p.a; LS facts = p.b; S ruleID = urldecode(uri); if (empty(uri)) { // Rule list ret h2_title(n2(rules, "rule") + " (showing first trigger)") + ul(map_pcall(reversed(rules), func(IfThen rule) { S s = ahref("/rules/" + urlencode(rule.globalID), htmlencode(rule.globalID)); Exp e = nlLogic_firstCondition(rule); if (e != null) s += " - " + htmlencode(e); ret tt(s); })); } L found = filterByField(rules, globalID := ruleID); if (empty(found)) ret "Rule " + htmlencode(ruleID) + " not found"; new StringBuilder buf; if (l(found) > 1) buf.append(p("Bad: Multiple rules for ID " + htmlencode(ruleID) + ".")); for (IfThen rule : found) { buf.append(h2_title("Rule " + htmlencode(rule.globalID))); buf.append(hsourcecode(/*str(rule)*/ rule.originalText)); if (ai_ruleDifferentFromOriginalText(rule)) { buf.append(h3("Loaded as")); buf.append(hsourcecode(str(rule))); } LS ruleFacts = stringsContaining(facts, ruleID); if (nempty(ruleFacts)) { buf.append(h3("Facts about this rule")); buf.append(hsourcecode(ruleFacts)); } } ret buf; }