public List <EngineerSchedule> GetAllEngineerSchedules() { List <Engineer> engineers = _repository.GetAllEngineers().Where(e => e.IsAvailable == true).ToList(); List <Engineer> initialList = _repository.GetAllEngineers().ToList(); List <EngineerSchedule> previousweek = null; if (engineers.Count < (shiftDays / 2)) { throw new InvalidOperationException("There are no enough engineers to generate schedule,adhering the rules"); } List <EngineerSchedule> engineerSchedules = new List <EngineerSchedule>(); DateTime currentDate = System.DateTime.Now; //Schedule starts from next monday int diffDays = ((int)DayOfWeek.Monday - (int)currentDate.DayOfWeek + 7) % 7; DateTime scheduleStartdate = currentDate.AddDays(diffDays); //Schedule spans for 2weeks 12 days(Monday to friday) DateTime scheduleEnddate = scheduleStartdate.AddDays(12); DateTime currentScheduleStart = scheduleStartdate; for (int j = 0; j < scheduleSpan; j++) { if (j > 0) { //To ensure that we are not getting the same random numbers in each week Thread.Sleep(100); } var rand = new Random(); var randomEngineers = engineers.OrderBy(item => rand.Next()).Where(e => e.IsAvailable == true).ToList(); if (randomEngineers.Count < shiftDays) { int noOfengShortage = shiftDays - randomEngineers.Count; //To make sure randomEngineers picked for 2nd week hasnt completed 1 day of support already in previous week if (j > 0 && previousweek.Count > 0) { List <Engineer> assignedEngineers = new List <Engineer>(); foreach (EngineerSchedule es in previousweek) { foreach (Engineer eng in es.engineer) { assignedEngineers.Add(eng); } } //To avoid duplicates in 2nd week,and make sure engineers opt out in last week completes 1 whole day of support foreach (Engineer e in engineers) { bool isShiftcompletedPrevweek = assignedEngineers.Any(emp => emp.ID == e.ID); bool isRandom = randomEngineers.Any(emp => emp.ID == e.ID); if (isShiftcompletedPrevweek == true && isRandom == true) { e.IsAvailable = false; } } } //Shuffle the available Engineers list again,so that we get enough engineers to work for the existing week var randomEngineers1 = engineers.OrderBy(item => rand.Next()).Where(e => e.IsAvailable == true).ToList().Take(noOfengShortage).ToList(); //Add it to the original randomEngineers list foreach (Engineer e in randomEngineers1) { bool isOvertime = false; if (isOvertime == false) { randomEngineers.Add(e); } } if (j == 0) { //Set IsAvailable=false for engineers picked in 2nd shuffle,if they have completed 1 day of support engineers = UpdateAvailableEngineersPool(randomEngineers, initialList); } } if (j > 0 && engineerSchedules.Count > 0) { currentScheduleStart = Convert.ToDateTime(engineerSchedules[engineerSchedules.Count - 1].ScheduleDate); if (currentScheduleStart.DayOfWeek == DayOfWeek.Friday) { int diffDay = ((int)DayOfWeek.Monday - (int)currentScheduleStart.DayOfWeek + 7) % 7; currentScheduleStart = currentScheduleStart.AddDays(diffDay); } } engineerSchedules = GenerateSschedulePerWeek(currentScheduleStart, scheduleStartdate, scheduleEnddate, randomEngineers, engineerSchedules, previousweek); previousweek = engineerSchedules; } return(engineerSchedules); }