From 5cd8069bf17d68b1b2db5f49152e7c68b7c23873 Mon Sep 17 00:00:00 2001 From: GenevensiS <66968533+G-e-n-e-v-e-n-s-i-S@users.noreply.github.com> Date: Mon, 21 Jul 2025 04:31:30 +0200 Subject: [PATCH] add global_script statistics dimension property this script is ran once at the start, and its result is stored in the 'global_value' variable, which is accessible to the regular script. --- doc/type/statistics_dimension.txt | 3 ++- src/data/statistics.cpp | 1 + src/data/statistics.hpp | 21 +++++++++++---------- src/gui/set/stats_panel.cpp | 24 +++++++++++++++++++++--- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/doc/type/statistics_dimension.txt b/doc/type/statistics_dimension.txt index 47ffa00a..61d017b9 100644 --- a/doc/type/statistics_dimension.txt +++ b/doc/type/statistics_dimension.txt @@ -16,7 +16,8 @@ Categories are also automatically generated from dimensions. | @description@ [[type:localized string]] @""@ A description of the dimension, currently not used. | @position hint@ [[type:string]] @0@ Hint for ordering dimensions. | @icon@ [[type:filename]] Filename of an icon for this dimension. -| @script@ [[type:script]] ''required'' Script that generates a value for each card in the set. +| @script@ [[type:script]] ''required'' Script that generates a value for each card in the set. Ran once for each card, then all the results are tallied. +| @global_script@ [[type:script]] ''nil'' Script that is ran once at the start. Its result is stored in the 'global_value' variable, which is accessible to the regular script. | @numeric@ [[type:boolean]] @false@ Is the value always a number? | @bin size@ [[type:double]] ''none'' For numeric dimensions: group numbers together into bins this large.
For example with @bin size: 5@, values @1@ and @3@ both get put under @"1-5"@. diff --git a/src/data/statistics.cpp b/src/data/statistics.cpp index 0de300ad..a406d8ad 100644 --- a/src/data/statistics.cpp +++ b/src/data/statistics.cpp @@ -68,6 +68,7 @@ IMPLEMENT_REFLECTION_NO_GET_MEMBER(StatsDimension) { REFLECT(position_hint); REFLECT_N("icon", icon_filename); REFLECT(script); + REFLECT(global_script); REFLECT(numeric); REFLECT(bin_size); REFLECT(show_empty); diff --git a/src/data/statistics.hpp b/src/data/statistics.hpp index 55948e5a..56050200 100644 --- a/src/data/statistics.hpp +++ b/src/data/statistics.hpp @@ -27,19 +27,20 @@ public: StatsDimension(); StatsDimension(const Field&); - const bool automatic; ///< Based on a card field? - String name; ///< Name of this dimension - LocalizedString description; ///< Description, used in status bar - int position_hint; ///< Hint for the ordering - String icon_filename; ///< Icon for lists - Bitmap icon; ///< The loaded icon (optional of course) - OptionalScript script; ///< Script that determines the value(s) - bool numeric; ///< Are the values numeric? If so, they require special sorting + const bool automatic; ///< Based on a card field? + String name; ///< Name of this dimension + LocalizedString description; ///< Description, used in status bar + int position_hint; ///< Hint for the ordering + String icon_filename; ///< Icon for lists + Bitmap icon; ///< The loaded icon (optional of course) + OptionalScript script; ///< Script that determines the value(s), ran on each card + OptionalScript global_script; ///< Script that determines the value(s), ran only once at the start + bool numeric; ///< Are the values numeric? If so, they require special sorting double bin_size; ///< Bin adjecent numbers? bool show_empty; ///< Should "" be shown? bool split_list; ///< Split values into multiple ones separated by commas - map colors; ///< Colors for the categories - vector groups; ///< Order of the items + map colors; ///< Colors for the categories + vector groups; ///< Order of the items DECLARE_REFLECTION(); }; diff --git a/src/gui/set/stats_panel.cpp b/src/gui/set/stats_panel.cpp index 5f1fd51d..c579e7c7 100644 --- a/src/gui/set/stats_panel.cpp +++ b/src/gui/set/stats_panel.cpp @@ -472,13 +472,29 @@ void StatsPanel::showCategory(const GraphType* prefer_layout) { dim->groups.empty() ? nullptr : &dim->groups ) ); + } + // find global_script values + vector global_values; + Context& global_ctx = set->getContext(); + ScriptValueP global_ctx_value = global_ctx.getVariableOpt("global_value"); + for (size_t d = 0 ; d < dims.size() ; ++d) { + auto& dim = dims[d]; + try { + ScriptValueP global_value = dim->global_script.invoke(global_ctx); + global_values.push_back(global_value); + } catch (ScriptError const& e) { + handle_error(ScriptError(e.what() + _("\n in global script for statistics dimension '") + dim->name + _("'"))); + global_values.push_back(script_nil); + } } - // find values for each card + // find script values for each card for (size_t i = 0 ; i < set->cards.size() ; ++i) { Context& ctx = set->getContext(set->cards[i]); GraphElementP e = make_intrusive(i); bool show = true; - FOR_EACH(dim, dims) { + for (size_t d = 0 ; d < dims.size() ; ++d) { + auto& dim = dims[d]; + ctx.setVariable("global_value", global_values[d]); try { String value = untag(dim->script.invoke(ctx)->toString()); e->values.push_back(value); @@ -497,7 +513,9 @@ void StatsPanel::showCategory(const GraphType* prefer_layout) { assert(e->values.size() == dims.size()); d.elements.push_back(e); } - } + } + // restore old global value if any + if (global_ctx_value) global_ctx.setVariable("global_value", global_ctx_value); // split lists size_t dim_id = 0; FOR_EACH(dim, dims) {