using System;
using System.Collections.Generic;
namespace StandardScene.Fass2Simulator
{
///
/// 对齐 Fass2ActionResolver 的到站动作判定(独立副本,避免引用 Magnetic)。
///
public static class Fass2SimActionResolver
{
public const byte StartStopPass = 1;
public const byte StartStopStop = 2;
public const byte StartStopControlStart = 11;
public const byte StartStopControlStop = 12;
public const byte StartStopPrecision = 22;
public static bool VerifyTrajectoryFields { get; set; }
private static readonly (string Name, Func Get)[] MechanismFields =
{
("Obstacle", n => n.Obstacle),
("Audio", n => n.Audio),
("Light", n => n.Light),
("Charge", n => n.Charge),
("Rest", n => n.Rest),
("Lift", n => n.Lift),
("Clamp", n => n.Clamp),
("Tray", n => n.Tray),
("Roll", n => n.Roll),
("Shutdown", n => n.Shutdown)
};
private static readonly (string Name, Func Get)[] TrajectoryFields =
{
("Direction", n => n.Direction),
("Orientation", n => n.Orientation),
("Byroad", n => n.Byroad)
};
public static bool AllowsAutoContinue(byte startStop)
{
return startStop == StartStopPass || startStop == StartStopControlStart;
}
public static bool RequiresActionWait(Fass2SimNodeMessage expected)
{
if (expected == null)
{
return false;
}
if (expected.StartStop is StartStopStop or StartStopPrecision or StartStopControlStop or StartStopControlStart)
{
return true;
}
foreach (var field in MechanismFields)
{
if (field.Get(expected) != 0)
{
return true;
}
}
if (!VerifyTrajectoryFields)
{
return false;
}
foreach (var field in TrajectoryFields)
{
if (field.Get(expected) != 0)
{
return true;
}
}
return expected.Speed != 0;
}
public static bool IsStationActionComplete(Fass2SimNodeMessage expected, Fass2SimVehicleSnapshot actual, byte vehicleState)
{
if (expected == null || actual == null)
{
return false;
}
if (actual.Node != expected.Node)
{
return false;
}
if (vehicleState is 1 or 5)
{
return false;
}
if (!RequiresActionWait(expected))
{
return true;
}
if (expected.StartStop == StartStopPass)
{
return true;
}
if (expected.StartStop == StartStopControlStop)
{
return false;
}
return ListPendingFields(expected, actual).Count == 0;
}
public static List ListPendingFields(Fass2SimNodeMessage expected, Fass2SimVehicleSnapshot actual)
{
var pending = new List();
if (expected == null || actual == null)
{
return pending;
}
if (expected.StartStop != 0 && actual.StartStop != expected.StartStop)
{
pending.Add("StartStop");
}
if (VerifyTrajectoryFields)
{
if (expected.Speed != 0 && actual.Speed != expected.Speed)
{
pending.Add("Speed");
}
foreach (var field in TrajectoryFields)
{
var expectedValue = field.Get(expected);
if (expectedValue != 0 && GetActualField(actual, field.Name) != expectedValue)
{
pending.Add(field.Name);
}
}
}
foreach (var field in MechanismFields)
{
var expectedValue = field.Get(expected);
if (expectedValue != 0 && GetActualField(actual, field.Name) != expectedValue)
{
pending.Add(field.Name);
}
}
return pending;
}
public static string DescribePending(Fass2SimNodeMessage expected, Fass2SimVehicleSnapshot actual)
{
var pending = ListPendingFields(expected, actual);
return pending.Count == 0 ? string.Empty : string.Join(",", pending);
}
private static byte GetActualField(Fass2SimVehicleSnapshot actual, string name)
{
switch (name)
{
case "Direction": return actual.Direction;
case "Orientation": return actual.Orientation;
case "Byroad": return actual.Byroad;
case "Obstacle": return actual.Obstacle;
case "Audio": return actual.Audio;
case "Light": return actual.Light;
case "Charge": return actual.Charge;
case "Rest": return actual.Rest;
case "Lift": return actual.Lift;
case "Clamp": return actual.Clamp;
case "Tray": return actual.Tray;
case "Roll": return actual.Roll;
case "Shutdown": return actual.Shutdown;
default: return 0;
}
}
}
}