diff --git a/.DS_Store b/.DS_Store index 9c7a65b5c6b718343b6028f838bf4f25b066ebb6..dc44f3e6614782a35458620bbff21591bcf9b06b 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 5b46933c500ea68e82d5beb38f78765b7010d12d..3531263ad93e5c81309fdeda793d2926ad565c8b 100755 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ bin # Project precomp_data test-results + +.DS_Store \ No newline at end of file diff --git a/clean.sh b/clean.sh new file mode 100755 index 0000000000000000000000000000000000000000..f4e580b9d8760e680c5ccd62daf45d272789b6a2 --- /dev/null +++ b/clean.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +./gradlew clean diff --git a/compile.sh b/compile.sh new file mode 100755 index 0000000000000000000000000000000000000000..b6a01563082d05c345b1b2d978892b3b54ea6eec --- /dev/null +++ b/compile.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +cd `dirname $0` + +rm -rf build +mkdir build + +chmod +x gradlew +./gradlew build diff --git a/config/module.cfg b/config/module.cfg index af44b7579bcdf17aa02bb5e6831138a474c4af15..7421f824bb9a60b1f35b9b7ae1533e5a1a26e3ae 100755 --- a/config/module.cfg +++ b/config/module.cfg @@ -1,17 +1,17 @@ ## DefaultTacticsAmbulanceTeam -DefaultTacticsAmbulanceTeam.HumanDetector : sample_team.module.complex.SampleHumanDetector -DefaultTacticsAmbulanceTeam.Search : sample_team.module.complex.SampleSearch +DefaultTacticsAmbulanceTeam.HumanDetector : autumn_2023.module.complex.CentralizedControlATHumanDetector +DefaultTacticsAmbulanceTeam.Search : autumn_2023.module.complex.SampleSearch DefaultTacticsAmbulanceTeam.ExtActionTransport : adf.impl.extaction.DefaultExtActionTransport DefaultTacticsAmbulanceTeam.ExtActionMove : adf.impl.extaction.DefaultExtActionMove DefaultTacticsAmbulanceTeam.CommandExecutorAmbulance : adf.impl.centralized.DefaultCommandExecutorAmbulance DefaultTacticsAmbulanceTeam.CommandExecutorScout : adf.impl.centralized.DefaultCommandExecutorScout ## DefaultTacticsFireBrigade -DefaultTacticsFireBrigade.HumanDetector : sample_team.module.complex.SampleHumanDetector -DefaultTacticsFireBrigade.Search : sample_team.module.complex.SampleSearch -DefaultTacticsFireBrigade.ExtActionFireRescue : adf.impl.extaction.DefaultExtActionFireRescue +DefaultTacticsFireBrigade.HumanDetector : autumn_2023.module.complex.CentralizedControlFBHumanDetector +DefaultTacticsFireBrigade.Search : autumn_2023.module.complex.SampleSearch +DefaultTacticsFireBrigade.ExtActionFireRescue : autumn_2023.extaction.ComplimentTacticsExtActionFireRescue DefaultTacticsFireBrigade.ExtActionMove : adf.impl.extaction.DefaultExtActionMove -DefaultTacticsFireBrigade.CommandExecutorFire : adf.impl.centralized.DefaultCommandExecutorFire +DefaultTacticsFireBrigade.CommandExecutorFire : autumn_2023.centralized.CentralizedControlCommandExecutorFire DefaultTacticsFireBrigade.CommandExecutorScout : adf.impl.centralized.DefaultCommandExecutorScout ## DefaultTacticsPoliceForce @@ -27,8 +27,8 @@ DefaultTacticsAmbulanceCentre.TargetAllocator : sample_team.module.complex.Sampl DefaultTacticsAmbulanceCentre.CommandPicker : adf.impl.centralized.DefaultCommandPickerAmbulance ## DefaultTacticsFireStation -DefaultTacticsFireStation.TargetAllocator : sample_team.module.complex.SampleFireTargetAllocator -DefaultTacticsFireStation.CommandPicker : adf.impl.centralized.DefaultCommandPickerFire +DefaultTacticsFireStation.CommandPicker : autumn_2023.centralized.CentralizedControlCommandPickerFire +TacticsFireStation.TargetAllocator : autumn_2023.module.complex.CentralizedControlFBAllocator ## DefaultTacticsPoliceOffice DefaultTacticsPoliceOffice.TargetAllocator : sample_team.module.complex.SamplePoliceTargetAllocator @@ -75,8 +75,8 @@ DefaultCommandExecutorAmbulance.ExtActionMove : adf.impl.extaction.DefaultExtAct ## DefaultCommandExecutorFire DefaultCommandExecutorFire.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning -DefaultCommandExecutorFire.EtxActionFireRescue : adf.impl.extaction.DefaultExtActionFireRescue -DefaultCommandExecutorFire.EtxActionFireFighting : adf.impl.extaction.DefaultExtActionFireFighting +DefaultCommandExecutorFire.ExtActionFireRescue : autumn_2023.extaction.ComplimentTacticsExtActionFireRescue +DefaultCommandExecutorFire.ExtActionFireFighting : adf.impl.extaction.DefaultExtActionFireFighting DefaultCommandExecutorFire.ExtActionMove : adf.impl.extaction.DefaultExtActionMove ## DefaultCommandExecutorPolice @@ -92,10 +92,10 @@ DefaultCommandExecutorScoutPolice.PathPlanning : adf.impl.module.algorithm.Dijks DefaultCommandExecutorScoutPolice.ExtActionClear : adf.impl.extaction.DefaultExtActionClear ## MessageManager -MessageManager.PlatoonChannelSubscriber : adf.impl.module.comm.DefaultChannelSubscriber -MessageManager.CenterChannelSubscriber : adf.impl.module.comm.DefaultChannelSubscriber -MessageManager.PlatoonMessageCoordinator : adf.impl.module.comm.DefaultMessageCoordinator -MessageManager.CenterMessageCoordinator : adf.impl.module.comm.DefaultMessageCoordinator +MessageManager.PlatoonChannelSubscriber : autumn_2023.module.comm.CentralizedControlChannelSubscriber +MessageManager.CenterChannelSubscriber : autumn_2023.module.comm.CentralizedControlChannelSubscriber +MessageManager.PlatoonMessageCoordinator : autumn_2023.module.comm.CentralizedControlMessageCoordinator +MessageManager.CenterMessageCoordinator : autumn_2023.module.comm.CentralizedControlMessageCoordinator ## VisualDebug VisualDebug : true \ No newline at end of file diff --git a/docs/.DS_Store b/docs/.DS_Store index 26b27a2e5d6d384691db1aa916d47bd5fbdb815b..81fe50bda9452aa93a904087a5452c16494dc7b1 100644 Binary files a/docs/.DS_Store and b/docs/.DS_Store differ diff --git a/precompute.sh b/precompute.sh new file mode 100755 index 0000000000000000000000000000000000000000..acfa047e0121674b63b9b4ed0c527c8154df8b99 --- /dev/null +++ b/precompute.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +LOADER="adf.impl.DefaultLoader" +PARAMS=$* + +cd `dirname $0` + +if [ ! -z "$1" ]; then + ./gradlew launch --args="${LOADER} ${PARAMS} -pre 1" +else + echo "Options:" + echo "-tn Team name" + echo "-t [FB],[FS],[PF],[PO],[AT],[AC] Number of agents" + echo "-fb [FB] Number of FireBrigade" + echo "-fs [FS] Number of FireStation" + echo "-pf [PF] Number of PoliceForce" + echo "-po [PO] Number of PoliceOffice" + echo "-at [AT] Number of AmbulanceTeam" + echo "-ac [AC] Number of AmbulanceCentre" + echo "-s [HOST]:[PORT] RCRS server host and port" + echo "-h [HOST] RCRS server host (port:27931)" + echo "-pre [0|1] Precompute flag" + echo "-d [0|1] Debug flag" + echo "-dev [0|1] Development mode" + echo "-mc [FILE] ModuleConfig file name" + echo "-md [JSON] ModuleConfig JSON" + echo "-df [FILE] DevelopData JSON file" + echo "-dd [JSON] DevelopData JSON" + echo "-all [alias] -t -1,-1,-1,-1,-1,-1" + echo "-allp [alias] -t 1,0,1,0,1,0," + echo "-local [alias] -h localhost" + echo "-precompute [alias] -pre 1" + echo "-debug [alias] -d 1" + echo "-develop [alias] -dev 1" +fi diff --git a/src/main/java/autumn_2023/centralized/HungarianCommandExecutorAmbulance.java b/src/main/java/autumn_2023/centralized/CentralizedControlCommandExecutorFire.java similarity index 54% rename from src/main/java/autumn_2023/centralized/HungarianCommandExecutorAmbulance.java rename to src/main/java/autumn_2023/centralized/CentralizedControlCommandExecutorFire.java index 33309c96809dd361d4719a15c9f23cdad36c360e..2dc706a1fee1ba646fa305c36a9e77963e937e5d 100644 --- a/src/main/java/autumn_2023/centralized/HungarianCommandExecutorAmbulance.java +++ b/src/main/java/autumn_2023/centralized/CentralizedControlCommandExecutorFire.java @@ -1,12 +1,13 @@ package autumn_2023.centralized; -import static rescuecore2.standard.entities.StandardEntityURN.AMBULANCE_TEAM; import static rescuecore2.standard.entities.StandardEntityURN.CIVILIAN; import static rescuecore2.standard.entities.StandardEntityURN.REFUGE; + +import adf.core.agent.action.Action; import adf.core.agent.action.common.ActionMove; import adf.core.agent.action.common.ActionRest; import adf.core.agent.communication.MessageManager; -import adf.core.agent.communication.standard.bundle.centralized.CommandAmbulance; +import adf.core.agent.communication.standard.bundle.centralized.CommandFire; import adf.core.agent.communication.standard.bundle.centralized.MessageReport; import adf.core.agent.develop.DevelopData; import adf.core.agent.info.AgentInfo; @@ -25,60 +26,67 @@ import rescuecore2.standard.entities.Human; import rescuecore2.standard.entities.StandardEntity; import rescuecore2.worldmodel.EntityID; -public class HungarianCommandExecutorAmbulance - extends CommandExecutor { +public class CentralizedControlCommandExecutorFire extends CommandExecutor { private static final int ACTION_UNKNOWN = -1; - private static final int ACTION_REST = CommandAmbulance.ACTION_REST; - private static final int ACTION_MOVE = CommandAmbulance.ACTION_MOVE; - private static final int ACTION_RESCUE = CommandAmbulance.ACTION_RESCUE; - private static final int ACTION_LOAD = CommandAmbulance.ACTION_LOAD; - private static final int ACTION_UNLOAD = CommandAmbulance.ACTION_UNLOAD; - private static final int ACTION_AUTONOMY = CommandAmbulance.ACTION_AUTONOMY; + private static final int ACTION_REST = CommandFire.ACTION_REST; + private static final int ACTION_MOVE = CommandFire.ACTION_MOVE; + private static final int ACTION_RESCUE = CommandFire.ACTION_RESCUE; + private static final int ACTION_AUTONOMY = CommandFire.ACTION_AUTONOMY; private PathPlanning pathPlanning; - private ExtAction actionTransport; + private ExtAction actionFireRescue; private ExtAction actionExtMove; private int commandType; private EntityID target; private EntityID commanderID; - public HungarianCommandExecutorAmbulance(AgentInfo ai, WorldInfo wi, ScenarioInfo si, ModuleManager moduleManager, DevelopData developData) { + private boolean commandCompleted; + + public CentralizedControlCommandExecutorFire(AgentInfo ai, WorldInfo wi, ScenarioInfo si, ModuleManager moduleManager, DevelopData developData) { super(ai, wi, si, moduleManager, developData); this.commandType = ACTION_UNKNOWN; + this.target = null; + this.commanderID = null; switch (scenarioInfo.getMode()) { case PRECOMPUTATION_PHASE: case PRECOMPUTED: case NON_PRECOMPUTE: this.pathPlanning = moduleManager.getModule( - "DefaultCommandExecutorAmbulance.PathPlanning", + "DefaultCommandExecutorFire.PathPlanning", "adf.impl.module.algorithm.DijkstraPathPlanning"); - this.actionTransport = moduleManager.getExtAction( - "DefaultCommandExecutorAmbulance.ExtActionTransport", - "adf.impl.extaction.DefaultExtActionTransport"); + this.actionFireRescue = moduleManager.getExtAction( + "DefaultCommandExecutorFire.ExtActionFireRescue", + "adf.impl.extaction.DefaultExtActionFireRescue"); this.actionExtMove = moduleManager.getExtAction( - "DefaultCommandExecutorAmbulance.ExActionMove", + "DefaultCommandExecutorFire.ExtActionMove", "adf.impl.extaction.DefaultExtActionMove"); break; } } - + /** + * 受信した司令を入力するためのメソッド + * @param command 受信した司令 + */ @Override - public CommandExecutor setCommand(CommandAmbulance command) { + public CommandExecutor setCommand(CommandFire command) { EntityID agentID = this.agentInfo.getID(); - if (command.isToIDDefined() && Objects.requireNonNull(command.getToID()) - .getValue() == agentID.getValue()) { - this.commandType = command.getAction(); - this.target = command.getTargetID(); - this.commanderID = command.getSenderID(); + if(!this.commandCompleted) return this; + if (command.isToIDDefined() && Objects.requireNonNull(command.getToID()).getValue() == agentID.getValue()) { + this.commandType = command.getAction();// 司令で出された行動内容 + this.target = command.getTargetID();// タスクとなる対象のID + this.commanderID = command.getSenderID();// 司令を出した司令所のID } return this; } - + /** + * 現在実行している司令が完了しているかを判定する + * 完了しているなら,消防司令所へ救助完了の報告を送る + */ @Override public CommandExecutor updateInfo(MessageManager messageManager) { super.updateInfo(messageManager); @@ -86,21 +94,17 @@ public class HungarianCommandExecutorAmbulance return this; } this.pathPlanning.updateInfo(messageManager); - this.actionTransport.updateInfo(messageManager); + this.actionFireRescue.updateInfo(messageManager); this.actionExtMove.updateInfo(messageManager); - if (this.isCommandCompleted()) { + this.commandCompleted = this.isCommandCompleted(this.commandType); + if (this.commandCompleted) { if (this.commandType != ACTION_UNKNOWN) { - messageManager - .addMessage(new MessageReport(true, true, false, this.commanderID)); - if (this.commandType == ACTION_LOAD) { - this.commandType = ACTION_UNLOAD; - this.target = null; - } else { - this.commandType = ACTION_UNKNOWN; - this.target = null; - this.commanderID = null; - } + messageManager.addMessage(new MessageReport(true, true, false, this.target)); + + this.commandType = ACTION_UNKNOWN; + this.target = null; + this.commanderID = null; } } return this; @@ -114,7 +118,7 @@ public class HungarianCommandExecutorAmbulance return this; } this.pathPlanning.precompute(precomputeData); - this.actionTransport.precompute(precomputeData); + this.actionFireRescue.precompute(precomputeData); this.actionExtMove.precompute(precomputeData); return this; } @@ -127,7 +131,7 @@ public class HungarianCommandExecutorAmbulance return this; } this.pathPlanning.resume(precomputeData); - this.actionTransport.resume(precomputeData); + this.actionFireRescue.resume(precomputeData); this.actionExtMove.resume(precomputeData); return this; } @@ -140,12 +144,17 @@ public class HungarianCommandExecutorAmbulance return this; } this.pathPlanning.preparate(); - this.actionTransport.preparate(); + this.actionFireRescue.preparate(); this.actionExtMove.preparate(); return this; } - + /** + * 受け取った司令を元に行動を決定・実行するためのメソッド + * + * 司令で出された行動内容によって救助活動を決定する + * ※実装では司令で出される行動内容はACTION_AUTONOMYになっている + */ @Override public CommandExecutor calc() { this.result = null; @@ -153,8 +162,7 @@ public class HungarianCommandExecutorAmbulance case ACTION_REST: EntityID position = this.agentInfo.getPosition(); if (this.target == null) { - Collection< - EntityID> refuges = this.worldInfo.getEntityIDsOfType(REFUGE); + Collection refuges = this.worldInfo.getEntityIDsOfType(REFUGE); if (refuges.contains(position)) { this.result = new ActionRest(); } else { @@ -181,26 +189,12 @@ public class HungarianCommandExecutorAmbulance return this; case ACTION_MOVE: if (this.target != null) { - this.result = this.actionExtMove.setTarget(this.target).calc() - .getAction(); + this.result = this.actionExtMove.setTarget(this.target).calc().getAction(); } return this; case ACTION_RESCUE: if (this.target != null) { - this.result = this.actionTransport.setTarget(this.target).calc() - .getAction(); - } - return this; - case ACTION_LOAD: - if (this.target != null) { - this.result = this.actionTransport.setTarget(this.target).calc() - .getAction(); - } - return this; - case ACTION_UNLOAD: - if (this.target != null) { - this.result = this.actionTransport.setTarget(this.target).calc() - .getAction(); + this.result = this.actionFireRescue.setTarget(this.target).calc().getAction(); } return this; case ACTION_AUTONOMY: @@ -209,25 +203,23 @@ public class HungarianCommandExecutorAmbulance } StandardEntity targetEntity = this.worldInfo.getEntity(this.target); if (targetEntity instanceof Area) { - if (this.agentInfo.someoneOnBoard() == null) { - this.result = this.actionExtMove.setTarget(this.target).calc() - .getAction(); - } else { - this.result = this.actionTransport.setTarget(this.target).calc() - .getAction(); - } + this.result = this.actionExtMove.setTarget(this.target).calc().getAction(); } else if (targetEntity instanceof Human) { - this.result = this.actionTransport.setTarget(this.target).calc() - .getAction(); + this.result = this.actionFireRescue.setTarget(this.target).calc().getAction(); } } return this; } - - private boolean isCommandCompleted() { + /** + * 司令が完了したかを判定するメソッド + * + * @param commandType 司令の種類 + * @return true : 完了 false : 実行中 + */ + private boolean isCommandCompleted(int commandType) { Human agent = (Human) this.agentInfo.me(); - switch (this.commandType) { + switch (commandType) { case ACTION_REST: if (this.target == null) { return (agent.getDamage() == 0); @@ -246,61 +238,19 @@ public class HungarianCommandExecutorAmbulance if (this.target == null) { return true; } - Human human = (Human) Objects - .requireNonNull(this.worldInfo.getEntity(this.target)); + Human human = (Human) Objects.requireNonNull(this.worldInfo.getEntity(this.target)); return human.isBuriednessDefined() && human.getBuriedness() == 0 || (human.isHPDefined() && human.getHP() == 0); - case ACTION_LOAD: - if (this.target == null) { - return true; - } - Human human1 = (Human) Objects - .requireNonNull(this.worldInfo.getEntity(this.target)); - if ((human1.isHPDefined() && human1.getHP() == 0)) { - return true; - } - if (human1.getStandardURN() != CIVILIAN) { - this.commandType = ACTION_RESCUE; - return this.isCommandCompleted(); - } - if (human1.isPositionDefined()) { - EntityID position = human1.getPosition(); - if (this.worldInfo.getEntityIDsOfType(AMBULANCE_TEAM) - .contains(position)) { - return true; - } else if (this.worldInfo.getEntity(position) - .getStandardURN() == REFUGE) { - return true; - } - } - return false; - case ACTION_UNLOAD: - if (this.target != null) { - StandardEntity entity = this.worldInfo.getEntity(this.target); - if (entity != null && entity instanceof Area) { - if (this.target.getValue() != this.agentInfo.getPosition() - .getValue()) { - return false; - } - } - } - return (this.agentInfo.someoneOnBoard() == null); + case ACTION_AUTONOMY: if (this.target != null) { StandardEntity targetEntity = this.worldInfo.getEntity(this.target); if (targetEntity instanceof Area) { - this.commandType = this.agentInfo.someoneOnBoard() == null - ? ACTION_MOVE - : ACTION_UNLOAD; - return this.isCommandCompleted(); + commandType = ACTION_MOVE; + return this.isCommandCompleted(commandType); } else if (targetEntity instanceof Human) { - Human h = (Human) targetEntity; - if ((h.isHPDefined() && h.getHP() == 0)) { - return true; - } - this.commandType = h.getStandardURN() == CIVILIAN ? ACTION_LOAD - : ACTION_RESCUE; - return this.isCommandCompleted(); + commandType = ACTION_RESCUE; + return this.isCommandCompleted(commandType); } } return true; diff --git a/src/main/java/autumn_2023/centralized/CentralizedControlCommandPickerFire.java b/src/main/java/autumn_2023/centralized/CentralizedControlCommandPickerFire.java new file mode 100644 index 0000000000000000000000000000000000000000..b6b736e881adf0c6a5e878fa889ac65df625de95 --- /dev/null +++ b/src/main/java/autumn_2023/centralized/CentralizedControlCommandPickerFire.java @@ -0,0 +1,83 @@ +package autumn_2023.centralized; + +import adf.core.agent.communication.standard.bundle.centralized.CommandFire; +import adf.core.agent.communication.standard.bundle.centralized.CommandScout; +import adf.core.agent.develop.DevelopData; +import adf.core.agent.info.AgentInfo; +import adf.core.agent.info.ScenarioInfo; +import adf.core.agent.info.WorldInfo; +import adf.core.agent.module.ModuleManager; +import adf.core.component.centralized.CommandPicker; +import adf.core.component.communication.CommunicationMessage; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import rescuecore2.standard.entities.Area; +import rescuecore2.standard.entities.Human; +import rescuecore2.standard.entities.StandardEntity; +import rescuecore2.standard.entities.StandardEntityURN; +import rescuecore2.worldmodel.EntityID; + +public class CentralizedControlCommandPickerFire extends CommandPicker { + + private int scoutDistance; + + private Collection messages; + private Map allocationData; + + public CentralizedControlCommandPickerFire(AgentInfo ai, WorldInfo wi, ScenarioInfo si, ModuleManager moduleManager, DevelopData developData) { + super(ai, wi, si, moduleManager, developData); + this.messages = new ArrayList<>(); + this.allocationData = null; + this.scoutDistance = developData.getInteger( + "adf.impl.centralized.DefaultCommandPickerFire.scoutDistance", 40000); + } + + /** + * TargetAllocatorの計算結果を入力するためのメソッド + * + * @param allocationData TargetAllocatorのgetResultメソッドの戻り値 + */ + @Override + public CommandPicker + setAllocatorResult(Map allocationData) { + this.allocationData = allocationData; + return this; + } + + /** + * 司令を生成・リスト化するためのメソッド + * 司令はTargetAllocatorから受け取った司令内容をもとに生成される + */ + @Override + public CommandPicker calc() { + this.messages.clear(); + if (this.allocationData == null) { + return this; + } + for (EntityID agentID : this.allocationData.keySet()) { + StandardEntity agent = this.worldInfo.getEntity(agentID); + if (agent != null + && agent.getStandardURN() == StandardEntityURN.FIRE_BRIGADE) { + StandardEntity target = this.worldInfo.getEntity(this.allocationData.get(agentID)); + if (target != null) { + + if (target instanceof Human) { + CommandFire command = new CommandFire(true, agentID, target.getID(), CommandFire.ACTION_AUTONOMY); + this.messages.add(command); + } + } + } + } + return this; + } + + /** + * calcメソッドで生成した司令リストを取得するためのメソッド + * @return 司令リスト + */ + @Override + public Collection getResult() { + return this.messages; + } +} \ No newline at end of file diff --git a/src/main/java/autumn_2023/extaction/ComplimentTacticsExtActionFireRescue.java b/src/main/java/autumn_2023/extaction/ComplimentTacticsExtActionFireRescue.java new file mode 100644 index 0000000000000000000000000000000000000000..7290b5521b882e606182f8abab63c883b7afbc9d --- /dev/null +++ b/src/main/java/autumn_2023/extaction/ComplimentTacticsExtActionFireRescue.java @@ -0,0 +1,239 @@ +package autumn_2023.extaction; + +import static rescuecore2.standard.entities.StandardEntityURN.BLOCKADE; +import adf.core.agent.action.Action; +import adf.core.agent.action.ambulance.ActionRescue; +import adf.core.agent.action.common.ActionMove; +import adf.core.agent.communication.MessageManager; +import adf.core.agent.communication.standard.bundle.information.MessageFireBrigade; +import adf.core.agent.develop.DevelopData; +import adf.core.agent.info.AgentInfo; +import adf.core.agent.info.ScenarioInfo; +import adf.core.agent.info.WorldInfo; +import adf.core.agent.module.ModuleManager; +import adf.core.agent.precompute.PrecomputeData; +import adf.core.component.extaction.ExtAction; +import adf.core.component.module.algorithm.PathPlanning; +import java.util.ArrayList; +import java.util.List; +import rescuecore2.config.NoSuchConfigOptionException; +import rescuecore2.standard.entities.Area; +import rescuecore2.standard.entities.Blockade; +import rescuecore2.standard.entities.FireBrigade; +import rescuecore2.standard.entities.Human; +import rescuecore2.standard.entities.StandardEntity; +import rescuecore2.worldmodel.EntityID; + +// ADFのDefaultTacticsFireBrigadeの修正用プログラム 無視してよい +public class ComplimentTacticsExtActionFireRescue extends ExtAction { + + private MessageManager mm; + private PathPlanning pathPlanning; + + private int thresholdRest; + private int kernelTime; + + private EntityID target; + + public ComplimentTacticsExtActionFireRescue(AgentInfo agentInfo, WorldInfo worldInfo, ScenarioInfo scenarioInfo, ModuleManager moduleManager, DevelopData developData) { + super(agentInfo, worldInfo, scenarioInfo, moduleManager, developData); + this.target = null; + this.thresholdRest = developData + .getInteger("adf.impl.extaction.DefaultExtActionFireRescue.rest", 100); + + switch (scenarioInfo.getMode()) { + case PRECOMPUTATION_PHASE: + case PRECOMPUTED: + case NON_PRECOMPUTE: + this.pathPlanning = moduleManager.getModule( + "DefaultExtActionFireRescue.PathPlanning", + "adf.impl.module.algorithm.DijkstraPathPlanning"); + break; + } + } + + + public ExtAction precompute(PrecomputeData precomputeData) { + super.precompute(precomputeData); + if (this.getCountPrecompute() >= 2) { + return this; + } + this.pathPlanning.precompute(precomputeData); + try { + this.kernelTime = this.scenarioInfo.getKernelTimesteps(); + } catch (NoSuchConfigOptionException e) { + this.kernelTime = -1; + } + return this; + } + + + public ExtAction resume(PrecomputeData precomputeData) { + super.resume(precomputeData); + if (this.getCountResume() >= 2) { + return this; + } + this.pathPlanning.resume(precomputeData); + try { + this.kernelTime = this.scenarioInfo.getKernelTimesteps(); + } catch (NoSuchConfigOptionException e) { + this.kernelTime = -1; + } + return this; + } + + + public ExtAction preparate() { + super.preparate(); + if (this.getCountPreparate() >= 2) { + return this; + } + this.pathPlanning.preparate(); + try { + this.kernelTime = this.scenarioInfo.getKernelTimesteps(); + } catch (NoSuchConfigOptionException e) { + this.kernelTime = -1; + } + return this; + } + + + public ExtAction updateInfo(MessageManager messageManager) { + super.updateInfo(messageManager); + if (this.getCountUpdateInfo() >= 2) { + return this; + } + this.mm = messageManager; + this.pathPlanning.updateInfo(messageManager); + return this; + } + + + @Override + public ExtAction setTarget(EntityID target) { + this.target = null; + if (target != null) { + StandardEntity entity = this.worldInfo.getEntity(target); + if (entity instanceof Human || entity instanceof Area) { + this.target = target; + return this; + } + } + return this; + } + + + @Override + public ExtAction calc() { + this.result = null; + FireBrigade agent = (FireBrigade) this.agentInfo.me(); + + if (this.needRest(agent)) { + EntityID areaID = this.convertArea(this.target); + ArrayList targets = new ArrayList<>(); + if (areaID != null) { + targets.add(areaID); + } + } + if (this.target != null) { + this.result = this.calcRescue(agent, this.pathPlanning, this.target); + } + if(this.result != null){ + Class actionClass = this.result.getClass(); + if (actionClass == ActionRescue.class) { + this.mm.addMessage(new MessageFireBrigade(true, agent, MessageFireBrigade.ACTION_RESCUE, this.target)); + } + } + return this; + } + + + private Action calcRescue(FireBrigade agent, PathPlanning pathPlanning, + EntityID targetID) { + StandardEntity targetEntity = this.worldInfo.getEntity(targetID); + if (targetEntity == null) { + return null; + } + EntityID agentPosition = agent.getPosition(); + if (targetEntity instanceof Human) { + Human human = (Human) targetEntity; + if (!human.isPositionDefined()) { + return null; + } + if (human.isHPDefined() && human.getHP() == 0) { + return null; + } + EntityID targetPosition = human.getPosition(); + if (agentPosition.getValue() == targetPosition.getValue()) { + if (human.isBuriednessDefined() && human.getBuriedness() > 0) { + return new ActionRescue(human); + } + } else { + List path = pathPlanning.getResult(agentPosition, + targetPosition); + if (path != null && path.size() > 0) { + return new ActionMove(path); + } + } + return null; + } + if (targetEntity.getStandardURN() == BLOCKADE) { + Blockade blockade = (Blockade) targetEntity; + if (blockade.isPositionDefined()) { + targetEntity = this.worldInfo.getEntity(blockade.getPosition()); + } + } + if (targetEntity instanceof Area) { + List path = pathPlanning.getResult(agentPosition, + targetEntity.getID()); + if (path != null && path.size() > 0) { + return new ActionMove(path); + } + } + return null; + } + + + private boolean needRest(Human agent) { + int hp = agent.getHP(); + int damage = agent.getDamage(); + if (hp == 0 || damage == 0) { + return false; + } + int activeTime = (hp / damage) + ((hp % damage) != 0 ? 1 : 0); + if (this.kernelTime == -1) { + try { + this.kernelTime = this.scenarioInfo.getKernelTimesteps(); + } catch (NoSuchConfigOptionException e) { + this.kernelTime = -1; + } + } + return damage >= this.thresholdRest + || (activeTime + this.agentInfo.getTime()) < this.kernelTime; + } + + + private EntityID convertArea(EntityID targetID) { + StandardEntity entity = this.worldInfo.getEntity(targetID); + if (entity == null) { + return null; + } + if (entity instanceof Human) { + Human human = (Human) entity; + if (human.isPositionDefined()) { + EntityID position = human.getPosition(); + if (this.worldInfo.getEntity(position) instanceof Area) { + return position; + } + } + } else if (entity instanceof Area) { + return targetID; + } else if (entity.getStandardURN() == BLOCKADE) { + Blockade blockade = (Blockade) entity; + if (blockade.isPositionDefined()) { + return blockade.getPosition(); + } + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/autumn_2023/module/comm/CentralizedControlChannelSubscriber.java b/src/main/java/autumn_2023/module/comm/CentralizedControlChannelSubscriber.java new file mode 100644 index 0000000000000000000000000000000000000000..e945e7ba5a94e9fb96188a5b8556d0fcca78cf68 --- /dev/null +++ b/src/main/java/autumn_2023/module/comm/CentralizedControlChannelSubscriber.java @@ -0,0 +1,100 @@ +package autumn_2023.module.comm; + +import adf.core.agent.communication.MessageManager; +import adf.core.agent.info.AgentInfo; +import adf.core.agent.info.ScenarioInfo; +import adf.core.agent.info.WorldInfo; +import adf.core.component.communication.ChannelSubscriber; +import rescuecore2.standard.entities.StandardEntityURN; + +public class CentralizedControlChannelSubscriber extends ChannelSubscriber { + + @Override + public void subscribe(AgentInfo agentInfo, WorldInfo worldInfo, + ScenarioInfo scenarioInfo, MessageManager messageManager) { + // subscribe only once at the beginning + if (agentInfo.getTime() == 1) { + int numChannels = scenarioInfo.getCommsChannelsCount() - 1; // 0th channel + // is the + // voice + // channel + + int maxChannelCount = 0; + boolean isPlatoon = isPlatoonAgent(agentInfo, worldInfo); + if (isPlatoon) { + maxChannelCount = scenarioInfo.getCommsChannelsMaxPlatoon(); + } else { + maxChannelCount = scenarioInfo.getCommsChannelsMaxOffice(); + } + + StandardEntityURN agentType = getAgentType(agentInfo, worldInfo); + int[] channels = new int[maxChannelCount]; + for (int i = 0; i < maxChannelCount; i++) { + channels[i] = getChannelNumber(agentType, i, numChannels); + } + + messageManager.subscribeToChannels(channels); + } + } + + + protected boolean isPlatoonAgent(AgentInfo agentInfo, WorldInfo worldInfo) { + StandardEntityURN agentType = getAgentType(agentInfo, worldInfo); + if (agentType == StandardEntityURN.FIRE_BRIGADE + || agentType == StandardEntityURN.POLICE_FORCE + || agentType == StandardEntityURN.AMBULANCE_TEAM) { + return true; + } + return false; + } + + + protected StandardEntityURN getAgentType(AgentInfo agentInfo, + WorldInfo worldInfo) { + StandardEntityURN agentType = worldInfo.getEntity(agentInfo.getID()) + .getStandardURN(); + return agentType; + } + + + public static int getChannelNumber(StandardEntityURN agentType, + int channelIndex, int numChannels) { + int agentIndex = 0; + if (agentType == StandardEntityURN.FIRE_BRIGADE + || agentType == StandardEntityURN.FIRE_STATION) { + agentIndex = 1; + } else if (agentType == StandardEntityURN.POLICE_FORCE + || agentType == StandardEntityURN.POLICE_OFFICE) { + agentIndex = 2; + } else if (agentType == StandardEntityURN.AMBULANCE_TEAM + || agentType == StandardEntityURN.AMBULANCE_CENTRE) { + agentIndex = 3; + } + + int index = (3 * channelIndex) + agentIndex; + if ((index % numChannels) == 0) { + index = numChannels; + } else { + index = index % numChannels; + } + return index; + } + + + public static void main(String[] args) { + int numChannels = 6; + int maxChannels = 2; + for (int i = 0; i < maxChannels; i++) { + System.out.println("FIREBRIGADE-" + i + ":" + + getChannelNumber(StandardEntityURN.FIRE_BRIGADE, i, numChannels)); + } + for (int i = 0; i < maxChannels; i++) { + System.out.println("POLICE-" + i + ":" + + getChannelNumber(StandardEntityURN.POLICE_OFFICE, i, numChannels)); + } + for (int i = 0; i < maxChannels; i++) { + System.out.println("AMB-" + i + ":" + getChannelNumber( + StandardEntityURN.AMBULANCE_CENTRE, i, numChannels)); + } + } +} \ No newline at end of file diff --git a/src/main/java/autumn_2023/module/comm/CentralizedControlMessageCoordinator.java b/src/main/java/autumn_2023/module/comm/CentralizedControlMessageCoordinator.java new file mode 100644 index 0000000000000000000000000000000000000000..5272c14906efb32455a050b09391af7bbc4b01b9 --- /dev/null +++ b/src/main/java/autumn_2023/module/comm/CentralizedControlMessageCoordinator.java @@ -0,0 +1,211 @@ +package autumn_2023.module.comm; + +import adf.core.agent.communication.MessageManager; +import adf.core.agent.communication.standard.bundle.StandardMessage; +import adf.core.agent.communication.standard.bundle.StandardMessagePriority; +import adf.core.agent.communication.standard.bundle.centralized.CommandAmbulance; +import adf.core.agent.communication.standard.bundle.centralized.CommandFire; +import adf.core.agent.communication.standard.bundle.centralized.CommandPolice; +import adf.core.agent.communication.standard.bundle.centralized.CommandScout; +import adf.core.agent.communication.standard.bundle.centralized.MessageReport; +import adf.core.agent.communication.standard.bundle.information.MessageAmbulanceTeam; +import adf.core.agent.communication.standard.bundle.information.MessageBuilding; +import adf.core.agent.communication.standard.bundle.information.MessageCivilian; +import adf.core.agent.communication.standard.bundle.information.MessageFireBrigade; +import adf.core.agent.communication.standard.bundle.information.MessagePoliceForce; +import adf.core.agent.communication.standard.bundle.information.MessageRoad; +import adf.core.agent.info.AgentInfo; +import adf.core.agent.info.ScenarioInfo; +import adf.core.agent.info.WorldInfo; +import adf.core.component.communication.CommunicationMessage; +import adf.core.component.communication.MessageCoordinator; +import adf.impl.module.comm.DefaultChannelSubscriber; + +import java.util.ArrayList; +import java.util.List; +import rescuecore2.standard.entities.StandardEntityURN; + +public class CentralizedControlMessageCoordinator extends MessageCoordinator { + + @Override + public void coordinate(AgentInfo agentInfo, WorldInfo worldInfo, + ScenarioInfo scenarioInfo, MessageManager messageManager, + ArrayList sendMessageList, + List> channelSendMessageList) { + + // have different lists for every agent + ArrayList policeMessages = new ArrayList<>(); + ArrayList ambulanceMessages = new ArrayList<>(); + ArrayList fireBrigadeMessages = new ArrayList<>(); + + ArrayList voiceMessages = new ArrayList<>(); + + StandardEntityURN agentType = getAgentType(agentInfo, worldInfo); + + for (CommunicationMessage msg : sendMessageList) { + if (msg instanceof StandardMessage + && !((StandardMessage) msg).isRadio()) { + voiceMessages.add(msg); + } else { + if (msg instanceof MessageBuilding) { + fireBrigadeMessages.add(msg); + } else if (msg instanceof MessageCivilian) { + fireBrigadeMessages.add(msg); + ambulanceMessages.add(msg); + } else if (msg instanceof MessageRoad) { + fireBrigadeMessages.add(msg); + ambulanceMessages.add(msg); + policeMessages.add(msg); + } else if (msg instanceof CommandAmbulance) { + ambulanceMessages.add(msg); + } else if (msg instanceof CommandFire) { + fireBrigadeMessages.add(msg); + } else if (msg instanceof CommandPolice) { + policeMessages.add(msg); + } else if (msg instanceof CommandScout) { + if (agentType == StandardEntityURN.FIRE_STATION) { + fireBrigadeMessages.add(msg); + } else if (agentType == StandardEntityURN.POLICE_OFFICE) { + policeMessages.add(msg); + } else if (agentType == StandardEntityURN.AMBULANCE_CENTRE) { + ambulanceMessages.add(msg); + } + } else if (msg instanceof MessageReport) { + if (agentType == StandardEntityURN.FIRE_BRIGADE) { + fireBrigadeMessages.add(msg); + } else if (agentType == StandardEntityURN.POLICE_FORCE) { + policeMessages.add(msg); + } else if (agentType == StandardEntityURN.AMBULANCE_TEAM) { + ambulanceMessages.add(msg); + } + } else if (msg instanceof MessageFireBrigade) { + fireBrigadeMessages.add(msg); + ambulanceMessages.add(msg); + policeMessages.add(msg); + } else if (msg instanceof MessagePoliceForce) { + ambulanceMessages.add(msg); + policeMessages.add(msg); + } else if (msg instanceof MessageAmbulanceTeam) { + ambulanceMessages.add(msg); + policeMessages.add(msg); + } + } + } + + if (scenarioInfo.getCommsChannelsCount() > 1) { + // send radio messages if there are more than one communication channel + int[] channelSize = new int[scenarioInfo.getCommsChannelsCount() - 1]; + + setSendMessages(scenarioInfo, StandardEntityURN.POLICE_FORCE, agentInfo, + worldInfo, policeMessages, channelSendMessageList, channelSize); + setSendMessages(scenarioInfo, StandardEntityURN.AMBULANCE_TEAM, agentInfo, + worldInfo, ambulanceMessages, channelSendMessageList, channelSize); + setSendMessages(scenarioInfo, StandardEntityURN.FIRE_BRIGADE, agentInfo, + worldInfo, fireBrigadeMessages, channelSendMessageList, channelSize); + } + + ArrayList voiceMessageLowList = new ArrayList<>(); + ArrayList voiceMessageNormalList = new ArrayList<>(); + ArrayList voiceMessageHighList = new ArrayList<>(); + + for (CommunicationMessage msg : voiceMessages) { + if (msg instanceof StandardMessage) { + StandardMessage m = (StandardMessage) msg; + switch (m.getSendingPriority()) { + case LOW: + voiceMessageLowList.add(m); + break; + case NORMAL: + voiceMessageNormalList.add(m); + break; + case HIGH: + voiceMessageHighList.add(m); + break; + } + } + } + + // set the voice channel messages + channelSendMessageList.get(0).addAll(voiceMessageHighList); + channelSendMessageList.get(0).addAll(voiceMessageNormalList); + channelSendMessageList.get(0).addAll(voiceMessageLowList); + } + + + protected int[] getChannelsByAgentType(StandardEntityURN agentType, + AgentInfo agentInfo, WorldInfo worldInfo, ScenarioInfo scenarioInfo, + int channelIndex) { + int numChannels = scenarioInfo.getCommsChannelsCount() - 1; // 0th channel + // is the voice + // channel + int maxChannelCount = 0; + boolean isPlatoon = isPlatoonAgent(agentInfo, worldInfo); + if (isPlatoon) { + maxChannelCount = scenarioInfo.getCommsChannelsMaxPlatoon(); + } else { + maxChannelCount = scenarioInfo.getCommsChannelsMaxOffice(); + } + int[] channels = new int[maxChannelCount]; + + for (int i = 0; i < maxChannelCount; i++) { + channels[i] = DefaultChannelSubscriber.getChannelNumber(agentType, i, + numChannels); + } + + return channels; + } + + + protected boolean isPlatoonAgent(AgentInfo agentInfo, WorldInfo worldInfo) { + StandardEntityURN agentType = getAgentType(agentInfo, worldInfo); + if (agentType == StandardEntityURN.FIRE_BRIGADE + || agentType == StandardEntityURN.POLICE_FORCE + || agentType == StandardEntityURN.AMBULANCE_TEAM) { + return true; + } + return false; + } + + + protected StandardEntityURN getAgentType(AgentInfo agentInfo, + WorldInfo worldInfo) { + StandardEntityURN agentType = worldInfo.getEntity(agentInfo.getID()) + .getStandardURN(); + return agentType; + } + + + protected void setSendMessages(ScenarioInfo scenarioInfo, + StandardEntityURN agentType, AgentInfo agentInfo, WorldInfo worldInfo, + List messages, + List> channelSendMessageList, + int[] channelSize) { + int channelIndex = 0; + int[] channels = getChannelsByAgentType(agentType, agentInfo, worldInfo, + scenarioInfo, channelIndex); + int channel = channels[channelIndex]; + int channelCapacity = scenarioInfo.getCommsChannelBandwidth(channel); + // start from HIGH, NORMAL, to LOW + for (int i = StandardMessagePriority.values().length - 1; i >= 0; i--) { + for (CommunicationMessage msg : messages) { + StandardMessage smsg = (StandardMessage) msg; + if (smsg.getSendingPriority() == StandardMessagePriority.values()[i]) { + channelSize[channel - 1] += smsg.getByteArraySize(); + if (channelSize[channel - 1] > channelCapacity) { + channelSize[channel - 1] -= smsg.getByteArraySize(); + channelIndex++; + if (channelIndex < channels.length) { + channel = channels[channelIndex]; + channelCapacity = scenarioInfo.getCommsChannelBandwidth(channel); + channelSize[channel - 1] += smsg.getByteArraySize(); + } else { + // if there is no new channel for that message types, just break + break; + } + } + channelSendMessageList.get(channel).add(smsg); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/autumn_2023/module/complex/CentralizedControlATHumanDetector.java b/src/main/java/autumn_2023/module/complex/CentralizedControlATHumanDetector.java new file mode 100755 index 0000000000000000000000000000000000000000..e1321db9cf8bb2054cac9ea1da4275399870233d --- /dev/null +++ b/src/main/java/autumn_2023/module/complex/CentralizedControlATHumanDetector.java @@ -0,0 +1,245 @@ +package autumn_2023.module.complex; + +import static rescuecore2.standard.entities.StandardEntityURN.AMBULANCE_TEAM; +import static rescuecore2.standard.entities.StandardEntityURN.CIVILIAN; +import static rescuecore2.standard.entities.StandardEntityURN.REFUGE; + +import adf.core.agent.action.Action; +import adf.core.agent.communication.MessageManager; +import adf.core.agent.communication.standard.bundle.StandardMessageBundle; +import adf.core.agent.communication.standard.bundle.StandardMessagePriority; +import adf.core.agent.communication.standard.bundle.information.MessageBuilding; +import adf.core.agent.communication.standard.bundle.information.MessageCivilian; +import adf.core.agent.develop.DevelopData; +import adf.core.agent.info.AgentInfo; +import adf.core.agent.info.ScenarioInfo; +import adf.core.agent.info.WorldInfo; +import adf.core.agent.module.ModuleManager; +import adf.core.component.communication.CommunicationMessage; +import adf.core.component.module.algorithm.Clustering; +import adf.core.component.module.complex.HumanDetector; +import adf.core.debug.DefaultLogger; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.log4j.Logger; + +import rescuecore2.standard.entities.Building; +import rescuecore2.standard.entities.Civilian; +import rescuecore2.standard.entities.Human; +import rescuecore2.standard.entities.StandardEntity; +import rescuecore2.standard.entities.StandardEntityURN; +import rescuecore2.worldmodel.EntityID; + +public class CentralizedControlATHumanDetector extends HumanDetector { + + private Clustering clustering; + + private EntityID result; + + private Logger logger; + + public CentralizedControlATHumanDetector(AgentInfo ai, WorldInfo wi, ScenarioInfo si, ModuleManager moduleManager, DevelopData developData) { + super(ai, wi, si, moduleManager, developData); + logger = DefaultLogger.getLogger(agentInfo.me()); + this.clustering = moduleManager.getModule("SampleHumanDetector.Clustering", + "adf.impl.module.algorithm.KMeansClustering"); + registerModule(this.clustering); + } + + /** + * 新しく受信したメッセージから情報を取得するためのメソッド + * + * 現在のステップで知覚した埋没市民を送信する + */ + @Override + public HumanDetector updateInfo(MessageManager messageManager) { + logger.debug("Time:" + agentInfo.getTime()); + super.updateInfo(messageManager); + + Set changes = this.worldInfo.getChanged().getChangedEntities(); + for(EntityID id : changes){ + StandardEntity entity = this.worldInfo.getEntity(id); + if(!(entity instanceof Civilian)) continue; + Civilian civ = (Civilian) entity; + + if(!this.isNeedRescueHuman(civ)){ + continue; + } + StandardMessagePriority level = StandardMessagePriority.NORMAL; + MessageCivilian civ_mes = new MessageCivilian(true, level, civ); + + messageManager.addMessage(civ_mes,true); + } + + return this; + } + + /** + * 搬送対象のIDを求めるメソッド + */ + @Override + public HumanDetector calc() { + Human transportHuman = this.agentInfo.someoneOnBoard(); + if (transportHuman != null) { + logger.debug("someoneOnBoard:" + transportHuman); + this.result = transportHuman.getID(); + return this; + } + if (this.result != null) { + Human target = (Human) this.worldInfo.getEntity(this.result); + if (!isValidHuman(target)) { + logger.debug("Invalid Human:" + target + " ==>reset target"); + this.result = null; + } + } + if (this.result == null) { + this.result = calcTarget(); + } + return this; + } + + + private EntityID calcTarget() { + List rescueTargets = filterRescueTargets( + this.worldInfo.getEntitiesOfType(CIVILIAN)); + List rescueTargetsInCluster = filterInCluster(rescueTargets); + List targets = rescueTargetsInCluster; + if (targets.isEmpty()) + targets = rescueTargets; + + logger.debug("Targets:" + targets); + if (!targets.isEmpty()) { + targets.sort(new DistanceSorter(this.worldInfo, this.agentInfo.me())); + Human selected = targets.get(0); + logger.debug("Selected:" + selected); + return selected.getID(); + } + + return null; + } + + /** + * 救助対象IDを返すメソッド + */ + @Override + public EntityID getTarget() { + return this.result; + } + + + private List + filterRescueTargets(Collection list) { + List rescueTargets = new ArrayList<>(); + for (StandardEntity next : list) { + if (!(next instanceof Human)) + continue; + Human h = (Human) next; + if (!isValidHuman(h)) + continue; + if (h.getBuriedness() == 0) + continue; + rescueTargets.add(h); + } + return rescueTargets; + } + + + private List + filterInCluster(Collection entities) { + int clusterIndex = clustering.getClusterIndex(this.agentInfo.getID()); + List filter = new ArrayList<>(); + HashSet inCluster = new HashSet<>( + clustering.getClusterEntities(clusterIndex)); + for (StandardEntity next : entities) { + if (!(next instanceof Human)) + continue; + Human h = (Human) next; + if (!h.isPositionDefined()) + continue; + StandardEntity position = this.worldInfo.getPosition(h); + if (position == null) + continue; + if (!inCluster.contains(position)) + continue; + filter.add(h); + } + return filter; + + } + + private class DistanceSorter implements Comparator { + + private StandardEntity reference; + private WorldInfo worldInfo; + + DistanceSorter(WorldInfo wi, StandardEntity reference) { + this.reference = reference; + this.worldInfo = wi; + } + + + public int compare(StandardEntity a, StandardEntity b) { + int d1 = this.worldInfo.getDistance(this.reference, a); + int d2 = this.worldInfo.getDistance(this.reference, b); + return d1 - d2; + } + } + + private boolean isValidHuman(StandardEntity entity) { + if (entity == null) + return false; + if (!(entity instanceof Human)) + return false; + + Human target = (Human) entity; + if (!target.isHPDefined() || target.getHP() == 0) + return false; + if (!target.isPositionDefined()) + return false; + if (!target.isDamageDefined() || target.getDamage() == 0) + return false; + if (!target.isBuriednessDefined()) + return false; + + StandardEntity position = worldInfo.getPosition(target); + if (position == null) + return false; + + StandardEntityURN positionURN = position.getStandardURN(); + if (positionURN == REFUGE || positionURN == AMBULANCE_TEAM) + return false; + + return true; + } + + private boolean isNeedRescueHuman(StandardEntity entity){ + if (entity == null) + return false; + if (!(entity instanceof Human)) + return false; + + Human target = (Human) entity; + if (!target.isHPDefined() || target.getHP() == 0) + return false; + if (!target.isPositionDefined()) + return false; + if (!target.isBuriednessDefined() || target.getBuriedness() == 0) + return false; + + StandardEntity position = worldInfo.getPosition(target); + if (position == null) + return false; + + StandardEntityURN positionURN = position.getStandardURN(); + if (positionURN == REFUGE || positionURN == AMBULANCE_TEAM) + return false; + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/autumn_2023/module/complex/CentralizedControlFBAllocator.java b/src/main/java/autumn_2023/module/complex/CentralizedControlFBAllocator.java new file mode 100755 index 0000000000000000000000000000000000000000..ef329713df30fd15d4d2aa7b6c597b115a5cd107 --- /dev/null +++ b/src/main/java/autumn_2023/module/complex/CentralizedControlFBAllocator.java @@ -0,0 +1,298 @@ +package autumn_2023.module.complex; + +import autumn_2023.module.algorithm.Hungarian; +import adf.core.agent.communication.MessageManager; +import adf.core.agent.communication.standard.bundle.MessageUtil; +import adf.core.agent.communication.standard.bundle.StandardMessageBundle; +import adf.core.agent.communication.standard.bundle.StandardMessagePriority; +import adf.core.agent.communication.standard.bundle.centralized.MessageReport; +import adf.core.agent.communication.standard.bundle.information.MessageBuilding; +import adf.core.agent.communication.standard.bundle.information.MessageCivilian; +import adf.core.agent.communication.standard.bundle.information.MessageFireBrigade; +import adf.core.agent.develop.DevelopData; +import adf.core.agent.info.AgentInfo; +import adf.core.agent.info.ScenarioInfo; +import adf.core.agent.info.WorldInfo; +import adf.core.agent.module.ModuleManager; +import adf.core.agent.precompute.PrecomputeData; +import adf.core.component.communication.CommunicationMessage; +import adf.core.component.module.complex.FireTargetAllocator; + +import static rescuecore2.standard.entities.StandardEntityURN.AMBULANCE_TEAM; +import static rescuecore2.standard.entities.StandardEntityURN.REFUGE; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collector; +import java.util.stream.Collectors; + +import rescuecore2.standard.entities.Building; +import rescuecore2.standard.entities.FireBrigade; +import rescuecore2.standard.entities.Human; +import rescuecore2.standard.entities.StandardEntity; +import rescuecore2.standard.entities.StandardEntityURN; +import rescuecore2.worldmodel.EntityID; + +public class CentralizedControlFBAllocator extends FireTargetAllocator { + + private Map fireBrigadeInfoMap; + private Set taskSet; + private Map allocateTaskMap; + private Set finishEntityIDs; + + public CentralizedControlFBAllocator(AgentInfo ai, WorldInfo wi, ScenarioInfo si, ModuleManager moduleManager, DevelopData developData) { + super(ai, wi, si, moduleManager, developData); + this.fireBrigadeInfoMap = new HashMap<>(); + this.taskSet = new HashSet<>(); + this.allocateTaskMap = new HashMap<>(); + this.finishEntityIDs = new HashSet<>(); + } + + + @Override + public FireTargetAllocator resume(PrecomputeData precomputeData) { + super.resume(precomputeData); + if (this.getCountResume() >= 2) { + return this; + } + for (EntityID id : this.worldInfo + .getEntityIDsOfType(StandardEntityURN.FIRE_BRIGADE)) { + this.fireBrigadeInfoMap.put(id, new FireBrigadeInfo(id)); + } + return this; + } + + + @Override + public FireTargetAllocator preparate() { + super.preparate(); + if (this.getCountPrecompute() >= 2) { + return this; + } + for (EntityID id : this.worldInfo + .getEntityIDsOfType(StandardEntityURN.FIRE_BRIGADE)) { + this.fireBrigadeInfoMap.put(id, new FireBrigadeInfo(id)); + } + return this; + } + + /** + * calcメソッドで算出した司令内容を返すためのメソッド + */ + @Override + public Map getResult() { + return this.convert(this.fireBrigadeInfoMap); + } + + /** + * 消防隊情報を + * key:命令対象のエージェントのID + * value:やるべきタスク(市民)のID + * のMapに変換するメソッド + * @param map 消防隊IDと消防隊情報に関連するMap + * @return 司令情報となるMap + */ + private Map convert(Map map) { + Map result = new HashMap<>(); + for (EntityID id : map.keySet()) { + FireBrigadeInfo info = map.get(id); + if (info != null && info.target != null) { + result.put(id, info.target); + } + } + return result; + } + + /** + * 分散エージェントへの司令内容を算出するためのメソッド + * + * ハンガリアンアルゴリズムを利用して消防隊に担当させるタスクを決定する + */ + @Override + public FireTargetAllocator calc() { + if(this.agentInfo.getTime() < scenarioInfo.getKernelAgentsIgnoreuntil()) return this; + + if(this.fireBrigadeInfoMap.keySet().size()==0||this.taskSet.size()==0) return this; + + int row = this.fireBrigadeInfoMap.keySet().size(); + int col = this.taskSet.size(); + boolean reverse = false; + List rowlist = new ArrayList<>(this.fireBrigadeInfoMap.keySet()); + List collist = new ArrayList<>(this.taskSet); + + if(row > col){ + reverse = true; + int tmp = row; + row = col; + col = tmp; + List tmplist = rowlist; + rowlist = collist; + collist = tmplist; + } + + int[][] costs = new int[row][col]; + for(int i = 0; i tmplist = rowlist; + rowlist = collist; + collist = tmplist; + int[] reverse_list = new int[row]; + for(int i = 0; i recievetasks = messageManager.getReceivedMessageList(MessageCivilian.class).stream() + .map(e -> { + MessageCivilian mesciv = (MessageCivilian) e; + MessageUtil.reflectMessage(this.worldInfo, mesciv); + return(mesciv); + }) + .map(MessageCivilian::getAgentID) + .filter(e -> this.isNeedRescueHuman(this.worldInfo.getEntity(e))) + .filter(e -> !(finishEntityIDs.contains(e))) + .collect(Collectors.toSet()); + + this.taskSet.addAll(recievetasks); + + List mesfblist = messageManager.getReceivedMessageList(MessageFireBrigade.class); + for(CommunicationMessage mes : mesfblist){ + MessageFireBrigade mesfb = (MessageFireBrigade) mes; + MessageUtil.reflectMessage(this.worldInfo, mesfb); + EntityID fbID = mesfb.getAgentID(); + FireBrigadeInfo fbi = this.fireBrigadeInfoMap.get(fbID); + fbi.setInfo(mesfb.getTargetID(), mesfb.getPosition(), mesfb.getBuriedness(), + (mesfb.getAction() == MessageFireBrigade.ACTION_RESCUE) ? false : true, this.agentInfo.getTime()); + } + + List reportlist = messageManager.getReceivedMessageList(MessageReport.class).stream() + .map(MessageReport.class::cast) + .filter(MessageReport::isDone) + .map(MessageReport::getFromID) + .collect(Collectors.toList()); + + this.finishEntityIDs.addAll(reportlist); + this.taskSet.removeAll(reportlist); + + return this; + } + + /** + * ある市民について消防隊による救助が必要かを判定するメソッド + * + * @param entity エンティティ + * @return true : 救助必要 false : 救助不必要 + */ + private boolean isNeedRescueHuman(StandardEntity entity){ + if (entity == null) + return false; + if (!(entity instanceof Human)) + return false; + + Human target = (Human) entity; + if (!target.isHPDefined() || target.getHP() == 0) + return false; + if (!target.isPositionDefined()) + return false; + if (!target.isBuriednessDefined() || target.getBuriedness() == 0) + return false; + + StandardEntity position = worldInfo.getPosition(target); + if (position == null) + return false; + + StandardEntityURN positionURN = position.getStandardURN(); + if (positionURN == REFUGE || positionURN == AMBULANCE_TEAM) + return false; + + return true; + } + + /** + * ハンガリアンアルゴリズムの割当結果をみるためのメソッド + * @param allocate 消防隊に対応するタスク割当結果配列 + * @param rowlist 消防隊IDリスト + * @param collist 埋没市民IDリスト + * @param row 消防隊の数 + */ + private void printAllocate(int[] allocate, List rowlist, List collist, int row){ + String str = " allocate"; + for(int i = 0; i changes = this.worldInfo.getChanged().getChangedEntities(); + for(EntityID id : changes){ + StandardEntity entity = this.worldInfo.getEntity(id); + if(!(entity instanceof Civilian)) continue; + Civilian civ = (Civilian) entity; + + if(!this.isNeedRescueHuman(civ)){ + continue; + } + StandardMessagePriority level = StandardMessagePriority.NORMAL; + MessageCivilian civ_mes = new MessageCivilian(true, level, civ); + + messageManager.addMessage(civ_mes,true); + } + + return this; + } + + /** + * 救助対象のIDを求めるメソッド + * + * 司令所の司令で行動するため,救助対象を決定しないようにしている + */ + @Override + public HumanDetector calc() { + if(this.agentInfo.getTime() < scenarioInfo.getKernelAgentsIgnoreuntil()) return this; + + this.result = null; + + return this; + } + + + private EntityID calcTarget() { + List rescueTargets = filterRescueTargets( + this.worldInfo.getEntitiesOfType(CIVILIAN)); + List rescueTargetsInCluster = filterInCluster(rescueTargets); + List targets = rescueTargetsInCluster; + if (targets.isEmpty()) + targets = rescueTargets; + + logger.debug("Targets:" + targets); + if (!targets.isEmpty()) { + targets.sort(new DistanceSorter(this.worldInfo, this.agentInfo.me())); + Human selected = targets.get(0); + logger.debug("Selected:" + selected); + return selected.getID(); + } + + return null; + } + + /** + * 救助対象IDを返すメソッド + */ + @Override + public EntityID getTarget() { + return this.result; + } + + + private List + filterRescueTargets(Collection list) { + List rescueTargets = new ArrayList<>(); + for (StandardEntity next : list) { + if (!(next instanceof Human)) + continue; + Human h = (Human) next; + if (!isValidHuman(h)) + continue; + if (h.getBuriedness() == 0) + continue; + rescueTargets.add(h); + } + return rescueTargets; + } + + + private List + filterInCluster(Collection entities) { + int clusterIndex = clustering.getClusterIndex(this.agentInfo.getID()); + List filter = new ArrayList<>(); + HashSet inCluster = new HashSet<>( + clustering.getClusterEntities(clusterIndex)); + for (StandardEntity next : entities) { + if (!(next instanceof Human)) + continue; + Human h = (Human) next; + if (!h.isPositionDefined()) + continue; + StandardEntity position = this.worldInfo.getPosition(h); + if (position == null) + continue; + if (!inCluster.contains(position)) + continue; + filter.add(h); + } + return filter; + + } + + private class DistanceSorter implements Comparator { + + private StandardEntity reference; + private WorldInfo worldInfo; + + DistanceSorter(WorldInfo wi, StandardEntity reference) { + this.reference = reference; + this.worldInfo = wi; + } + + + public int compare(StandardEntity a, StandardEntity b) { + int d1 = this.worldInfo.getDistance(this.reference, a); + int d2 = this.worldInfo.getDistance(this.reference, b); + return d1 - d2; + } + } + + private boolean isValidHuman(StandardEntity entity) { + if (entity == null) + return false; + if (!(entity instanceof Human)) + return false; + + Human target = (Human) entity; + if (!target.isHPDefined() || target.getHP() == 0) + return false; + if (!target.isPositionDefined()) + return false; + if (!target.isDamageDefined() || target.getDamage() == 0) + return false; + if (!target.isBuriednessDefined()) + return false; + + StandardEntity position = worldInfo.getPosition(target); + if (position == null) + return false; + + StandardEntityURN positionURN = position.getStandardURN(); + if (positionURN == REFUGE || positionURN == AMBULANCE_TEAM) + return false; + + return true; + } + + private boolean isNeedRescueHuman(StandardEntity entity){ + if (entity == null) + return false; + if (!(entity instanceof Human)) + return false; + + Human target = (Human) entity; + if (!target.isHPDefined() || target.getHP() == 0) + return false; + if (!target.isPositionDefined()) + return false; + if (!target.isBuriednessDefined() || target.getBuriedness() == 0) + return false; + + StandardEntity position = worldInfo.getPosition(target); + if (position == null) + return false; + + StandardEntityURN positionURN = position.getStandardURN(); + if (positionURN == REFUGE || positionURN == AMBULANCE_TEAM) + return false; + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/autumn_2023/module/complex/SampleAmbulanceTargetAllocator.java b/src/main/java/autumn_2023/module/complex/SampleAmbulanceTargetAllocator.java deleted file mode 100755 index 453de8aea76bdf9100e9468fea208738755ca455..0000000000000000000000000000000000000000 --- a/src/main/java/autumn_2023/module/complex/SampleAmbulanceTargetAllocator.java +++ /dev/null @@ -1,53 +0,0 @@ -package autumn_2023.module.complex; - -import adf.core.agent.communication.MessageManager; -import adf.core.agent.develop.DevelopData; -import adf.core.agent.info.AgentInfo; -import adf.core.agent.info.ScenarioInfo; -import adf.core.agent.info.WorldInfo; -import adf.core.agent.module.ModuleManager; -import adf.core.agent.precompute.PrecomputeData; -import adf.core.component.module.complex.AmbulanceTargetAllocator; -import java.util.HashMap; -import java.util.Map; -import rescuecore2.worldmodel.EntityID; - -public class SampleAmbulanceTargetAllocator extends AmbulanceTargetAllocator { - - public SampleAmbulanceTargetAllocator(AgentInfo ai, WorldInfo wi, ScenarioInfo si, ModuleManager moduleManager, DevelopData developData) { - super(ai, wi, si, moduleManager, developData); - } - - - @Override - public AmbulanceTargetAllocator resume(PrecomputeData precomputeData) { - super.resume(precomputeData); - return this; - } - - - @Override - public AmbulanceTargetAllocator preparate() { - super.preparate(); - return this; - } - - - @Override - public Map getResult() { - return new HashMap<>(); - } - - - @Override - public AmbulanceTargetAllocator calc() { - return this; - } - - - @Override - public AmbulanceTargetAllocator updateInfo(MessageManager messageManager) { - super.updateInfo(messageManager); - return this; - } -} \ No newline at end of file diff --git a/src/main/java/autumn_2023/module/complex/SampleSearch.java b/src/main/java/autumn_2023/module/complex/SampleSearch.java new file mode 100644 index 0000000000000000000000000000000000000000..4762efa0ecc4ea7c21e7ea031cda0fb650921c68 --- /dev/null +++ b/src/main/java/autumn_2023/module/complex/SampleSearch.java @@ -0,0 +1,121 @@ +package autumn_2023.module.complex; + +import adf.core.agent.communication.MessageManager; +import adf.core.agent.communication.standard.bundle.StandardMessagePriority; +import adf.core.agent.communication.standard.bundle.centralized.CommandAmbulance; +import adf.core.agent.communication.standard.bundle.information.MessageCivilian; +import adf.core.agent.info.*; +import adf.core.agent.precompute.PrecomputeData; +import adf.core.component.communication.CommunicationMessage; +import adf.core.component.module.complex.Search; +import adf.core.component.module.algorithm.Clustering; +import adf.core.agent.module.ModuleManager; +import adf.core.agent.develop.DevelopData; +import rescuecore2.standard.entities.*; +import rescuecore2.worldmodel.EntityID; +import java.util.*; +import java.util.stream.Collectors; + +import static java.lang.Double.POSITIVE_INFINITY; +import static rescuecore2.standard.entities.StandardEntityURN.AMBULANCE_TEAM; + +public class SampleSearch extends Search +{ + private EntityID result; + private Clustering clustering; + private Set searchedSet = new HashSet<>(); + private List list; + private MessageManager messageManager; + private static final int ACTION_LOAD = CommandAmbulance.ACTION_LOAD; + + public SampleSearch( + AgentInfo ai, WorldInfo wi, ScenarioInfo si, + ModuleManager mm, DevelopData dd) + { + super(ai, wi, si, mm, dd); + + String clusteringKey = "SampleSearch.Clustering.Ambulance"; + this.clustering = + mm.getModule(clusteringKey, + "adf.sample.module.algorithm.SampleKMeans"); + this.registerModule(this.clustering); + } + + @Override + public EntityID getTarget() + { + return this.result; + } + + @Override + public Search updateInfo(MessageManager mm) + { + super.updateInfo(mm); + if (this.getCountUpdateInfo() > 1) return this; + + // そのステップで受信した(前ステップで送信された)メッセージ一覧 + List messages = mm.getReceivedMessageList(); + this.messageManager = mm; + + // エージェントが現在位置する建物や道路のIDを取得する + EntityID position = this.agentInfo.getPosition(); + // 探索済みの (辿り着いたことがある) 対象を候補から除外する + this.searchedSet.add(position); + + return this; + + } + + @Override + public Search calc() + { + EntityID me = this.agentInfo.getID(); + int idx = this.clustering.getClusterIndex(me); + if (idx == -1) { + return this; + } + //System.out.println("time:"+this.agentInfo.getTime()+" id:"+me+" target:"+this.getTarget()); + + Collection cluster = + this.clustering.getClusterEntityIDs(idx); + if (cluster == null) { + return this; + } + + // Listに変換 + if (this.result == null){ + list = new ArrayList<>(cluster); + //System.out.println(list); + } + + // エージェントが現在位置する建物や道路のIDを取得する + EntityID position = this.agentInfo.getPosition(); + + if (this.getTarget() != null && !position.equals(this.getTarget())) { + return this; + } + + // 探索済みの (辿り着いたことがある) 対象を候補から除外する + list.removeAll(this.searchedSet); + + // すべての対象が探索済みの場合,候補をリセットする + if (list.size() <= 0) { + this.searchedSet.clear(); + list = new ArrayList<>(cluster); + } + + double near = Double.MAX_VALUE; + for (EntityID lists : this.list) { + StandardEntity test = this.worldInfo.getEntity(lists); + if(test instanceof Building) { + double distance = this.worldInfo.getDistance(position, lists); + if (distance < near){ + near = distance; + this.result = lists; + } + } + } + + return this; + } +} \ No newline at end of file diff --git a/start.sh b/start.sh new file mode 100755 index 0000000000000000000000000000000000000000..c6c705286afbabe8ac8c64bb58c727790c0d8a2c --- /dev/null +++ b/start.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +LOADER="adf.impl.DefaultLoader" +PARAMS=$* + +cd `dirname $0` + +if [ ! -z "$1" ]; then + ./gradlew launch --args="${LOADER} ${PARAMS} -pre 0" +else + echo "Options:" + echo "-tn Team name" + echo "-t [FB],[FS],[PF],[PO],[AT],[AC] Number of agents" + echo "-fb [FB] Number of FireBrigade" + echo "-fs [FS] Number of FireStation" + echo "-pf [PF] Number of PoliceForce" + echo "-po [PO] Number of PoliceOffice" + echo "-at [AT] Number of AmbulanceTeam" + echo "-ac [AC] Number of AmbulanceCentre" + echo "-s [HOST]:[PORT] RCRS server host and port" + echo "-h [HOST] RCRS server host (port:27931)" + echo "-pre [0|1] Precompute flag" + echo "-d [0|1] Debug flag" + echo "-dev [0|1] Development mode" + echo "-mc [FILE] ModuleConfig file name" + echo "-md [JSON] ModuleConfig JSON" + echo "-df [FILE] DevelopData JSON file" + echo "-dd [JSON] DevelopData JSON" + echo "-all [alias] -t -1,-1,-1,-1,-1,-1" + echo "-allp [alias] -t 1,0,1,0,1,0," + echo "-local [alias] -h localhost" + echo "-precompute [alias] -pre 1" + echo "-debug [alias] -d 1" + echo "-develop [alias] -dev 1" +fi diff --git a/submit.sh b/submit.sh new file mode 100755 index 0000000000000000000000000000000000000000..39604c8824557fa741d19d2e6aa9d79370190b03 --- /dev/null +++ b/submit.sh @@ -0,0 +1,10 @@ +#!/bin/sh +TEAM=ait +mkdir ../${TEAM} +cp -r src ../${TEAM} +cp -r lib ../${TEAM} +mv ../${TEAM}/lib ../${TEAM}/library +cp -r config ../${TEAM} +cp -r data ../${TEAM} +cd ../${TEAM} +tar cvzf ait.tgz *