/// <summary> /// Calculate WIP trace and assign WIPin and WIPout qtys to LotActvities /// </summary> /// <param name="startDate"></param> /// <param name="endDate"></param> public void CalculateWIPTrace(DateTime startDate, DateTime endDate) { // Determine begin qty int beginWIP = LotActivities.Where(x => (x.Arrival == null || x.Arrival < startDate) && (x.Departure == null || x.Departure > startDate)).Count(); WIPTrace.Add(new Tuple <DateTime, int>(startDate, beginWIP)); wipCalculations = new List <Tuple <DateTime, int, LotActivity> >(); // Add arrivals to WIPcalculations foreach (LotActivity activity in LotActivities.Where(x => x.Arrival != null && x.Arrival >= startDate && x.Arrival <= endDate)) { wipCalculations.Add(new Tuple <DateTime, int, LotActivity>((DateTime)activity.Arrival, +1, activity)); } // Add departures to WIPcalculations foreach (LotActivity activity in LotActivities.Where(x => x.Departure != null && x.Departure >= startDate && x.Departure <= endDate)) { wipCalculations.Add(new Tuple <DateTime, int, LotActivity>((DateTime)activity.Departure, -1, activity)); } int currentWIP = beginWIP; // Order WIP calculations on time wipCalculations = wipCalculations.OrderBy(x => x.Item1).ToList(); // Loop through arrival and departure events and generate WIP Trace foreach (Tuple <DateTime, int, LotActivity> calc in wipCalculations) { if (calc.Item1 == WIPTrace.Last().Item1) { WIPTrace.RemoveAt(WIPTrace.Count() - 1); } currentWIP += calc.Item2; WIPTrace.Add(new Tuple <DateTime, int>(calc.Item1, currentWIP)); // Assign WIPin qty (right before arrival) to LotActivity if (calc.Item2 == 1) { calc.Item3.WIPIn = currentWIP - 1; } // Assign WIPout qty (right after departure) to LotActivity else if (calc.Item2 == -1) { calc.Item3.WIPOut = currentWIP; } } // Check if last WIP value is correct int endWIP = LotActivities.Where(x => (x.Departure == null || x.Departure > endDate) && (x.Arrival == null || x.Arrival < endDate)).Count(); if (endWIP != WIPTrace.Last().Item2) { throw new Exception($"End WIP does not match Begin WIP + sum(WIP changes) for {WorkCenter}"); } wipTraceTimes = WIPTrace.Select(x => x.Item1).ToList(); }
public List <LotActivity> CalculateEPTs(List <LotActivity> lotActivities) { LotActivities = lotActivities.ToList(); allSortedOnDeparture = LotActivities.OrderBy(x => x.Departure).ToList(); subsetNoDeparture = LotActivities.Where(x => x.Arrival != null && x.Departure == null).ToList(); subsetNoArrivalDeparture = LotActivities.Where(x => x.Arrival == null && x.Departure == null).ToList(); DateTime?prevDepart = null; for (int i = 0; i < allSortedOnDeparture.Count; i++) { LotActivity act = allSortedOnDeparture[i]; if (act.Departure != null && prevDepart != null && act.WIPIn > -1) { TimeSpan ept = new TimeSpan(); // Calculate EPT if (act.WIPIn > 0) { ept = (DateTime)act.Departure - (DateTime)prevDepart; } else if (act.WIPIn == 0) { ept = (DateTime)act.Departure - (DateTime)act.Arrival; } act.EPT = ept.TotalSeconds; // Calculate overtaken lots (this operation is slow) act.OvertakenLots = subsetNoArrivalDeparture.Count + subsetNoDeparture.Where(x => x.Arrival < act.Arrival).Count() + allSortedOnDeparture.GetRange(i, allSortedOnDeparture.Count - i).Where(x => x.Arrival < act.Arrival).Count(); } prevDepart = act.Departure; } return(LotActivities); }