diff --git a/README.md b/README.md index 824dde0..84dd486 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ # Python Client for the Software-Challenge Germany 2023 -[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/FalconsSky/Software-Challenge-Python-Client/static%20and%20unit%20tests?label=Test)](https://github.com/FalconsSky/Software-Challenge-Python-Client) [![Read the Docs](https://img.shields.io/readthedocs/software-challenge-python-client?label=Docs)](https://software-challenge-python-client.readthedocs.io/en/latest/) [![PyPI](https://img.shields.io/pypi/v/socha?label=PyPi)](https://pypi.org/project/socha/) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/socha?label=Python)](https://pypi.org/project/socha/) diff --git a/pyproject.toml b/pyproject.toml index 5b732f4..bc163b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "socha" -version = "0.9.9" +version = "1.0.0" authors = [ { name = "FalconsSky", email = "stu222782@mail.uni-kiel.de" }, ] diff --git a/setup.py b/setup.py index 5e5e803..04a9da9 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name='socha', - version='0.9.9', + version='1.0.0', packages=['socha', 'socha.api', 'socha.api.plugin', 'socha.api.protocol', 'socha.api.networking'], url='https://github.com/FalconsSky/Software-Challenge-Python-Client', diff --git a/socha/api/plugin/penguins.py b/socha/api/plugin/penguins.py index 9783fa7..44c59dd 100644 --- a/socha/api/plugin/penguins.py +++ b/socha/api/plugin/penguins.py @@ -223,7 +223,7 @@ def from_index(index: int) -> Optional['CartesianCoordinate']: """ if 0 <= index <= 63: return CartesianCoordinate(x=index % 8, y=int(index / 8)) - return None + raise IndexError("Index out of range.") def __repr__(self) -> str: return f"CartesianCoordinate({self.x}, {self.y})" @@ -449,10 +449,12 @@ def get_team(self) -> Union[Team, None]: def __eq__(self, __o: object) -> bool: return isinstance(__o, Field) and self.field == __o.field - - def __str__(self): - return f"This Field is occupied by {self.field}" + ( - " fish(es)." if isinstance(self.field, int) else ".") + + def __repr__(self): + if isinstance(self.field, int): + return f"Field({self.coordinate}, Fish({self.field}))" + else: + return f"Field({self.coordinate}, {self.field})" class Board: @@ -671,7 +673,8 @@ def get_most_fish(self) -> List[Field]: :return: A list of Fields. """ - fields = self.get_all_fields() + + fields = list(filter(lambda field_x: not field_x.is_occupied(), self.get_all_fields())) fields.sort(key=lambda field_x: field_x.get_fish(), reverse=True) for i, field in enumerate(fields): if field.get_fish() < fields[0].get_fish(): diff --git a/tests/test_penguins.py b/tests/test_penguins.py index 361c85d..500bf7d 100644 --- a/tests/test_penguins.py +++ b/tests/test_penguins.py @@ -1,8 +1,36 @@ import unittest +import random from socha.api.plugin.penguins import * +def create_random_board() -> Board: + game_field = [] + teams = ["ONE", "TWO"] + one_penguins = 0 + two_penguins = 0 + for y in range(8): + row = [] + for x in range(8): + choice = random.choice([0, 1]) + if choice == 0: + field = Field(CartesianCoordinate(x, y).to_hex(), random.randint(0, 4)) + else: + if one_penguins <= 4 and two_penguins <= 4: + if one_penguins == two_penguins: + team = random.choice(teams) + elif one_penguins > two_penguins: + team = "TWO" + else: + team = "ONE" + field = Field(CartesianCoordinate(x, y).to_hex(), team) + else: + field = Field(CartesianCoordinate(x, y).to_hex(), random.randint(0, 4)) + row.append(field) + game_field.append(row) + return Board(game_field) + + class VectorTest(unittest.TestCase): def testVectorInit(self): v = Vector(5, -5) @@ -84,6 +112,70 @@ def testGetEmptyField(self): self.assertEqual(len(e), 49) +class BoardTest(unittest.TestCase): + b = create_random_board() + + def test_get_empty_fields(self): + empty_fields = self.b.get_empty_fields() + + for field in empty_fields: + self.assertTrue(field.is_empty()) + + def test_is_occupied(self): + for x in range(self.b.width() - 1): + for y in range(self.b.height() - 1): + field = self.b._get_field(x, y) + if field.is_occupied(): + self.assertTrue(self.b.is_occupied(field.coordinate)) + else: + self.assertFalse(self.b.is_occupied(field.coordinate)) + + def test_is_valid(self): + for x in range(self.b.width()): + for y in range(self.b.height()): + self.assertTrue(self.b.is_valid(CartesianCoordinate(x, y).to_hex())) + + self.assertFalse(self.b.is_valid(CartesianCoordinate(-1, 0).to_hex())) + self.assertFalse(self.b.is_valid(CartesianCoordinate(0, -1).to_hex())) + self.assertFalse(self.b.is_valid(CartesianCoordinate(8, 0).to_hex())) + self.assertFalse(self.b.is_valid(CartesianCoordinate(0, 8).to_hex())) + + def test_get_field(self): + valid_coordinates = [] + for y in range(self.b.height() - 1): + for x in range(self.b.width() - 1): + valid_coordinates.append(CartesianCoordinate(x, y).to_hex()) + random_coordinates = random.choice(valid_coordinates) + field = self.b.get_field(random_coordinates) + self.assertEqual(field.coordinate, random_coordinates) + self.assertTrue(isinstance(field.field, int) or isinstance(field.field, Team)) + + invalid_coordinates = [CartesianCoordinate(-1, 0).to_hex(), CartesianCoordinate(0, -1).to_hex(), + CartesianCoordinate(self.b.width(), 0).to_hex(), + CartesianCoordinate(0, self.b.height()).to_hex()] + random_coordinates = random.choice(invalid_coordinates) + with self.assertRaises(IndexError): + self.b.get_field(random_coordinates) + + def test_get_field_by_index(self): + random_indices = random.randint(0, 63) + field = self.b.get_field_by_index(random_indices) + self.assertEqual(field.coordinate, CartesianCoordinate(random_indices % self.b.width(), + int(random_indices / self.b.width())).to_hex()) + self.assertTrue(isinstance(field.field, int) or isinstance(field.field, Team)) + + random_indices = random.randint(-100, -1) + with self.assertRaises(IndexError): + self.b.get_field_by_index(random_indices) + + def test_get_most_fish(self): + most_fish_fields = self.b.get_most_fish() + self.assertTrue(isinstance(most_fish_fields, list)) + self.assertTrue(all(isinstance(field, Field) for field in most_fish_fields)) + self.assertTrue(all(isinstance(field.field, int) for field in most_fish_fields)) + self.assertTrue(all(field.field >= 0 for field in most_fish_fields)) + + class GameStateTest(unittest.TestCase): b = Board(game_field=[[Field(coordinate=CartesianCoordinate(j, i).to_hex(), field=1) for i in range(8)] for j in range(8)])