Skip to content

Commit

Permalink
Merge remote-tracking branch 'lookit/develop'
Browse files Browse the repository at this point in the history
* lookit/develop:
  WIP: Feature/protocol generator (#158)
  fix for exp-lookit-preferential-looking frame not playing audio in Firefox at test trials (due to race condition w mediaReload & starting audio)
  fix bug in exp-lookit-video trial declaring audio/video done after n-1 presentations
  Bump websocket-extensions from 0.1.3 to 0.1.4 (#148)
  • Loading branch information
Kim Scott committed Aug 11, 2020
2 parents a81b8f0 + c510b29 commit d486262
Show file tree
Hide file tree
Showing 16 changed files with 1,397 additions and 43 deletions.
11 changes: 9 additions & 2 deletions app/components/exp-frame-base/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,15 @@ export default Ember.Component.extend(FullScreen, SessionRecord, {
* - `ageAtBirth`: String; child's gestational age at birth in weeks. Possible values are
* "24" through "39", "na" (not sure or prefer not to answer),
* "<24" (under 24 weeks), and "40>" (40 or more weeks).
* - `birthday`: timestamp in format "Mon Apr 10 2017 20:00:00 GMT-0400 (Eastern Daylight Time)"
* - `birthday`: Date object
* - `gender`: "f" (female), "m" (male), "o" (other), or "na" (prefer not to answer)
* - `givenName`: String, child's given name/nickname
* - `id`: String, child UUID
* - `languageList`: String, space-separated list of languages child is exposed to
* (2-letter codes)
* - `conditionList`: String, space-separated list of conditions/characteristics
* - of child from registration form, as used in criteria expression, e.g.
* "autism_spectrum_disorder deaf multiple_birth"
*
*
* `pastSessions` is a list of previous response objects for this child and this study,
Expand All @@ -119,11 +124,13 @@ export default Ember.Component.extend(FullScreen, SessionRecord, {
* - `completed`: Boolean, whether they submitted an exit survey
* - `completedConsentFrame`: Boolean, whether they got through at least a consent frame
* - `conditions`: Object representing any conditions assigned by randomizer frames
* - `createdOn`: timestamp in format "Thu Apr 18 2019 12:33:26 GMT-0400 (Eastern Daylight Time)"
* - `createdOn`: Date object
* - `expData`: Object consisting of frameId: frameData pairs
* - `globalEventTimings`: list of any events stored outside of individual frames - currently
* just used for attempts to leave the study early
* - `sequence`: ordered list of frameIds, corresponding to keys in expData
* - `isPreview`: Boolean, whether this is from a preview session (possible in the event
* this is an experimenter's account)
*
*
* Example:
Expand Down
3 changes: 3 additions & 0 deletions app/components/exp-lookit-composite-video-trial/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,9 @@ export default ExpFrameBaseComponent.extend(FullScreen, MediaReload, VideoRecord
});

if (this.get('sources_parsed').length) {
if (!this.get('altSources_parsed').length) {
this.set('altSources_parsed', this.get('sources_parsed'));
}
this.set('videosShown', [this.get('sources_parsed')[0].src, this.get('altSources_parsed')[0].src]);
} else {
this.set('videosShown', []);
Expand Down
17 changes: 10 additions & 7 deletions app/components/exp-lookit-video-consent/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ document is displayed, with additional study-specific information provided by th
Researchers can select from the following named templates:
`consent_001`: Original Lookit consent document (2019)
`consent_002`: Added optional GDPR section and research subject rights statement
`consent_003`: Same as consent_002 except that the 'Payment' section is renamed 'Benefits, risks, and payment' for institutions that prefer that
* `consent_001`: Original Lookit consent document (2019)
To look up the exact text of each consent template for your IRB protocol, please see https://github.com/lookit/research-resources/tree/master/Legal
* `consent_002`: Added optional GDPR section and research subject rights statement
* `consent_003`: Same as consent_002 except that the 'Payment' section is renamed 'Benefits, risks, and payment' for institutions that prefer that
Important: To look up the exact text of each consent template for your IRB protocol, and to understand the context for each piece of text to be inserted, please see https://github.com/lookit/research-resources/tree/master/Legal
The consent document can be downloaded as PDF document by participant.
Expand Down Expand Up @@ -249,11 +251,11 @@ export default ExpFrameBaseComponent.extend(VideoRecord, {

/**
Whether to include an addition step #4 prompting any other adults present to read a statement of consent (I have read and understand the consent document. I also agree to participate in this study.)
@property {String} prompt_all_adults
@property {boolean} prompt_all_adults
@default false
*/
prompt_all_adults: {
type: 'string',
type: 'boolean',
description: 'Whether to include instructions for any additional adults to consent',
default: false
},
Expand Down Expand Up @@ -317,7 +319,8 @@ export default ExpFrameBaseComponent.extend(VideoRecord, {

/**
List of additional custom sections of the consent form, e.g. US Patriot Act Disclosure. These are subject to Lookit approval and in general can only add information that was true anyway but that your IRB needs included; please contact us before submitting your study to check.
@property {String} research_rights_statement
@property {Array} additional_segments
@default []
*/
additional_segments: {
type: 'array',
Expand Down
1 change: 0 additions & 1 deletion app/components/exp-lookit-video/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ let {
* @class Exp-lookit-video
* @extends Exp-frame-base
* @uses Full-screen
* @uses Media-reload
* @uses Video-record
* @uses Expand-assets
*/
Expand Down
12 changes: 10 additions & 2 deletions app/components/exp-player/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,18 @@ export default Ember.Component.extend(FullScreen, {
this._super(...arguments);
this._registerHandlers();

var structure = this.get('experiment.structure');
if (typeof(structure) === 'string') {
structure = structure.replace(/(\r\n|\n|\r)/gm,'');
structure = JSON.parse(structure);
}

var parser = new ExperimentParser({
structure: this.get('experiment.structure'),
structure: structure,
pastSessions: this.get('pastSessions').toArray(),
child: this.get('session.child')
child: this.get('session.child'),
useGenerator: this.get('experiment.useGenerator'),
generator: this.get('experiment.generator')
});
var [frameConfigs, conditions] = parser.parse();
this.set('frames', frameConfigs); // When player loads, convert structure to list of frames
Expand Down
2 changes: 2 additions & 0 deletions app/models/child.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ export default DS.Model.extend({
ageAtBirth: DS.attr('string'),
additionalInformation: DS.attr('string'),
deleted: DS.attr('boolean', {default: false}),
languageList: DS.attr('string'),
conditionList: DS.attr('string'),
user: DS.belongsTo('user')
});
5 changes: 0 additions & 5 deletions app/models/organization.js

This file was deleted.

5 changes: 2 additions & 3 deletions app/models/study.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@ import HasManyQuery from 'ember-data-has-many-query';

export default DS.Model.extend(HasManyQuery.ModelMixin, {
name: DS.attr('string'),
dateModified: DS.attr('date'),
shortDescription: DS.attr('string'),
longDescription: DS.attr('string'),
criteria: DS.attr('string'),
duration: DS.attr('string'),
contactInfo: DS.attr('string'),
image: DS.attr('string'),
structure: DS.attr(''),
generator: DS.attr('string'),
useGenerator: DS.attr('boolean'),
exitURL: DS.attr('string'),
state: DS.attr('string'),
public: DS.attr('boolean'),

organization: DS.belongsTo('organization'),
creator: DS.belongsTo('user'),
responses: DS.hasMany('response')
});
10 changes: 7 additions & 3 deletions app/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ import DS from 'ember-data';

export default DS.Model.extend({
givenName: DS.attr('string'),
middleName: DS.attr('string'),
familyName: DS.attr('string'),
nickname: DS.attr('string'),
identicon: DS.attr('string'),
isActive: DS.attr('boolean'),
isStaff: DS.attr('boolean'),

demographics: DS.hasMany('demographic'),
organization: DS.belongsTo('organization'),
children: DS.hasMany('child')
children: DS.hasMany('child'),

emailNextSession: DS.attr('boolean'),
emailNewStudies: DS.attr('boolean'),
emailStudyUpdates: DS.attr('boolean'),
emailResponseQuestions: DS.attr('boolean')
});
54 changes: 50 additions & 4 deletions app/utils/parse-experiment.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,28 @@ var urlPattern = /^(URL|JSON):(.*)$/;
import randomizers from '../randomizers/index';
import Substituter from './replace-values';

function assert(condition, message) {
if (!condition) {
throw new Error(message || 'Assertion failed');
}
}

var ExperimentParser = function (context = {
pastSessions: [],
structure: {
frames: {},
sequence: []
},
child: {}
child: {},
useGenerator: false,
generator: ''
}) {
this.pastSessions = context.pastSessions;
this.frames = context.structure.frames;
this.sequence = context.structure.sequence;
this.child = context.child;

this.useGenerator = context.useGenerator;
this.generator = context.generator;
};
/* Modifies the data in the experiment schema definition to match
* the format expected by exp-player
Expand Down Expand Up @@ -103,8 +112,8 @@ ExperimentParser.prototype._resolveFrame = function (frameId, frame) {
var thisFrame;
frame.frameList.forEach((fr, index) => {
thisFrame = {};
Ember.$.extend(true, thisFrame, frame.commonFrameProperties || {});
Ember.$.extend(true, thisFrame, fr);
Ember.$.extend(thisFrame, frame.commonFrameProperties || {}); // NOT deep-copying so we can recognize instances of the same list
Ember.$.extend(thisFrame, fr);
var [resolved, choice] = this._resolveFrame(null, thisFrame);
resolvedFrameList.push(...resolved);
if (choice) {
Expand All @@ -124,6 +133,43 @@ ExperimentParser.prototype._resolveFrame = function (frameId, frame) {
ExperimentParser.prototype.parse = function (prependFrameInds = true) {
var expFrames = [];
var choices = {};

// First, if useGenerator & generator defined, generate the sequence & frames.
if (this.useGenerator) {
var generatedStructure = {};
try {
new Function(this.generator)();
try {
let generatorFn = new Function('return ' + this.generator)();
assert(typeof generatorFn === 'function');
generatedStructure = generatorFn(this.child, this.pastSessions);
try {
assert(generatedStructure.hasOwnProperty('frames'));
assert(generatedStructure.hasOwnProperty('sequence'));
} catch (error) {
this.useGenerator = false;
console.error(error);
console.warn('Generator function does not return an object with "sequence" and "frames" fields.');
}
} catch (error) {
this.useGenerator = false;
console.error(error);
console.warn('Generator function does not evaluate to single function, or error upon calling function. Falling back to standard protocol definition.');
}
} catch (error) {
this.useGenerator = false;
console.error(error);
console.warn('Generator function provided is not valid Javascript. Falling back to standard protocol definition.');
} finally {
if (this.useGenerator) {
console.log('Using generator function in place of standard protocol definition.');
this.sequence = generatedStructure.sequence;
this.frames = generatedStructure.frames;
}
}
}
// After generating, process exactly as if these had been provided as a standard protocol.

this.sequence.forEach((frameId, index) => {
var [resolved, choice] = this._resolveFrame(frameId);
expFrames.push(...resolved);
Expand Down
2 changes: 1 addition & 1 deletion docs
Submodule docs updated 187 files
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ember-lookit-frameplayer",
"version": "v1.2.0",
"version": "v1.3.0",
"description": "Ember Frame Player",
"private": true,
"directories": {
Expand Down
12 changes: 0 additions & 12 deletions tests/unit/models/organization-test.js

This file was deleted.

2 changes: 1 addition & 1 deletion tests/unit/models/study-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { moduleForModel, test } from 'ember-qunit';

moduleForModel('study', 'Unit | Model | study', {
// Specify the other units that are required for this test.
needs: ['model:study', 'model:organization', 'model:user', 'model:response']
needs: ['model:study', 'model:user', 'model:response']
});

test('it exists', function(assert) {
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/models/user-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { moduleForModel, test } from 'ember-qunit';

moduleForModel('user', 'Unit | Model | user', {
// Specify the other units that are required for this test.
needs: ['model:user', 'model:demographic', 'model:organization', 'model:child']
needs: ['model:user', 'model:demographic', 'model:child']
});

test('it exists', function(assert) {
Expand Down
Loading

0 comments on commit d486262

Please sign in to comment.