diff --git a/MultiversalDiplomacy/Model/TimelineFactory.cs b/MultiversalDiplomacy/Model/TimelineFactory.cs
index 63c48b3..4cee83e 100644
--- a/MultiversalDiplomacy/Model/TimelineFactory.cs
+++ b/MultiversalDiplomacy/Model/TimelineFactory.cs
@@ -34,19 +34,33 @@ public class TimelineFactory(int nextTimeline)
///
/// Convert a timeline serial number to its string identifier.
///
- /// Integer.
+ /// Integer.
/// Timeline identifier.
- public static string IntToString(int designation) {
+ public static string IntToString(int serial) {
static int downshift(int i ) => (i - (i % 26)) / 26;
- IEnumerable result = [Letters[designation % 26]];
- for (int remainder = downshift(designation); remainder > 0; remainder = downshift(remainder) - 1) {
+ IEnumerable result = [Letters[serial % 26]];
+ for (int remainder = downshift(serial); remainder > 0; remainder = downshift(remainder) - 1) {
// We subtract 1 after downshifting for the same reason we add 1 above after upshifting.
- //
result = result.Prepend(Letters[(remainder % 26 + 25) % 26]);
}
return new string(result.ToArray());
}
+ ///
+ /// Extract the timeline and turn components of a season designation.
+ ///
+ /// A timeline-turn season designation.
+ /// The timeline and turn components.
+ ///
+ public static (string timeline, int turn) SplitKey(string seasonKey)
+ {
+ int i = 1;
+ for (; !char.IsAsciiDigit(seasonKey[i]) && i < seasonKey.Length; i++);
+ return int.TryParse(seasonKey.AsSpan(i), out int turn)
+ ? (seasonKey[..i], turn)
+ : throw new FormatException($"Could not parse turn from {seasonKey}");
+ }
+
public TimelineFactory() : this(0) { }
public int nextTimeline = nextTimeline;
diff --git a/MultiversalDiplomacyTests/Model/TimelineFactoryTest.cs b/MultiversalDiplomacyTests/Model/TimelineFactoryTest.cs
index 26d30dd..56a0c75 100644
--- a/MultiversalDiplomacyTests/Model/TimelineFactoryTest.cs
+++ b/MultiversalDiplomacyTests/Model/TimelineFactoryTest.cs
@@ -22,6 +22,16 @@ public class TimelineFactoryTest
Assert.That(TimelineFactory.StringToInt(designation), Is.EqualTo(number), "Incorrect number");
}
+ [TestCase("a0", "a", 0)]
+ [TestCase("a1", "a", 1)]
+ [TestCase("a10", "a", 10)]
+ [TestCase("aa2", "aa", 2)]
+ [TestCase("aa22", "aa", 22)]
+ public void SeasonKeySplit(string key, string timeline, int turn)
+ {
+ Assert.That(TimelineFactory.SplitKey(key), Is.EqualTo((timeline, turn)), "Failed to split key");
+ }
+
[Test]
public void NoSharedFactoryState()
{