public bool TryMerge(ref IScheduleElem sourceNode, ref IScheduleElem targetNode) { if (sourceNode.Level == targetNode.Level) { return(GetStrategy(targetNode.Level) .TryRootToRootMerge(sourceNode, targetNode, TryMerge)); } else { if (Math.Abs(sourceNode.Level - targetNode.Level) > 2 && targetNode.Level != ScheduleElemLevel.Undefined) { throw new ScheduleConstructorException("wrong schedule trees"); } //sourceNode.Level == Day and targetNode.Level == Week case f.e. if (sourceNode.Level > targetNode.Level) { GetStrategy(targetNode.Level).ChildToParent(ref sourceNode, ref targetNode, TryMerge); return(true); } else { GetStrategy(targetNode.Level).ParentToChild(ref sourceNode, ref targetNode, TryMerge); return(true); } } }
public Task <bool> UpdateScheduleAsync(IScheduleGroup targetGroup, IScheduleElem scheduleRoot) { return(Task.Factory.StartNew(() => { try { string key = KeyFromGroup(targetGroup); storage.AddOrUpdate(key, //if new key keyS => { switch (scheduleRoot.Level) { case ScheduleElemLevel.Week: return ((IScheduleElem)scheduleRoot.Clone()).Elems; case ScheduleElemLevel.Day: return new List <IScheduleElem>() { scheduleRoot }; default: throw new ArgumentOutOfRangeException( $"Db cannot add root with level {scheduleRoot.Level.ToString()}"); } }, //if already exists (keyS, days) => { switch (scheduleRoot.Level) { case ScheduleElemLevel.Week: return ((IScheduleElem)scheduleRoot.Clone()).Elems; case ScheduleElemLevel.Day: var casted = (Day)scheduleRoot; var toUpd = days.OfType <Day>().FirstOrDefault(d => d.DayOfWeek == casted.DayOfWeek); if (toUpd != null) { days.Remove(toUpd); } days.Add((IScheduleElem)casted.Clone()); return days; default: throw new ArgumentOutOfRangeException( $"Db cannot update root with level {scheduleRoot.Level.ToString()}"); } }); return true; } catch (ArgumentOutOfRangeException e) { //todo: logger return false; } })); }
private IScheduleElem AddToCommonParent(IScheduleElem sourceNode, IScheduleElem targetNode) { var res = CreateDefault(targetNode.Level - 1); res.Elems.Add(sourceNode); res.Elems.Add(targetNode); return(res); }
public void Merge(ref IScheduleElem sourceNode, ref IScheduleElem targetNode) { if (!TryMerge(ref sourceNode, ref targetNode)) { IScheduleElem commonParent = AddToCommonParent(sourceNode, targetNode); targetNode = commonParent; } }
public bool Equals(IScheduleElem obj) { if (obj.GetType() != this.GetType()) { return(false); } return(Equals((Lesson)obj)); }
public bool Equals(IScheduleElem other) { if (other.GetType() != this.GetType()) { return(false); } return(Equals((Week)other)); }
protected void Visit(IScheduleElem elem) { if (elem?.Elems != null) { foreach (var scheduleElem in elem.Elems) { VisitElem(scheduleElem); } } }
public EventArgs GetArgs(IScheduleElem schedule) { if (schedule is Day day) { return(new ParamEventArgs <DayOfWeek>() { Param = day.DayOfWeek }); } return(EventArgs.Empty); }
public override bool TryRootToRootMerge(IScheduleElem source, IScheduleElem target, ReccurentStep recurrentStep) { if (source == null || source.Elems == null || !source.Elems.Any()) { return(true); } var sourceDay = (Day)source; var targetDay = (Day)target; if (sourceDay.DayOfWeek != targetDay.DayOfWeek) { return(false); } if (targetDay.Elems == null || !targetDay.Elems.Any()) { targetDay.Elems = sourceDay.Elems; return(true); } targetDay.Elems = targetDay.Elems.Union(sourceDay.Elems).Cast <Lesson>().OrderBy(elem => elem.BeginTime) .ToList <IScheduleElem>(); Lesson prev = null; foreach (var lesson in targetDay.Elems.Cast <Lesson>()) { if (prev == null) { prev = lesson; continue; } if (lesson.BeginTime <= prev.BeginTime && (lesson.IsOnEvenWeek == null || prev.IsOnEvenWeek == null || prev.IsOnEvenWeek == lesson.IsOnEvenWeek)) { //throw new ScheduleConstructorException( //todo: throw exc!!!!! logger?.LogError(String.Format( "Day's lessons merge exception: time intersects: {0}, {1}", JsonConvert.SerializeObject(prev), JsonConvert.SerializeObject(lesson))); } } return(true); }
public override void ChildToParent(ref IScheduleElem sourceChild, ref IScheduleElem targetParent, ReccurentStep recurrentStep) { if (sourceChild == null) { return; } if (targetParent == null) { throw new ArgumentNullException("target branch is null"); } if (targetParent.Elems == null) { targetParent.Elems = new List <IScheduleElem>(); } if (!targetParent.Elems.Any()) { targetParent.Elems.Add(sourceChild); } else { var sourceDay = (Day)sourceChild; var days = targetParent.Elems.Cast <Day>().ToList(); var commonDays = days.Count(diw => diw.DayOfWeek == sourceDay.DayOfWeek); if (commonDays > 1) { throw new ScheduleConstructorException("Several same day's of week"); } if (commonDays == 1) { IScheduleElem common = days.FirstOrDefault(diw => diw.DayOfWeek == sourceDay.DayOfWeek); //swap target and source to save all into week branch //todo: remove get strategy!!!!! if (!recurrentStep.Invoke(ref sourceChild, ref common)) { throw new ArgumentException(String.Format("Bad arguments: {0}, {1}", JsonConvert.SerializeObject(sourceChild), JsonConvert.SerializeObject(common))); } } else { targetParent.Elems.Add(sourceDay); } } }
public override bool TryRootToRootMerge(IScheduleElem source, IScheduleElem target, ReccurentStep recurrentStep) { if (source == null || source.Elems == null || !source.Elems.Any()) { return(true); } var sourceWeek = (Week)source; var targetWeek = (Week)target; if (targetWeek.Elems == null || !targetWeek.Elems.Any()) { targetWeek.Elems = sourceWeek.Elems; return(true); } targetWeek.Elems = targetWeek.Elems.Concat(sourceWeek.Elems).GroupBy(elem => ((Day)elem).DayOfWeek, (dayOfWeek, elems) => { var count = elems.Count(); if (count > 2) { throw new ScheduleConstructorException("Several same day's of week"); } if (count == 1) { return(elems.First()); } var first = elems.First(); //next step merge var second = elems.ElementAt(1); if (!recurrentStep.Invoke(ref second, ref first)) { throw new ArgumentException(String.Format("Bad arguments: {0}, {1}", JsonConvert.SerializeObject(second), JsonConvert.SerializeObject(first))); } return(first); }).ToList(); return(true); }
public override void ParentToChild(ref IScheduleElem sourceParent, ref IScheduleElem targetChild, ReccurentStep recurrentStep) { if (sourceParent == null || sourceParent.Elems == null) { //todo: init elems by list throw new ArgumentOutOfRangeException( "source parent cannot be null and should have initialized collection"); } //var sourceWeek = (Week) sourceParent; var targetDay = (Day)targetChild; var days = sourceParent.Elems.Cast <Day>().ToList(); var commonDays = days.Count(diw => diw.DayOfWeek == targetDay.DayOfWeek); if (commonDays > 1) { throw new ScheduleConstructorException("Several same day's of week"); } if (commonDays == 1) { IScheduleElem common = days.FirstOrDefault(diw => diw.DayOfWeek == targetDay.DayOfWeek); //swap target and source to save all into week branch if (!recurrentStep.Invoke(ref targetChild, ref common)) { throw new ArgumentException(String.Format("Bad arguments: {0}, {1}", JsonConvert.SerializeObject(sourceParent), JsonConvert.SerializeObject(common))); } } else { sourceParent.Elems.Add(targetDay); } targetChild = sourceParent; }
public static IScheduleElem OrderChildrenByDefault(this IScheduleElem scheduleElem) { switch (scheduleElem.Level) { case ScheduleElemLevel.Week: scheduleElem.Elems = scheduleElem.Elems.Select(d => d.OrderChildrenByDefault()).Cast <Day>() .OrderBy(d => d.DayOfWeek).Cast <IScheduleElem>().ToList(); break; case ScheduleElemLevel.Day: scheduleElem.Elems = scheduleElem.Elems.Cast <Lesson>().OrderBy(l => l.BeginTime) .Cast <IScheduleElem>().ToList(); break; case ScheduleElemLevel.Undefined: break; default: throw new ArgumentOutOfRangeException("scheduleElem", $"Impossible to order children for such level {scheduleElem.Level}"); } return(scheduleElem); }
public void VisitElem(IScheduleElem elem) { dynamic @dynamic = elem; Visit(@dynamic); }
public override bool TryRootToRootMerge(IScheduleElem source, IScheduleElem target, ReccurentStep recurrentStep) { //no body return(true); }
public override void ChildToParent(ref IScheduleElem sourceChild, ref IScheduleElem targetParent, ReccurentStep recurrentStep) { targetParent = sourceChild; }
public bool Equals(IScheduleElem obj) { return(Equals((object)obj)); }
public static CheckResult CheckElemIsCorrect(this IScheduleElem scheduleElem) { var res = new CheckResult(); if (scheduleElem == null) { return(res.AddError("Null schedule elem")); } try { switch (scheduleElem.Level) { case ScheduleElemLevel.Week: if (!(scheduleElem is Week)) { res.AddError($"level week is not week level {scheduleElem.Level}, type: {scheduleElem.GetType()}"); } if (scheduleElem.Elems == null) { res.AddError("null children: " + JsonConvert.SerializeObject(scheduleElem)); } else { res = scheduleElem.Elems?.Aggregate(res, (result, elem) => result + CheckElemIsCorrect(elem)) ?? res; var nonUniqueDays = scheduleElem.Elems?.OfType <Day>()?.GroupBy(d => d.DayOfWeek) ?.FirstOrDefault(group => @group.Count() > 1); if (nonUniqueDays != null) { res.AddError($"not unique days in week: {nonUniqueDays.Key}"); } } break; case ScheduleElemLevel.Day: if (!(scheduleElem is Day)) { res.AddError($"level day is not day: level {scheduleElem.Level}, type: {scheduleElem.GetType()}"); } else { var day = (Day)scheduleElem; if (day.DayOfWeek > DayOfWeek.Saturday || day.DayOfWeek < DayOfWeek.Sunday) { res.AddError($"unknown dayofweek: {day.DayOfWeek}"); } } if (scheduleElem.Elems == null) { res.AddError("null children: " + JsonConvert.SerializeObject(scheduleElem)); } else { res = scheduleElem.Elems?.Aggregate(res, (result, elem) => result + CheckElemIsCorrect(elem)) ?? res; scheduleElem.Elems?.OfType <Lesson>()?.OrderBy(l => l.BeginTime).Aggregate((prev, current) => { if (current.BeginTime <= prev.BeginTime && (current.IsOnEvenWeek == null || prev.IsOnEvenWeek == null || prev.IsOnEvenWeek == current.IsOnEvenWeek)) { res.AddError($"incompatible lessons in day {((Day)scheduleElem).DayOfWeek}:" + JsonConvert.SerializeObject(prev) + JsonConvert.SerializeObject(current)); } return(current); }); } break; case ScheduleElemLevel.Lesson: if (!(scheduleElem is Lesson)) { res.AddError("level lesson is not lesson" + JsonConvert.SerializeObject(scheduleElem)); } if (scheduleElem.Elems != null) { res.AddError("not null children for lesson: " + JsonConvert.SerializeObject(scheduleElem)); } break; default: res.AddError($"Impossible to check for such level {scheduleElem.Level}"); break; } return(res); } catch (Exception e) { return(res.AddExeption(e)); } }
public abstract void ChildToParent(ref IScheduleElem sourceChild, ref IScheduleElem targetParent, ReccurentStep recurrentStep);
public abstract void ParentToChild(ref IScheduleElem sourceParent, ref IScheduleElem targetChild, ReccurentStep recurrentStep);
public abstract bool TryRootToRootMerge(IScheduleElem source, IScheduleElem target, ReccurentStep recurrentStep);
public override void ParentToChild(ref IScheduleElem sourceParent, ref IScheduleElem targetChild, ReccurentStep recurrentStep) { throw new NotImplementedException(); }
public override void ChildToParent(ref IScheduleElem sourceChild, ref IScheduleElem targetParent, ReccurentStep recurrentStep) { throw new NotImplementedException(); }