147 lines
8.1 KiB
C#
147 lines
8.1 KiB
C#
|
|
/**
|
||
|
|
* Chart.cs
|
||
|
|
* Representation of a chart, constructed from a .mer file.
|
||
|
|
*
|
||
|
|
* by muskit
|
||
|
|
* July 1, 2022
|
||
|
|
**/
|
||
|
|
|
||
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
|
||
|
|
namespace WacK.Data.Mer
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// Structurized representation of a .mer file.
|
||
|
|
/// </summary>
|
||
|
|
public class Mer
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// HIERARCHY:
|
||
|
|
/// Key is measure.
|
||
|
|
/// Value is List of (beat/1920, Notes) tuples.
|
||
|
|
/// </summary>
|
||
|
|
public SortedList<int, List<(int, MerNote)>> notes = new SortedList<int, List<(int, MerNote)>>();
|
||
|
|
|
||
|
|
public int playableNoteCount { get; private set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Construct Chart from contents of .mer file.
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="str">Contents of a .mer file.</param>
|
||
|
|
public Mer(string str)
|
||
|
|
{
|
||
|
|
if (str == String.Empty) return;
|
||
|
|
|
||
|
|
playableNoteCount = 0;
|
||
|
|
|
||
|
|
List<string> lines = new List<string>(str.Split('\n'));
|
||
|
|
foreach (var line in lines)
|
||
|
|
{
|
||
|
|
List<string> tokens = new List<string>(line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries));
|
||
|
|
if (tokens.Count == 0) continue;
|
||
|
|
if (tokens[0][0] == '#') continue;
|
||
|
|
|
||
|
|
int currentMeasure = int.Parse(tokens[0]);
|
||
|
|
int currentBeat = int.Parse(tokens[1]);
|
||
|
|
|
||
|
|
if (!notes.ContainsKey(currentMeasure))
|
||
|
|
{
|
||
|
|
notes[currentMeasure] = new List<(int, MerNote)>();
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (tokens[2])
|
||
|
|
{
|
||
|
|
case "1": // common note types
|
||
|
|
switch(tokens[3])
|
||
|
|
{
|
||
|
|
case "1": // touch
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.Touch)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "2": // touch w/ bonus
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.Touch, bonus: true)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "20": // touch w/ bonus (+ "big effect")
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.Touch, bonus: true)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "16": // untimed
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.Untimed)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "26": // untimed w/ bonus
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.Untimed, bonus: true)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "3": // swipe in (red)
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeIn)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "21": // swipe in w/ bonus
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeIn, bonus: true)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "4": // swipe out (blue)
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeOut)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "22": // swipe out w/ bonus
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeOut, bonus: true)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "7": // swipe CCW
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeCCW)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "8": // swipe CCW w/ bonus
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeCCW, bonus: true)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "5": // swipe CW
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeCW)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "6": // swipe CW w/ bonus
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeCW, bonus: true)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "9": // hold start
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), holdIndex: int.Parse(tokens[4]), holdNext: int.Parse(tokens[8]), type: MerType.HoldStart)));
|
||
|
|
break;
|
||
|
|
case "25": // hold start (w/ bonus)
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), holdIndex: int.Parse(tokens[4]), holdNext: int.Parse(tokens[8]), type: MerType.HoldStart, bonus: true)));
|
||
|
|
++playableNoteCount;
|
||
|
|
break;
|
||
|
|
case "10": // hold middle
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), holdIndex: int.Parse(tokens[4]), holdNext: int.Parse(tokens[8]), type: MerType.HoldMid)));
|
||
|
|
break;
|
||
|
|
case "11": // hold end
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), holdIndex: int.Parse(tokens[4]), type: MerType.HoldEnd)));
|
||
|
|
break;
|
||
|
|
case "12": // BG add
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), value: tokens[8], type: MerType.BGAdd)));
|
||
|
|
break;
|
||
|
|
case "13": // BG rem
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), value: tokens[8], type: MerType.BGRem)));
|
||
|
|
break;
|
||
|
|
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case "2": // tempo
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(value: tokens[3], type: MerType.Tempo)));
|
||
|
|
break;
|
||
|
|
case "3": // beats per measure
|
||
|
|
notes[currentMeasure].Add((currentBeat, new MerNote(value: $"{tokens[3]} {tokens[4]}", type: MerType.TimeSignature)));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
foreach (var measure in notes)
|
||
|
|
{
|
||
|
|
measure.Value.Sort((x, y) => x.Item1.CompareTo(y.Item1));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|