using System; using MfGames.Gallium; using MfGames.Nitride.Generators; using NodaTime; namespace MfGames.Nitride.Temporal.Schedules; /// /// A schedule that uses the `UPath` of the entity to determine an offset from /// a starting point and calculates the information from there. /// [WithProperties] public partial class PeriodicPathRegexSchedule : PathRegexScheduleBase { public PeriodicPathRegexSchedule() { this.CaptureOffset = -1; } /// /// Gets or sets the period between each matching entity. The period is /// amount of time between each item based on the number. So the first will /// be on the ScheduleDate, the second SchedulePeriod later, the third /// SchedulePeriod after the second, etc. More precisely, the date for /// any item TimeSpan * ((int)CaptureGroup + (int)CaptureOffset). /// public string? SchedulePeriod { get; set; } /// /// Gets or sets the schedule period as a TimeSpan object. This is converted /// from SchedulePeriod using https://github.com/pengowray/TimeSpanParser. /// If the value is null or blank or "immediate", then this will be instant /// (TimeSpan.Zero). /// public virtual TimeSpan? SchedulePeriodTimeSpan { get => TimeSpanHelper.Parse(this.SchedulePeriod); set => this.SchedulePeriod = value?.ToString(); } /// /// Gets or sets when the first item is scheduled. /// public DateTime? ScheduleStart { get; set; } /// protected override Entity Apply( Entity entity, int number, TimeService timeService) { // If we have a "never", then we skip it. TimeSpan? period = this.SchedulePeriodTimeSpan; DateTime? start = this.ScheduleStart; if (period == null || start == null) { return entity; } // Figure out the time from the start. DateTime when = start.Value + period.Value * number; Instant instant = timeService.CreateInstant(when); // If the time hasn't past, then we don't apply it. Instant now = timeService.Clock.GetCurrentInstant(); return instant > now ? entity : this.Apply(entity, number, instant); } /// /// Applies the schedule to the entity based on the number and instant /// given. /// protected virtual Entity Apply( Entity entity, int number, Instant instant) { return entity.Set(instant); } }