SchedulerModuleTimeManager.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. using Aitex.Core.RT.Fsm;
  2. using Aitex.Core.RT.IOCore;
  3. using Aitex.Core.RT.Log;
  4. using Aitex.Core.RT.SCCore;
  5. using Aitex.Core.Util;
  6. using CyberX8_RT.Modules;
  7. using CyberX8_RT.Schedulers.Transporter;
  8. using MECF.Framework.Common.CommonData;
  9. using MECF.Framework.Common.Equipment;
  10. using MECF.Framework.Common.RecipeCenter;
  11. using SecsGem.Core.ItemModel;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. using System.Reflection;
  16. using System.Text;
  17. using System.Threading.Tasks;
  18. namespace CyberX8_RT.Schedulers
  19. {
  20. public class SchedulerModuleTimeManager : Singleton<SchedulerModuleTimeManager>
  21. {
  22. /// <summary>
  23. /// 确定后面所有Metal、Qdr和Dryer资源
  24. /// </summary>
  25. /// <param name="schedulerSequences"></param>
  26. /// <param name="waferHolderId"></param>
  27. /// <param name="waferHolderMoveItem"></param>
  28. /// <param name="sequenceIndex"></param>
  29. /// <param name="materialId"></param>
  30. /// <param name="existEnableCell"></param>
  31. public bool ConfirmAllMetalQdrAndDryer(List<SchedulerSequence> schedulerSequences, string waferHolderId, int sequenceIndex,bool checkConflict,DateTime startTime)
  32. {
  33. int transporterTransferSeconds = SC.GetValue<int>("Transporter.TransporterTransferSeconds");
  34. var avaibleResults = AnalyseAfterAvaibleCell(schedulerSequences, startTime, waferHolderId, sequenceIndex,checkConflict);
  35. if (!avaibleResults.success)
  36. {
  37. return false;
  38. }
  39. if (avaibleResults.results.Count == 0 && avaibleResults.rinseResults.Item2 == ModuleName.Unknown && avaibleResults.dryerResults.Item2 == ModuleName.Unknown)
  40. {
  41. return false;
  42. }
  43. SchedulerModulePartTime metalPartTime = new SchedulerModulePartTime();
  44. SchedulerModulePartTime qdrPartTime = new SchedulerModulePartTime();
  45. SchedulerModulePartTime dryerPartTime = new SchedulerModulePartTime();
  46. //处理metal和Rinse
  47. for (int i = 0; i < avaibleResults.results.Count; i++)
  48. {
  49. var item = avaibleResults.results[i];
  50. int index = item.Item1;
  51. SchedulerSequence sequence = schedulerSequences[index];
  52. if (sequence.State == CyberX8_Core.RState.End)
  53. {
  54. continue;
  55. }
  56. if (sequence.ModuleName != ModuleName.Transporter1)
  57. {
  58. continue;
  59. }
  60. SchedulerSequence metalSequence = schedulerSequences[index + 1];
  61. if (metalSequence.ModuleType != ModuleType.Metal)
  62. {
  63. continue;
  64. }
  65. DepRecipe depRecipe = (DepRecipe)metalSequence.Recipe;
  66. QdrRecipe qdrRecipe = (QdrRecipe)metalSequence.NextRecipe;
  67. int depRecipeTimeLength = depRecipe.CalculateRecipeTotalTime();
  68. int qdrRecipeTimeLength = qdrRecipe.CalculateRunRecipeTime();
  69. if(!(sequence.Parameters is TransporterAction))
  70. {
  71. continue;
  72. }
  73. TransporterAction transporterAction = (TransporterAction)sequence.Parameters;
  74. if(!(transporterAction.Parameter is WaferHolderMoveItem))
  75. {
  76. continue;
  77. }
  78. WaferHolderMoveItem waferHolderMoveItem = (WaferHolderMoveItem)transporterAction.Parameter;
  79. waferHolderMoveItem.DestModule = item.Item2;
  80. DateTime metalStartTime = item.Item4.AddSeconds(transporterTransferSeconds);
  81. if (metalSequence.SchedulerModule == null)
  82. {
  83. metalSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(item.Item2);
  84. metalSequence.ModuleName = item.Item2;
  85. }
  86. if (!checkConflict)
  87. {
  88. SchedulerTime lastSchedulerTime = SchedulerMetalTimeManager.Instance.GetLastSchedulerTime(item.Item2.ToString());
  89. DateTime lastSchedulerEndTime = GetModuleLastSchedulerEndTime(lastSchedulerTime, metalPartTime, item.Item2.ToString(), depRecipeTimeLength, transporterTransferSeconds);
  90. if (lastSchedulerEndTime > metalStartTime)
  91. {
  92. metalStartTime = lastSchedulerEndTime;
  93. }
  94. }
  95. SchedulerMetalTimeManager.Instance.AddMetalScheduler(item.Item2.ToString(), waferHolderId, index + 1, metalStartTime,
  96. depRecipeTimeLength, false);
  97. SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, item.Item2.ToString(), ModuleType.Metal, index + 1,
  98. metalStartTime, depRecipeTimeLength);
  99. metalPartTime.AddScheduler(item.Item2.ToString(), waferHolderId, index + 1, metalStartTime, depRecipeTimeLength);
  100. if (index + 3 >= schedulerSequences.Count)
  101. {
  102. continue;
  103. }
  104. SchedulerSequence transporterSequence = schedulerSequences[index + 2];
  105. if(!(transporterSequence.Parameters is TransporterAction))
  106. {
  107. continue;
  108. }
  109. TransporterAction action = transporterSequence.Parameters as TransporterAction;
  110. if(!(action.Parameter is WaferHolderMoveItem))
  111. {
  112. continue;
  113. }
  114. WaferHolderMoveItem tranporterMoveItem = (WaferHolderMoveItem)action.Parameter;
  115. tranporterMoveItem.DestModule = item.Item3;
  116. //增加了transporter时间轴
  117. SchedulerTransporterTimeManager.Instance.AddTransporterScheduler(ModuleName.Transporter1.ToString(), waferHolderId, index + 2, metalStartTime.AddSeconds(depRecipeTimeLength),
  118. false);
  119. SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, ModuleName.Transporter1.ToString(), ModuleType.Transporter, index + 2,
  120. metalStartTime.AddSeconds(depRecipeTimeLength), transporterTransferSeconds);
  121. SchedulerSequence qdrSequence = schedulerSequences[index + 3];
  122. if (qdrSequence.ModuleType != ModuleType.Rinse)
  123. {
  124. continue;
  125. }
  126. if (qdrSequence.SchedulerModule == null)
  127. {
  128. qdrSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(item.Item3);
  129. qdrSequence.ModuleName = item.Item3;
  130. }
  131. DateTime schedulerQdrStartTime = SchedulerQdrTimeManager.Instance.CalculateQdrSchedulerStartTime(metalStartTime, depRecipeTimeLength);
  132. if (!checkConflict)
  133. {
  134. SchedulerTime lastSchedulerTime = SchedulerQdrTimeManager.Instance.GetLastSchedulerTime(item.Item3.ToString());
  135. DateTime lastSchedulerEndTime = GetModuleLastSchedulerEndTime(lastSchedulerTime, qdrPartTime, item.Item3.ToString(), qdrRecipeTimeLength, transporterTransferSeconds);
  136. if (lastSchedulerEndTime > schedulerQdrStartTime)
  137. {
  138. schedulerQdrStartTime = lastSchedulerEndTime;
  139. }
  140. }
  141. SchedulerQdrTimeManager.Instance.AddQdrScheduler(item.Item3.ToString(), waferHolderId, index + 3, schedulerQdrStartTime, qdrRecipeTimeLength, false);
  142. SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, item.Item3.ToString(),ModuleType.Rinse, index + 3,
  143. schedulerQdrStartTime, qdrRecipeTimeLength);
  144. qdrPartTime.AddScheduler(item.Item3.ToString(), waferHolderId, index + 3, schedulerQdrStartTime, qdrRecipeTimeLength);
  145. //增加了transporter时间轴
  146. SchedulerTransporterTimeManager.Instance.AddTransporterScheduler(ModuleName.Transporter1.ToString(), waferHolderId, index + 4, schedulerQdrStartTime.AddSeconds(qdrRecipeTimeLength),
  147. false);
  148. SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, ModuleName.Transporter1.ToString(), ModuleType.Transporter, index + 4,
  149. schedulerQdrStartTime.AddSeconds(qdrRecipeTimeLength), transporterTransferSeconds);
  150. }
  151. //处理单独Rinse
  152. if (avaibleResults.rinseResults.Item2 != ModuleName.Unknown)
  153. {
  154. int transporterIndex = avaibleResults.rinseResults.Item1;
  155. SchedulerSequence transporterSequence = schedulerSequences[transporterIndex];
  156. if (transporterSequence.State != CyberX8_Core.RState.End)
  157. {
  158. //增加了transporter时间轴
  159. SchedulerTransporterTimeManager.Instance.AddTransporterScheduler(ModuleName.Transporter1.ToString(), waferHolderId, transporterIndex, avaibleResults.rinseResults.Item3,
  160. false);
  161. SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, ModuleName.Transporter1.ToString(), ModuleType.Transporter, transporterIndex,
  162. avaibleResults.rinseResults.Item3, transporterTransferSeconds);
  163. }
  164. if(transporterSequence.Parameters is TransporterAction)
  165. {
  166. TransporterAction transporterAction=transporterSequence.Parameters as TransporterAction;
  167. WaferHolderMoveItem tranporterMoveItem = (WaferHolderMoveItem)transporterAction.Parameter;
  168. tranporterMoveItem.DestModule = avaibleResults.rinseResults.Item2;
  169. SchedulerSequence rinseSequence = schedulerSequences[transporterIndex + 1];
  170. QdrRecipe qdrRecipe = rinseSequence.Recipe as QdrRecipe;
  171. if (rinseSequence.SchedulerModule == null)
  172. {
  173. rinseSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(avaibleResults.rinseResults.Item2);
  174. rinseSequence.ModuleName = avaibleResults.rinseResults.Item2;
  175. }
  176. DateTime schedulerRinseStartTime = avaibleResults.rinseResults.Item3.AddSeconds(transporterTransferSeconds);
  177. if (!checkConflict)
  178. {
  179. SchedulerTime lastSchedulerTime = SchedulerQdrTimeManager.Instance.GetLastSchedulerTime(avaibleResults.rinseResults.Item2.ToString());
  180. DateTime lastSchedulerEndTime = GetModuleLastSchedulerEndTime(lastSchedulerTime, qdrPartTime, avaibleResults.rinseResults.Item2.ToString(), qdrRecipe.CalculateRunRecipeTime(), transporterTransferSeconds);
  181. if (lastSchedulerEndTime > schedulerRinseStartTime)
  182. {
  183. schedulerRinseStartTime = lastSchedulerEndTime;
  184. }
  185. }
  186. SchedulerQdrTimeManager.Instance.AddQdrScheduler(avaibleResults.rinseResults.Item2.ToString(), waferHolderId, transporterIndex + 1, schedulerRinseStartTime, qdrRecipe.CalculateRunRecipeTime(), false);
  187. SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, avaibleResults.rinseResults.Item2.ToString(), ModuleType.Rinse, transporterIndex + 1,
  188. schedulerRinseStartTime, qdrRecipe.CalculateRunRecipeTime());
  189. qdrPartTime.AddScheduler(avaibleResults.rinseResults.Item2.ToString(), waferHolderId, transporterIndex + 1, schedulerRinseStartTime, qdrRecipe.CalculateRunRecipeTime());
  190. SchedulerSequence nextTransporterSequence = schedulerSequences[transporterIndex + 2];
  191. if (nextTransporterSequence != null && nextTransporterSequence.State != CyberX8_Core.RState.End)
  192. {
  193. //增加了transporter时间轴
  194. SchedulerTransporterTimeManager.Instance.AddTransporterScheduler(ModuleName.Transporter1.ToString(), waferHolderId, transporterIndex + 2, schedulerRinseStartTime.AddSeconds(qdrRecipe.CalculateRunRecipeTime()),
  195. false);
  196. SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, ModuleName.Transporter1.ToString(), ModuleType.Transporter, transporterIndex + 2,
  197. schedulerRinseStartTime.AddSeconds(qdrRecipe.CalculateRunRecipeTime()), transporterTransferSeconds);
  198. }
  199. }
  200. }
  201. //处理Dryer
  202. if (avaibleResults.dryerResults.Item2 != ModuleName.Unknown)
  203. {
  204. int transporterIndex = avaibleResults.dryerResults.Item1;
  205. SchedulerSequence transporterSequence = schedulerSequences[transporterIndex];
  206. if (transporterSequence.Parameters is TransporterAction)
  207. {
  208. TransporterAction action=transporterSequence.Parameters as TransporterAction;
  209. WaferHolderMoveItem tranporterMoveItem = (WaferHolderMoveItem)action.Parameter;
  210. tranporterMoveItem.DestModule = avaibleResults.dryerResults.Item2;
  211. SchedulerSequence dryerSequence = schedulerSequences[transporterIndex + 1];
  212. HvdRecipe hvdRecipe = dryerSequence.Recipe as HvdRecipe;
  213. if (dryerSequence.SchedulerModule == null)
  214. {
  215. dryerSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(avaibleResults.dryerResults.Item2);
  216. dryerSequence.ModuleName = avaibleResults.dryerResults.Item2;
  217. }
  218. DateTime schedulerDryerStartTime = SchedulerDryerTimeManager.Instance.CalculateDryerSchedulerStartTime(avaibleResults.dryerResults.Item3);
  219. if (!checkConflict)
  220. {
  221. SchedulerTime lastSchedulerTime = SchedulerDryerTimeManager.Instance.GetLastSchedulerTime(avaibleResults.dryerResults.Item2.ToString());
  222. DateTime lastSchedulerEndTime = GetModuleLastSchedulerEndTime(lastSchedulerTime, qdrPartTime, avaibleResults.dryerResults.Item2.ToString(), hvdRecipe.DryTime, transporterTransferSeconds);
  223. if (lastSchedulerEndTime > schedulerDryerStartTime)
  224. {
  225. schedulerDryerStartTime = lastSchedulerEndTime;
  226. }
  227. }
  228. if (!SchedulerTransporterTimeManager.Instance.Contained(ModuleName.Transporter1.ToString(), waferHolderId, transporterIndex))
  229. {
  230. if (transporterSequence.State != CyberX8_Core.RState.End)
  231. {
  232. //增加了transporter时间轴
  233. SchedulerTransporterTimeManager.Instance.AddTransporterScheduler(ModuleName.Transporter1.ToString(), waferHolderId, transporterIndex, schedulerDryerStartTime.AddSeconds(-transporterTransferSeconds),
  234. false);
  235. SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, ModuleName.Transporter1.ToString(), ModuleType.Transporter, transporterIndex,
  236. schedulerDryerStartTime.AddSeconds(-transporterTransferSeconds), transporterTransferSeconds);
  237. }
  238. }
  239. SchedulerDryerTimeManager.Instance.AddDryerScheduler(avaibleResults.dryerResults.Item2.ToString(), waferHolderId, transporterIndex + 1, schedulerDryerStartTime, hvdRecipe.DryTime, false);
  240. SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, avaibleResults.dryerResults.Item2.ToString(), ModuleType.Dryer, transporterIndex + 1,
  241. schedulerDryerStartTime, hvdRecipe.DryTime);
  242. dryerPartTime.AddScheduler(avaibleResults.dryerResults.Item2.ToString(), waferHolderId, transporterIndex + 1, schedulerDryerStartTime, hvdRecipe.DryTime);
  243. }
  244. }
  245. SchedulerMetalTimeManager.Instance.WriteMetalSchedulerTimeLog();
  246. SchedulerQdrTimeManager.Instance.WriteQdrSchedulerTimeLog();
  247. SchedulerDryerTimeManager.Instance.WriteDryerSchedulerTimeLog();
  248. SchedulerTransporterTimeManager.Instance.WriteTransporterSchedulerTimeLog();
  249. SchedulerWaferHolderTimeManager.Instance.WriteSchedulerTimeLog(waferHolderId);
  250. qdrPartTime.Dispose();
  251. metalPartTime.Dispose();
  252. dryerPartTime.Dispose();
  253. return true;
  254. }
  255. /// <summary>
  256. /// 获取最新调度时间
  257. /// </summary>
  258. /// <param name="schedulerTime"></param>
  259. /// <param name="partTime"></param>
  260. /// <param name="module"></param>
  261. /// <param name="recipeLength"></param>
  262. /// <param name="transporterTransferSeconds"></param>
  263. /// <returns></returns>
  264. private DateTime GetModuleLastSchedulerEndTime(SchedulerTime schedulerTime,SchedulerModulePartTime partTime,string module,int recipeLength,int transporterTransferSeconds)
  265. {
  266. DateTime lastSchedulerEndTime = DateTime.MinValue;
  267. if (schedulerTime != null)
  268. {
  269. lastSchedulerEndTime = schedulerTime.ScheduleStartTime.AddSeconds(recipeLength).AddSeconds(transporterTransferSeconds);
  270. }
  271. DateTime lastPartTime = partTime.GetLastSchedulerTime(module);
  272. if (lastPartTime.AddSeconds(transporterTransferSeconds) > lastSchedulerEndTime)
  273. {
  274. lastSchedulerEndTime = lastPartTime.AddSeconds(transporterTransferSeconds);
  275. }
  276. return lastSchedulerEndTime;
  277. }
  278. /// <summary>
  279. /// 分析后面所有Cell可用资源
  280. /// sequenceIndex为transporter对应的索引
  281. /// </summary>
  282. /// <param name="schedulerSequences"></param>
  283. /// <param name="waferHolderId"></param>
  284. /// <param name="sequenceIndex"></param>
  285. /// <returns></returns>
  286. public (bool success,List<(int, ModuleName, ModuleName, DateTime)> results, (int, ModuleName, DateTime) rinseResults,(int, ModuleName, DateTime) dryerResults) AnalyseAfterAvaibleCell(List<SchedulerSequence> schedulerSequences,
  287. DateTime startTime, string waferHolderId, int sequenceIndex,bool checkConflict)
  288. {
  289. int transporterTransferSeconds = SC.GetValue<int>("Transporter.TransporterTransferSeconds");
  290. List<(int, ModuleName, ModuleName, DateTime)> results = new List<(int, ModuleName, ModuleName, DateTime)>();
  291. var dryerResults = new ValueTuple<int, ModuleName, DateTime>();
  292. dryerResults.Item2 = ModuleName.Unknown;
  293. var rinseResults = new ValueTuple<int, ModuleName, DateTime>();
  294. rinseResults.Item2 = ModuleName.Unknown;
  295. SchedulerModulePartTime metalPartTime = new SchedulerModulePartTime();
  296. SchedulerModulePartTime qdrPartTime = new SchedulerModulePartTime();
  297. for (int i = sequenceIndex; i < schedulerSequences.Count; i++)
  298. {
  299. SchedulerSequence sequence = schedulerSequences[i];
  300. if (sequence.State == CyberX8_Core.RState.End)
  301. {
  302. continue;
  303. }
  304. if (sequence.ModuleName != ModuleName.Transporter1)
  305. {
  306. continue;
  307. }
  308. if(!(sequence.Parameters is TransporterAction))
  309. {
  310. continue;
  311. }
  312. TransporterAction transporterAction = (TransporterAction)sequence.Parameters;
  313. if(!(transporterAction.Parameter is WaferHolderMoveItem))
  314. {
  315. continue;
  316. }
  317. WaferHolderMoveItem waferHolderMoveItem = (WaferHolderMoveItem)transporterAction.Parameter;
  318. //确定Dryer资源
  319. if (waferHolderMoveItem.DestModuleType == ModuleType.Dryer)
  320. {
  321. SchedulerSequence nextSequence = schedulerSequences[i + 1];
  322. HvdRecipe hvdRecipe = (HvdRecipe)nextSequence.Recipe;
  323. ModuleName dryerModule = SchedulerSequenceManager.Instance.GetAvaibleDryerCell(waferHolderId, startTime, hvdRecipe.DryTime,checkConflict);
  324. if (dryerModule == ModuleName.Unknown)
  325. {
  326. metalPartTime.Dispose();
  327. qdrPartTime.Dispose();
  328. return (false,results,rinseResults,dryerResults);
  329. }
  330. dryerResults.Item1 = i;
  331. dryerResults.Item2 = dryerModule;
  332. dryerResults.Item3 = startTime;
  333. continue;
  334. }
  335. if (waferHolderMoveItem.DestModuleType == ModuleType.Rinse&&!checkConflict)
  336. {
  337. SchedulerSequence preSequence= schedulerSequences[i -1];
  338. if (preSequence.ModuleName == ModuleName.Unknown)
  339. {
  340. continue;
  341. }
  342. SchedulerSequence nextSequence = schedulerSequences[i + 1];
  343. QdrRecipe nextQdrRecipe = (QdrRecipe)nextSequence.Recipe;
  344. ModuleName qdrModule = SchedulerSequenceManager.Instance.GetAvaibleQdrCell(waferHolderId, preSequence.ModuleName.ToString());
  345. if (qdrModule == ModuleName.Unknown)
  346. {
  347. metalPartTime.Dispose();
  348. qdrPartTime.Dispose();
  349. return (false, results,rinseResults, dryerResults);
  350. }
  351. rinseResults.Item1 = i;
  352. rinseResults.Item2 = qdrModule;
  353. rinseResults.Item3 = startTime;
  354. startTime = startTime.AddSeconds(transporterTransferSeconds).AddSeconds(nextQdrRecipe.CalculateRunRecipeTime());
  355. continue;
  356. }
  357. if (waferHolderMoveItem.DestModuleType != ModuleType.Metal)
  358. {
  359. continue;
  360. }
  361. SchedulerSequence metalSequence = schedulerSequences[i + 1];
  362. if (metalSequence.Recipe == null || !(metalSequence.Recipe is DepRecipe))
  363. {
  364. continue;
  365. }
  366. DepRecipe depRecipe = (DepRecipe)metalSequence.Recipe;
  367. QdrRecipe qdrRecipe = (QdrRecipe)metalSequence.NextRecipe;
  368. int depRecipeTimeLength = depRecipe.CalculateRecipeTotalTime();
  369. int qdrRecipeTimeLength = qdrRecipe.CalculateRunRecipeTime();
  370. bool existEnableCell = false;
  371. var result = SchedulerSequenceManager.Instance.CalculateAvaibleMetalCellByChemistry(depRecipe.Chemistry, waferHolderMoveItem.SourceModule.ToString(), metalSequence.SequenceType,
  372. waferHolderId, metalSequence.WaferSize,startTime.AddSeconds(transporterTransferSeconds), depRecipeTimeLength, qdrRecipeTimeLength,
  373. checkConflict,metalPartTime,qdrPartTime, ref existEnableCell);
  374. if (result.metalModule == ModuleName.Unknown || result.rinseModule == ModuleName.Unknown)
  375. {
  376. metalPartTime.Dispose();
  377. qdrPartTime.Dispose();
  378. return (false,results,rinseResults,dryerResults);
  379. }
  380. results.Add((i, result.metalModule, result.rinseModule, startTime));
  381. startTime = startTime.AddSeconds(transporterTransferSeconds).AddSeconds(depRecipeTimeLength)
  382. .AddSeconds(transporterTransferSeconds).AddSeconds(qdrRecipeTimeLength);
  383. metalPartTime.AddScheduler(result.metalModule.ToString(), waferHolderId, i + 1, startTime, depRecipeTimeLength);
  384. qdrPartTime.AddScheduler(result.rinseModule.ToString(), waferHolderId, i + 3, startTime.AddSeconds(depRecipeTimeLength).AddSeconds(transporterTransferSeconds), qdrRecipeTimeLength);
  385. i += 3;
  386. }
  387. metalPartTime.Dispose();
  388. qdrPartTime.Dispose();
  389. return (true, results,rinseResults, dryerResults);
  390. }
  391. }
  392. }