committed by
trae-solo-agent
parent
22f5240fa7
commit
08682045d4
@@ -62,6 +62,8 @@ class DeploymentScriptTests(unittest.TestCase):
|
||||
"jwebot_config",
|
||||
"jwebot_sdk",
|
||||
"jwebot_kernel",
|
||||
"jwebot_kernel/data",
|
||||
"kernel_data_source_dir",
|
||||
"jwebot_official_extensions",
|
||||
"data/cs_autochess",
|
||||
"official_autochess_data_source_dir",
|
||||
|
||||
@@ -1291,9 +1291,9 @@ class LedgerAndApplicationTests(unittest.TestCase):
|
||||
self.assertEqual(version["route"], "local")
|
||||
self.assertIn("JWeBot 版本", version["text"])
|
||||
self.assertIn("kernel", version["text"])
|
||||
self.assertIn("最新版本:beta 2.0.2.1021", version["text"])
|
||||
self.assertIn("更新时间:2026-10-21 18:11:35", version["text"])
|
||||
self.assertIn("更新摘要:上下文追问小版本更新完成", version["text"])
|
||||
self.assertIn("最新版本:beta 2.0.4.1023", version["text"])
|
||||
self.assertIn("更新时间:2026-10-23 16:56:33", version["text"])
|
||||
self.assertIn("更新摘要:许愿池和 21 点小版本更新完成", version["text"])
|
||||
self.assertEqual(debug["route"], "local")
|
||||
self.assertIn("调试埋点", debug["text"])
|
||||
self.assertEqual(balance["route"], "local")
|
||||
@@ -1574,7 +1574,7 @@ class LedgerAndApplicationTests(unittest.TestCase):
|
||||
|
||||
def test_trivia_quiz_broadcast_and_answer_rewards_mora(self):
|
||||
bank = MODULE.trivia_question_bank()
|
||||
self.assertGreater(len(bank), 200)
|
||||
self.assertEqual(len(bank), 500)
|
||||
display_text = "\n".join(
|
||||
"\n".join(
|
||||
[
|
||||
@@ -1640,10 +1640,12 @@ class LedgerAndApplicationTests(unittest.TestCase):
|
||||
delivery = self.application.deliver.call_args.args[0]
|
||||
self.assertIn("冷门知识问答", delivery["result_text"])
|
||||
self.assertIn("限时5分钟", delivery["result_text"])
|
||||
self.assertIn("出现次数:1", delivery["result_text"])
|
||||
self.assertIn("/回答 A", delivery["result_text"])
|
||||
state = ledger.local_game("group-a", MODULE.TRIVIA_GAME_KEY)
|
||||
self.assertIsNotNone(state)
|
||||
assert state is not None
|
||||
self.assertEqual(state["ask_count"], 1)
|
||||
state["expires_at"] = time.time() + 300
|
||||
ledger.save_local_game("group-a", MODULE.TRIVIA_GAME_KEY, state)
|
||||
answer = str(state["answer"])
|
||||
@@ -1664,6 +1666,49 @@ class LedgerAndApplicationTests(unittest.TestCase):
|
||||
account = ledger._load_player_account("group-a", str(person["person_key"]))
|
||||
self.assertEqual(account["balance"], 1000 + reward)
|
||||
|
||||
def test_trivia_quiz_prefers_least_asked_base_id(self):
|
||||
group = "group-trivia-balance"
|
||||
topic = "原神"
|
||||
topic_base_ids = sorted(
|
||||
{
|
||||
str(question["base_id"])
|
||||
for question in MODULE.trivia_question_bank()
|
||||
if question["topic"] == topic
|
||||
}
|
||||
)
|
||||
self.assertGreater(len(topic_base_ids), 3)
|
||||
least_asked = topic_base_ids[2]
|
||||
ask_counts = {base_id: 4 for base_id in topic_base_ids}
|
||||
ask_counts[least_asked] = 1
|
||||
self.application.ledger.save_local_game(
|
||||
group,
|
||||
MODULE.TRIVIA_HISTORY_KEY,
|
||||
{
|
||||
"recent_base_ids": topic_base_ids[: MODULE.TRIVIA_RECENT_BASE_LIMIT],
|
||||
"ask_counts": ask_counts,
|
||||
},
|
||||
)
|
||||
|
||||
selected = self.application.clock.select_trivia_question(
|
||||
group=group,
|
||||
local_now=MODULE.datetime(
|
||||
2026,
|
||||
10,
|
||||
23,
|
||||
13,
|
||||
0,
|
||||
tzinfo=MODULE.BEIJING_TIMEZONE,
|
||||
),
|
||||
topic=topic,
|
||||
)
|
||||
|
||||
self.assertEqual(selected["base_id"], least_asked)
|
||||
self.assertEqual(selected["ask_count"], 2)
|
||||
self.assertIn(
|
||||
"出现次数:2",
|
||||
self.application.clock.render_trivia_message(selected),
|
||||
)
|
||||
|
||||
def test_trivia_quiz_can_be_started_by_local_command(self):
|
||||
self.application.deepseek.complete = mock.Mock(side_effect=AssertionError)
|
||||
|
||||
|
||||
+14
-13
@@ -40,6 +40,7 @@ class Release061Tests(unittest.TestCase):
|
||||
|
||||
def test_aliases_are_corresponding_and_case_insensitive(self):
|
||||
pairs = [("上下文", "Context"), ("摩拉", "wallet"), ("抽奖", "draw"),
|
||||
("许愿池", "draw"), ("许愿", "draw"),
|
||||
("买彩票", "lottery"), ("21点", "blackjack"),
|
||||
("人物列表", "people"), ("人物", "person"), ("游戏帮助", "games")]
|
||||
for chinese, english in pairs:
|
||||
@@ -84,46 +85,46 @@ class Release061Tests(unittest.TestCase):
|
||||
def test_initial_funds_aliases_groups_and_replay(self):
|
||||
self.assertIn("摩拉 1000", self.command("/wallet", event_id="wallet-1"))
|
||||
with mock.patch.object(self.local.players.rng, "randrange", return_value=99):
|
||||
first = self.command("/draw 10", event_id="draw-1")
|
||||
replay = self.command("/draw 10", sender="a1", event_id="draw-1")
|
||||
first = self.command("/draw 1000", event_id="draw-1")
|
||||
replay = self.command("/draw 1000", sender="a1", event_id="draw-1")
|
||||
self.assertEqual(first, replay)
|
||||
self.assertEqual(self.state("a1")["balance"], 990)
|
||||
self.assertIn("许愿池", first)
|
||||
self.assertEqual(self.state("a1")["balance"], 0)
|
||||
self.assertIn("摩拉 1000", self.command("/wallet", sender="Bob"))
|
||||
self.assertIn("摩拉 1000", self.command("/wallet", group="group-b"))
|
||||
self.engine.ledger.connection.close()
|
||||
self.engine = MODULE.EdgeApplication(config(self.root))
|
||||
self.local = self.engine.local
|
||||
self.assertIn("摩拉 990", self.command("/wallet", event_id="restart"))
|
||||
self.assertIn("摩拉 0", self.command("/wallet", event_id="restart"))
|
||||
|
||||
def test_concurrent_replay_debits_once_and_rolls_back_failure(self):
|
||||
replies = []
|
||||
with mock.patch.object(self.local.players.rng, "randrange", return_value=99):
|
||||
threads = [threading.Thread(target=lambda: replies.append(
|
||||
self.command("/draw 100", event_id="concurrent"))) for _ in range(8)]
|
||||
self.command("/draw 1000", event_id="concurrent"))) for _ in range(8)]
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
self.assertEqual(len(replies), 8)
|
||||
self.assertEqual(len(set(replies)), 1)
|
||||
self.assertEqual(self.state()["balance"], 900)
|
||||
self.assertEqual(self.state()["balance"], 0)
|
||||
def broken(state):
|
||||
state["balance"] = -1
|
||||
return "bad"
|
||||
with self.assertRaises(MODULE.LocalCommandError):
|
||||
self.engine.ledger.apply_player_action("group-a", "Alice", "broken", "test", broken)
|
||||
self.assertEqual(self.state()["balance"], 900)
|
||||
self.assertEqual(self.state()["balance"], 0)
|
||||
with self.assertRaises(MODULE.LocalCommandError):
|
||||
self.command("/draw 100", sender="Bob", event_id="concurrent")
|
||||
self.command("/draw 1000", sender="Bob", event_id="concurrent")
|
||||
|
||||
def test_invalid_bets_insufficient_funds_and_lottery(self):
|
||||
for question in ("/draw -1", "/draw 0", "/draw 101", "/lottery xyz",
|
||||
"/blackjack start -1", "/blackjack hit 10"):
|
||||
self.assertRegex(self.command(question), "用法|下注")
|
||||
self.assertRegex(self.command(question), "用法|投入|下注")
|
||||
with mock.patch.object(self.local.players.rng, "randrange", return_value=99):
|
||||
for _ in range(10):
|
||||
self.command("/draw 100")
|
||||
self.assertIn("摩拉不足", self.command("/draw 2"))
|
||||
self.command("/draw 1000")
|
||||
self.assertIn("摩拉不足", self.command("/draw 1000"))
|
||||
self.assertEqual(self.state()["balance"], 0)
|
||||
|
||||
def test_blackjack_is_private_persistent_and_settles_exactly_once(self):
|
||||
@@ -136,7 +137,7 @@ class Release061Tests(unittest.TestCase):
|
||||
self.assertIn("暗牌", start)
|
||||
self.assertEqual(self.state()["balance"], 950)
|
||||
self.assertIn("没有进行中", self.command("/blackjack status", sender="Bob"))
|
||||
self.assertIn("已有一局", self.command("/draw"))
|
||||
self.assertIn("已有一局", self.command("/draw 1000"))
|
||||
self.engine.ledger.connection.close()
|
||||
self.engine = MODULE.EdgeApplication(config(self.root))
|
||||
self.local = self.engine.local
|
||||
|
||||
+64
-17
@@ -154,7 +154,20 @@ class Release063GameTests(unittest.TestCase):
|
||||
self.assertEqual(self.state()["balance"], 500)
|
||||
self.assertIn("已报名 1 人", self.command("/彩票状态"))
|
||||
|
||||
def test_blackjack_uses_1_to_500_and_indexed_history(self):
|
||||
def test_blackjack_uses_1_to_2000_and_indexed_history(self):
|
||||
self.command("/摩拉")
|
||||
account = self.state()
|
||||
account["balance"] = 2500
|
||||
person_key = self.engine.ledger.resolve_person(
|
||||
"group-a",
|
||||
"Alice",
|
||||
)["person_key"]
|
||||
self.engine.ledger._save_player_account(
|
||||
"group-a",
|
||||
person_key,
|
||||
account,
|
||||
MODULE.utc_now(),
|
||||
)
|
||||
def tied_deck(cards):
|
||||
first = [9, 6, 8, 7]
|
||||
cards[:] = first + [card for card in cards if card not in first]
|
||||
@@ -164,17 +177,23 @@ class Release063GameTests(unittest.TestCase):
|
||||
"shuffle",
|
||||
side_effect=tied_deck,
|
||||
):
|
||||
started = self.command("/21点开始500")
|
||||
started = self.command("/21点开始2000")
|
||||
self.assertTrue(started.startswith("alice #1:"))
|
||||
self.assertEqual(self.state()["balance"], 500)
|
||||
settled = self.command("/21点停牌")
|
||||
self.assertTrue(settled.startswith("alice #1:"))
|
||||
self.assertIn("平局", settled)
|
||||
self.assertEqual(self.state()["balance"], 1000)
|
||||
self.assertEqual(self.state()["balance"], 2500)
|
||||
history = self.command("/游戏记录")
|
||||
self.assertIn("alice #1:21点 平局", history)
|
||||
self.assertIn("下注 500,返还 500", history)
|
||||
self.assertIn("1~500", self.command("/21点开始501"))
|
||||
self.assertIn("下注 2000,返还 2000", history)
|
||||
rates = self.command("/21点胜率")
|
||||
self.assertIn("Taffy:胜 0 / 负 0 / 平 1,胜率 0.00%", rates)
|
||||
self.assertIn(
|
||||
"alice:胜 0 / 负 0 / 平 1,胜率 0.00%;净赚净亏 0 摩拉",
|
||||
rates,
|
||||
)
|
||||
self.assertIn("1~2000", self.command("/21点开始2001"))
|
||||
|
||||
def test_multiplayer_blackjack_table_guides_turns_and_settles(self):
|
||||
self.assertIn("黑杰克Blackjack 21点牌桌", self.command("/21点 多人 启动"))
|
||||
@@ -225,26 +244,54 @@ class Release063GameTests(unittest.TestCase):
|
||||
"bob #1:21点 你输了",
|
||||
self.command("/游戏记录", sender="Bob"),
|
||||
)
|
||||
rates = self.command("/21点 胜率")
|
||||
self.assertIn("本群已结算 2 手", rates)
|
||||
self.assertIn(
|
||||
"Taffy:胜 1 / 负 1 / 平 0,胜率 50.00%;净亏 100 摩拉",
|
||||
rates,
|
||||
)
|
||||
self.assertIn(
|
||||
"alice:胜 1 / 负 0 / 平 0,胜率 100.00%;净赚 200 摩拉",
|
||||
rates,
|
||||
)
|
||||
self.assertIn(
|
||||
"bob:胜 0 / 负 1 / 平 0,胜率 0.00%;净亏 100 摩拉",
|
||||
rates,
|
||||
)
|
||||
self.assertIn("+200:21点 获胜", self.command("/金币"))
|
||||
self.assertIn(
|
||||
"-100:21点 失败",
|
||||
self.command("/金币", sender="Bob"),
|
||||
)
|
||||
|
||||
def test_prize_draw_has_indexed_history(self):
|
||||
def test_wish_pool_has_indexed_history(self):
|
||||
self.command("/摩拉")
|
||||
account = self.state()
|
||||
account["balance"] = 2000
|
||||
person_key = self.engine.ledger.resolve_person(
|
||||
"group-a",
|
||||
"Alice",
|
||||
)["person_key"]
|
||||
self.engine.ledger._save_player_account(
|
||||
"group-a",
|
||||
person_key,
|
||||
account,
|
||||
MODULE.utc_now(),
|
||||
)
|
||||
self.engine.ledger.connection.commit()
|
||||
with mock.patch.object(
|
||||
self.engine.local.players.rng,
|
||||
"randrange",
|
||||
return_value=99,
|
||||
):
|
||||
first = self.command("/抽奖10")
|
||||
second = self.command("/抽奖10")
|
||||
first = self.command("/许愿1000")
|
||||
second = self.command("/抽奖1000")
|
||||
|
||||
self.assertTrue(first.startswith("alice #1:"))
|
||||
self.assertTrue(second.startswith("alice #2:"))
|
||||
history = self.command("/gamehistory")
|
||||
self.assertIn("alice #2:抽奖 未中奖", history)
|
||||
self.assertIn("alice #1:抽奖 未中奖", history)
|
||||
self.assertIn("alice #2:许愿池 沉底", history)
|
||||
self.assertIn("alice #1:许愿池 沉底", history)
|
||||
|
||||
def test_transfer_requires_initialized_target_and_replays_once(self):
|
||||
self.assertIn("摩拉 1000", self.command("/摩拉"))
|
||||
@@ -345,21 +392,21 @@ class Release063GameTests(unittest.TestCase):
|
||||
"randrange",
|
||||
return_value=99,
|
||||
):
|
||||
self.command("/抽奖10")
|
||||
self.command("/抽奖1000")
|
||||
with mock.patch.object(
|
||||
self.engine.local.players.rng,
|
||||
"randrange",
|
||||
return_value=0,
|
||||
side_effect=[950, 3000],
|
||||
):
|
||||
self.command("/抽奖10", sender="Bob")
|
||||
self.command("/抽奖1000", sender="Bob")
|
||||
|
||||
stats = self.command("/Taffy摩拉")
|
||||
|
||||
self.assertIn("玩家总下注 20,总返还 50", stats)
|
||||
self.assertIn("Taffy累计倒贴 30 摩拉", stats)
|
||||
self.assertIn("玩家总下注 2000,总返还 3000", stats)
|
||||
self.assertIn("Taffy累计倒贴 1000 摩拉", stats)
|
||||
self.assertIn("最大上贡者排行(含负数):", stats)
|
||||
self.assertIn("alice:上贡 10", stats)
|
||||
self.assertIn("bob:从Taffy赢走 40", stats)
|
||||
self.assertIn("alice:上贡 1000", stats)
|
||||
self.assertIn("bob:从Taffy赢走 2000", stats)
|
||||
self.assertIn("Taffy摩拉人数必须为 1~20", self.command("/Taffy摩拉 0"))
|
||||
|
||||
def test_open_round_and_history_survive_restart(self):
|
||||
|
||||
@@ -20,7 +20,7 @@ SPEC.loader.exec_module(MODULE)
|
||||
|
||||
|
||||
class ReleaseUpdateTests(unittest.TestCase):
|
||||
release = "beta 2.0.2.1021"
|
||||
release = "beta 2.0.4.1023"
|
||||
major_release = "beta 2.0.0.1021"
|
||||
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user