Skip to content

Commit

Permalink
centralize aggregation functions and provide ssrs when sorting topssrs
Browse files Browse the repository at this point in the history
  • Loading branch information
poco0317 committed Jul 18, 2021
1 parent 75ec3f8 commit 9a37e08
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 81 deletions.
2 changes: 1 addition & 1 deletion src/Etterna/MinaCalc/MinaCalc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ Calc::CalcMain(const std::vector<NoteInfo>& NoteInfo,
/* finished all modifications to skillset values, set overall using
* sigmoidal aggregation, but only let it buff files, don't set anything
* below the highest skillset th */
auto agg = AggregateRatings(mcbloop);
auto agg = aggregate_skill(mcbloop, 0.25, 1.11, 0.0, 10.24);
auto highest = max_val(mcbloop);
mcbloop[Skill_Overall] = agg > highest ? agg : highest;

Expand Down
46 changes: 30 additions & 16 deletions src/Etterna/MinaCalc/MinaCalcHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,36 @@ downscale_low_accuracy_scores(const float f, const float sg) -> float
max_rating);
}

// kinda copied and pasted but also kinda use case specific
inline auto
AggregateRatings(const std::vector<float>& skillsets,
float rating = 0.F,
const float res = 10.24F,
const int iter = 1.F) -> float
aggregate_skill(const std::vector<float>& v,
double delta_multiplier,
float result_multiplier,
float rating = 0.0F,
float resolution = 10.24F) -> float
{
double sum;
do {
rating += res;
sum = 0.0;
for (const auto& ss : skillsets) {
sum += std::max(0.0, 2.f / erfc(0.25 * (ss - rating)) - 2);
}
} while (pow(2, rating * 0.1) < sum);
if (iter == 11)
return rating * 1.11F;
return AggregateRatings(skillsets, rating - res, res / 2.f, iter + 1);
// this algorithm is roughly a binary search
// 11 iterations is enough to satisfy
for (int i = 0; i < 11; i++) {
double sum;

// at least 1 repeat iteration of:
// accumulate a sum of the input values
// after applying a function to the values initially
// when threshold is reached, this iteration of the search concludes
do {
rating += resolution;
sum = 0.0;
for (const auto& vv : v) {
sum += std::max(
0.0, 2.F / erfc(delta_multiplier * (vv - rating)) - 2);
}
} while (pow(2, rating * 0.1) < sum);

// binary searching: move backwards and proceed forward half as quickly
rating -= resolution;
resolution /= 2.F;
}
rating += resolution * 2.F;

return rating * result_multiplier;
}
82 changes: 25 additions & 57 deletions src/Etterna/Singletons/ScoreManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <algorithm>

#include "GameManager.h"
#include "Etterna/MinaCalc/MinaCalcHelpers.h"

using std::lock_guard;
using std::mutex;
Expand Down Expand Up @@ -774,27 +775,6 @@ ScoreManager::UnInvalidateAllScores(const string& profileID)
}
}

inline auto
AggregateSkillsets(const vector<float>& skillsets,
float rating,
float res,
int iter) -> float
{
double sum;
do {
rating += res;
sum = 0.0;
for (const auto& ss : skillsets) {
sum += std::max(0.0, 2.F / erfc(0.1 * (ss - rating)) - 2);
}
} while (pow(2, rating * 0.1) < sum);
if (iter == 11) {
return rating;
}

return AggregateSkillsets(skillsets, rating - res, res / 2.F, iter + 1);
}

void
ScoreManager::CalcPlayerRating(float& prating,
float* pskillsets,
Expand All @@ -810,57 +790,42 @@ ScoreManager::CalcPlayerRating(float& prating,
continue;
}

SortTopSSRPtrs(ss, profileID);
pskillsets[ss] = AggregateSSRs(ss, 0.F, 10.24F, 1) * 1.05F;
std::vector<float> ssrs = SortTopSSRPtrs(ss, profileID, true);
pskillsets[ss] = aggregate_skill(ssrs, 0.1, 1.05, 0.0, 10.24);
CLAMP(pskillsets[ss], 0.F, 100.F);
skillz.push_back(pskillsets[ss]);
}

prating = AggregateSkillsets(skillz, 0.F, 10.24F, 1) * 1.125F;
prating = aggregate_skill(skillz, 0.1, 1.125, 0.0, 10.24);
pskillsets[Skill_Overall] = prating;
}

// perhaps we will need a generalized version again someday, but not today
// currently set to only allow dance single scores
auto
ScoreManager::AggregateSSRs(Skillset ss,
float rating,
float res,
int iter) const -> float
{
double sum;
do {
rating += res;
sum = 0.0;
for (const auto& ts : TopSSRs) {
if (ts->GetSSRCalcVersion() == GetCalcVersion() &&
ts->GetEtternaValid() &&
static_cast<int>(ts->GetChordCohesion()) == 0 &&
ts->GetTopScore() != 0 &&
SONGMAN->GetStepsByChartkey(ts->GetChartKey())->m_StepsType ==
StepsType_dance_single) {
sum += std::max(
0.0, 2.F / erfc(0.1 * (ts->GetSkillsetSSR(ss) - rating)) - 2);
}
}
} while (pow(2, rating * 0.1) < sum);
if (iter == 11) {
return rating;
}

return AggregateSSRs(ss, rating - res, res / 2.F, iter + 1);
}

void
ScoreManager::SortTopSSRPtrs(Skillset ss, const string& profileID)
std::vector<float>
ScoreManager::SortTopSSRPtrs(Skillset ss, const string& profileID, bool getSSRs)
{
std::vector<float> o;
TopSSRs.clear();
for (auto& i : pscores[profileID]) {
if (!SONGMAN->IsChartLoaded(i.first)) {
continue;
}
for (const auto& hs : i.second.GetAllPBPtrs()) {
TopSSRs.emplace_back(hs);

if (getSSRs) {
if (hs->GetSSRCalcVersion() != GetCalcVersion())
continue;
if (!hs->GetEtternaValid())
continue;
if (static_cast<int>(hs->GetChordCohesion()) == 1)
continue;
if (hs->GetTopScore() == 0)
continue;
if (SONGMAN->GetStepsByChartkey(hs->GetChartKey())
->m_StepsType != StepsType_dance_single)
continue;
o.emplace_back(hs->GetSkillsetSSR(ss));
}
}
}

Expand All @@ -869,6 +834,9 @@ ScoreManager::SortTopSSRPtrs(Skillset ss, const string& profileID)
};

sort(TopSSRs.begin(), TopSSRs.end(), ssrcomp);
if (getSSRs)
sort(o.begin(), o.end());
return o;
}

void
Expand Down
12 changes: 5 additions & 7 deletions src/Etterna/Singletons/ScoreManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,11 @@ class ScoreManager
const float minpercent = PREFSMAN->m_fMinPercentToSaveScores;

// Player Rating and SSR functions
void SortTopSSRPtrs(Skillset ss,
const std::string& profileID =
PROFILEMAN->GetProfile(PLAYER_1)->m_sProfileID);
std::vector<float> SortTopSSRPtrs(
Skillset ss,
const std::string& profileID =
PROFILEMAN->GetProfile(PLAYER_1)->m_sProfileID,
bool getSSRs = false);
void SortTopSSRPtrsForGame(
Skillset ss,
const string& profileID = PROFILEMAN->GetProfile(PLAYER_1)->m_sProfileID);
Expand All @@ -183,10 +185,6 @@ class ScoreManager
void CalcPlayerRating(float& prating,
float* pskillsets,
const std::string& profileID);
[[nodiscard]] auto AggregateSSRs(Skillset ss,
float rating,
float res,
int iter) const -> float;

auto GetTopSSRValue(unsigned int rank, int ss) -> float;

Expand Down

0 comments on commit 9a37e08

Please sign in to comment.