class Condition(db.Model): """ An experimental condition, i.e. the variable conditions of a trial Attributes ---------- id : int Primary key test_id : int, optional Foreign key to the Test the condition belongs to group_id : int, optional data : str JSON-enconded string of formatted condition variables """ id = db.Column(db.Integer, primary_key=True) test_id = db.Column(db.Integer, db.ForeignKey('test.id')) group_id = db.Column(db.Integer, db.ForeignKey('group.id')) data = db.Column(db.Text) trials = db.relationship('Trial', backref='condition', lazy='dynamic') def __init__(self, data, test_id=None, group_id=None): self.data = data self.test_id = test_id self.group_id = group_id def __repr__(self): return "<Condition id=%r, test_id=%r, group_id=%r, data=%r>" % ( self.id, self.test_id, self.group_id, self.data)
class Group(db.Model): """ A group of conditions. For MUSHRA this is typically the same as the condition itself, but for pairwise these is the group of conditions that containing stimuli make up the set of stimuli of a MUSHRA trial. Note that the evaluation software currently only supports one group per evaluation--therefore when configuring the test, make sure that an integer multiple of `CONDITIONS_PER_EVALUATION` comprises the number of conditions per group. Attributes ---------- id : int Primary key data : str JSON-encoded string of formatted group condition variables (like shared references and stimuli) """ id = db.Column(db.Integer, primary_key=True) data = db.Column(db.Text) conditions = db.relationship('Condition', backref='group', lazy='dynamic') def __repr__(self): return "<Group id=%r,data=%r>" % (self.id, self.data)
class Test(db.Model): """ An experimental test. Many conditions may share these properties. Attributes ---------- id: int Primary key data: str JSON-encoded string of formatted test variables """ id = db.Column(db.Integer, primary_key=True) data = db.Column(db.Text) conditions = db.relationship('Condition', backref='test', lazy='dynamic') def __init__(self, data): self.data = data def __repr__(self): return "<Test id=%r, data=%r>" % (self.id, self.data)
class Participant(db.Model): """ A participant in an experiment Attributes ---------- id : int Primary key ip_address : str The IP address of the participant crowd_worker_id : str The crowdsourcing site ID, e.g. Amazon MTurk's workerId platform : str The platform the participant came from, e.g. ANONYMOUS, M_TURK, etc. passed_hearing_test : bool The user has passed the hearing test gave_consent : bool Participant agreed to the consent form. hearing_test_attempts : int The number of hearing_test_attempts hearing_test_last_attempt : DateTime The DateTime of the last hearing test attempt (pass or fail) pre_test_survey : str Pre-test survey data in JSON post_test_survey : str Post-test survey data in JSON hearing_response_estimation : str Hearing response estimation data in JSON """ id = db.Column(db.Integer, primary_key=True) ip_address = db.Column(db.String(45)) crowd_worker_id = db.Column(db.String(256), unique=True) platform = db.Column(db.String(128)) passed_hearing_test = db.Column(db.Boolean, default=False) gave_consent = db.Column(db.Boolean, default=False) hearing_test_attempts = db.Column(db.Integer, default=0) hearing_test_last_attempt = db.Column(db.DateTime, default=datetime.datetime(1, 1, 1)) pre_test_survey = db.Column(db.Text, default=None) post_test_survey = db.Column(db.Text, default=None) hearing_response_estimation = db.Column(db.Text, default=None) trials = db.relationship('Trial', backref='participant', lazy='dynamic') def __init__(self, platform, crowd_worker_id=None, ip_address=None): self.platform = platform if crowd_worker_id is None or crowd_worker_id == 'ANONYMOUS': self.crowd_worker_id = uuid.uuid4().hex else: self.crowd_worker_id = crowd_worker_id if app.config['IP_COLLECTION_ENABLED']: self.ip_address = ip_address def __repr__(self): return "<Participant id=%r, platform=%r, crowd_worker_id=%r>" % ( self.id, self.platform, self.crowd_worker_id) def has_passed_hearing_test_recently(self): """ Check to see if participant has passed the hearing test recently (as defined in settings.py) Returns ------- bool """ if (datetime.datetime.now() - self.hearing_test_last_attempt) \ >= datetime.timedelta(hours=app.config['HEARING_TEST_EXPIRATION_HOURS']): self.passed_hearing_test = False self.hearing_test_attempts = 0 # regardless of HEARING_TEST_REJECTION_ENABLED or not, if they haven't taken the test recently, have # them take it again return self.passed_hearing_test else: # regardless if they have taken the test recently, if HEARING_TEST_REJECTION_ENABLED is False, let them # through return self.passed_hearing_test or not app.config[ 'HEARING_TEST_REJECTION_ENABLED'] def set_passed_hearing_test(self, passed_hearing_test): """ Mark them as having passed the hearing test Parameters ---------- passed_hearing_test : bool Returns ------- None """ self.hearing_test_last_attempt = datetime.datetime.now() self.hearing_test_attempts += 1 self.passed_hearing_test = passed_hearing_test