diff options
Diffstat (limited to 'desktop/companion/test_mood.js')
| -rw-r--r-- | desktop/companion/test_mood.js | 74 |
1 files changed, 65 insertions, 9 deletions
diff --git a/desktop/companion/test_mood.js b/desktop/companion/test_mood.js index 90ebdd6..3439f7c 100644 --- a/desktop/companion/test_mood.js +++ b/desktop/companion/test_mood.js @@ -19,13 +19,17 @@ 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 };")(); + "\nreturn { T, click, clickFrame, pick, outfit, mockAllowed, canSpeak, monologue, admireAllowed };")(); +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({ - 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, + 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; @@ -37,6 +41,7 @@ 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 }], @@ -44,7 +49,10 @@ const ladder = [ ["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 }], @@ -56,6 +64,11 @@ for (let i = 0; i < ladder.length; i++) { 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" }); @@ -67,8 +80,21 @@ assert.deepStrictEqual(M.pick(calm({ idle: 1 })), { state: "bored", frame: "slee 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"); @@ -95,12 +121,18 @@ assert.deepStrictEqual([1, 2, 3, 4, 5, 6].map(M.clickFrame), // Outfit: the dress until the flash is over, then the leotard for // scorched + skirtless, then the dress again. -assert.strictEqual(M.outfit(0, NOW), "dress"); -assert.strictEqual(M.outfit(NOW - 10, NOW), "dress"); -assert.strictEqual(M.outfit(NOW - M.T.destruct, NOW), "leotard"); -const bare = M.T.destruct + M.T.scorched + M.T.skirtless; -assert.strictEqual(M.outfit(NOW - bare + 10, NOW), "leotard"); -assert.strictEqual(M.outfit(NOW - bare, NOW), "dress"); +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); @@ -119,4 +151,28 @@ 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(""), {}); + console.log("ok"); |
