磁导航1.0内部交管和信号交互

This commit is contained in:
ykkokluo
2026-08-24 14:55:35 +08:00
parent cacc5fea5c
commit 244b0af6c8
60 changed files with 6395 additions and 294 deletions
+87 -20
View File
@@ -4,30 +4,24 @@ using StandardScene.Signal.Model;
namespace StandardScene.Signal.Logic
{
/// <summary>
/// 一条握手点配置的解析结果。参数格式与反编译 <c>SignalStop.SignalParams</c> 一致
/// 一条握手点配置的解析结果。新列(机构/工位/动作/附加参数)优先,旧 SignalParams 作回退
/// </summary>
/// <remarks>
/// <see cref="SignalParams"/> 按分号切成 <see cref="Parts"/>,缺段时 <see cref="Part"/> 返回空串。
/// 各类型约定:
/// <list type="bullet">
/// <item><c>JGControl</c>:机构名;RequestIn|Arrived;[区域-车组-限额-点列表]</item>
/// <item><c>PointControl</c>UP1|UP2|Down1|Down2;机构名</item>
/// <item><c>TimedCharging</c>:最长秒数;上限电量;下限电量</item>
/// <item><c>RateFlowControl</c>:区域;车组;限额;点1,点2</item>
/// </list>
/// </remarks>
public sealed class SignalStopSpec
{
/// <summary>握手类型名,与 Handler 的 <see cref="Is"/> 比较时忽略大小写。</summary>
public string SignalType { get; init; } = "";
/// <summary>原始参数串,限流独立类型会整段交给 <see cref="RateFlowHandler"/>。</summary>
public string SignalParams { get; init; } = "";
/// <summary>按 ';' 切分,保留空段(与 Split None 一致,方便 Part(n) 按下标取)。</summary>
public string[] Parts { get; init; } = Array.Empty<string>();
/// <summary>取第 <paramref name="index"/> 段;越界或 null 返回空串。</summary>
public string JgName { get; init; } = "";
public string DockId { get; init; } = "";
public string Action { get; init; } = "";
public string ExtraParams { get; init; } = "";
public string Part(int index)
{
if (index < 0 || index >= Parts.Length)
@@ -35,29 +29,102 @@ namespace StandardScene.Signal.Logic
return Parts[index] ?? "";
}
/// <summary>从类型名和参数串构造;类型会 Trim,参数保持原样以便日志对照现场 JSON。</summary>
public static SignalStopSpec Parse(string signalType, string signalParams)
{
var type = (signalType ?? "").Trim();
var raw = signalParams ?? "";
return new SignalStopSpec
var parsed = new SignalStopSpec
{
SignalType = type,
SignalParams = raw,
Parts = raw.Split(new[] { ';' }, StringSplitOptions.None)
};
return EnrichFromParts(parsed);
}
/// <summary>从握手点 Model 构造;model 为 null 时返回 null。</summary>
public static SignalStopSpec From(HandshakePointModel model)
{
if (model == null)
return null;
return Parse(model.SignalType, model.SignalParams);
var type = (model.SignalType ?? "").Trim();
if (string.Equals(type, "TimedCharging", StringComparison.OrdinalIgnoreCase) ||
string.Equals(type, "RateFlowControl", StringComparison.OrdinalIgnoreCase))
{
var raw = First(model.ExtraParams, model.SignalParams);
return Parse(type, raw);
}
var parsed = Parse(type, model.SignalParams ?? "");
var jg = First(model.JgName, parsed.JgName);
var action = First(model.Action, parsed.Action);
var dock = First(model.DockId, parsed.DockId);
var extra = First(model.ExtraParams, parsed.ExtraParams);
return new SignalStopSpec
{
SignalType = parsed.SignalType,
SignalParams = parsed.SignalParams,
Parts = parsed.Parts,
JgName = jg,
DockId = dock,
Action = action,
ExtraParams = extra
};
}
/// <summary>类型名是否匹配(忽略大小写)。</summary>
public bool Is(string type) =>
string.Equals(SignalType, type, StringComparison.OrdinalIgnoreCase);
private static SignalStopSpec EnrichFromParts(SignalStopSpec parsed)
{
var type = parsed.SignalType;
if (string.Equals(type, "TimedCharging", StringComparison.OrdinalIgnoreCase) ||
string.Equals(type, "RateFlowControl", StringComparison.OrdinalIgnoreCase))
{
return new SignalStopSpec
{
SignalType = parsed.SignalType,
SignalParams = parsed.SignalParams,
Parts = parsed.Parts,
ExtraParams = parsed.SignalParams
};
}
var point = string.Equals(type, "PointControl", StringComparison.OrdinalIgnoreCase);
var jg = point ? parsed.Part(1).Trim() : parsed.Part(0).Trim();
var action = point ? parsed.Part(0).Trim() : parsed.Part(1).Trim();
var dock = "";
var extra = "";
var p2 = parsed.Part(2).Trim();
if (LooksLikeDock(p2))
dock = p2;
else if (LooksLikeRateFlow(p2))
extra = p2;
if (string.IsNullOrEmpty(extra))
extra = parsed.Part(3).Trim();
return new SignalStopSpec
{
SignalType = parsed.SignalType,
SignalParams = parsed.SignalParams,
Parts = parsed.Parts,
JgName = jg,
DockId = dock,
Action = action,
ExtraParams = extra
};
}
private static string First(string a, string b)
{
if (!string.IsNullOrWhiteSpace(a))
return a.Trim();
return (b ?? "").Trim();
}
private static bool LooksLikeRateFlow(string s) =>
!string.IsNullOrEmpty(s) && s.IndexOf('-') >= 0;
private static bool LooksLikeDock(string s) =>
!string.IsNullOrEmpty(s) && s.IndexOf('-') < 0 && s.IndexOf(',') < 0;
}
}