"""Behavioral coverage for the CS Major autochess 0.6.7 pacing rewrite.""" from __future__ import annotations import json import re import tempfile import unittest from pathlib import Path from test_jwebot_edge import MODULE, config from jwebot_official_extensions import cs_autochess as AUTOCHESS class Release067AutochessTests(unittest.TestCase): def setUp(self): self.temp = tempfile.TemporaryDirectory() self.engine = MODULE.EdgeApplication(config(Path(self.temp.name))) self.counter = 0 def tearDown(self): self.engine.close() self.temp.cleanup() def command(self, question, *, sender="Alice", event_id=None): self.counter += 1 response = self.engine.accept( { "event_id": event_id or f"autochess-067-{self.counter}", "group_fingerprint": "group-a", "sender": sender, "text": "@JWeBot " + question, "mention_bot": True, "confidence": 1.0, "sender_confidence": 1.0, "body_confidence": 1.0, } ) self.assertEqual(response["status"], "reply") return list(response.get("texts") or [response["text"]]) def state(self): row = self.engine.ledger.connection.execute( """ SELECT state_json FROM autochess_runs WHERE group_fingerprint = 'group-a' ORDER BY season_number DESC LIMIT 1 """ ).fetchone() self.assertIsNotNone(row) return json.loads(row[0]) def ready_all(self): state = self.state() replies = [] for key in list(state.get("ready_keys") or []): replies.extend( self.command( "/结束回合", sender=state["players"][key]["display_name"], ) ) return replies def start_two_human_two_ai(self): self.command("/自走棋开始") self.command("/自走棋报名", sender="Bob") self.command("/自走棋加AI战队") self.command("/自走棋开赛") def finish_draft(self): self.command("/选1") self.command("/选1", sender="Bob") self.command("/选1", sender="Bob") self.command("/选1") self.command("/选1") self.command("/选1", sender="Bob") def test_narrative_inventory_and_training_round_robin(self): self.assertGreaterEqual(AUTOCHESS._narrative_inventory_size(), 120) self.start_two_human_two_ai() self.finish_draft() training = "\n".join(self.ready_all()) state = self.state() self.assertEqual(len(state["training_rounds"]), 3) self.assertEqual(state["training_round_cursor"], 1) self.assertIn("训练赛第 1/3 轮对阵", training) self.assertIn("Team", training) self.assertIn("AI 战队", training) self.assertNotIn("目标", training) self.assertNotIn("发挥", training) def test_round_simulation_produces_natural_score_variety(self): self.start_two_human_two_ai() self.finish_draft() state = self.state() key_a, key_b = state["seed_order"][:2] scores = set() for index in range(12): result = AUTOCHESS._battle( state, key_a, key_b, f"score-variety-{index}", best_of=1, ) score = result["maps"][0]["score"] self.assertRegex(score, r"^\d+-\d+$") self.assertGreaterEqual(result["maps"][0]["rounds_played"], 16) scores.add(score) old_fixed = {"16-6", "16-9", "16-12", "16-14", "19-17"} self.assertGreaterEqual(len(scores), 3) self.assertTrue(scores - old_fixed) def test_group_report_is_paced_and_hides_raw_calculation_terms(self): self.start_two_human_two_ai() self.finish_draft() self.ready_all() self.ready_all() self.ready_all() self.ready_all() report = "\n".join(self.ready_all()) self.assertIn("图1", report) self.assertIn("系列赛结束", report) self.assertNotIn("目标", report) self.assertNotIn("发挥", report) self.assertNotIn("克制修正", report) self.assertIsNotNone(re.search(r"\b\d{2}-\d{1,2}\b", report)) if __name__ == "__main__": unittest.main()