// Path: comm-library/src/network/MessageType.java
// public class MessageType {
// 	// Control-related messages
// 	public final static int PING = 0;
// 	public static final int PING_RESPONSE = 1;
// 	public static int STATUS = 2;
// 	public static int STATUS_RESPONSE = 3;
// 	public static int CONTROL_FLOW = 4;
// 	public static int NODELIST = 5;
// 	public static int NODELIST_RESPONSE = 6;
// 	// the boundary
// 	public static int CONTROL = 31;
// 
// 	// Evolve-related messages
// 	public static int MIGRANT_MESSAGE = 32;
// 	public static int BEST_INDIVIDUAL = 33;
// 	// the boundary
// 	public static int EVOLVE = 64;
// 
// 	// Data-related messages
// 	public static int DATA_DESCRIPTION = 64;
// 	// the boundary
// 	public static int DATA = 96;
// 
// }
// 
// Path: comm-library/src/utility/IP.java
// public class IP {
// 	public String id;
// 	public String ip;
// 	public int port;
// 
// 	public IP(String _id, String _ip, int _port) {
// 		id = _id;
// 		ip = _ip;
// 		port = _port;
// 	}
// 
// 	public boolean equals(IP other) {
// 		return ((this.id == other.id) && (this.ip.equals(other.ip)) && (this.port == other.port));
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return String.valueOf(id) + ":" + ip + ":" + String.valueOf(port);
// 	}
// 
// 	public static final int ipToInt(String addr) {
// 		String[] addrArray = addr.split("\\.");
// 		if (addrArray.length != 4) {
// 			System.err.println("Improper ip address:" + addr);
// 			return 0;
// 		}
// 		int num = 0;
// 		for (int i = 0; i < addrArray.length; i++) {
// 			num += ((Integer.parseInt(addrArray[i]) % 256 * Math
// 					.pow(256, 3 - i)));
// 		}
// 		return num;
// 	}
// 
// 	public static String makeID(String ip, int port) {
// 		return ip + ":" + port;
// 	}
// 	
// 	public static String intToIp(int i) {
// 		return ((i >> 24) & 0xFF) + "." + ((i >> 16) & 0xFF) + "."
// 				+ ((i >> 8) & 0xFF) + "." + (i & 0xFF);
// 	}
// 
// 	/**
// 	 * Translate an "ip:port" pair into an IP object
// 	 * @param ip
// 	 * @return
// 	 */
// 	public static IP fromString(String ip) {
// 		// split into ip and port
// 		// TODO this should be done in a more stable/predictable way, plus tests
// 		String[] splitted = ip.split(":");
// 		if (splitted.length == 2) { 
// 			String id = IP.makeID(splitted[0], Integer.parseInt(splitted[1]));
// 			IP result = new IP(id, splitted[0], Integer.parseInt(splitted[1]));
// 			System.out
// 					.println(String.format(
// 							"String: %s    after formatting (2): %s", ip,
// 							result.toString()));
// 			return result;
// 		} else if (splitted.length == 1) {
// 			String id = IP.makeID(splitted[0], Control.PORT);
// 			IP result = new IP(id, splitted[0], Control.PORT);
// 			System.out
// 					.println(String.format(
// 							"String: %s    after formatting (1): %s", ip,
// 							result.toString()));
// 			return result;
// 		} else {
// 			System.err.println(String.format("Invalid IP entered: %s", ip));
// 			System.exit(-1);
// 			return null;
// 		}
// 	}
// }


import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import network.MessageType;
import utility.IP;

	public void succeed(String nodeID, NodeListEntry nle, Timestamp t) {
		succeed(nodeID, nle.ip, nle.port, nle.subnetLabel, t);
	}
	
	public synchronized void succeed(String nodeID, String ip, int port,
			String s, Timestamp t) {
		if (nodeID.equals(this.nodeID)) {
			// Don't add ourselves!
			return;
		}
		// add an entry to the goodNodeTable
		// TODO CHECK TO MAKE SURE THIS ENTRY IS MORE UP-TO-DATE
		Control.println(String.format("NodeList: recording success for node %s:%d",ip,port));
		if (!goodNodeTable.containsKey(nodeID)) {
			if (badNodeTable.containsKey(nodeID)) {
				badNodeTable.remove(nodeID);
				reportDeltas(1, goodNodeTable.size(), 1, 0, -1, 0,
						badNodeTable.size(), 0, 1, 0, MessageType.PING);
			} else {
				reportDeltas(1, goodNodeTable.size(), 0, 1, 0, 0,
						badNodeTable.size(), 0, 1, 0, MessageType.PING);
			}
		}
		goodNodeTable.put(nodeID, new NodeListEntry(ip, port, s, t));
		if (hasSecondTier() && (s.equals(this.subnetID))) {
			subnetNeighbors.add(nodeID);
		}
	}

// Path: comm-library/src/network/MessageType.java
// public class MessageType {
// 	// Control-related messages
// 	public final static int PING = 0;
// 	public static final int PING_RESPONSE = 1;
// 	public static int STATUS = 2;
// 	public static int STATUS_RESPONSE = 3;
// 	public static int CONTROL_FLOW = 4;
// 	public static int NODELIST = 5;
// 	public static int NODELIST_RESPONSE = 6;
// 	// the boundary
// 	public static int CONTROL = 31;
// 
// 	// Evolve-related messages
// 	public static int MIGRANT_MESSAGE = 32;
// 	public static int BEST_INDIVIDUAL = 33;
// 	// the boundary
// 	public static int EVOLVE = 64;
// 
// 	// Data-related messages
// 	public static int DATA_DESCRIPTION = 64;
// 	// the boundary
// 	public static int DATA = 96;
// 
// }
// 
// Path: comm-library/src/utility/IP.java
// public class IP {
// 	public String id;
// 	public String ip;
// 	public int port;
// 
// 	public IP(String _id, String _ip, int _port) {
// 		id = _id;
// 		ip = _ip;
// 		port = _port;
// 	}
// 
// 	public boolean equals(IP other) {
// 		return ((this.id == other.id) && (this.ip.equals(other.ip)) && (this.port == other.port));
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return String.valueOf(id) + ":" + ip + ":" + String.valueOf(port);
// 	}
// 
// 	public static final int ipToInt(String addr) {
// 		String[] addrArray = addr.split("\\.");
// 		if (addrArray.length != 4) {
// 			System.err.println("Improper ip address:" + addr);
// 			return 0;
// 		}
// 		int num = 0;
// 		for (int i = 0; i < addrArray.length; i++) {
// 			num += ((Integer.parseInt(addrArray[i]) % 256 * Math
// 					.pow(256, 3 - i)));
// 		}
// 		return num;
// 	}
// 
// 	public static String makeID(String ip, int port) {
// 		return ip + ":" + port;
// 	}
// 	
// 	public static String intToIp(int i) {
// 		return ((i >> 24) & 0xFF) + "." + ((i >> 16) & 0xFF) + "."
// 				+ ((i >> 8) & 0xFF) + "." + (i & 0xFF);
// 	}
// 
// 	/**
// 	 * Translate an "ip:port" pair into an IP object
// 	 * @param ip
// 	 * @return
// 	 */
// 	public static IP fromString(String ip) {
// 		// split into ip and port
// 		// TODO this should be done in a more stable/predictable way, plus tests
// 		String[] splitted = ip.split(":");
// 		if (splitted.length == 2) { 
// 			String id = IP.makeID(splitted[0], Integer.parseInt(splitted[1]));
// 			IP result = new IP(id, splitted[0], Integer.parseInt(splitted[1]));
// 			System.out
// 					.println(String.format(
// 							"String: %s    after formatting (2): %s", ip,
// 							result.toString()));
// 			return result;
// 		} else if (splitted.length == 1) {
// 			String id = IP.makeID(splitted[0], Control.PORT);
// 			IP result = new IP(id, splitted[0], Control.PORT);
// 			System.out
// 					.println(String.format(
// 							"String: %s    after formatting (1): %s", ip,
// 							result.toString()));
// 			return result;
// 		} else {
// 			System.err.println(String.format("Invalid IP entered: %s", ip));
// 			System.exit(-1);
// 			return null;
// 		}
// 	}
// }


// Path: comm-library/src/node/NodeList.java
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import network.MessageType;
import utility.IP;


	public void succeed(String nodeID, NodeListEntry nle, Timestamp t) {
		succeed(nodeID, nle.ip, nle.port, nle.subnetLabel, t);
	}
	
	public synchronized void succeed(String nodeID, String ip, int port,
			String s, Timestamp t) {
		if (nodeID.equals(this.nodeID)) {
			// Don't add ourselves!
			return;
		}
		// add an entry to the goodNodeTable
		// TODO CHECK TO MAKE SURE THIS ENTRY IS MORE UP-TO-DATE
		Control.println(String.format("NodeList: recording success for node %s:%d",ip,port));
		if (!goodNodeTable.containsKey(nodeID)) {
			if (badNodeTable.containsKey(nodeID)) {
				badNodeTable.remove(nodeID);
				reportDeltas(1, goodNodeTable.size(), 1, 0, -1, 0,
						badNodeTable.size(), 0, 1, 0, MessageType.PING);
			} else {
				reportDeltas(1, goodNodeTable.size(), 0, 1, 0, 0,
						badNodeTable.size(), 0, 1, 0, MessageType.PING);
			}
		}
		goodNodeTable.put(nodeID, new NodeListEntry(ip, port, s, t));
		if (hasSecondTier() && (s.equals(this.subnetID))) {
			subnetNeighbors.add(nodeID);
		}
	}

	public void fail(IP ip, String s, Timestamp t) {