-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbv_test.js
440 lines (361 loc) · 27 KB
/
bv_test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
/**
// Bourdon Vos Test - Stimuli Presentation (i.e. Task)
// @author Sally A.M. Hogenboom <[email protected]>
// Version Control via Git
*/
// SET [GLOBAL] VARIABLES
var responseArray = [];
var clickArray = [];
var correctionArray = [];
var responseOrderArray = [];
var canvasIdArray = ["Canvas1"];
var evaluationArray = [];
var responseTimeArray = [];
// INITIALIZE FUNCTIONS
window.onload = stimulusPresentation ("stimuli", 5,3,3);
window.onload = startTime();
/////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// MAIN FUNCTION /////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
function stimulusPresentation (appendObject, sizeCirckel, verticalCirckles, horizontalCirckles) {
// GOAL: Fill screen with responsive canvasses containing random dot figures.
// NOTE: incoorporates all supporting functions
// appendObject: ID of the object to which the canvas should be appended
// sizeCirckel = enlarge or decrease circkel size (currently only works for value < 6)
// verticalCirckles = amount of circkles to be drawn vertically (i.e. height of grid)
// horizontalCirckles = amount of circkles to be drawn horizontally (i.e. width of grid)
// INITIALIZE VARIABLES
appendObject = appendObject;
sizeCirckel = sizeCirckel;
verticalCirckles = verticalCirckles;
horizontalCirckles = horizontalCirckles;
// window.alert("appendObject = " + appendObject + " sizeCirckel = " + sizeCirckel + " verticalCirckles = " + verticalCirckles + " horizontalCirckles = " + horizontalCirckles); // TEST
// CALL firstCanvas to create 1st figure >> sets subsequent sizes
var dots1 = firstCanvas(appendObject, sizeCirckel, verticalCirckles, horizontalCirckles);
// window.alert("amount of dots in figure 1 = " + dots1); // TEST
// CALL maxFigures to determine how many figures to create + present
var totalFigures = maxFigures();
// window.alert("amount of figures to present = " + totalFigures); // TEST
// CREATE clickArray to log order of mouseclicks
clickArray = [];
for (y = 0; y < totalFigures; y++) { clickArray.push(0); } // for each canvas start amount of clicks at 0
// window.alert("ensure click array contains 0: " + clickArray); // TEST
// window.alert("ensure length of 0's = " + clickArray.length + " = " + totalFigures); // TEST
// CALL dotArray to calculate amount of 3/4/5 dot figures (balanced) and randomize order of presentation
dotsArray = randomizeDots(totalFigures, dots1, 3, 5);
// LOOP to fill screen with max amount of responsive figures
for (z = 2; z < (totalFigures +1); z++) { // start at 2 because first canvas was already created
var ID = "Canvas" + z; // Change .id for each newly created canvas
canvasIdArray.push(ID); // store number for later reference to canvasIDs
createCanvas (appendObject, ID, evaluationArray); // call upon createCanvas (see below) to create responsive canvas
var dots = dotsArray[z-2]; // -2 because index starts at 0
randomFigure (ID, 10,10,sizeCirckel, horizontalCirckles, verticalCirckles, dots); // call upon randomFigure (see below) to create random dot figure
} // END FOR LOOP
} // END stimulusPresentation FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// SUPPORTING FUNCTIONS ////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function getRandomInt(min, max) {
// GOAL: get a random integer in a range from min to max
return Math.floor(Math.random() * (max - min + 1) + min);
} // END RandomInt FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE: Function from internet
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
} // END shuffleArray FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function firstCanvas (appendObject, sizeCirckel, horizontalCirckles, verticalCirckles) {
// GOAL: create first canvas with random dots to allow for calculations of how many figures to present (based on stimulus size)
// appendObject: object to which the created canvas should be appended (div "stimuli")
// sizeCirckel: how large the dots should be (< 6)
// horizontalCirckles: width of the grid of dots
// verticalCirckles: height of the grid of dots
createCanvas(appendObject, "Canvas1", evaluationArray); // create new responsive canvas
var dots1 = getRandomInt(3, 5); // randomly select to present 3 / 4 / 5 dots
randomFigure ("Canvas1", 10,10,sizeCirckel, horizontalCirckles, verticalCirckles, dots1); // draw figure with dots1 amount of dots
return dots1;
} // END firstCanvas FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function maxFigures () {
// GOAL: determine how many whole figures will fit the current window
// no input variables required, variables calculated within function
// Determine size of window, using || allows for this function to work in Explorer and other browsers (from internet);
var winWidth = window.innerWidth
|| document.documentElement.clientWidth || document.body.clientWidth;
var winHeight = window.innerHeight
|| document.documentElement.clientHeight || document.body.clientHeight;
// Determine size of first canvas that was presented
var stimWidth = document.getElementById("Canvas1").width;
var stimHeight = document.getElementById("Canvas1").height;
// Calculate max number of pictures to fit the window
var winHeight = winHeight - stimHeight; // to allow room for "finish" button
var totalFigures = (((Math.floor(winWidth / stimWidth))-1) * ((Math.floor(winHeight / stimHeight)))); //Math.floor rounds the outcome down to an integer. -1 to allow room for the button
return totalFigures;
} // END maxFigures FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function randomizeDots (totalFigures, dots1, minDot, maxDot) {
// GOAL: determine how many 3/4/5 dot figures should be presented. Randomize order of presentation
// totalFigures: amount of figures that will be presented on screen (return from maxFigures function)
// dots1: whether figure 1 contains 3, 4, or 5 dots (var created in stimulusPresentatoin function)
// minDot: minimum amount of dots in each figure (BVTest set at 3)
// maxDot: maximum amount of dots in each figure (BVTest set at 5)
// INITIALIZE variables
var dotsArray = []; // is used in randomFigure function to specify the amount of dots that should be drawn
if (minDot != 3 || maxDot != 5) { // restore values to 3 & 5 if other values were specified, not yet supported
window.alert("Currently unable to support figures other than 3-4-5 dots." + "<br>" + "minDot = 3 && maxDot = 5"); // NOTIFICATION
var minDot = 3;
var maxDot = 5;
} // END IF
// LOOP for each amount of dots between minDot and maxDot
for (e = minDot; e < (maxDot + 1); e++) { // + 1 because < than is used
var amountFigures = totalFigures / ((maxDot - minDot) ); // divide by 3
// BALANCE
// Decrease amountFigures by 1 if first Figure (dots1) contains that amount of dots
if (dots1 === 3 && e === 3) { // change amount of figures to create with one less depending on the amount of dots the first figure contains
// window.alert((dots1 === 3 && e === 3));
var amountFigures = (amountFigures - 1);
} else if (dots1 === 4 && e === 4) {
// window.alert((dots1 === 4 && e === 4));
var amountFigures = (amountFigures - 1);
} else if (dots1 === 5 && e === 5) {
// window.alert((dots1 === 5 && e === 5));
var amountFigures = (amountFigures - 1);
} else {
// do nothing
} // END IF
// window.alert(amountFigures);
// FILL dotsArray with 1/3 of totalFigures 3, 1/3 4, 1/3 5
for (r = 0; r < amountFigures; r++) { // append 1/3 of totalFigures with 3 dots, 1/3 4 dots, 1/3 5 dots
dotsArray.push(e);
} // END dotsArray FILL
} // END dot LOOP
// RANDOMIZE dots order
shuffleArray(dotsArray); // shuffle to create random order of figures
dotsArray.unshift(dots1); // append firstly created canvas to the total array of Dots (for response tracking)
// window.alert(dotsArray);
return dotsArray;
} // END randomizeDots FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function createCanvas (appendObject, canvasID, evaluationArray) {
// GOAL: create a new reponsive EMPTY canvas
// appendObject: ID of the object to which the canvas should be appended <div id = "stimuli">
// canvasID: name you want to give to the created canvas
// CREATE CANVAS
var addCanvas = document.createElement('canvas'); // Create new canvas element
// ASSIGN PROPERTIES
addCanvas.id = canvasID; // .id to change on what is specified (itterates in stimulusPresentation function)
addCanvas.width = 100; // determine canvas width (manipulated in randomFigure function)
addCanvas.height = 100; // determine canvas height (manipulated in randomFigure function)
// ASSIGN RESPONSE ACTIONS
// addCanvas.onmouseover = function () { responseTime(evaluationArray) } ; // call upon getID function to register ID element that triggered function
addCanvas.onclick = function () {responseLogging(canvasID, canvasWidth, canvasHeight) } ; // call upon responseLogging to track correct crossout and log hits/miss/mistakes
// APPEND RESPONSE ACTIVE CANVAS
document.getElementById(appendObject).appendChild(addCanvas); // append newly created canvas to exisitng element
} // END createCanvas FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function getID () {
// GOAL: return ID of the canvas on which the mouse is hovering
// no input variables
// no var to make globally accesible
currentID = event.currentTarget.id; // register id of element that triggered the function
return currentID;
// window.alert(currentID); // TEST
} // END getID FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function responseLogging (canvasID, canvasWidth, canvasHeight) {
// DETERMINE CURRENT CANVAS
var ID = canvasID;
var index = (ID.replace("Canvas", ""))-1; // replace "Canvas" by nothing so unique number remains, -1 because index starts from 0
// LOG MOUSECLICKS
var clicks = clickArray[index];
if (clicks == 0) {
// canvas has not been clicked - draw line
var c=document.getElementById(canvasID); // refer to correct canvas
var ctx=c.getContext("2d"); // unkown but necessary
ctx.beginPath(); // start new drawing
ctx.moveTo(0,0); // determine starting position of line - constant
ctx.lineTo(canvasWidth,canvasHeight); // finish position of line - changes on canvas size specifiedin drawGrid function
ctx.lineWidth = 4; // size of the line to be drawn (should depend on circkle size)
ctx.strokeStyle = "#ff0000"; // color of line; red
ctx.stroke(); // initialize drawing
clickArray[index] = 1;
} else if (clicks == 1) {
// second response, draw correction line
var c=document.getElementById(canvasID); // refer to correct canvas
var ctx=c.getContext("2d"); // unkown but necessary
ctx.beginPath(); // start new drawing
ctx.moveTo(canvasWidth,0); // determine starting position of line (should depend on which canvas it is)
ctx.lineTo(0,canvasHeight); // finish position of line (should depend on size of canvas)
ctx.lineWidth = 4; // size of the line to be drawn (should depend on circkle size)
ctx.strokeStyle = "#ff0000"; // color of line; red
ctx.stroke(); // initialize drawing
clickArray[index] = 2;
} else {
// do nothing
} // END clicks IF
// extract amount of dots presented in figure
var amountDots = dotsArray[index];
// window.alert(amountDots);
// CODE RESPONSES (only cross out (click = 1) figures with 4 dots)
// CODING: HIT (1), Miss (2), False Alarm (3) // NO (0), YES (1)
if (amountDots == 3 || amountDots == 5) {
// do not click (click == 0) or correct mistake (click == 2) == HIT
if (clickArray[index] == 0) { // No click = CORRECT // NOTE: not coded because function only activated upon mouseclick
responseArray.push(1); // HIT
correctionArray.push(0); // NO
responseOrderArray.push(canvasID);
} else if (clickArray[index] == 1) { // 1 click == WRONG (only click figures with 4 dots)
responseArray.push(3); // FALSE ALARM
correctionArray.push(0); // NO
responseOrderArray.push(canvasID);
} else { // 2 clicks == CORRECTION
// clickArray[index] == 2
responseArray.push(1); // HIT
correctionArray.push(1); // YES
responseOrderArray.push(canvasID);
} // END if click
} else {
// amountDots == 4
if (clickArray[index] == 0) { // no click == WRONG // NOTE: not coded because function only activated upon mouseclick
responseArray.push(2); // MISS
correctionArray.push(0); // NO
responseOrderArray.push(canvasID);
} else if (clickArray[index] == 1) { // 1 click == CORRECT
responseArray.push(1); // HIT
correctionArray.push(0); // NO
responseOrderArray.push(canvasID);
} else { // 2 clicks == unjust correction aka WRONG
// clickArray[index] == 2
responseArray.push(2); // MISS
correctionArray.push(1); // YES
responseOrderArray.push(canvasID);
} // END if click
} // END IF amountDots
} // END correctResponse FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function randomFigure (canvasID, posX,posY,sizeCirckel, horizontalCirckles, verticalCirckles, dots) {
// GOAL: to create a random figure containing 3 - 4 - 5 black dots
// canvasID: name of canvas on which to draw (itterated in stimulusPresentation)
// posX: set at 10 (needs to be deleted)
// posY: set at 10 (needs to be deleted)
// sizeCirckel: change size of dots (currently only works for values < 6)
// horizontalCirckles: width of imaginary grid of dots (i.e. possible X positions)
// verticalCirckles: height of imaganinary grid of dots (i.e. possible Y positions)
// dots: amount of dots to be drawn (randomized in stimulusPresentation)
// SET VARIABLES
var distance = posX + sizeCirckel; // distance between dots, currently not included in position calculations
canvasWidth = ((distance * horizontalCirckles) + sizeCirckel) + posX; // size of canvas bigger than range for drawing dots (recalculate)
canvasHeight = ((distance * verticalCirckles) + sizeCirckel) + posY; // size of canvas bigger than range for drawing dots (recalculate)
// CREATE CANVAS OF CORRECT SIZE
document.getElementById(canvasID).width = canvasWidth; // change size of canvas (see HTML)
document.getElementById(canvasID).height = canvasHeight; // change size of canvas (see HTML)
// DRAW 1 BLACK DOT
// blackDot (posX, posY, sizeCirckel, canvasID);
// GENERATE RANDOM XY POSITIONS
positionGrid (verticalCirckles, horizontalCirckles, sizeCirckel); // call upon positionGrid function
// shuffle XY positions
var indexArray = []; // create new Array for random indexing out of XY coordinate arrays
for (y = 1; y < (horizontalCirckles * verticalCirckles); y++) { // create integers for each point in the grid (1 - ...)
indexArray.push(y); // append integer to indexArray
} // END for LOOP
shuffleArray(indexArray); // shuffle order of integers to allow for random indexing (i.e. dot placement)
// window.alert(indexArray);
// DRAW ALL DOTS
for (t = 0; t < dots; t++) { // draw 3 / 4 / 5 dots
var index = indexArray[t]; // random integer used to index from possible X and Y coordinate arrays
// access randomly selected XY coordinates
var X = arrayXPos[index]; // random - but unique - X coordinate
var Y = arrayYPos[index]; // random - but unique - Y coordinate
blackDot(X,Y, sizeCirckel, canvasID); // draw DOT in random placement
} // END DRAWING DOTS
} // END randomFigure FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function blackDot (posX, posY, sizeCirckel, canvasID) {
// GOAL: draw a single black circkle
// posX: X position of center circkel relative to canvas
// posY: Y position of center circkel relative to canvas
// sizeCirckel: increase size of circkel (currently only works for values < 6 )
// call canvas
var c = document.getElementById(canvasID); // draw on prespecified canvas (see HTML)
var ctx = c.getContext("2d"); // unkown functionality but necessary
// draw circkel
ctx.beginPath(); // initialize drawing
ctx.fillstyle = "black"; // specify fill color = black
ctx.arc(posX,posY,sizeCirckel,0,2*Math.PI); // specification of shape to draw (in this case a circkle)
ctx.stroke(); // draw specified shape
ctx.closePath(); // to allow for other figures to be drawn
ctx.fill(); // execute
} // END blackDot FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function positionGrid (verticalCirckles, horizontalCirckles, sizeCirckel) {
// GOAL: create an X and Y coordinate array depending on the amount of circkles that was specified
// verticalCirckles: height of grid
// horizontalCirckles: width of grid
// sizeCirckel: size of the circkles for between circkel distance
// possible X positions
arrayXPos = []; // create empty array accesible outside function
for (q = 1; q < (verticalCirckles + 1); q++) { // repeat X coordinates for all coordinates of Y
for (k = 1; k < (horizontalCirckles + 1); k++) { // positions for the amount of horizontalCirckles specified (+1 because k = 1)
var posX = ((3 * sizeCirckel) * k); // (should be changed depending on canvas & circkel size)
arrayXPos.push(posX); // append new position to array containing all X coordinates
} // END horizontal LOOP
} // END vertical LOOP
// window.alert(arrayXPos); // TEST
// possible Y positions
arrayYPos = []; // create empty array accesisble outside function
for (w = 1; w < (horizontalCirckles + 1); w++) { // repeat Y coordinates for all coordinates of X
for (l = 1; l < (verticalCirckles + 1); l++) { // positions for the amount of verticalCirckles specified (+1 because l = 1)
var posY = ((3 * sizeCirckel) * l); // change depending on circkelSize
arrayYPos.push(posY); // append new position to array containing all Y position
} // END vertical LOOP
} // END horizontal LOOP
// window.alert(arrayYPos); // TEST
// sort so when paired with X creates unique XY coordinates
arrayYPos.sort();
} // END positionGrid FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function startTime () {
// GOAL: log current Time
// no input variables
var sTime = new Date();
var startTime = sTime.getTime();
// window.alert(startTime); // TEST
sessionStorage.setItem("start", startTime); // store until tab is closed so can be used on next page
} // END startTime FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function finishTime () {
// GOAL: log current Time
// no input variables
var fTime = new Date ();
finishTime = fTime.getTime();
// document.getElementById("testing").innerHTML = (startTime - finishTime); // TEST
sessionStorage.setItem("finish", finishTime);
} // END startTime FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FROM INTERNET - ALLOWS FOR ARRAY STORAGE IN TEMP MEMORY
Storage.prototype.setObj = function(key, obj) {
return this.setItem(key, JSON.stringify(obj));
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function terminationButton () {
// STORE VARIABLES FOR CALCULATIONS
// startTime saved in Function
finishTime(); // finishTime saved in Function
// window.alert(responseArray);
sessionStorage.setObj("ARRAY_MADE_RESPONSES", responseArray); // responses made
sessionStorage.setObj("ARRAY_MADE_CORRECTIONS", correctionArray); // corrections made
sessionStorage.setObj("ARRAY_N_MOUSECLICKS", clickArray); // mouseclicks made
sessionStorage.setObj("ARRAY_CANVAS_RESPONSE_ORDER", responseOrderArray); // order in which responses were made
sessionStorage.setObj("ARRAY_N_DOTS", dotsArray); // amount of dots in each figures
sessionStorage.setObj("ARRAY_CANVAS_IDs", canvasIdArray); // IDs of canvasses that were created
// load next page
window.location.href = "bv_results.html";
} // END terminationButton FUNCTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////