public static void AddPrioritySegment(ushort nodeId, int segmentId, PrioritySegment.PriorityType type)
        {
            if (PrioritySegments.ContainsKey(segmentId))
            {
                var prioritySegment = PrioritySegments[segmentId];

                prioritySegment.Node2 = nodeId;
                prioritySegment.Instance2 = new PrioritySegment(nodeId, segmentId, type);
            }
            else
            {
                PrioritySegments.Add(segmentId, new TrafficSegment());
                PrioritySegments[segmentId].Segment = segmentId;
                PrioritySegments[segmentId].Node1 = nodeId;
                PrioritySegments[segmentId].Instance1 = new PrioritySegment(nodeId, segmentId, type);
            }
        }
		public static void AddPrioritySegment(ushort nodeId, ushort segmentId, PrioritySegment.PriorityType type) {
			if (nodeId <= 0 || segmentId <= 0)
				return;

			Log.Message("adding PrioritySegment @ node " + nodeId + ", seg. " + segmentId + ", type " + type);

			var prioritySegment = PrioritySegments[segmentId];
			if (prioritySegment != null) { // do not replace with IsPrioritySegment!
				prioritySegment.Segment = segmentId;

				Log.Message("Priority segment already exists. Node1=" + prioritySegment.Node1 + " Node2=" + prioritySegment.Node2);

				if (prioritySegment.Node1 == nodeId || prioritySegment.Node1 == 0) {
					Log.Message("Updating Node1");
					prioritySegment.Node1 = nodeId;
					PrioritySegments[segmentId].Instance1 = new PrioritySegment(nodeId, segmentId, type);
					return;
				}

				if (prioritySegment.Node2 != 0) {
					// overwrite Node2
					Log.Warning("Overwriting priority segment for node " + nodeId + ", seg. " + segmentId + ", type " + type);
					prioritySegment.Node2 = nodeId;
					prioritySegment.Instance2 = new PrioritySegment(nodeId, segmentId, type);
					rebuildPriorityNodes();
				} else {
					// add Node2
					Log.Message("Adding as Node2");
					prioritySegment.Node2 = nodeId;
					prioritySegment.Instance2 = new PrioritySegment(nodeId, segmentId, type);
				}
			} else {
				// add Node1
				Log.Message("Adding as Node1");
				prioritySegment = new TrafficSegment();
				prioritySegment.Segment = segmentId;
				prioritySegment.Node1 = nodeId;
				prioritySegment.Instance1 = new PrioritySegment(nodeId, segmentId, type);
				PrioritySegments[segmentId] = prioritySegment;
			}
			priorityNodes.Add(nodeId);
		}
        private static bool isValidPriorityNode(ushort nodeId, out NodeValidityState nodeState)
        {
            nodeState = NodeValidityState.Valid;

            if (nodeId <= 0)
            {
                nodeState = NodeValidityState.Invalid;
                return(false);
            }

            var node = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId];

            if (node.m_flags == NetNode.Flags.None)
            {
                nodeState = NodeValidityState.Unused;
                return(false);                // node is unused
            }

            var nodeSim = GetNodeSimulation(nodeId);

            if (nodeSim != null)
            {
                if ((node.m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None)
                {
                    // traffic light simulation is active but node does not have a traffic light
                    nodeState = NodeValidityState.SimWithoutLight;
                    return(false);
                }
                else
                {
                    // check if all timed step segments are valid
                    if (nodeSim.FlagTimedTrafficLights && nodeSim.TimedTrafficLightsActive)
                    {
                        TrafficLightsTimed timedLight = TrafficLightsTimed.GetTimedLight(nodeId);
                        if (timedLight == null || timedLight.Steps.Count <= 0)
                        {
                            Log.Warning("Housekeeping: Timed light is null or no steps!");
                            RemoveNodeFromSimulation(nodeId);
                            return(false);
                        }

                        /*foreach (var segmentId in timedLight.Steps[0].segmentIds) {
                         *      if (! IsPrioritySegment(nodeId, segmentId)) {
                         *              Log.Warning("Housekeeping: Timed light - Priority segment has gone away!");
                         *              RemoveNodeFromSimulation(nodeId);
                         *              return false;
                         *      }
                         * }*/
                    }
                    return(true);
                }
            }
            else
            {
                bool ok = false;
                for (var s = 0; s < 8; s++)
                {
                    var segmentId = node.GetSegment(s);
                    if (segmentId <= 0)
                    {
                        continue;
                    }
                    NetSegment segment = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId];
                    if (segment.m_startNode != nodeId && segment.m_endNode != nodeId)
                    {
                        continue;
                    }

                    PrioritySegment prioritySegment = GetPrioritySegment(nodeId, segmentId);
                    if (prioritySegment == null)
                    {
                        continue;
                    }

                    // if node is a traffic light, it must not have priority signs
                    if ((node.m_flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None)
                    {
                        prioritySegment.Type = PrioritySegment.PriorityType.None;
                    }

                    // if a priority sign is set, everything is ok
                    if (prioritySegment.Type != PrioritySegment.PriorityType.None)
                    {
                        ok = true;
                        break;
                    }
                }

                if (!ok)
                {
                    nodeState = NodeValidityState.NoValidSegments;
                }
                return(ok);
            }
        }
예제 #4
0
        public bool StepDone()
        {
            if (stepDone)
            {
                return(true);
            }

            if (startFrame + maxTime <= getCurrentFrame())
            {
                // maximum time reached. switch!
#if DEBUG
                //Log.Message("step finished @ " + nodeId);
#endif
                stepDone           = true;
                endTransitionStart = (int)getCurrentFrame();
                return(stepDone);
            }

            if (startFrame + minTime <= getCurrentFrame())
            {
                if (masterNodeId != null && TrafficLightsTimed.IsTimedLight((ushort)masterNodeId))
                {
                    TrafficLightsTimed masterTimedNode = TrafficLightsTimed.GetTimedLight((ushort)masterNodeId);
                    bool done = masterTimedNode.Steps[masterTimedNode.CurrentStep].StepDone();
#if DEBUG
                    //Log.Message("step finished (1) @ " + nodeId);
#endif
                    stepDone = done;
                    if (stepDone)
                    {
                        endTransitionStart = (int)getCurrentFrame();
                    }
                    return(stepDone);
                }
                else
                {
                    int   numFlows    = 0;
                    int   numWaits    = 0;
                    float curMeanFlow = 0;
                    float curMeanWait = 0;

                    // we are the master node. calculate traffic data
                    foreach (ushort timedNodeId in groupNodeIds)
                    {
                        if (!TrafficLightsTimed.IsTimedLight(timedNodeId))
                        {
                            continue;
                        }
                        TrafficLightsTimed slaveTimedNode = TrafficLightsTimed.GetTimedLight(timedNodeId);
                        TimedTrafficStep   slaveStep      = slaveTimedNode.Steps[timedNode.CurrentStep];

                        //List<int> segmentIdsToDelete = new List<int>();

                        // minimum time reached. check traffic!
                        foreach (KeyValuePair <ushort, ManualSegmentLight> e in slaveStep.segmentLightStates)
                        {
                            var   fromSegmentId = e.Key;
                            var   segLightState = e.Value;
                            float segmentWeight = Singleton <NetManager> .instance.m_segments.m_buffer[fromSegmentId].m_averageLength / maxSegmentLength;

                            // one of the traffic lights at this segment is green: count minimum traffic flowing through
                            PrioritySegment prioSeg = TrafficPriority.GetPrioritySegment(timedNodeId, fromSegmentId);
                            if (prioSeg == null)
                            {
                                //Log.Warning("stepDone(): prioSeg is null");
                                //segmentIdsToDelete.Add(fromSegmentId);
                                continue;                                 // skip invalid segment
                            }
                            foreach (KeyValuePair <ushort, int> f in prioSeg.numCarsGoingToSegmentId)
                            {
                                var toSegmentId = f.Key;
                                var numCars     = f.Value;

                                TrafficPriority.Direction dir = TrafficPriority.GetDirection(fromSegmentId, toSegmentId, timedNodeId);
                                bool addToFlow = false;
                                switch (dir)
                                {
                                case TrafficPriority.Direction.Left:
                                    if (segLightState.isLeftGreen())
                                    {
                                        addToFlow = true;
                                    }
                                    break;

                                case TrafficPriority.Direction.Right:
                                    if (segLightState.isRightGreen())
                                    {
                                        addToFlow = true;
                                    }
                                    break;

                                case TrafficPriority.Direction.Forward:
                                default:
                                    if (segLightState.isForwardGreen())
                                    {
                                        addToFlow = true;
                                    }
                                    break;
                                }

                                if (addToFlow)
                                {
                                    ++numFlows;
                                    curMeanFlow += (float)numCars * segmentWeight;
                                }
                                else
                                {
                                    ++numWaits;
                                    curMeanWait += (float)numCars * segmentWeight;
                                }
                            }
                        }

                        // delete invalid segments from step

                        /*foreach (int segmentId in segmentIdsToDelete) {
                         *      slaveStep.segmentLightStates.Remove(segmentId);
                         * }*/

                        if (slaveStep.segmentLightStates.Count <= 0)
                        {
                            invalid = true;
                            return(true);
                        }
                    }

                    if (numFlows > 0)
                    {
                        curMeanFlow /= (float)numFlows;
                    }
                    if (numWaits > 0)
                    {
                        curMeanWait /= (float)numWaits;
                    }

                    float decisionValue = 0.8f;                     // a value smaller than 1 rewards steady traffic currents
                    curMeanFlow /= decisionValue;

                    if (Single.IsNaN(minFlow))
                    {
                        minFlow = curMeanFlow;
                    }
                    else
                    {
                        minFlow = Math.Min(curMeanFlow, minFlow);
                    }

                    if (Single.IsNaN(maxWait))
                    {
                        maxWait = curMeanWait;
                    }
                    else
                    {
                        maxWait = Math.Max(curMeanWait, maxWait);
                    }

                    // if more cars are waiting than flowing, we change the step
                    bool done = maxWait > 0 && minFlow < maxWait;
#if DEBUG
                    //Log.Message("step finished (2) @ " + nodeId);
#endif
                    stepDone = done;
                    if (stepDone)
                    {
                        endTransitionStart = (int)getCurrentFrame();
                    }
                    return(stepDone);
                }
            }
            return(false);
        }