210 lines
7.3 KiB
C#
210 lines
7.3 KiB
C#
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.IO;
|
||
|
|
using System.Linq;
|
||
|
|
using System.Text;
|
||
|
|
|
||
|
|
namespace MainShell.DeviceMaintance.Model
|
||
|
|
{
|
||
|
|
public static class CylinderDefinitionLoader
|
||
|
|
{
|
||
|
|
private const string CylinderConfigFileName = "CylinderDefinitions.csv";
|
||
|
|
|
||
|
|
public static IReadOnlyList<CylinderDefinition> LoadDefinitions()
|
||
|
|
{
|
||
|
|
var definitions = new List<CylinderDefinition>();
|
||
|
|
var path = ResolveConfigPath();
|
||
|
|
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
|
||
|
|
{
|
||
|
|
return definitions;
|
||
|
|
}
|
||
|
|
|
||
|
|
var lines = File.ReadAllLines(path, Encoding.UTF8);
|
||
|
|
foreach (var raw in lines)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(raw))
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
var line = raw.Trim();
|
||
|
|
if (line.StartsWith("#") || line.StartsWith("Name", StringComparison.OrdinalIgnoreCase))
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
var cols = line.Split(',');
|
||
|
|
if (cols.Length < 7)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
var extendOutputPoints = ParsePointReferences(cols[3]);
|
||
|
|
if (extendOutputPoints.Count == 0)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
var retractOutputPoints = ParsePointReferences(cols[4]);
|
||
|
|
|
||
|
|
var hasConditionColumns = cols.Length >= 10;
|
||
|
|
var extendConditionIndex = hasConditionColumns ? 7 : -1;
|
||
|
|
var retractConditionIndex = hasConditionColumns ? 8 : -1;
|
||
|
|
var descriptionIndex = hasConditionColumns ? 9 : 7;
|
||
|
|
|
||
|
|
definitions.Add(new CylinderDefinition
|
||
|
|
{
|
||
|
|
Name = cols[0].Trim(),
|
||
|
|
Module = cols[1].Trim(),
|
||
|
|
ControlType = ParseControlType(cols[2]),
|
||
|
|
ExtendOutputPoints = extendOutputPoints,
|
||
|
|
RetractOutputPoints = retractOutputPoints,
|
||
|
|
ExtendedFeedbackPoints = ParsePointReferences(cols[5]),
|
||
|
|
RetractedFeedbackPoints = ParsePointReferences(cols[6]),
|
||
|
|
ExtendConditions = extendConditionIndex >= 0 ? ParseConditions(cols[extendConditionIndex]) : new List<CylinderActionConditionDefinition>(),
|
||
|
|
RetractConditions = retractConditionIndex >= 0 ? ParseConditions(cols[retractConditionIndex]) : new List<CylinderActionConditionDefinition>(),
|
||
|
|
Description = cols.Length > descriptionIndex ? string.Join(",", cols.Skip(descriptionIndex)).Trim() : string.Empty
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return definitions;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static CylinderControlType ParseControlType(string raw)
|
||
|
|
{
|
||
|
|
if (string.Equals(raw, "DualOutput", StringComparison.OrdinalIgnoreCase) ||
|
||
|
|
string.Equals(raw, "Dual", StringComparison.OrdinalIgnoreCase))
|
||
|
|
{
|
||
|
|
return CylinderControlType.DualOutput;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (string.Equals(raw, "MultiOutput", StringComparison.OrdinalIgnoreCase) ||
|
||
|
|
string.Equals(raw, "Multi", StringComparison.OrdinalIgnoreCase))
|
||
|
|
{
|
||
|
|
return CylinderControlType.MultiOutput;
|
||
|
|
}
|
||
|
|
|
||
|
|
return CylinderControlType.SingleOutput;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static List<string> ParsePointReferences(string raw)
|
||
|
|
{
|
||
|
|
return (raw ?? string.Empty)
|
||
|
|
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
|
||
|
|
.Select(x => x.Trim())
|
||
|
|
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||
|
|
.ToList();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static List<CylinderActionConditionDefinition> ParseConditions(string raw)
|
||
|
|
{
|
||
|
|
return (raw ?? string.Empty)
|
||
|
|
.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
|
||
|
|
.Select(ParseCondition)
|
||
|
|
.Where(x => x != null)
|
||
|
|
.ToList();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static CylinderActionConditionDefinition ParseCondition(string raw)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(raw))
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
var parts = raw.Split(new[] { ':' }, 3);
|
||
|
|
if (parts.Length < 2)
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
var pointReference = parts[1].Trim();
|
||
|
|
if (string.IsNullOrWhiteSpace(pointReference))
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
CylinderConditionType conditionType;
|
||
|
|
switch ((parts[0] ?? string.Empty).Trim().ToUpperInvariant())
|
||
|
|
{
|
||
|
|
case "POINTON":
|
||
|
|
case "ON":
|
||
|
|
conditionType = CylinderConditionType.PointOn;
|
||
|
|
break;
|
||
|
|
case "POINTOFF":
|
||
|
|
case "OFF":
|
||
|
|
conditionType = CylinderConditionType.PointOff;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
return new CylinderActionConditionDefinition
|
||
|
|
{
|
||
|
|
ConditionType = conditionType,
|
||
|
|
PointReference = pointReference,
|
||
|
|
Message = parts.Length > 2 ? parts[2].Trim() : string.Empty
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
private static string ResolveConfigPath()
|
||
|
|
{
|
||
|
|
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
|
||
|
|
var localPath = Path.Combine(baseDir, "Configuration", CylinderConfigFileName);
|
||
|
|
var sourcePath = ResolveRootConfigPath(baseDir);
|
||
|
|
|
||
|
|
if (TrySyncConfigToLocal(sourcePath, localPath))
|
||
|
|
{
|
||
|
|
return localPath;
|
||
|
|
}
|
||
|
|
|
||
|
|
return File.Exists(localPath) ? localPath : sourcePath;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static string ResolveRootConfigPath(string baseDir)
|
||
|
|
{
|
||
|
|
var current = new DirectoryInfo(baseDir);
|
||
|
|
while (current != null)
|
||
|
|
{
|
||
|
|
var rootConfigDir = Path.Combine(current.FullName, "Configuration");
|
||
|
|
if (Directory.Exists(rootConfigDir) && Directory.Exists(Path.Combine(current.FullName, "MainShell")))
|
||
|
|
{
|
||
|
|
var path = Path.Combine(rootConfigDir, CylinderConfigFileName);
|
||
|
|
if (File.Exists(path))
|
||
|
|
{
|
||
|
|
return path;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
current = current.Parent;
|
||
|
|
}
|
||
|
|
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool TrySyncConfigToLocal(string sourcePath, string localPath)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(sourcePath) || !File.Exists(sourcePath))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!string.Equals(Path.GetFullPath(sourcePath), Path.GetFullPath(localPath), StringComparison.OrdinalIgnoreCase))
|
||
|
|
{
|
||
|
|
var localDir = Path.GetDirectoryName(localPath);
|
||
|
|
if (!string.IsNullOrWhiteSpace(localDir))
|
||
|
|
{
|
||
|
|
Directory.CreateDirectory(localDir);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!File.Exists(localPath) || File.GetLastWriteTimeUtc(localPath) < File.GetLastWriteTimeUtc(sourcePath))
|
||
|
|
{
|
||
|
|
File.Copy(sourcePath, localPath, true);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|