• No results found

4.2 Progression

4.2.3 Insamling av data

Insamlingen av data består av två delar, dels tidtagning och insamling av tiden för varje uppgift samt insamling av svar på ett antal frågor i en enkät. För att göra mätningar av tid finns två huvudsakliga javascript-funktioner – Date.now() och performance.now().

Date.now() returnerar ett absolut värde (antalet millisekunder sedan 1 Januari, 1970 00:00:00 UTC) och perfomance.now() returnerar ett värde relativt till när sidan laddades in.

Om mätning görs på samma sida kan båda metoderna användas men i denna studie kommer tiden att startas på en sida och stoppas på en annan vilket gör att Date.now() är bättre lämpad för ändamålet. En nackdel med detta är att Date.now() har lägre upplösning än perfomance.now() men mätsäkerhet över millisekunder bedöms inte som nödvändigt och därför kommer Date.now() att användas.

Tiden startas med funktionen startTask() när användaren klickar på knappen ‖Start task‖. I denna funktion döljs instruktionsgränssnittet och Date.now() kallas och sparas till localstorage. Detta värde är uppgiftens starttid. När användaren klickar på ett element med klassen ‖solution‖ (denna klass tilldelas element som används som lösning för någon uppgift) kontrolleras elementets ‖data-solution‖-attributvärde. Detta attribut består av en siffra (som symboliserar den uppgift elementet är lösning till – värdet ‖0‖ betyder att elementet är lösning för den första uppgiften, uppgift 0). Om värdet motsvarar det värde som finns i currentTask kallas funktionen nextTask(). I nextTask() kallas Date.now() igen vilket ger uppgiftens sluttid. Genom att subtrahera starttiden från sluttiden och sedan dividera svaret med 1000 fås tiden för uppgiften i sekunder. Denna tid sparas sedan i localstorage tillsammans med tidigare tidtagningar. currentTask ökas till nästa uppgift (ökas med 1), om currentTask är större än antalet tasks som finns omdirigeras användaren till enkäten. Om currentTask är en giltig uppgift uppdateras instruktionsgränssnittet med denna och visas återigen. Hur detta implementerades3 visas i figur 11.

//stops timer, saves time in localstorage, increments currentTask. If all the tasks are done redirects to questionnaire page, otherwise show instructions for next task

const nextTask = () => { const stopTime = Date.now();

const startTime = localStorage.getItem('taskStart');

const totalTime = (stopTime - startTime) / 1000;

const taskTime = {task: currentTask, time: totalTime}

taskTimes.push(taskTime);

localStorage.setItem('taskTimes', JSON.stringify(taskTimes)) currentTask++;

currentTask > tasks.length - 1 && (window.location.href = './Form.php');

localStorage.setItem('currentTask', currentTask) instruction.textContent = tasks[currentTask];

instructions.style.display = 'flex';

localStorage.setItem('instructions-status', 'shown');

}

Figur 11 Implementation av tidtagning för uppgiftslösning.

För att samla in enkätsvar används ett form-element bestående av ett antal input-element (med tillhörande label-element). Denna form har ett action-attribut med värdet

‖./Thanks.php‖ som är den sida där koden som hanterar det inskickade formuläret finns. På denna sida tackas också deltagaren för sitt deltagande. Denna kod är till största del baserad på tidigare nämnda kodstycke av Mike Stratton (2020). Koden läser in innehållet från filen dataA.json (och motsvarande dataB.json för B-applikationen, den utan ljud). När formuläret skickas in sparas svaren i en array. För att taskTimes skall bli rätt format måste funktionen json_decode() kallas. Sedan läggs denna array till i slutet av det inlästa innehållet från filen.

Sedan formateras detta med json_encode() och skrivs till filen. På detta sätt påverkas inte data som samlats in från tidigare testpersoner. Det finns en liten risk att flera personer skickar in sina formulär exakt samtidigt. Detta kan göra att data inte sparas korrekt. Om innehållet i filen läses in samtidigt kommer endast den sista som skriver till filen att sparas korrekt eftersom den läser innehållet i filen och sedan lägger till den nya datan i slutet av filen. Om inläsning sker före någon annan skriver data till filen kommer detta att skriver

över. Risken för detta bedöms som relativt liten då undersökningen och datainsamlingen kommer att ske över en tid på en till två veckor. Ett sätt att undvika detta hade kunnat vara att använda en databas för datainsamlingen. Detta bedömdes som överflödigt då studien är av relativt liten skala. Koden som hanterar detta kan ses i figur 124.

$file = "../../Data/dataA.json"; 'taskTimes' => json_decode($_POST['taskTimes']) );

$array[] = $arr;

$json_string = json_encode($array);

file_put_contents($file, $json_string);

}

Figur 12 Formulärhantering baserad på kod av Mike Stratton.

4.2.4 Simulering av synnedsättning

Simulering av synnedsättningar kan göras på ett antal olika sätt, dels med rent fysiska lösningar så som tidigare nämnda ‖Sim Specs‖ som är glasögon som på olika sätt obstruerar synfältet för att likna olika synnedsättningar men även mer tekniska lösningar som de VR- och AR-simuleringar av Lewis m.fl. (2011) och Ates m.fl.(2015). I detta arbete kommer en mjukvarusimulering att användas. Denna simulering kommer att baseras på bilder av simuleringarna av Lewis m.fl., Ates m.fl., bilder från Finlands Svenska Synskadades Förbunds hemsida (u.å.) samt Google Chrome pluginen NoCoffee (Leventhal 2013).

Implementationen kommer att baseras på hur NoCoffee implementerar sina synnedsättningssimuleringar.

NoCoffees implementation av simulering av macular degeneration, glaucoma och hemianopia gjordes med hjälp av ett absolut positionerat div-element som täcker hela skärmen5. På detta div-element applicerades sedan en bakgrund i form av en bakgrund-bild bestående av en css-gradient. Denna implementation kan lätt förändras och anpassas och ansågs därför lämplig för detta arbete. I de fall viss synskärpenedsättning simulerades applicerar NoCoffee ett filter på html-elementet (se figur 13). Denna implementationsteknik fungerar väl meneftersom instruktioner till testdeltagarna kommer att visas på sidan är det inte fördelaktigt att applicera filter på html-elementet eftersom detta skulle göra att filtret även applicerades på instruktionerna. Istället applicerades ett backdrop-filter på det absolut positionerade div-elementet. Ett backdrop-filter fungerar som ett vanligt filter men istället för att förändra det element det appliceras på (och dess children) appliceras effekten på de element som befinner sig bakom elementet med ett backdrop-filter. Eftersom det absolut

4 https://github.com/c14jonfr/Examensarbete/commit/3c83121

positionerade div-elementet täcker hela sidan appliceras effekten på hela sidan. Genom att sedan placera elementet som skall visa upp instruktioner för testdeltagarna framför detta absolut positionerade div-element kan filtret appliceras endast på de element där det önskas.

.vis-container{

position: absolute;

top: 0;

bottom: 0;

left: 0;

right: 0;

z-index: 99;

pointer-events: none;

}

.macular-degeneration{

background-image:-webkit-radial-gradient(circle, rgba(150, 150, 150, 0.9400000000000001) 20%, transparent 50%);

}

.glaucoma{

background-image: -webkit-radial-gradient(circle, transparent 30%, black 70%);

}

.hemianopia{

background-image: -webkit-linear-gradient(left, black 20%, transparent 50%);

}

Figur 13 Implementation av olika synnedsättningssimuleringar.

Användandet av backdrop-filter fungerade väl i Google Chrome och Microsoft Edge men fungerade inte i Mozilla Firefox där filtret inte gjorde någon skillnad. Det visade sig att Mozilla Firefox har stöd för backdrop-filter men att detta inte är aktiverat per standard utan måste aktiveras manuellt av användaren. Detta är inget som kan förväntas av testdeltagarna och därför krävdes en annan lösning. Lösningen blev ett svg-filter6. Ett svg-element innehållandes ett filter (i detta fall ett gaussian blur filter) med ett id kan filtret användas i CSS med ‖url(#filterid)‖. Hur detta implementerades kan ses i Figur 14. Denna implementation fungerar för Google Chrome, Microsoft Edge samt Mozilla Firefox (och troligtvis fler webbläsare men dessa tre är de som testats under utvecklingen).

//HTML

<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://w ww.w3.org/1999/xlink">

<filter id="blur">

<feGaussianBlur in="SourceGraphic" stdDeviation="1" />

</filter>

</svg>

//CSS

.blur-filter{

filter: url(#blur);

}

Figur 14 Filterimplementation med hjälp av SVG-filter.

För implementationen av Cataracts och Diabetic Retinopathy användes bilder skapade i Affinity Photo, se figur 15. Dessa sätts som bakgrundsbild på VIS-elementet och fungerar då jämlikt med filter-funktionaliteten7.

.diabetic-retinopathy{

-webkit-transform: scale(1);

-webkit-transform-origin: 0 0;

background-image: url('./Images/DiabeticRetinopathy.jpg');

background-repeat: no-repeat;

background-size: 100% 100%;

background-position: 0 0;

-webkit-filter: opacity(66%);

}

Figur 15 Implementation av simuleringar som använder bakgrundsbild.

Bilderna skapades utifrån de exempelbilder som finns tillgängliga på Förbundet Finlands Svenska Synskadades hemsida, simuleringarna i NoCoffee-pluginen samt studien av Ates m.fl. (2015). Bilderna skapades i Affinity Photo. Bilden som skapades för att simulera Diabetic Retinopathy kan ses i figur 16 nedan.

Figur 16 Exempel på bild som används för att simulera synnedsättning

(‘DiabeticRetinopathy.jpg‘ som implementeras i figur 15).

Related documents