public virtual TimeSpan TimeWorked(
            DateTime beginning,
            DateTime end)
        {
            var  r            = this.runner;
            var  allTimes     = this.allTimes();
            var  timeWorked   = TimeSpan.Zero;
            var  timesInRange = new XLinkedList <DateTime>();
            long timeCounter  = 0;

            foreach (var time in allTimes)
            {
                if (time < beginning)
                {
                    ++timeCounter;
                    if (timeCounter < allTimes.Count)
                    {
                        continue;
                    }

                    goto checkIfClockedInBeforeFirst;
                }

                if (time > end)
                {
                    if (timesInRange.Count < 1 && timeCounter % 2 == 1)
                    {
                        // clocked in at beginning
                        timesInRange.AddTail(beginning);
                    }

                    if (timesInRange.Count % 2 == 1)
                    {
                        // clocked in at end
                        timesInRange.AddTail(end);
                    }

                    break;
                }

checkIfClockedInBeforeFirst:
                if (timesInRange.Count < 1 && timeCounter % 2 == 1)
                {
                    // clocked in at start of range
                    timesInRange.AddHead(beginning);
                }

                if (timeCounter >= allTimes.Count)
                {
                    break;
                }

                timesInRange.AddTail(time);
            }

            var e = ((ICollection <DateTime>)timesInRange)
                    .GetEnumerator();

            while (e?.MoveNext() ?? false)
            {
                var inTime = e.Current;
                if (!e.MoveNext())
                {
                    var now = DateTime.Now;
                    r?.Run <TimeProvider>(provider =>
                    {
                        now = provider.Now();
                    });

                    if (end.Date > now)
                    {
                        if (inTime < now)
                        {
                            timeWorked += now - inTime;
                        }

                        break;
                    }

                    timeWorked += end.Date - inTime;
                    break;
                }

                var outTime = e.Current;
                timeWorked += outTime - inTime;
            }

            e.Dispose();

            return(timeWorked);
        }
Пример #2
0
        public virtual void Handle(
            TimestampsUi ui,
            HomeNavUi homeNavUi,
            StatisticsUi statsUi)
        {
            var        r   = this.runner;
            const byte one = 1;

            r?.Run <UiReaderWriter>(uiRW =>
            {
                uiRW.Write(
                    homeNavUi,
                    () =>
                {
                    homeNavUi.ActiveKeyLabel = NavKeyLabels.Timestamps;
                });
            });

            var showCurrent = true;

            r?.Run <SettingsHolder>(settings =>
            {
                showCurrent = settings.ShowCurrent;
            });
            var now   = DateTime.Now;
            var start = DateTime.Today;

            r?.Run <TimeProvider>(provider =>
            {
                now   = provider.Now();
                start = now.Date;
            });

            var end = start.AddDays(one);

            if (showCurrent)
            {
                r?.Run <DateCalculator>(
                    calc =>
                {
                    start = calc.StartOfWeek();
                    end   = calc.EndOfWeek().AddDays(one);
                });
                goto findAndSetTimesInRange;
            }

            r?.Run <UiReaderWriter>(uiRW =>
            {
                start = uiRW.Read(
                    statsUi,
                    () => statsUi.StartDate);
                end = uiRW.Read(
                    statsUi,
                    () => statsUi.EndDate)
                      .AddDays(1);
            });

findAndSetTimesInRange:
            r?.Run <
                TimestampReader,
                Lotter,
                EnumerableSplitter,
                UiReaderWriter>(
                (reader, lotter, splitter, uiRW) =>
            {
                var allTimes     = reader.ReadAll();
                var timesInRange = new XLinkedList <DateTime>();
                foreach (var time in allTimes)
                {
                    if (time < start)
                    {
                        continue;
                    }

                    if (time > end)
                    {
                        continue;
                    }

                    timesInRange.AddTail(time);
                }

                bool firstIn, lastIn;
                if (timesInRange.Count < one)
                {
                    firstIn = false;
                    lastIn  = false;
                    goto checkAdd;
                }

                firstIn = this.isInTime(
                    timesInRange.Head);
                lastIn = this.isInTime(
                    timesInRange.Tail);

                checkAdd:
                var inNow           = allTimes.Count % two == one;
                var oddTimesInRange = timesInRange.Count % two == one;
                if (oddTimesInRange)
                {
                    if (inNow && firstIn)
                    {
                        if (now > end.AddDays(one))
                        {
                            // was clocked in at end of range
                            timesInRange.AddTail(end);
                        }

                        // clocked in currently, do nothing
                        goto afterCheckClockedIn;
                    }

                    if (firstIn)
                    {
                        // clocked in at end of week
                        timesInRange.AddTail(end.Date);
                        goto afterCheckClockedIn;
                    }

                    // clocked out now but was clocked in at start of week
                    timesInRange.AddHead(start.Date);
                    goto afterCheckClockedIn;
                }

                if (timesInRange.Count > zero)
                {
                    if (!firstIn)
                    {
                        timesInRange.AddHead(start.Date);
                    }

                    if (lastIn && end < now)
                    {
                        timesInRange.AddTail(end.Date);
                    }
                }

                afterCheckClockedIn:
                var splitTimesThisWeek = splitter.Split(
                    timesInRange,
                    two);
                var inTimes   = splitTimesThisWeek[zero];
                var uiTimesIn = lotter.Materialize(
                    EnumerableHelpers.Select(
                        inTimes,
                        this.formatTimestamp));
                uiRW.Write(
                    ui,
                    () =>
                {
                    ui.InTimes = uiTimesIn;
                });

                var outTimes   = splitTimesThisWeek[one];
                var uiTimesOut = lotter.Materialize(
                    EnumerableHelpers.Select(
                        outTimes,
                        this.formatTimestamp));

                uiRW.Write(
                    ui,
                    () =>
                {
                    ui.OutTimes = uiTimesOut;
                });

                r.Run <EnumerableSplicer>(
                    splicer =>
                {
                    var splicedTimes = splicer.Splice(
                        new[]
                    {
                        inTimes,
                        outTimes
                    });
                    short indexer = zero;
                    DateTime
                    currentInTime = default,