Coverage for pybeepop/beepop/daterangevalues.py: 50%

50 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-30 13:34 +0000

1""" 

2Date Range Values Module for BeePop+ Environmental Simulation 

3 

4This module provides temporal parameter management for the BeePop+ bee colony simulation. 

5It manages parameter values that vary over specific date ranges, supporting 

6time-dependent environmental conditions and management interventions. 

7 

8The DateRangeValues system enables dynamic parameter changes throughout simulations, 

9allowing for seasonal variations, treatment schedules, and environmental events 

10that affect colony development over time. 

11 

12Classes: 

13 DateRangeItem: Represents a single parameter value valid within a date range 

14 DateRangeValues: Collection manager for time-dependent parameter values 

15""" 

16 

17from datetime import datetime 

18from typing import List, Optional 

19 

20 

21class DateRangeItem: 

22 """ 

23 Single time-dependent parameter value for BeePop+ environmental simulation. 

24 

25 Represents a parameter value that is valid within a specific date range, 

26 enabling temporal variations in environmental conditions, management 

27 practices, or other simulation parameters that change over time. 

28 

29 Attributes: 

30 start_time (datetime): Beginning of the valid date range (inclusive) 

31 end_time (datetime): End of the valid date range (inclusive) 

32 value (float): Parameter value to apply during this date range 

33 """ 

34 

35 def __init__(self, start_time: datetime, end_time: datetime, value: float): 

36 self.start_time = start_time 

37 self.end_time = end_time 

38 self.value = value 

39 

40 

41class DateRangeValues: 

42 """ 

43 Temporal parameter collection manager for BeePop+ environmental simulation. 

44 

45 Manages collections of time-dependent parameter values that can change over 

46 specific date ranges during colony simulation. Supports environmental 

47 variations, treatment schedules, seasonal effects, and other temporal 

48 changes that affect bee colony development. 

49 

50 The system implements exact C++ compatibility for date range calculations. 

51 

52 Attributes: 

53 items (List[DateRangeItem]): Collection of date-ranged parameter values 

54 enabled (bool): Whether this parameter collection is active in simulation 

55 file_format_version (int): Deprecated 

56 """ 

57 

58 def __init__(self): 

59 self.items: List[DateRangeItem] = [] 

60 self.enabled: bool = True 

61 self.file_format_version: int = 1 

62 

63 def add_item(self, start_time: datetime, end_time: datetime, value: float): 

64 self.items.append(DateRangeItem(start_time, end_time, value)) 

65 

66 def get_item(self, index: int) -> Optional[DateRangeItem]: 

67 if 0 <= index < len(self.items): 

68 return self.items[index] 

69 return None 

70 

71 def get_active_item(self, the_date: datetime) -> Optional[DateRangeItem]: 

72 """ 

73 Find the first item where the_date falls within the date range. 

74 Implements the exact C++ logic from daterangevalues.cpp lines 67-98. 

75 """ 

76 for item in self.items: 

77 # Normalize dates to midnight (matching C++ VAR_DATEVALUEONLY behavior) 

78 start_normalized = item.start_time.replace( 

79 hour=0, minute=0, second=0, microsecond=0 

80 ) 

81 end_normalized = item.end_time.replace( 

82 hour=0, minute=0, second=0, microsecond=0 

83 ) 

84 date_normalized = the_date.replace( 

85 hour=0, minute=0, second=0, microsecond=0 

86 ) 

87 

88 # Calculate time spans exactly like C++ COleDateTimeSpan 

89 time_since_start = date_normalized - start_normalized 

90 time_till_end = end_normalized - date_normalized 

91 

92 # Convert to days (matching C++ GetDays() method) 

93 time_since_start_days = time_since_start.days 

94 time_till_end_days = time_till_end.days 

95 

96 # Apply exact C++ logic: (TimeSinceStart.GetDays() > 0) && (TimeTillEnd.GetDays() > 0) 

97 if time_since_start_days > 0 and time_till_end_days > 0: 

98 return item 

99 

100 return None 

101 

102 def get_active_value(self, the_date: datetime) -> Optional[float]: 

103 item = self.get_active_item(the_date) 

104 return item.value if item else None 

105 

106 def delete_item(self, index: int): 

107 if 0 <= index < len(self.items): 

108 del self.items[index] 

109 

110 def get_count(self) -> int: 

111 return len(self.items) 

112 

113 def clear_all(self): 

114 self.items.clear() 

115 

116 def is_enabled(self) -> bool: 

117 return self.enabled 

118 

119 def set_enabled(self, enable_val: bool): 

120 self.enabled = enable_val 

121 

122 def set_file_format_version(self, version: int): 

123 self.file_format_version = version 

124 

125 def copy(self, destination: "DateRangeValues"): 

126 destination.items = [ 

127 DateRangeItem(item.start_time, item.end_time, item.value) 

128 for item in self.items 

129 ] 

130 destination.enabled = self.enabled 

131 destination.file_format_version = self.file_format_version