SchedulerSequenceManager.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. using MECF.Framework.Common.RecipeCenter;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using MECF.Framework.Common.Equipment;
  8. using MECF.Framework.Common.Schedulers;
  9. using Aitex.Core.Common;
  10. using MECF.Framework.Common.CommonData;
  11. using System.Windows;
  12. using Aitex.Core.RT.IOCore;
  13. using Aitex.Core.RT.Log;
  14. using Aitex.Core.Util;
  15. using MECF.Framework.Common.Routine;
  16. using PunkHPX8_RT.Modules;
  17. using Aitex.Core.RT.Fsm;
  18. using PunkHPX8_RT.Modules.Dummy;
  19. using MECF.Framework.Common.SubstrateTrackings;
  20. using MECF.Framework.Common.ToolLayout;
  21. using MECF.Framework.RT.Core.Equipments;
  22. using MECF.Framework.Common.ProcessCell;
  23. using SecsGem.Core.ItemModel;
  24. using PunkHPX8_RT.Modules.Transporter;
  25. using PunkHPX8_Core;
  26. using Aitex.Core.RT.SCCore;
  27. using PunkHPX8_RT.Modules.SRD;
  28. using PunkHPX8_RT.Devices.EFEM;
  29. namespace PunkHPX8_RT.Schedulers
  30. {
  31. public class SchedulerSequenceManager : Singleton<SchedulerSequenceManager>
  32. {
  33. #region 常量
  34. private const string ENGINEERING = "Engineering";
  35. private const string PRODUCTION = "Production";
  36. private const string TRNPA = "TRNPA";
  37. private const string TRNPB = "TRNPB";
  38. #endregion
  39. /// <summary>
  40. /// 解析LoaderTransporter放至Loader第一次确定TRNP的方向
  41. /// </summary>
  42. /// <param name="sequenceRecipe"></param>
  43. /// <param name="waferCount"></param>
  44. /// <returns></returns>
  45. private string AnalyseLoadTransporterSide(SequenceRecipe sequenceRecipe,int productWaferCount,int dummyWaferCount)
  46. {
  47. //单片,同时loader两边尺寸不一致
  48. if ((productWaferCount == 1||dummyWaferCount==1) )
  49. {
  50. //recipe使用B面工艺,但loader A面与recipe尺寸一致
  51. if (sequenceRecipe.LastSingleWaferToSideB )
  52. {
  53. return "TRNPB";
  54. }
  55. //recipe使用A面工艺,但loader B面与recipe尺寸一致
  56. else if (!sequenceRecipe.LastSingleWaferToSideB)
  57. {
  58. return "TRNPB";
  59. }
  60. }
  61. return "TRNPA";
  62. }
  63. private string GetReverseTransporterLocation(string strTrn)
  64. {
  65. return strTrn == TRNPA ? TRNPB : TRNPA;
  66. }
  67. /// <summary>
  68. /// 检验Loader两边waferSize不一致
  69. /// </summary>
  70. /// <returns></returns>
  71. private bool CheckLoaderWaferSizeNotEqual()
  72. {
  73. return false;
  74. }
  75. /// <summary>
  76. /// 创建LoaderTrasporter同步模块消息
  77. /// </summary>
  78. /// <param name="tranporter"></param>
  79. /// <returns></returns>
  80. private List<SchedulerSyncModuleMessage> GenerateLoaderTransporterSyncModuleMessage(string tranporter)
  81. {
  82. List<SchedulerSyncModuleMessage> synModules = new List<SchedulerSyncModuleMessage>();
  83. SchedulerSyncModuleMessage syncModuleMessage = new SchedulerSyncModuleMessage();
  84. syncModuleMessage.ModuleEntity = Singleton<RouteManager>.Instance.GetModule<IModuleEntity>(ModuleName.Loader1.ToString());
  85. syncModuleMessage.parameters = new object[] { tranporter };
  86. synModules.Add(syncModuleMessage);
  87. return synModules;
  88. }
  89. /// <summary>
  90. /// 解析Dummy Wafer所有调度工序
  91. /// </summary>
  92. /// <param name="sequenceRecipe"></param>
  93. /// <returns></returns>
  94. public List<SchedulerSequence> AnalyDummyWaferAllSchedulerSequence(SequenceRecipe sequenceRecipe,WaferInfo waferInfo, ModuleName pufModule,string side)
  95. {
  96. waferInfo.LoaderSide = side;
  97. List<SchedulerSequence> schedulerSequences = new List<SchedulerSequence>();
  98. int index = 0;
  99. //DummyCassete至Aligner
  100. MoveItem moveItem = new MoveItem((ModuleName)waferInfo.Station, waferInfo.Slot, ModuleName.Aligner1, 0, Aitex.Sorter.Common.Hand.Blade1);
  101. SchedulerSequence secondEfemRobotSequence = CreateEfemRobotSequence(moveItem, null,sequenceRecipe.SubstrateSize, ref index);
  102. schedulerSequences.Add(secondEfemRobotSequence);
  103. //Aligner
  104. SchedulerSequence alignerSequence = alignerSequence=CreateAlignerSequence(sequenceRecipe, ref index);
  105. schedulerSequences.Add(alignerSequence);
  106. //Aligner至Puf
  107. MoveItem alignerToPufMoveItem = new MoveItem(ModuleName.Aligner1, 0, pufModule, 1, Aitex.Sorter.Common.Hand.Blade1);
  108. SchedulerSequence alignerToPufEfemRobotSequence = CreateEfemRobotSequence(alignerToPufMoveItem, null,sequenceRecipe.SubstrateSize, ref index);
  109. schedulerSequences.Add(alignerToPufEfemRobotSequence);
  110. SchedulerSequence pufSequence = CreatePufSequence(pufModule,sequenceRecipe, side,true, ref index);
  111. schedulerSequences.Add(pufSequence);
  112. return schedulerSequences;
  113. }
  114. /// <summary>
  115. /// 分析Sequence recipe对应的调度步骤
  116. /// </summary>
  117. /// <param name="sequenceRecipe"></param>
  118. /// <returns></returns>
  119. private List<SchedulerSequence> AnalyseSequenceRecipeScheduler(SequenceRecipe sequenceRecipe)
  120. {
  121. List<SchedulerSequence> schedulerSequences= new List<SchedulerSequence>();
  122. List<SchedulerSequence> tmpLst = new List<SchedulerSequence>();
  123. var processResult = AnalyseLastProcessRecipeIndex(sequenceRecipe.Recipes);
  124. bool isExistSrd = sequenceRecipe.Recipes.FindIndex(O=>O.ToLower().EndsWith("srd.rcp"))!=-1;
  125. int lastIndex = isExistSrd ? sequenceRecipe.Recipes.Count - 2 : sequenceRecipe.Recipes.Count - 1;
  126. for(int i=0;i<sequenceRecipe.Recipes.Count;i++)
  127. {
  128. string item = sequenceRecipe.Recipes[i];
  129. if(item.ToLower().EndsWith("srd.rcp"))//跳过SRD
  130. {
  131. continue;
  132. }
  133. SchedulerSequence schedulerSequence = new SchedulerSequence();
  134. if (i == 0 && item.ToLower().EndsWith("qdr.rcp"))
  135. {
  136. RinseItem rinsePwtItem = RinseItemManager.Instance.GetPrewetRinseItem();
  137. if (rinsePwtItem != null)
  138. {
  139. schedulerSequence.ModuleName = (ModuleName)Enum.Parse(typeof(ModuleName), rinsePwtItem.ModuleName);
  140. schedulerSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(schedulerSequence.ModuleName);
  141. }
  142. else
  143. {
  144. schedulerSequence.ModuleName = ModuleName.Unknown;
  145. }
  146. }
  147. else
  148. {
  149. schedulerSequence.ModuleName = ModuleName.Unknown;
  150. }
  151. schedulerSequence.ModuleType=SequenceRecipeManager.Instance.GetModuleType(item);
  152. schedulerSequence.SequenceIndex=i;
  153. schedulerSequence.WaferSize = sequenceRecipe.SubstrateSize;
  154. MECF.Framework.Common.RecipeCenter.RecipeType recipeType =SequenceRecipeManager.Instance.GetRecipeType(item);
  155. schedulerSequence.Recipe = SequenceRecipeManager.Instance.LoadSequenceTypeRecipe(sequenceRecipe.SequenceType,item, recipeType);
  156. schedulerSequence.SequenceType = sequenceRecipe.SequenceType;
  157. schedulerSequence.State = RState.Init;
  158. schedulerSequence.MaterialType = MaterialType.WaferHolder;
  159. tmpLst.Add(schedulerSequence);
  160. if (i != lastIndex)
  161. {
  162. string nextModule = sequenceRecipe.Recipes[i + 1];
  163. schedulerSequence.NextModuleType = SequenceRecipeManager.Instance.GetModuleType(nextModule);
  164. MECF.Framework.Common.RecipeCenter.RecipeType nextRecipeType = SequenceRecipeManager.Instance.GetRecipeType(nextModule);
  165. schedulerSequence.NextRecipe = SequenceRecipeManager.Instance.LoadSequenceTypeRecipe(sequenceRecipe.SequenceType, nextModule, nextRecipeType);
  166. }
  167. schedulerSequence.IsProcessSequece = true;
  168. if(i==processResult.lastIndex)
  169. {
  170. schedulerSequence.IsLastProcessSequence = true;
  171. }
  172. }
  173. int index = 0;
  174. for(int i=0;i<tmpLst.Count;i++)
  175. {
  176. tmpLst[i].SequenceIndex = 0;
  177. schedulerSequences.Add(tmpLst[i]);
  178. index++;
  179. }
  180. return schedulerSequences;
  181. }
  182. /// <summary>
  183. /// 分析最后加工recipe索引
  184. /// </summary>
  185. /// <param name="recipes"></param>
  186. /// <returns></returns>
  187. private (int lastIndex,List<int> processIndexList) AnalyseLastProcessRecipeIndex(List<string> recipes)
  188. {
  189. int index = 0;
  190. List<int> lst = new List<int>();
  191. for(int i=0;i<recipes.Count; i++)
  192. {
  193. string item=recipes[i];
  194. if(item.ToLower().EndsWith("dep.rcp"))
  195. {
  196. index = i;
  197. if(lst.Contains(i))
  198. {
  199. lst.Add(i);
  200. }
  201. }
  202. }
  203. if(lst.Count==0)
  204. {
  205. lst.Add(0);
  206. }
  207. return (index,lst);
  208. }
  209. /// <summary>
  210. /// 创建EFEM Robot步骤
  211. /// </summary>
  212. /// <param name="index"></param>
  213. /// <returns></returns>
  214. private SchedulerSequence CreateEfemRobotSequence(MoveItem moveItem,List<SchedulerSyncModuleMessage> synModules,int waferSize,ref int index)
  215. {
  216. SchedulerSequence sequence = new SchedulerSequence();
  217. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(ModuleName.EfemRobot);
  218. sequence.SequenceIndex= index;
  219. sequence.ModuleName=ModuleName.EfemRobot;
  220. sequence.State = RState.Init;
  221. sequence.Recipe = null;
  222. sequence.ModuleType=ModuleType.EfemRobot;
  223. sequence.Parameters =moveItem;
  224. sequence.MaterialType = MaterialType.Wafer;
  225. sequence.SynchronousModuleMessages = synModules;
  226. sequence.WaferSize = waferSize;
  227. index++;
  228. return sequence;
  229. }
  230. /// <summary>
  231. /// 创建Aligner步骤
  232. /// </summary>
  233. /// <param name="index"></param>
  234. /// <returns></returns>
  235. private SchedulerSequence CreateAlignerSequence(SequenceRecipe recipe,ref int index)
  236. {
  237. SchedulerSequence sequence = new SchedulerSequence();
  238. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(ModuleName.Aligner1);
  239. sequence.SequenceIndex = index;
  240. sequence.ModuleName = ModuleName.Aligner1;
  241. sequence.State = RState.Init;
  242. sequence.Recipe = recipe;
  243. sequence.ModuleType = ModuleType.Aligner;
  244. sequence.Parameters = null;
  245. sequence.MaterialType = MaterialType.Wafer;
  246. sequence.WaferSize = sequence.WaferSize;
  247. index++;
  248. return sequence;
  249. }
  250. /// <summary>
  251. /// 创建PUF步骤
  252. /// </summary>
  253. /// <param name="pufModuleName"></param>
  254. /// <param name="index"></param>
  255. /// <returns></returns>
  256. private SchedulerSequence CreatePufSequence(ModuleName pufModuleName,SequenceRecipe sequenceRecipe,string side,bool forward,ref int index)
  257. {
  258. SchedulerSequence sequence = new SchedulerSequence();
  259. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(pufModuleName);
  260. sequence.SequenceIndex = index;
  261. sequence.ModuleName = pufModuleName;
  262. sequence.State = RState.Init;
  263. sequence.Recipe = sequenceRecipe;
  264. sequence.Parameters = null;
  265. sequence.IsWaitNotify = !forward;
  266. sequence.ModuleType = ModuleType.PUF;
  267. sequence.MaterialType = MaterialType.Wafer;
  268. sequence.WaferSize = sequenceRecipe.SubstrateSize;
  269. index++;
  270. return sequence;
  271. }
  272. /// <summary>
  273. /// 创建Loader步骤
  274. /// </summary>
  275. /// <param name="index"></param>
  276. /// <returns></returns>
  277. private SchedulerSequence CreateSRDSequence(SrdRecipe recipe,ref int index)
  278. {
  279. SchedulerSequence sequence = new SchedulerSequence();
  280. sequence.SequenceIndex = index;
  281. sequence.State = RState.Init;
  282. sequence.Recipe = recipe;
  283. sequence.ModuleType = ModuleType.SRD;
  284. sequence.MaterialType = MaterialType.Wafer;
  285. index++;
  286. return sequence;
  287. }
  288. /// <summary>
  289. /// 获取可用Dummy slot
  290. /// </summary>
  291. /// <param name="moduleType"></param>
  292. /// <returns></returns>
  293. public (ModuleName moduleName, int slot) GetAvaibleDummySlots(WaferSize waferSize)
  294. {
  295. if (ModuleHelper.IsInstalled(ModuleName.Dummy1))
  296. {
  297. DummyEntity dummyEntity = Singleton<RouteManager>.Instance.GetModule<DummyEntity>(ModuleName.Dummy1.ToString());
  298. DummyDevice dummyDevice = Singleton<RouteManager>.Instance.EFEM.GetDummyDevice(0);
  299. if (dummyDevice != null && dummyDevice.HasCassette && dummyDevice.WaferSize == waferSize)
  300. {
  301. for (int i = 0; i < dummyEntity.MaxSlotNumber; i++)
  302. {
  303. if (WaferManager.Instance.CheckNoWafer(ModuleName.Dummy1, i))
  304. {
  305. return (ModuleName.Dummy1, i);
  306. }
  307. }
  308. }
  309. }
  310. if (ModuleHelper.IsInstalled(ModuleName.Dummy2))
  311. {
  312. DummyEntity dummyEntity = Singleton<RouteManager>.Instance.GetModule<DummyEntity>(ModuleName.Dummy2.ToString());
  313. DummyDevice dummyDevice = Singleton<RouteManager>.Instance.EFEM.GetDummyDevice(1);
  314. if (dummyDevice != null && dummyDevice.HasCassette && dummyDevice.WaferSize == waferSize)
  315. {
  316. for (int i = 0; i < dummyEntity.MaxSlotNumber; i++)
  317. {
  318. if (WaferManager.Instance.CheckNoWafer(ModuleName.Dummy2, i))
  319. {
  320. return (ModuleName.Dummy2, i);
  321. }
  322. }
  323. }
  324. }
  325. return (ModuleName.Unknown, -1);
  326. }
  327. /// <summary>
  328. /// 根据模块类型获取可用模块
  329. /// </summary>
  330. /// <param name="moduleType"></param>
  331. /// <returns></returns>
  332. public ModuleName GetAvaibleModuleCell(string sequenceType,ModuleType moduleType, ModuleName moduleName = ModuleName.Unknown)
  333. {
  334. if (ModuleHelper.IsMetal(moduleName))
  335. {
  336. List<IModuleEntity> entities = Singleton<RouteManager>.Instance.GetModulesByModuleType(moduleType);
  337. return GetMetalAvaibleRinseModule(entities, moduleName);
  338. }
  339. else
  340. {
  341. List<IModuleEntity> entities = Singleton<RouteManager>.Instance.GetModulesByModuleType(moduleType);
  342. List<IModuleEntity> avaibles = new List<IModuleEntity>();
  343. foreach (var item in entities)
  344. {
  345. bool result = CheckAvaibleModule(item,moduleType,sequenceType);
  346. if (result)
  347. {
  348. avaibles.Add(item);
  349. }
  350. }
  351. return GetMinTimeToReadyModule(avaibles,moduleType);
  352. }
  353. }
  354. /// <summary>
  355. /// 获取可用的Dryer cell
  356. /// </summary>
  357. /// <param name="waferHolderId"></param>
  358. /// <param name="startTime"></param>
  359. /// <param name="dryerTimeLength"></param>
  360. /// <returns></returns>
  361. public ModuleName GetAvaibleDryerCell(string waferHolderId, DateTime startTime, int dryerTimeLength, bool checkConflict)
  362. {
  363. List<IModuleEntity> entities = Singleton<RouteManager>.Instance.GetModulesByModuleType(ModuleType.Dryer);
  364. List<IModuleEntity> avaibleEntities = new List<IModuleEntity>();
  365. foreach (IModuleEntity item in entities)
  366. {
  367. if ((item.IsIdle || item.IsBusy) && item.IsAuto)
  368. {
  369. avaibleEntities.Add(item);
  370. }
  371. }
  372. if (checkConflict)
  373. {
  374. List<ModuleName> resets = SchedulerDryerTimeManager.Instance.ResetModuleOrderByUsed(avaibleEntities);
  375. List<IModuleEntity> avaibles = new List<IModuleEntity>();
  376. foreach (var item in resets)
  377. {
  378. var conflict = SchedulerDryerTimeManager.Instance.CheckDryerConflict(item.ToString(), waferHolderId, startTime, dryerTimeLength);
  379. if (!conflict.conflict)
  380. {
  381. return item;
  382. }
  383. }
  384. }
  385. else
  386. {
  387. List<ModuleName> resets = SchedulerDryerTimeManager.Instance.ResetModuleOrderBySchedulerEndTime(avaibleEntities);
  388. if (resets.Count != 0)
  389. {
  390. return resets[0];
  391. }
  392. }
  393. return ModuleName.Unknown;
  394. }
  395. /// <summary>
  396. /// 获取可用的Dryer cell
  397. /// </summary>
  398. /// <param name="waferHolderId"></param>
  399. /// <param name="startTime"></param>
  400. /// <param name="dryerTimeLength"></param>
  401. /// <returns></returns>
  402. public ModuleName GetAvaibleQdrCell(string waferHolderId, string metalName)
  403. {
  404. List<LayoutCellItem> rinseItems = CellItemManager.Instance.GetRinseItemsByMetal(metalName.ToString());
  405. if (rinseItems.Count == 0)
  406. {
  407. return ModuleName.Unknown;
  408. }
  409. List<IModuleEntity> entities = Singleton<RouteManager>.Instance.GetModulesByModuleType(ModuleType.Rinse);
  410. List<IModuleEntity> avaibles = new List<IModuleEntity>();
  411. foreach (var item in entities)
  412. {
  413. LayoutCellItem cellItem = rinseItems.Find(O => O.ModuleName == item.Module.ToString());
  414. if (cellItem != null)
  415. {
  416. }
  417. }
  418. List<ModuleName> resets = SchedulerQdrTimeManager.Instance.ResetModuleOrderBySchedulerEndTime(avaibles);
  419. if (resets.Count != 0)
  420. {
  421. return resets[0];
  422. }
  423. return ModuleName.Unknown;
  424. }
  425. /// <summary>
  426. /// 根据化学液计算时间获取可用MetalCell(参考其他Metal剩余时间)
  427. /// </summary>
  428. /// <param name="chemistry"></param>
  429. /// <returns></returns>
  430. public ModuleName CalculateAvaibleMetalCellByChemistry(string chemistry,string startRinse,string sequenceType,int waferSize,ref bool isExistEnableMetal)
  431. {
  432. if(!Enum.TryParse(startRinse,out ModuleName startRinseModule)||!ModuleHelper.IsRinse(startRinseModule))
  433. {
  434. startRinse = "";
  435. }
  436. isExistEnableMetal = false;
  437. return ModuleName.Unknown;
  438. }
  439. /// <summary>
  440. /// 根据化学液计算时间获取可用MetalCell(参考其他Metal剩余时间)
  441. /// </summary>
  442. /// <param name="chemistry"></param>
  443. /// <returns></returns>
  444. public (ModuleName metalModule, ModuleName rinseModule) CalculateAvaibleMetalCellByChemistry(string chemistry, string startRinse, string sequenceType, string waferHolderId,
  445. int waferSize,DateTime startTime, int depRecipeTimeLength, int qdrRecipeTimeLength, bool checkConflict,
  446. SchedulerModulePartTime metalPartTime, SchedulerModulePartTime qdrParTime, ref bool isExistEnableMetal)
  447. {
  448. bool isShowLog = SC.GetValue<bool>("Scheduler.IsShowLog");
  449. if (!Enum.TryParse(startRinse, out ModuleName startRinseModule) || !ModuleHelper.IsRinse(startRinseModule))
  450. {
  451. startRinse = "";
  452. }
  453. isExistEnableMetal = false;
  454. return (ModuleName.Unknown, ModuleName.Unknown);
  455. }
  456. /// <summary>
  457. /// 根据化学液获取可用Metal
  458. /// </summary>
  459. /// <param name="chemistry"></param>
  460. /// <param name="sequenceType"></param>
  461. /// <returns></returns>
  462. public bool CalculateAvaibleMetalCellByChemistry(string chemistry,string sequenceType,int waferSize)
  463. {
  464. return false;
  465. }
  466. /// <summary>
  467. /// 检验Process transporter正在Transfer WH移动至Rinse
  468. /// </summary>
  469. /// <returns></returns>
  470. private bool CheckProcessTransporterTransfering(List<string> rinseList)
  471. {
  472. return false;
  473. }
  474. /// <summary>
  475. /// 计算Metal所在Reservoir Busy Metal数量
  476. /// </summary>
  477. /// <param name="item"></param>
  478. /// <returns></returns>
  479. private (bool success,int busyCount) CalculateMetalReservoirAllBusyMetalCount(string metalName)
  480. {
  481. string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(metalName);
  482. if (string.IsNullOrEmpty(reservoirName))
  483. {
  484. return (false,0);
  485. }
  486. List<string> metals = ReservoirItemManager.Instance.GetMetalsByReservoir(reservoirName);
  487. int count = 0;
  488. foreach (string item in metals)
  489. {
  490. if (metalName == item)
  491. {
  492. continue;
  493. }
  494. }
  495. return (true,count);
  496. }
  497. /// <summary>
  498. /// 检验独立Rinse是否可用
  499. /// </summary>
  500. /// <param name="singleRinseItems"></param>
  501. /// <param name="metalName"></param>
  502. /// <returns></returns>
  503. private bool CheckSingleRinseItemsCanUsed(List<string> singleRinseItems, string metalName)
  504. {
  505. var result = CalculateMetalReservoirAllBusyMetalCount(metalName);
  506. if(result.success)
  507. {
  508. bool transporterTransfering = CheckProcessTransporterTransfering(singleRinseItems);
  509. if (transporterTransfering)
  510. {
  511. return result.busyCount + 1 < singleRinseItems.Count;
  512. }
  513. else
  514. {
  515. return result.busyCount < singleRinseItems.Count;
  516. }
  517. }
  518. return false;
  519. }
  520. /// <summary>
  521. /// 检验共享Rinse是否可用
  522. /// </summary>
  523. /// <param name="sharedRinse"></param>
  524. /// <param name="metalName"></param>
  525. /// <returns></returns>
  526. private bool CheckShardRinseCanUse(string sharedRinse, string metalName,string startRinse)
  527. {
  528. string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(metalName);
  529. List<string> shardReservoirs = CellItemManager.Instance.GetReservoirsBySharedRinse(sharedRinse);
  530. if (shardReservoirs == null || shardReservoirs.Count == 0)
  531. {
  532. return false;
  533. }
  534. foreach (string reservoir in shardReservoirs)
  535. {
  536. if (reservoir==reservoirName)
  537. {
  538. continue;
  539. }
  540. }
  541. return true;
  542. }
  543. /// <summary>
  544. /// 检验可用
  545. /// </summary>
  546. /// <param name="item"></param>
  547. /// <param name="moduleType"></param>
  548. /// <param name="sequenceType"></param>
  549. /// <param name="waferHolderId"></param>
  550. /// <param name="startTime"></param>
  551. /// <param name="processLength"></param>
  552. /// <returns></returns>
  553. public bool CheckAvaibleMetalModule(IModuleEntity item, ModuleType moduleType, string sequenceType, string waferHolderId, DateTime startTime, int processLength, bool checkConflict)
  554. {
  555. bool result = CheckAvaibleModule(item, moduleType, sequenceType);
  556. if (!result)
  557. {
  558. return false;
  559. }
  560. if (checkConflict)
  561. {
  562. var conflict = SchedulerMetalTimeManager.Instance.CheckMetalConflict(item.Module.ToString(), waferHolderId, startTime, processLength);
  563. return !conflict.conflict;
  564. }
  565. else
  566. {
  567. return result;
  568. }
  569. }
  570. /// <summary>
  571. /// 检验模块是否可用
  572. /// </summary>
  573. /// <param name="item"></param>
  574. /// <returns></returns>
  575. public bool CheckAvaibleModule(IModuleEntity item,ModuleType moduleType,string sequenceType)
  576. {
  577. if (item.IsDisable)
  578. {
  579. return false;
  580. }
  581. if (!item.IsAuto)
  582. {
  583. return false;
  584. }
  585. if (item.IsError)
  586. {
  587. return false;
  588. }
  589. if (item.IsInit)
  590. {
  591. return false;
  592. }
  593. if (moduleType==ModuleType.Metal)
  594. {
  595. if(item.IsProduction && sequenceType == ENGINEERING)
  596. return false;
  597. if (item.IsEngineering && sequenceType == PRODUCTION)
  598. return false;
  599. }
  600. return true;
  601. }
  602. /// <summary>
  603. /// 获取剩余时间最小的模块
  604. /// </summary>
  605. /// <param name="avaibles"></param>
  606. /// <returns></returns>
  607. private ModuleName GetMinTimeToReadyModule(List<IModuleEntity> avaibles,ModuleType moduleType)
  608. {
  609. if (avaibles.Count == 1)
  610. {
  611. return avaibles[0].Module;
  612. }
  613. int timeToReady = int.MaxValue;
  614. IModuleEntity selectedModule = null;
  615. List<IModuleEntity> idleModuleEtities = new List<IModuleEntity>();
  616. foreach (var item in avaibles)
  617. {
  618. if (item.IsIdle)
  619. {
  620. if(moduleType!=ModuleType.Metal)
  621. {
  622. return item.Module;
  623. }
  624. idleModuleEtities.Add(item);
  625. }
  626. if (item.TimeToReady < timeToReady&&idleModuleEtities.Count==0)
  627. {
  628. timeToReady = item.TimeToReady;
  629. selectedModule = item;
  630. }
  631. }
  632. if (idleModuleEtities.Count != 0)
  633. {
  634. return GetMinUsageMetal(idleModuleEtities);
  635. }
  636. if (selectedModule != null)
  637. {
  638. return selectedModule.Module;
  639. }
  640. return ModuleName.Unknown;
  641. }
  642. /// <summary>
  643. /// 获取电量最小的Metal
  644. /// </summary>
  645. /// <param name="idleModuleEntities"></param>
  646. /// <returns></returns>
  647. private ModuleName GetMinUsageMetal(List<IModuleEntity> idleModuleEntities, int depProcessLength, SchedulerModulePartTime metalPartTime)
  648. {
  649. ModuleName selectedModuleName = ModuleName.Unknown;
  650. List<string> minDateModuleLst = new List<string>();
  651. return selectedModuleName;
  652. }
  653. /// <summary>
  654. /// 获取电量最小的Metal
  655. /// </summary>
  656. /// <param name="idleModuleEntities"></param>
  657. /// <returns></returns>
  658. private ModuleName GetMinUsageMetal(List<IModuleEntity> idleModuleEntities)
  659. {
  660. ModuleName selectedModuleName = ModuleName.Unknown;
  661. return selectedModuleName;
  662. }
  663. /// <summary>
  664. /// 获取Metal可用的Rinse模块
  665. /// </summary>
  666. /// <param name="metalName"></param>
  667. /// <returns></returns>
  668. private ModuleName GetMetalAvaibleRinseModule(List<IModuleEntity> items, ModuleName metalName)
  669. {
  670. int metalId = CellItemManager.Instance.GetCellIdByModuleName(metalName.ToString());
  671. if (metalId == 0)
  672. {
  673. return ModuleName.Unknown;
  674. }
  675. List<LayoutCellItem> rinseItems = CellItemManager.Instance.GetRinseItemsByMetal(metalName.ToString());
  676. if (rinseItems.Count == 0)
  677. {
  678. return ModuleName.Unknown;
  679. }
  680. return ModuleName.Unknown;
  681. }
  682. /// <summary>
  683. /// 检验Metal可用的Rinse模块
  684. /// </summary>
  685. /// <param name="metalName"></param>
  686. /// <returns></returns>
  687. private ModuleName GetMetalAvaibleEmptyRinseModule(List<IModuleEntity> items, ModuleName metalName)
  688. {
  689. int metalId = CellItemManager.Instance.GetCellIdByModuleName(metalName.ToString());
  690. if (metalId == 0)
  691. {
  692. return ModuleName.Unknown;
  693. }
  694. List<LayoutCellItem> rinseItems = CellItemManager.Instance.GetRinseItemsByMetal(metalName.ToString());
  695. if (rinseItems.Count == 0)
  696. {
  697. return ModuleName.Unknown;
  698. }
  699. return ModuleName.Unknown;
  700. }
  701. /// <summary>
  702. /// 获取上一个Metal
  703. /// </summary>
  704. /// <param name="sequenceIndex"></param>
  705. /// <param name="sequences"></param>
  706. /// <returns></returns>
  707. public ModuleName GetPreMetalModuleName(int sequenceIndex,List<SchedulerSequence> sequences)
  708. {
  709. for(int i = sequenceIndex - 1; i >= 0; i--)
  710. {
  711. SchedulerSequence schedulerSequence= sequences[i];
  712. if (schedulerSequence.ModuleType == ModuleType.Metal && ModuleHelper.IsMetal(schedulerSequence.ModuleName))
  713. {
  714. return schedulerSequence.ModuleName;
  715. }
  716. }
  717. return ModuleName.Unknown;
  718. }
  719. }
  720. }