// SPDX-License-Identifier: Apache-2.0
; specs/widgets/hive-chain.t27 -- Chain depth: human, A, B, C, then silence
; Source of truth for public/widgets/hive-chain/ (gHashTag/trinity): scripts/widget-pages-from-spec.mjs
; compiles this file, checks its constants, evaluates the tests below and writes the page; the page
; hands every constant to tool.js as window.T27_WIDGET. tool.js holds no English and NO RULE of its
; own: every column, verdict and number it shows comes from public/widgets/hive-chain/logic.js -- the fn
; bodies of gHashTag/t27 specs/automation/agent-hive-group.t27 compiled to wasm, beside its copy logic.t27.
; Lesson 23 of the course queen-and-hive. ASCII only (L3), English only (LANG-EN).
; A K_ constant is an input, a preset, a range or a constant of the logic spec (widget-logic.mjs holds
; a K_ whose name the logic spec also has equal to it); never the result of a spec fn.

; WHAT IT DOES:  the reader drags the milliseconds between one bot message and the next. The
; person's rung is may_answer(from a person); each agent rung is may_answer(from a bot, depth, ms)
; at its depth, and chain_open(depth) beside it.

; WHAT IT DOES NOT CLAIM:  it is a ladder of turns, not a live chat.
; phi^2 + 1/phi^2 = 3 | TRINITY

module widget_hive_chain;

pub const KIND : str = "widget-tool";
pub const ID : str = "hive-chain";
pub const TITLE : str = "Chain depth: human, A, B, C, then silence";
pub const DESCRIPTION : str = "One person asks; agents answer each other. Drag the pause between bot messages: may_answer lets the chain run three bot messages deep and then stops it.";
pub const IMAGE_ALT : str = "Chain card: a person asks and agents answer 6 s apart. A ladder of six rungs: the person, agent A, agent B and agent C are lit green; agent D and agent E are grey, silent at depth 3. Tiles read depth limit 3 and cooldown 5000 ms.";
pub const HOOK : str = "Telegram has no loop protection between bots. Two numbers stop two agents answering each other forever: a depth of 3 and a cooldown of 5 s.";
pub const CATEGORY : str = "game";
pub const DATA_SOURCES : [2]str = ["gHashTag/t27 specs/automation/agent-hive-group.t27 (t27 master c42f8fb40): every value on the page is chain_open and may_answer, its fn bodies compiled to wasm (logic.js)", "Course 11 of t27.ai, queen-and-hive (gHashTag/trinity#1698): lesson 23 opens this widget"];
pub const READS_LOCAL_FILES : bool = false;
pub const SENDS_NOTHING : bool = true;

pub const K_CARD_WIDTH : u16 = 1200;
pub const K_CARD_HEIGHT : u16 = 630;

; --- Numbers: ranges, presets, and constants the logic spec holds ----------------------------
pub const K_GAP_MAX : u16 = 10000;
pub const K_GAP_STEP : u8 = 100;
pub const K_RUNGS : u8 = 6;
pub const K_MAX_BOT_DEPTH : u32 = 3;
pub const K_BOT_REPLY_COOLDOWN_MS : u32 = 5000;
pub const K_PRESET_GAP : [3]u16 = [6000, 3200, 5000];
pub const K_START_PRESET : u8 = 0;

; --- Words on screen ------------------------------------------------------------------------
pub const SAY_PRESETS_LABEL : str = "Start from";
pub const SAY_PRESET_NAMES : [3]str = ["6 s apart", "3.2 s apart", "Exactly 5 s"];
pub const SAY_ASK : str = "Two agents can answer each other. What stops them from doing it forever?";
pub const SAY_GAP : str = "ms between one bot message and the next";
pub const SAY_RUNG_NAMES : [6]str = ["a person asks", "agent A", "agent B", "agent C", "agent D", "agent E"];
pub const SAY_DEPTH : str = "depth {0}";
pub const SAY_OPEN : str = "chain open";
pub const SAY_CLOSED : str = "chain closed";
pub const SAY_ANSWERS : str = "answers";
pub const SAY_SILENT : str = "silent";
pub const SAY_LIMIT : str = "depth limit";
pub const SAY_COOL : str = "cooldown, ms";
pub const SAY_LAST : str = "last to speak";
pub const SAY_NOTE : str = "Depth counts the bot messages already between this one and the person. A person is always answered, whatever the depth; a bot only inside the chain and after the cooldown.";
pub const SAY_SOURCE : str = "Logic: t27 spec automation/agent-hive-group.t27, compiled";

test the_card_is_the_share_size {
    assert K_CARD_WIDTH == 1200;
    assert K_CARD_HEIGHT == 630;
    assert K_CARD_WIDTH * 21 == K_CARD_HEIGHT * 40;
}

test three_deep_five_seconds {
    assert K_MAX_BOT_DEPTH == 3;
    assert K_BOT_REPLY_COOLDOWN_MS == 5000;
    assert K_RUNGS > K_MAX_BOT_DEPTH + 1;
}

test the_start_is_past_the_cooldown {
    assert K_PRESET_GAP[0] > K_BOT_REPLY_COOLDOWN_MS;
    assert K_PRESET_GAP[2] == K_BOT_REPLY_COOLDOWN_MS;
    assert K_PRESET_GAP[0] <= K_GAP_MAX;
}
