static public List <USINGEVENT> CheckOverlapApprovedEvent(USINGCLASS usingClass, CLASS class_) { List <USINGEVENT> listOverlappedEvent = new List <USINGEVENT>(); var listEventMayOverlap = (from UsingEvent in DataProvider.Ins.DB.USINGEVENTs join StartPeriod in DataProvider.Ins.DB.PERIOD_TIMERANGE on UsingEvent.StartPeriod equals StartPeriod.PeriodID where UsingEvent.RoomID == usingClass.RoomID && UsingEvent.Status_ == (int)Enums.UsingStatus.Approved select new { UsingEvent, StartPeriod }).ToList(); listEventMayOverlap = listEventMayOverlap.FindAll(x => { int dayOfWeek = (int)x.UsingEvent.Date_.DayOfWeek; var startPeriod = (from period in DataProvider.Ins.DB.PERIOD_TIMERANGE where period.PeriodID == usingClass.StartPeriod select period).Single(); return (((x.UsingEvent.Date_ - ((DateTime)usingClass.StartDate)).Days / 7) % usingClass.RepeatCycle == 0 && dayOfWeek == usingClass.Day_ && (x.UsingEvent.Date_ >= usingClass.StartDate && x.UsingEvent.Date_ <= usingClass.EndDate) && !(x.StartPeriod.StartTime + x.UsingEvent.Duration <= startPeriod.StartTime || x.StartPeriod.StartTime >= startPeriod.StartTime + usingClass.Duration)); }); foreach (var event_ in listEventMayOverlap) { listOverlappedEvent.Add(event_.UsingEvent); } return(listOverlappedEvent); }
/// <summary> /// Auto choose the Room and Start period for the usingclass /// /// </summary> /// <param name="usingClass"></param> /// <param name="class_"></param> /// <param name="selectedRoom">If selected room is null, function auto choose the room for you</param> /// <param name="selectedDayOfWeek">If selected day is null, function auto choose the day of week</param> /// <returns> /// If success, return list of new UsingClass that auto scheduled /// Otherwise, return null /// </returns> static public List <USINGCLASS> AutoMakeSchedule(USINGCLASS usingClass_, CLASS class_, ROOM selectedRoom, DayOfWeek?selectedDayOfWeek, Nullable <int> selectedStartPeriod) { USINGCLASS usingClass = new USINGCLASS(usingClass_); List <int> listDayOfWeekToChoose = new List <int>(); if (selectedDayOfWeek == null) { for (int i = 1; i <= 6; i++) { listDayOfWeekToChoose.Add(i); } } else { listDayOfWeekToChoose.Add((int)selectedDayOfWeek); } foreach (int dayOfWeek in listDayOfWeekToChoose) { usingClass.Day_ = dayOfWeek; List <USINGCLASS> result; if (selectedStartPeriod == null) { result = AutoMakeSchedule(usingClass, class_, selectedRoom); } else { result = AutoMakeSchedule(usingClass, class_, selectedRoom, (int)selectedStartPeriod); } if (result != null) { return(result); } } return(null); }
static USINGCLASS CheckOverlapApprovedLecturerTimeUsingClass(USINGCLASS usingClass, CLASS class_) { var startPeriod = (from period in DataProvider.Ins.DB.PERIOD_TIMERANGE where period.PeriodID == usingClass.StartPeriod select period).Single(); var listUsingClassMayOverlap = (from usgClass in DataProvider.Ins.DB.USINGCLASSes join Class in DataProvider.Ins.DB.CLASSes on usgClass.ClassID equals Class.ClassID join StartPeriod in DataProvider.Ins.DB.PERIOD_TIMERANGE on usgClass.StartPeriod equals StartPeriod.PeriodID where Class.LecturerID == class_.LecturerID && usgClass.Day_ == usingClass.Day_ && usgClass.Status_ == (int)Enums.UsingStatus.Approved select new { usgClass, Class, StartPeriod }).ToList(); listUsingClassMayOverlap = listUsingClassMayOverlap.FindAll(x => { var cmcm = !(x.StartPeriod.StartTime + x.usgClass.Duration <startPeriod.StartTime || x.StartPeriod.StartTime> startPeriod.StartTime + usingClass.Duration); return (!(x.usgClass.EndDate < usingClass.StartDate || x.usgClass.StartDate > usingClass.EndDate) && !(x.StartPeriod.StartTime + x.usgClass.Duration <= startPeriod.StartTime || x.StartPeriod.StartTime >= startPeriod.StartTime + usingClass.Duration)); }); foreach (var usingClassMayOverlap in listUsingClassMayOverlap) { if (usingClass.RepeatCycle != usingClassMayOverlap.usgClass.RepeatCycle) { return(usingClassMayOverlap.usgClass); } // have the same repeat cycle but start after else if ((((DateTime)usingClass.StartDate - (DateTime)usingClassMayOverlap.usgClass.StartDate).Days / 7) % usingClass.RepeatCycle == 0) { return(usingClassMayOverlap.usgClass); } } return(null); }
/// <summary> /// This function split 1 using class into multiple using class /// so that it cannot overlap with event /// </summary> /// <param name="usingClass"></param> /// <param name="class_"></param> /// <returns></returns> static public List <USINGCLASS> HandleOverlapEvent(USINGCLASS usingClass, CLASS class_, out List <USINGEVENT> listOverlappedEvent) { List <USINGCLASS> listSplitedUsingClass = new List <USINGCLASS>(); listSplitedUsingClass.Add(usingClass); listOverlappedEvent = CheckOverLapEvent(usingClass, class_); if (listOverlappedEvent.Count > 3) { // NOT HANDLED YET return(null); } else { var listRoomFiltered = (from room in DataProvider.Ins.DB.ROOMs where room.Capacity >= class_.Population_ select room).ToList(); listRoomFiltered.Reverse(); listOverlappedEvent.Sort((x, y) => { return(Convert.ToInt32(x.Date_ > y.Date_)); }); foreach (var overlapEvent in listOverlappedEvent) { // split the last using class USINGCLASS targetUsingClass = listSplitedUsingClass[listSplitedUsingClass.Count - 1]; listSplitedUsingClass.RemoveAt(listSplitedUsingClass.Count - 1); USINGCLASS firstHalf = new USINGCLASS(targetUsingClass); USINGCLASS secondHalf = new USINGCLASS(targetUsingClass); firstHalf.EndDate = overlapEvent.Date_.AddDays(-(int)overlapEvent.Date_.DayOfWeek); secondHalf.StartDate = overlapEvent.Date_.AddDays(7 - ((int)overlapEvent.Date_.DayOfWeek - 1)); USINGCLASS middle = new USINGCLASS(targetUsingClass); middle.StartDate = ((DateTime)firstHalf.EndDate).AddDays(1); middle.EndDate = ((DateTime)secondHalf.StartDate).AddDays(-1); bool middleFound = false; foreach (var room in listRoomFiltered) { middle.RoomID = room.RoomID; var overlapUsingClass = CheckOverlapUsingClass(middle, class_); var listOverlapEvent = CheckOverLapEvent(middle, class_); if (overlapUsingClass == null && listOverlapEvent.Count == 0) { listSplitedUsingClass.Add(firstHalf); listSplitedUsingClass.Add(middle); listSplitedUsingClass.Add(secondHalf); middleFound = true; break; } } if (middleFound == false) { return(null); } } } return(listSplitedUsingClass); }
static private List <USINGCLASS> AutoMakeSchedule(USINGCLASS usingClass, CLASS class_, ROOM selectedRoom, int selectedStartPeriod) { if (CalcEndPeriod(selectedStartPeriod, usingClass.Duration) > 5 && selectedStartPeriod <= 5 || CalcEndPeriod(selectedStartPeriod, usingClass.Duration) == -1) { return(null); } List <USINGCLASS> result = null; var beginningRoomID = usingClass.RoomID; var beginningStartPeriod = usingClass.StartPeriod; List <ROOM> listRoomFiltered; if (selectedRoom == null) { listRoomFiltered = (from room in DataProvider.Ins.DB.ROOMs where room.Capacity >= class_.Population_ select room).ToList(); } else if (selectedRoom.Capacity >= class_.Population_) { listRoomFiltered = new List <ROOM>(); listRoomFiltered.Add(selectedRoom); } else { listRoomFiltered = new List <ROOM>(); } var targetDate = ((DateTime)usingClass.StartDate).AddDays(usingClass.Day_ - 1); TimeTableViewModel timeTableViewModel = new TimeTableViewModel(); timeTableViewModel.selectedDay = targetDate.Day; timeTableViewModel.selectedMonth.monthValue = targetDate.Month; timeTableViewModel.selectedYear = targetDate.Year; timeTableViewModel.GetTimeTable(); var listUsingClass = timeTableViewModel.tb; // get all using class for that day // only get using on the room that satisfy the capacity var listUsingClassFiltered = listUsingClass.Where(x => { return(DataProvider.Ins.DB.ROOMs.Find(x.roomID).Capacity >= class_.Population_); }).ToList(); var ListUsedRoom = (from usg in listUsingClassFiltered select usg.roomID).ToList(); List <ROOM> listUnusedRoom = listRoomFiltered.Where(x => { return(!ListUsedRoom.Contains(x.RoomID)); }).ToList(); foreach (var room in listRoomFiltered) { usingClass.RoomID = room.RoomID; usingClass.StartPeriod = selectedStartPeriod; USINGCLASS overlappedUsingClass = CheckOverlapUsingClass(usingClass, class_); USINGCLASS overlappedLecturerUsingClass = CheckOverlapLecturerTimeUsingClass(usingClass, class_); List <USINGEVENT> listOverlappedEvent = new List <USINGEVENT>(); if (overlappedUsingClass == null && overlappedLecturerUsingClass == null) { // we found an empty room and time, finish here result = HandleOverlapEvent(usingClass, class_, out listOverlappedEvent); if (result != null) { return(result); } } } return(null); }
/// <summary> /// Auto choose the Room and Start period for the usingclass /// /// </summary> /// <param name="usingClass"></param> /// <param name="class_"></param> /// <param name="selectedRoom">If selected room is null, function auto choose the room for you</param> /// <returns> /// If success, return list of new UsingClass that auto scheduled /// Otherwise, return null /// </returns> static private List <USINGCLASS> AutoMakeSchedule(USINGCLASS usingClass, CLASS class_, ROOM selectedRoom) { List <USINGCLASS> result = null; var beginningRoomID = usingClass.RoomID; var beginningStartPeriod = usingClass.StartPeriod; List <ROOM> listRoomFiltered; if (selectedRoom == null) { listRoomFiltered = (from room in DataProvider.Ins.DB.ROOMs where room.Capacity >= class_.Population_ select room).ToList(); } else if (selectedRoom.Capacity >= class_.Population_) { listRoomFiltered = new List <ROOM>(); listRoomFiltered.Add(selectedRoom); } else { listRoomFiltered = new List <ROOM>(); } var targetDate = ((DateTime)usingClass.StartDate).AddDays(usingClass.Day_ - 1); TimeTableViewModel timeTableViewModel = new TimeTableViewModel(); timeTableViewModel.selectedDay = targetDate.Day; timeTableViewModel.selectedMonth.monthValue = targetDate.Month; timeTableViewModel.selectedYear = targetDate.Year; timeTableViewModel.GetTimeTable(); var listUsingClass = timeTableViewModel.tb; // get all using class for that day // only get using on the room that satisfy the capacity var listUsingClassFiltered = listUsingClass.Where(x => { return(DataProvider.Ins.DB.ROOMs.Find(x.roomID).Capacity >= class_.Population_); }).ToList(); var ListUsedRoom = (from usg in listUsingClassFiltered select usg.roomID).ToList(); List <ROOM> listUnusedRoom = listRoomFiltered.Where(x => { return(!ListUsedRoom.Contains(x.RoomID)); }).ToList(); foreach (var room in listRoomFiltered) { usingClass.RoomID = room.RoomID; usingClass.StartPeriod = 1; USINGCLASS overlappedUsingClass = CheckOverlapUsingClass(usingClass, class_); USINGCLASS overlappedLecturerUsingClass = CheckOverlapLecturerTimeUsingClass(usingClass, class_); List <USINGEVENT> listOverlappedEvent = new List <USINGEVENT>(); if (overlappedUsingClass == null && overlappedLecturerUsingClass == null) { // we found an empty room and time, finish here result = HandleOverlapEvent(usingClass, class_, out listOverlappedEvent); if (result != null) { return(result); } } if (result == null) { int newStartPeriod = 0; int endPeriod = 0; // loop through period to find the next fit in room on target date while (endPeriod != -1) { if (overlappedUsingClass == null && overlappedLecturerUsingClass == null) // if both are null, then the problem is with the event { listOverlappedEvent.Sort((x, y) => { return(Convert.ToInt32(CalcEndPeriod(x.StartPeriod, x.Duration) < CalcEndPeriod(y.StartPeriod, y.Duration))); }); newStartPeriod = CalcEndPeriod(listOverlappedEvent[0].StartPeriod, listOverlappedEvent[0].Duration) + 1; } else if (overlappedUsingClass == null) { newStartPeriod = CalcEndPeriod(overlappedLecturerUsingClass.StartPeriod, overlappedLecturerUsingClass.Duration) + 1; } else if (overlappedLecturerUsingClass == null || overlappedUsingClass.StartPeriod > overlappedLecturerUsingClass.StartPeriod) { newStartPeriod = CalcEndPeriod(overlappedUsingClass.StartPeriod, overlappedUsingClass.Duration) + 1; } else { newStartPeriod = CalcEndPeriod(overlappedLecturerUsingClass.StartPeriod, overlappedLecturerUsingClass.Duration) + 1; } endPeriod = CalcEndPeriod(newStartPeriod, usingClass.Duration); if (endPeriod == -1) { break; } if (newStartPeriod <= 5 && endPeriod > 5) { newStartPeriod = 6; endPeriod = CalcEndPeriod(newStartPeriod, usingClass.Duration); } if (endPeriod == -1) { break; } usingClass.StartPeriod = newStartPeriod; overlappedUsingClass = CheckOverlapUsingClass(usingClass, class_); overlappedLecturerUsingClass = CheckOverlapLecturerTimeUsingClass(usingClass, class_); if (overlappedUsingClass == null && overlappedLecturerUsingClass == null) { result = HandleOverlapEvent(usingClass, class_, out listOverlappedEvent); if (result != null) { return(result); } } } } } usingClass.RoomID = beginningRoomID; usingClass.StartPeriod = beginningStartPeriod; return(result); }