Skip to content

Content Dataclass

Module defining room content types for the rooms of the AMR Hub ABM simulation.

This module defines the Content class, which represents the contents of rooms in the AMR Hub ABM simulation. The Content class includes attributes for content type, location, size, and occupancy status, as well as methods for calculating the polygon representation of the content and checking if it is occupied.

Content dataclass

Representation of content within a room in the AMR Hub ABM simulation.

Parameters:

Name Type Description Default
content_type ContentType

The type of content (e.g., bed, workstation, chair).

required
location Location

The location of the content within the room.

required
occupier_id tuple[int, AgentType] | None

The ID and type of the agent currently occupying the content, if any. Defaults to None.

None
owner_id tuple[int, AgentType] | None

The ID and type of the agent that owns the content, if any. Defaults to None.

None
reserver_id tuple[int, AgentType] | None

The ID and type of the agent travelling to occupy the content, if any. Defaults to None.

None
Source code in src/amr_hub_abm/spatial/furniture.py
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
@dataclass
class Content:
    """
    Representation of content within a room in the AMR Hub ABM simulation.

    Parameters
    ----------
    content_type : ContentType
        The type of content (e.g., bed, workstation, chair).
    location : Location
        The location of the content within the room.
    occupier_id : tuple[int, AgentType] | None, optional
        The ID and type of the agent currently occupying the content, if any.
        Defaults to None.
    owner_id : tuple[int, AgentType] | None, optional
        The ID and type of the agent that owns the content, if any.
        Defaults to None.
    reserver_id : tuple[int, AgentType] | None, optional
        The ID and type of the agent travelling to occupy the content, if any.
        Defaults to None.

    """

    content_id: int = field(init=False)
    content_type: ContentType
    location: Location
    color: str = field(init=False)
    size: tuple[float, float] = field(init=False)
    occupier_id: tuple[int, AgentType] | None = field(default=None)
    owner_id: tuple[int, AgentType] | None = field(default=None)
    reserver_id: tuple[int, AgentType] | None = field(default=None)

    marker_type: str = field(init=False, default="s")
    marker_size: int = field(init=False, default=100)

    def __post_init__(self) -> None:
        """Post-initialization to set content_id based on content_type and position."""
        self.content_id = hash((self.content_type, self.position))

        self.color = CONTENT_COLORS[self.content_type]
        self.size = CONTENT_SIZES[self.content_type]

    @property
    def length(self) -> float:
        """Get the length of the content based on its type."""
        return self.size[0]

    @property
    def width(self) -> float:
        """Get the width of the content based on its type."""
        return self.size[1]

    @property
    def polygon(self) -> shapely.geometry.Polygon:
        """Get the polygon representation of the content."""
        x, y = self.position
        length, width = self.size
        return shapely.geometry.box(
            x - length / 2, y - width / 2, x + length / 2, y + width / 2
        )

    @property
    def occupied(self) -> bool:
        """Check if the content is currently occupied by an agent."""
        return self.occupier_id is not None

    @property
    def reserved(self) -> bool:
        """Check if the content is reserved by an agent."""
        return self.reserver_id is not None

    @property
    def available(self) -> bool:
        """Check if the content is neither occupied nor reserved."""
        return not self.occupied and not self.reserved

    def is_available_to(self, agent_id: tuple[int, AgentType]) -> bool:
        """
        Check whether an agent may reserve this content.

        Parameters
        ----------
        agent_id : tuple[int, AgentType]
            Identity of the agent requesting the content.

        Returns
        -------
        bool
            Whether no other agent occupies or reserves the content.

        """
        valid_occupier = self.occupier_id in {None, agent_id}
        valid_reserver = self.reserver_id in {None, agent_id}
        return valid_occupier and valid_reserver

    def try_reserve(self, agent_id: tuple[int, AgentType]) -> bool:
        """
        Reserve the content if it is available to the given agent.

        Parameters
        ----------
        agent_id : tuple[int, AgentType]
            Identity of the agent requesting the reservation.

        Returns
        -------
        bool
            Whether the reservation was acquired.

        """
        if not self.is_available_to(agent_id):
            return False
        self.reserver_id = agent_id
        return True

    def release_reservation(self, agent_id: tuple[int, AgentType]) -> bool:
        """
        Release a reservation held by the given agent.

        Parameters
        ----------
        agent_id : tuple[int, AgentType]
            Identity of the agent releasing the reservation.

        Returns
        -------
        bool
            Whether a matching reservation was released.

        """
        if self.reserver_id != agent_id:
            return False
        self.reserver_id = None
        return True

    def try_occupy(self, agent_id: tuple[int, AgentType]) -> bool:
        """
        Occupy content without overwriting another agent's claim.

        Parameters
        ----------
        agent_id : tuple[int, AgentType]
            Identity of the agent occupying the content.

        Returns
        -------
        bool
            Whether occupancy was acquired.

        """
        if not self.is_available_to(agent_id):
            return False
        self.occupier_id = agent_id
        self.reserver_id = None
        return True

    def release_occupancy(self, agent_id: tuple[int, AgentType]) -> bool:
        """
        Release occupancy held by the given agent.

        Parameters
        ----------
        agent_id : tuple[int, AgentType]
            Identity of the agent releasing occupancy.

        Returns
        -------
        bool
            Whether matching occupancy was released.

        """
        if self.occupier_id != agent_id:
            return False
        self.occupier_id = None
        return True

    @property
    def owned(self) -> bool:
        """Check if the content is currently owned by an agent."""
        return self.owner_id is not None

    @property
    def position(self) -> tuple[float, float]:
        """Get the (x, y) position of the content."""
        return (self.location.x, self.location.y)

available property

Check if the content is neither occupied nor reserved.

length property

Get the length of the content based on its type.

occupied property

Check if the content is currently occupied by an agent.

owned property

Check if the content is currently owned by an agent.

polygon property

Get the polygon representation of the content.

position property

Get the (x, y) position of the content.

reserved property

Check if the content is reserved by an agent.

width property

Get the width of the content based on its type.

__post_init__()

Post-initialization to set content_id based on content_type and position.

Source code in src/amr_hub_abm/spatial/furniture.py
80
81
82
83
84
85
def __post_init__(self) -> None:
    """Post-initialization to set content_id based on content_type and position."""
    self.content_id = hash((self.content_type, self.position))

    self.color = CONTENT_COLORS[self.content_type]
    self.size = CONTENT_SIZES[self.content_type]

is_available_to(agent_id)

Check whether an agent may reserve this content.

Parameters:

Name Type Description Default
agent_id tuple[int, AgentType]

Identity of the agent requesting the content.

required

Returns:

Type Description
bool

Whether no other agent occupies or reserves the content.

Source code in src/amr_hub_abm/spatial/furniture.py
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
def is_available_to(self, agent_id: tuple[int, AgentType]) -> bool:
    """
    Check whether an agent may reserve this content.

    Parameters
    ----------
    agent_id : tuple[int, AgentType]
        Identity of the agent requesting the content.

    Returns
    -------
    bool
        Whether no other agent occupies or reserves the content.

    """
    valid_occupier = self.occupier_id in {None, agent_id}
    valid_reserver = self.reserver_id in {None, agent_id}
    return valid_occupier and valid_reserver

release_occupancy(agent_id)

Release occupancy held by the given agent.

Parameters:

Name Type Description Default
agent_id tuple[int, AgentType]

Identity of the agent releasing occupancy.

required

Returns:

Type Description
bool

Whether matching occupancy was released.

Source code in src/amr_hub_abm/spatial/furniture.py
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
def release_occupancy(self, agent_id: tuple[int, AgentType]) -> bool:
    """
    Release occupancy held by the given agent.

    Parameters
    ----------
    agent_id : tuple[int, AgentType]
        Identity of the agent releasing occupancy.

    Returns
    -------
    bool
        Whether matching occupancy was released.

    """
    if self.occupier_id != agent_id:
        return False
    self.occupier_id = None
    return True

release_reservation(agent_id)

Release a reservation held by the given agent.

Parameters:

Name Type Description Default
agent_id tuple[int, AgentType]

Identity of the agent releasing the reservation.

required

Returns:

Type Description
bool

Whether a matching reservation was released.

Source code in src/amr_hub_abm/spatial/furniture.py
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
def release_reservation(self, agent_id: tuple[int, AgentType]) -> bool:
    """
    Release a reservation held by the given agent.

    Parameters
    ----------
    agent_id : tuple[int, AgentType]
        Identity of the agent releasing the reservation.

    Returns
    -------
    bool
        Whether a matching reservation was released.

    """
    if self.reserver_id != agent_id:
        return False
    self.reserver_id = None
    return True

try_occupy(agent_id)

Occupy content without overwriting another agent's claim.

Parameters:

Name Type Description Default
agent_id tuple[int, AgentType]

Identity of the agent occupying the content.

required

Returns:

Type Description
bool

Whether occupancy was acquired.

Source code in src/amr_hub_abm/spatial/furniture.py
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
def try_occupy(self, agent_id: tuple[int, AgentType]) -> bool:
    """
    Occupy content without overwriting another agent's claim.

    Parameters
    ----------
    agent_id : tuple[int, AgentType]
        Identity of the agent occupying the content.

    Returns
    -------
    bool
        Whether occupancy was acquired.

    """
    if not self.is_available_to(agent_id):
        return False
    self.occupier_id = agent_id
    self.reserver_id = None
    return True

try_reserve(agent_id)

Reserve the content if it is available to the given agent.

Parameters:

Name Type Description Default
agent_id tuple[int, AgentType]

Identity of the agent requesting the reservation.

required

Returns:

Type Description
bool

Whether the reservation was acquired.

Source code in src/amr_hub_abm/spatial/furniture.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
def try_reserve(self, agent_id: tuple[int, AgentType]) -> bool:
    """
    Reserve the content if it is available to the given agent.

    Parameters
    ----------
    agent_id : tuple[int, AgentType]
        Identity of the agent requesting the reservation.

    Returns
    -------
    bool
        Whether the reservation was acquired.

    """
    if not self.is_available_to(agent_id):
        return False
    self.reserver_id = agent_id
    return True

ContentType

Bases: IntEnum

Enumeration of possible room content types.

Source code in src/amr_hub_abm/spatial/furniture.py
24
25
26
27
28
29
class ContentType(IntEnum):
    """Enumeration of possible room content types."""

    BED = 0
    WORKSTATION = 1
    CHAIR = 2