Etterna 0.75.1
Loading...
Searching...
No Matches
UlbuBase.h
1#pragma once
2
3#include "Agnostic/HA_PatternMods/GenericChordstream.h"
4#include "Agnostic/HA_PatternMods/CJ.h"
5#include "Agnostic/HA_PatternMods/HandBalance.h"
6
7#include "Dependent/MetaIntervalGenericHandInfo.h"
8#include "Dependent/HD_PatternMods/GenericBracketing.h"
9#include "Dependent/HD_PatternMods/GenericStream.h"
10
11#include "SequencedBaseDiffCalc.h"
12
16{
17 public:
18 Calc& _calc;
19 bool dbg = false;
20 int hand = 0;
21
22 // keeps track of occurrences of basic row based sequencing, mostly for
23 // skilset detection, contains itvinfo as well, the very basic metrics used
24 // for detection
25 metaItvInfo _mitvi;
26
27 // the generic hand stats
29
30 // meta row info keeps track of basic pattern sequencing as we scan down
31 // the notedata rows, we will recyle two pointers (we want each row to be
32 // able to "look back" at the meta info generated at the last row so the mhi
33 // generation requires the last generated mhi object as an arg
34 std::unique_ptr<metaRowInfo> _last_mri;
35 std::unique_ptr<metaRowInfo> _mri;
36
37 GStreamMod _gstream;
38 GChordStreamMod _gchordstream;
39 GBracketingMod _gbracketing;
40 CJMod _cj;
42
43 oversimplified_jacks lazy_jacks;
44
45 explicit Bazoinkazoink(Calc& calc)
46 : _calc(calc)
47 {
48 _last_mri = std::make_unique<metaRowInfo>(calc);
49 _mri = std::make_unique<metaRowInfo>(calc);
50 }
51
52 private:
53 const std::array<std::vector<int>, NUM_Skillset> pmods = { {
54 // Overall
55 {},
56
57 // Stream
58 {
59 GStream,
60 },
61
62 // Jumpstream
63 {
64 GChordStream,
65 },
66
67 // Handstream
68 {
69 GBracketing,
70 },
71
72 // Stamina
73 {},
74
75 // Jackspeed
76 {},
77
78 // Chordjack
79 {
80 CJ,
81 },
82
83 // Technical
84 {
85
86 },
87 }};
88
89 const std::array<float, NUM_Skillset> basescalers = {
90 0.F, 1.F, 1.F, 1.F, 0.93F, 1.F, 1.F, 1.F
91 };
92
93 public:
94 virtual const std::array<std::vector<int>, NUM_Skillset>& get_pmods() const
95 {
96 return pmods;
97 }
98 virtual const std::array<float, NUM_Skillset>& get_basescalers() const
99 {
100 return basescalers;
101 }
102 virtual void adj_diff_func(
103 const size_t& itv,
104 const int& hand,
105 float*& adj_diff,
106 float*& stam_base,
107 const float& adj_npsbase,
108 const int& ss,
109 std::array<float, NUM_Skillset>& pmod_product_cur_interval)
110 {
111 switch (ss) {
112 case Skill_Stream:
113 break;
114 case Skill_Jumpstream: {
115 } break;
116 case Skill_Handstream: {
117 } break;
118 case Skill_JackSpeed:
119 break;
120 case Skill_Chordjack:
121 break;
122 case Skill_Technical:
123 *adj_diff =
124 _calc.init_base_diff_vals.at(hand).at(TechBase).at(itv) *
125 pmod_product_cur_interval.at(ss) * basescalers.at(ss);
126 break;
127 default:
128 break;
129 }
130 }
131
132 virtual void apply_keymode_multipliers(
133 std::vector<float>& cur_iteration_skillset_vals) const
134 {
135
136 }
137
141 {
142 for (auto& hand : both_hands) {
143 for (auto& base : {TechBase}) {
144 // to be thorough: JackBase, CJBase, NPSBase, RMABase
145 auto& v = _calc.init_base_diff_vals.at(hand)[base];
146 std::fill(v.begin(), v.end(), 0.F);
147 }
148 _calc.jack_diff.at(hand).clear();
149 }
150 }
151
153 void operator()() {
155 hand = 0;
156
157 full_hand_reset();
158 full_agnostic_reset();
159 reset_row_sequencing();
160
161 run_agnostic_pmod_loop();
162 run_dependent_pmod_loop();
163 }
164
165 virtual void full_agnostic_reset() {
166 _gchordstream.full_reset();
167 _cj.full_reset();
168 _hb.full_reset();
169
170 _mri.get()->reset();
171 _last_mri.get()->reset();
172 }
173
174 virtual void setup_agnostic_pmods() {
175
176 }
177
178 virtual void advance_agnostic_sequencing()
179 {
180 _hb.advance_sequencing(_mri->notes, _calc);
181 }
182
183 virtual void set_agnostic_pmods(const int& itv) {
184 PatternMods::set_agnostic(
185 _gchordstream._pmod, _gchordstream(_mitvi), itv, _calc);
186 PatternMods::set_agnostic(_cj._pmod, _cj(_mitvi), itv, _calc);
187 PatternMods::set_agnostic(_hb._pmod, _hb(), itv, _calc);
188 }
189
190 virtual void run_agnostic_pmod_loop() {
191 setup_agnostic_pmods();
192
193 for (auto itv = 0; itv < _calc.numitv; ++itv) {
194 for (auto row = 0; row < _calc.itv_size.at(itv); ++row) {
195
196 const auto& ri = _calc.adj_ni.at(itv).at(row);
197 (*_mri)(
198 *_last_mri, _mitvi, ri.row_time, ri.row_count, ri.row_notes);
199
200 advance_agnostic_sequencing();
201
202 // we only need to look back 1 metanoterow object, so we can
203 // swap the one we just built into last and recycle the two
204 // pointers instead of keeping track of everything
205 swap(_mri, _last_mri);
206 }
207
208 // run pattern mod generation for hand agnostic mods
209 set_agnostic_pmods(itv);
210
211 // reset any accumulated interval info and set cur index number
212 _mitvi.handle_interval_end();
213 }
214
215 PatternMods::run_agnostic_smoothing_pass(_calc.numitv, _calc);
216
217 // copy left -> right for agnostic mods
218 PatternMods::bruh_they_the_same(_calc.numitv, _calc);
219 }
220
221
222 virtual void reset_row_sequencing() {
223 _mitvi.reset();
224 }
225
226 virtual void setup_dependent_mods() {
227
228 }
229
230 virtual void set_dependent_pmods(const int& itv) {
231 PatternMods::set_dependent(
232 hand, _gstream._pmod, _gstream(_mitvghi), itv, _calc);
233 PatternMods::set_dependent(
234 hand, _gbracketing._pmod, _gbracketing(_mitvghi), itv, _calc);
235 }
236
237 virtual void full_hand_reset() {
238 lazy_jacks.init(_calc.keycount);
239
240 _gstream.full_reset();
241 _gbracketing.full_reset();
242
243 _mitvghi.zero();
244 }
245
246 virtual void handle_dependent_interval_end(const int& itv) {
247 set_dependent_pmods(itv);
248
249 set_sequenced_base_diffs(itv);
250
251 _mitvghi.interval_end();
252 }
253
254 virtual void set_sequenced_base_diffs(const int& itv) const {
255
256 }
257
258 virtual void run_dependent_pmod_loop() {
259 setup_dependent_mods();
260
261 hand = 0;
262 for (const auto& ids : _calc.hand_col_masks) {
263 full_hand_reset();
264 nps::actual_cancer(_calc, hand);
265 Smooth(_calc.init_base_diff_vals.at(hand).at(NPSBase),
266 0.F,
267 _calc.numitv);
268
269 auto row_time = s_init;
270 auto last_row_time = s_init;
271 auto any_ms = ms_init;
272 auto row_notes = 0u;
273 for (auto itv = 0; itv < _calc.numitv; ++itv) {
274 for (auto row = 0; row < _calc.itv_size.at(itv); row++) {
275 const auto& ri = _calc.adj_ni.at(itv).at(row);
276 row_time = ri.row_time;
277 row_notes = ri.row_notes;
278 any_ms = ms_from(row_time, last_row_time);
279 auto masked_notes = row_notes & ids;
280
281 auto non_empty_cols = find_non_empty_cols(masked_notes);
282 if (non_empty_cols.empty()) {
283 continue;
284 }
285
286 for (auto& c : non_empty_cols) {
287 lazy_jacks(c, row_time);
288 }
289
290 // update counts
291 _mitvghi.handle_row(masked_notes, ids);
292
293 auto thing =
294 std::pair{ row_time,
295 ms_to_scaled_nps(
296 lazy_jacks.get_lowest_jack_ms(hand, _calc)) *
297 basescalers[Skill_JackSpeed] };
298 if (std::isnan(thing.second)) {
299 thing.second = 0.F;
300 }
301 _calc.jack_diff.at(hand).push_back(thing);
302
303 last_row_time = row_time;
304 }
305 handle_dependent_interval_end(itv);
306 }
307 PatternMods::run_dependent_smoothing_pass(_calc.numitv, _calc);
308
309 hand++;
310 }
311 }
312
313#if !defined(STANDALONE_CALC) && !defined(PHPCALC)
314
315 virtual const std::string get_calc_param_xml() const {
316 return "Save/CalcParams_generic.xml";
317 }
318
319 virtual void load_calc_params_internal(const XNode& params) const {
320 load_params_for_mod(&params, _gstream._params, _gstream.name);
321 load_params_for_mod(&params, _gchordstream._params, _gchordstream.name);
322 load_params_for_mod(&params, _gbracketing._params, _gbracketing.name);
323 load_params_for_mod(&params, _cj._params, _cj.name);
324 load_params_for_mod(&params, _hb._params, _hb.name);
325 }
326
327 virtual XNode* make_param_node_internal(XNode* calcparams) const
328 {
329 calcparams->AppendChild(
330 make_mod_param_node(_gstream._params, _gstream.name));
331 calcparams->AppendChild(
332 make_mod_param_node(_gchordstream._params, _gchordstream.name));
333 calcparams->AppendChild(
334 make_mod_param_node(_gbracketing._params, _gbracketing.name));
335 calcparams->AppendChild(make_mod_param_node(_cj._params, _cj.name));
336 calcparams->AppendChild(make_mod_param_node(_hb._params, _hb.name));
337
338 return calcparams;
339 }
340
342 void load_calc_params_from_disk(bool bForce = false) const {
343 const auto fn = get_calc_param_xml();
344
345 // Hold calc params program-global persistent info
346 thread_local RageFile* pFile;
347 thread_local XNode params;
348 // Only ever try to load params once per thread unless forcing
349 thread_local bool paramsLoaded = false;
350
351 // Don't keep loading params if nothing to load/no reason to
352 // Allow a force to bypass
353 if (paramsLoaded && !bForce)
354 return;
355
356 // Load if missing
357 if (pFile == nullptr || bForce || !pFile->IsOpen()) {
358 delete pFile;
359 pFile = new RageFile();
360 // Failed to load
361 if (!pFile->Open(fn, RageFile::READ))
362 return;
363 }
364
365 // If it isn't loaded or we are forcing a load, load it
366 if (params.ChildrenEmpty() || bForce) {
367 if (!XmlFileUtil::LoadFromFileShowErrors(params, *pFile)) {
368 pFile->Close();
369 return;
370 }
371 }
372
373 // ignore params from older versions
374 std::string vers;
375 params.GetAttrValue("vers", vers);
376 if (vers.empty() || stoi(vers) != GetCalcVersion()) {
377 return;
378 }
379 paramsLoaded = true;
380
381 load_calc_params_internal(params);
382 pFile->Close();
383 }
384
386 void write_params_to_disk() const {
387 const auto fn = get_calc_param_xml();
388 const std::unique_ptr<XNode> xml(make_param_node());
389
390 std::string err;
391 RageFile f;
392 if (!f.Open(fn, RageFile::WRITE)) {
393 return;
394 }
395 XmlFileUtil::SaveToFile(xml.get(), f, "", false);
396 f.Close();
397 }
398
399 static auto make_mod_param_node(
400 const std::vector<std::pair<std::string, float*>>& param_map,
401 const std::string& name) -> XNode*
402 {
403 auto* pmod = new XNode(name);
404 for (const auto& p : param_map) {
405 pmod->AppendChild(p.first, std::to_string(*p.second));
406 }
407
408 return pmod;
409 }
410
411 static void load_params_for_mod(
412 const XNode* node,
413 const std::vector<std::pair<std::string, float*>>& param_map,
414 const std::string& name)
415 {
416 auto boat = 0.F;
417 const auto* pmod = node->GetChild(name);
418 if (pmod == nullptr) {
419 return;
420 }
421 for (const auto& p : param_map) {
422 const auto* ch = pmod->GetChild(p.first);
423 if (ch == nullptr) {
424 continue;
425 }
426
427 ch->GetTextValue(boat);
428 *p.second = boat;
429 }
430 }
431
432 XNode* make_param_node() const {
433 auto* calcparams = new XNode("CalcParams");
434 calcparams->AppendAttr("vers", GetCalcVersion());
435 return make_param_node_internal(calcparams);
436 }
437#endif
438};
Main driver class for the difficulty calculator as a whole.
Definition MinaCalc.h:82
std::array< std::array< std::vector< float >, NUM_CalcDiffValue >, num_hands > init_base_diff_vals
Definition MinaCalc.h:187
int numitv
Total number of intervals for the current file/rate (one per half second)
Definition MinaCalc.h:263
std::vector< std::array< RowInfo, max_rows_for_single_interval > > adj_ni
Definition MinaCalc.h:162
unsigned keycount
Assigns the keymode specific logic.
Definition MinaCalc.h:104
std::array< std::vector< std::pair< float, float > >, num_hands > jack_diff
Definition MinaCalc.h:239
std::vector< int > itv_size
Number of rows in each interval.
Definition MinaCalc.h:165
High-level file access.
Definition RageFile.h:16
Definition XmlFile.h:95
Definition UlbuBase.h:16
void reset_base_diffs()
Definition UlbuBase.h:140
void write_params_to_disk() const
save default xml parameters
Definition UlbuBase.h:386
void load_calc_params_from_disk(bool bForce=false) const
load custom xml parameters
Definition UlbuBase.h:342
void operator()()
main driver for operations
Definition UlbuBase.h:153
Definition CJ.h:7
Definition GenericBracketing.h:7
Definition GenericChordstream.h:7
Definition GenericStream.h:8
Hand-Agnostic PatternMod weighing the balance of notes across hands.
Definition HandBalance.h:6
Definition MetaIntervalGenericHandInfo.h:145
void interval_end()
handle end of interval
Definition MetaIntervalGenericHandInfo.h:160
void zero()
Definition MetaIntervalGenericHandInfo.h:173
Definition MetaIntervalInfo.h:20
static void actual_cancer(Calc &calc, const int &hand)
determine NPSBase, itv_points, CJBase for this hand
Definition SequencedBaseDiffCalc.h:68
Definition SequencedBaseDiffCalc.h:942