UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

174 lines (127 loc) 4.31 kB
import { HashMap } from "../../../../core/collection/map/HashMap.js"; import { MultiPredicateEvaluator } from "../../../../core/model/reactive/evaluation/MultiPredicateEvaluator.js"; import { StaticKnowledgeDataTable } from "../../../knowledge/database/StaticKnowledgeDataTable.js"; import { DynamicRuleDescription } from "./DynamicRuleDescription.js"; export class DynamicRuleDescriptionTable extends StaticKnowledgeDataTable { /** * Used to speed up finding most complex matching predicate * @type {DynamicRuleDescription[]} * @private */ __sorted_by_predicate_complexity = []; /** * * @type {HashMap<ReactiveExpression, DynamicRuleDescription[]>} * @private */ __predicate_rule_mapping = new HashMap(); /** * * @param {ReactiveExpression} predicate * @return {DynamicRuleDescription[]|undefined} */ getRulesByPredicate(predicate) { return this.__predicate_rule_mapping.get(predicate); } /** * * @return {MultiPredicateEvaluator} */ buildEvaluator() { const evaluator = new MultiPredicateEvaluator(exp => exp.computeTreeSize()); /** * * @type {DynamicRuleDescription[]} */ const rules = this.asArray(); evaluator.build(rules.map(r => r.condition)); return evaluator; } buildIndex() { /** * * @type {DynamicRuleDescription[]} */ const rules = this.asArray(); // build sorted version this.__sorted_by_predicate_complexity = rules.slice(); this.__sorted_by_predicate_complexity.sort((a, b) => { return b.getPredicateComplexity() - a.getPredicateComplexity(); }); // build predicate rule mapping const n = rules.length; for (let i = 0; i < n; i++) { const rule = rules[i]; const bucket = this.__predicate_rule_mapping.get(rule.condition); if (bucket === undefined) { this.__predicate_rule_mapping.set(rule.condition, [rule]); } else { bucket.push(rule); } } } /** * * @param {Object} context * @returns {DynamicRuleDescription|undefined} */ matchBest(context) { /** * * @type {DynamicRuleDescription[]} */ const data = this.__sorted_by_predicate_complexity; const n = data.length; main:for (let i = 0; i < n; i++) { const rule = data[i]; const references = rule.references; const n = references.length; for (let i = 0; i < n; i++) { const reactiveReference = references[i]; if (context[reactiveReference.name] === undefined) { continue main; } } const isMatch = rule.condition.evaluate(context); if (isMatch) { return rule; } } return undefined; } /** * * @param {Object} context * @returns {DynamicRuleDescription[]} */ match(context) { const result = []; const data = this.__array; const n = data.length; main:for (let i = 0; i < n; i++) { const rule = data[i]; const references = rule.references; const n = references.length; for (let i = 0; i < n; i++) { const reactiveReference = references[i]; if (context[reactiveReference.name] === undefined) { continue main; } } const isMatch = rule.condition.evaluate(context); if (isMatch) { result.push(rule); } } return result; } link(database, assetManager, executor) { this.buildIndex(); return super.link(database, assetManager, executor); } parse(json) { const r = new DynamicRuleDescription(); r.fromJSON(json); return r; } }