} // 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 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