Skip to content

Commit

Permalink
Changed formatter to black
Browse files Browse the repository at this point in the history
  • Loading branch information
DiddiZ committed Feb 4, 2024
1 parent 5a495ee commit 9c7f376
Show file tree
Hide file tree
Showing 71 changed files with 531 additions and 376 deletions.
15 changes: 15 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-added-large-files
- id: check-merge-conflict
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
- id: end-of-file-fixer
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 23.12.1
hooks:
- id: black
16 changes: 11 additions & 5 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
{
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
"python.linting.enabled": true,
"editor.formatOnSave": true,
"python.formatting.provider": "yapf",
"python.testing.unittestArgs": ["-v", "-s", "./tests", "-p", "*_test.py"],
"python.testing.unittestEnabled": true
"python.testing.unittestEnabled": true,
"git.rebaseWhenSync": true,
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
}
}
3 changes: 2 additions & 1 deletion datasets/sequences.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ def create_sequences(log_dir, date, radius=5):

# Infer actions
actions = [
spe_ed.actions.index(a) if a in spe_ed.actions else None for a in (
spe_ed.actions.index(a) if a in spe_ed.actions else None
for a in (
spe_ed.infer_action(game.player_states[t][player_id - 1], game.player_states[t + 1][player_id - 1])
for t in range(len(windows))
)
Expand Down
6 changes: 3 additions & 3 deletions environments/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import pandas as pd


class Spe_edLogger():
class Spe_edLogger:
def __init__(self, log_dir="logs/", callbacks=[]):
self.log_dir = Path(log_dir)
self.log_dir.mkdir(parents=True, exist_ok=True)
Expand All @@ -22,7 +22,7 @@ def log(self, states, time_limits):
"""
log_file = self.log_dir / f"{datetime.now():%Y%m%d-%H%M%S}.json"
with open(log_file, "w") as f:
json.dump(states, f, separators=(',', ':'))
json.dump(states, f, separators=(",", ":"))

if len(time_limits) > 0:
time_file = log_file.parent / (log_file.name[:-5] + ".csv")
Expand All @@ -36,7 +36,7 @@ def log(self, states, time_limits):
logging.exception("Logging callback failed")


class CloudUploader():
class CloudUploader:
def __init__(self, url, user, password, remote_dir):
self.url = url
self.user = user
Expand Down
13 changes: 7 additions & 6 deletions environments/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,12 @@ def reset(self):
def game_state(self):
"""Get current game state as dict."""
return {
'width': self.width,
'height': self.height,
'cells': self.cells.tolist(),
'players': dict(p.to_dict() for p in self.players),
'you': self.controlled_player.player_id,
'running': sum(1 for p in self.players if p.active) > 1,
"width": self.width,
"height": self.height,
"cells": self.cells.tolist(),
"players": dict(p.to_dict() for p in self.players),
"you": self.controlled_player.player_id,
"running": sum(1 for p in self.players if p.active) > 1,
}


Expand All @@ -131,6 +131,7 @@ class Spe_edSimulator:
Keeps a history.
"""

def __init__(self, cells, players, rounds, changed=[], parent=None):
self.cells = cells
self.players = players
Expand Down
50 changes: 29 additions & 21 deletions environments/spe_ed.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
@dataclass(frozen=True)
class Direction(np.lib.mixins.NDArrayOperatorsMixin):
"""Common operations for directions."""

index: int
name: str
angle: float
Expand Down Expand Up @@ -42,6 +43,7 @@ def __array__(self):
@dataclass
class Player:
"""Player object."""

player_id: int
x: int
y: int
Expand All @@ -67,28 +69,32 @@ def perform(self, action):
if not self.active:
return

if action == 'turn_left':
if action == "turn_left":
self.direction = self.direction.turn_left()
elif action == 'turn_right':
elif action == "turn_right":
self.direction = self.direction.turn_right()
elif action == 'slow_down':
elif action == "slow_down":
self.speed -= 1
if self.speed < 1: # Check minimum speed
self.active = False
elif action == 'speed_up':
elif action == "speed_up":
self.speed += 1
if self.speed > 10: # Check maximum speed
self.active = False
elif action == 'change_nothing':
elif action == "change_nothing":
pass
else: # Invalid
self.active = False

def __eq__(self, other):
if self.__class__ == other.__class__:
return (
self.player_id == other.player_id and self.x == other.x and self.y == other.y and
self.direction == other.direction and self.speed == other.speed and self.active == other.active
self.player_id == other.player_id
and self.x == other.x
and self.y == other.y
and self.direction == other.direction
and self.speed == other.speed
and self.active == other.active
)
return False

Expand All @@ -100,31 +106,32 @@ def from_json(cls, player_id, data):
"""Create Player object from json data."""
return cls(
player_id=int(player_id),
x=data['x'],
y=data['y'],
direction=directions_by_name[data['direction']],
speed=data['speed'],
active=data['active'],
name=data.get('name'),
x=data["x"],
y=data["y"],
direction=directions_by_name[data["direction"]],
speed=data["speed"],
active=data["active"],
name=data.get("name"),
)

def to_dict(self):
"""Serialize Player object for JSON storage."""
d = {
'x': int(self.x), # Cast to python int
'y': int(self.y),
'direction': self.direction.name,
'speed': self.speed,
'active': self.active,
"x": int(self.x), # Cast to python int
"y": int(self.y),
"direction": self.direction.name,
"speed": self.speed,
"active": self.active,
}
if self.name is not None: # Add name if present
d['name'] = self.name
d["name"] = self.name

return str(self.player_id), d


class Cells(np.ndarray):
"""Cell state wrapper for common methods."""

def __new__(cls, cells):
return cells.view(cls)

Expand Down Expand Up @@ -178,16 +185,17 @@ class SavedGame:
* running: Redundant, last state has running=False
* deadline: irrelevant
"""

def __init__(self, data):
"""Initialize SavedGame.
Args:
data: JSON object
"""
self.data = data
self.cell_states = [np.array(state['cells'], dtype=np.int8) for state in data]
self.cell_states = [np.array(state["cells"], dtype=np.int8) for state in data]
self.player_states = [
[Player.from_json(player_id, player_data) for player_id, player_data in state['players'].items()]
[Player.from_json(player_id, player_data) for player_id, player_data in state["players"].items()]
for state in data
]
self.height, self.width = self.cell_states[0].shape
Expand Down
9 changes: 5 additions & 4 deletions environments/spe_ed_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class Spe_edEnv(gym.Env):
Handles common operations like rendering.
"""

def __init__(self, width, height):
self.width = width
self.height = height
Expand All @@ -21,7 +22,7 @@ def __init__(self, width, height):

self.viewer = None

def render(self, mode='human', screen_width=720, screen_height=720):
def render(self, mode="human", screen_width=720, screen_height=720):
import matplotlib.pyplot as plt

from visualization import Spe_edAx
Expand All @@ -35,15 +36,15 @@ def render(self, mode='human', screen_width=720, screen_height=720):
ax = plt.subplot(1, 1, 1)
self.viewer = Spe_edAx(fig, ax, self.cells, self.players)

if mode == 'human':
if mode == "human":
plt.show(block=False)
else:
self.viewer.update(self.cells, self.players)

if mode == 'human':
if mode == "human":
plt.pause(1e-6) # Let plot handlers resolve and update window
return not self.viewer.closed
elif mode == 'rgb_array':
elif mode == "rgb_array":
# Redraw and fetch rgb-array from plot
fig = plt.gcf()
fig.canvas.draw()
Expand Down
13 changes: 7 additions & 6 deletions environments/websocketenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

class WebsocketEnv(Spe_edEnv):
"""Environment for playing on the online server against other teams."""

def __init__(self, url, key, time_url):
"""Initialize WebsocketEnv.
Expand Down Expand Up @@ -59,7 +60,7 @@ async def await_state(self):
self.done = not state["running"]

if not self.done:
self.deadline = datetime.strptime(state['deadline'], "%Y-%m-%dT%H:%M:%S%z").timestamp() + self.time_offset
self.deadline = datetime.strptime(state["deadline"], "%Y-%m-%dT%H:%M:%S%z").timestamp() + self.time_offset
self.time_limit = self.deadline - time.time()

self.players = [Player.from_json(player_id, player_data) for player_id, player_data in state["players"].items()]
Expand All @@ -69,8 +70,8 @@ async def await_state(self):
self.controlled_player = [player for player in self.players if int(player.player_id) == state["you"]][0]

logging.info(
f"Client received state (active={self.controlled_player.active}, running={not self.done}" +
(f", time={self.time_limit:.02f})" if not self.done else ")")
f"Client received state (active={self.controlled_player.active}, running={not self.done}"
+ (f", time={self.time_limit:.02f})" if not self.done else ")")
)

if self.done: # Close connection if done
Expand All @@ -97,7 +98,7 @@ def game_state(self):
return self.__game_state


def measure_server_time(time_url='https://msoll.de/spe_ed_time', n_probes=10):
def measure_server_time(time_url="https://msoll.de/spe_ed_time", n_probes=10):
"""Measures roundtriptime time time diffference between local time and server time.
Transform server time to local time by adding `time_offset`.
Expand All @@ -115,12 +116,12 @@ def measure_server_time(time_url='https://msoll.de/spe_ed_time', n_probes=10):

# Parse servetime
server_time = (
datetime.strptime(data['time'], "%Y-%m-%dT%H:%M:%S%z") + timedelta(milliseconds=int(data['milliseconds']))
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_offsets.append(now - server_time)
last_server_time = server_time

return np.quantile(time_deltas, .9), np.mean(time_offsets)
return np.quantile(time_deltas, 0.9), np.mean(time_offsets)
11 changes: 7 additions & 4 deletions heuristics/composite_heuristic.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

class CompositeHeuristic(Heuristic):
"""Allows to combine multiple heuristics into a single score evaluating the same board state."""

def __init__(self, heuristics, weights=None):
"""Initialize OpponentDistanceHeuristic.
Expand Down Expand Up @@ -35,7 +36,9 @@ def score(self, cells, player, opponents, rounds, deadline):

def __str__(self):
"""Get readable representation."""
return "CompositeHeuristic(" + \
f"[{','.join([str(heuristic) for heuristic in self.heuristics])}], " + \
f"weights={self.weights}, " + \
")"
return (
"CompositeHeuristic("
+ f"[{','.join([str(heuristic) for heuristic in self.heuristics])}], "
+ f"weights={self.weights}, "
+ ")"
)
13 changes: 8 additions & 5 deletions heuristics/conditions/composite_condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

class CompositeCondition(Condition):
"""Allows to combine multiple conditions into a single score evaluating the same board state."""

def __init__(self, conditions, thresholds=None, logical_op=np.logical_and, compare_op=np.greater_equal):
"""Initialize CompositeCondition.
Expand Down Expand Up @@ -39,8 +40,10 @@ def score(self, cells, player, opponents, rounds, deadline):

def __str__(self):
"""Get readable representation."""
return "CompositeCondition(" + \
f"[{','.join([str(condition) for condition in self.conditions])}], " + \
f"weights={self.thresholds}, " + \
f"logical_op={self.logical_op}, " + \
")"
return (
"CompositeCondition("
+ f"[{','.join([str(condition) for condition in self.conditions])}], "
+ f"weights={self.thresholds}, "
+ f"logical_op={self.logical_op}, "
+ ")"
)
1 change: 1 addition & 0 deletions heuristics/conditions/condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

class Condition(ABC):
"""Abstract class to represent a board state condition."""

@abstractmethod
def score(self, cells, player, opponents, rounds, deadline):
"""Compute a score value for a given game state.
Expand Down
10 changes: 7 additions & 3 deletions heuristics/conditions/named_conditions/endgame_condition.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import numpy as np

from heuristics.conditions import (
CompositeCondition, Condition, OpponentsInPlayerRegionCondition, PlayerInBiggestRegionCondition
CompositeCondition,
Condition,
OpponentsInPlayerRegionCondition,
PlayerInBiggestRegionCondition,
)


class EndgameCondition(Condition):
""" Check if we are in the Endgame."""
"""Check if we are in the Endgame."""

def __init__(self):
"""Initialize EndgameCondition. """
"""Initialize EndgameCondition."""
in_biggest_region = PlayerInBiggestRegionCondition()
opp_num_in_region = OpponentsInPlayerRegionCondition()

Expand Down
Loading

0 comments on commit 9c7f376

Please sign in to comment.