jspsych 8.1.0 → 8.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.browser.js +1345 -393
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.min.js +7 -6
- package/dist/index.browser.min.js.map +1 -1
- package/dist/index.cjs +246 -108
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +28 -39
- package/dist/index.js +246 -108
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/ExtensionManager.spec.ts +1 -1
- package/src/JsPsych.ts +47 -0
- package/src/modules/extensions.ts +1 -0
- package/src/modules/plugins.ts +1 -0
- package/src/modules/randomization.ts +1 -1
- package/src/timeline/Timeline.spec.ts +2 -2
- package/src/timeline/Trial.spec.ts +16 -2
- package/src/timeline/Trial.ts +6 -1
package/dist/index.browser.js
CHANGED
|
@@ -51,70 +51,7 @@ var jsPsychModule = (function (exports) {
|
|
|
51
51
|
|
|
52
52
|
var autoBind$1 = /*@__PURE__*/getDefaultExportFromCjs(autoBind);
|
|
53
53
|
|
|
54
|
-
var
|
|
55
|
-
name: "jspsych",
|
|
56
|
-
version: "8.1.0",
|
|
57
|
-
description: "Behavioral experiments in a browser",
|
|
58
|
-
type: "module",
|
|
59
|
-
main: "dist/index.cjs",
|
|
60
|
-
exports: {
|
|
61
|
-
".": {
|
|
62
|
-
import: "./dist/index.js",
|
|
63
|
-
require: "./dist/index.cjs"
|
|
64
|
-
},
|
|
65
|
-
"./css/*": "./css/*"
|
|
66
|
-
},
|
|
67
|
-
typings: "dist/index.d.ts",
|
|
68
|
-
unpkg: "dist/index.browser.min.js",
|
|
69
|
-
files: [
|
|
70
|
-
"src",
|
|
71
|
-
"dist",
|
|
72
|
-
"css"
|
|
73
|
-
],
|
|
74
|
-
source: "src/index.ts",
|
|
75
|
-
scripts: {
|
|
76
|
-
test: "jest",
|
|
77
|
-
"test:watch": "npm test -- --watch",
|
|
78
|
-
tsc: "tsc",
|
|
79
|
-
"build:js": "rollup --config",
|
|
80
|
-
"build:styles": "webpack-cli",
|
|
81
|
-
build: "run-p build:js build:styles",
|
|
82
|
-
"build:watch": 'run-p "build:js -- --watch" "build:styles watch"',
|
|
83
|
-
prepack: "cp ../../README.md ."
|
|
84
|
-
},
|
|
85
|
-
repository: {
|
|
86
|
-
type: "git",
|
|
87
|
-
url: "git+https://github.com/jspsych/jsPsych.git",
|
|
88
|
-
directory: "packages/jspsych"
|
|
89
|
-
},
|
|
90
|
-
author: "Josh de Leeuw",
|
|
91
|
-
license: "MIT",
|
|
92
|
-
bugs: {
|
|
93
|
-
url: "https://github.com/jspsych/jsPsych/issues"
|
|
94
|
-
},
|
|
95
|
-
homepage: "https://www.jspsych.org",
|
|
96
|
-
dependencies: {
|
|
97
|
-
"auto-bind": "^4.0.0",
|
|
98
|
-
"random-words": "^1.1.1",
|
|
99
|
-
seedrandom: "^3.0.5",
|
|
100
|
-
"type-fest": "^2.9.0"
|
|
101
|
-
},
|
|
102
|
-
devDependencies: {
|
|
103
|
-
"@fontsource/open-sans": "4.5.3",
|
|
104
|
-
"@jspsych/config": "^3.0.1",
|
|
105
|
-
"@types/dom-mediacapture-record": "^1.0.11",
|
|
106
|
-
"base64-inline-loader": "^2.0.1",
|
|
107
|
-
"css-loader": "^6.6.0",
|
|
108
|
-
"mini-css-extract-plugin": "^2.5.3",
|
|
109
|
-
"npm-run-all": "^4.1.5",
|
|
110
|
-
"replace-in-file-webpack-plugin": "^1.0.6",
|
|
111
|
-
sass: "^1.43.5",
|
|
112
|
-
"sass-loader": "^12.4.0",
|
|
113
|
-
webpack: "^5.76.0",
|
|
114
|
-
"webpack-cli": "^4.9.2",
|
|
115
|
-
"webpack-remove-empty-scripts": "^0.7.2"
|
|
116
|
-
}
|
|
117
|
-
};
|
|
54
|
+
var version = "8.2.1";
|
|
118
55
|
|
|
119
56
|
class ExtensionManager {
|
|
120
57
|
constructor(dependencies, extensionsConfiguration) {
|
|
@@ -130,7 +67,6 @@ var jsPsychModule = (function (exports) {
|
|
|
130
67
|
static getExtensionNameByClass(extensionClass) {
|
|
131
68
|
return extensionClass["info"].name;
|
|
132
69
|
}
|
|
133
|
-
extensions;
|
|
134
70
|
getExtensionInstanceByClass(extensionClass) {
|
|
135
71
|
return this.extensions[ExtensionManager.getExtensionNameByClass(extensionClass)];
|
|
136
72
|
}
|
|
@@ -187,8 +123,7 @@ var jsPsychModule = (function (exports) {
|
|
|
187
123
|
return [...new Set(arr)];
|
|
188
124
|
}
|
|
189
125
|
function deepCopy(obj) {
|
|
190
|
-
if (!obj)
|
|
191
|
-
return obj;
|
|
126
|
+
if (!obj) return obj;
|
|
192
127
|
let out;
|
|
193
128
|
if (Array.isArray(obj)) {
|
|
194
129
|
out = [];
|
|
@@ -235,9 +170,9 @@ var jsPsychModule = (function (exports) {
|
|
|
235
170
|
|
|
236
171
|
var utils = /*#__PURE__*/Object.freeze({
|
|
237
172
|
__proto__: null,
|
|
238
|
-
unique: unique,
|
|
239
173
|
deepCopy: deepCopy,
|
|
240
|
-
deepMerge: deepMerge
|
|
174
|
+
deepMerge: deepMerge,
|
|
175
|
+
unique: unique
|
|
241
176
|
});
|
|
242
177
|
|
|
243
178
|
class DataColumn {
|
|
@@ -383,16 +318,13 @@ var jsPsychModule = (function (exports) {
|
|
|
383
318
|
const b = {};
|
|
384
319
|
for (let i = 0; i < a.length; ++i) {
|
|
385
320
|
const p = a[i].split("=", 2);
|
|
386
|
-
if (p.length == 1)
|
|
387
|
-
|
|
388
|
-
else
|
|
389
|
-
b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
|
|
321
|
+
if (p.length == 1) b[p[0]] = "";
|
|
322
|
+
else b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
|
|
390
323
|
}
|
|
391
324
|
return b;
|
|
392
325
|
}
|
|
393
326
|
|
|
394
327
|
class DataCollection {
|
|
395
|
-
trials;
|
|
396
328
|
constructor(data = []) {
|
|
397
329
|
this.trials = data;
|
|
398
330
|
}
|
|
@@ -411,26 +343,44 @@ var jsPsychModule = (function (exports) {
|
|
|
411
343
|
return new DataCollection([this.trials[this.trials.length - 1]]);
|
|
412
344
|
}
|
|
413
345
|
}
|
|
346
|
+
/**
|
|
347
|
+
* Queries the first n elements in a collection of trials.
|
|
348
|
+
*
|
|
349
|
+
* @param n A positive integer of elements to return. A value of
|
|
350
|
+
* n that is less than 1 will throw an error.
|
|
351
|
+
*
|
|
352
|
+
* @return First n objects of a collection of trials. If fewer than
|
|
353
|
+
* n trials are available, the trials.length elements will
|
|
354
|
+
* be returned.
|
|
355
|
+
*
|
|
356
|
+
*/
|
|
414
357
|
first(n = 1) {
|
|
415
358
|
if (n < 1) {
|
|
416
359
|
throw `You must query with a positive nonzero integer. Please use a
|
|
417
360
|
different value for n.`;
|
|
418
361
|
}
|
|
419
|
-
if (this.trials.length === 0)
|
|
420
|
-
|
|
421
|
-
if (n > this.trials.length)
|
|
422
|
-
n = this.trials.length;
|
|
362
|
+
if (this.trials.length === 0) return new DataCollection();
|
|
363
|
+
if (n > this.trials.length) n = this.trials.length;
|
|
423
364
|
return new DataCollection(this.trials.slice(0, n));
|
|
424
365
|
}
|
|
366
|
+
/**
|
|
367
|
+
* Queries the last n elements in a collection of trials.
|
|
368
|
+
*
|
|
369
|
+
* @param n A positive integer of elements to return. A value of
|
|
370
|
+
* n that is less than 1 will throw an error.
|
|
371
|
+
*
|
|
372
|
+
* @return Last n objects of a collection of trials. If fewer than
|
|
373
|
+
* n trials are available, the trials.length elements will
|
|
374
|
+
* be returned.
|
|
375
|
+
*
|
|
376
|
+
*/
|
|
425
377
|
last(n = 1) {
|
|
426
378
|
if (n < 1) {
|
|
427
379
|
throw `You must query with a positive nonzero integer. Please use a
|
|
428
380
|
different value for n.`;
|
|
429
381
|
}
|
|
430
|
-
if (this.trials.length === 0)
|
|
431
|
-
|
|
432
|
-
if (n > this.trials.length)
|
|
433
|
-
n = this.trials.length;
|
|
382
|
+
if (this.trials.length === 0) return new DataCollection();
|
|
383
|
+
if (n > this.trials.length) n = this.trials.length;
|
|
434
384
|
return new DataCollection(this.trials.slice(this.trials.length - n, this.trials.length));
|
|
435
385
|
}
|
|
436
386
|
values() {
|
|
@@ -550,13 +500,26 @@ var jsPsychModule = (function (exports) {
|
|
|
550
500
|
class JsPsychData {
|
|
551
501
|
constructor(dependencies) {
|
|
552
502
|
this.dependencies = dependencies;
|
|
503
|
+
/** Data properties for all trials */
|
|
504
|
+
this.dataProperties = {};
|
|
505
|
+
this.interactionListeners = {
|
|
506
|
+
blur: () => {
|
|
507
|
+
this.addInteractionRecord("blur");
|
|
508
|
+
},
|
|
509
|
+
focus: () => {
|
|
510
|
+
this.addInteractionRecord("focus");
|
|
511
|
+
},
|
|
512
|
+
fullscreenchange: () => {
|
|
513
|
+
this.addInteractionRecord(
|
|
514
|
+
// @ts-expect-error
|
|
515
|
+
document.isFullScreen || // @ts-expect-error
|
|
516
|
+
document.webkitIsFullScreen || // @ts-expect-error
|
|
517
|
+
document.mozIsFullScreen || document.fullscreenElement ? "fullscreenenter" : "fullscreenexit"
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
};
|
|
553
521
|
this.reset();
|
|
554
522
|
}
|
|
555
|
-
results;
|
|
556
|
-
resultToTrialMap;
|
|
557
|
-
interactionRecords;
|
|
558
|
-
dataProperties = {};
|
|
559
|
-
query_string;
|
|
560
523
|
reset() {
|
|
561
524
|
this.results = new DataCollection();
|
|
562
525
|
this.resultToTrialMap = /* @__PURE__ */ new WeakMap();
|
|
@@ -615,19 +578,6 @@ var jsPsychModule = (function (exports) {
|
|
|
615
578
|
this.interactionRecords.push(record);
|
|
616
579
|
this.dependencies.onInteractionRecordAdded(record);
|
|
617
580
|
}
|
|
618
|
-
interactionListeners = {
|
|
619
|
-
blur: () => {
|
|
620
|
-
this.addInteractionRecord("blur");
|
|
621
|
-
},
|
|
622
|
-
focus: () => {
|
|
623
|
-
this.addInteractionRecord("focus");
|
|
624
|
-
},
|
|
625
|
-
fullscreenchange: () => {
|
|
626
|
-
this.addInteractionRecord(
|
|
627
|
-
document.isFullScreen || document.webkitIsFullScreen || document.mozIsFullScreen || document.fullscreenElement ? "fullscreenenter" : "fullscreenexit"
|
|
628
|
-
);
|
|
629
|
-
}
|
|
630
|
-
};
|
|
631
581
|
createInteractionListeners() {
|
|
632
582
|
window.addEventListener("blur", this.interactionListeners.blur);
|
|
633
583
|
window.addEventListener("focus", this.interactionListeners.focus);
|
|
@@ -652,12 +602,16 @@ var jsPsychModule = (function (exports) {
|
|
|
652
602
|
this.getRootElement = getRootElement;
|
|
653
603
|
this.areResponsesCaseSensitive = areResponsesCaseSensitive;
|
|
654
604
|
this.minimumValidRt = minimumValidRt;
|
|
605
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
606
|
+
this.heldKeys = /* @__PURE__ */ new Set();
|
|
607
|
+
this.areRootListenersRegistered = false;
|
|
655
608
|
autoBind$1(this);
|
|
656
609
|
this.registerRootListeners();
|
|
657
610
|
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
611
|
+
/**
|
|
612
|
+
* If not previously done and `this.getRootElement()` returns an element, adds the root key
|
|
613
|
+
* listeners to that element.
|
|
614
|
+
*/
|
|
661
615
|
registerRootListeners() {
|
|
662
616
|
if (!this.areRootListenersRegistered) {
|
|
663
617
|
const rootElement = this.getRootElement();
|
|
@@ -773,11 +727,6 @@ var jsPsychModule = (function (exports) {
|
|
|
773
727
|
})(ParameterType || {});
|
|
774
728
|
|
|
775
729
|
class AudioPlayer {
|
|
776
|
-
audio;
|
|
777
|
-
webAudioBuffer;
|
|
778
|
-
audioContext;
|
|
779
|
-
useWebAudio;
|
|
780
|
-
src;
|
|
781
730
|
constructor(src, options = { useWebAudio: false }) {
|
|
782
731
|
this.src = src;
|
|
783
732
|
this.useWebAudio = options.useWebAudio;
|
|
@@ -794,8 +743,7 @@ var jsPsychModule = (function (exports) {
|
|
|
794
743
|
if (this.audio instanceof HTMLAudioElement) {
|
|
795
744
|
this.audio.play();
|
|
796
745
|
} else {
|
|
797
|
-
if (!this.audio)
|
|
798
|
-
this.audio = this.getAudioSourceNode(this.webAudioBuffer);
|
|
746
|
+
if (!this.audio) this.audio = this.getAudioSourceNode(this.webAudioBuffer);
|
|
799
747
|
this.audio.start();
|
|
800
748
|
}
|
|
801
749
|
}
|
|
@@ -857,19 +805,28 @@ var jsPsychModule = (function (exports) {
|
|
|
857
805
|
class MediaAPI {
|
|
858
806
|
constructor(useWebaudio) {
|
|
859
807
|
this.useWebaudio = useWebaudio;
|
|
808
|
+
// video //
|
|
809
|
+
this.video_buffers = {};
|
|
810
|
+
// audio //
|
|
811
|
+
this.context = null;
|
|
812
|
+
this.audio_buffers = [];
|
|
813
|
+
// preloading stimuli //
|
|
814
|
+
this.preload_requests = [];
|
|
815
|
+
this.img_cache = {};
|
|
816
|
+
this.preloadMap = /* @__PURE__ */ new Map();
|
|
817
|
+
this.microphone_recorder = null;
|
|
818
|
+
this.camera_stream = null;
|
|
819
|
+
this.camera_recorder = null;
|
|
860
820
|
if (this.useWebaudio && typeof window !== "undefined" && typeof window.AudioContext !== "undefined") {
|
|
861
821
|
this.context = new AudioContext();
|
|
862
822
|
}
|
|
863
823
|
}
|
|
864
|
-
video_buffers = {};
|
|
865
824
|
getVideoBuffer(videoID) {
|
|
866
825
|
if (videoID.startsWith("blob:")) {
|
|
867
826
|
this.video_buffers[videoID] = videoID;
|
|
868
827
|
}
|
|
869
828
|
return this.video_buffers[videoID];
|
|
870
829
|
}
|
|
871
|
-
context = null;
|
|
872
|
-
audio_buffers = [];
|
|
873
830
|
audioContext() {
|
|
874
831
|
if (this.context && this.context.state !== "running") {
|
|
875
832
|
this.context.resume();
|
|
@@ -888,8 +845,6 @@ var jsPsychModule = (function (exports) {
|
|
|
888
845
|
return this.audio_buffers[audioID];
|
|
889
846
|
}
|
|
890
847
|
}
|
|
891
|
-
preload_requests = [];
|
|
892
|
-
img_cache = {};
|
|
893
848
|
preloadAudio(files, callback_complete = () => {
|
|
894
849
|
}, callback_load = (filepath) => {
|
|
895
850
|
}, callback_error = (error) => {
|
|
@@ -994,7 +949,6 @@ var jsPsychModule = (function (exports) {
|
|
|
994
949
|
this.preload_requests.push(request);
|
|
995
950
|
}
|
|
996
951
|
}
|
|
997
|
-
preloadMap = /* @__PURE__ */ new Map();
|
|
998
952
|
getAutoPreloadList(timeline_description) {
|
|
999
953
|
const preloadPaths = Object.fromEntries(
|
|
1000
954
|
preloadParameterTypes.map((type) => [type, /* @__PURE__ */ new Set()])
|
|
@@ -1054,7 +1008,6 @@ var jsPsychModule = (function (exports) {
|
|
|
1054
1008
|
}
|
|
1055
1009
|
this.preload_requests = [];
|
|
1056
1010
|
}
|
|
1057
|
-
microphone_recorder = null;
|
|
1058
1011
|
initializeMicrophoneRecorder(stream) {
|
|
1059
1012
|
const recorder = new MediaRecorder(stream);
|
|
1060
1013
|
this.microphone_recorder = recorder;
|
|
@@ -1062,8 +1015,6 @@ var jsPsychModule = (function (exports) {
|
|
|
1062
1015
|
getMicrophoneRecorder() {
|
|
1063
1016
|
return this.microphone_recorder;
|
|
1064
1017
|
}
|
|
1065
|
-
camera_stream = null;
|
|
1066
|
-
camera_recorder = null;
|
|
1067
1018
|
initializeCameraRecorder(stream, opts) {
|
|
1068
1019
|
this.camera_stream = stream;
|
|
1069
1020
|
const recorder = new MediaRecorder(stream, opts);
|
|
@@ -1085,12 +1036,25 @@ var jsPsychModule = (function (exports) {
|
|
|
1085
1036
|
dispatchEvent(event) {
|
|
1086
1037
|
this.getDisplayContainerElement().dispatchEvent(event);
|
|
1087
1038
|
}
|
|
1039
|
+
/**
|
|
1040
|
+
* Dispatches a `keydown` event for the specified key
|
|
1041
|
+
* @param key Character code (`.key` property) for the key to press.
|
|
1042
|
+
*/
|
|
1088
1043
|
keyDown(key) {
|
|
1089
1044
|
this.dispatchEvent(new KeyboardEvent("keydown", { key }));
|
|
1090
1045
|
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Dispatches a `keyup` event for the specified key
|
|
1048
|
+
* @param key Character code (`.key` property) for the key to press.
|
|
1049
|
+
*/
|
|
1091
1050
|
keyUp(key) {
|
|
1092
1051
|
this.dispatchEvent(new KeyboardEvent("keyup", { key }));
|
|
1093
1052
|
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Dispatches a `keydown` and `keyup` event in sequence to simulate pressing a key.
|
|
1055
|
+
* @param key Character code (`.key` property) for the key to press.
|
|
1056
|
+
* @param delay Length of time to wait (ms) before executing action
|
|
1057
|
+
*/
|
|
1094
1058
|
pressKey(key, delay = 0) {
|
|
1095
1059
|
if (delay > 0) {
|
|
1096
1060
|
this.setJsPsychTimeout(() => {
|
|
@@ -1102,6 +1066,11 @@ var jsPsychModule = (function (exports) {
|
|
|
1102
1066
|
this.keyUp(key);
|
|
1103
1067
|
}
|
|
1104
1068
|
}
|
|
1069
|
+
/**
|
|
1070
|
+
* Dispatches `mousedown`, `mouseup`, and `click` events on the target element
|
|
1071
|
+
* @param target The element to click
|
|
1072
|
+
* @param delay Length of time to wait (ms) before executing action
|
|
1073
|
+
*/
|
|
1105
1074
|
clickTarget(target, delay = 0) {
|
|
1106
1075
|
if (delay > 0) {
|
|
1107
1076
|
this.setJsPsychTimeout(() => {
|
|
@@ -1115,6 +1084,12 @@ var jsPsychModule = (function (exports) {
|
|
|
1115
1084
|
target.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
1116
1085
|
}
|
|
1117
1086
|
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Sets the value of a target text input
|
|
1089
|
+
* @param target A text input element to fill in
|
|
1090
|
+
* @param text Text to input
|
|
1091
|
+
* @param delay Length of time to wait (ms) before executing action
|
|
1092
|
+
*/
|
|
1118
1093
|
fillTextInput(target, text, delay = 0) {
|
|
1119
1094
|
if (delay > 0) {
|
|
1120
1095
|
this.setJsPsychTimeout(() => {
|
|
@@ -1124,6 +1099,12 @@ var jsPsychModule = (function (exports) {
|
|
|
1124
1099
|
target.value = text;
|
|
1125
1100
|
}
|
|
1126
1101
|
}
|
|
1102
|
+
/**
|
|
1103
|
+
* Picks a valid key from `choices`, taking into account jsPsych-specific
|
|
1104
|
+
* identifiers like "NO_KEYS" and "ALL_KEYS".
|
|
1105
|
+
* @param choices Which keys are valid.
|
|
1106
|
+
* @returns A key selected at random from the valid keys.
|
|
1107
|
+
*/
|
|
1127
1108
|
getValidKey(choices) {
|
|
1128
1109
|
const possible_keys = [
|
|
1129
1110
|
"a",
|
|
@@ -1214,39 +1195,1017 @@ var jsPsychModule = (function (exports) {
|
|
|
1214
1195
|
}
|
|
1215
1196
|
}
|
|
1216
1197
|
|
|
1217
|
-
class TimeoutAPI {
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1198
|
+
class TimeoutAPI {
|
|
1199
|
+
constructor() {
|
|
1200
|
+
this.timeout_handlers = [];
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Calls a function after a specified delay, in milliseconds.
|
|
1204
|
+
* @param callback The function to call after the delay.
|
|
1205
|
+
* @param delay The number of milliseconds to wait before calling the function.
|
|
1206
|
+
* @returns A handle that can be used to clear the timeout with clearTimeout.
|
|
1207
|
+
*/
|
|
1208
|
+
setTimeout(callback, delay) {
|
|
1209
|
+
const handle = window.setTimeout(callback, delay);
|
|
1210
|
+
this.timeout_handlers.push(handle);
|
|
1211
|
+
return handle;
|
|
1212
|
+
}
|
|
1213
|
+
/**
|
|
1214
|
+
* Clears all timeouts that have been created with setTimeout.
|
|
1215
|
+
*/
|
|
1216
|
+
clearAllTimeouts() {
|
|
1217
|
+
for (const handler of this.timeout_handlers) {
|
|
1218
|
+
clearTimeout(handler);
|
|
1219
|
+
}
|
|
1220
|
+
this.timeout_handlers = [];
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
function createJointPluginAPIObject(jsPsych) {
|
|
1225
|
+
const settings = jsPsych.getInitSettings();
|
|
1226
|
+
const keyboardListenerAPI = new KeyboardListenerAPI(
|
|
1227
|
+
jsPsych.getDisplayContainerElement,
|
|
1228
|
+
settings.case_sensitive_responses,
|
|
1229
|
+
settings.minimum_valid_rt
|
|
1230
|
+
);
|
|
1231
|
+
const timeoutAPI = new TimeoutAPI();
|
|
1232
|
+
const mediaAPI = new MediaAPI(settings.use_webaudio);
|
|
1233
|
+
const simulationAPI = new SimulationAPI(
|
|
1234
|
+
jsPsych.getDisplayContainerElement,
|
|
1235
|
+
timeoutAPI.setTimeout.bind(timeoutAPI)
|
|
1236
|
+
);
|
|
1237
|
+
return Object.assign(
|
|
1238
|
+
{},
|
|
1239
|
+
...[keyboardListenerAPI, timeoutAPI, mediaAPI, simulationAPI].map((object) => autoBind$1(object))
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
var alea$1 = {exports: {}};
|
|
1244
|
+
|
|
1245
|
+
alea$1.exports;
|
|
1246
|
+
|
|
1247
|
+
(function (module) {
|
|
1248
|
+
// A port of an algorithm by Johannes Baagøe <baagoe@baagoe.com>, 2010
|
|
1249
|
+
// http://baagoe.com/en/RandomMusings/javascript/
|
|
1250
|
+
// https://github.com/nquinlan/better-random-numbers-for-javascript-mirror
|
|
1251
|
+
// Original work is under MIT license -
|
|
1252
|
+
|
|
1253
|
+
// Copyright (C) 2010 by Johannes Baagøe <baagoe@baagoe.org>
|
|
1254
|
+
//
|
|
1255
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1256
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
1257
|
+
// in the Software without restriction, including without limitation the rights
|
|
1258
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
1259
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
1260
|
+
// furnished to do so, subject to the following conditions:
|
|
1261
|
+
//
|
|
1262
|
+
// The above copyright notice and this permission notice shall be included in
|
|
1263
|
+
// all copies or substantial portions of the Software.
|
|
1264
|
+
//
|
|
1265
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1266
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1267
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1268
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1269
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
1270
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
1271
|
+
// THE SOFTWARE.
|
|
1272
|
+
|
|
1273
|
+
|
|
1274
|
+
|
|
1275
|
+
(function(global, module, define) {
|
|
1276
|
+
|
|
1277
|
+
function Alea(seed) {
|
|
1278
|
+
var me = this, mash = Mash();
|
|
1279
|
+
|
|
1280
|
+
me.next = function() {
|
|
1281
|
+
var t = 2091639 * me.s0 + me.c * 2.3283064365386963e-10; // 2^-32
|
|
1282
|
+
me.s0 = me.s1;
|
|
1283
|
+
me.s1 = me.s2;
|
|
1284
|
+
return me.s2 = t - (me.c = t | 0);
|
|
1285
|
+
};
|
|
1286
|
+
|
|
1287
|
+
// Apply the seeding algorithm from Baagoe.
|
|
1288
|
+
me.c = 1;
|
|
1289
|
+
me.s0 = mash(' ');
|
|
1290
|
+
me.s1 = mash(' ');
|
|
1291
|
+
me.s2 = mash(' ');
|
|
1292
|
+
me.s0 -= mash(seed);
|
|
1293
|
+
if (me.s0 < 0) { me.s0 += 1; }
|
|
1294
|
+
me.s1 -= mash(seed);
|
|
1295
|
+
if (me.s1 < 0) { me.s1 += 1; }
|
|
1296
|
+
me.s2 -= mash(seed);
|
|
1297
|
+
if (me.s2 < 0) { me.s2 += 1; }
|
|
1298
|
+
mash = null;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
function copy(f, t) {
|
|
1302
|
+
t.c = f.c;
|
|
1303
|
+
t.s0 = f.s0;
|
|
1304
|
+
t.s1 = f.s1;
|
|
1305
|
+
t.s2 = f.s2;
|
|
1306
|
+
return t;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
function impl(seed, opts) {
|
|
1310
|
+
var xg = new Alea(seed),
|
|
1311
|
+
state = opts && opts.state,
|
|
1312
|
+
prng = xg.next;
|
|
1313
|
+
prng.int32 = function() { return (xg.next() * 0x100000000) | 0; };
|
|
1314
|
+
prng.double = function() {
|
|
1315
|
+
return prng() + (prng() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
|
|
1316
|
+
};
|
|
1317
|
+
prng.quick = prng;
|
|
1318
|
+
if (state) {
|
|
1319
|
+
if (typeof(state) == 'object') copy(state, xg);
|
|
1320
|
+
prng.state = function() { return copy(xg, {}); };
|
|
1321
|
+
}
|
|
1322
|
+
return prng;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
function Mash() {
|
|
1326
|
+
var n = 0xefc8249d;
|
|
1327
|
+
|
|
1328
|
+
var mash = function(data) {
|
|
1329
|
+
data = String(data);
|
|
1330
|
+
for (var i = 0; i < data.length; i++) {
|
|
1331
|
+
n += data.charCodeAt(i);
|
|
1332
|
+
var h = 0.02519603282416938 * n;
|
|
1333
|
+
n = h >>> 0;
|
|
1334
|
+
h -= n;
|
|
1335
|
+
h *= n;
|
|
1336
|
+
n = h >>> 0;
|
|
1337
|
+
h -= n;
|
|
1338
|
+
n += h * 0x100000000; // 2^32
|
|
1339
|
+
}
|
|
1340
|
+
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
|
|
1341
|
+
};
|
|
1342
|
+
|
|
1343
|
+
return mash;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
|
|
1347
|
+
if (module && module.exports) {
|
|
1348
|
+
module.exports = impl;
|
|
1349
|
+
} else {
|
|
1350
|
+
this.alea = impl;
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
})(
|
|
1354
|
+
commonjsGlobal,
|
|
1355
|
+
module);
|
|
1356
|
+
} (alea$1));
|
|
1357
|
+
|
|
1358
|
+
var aleaExports = alea$1.exports;
|
|
1359
|
+
var seedrandom$3 = /*@__PURE__*/getDefaultExportFromCjs(aleaExports);
|
|
1360
|
+
|
|
1361
|
+
var xor128$1 = {exports: {}};
|
|
1362
|
+
|
|
1363
|
+
xor128$1.exports;
|
|
1364
|
+
|
|
1365
|
+
(function (module) {
|
|
1366
|
+
// A Javascript implementaion of the "xor128" prng algorithm by
|
|
1367
|
+
// George Marsaglia. See http://www.jstatsoft.org/v08/i14/paper
|
|
1368
|
+
|
|
1369
|
+
(function(global, module, define) {
|
|
1370
|
+
|
|
1371
|
+
function XorGen(seed) {
|
|
1372
|
+
var me = this, strseed = '';
|
|
1373
|
+
|
|
1374
|
+
me.x = 0;
|
|
1375
|
+
me.y = 0;
|
|
1376
|
+
me.z = 0;
|
|
1377
|
+
me.w = 0;
|
|
1378
|
+
|
|
1379
|
+
// Set up generator function.
|
|
1380
|
+
me.next = function() {
|
|
1381
|
+
var t = me.x ^ (me.x << 11);
|
|
1382
|
+
me.x = me.y;
|
|
1383
|
+
me.y = me.z;
|
|
1384
|
+
me.z = me.w;
|
|
1385
|
+
return me.w ^= (me.w >>> 19) ^ t ^ (t >>> 8);
|
|
1386
|
+
};
|
|
1387
|
+
|
|
1388
|
+
if (seed === (seed | 0)) {
|
|
1389
|
+
// Integer seed.
|
|
1390
|
+
me.x = seed;
|
|
1391
|
+
} else {
|
|
1392
|
+
// String seed.
|
|
1393
|
+
strseed += seed;
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
// Mix in string seed, then discard an initial batch of 64 values.
|
|
1397
|
+
for (var k = 0; k < strseed.length + 64; k++) {
|
|
1398
|
+
me.x ^= strseed.charCodeAt(k) | 0;
|
|
1399
|
+
me.next();
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
function copy(f, t) {
|
|
1404
|
+
t.x = f.x;
|
|
1405
|
+
t.y = f.y;
|
|
1406
|
+
t.z = f.z;
|
|
1407
|
+
t.w = f.w;
|
|
1408
|
+
return t;
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
function impl(seed, opts) {
|
|
1412
|
+
var xg = new XorGen(seed),
|
|
1413
|
+
state = opts && opts.state,
|
|
1414
|
+
prng = function() { return (xg.next() >>> 0) / 0x100000000; };
|
|
1415
|
+
prng.double = function() {
|
|
1416
|
+
do {
|
|
1417
|
+
var top = xg.next() >>> 11,
|
|
1418
|
+
bot = (xg.next() >>> 0) / 0x100000000,
|
|
1419
|
+
result = (top + bot) / (1 << 21);
|
|
1420
|
+
} while (result === 0);
|
|
1421
|
+
return result;
|
|
1422
|
+
};
|
|
1423
|
+
prng.int32 = xg.next;
|
|
1424
|
+
prng.quick = prng;
|
|
1425
|
+
if (state) {
|
|
1426
|
+
if (typeof(state) == 'object') copy(state, xg);
|
|
1427
|
+
prng.state = function() { return copy(xg, {}); };
|
|
1428
|
+
}
|
|
1429
|
+
return prng;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
if (module && module.exports) {
|
|
1433
|
+
module.exports = impl;
|
|
1434
|
+
} else {
|
|
1435
|
+
this.xor128 = impl;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
})(
|
|
1439
|
+
commonjsGlobal,
|
|
1440
|
+
module);
|
|
1441
|
+
} (xor128$1));
|
|
1442
|
+
|
|
1443
|
+
var xor128Exports = xor128$1.exports;
|
|
1444
|
+
|
|
1445
|
+
var xorwow$1 = {exports: {}};
|
|
1446
|
+
|
|
1447
|
+
xorwow$1.exports;
|
|
1448
|
+
|
|
1449
|
+
(function (module) {
|
|
1450
|
+
// A Javascript implementaion of the "xorwow" prng algorithm by
|
|
1451
|
+
// George Marsaglia. See http://www.jstatsoft.org/v08/i14/paper
|
|
1452
|
+
|
|
1453
|
+
(function(global, module, define) {
|
|
1454
|
+
|
|
1455
|
+
function XorGen(seed) {
|
|
1456
|
+
var me = this, strseed = '';
|
|
1457
|
+
|
|
1458
|
+
// Set up generator function.
|
|
1459
|
+
me.next = function() {
|
|
1460
|
+
var t = (me.x ^ (me.x >>> 2));
|
|
1461
|
+
me.x = me.y; me.y = me.z; me.z = me.w; me.w = me.v;
|
|
1462
|
+
return (me.d = (me.d + 362437 | 0)) +
|
|
1463
|
+
(me.v = (me.v ^ (me.v << 4)) ^ (t ^ (t << 1))) | 0;
|
|
1464
|
+
};
|
|
1465
|
+
|
|
1466
|
+
me.x = 0;
|
|
1467
|
+
me.y = 0;
|
|
1468
|
+
me.z = 0;
|
|
1469
|
+
me.w = 0;
|
|
1470
|
+
me.v = 0;
|
|
1471
|
+
|
|
1472
|
+
if (seed === (seed | 0)) {
|
|
1473
|
+
// Integer seed.
|
|
1474
|
+
me.x = seed;
|
|
1475
|
+
} else {
|
|
1476
|
+
// String seed.
|
|
1477
|
+
strseed += seed;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
// Mix in string seed, then discard an initial batch of 64 values.
|
|
1481
|
+
for (var k = 0; k < strseed.length + 64; k++) {
|
|
1482
|
+
me.x ^= strseed.charCodeAt(k) | 0;
|
|
1483
|
+
if (k == strseed.length) {
|
|
1484
|
+
me.d = me.x << 10 ^ me.x >>> 4;
|
|
1485
|
+
}
|
|
1486
|
+
me.next();
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
function copy(f, t) {
|
|
1491
|
+
t.x = f.x;
|
|
1492
|
+
t.y = f.y;
|
|
1493
|
+
t.z = f.z;
|
|
1494
|
+
t.w = f.w;
|
|
1495
|
+
t.v = f.v;
|
|
1496
|
+
t.d = f.d;
|
|
1497
|
+
return t;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
function impl(seed, opts) {
|
|
1501
|
+
var xg = new XorGen(seed),
|
|
1502
|
+
state = opts && opts.state,
|
|
1503
|
+
prng = function() { return (xg.next() >>> 0) / 0x100000000; };
|
|
1504
|
+
prng.double = function() {
|
|
1505
|
+
do {
|
|
1506
|
+
var top = xg.next() >>> 11,
|
|
1507
|
+
bot = (xg.next() >>> 0) / 0x100000000,
|
|
1508
|
+
result = (top + bot) / (1 << 21);
|
|
1509
|
+
} while (result === 0);
|
|
1510
|
+
return result;
|
|
1511
|
+
};
|
|
1512
|
+
prng.int32 = xg.next;
|
|
1513
|
+
prng.quick = prng;
|
|
1514
|
+
if (state) {
|
|
1515
|
+
if (typeof(state) == 'object') copy(state, xg);
|
|
1516
|
+
prng.state = function() { return copy(xg, {}); };
|
|
1517
|
+
}
|
|
1518
|
+
return prng;
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
if (module && module.exports) {
|
|
1522
|
+
module.exports = impl;
|
|
1523
|
+
} else {
|
|
1524
|
+
this.xorwow = impl;
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
})(
|
|
1528
|
+
commonjsGlobal,
|
|
1529
|
+
module);
|
|
1530
|
+
} (xorwow$1));
|
|
1531
|
+
|
|
1532
|
+
var xorwowExports = xorwow$1.exports;
|
|
1533
|
+
|
|
1534
|
+
var xorshift7$1 = {exports: {}};
|
|
1535
|
+
|
|
1536
|
+
xorshift7$1.exports;
|
|
1537
|
+
|
|
1538
|
+
(function (module) {
|
|
1539
|
+
// A Javascript implementaion of the "xorshift7" algorithm by
|
|
1540
|
+
// François Panneton and Pierre L'ecuyer:
|
|
1541
|
+
// "On the Xorgshift Random Number Generators"
|
|
1542
|
+
// http://saluc.engr.uconn.edu/refs/crypto/rng/panneton05onthexorshift.pdf
|
|
1543
|
+
|
|
1544
|
+
(function(global, module, define) {
|
|
1545
|
+
|
|
1546
|
+
function XorGen(seed) {
|
|
1547
|
+
var me = this;
|
|
1548
|
+
|
|
1549
|
+
// Set up generator function.
|
|
1550
|
+
me.next = function() {
|
|
1551
|
+
// Update xor generator.
|
|
1552
|
+
var X = me.x, i = me.i, t, v;
|
|
1553
|
+
t = X[i]; t ^= (t >>> 7); v = t ^ (t << 24);
|
|
1554
|
+
t = X[(i + 1) & 7]; v ^= t ^ (t >>> 10);
|
|
1555
|
+
t = X[(i + 3) & 7]; v ^= t ^ (t >>> 3);
|
|
1556
|
+
t = X[(i + 4) & 7]; v ^= t ^ (t << 7);
|
|
1557
|
+
t = X[(i + 7) & 7]; t = t ^ (t << 13); v ^= t ^ (t << 9);
|
|
1558
|
+
X[i] = v;
|
|
1559
|
+
me.i = (i + 1) & 7;
|
|
1560
|
+
return v;
|
|
1561
|
+
};
|
|
1562
|
+
|
|
1563
|
+
function init(me, seed) {
|
|
1564
|
+
var j, X = [];
|
|
1565
|
+
|
|
1566
|
+
if (seed === (seed | 0)) {
|
|
1567
|
+
// Seed state array using a 32-bit integer.
|
|
1568
|
+
X[0] = seed;
|
|
1569
|
+
} else {
|
|
1570
|
+
// Seed state using a string.
|
|
1571
|
+
seed = '' + seed;
|
|
1572
|
+
for (j = 0; j < seed.length; ++j) {
|
|
1573
|
+
X[j & 7] = (X[j & 7] << 15) ^
|
|
1574
|
+
(seed.charCodeAt(j) + X[(j + 1) & 7] << 13);
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
// Enforce an array length of 8, not all zeroes.
|
|
1578
|
+
while (X.length < 8) X.push(0);
|
|
1579
|
+
for (j = 0; j < 8 && X[j] === 0; ++j);
|
|
1580
|
+
if (j == 8) X[7] = -1; else X[j];
|
|
1581
|
+
|
|
1582
|
+
me.x = X;
|
|
1583
|
+
me.i = 0;
|
|
1584
|
+
|
|
1585
|
+
// Discard an initial 256 values.
|
|
1586
|
+
for (j = 256; j > 0; --j) {
|
|
1587
|
+
me.next();
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
init(me, seed);
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
function copy(f, t) {
|
|
1595
|
+
t.x = f.x.slice();
|
|
1596
|
+
t.i = f.i;
|
|
1597
|
+
return t;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
function impl(seed, opts) {
|
|
1601
|
+
if (seed == null) seed = +(new Date);
|
|
1602
|
+
var xg = new XorGen(seed),
|
|
1603
|
+
state = opts && opts.state,
|
|
1604
|
+
prng = function() { return (xg.next() >>> 0) / 0x100000000; };
|
|
1605
|
+
prng.double = function() {
|
|
1606
|
+
do {
|
|
1607
|
+
var top = xg.next() >>> 11,
|
|
1608
|
+
bot = (xg.next() >>> 0) / 0x100000000,
|
|
1609
|
+
result = (top + bot) / (1 << 21);
|
|
1610
|
+
} while (result === 0);
|
|
1611
|
+
return result;
|
|
1612
|
+
};
|
|
1613
|
+
prng.int32 = xg.next;
|
|
1614
|
+
prng.quick = prng;
|
|
1615
|
+
if (state) {
|
|
1616
|
+
if (state.x) copy(state, xg);
|
|
1617
|
+
prng.state = function() { return copy(xg, {}); };
|
|
1618
|
+
}
|
|
1619
|
+
return prng;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
if (module && module.exports) {
|
|
1623
|
+
module.exports = impl;
|
|
1624
|
+
} else {
|
|
1625
|
+
this.xorshift7 = impl;
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
})(
|
|
1629
|
+
commonjsGlobal,
|
|
1630
|
+
module);
|
|
1631
|
+
} (xorshift7$1));
|
|
1632
|
+
|
|
1633
|
+
var xorshift7Exports = xorshift7$1.exports;
|
|
1634
|
+
|
|
1635
|
+
var xor4096$1 = {exports: {}};
|
|
1636
|
+
|
|
1637
|
+
xor4096$1.exports;
|
|
1638
|
+
|
|
1639
|
+
(function (module) {
|
|
1640
|
+
// A Javascript implementaion of Richard Brent's Xorgens xor4096 algorithm.
|
|
1641
|
+
//
|
|
1642
|
+
// This fast non-cryptographic random number generator is designed for
|
|
1643
|
+
// use in Monte-Carlo algorithms. It combines a long-period xorshift
|
|
1644
|
+
// generator with a Weyl generator, and it passes all common batteries
|
|
1645
|
+
// of stasticial tests for randomness while consuming only a few nanoseconds
|
|
1646
|
+
// for each prng generated. For background on the generator, see Brent's
|
|
1647
|
+
// paper: "Some long-period random number generators using shifts and xors."
|
|
1648
|
+
// http://arxiv.org/pdf/1004.3115v1.pdf
|
|
1649
|
+
//
|
|
1650
|
+
// Usage:
|
|
1651
|
+
//
|
|
1652
|
+
// var xor4096 = require('xor4096');
|
|
1653
|
+
// random = xor4096(1); // Seed with int32 or string.
|
|
1654
|
+
// assert.equal(random(), 0.1520436450538547); // (0, 1) range, 53 bits.
|
|
1655
|
+
// assert.equal(random.int32(), 1806534897); // signed int32, 32 bits.
|
|
1656
|
+
//
|
|
1657
|
+
// For nonzero numeric keys, this impelementation provides a sequence
|
|
1658
|
+
// identical to that by Brent's xorgens 3 implementaion in C. This
|
|
1659
|
+
// implementation also provides for initalizing the generator with
|
|
1660
|
+
// string seeds, or for saving and restoring the state of the generator.
|
|
1661
|
+
//
|
|
1662
|
+
// On Chrome, this prng benchmarks about 2.1 times slower than
|
|
1663
|
+
// Javascript's built-in Math.random().
|
|
1664
|
+
|
|
1665
|
+
(function(global, module, define) {
|
|
1666
|
+
|
|
1667
|
+
function XorGen(seed) {
|
|
1668
|
+
var me = this;
|
|
1669
|
+
|
|
1670
|
+
// Set up generator function.
|
|
1671
|
+
me.next = function() {
|
|
1672
|
+
var w = me.w,
|
|
1673
|
+
X = me.X, i = me.i, t, v;
|
|
1674
|
+
// Update Weyl generator.
|
|
1675
|
+
me.w = w = (w + 0x61c88647) | 0;
|
|
1676
|
+
// Update xor generator.
|
|
1677
|
+
v = X[(i + 34) & 127];
|
|
1678
|
+
t = X[i = ((i + 1) & 127)];
|
|
1679
|
+
v ^= v << 13;
|
|
1680
|
+
t ^= t << 17;
|
|
1681
|
+
v ^= v >>> 15;
|
|
1682
|
+
t ^= t >>> 12;
|
|
1683
|
+
// Update Xor generator array state.
|
|
1684
|
+
v = X[i] = v ^ t;
|
|
1685
|
+
me.i = i;
|
|
1686
|
+
// Result is the combination.
|
|
1687
|
+
return (v + (w ^ (w >>> 16))) | 0;
|
|
1688
|
+
};
|
|
1689
|
+
|
|
1690
|
+
function init(me, seed) {
|
|
1691
|
+
var t, v, i, j, w, X = [], limit = 128;
|
|
1692
|
+
if (seed === (seed | 0)) {
|
|
1693
|
+
// Numeric seeds initialize v, which is used to generates X.
|
|
1694
|
+
v = seed;
|
|
1695
|
+
seed = null;
|
|
1696
|
+
} else {
|
|
1697
|
+
// String seeds are mixed into v and X one character at a time.
|
|
1698
|
+
seed = seed + '\0';
|
|
1699
|
+
v = 0;
|
|
1700
|
+
limit = Math.max(limit, seed.length);
|
|
1701
|
+
}
|
|
1702
|
+
// Initialize circular array and weyl value.
|
|
1703
|
+
for (i = 0, j = -32; j < limit; ++j) {
|
|
1704
|
+
// Put the unicode characters into the array, and shuffle them.
|
|
1705
|
+
if (seed) v ^= seed.charCodeAt((j + 32) % seed.length);
|
|
1706
|
+
// After 32 shuffles, take v as the starting w value.
|
|
1707
|
+
if (j === 0) w = v;
|
|
1708
|
+
v ^= v << 10;
|
|
1709
|
+
v ^= v >>> 15;
|
|
1710
|
+
v ^= v << 4;
|
|
1711
|
+
v ^= v >>> 13;
|
|
1712
|
+
if (j >= 0) {
|
|
1713
|
+
w = (w + 0x61c88647) | 0; // Weyl.
|
|
1714
|
+
t = (X[j & 127] ^= (v + w)); // Combine xor and weyl to init array.
|
|
1715
|
+
i = (0 == t) ? i + 1 : 0; // Count zeroes.
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
// We have detected all zeroes; make the key nonzero.
|
|
1719
|
+
if (i >= 128) {
|
|
1720
|
+
X[(seed && seed.length || 0) & 127] = -1;
|
|
1721
|
+
}
|
|
1722
|
+
// Run the generator 512 times to further mix the state before using it.
|
|
1723
|
+
// Factoring this as a function slows the main generator, so it is just
|
|
1724
|
+
// unrolled here. The weyl generator is not advanced while warming up.
|
|
1725
|
+
i = 127;
|
|
1726
|
+
for (j = 4 * 128; j > 0; --j) {
|
|
1727
|
+
v = X[(i + 34) & 127];
|
|
1728
|
+
t = X[i = ((i + 1) & 127)];
|
|
1729
|
+
v ^= v << 13;
|
|
1730
|
+
t ^= t << 17;
|
|
1731
|
+
v ^= v >>> 15;
|
|
1732
|
+
t ^= t >>> 12;
|
|
1733
|
+
X[i] = v ^ t;
|
|
1734
|
+
}
|
|
1735
|
+
// Storing state as object members is faster than using closure variables.
|
|
1736
|
+
me.w = w;
|
|
1737
|
+
me.X = X;
|
|
1738
|
+
me.i = i;
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
init(me, seed);
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
function copy(f, t) {
|
|
1745
|
+
t.i = f.i;
|
|
1746
|
+
t.w = f.w;
|
|
1747
|
+
t.X = f.X.slice();
|
|
1748
|
+
return t;
|
|
1749
|
+
}
|
|
1750
|
+
function impl(seed, opts) {
|
|
1751
|
+
if (seed == null) seed = +(new Date);
|
|
1752
|
+
var xg = new XorGen(seed),
|
|
1753
|
+
state = opts && opts.state,
|
|
1754
|
+
prng = function() { return (xg.next() >>> 0) / 0x100000000; };
|
|
1755
|
+
prng.double = function() {
|
|
1756
|
+
do {
|
|
1757
|
+
var top = xg.next() >>> 11,
|
|
1758
|
+
bot = (xg.next() >>> 0) / 0x100000000,
|
|
1759
|
+
result = (top + bot) / (1 << 21);
|
|
1760
|
+
} while (result === 0);
|
|
1761
|
+
return result;
|
|
1762
|
+
};
|
|
1763
|
+
prng.int32 = xg.next;
|
|
1764
|
+
prng.quick = prng;
|
|
1765
|
+
if (state) {
|
|
1766
|
+
if (state.X) copy(state, xg);
|
|
1767
|
+
prng.state = function() { return copy(xg, {}); };
|
|
1768
|
+
}
|
|
1769
|
+
return prng;
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
if (module && module.exports) {
|
|
1773
|
+
module.exports = impl;
|
|
1774
|
+
} else {
|
|
1775
|
+
this.xor4096 = impl;
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
})(
|
|
1779
|
+
commonjsGlobal, // window object or global
|
|
1780
|
+
module);
|
|
1781
|
+
} (xor4096$1));
|
|
1782
|
+
|
|
1783
|
+
var xor4096Exports = xor4096$1.exports;
|
|
1784
|
+
|
|
1785
|
+
var tychei$1 = {exports: {}};
|
|
1786
|
+
|
|
1787
|
+
tychei$1.exports;
|
|
1788
|
+
|
|
1789
|
+
(function (module) {
|
|
1790
|
+
// A Javascript implementaion of the "Tyche-i" prng algorithm by
|
|
1791
|
+
// Samuel Neves and Filipe Araujo.
|
|
1792
|
+
// See https://eden.dei.uc.pt/~sneves/pubs/2011-snfa2.pdf
|
|
1793
|
+
|
|
1794
|
+
(function(global, module, define) {
|
|
1795
|
+
|
|
1796
|
+
function XorGen(seed) {
|
|
1797
|
+
var me = this, strseed = '';
|
|
1798
|
+
|
|
1799
|
+
// Set up generator function.
|
|
1800
|
+
me.next = function() {
|
|
1801
|
+
var b = me.b, c = me.c, d = me.d, a = me.a;
|
|
1802
|
+
b = (b << 25) ^ (b >>> 7) ^ c;
|
|
1803
|
+
c = (c - d) | 0;
|
|
1804
|
+
d = (d << 24) ^ (d >>> 8) ^ a;
|
|
1805
|
+
a = (a - b) | 0;
|
|
1806
|
+
me.b = b = (b << 20) ^ (b >>> 12) ^ c;
|
|
1807
|
+
me.c = c = (c - d) | 0;
|
|
1808
|
+
me.d = (d << 16) ^ (c >>> 16) ^ a;
|
|
1809
|
+
return me.a = (a - b) | 0;
|
|
1810
|
+
};
|
|
1811
|
+
|
|
1812
|
+
/* The following is non-inverted tyche, which has better internal
|
|
1813
|
+
* bit diffusion, but which is about 25% slower than tyche-i in JS.
|
|
1814
|
+
me.next = function() {
|
|
1815
|
+
var a = me.a, b = me.b, c = me.c, d = me.d;
|
|
1816
|
+
a = (me.a + me.b | 0) >>> 0;
|
|
1817
|
+
d = me.d ^ a; d = d << 16 ^ d >>> 16;
|
|
1818
|
+
c = me.c + d | 0;
|
|
1819
|
+
b = me.b ^ c; b = b << 12 ^ d >>> 20;
|
|
1820
|
+
me.a = a = a + b | 0;
|
|
1821
|
+
d = d ^ a; me.d = d = d << 8 ^ d >>> 24;
|
|
1822
|
+
me.c = c = c + d | 0;
|
|
1823
|
+
b = b ^ c;
|
|
1824
|
+
return me.b = (b << 7 ^ b >>> 25);
|
|
1825
|
+
}
|
|
1826
|
+
*/
|
|
1827
|
+
|
|
1828
|
+
me.a = 0;
|
|
1829
|
+
me.b = 0;
|
|
1830
|
+
me.c = 2654435769 | 0;
|
|
1831
|
+
me.d = 1367130551;
|
|
1832
|
+
|
|
1833
|
+
if (seed === Math.floor(seed)) {
|
|
1834
|
+
// Integer seed.
|
|
1835
|
+
me.a = (seed / 0x100000000) | 0;
|
|
1836
|
+
me.b = seed | 0;
|
|
1837
|
+
} else {
|
|
1838
|
+
// String seed.
|
|
1839
|
+
strseed += seed;
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
// Mix in string seed, then discard an initial batch of 64 values.
|
|
1843
|
+
for (var k = 0; k < strseed.length + 20; k++) {
|
|
1844
|
+
me.b ^= strseed.charCodeAt(k) | 0;
|
|
1845
|
+
me.next();
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
function copy(f, t) {
|
|
1850
|
+
t.a = f.a;
|
|
1851
|
+
t.b = f.b;
|
|
1852
|
+
t.c = f.c;
|
|
1853
|
+
t.d = f.d;
|
|
1854
|
+
return t;
|
|
1855
|
+
}
|
|
1856
|
+
function impl(seed, opts) {
|
|
1857
|
+
var xg = new XorGen(seed),
|
|
1858
|
+
state = opts && opts.state,
|
|
1859
|
+
prng = function() { return (xg.next() >>> 0) / 0x100000000; };
|
|
1860
|
+
prng.double = function() {
|
|
1861
|
+
do {
|
|
1862
|
+
var top = xg.next() >>> 11,
|
|
1863
|
+
bot = (xg.next() >>> 0) / 0x100000000,
|
|
1864
|
+
result = (top + bot) / (1 << 21);
|
|
1865
|
+
} while (result === 0);
|
|
1866
|
+
return result;
|
|
1867
|
+
};
|
|
1868
|
+
prng.int32 = xg.next;
|
|
1869
|
+
prng.quick = prng;
|
|
1870
|
+
if (state) {
|
|
1871
|
+
if (typeof(state) == 'object') copy(state, xg);
|
|
1872
|
+
prng.state = function() { return copy(xg, {}); };
|
|
1873
|
+
}
|
|
1874
|
+
return prng;
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
if (module && module.exports) {
|
|
1878
|
+
module.exports = impl;
|
|
1879
|
+
} else {
|
|
1880
|
+
this.tychei = impl;
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
})(
|
|
1884
|
+
commonjsGlobal,
|
|
1885
|
+
module);
|
|
1886
|
+
} (tychei$1));
|
|
1887
|
+
|
|
1888
|
+
var tycheiExports = tychei$1.exports;
|
|
1889
|
+
|
|
1890
|
+
var seedrandom$2 = {exports: {}};
|
|
1891
|
+
|
|
1892
|
+
/*
|
|
1893
|
+
Copyright 2019 David Bau.
|
|
1894
|
+
|
|
1895
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
1896
|
+
a copy of this software and associated documentation files (the
|
|
1897
|
+
"Software"), to deal in the Software without restriction, including
|
|
1898
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
1899
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
1900
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
1901
|
+
the following conditions:
|
|
1902
|
+
|
|
1903
|
+
The above copyright notice and this permission notice shall be
|
|
1904
|
+
included in all copies or substantial portions of the Software.
|
|
1905
|
+
|
|
1906
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
1907
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
1908
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
1909
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
1910
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
1911
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
1912
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1231
1913
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1914
|
+
*/
|
|
1915
|
+
|
|
1916
|
+
(function (module) {
|
|
1917
|
+
(function (global, pool, math) {
|
|
1918
|
+
//
|
|
1919
|
+
// The following constants are related to IEEE 754 limits.
|
|
1920
|
+
//
|
|
1921
|
+
|
|
1922
|
+
var width = 256, // each RC4 output is 0 <= x < 256
|
|
1923
|
+
chunks = 6, // at least six RC4 outputs for each double
|
|
1924
|
+
digits = 52, // there are 52 significant digits in a double
|
|
1925
|
+
rngname = 'random', // rngname: name for Math.random and Math.seedrandom
|
|
1926
|
+
startdenom = math.pow(width, chunks),
|
|
1927
|
+
significance = math.pow(2, digits),
|
|
1928
|
+
overflow = significance * 2,
|
|
1929
|
+
mask = width - 1,
|
|
1930
|
+
nodecrypto; // node.js crypto module, initialized at the bottom.
|
|
1931
|
+
|
|
1932
|
+
//
|
|
1933
|
+
// seedrandom()
|
|
1934
|
+
// This is the seedrandom function described above.
|
|
1935
|
+
//
|
|
1936
|
+
function seedrandom(seed, options, callback) {
|
|
1937
|
+
var key = [];
|
|
1938
|
+
options = (options == true) ? { entropy: true } : (options || {});
|
|
1939
|
+
|
|
1940
|
+
// Flatten the seed string or build one from local entropy if needed.
|
|
1941
|
+
var shortseed = mixkey(flatten(
|
|
1942
|
+
options.entropy ? [seed, tostring(pool)] :
|
|
1943
|
+
(seed == null) ? autoseed() : seed, 3), key);
|
|
1944
|
+
|
|
1945
|
+
// Use the seed to initialize an ARC4 generator.
|
|
1946
|
+
var arc4 = new ARC4(key);
|
|
1947
|
+
|
|
1948
|
+
// This function returns a random double in [0, 1) that contains
|
|
1949
|
+
// randomness in every bit of the mantissa of the IEEE 754 value.
|
|
1950
|
+
var prng = function() {
|
|
1951
|
+
var n = arc4.g(chunks), // Start with a numerator n < 2 ^ 48
|
|
1952
|
+
d = startdenom, // and denominator d = 2 ^ 48.
|
|
1953
|
+
x = 0; // and no 'extra last byte'.
|
|
1954
|
+
while (n < significance) { // Fill up all significant digits by
|
|
1955
|
+
n = (n + x) * width; // shifting numerator and
|
|
1956
|
+
d *= width; // denominator and generating a
|
|
1957
|
+
x = arc4.g(1); // new least-significant-byte.
|
|
1958
|
+
}
|
|
1959
|
+
while (n >= overflow) { // To avoid rounding up, before adding
|
|
1960
|
+
n /= 2; // last byte, shift everything
|
|
1961
|
+
d /= 2; // right using integer math until
|
|
1962
|
+
x >>>= 1; // we have exactly the desired bits.
|
|
1963
|
+
}
|
|
1964
|
+
return (n + x) / d; // Form the number within [0, 1).
|
|
1965
|
+
};
|
|
1966
|
+
|
|
1967
|
+
prng.int32 = function() { return arc4.g(4) | 0; };
|
|
1968
|
+
prng.quick = function() { return arc4.g(4) / 0x100000000; };
|
|
1969
|
+
prng.double = prng;
|
|
1970
|
+
|
|
1971
|
+
// Mix the randomness into accumulated entropy.
|
|
1972
|
+
mixkey(tostring(arc4.S), pool);
|
|
1973
|
+
|
|
1974
|
+
// Calling convention: what to return as a function of prng, seed, is_math.
|
|
1975
|
+
return (options.pass || callback ||
|
|
1976
|
+
function(prng, seed, is_math_call, state) {
|
|
1977
|
+
if (state) {
|
|
1978
|
+
// Load the arc4 state from the given state if it has an S array.
|
|
1979
|
+
if (state.S) { copy(state, arc4); }
|
|
1980
|
+
// Only provide the .state method if requested via options.state.
|
|
1981
|
+
prng.state = function() { return copy(arc4, {}); };
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
// If called as a method of Math (Math.seedrandom()), mutate
|
|
1985
|
+
// Math.random because that is how seedrandom.js has worked since v1.0.
|
|
1986
|
+
if (is_math_call) { math[rngname] = prng; return seed; }
|
|
1987
|
+
|
|
1988
|
+
// Otherwise, it is a newer calling convention, so return the
|
|
1989
|
+
// prng directly.
|
|
1990
|
+
else return prng;
|
|
1991
|
+
})(
|
|
1992
|
+
prng,
|
|
1993
|
+
shortseed,
|
|
1994
|
+
'global' in options ? options.global : (this == math),
|
|
1995
|
+
options.state);
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
//
|
|
1999
|
+
// ARC4
|
|
2000
|
+
//
|
|
2001
|
+
// An ARC4 implementation. The constructor takes a key in the form of
|
|
2002
|
+
// an array of at most (width) integers that should be 0 <= x < (width).
|
|
2003
|
+
//
|
|
2004
|
+
// The g(count) method returns a pseudorandom integer that concatenates
|
|
2005
|
+
// the next (count) outputs from ARC4. Its return value is a number x
|
|
2006
|
+
// that is in the range 0 <= x < (width ^ count).
|
|
2007
|
+
//
|
|
2008
|
+
function ARC4(key) {
|
|
2009
|
+
var t, keylen = key.length,
|
|
2010
|
+
me = this, i = 0, j = me.i = me.j = 0, s = me.S = [];
|
|
2011
|
+
|
|
2012
|
+
// The empty key [] is treated as [0].
|
|
2013
|
+
if (!keylen) { key = [keylen++]; }
|
|
2014
|
+
|
|
2015
|
+
// Set up S using the standard key scheduling algorithm.
|
|
2016
|
+
while (i < width) {
|
|
2017
|
+
s[i] = i++;
|
|
2018
|
+
}
|
|
2019
|
+
for (i = 0; i < width; i++) {
|
|
2020
|
+
s[i] = s[j = mask & (j + key[i % keylen] + (t = s[i]))];
|
|
2021
|
+
s[j] = t;
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
// The "g" method returns the next (count) outputs as one number.
|
|
2025
|
+
(me.g = function(count) {
|
|
2026
|
+
// Using instance members instead of closure state nearly doubles speed.
|
|
2027
|
+
var t, r = 0,
|
|
2028
|
+
i = me.i, j = me.j, s = me.S;
|
|
2029
|
+
while (count--) {
|
|
2030
|
+
t = s[i = mask & (i + 1)];
|
|
2031
|
+
r = r * width + s[mask & ((s[i] = s[j = mask & (j + t)]) + (s[j] = t))];
|
|
2032
|
+
}
|
|
2033
|
+
me.i = i; me.j = j;
|
|
2034
|
+
return r;
|
|
2035
|
+
// For robust unpredictability, the function call below automatically
|
|
2036
|
+
// discards an initial batch of values. This is called RC4-drop[256].
|
|
2037
|
+
// See http://google.com/search?q=rsa+fluhrer+response&btnI
|
|
2038
|
+
})(width);
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
//
|
|
2042
|
+
// copy()
|
|
2043
|
+
// Copies internal state of ARC4 to or from a plain object.
|
|
2044
|
+
//
|
|
2045
|
+
function copy(f, t) {
|
|
2046
|
+
t.i = f.i;
|
|
2047
|
+
t.j = f.j;
|
|
2048
|
+
t.S = f.S.slice();
|
|
2049
|
+
return t;
|
|
2050
|
+
}
|
|
2051
|
+
//
|
|
2052
|
+
// flatten()
|
|
2053
|
+
// Converts an object tree to nested arrays of strings.
|
|
2054
|
+
//
|
|
2055
|
+
function flatten(obj, depth) {
|
|
2056
|
+
var result = [], typ = (typeof obj), prop;
|
|
2057
|
+
if (depth && typ == 'object') {
|
|
2058
|
+
for (prop in obj) {
|
|
2059
|
+
try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {}
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
return (result.length ? result : typ == 'string' ? obj : obj + '\0');
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
//
|
|
2066
|
+
// mixkey()
|
|
2067
|
+
// Mixes a string seed into a key that is an array of integers, and
|
|
2068
|
+
// returns a shortened string seed that is equivalent to the result key.
|
|
2069
|
+
//
|
|
2070
|
+
function mixkey(seed, key) {
|
|
2071
|
+
var stringseed = seed + '', smear, j = 0;
|
|
2072
|
+
while (j < stringseed.length) {
|
|
2073
|
+
key[mask & j] =
|
|
2074
|
+
mask & ((smear ^= key[mask & j] * 19) + stringseed.charCodeAt(j++));
|
|
2075
|
+
}
|
|
2076
|
+
return tostring(key);
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
//
|
|
2080
|
+
// autoseed()
|
|
2081
|
+
// Returns an object for autoseeding, using window.crypto and Node crypto
|
|
2082
|
+
// module if available.
|
|
2083
|
+
//
|
|
2084
|
+
function autoseed() {
|
|
2085
|
+
try {
|
|
2086
|
+
var out;
|
|
2087
|
+
if (nodecrypto && (out = nodecrypto.randomBytes)) {
|
|
2088
|
+
// The use of 'out' to remember randomBytes makes tight minified code.
|
|
2089
|
+
out = out(width);
|
|
2090
|
+
} else {
|
|
2091
|
+
out = new Uint8Array(width);
|
|
2092
|
+
(global.crypto || global.msCrypto).getRandomValues(out);
|
|
2093
|
+
}
|
|
2094
|
+
return tostring(out);
|
|
2095
|
+
} catch (e) {
|
|
2096
|
+
var browser = global.navigator,
|
|
2097
|
+
plugins = browser && browser.plugins;
|
|
2098
|
+
return [+new Date, global, plugins, global.screen, tostring(pool)];
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
//
|
|
2103
|
+
// tostring()
|
|
2104
|
+
// Converts an array of charcodes to a string
|
|
2105
|
+
//
|
|
2106
|
+
function tostring(a) {
|
|
2107
|
+
return String.fromCharCode.apply(0, a);
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
//
|
|
2111
|
+
// When seedrandom.js is loaded, we immediately mix a few bits
|
|
2112
|
+
// from the built-in RNG into the entropy pool. Because we do
|
|
2113
|
+
// not want to interfere with deterministic PRNG state later,
|
|
2114
|
+
// seedrandom will not call math.random on its own again after
|
|
2115
|
+
// initialization.
|
|
2116
|
+
//
|
|
2117
|
+
mixkey(math.random(), pool);
|
|
2118
|
+
|
|
2119
|
+
//
|
|
2120
|
+
// Nodejs and AMD support: export the implementation as a module using
|
|
2121
|
+
// either convention.
|
|
2122
|
+
//
|
|
2123
|
+
if (module.exports) {
|
|
2124
|
+
module.exports = seedrandom;
|
|
2125
|
+
// When in node.js, try using crypto package for autoseeding.
|
|
2126
|
+
try {
|
|
2127
|
+
nodecrypto = require('crypto');
|
|
2128
|
+
} catch (ex) {}
|
|
2129
|
+
} else {
|
|
2130
|
+
// When included as a plain script, set up Math.seedrandom global.
|
|
2131
|
+
math['seed' + rngname] = seedrandom;
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
|
|
2135
|
+
// End anonymous scope, and pass initial values.
|
|
2136
|
+
})(
|
|
2137
|
+
// global: `self` in browsers (including strict mode and web workers),
|
|
2138
|
+
// otherwise `this` in Node and other environments
|
|
2139
|
+
(typeof self !== 'undefined') ? self : commonjsGlobal,
|
|
2140
|
+
[], // pool: entropy pool starts empty
|
|
2141
|
+
Math // math: package containing random, pow, and seedrandom
|
|
2142
|
+
);
|
|
2143
|
+
} (seedrandom$2));
|
|
2144
|
+
|
|
2145
|
+
var seedrandomExports = seedrandom$2.exports;
|
|
2146
|
+
|
|
2147
|
+
// A library of seedable RNGs implemented in Javascript.
|
|
2148
|
+
//
|
|
2149
|
+
// Usage:
|
|
2150
|
+
//
|
|
2151
|
+
// var seedrandom = require('seedrandom');
|
|
2152
|
+
// var random = seedrandom(1); // or any seed.
|
|
2153
|
+
// var x = random(); // 0 <= x < 1. Every bit is random.
|
|
2154
|
+
// var x = random.quick(); // 0 <= x < 1. 32 bits of randomness.
|
|
2155
|
+
|
|
2156
|
+
// alea, a 53-bit multiply-with-carry generator by Johannes Baagøe.
|
|
2157
|
+
// Period: ~2^116
|
|
2158
|
+
// Reported to pass all BigCrush tests.
|
|
2159
|
+
var alea = aleaExports;
|
|
2160
|
+
|
|
2161
|
+
// xor128, a pure xor-shift generator by George Marsaglia.
|
|
2162
|
+
// Period: 2^128-1.
|
|
2163
|
+
// Reported to fail: MatrixRank and LinearComp.
|
|
2164
|
+
var xor128 = xor128Exports;
|
|
2165
|
+
|
|
2166
|
+
// xorwow, George Marsaglia's 160-bit xor-shift combined plus weyl.
|
|
2167
|
+
// Period: 2^192-2^32
|
|
2168
|
+
// Reported to fail: CollisionOver, SimpPoker, and LinearComp.
|
|
2169
|
+
var xorwow = xorwowExports;
|
|
2170
|
+
|
|
2171
|
+
// xorshift7, by François Panneton and Pierre L'ecuyer, takes
|
|
2172
|
+
// a different approach: it adds robustness by allowing more shifts
|
|
2173
|
+
// than Marsaglia's original three. It is a 7-shift generator
|
|
2174
|
+
// with 256 bits, that passes BigCrush with no systmatic failures.
|
|
2175
|
+
// Period 2^256-1.
|
|
2176
|
+
// No systematic BigCrush failures reported.
|
|
2177
|
+
var xorshift7 = xorshift7Exports;
|
|
2178
|
+
|
|
2179
|
+
// xor4096, by Richard Brent, is a 4096-bit xor-shift with a
|
|
2180
|
+
// very long period that also adds a Weyl generator. It also passes
|
|
2181
|
+
// BigCrush with no systematic failures. Its long period may
|
|
2182
|
+
// be useful if you have many generators and need to avoid
|
|
2183
|
+
// collisions.
|
|
2184
|
+
// Period: 2^4128-2^32.
|
|
2185
|
+
// No systematic BigCrush failures reported.
|
|
2186
|
+
var xor4096 = xor4096Exports;
|
|
2187
|
+
|
|
2188
|
+
// Tyche-i, by Samuel Neves and Filipe Araujo, is a bit-shifting random
|
|
2189
|
+
// number generator derived from ChaCha, a modern stream cipher.
|
|
2190
|
+
// https://eden.dei.uc.pt/~sneves/pubs/2011-snfa2.pdf
|
|
2191
|
+
// Period: ~2^127
|
|
2192
|
+
// No systematic BigCrush failures reported.
|
|
2193
|
+
var tychei = tycheiExports;
|
|
2194
|
+
|
|
2195
|
+
// The original ARC4-based prng included in this library.
|
|
2196
|
+
// Period: ~2^1600
|
|
2197
|
+
var sr = seedrandomExports;
|
|
2198
|
+
|
|
2199
|
+
sr.alea = alea;
|
|
2200
|
+
sr.xor128 = xor128;
|
|
2201
|
+
sr.xorwow = xorwow;
|
|
2202
|
+
sr.xorshift7 = xorshift7;
|
|
2203
|
+
sr.xor4096 = xor4096;
|
|
2204
|
+
sr.tychei = tychei;
|
|
2205
|
+
|
|
2206
|
+
var seedrandom$1 = sr;
|
|
2207
|
+
|
|
2208
|
+
var seedrandom = seedrandom$1;
|
|
1250
2209
|
|
|
1251
2210
|
var wordList = [
|
|
1252
2211
|
// Borrowed from xkcd password generator which borrowed it from wherever
|
|
@@ -1497,6 +2456,8 @@ var jsPsychModule = (function (exports) {
|
|
|
1497
2456
|
];
|
|
1498
2457
|
|
|
1499
2458
|
function words(options) {
|
|
2459
|
+
// initalize random number generator for words if options.seed is provided
|
|
2460
|
+
const random = options?.seed ? new seedrandom(options.seed) : null;
|
|
1500
2461
|
|
|
1501
2462
|
function word() {
|
|
1502
2463
|
if (options && options.maxLength > 1) {
|
|
@@ -1523,8 +2484,10 @@ var jsPsychModule = (function (exports) {
|
|
|
1523
2484
|
return wordList[randInt(wordList.length)];
|
|
1524
2485
|
}
|
|
1525
2486
|
|
|
2487
|
+
// random int as seeded by options.seed if applicable, or Math.random() otherwise
|
|
1526
2488
|
function randInt(lessThan) {
|
|
1527
|
-
|
|
2489
|
+
const r = random ? random() : Math.random();
|
|
2490
|
+
return Math.floor(r * lessThan);
|
|
1528
2491
|
}
|
|
1529
2492
|
|
|
1530
2493
|
// No arguments = generate one word
|
|
@@ -1591,130 +2554,8 @@ var jsPsychModule = (function (exports) {
|
|
|
1591
2554
|
|
|
1592
2555
|
var rw = /*@__PURE__*/getDefaultExportFromCjs(randomWords$1);
|
|
1593
2556
|
|
|
1594
|
-
var alea = {exports: {}};
|
|
1595
|
-
|
|
1596
|
-
alea.exports;
|
|
1597
|
-
|
|
1598
|
-
(function (module) {
|
|
1599
|
-
// A port of an algorithm by Johannes Baagøe <baagoe@baagoe.com>, 2010
|
|
1600
|
-
// http://baagoe.com/en/RandomMusings/javascript/
|
|
1601
|
-
// https://github.com/nquinlan/better-random-numbers-for-javascript-mirror
|
|
1602
|
-
// Original work is under MIT license -
|
|
1603
|
-
|
|
1604
|
-
// Copyright (C) 2010 by Johannes Baagøe <baagoe@baagoe.org>
|
|
1605
|
-
//
|
|
1606
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1607
|
-
// of this software and associated documentation files (the "Software"), to deal
|
|
1608
|
-
// in the Software without restriction, including without limitation the rights
|
|
1609
|
-
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
1610
|
-
// copies of the Software, and to permit persons to whom the Software is
|
|
1611
|
-
// furnished to do so, subject to the following conditions:
|
|
1612
|
-
//
|
|
1613
|
-
// The above copyright notice and this permission notice shall be included in
|
|
1614
|
-
// all copies or substantial portions of the Software.
|
|
1615
|
-
//
|
|
1616
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1617
|
-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1618
|
-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1619
|
-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1620
|
-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
1621
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
1622
|
-
// THE SOFTWARE.
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
(function(global, module, define) {
|
|
1627
|
-
|
|
1628
|
-
function Alea(seed) {
|
|
1629
|
-
var me = this, mash = Mash();
|
|
1630
|
-
|
|
1631
|
-
me.next = function() {
|
|
1632
|
-
var t = 2091639 * me.s0 + me.c * 2.3283064365386963e-10; // 2^-32
|
|
1633
|
-
me.s0 = me.s1;
|
|
1634
|
-
me.s1 = me.s2;
|
|
1635
|
-
return me.s2 = t - (me.c = t | 0);
|
|
1636
|
-
};
|
|
1637
|
-
|
|
1638
|
-
// Apply the seeding algorithm from Baagoe.
|
|
1639
|
-
me.c = 1;
|
|
1640
|
-
me.s0 = mash(' ');
|
|
1641
|
-
me.s1 = mash(' ');
|
|
1642
|
-
me.s2 = mash(' ');
|
|
1643
|
-
me.s0 -= mash(seed);
|
|
1644
|
-
if (me.s0 < 0) { me.s0 += 1; }
|
|
1645
|
-
me.s1 -= mash(seed);
|
|
1646
|
-
if (me.s1 < 0) { me.s1 += 1; }
|
|
1647
|
-
me.s2 -= mash(seed);
|
|
1648
|
-
if (me.s2 < 0) { me.s2 += 1; }
|
|
1649
|
-
mash = null;
|
|
1650
|
-
}
|
|
1651
|
-
|
|
1652
|
-
function copy(f, t) {
|
|
1653
|
-
t.c = f.c;
|
|
1654
|
-
t.s0 = f.s0;
|
|
1655
|
-
t.s1 = f.s1;
|
|
1656
|
-
t.s2 = f.s2;
|
|
1657
|
-
return t;
|
|
1658
|
-
}
|
|
1659
|
-
|
|
1660
|
-
function impl(seed, opts) {
|
|
1661
|
-
var xg = new Alea(seed),
|
|
1662
|
-
state = opts && opts.state,
|
|
1663
|
-
prng = xg.next;
|
|
1664
|
-
prng.int32 = function() { return (xg.next() * 0x100000000) | 0; };
|
|
1665
|
-
prng.double = function() {
|
|
1666
|
-
return prng() + (prng() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
|
|
1667
|
-
};
|
|
1668
|
-
prng.quick = prng;
|
|
1669
|
-
if (state) {
|
|
1670
|
-
if (typeof(state) == 'object') copy(state, xg);
|
|
1671
|
-
prng.state = function() { return copy(xg, {}); };
|
|
1672
|
-
}
|
|
1673
|
-
return prng;
|
|
1674
|
-
}
|
|
1675
|
-
|
|
1676
|
-
function Mash() {
|
|
1677
|
-
var n = 0xefc8249d;
|
|
1678
|
-
|
|
1679
|
-
var mash = function(data) {
|
|
1680
|
-
data = String(data);
|
|
1681
|
-
for (var i = 0; i < data.length; i++) {
|
|
1682
|
-
n += data.charCodeAt(i);
|
|
1683
|
-
var h = 0.02519603282416938 * n;
|
|
1684
|
-
n = h >>> 0;
|
|
1685
|
-
h -= n;
|
|
1686
|
-
h *= n;
|
|
1687
|
-
n = h >>> 0;
|
|
1688
|
-
h -= n;
|
|
1689
|
-
n += h * 0x100000000; // 2^32
|
|
1690
|
-
}
|
|
1691
|
-
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
|
|
1692
|
-
};
|
|
1693
|
-
|
|
1694
|
-
return mash;
|
|
1695
|
-
}
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
if (module && module.exports) {
|
|
1699
|
-
module.exports = impl;
|
|
1700
|
-
} else if (define && define.amd) {
|
|
1701
|
-
define(function() { return impl; });
|
|
1702
|
-
} else {
|
|
1703
|
-
this.alea = impl;
|
|
1704
|
-
}
|
|
1705
|
-
|
|
1706
|
-
})(
|
|
1707
|
-
commonjsGlobal,
|
|
1708
|
-
module, // present in node.js
|
|
1709
|
-
(typeof undefined) == 'function' // present with an AMD loader
|
|
1710
|
-
);
|
|
1711
|
-
} (alea));
|
|
1712
|
-
|
|
1713
|
-
var aleaExports = alea.exports;
|
|
1714
|
-
var seedrandom = /*@__PURE__*/getDefaultExportFromCjs(aleaExports);
|
|
1715
|
-
|
|
1716
2557
|
function setSeed(seed = Math.random().toString()) {
|
|
1717
|
-
Math.random = seedrandom(seed);
|
|
2558
|
+
Math.random = seedrandom$3(seed);
|
|
1718
2559
|
return seed;
|
|
1719
2560
|
}
|
|
1720
2561
|
function repeat(array, repetitions, unpack = false) {
|
|
@@ -1940,10 +2781,8 @@ var jsPsychModule = (function (exports) {
|
|
|
1940
2781
|
}
|
|
1941
2782
|
function randn_bm() {
|
|
1942
2783
|
var u = 0, v = 0;
|
|
1943
|
-
while (u === 0)
|
|
1944
|
-
|
|
1945
|
-
while (v === 0)
|
|
1946
|
-
v = Math.random();
|
|
2784
|
+
while (u === 0) u = Math.random();
|
|
2785
|
+
while (v === 0) v = Math.random();
|
|
1947
2786
|
return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
|
|
1948
2787
|
}
|
|
1949
2788
|
function unpackArray(array) {
|
|
@@ -1961,21 +2800,21 @@ var jsPsychModule = (function (exports) {
|
|
|
1961
2800
|
|
|
1962
2801
|
var randomization = /*#__PURE__*/Object.freeze({
|
|
1963
2802
|
__proto__: null,
|
|
1964
|
-
setSeed: setSeed,
|
|
1965
|
-
repeat: repeat,
|
|
1966
|
-
shuffle: shuffle,
|
|
1967
|
-
shuffleNoRepeats: shuffleNoRepeats,
|
|
1968
|
-
shuffleAlternateGroups: shuffleAlternateGroups,
|
|
1969
|
-
sampleWithoutReplacement: sampleWithoutReplacement,
|
|
1970
|
-
sampleWithReplacement: sampleWithReplacement,
|
|
1971
2803
|
factorial: factorial,
|
|
1972
2804
|
randomID: randomID,
|
|
1973
2805
|
randomInt: randomInt,
|
|
2806
|
+
randomWords: randomWords,
|
|
2807
|
+
repeat: repeat,
|
|
1974
2808
|
sampleBernoulli: sampleBernoulli,
|
|
1975
|
-
sampleNormal: sampleNormal,
|
|
1976
|
-
sampleExponential: sampleExponential,
|
|
1977
2809
|
sampleExGaussian: sampleExGaussian,
|
|
1978
|
-
|
|
2810
|
+
sampleExponential: sampleExponential,
|
|
2811
|
+
sampleNormal: sampleNormal,
|
|
2812
|
+
sampleWithReplacement: sampleWithReplacement,
|
|
2813
|
+
sampleWithoutReplacement: sampleWithoutReplacement,
|
|
2814
|
+
setSeed: setSeed,
|
|
2815
|
+
shuffle: shuffle,
|
|
2816
|
+
shuffleAlternateGroups: shuffleAlternateGroups,
|
|
2817
|
+
shuffleNoRepeats: shuffleNoRepeats
|
|
1979
2818
|
});
|
|
1980
2819
|
|
|
1981
2820
|
function turkInfo() {
|
|
@@ -2007,8 +2846,7 @@ var jsPsychModule = (function (exports) {
|
|
|
2007
2846
|
const turk = turkInfo();
|
|
2008
2847
|
const assignmentId = turk.assignmentId;
|
|
2009
2848
|
const turkSubmitTo = turk.turkSubmitTo;
|
|
2010
|
-
if (!assignmentId || !turkSubmitTo)
|
|
2011
|
-
return;
|
|
2849
|
+
if (!assignmentId || !turkSubmitTo) return;
|
|
2012
2850
|
const form = document.createElement("form");
|
|
2013
2851
|
form.method = "POST";
|
|
2014
2852
|
form.action = turkSubmitTo + "/mturk/externalSubmit?assignmentId=" + assignmentId;
|
|
@@ -2028,19 +2866,18 @@ var jsPsychModule = (function (exports) {
|
|
|
2028
2866
|
|
|
2029
2867
|
var turk = /*#__PURE__*/Object.freeze({
|
|
2030
2868
|
__proto__: null,
|
|
2031
|
-
|
|
2032
|
-
|
|
2869
|
+
submitToTurk: submitToTurk,
|
|
2870
|
+
turkInfo: turkInfo
|
|
2033
2871
|
});
|
|
2034
2872
|
|
|
2035
2873
|
class ProgressBar {
|
|
2036
2874
|
constructor(containerElement, message) {
|
|
2037
2875
|
this.containerElement = containerElement;
|
|
2038
2876
|
this.message = message;
|
|
2877
|
+
this._progress = 0;
|
|
2039
2878
|
this.setupElements();
|
|
2040
2879
|
}
|
|
2041
|
-
|
|
2042
|
-
innerDiv;
|
|
2043
|
-
messageSpan;
|
|
2880
|
+
/** Adds the progress bar HTML code into `this.containerElement` */
|
|
2044
2881
|
setupElements() {
|
|
2045
2882
|
this.messageSpan = document.createElement("span");
|
|
2046
2883
|
this.innerDiv = document.createElement("div");
|
|
@@ -2052,6 +2889,7 @@ var jsPsychModule = (function (exports) {
|
|
|
2052
2889
|
this.containerElement.appendChild(this.messageSpan);
|
|
2053
2890
|
this.containerElement.appendChild(outerDiv);
|
|
2054
2891
|
}
|
|
2892
|
+
/** Updates the progress bar according to `this.progress` */
|
|
2055
2893
|
update() {
|
|
2056
2894
|
this.innerDiv.style.width = this._progress * 100 + "%";
|
|
2057
2895
|
if (typeof this.message === "function") {
|
|
@@ -2060,6 +2898,10 @@ var jsPsychModule = (function (exports) {
|
|
|
2060
2898
|
this.messageSpan.innerHTML = this.message;
|
|
2061
2899
|
}
|
|
2062
2900
|
}
|
|
2901
|
+
/**
|
|
2902
|
+
* The bar's current position as a number in the closed interval [0, 1]. Set this to update the
|
|
2903
|
+
* progress bar accordingly.
|
|
2904
|
+
*/
|
|
2063
2905
|
set progress(progress) {
|
|
2064
2906
|
if (typeof progress !== "number" || progress < 0 || progress > 1) {
|
|
2065
2907
|
throw new Error("jsPsych.progressBar.progress must be a number between 0 and 1");
|
|
@@ -2108,8 +2950,6 @@ var jsPsychModule = (function (exports) {
|
|
|
2108
2950
|
constructor() {
|
|
2109
2951
|
this.reset();
|
|
2110
2952
|
}
|
|
2111
|
-
promise;
|
|
2112
|
-
resolvePromise;
|
|
2113
2953
|
reset() {
|
|
2114
2954
|
this.promise = new Promise((resolve) => {
|
|
2115
2955
|
this.resolvePromise = resolve;
|
|
@@ -2140,6 +2980,9 @@ var jsPsychModule = (function (exports) {
|
|
|
2140
2980
|
return typeof value === "object" && value !== null;
|
|
2141
2981
|
}
|
|
2142
2982
|
class ParameterObjectPathCache {
|
|
2983
|
+
constructor() {
|
|
2984
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
2985
|
+
}
|
|
2143
2986
|
static lookupChild(objectOrArray, childName) {
|
|
2144
2987
|
let doesPathExist = false;
|
|
2145
2988
|
let childValue;
|
|
@@ -2156,16 +2999,12 @@ var jsPsychModule = (function (exports) {
|
|
|
2156
2999
|
}
|
|
2157
3000
|
return { doesPathExist, value: childValue };
|
|
2158
3001
|
}
|
|
2159
|
-
cache = /* @__PURE__ */ new Map();
|
|
2160
|
-
rootObject;
|
|
2161
3002
|
get(path) {
|
|
2162
3003
|
return this.cache.get(path.join("."));
|
|
2163
3004
|
}
|
|
2164
3005
|
has(path) {
|
|
2165
3006
|
return this.cache.has(path.join("."));
|
|
2166
3007
|
}
|
|
2167
|
-
constructor() {
|
|
2168
|
-
}
|
|
2169
3008
|
initialize(rootObject) {
|
|
2170
3009
|
this.rootObject = rootObject;
|
|
2171
3010
|
this.cache.set("", rootObject);
|
|
@@ -2206,20 +3045,42 @@ var jsPsychModule = (function (exports) {
|
|
|
2206
3045
|
class TimelineNode {
|
|
2207
3046
|
constructor(dependencies) {
|
|
2208
3047
|
this.dependencies = dependencies;
|
|
3048
|
+
this.status = TimelineNodeStatus.PENDING;
|
|
3049
|
+
this.parameterValueCache = new ParameterObjectPathCache();
|
|
2209
3050
|
}
|
|
2210
|
-
index;
|
|
2211
|
-
status = TimelineNodeStatus.PENDING;
|
|
2212
3051
|
getStatus() {
|
|
2213
3052
|
return this.status;
|
|
2214
3053
|
}
|
|
2215
|
-
|
|
3054
|
+
/**
|
|
3055
|
+
* Initializes the parameter value cache with `this.description`. To be called by subclass
|
|
3056
|
+
* constructors after setting `this.description`.
|
|
3057
|
+
*/
|
|
2216
3058
|
initializeParameterValueCache() {
|
|
2217
3059
|
this.parameterValueCache.initialize(this.description);
|
|
2218
3060
|
}
|
|
3061
|
+
/**
|
|
3062
|
+
* Resets all cached parameter values in this timeline node and all of its parents. This is
|
|
3063
|
+
* necessary to re-evaluate function parameters and timeline variables at each new trial.
|
|
3064
|
+
*/
|
|
2219
3065
|
resetParameterValueCache() {
|
|
2220
3066
|
this.parameterValueCache.reset();
|
|
2221
3067
|
this.parent?.resetParameterValueCache();
|
|
2222
3068
|
}
|
|
3069
|
+
/**
|
|
3070
|
+
* Retrieves a parameter value from the description of this timeline node, recursively falling
|
|
3071
|
+
* back to the description of each parent timeline node unless `recursive` is set to `false`. If
|
|
3072
|
+
* the parameter...
|
|
3073
|
+
*
|
|
3074
|
+
* * is a timeline variable, evaluates the variable and returns the result.
|
|
3075
|
+
* * is not specified, returns `undefined`.
|
|
3076
|
+
* * is a function and `evaluateFunctions` is not set to `false`, invokes the function and returns
|
|
3077
|
+
* its return value
|
|
3078
|
+
* * has previously been looked up, return the cached result of the previous lookup
|
|
3079
|
+
*
|
|
3080
|
+
* @param parameterPath The path of the respective parameter in the timeline node description. If
|
|
3081
|
+
* the path is an array, nested object properties or array items will be looked up.
|
|
3082
|
+
* @param options See {@link GetParameterValueOptions}
|
|
3083
|
+
*/
|
|
2223
3084
|
getParameterValue(parameterPath, options = {}) {
|
|
2224
3085
|
const {
|
|
2225
3086
|
evaluateFunctions = true,
|
|
@@ -2248,6 +3109,11 @@ var jsPsychModule = (function (exports) {
|
|
|
2248
3109
|
}
|
|
2249
3110
|
return result;
|
|
2250
3111
|
}
|
|
3112
|
+
/**
|
|
3113
|
+
* Retrieves and evaluates the `data` parameter. It is different from other parameters in that
|
|
3114
|
+
* it's properties may be functions that have to be evaluated, and parent nodes' data parameter
|
|
3115
|
+
* properties are merged into the result.
|
|
3116
|
+
*/
|
|
2251
3117
|
getDataParameter() {
|
|
2252
3118
|
const data = this.getParameterValue("data", { recursive: false });
|
|
2253
3119
|
return {
|
|
@@ -2264,10 +3130,19 @@ var jsPsychModule = (function (exports) {
|
|
|
2264
3130
|
super(dependencies);
|
|
2265
3131
|
this.description = description;
|
|
2266
3132
|
this.parent = parent;
|
|
3133
|
+
this.onLoad = () => {
|
|
3134
|
+
this.runParameterCallback("on_load");
|
|
3135
|
+
this.dependencies.runOnLoadExtensionCallbacks(this.getParameterValue("extensions"));
|
|
3136
|
+
};
|
|
2267
3137
|
this.initializeParameterValueCache();
|
|
2268
3138
|
this.trialObject = deepCopy(description);
|
|
2269
3139
|
this.pluginClass = this.getParameterValue("type", { evaluateFunctions: false });
|
|
2270
|
-
this.pluginInfo = this.pluginClass["info"];
|
|
3140
|
+
this.pluginInfo = this.pluginClass?.["info"];
|
|
3141
|
+
if (!this.pluginInfo) {
|
|
3142
|
+
throw new Error(
|
|
3143
|
+
"Plugin not recognized. Please provide a valid plugin using the 'type' parameter."
|
|
3144
|
+
);
|
|
3145
|
+
}
|
|
2271
3146
|
if (!("version" in this.pluginInfo) && !("data" in this.pluginInfo)) {
|
|
2272
3147
|
console.warn(
|
|
2273
3148
|
this.pluginInfo["name"],
|
|
@@ -2285,12 +3160,6 @@ var jsPsychModule = (function (exports) {
|
|
|
2285
3160
|
);
|
|
2286
3161
|
}
|
|
2287
3162
|
}
|
|
2288
|
-
pluginClass;
|
|
2289
|
-
pluginInstance;
|
|
2290
|
-
trialObject;
|
|
2291
|
-
index;
|
|
2292
|
-
result;
|
|
2293
|
-
pluginInfo;
|
|
2294
3163
|
async run() {
|
|
2295
3164
|
this.status = TimelineNodeStatus.RUNNING;
|
|
2296
3165
|
this.processParameters();
|
|
@@ -2355,10 +3224,16 @@ var jsPsychModule = (function (exports) {
|
|
|
2355
3224
|
)
|
|
2356
3225
|
};
|
|
2357
3226
|
}
|
|
3227
|
+
/**
|
|
3228
|
+
* Cleanup the trial by removing the display element and removing event listeners
|
|
3229
|
+
*/
|
|
2358
3230
|
cleanupTrial() {
|
|
2359
3231
|
this.dependencies.clearAllTimeouts();
|
|
2360
3232
|
this.dependencies.getDisplayElement().innerHTML = "";
|
|
2361
3233
|
}
|
|
3234
|
+
/**
|
|
3235
|
+
* Add the CSS classes from the `css_classes` parameter to the display element
|
|
3236
|
+
*/
|
|
2362
3237
|
addCssClasses() {
|
|
2363
3238
|
const classes = this.getParameterValue("css_classes");
|
|
2364
3239
|
const classList = this.dependencies.getDisplayElement().classList;
|
|
@@ -2368,6 +3243,9 @@ var jsPsychModule = (function (exports) {
|
|
|
2368
3243
|
classList.add(...classes);
|
|
2369
3244
|
}
|
|
2370
3245
|
}
|
|
3246
|
+
/**
|
|
3247
|
+
* Removes the provided css classes from the display element
|
|
3248
|
+
*/
|
|
2371
3249
|
removeCssClasses() {
|
|
2372
3250
|
const classes = this.getParameterValue("css_classes");
|
|
2373
3251
|
if (classes) {
|
|
@@ -2416,6 +3294,12 @@ var jsPsychModule = (function (exports) {
|
|
|
2416
3294
|
}
|
|
2417
3295
|
return result;
|
|
2418
3296
|
}
|
|
3297
|
+
/**
|
|
3298
|
+
* Runs a callback function retrieved from a parameter value and returns its result.
|
|
3299
|
+
*
|
|
3300
|
+
* @param parameterName The name of the parameter to retrieve the callback function from.
|
|
3301
|
+
* @param callbackParameters The parameters (if any) to be passed to the callback function
|
|
3302
|
+
*/
|
|
2419
3303
|
runParameterCallback(parameterName, ...callbackParameters) {
|
|
2420
3304
|
const callback = this.getParameterValue(parameterName, { evaluateFunctions: false });
|
|
2421
3305
|
if (callback) {
|
|
@@ -2427,10 +3311,6 @@ var jsPsychModule = (function (exports) {
|
|
|
2427
3311
|
this.runParameterCallback("on_start", this.trialObject);
|
|
2428
3312
|
this.dependencies.runOnStartExtensionCallbacks(this.getParameterValue("extensions"));
|
|
2429
3313
|
}
|
|
2430
|
-
onLoad = () => {
|
|
2431
|
-
this.runParameterCallback("on_load");
|
|
2432
|
-
this.dependencies.runOnLoadExtensionCallbacks(this.getParameterValue("extensions"));
|
|
2433
|
-
};
|
|
2434
3314
|
async onFinish() {
|
|
2435
3315
|
const extensionResults = await this.dependencies.runOnFinishExtensionCallbacks(
|
|
2436
3316
|
this.getParameterValue("extensions")
|
|
@@ -2450,6 +3330,10 @@ var jsPsychModule = (function (exports) {
|
|
|
2450
3330
|
}
|
|
2451
3331
|
return super.getParameterValue(parameterPath, options);
|
|
2452
3332
|
}
|
|
3333
|
+
/**
|
|
3334
|
+
* Retrieves and evaluates the `simulation_options` parameter, considering nested properties and
|
|
3335
|
+
* global simulation options.
|
|
3336
|
+
*/
|
|
2453
3337
|
getSimulationOptions() {
|
|
2454
3338
|
const simulationOptions = this.getParameterValue("simulation_options", {
|
|
2455
3339
|
replaceResult: (result = {}) => {
|
|
@@ -2479,6 +3363,10 @@ var jsPsychModule = (function (exports) {
|
|
|
2479
3363
|
}
|
|
2480
3364
|
return simulationOptions;
|
|
2481
3365
|
}
|
|
3366
|
+
/**
|
|
3367
|
+
* Returns the result object of this trial or `undefined` if the result is not yet known or the
|
|
3368
|
+
* `record_data` trial parameter is `false`.
|
|
3369
|
+
*/
|
|
2482
3370
|
getResult() {
|
|
2483
3371
|
return this.getParameterValue("record_data") === false ? void 0 : this.result;
|
|
2484
3372
|
}
|
|
@@ -2486,6 +3374,12 @@ var jsPsychModule = (function (exports) {
|
|
|
2486
3374
|
const result = this.getResult();
|
|
2487
3375
|
return result ? [result] : [];
|
|
2488
3376
|
}
|
|
3377
|
+
/**
|
|
3378
|
+
* Checks that the parameters provided in the trial description align with the plugin's info
|
|
3379
|
+
* object, resolves missing parameter values from the parent timeline, resolves timeline variable
|
|
3380
|
+
* parameters, evaluates parameter functions if the expected parameter type is not `FUNCTION`, and
|
|
3381
|
+
* sets default values for optional parameters.
|
|
3382
|
+
*/
|
|
2489
3383
|
processParameters() {
|
|
2490
3384
|
const assignParameterValues = (parameterObject, parameterInfos, parentParameterPath = []) => {
|
|
2491
3385
|
for (const [parameterName, parameterConfig] of Object.entries(parameterInfos)) {
|
|
@@ -2545,13 +3439,12 @@ var jsPsychModule = (function (exports) {
|
|
|
2545
3439
|
constructor(dependencies, description, parent) {
|
|
2546
3440
|
super(dependencies);
|
|
2547
3441
|
this.parent = parent;
|
|
3442
|
+
this.children = [];
|
|
3443
|
+
this.shouldAbort = false;
|
|
3444
|
+
this.resumePromise = new PromiseWrapper();
|
|
2548
3445
|
this.description = Array.isArray(description) ? { timeline: description } : description;
|
|
2549
3446
|
this.initializeParameterValueCache();
|
|
2550
3447
|
}
|
|
2551
|
-
children = [];
|
|
2552
|
-
description;
|
|
2553
|
-
currentChild;
|
|
2554
|
-
shouldAbort = false;
|
|
2555
3448
|
async run() {
|
|
2556
3449
|
if (typeof this.index === "undefined") {
|
|
2557
3450
|
this.index = 0;
|
|
@@ -2612,7 +3505,6 @@ var jsPsychModule = (function (exports) {
|
|
|
2612
3505
|
}
|
|
2613
3506
|
this.status = TimelineNodeStatus.PAUSED;
|
|
2614
3507
|
}
|
|
2615
|
-
resumePromise = new PromiseWrapper();
|
|
2616
3508
|
resume() {
|
|
2617
3509
|
if (this.status == TimelineNodeStatus.PAUSED) {
|
|
2618
3510
|
if (this.currentChild instanceof Timeline) {
|
|
@@ -2622,6 +3514,9 @@ var jsPsychModule = (function (exports) {
|
|
|
2622
3514
|
this.resumePromise.resolve();
|
|
2623
3515
|
}
|
|
2624
3516
|
}
|
|
3517
|
+
/**
|
|
3518
|
+
* If the timeline is running or paused, aborts the timeline after the current trial has completed
|
|
3519
|
+
*/
|
|
2625
3520
|
abort() {
|
|
2626
3521
|
if (this.status === TimelineNodeStatus.RUNNING || this.status === TimelineNodeStatus.PAUSED) {
|
|
2627
3522
|
if (this.currentChild instanceof Timeline) {
|
|
@@ -2638,13 +3533,17 @@ var jsPsychModule = (function (exports) {
|
|
|
2638
3533
|
this.children.push(newChildNode);
|
|
2639
3534
|
return newChildNode;
|
|
2640
3535
|
}
|
|
2641
|
-
currentTimelineVariables;
|
|
2642
3536
|
setCurrentTimelineVariablesByIndex(index) {
|
|
2643
3537
|
this.currentTimelineVariables = {
|
|
2644
3538
|
...this.parent?.getAllTimelineVariables(),
|
|
2645
3539
|
...index === null ? void 0 : this.description.timeline_variables[index]
|
|
2646
3540
|
};
|
|
2647
3541
|
}
|
|
3542
|
+
/**
|
|
3543
|
+
* If the timeline has timeline variables, returns the order of `timeline_variables` array indices
|
|
3544
|
+
* to be used, according to the timeline's `sample` setting. If the timeline has no timeline
|
|
3545
|
+
* variables, returns `[null]`.
|
|
3546
|
+
*/
|
|
2648
3547
|
generateTimelineVariableOrder() {
|
|
2649
3548
|
const timelineVariableLength = this.description.timeline_variables?.length;
|
|
2650
3549
|
if (!timelineVariableLength) {
|
|
@@ -2671,7 +3570,8 @@ var jsPsychModule = (function (exports) {
|
|
|
2671
3570
|
break;
|
|
2672
3571
|
default:
|
|
2673
3572
|
throw new Error(
|
|
2674
|
-
`Invalid type "${
|
|
3573
|
+
`Invalid type "${// @ts-expect-error TS doesn't have a type for `sample` in this case
|
|
3574
|
+
sample.type}" in timeline sample parameters. Valid options for type are "custom", "with-replacement", "without-replacement", "fixed-repetitions", and "alternate-groups"`
|
|
2675
3575
|
);
|
|
2676
3576
|
}
|
|
2677
3577
|
}
|
|
@@ -2680,6 +3580,9 @@ var jsPsychModule = (function (exports) {
|
|
|
2680
3580
|
}
|
|
2681
3581
|
return order;
|
|
2682
3582
|
}
|
|
3583
|
+
/**
|
|
3584
|
+
* Returns the current values of all timeline variables, including those from parent timelines
|
|
3585
|
+
*/
|
|
2683
3586
|
getAllTimelineVariables() {
|
|
2684
3587
|
return this.currentTimelineVariables;
|
|
2685
3588
|
}
|
|
@@ -2703,6 +3606,10 @@ var jsPsychModule = (function (exports) {
|
|
|
2703
3606
|
}
|
|
2704
3607
|
return results;
|
|
2705
3608
|
}
|
|
3609
|
+
/**
|
|
3610
|
+
* Returns the naive progress of the timeline (as a fraction), without considering conditional or
|
|
3611
|
+
* loop functions.
|
|
3612
|
+
*/
|
|
2706
3613
|
getNaiveProgress() {
|
|
2707
3614
|
if (this.status === TimelineNodeStatus.PENDING) {
|
|
2708
3615
|
return 0;
|
|
@@ -2717,6 +3624,10 @@ var jsPsychModule = (function (exports) {
|
|
|
2717
3624
|
}
|
|
2718
3625
|
return Math.min(completedTrials / this.getNaiveTrialCount(), 1);
|
|
2719
3626
|
}
|
|
3627
|
+
/**
|
|
3628
|
+
* Recursively computes the naive number of trials in the timeline, without considering
|
|
3629
|
+
* conditional or loop functions.
|
|
3630
|
+
*/
|
|
2720
3631
|
getNaiveTrialCount() {
|
|
2721
3632
|
const getTrialCount = (description) => {
|
|
2722
3633
|
const getTimelineArrayTrialCount = (description2) => description2.map((childDescription) => getTrialCount(childDescription)).reduce((a, b) => a + b);
|
|
@@ -2758,24 +3669,70 @@ var jsPsychModule = (function (exports) {
|
|
|
2758
3669
|
}
|
|
2759
3670
|
|
|
2760
3671
|
class JsPsych {
|
|
2761
|
-
turk = turk;
|
|
2762
|
-
randomization = randomization;
|
|
2763
|
-
utils = utils;
|
|
2764
|
-
data;
|
|
2765
|
-
pluginAPI;
|
|
2766
|
-
version() {
|
|
2767
|
-
return _package.version;
|
|
2768
|
-
}
|
|
2769
|
-
options = {};
|
|
2770
|
-
timeline;
|
|
2771
|
-
displayContainerElement;
|
|
2772
|
-
displayElement;
|
|
2773
|
-
experimentStartTime;
|
|
2774
|
-
isFileProtocolUsed = false;
|
|
2775
|
-
simulationMode;
|
|
2776
|
-
simulationOptions;
|
|
2777
|
-
extensionManager;
|
|
2778
3672
|
constructor(options) {
|
|
3673
|
+
this.turk = turk;
|
|
3674
|
+
this.randomization = randomization;
|
|
3675
|
+
this.utils = utils;
|
|
3676
|
+
// prettier-ignore
|
|
3677
|
+
this.citation = {
|
|
3678
|
+
"apa": "de Leeuw, J. R., Gilbert, R. A., & Luchterhandt, B. (2023). jsPsych: Enabling an Open-Source Collaborative Ecosystem of Behavioral Experiments. Journal of Open Source Software, 8(85), 5351. https://doi.org/10.21105/joss.05351 ",
|
|
3679
|
+
"bibtex": '@article{Leeuw2023jsPsych, author = {de Leeuw, Joshua R. and Gilbert, Rebecca A. and Luchterhandt, Bj{\\" o}rn}, journal = {Journal of Open Source Software}, doi = {10.21105/joss.05351}, issn = {2475-9066}, number = {85}, year = {2023}, month = {may 11}, pages = {5351}, publisher = {Open Journals}, title = {jsPsych: Enabling an {Open}-{Source} {Collaborative} {Ecosystem} of {Behavioral} {Experiments}}, url = {https://joss.theoj.org/papers/10.21105/joss.05351}, volume = {8}, } '
|
|
3680
|
+
};
|
|
3681
|
+
/** Options */
|
|
3682
|
+
this.options = {};
|
|
3683
|
+
/**
|
|
3684
|
+
* Whether the page is retrieved directly via the `file://` protocol (true) or hosted on a web
|
|
3685
|
+
* server (false)
|
|
3686
|
+
*/
|
|
3687
|
+
this.isFileProtocolUsed = false;
|
|
3688
|
+
this.finishTrialPromise = new PromiseWrapper();
|
|
3689
|
+
this.timelineDependencies = {
|
|
3690
|
+
onTrialStart: (trial) => {
|
|
3691
|
+
this.options.on_trial_start(trial.trialObject);
|
|
3692
|
+
this.getDisplayContainerElement().focus();
|
|
3693
|
+
this.getDisplayElement().scrollTop = 0;
|
|
3694
|
+
},
|
|
3695
|
+
onTrialResultAvailable: (trial) => {
|
|
3696
|
+
const result = trial.getResult();
|
|
3697
|
+
if (result) {
|
|
3698
|
+
result.time_elapsed = this.getTotalTime();
|
|
3699
|
+
this.data.write(trial);
|
|
3700
|
+
}
|
|
3701
|
+
},
|
|
3702
|
+
onTrialFinished: (trial) => {
|
|
3703
|
+
const result = trial.getResult();
|
|
3704
|
+
this.options.on_trial_finish(result);
|
|
3705
|
+
if (result) {
|
|
3706
|
+
this.options.on_data_update(result);
|
|
3707
|
+
}
|
|
3708
|
+
if (this.progressBar && this.options.auto_update_progress_bar) {
|
|
3709
|
+
this.progressBar.progress = this.timeline.getNaiveProgress();
|
|
3710
|
+
}
|
|
3711
|
+
},
|
|
3712
|
+
runOnStartExtensionCallbacks: (extensionsConfiguration) => this.extensionManager.onStart(extensionsConfiguration),
|
|
3713
|
+
runOnLoadExtensionCallbacks: (extensionsConfiguration) => this.extensionManager.onLoad(extensionsConfiguration),
|
|
3714
|
+
runOnFinishExtensionCallbacks: (extensionsConfiguration) => this.extensionManager.onFinish(extensionsConfiguration),
|
|
3715
|
+
getSimulationMode: () => this.simulationMode,
|
|
3716
|
+
getGlobalSimulationOptions: () => this.simulationOptions,
|
|
3717
|
+
instantiatePlugin: (pluginClass) => new pluginClass(this),
|
|
3718
|
+
getDisplayElement: () => this.getDisplayElement(),
|
|
3719
|
+
getDefaultIti: () => this.getInitSettings().default_iti,
|
|
3720
|
+
finishTrialPromise: this.finishTrialPromise,
|
|
3721
|
+
clearAllTimeouts: () => this.pluginAPI.clearAllTimeouts()
|
|
3722
|
+
};
|
|
3723
|
+
this.extensionManagerDependencies = {
|
|
3724
|
+
instantiateExtension: (extensionClass) => new extensionClass(this)
|
|
3725
|
+
};
|
|
3726
|
+
this.dataDependencies = {
|
|
3727
|
+
getProgress: () => ({
|
|
3728
|
+
time: this.getTotalTime(),
|
|
3729
|
+
trial: this.timeline?.getLatestNode().index ?? 0
|
|
3730
|
+
}),
|
|
3731
|
+
onInteractionRecordAdded: (record) => {
|
|
3732
|
+
this.options.on_interaction_data_update(record);
|
|
3733
|
+
},
|
|
3734
|
+
getDisplayElement: () => this.getDisplayElement()
|
|
3735
|
+
};
|
|
2779
3736
|
options = {
|
|
2780
3737
|
display_element: void 0,
|
|
2781
3738
|
on_finish: () => {
|
|
@@ -2818,7 +3775,15 @@ var jsPsychModule = (function (exports) {
|
|
|
2818
3775
|
options.extensions
|
|
2819
3776
|
);
|
|
2820
3777
|
}
|
|
2821
|
-
|
|
3778
|
+
version() {
|
|
3779
|
+
return version;
|
|
3780
|
+
}
|
|
3781
|
+
/**
|
|
3782
|
+
* Starts an experiment using the provided timeline and returns a promise that is resolved when
|
|
3783
|
+
* the experiment is finished.
|
|
3784
|
+
*
|
|
3785
|
+
* @param timeline The timeline to be run
|
|
3786
|
+
*/
|
|
2822
3787
|
async run(timeline) {
|
|
2823
3788
|
if (typeof timeline === "undefined") {
|
|
2824
3789
|
console.error("No timeline declared in jsPsych.run(). Cannot start experiment.");
|
|
@@ -2832,7 +3797,7 @@ var jsPsychModule = (function (exports) {
|
|
|
2832
3797
|
await this.prepareDom();
|
|
2833
3798
|
await this.extensionManager.initializeExtensions();
|
|
2834
3799
|
document.documentElement.setAttribute("jspsych", "present");
|
|
2835
|
-
this.experimentStartTime = new Date();
|
|
3800
|
+
this.experimentStartTime = /* @__PURE__ */ new Date();
|
|
2836
3801
|
await this.timeline.run();
|
|
2837
3802
|
await Promise.resolve(this.options.on_finish(this.data.get()));
|
|
2838
3803
|
if (this.endMessage) {
|
|
@@ -2845,7 +3810,6 @@ var jsPsychModule = (function (exports) {
|
|
|
2845
3810
|
this.simulationOptions = simulation_options;
|
|
2846
3811
|
await this.run(timeline);
|
|
2847
3812
|
}
|
|
2848
|
-
progressBar;
|
|
2849
3813
|
getProgress() {
|
|
2850
3814
|
return {
|
|
2851
3815
|
total_trials: this.timeline?.getNaiveTrialCount(),
|
|
@@ -2860,7 +3824,7 @@ var jsPsychModule = (function (exports) {
|
|
|
2860
3824
|
if (!this.experimentStartTime) {
|
|
2861
3825
|
return 0;
|
|
2862
3826
|
}
|
|
2863
|
-
return new Date().getTime() - this.experimentStartTime.getTime();
|
|
3827
|
+
return (/* @__PURE__ */ new Date()).getTime() - this.experimentStartTime.getTime();
|
|
2864
3828
|
}
|
|
2865
3829
|
getDisplayElement() {
|
|
2866
3830
|
return this.displayElement;
|
|
@@ -2884,6 +3848,11 @@ var jsPsychModule = (function (exports) {
|
|
|
2884
3848
|
currentTimeline.abort();
|
|
2885
3849
|
}
|
|
2886
3850
|
}
|
|
3851
|
+
/**
|
|
3852
|
+
* Aborts a named timeline. The timeline must be currently running in order to abort it.
|
|
3853
|
+
*
|
|
3854
|
+
* @param name The name of the timeline to abort. Timelines can be given names by setting the `name` parameter in the description of the timeline.
|
|
3855
|
+
*/
|
|
2887
3856
|
abortTimelineByName(name) {
|
|
2888
3857
|
const timeline = this.timeline?.getActiveTimelineByName(name);
|
|
2889
3858
|
if (timeline) {
|
|
@@ -2918,6 +3887,36 @@ var jsPsychModule = (function (exports) {
|
|
|
2918
3887
|
getTimeline() {
|
|
2919
3888
|
return this.timeline?.description.timeline;
|
|
2920
3889
|
}
|
|
3890
|
+
/**
|
|
3891
|
+
* Prints out a string containing citations for the jsPsych library and all input plugins/extensions in the specified format.
|
|
3892
|
+
* If called without input, prints citation for jsPsych library.
|
|
3893
|
+
*
|
|
3894
|
+
* @param plugins The plugins/extensions to generate citations for. Always prints the citation for the jsPsych library at the top.
|
|
3895
|
+
* @param format The desired output citation format. Currently supports "apa" and "bibtex".
|
|
3896
|
+
* @returns String containing citations separated with newline character.
|
|
3897
|
+
*/
|
|
3898
|
+
getCitations(plugins = [], format = "apa") {
|
|
3899
|
+
const formatOptions = ["apa", "bibtex"];
|
|
3900
|
+
format = format.toLowerCase();
|
|
3901
|
+
if (!Array.isArray(plugins)) {
|
|
3902
|
+
throw new Error("Expected array of plugins/extensions");
|
|
3903
|
+
} else if (!formatOptions.includes(format)) {
|
|
3904
|
+
throw new Error("Unsupported citation format");
|
|
3905
|
+
} else {
|
|
3906
|
+
const jsPsychCitation = this.citation[format];
|
|
3907
|
+
const citationSet = /* @__PURE__ */ new Set([jsPsychCitation]);
|
|
3908
|
+
for (const plugin of plugins) {
|
|
3909
|
+
try {
|
|
3910
|
+
const pluginCitation = plugin["info"].citations[format];
|
|
3911
|
+
citationSet.add(pluginCitation);
|
|
3912
|
+
} catch {
|
|
3913
|
+
console.error(`${plugin} does not have citation in ${format} format.`);
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3916
|
+
const citationList = Array.from(citationSet).join("\n");
|
|
3917
|
+
return citationList;
|
|
3918
|
+
}
|
|
3919
|
+
}
|
|
2921
3920
|
get extensions() {
|
|
2922
3921
|
return this.extensionManager?.extensions ?? {};
|
|
2923
3922
|
}
|
|
@@ -2970,57 +3969,9 @@ var jsPsychModule = (function (exports) {
|
|
|
2970
3969
|
this.getDisplayContainerElement().insertAdjacentElement("afterbegin", progressBarContainer);
|
|
2971
3970
|
}
|
|
2972
3971
|
}
|
|
2973
|
-
finishTrialPromise = new PromiseWrapper();
|
|
2974
3972
|
finishTrial(data) {
|
|
2975
3973
|
this.finishTrialPromise.resolve(data);
|
|
2976
3974
|
}
|
|
2977
|
-
timelineDependencies = {
|
|
2978
|
-
onTrialStart: (trial) => {
|
|
2979
|
-
this.options.on_trial_start(trial.trialObject);
|
|
2980
|
-
this.getDisplayContainerElement().focus();
|
|
2981
|
-
this.getDisplayElement().scrollTop = 0;
|
|
2982
|
-
},
|
|
2983
|
-
onTrialResultAvailable: (trial) => {
|
|
2984
|
-
const result = trial.getResult();
|
|
2985
|
-
if (result) {
|
|
2986
|
-
result.time_elapsed = this.getTotalTime();
|
|
2987
|
-
this.data.write(trial);
|
|
2988
|
-
}
|
|
2989
|
-
},
|
|
2990
|
-
onTrialFinished: (trial) => {
|
|
2991
|
-
const result = trial.getResult();
|
|
2992
|
-
this.options.on_trial_finish(result);
|
|
2993
|
-
if (result) {
|
|
2994
|
-
this.options.on_data_update(result);
|
|
2995
|
-
}
|
|
2996
|
-
if (this.progressBar && this.options.auto_update_progress_bar) {
|
|
2997
|
-
this.progressBar.progress = this.timeline.getNaiveProgress();
|
|
2998
|
-
}
|
|
2999
|
-
},
|
|
3000
|
-
runOnStartExtensionCallbacks: (extensionsConfiguration) => this.extensionManager.onStart(extensionsConfiguration),
|
|
3001
|
-
runOnLoadExtensionCallbacks: (extensionsConfiguration) => this.extensionManager.onLoad(extensionsConfiguration),
|
|
3002
|
-
runOnFinishExtensionCallbacks: (extensionsConfiguration) => this.extensionManager.onFinish(extensionsConfiguration),
|
|
3003
|
-
getSimulationMode: () => this.simulationMode,
|
|
3004
|
-
getGlobalSimulationOptions: () => this.simulationOptions,
|
|
3005
|
-
instantiatePlugin: (pluginClass) => new pluginClass(this),
|
|
3006
|
-
getDisplayElement: () => this.getDisplayElement(),
|
|
3007
|
-
getDefaultIti: () => this.getInitSettings().default_iti,
|
|
3008
|
-
finishTrialPromise: this.finishTrialPromise,
|
|
3009
|
-
clearAllTimeouts: () => this.pluginAPI.clearAllTimeouts()
|
|
3010
|
-
};
|
|
3011
|
-
extensionManagerDependencies = {
|
|
3012
|
-
instantiateExtension: (extensionClass) => new extensionClass(this)
|
|
3013
|
-
};
|
|
3014
|
-
dataDependencies = {
|
|
3015
|
-
getProgress: () => ({
|
|
3016
|
-
time: this.getTotalTime(),
|
|
3017
|
-
trial: this.timeline?.getLatestNode().index ?? 0
|
|
3018
|
-
}),
|
|
3019
|
-
onInteractionRecordAdded: (record) => {
|
|
3020
|
-
this.options.on_interaction_data_update(record);
|
|
3021
|
-
},
|
|
3022
|
-
getDisplayElement: () => this.getDisplayElement()
|
|
3023
|
-
};
|
|
3024
3975
|
}
|
|
3025
3976
|
|
|
3026
3977
|
class MigrationError extends Error {
|
|
@@ -3066,6 +4017,7 @@ var jsPsychModule = (function (exports) {
|
|
|
3066
4017
|
init: "`jsPsych.init()` was replaced by `initJsPsych()` in jsPsych v7.",
|
|
3067
4018
|
ALL_KEYS: 'jsPsych.ALL_KEYS was replaced by the "ALL_KEYS" string in jsPsych v7.',
|
|
3068
4019
|
NO_KEYS: 'jsPsych.NO_KEYS was replaced by the "NO_KEYS" string in jsPsych v7.',
|
|
4020
|
+
// Getter functions that were renamed
|
|
3069
4021
|
currentTimelineNodeID: "`currentTimelineNodeID()` was renamed to `getCurrentTimelineNodeID()` in jsPsych v7.",
|
|
3070
4022
|
progress: "`progress()` was renamed to `getProgress()` in jsPsych v7.",
|
|
3071
4023
|
startTime: "`startTime()` was renamed to `getStartTime()` in jsPsych v7.",
|
|
@@ -3099,4 +4051,4 @@ var jsPsychModule = (function (exports) {
|
|
|
3099
4051
|
|
|
3100
4052
|
})({});
|
|
3101
4053
|
var initJsPsych = jsPsychModule.initJsPsych;
|
|
3102
|
-
//# sourceMappingURL=https://unpkg.com/jspsych@8.1
|
|
4054
|
+
//# sourceMappingURL=https://unpkg.com/jspsych@8.2.1/dist/index.browser.js.map
|