public virtual void SetTime(ITerm term, DateTime unCheckedstart, DateTime uncheckedEnd, Action <ITerm, bool> callback, bool withRplaceDayOff) { var start = unCheckedstart.TurnToMultiplesOf5(); var end = uncheckedEnd.TurnToMultiplesOf5(); var result = false; var source = (Term)term; var value = new DateRange(start, end); if (start >= end) { source.Exception = new TermException(source, "InvalidTimeValue"); callback(source, false); return; } bool?childIsInsideOfParent = null; source.Bottom.SaftyInvoke(o => childIsInsideOfParent = value.IsInTheRange(o)); //var assignmentIsOutOfBoundary = source.GetLowestTerm().IsOutOfBoundary(start, this); //if(assignmentIsOutOfBoundary) // source.Exception = new TermException(source, "IsOutOfBoundary"); if (childIsInsideOfParent == false) { source.Exception = new TermException(source, "BreakAwayFromParent"); } if ((!source.Locked) && childIsInsideOfParent != false) // ((!source.Locked) && !assignmentIsOutOfBoundary && childIsInsideOfParent != false) { var coverage = source.MeasureCoverage(value.Start, value.End); var coverdTerms = TermSet.Retrieve <Term>(coverage.Start, coverage.End, o => !ReferenceEquals(o, source) && o.IsNot <IImmutableTerm>()).ToList(); //range filter var overlappedTerm = coverdTerms.FirstOrDefault(o => o.Level == source.Level && o.IsCoverd(value)); //same level have any covered term var relatedTerms = coverdTerms.WhereFamilyTerms(source).ToList(); //relation filter, the real child in the parent if (overlappedTerm == null || (withRplaceDayOff && overlappedTerm is DayOff)) { if (source.IsNot <AbsentEvent>()) { overlappedTerm.SaftyInvoke <DayOff>(o => { _termSet.Remove(o); overlappedTerm = null; }); var notMoving = !source.CanCauseMoved(start, end); var offset = new { L = value.Start.Subtract(source.Start), R = value.End.Subtract(source.End) }; var verifiedTerms = relatedTerms.Where(o => o.IsInTheRange(source.Start, source.End)).OrderByDescending(o => o.Level); var lockedTerms = relatedTerms.Where(o => o.Locked && o.IsInTheRange(source.Start, source.End)); Action applyDelegate = () => { }; foreach (var o in verifiedTerms) { var newTime = new DateRange(o.Is <AbsentEvent>() || o.Locked || notMoving ? o.Start : o.Start.Add(offset.L), o.Is <AbsentEvent>() || o.Locked || notMoving ? o.End : o.End.Add(offset.R)); if (o.Level < source.Level ? !value.IsInTheRange(newTime) : !newTime.IsInTheRange(value) && o.IsNot <AbsentEvent>()) { overlappedTerm = o; break; } if (o.Is <AbsentEvent>() && !o.IsInTheRange(o.ParentTerm == term ? start : o.ParentTerm.Start, o.ParentTerm == term ? end : o.ParentTerm.End)) { overlappedTerm = o; break; } if (notMoving || o.Is <AbsentEvent>()) { continue; } var current = o; var verifyLockedTermIsNotInTheRange = new Func <Term, bool>(lockedTerm => { if (lockedTerm.Bottom != current) { return(false); } if (!lockedTerm.IsInTheRange(newTime.Start, newTime.End)) { overlappedTerm = lockedTerm; } return(true); }); if (lockedTerms.Any(verifyLockedTermIsNotInTheRange)) { continue; } overlappedTerm = lockedTerms.FirstOrDefault(locked => !ReferenceEquals(current, locked) && ((locked.Level == current.Level && locked.IsCoverd(newTime)))); if (overlappedTerm == null && !o.Locked && !o.BottomIsLocked()) { applyDelegate += () => { current.Snapshot(); current.Start = newTime.Start; current.End = newTime.End; }; current.ForceAssignSeat(coverdTerms, false); } if (overlappedTerm != null) { break; } } if (overlappedTerm == null) { applyDelegate(); } } if (overlappedTerm == null) { source.Snapshot(); source.RectifyAttribution(Boundary, value.Start); source.Start = value.Start; source.End = value.End; result = true; TermSet.Rebuild <Term>(); Reporting(source); EmptySeatArrangment <AbsentEvent>(source); source.ForceAssignSeat(coverdTerms, false); source.TryReplaceSeat(); } } if (overlappedTerm != null) { source.Exception = new TermException(overlappedTerm, "Covered"); } } callback(source, result); }