public void Special_SimplePairWithoutParentheses() { var s = @"x:[1,1/4,3]"; var special = Special.FromString(s); var std = new Special { Header = new NoteHeader { Measure = 1, Nominator = 1, Denominator = 4, Start = 3, End = 3, Speed = 1 } }; Assert.AreEqual(std, special); }
public SourceScore ReadSourceScore(Stream stream, string fileName, ReadSourceOptions sourceOptions) { var lines = ReadLines(stream); var c = 0; var offsetTimeSpan = TimeSpan.Parse(lines[c]); ++c; var leadTimeSpan = TimeSpan.Parse(lines[c]); ++c; var trackCount = Convert.ToInt32(lines[c]); ++c; var beatsPerMeasure = Convert.ToInt32(lines[c]); ++c; // splitter ++c; var notes = new List <SourceNote>(); while (!lines[c].StartsWith("---")) { var line = lines[c]; SourceNote[] sourceNotes; if (TapPattern.IsMatch(line)) { var tap = Tap.FromString(line); var sourceNote = new SourceNote { Type = NoteType.Tap }; FillHeader(sourceNote, tap.Header); sourceNote.Size = StrToSize(tap.Body.Size); sourceNotes = new[] { sourceNote }; } else if (HoldPairPattern.IsMatch(line)) { var holds = Hold.CreateHolds(line); var sourceNote = new SourceNote { Type = NoteType.Hold }; FillHeader(sourceNote, holds[0].Header); sourceNote.Size = StrToSize(holds[0].Body.Size); var holdEnd = new SourceNote { Type = NoteType.Hold }; FillHeader(holdEnd, holds[1].Header); holdEnd.Size = sourceNote.Size; holdEnd.FlickDirection = StrToDirection(holds[1].Body.Direction); sourceNote.FollowingNotes = new[] { holdEnd }; sourceNotes = new[] { sourceNote }; } else if (FlickPattern.IsMatch(line)) { var flick = Flick.FromString(line); var sourceNote = new SourceNote { Type = NoteType.Flick }; FillHeader(sourceNote, flick.Header); sourceNote.Size = StrToSize(flick.Body.Size); sourceNote.FlickDirection = StrToDirection(flick.Body.Direction); sourceNotes = new[] { sourceNote }; } else if (SlideSeriesPattern.IsMatch(line)) { var slides = Slide.CreateSlides(line); var sourceNote = new SourceNote { Type = NoteType.Slide }; FillHeader(sourceNote, slides[0].Header); var following = new List <SourceNote>(); for (var i = 1; i < slides.Count; ++i) { var nodeInSeries = new SourceNote { Type = NoteType.Slide }; FillHeader(nodeInSeries, slides[i].Header); if (i == slides.Count - 1) { nodeInSeries.FlickDirection = StrToDirection(slides[i].Body.Direction); } following.Add(nodeInSeries); } sourceNote.FollowingNotes = following.ToArray(); sourceNotes = new[] { sourceNote }; } else if (SpecialPattern.IsMatch(line)) { var special = Special.FromString(line); var sourceNote = new SourceNote { Type = NoteType.Special }; FillHeader(sourceNote, special.Header); sourceNotes = new[] { sourceNote }; } else { throw new FormatException("Error in simple format."); } notes.AddRange(sourceNotes); // next line ++c; } // Sort the added notes. notes.Sort((n1, n2) => n1.Ticks.CompareTo(n2.Ticks)); // splitter ++c; var conductors = new List <Conductor>(); for (; c < lines.Count; ++c) { var ss = lines[c].Split(':'); var measureIndex = Convert.ToInt32(ss[0]); var bpm = Convert.ToDouble(ss[1]); var conductor = new Conductor { Measure = measureIndex - 1, Tempo = bpm, Ticks = (measureIndex - 1) * beatsPerMeasure * NoteBase.TicksPerBeat, SignatureNumerator = beatsPerMeasure, SignatureDenominator = beatsPerMeasure }; conductors.Add(conductor); } conductors.Sort((n1, n2) => n1.Ticks.CompareTo(n2.Ticks)); var score = new SourceScore(); score.Conductors = conductors.ToArray(); score.Notes = notes.ToArray(); score.TrackCount = trackCount; score.MusicOffset = offsetTimeSpan.TotalSeconds; return(score); void FillHeader(SourceNote note, NoteHeader header) { var fraction = (float)(header.Nominator - 1) / header.Denominator; note.Beat = (int)(beatsPerMeasure * fraction); note.StartX = header.Start - 1; note.EndX = header.End - 1; note.Speed = header.Speed; note.LeadTime = leadTimeSpan.TotalSeconds; note.Measure = header.Measure - 1; note.Ticks = 60 * (long)(beatsPerMeasure * ((header.Measure - 1) + fraction) * NoteBase.TicksPerBeat); note.TrackIndex = (int)note.StartX; if (note.TrackIndex < 0 || note.TrackIndex >= trackCount) { Debug.Print("Warning: Invalid track index \"{0}\", changing into range [0, {1}].", note.TrackIndex, trackCount - 1); if (note.TrackIndex < 0) { note.TrackIndex = 0; } else if (note.TrackIndex >= trackCount) { note.TrackIndex = trackCount - 1; } } } NoteSize StrToSize(string str) { if (string.IsNullOrEmpty(str)) { return(NoteSize.Small); } else { switch (str) { case "small": return(NoteSize.Small); case "large": return(NoteSize.Large); default: throw new ArgumentOutOfRangeException(nameof(str), str, null); } } } FlickDirection StrToDirection(string str) { if (string.IsNullOrEmpty(str)) { return(FlickDirection.None); } else { switch (str) { case "left": return(FlickDirection.Left); case "right": return(FlickDirection.Right); case "up": return(FlickDirection.Up); default: throw new ArgumentOutOfRangeException(nameof(str), str, null); } } } }