diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-29 10:12:17 +0100 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-29 10:12:17 +0100 |
| commit | 0a7db3b48cce5f064c20f280e345a8bf1feb5ecb (patch) | |
| tree | eaf9c4be1a832893acf327019ef71a352d9d6647 /desktop/companion/test_mood.js | |
| parent | 28beb8a9600b6e74cab454401cc94c664d90bfe5 (diff) | |
| download | quickshell-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.js | 191 |
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"); |
