sclass NewWoody { transient Map rulesByName; transient new L badRules; Map ruleData = ciMap(); S lastOutput; BBRule lastRule, activeRule; sclass RuleData { int answerIndex; } RuleData ruleData(BBRule rule) { ret getOrCreate(ruleData, rule.listName, RuleData.class); } *() { if (!DynamicObject_isLoading()) rulesByName = indexFieldAsCIMap('listName, bb_allRules()); } *(NewWoody w) { initFrom(w); } void initFrom(NewWoody w) { copyFields(w, this, 'rulesByName, 'badRules); } void processInput(S input) { lastRule = null; lastOutput = null; temp tempSetTL(ctxContext_var(), nu(CtxContext, +input)); new L matching; for (BBRule r : valuesList(rulesByName)) if (ruleExpressionMatches(r)) matching.add(r); activeRule = lastRule = or(first(matching), activeRule); if (activeRule != null) if (cic(activeRule.answerMode, 'random)) lastOutput = random(activeRule.answers); else { RuleData rd = ruleData(activeRule); lastOutput = get(activeRule.answers, rd.answerIndex %= max(1, l(activeRule.answers))); ++rd.answerIndex; } } bool ruleExpressionMatches(BBRule r) { if (empty(r.expression)) false; try { ret ctxEvalCondition(r.expression); } catch print e { badRules.add(r); rulesByName.remove(r.listName); false; } } L listsMatchingInput(S input) { temp tempSetTL(ctxContext_var(), nu(CtxContext, +input)); ret [BBRule r : valuesList(rulesByName) | ruleExpressionMatches(r)]; } }