diff --git a/Mapperator.ConsoleApp/Mapperator.ConsoleApp.csproj b/Mapperator.ConsoleApp/Mapperator.ConsoleApp.csproj
index 21a56f5..d0dc8de 100644
--- a/Mapperator.ConsoleApp/Mapperator.ConsoleApp.csproj
+++ b/Mapperator.ConsoleApp/Mapperator.ConsoleApp.csproj
@@ -7,16 +7,16 @@
-
+
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/Mapperator.ConsoleApp/Program.cs b/Mapperator.ConsoleApp/Program.cs
index 584f79f..7acdc6f 100644
--- a/Mapperator.ConsoleApp/Program.cs
+++ b/Mapperator.ConsoleApp/Program.cs
@@ -19,17 +19,17 @@ private static int Main(string[] args) {
Dataset.DatasetOptions,
Dataset2.DatasetOptions2
>(args)
- .MapResult(
- (Count.CountOptions opts) => Count.DoDataCount(opts),
- (Extract.ExtractOptions opts) => Extract.DoDataExtraction(opts),
- (Build.BuildOptions opts) => Build.DoBuildGraph(opts),
- (Convert.ConvertOptions opts) => Convert.DoMapConvert(opts),
- (Search.SearchOptions opts) => Search.DoPatternSearch(opts),
- (Analyze.AnalyzeOptions opts) => Analyze.DoVisualSpacingExtract(opts),
- (Extract2.Extract2Options opts) => Extract2.DoDataExtraction(opts),
- (Dataset.DatasetOptions opts) => Dataset.DoDataExtraction(opts),
- (Dataset2.DatasetOptions2 opts) => Dataset2.DoDataExtraction2(opts),
- _ => 1);
+ .MapResult(
+ (Count.CountOptions opts) => Count.DoDataCount(opts),
+ (Extract.ExtractOptions opts) => Extract.DoDataExtraction(opts),
+ (Build.BuildOptions opts) => Build.DoBuildGraph(opts),
+ (Convert.ConvertOptions opts) => Convert.DoMapConvert(opts),
+ (Search.SearchOptions opts) => Search.DoPatternSearch(opts),
+ (Analyze.AnalyzeOptions opts) => Analyze.DoVisualSpacingExtract(opts),
+ (Extract2.Extract2Options opts) => Extract2.DoDataExtraction(opts),
+ (Dataset.DatasetOptions opts) => Dataset.DoDataExtraction(opts),
+ (Dataset2.DatasetOptions2 opts) => Dataset2.DoDataExtraction2(opts),
+ _ => 1);
}
}
}
diff --git a/Mapperator.ConsoleApp/Verbs/Build.cs b/Mapperator.ConsoleApp/Verbs/Build.cs
index 2f86fad..e2be7c0 100644
--- a/Mapperator.ConsoleApp/Verbs/Build.cs
+++ b/Mapperator.ConsoleApp/Verbs/Build.cs
@@ -23,7 +23,7 @@ public static int DoBuildGraph(BuildOptions opts) {
if (opts.OutputStructName is null) throw new ArgumentNullException(nameof(opts));
if (opts.DataPath is null) throw new ArgumentNullException(nameof(opts));
- var trainData = DataSerializer.DeserializeBeatmapData(File.ReadLines(Path.ChangeExtension(opts.DataPath, ".txt")));
+ var (_, trainData) = DataSerializer.DeserializeBeatmapData(File.ReadAllLines(Path.ChangeExtension(opts.DataPath, ".txt")));
var data = new RhythmDistanceTrieStructure();
if (data is not ISerializable sData) {
diff --git a/Mapperator.ConsoleApp/Verbs/Convert.cs b/Mapperator.ConsoleApp/Verbs/Convert.cs
index 60f36ca..f333d11 100644
--- a/Mapperator.ConsoleApp/Verbs/Convert.cs
+++ b/Mapperator.ConsoleApp/Verbs/Convert.cs
@@ -49,9 +49,9 @@ public static int DoMapConvert(ConvertOptions opts) {
stopwatch.Start();
Console.WriteLine(Strings.Program_DoMapConvert_Extracting_data___);
- var trainData = DataSerializer.DeserializeBeatmapData(File.ReadLines(Path.ChangeExtension(opts.DataPath, ".txt")));
+ var (trainVersion, trainData) = DataSerializer.DeserializeBeatmapData(File.ReadAllLines(Path.ChangeExtension(opts.DataPath, ".txt")));
var map = new BeatmapEditor(Path.ChangeExtension(opts.InputBeatmapPath, ".osu")).ReadFile();
- var input = new DataExtractor().ExtractBeatmapData(map).ToArray();
+ var input = new DataExtractor(trainVersion).ExtractBeatmapData(map).ToArray();
// TODO: add options to automatically add distance spacing
// TODO: also add options for ignoring angles, nc, or slider attributes
@@ -64,7 +64,7 @@ public static int DoMapConvert(ConvertOptions opts) {
if (opts.SpacingBeatmapPath is not null) {
Console.WriteLine(Strings.Program_DoMapConvert_Converting_spacing_to_reference_beatmap___);
var spacingMap = new BeatmapEditor(Path.ChangeExtension(opts.SpacingBeatmapPath, ".osu")).ReadFile();
- var spacingMapData = new DataExtractor().ExtractBeatmapData(spacingMap).ToArray();
+ var spacingMapData = new DataExtractor(trainVersion).ExtractBeatmapData(spacingMap).ToArray();
input = TransferSpacing(spacingMapData, input);
}
diff --git a/Mapperator.ConsoleApp/Verbs/Extract.cs b/Mapperator.ConsoleApp/Verbs/Extract.cs
index eeaed17..e565af1 100644
--- a/Mapperator.ConsoleApp/Verbs/Extract.cs
+++ b/Mapperator.ConsoleApp/Verbs/Extract.cs
@@ -21,7 +21,7 @@ public static int DoDataExtraction(ExtractOptions opts) {
File.WriteAllLines(Path.ChangeExtension(opts.OutputName, ".txt"),
DataSerializer.SerializeBeatmapData(DbManager.GetFilteredAndRead(opts)
.SelectMany(b => mirrors.Select(m => extractor.ExtractBeatmapData(b, m)))
- ));
+ ).Prepend(DataSerializer.CurrentHeader));
return 0;
}
diff --git a/Mapperator.DemoApp/Mapperator.DemoApp.Game.Tests/Mapperator.DemoApp.Game.Tests.csproj b/Mapperator.DemoApp/Mapperator.DemoApp.Game.Tests/Mapperator.DemoApp.Game.Tests.csproj
index 11531c4..a5162a6 100644
--- a/Mapperator.DemoApp/Mapperator.DemoApp.Game.Tests/Mapperator.DemoApp.Game.Tests.csproj
+++ b/Mapperator.DemoApp/Mapperator.DemoApp.Game.Tests/Mapperator.DemoApp.Game.Tests.csproj
@@ -8,8 +8,8 @@
-
-
+
+
diff --git a/Mapperator.DemoApp/Mapperator.DemoApp.Game/MainScreen.cs b/Mapperator.DemoApp/Mapperator.DemoApp.Game/MainScreen.cs
index f4c23f4..96d480b 100644
--- a/Mapperator.DemoApp/Mapperator.DemoApp.Game/MainScreen.cs
+++ b/Mapperator.DemoApp/Mapperator.DemoApp.Game/MainScreen.cs
@@ -222,7 +222,7 @@ private void OnBeatmapChange(ValueChangedEvent obj)
pos.MaxValue = obj.NewValue.HitObjects.Count - length - 1;
- pattern = new DataExtractor().ExtractBeatmapData(obj.NewValue).ToArray();
+ pattern = new DataExtractor(1).ExtractBeatmapData(obj.NewValue).ToArray();
matcher = new TrieDataMatcher(dataStruct, pattern);
filter = new OnScreenFilter();
judge = new SuperJudge(pattern);
diff --git a/Mapperator.DemoApp/Mapperator.DemoApp.Game/MapDataStore.cs b/Mapperator.DemoApp/Mapperator.DemoApp.Game/MapDataStore.cs
index e9214d5..b07a09d 100644
--- a/Mapperator.DemoApp/Mapperator.DemoApp.Game/MapDataStore.cs
+++ b/Mapperator.DemoApp/Mapperator.DemoApp.Game/MapDataStore.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
@@ -36,7 +37,10 @@ public IEnumerable> Get(string name)
using Stream stream = store.GetStream(name);
if (stream is null) return null;
using StreamReader reader = new StreamReader(stream);
- return DataSerializer.DeserializeBeatmapData(iterateLines(reader).ToArray());
+ var (version, data) = DataSerializer.DeserializeBeatmapData(iterateLines(reader).ToArray());
+ if (version != 1)
+ throw new NotImplementedException($"Data version {version} is not currently supported in MapDataStore");
+ return data;
}
public Task>> GetAsync(string name, CancellationToken cancellationToken = new())
@@ -44,7 +48,10 @@ public IEnumerable> Get(string name)
using Stream stream = store.GetStream(name);
if (stream is null) return null;
using StreamReader reader = new StreamReader(stream);
- return Task.FromResult(DataSerializer.DeserializeBeatmapData(iterateLines(reader)));
+ var (version, data) = DataSerializer.DeserializeBeatmapData(iterateLines(reader));
+ if (version != 1)
+ throw new NotImplementedException($"Data version {version} is not currently supported in MapDataStore");
+ return Task.FromResult(data);
}
public Stream GetStream(string name)
diff --git a/Mapperator.DemoApp/Mapperator.DemoApp.Game/Mapperator.DemoApp.Game.csproj b/Mapperator.DemoApp/Mapperator.DemoApp.Game/Mapperator.DemoApp.Game.csproj
index e1e9db9..803dbf4 100644
--- a/Mapperator.DemoApp/Mapperator.DemoApp.Game/Mapperator.DemoApp.Game.csproj
+++ b/Mapperator.DemoApp/Mapperator.DemoApp.Game/Mapperator.DemoApp.Game.csproj
@@ -7,7 +7,7 @@
-
-
+
+
diff --git a/Mapperator.Tests/Mapperator.Tests.csproj b/Mapperator.Tests/Mapperator.Tests.csproj
index ab773cf..8096981 100644
--- a/Mapperator.Tests/Mapperator.Tests.csproj
+++ b/Mapperator.Tests/Mapperator.Tests.csproj
@@ -7,10 +7,13 @@
-
-
-
-
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/Mapperator.Tests/Matching/DataStructures/RhythmDistanceTrieStructureTests.cs b/Mapperator.Tests/Matching/DataStructures/RhythmDistanceTrieStructureTests.cs
index b839e14..93dca56 100644
--- a/Mapperator.Tests/Matching/DataStructures/RhythmDistanceTrieStructureTests.cs
+++ b/Mapperator.Tests/Matching/DataStructures/RhythmDistanceTrieStructureTests.cs
@@ -39,27 +39,27 @@ public void TestQuery() {
var result = data.Trie.RetrieveSubstrings(query).ToList();
- Assert.IsTrue(result.Count > 0);
+ Assert.That(result.Count, Is.GreaterThan(0));
foreach (var wordPosition in result) {
//var rhythmString = dataRhythmStrings[wordPosition.Value];
//Console.WriteLine(string.Join('-', Enumerable.Range(0, searchLength).Select(o => rhythmString.Span[wordPosition.CharPosition + o])));
//Console.WriteLine(string.Join('-', query.ToArray()));
- Assert.IsTrue(data.WordPositionInRange(wordPosition));
- Assert.IsTrue(data.WordPositionInRange(wordPosition, searchLength - 1));
- Assert.AreEqual(searchLength, GetMatchLength(wordPosition, query));
+ Assert.That(data.WordPositionInRange(wordPosition));
+ Assert.That(data.WordPositionInRange(wordPosition, searchLength - 1));
+ Assert.That(searchLength, Is.EqualTo(GetMatchLength(wordPosition, query)));
}
var (min, max) = RhythmDistanceTrieStructure.ToDistanceRange(query, 10);
var rangeResult = data.Trie.RetrieveSubstringsRange(min, max).ToList();
- Assert.IsTrue(rangeResult.Count > 0);
+ Assert.That(rangeResult.Count > 0);
foreach (var wordPosition in rangeResult) {
//var rhythmString = dataRhythmStrings[wordPosition.Value];
//Console.WriteLine(string.Join('-', Enumerable.Range(0, searchLength).Select(o => rhythmString.Span[wordPosition.CharPosition + o])));
//Console.WriteLine(string.Join('-', query.ToArray()));
- Assert.IsTrue(data.WordPositionInRange(wordPosition));
- Assert.IsTrue(data.WordPositionInRange(wordPosition, searchLength - 1));
- Assert.AreEqual(searchLength, GetMatchLengthRange(wordPosition, min.Span, max.Span));
+ Assert.That(data.WordPositionInRange(wordPosition));
+ Assert.That(data.WordPositionInRange(wordPosition, searchLength - 1));
+ Assert.That(searchLength, Is.EqualTo(GetMatchLengthRange(wordPosition, min.Span, max.Span)));
}
}
}
diff --git a/Mapperator.Tests/Matching/DataStructures/RhythmDistanceTrieTests.cs b/Mapperator.Tests/Matching/DataStructures/RhythmDistanceTrieTests.cs
index 8d7a983..4d96eca 100644
--- a/Mapperator.Tests/Matching/DataStructures/RhythmDistanceTrieTests.cs
+++ b/Mapperator.Tests/Matching/DataStructures/RhythmDistanceTrieTests.cs
@@ -37,13 +37,13 @@ public void TestRetrieveSubstringsDynamicLengthAndDistanceRange() {
var result = trie.RetrieveSubstringsDynamicLengthAndDistanceRange(query, new RhythmDistanceTrie.MinLengthProvider(1)).ToArray();
- Assert.AreEqual(1, result.Length);
+ Assert.That(1, Is.EqualTo(result.Length));
var (pos, length, minMult, maxMult) = result[0];
Console.WriteLine(result[0]);
- Assert.AreEqual(0, pos.Value);
- Assert.AreEqual(0, pos.CharPosition);
- Assert.AreEqual(7, length);
- Assert.IsTrue(minMult < 1 && 1 < maxMult);
+ Assert.That(0, Is.EqualTo(pos.Value));
+ Assert.That(0, Is.EqualTo(pos.CharPosition));
+ Assert.That(7, Is.EqualTo(length));
+ Assert.That(minMult < 1 && 1 < maxMult);
}
[Test]
@@ -60,45 +60,45 @@ public void TestDynamicLengthRetrieveSubstringsDynamicLengthAndDistanceRange() {
var result = trie.RetrieveSubstringsDynamicLengthAndDistanceRange(query, new RhythmDistanceTrie.MinLengthProvider(1))
.OrderBy(o => o.Item1.CharPosition).ToArray();
- Assert.AreEqual(5, result.Length);
+ Assert.That(5, Is.EqualTo(result.Length));
var (pos, length, minMult, maxMult) = result[0];
- Assert.AreEqual(1, pos.CharPosition);
- Assert.AreEqual(6, length);
- Assert.IsTrue(minMult < 1 && 1 < maxMult);
+ Assert.That(1, Is.EqualTo(pos.CharPosition));
+ Assert.That(6, Is.EqualTo(length));
+ Assert.That(minMult < 1 && 1 < maxMult);
(pos, length, minMult, maxMult) = result[1];
- Assert.AreEqual(2, pos.CharPosition);
- Assert.AreEqual(2, length);
- Assert.IsTrue(minMult < 0.6 && 0.6 < maxMult);
+ Assert.That(2, Is.EqualTo(pos.CharPosition));
+ Assert.That(2, Is.EqualTo(length));
+ Assert.That(minMult < 0.6 && 0.6 < maxMult);
(pos, length, minMult, maxMult) = result[2];
- Assert.AreEqual(3, pos.CharPosition);
- Assert.AreEqual(1, length);
- Assert.IsTrue(minMult < 0.5 && 0.5 < maxMult);
+ Assert.That(3, Is.EqualTo(pos.CharPosition));
+ Assert.That(1, Is.EqualTo(length));
+ Assert.That(minMult < 0.5 && 0.5 < maxMult);
(pos, length, minMult, maxMult) = result[3];
- Assert.AreEqual(5, pos.CharPosition);
- Assert.AreEqual(2, length);
- Assert.IsTrue(minMult < 1 && 1 < maxMult);
+ Assert.That(5, Is.EqualTo(pos.CharPosition));
+ Assert.That(2, Is.EqualTo(length));
+ Assert.That(minMult < 1 && 1 < maxMult);
(pos, length, minMult, maxMult) = result[4];
- Assert.AreEqual(6, pos.CharPosition);
- Assert.AreEqual(1, length);
- Assert.IsTrue(minMult < 1 && 1 < maxMult);
+ Assert.That(6, Is.EqualTo(pos.CharPosition));
+ Assert.That(1, Is.EqualTo(length));
+ Assert.That(minMult < 1 && 1 < maxMult);
result = trie.RetrieveSubstringsDynamicLengthAndDistanceRange(query, new RhythmDistanceTrie.MinLengthProvider(2))
.OrderBy(o => o.Item1.CharPosition).ToArray();
- Assert.AreEqual(3, result.Length);
+ Assert.That(3, Is.EqualTo(result.Length));
(pos, length, _, _) = result[0];
- Assert.AreEqual(1, pos.CharPosition);
- Assert.AreEqual(6, length);
+ Assert.That(1, Is.EqualTo(pos.CharPosition));
+ Assert.That(6, Is.EqualTo(length));
(pos, length, _, _) = result[1];
- Assert.AreEqual(2, pos.CharPosition);
- Assert.AreEqual(2, length);
+ Assert.That(2, Is.EqualTo(pos.CharPosition));
+ Assert.That(2, Is.EqualTo(length));
(pos, length, _, _) = result[2];
- Assert.AreEqual(5, pos.CharPosition);
- Assert.AreEqual(2, length);
+ Assert.That(5, Is.EqualTo(pos.CharPosition));
+ Assert.That(2, Is.EqualTo(length));
result = trie.RetrieveSubstringsDynamicLengthAndDistanceRange(query, new RhythmDistanceTrie.MinLengthProvider(3)).ToArray();
- Assert.AreEqual(1, result.Length);
+ Assert.That(1, Is.EqualTo(result.Length));
}
[Test]
@@ -115,13 +115,13 @@ public void TestDynamicDistanceRetrieveSubstringsDynamicLengthAndDistanceRange()
var result = trie.RetrieveSubstringsDynamicLengthAndDistanceRange(query, new RhythmDistanceTrie.MinLengthProvider(1)).ToArray();
- Assert.AreEqual(1, result.Length);
+ Assert.That(1, Is.EqualTo(result.Length));
var (pos, length, minMult, maxMult) = result[0];
Console.WriteLine(result[0]);
- Assert.AreEqual(0, pos.Value);
- Assert.AreEqual(0, pos.CharPosition);
- Assert.AreEqual(7, length);
- Assert.IsTrue(minMult < 0.5 && 0.5 < maxMult);
+ Assert.That(0, Is.EqualTo(pos.Value));
+ Assert.That(0, Is.EqualTo(pos.CharPosition));
+ Assert.That(7, Is.EqualTo(length));
+ Assert.That(minMult < 0.5 && 0.5 < maxMult);
}
[Test]
diff --git a/Mapperator.Tests/Matching/Matchers/TrieDataMatcherTests.cs b/Mapperator.Tests/Matching/Matchers/TrieDataMatcherTests.cs
index 9bfd5b1..c9e86ee 100644
--- a/Mapperator.Tests/Matching/Matchers/TrieDataMatcherTests.cs
+++ b/Mapperator.Tests/Matching/Matchers/TrieDataMatcherTests.cs
@@ -27,8 +27,8 @@ public void TestQuery() {
foreach (var match in result) {
Console.WriteLine(match.Sequence.Length);
Console.WriteLine(string.Join('-', RhythmDistanceTrieStructure.ToRhythmString(match.Sequence.Span).ToArray()));
- //Assert.IsTrue(WordPositionInRange(wordPosition));
- //Assert.IsTrue(WordPositionInRange(wordPosition, searchLength));
+ //Assert.That(WordPositionInRange(wordPosition));
+ //Assert.That(WordPositionInRange(wordPosition, searchLength));
//Assert.AreEqual(searchLength, GetMatchLength(wordPosition, query));
}
}
diff --git a/Mapperator.Tests/Matching/TrieTests.cs b/Mapperator.Tests/Matching/TrieTests.cs
index d4477c2..8489232 100644
--- a/Mapperator.Tests/Matching/TrieTests.cs
+++ b/Mapperator.Tests/Matching/TrieTests.cs
@@ -1,6 +1,7 @@
using NUnit.Framework;
using System;
using System.Linq;
+using NUnit.Framework.Legacy;
using TrieNet.Ukkonen;
namespace Mapperator.Tests.Matching {
diff --git a/Mapperator/DataExtractor.cs b/Mapperator/DataExtractor.cs
index cca245e..891ef90 100644
--- a/Mapperator/DataExtractor.cs
+++ b/Mapperator/DataExtractor.cs
@@ -10,11 +10,13 @@
namespace Mapperator {
public class DataExtractor {
private readonly HitObjectEncoder encoder;
+ private readonly int dataVersion;
- public DataExtractor() : this(new HitObjectEncoder()) { }
+ public DataExtractor(int dataVersion = DataSerializer.CurrentDataVersion) : this(new HitObjectEncoder(), dataVersion) { }
- public DataExtractor(HitObjectEncoder encoder) {
+ public DataExtractor(HitObjectEncoder encoder, int dataVersion) {
this.encoder = encoder;
+ this.dataVersion = dataVersion;
}
public IEnumerable ExtractBeatmapData(IBeatmap beatmap, bool mirror = false) {
@@ -43,9 +45,17 @@ public IEnumerable ExtractBeatmapData(IEnumerable hitob
var segments = 0;
var controlPoints = path.ControlPoints;
- for (var i = 0; i < controlPoints.Count; i++) {
- if (i == controlPoints.Count - 1 || controlPoints[i] == controlPoints[i + 1] && i != controlPoints.Count - 2) {
- segments++;
+ if (dataVersion >= 2 && slider.SliderType == PathType.Linear) {
+ for (var i = 0; i < controlPoints.Count - 1; i++) {
+ if (controlPoints[i] != controlPoints[i + 1]) {
+ segments++;
+ }
+ }
+ } else {
+ for (var i = 0; i < controlPoints.Count; i++) {
+ if (i == controlPoints.Count - 1 || controlPoints[i] == controlPoints[i + 1] && i != controlPoints.Count - 2) {
+ segments++;
+ }
}
}
diff --git a/Mapperator/DataExtractor2.cs b/Mapperator/DataExtractor2.cs
index 57e115b..9df1ac7 100644
--- a/Mapperator/DataExtractor2.cs
+++ b/Mapperator/DataExtractor2.cs
@@ -36,10 +36,10 @@ public IEnumerable ExtractBeatmapData(IEnumerable hito
}
var t = timing2.UninheritedTimingPoint.MpB / sliderTickRate;
- var tick_ts = new List();
+ var tickTs = new List();
while (t + 10 < slider.SpanDuration) {
var t2 = t / slider.SpanDuration;
- tick_ts.Add(t2);
+ tickTs.Add(t2);
t += timing2.UninheritedTimingPoint.MpB / sliderTickRate;
}
@@ -48,9 +48,9 @@ public IEnumerable ExtractBeatmapData(IEnumerable hito
for (int i = 0; i < slider.SpanCount; i++) {
// Do ticks
- for (int j = 0; j < tick_ts.Count; j++) {
- var k = i % 2 == 0 ? j : tick_ts.Count - j - 1;
- var t2 = tick_ts[k];
+ for (int j = 0; j < tickTs.Count; j++) {
+ var k = i % 2 == 0 ? j : tickTs.Count - j - 1;
+ var t2 = tickTs[k];
var pos = path.PositionAt(t2);
var time = (int)(slider.StartTime + i * slider.SpanDuration + (i % 2 == 0 ? t2 : 1 - t2) * slider.SpanDuration);
diff --git a/Mapperator/DataSerializer.cs b/Mapperator/DataSerializer.cs
index 8dd9dd2..9c960a2 100644
--- a/Mapperator/DataSerializer.cs
+++ b/Mapperator/DataSerializer.cs
@@ -5,7 +5,11 @@
namespace Mapperator {
public static class DataSerializer {
+ public const int CurrentDataVersion = 2;
private const string BeatmapSeparator = "/-\\_/-\\_/-\\";
+ private const string DataHeader = "Mapperator file format v";
+
+ public static string CurrentHeader => $"{DataHeader}{CurrentDataVersion}";
public static IEnumerable SerializeBeatmapData(IEnumerable> data) {
foreach (var beatmap in data) {
@@ -21,8 +25,13 @@ public static string SerializeBeatmapDataSample(MapDataPoint data) {
return data.ToString();
}
- public static IEnumerable> DeserializeBeatmapData(IEnumerable data) {
- return data.Split(BeatmapSeparator, beatmapData => beatmapData.Select(DeserializeBeatmapDataSample));
+ public static (int, IEnumerable>) DeserializeBeatmapData(IEnumerable data) {
+ // ReSharper disable twice PossibleMultipleEnumeration
+ var firstLine = data.FirstOrDefault() ?? "";
+ if (firstLine.StartsWith(DataHeader)) {
+ return (int.Parse(firstLine.Split('v').Last()), data.Skip(1).Split(BeatmapSeparator, beatmapData => beatmapData.Select(DeserializeBeatmapDataSample)));
+ }
+ return (1, data.Split(BeatmapSeparator, beatmapData => beatmapData.Select(DeserializeBeatmapDataSample)));
}
public static MapDataPoint DeserializeBeatmapDataSample(string data) {
diff --git a/Mapperator/Mapperator.csproj b/Mapperator/Mapperator.csproj
index 973110c..4bbe331 100644
--- a/Mapperator/Mapperator.csproj
+++ b/Mapperator/Mapperator.csproj
@@ -7,8 +7,8 @@
-
-
+
+