Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Large Package Refactoring #9

Open
wants to merge 4 commits into
base: package-refactor
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
28 changes: 28 additions & 0 deletions assets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"default": {
"languageSpecific": {
"device": [],
"shared": [
"Honey_Hunt_Intro_1.mp4",
"Honey_Hunt_Intro_2.mp4",
"Honey_Hunt_Intro_3.mp4",
Willy-Chan marked this conversation as resolved.
Show resolved Hide resolved
"Honey_Hunt_Intro_4.mp4",
"Honey_Hunt_Intro_5.mp4",
"Honey_Hunt_Intro_Button_3.mp4",
"Honey_Hunt_Intro_Button_4.mp4",
"Honey_Hunt_End.mp4",
"Honey_Hunt_Level_Up_1.mp4",
"Honey_Hunt_Level_Up_2.mp4",
"Honey_Hunt_Level_Up_3.mp4",
"Honey_Hunt_Level_Up_4.mp4",
"Honey_Hunt_Level_Up_5.mp4"
]
},
"shared": [
"tree-left.png",
"tree-right.png",
"feedbackCorrect.mp3",
"feedbackIncorrect.mp3"
]
}
}
2,557 changes: 1,678 additions & 879 deletions package-lock.json

Large diffs are not rendered by default.

41 changes: 31 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,47 @@
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config webpack.prod.js",
"start": "webpack serve --open --config webpack.dev.js"
"build:dev": "npx webpack --mode production --env dbmode=development",
"build:prod": "npx webpack --mode production --env dbmode=production",
"build:package": "npx rollup -c",
"prepublishOnly": "npm run build:package",
"serve:dev": "npx webpack serve --open --mode development --env dbmode=development",
"serve:prod": "npx webpack serve --open --mode development --env dbmode=production"
},
"keywords": [],
"author": "",
"license": "STANFORD ACADEMIC SOFTWARE LICENSE FOR ROAR™",
"dependencies": {
"@bdelab/roar-firekit": "^0.1.3",
"@babel/core": "^7.19.3",
"@babel/preset-env": "^7.19.4",
"@bdelab/roar-firekit": "^3.7.2",
"@bdelab/roar-utils": "^1.0.10",
"@jspsych-contrib/plugin-rdk": "^1.1.0",
"@jspsych/plugin-audio-keyboard-response": "^1.1.0",
"@jspsych/plugin-fullscreen": "^1.1.0",
"@jspsych/plugin-html-keyboard-response": "^1.1.0",
"@jspsych/plugin-audio-keyboard-response": "^1.1.2",
"@jspsych/plugin-fullscreen": "^1.1.2",
"@jspsych/plugin-html-keyboard-response": "^1.1.2",
"@jspsych/plugin-image-keyboard-response": "^1.1.0",
"@jspsych/plugin-preload": "^1.1.1",
"@jspsych/plugin-survey-text": "^1.1.0",
"@jspsych/plugin-preload": "^1.1.2",
"@jspsych/plugin-survey-html-form": "^1.0.2",
"@jspsych/plugin-survey-multi-select": "^1.1.2",
"@jspsych/plugin-survey-text": "^1.1.2",
"@jspsych/plugin-video-keyboard-response": "^1.1.0",
"@jspsych/test-utils": "^1.1.2",
"babel-loader": "^8.2.5",
"file-loader": "^6.2.0",
"firebase": "^9.6.9",
"jspsych": "^7.2.1",
"regenerator-runtime": "^0.13.9"
"i18next": "^23.2.11",
"i18next-browser-languagedetector": "^7.1.0",
"jspsych": "^7.3.1",
"lodash": "^4.17.21",
"regenerator-runtime": "^0.13.10",
"roarr": "^7.14.0",
"setimmediate": "^1.0.5",
"store2": "^2.14.2",
"timers": "^0.1.1",
"timers-browserify": "^2.0.12",
"webpack": "^5.74.0",
"webpack-dev-server": "^4.11.1"
},
"devDependencies": {
"@babel/core": "^7.17.8",
Expand Down
33 changes: 33 additions & 0 deletions serve/firebaseConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { log } from '../src/experiment/config/logger';


const devFirebaseConfig = {
apiKey: "AIzaSyCX9WR-j9yv1giYeFsMpbjj2G3p7jNHxIU",
authDomain: "gse-yeatmanlab.firebaseapp.com",
projectId: "gse-yeatmanlab",
storageBucket: "gse-yeatmanlab.appspot.com",
messagingSenderId: "292331000426",
appId: "1:292331000426:web:91a04220991e3405737013",
measurementId: "G-0TBTMDS993",
};

const productionFirebaseConfig = {
apiKey: "AIzaSyDw0TnTXbvRyoVo5_oa_muhXk9q7783k_g",
authDomain: "gse-roar-assessment.firebaseapp.com",
projectId: "gse-roar-assessment",
storageBucket: "gse-roar-assessment.appspot.com",
messagingSenderId: "757277423033",
appId: "1:757277423033:web:d6e204ee2dd1047cb77268",
};

export const firebaseConfig =
// eslint-disable-next-line no-undef
ROAR_DB === "production" ? productionFirebaseConfig : devFirebaseConfig;

export const roarConfig = {
firebaseConfig,
}

const logMessage =
`This ROAR app will write data to the ${roarConfig.firebaseConfig.projectId} firestore database`
log.info(logMessage);
82 changes: 82 additions & 0 deletions serve/serve.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import ROARMP from "../src/index"
import { RoarAppkit, initializeFirebaseProject } from '@bdelab/roar-firekit';
import { roarConfig } from "./firebaseConfig.js";
import { onAuthStateChanged, signInAnonymously } from 'firebase/auth'

// Import necessary for async in the top level of the experiment script
import "regenerator-runtime/runtime.js";

//@ts-ignore
export const queryString = new URL(window.location).search;
export const urlParams = new URLSearchParams(queryString);
export const pid = urlParams.get('participant') || null;
export const studyId = urlParams.get('studyId') || null;
Willy-Chan marked this conversation as resolved.
Show resolved Hide resolved
export const classId = urlParams.get('classId') || null;
export const schoolId = urlParams.get('schoolId') || null;
export const labId = urlParams.get('labId') || null;
export const userMode = urlParams.get('mode') || "default";
export const redirectTo = urlParams.get('redirectTo') || null;
export const pipeline = urlParams.get('pipeline') || 'rc';
export const language = urlParams.get('language') || 'en';
export const responseModality = urlParams.get('responseModality') || 'touch';
export const enableButtons = responseModality === 'touch' ? true : false;

/* 4 modes
default: no-survey + story (if < grade 6) and no-story (if >= grade 6)
demo: survey + story all grades
story: no-survey + story all grades
nostory: no-survey + no-story all grades
*/
const taskVariant = urlParams.get('variant') || "pilot";
const consent = urlParams.get('consent') || true;
const grade = urlParams.get('grade') || null;
// TODO: change url parameters
const skipInstructions = urlParams.get('skip');

// @ts-ignore
const appKit = await initializeFirebaseProject(roarConfig.firebaseConfig, 'assessmentApp', 'none');

onAuthStateChanged(appKit.auth, (user) => {
if (user) {
const userInfo = {
assessmentPid: pid,
assessmentUid: user.uid,
userMetadata: {
classId,
schoolId,
districtId: '',
studyId,
},
};

const userParams = {
pid,
labId,
grade,
}

const gameParams = {
userMode,
taskVariant,
skipInstructions,
consent,
};

const taskInfo = {
taskId: 'mp',
variantParams: gameParams,
}

const firekit = new RoarAppkit({
firebaseProject: appKit,
taskInfo,
userInfo,
})

const roarApp = new ROARMP(firekit, gameParams, userParams);
roarApp.run();

}
});

await signInAnonymously(appKit.auth);
Binary file removed src/audio/feedbackCorrect.mp3
Binary file not shown.
Binary file removed src/audio/feedbackIncorrect.mp3
Binary file not shown.
154 changes: 154 additions & 0 deletions src/experiment/config/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import store from "store2";
import { getUserDataTimeline } from "../trials/getUserData";
import _omitBy from "lodash/omitBy.js";
import _isNull from "lodash/isNull.js";
import _isUndefined from "lodash/isUndefined.js";
import { jsPsych } from "../jsPsych";
import { RoarScores } from "../scores";

// Add this function to create random pid used for demo version later // TO DO: Make a random ID for the demo mode
const makePid = () => {
let text = "";
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
// eslint-disable-next-line max-len
for (let i = 0; i < 16; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); }
return text;
};

export const initStore = () => {
if (store.session.has("initialized") && store.local("initialized")) {
return store.session;
}
store.session.set("practiceIndex", 0);
// Counting variables
store.session.set("currentBlockIndex", 0);
store.session.set("trialNumBlock", 0); // counter for trials in block
store.session.set("trialNumTotal", 0); // counter for trials in experiment
store.session.set("demoCounter", 0);
store.session.set("nextStimulus", null);
store.session.set("response", "");
store.session.set("dataCorrect", "");
store.session.set("keyResponse", "");
store.session.set("gradeKeyResponse", []);
store.session.set("currentCorpus", []);

// variables to track current state of the experiment
store.session.set("currentTrialCorrect", true); // return true or false
store.session.set("coinTrackingIndex", 0);

store.session.set("initialized", true);

return store.session;
};


export const initConfig = async (firekit, params, displayElement) => {
const cleanParams = _omitBy(_omitBy(params, _isNull), _isUndefined);

const { userMode,
pid,
labId,
taskVariant,
userMetadata,
urlParams,
consent,
language,
skipInstructions,
grade,
} = cleanParams

let prefix = null;
if (pid) {
prefix = pid.split("-")[0];
if ((prefix === pid) || (taskVariant !== 'school')) {
prefix = null;
}
}

const config = {
pid,
labId,
userMode,
taskVariant: taskVariant || 'pilot',
consent: consent || true,
userMetadata: {grade: grade},
startTime: new Date(),
urlParams: urlParams,
firekit,
language,
skipInstructions: skipInstructions || true,
displayElement: displayElement || null,
};

if (config.pid !== null) {
await config.firekit.updateUser({ assessmentPid: config.pid, ...userMetadata });
}

return config;
}

export const initRoarJsPsych = (config) => {
if (config.displayElement) {
jsPsych.opts.display_element = config.displayElement
}

// Extend jsPsych's on_finish and on_data_update lifecycle functions to mark the
// run as completed and write data to Firestore, respectively.
const extend = (fn, code) =>
function () {
// eslint-disable-next-line prefer-rest-params
fn.apply(fn, arguments);
// eslint-disable-next-line prefer-rest-params
code.apply(fn, arguments);
};

jsPsych.opts.on_finish = extend(jsPsych.opts.on_finish, () => {
config.firekit.finishRun();
if (config.experimentFinished) {
config.experimentFinished()
}
});

const roarScores = new RoarScores();
jsPsych.opts.on_data_update = extend(jsPsych.opts.on_data_update, (data) => {
if (data.save_trial) {
config.firekit.writeTrial(
data,
roarScores.computedScoreCallback.bind(roarScores),
);
}
});

// Add a special error handler that writes javascript errors to a special trial
// type in the Firestore database
window.addEventListener('error', (e) => {
const { msg, url, lineNo, columnNo, error } = e;

config.firekit?.writeTrial({
assessment_stage: 'error',
lastTrial: jsPsych.data.getLastTrialData().trials[0],
message: String(msg),
source: url || null,
lineNo: String(lineNo || null),
colNo: String(columnNo || null),
error: JSON.stringify(error || null),
timeStamp: new Date().toISOString(),
});
});

initStore(config);
};

export const initRoarTimeline = (config) => {
const beginningTimeline = {
timeline: getUserDataTimeline,
on_timeline_finish: async () => {
// eslint-disable-next-line no-param-reassign
config.pid = config.pid || makePid();
await config.firekit.updateUser({ assessmentPid: config.pid, labId: config.labId, ...config.userMetadata });
},
};

return beginningTimeline;
};

Loading