// Path: src/MapGenerator/Graph/Edge.java
// public class Edge<T> implements Comparable<Edge<T>> {
//     private Node<T> from;
//     private Node<T> to;
//     private int weight;
// 
// 
//     /**
//      * @param from start node
//      * @param to end node
//      * @param weight weight of the edge
//      */
//     public Edge(Node<T> from, Node<T> to, int weight) {
//         this.from = from;
//         this.to = to;
//         this.weight = weight;
//     }
// 
//     /**
//      * @return return edge start node
//      */
//     public Node<T> getFrom() {
//         return from;
//     }
// 
//     /**
//      * @param from sets edge starts node
//      */
//     public void setFrom(Node<T> from) {
//         this.from = from;
//     }
// 
//     /**
//      * @return edge end node
//      */
//     public Node<T> getTo() {
//         return to;
//     }
// 
//     /**
//      * @param to edge end node
//      */
//     public void setTo(Node<T> to) {
//         this.to = to;
//     }
// 
//     /**
//      * @return weight on the edge
//      */
//     public int getWeight() {
//         return weight;
//     }
// 
//     /**
//      * @param weight changes edge's weight
//      */
//     public void setWeight(int weight) {
//         this.weight = weight;
//     }
// 
//     /**
//      * @param other edge to compare with
//      * @return -1 this is less than other; 0 this equals to other; 1 this is greater than other
//      */
//     @Override
//     public int compareTo(Edge<T> other) {
//         if(this.getWeight()<other.getWeight())
//             return -1;
//         else if (this.getWeight() == other.getWeight())
//             return 0;
//         else
//             return 1;
//     }
// 
//     /**
//      * @return String representation of the edge node a to node b
//      */
//     @Override
//     public String toString() {
//         StringBuilder outp = new StringBuilder();
//         outp.append(from.toString());
//         outp.append("->");
//         outp.append(to.toString());
//         outp.append("\n");
//         return outp.toString();
//     }
// }
// 
// Path: src/MapGenerator/Graph/Graph.java
// public class Graph<T> {
// 
//     protected ArrayList<Node<T>> nodes;
//     protected ArrayList<Edge<T>> edges;
// 
//     /**
//      * Creates empty graph
//      */
//     public Graph(){
//         nodes = new ArrayList<>();
//         edges= new ArrayList<>();
//     }
// 
//     /**
//      * Creates edge from a to b
//      * @param a from this node
//      * @param b to this node
//      * @param weight weight on the edge
//      */
//     public void addEdge(Node<T> a, Node<T> b, int weight){
//         // check if this kind of edge doesn't exists already- no multi-edges
//         if(a.getEdges().stream().filter(aa -> aa.getFrom() == b || aa.getTo() == b ).count() == 0){
//             Edge<T> edge=new Edge<>(a,b,weight);
//             edges.add(edge);
//             a.addEdge(edge);
//             b.addEdge(edge);
//         }
//     }
// 
//     /**
//      * Creates new node.
//      * @param data data to be stored in the graph node
//      */
//     public void addNode(T data){
//         // check if this node is not already pressent in the graph
//         if(getNode(data) == null){
//             Node<T> node = new Node<>(nodes.size()-1,data);
//             nodes.add(node);
//         }
// 
//     }
// 
//     /**
//      * Finds node which contains data
//      * @param data reference to data object
//      * @return node which contains data block
//      */
//     public Node<T> getNode(T data){
//         Optional<Node<T>> out = nodes.stream().filter(c->c.getData() == data).findFirst();
//         if (out.isPresent()) return out.get();
//         else return null;
//     }
// 
//     /**
//      * @return all edges in the Graph
//      */
//     public ArrayList<Edge<T>> getEdges(){
//         return edges;
//     }
// 
//     /**
//      * @param new_edges redefine edges in the Graph as new_edges
//      */
//     public void addAllEdges(ArrayList<Edge<T>> new_edges){
//         edges = new_edges;
//     }
// 
//     /**
//      * @return all nodes in the graph
//      */
//     public ArrayList<Node<T>> getNodes(){
//         return nodes;
//     }
// 
//     /**
//      * @return Graph representation of edges node a to node b
//      */
//     @Override
//     public String toString() {
//         StringBuilder outp = new StringBuilder();
//         edges.stream().forEach(c->c.toString());
//         return outp.toString();
//     }
// }


import MapGenerator.Graph.Edge;
import MapGenerator.Graph.Graph;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
package MapGenerator.KruskalsAlg;




/**
 * Creates specific graph for Kruskal's algorithm. Calculate minimal spanning tree
 * @author Lukas Jelinek
 * @param <T> data type of node
 */
public class KruskalsGraph<T> extends Graph<T>{
    private LinkedList<DisJointSet<T>> sets;
    int setsCounter;

    /**
     *  Creates empty  graph
     */
    public KruskalsGraph() {
        super();
        sets = new LinkedList<>();
        setsCounter=0;

    }

    /**
     * @param data data to be stored in the graph node
     */
    @Override
    public void addNode(T data) {
        // check if this node is not already pressent in the graph
        if(getNode(data) == null) {
            DisJointSet<T> disJointSet = new DisJointSet<>(setsCounter++);
            KruskalsNode<T> node = new KruskalsNode<>(disJointSet.getID(), data);
            nodes.add(node);
            disJointSet.addNode(node);
            sets.add(disJointSet);
        }
    }

    /**
     * Calculate minimal spanning tree
     * @return edges in minimal spanning tree
     */
// Path: src/MapGenerator/Graph/Edge.java
// public class Edge<T> implements Comparable<Edge<T>> {
//     private Node<T> from;
//     private Node<T> to;
//     private int weight;
// 
// 
//     /**
//      * @param from start node
//      * @param to end node
//      * @param weight weight of the edge
//      */
//     public Edge(Node<T> from, Node<T> to, int weight) {
//         this.from = from;
//         this.to = to;
//         this.weight = weight;
//     }
// 
//     /**
//      * @return return edge start node
//      */
//     public Node<T> getFrom() {
//         return from;
//     }
// 
//     /**
//      * @param from sets edge starts node
//      */
//     public void setFrom(Node<T> from) {
//         this.from = from;
//     }
// 
//     /**
//      * @return edge end node
//      */
//     public Node<T> getTo() {
//         return to;
//     }
// 
//     /**
//      * @param to edge end node
//      */
//     public void setTo(Node<T> to) {
//         this.to = to;
//     }
// 
//     /**
//      * @return weight on the edge
//      */
//     public int getWeight() {
//         return weight;
//     }
// 
//     /**
//      * @param weight changes edge's weight
//      */
//     public void setWeight(int weight) {
//         this.weight = weight;
//     }
// 
//     /**
//      * @param other edge to compare with
//      * @return -1 this is less than other; 0 this equals to other; 1 this is greater than other
//      */
//     @Override
//     public int compareTo(Edge<T> other) {
//         if(this.getWeight()<other.getWeight())
//             return -1;
//         else if (this.getWeight() == other.getWeight())
//             return 0;
//         else
//             return 1;
//     }
// 
//     /**
//      * @return String representation of the edge node a to node b
//      */
//     @Override
//     public String toString() {
//         StringBuilder outp = new StringBuilder();
//         outp.append(from.toString());
//         outp.append("->");
//         outp.append(to.toString());
//         outp.append("\n");
//         return outp.toString();
//     }
// }
// 
// Path: src/MapGenerator/Graph/Graph.java
// public class Graph<T> {
// 
//     protected ArrayList<Node<T>> nodes;
//     protected ArrayList<Edge<T>> edges;
// 
//     /**
//      * Creates empty graph
//      */
//     public Graph(){
//         nodes = new ArrayList<>();
//         edges= new ArrayList<>();
//     }
// 
//     /**
//      * Creates edge from a to b
//      * @param a from this node
//      * @param b to this node
//      * @param weight weight on the edge
//      */
//     public void addEdge(Node<T> a, Node<T> b, int weight){
//         // check if this kind of edge doesn't exists already- no multi-edges
//         if(a.getEdges().stream().filter(aa -> aa.getFrom() == b || aa.getTo() == b ).count() == 0){
//             Edge<T> edge=new Edge<>(a,b,weight);
//             edges.add(edge);
//             a.addEdge(edge);
//             b.addEdge(edge);
//         }
//     }
// 
//     /**
//      * Creates new node.
//      * @param data data to be stored in the graph node
//      */
//     public void addNode(T data){
//         // check if this node is not already pressent in the graph
//         if(getNode(data) == null){
//             Node<T> node = new Node<>(nodes.size()-1,data);
//             nodes.add(node);
//         }
// 
//     }
// 
//     /**
//      * Finds node which contains data
//      * @param data reference to data object
//      * @return node which contains data block
//      */
//     public Node<T> getNode(T data){
//         Optional<Node<T>> out = nodes.stream().filter(c->c.getData() == data).findFirst();
//         if (out.isPresent()) return out.get();
//         else return null;
//     }
// 
//     /**
//      * @return all edges in the Graph
//      */
//     public ArrayList<Edge<T>> getEdges(){
//         return edges;
//     }
// 
//     /**
//      * @param new_edges redefine edges in the Graph as new_edges
//      */
//     public void addAllEdges(ArrayList<Edge<T>> new_edges){
//         edges = new_edges;
//     }
// 
//     /**
//      * @return all nodes in the graph
//      */
//     public ArrayList<Node<T>> getNodes(){
//         return nodes;
//     }
// 
//     /**
//      * @return Graph representation of edges node a to node b
//      */
//     @Override
//     public String toString() {
//         StringBuilder outp = new StringBuilder();
//         edges.stream().forEach(c->c.toString());
//         return outp.toString();
//     }
// }


// Path: src/MapGenerator/KruskalsAlg/KruskalsGraph.java
import MapGenerator.Graph.Edge;
import MapGenerator.Graph.Graph;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

package MapGenerator.KruskalsAlg;




/**
 * Creates specific graph for Kruskal's algorithm. Calculate minimal spanning tree
 * @author Lukas Jelinek
 * @param <T> data type of node
 */
public class KruskalsGraph<T> extends Graph<T>{
    private LinkedList<DisJointSet<T>> sets;
    int setsCounter;

    /**
     *  Creates empty  graph
     */
    public KruskalsGraph() {
        super();
        sets = new LinkedList<>();
        setsCounter=0;

    }

    /**
     * @param data data to be stored in the graph node
     */
    @Override
    public void addNode(T data) {
        // check if this node is not already pressent in the graph
        if(getNode(data) == null) {
            DisJointSet<T> disJointSet = new DisJointSet<>(setsCounter++);
            KruskalsNode<T> node = new KruskalsNode<>(disJointSet.getID(), data);
            nodes.add(node);
            disJointSet.addNode(node);
            sets.add(disJointSet);
        }
    }

    /**
     * Calculate minimal spanning tree
     * @return edges in minimal spanning tree
     */
    public List<Edge<T>> calcSpanningTree() {