package rescuecore2.standard.kernel.comms; import java.util.Map; import rescuecore2.config.Config; import rescuecore2.worldmodel.Entity; import rescuecore2.worldmodel.EntityID; import rescuecore2.misc.collections.LazyMap; import rescuecore2.log.Logger; import rescuecore2.standard.messages.AKSpeak; import rescuecore2.standard.entities.StandardWorldModel; import rescuecore2.standard.entities.StandardEntity; import rescuecore2.standard.entities.StandardEntityURN; import rescuecore2.standard.entities.Human; /** A voice channel. */ public class VoiceChannel extends AbstractChannel { // Config option suffixes private static final String RANGE_SUFFIX = ".range"; private static final String MESSAGE_SIZE_SUFFIX = ".messages.size"; private static final String MESSAGE_MAX_SUFFIX = ".messages.max"; private int range; private int maxSize; private int maxMessages; private Map<EntityID, Integer> uttered; private StandardWorldModel world; /** Create a VoiceChannel. @param config The configuration to read. @param channelID The id of this channel. @param world The world model. */ public VoiceChannel(Config config, int channelID, StandardWorldModel world) { super(channelID); this.world = world; range = config.getIntValue(ChannelCommunicationModel.PREFIX + channelID + RANGE_SUFFIX); maxSize = config.getIntValue(ChannelCommunicationModel.PREFIX + channelID + MESSAGE_SIZE_SUFFIX); maxMessages = config.getIntValue(ChannelCommunicationModel.PREFIX + channelID + MESSAGE_MAX_SUFFIX); uttered = new LazyMap<EntityID, Integer>() { @Override public Integer createValue() { return 0; } }; } @Override public void timestep() { super.timestep(); uttered.clear(); } @Override protected void pushImpl(AKSpeak speak) throws InvalidMessageException { EntityID agentID = speak.getAgentID(); Entity e = world.getEntity(agentID); if (!(e instanceof Human)) { throw new InvalidMessageException("Agent " + agentID + " is not a human: " + (e == null ? "null" : e.getClass().getName())); } byte[] data = speak.getContent(); int count = uttered.get(agentID); if (count >= maxMessages) { throw new InvalidMessageException("Agent " + agentID + " has uttered too many voice messages on " + this); } if (data.length > maxSize) { throw new InvalidMessageException("Agent " + agentID + " tried to send an oversize voice message: " + data.length + " bytes but the limit is " + maxSize); } uttered.put(agentID, count + 1); // Find out who can hear it StandardEntity sender = world.getEntity(agentID); for (StandardEntity target : world.getEntitiesOfType(StandardEntityURN.FIRE_BRIGADE, StandardEntityURN.AMBULANCE_TEAM, StandardEntityURN.POLICE_FORCE, StandardEntityURN.CIVILIAN)) { if (world.getDistance(sender, target) <= range) { Logger.debug(target + " can hear voice message from " + sender); addMessageForAgent(target, speak); } } } @Override public String toString() { return "Voice channel " + channelID + " (range = " + range + ", max " + maxMessages + " messages of size " + maxSize + ")"; } }