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 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.Map.Entry;
import javolution.util.FastList;
import javolution.util.FastMap;
import org.apache.log4j.Logger;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.worldmodel.EntityID;
public class CompleteCoverageScenario implements ICommunicationScenario {
private ISimulationCommunicationConfiguration configuration;
private MessageChannel myChannel;
private int totalAgentsOnChannel;
private SharedBandwidthSchedule myScheduler;
Map<MessageChannel, List<Message>> map = new FastMap<MessageChannel, List<Message>>();
private static final Logger LOGGER = Logger
.getLogger(CompleteCoverageScenario.class);
public CompleteCoverageScenario(
ISimulationCommunicationConfiguration configuration) {
this.configuration = configuration;
// Divide channels equally between all agents
List<MessageChannel> channels = new ArrayList<MessageChannel>(
configuration.getRadioChannels());
Collections.sort(channels, new Comparator<MessageChannel>() {
@Override
public int compare(MessageChannel o1, MessageChannel o2) {
return Double.compare(o1.getChannelNumber(), o2
.getChannelNumber());
}
});
// Bandwidth per channel
int bandwidths[] = new int[channels.size()];
// number of agents assigned to channel
int assigned[] = new int[channels.size()];
int totalBandwidth = 0;
for (int i = 0; i < channels.size(); i++) {
MessageChannel messageChannel = channels.get(i);
bandwidths[i] = messageChannel.getBandwidth();
assigned[i] = 0;
totalBandwidth += messageChannel.getBandwidth();
}
List<StandardEntity> agents = new ArrayList<StandardEntity>();
Map<StandardEntityURN, Collection<StandardEntity>> agentsByType = configuration
.getAgentsByType();
for (Entry<StandardEntityURN, Collection<StandardEntity>> entry : agentsByType
.entrySet()) {
Collection<StandardEntity> theseAgents = entry.getValue();
agents.addAll(theseAgents);
}
int numAgents = agents.size();
// Which channel are they assigned to?
int[] assignedTo = new int[numAgents];
Collections.sort(agents, new EntityComparator());
// Greedily add agents to channels
int myIndex = -1;
for (int i = 0; i < assignedTo.length; i++) {
int bestChannel = -1;
int bestBandwidth = -1;
for (int j = 0; j < bandwidths.length; j++) {
int newBandwidth;
if (assigned[j] == 0) {
newBandwidth = bandwidths[j];
} else {
newBandwidth = assigned[j] * bandwidths[j]
/ (assigned[j] + 1);
}
if (newBandwidth > bestBandwidth) {
bestBandwidth = newBandwidth;
bestChannel = j;
}
}
assignedTo[i] = bestChannel;
bandwidths[bestChannel] = bestBandwidth;
assigned[bestChannel]++;
if (agents.get(i).getID().equals(configuration.getEntityID())) {
// Done myself
myChannel = channels.get(bestChannel);
myIndex = i;
}
}
totalAgentsOnChannel = assigned[assignedTo[myIndex]];
myScheduler = new SharedBandwidthSchedule(myChannel,
totalAgentsOnChannel);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Assigned channel " + myChannel + " to "
+ configuration.getEntityID() + ". This is shared with "
+ totalAgentsOnChannel
+ " in total, resulting in a bandwidth of "
+ myScheduler.getAllocatedMessagesSize(myChannel, 1)
+ " bytes each, maximum "
+ myScheduler.getAllocatedMessagesCount(myChannel, 0)
+ " messages and size "
+ myScheduler.getAllocatedMessagesSize(myChannel, 0));
}
}
@Override
public List<MessageChannel> getChannelsToOtherTeams() {
return Collections.singletonList(myChannel);
}
@Override
public List<MessageChannel> getChannelsToOwnTeam() {
return Collections.singletonList(myChannel);
}
@Override
public List<MessageChannel> getChannelsToSubscribeTo() {
List<MessageChannel> channels = new ArrayList<MessageChannel>();
channels.addAll(configuration.getRadioChannels());
return channels;
}
@Override
public StandardEntityURN getMyRole() {
return configuration.getAgentType();
}
@Override
public IMessagingSchedule getScheduler() {
return myScheduler;
}
/*
* (non-Javadoc)
*
* @see
* iamrescue.communication.scenario.ICommunicationScenario#distributeMessages
* (java.util.List, java.util.List, iamrescue.agent.ISimulationTimer)
*/
@Override
public Map<MessageChannel, List<Message>> distributeMessages(
List<Message> messagesToOwnTeam,
List<Message> messagesToOtherTeams, ISimulationTimer timer) {
map.clear();
List<Message> list = new FastList<Message>();
list.addAll(messagesToOtherTeams);
list.addAll(messagesToOwnTeam);
map.put(myChannel, list);
return map;
}
/*
* (non-Javadoc)
*
* @see
* iamrescue.communication.scenario.ICommunicationScenario#reinitialiseTeam
* (iamrescue.communication.ISimulationCommunicationConfiguration)
*/
@Override
public void reinitialiseTeam(Collection<EntityID> toIgnore) {
// Don't need to do anything
}
@Override
public List<EntityID> getMyCentres() {
return new ArrayList<EntityID>();
}
@Override
public boolean amICentre() {
return false;
}
}