/// <summary> /// Destroys the traffic light and removes it /// </summary> /// <param name="nodeId"></param> /// <param name="destroyGroup"></param> public void RemoveNodeFromSimulation(ushort nodeId, bool destroyGroup, bool removeTrafficLight) { if (!HasSimulation(nodeId)) { return; } TrafficLightSimulation sim = TrafficLightSimulations[nodeId]; TrafficLightManager tlm = TrafficLightManager.Instance; if (sim.TimedLight != null) { // remove/destroy all timed traffic lights in group List <ushort> oldNodeGroup = new List <ushort>(sim.TimedLight.NodeGroup); foreach (var timedNodeId in oldNodeGroup) { var otherNodeSim = GetNodeSimulation(timedNodeId); if (otherNodeSim == null) { continue; } if (destroyGroup || timedNodeId == nodeId) { //Log._Debug($"Slave: Removing simulation @ node {timedNodeId}"); otherNodeSim.DestroyTimedTrafficLight(); otherNodeSim.DestroyManualTrafficLight(); otherNodeSim.NodeGeoUnsubscriber?.Dispose(); RemoveNodeFromSimulation(timedNodeId); if (removeTrafficLight) { tlm.RemoveTrafficLight(timedNodeId); } } else { otherNodeSim.TimedLight.RemoveNodeFromGroup(nodeId); } } } //Flags.setNodeTrafficLight(nodeId, false); //sim.DestroyTimedTrafficLight(); sim.DestroyManualTrafficLight(); sim.NodeGeoUnsubscriber?.Dispose(); RemoveNodeFromSimulation(nodeId); if (removeTrafficLight) { tlm.RemoveTrafficLight(nodeId); } }
static TrafficLightManager() { Instance = new TrafficLightManager(); }
public bool LoadData(List <Configuration.TimedTrafficLights> data) { bool success = true; Log.Info($"Loading {data.Count} timed traffic lights (new method)"); TrafficLightManager tlm = TrafficLightManager.Instance; HashSet <ushort> nodesWithSimulation = new HashSet <ushort>(); foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { nodesWithSimulation.Add(cnfTimedLights.nodeId); } Dictionary <ushort, ushort> masterNodeIdBySlaveNodeId = new Dictionary <ushort, ushort>(); Dictionary <ushort, List <ushort> > nodeGroupByMasterNodeId = new Dictionary <ushort, List <ushort> >(); foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { try { // TODO most of this should not be necessary at all if the classes around TimedTrafficLights class were properly designed List <ushort> currentNodeGroup = cnfTimedLights.nodeGroup.Distinct().ToList(); // enforce uniqueness of node ids if (!currentNodeGroup.Contains(cnfTimedLights.nodeId)) { currentNodeGroup.Add(cnfTimedLights.nodeId); } // remove any nodes that are not configured to have a simulation currentNodeGroup = new List <ushort>(currentNodeGroup.Intersect(nodesWithSimulation)); // remove invalid nodes from the group; find if any of the nodes in the group is already a master node ushort masterNodeId = 0; int foundMasterNodes = 0; for (int i = 0; i < currentNodeGroup.Count;) { ushort nodeId = currentNodeGroup[i]; if (!NetUtil.IsNodeValid(currentNodeGroup[i])) { currentNodeGroup.RemoveAt(i); continue; } else if (nodeGroupByMasterNodeId.ContainsKey(nodeId)) { // this is a known master node if (foundMasterNodes > 0) { // we already found another master node. ignore this node. currentNodeGroup.RemoveAt(i); continue; } // we found the first master node masterNodeId = nodeId; ++foundMasterNodes; } ++i; } if (masterNodeId == 0) { // no master node defined yet, set the first node as a master node masterNodeId = currentNodeGroup[0]; } // ensure the master node is the first node in the list (TimedTrafficLights depends on this at the moment...) currentNodeGroup.Remove(masterNodeId); currentNodeGroup.Insert(0, masterNodeId); // update the saved node group and master-slave info nodeGroupByMasterNodeId[masterNodeId] = currentNodeGroup; foreach (ushort nodeId in currentNodeGroup) { masterNodeIdBySlaveNodeId[nodeId] = masterNodeId; } } catch (Exception e) { Log.Warning($"Error building timed traffic light group for TimedNode {cnfTimedLights.nodeId} (NodeGroup: {string.Join(", ", cnfTimedLights.nodeGroup.Select(x => x.ToString()).ToArray())}): " + e.ToString()); success = false; } } foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { try { if (!masterNodeIdBySlaveNodeId.ContainsKey(cnfTimedLights.nodeId)) { continue; } ushort masterNodeId = masterNodeIdBySlaveNodeId[cnfTimedLights.nodeId]; List <ushort> nodeGroup = nodeGroupByMasterNodeId[masterNodeId]; Log._Debug($"Adding timed light at node {cnfTimedLights.nodeId}. NodeGroup: {string.Join(", ", nodeGroup.Select(x => x.ToString()).ToArray())}"); TrafficLightSimulation sim = AddNodeToSimulation(cnfTimedLights.nodeId); sim.SetupTimedTrafficLight(nodeGroup); var timedNode = sim.TimedLight; int j = 0; foreach (Configuration.TimedTrafficLightsStep cnfTimedStep in cnfTimedLights.timedSteps) { Log._Debug($"Loading timed step {j} at node {cnfTimedLights.nodeId}"); TimedTrafficLightsStep step = timedNode.AddStep(cnfTimedStep.minTime, cnfTimedStep.maxTime, cnfTimedStep.waitFlowBalance); foreach (KeyValuePair <ushort, Configuration.CustomSegmentLights> e in cnfTimedStep.segmentLights) { if (!NetUtil.IsSegmentValid(e.Key)) { continue; } Log._Debug($"Loading timed step {j}, segment {e.Key} at node {cnfTimedLights.nodeId}"); CustomSegmentLights lights = null; if (!step.segmentLights.TryGetValue(e.Key, out lights)) { Log._Debug($"No segment lights found at timed step {j} for segment {e.Key}, node {cnfTimedLights.nodeId}"); continue; } Configuration.CustomSegmentLights cnfLights = e.Value; Log._Debug($"Loading pedestrian light @ seg. {e.Key}, step {j}: {cnfLights.pedestrianLightState} {cnfLights.manualPedestrianMode}"); lights.ManualPedestrianMode = cnfLights.manualPedestrianMode; lights.PedestrianLightState = cnfLights.pedestrianLightState; foreach (KeyValuePair <ExtVehicleType, Configuration.CustomSegmentLight> e2 in cnfLights.customLights) { Log._Debug($"Loading timed step {j}, segment {e.Key}, vehicleType {e2.Key} at node {cnfTimedLights.nodeId}"); CustomSegmentLight light = null; if (!lights.CustomLights.TryGetValue(e2.Key, out light)) { Log._Debug($"No segment light found for timed step {j}, segment {e.Key}, vehicleType {e2.Key} at node {cnfTimedLights.nodeId}"); continue; } Configuration.CustomSegmentLight cnfLight = e2.Value; light.currentMode = (CustomSegmentLight.Mode)cnfLight.currentMode; light.SetStates(cnfLight.mainLight, cnfLight.leftLight, cnfLight.rightLight, false); } } ++j; } } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading data from TimedNode (new method): " + e.ToString()); success = false; } } foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { try { TrafficLightSimulation sim = GetNodeSimulation(cnfTimedLights.nodeId); if (sim == null || sim.TimedLight == null) { continue; } var timedNode = sim.TimedLight; timedNode.housekeeping(); if (cnfTimedLights.started) { timedNode.Start(); } } catch (Exception e) { Log.Warning($"Error starting timed light @ {cnfTimedLights.nodeId}: " + e.ToString()); success = false; } } return(success); }