From 8d0dc09a327894b2c22781c53441e0938f867d1b Mon Sep 17 00:00:00 2001 From: K20014 <82937878+K20014@users.noreply.github.com> Date: Thu, 2 Nov 2023 18:38:30 +0900 Subject: [PATCH] =?UTF-8?q?=E4=BD=9C=E6=A5=AD=E9=80=94=E4=B8=AD=E3=81=AE?= =?UTF-8?q?=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuctionCommandExecutorFire.java | 130 +++++++++++++++++- .../centralized/AuctionCommandPickerFire.java | 80 ++++++++++- .../complex/AuctionFBHumanDetector.java | 56 +++++++- .../complex/AuctionFireTargetAllocator.java | 128 ++++++++++------- 4 files changed, 338 insertions(+), 56 deletions(-) diff --git a/src/main/java/autumn_2023/centralized/AuctionCommandExecutorFire.java b/src/main/java/autumn_2023/centralized/AuctionCommandExecutorFire.java index 5ecdda3..2eb8030 100644 --- a/src/main/java/autumn_2023/centralized/AuctionCommandExecutorFire.java +++ b/src/main/java/autumn_2023/centralized/AuctionCommandExecutorFire.java @@ -1,5 +1,133 @@ package autumn_2023.centralized; -public class AuctionCommandExecutorFire { +import adf.core.agent.communication.MessageManager; +import adf.core.agent.communication.standard.bundle.StandardMessagePriority; +import adf.core.agent.communication.standard.bundle.centralized.CommandFire; +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.centralized.CommandExecutor; +import adf.core.component.module.algorithm.PathPlanning; +import autumn_2023.module.comm.infomation.MessageCost; +import rescuecore2.standard.entities.*; +import rescuecore2.worldmodel.EntityID; +import java.util.*; +import java.util.stream.Collectors; + +import static rescuecore2.standard.entities.StandardEntityURN.AMBULANCE_TEAM; +import static rescuecore2.standard.entities.StandardEntityURN.REFUGE; + +public class AuctionCommandExecutorFire extends CommandExecutor { + + /* + 救急司令所からすでに受け取った埋没市民のIDの集合 + */ + private final Set bidCentreCivilians = new HashSet<>(); + private final PathPlanning pathPlanning; + + public AuctionCommandExecutorFire(AgentInfo ai, WorldInfo wi, ScenarioInfo si, ModuleManager moduleManager, DevelopData developData) { + super(ai, wi, si, moduleManager, developData); + + this.pathPlanning = moduleManager.getModule("SampleHumanDetector.PathPlanning", + "adf.impl.module.algorithm.DijkstraPathPlanning"); + } + + @Override + public CommandExecutor updateInfo(MessageManager messageManager) { + super.updateInfo(messageManager); + + // FireStationから受信したMessageCivilianを収集 + final Set receivedCentreCivilians = messageManager.getReceivedMessageList(MessageCivilian.class).parallelStream() + .map(MessageCivilian.class::cast) + .filter(e -> this.worldInfo.getEntity(e.getSenderID()) instanceof FireStation) + .map(MessageCivilian::getAgentID) + .filter(e -> !this.bidCentreCivilians.contains(e)) + .collect(Collectors.toSet()); + + // 新規メッセージクラスを用いてタスク実行時のコストを救急司令所に送信 + receivedCentreCivilians.parallelStream() + .map(e -> new MessageCost(true, StandardMessagePriority.HIGH, e, CalculationCost(e))) + .forEach(messageManager::addMessage); + + // 知覚した救助対象の市民の情報をMessageCivilianとして指令所に送信 + this.worldInfo.getChanged().getChangedEntities().parallelStream() + .filter(this::isRescueTarget) + .map(this.worldInfo::getEntity) + .filter(Civilian.class::isInstance) + .map(Civilian.class::cast) + .map(e -> new MessageCivilian(true, StandardMessagePriority.HIGH, e)) + .forEach(messageManager::addMessage); + + this.bidCentreCivilians.addAll(receivedCentreCivilians); + + return this; + } + + @Override + public CommandExecutor setCommand(CommandFire command) { + // TODO + return this; + } + + @Override + public CommandExecutor calc() { + // TODO + return this; + } + + /** + * 対象が救助活動の対象であるか否かを判定するメソッド + * @param entity 対象のエンティティ + * @return entityが救助活動の対象であるか否か + */ + private boolean isValidHuman(StandardEntity entity) { + if (entity == null) + return false; + if (!(entity instanceof Human target)) + return false; + + 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(); + return positionURN != REFUGE && positionURN != AMBULANCE_TEAM; + } + + /** + * 消防隊が対象を救出をするためのコストを計算するメソッド + * @param target 埋没したエージェントのID + * @return targetへ移動するためのステップ数 + */ + private int CalculationCost(EntityID target){ + double targetDistance = this.pathPlanning.getDistance(this.agentInfo.getID(), target); + return (int)(Math.ceil(targetDistance / 40000)); + } + + /** + * 対象が消防隊による救出の対象であるか否かを判定するメソッド + * @param target 判定対象のエンティティID + * @return targetが救出対象であるか否か + */ + private boolean isRescueTarget(EntityID target) { + final StandardEntity targetEntity = this.worldInfo.getEntity(target); + if (!isValidHuman(targetEntity)) + return false; + + final Human targetHuman = (Human) targetEntity; + return targetHuman.getBuriedness() > 0; + } } diff --git a/src/main/java/autumn_2023/centralized/AuctionCommandPickerFire.java b/src/main/java/autumn_2023/centralized/AuctionCommandPickerFire.java index b177ed3..495eca7 100644 --- a/src/main/java/autumn_2023/centralized/AuctionCommandPickerFire.java +++ b/src/main/java/autumn_2023/centralized/AuctionCommandPickerFire.java @@ -1,5 +1,83 @@ package autumn_2023.centralized; -public class AuctionCommandPickerFire { +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 AuctionCommandPickerFire extends CommandPicker{ + + private int scoutDistance; + + private Collection messages; + private Map allocationData; + + public AuctionCommandPickerFire(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); + } + + @Override + public CommandPicker setAllocatorResult(Map allocationData) + { + this.allocationData = allocationData; + + return this; + } + + + @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); + } else if (target instanceof Area) + { + CommandScout command = new CommandScout(true, agentID, target.getID(), this.scoutDistance); + this.messages.add(command); + } + } + } + } + return this; + } + + + @Override + public Collection getResult() + { + return this.messages; + } } diff --git a/src/main/java/autumn_2023/module/complex/AuctionFBHumanDetector.java b/src/main/java/autumn_2023/module/complex/AuctionFBHumanDetector.java index 0f56863..794ef67 100644 --- a/src/main/java/autumn_2023/module/complex/AuctionFBHumanDetector.java +++ b/src/main/java/autumn_2023/module/complex/AuctionFBHumanDetector.java @@ -1,5 +1,55 @@ package autumn_2023.module.complex; -public class AuctionFBHumanDetector { - -} +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.module.complex.HumanDetector; +import rescuecore2.standard.entities.Civilian; +import rescuecore2.standard.entities.Human; +import rescuecore2.standard.entities.StandardEntity; +import rescuecore2.worldmodel.EntityID; + +import java.util.Set; +import java.util.stream.Collectors; + +public class AuctionFBHumanDetector extends HumanDetector { + private EntityID result = null; + + public AuctionFBHumanDetector(AgentInfo ai, WorldInfo wi, ScenarioInfo si, ModuleManager moduleManager, DevelopData developData) { + super(ai, wi, si, moduleManager, developData); + } + + @Override + public EntityID getTarget() { + return this.result; + } + + @Override + public HumanDetector calc() { + final Set rescueTargetInSamePosition = this.worldInfo.getChanged().getChangedEntities().parallelStream() + .map(this.worldInfo::getEntity) + .filter(Civilian.class::isInstance) + .map(Civilian.class::cast) + .filter(e -> this.agentInfo.getPosition().equals(e.getPosition())) + .filter(Human::isHPDefined) + .filter(e -> e.getHP() > 0) + .filter(Human::isBuriednessDefined) + .filter(e -> e.getBuriedness() > 0) + .map(StandardEntity::getID) + .collect(Collectors.toSet()); + + if (rescueTargetInSamePosition.isEmpty()) { + this.result = null; + return this; + } + + if (rescueTargetInSamePosition.contains(this.result)) { + return this; + } + + this.result = rescueTargetInSamePosition.stream().findAny().orElse(null); + return this; + } +} \ No newline at end of file diff --git a/src/main/java/autumn_2023/module/complex/AuctionFireTargetAllocator.java b/src/main/java/autumn_2023/module/complex/AuctionFireTargetAllocator.java index 0de0123..f0d5a37 100644 --- a/src/main/java/autumn_2023/module/complex/AuctionFireTargetAllocator.java +++ b/src/main/java/autumn_2023/module/complex/AuctionFireTargetAllocator.java @@ -2,6 +2,7 @@ package autumn_2023.module.complex; import adf.core.agent.communication.MessageManager; import adf.core.agent.communication.standard.bundle.MessageUtil; +import adf.core.agent.communication.standard.bundle.StandardMessagePriority; import adf.core.agent.communication.standard.bundle.information.MessageCivilian; import adf.core.agent.develop.DevelopData; import adf.core.agent.info.AgentInfo; @@ -18,87 +19,112 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import rescuecore2.standard.entities.AmbulanceCentre; import rescuecore2.standard.entities.AmbulanceTeam; +import rescuecore2.standard.entities.Civilian; import rescuecore2.standard.entities.FireBrigade; import rescuecore2.worldmodel.EntityID; public class AuctionFireTargetAllocator extends FireTargetAllocator{ // 分散エージェントからの埋没市民のメッセージリスト - private List receivedAgentCivilians = new ArrayList<>(); - private List finishreceivedCivilians = new ArrayList<>(); + private List receivedAgentCivilians; + private List finishreceivedCivilians; // 分散エージェントからのコストのメッセージリスト - private List RescueCosts = new ArrayList<>(); + private List rescueCosts; + private Map rescueResult; public AuctionFireTargetAllocator(AgentInfo ai, WorldInfo wi, ScenarioInfo si, ModuleManager moduleManager, DevelopData developData) { super(ai, wi, si, moduleManager, developData); + + this.receivedAgentCivilians = new ArrayList<>(); + this.finishreceivedCivilians = new ArrayList<>(); + this.rescueCosts = new ArrayList<>(); + this.rescueResult = new HashMap<>(); } @Override - public FireTargetAllocator resume(PrecomputeData precomputeData) - { - super.resume(precomputeData); + public FireTargetAllocator resume(PrecomputeData precomputeData) + { + super.resume(precomputeData); - return this; - } + return this; + } - @Override - public FireTargetAllocator preparate() - { - super.preparate(); + @Override + public FireTargetAllocator preparate() + { + super.preparate(); - return this; - } + return this; + } - @Override - public Map getResult() - { - return new HashMap<>(); - } + @Override + public Map getResult() + { + return this.rescueResult; + } - @Override - public FireTargetAllocator calc() - { - return this; - } + @Override + public FireTargetAllocator calc() + { + return this; + } - @Override - public FireTargetAllocator updateInfo(MessageManager messageManager) - { - super.updateInfo(messageManager); - // そのステップで受信した(前ステップで送信された)メッセージ一覧 - List messages = messageManager.getReceivedMessageList(); - for(CommunicationMessage mes : messages) + @Override + public FireTargetAllocator updateInfo(MessageManager messageManager) { - // mesが市民の情報であれば - if (mes instanceof MessageCivilian) - { - MessageCivilian mesCiv = (MessageCivilian) mes; - MessageUtil.reflectMessage(this.worldInfo, mesCiv); - if (this.worldInfo.getEntity(mesCiv.getSenderID()) instanceof AmbulanceTeam - || this.worldInfo.getEntity(mesCiv.getSenderID()) instanceof FireBrigade) + super.updateInfo(messageManager); + + // 受信処理 + // そのステップで受信した(前ステップで送信された)メッセージ一覧 + List messages = messageManager.getReceivedMessageList(); + for(CommunicationMessage mes : messages) + { + // mesが市民の情報であれば + if (mes instanceof MessageCivilian) + { + MessageCivilian mesCiv = (MessageCivilian) mes; + if(mesCiv.getSendingPriority() == StandardMessagePriority.HIGH) + { + MessageUtil.reflectMessage(this.worldInfo, mesCiv); + if (this.worldInfo.getEntity(mesCiv.getSenderID()) instanceof AmbulanceTeam + || this.worldInfo.getEntity(mesCiv.getSenderID()) instanceof FireBrigade) + { + if(!receivedAgentCivilians.contains(mesCiv.getAgentID()) + || !finishreceivedCivilians.contains(mesCiv.getAgentID())) + { + receivedAgentCivilians.add(mesCiv.getAgentID()); + } + } + } + } + // mesがコストの情報であれば + if (mes instanceof MessageCost) { + MessageCost mesCos = (MessageCost) mes; + if (this.worldInfo.getEntity(mesCos.getSenderID()) instanceof FireBrigade) + { + rescueCosts.add(mesCos); + } + } + } + + // 送信処理 + // 埋没している市民の情報の送信 + for(EntityID res : receivedAgentCivilians) { - if(!receivedAgentCivilians.contains(mesCiv.getAgentID()) - || !finishreceivedCivilians.contains(mesCiv.getAgentID())) - { - receivedAgentCivilians.add(mesCiv.getAgentID()); - } + messageManager.addMessage(new MessageCivilian(true, StandardMessagePriority.HIGH, (Civilian)this.worldInfo.getEntity(res))); + finishreceivedCivilians.add(res); } - } - // mesがコストの情報であれば - if (mes instanceof MessageCost) { - - } + receivedAgentCivilians.clear(); + + return this; } - return this; - } } -- GitLab