Skip to content

Commit

Permalink
Merge pull request #154 from martius-lab/fkloss/various
Browse files Browse the repository at this point in the history
Several changes
  • Loading branch information
luator authored Jan 28, 2025
2 parents 1c96401 + d72ac8b commit 9b3c47c
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 23 deletions.
27 changes: 15 additions & 12 deletions comprl-hockey-game/config.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
[CompetitionServer]
port = 65335
timeout = 10
log_level = "DEBUG"
game_path = "hockey_game.py"
game_class = "HockeyGame"
database_path = "hockey.db"
data_dir = "/tmp"
match_quality_threshold = 0.8
percentage_min_players_waiting = 0.1
percental_time_bonus = 0.1
registration_key = "secret"
monitor_log_path = "/dev/shm/comprl_monitor"
port = 65335
server_update_interval = 5
timeout = 10
log_level = "INFO"
game_path = "hockey_game.py"
game_class = "HockeyGame"
database_path = "hockey.db"
data_dir = "/tmp"
match_quality_threshold = 0.8
percentage_min_players_waiting = 0.1
percental_time_bonus = 0.1
max_parallel_games = 100
monitor_log_path = "/dev/shm/comprl_monitor"

registration_key = "secret"
2 changes: 2 additions & 0 deletions comprl/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
config file location instead of to the working directory.
- Matchmaking now samples from all candidates with quality above the threshold instead
of using the first in the list.
- Do not update player ratings for games with disconnect.
- Add option to limit number of games run in parallel.

## Removed
- The `Agent.event` decorator has been removed. Instead of using it, create
Expand Down
2 changes: 1 addition & 1 deletion comprl/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "comprl"
version = "0.2.2-dev"
version = "0.2.3-dev"
description = "Competition Server for Reinforcement Agents -- Teamprojekt WS 23/24"
authors = [
{name = "Author Name", email = "optional@example.com"},
Expand Down
11 changes: 7 additions & 4 deletions comprl/src/comprl/server/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def on_remote_error(self, player: IPlayer, error: Exception):

def on_update(self):
"""gets called every update cycle"""
self.matchmaking._update()
self.matchmaking.update()
self._write_monitoring_data()

def _write_monitoring_data(self):
Expand All @@ -115,15 +115,18 @@ def plog(*args):

plog(datetime.datetime.now().isoformat(sep=" "))

plog("\nConnected players:")
n_connected = len(self.player_manager.connected_players)
plog(f"\nConnected players ({n_connected}):")
for player in self.player_manager.connected_players.values():
plog(f"\t{player.username} [{player.id}]")

plog("\nGames:")
n_games = len(self.game_manager.games)
plog(f"\nGames ({n_games}):")
for game in self.game_manager.games.values():
plog(f"\t{game.id} {tuple(str(pid) for pid in game.players)}")

plog("\nPlayers in queue:")
n_queue = len(self.matchmaking._queue)
plog(f"\nPlayers in queue ({n_queue}):")
for entry in self.matchmaking._queue:
plog(
f"\t{entry.user.username} [{entry.player_id}]"
Expand Down
2 changes: 2 additions & 0 deletions comprl/src/comprl/server/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class Config:
percentage_min_players_waiting: float = 0.1
#: (Minutes waiting * percentage) added as a time bonus for waiting players
percental_time_bonus: float = 0.1
#: Maximum number of games that can be played in parallel
max_parallel_games: int = 100

#: File to which monitoring information is written. Ideally use a in-memory file
#: (e.g. in /dev/shm).
Expand Down
24 changes: 18 additions & 6 deletions comprl/src/comprl/server/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from comprl.shared.types import GameID, PlayerID
from comprl.server.data import GameData, UserData
from comprl.server.data.sql_backend import User
from comprl.server.data.interfaces import UserRole
from comprl.server.data.interfaces import UserRole, GameEndState
from comprl.server.config import get_config


Expand Down Expand Up @@ -341,6 +341,7 @@ def __init__(
self._match_quality_threshold = config.match_quality_threshold
self._percentage_min_players_waiting = config.percentage_min_players_waiting
self._percental_time_bonus = config.percental_time_bonus
self._max_parallel_games = config.max_parallel_games

# cache matchmaking scores
self._match_quality_scores: dict[frozenset[str], float] = {}
Expand Down Expand Up @@ -412,7 +413,8 @@ def remove(self, player_id: PlayerID) -> None:
"""
self._queue = [entry for entry in self._queue if (entry.player_id != player_id)]

def _update(self) -> None:
def update(self) -> None:
"""Try to match players in the queue and start games."""
self._match_quality_scores = {}
self._search_for_matches()

Expand Down Expand Up @@ -462,6 +464,16 @@ def _search_for_matches(self) -> None:

i = 0
while i < len(self._queue) - 1:
# stop early if the limit for parallel games is reached
num_games = len(self.game_manager.games)
if num_games >= self._max_parallel_games:
self._log.debug(
"Limit for parallel games is reached (running: %d, limit: %d).",
num_games,
self._max_parallel_games,
)
return

player1 = self._queue[i]
candidates = self._queue[i + 1 :]

Expand Down Expand Up @@ -557,15 +569,15 @@ def _rate_match_quality(self, player1: QueueEntry, player2: QueueEntry) -> float
return match_quality

def _end_game(self, game: IGame) -> None:
"""
Readds players to queue after game has ended.
"""Update user ratings and re-add players to the queue.
Args:
game (IGame): The game to be ended.
game: The game that is ending.
"""
# update elo values
result = game.get_result()
if result is not None:
# if a player disconnected during the game, simply don't update the ratings
if result is not None and result.end_state is not GameEndState.DISCONNECTED:
mu_p1, sigma_p1 = self.player_manager.get_matchmaking_parameters(
result.user1_id
)
Expand Down

0 comments on commit 9b3c47c

Please sign in to comment.