public List <ICalendarDay> GenerateWeeks(DateTime dateTime, int weeksCount) { var days = new List <ICalendarDay>(); int dayCount = _calendar.WeekTemplate.Count; for (var i = 0; i < weeksCount; i++) { for (var j = 0; j < dayCount; j++) { ICalendarDay day; DateTime calendarDate = dateTime.AddDays(j + dayCount * i); ICalendarDay dayOff = _calendar.DayOffs .FirstOrDefault(d => d.CalendarDateTime.Date == calendarDate.Date); if (dayOff != null) { day = (ICalendarDay)dayOff.Clone(); } else { var dayOfWeek = _calendar.WeekTemplate .FirstOrDefault(d => d.DayOfWeek == calendarDate.DayOfWeek); day = (ICalendarDay)dayOfWeek.Clone(); day.CalendarDateTime = calendarDate; } days.Add(day); } } return(days); }
/// <summary> /// Get amount of non-working minutes on the day of case registration. /// </summary> /// <param name="days">Calendar days.</param> /// <param name="registrationDate">Case registration date.</param> /// <returns>Non-working minutes on the day of case registration.</returns> public static int GetNonWorkingMinutes(this IEnumerable <ICalendarDay> days, DateTime registrationDate) { ICalendarDay calendarDay = days.FirstOrDefault(day => day.DayOfWeek == registrationDate.DayOfWeek); if (calendarDay != null && !calendarDay.IsNonWorking) { IList <WorkingInterval> intervals = calendarDay.WorkingIntervals; WorkingInterval workingInterval = intervals.FirstOrDefault(interval => interval.GetIsDateBetween(registrationDate)); if (!workingInterval.Equals(default(WorkingInterval))) { int index = intervals.IndexOf(workingInterval); double minutesSumm = 0; for (int i = 0; i < index; i++) { minutesSumm += intervals[i].Length.TotalMinutes; } TimeSpan intervalMinuteOffset = registrationDate.TimeOfDay - intervals[index].Start; minutesSumm += intervalMinuteOffset.TotalMinutes; return((int)minutesSumm); } return((int)calendarDay.GetWorkingTime()); } return(default(int)); }
protected void LogFirstCalculationInterval(ICalendarDay day) { if (TermCalculationLogStore != null) { new TermCalculationLogger(TermCalculationLogStore) .AddFirstNonWorkingCalculationInterval(day); } }
/// <summary> /// Actualize calendar days for calculation. /// </summary> /// <param name="days">Calendar days.</param> /// <param name="dateTime">Calculation pivot.</param> public override void ActualizeDays(ref IEnumerable <ICalendarDay> days, DateTime dateTime) { ICalendarDay day = days.FirstOrDefault(d => d.CalendarDateTime.Date == dateTime.Date); if (day != default(ICalendarDay)) { day.WorkingIntervals = day.WorkingIntervals.Select(i => i.Truncate(dateTime)).ToList(); } }
/// <summary> /// Fills calculated working minutes time intervals. /// </summary> /// <param name="day">Calendar day.</param> /// <param name="workingTime">Working minute time.</param> public void FillWorkingMinuteCalculationInterval(ICalendarDay day, double workingTime) { _logStore.CalculationIntervals.Add(new CalculationInterval { IsWorkingDay = !day.IsNonWorking, SpentIntervalValue = workingTime, DayOfWeek = GetLocalDayOfWeek(day.DayOfWeek), CalendarDateTime = day.CalendarDateTime.ToString(_logStore.UserCulture.DateTimeFormat.ShortDatePattern) }); }
/// <summary> /// Fills first calculated working days time interval. /// </summary> /// <param name="day">Calendar day.</param> public void AddFirstNonWorkingCalculationInterval(ICalendarDay day) { if (_logStore.IsUsedIntervalCalculated) { _logStore.CalculationIntervals.Add(new CalculationInterval { IsWorkingDay = !day.IsNonWorking, SpentIntervalValue = 0, DayOfWeek = GetLocalDayOfWeek(day.DayOfWeek), CalendarDateTime = day.CalendarDateTime.ToString(_logStore.UserCulture.DateTimeFormat.ShortDatePattern) }); } }
public void Run(int day, string input) { if (!HasBeenSolved(day)) { Console.WriteLine($"Day {day} has not been solved!"); return; } ICalendarDay solution = Get(day); Console.WriteLine($"Day: {day}"); Console.WriteLine($"First Task: {solution.RunFirstPart(input)}"); Console.WriteLine($"Second Task: {solution.RunSecondPart(input)}\n"); }
/// <summary> /// Gets amount of time units from the very left day time point up to the <paramref name="end"/>. /// </summary> /// <param name="days">Calendar days.</param> /// <param name="end">Date and time of the end.</param> /// <returns>Time units amount.</returns> protected virtual int GetTimeUnits(IEnumerable <ICalendarDay> days, DateTime end) { double result = days .TakeWhile(day => day.CalendarDateTime.Date < end.Date) .Sum(day => day.GetWorkingTime()); ICalendarDay lastDay = days.FirstOrDefault(day => day.CalendarDateTime.Date == end.Date); if (lastDay != default(ICalendarDay)) { int least = GetSingleDayTimeUnits(lastDay, end); result += least; } return((int)result); }
/// <summary> /// Actualize calendar days for calculation. /// </summary> /// <param name="days">Calendar days.</param> /// <param name="dateTime">Calculation pivot.</param> public override void ActualizeDays(ref IEnumerable <ICalendarDay> days, DateTime dateTime) { ICalendarDay day = days.FirstOrDefault(d => d.CalendarDateTime.Date == dateTime.Date); if (day.WorkingIntervals.Count == 0) { return; } TimeSpan startInterval = day.WorkingIntervals.Min(i => i.Start); if (dateTime.TimeOfDay > startInterval) { days = days.Except(new[] { day }); } }
/// <summary> /// Adds <paramref name="minutes"/> by given days of the calendar. /// </summary> /// <param name="days">Calendar days.</param> /// <param name="minutes">Minutes to add.</param> /// <returns>Calculated date and time.</returns> public override DateTime Calculate(IEnumerable <ICalendarDay> days, int minutes) { var result = default(DateTime); double timeLeft = minutes; bool keepEnumeration = true; IEnumerator <ICalendarDay> daysEnumerator = days.GetEnumerator(); while (daysEnumerator.MoveNext() && keepEnumeration) { ICalendarDay day = daysEnumerator.Current; IEnumerator <WorkingInterval> intervalEnumerator = day.WorkingIntervals.GetEnumerator(); var workingTime = day.GetWorkingTime(); if (timeLeft > workingTime) { timeLeft -= workingTime; if (TermCalculationLogStore != null) { new TermCalculationLogger(TermCalculationLogStore) .FillWorkingMinuteCalculationInterval(day, workingTime); } } else { if (TermCalculationLogStore != null) { new TermCalculationLogger(TermCalculationLogStore) .FillWorkingMinuteCalculationInterval(day, timeLeft); } while (intervalEnumerator.MoveNext() && keepEnumeration) { WorkingInterval interval = intervalEnumerator.Current; double intervalMinutes = interval.Length.TotalMinutes; if (timeLeft > intervalMinutes) { timeLeft -= intervalMinutes; } else { result = day.CalendarDateTime.Date .Add(interval.Start) .AddMinutes(timeLeft); keepEnumeration = false; } } } } return(result); }
private int GetSingleDayTimeUnits(ICalendarDay day, DateTime end) { var length = default(TimeSpan); IEnumerator <WorkingInterval> enumerator = day.WorkingIntervals.GetEnumerator(); if (!day.WorkingIntervals.Any(interval => interval.GetIsDateBetween(end))) { return(0); } while (enumerator.MoveNext() && !enumerator.Current.GetIsDateBetween(end)) { length += enumerator.Current.Length; } length += enumerator.Current.Truncate(end, true).Length; return((int)length.TotalMinutes); }
/// <summary> /// Fills calendar week template. /// </summary> /// <param name="calendar">Calendar.</param> private void FillWeekTemplate(T calendar) { var query = new EntitySchemaQuery(_userConnection.EntitySchemaManager, "DayInCalendar"); string dayOfWeekCode = query.AddColumn("DayOfWeek.Code").Name; string dayOfWeekNonWorking = query.AddColumn("DayType.NonWorking").Name; string dayType = query.AddColumn("DayType.Id").Name; var intervalToColumn = query.AddColumn("[WorkingTimeInterval:DayInCalendar].To"); intervalToColumn.OrderByAsc(0); var intervalFromColumn = query.AddColumn("[WorkingTimeInterval:DayInCalendar].From"); intervalFromColumn.OrderByAsc(1); string dayOfWeekFromPeriod = intervalFromColumn.Name; string dayOfWeekToPeriod = intervalToColumn.Name; query.Filters.Add( query.CreateFilterWithParameters(FilterComparisonType.Equal, "Calendar", calendar.Id)); EntityCollection collection = query.GetEntityCollection(_userConnection); foreach (var record in collection) { var start = record.GetTypedColumnValue <DateTime>(dayOfWeekFromPeriod); var end = record.GetTypedColumnValue <DateTime>(dayOfWeekToPeriod); var dayCode = record.GetTypedColumnValue <string>(dayOfWeekCode); var dayOfWeek = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), dayCode); ICalendarDay day = calendar.WeekTemplate.FirstOrDefault(item => item.DayOfWeek == dayOfWeek); if (day == default(ICalendarDay)) { var isNonWorking = record.GetTypedColumnValue <bool>(dayOfWeekNonWorking); var dayTypeUId = record.GetTypedColumnValue <Guid>(dayType); day = new CalendarDay { DayOfWeek = dayOfWeek, IsNonWorking = isNonWorking, DayTypeUId = dayTypeUId }; calendar.WeekTemplate.Add(day); } if (!day.IsNonWorking) { day.WorkingIntervals.Add(new WorkingInterval(start.TimeOfDay, end.TimeOfDay)); } } }
/// <summary> /// Fills calendar day offs. /// </summary> /// <param name="calendar">Calendar.</param> private void FillDayOffInfo(T calendar) { var query = new EntitySchemaQuery(_userConnection.EntitySchemaManager, "DayOff"); string date = query.AddColumn("Date").Name; string dayType = query.AddColumn("DayType.Id").Name; string dayOffNonWorking = query.AddColumn("DayType.NonWorking").Name; string dayOffFromPeriod = query.AddColumn("[WorkingTimeInterval:DayOff].From").Name; string dayOffToPeriod = query.AddColumn("[WorkingTimeInterval:DayOff].To").Name; query.Filters.Add(query.CreateFilterWithParameters(FilterComparisonType.Equal, "Calendar", calendar.Id)); EntityCollection collection = query.GetEntityCollection(_userConnection); foreach (var record in collection) { var start = record.GetTypedColumnValue <DateTime>(dayOffFromPeriod); var end = record.GetTypedColumnValue <DateTime>(dayOffToPeriod); var dayTypeId = record.GetTypedColumnValue <Guid>(dayType); var isNonWorking = record.GetTypedColumnValue <bool>(dayOffNonWorking); if (!isNonWorking && (start == default(DateTime) || end == default(DateTime))) { continue; } var dayDate = record.GetTypedColumnValue <DateTime>(date); ICalendarDay dayOff = calendar.DayOffs.FirstOrDefault(item => item.CalendarDateTime.Date == dayDate); if (dayOff == default(ICalendarDay)) { dayOff = new CalendarDay { CalendarDateTime = dayDate, IsNonWorking = isNonWorking, DayTypeUId = dayTypeId, DayOfWeek = dayDate.DayOfWeek }; calendar.DayOffs.Add(dayOff); } if (!dayOff.IsNonWorking) { dayOff.WorkingIntervals.Add(new WorkingInterval(start.TimeOfDay, end.TimeOfDay)); } } }
/// <summary> /// Generate calendar days by calendar week template. /// </summary> /// <param name="calendar">The calendar.</param> /// <param name="dateTime">The date time.</param> /// <param name="weeksCount">Number of weeks to generate.</param> /// <returns> /// Calendar days. /// </returns> /// <exception cref="Exception">Unable to find day of week in week template</exception> public static IEnumerable <ICalendarDay> GenerateWeeks(this ICalendar <ICalendarDay> calendar, DateTime dateTime, int weeksCount) { int daysOffInPeriod = 0; var days = new List <ICalendarDay>(); int dayCount = calendar.WeekTemplate.Count; for (var i = 0; i < weeksCount + Math.Ceiling((decimal)daysOffInPeriod / 7); i++) { for (var j = 0; j < dayCount; j++) { ICalendarDay day; DateTime calendarDate = dateTime.AddDays(j + dayCount * i); ICalendarDay dayOff = calendar.DayOffs .FirstOrDefault(d => d.CalendarDateTime.Date == calendarDate.Date); if (dayOff != null) { day = (ICalendarDay)dayOff.Clone(); daysOffInPeriod++; } else { var dayOfWeek = calendar.WeekTemplate .FirstOrDefault(d => d.DayOfWeek == calendarDate.DayOfWeek); if (dayOfWeek == default(ICalendarDay)) { throw new Exception("Unable to find day of week in week template"); } day = (ICalendarDay)dayOfWeek.Clone(); day.CalendarDateTime = calendarDate; } days.Add(day); } } return(days); }
private void Add(int day, ICalendarDay solution) { _calendarDays.Add(day, solution); }