using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Diagnostics; using System.Linq; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using DocumentFormat.OpenXml.Drawing; using ExtendedGrid.Microsoft.Windows.Controls; using MECF.Framework.Common.DataCenter; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Utilities; using MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory; using MECF.Framework.UI.Client.ClientBase.Tree; using OpenSEMI.ClientBase.ServiceProvider; namespace MECF.Framework.UI.Client.CenterViews.Operations.RealTime { public class RealtimeProvider : IProvider { ObservableCollection _rootNode = new ObservableCollection(); Dictionary _indexer = new Dictionary(); public void Clear() { _indexer.Clear(); _rootNode.Clear(); } /// /// 使用字符串队列创建树结构的分支。 /// /// /// private static TreeNode CreateTreeBranch(Queue branchString, TreeNode node) { var rootNode = node; while (true) { if (branchString.Count <= 0) return rootNode; var name = branchString.Dequeue(); if (node == null) { // 根节点 node = new TreeNode(name); rootNode = node; } else { if (node.Name == name) continue; // 向ChildNode插入 var subNode = node.ChildNodes.FirstOrDefault(x => x.Name == name); if (subNode == null) { subNode = new TreeNode(name); node.ChildNodes.Add(subNode); } node = subNode; } } } public void Create() { } public ObservableCollection GetUserDefineParameters() { var typedContents = ((string)QueryDataClient.Instance.Service.GetTypedConfigContent("UserDefine", "")); ObservableCollection dataList = new ObservableCollection(); if (typedContents != null) { var contentList = typedContents.Split(',').ToList(); contentList.ForEach(x => { if (!string.IsNullOrEmpty(x)) dataList.Add($"{x}"); }); } return dataList; } public Dictionary GetSystemDeviceNameDict() { return new Dictionary() { {ModuleName.CarrierRobot.ToString(),ModuleName.Robot.ToString() }, {ModuleName.WaferRobot.ToString(),ModuleName.Robot.ToString() }, {ModuleName.FIMS1.ToString(),ModuleName.FIMS1.ToString() }, {ModuleName.FIMS2.ToString(),ModuleName.FIMS2.ToString() }, {ModuleName.LP1.ToString(),ModuleName.LP1.ToString() }, {ModuleName.LP2.ToString(),ModuleName.LP2.ToString() }, {ModuleName.LP3.ToString(),ModuleName.LP3.ToString() }, {ModuleName.LP4.ToString(),ModuleName.LP4.ToString() }, {ModuleName.Stocker1.ToString(),ModuleName.Stocker1.ToString() }, {ModuleName.Stocker2.ToString(),ModuleName.Stocker2.ToString() }, {ModuleName.Stocker3.ToString(),ModuleName.Stocker3.ToString() }, {ModuleName.Stocker4.ToString(),ModuleName.Stocker4.ToString() }, {ModuleName.Stocker5.ToString(),ModuleName.Stocker5.ToString() }, {ModuleName.Stocker6.ToString(),ModuleName.Stocker6.ToString() }, {ModuleName.Stocker7.ToString(),ModuleName.Stocker7.ToString() }, {ModuleName.Stocker8.ToString(),ModuleName.Stocker8.ToString() }, {ModuleName.Stocker9.ToString(),ModuleName.Stocker9.ToString() }, {ModuleName.Stocker10.ToString(),ModuleName.Stocker10.ToString() }, {ModuleName.Stocker11.ToString(),ModuleName.Stocker11.ToString() }, {ModuleName.Stocker12.ToString(),ModuleName.Stocker12.ToString() }, {ModuleName.Stocker13.ToString(),ModuleName.Stocker13.ToString() }, {ModuleName.Stocker14.ToString(),ModuleName.Stocker14.ToString() }, {ModuleName.Stocker15.ToString(),ModuleName.Stocker15.ToString() }, {ModuleName.Stocker16.ToString(),ModuleName.Stocker16.ToString() }, {ModuleName.Stocker17.ToString(),ModuleName.Stocker17.ToString() }, {ModuleName.Stocker18.ToString(),ModuleName.Stocker18.ToString() }, }; } /// /// 筛选数据库字段 /// /// /// private Dictionary FilterNumericDataList(List dataList, Dictionary displayXmlDict) { //这里包含了项目中注册到数据库中的所有字段,需要从中筛选出来有效字段并归类 Dictionary result = new Dictionary(); var effectiveDataList = dataList.Where(a => a.Split('.').Count() > 1); var pm1DataList = effectiveDataList.Where(a => a.StartsWith(ModuleName.PM1.ToString()) && !displayXmlDict.Keys.Contains(a)).ToDictionary(a => a, a => a); var systemDataList = effectiveDataList.Where(a => a.StartsWith(ModuleName.System.ToString()) && !displayXmlDict.Keys.Contains(a)).ToDictionary(a => a, a => a); result.AddRange(pm1DataList); result.AddRange(systemDataList); var systemDeviceNameDict = GetSystemDeviceNameDict(); foreach (var item in systemDeviceNameDict) { var data = effectiveDataList.Where(a => (a.StartsWith(item.Key))).ToDictionary(a => a, a => $"{item.Value}.{a}"); result.AddRange(data); } return result; } /// /// 获取指定日期数据库PM/System table 列 /// /// /// public List GetDBCol(string dbTableName) { var columnsql = $"select column_name from information_schema.columns where table_name = '{dbTableName}'"; var columnTable = QueryDataClient.Instance.Service.QueryData(columnsql); return columnTable.Rows.Cast().Select(x => x.ItemArray[0].ToString()).ToList(); } /// /// 获取DataHistory 左侧树字典(既包含配置文件字段,也包含PM/System表字段) /// /// public Dictionary GetTreeNameDict() { Dictionary displayDic = QueryDataClient.Instance.Service.GetData("System.Display") as Dictionary; List dataList = (List)QueryDataClient.Instance.Service.GetConfig("System.NumericDataList"); var dataListDict = FilterNumericDataList(dataList, displayDic); displayDic.AddRange(dataListDict); return displayDic; } /// /// 获取ProcessHistory 左侧树结构(不包含PM/System,只根据配置文件字段生成) /// /// /// /// public ObservableCollection GetParameters(out Dictionary processDetailDisplayDic, bool isSelected = false) { processDetailDisplayDic = new Dictionary(); ObservableCollection rootNode = new ObservableCollection(); try { Dictionary displayDic = QueryDataClient.Instance.Service.GetData("System.ProcessDetailDisplay") as Dictionary; if (displayDic == null) return rootNode; List dataList = new List(); foreach (var itemDisplay in displayDic) { string[] keyItems = itemDisplay.Key.Split('.'); string[] valueItems = itemDisplay.Value.Split('.'); if (keyItems != null) { if (keyItems.Length == 2) { var key = $"{valueItems[1]}"; var keyValue = itemDisplay.Key; if (!processDetailDisplayDic.ContainsKey(key)) { processDetailDisplayDic.Add(key, keyValue); } dataList.Add($"{valueItems[0]}.{valueItems[1]}"); } else if (keyItems.Length == 3) { var key = $"{valueItems[1]} {valueItems[2]}"; var keyValue = itemDisplay.Key; if (!processDetailDisplayDic.ContainsKey(key)) { processDetailDisplayDic.Add(key, keyValue); } dataList.Add($"{valueItems[0]}.{valueItems[1]}.{valueItems[2]}"); } } } Dictionary indexer = new Dictionary(); foreach (string dataName in dataList) { string[] nodeName = dataName.Split('.'); ParameterNode parentNode = null; string pathName = ""; for (int i = 0; i < nodeName.Length; i++) { pathName = (i == 0 || i == 1) ? nodeName[i] : (pathName + " " + nodeName[i]); if (!indexer.ContainsKey(pathName)) { indexer[pathName] = new ParameterNode() { Name = pathName, ChildNodes = new ObservableCollection(), ParentNode = parentNode }; if (parentNode == null) { rootNode.Add(indexer[pathName]); } else { parentNode.ChildNodes.Add(indexer[pathName]); } } parentNode = indexer[pathName]; } } SortParameterNode(rootNode, new Dictionary() { { "Heater",0}, { "MFC",1}, { "APC",2}, { "Boat",3}, { "Valve",4} }, isSelected); } catch (Exception ex) { LOG.Write(ex); } return rootNode; } /// /// 获取DataHistory 左侧树结构(既包含配置文件字段,也包含PM/System表字段) /// /// public List GetTreeNodeParameters() { var root = new List(); try { var displayDic = GetTreeNameDict(); foreach (var dataName in displayDic.Values) { var nodeName = new Queue(dataName.Split('.')); if (nodeName.Count <= 0) continue; // 开始创建Tree分支 var rootNode = root.FirstOrDefault(x => x.Name == nodeName.Peek()); var node = CreateTreeBranch(nodeName, rootNode); if (rootNode == null) { root.Add(node); } } SortParameterNode(root, "PM1", 0); SortParameterNode(root, "System", 1); SortParameterNode(root, "Heater", 2); SortParameterNode(root, "MFC", 3); SortParameterNode(root, "APC", 4); SortParameterNode(root, "Boat", 5); SortParameterNode(root, "Valve", 6); } catch (Exception ex) { LOG.Write(ex); } return root; } #region Sort 排序 void SortParameterNode(List rootNode, string Name, int Index) { if (Index >= rootNode.Count) { return; } if (rootNode[Index].Name != Name) { for (int i = 0; i < rootNode.Count; i++) { if (rootNode[i].Name == Name) { TreeNode node = rootNode[i]; rootNode.RemoveAt(i); rootNode.Insert(Index, node); } } } } void SortParameterNode(ObservableCollection rootNode, Dictionary sortDict, bool isSelectd = false) { foreach (var item in sortDict) { SortParameterNode(rootNode, item.Key, item.Value, isSelectd); } } void SortParameterNode(ObservableCollection rootNode, string Name, int Index, bool isSelectd = false) { if (Index >= rootNode.Count) { return; } if (rootNode[Index].Name != Name) { for (int i = 0; i < rootNode.Count; i++) { rootNode[i].Selected = isSelectd; if (rootNode[i].Name == Name) { ParameterNode node = rootNode[i]; rootNode.RemoveAt(i); rootNode.Insert(Index, node); } } } } #endregion public ObservableCollection GetParameterNodeParameters() { try { List dataList = (List)QueryDataClient.Instance.Service.GetConfig("System.NumericDataList"); var typedContents = ((string)QueryDataClient.Instance.Service.GetTypedConfigContent("UserDefine", "")); for (int i = 0; i < dataList.Count; i++) { if (dataList[i].StartsWith("SMIF")) dataList[i] = $"SMIFs.{dataList[i]}"; if (dataList[i].StartsWith("Stocker")) dataList[i] = $"Stockers.{dataList[i]}"; if (dataList[i].StartsWith("Stage")) dataList[i] = $"Stages.{dataList[i]}"; dataList[i] = dataList[i].Replace("PM1", "Tube"); } if (string.IsNullOrEmpty(typedContents)) { dataList.Add($"UserDefine"); } else { var contentList = typedContents.Split(',').ToList(); contentList.ForEach(x => { if (!string.IsNullOrEmpty(x)) dataList.Add($"UserDefine.{x}"); }); } dataList.Sort(); //List removeList = _indexer.Keys.ToList(); foreach (string dataName in dataList) { string[] nodeName = dataName.Split('.'); ParameterNode parentNode = null; string pathName = ""; for (int i = 0; i < nodeName.Length; i++) { pathName = (i == 0) ? nodeName[i] : (pathName + "." + nodeName[i]); //removeList.Remove(pathName); if (!_indexer.ContainsKey(pathName)) { _indexer[pathName] = new ParameterNode() { Name = pathName.Replace("UserDefine.", "").Replace("SMIFs.", "").Replace("Stages.", "") .Replace("Stockers.", ""), ChildNodes = new ObservableCollection(), ParentNode = parentNode }; if (parentNode == null) { _rootNode.Add(_indexer[pathName]); } else { parentNode.ChildNodes.Add(_indexer[pathName]); } } parentNode = _indexer[pathName]; //removeList.Remove(pathName); } } //foreach (var key in removeList) //{ // if (_indexer[key].ParentNode == null) // _rootNode.Remove(_indexer[key]); // else // { // _indexer[key].ParentNode.ChildNodes.Remove(_indexer[key]); // } //} return _rootNode; } catch (Exception ex) { LOG.Write(ex); } #region Test code ObservableCollection result = new ObservableCollection(); ParameterNode node1 = new ParameterNode() { Name = "Para Node 1", Selected = false, ChildNodes = new ObservableCollection() }; ParameterNode node2 = new ParameterNode() { Name = "Para Node 2", Selected = false, ChildNodes = new ObservableCollection() }; ParameterNode node3 = new ParameterNode() { Name = "Para Node 3", Selected = false, ChildNodes = new ObservableCollection() }; for (int i = 0; i < 5; i++) { ParameterNode node = new ParameterNode() { Name = node1.Name + "_" + i.ToString(), Selected = false, ChildNodes = new ObservableCollection() }; node1.ChildNodes.Add(node); } for (int i = 0; i < 3; i++) { ParameterNode node = new ParameterNode() { Name = node2.Name + "_" + i.ToString(), Selected = false, ChildNodes = new ObservableCollection() }; node2.ChildNodes.Add(node); } for (int i = 0; i < 4; i++) { ParameterNode node = new ParameterNode() { Name = node3.Name + "_" + i.ToString(), Selected = false, ChildNodes = new ObservableCollection() }; node3.ChildNodes.Add(node); } result.Add(node1); result.Add(node2); result.Add(node3); return result; #endregion } } public class NameComparer : IComparer { public int Compare(TreeNode x, TreeNode y) { if (x == null || y == null) throw new ArgumentException("Parameters can't be null"); string fileA = x.DisplayName; string fileB = y.DisplayName; char[] arr1 = fileA.ToCharArray(); char[] arr2 = fileB.ToCharArray(); int i = 0, j = 0; while (i < arr1.Length && j < arr2.Length) { if (char.IsDigit(arr1[i]) && char.IsDigit(arr2[j])) { string s1 = "", s2 = ""; while (i < arr1.Length && char.IsDigit(arr1[i])) { s1 += arr1[i]; i++; } while (j < arr2.Length && char.IsDigit(arr2[j])) { s2 += arr2[j]; j++; } if (int.Parse(s1) > int.Parse(s2)) { return 1; } if (int.Parse(s1) < int.Parse(s2)) { return -1; } } else { if (arr1[i] > arr2[j]) { return 1; } if (arr1[i] < arr2[j]) { return -1; } i++; j++; } } if (arr1.Length == arr2.Length) { return 0; } else { return arr1.Length > arr2.Length ? 1 : -1; } } } }