diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c67fc75..b0da406 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -22,14 +22,6 @@ jobs: with: python-version: 3.12 - - name: Cache pip - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - name: Cache virtual environment uses: actions/cache@v4 with: diff --git a/adf_core_python/core/agent/action/common/action_move.py b/adf_core_python/core/agent/action/common/action_move.py index 06dc150..a693817 100644 --- a/adf_core_python/core/agent/action/common/action_move.py +++ b/adf_core_python/core/agent/action/common/action_move.py @@ -15,19 +15,19 @@ class ActionMove(Action): def __init__( self, path: list[EntityID], - destinationX: Optional[int] = None, - destinationY: Optional[int] = None, + destination_x: Optional[int] = None, + destination_y: Optional[int] = None, ) -> None: self.path = path - self.destinationX = destinationX - self.destinationY = destinationY + self.destination_x = destination_x + self.destination_y = destination_y def get_command(self, agent_id: EntityID, time: int) -> Command: path: list[int] = [p.get_value() for p in self.path] - if self.destinationX is not None and self.destinationY is not None: - return AKMove(agent_id, time, path, self.destinationX, self.destinationY) + if self.destination_x is not None and self.destination_y is not None: + return AKMove(agent_id, time, path, self.destination_x, self.destination_y) else: return AKMove(agent_id, time, path) def __str__(self) -> str: - return f"ActionMove(path={self.path}, destinationX={self.destinationX}, destinationY={self.destinationY})" + return f"ActionMove(path={self.path}, destination_x={self.destination_x}, destination_y{self.destination_y})" diff --git a/adf_core_python/core/agent/agent.py b/adf_core_python/core/agent/agent.py new file mode 100644 index 0000000..ae19b1e --- /dev/null +++ b/adf_core_python/core/agent/agent.py @@ -0,0 +1,30 @@ +from rcrs_core.entities.entity import Entity + +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 + + +class Agent(Entity): + def __init__( + self, + team_name: str, + is_precompute: bool, + is_debug: bool, + data_storage_name: str, + module_config: ModuleConfig, + develop_data: DevelopData, + ): + self._tema_name = team_name + self._is_precompute = is_precompute + self._is_debug = is_debug + + if self._is_precompute: + # PrecomputeData.remove_data(data_storage_name) + self._mode = Mode.PRECOMPUTATION + + self._module_config: ModuleConfig = module_config + self._develop_data: DevelopData = develop_data + self._precompute_data: PrecomputeData = PrecomputeData(data_storage_name) + self._message_manager = None diff --git a/adf_core_python/core/agent/info/scenario_info.py b/adf_core_python/core/agent/info/scenario_info.py index 6a2d699..099b7f2 100644 --- a/adf_core_python/core/agent/info/scenario_info.py +++ b/adf_core_python/core/agent/info/scenario_info.py @@ -1,6 +1,6 @@ from enum import Enum -from rcrs_core.config.config import Config +from adf_core_python.core.config.config import Config class Mode(Enum): @@ -71,4 +71,4 @@ def get_config_value(self, key: str, default: str) -> str: str Value of the configuration """ - return self._config.get_value_or_default(key, default) + return self._config.get_value(key, default) diff --git a/adf_core_python/core/agent/info/world_info.py b/adf_core_python/core/agent/info/world_info.py index c765a82..076fe0e 100644 --- a/adf_core_python/core/agent/info/world_info.py +++ b/adf_core_python/core/agent/info/world_info.py @@ -1,5 +1,6 @@ from typing import Any +from rcrs_core.worldmodel.changeSet import ChangeSet from rcrs_core.worldmodel.entityID import EntityID from rcrs_core.worldmodel.worldmodel import WorldModel @@ -10,6 +11,7 @@ def __init__(self, world_model: WorldModel): self._time: int = 0 self._is_run_rollback: bool = False self._rollback: dict[EntityID, dict[int, dict[int, Any]]] = {} + self._change_set: ChangeSet # TODO: Implement the worldmodel access methods def get_world_model(self) -> WorldModel: @@ -22,3 +24,14 @@ def get_world_model(self) -> WorldModel: World model """ return self._world_model + + def set_change_set(self, change_set: ChangeSet) -> None: + """ + Set the change set + + Parameters + ---------- + change_set : ChangeSet + Change set + """ + self._change_set = change_set diff --git a/adf_core_python/core/agent/platoon/platoon.py b/adf_core_python/core/agent/platoon/platoon.py new file mode 100644 index 0000000..4b231e6 --- /dev/null +++ b/adf_core_python/core/agent/platoon/platoon.py @@ -0,0 +1,102 @@ +from logging import Logger, getLogger + +from rcrs_core.agents.agent import Agent +from rcrs_core.commands.Command import Command +from rcrs_core.worldmodel.changeSet import ChangeSet + +from adf_core_python.core.agent.action.action import Action +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.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 + + +class Platoon(Agent): + def __init__( + self, + tactics_agent: TacticsAgent, + team_name: str, + is_precompute: bool, + is_debug: bool, + data_storage_name: str, + module_config: ModuleConfig, + develop_data: DevelopData, + ) -> None: + super().__init__( + is_precompute, + ) + self._tactics_agent = tactics_agent + self._team_name = team_name + self._is_precompute = is_precompute + self._is_debug = is_debug + self._data_storage_name = data_storage_name + self._module_config = module_config + self._develop_data = develop_data + + def post_connect(self) -> None: + self._logger: Logger = getLogger(__name__) + 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) + + 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 + + self._scenario_info: ScenarioInfo = ScenarioInfo(self.config, self._mode) # type: ignore + self._module_manager: ModuleManager = ModuleManager( + self._agent_info, + self._world_info, + self._scenario_info, + self._module_config, + self._develop_data, + ) + + self._tactics_agent.initialize( + self._agent_info, + self._world_info, + self._scenario_info, + self._module_manager, + self._precompute_data, + MessageManager(), + self._develop_data, + ) + + match self._mode: + case Mode.PRECOMPUTATION: + pass + case Mode.PRECOMPUTED: + pass + case Mode.NON_PRECOMPUTE: + self._tactics_agent.prepare( + self._agent_info, + self._world_info, + self._scenario_info, + self._module_manager, + self._precompute_data, + self._develop_data, + ) + + def think(self, time: int, change_set: ChangeSet, hear: list[Command]) -> None: + action: Action = self._tactics_agent.think( + self._agent_info, + self._world_info, + self._scenario_info, + self._module_manager, + self._precompute_data, + MessageManager(), + 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)) diff --git a/adf_core_python/core/agent/platoon/platoon_ambulance.py b/adf_core_python/core/agent/platoon/platoon_ambulance.py new file mode 100644 index 0000000..e0d7fd7 --- /dev/null +++ b/adf_core_python/core/agent/platoon/platoon_ambulance.py @@ -0,0 +1,34 @@ +from rcrs_core.connection import URN + +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.platoon.platoon import Platoon +from adf_core_python.core.component.tactics.tactics_agent import TacticsAgent + + +class PlatoonAmbulance(Platoon): + def __init__( + self, + tactics_agent: TacticsAgent, + team_name: str, + is_precompute: bool, + is_debug: bool, + data_storage_name: str, + module_config: ModuleConfig, + develop_data: DevelopData, + ): + super().__init__( + tactics_agent, + team_name, + is_precompute, + is_debug, + data_storage_name, + module_config, + develop_data, + ) + + def precompute(self) -> None: + pass + + def get_requested_entities(self) -> list[str]: + return [URN.Entity.AMBULANCE_TEAM] diff --git a/adf_core_python/core/launcher/agent_launcher.py b/adf_core_python/core/launcher/agent_launcher.py index d73a499..f5b7fb1 100644 --- a/adf_core_python/core/launcher/agent_launcher.py +++ b/adf_core_python/core/launcher/agent_launcher.py @@ -35,7 +35,7 @@ def __init__(self, config: Config): self.connectors: list[Connector] = [] self.thread_list: list[threading.Thread] = [] - def initConnector(self) -> None: + def init_connector(self) -> None: loader_name, loader_class_name = self.config.get_value( ConfigKey.KEY_LOADER_CLASS, "adf_core_python.implement.default_loader.DefaultLoader", diff --git a/pyproject.toml b/pyproject.toml index 014b2f8..e9179d8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,7 +77,7 @@ target-version = "py312" # Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. # Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or # McCabe complexity (`C901`) by default. -select = ["E4", "E7", "E9", "F"] +select = ["E4", "E7", "E9", "F", "N8"] ignore = [] # Allow fix for all enabled rules (when `--fix`) is provided.