internal static void WriteAcidDensityLog(FabAoEquipment eqp, FabLot lot, AcidAlter alter, float alterQty, DateTime inTime, string status) { Outputs.AcidDensityLog row = new AcidDensityLog(); row.VERSION_ID = ModelContext.Current.VersionNo; row.FACTORY_ID = eqp.FactoryID; row.SHOP_ID = eqp.ShopID; row.EQP_ID = eqp.EqpID; row.EQP_GROUP = eqp.TargetEqp.EqpGroup; row.IN_TIME = inTime; row.STATUS = status; row.LOT_ID = lot.LotID; row.PRODUCT_ID = lot.CurrentProductID; row.STEP_ID = lot.CurrentStepID; row.UNIT_QTY = lot.UnitQty; row.CURRENT_DENSITY = eqp.AcidDensity.CurrentAcid; row.USED_DENSITY = alterQty; row.ALTER_DENCITY = alter != null ? alter.DENSITY_ALTER : 0; row.INIT_DENSITY = eqp.AcidDensity.InitAcid; row.MAX_DENSITY = eqp.AcidDensity.ChangeDensity; OutputMart.Instance.AcidDensityLog.Add(row); }
private void SetCurrentMask(FabAoEquipment eqp, FabLot lot) { if (SimHelper.IsTftRunning) { var mask = eqp.InUseMask; if (mask != null) { mask.WorkInfos.Add(lot); lot.CurrentMask = mask; lot.CurrentFabPlan.MaskID = mask.ToolID; } } else { var jig = eqp.InUseJig; if (jig != null) { StringBuilder sb = new StringBuilder(); foreach (var item in jig.Masks) { item.WorkInfos.Add(lot); if (sb.Length > 0) { sb.Append(","); } sb.Append(item.JigID); } lot.CurrentFabPlan.MaskID = sb.ToString(); } } }
private static bool IsLastRunStep(FabAoEquipment eqp, FabStep step) { if (eqp == null || step == null) { return(false); } if (eqp.IsParallelChamber) { foreach (var subEqp in eqp.SubEqps) { var last = subEqp.LastPlan; if (last != null && last.StepID == step.StepID) { return(true); } } } else { var last = eqp.GetLastPlan(); if (last != null && last.StepID == step.StepID) { return(true); } } return(false); }
private static DateTime GetAvailableSetupTime(FabAoEquipment eqp, DateTime now) { DateTime availableTime = eqp.AvailableSetupTime; //마스크 사용시 if (eqp.InUseMask != null) { //실제Setup시 Seize된 툴이 들어옴. 현재 이전의 LoadInfo을 참조해야함. if (eqp.InUseMask.LoadInfos.Count > 1) { MaskLoadInfo loadInfo = eqp.InUseMask.LoadInfos[eqp.InUseMask.LoadInfos.Count - 2]; if (loadInfo.EqpID != eqp.EqpID) { availableTime = LcdHelper.Max(eqp.AvailableSetupTime, (DateTime)loadInfo.AvailableTime); if (availableTime > now) { availableTime = now; } } } } return(availableTime); }
internal static double GetNewAssignNeedCnt(this JobFilterInfo info, FabAoEquipment eqp, double inflowHour, double workCnt) { double reqCnt = info.GetRequiredEqpCnt(eqp, (decimal)inflowHour); double needCnt = GetNewAssignNeedCnt(reqCnt, workCnt); return(needCnt); }
internal static List <FabSubEqp> GetAvailableSubEqp(this FabAoEquipment eqp) { var now = eqp.NowDT; List <FabSubEqp> list = new List <FabSubEqp>(); if (eqp.IsParallelChamber == false) { return(list); } var subEqpList = eqp.SubEqps; if (subEqpList == null) { return(list); } foreach (var subEqp in subEqpList) { if (subEqp.IsAvailable(now)) { list.Add(subEqp); } } return(list); }
internal static void CheckAvailableSubEqps(this FabAoEquipment eqp) { if (eqp.IsParallelChamber == false) { return; } var info = eqp.TriggerInfo; if (info == null) { return; } var currSubEqp = info.TriggerSubEqp; info.RemoveAvailableList(currSubEqp); if (info.AvailableList == null || info.AvailableList.Count == 0) { eqp.TriggerInfo = null; return; } info.SetTriggerSubEqp(); if (info.TriggerSubEqp != null) { //recall dispatch eqp.SetModified(); } }
internal static LineType GetLineType(this FabAoEquipment eqp) { if (eqp == null) { return(LineType.NONE); } string eqpID = LcdHelper.ToUpper(eqp.EqpID); if (eqp != null && eqpID.Contains("UPH")) { return(LineType.SUB); } var preset = eqp.Preset; if (preset != null) { string presetID = LcdHelper.ToUpper(preset.Name); if (presetID != null & presetID.Contains("ULINE")) { return(LineType.SUB); } } return(LineType.MAIN); }
internal static bool IsNeedSetup(FabAoEquipment eqp, FabLot lot) { if (lot == null) { return(false); } if (eqp.IsParallelChamber) { return(ResHelper.IsNeedChamberSetup(eqp, lot)); } if (ResHelper.IsIgnoreSetup(eqp)) { return(false); } return(IsNeedSetup(eqp, lot.CurrentShopID, lot.CurrentStepID, lot.CurrentProductID, lot.CurrentProductVersion, lot.OwnerType, lot.OwnerID)); }
public WeightValue ALLOW_RUN_DOWN_TIME(ISimEntity entity, DateTime now, ActiveObject target, WeightFactor factor, IDispatchContext ctx) { FabAoEquipment eqp = target as FabAoEquipment; FabLot lot = entity as FabLot; var wf = WeightHelper.GetWeightFactor(eqp.Target.Preset, Constants.WF_ALLOW_RUN_DOWN_TIME); if (wf == null || wf.Factor == 0) { return(new WeightValue(0)); } decimal inflowHour = (decimal)wf.Criteria[0]; var idleTime = eqp.GetIdleRunTime(); decimal adjustHour = inflowHour - Convert.ToDecimal(idleTime.TotalHours); if (adjustHour < 0) { return(new WeightValue(0)); } var inflowQty = InFlowMaster.GetAllowRunDownWip(eqp, lot.CurrentProductID, lot.OrigProductVersion, lot.OwnerType, lot.CurrentStep as FabStep, adjustHour); float score = 0f; if (inflowQty > 0) { score = 1f; } string desc = string.Format("[inflow:{0}]", inflowQty); return(new WeightValue(score * factor.Factor, desc)); }
internal static FabPlanInfo GetLastPlan(this FabAoEquipment eqp) { var last = eqp.LastPlan as FabPlanInfo; if (eqp.IsParallelChamber == false) { return(last); } var info = eqp.TriggerInfo; if (info == null) { return(last); } if (info.TriggerSubEqp != null) { return(info.TriggerSubEqp.LastPlan); } var list = eqp.GetAvailableSubEqp(); var first = list.FirstOrDefault(); if (first != null) { last = first.LastPlan; } return(last); }
/// <summary> /// </summary> /// <param name="entity"/> /// <param name="now"/> /// <param name="target"/> /// <param name="factor"/> /// <param name="ctx"/> /// <returns/> public WeightValue LAST_RUN(Mozart.Simulation.Engine.ISimEntity entity, DateTime now, Mozart.Simulation.Engine.ActiveObject target, Mozart.SeePlan.DataModel.WeightFactor factor, Mozart.SeePlan.Simulation.IDispatchContext ctx) { FabAoEquipment eqp = target as FabAoEquipment; var last = eqp.GetLastPlan(); //eqp.LastPlan; if (last == null) { return(new WeightValue(0)); } FabPlanInfo plan = last as FabPlanInfo; FabLot lot = entity as FabLot; bool isNeedSetup = eqp.IsNeedSetup(lot); float markValue = 0; if (isNeedSetup == false) { markValue = 1; if (lot.CurrentFabPlan.OwnerType != plan.OwnerType) { markValue = 0.5f; } } return(new WeightValue(markValue * factor.Factor)); }
/// <summary> /// </summary> /// <param name="entity"/> /// <param name="now"/> /// <param name="target"/> /// <param name="factor"/> /// <param name="ctx"/> /// <returns/> public WeightValue ASSIGN_STEP_PRIORITY(Mozart.Simulation.Engine.ISimEntity entity, DateTime now, Mozart.Simulation.Engine.ActiveObject target, Mozart.SeePlan.DataModel.WeightFactor factor, Mozart.SeePlan.Simulation.IDispatchContext ctx) { if (factor.Factor == 0) { return(new WeightValue(0)); } FabAoEquipment eqp = target as FabAoEquipment; FabEqp targetEqp = eqp.TargetEqp; FabLot lot = entity as FabLot; float score = 0f; bool isLastStep = false; var last = eqp.GetLastPlan(); if (last != null) { if (last.StepID == lot.CurrentStepID) { isLastStep = true; } } if (isLastStep || targetEqp.MainRunSteps.Contains(lot.CurrentFabStep.StdStep)) { score = 1f; } string lastStepID = last == null ? "-" : last.StepID; string desc = string.Format("[Last : {0}, MainSteps:{1}]", lastStepID, targetEqp.EqpMainRunsSteps); return(new WeightValue(score * factor.Factor, desc)); }
public WeightValue CU_DENSITY_3402(ISimEntity entity, DateTime now, ActiveObject target, WeightFactor factor, IDispatchContext ctx) { if (factor.Factor == 0) { return(new WeightValue(0)); } FabAoEquipment eqp = target as FabAoEquipment; FabLot lot = entity as FabLot; FabStep step = lot.CurrentFabStep; string targetStep = "3402"; int limitDensity = (int)factor.Criteria[0]; if (limitDensity == 0) { return(new WeightValue(0)); } float currDensity = eqp.AcidDensity == null ? 0 : eqp.AcidDensity.CurrentAcid; string desc = string.Format("[Density:{0}, Limit:{1}]", currDensity, limitDensity); float score = 0f; if (step.StepID == targetStep && currDensity < limitDensity) { score = 1f; } return(new WeightValue(score * factor.Factor, desc)); }
private static List <FabSubEqp> FindSubEqpsByState(this FabAoEquipment eqp, LoadingStates state, FabLot lot) { List <FabSubEqp> list = new List <FabSubEqp>(); var subEqpList = eqp.SubEqps; if (subEqpList == null || subEqpList.Length == 0) { return(list); } int count = eqp.SubEqps.Length; for (int i = 0; i < count; i++) { var subEqp = eqp.SubEqps[i]; ChamberInfo chamberInfo; if (eqp.CheckParallelChamberState(i, state, lot, out chamberInfo)) { list.Add(subEqp); } } return(list); }
public static void WriteDispatchLog_ParallelChamber(FabAoEquipment eqp, FabLot lot) { if (eqp == null) { return; } var subEqpList = eqp.SubEqps; if (subEqpList == null) { return; } foreach (var subEqp in subEqpList) { var info = subEqp.EqpDispatchInfo; if (info == null) { continue; } var currLot = subEqp.ChamberInfo.Current as FabLot; if (currLot != lot) { continue; } WriteDispatchLog(eqp, info, subEqp); //기록 후 삭제 처리 subEqp.EqpDispatchInfo = null; } }
private static bool ExistInflowWip(FabAoEquipment eqp, JobFilterInfo info) { var wf = WeightHelper.GetWeightFactor(eqp.Target.Preset, Constants.WF_ALLOW_RUN_DOWN_TIME); if (wf == null || wf.Factor == 0) { return(false); } decimal inflowHour = (decimal)wf.Criteria[0]; if (inflowHour <= 0) { return(false); } var idleTime = eqp.GetIdleRunTime(); decimal adjustHour = inflowHour - Convert.ToDecimal(idleTime.TotalHours); if (adjustHour <= 0) { return(false); } var inflowQty = InFlowMaster.GetAllowRunDownWip(eqp, info.ProductID, info.ProductVersion, info.OwnerType, info.Step, adjustHour); return(inflowQty > 0); }
private static void AddGroupDispatchInfo(FabAoEquipment eqp, IList <IHandlingBatch> lotList, IHandlingBatch[] selected, WeightPreset preset) { for (int i = 0; i < lotList.Count; i++) { var hb = lotList[i]; FabLot lot = hb.ToFabLot(); if (hb.HasContents) { StringBuilder sb = new StringBuilder(); foreach (FabLot item in hb.Contents) { if (sb.Length == 0) { sb.Append(item.LotID); } else { sb.AppendFormat(",{0}", item.LotID); } } lot.LogDetail = string.Format("{0} [{1}→{2}]", hb.UnitQty, hb.Count, sb); } else { Console.WriteLine(); } } eqp.EqpDispatchInfo.AddDispatchInfo(lotList, selected, preset); }
internal static void SetTriggerSubEqpInfo(this FabAoEquipment eqp) { if (eqp.IsParallelChamber == false) { return; } //if (eqp.EqpID == "THCVD400" && eqp.NowDT >= LcdHelper.StringToDateTime("20200305 141500 123540")) // Console.WriteLine("B"); var info = eqp.TriggerInfo; if (info == null) { info = new TriggerSubEqpInfo() { Target = eqp }; eqp.TriggerInfo = info; info.InitTriggerSubEqpInfo(); } info.SetTriggerSubEqp(); }
/// <summary> /// </summary> /// <param name="hb"/> /// <param name="ao"/> /// <param name="now"/> /// <param name="handled"/> public void ON_START_TASK0(Mozart.SeePlan.Simulation.IHandlingBatch hb, Mozart.Simulation.Engine.ActiveObject ao, DateTime now, ref bool handled) { FabLot lot = hb.ToFabLot(); hb.Apply((x, y) => LoadHelper.OnStartTask(x as FabLot)); InFlowMaster.ChangeWipLocation(hb, EventType.TrackIn); if (ao is AoEquipment) { FabAoEquipment eqp = ao as FabAoEquipment; MaskMaster.StartTask(lot, eqp); JigMaster.StartTask(lot, eqp); //TODO : 설비의 Property로 작성필요 (LastPlan의 Plan을 보고) if (lot.CurrentFabPlan.CurrentRecipeTime != null) { eqp.IsEqpRecipeRun = true; } else { eqp.IsEqpRecipeRun = false; } } OutCollector.Write_Rtd_LotUpkTracking(lot); }
public static bool OnParallelChamberPM(this FabAoEquipment eqp, PMSchedule pm, DownEventType det) { if (pm == null || eqp.IsParallelChamber || string.IsNullOrEmpty(pm.ComponentID)) { return(false); } var chamberID = pm.ComponentID; if (string.IsNullOrEmpty(chamberID)) { chamberID = Constants.NULL_ID; } var cproc = eqp.FirstProcess <AoChamberProc2>(); if (det == DownEventType.End) { cproc.Live(chamberID); eqp.WriteHistoryAfterBreak(); eqp.SetModified(); } else { cproc.Die(chamberID, pm.EndTime); eqp.WriteHistory(LoadingStates.PM); } return(true); }
private static void MoveQty(this FabMask mask, FabAoEquipment eqp, FabLot lot) { if (mask.HasLimit() == false) { return; } int qty = lot.UnitQty; if (qty <= 0) { return; } foreach (var item in mask.Limits) { if (item.ActivateType != ActivateType.M) { continue; } item.MoveQty += qty; item.Seq++; OutCollector.WriteLimitMLog(item, eqp, lot, eqp.NowDT); } }
public static bool TryGetMaxRequiredEqp(AoEquipment aeqp, List <JobFilterInfo> joblist, out double maxRequireEqp) { maxRequireEqp = 0; FabAoEquipment eqp = aeqp.ToFabAoEquipment(); //if (eqp.EqpID == "THATS400")// && eqp.NowDT >= LcdHelper.StringToDateTime("20190923181719")) // Console.WriteLine("B"); WeightFactor wf; if (TryGetEqpWeightFactor(eqp, Constants.WF_REQUIRED_EQP_PRIORITY, out wf) == false) { return(false); } double inflowHour = (double)wf.Criteria[0]; foreach (JobFilterInfo info in joblist) { double workCnt = info.WorkingEqpCnt; double needCnt = info.GetNewAssignNeedCnt(eqp, inflowHour, workCnt); maxRequireEqp = Math.Max(maxRequireEqp, needCnt); info.NewAssignNeedCount = needCnt; } return(true); }
private static void SeizeMaskTool(this FabAoEquipment eqp, FabMask mask, FabLot lot) { if (eqp.InUseMask != null) { if (mask == null || mask != eqp.InUseMask) { eqp.ReleaseMask(); } } eqp.InUseMask = mask; if (mask != null) { mask.StateChangeTime = eqp.NowDT; mask.StateCode = ToolStatus.INUSE; if (mask.EqpID != eqp.EqpID) { ChangeLocation(mask, mask.EqpID, eqp.EqpID); } mask.EqpID = eqp.EqpID; mask.Location = mask.EqpID; mask.AvailableTime = GetNextAvailableTime(eqp, lot); mask.AddWorkInfo(lot); } }
public static float GetSetupTime(AoEquipment aeqp, string shopID, string stepID, string productID, string prodVer, string ownerType, string ownerID, bool markingAcid = false) { FabAoEquipment eqp = aeqp.ToFabAoEquipment(); //if(eqp.EqpID == "THATS300") // Console.WriteLine("B"); //if (CheckLastPlan(eqp, shopID, stepID, productID, prodVer, ownerType, ownerID)) // return 0; SetupInfo info = CreateHelper.CreateSetupInfo(eqp, shopID, stepID, productID, prodVer, ownerType, ownerID); string eqpGroup = eqp.TargetEqp.EqpGroup; float setupTime = GetSetupTime(eqpGroup, info); float acidChangeTime = AcidMaster.GetAcidChangeTime(eqp, stepID, productID); float totalSetupTime = setupTime + acidChangeTime; //용액교체 Setup 발생시 EqpPlan 기록을 위해 표시 if (markingAcid && acidChangeTime > 0) { AcidMaster.SetSetupMark(eqp, true); } return(totalSetupTime); }
//private static void OnChamberStateChangedTemp(FabAoEquipment eqp, FabLot lot, LoadingStates state, DateTime now, bool isDone) //{ // if (eqp.IsParallelChamber == false) // return; // int count = eqp.SubEqps.Length; // for (int i = 0; i < count; i++) // { // var subEqp = eqp.SubEqps[i]; // if (isDone) // { // subEqp.OnStateChanged(eqp, state, lot, isDone); // continue; // } // ChamberInfo chamberInfo; // if (eqp.CheckParallelChamberState(i, state, lot, out chamberInfo)) // { // subEqp.OnStateChanged(eqp, state, lot, isDone); // //TODO : 임시처리로직 ParallelChamber 설비의 BUSY 이벤트 누락 발생으로 임시 처리함. (이슈 확인 후 삭제 필요함.) // if (state == LoadingStates.SETUP) // { // Time delay = Time.Max((subEqp.ChamberInfo.SetupEndTime - now), Time.Zero); // if (delay > Time.Zero) // { // object[] args = new object[3] { subEqp, LoadingStates.BUSY.ToString(), lot }; // eqp.AddTimeout(delay, SimHelper.OnEqpLoadingStateChanged, args); // } // } // } // else // { // if (state == LoadingStates.BUSY && subEqp.ChamberInfo.Next != null) // { // FabLot itsMe = subEqp.ChamberInfo.Next as FabLot; // if (lot.CurrentPlan == itsMe.CurrentPlan) // { // if (subEqp.ChamberInfo.OutTime > subEqp.SetupEndTime) // { // Time delay = Time.Max((subEqp.ChamberInfo.OutTime - now), Time.Zero); // if (delay > Time.Zero) // { // object[] args = new object[3] { subEqp, LoadingStates.BUSY.ToString(), lot }; // eqp.AddTimeout(delay, SimHelper.OnEqpLoadingStateChanged, args); // } // } // } // } // else if (state == LoadingStates.IDLERUN) // { // if (subEqp.ChamberInfo.Current != null) // { // Time delay = Time.Max((subEqp.ChamberInfo.OutTime - now), Time.Zero); // if (delay > Time.Zero) // { // object[] args = new object[3] { subEqp, LoadingStates.IDLERUN.ToString(), lot }; // eqp.AddTimeout(delay, SimHelper.OnEqpLoadingStateChanged, args); // } // } // } // else if (state == LoadingStates.SETUP) // { // if (subEqp.ChamberInfo.Current != null) // { // var workInfo = subEqp.ChamberInfo.List.Find(p => (p.Entity as FabLot).CurrentPlan == lot.CurrentPlan); // if (workInfo != null) // { // Time delay = Time.Max((workInfo.SetupStartTime - now), Time.Zero); // if (delay > Time.Zero) // { // object[] args = new object[3] { subEqp, LoadingStates.SETUP.ToString(), lot }; // eqp.AddTimeout(delay, SimHelper.OnEqpLoadingStateChanged, args); // subEqp.SetupStartTime = workInfo.SetupStartTime; // } // delay = Time.Max((workInfo.SetupEndTime - now), Time.Zero); // if (delay > Time.Zero) // { // object[] args = new object[3] { subEqp, LoadingStates.BUSY.ToString(), lot }; // eqp.AddTimeout(delay, SimHelper.OnEqpLoadingStateChanged, args); // subEqp.SetupEndTime = workInfo.SetupEndTime; // } // } // } // } // } // //if (eqp.EqpID == "THCVD500") // //{ // // string lotID = "-"; // // if (subEqp.ChamberInfo.Current != null) // // lotID = (subEqp.ChamberInfo.Current as FabLot).LotID; // // Logger.MonitorInfo("{0};{1};{2};{3};{4};{5};{6};{7};{8}\t", eqp.NowDT.ToString("HH:mm:ss"), state, lot == null ? "-" : lot.LotID, subEqp.SubEqpID, lotID, subEqp.ChamberInfo.OutTime == Time.Zero ? "-" : subEqp.ChamberInfo.OutTime.ToString(), subEqp.ChamberInfo.Next == null ? "-" : (subEqp.ChamberInfo.Next as FabLot).LotID, subEqp.ChamberInfo.Next == null ? "-" : subEqp.ChamberInfo.NextOutTime.ToString(), subEqp.ChamberInfo.LastUnits); // //} // } //} private static void OnChamberStateChanged(FabAoEquipment eqp, FabLot lot, LoadingStates state, DateTime now, bool isDone) { var findSubEqps = isDone ? eqp.GetSubEqpList() : eqp.FindSubEqpsByState(state, lot); if (findSubEqps != null && findSubEqps.Count > 0) { foreach (var subEqp in findSubEqps) { subEqp.OnStateChanged(eqp, state, lot, isDone); //TODO : 임시처리로직 ParallelChamber 설비의 BUSY 이벤트 누락 발생으로 임시 처리함. (이슈 확인 후 삭제 필요함.) if (state == LoadingStates.SETUP) { Time delay = Time.Max((subEqp.ChamberInfo.SetupEndTime - now), Time.Zero); if (delay > Time.Zero) { object[] args = new object[3] { subEqp, LoadingStates.BUSY.ToString(), lot }; eqp.AddTimeout(delay, SimHelper.OnEqpLoadingStateChanged, args); } } } } }
private static bool ExistRunEqpByDspEqpGroup(FabAoEquipment baseEqp, FabStep step) { if (baseEqp == null) { return(false); } string dspEqpGroup = baseEqp.DspEqpGroupID; var eqpList = ResHelper.GetEqpsByDspEqpGroup(dspEqpGroup); if (eqpList == null || eqpList.Count == 0) { return(false); } foreach (var eqp in eqpList) { if (eqp == baseEqp) { continue; } if (IsLastRunStep(eqp, step)) { return(true); } } return(false); }
private static void UpdateLastLoadInfo(this FabAoEquipment eqp, DateTime now, LoadingStates state) { var lastInfo = eqp.LastLoadInfo; if (lastInfo == null) { return; } lastInfo.EndTime = now; var lastPlan = lastInfo.Target as FabPlanInfo; if (lastPlan != null) { lastPlan.EqpInEndTime = now; } var infos = eqp.LoadInfos; if (lastInfo.IsDummyState()) { infos.Remove(lastInfo); } }
private static bool IsFilterDummyWaitEqp(this JobFilterInfo info, FabAoEquipment eqp, List <FabAoEquipment> eqpList) { if (eqpList == null) { return(false); } WeightFactor wf = WeightHelper.GetWeightFactor(eqp.Target.Preset, Constants.WF_DUMMY_WAIT_EQP_FILTER); if (wf == null || wf.Factor == 0) { return(false); } //연속진행인 경우 if (info.IsRunning) { return(false); } var waitEqps = eqpList.FindAll(x => x.IsDummyWait); bool isFilter = waitEqps.Count > 0; return(isFilter); }
private void AddTargetWaitWip(WipProfile profile, List <JobState> jobList, FabStep step, string prodVer, int exCludeStepCnt, AoEquipment inputEqp, decimal allowRunDonwTime ) { FabAoEquipment eqp = inputEqp.ToFabAoEquipment(); decimal tact = GetAverageTactTime(step, prodVer); if (exCludeStepCnt > 0) //자신의 Wait 제외시 { WipStep ws = new WipStep(step, tact, 0); profile.AddWipStep(ws); } else { decimal stepWaitQty = GetCurrenStepWaitWipQty(eqp, step, prodVer, allowRunDonwTime); WipStep ws = new WipStep(step, tact, stepWaitQty); profile.AddWipStep(ws); } }