Esempio n. 1
0
        /// <summary>
        /// 计算路段小时状态
        /// </summary>
        /// <param name="sectionFlow">路段流量</param>
        private void CaculateSectionHourStatus(SectionFlow sectionFlow)
        {
            if (!_sectionStatuses.ContainsKey(sectionFlow.SectionId))
            {
                _sectionStatuses.Add(sectionFlow.SectionId, new SectionStatus
                {
                    SectionId = sectionFlow.SectionId,
                    DateTime  = new DateTime(sectionFlow.DateTime.Year, sectionFlow.DateTime.Month, sectionFlow.DateTime.Day, sectionFlow.DateTime.Hour, 0, 0)
                });
            }

            if (sectionFlow.TrafficStatus == TrafficStatus.通畅)
            {
                _sectionStatuses[sectionFlow.SectionId].Good += 1;
            }
            else if (sectionFlow.TrafficStatus == TrafficStatus.基本通畅)
            {
                _sectionStatuses[sectionFlow.SectionId].Normal += 1;
            }
            else if (sectionFlow.TrafficStatus == TrafficStatus.轻度拥堵)
            {
                _sectionStatuses[sectionFlow.SectionId].Warning += 1;
            }
            else if (sectionFlow.TrafficStatus == TrafficStatus.中度拥堵)
            {
                _sectionStatuses[sectionFlow.SectionId].Bad += 1;
            }
            else if (sectionFlow.TrafficStatus == TrafficStatus.严重拥堵)
            {
                _sectionStatuses[sectionFlow.SectionId].Dead += 1;
            }
        }
Esempio n. 2
0
        /// <summary>
        /// 查询通道分钟流量状态
        /// </summary>
        /// <param name="channelId">通道编号</param>
        /// <returns>通道流量状态</returns>
        public ChannelMinuteFlow QueryChannelMuniteStatus(string channelId)
        {
            channelId = Uri.UnescapeDataString(channelId);
            ChannelMinuteFlow channelMinuteFlow = new ChannelMinuteFlow
            {
                LanesFlow = new List <LaneFlow>()
            };
            FlowChannel channel = _memoryCache.GetChannel(channelId);

            if (channel != null)
            {
                if (channel.SectionId.HasValue)
                {
                    SectionFlow sectionFlow = _memoryCache.GetSectionLastFlow(channel.SectionId.Value);
                    if (sectionFlow == null)
                    {
                        channelMinuteFlow.SectionFlow = new SectionFlow
                        {
                            SectionId   = channel.SectionId.Value,
                            SectionName = channel.RoadSection.SectionName
                        };
                    }
                    else
                    {
                        _memoryCache.FillSectionFlowCache(sectionFlow);
                        channelMinuteFlow.SectionFlow = sectionFlow;
                    }
                }

                foreach (Lane lane in channel.Lanes)
                {
                    LaneFlow f = _memoryCache.GetLaneLastFlow(lane.DataId);
                    if (f == null)
                    {
                        channelMinuteFlow.LanesFlow.Add(new LaneFlow
                        {
                            DataId   = lane.DataId,
                            LaneName = lane.LaneName
                        });
                    }
                    else
                    {
                        _memoryCache.FillLaneFlow(f);
                        channelMinuteFlow.LanesFlow.Add(f);
                    }
                }
            }
            return(channelMinuteFlow);
        }
Esempio n. 3
0
        /// <summary>
        /// 设置路段小时流量
        /// </summary>
        /// <param name="distributedCache">缓存</param>
        /// <param name="flow">路段小时流量</param>
        public static void SetSectionHourFlow(
            this IDistributedCache distributedCache, SectionFlow flow)
        {
            SectionFlow flowCache = GetSectionHourFlow(distributedCache, flow.SectionId, flow.DateTime);

            if (flowCache == null)
            {
                flowCache = flow;
            }
            else
            {
                flowCache.Vkt += flow.Vkt;
                flowCache.TravelTimeProportion += flow.TravelTimeProportion;
                flowCache.Count += flow.Count;
            }

            distributedCache.SetString(
                GetSectionHourFlowKey(flowCache.SectionId, flowCache.DateTime),
                JsonConvert.SerializeObject(flowCache),
                new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(1)
            });
        }
Esempio n. 4
0
 /// <summary>
 /// 设置路段最后流量缓存
 /// </summary>
 /// <param name="memoryCache">缓存实例</param>
 /// <param name="flow">流量数据</param>
 public static void SetSectionLastFlow(this IMemoryCache memoryCache, SectionFlow flow)
 {
     memoryCache.Set(GetSectionLastFlowKey(flow.SectionId),
                     flow, TimeSpan.FromMinutes(5));
 }
Esempio n. 5
0
 /// <summary>
 /// 填充路段流量缓存
 /// </summary>
 /// <param name="memoryCache">缓存</param>
 /// <param name="sectionFlow">车道流量</param>
 /// <returns>路段流量</returns>
 public static SectionFlow FillSectionFlowCache(this IMemoryCache memoryCache, SectionFlow sectionFlow)
 {
     if (sectionFlow != null)
     {
         RoadSection section = memoryCache.GetSection(sectionFlow.SectionId);
         if (section != null)
         {
             sectionFlow.SectionName = section.SectionName;
         }
     }
     return(sectionFlow);
 }
Esempio n. 6
0
        /// <summary>
        /// 设置路段当天流量
        /// </summary>
        /// <param name="distributedCache">缓存</param>
        /// <param name="flow">路段当天流量</param>
        public static void SetSectionDayFlow(
            this IDistributedCache distributedCache, SectionFlow flow)
        {
            SectionFlow flowCache = GetSectionDayFlow(distributedCache, flow.SectionId, flow.DateTime)
                                    ?? new SectionFlow
            {
                SectionId   = flow.SectionId,
                SectionType = flow.SectionType,
                DateTime    = flow.DateTime,

                //平均速度
                Vkt = flow.Vkt,
                Fls = flow.Fls,

                //拥堵状态
                //这里需要设置为通常才能触发如果是拥堵则设置开始时间的条件
                TrafficStatus         = TrafficStatus.通畅,
                CurrentCongestionSpan = flow.CurrentCongestionSpan,
                CongestionSpan        = flow.CongestionSpan,
                CongestionStartTime   = flow.CongestionStartTime
            };

            if (flow.TrafficStatus == TrafficStatus.通畅)
            {
                flowCache.CurrentCongestionSpan = 0;
            }
            else if (flow.TrafficStatus == TrafficStatus.基本通畅)
            {
                flowCache.CurrentCongestionSpan = 0;
            }
            else if (flow.TrafficStatus == TrafficStatus.轻度拥堵)
            {
                flowCache.CurrentCongestionSpan += 1;
                flowCache.CongestionSpan        += 1;
            }
            else if (flow.TrafficStatus == TrafficStatus.中度拥堵)
            {
                flowCache.CurrentCongestionSpan += 1;
                flowCache.CongestionSpan        += 1;
            }
            else
            {
                flowCache.CurrentCongestionSpan += 1;
                flowCache.CongestionSpan        += 1;
            }

            if (flowCache.TrafficStatus < TrafficStatus.轻度拥堵 &&
                flow.TrafficStatus >= TrafficStatus.轻度拥堵)
            {
                flowCache.CongestionStartTime = flow.DateTime;
            }
            flowCache.TrafficStatus = flow.TrafficStatus;

            flowCache.Total += flow.Total;
            flowCache.Vkt   += flow.Vkt;
            flowCache.Fls   += flow.Fls;
            flowCache.TravelTimeProportion += flow.TravelTimeProportion;
            flowCache.Count += flow.Count;

            distributedCache.SetString(
                GetSectionDayFlowKey(flowCache.SectionId, flowCache.DateTime),
                JsonConvert.SerializeObject(flowCache),
                new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(1)
            });
        }
Esempio n. 7
0
        /// <summary>
        /// 获取城市小时拥堵指数
        /// </summary>
        /// <param name="hour">时间</param>
        /// <returns>拥堵指数</returns>
        private double GetHourCongestionData(DateTime hour)
        {
            Dictionary <int, List <SectionFlow> > sectionTypeHourFlows = Enum.GetValues(typeof(SectionType)).Cast <SectionType>().ToDictionary(s => (int)s, s => new List <SectionFlow>());

            foreach (var section in _memoryCache.GetSections())
            {
                SectionFlow flow = _distributedCache.GetSectionHourFlow(section.SectionId, hour);
                if (flow != null)
                {
                    sectionTypeHourFlows[flow.SectionType].Add(flow);
                }
            }

            double totalHourVkts = sectionTypeHourFlows.Sum(p => p.Value.Sum(f => f.Vkt));

            //本小时拥堵指数
            if (totalHourVkts > 0)
            {
                double totalTravelTimeProportion = sectionTypeHourFlows
                                                   .Sum(p => p.Value.Sum(f => f.Count) == 0
                        ? 0
                        : p.Value.Sum(f => f.TravelTimeProportion) / p.Value.Sum(f => f.Count) * (p.Value.Sum(f => f.Vkt) / totalHourVkts));
                if (totalTravelTimeProportion < 1)
                {
                    totalTravelTimeProportion = 1;
                }

                double congestionData = (totalTravelTimeProportion - 1) / 0.3 * 2;

                if (totalTravelTimeProportion < 1.3)
                {
                    congestionData += 0;
                }
                else if (totalTravelTimeProportion >= 1.3 && totalTravelTimeProportion < 1.6)
                {
                    congestionData += 2;
                }
                else if (totalTravelTimeProportion >= 1.6 && totalTravelTimeProportion < 1.9)
                {
                    congestionData += 4;
                }
                else if (totalTravelTimeProportion >= 1.9 && totalTravelTimeProportion < 2.2)
                {
                    congestionData += 6;
                }
                else if (totalTravelTimeProportion >= 2.2 && totalTravelTimeProportion < 2.5)
                {
                    congestionData += 8;
                }
                else
                {
                    congestionData = 10;
                }

                return(congestionData);
            }
            else
            {
                return(0);
            }
        }
Esempio n. 8
0
        /// <summary>
        /// 计算路段当天流量
        /// </summary>
        private void CalculateSectionDayFlow()
        {
            DateTime   now        = DateTime.Now;
            CityStatus cityStatus = new CityStatus
            {
                CongestionDatas = new Dictionary <int, double>(),
                SectionStatuses = Enum.GetValues(typeof(TrafficStatus))
                                  .Cast <TrafficStatus>()
                                  .ToDictionary(trafficStatus => (int)trafficStatus, trafficStatus => new SectionsSpeed())
            };
            List <RoadSection> sections = _memoryCache.GetSections();
            //计算当前分钟路段交通状态
            Dictionary <TrafficStatus, List <SectionFlow> > trafficStatusFlows = Enum.GetValues(typeof(TrafficStatus)).Cast <TrafficStatus>().ToDictionary(trafficStatus => trafficStatus, trafficStatus => new List <SectionFlow>());

            foreach (var section in sections)
            {
                SectionFlow flow = _memoryCache.GetSectionLastFlow(section.SectionId);
                if (flow != null)
                {
                    trafficStatusFlows[flow.TrafficStatus].Add(flow);
                }
            }
            foreach (var pair in trafficStatusFlows)
            {
                //状态下路网总vkt
                double totalStatusVkts = pair.Value.Sum(f => f.Vkt);
                //状态下路网平均速度
                double totalStatusAverageSpeed = 0.0;
                if (totalStatusVkts > 0)
                {
                    //状态下路网平均速度
                    totalStatusAverageSpeed =
                        (pair.Value.Sum(f => f.Fls) > 0
                        ? pair.Value.Sum(f => f.Vkt) / pair.Value.Sum(f => f.Fls) * (pair.Value.Sum(f => f.Vkt) / totalStatusVkts)
                        : 0)
                        * 3600 / 1000;
                }

                //当前交通状态
                cityStatus.SectionStatuses[(int)pair.Key].AverageSpeed = Convert.ToInt32(totalStatusAverageSpeed);
                cityStatus.SectionStatuses[(int)pair.Key].SectionCount = pair.Value.Count;
            }

            //城市小时拥堵指数
            DateTime today = now.Date;

            for (int h = 0; h < now.Hour; ++h)
            {
                double?congestionData = _memoryCache.GetCityHourCongestionData(today.AddHours(h));
                if (!congestionData.HasValue)
                {
                    congestionData = GetHourCongestionData(today.AddHours(h));
                    _memoryCache.SetCityHourCongestionData(today.AddHours(h), congestionData.Value);
                }

                cityStatus.CongestionDatas.Add(h, Math.Round(congestionData.Value, 1));
            }
            cityStatus.CongestionDatas.Add(now.Hour, Math.Round(GetHourCongestionData(today.AddHours(now.Hour)), 1));

            //今日总流量
            foreach (var lane in _memoryCache.GetLanes())
            {
                LaneFlow flow = _distributedCache.GetLaneDayFlow(lane.DataId, today);
                if (flow != null)
                {
                    cityStatus.TotalFlow += flow.Total;
                }
            }
            //今日平均速度
            Dictionary <int, List <SectionFlow> > sectionTypeDayFlows = Enum.GetValues(typeof(SectionType)).Cast <SectionType>().ToDictionary(s => (int)s, s => new List <SectionFlow>());

            foreach (var section in sections)
            {
                SectionFlow flow = _distributedCache.GetSectionDayFlow(section.SectionId, today);
                if (flow != null)
                {
                    _memoryCache.FillSectionFlowCache(flow);
                    sectionTypeDayFlows[flow.SectionType].Add(flow);
                }
            }
            //路网总vkt
            double totalVkts = sectionTypeDayFlows.Sum(p => p.Value.Sum(f => f.Vkt));

            if (totalVkts > 0)
            {
                cityStatus.AverageSpeed = Convert.ToInt64(
                    sectionTypeDayFlows
                    .Sum(p => p.Value.Sum(f => f.Fls) > 0
                            ? p.Value.Sum(f => f.Vkt) / p.Value.Sum(f => f.Fls) * (p.Value.Sum(f => f.Vkt) / totalVkts)
                            : 0) * 3600 / 1000);
            }
            else
            {
                cityStatus.AverageSpeed = 0;
            }
            //拥堵排名
            cityStatus.SectionCongestionRank = sectionTypeDayFlows
                                               .SelectMany(p => p.Value)
                                               .Where(f => f.CongestionSpan > 0)
                                               .OrderByDescending(f => f.CongestionSpan)
                                               .Take(10)
                                               .ToList();

            //当前拥堵路段列表
            cityStatus.SectionCongestions = sectionTypeDayFlows
                                            .SelectMany(p => p.Value)
                                            .Where(f => f.TrafficStatus >= TrafficStatus.轻度拥堵)
                                            .OrderByDescending(f => f.CongestionStartTime)
                                            .ToList();

            Status = cityStatus;
        }
Esempio n. 9
0
 /// <summary>
 /// 保存路算分钟流量
 /// </summary>
 /// <param name="sectionFlow">路段流量</param>
 private void SaveSectionMinuteFlow(SectionFlow sectionFlow)
 {
     _memoryCache.SetSectionLastFlow(sectionFlow);
     _distributedCache.SetSectionHourFlow(sectionFlow);
     _distributedCache.SetSectionDayFlow(sectionFlow);
 }
Esempio n. 10
0
        /// <summary>
        /// 计算所有路段分钟流量
        /// </summary>
        /// <param name="time"></param>
        private void CalculateSectionMinuteFlow(DateTime time)
        {
            var totalLanes = _memoryCache.GetLanes();

            time = time.Add(-_span);
            foreach (RoadSection section in _memoryCache.GetSections())
            {
                List <Lane> sectionLanes = totalLanes
                                           .Where(l => l.Channel.SectionId.HasValue && l.Channel.SectionId.Value == section.SectionId)
                                           .ToList();
                SectionFlow sectionFlow = new SectionFlow
                {
                    SectionId   = section.SectionId,
                    DateTime    = time,
                    SectionType = section.SectionType,
                    FreeSpeed   = section.FreeSpeed,
                    Length      = section.Length
                };
                int availableLanesCount = 0;
                foreach (var lane in sectionLanes)
                {
                    LaneFlow laneFlow = _distributedCache.GetLaneMinuteFlow(lane.DataId, time);
                    if (laneFlow != null)
                    {
                        sectionFlow.Total         += laneFlow.Total;
                        sectionFlow.Vehicle       += laneFlow.Vehicle;
                        sectionFlow.HeadDistance  += laneFlow.HeadDistance;
                        sectionFlow.TimeOccupancy += laneFlow.TimeOccupancy;
                        sectionFlow.Occupancy     += laneFlow.Occupancy;
                        sectionFlow.Distance      += laneFlow.Distance;
                        sectionFlow.TravelTime    += laneFlow.TravelTime;
                        availableLanesCount       += 1;
                    }
                }

                if (availableLanesCount > 0)
                {
                    //路段平均速度(千米/小时)
                    double sectionAverageSpeed = sectionFlow.TravelTime > 0 ? (sectionFlow.Distance / sectionFlow.TravelTime * 3600 / 1000) : 0;
                    //路段行程时间(秒)
                    double sectionTravelTime = sectionAverageSpeed > 0 ? sectionFlow.Length / (sectionAverageSpeed * 1000 / 3600) : 0;
                    //路段自由流行程时间(秒)
                    double sectionFreeTravelTime = sectionFlow.FreeSpeed > 0 ? sectionFlow.Length / (sectionFlow.FreeSpeed * 1000 / 3600) : 0;
                    //路段行程时间比
                    double sectionTravelTimeProportion =
                        sectionTravelTime < sectionFreeTravelTime
                            ? 1
                            : sectionTravelTime / sectionFreeTravelTime;

                    //路段交通状态
                    TrafficStatus trafficStatus;
                    if (sectionAverageSpeed > sectionFlow.FreeSpeed * 0.7)
                    {
                        trafficStatus = TrafficStatus.通畅;
                    }
                    else if (sectionAverageSpeed <= sectionFlow.FreeSpeed * 0.7 &&
                             sectionAverageSpeed > sectionFlow.FreeSpeed * 0.5)
                    {
                        trafficStatus = TrafficStatus.基本通畅;
                    }
                    else if (sectionAverageSpeed <= sectionFlow.FreeSpeed * 0.5 &&
                             sectionAverageSpeed > sectionFlow.FreeSpeed * 0.4)
                    {
                        trafficStatus = TrafficStatus.轻度拥堵;
                    }
                    else if (sectionAverageSpeed <= sectionFlow.FreeSpeed * 0.4 &&
                             sectionAverageSpeed > sectionFlow.FreeSpeed * 0.3)
                    {
                        trafficStatus = TrafficStatus.中度拥堵;
                    }
                    else
                    {
                        trafficStatus = TrafficStatus.严重拥堵;
                    }

                    sectionFlow.Count = 1;

                    sectionFlow.AverageSpeed  = sectionAverageSpeed;
                    sectionFlow.HeadDistance  = sectionFlow.HeadDistance / availableLanesCount;
                    sectionFlow.Occupancy     = sectionFlow.Occupancy / availableLanesCount;
                    sectionFlow.TimeOccupancy = sectionFlow.TimeOccupancy / availableLanesCount;
                    sectionFlow.TrafficStatus = trafficStatus;

                    sectionFlow.Total   = sectionFlow.Total;
                    sectionFlow.Vehicle = sectionFlow.Vehicle;
                    sectionFlow.Vkt     = sectionFlow.Vehicle * sectionFlow.Length;
                    sectionFlow.Fls     = sectionFlow.Vehicle * sectionTravelTime;
                    sectionFlow.TravelTimeProportion = sectionTravelTimeProportion;

                    CaculateSectionHourStatus(sectionFlow);

                    SaveSectionMinuteFlow(sectionFlow);

                    _logger.LogDebug((int)LogEvent.路段流量, $"路段流量 id:{sectionFlow.SectionId} time:{sectionFlow.DateTime} total lanes:{sectionLanes.Count} available lanes:{availableLanesCount} type:{sectionFlow.SectionType} length:{sectionFlow.Length} free speed:{sectionFlow.FreeSpeed} average speed:{sectionFlow.AverageSpeed} head distance:{sectionFlow.HeadDistance} occ:{sectionFlow.Occupancy} tocc {sectionFlow.TimeOccupancy} status:{sectionFlow.TrafficStatus} total:{sectionFlow.Total} vehicle:{sectionFlow.Vehicle} vkt:{sectionFlow.Vkt} fls:{sectionFlow.Fls} ttp:{sectionFlow.TravelTimeProportion}");
                }
                else
                {
                    _logger.LogDebug((int)LogEvent.路段流量, $"路段流量计算失败 id:{sectionFlow.SectionId} time:{sectionFlow.DateTime} total lanes:{sectionLanes.Count} available lanes:{availableLanesCount}");
                }
            }
        }