/// <summary> /// An event that's called everytime the HotelEventManager pushes out an HotelEvent. /// </summary> /// <param name="Event">The HotelEvent containing event information.</param> public void Notify(HotelEvent Event) { //If the Cleaner is evacuating it should ignore all other Events and abandon all tasks in the CleanerTasks Queue. if (Status != HotelEventType.EVACUATE) { #region EVACUATE //Clears the CurrentTask and the Task Queue (because they need to evacuate) //When an EVACUATE event is called the Cleaner calculates the quickest route to the Reception if (Event.EventType == HotelEventType.EVACUATE) { CurrentTask = null; CleanerTasks.Clear(); Status = HotelEventType.EVACUATE; Destination = Hotel.Reception.Node; Path = Graph.QuickestRoute(Hotel.Floors[PositionY].Areas[PositionX].Node, Destination, true, true); } #endregion #region CLEANING_EMERGENCY //CLEANING_EMERGENCY should be treated as a regular task for the Cleaner if (Event.EventType == HotelEventType.CLEANING_EMERGENCY) { //In the int[] all the data that is given by the Event will be placed int[] Data = PullIntsFromString(Event.Data.Values.ToList()); for (int i = 0; i < GlobalStatistics.Rooms.Count; i++) { //If the given ID matches the ID of a Room, it will be given to the Cleaner as a task if (GlobalStatistics.Rooms[i].ID == Data[0]) { //The time that it's take to clean during a CLEANING_EMERGENCY is given withint the Data Dictionairy CleanRoom(new CleanRoom() { RoomToClean = GlobalStatistics.Rooms[i].Node, TimeToClean = Data[1] }); break; } } } #endregion } }
/// <summary> /// Enqueues a new Task for the Cleaner to do. /// </summary> /// <param name="RoomToClean">The CleanRoom task that the Cleaner needs to fullfill.</param> public void CleanRoom(CleanRoom RoomToClean) { CleanerTasks.Enqueue(RoomToClean); }
/// <summary> /// Moves the Cleaner depending on what Task is enqueued and what their Status is. /// </summary> public void Move() { //Since the applications is Multi-Threaded (runs on multiple threads due to the HotelEventManager) //This can't be added to the HotelEventManager when created through an Event //That's why it's called on the Main Application thread and not on the HotelEventManger thread if (!IsRegistered) { HotelEventManager.Register(this); IsRegistered = true; } #region Task Assignment //Gives the Cleaner a task if they don't have one and if there's a Queue of CleanerTasks if (CurrentTask == null && CleanerTasks.Count > 0) { CurrentTask = CleanerTasks.Dequeue(); } //If the Cleaner has nothing to do they need to move to their Optimal Position else if (CurrentTask == null && Destination == null && CleanerTasks.Count == 0) { MoveToOptimalPosition(); } #endregion #region Pathfinding to Cleaning Task //If the Cleaner has a Task and the Destination is null (or the current Position of the Cleaner) //The Path will be set for the Cleaner if (CurrentTask != null && (Destination == null || Destination == Hotel.Floors[PositionY].Areas[PositionX].Node)) { Destination = CurrentTask.RoomToClean; Path = Graph.QuickestRoute(Hotel.Floors[PositionY].Areas[PositionX].Node, Destination, true, true); } #endregion #region Performing Cleaning Task //If the Cleaner is standing on the Room Node that needs to be cleaned //Then the Room's IsDirty state will change to true and the Room will be cleaned if (CurrentTask != null && Hotel.Floors[PositionY].Areas[PositionX].Node == CurrentTask.RoomToClean) { //If the Room isn't being cleaned yet, the Room's IsDirty state will change to true and the cleaning time will be equal to the one set in the Task if (((Room)CurrentTask.RoomToClean.Area).CleaningTime == 0 && ((Room)CurrentTask.RoomToClean.Area).IsDirty == true) { ((Room)CurrentTask.RoomToClean.Area).CleaningTime = CurrentTask.TimeToClean; IsVisible = false; } else { //If the Room is currently being cleaned then the CleaningTime should go down with 1 (since this method is called every 1 HTE) if (((Room)CurrentTask.RoomToClean.Area).CleaningTime > 0) { ((Room)CurrentTask.RoomToClean.Area).CleaningTime--; //If the Room is done being cleaned, then the Cleaner needs to be visible again and the CurrentTask is done //The Room's IsDirty state will change to false and the room is able to be used again if (((Room)CurrentTask.RoomToClean.Area).CleaningTime == 0) { ((Room)CurrentTask.RoomToClean.Area).IsDirty = false; IsVisible = true; CurrentTask = null; Destination = null; } } } } #endregion //There's a better explenation about the PathFinding in the References folder (a document called "Project Hotel - Documentatie.docx") if (Path != null) { #region ToElevator //If the Cleaner is in front of the Elevator we will check if it's still efficient to use the Elevator or the Stairs if (Path.RouteType == ERouteType.ToElevator && Hotel.Floors[PositionY].Areas[PositionX - 1].AreaType == EAreaType.ElevatorShaft) { GetRoute(); } //If the Cleaner is not in front of the Elevator yet, they will walk towards the Elevator by Dequeueing Nodes else if (Path.RouteType == ERouteType.ToElevator && Path.PathToElevator.Count != 0) { //The Node contains all the info for the Cleaner to move forward (an X and Y co-ordinate) Node moveNode = Path.PathToElevator.Dequeue(); PositionX = moveNode.Area.PositionX; PositionY = moveNode.Area.PositionY; } #endregion #region Elevator //If the Cleaner has decided to take the Elevator then we're going to try and enter the Elevator if (Path.RouteType == ERouteType.Elevator) { //If the Cleaner isn't in the Elevator we're going to try and request it if (!IsInElevator) { //If the Cleaner is in front of the Elevator they will enter the Elevator and request the floor (int) that they need to go too if (Hotel.Elevator.GetElevatorInfo().Item2 == PositionY && Hotel.Floors[PositionY].Areas[PositionX - 1].AreaType == EAreaType.ElevatorShaft && !IsInElevator) { //Cleaner Requests the Elevator with their desired Floor Hotel.Elevator.RequestElevator(Destination.Floor); //If the Elevator is on their left side, all they have to do is step to the left (meaning X - 1) PositionX--; IsInElevator = true; //Reset RequestedElevator so that the Cleaner can request the Elevator again RequestedElevator = false; //Add the Cleaner to the Elevator so the Cleaner's position is updated with every HTE with the position of the Elevator Hotel.Elevator.InElevator.Add(this); } //If the Cleaner is in front of the ElevatorShaft they request the Elevator to their current position else if (Hotel.Floors[PositionY].Areas[PositionX - 1].AreaType == EAreaType.ElevatorShaft && !IsInElevator) { if (!RequestedElevator) { Hotel.Elevator.RequestElevator(PositionY); RequestedElevator = true; } } } //If the Cleaner is in the Elevator then we need to check if they need to get out the Elevator or not else { //If the Cleaner is on the Floor (int) that they need to be then she will step out of the Elevator and set their path to FromElevator if (PositionY == Destination.Floor) { Hotel.Elevator.InElevator.Remove(this); Path.RouteType = ERouteType.FromElevator; IsInElevator = false; } } } #endregion #region FromElevator //If the Cleaner has stepped out of the Elevator, they need to continue their Path to their Destination else if (Path.RouteType == ERouteType.FromElevator && Path.PathFromElevator.Count != 0) { //This is done by Dequeueing Node's and setting the Cleaner's current position to that of the Node Node moveNode = Path.PathFromElevator.Dequeue(); PositionX = moveNode.Area.PositionX; PositionY = moveNode.Area.PositionY; } #endregion #region Stairs //If the Cleaner has decided to take the Stairs instead of the Elevator if (Path.RouteType == ERouteType.Stairs) { //If the Cleaner needs to wait (due to the StairTime) she will not move if (WaitingTime > 0) { WaitingTime--; } //If the Cleaner doesn't need to wait else { //And the Stair Path is still filled with Node's if (Path.Path.Count != 0) { //By Dequeueing a Node, the Cleaner can move by making their X and Y co-ordinate the same as the Node's Node moveNode = Path.Path.Dequeue(); PositionX = moveNode.Area.PositionX; PositionY = moveNode.Area.PositionY; //If the Cleaner moves into a Node, their waiting time should be set to the StairTime (in Settings class) if (moveNode.Area.AreaType == EAreaType.Staircase) { WaitingTime = WaitingTime + Hotel.Settings.StairCase - 1; } } } } #endregion } }