De reverse engineering van mijn ADHD-test
Sterrenkijken
Ik heb altijd nieuwe hobby's op deze manier opgepikt. Echter, ik kon ze nooit volhouden.
(Bijschrift: Celestron NexStar 5SE telescoop, gefotografeerd vanaf mijn dak.)
Ik schreef dit toe aan het feit dat ik een spontiem mens ben. Pas toen een vriend hun recente autismediagnose deelden, besloot ik me te laten testen op ADHD. De psychiater legde uit dat een evaluatie een goed idee was. "Onbehandelde ADHD kan soms hand in hand gaan met depressie en angst," vertelde ze me. Ze liet me een online assessment maken, waarbij ze me waarschuwde dat ze niet met me zou kunnen praten zodra de test was begonnen. Onzeker over wat me te wachten stond, klikte ik op de "Begin Test"-link die ik via e-mail had ontvangen.
De test afleggen
De link bracht me naar een lege pagina die aanvoelde als een Flash-game uit het begin van de jaren 2000. De taak was simpel: druk op de spatiebalk telkens wanneer er een kaart met drie rode harten verscheen; doe anders niets.
Ik zat daar de spatiebalk in te drukken zoals gevraagd. Er was geen timer of score om bij te houden, alleen flitsende kaarten. Uiteindelijk begonnen er andere cliparts naast te verschijnen, schijnbaar als een manier om me af te leiden. Toch bleef ik de taak uitvoeren: de spatiebalk indrukken wanneer de kaart met drie rode harten verscheen. Dit duurde lang, waarbij uiteindelijk audio van huilende baby's en politiesirenes aan de mix werd toegevoegd. Op een gegeven moment voelde het alsof het nooit zou eindigen, dus begon ik wild op de spatiebalk te rammen in de hoop de schijnbaar eindeloze examinatie te voltooien.
(Bijschrift: Schermopname van een gedeelte van het ADHD-examen.)
Mijn nieuwsgierigheid werd gewekt en ik kreeg het heldere idee om de broncode van de pagina en alle uitgaande verzoeken vast te leggen. Ik opende DevTools, bewaarde alle scripts van de pagina en vervolgde het examen.
Gelukkig kwam er een einde aan! De psychiater vertelde me dat ze me de volgende week mijn resultaten zou laten weten.
Een blik onder de motorkap
Met alle opgeslagen scripts begon ik te graven. Een snelle grep op keyCode liet me zien hoe de test mijn spatiebalk-aanslagen verwerkte:
$(document).keyup(function (evt) {
keyPressed = false;
Context.LastPressTime = Context.CurrentTime;
if (evt.keyCode == 32 || evt.which == 32) {
Context.spacePressArray.clickTimes.push(adjustedTime);
console.log('Pushing Space: ' + Context.CurrentTime + ', Adjsuted Time: ' + adjustedTime);
}
else if (evt.keyCode != 32 && evt.keyCode != 13 ) {
Context.spacePressArray.badClickTimes.push(adjustedTime);
console.log('Pushing Bad Press: ' + ', Adjsuted Time: ' + adjustedTime);
}
}).keydown(function (evt) {
if (!keyPressed) {
adjustedTime = Context.CurrentTime - Context.Offset;
}
keyPressed = true;
})
Ze registreerden duidelijk elke keer dat ik op de spatiebalk drukte, samen met elke "foute" toets die ik indrukte (alles behalve Spatie of Enter).
Ze hadden ook een paar andere hooks geïmplementeerd:
onBlur = function (present_message){
present_message = (typeof present_message !== 'undefined' ? present_message : true);
if (!Context.canLooseFocus) {
Context.LastinFocusTime = Date.now();
InnerLog.log('Last in Focus Time: ' + Context.LastinFocusTime + ', Last Test Time in Focus: ' + Context.CurrentTime);
Context.InFocus = false;
adhd.prototype.addBeep();
if (present_message) {
this.outOfFocusAlert.htmlElement.style.visibility = "visible";
}
}
};
$(window).focus(function () {
if (!Context.canLooseFocus) {
this.outOfFocusAlert.htmlElement.style.visibility = "hidden";
Context.LostFocusAggregateTime += (Date.now() - Context.LastinFocusTime);
Context.InFocus = true;
Context.spacePressArray.lostFocusAggregateTime = Context.LostFocusAggregateTime;
adhd.prototype.removeBeep();
InnerLog.log('Aggregate Not in Focus Time: ' + Context.LostFocusAggregateTime + ", at: " + Context.CurrentTime);
if (Context.LostFocusAggregateTime < 0 || Context.CurrentTime < 0 || Context.startTime < 0) {
alert(Context.MessageSomethingWentWrong);
}
}
});
Ze kunnen zien wanneer de test het focus verliest (bijvoorbeeld als je een nieuw tabblad opent). Interessant genoeg ontdekte ik ook dat de assets werden gewisseld afhankelijk van of de persoon een volwassene of een kind was. Kinderen waren beperkt tot 15 FPS, volwassenen tot 24. Kinderen hoorden geluiden van vogels, bowling, lichtzwaarden en vliegtuigen. Volwassenen hoorden huilende baby's, auto-ongelukken en politiesirenes.
if (ageGroup == 'adults') {
properties = lib.properties_adults;
}
else {
properties = lib.properties_children;
}
lib.properties_children = {
width: 800,
height: 600,
fps: 15,
color: "#666666",
manifest: [
{src:"/js/adhd-html5/sounds/Birds.mp3", id:"Birds"},
{src:"/js/adhd-html5/sounds/Jedi.mp3", id:"Jedi"},
{src:"/js/adhd-html5/sounds/Bowling.mp3", id:"Bowling"},
{src:"/js/adhd-html5/sounds/Gong.mp3", id:"Gong"},
{src:"/js/adhd-html5/sounds/Plane.mp3", id:"Plane"},
{src:"/js/adhd-html5/sounds/Plane68.mp3", id:"Plane68"},
{src:"/js/adhd-html5/sounds/SaberSmall.mp3", id:"SaberSmall"},
{src:"/js/adhd-html5/sounds/PlaneBoom105.mp3", id:"PlaneBoom105"},
{src:"/js/adhd-html5/sounds/SaberOff3.mp3", id:"SaberOff3"},
{src:"/js/adhd-html5/sounds/Saber111.mp3", id:"Saber111"},
{src:"/js/adhd-html5/sounds/Saber111copy.mp3", id:"Saber111copy"},
{src:"/js/adhd-html5/sounds/Saber211.mp3", id:"Saber211"},
{src:"/js/adhd-html5/sounds/Saber211copy.mp3", id:"Saber211copy"},
{src:"/js/adhd-html5/sounds/Saber33.mp3", id:"Saber33"},
{src:"/js/adhd-html5/sounds/Saber33copy.mp3", id:"Saber33copy"},
{src:"/js/adhd-html5/sounds/SaberOnLong3.mp3", id:"SaberOnLong3"},
{src:"/js/adhd-html5/sounds/SaberOnLong3copy.mp3", id:"SaberOnLong3copy"},
{src:"/js/adhd-html5/sounds/beep-01a.mp3", id:"Beep"}
]
};
lib.properties_adults = {
width: 800,
height: 600,
fps: 24,
color: "#999999",
manifest: [
{src:"/js/adhd-html5/sounds/arsp018wav.mp3", id:"arsp018wav"},
{src:"/js/adhd-html5/sounds/assp022wav.mp3", id:"assp022wav"},
{src:"/js/adhd-html5/sounds/assp023wav.mp3", id:"assp023wav"},
{src:"/js/adhd-html5/sounds/babyCry.mp3", id:"babyCry"},
{src:"/js/adhd-html5/sounds/car_brakes.mp3", id:"BIKE2WAV"},
{src:"/js/adhd-html5/sounds/bottle_pop_2.mp3", id:"bottle_pop_2"},
{src:"/js/adhd-html5/sounds/carbrake01wav.mp3", id:"carbrake01wav"},
{src:"/js/adhd-html5/sounds/chsp016wav.mp3", id:"chsp016wav"},
{src:"/js/adhd-html5/sounds/copcar.mp3", id:"copcar"},
{src:"/js/adhd-html5/sounds/DogBarking02wav.mp3", id:"DogBarking02wav"},
{src:"/js/adhd-html5/sounds/flasher_coat_mono.mp3", id:"flasher_coat_mono"},
{src:"/js/adhd-html5/sounds/pouringliquid1.mp3", id:"pouringliquid1"},
{src:"/js/adhd-html5/sounds/arguing_couple.mp3", id:"arguing_couple"},
{src:"/js/adhd-html5/sounds/barking_dog.mp3", id:"barking_dog"},
{src:"/js/adhd-html5/sounds/police_car.mp3", id:"police_car"},
{src:"/js/adhd-html5/sounds/baby_crying.mp3", id:"baby_crying"},
{src:"/js/adhd-html5/sounds/smoking.mp3", id:"smoking"},
{src:"/js/adhd-html5/sounds/beep-01a.mp3", id:"Beep"}
]
};
De uiteindelijke payload bevatte alleen de timing van mijn spatiebalk-aanslagen, de timing van mijn "foute" aanslagen en de totale tijd dat het venster niet in focus was. Ik vroeg me af hoe dat alleen een diagnose kon opleveren. Ik kon enkele gissingen doen, maar het scoringsmodel was nergens in de broncode duidelijk aanwezig.
Ik zocht verder op de officiële pagina van de testsite en leerde meer over hoe de score wordt bepaald. Een citaat van de site: "Gestandaardiseerde Z-scores worden aangeboden voor vier verschillende aandachtsmetrieken: Aandacht, Tijdigheid, Hyper-reactiviteit en Impulsiviteit. Scores worden gestandaardiseerd op basis van een op leeftijd en geslacht afgestemde normgroep."
Berekening van de score
De vier metrieken zijn als volgt gedefinieerd:
Aandacht (A) Aandacht weerspiegelt het vermogen van de patiënt om een stimulus correct te evalueren en te reageren volgens de instructies. Patiënten die problemen ervaren in dit gebied hebben moeite met het letten op hun omgeving, of op specifieke details wanneer dat vereist is. Voor een toeschouwer kan iemand die geen aandacht lijkt te schenken, enigszins ongefocust en afgehaakt overkomen. Echter, dergelijke patiënten kampen met intense moeilijkheden in hun dagelijks leven, zoals het volgen van leraren in de klas, het begrijpen van complexere instructies, het bijhouden van kleine veranderingen in hun omgeving, het vermijden van rekenfouten en veel meer.
Tijdigheid (T) Tijdigheid weerspiegelt het vermogen van de patiënt om correct te reageren binnen het tijdskader dat aan een taak is toegewezen. Hoewel iemand met timingproblemen in staat kan zijn om hun omgeving correct te evalueren, kunnen ze falen wanneer gevraagd wordt om tijdig te reageren op omgevingsveranderingen. Voorbeelden hiervan zijn het uitvoeren van taken die een snelle en onmiddellijke reactie vereisen, evenals het schema's volgen. Dergelijke taken kunnen het beantwoorden van vragen onder tijdsdruk omvatten (zelfs wanneer het materiaal bekend is). Timingproblemen vertonen vergelijkbare kenmerken als aandachtsproblemen: er ontstaat een tijdsgat bij het proberen een taak te voltooien. Omdat het moeilijk is om bij te houden, ontstaat er een gat in het (studiemateriaal). Naarmate de taak voortduurt, vergroot dit gat zich totdat mensen die met dit type moeilijkheid kampen, uiteindelijk het gevoel van continuïteit en hun vermogen om de taak bij te houden, verliezen.
Impulsiviteit (I) Impulsiviteit is de neiging om te reageren op een tijdstip dat als 'verboden' is gedefinieerd. Iemand met een neiging tot impulsiviteit kan handelen zonder rekening te houden met de huidige situatie of de mogelijke uitkomsten van dergelijk gedrag. Dit gedrag kan plaatsvinden, zelfs wanneer een persoon de meer problematische en ongewenste resultaten van impulsief gedrag volledig begrijpt. In veel gevallen kan impulsiviteit ervoor zorgen dat mensen monitoringprocessen pas triggeren ná hun initiële reactie. Typische kenmerken van impulsiviteit zijn moeite met het wachten op een beurt of het aangaan van gevaarlijk gedrag zonder de consequenties te overwegen.
Hyper-reactiviteit (H) Hyperactiviteit is moeite met de efficiënte regulatie van motorische output en het onthouden van onnodige of ongewenste acties (beweging, overmatig praten, etc.). Met andere woorden, hyper-reactief gedrag zal gepaard gaan met excessieve reacties die als incorrect en ongewenst zijn gedefinieerd. Vaak zijn mensen die hyperactiviteit vertonen zich bewust van de ongewenste resultaten van hun gedrag, en toch staan ze voor de moeilijke uitdaging om dergelijke acties na te laten.
De resultaten bespreken
"Heeft u op enige manier geprobeerd het examen te sjoemelen?" vroeg de psychiater.
Was er een DevTools-val in een van de scripts? Was het de focus-hook? Ongeacht dat, ik probeerde niet te sjoemelen met het examen. Ik vertelde de psychiater dat ik mijn best had gedaan, maar dat het aan het einde voelde alsof het examen nooit zou eindigen, waardoor ik overging op het gedachteloos indrukken van mijn spatiebalk.
Ze vertelde me dat de grafieken zo ver buiten de norm lagen dat, zolang ik beloofde niet te hebben gesjoemeld, ze me het examen opnieuw zou laten doen. Ik beloofde haar dat ik niet had geprobeerd te sjoemelen, dus plande ze voor de volgende week een nieuw examen.
Een tweede kans
Toen de dag van de herkansing eindelijk aanbrak, klikte ik op "Begin Test" en begon ik herhaaldelijk op de spatiebalk te drukken. Deze keer deed ik mijn uiterste best om gefocust te blijven en de drang om op de spatiebalk te rammen te weerstaan.
Aan het einde vertelde ze me dat ze mijn examen zou beoordelen en de resultaten over enkele dagen klaar zou hebben.
Ik begon me af te vragen hoe de test eruitzag vanuit de zijde van mijn psychiater. Hoe werd het beoordeeld? Ik spulde nog wat verder in de opgeslagen broncode en stuitte op een interessante functie:
function sendParentReportToClinic(testId) {
var clinicEmail = $('#clinicEmail').val();
var data = {"test_id": testId, "clinic_email": clinicEmail};
$.ajax({
type: 'POST',
async: true,
dataType: 'json',
data: data,
url: location.protocol + '//' + location.host + '/api/tests/send_parent_report',
success: function (data) {
alert(data.data);
},
error: function(error) {
var errorText = $.parseJSON(error.responseText).message;
alert(errorText);
}
});
}
Deze functie stuurde het uiteindelijke rapport naar de kliniek. Alles wat nodig was, was het e-mailadres van de kliniek en het test-ID. Als de backend slordig was, zou ik theoretisch elk e-mailadres als kliniekadres kunnen opgeven, mijn test-ID (of een willekeurig test-ID) invoeren en het rapport naar mezelf kunnen laten sturen. Ik zette het verzoek om in een cURL-commando en probeerde precies dat:
curl -X POST 'https://adhd-test/api/tests/send_parent_report' \
-H 'Accept: application/json' \
--data-urlencode 'test_id=1010101' \
--data-urlencode 'clinic_email=email@example.com'
Ik ontving geen rapport. In plaats daarvan bevatte de respons HTML voor een inlogpagina. Wanneer ik naar het eindpunt navigeerde in mijn browser, merkte ik een aanmeldknop op. Alles wat nodig was, was een e-mailadres, wachtwoord en basisinformatie zoals mijn naam en telefoonnummer. Na het aanmelden werd ik meegenomen naar een dashboard waar ik cliënten kon toevoegen en mijn eigen tests kon beheren. Dit was geen verborgen dashboard dat ik per ongeluk had ontdekt; de service leek zorgverleners in staat te stellen proefaccounts aan te maken om het product te testen.
(Bijschrift: Het dashboard voor zorgverleners waarop de twee voltooide tests te zien zijn.)
Gecontroleerd experiment
De proefperiode liet me twee gratis tests afnemen, dus ik had een plan: ik zou mezelf twee tests geven, één waarbij ik uiteindelijk de spatiebalk zou rammen vergelijkbaar met mijn eerste poging, en een andere waarbij ik de test normaal zou doen, zoals tijdens de herkansing.
Na mezelf als cliënt toe te voegen en de testuitnodigingen te versturen, deed ik precies dat. De rapporten verschenen spoedig in het dashboard, klaar voor review.
De experimenten vergelijken
De "spam"-test
Kijkend naar de resultaten van dit examen werd het onmiddellijk duidelijk waarom de psychiater dacht dat ik had gesjoemeld. Ten eerste is het rapport gemarkeerd als "lage geloofwaardigheid" (low credibility). De grafieken voor normvergelijking maakten ook duidelijk dat er iets mis was.
(Bijschrift: Resultaten van de test waarbij de spatiebalk werd geramd.)
De serieuze poging
De resultaten van mijn serieuze poging zagen er veel... normaler uit? De geloofwaardigheidsindicator was groen, geweldig. De normvergelijkingen leken ook redelijk in lijn, waarbij het enige dat opviel Impulsiviteit was, waar ik werd gemarkeerd als iemand met een hoger dan normale impulsiviteit.
(Bijschriften: Normvergelijkingen en prestaties over de fasen van mijn serieuze poging. De groene geloofwaardigheidsindicator van mijn serieuze poging.)
De site bood aan het einde een nuttige samenvatting:
"Op basis van vergelijkingen met normen voor leeftijd en geslacht is een significante afwijking van de norm gedetecteerd in de I-prestatie van Null Ptr. Dit prestatiepatroon kan wijzen op aandachtsproblemen en, in combinatie met andere bevindingen, een verhoogde waarschijnlijkheid voor het bestaan van ADHD."
Samenvatting van de prestaties van Null Ptr in vergelijking met basisresultaten:
- De prestaties van Null Ptr bij aanhoudende aandacht wezen op een stabiele prestatie in metrieken A, T, H, I.
- De prestaties van Null Ptr in aanwezigheid van visuele afleiders wezen op een stabiele prestatie in metrieken A, T, H, I.
- De prestaties van Null Ptr in aanwezigheid van auditieve afleiders wezen op een toename in metriek I en een stabiele prestatie in metrieken A, T, H.
- De prestaties van Null Ptr in aanwezigheid van gecombineerde audio-visuele afleiders wezen op een stabiele prestatie in metrieken A, T, H, I.
- De prestaties van Null Ptr in aanwezigheid van een hoge afleidingslast wezen op een toename in metriek I, een afname in metriek T en een stabiele prestatie in metrieken A, H.
Het model vond een verhoogde waarschijnlijkheid dat ik ADHD had vanwege mijn impulsiviteit. Dit was interessant, maar ik wachtte nog steeds op mijn vervolgafspraak met de psychiater om te zien wat de officiële test zou uitwijzen.
Een vriend laten proberen
Uit nieuwsgierigheid liet ik mijn vriend Haze de test ook doen. Het was interessant om te zien hoeveel geduldiger hij was dan ik. Nadat ik hem 18 minuten lang op de spatiebalk had zien drukken, luidden zijn resultaten:
"Volgens de normvergelijkingstabel is er een lage waarschijnlijkheid dat Haze aandachtsproblemen heeft."
Samenvatting van de prestaties van Haze in vergelijking met basisresultaten:
- De prestaties van Haze bij aanhoudende aandacht wezen op een stabiele prestatie in metrieken A, T, H, I.
- De prestaties van Haze in aanwezigheid van visuele afleiders wezen op een stabiele prestatie in metrieken A, T, H, I.
- De prestaties van Haze in aanwezigheid van auditieve afleiders wezen op een stabiele prestatie in metrieken A, T, H, I.
- De prestaties van Haze in aanwezigheid van gecombineerde audio-visuele afleiders wezen op een stabiele prestatie in metrieken A, T, H, I.
- De prestaties van Haze in aanwezigheid van een hoge afleidingslast wezen op een toename in metriek T en een stabiele prestatie in metrieken A, I, H.
(Bijschrift: Mijn vriend Haze die de ADHD-test aflegt.)
Opvolging bij de psychiater
Tijdens de vervolgafspraak vertelde de psychiater me dat ik inderdaad ADHD had en dat mijn impulsiviteit hoog was. Surprised Pikachu. Ik was niet zeker wat dit betekende voor mijn toekomst. Ik had mijn hele schooltijd ongediagnosticeerd doorgebracht. Achteraf gezien had het overduidelijk moeten zijn. Mijn cijfers waren verschrikkelijk in elk vak, behalve informatica, waar ik uitzonderlijk goed scoorde.
Ik zal deze diagnose niet gebruiken om elke beslissing die ik ooit heb genomen te verklaren, maar het helpt me om ze anders te begrijpen.
Geniet nu van deze foto die ik door mijn telescoop heb gemaakt:
(Bijschrift: De maan, gefotografeerd met een Canon EOS R5 door een Celestron NexStar 5SE.)
Groetjes,