private IEnumerable <Event> OrderCompletion() { var before = Now; using (var req = handover.Request()) { yield return(req); var block = World.Handover.Block; while (!block.Ready) { yield return(sim.Timeout(settings.CheckInterval)); } // TODO: when ready ?! block.Delivered = true; if (block.Due >= Now) { ServiceLevel.Add(1); // A 0 will be entered by BlockProcess World.KPIs.ServiceLevelMean = ServiceLevel.Mean; Tardiness.Add(0); World.KPIs.TardinessMean = Tardiness.Mean; } else { var tardiness = Now - block.Due; Tardiness.Add(tardiness.TotalSeconds); World.KPIs.TardinessMean = Tardiness.Mean; } var leadTime = Now - block.Release; LeadTimes.Add(leadTime.TotalSeconds); World.KPIs.LeadTimeMean = LeadTimes.Mean; World.KPIs.DeliveredBlocks++; OnWorldChanged(kpichange: true); yield return(sim.TimeoutTriangular(handoverRNG, settings.MinClearTime, settings.MaxClearTime)); World.Handover.Block = null; World.Handover.Ready = false; OnWorldChanged(); //sim.Log("{0} Block ({1}) is removed, due: {2}", Now, block.Id, block.Due); //sim.Log("{0} KPIs! Manipulations = {1}, SL = {2:F1}, Delivered = {3}, Leadtime = {4:F2}", Now, World.KPIs.CraneManipulations, World.KPIs.ServiceLevelMean, World.KPIs.DeliveredBlocks, World.KPIs.LeadTimeMean); //yield return sim.TimeoutExponential(handoverRNG, settings.HandoverInterval); yield return(sim.Timeout(sim.RandLogNormal2(handoverRNG, settings.HandoverTimeMean, settings.HandoverTimeStd))); World.Handover.Ready = true; var elapsed = Now - before; World.ObservationData.HandoverReadyIntervals.AddLast(elapsed.TotalSeconds); if (World.ObservationData.HandoverReadyIntervals.Count > MAX_OBSERVATIONS) { World.ObservationData.HandoverReadyIntervals.RemoveFirst(); } OnWorldChanged(); //sim.Log("{0} Handover is ready", Now); } }
private IEnumerable <Event> BlockProcess(Block block, bool suppressEvent = false) { World.KPIs.TotalBlocksOnTime++; if (!suppressEvent) { OnWorldChanged(kpichange: true); } if (!block.Ready) { var delta = (Now - block.Release); // if block release was already, e.g. after initializing world state var timeout = TimeSpan.FromSeconds(sim.RandUniform(readyRNG, settings.ReadyFactorMin, settings.ReadyFactorMax) * (block.Due - block.Release).TotalSeconds) - delta; if (timeout > TimeSpan.Zero) { yield return(sim.Timeout(timeout)); } block.Ready = true; if (!suppressEvent || timeout > TimeSpan.Zero) { OnWorldChanged(); } //sim.Log("{0} Block ({1}) is ready, due: {2}", Now, block.Id, block.Due); } var untilDue = block.Due - Now + settings.CheckInterval; if (untilDue > TimeSpan.Zero) { yield return(sim.Timeout(untilDue)); } if (block.Delivered) { yield break; } ServiceLevel.Add(0); World.KPIs.ServiceLevelMean = ServiceLevel.Mean; World.KPIs.TotalBlocksOnTime--; OnWorldChanged(kpichange: true); //sim.Log($"{Now} Block ({block.Id}) is overdue"); }