content: /*
   * Copyright 2011 Aalto University, ComNet
   * Released under GPLv3. See LICENSE.txt for details.
   */
  package report;
  
  import java.util.HashSet;
  import java.util.List;
  import java.util.Random;
  import java.util.Set;
  
  import core.Connection;
  import core.DTNHost;
  import core.Message;
  import core.Settings;
  import core.SettingsError;
  
  /**
   * Reports which messages are available (either in the buffer or at one
   * of the connected hosts' buffer) for certain, randomly selected,
   * tracked hosts. Supports the same settings as the
   * {@link MessageLocationReport}
   */
  public class MessageAvailabilityReport extends MessageLocationReport {
  
  	/** Number of tracked hosts -setting id ({@value}). Defines how many
  	 * hosts are selected for sampling message availability */
  	public static final String NROF_HOSTS_S = "nrofHosts";
  
  	private int nrofHosts;
  	private Set<DTNHost> trackedHosts;
  	private Random rng;
  
  	public MessageAvailabilityReport() {
  		super();
  		Settings s = getSettings();
  		nrofHosts = s.getInt(NROF_HOSTS_S, -1);
  		this.rng = new Random(nrofHosts);
  
  		this.trackedHosts = null;
  	}
  
  	/**
  	 * Randomly selects the hosts to track
  	 * @param allHosts All hosts in the scenario
  	 * @return The set of tracked hosts
  	 */
  	private Set<DTNHost> selectTrackedHosts(List<DTNHost> allHosts) {
  		Set<DTNHost> trackedHosts = new HashSet<DTNHost>();
  
  		if (this.nrofHosts > allHosts.size()) {
  			throw new SettingsError("Can't use more hosts than there are " +
  					"in the simulation scenario");
  		}
  
  
  		for (int i=0; i<nrofHosts; i++) {
  			DTNHost nextHost = allHosts.get(rng.nextInt(allHosts.size()));
  			if (trackedHosts.contains(nextHost)) {
  				i--;
  			} else {
  				trackedHosts.add(nextHost);
  			}
  		}
  
  		return trackedHosts;
  	}
  
  	/**
  	 * Creates a snapshot of message availability
  	 * @param hosts The list of tracked hosts in the world
  	 */
  	@Override
  	protected void createSnapshot(List<DTNHost> hosts) {
  		write("[" + (int) getSimTime() + "]"); /* write sim time stamp */
  
  		if (this.trackedHosts == null) {
  			this.trackedHosts = selectTrackedHosts(hosts);
  		}
  
  		for (DTNHost host : hosts) {
  			Set<String> msgIds = null;
  			String idString = "";
  
  			if (! this.trackedHosts.contains(host)) {
  				continue;
  			}
  
  			msgIds = new HashSet<String>();
  
  			/* add own messages */
  			for (Message m : host.getMessageCollection()) {
  				if (!isTracked(m)) {
  					continue;
  				}
  				msgIds.add(m.getId());
  			}
  			/* add all peer messages */
  			for (Connection c : host.getConnections()) {
  				DTNHost peer = c.getOtherNode(host);
  				for (Message m : peer.getMessageCollection()) {
  					if (!isTracked(m)) {
  						continue;
  					}
  					msgIds.add(m.getId());
  				}
  			}
  
  			for (String id : msgIds) {
  				idString += " " + id;
  			}
  
  			write(host + idString);
  		}
  	}
  }
  