2.0协议完善加简单交管配置
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
using StandardScene.Magnetic.Protocol;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace StandardScene.Magnetic.Tasking
|
||||
{
|
||||
/// <summary>
|
||||
/// 管控停止(StartStop=12)按车放行:地图站点保持 12,仅改本车任务报文。
|
||||
/// </summary>
|
||||
public sealed class Fass2ControlAreaInfo
|
||||
{
|
||||
public int SiteId { get; set; }
|
||||
public string AreaId { get; set; } = string.Empty;
|
||||
public int[] AreaSiteIds { get; set; } = Array.Empty<int>();
|
||||
public int Capacity { get; set; } = 1;
|
||||
public byte ReleaseStartStop { get; set; } = Fass2TaskBuilder.StartStopControlStart;
|
||||
}
|
||||
|
||||
public sealed class Fass2ControlOccupancy
|
||||
{
|
||||
public Fass2ControlOccupancy(int carId, IReadOnlyList<int> occupiedSiteIds)
|
||||
{
|
||||
CarId = carId;
|
||||
OccupiedSiteIds = occupiedSiteIds ?? Array.Empty<int>();
|
||||
}
|
||||
|
||||
public int CarId { get; }
|
||||
public IReadOnlyList<int> OccupiedSiteIds { get; }
|
||||
}
|
||||
|
||||
public sealed class Fass2ControlReleaseCheck
|
||||
{
|
||||
public bool CanRelease { get; set; }
|
||||
public string AreaId { get; set; } = string.Empty;
|
||||
public int Capacity { get; set; } = 1;
|
||||
public int OthersInArea { get; set; }
|
||||
public byte ReleaseStartStop { get; set; } = Fass2TaskBuilder.StartStopControlStart;
|
||||
public string Reason { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public static class Fass2ControlAreaGate
|
||||
{
|
||||
private static readonly char[] SiteIdSeparators = { ',', ';', '|', ' ', '\t', '[', ']', '(', ')', '{', '}' };
|
||||
|
||||
public static bool IsControlStop(byte startStop)
|
||||
{
|
||||
return startStop == Fass2TaskBuilder.StartStopControlStop;
|
||||
}
|
||||
|
||||
public static bool AllowsLeave(byte startStop)
|
||||
{
|
||||
return startStop == Fass2TaskBuilder.StartStopPass
|
||||
|| startStop == Fass2TaskBuilder.StartStopControlStart;
|
||||
}
|
||||
|
||||
public static Fass2ControlAreaInfo Resolve(Fass2SiteActionData data, int siteId)
|
||||
{
|
||||
data ??= new Fass2SiteActionData();
|
||||
var areaSites = ParseSiteIds(data.ControlArea, siteId);
|
||||
var capacity = data.ControlCapacity.GetValueOrDefault(1);
|
||||
if (capacity < 1)
|
||||
{
|
||||
capacity = 1;
|
||||
}
|
||||
|
||||
var release = data.ControlReleaseStartStop ?? Fass2TaskBuilder.StartStopControlStart;
|
||||
if (release != Fass2TaskBuilder.StartStopPass &&
|
||||
release != Fass2TaskBuilder.StartStopControlStart)
|
||||
{
|
||||
release = Fass2TaskBuilder.StartStopControlStart;
|
||||
}
|
||||
|
||||
return new Fass2ControlAreaInfo
|
||||
{
|
||||
SiteId = siteId,
|
||||
AreaSiteIds = areaSites,
|
||||
AreaId = string.Join(",", areaSites),
|
||||
Capacity = capacity,
|
||||
ReleaseStartStop = release
|
||||
};
|
||||
}
|
||||
|
||||
public static int[] ParseSiteIds(string text, int fallbackSiteId)
|
||||
{
|
||||
var ids = new List<int>();
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
var parts = text.Split(SiteIdSeparators, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var part in parts)
|
||||
{
|
||||
if (int.TryParse(part.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var id) &&
|
||||
id > 0 && !ids.Contains(id))
|
||||
{
|
||||
ids.Add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ids.Count == 0 && fallbackSiteId > 0)
|
||||
{
|
||||
ids.Add(fallbackSiteId);
|
||||
}
|
||||
|
||||
return ids.ToArray();
|
||||
}
|
||||
|
||||
public static int LimitWindowCount(
|
||||
IReadOnlyList<Fass2NodeMessage> nodes,
|
||||
int startIndex,
|
||||
int count,
|
||||
int releasedIndex)
|
||||
{
|
||||
if (nodes == null || count <= 0 || startIndex < 0 || startIndex >= nodes.Count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var limited = Math.Min(count, nodes.Count - startIndex);
|
||||
for (var i = 0; i < limited; i++)
|
||||
{
|
||||
var node = nodes[startIndex + i];
|
||||
if (node != null && IsControlStop(node.StartStop) && releasedIndex != startIndex + i)
|
||||
{
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return limited;
|
||||
}
|
||||
|
||||
public static Fass2ControlReleaseCheck Evaluate(
|
||||
int selfCarId,
|
||||
Fass2ControlAreaInfo area,
|
||||
IReadOnlyList<Fass2ControlOccupancy> occupancies)
|
||||
{
|
||||
area ??= new Fass2ControlAreaInfo();
|
||||
if (area.AreaSiteIds == null || area.AreaSiteIds.Length == 0)
|
||||
{
|
||||
area.AreaSiteIds = area.SiteId > 0 ? new[] { area.SiteId } : Array.Empty<int>();
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(area.AreaId))
|
||||
{
|
||||
area.AreaId = string.Join(",", area.AreaSiteIds);
|
||||
}
|
||||
|
||||
if (area.Capacity < 1)
|
||||
{
|
||||
area.Capacity = 1;
|
||||
}
|
||||
|
||||
var others = 0;
|
||||
if (occupancies != null)
|
||||
{
|
||||
foreach (var occupancy in occupancies)
|
||||
{
|
||||
if (occupancy == null || occupancy.CarId == selfCarId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (OccupiesListedSites(occupancy.OccupiedSiteIds, area.AreaSiteIds))
|
||||
{
|
||||
others++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var canRelease = others < area.Capacity;
|
||||
return new Fass2ControlReleaseCheck
|
||||
{
|
||||
CanRelease = canRelease,
|
||||
AreaId = area.AreaId,
|
||||
Capacity = area.Capacity,
|
||||
OthersInArea = others,
|
||||
ReleaseStartStop = area.ReleaseStartStop == 0
|
||||
? Fass2TaskBuilder.StartStopControlStart
|
||||
: area.ReleaseStartStop,
|
||||
Reason = canRelease
|
||||
? "area clear"
|
||||
: $"area occupied cars={others}, capacity={area.Capacity}"
|
||||
};
|
||||
}
|
||||
|
||||
public static bool OccupiesListedSites(IReadOnlyList<int> occupiedSiteIds, IReadOnlyList<int> areaSiteIds)
|
||||
{
|
||||
if (occupiedSiteIds == null || occupiedSiteIds.Count == 0 ||
|
||||
areaSiteIds == null || areaSiteIds.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < occupiedSiteIds.Count; i++)
|
||||
{
|
||||
var occupied = occupiedSiteIds[i];
|
||||
if (occupied <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var j = 0; j < areaSiteIds.Count; j++)
|
||||
{
|
||||
if (areaSiteIds[j] == occupied)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user