From c800e252f93a8fb35bea2f511e4ccdbb1ffcd702 Mon Sep 17 00:00:00 2001 From: shima004 Date: Sat, 26 Oct 2024 12:10:28 +0900 Subject: [PATCH 1/8] feat: communication module --- adf_core_python/core/agent/agent.py | 38 ++- .../agent/communication/message_manager.py | 271 +++++++++++++++++- .../standard/standard_communication_module.py | 14 + .../core/agent/info/scenario_info.py | 31 ++ .../communication/channel_subscriber.py | 32 +++ .../communication/communication_message.py | 4 + .../communication/communication_module.py | 15 + .../communication/message_coordinator.py | 23 ++ 8 files changed, 425 insertions(+), 3 deletions(-) create mode 100644 adf_core_python/core/agent/communication/standard/standard_communication_module.py create mode 100644 adf_core_python/core/component/communication/channel_subscriber.py create mode 100644 adf_core_python/core/component/communication/communication_module.py create mode 100644 adf_core_python/core/component/communication/message_coordinator.py diff --git a/adf_core_python/core/agent/agent.py b/adf_core_python/core/agent/agent.py index 297f42a4..50056da9 100644 --- a/adf_core_python/core/agent/agent.py +++ b/adf_core_python/core/agent/agent.py @@ -1,14 +1,30 @@ import sys +from abc import abstractmethod from typing import Any, NoReturn from rcrs_core.agents.agent import Agent as RCRSAgent +from rcrs_core.connection.URN import Entity as EntityURN from rcrs_core.worldmodel.worldmodel import WorldModel +from adf_core_python.core.agent.communication.message_manager import MessageManager +from adf_core_python.core.agent.config.module_config import ModuleConfig +from adf_core_python.core.agent.develop.develop_data import DevelopData +from adf_core_python.core.agent.info.scenario_info import Mode +from adf_core_python.core.agent.precompute.precompute_data import PrecomputeData from adf_core_python.core.logger.logger import get_logger class Agent(RCRSAgent): - def __init__(self, is_precompute: bool, name: str) -> None: + def __init__( + self, + is_precompute: bool, + name: str, + is_debug: bool, + team_name: str, + deta_storage_name: str, + module_config: ModuleConfig, + develop_data: DevelopData, + ) -> None: self.name = name self.connect_request_id = None self.world_model = WorldModel() @@ -20,8 +36,28 @@ def __init__(self, is_precompute: bool, name: str) -> None: f"{self.__class__.__module__}.{self.__class__.__qualname__}" ) + self.team_name = team_name + self.is_debug = is_debug + self.is_precompute = is_precompute + + if is_precompute: + # PrecomputeData.remove_date(deta_storage_name) + self.mode = Mode.PRECOMPUTATION + + self.module_config = module_config + self.develop_data = develop_data + self.precompute_data = PrecomputeData(deta_storage_name) + self.message_manager: MessageManager = MessageManager() + def handle_connect_error(self, msg: Any) -> NoReturn: self.logger.error( "Failed to connect agent: %s(request_id: %s)", msg.reason, msg.request_id ) sys.exit(1) + + def precompute(self): + pass + + @abstractmethod + def get_requested_entities(self) -> list[EntityURN]: + pass diff --git a/adf_core_python/core/agent/communication/message_manager.py b/adf_core_python/core/agent/communication/message_manager.py index 78831364..e873664c 100644 --- a/adf_core_python/core/agent/communication/message_manager.py +++ b/adf_core_python/core/agent/communication/message_manager.py @@ -1,4 +1,271 @@ -# TODO: Implement MessageManager class +from adf_core_python.core.agent.info.agent_info import AgentInfo +from adf_core_python.core.agent.info.scenario_info import ScenarioInfo, ScenarioInfoKeys +from adf_core_python.core.agent.info.world_info import WorldInfo +from adf_core_python.core.component.communication.channel_subscriber import ( + ChannelSubscriber, +) +from adf_core_python.core.component.communication.communication_message import ( + CommunicationMessage, +) +from adf_core_python.core.component.communication.message_coordinator import ( + MessageCoordinator, +) + + class MessageManager: + MAX_MESSAGE_CLASS_COUNT = 32 + def __init__(self) -> None: - pass + """ + Initialize the MessageManager. + + Parameters + ---------- + __standard_message_class_count : int + The count of standard message classes. + __custom_message_class_count : int + The count of custom message classes. + __message_classes : dict[int, CommunicationMessage] + The message classes. + __subscribed_channels : list[int] + The subscribed channels. Default is [1]. + __is_subscribed : bool + The flag to indicate if the agent is subscribed to the channel. + """ + self.__standard_message_class_count = 0b0000_0001 + self.__custom_message_class_count = 0b0001_0000 + self.__message_classes: dict[int, CommunicationMessage] = {} + self.__send_message_list: list[CommunicationMessage] = [] + self.__received_message_list: list[CommunicationMessage] = [] + self.__channel_send_message_list: list[list[CommunicationMessage]] = [] + self.__check_duplicate_cache: set[str] = set() + self.__message_coordinator: MessageCoordinator + self.__channel_subscriber: ChannelSubscriber + self.__heard_agent_help_message_count: int = 0 + self.__subscribed_channels: list[int] = [1] + self.__is_subscribed = False + + def set_subscribed_channels(self, subscribed_channels: list[int]) -> None: + """ + Set the subscribed channels. + + Parameters + ---------- + subscribed_channels : list[int] + The subscribed channels. + + """ + self.__subscribed_channels = subscribed_channels + self.__is_subscribed = False + + def get_subscribed_channels(self) -> list[int]: + """ + Get the subscribed channels. + + Returns + ------- + list[int] + The subscribed channels. + + """ + return self.__subscribed_channels + + def set_is_subscribed(self, is_subscribed: bool) -> None: + """ + Set the flag to indicate if the agent is subscribed to the channel. + + Parameters + ---------- + is_subscribed : bool + The flag to indicate if the agent is subscribed to the channel. + + """ + self.__is_subscribed = is_subscribed + + def get_is_subscribed(self) -> bool: + """ + Get the flag to indicate if the agent is subscribed to the channel. + + Returns + ------- + bool + The flag to indicate if the agent is subscribed to the channel. + + """ + return self.__is_subscribed + + def set_channel_subscriber(self, channel_subscriber: ChannelSubscriber) -> None: + """ + Set the channel subscriber. + + Parameters + ---------- + channel_subscriber : ChannelSubscriber + The channel subscriber. + + """ + self.__channel_subscriber = channel_subscriber + + def get_channel_subscriber(self) -> ChannelSubscriber: + """ + Get the channel subscriber. + + Returns + ------- + ChannelSubscriber + The channel subscriber. + + """ + return self.__channel_subscriber + + def add_heard_agent_help_message_count(self) -> None: + """ + Add the heard agent help message count. + + """ + self.__heard_agent_help_message_count += 1 + + def get_heard_agent_help_message_count(self) -> int: + """ + Get the heard agent help message count. + + Returns + ------- + int + The heard agent help message count. + + """ + return self.__heard_agent_help_message_count + + def add_received_message(self, message: CommunicationMessage) -> None: + """ + Add the received message. + + Parameters + ---------- + message : CommunicationMessage + The received message. + + """ + self.__received_message_list.append(message) + + def get_received_message_list(self) -> list[CommunicationMessage]: + """ + Get the received message list. + + Returns + ------- + list[CommunicationMessage] + The received message list. + + """ + return self.__received_message_list + + def subscribe( + self, agent_info: AgentInfo, world_info: WorldInfo, scenario_info: ScenarioInfo + ) -> None: + """ + Subscribe to the channel. + + Parameters + ---------- + agent_info : AgentInfo + The agent info. + world_info : WorldInfo + The world info. + scenario_info : ScenarioInfo + The scenario info. + + Throws + ------ + ValueError + If the ChannelSubscriber is not set. + + """ + if self.__channel_subscriber is None: + raise ValueError("ChannelSubscriber is not set.") + + self.__channel_subscriber.subscribe(agent_info, world_info, scenario_info, self) + + def register_message_class( + self, index: int, message_class: CommunicationMessage + ) -> None: + """ + Register the message class. + + Parameters + ---------- + message_class : type[CommunicationMessage] + The message class. + + """ + if index >= self.MAX_MESSAGE_CLASS_COUNT: + raise ValueError( + f"Possible index values are 0 to {self.MAX_MESSAGE_CLASS_COUNT-1}" + ) + self.__message_classes[index] = message_class + + def add_message( + self, message: CommunicationMessage, check_duplicate: bool = True + ) -> None: + """ + Add the message. + + Parameters + ---------- + message : CommunicationMessage + The message. + + """ + check_key = message.get_check_key() + # TODO:両方同じコードになっているが、なぜなのか調査する + if check_duplicate and check_key not in self.__check_duplicate_cache: + self.__send_message_list.append(message) + self.__check_duplicate_cache.add(check_key) + else: + self.__send_message_list.append(message) + self.__check_duplicate_cache.add(check_key) + + def coordinate_message( + self, agent_info: AgentInfo, world_info: WorldInfo, scenario_info: ScenarioInfo + ) -> None: + """ + Coordinate the message. + + Parameters + ---------- + agent_info : AgentInfo + The agent info. + world_info : WorldInfo + The world info. + scenario_info : ScenarioInfo + The scenario info. + + """ + if self.__message_coordinator is None: + raise ValueError("MessageCoordinator is not set.") + + self.__channel_send_message_list = [ + [] + for _ in range( + scenario_info.get_value(ScenarioInfoKeys.COMMS_CHANNELS_COUNT, 1) + ) + ] + + self.__message_coordinator.coordinate( + agent_info, + world_info, + scenario_info, + self, + self.__send_message_list, + self.__channel_send_message_list, + ) + + def refresh(self) -> None: + """ + Refresh the message manager. + + """ + self.__send_message_list = [] + self.__check_duplicate_cache = set() + self.__heard_agent_help_message_count = 0 diff --git a/adf_core_python/core/agent/communication/standard/standard_communication_module.py b/adf_core_python/core/agent/communication/standard/standard_communication_module.py new file mode 100644 index 00000000..057930d1 --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/standard_communication_module.py @@ -0,0 +1,14 @@ +from rcrs_core.agents.agent import Agent + +from adf_core_python.core.agent.communication.message_manager import MessageManager +from adf_core_python.core.component.communication.communication_module import ( + CommunicationModule, +) + + +class StandardCommunicationModule(CommunicationModule): + def receive(self, agent: Agent, message_manager: MessageManager) -> None: + raise NotImplementedError + + def send(self, agent: Agent, message_manager: MessageManager) -> None: + raise NotImplementedError diff --git a/adf_core_python/core/agent/info/scenario_info.py b/adf_core_python/core/agent/info/scenario_info.py index fe085bf2..f8d35fab 100644 --- a/adf_core_python/core/agent/info/scenario_info.py +++ b/adf_core_python/core/agent/info/scenario_info.py @@ -10,6 +10,37 @@ class Mode(Enum): PRECOMPUTATION = 2 +class ScenarioInfoKeys: + KERNEL_PERCEPTION = "kernel.perception" + PERCEPTION_LOS_PRECISION_HP = "perception.los.precision.hp" + CLEAR_REPAIR_RAD = "clear.repair.rad" + FIRE_TANK_REFILL_HYDRANT_RATE = "fire.tank.refill_hydrant_rate" + SCENARIO_AGENTS_PF = "scenario.agents.pf" + SCENARIO_AGENTS_FS = "scenario.agents.fs" + VOICE_MESSAGES_SIZE = "comms.channels.0.messages.size" + FIRE_TANK_REFILL_RATE = "fire.tank.refill_rate" + KERNEL_TIMESTEPS = "kernel.timesteps" + FIRE_EXTINGUISH_MAX_SUM = "fire.extinguish.max-sum" + COMMS_CHANNELS_MAX_PLATOON = "comms.channels.max.platoon" + KERNEL_AGENTS_THINK_TIME = "kernel.agents.think-time" + FIRE_TANK_MAXIMUM = "fire.tank.maximum" + CLEAR_REPAIR_RATE = "clear.repair.rate" + KERNEL_STARTUP_CONNECT_TIME = "kernel.startup.connect-time" + KERNEL_HOST = "kernel.host" + SCENARIO_AGENTS_AT = "scenario.agents.at" + PERCEPTION_LOS_MAX_DISTANCE = "perception.los.max-distance" + SCENARIO_AGENTS_FB = "scenario.agents.fb" + SCENARIO_AGENTS_PO = "scenario.agents.po" + KERNEL_COMMUNICATION_MODEL = "kernel.communication-model" + PERCEPTION_LOS_PRECISION_DAMAGE = "perception.los.precision.damage" + SCENARIO_AGENTS_AC = "scenario.agents.ac" + COMMS_CHANNELS_MAX_OFFICE = "comms.channels.max.centre" + FIRE_EXTINGUISH_MAX_DISTANCE = "fire.extinguish.max-distance" + KERNEL_AGENTS_IGNOREUNTIL = "kernel.agents.ignoreuntil" + CLEAR_REPAIR_DISTANCE = "clear.repair.distance" + COMMS_CHANNELS_COUNT = "comms.channels.count" + + class ScenarioInfo: def __init__(self, config: Config, mode: Mode): """ diff --git a/adf_core_python/core/component/communication/channel_subscriber.py b/adf_core_python/core/component/communication/channel_subscriber.py new file mode 100644 index 00000000..7b4ee895 --- /dev/null +++ b/adf_core_python/core/component/communication/channel_subscriber.py @@ -0,0 +1,32 @@ +from abc import ABC, abstractmethod + +from adf_core_python.core.agent.communication.message_manager import MessageManager +from adf_core_python.core.agent.info.agent_info import AgentInfo +from adf_core_python.core.agent.info.scenario_info import ScenarioInfo +from adf_core_python.core.agent.info.world_info import WorldInfo + + +class ChannelSubscriber(ABC): + @abstractmethod + def subscribe( + self, + agent_info: AgentInfo, + world_info: WorldInfo, + scenario_info: ScenarioInfo, + message_manager: MessageManager, + ) -> None: + """ + Subscribe to the channel. + + Parameters + ---------- + agent_info : AgentInfo + The agent info. + world_info : WorldInfo + The world info. + scenario_info : ScenarioInfo + The scenario info. + message_manager : MessageManager + The message manager. + """ + pass diff --git a/adf_core_python/core/component/communication/communication_message.py b/adf_core_python/core/component/communication/communication_message.py index 2909fcf2..a6cd25d0 100644 --- a/adf_core_python/core/component/communication/communication_message.py +++ b/adf_core_python/core/component/communication/communication_message.py @@ -16,4 +16,8 @@ def get_byte_size(self) -> int: def to_bytes(self) -> bytes: raise NotImplementedError + @abstractmethod + def get_check_key(self) -> str: + raise NotImplementedError + # TODO: Implement the toBitOutputStream and getCheckKey methods diff --git a/adf_core_python/core/component/communication/communication_module.py b/adf_core_python/core/component/communication/communication_module.py new file mode 100644 index 00000000..c1b957e7 --- /dev/null +++ b/adf_core_python/core/component/communication/communication_module.py @@ -0,0 +1,15 @@ +from abc import ABC, abstractmethod + +from rcrs_core.agents.agent import Agent + +from adf_core_python.core.agent.communication.message_manager import MessageManager + + +class CommunicationModule(ABC): + @abstractmethod + def receive(self, agent: Agent, message_manager: MessageManager) -> None: + pass + + @abstractmethod + def send(self, agent: Agent, message_manager: MessageManager) -> None: + pass diff --git a/adf_core_python/core/component/communication/message_coordinator.py b/adf_core_python/core/component/communication/message_coordinator.py new file mode 100644 index 00000000..d7490501 --- /dev/null +++ b/adf_core_python/core/component/communication/message_coordinator.py @@ -0,0 +1,23 @@ +from abc import ABC, abstractmethod + +from adf_core_python.core.agent.communication.message_manager import MessageManager +from adf_core_python.core.agent.info.agent_info import AgentInfo +from adf_core_python.core.agent.info.scenario_info import ScenarioInfo +from adf_core_python.core.agent.info.world_info import WorldInfo +from adf_core_python.core.component.communication.communication_message import ( + CommunicationMessage, +) + + +class MessageCoordinator(ABC): + @abstractmethod + def coordinate( + self, + agent_info: AgentInfo, + world_info: WorldInfo, + scenario_info: ScenarioInfo, + message_manager: MessageManager, + send_message_list: list[CommunicationMessage], + channel_send_message_list: list[list[CommunicationMessage]], + ) -> None: + pass From e37bac5ad8696220027fd78ec660ead8a6171188 Mon Sep 17 00:00:00 2001 From: shima004 Date: Fri, 18 Oct 2024 20:31:14 +0900 Subject: [PATCH 2/8] feat: add standard message and priority classes --- adf_core_python/core/agent/agent.py | 70 +++++++- .../infomation/message_ambulance_team.py | 159 ++++++++++++++++++ .../standard/bundle/standard_message.py | 53 ++++++ .../bundle/standard_message_priority.py | 14 ++ 4 files changed, 291 insertions(+), 5 deletions(-) create mode 100644 adf_core_python/core/agent/communication/standard/bundle/infomation/message_ambulance_team.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/standard_message.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py diff --git a/adf_core_python/core/agent/agent.py b/adf_core_python/core/agent/agent.py index 50056da9..805d29c5 100644 --- a/adf_core_python/core/agent/agent.py +++ b/adf_core_python/core/agent/agent.py @@ -3,15 +3,28 @@ from typing import Any, NoReturn from rcrs_core.agents.agent import Agent as RCRSAgent +from rcrs_core.commands.Command import Command +from rcrs_core.config.config import Config as RCRSConfig from rcrs_core.connection.URN import Entity as EntityURN +from rcrs_core.worldmodel.changeSet import ChangeSet from rcrs_core.worldmodel.worldmodel import WorldModel from adf_core_python.core.agent.communication.message_manager import MessageManager +from adf_core_python.core.agent.communication.standard.standard_communication_module import ( + StandardCommunicationModule, +) from adf_core_python.core.agent.config.module_config import ModuleConfig from adf_core_python.core.agent.develop.develop_data import DevelopData -from adf_core_python.core.agent.info.scenario_info import Mode +from adf_core_python.core.agent.info.agent_info import AgentInfo +from adf_core_python.core.agent.info.scenario_info import Mode, ScenarioInfo +from adf_core_python.core.agent.info.world_info import WorldInfo from adf_core_python.core.agent.precompute.precompute_data import PrecomputeData -from adf_core_python.core.logger.logger import get_logger +from adf_core_python.core.component.communication.communication_module import ( + CommunicationModule, +) +from adf_core_python.core.config.config import Config +from adf_core_python.core.launcher.config_key import ConfigKey +from adf_core_python.core.logger.logger import get_agent_logger, get_logger class Agent(RCRSAgent): @@ -21,7 +34,7 @@ def __init__( name: str, is_debug: bool, team_name: str, - deta_storage_name: str, + data_storage_name: str, module_config: ModuleConfig, develop_data: DevelopData, ) -> None: @@ -41,13 +54,60 @@ def __init__( self.is_precompute = is_precompute if is_precompute: - # PrecomputeData.remove_date(deta_storage_name) + # PrecomputeData.remove_date(data_storage_name) self.mode = Mode.PRECOMPUTATION self.module_config = module_config self.develop_data = develop_data - self.precompute_data = PrecomputeData(deta_storage_name) + self.precompute_data = PrecomputeData(data_storage_name) self.message_manager: MessageManager = MessageManager() + self.communication_module: CommunicationModule = StandardCommunicationModule() + + def post_connect(self) -> None: + self.world_model.index_entities() + + config = Config() + if self.config is not None: + rcrc_config: RCRSConfig = self.config + for key, value in rcrc_config.data.items(): + config.set_value(key, value) + for key, value in rcrc_config.int_data.items(): + config.set_value(key, value) + for key, value in rcrc_config.float_data.items(): + config.set_value(key, value) + for key, value in rcrc_config.boolean_data.items(): + config.set_value(key, value) + for key, value in rcrc_config.array_data.items(): + config.set_value(key, value) + + if self.is_precompute: + self._mode = Mode.PRECOMPUTATION + else: + # if self._precompute_data.is_ready(): + # self._mode = Mode.PRECOMPUTED + # else: + # self._mode = Mode.NON_PRECOMPUTE + self._mode = Mode.NON_PRECOMPUTE + + config.set_value(ConfigKey.KEY_DEBUG_FLAG, self.is_debug) + config.set_value( + ConfigKey.KEY_DEVELOP_FLAG, self.develop_data.is_develop_mode() + ) + self.ignore_time = config.get_value("kernel.agents.ignoreuntil", 3) + self.scenario_info: ScenarioInfo = ScenarioInfo(config, self._mode) + self.world_info: WorldInfo = WorldInfo(self.world_model) + self.agent_info = AgentInfo(self, self.world_model) + self.logger = get_agent_logger( + f"{self.__class__.__module__}.{self.__class__.__qualname__}", + self.agent_info, + ) + + def think(self, time: int, change_set: ChangeSet, hear: list[Command]) -> None: + self.agent_info.record_think_start_time() + self.agent_info.set_time(time) + + # if time == 1: + # self.message_manager.register_message_class() def handle_connect_error(self, msg: Any) -> NoReturn: self.logger.error( diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_ambulance_team.py b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_ambulance_team.py new file mode 100644 index 00000000..3c11291a --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_ambulance_team.py @@ -0,0 +1,159 @@ +from typing import TYPE_CHECKING, Optional + +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) + +if TYPE_CHECKING: + from rcrs_core.entities.ambulanceTeam import AmbulanceTeamEntity + + +class MessageAmbulanceTeam(StandardMessage): + ACTION_REST: int = 0 + ACTION_MOVE: int = 1 + ACTION_RESCUE: int = 2 + ACTION_LOAD: int = 3 + ACTION_UNLOAD: int = 4 + + SIZE_AMBULANCE_TEAM_ENTITY_ID: int = 32 + SIZE_AMBULANCE_TEAM_HP: int = 14 + SIZE_AMBULANCE_TEAM_BURIEDNESS: int = 13 + SIZE_AMBULANCE_TEAM_DAMAGE: int = 14 + SIZE_AMBULANCE_TEAM_POSITION: int = 32 + SIZE_TARGET_ENTITY_ID: int = 32 + SIZE_ACTION: int = 4 + + def __init__( + self, + is_wireless_message: bool, + sender_id: int, + ttl: int, + priority: StandardMessagePriority, + ambulance_team: AmbulanceTeamEntity, + action: int, + target_entity_id: EntityID, + ): + super().__init__(is_wireless_message, sender_id, ttl, priority) + self._ambulance_team_entity_id: Optional[EntityID] = ambulance_team.get_id() + self._ambulance_team_hp: Optional[int] = ambulance_team.get_hp() or -1 + self._ambulance_team_buriedness: Optional[int] = ( + ambulance_team.get_buriedness() or -1 + ) + self._ambulance_team_damage: Optional[int] = ambulance_team.get_damage() or -1 + self._ambulance_team_position: Optional[EntityID] = ( + ambulance_team.get_position() or EntityID(-1) + ) + self._target_entity_id: Optional[EntityID] = target_entity_id + self._action: Optional[int] = action + + def get_byte_size(self) -> int: + return self.to_bytes().__len__() + + def to_bytes(self) -> bytes: + byte_array = bytearray() + self.write_with_exist_flag( + byte_array, + self._ambulance_team_entity_id.get_value() + if self._ambulance_team_entity_id + else None, + self.SIZE_AMBULANCE_TEAM_ENTITY_ID, + ) + self.write_with_exist_flag( + byte_array, self._ambulance_team_hp, self.SIZE_AMBULANCE_TEAM_HP + ) + self.write_with_exist_flag( + byte_array, + self._ambulance_team_buriedness, + self.SIZE_AMBULANCE_TEAM_BURIEDNESS, + ) + self.write_with_exist_flag( + byte_array, self._ambulance_team_damage, self.SIZE_AMBULANCE_TEAM_DAMAGE + ) + self.write_with_exist_flag( + byte_array, + self._ambulance_team_position.get_value() + if self._ambulance_team_position + else None, + self.SIZE_AMBULANCE_TEAM_POSITION, + ) + self.write_with_exist_flag( + byte_array, + self._target_entity_id.get_value() if self._target_entity_id else None, + self.SIZE_TARGET_ENTITY_ID, + ) + self.write_with_exist_flag(byte_array, self._action, self.SIZE_ACTION) + return bytes(byte_array) + + def from_bytes(self, bytes: bytes) -> None: + byte_array = bytearray(bytes) + raw_ambulance_team_entity_id = self.read_with_exist_flag( + byte_array, self.SIZE_AMBULANCE_TEAM_ENTITY_ID + ) + self._ambulance_team_entity_id = ( + EntityID(raw_ambulance_team_entity_id) + if raw_ambulance_team_entity_id + else None + ) + self._ambulance_team_hp = self.read_with_exist_flag( + byte_array, self.SIZE_AMBULANCE_TEAM_HP + ) + self._ambulance_team_buriedness = self.read_with_exist_flag( + byte_array, self.SIZE_AMBULANCE_TEAM_BURIEDNESS + ) + self._ambulance_team_damage = self.read_with_exist_flag( + byte_array, self.SIZE_AMBULANCE_TEAM_DAMAGE + ) + raw_ambulance_team_position = self.read_with_exist_flag( + byte_array, self.SIZE_AMBULANCE_TEAM_POSITION + ) + self._ambulance_team_position = ( + EntityID(raw_ambulance_team_position) + if raw_ambulance_team_position + else None + ) + raw_target_entity_id = self.read_with_exist_flag( + byte_array, self.SIZE_TARGET_ENTITY_ID + ) + self._target_entity_id = ( + EntityID(raw_target_entity_id) if raw_target_entity_id else None + ) + self._action = self.read_with_exist_flag(byte_array, self.SIZE_ACTION) + + def get_check_key(self) -> str: + target_id_value: str = ( + str(self._target_entity_id.get_value()) + if self._target_entity_id + else "None" + ) + ambulance_team_id_value: str = ( + str(self._ambulance_team_entity_id.get_value()) + if self._ambulance_team_entity_id + else "None" + ) + return f"{self.__class__.__name__} > agent: {ambulance_team_id_value}, target: {target_id_value}, action: {self._action}" + + def get_ambulance_team_entity_id(self) -> Optional[EntityID]: + return self._ambulance_team_entity_id + + def get_ambulance_team_hp(self) -> Optional[int]: + return self._ambulance_team_hp + + def get_ambulance_team_buriedness(self) -> Optional[int]: + return self._ambulance_team_buriedness + + def get_ambulance_team_damage(self) -> Optional[int]: + return self._ambulance_team_damage + + def get_ambulance_team_position(self) -> Optional[EntityID]: + return self._ambulance_team_position + + def get_target_entity_id(self) -> Optional[EntityID]: + return self._target_entity_id + + def get_action(self) -> Optional[int]: + return self._action diff --git a/adf_core_python/core/agent/communication/standard/bundle/standard_message.py b/adf_core_python/core/agent/communication/standard/bundle/standard_message.py new file mode 100644 index 00000000..db6c8dda --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/standard_message.py @@ -0,0 +1,53 @@ +from typing import Optional + +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) +from adf_core_python.core.component.communication.communication_message import ( + CommunicationMessage, +) + + +class StandardMessage(CommunicationMessage): + def __init__( + self, + is_wireless_message: bool, + sender_id: int, + ttl: int, + priority: StandardMessagePriority, + ): + super().__init__(is_wireless_message) + self._sender_id = sender_id + self._ttl = ttl + self._priority = priority + + def get_sender_entity_id(self) -> EntityID: + return EntityID(self._sender_id) + + def get_ttl(self) -> int: + return self._ttl + + def get_priority(self) -> StandardMessagePriority: + return self._priority + + def write_with_exist_flag( + self, byte_array: bytearray, value: Optional[int], size: int + ) -> None: + if value is None: + byte_array.extend(b"\b0") + else: + byte_array.extend(b"\b1") + byte_array.extend(value.to_bytes(size, "big")) + + def read_with_exist_flag(self, byte_array: bytearray, size: int) -> Optional[int]: + exist_flag = byte_array.pop(0) + if exist_flag == 0: + return None + elif exist_flag == 1: + value = int.from_bytes(byte_array[:size], "big") + del byte_array[:size] + return value + else: + raise ValueError("Invalid exist flag") diff --git a/adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py b/adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py new file mode 100644 index 00000000..1c6b17f7 --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py @@ -0,0 +1,14 @@ +from enum import Enum + + +class StandardMessagePriority(Enum): + """ + Standard message priorities. + """ + + LOW = 0 + NORMAL = 1 + HIGH = 2 + + def __str__(self) -> str: + return self.name.lower() From 48fa3b3ab3551bd17c504a52ecd0fdfd287ad664 Mon Sep 17 00:00:00 2001 From: shima004 Date: Mon, 21 Oct 2024 02:52:07 +0900 Subject: [PATCH 3/8] feat: add info message --- adf_core_python/core/agent/agent.py | 2 +- .../infomation/message_ambulance_team.py | 101 +++++--- .../bundle/infomation/message_building.py | 110 ++++++++ .../bundle/infomation/message_civilian.py | 123 +++++++++ .../bundle/infomation/message_fire_brigade.py | 185 ++++++++++++++ .../bundle/infomation/message_police_force.py | 169 ++++++++++++ .../bundle/infomation/message_road.py | 167 ++++++++++++ .../standard/bundle/standard_message.py | 25 +- poetry.lock | 240 ++++++++++++++---- pyproject.toml | 2 +- 10 files changed, 1023 insertions(+), 101 deletions(-) create mode 100644 adf_core_python/core/agent/communication/standard/bundle/infomation/message_building.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/infomation/message_civilian.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/infomation/message_fire_brigade.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/infomation/message_police_force.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/infomation/message_road.py diff --git a/adf_core_python/core/agent/agent.py b/adf_core_python/core/agent/agent.py index 805d29c5..2e86e219 100644 --- a/adf_core_python/core/agent/agent.py +++ b/adf_core_python/core/agent/agent.py @@ -115,7 +115,7 @@ def handle_connect_error(self, msg: Any) -> NoReturn: ) sys.exit(1) - def precompute(self): + def precompute(self) -> None: pass @abstractmethod diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_ambulance_team.py b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_ambulance_team.py index 3c11291a..6a462a29 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_ambulance_team.py +++ b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_ambulance_team.py @@ -1,5 +1,9 @@ -from typing import TYPE_CHECKING, Optional +from __future__ import annotations +from typing import Optional + +from bitarray import bitarray +from rcrs_core.entities.ambulanceTeam import AmbulanceTeamEntity from rcrs_core.worldmodel.entityID import EntityID from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( @@ -9,9 +13,6 @@ StandardMessagePriority, ) -if TYPE_CHECKING: - from rcrs_core.entities.ambulanceTeam import AmbulanceTeamEntity - class MessageAmbulanceTeam(StandardMessage): ACTION_REST: int = 0 @@ -31,22 +32,22 @@ class MessageAmbulanceTeam(StandardMessage): def __init__( self, is_wireless_message: bool, - sender_id: int, - ttl: int, priority: StandardMessagePriority, ambulance_team: AmbulanceTeamEntity, action: int, target_entity_id: EntityID, + sender_id: int = -1, + ttl: int = -1, ): - super().__init__(is_wireless_message, sender_id, ttl, priority) + super().__init__(is_wireless_message, priority, sender_id, ttl) self._ambulance_team_entity_id: Optional[EntityID] = ambulance_team.get_id() - self._ambulance_team_hp: Optional[int] = ambulance_team.get_hp() or -1 + self._ambulance_team_hp: Optional[int] = ambulance_team.get_hp() or None self._ambulance_team_buriedness: Optional[int] = ( - ambulance_team.get_buriedness() or -1 + ambulance_team.get_buriedness() or None ) - self._ambulance_team_damage: Optional[int] = ambulance_team.get_damage() or -1 + self._ambulance_team_damage: Optional[int] = ambulance_team.get_damage() or None self._ambulance_team_position: Optional[EntityID] = ( - ambulance_team.get_position() or EntityID(-1) + ambulance_team.get_position() or None ) self._target_entity_id: Optional[EntityID] = target_entity_id self._action: Optional[int] = action @@ -55,74 +56,92 @@ def get_byte_size(self) -> int: return self.to_bytes().__len__() def to_bytes(self) -> bytes: - byte_array = bytearray() + bit_array = bitarray() self.write_with_exist_flag( - byte_array, + bit_array, self._ambulance_team_entity_id.get_value() if self._ambulance_team_entity_id else None, self.SIZE_AMBULANCE_TEAM_ENTITY_ID, ) self.write_with_exist_flag( - byte_array, self._ambulance_team_hp, self.SIZE_AMBULANCE_TEAM_HP + bit_array, self._ambulance_team_hp, self.SIZE_AMBULANCE_TEAM_HP ) self.write_with_exist_flag( - byte_array, + bit_array, self._ambulance_team_buriedness, self.SIZE_AMBULANCE_TEAM_BURIEDNESS, ) self.write_with_exist_flag( - byte_array, self._ambulance_team_damage, self.SIZE_AMBULANCE_TEAM_DAMAGE + bit_array, self._ambulance_team_damage, self.SIZE_AMBULANCE_TEAM_DAMAGE ) self.write_with_exist_flag( - byte_array, + bit_array, self._ambulance_team_position.get_value() if self._ambulance_team_position else None, self.SIZE_AMBULANCE_TEAM_POSITION, ) self.write_with_exist_flag( - byte_array, + bit_array, self._target_entity_id.get_value() if self._target_entity_id else None, self.SIZE_TARGET_ENTITY_ID, ) - self.write_with_exist_flag(byte_array, self._action, self.SIZE_ACTION) - return bytes(byte_array) + self.write_with_exist_flag(bit_array, self._action, self.SIZE_ACTION) + return bit_array.tobytes() - def from_bytes(self, bytes: bytes) -> None: - byte_array = bytearray(bytes) - raw_ambulance_team_entity_id = self.read_with_exist_flag( - byte_array, self.SIZE_AMBULANCE_TEAM_ENTITY_ID + @classmethod + def from_bytes(cls, bytes: bytes) -> MessageAmbulanceTeam: + bit_array = bitarray() + bit_array.frombytes(bytes) + raw_ambulance_team_entity_id = cls.read_with_exist_flag( + bit_array, cls.SIZE_AMBULANCE_TEAM_ENTITY_ID ) - self._ambulance_team_entity_id = ( + ambulance_team_entity_id = ( EntityID(raw_ambulance_team_entity_id) - if raw_ambulance_team_entity_id + if raw_ambulance_team_entity_id is not None else None ) - self._ambulance_team_hp = self.read_with_exist_flag( - byte_array, self.SIZE_AMBULANCE_TEAM_HP + ambulance_team_hp = cls.read_with_exist_flag( + bit_array, cls.SIZE_AMBULANCE_TEAM_HP ) - self._ambulance_team_buriedness = self.read_with_exist_flag( - byte_array, self.SIZE_AMBULANCE_TEAM_BURIEDNESS + ambulance_team_buriedness = cls.read_with_exist_flag( + bit_array, cls.SIZE_AMBULANCE_TEAM_BURIEDNESS ) - self._ambulance_team_damage = self.read_with_exist_flag( - byte_array, self.SIZE_AMBULANCE_TEAM_DAMAGE + ambulance_team_damage = cls.read_with_exist_flag( + bit_array, cls.SIZE_AMBULANCE_TEAM_DAMAGE ) - raw_ambulance_team_position = self.read_with_exist_flag( - byte_array, self.SIZE_AMBULANCE_TEAM_POSITION + + raw_ambulance_team_position = cls.read_with_exist_flag( + bit_array, cls.SIZE_AMBULANCE_TEAM_POSITION ) - self._ambulance_team_position = ( + ambulance_team_position = ( EntityID(raw_ambulance_team_position) - if raw_ambulance_team_position + if raw_ambulance_team_position is not None else None ) - raw_target_entity_id = self.read_with_exist_flag( - byte_array, self.SIZE_TARGET_ENTITY_ID + + raw_target_entity_id = cls.read_with_exist_flag( + bit_array, cls.SIZE_TARGET_ENTITY_ID + ) + target_entity_id = ( + EntityID(raw_target_entity_id) if raw_target_entity_id is not None else None + ) + action = cls.read_with_exist_flag(bit_array, cls.SIZE_ACTION) + ambulance_team = AmbulanceTeamEntity( + ambulance_team_entity_id, ) - self._target_entity_id = ( - EntityID(raw_target_entity_id) if raw_target_entity_id else None + ambulance_team.set_hp(ambulance_team_hp) + ambulance_team.set_buriedness(ambulance_team_buriedness) + ambulance_team.set_damage(ambulance_team_damage) + ambulance_team.set_position(ambulance_team_position) + return MessageAmbulanceTeam( + False, + StandardMessagePriority.NORMAL, + ambulance_team, + action or -1, + target_entity_id or EntityID(-1), ) - self._action = self.read_with_exist_flag(byte_array, self.SIZE_ACTION) def get_check_key(self) -> str: target_id_value: str = ( diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_building.py b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_building.py new file mode 100644 index 00000000..e26d00c1 --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_building.py @@ -0,0 +1,110 @@ +from __future__ import annotations + +from typing import Optional + +from bitarray import bitarray +from rcrs_core.entities.building import Building +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) + + +class MessageBuilding(StandardMessage): + SIZE_BUILDING_ENTITY_ID: int = 32 + SIZE_BUILDING_BROKENNESS: int = 32 + SIZE_BUILDING_FIREYNESS: int = 32 + SIZE_BUILDING_TEMPERATURE: int = 32 + + def __init__( + self, + is_wireless_message: bool, + building: Building, + priority: StandardMessagePriority = StandardMessagePriority.NORMAL, + sender_id: int = -1, + ttl: int = -1, + ): + super().__init__(is_wireless_message, priority, sender_id, ttl) + self._building_entity_id: Optional[EntityID] = building.get_id() + self._building_brokenness: Optional[int] = building.get_brokenness() or None + self._building_fireyness: Optional[int] = building.get_fieryness() or None + self._building_temperature: Optional[int] = building.get_temperature() or None + + def get_byte_size(self) -> int: + return self.to_bytes().__len__() + + def to_bytes(self) -> bytes: + bit_array = bitarray() + self.write_with_exist_flag( + bit_array, + self._building_entity_id.get_value() if self._building_entity_id else None, + self.SIZE_BUILDING_ENTITY_ID, + ) + self.write_with_exist_flag( + bit_array, + self._building_brokenness, + self.SIZE_BUILDING_BROKENNESS, + ) + self.write_with_exist_flag( + bit_array, + self._building_fireyness, + self.SIZE_BUILDING_FIREYNESS, + ) + self.write_with_exist_flag( + bit_array, + self._building_temperature, + self.SIZE_BUILDING_TEMPERATURE, + ) + return bit_array.tobytes() + + @classmethod + def from_bytes(cls, bytes: bytes) -> MessageBuilding: + bit_array = bitarray() + bit_array.frombytes(bytes) + raw_building_entity_id = cls.read_with_exist_flag( + bit_array, cls.SIZE_BUILDING_ENTITY_ID + ) + building_entity_id = ( + EntityID(raw_building_entity_id) if raw_building_entity_id else None + ) + building_brokenness = cls.read_with_exist_flag( + bit_array, cls.SIZE_BUILDING_BROKENNESS + ) + building_fireyness = cls.read_with_exist_flag( + bit_array, cls.SIZE_BUILDING_FIREYNESS + ) + building_temperature = cls.read_with_exist_flag( + bit_array, cls.SIZE_BUILDING_TEMPERATURE + ) + building = Building( + building_entity_id.get_value() if building_entity_id else None + ) + building.set_brokenness(building_brokenness) + building.set_fieryness(building_fireyness) + building.set_temperature(building_temperature) + return MessageBuilding( + False, + building, + ) + + def get_check_key(self) -> str: + building_entity_id_value = ( + self._building_entity_id.get_value() if self._building_entity_id else None + ) + return f"{self.__class__.__name__} > building: {building_entity_id_value}" + + def get_building_entity_id(self) -> Optional[EntityID]: + return self._building_entity_id + + def get_building_brokenness(self) -> Optional[int]: + return self._building_brokenness + + def get_building_fireyness(self) -> Optional[int]: + return self._building_fireyness + + def get_building_temperature(self) -> Optional[int]: + return self._building_temperature diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_civilian.py b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_civilian.py new file mode 100644 index 00000000..bc3c73b3 --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_civilian.py @@ -0,0 +1,123 @@ +from __future__ import annotations + +from typing import Optional + +from bitarray import bitarray +from rcrs_core.entities.civilian import Civilian +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) + + +class MessageCivilian(StandardMessage): + SIZE_CIVILIAN_ENTITY_ID: int = 32 + SIZE_CIVILIAN_HP: int = 14 + SIZE_CIVILIAN_BURIEDNESS: int = 13 + SIZE_CIVILIAN_DAMAGE: int = 14 + SIZE_CIVILIAN_POSITION: int = 32 + + def __init__( + self, + is_wireless_message: bool, + civilian: Civilian, + priority: StandardMessagePriority = StandardMessagePriority.NORMAL, + sender_id: int = -1, + ttl: int = -1, + ): + super().__init__(is_wireless_message, priority, sender_id, ttl) + self._civilian_entity_id: Optional[EntityID] = civilian.get_id() + self._civilian_hp: Optional[int] = civilian.get_hp() or None + self._civilian_buriedness: Optional[int] = civilian.get_buriedness() or None + self._civilian_damage: Optional[int] = civilian.get_damage() or None + self._civilian_position: Optional[EntityID] = civilian.get_position() or None + + def get_byte_size(self) -> int: + return self.to_bytes().__len__() + + def to_bytes(self) -> bytes: + bit_array = bitarray() + self.write_with_exist_flag( + bit_array, + self._civilian_entity_id.get_value() if self._civilian_entity_id else None, + self.SIZE_CIVILIAN_ENTITY_ID, + ) + self.write_with_exist_flag( + bit_array, + self._civilian_hp, + self.SIZE_CIVILIAN_HP, + ) + self.write_with_exist_flag( + bit_array, + self._civilian_buriedness, + self.SIZE_CIVILIAN_BURIEDNESS, + ) + self.write_with_exist_flag( + bit_array, + self._civilian_damage, + self.SIZE_CIVILIAN_DAMAGE, + ) + self.write_with_exist_flag( + bit_array, + self._civilian_position.get_value() if self._civilian_position else None, + self.SIZE_CIVILIAN_POSITION, + ) + return bit_array.tobytes() + + @classmethod + def from_bytes(cls, bytes: bytes) -> MessageCivilian: + bit_array = bitarray() + bit_array.frombytes(bytes) + raw_civilian_entity_id = cls.read_with_exist_flag( + bit_array, cls.SIZE_CIVILIAN_ENTITY_ID + ) + civilian_entity_id = ( + EntityID(raw_civilian_entity_id) if raw_civilian_entity_id else None + ) + civilian_hp = cls.read_with_exist_flag(bit_array, cls.SIZE_CIVILIAN_HP) + civilian_buriedness = cls.read_with_exist_flag( + bit_array, cls.SIZE_CIVILIAN_BURIEDNESS + ) + civilian_damage = cls.read_with_exist_flag(bit_array, cls.SIZE_CIVILIAN_DAMAGE) + raw_civilian_position = cls.read_with_exist_flag( + bit_array, cls.SIZE_CIVILIAN_POSITION + ) + civilian_position = ( + EntityID(raw_civilian_position) if raw_civilian_position else None + ) + civilian = Civilian( + civilian_entity_id.get_value() if civilian_entity_id else None + ) + civilian.set_hp(civilian_hp) + civilian.set_buriedness(civilian_buriedness) + civilian.set_damage(civilian_damage) + civilian.set_position(civilian_position) + return MessageCivilian( + False, + civilian, + ) + + def get_check_key(self) -> str: + civilian_entity_id_value = ( + self._civilian_entity_id.get_value() if self._civilian_entity_id else None + ) + return f"{self.__class__.__name__} > civilian: {civilian_entity_id_value}" + + def get_civilian_entity_id(self) -> Optional[EntityID]: + return self._civilian_entity_id + + def get_civilian_hp(self) -> Optional[int]: + return self._civilian_hp + + def get_civilian_buriedness(self) -> Optional[int]: + return self._civilian_buriedness + + def get_civilian_damage(self) -> Optional[int]: + return self._civilian_damage + + def get_civilian_position(self) -> Optional[EntityID]: + return self._civilian_position diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_fire_brigade.py b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_fire_brigade.py new file mode 100644 index 00000000..b2d9298b --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_fire_brigade.py @@ -0,0 +1,185 @@ +from __future__ import annotations + +from typing import Optional + +from bitarray import bitarray +from rcrs_core.entities.fireBrigade import FireBrigadeEntity +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) + + +class MessageFireBrigade(StandardMessage): + CTION_REST: int = 0 + ACTION_MOVE: int = 1 + ACTION_EXTINGUISH: int = 2 + ACTION_REFILL: int = 3 + ACTION_RESCUE: int = 4 + + SIZE_FIRE_BRIGADE_ENTITY_ID: int = 32 + SIZE_FIRE_BRIGADE_HP: int = 14 + SIZE_FIRE_BRIGADE_BURIEDNESS: int = 13 + SIZE_FIRE_BRIGADE_DAMAGE: int = 14 + SIZE_FIRE_BRIGADE_POSITION: int = 32 + SIZE_FIRE_BRIGADE_WATER: int = 14 + SIZE_TARGET_ENTITY_ID: int = 32 + SIZE_ACTION: int = 4 + + def __init__( + self, + is_wireless_message: bool, + fire_brigade: FireBrigadeEntity, + action: int, + target_entity_id: EntityID, + priority: StandardMessagePriority = StandardMessagePriority.NORMAL, + sender_id: int = -1, + ttl: int = -1, + ): + super().__init__(is_wireless_message, priority, sender_id, ttl) + self._fire_brigade_entity_id: Optional[EntityID] = fire_brigade.get_id() + self._fire_brigade_hp: Optional[int] = fire_brigade.get_hp() or None + self._fire_brigade_buriedness: Optional[int] = ( + fire_brigade.get_buriedness() or None + ) + self._fire_brigade_damage: Optional[int] = fire_brigade.get_damage() or None + self._fire_brigade_position: Optional[EntityID] = ( + fire_brigade.get_position() or None + ) + self._fire_brigade_water: Optional[int] = fire_brigade.get_water() or None + self._target_entity_id: Optional[EntityID] = target_entity_id + self._action: Optional[int] = action + + def get_byte_size(self) -> int: + return self.to_bytes().__len__() + + def to_bytes(self) -> bytes: + bit_array = bitarray() + self.write_with_exist_flag( + bit_array, + self._fire_brigade_entity_id.get_value() + if self._fire_brigade_entity_id + else None, + self.SIZE_FIRE_BRIGADE_ENTITY_ID, + ) + self.write_with_exist_flag( + bit_array, + self._fire_brigade_hp, + self.SIZE_FIRE_BRIGADE_HP, + ) + self.write_with_exist_flag( + bit_array, + self._fire_brigade_buriedness, + self.SIZE_FIRE_BRIGADE_BURIEDNESS, + ) + self.write_with_exist_flag( + bit_array, + self._fire_brigade_damage, + self.SIZE_FIRE_BRIGADE_DAMAGE, + ) + self.write_with_exist_flag( + bit_array, + self._fire_brigade_position.get_value() + if self._fire_brigade_position + else None, + self.SIZE_FIRE_BRIGADE_POSITION, + ) + self.write_with_exist_flag( + bit_array, + self._fire_brigade_water, + self.SIZE_FIRE_BRIGADE_WATER, + ) + self.write_with_exist_flag( + bit_array, + self._target_entity_id.get_value() if self._target_entity_id else None, + self.SIZE_TARGET_ENTITY_ID, + ) + self.write_with_exist_flag(bit_array, self._action, self.SIZE_ACTION) + return bit_array.tobytes() + + @classmethod + def from_bytes(cls, bytes: bytes) -> MessageFireBrigade: + bit_array = bitarray() + bit_array.frombytes(bytes) + raw_fire_brigade_entity_id = cls.read_with_exist_flag( + bit_array, cls.SIZE_FIRE_BRIGADE_ENTITY_ID + ) + fire_brigade_entity_id = ( + EntityID(raw_fire_brigade_entity_id) if raw_fire_brigade_entity_id else None + ) + fire_brigade_hp = cls.read_with_exist_flag(bit_array, cls.SIZE_FIRE_BRIGADE_HP) + fire_brigade_buriedness = cls.read_with_exist_flag( + bit_array, cls.SIZE_FIRE_BRIGADE_BURIEDNESS + ) + fire_brigade_damage = cls.read_with_exist_flag( + bit_array, cls.SIZE_FIRE_BRIGADE_DAMAGE + ) + raw_fire_brigade_position = cls.read_with_exist_flag( + bit_array, cls.SIZE_FIRE_BRIGADE_POSITION + ) + fire_brigade_position = ( + EntityID(raw_fire_brigade_position) if raw_fire_brigade_position else None + ) + fire_brigade_water = cls.read_with_exist_flag( + bit_array, cls.SIZE_FIRE_BRIGADE_WATER + ) + raw_target_entity_id = cls.read_with_exist_flag( + bit_array, cls.SIZE_TARGET_ENTITY_ID + ) + target_entity_id = ( + EntityID(raw_target_entity_id) if raw_target_entity_id else None + ) + action = cls.read_with_exist_flag(bit_array, cls.SIZE_ACTION) + fire_brigade = FireBrigadeEntity( + fire_brigade_entity_id.get_value() if fire_brigade_entity_id else None + ) + fire_brigade.set_hp(fire_brigade_hp) + fire_brigade.set_buriedness(fire_brigade_buriedness) + fire_brigade.set_damage(fire_brigade_damage) + fire_brigade.set_position(fire_brigade_position) + fire_brigade.set_water(fire_brigade_water) + return MessageFireBrigade( + False, + fire_brigade, + action or -1, + target_entity_id or EntityID(-1), + ) + + def get_check_key(self) -> str: + fire_brigade_entity_id_value = ( + self._fire_brigade_entity_id.get_value() + if self._fire_brigade_entity_id + else None + ) + target_entity_id_value = ( + self._target_entity_id.get_value() if self._target_entity_id else None + ) + return f"{self.__class__.__name__} > fire brigade: {fire_brigade_entity_id_value} > target: {target_entity_id_value} > action: {self._action}" + + def get_fire_brigade_entity_id(self) -> Optional[EntityID]: + return self._fire_brigade_entity_id + + def get_fire_brigade_hp(self) -> Optional[int]: + return self._fire_brigade_hp + + def get_fire_brigade_buriedness(self) -> Optional[int]: + return self._fire_brigade_buriedness + + def get_fire_brigade_damage(self) -> Optional[int]: + return self._fire_brigade_damage + + def get_fire_brigade_position(self) -> Optional[EntityID]: + return self._fire_brigade_position + + def get_fire_brigade_water(self) -> Optional[int]: + return self._fire_brigade_water + + def get_target_entity_id(self) -> Optional[EntityID]: + return self._target_entity_id + + def get_action(self) -> Optional[int]: + return self._action diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_police_force.py b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_police_force.py new file mode 100644 index 00000000..6f3c43c0 --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_police_force.py @@ -0,0 +1,169 @@ +from __future__ import annotations + +from typing import Optional + +from bitarray import bitarray +from rcrs_core.entities.policeForce import PoliceForceEntity +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) + + +class MessagePoliceForce(StandardMessage): + CTION_REST: int = 0 + ACTION_MOVE: int = 1 + ACTION_CLEAR: int = 2 + + SIZE_POLICE_FORCE_ENTITY_ID: int = 32 + SIZE_POLICE_FORCE_HP: int = 14 + SIZE_POLICE_FORCE_BURIEDNESS: int = 13 + SIZE_POLICE_FORCE_DAMAGE: int = 14 + SIZE_POLICE_FORCE_POSITION: int = 32 + SIZE_TARGET_ENTITY_ID: int = 32 + SIZE_ACTION: int = 4 + + def __init__( + self, + is_wireless_message: bool, + police_force: PoliceForceEntity, + action: int, + target_entity_id: EntityID, + priority: StandardMessagePriority = StandardMessagePriority.NORMAL, + sender_id: int = -1, + ttl: int = -1, + ): + super().__init__(is_wireless_message, priority, sender_id, ttl) + self._police_force_entity_id: Optional[EntityID] = police_force.get_id() + self._police_force_hp: Optional[int] = police_force.get_hp() or None + self._police_force_buriedness: Optional[int] = ( + police_force.get_buriedness() or None + ) + self._police_force_damage: Optional[int] = police_force.get_damage() or None + self._police_force_position: Optional[EntityID] = ( + police_force.get_position() or None + ) + self._target_entity_id: Optional[EntityID] = target_entity_id + self._action: Optional[int] = action + + def get_byte_size(self) -> int: + return self.to_bytes().__len__() + + def to_bytes(self) -> bytes: + bit_array = bitarray() + self.write_with_exist_flag( + bit_array, + self._police_force_entity_id.get_value() + if self._police_force_entity_id + else None, + self.SIZE_POLICE_FORCE_ENTITY_ID, + ) + self.write_with_exist_flag( + bit_array, + self._police_force_hp, + self.SIZE_POLICE_FORCE_HP, + ) + self.write_with_exist_flag( + bit_array, + self._police_force_buriedness, + self.SIZE_POLICE_FORCE_BURIEDNESS, + ) + self.write_with_exist_flag( + bit_array, + self._police_force_damage, + self.SIZE_POLICE_FORCE_DAMAGE, + ) + self.write_with_exist_flag( + bit_array, + self._police_force_position.get_value() + if self._police_force_position + else None, + self.SIZE_POLICE_FORCE_POSITION, + ) + self.write_with_exist_flag( + bit_array, + self._target_entity_id.get_value() if self._target_entity_id else None, + self.SIZE_TARGET_ENTITY_ID, + ) + self.write_with_exist_flag(bit_array, self._action, self.SIZE_ACTION) + return bit_array.tobytes() + + @classmethod + def from_bytes(cls, bytes: bytes) -> MessagePoliceForce: + bit_array = bitarray() + bit_array.frombytes(bytes) + raw_police_force_entity_id = cls.read_with_exist_flag( + bit_array, cls.SIZE_POLICE_FORCE_ENTITY_ID + ) + police_force_entity_id = ( + EntityID(raw_police_force_entity_id) if raw_police_force_entity_id else None + ) + police_force_hp = cls.read_with_exist_flag(bit_array, cls.SIZE_POLICE_FORCE_HP) + police_force_buriedness = cls.read_with_exist_flag( + bit_array, cls.SIZE_POLICE_FORCE_BURIEDNESS + ) + police_force_damage = cls.read_with_exist_flag( + bit_array, cls.SIZE_POLICE_FORCE_DAMAGE + ) + raw_police_force_position = cls.read_with_exist_flag( + bit_array, cls.SIZE_POLICE_FORCE_POSITION + ) + police_force_position = ( + EntityID(raw_police_force_position) if raw_police_force_position else None + ) + raw_target_entity_id = cls.read_with_exist_flag( + bit_array, cls.SIZE_TARGET_ENTITY_ID + ) + target_entity_id = ( + EntityID(raw_target_entity_id) if raw_target_entity_id else None + ) + action = cls.read_with_exist_flag(bit_array, cls.SIZE_ACTION) + police_force = PoliceForceEntity( + police_force_entity_id.get_value() if police_force_entity_id else None + ) + police_force.set_hp(police_force_hp) + police_force.set_buriedness(police_force_buriedness) + police_force.set_damage(police_force_damage) + police_force.set_position(police_force_position) + return MessagePoliceForce( + False, + police_force, + action or -1, + target_entity_id or EntityID(-1), + ) + + def get_check_key(self) -> str: + police_force_entity_id_value = ( + self._police_force_entity_id.get_value() + if self._police_force_entity_id + else None + ) + target_entity_id_value = ( + self._target_entity_id.get_value() if self._target_entity_id else None + ) + return f"{self.__class__.__name__} > police force: {police_force_entity_id_value} > target: {target_entity_id_value} > action: {self._action}" + + def get_police_force_entity_id(self) -> Optional[EntityID]: + return self._police_force_entity_id + + def get_police_force_hp(self) -> Optional[int]: + return self._police_force_hp + + def get_police_force_buriedness(self) -> Optional[int]: + return self._police_force_buriedness + + def get_police_force_damage(self) -> Optional[int]: + return self._police_force_damage + + def get_police_force_position(self) -> Optional[EntityID]: + return self._police_force_position + + def get_target_entity_id(self) -> Optional[EntityID]: + return self._target_entity_id + + def get_action(self) -> Optional[int]: + return self._action diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_road.py b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_road.py new file mode 100644 index 00000000..89a2863b --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/infomation/message_road.py @@ -0,0 +1,167 @@ +from __future__ import annotations + +from typing import Optional + +from bitarray import bitarray +from rcrs_core.entities.blockade import Blockade +from rcrs_core.entities.road import Road +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) + + +class MessageRoad(StandardMessage): + CTION_REST: int = 0 + ACTION_MOVE: int = 1 + ACTION_CLEAR: int = 2 + + SIZE_ROAD_ENTITY_ID: int = 32 + SIZE_ROAD_BLOCKADE_ENTITY_ID: int = 32 + SIZE_ROAD_BLOCKADE_REPAIR_COST: int = 32 + SIZE_ROAD_BLOCKADE_X: int = 32 + SIZE_ROAD_BLOCKADE_Y: int = 32 + SIZE_PASSABLE: int = 1 + + def __init__( + self, + is_wireless_message: bool, + road: Road, + is_send_blockade_location: bool, + is_passable: Optional[bool], + blockade: Optional[Blockade], + priority: StandardMessagePriority = StandardMessagePriority.NORMAL, + sender_id: int = -1, + ttl: int = -1, + ): + super().__init__(is_wireless_message, priority, sender_id, ttl) + self._road_entity_id: Optional[EntityID] = road.get_id() + self._road_blockade_entity_id: Optional[EntityID] = None + self._road_blockade_repair_cost: Optional[int] = None + self._road_blockade_x: Optional[int] = None + self._road_blockade_y: Optional[int] = None + + if blockade: + self._road_blockade_entity_id = blockade.get_id() + self._road_blockade_repair_cost = blockade.get_repaire_cost() + if is_send_blockade_location: + self._road_blockade_x = blockade.get_x() or None + self._road_blockade_y = blockade.get_y() or None + + self._is_passable: Optional[bool] = is_passable + self._is_send_blockade_location: bool = is_send_blockade_location + + def get_byte_size(self) -> int: + return self.to_bytes().__len__() + + def to_bytes(self) -> bytes: + bit_array = bitarray() + self.write_with_exist_flag( + bit_array, + self._road_entity_id.get_value() if self._road_entity_id else None, + self.SIZE_ROAD_ENTITY_ID, + ) + self.write_with_exist_flag( + bit_array, + self._road_blockade_entity_id.get_value() + if self._road_blockade_entity_id + else None, + self.SIZE_ROAD_BLOCKADE_ENTITY_ID, + ) + self.write_with_exist_flag( + bit_array, + self._road_blockade_repair_cost + if self._road_blockade_repair_cost + else None, + self.SIZE_ROAD_BLOCKADE_REPAIR_COST, + ) + if self._is_send_blockade_location: + self.write_with_exist_flag( + bit_array, + self._road_blockade_x if self._road_blockade_x else None, + self.SIZE_ROAD_BLOCKADE_X, + ) + self.write_with_exist_flag( + bit_array, + self._road_blockade_y if self._road_blockade_y else None, + self.SIZE_ROAD_BLOCKADE_Y, + ) + else: + self.write_with_exist_flag(bit_array, None, self.SIZE_ROAD_BLOCKADE_X) + self.write_with_exist_flag(bit_array, None, self.SIZE_ROAD_BLOCKADE_Y) + self.write_with_exist_flag( + bit_array, + self._is_passable if self._is_passable else None, + self.SIZE_PASSABLE, + ) + return bit_array.tobytes() + + @classmethod + def from_bytes(cls, bytes: bytes) -> MessageRoad: + bit_array = bitarray() + bit_array.frombytes(bytes) + raw_road_entity_id = cls.read_with_exist_flag( + bit_array, cls.SIZE_ROAD_ENTITY_ID + ) + road_entity_id = EntityID(raw_road_entity_id) if raw_road_entity_id else None + raw_road_blockade_entity_id = cls.read_with_exist_flag( + bit_array, cls.SIZE_ROAD_BLOCKADE_ENTITY_ID + ) + road_blockade_entity_id = ( + EntityID(raw_road_blockade_entity_id) + if raw_road_blockade_entity_id + else None + ) + road_blockade_repair_cost = cls.read_with_exist_flag( + bit_array, cls.SIZE_ROAD_BLOCKADE_REPAIR_COST + ) + road_blockade_x = cls.read_with_exist_flag(bit_array, cls.SIZE_ROAD_BLOCKADE_X) + road_blockade_y = cls.read_with_exist_flag(bit_array, cls.SIZE_ROAD_BLOCKADE_Y) + is_passable = ( + True if cls.read_with_exist_flag(bit_array, cls.SIZE_PASSABLE) else False + ) + road = Road(road_entity_id.get_value() if road_entity_id else None) + blockade = Blockade( + road_blockade_entity_id.get_value() if road_blockade_entity_id else None + ) + blockade.set_repaire_cost(road_blockade_repair_cost) + blockade.set_x(road_blockade_x) + blockade.set_y(road_blockade_y) + return MessageRoad( + False, + road, + False, + is_passable, + blockade, + ) + + def get_check_key(self) -> str: + road_entity_id_value = ( + self._road_entity_id.get_value() if self._road_entity_id else None + ) + return f"{self.__class__.__name__} > road: {road_entity_id_value}" + + def get_road_entity_id(self) -> Optional[EntityID]: + return self._road_entity_id + + def get_road_blockade_entity_id(self) -> Optional[EntityID]: + return self._road_blockade_entity_id + + def get_road_blockade_repair_cost(self) -> Optional[int]: + return self._road_blockade_repair_cost + + def get_road_blockade_x(self) -> Optional[int]: + return self._road_blockade_x + + def get_road_blockade_y(self) -> Optional[int]: + return self._road_blockade_y + + def get_is_passable(self) -> Optional[bool]: + return self._is_passable + + def get_is_send_blockade_location(self) -> bool: + return self._is_send_blockade_location diff --git a/adf_core_python/core/agent/communication/standard/bundle/standard_message.py b/adf_core_python/core/agent/communication/standard/bundle/standard_message.py index db6c8dda..c66f66a1 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/standard_message.py +++ b/adf_core_python/core/agent/communication/standard/bundle/standard_message.py @@ -1,5 +1,6 @@ from typing import Optional +from bitarray import bitarray from rcrs_core.worldmodel.entityID import EntityID from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( @@ -14,14 +15,14 @@ class StandardMessage(CommunicationMessage): def __init__( self, is_wireless_message: bool, - sender_id: int, - ttl: int, priority: StandardMessagePriority, + sender_id: int = -1, + ttl: int = -1, ): super().__init__(is_wireless_message) + self._priority = priority self._sender_id = sender_id self._ttl = ttl - self._priority = priority def get_sender_entity_id(self) -> EntityID: return EntityID(self._sender_id) @@ -32,22 +33,24 @@ def get_ttl(self) -> int: def get_priority(self) -> StandardMessagePriority: return self._priority + @staticmethod def write_with_exist_flag( - self, byte_array: bytearray, value: Optional[int], size: int + bit_array: bitarray, value: Optional[int], size: int ) -> None: if value is None: - byte_array.extend(b"\b0") + bit_array.extend([False]) else: - byte_array.extend(b"\b1") - byte_array.extend(value.to_bytes(size, "big")) + bit_array.extend([True]) + bit_array.frombytes(value.to_bytes(size, "big")) - def read_with_exist_flag(self, byte_array: bytearray, size: int) -> Optional[int]: - exist_flag = byte_array.pop(0) + @staticmethod + def read_with_exist_flag(bit_array: bitarray, size: int) -> Optional[int]: + exist_flag = bit_array.pop(0) if exist_flag == 0: return None elif exist_flag == 1: - value = int.from_bytes(byte_array[:size], "big") - del byte_array[:size] + value = int.from_bytes(bit_array.tobytes()[:size], "big") + del bit_array[:size] return value else: raise ValueError("Invalid exist flag") diff --git a/poetry.lock b/poetry.lock index a96b2720..50ac978e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,151 @@ # This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +[[package]] +name = "bitarray" +version = "3.0.0" +description = "efficient arrays of booleans -- C extension" +optional = false +python-versions = "*" +files = [ + {file = "bitarray-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5ddbf71a97ad1d6252e6e93d2d703b624d0a5b77c153b12f9ea87d83e1250e0c"}, + {file = "bitarray-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0e7f24a0b01e6e6a0191c50b06ca8edfdec1988d9d2b264d669d2487f4f4680"}, + {file = "bitarray-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:150b7b29c36d9f1a24779aea723fdfc73d1c1c161dc0ea14990da27d4e947092"}, + {file = "bitarray-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8330912be6cb8e2fbfe8eb69f82dee139d605730cadf8d50882103af9ac83bb4"}, + {file = "bitarray-3.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e56ba8be5f17dee0ffa6d6ce85251e062ded2faa3cbd2558659c671e6c3bf96d"}, + {file = "bitarray-3.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffd94b4803811c738e504a4b499fb2f848b2f7412d71e6b517508217c1d7929d"}, + {file = "bitarray-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0255bd05ec7165e512c115423a5255a3f301417973d20a80fc5bfc3f3640bcb"}, + {file = "bitarray-3.0.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe606e728842389943a939258809dc5db2de831b1d2e0118515059e87f7bbc1a"}, + {file = "bitarray-3.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e89ea59a3ed86a6eb150d016ed28b1bedf892802d0ed32b5659d3199440f3ced"}, + {file = "bitarray-3.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:cf0cc2e91dd38122dec2e6541efa99aafb0a62e118179218181eff720b4b8153"}, + {file = "bitarray-3.0.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:2d9fe3ee51afeb909b68f97e14c6539ace3f4faa99b21012e610bbe7315c388d"}, + {file = "bitarray-3.0.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:37be5482b9df3105bad00fdf7dc65244e449b130867c3879c9db1db7d72e508b"}, + {file = "bitarray-3.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0027b8f3bb2bba914c79115e96a59b9924aafa1a578223a7c4f0a7242d349842"}, + {file = "bitarray-3.0.0-cp310-cp310-win32.whl", hash = "sha256:628f93e9c2c23930bd1cfe21c634d6c84ec30f45f23e69aefe1fcd262186d7bb"}, + {file = "bitarray-3.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:0b655c3110e315219e266b2732609fddb0857bc69593de29f3c2ba74b7d3f51a"}, + {file = "bitarray-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:44c3e78b60070389b824d5a654afa1c893df723153c81904088d4922c3cfb6ac"}, + {file = "bitarray-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:545d36332de81e4742a845a80df89530ff193213a50b4cbef937ed5a44c0e5e5"}, + {file = "bitarray-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8a9eb510cde3fa78c2e302bece510bf5ed494ec40e6b082dec753d6e22d5d1b1"}, + {file = "bitarray-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e3727ab63dfb6bde00b281934e2212bb7529ea3006c0031a556a84d2268bea5"}, + {file = "bitarray-3.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2055206ed653bee0b56628f6a4d248d53e5660228d355bbec0014bdfa27050ae"}, + {file = "bitarray-3.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:147542299f458bdb177f798726e5f7d39ab8491de4182c3c6d9885ed275a3c2b"}, + {file = "bitarray-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f761184b93092077c7f6b7dad7bd4e671c1620404a76620da7872ceb576a94"}, + {file = "bitarray-3.0.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e008b7b4ce6c7f7a54b250c45c28d4243cc2a3bbfd5298fa7dac92afda229842"}, + {file = "bitarray-3.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dfea514e665af278b2e1d4deb542de1cd4f77413bee83dd15ae16175976ea8d5"}, + {file = "bitarray-3.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:66d6134b7bb737b88f1d16478ad0927c571387f6054f4afa5557825a4c1b78e2"}, + {file = "bitarray-3.0.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:3cd565253889940b4ec4768d24f101d9fe111cad4606fdb203ea16f9797cf9ed"}, + {file = "bitarray-3.0.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:4800c91a14656789d2e67d9513359e23e8a534c8ee1482bb9b517a4cfc845200"}, + {file = "bitarray-3.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c2945e0390d1329c585c584c6b6d78be017d9c6a1288f9c92006fe907f69cc28"}, + {file = "bitarray-3.0.0-cp311-cp311-win32.whl", hash = "sha256:c23286abba0cb509733c6ce8f4013cd951672c332b2e184dbefbd7331cd234c8"}, + {file = "bitarray-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:ca79f02a98cbda1472449d440592a2fe2ad96fe55515a0447fa8864a38017cf8"}, + {file = "bitarray-3.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:184972c96e1c7e691be60c3792ca1a51dd22b7f25d96ebea502fe3c9b554f25d"}, + {file = "bitarray-3.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:787db8da5e9e29be712f7a6bce153c7bc8697ccc2c38633e347bb9c82475d5c9"}, + {file = "bitarray-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2da91ab3633c66999c2a352f0ca9ae064f553e5fc0eca231d28e7e305b83e942"}, + {file = "bitarray-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7edb83089acbf2c86c8002b96599071931dc4ea5e1513e08306f6f7df879a48b"}, + {file = "bitarray-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996d1b83eb904589f40974538223eaed1ab0f62be8a5105c280b9bd849e685c4"}, + {file = "bitarray-3.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4817d73d995bd2b977d9cde6050be8d407791cf1f84c8047fa0bea88c1b815bc"}, + {file = "bitarray-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d47bc4ff9b0e1624d613563c6fa7b80aebe7863c56c3df5ab238bb7134e8755"}, + {file = "bitarray-3.0.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aca0a9cd376beaccd9f504961de83e776dd209c2de5a4c78dc87a78edf61839b"}, + {file = "bitarray-3.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:572a61fba7e3a710a8324771322fba8488d134034d349dcd036a7aef74723a80"}, + {file = "bitarray-3.0.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a817ad70c1aff217530576b4f037dd9b539eb2926603354fcac605d824082ad1"}, + {file = "bitarray-3.0.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:2ac67b658fa5426503e9581a3fb44a26a3b346c1abd17105735f07db572195b3"}, + {file = "bitarray-3.0.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:12f19ede03e685c5c588ab5ed63167999295ffab5e1126c5fe97d12c0718c18f"}, + {file = "bitarray-3.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fcef31b062f756ba7eebcd7890c5d5de84b9d64ee877325257bcc9782288564a"}, + {file = "bitarray-3.0.0-cp312-cp312-win32.whl", hash = "sha256:656db7bdf1d81ec3b57b3cad7ec7276765964bcfd0eb81c5d1331f385298169c"}, + {file = "bitarray-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f785af6b7cb07a9b1e5db0dea9ef9e3e8bb3d74874a0a61303eab9c16acc1999"}, + {file = "bitarray-3.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7cb885c043000924554fe2124d13084c8fdae03aec52c4086915cd4cb87fe8be"}, + {file = "bitarray-3.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7814c9924a0b30ecd401f02f082d8697fc5a5be3f8d407efa6e34531ff3c306a"}, + {file = "bitarray-3.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bcf524a087b143ba736aebbb054bb399d49e77cf7c04ed24c728e411adc82bfa"}, + {file = "bitarray-3.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1d5abf1d6d910599ac16afdd9a0ed3e24f3b46af57f3070cf2792f236f36e0b"}, + {file = "bitarray-3.0.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9929051feeaf8d948cc0b1c9ce57748079a941a1a15c89f6014edf18adaade84"}, + {file = "bitarray-3.0.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96cf0898f8060b2d3ae491762ae871b071212ded97ff9e1e3a5229e9fefe544c"}, + {file = "bitarray-3.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab37da66a8736ad5a75a58034180e92c41e864da0152b84e71fcc253a2f69cd4"}, + {file = "bitarray-3.0.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeb79e476d19b91fd6a3439853e4e5ba1b3b475920fa40d62bde719c8af786f"}, + {file = "bitarray-3.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f75fc0198c955d840b836059bd43e0993edbf119923029ca60c4fc017cefa54a"}, + {file = "bitarray-3.0.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f12cc7c7638074918cdcc7491aff897df921b092ffd877227892d2686e98f876"}, + {file = "bitarray-3.0.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dbe1084935b942fab206e609fa1ed3f46ad1f2612fb4833e177e9b2a5e006c96"}, + {file = "bitarray-3.0.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ac06dd72ee1e1b6e312504d06f75220b5894af1fb58f0c20643698f5122aea76"}, + {file = "bitarray-3.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:00f9a88c56e373009ac3c73c55205cfbd9683fbd247e2f9a64bae3da78795252"}, + {file = "bitarray-3.0.0-cp313-cp313-win32.whl", hash = "sha256:9c6e52005e91803eb4e08c0a08a481fb55ddce97f926bae1f6fa61b3396b5b61"}, + {file = "bitarray-3.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:cb98d5b6eac4b2cf2a5a69f60a9c499844b8bea207059e9fc45c752436e6bb49"}, + {file = "bitarray-3.0.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:eb27c01b747649afd7e1c342961680893df6d8d81f832a6f04d8c8e03a8a54cc"}, + {file = "bitarray-3.0.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4683bff52f5a0fd523fb5d3138161ef87611e63968e1fcb6cf4b0c6a86970fe0"}, + {file = "bitarray-3.0.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cb7302dbcfcb676f0b66f15891f091d0233c4fc23e1d4b9dc9b9e958156e347f"}, + {file = "bitarray-3.0.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:153d7c416a70951dcfa73487af05d2f49c632e95602f1620cd9a651fa2033695"}, + {file = "bitarray-3.0.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251cd5bd47f542893b2b61860eded54f34920ea47fd5bff038d85e7a2f7ae99b"}, + {file = "bitarray-3.0.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fa4b4d9fa90124b33b251ef74e44e737021f253dc7a9174e1b39f097451f7ca"}, + {file = "bitarray-3.0.0-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:18abdce7ab5d2104437c39670821cba0b32fdb9b2da9e6d17a4ff295362bd9dc"}, + {file = "bitarray-3.0.0-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:2855cc01ee370f7e6e3ec97eebe44b1453c83fb35080313145e2c8c3c5243afb"}, + {file = "bitarray-3.0.0-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:0cecaf2981c9cd2054547f651537b4f4939f9fe225d3fc2b77324b597c124e40"}, + {file = "bitarray-3.0.0-cp36-cp36m-musllinux_1_2_s390x.whl", hash = "sha256:22b00f65193fafb13aa644e16012c8b49e7d5cbb6bb72825105ff89aadaa01e3"}, + {file = "bitarray-3.0.0-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:20f30373f0af9cb583e4122348cefde93c82865dbcbccc4997108b3d575ece84"}, + {file = "bitarray-3.0.0-cp36-cp36m-win32.whl", hash = "sha256:aef404d5400d95c6ec86664df9924bde667c8865f8e33c9b7bd79823d53b3e5d"}, + {file = "bitarray-3.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:ec5b0f2d13da53e0975ac15ecbe8badb463bdb0bebaa09457f4df3320421915c"}, + {file = "bitarray-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:041c889e69c847b8a96346650e50f728b747ae176889199c49a3f31ae1de0e23"}, + {file = "bitarray-3.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc83ea003dd75e9ade3291ef0585577dd5524aec0c8c99305c0aaa2a7570d6db"}, + {file = "bitarray-3.0.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c33129b49196aa7965ac0f16fcde7b6ad8614b606caf01669a0277cef1afe1d"}, + {file = "bitarray-3.0.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ef5c787c8263c082a73219a69eb60a500e157a4ac69d1b8515ad836b0e71fb4"}, + {file = "bitarray-3.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e15c94d79810c5ab90ddf4d943f71f14332890417be896ca253f21fa3d78d2b1"}, + {file = "bitarray-3.0.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7cd021ada988e73d649289cee00428b75564c46d55fbdcb0e3402e504b0ae5ea"}, + {file = "bitarray-3.0.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7f1c24be7519f16a47b7e2ad1a1ef73023d34d8cbe1a3a59b185fc14baabb132"}, + {file = "bitarray-3.0.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:000df24c183011b5d27c23d79970f49b6762e5bb5aacd25da9c3e9695c693222"}, + {file = "bitarray-3.0.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:42bf1b222c698b467097f58b9f59dc850dfa694dde4e08237407a6a103757aa3"}, + {file = "bitarray-3.0.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:648e7ce794928e8d11343b5da8ecc5b910af75a82ea1a4264d5d0a55c3785faa"}, + {file = "bitarray-3.0.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:f536fc4d1a683025f9caef0bebeafd60384054579ffe0825bb9bd8c59f8c55b8"}, + {file = "bitarray-3.0.0-cp37-cp37m-win32.whl", hash = "sha256:a754c1464e7b946b1cac7300c582c6fba7d66e535cd1dab76d998ad285ac5a37"}, + {file = "bitarray-3.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e91d46d12781a14ccb8b284566b14933de4e3b29f8bc5e1c17de7a2001ad3b5b"}, + {file = "bitarray-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:904c1d5e3bd24f0c0d37a582d2461312033c91436a6a4f3bdeeceb4bea4a899d"}, + {file = "bitarray-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:47ccf9887bd595d4a0536f2310f0dcf89e17ab83b8befa7dc8727b8017120fda"}, + {file = "bitarray-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:71ad0139c95c9acf4fb62e203b428f9906157b15eecf3f30dc10b55919225896"}, + {file = "bitarray-3.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53e002ac1073ac70e323a7a4bfa9ab95e7e1a85c79160799e265563f342b1557"}, + {file = "bitarray-3.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:acc07211a59e2f245e9a06f28fa374d094fb0e71cf5366eef52abbb826ddc81e"}, + {file = "bitarray-3.0.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98a4070ddafabddaee70b2aa7cc6286cf73c37984169ab03af1782da2351059a"}, + {file = "bitarray-3.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7d09ef06ba57bea646144c29764bf6b870fb3c5558ca098191e07b6a1d40bf7"}, + {file = "bitarray-3.0.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce249ed981f428a8b61538ca82d3875847733d579dd40084ab8246549160f8a4"}, + {file = "bitarray-3.0.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea40e98d751ed4b255db4a88fe8fb743374183f78470b9e9305aab186bf28ede"}, + {file = "bitarray-3.0.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:928b8b6dfcd015e1a81334cfdac02815da2a2407854492a80cf8a3a922b04052"}, + {file = "bitarray-3.0.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:fbb645477595ce2a0fbb678d1cfd08d3b896e5d56196d40fb9e114eeab9382b3"}, + {file = "bitarray-3.0.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:dc1937a0ff2671797d35243db4b596329842480d125a65e9fe964bcffaf16dfc"}, + {file = "bitarray-3.0.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a4f49ac31734fe654a68e2515c0da7f5bbdf2d52755ba09a42ac406f1f08c9d0"}, + {file = "bitarray-3.0.0-cp38-cp38-win32.whl", hash = "sha256:6d2a2ce73f9897268f58857ad6893a1a6680c5a6b28f79d21c7d33285a5ae646"}, + {file = "bitarray-3.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:b1047999f1797c3ea7b7c85261649249c243308dcf3632840d076d18fa72f142"}, + {file = "bitarray-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:39b38a3d45dac39d528c87b700b81dfd5e8dc8e9e1a102503336310ef837c3fd"}, + {file = "bitarray-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0e104f9399144fab6a892d379ba1bb4275e56272eb465059beef52a77b4e5ce6"}, + {file = "bitarray-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0879f839ec8f079fa60c3255966c2e1aa7196699a234d4e5b7898fbc321901b5"}, + {file = "bitarray-3.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9502c2230d59a4ace2fddfd770dad8e8b414cbd99517e7e56c55c20997c28b8d"}, + {file = "bitarray-3.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57d5ef854f8ec434f2ffd9ddcefc25a10848393fe2976e2be2c8c773cf5fef42"}, + {file = "bitarray-3.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3c36b2fcfebe15ad1c10a90c1d52a42bebe960adcbce340fef867203028fbe7"}, + {file = "bitarray-3.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66a33a537e781eac3a352397ce6b07eedf3a8380ef4a804f8844f3f45e335544"}, + {file = "bitarray-3.0.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa54c7e1da8cf4be0aab941ea284ec64033ede5d6de3fd47d75e77cafe986e9d"}, + {file = "bitarray-3.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a667ea05ba1ea81b722682276dbef1d36990f8908cf51e570099fd505a89f931"}, + {file = "bitarray-3.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d756bfeb62ca4fe65d2af7a39249d442c05070c047d03729ad6cd4c2e9b0f0bd"}, + {file = "bitarray-3.0.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c9e9fef0754867d88e948ce8351c9fd7e507d8514e0f242fd67c907b9cdf98b3"}, + {file = "bitarray-3.0.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:67a0b56dd02f2713f6f52cacb3f251afd67c94c5f0748026d307d87a81a8e15c"}, + {file = "bitarray-3.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d8c36ddc1923bcc4c11b9994c54eaae25034812a42400b7b8a86fe6d242166a2"}, + {file = "bitarray-3.0.0-cp39-cp39-win32.whl", hash = "sha256:1414a7102a3c4986f241480544f5c99f5d32258fb9b85c9c04e84e48c490ab35"}, + {file = "bitarray-3.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:8c9733d2ff9b7838ac04bf1048baea153174753e6a47312be14c83c6a395424b"}, + {file = "bitarray-3.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fef4e3b3f2084b4dae3e5316b44cda72587dcc81f68b4eb2dbda1b8d15261b61"}, + {file = "bitarray-3.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e9eee03f187cef1e54a4545124109ee0afc84398628b4b32ebb4852b4a66393"}, + {file = "bitarray-3.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cb5702dd667f4bb10fed056ffdc4ddaae8193a52cd74cb2cdb54e71f4ef2dd1"}, + {file = "bitarray-3.0.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:666e44b0458bb2894b64264a29f2cc7b5b2cbcc4c5e9cedfe1fdbde37a8e329a"}, + {file = "bitarray-3.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c756a92cf1c1abf01e56a4cc40cb89f0ff9147f2a0be5b557ec436a23ff464d8"}, + {file = "bitarray-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7e51e7f8289bf6bb631e1ef2a8f5e9ca287985ff518fe666abbdfdb6a848cb26"}, + {file = "bitarray-3.0.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fa5d8e4b28388b337face6ce4029be73585651a44866901513df44be9a491ab"}, + {file = "bitarray-3.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3963b80a68aedcd722a9978d261ae53cb9bb6a8129cc29790f0f10ce5aca287a"}, + {file = "bitarray-3.0.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b555006a7dea53f6bebc616a4d0249cecbf8f1fadf77860120a2e5dbdc2f167"}, + {file = "bitarray-3.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:4ac2027ca650a7302864ed2528220d6cc6921501b383e9917afc7a2424a1e36d"}, + {file = "bitarray-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bf90aba4cff9e72e24ecdefe33bad608f147a23fa5c97790a5bab0e72fe62b6d"}, + {file = "bitarray-3.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1a199e6d7c3bad5ba9d0e4dc00dde70ee7d111c9dfc521247fa646ef59fa57e"}, + {file = "bitarray-3.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43b6c7c4f4a7b80e86e24a76f4c6b9b67d03229ea16d7d403520616535c32196"}, + {file = "bitarray-3.0.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34fc13da3518f14825b239374734fce93c1a9299ed7b558c3ec1d659ec7e4c70"}, + {file = "bitarray-3.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:369b6d457af94af901d632c7e625ca6caf0a7484110fc91c6290ce26bc4f1478"}, + {file = "bitarray-3.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ee040ad3b7dfa05e459713099f16373c1f2a6f68b43cb0575a66718e7a5daef4"}, + {file = "bitarray-3.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dad7ba2af80f9ec1dd988c3aca7992408ec0d0b4c215b65d353d95ab0070b10"}, + {file = "bitarray-3.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4839d3b64af51e4b8bb4a602563b98b9faeb34fd6c00ed23d7834e40a9d080fc"}, + {file = "bitarray-3.0.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f71f24b58e75a889b9915e3197865302467f13e7390efdea5b6afc7424b3a2ea"}, + {file = "bitarray-3.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:bcf0150ae0bcc4aa97bdfcb231b37bad1a59083c1b5012643b266012bf420e68"}, + {file = "bitarray-3.0.0.tar.gz", hash = "sha256:a2083dc20f0d828a7cdf7a16b20dae56aab0f43dc4f347a3b3039f6577992b03"}, +] + [[package]] name = "colorama" version = "0.4.6" @@ -46,43 +192,43 @@ files = [ [[package]] name = "mypy" -version = "1.13.0" +version = "1.12.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"}, - {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"}, - {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"}, - {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"}, - {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"}, - {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"}, - {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"}, - {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"}, - {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"}, - {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"}, - {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"}, - {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"}, - {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"}, - {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"}, - {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"}, - {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"}, - {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"}, - {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"}, - {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"}, - {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"}, - {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"}, - {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"}, - {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"}, - {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"}, - {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"}, - {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"}, - {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"}, - {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"}, - {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"}, - {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"}, - {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"}, - {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"}, + {file = "mypy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4397081e620dc4dc18e2f124d5e1d2c288194c2c08df6bdb1db31c38cd1fe1ed"}, + {file = "mypy-1.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:684a9c508a283f324804fea3f0effeb7858eb03f85c4402a967d187f64562469"}, + {file = "mypy-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cabe4cda2fa5eca7ac94854c6c37039324baaa428ecbf4de4567279e9810f9e"}, + {file = "mypy-1.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:060a07b10e999ac9e7fa249ce2bdcfa9183ca2b70756f3bce9df7a92f78a3c0a"}, + {file = "mypy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:0eff042d7257f39ba4ca06641d110ca7d2ad98c9c1fb52200fe6b1c865d360ff"}, + {file = "mypy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b86de37a0da945f6d48cf110d5206c5ed514b1ca2614d7ad652d4bf099c7de7"}, + {file = "mypy-1.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:20c7c5ce0c1be0b0aea628374e6cf68b420bcc772d85c3c974f675b88e3e6e57"}, + {file = "mypy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a64ee25f05fc2d3d8474985c58042b6759100a475f8237da1f4faf7fcd7e6309"}, + {file = "mypy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:faca7ab947c9f457a08dcb8d9a8664fd438080e002b0fa3e41b0535335edcf7f"}, + {file = "mypy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:5bc81701d52cc8767005fdd2a08c19980de9ec61a25dbd2a937dfb1338a826f9"}, + {file = "mypy-1.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8462655b6694feb1c99e433ea905d46c478041a8b8f0c33f1dab00ae881b2164"}, + {file = "mypy-1.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:923ea66d282d8af9e0f9c21ffc6653643abb95b658c3a8a32dca1eff09c06475"}, + {file = "mypy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ebf9e796521f99d61864ed89d1fb2926d9ab6a5fab421e457cd9c7e4dd65aa9"}, + {file = "mypy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e478601cc3e3fa9d6734d255a59c7a2e5c2934da4378f3dd1e3411ea8a248642"}, + {file = "mypy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:c72861b7139a4f738344faa0e150834467521a3fba42dc98264e5aa9507dd601"}, + {file = "mypy-1.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52b9e1492e47e1790360a43755fa04101a7ac72287b1a53ce817f35899ba0521"}, + {file = "mypy-1.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:48d3e37dd7d9403e38fa86c46191de72705166d40b8c9f91a3de77350daa0893"}, + {file = "mypy-1.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2f106db5ccb60681b622ac768455743ee0e6a857724d648c9629a9bd2ac3f721"}, + {file = "mypy-1.12.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:233e11b3f73ee1f10efada2e6da0f555b2f3a5316e9d8a4a1224acc10e7181d3"}, + {file = "mypy-1.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:4ae8959c21abcf9d73aa6c74a313c45c0b5a188752bf37dace564e29f06e9c1b"}, + {file = "mypy-1.12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eafc1b7319b40ddabdc3db8d7d48e76cfc65bbeeafaa525a4e0fa6b76175467f"}, + {file = "mypy-1.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9b9ce1ad8daeb049c0b55fdb753d7414260bad8952645367e70ac91aec90e07e"}, + {file = "mypy-1.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfe012b50e1491d439172c43ccb50db66d23fab714d500b57ed52526a1020bb7"}, + {file = "mypy-1.12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2c40658d4fa1ab27cb53d9e2f1066345596af2f8fe4827defc398a09c7c9519b"}, + {file = "mypy-1.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:dee78a8b9746c30c1e617ccb1307b351ded57f0de0d287ca6276378d770006c0"}, + {file = "mypy-1.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b5df6c8a8224f6b86746bda716bbe4dbe0ce89fd67b1fa4661e11bfe38e8ec8"}, + {file = "mypy-1.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5feee5c74eb9749e91b77f60b30771563327329e29218d95bedbe1257e2fe4b0"}, + {file = "mypy-1.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:77278e8c6ffe2abfba6db4125de55f1024de9a323be13d20e4f73b8ed3402bd1"}, + {file = "mypy-1.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:dcfb754dea911039ac12434d1950d69a2f05acd4d56f7935ed402be09fad145e"}, + {file = "mypy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:06de0498798527451ffb60f68db0d368bd2bae2bbfb5237eae616d4330cc87aa"}, + {file = "mypy-1.12.0-py3-none-any.whl", hash = "sha256:fd313226af375d52e1e36c383f39bf3836e1f192801116b31b090dfcd3ec5266"}, + {file = "mypy-1.12.0.tar.gz", hash = "sha256:65a22d87e757ccd95cbbf6f7e181e6caa87128255eb2b6be901bb71b26d8a99d"}, ] [package.dependencies] @@ -197,22 +343,22 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "protobuf" -version = "5.28.3" +version = "5.28.2" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "protobuf-5.28.3-cp310-abi3-win32.whl", hash = "sha256:0c4eec6f987338617072592b97943fdbe30d019c56126493111cf24344c1cc24"}, - {file = "protobuf-5.28.3-cp310-abi3-win_amd64.whl", hash = "sha256:91fba8f445723fcf400fdbe9ca796b19d3b1242cd873907979b9ed71e4afe868"}, - {file = "protobuf-5.28.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a3f6857551e53ce35e60b403b8a27b0295f7d6eb63d10484f12bc6879c715687"}, - {file = "protobuf-5.28.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:3fa2de6b8b29d12c61911505d893afe7320ce7ccba4df913e2971461fa36d584"}, - {file = "protobuf-5.28.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:712319fbdddb46f21abb66cd33cb9e491a5763b2febd8f228251add221981135"}, - {file = "protobuf-5.28.3-cp38-cp38-win32.whl", hash = "sha256:3e6101d095dfd119513cde7259aa703d16c6bbdfae2554dfe5cfdbe94e32d548"}, - {file = "protobuf-5.28.3-cp38-cp38-win_amd64.whl", hash = "sha256:27b246b3723692bf1068d5734ddaf2fccc2cdd6e0c9b47fe099244d80200593b"}, - {file = "protobuf-5.28.3-cp39-cp39-win32.whl", hash = "sha256:135658402f71bbd49500322c0f736145731b16fc79dc8f367ab544a17eab4535"}, - {file = "protobuf-5.28.3-cp39-cp39-win_amd64.whl", hash = "sha256:70585a70fc2dd4818c51287ceef5bdba6387f88a578c86d47bb34669b5552c36"}, - {file = "protobuf-5.28.3-py3-none-any.whl", hash = "sha256:cee1757663fa32a1ee673434fcf3bf24dd54763c79690201208bafec62f19eed"}, - {file = "protobuf-5.28.3.tar.gz", hash = "sha256:64badbc49180a5e401f373f9ce7ab1d18b63f7dd4a9cdc43c92b9f0b481cef7b"}, + {file = "protobuf-5.28.2-cp310-abi3-win32.whl", hash = "sha256:eeea10f3dc0ac7e6b4933d32db20662902b4ab81bf28df12218aa389e9c2102d"}, + {file = "protobuf-5.28.2-cp310-abi3-win_amd64.whl", hash = "sha256:2c69461a7fcc8e24be697624c09a839976d82ae75062b11a0972e41fd2cd9132"}, + {file = "protobuf-5.28.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a8b9403fc70764b08d2f593ce44f1d2920c5077bf7d311fefec999f8c40f78b7"}, + {file = "protobuf-5.28.2-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:35cfcb15f213449af7ff6198d6eb5f739c37d7e4f1c09b5d0641babf2cc0c68f"}, + {file = "protobuf-5.28.2-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:5e8a95246d581eef20471b5d5ba010d55f66740942b95ba9b872d918c459452f"}, + {file = "protobuf-5.28.2-cp38-cp38-win32.whl", hash = "sha256:87317e9bcda04a32f2ee82089a204d3a2f0d3c8aeed16568c7daf4756e4f1fe0"}, + {file = "protobuf-5.28.2-cp38-cp38-win_amd64.whl", hash = "sha256:c0ea0123dac3399a2eeb1a1443d82b7afc9ff40241433296769f7da42d142ec3"}, + {file = "protobuf-5.28.2-cp39-cp39-win32.whl", hash = "sha256:ca53faf29896c526863366a52a8f4d88e69cd04ec9571ed6082fa117fac3ab36"}, + {file = "protobuf-5.28.2-cp39-cp39-win_amd64.whl", hash = "sha256:8ddc60bf374785fb7cb12510b267f59067fa10087325b8e1855b898a0d81d276"}, + {file = "protobuf-5.28.2-py3-none-any.whl", hash = "sha256:52235802093bd8a2811abbe8bf0ab9c5f54cca0a751fdd3f6ac2a21438bffece"}, + {file = "protobuf-5.28.2.tar.gz", hash = "sha256:59379674ff119717404f7454647913787034f03fe7049cbef1d74a97bb4593f0"}, ] [[package]] @@ -342,7 +488,7 @@ rtree = "*" type = "git" url = "https://github.com/adf-python/rcrs-core-python" reference = "HEAD" -resolved_reference = "b353cd6e82005e20e099554d4f357d9c0cc2e052" +resolved_reference = "e6d1c51c7a03122f8c2f98e88272775ee77363ce" [[package]] name = "rtree" @@ -634,4 +780,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "f5041edb49c80e926991fbd658e04175d3c35e3e95fb90bf8762d244de7498f3" +content-hash = "6fdb27af56e45fff1fa8898664fb70a3df4a4258237612e8fc3d795d4c2dc45d" diff --git a/pyproject.toml b/pyproject.toml index b768e40b..d41e1935 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ pytest = "^8.3.2" types-pyyaml = "^6.0.12.20240808" scikit-learn = "^1.5.2" structlog = "^24.4.0" -shapely = "^2.0.6" +bitarray = "^3.0.0" [tool.poetry.group.dev.dependencies] From 2b19002b0035e9c7e528645c4e445e08010735a3 Mon Sep 17 00:00:00 2001 From: shima004 Date: Sat, 26 Oct 2024 12:16:05 +0900 Subject: [PATCH 4/8] update: package version --- poetry.lock | 156 +++++++++++++++++----------------------------------- 1 file changed, 49 insertions(+), 107 deletions(-) diff --git a/poetry.lock b/poetry.lock index 50ac978e..c0b7ea81 100644 --- a/poetry.lock +++ b/poetry.lock @@ -192,43 +192,43 @@ files = [ [[package]] name = "mypy" -version = "1.12.0" +version = "1.13.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4397081e620dc4dc18e2f124d5e1d2c288194c2c08df6bdb1db31c38cd1fe1ed"}, - {file = "mypy-1.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:684a9c508a283f324804fea3f0effeb7858eb03f85c4402a967d187f64562469"}, - {file = "mypy-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cabe4cda2fa5eca7ac94854c6c37039324baaa428ecbf4de4567279e9810f9e"}, - {file = "mypy-1.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:060a07b10e999ac9e7fa249ce2bdcfa9183ca2b70756f3bce9df7a92f78a3c0a"}, - {file = "mypy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:0eff042d7257f39ba4ca06641d110ca7d2ad98c9c1fb52200fe6b1c865d360ff"}, - {file = "mypy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b86de37a0da945f6d48cf110d5206c5ed514b1ca2614d7ad652d4bf099c7de7"}, - {file = "mypy-1.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:20c7c5ce0c1be0b0aea628374e6cf68b420bcc772d85c3c974f675b88e3e6e57"}, - {file = "mypy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a64ee25f05fc2d3d8474985c58042b6759100a475f8237da1f4faf7fcd7e6309"}, - {file = "mypy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:faca7ab947c9f457a08dcb8d9a8664fd438080e002b0fa3e41b0535335edcf7f"}, - {file = "mypy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:5bc81701d52cc8767005fdd2a08c19980de9ec61a25dbd2a937dfb1338a826f9"}, - {file = "mypy-1.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8462655b6694feb1c99e433ea905d46c478041a8b8f0c33f1dab00ae881b2164"}, - {file = "mypy-1.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:923ea66d282d8af9e0f9c21ffc6653643abb95b658c3a8a32dca1eff09c06475"}, - {file = "mypy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ebf9e796521f99d61864ed89d1fb2926d9ab6a5fab421e457cd9c7e4dd65aa9"}, - {file = "mypy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e478601cc3e3fa9d6734d255a59c7a2e5c2934da4378f3dd1e3411ea8a248642"}, - {file = "mypy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:c72861b7139a4f738344faa0e150834467521a3fba42dc98264e5aa9507dd601"}, - {file = "mypy-1.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52b9e1492e47e1790360a43755fa04101a7ac72287b1a53ce817f35899ba0521"}, - {file = "mypy-1.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:48d3e37dd7d9403e38fa86c46191de72705166d40b8c9f91a3de77350daa0893"}, - {file = "mypy-1.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2f106db5ccb60681b622ac768455743ee0e6a857724d648c9629a9bd2ac3f721"}, - {file = "mypy-1.12.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:233e11b3f73ee1f10efada2e6da0f555b2f3a5316e9d8a4a1224acc10e7181d3"}, - {file = "mypy-1.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:4ae8959c21abcf9d73aa6c74a313c45c0b5a188752bf37dace564e29f06e9c1b"}, - {file = "mypy-1.12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eafc1b7319b40ddabdc3db8d7d48e76cfc65bbeeafaa525a4e0fa6b76175467f"}, - {file = "mypy-1.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9b9ce1ad8daeb049c0b55fdb753d7414260bad8952645367e70ac91aec90e07e"}, - {file = "mypy-1.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfe012b50e1491d439172c43ccb50db66d23fab714d500b57ed52526a1020bb7"}, - {file = "mypy-1.12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2c40658d4fa1ab27cb53d9e2f1066345596af2f8fe4827defc398a09c7c9519b"}, - {file = "mypy-1.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:dee78a8b9746c30c1e617ccb1307b351ded57f0de0d287ca6276378d770006c0"}, - {file = "mypy-1.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b5df6c8a8224f6b86746bda716bbe4dbe0ce89fd67b1fa4661e11bfe38e8ec8"}, - {file = "mypy-1.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5feee5c74eb9749e91b77f60b30771563327329e29218d95bedbe1257e2fe4b0"}, - {file = "mypy-1.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:77278e8c6ffe2abfba6db4125de55f1024de9a323be13d20e4f73b8ed3402bd1"}, - {file = "mypy-1.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:dcfb754dea911039ac12434d1950d69a2f05acd4d56f7935ed402be09fad145e"}, - {file = "mypy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:06de0498798527451ffb60f68db0d368bd2bae2bbfb5237eae616d4330cc87aa"}, - {file = "mypy-1.12.0-py3-none-any.whl", hash = "sha256:fd313226af375d52e1e36c383f39bf3836e1f192801116b31b090dfcd3ec5266"}, - {file = "mypy-1.12.0.tar.gz", hash = "sha256:65a22d87e757ccd95cbbf6f7e181e6caa87128255eb2b6be901bb71b26d8a99d"}, + {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"}, + {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"}, + {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"}, + {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"}, + {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"}, + {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"}, + {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"}, + {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"}, + {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"}, + {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"}, + {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"}, + {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"}, + {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"}, + {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"}, + {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"}, + {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"}, + {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"}, + {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"}, + {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"}, + {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"}, + {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"}, + {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"}, ] [package.dependencies] @@ -343,22 +343,22 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "protobuf" -version = "5.28.2" +version = "5.28.3" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "protobuf-5.28.2-cp310-abi3-win32.whl", hash = "sha256:eeea10f3dc0ac7e6b4933d32db20662902b4ab81bf28df12218aa389e9c2102d"}, - {file = "protobuf-5.28.2-cp310-abi3-win_amd64.whl", hash = "sha256:2c69461a7fcc8e24be697624c09a839976d82ae75062b11a0972e41fd2cd9132"}, - {file = "protobuf-5.28.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a8b9403fc70764b08d2f593ce44f1d2920c5077bf7d311fefec999f8c40f78b7"}, - {file = "protobuf-5.28.2-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:35cfcb15f213449af7ff6198d6eb5f739c37d7e4f1c09b5d0641babf2cc0c68f"}, - {file = "protobuf-5.28.2-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:5e8a95246d581eef20471b5d5ba010d55f66740942b95ba9b872d918c459452f"}, - {file = "protobuf-5.28.2-cp38-cp38-win32.whl", hash = "sha256:87317e9bcda04a32f2ee82089a204d3a2f0d3c8aeed16568c7daf4756e4f1fe0"}, - {file = "protobuf-5.28.2-cp38-cp38-win_amd64.whl", hash = "sha256:c0ea0123dac3399a2eeb1a1443d82b7afc9ff40241433296769f7da42d142ec3"}, - {file = "protobuf-5.28.2-cp39-cp39-win32.whl", hash = "sha256:ca53faf29896c526863366a52a8f4d88e69cd04ec9571ed6082fa117fac3ab36"}, - {file = "protobuf-5.28.2-cp39-cp39-win_amd64.whl", hash = "sha256:8ddc60bf374785fb7cb12510b267f59067fa10087325b8e1855b898a0d81d276"}, - {file = "protobuf-5.28.2-py3-none-any.whl", hash = "sha256:52235802093bd8a2811abbe8bf0ab9c5f54cca0a751fdd3f6ac2a21438bffece"}, - {file = "protobuf-5.28.2.tar.gz", hash = "sha256:59379674ff119717404f7454647913787034f03fe7049cbef1d74a97bb4593f0"}, + {file = "protobuf-5.28.3-cp310-abi3-win32.whl", hash = "sha256:0c4eec6f987338617072592b97943fdbe30d019c56126493111cf24344c1cc24"}, + {file = "protobuf-5.28.3-cp310-abi3-win_amd64.whl", hash = "sha256:91fba8f445723fcf400fdbe9ca796b19d3b1242cd873907979b9ed71e4afe868"}, + {file = "protobuf-5.28.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a3f6857551e53ce35e60b403b8a27b0295f7d6eb63d10484f12bc6879c715687"}, + {file = "protobuf-5.28.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:3fa2de6b8b29d12c61911505d893afe7320ce7ccba4df913e2971461fa36d584"}, + {file = "protobuf-5.28.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:712319fbdddb46f21abb66cd33cb9e491a5763b2febd8f228251add221981135"}, + {file = "protobuf-5.28.3-cp38-cp38-win32.whl", hash = "sha256:3e6101d095dfd119513cde7259aa703d16c6bbdfae2554dfe5cfdbe94e32d548"}, + {file = "protobuf-5.28.3-cp38-cp38-win_amd64.whl", hash = "sha256:27b246b3723692bf1068d5734ddaf2fccc2cdd6e0c9b47fe099244d80200593b"}, + {file = "protobuf-5.28.3-cp39-cp39-win32.whl", hash = "sha256:135658402f71bbd49500322c0f736145731b16fc79dc8f367ab544a17eab4535"}, + {file = "protobuf-5.28.3-cp39-cp39-win_amd64.whl", hash = "sha256:70585a70fc2dd4818c51287ceef5bdba6387f88a578c86d47bb34669b5552c36"}, + {file = "protobuf-5.28.3-py3-none-any.whl", hash = "sha256:cee1757663fa32a1ee673434fcf3bf24dd54763c79690201208bafec62f19eed"}, + {file = "protobuf-5.28.3.tar.gz", hash = "sha256:64badbc49180a5e401f373f9ce7ab1d18b63f7dd4a9cdc43c92b9f0b481cef7b"}, ] [[package]] @@ -488,7 +488,7 @@ rtree = "*" type = "git" url = "https://github.com/adf-python/rcrs-core-python" reference = "HEAD" -resolved_reference = "e6d1c51c7a03122f8c2f98e88272775ee77363ce" +resolved_reference = "b353cd6e82005e20e099554d4f357d9c0cc2e052" [[package]] name = "rtree" @@ -630,64 +630,6 @@ dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodest doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.13.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<=7.3.7)", "sphinx-design (>=0.4.0)"] test = ["Cython", "array-api-strict (>=2.0)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] -[[package]] -name = "shapely" -version = "2.0.6" -description = "Manipulation and analysis of geometric objects" -optional = false -python-versions = ">=3.7" -files = [ - {file = "shapely-2.0.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29a34e068da2d321e926b5073539fd2a1d4429a2c656bd63f0bd4c8f5b236d0b"}, - {file = "shapely-2.0.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c84c3f53144febf6af909d6b581bc05e8785d57e27f35ebaa5c1ab9baba13b"}, - {file = "shapely-2.0.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ad2fae12dca8d2b727fa12b007e46fbc522148a584f5d6546c539f3464dccde"}, - {file = "shapely-2.0.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3304883bd82d44be1b27a9d17f1167fda8c7f5a02a897958d86c59ec69b705e"}, - {file = "shapely-2.0.6-cp310-cp310-win32.whl", hash = "sha256:3ec3a0eab496b5e04633a39fa3d5eb5454628228201fb24903d38174ee34565e"}, - {file = "shapely-2.0.6-cp310-cp310-win_amd64.whl", hash = "sha256:28f87cdf5308a514763a5c38de295544cb27429cfa655d50ed8431a4796090c4"}, - {file = "shapely-2.0.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5aeb0f51a9db176da9a30cb2f4329b6fbd1e26d359012bb0ac3d3c7781667a9e"}, - {file = "shapely-2.0.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a7a78b0d51257a367ee115f4d41ca4d46edbd0dd280f697a8092dd3989867b2"}, - {file = "shapely-2.0.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f32c23d2f43d54029f986479f7c1f6e09c6b3a19353a3833c2ffb226fb63a855"}, - {file = "shapely-2.0.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3dc9fb0eb56498912025f5eb352b5126f04801ed0e8bdbd867d21bdbfd7cbd0"}, - {file = "shapely-2.0.6-cp311-cp311-win32.whl", hash = "sha256:d93b7e0e71c9f095e09454bf18dad5ea716fb6ced5df3cb044564a00723f339d"}, - {file = "shapely-2.0.6-cp311-cp311-win_amd64.whl", hash = "sha256:c02eb6bf4cfb9fe6568502e85bb2647921ee49171bcd2d4116c7b3109724ef9b"}, - {file = "shapely-2.0.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cec9193519940e9d1b86a3b4f5af9eb6910197d24af02f247afbfb47bcb3fab0"}, - {file = "shapely-2.0.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83b94a44ab04a90e88be69e7ddcc6f332da7c0a0ebb1156e1c4f568bbec983c3"}, - {file = "shapely-2.0.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:537c4b2716d22c92036d00b34aac9d3775e3691f80c7aa517c2c290351f42cd8"}, - {file = "shapely-2.0.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98fea108334be345c283ce74bf064fa00cfdd718048a8af7343c59eb40f59726"}, - {file = "shapely-2.0.6-cp312-cp312-win32.whl", hash = "sha256:42fd4cd4834747e4990227e4cbafb02242c0cffe9ce7ef9971f53ac52d80d55f"}, - {file = "shapely-2.0.6-cp312-cp312-win_amd64.whl", hash = "sha256:665990c84aece05efb68a21b3523a6b2057e84a1afbef426ad287f0796ef8a48"}, - {file = "shapely-2.0.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:42805ef90783ce689a4dde2b6b2f261e2c52609226a0438d882e3ced40bb3013"}, - {file = "shapely-2.0.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6d2cb146191a47bd0cee8ff5f90b47547b82b6345c0d02dd8b25b88b68af62d7"}, - {file = "shapely-2.0.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3fdef0a1794a8fe70dc1f514440aa34426cc0ae98d9a1027fb299d45741c381"}, - {file = "shapely-2.0.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c665a0301c645615a107ff7f52adafa2153beab51daf34587170d85e8ba6805"}, - {file = "shapely-2.0.6-cp313-cp313-win32.whl", hash = "sha256:0334bd51828f68cd54b87d80b3e7cee93f249d82ae55a0faf3ea21c9be7b323a"}, - {file = "shapely-2.0.6-cp313-cp313-win_amd64.whl", hash = "sha256:d37d070da9e0e0f0a530a621e17c0b8c3c9d04105655132a87cfff8bd77cc4c2"}, - {file = "shapely-2.0.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fa7468e4f5b92049c0f36d63c3e309f85f2775752e076378e36c6387245c5462"}, - {file = "shapely-2.0.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed5867e598a9e8ac3291da6cc9baa62ca25706eea186117034e8ec0ea4355653"}, - {file = "shapely-2.0.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81d9dfe155f371f78c8d895a7b7f323bb241fb148d848a2bf2244f79213123fe"}, - {file = "shapely-2.0.6-cp37-cp37m-win32.whl", hash = "sha256:fbb7bf02a7542dba55129062570211cfb0defa05386409b3e306c39612e7fbcc"}, - {file = "shapely-2.0.6-cp37-cp37m-win_amd64.whl", hash = "sha256:837d395fac58aa01aa544495b97940995211e3e25f9aaf87bc3ba5b3a8cd1ac7"}, - {file = "shapely-2.0.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c6d88ade96bf02f6bfd667ddd3626913098e243e419a0325ebef2bbd481d1eb6"}, - {file = "shapely-2.0.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8b3b818c4407eaa0b4cb376fd2305e20ff6df757bf1356651589eadc14aab41b"}, - {file = "shapely-2.0.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bbc783529a21f2bd50c79cef90761f72d41c45622b3e57acf78d984c50a5d13"}, - {file = "shapely-2.0.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2423f6c0903ebe5df6d32e0066b3d94029aab18425ad4b07bf98c3972a6e25a1"}, - {file = "shapely-2.0.6-cp38-cp38-win32.whl", hash = "sha256:2de00c3bfa80d6750832bde1d9487e302a6dd21d90cb2f210515cefdb616e5f5"}, - {file = "shapely-2.0.6-cp38-cp38-win_amd64.whl", hash = "sha256:3a82d58a1134d5e975f19268710e53bddd9c473743356c90d97ce04b73e101ee"}, - {file = "shapely-2.0.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:392f66f458a0a2c706254f473290418236e52aa4c9b476a072539d63a2460595"}, - {file = "shapely-2.0.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eba5bae271d523c938274c61658ebc34de6c4b33fdf43ef7e938b5776388c1be"}, - {file = "shapely-2.0.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7060566bc4888b0c8ed14b5d57df8a0ead5c28f9b69fb6bed4476df31c51b0af"}, - {file = "shapely-2.0.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b02154b3e9d076a29a8513dffcb80f047a5ea63c897c0cd3d3679f29363cf7e5"}, - {file = "shapely-2.0.6-cp39-cp39-win32.whl", hash = "sha256:44246d30124a4f1a638a7d5419149959532b99dfa25b54393512e6acc9c211ac"}, - {file = "shapely-2.0.6-cp39-cp39-win_amd64.whl", hash = "sha256:2b542d7f1dbb89192d3512c52b679c822ba916f93479fa5d4fc2fe4fa0b3c9e8"}, - {file = "shapely-2.0.6.tar.gz", hash = "sha256:997f6159b1484059ec239cacaa53467fd8b5564dabe186cd84ac2944663b0bf6"}, -] - -[package.dependencies] -numpy = ">=1.14,<3" - -[package.extras] -docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] -test = ["pytest", "pytest-cov"] - [[package]] name = "structlog" version = "24.4.0" @@ -707,13 +649,13 @@ typing = ["mypy (>=1.4)", "rich", "twisted"] [[package]] name = "taskipy" -version = "1.13.0" +version = "1.14.0" description = "tasks runner for python projects" optional = false python-versions = "<4.0,>=3.6" files = [ - {file = "taskipy-1.13.0-py3-none-any.whl", hash = "sha256:56f42b7e508d9aed2c7b6365f8d3dab62dbd0c768c1ab606c819da4fc38421f7"}, - {file = "taskipy-1.13.0.tar.gz", hash = "sha256:2b52f0257958fed151f1340f7de93fcf0848f7a358ad62ba05c31c2ca04f89fe"}, + {file = "taskipy-1.14.0-py3-none-any.whl", hash = "sha256:29040d9a8038170602feb71792bdef5203720ed30f595304aee843625892452b"}, + {file = "taskipy-1.14.0.tar.gz", hash = "sha256:5d9631c29980481d59858f0a100ed3200cf7468ca8c0540ef19388586485532d"}, ] [package.dependencies] From 56a70d59a5a8b48efc10ff2af4eef2af3ddc59f8 Mon Sep 17 00:00:00 2001 From: shima004 Date: Wed, 30 Oct 2024 02:19:02 +0900 Subject: [PATCH 5/8] feat: standard messages WIP WIP WIP WIP WIP WIP WIP WIP WIP feat: standard messages --- adf_core_python/core/agent/agent.py | 289 ++++++++++++--- adf_core_python/core/agent/command_factory.py | 44 +++ .../agent/communication/message_manager.py | 134 ++++++- .../agent/communication/standard/__init__.py | 0 .../communication/standard/bundle/__init__.py | 0 .../standard/bundle/centralized/__init__.py | 0 .../bundle/centralized/command_ambulance.py | 135 +++++++ .../bundle/centralized/command_fire.py | 136 +++++++ .../bundle/centralized/command_police.py | 134 +++++++ .../bundle/centralized/command_scout.py | 129 +++++++ .../bundle/centralized/message_report.py | 88 +++++ .../standard/bundle/information/__init__.py | 0 .../message_ambulance_team.py | 162 +++++---- .../message_building.py | 96 ++--- .../message_civilian.py | 107 +++--- .../message_fire_brigade.py | 159 +++++---- .../message_police_force.py | 150 ++++---- .../message_road.py | 138 ++++---- .../standard/bundle/standard_message.py | 71 ++-- .../bundle/standard_message_priority.py | 8 + .../standard/standard_communication_module.py | 168 ++++++++- .../standard/utility/__init__.py | 0 .../standard/utility/apply_to_world_info.py | 335 ++++++++++++++++++ .../utility/bitarray_with_exits_flag.py | 72 ++++ adf_core_python/core/agent/info/agent_info.py | 19 +- .../core/agent/info/scenario_info.py | 21 +- adf_core_python/core/agent/info/world_info.py | 11 + .../core/agent/module/module_manager.py | 58 +++ adf_core_python/core/agent/platoon/platoon.py | 85 ++--- .../core/component/communication/__init__.py | 0 .../communication/channel_subscriber.py | 21 +- .../communication/communication_message.py | 12 +- .../communication/communication_module.py | 9 +- .../communication/message_coordinator.py | 18 +- .../launcher/connect/component_launcher.py | 15 +- .../connect/connector_ambulance_centre.py | 4 +- .../connect/connector_ambulance_team.py | 4 +- .../connect/connector_fire_brigade.py | 4 +- .../connect/connector_fire_station.py | 5 +- .../connect/connector_police_force.py | 4 +- .../connect/connector_police_office.py | 6 +- .../default_channel_subscriber.py | 101 ++++++ .../default_message_coordinator.py | 222 ++++++++++++ .../tactics/default_tactics_ambulance_team.py | 73 ++++ config/launcher.yaml | 6 +- config/module.yaml | 11 +- poetry.lock | 178 +++++++--- pyproject.toml | 1 + pyrightconfig.json | 2 +- 49 files changed, 2820 insertions(+), 625 deletions(-) create mode 100644 adf_core_python/core/agent/command_factory.py create mode 100644 adf_core_python/core/agent/communication/standard/__init__.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/__init__.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/centralized/__init__.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/centralized/command_ambulance.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/centralized/command_fire.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/centralized/command_police.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/centralized/command_scout.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/centralized/message_report.py create mode 100644 adf_core_python/core/agent/communication/standard/bundle/information/__init__.py rename adf_core_python/core/agent/communication/standard/bundle/{infomation => information}/message_ambulance_team.py (61%) rename adf_core_python/core/agent/communication/standard/bundle/{infomation => information}/message_building.py (57%) rename adf_core_python/core/agent/communication/standard/bundle/{infomation => information}/message_civilian.py (58%) rename adf_core_python/core/agent/communication/standard/bundle/{infomation => information}/message_fire_brigade.py (63%) rename adf_core_python/core/agent/communication/standard/bundle/{infomation => information}/message_police_force.py (61%) rename adf_core_python/core/agent/communication/standard/bundle/{infomation => information}/message_road.py (60%) create mode 100644 adf_core_python/core/agent/communication/standard/utility/__init__.py create mode 100644 adf_core_python/core/agent/communication/standard/utility/apply_to_world_info.py create mode 100644 adf_core_python/core/agent/communication/standard/utility/bitarray_with_exits_flag.py create mode 100644 adf_core_python/core/component/communication/__init__.py create mode 100644 adf_core_python/implement/module/communication/default_channel_subscriber.py create mode 100644 adf_core_python/implement/module/communication/default_message_coordinator.py diff --git a/adf_core_python/core/agent/agent.py b/adf_core_python/core/agent/agent.py index 2e86e219..51c9e980 100644 --- a/adf_core_python/core/agent/agent.py +++ b/adf_core_python/core/agent/agent.py @@ -2,14 +2,66 @@ from abc import abstractmethod from typing import Any, NoReturn -from rcrs_core.agents.agent import Agent as RCRSAgent +from bitarray import bitarray +from rcrs_core.commands.AKClear import AKClear +from rcrs_core.commands.AKClearArea import AKClearArea +from rcrs_core.commands.AKLoad import AKLoad +from rcrs_core.commands.AKMove import AKMove +from rcrs_core.commands.AKRescue import AKRescue +from rcrs_core.commands.AKRest import AKRest +from rcrs_core.commands.AKSay import AKSay +from rcrs_core.commands.AKSpeak import AKSpeak +from rcrs_core.commands.AKSubscribe import AKSubscribe +from rcrs_core.commands.AKTell import AKTell +from rcrs_core.commands.AKUnload import AKUnload from rcrs_core.commands.Command import Command from rcrs_core.config.config import Config as RCRSConfig from rcrs_core.connection.URN import Entity as EntityURN +from rcrs_core.messages.AKAcknowledge import AKAcknowledge +from rcrs_core.messages.AKConnect import AKConnect +from rcrs_core.messages.controlMessageFactory import ControlMessageFactory +from rcrs_core.messages.KAConnectError import KAConnectError +from rcrs_core.messages.KAConnectOK import KAConnectOK +from rcrs_core.messages.KASense import KASense from rcrs_core.worldmodel.changeSet import ChangeSet +from rcrs_core.worldmodel.entityID import EntityID from rcrs_core.worldmodel.worldmodel import WorldModel +from adf_core_python.core.agent.command_factory import CommandFactory from adf_core_python.core.agent.communication.message_manager import MessageManager +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_ambulance import ( + CommandAmbulance, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_fire import ( + CommandFire, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_police import ( + CommandPolice, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_scout import ( + CommandScout, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.message_report import ( + CommandReport, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_ambulance_team import ( + MessageAmbulanceTeam, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_building import ( + MessageBuilding, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_civilian import ( + MessageCivilian, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_fire_brigade import ( + MessageFireBrigade, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_police_force import ( + MessagePoliceForce, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_road import ( + MessageRoad, +) from adf_core_python.core.agent.communication.standard.standard_communication_module import ( StandardCommunicationModule, ) @@ -27,7 +79,7 @@ from adf_core_python.core.logger.logger import get_agent_logger, get_logger -class Agent(RCRSAgent): +class Agent: def __init__( self, is_precompute: bool, @@ -41,9 +93,9 @@ def __init__( self.name = name self.connect_request_id = None self.world_model = WorldModel() - self.config = None + self.config: Config self.random = None - self.agent_id = None + self.agent_id: EntityID self.precompute_flag = is_precompute self.logger = get_logger( f"{self.__class__.__module__}.{self.__class__.__qualname__}" @@ -57,29 +109,19 @@ def __init__( # PrecomputeData.remove_date(data_storage_name) self.mode = Mode.PRECOMPUTATION - self.module_config = module_config - self.develop_data = develop_data - self.precompute_data = PrecomputeData(data_storage_name) - self.message_manager: MessageManager = MessageManager() - self.communication_module: CommunicationModule = StandardCommunicationModule() + self._module_config = module_config + self._develop_data = develop_data + self._precompute_data = PrecomputeData(data_storage_name) + self._message_manager: MessageManager = MessageManager() + self._communication_module: CommunicationModule = StandardCommunicationModule() - def post_connect(self) -> None: - self.world_model.index_entities() - - config = Config() - if self.config is not None: - rcrc_config: RCRSConfig = self.config - for key, value in rcrc_config.data.items(): - config.set_value(key, value) - for key, value in rcrc_config.int_data.items(): - config.set_value(key, value) - for key, value in rcrc_config.float_data.items(): - config.set_value(key, value) - for key, value in rcrc_config.boolean_data.items(): - config.set_value(key, value) - for key, value in rcrc_config.array_data.items(): - config.set_value(key, value) + def get_entity_id(self) -> EntityID: + return self.agent_id + + def set_send_msg(self, connection_send_func): + self.send_msg = connection_send_func + def post_connect(self) -> None: if self.is_precompute: self._mode = Mode.PRECOMPUTATION else: @@ -89,35 +131,198 @@ def post_connect(self) -> None: # self._mode = Mode.NON_PRECOMPUTE self._mode = Mode.NON_PRECOMPUTE - config.set_value(ConfigKey.KEY_DEBUG_FLAG, self.is_debug) - config.set_value( - ConfigKey.KEY_DEVELOP_FLAG, self.develop_data.is_develop_mode() + self.config.set_value(ConfigKey.KEY_DEBUG_FLAG, self.is_debug) + self.config.set_value( + ConfigKey.KEY_DEVELOP_FLAG, self._develop_data.is_develop_mode() ) - self.ignore_time = config.get_value("kernel.agents.ignoreuntil", 3) - self.scenario_info: ScenarioInfo = ScenarioInfo(config, self._mode) - self.world_info: WorldInfo = WorldInfo(self.world_model) - self.agent_info = AgentInfo(self, self.world_model) + self._ignore_time: int = int( + self.config.get_value("kernel.agents.ignoreuntil", 3) + ) + self._scenario_info: ScenarioInfo = ScenarioInfo(self.config, self._mode) + self._world_info: WorldInfo = WorldInfo(self.world_model) + self._agent_info = AgentInfo(self, self.world_model) self.logger = get_agent_logger( f"{self.__class__.__module__}.{self.__class__.__qualname__}", - self.agent_info, + self._agent_info, ) - def think(self, time: int, change_set: ChangeSet, hear: list[Command]) -> None: - self.agent_info.record_think_start_time() - self.agent_info.set_time(time) + self.logger.info(f"config: {self.config}") - # if time == 1: - # self.message_manager.register_message_class() + def update_step_info( + self, time: int, change_set: ChangeSet, hear: list[Command] + ) -> None: + self._agent_info.record_think_start_time() + self._agent_info.set_time(time) - def handle_connect_error(self, msg: Any) -> NoReturn: - self.logger.error( - "Failed to connect agent: %s(request_id: %s)", msg.reason, msg.request_id + if time == 1: + self._message_manager.register_message_class(0, MessageAmbulanceTeam) + self._message_manager.register_message_class(1, MessageFireBrigade) + self._message_manager.register_message_class(2, MessagePoliceForce) + self._message_manager.register_message_class(3, MessageBuilding) + self._message_manager.register_message_class(4, MessageCivilian) + self._message_manager.register_message_class(5, MessageRoad) + self._message_manager.register_message_class(6, CommandAmbulance) + self._message_manager.register_message_class(7, CommandFire) + self._message_manager.register_message_class(8, CommandPolice) + self._message_manager.register_message_class(9, CommandScout) + self._message_manager.register_message_class(10, CommandReport) + + if time > self._ignore_time: + self._message_manager.subscribe( + self._agent_info, self._world_info, self._scenario_info + ) + if not self._message_manager.get_is_subscribed(): + subscribed_channels = self._message_manager.get_subscribed_channels() + if subscribed_channels: + self.logger.debug( + f"Subscribed channels: {subscribed_channels}", + message_manager=self._message_manager, + ) + self.send_subscribe(time, subscribed_channels) + self._message_manager.set_is_subscribed(True) + + self._agent_info.set_heard_commands(hear) + self._agent_info.set_change_set(change_set) + self._world_info.set_change_set(change_set) + + self._message_manager.refresh() + self._communication_module.receive(self, self._message_manager) + + self.think() + + self.logger.debug( + f"send messages: {self._message_manager.get_send_message_list()}", + message_manager=self._message_manager, ) - sys.exit(1) + self._message_manager.coordinate_message( + self._agent_info, self._world_info, self._scenario_info + ) + self._communication_module.send(self, self._message_manager) + + @abstractmethod + def think(self) -> None: + pass + + @abstractmethod def precompute(self) -> None: pass @abstractmethod def get_requested_entities(self) -> list[EntityURN]: pass + + def start_up(self, request_id): + ak_connect = AKConnect() + self.send_msg(ak_connect.write(request_id, self)) + + def message_received(self, msg): + c_msg = ControlMessageFactory().make_message(msg) + if isinstance(c_msg, KASense): + self.handler_sense(c_msg) + elif isinstance(c_msg, KAConnectOK): + self.handle_connect_ok(c_msg) + elif isinstance(c_msg, KAConnectError): + self.handle_connect_error(c_msg) + + def handle_connect_error(self, msg: Any) -> NoReturn: + self.logger.error( + "Failed to connect agent: %s(request_id: %s)", msg.reason, msg.request_id + ) + sys.exit(1) + + def handle_connect_ok(self, msg): + self.agent_id = EntityID(msg.agent_id) + self.world_model.add_entities(msg.world) + config: RCRSConfig = msg.config + self.config = Config() + if config is not None: + for key, value in config.data.items(): + self.config.set_value(key, value) + for key, value in config.int_data.items(): + self.config.set_value(key, value) + for key, value in config.float_data.items(): + self.config.set_value(key, value) + for key, value in config.boolean_data.items(): + self.config.set_value(key, value) + for key, value in config.array_data.items(): + self.config.set_value(key, value) + self.send_acknowledge(msg.request_id) + self.post_connect() + if self.precompute_flag: + print("self.precompute_flag: ", self.precompute_flag) + self.precompute() + + def handler_sense(self, msg): + _id = EntityID(msg.agent_id) + time = msg.time + change_set = msg.change_set + hear = msg.hear.commands + + if _id != self.get_entity_id(): + self.logger.error("Agent ID mismatch: %s != %s", _id, self.get_entity_id()) + return + + hear_commands = [CommandFactory.create_command(cmd) for cmd in hear] + + self.world_model.merge(change_set) + self.update_step_info(time, change_set, hear_commands) + + def send_acknowledge(self, request_id): + ak_ack = AKAcknowledge() + self.send_msg(ak_ack.write(request_id, self.agent_id)) + + def send_clear(self, time, target): + cmd = AKClear(self.get_entity_id(), time, target) + msg = cmd.prepare_cmd() + self.send_msg(msg) + + def send_clear_area(self, time, x=-1, y=-1): + cmd = AKClearArea(self.get_entity_id(), time, x, y) + msg = cmd.prepare_cmd() + self.send_msg(msg) + + def send_load(self, time, target): + cmd = AKLoad(self.get_entity_id(), time, target) + msg = cmd.prepare_cmd() + self.send_msg(msg) + + def send_move(self, time, path, x=-1, y=-1): + cmd = AKMove(self.get_entity_id(), time, path[:], x, y) + msg = cmd.prepare_cmd() + self.send_msg(msg) + + def send_rescue(self, time, target): + cmd = AKRescue(self.get_entity_id(), time, target) + msg = cmd.prepare_cmd() + self.send_msg(msg) + + def send_rest(self, time_step): + cmd = AKRest(self.get_entity_id(), time_step) + msg = cmd.prepare_cmd() + self.send_msg(msg) + + def send_say(self, time_step: int, message: str): + cmd = AKSay(self.get_entity_id(), time_step, message) + msg = cmd.prepare_cmd() + self.send_msg(msg) + + def send_speak(self, time_step: int, message: bitarray, channel: int): + cmd = AKSpeak(self.get_entity_id(), time_step, bytes(message), channel) # type: ignore + msg = cmd.prepare_cmd() + self.send_msg(msg) + + def send_subscribe(self, time, channel): + cmd = AKSubscribe(self.get_entity_id(), time, channel) + msg = cmd.prepare_cmd() + self.send_msg(msg) + + def send_tell(self, time_step: int, message: str): + cmd = AKTell(self.get_entity_id(), time_step, message) + msg = cmd.prepare_cmd() + self.send_msg(msg) + + def send_unload(self, time): + cmd = AKUnload(self.get_entity_id(), time) + msg = cmd.prepare_cmd() + self.send_msg(msg) diff --git a/adf_core_python/core/agent/command_factory.py b/adf_core_python/core/agent/command_factory.py new file mode 100644 index 00000000..33c52530 --- /dev/null +++ b/adf_core_python/core/agent/command_factory.py @@ -0,0 +1,44 @@ +from rcrs_core.commands.AKClear import AKClear +from rcrs_core.commands.AKClearArea import AKClearArea +from rcrs_core.commands.AKExtinguish import AKExtinguish +from rcrs_core.commands.AKLoad import AKLoad +from rcrs_core.commands.AKMove import AKMove +from rcrs_core.commands.AKRescue import AKRescue +from rcrs_core.commands.AKRest import AKRest +from rcrs_core.commands.AKSay import AKSay +from rcrs_core.commands.AKSpeak import AKSpeak +from rcrs_core.commands.AKSubscribe import AKSubscribe +from rcrs_core.commands.AKTell import AKTell +from rcrs_core.commands.AKUnload import AKUnload +from rcrs_core.commands.Command import Command +from rcrs_core.connection.URN import Command as CommandURN +from rcrs_core.connection.URN import ComponentCommand as ComponentCommandMessageID +from rcrs_core.connection.URN import ComponentControlMSG as ComponentControlMessageID + + +class CommandFactory: + @staticmethod + def create_command(herad_command) -> Command: + if herad_command.urn == CommandURN.AK_SPEAK: + return AKSpeak( + herad_command.components[ComponentControlMessageID.AgentID].entityID, + herad_command.components[ComponentControlMessageID.Time].intValue, + herad_command.components[ComponentCommandMessageID.Message].rawData, + herad_command.components[ComponentCommandMessageID.Channel].intValue, + ) + return herad_command + # if herad_command.urn == CommandURN.AK_CLEAR: + # return AKClear( + # herad_command.agent_id, herad_command.time, herad_command.target + # ) + # elif herad_command.urn == CommandURN.AK_CLEAR_AREA: + # return AKClearArea( + # herad_command.agent_id, + # herad_command.time, + # herad_command.x, + # herad_command.y, + # ) + # elif herad_command.urn == CommandURN.AK_EXTINGUISH: + # return AKExtinguish( + # herad_command.agent_id, herad_command.time, herad_command.target + # ) diff --git a/adf_core_python/core/agent/communication/message_manager.py b/adf_core_python/core/agent/communication/message_manager.py index e873664c..53c8f43f 100644 --- a/adf_core_python/core/agent/communication/message_manager.py +++ b/adf_core_python/core/agent/communication/message_manager.py @@ -1,15 +1,21 @@ -from adf_core_python.core.agent.info.agent_info import AgentInfo +from __future__ import annotations + +from typing import TYPE_CHECKING + from adf_core_python.core.agent.info.scenario_info import ScenarioInfo, ScenarioInfoKeys from adf_core_python.core.agent.info.world_info import WorldInfo -from adf_core_python.core.component.communication.channel_subscriber import ( - ChannelSubscriber, -) -from adf_core_python.core.component.communication.communication_message import ( - CommunicationMessage, -) -from adf_core_python.core.component.communication.message_coordinator import ( - MessageCoordinator, -) + +if TYPE_CHECKING: + from adf_core_python.core.agent.info.agent_info import AgentInfo + from adf_core_python.core.component.communication.channel_subscriber import ( + ChannelSubscriber, + ) + from adf_core_python.core.component.communication.communication_message import ( + CommunicationMessage, + ) + from adf_core_python.core.component.communication.message_coordinator import ( + MessageCoordinator, + ) class MessageManager: @@ -34,7 +40,7 @@ def __init__(self) -> None: """ self.__standard_message_class_count = 0b0000_0001 self.__custom_message_class_count = 0b0001_0000 - self.__message_classes: dict[int, CommunicationMessage] = {} + self.__message_classes: dict[int, type[CommunicationMessage]] = {} self.__send_message_list: list[CommunicationMessage] = [] self.__received_message_list: list[CommunicationMessage] = [] self.__channel_send_message_list: list[list[CommunicationMessage]] = [] @@ -106,6 +112,18 @@ def set_channel_subscriber(self, channel_subscriber: ChannelSubscriber) -> None: """ self.__channel_subscriber = channel_subscriber + def set_message_coordinator(self, message_coordinator: MessageCoordinator) -> None: + """ + Set the message coordinator. + + Parameters + ---------- + message_coordinator : MessageCoordinator + The message coordinator. + + """ + self.__message_coordinator = message_coordinator + def get_channel_subscriber(self) -> ChannelSubscriber: """ Get the channel subscriber. @@ -161,6 +179,18 @@ def get_received_message_list(self) -> list[CommunicationMessage]: """ return self.__received_message_list + def get_channel_send_message_list(self) -> list[list[CommunicationMessage]]: + """ + Get the channel send message list. + + Returns + ------- + list[list[CommunicationMessage]] + The channel send message list. + + """ + return self.__channel_send_message_list + def subscribe( self, agent_info: AgentInfo, world_info: WorldInfo, scenario_info: ScenarioInfo ) -> None: @@ -185,10 +215,13 @@ def subscribe( if self.__channel_subscriber is None: raise ValueError("ChannelSubscriber is not set.") - self.__channel_subscriber.subscribe(agent_info, world_info, scenario_info, self) + if agent_info.get_time() == 1: + self.__subscribed_channels = self.__channel_subscriber.subscribe( + agent_info, world_info, scenario_info + ) def register_message_class( - self, index: int, message_class: CommunicationMessage + self, index: int, message_class: type[CommunicationMessage] ) -> None: """ Register the message class. @@ -205,6 +238,43 @@ def register_message_class( ) self.__message_classes[index] = message_class + def get_message_class(self, index: int) -> type[CommunicationMessage]: + """ + Get the message class. + + Parameters + ---------- + index : int + The index. + + Returns + ------- + type[CommunicationMessage] + The message class. + + """ + return self.__message_classes[index] + + def get_message_class_index(self, message_class: type[CommunicationMessage]) -> int: + """ + Get the message class index. + + Parameters + ---------- + message_class : type[CommunicationMessage] + The message class. + + Returns + ------- + int + The message class index. + + """ + for index, cls in self.__message_classes.items(): + if cls == message_class: + return index + return -1 + def add_message( self, message: CommunicationMessage, check_duplicate: bool = True ) -> None: @@ -217,7 +287,7 @@ def add_message( The message. """ - check_key = message.get_check_key() + check_key = message.__hash__() # TODO:両方同じコードになっているが、なぜなのか調査する if check_duplicate and check_key not in self.__check_duplicate_cache: self.__send_message_list.append(message) @@ -226,6 +296,18 @@ def add_message( self.__send_message_list.append(message) self.__check_duplicate_cache.add(check_key) + def get_send_message_list(self) -> list[CommunicationMessage]: + """ + Get the send message list. + + Returns + ------- + list[CommunicationMessage] + The send message list. + + """ + return self.__send_message_list + def coordinate_message( self, agent_info: AgentInfo, world_info: WorldInfo, scenario_info: ScenarioInfo ) -> None: @@ -248,7 +330,11 @@ def coordinate_message( self.__channel_send_message_list = [ [] for _ in range( - scenario_info.get_value(ScenarioInfoKeys.COMMS_CHANNELS_COUNT, 1) + int( + scenario_info.get_value( + ScenarioInfoKeys.COMMUNICATION_CHANNELS_COUNT, 1 + ) + ) ) ] @@ -267,5 +353,23 @@ def refresh(self) -> None: """ self.__send_message_list = [] + self.__received_message_list = [] self.__check_duplicate_cache = set() self.__heard_agent_help_message_count = 0 + + def __str__(self) -> str: + return ( + f"MessageManager(" + f"standard_message_class_count={self.__standard_message_class_count}, " + f"custom_message_class_count={self.__custom_message_class_count}, " + f"message_classes={self.__message_classes}, " + f"send_message_list={self.__send_message_list}, " + f"received_message_list={self.__received_message_list}, " + f"channel_send_message_list={self.__channel_send_message_list}, " + f"check_duplicate_cache={self.__check_duplicate_cache}, " + f"message_coordinator={self.__message_coordinator}, " + f"channel_subscriber={self.__channel_subscriber}, " + f"heard_agent_help_message_count={self.__heard_agent_help_message_count}, " + f"subscribed_channels={self.__subscribed_channels}, " + f"is_subscribed={self.__is_subscribed})" + ) diff --git a/adf_core_python/core/agent/communication/standard/__init__.py b/adf_core_python/core/agent/communication/standard/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/communication/standard/bundle/__init__.py b/adf_core_python/core/agent/communication/standard/bundle/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/communication/standard/bundle/centralized/__init__.py b/adf_core_python/core/agent/communication/standard/bundle/centralized/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_ambulance.py b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_ambulance.py new file mode 100644 index 00000000..ff28ab88 --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_ambulance.py @@ -0,0 +1,135 @@ +from __future__ import annotations + +from typing import Optional + +from bitarray import bitarray +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) + + +class CommandAmbulance(StandardMessage): + ACTION_REST: int = 0 + ACTION_MOVE: int = 1 + ACTION_RESCUE: int = 2 + ACTION_LOAD: int = 3 + ACTION_UNLOAD: int = 4 + ACTION_AUTONOMY: int = 5 + + SIZE_AMBULANCE_TEAM_ENTITY_ID: int = 32 + SIZE_TARGET_ENTITY_ID: int = 32 + SIZE_ACTION: int = 4 + + def __init__( + self, + is_wireless_message: bool, + command_executor_agent_entity_id: EntityID, + sender_entity_id: EntityID, + execute_action: int, + priority: StandardMessagePriority, + command_target_entity_id: Optional[EntityID] = None, + ): + super().__init__(is_wireless_message, priority, sender_entity_id) + self._command_executor_agent_entity_id: Optional[EntityID] = ( + command_executor_agent_entity_id + ) + self._command_target_entity_id: Optional[EntityID] = command_target_entity_id + self._is_bloadcast: bool = command_target_entity_id is None + self._execute_action: Optional[int] = execute_action + + def get_command_executor_agent_entity_id(self) -> Optional[EntityID]: + return self._command_executor_agent_entity_id + + def get_command_target_entity_id(self) -> Optional[EntityID]: + return self._command_target_entity_id + + def get_execute_action(self) -> Optional[int]: + return self._execute_action + + def is_broadcast(self) -> bool: + return self._is_bloadcast + + def get_bit_size(self) -> int: + return self.to_bits().__len__() + + def to_bits(self) -> bitarray: + bit_array = super().to_bits() + raw_command_executor_agent_entity_id = ( + self._command_executor_agent_entity_id.get_value() + if self._command_executor_agent_entity_id is not None + else None + ) + write_with_exist_flag( + bit_array, + raw_command_executor_agent_entity_id, + self.SIZE_AMBULANCE_TEAM_ENTITY_ID, + ) + raw_command_target_entity_id = ( + self._command_target_entity_id.get_value() + if self._command_target_entity_id is not None + else None + ) + write_with_exist_flag( + bit_array, raw_command_target_entity_id, self.SIZE_TARGET_ENTITY_ID + ) + write_with_exist_flag(bit_array, self._execute_action, self.SIZE_ACTION) + return bit_array + + @classmethod + def from_bits( + cls, + bit_array: bitarray, + is_wireless_message: bool, + sender_entity_id: EntityID, + ) -> CommandAmbulance: + std_message = super().from_bits( + bit_array, is_wireless_message, sender_entity_id + ) + raw_command_executor_agent_entity_id = read_with_exist_flag( + bit_array, cls.SIZE_AMBULANCE_TEAM_ENTITY_ID + ) + command_executor_agent_id = ( + EntityID(raw_command_executor_agent_entity_id) + if raw_command_executor_agent_entity_id is not None + else None + ) + raw_command_target_entity_id = read_with_exist_flag( + bit_array, cls.SIZE_TARGET_ENTITY_ID + ) + command_target_id = ( + EntityID(raw_command_target_entity_id) + if raw_command_target_entity_id is not None + else None + ) + execute_action = read_with_exist_flag(bit_array, cls.SIZE_ACTION) + return cls( + is_wireless_message, + command_executor_agent_id or EntityID(-1), + sender_entity_id, + execute_action if execute_action is not None else -1, + std_message.get_priority(), + command_target_id, + ) + + def __hash__(self): + h = super().__hash__() + return hash( + ( + h, + self._command_executor_agent_entity_id, + self._command_target_entity_id, + self._execute_action, + ) + ) + + def __str__(self) -> str: + return f"CommandAmbulance(executor={self._command_executor_agent_entity_id}, target={self._command_target_entity_id}, action={self._execute_action})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_fire.py b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_fire.py new file mode 100644 index 00000000..5927a2ef --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_fire.py @@ -0,0 +1,136 @@ +from __future__ import annotations + +from typing import Optional + +from bitarray import bitarray +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) + + +class CommandFire(StandardMessage): + ACTION_REST: int = 0 + ACTION_MOVE: int = 1 + ACTION_EXTINGUISH: int = 2 + ACTION_REFILL: int = 3 + ACTION_RESCUE: int = 4 + ACTION_AUTONOMY: int = 5 + + SIZE_FIRE_BRIGADE_ENTITY_ID: int = 32 + SIZE_TARGET_ENTITY_ID: int = 32 + SIZE_ACTION: int = 4 + + def __init__( + self, + is_wireless_message: bool, + command_executor_agent_entity_id: EntityID, + sender_entity_id: EntityID, + execute_action: int, + priority: StandardMessagePriority, + command_target_entity_id: Optional[EntityID] = None, + ): + super().__init__(is_wireless_message, priority, sender_entity_id) + self._command_executor_agent_entity_id: Optional[EntityID] = ( + command_executor_agent_entity_id + ) + self._command_target_entity_id: Optional[EntityID] = command_target_entity_id + self._is_bloadcast: bool = command_target_entity_id is None + self._execute_action: Optional[int] = execute_action + + def get_command_executor_agent_entity_id(self) -> Optional[EntityID]: + return self._command_executor_agent_entity_id + + def get_command_target_entity_id(self) -> Optional[EntityID]: + return self._command_target_entity_id + + def get_execute_action(self) -> Optional[int]: + return self._execute_action + + def is_broadcast(self) -> bool: + return self._is_bloadcast + + def get_bit_size(self) -> int: + return self.to_bits().__len__() + + def to_bits(self) -> bitarray: + bit_array = super().to_bits() + raw_command_executor_agent_entity_id = ( + self._command_executor_agent_entity_id.get_value() + if self._command_executor_agent_entity_id is not None + else None + ) + write_with_exist_flag( + bit_array, + raw_command_executor_agent_entity_id, + self.SIZE_FIRE_BRIGADE_ENTITY_ID, + ) + raw_command_target_entity_id = ( + self._command_target_entity_id.get_value() + if self._command_target_entity_id is not None + else None + ) + write_with_exist_flag( + bit_array, raw_command_target_entity_id, self.SIZE_TARGET_ENTITY_ID + ) + write_with_exist_flag(bit_array, self._execute_action, self.SIZE_ACTION) + + return bit_array + + @classmethod + def from_bits( + cls, + bit_array: bitarray, + is_wireless_message: bool, + sender_entity_id: EntityID, + ) -> CommandFire: + std_message = super().from_bits( + bit_array, is_wireless_message, sender_entity_id + ) + raw_command_executor_agent_entity_id = read_with_exist_flag( + bit_array, cls.SIZE_FIRE_BRIGADE_ENTITY_ID + ) + command_executor_agent_id = ( + EntityID(raw_command_executor_agent_entity_id) + if raw_command_executor_agent_entity_id is not None + else None + ) + raw_command_target_entity_id = read_with_exist_flag( + bit_array, cls.SIZE_TARGET_ENTITY_ID + ) + command_target_id = ( + EntityID(raw_command_target_entity_id) + if raw_command_target_entity_id is not None + else None + ) + execute_action = read_with_exist_flag(bit_array, cls.SIZE_ACTION) + return cls( + is_wireless_message, + command_executor_agent_id or EntityID(-1), + sender_entity_id, + execute_action if execute_action is not None else -1, + std_message.get_priority(), + command_target_id, + ) + + def __hash__(self): + h = super().__hash__() + return hash( + ( + h, + self._command_executor_agent_entity_id, + self._command_target_entity_id, + self._execute_action, + ) + ) + + def __str__(self) -> str: + return f"CommandFire(executor={self._command_executor_agent_entity_id}, target={self._command_target_entity_id}, action={self._execute_action})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_police.py b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_police.py new file mode 100644 index 00000000..cf3cc4d6 --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_police.py @@ -0,0 +1,134 @@ +from __future__ import annotations + +from typing import Optional + +from bitarray import bitarray +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) + + +class CommandPolice(StandardMessage): + ACTION_REST: int = 0 + ACTION_MOVE: int = 1 + ACTION_CLEAR: int = 2 + ACTION_AUTONOMY: int = 3 + + SIZE_POLICE_FORCE_ENTITY_ID: int = 32 + SIZE_TARGET_ENTITY_ID: int = 32 + SIZE_ACTION: int = 4 + + def __init__( + self, + is_wireless_message: bool, + command_executor_agent_entity_id: EntityID, + sender_entity_id: EntityID, + execute_action: int, + priority: StandardMessagePriority, + command_target_entity_id: Optional[EntityID] = None, + ): + super().__init__(is_wireless_message, priority, sender_entity_id) + self._command_executor_agent_entity_id: Optional[EntityID] = ( + command_executor_agent_entity_id + ) + self._command_target_entity_id: Optional[EntityID] = command_target_entity_id + self._is_bloadcast: bool = command_target_entity_id is None + self._execute_action: Optional[int] = execute_action + + def get_command_executor_agent_entity_id(self) -> Optional[EntityID]: + return self._command_executor_agent_entity_id + + def get_command_target_entity_id(self) -> Optional[EntityID]: + return self._command_target_entity_id + + def get_execute_action(self) -> Optional[int]: + return self._execute_action + + def is_broadcast(self) -> bool: + return self._is_bloadcast + + def get_bit_size(self) -> int: + return self.to_bits().__len__() + + def to_bits(self) -> bitarray: + bit_array = super().to_bits() + raw_command_executor_agent_entity_id = ( + self._command_executor_agent_entity_id.get_value() + if self._command_executor_agent_entity_id is not None + else None + ) + write_with_exist_flag( + bit_array, + raw_command_executor_agent_entity_id, + self.SIZE_POLICE_FORCE_ENTITY_ID, + ) + raw_command_target_entity_id = ( + self._command_target_entity_id.get_value() + if self._command_target_entity_id is not None + else None + ) + write_with_exist_flag( + bit_array, raw_command_target_entity_id, self.SIZE_TARGET_ENTITY_ID + ) + write_with_exist_flag(bit_array, self._execute_action, self.SIZE_ACTION) + + return bit_array + + @classmethod + def from_bits( + cls, + bit_array: bitarray, + is_wireless_message: bool, + sender_entity_id: EntityID, + ) -> CommandPolice: + std_message = super().from_bits( + bit_array, is_wireless_message, sender_entity_id + ) + raw_command_executor_agent_entity_id = read_with_exist_flag( + bit_array, cls.SIZE_POLICE_FORCE_ENTITY_ID + ) + command_executor_agent_id = ( + EntityID(raw_command_executor_agent_entity_id) + if raw_command_executor_agent_entity_id is not None + else None + ) + raw_command_target_entity_id = read_with_exist_flag( + bit_array, cls.SIZE_TARGET_ENTITY_ID + ) + command_target_id = ( + EntityID(raw_command_target_entity_id) + if raw_command_target_entity_id is not None + else None + ) + execute_action = read_with_exist_flag(bit_array, cls.SIZE_ACTION) + return cls( + is_wireless_message, + command_executor_agent_id or EntityID(-1), + sender_entity_id, + execute_action if execute_action is not None else -1, + std_message.get_priority(), + command_target_id, + ) + + def __hash__(self): + h = super().__hash__() + return hash( + ( + h, + self._command_executor_agent_entity_id, + self._command_target_entity_id, + self._execute_action, + ) + ) + + def __str__(self) -> str: + return f"CommandPolice(executor={self._command_executor_agent_entity_id}, target={self._command_target_entity_id}, action={self._execute_action})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_scout.py b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_scout.py new file mode 100644 index 00000000..253883b0 --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_scout.py @@ -0,0 +1,129 @@ +from __future__ import annotations + +from typing import Optional + +from bitarray import bitarray +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) + + +class CommandScout(StandardMessage): + SIZE_AGENT_ENTITY_ID: int = 32 + SIZE_TARGET_ENTITY_ID: int = 32 + SIZE_SCOUT_RANGE: int = 32 + + def __init__( + self, + is_wireless_message: bool, + command_executor_agent_entity_id: EntityID, + sender_entity_id: EntityID, + scout_range: int, + priority: StandardMessagePriority, + command_target_entity_id: Optional[EntityID] = None, + ): + super().__init__(is_wireless_message, priority, sender_entity_id) + self._command_executor_agent_entity_id: Optional[EntityID] = ( + command_executor_agent_entity_id + ) + self._command_target_entity_id: Optional[EntityID] = command_target_entity_id + self._is_bloadcast: bool = command_target_entity_id is None + self._scout_range: Optional[int] = scout_range + + def get_command_executor_agent_entity_id(self) -> Optional[EntityID]: + return self._command_executor_agent_entity_id + + def get_command_target_entity_id(self) -> Optional[EntityID]: + return self._command_target_entity_id + + def get_scout_range(self) -> Optional[int]: + return self._scout_range + + def is_broadcast(self) -> bool: + return self._is_bloadcast + + def get_bit_size(self) -> int: + return self.to_bits().__len__() + + def to_bits(self) -> bitarray: + bit_array = super().to_bits() + raw_command_executor_agent_entity_id = ( + self._command_executor_agent_entity_id.get_value() + if self._command_executor_agent_entity_id is not None + else None + ) + write_with_exist_flag( + bit_array, + raw_command_executor_agent_entity_id, + self.SIZE_AGENT_ENTITY_ID, + ) + raw_command_target_entity_id = ( + self._command_target_entity_id.get_value() + if self._command_target_entity_id is not None + else None + ) + write_with_exist_flag( + bit_array, raw_command_target_entity_id, self.SIZE_TARGET_ENTITY_ID + ) + write_with_exist_flag(bit_array, self._scout_range, self.SIZE_SCOUT_RANGE) + + return bit_array + + @classmethod + def from_bits( + cls, + bit_array: bitarray, + is_wireless_message: bool, + sender_entity_id: EntityID, + ) -> CommandScout: + std_message = super().from_bits( + bit_array, is_wireless_message, sender_entity_id + ) + raw_command_executor_agent_entity_id = read_with_exist_flag( + bit_array, cls.SIZE_AGENT_ENTITY_ID + ) + command_executor_agent_id = ( + EntityID(raw_command_executor_agent_entity_id) + if raw_command_executor_agent_entity_id is not None + else None + ) + raw_command_target_entity_id = read_with_exist_flag( + bit_array, cls.SIZE_TARGET_ENTITY_ID + ) + command_target_id = ( + EntityID(raw_command_target_entity_id) + if raw_command_target_entity_id is not None + else None + ) + scout_range = read_with_exist_flag(bit_array, cls.SIZE_SCOUT_RANGE) + return cls( + is_wireless_message, + command_executor_agent_id or EntityID(-1), + sender_entity_id, + scout_range if scout_range is not None else -1, + std_message.get_priority(), + command_target_id, + ) + + def __hash__(self): + h = super().__hash__() + return hash( + ( + h, + self._command_executor_agent_entity_id, + self._command_target_entity_id, + self._scout_range, + ) + ) + + def __str__(self) -> str: + return f"CommandScout(executor={self._command_executor_agent_entity_id}, target={self._command_target_entity_id}, scout_range={self._scout_range})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/centralized/message_report.py b/adf_core_python/core/agent/communication/standard/bundle/centralized/message_report.py new file mode 100644 index 00000000..2971bb5b --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/bundle/centralized/message_report.py @@ -0,0 +1,88 @@ +from __future__ import annotations + +from bitarray import bitarray +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) + + +class CommandReport(StandardMessage): + SIZE_DONE: int = 1 + SIZE_BLOADCAST: int = 1 + + def __init__( + self, + is_wireless_message: bool, + is_done: bool, + is_bloadcast: bool, + sender_entity_id: EntityID, + priority: StandardMessagePriority, + ): + super().__init__(is_wireless_message, priority, sender_entity_id) + self._is_done: bool = is_done + self._is_bloadcast: bool = is_bloadcast + + def is_done(self) -> bool: + return self._is_done + + def is_broadcast(self) -> bool: + return self._is_bloadcast + + def get_bit_size(self) -> int: + return self.to_bits().__len__() + + def to_bits(self) -> bitarray: + bit_array = super().to_bits() + write_with_exist_flag( + bit_array, + self._is_done, + self.SIZE_DONE, + ) + write_with_exist_flag( + bit_array, + self._is_bloadcast, + self.SIZE_BLOADCAST, + ) + return bit_array + + @classmethod + def from_bits( + cls, + bit_array: bitarray, + is_wireless_message: bool, + sender_entity_id: EntityID, + ) -> CommandReport: + std_message = super().from_bits( + bit_array, is_wireless_message, sender_entity_id + ) + is_done = read_with_exist_flag(bit_array, cls.SIZE_DONE) == 1 + is_bloadcast = read_with_exist_flag(bit_array, cls.SIZE_BLOADCAST) == 1 + return cls( + is_wireless_message, + is_done, + is_bloadcast, + std_message.get_sender_entity_id(), + std_message.get_priority(), + ) + + def __hash__(self): + h = super().__hash__() + return hash( + ( + h, + self._is_done, + self._is_bloadcast, + ) + ) + + def __str__(self) -> str: + return f"CommandReport(done={self._is_done}, broadcast={self._is_bloadcast})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/information/__init__.py b/adf_core_python/core/agent/communication/standard/bundle/information/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_ambulance_team.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_ambulance_team.py similarity index 61% rename from adf_core_python/core/agent/communication/standard/bundle/infomation/message_ambulance_team.py rename to adf_core_python/core/agent/communication/standard/bundle/information/message_ambulance_team.py index 6a462a29..7f495f72 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_ambulance_team.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_ambulance_team.py @@ -12,6 +12,10 @@ from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( StandardMessagePriority, ) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) class MessageAmbulanceTeam(StandardMessage): @@ -32,14 +36,14 @@ class MessageAmbulanceTeam(StandardMessage): def __init__( self, is_wireless_message: bool, - priority: StandardMessagePriority, ambulance_team: AmbulanceTeamEntity, action: int, target_entity_id: EntityID, - sender_id: int = -1, - ttl: int = -1, + priority: StandardMessagePriority, + sender_entity_id: EntityID, + ttl: Optional[int] = None, ): - super().__init__(is_wireless_message, priority, sender_id, ttl) + super().__init__(is_wireless_message, priority, sender_entity_id, ttl) self._ambulance_team_entity_id: Optional[EntityID] = ambulance_team.get_id() self._ambulance_team_hp: Optional[int] = ambulance_team.get_hp() or None self._ambulance_team_buriedness: Optional[int] = ( @@ -52,67 +56,86 @@ def __init__( self._target_entity_id: Optional[EntityID] = target_entity_id self._action: Optional[int] = action - def get_byte_size(self) -> int: - return self.to_bytes().__len__() + def get_ambulance_team_entity_id(self) -> Optional[EntityID]: + return self._ambulance_team_entity_id + + def get_ambulance_team_hp(self) -> Optional[int]: + return self._ambulance_team_hp + + def get_ambulance_team_buriedness(self) -> Optional[int]: + return self._ambulance_team_buriedness + + def get_ambulance_team_damage(self) -> Optional[int]: + return self._ambulance_team_damage + + def get_ambulance_team_position(self) -> Optional[EntityID]: + return self._ambulance_team_position + + def get_target_entity_id(self) -> Optional[EntityID]: + return self._target_entity_id + + def get_action(self) -> Optional[int]: + return self._action - def to_bytes(self) -> bytes: - bit_array = bitarray() - self.write_with_exist_flag( + def get_bit_size(self) -> int: + return self.to_bits().__len__() + + def to_bits(self) -> bitarray: + bit_array = super().to_bits() + write_with_exist_flag( bit_array, self._ambulance_team_entity_id.get_value() if self._ambulance_team_entity_id else None, self.SIZE_AMBULANCE_TEAM_ENTITY_ID, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._ambulance_team_hp, self.SIZE_AMBULANCE_TEAM_HP ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._ambulance_team_buriedness, self.SIZE_AMBULANCE_TEAM_BURIEDNESS, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._ambulance_team_damage, self.SIZE_AMBULANCE_TEAM_DAMAGE ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._ambulance_team_position.get_value() if self._ambulance_team_position else None, self.SIZE_AMBULANCE_TEAM_POSITION, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._target_entity_id.get_value() if self._target_entity_id else None, self.SIZE_TARGET_ENTITY_ID, ) - self.write_with_exist_flag(bit_array, self._action, self.SIZE_ACTION) - return bit_array.tobytes() + write_with_exist_flag(bit_array, self._action, self.SIZE_ACTION) + return bit_array @classmethod - def from_bytes(cls, bytes: bytes) -> MessageAmbulanceTeam: - bit_array = bitarray() - bit_array.frombytes(bytes) - raw_ambulance_team_entity_id = cls.read_with_exist_flag( - bit_array, cls.SIZE_AMBULANCE_TEAM_ENTITY_ID - ) - ambulance_team_entity_id = ( - EntityID(raw_ambulance_team_entity_id) - if raw_ambulance_team_entity_id is not None - else None + def from_bits( + cls, + bit_array: bitarray, + is_wireless_message: bool, + sender_entity_id: EntityID, + ) -> MessageAmbulanceTeam: + std_message = super().from_bits( + bit_array, is_wireless_message, sender_entity_id ) - ambulance_team_hp = cls.read_with_exist_flag( - bit_array, cls.SIZE_AMBULANCE_TEAM_HP + ambulance_team_id = read_with_exist_flag( + bit_array, cls.SIZE_AMBULANCE_TEAM_ENTITY_ID ) - ambulance_team_buriedness = cls.read_with_exist_flag( + ambulance_team_hp = read_with_exist_flag(bit_array, cls.SIZE_AMBULANCE_TEAM_HP) + ambulance_team_buriedness = read_with_exist_flag( bit_array, cls.SIZE_AMBULANCE_TEAM_BURIEDNESS ) - ambulance_team_damage = cls.read_with_exist_flag( + ambulance_team_damage = read_with_exist_flag( bit_array, cls.SIZE_AMBULANCE_TEAM_DAMAGE ) - - raw_ambulance_team_position = cls.read_with_exist_flag( + raw_ambulance_team_position = read_with_exist_flag( bit_array, cls.SIZE_AMBULANCE_TEAM_POSITION ) ambulance_team_position = ( @@ -120,59 +143,44 @@ def from_bytes(cls, bytes: bytes) -> MessageAmbulanceTeam: if raw_ambulance_team_position is not None else None ) - - raw_target_entity_id = cls.read_with_exist_flag( + raw_target_entity_id = read_with_exist_flag( bit_array, cls.SIZE_TARGET_ENTITY_ID ) target_entity_id = ( - EntityID(raw_target_entity_id) if raw_target_entity_id is not None else None - ) - action = cls.read_with_exist_flag(bit_array, cls.SIZE_ACTION) - ambulance_team = AmbulanceTeamEntity( - ambulance_team_entity_id, + EntityID(raw_target_entity_id) + if raw_target_entity_id is not None + else EntityID(-1) ) + action = read_with_exist_flag(bit_array, cls.SIZE_ACTION) + ambulance_team = AmbulanceTeamEntity(ambulance_team_id or -1) ambulance_team.set_hp(ambulance_team_hp) ambulance_team.set_buriedness(ambulance_team_buriedness) ambulance_team.set_damage(ambulance_team_damage) ambulance_team.set_position(ambulance_team_position) return MessageAmbulanceTeam( False, - StandardMessagePriority.NORMAL, ambulance_team, - action or -1, - target_entity_id or EntityID(-1), - ) - - def get_check_key(self) -> str: - target_id_value: str = ( - str(self._target_entity_id.get_value()) - if self._target_entity_id - else "None" - ) - ambulance_team_id_value: str = ( - str(self._ambulance_team_entity_id.get_value()) - if self._ambulance_team_entity_id - else "None" - ) - return f"{self.__class__.__name__} > agent: {ambulance_team_id_value}, target: {target_id_value}, action: {self._action}" - - def get_ambulance_team_entity_id(self) -> Optional[EntityID]: - return self._ambulance_team_entity_id - - def get_ambulance_team_hp(self) -> Optional[int]: - return self._ambulance_team_hp - - def get_ambulance_team_buriedness(self) -> Optional[int]: - return self._ambulance_team_buriedness - - def get_ambulance_team_damage(self) -> Optional[int]: - return self._ambulance_team_damage - - def get_ambulance_team_position(self) -> Optional[EntityID]: - return self._ambulance_team_position - - def get_target_entity_id(self) -> Optional[EntityID]: - return self._target_entity_id - - def get_action(self) -> Optional[int]: - return self._action + action if action is not None else -1, + target_entity_id, + StandardMessagePriority.NORMAL, + sender_entity_id, + std_message.get_ttl(), + ) + + def __hash__(self): + h = super().__hash__() + return hash( + ( + h, + self._ambulance_team_entity_id, + self._ambulance_team_hp, + self._ambulance_team_buriedness, + self._ambulance_team_damage, + self._ambulance_team_position, + self._target_entity_id, + self._action, + ) + ) + + def __str__(self) -> str: + return f"MessageAmbulanceTeam(ambulance_team_entity_id={self._ambulance_team_entity_id}, ambulance_team_hp={self._ambulance_team_hp}, ambulance_team_buriedness={self._ambulance_team_buriedness}, ambulance_team_damage={self._ambulance_team_damage}, ambulance_team_position={self._ambulance_team_position}, target_entity_id={self._target_entity_id}, action={self._action}, ttl={self._ttl})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_building.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_building.py similarity index 57% rename from adf_core_python/core/agent/communication/standard/bundle/infomation/message_building.py rename to adf_core_python/core/agent/communication/standard/bundle/information/message_building.py index e26d00c1..3363e92c 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_building.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_building.py @@ -12,6 +12,10 @@ from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( StandardMessagePriority, ) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) class MessageBuilding(StandardMessage): @@ -24,87 +28,95 @@ def __init__( self, is_wireless_message: bool, building: Building, - priority: StandardMessagePriority = StandardMessagePriority.NORMAL, - sender_id: int = -1, - ttl: int = -1, + priority: StandardMessagePriority, + sender_entity_id: EntityID, + ttl: Optional[int] = None, ): - super().__init__(is_wireless_message, priority, sender_id, ttl) + super().__init__(is_wireless_message, priority, sender_entity_id, ttl) self._building_entity_id: Optional[EntityID] = building.get_id() self._building_brokenness: Optional[int] = building.get_brokenness() or None self._building_fireyness: Optional[int] = building.get_fieryness() or None self._building_temperature: Optional[int] = building.get_temperature() or None - def get_byte_size(self) -> int: - return self.to_bytes().__len__() + def get_building_entity_id(self) -> Optional[EntityID]: + return self._building_entity_id + + def get_building_brokenness(self) -> Optional[int]: + return self._building_brokenness + + def get_building_fireyness(self) -> Optional[int]: + return self._building_fireyness + + def get_building_temperature(self) -> Optional[int]: + return self._building_temperature + + def get_bit_size(self) -> int: + return self.to_bits().__len__() - def to_bytes(self) -> bytes: - bit_array = bitarray() - self.write_with_exist_flag( + def to_bits(self) -> bitarray: + bit_array = super().to_bits() + write_with_exist_flag( bit_array, self._building_entity_id.get_value() if self._building_entity_id else None, self.SIZE_BUILDING_ENTITY_ID, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._building_brokenness, self.SIZE_BUILDING_BROKENNESS, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._building_fireyness, self.SIZE_BUILDING_FIREYNESS, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._building_temperature, self.SIZE_BUILDING_TEMPERATURE, ) - return bit_array.tobytes() + return bit_array @classmethod - def from_bytes(cls, bytes: bytes) -> MessageBuilding: - bit_array = bitarray() - bit_array.frombytes(bytes) - raw_building_entity_id = cls.read_with_exist_flag( - bit_array, cls.SIZE_BUILDING_ENTITY_ID + def from_bits( + cls, bit_array: bitarray, is_wireless_message: bool, sender_entity_id: EntityID + ) -> MessageBuilding: + std_message = super().from_bits( + bit_array, is_wireless_message, sender_entity_id ) - building_entity_id = ( - EntityID(raw_building_entity_id) if raw_building_entity_id else None - ) - building_brokenness = cls.read_with_exist_flag( + building_id = read_with_exist_flag(bit_array, cls.SIZE_BUILDING_ENTITY_ID) + building_brokenness = read_with_exist_flag( bit_array, cls.SIZE_BUILDING_BROKENNESS ) - building_fireyness = cls.read_with_exist_flag( + building_fireyness = read_with_exist_flag( bit_array, cls.SIZE_BUILDING_FIREYNESS ) - building_temperature = cls.read_with_exist_flag( + building_temperature = read_with_exist_flag( bit_array, cls.SIZE_BUILDING_TEMPERATURE ) - building = Building( - building_entity_id.get_value() if building_entity_id else None - ) + building = Building(building_id or -1) building.set_brokenness(building_brokenness) building.set_fieryness(building_fireyness) building.set_temperature(building_temperature) return MessageBuilding( False, building, + StandardMessagePriority.NORMAL, + sender_entity_id, + std_message.get_ttl(), ) - def get_check_key(self) -> str: - building_entity_id_value = ( - self._building_entity_id.get_value() if self._building_entity_id else None + def __hash__(self): + h = super().__hash__() + return hash( + ( + h, + self._building_entity_id, + self._building_brokenness, + self._building_fireyness, + self._building_temperature, + ) ) - return f"{self.__class__.__name__} > building: {building_entity_id_value}" - def get_building_entity_id(self) -> Optional[EntityID]: - return self._building_entity_id - - def get_building_brokenness(self) -> Optional[int]: - return self._building_brokenness - - def get_building_fireyness(self) -> Optional[int]: - return self._building_fireyness - - def get_building_temperature(self) -> Optional[int]: - return self._building_temperature + def __str__(self): + return f"MessageBuilding(building_entity_id={self._building_entity_id}, building_brokenness={self._building_brokenness}, building_fireyness={self._building_fireyness}, building_temperature={self._building_temperature})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_civilian.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_civilian.py similarity index 58% rename from adf_core_python/core/agent/communication/standard/bundle/infomation/message_civilian.py rename to adf_core_python/core/agent/communication/standard/bundle/information/message_civilian.py index bc3c73b3..ac298471 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_civilian.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_civilian.py @@ -12,6 +12,10 @@ from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( StandardMessagePriority, ) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) class MessageCivilian(StandardMessage): @@ -25,73 +29,84 @@ def __init__( self, is_wireless_message: bool, civilian: Civilian, - priority: StandardMessagePriority = StandardMessagePriority.NORMAL, - sender_id: int = -1, - ttl: int = -1, + priority: StandardMessagePriority, + sender_entity_id: EntityID, + ttl: Optional[int] = None, ): - super().__init__(is_wireless_message, priority, sender_id, ttl) + super().__init__(is_wireless_message, priority, sender_entity_id, ttl) self._civilian_entity_id: Optional[EntityID] = civilian.get_id() self._civilian_hp: Optional[int] = civilian.get_hp() or None self._civilian_buriedness: Optional[int] = civilian.get_buriedness() or None self._civilian_damage: Optional[int] = civilian.get_damage() or None self._civilian_position: Optional[EntityID] = civilian.get_position() or None - def get_byte_size(self) -> int: - return self.to_bytes().__len__() + def get_civilian_entity_id(self) -> Optional[EntityID]: + return self._civilian_entity_id + + def get_civilian_hp(self) -> Optional[int]: + return self._civilian_hp + + def get_civilian_buriedness(self) -> Optional[int]: + return self._civilian_buriedness + + def get_civilian_damage(self) -> Optional[int]: + return self._civilian_damage + + def get_civilian_position(self) -> Optional[EntityID]: + return self._civilian_position + + def get_bit_size(self) -> int: + return self.to_bits().__len__() - def to_bytes(self) -> bytes: - bit_array = bitarray() - self.write_with_exist_flag( + def to_bits(self) -> bitarray: + bit_array = super().to_bits() + write_with_exist_flag( bit_array, self._civilian_entity_id.get_value() if self._civilian_entity_id else None, self.SIZE_CIVILIAN_ENTITY_ID, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._civilian_hp, self.SIZE_CIVILIAN_HP, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._civilian_buriedness, self.SIZE_CIVILIAN_BURIEDNESS, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._civilian_damage, self.SIZE_CIVILIAN_DAMAGE, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._civilian_position.get_value() if self._civilian_position else None, self.SIZE_CIVILIAN_POSITION, ) - return bit_array.tobytes() + return bit_array @classmethod - def from_bytes(cls, bytes: bytes) -> MessageCivilian: - bit_array = bitarray() - bit_array.frombytes(bytes) - raw_civilian_entity_id = cls.read_with_exist_flag( - bit_array, cls.SIZE_CIVILIAN_ENTITY_ID + def from_bits( + cls, bit_array: bitarray, is_wireless_message: bool, sender_entity_id: EntityID + ) -> MessageCivilian: + std_message = super().from_bits( + bit_array, is_wireless_message, sender_entity_id ) - civilian_entity_id = ( - EntityID(raw_civilian_entity_id) if raw_civilian_entity_id else None - ) - civilian_hp = cls.read_with_exist_flag(bit_array, cls.SIZE_CIVILIAN_HP) - civilian_buriedness = cls.read_with_exist_flag( + civilian_id = read_with_exist_flag(bit_array, cls.SIZE_CIVILIAN_ENTITY_ID) + civilian_hp = read_with_exist_flag(bit_array, cls.SIZE_CIVILIAN_HP) + civilian_buriedness = read_with_exist_flag( bit_array, cls.SIZE_CIVILIAN_BURIEDNESS ) - civilian_damage = cls.read_with_exist_flag(bit_array, cls.SIZE_CIVILIAN_DAMAGE) - raw_civilian_position = cls.read_with_exist_flag( + civilian_damage = read_with_exist_flag(bit_array, cls.SIZE_CIVILIAN_DAMAGE) + raw_civilian_position = read_with_exist_flag( bit_array, cls.SIZE_CIVILIAN_POSITION ) civilian_position = ( EntityID(raw_civilian_position) if raw_civilian_position else None ) - civilian = Civilian( - civilian_entity_id.get_value() if civilian_entity_id else None - ) + civilian = Civilian(civilian_id or -1) civilian.set_hp(civilian_hp) civilian.set_buriedness(civilian_buriedness) civilian.set_damage(civilian_damage) @@ -99,25 +114,23 @@ def from_bytes(cls, bytes: bytes) -> MessageCivilian: return MessageCivilian( False, civilian, + StandardMessagePriority.NORMAL, + sender_entity_id, + std_message.get_ttl(), ) - def get_check_key(self) -> str: - civilian_entity_id_value = ( - self._civilian_entity_id.get_value() if self._civilian_entity_id else None + def __hash__(self): + h = super().__hash__() + return hash( + ( + h, + self._civilian_entity_id, + self._civilian_hp, + self._civilian_buriedness, + self._civilian_damage, + self._civilian_position, + ) ) - return f"{self.__class__.__name__} > civilian: {civilian_entity_id_value}" - - def get_civilian_entity_id(self) -> Optional[EntityID]: - return self._civilian_entity_id - - def get_civilian_hp(self) -> Optional[int]: - return self._civilian_hp - def get_civilian_buriedness(self) -> Optional[int]: - return self._civilian_buriedness - - def get_civilian_damage(self) -> Optional[int]: - return self._civilian_damage - - def get_civilian_position(self) -> Optional[EntityID]: - return self._civilian_position + def __str__(self): + return f"MessageCivilian(civilian_entity_id={self._civilian_entity_id}, civilian_hp={self._civilian_hp}, civilian_buriedness={self._civilian_buriedness}, civilian_damage={self._civilian_damage}, civilian_position={self._civilian_position})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_fire_brigade.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_fire_brigade.py similarity index 63% rename from adf_core_python/core/agent/communication/standard/bundle/infomation/message_fire_brigade.py rename to adf_core_python/core/agent/communication/standard/bundle/information/message_fire_brigade.py index b2d9298b..11742d5a 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_fire_brigade.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_fire_brigade.py @@ -12,10 +12,14 @@ from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( StandardMessagePriority, ) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) class MessageFireBrigade(StandardMessage): - CTION_REST: int = 0 + ACTION_REST: int = 0 ACTION_MOVE: int = 1 ACTION_EXTINGUISH: int = 2 ACTION_REFILL: int = 3 @@ -36,11 +40,11 @@ def __init__( fire_brigade: FireBrigadeEntity, action: int, target_entity_id: EntityID, - priority: StandardMessagePriority = StandardMessagePriority.NORMAL, - sender_id: int = -1, - ttl: int = -1, + priority: StandardMessagePriority, + sender_entity_id: EntityID, + ttl: Optional[int] = None, ): - super().__init__(is_wireless_message, priority, sender_id, ttl) + super().__init__(is_wireless_message, priority, sender_entity_id, ttl) self._fire_brigade_entity_id: Optional[EntityID] = fire_brigade.get_id() self._fire_brigade_hp: Optional[int] = fire_brigade.get_hp() or None self._fire_brigade_buriedness: Optional[int] = ( @@ -54,88 +58,112 @@ def __init__( self._target_entity_id: Optional[EntityID] = target_entity_id self._action: Optional[int] = action - def get_byte_size(self) -> int: - return self.to_bytes().__len__() + def get_fire_brigade_entity_id(self) -> Optional[EntityID]: + return self._fire_brigade_entity_id + + def get_fire_brigade_hp(self) -> Optional[int]: + return self._fire_brigade_hp + + def get_fire_brigade_buriedness(self) -> Optional[int]: + return self._fire_brigade_buriedness + + def get_fire_brigade_damage(self) -> Optional[int]: + return self._fire_brigade_damage + + def get_fire_brigade_position(self) -> Optional[EntityID]: + return self._fire_brigade_position - def to_bytes(self) -> bytes: - bit_array = bitarray() - self.write_with_exist_flag( + def get_fire_brigade_water(self) -> Optional[int]: + return self._fire_brigade_water + + def get_target_entity_id(self) -> Optional[EntityID]: + return self._target_entity_id + + def get_action(self) -> Optional[int]: + return self._action + + def get_bit_size(self) -> int: + return self.to_bits().__len__() + + def to_bits(self) -> bitarray: + bit_array = super().to_bits() + write_with_exist_flag( bit_array, self._fire_brigade_entity_id.get_value() if self._fire_brigade_entity_id else None, self.SIZE_FIRE_BRIGADE_ENTITY_ID, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._fire_brigade_hp, self.SIZE_FIRE_BRIGADE_HP, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._fire_brigade_buriedness, self.SIZE_FIRE_BRIGADE_BURIEDNESS, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._fire_brigade_damage, self.SIZE_FIRE_BRIGADE_DAMAGE, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._fire_brigade_position.get_value() if self._fire_brigade_position else None, self.SIZE_FIRE_BRIGADE_POSITION, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._fire_brigade_water, self.SIZE_FIRE_BRIGADE_WATER, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._target_entity_id.get_value() if self._target_entity_id else None, self.SIZE_TARGET_ENTITY_ID, ) - self.write_with_exist_flag(bit_array, self._action, self.SIZE_ACTION) - return bit_array.tobytes() + write_with_exist_flag(bit_array, self._action, self.SIZE_ACTION) + return bit_array @classmethod - def from_bytes(cls, bytes: bytes) -> MessageFireBrigade: - bit_array = bitarray() - bit_array.frombytes(bytes) - raw_fire_brigade_entity_id = cls.read_with_exist_flag( - bit_array, cls.SIZE_FIRE_BRIGADE_ENTITY_ID + def from_bits( + cls, bit_array: bitarray, is_wireless_message: bool, sender_entity_id: EntityID + ) -> MessageFireBrigade: + std_message = super().from_bits( + bit_array, is_wireless_message, sender_entity_id ) - fire_brigade_entity_id = ( - EntityID(raw_fire_brigade_entity_id) if raw_fire_brigade_entity_id else None + fire_brigade_id = read_with_exist_flag( + bit_array, cls.SIZE_FIRE_BRIGADE_ENTITY_ID ) - fire_brigade_hp = cls.read_with_exist_flag(bit_array, cls.SIZE_FIRE_BRIGADE_HP) - fire_brigade_buriedness = cls.read_with_exist_flag( + fire_brigade_hp = read_with_exist_flag(bit_array, cls.SIZE_FIRE_BRIGADE_HP) + fire_brigade_buriedness = read_with_exist_flag( bit_array, cls.SIZE_FIRE_BRIGADE_BURIEDNESS ) - fire_brigade_damage = cls.read_with_exist_flag( + fire_brigade_damage = read_with_exist_flag( bit_array, cls.SIZE_FIRE_BRIGADE_DAMAGE ) - raw_fire_brigade_position = cls.read_with_exist_flag( + raw_fire_brigade_position = read_with_exist_flag( bit_array, cls.SIZE_FIRE_BRIGADE_POSITION ) fire_brigade_position = ( EntityID(raw_fire_brigade_position) if raw_fire_brigade_position else None ) - fire_brigade_water = cls.read_with_exist_flag( + fire_brigade_water = read_with_exist_flag( bit_array, cls.SIZE_FIRE_BRIGADE_WATER ) - raw_target_entity_id = cls.read_with_exist_flag( + raw_target_entity_id = read_with_exist_flag( bit_array, cls.SIZE_TARGET_ENTITY_ID ) target_entity_id = ( - EntityID(raw_target_entity_id) if raw_target_entity_id else None + EntityID(raw_target_entity_id) if raw_target_entity_id else EntityID(-1) ) - action = cls.read_with_exist_flag(bit_array, cls.SIZE_ACTION) + action = read_with_exist_flag(bit_array, cls.SIZE_ACTION) fire_brigade = FireBrigadeEntity( - fire_brigade_entity_id.get_value() if fire_brigade_entity_id else None + fire_brigade_id or -1, ) fire_brigade.set_hp(fire_brigade_hp) fire_brigade.set_buriedness(fire_brigade_buriedness) @@ -145,41 +173,28 @@ def from_bytes(cls, bytes: bytes) -> MessageFireBrigade: return MessageFireBrigade( False, fire_brigade, - action or -1, - target_entity_id or EntityID(-1), - ) - - def get_check_key(self) -> str: - fire_brigade_entity_id_value = ( - self._fire_brigade_entity_id.get_value() - if self._fire_brigade_entity_id - else None - ) - target_entity_id_value = ( - self._target_entity_id.get_value() if self._target_entity_id else None - ) - return f"{self.__class__.__name__} > fire brigade: {fire_brigade_entity_id_value} > target: {target_entity_id_value} > action: {self._action}" - - def get_fire_brigade_entity_id(self) -> Optional[EntityID]: - return self._fire_brigade_entity_id - - def get_fire_brigade_hp(self) -> Optional[int]: - return self._fire_brigade_hp - - def get_fire_brigade_buriedness(self) -> Optional[int]: - return self._fire_brigade_buriedness - - def get_fire_brigade_damage(self) -> Optional[int]: - return self._fire_brigade_damage - - def get_fire_brigade_position(self) -> Optional[EntityID]: - return self._fire_brigade_position - - def get_fire_brigade_water(self) -> Optional[int]: - return self._fire_brigade_water - - def get_target_entity_id(self) -> Optional[EntityID]: - return self._target_entity_id - - def get_action(self) -> Optional[int]: - return self._action + action if action is not None else -1, + target_entity_id, + StandardMessagePriority.NORMAL, + sender_entity_id, + std_message.get_ttl(), + ) + + def __hash__(self): + h = super().__hash__() + return hash( + ( + h, + self._fire_brigade_entity_id, + self._fire_brigade_hp, + self._fire_brigade_buriedness, + self._fire_brigade_damage, + self._fire_brigade_position, + self._fire_brigade_water, + self._target_entity_id, + self._action, + ) + ) + + def __str__(self): + return f"MessageFireBrigade(fire_brigade_entity_id={self._fire_brigade_entity_id}, fire_brigade_hp={self._fire_brigade_hp}, fire_brigade_buriedness={self._fire_brigade_buriedness}, fire_brigade_damage={self._fire_brigade_damage}, fire_brigade_position={self._fire_brigade_position}, fire_brigade_water={self._fire_brigade_water}, target_entity_id={self._target_entity_id}, action={self._action})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_police_force.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_police_force.py similarity index 61% rename from adf_core_python/core/agent/communication/standard/bundle/infomation/message_police_force.py rename to adf_core_python/core/agent/communication/standard/bundle/information/message_police_force.py index 6f3c43c0..8280184d 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_police_force.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_police_force.py @@ -12,10 +12,14 @@ from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( StandardMessagePriority, ) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) class MessagePoliceForce(StandardMessage): - CTION_REST: int = 0 + ACTION_REST: int = 0 ACTION_MOVE: int = 1 ACTION_CLEAR: int = 2 @@ -33,11 +37,11 @@ def __init__( police_force: PoliceForceEntity, action: int, target_entity_id: EntityID, - priority: StandardMessagePriority = StandardMessagePriority.NORMAL, - sender_id: int = -1, - ttl: int = -1, + priority: StandardMessagePriority, + sender_entity_id: EntityID, + ttl: Optional[int] = None, ): - super().__init__(is_wireless_message, priority, sender_id, ttl) + super().__init__(is_wireless_message, priority, sender_entity_id, ttl) self._police_force_entity_id: Optional[EntityID] = police_force.get_id() self._police_force_hp: Optional[int] = police_force.get_hp() or None self._police_force_buriedness: Optional[int] = ( @@ -50,81 +54,100 @@ def __init__( self._target_entity_id: Optional[EntityID] = target_entity_id self._action: Optional[int] = action - def get_byte_size(self) -> int: - return self.to_bytes().__len__() + def get_police_force_entity_id(self) -> Optional[EntityID]: + return self._police_force_entity_id + + def get_police_force_hp(self) -> Optional[int]: + return self._police_force_hp + + def get_police_force_buriedness(self) -> Optional[int]: + return self._police_force_buriedness + + def get_police_force_damage(self) -> Optional[int]: + return self._police_force_damage + + def get_police_force_position(self) -> Optional[EntityID]: + return self._police_force_position - def to_bytes(self) -> bytes: - bit_array = bitarray() - self.write_with_exist_flag( + def get_target_entity_id(self) -> Optional[EntityID]: + return self._target_entity_id + + def get_action(self) -> Optional[int]: + return self._action + + def get_bit_size(self) -> int: + return self.to_bits().__len__() + + def to_bits(self) -> bitarray: + bit_array = super().to_bits() + write_with_exist_flag( bit_array, self._police_force_entity_id.get_value() if self._police_force_entity_id else None, self.SIZE_POLICE_FORCE_ENTITY_ID, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._police_force_hp, self.SIZE_POLICE_FORCE_HP, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._police_force_buriedness, self.SIZE_POLICE_FORCE_BURIEDNESS, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._police_force_damage, self.SIZE_POLICE_FORCE_DAMAGE, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._police_force_position.get_value() if self._police_force_position else None, self.SIZE_POLICE_FORCE_POSITION, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._target_entity_id.get_value() if self._target_entity_id else None, self.SIZE_TARGET_ENTITY_ID, ) - self.write_with_exist_flag(bit_array, self._action, self.SIZE_ACTION) - return bit_array.tobytes() + write_with_exist_flag(bit_array, self._action, self.SIZE_ACTION) + return bit_array @classmethod - def from_bytes(cls, bytes: bytes) -> MessagePoliceForce: - bit_array = bitarray() - bit_array.frombytes(bytes) - raw_police_force_entity_id = cls.read_with_exist_flag( - bit_array, cls.SIZE_POLICE_FORCE_ENTITY_ID + def from_bits( + cls, bit_array: bitarray, is_wireless_message: bool, sender_entity_id: EntityID + ) -> MessagePoliceForce: + std_message = super().from_bits( + bit_array, is_wireless_message, sender_entity_id ) - police_force_entity_id = ( - EntityID(raw_police_force_entity_id) if raw_police_force_entity_id else None + police_force_id = read_with_exist_flag( + bit_array, cls.SIZE_POLICE_FORCE_ENTITY_ID ) - police_force_hp = cls.read_with_exist_flag(bit_array, cls.SIZE_POLICE_FORCE_HP) - police_force_buriedness = cls.read_with_exist_flag( + police_force_hp = read_with_exist_flag(bit_array, cls.SIZE_POLICE_FORCE_HP) + police_force_buriedness = read_with_exist_flag( bit_array, cls.SIZE_POLICE_FORCE_BURIEDNESS ) - police_force_damage = cls.read_with_exist_flag( + police_force_damage = read_with_exist_flag( bit_array, cls.SIZE_POLICE_FORCE_DAMAGE ) - raw_police_force_position = cls.read_with_exist_flag( + raw_police_force_position = read_with_exist_flag( bit_array, cls.SIZE_POLICE_FORCE_POSITION ) police_force_position = ( EntityID(raw_police_force_position) if raw_police_force_position else None ) - raw_target_entity_id = cls.read_with_exist_flag( + raw_target_entity_id = read_with_exist_flag( bit_array, cls.SIZE_TARGET_ENTITY_ID ) target_entity_id = ( - EntityID(raw_target_entity_id) if raw_target_entity_id else None - ) - action = cls.read_with_exist_flag(bit_array, cls.SIZE_ACTION) - police_force = PoliceForceEntity( - police_force_entity_id.get_value() if police_force_entity_id else None + EntityID(raw_target_entity_id) if raw_target_entity_id else EntityID(-1) ) + action = read_with_exist_flag(bit_array, cls.SIZE_ACTION) + police_force = PoliceForceEntity(police_force_id or -1) police_force.set_hp(police_force_hp) police_force.set_buriedness(police_force_buriedness) police_force.set_damage(police_force_damage) @@ -132,38 +155,27 @@ def from_bytes(cls, bytes: bytes) -> MessagePoliceForce: return MessagePoliceForce( False, police_force, - action or -1, - target_entity_id or EntityID(-1), - ) - - def get_check_key(self) -> str: - police_force_entity_id_value = ( - self._police_force_entity_id.get_value() - if self._police_force_entity_id - else None - ) - target_entity_id_value = ( - self._target_entity_id.get_value() if self._target_entity_id else None - ) - return f"{self.__class__.__name__} > police force: {police_force_entity_id_value} > target: {target_entity_id_value} > action: {self._action}" - - def get_police_force_entity_id(self) -> Optional[EntityID]: - return self._police_force_entity_id - - def get_police_force_hp(self) -> Optional[int]: - return self._police_force_hp - - def get_police_force_buriedness(self) -> Optional[int]: - return self._police_force_buriedness - - def get_police_force_damage(self) -> Optional[int]: - return self._police_force_damage - - def get_police_force_position(self) -> Optional[EntityID]: - return self._police_force_position - - def get_target_entity_id(self) -> Optional[EntityID]: - return self._target_entity_id - - def get_action(self) -> Optional[int]: - return self._action + action if action is not None else -1, + target_entity_id, + StandardMessagePriority.NORMAL, + sender_entity_id, + std_message.get_ttl(), + ) + + def __hash__(self): + h = super().__hash__() + return hash( + ( + h, + self._police_force_entity_id, + self._police_force_hp, + self._police_force_buriedness, + self._police_force_damage, + self._police_force_position, + self._target_entity_id, + self._action, + ) + ) + + def __str__(self): + return f"MessagePoliceForce(police_force_entity_id={self._police_force_entity_id}, police_force_hp={self._police_force_hp}, police_force_buriedness={self._police_force_buriedness}, police_force_damage={self._police_force_damage}, police_force_position={self._police_force_position}, target_entity_id={self._target_entity_id}, action={self._action})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_road.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_road.py similarity index 60% rename from adf_core_python/core/agent/communication/standard/bundle/infomation/message_road.py rename to adf_core_python/core/agent/communication/standard/bundle/information/message_road.py index 89a2863b..9023973f 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/infomation/message_road.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_road.py @@ -13,10 +13,14 @@ from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( StandardMessagePriority, ) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) class MessageRoad(StandardMessage): - CTION_REST: int = 0 + ACTION_REST: int = 0 ACTION_MOVE: int = 1 ACTION_CLEAR: int = 2 @@ -34,11 +38,11 @@ def __init__( is_send_blockade_location: bool, is_passable: Optional[bool], blockade: Optional[Blockade], - priority: StandardMessagePriority = StandardMessagePriority.NORMAL, - sender_id: int = -1, - ttl: int = -1, + priority: StandardMessagePriority, + sender_entity_id: EntityID, + ttl: Optional[int] = None, ): - super().__init__(is_wireless_message, priority, sender_id, ttl) + super().__init__(is_wireless_message, priority, sender_entity_id, ttl) self._road_entity_id: Optional[EntityID] = road.get_id() self._road_blockade_entity_id: Optional[EntityID] = None self._road_blockade_repair_cost: Optional[int] = None @@ -55,24 +59,45 @@ def __init__( self._is_passable: Optional[bool] = is_passable self._is_send_blockade_location: bool = is_send_blockade_location - def get_byte_size(self) -> int: - return self.to_bytes().__len__() + def get_road_entity_id(self) -> Optional[EntityID]: + return self._road_entity_id + + def get_road_blockade_entity_id(self) -> Optional[EntityID]: + return self._road_blockade_entity_id + + def get_road_blockade_repair_cost(self) -> Optional[int]: + return self._road_blockade_repair_cost + + def get_road_blockade_x(self) -> Optional[int]: + return self._road_blockade_x - def to_bytes(self) -> bytes: - bit_array = bitarray() - self.write_with_exist_flag( + def get_road_blockade_y(self) -> Optional[int]: + return self._road_blockade_y + + def get_is_passable(self) -> Optional[bool]: + return self._is_passable + + def get_is_send_blockade_location(self) -> bool: + return self._is_send_blockade_location + + def get_bit_size(self) -> int: + return self.to_bits().__len__() + + def to_bits(self) -> bitarray: + bit_array = super().to_bits() + write_with_exist_flag( bit_array, self._road_entity_id.get_value() if self._road_entity_id else None, self.SIZE_ROAD_ENTITY_ID, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._road_blockade_entity_id.get_value() if self._road_blockade_entity_id else None, self.SIZE_ROAD_BLOCKADE_ENTITY_ID, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._road_blockade_repair_cost if self._road_blockade_repair_cost @@ -80,88 +105,75 @@ def to_bytes(self) -> bytes: self.SIZE_ROAD_BLOCKADE_REPAIR_COST, ) if self._is_send_blockade_location: - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._road_blockade_x if self._road_blockade_x else None, self.SIZE_ROAD_BLOCKADE_X, ) - self.write_with_exist_flag( + write_with_exist_flag( bit_array, self._road_blockade_y if self._road_blockade_y else None, self.SIZE_ROAD_BLOCKADE_Y, ) else: - self.write_with_exist_flag(bit_array, None, self.SIZE_ROAD_BLOCKADE_X) - self.write_with_exist_flag(bit_array, None, self.SIZE_ROAD_BLOCKADE_Y) - self.write_with_exist_flag( + write_with_exist_flag(bit_array, None, self.SIZE_ROAD_BLOCKADE_X) + write_with_exist_flag(bit_array, None, self.SIZE_ROAD_BLOCKADE_Y) + write_with_exist_flag( bit_array, self._is_passable if self._is_passable else None, self.SIZE_PASSABLE, ) - return bit_array.tobytes() + return bit_array @classmethod - def from_bytes(cls, bytes: bytes) -> MessageRoad: - bit_array = bitarray() - bit_array.frombytes(bytes) - raw_road_entity_id = cls.read_with_exist_flag( - bit_array, cls.SIZE_ROAD_ENTITY_ID + def from_bits( + cls, bit_array: bitarray, is_wireless_message: bool, sender_entity_id: EntityID + ) -> MessageRoad: + std_message = super().from_bits( + bit_array, is_wireless_message, sender_entity_id ) - road_entity_id = EntityID(raw_road_entity_id) if raw_road_entity_id else None - raw_road_blockade_entity_id = cls.read_with_exist_flag( + road_id = read_with_exist_flag(bit_array, cls.SIZE_ROAD_ENTITY_ID) + road_blockade_id = read_with_exist_flag( bit_array, cls.SIZE_ROAD_BLOCKADE_ENTITY_ID ) - road_blockade_entity_id = ( - EntityID(raw_road_blockade_entity_id) - if raw_road_blockade_entity_id - else None - ) - road_blockade_repair_cost = cls.read_with_exist_flag( + road_blockade_repair_cost = read_with_exist_flag( bit_array, cls.SIZE_ROAD_BLOCKADE_REPAIR_COST ) - road_blockade_x = cls.read_with_exist_flag(bit_array, cls.SIZE_ROAD_BLOCKADE_X) - road_blockade_y = cls.read_with_exist_flag(bit_array, cls.SIZE_ROAD_BLOCKADE_Y) + road_blockade_x = read_with_exist_flag(bit_array, cls.SIZE_ROAD_BLOCKADE_X) + road_blockade_y = read_with_exist_flag(bit_array, cls.SIZE_ROAD_BLOCKADE_Y) is_passable = ( - True if cls.read_with_exist_flag(bit_array, cls.SIZE_PASSABLE) else False - ) - road = Road(road_entity_id.get_value() if road_entity_id else None) - blockade = Blockade( - road_blockade_entity_id.get_value() if road_blockade_entity_id else None + True if read_with_exist_flag(bit_array, cls.SIZE_PASSABLE) else False ) + road = Road(road_id or -1) + blockade = Blockade(road_blockade_id or -1) blockade.set_repaire_cost(road_blockade_repair_cost) blockade.set_x(road_blockade_x) blockade.set_y(road_blockade_y) return MessageRoad( - False, + is_wireless_message, road, False, is_passable, blockade, + StandardMessagePriority.NORMAL, + sender_entity_id, + std_message.get_ttl(), ) - def get_check_key(self) -> str: - road_entity_id_value = ( - self._road_entity_id.get_value() if self._road_entity_id else None + def __hash__(self): + h = super().__hash__() + return hash( + ( + h, + self._road_entity_id, + self._road_blockade_entity_id, + self._road_blockade_repair_cost, + self._road_blockade_x, + self._road_blockade_y, + self._is_passable, + self._is_send_blockade_location, + ) ) - return f"{self.__class__.__name__} > road: {road_entity_id_value}" - - def get_road_entity_id(self) -> Optional[EntityID]: - return self._road_entity_id - - def get_road_blockade_entity_id(self) -> Optional[EntityID]: - return self._road_blockade_entity_id - - def get_road_blockade_repair_cost(self) -> Optional[int]: - return self._road_blockade_repair_cost - def get_road_blockade_x(self) -> Optional[int]: - return self._road_blockade_x - - def get_road_blockade_y(self) -> Optional[int]: - return self._road_blockade_y - - def get_is_passable(self) -> Optional[bool]: - return self._is_passable - - def get_is_send_blockade_location(self) -> bool: - return self._is_send_blockade_location + def __str__(self): + return f"MessageRoad(road_entity_id={self._road_entity_id}, road_blockade_entity_id={self._road_blockade_entity_id}, road_blockade_repair_cost={self._road_blockade_repair_cost}, road_blockade_x={self._road_blockade_x}, road_blockade_y={self._road_blockade_y}, is_passable={self._is_passable}, is_send_blockade_location={self._is_send_blockade_location})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/standard_message.py b/adf_core_python/core/agent/communication/standard/bundle/standard_message.py index c66f66a1..490f3675 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/standard_message.py +++ b/adf_core_python/core/agent/communication/standard/bundle/standard_message.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Optional from bitarray import bitarray @@ -6,51 +8,64 @@ from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( StandardMessagePriority, ) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) from adf_core_python.core.component.communication.communication_message import ( CommunicationMessage, ) class StandardMessage(CommunicationMessage): + SIZE_TTL: int = 3 + def __init__( self, is_wireless_message: bool, priority: StandardMessagePriority, - sender_id: int = -1, - ttl: int = -1, + sender_entity_id: EntityID, + ttl: Optional[int] = None, ): super().__init__(is_wireless_message) self._priority = priority - self._sender_id = sender_id + self._sender_entity_id = sender_entity_id self._ttl = ttl def get_sender_entity_id(self) -> EntityID: - return EntityID(self._sender_id) - - def get_ttl(self) -> int: - return self._ttl + return self._sender_entity_id def get_priority(self) -> StandardMessagePriority: return self._priority - @staticmethod - def write_with_exist_flag( - bit_array: bitarray, value: Optional[int], size: int - ) -> None: - if value is None: - bit_array.extend([False]) - else: - bit_array.extend([True]) - bit_array.frombytes(value.to_bytes(size, "big")) - - @staticmethod - def read_with_exist_flag(bit_array: bitarray, size: int) -> Optional[int]: - exist_flag = bit_array.pop(0) - if exist_flag == 0: - return None - elif exist_flag == 1: - value = int.from_bytes(bit_array.tobytes()[:size], "big") - del bit_array[:size] - return value - else: - raise ValueError("Invalid exist flag") + def get_ttl(self) -> Optional[int]: + return self._ttl + + @classmethod + def from_bits( + cls, + bit_array: bitarray, + is_wireless_message: bool, + sender_entity_id: EntityID, + ) -> StandardMessage: + ttl = read_with_exist_flag(bit_array, cls.SIZE_TTL) + return StandardMessage( + is_wireless_message, + StandardMessagePriority.NORMAL, + sender_entity_id, + ttl, + ) + + def to_bits(self) -> bitarray: + bit_array = bitarray() + write_with_exist_flag(bit_array, self._ttl, self.SIZE_TTL) + return bit_array + + def get_bit_size(self) -> int: + raise NotImplementedError + + def __hash__(self): + return hash((self._sender_entity_id, self._priority, self._ttl)) + + def __str__(self) -> str: + return f"StandardMessage(sender_entity_id={self._sender_entity_id}, priority={self._priority}, ttl={self._ttl})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py b/adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py index 1c6b17f7..e8e2e256 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py +++ b/adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py @@ -12,3 +12,11 @@ class StandardMessagePriority(Enum): def __str__(self) -> str: return self.name.lower() + + def __lt__(self, other): + if isinstance(other, StandardMessagePriority): + return self.value < other.value + + def __le__(self, other): + if isinstance(other, StandardMessagePriority): + return self.value <= other.value diff --git a/adf_core_python/core/agent/communication/standard/standard_communication_module.py b/adf_core_python/core/agent/communication/standard/standard_communication_module.py index 057930d1..3fdffb3c 100644 --- a/adf_core_python/core/agent/communication/standard/standard_communication_module.py +++ b/adf_core_python/core/agent/communication/standard/standard_communication_module.py @@ -1,14 +1,176 @@ -from rcrs_core.agents.agent import Agent +from __future__ import annotations + +from typing import TYPE_CHECKING + +from bitarray import bitarray +from rcrs_core.commands.AKSpeak import AKSpeak +from rcrs_core.worldmodel.entityID import EntityID from adf_core_python.core.agent.communication.message_manager import MessageManager +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.utility.bitarray_with_exits_flag import ( + read_with_exist_flag, + write_with_exist_flag, +) from adf_core_python.core.component.communication.communication_module import ( CommunicationModule, ) +from adf_core_python.core.logger.logger import get_logger + +if TYPE_CHECKING: + from adf_core_python.core.agent.agent import Agent class StandardCommunicationModule(CommunicationModule): + ESCAPE_CHAR = bitarray("11111111") + SIZE_ID: int = 5 + SIZE_TTL: int = 3 + def receive(self, agent: Agent, message_manager: MessageManager) -> None: - raise NotImplementedError + heard_commands = agent._agent_info.get_heard_commands() + for command in heard_commands: + if isinstance(command, AKSpeak): + sender_entity_id = command.agent_id + if sender_entity_id == agent.get_entity_id(): + continue + data = command.message + is_wireless_message = command.channel != 0 + + if len(data) == 0: + continue + + if is_wireless_message: + bit_array = bitarray() + bit_array.frombytes(data) + self.add_received_message( + message_manager, + is_wireless_message, + sender_entity_id, + bit_array, + ) + else: + try: + voice_message = data.decode("utf-8") + if voice_message.startswith("Help") or voice_message.startswith( + "Ouch" + ): + message_manager.add_heard_agent_help_message_count() + continue + except UnicodeDecodeError: + pass + + escape_char = self.ESCAPE_CHAR.tobytes()[0] + i = 0 + bit_array = bitarray() + a = bitarray() + a.frombytes(data) + while i < len(data): + if data[i] == escape_char: + if (i + 1) >= len(data): + self.add_received_message( + message_manager, + False, + sender_entity_id, + bit_array, + ) + break + elif data[i + 1] != escape_char: + self.add_received_message( + message_manager, + False, + sender_entity_id, + bit_array, + ) + bit_array.clear() + i += 1 # Skip the next character + continue + i += 1 # Skip the escaped character + bits = bitarray() + bits.frombytes(data[i].to_bytes(1, "big")) + bit_array.extend(bits) + i += 1 def send(self, agent: Agent, message_manager: MessageManager) -> None: - raise NotImplementedError + voice_message_limit_bytes = agent._scenario_info.get_value( + "comms.channels.0.messages.size", 256 + ) + left_voice_message_limit_bits = voice_message_limit_bytes * 8 + voice_message_bit_array = bitarray() + + send_messages = message_manager.get_channel_send_message_list() + + for channel in range(len(send_messages)): + for message in send_messages[channel]: + message_class_index = message_manager.get_message_class_index( + type(message) + ) + bit_array = bitarray() + + write_with_exist_flag(bit_array, message_class_index, self.SIZE_ID) + + bit_array.extend(message.to_bits()) + + if channel > 0: + agent.send_speak( + agent._agent_info.get_time(), + bit_array, + channel, + ) + else: + # bit_arrayを8bitごとに区切れるようにして、エスケープ処理を行う + if len(bit_array) % 8 != 0: + bit_array.extend([False] * (8 - len(bit_array) % 8)) + message_bit_size = len(bit_array) + if message_bit_size <= left_voice_message_limit_bits: + esceped_message_data = bitarray() + for i in range(len(bit_array) // 8): + if bit_array[(i * 8) : ((i + 1) * 8)] == self.ESCAPE_CHAR: + esceped_message_data.extend(self.ESCAPE_CHAR) + esceped_message_data.extend( + bit_array[(i * 8) : ((i + 1) * 8)] + ) + esceped_message_data.extend(self.ESCAPE_CHAR) + if len(esceped_message_data) <= voice_message_limit_bytes: + left_voice_message_limit_bits -= len(esceped_message_data) + voice_message_bit_array.extend(esceped_message_data) + + if len(voice_message_bit_array) > 0: + agent.send_speak( + agent._agent_info.get_time(), + voice_message_bit_array, + 0, + ) + + def add_received_message( + self, + message_manager: MessageManager, + is_wireless_message: bool, + sender_entity_id: EntityID, + data: bitarray, + ) -> None: + message_class_index = read_with_exist_flag(data, self.SIZE_ID) + if message_class_index is None or message_class_index < 0: + get_logger( + f"{self.__class__.__module__}.{self.__class__.__qualname__}" + ).warning(f"Invalid message class index: {message_class_index}") + return + + message = message_manager.get_message_class(message_class_index) + if message is None: + get_logger( + f"{self.__class__.__module__}.{self.__class__.__qualname__}" + ).warning(f"Invalid message class index: {message_class_index}") + return + + if issubclass(message, StandardMessage): + message_instance = message.from_bits( + data, is_wireless_message, sender_entity_id + ) + message_manager.add_received_message(message_instance) + else: + get_logger( + f"{self.__class__.__module__}.{self.__class__.__qualname__}" + ).warning(f"Invalid message class: {message}") + return diff --git a/adf_core_python/core/agent/communication/standard/utility/__init__.py b/adf_core_python/core/agent/communication/standard/utility/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/communication/standard/utility/apply_to_world_info.py b/adf_core_python/core/agent/communication/standard/utility/apply_to_world_info.py new file mode 100644 index 00000000..811c152d --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/utility/apply_to_world_info.py @@ -0,0 +1,335 @@ +from rcrs_core.entities.ambulanceTeam import AmbulanceTeamEntity +from rcrs_core.entities.blockade import Blockade +from rcrs_core.entities.building import Building +from rcrs_core.entities.civilian import Civilian +from rcrs_core.entities.fireBrigade import FireBrigadeEntity +from rcrs_core.entities.policeForce import PoliceForceEntity +from rcrs_core.entities.road import Road + +from adf_core_python.core.agent.communication.standard.bundle.information.message_ambulance_team import ( + MessageAmbulanceTeam, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_building import ( + MessageBuilding, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_civilian import ( + MessageCivilian, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_fire_brigade import ( + MessageFireBrigade, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_police_force import ( + MessagePoliceForce, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_road import ( + MessageRoad, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.info.world_info import WorldInfo + + +def apply_to_world_info( + world_info: WorldInfo, + standard_message: StandardMessage, +) -> None: + """ + Apply to world info. + + PARAMETERS + ---------- + world_info: WorldInfo + The world info to apply to. + standard_message: StandardMessage + The standard message to apply to world info. + """ + + if isinstance(standard_message, MessageAmbulanceTeam): + _apply_to_world_info_ambulance_team(world_info, standard_message) + elif isinstance(standard_message, MessageFireBrigade): + _apply_to_world_info_fire_brigade(world_info, standard_message) + elif isinstance(standard_message, MessagePoliceForce): + _apply_to_world_info_police_force(world_info, standard_message) + elif isinstance(standard_message, MessageCivilian): + _apply_to_world_info_civilian(world_info, standard_message) + elif isinstance(standard_message, MessageBuilding): + _apply_to_world_info_building(world_info, standard_message) + elif isinstance(standard_message, MessageRoad): + _apply_to_world_info_road(world_info, standard_message) + else: + return + + +def _apply_to_world_info_ambulance_team( + world_info: WorldInfo, + message_ambulance_team: MessageAmbulanceTeam, +) -> None: + """ + Apply to world info for ambulance team. + + PARAMETERS + ---------- + world_info: WorldInfo + The world info to apply to. + standard_message: StandardMessage + The standard message to apply to world info. + """ + entity_id = message_ambulance_team.get_ambulance_team_entity_id() + if entity_id is None: + return + entity = world_info.get_entity(entity_id) + if entity is None: + ambulance = AmbulanceTeamEntity(entity_id.get_value()) + if (hp := message_ambulance_team.get_ambulance_team_hp()) is not None: + ambulance.set_hp(hp) + if (damege := message_ambulance_team.get_ambulance_team_damage()) is not None: + ambulance.set_damage(damege) + if ( + buriedness := message_ambulance_team.get_ambulance_team_buriedness() + ) is not None: + ambulance.set_buriedness(buriedness) + if ( + position := message_ambulance_team.get_ambulance_team_position() + ) is not None: + ambulance.set_position(position) + world_info.add_entity(ambulance) + else: + if isinstance(entity, AmbulanceTeamEntity): + if (hp := message_ambulance_team.get_ambulance_team_hp()) is not None: + entity.set_hp(hp) + if ( + damege := message_ambulance_team.get_ambulance_team_damage() + ) is not None: + entity.set_damage(damege) + if ( + buriedness := message_ambulance_team.get_ambulance_team_buriedness() + ) is not None: + entity.set_buriedness(buriedness) + if ( + position := message_ambulance_team.get_ambulance_team_position() + ) is not None: + entity.set_position(position) + + +def _apply_to_world_info_fire_brigade( + world_info: WorldInfo, + message_fire_brigade: MessageFireBrigade, +) -> None: + """ + Apply to world info for fire brigade. + + PARAMETERS + ---------- + world_info: WorldInfo + The world info to apply to. + standard_message: StandardMessage + The standard message to apply to world info. + """ + entity_id = message_fire_brigade.get_fire_brigade_entity_id() + if entity_id is None: + return + entity = world_info.get_entity(entity_id) + if entity is None: + fire_brigade = FireBrigadeEntity(entity_id.get_value()) + if (hp := message_fire_brigade.get_fire_brigade_hp()) is not None: + fire_brigade.set_hp(hp) + if (damage := message_fire_brigade.get_fire_brigade_damage()) is not None: + fire_brigade.set_damage(damage) + if ( + buriedness := message_fire_brigade.get_fire_brigade_buriedness() + ) is not None: + fire_brigade.set_buriedness(buriedness) + if (position := message_fire_brigade.get_fire_brigade_position()) is not None: + fire_brigade.set_position(position) + if (water := message_fire_brigade.get_fire_brigade_water()) is not None: + fire_brigade.set_water(water) + world_info.add_entity(fire_brigade) + else: + if isinstance(entity, FireBrigadeEntity): + if (hp := message_fire_brigade.get_fire_brigade_hp()) is not None: + entity.set_hp(hp) + if (damage := message_fire_brigade.get_fire_brigade_damage()) is not None: + entity.set_damage(damage) + if ( + buriedness := message_fire_brigade.get_fire_brigade_buriedness() + ) is not None: + entity.set_buriedness(buriedness) + if ( + position := message_fire_brigade.get_fire_brigade_position() + ) is not None: + entity.set_position(position) + if (water := message_fire_brigade.get_fire_brigade_water()) is not None: + entity.set_water(water) + + +def _apply_to_world_info_police_force( + world_info: WorldInfo, + message_police_force: MessagePoliceForce, +) -> None: + """ + Apply to world info for police force. + + PARAMETERS + ---------- + world_info: WorldInfo + The world info to apply to. + standard_message: StandardMessage + The standard message to apply to world info. + """ + entity_id = message_police_force.get_police_force_entity_id() + if entity_id is None: + return + entity = world_info.get_entity(entity_id) + if entity is None: + police_force = PoliceForceEntity(entity_id.get_value()) + if (hp := message_police_force.get_police_force_hp()) is not None: + police_force.set_hp(hp) + if (damage := message_police_force.get_police_force_damage()) is not None: + police_force.set_damage(damage) + if ( + buriedness := message_police_force.get_police_force_buriedness() + ) is not None: + police_force.set_buriedness(buriedness) + if (position := message_police_force.get_police_force_position()) is not None: + police_force.set_position(position) + world_info.add_entity(police_force) + else: + if isinstance(entity, PoliceForceEntity): + if (hp := message_police_force.get_police_force_hp()) is not None: + entity.set_hp(hp) + if (damage := message_police_force.get_police_force_damage()) is not None: + entity.set_damage(damage) + if ( + buriedness := message_police_force.get_police_force_buriedness() + ) is not None: + entity.set_buriedness(buriedness) + if ( + position := message_police_force.get_police_force_position() + ) is not None: + entity.set_position(position) + + +def _apply_to_world_info_civilian( + world_info: WorldInfo, + message_civilian: MessageCivilian, +) -> None: + """ + Apply to world info for civilian. + + PARAMETERS + ---------- + world_info: WorldInfo + The world info to apply to. + standard_message: StandardMessage + The standard message to apply to world info. + """ + entity_id = message_civilian.get_civilian_entity_id() + if entity_id is None: + return + entity = world_info.get_entity(entity_id) + if entity is None: + civilian = Civilian(entity_id.get_value()) + if (hp := message_civilian.get_civilian_hp()) is not None: + civilian.set_hp(hp) + if (damage := message_civilian.get_civilian_damage()) is not None: + civilian.set_damage(damage) + if (buriedness := message_civilian.get_civilian_buriedness()) is not None: + civilian.set_buriedness(buriedness) + if (position := message_civilian.get_civilian_position()) is not None: + civilian.set_position(position) + world_info.add_entity(civilian) + else: + if isinstance(entity, Civilian): + if (hp := message_civilian.get_civilian_hp()) is not None: + entity.set_hp(hp) + if (damage := message_civilian.get_civilian_damage()) is not None: + entity.set_damage(damage) + if (buriedness := message_civilian.get_civilian_buriedness()) is not None: + entity.set_buriedness(buriedness) + if (position := message_civilian.get_civilian_position()) is not None: + entity.set_position(position) + + +def _apply_to_world_info_building( + world_info: WorldInfo, + message_building: MessageBuilding, +) -> None: + """ + Apply to world info for building. + + PARAMETERS + ---------- + world_info: WorldInfo + The world info to apply to. + standard_message: StandardMessage + The standard message to apply to world info. + """ + entity_id = message_building.get_building_entity_id() + if entity_id is None: + return + entity = world_info.get_entity(entity_id) + if entity is None: + building = Building(entity_id.get_value()) + if (fieryness := message_building.get_building_fireyness()) is not None: + building.set_fieryness(fieryness) + if (brokenness := message_building.get_building_brokenness()) is not None: + building.set_brokenness(brokenness) + if (temperature := message_building.get_building_temperature()) is not None: + building.set_temperature(temperature) + world_info.add_entity(building) + else: + if isinstance(entity, Building): + if (fieryness := message_building.get_building_fireyness()) is not None: + entity.set_fieryness(fieryness) + if (brokenness := message_building.get_building_brokenness()) is not None: + entity.set_brokenness(brokenness) + if (temperature := message_building.get_building_temperature()) is not None: + entity.set_temperature(temperature) + + +def _apply_to_world_info_road( + world_info: WorldInfo, + message_road: MessageRoad, +) -> None: + """ + Apply to world info for road. + + PARAMETERS + ---------- + world_info: WorldInfo + The world info to apply to. + standard_message: StandardMessage + The standard message to apply to world info. + """ + entity_id = message_road.get_road_entity_id() + if entity_id is None: + return + entity = world_info.get_entity(entity_id) + if not isinstance(entity, Road): + return + + blockade_entity_id = message_road.get_road_blockade_entity_id() + if blockade_entity_id is None: + return + + blockade = world_info.get_entity(blockade_entity_id) + if blockade is None: + road_blockade = Blockade(blockade_entity_id.get_value()) + if (repair_cost := message_road.get_road_blockade_repair_cost()) is not None: + road_blockade.set_repaire_cost(repair_cost) + if (x := message_road.get_road_blockade_x()) is not None: + road_blockade.set_x(x) + if (y := message_road.get_road_blockade_y()) is not None: + road_blockade.set_y(y) + world_info.add_entity(road_blockade) + else: + if isinstance(blockade, Blockade): + if ( + repair_cost := message_road.get_road_blockade_repair_cost() + ) is not None: + blockade.set_repaire_cost(repair_cost) + if (x := message_road.get_road_blockade_x()) is not None: + blockade.set_x(x) + if (y := message_road.get_road_blockade_y()) is not None: + blockade.set_y(y) diff --git a/adf_core_python/core/agent/communication/standard/utility/bitarray_with_exits_flag.py b/adf_core_python/core/agent/communication/standard/utility/bitarray_with_exits_flag.py new file mode 100644 index 00000000..64ab01b3 --- /dev/null +++ b/adf_core_python/core/agent/communication/standard/utility/bitarray_with_exits_flag.py @@ -0,0 +1,72 @@ +from typing import Optional + +from bitarray import bitarray + +IS_EXIST_FLAG = 1 +IS_NOT_EXIST_FLAG = 0 + + +def write_with_exist_flag( + bit_array: bitarray, value: Optional[int], bit_size: int +) -> None: + """ + Write value to bit_array with an exist flag. + If value is None, write IS_NOT_EXIST_FLAG to bit_array. + If value is not None, write IS_EXIST_FLAG to bit_array and then write value to bit_array. + + PARAMETERS + ---------- + bit_array: bitarray + The bitarray to write to. + value: Optional[int] + The value to write. + bit_size: int + The number of bits to use to write value. + + RAISES + ------ + ValueError + If value is too large to fit into bit_size bits. + """ + if value is None: + bit_array.extend([IS_NOT_EXIST_FLAG]) + else: + bit_array.extend([IS_EXIST_FLAG]) + bit_value = bitarray(f"{value:0{bit_size}b}") + if len(bit_value) > bit_size: + raise ValueError(f"Value {value} is too large to fit into {bit_size} bits") + bit_array.extend(bit_value) + + +def read_with_exist_flag(bit_array: bitarray, size: int) -> Optional[int]: + """ + Read value from bit_array with an exist flag. + If the first bit is IS_NOT_EXIST_FLAG, return None. + If the first bit is IS_EXIST_FLAG, read and return value from bit_array. + + PARAMETERS + ---------- + bit_array: bitarray + The bitarray to read from. + size: int + The number of bits to read to get value. + + RETURNS + ------- + Optional[int] + The value read from bit_array. + + RAISES + ------ + ValueError + If the first bit is not IS_EXIST_FLAG or IS_NOT_EXIST_FLAG. + """ + exist_flag = bit_array.pop(0) + if exist_flag == IS_NOT_EXIST_FLAG: + return None + elif exist_flag == IS_EXIST_FLAG: + value = int(bit_array[:size].to01(), 2) + del bit_array[:size] + return value + else: + raise ValueError("Invalid exist flag") diff --git a/adf_core_python/core/agent/info/agent_info.py b/adf_core_python/core/agent/info/agent_info.py index 79e8cf28..b3e78ee4 100644 --- a/adf_core_python/core/agent/info/agent_info.py +++ b/adf_core_python/core/agent/info/agent_info.py @@ -1,7 +1,9 @@ +from __future__ import annotations + from time import time -from typing import Any +from typing import TYPE_CHECKING, Any -from rcrs_core.agents.agent import Agent +from rcrs_core.commands.Command import Command from rcrs_core.entities.civilian import Civilian from rcrs_core.entities.entity import Entity from rcrs_core.entities.human import Human @@ -11,6 +13,9 @@ from adf_core_python.core.agent.action.action import Action +if TYPE_CHECKING: + from adf_core_python.core.agent.agent import Agent + class AgentInfo: # TODO: Replace Any with the actual type @@ -45,24 +50,24 @@ def get_time(self) -> int: """ return self._time - def set_heard_commands(self, heard_commands: list[Any]) -> None: + def set_heard_commands(self, heard_commands: list[Command]) -> None: """ Set the heard commands Parameters ---------- - heard_commands : list[Any] + heard_commands : list[Command] Heard commands """ self._heard_commands = heard_commands - def get_heard_commands(self) -> list[Any]: + def get_heard_commands(self) -> list[Command]: """ Get the heard commands Returns ------- - list[Any] + list[Command] Heard commands """ return self._heard_commands @@ -77,7 +82,7 @@ def get_entity_id(self) -> EntityID: Entity ID of the agent """ # TODO: Agent class should return EntityID instead of EntityID | None - return self._agent.get_id() # type: ignore + return self._agent.get_entity_id() def get_myself(self) -> Entity: """ diff --git a/adf_core_python/core/agent/info/scenario_info.py b/adf_core_python/core/agent/info/scenario_info.py index f8d35fab..85bf7dab 100644 --- a/adf_core_python/core/agent/info/scenario_info.py +++ b/adf_core_python/core/agent/info/scenario_info.py @@ -1,8 +1,10 @@ from enum import Enum -from typing import Any +from typing import TypeVar from adf_core_python.core.config.config import Config +T = TypeVar("T") + class Mode(Enum): NON_PRECOMPUTE = 0 @@ -21,7 +23,7 @@ class ScenarioInfoKeys: FIRE_TANK_REFILL_RATE = "fire.tank.refill_rate" KERNEL_TIMESTEPS = "kernel.timesteps" FIRE_EXTINGUISH_MAX_SUM = "fire.extinguish.max-sum" - COMMS_CHANNELS_MAX_PLATOON = "comms.channels.max.platoon" + COMMUNICATION_CHANNELS_MAX_PLATOON = "comms.channels.max.platoon" KERNEL_AGENTS_THINK_TIME = "kernel.agents.think-time" FIRE_TANK_MAXIMUM = "fire.tank.maximum" CLEAR_REPAIR_RATE = "clear.repair.rate" @@ -34,11 +36,11 @@ class ScenarioInfoKeys: KERNEL_COMMUNICATION_MODEL = "kernel.communication-model" PERCEPTION_LOS_PRECISION_DAMAGE = "perception.los.precision.damage" SCENARIO_AGENTS_AC = "scenario.agents.ac" - COMMS_CHANNELS_MAX_OFFICE = "comms.channels.max.centre" + COMMUNICATION_CHANNELS_MAX_OFFICE = "comms.channels.max.centre" FIRE_EXTINGUISH_MAX_DISTANCE = "fire.extinguish.max-distance" KERNEL_AGENTS_IGNOREUNTIL = "kernel.agents.ignoreuntil" CLEAR_REPAIR_DISTANCE = "clear.repair.distance" - COMMS_CHANNELS_COUNT = "comms.channels.count" + COMMUNICATION_CHANNELS_COUNT = "comms.channels.count" class ScenarioInfo: @@ -89,7 +91,7 @@ def get_mode(self) -> Mode: """ return self._mode - def get_value(self, key: str, default: Any) -> Any: + def get_value(self, key: str, default: T) -> T: """ Get the value of the configuration @@ -105,4 +107,11 @@ def get_value(self, key: str, default: Any) -> Any: Any Value of the configuration """ - return self._config.get_value(key, default) + value = self._config.get_value(key, default) + if not isinstance(value, type(default)): + try: + return type(default)(value) # type: ignore + except (ValueError, TypeError): + # 型変換に失敗した場合はそのままデフォルト値を返す + return default + return value diff --git a/adf_core_python/core/agent/info/world_info.py b/adf_core_python/core/agent/info/world_info.py index 223bfb14..5bd66761 100644 --- a/adf_core_python/core/agent/info/world_info.py +++ b/adf_core_python/core/agent/info/world_info.py @@ -171,3 +171,14 @@ def get_bloackades(self, area: Area) -> set[Blockade]: if isinstance(bloackde_entity, Blockade): bloakcades.add(cast(Blockade, bloackde_entity)) return bloakcades + + def add_entity(self, entity: Entity) -> None: + """ + Add the entity + + Parameters + ---------- + entity : Entity + Entity + """ + self._world_model.add_entity(entity) diff --git a/adf_core_python/core/agent/module/module_manager.py b/adf_core_python/core/agent/module/module_manager.py index b15dd8e1..7609e62a 100644 --- a/adf_core_python/core/agent/module/module_manager.py +++ b/adf_core_python/core/agent/module/module_manager.py @@ -4,6 +4,12 @@ from typing import TYPE_CHECKING, Any from adf_core_python.core.component.action.extend_action import ExtendAction +from adf_core_python.core.component.communication.channel_subscriber import ( + ChannelSubscriber, +) +from adf_core_python.core.component.communication.message_coordinator import ( + MessageCoordinator, +) from adf_core_python.core.component.module.abstract_module import AbstractModule if TYPE_CHECKING: @@ -92,6 +98,58 @@ def get_extend_action( raise RuntimeError(f"Action {class_name} is not a subclass of ExtendAction") + def get_channel_subscriber( + self, channel_subscriber_name: str, default_channel_subscriber_name: str + ) -> ChannelSubscriber: + class_name = self._module_config.get_value_or_default( + channel_subscriber_name, default_channel_subscriber_name + ) + + try: + channel_subscriber_class: type = self._load_module(class_name) + except (ImportError, AttributeError) as e: + raise RuntimeError(f"Failed to load channel subscriber {class_name}") from e + + instance = self._channel_subscribers.get(channel_subscriber_name) + if instance is not None: + return instance + + if issubclass(channel_subscriber_class, ChannelSubscriber): + instance = channel_subscriber_class() + self._channel_subscribers[channel_subscriber_name] = instance + return instance + + raise RuntimeError( + f"Channel subscriber {class_name} is not a subclass of ChannelSubscriber" + ) + + def get_message_coordinator( + self, message_coordinator_name: str, default_message_coordinator_name: str + ) -> MessageCoordinator: + class_name = self._module_config.get_value_or_default( + message_coordinator_name, default_message_coordinator_name + ) + + try: + message_coordinator_class: type = self._load_module(class_name) + except (ImportError, AttributeError) as e: + raise RuntimeError( + f"Failed to load message coordinator {class_name}" + ) from e + + instance = self._message_coordinators.get(message_coordinator_name) + if instance is not None: + return instance + + if issubclass(message_coordinator_class, MessageCoordinator): + instance = message_coordinator_class() + self._message_coordinators[message_coordinator_name] = instance + return instance + + raise RuntimeError( + f"Message coordinator {class_name} is not a subclass of MessageCoordinator" + ) + def _load_module(self, class_name: str) -> type: module_name, module_class_name = class_name.rsplit(".", 1) module = importlib.import_module(module_name) diff --git a/adf_core_python/core/agent/platoon/platoon.py b/adf_core_python/core/agent/platoon/platoon.py index 6ffcd020..098945f2 100644 --- a/adf_core_python/core/agent/platoon/platoon.py +++ b/adf_core_python/core/agent/platoon/platoon.py @@ -1,20 +1,12 @@ -# from rcrs_core.agents.agent import Agent -from rcrs_core.commands.Command import Command -from rcrs_core.config.config import Config as RCRSConfig -from rcrs_core.worldmodel.changeSet import ChangeSet - from adf_core_python.core.agent.action.action import Action from adf_core_python.core.agent.agent import Agent from adf_core_python.core.agent.communication.message_manager import MessageManager from adf_core_python.core.agent.config.module_config import ModuleConfig from adf_core_python.core.agent.develop.develop_data import DevelopData -from adf_core_python.core.agent.info.agent_info import AgentInfo -from adf_core_python.core.agent.info.scenario_info import Mode, ScenarioInfo -from adf_core_python.core.agent.info.world_info import WorldInfo +from adf_core_python.core.agent.info.scenario_info import Mode from adf_core_python.core.agent.module.module_manager import ModuleManager from adf_core_python.core.agent.precompute.precompute_data import PrecomputeData from adf_core_python.core.component.tactics.tactics_agent import TacticsAgent -from adf_core_python.core.config.config import Config from adf_core_python.core.logger.logger import get_agent_logger @@ -29,7 +21,15 @@ def __init__( module_config: ModuleConfig, develop_data: DevelopData, ) -> None: - super().__init__(is_precompute, self.__class__.__qualname__) + super().__init__( + is_precompute, + self.__class__.__qualname__, + is_debug, + team_name, + data_storage_name, + module_config, + develop_data, + ) self._tactics_agent = tactics_agent self._team_name = team_name self._is_precompute = is_precompute @@ -39,39 +39,14 @@ def __init__( self._develop_data = develop_data def post_connect(self) -> None: - self._agent_info: AgentInfo = AgentInfo(self, self.world_model) - self._world_info: WorldInfo = WorldInfo(self.world_model) - self._precompute_data: PrecomputeData = PrecomputeData(self._data_storage_name) + super().post_connect() + self.precompute_data: PrecomputeData = PrecomputeData(self._data_storage_name) self._logger = get_agent_logger( f"{self.__class__.__module__}.{self.__class__.__qualname__}", self._agent_info, ) - if self._is_precompute: - self._mode = Mode.PRECOMPUTATION - else: - # if self._precompute_data.is_ready(): - # self._mode = Mode.PRECOMPUTED - # else: - # self._mode = Mode.NON_PRECOMPUTE - self._mode = Mode.NON_PRECOMPUTE - - config = Config() - if self.config is not None: - rcrc_config: RCRSConfig = self.config - for key, value in rcrc_config.data.items(): # type: ignore - config.set_value(key, value) - for key, value in rcrc_config.int_data.items(): # type: ignore - config.set_value(key, value) - for key, value in rcrc_config.float_data.items(): # type: ignore - config.set_value(key, value) - for key, value in rcrc_config.boolean_data.items(): # type: ignore - config.set_value(key, value) - for key, value in rcrc_config.array_data.items(): # type: ignore - config.set_value(key, value) - - self._scenario_info: ScenarioInfo = ScenarioInfo(config, self._mode) self._module_manager: ModuleManager = ModuleManager( self._agent_info, self._world_info, @@ -80,17 +55,30 @@ def post_connect(self) -> None: self._develop_data, ) + self._message_manager.set_channel_subscriber( + self._module_manager.get_channel_subscriber( + "MessageManager.PlatoonChannelSubscriber", + "adf_core_python.implement.module.communication.default_channel_subscriber.DefaultChannelSubscriber", + ) + ) + self._message_manager.set_message_coordinator( + self._module_manager.get_message_coordinator( + "MessageManager.PlatoonMessageCoordinator", + "adf_core_python.implement.module.communication.default_message_coordinator.DefaultMessageCoordinator", + ) + ) + self._tactics_agent.initialize( self._agent_info, self._world_info, self._scenario_info, self._module_manager, self._precompute_data, - MessageManager(), + self._message_manager, self._develop_data, ) - match self._mode: + match self._scenario_info.get_mode(): case Mode.PRECOMPUTATION: pass case Mode.PRECOMPUTED: @@ -101,25 +89,24 @@ def post_connect(self) -> None: self._world_info, self._scenario_info, self._module_manager, - self._precompute_data, + self.precompute_data, self._develop_data, ) - def think(self, time: int, change_set: ChangeSet, hear: list[Command]) -> None: - self._agent_info.set_change_set(change_set) - self._world_info.set_change_set(change_set) - self._agent_info.set_time(time) - self._agent_info.set_heard_commands(hear) - + def think(self) -> None: action: Action = self._tactics_agent.think( self._agent_info, self._world_info, self._scenario_info, self._module_manager, self._precompute_data, - MessageManager(), + self._message_manager, self._develop_data, ) if action is not None and self.agent_id is not None: - self._agent_info.set_executed_action(time, action) - self.send_msg(action.get_command(self.agent_id, time).prepare_cmd()) + self._agent_info.set_executed_action(self._agent_info.get_time(), action) + self.send_msg( + action.get_command( + self.agent_id, self._agent_info.get_time() + ).prepare_cmd() + ) diff --git a/adf_core_python/core/component/communication/__init__.py b/adf_core_python/core/component/communication/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/component/communication/channel_subscriber.py b/adf_core_python/core/component/communication/channel_subscriber.py index 7b4ee895..d2da83f2 100644 --- a/adf_core_python/core/component/communication/channel_subscriber.py +++ b/adf_core_python/core/component/communication/channel_subscriber.py @@ -1,9 +1,12 @@ +from __future__ import annotations + from abc import ABC, abstractmethod +from typing import TYPE_CHECKING -from adf_core_python.core.agent.communication.message_manager import MessageManager -from adf_core_python.core.agent.info.agent_info import AgentInfo -from adf_core_python.core.agent.info.scenario_info import ScenarioInfo -from adf_core_python.core.agent.info.world_info import WorldInfo +if TYPE_CHECKING: + from adf_core_python.core.agent.info.agent_info import AgentInfo + from adf_core_python.core.agent.info.scenario_info import ScenarioInfo + from adf_core_python.core.agent.info.world_info import WorldInfo class ChannelSubscriber(ABC): @@ -13,8 +16,7 @@ def subscribe( agent_info: AgentInfo, world_info: WorldInfo, scenario_info: ScenarioInfo, - message_manager: MessageManager, - ) -> None: + ) -> list[int]: """ Subscribe to the channel. @@ -26,7 +28,10 @@ def subscribe( The world info. scenario_info : ScenarioInfo The scenario info. - message_manager : MessageManager - The message manager. + + Returns + ------- + list[int] + The list of subscribed channels. """ pass diff --git a/adf_core_python/core/component/communication/communication_message.py b/adf_core_python/core/component/communication/communication_message.py index a6cd25d0..0760ac0f 100644 --- a/adf_core_python/core/component/communication/communication_message.py +++ b/adf_core_python/core/component/communication/communication_message.py @@ -1,5 +1,9 @@ +from __future__ import annotations + from abc import ABC, abstractmethod +from bitarray import bitarray + class CommunicationMessage(ABC): def __init__(self, is_wireless_message: bool) -> None: @@ -9,15 +13,13 @@ def is_wireless_message(self) -> bool: return self._is_wireless_message @abstractmethod - def get_byte_size(self) -> int: + def get_bit_size(self) -> int: raise NotImplementedError @abstractmethod - def to_bytes(self) -> bytes: + def to_bits(self) -> bitarray: raise NotImplementedError @abstractmethod - def get_check_key(self) -> str: + def __hash__(self): raise NotImplementedError - - # TODO: Implement the toBitOutputStream and getCheckKey methods diff --git a/adf_core_python/core/component/communication/communication_module.py b/adf_core_python/core/component/communication/communication_module.py index c1b957e7..2e87e31c 100644 --- a/adf_core_python/core/component/communication/communication_module.py +++ b/adf_core_python/core/component/communication/communication_module.py @@ -1,8 +1,11 @@ -from abc import ABC, abstractmethod +from __future__ import annotations -from rcrs_core.agents.agent import Agent +from abc import ABC, abstractmethod +from typing import TYPE_CHECKING -from adf_core_python.core.agent.communication.message_manager import MessageManager +if TYPE_CHECKING: + from adf_core_python.core.agent.agent import Agent + from adf_core_python.core.agent.communication.message_manager import MessageManager class CommunicationModule(ABC): diff --git a/adf_core_python/core/component/communication/message_coordinator.py b/adf_core_python/core/component/communication/message_coordinator.py index d7490501..9d8cb1be 100644 --- a/adf_core_python/core/component/communication/message_coordinator.py +++ b/adf_core_python/core/component/communication/message_coordinator.py @@ -1,12 +1,16 @@ +from __future__ import annotations + from abc import ABC, abstractmethod +from typing import TYPE_CHECKING -from adf_core_python.core.agent.communication.message_manager import MessageManager -from adf_core_python.core.agent.info.agent_info import AgentInfo -from adf_core_python.core.agent.info.scenario_info import ScenarioInfo -from adf_core_python.core.agent.info.world_info import WorldInfo -from adf_core_python.core.component.communication.communication_message import ( - CommunicationMessage, -) +if TYPE_CHECKING: + from adf_core_python.core.agent.communication.message_manager import MessageManager + from adf_core_python.core.agent.info.agent_info import AgentInfo + from adf_core_python.core.agent.info.scenario_info import ScenarioInfo + from adf_core_python.core.agent.info.world_info import WorldInfo + from adf_core_python.core.component.communication.communication_message import ( + CommunicationMessage, + ) class MessageCoordinator(ABC): diff --git a/adf_core_python/core/launcher/connect/component_launcher.py b/adf_core_python/core/launcher/connect/component_launcher.py index 027bb85f..56a142ce 100644 --- a/adf_core_python/core/launcher/connect/component_launcher.py +++ b/adf_core_python/core/launcher/connect/component_launcher.py @@ -1,8 +1,8 @@ import socket -from rcrs_core.agents.agent import Agent from structlog import BoundLogger +from adf_core_python.core.agent.agent import Agent from adf_core_python.core.launcher.connect.connection import Connection @@ -17,7 +17,7 @@ def make_connection(self) -> Connection: return Connection(self.host, self.port) def connect(self, agent: Agent, _request_id: int) -> None: - self.logger.bind(agent_id=agent.get_id()) + # self.logger.bind(agent_id=agent.get_id()) self.logger.info( f"{agent.__class__.__name__} connecting to {self.host}:{self.port} request_id: {_request_id}" @@ -33,8 +33,10 @@ def connect(self, agent: Agent, _request_id: int) -> None: except socket.timeout: self.logger.warning(f"Connection to {self.host}:{self.port} timed out") return - except socket.error: - self.logger.error(f"Failed to connect to {self.host}:{self.port}") + except socket.error as e: + self.logger.exception( + f"Failed to connect to {self.host}:{self.port}", exception=str(e) + ) return connection.message_received(agent.message_received) @@ -44,7 +46,10 @@ def connect(self, agent: Agent, _request_id: int) -> None: try: connection.parse_message_from_kernel() except Exception as e: - self.logger.error(f"Failed to connect agent: {self.host}:{self.port} {e}") + self.logger.exception( + f"Failed to connect agent: {self.host}:{self.port} {e}", + exception=str(e), + ) def generate_request_id(self) -> int: self.request_id += 1 diff --git a/adf_core_python/core/launcher/connect/connector_ambulance_centre.py b/adf_core_python/core/launcher/connect/connector_ambulance_centre.py index 01949183..8004fb9d 100644 --- a/adf_core_python/core/launcher/connect/connector_ambulance_centre.py +++ b/adf_core_python/core/launcher/connect/connector_ambulance_centre.py @@ -52,6 +52,7 @@ def connect( ), ) + request_id: int = component_launcher.generate_request_id() # TODO: component_launcher.generate_request_ID can cause race condition thread = threading.Thread( target=component_launcher.connect, @@ -59,8 +60,9 @@ def connect( AmbulanceCenterAgent( config.get_value(ConfigKey.KEY_PRECOMPUTE, False), ), # type: ignore - component_launcher.generate_request_id(), + request_id, ), + name=f"AmbulanceCentreAgent-{request_id}", ) threads.append(thread) diff --git a/adf_core_python/core/launcher/connect/connector_ambulance_team.py b/adf_core_python/core/launcher/connect/connector_ambulance_team.py index 15da390c..350d6bd8 100644 --- a/adf_core_python/core/launcher/connect/connector_ambulance_team.py +++ b/adf_core_python/core/launcher/connect/connector_ambulance_team.py @@ -53,6 +53,7 @@ def connect( ), ) + request_id: int = component_launcher.generate_request_id() thread = threading.Thread( target=component_launcher.connect, args=( @@ -65,8 +66,9 @@ def connect( module_config, develop_data, ), - component_launcher.generate_request_id(), + request_id, ), + name=f"AmbulanceTeam-{request_id}", ) threads.append(thread) diff --git a/adf_core_python/core/launcher/connect/connector_fire_brigade.py b/adf_core_python/core/launcher/connect/connector_fire_brigade.py index fab7095e..9fc24aa7 100644 --- a/adf_core_python/core/launcher/connect/connector_fire_brigade.py +++ b/adf_core_python/core/launcher/connect/connector_fire_brigade.py @@ -51,6 +51,7 @@ def connect( ), ) + request_id: int = component_launcher.generate_request_id() thread = threading.Thread( target=component_launcher.connect, args=( @@ -63,8 +64,9 @@ def connect( module_config, develop_data, ), - component_launcher.generate_request_id(), + request_id, ), + name=f"FireBrigadeAgent-{request_id}", ) threads.append(thread) diff --git a/adf_core_python/core/launcher/connect/connector_fire_station.py b/adf_core_python/core/launcher/connect/connector_fire_station.py index 49bd190a..cd5632e4 100644 --- a/adf_core_python/core/launcher/connect/connector_fire_station.py +++ b/adf_core_python/core/launcher/connect/connector_fire_station.py @@ -52,15 +52,16 @@ def connect( ), ) - # TODO: component_launcher.generate_request_ID can cause race condition + request_id: int = component_launcher.generate_request_id() thread = threading.Thread( target=component_launcher.connect, args=( FireStationAgent( config.get_value(ConfigKey.KEY_PRECOMPUTE, False), ), # type: ignore - component_launcher.generate_request_id(), + request_id, ), + name=f"FireStationAgent-{request_id}", ) threads.append(thread) diff --git a/adf_core_python/core/launcher/connect/connector_police_force.py b/adf_core_python/core/launcher/connect/connector_police_force.py index bbf93596..2b3a905d 100644 --- a/adf_core_python/core/launcher/connect/connector_police_force.py +++ b/adf_core_python/core/launcher/connect/connector_police_force.py @@ -51,6 +51,7 @@ def connect( ), ) + request_id: int = component_launcher.generate_request_id() thread = threading.Thread( target=component_launcher.connect, args=( @@ -63,8 +64,9 @@ def connect( module_config, develop_data, ), - component_launcher.generate_request_id(), + request_id, ), + name=f"PoliceForceAgent-{request_id}", ) threads.append(thread) diff --git a/adf_core_python/core/launcher/connect/connector_police_office.py b/adf_core_python/core/launcher/connect/connector_police_office.py index 32e90607..561b9872 100644 --- a/adf_core_python/core/launcher/connect/connector_police_office.py +++ b/adf_core_python/core/launcher/connect/connector_police_office.py @@ -1,3 +1,4 @@ +import re import threading from rcrs_core.agents.policeOfficeAgent import PoliceOfficeAgent @@ -52,15 +53,16 @@ def connect( ), ) - # TODO: component_launcher.generate_request_ID can cause race condition + request_id: int = component_launcher.generate_request_id() thread = threading.Thread( target=component_launcher.connect, args=( PoliceOfficeAgent( config.get_value(ConfigKey.KEY_PRECOMPUTE, False), ), # type: ignore - component_launcher.generate_request_id(), + request_id, ), + name=f"PoliceOfficeAgent-{request_id}", ) threads.append(thread) diff --git a/adf_core_python/implement/module/communication/default_channel_subscriber.py b/adf_core_python/implement/module/communication/default_channel_subscriber.py new file mode 100644 index 00000000..d195c9a8 --- /dev/null +++ b/adf_core_python/implement/module/communication/default_channel_subscriber.py @@ -0,0 +1,101 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +from rcrs_core.connection.URN import Entity as EntityURN + +from adf_core_python.core.agent.info.scenario_info import ScenarioInfoKeys +from adf_core_python.core.component.communication.channel_subscriber import ( + ChannelSubscriber, +) + +if TYPE_CHECKING: + from adf_core_python.core.agent.info.agent_info import AgentInfo + from adf_core_python.core.agent.info.scenario_info import ScenarioInfo + from adf_core_python.core.agent.info.world_info import WorldInfo + + +class DefaultChannelSubscriber(ChannelSubscriber): + def subscribe( + self, + agent_info: AgentInfo, + world_info: WorldInfo, + scenario_info: ScenarioInfo, + ) -> list[int]: + agent = world_info.get_entity(agent_info.get_entity_id()) + if agent is None: + return [] + + agent_type = agent.get_urn() + + number_of_channels: int = ( + scenario_info.get_value(ScenarioInfoKeys.COMMUNICATION_CHANNELS_COUNT, 1) + - 1 + ) + + is_platoon: bool = ( + agent_type == EntityURN.FIRE_BRIGADE + or agent_type == EntityURN.POLICE_FORCE + or agent_type == EntityURN.AMBULANCE_TEAM + ) + + max_channel_count: int = ( + scenario_info.get_value( + ScenarioInfoKeys.COMMUNICATION_CHANNELS_MAX_PLATOON, 1 + ) + if is_platoon + else scenario_info.get_value( + ScenarioInfoKeys.COMMUNICATION_CHANNELS_MAX_OFFICE, 1 + ) + ) + + channels = [ + self.get_channel_number(agent_type, i, number_of_channels) + for i in range(max_channel_count) + ] + return channels + + @staticmethod + def get_channel_number( + agent_type: EntityURN, channel_index: int, number_of_channels: int + ) -> int: + agent_index = 0 + if agent_type == EntityURN.FIRE_BRIGADE or agent_type == EntityURN.FIRE_STATION: + agent_index = 1 + elif ( + agent_type == EntityURN.POLICE_FORCE + or agent_type == EntityURN.POLICE_OFFICE + ): + agent_index = 2 + elif ( + agent_type == EntityURN.AMBULANCE_TEAM + or agent_type == EntityURN.AMBULANCE_CENTRE + ): + agent_index = 3 + + index = (3 * channel_index) + agent_index + if (index % number_of_channels) == 0: + index = number_of_channels + else: + index = index % number_of_channels + return index + + +if __name__ == "__main__": + num_channels = 1 + max_channels = 2 + + for i in range(max_channels): + print( + f"FIREBRIGADE-{i}: {DefaultChannelSubscriber.get_channel_number(EntityURN.FIRE_BRIGADE, i, num_channels)}" + ) + + for i in range(max_channels): + print( + f"POLICE-{i}: {DefaultChannelSubscriber.get_channel_number(EntityURN.POLICE_OFFICE, i, num_channels)}" + ) + + for i in range(max_channels): + print( + f"AMB-{i}: {DefaultChannelSubscriber.get_channel_number(EntityURN.AMBULANCE_CENTRE, i, num_channels)}" + ) diff --git a/adf_core_python/implement/module/communication/default_message_coordinator.py b/adf_core_python/implement/module/communication/default_message_coordinator.py new file mode 100644 index 00000000..2e612645 --- /dev/null +++ b/adf_core_python/implement/module/communication/default_message_coordinator.py @@ -0,0 +1,222 @@ +from rcrs_core.connection.URN import Entity as EntityURN + +from adf_core_python.core.agent.communication.standard.bundle.information.message_ambulance_team import ( + MessageAmbulanceTeam, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_building import ( + MessageBuilding, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_civilian import ( + MessageCivilian, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_fire_brigade import ( + MessageFireBrigade, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_police_force import ( + MessagePoliceForce, +) +from adf_core_python.core.agent.communication.standard.bundle.information.message_road import ( + MessageRoad, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message import ( + StandardMessage, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) +from adf_core_python.core.agent.info.agent_info import AgentInfo +from adf_core_python.core.agent.info.scenario_info import ScenarioInfo, ScenarioInfoKeys +from adf_core_python.core.agent.info.world_info import WorldInfo +from adf_core_python.core.component.communication.message_coordinator import ( + MessageCoordinator, +) +from adf_core_python.implement.module.communication.default_channel_subscriber import ( + DefaultChannelSubscriber, +) + + +class DefaultMessageCoordinator(MessageCoordinator): + def coordinate( + self, + agent_info, + world_info, + scenario_info, + message_manager, + send_message_list, + channel_send_message_list, + ): + police_messages = [] + ambulance_messages = [] + fire_brigade_messages = [] + voice_messages = [] + + agent_type = self.get_agent_type(agent_info, world_info) + + for msg in send_message_list: + if isinstance(msg, StandardMessage) and not msg.is_wireless_message(): + voice_messages.append(msg) + else: + if isinstance(msg, MessageBuilding): + fire_brigade_messages.append(msg) + elif isinstance(msg, MessageCivilian): + ambulance_messages.append(msg) + elif isinstance(msg, MessageRoad): + fire_brigade_messages.append(msg) + ambulance_messages.append(msg) + police_messages.append(msg) + # elif isinstance(msg, CommandAmbulance): + # ambulance_messages.append(msg) + # elif isinstance(msg, CommandFire): + # fire_brigade_messages.append(msg) + # elif isinstance(msg, CommandPolice): + # police_messages.append(msg) + # elif isinstance(msg, CommandScout): + # if agent_type == EntityURN.FIRE_STATION: + # fire_brigade_messages.append(msg) + # elif agent_type == EntityURN.POLICE_OFFICE: + # police_messages.append(msg) + # elif agent_type == EntityURN.AMBULANCE_CENTRE: + # ambulance_messages.append(msg) + # elif isinstance(msg, MessageReport): + # if agent_type == EntityURN.FIRE_BRIGADE: + # fire_brigade_messages.append(msg) + # elif agent_type == EntityURN.POLICE_FORCE: + # police_messages.append(msg) + # elif agent_type == EntityURN.AMBULANCE_TEAM: + # ambulance_messages.append(msg) + elif isinstance(msg, MessageFireBrigade): + fire_brigade_messages.append(msg) + ambulance_messages.append(msg) + police_messages.append(msg) + elif isinstance(msg, MessagePoliceForce): + ambulance_messages.append(msg) + police_messages.append(msg) + elif isinstance(msg, MessageAmbulanceTeam): + ambulance_messages.append(msg) + police_messages.append(msg) + + if int(scenario_info.get_value("comms.channels.count", 1)) > 1: + channel_size = [0] * ( + int(scenario_info.get_value("comms.channels.count", 1)) + ) + self.set_send_messages( + scenario_info, + EntityURN.POLICE_FORCE, + agent_info, + world_info, + police_messages, + channel_send_message_list, + channel_size, + ) + self.set_send_messages( + scenario_info, + EntityURN.AMBULANCE_TEAM, + agent_info, + world_info, + ambulance_messages, + channel_send_message_list, + channel_size, + ) + self.set_send_messages( + scenario_info, + EntityURN.FIRE_BRIGADE, + agent_info, + world_info, + fire_brigade_messages, + channel_send_message_list, + channel_size, + ) + + voice_message_low_list = [] + voice_message_normal_list = [] + voice_message_high_list = [] + + for msg in voice_messages: + if isinstance(msg, StandardMessage): + if msg.get_priority() == StandardMessagePriority.LOW: + voice_message_low_list.append(msg) + elif msg.get_priority() == StandardMessagePriority.NORMAL: + voice_message_normal_list.append(msg) + elif msg.get_priority() == StandardMessagePriority.HIGH: + voice_message_high_list.append(msg) + + channel_send_message_list[0].extend(voice_message_high_list) + channel_send_message_list[0].extend(voice_message_normal_list) + channel_send_message_list[0].extend(voice_message_low_list) + + def get_channels_by_agent_type( + self, + agent_type, + agent_info: AgentInfo, + world_info: WorldInfo, + scenario_info: ScenarioInfo, + ): + num_channels = ( + scenario_info.get_value(ScenarioInfoKeys.COMMUNICATION_CHANNELS_COUNT, 1) + - 1 + ) + max_channel_count = int( + # scenario_info.get_comms_channels_max_platoon() + scenario_info.get_value( + ScenarioInfoKeys.COMMUNICATION_CHANNELS_MAX_PLATOON, 1 + ) + if self.is_platoon_agent(agent_info, world_info) + else scenario_info.get_value( + ScenarioInfoKeys.COMMUNICATION_CHANNELS_MAX_OFFICE, 1 + ) + ) + channels = [ + DefaultChannelSubscriber.get_channel_number(agent_type, i, num_channels) + for i in range(max_channel_count) + ] + return channels + + def is_platoon_agent(self, agent_info, world_info): + agent_type = self.get_agent_type(agent_info, world_info) + return agent_type in [ + EntityURN.FIRE_BRIGADE, + EntityURN.POLICE_FORCE, + EntityURN.AMBULANCE_TEAM, + ] + + def get_agent_type(self, agent_info: AgentInfo, world_info: WorldInfo): + entity = world_info.get_entity(agent_info.get_entity_id()) + if entity is None: + return None + return entity.get_urn() + + def set_send_messages( + self, + scenario_info: ScenarioInfo, + agent_type: EntityURN, + agent_info: AgentInfo, + world_info: WorldInfo, + messages: list[StandardMessage], + channel_send_message_list, + channel_size, + ): + channels = self.get_channels_by_agent_type( + agent_type, agent_info, world_info, scenario_info + ) + channel_capacities = [ + scenario_info.get_value("comms.channels." + str(channel) + ".bandwidth", 0) + for channel in range( + scenario_info.get_value( + ScenarioInfoKeys.COMMUNICATION_CHANNELS_COUNT, 1 + ) + ) + ] + + sorted_messages = sorted( + messages, key=lambda x: x.get_priority().value, reverse=True + ) + + for message in sorted_messages: + for channel in channels: + if message not in channel_send_message_list[channel] and ( + (channel_size[channel] + message.get_bit_size()) + <= channel_capacities[channel] + ): + channel_size[channel] += message.get_bit_size() + channel_send_message_list[channel].append(message) + break diff --git a/adf_core_python/implement/tactics/default_tactics_ambulance_team.py b/adf_core_python/implement/tactics/default_tactics_ambulance_team.py index 3154107f..7a30dee8 100644 --- a/adf_core_python/implement/tactics/default_tactics_ambulance_team.py +++ b/adf_core_python/implement/tactics/default_tactics_ambulance_team.py @@ -5,6 +5,24 @@ from adf_core_python.core.agent.action.action import Action from adf_core_python.core.agent.action.common.action_rest import ActionRest from adf_core_python.core.agent.communication.message_manager import MessageManager +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_ambulance import ( + CommandAmbulance, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_fire import ( + CommandFire, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_police import ( + CommandPolice, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_scout import ( + CommandScout, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.message_report import ( + CommandReport, +) +from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( + StandardMessagePriority, +) from adf_core_python.core.agent.develop.develop_data import DevelopData from adf_core_python.core.agent.info.agent_info import AgentInfo from adf_core_python.core.agent.info.scenario_info import Mode, ScenarioInfo @@ -119,6 +137,61 @@ def think( agent: AmbulanceTeamEntity = cast(AmbulanceTeamEntity, agent_info.get_myself()) # noqa: F841 entity_id = agent_info.get_entity_id() # noqa: F841 + message_manager.add_message( + CommandAmbulance( + False, + entity_id, + entity_id, + CommandAmbulance.ACTION_REST, + StandardMessagePriority.NORMAL, + entity_id, + ) + ) + message_manager.add_message( + CommandFire( + False, + entity_id, + entity_id, + CommandFire.ACTION_REST, + StandardMessagePriority.NORMAL, + entity_id, + ) + ) + message_manager.add_message( + CommandPolice( + False, + entity_id, + entity_id, + CommandPolice.ACTION_REST, + StandardMessagePriority.NORMAL, + entity_id, + ) + ) + message_manager.add_message( + CommandScout( + False, + entity_id, + entity_id, + 20000, + StandardMessagePriority.NORMAL, + entity_id, + ) + ) + message_manager.add_message( + CommandReport( + False, + True, + True, + entity_id, + StandardMessagePriority.NORMAL, + ) + ) + + self._logger.debug( + f"received messages: {[str(message) for message in message_manager.get_received_message_list()]}, help: {message_manager.get_heard_agent_help_message_count()}", + message_manager=message_manager, + ) + target_entity_id = self._human_detector.calculate().get_target_entity_id() self._logger.debug( f"human detector target_entity_id: {target_entity_id}", diff --git a/config/launcher.yaml b/config/launcher.yaml index 3d642721..d69a51b2 100644 --- a/config/launcher.yaml +++ b/config/launcher.yaml @@ -21,11 +21,11 @@ adf: team: platoon: ambulance: - count: 100 + count: 1 fire: - count: 100 + count: 0 police: - count: 100 + count: 0 office: ambulance: count: -1 diff --git a/config/module.yaml b/config/module.yaml index a265bde4..b4fbba11 100644 --- a/config/module.yaml +++ b/config/module.yaml @@ -106,11 +106,10 @@ SampleSearch: # ExtendActionClear: adf_core_python.implement.action.DefaultExtendActionClear # ## MessageManager -# MessageManager: -# PlatoonChannelSubscriber: adf_core_python.implement.module.comm.DefaultChannelSubscriber -# CenterChannelSubscriber: adf_core_python.implement.module.comm.DefaultChannelSubscriber -# PlatoonMessageCoordinator: adf_core_python.implement.module.comm.DefaultMessageCoordinator -# CenterMessageCoordinator: adf_core_python.implement.module.comm.DefaultMessageCoordinator - +MessageManager: + PlatoonChannelSubscriber: adf_core_python.implement.module.communication.default_channel_subscriber.DefaultChannelSubscriber + CenterChannelSubscriber: adf_core_python.implement.module.communication.default_channel_subscriber.DefaultChannelSubscriber + PlatoonMessageCoordinator: adf_core_python.implement.module.communication.default_message_coordinator.DefaultMessageCoordinator + CenterMessageCoordinator: adf_core_python.implement.module.communication.default_message_coordinator.DefaultMessageCoordinator # ## VisualDebug # VisualDebug: true diff --git a/poetry.lock b/poetry.lock index c0b7ea81..249bcc8a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -255,75 +255,77 @@ files = [ [[package]] name = "numpy" -version = "2.1.2" +version = "2.1.3" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" files = [ - {file = "numpy-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30d53720b726ec36a7f88dc873f0eec8447fbc93d93a8f079dfac2629598d6ee"}, - {file = "numpy-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d3ca0a72dd8846eb6f7dfe8f19088060fcb76931ed592d29128e0219652884"}, - {file = "numpy-2.1.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:fc44e3c68ff00fd991b59092a54350e6e4911152682b4782f68070985aa9e648"}, - {file = "numpy-2.1.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:7c1c60328bd964b53f8b835df69ae8198659e2b9302ff9ebb7de4e5a5994db3d"}, - {file = "numpy-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6cdb606a7478f9ad91c6283e238544451e3a95f30fb5467fbf715964341a8a86"}, - {file = "numpy-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d666cb72687559689e9906197e3bec7b736764df6a2e58ee265e360663e9baf7"}, - {file = "numpy-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6eef7a2dbd0abfb0d9eaf78b73017dbfd0b54051102ff4e6a7b2980d5ac1a03"}, - {file = "numpy-2.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:12edb90831ff481f7ef5f6bc6431a9d74dc0e5ff401559a71e5e4611d4f2d466"}, - {file = "numpy-2.1.2-cp310-cp310-win32.whl", hash = "sha256:a65acfdb9c6ebb8368490dbafe83c03c7e277b37e6857f0caeadbbc56e12f4fb"}, - {file = "numpy-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:860ec6e63e2c5c2ee5e9121808145c7bf86c96cca9ad396c0bd3e0f2798ccbe2"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b42a1a511c81cc78cbc4539675713bbcf9d9c3913386243ceff0e9429ca892fe"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:faa88bc527d0f097abdc2c663cddf37c05a1c2f113716601555249805cf573f1"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:c82af4b2ddd2ee72d1fc0c6695048d457e00b3582ccde72d8a1c991b808bb20f"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:13602b3174432a35b16c4cfb5de9a12d229727c3dd47a6ce35111f2ebdf66ff4"}, - {file = "numpy-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ebec5fd716c5a5b3d8dfcc439be82a8407b7b24b230d0ad28a81b61c2f4659a"}, - {file = "numpy-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2b49c3c0804e8ecb05d59af8386ec2f74877f7ca8fd9c1e00be2672e4d399b1"}, - {file = "numpy-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2cbba4b30bf31ddbe97f1c7205ef976909a93a66bb1583e983adbd155ba72ac2"}, - {file = "numpy-2.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8e00ea6fc82e8a804433d3e9cedaa1051a1422cb6e443011590c14d2dea59146"}, - {file = "numpy-2.1.2-cp311-cp311-win32.whl", hash = "sha256:5006b13a06e0b38d561fab5ccc37581f23c9511879be7693bd33c7cd15ca227c"}, - {file = "numpy-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:f1eb068ead09f4994dec71c24b2844f1e4e4e013b9629f812f292f04bd1510d9"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7bf0a4f9f15b32b5ba53147369e94296f5fffb783db5aacc1be15b4bf72f43b"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b1d0fcae4f0949f215d4632be684a539859b295e2d0cb14f78ec231915d644db"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:f751ed0a2f250541e19dfca9f1eafa31a392c71c832b6bb9e113b10d050cb0f1"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:bd33f82e95ba7ad632bc57837ee99dba3d7e006536200c4e9124089e1bf42426"}, - {file = "numpy-2.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b8cde4f11f0a975d1fd59373b32e2f5a562ade7cde4f85b7137f3de8fbb29a0"}, - {file = "numpy-2.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d95f286b8244b3649b477ac066c6906fbb2905f8ac19b170e2175d3d799f4df"}, - {file = "numpy-2.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ab4754d432e3ac42d33a269c8567413bdb541689b02d93788af4131018cbf366"}, - {file = "numpy-2.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e585c8ae871fd38ac50598f4763d73ec5497b0de9a0ab4ef5b69f01c6a046142"}, - {file = "numpy-2.1.2-cp312-cp312-win32.whl", hash = "sha256:9c6c754df29ce6a89ed23afb25550d1c2d5fdb9901d9c67a16e0b16eaf7e2550"}, - {file = "numpy-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:456e3b11cb79ac9946c822a56346ec80275eaf2950314b249b512896c0d2505e"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a84498e0d0a1174f2b3ed769b67b656aa5460c92c9554039e11f20a05650f00d"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4d6ec0d4222e8ffdab1744da2560f07856421b367928026fb540e1945f2eeeaf"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:259ec80d54999cc34cd1eb8ded513cb053c3bf4829152a2e00de2371bd406f5e"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:675c741d4739af2dc20cd6c6a5c4b7355c728167845e3c6b0e824e4e5d36a6c3"}, - {file = "numpy-2.1.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b2d4e667895cc55e3ff2b56077e4c8a5604361fc21a042845ea3ad67465aa8"}, - {file = "numpy-2.1.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43cca367bf94a14aca50b89e9bc2061683116cfe864e56740e083392f533ce7a"}, - {file = "numpy-2.1.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:76322dcdb16fccf2ac56f99048af32259dcc488d9b7e25b51e5eca5147a3fb98"}, - {file = "numpy-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:32e16a03138cabe0cb28e1007ee82264296ac0983714094380b408097a418cfe"}, - {file = "numpy-2.1.2-cp313-cp313-win32.whl", hash = "sha256:242b39d00e4944431a3cd2db2f5377e15b5785920421993770cddb89992c3f3a"}, - {file = "numpy-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:f2ded8d9b6f68cc26f8425eda5d3877b47343e68ca23d0d0846f4d312ecaa445"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ffef621c14ebb0188a8633348504a35c13680d6da93ab5cb86f4e54b7e922b5"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ad369ed238b1959dfbade9018a740fb9392c5ac4f9b5173f420bd4f37ba1f7a0"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d82075752f40c0ddf57e6e02673a17f6cb0f8eb3f587f63ca1eaab5594da5b17"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:1600068c262af1ca9580a527d43dc9d959b0b1d8e56f8a05d830eea39b7c8af6"}, - {file = "numpy-2.1.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a26ae94658d3ba3781d5e103ac07a876b3e9b29db53f68ed7df432fd033358a8"}, - {file = "numpy-2.1.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13311c2db4c5f7609b462bc0f43d3c465424d25c626d95040f073e30f7570e35"}, - {file = "numpy-2.1.2-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:2abbf905a0b568706391ec6fa15161fad0fb5d8b68d73c461b3c1bab6064dd62"}, - {file = "numpy-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ef444c57d664d35cac4e18c298c47d7b504c66b17c2ea91312e979fcfbdfb08a"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:bdd407c40483463898b84490770199d5714dcc9dd9b792f6c6caccc523c00952"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:da65fb46d4cbb75cb417cddf6ba5e7582eb7bb0b47db4b99c9fe5787ce5d91f5"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c193d0b0238638e6fc5f10f1b074a6993cb13b0b431f64079a509d63d3aa8b7"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a7d80b2e904faa63068ead63107189164ca443b42dd1930299e0d1cb041cec2e"}, - {file = "numpy-2.1.2.tar.gz", hash = "sha256:13532a088217fa624c99b843eeb54640de23b3414b14aa66d023805eb731066c"}, + {file = "numpy-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c894b4305373b9c5576d7a12b473702afdf48ce5369c074ba304cc5ad8730dff"}, + {file = "numpy-2.1.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b47fbb433d3260adcd51eb54f92a2ffbc90a4595f8970ee00e064c644ac788f5"}, + {file = "numpy-2.1.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:825656d0743699c529c5943554d223c021ff0494ff1442152ce887ef4f7561a1"}, + {file = "numpy-2.1.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:6a4825252fcc430a182ac4dee5a505053d262c807f8a924603d411f6718b88fd"}, + {file = "numpy-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e711e02f49e176a01d0349d82cb5f05ba4db7d5e7e0defd026328e5cfb3226d3"}, + {file = "numpy-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78574ac2d1a4a02421f25da9559850d59457bac82f2b8d7a44fe83a64f770098"}, + {file = "numpy-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c7662f0e3673fe4e832fe07b65c50342ea27d989f92c80355658c7f888fcc83c"}, + {file = "numpy-2.1.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fa2d1337dc61c8dc417fbccf20f6d1e139896a30721b7f1e832b2bb6ef4eb6c4"}, + {file = "numpy-2.1.3-cp310-cp310-win32.whl", hash = "sha256:72dcc4a35a8515d83e76b58fdf8113a5c969ccd505c8a946759b24e3182d1f23"}, + {file = "numpy-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:ecc76a9ba2911d8d37ac01de72834d8849e55473457558e12995f4cd53e778e0"}, + {file = "numpy-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4d1167c53b93f1f5d8a139a742b3c6f4d429b54e74e6b57d0eff40045187b15d"}, + {file = "numpy-2.1.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c80e4a09b3d95b4e1cac08643f1152fa71a0a821a2d4277334c88d54b2219a41"}, + {file = "numpy-2.1.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:576a1c1d25e9e02ed7fa5477f30a127fe56debd53b8d2c89d5578f9857d03ca9"}, + {file = "numpy-2.1.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:973faafebaae4c0aaa1a1ca1ce02434554d67e628b8d805e61f874b84e136b09"}, + {file = "numpy-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:762479be47a4863e261a840e8e01608d124ee1361e48b96916f38b119cfda04a"}, + {file = "numpy-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f24b3d1ecc1eebfbf5d6051faa49af40b03be1aaa781ebdadcbc090b4539b"}, + {file = "numpy-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:17ee83a1f4fef3c94d16dc1802b998668b5419362c8a4f4e8a491de1b41cc3ee"}, + {file = "numpy-2.1.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:15cb89f39fa6d0bdfb600ea24b250e5f1a3df23f901f51c8debaa6a5d122b2f0"}, + {file = "numpy-2.1.3-cp311-cp311-win32.whl", hash = "sha256:d9beb777a78c331580705326d2367488d5bc473b49a9bc3036c154832520aca9"}, + {file = "numpy-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:d89dd2b6da69c4fff5e39c28a382199ddedc3a5be5390115608345dec660b9e2"}, + {file = "numpy-2.1.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f55ba01150f52b1027829b50d70ef1dafd9821ea82905b63936668403c3b471e"}, + {file = "numpy-2.1.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13138eadd4f4da03074851a698ffa7e405f41a0845a6b1ad135b81596e4e9958"}, + {file = "numpy-2.1.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:a6b46587b14b888e95e4a24d7b13ae91fa22386c199ee7b418f449032b2fa3b8"}, + {file = "numpy-2.1.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:0fa14563cc46422e99daef53d725d0c326e99e468a9320a240affffe87852564"}, + {file = "numpy-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8637dcd2caa676e475503d1f8fdb327bc495554e10838019651b76d17b98e512"}, + {file = "numpy-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2312b2aa89e1f43ecea6da6ea9a810d06aae08321609d8dc0d0eda6d946a541b"}, + {file = "numpy-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a38c19106902bb19351b83802531fea19dee18e5b37b36454f27f11ff956f7fc"}, + {file = "numpy-2.1.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02135ade8b8a84011cbb67dc44e07c58f28575cf9ecf8ab304e51c05528c19f0"}, + {file = "numpy-2.1.3-cp312-cp312-win32.whl", hash = "sha256:e6988e90fcf617da2b5c78902fe8e668361b43b4fe26dbf2d7b0f8034d4cafb9"}, + {file = "numpy-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:0d30c543f02e84e92c4b1f415b7c6b5326cbe45ee7882b6b77db7195fb971e3a"}, + {file = "numpy-2.1.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96fe52fcdb9345b7cd82ecd34547fca4321f7656d500eca497eb7ea5a926692f"}, + {file = "numpy-2.1.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f653490b33e9c3a4c1c01d41bc2aef08f9475af51146e4a7710c450cf9761598"}, + {file = "numpy-2.1.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dc258a761a16daa791081d026f0ed4399b582712e6fc887a95af09df10c5ca57"}, + {file = "numpy-2.1.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:016d0f6f5e77b0f0d45d77387ffa4bb89816b57c835580c3ce8e099ef830befe"}, + {file = "numpy-2.1.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c181ba05ce8299c7aa3125c27b9c2167bca4a4445b7ce73d5febc411ca692e43"}, + {file = "numpy-2.1.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5641516794ca9e5f8a4d17bb45446998c6554704d888f86df9b200e66bdcce56"}, + {file = "numpy-2.1.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ea4dedd6e394a9c180b33c2c872b92f7ce0f8e7ad93e9585312b0c5a04777a4a"}, + {file = "numpy-2.1.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0df3635b9c8ef48bd3be5f862cf71b0a4716fa0e702155c45067c6b711ddcef"}, + {file = "numpy-2.1.3-cp313-cp313-win32.whl", hash = "sha256:50ca6aba6e163363f132b5c101ba078b8cbd3fa92c7865fd7d4d62d9779ac29f"}, + {file = "numpy-2.1.3-cp313-cp313-win_amd64.whl", hash = "sha256:747641635d3d44bcb380d950679462fae44f54b131be347d5ec2bce47d3df9ed"}, + {file = "numpy-2.1.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:996bb9399059c5b82f76b53ff8bb686069c05acc94656bb259b1d63d04a9506f"}, + {file = "numpy-2.1.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:45966d859916ad02b779706bb43b954281db43e185015df6eb3323120188f9e4"}, + {file = "numpy-2.1.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:baed7e8d7481bfe0874b566850cb0b85243e982388b7b23348c6db2ee2b2ae8e"}, + {file = "numpy-2.1.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f7f672a3388133335589cfca93ed468509cb7b93ba3105fce780d04a6576a0"}, + {file = "numpy-2.1.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7aac50327da5d208db2eec22eb11e491e3fe13d22653dce51b0f4109101b408"}, + {file = "numpy-2.1.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4394bc0dbd074b7f9b52024832d16e019decebf86caf909d94f6b3f77a8ee3b6"}, + {file = "numpy-2.1.3-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:50d18c4358a0a8a53f12a8ba9d772ab2d460321e6a93d6064fc22443d189853f"}, + {file = "numpy-2.1.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:14e253bd43fc6b37af4921b10f6add6925878a42a0c5fe83daee390bca80bc17"}, + {file = "numpy-2.1.3-cp313-cp313t-win32.whl", hash = "sha256:08788d27a5fd867a663f6fc753fd7c3ad7e92747efc73c53bca2f19f8bc06f48"}, + {file = "numpy-2.1.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2564fbdf2b99b3f815f2107c1bbc93e2de8ee655a69c261363a1172a79a257d4"}, + {file = "numpy-2.1.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4f2015dfe437dfebbfce7c85c7b53d81ba49e71ba7eadbf1df40c915af75979f"}, + {file = "numpy-2.1.3-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:3522b0dfe983a575e6a9ab3a4a4dfe156c3e428468ff08ce582b9bb6bd1d71d4"}, + {file = "numpy-2.1.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c006b607a865b07cd981ccb218a04fc86b600411d83d6fc261357f1c0966755d"}, + {file = "numpy-2.1.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e14e26956e6f1696070788252dcdff11b4aca4c3e8bd166e0df1bb8f315a67cb"}, + {file = "numpy-2.1.3.tar.gz", hash = "sha256:aa08e04e08aaf974d4458def539dece0d28146d866a39da5639596f4921fd761"}, ] [[package]] name = "packaging" -version = "24.1" +version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] [[package]] @@ -488,7 +490,7 @@ rtree = "*" type = "git" url = "https://github.com/adf-python/rcrs-core-python" reference = "HEAD" -resolved_reference = "b353cd6e82005e20e099554d4f357d9c0cc2e052" +resolved_reference = "c4ec7b2d32badb2f10fc1d03b962b465624a1ed5" [[package]] name = "rtree" @@ -630,6 +632,64 @@ dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodest doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.13.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<=7.3.7)", "sphinx-design (>=0.4.0)"] test = ["Cython", "array-api-strict (>=2.0)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +[[package]] +name = "shapely" +version = "2.0.6" +description = "Manipulation and analysis of geometric objects" +optional = false +python-versions = ">=3.7" +files = [ + {file = "shapely-2.0.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29a34e068da2d321e926b5073539fd2a1d4429a2c656bd63f0bd4c8f5b236d0b"}, + {file = "shapely-2.0.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c84c3f53144febf6af909d6b581bc05e8785d57e27f35ebaa5c1ab9baba13b"}, + {file = "shapely-2.0.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ad2fae12dca8d2b727fa12b007e46fbc522148a584f5d6546c539f3464dccde"}, + {file = "shapely-2.0.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3304883bd82d44be1b27a9d17f1167fda8c7f5a02a897958d86c59ec69b705e"}, + {file = "shapely-2.0.6-cp310-cp310-win32.whl", hash = "sha256:3ec3a0eab496b5e04633a39fa3d5eb5454628228201fb24903d38174ee34565e"}, + {file = "shapely-2.0.6-cp310-cp310-win_amd64.whl", hash = "sha256:28f87cdf5308a514763a5c38de295544cb27429cfa655d50ed8431a4796090c4"}, + {file = "shapely-2.0.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5aeb0f51a9db176da9a30cb2f4329b6fbd1e26d359012bb0ac3d3c7781667a9e"}, + {file = "shapely-2.0.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a7a78b0d51257a367ee115f4d41ca4d46edbd0dd280f697a8092dd3989867b2"}, + {file = "shapely-2.0.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f32c23d2f43d54029f986479f7c1f6e09c6b3a19353a3833c2ffb226fb63a855"}, + {file = "shapely-2.0.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3dc9fb0eb56498912025f5eb352b5126f04801ed0e8bdbd867d21bdbfd7cbd0"}, + {file = "shapely-2.0.6-cp311-cp311-win32.whl", hash = "sha256:d93b7e0e71c9f095e09454bf18dad5ea716fb6ced5df3cb044564a00723f339d"}, + {file = "shapely-2.0.6-cp311-cp311-win_amd64.whl", hash = "sha256:c02eb6bf4cfb9fe6568502e85bb2647921ee49171bcd2d4116c7b3109724ef9b"}, + {file = "shapely-2.0.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cec9193519940e9d1b86a3b4f5af9eb6910197d24af02f247afbfb47bcb3fab0"}, + {file = "shapely-2.0.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83b94a44ab04a90e88be69e7ddcc6f332da7c0a0ebb1156e1c4f568bbec983c3"}, + {file = "shapely-2.0.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:537c4b2716d22c92036d00b34aac9d3775e3691f80c7aa517c2c290351f42cd8"}, + {file = "shapely-2.0.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98fea108334be345c283ce74bf064fa00cfdd718048a8af7343c59eb40f59726"}, + {file = "shapely-2.0.6-cp312-cp312-win32.whl", hash = "sha256:42fd4cd4834747e4990227e4cbafb02242c0cffe9ce7ef9971f53ac52d80d55f"}, + {file = "shapely-2.0.6-cp312-cp312-win_amd64.whl", hash = "sha256:665990c84aece05efb68a21b3523a6b2057e84a1afbef426ad287f0796ef8a48"}, + {file = "shapely-2.0.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:42805ef90783ce689a4dde2b6b2f261e2c52609226a0438d882e3ced40bb3013"}, + {file = "shapely-2.0.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6d2cb146191a47bd0cee8ff5f90b47547b82b6345c0d02dd8b25b88b68af62d7"}, + {file = "shapely-2.0.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3fdef0a1794a8fe70dc1f514440aa34426cc0ae98d9a1027fb299d45741c381"}, + {file = "shapely-2.0.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c665a0301c645615a107ff7f52adafa2153beab51daf34587170d85e8ba6805"}, + {file = "shapely-2.0.6-cp313-cp313-win32.whl", hash = "sha256:0334bd51828f68cd54b87d80b3e7cee93f249d82ae55a0faf3ea21c9be7b323a"}, + {file = "shapely-2.0.6-cp313-cp313-win_amd64.whl", hash = "sha256:d37d070da9e0e0f0a530a621e17c0b8c3c9d04105655132a87cfff8bd77cc4c2"}, + {file = "shapely-2.0.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fa7468e4f5b92049c0f36d63c3e309f85f2775752e076378e36c6387245c5462"}, + {file = "shapely-2.0.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed5867e598a9e8ac3291da6cc9baa62ca25706eea186117034e8ec0ea4355653"}, + {file = "shapely-2.0.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81d9dfe155f371f78c8d895a7b7f323bb241fb148d848a2bf2244f79213123fe"}, + {file = "shapely-2.0.6-cp37-cp37m-win32.whl", hash = "sha256:fbb7bf02a7542dba55129062570211cfb0defa05386409b3e306c39612e7fbcc"}, + {file = "shapely-2.0.6-cp37-cp37m-win_amd64.whl", hash = "sha256:837d395fac58aa01aa544495b97940995211e3e25f9aaf87bc3ba5b3a8cd1ac7"}, + {file = "shapely-2.0.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c6d88ade96bf02f6bfd667ddd3626913098e243e419a0325ebef2bbd481d1eb6"}, + {file = "shapely-2.0.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8b3b818c4407eaa0b4cb376fd2305e20ff6df757bf1356651589eadc14aab41b"}, + {file = "shapely-2.0.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bbc783529a21f2bd50c79cef90761f72d41c45622b3e57acf78d984c50a5d13"}, + {file = "shapely-2.0.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2423f6c0903ebe5df6d32e0066b3d94029aab18425ad4b07bf98c3972a6e25a1"}, + {file = "shapely-2.0.6-cp38-cp38-win32.whl", hash = "sha256:2de00c3bfa80d6750832bde1d9487e302a6dd21d90cb2f210515cefdb616e5f5"}, + {file = "shapely-2.0.6-cp38-cp38-win_amd64.whl", hash = "sha256:3a82d58a1134d5e975f19268710e53bddd9c473743356c90d97ce04b73e101ee"}, + {file = "shapely-2.0.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:392f66f458a0a2c706254f473290418236e52aa4c9b476a072539d63a2460595"}, + {file = "shapely-2.0.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eba5bae271d523c938274c61658ebc34de6c4b33fdf43ef7e938b5776388c1be"}, + {file = "shapely-2.0.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7060566bc4888b0c8ed14b5d57df8a0ead5c28f9b69fb6bed4476df31c51b0af"}, + {file = "shapely-2.0.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b02154b3e9d076a29a8513dffcb80f047a5ea63c897c0cd3d3679f29363cf7e5"}, + {file = "shapely-2.0.6-cp39-cp39-win32.whl", hash = "sha256:44246d30124a4f1a638a7d5419149959532b99dfa25b54393512e6acc9c211ac"}, + {file = "shapely-2.0.6-cp39-cp39-win_amd64.whl", hash = "sha256:2b542d7f1dbb89192d3512c52b679c822ba916f93479fa5d4fc2fe4fa0b3c9e8"}, + {file = "shapely-2.0.6.tar.gz", hash = "sha256:997f6159b1484059ec239cacaa53467fd8b5564dabe186cd84ac2944663b0bf6"}, +] + +[package.dependencies] +numpy = ">=1.14,<3" + +[package.extras] +docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] +test = ["pytest", "pytest-cov"] + [[package]] name = "structlog" version = "24.4.0" @@ -722,4 +782,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "6fdb27af56e45fff1fa8898664fb70a3df4a4258237612e8fc3d795d4c2dc45d" +content-hash = "6e8244db0f75c542b50338580672c5e11b1cdfe38b0a62d01b757b31d4eddaf0" diff --git a/pyproject.toml b/pyproject.toml index d41e1935..35dee4b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,6 +18,7 @@ types-pyyaml = "^6.0.12.20240808" scikit-learn = "^1.5.2" structlog = "^24.4.0" bitarray = "^3.0.0" +shapely = "^2.0.6" [tool.poetry.group.dev.dependencies] diff --git a/pyrightconfig.json b/pyrightconfig.json index 8a1eb709..8c19fca2 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -1,4 +1,4 @@ { "typeCheckingMode": "standard", - "exclude": ["**/site-packages"] + "exclude": [".venv", ".git"] } From d24537638ab923eaaefc4ad203016a44083a5ed8 Mon Sep 17 00:00:00 2001 From: shima004 Date: Thu, 14 Nov 2024 02:32:45 +0900 Subject: [PATCH 6/8] refactor: update hash methods to include return type annotations and clean up imports --- adf_core_python/core/agent/agent.py | 74 +++++++++----- adf_core_python/core/agent/command_factory.py | 44 --------- .../agent/communication/message_manager.py | 2 +- .../bundle/centralized/command_ambulance.py | 2 +- .../bundle/centralized/command_fire.py | 2 +- .../bundle/centralized/command_police.py | 2 +- .../bundle/centralized/command_scout.py | 2 +- .../bundle/centralized/message_report.py | 6 +- .../information/message_ambulance_team.py | 2 +- .../bundle/information/message_building.py | 4 +- .../bundle/information/message_civilian.py | 4 +- .../information/message_fire_brigade.py | 4 +- .../information/message_police_force.py | 4 +- .../bundle/information/message_road.py | 4 +- .../standard/bundle/standard_message.py | 2 +- .../bundle/standard_message_priority.py | 6 +- adf_core_python/core/agent/platoon/platoon.py | 1 - .../communication/communication_message.py | 2 +- .../connect/connector_police_office.py | 1 - .../action/default_extend_action_rescue.py | 24 +++-- .../default_message_coordinator.py | 99 ++++++++++++------- .../tactics/default_tactics_ambulance_team.py | 4 +- 22 files changed, 152 insertions(+), 143 deletions(-) delete mode 100644 adf_core_python/core/agent/command_factory.py diff --git a/adf_core_python/core/agent/agent.py b/adf_core_python/core/agent/agent.py index 51c9e980..4d41918f 100644 --- a/adf_core_python/core/agent/agent.py +++ b/adf_core_python/core/agent/agent.py @@ -1,6 +1,6 @@ import sys from abc import abstractmethod -from typing import Any, NoReturn +from typing import Any, Callable, NoReturn from bitarray import bitarray from rcrs_core.commands.AKClear import AKClear @@ -16,6 +16,9 @@ from rcrs_core.commands.AKUnload import AKUnload from rcrs_core.commands.Command import Command from rcrs_core.config.config import Config as RCRSConfig +from rcrs_core.connection.URN import Command as CommandURN +from rcrs_core.connection.URN import ComponentCommand as ComponentCommandMessageID +from rcrs_core.connection.URN import ComponentControlMSG as ComponentControlMessageID from rcrs_core.connection.URN import Entity as EntityURN from rcrs_core.messages.AKAcknowledge import AKAcknowledge from rcrs_core.messages.AKConnect import AKConnect @@ -27,7 +30,6 @@ from rcrs_core.worldmodel.entityID import EntityID from rcrs_core.worldmodel.worldmodel import WorldModel -from adf_core_python.core.agent.command_factory import CommandFactory from adf_core_python.core.agent.communication.message_manager import MessageManager from adf_core_python.core.agent.communication.standard.bundle.centralized.command_ambulance import ( CommandAmbulance, @@ -42,7 +44,7 @@ CommandScout, ) from adf_core_python.core.agent.communication.standard.bundle.centralized.message_report import ( - CommandReport, + MessageReport, ) from adf_core_python.core.agent.communication.standard.bundle.information.message_ambulance_team import ( MessageAmbulanceTeam, @@ -118,7 +120,7 @@ def __init__( def get_entity_id(self) -> EntityID: return self.agent_id - def set_send_msg(self, connection_send_func): + def set_send_msg(self, connection_send_func: Callable) -> None: self.send_msg = connection_send_func def post_connect(self) -> None: @@ -165,7 +167,7 @@ def update_step_info( self._message_manager.register_message_class(7, CommandFire) self._message_manager.register_message_class(8, CommandPolice) self._message_manager.register_message_class(9, CommandScout) - self._message_manager.register_message_class(10, CommandReport) + self._message_manager.register_message_class(10, MessageReport) if time > self._ignore_time: self._message_manager.subscribe( @@ -212,11 +214,11 @@ def precompute(self) -> None: def get_requested_entities(self) -> list[EntityURN]: pass - def start_up(self, request_id): + def start_up(self, request_id: int) -> None: ak_connect = AKConnect() self.send_msg(ak_connect.write(request_id, self)) - def message_received(self, msg): + def message_received(self, msg: Any) -> None: c_msg = ControlMessageFactory().make_message(msg) if isinstance(c_msg, KASense): self.handler_sense(c_msg) @@ -231,7 +233,7 @@ def handle_connect_error(self, msg: Any) -> NoReturn: ) sys.exit(1) - def handle_connect_ok(self, msg): + def handle_connect_ok(self, msg: Any) -> None: self.agent_id = EntityID(msg.agent_id) self.world_model.add_entities(msg.world) config: RCRSConfig = msg.config @@ -253,76 +255,94 @@ def handle_connect_ok(self, msg): print("self.precompute_flag: ", self.precompute_flag) self.precompute() - def handler_sense(self, msg): + def handler_sense(self, msg: Any) -> None: _id = EntityID(msg.agent_id) time = msg.time change_set = msg.change_set - hear = msg.hear.commands + heard = msg.hear.commands if _id != self.get_entity_id(): self.logger.error("Agent ID mismatch: %s != %s", _id, self.get_entity_id()) return - hear_commands = [CommandFactory.create_command(cmd) for cmd in hear] + heard_commands: list[Command] = [] + for herad_command in heard: + if herad_command.urn == CommandURN.AK_SPEAK: + heard_commands.append( + AKSpeak( + herad_command.components[ + ComponentControlMessageID.AgentID + ].entityID, + herad_command.components[ + ComponentControlMessageID.Time + ].intValue, + herad_command.components[ + ComponentCommandMessageID.Message + ].rawData, + herad_command.components[ + ComponentCommandMessageID.Channel + ].intValue, + ) + ) self.world_model.merge(change_set) - self.update_step_info(time, change_set, hear_commands) + self.update_step_info(time, change_set, heard_commands) - def send_acknowledge(self, request_id): + def send_acknowledge(self, request_id: int) -> None: ak_ack = AKAcknowledge() self.send_msg(ak_ack.write(request_id, self.agent_id)) - def send_clear(self, time, target): + def send_clear(self, time: int, target: EntityID) -> None: cmd = AKClear(self.get_entity_id(), time, target) msg = cmd.prepare_cmd() self.send_msg(msg) - def send_clear_area(self, time, x=-1, y=-1): + def send_clear_area(self, time: int, x: int = -1, y: int = -1) -> None: cmd = AKClearArea(self.get_entity_id(), time, x, y) msg = cmd.prepare_cmd() self.send_msg(msg) - def send_load(self, time, target): + def send_load(self, time: int, target: EntityID) -> None: cmd = AKLoad(self.get_entity_id(), time, target) msg = cmd.prepare_cmd() self.send_msg(msg) - def send_move(self, time, path, x=-1, y=-1): + def send_move(self, time: int, path: list[int], x: int = -1, y: int = -1) -> None: cmd = AKMove(self.get_entity_id(), time, path[:], x, y) msg = cmd.prepare_cmd() self.send_msg(msg) - def send_rescue(self, time, target): + def send_rescue(self, time: int, target: EntityID) -> None: cmd = AKRescue(self.get_entity_id(), time, target) msg = cmd.prepare_cmd() self.send_msg(msg) - def send_rest(self, time_step): - cmd = AKRest(self.get_entity_id(), time_step) + def send_rest(self, time: int) -> None: + cmd = AKRest(self.get_entity_id(), time) msg = cmd.prepare_cmd() self.send_msg(msg) - def send_say(self, time_step: int, message: str): + def send_say(self, time_step: int, message: str) -> None: cmd = AKSay(self.get_entity_id(), time_step, message) msg = cmd.prepare_cmd() self.send_msg(msg) - def send_speak(self, time_step: int, message: bitarray, channel: int): + def send_speak(self, time_step: int, message: bitarray, channel: int) -> None: cmd = AKSpeak(self.get_entity_id(), time_step, bytes(message), channel) # type: ignore msg = cmd.prepare_cmd() self.send_msg(msg) - def send_subscribe(self, time, channel): - cmd = AKSubscribe(self.get_entity_id(), time, channel) + def send_subscribe(self, time: int, channels: list[int]) -> None: + cmd = AKSubscribe(self.get_entity_id(), time, channels) msg = cmd.prepare_cmd() self.send_msg(msg) - def send_tell(self, time_step: int, message: str): - cmd = AKTell(self.get_entity_id(), time_step, message) + def send_tell(self, time: int, message: str) -> None: + cmd = AKTell(self.get_entity_id(), time, message) msg = cmd.prepare_cmd() self.send_msg(msg) - def send_unload(self, time): + def send_unload(self, time: int) -> None: cmd = AKUnload(self.get_entity_id(), time) msg = cmd.prepare_cmd() self.send_msg(msg) diff --git a/adf_core_python/core/agent/command_factory.py b/adf_core_python/core/agent/command_factory.py deleted file mode 100644 index 33c52530..00000000 --- a/adf_core_python/core/agent/command_factory.py +++ /dev/null @@ -1,44 +0,0 @@ -from rcrs_core.commands.AKClear import AKClear -from rcrs_core.commands.AKClearArea import AKClearArea -from rcrs_core.commands.AKExtinguish import AKExtinguish -from rcrs_core.commands.AKLoad import AKLoad -from rcrs_core.commands.AKMove import AKMove -from rcrs_core.commands.AKRescue import AKRescue -from rcrs_core.commands.AKRest import AKRest -from rcrs_core.commands.AKSay import AKSay -from rcrs_core.commands.AKSpeak import AKSpeak -from rcrs_core.commands.AKSubscribe import AKSubscribe -from rcrs_core.commands.AKTell import AKTell -from rcrs_core.commands.AKUnload import AKUnload -from rcrs_core.commands.Command import Command -from rcrs_core.connection.URN import Command as CommandURN -from rcrs_core.connection.URN import ComponentCommand as ComponentCommandMessageID -from rcrs_core.connection.URN import ComponentControlMSG as ComponentControlMessageID - - -class CommandFactory: - @staticmethod - def create_command(herad_command) -> Command: - if herad_command.urn == CommandURN.AK_SPEAK: - return AKSpeak( - herad_command.components[ComponentControlMessageID.AgentID].entityID, - herad_command.components[ComponentControlMessageID.Time].intValue, - herad_command.components[ComponentCommandMessageID.Message].rawData, - herad_command.components[ComponentCommandMessageID.Channel].intValue, - ) - return herad_command - # if herad_command.urn == CommandURN.AK_CLEAR: - # return AKClear( - # herad_command.agent_id, herad_command.time, herad_command.target - # ) - # elif herad_command.urn == CommandURN.AK_CLEAR_AREA: - # return AKClearArea( - # herad_command.agent_id, - # herad_command.time, - # herad_command.x, - # herad_command.y, - # ) - # elif herad_command.urn == CommandURN.AK_EXTINGUISH: - # return AKExtinguish( - # herad_command.agent_id, herad_command.time, herad_command.target - # ) diff --git a/adf_core_python/core/agent/communication/message_manager.py b/adf_core_python/core/agent/communication/message_manager.py index 53c8f43f..f318b1ab 100644 --- a/adf_core_python/core/agent/communication/message_manager.py +++ b/adf_core_python/core/agent/communication/message_manager.py @@ -44,7 +44,7 @@ def __init__(self) -> None: self.__send_message_list: list[CommunicationMessage] = [] self.__received_message_list: list[CommunicationMessage] = [] self.__channel_send_message_list: list[list[CommunicationMessage]] = [] - self.__check_duplicate_cache: set[str] = set() + self.__check_duplicate_cache: set[int] = set() self.__message_coordinator: MessageCoordinator self.__channel_subscriber: ChannelSubscriber self.__heard_agent_help_message_count: int = 0 diff --git a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_ambulance.py b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_ambulance.py index ff28ab88..a5d69843 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_ambulance.py +++ b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_ambulance.py @@ -120,7 +120,7 @@ def from_bits( command_target_id, ) - def __hash__(self): + def __hash__(self) -> int: h = super().__hash__() return hash( ( diff --git a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_fire.py b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_fire.py index 5927a2ef..cf611315 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_fire.py +++ b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_fire.py @@ -121,7 +121,7 @@ def from_bits( command_target_id, ) - def __hash__(self): + def __hash__(self) -> int: h = super().__hash__() return hash( ( diff --git a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_police.py b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_police.py index cf3cc4d6..64b8e349 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_police.py +++ b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_police.py @@ -119,7 +119,7 @@ def from_bits( command_target_id, ) - def __hash__(self): + def __hash__(self) -> int: h = super().__hash__() return hash( ( diff --git a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_scout.py b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_scout.py index 253883b0..138a1ddb 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/centralized/command_scout.py +++ b/adf_core_python/core/agent/communication/standard/bundle/centralized/command_scout.py @@ -114,7 +114,7 @@ def from_bits( command_target_id, ) - def __hash__(self): + def __hash__(self) -> int: h = super().__hash__() return hash( ( diff --git a/adf_core_python/core/agent/communication/standard/bundle/centralized/message_report.py b/adf_core_python/core/agent/communication/standard/bundle/centralized/message_report.py index 2971bb5b..55f89074 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/centralized/message_report.py +++ b/adf_core_python/core/agent/communication/standard/bundle/centralized/message_report.py @@ -15,7 +15,7 @@ ) -class CommandReport(StandardMessage): +class MessageReport(StandardMessage): SIZE_DONE: int = 1 SIZE_BLOADCAST: int = 1 @@ -60,7 +60,7 @@ def from_bits( bit_array: bitarray, is_wireless_message: bool, sender_entity_id: EntityID, - ) -> CommandReport: + ) -> MessageReport: std_message = super().from_bits( bit_array, is_wireless_message, sender_entity_id ) @@ -74,7 +74,7 @@ def from_bits( std_message.get_priority(), ) - def __hash__(self): + def __hash__(self) -> int: h = super().__hash__() return hash( ( diff --git a/adf_core_python/core/agent/communication/standard/bundle/information/message_ambulance_team.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_ambulance_team.py index 7f495f72..6c73a959 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/information/message_ambulance_team.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_ambulance_team.py @@ -167,7 +167,7 @@ def from_bits( std_message.get_ttl(), ) - def __hash__(self): + def __hash__(self) -> int: h = super().__hash__() return hash( ( diff --git a/adf_core_python/core/agent/communication/standard/bundle/information/message_building.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_building.py index 3363e92c..be9f911a 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/information/message_building.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_building.py @@ -106,7 +106,7 @@ def from_bits( std_message.get_ttl(), ) - def __hash__(self): + def __hash__(self) -> int: h = super().__hash__() return hash( ( @@ -118,5 +118,5 @@ def __hash__(self): ) ) - def __str__(self): + def __str__(self) -> str: return f"MessageBuilding(building_entity_id={self._building_entity_id}, building_brokenness={self._building_brokenness}, building_fireyness={self._building_fireyness}, building_temperature={self._building_temperature})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/information/message_civilian.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_civilian.py index ac298471..a5a62b42 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/information/message_civilian.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_civilian.py @@ -119,7 +119,7 @@ def from_bits( std_message.get_ttl(), ) - def __hash__(self): + def __hash__(self) -> int: h = super().__hash__() return hash( ( @@ -132,5 +132,5 @@ def __hash__(self): ) ) - def __str__(self): + def __str__(self) -> str: return f"MessageCivilian(civilian_entity_id={self._civilian_entity_id}, civilian_hp={self._civilian_hp}, civilian_buriedness={self._civilian_buriedness}, civilian_damage={self._civilian_damage}, civilian_position={self._civilian_position})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/information/message_fire_brigade.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_fire_brigade.py index 11742d5a..a7c4cee1 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/information/message_fire_brigade.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_fire_brigade.py @@ -180,7 +180,7 @@ def from_bits( std_message.get_ttl(), ) - def __hash__(self): + def __hash__(self) -> int: h = super().__hash__() return hash( ( @@ -196,5 +196,5 @@ def __hash__(self): ) ) - def __str__(self): + def __str__(self) -> str: return f"MessageFireBrigade(fire_brigade_entity_id={self._fire_brigade_entity_id}, fire_brigade_hp={self._fire_brigade_hp}, fire_brigade_buriedness={self._fire_brigade_buriedness}, fire_brigade_damage={self._fire_brigade_damage}, fire_brigade_position={self._fire_brigade_position}, fire_brigade_water={self._fire_brigade_water}, target_entity_id={self._target_entity_id}, action={self._action})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/information/message_police_force.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_police_force.py index 8280184d..45116f3e 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/information/message_police_force.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_police_force.py @@ -162,7 +162,7 @@ def from_bits( std_message.get_ttl(), ) - def __hash__(self): + def __hash__(self) -> int: h = super().__hash__() return hash( ( @@ -177,5 +177,5 @@ def __hash__(self): ) ) - def __str__(self): + def __str__(self) -> str: return f"MessagePoliceForce(police_force_entity_id={self._police_force_entity_id}, police_force_hp={self._police_force_hp}, police_force_buriedness={self._police_force_buriedness}, police_force_damage={self._police_force_damage}, police_force_position={self._police_force_position}, target_entity_id={self._target_entity_id}, action={self._action})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/information/message_road.py b/adf_core_python/core/agent/communication/standard/bundle/information/message_road.py index 9023973f..474421c4 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/information/message_road.py +++ b/adf_core_python/core/agent/communication/standard/bundle/information/message_road.py @@ -160,7 +160,7 @@ def from_bits( std_message.get_ttl(), ) - def __hash__(self): + def __hash__(self) -> int: h = super().__hash__() return hash( ( @@ -175,5 +175,5 @@ def __hash__(self): ) ) - def __str__(self): + def __str__(self) -> str: return f"MessageRoad(road_entity_id={self._road_entity_id}, road_blockade_entity_id={self._road_blockade_entity_id}, road_blockade_repair_cost={self._road_blockade_repair_cost}, road_blockade_x={self._road_blockade_x}, road_blockade_y={self._road_blockade_y}, is_passable={self._is_passable}, is_send_blockade_location={self._is_send_blockade_location})" diff --git a/adf_core_python/core/agent/communication/standard/bundle/standard_message.py b/adf_core_python/core/agent/communication/standard/bundle/standard_message.py index 490f3675..bdec11b6 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/standard_message.py +++ b/adf_core_python/core/agent/communication/standard/bundle/standard_message.py @@ -64,7 +64,7 @@ def to_bits(self) -> bitarray: def get_bit_size(self) -> int: raise NotImplementedError - def __hash__(self): + def __hash__(self) -> int: return hash((self._sender_entity_id, self._priority, self._ttl)) def __str__(self) -> str: diff --git a/adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py b/adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py index e8e2e256..9e45154b 100644 --- a/adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py +++ b/adf_core_python/core/agent/communication/standard/bundle/standard_message_priority.py @@ -13,10 +13,12 @@ class StandardMessagePriority(Enum): def __str__(self) -> str: return self.name.lower() - def __lt__(self, other): + def __lt__(self, other: object) -> bool: if isinstance(other, StandardMessagePriority): return self.value < other.value + return NotImplemented - def __le__(self, other): + def __le__(self, other: object) -> bool: if isinstance(other, StandardMessagePriority): return self.value <= other.value + return NotImplemented diff --git a/adf_core_python/core/agent/platoon/platoon.py b/adf_core_python/core/agent/platoon/platoon.py index 098945f2..01babaaa 100644 --- a/adf_core_python/core/agent/platoon/platoon.py +++ b/adf_core_python/core/agent/platoon/platoon.py @@ -1,6 +1,5 @@ from adf_core_python.core.agent.action.action import Action from adf_core_python.core.agent.agent import Agent -from adf_core_python.core.agent.communication.message_manager import MessageManager from adf_core_python.core.agent.config.module_config import ModuleConfig from adf_core_python.core.agent.develop.develop_data import DevelopData from adf_core_python.core.agent.info.scenario_info import Mode diff --git a/adf_core_python/core/component/communication/communication_message.py b/adf_core_python/core/component/communication/communication_message.py index 0760ac0f..60972ff4 100644 --- a/adf_core_python/core/component/communication/communication_message.py +++ b/adf_core_python/core/component/communication/communication_message.py @@ -21,5 +21,5 @@ def to_bits(self) -> bitarray: raise NotImplementedError @abstractmethod - def __hash__(self): + def __hash__(self) -> int: raise NotImplementedError diff --git a/adf_core_python/core/launcher/connect/connector_police_office.py b/adf_core_python/core/launcher/connect/connector_police_office.py index 561b9872..b20da2e4 100644 --- a/adf_core_python/core/launcher/connect/connector_police_office.py +++ b/adf_core_python/core/launcher/connect/connector_police_office.py @@ -1,4 +1,3 @@ -import re import threading from rcrs_core.agents.policeOfficeAgent import PoliceOfficeAgent diff --git a/adf_core_python/implement/action/default_extend_action_rescue.py b/adf_core_python/implement/action/default_extend_action_rescue.py index 845ad188..67f4ff36 100644 --- a/adf_core_python/implement/action/default_extend_action_rescue.py +++ b/adf_core_python/implement/action/default_extend_action_rescue.py @@ -1,4 +1,4 @@ -from typing import cast, Optional +from typing import Optional, cast from rcrs_core.entities.area import Area from rcrs_core.entities.blockade import Blockade @@ -12,7 +12,11 @@ from adf_core_python.core.agent.communication.message_manager import MessageManager from adf_core_python.core.agent.develop.develop_data import DevelopData from adf_core_python.core.agent.info.agent_info import AgentInfo -from adf_core_python.core.agent.info.scenario_info import ScenarioInfo, Mode +from adf_core_python.core.agent.info.scenario_info import ( + Mode, + ScenarioInfo, + ScenarioInfoKeys, +) from adf_core_python.core.agent.info.world_info import WorldInfo from adf_core_python.core.agent.module.module_manager import ModuleManager from adf_core_python.core.agent.precompute.precompute_data import PrecomputeData @@ -32,8 +36,8 @@ def __init__( super().__init__( agent_info, world_info, scenario_info, module_manager, develop_data ) - self._kernel_time = None - self._target_entity_id = None + self._kernel_time: int = -1 + self._target_entity_id: Optional[EntityID] = None self._threshold_rest = develop_data.get_value( "adf_core_python.implement.action.DefaultExtendActionRescue.rest", 100 ) @@ -57,7 +61,9 @@ def precompute(self, precompute_data: PrecomputeData) -> ExtendAction: if self.get_count_precompute() >= 2: return self self._path_planning.precompute(precompute_data) - self._kernel_time = self.scenario_info.get_value("kernel.timesteps", -1) + self._kernel_time = self.scenario_info.get_value( + ScenarioInfoKeys.KERNEL_TIMESTEPS, -1 + ) return self def resume(self, precompute_data: PrecomputeData) -> ExtendAction: @@ -65,7 +71,9 @@ def resume(self, precompute_data: PrecomputeData) -> ExtendAction: if self.get_count_resume() >= 2: return self self._path_planning.resume(precompute_data) - self._kernel_time = self.scenario_info.get_value("kernel.timesteps", -1) + self._kernel_time = self.scenario_info.get_value( + ScenarioInfoKeys.KERNEL_TIMESTEPS, -1 + ) return self def prepare(self) -> ExtendAction: @@ -73,7 +81,9 @@ def prepare(self) -> ExtendAction: if self.get_count_prepare() >= 2: return self self._path_planning.prepare() - self._kernel_time = self.scenario_info.get_value("kernel.timesteps", -1) + self._kernel_time = self.scenario_info.get_value( + ScenarioInfoKeys.KERNEL_TIMESTEPS, -1 + ) return self def update_info(self, message_manager: MessageManager) -> ExtendAction: diff --git a/adf_core_python/implement/module/communication/default_message_coordinator.py b/adf_core_python/implement/module/communication/default_message_coordinator.py index 2e612645..92e1555c 100644 --- a/adf_core_python/implement/module/communication/default_message_coordinator.py +++ b/adf_core_python/implement/module/communication/default_message_coordinator.py @@ -1,5 +1,23 @@ +from typing import Optional + from rcrs_core.connection.URN import Entity as EntityURN +from adf_core_python.core.agent.communication.message_manager import MessageManager +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_ambulance import ( + CommandAmbulance, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_fire import ( + CommandFire, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_police import ( + CommandPolice, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.command_scout import ( + CommandScout, +) +from adf_core_python.core.agent.communication.standard.bundle.centralized.message_report import ( + MessageReport, +) from adf_core_python.core.agent.communication.standard.bundle.information.message_ambulance_team import ( MessageAmbulanceTeam, ) @@ -27,6 +45,9 @@ from adf_core_python.core.agent.info.agent_info import AgentInfo from adf_core_python.core.agent.info.scenario_info import ScenarioInfo, ScenarioInfoKeys from adf_core_python.core.agent.info.world_info import WorldInfo +from adf_core_python.core.component.communication.communication_message import ( + CommunicationMessage, +) from adf_core_python.core.component.communication.message_coordinator import ( MessageCoordinator, ) @@ -38,17 +59,17 @@ class DefaultMessageCoordinator(MessageCoordinator): def coordinate( self, - agent_info, - world_info, - scenario_info, - message_manager, - send_message_list, - channel_send_message_list, - ): - police_messages = [] - ambulance_messages = [] - fire_brigade_messages = [] - voice_messages = [] + agent_info: AgentInfo, + world_info: WorldInfo, + scenario_info: ScenarioInfo, + message_manager: MessageManager, + send_message_list: list[CommunicationMessage], + channel_send_message_list: list[list[CommunicationMessage]], + ) -> None: + police_messages: list[StandardMessage] = [] + ambulance_messages: list[StandardMessage] = [] + fire_brigade_messages: list[StandardMessage] = [] + voice_messages: list[StandardMessage] = [] agent_type = self.get_agent_type(agent_info, world_info) @@ -64,26 +85,26 @@ def coordinate( fire_brigade_messages.append(msg) ambulance_messages.append(msg) police_messages.append(msg) - # elif isinstance(msg, CommandAmbulance): - # ambulance_messages.append(msg) - # elif isinstance(msg, CommandFire): - # fire_brigade_messages.append(msg) - # elif isinstance(msg, CommandPolice): - # police_messages.append(msg) - # elif isinstance(msg, CommandScout): - # if agent_type == EntityURN.FIRE_STATION: - # fire_brigade_messages.append(msg) - # elif agent_type == EntityURN.POLICE_OFFICE: - # police_messages.append(msg) - # elif agent_type == EntityURN.AMBULANCE_CENTRE: - # ambulance_messages.append(msg) - # elif isinstance(msg, MessageReport): - # if agent_type == EntityURN.FIRE_BRIGADE: - # fire_brigade_messages.append(msg) - # elif agent_type == EntityURN.POLICE_FORCE: - # police_messages.append(msg) - # elif agent_type == EntityURN.AMBULANCE_TEAM: - # ambulance_messages.append(msg) + elif isinstance(msg, CommandAmbulance): + ambulance_messages.append(msg) + elif isinstance(msg, CommandFire): + fire_brigade_messages.append(msg) + elif isinstance(msg, CommandPolice): + police_messages.append(msg) + elif isinstance(msg, CommandScout): + if agent_type == EntityURN.FIRE_STATION: + fire_brigade_messages.append(msg) + elif agent_type == EntityURN.POLICE_OFFICE: + police_messages.append(msg) + elif agent_type == EntityURN.AMBULANCE_CENTRE: + ambulance_messages.append(msg) + elif isinstance(msg, MessageReport): + if agent_type == EntityURN.FIRE_BRIGADE: + fire_brigade_messages.append(msg) + elif agent_type == EntityURN.POLICE_FORCE: + police_messages.append(msg) + elif agent_type == EntityURN.AMBULANCE_TEAM: + ambulance_messages.append(msg) elif isinstance(msg, MessageFireBrigade): fire_brigade_messages.append(msg) ambulance_messages.append(msg) @@ -146,11 +167,11 @@ def coordinate( def get_channels_by_agent_type( self, - agent_type, + agent_type: EntityURN, agent_info: AgentInfo, world_info: WorldInfo, scenario_info: ScenarioInfo, - ): + ) -> list[int]: num_channels = ( scenario_info.get_value(ScenarioInfoKeys.COMMUNICATION_CHANNELS_COUNT, 1) - 1 @@ -171,7 +192,7 @@ def get_channels_by_agent_type( ] return channels - def is_platoon_agent(self, agent_info, world_info): + def is_platoon_agent(self, agent_info: AgentInfo, world_info: WorldInfo) -> bool: agent_type = self.get_agent_type(agent_info, world_info) return agent_type in [ EntityURN.FIRE_BRIGADE, @@ -179,7 +200,9 @@ def is_platoon_agent(self, agent_info, world_info): EntityURN.AMBULANCE_TEAM, ] - def get_agent_type(self, agent_info: AgentInfo, world_info: WorldInfo): + def get_agent_type( + self, agent_info: AgentInfo, world_info: WorldInfo + ) -> Optional[EntityURN]: entity = world_info.get_entity(agent_info.get_entity_id()) if entity is None: return None @@ -192,9 +215,9 @@ def set_send_messages( agent_info: AgentInfo, world_info: WorldInfo, messages: list[StandardMessage], - channel_send_message_list, - channel_size, - ): + channel_send_message_list: list[list[CommunicationMessage]], + channel_size: list[int], + ) -> None: channels = self.get_channels_by_agent_type( agent_type, agent_info, world_info, scenario_info ) diff --git a/adf_core_python/implement/tactics/default_tactics_ambulance_team.py b/adf_core_python/implement/tactics/default_tactics_ambulance_team.py index 7a30dee8..f2ebf21a 100644 --- a/adf_core_python/implement/tactics/default_tactics_ambulance_team.py +++ b/adf_core_python/implement/tactics/default_tactics_ambulance_team.py @@ -18,7 +18,7 @@ CommandScout, ) from adf_core_python.core.agent.communication.standard.bundle.centralized.message_report import ( - CommandReport, + MessageReport, ) from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( StandardMessagePriority, @@ -178,7 +178,7 @@ def think( ) ) message_manager.add_message( - CommandReport( + MessageReport( False, True, True, From ae093ef703ce23db6e0b566368732b6657ed34d6 Mon Sep 17 00:00:00 2001 From: shima004 Date: Thu, 14 Nov 2024 02:46:32 +0900 Subject: [PATCH 7/8] add: __init__ file --- adf_core_python/core/agent/__init__.py | 0 adf_core_python/core/agent/action/__init__.py | 0 adf_core_python/core/agent/action/ambulance/__init__.py | 0 adf_core_python/core/agent/action/common/__init__.py | 0 adf_core_python/core/agent/action/fire/__init__.py | 0 adf_core_python/core/agent/action/police/__init__.py | 0 adf_core_python/core/agent/info/__init__.py | 0 adf_core_python/core/agent/platoon/__init__.py | 0 adf_core_python/core/agent/precompute/__init__.py | 0 adf_core_python/core/component/action/__init__.py | 0 adf_core_python/core/component/module/__init__.py | 0 adf_core_python/core/component/module/algorithm/__init__.py | 0 adf_core_python/core/component/module/complex/__init__.py | 0 adf_core_python/core/component/tactics/__init__.py | 0 adf_core_python/core/config/__init__.py | 0 adf_core_python/core/launcher/__init__.py | 0 adf_core_python/core/launcher/connect/__init__.py | 0 adf_core_python/core/logger/__init__.py | 0 adf_core_python/implement/__init__.py | 0 adf_core_python/implement/action/__init__.py | 0 adf_core_python/implement/module/communication/__init__.py | 0 adf_core_python/implement/tactics/__init__.py | 0 22 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 adf_core_python/core/agent/__init__.py create mode 100644 adf_core_python/core/agent/action/__init__.py create mode 100644 adf_core_python/core/agent/action/ambulance/__init__.py create mode 100644 adf_core_python/core/agent/action/common/__init__.py create mode 100644 adf_core_python/core/agent/action/fire/__init__.py create mode 100644 adf_core_python/core/agent/action/police/__init__.py create mode 100644 adf_core_python/core/agent/info/__init__.py create mode 100644 adf_core_python/core/agent/platoon/__init__.py create mode 100644 adf_core_python/core/agent/precompute/__init__.py create mode 100644 adf_core_python/core/component/action/__init__.py create mode 100644 adf_core_python/core/component/module/__init__.py create mode 100644 adf_core_python/core/component/module/algorithm/__init__.py create mode 100644 adf_core_python/core/component/module/complex/__init__.py create mode 100644 adf_core_python/core/component/tactics/__init__.py create mode 100644 adf_core_python/core/config/__init__.py create mode 100644 adf_core_python/core/launcher/__init__.py create mode 100644 adf_core_python/core/launcher/connect/__init__.py create mode 100644 adf_core_python/core/logger/__init__.py create mode 100644 adf_core_python/implement/__init__.py create mode 100644 adf_core_python/implement/action/__init__.py create mode 100644 adf_core_python/implement/module/communication/__init__.py create mode 100644 adf_core_python/implement/tactics/__init__.py diff --git a/adf_core_python/core/agent/__init__.py b/adf_core_python/core/agent/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/action/__init__.py b/adf_core_python/core/agent/action/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/action/ambulance/__init__.py b/adf_core_python/core/agent/action/ambulance/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/action/common/__init__.py b/adf_core_python/core/agent/action/common/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/action/fire/__init__.py b/adf_core_python/core/agent/action/fire/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/action/police/__init__.py b/adf_core_python/core/agent/action/police/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/info/__init__.py b/adf_core_python/core/agent/info/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/platoon/__init__.py b/adf_core_python/core/agent/platoon/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/agent/precompute/__init__.py b/adf_core_python/core/agent/precompute/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/component/action/__init__.py b/adf_core_python/core/component/action/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/component/module/__init__.py b/adf_core_python/core/component/module/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/component/module/algorithm/__init__.py b/adf_core_python/core/component/module/algorithm/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/component/module/complex/__init__.py b/adf_core_python/core/component/module/complex/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/component/tactics/__init__.py b/adf_core_python/core/component/tactics/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/config/__init__.py b/adf_core_python/core/config/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/launcher/__init__.py b/adf_core_python/core/launcher/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/launcher/connect/__init__.py b/adf_core_python/core/launcher/connect/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/core/logger/__init__.py b/adf_core_python/core/logger/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/implement/__init__.py b/adf_core_python/implement/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/implement/action/__init__.py b/adf_core_python/implement/action/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/implement/module/communication/__init__.py b/adf_core_python/implement/module/communication/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/adf_core_python/implement/tactics/__init__.py b/adf_core_python/implement/tactics/__init__.py new file mode 100644 index 00000000..e69de29b From 86f1c2770fa805ef1cb9a0d3360e4f1525e5580a Mon Sep 17 00:00:00 2001 From: shima004 Date: Thu, 14 Nov 2024 02:48:15 +0900 Subject: [PATCH 8/8] refactor: remove unused command imports and message additions from DefaultTacticsAmbulanceTeam --- .../tactics/default_tactics_ambulance_team.py | 68 ------------------- 1 file changed, 68 deletions(-) diff --git a/adf_core_python/implement/tactics/default_tactics_ambulance_team.py b/adf_core_python/implement/tactics/default_tactics_ambulance_team.py index f2ebf21a..857d724d 100644 --- a/adf_core_python/implement/tactics/default_tactics_ambulance_team.py +++ b/adf_core_python/implement/tactics/default_tactics_ambulance_team.py @@ -5,24 +5,6 @@ from adf_core_python.core.agent.action.action import Action from adf_core_python.core.agent.action.common.action_rest import ActionRest from adf_core_python.core.agent.communication.message_manager import MessageManager -from adf_core_python.core.agent.communication.standard.bundle.centralized.command_ambulance import ( - CommandAmbulance, -) -from adf_core_python.core.agent.communication.standard.bundle.centralized.command_fire import ( - CommandFire, -) -from adf_core_python.core.agent.communication.standard.bundle.centralized.command_police import ( - CommandPolice, -) -from adf_core_python.core.agent.communication.standard.bundle.centralized.command_scout import ( - CommandScout, -) -from adf_core_python.core.agent.communication.standard.bundle.centralized.message_report import ( - MessageReport, -) -from adf_core_python.core.agent.communication.standard.bundle.standard_message_priority import ( - StandardMessagePriority, -) from adf_core_python.core.agent.develop.develop_data import DevelopData from adf_core_python.core.agent.info.agent_info import AgentInfo from adf_core_python.core.agent.info.scenario_info import Mode, ScenarioInfo @@ -137,56 +119,6 @@ def think( agent: AmbulanceTeamEntity = cast(AmbulanceTeamEntity, agent_info.get_myself()) # noqa: F841 entity_id = agent_info.get_entity_id() # noqa: F841 - message_manager.add_message( - CommandAmbulance( - False, - entity_id, - entity_id, - CommandAmbulance.ACTION_REST, - StandardMessagePriority.NORMAL, - entity_id, - ) - ) - message_manager.add_message( - CommandFire( - False, - entity_id, - entity_id, - CommandFire.ACTION_REST, - StandardMessagePriority.NORMAL, - entity_id, - ) - ) - message_manager.add_message( - CommandPolice( - False, - entity_id, - entity_id, - CommandPolice.ACTION_REST, - StandardMessagePriority.NORMAL, - entity_id, - ) - ) - message_manager.add_message( - CommandScout( - False, - entity_id, - entity_id, - 20000, - StandardMessagePriority.NORMAL, - entity_id, - ) - ) - message_manager.add_message( - MessageReport( - False, - True, - True, - entity_id, - StandardMessagePriority.NORMAL, - ) - ) - self._logger.debug( f"received messages: {[str(message) for message in message_manager.get_received_message_list()]}, help: {message_manager.get_heard_agent_help_message_count()}", message_manager=message_manager,