MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_NextPart_01C4CD51.1B5B4D70" Dette dokument er en webside i én fil. Det kaldes også en webarkivfil. Hvis du kan se denne meddelelse, skyldes det, at webbrowseren eller editoren ikke understøtter webarkivfiler. Hent en webbrowser, der understøtter webarkivfiler, f.eks. Microsoft Internet Explorer. ------=_NextPart_01C4CD51.1B5B4D70 Content-Location: file:///C:/4939CAB4/Delttavleudviklingsrapport.htm Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset="us-ascii" Arkitektur

 =

 =

 =


Delt tavle over Internettet

 

 

 

 <= /span>

 <= /span>

 

 

 

 

 

 

 <= /span>

Projekt Flexnet

Ole E. M. Borch, Aalborg Universitet

Rune Lund Olesen, Aalborg Universitet

Axel Gottlieb Michelsen, Aalborg Universitet<= /p>

 <= /span>

 

 

 

 

 

 

 

 

ID: AAU.IES.Flexnet
12. februar 2004
<= /o:p>


<= /o:p>

Indled= ning= .. 4=

Proble= mformulering= .. 5=

Forana= lyse= .. 6=

Protokoller= . 6

TCP (Transport Control Protocol) [RFC793]= 6

HTTP (HyperTekst Transfer Protocol)  [RFC1945]= 6

UDP (U= niversal Datagram Protocol)  [RFC768]= 6

RTP (Real Time Protocol) [RFC1889] 6

SIP (Session Initiation Protocol) [RFC2543]= 7

Shared whiteboards= . 7

Coccinella [COCC]= 7

Network Assistant [NETA] 8

Teknol= ogier= . 9

Servle= ts [DJSE] [TYJS] [JSSE]  [PJSP]<= /span>= 9

Mica [= MICA]= 9

XML [X= ML]= 9

Analys= e af anvendelsesområde.. 10=

Proble= mopdeling= . 10

Idenfi= kation af aktøre. 10

Netv&a= elig;rk= . 10

Bruger= = 10

Whiteb= oardklient= 10

Usecas= e= . 10

Delpro= blemer= 11

Swimla= nes= . 12

Funkti= onstabel= 15

Whiteb= oardserver= . 17

Usecas= e= . 17

Swimla= nes= . 17

Funkti= onstabel= 18

Design= og implementering.. 19=

Arkite= ktur= . 19

Whiteboard= . 19

WBStar= t= 21

FileMa= nager= 21

WBPopu= pMenu= . 21

Whiteb= oard= . 22

Messag= eListener= 23

Drawin= gTabbedPane= . 23

Drawin= gArea= . 24

WBConf= ig= . 24

Messag= es= . 24

Messag= e= . 27

Drawab= le= . 27

DeltaD= rawingArea= . 27

FullDr= awingArea= . 28

MText<= /span>= 29

MDelet= e= . 29

MElips= e= . 29

MMulti= Line= . 30

MRecta= ngle= . 30

Tools<= /span>= . 31

Toolbo= x= . 33

Drawin= gConfiguration= . 34

Tool= 35

PressD= ragRelease= . 35

TextTo= ol= 36

FillCh= ooserTool= 36

ColorTool= 37

Stroke= WidthChooser= 37

Whiteb= oardserver= . 38

Result= ater= .. 39=

Test= 40

Konklu= sion= .. 42=

Fremti= digt arbejde. 42

Instal= lering= .. 43=

Whiteb= oardklient i en applet 43

Whiteb= oardserver= . 43

How To= .. 44=

Tilføje features til whiteboard= . 44

Popup = menu (højre click på whiteboard)= 44

Lav et= nyt DeltaDrawingArea. 44

Kilder= .. 46=

 <= /span>

Indledning=

Samarbejdende aktiviteter over netværk leder naturligt tanken hen på anvendel= se af multitast som kommunikationsmetode. Princippet går ud på at = alle klienter lytter efter datapakker på nettet indeholdende en defineret IP-multicastadresse. Når blot en eller flere klienter sender på samme adresse, vil alle modtage samme data. Der er altså ingen server involveret – kun datanettet. Problemet med multicast, er at der anven= des UDP som transportprotokol (ofte lukket da UDP er connection-less og derfor virker som ’reklamepostkasse’) og at multicast typisk ikke forwardes af rutere.  Derfor ønskes en application som anvender unicast og TCP. Problemet er om d= er også skal anvendes en fast server eller denne centrale facilitet skal ligge i alle klienter hvor et abitreringssystem skal afgøre hvem der skal være server. Andre variationer findes også. Her vælg= es en client/server løsning.


Problemformule= ring

Udviklingen ønskes foretaget efter objektorienterede principper og programmeret = i Java. Der ønskes foretaget et design med stor vægt på komponen= ter og genbrug. Den grafiske brugergrænseflade ønskes udformet som= en komponent som let kan indlejres i en java frame eller en applet, som dereft= er kan tilkobles et bestemt rum. Der ønskes flere tavle-sessions, hvilk= et betyder, at flere tavler kan eksistere samtidigt på serveren og bruge= rne kan framelde og tilmelde en tavle-session i takt med at der skiftes rum i et virtuelt college.


Foranalyse=

Eftersom shared whiteboard nødvendigvis skal kommunikere over netværk v= il der i foranalysen blive undersøgt forskellige protokoller. Endvidere= vil eksisterende shared whiteboards blive undersøgt for at få en større viden om emnet. Til sidste vil et antal eksisterende teknolog= ier blive undersøgt i håb om at noget kan genbruges.=

Protokoller

TCP (Transport Control Protocol) [RFC793]

TCP er den gængse transportprotokol på internettet. Den er robust, og generelt et godt = valg til overførsel af data.

Den har dog en del kompli= kationer i forbindelse med realtids audio, bl.a. kan dens congestion control, hvor transmissionraten midlertidigt reduceres, skabe huller i datastrømme= n. Dette er brugbart for almindelig streaming media da den gennemsnitlige transmissions rate er mere konsistent, og tillader mange forbindelser at skalere sig mod hinnanden.

TCP bygger også p&a= ring; et data aknowledge system, som sikre at tabte pakker bliver retransmiteret. I forbindelse med audio kan det betyde at en sample ankommer efter den skulle være afspillet, og er derfor spildt båndbredde, da den er forældet.

HTTP (HyperTekst Transfer Protocol)  [RFC1945]

HTTP bygges ovenpå = en TCP forbindelse, og fungere efter besked/svar princippet.

HTTP bruges hyppigt i for= bindelse med netradio, hvor en stabil strøm af data, der kan modtages gennem proxy servere og firewalls er ønskeligt. Der bruges ofte en meget st= or lokal buffer til at kompensere for TCP protokolens slowstart, og congestion kontrol, ofte 10-15 sekunder.

UDP (Universal Datagram Protocol)  = [RFC768]

UDP bruges flittigt i Voi= ce over IP sammenhænge pga. det lave delay og meget høje udnyttelsesgr= ad. UDP er dog blokeret i visse firewall, men flere applikationer kompensere for dette ved at bygge sig op så det stille så lille et krav til hu= llet i firewallen som muligt. Ofte (se Team Speak og Pico Phone) ved at kun bruge én enkelt port, som kan ændres hvis tilpasning er nødvendigt. Client/Server modellen er også brugt, hvor man kan bruge en server mellem to firewalls, så indgående forbindelser = ikke er et krav.

RTP (Real Time Protocol)= [RFC1889]

RTP er en transport proto= kol brugt til lyd- og billedemedia, transmiteret over UDP, og giver faciliteter= til f.eks. synkronisering af lyd og billede, samt codec specificering.

RTP laver dog et vist ove= rhead, og skal kombineres med RTCP (Real Time Control Protocol) for at fungere optimalt.

SIP (Session Initiation Protoco= l) [RFC2543]

SIP eller Session initiate protokol, er en protokol standard beregnet til at brugere kan kalde op, og udveksle forskellige informationer før selve opkaldet. F.eks. om transportprotokol og codec.

SIP kan fungere ovenp&ari= ng; TCP eller UDP, og kan udveksle informationer om firewalls og evt. Proxy servere= i brug, og dermed hjælpe programmer med at etablere den bedst mulige forbindelse inden selve forbindelsen, og dermed opkaldet, bliver oprettet.<= /p>

Et muligt scenarie kunne = f.eks. være at finde ud af hvilke, om nogen, af klienterne den kan modtage U= DP pakker, eller og en alternativ transport løsning, f.eks. via TCP, sk= al søges.

Shared w= hiteboards

Coccinella [COCC]

Coccinella er en chatklient til instant messaging protokollen Jabber med shared whiteboard.

Jabber bruger XML i sin p= rotocol.

Test af Coccinella

Opsætn= ing:

·        2 Klienter kørte over jabber.dk

·      =   OS: Windows XP og Windows 2000

·        Coccinella kræver et TCL[1] script fortolker installeret først

 

jabber.dk havde en averag= e round trip time på 25,5 ms.

Udfør= sel:

Session blev oprette og de forskellige tegneredskaber blev undersøgt med henblik på konsistens og resulterende latenstid.

Resultat:

Brugervenlighed

Selvom ingen af testpersonerne kendte jabber v= ar det meget intuitivt.

Coccinella, når sessionen er igang, vold= te heller ikke de store problemer.

Antallet af funktioner er passende, og de er a= lle anvendelige.

Latenstid

Overførslen af simple figure som firkan= ter og cirkler foregik med lav latens (ca. 1 sek eller under).

Farvelægning af firkanter og cirkler for= egik med samme lave latenstid.

Stregtegning varierede meget(fra næsten ubemærkeligt til 1 min i værste tilfælde). Det var af stor betydning hvor kompliceret tegningen var.

Et billede (bitmap) blev sat ind. Det nå= ede ikke frem.

Bugs

Programmet var temmelig fejbehæftet p&ar= ing; Windows platformen.

Fejlene var af forskellige karakter og i regle= n af kritisk art.

Efter flere forsøg blev det konstateret= at når session forsøges startet er det ikke altid den når f= rem til modtageren, dette resulterer ofte i flere forskellige vinduer men kun et der skal bruges.

Ved erase all funktionen efterfulgt af undo funktionen blev der genereret en fejlmeddelelse.

Network Assistant [NETA]

Network Assistent er et L= AN chatprogram med indbygget shared whiteboard og eventlogger.

Test af Network Assistant

Opsætn= ing:

·        2 klienter, ingen server opsætning

·      =   OS: Windows XP og Windows 2000

Udfør= sel:

Session blev oprettet og = de forskellige tegneredskaber med videre blev undersøgt med henblik på konsistens og resulterende latenstid.

Resultat:

Brugervenlighed

Network Assistant er meget brugervenligt. Brugergrænsefladen er opbygget så der er konsistens med microso= fts brugergrænseflade.

Ved whiteboardet er kun simple funktioner til = stede. Det er ikke muligt at slette enkelte streger eller ændre på indholdet af whiteboardet på andre måder end ved at slette hele whiteboardet eller tegne oven i den eksisterende tegning.

Latenstid

Network Assistant havde meget lav latens.

På intet tidspunkt blev der observeret latenstider på over 2 sekunder.

Bugs

Ingen bugs blev fund<= /a>

Teknologier

Servlets [DJSE] [TYJS] [JSSE]  [PJSP]

Java servlets er et frame= work til at skrive webserverapplikationer, almindeligvis ved at bruge HTTP protokole= n.

De har en række for= dele i forhold til andre serverside løsninger mht. Til dynamisk content og = serving.

Buzzwords som effektivitet (kompleksitetsmæssigt), platformsuafhængighed, sikkerhed, pålidelighed og fleksibilitet gør sig gældende.

Endvidere er almindelige firewalls og proxys ikke noget problem, eftersom servlets bruger TCP port 8= 0, som også benyttes af webservices generelt.

Dog kan TCP protokollen introducere for meget overhead i denne sammenhæng.

Mica [MICA]

Mica er et objektorienter= et grafisk framework, specielt bygget til at underbygge implemenation og manipulation af grafikeditore, tegneprogrammer og brugergrænseflader.=

Mica giver udvidet support til display li= sts, event handling, action dispatching, coordinate transforms og connectivity.<= o:p>

En ulempe ved mica er ris= ikoen for at introducere for meget overhead når objekter skal overfø= res.

XML [XML]

XML, Extensible Markup La= nguage, er et simpelt og meget fleksibelt opsætningssprog. XML er som så= ;dan ikke et værktøj, men bliver bl.a. brugt i Jabber som er brugt i forbindelse med Coccinellas netværks del.

Formatet kan eventuelt br= uges til at formatere grafikken, der skal sendes over netværket. Eftersom XML = er et tekstformat, og formateringen derfor er i ren tekst, er der en risiko fo= r at der introduceres for stort et overhead hvis mange små objekter skal t= ransmitteres. I så fald skal der tages ekstra skridt for at minimere dette, hvilket indebærer risiko for at bevæge sig væk fra den objektorienterede tankegang.


Analyse af anvendelsesområde

I analysen af anvendelsesområdet analyseres de aktører de enkelte delproblemer skal interagere med. For at give et større overblik, vil opdelingen af problemstillingen blive klarlagt.=

Problemopdeling

Shared whiteboard bliver = delt op i whiteboardklient og whiteboardserver, på henholdsvis klientsiden og serversiden, for nemmere at kunne beskrive den ønskede funktionalite= t. Dette er visualiseret i Figur 1.

 

Figur 1 Shared whiteboards delproblemer=

Idenfikation af aktøre

De to delproblemers anven= delsesområde har tilsammen følgende aktøre.

Netværk

Netaktøren represe= nterer det netværk, som forbinder de enkelte computere med hinanden. Det er = en vigtig aktør på grund af netværkets nondeterministiske n= atur og fastlægelsen af de protokoller der skal anvendes for at kunne kommunikere over netværket.

Bruger

Brugeraktøren er d= en aktør som interagerer med systemet udefra. Brugeren stiller i dette projekt krav om funktionalitet og grafik. Brugeren er på samme tid producer og consumer.

Whiteboardklient

 

Usecase

For at finde de brugsmønstre der gør sig gældende ved whiteboardkliente= n, opstilles et brugsmønsterdiagram for denne.

Figur 2 Usecasediagram for whiteboardkl= ient

I Figur 2 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000D0000005F005200= 65006600360033003400330034003000310031000000 er brugsmønsterdiagrammet for whiteboardklienten vist. De to aktøre er brugeren og netværket. Brugsmønstrene er kort beskrevet i det følgende.

Delprobl= emer

For nemmere at kunne over= skue realisationen af brugsmønstrene deles whiteboardklienten op i tre delproblemer. Disse delproblemer er et delproblem for hver aktør, som varetager grænsefladen til disse, og et delproblem, som er kernefunktionaliteten af white boardet, og interfacer til de to andre delproblemer.

 

Figur 3 Whiteboardklientens delprobleme= r

I Figur 3 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000D0000005F005200= 65006600360033003400330034003100300034000000 ses det samlede problem delt op i de tre dele, hv= oraf den første omhandler interaktion med brugeren, den anden omhandler whiteboard funktionalitet og den tredje omhandler kommunikation med netværket. Delproblemerne vil i det følgende fremgå ved = hver deres swimlane.

Swimlanes

På de følgen= de aktivitetsdiagrammer er adskillelser og kommunikation mellem delproblemerne vist. Aktivitetsdiagrammerne viser hvad der sker når en bruger eller netværket interagere med systemet.

Figur 4 Manipuler whiteboard brugsmønster

Figur 4 viser aktivitetsdiagrammet for manipuler white bo= ard. Brugeren manipulerer whiteboardet ved hjælp af UI. Herefter opdateres white boardet, og opdateringen sendes ved hjælp af klientsession.

Figur 5 Modtag opdatering brugsmø= ;nster

Figur 5 viser aktivitetsdiagrammet for modtag opdatering. Opdateringen bliver modtaget over nettet, hvorefter white boardet bliver opdateret.

Figur 6 vælg tegneindstillinger brugsmønstret

Figur 6 viser aktivitetsdiagrammet for vælg tegneindstillinger. Fra UI vælges indstillinger, som opdateres i white boardet.

Figur 7 vælg figur brugsmø= nstret

Figur 7 viser aktivitetsdiagrammet for brugsmønstr= et se figurinfo. Brugeren vælger en figur gennem UI, hvorefter white boa= rdet viser informationen for brugeren.

Figur 8 Gem fil brugsmønstret

Figur 8 viser aktivitetsdiagrammet for brugsmønstr= et gem. Brugeren vælger at gemme gennem UI, hvorefter white boardet vise= r en filvælgermenu. Brugeren vælger herefter filen. Endelig bliver w= hite boardet gemt i den valgte fil.

Figur 9 Åbn fil brugsmønst= ret

Figur 9 viser brugsmønstret hent white board fra f= il. Først vælger brugeren at åbne en fil ved hjælp af = UI. Herefter viser white boardet en filvælger, så brugeren kan vælge hvilken fil der skal åbnes. Filen åbnes, og whiteboardet bliver opdateret i henhold til indholdet i filen. Endelig bliv= er opdateringerne sendt ved hjælp af klient session.

Funktionstabel

I dette afsnit vil aktivi= teterne fundet i det foregående blive nedbrudt til funktioner, enten i forhol= det en til en eller i forholdet en aktivitet til flere funktioner.

Aktiviteter

Funktioner

Beskrivelse

Send besked

Send

Send sender sessionsrelevant data til klientsession.=

Vælg figur

Vælg figur

Vælg figur lytter efter de hændelser der= kendetegner en brugers ønske om at vælge en figur.

Vis figurinfo

Vis figurinfo

Viser et tooltip med brugeren der har tegnet det pågældende elements navn.

Vælg tegneindstillinger

Vælg tegneindstillinger

Viser en brugergrænseflade hvori tegneindstill= inger som tykkelse af streg, farve og fyldfarve kan vælges.

Sæt tegneindstillinger

Sæt tegneindstillinger

Sætter de valgte tegneindstillinger.

Gem

Gem

Gem funktionen reagerer på hændelsen gem= , som indtræffer når brugeren vælger at gemme whiteboardet i = en fil.

Åbn

Åbn

Åbn funktionen reagerer på hændels= en åbn, som indtræffer når brugeren vælger at å= ;bne en fil.

Vis filvælger

Vis filvælger

Viser en brugergrænseflade, hvori det er mulig= t at vælge filen der skal tilgåes.

Vælg fil

Vælg fil

Vælg fil reagerer på hændelsen vælg fil.

Filbehandling

Læs fil

 

Skriv fil

Læs fil læser et whiteboard fra en fil.<= /p>

Skriv fil skriver et whiteboard ned i en fil

Manipuler white board

Tilføj element

 

 

Slet element

 

Ændr element

Tilføj element funktionen indsætter et element på white boardet.

Slet element sletter et element på whiteboarde= t.

Ændr element ændrer på et element på whiteboardet.

Send opdatering

Send

Send sender den indpakkede opdatering via klientsess= ion.

Modtag opdatering

Modtag

Modtag modtager en indpakket opdatering fra klientse= ssion.

 

Whiteboardserver

Usecase

For at finde de funktione= r som skal implementers i det endelige produkt udarbejdes usecase for white board serveren.

Figur 10 Usecasediagram for whiteboardse= rver

I Figur 10<= !--[if gte mso 9]> 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000D0000005F005200= 65006600360033003400330034003200350038000000 ses aktøren net som repræsenterer netværket. White board serveren modtager data fra nettet, sender data over nettet, og modtager sessionsændringer. Usecasene er uddybet i det efterfølgende.

Swimlanes

Figur 11 Modtag opdatering brugsmø= ;nster

Figur 11 viser aktivitetsdiagrammet for usecasen modtag. Serveren modtager en white board opdatering fra nettet, som bliver brugt ti= l at opdatere modellen af whiteboardet på serveren. Herefter sendes opdateringen ud over netværket til alle klienter i samme gruppe som sender af opdateringen.

Funktionstabel

I dette afsnit vil aktivi= teterne fundet i det foregående blive nedbrudt til funktioner, enten i forhol= det en til en eller i forholdet en aktivitet til flere funktioner.

 

Aktiviteter

Funktioner

Beskrivelse

modtag opdatering

modtag

Modtager data fra whiteboardklienten og sender det t= il alle whiteboardklienterne.


Design og implementering

Eftersom udviklingen af whiteboardet har været stærk iterativt og præget af udstrakt brug af prototyping bliver der i det efterfølgende ikke skelnet mellem beslutninger taget under design og implementering.

Arkitektur

Whiteboardklienten best&a= ring;r af tre dele. Messages delen, som sørger for at encode og decode besk= eder der skal sendes eller er blevet modtaget over netværket, Whiteboard delen, den del der kan tegnes på og Tools delen, som er værktøjer der kan bruges til at tegne på DrawingArea del= en. Whiteboardserveren består af en enkelt komponent som videresender beskeder modtaget over netværket.

Et deploymentdiagram der = viser hvordan de forskellige komponenter er fordelt ud kan ses i figur Figur 12.

= Figur 12 Deployment af Shared Whiteb= oard

 

<= o:p> 

Whiteboard

Repræsentationen af Whiteboardet ses i = Figur 13.

Figur 13

Whiteboard komponenten ha= r ansvar for at vise whiteboardet samt for at kommunikere med whiteboardserveren. Derudover er den ansvarlig for at whiteboardet bliver startet rigtigt op, derunder for at starte Tools komponenten.

WBStart

WBStarts opgave er at instanciere Whiteboard på = samme måde, lige meget om WBStart bliver brugt som en applet eller eksekver= et i en Java Virtual Machine (JVM). Klassen WBStart kan ses i figur Figur 14.

Figur 14 Klassen WBStart

WBStart nedarver fra JApplet og indeholder funktionen = init for at kunne blive startet som en applet og indeholder funktionen main for = at kunne blive eksekveret i en JVM.

FileManager

FileManager indeholder statiske funktioner til at gemme billeder som filer og hente billeder i filer. Klassen kan ses i Figur 15.

Figur 15 Klassen FileManager

WBPopupMenu

Klassen WBPopupMenu ses i Figur 16.

Figur 16 Klassen WBPopupMenu

WBPopupMenu nedarver fra JPopupMenu og bliver vist som en popup menu på whiteboardet. Den implementerer MouseListener for at kunne fange events genereret af DrawingA= rea og derved kunne reagere på højreklik med musen på denne. Derudover er WBPopupMenu sin egen ActionListener for at kunne fange events genereret når en bruger klikker på de enkelte menupunkter i popupmenuen. WBPopupMenu bruger FileManager til at hente billeder fra filer= og gemme billeder i filer.

Whiteboard

Whiteboard klassen er den øverste klasse i Whiteboards klassehierakiet. Klasen kan ses i Figur 17.

Figur 17 Klassen Whiteboard

Whiteboards opgaver best&= aring;r i at instanciere klasser længere nede i klassehierakiet, vise disse klassers grafiske representation og ekstern kommunikation til whiteboardserveren.

MessageListener

MessageListener er et int= erface til klasser som ønsker at blive gjort opmærksom på Messa= ges der er færdige til at blive sendt over netværket.

Figur 18 Interfacet MessageListener

DrawingTabbedPane

DrawingTabbedPane viser e= t antal Drawingareas som på et JTabbedPane. Klassen kan ses i Figur 19.

Figur 19 Klassen DrawingTabbedPane

DrawingTabbedPane inds&ae= lig;tter Toolbox og WBPopupMenu som EventListeners på Drawingarea når den bliver instancieret.

DrawingArea

DrawingArea viser tegneområdet som et JPanel. Klassen kan ses i Figur 20<= !--[if gte mso 9]> 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000D0000005F005200= 65006600360033003400330034003400340038000000 .

Figur 20 Klassen DrawingArea

For at fjerne flimmer i g= rafikken bliver der brugt double buffering til at optegne billedet. DrawingArea indeholder en liste af Drawables, drawableList, som endnu ikke er blevet verificeret af serveren, for at sørge for at de enkelte klienter er synkroniserede. Denne list kan tilgås med operationerne add og remove. Operationen paint bruges til at tegne en Drawable på DrawingArea.

WBConfig

WBConfig interfacet er en opremsning af indstillingsmulighederne for whiteboardet.

Messages

Klasserne i Messages er s= om set i figur Figur 21, med Message som superklassen alle klasser nedarv= er fra.

Figur 21 Messages klasse diagram

Objekterne bliver encodet= som byte arrays, så de kan sendes over netværket, ved at kalde enco= de funktionen, som i hvert objekt kalder encode funktionen i den klasse de nedarver fra, før de selv enkoder data, og returnerer det som et byte array. Et sekvensdiagram som viser dette kan ses i Figur 22<= !--[if gte mso 9]> 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000D0000005F005200= 65006600360033003400330034003400370039000000 .

Figur 22 Sekvensdiagram for enkodning af objekter af klassen Message

På den måde bliver data tilhørende = de enkelte klasser pakket ned som vist på eksemplet af et nedpakket obje= kt af klassen MEllipse i

Figur 23 Formatet for et enkodet objekt = af klassen Message

Et enkodet objekt kan rek= onstruktureres ved at kalde konstruktoren i den klasse den er blevet enkodet ud fra med by= te arrayet som input. Ved at kalde konstuktoren fra superklassen bliver data enkodet ved hjælp af superklassens encode funktion dekodet. Et sekvensdiagram som viser hvordan byte arrayet bliver dekodet kan ses i Figur 24.

Figur 24 Sekvensdiagram for dekodning af objekter af klassen Message

Message

Message er den øverste klasse i Message hieraki= et og kan ses i Figur 25.

Figur 25 Klassen Message

Message opgave bestå= ;r i at identificere objekter af klasser der nedarver fra Message som unikke objekt= er, selvom de har været encoded som et byte array og decoded til et objek= t af klassen Message igen. Dette gøres ved at generere et tilfældigt tal, sessionId, for hvert whiteboard, så de enkelte klienter kan skel= nes fra hinanden og et fortløbende tal, idNr, for hvert objekt af klassen Message, så de enkelte objekter af klassen Message instancieret p&ari= ng; de enkelte klienter kan skelnes fra hinanden. Equals funktionen fra klassen Object er overskrevet så sammenligningen sker på baggrund af id= Nr og sessionId.

Drawable

Drawable nedarver fra Mes= sage og kan ses i Figur 26.

Figur 26 Klassen Darwable

Den indeholder informatio= n om hvilket DrawingArea Drawable skal tegnes på. Endvidere har den en abstract funktion, paint, som bliver kaldt når børn af Drawable skal tegnes på et DrawingArea.

DeltaDrawingArea

DeltaDrawingArea nedarver= fra Drawable og kan ses i

Figur 27 Klassen DeltaDrawingArea

DeltaDrawingArea indehold= er information nødvendigt når der skal tegnes på et eksisterende DrawingArea. color er den farve der skal tegnes med, strokeWid= th er bredden af stregen i pixels og fill er en boolsk værdi som udtrykk= er om objektet som skal tegnes skal fyldes ud eller ej.

Envidere har den en abstr= acte funktioner, create, som skal overskrives af nedarvende klasser så den returnerer en ny instans af den nedarvende klasse, setStartingPoint, som sk= al overskrives af nedarvende klasser så udgangspositionen bliver gemt i = den og setPoint, som skal overskrives af nedarvende klasser så de gemmer = det punkt der er blevet sat. Endvidere skal setPoint returnere en boolsk værdi, hvorvidt hele drawingArea skal gentegnes eller ej.

FullDrawingArea

FullDrawingArea nedarver = fra Drawable og kan ses i

Figur 28 Klassen FullDrawingArea

FullDrawingArea indeholder billedet fra et DrawingArea, så det kan sendes over netværket.<= /p>

MText

MText nedarver fra DeltaDrawingArea og kan ses i Figur 29.

Figur 29 Klassen MText

MText indeholder text skr= evet på DrawingArea og begyndelseskoordinaterne for teksten, x og y, s&ari= ng; tekst kan sendes over netværket.

MDelete

MDelete nedarver fra DeltaDrawingArea og kan ses i Figur 30.

Figur 30 Klassen MDelete

DELETE_STROKE_MULTIPLIER er den faktor strokeWidth bli= ver ganget med før der bliver slettet på drawingArea, så MDe= lete bliver tegnet større end en tilsvarende streg.

MElipse

MElipse nedarver fra DeltaDrawingArea og kan ses i Figur 31.

Figur 31 Klassen MEllipse

MEllipse indeholder begyndelseskoordinaterne, højden og vidden for en ellipse, x, y, w o= g h, så den kan sendes over netværket. Operationen paint tegner en ellipse som beskrevet i variablene.

MMultiLine

Klassen MMultieLine kan ses i Figur 32<= !--[if gte mso 9]> 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000D0000005F005200= 65006600360033003400330034003500380039000000 .

Figur 32 Klassen MMultiLine

MMultiLine indeholder en = liste af x- og y-koordinater, så en mængde sammenhængende streger = kan tegnes.

MRectangle

Klassen MRectangel kan ses i Figur 33<= !--[if gte mso 9]> 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000D0000005F005200= 65006600360033003400330034003500390038000000 .

Figur 33 Klassen MRectangle

MRectangle indeholder begyndelseskoordinaterne, højden og vidden for et rektangel, x, y, w= og h, så den kan sendes over netværket. Operationen paint tegner et rektangel som beskrevet i variablene.

Tools

Værktøjerne = til whiteboard er organiseret som vist i Figur 34.

Figur 34 Klassediagram over klasser i to= ols.

Toolbox modtager events f= ra objekter af klassen DrawingArea og videresender dem til det valgte Tool, hvorved objekter af klassen DrawingArea kan manipuleres. Dette kan ses p&ar= ing; sekvensdiagrammet i Figur 35.

Figur 35 Sekvensdiagram over håndteringen af events på whiteboardet

Brugeren tegner på DrawingArea. De generede events bliver hørt af Toolbox, som sender d= em videre til det valgte Tool. Det valgte Tool instancierer en subklasse til M= essage, og modificerer den som Toolet fortolker den modtagne event. Denne Message bliver tegnet på DrawingArea, hvorefter Brugeren enten tegner videre på den samme Message, eller bliver færdig med at tegne. Hvis brugeren tegner videre bliver den instancierede Message modificeret endnu engang. Når brugeren har tegnet færdigt bliver messageCreated k= aldt i Whiteboard, som sender den færdige Message over netværket.

Toolbox

Toolbox klassens opgaver består i at vise Tools i Whiteboardet og videresende events fanget på DrawingArea til det valgte Tool. Klassen Toolbox kan ses i Figur 36.

Figur 36 Klassen Toolbox

Toolbox implementerer KeyListener, MouseListener og MouseMotionListener. Metoderne i Toolbox send= er events fanget fra DrawingArea til currentTool ved at kalde tilsvarende funktioner i tool, handleMouseClicked for mouseClicked og så videre.<= /p>

DrawingConfiguration

DrawingConfiguration klas= sens opgave består i at gemme indstillinger af Tools et centralt sted. Kla= ssen DrawingConfiguration kan ses i Figur 37.

Figur 37 KlassenDrawingConfiguration

strokeColor er den farve = streger skal tegnes med, strokeWidth er den tykkelse streger skal tegnes med i pixe= ls og fill er om objekter skal tegnes fyldt ud eller tomme.

Tool

Klassen Tool kan ses i Figur 38.

Figur 38 Klassen Tool

Tool er en abstrakt klass= e, hvis opgave er at stille en række callbackfunktioner til rådighed for klasser, som nedarver fra tool. Callbackfunktionerne bliver kaldt når= der forgår events på DrawingArea. Tool nedarver fra JButton, og bli= ver derved fremstillet som en knap i ToolBox. Objekter af klassen Tool er deres egen ActionListener og sætter sig selv som valgte Tool i Toolbox når den bliver klikket på.

PressDragRelease

PressDragRelease nedarver= fra Tool og er universalværktøjet for whiteboardet. Klassen PressDragRelease kan ses i Figur 39.

Figur 39 Klassen PressDragRelease

 Alt som skal tegnes ved at presse v= enstre museknap ned på DrawingArea, trække musen rundt på DrawingArea og slippe venstre museknap på DrawingArea for at afslutte tegningen, tegnes ved hjælp af toolet PressDragRelease. Et tilstandsdiagram der beskriver PressDragRelease kan ses i Figur 40.

Figur 40 Tilstandsdiagram for objekter af klassen PressDragRelease

Hændelser press, drag og release svarer til de t= re funktioner fra Tool som er overskrevet af PressDragRelease, HandleMousePres= sed, HandleMouseDragged og HandleMouseReleased.

PressDragRelease opererer på DeltaDrawingAreas, så en ny subklasse til DeltaDrawingArea kan gives til PressDragReleas= e, hvorved Whiteboardet nemt kan udbygges med flere tegneredskaber. Objekter af klassen PressDragRelease bliver brugt til at tegne rektangler, elipser, frihåndstegning og til at slette.

TextTool

TextTool nedarver fra Too= l og overskriver funtionerne handleMouseReleased i Tool. Klassen TextTool kan se= s i Figur 41.

Figur 41 Klassen TextTool

Når musens venstre = knap bliver sluppet på DrawingArea poppes en JTextField op, hvori der kan skrives. Ved endt skrivning bliver der instancieret et objekt af klassen MT= ext som bliver sendt til Whiteboard.

FillChooserTool

FillChooserTool nedarver = fra Tool og overskriver actionPerformed, så FillChooserTool ikke bliver valgt = som det aktive Tool i Toolbox når der bliver klikket på Toolet i Toolboxen, men i stedet ændrer på om rektangler og ellipser skal tegnes fyldt ud eller tomme. Klassen FillchooserTool kan ses i Figur 42= .

= Figur 42 Klassen FillChooserTool

ColorTool

K= lassen ColorTool kan ses i Figur 43.

Figur 43 Klassen ColorTool

Ligesom FillChooserTool n= edarver ColorTool fra Tool, og overskriver actionePerformed i Tool, så ColorT= ool ike bliver valgt som det aktive tool, men i stedet åbner en color cho= oser dialog, hvor der kan vælges en farve. DrawingConfiguration bliver efterfølgende opdateret, så color er tilgængelig for alle tools.

StrokeWidthChooser

StrokeWidthChooser, som ses i Figur 44<= !--[if gte mso 9]> 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000D0000005F005200= 65006600360033003400330034003700370039000000 , nedarver ikke fra Tool som de andre værktøjer, men i stedet fra JSlider, så den bliver en sl= ider i stedet for en knap.

Figur 44 Klassen StrokeWidthChooser

StrokeWidthChooser er sin egen ChangeListener og opdat= erer DrawingConfiguration når StrokeWidth bliver ændret, så StrokeWidth er tilgængelig for alle tools.

Whiteboardserver

Klassediagramme for WhiteboradServeren kan ses i Figur 45.

Figur 45 Klassen SServer

Whiteboardserveren best&a= ring;r af en enkelt klasse, SServer, som sender beskeder modtaget fra en whiteboardklient ud til alle whiteboardklienterne. Endvidere gemmes modtagne beskeder i et objekt af klassen DrawingTabbedPane. Når en bruger logg= er på whiteboardserveren bliver DrawingAreaer fra DrawingTabbedPane sendt til den nye whiteboardklient, så den har samme DrawingAreaer som de a= ndre klienter.


Resultater

Et screendump af det endelige produkt kan ses i Figur 46. Det viste Whiteboardet kører som en applet under Windows.

Figur 46 Whiteboardet

I venstre side ses den gr= afiske repræsentation af Toolbox med de forskellige tools, som kan bruges ti= l at manipulere drawingArea med. I midten ses den grafiske repræsentation = af DrawingArea med tabbed panes, som kan bruges til at skifte mellem de forske= llige whiteboards, i toppen.

Ved at højreklikke på whiteboardet åbnes WBPopupMenu med de to underpunkter Open og Save as, som det ses i

Figur 47 Whiteboardet med WBPopupMenu

Whiteboardet blev testet = på samme måde som de fundne whiteboards blev testet i foranalysen, da det ikke er muligt at måle latenstid fra noget er tegnet på et whiteboard til det dukker op på et andet.

 

Test

Opsætn= ing:

·        2 Klienter

·      =   OS: Windows XP og Windows 2000

·        1 Server

·        OS: Windows 2000

·        LAN

Udfør= sel:

Whiteboardserveren blev started på serverpc’eren, hvorefter whiteboardklienterne blev started på d= e to klientmaskiner med serverens IP-addresse som parameter.

Resultat:

Latenstid

Overførslen af simple figurer som firka= nter, cirkler og frihåndstegning foregik med lav latens (under et sekund).<= /p>

Overførsel af billeder, ved at åb= ne dem i whiteboardklienten, foregik også med lav latens (under et sekund).<= /p>

 


Konklusion

 

Der er udviklet et shared whiteboard ved hjælp af klient/server arkitekturen. Shared whiteboard= har et simpelt brugerinterface hvormed, der kan tegnes simple figure og skrives tekst, gemme og hente billeder. Overførslen af figurer og billeder o= ver netværket sker med lav latenstid.

 

Shared whiteboard er blev= et udviklet efter objektorienterede principper og implementeret i Java. Under udviklingen er der blevet lagt stor vægt på at shared whiteboard skulle være let at videreudvikle, hvilket har resulteret i et udbyggelsesvenligt produkt.

Derudover kan shared whit= eboard indgå som en delkomponent i andre projekter da whiteboardklienten kan indlejres i en Java frame eller en applet.

 

En begrænsning for = shared whiteboard er at det ikke er udviklet til flere tavlesessions, hvilket reulterer i at der skal være en server til hvert enkelt shared whiteboard.

 

Fremtidigt arbejde

 

Da hverken serveren eller= den brugte protokol, TCP, understøtter brugen af flere tavlesessioner kan der implementeres en sessionsprotokol mellem transportlaget og shared whiteboard.

Endvidere kan funktionali= teten udbygges med flere tegneredskaber.


Installering

Whiteboardklient i en applet

 

  1. Sørg for at jar fil med whiteboard klienten er "signed" med et certifikat. Kend IP-addressen på en kørende whiteboard server.
  2. Skriv jar filen ind på den hjemmeside hvor whiteboard skal vises. Det gøres såden:

<APPLET codebase=3D"../../../&quo= t; code=3D"vcollege/whiteboard/client/WBStart.class"

archive=3D"vcollege/whiteboard/clien= t/WBStart2_3.jar" width=3D800 height=3D600>

<PARAM name=3Dserverip value=3D"127.0.0.1">

</APPLET>

Parameteren serverip bliv= er brugt af klienten til at connect til serveren. Ændr dens value til serverens IP-addresse.

  1. Sørg for at hjemmesiden ligger på en webserver der understøtter applets. Webserveren og whiteboardserveren kan være samme ip/maksine.
  2. Gå ind på hjemmesiden og appletten starter op automatisk i browsere= n.

 

Whiteboardserver

 

  1. Find SServer.class filen. Den ligger som standard under vcollege/whiteboard/server. Serveren kører på TCP port 12= 58.
  2. Start serveren ved: java SServer
  3. Klienter kan nu connect til serveren og tegne på dennes whiteboard. Sørg for at klient- og serverversionerne er kompatible og at der ikke er problemer med proxyen for klienterne.

 


How To =

Tilføje features til whiteboard

Alle klasserne nævnt i den følgende tekst= kan findes i vcollege.whiteboard.client pakken(package). En god forståels= e af java syntax og semantic er at foretrække for at bruge denne how to, m= en nogle af emnerne kan udføres af de fleste brugere.

Popup menu (højre click på whiteb= oard)

  1. Find WBPopupMenu class.
  2. Tilføj et menu item til popupmenu i meto= den

private void createPopupMenu( JPopupMenu popmenu, ActionListener al) med eksempelvis popmenu.add(new JMenuItem("NAMETOAPPEAR", SHORTCUTKEY )).addActionListener(al);

SHORTC= UTKEY: er en tast som brugeren trykker på istedet for musen, referer til, ja= va api class KeyEvent. Kan også blot udelades.

  1. Gå til

public void actionPerformed(ActionEvent e= )

og tilføj en if st= atement i begyndelsen af methoden, som her:

if (sourceText.equals("NAMETOAPPEAR")) {

            //kode der skal eksekveres når brugeren trykker.

}

hvor NAMETOAPPEAR er det = samme som i 2.

Lav et nyt DeltaDrawingArea

DeltaDrawingArea er de objecter der ændrer p&ari= ng; drawingarea’et, f.eks. en firkant, referer til klassebeskrivelsen for mere info. Som eksempel på et specialiseret DeltaDrawingArea kan anbefales MEllipse.

  1. Opret en ny klasse som nedarver DeltaDrawingArea klassen.

pub= lic class NAVN extends DeltaDrawingArea

her er NAVN navnet p&arin= g; den ny klassen.

  1. Da DeltaDrawingArea er en abstract klasse kræver den at en ræ= kke metoder som minimum implementeres. Disse er:

    abstract void setStartingPoint(int x, int y);

 &nb= sp;          kaldes når startkoordinaten kendes.

    abstract boolean setPoint(int x, int y, java.awt.Graphics g);

            kaldes hvergang et nyt koordinat kendes(hvis f.eks. musen trækkes).

    abstract DeltaDrawingA= rea create();

            skal returnere en ny instans af det mest specialiseret object.

Skriv metoderne ind i kla= ssen (fjern abstract).

  1. To andre metoder er nødvendige for at objecter transmitteres korre= kt over netværket. Tilføj følgende metoder:

    public ByteArrayOutput= Stream encode() {

        ByteArrayOutputStream baos =3D super.encode();

            //tilføj de ting til baos’en som er nødvendige for encodningen.

    }

og en constructor (virker= kun med nøjagtigt fingerprint)

    public NAVN(ByteArrayInputStream bais){

        super(bais);

//fjern de ting fra bais’en som du encoded ovenfor i samme rækkefølge.<= /o:p>

    }

NAVN er klassenavnet.

  1. Klassen består også af Drawable(endnu en abstract klasse), her er = det nødevendig at implementer en metode om hvordan objected skal te= gnes (fjern abstract).

public abstract void paint(Graphics g);

grafik objectet g, er der= hvor grafikken skal tegnes på. Det udgør hele tegnefladen i størrelsen.

  1. Hvis det giver mening at oprette objectet med tryk-træk-slip adfær(denne er så generel at det virker for stort set alle ting der skal tegnes, og det er jo netop tilfældet her), kan det= ny DeltaDrawingArea tilføjes i Toolbox umiddelbart ved brug af den allerede eksisterende PressDragRelease klasse. Find klassen Toolbox og tilføj i konstruktoren:

 

this.add(new PressDragRelease(this, createImageIcon("toolpics/FILNAVN.png", "ICON_NAVN"), n= ew NAVN()));

<= o:p> 

NAVN er klassenavnet.

ICON_NAVN er et arbitr&ae= lig;rt navn, som ikke skal bruges til noget.

FILNAVN er navnet på= ; en billedfil som bliver billedet på iconet.


 

Kilder

[RFC2543] - SIP: Session initiation protocol

http://www.ietf.org/rfc/rfc2= 543.txt

<= o:p> 

[RFC1889] - RTP: A transport protocol for real-time applications

http://www.ietf.org/rfc/rfc1= 889.txt

<= o:p> 

 [RFC768] – UDP: User datagram protocol

http://www.faqs.org/rfcs/rfc793.html

 <= /span>

 [RFC791] – IP: Internet protoc= ol

http://www.faqs.org/rfcs/rfc= 791.html

<= o:p> 

[RFC793] – TCP: Transmission control protocol

http://www.faqs.org/rfcs/rfc= 793.html

<= o:p> 

 [RFC1945] <= span lang=3DEN-US style=3D'mso-ansi-language:EN-US'>HTTP: Hypertext Transfer Pro= tocol

http://www.faqs.org/rfcs/rfc= 1945.html

<= o:p> 

[COCC] – Coccinella homepage=

http://hem.fyristorg.com/matben/

<= o:p> 

[NETA] – Network Assistant h= omepage

http://www.gracebyte.com/nassi/

<= o:p> 

[MICA] – The MICA Graphics F= ramework homepage

http://www.swfm.com/mica.htm

<= o:p> 

[DJSE] – Developing Java Ser= vlets. James Goodwill ISBN: 0-672-31600-5

<= o:p> 

[TYJS] – Teach Yourself Java= Server Pages. Jose Annunziato et al. ISBN: 0-672-32023-1

 

[JSSE] – Jav= aServer Pages, Second Edition. Hans Bergsten ISBN: 0-596-00317-X

 

[PJSP] – Proffesional Java Se= rver Programming. Danny Ayers et al. ISBN: 1-861002-77-7

 

[XML]Extensible Markup Language (XML)

http://www.w3.org/XML/

<= o:p> 



[1] Tool Command Language. Fortolkersprog, ofte embedded I andre systemer.

------=_NextPart_01C4CD51.1B5B4D70 Content-Location: file:///C:/4939CAB4/Delttavleudviklingsrapport-filer/image001.jpg Content-Transfer-Encoding: base64 Content-Type: image/jpeg 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 //////////////////8D6AAAAAD/////////////////////////////A+gAADhCSU0EAAAAAAAA AgACOEJJTQQCAAAAAAAGAAAAAAAAOEJJTQQIAAAAAAAQAAAAAQAAAkAAAAJAAAAAADhCSU0EHgAA AAAABAAAAAA4QklNBBoAAAAAA10AAAAGAAAAAAAAAAAAAABPAAAAuQAAABQAaQB0AHYAZQBzAHQA RABLAGwAZQBhAHIAbgBpAG4AZwBuAGUAdAAzAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAA AAAAAAC5AAAATwAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABAAAAABAAAAAAAA bnVsbAAAAAIAAAAGYm91bmRzT2JqYwAAAAEAAAAAAABSY3QxAAAABAAAAABUb3AgbG9uZwAAAAAA AAAATGVmdGxvbmcAAAAAAAAAAEJ0b21sb25nAAAATwAAAABSZ2h0bG9uZwAAALkAAAAGc2xpY2Vz VmxMcwAAAAFPYmpjAAAAAQAAAAAABXNsaWNlAAAAEgAAAAdzbGljZUlEbG9uZwAAAAAAAAAHZ3Jv dXBJRGxvbmcAAAAAAAAABm9yaWdpbmVudW0AAAAMRVNsaWNlT3JpZ2luAAAADWF1dG9HZW5lcmF0 ZWQAAAAAVHlwZWVudW0AAAAKRVNsaWNlVHlwZQAAAABJbWcgAAAABmJvdW5kc09iamMAAAABAAAA AAAAUmN0MQAAAAQAAAAAVG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAA AE8AAAAAUmdodGxvbmcAAAC5AAAAA3VybFRFWFQAAAABAAAAAAAAbnVsbFRFWFQAAAABAAAAAAAA TXNnZVRFWFQAAAABAAAAAAAGYWx0VGFnVEVYVAAAAAEAAAAAAA5jZWxsVGV4dElzSFRNTGJvb2wB AAAACGNlbGxUZXh0VEVYVAAAAAEAAAAAAAlob3J6QWxpZ25lbnVtAAAAD0VTbGljZUhvcnpBbGln bgAAAAdkZWZhdWx0AAAACXZlcnRBbGlnbmVudW0AAAAPRVNsaWNlVmVydEFsaWduAAAAB2RlZmF1 bHQAAAALYmdDb2xvclR5cGVlbnVtAAAAEUVTbGljZUJHQ29sb3JUeXBlAAAAAE5vbmUAAAAJdG9w T3V0c2V0bG9uZwAAAAAAAAAKbGVmdE91dHNldGxvbmcAAAAAAAAADGJvdHRvbU91dHNldGxvbmcA AAAAAAAAC3JpZ2h0T3V0c2V0bG9uZwAAAAAAOEJJTQQUAAAAAAAEAAAABThCSU0EDAAAAAALtgAA AAEAAACAAAAANwAAAYAAAFKAAAALmgAYAAH/2P/gABBKRklGAAECAQBIAEgAAP/tAAxBZG9iZV9D TQAC/+4ADkFkb2JlAGSAAAAAAf/bAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwM DAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwM DAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/8AAEQgANwCAAwEiAAIRAQMR Af/dAAQACP/EAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVS wWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSl tcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5/cRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFR YXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOE w9N14/NGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x//aAAwDAQACEQMRAD8A v/Vj6sfXTD+ulvUOoWuOJutOTkm0ObkNcHChjKGvc9u17q7GMsZX9m9P02Lrfrh1LM6V9W87qGE4 MycdjXVuc0OAJexplh/kuXm31R611q/69YuLf1HLux3ZGQ11Fl9j6yG15DmNNT3lnt2NW/8A4zei 9ftZk9WpzzX0inHrbdg+raA9wedzvs7f1d385V9P9xJTc/xbfWnrP1gs6k3qljLBiig1bGBkep9o 9Sdv0v5li7deG/U7oX1i6yc5vQuonpr6G1euRbbTv3+t6P8ARfp+l6dv0/8ASL2+lr2U1sedz2tA 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 /sf0bfS+zehA9fbs2R+b6se3/PXzEkkp+prfs+6r1dm7d+h3RO+HfzW78/Zv+ihv/Z8u3+jPqM3z tn1fb6O7/hvoen+evl1JJT9Sfqu+7+b37R6/E7Yds9b+R9PbvS/U9tEent0+zfRidp2+h/1r/R/4 NfLaSSn6kP2Ob59OYH2mds7Y09f+T6f+kWf1jEw8nHq2XVU2ME0S4Na5hj2N/kfR2OavmtJQ817X sz97+br1f9zX9Zkw8fuR9v5r0foxmd1/HaKbMY2uboHlpcf7T6jscnwca2zqAy+qWMZfp6OOXNDt ZDP0c+1jf8G399fOSSzcPF7sPvHu+1xD7v7vy8f6HvcP6f7jbyVwS9rg46/W8G/D+l7b9TH0Nr52 bZ/STETp9NNd9m09fZ3jfHz+kvlpJbDQfqc+luZO3drs4njXYkPS9R23b6kDfEbo12bv+kvlhJJT 9TU/Z9fQ2fytkfjtSf8AZ4fv2Rp6kx/Z3r5ZSSU//9k4QklNBCEAAAAAAFUAAAABAQAAAA8AQQBk AG8AYgBlACAAUABoAG8AdABvAHMAaABvAHAAAAATAEEAZABvAGIAZQAgAFAAaABvAHQAbwBzAGgA bwBwACAANwAuADAAAAABADhCSU0EBgAAAAAABwAIAAAAAQEA/+ESSGh0dHA6Ly9ucy5hZG9iZS5j b20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSfvu78nIGlkPSdXNU0wTXBDZWhpSHpyZVN6TlRj emtjOWQnPz4KPD9hZG9iZS14YXAtZmlsdGVycyBlc2M9IkNSIj8+Cjx4OnhhcG1ldGEgeG1sbnM6 eD0nYWRvYmU6bnM6bWV0YS8nIHg6eGFwdGs9J1hNUCB0b29sa2l0IDIuOC4yLTMzLCBmcmFtZXdv cmsgMS41Jz4KPHJkZjpSREYgeG1sbnM6cmRmPSdodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIy LXJkZi1zeW50YXgtbnMjJyB4bWxuczppWD0naHR0cDovL25zLmFkb2JlLmNvbS9pWC8xLjAvJz4K CiA8cmRmOkRlc2NyaXB0aW9uIGFib3V0PSd1dWlkOmFmZmUxNjUxLTE2OWQtMTFkOC1iZjc2LTgy YTM4NWUwMTk3ZScKICB4bWxuczp4YXBNTT0naHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21t Lyc+CiAgPHhhcE1NOkRvY3VtZW50SUQ+YWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOjVjNzE5YWU4LTE2 OWQtMTFkOC1iZjc2LTgyYTM4NWUwMTk3ZTwveGFwTU06RG9jdW1lbnRJRD4KIDwvcmRmOkRlc2Ny aXB0aW9uPgoKPC9yZGY6UkRGPgo8L3g6eGFwbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIC