def initialize_and_update(username): configuration = Configuration.objects.get(user__username = username) day_service = DayService(user=configuration.user) walking_suggestion_service = WalkingSuggestionService(configuration=configuration) date_joined = day_service.get_date_at(configuration.user.date_joined) today = day_service.get_current_date() days_to_go_back = (today - date_joined).days date_range = [today - timedelta(days=offset+1) for offset in range(days_to_go_back)] while len(date_range): initialize_date = date_range.pop() try: walking_suggestion_service.get_initialization_days(initialize_date) break except WalkingSuggestionService.UnableToInitialize: pass walking_suggestion_service.initialize(initialize_date) NightlyUpdate.objects.filter(user = configuration.user).delete() while len(date_range): update_date = date_range.pop() walking_suggestion_service.update(update_date) NightlyUpdate.objects.create( user = configuration.user, day = update_date, updated = True )
def is_forecast_in_past(self, forecast): day_service = DayService(user = self.__user) end_of_day = day_service.get_end_of_day(forecast.date) if end_of_day < timezone.now(): return True else: return False
def export_step_count_records_csv(users, filename, start_date, end_date): dates_diff = end_date - start_date dates = [ start_date + timedelta(days=offset) for offset in range(dates_diff.days) ] rows = [] for _user in users: row = [_user.username] day_service = DayService(user=_user) for _date in dates: start = day_service.get_start_of_day(_date) end = start + timedelta(days=1) if _user.date_joined < end: query = StepCount.objects.filter(user=_user, start__range=[start, end]) row.append(query.count()) else: row.append(None) rows.append(row) headers = [''] + [d.strftime('%Y-%m-%d') for d in dates] rows = [headers] + rows f = open(filename, 'w') writer = csv.writer(f) writer.writerows(rows) f.close()
def initialize(self, date=None): if not date: day_service = DayService(user=self.__user) date = day_service.get_current_date() dates = self.get_initialization_days(date) gap_dates = self.get_gap_days(dates) data = { 'date': date.strftime('%Y-%m-%d'), 'pooling': self.__configuration.pooling, 'totalStepsArray': [self.get_steps(date) for date in dates], 'preStepsMatrix': [{ 'steps': self.get_pre_steps(date) } for date in dates], 'postStepsMatrix': [{ 'steps': self.get_post_steps(date) } for date in dates], 'PriorAntiMatrix': [{ 'priorAnti': self.get_all_anti_sedentary_treatments(date) } for date in gap_dates], 'DelieverMatrix': [{ 'walking': self.get_received_messages(date) } for date in gap_dates] } self.make_request('initialize', data=data) self.__configuration.service_initialized_date = date self.__configuration.save()
def get_study_day(self, time): day_service = DayService(user=self.__user) day = day_service.get_date_at(time) initialized_day = day_service.get_date_at( self.__configuration.service_initialized_date) difference = day - initialized_day return difference.days
def localize_datetime(self, user, datetime_in_UTC): day_service = DayService(user) local_timezone = day_service.get_timezone_at(datetime_in_UTC) if isinstance(datetime_in_UTC, datetime): return datetime_in_UTC.astimezone(local_timezone) else: return datetime(datetime_in_UTC.year, datetime_in_UTC.month, datetime_in_UTC.day, tzinfo=local_timezone)
def send_notification(self, day=False, test=False): if not day: service = DayService(user=self.__user) day = service.get_current_date() morning_message, _ = self.get_or_create(day) if not self.__configuration.enabled: raise MorningMessageService.NotEnabled() serialized = MorningMessageSerializer(morning_message).data serialized['type'] = 'morning-message' if not serialized['text']: del serialized['text'] if not serialized['anchor']: del serialized['anchor'] if serialized['notification']: serialized['body'] = serialized['notification'] del serialized['notification'] push_service = PushMessageService(user=self.__user) message = push_service.send_notification( body=morning_message.notification, title='Morning check-in', data=serialized, collapse_subject='morning-message', send_message_id_only=True) morning_message.add_context(message) return message
def timezone(self): if hasattr(self, '_timezone'): return self._timezone service = DayService(user = self.user) tz = service.get_timezone_at(self.time) self._timezone = tz return self._timezone
def get_study_end_datetime(self): study_start_date = self.get_study_start_date() if study_start_date and self.study_length: end_date = self.study_start + timedelta(days=self.study_length) service = DayService(user=self.user) return service.get_end_of_day(end_date) else: return None
def localize_time(self, time): day_service = DayService(self.__user) local_timezone = day_service.get_timezone_at(time) if isinstance(time, datetime): return time.astimezone(local_timezone) else: return datetime(time.year, time.month, time.day, tzinfo=local_timezone) return time.astimezone(local_timezone)
def daily_update(username): service = ParticipantService(username=username) day_service = DayService(username=username) yesterday = day_service.get_current_date() - timedelta(days=1) service.update(yesterday) if not service.participant.study_start_date: service.participant.study_start_date = service.participant.get_study_start_date() service.participant.save() update_location_categories(username)
def daily_update(self, instance): if instance.daily_task: next_run_datetime = instance.daily_task.get_next_run_time() day_service = DayService(user = instance.user) timezone = day_service.get_timezone_at(next_run_datetime) corrected_datetime = next_run_datetime.astimezone(timezone) if next_run_datetime: return 'Next update at %s (%s)' % (corrected_datetime.strftime('%Y-%m-%d %H:%M'), timezone.zone) else: return 'No daily update'
def update_weeks(self): service = DayService(self.__user) tz = service.get_current_timezone() now = timezone.now().astimezone(tz) start_date = self.__user.date_joined.astimezone(tz) week = self.get_or_create_week(start_date) while week.end < now: next_day = week.end + timedelta(days=1) week = self.get_or_create_week(next_day)
def update_message_receipts(self, date): if not self.user: return day_service = DayService(user=self.user) messages = PushMessage.objects.filter( recipient=self.user, created__gte=day_service.get_start_of_day(date), created__lte=day_service.get_end_of_day(date)).all() for message in messages: message.update_message_receipts()
def get_study_start_date(self): if self.user and self.user.date_joined: study_start_datetime = self.user.date_joined else: study_start_datetime = self.get_fitbit_start_datetime() if study_start_datetime: day_service = DayService(user=self.user) return day_service.get_date_at(study_start_datetime) else: return None
def activity_log_updates_day(sender, instance, *args, **kwargs): activity_log = instance day_service = DayService(user=activity_log.user) local_timezone = day_service.get_timezone_at(activity_log.start) local_time = activity_log.start.astimezone(local_timezone) local_date = date(local_time.year, local_time.month, local_time.day) for day in list_and_create_day(activity_log.user, local_date): day.update_from_activities()
def __get_time_range(self, time_range): if time_range not in self.TIME_RANGES: raise RuntimeError('time range not found') else: service = DayService(user=self.user) today = service.get_current_date() start_date = today - timedelta(days=time_range.offset) return [ service.get_start_of_day(start_date), service.get_end_of_day(today) ]
def get_start_of_day(self, day=None): if day: service = DayService(user=self.user) day = service.get_date_at(day) else: day = self.current_datetime return datetime(year=day.year, month=day.month, day=day.day, hour=self.day_start_hour, minute=self.day_start_minute, tzinfo=self.timezone)
def get_datetime_on(self, date): service = DayService(user = self.user) tz = service.get_timezone_at(date) local_date = service.get_date_at(date) dt = datetime( local_date.year, local_date.month, local_date.day, self.hour, self.minute ) return tz.localize(dt)
def export_activity_logs(username, filename=None, directory=None, start=None, end=None): if not directory: directory = './' if not filename: filename = '%s.activity_logs.csv' % (username) activity_log_query = ActivityLog.objects.filter( user__username=username ) \ .order_by('start') \ .prefetch_related('type') day_service = DayService(username=username) if start: start_datetime = day_service.get_start_of_day(start) activity_log_query = activity_log_query.filter( start__gte=start_datetime) if end: end_datetime = day_service.get_end_of_day(end) activity_log_query = activity_log_query.filter(start__lte=end_datetime) rows = [] headers = [ 'Participant ID', 'Activity ID', 'Study Day', 'Date', 'Start Time', 'Timezone', 'Activity Type ID', 'Activity Type Title', 'Activity Duration', 'Activity Vigorous' ] rows.append(headers) for activity_log in activity_log_query.all(): rows.append([ username, activity_log.id, 'study day', activity_log.start.astimezone( pytz.timezone('America/Los_Angeles')).strftime('%Y-%m-%d'), activity_log.start.astimezone(pytz.timezone( 'America/Los_Angeles')).strftime('%Y-%m-%d %H:%M:%S'), 'timezone', activity_log.type.id, activity_log.type.title, activity_log.duration, activity_log.vigorous ]) _file = open(path.join(directory, filename), 'w') writer = csv.writer(_file) writer.writerows(rows) _file.close()
def get_adherence_during(self, start, end): if not self.user: return [] metrics = {} adherence_metrics = AdherenceMetric.objects.filter( user=self.user, date__range=[start, end]).all() for metric in adherence_metrics: if metric.date not in metrics: metrics[metric.date] = {} metrics[metric.date][metric.category] = metric.value messages = {} day_service = DayService(user=self.user) adherence_messages = AdherenceMessage.objects.filter( user=self.user, created__range=[ day_service.get_start_of_day(start), day_service.get_end_of_day(end) ]).all() for message in adherence_messages: message_date = day_service.get_date(message.created) if message_date not in messages: messages[message_date] = [] messages[message_date].append({ 'category': message.category, 'body': message.body }) summaries = [] _dates = [ end - timedelta(days=offset) for offset in range((end - start).days + 1) ] for _date in _dates: _metrics = {} if _date in metrics: _metrics = metrics[_date] _messages = [] if _date in messages: _messages = messages[_date] summaries.append({ 'date': _date, 'metrics': _metrics, 'messages': _messages }) return summaries
def suggestion_time_category_available_at(self, time): category = self.suggestion_time_category_at(time) day_service = DayService(user=self.__user) query = WalkingSuggestionDecision.objects.filter( user=self.__user, test=False, time__range=[ day_service.get_start_of_day(time), day_service.get_end_of_day(time) ]) tags = [decision.category for decision in query.all()] if category in tags: raise self.Unavailable('Time already taken') else: return category
def send_message(self): if not self.user.is_active: raise Configuration.ConfigurationDisabled( 'Configuration user disabled') if not self.enabled: raise Configuration.ConfigurationDisabled( 'Configuration task disabled') if self.message: raise Configuration.MessageAlreadySent( 'Will not send message twice') day_service = DayService(user=self.user) current_date = day_service.get_current_date() if current_date < self.closeout_date: raise Configuration.BeforeCloseoutDate( 'Will not send before closeout date') sms_service = SMSService(user=self.user) self.message = sms_service.send(CLOSEOUT_MESSAGE) self.save() self.disable()
def test_does_not_update_if_device_sync_not_updated(self, update): self.configuration.service_initialized_date = date.today() - timedelta(days=1) self.configuration.save() day_service = DayService(user=self.user) nightly_update( username = self.user.username, day_string = date.today().strftime('%Y-%m-%d') ) update.assert_not_called() self.assertEqual(NightlyUpdate.objects.count(), 0)
def decide(self, decision): if not self.is_initialized(): raise self.NotInitialized() pooling = False try: pooling_configuration = PoolingServiceConfiguration.objects.get( user=self.__configuration.user) pooling = pooling_configuration.use_pooling except PoolingServiceConfiguration.DoesNotExist: pass day_service = DayService(user=decision.user) date = day_service.get_date_at(decision.time) response = self.make_request( 'decision', data={ 'date': date.strftime('%Y-%m-%d'), 'studyDay': self.get_study_day(decision.time), 'decisionTime': self.categorize_suggestion_time(decision), 'availability': decision.available, 'priorAnti': self.anti_sedentary_treated_since_previous_decision(decision), 'lastActivity': self.previous_decision_was_received(decision), 'location': self.get_location_type(decision), 'pooling': pooling, 'watch': self.has_watch_app_step_count(decision) }) decision.treated = response['send'] decision.treatment_probability = response['probability'] decision.save()
def get_time_of_day_context(self): service = DayService(user = self.decision.user) local_timezone = service.get_timezone_at(self.decision.time) local_time = self.decision.time.astimezone(local_timezone) start_of_day = local_time.replace(hour=8, minute=0) morning_end = local_time.replace(hour=10, minute=30) lunch_end = local_time.replace(hour=13, minute=30) afternoon_end = local_time.replace(hour=16, minute=30) evening_end = local_time.replace(hour=18, minute=30) end_of_day = local_time.replace(hour=20, minute=0) if start_of_day < self.decision.time <= morning_end: return 'morning' if morning_end < self.decision.time <= lunch_end: return 'lunch' if lunch_end < self.decision.time <= afternoon_end: return 'midafternoon' if afternoon_end < self.decision.time <= evening_end: return 'evening' if evening_end < self.decision.time <= end_of_day: return 'postdinner'
def test_update_walking_suggestion_service(self, update): self.configuration.service_initialized_date = date.today() - timedelta(days=2) self.configuration.save() day_service = DayService(user=self.user) for _date in [date.today() - timedelta(days=offset) for offset in range(2)]: FitbitDay.objects.create( account = self.account, date = _date ) nightly_update( username = self.user.username, day_string = date.today().strftime('%Y-%m-%d') ) yesterday = date.today() - timedelta(days=1) update.assert_called_with( date = yesterday ) update.assert_called_once() nightly_update_object = NightlyUpdate.objects.get() self.assertEqual(nightly_update_object.day, yesterday) self.assertTrue(nightly_update_object.updated)
def export_firsts_csv(users, directory='./', filename='firsts_exports.csv'): headers = [[ 'HeartSteps ID', 'Enrolled Date', 'Baseline Complete Date', 'First Anti-Sedentary Decision Date', 'First Anti-Sedentary Decision Service Request Date', 'First Anti-Sedentary Real-Time Sedentary Treated Decision Date' ]] rows = [] for first in Configuration.objects.filter(user__in=users).get_firsts(): day_service = DayService(username=first['username']) enroll_date = day_service.get_date_at( first['date_joined']) if first['date_joined'] else None baseline_complete_date = day_service.get_date_at( first['baseline_complete_date'] ) if first['baseline_complete_date'] else None first_decision_date = day_service.get_date_at( first['first_decision'].time) if first['first_decision'] else None first_decision_service_request_date = day_service.get_date_at( first['first_decision_service_request'].request_time ) if first['first_decision_service_request'] else None first_real_time_sedentary_treated_decision_date = day_service.get_date_at( first['first_real_time_sedentary_treated_decision'].time ) if first['first_real_time_sedentary_treated_decision'] else None rows.append([ first['username'], enroll_date.strftime('%Y-%m-%d') if enroll_date else '', baseline_complete_date.strftime('%Y-%m-%d') if baseline_complete_date else '', first_decision_date.strftime('%Y-%m-%d') if first_decision_date else '', first_decision_service_request_date.strftime('%Y-%m-%d') if first_decision_service_request_date else '', first_real_time_sedentary_treated_decision_date.strftime( '%Y-%m-%d') if first_real_time_sedentary_treated_decision_date else '' ]) _file = open(os.path.join(directory, filename), 'w') writer = csv.writer(_file) writer.writerows(headers + rows) _file.close()
def timezone(self): service = DayService(user=self.user) return service.get_current_timezone()
def get_study_start_datetime(self): study_start_date = self.get_study_start_date() if study_start_date: day_service = DayService(user=self.user) return day_service.get_start_of_day(study_start_date) return None