Skip to content

blackcub3s/calculaTempsReaccio

Repository files navigation

Taula de continguts

  1. Finalitat
  2. Implementació

1. Finalitat

Aquesta eina permet fer una aproximació del temps de reacció motor d'una persona computant la diferència entre múltiples clics consecutius entre les cel·les d'una taula que van apareixent i desapareixent de forma aleatòria.

No és una eina perfectament fiable per donar una lectura acurada ja que existeixen diferents fonts de variabilitat en la mesura, com per exemple la velocitat de l'ordinador de la persona que té el client (navegador), el propi llenguatge javascript o, fins i tot, la senzilla lògica de programació emprada per evitar que surtin dues cel·les consecutives, com veurem. Tot i així, serveix com una bona aproximació per comparar individus sempre que facin servir el mateix dispositiu (sigui mòbil, tablet o ordinador).

El funcionament de l'aplicació és tal i com es mostra en el següent GIF:

gif_de_mostra

2. Implementació

2.1 Fitxer scriptTaula.js

2.1.1 Funció main()

El que veu l'usuari res més carregar la pàgina és, principalment, una taula html (encara que no ho sembli). Per mostrar-la, res més carregar l'html, es crida la funció main() del fitxer scriptTaula.js. Aquesta funció amaga tots els elements <td></td> de la taula posant la propietat de CSS a style: hidden mitjançant javascript, a excepció d'un d'ells, que es deixa visible triant-lo de forma aleatòria mitjançant la funció Math.random()

function main() {
//VALOR ALEATORI ENTRE INTERVAL TANCAT [0, elements.length - 1]
indexAleatori = Math.floor(Math.random() * elements.length);
for (let i = 0; i < nreCaselles; i++) {
if (indexAleatori != i) {
elements[i].style.visibility = "hidden";
}
}
}
main();

Aquesta funció, igual que les demés funcions crida diverses variables globals diposades a l'inici del fitxer (així es troben disponibles mentre no es refresci la pàgina):

var elements = document.getElementsByTagName("td");
let nreCaselles = elements.length;
var indexAleatori = -1;
var ultimNombreAleatoriGenerat = -1;
var trMinim = Number.MAX_SAFE_INTEGER;
var trMax = 0;
var clics = 0;
var sumaTemps = 0;
var arrayTempsReaccio = [];
var arrayTempsNoRepresentatsEnHistorama = []; //s'usa en fitxer scriptHistograma

2.1.2 Funció casellaClicada()

Aquesta funció és invocada cada cop que cliquem damunt d'una de les cel·les visibles de la taula. Si la casella que s'ha clicat s'ha clicat per primer cop des de que hem carregat la pàgina, s'inicia un temporitzador amb t = performance.now() (cas en que la variable global clics val zero). En cas contrari, si la cel·la ja ha sigut premuda en anteriors ocasions (és a dir, que clics és superior a 0, exemplificat per la condició clics != 0) aleshores ja tenim una referència temporal iniciada per l'usuari i podem calcular un temps de reacció emmagatzemant el valor de t en una variable auxiliar t_previ tot fent t_previ = t i aplicant de nou la sentència t = performance.now per poder fer posteriorment la diferència t - t_previ. La funció, a més a més de computar el temps de reacció, també computa quin és el minim temps de reacció de l'usuari, el màxim, la mitjana aritmètica de tots els temps de reacció que es fan des de l'últim refresc de pantalla i passar a l'HTML les estadístiques mencionades perquè puguin ser vistes en temps real. A més a més, aquesta funció també va guardant cada temps de reacció en l'arrayTempsReaccio perquè després es pugui mostrar l'histograma quan ho demani l'usuari.

//PRE: quan clico una td -cel·la de la taula- entra per variable global l'index de la mateixa (indexAleatori, generat en el main)
//POST: em genera un nou nombre aleatori, que referencia la td clicada -l'única visible per ara-, l'amaga,
// va a obtenir un altre nombre aleatori i mostra el td que és referenciat per aquest altre nombre aleatori.
////FUNCIONAMENT: En essència és el que denominem com a EVENT LISTENER
function casellaClicada() {
if (clics != 0) {
//calculo diferencia temporal entre clic previ (o càrrega de programa) i clic actual.
var t_previ = t;
t = performance.now();
tReacc = t - t_previ;
//A cada clicada calculo la mitjana de temps de reaccio, el valor mínim, màxim i guardo els valors en array
trMinim = minim2(tReacc, trMinim);
trMax = maxim2(tReacc, trMax);
sumaTemps += tReacc;
mitjana = sumaTemps / clics;
arrayTempsReaccio.push(Math.round((tReacc)*10)/10); //guardem un sol decimal del temps de reaccio
//console.log(arrayTempsReaccio);
//poso el temps de reacció en relació a l'anterior clic amb respecte a clic actual i poso la mitjana aritmètica actual i el minim
document.getElementById("difClicsConsecutius").innerHTML = "t("+clics+"): " + Math.round((tReacc)*10)/10 + " ms";
document.getElementById("estadistiques").innerHTML = "<i>[min = "+Math.round(trMinim)+" ms | &mu; = " + Math.round(mitjana) + " ms | max = "+Math.round(trMax)+" ms]</i>";
clics += 1;
} else { //cas en que fem el primer clic, que és quan realment començem a contar el temps de reacció a l'usuari (no des de la càrrega de la pàgina)
t = performance.now();
clics += 1;
}
//amago casella antiga i mostro la nova (escollida aleatòriament, excloient L'ANTERIOR CASELLA MOSTRADA -ALEATORI SENSE REPOSICIO DE L'ULTIMA CASELLA-)
ultimNombreAleatoriGenerat = indexAleatori;
elements[indexAleatori].style.visibility = "hidden"; //podia posar indexCasella en comptes de indexAleatori de fet, i passar per parametre indexCasella en l'event listener de casellaClicada
indexAleatori = aleatoriSenseResposicio(ultimNombreAleatoriGenerat);
elements[indexAleatori].style.visibility = "visible";
}

2.2 Fitxer scriptHistogramaGPT.js

Per fer l'histograma hi havia dues opcions. La primera era mirar alguna llibreria que ja l'implementés, però aquestes llibreries solen generar problemes per poder modificar l'histograma a diferents dispositius o al teu gust. La segona opció era fer des de zero l'histograma.

Per simplificar la tasca vaig demanar a xatGPT la següent prompt: "I want to generate an histogram using pure CSS, html and javascript, with no external libraries of javascript. I want it from scratch. How do i do it?". La resposta de xatGPT va ser el fitxer GPT_1.html, que permet introduir en un array el nombre de dades que volem a cada barra de l'histograma (en l'exemple de prova) mitjançant un array const data = [4, 7, 2, 5, 10];, quedant així:

sortida fitxer gpt1

A partir d'aquest fitxer vaig anar fent modificacions fins acabar obtenint el fitxer scriptHistogramaGPT.js que, sumat a l'arxiu CSS histogramaGPT.css, ens permet obtenir aquest histograma:

sortida fitxer meu

Dins scriptHistogramaGPT.js tenim una variable global booleana inicialitzada a fals (var histogramaGenerat = false) i tres funcions, que desgranarem a continuació en els seguents tres sub apartats (2.2.1, 2.2.2 i 2.2.3):

2.2.1 Funció generaIntervals()

Per tal de generar els límits superiors dels intervals de l'histograma (el límit inferior el calcularem dins la funció següent) donem una dada en milisegons inicial, una dada en milisegons final i un increment, que serà l'amplada de l'interval. Així podem generar un nombre d'intervals variables en funció del que ens convingui a nosaltres:

function generaIntervals(inicial, final, increment) {
var dades = [];
var i = inicial;
dades.push(inicial);
while (i < final) {
i += increment;
dades.push(i);
}
return dades;
}

2.2.2 Funció afegeix_TR_a_arrayHistograma()

Aquesta funció el que fa és prendre l'array d'intervals i l'array de temps de reacció i retorna un array amb les dades necessaries per fer després l'histograma. Recorre un per un l'array de temps de reacció i a cada element de la mateixa l'assigna a un dels intervals de l'histograma. Noteu que per a un element el de l'array dades que retorna generaIntervals() en aquesta funció es genera un increment d'una unitat en una posició de l'array que després retorna. Aquesta última array, cada element, és el nombre d'ocurrències que hi ha per a un interval de l'histograma de tipus obert per l'esquerra i tancat per la dreta de la forma: [el - increment, el):

function afegeix_TR_a_arrayHistograma(arrIntervals, arrTR, incrementHistograma) {
//inicialitzo una array per a l'histograma amb tot zeros
var dades = Array(arrIntervals.length).fill(0);
var ls;
var li;
var afegit; //variable que mostra si hem afegit un temps de reaccio a l'histograma o no
for (let i = 0; i < arrTR.length; ++i) {
afegit = false;
for (let j = 0; j < arrIntervals.length; ++j) {
ls = arrIntervals[j];
li = arrIntervals[j] - incrementHistograma;
if (arrTR[i] >= li && arrTR[i] < ls) { // --- > [li,ls) <----
dades[j] += 1; //incrementem una unitat en l'slot de dades correlatiu (j-èssim) a on cau l'i-èssim valor d'arrTR.
afegit = true;
break; //esquema de cerca, no volem arribar fins a final d'arrIntervals quan el trobem, sino que continuem classificatn valors arrTR
}
}
//si no l'hem afegit a l'histograma perquè no tenim espai a l'esquerra i a la dreta volem registrar aquetsos temps també i informar a l'usuari
if (!afegit) {
arrayTempsNoRepresentatsEnHistorama.push(arrTR[i]);
}
}
//console.log(arrayTempsNoRepresentatsEnHistorama);
return dades;
}

2.2.3 Funció main_fesHistograma()

Aquesta funció mostra el contenidor de l'histograma i la línia horitzontal que el separa de l'àrea de joc a petició de l'usuari (quan aquest clica histograma). A més a més, carrega les dades que necessiten les dues funcions previes, les invoca i finalment genera l'histograma amb la variable data. El codi que hi ha dins del for.Each és el codi adaptat i força modificat de GPT_1.html que no només genera l'histograma sino que també posa les etiquetes d'intervals a sota i mostra un missatge d'error si l'usuari intenta generar un altre histograma sense refrescar la pàgina:

function main_fesHistograma() {
if (!histogramaGenerat) {
document.getElementById("histogram-container").style.visibility = 'visible';
document.getElementsByTagName("hr")[0].style.visibility = 'visible';
histogramaGenerat = true;
/*TODO --> [300 - 325), [325 - 350), [350 - 375), [375 - 400), [400 - 425), [425 - 450), [450 - 475),
[475 - 500), [500 - 525), [525 - 550), [550 - 575), [575 - 600), [600 - 625), [625 - 650), [650 - 675), [675 - 700) ms*/
//el primer interval va de 300 a 325, segon de 325 a 350..
const iniciHistograma = 340; //inici real sera "incrementHistograma" per sota del valor iniciHistograma: "[incrementHistograma - iniciHistograma"
const finalHistograma = 700; //final real es aquest, amb interval obert "finalHistograma)" o bé proper si els increments no cauen just a final histograma "finalHistograma + increment"
const incrementHistograma = 30; //increments d'histograma, de valor "incrementHistograma"
const arrIntervals = generaIntervals(iniciHistograma,finalHistograma,incrementHistograma); //ES AIXO --> [275, 300, 325, 350, 375, 400, 425, 450, 475, 500, 525, 550, 575, 600, 625, 650, 675, 700];
var data = afegeix_TR_a_arrayHistograma(arrIntervals, arrayTempsReaccio, incrementHistograma); // arrTR te els temps de reaccio de l'usuari, d'aspecte [324,323,322,325,699..], i es una variable global de scriptTaula.js, i ve d'allà automaticament.
//const data = [0,0, 1, 4, 5, 6, 10, 12, 15, 13, 12, 9, 7, 9, 6, 5, 4, 2];
//console.log("arrIntervals --> ", arrIntervals);
//console.log("arrData --> ", data);
const histogramContainer = document.getElementById("histogram-container");
data.forEach((value, index) => {
const barContainer = document.createElement("div");
barContainer.className = "bar-container";
const bar = document.createElement("div");
bar.className = "bar";
bar.style.height = value * .5 + "em"; // You can adjust the multiplier for height
bar.style.width = .3+"em";
const barLabel = document.createElement("div");
barLabel.className = "bar-label";
barLabel.textContent = value;
/*AFEGEIXO ELS VALORS DE LIMITS SUPERIORS DINS DE CADA BAR O BARRA*/
const barEtiquetaX_ls = document.createElement("div");
barEtiquetaX_ls.className = "etiqueta-Eix-X-ls";
barEtiquetaX_ls.textContent = arrIntervals[index];
/*AFEGEIXO EL SEPARADOR ENTRE ELS LIMITS SUPERIORS I INFERIORS*/
const separador = document.createElement("div");
separador.className = "etiqueta-Eix-X-li";
separador.textContent = arrIntervals[index] - incrementHistograma;
/*AFEGEIXO ELS VALORS DE LIMITS INFERIORS DINS DE CADA BAR O BARRA*/
const barEtiquetaX_li = document.createElement("div");
barEtiquetaX_li.className = "separador";
barEtiquetaX_li.textContent = "<>";
barContainer.appendChild(barEtiquetaX_ls);
barContainer.appendChild(barEtiquetaX_li);
barContainer.appendChild(separador);
/*FI AFEGIMENT VALORS X*/
barContainer.appendChild(bar);
barContainer.appendChild(barLabel);
histogramContainer.appendChild(barContainer);
});
document.getElementById("remanentsHistograma").innerHTML = "TRs fora dels límits de representació de l'histograma: "+arrayTempsNoRepresentatsEnHistorama.length;
} else {
alert("No pots generar dos histogrames. Has de refrescar la pàgina i tornar a començar!");
}
}

About

En aquest repositori mostro una petita aplicació web per calcular el temps de reacció motor d'un usuari, clicant de forma successiva als quadrats negres. També mostra, clicant en el botó corresponent, un histograma amb les dades representades en intervals.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors