using System; using System.Collections.Generic; using System.Linq; using System.Threading; using Simple3.RCS; using Simple3.RCS.CarTypes; using SimpleCore; using Newtonsoft.Json; using Simple3.CADTools; using Simple3.Props; using Simple3.UI; using SimpleCore.Library; using System.Threading.Tasks; using System.Diagnostics; using SimpleCore.Traffic; using SimpleCore.PropType; using LessokajiWeaverUtilities.Utilities; namespace StandardScene.Scheduler { [MissionType(Name = "区域流量监控", editor = typeof(RegionalTrafficControlMission))] [I18N.DocumentTranslation(Name = "Regional Traffic Control Mission", locale = "en")] public class RegionalTrafficControlMission : Mission { public static Mission Create() { return new RegionalTrafficControlMission(); } /// /// 区域流量监控状态 /// public class RegionalTrafficControlMissionStatus : MissionStatus { /// /// 区域车辆统计信息:区域编号 -> 当前车辆数量 /// public Dictionary RegionVehicleCounts { get; set; } = new Dictionary(); /// /// 区域限制信息:区域编号 -> 最大允许车辆数 /// public Dictionary RegionMaxCounts { get; set; } = new Dictionary(); /// /// 被阻止的车辆统计:区域编号 -> 被阻止次数 /// public Dictionary BlockedCounts { get; set; } = new Dictionary(); } public override MissionStatus status { get; set; } = new RegionalTrafficControlMissionStatus(); [JsonIgnore] private bool started = false; [JsonIgnore] private object sync = new object(); /// /// 区域内的车辆记录:区域编号 -> 车辆ID列表 /// [JsonIgnore] private readonly Dictionary> carsInRegions = new Dictionary>(); /// /// 启动进程 /// [MethodMember(Name = "启动进程", Description = "开始区域流量监控")] public override void Execute() { if (started) { Diagnosis.Post("区域流量监控已在运行中", "区域流量监控"); return; } started = true; status.status = "运行中"; // 订阅交通控制事件 TrafficControl.BeforeLock += BeforeLockEvent; TrafficControl.AfterLeave += AfterLeaveEvent; TrafficControl.OnLockAcquired += OnLockAcquiredEvent; // 启动统计更新任务 Task.Factory.StartNew(() => { while (started) { try { UpdateRegionStatistics(); Thread.Sleep(500); } catch (Exception e) { Diagnosis.Post($"{ExceptionFormatter.FormatEx(e)}", "区域流量监控"); } } }); Diagnosis.Post("区域流量监控已启动", "区域流量监控", true); } /// /// 停止进程 /// [MethodMember(Name = "停止进程", Description = "停止区域流量监控")] public override void Stop() { if (!started) { return; } started = false; // 取消事件订阅 TrafficControl.BeforeLock -= BeforeLockEvent; TrafficControl.AfterLeave -= AfterLeaveEvent; TrafficControl.OnLockAcquired -= OnLockAcquiredEvent; status.status = "已停止"; Diagnosis.Post("区域流量监控已停止", "区域流量监控", true); } /// /// 获取站点的区域信息 /// /// 站点 /// 区域标识和限制数量,如果站点不属于任何区域则返回null private (string regionId, int maxCount)? GetRegionInfo(Site site) { if (site == null || site.fields == null) { return null; } // 查找所有以Region开头的字段 var regionField = site.fields.FirstOrDefault(kvp => kvp.Key.StartsWith("Region", StringComparison.OrdinalIgnoreCase)); if (regionField.Key == null) { return null; // 站点不属于任何区域 } string regionId = regionField.Key; // 例如 "Region1" // 字段值就是限制数量 if (!int.TryParse(regionField.Value, out int maxCount)) { return null; // 无法解析限制数量 } return (regionId, maxCount); } /// /// 检查车辆是否已经在指定区域内 /// private bool IsCarAlreadyInRegion(AbstractCar car, string regionId) { if (car?.status == null) { return false; } // 检查车辆当前占用的站点是否属于该区域 if (car.status.holdingLocks != null) { foreach (var lockedSiteId in car.status.holdingLocks) { var lockedSite = SimpleLib.GetSite(lockedSiteId); var regionInfo = GetRegionInfo(lockedSite); if (regionInfo.HasValue && regionInfo.Value.regionId == regionId) { return true; // 车辆已经在区域内 } } } return false; } /// /// BeforeLock事件处理:检查车辆是否可以进入区域 /// private bool BeforeLockEvent(AbstractCar car, int siteId) { try { var site = SimpleLib.GetSite(siteId); if (site == null) { return true; } // 获取站点的区域信息 var regionInfo = GetRegionInfo(site); if (!regionInfo.HasValue) { return true; // 站点不属于任何区域,允许通过 } var (regionId, maxCount) = regionInfo.Value; // 如果最大数量为0或负数,表示不限制 if (maxCount <= 0) { return true; } // 检查车辆是否已经在区域内 lock (sync) { if (IsCarAlreadyInRegion(car, regionId)) { // 车辆已经在区域内,允许通行 return true; } // 车辆即将进入区域,需要检查是否超过限制 // 排除当前车辆本身,因为它还没有进入区域 int currentCount = CountCarsInRegion(regionId, excludeCarId: car.id); // 如果当前车辆数量已达到或超过限制,阻止进入 if (currentCount >= maxCount) { var statusObj = (RegionalTrafficControlMissionStatus)status; if (!statusObj.BlockedCounts.ContainsKey(regionId)) { statusObj.BlockedCounts[regionId] = 0; } statusObj.BlockedCounts[regionId]++; Diagnosis.Log($"车辆 {car.id} 尝试进入区域 {regionId} 被阻止,当前车辆数: {currentCount}/{maxCount}", "区域流量监控", true); return false; // 阻止进入 } return true; // 允许进入 } } catch (Exception e) { Diagnosis.Post($"BeforeLockEvent错误: {ExceptionFormatter.FormatEx(e)}", "区域流量监控"); return true; // 发生错误时允许通过,避免阻塞系统 } } /// /// AfterLeave事件处理:车辆离开区域时更新统计 /// private void AfterLeaveEvent(AbstractCar car, int siteId) { try { var site = SimpleLib.GetSite(siteId); if (site == null) { return; } // 获取站点的区域信息 var regionInfo = GetRegionInfo(site); if (!regionInfo.HasValue) { return; // 站点不属于任何区域 } string regionId = regionInfo.Value.regionId; // 从区域车辆列表中移除该车辆 lock (sync) { if (carsInRegions.TryGetValue(regionId, out var carSet)) { carSet.Remove(car.id); if (carSet.Count == 0) { carsInRegions.Remove(regionId); } } } } catch (Exception e) { Diagnosis.Post($"AfterLeaveEvent错误: {ExceptionFormatter.FormatEx(e)}", "区域流量监控"); } } /// /// OnLockAcquired事件处理:车辆成功锁定站点时,将其加入区域统计 /// private void OnLockAcquiredEvent(AbstractCar car, int siteId) { try { var site = SimpleLib.GetSite(siteId); if (site == null) { return; } // 获取站点的区域信息 var regionInfo = GetRegionInfo(site); if (!regionInfo.HasValue) { return; // 站点不属于任何区域 } string regionId = regionInfo.Value.regionId; // 将车辆添加到区域车辆列表中 lock (sync) { if (!carsInRegions.TryGetValue(regionId, out var carSet)) { carSet = new HashSet(); carsInRegions[regionId] = carSet; } carSet.Add(car.id); } } catch (Exception e) { Diagnosis.Post($"OnLockAcquiredEvent错误: {ExceptionFormatter.FormatEx(e)}", "区域流量监控"); } } /// /// 统计指定区域内的车辆数量 /// /// 区域标识 /// 要排除的车辆ID(可选,用于排除即将进入的车辆) /// 区域内的车辆数量 private int CountCarsInRegion(string regionId, int excludeCarId = -1) { lock (sync) { // 首先从已记录的车辆列表中统计 int count = 0; if (carsInRegions.TryGetValue(regionId, out var recordedCars)) { count = recordedCars.Count(carId => carId != excludeCarId); } // 同时检查所有站点,统计属于该区域且当前有车辆占用的站点 var regionSites = SimpleLib.GetAllSites() .Where(s => { var regionInfo = GetRegionInfo(s); return regionInfo.HasValue && regionInfo.Value.regionId == regionId; }) .ToList(); // 统计这些站点上的车辆(只统计已锁定的,不包括正在前往的) // 因为正在前往的车辆还没有真正进入区域 var carsInRegionSites = SimpleLib.GetAllCars() .OfType() .Where(car => { if (car?.status == null) return false; // 排除指定车辆 if (car.id == excludeCarId) return false; // 只统计已经在区域内的站点(holdingLocks) // 不统计pendingLocks,因为那些车辆还没有真正进入区域 bool inRegionSite = car.status.holdingLocks?.Any(siteId => { var site = SimpleLib.GetSite(siteId); var regionInfo = GetRegionInfo(site); return regionInfo.HasValue && regionInfo.Value.regionId == regionId; }) == true; return inRegionSite; }) .Select(car => car.id) .ToHashSet(); // 返回两者中的较大值,确保统计准确 return Math.Max(count, carsInRegionSites.Count); } } /// /// 更新区域统计信息 /// private void UpdateRegionStatistics() { try { lock (sync) { var statusObj = (RegionalTrafficControlMissionStatus)status; statusObj.RegionVehicleCounts.Clear(); statusObj.RegionMaxCounts.Clear(); // 获取所有有区域字段的站点,按区域分组 var regionSites = SimpleLib.GetAllSites() .Select(s => { var regionInfo = GetRegionInfo(s); return regionInfo.HasValue ? (site: s, regionId: regionInfo.Value.regionId, maxCount: regionInfo.Value.maxCount) : (site: (Site)null, regionId: (string)null, maxCount: 0); }) .Where(x => x.site != null && !string.IsNullOrEmpty(x.regionId)) .GroupBy(x => x.regionId) .ToList(); foreach (var group in regionSites) { string regionId = group.Key; var firstItem = group.First(); // 获取最大允许数量(从第一个站点的字段值获取) int maxCount = firstItem.maxCount; // 统计当前车辆数量 int currentCount = CountCarsInRegion(regionId); statusObj.RegionMaxCounts[regionId] = maxCount; statusObj.RegionVehicleCounts[regionId] = currentCount; } } } catch (Exception e) { Diagnosis.Post($"UpdateRegionStatistics错误: {ExceptionFormatter.FormatEx(e)}", "区域流量监控"); } } } }