aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/appearance
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/modules/appearance')
-rw-r--r--desktop/modules/appearance/TransitionPick.js32
-rw-r--r--desktop/modules/appearance/test_transitions.js51
2 files changed, 83 insertions, 0 deletions
diff --git a/desktop/modules/appearance/TransitionPick.js b/desktop/modules/appearance/TransitionPick.js
new file mode 100644
index 0000000..3a8b11a
--- /dev/null
+++ b/desktop/modules/appearance/TransitionPick.js
@@ -0,0 +1,32 @@
+.pragma library
+
+// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Which transition plays, tested by test_transitions.js under node.
+
+// The name for a run. `pick` is a name or "random"; `pool` is what random may
+// draw; `last` is what played last, skipped while there is anything else.
+function choose(pick, pool, last) {
+ if (pick !== "random") return pick;
+ const from = pool.length > 1 ? pool.filter(n => n !== last) : pool;
+ return from.length ? from[Math.floor(Math.random() * from.length)] : "burn";
+}
+
+// What was saved, made safe against `names`. Nothing saved ticks everything;
+// a pool is kept in the order of `names`, so two can be compared as strings.
+function clean(saved, names) {
+ const s = saved && typeof saved === "object" ? saved : {};
+ return {
+ pick: s.pick === "random" || names.indexOf(s.pick) >= 0 ? s.pick : "burn",
+ pool: Array.isArray(s.pool) ? names.filter(n => s.pool.indexOf(n) >= 0) : names,
+ };
+}
diff --git a/desktop/modules/appearance/test_transitions.js b/desktop/modules/appearance/test_transitions.js
new file mode 100644
index 0000000..c703703
--- /dev/null
+++ b/desktop/modules/appearance/test_transitions.js
@@ -0,0 +1,51 @@
+// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Run: node desktop/modules/appearance/test_transitions.js
+// TransitionPick.js is a QML library, so its .pragma line is stripped before
+// node evaluates it.
+
+const fs = require("fs");
+const assert = require("assert");
+
+const src = fs.readFileSync(__dirname + "/TransitionPick.js", "utf8").replace(/^\.pragma library$/m, "");
+const T = new Function(src + "\nreturn { choose, clean };")();
+
+// A named pick is returned as it is, whatever the pool holds.
+assert.strictEqual(T.choose("melt", [], "melt"), "melt");
+
+// Random stays in the pool and never plays the same one twice running.
+const pool = ["ink", "melt", "blinds"];
+let last = "";
+const seen = {};
+for (let i = 0; i < 500; i++) {
+ const n = T.choose("random", pool, last);
+ assert.ok(pool.indexOf(n) >= 0, `${n} is not in the pool`);
+ assert.notStrictEqual(n, last, `${n} twice running`);
+ seen[n] = true;
+ last = n;
+}
+assert.strictEqual(Object.keys(seen).length, 3);
+
+// A pool of one has to repeat, and an empty one falls back.
+assert.strictEqual(T.choose("random", ["ink"], "ink"), "ink");
+assert.strictEqual(T.choose("random", [], "ink"), "burn");
+
+// Saved values: missing, wrong and unknown all land on something playable,
+// and the pool comes back in the list's order.
+const names = ["burn", "ink", "melt"];
+assert.deepStrictEqual(T.clean(null, names), { pick: "burn", pool: names });
+assert.deepStrictEqual(T.clean({ pick: "gone", pool: "x" }, names), { pick: "burn", pool: names });
+assert.deepStrictEqual(T.clean({ pick: "random", pool: ["melt", "gone", "burn"] }, names),
+ { pick: "random", pool: ["burn", "melt"] });
+assert.deepStrictEqual(T.clean({ pick: "ink", pool: [] }, names), { pick: "ink", pool: [] });
+
+console.log("ok");