-
Notifications
You must be signed in to change notification settings - Fork 268
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add data classes and YAML serialization of test matches
- Loading branch information
1 parent
ca05063
commit 5195f31
Showing
6 changed files
with
141 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
from __future__ import annotations | ||
from dataclasses import dataclass | ||
from typing import List, Optional, Tuple | ||
|
||
import axelrod | ||
from axelrod.action import Action | ||
|
||
|
||
@dataclass | ||
class PlayerConfig: | ||
name: str | ||
init_kwargs: dict = None | ||
|
||
def __call__(self): | ||
# Look up player by name | ||
player_class = getattr(axelrod, self.name) | ||
if self.init_kwargs: | ||
return player_class(**self.init_kwargs) | ||
return player_class() | ||
|
||
|
||
@dataclass | ||
class MatchParameters: | ||
turns: Optional[int] = None | ||
noise: Optional[float] = None | ||
prob_end: Optional[float] = None | ||
seed: Optional[int] = None | ||
game: Optional[axelrod.Game] = None | ||
|
||
|
||
@dataclass | ||
class ExpectedMatchOutcome: | ||
player_actions: Tuple[Action, ...] | ||
coplayer_actions: Tuple[Action, ...] | ||
player_attributes: Optional[dict] = None | ||
|
||
|
||
@dataclass | ||
class MatchConfig: | ||
player: PlayerConfig | ||
coplayer: PlayerConfig | ||
match_parameters: MatchParameters | ||
expected_outcome: Optional[ExpectedMatchOutcome] = None | ||
|
||
def __call__(self): | ||
"""Generate the match.""" | ||
player = self.player() | ||
coplayer = self.coplayer() | ||
noise = self.match_parameters.noise | ||
prob_end = self.match_parameters.prob_end | ||
turns = len(self.expected_outcome.player_actions) | ||
match = axelrod.Match( | ||
(player, coplayer), | ||
turns=turns, | ||
noise=noise, | ||
prob_end=prob_end | ||
) | ||
return match | ||
|
||
def test_match(self): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import unittest | ||
import axelrod as axl | ||
|
||
|
||
class TestPlayerConfig(unittest.TestCase): | ||
|
||
def test_call(self): | ||
pc = axl.PlayerConfig("Cooperator") | ||
player = pc() | ||
print(player) | ||
self.assertTrue(issubclass(type(player), axl.Player)) | ||
self.assertTrue(isinstance(player, axl.Cooperator)) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
from dataclasses import asdict | ||
from typing import Tuple | ||
|
||
from dacite import from_dict, Config | ||
import yaml | ||
|
||
import axelrod | ||
from axelrod.action import Action, actions_to_str, str_to_actions | ||
from axelrod.data_classes import ExpectedMatchOutcome, PlayerConfig, MatchConfig, MatchParameters | ||
|
||
filename = "test_matches.yaml" | ||
|
||
|
||
def build_player_spec(name, init_kwargs=None): | ||
return PlayerConfig(name=name, init_kwargs=dict(init_kwargs)) | ||
|
||
|
||
def build_expected_spec(player_actions, coplayer_actions, attr=None): | ||
return ExpectedMatchOutcome( | ||
player_actions=player_actions, | ||
coplayer_actions=coplayer_actions, | ||
player_attributes=attr) | ||
|
||
|
||
def build_match_parameters_spec(noise=None, seed=None): | ||
return MatchParameters(noise=noise, seed=seed) | ||
|
||
|
||
def build_match_spec(player_name, coplayer_name, player_actions, coplayer_actions, noise=None, seed=None, | ||
player_init_kwargs=None, coplayer_init_kwargs=None, attr=None): | ||
return MatchConfig( | ||
player=build_player_spec(player_name, init_kwargs=player_init_kwargs.copy()), | ||
coplayer=build_player_spec(coplayer_name,init_kwargs=coplayer_init_kwargs.copy()), | ||
match_parameters=build_match_parameters_spec(noise=noise, seed=seed), | ||
expected_outcome=build_expected_spec(player_actions, coplayer_actions, attr=attr) | ||
) | ||
|
||
|
||
def log_kwargs(func): | ||
def wrapper(*args, **kwargs): | ||
stream = open('test_matches.yaml', 'a') | ||
spec = build_match_spec(str(args[1].__class__.__name__), str(args[2].__class__.__name__), | ||
actions_to_str(args[-2]), actions_to_str(args[-1]), | ||
noise=kwargs["noise"], seed=kwargs["seed"], | ||
player_init_kwargs=args[1].init_kwargs, | ||
coplayer_init_kwargs=args[2].init_kwargs) | ||
stream.write("---\n") | ||
yaml.dump(asdict(spec), stream) | ||
return func(*args, **kwargs) | ||
return wrapper | ||
|
||
|
||
def load_matches(): | ||
stream = open(filename, 'r') | ||
matches = yaml.load_all(stream, Loader=yaml.Loader) | ||
return [from_dict(data_class=MatchConfig, data=match, config=Config( | ||
type_hooks={Tuple[Action, ...]: str_to_actions})) for match in matches] | ||
|
||
|