11//! Defines the `ModelParameters` struct, which represents the contents of `model.toml`.
2+ use crate :: ISSUES_URL ;
23use crate :: asset:: check_capacity_valid_for_asset;
34use crate :: input:: {
45 deserialise_proportion_nonzero, input_err_msg, is_sorted_and_unique, read_toml,
@@ -9,9 +10,23 @@ use log::warn;
910use serde:: Deserialize ;
1011use serde_string_enum:: DeserializeLabeledStringEnum ;
1112use std:: path:: Path ;
13+ use std:: sync:: OnceLock ;
1214
1315const MODEL_PARAMETERS_FILE_NAME : & str = "model.toml" ;
1416
17+ /// The name of the option used to gate other, broken options.
18+ pub const ALLOW_BROKEN_OPTION_NAME : & str = "please_give_me_broken_results" ;
19+
20+ /// Whether broken options have been enabled by an option in the model config file
21+ static BROKEN_OPTIONS_ALLOWED : OnceLock < bool > = OnceLock :: new ( ) ;
22+
23+ /// Whether broken model options have been enabled in the config file or not
24+ pub fn broken_model_options_allowed ( ) -> bool {
25+ * BROKEN_OPTIONS_ALLOWED
26+ . get ( )
27+ . expect ( "Broken options flag not set" )
28+ }
29+
1530macro_rules! define_unit_param_default {
1631 ( $name: ident, $type: ty, $value: expr) => {
1732 fn $name( ) -> $type {
@@ -42,6 +57,9 @@ define_param_default!(default_max_ironing_out_iterations, u32, 10);
4257pub struct ModelParameters {
4358 /// Milestone years
4459 pub milestone_years : Vec < u32 > ,
60+ /// Allow known-broken options to be enabled.
61+ #[ serde( default , rename = "please_give_me_broken_results" ) ] // Can't use constant here :-(
62+ pub allow_broken_options : bool ,
4563 /// The (small) value of capacity given to candidate assets.
4664 ///
4765 /// Don't change unless you know what you're doing.
@@ -134,6 +152,11 @@ impl ModelParameters {
134152 let file_path = model_dir. as_ref ( ) . join ( MODEL_PARAMETERS_FILE_NAME ) ;
135153 let model_params: ModelParameters = read_toml ( & file_path) ?;
136154
155+ // Set flag signalling whether broken model options are allowed or not
156+ BROKEN_OPTIONS_ALLOWED
157+ . set ( model_params. allow_broken_options )
158+ . unwrap ( ) ; // Will only fail if there is a race condition, which shouldn't happen
159+
137160 model_params
138161 . validate ( )
139162 . with_context ( || input_err_msg ( file_path) ) ?;
@@ -143,15 +166,30 @@ impl ModelParameters {
143166
144167 /// Validate parameters after reading in file
145168 fn validate ( & self ) -> Result < ( ) > {
169+ if self . allow_broken_options {
170+ warn ! (
171+ "!!! You've enabled the {ALLOW_BROKEN_OPTION_NAME} option. !!!\n \
172+ I see you like to live dangerously 😈. This option should ONLY be used by \
173+ developers as it can cause peculiar behaviour that breaks things. NEVER enable it \
174+ for results you actually care about or want to publish. You have been warned!"
175+ ) ;
176+ }
177+
146178 // milestone_years
147179 check_milestone_years ( & self . milestone_years ) ?;
148180
149181 // pricing_strategy
150182 if self . pricing_strategy == PricingStrategy :: ScarcityAdjusted {
183+ ensure ! (
184+ self . allow_broken_options,
185+ "The pricing strategy is set to 'scarcity_adjusted', which is known to be broken. \
186+ If you are sure that you want to enable it anyway, you need to set the \
187+ {ALLOW_BROKEN_OPTION_NAME} option to true."
188+ ) ;
189+
151190 warn ! (
152191 "The pricing strategy is set to 'scarcity_adjusted'. Commodity prices may be \
153- incorrect if assets have more than one output commodity. See: {}/issues/677",
154- env!( "CARGO_PKG_REPOSITORY" )
192+ incorrect if assets have more than one output commodity. See: {ISSUES_URL}/677"
155193 ) ;
156194 }
157195
0 commit comments