33use crate :: commodity:: { Commodity , CommodityID } ;
44use crate :: id:: define_id_type;
55use crate :: region:: RegionID ;
6- use crate :: time_slice:: { Season , TimeSliceID , TimeSliceInfo , TimeSliceLevel , TimeSliceSelection } ;
6+ use crate :: time_slice:: { Season , TimeSliceID , TimeSliceInfo , TimeSliceSelection } ;
77use crate :: units:: {
88 ActivityPerCapacity , Dimensionless , FlowPerActivity , MoneyPerActivity , MoneyPerCapacity ,
99 MoneyPerCapacityPerYear , MoneyPerFlow ,
@@ -243,7 +243,7 @@ impl ActivityLimits {
243243 /// Add an annual limit
244244 fn add_annual_limit ( & mut self , limit : RangeInclusive < Dimensionless > ) -> Result < ( ) > {
245245 // Get current limit for the year
246- let current_limit = self . get_limit_for_year ( & TimeSliceInfo :: default ( ) ) ;
246+ let current_limit = self . get_limit_for_year ( ) ;
247247
248248 // Ensure that the new limit overlaps with the current limit
249249 // If not, it's impossible to satisfy both limits, so we must exit with an error
@@ -266,12 +266,11 @@ impl ActivityLimits {
266266 pub fn get_limit (
267267 & self ,
268268 time_slice_selection : & TimeSliceSelection ,
269- time_slice_info : & TimeSliceInfo ,
270269 ) -> RangeInclusive < Dimensionless > {
271270 match time_slice_selection {
272271 TimeSliceSelection :: Single ( ts_id) => self . get_limit_for_time_slice ( ts_id) ,
273272 TimeSliceSelection :: Season ( season) => self . get_limit_for_season ( season) ,
274- TimeSliceSelection :: Annual => self . get_limit_for_year ( time_slice_info ) ,
273+ TimeSliceSelection :: Annual => self . get_limit_for_year ( ) ,
275274 }
276275 }
277276
@@ -325,14 +324,16 @@ impl ActivityLimits {
325324 }
326325
327326 /// Get the limit for the entire year
328- fn get_limit_for_year ( & self , time_slice_info : & TimeSliceInfo ) -> RangeInclusive < Dimensionless > {
327+ fn get_limit_for_year ( & self ) -> RangeInclusive < Dimensionless > {
329328 // Get the sum of limits for all seasons
330329 let mut total_lower = Dimensionless ( 0.0 ) ;
331330 let mut total_upper = Dimensionless ( 0.0 ) ;
332- for ts_selection in time_slice_info. iter_selections_at_level ( TimeSliceLevel :: Season ) {
333- let TimeSliceSelection :: Season ( season) = ts_selection else {
334- panic ! ( "Expected season selection" )
335- } ;
331+ let seasons = self
332+ . time_slice_limits
333+ . keys ( )
334+ . map ( |ts_id| ts_id. season . clone ( ) )
335+ . unique ( ) ;
336+ for season in seasons {
336337 let season_limit = self . get_limit_for_season ( & season) ;
337338 total_lower += * season_limit. start ( ) ;
338339 total_upper += * season_limit. end ( ) ;
@@ -990,7 +991,7 @@ mod tests {
990991 }
991992
992993 // Annual limit should be 0..1
993- let annual_limit = limits. get_limit ( & TimeSliceSelection :: Annual , & time_slice_info2 ) ;
994+ let annual_limit = limits. get_limit ( & TimeSliceSelection :: Annual ) ;
994995 assert_approx_eq ! ( Dimensionless , * annual_limit. start( ) , Dimensionless ( 0.0 ) ) ;
995996 assert_approx_eq ! ( Dimensionless , * annual_limit. end( ) , Dimensionless ( 1.0 ) ) ;
996997 }
@@ -1014,11 +1015,35 @@ mod tests {
10141015 }
10151016
10161017 // The seasonal limit should reflect the given bound
1017- let season_limit = result. get_limit (
1018- & TimeSliceSelection :: Season ( "winter" . into ( ) ) ,
1019- & time_slice_info2,
1018+ let season_limit = result. get_limit ( & TimeSliceSelection :: Season ( "winter" . into ( ) ) ) ;
1019+ assert_eq ! ( * season_limit. end( ) , Dimensionless ( 0.01 ) ) ;
1020+ }
1021+
1022+ #[ rstest]
1023+ fn test_new_from_limits_with_annual_limit_applied ( time_slice_info2 : TimeSliceInfo ) {
1024+ let mut limits = HashMap :: new ( ) ;
1025+
1026+ // Set an annual upper limit that is stricter than the sum of timeslices
1027+ limits. insert (
1028+ TimeSliceSelection :: Annual ,
1029+ Dimensionless ( 0.0 ) ..=Dimensionless ( 0.01 ) ,
10201030 ) ;
1031+
1032+ let result = ActivityLimits :: new_from_limits ( & limits, & time_slice_info2) . unwrap ( ) ;
1033+
1034+ // Each timeslice upper bound should be capped by the annual upper bound (0.01)
1035+ for ( ts_id, _ts_len) in time_slice_info2. iter ( ) {
1036+ let ts_limit = result. get_limit_for_time_slice ( & ts_id) ;
1037+ assert_eq ! ( * ts_limit. end( ) , Dimensionless ( 0.01 ) ) ;
1038+ }
1039+
1040+ // The seasonal limit should be capped by the annual upper bound (0.01)
1041+ let season_limit = result. get_limit ( & TimeSliceSelection :: Season ( "winter" . into ( ) ) ) ;
10211042 assert_eq ! ( * season_limit. end( ) , Dimensionless ( 0.01 ) ) ;
1043+
1044+ // The annual limit should reflect the given bound
1045+ let annual_limit = result. get_limit ( & TimeSliceSelection :: Annual ) ;
1046+ assert_eq ! ( * annual_limit. end( ) , Dimensionless ( 0.01 ) ) ;
10221047 }
10231048
10241049 #[ rstest]
0 commit comments