MapGraph.java

package io.github.neonteam10.graphs;

import io.github.neonteam10.map.Building;

import java.util.*;

/**
 * This graph is purely for literal connections between map nodes (A building can only be connected to roads in this graph)
 */
public class MapGraph {
    final float BUILDING_GAIN_VALUE = 1.0f;
    List<MapNode> nodes;
    BuildingGraph buildingGraph;
    public MapGraph() {
        nodes = new ArrayList<>();
        buildingGraph = new BuildingGraph();
    }

    public void addBuilding(Building building) {
        MapNode newNode = new MapNode(building);
        nodes.add(newNode);
        addAllNodeNeighbours(newNode);
        //System.out.println(newNode.getX() + " " + newNode.getY() + ": " + newNode.getNeighbours());
        if (!building.getRoad()) {
            BuildingNode buildingNode = new BuildingNode(building);
            buildingGraph.addNode(buildingNode);
            newNode.addBuildingNode(buildingNode);
            recalculateBuildingGraphConnections();
        }
    }

    public void addAllNodeNeighbours(MapNode node) {
        for (MapNode n : nodes) {
            if (connected(node, n)) {
                //System.out.println(node + " connected to " + n);
                node.addNeighbour(n);
                n.addNeighbour(node);

            }
        }
    }

    /**
     * Finds out whether two buildings, including roads are connected.
     * @param node1 The node to find if node 2 is connected to
     * @param node2 The node to find if connected to node 1
     * @return A boolean representing whether the two nodes are connected.
     */
    private boolean connected(MapNode node1, MapNode node2) {
        if (node1 == node2) {
            return false;
        }
        if (!(node1.isRoad() || node2.isRoad())) {
            return false;
        }
        else if (node1.isRoad() && node2.isRoad()) {
            int horizontalDiff = Math.abs(node1.getX() - node2.getX());
            int verticalDiff = Math.abs(node1.getY() - node2.getY());
            return (horizontalDiff <= 1 && verticalDiff == 0) || (verticalDiff <= 1 && horizontalDiff == 0);
        }
        else if (node1.isRoad()) {
            return node2.getY() - 1 == node1.getY() && node2.getX() <= node1.getX() && node2.getX() + node2.getWidth() >= node1.getX();
        }
        else {
            return node1.getY() - 1 == node2.getY() && node1.getX() <= node2.getX() && node1.getX() + node1.getWidth() >= node2.getX();
        }
    }

    public void recalculateBuildingGraphConnections() {
        for (MapNode startNode : nodes) {
            Map<MapNode, Integer> nodeConnections = new HashMap<>();
            for (MapNode node : nodes) {
                if (node == startNode) {
                    nodeConnections.put(node, 0);
                }
                else {
                    nodeConnections.put(node, Integer.MAX_VALUE);
                }
            }
            Set<MapNode> unvisited = new HashSet<>(nodes);
            while (!(unvisited.isEmpty())) {
                MapNode currentNode = null;
                int shortestDistance = Integer.MAX_VALUE;
                for (MapNode node2 : unvisited) {
                    if (currentNode == null) {
                        shortestDistance = nodeConnections.get(node2);
                        currentNode = node2;
                    }
                    if (nodeConnections.get(node2) < shortestDistance) {
                        shortestDistance = nodeConnections.get(node2);
                        currentNode = node2;
                    }
                }
                unvisited.remove(currentNode);
                for (MapNode node2 : currentNode.getNeighbours()) {
                    if (unvisited.contains(node2)) {
                        if (nodeConnections.get(currentNode) + 1 < nodeConnections.get(node2)) {
                            nodeConnections.put(node2, nodeConnections.get(currentNode) + 1);
                            if (startNode.buildingNode != null && node2.buildingNode != null) {
                                startNode.buildingNode.connections.put(node2.buildingNode, nodeConnections.get(currentNode));
                                node2.buildingNode.connections.put(startNode.buildingNode, nodeConnections.get(currentNode));
                            }
                        }
                    }

                }
            }
        }


    }

    public float getBonus(String buildingType) {
        if (buildingType == "Canteen") {
            return buildingGraph.canteenBonus();
        } else if (buildingType == "Accommodation") {
            return buildingGraph.accommodationBonus();
        } else {
            return 0;
        }
    }


}