pumpkin_solver/statistics/statistic_logging.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
//! Responsible for behaviour related to logging statistics with a specific pre-fix and closing
//! lines.
use std::fmt::Display;
use std::sync::OnceLock;
use convert_case::Case;
use convert_case::Casing;
/// The options for statistic logging containing the statistic prefix, the (optional) line which is
/// printed after the statistics, and the (optional) casing of the statistics.
#[derive(Debug)]
pub struct StatisticOptions<'a> {
// What is printed before a statistic is printed, the statistics will be printed in the
// form `{PREFIX} {VALUE}={NAME}`
statistic_prefix: &'a str,
// A closing line which is printed after all of the statistics have been printed
after_statistics: Option<&'a str>,
// The casing of the name of the statistic
statistics_casing: Option<Case>,
}
static STATISTIC_OPTIONS: OnceLock<StatisticOptions> = OnceLock::new();
/// Configures the logging of the statistics.
///
/// It specifies the (optional) prefix and a closing line (postfix) which
/// can be printed after all of the statistics have been logged. Statistics will only be printed
/// if `log_statistics` is true.
pub fn configure_statistic_logging(
prefix: &'static str,
after: Option<&'static str>,
casing: Option<Case>,
) {
let _ = STATISTIC_OPTIONS.get_or_init(|| StatisticOptions {
statistic_prefix: prefix,
after_statistics: after,
statistics_casing: casing,
});
}
/// Logs the provided statistic with name `name` and value `value`. At the moment it will log in
/// the format `STATISTIC_PREFIX NAME=VALUE`.
pub fn log_statistic(name: impl Display, value: impl Display) {
if let Some(statistic_options) = STATISTIC_OPTIONS.get() {
let name = if let Some(casing) = &statistic_options.statistics_casing {
name.to_string().to_case(*casing)
} else {
name.to_string()
};
println!("{} {name}={value}", statistic_options.statistic_prefix)
}
}
/// Logs the postfix of the statistics (if it has been set).
///
/// Certain formats (e.g. the [MiniZinc](https://www.minizinc.org/doc-2.7.6/en/fzn-spec.html#statistics-output)
/// output format) require that a block of statistics is followed by a closing line; this
/// function outputs this closing line **if** it is configued.
pub fn log_statistic_postfix() {
if let Some(statistic_options) = STATISTIC_OPTIONS.get() {
if let Some(post_fix) = statistic_options.after_statistics {
println!("{post_fix}")
}
}
}
/// Returns whether or not statistics should be logged by determining whether the
/// [`StatisticOptions`] have been configured.
pub fn should_log_statistics() -> bool {
STATISTIC_OPTIONS.get().is_some()
}