Added functions for generating GrooveStats hash for a given chart.

This commit is contained in:
Michael Votaw
2024-07-23 17:02:51 -05:00
committed by teejusb
parent 0cbc92ff0f
commit 632f456ea0
2 changed files with 154 additions and 0 deletions
+144
View File
@@ -750,6 +750,7 @@ void Steps::SetCachedRadarValues( const RadarValues v[NUM_PLAYERS] )
m_bAreCachedRadarValuesJustLoaded = true;
}
void Steps::SetCachedTechCounts( const TechCounts ts[NUM_PLAYERS] )
{
DeAutogen();
@@ -776,6 +777,134 @@ void Steps::SetPeakNps(std::vector<float> &peakNps)
m_PeakNps.assign(peakNps.begin(), peakNps.end());
}
const RString Steps::GetGrooveStatsHash() const
{
return GrooveStatsHash;
}
void Steps::CalculateGrooveStatsHash()
{
if (m_bIsCachedGrooveStatsHashJustLoaded == true)
{
m_bIsCachedGrooveStatsHashJustLoaded = false;
return;
}
this->Decompress();
RString smNoteData = this->MinimizedChartString();
TimingData * timingData = this->GetTimingData();
std::vector<TimingSegment *> segments = timingData->GetTimingSegments(SEGMENT_BPM);
std::vector<RString> bpmStrings;
for (TimingSegment *segment : segments)
{
BPMSegment *bpmSegment = ToBPM(segment);
float beat = bpmSegment->GetBeat();
float bpm = bpmSegment->GetBPM();
std::ostringstream os;
os << std::fixed << std::setprecision(3) << beat;
os << "=";
os << std::fixed << std::setprecision(3) << bpm;
bpmStrings.push_back(os.str());
}
RString bpmString = join(",", bpmStrings);
smNoteData.append(bpmString);
RString gsKey = BinaryToHex(CryptManager::GetSHA1ForString(smNoteData));
gsKey = gsKey.substr(0, 16);
GrooveStatsHash = gsKey;
}
RString Steps::MinimizedChartString()
{
// We can potentially minimize the chart to get the most compressed
// form of the actual chart data.
// NOTE(teejusb): This can be more compressed than the data actually
// generated by StepMania. This is okay because the charts would still
// be considered equivalent.
// E.g. 0000 0000
// 0000 -- minimized to -->
// 0000
// 0000
// StepMania will always generate the former since quarter notes are
// the smallest quantization.
RString smNoteData = "";
this->GetSMNoteData(smNoteData);
if( smNoteData == "")
{
return "";
}
RString minimizedNoteData = "";
std::vector<RString> measures;
Regex anyNote("[^0]");
split(smNoteData, ",", measures, true);
for (unsigned m = 0; m < measures.size(); m++)
{
Trim(measures[m]);
bool isEmpty = true;
bool allZeroes = true;
bool minimal = false;
std::vector<RString> lines;
split(measures[m], "\n", lines, true);
while (!minimal && lines.size() % 2 == 0)
{
// If every other line is all 0s, we can minimize the measure
for (unsigned i = 1; i < lines.size(); i += 2)
{
Trim(lines[i]);
if (anyNote.Compare(lines[i]) == true)
{
allZeroes = false;
break;
}
}
if (allZeroes)
{
// Iterate through lines, removing every other item.
// Note that we're removing the odd indices, so we
// call `++it;` and then erase the following line
auto it = lines.begin();
while (it != lines.end())
{
++it;
if (it != lines.end())
{
it = lines.erase(it);
}
}
}
else
{
minimal = true;
}
}
// Once the measure has been minimized, make sure all of the lines are
// actually trimmed.
// (for some reason, the chart returned by GetSMNoteData() have a lot
// of extra newlines)
for (unsigned l = 0; l < lines.size(); l++)
{
Trim(lines[l]);
}
// Then, rejoin the lines together to make a measure,
// and add it to minimizedNoteData.
minimizedNoteData += join("\n", lines);
if (m < measures.size() - 1)
{
minimizedNoteData += "\n,\n";
}
}
return minimizedNoteData;
}
RString Steps::GenerateChartKey()
{
ChartKey = this->GenerateChartKey(*m_pNoteData, this->GetTimingData());
@@ -1019,6 +1148,19 @@ public:
return 1;
}
*/
static int GetMinimizedChartString(T * p, lua_State *L)
{
lua_pushstring(L, p->MinimizedChartString());
return 1;
}
static int GetGrooveStatsHash(T *p, lua_State *L)
{
lua_pushstring(L, p->GetGrooveStatsHash());
return 1;
}
static int GetChartName(T *p, lua_State *L)
{
lua_pushstring(L, p->GetChartName());
@@ -1114,6 +1256,8 @@ public:
ADD_METHOD( GetDifficulty );
ADD_METHOD( GetFilename );
ADD_METHOD( GetHash );
ADD_METHOD( GetMinimizedChartString );
ADD_METHOD( GetGrooveStatsHash );
ADD_METHOD( GetMeter );
ADD_METHOD( HasSignificantTimingChanges );
ADD_METHOD( HasAttacks );
+10
View File
@@ -139,6 +139,13 @@ public:
/** @brief Produces a chart that's reduced to it's smallest unique representable form. */
RString MinimizedChartString();
/** @brief Generates a hash used for GrooveStats integration. */
void CalculateGrooveStatsHash();
const RString GetGrooveStatsHash() const;
/** @brief Produces a chart that's reduced to it's smallest unique representable form. */
RString MinimizedChartString();
void ChangeFilenamesForCustomSong();
void SetLoadedFromProfile( ProfileSlot slot ) { m_LoadedFromProfile = slot; }
@@ -296,6 +303,9 @@ private:
RString GrooveStatsHash;
bool m_bIsCachedGrooveStatsHashJustLoaded;
/** @brief The name of the person who created the Steps. */
RString m_sCredit;
/** @brief The name of the chart. */