/*
* plugin based in Qisheng Li 11/2019. /// https://github.com/QishengLi/virtual_chinrest
Modified by Gustavo Juantorena 08/2020
*/
jsPsych.plugins['virtual-chin'] = (function() {
var plugin = {};
plugin.info = {
name: "virtual-chin",
parameters: {
viewing_distance_cm: {
type: jsPsych.plugins.parameterType.INT,
default: 0
},
cardWidth_px: {
type: jsPsych.plugins.parameterType.INT,
default: 0
},
pixels_per_unit: {
type: jsPsych.plugins.parameterType.INT,
pretty_name: 'Pixels per unit',
default: 100,
description: 'After the scaling factor is applied, this many pixels will equal one unit of measurement.'
},
prompt_instructions: {
type: jsPsych.plugins.parameterType.STRING,
default: null,
description: 'Any content here will be displayed above card image.'
},
// prompt_card: {
// type: jsPsych.plugins.parameterType.STRING,
// default: null,
// description: 'Any content here will be displayed above card image.'
// },
// prompt_blindspot: {
// type: jsPsych.plugins.parameterType.STRING,
// default: null,
// description: 'Any content here will be displayed below the stimulus.'
// }
}
}
plugin.trial = function(display_element, trial) {
// data saving
var trial_data = { //I need to modify this in order to save important data
'viewing_distance_cm': trial.viewing_distance_cm,
'cardWidth_px': trial.cardWidth_px
};
//Store all the configuration data in variable 'data'
var data = {"dataType":"configurationData"};
data["ballPosition"] = [];
data["sliderClicked"] = false;
(function ( distanceSetup, $ ) { // jQuery short-hand for $(document).ready(function() { ... });
distanceSetup.round = function(value, decimals) {
return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
};
distanceSetup.px2mm = function(cardImageWidth) {
const cardWidth = 85.6; //card dimension: 85.60 × 53.98 mm (3.370 × 2.125 in)
var px2mm = cardImageWidth/cardWidth;
data["px2mm"] = distanceSetup.round(px2mm, 2);
return px2mm;
};
}( window.distanceSetup = window.distanceSetup || {}, jQuery));
function getCardWidth() {
var cardWidthPx = $('#card').width();
data["cardWidthPx"] = distanceSetup.round(cardWidthPx,2);
console.log(cardWidthPx)
trial_data.cardWidth_px = cardWidthPx // add to trial_data
return cardWidthPx
}
function configureBlindSpot() {
drawBall();
$('#page-size').remove();
$('#blind-spot').css({'visibility':'visible'});
// $(document).on('keydown', recordPosition);
$(document).on('keydown', recordPosition);
};
$( function() {
$( "#slider" ).slider({value:"50"});
} );
$(document).ready(function() {
$( "#slider" ).on("slide", function (event, ui) {
var cardWidth = ui.value + "%";
$("#card").css({"width":cardWidth});
});
$('#slider').on('slidechange', function(event, ui){
data["sliderClicked"] = true;
});
});
//=============================
//Ball Animation
function drawBall(pos=180){
// pos: define where the fixation square should be.
var mySVG = SVG("svgDiv");
const cardWidthPx = getCardWidth()
const rectX = distanceSetup.px2mm(cardWidthPx)*pos;
const ballX = rectX*0.6 // define where the ball is
var ball = mySVG.circle(30).move(ballX, 50).fill("#f00");
window.ball = ball;
var square = mySVG.rect(30, 30).move(Math.min(rectX - 50, 950), 50); //square position
data["squarePosition"] = distanceSetup.round(square.cx(),2);
data['rectX'] = rectX
data['ballX'] = ballX
};
function animateBall(){
ball.animate(7000).during(
function(pos){
moveX = - pos*data['ballX'];
window.moveX = moveX;
moveY = 0;
ball.attr({transform:"translate("+moveX+","+moveY+")"});
}
).loop(true, false).
after(function(){
animateBall();
});
//disbale the button after clicked once.
$("#start").attr("disabled", true);
};
function recordPosition(event, angle=13.5) {
// angle: define horizontal blind spot entry point position in degrees.
if (event.keyCode == '32') { //Press "Space"
data["ballPosition"].push(distanceSetup.round((ball.cx() + moveX),2));
var sum = data["ballPosition"].reduce((a, b) => a + b, 0);
var ballPosLen = data["ballPosition"].length;
data["avgBallPos"] = distanceSetup.round(sum/ballPosLen, 2);
var ball_sqr_distance = (data["squarePosition"]-data["avgBallPos"])/data["px2mm"];
var viewDistance = ball_sqr_distance/Math.radians(angle)
console.log(Math.radians(angle))
data["viewDistance_mm"] = distanceSetup.round(viewDistance, 2);
//counter and stop
var counter = Number($('#click').text());
counter = counter - 1;
$('#click').text(Math.max(counter, 0));
if (counter <= 0) {
ball.stop();
// Disable space key
$('html').bind('keydown', function(e)
{
if (e.keyCode == 32) {return false;} //32 is spacebar
});
// // Display data
// $('#info').css("visibility", "visible");
// $('#info-h').append(data["viewDistance_mm"]/10)
//Estimated viewing distance in centimeters
trial_data.viewing_distance_cm = (data["viewDistance_mm"]/10); // add to trial_data
console.log(data["viewDistance_mm"]/10);
dist = Math.round(data["viewDistance_mm"]/10)
// The trial must end
end_trial();
// You can then DO SOMETHING HERE TO PROCEED TO YOUR NEXT STEPS OF THE EXPERIMENT. For example, add a button to go to the next page.
// display_element.innerHTML = `
"Press space bar to start the experiment.
`
display_element.innerHTML =
`
Este experimento consta de dos tipos de ensayos:
Los ensayos del primer tipo consisten en una serie de números del 1 al 20 rodeados cada
uno por un círculo. Su objetivo será unir con un trazo continuo los puntos en orden creciente, tratando de
evitar que los trazos se toquen. Tendrá un límite de tiempo fijo para resolver cada ensayo.
AL COMENZAR CADA ENSAYO VERÁ UNA CRUZ EN EL CENTRO DE LA PANTALLA, CUANDO ESTA DESAPAREZCA Y VEA LOS CIRCULOS
DEBERÁ PRESIONAR EL BOTON IZQUIERDO DEL MOUSE (O SU PAD DE NOTEBOOK) Y
MANTENERLO PRESIONADO HASTA TERMINARLO. No levante el dedo del botón al menos que
hayas terminado el ensayo, o que este haya terminado por superar el tiempo límite.
El otro tipo de ensayo consiste en una serie de números del 1 al 10 y letras de la A
a la J. Su objetivo será unir con un trazo continuo los puntos de manera alternada (ejemplo 1-A-2-B-3-C,
etc).
Su objetivo será realizar la tarea SIN PASAR POR ENCIMA DE SU PROPIO TRAZO y lo más rápido posible.
Los ensayos van a aparecer siempre alternadamente.
¡Suerte y muchas gracias por participar!
Para comenzar por favor presione la barra espaciadora
`
return trial_data.viewing_distance_cm;
}
ball.stop();
animateBall();
}
}
//helper function for radians
// Converts from degrees to radians.
Math.radians = function(degrees) {
return degrees * Math.PI / 180;
};
// You can write functions here that live only in the scope of plugin.trial
function show_stimulus(){
display_element.innerHTML = `
Por favor repetí la medición de la tarjeta,pero esta vez utilizando la barra deslizante.
`
var html = "
";
// html += "
Let’s find out what your monitor size is (click to go into
full screen mode
).";
html += "
Por favor repita la medición de la misma tarjeta, pero esta vez utilizando la barra deslizante.
";
html += "Asegúrese de poner la tarjeta sobre la pantalla.";
html += '
';
html += "";
html += '
';
html +='
';
html += '
';
html += '';
html += "
Ahora vamos a estimar su distancia a la pantalla.
";
html += '
Instrucciones
';
html += '
1. Coloque su dedo índice en la barra espaciadora
';
html += '
2. Cierre su ojo derecho. (Tip:Quizá le resulte más fácil tapándolo con su mano!)
';
html += '
3. Usando su ojo izquierdo, haga foco en el cuadrado negro.
';
html += '
4. Presione el botón de abajo para iniciar la animación de la pelotita roja. Esa pelotita roja va a desaparecer de su vista en algún momento. Ni bien la deje de ver (siempre enfocando en el cuadrado negro) presione una vez la barra lo más rápidamente posible.
';
html += '
Por favor repita el proceso cinco veces. Mantenga su ojo derecho cerrado y presione la barra espaciadora lo más rápidamente posible!
';
html += '';
html += '';
html += "Presioná la barra
5
veces más!
";
display_element.innerHTML = html; //
document.getElementById("btnBlindSpot").addEventListener('click', function() {
console.log('presionaste el boton 1');
configureBlindSpot();
});
document.getElementById("start").addEventListener('click', function() {
console.log('presionaste el boton 2');
animateBall();
});
jsPsych.pluginAPI.getKeyboardResponse({
callback_function: after_response, // we need to create after_response
valid_responses: [trial.key], // valid_responses expects an array
rt_method: 'performance', // This is only relevant for RT in audio stimuli
persist: false, // true if you want to listen to more than one key
allow_held_key: true // false for a new key pressing in order to get a new response
});
}
//
//
//
//
//
//
//
//
// scales the stimulus
// var scale_factor;
// var final_height_px, final_width_px;
// final_width_px = trial.cardWidth_px;
// function scale() {
// final_width_px = scale_div.offsetWidth;
// //final_height_px = scale_div.offsetHeight;
// var pixels_unit_screen = final_width_px / trial.item_width;
// scale_factor = pixels_unit_screen / trial.pixels_per_unit;
// document.getElementById("jspsych-content").style.transform = "scale(" + scale_factor + ")";
// };
function after_response(response_info){
// rt.push(response_info.rt); // response time of the key
// scale() // Esto lo agregue pero no creo que quede
end_trial();
}
function end_trial(){
document.getElementsByClassName("jspsych-content-wrapper")[0].style.backgroundColor = 'gray'; //Background color
// trial_data.viewingDistance= JSON.stringify(viewingDistance); // best practice for saving in jsPsych. It is a JSON instead of array.
jsPsych.finishTrial(trial_data); // ends trial and save the data
display_element.innerHTML = ' '; // clear the display
}
show_stimulus();
};
return plugin;
})();