Introductie tot R, RStudio en R Markdown

Met R MarkDown kan je gemakkelijk webpagina’s, documenten en slides maken die tekst, R chunks, plots en Latex vergelijkingen bevatten. Tijdens de tutorialsessies zullen we altijd R Markdown gebruiken. R Markdown vervangt scripts en is erg handig omdat je extra opmerkingen kunt toevoegen aan de hoorcolleges en tutorials.

Resultaat bekijken

Door gebruik te maken van notebooks, kan je de wijzigingen die je maakt onmiddellijk opvolgen op een interactieve manier. Klik op Preview bovenaan in je RStudio venster om de html versie van de notebook te zien.

Je zal zien dat de R-code nog niet is uitgevoerd. Hier komen we verder op terug. Op Windows is het soms zo dat de preview functie pas werkt nadat er een wijziging werd uitgevoerd aan de file en deze werd opgeslagen. Je kan bijvoorbeeld een spatie toevoegen en de file opslaan … Daarna zou de preview functie een resultaat moeten weergeven.

Opmaak

Als je iets in vet of cursief wilt benadrukken, gebruik je dubbele sterretjes voor vet en enkele sterretjes voor cursief. Als je een niet-genummerde lijst wilt toevoegen, gebruik dan een streepje:

  • Element 1
  • Element 2
  • Element 3

Je kunt titels toevoegen met behulp van het hekje #

Hoofdtitel met een enkel #

ondertitel 1 met twee ##

subsubtitle met drie ###

enz.

Integreer tekst en R-code

Eenvoudige berekeningen

Je kunt stukjes R-code integreren in je RMarkdown-bestand. Dit doe je door een omgeving te maken die begint met ```{r} en eindigt met ```.

Hieronder zullen we R-code demonstreren aan de hand van verschillende voorbeelden, zodat je vertrouwd kan geraken met de syntax.

Je kunt RStudio bijvoorbeeld gebruiken als een rekenmachine. Code uitvoeren kan je op verschillende manieren - door in een stukje code met je muis te klikken en dan via de “Run”-knop bovenaan in de console op “Run current chunck” te klikken. - Door op het groene pijltje te klikken rechts van de chunk. - Door je cursor in/naast de regel te zetten en de toetsencombinatie Ctrl+Enter (Mac: Cmd+Enter) uit te voeren.

Telkens je het document opslaat wordt dan de webpagina (html-file) geupdatet.

Laat de onderstaande code lopen. Sla op en bekijk het resultaat in je html file.

1+1
[1] 2
(5-3)+7*10/2
[1] 37
  • Je kan ook alle chunks laten lopen boven of onder de positie waarop je je bevindt via de “Run”-knop bovenaan in de console en dan “Run all Chunks below” of “Run all Chunks above” te selecteren, respectievelijk. Dat is bijvoorbeeld handig als je iets in de analyse hebt veranderd die een effect heeft op de onderstaande berekeningen.

  • Je kan ook de R sessie opnieuw starten en alle chunks volledig opnieuw laten lopen.

  • Het voordeel van een notebook is dat je bij kleine wijzigingen niet de volledige notebook opnieuw moet laten lopen, wanneer het volstaat om enkel de chunks te laten lopen die je hebt aangepast. Daarnaast is het hierdoor erg interactief. Telkens je opslaat zie je onmiddellijk de aanpassingen in de html file.

Commentaar in R-code

Je kunt ook binnen je stukjes R-code commentaar schrijven. Commentaar laat je voorafgaan door een #.

# Dit is commentaar.
# Code in commentaar wordt niet uitgevoerd.
# 1+1

Gebruik objecten om resultaten, berekeningen, enz. op te slaan.

Je kunt resultaten van functies of berekeningen opslaan in objecten die je kan bijhouden voor toekomstig gebruik. Dit doe je door middel van <- of =.

x = 2
x
[1] 2
x <- 3
x
[1] 3

De aanbevolen manier in R is om gebruik te maken van <-, aangezien = ook gebruikt wordt binnen functies. Dit zullen wij vanaf nu dan ook altijd doen.

**TIP:** Een snelle manier om <- te bekomen is de toetscombinatie “ALT” + “-”.

Je kan met deze variabelen ook berekeningen doen.

beta0 <- 1
beta1 <- 2
beta0 + beta1
[1] 3
x <- 4
y <- beta0 + beta1*x
y
[1] 9

Functies

Functies worden opgeroepen met hun functienaam onmiddellijk gevolgd door ronde haakjes (), waarin de verschillende argumenten gespecifieerd kunnen worden. In dit voorbeeld simuleren we 101 trekkingen uit een normale verdeling aan de hand van de functie rnorm

# Simuleer 101 trekkingen uit een normale verdeling met gemiddelde 0 en standaarddeviatie 1 en steek ze in object "e1".
e1 <- rnorm(101)

Eerste hulp bij RStudio: “?”.

We willen 101 trekkingen uit een normale verdeling met gemiddelde 5 en standaarddeviatie 2 trekken. Hoe wijzigen we het gemiddelde en de standaarddeviatie in de rnorm-functie? Hiervoor bestaat het handige hulpmiddel “?”.

?rnorm

Dit commando opende het helpvenster voor de rnorm-functie. We zien dat we voor het gemiddelde het argument mean en voor de standaarddeviatie het argument sd moeten aanpassen. Onze 101 trekkingen uit een normale verdeling met gemiddelde 5 en standaarddeviatie 2 berekenen we dus als volgt:

# Simuleer 101 trekkingen uit een normale verdeling met gemiddelde 5 en standaarddeviatie 2 en steek ze in object "e2".
e2 <- rnorm(101, mean = 5, sd = 2)

We willen nu graag een histogram maken van e1 en e2. Hoe vinden we de correcte functie? Het internet is onze bondgenoot. We googelen “histogram R function”. Hiermee vinden we snel dat hist de functie is de we zoeken. We maken de histogrammen.

hist(e1)

hist(e2)

Vectoren

R kan ook werken met vectoren. Die worden aangemaakt met de functie c.

x <- c(1,2,3)
y <- c(3,2,1)
x
[1] 1 2 3
# Berekeningen gebeuren voor elk element van de vector.
2*x
[1] 2 4 6
x+y
[1] 4 4 4

Vectoren kunnen slechts elementen bevatten van ????n enkele klasse.

# Een voorbeeld van de character-klasse.
x <- c("Biologie", "Biochemie", "Chemie", "Biomedische")
x
[1] "Biologie"    "Biochemie"   "Chemie"      "Biomedische"
class(x)
[1] "character"
# Een voorbeeld van de numerieke klasse.
x <- c(1,2,3)
x
[1] 1 2 3
class(x)
[1] "numeric"
x <- c(1,2,3,"Biologie")
class(x) # Alles werd omgezet naar de character-klasse.
[1] "character"

Als je het volgende uitvoert, krijg je een error, want een wiskundige operatie met een vector van het klasse character kan niet (dit is, Biologie+1 houdt geen steek).

x + 2 # Al Wiskundige opratie met string kan niet.

Subsets van vectoren

Je kan elementen van objecten selecteren met behulp van vierkante haakjes.

x[1] # Selecteer element 1
[1] "1"
x[2] # Selecteer element 2
[1] "2"
x[c(1,2)] # Selecteer element 1 en 2
[1] "1" "2"
x[1:2] # Selecteer element 1 en 2
[1] "1" "2"
x[-1] # verwijder het eerste element
[1] "2"        "3"        "Biologie"

Matrices

# Merk op bij onderstaande code dat je een commando over meerdere lijnen kan splitsen.
xMat <- matrix(c(5, 6,
                4, 3), byrow=TRUE, nrow=2, ncol=2)
xMat
     [,1] [,2]
[1,]    5    6
[2,]    4    3

Je kan de matrix overzichtelijker maken door rij- en kolomnamen toe te voegen

rownames(xMat) <- c("rij1", "rij2")
colnames(xMat) <- c("kol1", "kol2")
xMat
     kol1 kol2
rij1    5    6
rij2    4    3

Je kan ook met matrices wiskundige berekeningen doen.

xMat*2
     kol1 kol2
rij1   10   12
rij2    8    6
xMat - 2
     kol1 kol2
rij1    3    4
rij2    2    1
yMat <- matrix(c(1, 7,
                2, 3), byrow = TRUE, nrow = 2, ncol = 2)
xMat - yMat # Merk op dat rij- en kolomnamen behouden blijven.
     kol1 kol2
rij1    4   -1
rij2    2    0

Matrices kun je ook subsetten. Dit kan op verschillende manieren.

# Subsetten op index
xMat[1, ] # Volledige rij 1!
kol1 kol2 
   5    6 
xMat[ ,1] # Volledige kolom 1!
rij1 rij2 
   5    4 
xMat[2,2] # Element in 2de rij, 2de kolom
[1] 3
# Subsetten op rij- en kolomnaam
xMat["rij1", ] # Volledige rij 1!
kol1 kol2 
   5    6 
xMat[ ,"kol1"] # Volledige kolom 1!
rij1 rij2 
   5    4 
xMat["rij2","kol2"] # Element in 2de rij, 2de kolom
[1] 3

Data frames

Data frames zijn net als matrices tweedimensionale structuren, maar ze kunnen verschillende datatypes samen bevatten. Ze zijn dus ideaal om datasets in op te slaan.

# Maak een simpel data frame
# Ons voorbeeld is een data frame met het aantal bedreigde species per taxon in de VS in 2002.
EndangeredSpecies <- data.frame(
  taxon = c("Mammals", "Birds", "Reptiles", "Amphibians", "Fish", "Crustaceans", "Snails", "Insects", "Arachnids", "Clams", "Plants"),
  num.species = c(74, 92, 36, 22, 115, 21, 32, 44, 12, 70, 745)
)
EndangeredSpecies
         taxon num.species
1      Mammals          74
2        Birds          92
3     Reptiles          36
4   Amphibians          22
5         Fish         115
6  Crustaceans          21
7       Snails          32
8      Insects          44
9    Arachnids          12
10       Clams          70
11      Plants         745

Data frames kun je ook subsetten. Dit kan opnieuw op verschillende manieren.

# Subsetten op index
EndangeredSpecies[3,] # Rij 3
     taxon num.species
3 Reptiles          36
EndangeredSpecies[,2] # Kolom 2
 [1]  74  92  36  22 115  21  32  44  12  70 745
# Subsetten op naam
EndangeredSpecies[, "taxon"]
 [1] Mammals     Birds       Reptiles    Amphibians  Fish        Crustaceans Snails     
 [8] Insects     Arachnids   Clams       Plants     
11 Levels: Amphibians Arachnids Birds Clams Crustaceans Fish Insects Mammals ... Snails
# Bij data frames kan je ook gebruik maken van de "$"-operator om een kolom te selecteren
EndangeredSpecies$taxon
 [1] Mammals     Birds       Reptiles    Amphibians  Fish        Crustaceans Snails     
 [8] Insects     Arachnids   Clams       Plants     
11 Levels: Amphibians Arachnids Birds Clams Crustaceans Fish Insects Mammals ... Snails

Data importeren

Data importeren in R kan via de functie read.table. Hierbij moet je het pad naar je bestand defini??ren en een separator opgeven (bv. “\t” als het een tab-delimited file is, “,” als het een komma is, etc.). Wij zullen er altijd voor zorgen dat je een werkend bestand kunt importeren. Als je ook offline wil kunnen werken, kan je altijd het bestand downloaden en (in plaats van de hyperlink) verwijzen naar de bestandslocatie op je computer.

path <- "https://raw.githubusercontent.com/statOmics/statistiekBasisCursus/gh-pages/practica/practicum1/data/lovett.dat"
lovett <- read.table(path, header = TRUE, sep = "\t", dec = ",")
lovett
         STREAM MAXELEV SAMPELEV LENGTH AREA HEIGHT  NO3 TON   TN NH4   DOC  SO4   CL   CA
1    Santa Cruz    1006      680   1680   23      1 24.2 5.6 29.9 0.8 180.4 50.6 15.5 54.7
2       Colgate    1216      628   3912  462      1 25.4 4.9 30.3 1.4 108.8 55.4 16.4 58.4
3        Halsey    1204      625   4032  297      1 29.7 4.4 33.0 0.8 104.7 56.5 17.1 65.9
4  Batavia Hill    1213      663   3072  399      1 22.1 6.1 28.3 1.4  84.5 57.5 16.8 59.5
5  Windham Ridg    1074      616   2520  207      1 13.1 5.7 17.6 0.6  82.4 58.3 18.3 54.6
6  Silver Sprin    1113      451   3120  348      0 27.5 3.0 30.8 1.1  86.6 63.0 15.7 68.5
7  Little Timbe    1027      463   2064  179      0 28.1 4.7 32.8 1.4  91.9 66.5 26.9 84.6
8        Hunter    1234      634   4416  504      1 31.2 5.4 37.1 2.5  39.1 64.5 22.0 73.1
9     West Kill    1234      658   3600  546      1 22.6 3.1 26.0 3.1  66.6 63.4 21.3 71.1
10         Mill    1137      674   2856  279      1 35.9 4.9 39.8 1.4  59.3 58.4 29.8 91.2
11 Kelly Hollow    1061      533   3960  516      1 35.9 2.9 40.8 0.6  51.3 70.6 18.4 94.4
12       Pigeon    1173      619   4608  706      1 22.4 5.8 28.0 1.1  93.7 56.9 16.6 59.4
13      Biscuit    1125      619   5616  992      1 22.2 4.0 25.8 0.8  83.5 56.7 16.6 46.7
14         Fall    1018      530   7176 1263      1 20.5 3.9 23.3 0.8  70.1 60.4 19.4 70.0
15    Bear Hole    1171      363   6960  804      0 24.9 5.7 30.7 0.8  67.4 67.8 19.9 43.9
16 Buttermilk F    1076      405   2856  183      0 33.1 6.2 40.6 1.4 104.4 70.8 20.6 53.3
17      Rondout    1171      454   6456 1686      0 23.4 3.8 26.5 1.1  61.2 58.6 21.5 35.6
18       Kanape     939      334   4704  766      0 10.2 5.9 16.7 2.2  40.2 59.5 25.5 60.3
19 Woodland Val    1277      425   5280 1380      0 18.6 6.6 25.3 2.5  44.1 55.5 24.5 44.2
20 Broadst Holl    1180      433   4752  996      0 19.5 6.8 27.1 3.3  70.8 63.4 22.4 78.4
21        Pecoy    1161      591   2904  290      1 28.0 4.5 31.9 1.9  84.9 57.8 26.4 56.1
22     Prediger    1030      610   2688  125      1 21.5 3.9 24.9 3.1  85.1 55.1 20.5 40.8
23     Bear Pen    1076      497   2544  209      0 22.6 7.7 30.8 1.7  99.5 65.5 13.4 72.5
24       Weaver    1021      786    960   33      1 17.2 6.7 24.0 1.4  66.1 62.7 13.0 50.3
25         BWS6     754      512   2016  144      1  3.8 5.7 10.9 1.9  51.3 72.1 18.7 73.4
26      Halcott    1039      555   1584  107      1 20.9 6.2 27.6 2.2  66.8 63.4 24.6 62.0
27       Tonshi     762      293   2976  267      0  2.1 5.6  8.3 1.7  82.4 68.5 78.8 54.5
28    Grog Kill     863      271   3384  441      0  3.0 7.1 10.5 2.2  58.9 65.8 63.6 82.8
29  Hollow Tree    1137      457   3096  492      0 36.1 3.9 40.4 1.9  42.7 69.2 22.3 81.8
30   Lost Clove    1091      460   3000  413      0 22.4 5.8 28.4 2.2  45.4 66.7 18.6 70.4
31        Black    1137      683   4416  376      1 34.4 2.8 36.0 1.4  49.5 59.3 14.9 68.6
32       Styles    1186      576   3840  395      1 31.8 5.5 37.7 0.8  83.3 61.1 17.8 69.4
33      Warners    1173      418   8328 1835      0 21.6 3.6 25.3 1.4  65.4 62.1 34.4 76.8
34       Kittle     957      567   1800   63      1 32.2 4.4 36.4 2.2  66.2 70.4 24.4 82.5
35 Traver Hollo     887      311   3000  604      0 16.2 4.6 21.3 1.1  57.5 62.1 21.9 67.9
36   Willowemoc     983      607   5472  915      1 19.8 3.2 22.8 1.4  42.7 64.6 16.4 75.5
37       Myrtle    1219      475   4320  476      0 17.4 3.6 22.3 2.5  42.9 61.4 21.0 63.4
38 Becker Hollo    1231      588   2664  376      1 26.9 4.7 30.0 2.5  55.8 56.9 20.9 58.6
     MG    H
1  14.4 0.48
2  17.0 0.24
3  19.6 0.47
4  19.5 0.23
5  21.9 0.37
6  22.4 0.17
7  26.2 0.14
8  25.4 0.14
9  21.8 0.16
10 22.2 0.10
11 28.5 0.11
12 16.0 0.27
13 17.5 0.46
14 18.2 0.22
15 25.0 0.50
16 26.3 0.50
17 19.6 1.33
18 30.0 0.15
19 24.9 0.35
20 27.7 0.12
21 15.5 0.50
22 13.8 1.14
23 25.7 0.12
24 22.2 0.37
25 30.1 0.17
26 27.4 0.17
27 34.7 0.11
28 31.7 0.09
29 26.5 0.10
30 28.8 0.16
31 18.7 0.13
32 22.5 0.20
33 24.6 0.10
34 25.6 0.16
35 22.8 0.13
36 16.5 0.18
37 19.2 0.14
38 18.2 0.16

Doel van de practica en de projecten

Belangrijk: De bedoeling van de practica en de projecten die jullie zullen maken is om jullie te leren correcte statistische analyses uit te voeren en deze ook correct te rapporteren. Hierbij zullen jullie gebruik maken van RMarkdown in RStudio, wat later ook nog van pas kan komen, bv. bij het maken van jullie thesis. Het is echter NIET de bedoeling om uren te zoeken op wat er misloopt als je iets in R probeert te implementeren. Dus: als je problemen ondervindt om iets te implementeren in R, aarzel niet om ons persoonlijk of via e-mail te contacteren!

Integreer R-resultaten inline in de tekst.

We voegen het gemiddelde van 100 gesimuleerde datapunten inline toe en we zullen het afronden op twee cijfers. Hiervoor maken we gebruik van de omgeving die begint met “`r” en eindigt met “`”. Het gemiddelde van een willekeurige steekproef met 100 observaties getroken uit een standaard normaal verdeling is gelijk aan -0.1.

Toevoegen van formules door latexvergelijkingen te gebruiken

Je kunt ook vergelijkingen toevoegen met behulp van dubbele $$ - tekens, bijvoorbeeld: \[y_i = \beta_0 + \beta_1 x_i + \epsilon_i\] Je kunt ook inline-latexcode toevoegen met behulp van enkele $ - tekens. Bijvoorbeeld het steekproefgemiddelde van y: \(\bar{y}=\sum\limits_{i=1}^{n}\frac{y_i}{n}\)

LS0tCnRpdGxlOiAiSW50cm9kdWN0aWUgdG90IFIgTWFya2Rvd24gbm90ZWJvb2tzIgphdXRob3I6ICJOYW1lbiBBdXRldXJzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vawotLS0KCiMgSW50cm9kdWN0aWUgdG90IFIsIFJTdHVkaW8gZW4gUiBNYXJrZG93bgoKTWV0IFIgTWFya0Rvd24ga2FuIGplIGdlbWFra2VsaWprIHdlYnBhZ2luYSdzLCBkb2N1bWVudGVuIGVuIHNsaWRlcyBtYWtlbiBkaWUgdGVrc3QsIFIgY2h1bmtzLCBwbG90cyBlbiBMYXRleCB2ZXJnZWxpamtpbmdlbiBiZXZhdHRlbi4gVGlqZGVucyBkZSB0dXRvcmlhbHNlc3NpZXMgenVsbGVuIHdlIGFsdGlqZCBSIE1hcmtkb3duIGdlYnJ1aWtlbi4gUiBNYXJrZG93biB2ZXJ2YW5ndCBzY3JpcHRzIGVuIGlzIGVyZyBoYW5kaWcgb21kYXQgamUgZXh0cmEgb3BtZXJraW5nZW4ga3VudCB0b2V2b2VnZW4gYWFuIGRlIGhvb3Jjb2xsZWdlcyBlbiB0dXRvcmlhbHMuCgojIyBIZWFkZXIKRGUgbWFya2Rvd24gbm90ZWJvb2sgc3RhcnQgbWV0IGVlbiBoZWFkZXIuCkhldCBiZXZhdCBvbmRlcm1lZXIgZGUgdGl0ZWwsIGRlIG5hbWVuIHZhbiBkZSBhdXRldXJzIGVuIGhldCB0eXBlIFJNYXJrZG93biBmaWxlLiAKV2Ugd2Vya2VuIHR5cGlzY2ggbWV0IGludGVyYWN0aWV2ZSBodG1sX25vdGVib29rcyB0aWpkZW5zIGRlIG9udHdpa2tlbGluZyB2YW4gb256ZSBjb2RlLgoKYGBgIHlhbWwKLS0tCnRpdGxlOiAiSW50cm9kdWN0aWUgdG90IFIgTWFya2Rvd24gbm90ZWJvb2tzIgphdXRob3I6ICJOYW1lbiBBdXRldXJzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAotLS0KYGBgCgpEZXplIGhlYWRlciB3b3JkdCB2YWFrIHN0YW5kYWFyZCB2ZXJ3aWpkZXJkIGFscyBqZSBtYXJrZG93biBmaWxlcyBkb3dubG9hZCB2YW4gaGV0IHdlYi4gCktvcGllZXIgZGUgaGVhZGVyLCBzdGFydGVuZGUgbWV0IGRlIGRyaWUgbWludGVrZW5zIHRvdCBlbiBtZXQgZGUgZHJpZSBvbmRlcnN0ZSBtaW50ZWtlbnMuCgpQbGFrIGRlIGhlYWRlciBib3ZlbmFhbiBqZSBkb2N1bWVudCBlbiBzbGEgaGV0IGRvY3VtZW50IG9wLiAKSGV0IGRvY3VtZW50IGlzIG51IGdlZGVmaW5lZXJkIGFscyBlZW4gaW50ZXJhY3RpZXZlIGh0bWxfbm90ZWJvb2suCgojIyBSZXN1bHRhYXQgYmVraWprZW4KRG9vciBnZWJydWlrIHRlIG1ha2VuIHZhbiBub3RlYm9va3MsIGthbiBqZSBkZSB3aWp6aWdpbmdlbiBkaWUgamUgbWFha3Qgb25taWRkZWxsaWprIG9wdm9sZ2VuIG9wIGVlbiBpbnRlcmFjdGlldmUgbWFuaWVyLiAKS2xpayBvcCBQcmV2aWV3IGJvdmVuYWFuIGluIGplIFJTdHVkaW8gdmVuc3RlciBvbSBkZSBodG1sIHZlcnNpZSB2YW4gZGUgbm90ZWJvb2sgdGUgemllbi4gCgpKZSB6YWwgemllbiBkYXQgZGUgUi1jb2RlIG5vZyBuaWV0IGlzIHVpdGdldm9lcmQuIEhpZXIga29tZW4gd2UgdmVyZGVyIG9wIHRlcnVnLgpPcCBXaW5kb3dzIGlzIGhldCBzb21zIHpvIGRhdCBkZSBwcmV2aWV3IGZ1bmN0aWUgcGFzIHdlcmt0IG5hZGF0IGVyIGVlbiB3aWp6aWdpbmcgd2VyZCB1aXRnZXZvZXJkIGFhbiBkZSBmaWxlIGVuIGRlemUgd2VyZCBvcGdlc2xhZ2VuLiAKSmUga2FuIGJpanZvb3JiZWVsZCBlZW4gc3BhdGllIHRvZXZvZWdlbiBlbiBkZSBmaWxlIG9wc2xhYW4gLi4uCkRhYXJuYSB6b3UgZGUgcHJldmlldyBmdW5jdGllIGVlbiByZXN1bHRhYXQgbW9ldGVuIHdlZXJnZXZlbi4KCiMjIE9wbWFhawoKQWxzIGplIGlldHMgaW4gdmV0IG9mIGN1cnNpZWYgd2lsdCBiZW5hZHJ1a2tlbiwgZ2VicnVpayBqZSBkdWJiZWxlIHN0ZXJyZXRqZXMgdm9vciAqKnZldCoqIGVuIGVua2VsZSBzdGVycmV0amVzIHZvb3IgKmN1cnNpZWYqLiBBbHMgamUgZWVuIG5pZXQtZ2VudW1tZXJkZSBsaWpzdCB3aWx0IHRvZXZvZWdlbiwgZ2VicnVpayBkYW4gZWVuIHN0cmVlcGplOgoKLSBFbGVtZW50IDEKLSBFbGVtZW50IDIKLSBFbGVtZW50IDMKCkplIGt1bnQgdGl0ZWxzIHRvZXZvZWdlbiBtZXQgYmVodWxwIHZhbiBoZXQgaGVramUgXCMKCiMgSG9vZmR0aXRlbCBtZXQgZWVuIGVua2VsIFwjCgojIyBvbmRlcnRpdGVsIDEgbWV0IHR3ZWUgXCNcIwoKIyMjIHN1YnN1YnRpdGxlIG1ldCBkcmllIFwjXCNcIwoKIyMjIyBlbnouCgojIEludGVncmVlciB0ZWtzdCBlbiBSLWNvZGUKCiMjIEVlbnZvdWRpZ2UgYmVyZWtlbmluZ2VuCgpKZSBrdW50IHN0dWtqZXMgUi1jb2RlIGludGVncmVyZW4gaW4gamUgUk1hcmtkb3duLWJlc3RhbmQuIERpdCBkb2UgamUgZG9vciBlZW4gb21nZXZpbmcgdGUgbWFrZW4gZGllIGJlZ2ludCBtZXQgXGBcYFxge3J9IGVuIGVpbmRpZ3QgbWV0IFxgXGBcYC4gCgpIaWVyb25kZXIgenVsbGVuIHdlIFItY29kZSBkZW1vbnN0cmVyZW4gYWFuIGRlIGhhbmQgdmFuIHZlcnNjaGlsbGVuZGUgdm9vcmJlZWxkZW4sIHpvZGF0IGplIHZlcnRyb3V3ZCBrYW4gZ2VyYWtlbiBtZXQgZGUgc3ludGF4LgoKSmUga3VudCBSU3R1ZGlvIGJpanZvb3JiZWVsZCBnZWJydWlrZW4gYWxzIGVlbiByZWtlbm1hY2hpbmUuIENvZGUgdWl0dm9lcmVuIGthbiBqZSBvcCB2ZXJzY2hpbGxlbmRlIG1hbmllcmVuCiAtIGRvb3IgaW4gZWVuIHN0dWtqZSBjb2RlIG1ldCBqZSBtdWlzIHRlIGtsaWtrZW4gZW4gZGFuIHZpYSBkZSAiUnVuIi1rbm9wIGJvdmVuYWFuIGluIGRlIGNvbnNvbGUgb3AgIlJ1biBjdXJyZW50IGNodW5jayIgdGUga2xpa2tlbi4KIC0gRG9vciBvcCBoZXQgZ3JvZW5lIHBpamx0amUgdGUga2xpa2tlbiByZWNodHMgdmFuIGRlIGNodW5rLiAKIC0gRG9vciBqZSBjdXJzb3IgaW4vbmFhc3QgZGUgcmVnZWwgdGUgemV0dGVuIGVuIGRlIHRvZXRzZW5jb21iaW5hdGllIEN0cmwrRW50ZXIgKE1hYzogQ21kK0VudGVyKSB1aXQgdGUgdm9lcmVuLgoKVGVsa2VucyBqZSBoZXQgZG9jdW1lbnQgb3BzbGFhdCB3b3JkdCBkYW4gZGUgd2VicGFnaW5hIChodG1sLWZpbGUpIGdldXBkYXRldC4KCkxhYXQgZGUgb25kZXJzdGFhbmRlIGNvZGUgbG9wZW4uIFNsYSBvcCBlbiBiZWtpamsgaGV0IHJlc3VsdGFhdCBpbiBqZSBodG1sIGZpbGUuCgpgYGB7cn0KMSsxCig1LTMpKzcqMTAvMgpgYGAKCi0gSmUga2FuIG9vayBhbGxlIGNodW5rcyBsYXRlbiBsb3BlbiBib3ZlbiBvZiBvbmRlciBkZSBwb3NpdGllIHdhYXJvcCBqZSBqZSBiZXZpbmR0IHZpYSBkZSAiUnVuIi1rbm9wIGJvdmVuYWFuIGluIGRlIGNvbnNvbGUgZW4gZGFuICJSdW4gYWxsIENodW5rcyBiZWxvdyIgb2YgIlJ1biBhbGwgQ2h1bmtzIGFib3ZlIiB0ZSBzZWxlY3RlcmVuLCByZXNwZWN0aWV2ZWxpamsuIERhdCBpcyBiaWp2b29yYmVlbGQgaGFuZGlnIGFscyBqZSBpZXRzIGluIGRlIGFuYWx5c2UgaGVidCB2ZXJhbmRlcmQgZGllIGVlbiBlZmZlY3QgaGVlZnQgb3AgZGUgb25kZXJzdGFhbmRlIGJlcmVrZW5pbmdlbi4KCi0gSmUga2FuIG9vayBkZSBSIHNlc3NpZSBvcG5pZXV3IHN0YXJ0ZW4gZW4gYWxsZSBjaHVua3Mgdm9sbGVkaWcgb3BuaWV1dyBsYXRlbiBsb3Blbi4gCgotIEhldCB2b29yZGVlbCB2YW4gZWVuIG5vdGVib29rIGlzIGRhdCBqZSBiaWoga2xlaW5lIHdpanppZ2luZ2VuIG5pZXQgZGUgdm9sbGVkaWdlIG5vdGVib29rIG9wbmlldXcgbW9ldCBsYXRlbiBsb3Blbiwgd2FubmVlciBoZXQgdm9sc3RhYXQgb20gZW5rZWwgZGUgY2h1bmtzIHRlIGxhdGVuIGxvcGVuIGRpZSBqZSBoZWJ0IGFhbmdlcGFzdC4gRGFhcm5hYXN0IGlzIGhldCBoaWVyZG9vciBlcmcgaW50ZXJhY3RpZWYuIFRlbGtlbnMgamUgb3BzbGFhdCB6aWUgamUgb25taWRkZWxsaWprIGRlIGFhbnBhc3NpbmdlbiBpbiBkZSBodG1sIGZpbGUuCgojIyMgQ29tbWVudGFhciBpbiBSLWNvZGUgCgpKZSBrdW50IG9vayBiaW5uZW4gamUgc3R1a2plcyBSLWNvZGUgY29tbWVudGFhciBzY2hyaWp2ZW4uIENvbW1lbnRhYXIgbGFhdCBqZSB2b29yYWZnYWFuIGRvb3IgZWVuIFwjLgoKYGBge3J9CiMgRGl0IGlzIGNvbW1lbnRhYXIuCiMgQ29kZSBpbiBjb21tZW50YWFyIHdvcmR0IG5pZXQgdWl0Z2V2b2VyZC4KIyAxKzEKYGBgCgojIyBHZWJydWlrIG9iamVjdGVuIG9tIHJlc3VsdGF0ZW4sIGJlcmVrZW5pbmdlbiwgZW56LiBvcCB0ZSBzbGFhbi4KCkplIGt1bnQgcmVzdWx0YXRlbiB2YW4gZnVuY3RpZXMgb2YgYmVyZWtlbmluZ2VuIG9wc2xhYW4gaW4gb2JqZWN0ZW4gZGllIGplIGthbiBiaWpob3VkZW4gdm9vciB0b2Vrb21zdGlnIGdlYnJ1aWsuIERpdCBkb2UgamUgZG9vciBtaWRkZWwgdmFuIGA8LWAgb2YgYD1gLiAKCmBgYHtyfQp4ID0gMgp4CnggPC0gMwp4CmBgYAoKRGUgYWFuYmV2b2xlbiBtYW5pZXIgaW4gUiBpcyBvbSBnZWJydWlrIHRlIG1ha2VuIHZhbiBgPC1gLCBhYW5nZXppZW4gYD1gIG9vayBnZWJydWlrdCB3b3JkdCBiaW5uZW4gZnVuY3RpZXMuIERpdCB6dWxsZW4gd2lqIHZhbmFmIG51IGRhbiBvb2sgYWx0aWpkIGRvZW4uCgoqKlRJUDoqKiBFZW4gc25lbGxlIG1hbmllciBvbSBgPC1gIHRlIGJla29tZW4gaXMgZGUgdG9ldHNjb21iaW5hdGllICJBTFQiICsgIi0iLgoKSmUga2FuIG1ldCBkZXplIHZhcmlhYmVsZW4gb29rIGJlcmVrZW5pbmdlbiBkb2VuLgoKYGBge3J9CmJldGEwIDwtIDEKYmV0YTEgPC0gMgpiZXRhMCArIGJldGExCgp4IDwtIDQKeSA8LSBiZXRhMCArIGJldGExKngKeQpgYGAKCiMjIEZ1bmN0aWVzCgpGdW5jdGllcyB3b3JkZW4gb3BnZXJvZXBlbiBtZXQgaHVuIGZ1bmN0aWVuYWFtIG9ubWlkZGVsbGlqayBnZXZvbGdkIGRvb3Igcm9uZGUgaGFha2plcyAoKSwgd2FhcmluIGRlIHZlcnNjaGlsbGVuZGUgYXJndW1lbnRlbiBnZXNwZWNpZmllZXJkIGt1bm5lbiB3b3JkZW4uCkluIGRpdCB2b29yYmVlbGQgc2ltdWxlcmVuIHdlIDEwMSB0cmVra2luZ2VuIHVpdCBlZW4gbm9ybWFsZSB2ZXJkZWxpbmcgYWFuIGRlIGhhbmQgdmFuIGRlIGZ1bmN0aWUgYHJub3JtYAoKYGBge3J9CiMgU2ltdWxlZXIgMTAxIHRyZWtraW5nZW4gdWl0IGVlbiBub3JtYWxlIHZlcmRlbGluZyBtZXQgZ2VtaWRkZWxkZSAwIGVuIHN0YW5kYWFyZGRldmlhdGllIDEgZW4gc3RlZWsgemUgaW4gb2JqZWN0ICJlMSIuCmUxIDwtIHJub3JtKDEwMSkKYGBgCgojIyBFZXJzdGUgaHVscCBiaWogUlN0dWRpbzogIj8iLgoKV2Ugd2lsbGVuIDEwMSB0cmVra2luZ2VuIHVpdCBlZW4gbm9ybWFsZSB2ZXJkZWxpbmcgbWV0IGdlbWlkZGVsZGUgNSBlbiBzdGFuZGFhcmRkZXZpYXRpZSAyIHRyZWtrZW4uIEhvZSB3aWp6aWdlbiB3ZSBoZXQgZ2VtaWRkZWxkZSBlbiBkZSBzdGFuZGFhcmRkZXZpYXRpZSBpbiBkZSBgcm5vcm1gLWZ1bmN0aWU/CkhpZXJ2b29yIGJlc3RhYXQgaGV0IGhhbmRpZ2UgaHVscG1pZGRlbCAiPyIuCgpgYGB7cn0KP3Jub3JtCmBgYAoKRGl0IGNvbW1hbmRvIG9wZW5kZSBoZXQgaGVscHZlbnN0ZXIgdm9vciBkZSBgcm5vcm1gLWZ1bmN0aWUuIFdlIHppZW4gZGF0IHdlIHZvb3IgaGV0IGdlbWlkZGVsZGUgaGV0IGFyZ3VtZW50IGBtZWFuYCBlbiB2b29yIGRlIHN0YW5kYWFyZGRldmlhdGllIGhldCBhcmd1bWVudCBgc2RgIG1vZXRlbiBhYW5wYXNzZW4uIE9uemUgMTAxIHRyZWtraW5nZW4gdWl0IGVlbiBub3JtYWxlIHZlcmRlbGluZyBtZXQgZ2VtaWRkZWxkZSA1IGVuIHN0YW5kYWFyZGRldmlhdGllIDIgYmVyZWtlbmVuIHdlIGR1cyBhbHMgdm9sZ3Q6CgpgYGB7cn0KIyBTaW11bGVlciAxMDEgdHJla2tpbmdlbiB1aXQgZWVuIG5vcm1hbGUgdmVyZGVsaW5nIG1ldCBnZW1pZGRlbGRlIDUgZW4gc3RhbmRhYXJkZGV2aWF0aWUgMiBlbiBzdGVlayB6ZSBpbiBvYmplY3QgImUyIi4KZTIgPC0gcm5vcm0oMTAxLCBtZWFuID0gNSwgc2QgPSAyKQpgYGAKCldlIHdpbGxlbiBudSBncmFhZyBlZW4gaGlzdG9ncmFtIG1ha2VuIHZhbiBgZTFgIGVuIGBlMmAuICoqSG9lIHZpbmRlbiB3ZSBkZSBjb3JyZWN0ZSBmdW5jdGllPyBIZXQgaW50ZXJuZXQgaXMgb256ZSBib25kZ2Vub290LioqIFdlIGdvb2dlbGVuICJoaXN0b2dyYW0gUiBmdW5jdGlvbiIuIEhpZXJtZWUgdmluZGVuIHdlIHNuZWwgZGF0IGBoaXN0YCBkZSBmdW5jdGllIGlzIGRlIHdlIHpvZWtlbi4gV2UgbWFrZW4gZGUgaGlzdG9ncmFtbWVuLgoKYGBge3J9Cmhpc3QoZTEpCmhpc3QoZTIpCmBgYAoKIyMgVmVjdG9yZW4KClIga2FuIG9vayB3ZXJrZW4gbWV0IHZlY3RvcmVuLiBEaWUgd29yZGVuIGFhbmdlbWFha3QgbWV0IGRlIGZ1bmN0aWUgYGNgLgoKYGBge3J9CnggPC0gYygxLDIsMykKeSA8LSBjKDMsMiwxKQp4CgojIEJlcmVrZW5pbmdlbiBnZWJldXJlbiB2b29yIGVsayBlbGVtZW50IHZhbiBkZSB2ZWN0b3IuCjIqeAp4K3kKYGBgCgpWZWN0b3JlbiBrdW5uZW4gc2xlY2h0cyBlbGVtZW50ZW4gYmV2YXR0ZW4gdmFuID8/Pz9uIGVua2VsZSBrbGFzc2UuCgpgYGB7cn0KIyBFZW4gdm9vcmJlZWxkIHZhbiBkZSBjaGFyYWN0ZXIta2xhc3NlLgp4IDwtIGMoIkJpb2xvZ2llIiwgIkJpb2NoZW1pZSIsICJDaGVtaWUiLCAiQmlvbWVkaXNjaGUiKQp4CmNsYXNzKHgpCmBgYAoKYGBge3J9CiMgRWVuIHZvb3JiZWVsZCB2YW4gZGUgbnVtZXJpZWtlIGtsYXNzZS4KeCA8LSBjKDEsMiwzKQp4CmNsYXNzKHgpCmBgYAoKYGBge3J9CnggPC0gYygxLDIsMywiQmlvbG9naWUiKQpjbGFzcyh4KSAjIEFsbGVzIHdlcmQgb21nZXpldCBuYWFyIGRlIGNoYXJhY3Rlci1rbGFzc2UuCmBgYAoKQWxzIGplIGhldCB2b2xnZW5kZSB1aXR2b2VydCwga3JpamcgamUgZWVuIGVycm9yLCB3YW50IGVlbiB3aXNrdW5kaWdlIG9wZXJhdGllIG1ldCBlZW4gdmVjdG9yIHZhbiBoZXQga2xhc3NlIGNoYXJhY3RlciBrYW4gbmlldCAoZGl0IGlzLCBCaW9sb2dpZSsxIGhvdWR0IGdlZW4gc3RlZWspLgoKYGBge3IgZXZhbCA9IEZBTFNFfQp4ICsgMiAjIEFsIFdpc2t1bmRpZ2Ugb3ByYXRpZSBtZXQgc3RyaW5nIGthbiBuaWV0LgpgYGAKCiMjIFN1YnNldHMgdmFuIHZlY3RvcmVuCgpKZSBrYW4gZWxlbWVudGVuIHZhbiBvYmplY3RlbiBzZWxlY3RlcmVuIG1ldCBiZWh1bHAgdmFuIHZpZXJrYW50ZSBoYWFramVzLgoKYGBge3J9CnhbMV0gIyBTZWxlY3RlZXIgZWxlbWVudCAxCnhbMl0gIyBTZWxlY3RlZXIgZWxlbWVudCAyCnhbYygxLDIpXSAjIFNlbGVjdGVlciBlbGVtZW50IDEgZW4gMgp4WzE6Ml0gIyBTZWxlY3RlZXIgZWxlbWVudCAxIGVuIDIKeFstMV0gIyB2ZXJ3aWpkZXIgaGV0IGVlcnN0ZSBlbGVtZW50CmBgYAoKIyMgTWF0cmljZXMKCmBgYHtyfQojIE1lcmsgb3AgYmlqIG9uZGVyc3RhYW5kZSBjb2RlIGRhdCBqZSBlZW4gY29tbWFuZG8gb3ZlciBtZWVyZGVyZSBsaWpuZW4ga2FuIHNwbGl0c2VuLgp4TWF0IDwtIG1hdHJpeChjKDUsIDYsCiAgICAgICAgICAgICAgICA0LCAzKSwgYnlyb3c9VFJVRSwgbnJvdz0yLCBuY29sPTIpCnhNYXQKYGBgCgojIEplIGthbiBkZSBtYXRyaXggb3ZlcnppY2h0ZWxpamtlciBtYWtlbiBkb29yIHJpai0gZW4ga29sb21uYW1lbiB0b2UgdGUgdm9lZ2VuCgpgYGB7cn0Kcm93bmFtZXMoeE1hdCkgPC0gYygicmlqMSIsICJyaWoyIikKY29sbmFtZXMoeE1hdCkgPC0gYygia29sMSIsICJrb2wyIikKeE1hdApgYGAKCiMgSmUga2FuIG9vayBtZXQgbWF0cmljZXMgd2lza3VuZGlnZSBiZXJla2VuaW5nZW4gZG9lbi4KCmBgYHtyfQp4TWF0KjIKeE1hdCAtIDIKeU1hdCA8LSBtYXRyaXgoYygxLCA3LAogICAgICAgICAgICAgICAgMiwgMyksIGJ5cm93ID0gVFJVRSwgbnJvdyA9IDIsIG5jb2wgPSAyKQoKeE1hdCAtIHlNYXQgIyBNZXJrIG9wIGRhdCByaWotIGVuIGtvbG9tbmFtZW4gYmVob3VkZW4gYmxpanZlbi4KYGBgCgpNYXRyaWNlcyBrdW4gamUgb29rIHN1YnNldHRlbi4gRGl0IGthbiBvcCB2ZXJzY2hpbGxlbmRlIG1hbmllcmVuLgoKYGBge3J9CiMgU3Vic2V0dGVuIG9wIGluZGV4CnhNYXRbMSwgXSAjIFZvbGxlZGlnZSByaWogMSEKeE1hdFsgLDFdICMgVm9sbGVkaWdlIGtvbG9tIDEhCnhNYXRbMiwyXSAjIEVsZW1lbnQgaW4gMmRlIHJpaiwgMmRlIGtvbG9tCgojIFN1YnNldHRlbiBvcCByaWotIGVuIGtvbG9tbmFhbQp4TWF0WyJyaWoxIiwgXSAjIFZvbGxlZGlnZSByaWogMSEKeE1hdFsgLCJrb2wxIl0gIyBWb2xsZWRpZ2Uga29sb20gMSEKeE1hdFsicmlqMiIsImtvbDIiXSAjIEVsZW1lbnQgaW4gMmRlIHJpaiwgMmRlIGtvbG9tCmBgYAoKIyMgRGF0YSBmcmFtZXMKCkRhdGEgZnJhbWVzIHppam4gbmV0IGFscyBtYXRyaWNlcyB0d2VlZGltZW5zaW9uYWxlIHN0cnVjdHVyZW4sIG1hYXIgemUga3VubmVuIHZlcnNjaGlsbGVuZGUgZGF0YXR5cGVzIHNhbWVuIGJldmF0dGVuLiBaZSB6aWpuIGR1cyBpZGVhYWwgb20gZGF0YXNldHMgaW4gb3AgdGUgc2xhYW4uCgpgYGB7cn0KIyBNYWFrIGVlbiBzaW1wZWwgZGF0YSBmcmFtZQojIE9ucyB2b29yYmVlbGQgaXMgZWVuIGRhdGEgZnJhbWUgbWV0IGhldCBhYW50YWwgYmVkcmVpZ2RlIHNwZWNpZXMgcGVyIHRheG9uIGluIGRlIFZTIGluIDIwMDIuCkVuZGFuZ2VyZWRTcGVjaWVzIDwtIGRhdGEuZnJhbWUoCiAgdGF4b24gPSBjKCJNYW1tYWxzIiwgIkJpcmRzIiwgIlJlcHRpbGVzIiwgIkFtcGhpYmlhbnMiLCAiRmlzaCIsICJDcnVzdGFjZWFucyIsICJTbmFpbHMiLCAiSW5zZWN0cyIsICJBcmFjaG5pZHMiLCAiQ2xhbXMiLCAiUGxhbnRzIiksCiAgbnVtLnNwZWNpZXMgPSBjKDc0LCA5MiwgMzYsIDIyLCAxMTUsIDIxLCAzMiwgNDQsIDEyLCA3MCwgNzQ1KQopCkVuZGFuZ2VyZWRTcGVjaWVzCmBgYAoKRGF0YSBmcmFtZXMga3VuIGplIG9vayBzdWJzZXR0ZW4uIERpdCBrYW4gb3BuaWV1dyBvcCB2ZXJzY2hpbGxlbmRlIG1hbmllcmVuLgoKYGBge3J9CiMgU3Vic2V0dGVuIG9wIGluZGV4CkVuZGFuZ2VyZWRTcGVjaWVzWzMsXSAjIFJpaiAzCkVuZGFuZ2VyZWRTcGVjaWVzWywyXSAjIEtvbG9tIDIKCiMgU3Vic2V0dGVuIG9wIG5hYW0KRW5kYW5nZXJlZFNwZWNpZXNbLCAidGF4b24iXQoKIyBCaWogZGF0YSBmcmFtZXMga2FuIGplIG9vayBnZWJydWlrIG1ha2VuIHZhbiBkZSAiJCItb3BlcmF0b3Igb20gZWVuIGtvbG9tIHRlIHNlbGVjdGVyZW4KRW5kYW5nZXJlZFNwZWNpZXMkdGF4b24KYGBgCgojIyBEYXRhIGltcG9ydGVyZW4KCkRhdGEgaW1wb3J0ZXJlbiBpbiBSIGthbiB2aWEgZGUgZnVuY3RpZSBgcmVhZC50YWJsZWAuIEhpZXJiaWogbW9ldCBqZSBoZXQgcGFkIG5hYXIgamUgYmVzdGFuZCBkZWZpbmk/P3JlbiBlbiBlZW4gc2VwYXJhdG9yIG9wZ2V2ZW4gKGJ2LiAiXFx0IiBhbHMgaGV0IGVlbiB0YWItZGVsaW1pdGVkIGZpbGUgaXMsICIsIiBhbHMgaGV0IGVlbiBrb21tYSBpcywgZXRjLikuIFdpaiB6dWxsZW4gZXIgYWx0aWpkIHZvb3Igem9yZ2VuIGRhdCBqZSBlZW4gd2Vya2VuZCBiZXN0YW5kIGt1bnQgaW1wb3J0ZXJlbi4gQWxzIGplIG9vayBvZmZsaW5lIHdpbCBrdW5uZW4gd2Vya2VuLCBrYW4gamUgYWx0aWpkIGhldCBiZXN0YW5kIGRvd25sb2FkZW4gZW4gKGluIHBsYWF0cyB2YW4gZGUgaHlwZXJsaW5rKSB2ZXJ3aWp6ZW4gbmFhciBkZSBiZXN0YW5kc2xvY2F0aWUgb3AgamUgY29tcHV0ZXIuCgpgYGB7cn0KcGF0aCA8LSAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3N0YXRPbWljcy9zdGF0aXN0aWVrQmFzaXNDdXJzdXMvZ2gtcGFnZXMvcHJhY3RpY2EvcHJhY3RpY3VtMS9kYXRhL2xvdmV0dC5kYXQiCgpsb3ZldHQgPC0gcmVhZC50YWJsZShwYXRoLCBoZWFkZXIgPSBUUlVFLCBzZXAgPSAiXHQiLCBkZWMgPSAiLCIpCmxvdmV0dApgYGAKCiMjIERvZWwgdmFuIGRlIHByYWN0aWNhIGVuIGRlIHByb2plY3RlbgoKKipCZWxhbmdyaWprOiBEZSBiZWRvZWxpbmcgdmFuIGRlIHByYWN0aWNhIGVuIGRlIHByb2plY3RlbiBkaWUganVsbGllIHp1bGxlbiBtYWtlbiBpcyBvbSBqdWxsaWUgdGUgbGVyZW4gY29ycmVjdGUgc3RhdGlzdGlzY2hlIGFuYWx5c2VzIHVpdCB0ZSB2b2VyZW4gZW4gZGV6ZSBvb2sgY29ycmVjdCB0ZSByYXBwb3J0ZXJlbi4gSGllcmJpaiB6dWxsZW4ganVsbGllIGdlYnJ1aWsgbWFrZW4gdmFuIFJNYXJrZG93biBpbiBSU3R1ZGlvLCB3YXQgbGF0ZXIgb29rIG5vZyB2YW4gcGFzIGthbiBrb21lbiwgYnYuIGJpaiBoZXQgbWFrZW4gdmFuIGp1bGxpZSB0aGVzaXMuIEhldCBpcyBlY2h0ZXIgTklFVCBkZSBiZWRvZWxpbmcgb20gdXJlbiB0ZSB6b2VrZW4gb3Agd2F0IGVyIG1pc2xvb3B0IGFscyBqZSBpZXRzIGluIFIgcHJvYmVlcnQgdGUgaW1wbGVtZW50ZXJlbi4gRHVzOiBhbHMgamUgcHJvYmxlbWVuIG9uZGVydmluZHQgb20gaWV0cyB0ZSBpbXBsZW1lbnRlcmVuIGluIFIsIGFhcnplbCBuaWV0IG9tIG9ucyBwZXJzb29ubGlqayBvZiB2aWEgZS1tYWlsIHRlIGNvbnRhY3RlcmVuISoqCgojIyBJbnRlZ3JlZXIgUi1yZXN1bHRhdGVuIGlubGluZSBpbiBkZSB0ZWtzdC4KCldlIHZvZWdlbiBoZXQgZ2VtaWRkZWxkZSB2YW4gMTAwIGdlc2ltdWxlZXJkZSBkYXRhcHVudGVuIGlubGluZSB0b2UgZW4gd2UgenVsbGVuIGhldCBhZnJvbmRlbiBvcCB0d2VlIGNpamZlcnMuIEhpZXJ2b29yIG1ha2VuIHdlIGdlYnJ1aWsgdmFuIGRlIG9tZ2V2aW5nIGRpZSBiZWdpbnQgbWV0ICJcYHIiIGVuIGVpbmRpZ3QgbWV0ICJcYCIuIEhldCBnZW1pZGRlbGRlIHZhbiBlZW4gd2lsbGVrZXVyaWdlIHN0ZWVrcHJvZWYgbWV0IDEwMCBvYnNlcnZhdGllcyBnZXRyb2tlbiB1aXQgZWVuIHN0YW5kYWFyZCBub3JtYWFsIHZlcmRlbGluZyBpcyBnZWxpamsgYWFuIGByIHJvdW5kKG1lYW4ocm5vcm0oMTAwKSksIDIpYC4KCiMjIFRvZXZvZWdlbiB2YW4gZm9ybXVsZXMgZG9vciBsYXRleHZlcmdlbGlqa2luZ2VuIHRlIGdlYnJ1aWtlbgoKSmUga3VudCBvb2sgdmVyZ2VsaWpraW5nZW4gdG9ldm9lZ2VuIG1ldCBiZWh1bHAgdmFuIGR1YmJlbGUgXCRcJCAtIHRla2VucywgYmlqdm9vcmJlZWxkOgokJHlfaSA9IFxiZXRhXzAgKyBcYmV0YV8xIHhfaSArIFxlcHNpbG9uX2kkJApKZSBrdW50IG9vayBpbmxpbmUtbGF0ZXhjb2RlIHRvZXZvZWdlbiBtZXQgYmVodWxwIHZhbiBlbmtlbGUgXCQgLSB0ZWtlbnMuIEJpanZvb3JiZWVsZCBoZXQgc3RlZWtwcm9lZmdlbWlkZGVsZGUgdmFuIHk6CiRcYmFye3l9PVxzdW1cbGltaXRzX3tpPTF9XntufVxmcmFje3lfaX17bn0kCg==