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.ChannelDividerUtil; import iamrescue.communication.scenario.ICommunicationScenario; import iamrescue.util.comparators.ChannelBandwidthComparator; import iamrescue.util.comparators.EntityIDComparator; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Set; import javolution.util.FastMap; import javolution.util.FastSet; import org.apache.log4j.Logger; import rescuecore2.misc.Pair; import rescuecore2.standard.entities.StandardEntity; import rescuecore2.standard.entities.StandardEntityURN; import rescuecore2.worldmodel.EntityID; public class DefaultIAMCommunicationsScenario implements ICommunicationScenario { // TODO: Should do this per agent? // Channels with this bandwidth are considered high-bandwidth public static final int HIGH_BANDWIDTH_THRESHOLD = 800; // If we can achieve this per agent, we always prefer single teams: public static final int PER_AGENT_SINGLE_TEAM_THRESHOLD = 150; private ISimulationCommunicationConfiguration configuration; private ArrayList<MessageChannel> radioChannels; private Map<EntityID, IAMTeamCommunicationConfiguration> teamConfigurations = new FastMap<EntityID, IAMTeamCommunicationConfiguration>(); private Map<MessageChannel, List<Message>> mapOut = new FastMap<MessageChannel, List<Message>>(); private int maxCentreChannels; private int maxPlatoonChannels; private List<IAMTeamCommunicationConfiguration> configs = new ArrayList<IAMTeamCommunicationConfiguration>(); private MessageChannel myTeamOut; private IMessagingSchedule teamSchedule; private IMessagingSchedule overflowSchedule; private MessageChannel myOverflowOut; private List<MessageChannel> mySubscribed; private List<MessageChannel> channelsToOwnTeam; private List<MessageChannel> channelsToOtherTeams; private IMessagingSchedule scheduler; private IAMTeamCommunicationConfiguration myTeamConfig; private static final Logger LOGGER = Logger .getLogger(DefaultIAMCommunicationsScenario.class); public DefaultIAMCommunicationsScenario( ISimulationCommunicationConfiguration configuration) { // Set up config fields. this.configuration = configuration; maxCentreChannels = configuration.getMaxListenChannelCountCentre() - configuration.getVoiceChannels().size(); maxPlatoonChannels = configuration.getMaxListenChannelCountPlatoon() - configuration.getVoiceChannels().size(); radioChannels = new ArrayList<MessageChannel>(configuration .getRadioChannels()); // sort channels by increasing bandwidth Collections.sort(radioChannels, ChannelBandwidthComparator.INSTANCE); // First try single team with all agents Collection<StandardEntity> allPlatoons = ChannelDividerUtil .flattenMap(configuration.getPlatoonsByType()); int numAgents = allPlatoons.size(); // If desired num. of bytes can be met, we prefer single team scenario. int desired = numAgents * PER_AGENT_SINGLE_TEAM_THRESHOLD; // Now try desired scenarios in order // First try single team, desired bandwidth boolean done = attemptToGenerateScenario(1, maxPlatoonChannels, desired); // Now try 3,2,1 teams in order, using high bandwidth target. int teams = 3; while (!done && teams > 0) { done = attemptToGenerateScenario(teams, maxPlatoonChannels, HIGH_BANDWIDTH_THRESHOLD); teams--; } // Now repeat 3,2,1 teams, but accept any bandwidth above 0 teams = 3; while (!done && teams > 0) { done = attemptToGenerateScenario(teams, maxPlatoonChannels, 1); teams--; } if (!done) { LOGGER.warn("No communication scenario was possible. " + "Agent is not sending or receiving"); // generateNoCommunicationScenario(); throw new IllegalStateException("Could not generate scenario."); } else { finaliseAllocation(); } } private void generateNoCommunicationScenario() { List<MessageChannel> emptyList = new ArrayList<MessageChannel>(); channelsToOtherTeams = emptyList; channelsToOwnTeam = emptyList; mySubscribed = emptyList; // Empty multi channel scheduler returns 0 to all by default. scheduler = new MultiChannelScheduler(configuration.getVoiceChannels()); } private boolean attemptToGenerateScenario(int teams, int maxChannelsPerTeam, int targetMinimumBandwidth) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Attempting to achieve total bandwidth of " + targetMinimumBandwidth + " bytes with " + teams + " team" + ((teams == 1) ? "" : "s") + "."); } // Try to allocate List<List<MessageChannel>> mainTeamChannels = distributeChannels(teams, maxPlatoonChannels); // What's the bandwidth for this? int minBandwidthAvailable = ChannelDividerUtil .findMinimumBandwidth(mainTeamChannels); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Total achievable: " + minBandwidthAvailable + " bytes"); } if (minBandwidthAvailable >= targetMinimumBandwidth) { // Good if (LOGGER.isDebugEnabled()) { LOGGER.debug("This is enough. Starting generation " + "for main channels: " + mainTeamChannels); } generateMultipleChannelsScenario(mainTeamChannels); return true; } else { // Not good if (LOGGER.isDebugEnabled()) { LOGGER.debug("This is not enough."); } return false; } } /** * */ private void finaliseAllocation() { // All allocations are done now. Extract relevant info from the configs for (IAMTeamCommunicationConfiguration config : configs) { Set<EntityID> centres = config.getCentres(); for (EntityID entityID : centres) { teamConfigurations.put(entityID, config); } Set<EntityID> platoons = config.getPlatoons(); for (EntityID entityID : platoons) { teamConfigurations.put(entityID, config); } } EntityID id = configuration.getEntityID(); myTeamConfig = teamConfigurations.get(id); if (myTeamConfig == null) { // I am a centre that is not taking part } else { myTeamOut = myTeamConfig.getOutputMainChannels().get(id); myOverflowOut = myTeamConfig.getOutputOverflowChannels().get(id); mySubscribed = myTeamConfig.getSubscribedChannels().get(id); channelsToOwnTeam = myTeamConfig.getMainCommunicationChannels(); channelsToOtherTeams = new ArrayList<MessageChannel>(); // Now create schedules int myShare; if (myTeamConfig.getCentres().contains(id)) { myShare = IAMTeamCommunicationConfiguration.RELATIVE_CENTRE_BANDIWDTH; } else { myShare = 1; } List<EntityID> list = myTeamConfig.getChannelSenders().get( myTeamOut); int totalBandwidthTeamOut = 0; for (EntityID otherID : list) { if (myTeamConfig.getCentres().contains(otherID)) { totalBandwidthTeamOut += IAMTeamCommunicationConfiguration.RELATIVE_CENTRE_BANDIWDTH; } else { totalBandwidthTeamOut++; } } teamSchedule = new SharedBandwidthSchedule(myTeamOut, totalBandwidthTeamOut, myShare); if (myOverflowOut != null) { list = myTeamConfig.getChannelSenders().get(myOverflowOut); int totalBandwidthOverflow = 0; for (EntityID otherID : list) { if (myTeamConfig.getCentres().contains(otherID)) { totalBandwidthOverflow += IAMTeamCommunicationConfiguration.RELATIVE_CENTRE_BANDIWDTH; } else { totalBandwidthOverflow++; } } overflowSchedule = new SharedBandwidthSchedule(myOverflowOut, totalBandwidthOverflow, myShare); } MultiChannelScheduler scheduler = new MultiChannelScheduler( configuration.getVoiceChannels()); scheduler.addSchedule(myTeamOut, teamSchedule); if (overflowSchedule != null) { scheduler.addSchedule(myOverflowOut, overflowSchedule); } this.scheduler = scheduler; if (LOGGER.isInfoEnabled()) { LOGGER.info(toVerboseString()); LOGGER.info(myTeamConfig.toVerboseString()); } } } public String toVerboseString() { String str = "Scenario for agent " + configuration.getEntityID(); str += myTeamConfig.getCentres().contains(configuration.getEntityID()) ? " (centre role) " : " (platoon) "; if (myTeamOut == null) { str += ", inactive (not sending)"; } else { str += ", sending to " + myTeamOut.getChannelNumber() + " (" + scheduler.getAllocatedTotalBandwidth(myTeamOut, 1) + " bytes ), overflow: "; str += (myOverflowOut != null) ? myOverflowOut.getChannelNumber() + " (" + scheduler.getAllocatedTotalBandwidth(myOverflowOut, 0) + " bytes)" : "none"; } str += ", listening to"; for (MessageChannel channel : mySubscribed) { str += " " + channel.getChannelNumber(); } return str; } private void generateMultipleChannelsScenario( List<List<MessageChannel>> mainTeamChannels) { // Work out how many teams there are int teams = mainTeamChannels.size(); // Filter out remaining channels as overflow channels Set<MessageChannel> taken = new FastSet<MessageChannel>(); for (List<MessageChannel> channelList : mainTeamChannels) { for (MessageChannel messageChannel : channelList) { taken.add(messageChannel); } } List<MessageChannel> overflowChannels = new ArrayList<MessageChannel>(); for (MessageChannel messageChannel : radioChannels) { if (!taken.contains(messageChannel)) { overflowChannels.add(messageChannel); } } // Now assign overflow channels equally to the teams. int maxOverflow = maxCentreChannels; List<List<MessageChannel>> overflowChannelsAssigned = distributeUnallocatedChannels( mainTeamChannels, Integer.MAX_VALUE); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Assigned initial overflow channels: " + overflowChannelsAssigned + ", based on max number: " + maxOverflow); } // Now assign all remaining as overflow (in case there are multiple // centres) /* * List<List<MessageChannel>> moreOverflowChannelsAssigned = * distributeUnallocatedChannels( mainTeamChannels, maxOverflow); */ sortByDecreasingMainChannelBW(mainTeamChannels, overflowChannelsAssigned); // Now split up teams List<List<StandardEntity>> generatedTeams = generateTeams(teams); for (int i = 0; i < generatedTeams.size(); i++) { ArrayList<MessageChannel> otherOverflow = new ArrayList<MessageChannel>(); if (teams > 1) { otherOverflow.addAll(overflowChannelsAssigned.get((i + 1) % teams)); if (teams > 2) { otherOverflow.addAll(overflowChannelsAssigned.get((i + 2) % teams)); } } List<MessageChannel> lowPriority; if (teams == 1) { lowPriority = new ArrayList<MessageChannel>(); } else if (teams == 2) { lowPriority = otherOverflow; } else { lowPriority = mainTeamChannels.get((i + 2) % 3); } List<MessageChannel> veryLowPriority; if (teams <= 2) { veryLowPriority = new ArrayList<MessageChannel>(); } else { veryLowPriority = otherOverflow; } List<MessageChannel> highPriority; if (teams == 1) { highPriority = new ArrayList<MessageChannel>(); } else { highPriority = mainTeamChannels.get((i + 1) % teams); } IAMTeamCommunicationConfiguration team = IAMTeamCommunicationConfiguration .createTeam(mainTeamChannels.get(i), overflowChannelsAssigned.get(i), highPriority, lowPriority, veryLowPriority, generatedTeams.get(i), maxPlatoonChannels, maxCentreChannels); configs.add(team); } } private void sortByDecreasingMainChannelBW( List<List<MessageChannel>> mainTeamChannels, List<List<MessageChannel>> overflowChannelsAssigned) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Reordering main team and associated overflow " + "channels, so that they are " + "ordered by decreasing bandwidth for main " + "channels. Main before: " + mainTeamChannels + ", overflow before: " + overflowChannelsAssigned); } List<Pair<List<MessageChannel>, Integer>> pairs = new ArrayList<Pair<List<MessageChannel>, Integer>>(); for (int i = 0; i < mainTeamChannels.size(); i++) { pairs.add(new Pair<List<MessageChannel>, Integer>(mainTeamChannels .get(i), i)); } // Now sort based on total bandwidth for main channels Collections.sort(pairs, new Comparator<Pair<List<MessageChannel>, Integer>>() { @Override public int compare( Pair<List<MessageChannel>, Integer> arg0, Pair<List<MessageChannel>, Integer> arg1) { int compared = -Double.compare(ChannelDividerUtil .computeTotalBandwidth(arg0.first()), ChannelDividerUtil.computeTotalBandwidth(arg1 .first())); if (compared != 0) { return compared; } else { return Double.compare(arg1.second(), arg0.second()); } } }); List<List<MessageChannel>> overflowCopy = new ArrayList<List<MessageChannel>>( overflowChannelsAssigned); // Use result to re-order original lists for (int i = 0; i < pairs.size(); i++) { mainTeamChannels.set(i, pairs.get(i).first()); overflowChannelsAssigned.set(i, overflowCopy.get(i)); } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Main after: " + mainTeamChannels + ", overflow after: " + overflowChannelsAssigned); } } private List<List<StandardEntity>> generateTeams(int number) { if (number == 1) { List<List<StandardEntity>> list = new ArrayList<List<StandardEntity>>(); list.add(ChannelDividerUtil.flattenMap(configuration .getAgentsByType())); return list; } else { // Split into two or more teams List<StandardEntity> policeAgents = new ArrayList<StandardEntity>( configuration.getAgentsByType().get( StandardEntityURN.POLICE_FORCE)); List<StandardEntity> policeCentres = new ArrayList<StandardEntity>( configuration.getAgentsByType().get( StandardEntityURN.POLICE_OFFICE)); List<StandardEntity> ambulanceAgents = new ArrayList<StandardEntity>( configuration.getAgentsByType().get( StandardEntityURN.AMBULANCE_TEAM)); List<StandardEntity> ambulanceCentres = new ArrayList<StandardEntity>( configuration.getAgentsByType().get( StandardEntityURN.AMBULANCE_CENTRE)); List<StandardEntity> fireAgents = new ArrayList<StandardEntity>( configuration.getAgentsByType().get( StandardEntityURN.FIRE_BRIGADE)); List<StandardEntity> fireCentres = new ArrayList<StandardEntity>( configuration.getAgentsByType().get( StandardEntityURN.FIRE_STATION)); // sort by ids, so that consistent information is generated by all // agents. Collections.sort(policeAgents, new EntityIDComparator()); Collections.sort(policeCentres, new EntityIDComparator()); Collections.sort(ambulanceAgents, new EntityIDComparator()); Collections.sort(ambulanceCentres, new EntityIDComparator()); Collections.sort(fireAgents, new EntityIDComparator()); Collections.sort(fireCentres, new EntityIDComparator()); List<List<StandardEntity>> platoons = new ArrayList<List<StandardEntity>>(); platoons.add(policeAgents); platoons.add(fireAgents); platoons.add(ambulanceAgents); List<List<StandardEntity>> centres = new ArrayList<List<StandardEntity>>(); centres.add(policeCentres); centres.add(fireCentres); centres.add(ambulanceCentres); if (number == 2) { List<StandardEntity> team1 = new ArrayList<StandardEntity>(); List<StandardEntity> team2 = new ArrayList<StandardEntity>(); List<StandardEntity> centres1 = new ArrayList<StandardEntity>(); List<StandardEntity> centres2 = new ArrayList<StandardEntity>(); // Add largest platoon team to first channel int largestSize = -1; int largestIndex = -1; for (int i = 0; i < platoons.size(); i++) { if (platoons.get(i).size() > largestSize) { largestSize = platoons.get(i).size(); largestIndex = i; } } team1.addAll(platoons.remove(largestIndex)); centres1.addAll(centres.remove(largestIndex)); // Are the remaining small enough to share one team? if (platoons.get(0).size() + platoons.get(1).size() <= team1 .size()) { // Yes team2.addAll(platoons.remove(0)); centres2.addAll(centres.remove(0)); team2.addAll(platoons.remove(1)); centres2.addAll(centres.remove(1)); } else { // No team2.addAll(platoons.remove(0)); centres2.addAll(centres.remove(0)); // Divide up remaining team List<StandardEntity> remainingPlatoons = platoons.get(0); List<StandardEntity> remainingCentres = centres.get(0); int toSecond = (team1.size() - team2.size() + remainingPlatoons .size()) / 2; for (int i = 0; i < toSecond; i++) { team2.add(remainingPlatoons.get(i)); } for (int i = toSecond; i < remainingPlatoons.size(); i++) { team1.add(remainingPlatoons.get(i)); } // Divide up centres equally for (int i = 0; i < remainingCentres.size(); i++) { if (i % 2 == 0) { centres2.add(remainingCentres.get(i)); } else { centres1.add(remainingCentres.get(i)); } } // Check if we can re-distribute centres? while (centres2.size() - centres1.size() > 1) { centres1.add(centres2.remove(centres2.size() - 1)); } while (centres1.size() - centres2.size() > 1) { centres2.add(centres1.remove(centres1.size() - 1)); } } List<List<StandardEntity>> teams = new ArrayList<List<StandardEntity>>(); team1.addAll(centres1); team2.addAll(centres2); teams.add(team1); teams.add(team2); return teams; } else { // 3 teams List<List<StandardEntity>> platoonList = new ArrayList<List<StandardEntity>>(); platoonList.add(policeAgents); platoonList.add(ambulanceAgents); platoonList.add(fireAgents); List<List<StandardEntity>> centreList = new ArrayList<List<StandardEntity>>(); centreList.add(policeCentres); centreList.add(ambulanceCentres); centreList.add(fireCentres); boolean done = false; while (!done) { int largest = getLargest(centreList); int smallest = getSmallest(centreList); List<StandardEntity> largestList = centreList.get(largest); List<StandardEntity> smallestList = centreList .get(smallest); if (largestList.size() - smallestList.size() > 1) { smallestList.add(largestList .remove(largestList.size() - 1)); } else { done = true; } } for (int i = 0; i < 3; i++) { platoonList.get(i).addAll(centreList.get(i)); } return platoonList; } } } public int getLargest(List<? extends List<?>> collection) { int largest = -1; int largestIndex = -1; int counter = 0; for (List<?> collection2 : collection) { if (collection2.size() > largest) { largest = collection2.size(); largestIndex = counter; } counter++; } return largestIndex; } public int getSmallest(List<? extends List<?>> collection) { int smallest = Integer.MAX_VALUE; int smallestIndex = -1; int counter = 0; for (List<?> collection2 : collection) { if (collection2.size() < smallest) { smallest = collection2.size(); smallestIndex = counter; } counter++; } return smallestIndex; } private void generateSingleChannelScenario(List<MessageChannel> list) { // We have only one team. Every writes to and reads from the same // channels // First work out if we have centres. Each one can listen to overflow // channels and aggregate information from those into the main channel List<MessageChannel> overflowChannels = new ArrayList<MessageChannel>(); for (int i = 0; i < radioChannels.size(); i++) { MessageChannel messageChannel = radioChannels.get(i); if (!list.contains(messageChannel)) { overflowChannels.add(messageChannel); } } List<StandardEntity> allAgents = ChannelDividerUtil .flattenMap(configuration.getAgentsByType()); IAMTeamCommunicationConfiguration team = IAMTeamCommunicationConfiguration .createTeam(list, overflowChannels, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, allAgents, maxPlatoonChannels, maxCentreChannels); configs.add(team); } /** * * @param radioChannels * All radio channels * @param requiredTeams * The number of teams to allocate channels to * @param maxChannelsPerTeam * The maximum number of channels per team * @return An allocation with the highest bandwidth channels distributed * between teams */ private List<List<MessageChannel>> distributeChannels(int requiredTeams, int maxChannelsPerTeam) { List<List<MessageChannel>> alreadyAllocated = new ArrayList<List<MessageChannel>>( requiredTeams); for (int i = 0; i < requiredTeams; i++) { alreadyAllocated.add(new ArrayList<MessageChannel>()); } return distributeUnallocatedChannels(alreadyAllocated, maxChannelsPerTeam); } /** * This method distributes all radioChannels that have not been allocated to * the teams, maximising the minimum total bandwidth for any team. * * @param alreadyAllocated * The channels for each team that have already been allocated. * @param maxChannelsPerTeam * The maximum number of channels that each team should get * allocated. * @return The allocation. */ private List<List<MessageChannel>> distributeUnallocatedChannels( List<List<MessageChannel>> alreadyAllocated, int maxChannelsPerTeam) { // Try to satisfy high bandwidth requirements for the number of required // teams. Set<MessageChannel> available = new FastSet<MessageChannel>(); available.addAll(radioChannels); int teams = alreadyAllocated.size(); List<List<MessageChannel>> allocated = new ArrayList<List<MessageChannel>>(); // total allocated bandwidth to each team int[] totalBandwidths = new int[teams]; // Total allocated num. channels to each team int[] totalChannels = new int[teams]; // Initialise for (int i = 0; i < teams; i++) { allocated.add(new ArrayList<MessageChannel>()); totalBandwidths[i] = 0; List<MessageChannel> list = alreadyAllocated.get(i); totalChannels[i] = list.size(); for (MessageChannel messageChannel : list) { totalBandwidths[i] += messageChannel.getEffectiveBandwidth(); available.remove(messageChannel); } } // Just consider radio channels that have not been allocated yet. List<MessageChannel> radioChannelsLeft = new ArrayList<MessageChannel>(); radioChannelsLeft.addAll(available); // Sort by ascending bandwidth Collections .sort(radioChannelsLeft, ChannelBandwidthComparator.INSTANCE); // Assign one by one starting with highest bandwidth for (int i = radioChannelsLeft.size() - 1; i >= 0; i--) { MessageChannel channel = radioChannelsLeft.get(i); int lowest = -1; int lowestBandwidth = Integer.MAX_VALUE; // Find lowest total bandwidth for (int j = 0; j < teams; j++) { if (totalChannels[j] < maxChannelsPerTeam && totalBandwidths[j] < lowestBandwidth) { lowest = j; lowestBandwidth = totalBandwidths[j]; } } // Add channel to lowest if (lowest != -1) { allocated.get(lowest).add(channel); totalBandwidths[lowest] += channel.getEffectiveBandwidth(); totalChannels[lowest]++; } else { // Capacity reached break; } } return allocated; } @Override public Map<MessageChannel, List<Message>> distributeMessages( List<Message> messagesToOwnTeam, List<Message> messagesToOtherTeams, ISimulationTimer timer) { mapOut.clear(); // if (myTeamOut != null) { mapOut.put(myTeamOut, messagesToOwnTeam); // } else { // if (messagesToOwnTeam.size() > 0) { // LOGGER.error("Cannot send any messages as channel is null: " // + messagesToOwnTeam); // } // } if (messagesToOtherTeams.size() > 0) { LOGGER.error("Cannot send messages to other team. Tried: " + messagesToOtherTeams); } return mapOut; } @Override public List<MessageChannel> getChannelsToOtherTeams() { return channelsToOtherTeams; } @Override public List<MessageChannel> getChannelsToOwnTeam() { return channelsToOwnTeam; } @Override public List<MessageChannel> getChannelsToSubscribeTo() { return mySubscribed; } @Override public StandardEntityURN getMyRole() { return configuration.getAgentType(); } @Override public IMessagingSchedule getScheduler() { return scheduler; } @Override public void reinitialiseTeam(Collection<EntityID> toIgnore) { myTeamConfig.reinitialise(toIgnore); finaliseAllocation(); } public static class MultiChannelScheduler implements IMessagingSchedule { private Map<MessageChannel, IMessagingSchedule> map = new FastMap<MessageChannel, IMessagingSchedule>(); public MultiChannelScheduler(List<MessageChannel> voiceChannels) { // System.out.println("Voice channels: " + voiceChannels); for (MessageChannel channel : voiceChannels) { map.put(channel, new IMessagingSchedule() { @Override public int getMaximumRepetitions(MessageChannel channel, int time) { return 0; } @Override public int getAllocatedTotalBandwidth( MessageChannel channel, int time) { if (channel.getBandwidth() == null) { // Some high number (this happens for voice channels return getAllocatedMessagesSize(channel, time) * getAllocatedMessagesCount(channel, time); } else { return channel.getBandwidth(); } } @Override public int getAllocatedMessagesSize(MessageChannel channel, int time) { return channel.getMaxMessageSize(); } @Override public int getAllocatedMessagesCount( MessageChannel channel, int timestep) { return channel.getMaxMessageCount(); } }); } } public void addSchedule(MessageChannel channel, IMessagingSchedule schedule) { map.put(channel, schedule); } @Override public int getAllocatedMessagesCount(MessageChannel channel, int timestep) { IMessagingSchedule schedule = map.get(channel); if (schedule != null) { return schedule.getAllocatedMessagesCount(channel, timestep); } else { return 0; } } @Override public int getAllocatedMessagesSize(MessageChannel channel, int time) { IMessagingSchedule schedule = map.get(channel); if (schedule != null) { return schedule.getAllocatedMessagesSize(channel, time); } else { return 0; } } @Override public int getAllocatedTotalBandwidth(MessageChannel channel, int time) { IMessagingSchedule schedule = map.get(channel); if (schedule != null) { return schedule.getAllocatedTotalBandwidth(channel, time); } else { return 0; } } @Override public int getMaximumRepetitions(MessageChannel channel, int time) { IMessagingSchedule schedule = map.get(channel); if (schedule != null) { return schedule.getMaximumRepetitions(channel, time); } else { return 0; } } } @Override public boolean amICentre() { EntityID myID = configuration.getEntityID(); return myTeamConfig.getCentres().contains(myID); } @Override public Collection<EntityID> getMyCentres() { return myTeamConfig.getCentres(); } }