class EncryptionErrorMetadata(TimestampedModel): file_name = models.CharField(max_length=256) total_lines = models.PositiveIntegerField() number_errors = models.PositiveIntegerField() error_lines = JSONTextField() error_types = JSONTextField() participant = models.ForeignKey('Participant', on_delete=models.PROTECT, null=True)
class AbstractSurvey(AbstractModel): """ AbstractSurvey contains all fields that we want to have copied into a survey backup whenever it is updated. """ AUDIO_SURVEY = 'audio_survey' TRACKING_SURVEY = 'tracking_survey' DUMMY_SURVEY = 'dummy' IMAGE_SURVEY = 'image_survey' SURVEY_TYPE_CHOICES = ((AUDIO_SURVEY, AUDIO_SURVEY), (TRACKING_SURVEY, TRACKING_SURVEY), (DUMMY_SURVEY, DUMMY_SURVEY), (IMAGE_SURVEY, IMAGE_SURVEY)) content = JSONTextField( default='[]', help_text='JSON blob containing information about the survey questions.' ) survey_type = models.CharField(max_length=16, choices=SURVEY_TYPE_CHOICES, help_text='What type of survey this is.') settings = JSONTextField( default='{}', help_text='JSON blob containing settings for the survey.') timings = JSONTextField( default=json.dumps([[], [], [], [], [], [], []]), help_text='JSON blob containing the times at which the survey is sent.' ) class Meta: abstract = True
class AbstractSurvey(AbstractModel): """ AbstractSurvey contains all fields that we want to have copied into a survey backup whenever it is updated. """ AUDIO_SURVEY = 'audio_survey' TRACKING_SURVEY = 'tracking_survey' DUMMY_SURVEY = 'dummy' IMAGE_SURVEY = 'image_survey' SURVEY_TYPE_CHOICES = ((AUDIO_SURVEY, AUDIO_SURVEY), (TRACKING_SURVEY, TRACKING_SURVEY), (DUMMY_SURVEY, DUMMY_SURVEY), (IMAGE_SURVEY, IMAGE_SURVEY)) name = models.TextField( unique=True, null=False, help_text='Name of the study; can be of any length') content = JSONTextField( default='[]', help_text='JSON blob containing information about the survey questions.' ) survey_type = models.CharField(max_length=16, choices=SURVEY_TYPE_CHOICES, help_text='What type of survey this is.') settings = JSONTextField( default='{}', help_text='JSON blob containing settings for the survey.') timings = JSONTextField( default=json.dumps([[], [], [], [], [], [], []]), help_text='JSON blob containing the times at which the survey is sent.' ) def mark_deleted(self): self.name = '{0} Deleted {1}'.format(self.name, timezone.now().isoformat()) self.deleted = True self.save() class Meta: abstract = True
class DeviceSettings(AbstractModel): """ The DeviceSettings database contains the structure that defines settings pushed to devices of users in of a study. """ # Whether various device options are turned on accelerometer = models.BooleanField(default=True) gps = models.BooleanField(default=True) calls = models.BooleanField(default=True) texts = models.BooleanField(default=True) wifi = models.BooleanField(default=True) bluetooth = models.BooleanField(default=False) power_state = models.BooleanField(default=True) use_anonymized_hashing = models.BooleanField(default=True) use_gps_fuzzing = models.BooleanField(default=False) call_clinician_button_enabled = models.BooleanField(default=True) call_research_assistant_button_enabled = models.BooleanField(default=True) # Whether iOS-specific data streams are turned on proximity = models.BooleanField(default=False) gyro = models.BooleanField(default=False) magnetometer = models.BooleanField(default=False) devicemotion = models.BooleanField(default=False) reachability = models.BooleanField(default=True) # Upload over cellular data or only over WiFi (WiFi-only is default) allow_upload_over_cellular_data = models.BooleanField(default=False) # Timer variables accelerometer_off_duration_seconds = models.PositiveIntegerField( default=10) accelerometer_on_duration_seconds = models.PositiveIntegerField(default=10) bluetooth_on_duration_seconds = models.PositiveIntegerField(default=60) bluetooth_total_duration_seconds = models.PositiveIntegerField(default=300) bluetooth_global_offset_seconds = models.PositiveIntegerField(default=0) check_for_new_surveys_frequency_seconds = models.PositiveIntegerField( default=3600 * 6) create_new_data_files_frequency_seconds = models.PositiveIntegerField( default=15 * 60) gps_off_duration_seconds = models.PositiveIntegerField(default=600) gps_on_duration_seconds = models.PositiveIntegerField(default=60) seconds_before_auto_logout = models.PositiveIntegerField(default=600) upload_data_files_frequency_seconds = models.PositiveIntegerField( default=3600) voice_recording_max_time_length_seconds = models.PositiveIntegerField( default=240) wifi_log_frequency_seconds = models.PositiveIntegerField(default=300) # iOS-specific timer variables gyro_off_duration_seconds = models.PositiveIntegerField(default=600) gyro_on_duration_seconds = models.PositiveIntegerField(default=60) magnetometer_off_duration_seconds = models.PositiveIntegerField( default=600) magnetometer_on_duration_seconds = models.PositiveIntegerField(default=60) devicemotion_off_duration_seconds = models.PositiveIntegerField( default=600) devicemotion_on_duration_seconds = models.PositiveIntegerField(default=60) # Text strings about_page_text = models.TextField(default=ABOUT_PAGE_TEXT) call_clinician_button_text = models.TextField(default='Call My Clinician') consent_form_text = models.TextField(default=CONSENT_FORM_TEXT) survey_submit_success_toast_text = models.TextField( default=SURVEY_SUBMIT_SUCCESS_TOAST_TEXT) # Consent sections consent_sections = JSONTextField(default=DEFAULT_CONSENT_SECTIONS_JSON) study = models.OneToOneField('Study', on_delete=models.PROTECT, related_name='device_settings')