Coverage for pybeepop/beepop/coldstoragesimulator.py: 42%

100 statements  

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

1""" 

2ColdStorageSimulator class: 

3- Simulates cold storage conditions for a bee colony. 

4- Can be activated manually or by specifying start/end dates. 

5- When active, overrides temperature and disables foraging. 

6- Tracks active, starting, and ending phases. 

7- All logic and comments from the C++ version are preserved. 

8""" 

9 

10from datetime import datetime 

11 

12 

13class ColdStorageSimulator: 

14 DEFAULT_TEMPERATURE = (40.0 - 32.0) / 1.8 # Celsius 

15 _instance = None 

16 

17 def __init__(self): 

18 self.enabled = False 

19 self.start_date = None 

20 self.end_date = None 

21 self.on = False 

22 self.temperature = self.DEFAULT_TEMPERATURE 

23 self.start_date_str = "" 

24 self.end_date_str = "" 

25 self.is_active = False 

26 self.is_starting = False 

27 self.is_ending = False 

28 

29 @classmethod 

30 def get(cls): 

31 if cls._instance is None: 

32 cls._instance = ColdStorageSimulator() 

33 return cls._instance 

34 

35 def set_enabled(self, enabled): 

36 self.enabled = enabled 

37 

38 def is_enabled(self): 

39 return self.enabled 

40 

41 def activate(self): 

42 self.on = True 

43 

44 def deactivate(self): 

45 self.on = False 

46 

47 def is_on(self): 

48 return self.on 

49 

50 def is_automatic(self): 

51 return not self.start_date_str and not self.end_date_str 

52 

53 def get_temp(self, event): 

54 temperature = getattr(event, "temp", None) 

55 if self.is_active: 

56 temperature = self.temperature 

57 return temperature 

58 

59 def get_max_temp(self, event): 

60 temperature = getattr(event, "max_temp", None) 

61 if self.is_active: 

62 temperature = self.temperature 

63 return temperature 

64 

65 def get_min_temp(self, event): 

66 temperature = getattr(event, "min_temp", None) 

67 if self.is_active: 

68 temperature = self.temperature 

69 return temperature 

70 

71 def get_forage_inc(self, event): 

72 forage_inc = getattr(event, "forage_inc", None) 

73 if self.is_active: 

74 forage_inc = 0.0 

75 return forage_inc 

76 

77 def is_forage_day(self, event): 

78 forage_day = getattr(event, "forage_day", None) 

79 if self.is_active: 

80 forage_day = False 

81 return forage_day 

82 

83 def set_start_date(self, start_date): 

84 self.start_date = start_date 

85 self.start_date_str = start_date.strftime("%m%d") if start_date else "" 

86 

87 def set_end_date(self, end_date): 

88 self.end_date = end_date 

89 self.end_date_str = end_date.strftime("%m%d") if end_date else "" 

90 

91 def update(self, event, colony): 

92 """ 

93 Updates the state of the cold storage, call once per simulation day. 

94 Tracks starting/ending phases based on colony and event state. 

95 """ 

96 is_active = self.enabled and (self.on or self.is_cold_storage_period(event)) 

97 if not self.is_active and is_active: 

98 self.is_starting = True 

99 # Starting phase: bees placed in cold storage, brood still present 

100 if self.is_starting: 

101 starting = ( 

102 getattr(colony.queen, "teggs", 0) > 0 

103 or getattr(colony, "cap_drn", None) 

104 and getattr(colony.cap_drn, "quantity", 0) > 0 

105 or getattr(colony, "cap_wkr", None) 

106 and getattr(colony.cap_wkr, "quantity", 0) > 0 

107 ) 

108 self.is_starting = starting 

109 # Ending phase: queen starts to lay eggs again while in cold storage 

110 if is_active and not self.is_starting and getattr(colony.queen, "teggs", 0) > 0: 

111 self.is_ending = True 

112 if not is_active: 

113 self.is_starting = False 

114 self.is_ending = False 

115 self.is_active = is_active 

116 

117 def reset(self): 

118 self.enabled = False 

119 self.start_date = None 

120 self.end_date = None 

121 self.on = False 

122 self.temperature = self.DEFAULT_TEMPERATURE 

123 self.start_date_str = "" 

124 self.end_date_str = "" 

125 self.is_active = False 

126 self.is_starting = False 

127 self.is_ending = False 

128 

129 def is_active_now(self): 

130 return self.is_active 

131 

132 def is_starting_now(self): 

133 return self.is_active and self.is_starting 

134 

135 def is_ending_now(self): 

136 return self.is_active and self.is_ending 

137 

138 def is_cold_storage_period(self, event): 

139 """ 

140 Returns True if the current event is within the cold storage period. 

141 """ 

142 if not self.start_date_str or not self.end_date_str: 

143 return False 

144 current_date_str = event.time.strftime("%m%d") if hasattr(event, "time") else "" 

145 if self.start_date_str >= self.end_date_str: 

146 return ( 

147 current_date_str >= self.start_date_str 

148 or current_date_str <= self.end_date_str 

149 ) 

150 else: 

151 return self.start_date_str <= current_date_str <= self.end_date_str