using Aitex.Core.RT.Fsm; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using CyberX8_RT.Dispatch; using CyberX8_RT.Modules.Metal; using CyberX8_RT.Modules.Rinse; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.WaferHolder; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CyberX8_RT.Schedulers { public class SchedulerMetalTimeManager: Singleton { #region 内部变量 private ConcurrentDictionary> _metalScheduleTimeDic = new ConcurrentDictionary>(); #endregion /// /// 重置 /// /// /// public List ResetModuleOrder(List modules) { List schedulerModuleUses = new List(); foreach (IModuleEntity module in modules) { SchedulerModuleUse moduleUse = new SchedulerModuleUse(); moduleUse.ModuleName = module.Module; moduleUse.Used = _metalScheduleTimeDic.ContainsKey(module.Module.ToString()) ? _metalScheduleTimeDic[module.Module.ToString()].Count : 0; schedulerModuleUses.Add(moduleUse); } List results = schedulerModuleUses.OrderBy(O => O.Used).Select(O => O.ModuleName).ToList(); return results; } /// /// 计算Metal已经使用次数 /// /// /// /// public int CalculateMetalUsed(string metal,SchedulerModulePartTime metalPartTime) { int usedCount = _metalScheduleTimeDic.ContainsKey(metal) ? _metalScheduleTimeDic[metal].Count : 0; return metalPartTime.GetModuleUsedCount(metal) + usedCount; } /// /// 按照计划时间排序 /// /// /// public List ResetModuleOrderBySchedulerEndTime(List modules) { List schedulerModuleUses = new List(); foreach (IModuleEntity module in modules) { SchedulerModuleEndTime moduleEndTime = new SchedulerModuleEndTime(); moduleEndTime.ModuleName = module.Module; if (_metalScheduleTimeDic.ContainsKey(module.Module.ToString())) { List schedulerTimes = _metalScheduleTimeDic[module.Module.ToString()].OrderBy(O=>O.ScheduleStartTime).ToList(); SchedulerTime lastSchedulerTime = schedulerTimes.Last(); DateTime lastSchedulerEndTime = lastSchedulerTime.ScheduleStartTime.AddSeconds(lastSchedulerTime.ProcessTimeLength); moduleEndTime.SchedulerEndTime = lastSchedulerEndTime; } else { moduleEndTime.SchedulerEndTime = DateTime.MinValue; } schedulerModuleUses.Add(moduleEndTime); } List results = schedulerModuleUses.OrderBy(O => O.SchedulerEndTime).Select(O => O.ModuleName).ToList(); return results; } /// /// 获取最后的时间轴对象 /// /// /// public SchedulerTime GetLastSchedulerTime(string metal) { if (_metalScheduleTimeDic.ContainsKey(metal)) { List schedulerTimes = _metalScheduleTimeDic[metal].OrderBy(O=>O.ScheduleStartTime).ToList(); if (schedulerTimes.Count != 0) { return schedulerTimes.Last(); } else { return null; } } else { return null; } } /// /// 增加 /// /// /// /// /// public void AddMetalScheduler(string metal,string waferHolderId,int schedulerIndex,DateTime schedulerStartTime,int processTimeLength,bool writeMetalLog=true) { if (!_metalScheduleTimeDic.ContainsKey(metal)) { SchedulerTime metalTime = new SchedulerTime(); metalTime.WaferHolderId = waferHolderId; metalTime.ScheduleStartTime = schedulerStartTime; metalTime.ProcessTimeLength = processTimeLength; metalTime.SchedulerIndex = schedulerIndex; List schedulerMetalTimes = new List(); schedulerMetalTimes.Add(metalTime); _metalScheduleTimeDic.TryAdd(metal, schedulerMetalTimes); } else { List schedulerMetalTimes = _metalScheduleTimeDic[metal]; if(schedulerMetalTimes.Find(O=>O.WaferHolderId==waferHolderId&&O.SchedulerIndex==schedulerIndex) == null) { SchedulerTime metalTime = new SchedulerTime(); metalTime.WaferHolderId = waferHolderId; metalTime.ScheduleStartTime = schedulerStartTime; metalTime.ProcessTimeLength = processTimeLength; metalTime.SchedulerIndex = schedulerIndex; schedulerMetalTimes.Add(metalTime); } } if (writeMetalLog) { WriteMetalSchedulerTimeLog(); } LOG.WriteLog(eEvent.INFO_METAL, metal, $"add wafer shuttle {waferHolderId} scheduler {schedulerIndex} metal {metal} in scheduler time"); } /// /// 写Metal调度时间轴日志 /// public void WriteMetalSchedulerTimeLog() { List keys = _metalScheduleTimeDic.Keys.ToList(); foreach (string key in keys) { List schedulerMetalTimes = _metalScheduleTimeDic[key].OrderBy(O=>O.ScheduleStartTime).ToList(); foreach (SchedulerTime item in schedulerMetalTimes) { DateTime startTime = item.ScheduleStartTime; DateTime endTime = startTime.AddSeconds(item.ProcessTimeLength); LOG.WriteLog(eEvent.INFO_METAL, key, $"wafer shuttle {item.WaferHolderId} scheduler {item.SchedulerIndex} metal {key} start time {startTime} end time {endTime} processLength {item.ProcessTimeLength} s"); } } } /// /// 更新Metal实际启动时间 /// /// /// public void UpdateMetalStartTime(string metal,string waferHolderId,int schedulerIndex,DateTime startTime) { if (_metalScheduleTimeDic.ContainsKey(metal)) { List schedulerMetalTimes= _metalScheduleTimeDic[metal]; SchedulerTime schedulerMetalTime=schedulerMetalTimes.Find(O=>O.WaferHolderId==waferHolderId&&O.SchedulerIndex==schedulerIndex); if (schedulerMetalTime != null) { schedulerMetalTime.StartTime = startTime; if (schedulerMetalTime.StartTime > schedulerMetalTime.ScheduleStartTime) { LOG.WriteLog(eEvent.INFO_METAL, metal, $"wafer shuttle {waferHolderId} scheduler {schedulerIndex} metal {metal} start time {startTime} after scheduler start time {schedulerMetalTime.ScheduleStartTime}"); double interSeconds = schedulerMetalTime.StartTime.Subtract(schedulerMetalTime.ScheduleStartTime).TotalSeconds; schedulerMetalTime.ScheduleStartTime = schedulerMetalTime.StartTime; DelayMetalSchedulerStartTime(waferHolderId,schedulerIndex, interSeconds); SchedulerQdrTimeManager.Instance.DelayQdrSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds); SchedulerDryerTimeManager.Instance.DelayDryerSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds); SchedulerTransporterTimeManager.Instance.DelayTransporterSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds); SchedulerWaferHolderTimeManager.Instance.DelayWaferHolderSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds); } LOG.WriteLog(eEvent.INFO_METAL, metal, $"update wafer shuttle {waferHolderId} scheduler {schedulerIndex} metal {metal} start time {startTime}"); } } } /// /// 延后metal后续时间 /// /// /// /// public void DelayMetalSchedulerStartTime(string waferHolderId,int schedulerIndex,double seconds) { List keys = _metalScheduleTimeDic.Keys.ToList(); foreach(string key in keys) { List schedulerTimes= _metalScheduleTimeDic[key]; List postSchedulerTimes= schedulerTimes.FindAll(O => O.WaferHolderId == waferHolderId && O.SchedulerIndex > schedulerIndex); foreach(SchedulerTime schedulerTime in postSchedulerTimes) { schedulerTime.ScheduleStartTime=schedulerTime.ScheduleStartTime.AddSeconds(seconds); } } } /// /// 是否为第一个Metal /// /// /// /// private bool IsFirstMetal(string waferHolderId,int scheduleIndex) { WaferHolderTask task = WaferHolderTaskManager.Instance.GetWaferHolderTaskByWaferHolderId(waferHolderId); if (task == null) { return false; } for(int i = 0; i < task.SchedulerSequences.Count; i++) { SchedulerSequence sequence=task.SchedulerSequences[i]; if (sequence.ModuleType == ModuleType.Metal&&scheduleIndex==i) { return true; } } return false; } /// /// 移除 /// /// public void RemoveMetalStartTime(string metal,string waferHolderId,int schedulerIndex) { if (_metalScheduleTimeDic.ContainsKey(metal)) { List schedulerMetalTimes = _metalScheduleTimeDic[metal]; SchedulerTime schedulerMetalTime = schedulerMetalTimes.Find(O => O.WaferHolderId == waferHolderId && O.SchedulerIndex == schedulerIndex); if (schedulerMetalTime != null) { LOG.WriteLog(eEvent.INFO_RINSE, metal, $"remove wafer shuttle {waferHolderId} scheduler {schedulerIndex} metal {metal} in scheduler time"); schedulerMetalTimes.Remove(schedulerMetalTime); } if (schedulerMetalTimes.Count == 0) { _metalScheduleTimeDic.TryRemove(metal, out schedulerMetalTimes); LOG.WriteLog(eEvent.INFO_METAL, metal, $"delete wafer shuttle {waferHolderId} scheduler {schedulerIndex} metal {metal} in scheduler time"); } } } /// /// 检验Metal是否冲突 /// /// /// /// /// public (bool conflict,string waferHolderId,int schedluerIndex) CheckMetalConflict(string metal,string waferHolderId, DateTime schedulerStartTime, int processTimeLength) { if (!_metalScheduleTimeDic.ContainsKey(metal)) { return (false, "", -1); } List schedulerMetalTimes= _metalScheduleTimeDic[metal]; foreach(SchedulerTime item in schedulerMetalTimes) { if (item.WaferHolderId == waferHolderId) { continue; } //if (WaferHolderManager.Instance.HasWaferHolder(metal)) //{ // WaferHolderInfo waferHolderInfo = WaferHolderManager.Instance.GetWaferHolder(metal); // if (waferHolderInfo==null) // { // return (true, "", -1); // } // WaferHolderTask waferHolderTask= WaferHolderTaskManager.Instance.GetWaferHolderTaskByWaferHolderId(waferHolderInfo.Id); // if (waferHolderTask != null) // { // return (true, waferHolderInfo.Id, waferHolderTask.GetCurrentSchedulerIndex()); // } // return (true, "", -1); //} bool result=CheckMetalTimeConflict(item,schedulerStartTime, processTimeLength); if (result) { return (true,item.WaferHolderId,item.SchedulerIndex); } } return (false, "", -1); } /// /// 判定时间是否冲突 /// /// /// /// /// private bool CheckMetalTimeConflict(SchedulerTime schedulerMetalTime, DateTime schedulerStartTime, int processTimeLength) { int transporterTransferSeconds = SC.GetValue("Transporter.TransporterTransferSeconds"); DateTime schedulerEndTime = schedulerStartTime.AddSeconds(processTimeLength); DateTime metalEndTime = schedulerMetalTime.ScheduleStartTime.AddSeconds(schedulerMetalTime.ProcessTimeLength); DateTime metalStartTime= schedulerMetalTime.ScheduleStartTime; if (schedulerStartTime > metalEndTime.AddSeconds(transporterTransferSeconds)) { return false; } if (schedulerEndTime.AddSeconds(transporterTransferSeconds) < metalStartTime) { return false; } return true; } /// /// 清除所有 /// public void RemoveAll() { List keys = _metalScheduleTimeDic.Keys.ToList(); foreach (string key in keys) { List schedulerTimes = _metalScheduleTimeDic[key]; schedulerTimes.Clear(); } _metalScheduleTimeDic.Clear(); LOG.Write(eEvent.INFO_RINSE,"System", "Remove all metal scheduler time"); } /// /// 计算数量 /// /// /// public DateTime CalculateSchedulerEndTime(string metal) { if (_metalScheduleTimeDic.ContainsKey(metal)) { DateTime dateTime = DateTime.MinValue; foreach(var item in _metalScheduleTimeDic[metal]) { DateTime startTime = item.ScheduleStartTime; if (startTime.AddSeconds(item.ProcessTimeLength) > dateTime) { dateTime= startTime.AddSeconds(item.ProcessTimeLength); } } return dateTime; } else { return DateTime.MinValue; } } /// /// 是否包含 /// /// /// public bool ContainedMetal(string metal) { return _metalScheduleTimeDic.ContainsKey(metal); } } }