Upload
phungquynh
View
219
Download
0
Embed Size (px)
Citation preview
Elektroniskt Skyttesystem
Databearbetning & Presentation
Electronic Scoring System
Data Processing & Presentation
Andreas Bergman
Fakulteten för hälsa, natur- och teknikvetenskap
Datavetenskap
Examensarbete 30 hp
Handledare: Kerstin Andersson
Examinator: Thijs J Holleboom
Oppositionsdatum: 2016-06-07
i
Sammanfattning
Denna rapport beskriver ett projekt med målet att utveckla ett elektroniskt skyttesystem
utifrån mindre kostsamma standardkomponenter. Det utvecklade systemet avses inneha
funktionalitet som är jämförbar med befintliga sådana system. En utredning av det utvecklade
systemets precision ämnas utföras, och om precisionen visar sig vara undermålig behöver en
utredning ge förslag på ytterligare hårdvara som krävs för att nå en högre sådan.
Projektet resulterade i ett delvis sammankopplat, fungerande system. Systemet består av
fysiska komponenter, en databas och en visningsklientsapplikation som bearbetar och
presenterar data. Systemets fysiska komponenter innefattar fyra mikrofoner och en Raspberry
Pi 2-enhet. Mikrofonerna registrerar ljudankomster och signalerar dessa till Raspberry-
enheten, som sparar data i databasen. Denna data hämtas, bearbetas och visualiseras av
visningsklienten.
Systemet saknar i nuläget en fysisk träffyta, och precisionsbrister hos dess fysiska
komponenter resulterar i opålitliga resultat, då mätvärden är okonsekventa utifrån upprepade
träffar på en specifik position.
ii
Abstract
This report describes a project with the goal of developing an electronic scoring system from
less costly standard components. The developed system means to have comparable
functionality to existing such systems. An analysis of the developed system’s precision is
intended to be performed, and if the precision is found to be substandard an investigation
needs suggest further hardware necessary for reaching a higher one.
The project resulted in a partially connected, functioning system. The system consists of
physical components, a database and a visual client application that processes and presents
data. The system’s physical components comprises four microphones and a Raspberry Pi 2
unit. The microphones register sound arrivals and signal these to the Raspberry unit, which
saves data in the database. This data is retrieved, processed and presented by the visual client.
The system currently lacks a physical target surface, and precision flaws in the system’s
physical components result in unreliable results, since readings are inconsistent from repeated
hits at a specific position.
iii
Innehållsförteckning
1 Inledning ............................................................................................................................ 1
1.1 Projektmål .................................................................................................................. 1
1.2 Projektets uppdelning ................................................................................................ 2
1.3 Rapportstruktur .......................................................................................................... 3
2 Bakgrund............................................................................................................................ 4
2.1 Sogeti Sverige AB ..................................................................................................... 4
2.2 Elektroniska skyttesystem.......................................................................................... 4
2.3 Problemformulering ................................................................................................... 6
2.4 Systemkomponenter................................................................................................... 6 2.4.1 Mikrofoner 2.4.2 Raspberry Pi 2 2.4.3 Databas 2.4.4 Visningsklient
2.5 Utvecklingsmiljö ...................................................................................................... 12
2.6 Kapitelsammanfattning ............................................................................................ 12
3 Design ............................................................................................................................... 14
3.1 Systemets övergripande design ................................................................................ 14
3.2 Mikrofoner ............................................................................................................... 15
3.3 Raspberry-enhet ....................................................................................................... 15
3.4 Application Programming Interface ........................................................................ 16
3.5 Databas..................................................................................................................... 16 3.5.1 Molnlösning kontra SQLite 3.5.2 Databaskommunikation genom ramverket Entity Framework
3.6 Data .......................................................................................................................... 18 3.6.1 Mätdata 3.6.2 Databasdata
3.7 Visningsklient .......................................................................................................... 19 3.7.1 Användargränssnitt 3.7.2 Övergripande bakgrundsfunktionalitet 3.7.3 Hämtning av data från databasen
3.8 Träffsimulering ........................................................................................................ 29 3.8.1 Testapplikationens vyklass 3.8.2 Testapplikationens datahanteringsklass
iv
3.9 Kapitelsammanfattning ............................................................................................ 32
4 Implementation................................................................................................................ 33
4.1 Azure SQL-server & databas ................................................................................... 33
4.2 Utvecklingsmiljöns databasdesigner........................................................................ 35
4.3 Visningsklient .......................................................................................................... 37 4.3.1 Ramverksimplementation 4.3.2 Användargränssnitt 4.3.3 Vyklass 4.3.4 Datahanteringsklass
4.4 Testapplikation......................................................................................................... 51 4.4.1 Vyklass 4.4.2 Datahanteringsklass
4.5 Kapitelsammanfattning ............................................................................................ 56
5 Resultat ............................................................................................................................. 57
5.1 Resultatsammanfattning........................................................................................... 57
5.2 Fysiska komponenter ............................................................................................... 58 5.2.1 Träffyta 5.2.2 Raspberry-enhet 5.2.3 Systemets precision
5.3 Molnet ...................................................................................................................... 60 5.3.1 API 5.3.2 Databas
5.4 Visningsklient .......................................................................................................... 61
5.5 Hela systemet sammankopplat................................................................................. 62
5.6 Kapitelsammanfattning ............................................................................................ 63
6 Slutsats.............................................................................................................................. 64
6.1 Projektutvärdering ................................................................................................... 64 6.1.1 Utvecklingen 6.1.2 Prototypen 6.1.3 Uppdragsgivaren
6.2 Framtida arbete ........................................................................................................ 66 6.2.1 Systemfunktionalitet för flera enheter 6.2.2 Datahämtning och användargränssnittsuppdatering 6.2.3 Enhetlig API-implementation 6.2.4 Systemets databassäkerhet
6.3 Slutord ...................................................................................................................... 68
Referenser ............................................................................................................................... 70
A Kravspecifikation av Mats Persson ............................................................................... 72
A.1. Allmän beskrivning av uppdraget ............................................................................. 72 A.1.1 Bakgrund
A.2. Markeringssystem ..................................................................................................... 72 A.2.1 Raspberry Pi 2
v
A.2.2 Visningsklienten A.2.3 Utredning A.2.4 Optioner
A.3. Genomförande/arbetssätt ........................................................................................... 75 A.3.1 Rutiner A.3.2 Hårdvara A.3.3 Genomförande
A.4. Stöd/kvalitetssäkring ................................................................................................. 75 A.4.1 Granskningar A.4.2 Testarbete A.4.3 Stöd
A.5. Leveranser ................................................................................................................. 76 A.5.1 Dokumentation
A.6. Konfigurationsstyrning .............................................................................................. 76
A.7. Miljö .......................................................................................................................... 76
A.8. Uppföljning och Rapportering................................................................................... 76 A.8.1 Rapportering internt/externt
B Resultat för ljudankomster till systemets mikrofonkomponenter ................................. 77
vi
Figurförteckning
1.1: Design av ett önskat elektroniskt skyttesystem...................................................................1
1.2: Illustrerad systemdesign och dess uppdelning.....................................................................2
2.1: Existerande system på en skyttebana [5], samt måltavlor [6]..............................................5
2.2: Tvådimensionell trilateration...............................................................................................5
2.3: SparkFun Sound Detector [8]..............................................................................................7
2.4: Illustration av förfrågandeprocessen mellan användare och databas...................................9
2.5: Överblick av Entity Frameworks tre användningsområden [17].......................................10
2.6: Microsoft Azure Webbportal.............................................................................................11
3.1: Illustrerad design av det elektroniska skyttesystemet........................................................14
3.2: Mikrofon med markerade portar........................................................................................15
3.3: DbContext illustrerad [29].................................................................................................18
3.4: Övergripande bild av data till databas genom en Raspberry-enhet...................................19
3.5: Illustration av visningsklientens användargränssnittsdesign.............................................20
3.6: Illustrerad WPF-designer i utvecklingsmiljön [32]...........................................................20
3.7: Illustration av visningsklientens klasser i dess bakgrundsfunktionalitet...........................22
3.8: Visningsklientens illustrerade vyklassmetoder och ramverksbaserade
datahanteringsklassmetoder...............................................................................................23
3.9: Den listbaserade visningsklientens illustrerade datahanteringsklassmetoder....................26
3.10: Illustration av visningsklient, testapplikation och databas..............................................30
4.1: Brandväggsregler för SQL-servern i Azureportalen..........................................................35
4.2: Utvecklingsmiljöns databasdesigner för databastabellen shots,
samt databastabellen shots i utvecklingsmiljöns utforskare..............................................37
4.3: Visningsklientens användargränssnitt i utvecklingsmiljöns WPF-designer......................42
4.4: Kvadratinramad ellipsform, med faktiska och önskade koordinater.................................45
4.5: Illustrerat poängområde i träffytan, inklusive dess breddvärde.........................................51
5.1: Omonterade, numrerade mikrofoner, samt en markerad träffpunkt p...............................60
vii
5.2: Utökad design av det elektroniska skyttesystemet ............................................................61
5.3: Illustrerad visningsklient....................................................................................................63
1
1 Inledning
Detta kapitel ämnar introducera projektets mål, samt beskriva den projektuppdelning som
projektutvecklarna gjort. Detta följs av en övergripande och kortfattad beskrivning av
rapportens struktur och innehåll.
1.1 Projektmål
Målet med projektet var att utveckla ett elektroniskt skyttesystem utifrån mindre kostsamma
komponenter jämförbart med befintliga system som i nuläget finns på marknaden (se bilaga
A.1.1). Ett prototypsystem avsågs implementeras (se bilaga A.2), bestående av fysiska
komponenter och en visningsklient. Ett sådant system, utifrån uppdragsgivarens önskade
design, illustreras i Figur 1.1. När systemet sammankopplats skulle det reagera när
mikrofonkomponenter tog emot ljud och läsa in mätvärden utifrån dem. Dessa mätvärden
skulle sparas in i en databas tillsammans med en enhetsidentitet tillhörande den Raspberry Pi
2-enhet som mikrofonerna kopplats till. Ur denna databas skulle sedan visningsklienten hämta
datan, beräkna en träffposition och visualisera denna överskådligt för en användare. Det
utvecklade systemets möjliga precision skulle sedan undersökas; om precisionen visade sig
undermålig skulle projektutvecklarna utreda vilken typ av hårdvara som behövdes för att nå
en högre sådan.
Figur 1.1: Design av ett önskat elektroniskt skyttesystem (bilaga A.2)
2
I kravspecifikationen fanns även förslag på vidareutveckling (se bilaga A.2.4.1), vilket
innefattade beräkning och presentation av träffresultat, systemhantering av flera Raspberry-
enheter och träffytor, samt en administrationsdel. Genom denna administrationsdel skulle man
kunna se vilka träffytor som finns tillgängliga, sätta upp en tävling mellan användare samt
presentera en vinnare efter en träffserie.
1.2 Projektets uppdelning
Detta projekt valdes att delas upp i två delar, illustrerade i Figur 1.2. Den första delen rör
systemets fysiska komponenter, den beräkning som sker kring dessa, samt den data som
lagras i systemets databas. Den första delen beskrivs endast övergripligt i denna rapport; den
får istället större fokus i rapporten författad av Niklas Ivarsson [1].
Den andra delen rör systemets databas, visningsklient och träffsimuleringsapplikation som
togs fram i testsyfte. Denna rapport beskriver hur en databas sätts upp och struktureras, hur
kommunikation mellan denna databas och en visningsklient sker, hur data används för att
beräkna och visualisera relevant information i visningsklienten, samt hur en testapplikation
kan simulera värden och skicka dessa till databasen i syfte att testa visningsklienten.
Figur 1.2: Illustrerad systemdesign och dess uppdelning
3
1.3 Rapportstruktur
Detta avsnitt beskriver övergripande och kortfattat rapportens struktur och innehåll.
Kapitel 1 introducerar projektets mål, samt beskriver den projektuppdelning som
projektutvecklarna gjort.
Kapitel 2 beskriver projektets bakgrund. Detta innefattar beskrivningar av uppdragsgivaren,
hur befintliga system fungerar, samt den problemformulering som ställts i uppdragsgivarens
kravspecifikation. Därefter följer beskrivningar av systemets komponenter, samt den
utvecklingsmiljö som används för att utveckla systemets visningsklient.
Kapitel 3 beskriver designen för systemets olika komponenter, först övergripande och sedan
för dess individuella komponenter. I kapitlet beskrivs även vissa designbeslut som tagits för
systemet och dess komponenter, till exempel rörande systemets databas och visningsklient.
En beskrivning av en fristående testapplikation återfinns även här, vars syfte är att simulera
träffar för testning av systemets visningsklient. Designen för de komponenter som befinner
sig i uppdelningens första del beskrivs endast kortfattat i detta kapitel; större fokus ligger
kring de komponenter som befinner sig i den andra delen (se avsnitt 1.2).
Kapitel 4 beskriver systemets implementation, rörande dess databas och visningsklient, samt
den fristående testapplikationen som tidigare nämnts. Detta kapitel beskriver endast
implementationen av de komponenter som befinner sig i uppdelningens andra del.
Kapitel 5 redovisar projektets gemensamma resultat, utifrån systemets individuella
komponenter samt det slutgiltiga, sammankopplade systemet.
Kapitel 6 redovisar rapportförfattarens slutsatser kring projektet. Detta innefattar en
utvärdering av projektutvecklingen, den slutgiltiga prototypen samt uppdragsgivaren. Ett
avsnitt tar sedan upp de möjligheter som finns till framtida utveckling och optimering av
systemet. Kapitlet avslutas med ett avsnitt innehållande rapportförfattarens slutord.
4
2 Bakgrund
Det här kapitlet ämnar ge bakgrundsinformation kring uppdragsgivaren, den
problemformulering som ställts, och det system som under projektets gång avsågs utvecklas.
Detta innefattar systemets komponenter, den teknik som användes för att utveckla systemets
visningsklient, samt den utvecklingsmiljö som användes för att utveckla
systemapplikationerna.
2.1 Sogeti Sverige AB
Sogeti Sverige AB (Sogeti) är ett IT-konsultbolag med en bred verksamhet och ett stort fokus
på kompetens och modern teknik (se bilaga A.1.1). Bolaget bildades 1 januari 2003 [2] och är
en del av den franska Capgemini-koncernen, ett av världens största konsult- och
teknologiföretag med över 180 000 anställda i över 40 länder [3].
Ett projektuppdrag togs fram utifrån ett personligt intresse som fanns på det Karlstadbaserade
kontoret rörande elektroniska skyttesystem.
2.2 Elektroniska skyttesystem
Automatiserade elektroniska skyttesystem används inom sportskytte för att visualisera
träffplacering och räkna ut resultat. Detta möjliggör en omedelbar och precis återkoppling till
skytten, samtidigt som det underlättar för tävlingsorganisatörer och publik [4].
Existerande system består av måltavlor med monterade sensorer, samt monitorer som
visualiserar träffytan, träffar och resultat (se Figur 2.1 (a)). Dessa måltavlor kan vara så
kallade mjuka eller hårda (se Figur 2.1 (b respektive c)). Mjuka måltavlor har sensorer som är
isolerade från träffytan och är stora men relativt lätta, medan hårda måltavlor har sensorer
monterade direkt på träffytan och en vikt som beror på byggmaterialet [6].
Olika systemtekniker existerar, där den vanligaste utnyttjar akustik; tre eller flera mikrofoner
känner med hjälp av trilateration [7] av var en kula träffat en yta (se bilaga A.1.1).
Trilateration går ut på att en position uppskattas utifrån olika punktavstånd (där punkterna i
detta fall är de mikrofoner som används), med hjälp av cirkel- eller triangelgeometri. Den
eftersökta positionen återfinns i det område där två eller flera sådana former skär varandra.
Figur 2.2 illustrerar hur en punkt P återfinns inom det område där tre cirklar med mittpunkter
p1, p2 och p3 skär varandra. Denna teknik har praktiska applikationer inom till exempel
fältmätning och positioneringssystem.
5
Figur 2.1: Existerande system på en skyttebana [5], samt måltavlor [6]
Figur 2.2: Tvådimensionell trilateration
6
2.3 Problemformulering
Elektroniska skyttesystem är i dagsläget förhållandevis dyra (se bilaga A.1.1). Därför vill
Sogeti utforska om liknande system kan utvecklas utifrån mindre kostsamma
standardkomponenter för att uppnå den precision som krävs. Alternativt vill Sogeti ha svar på
följande frågeställningar (se bilaga A.2.3):
Hur hög precision kan man komma upp i med den utrustning som tillhandahålls? (del
av mm, mm, cm, dm?)
Vilken typ av hårdvara skulle man behöva för att komma upp i högre precision?
Hur mycket skiljer det i precision med den tillgängliga utrustningen jämfört med de
kommersiella systemen som finns?
Figur 1.1 illustrerar den design som Sogeti har bidragit med av ett önskat skyttesystem med
flera komponenter: en träffyta med mikrofoner där en träff ska registreras, en Raspberry Pi 2
som skickar värden och enhetsnamn till en databas, vars innehåll visualiseras i en
visningsklient.
2.4 Systemkomponenter
I detta avsnitt kommer de fyra systemkomponenter illustrerade i Figur 1.1 att beskrivas. Dessa
innefattar systemets mikrofoner som registrerar träffljud, den Raspberry Pi 2-enhet som tar
emot och skickar vidare värden till en databas, samt den visningsklient som visualiserar
träffar och resultat för en användare.
2.4.1 Mikrofoner
Systemet har för avsikt att med hjälp av mikrofoner reagera på när dessa tar emot ljud av en
viss ljudnivå, och sedan uppskatta var en träff har skett (se bilaga A.2).
Härnäst följer en beskrivning av de mikrofoner som tillhandahållits, samt den
beräkningsmetod som utförs utifrån de ljudankomster som mikrofonerna registrerar.
7
2.4.1.1 SparkFun Sound Detector
De mikrofoner som Sogeti tillhandahöll var SparkFun Sound Detector (SEN-12642),
illustrerad i Figur 2.3. Dessa mikrofoner är små och användarvänliga, med tre möjliga
outputsignaler. Den första av dessa är ljudoutput, den andra en binär indikation av
ljudnärvaro, och den tredje är en analog representation av ljudamplituden. Dessa tre
outputsignaler är simultana och självständiga, vilket möjliggör utnyttjande av så få eller så
många signaler som krävs [8]. När en mikrofon lyckas ta emot ljud har den möjlighet att
indikera detta genom att en röd lampa på enheten tänds.
Figur 2.3: SparkFun Sound Detector [8]
2.4.1.2 Multilateration
För att uppskatta var på en yta en träff har skett används en teknik som kallas för
multilateration, där tidsskillnaden för ljudankomster till tre eller flera punkter mäts [9], och
där punkterna i detta fall är systemets mikrofonkomponenter. Denna teknik skiljer sig från
trilaterationstekniken, där uppskattningen gjordes utifrån punkternas olika absoluta avstånd
till varandra. Multilaterationstekniken går istället ut på att mäta tidskillnader mellan två
ankomstpunkter i taget. Den tidsskillnad som uppmäts resulterar i en hyperbel mellan de båda
ankomstpunkterna, med ett oändligt antal ursprungspositioner. Genom att utnyttja ytterligare
par av ankomstpunkter så kan en ursprungspunkt approximeras utifrån de skärningspunkter
som uppstår för de olika utmätta hyperblarna.
8
2.4.2 Raspberry Pi 2
I systemet kopplas mikrofonerna till en Raspberry Pi 2, som avser samla in mätvärden från
mikrofonerna och spara dessa samt en enhetensidentitet i en databas (se bilaga A.2).
Raspberry Pi 2 Model B är den andra generationen Raspberry Pi, som ersatte sin föregångare
Raspberry Pi 1 Model B+ i februari 2015. Denna nya version har byggt vidare på originalet
och kan erbjuda en fyrkärnig 900MHz processor samt 1GB RAM-minne, utöver den
funktionalitet som funnits tidigare, som till exempel portar för USB, Ethernet och HDMI,
samt kortingång för micro-SD [10]. Jämförelsevis kunde de föregående modellerna endast
erbjuda en enkärnig 700MHz processor och antingen 256MB eller 512MB RAM-minne
[11].
Detta avsnitt följs av en beskrivning av Raspberry-enhetens operativsystem. Därefter följer ett
avsnitt som beskriver den ytterligare hårdvara som Sogeti befarar krävs för tidsregistreringen,
eftersom Raspberry-enhetens I/O-ingångar kan vara för långsamma för de korta tider det rör
sig om (se bilaga A.2.1).
2.4.2.1 Windows 10 IoT Core
Det operativsystem som Sogeti önskar att enheten använder är Windows 10 (se bilaga A.2.1).
Den version som kommer användas är Windows 10 IoT Core [13], som är specifikt designad
för små enheter och möjliggör ytterligare integrationsmöjligheter med enheter som delar
samma operativsystem [14]. Förkortningen IoT står för Internet of Things [15] (på svenska
sakernas Internet), och syftar på fysiska objekts förmåga att samla in och dela med sig av
information över olika nätverk.
2.4.2.2 Time-to-Digital Converter
Sogeti har föreslagit att den ytterligare hårdvara som kan komma att krävas skulle kunna vara
en så kallad Time-to-Digital-omvandlare (Time-to-Digital Converter, TDC) (se bilaga A.1.1).
En TDC [12] representerar digitalt tiden för en skedd händelse. Sådana händelser skulle till
exempel kunna vara ankomsttiden för flera start- och stoppsignaler; TDC används vanligast
för att mäta ett tidsintervall mellan sådana signaler. Denna mätning startas när en signalpuls
korsar ett visst bestämt tröskelvärde.
Det intervall som önskas mätas är intervallet mellan ljudankomsterna hos de olika
mikrofonerna på träffytan. Startsignalen representerar ljudankomsten hos den närmaste
9
mikrofonen, och följande signaler kommer ifrån de övriga mikrofonerna. Intervallen mellan
dessa signaler är relevanta för att uppskatta var på ytan träffen har skett.
2.4.3 Databas
En databas används för att organiserat samla viss data. Den data som avses samlas är
enhetsidentiteten och antingen de uppmätta mätvärdena eller de slutgiltiga koordinaterna,
beroende på var i systemet beräkningen sker (mer om detta i avsnitt 3.6.1). I de avsnitt som
följer beskrivs det programspråk som används för att kommunicera med databasen, det
ramverk som underlättar databashanteringen, samt den plattform som möjliggör
databasplacering i molnet.
2.4.3.1 Structured Query Language
Structured Query Language (SQL) är ett programspråk designat för att hantera data som finns
i databassystem. Den datahantering som förfrågor med SQL möjliggör är infogning,
hämtning, uppdatering samt radering [16]. Figur 2.4 illustrerar den förfrågandeprocess som
sker mellan en användare och en databas. Det förfråganderesultat som returneras, precis som
de tabeller där data placeras i och hämtas ifrån, är listor av rader.
Figur 2.4: Illustration av förfrågandeprocessen mellan användare och databas
10
2.4.3.2 Entity Framework
Entity Framwork är ett ramverk utvecklat av Microsoft som sammankopplar data med
domänbaserade objekt och egenskaper. Ramverket kan översätta operationer för dataåtkomst
mot objekten och deras egenskaper till ekvivalenta databasåtgärder. Detta möjliggör att
databashanteringen kan abstraheras ut ur programkoden, så att en utvecklare ej behöver
bekymra sig om de databastabeller där den lagrade datan finns; utvecklaren agerar då istället
främst mot en konceptuell modell av den aktuella databasen [17].
Entity Framwork kan användas på tre olika sätt, vilket illustreras i Figur 2.5: för att skapa
dataåtkomstklasser för interagering med en redan existerande databas, för att skapa en databas
utifrån domänklasser, och för att skapa en databas och relevanta klasser utifrån en designad
databasmodell.
Figur 2.5: Överblick av Entity Frameworks tre användningsområden [17]
11
2.4.3.3 Microsoft Azure
Tanken är att hantera SQL-databasen genom Microsoft Azure [18] som erbjuder en samling
integrerade molntjänster. Azure möjliggör att skapa och hantera sådana databaser i molnet
över en webbportal (se Figur 2.6) eller direkt genom en utvecklingsmiljö. Andra exempel på
populära Azure-tjänster är applikationsutveckling för mobila och webbaserade lösningar, samt
molndistribuering av avbildningar för virtuella maskiner [19].
Figur 2.6: Microsoft Azure Webbportal
2.4.4 Visningsklient
Visningsklienten ämnar hämta den data som finns samlad i databasen, och uppskatta var på
ytan träffen skett utifrån denna (se bilaga A.2.2). Denna information ska presenteras
överskådligt och korrekt för användaren. Utöver träffvisualisering ska visningsklienten även
beräkna och överskådligt visualisera resultat utifrån dessa träffar.
Visningsklienten utvecklades som en så kallad Windows Presentation Foundation-applikation
[20]. Windows Presentation Foundation (WPF) är ett grafiskt subsystem framtaget av
Microsoft, som används för att rendera gränssnitt för Windows-baserade applikationer. WPF
12
har i syfte att erbjuda en konsekvent programmeringsmodell för applikationsskapande, och
separerar användargränssnittet från den logik [21] som styr hur data skapas, visas upp, lagras
och ändras. Genom att skilja en kontrolls logik från dess utseende kan dess gränsnitt ändras
radikalt utan att dess uppförande påverkas.
2.5 Utvecklingsmiljö
Sogeti har begärt att projektets utvecklingsmiljö, om möjligt, ska vara Visual Studio 2015
[22], som är en utvecklingsmiljö framtagen av Microsoft. Denna miljö erbjuder verktyg för att
designa bland annat applikationsgränssnitt, webbmiljöer samt databasdiagram, och stödjer
olika typer av programmeringsspråk, som till exempel C# [23]. Visual Studio underlättar för
programmerare på olika sätt, till exempel genom så kallad syntaxmarkering, som möjliggör
att olika delar av källkoden skrivs ut i olika färger, och kodkomplettering, som ger förslag på
möjliga variabler och metoder som kan användas. Genom att tillämpa bakgrundskompilering
kan miljön ge en programmerare omedelbar återkoppling huruvida dennes kod genererar fel
eller varningar redan när den skrivs, vilket visualiseras genom röda respektive gröna
markeringslinjer under koden i fråga.
Den utgåva av Visual Studio som kommer att användas kallas Community, en gratisupplaga
speciellt riktad mot enskilda utvecklare eller små arbetslag, med funktionalitet som liknar den
professionella utgåvan Visual Studio Professional.
2.6 Kapitelsammanfattning
Det här kapitlet har beskrivit uppdragsgivaren Sogeti, det projektuppdrag kring elektroniska
skyttesystem som denne tagit fram, samt den problemformulering som återfinns i projektets
kravspecifikation (se bilaga A). I problemformuleringen vill uppdragsgivaren undersöka om
det är möjligt att utveckla ett mindre kostsamt system; i brist på detta vill uppdragsgivaren
veta hur hög precision som kan uppnås och vilken utrustning som behövs för att optimera
systemet.
Därefter beskrevs systemets komponenter. Detta innefattade systemets mikrofonkomponenter,
av märket SparkFun Sound Detector. Mikrofonerna har i uppgift att registrera träffar, vars
ljudankomster används för att mäta deras tidsintervall. Med en så kallad
multilaterationsberäkning approximeras träffens position med hjälp av de uppmätta
13
tidsintervallerna. En Raspberry-enhet, som på inrådan av uppdragsgivaren använder en IoT-
version av operativsystemet Windows 10, avser samla in mätvärden från mikrofonerna. Dess
precision befaras av uppdragsgivaren vara undermålig, och således befaras en så kallad Time-
to-Digital-omvandlare vara nödvändig för ökad systemprecision.
Raspberry-enheten avser skicka vidare relevant data till en databas. Databasen använder sig
av SQL för att hantera data däri genom relevanta förfrågor. Kommunikation till denna databas
hanteras genom ramverket Entity Framework, som möjliggör att en utvecklare agerar mot en
konceptuell modell av databasen istället för hårdkodade SQL-förfrågor. Denna databas är
tänkt att hanteras som en molntjänst genom Microsofts Azureportal.
Därefter följde en beskrivning av systemets visningsklient, som utvecklas som en WPF-
applikation. Visningsklienten avser hantera datan i databasen och presentera den överskådligt
för en användare. Även utvecklingsmiljön Visual Studio 2015 Community beskrivs, som
används för att utveckla systemets applikationer.
14
3 Design
Detta kapitel avser beskriva systemets övergripande design. Kortfattade beskrivningar av
systemets fysiska komponenter följer; dessa beskrivs mer utförligt i rapporten författad av
Niklas Ivarsson [1]. Därefter beskrivs systemets databas, den data som den ämnar innehålla,
systemets visningsklient, samt den testapplikation som utvecklats för att simulera träffvärden i
syfte att testa visningsklienten.
3.1 Systemets övergripande design
Den övergripande designen för det elektroniska skyttesystemet ser ut som illustrerat i Figur
3.1. Flera mikrofoner monteras på en träffyta med uppgiften att registrera träffljud.
Ankomsttider för dessa träffljud ska tas emot av en Raspberry Pi 2-enhet, som även måste
veta i vilken ordning de olika mikrofonerna tog emot ljudankomsten. Denna Raspberry-enhet
ska i sin tur räkna ut en träffposition utifrån denna mätdata, och sedan skicka relevant
information till en databas i molnet. En visningsklient ska sedan hämta denna data, utifrån
vilken resultat beräknas och visualiseras i ett användargränssnitt. Även själva träffarna bör
visas upp i en träffyta i användargränssnittet, liknande den en användare skjuter mot.
Figur 3.1: Illustrerad design av det elektroniska skyttesystemet
15
3.2 Mikrofoner
De mikrofoner som används i systemet är fyra stycken SparkFun Sound Detectors. Dessa
komponenter valdes av Sogeti utifrån deras mindre kostnad (de kostar runt $11 styck [7]).
Figur 3.2 illustrerar en sådan mikrofon. De röd- och gulmarkerade portarna hanterar
komponentens strömförsörjning respektive dess grundnivå (även kallad jord). På mikrofonens
grönmarkerade port finns möjligheten att få ut en binär signal då en ljudankomst registrerats.
De binära signalerna från samtliga fyra mikrofoner avses tas emot av Raspberry-enheten
tillsammans med den identitet tillhörande den mikrofon som skickade respektive signal.
Figur 3.2: Mikrofon med markerade portar
3.3 Raspberry-enhet
En Raspberry-enhet ska med hjälp av en Universal Windows Platform-applikation (UWP)
[24] ta emot binära signaler från mikrofonkomponenterna. Dessa signaler används för att
bestämma de olika tidsintervallen för mikrofonernas ljudankomster. Genom
multilaterationsberäkning omvandlas dessa tidsintervall till approximerade x- och y-
koordinater för en träff i träffytan. Raspberry-enheten skickar slutligen relevant data till
databasen genom ett Application Programming Interface (API) [25].
16
3.4 Application Programming Interface
API:t hanterar kommunikationen mellan Raspberry-enheten och databasen. Detta krävs på
grund av att UWP inte kan ställa SQL-förfrågor, utan måste istället kommunicera genom
Hypertext Transfer Protocol (HTTP) [26]. API:t översätter därför denna HTTP-
kommunikation till SQL-förfrågor mot databasen.
3.5 Databas
Systemets databas har i uppgift att lagra viss data från Raspberry-enheten, som sedan ska
hämtas ut av visningsklienten. Några förslag på hur denna databas skulle kunna hanteras gavs
av Sogeti. Den skulle antingen kunna utnyttjas som en molntjänst genom Microsoft Azure,
eller som en lokal lösning med hjälp av SQLite. I följande avsnitt jämförs för- och nackdelar
mellan de olika lösningarna, vilket följs av ett avsnitt som beskriver kommunikationen med
databasen genom ramverket Entity Framework.
3.5.1 Molnlösning kontra SQLite
SQLite är en serverlös open source-lösning som erbjuder databashantering direkt mot vanliga
diskfiler. Dessa diskfiler innehåller databasens tabeller, som läs- och skrivoperationer kan
utföras mot direkt i en applikation utan att behöva förlita sig på en separat serverprocess [27].
Fördelen med molntjänstlösningen är att den är skalbar och att jämlöpande skrivoperationer
utförda av flera klienter är möjligt. Detta är önskvärt då funktionalitet för flera enheter önskas
(se bilaga A.2.4.3). En nackdel med denna lösning är svårigheten att skapa den i
Azureportalen, eftersom en Azure-prenumeration behövs för att komma åt portalen och
brandväggsregler behöver sättas upp för de IP-adresser som behöver åtkomst till databasen.
En annan nackdel är att en Internetuppkoppling krävs för att kunna skicka in och hämta data i
databasen. Några fördelar med den lokala SQLite-lösningen är att databasen är lätt att sätta
upp, samt att den passar IoT-enheter då den ej behöver administreras. Nackdelar med denna
lösning är storleken på disken som den lokala filen kräver (och som även kan hämmas om den
har en viss bestämd storleksgräns), de instanser som behöver kommunicera med databasen är
fastlåsta till enheten den är lagrad på, samt att jämlöpande skrivoperationer av flera användare
ej är möjliga [28].
I slutändan valdes molnlösningen för detta projekt. Att jämlöpande skrivoperationer är
möjliga ansågs vara nödvändigt om flera enheter implementeras. Att en molntjänst är en
17
kommersiell lösning som kan anses strida mot systemets lågkostnadsmål så är en sådan
lösning i slutändan skalbar; man betalar således endast för vad som behöver användas. Det
kan även vara värt att notera att uppdragsgivaren Sogeti vanligtvis använder sig av sådana
lösningar.
3.5.2 Databaskommunikation genom ramverket Entity Framework
Kommunikationen med databasen utförs genom SQL-förfrågor från Raspberry-enheten och
visningsklienten. Med hjälp av ramverket Entity Framework är det möjligt att abstrahera bort
hårdkodade sådana förfrågor direkt i applikationskoden och ersätta dessa med
objektorienterade metodanrop.
Till att börja med så skapas en så kallad Entity Data Model, som är en slags beskrivning av en
datastruktur, utifrån den existerande databasen. En kontextklass skapas, härledd utifrån en så
kallad DbContext [29], illustrerad i Figur 3.3. DbContext är bryggan mellan applikationens
entitetsklasser och databaser; den innehåller den mängd databasentiteter som en utvecklare
väljer att hantera i applikationen, den översätter Linq-to-Entities-förfrågor [30] (den metod
som används för att utföra förfrågor mot Entity Framework) till SQL-förfrågor, och möjliggör
att operationer kan utföra och spara ändringar i databasen. Även entitetsklasser skapas, utifrån
de databastabeller som avses hanteras i applikationen, med tillhörande get- och set-metoder
till deras egenskaper.
Genom att i applikationen skapa en ny instans av kontextklassen så sätts en uppkoppling till
databasen upp. Ett sätt att utföra detta är att använda using-satser där de behövs, istället för att
sätta upp en global uppkoppling till databasen och sedan behålla denna under hela
applikationens exekvering. Detta leder till att uppkopplingsobjekten får ett mindre omfång,
och vid vars ände objekten automatiskt släpps utan att en Dispose-metod behöver kallas.
I samband med att modellen skapas måste en utvecklare välja datauppkoppling till server och
databas. Inloggningsuppgifter måste därför anges, och utvecklaren får möjlighet att välja om
dessa uppgifter ska skickas med i uppkopplingssträngen som används för att koppla upp sig
mot databasen, eller i själva applikationen. Utvecklaren förvarnas att medskick av sådan
känslig information i uppkopplingssträngen är en säkerhetsrisk. I detta projekt valdes att
skicka med inloggningsuppgifterna i uppkopplingssträngen; en användare behöver således
inte genomgå en uppkopplingsprocess i applikationen.
18
Figur 3.3: DbContext illustrerad [29]
3.6 Data
Detta avsnitt avser beskriva den data som från träffytan hanteras i Raspberry-enheten, och
därefter den data som sparas i databasen.
3.6.1 Mätdata
Den mätdata som kommer från träffytan och dess mikrofoner är träffljudets ankomsttider till
de olika mikrofonerna, samt deras mikrofonidentitet. Denna data kan ge en uppskattad
träffposition, i och med att den mikrofon som befinner sig närmast träffen får en ankomsttid
noll, följt av de ankomsttider till de mikrofoner som befinner sig på ett ökande avstånd från
träffen. Mätdatan ska i något skede av processen användas för att räkna ut träffens x- och y-
koordinater på träffytan.
Denna beräkning kan antingen ske i Raspberry-enheten eller i visningsklienten. Fördelarna
med att sköta beräkningen i Raspberry-enheten är att redan beräknad data kan placeras i
databasen, vars innehåll då blir mer lätthanterlig än om både ankomsttider och
mikrofonidentiteter placeras däri. Systemet skulle då lättare kunna hantera flera träffytor med
tillhörande Raspberry-enheter som önskat (se bilaga A.2.4.3), eftersom varje enhet sköter sin
egen beräkning och underlättar därigenom för visningsklienten. En nackdel är att varje
Raspberry-enhet då utför ytterligare arbete än om de endast behöver spara inhämtad mätdata i
databasen. En fördel med att sköta beräkningen i visningsklienten är att Raspberry-enheten
kan agera effektivare, eftersom den endast behöver skicka den mätdata som tas fram direkt till
19
databasen. Nackdelarna med denna lösning är att databasen behöver hantera mer data, samt att
visningsklienten behöver utföra samma beräkning för flera enheter.
I detta projekt valdes lösningen där beräkningen sker i Raspberry-enheten; visningsklienten
behöver således endast hantera färdig data från en eller flera implementerade enheter.
3.6.2 Databasdata
Figur 3.4 illustrerar den data som, genom Raspberry-enheten, hamnar i databasen. Utifrån
mätdatan bestående av mikrofonernas ljudankomsttider samt identiteter ska data tas fram som
ska skickas vidare till systemets databas. Denna data ska bestå av träffens x- och y-
koordinater på träffytan, Raspberry-enhetens identitet samt vilket nummer träffen får i
träffserien. Databasens primärnyckel måste bestå av både träffnummer och enhetsidentiteten,
på grund av att flera enheter ska ha möjlighet att kunna registrera värden från sina skjutserier;
de olika enheterna kan komma att dela träffnummervärden, vilket medföljer att identiteten
även måste vara kopplad till primärnyckeln för att denna ska vara unik. En tabellrad bestående
av dessa värden skickas sedan in i molndatabasen.
Figur 3.4: Övergripande bild av data till databas genom en Raspberry-enhet
3.7 Visningsklient
Detta avsnitt ämnar beskriva visningsklientens användargränssnitt, bakgrundsfunktionalitet,
och hur hämntningen av databasdata sker.
3.7.1 Användargränssnitt
Visningsklientens användargränssnitt (se Figur 3.5) ska överskådligt visualisera relevant
information för en användare. I en ruta liknande den träffyta som användaren skjuter mot ska
approximerade träffar visualiseras efter skotten. Detta utförs genom att placera träffcirklar i
rutan utifrån de koordinater som visningsklienten hämtar ut ur databasen. En större List Box
20
används för att lista de beräknade träffresultaten. En mindre Text Box används för att skriva ut
det medelvärdesresultat användaren fått från sina träffar. Denna Text Box ska användaren
själv ej ha möjlighet att skriva i, så att innehållet endast ändras när medelvärdesresultatet
uppdateras utifrån ytterligare träffar.
Visningsklientens användargränssnitt är grafiskt designad i utvecklingsmiljön Visual Studio
med hjälp av den designer som subsystemet WPF erbjuder (se Figur 3.6). I denna lösning har
man möjlighet att utveckla visningsklientens användargränssnitt genom att skapa och placera
komponenter så som knappar, etiketter och boxar av olika slag i designvyn (på engelska
design view) ur en verktygslåda (toolbox). Funktionalitet och egenskaper för dessa
komponenter kan sedan påverkas i ett egenskapsfönster (properties window). Man har även
möjlighet att i WPF-lösningar utnyttja något som kallas Extensible Application Markup
Language (XAML) [31], vilket är en XML-baserad språklösning för att initialisera och
definiera objekt i användargränssnittet från en egen ruta (XAML view). En utvecklare kan
således skriva kod i XAML-vyn för att påverka en WPF-applikationens visuella utseende
utöver det som erbjuds från verktygslådekomponenter och deras egenskaper.
Figur 3.5: Illustration av visningsklientens användargränssnittsdesign
Figur 3.6: Illustrerad WPF-designer i utvecklingsmiljön [32]
21
3.7.2 Övergripande bakgrundsfunktionalitet
Visningsklientens bakgrundsfunktionalitet består i huvudsak av fyra klasser (se Figur 3.7):
En kontextklass sätter upp och hanterar kommunikationen med databasen och datan
däri. Denna klass genereras utifrån databasen genom implementation av Entity
Framework.
En träffklass innehåller get- och set-metoder till variablerna enhetsID, träffnummer,
samt x- och y-position från de respektive kolumner som databasen innehåller. Även
denna klass genereras utifrån databasen genom implementation av Entity Framework.
En datahanteringsklass använder instanser av kontextklassen för att koppla
applikationens logik med databasen och dess innehåll. Klassen innehåller metoder för
att beräkna träff- och medelvärdesresultat utifrån data i databasen, samt metoder för
att hämta ut och skicka vidare denna data.
En vyklass innehåller de metoder som skapar och visualiserar träffcirklar på
användargränssnittets träffyta, samt de metoder som skriver ut de olika resultaten i
användargränssnittets designerade rutor.
Visningsklientens bakgrundsfunktionalitet utvecklades under projektets gång från en version
som förlitade sig mer på kommunikation med databasen genom ramverket Entity Framework
för att hantera dess data, till en version som allt mindre förlitade sig på denna kommunikation
genom att spara ner all data i databasen och hantera denna mer lokalt. Båda dessa lösningar
har fördelar och nackdelar. Den tidigare lösningen funger utmärkt om visningsklienten avser
uppdateras för varje individuell träff; det finns då mindre anledning att hämta ner och lägga in
allt databasinnehåll i en lista för varje sådan träff. Med denna tidigare lösning så tar
datahämtning och beräkning lite längre tid då databasen måste kontaktas flera gånger per
träff, men denna fördröjning mellan träff och visualiserat resultat är försumbar för bearbetning
av endast en träff åt gången. Om istället flera träffar i följd ska beräknas och visualiseras
mellan uppdateringstillfällena så är däremot den senare lösningen mer effektiv, både
tidsmässigt och ur kodperspektiv. Flera metoder som krävs i den tidigare lösningen kan
refaktoriseras bort ur den senare lösningen eftersom deras funktionalitet kan utföras direkt
mot varje träff i listan.
I följande avsnitt kommer dessa antaganden att utvecklas, då de två lösningarna beskrivs mer
ingående.
22
Figur 3.7: Illustration av visningsklientens klasser i dess bakgrundsfunktionalitet
3.7.2.1 Ramverksbaserad bakgrundsfunktionalitet
Denna tidigare lösning för visningsklientens bakgrundsfunktionalitet baserade
kommunikationen med databasen och dess data utifrån flera metoder innehållande
implementation av ramverket Entity Framework. Flera aspekter av denna ramverksbaserade
bakgrundsfunktionalitet användes i den fristående testapplikationen (se avsnitt 3.8), som kan
simulera träffar för att testa visningsklienten.
En metod i datahanteringsklassen behövde anropas i samband med att applikationen
initialiserades med uppgiften att tömma databasen. All data däri behövde tas bort, som
försäkring att inga tidigare existerande värden befann sig där som kunde påverka
resultatberäkning och träffvisualisering negativt. När så applikationen startas så gör den det
med en tom databas och träffyta, och är precis som ett riktigt system redo för en ny träffserie
från en användare.
En metod för beräkning av resultat för varje träff krävdes i datahanteringsklassen, som
anropades i vyklassen när en uppdatering av användargränssnittet skedde. Detta träffresultat
behövdes för de enskilda, beräknade resultaten som skrevs ut i användargränssnittet. I denna
metod adderades även det beräknade träffresultatet in i en klassegenskapsvariabel som
representerade det totala resultatet för alla träffar i träffserien. Detta totala resultat behövdes
sedan när medelresultatet för samtliga träffar beräknades.
För varje enskild träff behövdes dess x- och y-koordinater hämtas ut ur databasen, vilket
krävde en metod vardera i datahanteringsklassen för att utföra denna uppgift och returnera
koordinaterna de hittade.
23
När ett träffresultat beräknats i datahanteringsklassen returnerades det ut till vyklassen, som
skickade resultatet som en parameter till en metod med uppgiften att skriva ut det i den List
Box som befann sig i användargränssnittet. Det totala resultatet skickades som en parameter
till en metod som räknade ut det medelresultat som träffserien genererat. Även detta resultat
returnerades till vyklassen, för att i en metod skrivas ut i den Text Box som befann sig i
användargränssnittet.
En metod i vyklassen skapade en träffellips i användargränssnittets träffyta utifrån en träffs x-
och y-koordinater. För att placera träffellipsen rätt på användargränssnittets träffyta behövde
dessa koordinater på nytt hämtas ut från databasen genom att anropa de metoder som skötte
detta. När träffellipsen fått rätt värden bestämdes dess storlek och färg, och lades sedan till i
användargränssnittets träffyta.
Allt detta behövde ske för varje individuell träff i databasen då den anlänt däri. Applikationen
måste således kunna uppfatta att en ändring skett i databasen och reagera på detta.
Implementation utav sådan funktionalitet visade sig dock vara för tidskrävande; mer om detta
i avsnitt 3.7.3.
Härnäst följer en mer ingående beskrivning av först den ramverksbaserade
bakgrundsfunktionalitetens vyklassmetoder följt av dess datahanteringsklassmetoder,
illustrerade i Figur 3.8 (a respektive b).
(a) (b)
Figur 3.8: Visningsklientens illustrerade vyklassmetoder och ramverksbaserade
datahanteringsklassmetoder
24
visualizeScoreInListBox
Denna metod i vyklassen lade in det beräknade träffresultatet överst i användargränssnittets
List Box. Därigenom befann sig alltid det senaste träffresultatet överst i den visualiserade
träffserien.
visualizeAverageScoreInTextBox
Denna metod i vyklassen skrev ut det beräknade medelresultatet för alla träffar som en sträng
i användargränssnittets Text Box.
visualizeShot
Denna metod i vyklassen skapade träffellipser utifrån de värden som fanns att hämta i
databasen. Träffens x- och y-koordinater returnerades till denna metod genom anrop till ett
par metoder i datahanteringsklassen med uppgift att hämta ut denna data ur databasen, som
därefter tilldelades träffellipsen. När sedan träffellipsens höjd, bredd och färg hade tilldelats
antagna värden så kunde träffellipsen till slut läggas till i användargränssnittets träffyta.
visualizeAverageShot
Denna metod i vyklassen skapade en träffellips utifrån de övriga träffarna. Träffens x- och y-
koordinater returnerades efter att ett par metoder i datahanteringsklassen anropats, vars
uppgifter var att beräkna medelvärdet av alla träffars x- respektive y-koordinater. Dessa
värden tilldelades sedan träffellipsen, tillsammans med antagna värden för höjd, bredd och
färg (denna färg skilde sig från övriga träffar). När detta hade bestämts så kunde träffen till
slut läggas till i användargränssnittets träffyta.
clearDB
Denna metod i datahanteringsklassen tog bort alla gamla träffar i databasen, och sparade
denna ändring i databasen. Denna metod anropades i samband med att applikationen
startades; detta var nödvändigt för att starta visningsklienten tom från gamla skräpvärden som
kunde påverka beräkning av träffantal negativt, och gjorde den redo att ta emot nya träffserier
från användare.
calculateScore
Denna metod i datahanteringsklassen räknade ut det resultat som den senaste träffen givit.
Mittkoordinater för användargränssnittets träffyta i x- och y-led, samt två variabler för
deltavärden för x och y definierades. Metoden beräknade det avstånd mellan träffytans
mittpunkt i x-led och träffens x-koordinat, samt det avstånd mellan mittpunkten i y-led och
25
träffens y-koordinat, och tilldelade deltavärdena dessa beräknade avstånd. Avståndet mellan
träffen och träffytans mittpunkt kunde beräknas med hjälp av Pythagoras sats utifrån de
beräknade deltavärdena:
√
Avståndet subtraherades sedan från maxresultatet i träffytan (som i detta projekt var tio),
vilket gav ett lägre resultat desto längre ifrån träffytans mittpunkt som träffen befann sig.
Klassegenskapsvariabeln innehållande totalresultatet för alla träffar adderades med träffens
resultat, innan träffresultatet returnerades.
calculateAverageScore
Denna metod i datahanteringsklassen hade i uppgift att beräkna det medelvärde som alla
träffar givit. Detta utfördes genom att dividera det totala resultatet för alla träffar med antalet
träffar i serien. Det totala resultatet fanns sparat i den klassegenskapsvariabel avsedd för
denna uppgift, och antalet träffar hämtades ut ur databasen utifrån den senaste träffens
träffnummervärde.
calculateAverageXPosition & calculateAverageYPosition
Dessa metoder i datahanteringsklassen hade i uppgift att beräkna medelvärdet av x- och y-
koordinater hos alla träffar i databasen. För varje träff däri hämtades dess x- respektive y-
koordinat ut med hjälp av den get-metod som befann sig i träffklassen, och koordinaterna
adderades ihop. Metoden returnerade dessa adderade värden dividerat med antalet träffar i
databasen, utifrån den klassegenskapsvariabel som höll reda på detta.
getLastShotXPosition & getLastShotYPosition
Dessa metoder i testapplikationens datahanteringsklass hade i uppgift att hämta ut den senaste
träffens x- respektive y-koordinat och returnera dem. Eftersom Last-metoden, som har i
uppgift att returnera den sista entiteten i en sekvens, inte stöds av Linq-to-Entities-förfrågor så
behövde man ordna databasen i nedåtgående ordning och sedan välja ut den första entiteten i
denna ordnade sekvens med en First-metod.
3.7.2.2 Listbaserad bakgrundsfunktionalitet
Den tidigare lösningen med omfattande ramverksfunktionalitet fungerade och hade varit
idealisk vid uppdatering för individuella träffar, men på grund av att implementationen av
26
funktionalitet för att uppdatera visningsklienten vid databasändringar var för tidskrävande (se
avsnitt 3.7.3) behövde ett alternativ tas fram.
En ny lösning togs fram, som hämtar ner alla träffar i databasen och lägger in dessa i en lista
varje gång en användarstyrd uppdatering sker. Detta medföljer att värdeshanteringen istället
för att vara fullt kopplad med databasen nu sker på lokalt hämtade värden. Träffarna kan
direkt skickas utifrån listan som argument till metoder, vilket leder till att deras värden kan
hämtas och sättas med hjälp av de definierade get- och set-metoder som finns i träffklassen.
Detta ledde till att några metoder kunde refaktoriseras bort då deras funktionalitet effektivare
kunde utnyttjas direkt på medskickade objekt och värden. De metoder som visningsklienten
består av beskrivs i följande avsnitt, där dess metoder i vyklassen illustrerade i Figur 3.8 (a)
följs av de som befinner sig i dess datahanteringsklass (se Figur 3.9).
Figur 3.9: Den listbaserade visningsklientens illustrerade datahanteringsklassmetoder
visualizeScoreInListBox, visualizeAverageInTextBox & visualizeAverageShot
Dessa metoder återfinns i visningsklientens vyklass, och de behåller den funktionalitet som
tidigare beskrivits (se avsnitt 3.5.2.1).
visualizeShot
Denna metod i vyklassen behåller sin tidigare funktionalitet (se avsnitt 3.5.2.1), med några
förändringar. En träffparameter tas emot av funktionen, och det är utifrån denna medskickade
träff som den visualiserade träffens x- och y-koordinater hämtas och tilldelas.
clearDB
Denna metod i datahanteringsklassen behåller den funktionalitet som tidigare beskrivits (se
avsnitt 3.5.2.1).
27
loadDBShotsIntoList
Denna metod i datahanteringsklassen skapar en ny instans av listan som träffarna läggs in i.
Metoden tilldelar även en träffräknare värdet noll, samt nollställer totalresultatet för
träffserien. För varje träff i databasen läggs sedan träffen in i listan, dess värden sätts med
hjälp av set-metoderna i träffklassen till de värden som återfinns i databasen, och räknaren
inkrementeras. Denna räknare kan sedan användas för att utreda hur många träffar som finns
i listan.
calculateScore
Denna metod i datahanteringsklassen behåller den funktionalitet som tidigare beskrivits (se
avsnitt 3.5.2.1), med några förändringar. Som parameter tar den här metoden emot en träff,
utifrån vilken de x- och y-koordinater som används vid beräkning hämtas ut ifrån. Denna
metod behöver då inte längre uppsöka den senaste träffen i databasen och hämta ut dess x-
och y-koordinater, vilket behövdes i den tidigare ramverksbaserade lösningen.
calculateAverageScore
Denna metod i datahanteringsklassen behåller den funktionalitet som tidigare beskrivits (se
avsnitt 3.5.2.1); metoden får dock träffantalet genom den klassegenskapsvariabel med uppgift
att hålla reda på detta antal, istället för att som i den tidigare lösningen hämta ut den senaste
träffens nummer i träffordningen.
calculateAverageXPosition & calculateAverageYPosition
Dessa metoder i datahanteringsklassen behåller den funktionalitet som tidigare beskrivits (se
avsnitt 3.5.2.1), med några förändringar. Istället för att hämta x- respektive y-koordinater från
alla träffar i databasen utförs detta mot alla träffar i listan med hjälp av de get-metoder som
befinner sig i träffklassen. Dessa koordinatvärden adderas ihop, och metoderna returnerar
dessa värden dividerat med antal träffar i listan, som går att återfinna i den
klassegenskapsvariabel med uppgift att hålla reda på detta.
3.7.3 Hämtning av data från databasen
Hämtning av databasdata vore idealisk om denna kunde ske i samband med att varje träff
anländer i databasen. För att detta ska vara möjligt så måste databasändringar registreras och
hanteras i applikationen. Sogeti föreslog att en teknik som kallas SignalR eventuellt kunde
vara relevant.
28
Tekniken SignalR sätter upp ett bakplan (på engelska backplane), som tar emot och
vidarebefordrar meddelanden från och till varje applikationsinstans. Varje sådant meddelande
skickas genom en meddelandebuss med en publish/subscribe-mekanism designad för
bakplanet; serverinstanser kopplas sedan till bakplanet genom denna buss. När meddelanden
sedan avses skickas till servern hamnar det istället först i bakplanet, som har möjlighet att
skicka vidare meddelandet till alla eventuella serverinstanser. När en server således tar emot
ett meddelande från bakplanet placeras det i serverns lokala cache-minne, varifrån
meddelanden sedan levereras till klienter [33].
Ett relevant användningsområde med SignalR-implementation att jämföra önskad
funktionalitet med är chattapplikationer; en sådan applikation kan utnyttja publish/subscribe-
kommunikation mellan två eller flera klientapplikationer genom en serverinstans. Ett
meddelande från en klient når och lagras således i databasen, som har möjlighet att publicera
att en ändring i dess innehåll har skett. Övriga klienter som prenumererar på relevanta
händelser i databasen har då möjlighet att ta emot meddelanden från servern och uppdatera
sina användargränssnitt därefter. En snarlik lösning för applikationen i Raspberry-enheten,
databasen och visningsklienten hade varit önskvärd, men på grund av projekttidsbrist hann en
sådan implementation inte tas fram. Således fick visningsklienten fungera utifrån en alternativ
lösning.
I nuläget uppdaterar visningsklienten istället sitt användargränssnitt med hämtad databasdata
utifrån manuell uppdatering. Genom att en användare trycker på en knapp i
användargränssnittet så hämtas all databasdata till visningsklienten och läggs in i en lista. De
funktioner som sedan behöver denna data för beräkning och visualisering kommunicerar
följaktligen med denna lokala lista.
Detta möjliggör beräkning och visualisering av flera träffar i följd. Med den
ramverksbaserade lösningen var sådan följduppdatering möjlig, men den krävde upprepad
kommunikation med molndatabasen för att hämta x- och y-koordinater för varje träff, samt
för att returnera den sista träffens nummer i träffordningen; detta var nödvändigt för att veta
hur många träffar som behövde beräknas och visualiseras. Eftersom åtkomst till databasen är
skild från vyklassen måste således flera metoder i datahanteringsklassen med möjlighet att
hämta databasdata anropas därifrån så att relevanta värden kan returneras.
29
3.8 Träffsimulering
För att kunna visualisera träffar och beräknade värden i visningsklienten behöver data som
ska hämtas ur databasen faktiskt finnas där. En fristående testapplikation togs därför fram för
att simulera träffar så att funktionaliteten kring dem kan testas i visningsklienten.
Testapplikationens syfte är därmed att skapa de databasentiteter som visningsklienten sedan
kan hämta genom manuell användaruppdatering.
Testapplikationen liknar visningsklienten, både i användargränssnitt och
bakgrundsfunktionalitet (se Figur 3.10). Den skiljer sig dock i att en användare med hjälp av
muspekaren kan skapa träffar i användargränssnittets träffyta; för att tydliggöra detta skiftar
muspekarikonen till ett kors när denna befinner sig inom träffytan. För varje träff som skapas
skickas dess värden in i databasen, där de sedan hämtas tillbaka för att beräknas och
visualiseras. Denna händelsekedja visar att inlägg och uthämtning av data i och ur databasen
är möjlig och fungerar korrekt.
Testapplikationen motsvarar den tidigare ramverksbaserade visningsklientlösningen.
Eftersom uppdateringen i testapplikationen sker för varje träff så ansågs det inte finnas någon
anledning att hämta ner alla databasvärden i en lista varje gång uppdateringen sker;
testapplikationen arbetar således direkt mot databasen. Testapplikationen blir då lite
långsammare, särskilt om en serie träffar simuleras i snabb följd, men eftersom applikationen
är fristående från visningsklienten och endast avsedd för träffsimulering i brist på riktiga
värden ansågs detta försumbart.
Den ytterligare funktionalitet som skiljer testapplikationen åt från visningsklienten är att varje
uppdatering sker när en användare trycker ner vänster musknapp då muspekaren befinner sig
inom användargränssnittets träffyta. När en träff skapas däri sätts träffens x- och y-
koordinater till de koordinater som muspekaren har vid träfftillfället; varje träff som simuleras
skickas in i databasen med dessa värden samt enhetsidentitet och ett träffnummer enligt en
räknare av antalet simulerade träffar. Eftersom testapplikationen precis som den
ramverksbaserade visningsklienten räknar ut träffresultat för varje träff när den simuleras så
behöver den möjlighet att hämta ut x- och y-koordinater för den senaste träffen, och därför
återfinns två sådana metoder.
Härnäst följer två avsnitt rörande testapplikationens funktionalitet, först i dess vyklass och
därefter i dess datahanteringsklass.
30
Figur 3.10: Illustration av visningsklient, testapplikation och databas
3.8.1 Testapplikationens vyklass
Testapplikationens vyklass har, precis som visningsklientens sådan, i uppgift att visualisera
träffar och beräknade resultat. Skillnaden här är att användaren själv väljer var i
användargränssnittets träffyta som träffarna placeras, genom att med muspekaren klicka inom
träffytan. Dessa användarplacerade träffar ämnas sedan skickas in i databasen, med de
koordinater och träffnummer som träffsimuleringen genererar.
Härnäst beskrivs testapplikationens vyklassmetoder.
3.8.1.1 visualizeScoreInListBox & visualizeAverageInTextBox
Dessa metoder i testapplikationens vyklass behåller den funktionalitet som tidigare beskrivits
(se avsnitt 3.5.2.1).
3.8.1.2 createAndVisualizeShot
Denna metod i testapplikationens vyklass skapar och visualiserar de simulerade träffarna i sitt
gränssnitt. Träffarnas x- och y-koordinater sätts till de värden som muspekarens position har
31
vid träfftillfället. En räknare i datahanteringsklassen inkrementeras varje gång en träff läggs
till i användargränssnittet, för att hålla reda på det antal träffar som simuleras. Efter detta så
skickas träffens x- och y-koordinater som argument i ett anrop till en metod i
datahanteringsklassen som lägger till träffen i databasen.
3.8.2 Testapplikationens datahanteringsklass
Testapplikationens datahanteringsklass, liknande den datahanteringsklass som finns i
visningsklienten, har i uppgift att tömma databasen, lägga till träffar i den, hämta ut
nödvändiga värden utifrån den data däri och beräkna träffresultat.
Härnäst beskrivs datahanteringsklassens metoder.
3.8.2.1 clearDB
Denna metod i testapplikationens datahanteringsklass behåller den funktionalitet som tidigare
beskrivits (se avsnitt 3.5.2.1).
3.8.2.2 insertShotIntoDB
Denna metod i testapplikationens datahanteringsklass har i uppgift att lägga till en träffentitet
i databasen. Den tar emot träffens x- och y-koordinater som parametrar, och lägger till en träff
med dessa värden samt en antagen enhetsidentitet med värdet ett och träffnummer enligt den
räknare som inkrementeras när träffar simuleras i användargränssnittets träffyta. När en träff
således har lagts in i databasen så sparas denna ändring.
3.8.2.3 getLastShotXPosition & getLastShotYPosition
Dessa metoder i testapplikationens datahanteringsklass behåller den funktionalitet som
tidigare beskrivits (se respektive metoder i avsnitt 3.7.2.1).
3.8.2.4 calculateScore
Denna metod i testapplikationens datahanteringsklass behåller den funktionalitet som tidigare
beskrivits (se avsnitt 3.5.2.1), med en förändring. Metoden hämtar en träffs x- och y-koordinat
genom att anropa metoderna getLastShotXPos och getLastShotYPos, och spara deras
returvärden i ett par variabler.
32
3.8.2.5 calculateAverageScore
Denna metod i testapplikationens datahanteringsklass behåller den funktionalitet som tidigare
beskrivits (se avsnitt 3.5.2.1); de värden som divideras är totalresultatet för alla träffar samt
antal träffar i databasen. Båda dessa värden återfinns i klassegenskapsvariabler i
datahanteringsklassen.
3.9 Kapitelsammanfattning
I detta kapitel har systemets övergripande design beskrivits och illustrerats, där dess
systemkomponenter introducerats och deras respektive uppgifter angivits.
Därefter följde en kort beskrivning av systemets fysiska komponenter, samt det API som
hanterar kommunikationen mellan Raspberry-enheten och systemets databas.
Ett avsnitt rörande denna databas följde, som beskrev hur en jämförelse mellan en
molnlösning kontra en lokal sådan ledde till att databasen i detta projekt placerades i molnet,
samt hur kommunikationen till och från den sker med hjälp av ramverket Entity Framework.
Därefter beskrevs systemets olika data: först mätdatan från mikrofonkomponenterna och var
den beräkning som utförs utifrån denna data utförs, samt den data som sparas i databasen.
Ett avsnitt som beskrev systemets visningsklient följde, där dess användargränssnittsdesign
illustrerades och den designer som används för att grafiskt designa användargränssnittet
beskrevs. En beskrivning av visningsklientens övergripande bakgrundsfunktionalitet följde,
vilket innefattade dess klasser och metoder. Avsnittet beskrev även hur en ramverksbaserad
bakgrundsfunktionalitet som var en mer optimal lösning för automatisk datahämtning och
användargränssnittsuppdatering ersattes av en listbaserad bakgrundsfunktionalitetslösning då
visningsklienten fick sköta hämtning och uppdatering utifrån manuell användarinput när
implementering av tekniken SignalR ansågs alltför tidskrävande. Avsnittet följdes av ett
avsnitt beskrivande den utvecklade testapplikation, med funktionalitet motsvarande den
ramverksbaserade sådan för visningsklienten, som avser simulera träffar som sparas i
systemets databas. Således kan visningsklienten testas genom att hämta, beräkna och
visualisera träffar och resultat utifrån denna sparade data.
33
4 Implementation
Det här kapitlet ämnar beskriva genom bilder och text hur en SQL-server och databas sätts
upp i Azureportalen, hur visningsklientens alla beståndsdelar skapas och implementeras, samt
kodutseende och funktionalitet för visningsklientens och testapplikationens olika klasser.
4.1 Azure SQL-server & databas
För att få tillgång till Azureportalen och därefter sätta upp en SQL-server och databas krävs
en Azure-prenumeration kopplad till ett Microsoftkonto. I detta projekt var det möjligt att
skapa en sådan med hjälp av Microsoft DreamSpark Premium [34], som erbjuds studenter
inom STEM-institutioner (Science, Technology, Engineering och Math) vid Karlstads
Universitet.
I samband med att man skapar en databas kan man välja att skapa en ny Azure SQL-server
eller använda en redan befintlig sådan. Om man väljer att skapa en ny server så får skaparen
möjlighet att välja de inloggningsuppgifter som senare kommer användas för att komma åt
servern och databasen i utvecklingsmiljön.
Det sista som behöver utföras i Azureportalen när väl SQL-servern är skapad är att lägga till
den aktuella IP-adressen i serverns brandväggsregler. Om inte detta utförs kommer
applikationen att nekas åtkomst till servern och dess databaser. Figur 4.1 illustrerar var man
kan hitta denna inställning; i den skapade databasens flik klickar man först på servernamnet,
och väljer i dess flik sedan antingen Visa brandväggsinställningar, eller Alla inställningar
och sedan Brandvägg. Man har där möjlighet att lägga till nya klient-IP-adresser, vilket måste
utföras för varje ny adress som behöver åtkomst till databas och server.
34
Figur 4.1: Brandväggsregler för SQL-servern i Azureportalen
35
4.2 Utvecklingsmiljöns databasdesigner
För att påverka databasen inuti utvecklingsmiljön måste först SQL-servern kopplas samman
med denna. Servern behöver läggas till i utvecklingsmiljöns utforskare SQL Server Object
Explorer; för att göra detta behövs dess servernamn och inloggningsuppgifter.
När servern har lagts till och databasen kan hittas i utforskaren kan en utvecklare skapa en ny
databastabell i denna genom att högerklicka på undermappen Tables och välja alternativet
Lägg Till Ny Tabell. Detta laddar då en databasdesigner, där utvecklaren lätt kan skapa namn
och typ för den data som tabellen ska innehålla. Figur 4.2 (a) illustrerar databastabellen shots
för de träffar som läggs in i och hämtas ut ur databasen. Id är den enhetsidentitet som en
Raspberry-enhet blivit tilldelad. ShotNum är en träffs ordning i träffserien. Dessa två värden
sätts som primärnycklar genom att klicka i rutan till vänster om namnen, och tilldelas
datatypen integer i rutan till höger om namnen. xPos och yPos är de x- och y-koordinater en
träff får på träffytan, och de tilldelas datatypen float. För att spara tabellen i databasen måste
utvecklaren trycka på Update-knappen som befinner sig i övre vänstra hörnet av designern,
ovanför namnkolumnen. Figur 4.2 (b) illustrerar resultatet i utforskaren, där databastabellen
shots med dess tillhörande kolumner ligger tillagd i databasen ElectronicMarking.
36
(a) (b)
Figur 4.2: Utvecklingsmiljöns databasdesigner för databastabellen shots, samt
databastabellen shots i utvecklingsmiljöns utforskare
37
4.3 Visningsklient
Visningsklienten skapas i utvecklingsmiljön som ett WPF-projekt. Visningsklienten består av
ett användargränssnitt och fyra klasser i bakgrundsfunktionaliteten. Detta avsnitt avser
beskriva dessa komponenter och hur de implementeras.
4.3.1 Ramverksimplementation
Två av visningsklientens klasser, träffklassen Shot och kontextklassen Context, skapas utifrån
databasen då ramverket Entity Framework implementeras. För att implementera ramverket i
projektet så behövs en ny programdel ADO.NET Data Entity Model (se avsnitt 3.3.2) läggas
till. Modellen sätts upp som en Code First-lösning, vilket ser till att klasser i modellen skapas
utifrån den redan existerande databasen. En utvecklare får då möjlighet att välja
databasuppkoppling, modellinställningar och vilka databasobjekt som inkluderas i modellen.
I samband med att uppkopplingen till databasen sätts upp behöver utvecklaren förse de
inloggningsuppgifter som angetts när servern skapades i Azureportalen. Dessa
inloggningsuppgifter krävs för att koppla visningsklienten till databasen, och utvecklaren kan
sedan välja att skicka med dessa i den uppkopplingsträng som skapas i slutet av
ramverksimplementationen, eller om de ska förses på annat sätt i själva applikationen. I detta
projekt gjordes antagandet att skicka med uppgifterna i uppkopplingssträngen, då fokus under
utvecklingsprocessen låg på att utveckla en fungerande visningsklient, inte på dess säkerhet.
Uppkopplingsinställningarna sparas som en given sträng, i detta fall den antagna strängen
Context, i applikationens konfigureringsfil App.config. Denna fil innehåller ramverkets
uppkopplingskonfiguration mellan applikationen och databasen. Denna konfiguration
innefattar den skapade uppkopplingsträngen. Uppkopplingsträngens relevanta innehåll är
följande:
Name: den givna strängen som uppkopplingsinställningarna sparades under
Data Source: den server som agerar datakälla
Initial Catalog: den databas som uppkopplingen upprättats mot
User id & password: de inloggningsuppgifter som är kopplade till servern, och som i
detta fall valts att medskickas i uppkopplingssträngen
Provider Name: det namn som en så kallad SqlDataSource-kontroll använder för
uppkoppling till en underliggande datakälla
38
Notera att känslig information i koden som följer har bytts ut mot stjärnsymboler; detta på
grund av att SQL-servern och dess inloggningsuppgifter tillhandahållits av Sogeti.
<connectionStrings> <add name="Context" connectionString="data source=**********.database.windows.net; initial catalog=ElectronicMarking; user id=electronicMarking; password=******************" providerName="System.Data.SqlClient" /> </connectionStrings>
Ramverksimplementationen resulterar i två genererade klasser: en kontextklass som hanterar
uppkopplingen mellan applikationen och databasen, och en träffklass som representerar den
databastabell som utvecklaren har möjlighet att inkludera i den skapade modellen.
Kontextklassen innehåller en konstruktor, där den givna strängen Context används för att
skapa en ny kontextinstans för uppkopplingen till databasen, samt get- och set-metoder till de
entiteter som kan förfrågas i databasen; i detta fall är dessa entiteter träffarna shots, som är en
databassamling DbSet av typen Shot.
public partial class Context : DbContext { public Context() : base("name=Context") { } public virtual DbSet<Shot> shots { get; set; } }
Träffklassen innehåller get- och set-metoder till de egenskaper som databasentiteterna innehar
(se avsnitt 4.2), samt information rörande databasens primärnycklar. Informationen rör de
kolumner som primärnycklarna mappas till, samt eventuella sätt som egenskapsvärden
genereras. Primärnycklarna Id och ShotNum är båda av typ int, och träffarnas x- samt y-
koordinatsvärden, xPos respektive yPos, är av typen double.
public partial class Shot { [Key] [Column(Order = 0)] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int Id { get; set; } [Key] [Column(Order = 1)] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int ShotNum { get; set; } public double xPos { get; set; }
39
public double yPos { get; set; } }
4.3.2 Användargränssnitt
Visningsklientens användargränssnitt utvecklas i utvecklingsmiljöns vydesigner. Tack vare att
projektet utvecklas i WPF så finns det ytterligare utvecklingsmöjligheter genom dess XAML-
designer (se avsnitt 3.7.1). Visningsklienten ges däri namnet Visningsklient, och sätts till en
antagen fönsterstorlek. Resten av dess funktionalitet sätts i en kanvaskontroll, som innehåller
den samling objekt som användargränssnittet kommer bestå utav.
<Window x:Class="Elektroniskt_Skyttesystem_Visningsklient.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Elektroniskt_Skyttesystem_Visningsklient" mc:Ignorable="d" Title="Visningsklient" Height="350" Width="480"> <Canvas Name="TargetCanvas">
Det som antogs behöver visas upp för en användare är en träffyta, där dennes träffar
möjligtvis kan visualiseras utifrån var användaren själv träffat på den fysiska träffytan.
Träffytan i användargränssnittet är ursprungligen en Scalable Vector Graphics-fil (svg)
hämtad på inrådan av Sogeti från Internet [35], för att möjliggöra en mer detaljerad
träffpresentation i visningsklientens användargränssnitt. Filformatet svg stöds inte av XAML-
designern, så den behöver först konverteras till ett tillåtet sådant; detta går att genomföra
genom att utnyttja applikationen Inkscape [36] för att konvertera filen till en Portable
Network Graphics-bild (png). Träffytan kan därefter tilldelas en antagen storlek inuti
användargränssnittet.
<Image Name="Target" Source="C:\Users\abergman\Documents\Visual Studio 2015\Projects\Elektroniskt Skyttesystem Visningsklient\10_m_Air_Rifle_target.png" Height="321" Width="345" />
Ytterligare användargränssnittkomponenter väljs från designerns verktygslåda. Användarens
beräknade träffresultat väljs att presenteras i en List Box. Dock så får en användare då
möjlighet att markera artiklar som presenteras i denna ruta genom att med muspekaren klicka
på dem; således valdes att påverka rutan så att en användare inte längre kan utföra detta.
40
Detta utförs genom att i XAML-designern sätta en ofokuserbar egenskap för alla artiklar som
rutan innehåller; när således en användare försöker att markera ett värde i listan så händer
ingenting. En List Box har en egenskap ItemContainerStyle, som kan sätta stilen för
renderade artiklar däri; det är således dessa artiklar ListBoxItems man väljer som
stilmålgrupp. Således väljs artikelegenskapen Focusable, som ges ett värde False för att göra
artiklarna ofokuserbara.
<ListBox x:Name="listBox" Height="150" Width="100" Canvas.Left="350" Canvas.Top="60"> <ListBox.ItemContainerStyle> <Style TargetType="ListBoxItem"> <Setter Property="Focusable" Value="False"/> </Style> </ListBox.ItemContainerStyle> </ListBox>
Det beräknade medelresultatet väljs att presenteras i en Text Box. Dess innehåll ska ej kunna
påverkas av en användare, utan ska endast visa det avsedda, beräknade medelresultatet. Detta
utförs genom att ange värdet True i knappens egenskap IsReadOnly. Rutans antagna storlek
och position kan sedan anges.
<TextBox x:Name="textBox" IsReadOnly="True" Height="23" Width="100" Canvas.Left="350"
Canvas.Top="236"/>
Två etiketter för Träffresultat och Medelresultat befinner sig över respektive ruta i syfte att
förtydliga rutinnehåll för en användare. Efter att deras innehåll har sätts så tilldelas de antagna
positioner.
<Label x:Name="label" Content="Träffresultat:" Canvas.Left="363" Canvas.Top="30"/> <Label x:Name="label2" Content="Medelresultat:" Canvas.Left="363" Canvas.Top="210"/>
Till sist placeras den knapp som en användare använder för att uppdatera användargränssnittet
med alla träffar och beräknade resultat. För att förtydliga för en användare vad knappens
funktion är så sätts dess innehåll till Uppdatera, och dess händelsehanterare vid knapptryck
kopplas till en metod button_Click. Knappen tilldelas sedan antagna storlekar och positioner i
användargränssnittet. I och med att knappen är fönstrets sista komponent stängs därefter först
kanvaskontrollen och sedan fönstret i XAML-koden.
41
<Button x:Name="button" Content="Uppdatera" HorizontalAlignment="Left"
VerticalAlignment="Top" Width="75" Grid.Column="1" Grid.Row="1" Click="button_Click"
Canvas.Left="375" Canvas.Top="264"/>
</Canvas> </Window>
Figur 4.3 illustrerar det slutgiltiga användargränssnittet i utvecklingsmiljöns WPF-designer.
Dess träffyta befinner sig på fönstrets vänstra sida, och till höger återfinns knappen samt de
rutor och etiketter som tidigare beskrivits.
Figur 4.3: Visningsklientens användargränssnitt i utvecklingsmiljöns WPF-designer
4.3.3 Vyklass
Visningsklientens vyklass har i uppgift att visualisera träffar och beräknade resultat i
användargränssnittet, samt hantera händelsen då en användare trycker på knappen däri.
Följande avsnitt beskriver dess klassegenskaper, konstruktor och metoder.
4.3.3.1 Klassegenskaper
Först instansieras ett objekt DH, som är en instans av datahanteringsklassen DataHandler.
Man får därigenom möjlighet att anropa metoder i denna klass från vyklassen. Därefter
definieras en referens averageEllipse, av typen Ellipse. Den behöver vara en egenskap av skäl
som tas upp i avsnitt 4.3.3.6.
DataHandler DH = new DataHandler();
Ellipse averageEllipse;
42
4.3.3.2 MainWindow-konstruktorn
I huvudfönstrets konstruktor finns ett anrop till metoderna InitializeComponent, som laddar
användargränssnittet, och clearDB i datahanteringsklassen. Detta andra metodanrop görs i
syfte att starta applikationen med en tom databas, redo att ta emot nya användarträffar.
public MainWindow() { InitializeComponent(); DH.clearDB(); }
4.3.3.3 visualizeScoreInListBox
Denna metod tar emot en parameter result av typen double, som representerar ett träffresultat.
Detta resultat läggs sedan in som en artikel i användargränssnittets List Box, på dess första
position. Detta antogs vara ett användarvänligt val, då en användares senaste träff då alltid
befinner sig högst upp i listan, följt av dess föregångare.
private void visualizeScoreInListBox(double result) { listBox.Items.Insert(0, result); }
4.3.3.4 visualizeAverageScoreInTextBox
Även denna metod tar emot en parameter av typen double, här kallad averageResult. Den
representerar det beräknade medelresultatet för alla träffresultat. Textrutans innehåll sätts till
detta resultat, efter att det konverteras från ett numeriskt värde till en textsträng.
private void visualizeAverageScoreInTextBox(double averageResult) { textBox.Text = averageResult.ToString(); }
4.3.3.5 visualizeShot
Denna metod tar emot en träffparameter shot av typen Shot. Därefter skapas ett objekt
shotEllipse, som är en ny instans av ellipsklassen. Denna träffellips tilldelas sedan ett par
antagna höjd- och breddstorlekar.
43
private void visualizeShot(Shot shot) { Ellipse shotEllipse = new Ellipse(); shotEllipse.Width = 5; shotEllipse.Height = 5;
Då träffellipsens koordinater i x- och y-led på träffytan ska sättas behöver man ta hänsyn till
hur ellipser placeras i vyn. När man skapar och placerar ellipsformer i en vy så görs detta från
kvadrater innehållande dessa ellipsformer, som illustreras i Figur 4.4. Det är från denna
kvadrats övre vänstra hörn som ellipsformen sedan styrs av de värden man tilldelar dess x-
och y-koordinater. De x- och y-koordinater som träffarna har i databasen och därefter
representerar deras approximerade mittpunkt. För att den skapade träffellipsen ska få de
önskade x- och y-koordinaterna (x’ och y’ i Figur 4.4) så måste de koordinater man placerar
ellipsen med reduceras med hälften av dess angivna bredd respektive höjd för att nå dess
mittpunkt. Dessa reducerade x- och y-koordinater tilldelas träffellipsen genom att anropa dess
SetValue-metod i vänsterled och toppled.
shotEllipse.SetValue(Canvas.LeftProperty, shot.xPos - (shotEllipse.Width / 2)); shotEllipse.SetValue(Canvas.TopProperty, shot.yPos - (shotEllipse.Height / 2));
För att sedan färglägga träffellipsen behövs ett objekt solidColorBrush skapas, som är en
instans av klassen SolidColorBrush. Dess färgegenskap Color tilldelas ett värde med hjälp av
metoden FromArgb. Denna metod skapar en färgstruktur utifrån alpha (transparens), samt
färgerna röd, grön och blå. Transparensargumentet sätts till maxvärdet tvåhundrafemtiofem
(255), vilket även tilldelas det röda värdet; resterande färgargument sätts till noll, och
träffellipsen fylls därefter. Det som sedan återstår är att lägga till träffellipsen i
kanvaskontrollen som ett barnelement till denna.
SolidColorBrush solidColorBrush = new SolidColorBrush(); solidColorBrush.Color = Color.FromArgb(255, 255, 0, 0); shotEllipse.Fill = solidColorBrush; TargetCanvas.Children.Add(shotEllipse); }
44
Figur 4.4: Kvadratinramad ellipsform, med faktiska och önskade koordinater
4.3.3.6 visualizeAverageShot
Denna metod har i uppgift att visualisera den medelträff som en användares träffserie
resulterat i. Notera att denna medelträff utgår ifrån alla träffars koordinater, inte resultat,
vilket frikopplar denna träffellips från det presenterade medelresultatet i användargränssnittets
Text Box.
Metodens kodstruktur liknar visualiseringsmetoden för övriga träffar, med några
modifikationer. Först så undersöker en if-sats om kanvaskontrollen redan innehåller en
medelträff averageEllipse, och om så är fallet så tas denna bort. Detta utförs så att inte fler än
en medelträff återfinns i träffytan i användargränssnittet, och som är skälet till att referensen
till medelträffen behövde vara en klassegenskap. Därefter sätts referensen till
medelträffellipsen till en ny instans av ellipsklassen, och tilldelas antagna bredd- och
höjdvärden.
private void visualizeAverageShot() { if (TargetCanvas.Children.Contains(averageEllipse)) TargetCanvas.Children.Remove(averageEllipse); averageEllipse = new Ellipse(); averageEllipse.Width = 5; averageEllipse.Height = 5;
Där medelträffellipsens x- och y-koordinater ska sättas behövs ett par anrop till metoderna
calculateAverageXPosition och calculateAverageYPosition i datahanteringsklassen. Dessa
metoder har i uppgift att räkna ut medelvärdet för alla träffars x- respektive y-koordinater, och
sedan returnera dessa. Dessa returnerade koordinater används således i de tidigare nämnda
SetValue-metoderna i vänsterled och toppled i kanvaskontrollen, subtraherade med ellipsen
halva bredd- och höjdvärden.
45
averageEllipse.SetValue(Canvas.LeftProperty, DH.calculateAverageXPosition() - (averageEllipse.Width / 2)); averageEllipse.SetValue(Canvas.TopProperty, DH.calculateAverageYPosition() -
(averageEllipse.Height / 2));
Ett antagande gjordes att färgen som tilldelas medelträffellipsen bör skilja sig från den som
tilldelas övriga visualiserade träffar för att en användare lättare ska kunna överblicka
resultatet i användargränssnittet. Genom att ge även argumentvärdet för grön färg maxvärdet
tvåhundrafemtiofem (255), så fylls sedan medelträffellipsen med en gul färg.
Medelträffellipsen läggs på samma sätt som tidigare med i kanvaskontrollen som ett
barnelement till denna.
SolidColorBrush solidColorBrush = new SolidColorBrush(); solidColorBrush.Color = Color.FromArgb(255, 255, 255, 0); averageEllipse.Fill = solidColorBrush; TargetCanvas.Children.Add(averageEllipse); }
4.3.3.7 button_Click
Denna metod är en händelsehanteringsmetod som anropas om en användare trycker på
knappen i användargränssnittet. Den har i uppgift att sköta uppdateringen av
användargränssnittet, genom att anropa alla relevanta metoder i visningsklientens olika
klasser.
Först anropas en metod loadDBShotsIntoList i datahanteringsklassen, som har i uppgift att
läsa in alla träffar i databasen och lägga in det i visningsklientens lokala lista. Därefter töms
innehållet i användargränssnittets List Box, så att inte tidigare träffserier återfinns däri när ny
data således ska presenteras. En if-sats undersöker sedan huruvida antalet inlästa träffar i
listan är noll utifrån en egenskapsvariabel i datahanteringsklassen som avser rymma
träffantalet i listan. Om så är fallet så returneras man ut ur metoden. Syftet med detta är att
förhindra att en användare försöker uppdatera utifrån en tom lista; då beräkningen av
medelresultat utförs så sker det då med en nolldivision och resultatet presenteras som
symboler i användargränssnittet. Med denna lösning så går processen inte så långt, utan man
returneras ut ur metoden tidigt och användargränssnittet behåller sitt tomma utseende.
46
private void button_Click(object sender, RoutedEventArgs e) { DH.loadDBShotsIntoList(); listBox.Items.Clear(); if (DH.shotsInList == 0) return;
Om det istället existerar inlästa träffar i listan så ska metoden för varje sådan träff i listan
visualisera dess beräknade träffresultat och själva träffen i användargränssnittet. En lokal
variabel result av typen double tilldelas ett returnerat värde från metoden calculateScore i
datahanteringsklassen. Denna metod har i uppgift att räkna ut ett träffresultat utifrån träffens
koordinater utifrån avståndet från träffytans mittpunkt. Denna mittpunkt beräknas utifrån
träffytebildens antagna bredd- och höjdvärden, så för att undkomma hårdkodade sådana
värden i beräkningsmetoden måste dessa värden skickas med som argument i metodanropet;
detta eftersom datahanteringsklassen, till skillnad från vyklassen, är skild från vyn och dess
kontroller, och kan således inte komma åt dessa värden på egen hand. Även träffen som läses
ut för varje varv i listan skickas med som ett argument i metodanropet. Träffresultatet och
själva träffen visualiseras sedan genom att resultatet och träffen skickas som argument i
metodanropen av metoderna visualizeScoreInListBox respektive visualizeShot.
foreach (Shot shot in DH.listShots) { double result = DH.calculateScore(shot, Target.Width, Target.Height); visualizeScoreInListBox(result); visualizeShot(shot); }
När alla träffar i listan således hanterats behöver metoden även visualisera det beräknade
medelresultatet för alla träffresultat och själva medelträffen i användargränssnittet.
Funktionaliteten i denna del liknar den för varje individuell träff: En lokal variabel
averageResult av typen double tilldelas ett returnerat värde efter ett metodanrop till metoden
calculateAverageScore i datahanteringsklassen, som skickas som med som ett argument till
metoden visualizeAverageScoreInTextBox, innan metoden visualizeAverageShot anropas.
double averageResult = DH.calculateAverageScore(); visualizeAverageScoreInTextBox(averageResult); visualizeAverageShot(); }
47
4.3.4 Datahanteringsklass
Visningsklientens datahanteringsklass avser hantera databasrensning, inläsning av träffar i en
lista, samt beräkning av träffresultat och alla medelresultat. Följande avsnitt beskriver
datahanteringsklassens klassegenskaper och metoder.
4.3.4.1 Klassegenskaper
En egenskapsreferens listShots, som är en lista av träffar, och två klassegenskapsvariabler
shotsInList och totalResult definieras, av typerna int respektive double. listShots ämnas
innehålla alla inläsa träffar, shotsInList det antal träffar som finns inlästa i listan och
totalResult det totala resultatet som alla träffar genererat. listShots och shotsInList är publika,
så att deras innehåll går att komma åt i vyklassen. Variabeln totalResult är privat, då dess
innehåll endast behövs i datahanteringsklassen.
public List<Shot> listShots; public int shotsInList; private double totalResult;
4.3.4.2 clearDB
Denna metod har för avsikt att tömma databasen på gamla värden, vilket gör den redo för en
ny träffserie. Metoden är publik, då den anropas i vyklassen i samband med att
användargränssnittet laddas. Metoden sätter upp en uppkoppling till databasen genom att
använda en using-sats med kontexten context. Räckvidden för denna sats är hela metoden, och
när metoden är till ända så görs den av med. För varje träffentitet shot som befinner sig i
databasen utförs en borttagning med hjälp av en Remove-metod. När således alla träffar
hanterats så sparas denna ändring i kontexten.
public void clearDB() { using (Context context = new Context()) { foreach (Shot shot in context.shots) { context.shots.Remove(shot); } context.SaveChanges(); } }
48
4.3.4.3 loadShotsIntoList
Denna metod har i uppgift att för varje träff i databasen läsa in denna i en lista. Till att börja
med instansieras egenskapsreferensen listShots till en ny träfflista, och
klassegenskapsvariablerna shotsInList och totalResult nollställs.
public void loadDBShotsIntoList() { listShots = new List<Shot>(); shotsInList = 0; totalResult = 0;
Som I föregående metod sätts en uppkoppling mot databasen upp med hjälp av en using-sats
med kontexten context. För varje träff däri så läggs dess enhetsidentitet, träffnummer, samt x-
och y-koordinater in i en ny träff i listan. Räknaren shotsInList inkrementeras därefter för
varje tillagd listträff.
using (Context context = new Context()) { foreach (Shot shot in context.shots) { listShots.Add(new Shot { Id = shot.Id, ShotNum = shot.ShotNum, xPos = shot.xPos, yPos = shot.yPos }); shotsInList++; } } }
4.3.4.4 calculateScore
Denna metod har i uppgift att beräkna ett träffresultat utifrån träffens avstånd från träffytans
mittpunkt.
Metoden tar emot tre parametrar: en träff shot av typen Shot, samt träffytans breddvärde
targetWidth och dess höjdvärde targetHeight, båda av typen double. Därefter definieras och
instansieras flera lokala variabler av typen double. Variablerna midX och midY ämnas
innehålla träffytans mittpunkt i x- respektive y-led, så de tilldelas parametervärdena för höjd
och bredd dividerat med två. Variablerna deltaX och deltaY kommer att representera de
avstånd som mäts upp mellan träffen och träffytans mittpunkt. Variablerna xPosition och
yPosition tilldelas de x- respektive y-koordinater som den medskickade parameterträffen har.
Tre variabler targetMaxResult, targetMinResult och targetFactor av typ int definieras till
värde tio, ett respektive sexton. Dessa antagna värden fås utifrån den träffyta som används i
49
visningsklientens gränssnitt (se avsnitt 4.3.2), och används senare i metoden där träffresultatet
beräknas.
public double calculateScore(Shot shot, double targetWidth, double targetHeight) { double midX = (targetWidth / 2), midY = (targetHeight / 2), deltaX, deltaY,
xPosition = shot.xPos, yPosition = shot.yPos;
int targetMaxResult = 10, targetMinResult = 1, targetFactor = 16;
Variablerna deltaX och deltaY ska innehålla de positiva avstånden mellan deras respektive
koordinater och träffytans mittpunkt. Därigenom följer två if-satser, som undersöker huruvida
träffens koordinat i de olika leden är mindre eller lika med denna mittpunkt. Om så är fallet
tilldelas deltavariablerna värdet för mittpunktsvärdet subtraherat med koordinatvärdet. Om
träffens koordinat istället är större än mittpunktsvärdet så tilldelas deltavariablerna värdet för
koordinatvärdet subtraherat med mittpunktsvärdet.
if (xPosition <= midX) deltaX = midX - xPosition; else deltaX = xPosition - midX; if (yPosition <= midY) deltaY = midY - yPosition; else deltaY = yPosition - midY;
Det antagna maxresultatet som en träff i träffytan kan uppnå har tidigare definierats i
variabeln targetMaxResult. Detta maxresultat uppnår en träff antingen i mitten av träffytan,
vilket innebär att träffens koordinater är desamma som träffytans mittkoordinater i x- och y-
led, eller så nära mitten att avståndet i beräkningen avrundas till noll. Träffresultatet blir
mindre ju längre från mitten en träff hamnar. En variabel result av typen double tilldelas
resultatvärdet för en träff. Detta resultat beräknas utifrån maxresultatet, subtraherat med
divisionen av det avstånd en träff har till mittpunkten och en viss träffytefaktor. Denna faktor
är en i pixlar uppmätt medelbredd för alla poängområden i den använda träffytan, illustrerad i
Figur 4.5. Avståndet beräknas med hjälp av Pythagoras sats, innehållande de deltavärden som
beräknats för träffens x- och y-koordinater.
Notera att denna formel således är en antagen lösning utifrån den träffyta som används i
gränssnittet, och som i detta fall resulterar acceptabla värden.
double result = targetMaxResult – (Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY,
2)) / targetFactor);
50
För att förhindra att träffar utanför träffytan resulterar i träffresultat undersöker en if-sats om
resultatet är mindre än det antagna minsta möjliga resultatet i träffytan som finns i variabeln
targetMinResult, vilket är det resultat som en träff i det sista poängområdet bör resultera i.
Om så är fallet så tilldelas resultatvariabeln istället värdet noll; annars så avrundas resultatet
till en decimal. Oavsett vad som sker så adderas resultatet in i totalresultatet, med hjälp av den
variabel som har i uppgift att hålla reda på detta värde. Slutligen så returnerar metoden
träffresultatet.
if (result < targetMinResult) result = 0; else result = Math.Round(result, 1); totalResult += result; return result; }
Figur 4.5: Illustrerat poängområde i träffytan, inklusive dess breddvärde
4.3.4.5 calculateAverageScore
Denna metod har i uppgift att beräkna medelresultatet för alla träffar i listan. Metoden
returnerar resultatet av beräkningen som sker på värdet i totalResult, dividerat med
räknarvärdet i shotsInList, avrundat till en decimal.
public double calculateAverageScore() { return Math.Round((totalResult / shotsInList), 1); }
4.3.4.6 calculateAverageXPosition & calculateAverageYPosition
Dessa metoder har i uppgift att beräkna koordinaterna för den medelträff som avses
visualiseras i användargränssnittets träffyta, utifrån samtliga respektive träffkoordinater i
51
träfflistan. Funktionaliteten är densamma för dessa två metoder; även om metoden
calculateAverageXPosition beskrivs och illustreras så behöver endast alla x bytas ut mot y i
koden som implementeras.
Till att börja med instansieras en lokal variabel averageXPosition av typen double med värdet
noll. Denna variabel har i uppgift att innehålla de summerade x-koordinater som alla träffar i
listan har. För alla träffar i listan läses sedan dessa x-koordinater ut och summeras således in i
denna variabel. Metoden returnerar sedan denna summa av alla träffars x-koordinater,
dividerat med antalet träffar i listan utifrån shotsInList, avrundat till en decimal.
public double calculateAverageXPosition() { double averageXPosition = 0; foreach(Shot shot in listShots) { averageXPosition += shot.xPos; } return Math.Round((averageXPosition / shotsInList), 1); }
4.4 Testapplikation
Den fristående testapplikationen som utvecklades har i uppgift att simulera träffar. Dess
användargränssnittsutseende och funktionalitet liknar visningsklienten. I följande avsnitt
beskrivs dess vyklass och datahanteringsklass.
4.4.1 Vyklass
Avsnitt 3.8.1 beskriver testapplikationens vyklassdesign och funktionalitet, där
användarplacerade träffar simuleras, skickas till databasen och slutligen resultatberäknas.
Två metoder skiljer testapplikationens vyklass åt från den som finns i visningsklienten;
härnäst följer en beskrivning av dessa. De metoder som består oförändrade från
visningsklientens vyklass är visualizeScoreInListBox (se avsnitt 4.3.3.3) och
visualizeAverageScoreInTextBox (se avsnitt 4.3.3.4).
52
4.4.1.1 createAndVisualizeShot
Denna metod ersätter visningsklientens vyklassmetod visualizeShot (se avsnitt 4.3.3.5), och
har i uppgift att utifrån de koordinater som muspekaren har i träffytan vid tidpunkten för en
träffsimulering skapa en träff som visualiseras, och vars värden skickas vidare till databasen.
Genom att utnyttja en struct Point, som representerar ett x- och y-koordinatpar i ett
tvådimensionellt plan, kan sådana koordinater utläsas utifrån muspekarens position. En ny
sådan instans mousePoint skapas, och tilldelas muspekarens positionsvärde. Två lokala
variabler xPosition och yPosition av typen double tilldelas sedan mousePoints x- respektive y-
koordinatvärden. Således har muspekarens position hämtats och sparats för användning.
private void createAndVisualizeShot() { Point mousePoint = new Point(); mousePoint = Mouse.GetPosition(this); double xPosition = mousePoint.X, yPosition = mousePoint.Y;
Härnäst följer funktionalitet som liknar den som finns i visningsklientens visualizeShot-
metod. Träffellipsens x- och y-koordinater tilldelas de värden som hämtades från mousePoint
i samband med att dessa värden sätts med SetValue-metoden.
I slutet av metoden anropas en metod insertShotIntoDB i datahanteringsklassen, med de
sparade x- och y-koordinaterna som argument, som ämnar lägga till den visualiserade träffen i
databasen.
DH.insertShotIntoDB(xPosition, yPosition); }
4.4.1.2 target_MouseLeftButtonDown
Denna metod ersätter visningsklientens vyklassmetod button_Click (se avsnitt 4.3.3.7), och
har i uppgift att hantera händelsen då en användare klickar med muspekaren någonstans inom
träffytan. När detta sker ska således användargränssnittet uppdateras med en nyskapad och
visualiserad träff, samt med beräknade resultat.
I början av metoden anropas metoden createAndVisualizeShot, som ser till att den simulerade
träffen skapas, visualiseras och skickas vidare för att läggas till i databasen.
private void Target_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { createAndVisualizeShot();
53
En lokal variabel result av typen double tilldelas sedan det beräknade träffresultatet som
returneras från metoden calculateScore i datahanteringsklassen genom ett anrop till denna.
Som argument till denna metod skickas träffytebildens antagna bredd- och höjdvärden. Skälet
till detta är detsamma som för visningsklientens vyklassmetod button_Click, som redan
beskrivits i avsnitt 4.3.3.7. Detta resultat visualiseras sedan i användargränssnittets List Box
genom att det skickas som ett argument i anropet till metoden visualizeScoreInListBox.
double result = DH.calculateScore(Target.Width, Target.Height); visualizeScoreInListBox(result);
Därefter beräknas och visualiseras det medelresultat som alla simulerade träffar resulterat i.
En lokal variabel averageResult av typen double tilldelas det beräknade medelresultatet som
returneras från metoden calculateAverageScore i datahanteringsklassen. Detta resultat
skickas som ett argument när metoden visualizeAverageScoreInTextBox anropas. Till skillnad
från visningsklienten, där en medelträff koordinatberäknades och visualiserades i
användargränssnittets träffyta, så antogs det att den fristående testapplikationen inte krävde en
sådan, eftersom syftet med applikationen är att simulera vanliga träffar och lägga till dem i
databasen. Således återfinns inga sådana relaterade metoder eller metodanrop i
testapplikationen.
double averageResult = DH.calculateAverageScore(); visualizeAverageScoreInTextBox(averageResult); }
4.4.2 Datahanteringsklass
Avsnitt 3.8.2 beskriver testapplikationens datahanteringsklassdesign och funktionalitet, som
innefattar tömning av databasen, hantering av data däri samt resultatberäkning. Vissa
egenskaper och metoder skiljer sig från visningsklientens datahanteringsklass; härnäst följer
en beskrivning av dessa. De metoder som består oförändrade från visningsklientens
datahanteringsklass är clearDB (se avsnitt 4.3.4.2) och calculateAverageScore (se avsnitt
4.3.4.5).
54
4.4.2.1 Klassegenskaper
Den information som behöver hållas reda på i testapplikationens klassegenskaper är hur
många träffar som databasen innehåller, och det totala träffresultatet. Såldedes definieras
shotsInDB och totalResult, av typerna int respektive double. shotsInDB ersätter
klassegenskapsvariabeln shotsInList i visningsklientens datahanteringsklass, och har i uppgift
att som en räknare inkrementeras varje gång en träff ska läggas till i databasen. Variabeln
totalResult har samma syfte som totalResult i visningsklientens datahanteringsklass (se avsnitt
4.3.3.1).
class DataHandler { public int shotsInDB = 0; public double totalResult = 0;
4.4.2.2 insertShotIntoDB
Denna metod har i uppgift att, då en träff simuleras och visualiseras i användargränssnittet,
även lägga till träffen i databasen. Den tar emot två parametrar x- respektive y-Position, som
är den simulerade träffens koordinater från träffsimuleringen.
Till att börja med inkrementeras räknaren shotsInDB. Detta räknarvärde används senare i
metoden för att ge den träffs som läggs till i databasen rätt träffnummer i den simulerade
träffserien.
public void insertShotIntoDB(double xPosition, double yPosition) { shotsInDB++;
Därefter sätts en uppkoppling mot databasen upp med hjälp av en using-sats med kontexten
context. Den simulerade träffen läggs in i som en databasentitet med en antagen
enhetsidentitet bestämd till ett (1), ett träffnummer som fås ur den relaterade räknarvariabeln,
samt x- och y-koordinater ur argumentvärdena. Enhetsidentiteten som träffen tilldelas är i
testapplikationen hårdkodad i nuläget; när fler träffytor möjliggjorts i användargränssnittet
bör det här vara möjligt att använda den enhetsidentitet som respektive träffyta representerar,
möjligtvis medskickad som ännu en inparameter till metoden. Slutligen så sparas ändringen i
databasen.
55
using (Context context = new Context()) { context.shots.Add(new Shot() { Id = 1, ShotNum = shotsInDB, xPos = xPosition, yPos = yPosition }); context.SaveChanges(); } }
4.4.2.3 getLastShotXPosition & getLastShotYPosition
Dessa metoder har i uppgift att utifrån den senast tillagda träffen i databasen utläsa dess x-
respektive y-koordinat och returnera detta värde. I visningsklientens fall hade detta kunnat
skötas genom att skicka med träffen som en inparameter och ur den hämtat det relevanta
koordinatvärdet, men eftersom testapplikationen sköter användargränssnittsuppdatering
utifrån individuella träffar som i detta fall måste hämtas ut ur databasen måste enskilda
metoder skapas för denna uppgift. Funktionaliteten för dessa två metoder är densamma; även
om metoden getLastShotXPosition beskrivs och illustreras så behöver endast alla x bytas ut
mot y i koden som implementeras.
Till att börja med så används en using-sats med kontexten context för att upprätta en
uppkoppling med databasen. Väl därinne instansieras ett nytt träffobjekt lastShot av typ Shot,
som representerar den senast tillagda träffentiteten i databasen. För att få fram denna senast
tillagda träff så måste man, som avsnitt 3.6.1.4 beskriver, först ordna träffordningen i
nedåtgående ordning utifrån träffarnas träffnummer, varefter det första elementet väljs ut med
en First-metod. Slutligen returneras denna träffs x-koordinatat.
public double getLastShotXPosition() { using (Context context = new Context()) { Shot lastShot = context.shots.OrderByDescending(s => s.ShotNum).First(); return lastShot.xPos; } }
4.4.2.4 calculateScore
Denna metod har i princip samma funktionalitet som samma metod calculateScore i
visningsklientens datahanteringsklass (se avsnitt 4.3.4.4). Den enda skillnaden är att i
samband med att de första lokabla koordinat-variablerna deklareras så tilldelas variablerna
xPosition och yPosition de värden som returneras då metoderna getLastShotXPosition
respektive getLastShotYPosition anropas.
56
public double calculateScore(double targetWidth, double targetHeight) { double midX = (targetWidth / 2), midY = (targetHeight / 2), deltaX, deltaY,
xPosition = getLastShotXPosition(), yPosition = getLastShotYPosition();
4.5 Kapitelsammanfattning
Detta kapitel har beskrivit hur en SQL-server och databas sätts upp i Azureportalen, och de
brandväggsregler som behöver ändras däri för att få åtkomst till dem. Därefter beskrevs och
illustrerades utvecklingsmiljöns databasdesigner, vari man kan lägga till tabeller i databasen
och bestämma deras innehåll.
Härnäst följde ett avsnitt rörande systemets visningsklient. Avsnittet beskrev
visningsklientens ramverksimplementation, användargränssnitt och klasser.
Ramverksimplementationen innefattade modellen som bryggar applikationen och databasen,
den tillhörande uppkopplingssträngen, samt funktionalitet och kodstruktur för de resulterande
kontext- och träffmetoderna.
Användargränssnittets XAML-kod beskrevs, och själva användargränssnittet i
utvecklingsmiljöns WPF-designer illustrerades.
Vy- och datahanteringsklassernas klassegenskaper, metodfunktionalitet och kodstruktur
beskrevs sedan.
Slutligen följde ett avsnitt rörande den testapplikation som utvecklades för att spara
simulerade träffvärden i systemets databas i syfte att testa visningsklienten utifrån dessa
värden. Precis som för visningsklienten beskrevs testapplikationens vy- och
datahanteringsklasser; detta innefattade deras klassegenskaper, metodfunktionalitet och
kodstruktur.
57
5 Resultat
Detta kapitel avser resultatsammanfatta implementationen av det utvecklade systemet, innan
beskrivningar av de förväntningar och uppnådda resultat kring det utvecklade systemet och
dess olika beståndsdelar tas upp. Dessa beståndsdelar innefattar systemets fysiska
komponenter, de komponenter som rör molnet samt systemets visningsklient.
5.1 Resultatsammanfattning
I uppdragsgivaren Sogetis kravspecifikation beskrevs ett system innehållande en fysisk
träffyta, och således förväntade projektutvecklarna att det slutgiltiga systemet skulle innehålla
en sådan. Uppdragsgivaren meddelade att en träffyta kunde förses om utvecklingen lyckades
nå en punkt där en sådan ansågs vara nödvändig; i slutändan försågs ingen sådan, och
systemet saknar således i nuläget en fysisk träffyta.
De mikrofoner som försetts av uppdragsgivaren från projektstarten, och som förväntades
monteras på den eventuella träffytan, har möjlighet att registrera ljudankomster och signalera
dessa som binära signaler genom en av komponenternas portar.
Dessa signaler från samtliga mikrofoner tas emot av en Raspberry-enhet, som omvandlar de
tidsintervall som ljudankomstsignalerna ger enheten till koordinater med en
multilaterationsberäkning. De resulterande ankomstordnings- och de tidsintervallsvärden som
mäts av enheten (redovisade i bilaga B) visar sig dock vara opålitliga, då värdena inte är
konsekventa utifrån upprepade träffar på en specifik position. Enheten avser sedan skicka de
omvandlade koordinatvärdena, tillsammans med dess bestämda enhetsidentitet samt det
nummer träffen innehar i träffordningen till en molnbaserad databas.
Denna databasdata hämtas sedan i en visningsklient, som utifrån datan beräknar träffresultat.
Träffar och träffresultat visualiseras sedan i visningsklientens användargränssnitt.
Systemet fungerar i nuläget till viss del sammankopplat: . Det finns istället möjlighet att
simulera träffar i systemet på två platser och på två olika sätt: som slumpmässigt genererade
träffar i den applikation som återfinns i Raspberry-enheten, samt som manuellt placerade
träffar i den fristående testapplikationen med en träffyta liknande den som befinner sig i
visningsklientens användargränssnitt. Eftersom de både träffytorna i testapplikationens
respektive visningsklientens användargränssnitt har samma mått i bredd- och höjdled, så
58
försäkrar detta att simulerade träffar i testapplikationen placeras och visualiseras inom
träffytans ramar i visningsklienten.
5.2 Fysiska komponenter
Detta avsnitt avser beskriva de förväntningar och uppnådda resultat kring systemets fysiska
komponenter. Detta innefattar systemets träffyta och Raspberry-enhet, samt den precision
som systemet uppnår med dessa komponenter.
5.2.1 Träffyta
I uppdragsgivarens kravspecifikation beskrevs ett system innehållande en träffyta, i form av
en tavla (se bilaga A.2). På denna yta skulle användarträffar registreras av monterade
mikrofoner. Systemet förväntades därför från projektutvecklarnas håll innehålla en sådan
träffyta, men i kravspecifikationen framgick det inte om träffytan skulle förses av
uppdragsgivaren eller monteras av projektutvecklarna; under ett av de regelbundna
återkopplingsmöten som hölls med uppdragsgivaren framgick det att en träffyta kunde förses
om utvecklingen lyckades hinna nå en punkt där en sådan ansågs nödvändig.
Ingen sådan träffyta försågs eller monterades i slutändan; de omonterade
mikrofonkomponenterna (se Figur 5.1) kopplades istället direkt till systemets Raspberry-
enhet. Ljudankomster till mikrofonerna registreras, och signaleras genom en av deras portar
binärt till enheten.
59
Figur 5.1: Omonterade, numrerade mikrofoner, samt en markerad träffpunkt p
5.2.2 Raspberry-enhet
Enheten läser med hjälp av en applikation in mikrofonernas binära signaler som representerar
de ljudankomster de registrerar, som sedan mäter tidsintervall utifrån dessa. Dessa
tidsintervall omvandlas med hjälp av multilaterationsberäkning till approximerade positioner
där träffar antas ha träffat.
När dessa komponenter testas med upprepade träffar på samma position p (se Figur 5.1) visar
sig dessa uppmätta tidsintervall, samt den ljudankomstordning som registreras utifrån de
mottagna signalerna inte vara konsekventa nog mot vad som antas bör gälla utifrån upprepade
sådana försök. I bilaga B finns resultat där både ankomsttider och ankomstordning fluktuerar
mellan träffarna. Dessa resultat visar att de fysiska systemkomponenter som försetts från
projektstarten inte är precisa nog, och att själva resultaten således är opålitliga.
60
5.2.3 Systemets precision
Systemets precision misstänktes redan i kravspecifikationen vara undermålig med endast en
implementerad Raspberry-enhet (se bilaga A.2.1). Dessa prestandabrister förväntas en TDC
kunna uppväga, genom att registrera de signalerade ljudankomsterna från
mikrofonkomponenterna snabbare och mer precist. Detta skulle i sin tur leda till mer exakta
approximationer av användarträffar. En sådan enhet placeras då mellan träffytan och
Raspberry-enheten, som illustreras i den utökade systemdesignen i Figur 5.2.
Figur 5.2: Utökad design av det elektroniska skyttesystemet
5.3 Molnet
Detta avsnitt avser beskriva de förväntningar och resultat kring de systemkomponenter som är
knutna till molnet. Detta innefattar det API som bryggar applikationen i Raspberry-enheten
och databasen, samt den databas som skapats som en molntjänst i Azureportalen.
5.3.1 API
Ett API behövde placeras mellan Raspberry-enheten och databasen, då enhetens UWP-
applikation inte självmant kan ställa SQL-förfrågor. API:t har således i uppgift att ta emot
HTTP-begäranden från enheten, och skicka respektive SQL-förfråga till databasen; denna
uppgift uppfylls i nuläget.
61
5.3.2 Databas
Enligt uppdragsgivarens kravspecifikation ska vissa mätvärden sparas i en SQL-databas (se
bilaga A.2). I specifikationen finns inga preferenser om databasen ska vara en molnlösning
eller en lokal sådan. Under projektet togs därför beslutet utifrån jämförelser mellan
lösningarna (se avsnitt 3.5.1) att databasen skulle skapas som en molnlösning i Azureportalen.
En sådan databas skapades, och är i nuläget kopplad till systemet. I databasen finns möjlighet
att spara och hämta ut data i relevanta delar av systemet. Denna data består av träffentiteter
innehållande en träffs x- och y-koordinater, den identitet kopplad till enheten som skickat
datan, samt det nummer i träffordningen som träffen innehar.
5.4 Visningsklient
I uppdragsgivarens kravspecifikation finns en önskan om att en visningsklient utvecklas.
Visningsklienten fick utvecklas med vilken teknik som helst under Microsoft-plattformen (se
bilaga A.2.2), så ett antagande gjordes därefter att utveckla den som en WPF-applikation.
Enligt kravspecifikationen skulle visningsklienten beräkna en träffs approximerade position
på träffytan (se bilaga A.2.2); eftersom detta under projektets gång valdes att hanteras i
Raspberry-enhetens applikation sker således inte detta i visningsklienten. Ytterligare
utvecklingsoptioner gavs i kravspecifikationen (se bilaga A.2.4), och visningsklienten
uppfyller i nuläget de två första: den har möjlighet att visualisera träffar och beräknade
träffresultat i sitt användargränssnitt. Utöver detta beräknar applikationen ett medelresultat för
alla träffresultat, samt medelkoordinater för alla träffar. Dessa koordinater används för att
visualisera en medelträff tillsammans med övriga träffar i användargränssnittets träffyta; de
beräknade resultaten presenteras i två resultatrutor i användargränssnittet.
Figur 5.3 illustrerar den slutgiltiga visningsklienten. Flera röda träffar samt en gul medelträff
visualiseras i dess träffyta, och tillhörande träffresultat presenteras i en lista till höger om
träffytan. Notera att det presenterade medelresultatet är skilt från medelträffen;
medelresultatet beräknas utifrån träffresultat, och medelträffen utifrån träffkoordinater.
62
Figur 5.3: Illustrerad visningsklient
Visningsklienten kunde testas innan hela systemet kopplades ihop genom att hämta
simulerade träffvärden från databasen som ursprungligen skickats dit från en utvecklad
testapplikation. Denna applikation delar utseende och viss funktionalitet med
visningsklienten. Testapplikationen kan, genom att en användare positionerar träffar i dess
träffyta, utläsa de simulerade träffarnas koordinater och skicka dessa till databasen
tillsammans med en bestämd enhetsidentitet samt det nummer träffen innehar i
träffordningen.
5.5 Hela systemet sammankopplat
Hela systemet förväntades i slutändan att fungera sammankopplat, och detta mål har delvis
uppnåtts. Systemet saknar i nuläget en fysisk träffyta att montera dess mikrofonkomponenter
på. Mätvärden utifrån mikrofonkomponenterna omvandlas i Raspberry-enheten, som sedan
skickar nödvändig data genom ett API till databasen. Denna databasdata hämtas i systemets
visningsklient, som visualiserar träffarna samt deras beräknade resultat i dess
användargränssnitt.
63
De uppmätta resultat som de fysiska komponenterna ger (se bilaga B) visar dock att dessa
komponenter för tillfället inte är precisionsmässigt tillförlitliga. Resultatet får istället bevisa
att möjligheten för ett helt sammankopplat system är möjligt om det först optimeras.
I och utanför systemet finns istället möjlighet att simulera träffar på två platser i processen.
Detta kan göras i Raspberry-enhetens applikation, som genererar slumpmässiga
träffkoordinater var tionde sekund. Dessa koordinater förs med en enhetsidentitet och ett
träffnummer in i databasen, vars data sedan finns tillgänglig att uppdatera visningsklientens
användargränssnitt med. Träffsimuleringar går även att göra i den fristående
testapplikationen, där en användare manuellt placerar träffar i en träffyta liknande den som
återfinns i visningsklientens användargränssnitt. Eftersom träffytorna i de båda
applikationernas användargränssnitt har samma mått i bredd- och höjdled, försäkrar detta att
alla simulerade träffar i testapplikationen placeras och visualiseras inom träffytans ramar i
visningsklienten. Detta gäller även den träffsimulering som sker i Raspberry-enhetens
applikation, då träffytans mått i bredd- och höjdled används för att avgränsa de intervall vari
slumpkoordinater kan erhålla värden.
5.6 Kapitelsammanfattning
Det här kapitlet har gett en sammanfattning av systemimplementationens resultat. Det har
även innehållit förväntningar och resultat kring det sammankopplade systemet, samt dess
beståndsdelar. Detta innefattar systemets fysiska komponenter, där en förväntad träffyta
uteblev, mikrofoner som registrerar och signalerar ljudankomster, samt en Raspberry-enhet
som tar emot dessa signaler. Enhetens resulterande mätvärden, redovisade i bilaga B, visar sig
dock vara opålitliga; värdena är inte konsekventa utifrån upprepade träffar på en specifik
position. Enheten har möjlighet att skicka värden till systemets molndatabas genom ett API,
som översätter kommunikationen från HTTP-begäranden till SQL-förfrågor. Systemet
innehåller även en visningsklient, som har möjlighet att utföra beräkningar utifrån den data
som återfinns i databasen, samt visualisera träffar och träffresultat i sitt användargränssnitt.
Kapitlet har även innehållit en beskrivning av hur träffar kan simuleras på två olika platser
och två olika sätt: slumpmässigt genererade sådana i Raspberry-enhetens applikation, samt
användarplacerade sådana i en fristående testapplikation.
64
6 Slutsats
Detta kapitel avser redovisa de slutsatser som rapportförfattaren nått under projektet.
Projektaspekter kring utvecklingen, prototypen och uppdragsgivaren utvärderas, och områden
där framtida arbete och optimering av systemet är möjliga presenteras.
6.1 Projektutvärdering
Detta avsnitt avser utvärdera tre aspekter av projektet: utvecklingen, prototypen samt
uppdragsgivaren.
6.1.1 Utvecklingen
Ett stort fokus lades av båda projektutvecklarna under projektets tidiga skede på de delar som
från början försetts från uppdragsgivaren Sogeti, och som varit främmande mot vad som
tidigare förekommit i utbildningen. Dessa delar innefattade till största del de fysiska
komponenter som systemet skulle bestå av, samt den elektronik som hörde därtill. Tyvärr var
tiden som lades på detta i början av projektet tid som istället hade kunnat användas för att i
slutändan utveckla systemet längre än vad som hanns, utifrån de förväntningar som fanns hos
projektutvecklarna.
Under projektets gång varvades utvecklingsarbetet med rapportskrivning där detta var
möjligt. Detta innebar att förmiddagar ägnades åt utvecklingsarbete, och på eftermiddagar
gällde rapportskrivning. Detta gällde i stort sett hela projekttiden; i början lades dock större
fokus på utvecklingen, och i slutet avrundades utvecklingen och mer tid gavs
rapportskrivningen.
Utvecklingen har under projektet gett projektutvecklarna värdefull erfarenhet av sådant som
enligt intryck från uppdragsgivaren är relevant i arbetslivet. Detta innefattar utveckling inom
.NET och IoT, samt molntjänster i Azureportalen.
65
6.1.2 Prototypen
Den visningsklient som slutligen togs fram under projektet är en fungerande prototyp
utvecklad efter författarens egna antaganden. Inga större krav på denna prototyp från
uppdragsgivaren Sogetis sida har framkommit utöver de som ställdes i kravspecifikationen (se
bilaga A.2.2). Dessa antaganden, samt uppdragsgivarens synpunkter på dem under
regulbundna återkopplingsmöten under projektets gång, har därför fått styra utvecklingen.
Ett exempel på detta är visningsklientens användargränssnittsutseende och vad för slags
information som skulle presenteras däri: kravspecifikationens illustration av ett möjligt
utseende (se bilaga A.2) influerade visningsklientens presentation av vanliga träffar och
resultat, men utifrån diskussioner under de regelbundna återkopplingsmötena möjliggjordes
även presentation av medelträffar och medelresultat. Således har prototypen under projektets
gång formats av flera viljor, vilket är en viktig lärdom att ta med sig inför framtida projekt.
Vissa funktionalitetsbeslut kring prototypen har även tagits då problem uppstått, till exempel
kring automatisk hämtning av databasdata och användargränssnittsuppdatering. Att kunna
inse att vissa förväntningar inte kan uppfyllas inom ett projekts ramar och sedan hantera detta
är även detta en viktig lärdom.
6.1.3 Uppdragsgivaren
Uppdragsgivaren formulerade innan projektstart en konkret kravspecifikation, som både innan
och under projektet varit en bra stöttepelare att luta sig emot. Kravspecifikationen har inte
bara erbjudit hjälp i prototyputvecklingen, utan även i rapportskrivningen, där relevanta
avsnitt har kunnat hänvisas till vid behov.
Under projektet skedde regulbunda återkopplingsmöten med uppdragsgivaren, där möjlighet
gavs att visa utvecklingen och få respons på denna.
Till systemet har uppdragsgivaren försett den molndatabas som har använts för att spara och
hämta relevant data, samt de inloggningsuppgifter som möjliggör åtkomst till den.
Förutom de tidigare nämnda synpunkterna har uppdragsgivaren under projektets gång även
erbjudit en arbetsmiljö på Sogetis kontor i Karlstad där i princip allt arbete har utförts, de
datorer och komponenter som använts, samt den expertis som företagets anställda besitter
kring de arbetsområden som varit relevanta för projektet. Således har en bild givits av hur en
arbetssituation kan förefalla efter att utbildningen är slutförd.
66
6.2 Framtida arbete
Den främsta faktorn som under utvecklingsprocessen influerat de antaganden som gjorts är
tidsbrist. I slutändan har målet för projektet blivit att kunna presentera en fungerande
prototyp. Vissa antaganden har dock gjorts för att applikationen bara är en prototyp, och att
den således inom ramarna av projektet inte har samma krav som en riktig produkt.
Härnäst följer några punkter där systemet skulle kunna utökas i framtiden.
6.2.1 Systemfunktionalitet för flera enheter
Hantering av flera enheter önskas från Sogetis håll (se bilaga A.2.4.3). Därför innehar de
träffentiteter som hanteras i databasen en enhetsidentitet, som ämnar representera den
Raspberry-enhet som försett träffen.
I nuläget har visningsklienten endast funktionalitet för att uppvisa en träffyta, som visualiserar
alla träffar i databasen oavsett dess enhetsidentitet. De träffar som simuleras i
testapplikationen skickas in som träffentiteter till databasen med en viss enhetsidentitet, så
även denna applikation kan utökas för att möjliggöra hanteringar av flera enheter.
Implementerad funktionalitet för flera Raspberry-enheter bör påverka visningsklientens, och
isåfall även testapplikationens, utseende. Varje Raspberry-enhet borde i användargränssnittet
representeras av en egen träffyta, med tillhörande resultatrutor. Träffsimuleringsprocessen
skulle isåfall kunna fungera så att, beroende på i vilken träffyta en träff simuleras, så skickas
den till databasen med en respektiv enhetsidentitet, som sedan resultatberäknas och
visualiseras i en representerande användargränssnittsdel.
De frågor som uppstår kring en sådan implementation är hur många sådana träffytor som är
möjligt och lämpligt att visualisera, samt huruvida visualiseringen görs utifrån hur många
enheter som kopplats till systemet eller om alla möjliga träffytor visualiseras oavsett hur
många sådana enheter som upptäckts.
67
6.2.2 Datahämtning och användargränssnittsuppdatering
Den nuvarande prototypen utnyttjar manuell användaruppdatering av dess användargränssnitt.
De träffentiteter som befinner sig i databasen vid uppdateringstidpunkten läses in från
databasen till en lista. Detta leder till att alla träffar hämtas från databasen vid ett tillfälle,
istället för att databaskommunikation måste ske för varje träff då de hanteras var för sig.
En optimal lösning för systemet vore om sådan datahämtning och uppdatering kan ske
automatiskt utan användarinput. En sådan lösning skulle eventuellt kunna implementera
tekniken SignalR, som beskrivs i avsnitt 3.7.3. Tekniken implementerar ett bakplan som
sköter meddelandeprocessen mellan servrar och klienter enligt en publish/subscribe-metod.
Systemet skulle då kunna, ungefär som en chattapplikation, kunna upptäcka att information
har skickats från Raspberry-enhetens applikation och att informationen i databasen således
förändrats. Därigenom skulle visningsklienten således förstå att den behöver hämta denna nya
information på egen hand, och att därefter resultatberäkna och visualisera den i
användargränssnittet.
Om det således finns funktionalitet i visningsklienten implementerad för hantering av fler
enheter (se avsnitt 6.2.1), så behöver denna datahämtning och uppdatering eventuellt ske
asynkront beroende på vilken enhet som ursprungligen skickat informationen, vilket påverkar
i vilken användargränssnittsdel som informationen behöver visualiseras.
6.2.3 Enhetlig API-implementation
Eftersom applikationen som finns i Raspberry-enheten kommunicerar med databasen genom
ett API, kan det eventuellt vara intressant att sköta all kommunikation mellan databasen och
visningsklienten på samma sätt för att hålla systemet så enhetligt som möjligt. Enligt
uppdragsgivaren så föredras en sådan enhetlig lösning om ett API anses vara nödvändigt i de
applikationer som Sogeti utvecklar; framtida eventuella ändringar i systemet behöver isåfall
endast utföras i API:t istället för i flera systemkomponenter.
Eftersom API:t redan är färdigutvecklat och utför dess avsedda uppgift (se avsnitt 5.3.1), så
behöver endast visningsklientens funktionalitet modifieras; istället för att kommunicera direkt
med databasen genom ramverket Entity Framework så utförs detta genom API:t med HTTP-
begäranden.
68
6.2.4 Systemets databassäkerhet
De eventuella säkerhetsbrister som systemet har är de åtkomstregler som kan sättas för
databasen, samt den uppkopplingssträng som kopplar visningsklienten till den. Sådana brister
i systemets säkerhet kan leda till att obehörig åtkomst till server och databas förekommer och
att data däri påverkas.
De åtkomstregler som i nuläget gäller för databasen är de brandväggsregler som kan sättas för
både den Azure SQL-server som innehåller databasen, samt även enskilt för varje enskild
databas i servern för ytterligare åtkomstkontroll. Sådana regler håller reda på de IP-adresser
som tillåts åtkomst till servern och därigenom dess databaser.
Under utvecklingsprocessen av applikationen frågas huruvida den uppkopplingssträng som
däri används för åtkomst till databasen ska innehålla känslig information eller ej. I nuläget
antogs denna lösning vara god nog för en prototyp, men möjlighet finns att låta en användare
under exekvering förse applikationen med de inloggningsuppgifter som krävs. Möjligtvis kan
en implementationslösning där sådana uppgifter läses in från separata konfigureringsfiler även
vara relevant.
Sådana lösningar kan således i autentiseringssyfte koppla behöriga användare till
databasåtkomst utifrån de uppgifter eller filer som de tilldelas, istället för att all åtkomst tillåts
direkt från applikationen.
6.3 Slutord
Rapportförfattarens intryck av projektet är i det stora hela mycket positivt. Projektet har både
av projektutvecklarna och utomstående ansetts vara ett bra ingenjörsprojekt, då det innehållit
moment och komponenter som har varit nya från vad som tidigare förekommit i utbildningen.
Projektutvecklarna har således tagit med sig erfarenhet av utveckling som enligt de intryck
från uppdragsgivaren visar kan komma att vara relevanta i arbetslivet. Uppdragsgivaren har
för övrigt varit ett stort stöd under projektet, då projektutvecklarna försetts med det material
och den expertis som hjälpt till att driva utvecklingen framåt.
Utvecklingen har under projektet skett förhållandevis problemfritt, och har i den mån det varit
möjligt varvats med rapportförfattandet. Vissa antaganden behövdes i slutskedet göras utifrån
tidsbrist, men i slutändan resulterade projektet i ett delvis sammankopplat, fungerande system.
Även om systemet saknar en fysisk träffyta och dess precision dras ned utav dess fysiska
komponenter ger det ändå en bild av hur ett optimerat sådant system skulle kunna fungera i
framtiden.
69
Huruvida projektmålen från början varit för ambitiösa för projektets tidsramar, eller om
brister hos projektutvecklarna lett till att projektet inte räckte längre vågar inte
rapportförfattaren svara på. Även om inte alla frågeställningar kunnat besvaras (se bilaga
A.2.3) eller alla optioner hanterats (se bilaga A.2.4) i kravspecifikationen, så kan det i nuläget
delvis fungerande prototypsystem som tagits fram visa att ett mindre kostsamt elektroniskt
skyttesystem är möjligt, samt att möjlighet till fortsatt utveckling och optimering finns.
70
Referenser
[1] Ivarsson, N. 2016. Electronic Scoring System: An Electronical & Mathematical
Approach. Unpublished.
[2] Sogeti, “Historia”, [Online]. Tillgänglig: http://www.sogeti.se/om-oss/historia/ [Använd
18 02 2016]
[3] Capgemini, “Company Profile & Key Figures”, [Online]. Tillgänglig:
https://www.capgemini.com/about/group/company-profile-key-figures [Använd 18 02
2016]
[4] Wikipedia, “Electronic scoring system”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Electronic_scoring_system [Använd 08 02 2016]
[5] Megalink Electronic Scoring Systems, “10m range - Cheongwon SR”, [Online].
Tillgänglig: http://www.megalink.no/ [Använd 17 02 2016]
[6] Salazar, D., Waterman, M. 2011. Electronic Target. Senior Design II, Northern Illinois
University
[7] Wikipedia, “Trilateration”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Trilateration [Använd 11 02 2016]
[8] SparkFun Electronics Inc., “SparkFun Sound Detector”, [Online]. Tillgänglig:
https://www.sparkfun.com/products/12642 [Använd 08 02 2016]
[9] Wikipedia, “Trilateration”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Trilateration#See_also [Använd 10 02 2016]
[10] Raspberry Pi, “Raspberry Pi 2 Model B”, [Online]. Tillgänglig:
https://www.raspberrypi.org/products/raspberry-pi-2-model-b/ [Använd 10 02 2016]
[11] Wikipedia, “Raspberry Pi”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Raspberry_Pi [Använd 10 02 2016]
[12] Wikipedia, “Time-to-digital converter”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Time-to-digital_converter [Använd 11 02 2016]
[13] Wikipedia, “Windows 10 Editions”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Windows_10_editions [Använd 10 02 2016]
[14] Halsey, M. 2015. Windows 10 Primer, New York City, NY: Apress, pp. 33.
[15] Wikipedia, “Internet of Things”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Internet_of_Things [Använd 11 02 2016]
[16] Wikipedia, “SQL”, [Online]. Tillgänglig: https://en.wikipedia.org/wiki/SQL [Använd
18 02 2016]
[17] Microsoft, “Entity Framework”, [Online]. Tillgänglig: https://msdn.microsoft.com/en-
us/library/gg696172%28v=vs.103%29.aspx [Använd 03 03 2016]
[18] Microsoft Azure, “What is Azure”, [Online]. Tillgänglig:
https://azure.microsoft.com/en-us/overview/what-is-azure/ [Använd 18 02 2016]
[19] Microsoft Azure, “Services”, [Online]. Tillgänglig: https://azure.microsoft.com/en-
us/services/ [18 02 2016]
[20] Wikipedia, “Windows Presentation Foundation”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Windows_Presentation_Foundation [Använd 11 02 2016]
[21] Wikipedia, “Business Logic”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Business_logic [Använd 18 02 2016]
71
[22] Wikipedia, “Microsoft Visual Studio”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Microsoft_Visual_Studio [Använd 11 02 2016]
[23] Wikipedia, “C Sharp (programming language)”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/C_Sharp_%28programming_language%29 [Använd 16 02
2016]
[24] Wikipedia, “Universal Windows Platform”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Universal_Windows_Platform [Använd 19 05 2016]
[25] Wikipedia, “Application programming interface”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Application_programming_interface [Använd 19 05 2016]
[26] Wikipedia, “Hypertext Transfer Protocol”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol [Använd 19 05 2016]
[27] SQLite, “About SQLite”, [Online]. Tillgänglig: http://www.sqlite.org/about.html
[Använd 21 03 2016]
[28] SQLite, “When To Use SQLite”, [Online]. Tillgänglig:
http://www.sqlite.org/whentouse.html [Använd 21 03 2016]
[29] Entity Framework Tutorial, “DbContext”, [Online]. Tillgänglig:
http://www.entityframeworktutorial.net/EntityFramework4.3/dbcontext-vs-
objectcontext.aspx [Använd 19 05 2016]
[30] Microsoft, “LINQ to Entities”, [Online]. Tillgänglig: https://msdn.microsoft.com/en-
us/library/bb386964%28v=vs.100%29.aspx [Använd 12 04 16]
[31] Wikipedia, “Extensible Application Markup Language”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/Extensible_Application_Markup_Language [Använd 28
03 2016]
[32] Microsoft, “WPF Designer Overview”, [Online]. Tillgänglig:
https://msdn.microsoft.com/en-us/library/bb514528%28v=vs.90%29.aspx [Använd 28
03 2016]
[33] Fletcher, P., Wasson M. 2014. Introduction to Scaleout in SignalR. [Blog] ASP.NET.
Tillgänglig: http://www.asp.net/signalr/overview/performance/scaleout-in-signalr
[Använd 19 05 2016]
[34] Wikipedia, “DreamSpark”, [Online]. Tillgänglig:
https://en.wikipedia.org/wiki/DreamSpark [Använd 19 05 2016]
[35] Wikimedia Commons, “File: 10 m Air Rifle target.svg” [Online]. Tillgänglig:
https://commons.wikimedia.org/wiki/File:10_m_Air_Rifle_target.svg [Använd 19 05
2016]
[36] Wikipedia, “Inkscape”, [Online]. Tillgänglig: https://en.wikipedia.org/wiki/Inkscape
[Använd 19 05 2016]
72
A Kravspecifikation av Mats Persson
A.1. Allmän beskrivning av uppdraget
A.1.1 Bakgrund
Sogeti Sverige AB (Sogeti) är ett IT-konsultbolag med bred verksamhet, stort fokus på
kompetens och modern teknik.
Inom sportskytte används idag elektroniska markeringssystem för att detektera och avläsa
träffar och dess poäng. Det finns flera olika tekniker för detta, men bland de vanligare är att
systemen använder akustik, där man med tre eller flera sensorer (mikrofoner/piezosensorer)
och med trilateration baserat på ljudhastigheten detekterar var på en yta en kula träffar.
De största kommersiella systemen som finns för detta idag är:
• Megalink - http://megalink.no/
• Sius - http://www.sius.com/
Dessa system är förhållandevis dyra, från 30 000 kr och uppåt per enhet, och detta exjobb
ämnar att utreda om man med billiga standardkomponenter kan implementera ett liknande
system och uppnå den precision som krävs, alternativt utreda hur hög precision som man
rimligen kan uppnå. En implementation av ett prototypsystem ingår också.
Olika skyttediscipliner kräver olika upplösning, men till exempel kan nämnas att för att ett
system skall fungera bra för 10m luftgevärsskytte så bör en precision på tiondels millimeter
uppnås.
Vi tror att man till exempel skulle kunna använda en Raspberry Pi 2 tillsammans med en s.k.
”Time To Digital”-omvandlare för att mäta tidsskillnaderna mellan signalerna från
mikrofonerna
A.2. Markeringssystem
Uppdrag går ut på att utveckla ett markeringssystem för att ta emot träffar på en tavla och
presentera träffarna i en klient.
Med hjälp av 4 mikrofoner kopplade till en Raspberry Pi 2 så tar man emot mätvärden och
sparar ner det i en databas tillsammans med namnet på enheten. I visningsklienten sen hämtas
mätvärden från databasen och den räknar ut var på tavlan man träffat presenterar det.
73
Som vi ser det så består uppdraget av följande delar:
Koppla ihop allt och få systemet att reagera när mikrofonerna tar emot ljud av en viss
ljudnivå (mycket elektronik i detta)
Läsa in mätvärden från mikrofonerna
Ta reda på hur man räknar ut med så hög precision som möjligt var på tavlan man
träffat.
Vilken precision kan man uppnå med hårdvaran uppdragstagarna har tillgängligt och
jämföra detta med befintliga system.
A.2.1 Raspberry Pi 2
Enheten behöver kunna ta emot mätvärden från alla 4 mikrofonerna, applikationen som
hanterar detta ser vi gärna att man utvecklar och kör i Windows 10 på enheten. Enheten
behöver kunna trigga händelser i visningsklienten för att den ska uppdatera sig också, om man
inte väljer att helt lösa det på visningsklienten så den uppdaterar sig på annat sätt. Det kan
vara så att ytterligare hårdvara krävs för tidsregistrering då IOingångarna på t.ex. en Rasberry
Pi 2 troligen är för långsamma för att detektera de korta tider det rör sig om.
A.2.2 Visningsklienten
Visningsklienten behöver kunna hämta data från databasen och det här skall beräkningen
ligga för att räkna ut var på tavlan man har träffat. Detta inkluderar då att ta fram den
matematiska formel som behövs för att kunna räkna ut, med så hög precision som möjligt, var
på tavlan man träffat utifrån 4 mätvärden.
74
Visningsklienten lämnar vi fritt för uppdragstagarna att själva välja vad de vill utveckla med
för teknik, vi vill dock att man håller sig till Microsoft-plattformen. Några av alternativens
som finns är:
ASP.NET MVC (webb)
WPF (desktop)
UWP (Universal app för Windows 10 desktop, plattor, telefoner m.m.)
A.2.3 Utredning
Det finns några saker att reda ut i detta uppdraget, så en del av uppdraget är att svara på
följande frågor:
Hur hög precision kan man komma upp i med den utrustning som finns tillgänglig?
(del av mm., mm, cm, dm?)
Vilken typ av hårdvara skulle man behöva för att komma upp i högre precision?
Hur mycket skiljer det i precision med den tillgängliga utrustningen jämfört med de
kommersiella systemen som finns?
A.2.4 Optioner
Följande är förslag på vidareutveckling av detta som uppdragstagarna själv får plocka från om
tid finns. Innan uppdragstagarna börjar med någon option så måste ett möte till för att
prioritera dessa.
A.2.4.1 Option 1 – Presentera träffarna i en klient
När visningsklienten fått in information om en träff och räknat ut var på tavlan man träffat så
ska det även presenteras grafiskt i en tavla så man tydligt ser var man träffat.
A.2.4.2 Option 2 – Presentera hur mycket poäng varje träff är värd
Efter att man tagit reda på var på tavlan man träffat så kan man räkna ut hur mycket poäng
träffen är värd och även presentera det för användaren.
A.2.4.3 Option 3 – Hantera flera enheter
Att enbart hantera en enhet är begränsande så finns det tid så se till att visningsklienten har
stöd för att visa information från flera tavlor.
A.2.4.4 Option 4 – Administrationsdel
I visningsklienten ska det också finnas en administrationsdel där man kan se vilka ”tavlor”
som finns tillgängliga och där man kan sätta upp en tävling med flera deltagare och att
75
mätresultaten som kommer in kopplas till en specifik person i tävlingen. Programmet ska
även då kunna presentera en vinnare efter att alla skjutit ett antal skott som man också kan
ställa in.
A.3. Genomförande/arbetssätt
A.3.1 Rutiner
Sogeti tillhandahåller arbetsplatser, datorer, hårdvara samt erforderliga utvecklingsverktyg.
Uppdragstagarna kommer att ha access till Sogetis nätverk och förväntas nyttja vår TFS-
server för versionshantering.
A.3.2 Hårdvara
Hårdvara för projektet kommer att bestämmas och köpas in innan projektets start men det är
inte bestämt än exakt vad för hårdvara det kommer vara.
A.3.3 Genomförande
Uppdragstagarna planerar själv genomförandet och Sogeti tillhandahåller stöttning både
projektstyrningsmässigt och rent implementationstekniskt. Sogeti tillhandahåller all
programvara och hårdvara som behövs.
Förslagsvis används SCRUM med en sprintlängd på 2-3 veckor som sätts upp där
uppdragstagarna specificerar vad de tror att de hinner med i början av varje sprint och har en
demo för en eller flera på Sogeti i slutet på varje sprint.
A.4. Stöd/kvalitetssäkring
A.4.1 Granskningar
Vid behov genomförs granskning som kan initieras av både handledare och uppdragstagare.
Lämpligen definieras några granskningspunkter vid planeringen av projektet.
A.4.2 Testarbete
Funktions-, system- och integrationstest görs av uppdragstagarna.
A.4.3 Stöd
Eftersom detta uppdrag är väldigt tungt med elektronik så har vi hittat ett liknande projekt
som man kan kika på för att komma igång snabbt.
http://hotchk155.blogspot.com/2011/10/musical-ping-pong-tables-and.html
76
http://hotchk155.blogspot.com/2011/11/lost-in-maths.html
http://hotchk155.blogspot.com/2012/02/midi-table-top-sensingits-working.html
A.5. Leveranser
A.5.1 Dokumentation
Systemdokumentation görs av uppdragstagarna. Dokumenten lagras i projektarkiv hos Sogeti.
A.6. Konfigurationsstyrning
All programkod och tillhörande specifikationer och andra utvecklingsdokument ska
versionshanteras med hjälp av Microsoft TFS.
A.7. Miljö
Utvecklingsmiljö för projektet skall om möjligt vara Visual Studio 2015.
A.8. Uppföljning och Rapportering
A.8.1 Rapportering internt/externt
A.8.1.1 Statusrapportering
Rapportering av status och framskridande i utvecklingen beslutas i samråd vid
projektuppstart.
A.8.1.2 Möten
Möten hålls vid behov. Vid uppstart läggs lämpligt antal avstämningsmöten in i
projektplanen.
A.8.1.3 Slutrapportering
Arbetet presenteras för Sogeti i samband med lämpligt månadsmöte alternativt lunchmöte.
77
B Resultat för ljudankomster till systemets mikrofonkomponenter
1. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001184 0.0005981 0.0142898" 2. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001184 0.0005981 0.0142898" 3. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001184 0.0005981 0.0142898" 4. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.000571 0.0012036 0.0154032" 5. Order: "Detector order: 3 1 4 2 " Time: "Time differences: 0 0.0002047 0.0004116 2.0127742" 6. Order: "Detector order: 3 1 4 2 " Time: "Time differences: 0 0.0002047 0.0004116 2.0127742" 7. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001155 0.0006424 0.0127164" 8. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001111 0.0006781 0.0129435" 9. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001111 0.0006781 0.0129435" 10. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001111 0.0006781 0.0129435" 11. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.0008667 0.001424 0.0141191" 12. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 9.61E-05 0.0006673 0.0138749" 13. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 9.61E-05 0.0006673 0.0138749" 14. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 9.61E-05 0.0006673 0.0138749" 15. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001007 0.0006233 0.0125089" 16. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001114 0.0005628 0.0129779" 17. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001114 0.0005628 0.0129779" 18. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001114 0.0005628 0.0129779" 19. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.0006501 0.0011831 0.0145521" 20. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001115 0.000613 0.0145816" 21. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001115 0.000613 0.0145816" 22. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001115 0.000613 0.0145816" 23. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.0006448 0.0014338 0.012015 " 24. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.000113 0.000587 0.0129469" 25. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 9.93E-05 0.0006272 0.0132733" 26. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 9.93E-05 0.0006272 0.0132733" 27. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 9.93E-05 0.0006272 0.0132733" 28. Order: "Detector order: 3 1 4 2 " Time: "Time differences: 0 9.43E-05 0.0003033 0.014213 " 29. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 9.33E-05 0.0005258 0.011332 " 30. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 9.33E-05 0.0005258 0.011332 " 31. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 9.33E-05 0.0005258 0.011332 " 32. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.0006344 0.0011601 0.0138831" 33. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 9.53E-05 0.0005456 0.0148781" 34. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 9.39E-05 0.0001653 0.0408589" 35. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.0006926 0.0012303 0.0143309" 36. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.0006926 0.0012303 0.0143309" 37. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.0006926 0.0012303 0.0143309" 38. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0005902 0.0006819 0.0131173" 39. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.00011 0.0004944 0.0153759" 40. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.00011 0.0004944 0.0153759" 41. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.00011 0.0004944 0.0153759" 42. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001114 0.0006314 0.0139413" 43. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.0006318 0.0011992 0.0136182" 44. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.0006318 0.0011992 0.0136182" 45. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.000113 0.0004775 0.0131893" 46. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001129 0.0005138 0.0149096" 47. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001129 0.0005138 0.0149096" 48. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001129 0.0005138 0.0149096" 49. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001127 0.000746 0.0140518 " 50. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0004528 0.0006627 0.0144632" 51. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0004528 0.0006627 0.0144632" 52. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.0006854 0.0011765 0.0144559" 53. Order: "Detector order: 1 3 4 2 " Time: "Time differences: 0 0.0007267 0.0012248 0.0141011" 54. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.000121 0.0004878 1.0997302" 55. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.000121 0.0004878 1.0997302" 56. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.000121 0.0004878 1.0997302" 57. Order: "Detector order: 1 4 3 2 " Time: "Time differences: 0 0.0001078 0.0007021 0.0128322"