diff --git a/Code/Communication/APIRequests.py b/Code/Communication/APIRequests.py new file mode 100644 index 0000000..fcd1f55 --- /dev/null +++ b/Code/Communication/APIRequests.py @@ -0,0 +1,19 @@ +from dataclasses import asdict + +import requests as requests + +from Code.Communication.Direction import Direction +from Code.Communication.Member import Member + + +class APIRequests: + + def connectToMember(self, own_process: Member, ip, port, direction: Direction) -> Member: + body = asdict(own_process) + response = requests.post(f"http://{ip}:{port}/connect/{direction.name}", json=body) + jsonValue = response.json() + return Member(jsonValue["ip"], jsonValue["port"]) + + def get_edge(self, target: Member, direction: Direction): + response = requests.get(f"http://{target.ip}:{target.port}/border/{direction.name}") + return response.json() diff --git a/Code/Communication/Direction.py b/Code/Communication/Direction.py index e0ad8d2..7a99118 100644 --- a/Code/Communication/Direction.py +++ b/Code/Communication/Direction.py @@ -4,3 +4,5 @@ from enum import Enum class Direction(Enum): LEFT = 1 RIGHT = 2 + TOP = 3 + BOTTOM = 4 diff --git a/Code/Communication/Member.py b/Code/Communication/Member.py index 969a218..0dc6103 100644 --- a/Code/Communication/Member.py +++ b/Code/Communication/Member.py @@ -5,3 +5,4 @@ from dataclasses import dataclass class Member: ip: str port: int + diff --git a/Code/Communication/Neighbours.py b/Code/Communication/Neighbours.py index 34118f0..cee807c 100644 --- a/Code/Communication/Neighbours.py +++ b/Code/Communication/Neighbours.py @@ -1,5 +1,7 @@ +from Code.Communication.APIRequests import APIRequests from Code.Communication.Direction import Direction from Code.Communication.Member import Member +from Code.Config import GeneralConfig class Neighbours: @@ -7,16 +9,24 @@ class Neighbours: def __init__(self, own_process: Member): self.neighbours = {} self.own_process = own_process + self.api = APIRequests() def connect(self, direction, ip, port): print(f"connecting to {ip}:{port} on {direction} side") - pass + new_neighbour = self.api.connectToMember(self.own_process, ip, port, direction) + self.neighbours[direction] = new_neighbour - def acceptConnection(self, direction: Direction, ip, port) -> tuple[Member, bool]: + def accept_connection(self, direction: Direction, ip, port) -> tuple[Member, bool]: if direction in self.neighbours: - return (self.neighbours[direction],False) + return self.neighbours[direction], False member = Member(ip, port) print(f"Adding neighbour {member.__repr__()}") self.neighbours[direction] = member - return (self.own_process,True) + return self.own_process, True + + def get_edge(self, direction: Direction): + if direction in self.neighbours: + return self.api.get_edge(self.neighbours[direction], direction) + elif direction == Direction.RIGHT or direction.LEFT: + return [False] * GeneralConfig.fields_amount_y diff --git a/Code/Communication/RequestHandler.py b/Code/Communication/RequestHandler.py index b8c8dc3..88365d2 100644 --- a/Code/Communication/RequestHandler.py +++ b/Code/Communication/RequestHandler.py @@ -6,16 +6,26 @@ from http.server import BaseHTTPRequestHandler, HTTPServer from Code.Communication.Direction import Direction from Code.Communication.Neighbours import Neighbours +from Code.UI.Field import Field +from Code.UI.PlayingField import GameState class RequestHandler(BaseHTTPRequestHandler): neighbours: Neighbours = None + game_state: GameState = None def do_GET(self): print("got Get request") if self.path == "/": self.send_response(200, "running") - self.end_headers() + elif self.path.startswith("/border/"): + direction = re.findall("/border/(left|right)", self.path, flags=re.IGNORECASE)[0] + cells = self.game_state.field.get_edge(Direction[direction.upper()]) + + self.send_response(200) + self.send_header('Content-Type', 'application/json') + self.end_headers() + self.wfile.write(json.dumps(cells).encode('utf8')) def handle(self) -> None: super().handle() @@ -29,12 +39,12 @@ class RequestHandler(BaseHTTPRequestHandler): """ def do_POST(self): - print("Got post request") if self.path.startswith("/connect/"): direction = re.findall("/connect/(left|right)", self.path, flags=re.IGNORECASE)[0] data_string = self.rfile.read(int(self.headers['Content-Length'])) + print(f"Got conenction request with value {data_string}") data = json.loads(data_string) - neighbour, accepted = self.neighbours.acceptConnection(Direction[direction.upper()], data["ip"], data["port"]) + neighbour, accepted = self.neighbours.accept_connection(Direction[direction.upper()], data["ip"], data["port"]) print(f"Sending neighbour: {neighbour}") if accepted: diff --git a/Code/Communication/Server.py b/Code/Communication/Server.py index 494eea8..b3e24a0 100644 --- a/Code/Communication/Server.py +++ b/Code/Communication/Server.py @@ -2,11 +2,14 @@ from http.server import HTTPServer from Code.Communication.Neighbours import Neighbours from Code.Communication.RequestHandler import RequestHandler +from Code.UI.PlayingField import GameState class Server: - def __init__(self, neighbours: Neighbours): + def __init__(self, neighbours: Neighbours,game_state:GameState): + self.server = None self.neighbours = neighbours + self.game_state = game_state self.port = neighbours.own_process.port self.ip = neighbours.own_process.ip @@ -16,6 +19,7 @@ class Server: def start(self): RequestHandler.neighbours = self.neighbours + RequestHandler.game_state = self.game_state print(f"HTTP Server Running on {self.ip}: {self.port}") self.server = HTTPServer((self.ip, self.port), RequestHandler) self.server.serve_forever() diff --git a/Code/Config.py b/Code/Config.py index a5f1084..799a2a6 100644 --- a/Code/Config.py +++ b/Code/Config.py @@ -1,22 +1,28 @@ -class GeneralConfig: - width = 1000 - height = 1000 - fps = 150 - window_caption = "GOL" - evolve_speed= 360# ziemlich slow das updated abhänig davon wie viele mill sec das game seit dem eltzten mal gelaufen ist im schnit sind das so 60 +import math + class Colors: - ORANGE = (255, 140, 0) - RED = (255, 0, 0) - GREEN = (5, 112, 0) - BLACK = (0, 0, 0) - WHITE = (255, 255, 255) - GREY = (84, 84, 84) + ORANGE = (255, 140, 0) + RED = (255, 0, 0) + GREEN = (5, 112, 0) + BLACK = (0, 0, 0) + WHITE = (255, 255, 255) + GREY = (84, 84, 84) + class SquareConfig: - width = 10 - height = 10 + width = 10 + height = 10 + + unclicked_color = Colors.BLACK + clicked_color = Colors.WHITE - unclicked_color = Colors.BLACK - clicked_color = Colors.WHITE \ No newline at end of file +class GeneralConfig: + width = 1000 + height = 1000 + fields_amount_x = math.trunc(width / SquareConfig.width) + fields_amount_y = math.trunc(height / SquareConfig.height) + fps = 150 + window_caption = "GOL" + evolve_speed = 360 # ziemlich slow das updated abhänig davon wie viele mill sec das game seit dem eltzten mal gelaufen ist im schnit sind das so 60 diff --git a/Code/Main.py b/Code/Main.py index 89e8f3c..8d61783 100644 --- a/Code/Main.py +++ b/Code/Main.py @@ -5,7 +5,7 @@ from Code.Communication.Direction import Direction from Code.Communication.Member import Member from Code.Communication.Neighbours import Neighbours from Code.Communication.Server import Server -from Code.UI.PlayingField import run_game +from Code.UI.PlayingField import run_game, GameState if __name__ == "__main__": @@ -25,24 +25,25 @@ if __name__ == "__main__": print(args) if len(args) >= 2: - own_port =int(args[1]) + own_port = int(args[1]) else: print("using default port 8080") own_port = 8080 + neighbours = Neighbours(own_process=Member("0.0.0.0", own_port)) + game_state = GameState(neighbours) + server = Server(neighbours, game_state) + + n_direction = Direction.LEFT + if len(args) > 4: + n_direction = args[4] if len(args) >= 4: n_ip = args[2] n_port = int(args[3]) - if len(args) > 4: - n_direction = args[4] - - neighbours = Neighbours(own_process=Member("0.0.0.0", own_port)) - server = Server(neighbours) - - neighbours.connect(Direction[n_direction], n_ip, n_port) + neighbours.connect(Direction[n_direction], n_ip, n_port) serverThread = threading.Thread(target=server.start) serverThread.start() - run_game() + run_game(game_state) print("finished game") server.stop_server() diff --git a/Code/UI/Field.py b/Code/UI/Field.py index 9a2910f..63ef032 100644 --- a/Code/UI/Field.py +++ b/Code/UI/Field.py @@ -1,29 +1,84 @@ -from Code.Config import GeneralConfig, SquareConfig import math +from Code.Communication.Direction import Direction +from Code.Config import GeneralConfig, SquareConfig from Code.UI import Square from Code.UI.Square import Square class Field: - def __init__(self): - self.width = math.trunc(GeneralConfig.width / SquareConfig.width) + 2 - self.height = math.trunc(GeneralConfig.height / SquareConfig.height) + 2 - self.field_shift = -10 - self.squares = self._creat_squares() + def __init__(self): + self.width = GeneralConfig.fields_amount_x+2 + self.height = GeneralConfig.fields_amount_y+2 + self.field_shift = -10 + self.squares = self._creat_squares() - def _creat_squares(self): - squares = [ - [Square(x_pos=j * SquareConfig.width + self.field_shift, y_pos=i * SquareConfig.height + self.field_shift) - for i in range(self.height)] for - j in range(self.width)] - - return squares + def _creat_squares(self): + squares = [ + [Square(x_pos=j * SquareConfig.width + self.field_shift, y_pos=i * SquareConfig.height + self.field_shift) + for i in range(self.height)] for + j in range(self.width)] - def update_squares(self,squares): - self.squares=squares + return squares - def draw_squares(self, window): - for x in self.squares: - for y in x: - y.draw(window) + def update_squares(self, squares): + self.squares = squares + + def draw_squares(self, window): + for x in self.squares: + for y in x: + y.draw(window) + + def get_edge(self, edg_pos: Direction) -> list: + edge = {Direction.LEFT: self.get_left_edge(), Direction.RIGHT: self.get_right_edge(), + Direction.TOP: self.get_top(), Direction.BOTTOM: self.get_bottom_edge()} + return edge[edg_pos] + + def get_top(self): + top_squares = [] + for y in self.squares: + top_squares.append(y[1].active) + + return top_squares + + def get_bottom_edge(self): + right_squares = [] + for y in self.squares: + right_squares.append(y[len(y) - 2].active) + return right_squares + + def get_left_edge(self): + left_squares = [] + for x in self.squares[1]: + left_squares.append(x.active) + return left_squares + + def get_right_edge(self): + right_squares = [] + + for x in self.squares[len(self.squares[0]) - 2]: + right_squares.append(x.active) + + return right_squares + + def fill_ghost_edge(self, value: list): + + edge_fn = {Direction.LEFT: self.fill_left_ghost_edge, Direction.RIGHT: self.fill_right_ghost_edge, + Direction.TOP: self.fill_top_ghost_edge, Direction.BOTTOM: self.fill_bottom_ghost_edge} + + edge_fn(value) + + def fill_right_ghost_edge(self, value: list): + #if len(value)== self.square. + for i in range(len(value)): + self.squares[len(self.squares[0]) - 1][i].active = value[i] + + def fill_left_ghost_edge(self, value: list): + for i in range(len(value)): + self.squares[0][i].active = value[i] + + def fill_top_ghost_edge(self,value): + pass + + def fill_bottom_ghost_edge(self,value): + pass diff --git a/Code/UI/PlayingField.py b/Code/UI/PlayingField.py index 9d78256..f4f244e 100644 --- a/Code/UI/PlayingField.py +++ b/Code/UI/PlayingField.py @@ -1,12 +1,15 @@ import pygame as pygame +from Code.Communication.Direction import Direction +from Code.Communication.Neighbours import Neighbours from Code.Config import GeneralConfig, Colors from Code.GameLogic.Rules import Rules from Code.UI.Field import Field class GameState: - def __init__(self): + def __init__(self, neighbours: Neighbours): + self.neighbours = neighbours self.run = True self.pause_for_input = False self.field = Field() @@ -29,7 +32,6 @@ class GameState: square.update(not square.active) def evolve(self): - rules = Rules() self.field.update_squares(rules.evolve_field(self.field)) @@ -37,13 +39,15 @@ class GameState: window.fill(Colors.BLACK) self.field.draw_squares(window) + def update_borders(self): + self.field.fill_right_ghost_edge(self.neighbours.get_edge(Direction.RIGHT)) + self.field.fill_left_ghost_edge(self.neighbours.get_edge(Direction.LEFT)) -def run_game(): +def run_game(game_state: GameState): pygame.init() pygame.display.set_caption(GeneralConfig.window_caption) window = pygame.display.set_mode((GeneralConfig.width, GeneralConfig.height)) clock = pygame.time.Clock() - game_state = GameState() time_elapsed_since_last_action = 0 while game_state.run: game_state.event_handler() @@ -59,6 +63,7 @@ def run_game(): if time_elapsed_since_last_action > 100: # start = ti.time() + game_state.update_borders() game_state.evolve() # end = ti.time() # print(end - start)