mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 09:48:26 -04:00
104 lines
3.8 KiB
C#
104 lines
3.8 KiB
C#
using NadekoBot.Services.Database.Models;
|
|
|
|
namespace NadekoBot.Modules.Utility.Services;
|
|
|
|
public sealed class RunningRepeater
|
|
{
|
|
public DateTime NextTime { get; private set; }
|
|
|
|
public Repeater Repeater { get; }
|
|
public int ErrorCount { get; set; }
|
|
|
|
public RunningRepeater(Repeater repeater)
|
|
{
|
|
this.Repeater = repeater;
|
|
NextTime = CalculateInitialExecution();
|
|
}
|
|
|
|
public void UpdateNextTime()
|
|
{
|
|
NextTime = DateTime.UtcNow + Repeater.Interval;
|
|
}
|
|
|
|
private DateTime CalculateInitialExecution()
|
|
{
|
|
if (Repeater.StartTimeOfDay != null)
|
|
{
|
|
// if there was a start time of day
|
|
// calculate whats the next time of day repeat should trigger at
|
|
// based on teh dateadded
|
|
|
|
// i know this is not null because of the check in the query
|
|
var added = Repeater.DateAdded;
|
|
|
|
// initial trigger was the time of day specified by the command.
|
|
var initialTriggerTimeOfDay = Repeater.StartTimeOfDay.Value;
|
|
|
|
DateTime initialDateTime;
|
|
|
|
// if added timeofday is less than specified timeofday for initial trigger
|
|
// that means the repeater first ran that same day at that exact specified time
|
|
if (added.TimeOfDay <= initialTriggerTimeOfDay)
|
|
{
|
|
// in that case, just add the difference to make sure the timeofday is the same
|
|
initialDateTime = added + (initialTriggerTimeOfDay - added.TimeOfDay);
|
|
}
|
|
else
|
|
{
|
|
// if not, then it ran at that time the following day
|
|
// in other words; Add one day, and subtract how much time passed since that time of day
|
|
initialDateTime = added + TimeSpan.FromDays(1) - (added.TimeOfDay - initialTriggerTimeOfDay);
|
|
}
|
|
|
|
return CalculateInitialInterval(initialDateTime);
|
|
}
|
|
|
|
// if repeater is not running daily, its initial time is the time it was Added at, plus the interval
|
|
return CalculateInitialInterval(Repeater.DateAdded + Repeater.Interval);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate when is the proper time to run the repeater again based on initial time repeater ran.
|
|
/// </summary>
|
|
/// <param name="repeaterter"></param>
|
|
/// <param name="initialDateTime">Initial time repeater ran at (or should run at).</param>
|
|
private DateTime CalculateInitialInterval(DateTime initialDateTime)
|
|
{
|
|
// if the initial time is greater than now, that means the repeater didn't still execute a single time.
|
|
// just schedule it
|
|
if (initialDateTime > DateTime.UtcNow)
|
|
{
|
|
return initialDateTime;
|
|
}
|
|
|
|
// else calculate based on minutes difference
|
|
|
|
// get the difference
|
|
var diff = DateTime.UtcNow - initialDateTime;
|
|
|
|
// see how many times the repeater theoretically ran already
|
|
var triggerCount = diff / Repeater.Interval;
|
|
|
|
// ok lets say repeater was scheduled to run 10h ago.
|
|
// we have an interval of 2.4h
|
|
// repeater should've ran 4 times- that's 9.6h
|
|
// next time should be in 2h from now exactly
|
|
// 10/2.4 is 4.166
|
|
// 4.166 - Math.Truncate(4.166) is 0.166
|
|
// initial interval multiplier is 1 - 0.166 = 0.834
|
|
// interval (2.4h) * 0.834 is 2.0016 and that is the initial interval
|
|
|
|
var initialIntervalMultiplier = 1 - (triggerCount - Math.Truncate(triggerCount));
|
|
return DateTime.UtcNow + (Repeater.Interval * initialIntervalMultiplier);
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
return obj is RunningRepeater rr && rr.Repeater.Id == this.Repeater.Id;
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return this.Repeater.Id;
|
|
}
|
|
} |