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.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 SchedulerDryerTimeManager: Singleton { #region 内部变量 private ConcurrentDictionary> _dryerScheduleTimeDic = new ConcurrentDictionary>(); #endregion /// /// 按照用量排序 /// /// /// public List ResetModuleOrderByUsed(List modules) { List schedulerModuleUses= new List(); foreach (IModuleEntity module in modules) { SchedulerModuleUse moduleUse = new SchedulerModuleUse(); moduleUse.ModuleName = module.Module; moduleUse.Used = _dryerScheduleTimeDic.ContainsKey(module.Module.ToString()) ? _dryerScheduleTimeDic[module.Module.ToString()].Count : 0; schedulerModuleUses.Add(moduleUse); } List results= schedulerModuleUses.OrderBy(O => O.Used).Select(O => O.ModuleName).ToList(); return results; } /// /// 获取最后的时间轴对象 /// /// /// public SchedulerTime GetLastSchedulerTime(string dryer) { if (_dryerScheduleTimeDic.ContainsKey(dryer)) { List schedulerTimes = _dryerScheduleTimeDic[dryer].OrderBy(O=>O.ScheduleStartTime).ToList(); if (schedulerTimes.Count != 0) { return schedulerTimes.Last(); } else { return null; } } else { return null; } } /// /// 按照计划时间排序 /// /// /// public List ResetModuleOrderBySchedulerEndTime(List modules) { List schedulerModuleUses = new List(); foreach (IModuleEntity module in modules) { SchedulerModuleEndTime moduleEndTime = new SchedulerModuleEndTime(); moduleEndTime.ModuleName = module.Module; if (_dryerScheduleTimeDic.ContainsKey(module.Module.ToString())) { List schedulerTimes = _dryerScheduleTimeDic[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 void AddDryerScheduler(string dryer,string waferHolderId,int schedulerIndex,DateTime schedulerStartTime,int processTimeLength,bool writeDryerLog=true) { if (!_dryerScheduleTimeDic.ContainsKey(dryer)) { SchedulerTime dryerTime = new SchedulerTime(); dryerTime.WaferHolderId = waferHolderId; dryerTime.ScheduleStartTime = schedulerStartTime; dryerTime.ProcessTimeLength = processTimeLength; dryerTime.SchedulerIndex = schedulerIndex; List schedulerDryerTimes = new List(); schedulerDryerTimes.Add(dryerTime); _dryerScheduleTimeDic.TryAdd(dryer, schedulerDryerTimes); } else { List schedulerDryerTimes = _dryerScheduleTimeDic[dryer]; if(schedulerDryerTimes.Find(O=>O.WaferHolderId==waferHolderId&&O.SchedulerIndex==schedulerIndex) == null) { SchedulerTime dryerTime = new SchedulerTime(); dryerTime.WaferHolderId = waferHolderId; dryerTime.ScheduleStartTime = schedulerStartTime; dryerTime.ProcessTimeLength = processTimeLength; dryerTime.SchedulerIndex = schedulerIndex; schedulerDryerTimes.Add(dryerTime); } } if (writeDryerLog) { WriteDryerSchedulerTimeLog(); } LOG.WriteLog(eEvent.INFO_RINSE, dryer, $"add wafer shuttle {waferHolderId} scheduler {schedulerIndex} dryer {dryer} in scheduler time"); } /// /// 写Dryer调度时间轴日志 /// public void WriteDryerSchedulerTimeLog() { List keys = _dryerScheduleTimeDic.Keys.ToList(); foreach (string key in keys) { List schedulerDryerTimes = _dryerScheduleTimeDic[key].OrderBy(O => O.ScheduleStartTime).ToList(); foreach (SchedulerTime item in schedulerDryerTimes) { DateTime startTime = item.ScheduleStartTime; DateTime endTime = startTime.AddSeconds(item.ProcessTimeLength); LOG.WriteLog(eEvent.INFO_DRYER, key, $"wafer shuttle {item.WaferHolderId} scheduler {item.SchedulerIndex} dryer {key} start time {startTime} end time {endTime} processLength {item.ProcessTimeLength} s"); } } } /// /// 更新Dryer实际启动时间 /// /// /// public void UpdateDryerStartTime(string dryer,string waferHolderId,int schedulerIndex,DateTime startTime) { if (_dryerScheduleTimeDic.ContainsKey(dryer)) { List schedulerDryerTimes= _dryerScheduleTimeDic[dryer]; SchedulerTime schedulerDryerTime=schedulerDryerTimes.Find(O=>O.WaferHolderId==waferHolderId&&O.SchedulerIndex==schedulerIndex); if (schedulerDryerTime != null) { schedulerDryerTime.StartTime = startTime; if (schedulerDryerTime.StartTime > schedulerDryerTime.ScheduleStartTime) { LOG.WriteLog(eEvent.INFO_DRYER, dryer, $"wafer shuttle {waferHolderId} scheduler {schedulerIndex} dryer {dryer} start time {startTime} after scheduler start time {schedulerDryerTime.ScheduleStartTime}"); double interSeconds = schedulerDryerTime.StartTime.Subtract(schedulerDryerTime.ScheduleStartTime).TotalSeconds; schedulerDryerTime.ScheduleStartTime = schedulerDryerTime.StartTime; SchedulerMetalTimeManager.Instance.DelayMetalSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds); SchedulerQdrTimeManager.Instance.DelayQdrSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds); DelayDryerSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds); SchedulerTransporterTimeManager.Instance.DelayTransporterSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds); SchedulerWaferHolderTimeManager.Instance.DelayWaferHolderSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds); } LOG.WriteLog(eEvent.INFO_DRYER, dryer, $"update wafer shuttle {waferHolderId} scheduler {schedulerIndex} dryer {dryer} start time {startTime}"); } } } /// /// 延后metal后续时间 /// /// /// /// public void DelayDryerSchedulerStartTime(string waferHolderId, int schedulerIndex, double seconds) { List keys = _dryerScheduleTimeDic.Keys.ToList(); foreach (string key in keys) { List schedulerTimes = _dryerScheduleTimeDic[key]; List postSchedulerTimes = schedulerTimes.FindAll(O => O.WaferHolderId == waferHolderId && O.SchedulerIndex > schedulerIndex); foreach (SchedulerTime schedulerTime in postSchedulerTimes) { schedulerTime.ScheduleStartTime = schedulerTime.ScheduleStartTime.AddSeconds(seconds); } } WriteDryerSchedulerTimeLog(); } /// /// 移除 /// /// public void RemoveDryerStartTime(string dryer,string waferHolderId,int schedulerIndex) { if (_dryerScheduleTimeDic.ContainsKey(dryer)) { List schedulerDryerTimes = _dryerScheduleTimeDic[dryer]; SchedulerTime schedulerDryerTime = schedulerDryerTimes.Find(O => O.WaferHolderId == waferHolderId && O.SchedulerIndex == schedulerIndex); if (schedulerDryerTime != null) { LOG.WriteLog(eEvent.INFO_RINSE, dryer, $"remove wafer shuttle {waferHolderId} scheduler {schedulerIndex} dryer {dryer} in scheduler time"); schedulerDryerTimes.Remove(schedulerDryerTime); } if (schedulerDryerTimes.Count == 0) { _dryerScheduleTimeDic.TryRemove(dryer, out schedulerDryerTimes); LOG.WriteLog(eEvent.INFO_RINSE, dryer, $"delete wafer shuttle {waferHolderId} scheduler {schedulerIndex} dryer {dryer} in scheduler time"); } } } /// /// 检验Dryer是否冲突 /// /// /// /// /// public (bool conflict,string waferHolderId,int schedluerIndex) CheckDryerConflict(string dryer,string waferHolderId, DateTime schedulerStartTime, int processTimeLength) { if (!_dryerScheduleTimeDic.ContainsKey(dryer)) { return (false, "", -1); } List schedulerDryerTimes= _dryerScheduleTimeDic[dryer]; foreach(SchedulerTime item in schedulerDryerTimes) { if (item.WaferHolderId == waferHolderId) { continue; } if (WaferHolderManager.Instance.HasWaferHolder(dryer)) { WaferHolderInfo waferHolderInfo = WaferHolderManager.Instance.GetWaferHolder(dryer); if (waferHolderInfo!=null) { WaferHolderTask waferHolderTask= WaferHolderTaskManager.Instance.GetWaferHolderTaskByWaferHolderId(waferHolderInfo.Id); if (waferHolderTask != null) { return (true, waferHolderInfo.Id, waferHolderTask.GetCurrentSchedulerIndex()); } return (true, "", -1); } return (true, "", -1); } bool result=CheckDryerTimeConflict(item,schedulerStartTime, processTimeLength); if (result) { return (true,item.WaferHolderId,item.SchedulerIndex); } } return (false, "", -1); } /// /// 判定时间是否冲突 /// /// /// /// /// private bool CheckDryerTimeConflict(SchedulerTime schedulerDryerTime, DateTime schedulerStartTime, int processTimeLength) { int transporterTransferSeconds = SC.GetValue("Transporter.TransporterTransferSeconds"); DateTime schedulerEndTime = schedulerStartTime.AddSeconds(processTimeLength); DateTime dryerEndTime = schedulerDryerTime.ScheduleStartTime.AddSeconds(schedulerDryerTime.ProcessTimeLength); DateTime dryerStartTime= schedulerDryerTime.ScheduleStartTime; if (schedulerStartTime > dryerEndTime.AddSeconds(transporterTransferSeconds)) { return false; } if (schedulerEndTime.AddSeconds(transporterTransferSeconds) < dryerStartTime) { return false; } return true; } /// /// 计算Dryer调度预计开始时间 /// /// /// public DateTime CalculateDryerSchedulerStartTime(DateTime dateTime) { int transporterTransferSeconds = SC.GetValue("Transporter.TransporterTransferSeconds"); //Transporter传输时间 return dateTime.AddSeconds(transporterTransferSeconds); } /// /// 清除所有 /// public void RemoveAll() { List keys = _dryerScheduleTimeDic.Keys.ToList(); foreach (string key in keys) { List schedulerTimes = _dryerScheduleTimeDic[key]; schedulerTimes.Clear(); } _dryerScheduleTimeDic.Clear(); LOG.Write(eEvent.INFO_RINSE,"System", "Remove all dryer scheduler time"); } } }