content: /*
   * Copyright 2010 Aalto University, ComNet
   * Released under GPLv3. See LICENSE.txt for details.
   */
  package report;
  
  import java.util.Arrays;
  import java.util.LinkedList;
  import java.util.List;
  
  import core.ConnectionListener;
  import core.DTNHost;
  import core.UpdateListener;
  
  /**
   * The number of contacts during an inter-contact time metric is similar to
   * the inter-contact times metric, except that instead of measuring the time
   * until a node meets again, we count the number of other nodes both of the
   * nodes meet separately.  In contrast to the inter-contact times, the number
   * of contacts during an inter-contact is not symmetric, i.e. during an
   * inter-contact both nodes wait the exact same time but will meet a different
   * number of nodes.
   *
   * @author Frans Ekman
   */
  public class ContactsDuringAnICTReport extends Report
  	implements ConnectionListener, UpdateListener {
  
  	private boolean[][] areDisconnected;
  	private int[][] contactCount;
  	private LinkedList<Integer> contactsDuringIC;
  
  	private boolean updateHasBeenCalled;
  
  	public ContactsDuringAnICTReport() {
  		super();
  		init();
  	}
  
  
  	@Override
  	protected void init() {
  		super.init();
  		contactsDuringIC = new LinkedList<Integer>();
  	}
  
  
  	public void hostsConnected(DTNHost host1, DTNHost host2) {
  		if (!updateHasBeenCalled) {
  			return;
  		}
  		int id1 = host1.getAddress();
  		int id2 = host2.getAddress();
  		if (areDisconnected[id1][id2]) {
  			areDisconnected[id1][id2] = false;
  			areDisconnected[id2][id1] = false;
  			contactsDuringIC.add(new Integer(contactCount[id1][id2]));
  			contactsDuringIC.add(new Integer(contactCount[id2][id1]));
  			contactCount[id1][id2] = 0;
  			contactCount[id2][id1] = 0;
  		}
  
  		incContactForAllDisconnectedNodes(host1);
  		incContactForAllDisconnectedNodes(host2);
  
  	}
  
  	private void incContactForAllDisconnectedNodes(DTNHost host) {
  		int id = host.getAddress();
  		for (int i=0; i<contactCount[id].length; i++) {
  			if (areDisconnected[id][i]) {
  				contactCount[id][i]++;
  			}
  		}
  	}
  
  	public void hostsDisconnected(DTNHost host1, DTNHost host2) {
  		if (!updateHasBeenCalled) {
  			return;
  		}
  		areDisconnected[host1.getAddress()][host2.getAddress()] = true;
  		areDisconnected[host2.getAddress()][host1.getAddress()] = true;
  	}
  
  	public void updated(List<DTNHost> hosts) {
  		if (areDisconnected == null || contactCount == null) {
  			areDisconnected = new boolean[hosts.size()][hosts.size()];
  			contactCount = new int[hosts.size()][hosts.size()];
  		}
  		updateHasBeenCalled = true;
  	}
  
  	@Override
  	public void done() {
  		Integer[] contacts = (Integer[])contactsDuringIC.toArray(new Integer[0]);
  		Arrays.sort(contacts);
  
  		int count = 0;
  		int last = 0;
  		for (int i=0; i<contacts.length; i++) {
  			if (contacts[i].intValue() == last) {
  				count++;
  				if (i == contacts.length -1) {
  					write(last + "\t" + count);
  				}
  			} else {
  				write(last + "\t" + count);
  				last++;
  				i--;
  				count = 0;
  			}
  		}
  		super.done();
  	}
  }
  