private static (ISchedule, IScheduleGroup, Week, Day, Lesson) GetEmpty2BottomLayersSchedule(
            ISchElemsFactory factory)
        {
            var res   = factory.GetSchedule();
            var group = new ScheduleGroup()
            {
                GType = ScheduleGroupType.Academic, Name = "11-401"
            };

            res.ScheduleGroups.Add(group);
            var day    = factory.GetDay();
            var lesson = factory.GetLesson("test", "teacher", "place", new TimeSpan(8, 0, 0));

            day.Elems.Add(lesson);
            res.ScheduleRoot = day;
            return(res, group, null, day, lesson);
        }
        private static (ISchedule, IScheduleGroup, Week, Day, Lesson) GetEmpty2TopLayersSchedule(
            ISchElemsFactory factory)
        {
            var res   = factory.GetSchedule();
            var group = new ScheduleGroup()
            {
                GType = ScheduleGroupType.Academic, Name = "11-401"
            };

            res.ScheduleGroups.Add(group);
            var week = factory.GetWeek();

            res.ScheduleRoot = week;
            var day = factory.GetDay();

            res.ScheduleRoot.Elems.Add(day);
            return(res, group, week, day, null);
        }
        private IEnumerable <ISchedule> GetSchedules(IEnumerable <IScheduleGroup> availableGroups,
                                                     Func <IEnumerable <Day>, IEnumerable <Day> > modificator)
        {
            string    key;
            ISchedule schedule;

            foreach (var availableGroup in availableGroups)
            {
                key = KeyFromGroup(availableGroup);
                if (storage.TryGetValue(key, out ICollection <IScheduleElem> days))
                {
                    foreach (var resDay in modificator(days.OfType <Day>()))
                    {
                        schedule = factory.GetSchedule();

                        schedule.ScheduleRoot = (IScheduleElem)resDay.Clone();
                        schedule.ScheduleGroups.Add(availableGroup);
                        yield return(schedule);
                    }
                }
            }
        }
        public Task <ISchedule> ConstructFromMany(IEnumerable <ISchedule> schedules)
        {
            return(Task.Run <ISchedule>(() =>
            {
                try
                {
                    var result = elemsFactory.GetSchedule();
                    Dictionary <ScheduleGroupType, IScheduleGroup> uniqGroups = new Dictionary <ScheduleGroupType, IScheduleGroup>();


                    foreach (var schedule in schedules)
                    {
                        if (schedule.ScheduleGroups == null || !schedule.ScheduleGroups.Any(group => HasConflictsWithMemory(group, uniqGroups)))
                        {
                            var incomingRoot = schedule.ScheduleRoot;
                            var currentResultRoot = result.ScheduleRoot;
                            branchMerger.Merge(ref incomingRoot, ref currentResultRoot);
                            result.ScheduleRoot = currentResultRoot;
                        }
                        else
                        {
                            throw new ScheduleConstructorException("Incompatible groups in schedule parts found");
                        }
                    }

                    foreach (var group in uniqGroups.Values)
                    {
                        result.ScheduleGroups.Add(group);
                    }
                    return result;
                }
                catch (Exception e)
                {
                    throw new ScheduleConstructorException("An exception occured while constructing schedule.", e);
                }
            }));
        }