Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions includes/RhythmGameUtilities/Parsers.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
#pragma once

#include <algorithm>
#include <map>
#include <regex>
#include <string>
#include <vector>

#include "Enums/Difficulty.h"
#include "Enums/NamedSection.h"
#include "Enums/TypeCode.h"

#include "Structs/Note.h"

#include "Utilities.hpp"

#ifdef _WIN32
Expand Down Expand Up @@ -91,4 +99,96 @@ std::vector<ChartSection> ParseSectionsFromChart(const char *contents)
return sections;
}

std::map<int, int>
ParseTimeSignaturesFromChartSection(std::vector<ChartSection> sections)
{
auto timeSignatures = std::map<int, int>();

for (auto &section : sections)
{
if (section.name == ToString(NamedSection::SyncTrack))
{
for (auto &line : section.lines)
{
if (line.second.front() ==
ToString(TypeCode::TimeSignatureMarker))
{
timeSignatures.insert(
{std::stoi(line.first), std::stoi(line.second.at(1))});
}
}
}
}

return timeSignatures;
}

std::map<int, int> ParseBpmFromChartSection(std::vector<ChartSection> sections)
{
auto bpm = std::map<int, int>();

for (auto &section : sections)
{
if (section.name == ToString(NamedSection::SyncTrack))
{
for (auto &line : section.lines)
{
if (line.second.front() == ToString(TypeCode::BPM_Marker))
{
bpm.insert(
{std::stoi(line.first), std::stoi(line.second.at(1))});
}
}
}
}

return bpm;
}

std::vector<Note> ParseNotesFromChartSection(std::vector<ChartSection> sections,
Difficulty difficulty)
{
auto notes = std::vector<Note>();

for (auto &section : sections)
{
if (section.name == ToString(difficulty) + "Single")
{
for (auto &line : section.lines)
{
if (line.second.front() == ToString(TypeCode::NoteMarker))
{
notes.push_back({std::stoi(line.first),
std::stoi(line.second.at(1)),
std::stoi(line.second.at(2))});
}
}
}
}

return notes;
}

std::map<int, std::string>
ParseLyricsFromChartSection(std::vector<ChartSection> sections)
{
auto lyrics = std::map<int, std::string>();

for (auto &section : sections)
{
if (section.name == ToString(NamedSection::Events))
{
for (auto &line : section.lines)
{
if (line.second.back().rfind("lyric", 0) == 0)
{
lyrics.insert({std::stoi(line.first), line.second.at(1)});
}
}
}
}

return lyrics;
}

} // namespace RhythmGameUtilities
67 changes: 67 additions & 0 deletions includes/RhythmGameUtilities/Structs/Song.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#pragma once

#include <map>
#include <string>

#include "RhythmGameUtilities/Enums/Difficulty.h"
#include "RhythmGameUtilities/Structs/BeatBar.h"
#include "RhythmGameUtilities/Structs/Note.h"

namespace RhythmGameUtilities
{

struct Song
{

// Title of the song.
std::string Name;

// Artist(s) or band(s) behind the song.
std::string Artist;

// Title of the album the song is featured in.
std::string Album;

// Genre of the song.
std::string Genre;

// Year of the song’s release.<br />Typically preceded by a comma and space,
// for example `, 2002`, to make importing into GHTCP quicker.
std::string Year;

// Community member who charted the song.
std::string Charter;

// (Required) Number of positional ticks between each 1/4th note in the
// chart.
int Resolution;

// Estimated difficulty of the song.
int Difficulty;

// Start time of the audio, in seconds.<br />A higher value makes the audio
// start sooner.
double Offset;

// Time of the song, in seconds, where the song preview should start.
double PreviewStart;

// Time of the song, in seconds, where the song preview should end.
double PreviewEnd;

// The main audio stream.<br />When other audio stems are present, this is
// background audio not in the other tracks and/or instruments not charted.
std::string MusicStream;

std::map<int, std::string> Lyrics;

std::map<DifficultyType, std::vector<Note>> Difficulties;

std::map<int, int> BPM;

std::map<int, std::vector<int>> TimeSignatures;

std::vector<BeatBar> BeatBars;
};

} // namespace RhythmGameUtilities
49 changes: 49 additions & 0 deletions tests/RhythmGameUtilities/Parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,59 @@ void testParseValuesFromChartSections()
std::cout << ".";
}

void testParseTimeSignaturesFromChartSection()
{
auto sections = ParseSectionsFromChart(contents);

auto lines = ParseTimeSignaturesFromChartSection(sections);

assert(lines.size() == 4);

std::cout << ".";
}

void testParseBpmFromChartSection()
{
auto sections = ParseSectionsFromChart(contents);

auto lines = ParseBpmFromChartSection(sections);

assert(lines.size() == 7);

std::cout << ".";
}

void testParseNotesFromChartSection()
{
auto sections = ParseSectionsFromChart(contents);

auto lines = ParseNotesFromChartSection(sections, Difficulty::Expert);

assert(lines.size() == 8);

std::cout << ".";
}

void testParseLyricsFromChartSection()
{
auto sections = ParseSectionsFromChart(contents);

auto lines = ParseLyricsFromChartSection(sections);

assert(lines.size() == 12);

std::cout << ".";
}

int main()
{
testParseSectionsFromChart();
testParseValuesFromChartSections();

testParseTimeSignaturesFromChartSection();
testParseBpmFromChartSection();
testParseNotesFromChartSection();
testParseLyricsFromChartSection();

return 0;
}