//import java.lang.Comparable;

/*

  Data type for representing edges in directed graph.
  Each edge represented by pair of nodes (given by integer indices),
  a numeric weight, and a "tag", which can be null or an arbitrary string.

*/

/*
  class BadGraphException extends Exception {}
*/
class GraphEdge implements Comparable<GraphEdge> {
    public int fromNode;
    public int toNode;
    public double weight;
    public String tag;

    GraphEdge(int from, int to, double wt) {
	fromNode = from;
	toNode = to;
	weight = wt;
	tag = "";
    }

    GraphEdge(String s)
	throws BadGraphException
    {
	String tokens[] = s.split("\\s+");
	if (tokens.length < 3) {
	    throw new BadGraphException();
	}
	try {
	    fromNode = Integer.parseInt(tokens[0]);
	    toNode = Integer.parseInt(tokens[1]);
	    weight = Double.parseDouble(tokens[2]);
	} catch (NumberFormatException e) {
	    throw new BadGraphException();
	}
	if (tokens.length == 4)
	    tag = tokens[3];
    }

    public int compareTo(GraphEdge other) {
	int val = new Integer(this.fromNode).compareTo(other.fromNode);
	if (val != 0)
	    return val;
	val = new Integer(this.toNode).compareTo(other.toNode);
	if (val != 0)
	    return val;
	val = new Double(this.weight).compareTo(other.weight);
	if (val != 0)
	    return val;
	return this.tag.compareTo(other.tag);
    }

    void assignTag(String t) {
	tag = t;
    }

    void clearTag() {
	assignTag(null);
    }

    public String toString() {
	String s = fromNode + " " + toNode + " " + weight;
	if (tag != null) {
	    s += " " + tag;
	}
	return s;
    }

    /* Create new edge by combining two edges and summing their weights */
    /* Null returned when not a consecutive pair */
    public GraphEdge contractSum(GraphEdge e)
    {
	if (this.toNode != e.fromNode) {
	    return null;
	}
	return new GraphEdge(this.fromNode, e.toNode,
			     this.weight + e.weight);
	
    }

    /* Create new edge by combining two edges and multiplying their weights */
    /* Null returned when not a consecutive pair */
    public GraphEdge contractProd(GraphEdge e)
    {
	if (this.toNode != e.fromNode) {
	    return null;
	}
	return new GraphEdge(this.fromNode, e.toNode,
			     this.weight * e.weight);
	
    }


}