Files
GmRelayBot/src/GmRelay.Web/Services/BatchSchedulePlanner.cs
T
Toutsu 0218890a7a
Deploy Telegram Bot / build-and-push (push) Successful in 3m49s
Deploy Telegram Bot / deploy (push) Successful in 10s
feat: add campaign templates and recurring schedules
2026-04-28 10:01:18 +03:00

92 lines
2.7 KiB
C#

using GmRelay.Shared.Domain;
namespace GmRelay.Web.Services;
public enum BatchCloneInterval
{
NextWeek,
NextMonth
}
public sealed record WebSessionBatch(
Guid Id,
Guid GroupId,
string Title,
string JoinLink,
DateTime FirstScheduledAt,
DateTime LastScheduledAt,
int SessionCount,
string NotificationMode = SessionNotificationModeExtensions.GroupAndDirectValue);
public sealed record WebCampaignTemplate(
Guid Id,
Guid GroupId,
string Name,
string Title,
string JoinLink,
int SessionCount,
int IntervalDays,
int? MaxPlayers,
string NotificationMode,
DateTime CreatedAt,
DateTime UpdatedAt);
public sealed record CreateCampaignTemplateRequest(
string Name,
string Title,
string JoinLink,
int SessionCount,
int IntervalDays,
int? MaxPlayers,
SessionNotificationMode NotificationMode);
public static class BatchSchedulePlanner
{
private const int MaxTemplateSessionCount = 52;
private const int MaxTemplateIntervalDays = 365;
public static IReadOnlyList<DateTime> BuildFixedIntervalSchedule(
IEnumerable<DateTime> currentSchedule,
DateTime firstScheduledAt,
int intervalDays)
{
if (intervalDays <= 0)
{
throw new ArgumentOutOfRangeException(nameof(intervalDays), intervalDays, "Interval must be greater than zero.");
}
return currentSchedule
.OrderBy(scheduledAt => scheduledAt)
.Select((_, index) => firstScheduledAt.AddDays(intervalDays * index))
.ToList();
}
public static IReadOnlyList<DateTime> BuildRecurringSchedule(
DateTime firstScheduledAt,
int sessionCount,
int intervalDays)
{
if (sessionCount is < 1 or > MaxTemplateSessionCount)
{
throw new ArgumentOutOfRangeException(nameof(sessionCount), sessionCount, "Session count must be between 1 and 52.");
}
if (intervalDays is < 1 or > MaxTemplateIntervalDays)
{
throw new ArgumentOutOfRangeException(nameof(intervalDays), intervalDays, "Interval must be between 1 and 365 days.");
}
return Enumerable.Range(0, sessionCount)
.Select(index => firstScheduledAt.AddDays(intervalDays * index))
.ToList();
}
public static DateTime ShiftForClone(DateTime scheduledAt, BatchCloneInterval interval) =>
interval switch
{
BatchCloneInterval.NextWeek => scheduledAt.AddDays(7),
BatchCloneInterval.NextMonth => scheduledAt.AddMonths(1),
_ => throw new ArgumentOutOfRangeException(nameof(interval), interval, "Unknown clone interval.")
};
}