Skip to content

Commit 26537b5

Browse files
committed
reimplement msbase for chordjacks, fixed old msbase bug | 478
severe nerfs to chordjacks with this change, it is completely untuned so downscaling from ms base means everything is like 20-30 but downscaled. will need a proper look over
1 parent ca2ae1d commit 26537b5

File tree

7 files changed

+218
-6
lines changed

7 files changed

+218
-6
lines changed

src/Etterna/MinaCalc/MinaCalc.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,12 @@ Calc::Chisel(const float player_skill,
679679
}
680680
} else if (ss == Skill_JackSpeed) {
681681
// no pattern mods atm
682+
} else if (ss == Skill_Chordjack) {
683+
for (auto i = 0; i < numitv; ++i) {
684+
debugTotalPatternMod.at(hand).at(ss).at(i) =
685+
base_adj_diff.at(hand).at(ss).at(i) /
686+
init_base_diff_vals.at(hand)[MSBase].at(i);
687+
}
682688
} else {
683689
// everything else uses nps base
684690
for (auto i = 0; i < numitv; ++i) {
@@ -880,6 +886,11 @@ Calc::InitAdjDiff(Calc& calc, const int& hand)
880886
case Skill_JackSpeed:
881887
break;
882888
case Skill_Chordjack:
889+
*adj_diff =
890+
calc.init_base_diff_vals.at(hand).at(MSBase).at(i) *
891+
basescalers.at(Skill_Chordjack) *
892+
pmod_product_cur_interval[Skill_Chordjack];
893+
// we leave stam_base alone here, still based on nps
883894
break;
884895
case Skill_Technical:
885896
*adj_diff =
@@ -993,7 +1004,7 @@ MinaSDCalcDebug(
9931004
}
9941005
}
9951006

996-
int mina_calc_version = 477;
1007+
int mina_calc_version = 478;
9971008
auto
9981009
GetCalcVersion() -> int
9991010
{

src/Etterna/MinaCalc/PatternModHelpers.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,75 @@ cv(const std::vector<float>& input) -> float
6262
return fastsqrt(sd / static_cast<float>(input.size())) / average;
6363
}
6464

65+
// cv of a vector truncated to a set number of values, or if below, filled with
66+
// dummy values to reach the desired num_vals
67+
inline auto
68+
cv_trunc_fill(const std::vector<float>& input,
69+
const int& num_vals,
70+
const float& ms_dummy) -> float
71+
{
72+
int input_sz = static_cast<int>(input.size());
73+
float sd = 0.F;
74+
float average = 0.F;
75+
if (input_sz >= num_vals) {
76+
for (int i = 0; i < std::min(input_sz, num_vals); ++i) {
77+
average += input[i];
78+
}
79+
average /= static_cast<float>(num_vals);
80+
81+
for (int i = 0; i < std::min(input_sz, num_vals); ++i) {
82+
sd += (input[i] - average) * (input[i] - average);
83+
}
84+
85+
return fastsqrt(sd / static_cast<float>(num_vals)) / average;
86+
}
87+
88+
for (int i = 0; i < std::min(input_sz, num_vals); ++i) {
89+
average += input[i];
90+
}
91+
92+
// fill with dummies if input is below desired number of values
93+
for (int i = 0; i < num_vals - input_sz; ++i) {
94+
average += ms_dummy;
95+
}
96+
average /= static_cast<float>(num_vals);
97+
98+
for (int i = 0; i < std::min(input_sz, num_vals); ++i) {
99+
sd += (input[i] - average) * (input[i] - average);
100+
}
101+
102+
for (int i = 0; i < num_vals - input_sz; ++i) {
103+
sd += (ms_dummy - average) * (ms_dummy - average);
104+
}
105+
106+
return fastsqrt(sd / static_cast<float>(num_vals)) / average;
107+
}
108+
109+
inline auto
110+
sum_trunc_fill(const std::vector<float>& input,
111+
const int& num_vals,
112+
const float& ms_dummy) -> float
113+
{
114+
int input_sz = static_cast<int>(input.size());
115+
float sum = 0.F;
116+
// use up to num_vals
117+
for (int i = 0; i < std::min(input_sz, num_vals); ++i) {
118+
sum += input[i];
119+
}
120+
121+
// got enough
122+
if (input_sz >= num_vals) {
123+
return sum;
124+
}
125+
126+
// fill with dummies if input is below desired number of values
127+
for (int i = 0; i < num_vals - static_cast<int>(input_sz); ++i) {
128+
sum += ms_dummy;
129+
}
130+
131+
return sum;
132+
}
133+
65134
inline auto
66135
div_high_by_low(float a, float b) -> float
67136
{

src/Etterna/MinaCalc/SequencedBaseDiffCalc.h

Lines changed: 132 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,151 @@
1212
constexpr float min_threshold = 0.65F;
1313
static const float downscale_logbase = std::log(6.2F);
1414

15+
constexpr float scaler_for_ms_base = 1.175F;
16+
// i do not know a proper name for these
17+
constexpr float ms_base_finger_weighter_2 = 9.F;
18+
constexpr float ms_base_finger_weighter = 5.5F;
19+
20+
static auto
21+
CalcMSEstimate(std::vector<float>& input, const int& burp) -> float
22+
{
23+
// how many ms values we use from here, if there are fewer than this
24+
// number we'll mock up some values to water down intervals with a
25+
// single extremely fast minijack, if there are more, we will truncate
26+
unsigned int num_used = burp;
27+
28+
if (input.empty()) {
29+
return 0.F;
30+
}
31+
32+
// avoiding this for now because of smoothing
33+
// single ms value, dunno if we want to do this? technically the tail
34+
// end of an insanely hard burst that gets lopped off at the last note
35+
// is still hard? if (input.size() < 2) return 1.f;
36+
37+
// sort before truncating/filling
38+
std::sort(input.begin(), input.end());
39+
40+
// truncate if we have more values than what we care to sample, we're
41+
// looking for a good estimate of the hardest part of this interval
42+
// if above 1 and below used_ms_vals, fill up the stuff with dummies
43+
// my god i was literally an idiot for doing what i was doing before
44+
static const float ms_dummy = 360.F;
45+
46+
// mostly try to push down stuff like jumpjacks, not necessarily to push
47+
// up "complex" stuff (this will push up intervals with few fast ms
48+
// values kinda hard but it shouldn't matter as their base ms diff
49+
// should be extremely low
50+
float cv_yo = cv_trunc_fill(input, burp, ms_dummy) + 0.5F;
51+
cv_yo = std::clamp(cv_yo, 0.5F, 1.25F);
52+
53+
// basically doing a jank average, bigger m = lower difficulty
54+
float m = sum_trunc_fill(input, burp, ms_dummy);
55+
56+
// add 1 to num_used because some meme about sampling
57+
// same thing as jack stuff, convert to bpm and then nps
58+
float bpm_est = ms_to_bpm(m / (num_used + 1));
59+
float nps_est = bpm_est / 15.F;
60+
float fdiff = nps_est * cv_yo;
61+
return fdiff;
62+
}
63+
1564
struct nps
1665
{
17-
/// determine NPSBase, itv_points for this hand
66+
/// determine NPSBase, itv_points, CJBase for this hand
1867
static void actual_cancer(Calc& calc, const int& hand)
1968
{
20-
for (auto itv = 0; itv < calc.numitv; ++itv) {
69+
// finger row times
70+
auto last_left_row_time = s_init;
71+
auto last_right_row_time = s_init;
72+
73+
auto scaly_ms_estimate = [](std::vector<float>& input,
74+
const float& scaler) {
75+
float o = CalcMSEstimate(input, 3);
76+
if (input.size() > 3) {
77+
o = std::max(o, CalcMSEstimate(input, 4) * scaler);
78+
}
79+
if (input.size() > 4) {
80+
o = std::max(o, CalcMSEstimate(input, 5) * scaler * scaler);
81+
}
82+
return o;
83+
};
2184

85+
for (auto itv = 0; itv < calc.numitv; ++itv) {
2286
auto notes = 0;
2387

88+
// times between rows for this interval for each finger
89+
std::vector<float> left_finger_ms{};
90+
std::vector<float> right_finger_ms{};
91+
2492
for (auto row = 0; row < calc.itv_size.at(itv); ++row) {
2593
const auto& cur = calc.adj_ni.at(itv).at(row);
2694
notes += cur.hand_counts.at(hand);
95+
96+
const auto& crt = cur.row_time;
97+
switch (determine_col_type(cur.row_notes, hand_col_ids[hand])) {
98+
case col_left:
99+
if (last_left_row_time != s_init) {
100+
const auto left_ms =
101+
ms_from(crt, last_left_row_time);
102+
left_finger_ms.push_back(left_ms);
103+
}
104+
last_left_row_time = crt;
105+
break;
106+
case col_right:
107+
if (last_right_row_time != s_init) {
108+
const auto right_ms =
109+
ms_from(crt, last_right_row_time);
110+
right_finger_ms.push_back(right_ms);
111+
}
112+
last_right_row_time = crt;
113+
break;
114+
case col_ohjump:
115+
if (last_right_row_time != s_init) {
116+
const auto right_ms =
117+
ms_from(crt, last_right_row_time);
118+
right_finger_ms.push_back(right_ms);
119+
}
120+
if (last_left_row_time != s_init) {
121+
const auto left_ms =
122+
ms_from(crt, last_left_row_time);
123+
left_finger_ms.push_back(left_ms);
124+
}
125+
last_left_row_time = crt;
126+
last_right_row_time = crt;
127+
break;
128+
case col_empty:
129+
case col_init:
130+
default:
131+
// none
132+
break;
133+
}
27134
}
28135

29136
// nps for this interval
30-
calc.init_base_diff_vals.at(hand).at(NPSBase).at(itv) =
31-
static_cast<float>(notes) * finalscaler * 1.6F;
137+
const auto nps = static_cast<float>(notes) * finalscaler * 1.6F;
138+
calc.init_base_diff_vals.at(hand).at(NPSBase).at(itv) = nps;
139+
140+
// ms base for this interval
141+
const auto left =
142+
scaly_ms_estimate(left_finger_ms, scaler_for_ms_base);
143+
const auto right =
144+
scaly_ms_estimate(right_finger_ms, scaler_for_ms_base);
145+
float msdiff = 0.F;
146+
if (left > right) {
147+
msdiff = weighted_average(left,
148+
right,
149+
ms_base_finger_weighter,
150+
ms_base_finger_weighter_2);
151+
} else {
152+
msdiff = weighted_average(right,
153+
left,
154+
ms_base_finger_weighter,
155+
ms_base_finger_weighter_2);
156+
}
157+
const auto msbase = finalscaler * msdiff;
158+
calc.init_base_diff_vals.at(hand).at(MSBase).at(itv) = msbase;
159+
/////
32160

33161
// set points for this interval
34162
calc.itv_points.at(hand).at(itv) = notes * 2;

src/Etterna/MinaCalc/Ulbu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,8 @@ struct TheGreatBazoinkazoinkInTheSky
396396
// maybe we _don't_ want this smoothed before the tech pass? and so
397397
// it could be constructed parallel? NEEDS TEST
398398
Smooth(_calc.init_base_diff_vals.at(hand).at(NPSBase), 0.F, _calc.numitv);
399+
MSSmooth(
400+
_calc.init_base_diff_vals.at(hand).at(MSBase), 0.F, _calc.numitv);
399401

400402
for (auto itv = 0; itv < _calc.numitv; ++itv) {
401403
auto jack_counter = 0;

src/Etterna/MinaCalc/UlbuAcolytes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* patterns have lower enps than streams, streams default to 1 and chordstreams
1111
* start lower, stam is a special case and may use normalizers again */
1212
static const std::array<float, NUM_Skillset> basescalers = {
13-
0.F, 0.93F, 0.885F, 0.84F, 0.93F, 1.02F, .89F, 0.9F
13+
0.F, 0.93F, 0.885F, 0.84F, 0.93F, 1.02F, .95F, 0.9F
1414
};
1515

1616
static const std::string calc_params_xml = "Save/calc params.xml";

src/Etterna/Models/Misc/GameConstantsAndTypes.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ XToString(CalcPatternMod);
260260
LuaXType(CalcPatternMod);
261261

262262
static const char* CalcDiffValueNames[] = { "NPSBase",
263+
"MSBase",
263264
// "JackBase",
264265
// "CJBase",
265266
"TechBase",

src/Etterna/Models/NoteData/NoteDataStructures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ enum CalcPatternMod
8080
enum CalcDiffValue
8181
{
8282
NPSBase,
83+
MSBase,
8384
// JackBase,
8485
// CJBase,
8586
TechBase,

0 commit comments

Comments
 (0)