feat(schedules): changed ApplySchedules.Schedules to a getter GetSchedules
This commit is contained in:
parent
fc1ab22a0e
commit
08aafb144c
6 changed files with 100 additions and 31 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
@ -8,24 +9,6 @@ using MfGames.Nitride.Generators;
|
||||||
|
|
||||||
namespace MfGames.Nitride.Temporal.Schedules;
|
namespace MfGames.Nitride.Temporal.Schedules;
|
||||||
|
|
||||||
public enum SchedulePeriod
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates that all the matching schedule periods are instant (zero time).
|
|
||||||
/// </summary>
|
|
||||||
Instant,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates that the entities will be scheduled a day apart.
|
|
||||||
/// </summary>
|
|
||||||
Day,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates that the entities will be scheduled seven days apart.
|
|
||||||
/// </summary>
|
|
||||||
Week,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies schedules against the list of entities.
|
/// Applies schedules against the list of entities.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -40,13 +23,15 @@ public partial class ApplySchedules : OperationBase
|
||||||
{
|
{
|
||||||
this.Timekeeper = timekeeper;
|
this.Timekeeper = timekeeper;
|
||||||
this.validator = validator;
|
this.validator = validator;
|
||||||
this.Schedules = new List<ISchedule>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ordered list of schedules to apply to the entities.
|
/// Gets or sets the callback to get the schedules for the entity. This is
|
||||||
|
/// used to allow for per-entity schedules or generic schedules across
|
||||||
|
/// the entire system. If this returns null, then no schedule will be
|
||||||
|
/// applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IList<ISchedule> Schedules { get; set; }
|
public Func<Entity, IList<ISchedule>?>? GetSchedules { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the timekeeper associated with this operation.
|
/// Gets or sets the timekeeper associated with this operation.
|
||||||
|
@ -61,16 +46,30 @@ public partial class ApplySchedules : OperationBase
|
||||||
return input.Select(this.Apply);
|
return input.Select(this.Apply);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApplySchedules WithSchedules<TItem>(IEnumerable<TItem> items)
|
public ApplySchedules WithGetSchedules<TType>(
|
||||||
where TItem : ISchedule
|
Func<Entity, IEnumerable<TType>?> value)
|
||||||
|
where TType : ISchedule
|
||||||
{
|
{
|
||||||
this.Schedules = items.OfType<ISchedule>().ToList();
|
this.GetSchedules = entity => value?
|
||||||
|
.Invoke(entity)
|
||||||
|
?.Cast<ISchedule>()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Entity Apply(Entity entity)
|
private Entity Apply(Entity entity)
|
||||||
{
|
{
|
||||||
foreach (ISchedule schedule in this.Schedules)
|
// Get the schedule for this entity.
|
||||||
|
IList<ISchedule>? schedules = this.GetSchedules?.Invoke(entity);
|
||||||
|
|
||||||
|
if (schedules == null || schedules.Count == 0)
|
||||||
|
{
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, apply the schedules to this entity.
|
||||||
|
foreach (ISchedule schedule in schedules)
|
||||||
{
|
{
|
||||||
if (!schedule.CanApply(entity))
|
if (!schedule.CanApply(entity))
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,7 +20,7 @@ public partial class NumericalPathSchedule : ISchedule
|
||||||
public NumericalPathSchedule()
|
public NumericalPathSchedule()
|
||||||
{
|
{
|
||||||
this.PathRegex = new Regex(@"^.*(\d+)");
|
this.PathRegex = new Regex(@"^.*(\d+)");
|
||||||
this.GetPath = (entity) => entity.Get<UPath>().ToString();
|
this.GetPath = entity => entity.Get<UPath>().ToString();
|
||||||
this.CaptureGroup = 1;
|
this.CaptureGroup = 1;
|
||||||
this.CaptureOffset = -1;
|
this.CaptureOffset = -1;
|
||||||
}
|
}
|
||||||
|
|
19
src/MfGames.Nitride.Temporal.Schedules/SchedulePeriod.cs
Normal file
19
src/MfGames.Nitride.Temporal.Schedules/SchedulePeriod.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
namespace MfGames.Nitride.Temporal.Schedules;
|
||||||
|
|
||||||
|
public enum SchedulePeriod
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that all the matching schedule periods are instant (zero time).
|
||||||
|
/// </summary>
|
||||||
|
Instant,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the entities will be scheduled a day apart.
|
||||||
|
/// </summary>
|
||||||
|
Day,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the entities will be scheduled seven days apart.
|
||||||
|
/// </summary>
|
||||||
|
Week,
|
||||||
|
}
|
51
src/MfGames.Nitride.Temporal.Schedules/SimplePathSchedule.cs
Normal file
51
src/MfGames.Nitride.Temporal.Schedules/SimplePathSchedule.cs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using MfGames.Gallium;
|
||||||
|
using MfGames.Nitride.Generators;
|
||||||
|
|
||||||
|
using NodaTime;
|
||||||
|
|
||||||
|
namespace MfGames.Nitride.Temporal.Schedules;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A schedule that goes against all entities it is applied to.
|
||||||
|
/// </summary>
|
||||||
|
[WithProperties]
|
||||||
|
public partial class SimplePathSchedule : ISchedule
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets when the first item is scheduled.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? ScheduleStart { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual Entity Apply(
|
||||||
|
Entity entity,
|
||||||
|
Timekeeper timekeeper)
|
||||||
|
{
|
||||||
|
DateTime start = this.ScheduleStart
|
||||||
|
?? throw new NullReferenceException(
|
||||||
|
"Cannot use a schedule without a start date.");
|
||||||
|
Instant instant = timekeeper.CreateInstant(start);
|
||||||
|
|
||||||
|
// If the time hasn't past, then we don't apply it.
|
||||||
|
Instant now = timekeeper.Clock.GetCurrentInstant();
|
||||||
|
|
||||||
|
return instant > now
|
||||||
|
? entity
|
||||||
|
: this.Apply(entity, instant);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual bool CanApply(Entity entity)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual Entity Apply(
|
||||||
|
Entity entity,
|
||||||
|
Instant instant)
|
||||||
|
{
|
||||||
|
return entity.Set(instant);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,8 +6,8 @@ public class ApplySchedulesValidator : AbstractValidator<ApplySchedules>
|
||||||
{
|
{
|
||||||
public ApplySchedulesValidator()
|
public ApplySchedulesValidator()
|
||||||
{
|
{
|
||||||
this.RuleFor(x => x.Schedules)
|
this.RuleFor(x => x.GetSchedules)
|
||||||
.NotEmpty();
|
.NotNull();
|
||||||
|
|
||||||
this.RuleFor(x => x.Timekeeper)
|
this.RuleFor(x => x.Timekeeper)
|
||||||
.NotNull();
|
.NotNull();
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class NumericalPathScheduleTests : TemporalSchedulesTestBase
|
||||||
// second but before the third item.
|
// second but before the third item.
|
||||||
Timekeeper time = context.Resolve<Timekeeper>();
|
Timekeeper time = context.Resolve<Timekeeper>();
|
||||||
ApplySchedules op = context.Resolve<ApplySchedules>()
|
ApplySchedules op = context.Resolve<ApplySchedules>()
|
||||||
.WithSchedules(schedules);
|
.WithGetSchedules(_ => schedules);
|
||||||
var now = Instant.FromUtc(2023, 1, 9, 0, 0);
|
var now = Instant.FromUtc(2023, 1, 9, 0, 0);
|
||||||
|
|
||||||
time.Clock = new FakeClock(now);
|
time.Clock = new FakeClock(now);
|
||||||
|
@ -111,7 +111,7 @@ public class NumericalPathScheduleTests : TemporalSchedulesTestBase
|
||||||
// second but before the third item.
|
// second but before the third item.
|
||||||
Timekeeper time = context.Resolve<Timekeeper>();
|
Timekeeper time = context.Resolve<Timekeeper>();
|
||||||
ApplySchedules op = context.Resolve<ApplySchedules>()
|
ApplySchedules op = context.Resolve<ApplySchedules>()
|
||||||
.WithSchedules(schedules);
|
.WithGetSchedules(_ => schedules);
|
||||||
var now = Instant.FromUtc(2023, 1, 9, 0, 0);
|
var now = Instant.FromUtc(2023, 1, 9, 0, 0);
|
||||||
|
|
||||||
time.Clock = new FakeClock(now);
|
time.Clock = new FakeClock(now);
|
||||||
|
@ -171,7 +171,7 @@ public class NumericalPathScheduleTests : TemporalSchedulesTestBase
|
||||||
// second but before the third item.
|
// second but before the third item.
|
||||||
Timekeeper time = context.Resolve<Timekeeper>();
|
Timekeeper time = context.Resolve<Timekeeper>();
|
||||||
ApplySchedules op = context.Resolve<ApplySchedules>()
|
ApplySchedules op = context.Resolve<ApplySchedules>()
|
||||||
.WithSchedules(schedules);
|
.WithGetSchedules(_ => schedules);
|
||||||
var now = Instant.FromUtc(2023, 1, 9, 0, 0);
|
var now = Instant.FromUtc(2023, 1, 9, 0, 0);
|
||||||
|
|
||||||
time.Clock = new FakeClock(now);
|
time.Clock = new FakeClock(now);
|
||||||
|
|
Reference in a new issue