summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Paul <n@nc0.fr>2024-03-08 16:01:30 +0100
committerNicolas Paul <n@nc0.fr>2024-03-08 23:12:55 +0100
commit9459d7a1661ee70df4da10e766857e9ab56be71d (patch)
tree6159ad1a9455506e1f7bf813b4d350fb50f9fb30
parenta03adb2b24c2a3b69fbb6c1ab31056e8780d6fa8 (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.js1
-rw-r--r--life2/game/rules_manager.js88
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);
+ }
+}