5dplomacy/MultiversalDiplomacy/Model/Timeline.cs

139 lines
3.8 KiB
C#
Raw Permalink Normal View History

2022-11-10 18:11:44 +00:00
using System.Diagnostics.CodeAnalysis;
namespace MultiversalDiplomacy.Model;
/// <summary>
/// A timeline of a game. Essentially a wrapper around <see cref="int"/> for tracking the multiversal dimension.
/// </summary>
public struct Timeline
{
public readonly int number;
/// <summary>
/// Timeline designations for differentiating timelines. Shortenable to the first character.
/// </summary>
private static readonly string[] primaryDesignations = new string[]
{
"alfa",
"bravo",
"charlie",
"delta",
"echo",
"foxtrot",
"golf",
"hotel",
"india",
"juliett",
"kilo",
"lima",
"mike",
"november",
"oscar",
"papa",
"quebec",
"romeo",
"sierra",
"tango",
"uniform",
"victor",
"whiskey",
"xray",
"yankee",
"zulu"
};
/// <summary>
/// Disambiguators used once all primary timeline designations have been used.
/// </summary>
private static readonly string[] secondaryDesignations = new string[]
{
"",
"-prime",
"-second",
"-third",
"-fourth",
"-fifth",
"-sixth",
"-seventh",
"-eighth",
"-ninth",
};
/// <summary>
/// Short versions of the secondary timeline disambiguators.
/// </summary>
private static readonly string[] secondaryDesignationsShort = new string[]
{
"",
"'",
"\"",
"\x2073",
"\x2074",
"\x2075",
"\x2076",
"\x2077",
"\x2078",
"\x2079",
};
public Timeline(int number)
{
if (number < FIRST_TIMELINE)
{
throw new ArgumentException($"Invalid timeline number: {number}", nameof(number));
}
if (number >= primaryDesignations.Length * secondaryDesignations.Length)
{
throw new ArgumentException($"Timeline number too high: {number}", nameof(number));
}
this.number = number;
}
/// <summary>
/// The first timeline number.
/// </summary>
public const int FIRST_TIMELINE = 0;
/// <summary>
/// Which primary designation the timeline has.
/// </summary>
private int primaryIndex => number % primaryDesignations.Length;
/// <summary>
/// Which secondary designation the timeline has.
/// </summary>
private int secondaryIndex => number / primaryDesignations.Length;
/// <summary>
/// Returns the timeline's full string representation.
/// </summary>
/// <returns>The timeline designation as a string, such as "bravo" or "delta-prime".</returns>
public override string ToString()
=> primaryDesignations[primaryIndex] + secondaryDesignations[secondaryIndex];
/// <summary>
/// Returns a shorter string representation of the timeline.
/// </summary>
/// <returns>The timeline's designation as a string, such as "b" or "d'".</returns>
public string ToShort()
=> primaryDesignations[primaryIndex][0] + secondaryDesignationsShort[secondaryIndex];
/// <summary>
/// Returns a value indicating whether this instance is equal to a specified <see cref="Timeline"/> value.
/// </summary>
/// <returns>true if obj has the same value as this instance; otherwise, false.</returns>
public override bool Equals([NotNullWhen(true)] object? obj)
=> obj is Timeline other
? number.Equals(other.number)
: false;
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
=> number.GetHashCode();
public static int operator -(Timeline first, Timeline second)
=> Math.Abs(first.number - second.number);
}