diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 94d6267..1c78cc8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,34 @@ repos: - id: check-executables-have-shebangs - id: check-shebang-scripts-are-executable - id: end-of-file-fixer + - repo: https://github.com/asottile/pyupgrade + rev: v3.15.0 + hooks: + - id: pyupgrade + args: + - "--py38-plus" - repo: https://github.com/psf/black-pre-commit-mirror rev: 23.12.1 hooks: - id: black + - repo: https://github.com/PyCQA/isort + rev: 5.13.2 + hooks: + - id: isort + - repo: https://github.com/PyCQA/flake8 + rev: 6.1.0 + hooks: + - id: flake8 + additional_dependencies: + - flake8-absolute-import + # - flake8-annotations + - flake8-builtins + - flake8-comprehensions + # - flake8-docstrings + - flake8-future-annotations + - flake8-no-implicit-concat + # - flake8-print + # - flake8-requirements + - flake8-simplify + - flake8-use-fstring + - flake8-use-pathlib diff --git a/environments/logging.py b/environments/logging.py index 3e40911..d82253d 100644 --- a/environments/logging.py +++ b/environments/logging.py @@ -1,3 +1,4 @@ +import contextlib import json import logging from datetime import datetime @@ -47,10 +48,8 @@ def upload(self, log_file): oc = owncloud.Client(self.url) oc.login(self.user, self.password) - try: # Create folder + with contextlib.suppress(owncloud.HTTPResponseError): oc.mkdir(self.remote_dir) - except owncloud.HTTPResponseError: - pass oc.put_file(self.remote_dir + log_file.name, str(log_file)) diff --git a/environments/spe_ed_env.py b/environments/spe_ed_env.py index 18c9755..b481c78 100644 --- a/environments/spe_ed_env.py +++ b/environments/spe_ed_env.py @@ -54,9 +54,9 @@ def render(self, mode="human", screen_width=720, screen_height=720): def _validate_action(self, action): """Change illegal actions to do nothing""" controlled_player = self.players[0] - if controlled_player.speed >= 10 and action == "speed_up": - action = "change_nothing" - elif controlled_player.speed <= 1 and action == "slow_down": + if (controlled_player.speed >= 10 and action == "speed_up") or ( + controlled_player.speed <= 1 and action == "slow_down" + ): action = "change_nothing" return action diff --git a/environments/websocketenv.py b/environments/websocketenv.py index 5f88252..c80b690 100644 --- a/environments/websocketenv.py +++ b/environments/websocketenv.py @@ -91,7 +91,7 @@ async def send_action(self, action): """Wait for send action.""" await self.websocket.send(json.dumps({"action": action})) elapsed_time = time.time() + self.time_limit - self.deadline - logging.info(f"Client sent action {action}, took {elapsed_time:.02f}s ({elapsed_time/self.time_limit:.02%})") + logging.info(f"Client sent action {action}, took {elapsed_time:.02f}s ({elapsed_time / self.time_limit:.02%})") def game_state(self): """Get current game state as dict.""" @@ -119,7 +119,7 @@ def measure_server_time(time_url="https://msoll.de/spe_ed_time", n_probes=10): datetime.strptime(data["time"], "%Y-%m-%dT%H:%M:%S%z") + timedelta(milliseconds=int(data["milliseconds"])) ).timestamp() if last_server_time is not None: - time_deltas.append((server_time - last_server_time)) + time_deltas.append(server_time - last_server_time) time_offsets.append(now - server_time) last_server_time = server_time diff --git a/heuristics/opponentdistance_heuristic.py b/heuristics/opponentdistance_heuristic.py index f03a934..5510e8b 100644 --- a/heuristics/opponentdistance_heuristic.py +++ b/heuristics/opponentdistance_heuristic.py @@ -13,7 +13,7 @@ def __init__(self, dist_threshold=16): def score(self, cells, player, opponents, rounds, deadline): """Computes the distance to all players.""" min_opponent_dist = min( - min(np.sum(np.abs((player.position - o.position))) for o in opponents if o.active), self.dist_threshold + min(np.sum(np.abs(player.position - o.position)) for o in opponents if o.active), self.dist_threshold ) return min_opponent_dist / np.sum(cells.shape) diff --git a/policies/circle_policy.py b/policies/circle_policy.py index 221f96a..845397a 100644 --- a/policies/circle_policy.py +++ b/policies/circle_policy.py @@ -7,7 +7,7 @@ class CirclePolicy(Policy): Baseline strategy, smarter policies should be able to outperform this. """ - def act(self, cells, player, opponents, round, deadline): + def act(self, cells, player, opponents, rounds, deadline): """Choose action.""" # directions - relative to player direction forward = player.direction diff --git a/policies/mazewalker_policy.py b/policies/mazewalker_policy.py index a9c2094..2943dfd 100644 --- a/policies/mazewalker_policy.py +++ b/policies/mazewalker_policy.py @@ -11,7 +11,7 @@ def __init__(self): """Initialize MazeWalkerPolicy.""" self.hit_wall = False - def act(self, cells, player, opponents, round, deadline): + def act(self, cells, player, opponents, rounds, deadline): """Choose action.""" def is_free(pos): diff --git a/policies/policy.py b/policies/policy.py index f826700..ea7b14f 100644 --- a/policies/policy.py +++ b/policies/policy.py @@ -7,12 +7,12 @@ class Policy(ABC): """Abstract base class for all policies.""" @abstractmethod - def act(self, cells, you, opponents, rounds, deadline): + def act(self, cells, player, opponents, rounds, deadline): """Produce an action for a given game state. Args: cells: binary ndarray of cell occupancies. - you: Controlled player + player: Controlled player opponents: List of other active players rounds: Number of this round. Starts with 1, thus `rounds % 6 == 0` indicates a jump. deadline: A deadline after which the policy must return immediately. diff --git a/policies/random_policy.py b/policies/random_policy.py index 22afcdc..c20e796 100644 --- a/policies/random_policy.py +++ b/policies/random_policy.py @@ -30,9 +30,7 @@ def act(self, cells, player, opponents, rounds, deadline): action = self.rng.choice(actions, p=self.p) # Check for illegal actions - if player.speed >= 10 and action == "speed_up": - action = "change_nothing" - elif player.speed <= 1 and action == "slow_down": + if (player.speed >= 10 and action == "speed_up") or (player.speed <= 1 and action == "slow_down"): action = "change_nothing" return action diff --git a/policies/spiral_policy.py b/policies/spiral_policy.py index 53ef607..b4dbc1f 100644 --- a/policies/spiral_policy.py +++ b/policies/spiral_policy.py @@ -11,7 +11,7 @@ def __init__(self): """Initialize MazeWalkerPolicy.""" self.clockwise = True - def act(self, cells, player, opponents, round, deadline): + def act(self, cells, player, opponents, rounds, deadline): """Choose action.""" # directions - relative to player direction forward = player.direction diff --git a/setup.cfg b/setup.cfg index 725a3a2..1c1325f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [flake8] -ignore = E265,E741,W504,D100 +ignore = E203,E741,W503,D100,D104,D105,PL123,ANN101,ANN102 max-line-length = 120 docstring-convention = google diff --git a/statistics/stats.py b/statistics/stats.py index a5aef5f..3083725 100644 --- a/statistics/stats.py +++ b/statistics/stats.py @@ -2,7 +2,6 @@ from pathlib import Path from statistics.log_files import get_log_files -import numpy as np import pandas as pd from tqdm import tqdm diff --git a/tests/websocket_test.py b/tests/websocket_test.py index bec28a5..13a6969 100644 --- a/tests/websocket_test.py +++ b/tests/websocket_test.py @@ -1,21 +1,17 @@ import asyncio import json -import threading import unittest import websockets -from environments import WebsocketEnv - class DummyServer: def __init__(self, url, port): self.url = url self.port = port self.step_counter = 0 - file = open("tests/spe_ed-1603124417603.json", "r") - self.states = json.load(file) - file.close() + with open("tests/spe_ed-1603124417603.json") as file: + self.states = json.load(file) # Start new thread from current loop self.__serving = asyncio.get_event_loop().run_in_executor(None, self.run) self.__starting = asyncio.get_event_loop().create_future() @@ -54,7 +50,6 @@ def run(self): # Executed in new thread self.__starting.get_loop().call_soon_threadsafe(self.__starting.set_result, None) loop.run_until_complete(self.serve()) # Run serve in loop until stopped - # threading.Thread(target=loop.run_forever).start() loop.close() print("Server stopped") @@ -76,12 +71,3 @@ def setUp(self): def tearDown(self): print("Stop") self.server.stop() - - # def test_connection(self): - # env = WebsocketEnv(f"ws://{self.url}:{self.port}", self.key) - # obs = env.reset() - # done = False - # while not done: - # action = "change_nothing" - # obs, reward, done, _ = env.step(action) - # print(done) diff --git a/tool_render_opponent_overview.py b/tool_render_opponent_overview.py index 48a67c5..36edd40 100644 --- a/tool_render_opponent_overview.py +++ b/tool_render_opponent_overview.py @@ -20,13 +20,13 @@ def easeOutCubic(t): def names_to_codes(names): code_map = {} - id = 0 + name_id = 0 codes = [] for name in names: if name not in code_map: - code_map[name] = id - id += 1 + code_map[name] = name_id + name_id += 1 codes.append(code_map[name]) diff --git a/tournament/tournament_config.py b/tournament/tournament_config.py index 520b3ed..f36023f 100644 --- a/tournament/tournament_config.py +++ b/tournament/tournament_config.py @@ -1,4 +1,4 @@ -from policies import RandomPolicy, SpiralPolicy, load_named_policy +from policies import SpiralPolicy, load_named_policy # participating policies with short nick names policies = [ diff --git a/visualization/axes.py b/visualization/axes.py index af9e969..e1e95d8 100644 --- a/visualization/axes.py +++ b/visualization/axes.py @@ -1,8 +1,6 @@ -import matplotlib.pyplot as plt import numpy as np import pandas as pd from matplotlib.colors import ListedColormap -from matplotlib.dates import AutoDateLocator player_colors = [ (204.0 / 255, 7.0 / 255, 30.0 / 255, 1.0), # Player 1 - red @@ -66,6 +64,5 @@ def __init__(self, fig, ax, date, won, groupby="D"): (line,) = ax.plot(date, mean, label="win rate", c=player_colors[0]) c = line.get_color() ax.fill_between(date, low, high, facecolor=c, alpha=0.25, interpolate=True, label="confidence interval") - # ax.xaxis.set_major_locator(AutoDateLocator(maxticks=6)) ax.set_xlim(date[0], date[-1] + pd.offsets.Day(1)) ax.set_ylim(0, 1)