feat(tally): core model, evaluation and status formatting (#1337)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
NotSoToothless
2026-06-19 00:15:43 -07:00
committed by GitHub
parent 76844c1c6f
commit 74c59eb139
3 changed files with 249 additions and 0 deletions
+108
View File
@@ -0,0 +1,108 @@
"""
Pure-logic tests for BOT/tally.py (no Discord, no I/O).
Usage:
source ../SHARED/.venv/bin/activate && python BOT/tests/test_tally_logic.py
"""
import sys
import os
from pathlib import Path
# Set a temporary storage path before importing BOT (which imports utils)
os.environ.setdefault("STORAGE_VOL_PATH", "/tmp/tally_test_storage")
Path(os.environ["STORAGE_VOL_PATH"]).mkdir(parents=True, exist_ok=True)
sys.path.insert(0, str(Path(__file__).resolve().parents[2])) # repo root for `BOT` package
from BOT.tally import Tally, team_index_for, evaluate, format_status, strip_tag
def _teams():
return [
{"squadron_short": "-DSPL-", "players": [{"nick": "Alpha"}, {"nick": "Bravo"}]},
{"squadron_short": "ENEMY", "players": [{"nick": "Echo"}]},
]
def test_strip_tag():
assert strip_tag("-DSPL-") == "DSPL"
assert strip_tag("=ABC=") == "ABC"
assert strip_tag(None) == ""
def test_team_index_player_mode():
t = Tally(guild_id=1, channel_id=2, mode="player", target="bravo", display_target="Bravo")
assert team_index_for(t, _teams()) == 0
t2 = Tally(guild_id=1, channel_id=2, mode="player", target="nobody", display_target="nobody")
assert team_index_for(t2, _teams()) is None
def test_team_index_squadron_mode():
t = Tally(guild_id=1, channel_id=2, mode="squadron", target="ENEMY", display_target="ENEMY")
assert team_index_for(t, _teams()) == 1
def test_evaluate_win_increments_and_records_opponent():
t = Tally(guild_id=1, channel_id=2, mode="squadron", target="DSPL", display_target="DSPL")
kind = evaluate(t, _teams(), winner_short="DSPL", is_draw=False, session_id="s1")
assert kind == "win"
assert (t.wins, t.losses) == (1, 0)
assert t.last_result_kind == "win"
assert t.last_opponent == "ENEMY"
def test_evaluate_loss():
t = Tally(guild_id=1, channel_id=2, mode="squadron", target="DSPL", display_target="DSPL")
kind = evaluate(t, _teams(), winner_short="ENEMY", is_draw=False, session_id="s1")
assert kind == "loss"
assert (t.wins, t.losses) == (0, 1)
assert t.last_result_kind == "loss"
def test_evaluate_draw_counts_as_loss_but_kind_draw():
t = Tally(guild_id=1, channel_id=2, mode="squadron", target="DSPL", display_target="DSPL")
kind = evaluate(t, _teams(), winner_short=None, is_draw=True, session_id="s1")
assert kind == "draw"
assert (t.wins, t.losses) == (0, 1)
assert t.last_result_kind == "draw"
def test_evaluate_dedup_same_session():
t = Tally(guild_id=1, channel_id=2, mode="squadron", target="DSPL", display_target="DSPL")
assert evaluate(t, _teams(), "DSPL", False, "s1") == "win"
assert evaluate(t, _teams(), "DSPL", False, "s1") is None
assert (t.wins, t.losses) == (1, 0)
def test_evaluate_not_involved_returns_none():
t = Tally(guild_id=1, channel_id=2, mode="squadron", target="OTHER", display_target="OTHER")
assert evaluate(t, _teams(), "DSPL", False, "s1") is None
def test_format_status_fresh():
t = Tally(guild_id=1, channel_id=2, mode="squadron", target="DSPL", display_target="DSPL")
assert format_status(t, "en") == "0W-0L"
def test_format_status_after_win():
t = Tally(guild_id=1, channel_id=2, mode="squadron", target="DSPL", display_target="DSPL")
evaluate(t, _teams(), "DSPL", False, "s1")
assert format_status(t, "en") == "1W-0L: Win against ENEMY"
def test_format_status_after_draw():
t = Tally(guild_id=1, channel_id=2, mode="squadron", target="DSPL", display_target="DSPL")
evaluate(t, _teams(), None, True, "s1")
assert format_status(t, "en") == "0W-1L: Draw against ENEMY"
def _run():
fns = [v for k, v in sorted(globals().items()) if k.startswith("test_")]
for fn in fns:
fn()
print(f"ok {fn.__name__}")
print(f"\nALL {len(fns)} TESTS PASSED")
if __name__ == "__main__":
_run()