Added functions for generating GrooveStats hash for a given chart.
This commit is contained in:
+144
@@ -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
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user