private void HandleAdjacentNodesAfterNodeRemoval(List <ElectricNetworkNode> adjacentNodes)
    {
        // Check if there is only one network in the involved nodes. If there is more than one, something went horribly wrong.
        ElectricNetwork[] differentNetworksInvolved = ElectricNetworkUtil.GetDifferentNetworksOf(adjacentNodes.ToArray());
        if (differentNetworksInvolved.Length > 1)
        {
            Debug.LogError($"ERROR REMOVING NODE: The adjacent nodes of the removed node should all have the same network " +
                           $"(network count = 1), but there are {differentNetworksInvolved.Length} different networks. ");
        }

        // Case 1: There are no adjacent nodes on removal
        if (adjacentNodes == null || adjacentNodes.Count == 0)
        {
            return;
        }

        // Case 2: There is only one adjacent node on removal; no changes to network
        if (adjacentNodes.Count == 1)
        {
            return;
        }

        // Case 3: There are at least two adjacent nodes; what happens with the network is ambiguous --> NetworkResolver
        HandleNetworkResolving(adjacentNodes);

        // Case 4: (Special case) There are at least two adjacent nodes and all are connected with each other on removal.
        // This case is not handled here, because it also gets resolved by the NetworkResolver.
    }
    /*
     * You should not call this method directly. Instead, call HandleAdjacentNodesAfterNodeRemoval()
     */
    private void HandleNetworkResolving(List <ElectricNetworkNode> nodesToBeResolved)
    {
        NetworkResolver networkResolver = new NetworkResolver();

        networkResolver.ResolveNetworks(nodesToBeResolved);
        List <ElectricNetworkSeed> resolvedNetworkSeeds = networkResolver.resolvedNetworkSeeds;

        // If only one ElectricNetworkSeed gets returned, it means that the network doesn't break up. Just one node gets removed.
        if (resolvedNetworkSeeds.Count == 1)
        {
            return;
        }

        // Because all former nodes and edges now are reassigned in resolved network seeds, it is save to wipe all
        // content from the network before removal (unregister all nodes and edges).
        ElectricNetwork networkBeforeRemoval = nodesToBeResolved[0].connectedNetwork;

        ElectricNetworkUtil.RemoveNetworkContent(networkBeforeRemoval);

        // Reassign the biggest networkSeed to the network before the removal
        ElectricNetworkUtil.SortBySize(resolvedNetworkSeeds);
        ElectricNetworkSeed biggestNetworkSeed = resolvedNetworkSeeds[0];

        ElectricNetworkUtil.AddNetworkContent(networkBeforeRemoval, biggestNetworkSeed);
        Debug.Log($"INFO: There are {biggestNetworkSeed.nodes.Count} nodes in the biggest network after removing a node. ");
        resolvedNetworkSeeds.Remove(biggestNetworkSeed);

        // For every other networkSeed: Create a new network and populate it with the contents of the networkSeed
        foreach (ElectricNetworkSeed networkSeed in resolvedNetworkSeeds)
        {
            ElectricNetwork electricNetwork = CreateNewElectricNetwork();
            networkSeed.nodes.ForEach(node => ElectricNetworkUtil.Register(electricNetwork, node));
            networkSeed.edges.ForEach(edge => ElectricNetworkUtil.Register(electricNetwork, edge));
        }
    }
    private void HandleCreationOfASingleNewNetwork(ElectricNetworkNode addedNode, List <ElectricNetworkNode> adjacentNodes)
    {
        // Check if adjacentNodes all have no network;
        // If they do, another method about handling addon to network(s) should be called.
        foreach (ElectricNetworkNode adjacentNode in adjacentNodes)
        {
            if (adjacentNode.connectedNetwork != null)
            {
                Debug.LogError($"ERROR CREATING NODE: Node {addedNode} should be only one with network, " +
                               $"but Node {adjacentNode} already has network {adjacentNode.connectedNetwork}. ");
                return;
            }
        }
        ElectricNetwork network = CreateNewElectricNetwork();

        ElectricNetworkUtil.Register(network, addedNode);
        Debug.Log($"INFO CREATING NODE: Node {addedNode} was created with network {network}. ");

        if (adjacentNodes != null && adjacentNodes.Count > 0)
        {
            foreach (ElectricNetworkNode adjacentNode in adjacentNodes)
            {
                ElectricNetworkUtil.Register(network, adjacentNode);
                Debug.Log($"INFO REGISTERING: Node {adjacentNode} was added to network {network}. ");
            }
        }

        SortElectricNetworks();
    }
    private void HandleAddonToAnExistingNetwork(ElectricNetworkNode addedNode, List <ElectricNetworkNode> adjacentNodes)
    {
        ElectricNetwork network = adjacentNodes[0].connectedNetwork;

        ElectricNetworkUtil.Register(network, addedNode);
        SortElectricNetworks();
        Debug.Log($"INFO: Node {addedNode} was added to network {network}. ");
    }
    /*
     * This method should not be called each Update, rather only on changes.
     */
    public void AddPreviewNode(ElectricNetworkNode previewNode, List <ElectricNetworkNode> interactedNodes)
    {
        foreach (ElectricNetworkNode interactedNode in interactedNodes)
        {
            ElectricNetworkUtil.ConnectPreview(previewNode, interactedNode, previewNetwork);
        }

        CreateCablesForNetwork(previewNetwork);
    }
        /*
         * There are actually two lists with traveresed nodes in this NetworkResolver:
         * 1) traversedNodes represents all nodes that have been passed through the traversal
         * 2) nodesInThisNetwork represents a subset of all traversed nodes, namely only those that are connected with each other (--> network)
         */
        private ElectricNetworkSeed TraverseNodesInQueueAndResolveAsNetwork(Queue <ElectricNetworkNode> nodeQueue)
        {
            List <ElectricNetworkNode> nodesInThisNetwork  = new List <ElectricNetworkNode>();
            List <ElectricNetworkEdge> edgesInThisNetwork  = new List <ElectricNetworkEdge>();
            ElectricNetworkSeed        resolvedNetworkSeed = new ElectricNetworkSeed();

            while (nodeQueue.Count > 0)
            {
                ElectricNetworkNode nodeOnTop = nodeQueue.Peek();

                // Add each connected node to the network (plus the corresponding edge)
                foreach (ElectricNetworkNode connectedNode in nodeOnTop.connectedNodes)
                {
                    // If the resolver already visited this node, continue
                    if (traversedNodes.Contains(connectedNode))
                    {
                        continue;
                    }

                    // Add connected Node to queue
                    nodeQueue.Enqueue(connectedNode);

                    // Add node to traversed nodes (as soon as they are in queue, they count as traversed/visited)
                    traversedNodes.Add(connectedNode);

                    // Get edge between two nodes
                    ElectricNetworkEdge commonEdge = ElectricNetworkUtil.GetCommonEdge(nodeOnTop, connectedNode);
                    if (commonEdge == null)
                    {
                        Debug.LogError($"ERROR RESOLVING NETWORKS: " +
                                       $"There is no common edge between Node 1 {nodeOnTop} and Node 2 {connectedNode}. ");
                    }
                    edgesInThisNetwork.Add(commonEdge);
                }

                // Add traversed node to all 1) visited nodes and 2) nodes for network
                traversedNodes.Add(nodeOnTop);
                nodesInThisNetwork.Add(nodeOnTop);

                // Remove top node from queue
                nodeQueue.Dequeue();
            }

            // Return resolved network
            resolvedNetworkSeed.nodes = nodesInThisNetwork;
            resolvedNetworkSeed.edges = edgesInThisNetwork;
            return(resolvedNetworkSeed);
        }
    public void AddNode(ElectricNetworkNode addedNode, List <ElectricNetworkNode> interactedNodes)
    {
        int numberOfInvolvedNetworksInConnectionAttempt = ElectricNetworkUtil.GetDifferentNetworksOf(interactedNodes.ToArray()).Length;

        // Debug info
        if (GameManager.Instance.isDebugging)
        {
            for (int i = 0; i < interactedNodes.Count(); i++)
            {
                Debug.Log($"INFO NETWORK ADDON: Interacted Node {i}: {interactedNodes[i]}. ");
            }
        }

        // Handle addon to network
        if (numberOfInvolvedNetworksInConnectionAttempt == 0)
        {
            // Interacted Nodes are passed as parameter, because there can be a connection attempt with
            // interacted/adjacent nodes, that have connectedNetwork = null.
            HandleCreationOfASingleNewNetwork(addedNode, interactedNodes);
        }
        else if (numberOfInvolvedNetworksInConnectionAttempt == 1)
        {
            HandleAddonToAnExistingNetwork(addedNode, interactedNodes);
        }
        else if (numberOfInvolvedNetworksInConnectionAttempt > 1)
        {
            HandleAddonToMultipleExistingNetworks(addedNode, interactedNodes);
        }
        else
        {
            Debug.LogError($"ERROR NETWORK ADDON: There is an illegal number of involved networks " +
                           $"({numberOfInvolvedNetworksInConnectionAttempt}) when trying to add a new node. ");
        }

        // Connect nodes with each other and create edges
        foreach (ElectricNetworkNode interactedNode in interactedNodes)
        {
            ElectricNetworkUtil.Connect(addedNode, interactedNode);
        }

        // Create cables between power poles, if they are missing
        CreateAllCables();
    }
    private void HandleAddonToMultipleExistingNetworks(ElectricNetworkNode addedNode, List <ElectricNetworkNode> adjacentNodes)
    {
        ElectricNetwork[] existingNetworks = ElectricNetworkUtil.GetDifferentNetworksOf(adjacentNodes.ToArray());
        existingNetworks = ElectricNetwork.SortBySize(existingNetworks);
        ElectricNetwork biggestNetwork = existingNetworks[0];

        // Integrate smaller networks into the biggest one
        foreach (ElectricNetwork disintegratedNetwork in existingNetworks)
        {
            if (disintegratedNetwork == biggestNetwork)
            {
                continue;
            }
            IntegrateElectricNetworkIntoAnother(biggestNetwork, disintegratedNetwork);
        }

        // Register added node into biggest network all other networks get integrated into
        ElectricNetworkUtil.Register(biggestNetwork, addedNode);

        SortElectricNetworks();
    }
    private void IntegrateElectricNetworkIntoAnother(ElectricNetwork targetNetwork, ElectricNetwork disintegratingNetwork)
    {
        // Create new lists. Otherwise, elements would be removed while iterating over the list.
        List <ElectricNetworkNode> movedNodes = new List <ElectricNetworkNode>(disintegratingNetwork.nodes);
        List <ElectricNetworkEdge> movedEdges = new List <ElectricNetworkEdge>(disintegratingNetwork.edges);

        // Transfer nodes
        foreach (ElectricNetworkNode node in movedNodes)
        {
            ElectricNetworkUtil.Unregister(disintegratingNetwork, node);
            ElectricNetworkUtil.Register(targetNetwork, node);
        }

        // Transfer edges
        foreach (ElectricNetworkEdge edge in movedEdges)
        {
            ElectricNetworkUtil.Unregister(disintegratingNetwork, edge);
            ElectricNetworkUtil.Register(targetNetwork, edge);
        }

        // "Destroy" (aka unlink) network
        DestroyElectricNetwork(disintegratingNetwork);
    }
예제 #10
0
    public void DestroyNode(ElectricNetworkNode node)
    {
        ElectricNetwork networkOfDestroyedNode = node.connectedNetwork;

        // Could throw error, when "node.connectedNodes = null" and then "adjacentNodes[0]"?
        List <ElectricNetworkNode> adjacentNodes = new List <ElectricNetworkNode>(node.connectedNodes);

        // Unregister from network
        ElectricNetworkUtil.Unregister(node.connectedNetwork, node);

        // If no nodes are connected, destroy the network (the destroyed node was the last one in the network)
        if (node.connectedNodes.Count() == 0 && node.connectedEdges.Count() == 0)
        {
            if (ElectricNetworkUtil.CheckIfNetworkIsEmpty(networkOfDestroyedNode))
            {
                DestroyElectricNetwork(networkOfDestroyedNode);
            }
            else
            {
                Debug.LogError($"ERROR DELETING NODE: Network {networkOfDestroyedNode} is not empty, but it should be. " +
                               $"On Removal, there were no adjacent nodes, so Node {node} must be the only member. ");
            }
            return;
        }

        // Destroy cables and disconnect edges
        List <ElectricNetworkEdge> connectedEdges = new List <ElectricNetworkEdge>(node.connectedEdges);

        foreach (ElectricNetworkEdge edge in connectedEdges)
        {
            Destroy(edge.cable.gameObject);
            ElectricNetworkUtil.Disconnect(edge);
        }

        // Handle adjacent nodes
        HandleAdjacentNodesAfterNodeRemoval(adjacentNodes);
    }