aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/companion/test_mood.js
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-29 10:12:17 +0100
committerDanilo M. <danix@danix.xyz>2026-10-29 10:12:17 +0100
commit0a7db3b48cce5f064c20f280e345a8bf1feb5ecb (patch)
treeeaf9c4be1a832893acf327019ef71a352d9d6647 /desktop/companion/test_mood.js
parent28beb8a9600b6e74cab454401cc94c664d90bfe5 (diff)
downloadquickshell-0a7db3b48cce5f064c20f280e345a8bf1feb5ecb.tar.gz
quickshell-0a7db3b48cce5f064c20f280e345a8bf1feb5ecb.zip
companion: remove from the tree, archived as tag archive/companion
The chibi 2B companion is retired for now. Its last state is kept in the signed tag archive/companion (the commit before this one), so it can be revisited with `git checkout archive/companion`; hypr-theme carries a tag of the same name for its compositor hooks (typing/delete events and the SUPER+\ bind). Removed with it, since nothing else used them: the Companion, phrases and artists settings pages, the five companion prefs in Prefs.qml and Prefs.ready, the wallpaper heart (Admired.qml's list), the assistant's replied() signal and cardTop, and the keybinds reminder's name for the code:49 bind. The design specs and plans under docs/ stay as history. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/companion/test_mood.js')
-rw-r--r--desktop/companion/test_mood.js191
1 files changed, 0 insertions, 191 deletions
diff --git a/desktop/companion/test_mood.js b/desktop/companion/test_mood.js
deleted file mode 100644
index 3dd3dba..0000000
--- a/desktop/companion/test_mood.js
+++ /dev/null
@@ -1,191 +0,0 @@
-// 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/companion/test_mood.js
-// Mood.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 + "/Mood.js", "utf8")
- .replace(/^\.pragma library$/m, "");
-const M = new Function(src +
- "\nreturn { T, click, clickFrame, pick, outfit, mockAllowed, canSpeak, monologue, admireAllowed, seatFrame };")();
-const lsrc = fs.readFileSync(__dirname + "/ListFile.js", "utf8")
- .replace(/^\.pragma library$/m, "");
-const L = new Function(lsrc + "\nreturn { parse, toggle, outputs };")();
-
-const NOW = 10000000;
-// A snapshot with nothing going on, overridden per case.
-const calm = over => Object.assign({
- leaving: false, now: NOW, destructAt: 0, dodging: false, shoved: false, shovedAt: 0, recording: false, busy: false,
- repliedAt: 0, clicks: { count: 0, at: 0 }, mockAt: 0, typingAt: 0, wakeAt: 0, admireAt: 0, singAt: 0,
- djAt: 0, music: false, groove: "",
- monologue: false, idle: 0,
-}, over);
-const state = over => M.pick(calm(over)).state;
-const frame = over => M.pick(calm(over)).frame;
-
-// Nothing going on: the rest pose.
-assert.deepStrictEqual(M.pick(calm({})), { state: "base", frame: "base" });
-
-// The priority table, top to bottom: with every trigger from a row down
-// active at once, that row wins. Merged so a higher row's values win.
-const ladder = [
- ["bye", { leaving: true }],
- ["destruct", { destructAt: NOW - 10 }],
- ["scorched", { destructAt: NOW - M.T.destruct - 10 }],
- ["dodge", { dodging: true }],
- ["shoved", { shoved: true }],
- ["listen", { recording: true }],
- ["think", { busy: true }],
- ["wave", { repliedAt: NOW - 10 }],
- ["sing", { singAt: NOW - 10 }],
- ["dj", { djAt: NOW - 10 }],
- ["clicks", { clicks: { count: 2, at: NOW - 10 } }],
- ["admire", { admireAt: NOW - 10 }],
- ["mock", { mockAt: NOW - 10 }],
- ["watch", { typingAt: NOW - 10 }],
- ["stretch", { wakeAt: NOW - 10 }],
- ["muse", { monologue: true }],
- ["lying", { idle: 3 }],
-];
-for (let i = 0; i < ladder.length; i++) {
- const all = Object.assign({}, ...ladder.slice(i).map(l => l[1]).reverse());
- assert.strictEqual(state(all), ladder[i][0], "everything from " + ladder[i][0] + " down");
-}
-
-// A hide: she waves goodbye, above everything else, whatever she was doing.
-assert.deepStrictEqual(
- M.pick(calm({ leaving: true, idle: 3, clicks: { count: 3, at: NOW - 10 } })),
- { state: "bye", frame: "wave" });
-
-// Shoved: knocked off balance for a moment, then mad beside the balloon
-// for as long as it stays.
-assert.deepStrictEqual(M.pick(calm({ shoved: true, shovedAt: NOW - 10 })), { state: "shoved", frame: "shoved" });
-assert.deepStrictEqual(M.pick(calm({ shoved: true, shovedAt: NOW - M.T.shoveHold })), { state: "shoved", frame: "mad" });
-assert.strictEqual(frame({ shoved: true, shovedAt: 0 }), "shoved");
-
-// Idle levels and their frames.
-assert.deepStrictEqual(M.pick(calm({ idle: 1 })), { state: "bored", frame: "sleepy" });
-assert.deepStrictEqual(M.pick(calm({ idle: 2 })), { state: "yawn", frame: "yawn" });
-assert.deepStrictEqual(M.pick(calm({ idle: 3 })), { state: "lying", frame: "lying" });
-
-// Music while bored: she grooves with the picked frame instead, whistling
-// when nothing was picked; yawning and lying down are unchanged.
-assert.deepStrictEqual(M.pick(calm({ idle: 1, music: true, groove: "headbang" })), { state: "groove", frame: "headbang" });
-assert.deepStrictEqual(M.pick(calm({ idle: 1, music: true })), { state: "groove", frame: "whistle" });
-assert.deepStrictEqual(M.pick(calm({ idle: 1, groove: "headbang" })), { state: "bored", frame: "sleepy" });
-assert.strictEqual(state({ idle: 2, music: true }), "yawn");
-assert.strictEqual(state({ idle: 3, music: true }), "lying");
-// Music while awake is the rest pose; the DJ is only the burst.
-assert.strictEqual(state({ music: true }), "base");
-assert.deepStrictEqual(M.pick(calm({ djAt: NOW - 10 })), { state: "dj", frame: "dj" });
-
-// Holds end on time.
-assert.strictEqual(state({ repliedAt: NOW - M.T.waveHold }), "base");
-assert.strictEqual(state({ singAt: NOW - M.T.singHold }), "base");
-assert.strictEqual(state({ djAt: NOW - M.T.djHold }), "base");
-assert.strictEqual(state({ typingAt: NOW - M.T.typingHold }), "base");
-assert.strictEqual(state({ wakeAt: NOW - M.T.wakeHold }), "base");
-assert.strictEqual(state({ clicks: { count: 3, at: NOW - M.T.clickHold } }), "base");
-assert.strictEqual(state({ destructAt: NOW - M.T.destruct - M.T.scorched }), "base");
-// The mock points first, then smirks.
-assert.strictEqual(frame({ mockAt: NOW - 10 }), "point");
-assert.strictEqual(frame({ mockAt: NOW - M.T.mockHold / 2 - 10 }), "smirk");
-assert.strictEqual(state({ mockAt: NOW - M.T.mockHold }), "base");
-
-// A click burst: within burstGap it grows, past it it starts over.
-let c = { count: 0, at: 0 };
-c = M.click(c, 1000);
-assert.deepStrictEqual(c, { count: 1, at: 1000 });
-c = M.click(c, 1000 + M.T.burstGap);
-assert.strictEqual(c.count, 2);
-c = M.click(c, c.at + M.T.burstGap + 1);
-assert.strictEqual(c.count, 1);
-c = { count: 0, at: 0 };
-for (let i = 0; i < 7; i++) c = M.click(c, 5000 + i * 300);
-assert.strictEqual(c.count, 7);
-// 1 smiles, 2-6 blush harder.
-assert.deepStrictEqual([1, 2, 3, 4, 5, 6].map(M.clickFrame),
- ["smile", "blush1", "blush1", "blush2", "blush2", "blush3"]);
-
-// Outfit: the dress until the flash is over, then the leotard for
-// scorched + skirtless, then the dress again.
-const SK = 60000;
-assert.strictEqual(M.outfit(0, NOW, SK), "dress");
-assert.strictEqual(M.outfit(NOW - 10, NOW, SK), "dress");
-assert.strictEqual(M.outfit(NOW - M.T.destruct, NOW, SK), "leotard");
-const bare = M.T.destruct + M.T.scorched + SK;
-assert.strictEqual(M.outfit(NOW - bare + 10, NOW, SK), "leotard");
-assert.strictEqual(M.outfit(NOW - bare, NOW, SK), "dress");
-// A skirtless time of 0 keeps the leotard until she is shown again, which
-// resets destructAt.
-assert.strictEqual(M.outfit(NOW - 10, NOW, 0), "dress");
-assert.strictEqual(M.outfit(NOW - 3600000, NOW, 0), "leotard");
-assert.strictEqual(M.outfit(0, NOW, 0), "dress");
-
-// Cooldowns.
-assert.strictEqual(M.mockAllowed(0, NOW), true);
-assert.strictEqual(M.mockAllowed(NOW - M.T.mockCooldown + 1, NOW), false);
-assert.strictEqual(M.mockAllowed(NOW - M.T.mockCooldown, NOW), true);
-assert.strictEqual(M.canSpeak(0, NOW), true);
-assert.strictEqual(M.canSpeak(NOW - M.T.lineCooldown + 1, NOW), false);
-assert.strictEqual(M.canSpeak(NOW - M.T.lineCooldown, NOW), true);
-
-// The monologue: 1 in 4 on boredom, 1 in 3 on being shown, once an hour.
-assert.strictEqual(M.monologue("bored", 0, NOW, 0.24), true);
-assert.strictEqual(M.monologue("bored", 0, NOW, 0.25), false);
-assert.strictEqual(M.monologue("shown", 0, NOW, 0.33), true);
-assert.strictEqual(M.monologue("shown", 0, NOW, 0.34), false);
-assert.strictEqual(M.monologue("other", 0, NOW, 0), false);
-assert.strictEqual(M.monologue("bored", NOW - M.T.monologueCooldown + 1, NOW, 0), false);
-assert.strictEqual(M.monologue("bored", NOW - M.T.monologueCooldown, NOW, 0), true);
-
-// Admiring a wallpaper: turned to it, then blushing, then done.
-assert.deepStrictEqual(M.pick(calm({ admireAt: NOW - 10 })), { state: "admire", frame: "watch" });
-assert.strictEqual(frame({ admireAt: NOW - M.T.admireLook }), "blush3");
-assert.strictEqual(state({ admireAt: NOW - M.T.admireLook - M.T.admireBlush }), "base");
-assert.strictEqual(M.admireAllowed(0, NOW), true);
-assert.strictEqual(M.admireAllowed(NOW - M.T.admireCooldown + 1, NOW), false);
-assert.strictEqual(M.admireAllowed(NOW - M.T.admireCooldown, NOW), true);
-
-// The wallpaper list: paths, blank lines and # comments skipped.
-assert.deepStrictEqual(L.parse(""), []);
-assert.deepStrictEqual(L.parse("# mine\n/a.png\n\n /b.png \n#/c.png\n"), ["/a.png", "/b.png"]);
-// Toggling adds a missing path and removes a listed one, leaving
-// comments and every other line as they were.
-assert.strictEqual(L.toggle("", "/a.png"), "/a.png\n");
-assert.strictEqual(L.toggle("# mine\n/b.png", "/a.png"), "# mine\n/b.png\n/a.png\n");
-assert.strictEqual(L.toggle("# mine\n/a.png\n/b.png\n", "/a.png"), "# mine\n/b.png\n");
-assert.strictEqual(L.toggle("/a.png\n", "/a.png"), "");
-// A commented-out path is not listed, so toggling it adds a live line.
-assert.strictEqual(L.toggle("#/a.png\n", "/a.png"), "#/a.png\n/a.png\n");
-// wallp.conf's outputs, by connector.
-assert.deepStrictEqual(L.outputs("# x\nOUTPUT_H=DP-1\nOUTPUT_V=DP-3\nDEFAULT_H=~/h.png\n"),
- { "DP-1": "H", "DP-3": "V" });
-assert.deepStrictEqual(L.outputs(""), {});
-
-// Seated on the assistant's card: each standing frame to its sitting one,
-// the goodbye's sway to the one wave, and anything else to the plain sit.
-assert.strictEqual(M.seatFrame("watch"), "sit-read");
-assert.strictEqual(M.seatFrame("point"), "sit-point");
-assert.strictEqual(M.seatFrame("smirk"), "sit-smirk");
-assert.strictEqual(M.seatFrame("think"), "sit-think");
-assert.strictEqual(M.seatFrame("listen"), "sit-listen");
-assert.strictEqual(M.seatFrame("wave"), "sit-wave");
-assert.strictEqual(M.seatFrame("wave-l"), "sit-wave");
-assert.strictEqual(M.seatFrame("wave-r"), "sit-wave");
-assert.strictEqual(M.seatFrame("dj-scratch"), "sit");
-assert.strictEqual(M.seatFrame("base"), "sit");
-
-console.log("ok");