package iamrescue.communication.scenario.scenarios; import iamrescue.agent.ISimulationTimer; import iamrescue.communication.IMessagingSchedule; import iamrescue.communication.ISimulationCommunicationConfiguration; import iamrescue.communication.messages.Message; import iamrescue.communication.messages.MessageChannel; import iamrescue.communication.scenario.ICommunicationScenario; import iamrescue.util.EntityComparator; import iamrescue.util.comparators.ChannelIDComparator; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import javolution.util.FastMap; import rescuecore2.standard.entities.StandardEntity; import rescuecore2.standard.entities.StandardEntityURN; import rescuecore2.worldmodel.EntityID; public class ManyLowBandwidthScenario implements ICommunicationScenario { // Centre counts as five agents for relative bandwidth share. private static final int RELATIVE_CENTRE_SHARE = 5; private static final int POLICE_INDEX = 0; private static final int AMBULANCE_INDEX = 1; private static final int FIRE_INDEX = 2; private List<MessageChannel> myTeamChannels = new ArrayList<MessageChannel>(); private List<MessageChannel> otherTeamCentreChannels = new ArrayList<MessageChannel>(); private List<MessageChannel> myCentreOutChannels = new ArrayList<MessageChannel>(); private List<MessageChannel> mySubscribedChannels = new ArrayList<MessageChannel>(); private MessageChannel myOutputChannel; Map<MessageChannel, List<Message>> outMap = new FastMap<MessageChannel, List<Message>>(); private boolean iamCentre; private ISimulationCommunicationConfiguration configuration; private SharedBandwidthSchedule schedule; private int myTeamIndex; public ManyLowBandwidthScenario( ISimulationCommunicationConfiguration configuration) { List<MessageChannel> channels = new ArrayList<MessageChannel>( configuration.getRadioChannels()); Collections.sort(channels, ChannelIDComparator.INSTANCE); Map<StandardEntityURN, Collection<StandardEntity>> agentsByType = configuration .getAgentsByType(); int ambulanceCentres = agentsByType.get( StandardEntityURN.AMBULANCE_CENTRE).size(); int ambulances = agentsByType.get(StandardEntityURN.AMBULANCE_TEAM) .size(); int policeCentres = agentsByType.get(StandardEntityURN.POLICE_OFFICE) .size(); int policeForces = agentsByType.get(StandardEntityURN.POLICE_FORCE) .size(); int fireStations = agentsByType.get(StandardEntityURN.FIRE_STATION) .size(); int fireBrigades = agentsByType.get(StandardEntityURN.FIRE_BRIGADE) .size(); this.configuration = configuration; // Keep track of channels List<List<MessageChannel>> centreChannels = new ArrayList<List<MessageChannel>>(); List<MessageChannel> policeCentreChannels = new ArrayList<MessageChannel>(); List<MessageChannel> ambulanceCentreChannels = new ArrayList<MessageChannel>(); List<MessageChannel> fireBrigadeCentreChannels = new ArrayList<MessageChannel>(); centreChannels.add(policeCentreChannels); centreChannels.add(ambulanceCentreChannels); centreChannels.add(fireBrigadeCentreChannels); List<List<MessageChannel>> platoonChannels = new ArrayList<List<MessageChannel>>(); List<MessageChannel> policeChannels = new ArrayList<MessageChannel>(); List<MessageChannel> ambulanceChannels = new ArrayList<MessageChannel>(); List<MessageChannel> fireBrigadeChannels = new ArrayList<MessageChannel>(); platoonChannels.add(policeChannels); platoonChannels.add(ambulanceChannels); platoonChannels.add(fireBrigadeChannels); // We assume for now channels are homogeneous // Start by reserving one channel for each team. policeChannels.add(channels.remove(0)); ambulanceChannels.add(channels.remove(0)); fireBrigadeChannels.add(channels.remove(0)); // Reserve three channels for the centres (outgoing) for (int i = 0; i < 3 && channels.size() > 0; i++) { centreChannels.get(i).add(channels.remove(0)); } // How many channels can a platoon listen to? int maxListenPlatoon = configuration.getMaxListenChannelCountPlatoon() - configuration.getVoiceChannels().size(); int maxListenCentre = configuration.getMaxListenChannelCountCentre() - configuration.getVoiceChannels().size(); // Divide up the remaining channels. For every 2 platoon channels, // create 1 centre channel. (while there is any more point) boolean added = false; do { for (int i = 0; i < platoonChannels.size() && channels.size() > 0; i++) { List<MessageChannel> platoonList = platoonChannels.get(i); if (maxListenPlatoon > platoonList.size()) { platoonList.add(channels.remove(0)); added = true; } } for (int i = 0; i < 3 && channels.size() > 0; i++) { int otherCenterChannelCount = Math .max(centreChannels.get(i + 1 % 3).size(), centreChannels.get(i + 2 % 3).size()); if (maxListenCentre > otherCenterChannelCount + platoonChannels.get(i).size()) { centreChannels.get(i).add(channels.remove(0)); added = true; } } } while (added && channels.size() > 0); // We have channels now // Get my team List<StandardEntity> myPlatoonTeam; Map<EntityID, MessageChannel> outputChannels = new FastMap<EntityID, MessageChannel>(); if (configuration.getAgentType().equals(StandardEntityURN.POLICE_FORCE) || configuration.getAgentType().equals( StandardEntityURN.POLICE_OFFICE)) { myTeamIndex = POLICE_INDEX; myPlatoonTeam = new ArrayList<StandardEntity>(configuration .getAgentsByType().get(StandardEntityURN.POLICE_FORCE)); } else if (configuration.getAgentType().equals( StandardEntityURN.AMBULANCE_TEAM) || configuration.getAgentType().equals( StandardEntityURN.AMBULANCE_CENTRE)) { myTeamIndex = AMBULANCE_INDEX; myPlatoonTeam = new ArrayList<StandardEntity>(configuration .getAgentsByType().get(StandardEntityURN.AMBULANCE_TEAM)); } else { // if // (configuration.getAgentType().equals(StandardEntityURN.FIRE_BRIGADE) // || // configuration.getAgentType().equals(StandardEntityURN.FIRE_STATION)) // { myTeamIndex = FIRE_INDEX; myPlatoonTeam = new ArrayList<StandardEntity>(configuration .getAgentsByType().get(StandardEntityURN.FIRE_BRIGADE)); } Collections.sort(myPlatoonTeam, new EntityComparator()); myTeamChannels = platoonChannels.get(myTeamIndex); int[] perChannel = new int[myTeamChannels.size()]; for (int i = 0; i < perChannel.length; i++) { perChannel[i] = 0; } iamCentre = (configuration.getAgentType().equals( StandardEntityURN.AMBULANCE_CENTRE) || configuration.getAgentType().equals( StandardEntityURN.POLICE_OFFICE) || configuration .getAgentType().equals(StandardEntityURN.FIRE_STATION)); List<StandardEntity> centres; if (myTeamIndex == 0) { centres = new ArrayList<StandardEntity>(configuration .getCentresByType().get(StandardEntityURN.POLICE_OFFICE)); } else if (myTeamIndex == 1) { centres = new ArrayList<StandardEntity>(configuration .getCentresByType().get(StandardEntityURN.AMBULANCE_CENTRE)); } else { centres = new ArrayList<StandardEntity>(configuration .getCentresByType().get(StandardEntityURN.FIRE_STATION)); } Collections.sort(centres, new EntityComparator()); int counter = 0; int highest = 0; int myChannelIndex = -1; for (StandardEntity centre : centres) { int index = counter % myTeamChannels.size(); MessageChannel channel = myTeamChannels.get(index); outputChannels.put(centre.getID(), channel); perChannel[index] += RELATIVE_CENTRE_SHARE; if (perChannel[index] > highest) { highest = perChannel[index]; } if (centre.getID().equals(configuration.getEntityID())) { myOutputChannel = channel; myChannelIndex = index; } counter++; } int startCounter = counter; boolean metHighest = false; for (StandardEntity standardEntity : myPlatoonTeam) { int index = counter % myTeamChannels.size(); // This is to ensure centre channels are avoided until equivalent // capacity on other channels has been filled up if (index == 0 && !metHighest) { index = startCounter % myTeamChannels.size(); } MessageChannel channel = myTeamChannels.get(index); outputChannels.put(standardEntity.getID(), channel); perChannel[index]++; if (perChannel[index] == highest) { metHighest = true; } if (standardEntity.getID().equals(configuration.getEntityID())) { myOutputChannel = channel; myChannelIndex = index; } counter++; } myCentreOutChannels = centreChannels.get(myTeamIndex); mySubscribedChannels.addAll(myTeamChannels); if (iamCentre) { mySubscribedChannels.addAll(centreChannels.get(myTeamIndex + 1 % centreChannels.size())); mySubscribedChannels.addAll(centreChannels.get(myTeamIndex + 2 % centreChannels.size())); // If more channels available, listen to other platoons directly for (int i = 0; i < platoonChannels.get(0).size() && mySubscribedChannels.size() < maxListenCentre; i++) { for (int j = 1; j <= 2 && mySubscribedChannels.size() < maxListenCentre; j++) { int index = (myTeamIndex + 1 + j) % 3; List<MessageChannel> list = platoonChannels.get(index); if (list.size() <= i) { continue; } else { mySubscribedChannels.add(list.get(i)); } } } schedule = new SharedBandwidthSchedule(myOutputChannel, perChannel[myChannelIndex], RELATIVE_CENTRE_SHARE); } else { // If more channels available, listen to other centres directly for (int i = 0; i < centreChannels.get(0).size() && mySubscribedChannels.size() < maxListenPlatoon; i++) { for (int j = 0; j < 2 && mySubscribedChannels.size() < maxListenPlatoon; j++) { int index = (myTeamIndex + 1 + j) % 3; List<MessageChannel> list = centreChannels.get(index); if (list.size() <= i) { continue; } else { mySubscribedChannels.add(list.get(i)); } } } schedule = new SharedBandwidthSchedule(myOutputChannel, perChannel[myChannelIndex]); } } @Override public Map<MessageChannel, List<Message>> distributeMessages( List<Message> messagesToOwnTeam, List<Message> messagesToOtherTeams, ISimulationTimer timer) { outMap.clear(); outMap.put(myOutputChannel, messagesToOwnTeam); if (messagesToOtherTeams.size() > 0) { for (MessageChannel channel : myCentreOutChannels) { outMap.put(channel, new ArrayList<Message>()); } int counter = 0; for (Message message : messagesToOtherTeams) { outMap.get( myCentreOutChannels.get(counter % myCentreOutChannels.size())).add(message); counter++; } } return outMap; } @Override public List<MessageChannel> getChannelsToOtherTeams() { return myCentreOutChannels; } @Override public List<MessageChannel> getChannelsToOwnTeam() { return myTeamChannels; } @Override public List<MessageChannel> getChannelsToSubscribeTo() { return mySubscribedChannels; } @Override public StandardEntityURN getMyRole() { return configuration.getAgentType(); } @Override public IMessagingSchedule getScheduler() { return schedule; } /* * (non-Javadoc) * * @see * iamrescue.communication.scenario.ICommunicationScenario#reinitialiseTeam * (iamrescue.communication.ISimulationCommunicationConfiguration) */ @Override public void reinitialiseTeam(Collection<EntityID> toIgnore) { // // TODO : Code this. // newConfiguration.getCentresByType().get(key) } @Override public boolean amICentre() { // TODO Auto-generated method stub return false; } @Override public List<EntityID> getMyCentres() { // TODO Auto-generated method stub return null; } }