class ShipBell(threading.Thread): SECONDS_PER_MINUTE = 60 MINUTES_PER_HALF_HOUR = 30 MAX_DOUBLE_STRIKES = 4 def run(self): while True: current_time = time.localtime() minutes = current_time.tm_min hours = current_time.tm_hour # Strike bell at every half or full hour. if (minutes % ShipBell.MINUTES_PER_HALF_HOUR) == 0: double_strikes, single_strikes = self.compute_strikes(hours, minutes) self.strike_bell(double_strikes, single_strikes) time.sleep(self.compute_sleep_time(minutes)) def compute_strikes(self, hours, minutes): # Single strike only on half hour. single_strikes = 1 if minutes == ShipBell.MINUTES_PER_HALF_HOUR else 0 double_strikes = hours % ShipBell.MAX_DOUBLE_STRIKES # Correction for four double-strikes at 00:00, 04:00, 08:00 ... if double_strikes == 0: double_strikes = ShipBell.MAX_DOUBLE_STRIKES return (double_strikes, single_strikes) def compute_sleep_time(self, minutes): # Remaining minutes till half or full hour. delta_minutes = ShipBell.MINUTES_PER_HALF_HOUR - minutes % ShipBell.MINUTES_PER_HALF_HOUR # If enough time is left, sleep through half of it. if delta_minutes >= 2: return delta_minutes / 2.0 * ShipBell.SECONDS_PER_MINUTE # During the last minute, check every second. return 1.0 def strike_bell(self, double_strikes, single_strikes): # Just a simulation -- print to screen instead of playing sounds. print(time.asctime() + ": " + "PING-PING " * double_strikes + "PING" * single_strikes)