diff options
| author | Nicolas Paul <n@nc0.fr> | 2024-03-08 16:01:30 +0100 |
|---|---|---|
| committer | Nicolas Paul <n@nc0.fr> | 2024-03-08 23:12:55 +0100 |
| commit | 9459d7a1661ee70df4da10e766857e9ab56be71d (patch) | |
| tree | 6159ad1a9455506e1f7bf813b4d350fb50f9fb30 | |
| parent | a03adb2b24c2a3b69fbb6c1ab31056e8780d6fa8 (diff) | |
Add RulesManager helper
RulesManager is a utility class that has the responsability of storing
and managing a set of rules. Rules are identified by their name,
meaning that there cannot be two rules with the same names. However, no
check is done on the function content:
const func = (cell, _) => cell;
const rule1 = new Rule("foo", "", func);
const rule2 = new Rule("bar", "", func);
const rule3 = new Rule("foo", "", func);
const manager = new RulesManager();
manager.add(rule1); // OK
manager.add(rule2); // OK because "foo" != "bar"
manager.add(rule3); // Error("Rule 'foo' is already registered')
Also, the manager internally use a JavaScript Map object, meaning the
order returned when getting all registered rules is not promised to be
the same has the order of registration. This also means that the
performance and time complexity of the object is dependant on the
JavaScript engine (the ECMA Script specification only imposes a
datastructure where operations have a complexity better than O(n)).
I believe it is a non-issue as the manager should not keep a lot of
rules anyway.
The reason for the existance of the RulesManager class is to simplify
the facade that is the World class.
Signed-off-by: Nicolas Paul <n@nc0.fr>
| -rw-r--r-- | life2/game/index.js | 1 | ||||
| -rw-r--r-- | life2/game/rules_manager.js | 88 |
2 files changed, 89 insertions, 0 deletions
diff --git a/life2/game/index.js b/life2/game/index.js index 276e452..f6c0ff5 100644 --- a/life2/game/index.js +++ b/life2/game/index.js @@ -24,3 +24,4 @@ export {Board, Grid} from './board'; export {Cell} from './cell'; export {Rule, RuleFunction} from './rule'; +export {RulesManager} from './rules_manager'; diff --git a/life2/game/rules_manager.js b/life2/game/rules_manager.js new file mode 100644 index 0000000..5dc0149 --- /dev/null +++ b/life2/game/rules_manager.js @@ -0,0 +1,88 @@ +/** + * Copyright 2024 The Life2 Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * @license + */ + +/** + * @fileoverview RulesManager is a class responsible to manage a set of Rules, + * such as (un)registering some, enabling or disabling others... + * + * @package life2 + */ + +import {Rule} from './rule'; + +/** + * The RulesManager class is responsible to manage a set of Rules, such as + * (un)registering some, enabling or disabling others... + */ +export class RulesManager { + /** + * Creates a new rules manager. + * @param {?Array<!Rule>} rules A list of rules to add and enable by default. + */ + constructor(rules) { + /** + * The store of rules. + * @type {!Map<string, !Rule>} + * @private + */ + this.store_ = new Map(); + if (rules) rules.forEach((r) => this.add(r)); + } + + /** + * Returns the list of rules. + * @return {!Array<!Rule>} The list of rules. + */ + getAll() { + return Array.from(this.store_.values()); + } + + /** + * Registers a new rule. + * @param {!Rule} rule The rule to register. + * @throws {Error} If the rule is already registered. + */ + add(rule) { + if (this.has(rule.name)) { + throw new Error(`Rule '${rule.name}' is already registered.`); + } + + this.store_.set(rule.name, rule); + } + + /** + * Unregisters a rule. + * @param {string} rule The name of the rule to unregister. + * @return {!Rule} The rule that was unregistered. + * @throws {Error} If the rule is not registered. + */ + remove(rule) { + if (!this.has(rule)) throw new Error(`Rule '${rule}' is not registered.`); + const r = this.store_.get(rule); + this.store_.delete(rule); + return r; + } + + /** + * Checks if a rule is registered. + * @param {string} rule The name of the rule to check. + * @return {boolean} True if the rule is registered, false otherwise. + */ + has(rule) { + return this.store_.has(rule); + } +} |
