/// <summary> /// Initialization: Patient arrival stream for waiting list patients is initialized. /// If dispatching is done at discrete events this stream is initialized as well. /// </summary> /// <param name="startTime">Time the simulation starts</param> /// <param name="simEngine">SimEngine that handles the simulation run</param> protected override void CustomInitialize(DateTime startTime, ISimulationEngine simEngine) { WaitingListSchedule.Initialize(startTime); AddEntity((EntityWaitingListSchedule)WaitingListSchedule); DateTime nextArrivalTime; Admission admission; EntityPatient newPatient = InputData.GetNextWaitingListPatient(out nextArrivalTime, out admission, this, startTime); if (newPatient != null) { EventOutpatientWaitingListPatientArrival nextArrival = new EventOutpatientWaitingListPatientArrival(this, (ControlUnitOutpatient)ParentControlUnit, newPatient, admission, InputData); simEngine.AddScheduledEvent(nextArrival, nextArrivalTime); } // end if WaitingListSchedule.ReadyForDispatch = true; if (AssigningSlotsAtEvents) { EventOutpatientStartDispatching nextDispatch = new EventOutpatientStartDispatching(this, WaitingListSchedule, InputData); simEngine.AddScheduledEvent(nextDispatch, InputData.NextDispatching(startTime)); WaitingListSchedule.ReadyForDispatch = false; } } // end of Initialize
protected override void CustomInitialize(DateTime startTime, ISimulationEngine simEngine) { if (startTime.Date + InputData.InPatientStartTime() >= startTime) { simEngine.AddScheduledEvent(new EventInpatientDayStart(this), startTime + InputData.InPatientStartTime()); } else { simEngine.AddScheduledEvent(new EventInpatientDayStart(this), startTime.Date + TimeSpan.FromDays(1) + InputData.InPatientStartTime()); } // end if } // end of Initialize
} // end of AffectedEntities #endregion //-------------------------------------------------------------------------------------------------- // Events //-------------------------------------------------------------------------------------------------- #region TriggerStartEvent /// <summary> /// Overrides the state change at start. Server is not idle, and end event is triggered. /// </summary> override public void StateChangeStartEvent(DateTime time, ISimulationEngine simEngine) { double serviceTimeMinutes = ((SimulationModelQueuing)ParentControlUnit.ParentSimulationModel).ServiceTime; Server.IsIdle = false; simEngine.AddScheduledEvent(EndEvent, time + TimeSpan.FromMinutes(Distributions.Instance.Exponential(serviceTimeMinutes))); } // end of TriggerStartEvent
} // end of ControlUnit #endregion #region Initialize /// <summary> /// Initializes patient stream /// </summary> /// <param name="startTime">Start time of the simulation model</param> /// <param name="simEngine">SimEngine responsible for simulation execution</param> protected override void CustomInitialize(DateTime startTime, ISimulationEngine simEngine) { EntityPatient patient = InputData.GetNextPatient(); EventEmergencyPatientArrival firstPatient = new EventEmergencyPatientArrival(this, patient, InputData); simEngine.AddScheduledEvent(firstPatient, startTime + InputData.PatientArrivalTime(startTime)); } // end of Initialize
} // 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 Event #endregion //-------------------------------------------------------------------------------------------------- // State Change //-------------------------------------------------------------------------------------------------- #region Trigger /// <summary> /// State change of event. Sets Dispatching flag to true and schedules next event. /// </summary> /// <param name="time">Current time</param> /// <param name="simEngine">SimEngine responsible for simulation execution</param> protected override void StateChange(DateTime time, ISimulationEngine simEngine) { WaitingListSchedule.ReadyForDispatch = true; EventOutpatientStartDispatching nextDispatch = new EventOutpatientStartDispatching(ParentControlUnit, WaitingListSchedule, InputData); simEngine.AddScheduledEvent(nextDispatch, InputData.NextDispatching(time)); } // end of Trigger
} // end of #endregion #region Initialize /// <summary> /// Arrival stream of clients is initialized /// </summary> /// <param name="startTime">Start time of simulation</param> /// <param name="simEngine">End time of simulation</param> protected override void CustomInitialize(DateTime startTime, ISimulationEngine simEngine) { EntityClient nextClient = new EntityClient(); EventClientArrival nextClientArrival = new EventClientArrival(this, nextClient); double arrivalTimeMinutes = ((SimulationModelQueuing)ParentSimulationModel).ArrivalTime; simEngine.AddScheduledEvent(nextClientArrival, startTime + TimeSpan.FromMinutes(Distributions.Instance.Exponential(arrivalTimeMinutes))); } // end of CustomInitialize
} // end of OutpatientControlUnit #endregion #region Initialize /// <summary> /// Initializes walk in patient stream /// </summary> /// <param name="startTime">Start time of the simulation model</param> /// <param name="simEngine">SimEngine responsible for simulation execution</param> protected override void CustomInitialize(DateTime startTime, ISimulationEngine simEngine) { DateTime arrivalWalkIn; EntityPatient patient = InputData.GetNextWalkInPatient(out arrivalWalkIn, ParentControlUnit, startTime); if (patient != null) { EventOutpatientWalkInPatientArrival firstPatient = new EventOutpatientWalkInPatientArrival(this, InputData, patient); simEngine.AddScheduledEvent(firstPatient, arrivalWalkIn); } // end if } // end of Initialize
} // end of ControlUnitOutpatient #endregion #region Initialize /// <summary> /// Overrides basic initialiing method. Besides standard operations a possible walk in stream of /// patients is /// </summary> /// <param name="startTime">Time the simulation starts</param> /// <param name="simEngine">SimEngine that handles the simulation run</param> public override void Initialize(DateTime startTime, ISimulationEngine simEngine) { base.Initialize(startTime, simEngine); EntityPatient nextPatient = null; DateTime nextArrivalTime; if ((nextPatient = InputData.GetNextWalkInPatient(out nextArrivalTime, this, startTime)) != null) { EventOutpatientWalkInPatientArrival nextArrival = new EventOutpatientWalkInPatientArrival(this, InputData, nextPatient); simEngine.AddScheduledEvent(nextArrival, nextArrivalTime); } // end if } // end of CustomInitialize
} // 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
} // end of Event #endregion //-------------------------------------------------------------------------------------------------- // State Change //-------------------------------------------------------------------------------------------------- #region Trigger /// <summary> /// State chage of event. Checks if patient comes from outside of the model. In that case /// a new event is triggered. Waiting for assign slot is started. /// </summary> /// <param name="time">Arriving time</param> /// <param name="simEngine">SimEngine responsible for simulation execution</param> protected override void StateChange(DateTime time, ISimulationEngine simEngine) { if (AdmissionType.IsExtern) { DateTime nextArrivalTime; Admission admission; EntityPatient newPatient = InputData.GetNextWaitingListPatient(out nextArrivalTime, out admission, ParentControlUnit, time); if (newPatient != null) { EventOutpatientWaitingListPatientArrival nextArrival = new EventOutpatientWaitingListPatientArrival(ParentControlUnit, OutpatientControlUnit, newPatient, admission, InputData); simEngine.AddScheduledEvent(nextArrival, nextArrivalTime); } // end if } // end if DateTime earliestTime = (time + TimeSpan.FromDays(AdmissionType.MinDaySpan)).Date; DateTime latestTime = DateTime.MaxValue; if (AdmissionType.MaxDaySpan < double.MaxValue) { latestTime = (time + TimeSpan.FromDays(AdmissionType.MaxDaySpan)).Date; } ActivityOutpatientWaitingListWaitToAssignSlot waitForAssignment = new ActivityOutpatientWaitingListWaitToAssignSlot(ParentControlUnit, Patient, AdmissionType, earliestTime, latestTime); SequentialEvents.Add(waitForAssignment.StartEvent); } // 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
} // 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
} // end of EventStaffChange #endregion //-------------------------------------------------------------------------------------------------- // State Change //-------------------------------------------------------------------------------------------------- #region Trigger /// <summary> /// Overrides the state change method, staffing levels will change, for leaving /// staff requests for absence are filed, incoming staff is added to the /// parent control unit /// </summary> /// <param name="time">Time the staffing changes</param> /// <param name="simEngine">SimEngine responsible for simulation execution</param> protected override void StateChange(DateTime time, ISimulationEngine simEngine) { // foreach leaving staff a request to be absent is filed at their control unit // arriving staff is automatically added to the control by the triggering // of the event foreach (ResourceAssignmentStaff staffAssignment in StaffLeaving) { ParentDepartmentControl.AddRequest(new RequestBeAbsent(staffAssignment.Resource, time)); staffAssignment.Resource.StaffOutsideShift = true; } // end foreach foreach (ResourceAssignmentStaff staffAssignment in StaffAriving) { staffAssignment.Resource.StaffOutsideShift = false; staffAssignment.Resource.BlockedForDispatching = false; staffAssignment.Resource.BaseControlUnit = ParentDepartmentControl; staffAssignment.Resource.AssignmentType = staffAssignment.AssignmentType; if (staffAssignment.OrganizationalUnit == "RootDepartment") { ParentDepartmentControl.AddEntity(staffAssignment.Resource); } else { ParentDepartmentControl.OrganizationalUnitPerName[staffAssignment.OrganizationalUnit].AddEntity(staffAssignment.Resource); } SequentialEvents.Add(staffAssignment.Resource.StartWaitingActivity(ParentDepartmentControl.WaitingRoomForStaff(staffAssignment.Resource))); } // end foreach DateTime nextTime; // schedule the next staff change Event nextChange = StaffHandler.GetNextStaffChangingEvent(ParentDepartmentControl, time, out nextTime); simEngine.AddScheduledEvent(nextChange, nextTime); } // end of Trigger
} // end of ControlUnitHealthCare #endregion #region Initialize /// <summary> /// Overrides the base initialize method of control units. All staff members, treatment facilities /// and waiting areas are intialized and assigned to sub organizational control units and structural areas /// </summary> /// <param name="startTime">Time the simulation starts</param> /// <param name="simEngine">SimEngine that handles the simulation run</param> public override void Initialize(DateTime startTime, ISimulationEngine simEngine) { #region TreatmentFacilityInitialize string[] structuralAreaIdentifier = InputData.GetStructuralAreaIdentifiers(); Dictionary <string, StructuralArea> strucArePerName = new Dictionary <string, StructuralArea>(); // create all structural areas that occur in waiting areas and treamtent facilities foreach (string identifier in structuralAreaIdentifier) { strucArePerName.Add(identifier, new StructuralArea(identifier)); } // end foreach _assingedTreatmentFacilities = new List <EntityTreatmentFacility>(); ResourceAssignmentPhysical <EntityTreatmentFacility>[] treatmentFacilityAssigns = InputData.GetTreatmentFacilities(); // assign treatment facilities to organizational and structural areas foreach (ResourceAssignmentPhysical <EntityTreatmentFacility> assignment in treatmentFacilityAssigns) { assignment.Resource.SetParentDepartmentControl(this); assignment.Resource.AssignmentType = assignment.AssignmentType; if (assignment.OrganizationalUnit != "RootDepartment") { // the facility is assigned to the specified organizational control OrganizationalUnitPerName[assignment.OrganizationalUnit].AddEntity(assignment.Resource); OrganizationalUnitPerName[assignment.OrganizationalUnit].AddAssignedTreatmentFacility(assignment.Resource); } else { // if no organizational area was specified or the root department was specified // the facility is added in the department control AddEntity(assignment.Resource); AssignedTreatmentFacilities.Add(assignment.Resource); } // end if // faciltiy is added to the specified structural area if (!strucArePerName.ContainsKey(assignment.StructuralArea)) { throw new InvalidOperationException("Structural area identifier not specified"); } if (assignment.Resource is EntityMultiplePatientTreatmentFacility) { strucArePerName[assignment.StructuralArea].MultiplePatientTreatmentFacilities.Add((EntityMultiplePatientTreatmentFacility)assignment.Resource); } else { strucArePerName[assignment.StructuralArea].TreatmentFacilities.Add(assignment.Resource); } } // end foreach #endregion #region WaitingAreas // same principle as for treatment facility is used for waiting areas foreach (ResourceAssignmentPhysical <EntityWaitingArea> waitingRoomAssignment in InputData.GetWaitingRoomPatients()) { if (waitingRoomAssignment.OrganizationalUnit != "RootDepartment") { OrganizationalUnitPerName[waitingRoomAssignment.OrganizationalUnit].AddEntity(waitingRoomAssignment.Resource); } else { AddEntity(waitingRoomAssignment.Resource); } // end if if (!strucArePerName.ContainsKey(waitingRoomAssignment.StructuralArea)) { throw new InvalidOperationException("Structural area identifier not specified"); } strucArePerName[waitingRoomAssignment.StructuralArea].WaitingAreasPatients.Add(waitingRoomAssignment.Resource); } // end foreach foreach (ResourceAssignmentPhysical <EntityWaitingArea> waitingRoomAssignment in InputData.GetWaitingRoomsStaff()) { if (waitingRoomAssignment.OrganizationalUnit != "RootDepartment") { OrganizationalUnitPerName[waitingRoomAssignment.OrganizationalUnit].AddEntity(waitingRoomAssignment.Resource); } else { AddEntity(waitingRoomAssignment.Resource); } // end if if (!strucArePerName.ContainsKey(waitingRoomAssignment.StructuralArea)) { throw new InvalidOperationException("Structural area identifier not specified"); } strucArePerName[waitingRoomAssignment.StructuralArea].StaffWaitingRoom = waitingRoomAssignment.Resource; } // end foreach #endregion _structuralAres = strucArePerName.Values.ToArray(); #region StaffInitialze // the starting staff assignements specified by the input is obtained List <ResourceAssignmentStaff> staffAssignments = InputData.StaffHandler.GetStartingStaff(startTime); foreach (ResourceAssignmentStaff staffAssignment in staffAssignments) { staffAssignment.Resource.StaffOutsideShift = false; staffAssignment.Resource.BlockedForDispatching = false; staffAssignment.Resource.BaseControlUnit = this; staffAssignment.Resource.AssignmentType = staffAssignment.AssignmentType; // staff is either assigned to a organizational control or the department control if (staffAssignment.OrganizationalUnit == "RootDepartment") { AddEntity(staffAssignment.Resource); } else { OrganizationalUnitPerName[staffAssignment.OrganizationalUnit].AddEntity(staffAssignment.Resource); } } // end foreach DateTime nextStaffChange; // the next time the staffing levels change an event is scheduled with the associated staff changes Event staffChangeEvent = InputData.StaffHandler.GetNextStaffChangingEvent(this, startTime, out nextStaffChange); simEngine.AddScheduledEvent(staffChangeEvent, nextStaffChange); // all hanlded staff members (doctors and nurses) are sent in a waiting activity foreach (EntityDoctor doc in HandledDoctors) { Event docWait = doc.StartWaitingActivity(WaitingRoomForStaff(doc)); docWait.Trigger(startTime, simEngine); } // end foreach foreach (EntityNurse nurse in HandledNurses) { Event nurseWait = nurse.StartWaitingActivity(WaitingRoomForStaff(nurse)); nurseWait.Trigger(startTime, simEngine); } // end foreach #endregion // base initializ is called to move down the tree base.Initialize(startTime, simEngine); } // end of Initilaize
} // end of ParentDepartmentControl #endregion //-------------------------------------------------------------------------------------------------- // Events //-------------------------------------------------------------------------------------------------- #region TriggerStartEvent /// <summary> /// State changes of the activities start 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 StateChangeStartEvent(DateTime time, ISimulationEngine simEngine) { //-------------------------------------------------------------------------------------------------- // Some activities define the start of corresponding doctor, nurses for future reference //-------------------------------------------------------------------------------------------------- #region CorrespondingStaff if (ActionType.DefinesCorrespondingDocStart) { Patient.CorrespondingDoctor = ResourceSet.MainDoctor; ResourceSet.MainDoctor.AddPatient(Patient); } // end if if (ActionType.DefinesCorrespondingNurseStart) { Patient.CorrespondingNurse = ResourceSet.MainNurse; ResourceSet.MainNurse.AddPatient(Patient); } // end if #endregion //-------------------------------------------------------------------------------------------------- // If treatment has doctor(s), busyFactors are assigned //-------------------------------------------------------------------------------------------------- #region AssignBusyFactorsDoctors if (ResourceSet.MainDoctor != null) { ResourceSet.MainDoctor.BusyFactor += ActionType.BusyFactorDoctor; } 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]; } // 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 //-------------------------------------------------------------------------------------------------- // Preemption //-------------------------------------------------------------------------------------------------- #region Preemption // in case the activity was preempted only the remaining duration is considered for scheduling // the end event if (DegreeOfCompletion > 0) { DateTime endTime = time + Helpers <double> .MultiplyTimeSpan(Duration, (1 - DegreeOfCompletion)); simEngine.AddScheduledEvent(this.EndEvent, endTime); return; } // end if #endregion //-------------------------------------------------------------------------------------------------- // Occupation //-------------------------------------------------------------------------------------------------- #region Occupation // in case of a multiple patient treatment facility the patient // is added to the holdeld entities if (ResourceSet.TreatmentFacility is EntityMultiplePatientTreatmentFacility) { ((EntityMultiplePatientTreatmentFacility)ResourceSet.TreatmentFacility).HoldedEntities.Add(Patient); } else { //-------------------------------------------------------------------------------------------------- // Set treatmentBooth to occupied //-------------------------------------------------------------------------------------------------- ResourceSet.TreatmentFacility.Occupied = true; //-------------------------------------------------------------------------------------------------- // in case patient is blocking the facility required actions are taken //-------------------------------------------------------------------------------------------------- if (ActionType.DefinesFacilitiyOccupationStart) { // facility is blocked for patient ResourceSet.TreatmentFacility.PatientBlocking = Patient; // facility is assigned to patient Patient.OccupiedFacility = ResourceSet.TreatmentFacility; } // end if } // end if #endregion //-------------------------------------------------------------------------------------------------- // Updating of next Acion and possible skipping of latter //-------------------------------------------------------------------------------------------------- #region UpdateNextAction PatientPath.UpdateNextAction(); T nextActionType = PatientPath.GetCurrentActionType(); #endregion #region PossibleSkipOfNextAction //-------------------------------------------------------------------------------------------------- // A treatment may be skipped, e.g. in case that the current doctor is qualified enough // This is defined via the input //-------------------------------------------------------------------------------------------------- while (ParentDepartmentControl.SkipNextAction(Patient, ResourceSet.MainDoctor, ActionType, PatientPath.GetCurrentActionType())) { PatientPath.UpdateNextAction(); nextActionType = PatientPath.GetCurrentActionType(); } // end if #endregion //-------------------------------------------------------------------------------------------------- // In case a holding Activity follows no end event is scheduled //-------------------------------------------------------------------------------------------------- #region HoldingOfPatient if (ActionType.IsHold) { // Staff on hold flag is set to true foreach (EntityStaff staff in AffectedEntities.Where(p => p is EntityStaff)) { staff.OnHold = true; } // end foreach HoldingRequired = true; // in case of holding the next action on the path is taken if (PatientPath.TakeNextAction(simEngine, StartEvent, 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 } else { // if the activity is not hold the end event is scheduled Duration = InputData.PatientActionTime(Patient, ResourceSet, ActionType); DateTime endTime = time + Duration; simEngine.AddScheduledEvent(this.EndEvent, endTime); } // end if #endregion } // end of TriggerStartEvent
} // end of AffectedEntities #endregion //-------------------------------------------------------------------------------------------------- // Events //-------------------------------------------------------------------------------------------------- #region TriggerStartEvent /// <summary> /// Actual state change, calls the leaving method of the origin control unit and scheduled the end event /// </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) { Origin.EntityLeaveControlUnit(time, simEngine, MovingEntity, DelegateOrigin); _endTime = time + Duration; simEngine.AddScheduledEvent(EndEvent, time + Duration); } // end of TriggerStartEvent