engine improvements

This commit is contained in:
Aleksander Szamałek 2022-05-22 16:27:36 +02:00
parent 4504d0d412
commit 522b29269d
17 changed files with 320 additions and 160 deletions

View File

@ -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):

View File

@ -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

View File

@ -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())

View File

@ -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)

View File

@ -7,3 +7,6 @@ class PatchType(enum.Enum):
item = 3
wall = 4
diffTerrain = 5
packingA = 6
packingB = 7
packingC = 8

View File

@ -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)

View File

@ -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)

View File

@ -5,4 +5,3 @@ class ItemType(Enum):
PIZZA = 1
PASTA = 2
EGG = 3
UNKNOWN = 4

9
decision/Action.py Normal file
View File

@ -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

View File

@ -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 []

31
main.py
View File

@ -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()

View File

@ -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
self.desired_item = desired_item

View File

@ -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,9 +53,9 @@ 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
@ -66,21 +66,21 @@ class PathFinderOnStates:
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():

View File

@ -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:

View File

@ -3,21 +3,21 @@ 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)

View File

@ -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

View File

@ -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)