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); }
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,