using MainShell.Common; using MainShell.Filewritable; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace MainShell.Process { public class WaferHandlingFlowNodeRule { public string Key { get; set; } public string DisplayName { get; set; } public List ActivityKeywords { get; set; } = new List(); public List WorkflowKeywords { get; set; } = new List(); public List ParentKeywords { get; set; } = new List(); } public class WaferHandlingFlowConfig { public List Nodes { get; } = new List(); public static string DefaultConfigPath => Path.Combine(Paths.BasePath, "Configuration", "WaferHandlingFlow.json"); public static WaferHandlingFlowConfig LoadOrCreate(string filePath = null) { var path = string.IsNullOrWhiteSpace(filePath) ? DefaultConfigPath : filePath; var dir = Path.GetDirectoryName(path); if (!string.IsNullOrWhiteSpace(dir)) { Directory.CreateDirectory(dir); } if (!File.Exists(path)) { var def = CreateDefault(); def.Save(path); return def; } try { var loaded = Load(path); if (loaded == null || loaded.Nodes.Count == 0) { throw new InvalidDataException("WaferHandlingFlow config is empty."); } loaded.Normalize(); return loaded; } catch { var def = CreateDefault(); def.Save(path); return def; } } public static WaferHandlingFlowConfig Load(string filePath) { var json = File.ReadAllText(filePath); var data = JsonConvert.DeserializeObject(json); var cfg = new WaferHandlingFlowConfig(); if (data?.Nodes != null) { cfg.Nodes.AddRange(data.Nodes); } cfg.Normalize(); return cfg; } public void Save(string filePath = null) { var path = string.IsNullOrWhiteSpace(filePath) ? DefaultConfigPath : filePath; Normalize(); var data = new WaferHandlingFlowFile { Nodes = Nodes.ToList() }; var json = JsonConvert.SerializeObject(data, Formatting.Indented); File.WriteAllText(path, json); } public string ResolveNodeKey(string workflowName, string parentActivityName, string activityName) { var activity = activityName ?? string.Empty; var workflow = workflowName ?? string.Empty; var parent = parentActivityName ?? string.Empty; var rule = Nodes.FirstOrDefault(n => IsMatch(n, activity, workflow, parent)); return rule?.Key; } private static bool IsMatch(WaferHandlingFlowNodeRule node, string activity, string workflow, string parent) { if (node == null) return false; return ContainsAny(activity, node.ActivityKeywords) || ContainsAny(workflow, node.WorkflowKeywords) || ContainsAny(parent, node.ParentKeywords); } private static bool ContainsAny(string source, List keywords) { if (keywords == null || keywords.Count == 0) return false; foreach (var keyword in keywords) { if (string.IsNullOrWhiteSpace(keyword)) continue; if ((source ?? string.Empty).IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private void Normalize() { Nodes.RemoveAll(n => n == null || string.IsNullOrWhiteSpace(n.Key)); foreach (var node in Nodes) { if (string.IsNullOrWhiteSpace(node.DisplayName)) { node.DisplayName = node.Key; } node.ActivityKeywords = node.ActivityKeywords ?? new List(); node.WorkflowKeywords = node.WorkflowKeywords ?? new List(); node.ParentKeywords = node.ParentKeywords ?? new List(); } } public static WaferHandlingFlowConfig CreateDefault() { var cfg = new WaferHandlingFlowConfig(); cfg.Nodes.Add(new WaferHandlingFlowNodeRule { Key = "WaferLoad", DisplayName = "晶圆上料", ActivityKeywords = new List { "ChipLoad", ProcessFlowName.ChipLoadExecuteActivity } }); cfg.Nodes.Add(new WaferHandlingFlowNodeRule { Key = "WaferSupply", DisplayName = "晶片准备", WorkflowKeywords = new List { ProcessFlowName.ChipStraighteningFlow, ProcessFlowName.DiePositionFlow, ProcessFlowName.DieTransferFlow, ProcessFlowName.DieRecheckFlow }, ParentKeywords = new List { "DieAlign", "DieBond", "Inspect" } }); cfg.Nodes.Add(new WaferHandlingFlowNodeRule { Key = "WaferUnload", DisplayName = "晶圆下料", ActivityKeywords = new List { "ChipUnload", ProcessFlowName.ChipUnloadExecuteActivity } }); return cfg; } public class WaferHandlingFlowFile { public List Nodes { get; set; } = new List(); } } }