Skip to content

Commit

Permalink
Add another map to PlayerAI to facilitate Combo/Life graph calculation
Browse files Browse the repository at this point in the history
keys are elapsed times at all rows
values are the same vectors of data put into the normal maps
also threw in a useless function in case i need it in the future
  • Loading branch information
poco0317 committed Oct 26, 2019
1 parent cda4854 commit c3904ce
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 2 deletions.
77 changes: 75 additions & 2 deletions src/Etterna/Models/Misc/PlayerAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ map<int, vector<TapReplayResult>> PlayerAI::m_ReplayTapMap;
map<int, vector<HoldReplayResult>> PlayerAI::m_ReplayHoldMap;
map<int, vector<TapReplayResult>> PlayerAI::m_ReplayExactTapMap;
map<int, ReplaySnapshot> PlayerAI::m_ReplaySnapshotMap;
map<float, vector<TapReplayResult>> PlayerAI::m_ReplayTapMapByElapsedTime;
map<float, vector<HoldReplayResult>> PlayerAI::m_ReplayHoldMapByElapsedTime;
float PlayerAI::replayRate = 1.f;
RString PlayerAI::replayModifiers = "";
RString PlayerAI::oldModifiers = "";
Expand Down Expand Up @@ -64,6 +66,13 @@ PlayerAI::GetTapNoteScoreForReplay(const PlayerState* pPlayerState,
return TNS_None;
}

float
PlayerAI::FindMissWindowBegin()
{
// when this becomes useful, this will be finished
return 0.18f;
}

void
PlayerAI::ResetScoreData()
{
Expand Down Expand Up @@ -176,13 +185,14 @@ PlayerAI::SetUpExactTapMap(TimingData* timing)
{
pReplayTiming = timing;

m_ReplayExactTapMap.clear();
m_ReplayTapMapByElapsedTime.clear();

// Don't continue if the replay doesn't have column data.
// We can't be accurate without it.
if (pScoreData->GetReplayType() != 2)
return;

m_ReplayExactTapMap.clear();

// For every row in the replay data...
for (auto& row : m_ReplayTapMap) {
// Get the current time and go over all taps on this row...
Expand All @@ -203,6 +213,69 @@ PlayerAI::SetUpExactTapMap(TimingData* timing)
vector<TapReplayResult> trrVector = { trr };
m_ReplayExactTapMap[tapRow] = trrVector;
}

// Also put it into the elapsed time map :)
if (m_ReplayTapMapByElapsedTime.count(tapTime) != 0) {
m_ReplayTapMapByElapsedTime[tapTime].push_back(trr);
} else {
vector<TapReplayResult> trrVector = { trr };
m_ReplayTapMapByElapsedTime[tapTime] = trrVector;
}
}
}

// Sneak in the HoldMapByElapsedTime construction for consistency
// Go over all of the elements, you know the deal.
// We can avoid getting offset rows here since drops don't do that
for (auto& row : m_ReplayHoldMap) {
float dropTime = timing->WhereUAtBro(row.first);
for (HoldReplayResult& hrr : row.second) {
if (m_ReplayHoldMapByElapsedTime.count(dropTime) != 0) {
m_ReplayHoldMapByElapsedTime[dropTime].push_back(hrr);
} else {
vector<HoldReplayResult> hrrVector = { hrr };
m_ReplayHoldMapByElapsedTime[dropTime] = hrrVector;
}
}
}

// If things were in the right order by this point
// then we know SnapshotMap is filled out.
// This is how we can find misses quickly without having to keep
// track of them in some other special way.
if (!m_ReplaySnapshotMap.empty()) {
auto curSnap = m_ReplaySnapshotMap.begin();
curSnap++;
auto prevSnap = m_ReplaySnapshotMap.begin();
while (curSnap != m_ReplaySnapshotMap.end()) {
auto csn = curSnap->second;
auto psn = prevSnap->second;
int missDiff = csn.judgments[TNS_Miss] - psn.judgments[TNS_Miss];
if (missDiff > 0) {
int row = curSnap->first;
// the tap time is pushed back by the smallest normal boo
// window. the reason for this is that's about the point where
// the game should usually count something as a miss. we dont
// use this time for anything other than chronologically parsing
// replay data for combo/life stuff so this is okay (i hope)
float tapTime = timing->WhereUAtBro(row) + .18f;
for (int i = 0; i < missDiff; i++) {
// we dont really care about anything other than the offset
// because we have the estimate time at the row in the map
// and then we just need to know what judgment to assign it
TapReplayResult trr;
trr.row = row;
trr.offset = 1.f;
if (m_ReplayTapMapByElapsedTime.count(tapTime) != 0) {
m_ReplayTapMapByElapsedTime[tapTime].push_back(trr);
} else {
vector<TapReplayResult> trrVector = { trr };
m_ReplayTapMapByElapsedTime[tapTime] = trrVector;
}
}
}
curSnap++;
prevSnap++;
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/Etterna/Models/Misc/PlayerAI.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ class PlayerAI
// of the Replay at that moment
static map<int, ReplaySnapshot> m_ReplaySnapshotMap;

// For Life/Combo graph calculations
// A reformatting of the ExactTapMap with elapsed times as keys
static map<float, vector<TapReplayResult>> m_ReplayTapMapByElapsedTime;
// A reformatting of the HoldMap with elapsed times as keys
static map<float, vector<HoldReplayResult>> m_ReplayHoldMapByElapsedTime;

static RString oldModifiers;
static RString replayModifiers;
static RString oldNoteskin;
Expand All @@ -68,6 +74,8 @@ class PlayerAI
static TapNoteScore GetTapNoteScoreForReplay(
const PlayerState* pPlayerState,
float fNoteOffset);
// Locate the earliest value in Seconds that is counted as a miss
static float FindMissWindowBegin();
static bool DetermineIfHoldDropped(int noteRow, int col);
// Returns the row of the dropped hold if the given range contains a dropped
// hold on the track Returns -1 if no dropped hold is in range.
Expand Down

0 comments on commit c3904ce

Please sign in to comment.