Ejemplo n.º 1
0
        /// <summary>
        /// Calculates for each segment the number of cars going to this segment.
        /// We use integer arithmetic for better performance.
        /// </summary>
        public Dictionary <ushort, uint> GetVehicleMetricGoingToSegment(bool includeStopped = true, byte?laneIndex = null, bool debug = false)
        {
#if TRACE
            Singleton <CodeProfiler> .instance.Start("SegmentEnd.GetVehicleMetricGoingToSegment");
#endif
            VehicleManager      vehicleManager  = Singleton <VehicleManager> .instance;
            NetManager          netManager      = Singleton <NetManager> .instance;
            VehicleStateManager vehStateManager = VehicleStateManager.Instance();

            Dictionary <ushort, uint> ret = includeStopped ? numVehiclesGoingToSegmentId : numVehiclesFlowingToSegmentId;

            for (var s = 0; s < 8; s++)
            {
                ushort segmentId = netManager.m_nodes.m_buffer[NodeId].GetSegment(s);

                if (segmentId == 0 || segmentId == SegmentId)
                {
                    continue;
                }

                if (!ret.ContainsKey(segmentId))
                {
                    continue;
                }

                ret[segmentId] = 0;
            }

#if DEBUGMETRIC
            if (debug)
            {
                Log._Debug($"GetVehicleMetricGoingToSegment: Segment {SegmentId}, Node {NodeId}. Target segments: {string.Join(", ", ret.Keys.Select(x => x.ToString()).ToArray())}, Registered Vehicles: {string.Join(", ", GetRegisteredVehicles().Select(x => x.Key.ToString()).ToArray())}");
            }
#endif

            ushort vehicleId    = FirstRegisteredVehicleId;
            int    numProcessed = 0;
            while (vehicleId != 0)
            {
                VehicleState state = vehStateManager._GetVehicleState(vehicleId);

                bool breakLoop = false;

                state.ProcessCurrentAndNextPathPosition(ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleId], delegate(ref Vehicle vehState, ref PathUnit.Position curPos, ref PathUnit.Position nextPos) {
                    if (!state.CheckValidity(ref vehState))
                    {
                        RequestCleanup();
                        return;
                    }

#if DEBUGMETRIC
                    if (debug)
                    {
                        Log._Debug($" GetVehicleMetricGoingToSegment: Checking vehicle {vehicleId}");
                    }
#endif

                    if (!ret.ContainsKey(nextPos.m_segment))
                    {
#if DEBUGMETRIC
                        if (debug)
                        {
                            Log._Debug($"  GetVehicleMetricGoingToSegment: ret does not contain key for target segment {pos.TargetSegmentId}");
                        }
#endif
                        return;
                    }

                    if (!includeStopped && vehState.GetLastFrameVelocity().magnitude < TrafficPriorityManager.maxStopVelocity)
                    {
#if DEBUGMETRIC
                        if (debug)
                        {
                            Log._Debug($"  GetVehicleMetricGoingToSegment: Vehicle {vehicleId}: too slow");
                        }
#endif
                        ++numProcessed;
                        return;
                    }

                    if (laneIndex != null && curPos.m_lane != laneIndex)
                    {
#if DEBUGMETRIC
                        if (debug)
                        {
                            Log._Debug($"  GetVehicleMetricGoingToSegment: Vehicle {vehicleId}: Lane index mismatch (expected: {laneIndex}, was: {pos.SourceLaneIndex})");
                        }
#endif
                        return;
                    }

                    if (Options.simAccuracy <= 2)
                    {
                        uint avgSegmentLength = (uint)netManager.m_segments.m_buffer[SegmentId].m_averageLength;
                        uint normLength       = Math.Min(100u, (uint)(state.TotalLength * 100u) / avgSegmentLength);

#if DEBUGMETRIC
                        if (debug)
                        {
                            Log._Debug($"  GetVehicleMetricGoingToSegment: NormLength of vehicle {vehicleId}: {avgSegmentLength} -> {normLength}");
                        }
#endif

#if DEBUGMETRIC
                        if (debug)
                        {
                            ret[pos.TargetSegmentId] += 1;
                        }
                        else
                        {
                            ret[pos.TargetSegmentId] = Math.Min(100u, ret[pos.TargetSegmentId] + normLength);
                        }
#else
                        ret[nextPos.m_segment] += normLength;
#endif
                    }
                    else
                    {
                        ret[nextPos.m_segment] += 10;
                    }
                    ++numProcessed;

                    if ((Options.simAccuracy >= 3 && numProcessed >= 3) || (Options.simAccuracy == 2 && numProcessed >= 5) || (Options.simAccuracy == 1 && numProcessed >= 10))
                    {
                        breakLoop = true;
                        return;
                    }

#if DEBUGMETRIC
                    if (debug)
                    {
                        Log._Debug($"  GetVehicleMetricGoingToSegment: Vehicle {vehicleId}: *added*! Coming from segment {SegmentId}, lane {laneIndex}. Going to segment {pos.TargetSegmentId}, lane {pos.TargetLaneIndex}, minSpeed={TrafficPriority.maxStopVelocity}, speed={speed}");
                    }
#endif
                });

                if (breakLoop)
                {
                    break;
                }

                vehicleId = state.NextVehicleIdOnSegment;
            }

#if DEBUGMETRIC
            if (debug)
            {
                Log._Debug($"GetVehicleMetricGoingToSegment: Calculation completed. {string.Join(", ", ret.Select(x => x.Key.ToString() + "=" + x.Value.ToString()).ToArray())}");
            }
#endif
#if TRACE
            Singleton <CodeProfiler> .instance.Stop("SegmentEnd.GetVehicleMetricGoingToSegment");
#endif
            return(ret);
        }
        /// <summary>
        /// Calculates for each segment the number of cars going to this segment.
        /// We use integer arithmetic for better performance.
        /// </summary>
        public Dictionary <ushort, uint> GetVehicleMetricGoingToSegment(bool includeStopped = true, byte?laneIndex = null, bool debug = false)
        {
            VehicleManager      vehicleManager  = Singleton <VehicleManager> .instance;
            NetManager          netManager      = Singleton <NetManager> .instance;
            VehicleStateManager vehStateManager = VehicleStateManager.Instance;

            Dictionary <ushort, uint> ret = includeStopped ? numVehiclesGoingToSegmentId : numVehiclesFlowingToSegmentId;

            foreach (SegmentEndGeometry endGeo in NodeGeometry.Get(NodeId).SegmentEndGeometries)
            {
                if (endGeo == null)
                {
                    continue;
                }

                if (!endGeo.IncomingOneWay && !ret.ContainsKey(endGeo.SegmentId))
                {
#if DEBUG
                    Log._Debug($"SegmentEnd.GetVehicleMetricGoingToSegment: return dict does not contain entry for segment {endGeo.SegmentId}");
#endif
                }


                ret[endGeo.SegmentId] = 0;
            }

#if DEBUGMETRIC
            if (debug)
            {
                Log._Debug($"GetVehicleMetricGoingToSegment: Segment {SegmentId}, Node {NodeId}. Target segments: {string.Join(", ", ret.Keys.Select(x => x.ToString()).ToArray())}");
            }
#endif

            ushort vehicleId    = FirstRegisteredVehicleId;
            int    numProcessed = 0;
            while (vehicleId != 0)
            {
                VehicleState state = vehStateManager._GetVehicleState(vehicleId);

                bool breakLoop = false;

                state.ProcessCurrentAndNextPathPosition(ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleId], delegate(ref Vehicle vehState, ref PathUnit.Position curPos, ref PathUnit.Position nextPos) {
                    if (!state.CheckValidity(ref vehState))
                    {
                        RequestCleanup();
                        return;
                    }

#if DEBUGMETRIC2
                    if (debug)
                    {
                        Log._Debug($" GetVehicleMetricGoingToSegment: Checking vehicle {vehicleId}");
                    }
#endif

                    if (!ret.ContainsKey(nextPos.m_segment))
                    {
#if DEBUGMETRIC2
                        if (debug)
                        {
                            Log._Debug($"  GetVehicleMetricGoingToSegment: ret does not contain key for target segment {nextPos.m_segment}");
                        }
#endif
                        return;
                    }

                    if (!includeStopped && vehState.GetLastFrameVelocity().sqrMagnitude < TrafficPriorityManager.MAX_SQR_STOP_VELOCITY)
                    {
#if DEBUGMETRIC2
                        if (debug)
                        {
                            Log._Debug($"  GetVehicleMetricGoingToSegment: Vehicle {vehicleId}: too slow");
                        }
#endif
                        ++numProcessed;
                        return;
                    }

                    if (laneIndex != null && curPos.m_lane != laneIndex)
                    {
#if DEBUGMETRIC2
                        if (debug)
                        {
                            Log._Debug($"  GetVehicleMetricGoingToSegment: Vehicle {vehicleId}: Lane index mismatch (expected: {laneIndex}, was: {curPos.m_lane})");
                        }
#endif
                        return;
                    }

                    if (Options.simAccuracy <= 2)
                    {
                        uint avgSegmentLength = (uint)netManager.m_segments.m_buffer[SegmentId].m_averageLength;
                        uint normLength       = 100u;
                        if (avgSegmentLength > 0)
                        {
                            normLength = Math.Min(100u, (uint)(state.TotalLength * 100u) / avgSegmentLength);
                        }

#if DEBUGMETRIC
                        if (debug)
                        {
                            Log._Debug($"  GetVehicleMetricGoingToSegment: NormLength of vehicle {vehicleId}: {avgSegmentLength} -> {normLength}");
                        }
#endif

                        ret[nextPos.m_segment] += normLength;
                    }
                    else
                    {
                        ret[nextPos.m_segment] += 10;
                    }

                    ++ret[nextPos.m_segment];
                    ++numProcessed;

                    if ((Options.simAccuracy >= 3 && numProcessed >= 3) || (Options.simAccuracy == 2 && numProcessed >= 5) || (Options.simAccuracy == 1 && numProcessed >= 10))
                    {
                        breakLoop = true;
                        return;
                    }

#if DEBUGMETRIC2
                    if (debug)
                    {
                        Log._Debug($"  GetVehicleMetricGoingToSegment: Vehicle {vehicleId}: *added*! Coming from segment {SegmentId}, lane {laneIndex}. Going to segment {nextPos.m_segment}, lane {nextPos.m_lane}");
                    }
#endif
                });

                if (breakLoop)
                {
                    break;
                }

                vehicleId = state.NextVehicleIdOnSegment;
            }

#if DEBUGMETRIC
            if (debug)
            {
                Log._Debug($"GetVehicleMetricGoingToSegment: Calculation completed. {string.Join(", ", ret.Select(x => x.Key.ToString() + "=" + x.Value.ToString()).ToArray())}");
            }
#endif
            return(ret);
        }