using SimpleCore.PropType; using System; using System.Collections.Generic; using System.Globalization; namespace StandardScene.Magnetic.Tasking { internal static class Fass2SiteFieldReader { public static Fass2SiteActionData Read(Site site) { var data = new Fass2SiteActionData(); if (site?.fields == null) { return data; } data.StartStop = TryReadByte(site.fields, Fass2SiteFields.StartStop); data.Byroad = TryReadByte(site.fields, Fass2SiteFields.Byroad); data.Direction = TryReadByte(site.fields, Fass2SiteFields.Direction); data.Orientation = TryReadByte(site.fields, Fass2SiteFields.Orientation); data.Lift = TryReadByte(site.fields, Fass2SiteFields.Lift); data.Roll = TryReadByte(site.fields, Fass2SiteFields.Roll); data.Charge = TryReadByte(site.fields, Fass2SiteFields.Charge); data.Obstacle = TryReadByte(site.fields, Fass2SiteFields.Obstacle); data.Audio = TryReadByte(site.fields, Fass2SiteFields.Audio); data.Light = TryReadByte(site.fields, Fass2SiteFields.Light); data.Rest = TryReadByte(site.fields, Fass2SiteFields.Rest); data.Clamp = TryReadByte(site.fields, Fass2SiteFields.Clamp); data.Tray = TryReadByte(site.fields, Fass2SiteFields.Tray); data.Shutdown = TryReadByte(site.fields, Fass2SiteFields.Shutdown); data.PrecisionStop = TryReadBool(site.fields, Fass2SiteFields.PrecisionStop); data.WaitMode = TryReadString(site.fields, Fass2SiteFields.WaitMode); data.ControlArea = TryReadString(site.fields, Fass2SiteFields.ControlArea); data.ControlCapacity = TryReadInt(site.fields, Fass2SiteFields.ControlCapacity); data.ControlReleaseStartStop = TryReadByte(site.fields, Fass2SiteFields.ControlReleaseStartStop); if (!data.ControlCapacity.HasValue) { TryFillRegionCapacityFallback(site.fields, data); } return data; } public static string BuildFieldsSignature(IReadOnlyList siteIds, int fromIndex, Func getSite) { if (siteIds == null || siteIds.Count == 0) { return string.Empty; } var parts = new List(siteIds.Count - fromIndex); for (var i = Math.Max(0, fromIndex); i < siteIds.Count; i++) { var site = getSite(siteIds[i]); if (site?.fields == null) { parts.Add($"{siteIds[i]}:"); continue; } var keys = new List(); foreach (var pair in site.fields) { if (pair.Key.StartsWith("Fass2_", StringComparison.OrdinalIgnoreCase) || pair.Key.Equals(Fass2SiteFields.TagValue, StringComparison.OrdinalIgnoreCase)) { keys.Add($"{pair.Key}={pair.Value}"); } } keys.Sort(StringComparer.OrdinalIgnoreCase); parts.Add($"{siteIds[i]}:{string.Join("|", keys)}"); } return string.Join(";", parts); } private static byte? TryReadByte(Dictionary fields, string key) { if (!fields.TryGetValue(key, out var text) || string.IsNullOrWhiteSpace(text)) { return null; } if (byte.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) { return value; } return null; } private static bool TryReadBool(Dictionary fields, string key) { if (!fields.TryGetValue(key, out var text) || string.IsNullOrWhiteSpace(text)) { return false; } return bool.TryParse(text, out var value) && value || text == "1" || string.Equals(text, "true", StringComparison.OrdinalIgnoreCase); } private static string TryReadString(Dictionary fields, string key) { return fields.TryGetValue(key, out var text) ? text : null; } private static int? TryReadInt(Dictionary fields, string key) { if (!fields.TryGetValue(key, out var text) || string.IsNullOrWhiteSpace(text)) { return null; } if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) { return value; } return null; } private static void TryFillRegionCapacityFallback(Dictionary fields, Fass2SiteActionData data) { foreach (var pair in fields) { if (string.IsNullOrEmpty(pair.Key) || !pair.Key.StartsWith("Region", StringComparison.OrdinalIgnoreCase)) { continue; } if (int.TryParse(pair.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var maxCount) && maxCount > 0) { data.ControlCapacity = maxCount; } return; } } } }