Files
tbd-station-14/Content.Server/Holiday/ShouldCelebrate/Computus.cs

114 lines
3.4 KiB
C#

using System.IO;
using JetBrains.Annotations;
namespace Content.Server.Holiday.ShouldCelebrate
{
/// <summary>
/// Computus for easter calculation.
/// </summary>
[UsedImplicitly]
[DataDefinition]
public sealed partial class Computus : DefaultHolidayShouldCelebrate
{
[DataField("daysEarly")]
private byte _daysEarly = 1;
[DataField("daysExtra")]
private byte _daysExtra = 1;
public (int day, int month) DoComputus(DateTime date)
{
var currentYear = date.Year;
var m = 0;
var n = 0;
switch (currentYear)
{
case var i when i >= 1900 && i <= 2099:
m = 24;
n = 5;
break;
case var i when i >= 2100 && i <= 2199:
m = 24;
n = 6;
break;
case var i when i >= 2200 && i <= 2299:
m = 25;
n = 0;
break;
// Hello, future person! If you're living in the year >=2300, you might want to fix this method.
// t. earth coder living in 2021
default:
throw new InvalidDataException("Easter machine broke.");
}
var a = currentYear % 19;
var b = currentYear % 4;
var c = currentYear % 7;
var d = (19 * a + m) % 30;
var e = (2 * b + 4 * c + 6 * d + n) % 7;
(int day, int month) easterDate = (0, 0);
if (d + e < 10)
{
easterDate.month = 3;
easterDate.day = (d + e + 22);
} else if (d + e > 9)
{
easterDate.month = 4;
easterDate.day = (d + e - 9);
}
if (easterDate.month == 4 && easterDate.day == 26)
easterDate.day = 19;
if (easterDate.month == 4 && easterDate.day == 25 && d == 28 && e == 6 && a > 10)
easterDate.day = 18;
return easterDate;
}
public override bool ShouldCelebrate(DateTime date, HolidayPrototype holiday)
{
if (holiday.BeginMonth == Month.Invalid)
{
var (day, month) = DoComputus(date);
holiday.BeginDay = (byte) day;
holiday.BeginMonth = (Month) month;
holiday.EndDay = (byte) (holiday.BeginDay + _daysExtra);
holiday.EndMonth = holiday.BeginMonth;
// Begins in march, ends in april
if (holiday.EndDay >= 32 && holiday.EndMonth == Month.March)
{
holiday.EndDay -= 31;
holiday.EndMonth++;
}
// Begins in april, ends in june.
if (holiday.EndDay >= 31 && holiday.EndMonth == Month.April)
{
holiday.EndDay -= 30;
holiday.EndMonth++;
}
holiday.BeginDay -= _daysEarly;
// Begins in march, ends in april.
if (holiday.BeginDay <= 0 && holiday.BeginMonth == Month.April)
{
holiday.BeginDay += 31;
holiday.BeginMonth--;
}
}
return base.ShouldCelebrate(date, holiday);
}
}
}