Пример #1
0
        } // end of Event

        #endregion

        //--------------------------------------------------------------------------------------------------
        // State Change
        //--------------------------------------------------------------------------------------------------

        #region Trigger

        /// <summary>
        /// Acutal state change of arrival. If patient arrives from waiting list path is set, otherwise
        /// next action is taken.
        /// </summary>
        /// <param name="time">Time the patient arrives</param>
        /// <param name="simEngine">SimEngine responsible for simulation execution</param>
        protected override void StateChange(DateTime time, ISimulationEngine simEngine)
        {
            //--------------------------------------------------------------------------------------------------
            // In case Patient is returning from special service facility the path
            // has already been set and needs update to next action
            //--------------------------------------------------------------------------------------------------
            if (Patient.OutpatientTreatmentPath != null)
            {
                Patient.OutpatientTreatmentPath.UpdateNextAction();
            }
            else
            {
                Patient.OutpatientTreatmentPath = InputData.CreateOutpatientTreatmentPath(Patient, Admission, ScheduledTime, false);

                ParentControlUnit.AddEntity(Patient);
            } // end if

            if (Patient.OutpatientTreatmentPath.TakeNextAction(simEngine, this, time, ParentControlUnit))
            {
                if (Patient.OccupiedFacility == null || Patient.OccupiedFacility.ParentDepartmentControl != ParentControlUnit)
                {
                    SequentialEvents.Add(Patient.StartWaitingActivity(((ControlUnitOutpatient)ParentControlUnit).WaitingAreaPatientForNextActionType(Patient.OutpatientTreatmentPath.GetCurrentActionType())));
                }
                else
                {
                    ActivityWaitInFacility waitInFacility = new ActivityWaitInFacility(ParentControlUnit, Patient, Patient.OccupiedFacility);
                    SequentialEvents.Add(waitInFacility.StartEvent);
                } // end if
            }     // end if
        }         // end of Trigger
Пример #2
0
        } // end of Event

        #endregion

        //--------------------------------------------------------------------------------------------------
        // Statechange
        //--------------------------------------------------------------------------------------------------

        #region Trigger

        /// <summary>
        /// Overriden state change of the event. If the patient's path indicates a inpatient or outpatient
        /// admission the corresponding request is sent up the control tree.
        /// </summary>
        /// <param name="time">Time the patient leaves</param>
        /// <param name="simEngine">SimEngine responsible for simulation execution</param>
        protected override void StateChange(DateTime time, ISimulationEngine simEngine)
        {
            ParentControlUnit.RemoveEntity(Patient);
            Patient.CorrespondingDoctor = null;

            if (Patient.OutpatientTreatmentPath.InpatientAdmission != null)
            {
                RequestMoveInpatient reqMoveInpatient = new RequestMoveInpatient(Patient.ToArray(),
                                                                                 time,
                                                                                 Patient,
                                                                                 ParentControlUnit,
                                                                                 Patient.OutpatientTreatmentPath.InpatientAdmission);
                ParentControlUnit.DelegateOutBox.Add(reqMoveInpatient);
            } // end if

            if (Patient.OutpatientTreatmentPath.OutpatientAdmission != null)
            {
                RequestMoveOutpatient reqMoveOutPatient = new RequestMoveOutpatient(Patient.ToArray(),
                                                                                    time,
                                                                                    Patient,
                                                                                    ParentControlUnit,
                                                                                    Patient.OutpatientTreatmentPath.OutpatientAdmission);

                ParentControlUnit.DelegateOutBox.Add(reqMoveOutPatient);
            } // end if

            Patient.OutpatientTreatmentPath = null;
        } // end of Trigger
        } // end of Initialize

        #endregion

        //--------------------------------------------------------------------------------------------------
        // Rule Handling
        //--------------------------------------------------------------------------------------------------

        #region PerformCustomRules

        /// <summary>
        /// Dispatches slot requests by booking in the booking model, further, now show probabilities
        /// and arrival deviations of patients are calculated. Corresponding events for arrival are scheduled.
        /// </summary>
        /// <param name="startTime">Time rules are executed</param>
        /// <param name="simEngine">SimEngine responsible for simulation execution</param>
        /// <returns>False</returns>
        protected override bool PerformCustomRules(DateTime time, ISimulationEngine simEngine)
        {
            if (RAEL.Count == 0)
            {
                return(false);
            }

            if (!WaitingListSchedule.ReadyForDispatch)
            {
                return(false);
            }

            while (RAEL.Count > 0)
            {
                RequestOutpatientWaitingListPatientToAssignSlot reqToDisptatch = (RequestOutpatientWaitingListPatientToAssignSlot)RAEL.First();

                DateTime earliestTime = time;

                earliestTime = reqToDisptatch.EarliestTime;

                Slot slot = WaitingListSchedule.GetEarliestSlotTime(time,
                                                                    earliestTime,
                                                                    reqToDisptatch.Patient,
                                                                    reqToDisptatch.AdmissionType);

                WaitingListSchedule.BookSlot(slot, reqToDisptatch.AdmissionType);

                reqToDisptatch.Patient.StopCurrentActivities(time, simEngine);
                ParentControlUnit.RemoveRequest(reqToDisptatch);
                RemoveRequest(reqToDisptatch);

                if (InputData.NoShowForAppointment(reqToDisptatch.Patient, reqToDisptatch.AdmissionType, slot, time))
                {
                    continue;
                }

                DateTime arrivalTime = slot.StartTime + InputData.PatientArrivalDeviationFromSlotTime(reqToDisptatch.Patient, reqToDisptatch.AdmissionType);

                arrivalTime = new DateTime(Math.Max(time.Ticks, arrivalTime.Ticks));

                EventOutpatientArrival arrival = new EventOutpatientArrival(ParentControlUnit,
                                                                            reqToDisptatch.Patient,
                                                                            slot.StartTime,
                                                                            InputData,
                                                                            reqToDisptatch.AdmissionType);

                simEngine.AddScheduledEvent(arrival, arrivalTime);

                Event patientWait = reqToDisptatch.Patient.StartWaitingActivity(null);

                patientWait.Trigger(time, simEngine);
            } // end while

            WaitingListSchedule.ReadyForDispatch = false;

            return(false);
        } // end of PerformCustomRules
        } // end of AdmissionType

        #endregion

        //--------------------------------------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------------------------------------

        #region TriggerStartEvent

        /// <summary>
        /// State changes of the activities start event. Request for slot assigning is filed
        /// </summary>
        /// <param name="time"> Time of activity start</param>
        /// <param name="simEngine"> SimEngine the handles the activity triggering</param>
        override public void StateChangeStartEvent(DateTime time, ISimulationEngine simEngine)
        {
            RequestOutpatientWaitingListPatientToAssignSlot requestAssign
                = new RequestOutpatientWaitingListPatientToAssignSlot(Patient,
                                                                      time,
                                                                      AdmissionType,
                                                                      EarliestTime,
                                                                      LatestTime);

            ParentControlUnit.AddRequest(requestAssign);
        } // end of TriggerStartEvent
Пример #5
0
        } // end of Event

        #endregion

        //--------------------------------------------------------------------------------------------------
        // State Change
        //--------------------------------------------------------------------------------------------------

        #region StateChange

        /// <summary>
        /// Overriden state change of the event. Request for service is made, next client arrival is scheduled
        /// </summary>
        /// <param name="time">Time the client arrives</param>
        /// <param name="simEngine">SimEngine responsible for simulation execution</param>
        protected override void StateChange(DateTime time, ISimulationEngine simEngine)
        {
            // next arrival is scheduled

            EntityClient nextClient = new EntityClient();

            EventClientArrival nextClientArrival = new EventClientArrival(ParentControlUnit, nextClient);

            double arrivalTimeMinutes = ((SimulationModelQueuing)ParentControlUnit.ParentSimulationModel).ArrivalTime;

            simEngine.AddScheduledEvent(nextClientArrival, time
                                        + TimeSpan.FromMinutes(Distributions.Instance.Exponential(arrivalTimeMinutes)));

            ParentControlUnit.AddRequest(new RequestQueing("WaitInQueue", Client, time));
        } // end of Trigger
Пример #6
0
        } // end of SetChildControlUnits

        #endregion

        #region FindSmallestJointControl

        /// <summary>
        /// Helping function that returns the lowest joint control unit in the control tree that contains
        /// both control units in its sub-tree.
        /// </summary>
        /// <param name="otherControl"> the other control unit that the smallest joint control is used for</param>
        /// <returns>Control unit that is lowest in the control tree and has both control units in its subtree,
        ///          returns null if no joint control has been found</returns>
        public ControlUnit FindSmallestJointControl(ControlUnit otherControl)
        {
            if (ChildControlUnits.Contains(otherControl))
            {
                return(this);
            }
            else
            {
                if (ParentControlUnit == null)
                {
                    return(null);
                }

                return(ParentControlUnit.FindSmallestJointControl(otherControl));
            } // end if
        }     // end of FindSmallestJointControl
        } // end of Event

        #endregion

        //--------------------------------------------------------------------------------------------------
        // State Change
        //--------------------------------------------------------------------------------------------------

        #region Trigger

        /// <summary>
        /// State change of event. Sends patient to the special service model
        /// </summary>
        /// <param name="time">Time event is triggered</param>
        /// <param name="simEngine">SimEngine responsible for simulation execution</param>
        protected override void StateChange(DateTime time, ISimulationEngine simEngine)
        {
            ControlUnitManagement jointControl = (ControlUnitManagement)ParentControlUnit.FindSmallestJointControl(Availability.ServiceControl);

            if (Patient != null)
            {
                ActivityMove movePatientToSpecialTreatment
                    = new ActivityMove(jointControl,
                                       Patient,
                                       ParentControlUnit,
                                       Availability.ServiceControl,
                                       ReturnDelegate,
                                       jointControl.InputData.DurationMove(Patient,
                                                                           ParentControlUnit,
                                                                           Availability.ServiceControl));
                SequentialEvents.Add(movePatientToSpecialTreatment.StartEvent);
            } // end if
        }     // end of Trigger
Пример #8
0
        } // end of EventType

        #endregion

        #region Trigger

        /// <summary>
        /// Trigger method of the event.
        /// </summary>
        /// <param name="time">Time when event is triggered</param>
        /// <param name="simEngine">SimEngine that executes the model</param>
        public void Trigger(DateTime time, ISimulationEngine simEngine)
        {
            foreach (Entity entity in AffectedEntities)
            {
                // if the parent control unit of the entity is already set it is checked if the
                // parent control unit differs from the control the event is hosted.
                // If it is different it is changed to the parent control of the event and the entity is
                // added to this control unit
                if (entity.ParentControlUnit != null)
                {
                    if (entity.ParentControlUnit != ParentControlUnit)
                    {
                        entity.ParentControlUnit.RemoveEntity(entity);
                        ParentControlUnit.AddEntity(entity);
                    }
                }
                // if the entities parent control is not set it is added to the parent control of the event
                else
                {
                    ParentControlUnit.AddEntity(entity);
                }
            } // endforeach

            // custom state change of the event, cann be overwritten by the user
            StateChange(time, simEngine);

            // the event is logged at the used simulation engine
            simEngine.LogEvent(this);

            // sequential events are triggered, they might be defined by custom state change method.
            foreach (Event seqEvent in SequentialEvents)
            {
                seqEvent.Trigger(time, simEngine);
            } // end foreach

            // The behavior occured flag of the parent control is set to true
            ParentControlUnit.BehaviorOccured = true;

            // sequential eventy are cleared
            SequentialEvents.Clear();
        } // end of Trigger
        } // end of Event

        #endregion

        //--------------------------------------------------------------------------------------------------
        // State Change
        //--------------------------------------------------------------------------------------------------

        #region StateChange

        /// <summary>
        /// Overriden state change of the event. If the patient is arrving externaly then the next arrival is
        /// scheduled. Else the path is updated and the next/first action is taken from the path.
        /// </summary>
        /// <param name="time">Time the patient arrives</param>
        /// <param name="simEngine">SimEngine responsible for simulation execution</param>
        protected override void StateChange(DateTime time, ISimulationEngine simEngine)
        {
            // if patient has a path it is updated
            if (Patient.EmergencyTreatmentPath != null)
            {
                Patient.EmergencyTreatmentPath.UpdateNextAction();
            }
            else
            {
                // if patient has no path he is arriving externaly

                // path is created
                Patient.EmergencyTreatmentPath = ((ControlUnitEmergency)ParentControlUnit).InputData.CreateEmergencyPath(Patient);

                // patient is added to control unit
                ParentControlUnit.AddEntity(Patient);

                // arrival of next patient is created and scheduled
                EntityPatient nextPatient = ((ControlUnitEmergency)ParentControlUnit).InputData.GetNextPatient();

                EventEmergencyPatientArrival nextPatientArrival = new EventEmergencyPatientArrival(ParentControlUnit, nextPatient, InputData);

                simEngine.AddScheduledEvent(nextPatientArrival, time + ((ControlUnitEmergency)ParentControlUnit).InputData.PatientArrivalTime(time));
            } // end if

            // next action on path is taken
            if (Patient.EmergencyTreatmentPath.TakeNextAction(simEngine, this, time, ParentControlUnit))
            {
                // possible waiting or waiting in facility is triggered
                if (Patient.OccupiedFacility == null || Patient.OccupiedFacility.ParentDepartmentControl != ParentControlUnit)
                {
                    SequentialEvents.Add(Patient.StartWaitingActivity(((ControlUnitEmergency)ParentControlUnit).WaitingAreaPatientForNextActionType(Patient.EmergencyTreatmentPath.GetCurrentActionType())));
                }
                else
                {
                    ActivityWaitInFacility waitInFacility = new ActivityWaitInFacility(ParentControlUnit, Patient, Patient.OccupiedFacility);
                    SequentialEvents.Add(waitInFacility.StartEvent);
                } // end if
            }     // end if
        }         // end of Trigger
Пример #10
0
        } // end of InputData

        #endregion

        //--------------------------------------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------------------------------------

        #region StateChange

        /// <summary>
        /// Overriden state change. Initializes a new arrival and patient paths and first action.
        /// </summary>
        /// <param name="time">Time the patient arrives</param>
        /// <param name="simEngine">SimEngine responsible for simulation execution</param>
        protected override void StateChange(DateTime time, ISimulationEngine simEngine)
        {
            Patient.OutpatientTreatmentPath =
                InputData.CreateOutpatientTreatmentPath(Patient,
                                                        null,
                                                        time,
                                                        true);

            ParentControlUnit.AddEntity(Patient);

            DateTime nextTime;;

            EntityPatient nextPatient = InputData.GetNextWalkInPatient(out nextTime, ParentControlUnit, time);

            EventOutpatientWalkInPatientArrival nextPatientArrival = new EventOutpatientWalkInPatientArrival(ParentControlUnit, InputData, nextPatient);

            simEngine.AddScheduledEvent(nextPatientArrival, nextTime);

            if (Patient.EmergencyTreatmentPath.TakeNextAction(simEngine, this, time, ParentControlUnit))
            {
                SequentialEvents.Add(Patient.StartWaitingActivity());
            } // end if
        }     // end of StateChange
Пример #11
0
        } // end of EventStaffChange

        #endregion

        //--------------------------------------------------------------------------------------------------
        // State Change
        //--------------------------------------------------------------------------------------------------

        #region Trigger

        /// <summary>
        /// STaff is removed from control unit
        /// </summary>
        /// <param name="time">Time staff is leaving</param>
        /// <param name="simEngine">SimEngine responsible for simulation execution</param>
        protected override void StateChange(DateTime time, ISimulationEngine simEngine)
        {
            ParentControlUnit.RemoveEntity(StaffLeaving);
        } // end of Trigger
Пример #12
0
        } // end of TriggerStartEvent

        #endregion

        #region TriggerEndEvent

        /// <summary>
        /// State changes of the activities end event. Most state changes are standardized and configurable via input.
        /// </summary>
        /// <param name="time"> time of activity start</param>
        /// <param name="simEngine"> SimEngine the handles the activity triggering</param>
        override public void StateChangeEndEvent(DateTime time, ISimulationEngine simEngine)
        {
            //--------------------------------------------------------------------------------------------------
            // Some activities define the end of corresponding doctor, nurses for future reference
            //--------------------------------------------------------------------------------------------------

            #region CorrespondingStaff

            if (ActionType.DefinesCorrespondingDocEnd)
            {
                Patient.CorrespondingDoctor = null;
                ResourceSet.MainDoctor.RemovePatient(Patient);
            } // end if

            if (ActionType.DefinesCorrespondingNurseEnd)
            {
                Patient.CorrespondingNurse = null;
                ResourceSet.MainNurse.RemovePatient(Patient);
            } // end if

            #endregion

            //--------------------------------------------------------------------------------------------------
            // Occupation
            //--------------------------------------------------------------------------------------------------

            #region Occupation

            if (ResourceSet.TreatmentFacility is EntityMultiplePatientTreatmentFacility)
            {
                ((EntityMultiplePatientTreatmentFacility)ResourceSet.TreatmentFacility).HoldedEntities.Remove(Patient);
            }
            else
            {
                ResourceSet.TreatmentFacility.Occupied = false;

                //--------------------------------------------------------------------------------------------------
                // in case patient blocking is released required actions are taken
                //--------------------------------------------------------------------------------------------------
                if (ActionType.DefinesFacilitiyOccupationEnd)
                {
                    // facility is released
                    ResourceSet.TreatmentFacility.PatientBlocking = null;

                    // facility is removed from patient
                    Patient.OccupiedFacility = null;
                } // end if
            }     // end if
            #endregion

            //--------------------------------------------------------------------------------------------------
            // If treatment has doctor(s), busyFactors are assigned
            //--------------------------------------------------------------------------------------------------

            #region AssignBusyFactorsDoctors

            if (ResourceSet.MainDoctor != null)
            {
                ResourceSet.MainDoctor.BusyFactor           -= ActionType.BusyFactorDoctor;
                ResourceSet.MainDoctor.BlockedForDispatching = false;
            } // end if

            if (ResourceSet.AssistingDoctors != null)
            {
                if (ResourceSet.AssistingDoctors.Length != ActionType.BusyFactorAssistingDoctors.Length)
                {
                    throw new InvalidOperationException();
                }

                for (int i = 0; i < ResourceSet.AssistingDoctors.Length; i++)
                {
                    ResourceSet.AssistingDoctors[i].BusyFactor           -= ActionType.BusyFactorAssistingDoctors[i];
                    ResourceSet.AssistingDoctors[i].BlockedForDispatching = false;
                } // end for
            }     // end if

            #endregion

            //--------------------------------------------------------------------------------------------------
            // If treatment has nurse(s), busyFactors are assigned
            //--------------------------------------------------------------------------------------------------

            #region AssignBusyFactorsNurses

            if (ResourceSet.MainNurse != null)
            {
                ResourceSet.MainNurse.BusyFactor -= ActionType.BusyFactorNurse;
            }

            if (ResourceSet.AssistingNurses != null)
            {
                if (ResourceSet.AssistingNurses.Length != ActionType.BusyFactorAssistingNurses.Length)
                {
                    throw new InvalidOperationException();
                }

                for (int i = 0; i < ResourceSet.AssistingNurses.Length; i++)
                {
                    ResourceSet.AssistingNurses[i].BusyFactor -= ActionType.BusyFactorAssistingNurses[i];
                } // end for
            }     // end if

            #endregion

            T nextActionType = PatientPath.GetCurrentActionType();

            //--------------------------------------------------------------------------------------------------
            // Preemption
            //--------------------------------------------------------------------------------------------------

            #region Preempted

            if (!HoldingRequired)
            {
                if (Duration.Ticks > 0)
                {
                    DegreeOfCompletion += (double)(time - StartTime).Ticks / Duration.Ticks;
                }
                else
                {
                    DegreeOfCompletion = 1;
                }

                if (Math.Abs(DegreeOfCompletion - 1) > Helpers <double> .GetNumbericalPrecission())
                {
                    RequestHealthCareAction <T> req =
                        new RequestHealthCareAction <T>(Patient,
                                                        DegreeOfCompletion,
                                                        ActionType,
                                                        time,
                                                        ResourceSet);

                    ParentControlUnit.AddRequest(req);
                    simEngine.RemoveScheduledEvent(EndEvent);
                    EndEvent.SequentialEvents.Add(Patient.StartWaitingActivity(ParentDepartmentControl.WaitingAreaPatientForNextActionType(nextActionType)));
                    return;
                } // end if
            }     // end if

            #endregion

            #region NextActions

            //--------------------------------------------------------------------------------------------------
            // In case of an holding treatment the next action was already taken
            //--------------------------------------------------------------------------------------------------

            if (!HoldingRequired)
            {
                if (PatientPath.TakeNextAction(simEngine,
                                               EndEvent,
                                               time,
                                               ParentControlUnit))
                {
                    // either waiting or waiting in the treatment facility is launched
                    if (Patient.OccupiedFacility == null || Patient.OccupiedFacility.ParentDepartmentControl != ParentDepartmentControl)
                    {
                        EndEvent.SequentialEvents.Add(Patient.StartWaitingActivity(ParentDepartmentControl.WaitingAreaPatientForNextActionType(nextActionType)));
                    }
                    else
                    {
                        ActivityWaitInFacility waitInFacility = new ActivityWaitInFacility(ParentControlUnit, Patient, Patient.OccupiedFacility);
                        EndEvent.SequentialEvents.Add(waitInFacility.StartEvent);
                    } // end if
                }     // end if
                  //--------------------------------------------------------------------------------------------------
                  // Possible waiting activities are started
                  //--------------------------------------------------------------------------------------------------

                #region StartWaitingActivities

                if (ResourceSet.MainDoctor != null && ResourceSet.MainDoctor.GetCurrentActivities().Count == 1)
                {
                    EndEvent.SequentialEvents.Add(ResourceSet.MainDoctor.StartWaitingActivity(ParentDepartmentControl.WaitingRoomForStaff(ResourceSet.MainDoctor)));
                }

                if (ResourceSet.AssistingDoctors != null)
                {
                    foreach (EntityDoctor doc in ResourceSet.AssistingDoctors)
                    {
                        if (doc.GetCurrentActivities().Count == 1)
                        {
                            EndEvent.SequentialEvents.Add(doc.StartWaitingActivity(ParentDepartmentControl.WaitingRoomForStaff(doc)));
                        }
                    } // end foreach
                }     // end if

                if (ResourceSet.MainNurse != null && ResourceSet.MainNurse.GetCurrentActivities().Count == 1)
                {
                    EndEvent.SequentialEvents.Add(ResourceSet.MainNurse.StartWaitingActivity(ParentDepartmentControl.WaitingRoomForStaff(ResourceSet.MainDoctor)));
                }

                if (ResourceSet.AssistingNurses != null)
                {
                    foreach (EntityNurse nurse in ResourceSet.AssistingNurses)
                    {
                        if (nurse.GetCurrentActivities().Count == 1)
                        {
                            EndEvent.SequentialEvents.Add(nurse.StartWaitingActivity(ParentDepartmentControl.WaitingRoomForStaff(nurse)));
                        }
                    } // end foreach
                }     // end if

                #endregion
            }

            #endregion

            #region ReleaseHolding

            if (ActionType.IsHold)
            {
                foreach (EntityStaff staff in AffectedEntities.Where(p => p is EntityStaff))
                {
                    staff.OnHold = false;
                } // end foreach
                return;
            }     // end if

            #endregion
        } // end of TriggerEndEvent