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)}", "区域流量监控");
}
}
}
}