Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions server/core/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@
from .documents.transcriber_role import TranscriberRoleMixin
from .virtual_bots import VirtualBotManager
from ..network.websocket_server import WebSocketServer, ClientConnection
from ..persistence.database import Database
from ..persistence.database import Database, UserRecord
from ..auth.auth import AuthManager, AuthResult
from .tables.manager import TableManager
from .tables.table import Table
from .users.network_user import NetworkUser
from .users.base import MenuItem, EscapeBehavior, TrustLevel
from .users.preferences import UserPreferences, DiceKeepingStyle, PREF_CATEGORIES, PrefMeta
Expand Down Expand Up @@ -1133,7 +1134,7 @@ async def _finalize_login(
if not self._restore_login_table(user, username):
self._show_main_menu(user)

def _load_user_preferences(self, user_record: "AuthUserRecord") -> UserPreferences:
def _load_user_preferences(self, user_record: "UserRecord") -> UserPreferences:
"""Load stored preferences, falling back to defaults."""
if user_record.preferences_json:
try:
Expand All @@ -1150,7 +1151,7 @@ async def _attach_or_update_user(
self,
client: ClientConnection,
username: str,
user_record: "AuthUserRecord",
user_record: "UserRecord",
preferences: UserPreferences,
) -> tuple[NetworkUser, bool]:
"""Attach a connection to an existing user or create a new one."""
Expand Down
6 changes: 3 additions & 3 deletions server/core/virtual_bots.py
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ def _build_admin_guided_snapshot(self) -> list[dict[str, Any]]:
"""Build snapshot data for guided table rules."""
return [self._build_guided_state_snapshot(state) for state in self._iter_guided_states()]

def _build_guided_state_snapshot(self, state: "GuidedTableRuleState") -> dict[str, Any]:
def _build_guided_state_snapshot(self, state: "GuidedTableState") -> dict[str, Any]:
"""Build a snapshot for a single guided rule state."""
config = state.config
assigned = len(state.assigned_bots)
Expand Down Expand Up @@ -937,7 +937,7 @@ def _build_guided_state_snapshot(self, state: "GuidedTableRuleState") -> dict[st
"unavailable_bots": unavailable,
}

def _count_guided_availability(self, state: "GuidedTableRuleState") -> tuple[int, int]:
def _count_guided_availability(self, state: "GuidedTableState") -> tuple[int, int]:
"""Count guided bots waiting vs unavailable for a rule."""
waiting = 0
unavailable = 0
Expand All @@ -958,7 +958,7 @@ def _count_guided_availability(self, state: "GuidedTableRuleState") -> tuple[int
return waiting, unavailable

def _describe_guided_table(
self, state: "GuidedTableRuleState"
self, state: "GuidedTableState"
) -> tuple[str, str | None, int, int]:
"""Describe the guided table link and player counts."""
if not state.table_id:
Expand Down
1 change: 1 addition & 0 deletions server/games/ageofheroes/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

if TYPE_CHECKING:
from .game import AgeOfHeroesGame, AgeOfHeroesPlayer
from .state import TribeState


def bot_think(game: AgeOfHeroesGame, player: AgeOfHeroesPlayer) -> str | None:
Expand Down
4 changes: 4 additions & 0 deletions server/games/backgammon/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
import logging
from dataclasses import dataclass, field
import random
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from .gnubg import GnubgProcess

log = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion server/games/chaosbear/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ def bot_think(self, player: ChaosBearPlayer) -> str | None:
# Otherwise roll the dice
return "roll_dice"

def _start_next_turn(self, previous_player: "ChaosPlayer | None" = None) -> None:
def _start_next_turn(self, previous_player: "ChaosBearPlayer | None" = None) -> None:
"""Start the next player's turn with menu rebuild and bot jolt.

Args:
Expand Down
1 change: 1 addition & 0 deletions server/games/sorry/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
)
from .state import (
SorryGameState,
SorryPawnState,
SorryPlayerState,
build_initial_game_state,
discard_current_card,
Expand Down
3 changes: 0 additions & 3 deletions server/tests/test_server_admin_virtual_bots.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,6 @@ def clear_bots(self):
self.cleared = True
return 2, 0

def save_state(self):
self.saved = True

def get_status(self):
return {"online": 0, "total": 0, "offline": 0, "in_game": 0}

Expand Down
36 changes: 0 additions & 36 deletions server/tests/test_virtual_bots.py
Original file line number Diff line number Diff line change
Expand Up @@ -1311,42 +1311,6 @@ def execute_action(self, player, action_id):
assert table.game.actions == [("BotA", "start_game")]


def test_process_leaving_game_logout_branch(monkeypatch):
manager = VirtualBotManager(FakeServer())
bot = VirtualBot("Leaf", state=VirtualBotState.LEAVING_GAME)
bot.logout_after_game = True
bot.online_ticks = 10
bot.target_online_ticks = 999
manager._bots["Leaf"] = bot
monkeypatch.setattr("server.core.virtual_bots.random.randint", lambda a, b: a)

manager._process_leaving_game_bot(bot)

assert bot.state == VirtualBotState.ONLINE_IDLE
assert bot.cooldown_ticks == manager._get_config_value(bot, "logout_after_game_min_ticks")


def test_process_leaving_game_offline_path(monkeypatch):
manager = VirtualBotManager(FakeServer())
bot = VirtualBot("Leaf", state=VirtualBotState.LEAVING_GAME)
bot.logout_after_game = False
bot.online_ticks = 100
bot.target_online_ticks = 50
manager._bots["Leaf"] = bot
taken_offline = {}

def fake_take(target_bot):
taken_offline["bot"] = target_bot
target_bot.state = VirtualBotState.OFFLINE

monkeypatch.setattr(manager, "_take_bot_offline", fake_take)

manager._process_leaving_game_bot(bot)

assert taken_offline["bot"] is bot
assert bot.state == VirtualBotState.OFFLINE


def test_on_tick_processes_all_bots(monkeypatch):
manager = _make_single_bot_manager(["BotA", "BotB"])
calls = []
Expand Down
Loading