diff --git a/ForkliftAgent.py b/ForkliftAgent.py index 2f31f24..5201ca2 100644 --- a/ForkliftAgent.py +++ b/ForkliftAgent.py @@ -2,6 +2,7 @@ from typing import Tuple, List from AgentBase import AgentBase from data.enum.Direction import Direction +from decision.Action import Action from decision.ActionType import ActionType @@ -9,52 +10,52 @@ class ForkliftAgent(AgentBase): def __init__(self, model): super().__init__(model) - self.movement_queue = [] + self.action_queue: List[Action] = [] self.current_position = Tuple[int, int] self.current_rotation = Direction.right - def queue_movement_actions(self, movement_actions: List[ActionType]): - self.movement_queue.extend(movement_actions) + def queue_movement_actions(self, movement_actions: List[Action]): + self.action_queue.extend(movement_actions) def move(self): - if len(self.movement_queue) > 0: - action = self.movement_queue.pop(0) + if len(self.action_queue) > 0: + action = self.action_queue.pop(0) + action_type = action.action_type - if action == ActionType.ROTATE_UP: - print("rotate {} --> {}".format(self.current_rotation, action)) + if action_type == ActionType.ROTATE_UP: + print("rotate {} --> {}".format(self.current_rotation, action_type)) self.current_rotation = Direction.top - elif action == ActionType.ROTATE_RIGHT: - print("rotate {} --> {}".format(self.current_rotation, action)) + elif action_type == ActionType.ROTATE_RIGHT: + print("rotate {} --> {}".format(self.current_rotation, action_type)) self.current_rotation = Direction.right - elif action == ActionType.ROTATE_DOWN: - print("rotate {} --> {}".format(self.current_rotation, action)) + elif action_type == ActionType.ROTATE_DOWN: + print("rotate {} --> {}".format(self.current_rotation, action_type)) self.current_rotation = Direction.down - elif action == ActionType.ROTATE_LEFT: - print("rotate {} --> {}".format(self.current_rotation, action)) + elif action_type == ActionType.ROTATE_LEFT: + print("rotate {} --> {}".format(self.current_rotation, action_type)) self.current_rotation = Direction.left - elif action == ActionType.MOVE: + elif action_type == ActionType.MOVE: if self.current_rotation == Direction.top: - print("move {} --> {}".format(self.current_position, action)) + print("move {} --> {}".format(self.current_position, action_type)) self.current_position = (self.current_position[0], self.current_position[1] + 1) elif self.current_rotation == Direction.down: - print("move {} --> {}".format(self.current_position, action)) + print("move {} --> {}".format(self.current_position, action_type)) self.current_position = (self.current_position[0], self.current_position[1] - 1) elif self.current_rotation == Direction.right: - print("move {} --> {}".format(self.current_position, action)) + print("move {} --> {}".format(self.current_position, action_type)) self.current_position = (self.current_position[0] + 1, self.current_position[1]) elif self.current_rotation == Direction.left: - print("move {} --> {}".format(self.current_position, action)) + print("move {} --> {}".format(self.current_position, action_type)) self.current_position = (self.current_position[0] - 1, self.current_position[1]) def step(self) -> None: - print("forklift step") self.move() def creation_log(self): diff --git a/GameModel.py b/GameModel.py index 01ae27e..e8db162 100644 --- a/GameModel.py +++ b/GameModel.py @@ -1,3 +1,4 @@ +from enum import Enum from typing import List from mesa import Model @@ -10,89 +11,229 @@ from InitialStateFactory import InitialStateFactory from PatchAgent import PatchAgent from PatchType import PatchType from data.GameConstants import GameConstants +from data.Item import Item +from data.Order import Order +from data.enum.Direction import Direction +from data.enum.ItemType import ItemType +from decision.Action import Action from decision.ActionType import ActionType from pathfinding.PathfinderOnStates import PathFinderOnStates, PathFinderState from util.PathDefinitions import GridLocation, GridWithWeights +class Phase(Enum): + INIT = 1 + ITEM_RECOGNITION = 2 + CLIENT_SORTING = 3 + PLAN_MOVEMENT = 4 + EXECUTION = 5 + + class GameModel(Model): - def __init__(self, width, height, graph: GridWithWeights, graph2: GridWithWeights): + def __init__(self, width, height, graph: GridWithWeights): # self.num_agents = 5 + self.first = True + self.item_recognised = False self.running = True self.grid = MultiGrid(height, width, True) self.schedule = RandomActivation(self) - self.agents = [AgentBase] + self.client_delivery: PatchAgent = None + self.drop_off: PatchAgent = None + + self.agents = [AgentBase] self.forklift_agent = ForkliftAgent(self) self.schedule.add(self.forklift_agent) self.agents.append(self.forklift_agent) - - initial_state_factory = InitialStateFactory() + self.graph = graph self.game_constants = GameConstants( width, height, graph.walls, - graph2.puddles + graph.puddles ) - # Add the agent to a random grid cell - x = 5 - y = 5 - self.grid.place_agent(self.forklift_agent, (x, y)) - self.forklift_agent.current_position = (x, y) + # INITIALIZATION # + print("############## INITIALIZATION ##############") + self.phase = Phase.INIT + self.initialize_grid(graph) + self.orderList: List[Order] = InitialStateFactory.generate_order_list(3) - start, goal = (x, y), (1, 3) + print("############## RECOGNISE ITEMS ##############") + self.phase = Phase.ITEM_RECOGNITION + self.provided_items = InitialStateFactory.generate_item_list(3) + self.recognised_items: List[Item] = [] + + print("Relocate forklift agent to loading area for item recognition") pathFinder = PathFinderOnStates( self.game_constants, - goal, + self.drop_off.location, PathFinderState(self.forklift_agent.current_position, self.forklift_agent.current_rotation, 0, - ActionType.NONE, []) + Action(ActionType.NONE), []) ) - self.place_patch_agents() - self.place_walls_agents(graph.walls) - self.place_puddles(graph2.puddles) - actions = pathFinder.get_action_list() print("PATHFINDING") print(actions) self.forklift_agent.queue_movement_actions(actions) - def place_patch_agents(self): - agent = PatchAgent(self, PatchType.pickUp) + def initialize_grid(self, graph: GridWithWeights): + print("INITIALIZING GRID") + # Add the agent to a random grid cell + x = 5 + y = 5 + self.grid.place_agent(self.forklift_agent, (x, y)) + self.forklift_agent.current_position = (x, y) + + self.place_logistics() + self.place_walls_agents(graph.walls) + self.place_puddles(graph.puddles) + self.place_packing_stations(graph.packingStations) + + def place_logistics(self): + agent = PatchAgent(self, (self.grid.width - 1, int(self.grid.height / 2)), PatchType.pickUp) self.schedule.add(agent) - self.grid.place_agent(agent, (self.grid.width - 1, self.grid.height - 1)) + self.grid.place_agent(agent, agent.location) self.agents.append(agent) + self.client_delivery = agent - agent = PatchAgent(self, PatchType.dropOff) - # self.schedule.add(agent) - self.grid.place_agent(agent, (0, self.grid.height - 1)) + agent = PatchAgent(self, (0, int(self.grid.height / 2)), PatchType.dropOff) + self.grid.place_agent(agent, agent.location) self.agents.append(agent) - - for i in range(3): - a = PatchAgent(self, PatchType.item) - self.agents.append(a) - self.grid.place_agent(a, (i, 0)) + self.drop_off = agent def place_walls_agents(self, walls: List[GridLocation]): for w in walls: - agent = PatchAgent(self, PatchType.wall) + agent = PatchAgent(self, w, PatchType.wall) self.agents.append(agent) self.grid.place_agent(agent, w) def place_puddles(self, puddles: List[GridLocation]): for p in puddles: - agent = PatchAgent(self, PatchType.diffTerrain) + agent = PatchAgent(self, p, PatchType.diffTerrain) self.agents.append(agent) self.grid.place_agent(agent, p) + def place_packing_stations(self, packing_stations: List[tuple[PatchType, GridLocation]]): + for p in packing_stations: + agent = PatchAgent(self, p[1], p[0]) + self.agents.append(agent) + self.grid.place_agent(agent, p[1]) + def step(self): self.schedule.step() - - print("update multiGrid") - self.grid.remove_agent(self.forklift_agent) self.grid.place_agent(self.forklift_agent, self.forklift_agent.current_position) + + if self.phase == Phase.ITEM_RECOGNITION: + if not self.item_recognised and self.forklift_agent.current_position == self.drop_off.location: + + if len(self.provided_items) == 0: + print("FINISHED ITEM RECOGNITION") + self.item_recognised = True + self.phase = Phase.CLIENT_SORTING + else: + print("BEGIN ITEM RECOGNITION, left: {}".format(len(self.provided_items))) + item_to_recognise = self.provided_items.pop() + recognised = self.recognise_item(item_to_recognise) + self.recognised_items.append(recognised) + + if self.phase == Phase.CLIENT_SORTING: + # TODO GENERICS SORTING + sorted(self.orderList, key=lambda x: len(x.items)) + print("FINISHED CLIENT ORDER SORTING") + self.phase = Phase.PLAN_MOVEMENT + + if self.phase == Phase.PLAN_MOVEMENT: + if len(self.orderList) > 0: + self.plan_actions() + self.phase = Phase.EXECUTION + else: + print("NO MORE ORDERS") + + if self.phase == Phase.EXECUTION: + print("Execution") + if (len(self.forklift_agent.action_queue) == 0): + self.phase = Phase.PLAN_MOVEMENT + + def plan_actions(self): + order = self.orderList.pop(0) + print("PLAN MOVEMENT") + for i in order.items: + if self.first: + # get item + pathFinder = PathFinderOnStates( + self.game_constants, + self.drop_off.location, + PathFinderState(self.forklift_agent.current_position, + self.forklift_agent.current_rotation, + 0, + Action(ActionType.NONE), + []) + ) + actions = pathFinder.get_action_list() + self.forklift_agent.queue_movement_actions(actions) + self.first = False + else: + # get item + pathFinder = PathFinderOnStates( + self.game_constants, + self.drop_off.location, + PathFinderState(self.client_delivery.location, + Direction.right, + 0, + Action(ActionType.NONE), + []) + ) + actions = pathFinder.get_action_list() + self.forklift_agent.queue_movement_actions(actions) + self.first = False + + # go through station + packing_station: GridLocation = None + stations = dict(self.graph.packingStations) + if i.real_type == ItemType.PASTA: + packing_station = stations[PatchType.packingA] + elif i.real_type == ItemType.EGG: + packing_station = stations[PatchType.packingB] + elif i.real_type == ItemType.PIZZA: + packing_station = stations[PatchType.packingC] + + pathFinder = PathFinderOnStates( + self.game_constants, + packing_station, + PathFinderState(self.drop_off.location, + Direction.left, + 0, + Action( + desired_item=i, + action_type=ActionType.PICK_ITEM + ), + []) + ) + actions = pathFinder.get_action_list() + self.forklift_agent.queue_movement_actions(actions) + + # go to client delivery area + pathFinder = PathFinderOnStates( + self.game_constants, + self.client_delivery.location, + PathFinderState(packing_station, + Direction.right, + 0, + Action(ActionType.NONE), + []) + ) + actions = pathFinder.get_action_list() + self.forklift_agent.queue_movement_actions(actions) + self.forklift_agent.queue_movement_actions( + [Action(ActionType.DROP_ITEM)] + ) + + def recognise_item(self, item: Item): + # TODO IMAGE PROCESSING + item.guessed_type = item.real_type + return item diff --git a/InitialStateFactory.py b/InitialStateFactory.py index 9eeb73c..a1b61f2 100644 --- a/InitialStateFactory.py +++ b/InitialStateFactory.py @@ -1,38 +1,47 @@ import random from data.Item import Item -from data.enum.ItemType import ItemType from data.Order import Order +from data.enum.ItemType import ItemType +from util.ClientParamsFactory import ClientParamsFactory class InitialStateFactory: @staticmethod - def generate_order_list(self, output_order_list_size: int): - order_list = [Order] - for i in range(0, output_order_list_size): - order_list.append(self.__generate_order()) + def generate_item_list(output_list_size: int): + item_list : [Item] = [] + for i in range(output_list_size): + item_list.append(InitialStateFactory.__generate_item()) + + return item_list + + @staticmethod + def generate_order_list(output_order_list_size: int): + order_list: [Order] = [] + for i in range(output_order_list_size): + order_list.append(InitialStateFactory.__generate_order()) return order_list @staticmethod - def __generate_order(self) -> Order: + def __generate_order() -> Order: order_size = random.randint(1, 4) - items = [Item] + items: [Item] = [] for i in range(order_size): - items.append(self.generate_item()) + items.append(InitialStateFactory.__generate_item()) time_base = random.randint(8, 20) final_time = time_base * order_size - value = sum(i.price for i in items) + client_params = ClientParamsFactory.get_client_params() - return Order(final_time, items, value) + return Order(final_time, items, None, client_params) @staticmethod def generate_input_sequence(self, input_sequence_size): - sequence = [Item] + sequence : [Item] = [] for i in range(0, input_sequence_size): sequence.append(self.__generate_item()) diff --git a/PatchAgent.py b/PatchAgent.py index 174461d..ab3d2b7 100644 --- a/PatchAgent.py +++ b/PatchAgent.py @@ -1,12 +1,12 @@ -from mesa import Agent, Model - from AgentBase import AgentBase from PatchType import PatchType +from util.PathDefinitions import GridLocation class PatchAgent(AgentBase): - def __init__(self, model, patch_type: PatchType): + def __init__(self, model, location: GridLocation, patch_type: PatchType): + self.location = location self.patch_type = patch_type super().__init__(model) diff --git a/PatchType.py b/PatchType.py index 283857a..bae60de 100644 --- a/PatchType.py +++ b/PatchType.py @@ -7,3 +7,6 @@ class PatchType(enum.Enum): item = 3 wall = 4 diffTerrain = 5 + packingA = 6 + packingB = 7 + packingC = 8 diff --git a/data/Item.py b/data/Item.py index ecfb9f0..bf2f67c 100644 --- a/data/Item.py +++ b/data/Item.py @@ -6,11 +6,10 @@ from data.enum.ItemType import ItemType class Item: id_counter = count(start=0) - def __init__(self, type: ItemType): + def __init__(self, item_type: ItemType): self.id = next(self.id_counter) - self.category = type - self.price = self.price_factory(type) + self.real_type = item_type + self.guessed_type = None - @staticmethod - def price_factory(self, type: ItemType): - return 1 + def __repr__(self) -> str: + return "|real: {} -- guessed: {}| \n".format(self.real_type, self.guessed_type) diff --git a/data/Order.py b/data/Order.py index 79f5253..7fd9c88 100644 --- a/data/Order.py +++ b/data/Order.py @@ -1,4 +1,5 @@ from itertools import count +from typing import List from data.ClientParams import ClientParams from data.Item import Item @@ -8,9 +9,12 @@ from data.enum.Priority import Priority class Order: id_counter = count(start=0) - def __init__(self, time: int, items: [Item], value: int, priority: Priority, client_params: ClientParams): + def __init__(self, time: int, items: [Item], priority: Priority, client_params: ClientParams): self.id = next(self.id_counter) self.time = time - self.items = items - self.value = value + self.items: List[Item] = items + self.client_params = client_params self.priority = priority + + def __repr__(self) -> str: + return "items: {} priority: {}".format(self.items, self.priority) diff --git a/data/enum/ItemType.py b/data/enum/ItemType.py index 007b743..edb4e4b 100644 --- a/data/enum/ItemType.py +++ b/data/enum/ItemType.py @@ -4,5 +4,4 @@ from enum import Enum class ItemType(Enum): PIZZA = 1 PASTA = 2 - EGG = 3 - UNKNOWN = 4 \ No newline at end of file + EGG = 3 \ No newline at end of file diff --git a/decision/Action.py b/decision/Action.py new file mode 100644 index 0000000..58bda61 --- /dev/null +++ b/decision/Action.py @@ -0,0 +1,9 @@ +from data.Item import Item +from decision.ActionType import ActionType + + +class Action: + + def __init__(self, action_type: ActionType, desired_item: Item = None): + self.desired_item = desired_item + self.action_type = action_type diff --git a/decision/StateTree.py b/decision/StateTree.py deleted file mode 100644 index 3dcb59f..0000000 --- a/decision/StateTree.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import List - -from InitialStateFactory import InitialStateFactory -from data.GameConstants import GameConstants -from decision.ActionType import ActionType -from decision.State import State -from util.PathDefinitions import GridLocation - - -class StateTree: - - def __init__(self, initial_state_factory: InitialStateFactory, game_constants: GameConstants, - initial_forklift_position: GridLocation): - self.game_constants = game_constants - - parent = State( - action_taken=ActionType.NONE, - forklift_position=initial_forklift_position, - pending_orders=initial_state_factory.generate_order_list(5), - filled_orders=[], - input_items=initial_state_factory.generate_input_sequence(20) - ) - - def expansion(self, from_state: State) -> List[State]: - return [] \ No newline at end of file diff --git a/main.py b/main.py index 853abdb..9881bc2 100644 --- a/main.py +++ b/main.py @@ -1,25 +1,15 @@ -import csv import random -import pandas -import sklearn.tree - from mesa.visualization.ModularVisualization import ModularServer from mesa.visualization.modules import CanvasGrid -from sklearn import metrics, preprocessing -from sklearn.model_selection import train_test_split -from sklearn.tree import DecisionTreeClassifier -from ClientParamsFactory import ClientParamsFactory from ForkliftAgent import ForkliftAgent from GameModel import GameModel from PatchAgent import PatchAgent from PatchType import PatchType -from data.enum.CompanySize import CompanySize from data.enum.Direction import Direction -from data.enum.Priority import Priority -from tree.DecisionTree import DecisionTree from util.PathDefinitions import GridWithWeights +from visualization.DisplayAttributeElement import DisplayAttributeElement colors = [ 'blue', 'cyan', 'orange', 'yellow', 'magenta', 'purple', '#103d3e', '#9fc86c', @@ -63,24 +53,27 @@ def agent_portrayal(agent): if __name__ == '__main__': - base = 512 gridWidth = 10 gridHeight = 10 scale = base / gridWidth - diagram4 = GridWithWeights(gridWidth, gridHeight) - diagram4.walls = [(6, 5), (6, 6), (6, 7), (6, 8), (2, 3), (2, 4), (3, 4), (4, 4), (6, 4)] - - diagram5 = GridWithWeights(gridWidth, gridHeight) - diagram5.puddles = [(2, 2), (2, 5), (2, 6), (5, 4)] + diagram = GridWithWeights(gridWidth, gridHeight) + diagram.walls = [(6, 5), (6, 6), (6, 7), (6, 8), (2, 3), (2, 4), (3, 4), (4, 4), (6, 4)] + diagram.puddles = [(2, 2), (2, 5), (2, 6), (5, 4)] + diagram.packingStations = [(PatchType.packingA, (4, 8)), (PatchType.packingB, (4, 6)), (PatchType.packingC, (4, 2))] grid = CanvasGrid(agent_portrayal, gridWidth, gridHeight, scale * gridWidth, scale * gridHeight) + readyText = DisplayAttributeElement("phase") + provided_itesm = DisplayAttributeElement("provided_items") + recognised_items = DisplayAttributeElement("recognised_items") + ordersText = DisplayAttributeElement("orderList") + server = ModularServer(GameModel, - [grid], + [grid, readyText, provided_itesm, recognised_items], "Automatyczny Wózek Widłowy", - {"width": gridHeight, "height": gridWidth, "graph": diagram4, "graph2": diagram5},) + {"width": gridHeight, "height": gridWidth, "graph": diagram}, ) server.port = 8888 server.launch() diff --git a/pathfinding/PathFinderState.py b/pathfinding/PathFinderState.py index 832ac85..3a0d4c7 100644 --- a/pathfinding/PathFinderState.py +++ b/pathfinding/PathFinderState.py @@ -1,17 +1,23 @@ from typing import List from data.enum.Direction import Direction -from decision.ActionType import ActionType +from decision.Action import Action from util.PathDefinitions import GridLocation class PathFinderState: - def __init__(self, agent_position: GridLocation, agent_direction: Direction, cost: float, - last_action: ActionType, action_taken: List[ActionType]): + def __init__(self, + agent_position: GridLocation, + agent_direction: Direction, + cost: float, + last_action: Action, + action_taken: List[Action], + desired_item=None): super().__init__() self.agent_position = agent_position self.agent_direction = agent_direction self.cost = cost self.last_action = last_action - self.action_taken = action_taken \ No newline at end of file + self.action_taken = action_taken + self.desired_item = desired_item diff --git a/pathfinding/PathfinderOnStates.py b/pathfinding/PathfinderOnStates.py index 953726c..65b306d 100644 --- a/pathfinding/PathfinderOnStates.py +++ b/pathfinding/PathfinderOnStates.py @@ -1,9 +1,9 @@ from typing import List from typing import Tuple - from data.GameConstants import GameConstants from data.enum.Direction import Direction +from decision.Action import Action from decision.ActionType import ActionType from pathfinding.PathFinderState import PathFinderState from pathfinding.PrioritizedItem import PrioritizedItem @@ -53,34 +53,34 @@ class PathFinderOnStates: else: return True - def create_state(self, curr_state: PathFinderState, action: ActionType) -> PathFinderState: + def create_state(self, curr_state: PathFinderState, action: Action) -> PathFinderState: - if action == action.MOVE: + if action == action.action_type.MOVE: if curr_state.agent_position in self.game_constants.diffTerrain: cost = curr_state.cost + 20 # tutaj koszt kaluzy else: cost = curr_state.cost + 1 - #TODO: jezeli bedziemy rozpatrywac rozne stany to nalezy rozbic na kazdy mozliwy obrot + # TODO: jezeli bedziemy rozpatrywac rozne stany to nalezy rozbic na kazdy mozliwy obrot else: cost = curr_state.cost + 10 last_action = action - action_taken: List[ActionType] = [] + action_taken: List[Action] = [] action_taken.extend(curr_state.action_taken) action_taken.append(last_action) agent_position = curr_state.agent_position agent_direction = curr_state.agent_direction - if action == ActionType.ROTATE_UP: + if action.action_type == ActionType.ROTATE_UP: agent_direction = Direction.top - elif action == ActionType.ROTATE_DOWN: + elif action.action_type == ActionType.ROTATE_DOWN: agent_direction = Direction.down - elif action == ActionType.ROTATE_LEFT: + elif action.action_type == ActionType.ROTATE_LEFT: agent_direction = Direction.left - elif action == ActionType.ROTATE_RIGHT: + elif action.action_type == ActionType.ROTATE_RIGHT: agent_direction = Direction.right - elif action == ActionType.MOVE: + elif action.action_type == ActionType.MOVE: agent_position = self.get_position_after_move(curr_state) return PathFinderState(agent_position, agent_direction, cost, last_action, action_taken) @@ -93,31 +93,31 @@ class PathFinderOnStates: # sprawdz w ktorym kierunku obrocony possible_next_states: List[PathFinderState] = [] if self.is_move_possible(curr_state): - possible_next_states.append(self.create_state(curr_state, ActionType.MOVE)) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.MOVE))) if curr_state.agent_direction == Direction.top: - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_RIGHT)) - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_LEFT)) - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_DOWN)) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_RIGHT))) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_LEFT))) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_DOWN))) elif curr_state.agent_direction == Direction.down: - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_RIGHT)) - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_LEFT)) - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_UP)) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_RIGHT))) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_LEFT))) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_UP))) elif curr_state.agent_direction == Direction.left: - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_RIGHT)) - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_UP)) - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_DOWN)) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_RIGHT))) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_UP))) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_DOWN))) elif curr_state.agent_direction == Direction.right: - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_UP)) - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_LEFT)) - possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_DOWN)) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_UP))) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_LEFT))) + possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_DOWN))) return possible_next_states - def get_action_list(self) -> List[ActionType]: + def get_action_list(self) -> List[Action]: already_visited = {} while not self.queue.empty(): diff --git a/tree/DecisionTree.py b/tree/DecisionTree.py index e975abc..bdb6cb7 100644 --- a/tree/DecisionTree.py +++ b/tree/DecisionTree.py @@ -6,7 +6,7 @@ from sklearn import metrics, preprocessing from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier -from ClientParamsFactory import ClientParamsFactory +from util.ClientParamsFactory import ClientParamsFactory class DecisionTree: diff --git a/ClientParamsFactory.py b/util/ClientParamsFactory.py similarity index 65% rename from ClientParamsFactory.py rename to util/ClientParamsFactory.py index 8ca3388..1779854 100644 --- a/ClientParamsFactory.py +++ b/util/ClientParamsFactory.py @@ -3,25 +3,25 @@ import random from data.ClientParams import ClientParams from data.enum.CompanySize import CompanySize + class ClientParamsFactory: - def __init__(self) -> None: - super().__init__() - - def getTrueMore(self, perOfTrue: int) -> bool: - custom = random.randint(0, perOfTrue) + @staticmethod + def getTrueMore(per_of_true: int) -> bool: + custom = random.randint(0, per_of_true) return custom > 0 - def get_client_params(self) -> ClientParams: + @staticmethod + def get_client_params() -> ClientParams: payment_delay = random.randint(0, 14) - payed = self.getTrueMore(5) + payed = ClientParamsFactory.getTrueMore(5) net_worth = random.randint(0, 100) - is_skarbowka = not self.getTrueMore(5) + is_skarbowka = not ClientParamsFactory.getTrueMore(5) membership = random.getrandbits(1) infuelnce_rate = random.randint(0, 100) is_hat = random.getrandbits(1) - company_size = random.randint(1,6) + company_size = random.randint(1, 6) return ClientParams( payment_delay, @@ -32,4 +32,4 @@ class ClientParamsFactory: bool(membership), bool(is_hat), CompanySize(company_size) - ) \ No newline at end of file + ) diff --git a/util/PathDefinitions.py b/util/PathDefinitions.py index 99ae044..90714c3 100644 --- a/util/PathDefinitions.py +++ b/util/PathDefinitions.py @@ -1,5 +1,7 @@ from typing import Iterator, Protocol, List, TypeVar, Tuple, Dict +from PatchType import PatchType + GridLocation = Tuple[int, int] Location = TypeVar('Location') @@ -14,6 +16,7 @@ class SquareGrid: self.height = height self.walls: List[GridLocation] = [] self.puddles: List[GridLocation] = [] + self.packingStations: List[tuple[PatchType, GridLocation]] = [] def in_bounds(self, id: GridLocation) -> bool: (x, y) = id diff --git a/visualization/DisplayAttributeElement.py b/visualization/DisplayAttributeElement.py new file mode 100644 index 0000000..26e73e9 --- /dev/null +++ b/visualization/DisplayAttributeElement.py @@ -0,0 +1,18 @@ +from mesa.visualization.modules import TextElement + + +class DisplayAttributeElement(TextElement): + def __init__(self, attr_name): + ''' + Create a new text attribute element. + + Args: + attr_name: The name of the attribute to extract from the model. + + Example return: "happy: 10" + ''' + self.attr_name = attr_name + + def render(self, model): + val = getattr(model, self.attr_name) + return self.attr_name + ": " + str(val) \ No newline at end of file