33 std::unique_ptr<metaRowInfo> _last_mri;
34 std::unique_ptr<metaRowInfo> _mri;
46 _last_mri = std::make_unique<metaRowInfo>(calc);
47 _mri = std::make_unique<metaRowInfo>(calc);
51 const std::array<std::vector<int>, NUM_Skillset> pmods = { {
87 const std::array<float, NUM_Skillset> basescalers = {
88 0.F, 1.F, 1.F, 1.F, 0.93F, 1.F, 1.F, 1.F
92 virtual const std::array<std::vector<int>, NUM_Skillset>& get_pmods()
const
96 virtual const std::array<float, NUM_Skillset>& get_basescalers()
const
100 virtual void adj_diff_func(
105 const float& adj_npsbase,
107 std::array<float, NUM_Skillset>& pmod_product_cur_interval)
112 case Skill_Jumpstream: {
114 case Skill_Handstream: {
116 case Skill_JackSpeed:
118 case Skill_Chordjack:
120 case Skill_Technical:
123 pmod_product_cur_interval.at(ss) * basescalers.at(ss);
134 for (
auto& hand : both_hands) {
135 for (
auto& base : {TechBase}) {
138 std::fill(v.begin(), v.end(), 0.F);
150 full_agnostic_reset();
151 reset_row_sequencing();
153 run_agnostic_pmod_loop();
154 run_dependent_pmod_loop();
157 virtual void full_agnostic_reset() {
158 _gchordstream.full_reset();
162 _last_mri.get()->reset();
165 virtual void setup_agnostic_pmods() {
169 virtual void advance_agnostic_sequencing() {
173 virtual void set_agnostic_pmods(
const int& itv) {
174 PatternMods::set_agnostic(
175 _gchordstream._pmod, _gchordstream(_mitvi), itv, _calc);
176 PatternMods::set_agnostic(_cj._pmod, _cj(_mitvi), itv, _calc);
179 virtual void run_agnostic_pmod_loop() {
180 setup_agnostic_pmods();
182 for (
auto itv = 0; itv < _calc.
numitv; ++itv) {
183 for (
auto row = 0; row < _calc.
itv_size.at(itv); ++row) {
185 const auto& ri = _calc.
adj_ni.at(itv).at(row);
187 *_last_mri, _mitvi, ri.row_time, ri.row_count, ri.row_notes);
189 advance_agnostic_sequencing();
194 swap(_mri, _last_mri);
198 set_agnostic_pmods(itv);
201 _mitvi.handle_interval_end();
204 PatternMods::run_agnostic_smoothing_pass(_calc.
numitv, _calc);
207 PatternMods::bruh_they_the_same(_calc.
numitv, _calc);
211 virtual void reset_row_sequencing() {
215 virtual void setup_dependent_mods() {
219 virtual void set_dependent_pmods(
const int& itv) {
220 PatternMods::set_dependent(
221 hand, _gstream._pmod, _gstream(_mitvghi), itv, _calc);
222 PatternMods::set_dependent(
223 hand, _gbracketing._pmod, _gbracketing(_mitvghi), itv, _calc);
226 virtual void full_hand_reset() {
229 _gstream.full_reset();
230 _gbracketing.full_reset();
235 virtual void handle_dependent_interval_end(
const int& itv) {
236 set_dependent_pmods(itv);
238 set_sequenced_base_diffs(itv);
243 virtual void set_sequenced_base_diffs(
const int& itv)
const {
247 virtual void run_dependent_pmod_loop() {
248 setup_dependent_mods();
251 for (
const auto& ids : _calc.hand_col_masks) {
258 auto row_time = s_init;
259 auto last_row_time = s_init;
260 auto any_ms = ms_init;
262 for (
auto itv = 0; itv < _calc.
numitv; ++itv) {
263 for (
auto row = 0; row < _calc.
itv_size.at(itv); row++) {
264 const auto& ri = _calc.
adj_ni.at(itv).at(row);
265 row_time = ri.row_time;
266 row_notes = ri.row_notes;
267 any_ms = ms_from(row_time, last_row_time);
268 auto masked_notes = row_notes & ids;
270 auto non_empty_cols = find_non_empty_cols(masked_notes);
271 if (non_empty_cols.empty()) {
275 for (
auto& c : non_empty_cols) {
276 lazy_jacks(c, row_time);
280 _mitvghi.handle_row(masked_notes, ids);
285 lazy_jacks.get_lowest_jack_ms(hand, _calc)) *
286 basescalers[Skill_JackSpeed] };
287 if (std::isnan(thing.second)) {
290 _calc.
jack_diff.at(hand).push_back(thing);
292 last_row_time = row_time;
294 handle_dependent_interval_end(itv);
296 PatternMods::run_dependent_smoothing_pass(_calc.
numitv, _calc);
302#if !defined(STANDALONE_CALC) && !defined(PHPCALC)
304 virtual const std::string get_calc_param_xml()
const {
305 return "Save/CalcParams_generic.xml";
308 virtual void load_calc_params_internal(
const XNode& params)
const {
309 load_params_for_mod(¶ms, _gstream._params, _gstream.name);
310 load_params_for_mod(¶ms, _gchordstream._params, _gchordstream.name);
311 load_params_for_mod(¶ms, _gbracketing._params, _gbracketing.name);
312 load_params_for_mod(¶ms, _cj._params, _cj.name);
315 virtual XNode* make_param_node_internal(
XNode* calcparams)
const
317 calcparams->AppendChild(
318 make_mod_param_node(_gstream._params, _gstream.name));
319 calcparams->AppendChild(
320 make_mod_param_node(_gchordstream._params, _gchordstream.name));
321 calcparams->AppendChild(
322 make_mod_param_node(_gbracketing._params, _gbracketing.name));
323 calcparams->AppendChild(make_mod_param_node(_cj._params, _cj.name));
330 const auto fn = get_calc_param_xml();
334 thread_local XNode params;
336 thread_local bool paramsLoaded =
false;
340 if (paramsLoaded && !bForce)
344 if (pFile ==
nullptr || bForce || !pFile->IsOpen()) {
348 if (!pFile->Open(fn, RageFile::READ))
353 if (params.ChildrenEmpty() || bForce) {
354 if (!XmlFileUtil::LoadFromFileShowErrors(params, *pFile)) {
362 params.GetAttrValue(
"vers", vers);
363 if (vers.empty() || stoi(vers) != GetCalcVersion()) {
368 load_calc_params_internal(params);
374 const auto fn = get_calc_param_xml();
375 const std::unique_ptr<XNode> xml(make_param_node());
379 if (!f.Open(fn, RageFile::WRITE)) {
382 XmlFileUtil::SaveToFile(xml.get(), f,
"",
false);
386 static auto make_mod_param_node(
387 const std::vector<std::pair<std::string, float*>>& param_map,
388 const std::string& name) ->
XNode*
390 auto* pmod =
new XNode(name);
391 for (
const auto& p : param_map) {
392 pmod->AppendChild(p.first, std::to_string(*p.second));
398 static void load_params_for_mod(
400 const std::vector<std::pair<std::string, float*>>& param_map,
401 const std::string& name)
404 const auto* pmod = node->GetChild(name);
405 if (pmod ==
nullptr) {
408 for (
const auto& p : param_map) {
409 const auto* ch = pmod->GetChild(p.first);
414 ch->GetTextValue(boat);
419 XNode* make_param_node()
const {
420 auto* calcparams =
new XNode(
"CalcParams");
421 calcparams->AppendAttr(
"vers", GetCalcVersion());
422 return make_param_node_internal(calcparams);