using System; using System.Text.RegularExpressions; using MfGames.Gallium; using MfGames.Nitride.Generators; using Zio; namespace MfGames.Nitride.Temporal.Schedules; /// /// A common base for a schedule that is built off the path associated with /// the entity. /// [WithProperties] public abstract partial class PathRegexScheduleBase : ISchedule { protected PathRegexScheduleBase() { this.PathRegex = @"^.*?(\d+)[^\d]*$"; this.GetPath = entity => entity.Get().ToString(); this.CaptureGroup = 1; } /// /// Gets or sets the group number of the capture group with 1 being being the /// first group in PathRegex. /// public int CaptureGroup { get; set; } /// /// Gets or sets the offset to make the resulting capture group a zero-based /// number. /// public int CaptureOffset { get; set; } /// /// Gets or sets the method for retrieving the path for the entity. /// public Func GetPath { get; set; } /// /// Gets or sets the regular expression to identify a matching path. /// public string? PathRegex { get; set; } /// public virtual Entity Apply( Entity entity, TimeService timeService) { // Get the path and match it. string path = this.GetPath(entity); Regex? regex = this.GetRegex(); Match match = regex?.Match(path) ?? throw new NullReferenceException( "PathRegex was not configured for the " + this.GetType().Name + "."); if (!match.Success) { return entity; } if (match.Groups.Count < 2) { throw new InvalidOperationException( "There must be at least one capture group in '" + this.PathRegex + "'."); } // Figure out the index/number of this entry. string numberValue = match.Groups[this.CaptureGroup].Value; if (!int.TryParse(numberValue, out int number)) { throw new FormatException( path + ": Cannot parse '" + numberValue + "' as integer."); } number += this.CaptureOffset; // Pass it onto the extending class. return this.Apply(entity, number, timeService); } /// public virtual bool CanApply(Entity entity) { string path = this.GetPath(entity); Regex? regex = this.GetRegex(); Match match = regex?.Match(path) ?? throw new NullReferenceException( "PathRegex was not configured for the " + this.GetType().Name + "."); return match.Success; } /// /// Applies the schedule according to the normalized number (after /// CaptureOffset). /// protected abstract Entity Apply( Entity entity, int number, TimeService timeService); private Regex? GetRegex() { return this.PathRegex == null ? null : new Regex(this.PathRegex); } }