179 lines
6.4 KiB
Python
179 lines
6.4 KiB
Python
"""Behavioral coverage for the CS Major autochess 0.6.6 flow."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
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 Release064AutochessTests(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-{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 start_two_human_two_ai(self):
|
|
self.command("/自走棋开始")
|
|
self.command("/自走棋报名", sender="Bob")
|
|
self.command("/自走棋加AI战队")
|
|
return 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")
|
|
return self.command("/选1", sender="Bob")
|
|
|
|
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 test_static_pool_parser_and_coach_pool(self):
|
|
self.assertEqual(len(AUTOCHESS.PLAYER_POOL), 60)
|
|
self.assertEqual(len({card["id"] for card in AUTOCHESS.PLAYER_POOL}), 60)
|
|
self.assertEqual(len(AUTOCHESS.COACH_POOL), 10)
|
|
self.assertEqual(
|
|
len({coach["id"] for coach in AUTOCHESS.COACH_POOL}),
|
|
10,
|
|
)
|
|
self.assertEqual(
|
|
AUTOCHESS.parse_autochess_action("/自走棋开始"),
|
|
("create", ""),
|
|
)
|
|
self.assertEqual(
|
|
AUTOCHESS.parse_autochess_action("/选6"),
|
|
("buy", "6"),
|
|
)
|
|
self.assertEqual(
|
|
AUTOCHESS.parse_autochess_action("/战术残局"),
|
|
("tactic", "残局"),
|
|
)
|
|
|
|
def test_launch_starts_multimessage_coach_draft_not_full_rosters(self):
|
|
response = self.start_two_human_two_ai()
|
|
state = self.state()
|
|
|
|
self.assertGreaterEqual(len(response), 5)
|
|
self.assertIn("第一轮选秀", "\n".join(response))
|
|
self.assertIn("1. zonic", "\n".join(response))
|
|
self.assertEqual(state["phase"], "draft_coach_1")
|
|
self.assertEqual(state["ai_test_variant"], "two_plus_two")
|
|
self.assertEqual(
|
|
state["seed_order"][2:],
|
|
[AUTOCHESS.AI_PERSON_KEY, AUTOCHESS.AI_SECOND_PERSON_KEY],
|
|
)
|
|
for player in state["players"].values():
|
|
self.assertEqual(player["board"], [])
|
|
self.assertEqual(player["coach_id"], "")
|
|
|
|
def test_three_round_draft_training_and_group_intro(self):
|
|
self.start_two_human_two_ai()
|
|
final_draft = self.finish_draft()
|
|
state = self.state()
|
|
|
|
self.assertIn("三轮选秀结束", "\n".join(final_draft))
|
|
self.assertEqual(state["phase"], "lineup_prep")
|
|
for player in state["players"].values():
|
|
self.assertEqual(len(player["board"]), 5)
|
|
self.assertEqual(len(player["bench"]), 3)
|
|
self.assertTrue(player["coach_id"])
|
|
|
|
self.command("/结束回合")
|
|
training = self.command("/结束回合", sender="Bob")
|
|
self.assertIn("Team Falcons", "\n".join(training))
|
|
self.assertIn("Natus Vincere", "\n".join(training))
|
|
self.assertEqual(self.state()["phase"], "training_manage")
|
|
|
|
self.command("/结束回合")
|
|
group = self.command("/结束回合", sender="Bob")
|
|
self.assertIn("正赛小组赛", "\n".join(group))
|
|
state = self.state()
|
|
self.assertEqual(state["phase"], "group_ready")
|
|
self.assertEqual(len(state["group_matches"]), 6)
|
|
|
|
def test_full_tournament_completes_and_only_active_playoff_players_ready(self):
|
|
self.start_two_human_two_ai()
|
|
self.finish_draft()
|
|
seen_playoff_prompt = False
|
|
|
|
for _ in range(80):
|
|
state = self.state()
|
|
if state["status"] == "completed":
|
|
break
|
|
ready_keys = list(state.get("ready_keys") or [])
|
|
self.assertTrue(ready_keys, state["phase"])
|
|
if state["phase"] in {"semifinal_ready", "final_ready"}:
|
|
pair = set(state["current_match"]["pair"])
|
|
self.assertEqual(set(ready_keys), pair & set(AUTOCHESS._human_keys(state)))
|
|
seen_playoff_prompt = True
|
|
self.ready_all()
|
|
else:
|
|
self.fail("tournament did not complete")
|
|
|
|
state = self.state()
|
|
self.assertTrue(seen_playoff_prompt)
|
|
self.assertEqual(state["status"], "completed")
|
|
self.assertEqual(state["phase"], "completed")
|
|
self.assertTrue(state["champion_key"])
|
|
|
|
def test_multimessage_response_replays_identically(self):
|
|
self.command("/自走棋开始")
|
|
self.command("/自走棋报名", sender="Bob")
|
|
self.command("/自走棋加AI战队")
|
|
first = self.command("/自走棋开赛", event_id="same-launch")
|
|
replay = self.command("/自走棋开赛", event_id="same-launch")
|
|
self.assertEqual(first, replay)
|
|
self.assertGreater(len(first), 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|