Ejemplo n.º 1
0
        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);
        }