/// <summary> /// Создает План занятий с объединением планов групп и количеством пар которые можно изменить /// </summary> /// <param name="unionGroups"> Возможные объедиения групп</param> /// <returns>Объединенный план занятий</returns> private CurriculaWithAmountPair[] CurriculaWithUnionGroupsAndNumberOfPairs(List <Group[]> unionGroups) { //Произведена группировка по предметам. Каждый Предмет включает План для нескольких групп по нему var SubjectIncludePlans = Curricula.OrderByDescending(x => x.Number).GroupBy(x => x.Subject).Select(g => g.ToList()).ToList(); // Можно сразу выкинуть из объединенного плана если количество элементов в предмете =1 так как не с чем объединять //Добавляем эти одиночные предметы в объединенный план List <CurriculaWithAmountPair> CurriculaAndNumPairs = SubjectIncludePlans.Where(x => x.Count == 1).Select(c => new CurriculaWithAmountPair(c[0])).ToList(); //Убираем из группировки по предметам одиночные предметы SubjectIncludePlans = SubjectIncludePlans.Where(x => x.Count > 1).ToList(); // Подбираются планы из группировки по предметам (там теперь нет одиночных) и пытаюсь объединить //TODO: Просто просто делаю //прохожу по предметам с планами foreach (var plansInSubject in SubjectIncludePlans) { //прохожу по объединению групп где объединение >1 foreach (var groups in unionGroups.Where(x => x.Length > 1)) { //если план по предмету содержит все объединенные группы то объединяем по этому предмету эти группы // правда ли что для всех групп -> хотябы один план содежит группу bool ContainsAllGroups = groups.All(x => plansInSubject.Any(y => y.Group == x)); if (ContainsAllGroups) { //Выбираю планы, только для объединенных групп Curriculum[] curriculaUnionGroup = plansInSubject.Where(x => groups.Contains(x.Group)).ToArray(); //Проверям что у всех кто объединитсь одинаковое количество пар if (curriculaUnionGroup.All(x => x.Number == curriculaUnionGroup[0].Number)) { //Создаем план с возможностью изменения кол-во пар только для первой группы CurriculaWithAmountPair tempCurriculaWithAmountPair = new CurriculaWithAmountPair(curriculaUnionGroup[0]); //добавляем в этот объединенный план все остальные группы и если удалось то add->true bool add = tempCurriculaWithAmountPair.AddCurriculum(curriculaUnionGroup.Skip(1).ToArray()); //Если удалось добавить if (add) { //Добавляем этот план в объединенный план CurriculaAndNumPairs.Add(tempCurriculaWithAmountPair); //Удаляем из плана добавления в предмете что уже добавили тоесть все группы объединенные удаляем. plansInSubject.RemoveAll(x => curriculaUnionGroup.Contains(x)); } } } } //Добавляю оставшиеся планы в Главный план CurriculaAndNumPairs.AddRange(plansInSubject.Select(x => new CurriculaWithAmountPair(x)).ToArray()); } //План занятий с объединенными планами и кол-вом пар return(CurriculaAndNumPairs.ToArray()); }
/// <summary> /// Добавить один предмет в учебный план и выводит которые не получилось добавить /// </summary> /// <param name="MaxCurricula"> План для добавления предмета </param> /// <returns> Выводить список планов которые не удалось добавить</returns> private List <Curriculum> AddOneSubjectInCurriculum(CurriculaWithAmountPair MaxCurricula) { //Пустой план не получившийся добавить List <Curriculum> curriculaNot = new List <Curriculum>(); //a. Из элемента плана понимаем что за предмет и какая группа var group = MaxCurricula.GetGroups(); var subject = MaxCurricula.GetSubject(); //c. Выбираем аудитории с кол-во мест больше чем в группе //(так как они отсортированы по возрастанию то просто номер первой подходящей аудитории) //Номер Аудитории из массива которая сейчас будет рассматриваться -1 значит нет такой аудитории int NumClassroom = Classrooms.FindIndex(x => x.NumberOfSeats >= group.Sum(y => y.NumberOfPersons)); //Теперь для каждой группы подцепляем занятость var fillingGroup = FillingGroups.Where(x => group.Contains(x.Value)).ToList(); //Добавилась ли пара bool success = false; //i. Цикл по расписанию if (NumClassroom != -1) { for (int cu = 0; cu < NumberStudyDays; cu++) { //d. Цикл по аудиториям for (int cl = NumClassroom; cl < Classrooms.Count; cl++) { //Теперь для аудитории подцепляем занятость var fillingClassroom = FillingClassrooms.First(x => x.Value.ClassroomId == Classrooms[cl].ClassroomId); //Условия что в этот день в эту пару группы не заняты bool FG = true; foreach (var fillingGroup1 in fillingGroup) { bool FG1 = fillingGroup1[cu].BusyPair == null; if (!FG1) { FG = false; break; } } //Условия что в этот день в эту пару классная комната не занята bool FC = fillingClassroom[cu].BusyPair == null; //ToDO: в день не должно быть более 2-х одинаковых пар //все пары в этот день у этой группы var allPairsInGroup = fillingGroup[0].PossibleFillings.Where(x => x.StudyDay == fillingGroup[0].PossibleFillings[cu].StudyDay).ToArray(); //одинаковые пары в день int numOfThisLesson = allPairsInGroup.Where(x => x.BusyPair != null && x.BusyPair.Subject == subject).Count(); //Кол-во пар в день не более 2 bool FNT = true; if (numOfThisLesson >= 2) { FNT = false; } //1. Если в этот день свободна и группа и преподаватель и аудитория if (FNT && FG && FC) { BusyPair busyPair = new BusyPair(Classrooms[cl], subject, group); //a. Добавляем им пару foreach (var fillingGroup1 in fillingGroup) { fillingGroup1[cu].BusyPair = busyPair; } fillingClassroom[cu].BusyPair = busyPair; //b. Заканчиваем 2 цикла(по расписанию и по аудиториям) success = true; break; } //Если закончено } //Цикл по расписанию закончен //b. Заканчиваем 2 цикла(по расписанию и по аудиториям) если пара добавилась if (success) { break; } } } //Цикл аудиторий закончен //e. Если не смогли добавить то if (!success) { //Так как несколько планов то проходим по всем for (int i = 0; i < MaxCurricula.GetNumberPlan(); i++) { //индекс в учебном плане int ind = curriculaNot.FindIndex(x => x.CurriculumId == MaxCurricula.GetCurriculumId()[i]); //i. Если был такой элемент if (ind == -1) { //1. Сохраняем что не смогли добавить в кол-ве 1 пара curriculaNot.Add(MaxCurricula.NewCurriculum(i, 1)); } //Иначе если не было такого элемента else { //1. Добавляем к элементу 1 пару curriculaNot[ind].Number++; } //Если закончено } } //Если закончено //план не получившийся добавить return(curriculaNot); }