1 Introduction

1.1 Population

  • Het doel van een wetenschappelijk onderzoek is om conclusies te trekken over de algemene populatie

  • Hier bestuderen we de invloed van Captopril op de bloeddruk van patiënten met hyptertensie.

  • We zullen data verzamelen en deze dan modelleren

  • We moeten de onderzoeksvraag altijd vertalen naar de modelparameters of een combinatie van modelparameters.

  • bv. het populatie gemiddelde \[E(X)=\mu\]

  • Vermindert de gemiddelde bloeddruk bij patiënten met hypertensie na toedienen van Captopril?


1.2 Overzicht

  • Experimenteel Design & Data Exploratie
  • Puntschatters (Schatting)
  • Interval schatters (Statistische inferentie)
  • Hypothese testen (Statistische inferentie)

2 Captopril voorbeeld

2.1 Experimental design

  • 15 patiënten werden at random getrokken uit de populatie van patiënten met hypertensie
  • pre-test/post-test design: de systolische en diastolysche bloeddruk worden gemeten voor en na toedienen van Captopril.
  • Voordeel: We kunnen het effect van de Captopril toediening op de bloeddruk van de individuele patiënten beoordelen.
  • Nadeel?


2.2 Data Exploratie en Beschrijvende Statistiek

captopril <- read_csv("https://raw.githubusercontent.com/statOmics/sbc20/master/data/captopril.txt")
head(captopril)
# A tibble: 6 x 5
     id  SBPb  DBPb  SBPa  DBPa
  <dbl> <dbl> <dbl> <dbl> <dbl>
1     1   210   130   201   125
2     2   169   122   165   121
3     3   187   124   166   121
4     4   160   104   157   106
5     5   167   112   147   101
6     6   176   101   145    85
summary(captopril)
       id            SBPb            DBPb            SBPa    
 Min.   : 1.0   Min.   :146.0   Min.   : 98.0   Min.   :129  
 1st Qu.: 4.5   1st Qu.:163.5   1st Qu.:103.0   1st Qu.:146  
 Median : 8.0   Median :174.0   Median :112.0   Median :157  
 Mean   : 8.0   Mean   :176.9   Mean   :112.3   Mean   :158  
 3rd Qu.:11.5   3rd Qu.:192.5   3rd Qu.:121.5   3rd Qu.:168  
 Max.   :15.0   Max.   :210.0   Max.   :130.0   Max.   :201  
      DBPa      
 Min.   : 82.0  
 1st Qu.: 98.0  
 Median :103.0  
 Mean   :103.1  
 3rd Qu.:108.0  
 Max.   :125.0  
captoprilTidy <-
  captopril %>%
  gather(type,bp,-id)

captoSum <- captoprilTidy %>%
  group_by(type) %>%
  summarize(
    mean = mean(bp,na.rm=TRUE),
    sd = sd(bp,na.rm=TRUE),
    n = bp %>%
      is.na %>%
      `!` %>%
      sum) %>%
  mutate(se = sd/sqrt(n))

captoSum
# A tibble: 4 x 5
  type   mean    sd     n    se
  <chr> <dbl> <dbl> <int> <dbl>
1 DBPa   103.  12.6    15  3.24
2 DBPb   112.  10.5    15  2.70
3 SBPa   158   20.0    15  5.16
4 SBPb   177.  20.6    15  5.31
captoSum %>%
  ggplot(aes(x=type,y=mean)) +
  geom_bar(stat="identity") +
  geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd),width=.2) +
  ylim(0,210) +
  ylab("blood pressure (mmHg)")

  • Deze figuur is niet informatief! Het toont de ruwe data niet enkel gemiddelden en de standaard deviatie voor een bloeddruk karakteristiek.
captoprilTidy %>%
  ggplot(aes(x=type,y=bp)) +
  geom_boxplot(outlier.shape=NA) +
  geom_point(position="jitter") +
  ylim(0,210)

We zien dat veel van de ruimte die werd ingenomen door de barplot geen gegevens bevat!

captoprilTidy %>%
  ggplot(aes(x=type,y=bp)) +
  geom_boxplot(outlier.shape=NA) +
  geom_point(position="jitter")

  • Deze plot zou informatief zijn geweest als de gegevens over verschillende individuen waren verzameld.

  • De bloeddruk wordt echter bij dezelfde patiënt gemeten!

  • We zullen een plot maken waar we de systolische bloeddruk filteren

captoprilTidy %>%
  filter(type%in%c("SBPa","SBPb")) %>%
  mutate(type=factor(type,levels=c("SBPb","SBPa"))) %>%
  ggplot(aes(x=type,y=bp)) +
  geom_line(aes(group = id)) +
  geom_point()

  • We hebben gepaarde data. We kunnen het effect van de behandeling dus onmiddellijk inschatten door de bloeddruk na behandeling te vergelijken met de bloeddruk vóór de behandeling.
captopril <-
  captopril %>%
  mutate(deltaSBP = SBPa - SBPb)

captopril %>%
  ggplot(aes(x="Systolic blood pressure",y=deltaSBP)) +
  geom_boxplot(outlier.shape=NA) +
  geom_point(position="jitter")+
  ylab("Difference (mm mercury)") +
  xlab("")

captopril %>%
  summarize(
    mean = mean(deltaSBP,na.rm=TRUE),
    sd = sd(deltaSBP,na.rm=TRUE),
    n = deltaSBP %>%
      is.na %>%
      `!` %>%
      sum) %>%
  mutate(se = sd/sqrt(n))
# A tibble: 1 x 4
   mean    sd     n    se
  <dbl> <dbl> <int> <dbl>
1 -18.9  9.03    15  2.33
  • Pre-test/post-test design: Effect van Captopril in de steekproef met \(X=\Delta_\text{na-voor}\)!

  • Hoe modelleren we \(X=\Delta_\text{na-voor}\) en schatten we het effect van Captopril?

captopril %>%
  ggplot(aes(sample=deltaSBP)) +
  stat_qq() +
  stat_qq_line()

2.3 De systolische bloeddruk verschillen zijn ongeveer normaal verdeeld.

2.4 Schatten

  • Geen susbtantiële afwijkingen van normaliteit.

  • We kunnen aannemen dat de verschillen \(X \sim N(\mu, \sigma^2)\).

  • Het effect van Captopril in de populatie wordt weergegeven door het gemiddelde bloeddruk verschil \(\mu\).

  • De gemiddelde bloeddruk \(\mu\) in de populatie kan worden geschat met behulp van het steekproefgemiddelde \(\bar x\) = -18.93

  • De standaarddeviatie \(\sigma\) met de steekproefstandaarddeviatie \(\text{S}\) = 9.03.

  • Is het effect dat we in de steekproef observeren groot genoeg om te concluderen dat er een effect is van de captoprilbehandeling op de bloeddruk op populatieniveau?

  • Onze schattingen zullen van steekproef tot steekproef veranderen!

  • Hoe zijn de schatters \(\bar X\) en \(S\) verdeeld?

3 Punt schatters: het steekproefgemiddelde

  • Stel dat \(X\) een willekeurige steekproef is uit de populatie en neem aan dat \(X \sim N(\mu,\sigma^2)\)

  • Schat \(\mu\) op basis van de steekproef \(X_1,...,X_n\), gebruik makende van het steekproefgemiddelde \[\bar X = \frac{X_1+ X_2+ ... + X_n}{n} = \frac{\sum_{i=1}^{n} X_i}{n}\] van willekeurige variabelen \(X_1,X_2, ..., X_n\).

  • Steekproef gemiddelde \(\bar X\) is een willekeurige variable dat varieert van steekproef tot steekproef.

  • Bestudeer de theoretische verdeling van het steekproefgemiddelde om inzicht te krijgen

    1. in hoe het steekproefgemiddelde kan variëren in een nieuw gelijkaardig onderzoek
    2. hoe ver \(\bar X\) kan verschillen van het populatiegemiddelde \(\mu\)

3.1 Overzicht

  1. Het steekproefgemiddelde is onvertekend
  2. Precisie van steekproefgemiddelde
  3. Distributie van steekproefgemiddelde

3.2 Het steekproefgemiddelde is onvertekend

  • We kunnen het effect in de steekproef veralgemenen naar de populatie als de schatting in de steekproef een goede benadering is van de populatiewaarde.

  • De steekproef moet representatief zijn om de resultaten van de steekproef naar de populatie te generaliseren

  • Vermijd bias (zodat het populatiegemiddelde niet systematisch onder of overschat wordt)

  • Rapporteer hoe de steekproef is genomen!

  • Randomisatie!

  • Neem de proefpersonen willekeurig uit de populatie, zodat elke proefpersoon dezelfde kans heeft om in de steekproef terecht te komen

  • Proefpersonen met hyptertensie worden willekeurig uit de populatie genomen.

  • Eenvoudige willekeurige steekproef: \(X_1,...,X_n\) voor kenmerk \(X\)

  • \(X_1,...,X_n\) hebben dezelfde distributie

  • Ze hebben hetzelfde gemiddelde \(\mu\) en variantie \(\sigma^2\)

  • \(E(X_1)=...=E(X_n)=\mu\) en \(\text{Var}(X_1)=...=\text{Var}(X_n)=\sigma^2\)

  • \(\bar X\) is een overtekende schatter voor \(\mu\)

Click to see proof

\[\begin{eqnarray*} E(\bar X) &=& E \left(\frac{X_1+ X_2+ ... + X_n}{n}\right) \\ &= & \frac{E(X_1)+ E(X_2)+ ... + E(X_n)}{n} \\ &=& \frac{\mu + \mu + ... +\mu}{n} \\ &= & \mu \end{eqnarray*}\]


3.3 Imprecisie/standard error

  • Ook voor representatieve steekproeven zijn de resultaten onnauwkeurig

  • Verschillende steekproeven uit dezelfde populatie geven verschillende resultaten.

  • We illustreren dit met de NHANES studie

    • We zullen 15 vrouwen willekeurig selecteren uit de NHANES studie en zullen hun lengte registreren.
    • We herhalen dit 50 keer om de variatie van steekproef tot steekproef te beoordelen
    • We plotten de boxplot voor iedere steekproef en duiden het gemiddelde aan.
library(NHANES)

fem <- NHANES %>%
  filter(Gender=="female" & !is.na(DirectChol)) %>%
  select("DirectChol")

n <- 15 # number of subjects per sample
nSim <- 50 # number of simulations

femSamp <- matrix(nrow=n,ncol=nSim)
for (j in 1:nSim)
{
  set.seed(2105)
  femSamp[,j] <- sample(fem$DirectChol,15)
  if (j<4) {
    p <- femSamp %>%
      log2 %>%
      data.frame %>%
      gather("sample","log2cholesterol") %>%
      ggplot(aes(x=sample,y=log2cholesterol)) +
      geom_boxplot() +
      stat_summary(
        fun.y=mean,
        geom="point",
        shape=19,
        size=3,
        color="red",
        fill="red") +
      geom_hline(yintercept = mean(fem$DirectChol %>% log2)) +
      ylab("cholesterol (log2)")
    print(p)
  }
}

femSamp %>%
  log2 %>%
  data.frame %>%
  gather("sample","log2cholesterol") %>%
  ggplot(aes(x=sample,y=log2cholesterol)) +
  geom_boxplot() +
  stat_summary(fun.y=mean, geom="point", shape=19, size=3, color="red", fill="red") +
  geom_hline(yintercept = mean(fem$DirectChol %>% log2)) +
  ylab("cholesterol (log2)")

We observeren dat het steekproefgemiddelde fluctueert rond het gemiddelde van de populatie.

Opdracht:

  1. Kopieer de code
  2. Vergroot de steekproefgrootte tot 100 proefpersonen
  3. Wat observeer je?

Hoe doen we dit op basis van een enkele steekproef?

  • Inzicht in hoe dicht we \(\bar X\) tot\(\mu\) kunnen verwachten?

  • Hoe varieert \(\bar X\) van steekproef tot steekproef?

  • Variabiliteit op \(\bar X\)

  • Dit moeten we bepalen op basis van een enkele steekproef!

  • We moeten assumpties maken

  • We nemen aan dat de willekeurige variabelen \(X_1, X_2, ..., X_n\) afkomstig zijn van \(n\) onafhankelijke personen.

  • Voor de Captopril studie hebben we afhankelijke observaties

    • Bloeddrukmetingen voor (\(Y_{i,before}\)) en na (\(Y_{i,after}\)) toediening van captopril aan dezelfde patiënt \(i=1,\ldots,n\).
    • We hebben ze omgezet in n onafhankelijke metingen door het verschil \(Y_{i,na}-Y_{i,voor}\) te nemen.

3.3.1 Variantie schatter voor \(\bar X\)

\[\sigma^2_{\bar X}=\frac{\sigma^2}{n}\]

  • De standaarddeviatie van \(\bar X\) rond \(\mu\) is \(\sqrt{n}\) keer kleiner dan de deviatie rond de originele observaties \(X\).

  • Hoe meer observaties we hebben, des te nauwkeuriger \(\bar X\).

Click to see proof

\[\begin{eqnarray*} \text{Var}(\bar X)&=&\text{Var} \left(\frac{X_1+ X_2+ ... + X_n}{n}\right) \\ &\overset{*}{=} & \frac{\text{Var}(X_1)+ \text{Var}(X_2)+ ... + \text{Var}(X_n)}{n^2} \\ &=& \frac{\sigma^2 + \sigma^2 + ... \sigma^2}{n^2} \\ &= & \frac{\sigma^2}{n}. \end{eqnarray*}\]

  • (*) Dit is gebaseerd op de assumptie van onafhankelijkheid \[\text{Var}[a X_1 + b X_2] = a^2\text{Var}[X_1] + b^2 \text{Var}[X_2] + 2 ab\text{Covar}[X_1,X_2]\]

    • Met \(Covar[X_1,X_2]=0\) wanneer \(X_1\) en \(X_2\) onafhankelijk zijn.

s

Definitie: standaard error

De standaard deviatie van \(\bar{X}\) is \(\sigma/\sqrt{n}\) en wordt ook wel de standaard error van het gemiddelde genoemd. Over het algemeen verwijst men naar de standaarddeviatie van een schatter voor een bepaalde parameter \(\theta\) met de term standaard error van de schatter die wordt aangeduid als \(SE\)


3.3.2 Captopril voorbeeld

  • \(n = 15\) verschillen in systolische bloeddruk

  • Stel dat de standaarddeviatie van de bloeddrukverschillen in de populatie \(\sigma = 9.0\) mmHg is

  • Dan wordt de standaard error (SE) op de gemiddelde systolische bloeddruk verschillen \(\bar X\):

\[ SE = \frac{9.0}{\sqrt{15}}=2.32\text{mmHg.} \]

  • Over het algemeen zijn \(\sigma\), en dus de SE op het steekproefgemiddelde onbekend.

  • We moeten dus ook de standaarddeviatie van de steekproef schatten om de standaard error te verkrijgen.

  • Schatter: \(SE=S/\sqrt{n},\)

  • Met \(S^2\) de steekproefvariantie van \(X_1,...,X_n\) en \(S\) de steekproefstandaarddeviatie

  • Voor het Captopril voorbeeld krijgen we:

n <- length(captopril$deltaSBP)
se <- sd(captopril$deltaSBP)/sqrt(n)
se
[1] 2.330883

3.3.3 standaarddeviatie vs standaard error

3.3.3.1 Illustratie via herhaalde steekproeven

  • Verschillende steekproef groottes: 10, 50, 100

  • Neem 1000 steekproeven per steekproef grootte van de NHANES studie, voor iedere steekproef berekenen we:

    • Het gemiddelde
    • De steekproefstandaarddeviatie
    • de standaard error
  • We maken een boxplot van de steekproefstandaardevaties en de standaard errors voor de verschillende steekproefgroottes

  • In plaats van een for loop te gebruiken zullen we de sapply functie gebruiken die efficiënter is. Het neemt een vector of lijst als invoer en past de functie toe op ieder element van de vector of lijst.

set.seed(24)
femSamp10 <- sapply(
  1:1000,
  function(j,x,size) sample(x,size),
  size=10,
  x=fem$DirectChol)

femSamp50 <- sapply(
  1:1000,
  function(j,x,size) sample(x,size),
  size=50,
  x=fem$DirectChol)

femSamp100 <- sapply(
  1:1000,
  function(j,x,size) sample(x,size),
  size=100,
  x=fem$DirectChol)

res<-rbind(
  femSamp10 %>%
    log2%>%
    as.data.frame %>%
    gather(sample,log2Chol) %>%
    group_by(sample)%>%
    summarize_at("log2Chol",
               list(median=~median(.,na.rm=TRUE),
                    mean=~mean(.,na.rm=TRUE),
                    sd=~sd(.,na.rm=TRUE),
                    n=function(x) x%>%is.na%>%`!`%>%sum)) %>%
    mutate(se=sd/sqrt(n)) ,

  femSamp50 %>%
    log2 %>%  
    as.data.frame %>%
    gather(sample,log2Chol) %>%
    group_by(sample)%>%
    summarize_at("log2Chol",
               list(median=~median(.,na.rm=TRUE),
                    mean=~mean(.,na.rm=TRUE),
                    sd=~sd(.,na.rm=TRUE),
                    n=function(x) x%>%is.na%>%`!`%>%sum)) %>%
    mutate(se=sd/sqrt(n)),

  femSamp100 %>%
    log2 %>%
    as.data.frame %>%
    gather(sample,log2Chol) %>%
    group_by(sample)%>%
    summarize_at("log2Chol",
               list(median=~median(.,na.rm=TRUE),
                    mean=~mean(.,na.rm=TRUE),
                    sd=~sd(.,na.rm=TRUE),
                    n=function(x) x%>%is.na%>%`!`%>%sum)) %>%
    mutate(se=sd/sqrt(n))
  )

Gemiddelden

We illustreren de impact van steekproefgrootte op de distributie van de gemiddeldes van verschillende steekproeven

res %>%
  ggplot(aes(x= n %>% as.factor,y = mean)) +
  geom_boxplot() +
  ylab("Direct cholesterol (log2)") +
  xlab("sample size")

  • Merk op dat de variatie van de steekproefgemiddelden inderdaad afneemt naarmate de steekproefgrootte toeneemt. De schatting wordt dus nauwkeuriger naarmate de steekproefgrootte toeneemt.

Standard deviatie

We illustreren nu de impact van de steekproefgrootte op de verdeling van de standaarddeviatie van de verschillende steekproeven

res %>%
  ggplot(aes(x=n%>%as.factor,y=sd)) +
  geom_boxplot() +
  ylab("standard deviation") +
  xlab("sample size")

  • De standaarddeviatie blijft vergelijkbaar voor de steekproefgroottes. Het is gecentreerd rond dezelfde waarde: de standaarddeviatie in de populatie. Het vergroten van de steekproefgrootte heeft inderdaad geen invloed op de variabiliteit in de populatie!

  • Opnieuw zien we dat de variabiliteit van de standaarddeviatie afneemt naarmate de steekproefgrootte toeneemt. De standaarddeviatie kan dus ook nauwkeuriger worden geschat naarmate de steekproefgrootte toeneemt.


Standaard error van het gemiddelde

Ten slotte illustreren we de impact van de steekproefgrootte op de verdeling van de standaarddeviatie van het gemiddelde van de verschillende steekproeven, de standaard error.

res %>%
ggplot(aes(x=n%>%as.factor,y=se)) +
geom_boxplot() +
ylab("standard error") +
xlab("sample size")

  • De standaard error (de schatter voor de nauwkeurigheid van het steekproefgemiddelde) vermindert aanzienlijk naarmate de steekproefgrootte toeneemt, wat opnieuw bevestigt dat de schatting van het steekproefgemiddelde nauwkeuriger wordt.

3.3.4 Normaal verdeelde data

  • Voor normaal verdeelde data hebben we meerdere schatters voor het populatiegemiddelde \(\mu\) bv. gemiddelde en mediaan.

  • Maar \(\bar{X}\) is de overtekende schatter van \(\mu\) met de kleinste standaard error

  • \(\bar{X}\) wijkt minder af van het gemiddelde \(\mu\) dan de mediaan

  • We illustreren dit voor herhaalde steekproeven met steekproefgrootte 10

res %>%
  filter(n == 10) %>%
  select(mean,median) %>%
  gather(type,estimate) %>%
  ggplot(aes(x = type,y = estimate)) +
  geom_boxplot() +
  geom_hline(yintercept = fem$DirectChol %>%
    log2 %>%
    mean) +
  ggtitle("10 personen")

Vervolgens vergelijken we de verdeling van het gemiddelde en de mediaan in herhaalde steekproeven van steekproefgrootte 50.

res %>%
  filter(n == 50) %>%
  select(mean, median) %>%
  gather(type, estimate) %>%
  ggplot(aes(x = type,y = estimate)) +
  geom_boxplot()+
  geom_hline(yintercept = fem$DirectChol %>%
    log2 %>%
    mean) +
  ggtitle("50 personen")

3.4 Verdeling van het steekproefgemiddelde

  • Hoe varieert \(\bar X\) van steekproef tot steekproef?
  • Verdeling van \(\bar X\)?
  • Als \(\bar X\) normaal verdeeld is, heeft de standaard error een goede interpretatie: de SE is de standaard deviatie van het steekproefgemiddelde.
  • Als de data \(X_i\) normaal verdeeld zijn, is het steekproefgemiddelde ook normaal verdeeld.

\[X_i \sim N(\mu,\sigma^2) \rightarrow \bar X \sim N(\mu, \sigma^2/n)\]


3.4.1 NHANES: cholesterol

We illustreren dit nogmaals met een simulatie gebruik makende van de NHANES-studie. De log2-cholesterolwaarden zijn normaal verdeeld.

 fem %>%
  ggplot(aes(x = DirectChol %>% log2))+
  geom_histogram(aes(y = ..density.., fill = ..count..)) +
  xlab("Direct cholesterol (log2)") +
  stat_function(
    fun = dnorm,
    color = "red",
    args = list(
      mean=mean(fem$DirectChol%>%log2),
      sd = sd(fem$DirectChol%>%log2)
      )
    ) +
  ggtitle("Alle vrouwen in NHANES studie")

fem %>%
  ggplot(aes(sample = DirectChol %>% log2)) +
  stat_qq() +
  stat_qq_line() +
  ggtitle("Alle vrouwen in NHANES study")


3.4.1.0.1 Evalueer de verdeling van het gemiddelde voor steekproeven van grootte 10

We onderzoeken de resultaten voor de steekproefgrootte van 10.

We bekijken eerst de plot voor de eerste steekproef.

femSamp10[,1] %>%
  log2 %>%
  as.data.frame %>%
  ggplot(aes(x=.))+
    geom_histogram(aes(y=..density.., fill=..count..),bins=10) +
    xlab("Direct cholesterol (log2)") +
    stat_function(
      fun=dnorm,
      color="red",
      args=list(
        mean=femSamp10[,1]%>%log2%>%mean, sd=femSamp10[,1]%>%log2%>%sd)
      ) +
    ggtitle("10 random females") +
    xlim(fem$DirectChol %>% log2 %>% range)

Vervolgens kijken we naar de verdeling van het steekproefgemiddelde over 1000 steekproeven van steekproefgrootte 10.

femSamp10 %>%
  log2 %>%
  colMeans %>%
  as.data.frame %>%
  ggplot(aes(x=.)) +
  geom_histogram(aes(y=..density.., fill=..count..),bins=15) +
  xlab("Mean cholesterol (log2)") +
  stat_function(
    fun=dnorm,
    color="red",
    args=list(
      mean=femSamp10%>%log2%>% colMeans %>% mean,
      sd=femSamp10%>%log2%>% colMeans %>% sd)
    ) +
  ggtitle("Means on 10 females")

femSamp10 %>%
  log2%>%
  colMeans %>%
  as.data.frame %>%  
  ggplot(aes(sample=.)) +
  stat_qq() +
  stat_qq_line() +
  ggtitle("Means on 10 females")

We hebben dus bevestigd dat het gemiddelde ongeveer normaal verdeeld is voor studies met 5 en 10 vrouwen, terwijl de originele gegevens ongeveer normaal verdeeld zijn.


3.4.1.1 Captopril studie

  • De systolische bloeddrukverschillen in de Captopril studie zijn bij benadering normaal verdeeld.

  • s.e.= 2.32 mm Hg

  • In 95 van de 100 studies met n = 15 proefpersonen verwachten we dat het steekproefgemiddelde van de systolische bloeddrukverschillen (\(\bar X\)) op minder dan \(2 \times 2.32 = 4.64\)mm Hg van het werkelijk populatiegemiddelde van de bloeddrukverschillen geschat wordt.


3.4.2 Niet-normaal verdeelde data

  • Als individuele observaties geen normale verdeling hebben, is \(\bar X\) nog steeds normaal verdeeld wanneer het aantaal observaties groot genoeg is.

  • Hoe groot moet de steekproef zijn om de normale benadering te laten werken?

  • Dit hangt af van de scheefheid van de distributie!


3.4.2.1 NHANES: cholesterol

  • We kunnen dit evalueren in de NHanes-studie als we de gegevens niet log2 transformeren.
fem %>%
   ggplot(aes(x=DirectChol))+
   geom_histogram(aes(y=..density.., fill=..count..)) +
   xlab("Direct cholesterol") +
   stat_function(
     fun=dnorm,
     color="red",
     args=list(
       mean=mean(fem$DirectChol),
       sd=sd(fem$DirectChol))

    ) +
   ggtitle("All females in Nhanes study")

 fem %>%
  ggplot(aes(sample=DirectChol)) +
  stat_qq() +
  stat_qq_line() +
  ggtitle("All females in Nhanes study")

De cholesterol data zijn duidelijk niet-normaal verdeeld.

3.4.2.1.1 Verdeling van het steekproefgemiddelde voor verschillende steekproefgroottes
set.seed(121)
femSamp5 <- sapply(
  1:1000,
  function(j,x,size) sample(x,size),
  size = 5,
  x = fem$DirectChol)

femSamp5 %>%
  colMeans %>%
  as.data.frame %>% ggplot(aes(x=.)) +
  geom_histogram(aes(y=..density.., fill=..count..),bins=15) +
  xlab("Mean cholesterol") +
  stat_function(
    fun=dnorm,
    color="red",
    args=list(
      mean=femSamp5%>% colMeans %>% mean,
      sd=femSamp5%>% colMeans %>% sd)
    ) +
  ggtitle("Means on 5 females")

femSamp5 %>%
  colMeans %>%
  as.data.frame %>%  
  ggplot(aes(sample=.)) +
  stat_qq() +
  stat_qq_line() +
  ggtitle("Means on 5 females")

femSamp10 %>%
  colMeans %>%
  as.data.frame %>% ggplot(aes(x=.)) +
  geom_histogram(aes(y=..density.., fill=..count..),bins=15) +
  xlab("Mean cholesterol") +
  stat_function(
    fun=dnorm,
    color="red",
    args=list(
      mean=femSamp10%>% colMeans %>% mean,
      sd=femSamp10%>% colMeans %>% sd)
    ) +
ggtitle("Means on 10 females")

femSamp10 %>%
  colMeans %>%
  as.data.frame %>%  
  ggplot(aes(sample=.)) +
  stat_qq() +
  stat_qq_line() +
  ggtitle("Means on 10 females")

femSamp50 %>%
  colMeans %>%
  as.data.frame %>%  
  ggplot(aes(sample=.)) +
  stat_qq() +
  stat_qq_line() +
  ggtitle("Means on 50 females")

femSamp100 %>%
  colMeans %>%
  as.data.frame %>%  
  ggplot(aes(sample=.)) +
  stat_qq() +
  stat_qq_line() +
  ggtitle("Means on 100 females")

  • We merken op dat wanneer de data niet normaal verdeeld zijn, de verdeling van het steekproefgemiddelde niet normaal verdeeld is over kleine steekproeven

  • Voor grote steekproeven is het steekproefgemiddelde van niet-normale gegevens echter nog steeds ongeveer normaal verdeeld.


3.4.3 Centrale limietstelling

Laat \(X_1, \ldots, X_n\) een reeks willekeurige variabelen zijn die onafhankelijk van dezelfde verdeling (populatie) worden getrokken. Zolang de steekproefgrootte n voldoende groot is, is het steekproefgemiddelde \(\bar X\) ongeveer normaal verdeeld, ongeacht de verdeling van de waarnemingen \(X_i\).

3.4.4 Overzicht van de verdeling van het gemiddelde


4 Interval schatters

  • \(\bar X\) varieert rond \(\mu\)

  • hier zullen we een interval ontwikkelen rond \(\bar X\) dat de waarde \(\mu\) bevat met een waarschijnlijkheid van 95% voor een willekeurige steekproef.

  • We nemen eerst aan dat \(\sigma^2\) bekend is en we zullen deze aanname later versoepelen.


4.1 Normaal verdeelde data met gekende variantie

  • \(X\sim N(\mu,\sigma^2) \rightarrow \bar X\sim N\left(\mu,\frac{\sigma^2}{n}\right)\)

  • 95% referentie-interval voor het steekproefgemiddelde

\[\begin{equation*} \left[\mu - 1.96 \frac{\sigma}{\sqrt{n}},\mu + 1.96 \frac{\sigma}{\sqrt{n}}% \right] \end{equation*}\]

  • Het interval bevat het steekproefgemiddelde van een willekeurige steekproef met een kans van 95%.

  • We kunnen dit niet berekenen aangezien \(\mu\) niet gekend is.

  • Schat \(\mu\) met \(\bar X\).
    \[\begin{equation*} \left[\bar X - 1.96 \frac{\sigma}{\sqrt{n}},\bar X + 1.96 \frac{\sigma}{\sqrt{n}}\right] \end{equation*}\]

  • Meer bruikbare interpretatie:

  • herschrijf \(\mu - 1.96 \ \sigma/\sqrt{n} < \bar{X}\) as \(\mu < \bar{X} + 1.96 \ \sigma/\sqrt{n}\).

Zodat we kunnen schrijven \[\begin{eqnarray*} 95\% &=& P( \mu - 1.96 \ \sigma/\sqrt{n} < \bar{X} < \mu + 1.96 \ \sigma/\sqrt{n} ) \\ &=&P( \bar{X} - 1.96 \ \sigma/\sqrt{n} < \mu < \bar{X} + 1.96 \ \sigma/\sqrt{n} ) \end{eqnarray*}\]


Definitie van 95% betrouwbaarheids interval op het gemiddelde Voor een willekeurige steekproef bevat het interval \[\begin{equation} [\bar{X} - 1.96 \ \sigma/\sqrt{n} , \bar{X} + 1.96 \ \sigma/\sqrt{n} ], \end{equation}\] het populatiegemiddelde \(\mu\) met een kans van 95%.


  • De kans dat het BI voor een willekeurige steekproef de populatieparameter \(\mu\) bevat, dus 95%, wordt ook wel het betrouwbaarheidsniveau genoemd.

  • Merk op dat de onder- en bovengrens van het interval ook willekeurige variabelen zijn die van steekproef tot steekproef variëren. Verschillende steekproeven resulteren inderdaad in verschillende betrouwbaarheidsintervallen omdat ze gebaseerd zijn op verschillende waarnemingen.

  • Het zijn dus stochastische intervallen

  • 95% van de steekproeven zullen een 95% betrouwbaarheidsinterval produceren dat het populatiegemiddelde \(\mu\) zal bevatten. De overige 5% zullen intervallen produceren die het populatiegemiddelde niet bevatten.

  • Op basis van één interval kun je niet concluderen dat het de werkelijke populatieparameter bevat, omdat de waarde ervan onbekend is.

Over het algemeen is de standaarddeviatie ongekend en moet het geschat worden.

  • Voor grote \(n\), zal \([\bar{X} - 1.96 \ s/\sqrt{n} , \bar{X} + 1.96 \ s/\sqrt{n} ]\) het populatiegemiddelde bevatten met een probabiliteit van 95%.

4.1.1 NHANES log2 cholesterol voorbeeld

4.1.1.1 1 steekproef

set.seed(3146)
samp50 <- sample(fem$DirectChol,50)

ll <- mean(samp50 %>% log2) - 1.96*sd(samp50 %>% log2)/sqrt(50)
ul <- mean(samp50 %>% log2) + 1.96*sd(samp50 %>% log2)/sqrt(50)
popMean <- mean(fem$DirectChol%>%log2)

c(ll=ll,ul=ul,popMean=popMean)
       ll        ul   popMean 
0.4326245 0.6291622 0.5142563 

4.1.1.2 Herhaalde steekproeven

res$ll <- res$mean-1.96*res$se
res$ul <- res$mean+1.96*res$se
mu <- fem$DirectChol%>%
  log2%>%
  mean

res$inside<- res$ll <= mu & mu <= res$ul
res$n <- as.factor(res$n)
res %>%
  group_by(n) %>%
  summarize(coverage=mean(inside)) %>%
  spread(n,coverage)
# A tibble: 1 x 3
   `10`  `50` `100`
  <dbl> <dbl> <dbl>
1  0.92 0.942 0.954
  • Merk op dat de omvang in de steekproeven met 10 waarnemingen te laag is omdat we geen rekening houden met de onzekerheid in de schatting van de standaarddeviatie.

  • Als we kijken naar de eerste 20 intervallen, bevat 1 van de 20 niet het populatiegemiddelde.

res %>%
  filter(n==10) %>%
  slice(1:20) %>%
  ggplot(aes(x = sample,y = mean,color = inside)) +
  geom_point() +
  geom_errorbar(aes(ymin = mean-1.96*se,ymax = mean+1.96*se))+
  geom_hline(yintercept = fem$DirectChol %>% log2 %>% mean) +
  ggtitle("20 CI for N = 10") +
  ylim(range(fem$DirectChol %>% log2))


  • Voor grote steekproeven (100) is de omvang prima omdat we de standaarddeviatie met een relatief hoge precisie kunnen schatten.
res %>%
  filter(n == 50) %>%
  slice(1:20) %>%
  ggplot(aes(x = sample,y = mean,color = inside)) +
  geom_point() +
  geom_errorbar(aes(ymin = mean-1.96*se,ymax = mean+1.96*se))+
  geom_hline(yintercept = fem$DirectChol %>% log2 %>% mean) +
  ggtitle("20 CI for N = 50") +
  ylim(range(fem$DirectChol %>% log2))

res %>%
  filter(n == 100) %>%
  slice(1:20) %>%
  ggplot(aes(x = sample,y = mean,color = inside)) +
  geom_point() +
  geom_errorbar(aes(ymin = mean-1.96*se,ymax = mean+1.96*se))+
  geom_hline(yintercept = fem$DirectChol %>% log2 %>% mean) +
  ggtitle("20 CI for N = 100") +
  ylim(range(fem$DirectChol %>% log2))

  • Wat heb je geobserveerd voor de intervalbreedte?

4.1.2 Andere betrouwbaarheidsniveaus

  • We kunnen \(z_{2.5\%}=1.96\) vervangen door een ander kwantiel van de normale verdeling $z_{/2} om een interval te krijgen met een ander betrouwbaarheidsniveau \(1-\alpha\).

  • Betrouwbaarheidsintervallen worden niet alleen gebruikt voor het gemiddelde, maar ook voor andere populatieparameters.


4.2 Ongekende variantie

In echte voorbeelden is \(\sigma\) ongekend en wordt het geschat op basis van de steekproef met behulp van de standaarddeviatie \(S\).

  • De vorige intervallen waren iets te klein omdat ze geen rekening hielden met de onzekerheid over de schatting van \(S\).

  • Als \(n\) groot is, ligt \(S\) in de buurt van \(\sigma\).

  • Vandaar dat \({(\bar{X} - \mu)}/{(S/\sqrt{n}) }\) ongeveer standaard normaal verdeeld is en \[\begin{equation*} \left[\bar{X} - z_{\alpha/2} \ \frac{S}{\sqrt{n}} , \bar{X} + z_{\alpha/2} \ \frac{S}{\sqrt{n}}\right] \end{equation*}\] is een geschatte \((1- \alpha)100\%\) CI voor \(\mu\).

  • Voor kleine steekproeven geldt dit niet meer (e.g. n=10)

De schatting van \(S\) introduceert extra onzekerheid in de gestandaardiseerde waarde \({(\bar{X} - \mu)}/{(S/\sqrt{n})}\). Zijn distributie

  • is nog steeds symmetrisch maar heeft zwaardere staarten dan de normale verdeling.

  • Het hangt van \(n\) af hoeveel zwaarder de staarten zijn

  • is een (Student) \(t\)-verdeling met \(n-1\) vrijheidsgraden.


4.2.1 T-verdeling

Formeel: Let \(X_1, X_2, ..., X_n\) een onafhankelijke willekeurige steekproef zijn uit een normale verdeling \(N(\mu, \sigma^2)\), dan volgt \((\bar{X} - \mu)/(S/\sqrt{n})\) een \(t\)-verdeling met \(n-1\) vrijheidsgraden.

De densiteit van een t-verdeling kan worden berekend in R met de functie dt. Het heeft argumenten ‘x’ voor het kwantiel en ‘df’ voor de vrijheidsgraden.

grid <- seq(-5,5,.1)
densDist <- cbind(grid,dnorm(grid), sapply(c(2,5,10),dt,x=grid))
colnames(densDist) <- c("x","normal",paste0("t",c(2,5,10)))

densDist %>%
  as.data.frame %>%
  gather(dist,dens,-x) %>%
  ggplot(aes(x=x,y=dens,color=dist)) +
  geom_line() +
  xlab("x") +
  ylab("Densiteit")

t-verdelingen hebben zwaardere staarten dan de normale verdeling \(\rightarrow\) grotere kantielen, dus bredere intervallen voor hetzelfde betrouwbaarheidsniveau.

  • Dit geeft de extra onzekerheid weer voor het schatten van \(S\).

  • Als \(n \rightarrow \infty\) dan \(t(df) \rightarrow N(0,1)\)

  • kwantielen van de \(t\)-verdeling kunnen worden berekend in R met behulp van qt. bv. 95%, 97.5%, 99.5% kwantiel voor een t-verdeling met 14 vrijheidsgraden.

qt(.975,df=14)
[1] 2.144787
qt(c(.95,.975,.995),df=14)
[1] 1.761310 2.144787 2.976843
  • Deze kwantielen kunnen gebruikt worden om de 90%, 95% and 99% CI te berekenen.

  • 97.5% kwantiel2.14 van een t-verdeling met \(n-1=14\) vrijheidsgraden is inderdaad groter dan die van een standaard normale verdeling 1.96.

4.2.2 Interpretatie van het betrouwbaarheidsinterval

  • We zullen opnieuw steekproeven trekken van de grote NHANES studie en deze keer BI’s bestuderen voor log2-cholesterol steekproefwaarden. We voeren eerst herhaalde experimenten uit met steekproefgrootte 10.
res$n <- as.character(res$n) %>%
  as.double(res$n)

res$ll <- res$mean-qt(0.975,df=res$n-1)*res$se
res$ul <- res$mean+qt(0.975,df=res$n-1)*res$se

mu <- fem$DirectChol%>%log2%>%mean

res$inside <- res$ll<=mu & mu<=res$ul
res$n <- as.factor(res$n)

res %>%
  group_by(n) %>%
  summarize(coverage=mean(inside)) %>%
  spread(n,coverage)
# A tibble: 1 x 3
   `10`  `50` `100`
  <dbl> <dbl> <dbl>
1 0.949 0.947 0.959

We zien dat de omvang van de intervallen nu worden gecontroleerd op hun nominale betrouwbaarheidsniveau van 95%.

res %>%
  filter(n==10) %>%
  slice(1:20) %>%
  ggplot(aes(x=sample,y=mean,color=inside)) +
  geom_point() +
  geom_errorbar(
    aes(ymin=mean-qt(0.975,df=9)*se,
    ymax=mean+qt(0.975,df=9)*se))+
  geom_hline(yintercept = fem$DirectChol %>% log2 %>% mean) +
  ggtitle("20 CI for N=10") +
  ylim(range(fem$DirectChol %>% log2))


4.3 Rapporteren?

  • Rapporteer altijd de onzekerheid over de resultaten!

  • Conclusies op basis van een puntschatting kunnen erg misleidend zijn.

  • Bij een statistische analyse rapporteren we daarom altijd betrouwbaarheidsintervallen

  • Ze zijn klein genoeg om informatief te zijn, maar bijna nooit misleidend

  • Ze vormen een goede afweging tussen statistische significantie en biologische relevantie.

  • Rapporteer altijd de onzekerheid op de resultaten!

  • Bij een statistische analyse rapporteren we daarom altijd betrouwbaarheidsintervallen

  • De intervallen zijn klein genoeg om informatief te zijn, maar bijna nooit misleidend

  • Ze vormen een goede afweging tussen statistische significantie en biologische relevantie.

  • We concluderen dat de populatieparameter in het interval ligt en weten dat deze stelling geldt met een probabiliteit van 95% voor willekeurige steekproeven.

4.3.1 Captopril voorbeeld

We concluderen dat de bloeddruk gemiddeld met 18.9mmHg vermindert na toediening van captopril (95% CI [-23.9,-13.9]mmHg).

Op basis van deze resultaten is het duidelijk dat de behandeling een sterke bloeddrukdaling veroorzaakt bij patiënten met hypertensie.

5 Hypothese testen

5.1 Captopril voorbeeld:

Onderzoekers willen beoordelen of het medicijn captopril de bloeddruk verlaagt bij patiënten met hypertensie.

  • Heeft het toedienen van captopril wel of geen effect op de systolische bloeddruk?

  • Het ligt niet voor de hand om dergelijke conclusies te trekken op basis van een kleine steekproef

  • Het is onzeker of we de observaties in de steekproef naar de populatie kunnen veralgemenen!

  • Is het schijnbaar gunstige effect systematisch of willekeurig?

captoprilTidy %>%
  filter(type%in%c("SBPa","SBPb")) %>%
  mutate(type=factor(type,levels=c("SBPb","SBPa"))) %>%
  ggplot(aes(x=type,y=bp)) +
  geom_line(aes(group = id)) +
  geom_point()

captopril$deltaSBP <- captopril$SBPa-captopril$SBPb
captopril%>%
  ggplot(aes(x="Systolic blood pressure",y=deltaSBP)) +
  geom_boxplot(outlier.shape=NA) +
  geom_point(position="jitter")+
  ylab("Difference (mm mercury)") +
  xlab("")

  • Het gemiddelde bloeddrukverschil \(\bar X\) is een natuurlijke basis om onze beslissingen op te baseren.

\[\bar x\text{=-18.93 (s=9.03, SE=2.33)}\]

  • Het is niet voldoende dat \(\bar{x}< 0\) om te concluderen dat de systolische bloeddruk gemiddeld lager is bij toediening van Captopril op het niveau van de gehele populatie.

  • Om het effect dat we in de steekproef waarnemen te veralgemenen naar de populatie, moet het voldoende groot zijn.

  • Maar hoe groot?


5.1.1 Hypothese testen

  • Voor dit doel zijn statistische hypothesetests ontwikkeld

  • Deze geven een zwart/wit antwoord

  • Het is bijna onmogelijk om een wetenschappelijke publicate te lezen zonder resultaten van statistische testen

  • Volgens het falsificatie principe van Popper kunnen we nooit een hypothese bewijzen op basis van gegevens.

    • Daarom introduceren we twee hypothesen: een nulhypothese \(H_0\) en een alternatieve hypothese \(H_1\).

    • We zullen proberen de nulhypothese te ontkrachten op basis van de statistische test.

5.1.1.1 Captopril

  • Op basis van de steekproef kunnen we niet bewijzen dat er een effect is van het toedienen van captopril (\(H_1\), alternatieve hypothese).

  • We veronderstellen daarom dat er geen effect is van captopril

    • We noemen dit de nulhypothese \(H_0\).

    • Falsify (“probeer te ontkrachten”) de \(H_0\).

    • Hoe waarschijnlijk is het om een effect waar te nemen dat minstens zo groot is als wat we in de steekproef in een willekeurige steekproef hebben gezien als \(H_0\) waar is?


5.1.1.2 Permutatie test

  • Onder \(H_0\) zijn de bloeddrukmetingen voor en na toediening van captopril twee “base line” bloeddrukmetingen voor een patiënt

  • Onder H\(_0\) kunnen we de bloeddrukmetingen voor iedere patiënt in willekeurige volgorde plaatsen (permuteren).

set.seed(35)
captoprilSamp <- captopril
perm <- sample(c(FALSE, TRUE), 15, replace = TRUE)
captoprilSamp$SBPa[perm] <- captopril$SBPb[perm]
captoprilSamp$SBPb[perm] <- captopril$SBPa[perm]
captoprilSamp$deltaSBP <- captoprilSamp$SBPa-captoprilSamp$SBPb
captoprilSamp %>%
  gather(type, bp, -id) %>%
  filter(type %in% c("SBPa","SBPb")) %>%
  mutate(type = factor(type, levels = c("SBPb", "SBPa")))%>%
  ggplot(aes(x = type,y = bp)) +
  geom_line(aes(group = id)) +
  geom_point()

data.frame(
  deltaSBP = c(captopril$deltaSBP,captoprilSamp$deltaSBP),
  shuffled=rep(c(FALSE,TRUE),each=15)
  ) %>%
  ggplot(aes(x = shuffled, y = deltaSBP)) +
  geom_boxplot(outlier.shape = NA) +
  geom_point(position = "jitter")+
  stat_summary(
    fun.y = mean,
    geom = "point",
    shape = 19,
    size = 3,
    color = "red",
    fill = "red") +
  ylab("Difference (mm mercury)")

We permuteren opnieuw

captoprilSamp <- captopril
perm <- sample(c(FALSE,TRUE), 15, replace = TRUE)
captoprilSamp$SBPa[perm] <- captopril$SBPb[perm]
captoprilSamp$SBPb[perm] <- captopril$SBPa[perm]
captoprilSamp$deltaSBP <- captoprilSamp$SBPa-captoprilSamp$SBPb
captoprilSamp %>%
  gather(type, bp, -id) %>%
  filter(type %in% c("SBPa","SBPb")) %>%
  mutate(type = factor(type, levels = c("SBPb", "SBPa")))%>%
  ggplot(aes(x = type,y = bp)) +
  geom_line(aes(group = id)) +
  geom_point()

data.frame(
  deltaSBP = c(captopril$deltaSBP,captoprilSamp$deltaSBP),
  shuffled=rep(c(FALSE,TRUE),each=15)
  ) %>%
  ggplot(aes(x = shuffled, y = deltaSBP)) +
  geom_boxplot(outlier.shape = NA) +
  geom_point(position = "jitter")+
  stat_summary(
    fun.y = mean,
    geom = "point",
    shape = 19,
    size = 3,
    color = "red",
    fill = "red") +
  ylab("Difference (mm mercury)")

  • Er zijn \(2^{15}\) = 32768 mogelijke permutaties!
  • We hoeven in principe alleen de tekens van de waargenomen bloeddrukverschillen \(x\) te wisselen als we permuteren.
permH <- expand.grid(
  replicate(
    15,
    c(-1,1),
    simplify=FALSE)
  ) %>%
  t

permH[,1:5]
      [,1] [,2] [,3] [,4] [,5]
Var1    -1    1   -1    1   -1
Var2    -1   -1    1    1   -1
Var3    -1   -1   -1   -1    1
Var4    -1   -1   -1   -1   -1
Var5    -1   -1   -1   -1   -1
Var6    -1   -1   -1   -1   -1
Var7    -1   -1   -1   -1   -1
Var8    -1   -1   -1   -1   -1
Var9    -1   -1   -1   -1   -1
Var10   -1   -1   -1   -1   -1
Var11   -1   -1   -1   -1   -1
Var12   -1   -1   -1   -1   -1
Var13   -1   -1   -1   -1   -1
Var14   -1   -1   -1   -1   -1
Var15   -1   -1   -1   -1   -1
  • We zullen dit voor alle mogelijke permutaties doen en we zullen het gemiddelde bijhouden.
#calculate the means for the permuted data
muPerm <- colMeans(permH*captopril$deltaSBP)
muPerm %>%
  as.data.frame %>%
  ggplot(aes(x=.)) +
  geom_histogram() +
  geom_vline(
    xintercept = mean(captopril$deltaSBP),
    col = "blue")

sum(muPerm <= mean(captopril$deltaSBP))
[1] 1
mean(muPerm <= mean(captopril$deltaSBP))
[1] 3.051758e-05
  • We zien dat maar 1 van de gemiddelden die werden verkregen onder \(H_0\) (door permutatie) zo extreem was als het steekproefgemiddelde dat we in de captopril-studie hebben waargenomen.

  • Dus de kans om een bloeddrukdaling waar te nemen die groter of gelijk is dan die in de captopril-studie in een willekeurige steekproef onder de nulhypothese, is 1 op de 32768.

We hebben dus sterk bewijs dat \(H_0\) onjuist is en daarom verwerpen we \(H_0\) en concluderen \(H_1\): het toedienen van captopril heeft een effect op de bloeddruk van patiënten met hypertensie.


5.1.2 Pivot

  • In de praktijk gebruiken we altijd statistieken die de effectgrootte (gemiddeld verschil) afwegen tegen ruis (standaard error)

  • Als we de nulhypothese ontkrachten, standaardiseren we het gemiddelde rond \(\mu_0 = 0\) het gemiddelde onder \(H_0\)

\[t=\frac{\bar X-\mu_0}{se_{\bar X}}\]

  • Voor het Captopril voorbeeld wordt dit: \[\frac{-18.93-0}{2.33}=-8.12\]

We bepalen nu de nulverdeling van teststatistiek t met permutatie.

deltaPerms <- permH*captopril$deltaSBP
tPerm <- colMeans(deltaPerms)/(apply(deltaPerms,2,sd)/sqrt(15))
tOrig <- mean(captopril$deltaSBP)/sd(captopril$deltaSBP)*sqrt(15)

tPermPlot <- tPerm %>%
  as.data.frame %>%
  ggplot(aes(x = .)) +
  geom_histogram(aes(y = ..density.., fill = ..count..)) +
  geom_vline(xintercept = tOrig,col = "blue")
tPermPlot

  • Opnieuw heeft slechts 1 van de permutaties een t-statistiek die zo extreem is als de statistiek die wordt waargenomen in de captopril-studie.

Wanneer er geen effect van captopril is, is het bijna onmogelijk om een teststatistiek te verkrijgen die zo extreem is als degene die werd waargenomen ( t=-8.12).

-De kans om een grotere bloeddrukdaling waar te nemen dan degene die we in onze steekproef hebben waargenomen in een willekeurige steekproef onder \(H_0\) is 1/32768.

  • We noemen deze kans de p-waarde.

  • Het meet de sterkte van het bewijs tegen de nulwaarde: hoe kleiner de p-waarde, hoe meer bewijs we hebben dat de nulwaarde niet waar is.

  • De verdeling heeft een mooie klokvorm.


5.1.3 Hoe beslissen we?

Wanneer is de p-waarde klein genoeg om te concluderen dat er sterk bewijs is tegen de nulhypothese?

  • We werken doorgaans met een significantieniveau van \(\alpha = 0,05\)

  • We stellen dat we de test hebben uitgevoerd op het significantieniveau van 5%


5.1.4 Permutatietests zijn computationeel veeleisend

  • Kunnen we beoordelen hoe extreem de bloeddrukdaling was zonder permutatie?

  • We weten dat de bloeddrukverschillen ongeveer normaal verdeeld zijn, dus

\[t=\frac{\bar X - \mu}{se_{\bar X}}\]

volgt een t-verdeling (met 14 vrijheidsgraden voor het Captopril voorbeeld).

  • Onder H\(_0\) \(\mu=0\) en \[t=\frac{\bar X-0}{se_{\bar X}}\sim f_{T,14}\]
tPermPlot +
  stat_function(
    fun = dt,
    color = "red",
    args = list(df=14))

  • Merk op dat de permutatie-nulverdeling inderdaad overeenkomt met een t-verdeling met 14 vrijheidsgraden.

  • Zodat we de statistische test kunnen uitvoeren met behulp van statistische modellen van de gegevens.

  • Hiervoor moeten we assumpties maken, die we verifiëren in de data exploratie.


5.2 Hypotheses

Vertaal de onderzoeksvraag naar een nulhypothese (\(H_0\)) en een alternatieve hypothese (\(H_1\))

Eerst moeten we de onderzoeksvraag vertalen naar een geparametriseerd statistisch model.

  • Uit het experimentele ontwerp volgt dat \[X_1,...,X_n \text{ i.i.d } f(X),\] met \(f(X)\) de dichtheidsfunctie van bloeddrukverschillen.

  • vereenvoudig: neem aan dat \(f(X)\) gekend is met uitzondering van een eindig dimensionale set parameters \(\mathbf{\theta}\) die nog moet worden geschat (parametrisch statistisch model).

5.2.1 Captopril voorbeeld

\(X \sim N(\mu,\sigma^2)\) with \(\mathbf{\theta}=(\mu,\sigma^2)\), the mean \(\mu\) and variance \(\sigma^2\).

De onderzoeksvraag is nu vertaald in termen van de gemiddelde bloeddrukdaling:: \(\mu = E_f[X]\).

De alternatieve hypothese is geformuleerd in termen van een parameter van \(f(X)\) moet uitdrukken wat de onderzoekers met het onderzoek willen bewijzen.

  • hier: \[H_1: \mu<0.\] Gemiddeld daalt de bloeddruk van patiënten met hypertensie na toediening van captopril.

De nul hypothese drukt over het algemeen een nulvoorwaarde uit, d.w.z wanneer er niets uitzonderlijks gebeurt.

  • Onderzoekers proberen doorgaans via empirisch onderzoek aan te tonen dat het observeren van de gegevens onder de nul hoogst onwaarschijnlijk is, zodat ze de nulhypothese kunnen verwerpen: Falsificatie principe.

  • De nul hypothese wordt doorgaans uitgedrukt met dezelfde modelparameter als die wordt gebruikt voor \(H_1\).

  • Hier: \[H_0 : \mu=0\] d.w.z. gemiddeld blijft de systolische bloeddruk ongewijzigd na toediening van captopril.


5.3 Test-statistiek

Zodra de populatie, de parameters en \(H_0\) en \(H_1\) zijn bepaald, volgt men bij hypothesetesten de volgende rationale:

Construeer een teststatistiek zodat deze

  1. het bewijs meet in de steekproef,
  2. tegen de nulhypothese, en
  3. in het voordeel van de alternatieve hypothese.

Een teststatistiek moet dus een functie zijn van de waarnemingen in de steekproef.

5.3.1 Captopril voorbeeld

\[T=\frac{\bar{X}-\mu_0}{\text{SE}_{\bar X}}\] Met \(\mu_0=0\) onder \(H_0\)

Opnieuw

  • Als \(H_0\) geldt, is er geen effect van captopril op de bloeddruk in de populatie en dan verwachten we teststatistiek \(T\) dicht bij 0.

  • Als \(H_1\) waar is, verwachten we \(T <0\).

  • In het captopril voorbeeld observeren we \(t=(-18.93-0)/2.33=-8.12\).

  • Is \(t = -8.12\) in absolute waarde groot genoeg om te concluderen dat \(\mu < 0\) en met welk vertrouwen kunnen we deze conclusie trekken?

  • We weten dat t een t-verdeling volgt met 14 vrijheidsgraden onder \(H_0\)


5.4 p-waarde

De p-waarde is de probabiliteit die \(H_0\) en \(H_1\) afweegt.

De manier waarop we het berekenen is contextafhankelijk

  • Voor het Captopril voorbeeld hebben we \[ p = P\left[T \leq t \mid H_0\right] = \text{P}_0\left[T\leq t\right], \] De index “0” in \(\text{P}_0\left[.\right]\) geeft aan dat de kans wordt berekend onder \(H_0\).

Het geeft de kans weer om een teststatistiek \(T\) te bekomen die lager of gelijk is aan de waarde die wordt waargenomen in de huidige steekproef in een willekeurige steekproef onder \(H_0\) waar te nemen. - d.w.z. de kans om een teststatistiek \(T\) te vinden in een willekeurige steekproef onder \(H_0\) met een waarde die extremer is (meer in de richting van \(H_1\)) dan die waargenomen in de huidige steekproef.

5.4.1 Captopril Voorbeeld

  • De \(p\)-waarde voor het captopril voorbeeld wordt als volgt berekend. \[p= \text{P}_0\left[T\leq -8.12\right]=F_t(-8.12;14) = 0.6\ 10^{-6}.\]

    met \(F_t(;14)\) de cumulatieve verdelingsfunctie van een t-verdeling met 14 vrijheidsgraden:

\[F_t(x;14)=\int\limits_{-\infty}^{x} f_t(x;14).\]

en \(f_t(.;14)\) de dichtheidsfunctie van de t-verdeling.

  • We berekenen deze kans in R met pt(x,df)

    • De waarde van de waargenomen teststatistiek x en
    • het aantal vrijheidsgraden van de t-verdeling “df”.
  • pt(x,df) berekent de kans om een waarde kleiner of gelijk aan x waar te nemen als we een willekeurige steekproef zouden trekken uit een t-verdeling met df vrijheidsgraden.

n <- length(captopril$deltaSBP)
stat <- (mean(captopril$deltaSBP)-0)/(sd(captopril$deltaSBP)/sqrt(n))
stat
[1] -8.122816
pt(stat,n-1)
[1] 5.731936e-07

In de praktijk gaan we de test niet zelf berekenen, maar gebruiken we de functie t.test:

t.test(captopril$deltaSBP, alternative = "less")

    One Sample t-test

data:  captopril$deltaSBP
t = -8.1228, df = 14, p-value = 5.732e-07
alternative hypothesis: true mean is less than 0
95 percent confidence interval:
      -Inf -14.82793
sample estimates:
mean of x 
-18.93333 

Merk op dat we het argument alternative="less" moeten specificeren, zodat de p-waarde in de linker staart wordt berekend.

De functie geeft ook een eenzijdig interval omdat we in één richting testen.


5.4.2 Definitie van de p-waarde

De p-waarde (ook wel het ** waargenomen significantieniveau ** genoemd) is de kans om een teststatistiek in een willekeurige steekproef waar te nemen onder de nulhypothese die even extreem of extremer is dan de teststatistiek die in de huidige steekproef is waargenomen

  • Hoe kleiner de kans, hoe meer bewijs tegen \(H_0\).

  • Merk op dat de p-waarde ** niet ** de kans is dat de nulhypothese waar is!

  • Het woord “extreem” geeft aan in welke richting de teststatistiek waarschijnlijker is onder de alternatieve hypothese.

  • In het voorbeeld \(H_1: \mu < 0\) n we verwachten dus zeer negatieve waarden voor \(t\) onder \(H_1\).

  • Vanuit de definitie geven kleine p-waarden aan dat de geobserveerde teststatistiek onwaarschijniljk is in de veronderstelling dat \(H_0\) correct is.

  • Dus een kleine waarde van \(p\)-waarde betekent dat we ** \(H_0\) ** moeten afwijzen ten gunste van \(H_1\).

  • De drempel die we gebruiken om de \(p\)-waarde te vergelijken, wordt het significantie nievau genoemd en wordt aangegeven met \(\alpha\).

  • Een statistische test uitgevoerd op het \(\alpha\) significantie niveau wordt ook wel een niveau-\(\alpha\) test.

Een test resultaat is statistisch significant als \(p<\alpha\)

  • \(\alpha\) wordt gewoonlijk gezet op 5%.

  • Hoe kleiner de p-waarde hoe `significanter’ het testresultaat afwijkt van wat onder \(H_0\) verwacht kan worden.

  • Het vat het bewijs tegen de nul samen.

\[\begin{array}{cl}>0.10 & \text{ non significant (no evidence)}\\0.05-0.10 & \text{ marginal significant, weak evidence (do not use this yourself)}\\0.01-0.05 & \text{ significant}\\0.001-0.01 & \text{strongly significant}\\<0.001 & \text{ extremely significant}\end{array}\]


5.5 Kritieke waarde


5.6 Beslissingsfouten

De beslissing om \(H_0\) te accepteren of te verwerpen wordt genomen op basis van een enkele steekproef. Er kan een verkeerde beslissing zijn genomen.

Reality
Conclusion H0 H1
Accept H0 OK Type II (\(\beta\))
Reject H0 Type I (\(\alpha\)) OK
  • Type I error, \(\alpha\): de nul hypothese wordt ten onrechte verworpen (vals positief)

  • Type II error, \(\beta\): de nulhypothese wordt ten onrechte aanvaard

  • Beslissing is ook stochastisch! Zie eerste hoofdstuk van de cursus

5.6.1 Captopril Voorbeeld

  • \(H_0\): Het toedienen van captopril heeft geen effect op de systolische bloeddruk

  • \(H_1\): Het toedienen van captopril leidt gemiddeld tot een verlaging van de bloeddruk

  • Type I error: er is gemiddeld geen bloeddrukdaling bij toediening van captopril, maar we concluderen dat er een effect is van captopril.

  • Type II error: er is gemiddeld een bloeddrukdaling bij toediening van captopril, maar deze wordt niet opgemerkt door de statistische test.


5.6.2 Type I fout wordt gecontroleerd

De type I-fout wordt gecontroleerd door de constructie van de statistische test.

\[\text{P}\left[\text{type I error}\right]=\text{P}\left[\text{reject }H_0 \mid H_0\right] = \text{P}_0\left[T<t_{n-1;1-\alpha}\right]=\alpha \]

  • Het significantieniveau \(\alpha\) is de kans om een type I-fout te maken.

  • De statistische test zorgt ervoor dat de kans op een type I-fout wordt gecontroleerd op het significantieniveau \(\alpha\).

  • De kans om \(H_0\) correct te accepteren is \(1-\alpha\).

  • We kunnen aantonen dat de p-waarde onder \(H_0\) uniform verdeeld is.

  • Het testen van statistische hypothesen leidt dus tot een uniforme beslissingsstrategie.

We illustreren dit in een simulatiestudie

  • n=15
  • \(\mu=0\) mmHg, er is dus geen effect van de behandeling
  • \(\sigma =9\) mmHg
  • 1000 gesimuleerde steekproeven
nsim <- 10000
n <- 15
sigma <- 9
mu <- 0
mu0 <- 0
alpha <- 0.05

#simulate nsim samples of size n
deltaSim <- matrix(
  rnorm(n*nsim,mu,sigma),
  nrow=n,
  ncol=nsim)

pSim <- apply(
  deltaSim,
  2,
  function(x, mu, alternative)    
    t.test(x,
      mu = mu,
      alternative = alternative)$p.value,
      mu = mu0,
      alternative="less"
  )

mean(pSim<alpha)
[1] 0.0519
pSim %>%
  as.data.frame %>%
  ggplot(aes(x=.)) +
  geom_histogram() +
  xlim(0,1)

  • De type I-fout is inderdaad ongeveer 0,05
  • De p-waarden zijn uniform

5.6.3 Type II fout

  • Type II-fout bepalen is minder duidelijk.

  • We moeten redeneren onder \(H_1\)

  • In the captopril voorbeeld is \(H_1: \mu<0\)

  • Er zijn veel mogelijke alternatieven

  • De verdeling onder \(H_1\) is niet volledig gespecificeerd

  • oplossing: kies een specifieke distributie onder \(H_1\).

\[H_1(\delta): \mu=0-\delta \text{ for }\delta>0.\]

  • bijv. een bloeddrukverschil van 2 mmHg

  • type II wordt ook wel de kracht of “power” genoemd. Het is de kans om de alternatieve hypothese te aanvaarden.

  • Het wordt niet gegarandeerd door het design van de test

  • Het hangt af van de experimentele opzet van de studie

nsim <- 10000
n <- 15
sigma <- 9
mu <- -2
mu0 <- 0
alpha <- 0.05

#simulate nsim samples of size n
deltaSim <- matrix(
  rnorm(n*nsim, mu, sigma),
  nrow=n,
  ncol=nsim)

pSim <- apply(
  deltaSim,
  2,
  function(x,mu,alternative)          
    t.test(x,
      mu = mu,
      alternative = alternative)$p.value,
      mu = mu0,
      alternative = "less"
  )

mean(pSim<alpha)
[1] 0.2098
pSim %>%
  as.data.frame %>%
  ggplot(aes(x=.)) +
  geom_histogram() +
  xlim(0,1)

- We observeren dat een power van 0.2098 of een type II error van 0.7902.


  • Wanneer we de steekproefgrootte vergroten
nsim <- 10000
n <- 30
sigma <- 9
mu <- -2
mu0 <- 0
alpha <- 0.05

#simulate nsim samples of size n
deltaSim <- matrix(
  rnorm(n*nsim, mu, sigma),
  nrow=n,
  ncol=nsim)

pSim <- apply(
  deltaSim,
  2,
  function(x,mu,alternative)          
    t.test(x,
      mu = mu,
      alternative = alternative)$p.value,
      mu = mu0,
      alternative = "less"
  )

mean(pSim < alpha)
[1] 0.3203
pSim %>%
  as.data.frame %>%
  ggplot(aes(x=.)) +
  geom_histogram() +
  xlim(0,1)

  • Het vergroten van de steekproefgrootte leidt tot een hogere power.
  • Toch blijft de power om zo’n kleine bloeddrukdaling op te vangen erg laag.
  • Een daling van 2 mmHg is ook niet relevant voor farmaceutische bedrijven.


5.6.4 Interpretatie

Stel dat een bepaalde steekproef \(p < \alpha\), d.w.z. \(H_0\) afwijzen

  • Twee mogelijkheden

    • Correcte beslissing,
      • of type I fout.
  • We weten dat de kans op een type-I fout klein is, d.w.z. \(\alpha=0.05\).

Aan de andere kant als \(p\geq\alpha\) en we \(H_0\) niet afwijzen hebben we ook twee opties:

  • Correcte beslissing,
  • of we hebben een type II fout gemaakt.

De kans op een type II fout (\(\beta\)) wordt niet gecontroleerd op een specifieke waarde.

Statistische test is geconstrueerd om alleen de kans op een type I-fout op \(\alpha\) te controleren.

Om wetenschappelijk correct te zijn, moeten we een pessimistische houding aannemen en moeten we toegeven dat \(\beta\) groot kan zijn (d.w.z. een kleine power om het alternatief te detecteren).

Dus,

  • \(p < \alpha\) we verwerpen \(H_0\)

    • We concluderen dat \(H_1\) waarschijnlijk correct is
      • We noemen dit een sterke conclusie
  • \(p \geq \alpha\) accepteer \(H_0\)

    - Betekent niet dat we $H_0$ correct accepteren.
    • We kunnen enkel concluderen dat de gegevens onvoldoende bewzijs hebben tegen de \(H_0\) in voordeel van \(H_1\).
    • Dit noemen we een zwakke conclusie
    • We concluderen doorgaans dat het effect van de behandeling niet significant is.

5.7 Conclusies captopril voorbeeld

De test die we hebben uitgevoerd, wordt aangeduid als

  • De enkele steekproef t-test op het verschil of

  • een gepaarde t-test. We beschikken inderdaad over gepaarde observaties voor elke patiënt.

  • De test is eenzijdig gedaan omdat we testen tegen het alternatief van een bloeddrukdaling.

  • Beide tests (één voorbeeld van een t-test op het verschil en een gepaarde t-test) geven dezelfde resultaten:

t.test(captopril$deltaSBP,alternative="less")

    One Sample t-test

data:  captopril$deltaSBP
t = -8.1228, df = 14, p-value = 5.732e-07
alternative hypothesis: true mean is less than 0
95 percent confidence interval:
      -Inf -14.82793
sample estimates:
mean of x 
-18.93333 
t.test(captopril$SBPa,captopril$SBPb,paired=TRUE,alternative="less")

    Paired t-test

data:  captopril$SBPa and captopril$SBPb
t = -8.1228, df = 14, p-value = 5.732e-07
alternative hypothesis: true difference in means is less than 0
95 percent confidence interval:
      -Inf -14.82793
sample estimates:
mean of the differences 
              -18.93333 

5.7.1 Conclusie

Er is gemiddeld een extreem significante bloeddrukdaling bij toediening van captopril aan patiënten met hypertensie. De systolische bloeddruk daalt gemiddeld met 18,9 mmHg bij de behandeling met captopril (95% CI [\(-\infty,-14.82\)] mmHg).

Let op dat

  1. Er wordt een eenzijdig interval gerapporteerd omdat we alleen geïnteresseerd zijn in een bloeddrukdaling.

  2. Vanwege de pretest / posttest opzet kunnen we geen onderscheid maken tussen het effect van de behandeling en een placebo-effect. Er was geen goede controle! Het ontbreken van een goede controle komt meestal voor bij pre-test / post-test designs. Hoe hadden we het design kunnen verbeteren?


5.8 eenzijdig or tweezijdige testen?

De test in het captopril-voorbeeld was een eenzijdige test. We proberen alleen te detecteren of de captoprilbehandeling gemiddeld de bloeddruk verlaagt.

Stel dat we het bloeddrukverschil hebben gedefinieerd als \(X_{i}^\prime=Y_{i}^\text{before}-Y_{i}^\text{after}\)

  • Nu duidt een positieve waarde op een bloeddrukdaling

  • De gemiddelde verandering in bloeddruk wordt nu aangeduid als \(\mu^\prime=\text{E}[X^\prime]\).

  • Dus nu moeten we een eenzijdige test gebruiken om \(H_0: \mu^\prime=0\) te beoordelen tegen \(H_1: \mu^\prime>0\).

  • p-waarde wordt nu: \[p=\text{P}_0\left[T\geq t\right].\]


Analyse gebaseerd op \(X^\prime\): Argument alternative="greater" Zo dat we \(H_1: \mu^\prime>0\) gebruiken:

t.test(captopril$SBPb-captopril$SBPa, alternative="greater")

    One Sample t-test

data:  captopril$SBPb - captopril$SBPa
t = 8.1228, df = 14, p-value = 5.732e-07
alternative hypothesis: true mean is greater than 0
95 percent confidence interval:
 14.82793      Inf
sample estimates:
mean of x 
 18.93333 

Natuurlijk behalen we dezelfde resultaten. Alleen het teken is verwisseld.

5.8.1 Tweezijdige test

Stel dat onderzoekers het werkingsmechanisme van het nieuwe medicijn captopril in de ontwerpfase wilden beoordelen en veronderstel dat gezonde proefpersonen in een vroege fase van de medicijnontwikkeling werden gebruikt.

In dit geval zou het interessant zijn geweest om zowel bloeddrukdalingen als stijgingen waar te nemen.

Dan hebben we een tweezijdige teststrategie nodig

\[H_0: \mu=0\] tegen de alternatieve hypothese

\[H_1: \mu\neq0,\]

zodat het gemiddelde onder het alternatief verschilt van nul.

Het kunnen zowel positieve als negatieve veranderingen zijn en we wisten van tevoren niet in welke richting het werkelijke gemiddelde zal afwijken van \(H_1\).

We kunnen een tweezijdige test uitvoeren op het \(\alpha=5\%\) significantieniveau door


Het argument alternative van de t.test functie is heeft default waarde alternative="two.sided".

t.test(captopril$deltaSBP)

    One Sample t-test

data:  captopril$deltaSBP
t = -8.1228, df = 14, p-value = 1.146e-06
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
 -23.93258 -13.93409
sample estimates:
mean of x 
-18.93333 
  • We behalen nog steeds een buitengewoon significant resultaat.
  • De p-waarde is dubbel zo groot omdat we tweezijdig testen.

Inderdaad

\[p=P_0[T \leq -\vert t \vert] + P_0[T \geq \vert t \vert] = P_0[\vert T \vert \geq \vert t \vert] = 2 \times P_0[T \geq \vert t \vert]\]

  • We verkrijgen ook een tweezijdig betrouwbaarheidsinterval

5.8.2 Eénzijdige of tweezijdige test?

Met een eenzijdige test kunnen we \(H_0\) gemakkelijker afwijzen op voorwaarde dat \(H_1\) waar is dan met een tweezijdige test.

  • Alle informatie wordt gebruikt om in één richting te testen

  • De beslissing om eenzijdig te testen moet in de ontwerpfase worden genomen voordat het experiment wordt uitgevoerd

  • Zelfs als we sterke a priori aannames hebben, zijn we er niet helemaal zeker van, anders zouden we geen reden hebben om het onderzoek te doen.

  • Als we in de ontwerpfase een eenzijdige test voorstellen en we zien een resultaat in tegengestelde richting dat statistisch significant zou zijn, kunnen we geen conclusies trekken uit het experiment.

  • In de ontwerpfase hebben we dit resultaat uitgesloten omdat het zo onverwacht is dat het een vals positief moet zijn.

  • Daarom worden eenzijdige tests niet aanbevolen.

Een tweezijdige test kan altijd worden verdedigd en stelt u in staat elke afwijking van \(H_0\) te detecteren en wordt ten zeerste aanbevolen.

Het is nooit toegestaan om een tweezijdige test te veranderen in een eenzijdige test op basis van wat er in de steekproef is waargenomen! Anders wordt de type I-fout van de teststrategie niet correct gecontroleerd.


We illustreren dit in onderstaande simulatiestudie:

  1. correcte tweezijdige test en
  2. eenzijdige test met zijn teken gebaseerd op wat werd waargenomen in de steekproef.
set.seed(115)
mu <- 0
sigma <- 9.0
nSim <- 1000
alpha <- 0.05
n <- 15

pvalsCor <-
  pvalsInCor <-
  array(0,nSim)

for (i in 1:nSim)
{
    x <- rnorm(n, mean = mu, sd = sigma)
    pvalsCor[i] <- t.test(x)$p.value
    if (mean(x) < 0)
        pvalsInCor[i] <- t.test(x, alternative = "less")$p.value else
        pvalsInCor[i] <- t.test(x, alternative = "greater")$p.value
}

mean(pvalsCor < 0.05)
[1] 0.049
mean(pvalsInCor < 0.05)
[1] 0.106
  • Type I-fout correct gecontroleerd op \(\alpha\) voor tweezijdige test.
  • Type I-fout niet correct gecontroleerd wanneer we eenzijdig testen op basis van wat we in de steekproef hebben waargenomen.

6 Nature column over testen

7 Geclusterde metingen

  • Data niet altijd onafhankelijk.
  • Consequenties voor schatten van standaard errors

7.1 Voorbeeld

  • Studiedesign met \(n\) planten

  • Expressie van bepaald gen wordt 2 maal gemeten

  • Men is geïnteresseerd in gemiddelde genexpressie.

  • \(Y_{i1}\) en \(Y_{i2}\) de eerste en tweede meting voor plant \(i=1,...,n\): \[\begin{equation*} \bar Y = \sum_{i=1}^n \frac{Y_{i1}+Y_{i2}}{2n} \end{equation*}\]

  • Stel planten onafhankelijk

  • Eerste en tweede metingen even variabel ()\(\text{Var}(Y_{i1})=\text{Var}(Y_{i2})=\sigma^2\))

  • Variantie op steekproefgemiddelde: \[\begin{eqnarray*} \text{Var}(\bar Y)&=&\sum_{i=1}^n \frac{\text{Var}(Y_{i1}+Y_{i2})}{4n^2} \\ &=&\sum_{i=1}^n \frac{\sigma^2+\sigma^2+2\text{Cor}(Y_{i1},Y_{i2})\sigma^2}{% 4n^2} \\ &=&\frac{\sigma^2}{2n}\{1+\text{Cor}(Y_{1},Y_{2})\} \end{eqnarray*}\]

  • Metingen afkomstig van zelfde plant doorgaans positief met elkaar gecorreleerd zijn

  • \(SE_{\bar Y}\) dus groter dan bij \(2n\) metingen van \(2n\) verschillende planten

  • Gegeven eerste meting \(Y_{i1}\) brengt de tweede meting \(Y_{i2}\) geen volledig nieuwe informatie bij

  • Er is bijgevolg minder informatie beschikbaar om het gemiddelde te schatten dan wanneer alle gegevens van verschillende planten afkomstig waren.

Wat bij twee extremen:

  • Stel dat \(\text{Cor}(Y_{1},Y_{2})=1\) tweede meting geen nieuwe informatie en zelfde nauwkeurigheid als wanneer we alleen de n eerste metingen beschouwen
  • Wanneer \(\text{Cor}(Y_{1},Y_{2})=0\), tweede meting volledig nieuwe informatie en dus eenzelfde nauwkeurigheid als bij 1 meting voor \(2n\) i.p.v. \(n\) verschillende planten. Vermits \[\frac{\sigma^2}{2n}\{1+\text{Cor}(Y_{1},Y_{2})\}\geq \frac{\sigma^2}{2n}\]

Wanneer de correlatie tussen herhaalde genexpressie metingen positief is (hetgeen we verwachten), zal men in de praktijk meer preciese resultaten bekomen door 1 meting te bepalen voor \(2n\) verschillende planten dan door 2 metingen te bepalen voor \(n\) verschillende planten.

  • Als er evenveel herhaalde metingen zijn voor elk subject/experimentele unit (vb plant) dan kan men metingen ook reduceren naar \(n\) onafhankelijke metingen door het gemiddelde te berekenen per experimentele unit.
  • Omdat de gemiddeldes per experimentele unit zijn gebaseerd op evenveel herhaalde metingen zal de precisie van die gemiddeldes hetzelfde zijn.
  • Bij verschillend aantal herhaalde metingen per experimentele unit kan men NIET met gemiddeldes per Exp. unit werken want die hebben anders een verschillende precisie \(longrightarrow\) dan zijn meer geavanceerde methoden nodig!

7.2 Captopril

  • Metingen geclusterd: twee systolische bloeddrukmetingen per patiënt

    • 1 meting voor en
    • 1 meting na het toedienen van captopril.
  • Gemiddelde bloeddrukverandering \(\mu\) schatten a.d.h.v. gegevens \[(Y_{i1} , Y_{i2}),\] voor subjecten \(i = 1, ..., n\).

\[\bar X = \sum_{i=1}^n \frac{Y_{i2}-Y_{i1}}{n}\]

Uit rekenregels voor variantie: \[\begin{eqnarray*} \text{Var}\left[\bar X\right]&=&\sum_{i=1}^n \frac{\text{Var}\left[Y_{i1}-Y_{i2}\right]}{n^2}\\ &=&\sum_{i=1}^n \frac{\sigma^2_1+\sigma^2_2-2\text{Cor}\left[Y_{i1},Y_{i2}\right]\sigma_1\sigma_2}{n^2}\\ &=&\frac{\sigma^2_1+\sigma^2_2-2\text{Cor}\left[Y_{i1},Y_{i2}\right]\sigma_1\sigma_2}{n},\\ \end{eqnarray*}\]

#functie var op een matrix berekent varianties sigma_1^2, sigma_2^2
#covariantie sigma_{12}
vars <- var(captopril[,c("SBPb","SBPa")])
vars
         SBPb     SBPa
SBPb 422.9238 370.7857
SBPa 370.7857 400.1429
cor(captopril$SBPa,captopril$SBPb)
[1] 0.9013312
varXbarDelta <- (vars[1,1]+vars[2,2]-2*vars[1,2])/15
sqrt(varXbarDelta)
[1] 2.330883
  • Metingen heel sterk gecorreleerd. Variantie op het verschil veel lager dan op de originele metingen!

  • alternatieve methode om de standard error te bepalen:

    • gecorreleerde metingen tot 1 meting te reduceren
    • kan enkel voor design met gepaarde metingen (2 metingen per patient)
    • Alle verschillen zijn onafhankelijk.

\[X_{i}=Y_{ai}-Y_{bi}\] - vervolgens standard error op \(\bar X\).

In het captopril voorbeeld wordt de schatting

sd(captopril$deltaSBP)/sqrt(15)
[1] 2.330883
  • Exact dezelfde schatting voor standard error

  • Groot voordeel van design:

    • bloeddrukmetingen voor en na sterk positief gecorreleerd \(\longrightarrow\) variantie van verschil veel lager dan dat op originele bloeddrukmetingen

    • Iedere patiënt dient immers als zijn eigen controle

    • We kunnen variabiliteit in bloeddrukmetingen tussen patiënten uit de analyse verwijderen!

  • Een gepaard experiment is speciale vorm van randomized complete block design:

    • Elke persoon is een blok en

    • Elke behandeling getest blok: een controle bloeddrukmeting en een bloeddrukmeting na toedienen van captopril

    • Er is een grote variabiliteit tussen blokken! \(\longrightarrow\) Bloeddruk hoog voor meestal ook bloeddruk hoog na captopril behandeling.

    • standaarddeviatie in bloeddruk tussen patienten voor toedienen van captopril bedraagt 20.6 mmHg.

    • Effect van captopril schatten binnen patient.

    • Door het blokdesign variabiliteit tussen patiënten uit de analyse weren.

    • Voor een gepaard design kan dat door b.v. analyse op bloeddrukverschillen.

    • Standaard error op bloeddruk verschillen tussen patiënten is inderdaad veel lager 9.03.

    • Voor blok design met meer metingen per blok analyse met meervoudig regressie model (Hoofdstuk 10).

Hoe kunnen we het captopril experiment verder verbeteren?


LS0tCnRpdGxlOiAiNS4gU3RhdGlzdGlzY2hlIGJlc2x1aXR2b3JtaW5nIgphdXRob3I6ICJMaWV2ZW4gQ2xlbWVudCIKZGF0ZTogInN0YXRPbWljcywgR2hlbnQgVW5pdmVyc2l0eSAoaHR0cHM6Ly9zdGF0b21pY3MuZ2l0aHViLmlvKSIKb3V0cHV0OgogICAgaHRtbF9kb2N1bWVudDoKICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZSAgICAKICAgICAgdGhlbWU6IGNvc21vCiAgICAgIHRvYzogdHJ1ZQogICAgICB0b2NfZmxvYXQ6IHRydWUKICAgICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGluY2x1ZGUgPSBUUlVFLCBjb21tZW50ID0gTkEsIGVjaG8gPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UpCmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQojRG8gbm90IHJ1biBkdXJpbmcgdGhlIGxlY3R1cmUgd2hlbiB3ZSB3b3JrIGludGVyYWN0aXZlbHkKc2V0LnNlZWQoMTMxNCkKYGBgCgojIEludHJvZHVjdGlvbgojIyBQb3B1bGF0aW9uCi0gSGV0IGRvZWwgdmFuIGVlbiB3ZXRlbnNjaGFwcGVsaWprIG9uZGVyem9layBpcyBvbSBjb25jbHVzaWVzIHRlIHRyZWtrZW4gb3ZlciBkZSBhbGdlbWVuZSBwb3B1bGF0aWUKCi0gSGllciBiZXN0dWRlcmVuIHdlIGRlIGludmxvZWQgdmFuIENhcHRvcHJpbCBvcCBkZSBibG9lZGRydWsgdmFuIHBhdGnDq250ZW4gbWV0IGh5cHRlcnRlbnNpZS4KCi0gV2UgenVsbGVuIGRhdGEgdmVyemFtZWxlbiBlbiBkZXplIGRhbiBtb2RlbGxlcmVuCgotIFdlIG1vZXRlbiBkZSBvbmRlcnpvZWtzdnJhYWcgYWx0aWpkIHZlcnRhbGVuIG5hYXIgZGUgbW9kZWxwYXJhbWV0ZXJzIG9mIGVlbiBjb21iaW5hdGllIHZhbiBtb2RlbHBhcmFtZXRlcnMuCgotIGJ2LiBoZXQgcG9wdWxhdGllIGdlbWlkZGVsZGUKICAkJEUoWCk9XG11JCQKLSBWZXJtaW5kZXJ0IGRlIGdlbWlkZGVsZGUgYmxvZWRkcnVrIGJpaiBwYXRpw6tudGVuIG1ldCBoeXBlcnRlbnNpZSBuYSB0b2VkaWVuZW4gdmFuIENhcHRvcHJpbD8KCi0tLQoKIyMgT3ZlcnppY2h0CgotIEV4cGVyaW1lbnRlZWwgRGVzaWduICYgRGF0YSBFeHBsb3JhdGllCi0gUHVudHNjaGF0dGVycyAoU2NoYXR0aW5nKQotIEludGVydmFsIHNjaGF0dGVycyAoU3RhdGlzdGlzY2hlIGluZmVyZW50aWUpCi0gSHlwb3RoZXNlIHRlc3RlbiAoU3RhdGlzdGlzY2hlIGluZmVyZW50aWUpCgotLS0KCiMgQ2FwdG9wcmlsIHZvb3JiZWVsZAojIyBFeHBlcmltZW50YWwgZGVzaWduCgotIDE1IHBhdGnDq250ZW4gd2VyZGVuIGF0IHJhbmRvbSBnZXRyb2trZW4gdWl0IGRlIHBvcHVsYXRpZSB2YW4gcGF0acOrbnRlbiBtZXQgaHlwZXJ0ZW5zaWUKLSBwcmUtdGVzdC9wb3N0LXRlc3QgZGVzaWduOiBkZSBzeXN0b2xpc2NoZSBlbiBkaWFzdG9seXNjaGUgYmxvZWRkcnVrIHdvcmRlbiBnZW1ldGVuIHZvb3IgZW4gbmEgdG9lZGllbmVuIHZhbiBDYXB0b3ByaWwuCi0gVm9vcmRlZWw6IFdlIGt1bm5lbiBoZXQgZWZmZWN0IHZhbiBkZSBDYXB0b3ByaWwgdG9lZGllbmluZyBvcCBkZSBibG9lZGRydWsgdmFuIGRlIGluZGl2aWR1ZWxlIHBhdGnDq250ZW4gYmVvb3JkZWxlbi4KLSBOYWRlZWw/CgpgYGB7ciBwb3AyU2FtcDJQb3AsZmlnLmFzcD0uOCwgZmlnLmFsaWduPSdjZW50ZXInLGVjaG89RkFMU0V9CmlmICgicGkiJWluJWxzKCkpIHJtKCJwaSIpCmtvcHZvZXRlcjwtZnVuY3Rpb24oeCx5LGFuZ2xlPTAsbD0uMixjZXguZG90PS41LHBjaD0xOSxjb2w9ImJsYWNrIikKewphbmdsZT1hbmdsZS8xODAqcGkKcG9pbnRzKHgseSxjZXg9Y2V4LmRvdCxwY2g9cGNoLGNvbD1jb2wpCmxpbmVzKGMoeCx4K2wqY29zKC1waS8yK2FuZ2xlKSksYyh5LHkrbCpzaW4oLXBpLzIrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbC8yKmNvcygtcGkvMithbmdsZSkseCtsLzIqY29zKC1waS8yK2FuZ2xlKStsLzQqY29zKGFuZ2xlKSksYyh5K2wvMipzaW4oLXBpLzIrYW5nbGUpLHkrbC8yKnNpbigtcGkvMithbmdsZSkrbC80KnNpbihhbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsLzIqY29zKC1waS8yK2FuZ2xlKSx4K2wvMipjb3MoLXBpLzIrYW5nbGUpK2wvNCpjb3MocGkrYW5nbGUpKSxjKHkrbC8yKnNpbigtcGkvMithbmdsZSkseStsLzIqc2luKC1waS8yK2FuZ2xlKStsLzQqc2luKHBpK2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wqY29zKC1waS8yK2FuZ2xlKSx4K2wqY29zKC1waS8yK2FuZ2xlKStsLzIqY29zKC1waS8yK3BpLzQrYW5nbGUpKSxjKHkrbCpzaW4oLXBpLzIrYW5nbGUpLHkrbCpzaW4oLXBpLzIrYW5nbGUpK2wvMipzaW4oLXBpLzIrcGkvNCthbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsKmNvcygtcGkvMithbmdsZSkseCtsKmNvcygtcGkvMithbmdsZSkrbC8yKmNvcygtcGkvMi1waS80K2FuZ2xlKSksYyh5K2wqc2luKC1waS8yK2FuZ2xlKSx5K2wqc2luKC1waS8yK2FuZ2xlKStsLzIqc2luKC1waS8yLXBpLzQrYW5nbGUpKSxjb2w9Y29sKQp9CgpwYXIobWFyPWMoMCwwLDAsMCksbWFpPWMoMCwwLDAsMCkpCnBsb3QoMCwwLHhsYWI9IiIseWxhYj0iIix4bGltPWMoMCwxMCkseWxpbT1jKDAsMTApLGNvbD0wLHhheHQ9Im5vbmUiLHlheHQ9Im5vbmUiLGF4ZXM9RkFMU0UpCnJlY3QoMCw2LDEwLDEwLGJvcmRlcj0icmVkIixsd2Q9MikKdGV4dCguNSw4LCJwb3B1bGF0aWUiLHNydD05MCxjb2w9InJlZCIsY2V4PTIpCnN5bWJvbHMgKDMsIDgsIGNpcmNsZXM9MS41LCBjb2w9InJlZCIsYWRkPVRSVUUsZmc9InJlZCIsaW5jaGVzPUZBTFNFLGx3ZD0yKQpncmlkPXNlcSgwLDEuMywuMDEpCgpmb3IgKGkgaW4gMTo1MCkKewoJYW5nbGUxPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJYW5nbGUyPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJcmFkaXVzPXNhbXBsZShncmlkLHByb2I9Z3JpZF4yKnBpL3N1bShncmlkXjIqcGkpLHNpemU9MSkKCWtvcHZvZXRlcigzK3JhZGl1cypjb3MoYW5nbGUxLzE4MCpwaSksOCtyYWRpdXMqc2luKGFuZ2xlMS8xODAqcGkpLGFuZ2xlPWFuZ2xlMikKfQp0ZXh0KDcuNSw4LCJFZmZlY3QgdmFuIENhcHRvcHJpbCBpbiBwb3B1bGF0aWUiLGNvbD0icmVkIixjZXg9MS4yKQoKcmVjdCgwLDAsMTAsNCxib3JkZXI9ImJsdWUiLGx3ZD0yKQp0ZXh0KC41LDIsInNhbXBsZSIsc3J0PTkwLGNvbD0iYmx1ZSIsY2V4PTIpCnN5bWJvbHMgKDMsIDIsIGNpcmNsZXM9MS41LCBjb2w9InJlZCIsYWRkPVRSVUUsZmc9ImJsdWUiLGluY2hlcz1GQUxTRSxsd2Q9MikKZm9yIChpIGluIDA6MikKCWZvciAoaiBpbiAwOjQpCnsKCglrb3B2b2V0ZXIoMi4xK2oqKDMuOS0yLjEpLzQsMS4xK2kpCn0KdGV4dCg3LjUsMiwiRWZmZWN0IHZhbiBDYXB0b3ByaWwgaW4gc3RlZWtwcm9lZiIsY29sPSJibHVlIixjZXg9MS4yKQoKYXJyb3dzKDMsNS45LDMsNC4xLGNvbD0iYmxhY2siLGx3ZD0zKQphcnJvd3MoNyw0LjEsNyw1LjksY29sPSJibGFjayIsbHdkPTMpCnRleHQoMS41LDUsIkVYUC4gREVTSUdOICgxKSIsY29sPSJibGFjayIsY2V4PTEuMikKdGV4dCg4LjUsNSwiU0NIQVRURU4gJlxuSU5GRVJFTlRJRSAoMykiLGNvbD0iYmxhY2siLGNleD0xLjIpCnRleHQoNy41LC41LCJEQVRBIEVYUExPUkFUSUUgJlxuQkVTQ0hSSUpWRU5ERSBTVEFUSVNUSUVLICgyKSIsY29sPSJibGFjayIsY2V4PTEuMikKYGBgCgotLS0KCiMjIERhdGEgRXhwbG9yYXRpZSBlbiBCZXNjaHJpanZlbmRlIFN0YXRpc3RpZWsKCmBgYHtyfQpjYXB0b3ByaWwgPC0gcmVhZF9jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9zdGF0T21pY3Mvc2JjMjAvbWFzdGVyL2RhdGEvY2FwdG9wcmlsLnR4dCIpCmhlYWQoY2FwdG9wcmlsKQpzdW1tYXJ5KGNhcHRvcHJpbCkKYGBgCgpgYGB7cn0KY2FwdG9wcmlsVGlkeSA8LQogIGNhcHRvcHJpbCAlPiUKICBnYXRoZXIodHlwZSxicCwtaWQpCgpjYXB0b1N1bSA8LSBjYXB0b3ByaWxUaWR5ICU+JQogIGdyb3VwX2J5KHR5cGUpICU+JQogIHN1bW1hcml6ZSgKICAgIG1lYW4gPSBtZWFuKGJwLG5hLnJtPVRSVUUpLAogICAgc2QgPSBzZChicCxuYS5ybT1UUlVFKSwKICAgIG4gPSBicCAlPiUKICAgICAgaXMubmEgJT4lCiAgICAgIGAhYCAlPiUKICAgICAgc3VtKSAlPiUKICBtdXRhdGUoc2UgPSBzZC9zcXJ0KG4pKQoKY2FwdG9TdW0KCmNhcHRvU3VtICU+JQogIGdncGxvdChhZXMoeD10eXBlLHk9bWVhbikpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPW1lYW4tc2QsIHltYXg9bWVhbitzZCksd2lkdGg9LjIpICsKICB5bGltKDAsMjEwKSArCiAgeWxhYigiYmxvb2QgcHJlc3N1cmUgKG1tSGcpIikKYGBgCgotIERlemUgZmlndXVyIGlzIG5pZXQgaW5mb3JtYXRpZWYhIEhldCB0b29udCBkZSBydXdlIGRhdGEgbmlldCBlbmtlbCBnZW1pZGRlbGRlbiBlbiBkZSBzdGFuZGFhcmQgZGV2aWF0aWUgdm9vciBlZW4gYmxvZWRkcnVrIGthcmFrdGVyaXN0aWVrLgoKYGBge3J9CmNhcHRvcHJpbFRpZHkgJT4lCiAgZ2dwbG90KGFlcyh4PXR5cGUseT1icCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZT1OQSkgKwogIGdlb21fcG9pbnQocG9zaXRpb249ImppdHRlciIpICsKICB5bGltKDAsMjEwKQpgYGAKCldlIHppZW4gZGF0IHZlZWwgdmFuIGRlIHJ1aW10ZSBkaWUgd2VyZCBpbmdlbm9tZW4gZG9vciBkZSBiYXJwbG90IGdlZW4gZ2VnZXZlbnMgYmV2YXQhCgpgYGB7cn0KY2FwdG9wcmlsVGlkeSAlPiUKICBnZ3Bsb3QoYWVzKHg9dHlwZSx5PWJwKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlPU5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbj0iaml0dGVyIikKYGBgCgotIERlemUgcGxvdCB6b3UgaW5mb3JtYXRpZWYgemlqbiBnZXdlZXN0IGFscyBkZSBnZWdldmVucyBvdmVyIHZlcnNjaGlsbGVuZGUgaW5kaXZpZHVlbiB3YXJlbiB2ZXJ6YW1lbGQuCgotIERlIGJsb2VkZHJ1ayB3b3JkdCBlY2h0ZXIgYmlqIGRlemVsZmRlIHBhdGnDq250IGdlbWV0ZW4hCgotIFdlIHp1bGxlbiBlZW4gcGxvdCBtYWtlbiB3YWFyIHdlIGRlIHN5c3RvbGlzY2hlIGJsb2VkZHJ1ayBmaWx0ZXJlbgoKYGBge3J9CmNhcHRvcHJpbFRpZHkgJT4lCiAgZmlsdGVyKHR5cGUlaW4lYygiU0JQYSIsIlNCUGIiKSkgJT4lCiAgbXV0YXRlKHR5cGU9ZmFjdG9yKHR5cGUsbGV2ZWxzPWMoIlNCUGIiLCJTQlBhIikpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dHlwZSx5PWJwKSkgKwogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBpZCkpICsKICBnZW9tX3BvaW50KCkKYGBgCgotIFdlIGhlYmJlbiBnZXBhYXJkZSBkYXRhLiBXZSBrdW5uZW4gaGV0IGVmZmVjdCB2YW4gZGUgYmVoYW5kZWxpbmcgZHVzIG9ubWlkZGVsbGlqayBpbnNjaGF0dGVuIGRvb3IgZGUgYmxvZWRkcnVrIG5hIGJlaGFuZGVsaW5nIHRlIHZlcmdlbGlqa2VuIG1ldCBkZSBibG9lZGRydWsgdsOzw7NyIGRlIGJlaGFuZGVsaW5nLgoKYGBge3J9CmNhcHRvcHJpbCA8LQogIGNhcHRvcHJpbCAlPiUKICBtdXRhdGUoZGVsdGFTQlAgPSBTQlBhIC0gU0JQYikKCmNhcHRvcHJpbCAlPiUKICBnZ3Bsb3QoYWVzKHg9IlN5c3RvbGljIGJsb29kIHByZXNzdXJlIix5PWRlbHRhU0JQKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlPU5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbj0iaml0dGVyIikrCiAgeWxhYigiRGlmZmVyZW5jZSAobW0gbWVyY3VyeSkiKSArCiAgeGxhYigiIikKYGBgCgpgYGB7cn0KY2FwdG9wcmlsICU+JQogIHN1bW1hcml6ZSgKICAgIG1lYW4gPSBtZWFuKGRlbHRhU0JQLG5hLnJtPVRSVUUpLAogICAgc2QgPSBzZChkZWx0YVNCUCxuYS5ybT1UUlVFKSwKICAgIG4gPSBkZWx0YVNCUCAlPiUKICAgICAgaXMubmEgJT4lCiAgICAgIGAhYCAlPiUKICAgICAgc3VtKSAlPiUKICBtdXRhdGUoc2UgPSBzZC9zcXJ0KG4pKQpgYGAKCgotIFByZS10ZXN0L3Bvc3QtdGVzdCBkZXNpZ246IEVmZmVjdCB2YW4gQ2FwdG9wcmlsIGluIGRlIHN0ZWVrcHJvZWYgbWV0ICAkWD1cRGVsdGFfXHRleHR7bmEtdm9vcn0kIQoKLSBIb2UgbW9kZWxsZXJlbiB3ZSAkWD1cRGVsdGFfXHRleHR7bmEtdm9vcn0kIGVuIHNjaGF0dGVuIHdlIGhldCBlZmZlY3QgdmFuIENhcHRvcHJpbD8KCmBgYHtyfQpjYXB0b3ByaWwgJT4lCiAgZ2dwbG90KGFlcyhzYW1wbGU9ZGVsdGFTQlApKSArCiAgc3RhdF9xcSgpICsKICBzdGF0X3FxX2xpbmUoKQpgYGAKCkRlIHN5c3RvbGlzY2hlIGJsb2VkZHJ1ayB2ZXJzY2hpbGxlbiB6aWpuIG9uZ2V2ZWVyIG5vcm1hYWwgdmVyZGVlbGQuCi0tLQoKIyMgU2NoYXR0ZW4KCgotIEdlZW4gc3VzYnRhbnRpw6tsZSBhZndpamtpbmdlbiB2YW4gbm9ybWFsaXRlaXQuCgotIFdlIGt1bm5lbiBhYW5uZW1lbiBkYXQgZGUgdmVyc2NoaWxsZW4gICRYIFxzaW0gTihcbXUsIFxzaWdtYV4yKSQuCgotIEhldCBlZmZlY3QgdmFuIENhcHRvcHJpbCBpbiBkZSBwb3B1bGF0aWUgd29yZHQgd2VlcmdlZ2V2ZW4gZG9vciBoZXQgZ2VtaWRkZWxkZSBibG9lZGRydWsgdmVyc2NoaWwgJFxtdSQuCgotIERlIGdlbWlkZGVsZGUgYmxvZWRkcnVrICRcbXUkIGluIGRlIHBvcHVsYXRpZSBrYW4gd29yZGVuIGdlc2NoYXQgbWV0IGJlaHVscCB2YW4gaGV0IHN0ZWVrcHJvZWZnZW1pZGRlbGRlICRcYmFyIHgkID0gYHIgcm91bmQobWVhbihjYXB0b3ByaWwkZGVsdGFTQlApLDIpYAoKLSBEZSBzdGFuZGFhcmRkZXZpYXRpZSAkXHNpZ21hJCBtZXQgZGUgc3RlZWtwcm9lZnN0YW5kYWFyZGRldmlhdGllICAkXHRleHR7U30kID0gYHIgcm91bmQoc2QoY2FwdG9wcmlsJGRlbHRhU0JQKSwyKWAuCgotIElzIGhldCBlZmZlY3QgZGF0IHdlIGluIGRlIHN0ZWVrcHJvZWYgb2JzZXJ2ZXJlbiBncm9vdCBnZW5vZWcgb20gdGUgY29uY2x1ZGVyZW4gZGF0IGVyIGVlbiBlZmZlY3QgaXMgdmFuIGRlIGNhcHRvcHJpbGJlaGFuZGVsaW5nIG9wIGRlIGJsb2VkZHJ1ayBvcCBwb3B1bGF0aWVuaXZlYXU/CgotIE9uemUgc2NoYXR0aW5nZW4genVsbGVuIHZhbiBzdGVla3Byb2VmIHRvdCBzdGVla3Byb2VmIHZlcmFuZGVyZW4hCgotIEhvZSB6aWpuIGRlIHNjaGF0dGVycyAkXGJhciBYJCBlbiAkUyQgdmVyZGVlbGQ/CgoKIyBQdW50IHNjaGF0dGVyczogaGV0IHN0ZWVrcHJvZWZnZW1pZGRlbGRlCgotIFN0ZWwgZGF0ICRYJCBlZW4gd2lsbGVrZXVyaWdlIHN0ZWVrcHJvZWYgaXMgdWl0IGRlIHBvcHVsYXRpZSBlbiBuZWVtIGFhbiBkYXQgJFggXHNpbSBOKFxtdSxcc2lnbWFeMikkCgotIFNjaGF0ICRcbXUkIG9wIGJhc2lzIHZhbiBkZSBzdGVla3Byb2VmICRYXzEsLi4uLFhfbiQsIGdlYnJ1aWsgbWFrZW5kZSB2YW4gaGV0IHN0ZWVrcHJvZWZnZW1pZGRlbGRlCiAgJCRcYmFyIFggPSBcZnJhY3tYXzErIFhfMisgLi4uICsgWF9ufXtufSA9IFxmcmFje1xzdW1fe2k9MX1ee259IFhfaX17bn0kJCB2YW4gd2lsbGVrZXVyaWdlIHZhcmlhYmVsZW4gJFhfMSxYXzIsIC4uLiwgWF9uJC4KCi0gU3RlZWtwcm9lZiBnZW1pZGRlbGRlICRcYmFyIFgkIGlzIGVlbiB3aWxsZWtldXJpZ2UgdmFyaWFibGUgZGF0IHZhcmllZXJ0IHZhbiBzdGVla3Byb2VmIHRvdCBzdGVla3Byb2VmLgoKLSBCZXN0dWRlZXIgZGUgdGhlb3JldGlzY2hlIHZlcmRlbGluZyB2YW4gaGV0IHN0ZWVrcHJvZWZnZW1pZGRlbGRlIG9tIGluemljaHQgdGUga3JpamdlbgoKICAgIDEuIGluIGhvZSBoZXQgc3RlZWtwcm9lZmdlbWlkZGVsZGUga2FuIHZhcmnDq3JlbiBpbiBlZW4gbmlldXcgZ2VsaWprYWFyZGlnIG9uZGVyem9lawogICAgMi4gaG9lIHZlciAkXGJhciBYJCBrYW4gdmVyc2NoaWxsZW4gdmFuIGhldCBwb3B1bGF0aWVnZW1pZGRlbGRlICRcbXUkCgotLS0KCiMjIE92ZXJ6aWNodAoKCjEuIEhldCBzdGVla3Byb2VmZ2VtaWRkZWxkZSBpcyBvbnZlcnRla2VuZAoyLiBQcmVjaXNpZSB2YW4gc3RlZWtwcm9lZmdlbWlkZGVsZGUKMy4gRGlzdHJpYnV0aWUgdmFuIHN0ZWVrcHJvZWZnZW1pZGRlbGRlCgotLS0KCiMjIEhldCBzdGVla3Byb2VmZ2VtaWRkZWxkZSBpcyBvbnZlcnRla2VuZAoKLSBXZSBrdW5uZW4gaGV0IGVmZmVjdCBpbiBkZSBzdGVla3Byb2VmIHZlcmFsZ2VtZW5lbiBuYWFyIGRlIHBvcHVsYXRpZSBhbHMgZGUgc2NoYXR0aW5nIGluIGRlIHN0ZWVrcHJvZWYgZWVuIGdvZWRlIGJlbmFkZXJpbmcgaXMgdmFuIGRlIHBvcHVsYXRpZXdhYXJkZS4KCi0gRGUgc3RlZWtwcm9lZiBtb2V0IHJlcHJlc2VudGF0aWVmIHppam4gb20gZGUgcmVzdWx0YXRlbiB2YW4gZGUgc3RlZWtwcm9lZiBuYWFyIGRlIHBvcHVsYXRpZSB0ZSBnZW5lcmFsaXNlcmVuCgotIFZlcm1pamQgYmlhcyAoem9kYXQgaGV0IHBvcHVsYXRpZWdlbWlkZGVsZGUgbmlldCBzeXN0ZW1hdGlzY2ggb25kZXIgb2Ygb3ZlcnNjaGF0IHdvcmR0KQoKLSBSYXBwb3J0ZWVyIGhvZSBkZSBzdGVla3Byb2VmIGlzIGdlbm9tZW4hCgotIFJhbmRvbWlzYXRpZSEKCi0gTmVlbSBkZSBwcm9lZnBlcnNvbmVuIHdpbGxla2V1cmlnIHVpdCBkZSBwb3B1bGF0aWUsIHpvZGF0IGVsa2UgcHJvZWZwZXJzb29uIGRlemVsZmRlIGthbnMgaGVlZnQgb20gaW4gZGUgc3RlZWtwcm9lZiB0ZXJlY2h0IHRlIGtvbWVuCgotIFByb2VmcGVyc29uZW4gbWV0IGh5cHRlcnRlbnNpZSB3b3JkZW4gd2lsbGVrZXVyaWcgdWl0IGRlIHBvcHVsYXRpZSBnZW5vbWVuLgoKCi0gRWVudm91ZGlnZSB3aWxsZWtldXJpZ2Ugc3RlZWtwcm9lZjogICRYXzEsLi4uLFhfbiQgdm9vciBrZW5tZXJrICRYJAoKLSAkWF8xLC4uLixYX24kIGhlYmJlbiBkZXplbGZkZSBkaXN0cmlidXRpZQotIFplIGhlYmJlbiBoZXR6ZWxmZGUgZ2VtaWRkZWxkZSAkXG11JCBlbiB2YXJpYW50aWUgJFxzaWdtYV4yJAoKLSAkRShYXzEpPS4uLj1FKFhfbik9XG11JCBlbiAkXHRleHR7VmFyfShYXzEpPS4uLj1cdGV4dHtWYXJ9KFhfbik9XHNpZ21hXjIkCgotICRcYmFyIFgkIGlzIGVlbiAqb3ZlcnRla2VuZGUgc2NoYXR0ZXIqIHZvb3IgJFxtdSQKCjxkZXRhaWxzPjxzdW1tYXJ5PkNsaWNrIHRvIHNlZSBwcm9vZjwvc3VtbWFyeT48cD4KXGJlZ2lue2VxbmFycmF5Kn0KRShcYmFyIFgpICY9JiBFIFxsZWZ0KFxmcmFje1hfMSsgWF8yKyAuLi4gKyBYX259e259XHJpZ2h0KSBcXAomPSAmIFxmcmFje0UoWF8xKSsgRShYXzIpKyAuLi4gKyBFKFhfbil9e259IFxcCiY9JiBcZnJhY3tcbXUgKyBcbXUgKyAuLi4gK1xtdX17bn0gXFwKJj0gJiBcbXUKXGVuZHtlcW5hcnJheSp9CjwvcD48L2RldGFpbHM+CgotLS0KCiMjIEltcHJlY2lzaWUvc3RhbmRhcmQgZXJyb3IKCi0gT29rIHZvb3IgcmVwcmVzZW50YXRpZXZlIHN0ZWVrcHJvZXZlbiB6aWpuIGRlIHJlc3VsdGF0ZW4gb25uYXV3a2V1cmlnClx2c3BhY2V7MTBwdH0KLSBWZXJzY2hpbGxlbmRlIHN0ZWVrcHJvZXZlbiB1aXQgZGV6ZWxmZGUgcG9wdWxhdGllIGdldmVuIHZlcnNjaGlsbGVuZGUgcmVzdWx0YXRlbi4KCi0gV2UgaWxsdXN0cmVyZW4gZGl0IG1ldCBkZSBOSEFORVMgc3R1ZGllCgogICAgLSBXZSB6dWxsZW4gMTUgdnJvdXdlbiB3aWxsZWtldXJpZyBzZWxlY3RlcmVuIHVpdCBkZSBOSEFORVMgc3R1ZGllIGVuIHp1bGxlbiBodW4gbGVuZ3RlIHJlZ2lzdHJlcmVuLgogICAgLSBXZSBoZXJoYWxlbiBkaXQgNTAga2VlciBvbSBkZSB2YXJpYXRpZSB2YW4gc3RlZWtwcm9lZiB0b3Qgc3RlZWtwcm9lZiB0ZSBiZW9vcmRlbGVuCiAgICAtIFdlIHBsb3R0ZW4gZGUgYm94cGxvdCB2b29yIGllZGVyZSBzdGVla3Byb2VmIGVuIGR1aWRlbiBoZXQgZ2VtaWRkZWxkZSBhYW4uCgpgYGB7cn0KbGlicmFyeShOSEFORVMpCgpmZW0gPC0gTkhBTkVTICU+JQogIGZpbHRlcihHZW5kZXI9PSJmZW1hbGUiICYgIWlzLm5hKERpcmVjdENob2wpKSAlPiUKICBzZWxlY3QoIkRpcmVjdENob2wiKQoKbiA8LSAxNSAjIG51bWJlciBvZiBzdWJqZWN0cyBwZXIgc2FtcGxlCm5TaW0gPC0gNTAgIyBudW1iZXIgb2Ygc2ltdWxhdGlvbnMKCmZlbVNhbXAgPC0gbWF0cml4KG5yb3c9bixuY29sPW5TaW0pCmZvciAoaiBpbiAxOm5TaW0pCnsKICBzZXQuc2VlZCgyMTA1KQogIGZlbVNhbXBbLGpdIDwtIHNhbXBsZShmZW0kRGlyZWN0Q2hvbCwxNSkKICBpZiAoajw0KSB7CiAgICBwIDwtIGZlbVNhbXAgJT4lCiAgICAgIGxvZzIgJT4lCiAgICAgIGRhdGEuZnJhbWUgJT4lCiAgICAgIGdhdGhlcigic2FtcGxlIiwibG9nMmNob2xlc3Rlcm9sIikgJT4lCiAgICAgIGdncGxvdChhZXMoeD1zYW1wbGUseT1sb2cyY2hvbGVzdGVyb2wpKSArCiAgICAgIGdlb21fYm94cGxvdCgpICsKICAgICAgc3RhdF9zdW1tYXJ5KAogICAgICAgIGZ1bi55PW1lYW4sCiAgICAgICAgZ2VvbT0icG9pbnQiLAogICAgICAgIHNoYXBlPTE5LAogICAgICAgIHNpemU9MywKICAgICAgICBjb2xvcj0icmVkIiwKICAgICAgICBmaWxsPSJyZWQiKSArCiAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IG1lYW4oZmVtJERpcmVjdENob2wgJT4lIGxvZzIpKSArCiAgICAgIHlsYWIoImNob2xlc3Rlcm9sIChsb2cyKSIpCiAgICBwcmludChwKQogIH0KfQoKZmVtU2FtcCAlPiUKICBsb2cyICU+JQogIGRhdGEuZnJhbWUgJT4lCiAgZ2F0aGVyKCJzYW1wbGUiLCJsb2cyY2hvbGVzdGVyb2wiKSAlPiUKICBnZ3Bsb3QoYWVzKHg9c2FtcGxlLHk9bG9nMmNob2xlc3Rlcm9sKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBzdGF0X3N1bW1hcnkoZnVuLnk9bWVhbiwgZ2VvbT0icG9pbnQiLCBzaGFwZT0xOSwgc2l6ZT0zLCBjb2xvcj0icmVkIiwgZmlsbD0icmVkIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IG1lYW4oZmVtJERpcmVjdENob2wgJT4lIGxvZzIpKSArCiAgeWxhYigiY2hvbGVzdGVyb2wgKGxvZzIpIikKYGBgCgpXZSBvYnNlcnZlcmVuIGRhdCBoZXQgc3RlZWtwcm9lZmdlbWlkZGVsZGUgZmx1Y3R1ZWVydCByb25kIGhldCBnZW1pZGRlbGRlIHZhbiBkZSBwb3B1bGF0aWUuCgpPcGRyYWNodDoKCjEuIEtvcGllZXIgZGUgY29kZQoyLiBWZXJncm9vdCBkZSBzdGVla3Byb2VmZ3Jvb3R0ZSB0b3QgMTAwIHByb2VmcGVyc29uZW4KMy4gV2F0IG9ic2VydmVlciBqZT8KCi0tLQoKKipIb2UgZG9lbiB3ZSBkaXQgb3AgYmFzaXMgdmFuIGVlbiBlbmtlbGUgc3RlZWtwcm9lZj8qKgoKLSBJbnppY2h0IGluIGhvZSBkaWNodCB3ZSAkXGJhciBYJCB0b3QkXG11JCBrdW5uZW4gdmVyd2FjaHRlbj8KCi0gSG9lIHZhcmllZXJ0ICRcYmFyIFgkIHZhbiBzdGVla3Byb2VmIHRvdCBzdGVla3Byb2VmPwoKLSBWYXJpYWJpbGl0ZWl0IG9wICRcYmFyIFgkCgotIERpdCBtb2V0ZW4gd2UgYmVwYWxlbiBvcCBiYXNpcyB2YW4gZWVuIGVua2VsZSBzdGVla3Byb2VmIQoKLSBXZSBtb2V0ZW4gYXNzdW1wdGllcyBtYWtlbgoKLSBXZSBuZW1lbiBhYW4gZGF0IGRlIHdpbGxla2V1cmlnZSB2YXJpYWJlbGVuICRYXzEsIFhfMiwgLi4uLCBYX24kIGFma29tc3RpZyB6aWpuIHZhbiAkbiQgKm9uYWZoYW5rZWxpamtlKiBwZXJzb25lbi4KCi0gVm9vciBkZSBDYXB0b3ByaWwgc3R1ZGllIGhlYmJlbiB3ZSBhZmhhbmtlbGlqa2Ugb2JzZXJ2YXRpZXMKCiAgICAtIEJsb2VkZHJ1a21ldGluZ2VuIHZvb3IgKCRZX3tpLGJlZm9yZX0kKSBlbiBuYSAoJFlfe2ksYWZ0ZXJ9JCkgdG9lZGllbmluZyB2YW4gY2FwdG9wcmlsIGFhbiBkZXplbGZkZSBwYXRpw6tudCAkaT0xLFxsZG90cyxuJC4KICAgIC0gV2UgaGViYmVuIHplIG9tZ2V6ZXQgaW4gbiBvbmFmaGFua2VsaWprZSBtZXRpbmdlbiBkb29yIGhldCB2ZXJzY2hpbCAkWV97aSxuYX0tWV97aSx2b29yfSQgdGUgbmVtZW4uCgotLS0KCiMjIyBWYXJpYW50aWUgc2NoYXR0ZXIgdm9vciAkXGJhciBYJAoKJCRcc2lnbWFeMl97XGJhciBYfT1cZnJhY3tcc2lnbWFeMn17bn0kJAoKLSBEZSBzdGFuZGFhcmRkZXZpYXRpZSB2YW4gJFxiYXIgWCQgcm9uZCAkXG11JCBpcyAkXHNxcnR7bn0kIGtlZXIga2xlaW5lciBkYW4gZGUgZGV2aWF0aWUgcm9uZCBkZSBvcmlnaW5lbGUgb2JzZXJ2YXRpZXMgJFgkLgoKLSBIb2UgbWVlciBvYnNlcnZhdGllcyB3ZSBoZWJiZW4sIGRlcyB0ZSBuYXV3a2V1cmlnZXIgJFxiYXIgWCQuCgoKPGRldGFpbHM+PHN1bW1hcnk+Q2xpY2sgdG8gc2VlIHByb29mPC9zdW1tYXJ5PjxwPgpcYmVnaW57ZXFuYXJyYXkqfQpcdGV4dHtWYXJ9KFxiYXIgWCkmPSZcdGV4dHtWYXJ9IFxsZWZ0KFxmcmFje1hfMSsgWF8yKyAuLi4gKyBYX259e259XHJpZ2h0KSBcXAomXG92ZXJzZXR7Kn17PX0gJiBcZnJhY3tcdGV4dHtWYXJ9KFhfMSkrIFx0ZXh0e1Zhcn0oWF8yKSsgLi4uICsgXHRleHR7VmFyfShYX24pfXtuXjJ9IFxcCiY9JiBcZnJhY3tcc2lnbWFeMiArIFxzaWdtYV4yICsgLi4uIFxzaWdtYV4yfXtuXjJ9IFxcCiY9ICYgXGZyYWN7XHNpZ21hXjJ9e259LgpcZW5ke2VxbmFycmF5Kn0KCi0gKCopIERpdCBpcyBnZWJhc2VlcmQgb3AgZGUgYXNzdW1wdGllIHZhbiBvbmFmaGFua2VsaWpraGVpZAokJFx0ZXh0e1Zhcn1bYSBYXzEgKyBiIFhfMl0gPSBhXjJcdGV4dHtWYXJ9W1hfMV0gKyBiXjIgXHRleHR7VmFyfVtYXzJdICsgMiBhYlx0ZXh0e0NvdmFyfVtYXzEsWF8yXSQkCgogICAgLSBNZXQgJENvdmFyW1hfMSxYXzJdPTAkIHdhbm5lZXIgJFhfMSQgZW4gJFhfMiQgb25hZmhhbmtlbGlqayB6aWpuLgo8L3A+PC9kZXRhaWxzPnMKCioqRGVmaW5pdGllOiBzdGFuZGFhcmQgZXJyb3IqKgoKRGUgc3RhbmRhYXJkIGRldmlhdGllIHZhbiAkXGJhcntYfSQgaXMgJFxzaWdtYS9cc3FydHtufSQgZW4gd29yZHQgb29rIHdlbCBkZSAqKnN0YW5kYWFyZCBlcnJvcioqIHZhbiBoZXQgZ2VtaWRkZWxkZSBnZW5vZW1kLgpPdmVyIGhldCBhbGdlbWVlbiB2ZXJ3aWpzdCBtZW4gbmFhciBkZSBzdGFuZGFhcmRkZXZpYXRpZSB2YW4gZWVuIHNjaGF0dGVyIHZvb3IgZWVuIGJlcGFhbGRlIHBhcmFtZXRlciAkXHRoZXRhJCBtZXQgZGUgdGVybSAqKnN0YW5kYWFyZCBlcnJvcioqIHZhbiBkZSBzY2hhdHRlciBkaWUgd29yZHQgYWFuZ2VkdWlkIGFscyAkU0UkCgotLS0KCiMjIyBDYXB0b3ByaWwgdm9vcmJlZWxkCgoKLSAkbiA9IDE1JCB2ZXJzY2hpbGxlbiBpbiBzeXN0b2xpc2NoZSBibG9lZGRydWsKCi0gU3RlbCBkYXQgZGUgc3RhbmRhYXJkZGV2aWF0aWUgdmFuIGRlIGJsb2VkZHJ1a3ZlcnNjaGlsbGVuIGluIGRlIHBvcHVsYXRpZSAkXHNpZ21hID0gOS4wJCBtbUhnIGlzCgotIERhbiB3b3JkdCBkZSBzdGFuZGFhcmQgZXJyb3IgKFNFKSBvcCBkZSBnZW1pZGRlbGRlIHN5c3RvbGlzY2hlIGJsb2VkZHJ1ayB2ZXJzY2hpbGxlbiAkXGJhciBYJDoKCiQkClNFID0gXGZyYWN7OS4wfXtcc3FydHsxNX19PTIuMzJcdGV4dHttbUhnLn0KJCQKCi0gT3ZlciBoZXQgYWxnZW1lZW4gemlqbiAkXHNpZ21hJCwgZW4gZHVzIGRlIFNFIG9wIGhldCBzdGVla3Byb2VmZ2VtaWRkZWxkZSBvbmJla2VuZC4KLSBXZSBtb2V0ZW4gZHVzIG9vayBkZSBzdGFuZGFhcmRkZXZpYXRpZSB2YW4gZGUgc3RlZWtwcm9lZiBzY2hhdHRlbiBvbSBkZSBzdGFuZGFhcmQgZXJyb3IgdGUgdmVya3Jpamdlbi4KLSBTY2hhdHRlcjogJFNFPVMvXHNxcnR7bn0sJAotIE1ldCAkU14yJCBkZSBzdGVla3Byb2VmdmFyaWFudGllIHZhbiAkWF8xLC4uLixYX24kICBlbiAkUyQgZGUgc3RlZWtwcm9lZnN0YW5kYWFyZGRldmlhdGllCgotIFZvb3IgaGV0IENhcHRvcHJpbCB2b29yYmVlbGQga3JpamdlbiB3ZToKCmBgYHtyfQpuIDwtIGxlbmd0aChjYXB0b3ByaWwkZGVsdGFTQlApCnNlIDwtIHNkKGNhcHRvcHJpbCRkZWx0YVNCUCkvc3FydChuKQpzZQpgYGAKCi0tLQoKIyMjIHN0YW5kYWFyZGRldmlhdGllIHZzIHN0YW5kYWFyZCBlcnJvcgoKIyMjIyBJbGx1c3RyYXRpZSB2aWEgaGVyaGFhbGRlIHN0ZWVrcHJvZXZlbgoKLSBWZXJzY2hpbGxlbmRlIHN0ZWVrcHJvZWYgZ3Jvb3R0ZXM6IDEwLCA1MCwgMTAwCi0gTmVlbSAxMDAwIHN0ZWVrcHJvZXZlbiBwZXIgc3RlZWtwcm9lZiBncm9vdHRlIHZhbiBkZSBOSEFORVMgc3R1ZGllLCB2b29yIGllZGVyZSBzdGVla3Byb2VmIGJlcmVrZW5lbiB3ZToKICAgIC0gSGV0IGdlbWlkZGVsZGUKICAgIC0gRGUgc3RlZWtwcm9lZnN0YW5kYWFyZGRldmlhdGllCiAgICAtIGRlIHN0YW5kYWFyZCBlcnJvcgotIFdlIG1ha2VuIGVlbiBib3hwbG90IHZhbiBkZSBzdGVla3Byb2Vmc3RhbmRhYXJkZXZhdGllcyBlbiBkZSBzdGFuZGFhcmQgZXJyb3JzIHZvb3IgZGUgdmVyc2NoaWxsZW5kZSBzdGVla3Byb2VmZ3Jvb3R0ZXMKCi0gSW4gcGxhYXRzIHZhbiBlZW4gZm9yIGxvb3AgdGUgZ2VicnVpa2VuIHp1bGxlbiB3ZSBkZSBzYXBwbHkgZnVuY3RpZSBnZWJydWlrZW4gZGllIGVmZmljacOrbnRlciBpcy4gSGV0IG5lZW10IGVlbiB2ZWN0b3Igb2YgbGlqc3QgYWxzIGludm9lciBlbiBwYXN0IGRlIGZ1bmN0aWUgdG9lIG9wIGllZGVyIGVsZW1lbnQgdmFuIGRlIHZlY3RvciBvZiBsaWpzdC4KCmBgYHtyfQpzZXQuc2VlZCgyNCkKZmVtU2FtcDEwIDwtIHNhcHBseSgKICAxOjEwMDAsCiAgZnVuY3Rpb24oaix4LHNpemUpIHNhbXBsZSh4LHNpemUpLAogIHNpemU9MTAsCiAgeD1mZW0kRGlyZWN0Q2hvbCkKCmZlbVNhbXA1MCA8LSBzYXBwbHkoCiAgMToxMDAwLAogIGZ1bmN0aW9uKGoseCxzaXplKSBzYW1wbGUoeCxzaXplKSwKICBzaXplPTUwLAogIHg9ZmVtJERpcmVjdENob2wpCgpmZW1TYW1wMTAwIDwtIHNhcHBseSgKICAxOjEwMDAsCiAgZnVuY3Rpb24oaix4LHNpemUpIHNhbXBsZSh4LHNpemUpLAogIHNpemU9MTAwLAogIHg9ZmVtJERpcmVjdENob2wpCgpyZXM8LXJiaW5kKAogIGZlbVNhbXAxMCAlPiUKICAgIGxvZzIlPiUKICAgIGFzLmRhdGEuZnJhbWUgJT4lCiAgICBnYXRoZXIoc2FtcGxlLGxvZzJDaG9sKSAlPiUKICAgIGdyb3VwX2J5KHNhbXBsZSklPiUKICAgIHN1bW1hcml6ZV9hdCgibG9nMkNob2wiLAogICAgICAgICAgICAgICBsaXN0KG1lZGlhbj1+bWVkaWFuKC4sbmEucm09VFJVRSksCiAgICAgICAgICAgICAgICAgICAgbWVhbj1+bWVhbiguLG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgIHNkPX5zZCguLG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgIG49ZnVuY3Rpb24oeCkgeCU+JWlzLm5hJT4lYCFgJT4lc3VtKSkgJT4lCiAgICBtdXRhdGUoc2U9c2Qvc3FydChuKSkgLAoKICBmZW1TYW1wNTAgJT4lCiAgICBsb2cyICU+JSAgCiAgICBhcy5kYXRhLmZyYW1lICU+JQogICAgZ2F0aGVyKHNhbXBsZSxsb2cyQ2hvbCkgJT4lCiAgICBncm91cF9ieShzYW1wbGUpJT4lCiAgICBzdW1tYXJpemVfYXQoImxvZzJDaG9sIiwKICAgICAgICAgICAgICAgbGlzdChtZWRpYW49fm1lZGlhbiguLG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgIG1lYW49fm1lYW4oLixuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgICBzZD1+c2QoLixuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgICBuPWZ1bmN0aW9uKHgpIHglPiVpcy5uYSU+JWAhYCU+JXN1bSkpICU+JQogICAgbXV0YXRlKHNlPXNkL3NxcnQobikpLAoKICBmZW1TYW1wMTAwICU+JQogICAgbG9nMiAlPiUKICAgIGFzLmRhdGEuZnJhbWUgJT4lCiAgICBnYXRoZXIoc2FtcGxlLGxvZzJDaG9sKSAlPiUKICAgIGdyb3VwX2J5KHNhbXBsZSklPiUKICAgIHN1bW1hcml6ZV9hdCgibG9nMkNob2wiLAogICAgICAgICAgICAgICBsaXN0KG1lZGlhbj1+bWVkaWFuKC4sbmEucm09VFJVRSksCiAgICAgICAgICAgICAgICAgICAgbWVhbj1+bWVhbiguLG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgIHNkPX5zZCguLG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgIG49ZnVuY3Rpb24oeCkgeCU+JWlzLm5hJT4lYCFgJT4lc3VtKSkgJT4lCiAgICBtdXRhdGUoc2U9c2Qvc3FydChuKSkKICApCmBgYAoKKipHZW1pZGRlbGRlbioqCgpXZSBpbGx1c3RyZXJlbiBkZSBpbXBhY3QgdmFuIHN0ZWVrcHJvZWZncm9vdHRlIG9wIGRlIGRpc3RyaWJ1dGllIHZhbiBkZSBnZW1pZGRlbGRlcyB2YW4gdmVyc2NoaWxsZW5kZSBzdGVla3Byb2V2ZW4KCgpgYGB7cn0KcmVzICU+JQogIGdncGxvdChhZXMoeD0gbiAlPiUgYXMuZmFjdG9yLHkgPSBtZWFuKSkgKwogIGdlb21fYm94cGxvdCgpICsKICB5bGFiKCJEaXJlY3QgY2hvbGVzdGVyb2wgKGxvZzIpIikgKwogIHhsYWIoInNhbXBsZSBzaXplIikKYGBgCgotIE1lcmsgb3AgZGF0IGRlIHZhcmlhdGllIHZhbiBkZSBzdGVla3Byb2VmZ2VtaWRkZWxkZW4gaW5kZXJkYWFkIGFmbmVlbXQgbmFhcm1hdGUgZGUgc3RlZWtwcm9lZmdyb290dGUgdG9lbmVlbXQuIERlIHNjaGF0dGluZyB3b3JkdCBkdXMgbmF1d2tldXJpZ2VyIG5hYXJtYXRlIGRlIHN0ZWVrcHJvZWZncm9vdHRlIHRvZW5lZW10LgoKLS0tCgoqKlN0YW5kYXJkIGRldmlhdGllKioKCldlIGlsbHVzdHJlcmVuIG51IGRlIGltcGFjdCB2YW4gZGUgc3RlZWtwcm9lZmdyb290dGUgb3AgZGUgdmVyZGVsaW5nIHZhbiBkZSBzdGFuZGFhcmRkZXZpYXRpZSB2YW4gZGUgdmVyc2NoaWxsZW5kZSBzdGVla3Byb2V2ZW4KCmBgYHtyfQpyZXMgJT4lCiAgZ2dwbG90KGFlcyh4PW4lPiVhcy5mYWN0b3IseT1zZCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgeWxhYigic3RhbmRhcmQgZGV2aWF0aW9uIikgKwogIHhsYWIoInNhbXBsZSBzaXplIikKYGBgCgotIERlIHN0YW5kYWFyZGRldmlhdGllIGJsaWpmdCB2ZXJnZWxpamtiYWFyIHZvb3IgZGUgc3RlZWtwcm9lZmdyb290dGVzLgpIZXQgaXMgZ2VjZW50cmVlcmQgcm9uZCBkZXplbGZkZSB3YWFyZGU6IGRlIHN0YW5kYWFyZGRldmlhdGllIGluIGRlIHBvcHVsYXRpZS4gSGV0IHZlcmdyb3RlbiB2YW4gZGUgc3RlZWtwcm9lZmdyb290dGUgaGVlZnQgaW5kZXJkYWFkIGdlZW4gaW52bG9lZCBvcCBkZSB2YXJpYWJpbGl0ZWl0IGluIGRlIHBvcHVsYXRpZSEKCi0gT3BuaWV1dyB6aWVuIHdlIGRhdCBkZSB2YXJpYWJpbGl0ZWl0IHZhbiBkZSBzdGFuZGFhcmRkZXZpYXRpZSBhZm5lZW10IG5hYXJtYXRlIGRlIHN0ZWVrcHJvZWZncm9vdHRlIHRvZW5lZW10LiBEZSBzdGFuZGFhcmRkZXZpYXRpZSBrYW4gZHVzIG9vayBuYXV3a2V1cmlnZXIgd29yZGVuIGdlc2NoYXQgbmFhcm1hdGUgZGUgc3RlZWtwcm9lZmdyb290dGUgdG9lbmVlbXQuCgotLS0KCioqU3RhbmRhYXJkIGVycm9yIHZhbiBoZXQgZ2VtaWRkZWxkZSoqCgpUZW4gc2xvdHRlIGlsbHVzdHJlcmVuIHdlIGRlIGltcGFjdCB2YW4gZGUgc3RlZWtwcm9lZmdyb290dGUgb3AgZGUgdmVyZGVsaW5nIHZhbiBkZSBzdGFuZGFhcmRkZXZpYXRpZSB2YW4gaGV0IGdlbWlkZGVsZGUgdmFuIGRlIHZlcnNjaGlsbGVuZGUgc3RlZWtwcm9ldmVuLCBkZSBzdGFuZGFhcmQgZXJyb3IuCgpgYGB7cn0KcmVzICU+JQpnZ3Bsb3QoYWVzKHg9biU+JWFzLmZhY3Rvcix5PXNlKSkgKwpnZW9tX2JveHBsb3QoKSArCnlsYWIoInN0YW5kYXJkIGVycm9yIikgKwp4bGFiKCJzYW1wbGUgc2l6ZSIpCmBgYAoKLSBEZSBzdGFuZGFhcmQgZXJyb3IgKGRlIHNjaGF0dGVyIHZvb3IgZGUgbmF1d2tldXJpZ2hlaWQgdmFuIGhldCBzdGVla3Byb2VmZ2VtaWRkZWxkZSkgdmVybWluZGVydCBhYW56aWVubGlqayBuYWFybWF0ZSBkZSBzdGVla3Byb2VmZ3Jvb3R0ZSB0b2VuZWVtdCwgd2F0IG9wbmlldXcgYmV2ZXN0aWd0IGRhdCBkZSBzY2hhdHRpbmcgdmFuIGhldCBzdGVla3Byb2VmZ2VtaWRkZWxkZSBuYXV3a2V1cmlnZXIgd29yZHQuCgotLS0KCiMjIyBOb3JtYWFsIHZlcmRlZWxkZSBkYXRhCgotIFZvb3Igbm9ybWFhbCB2ZXJkZWVsZGUgZGF0YSBoZWJiZW4gd2UgbWVlcmRlcmUgc2NoYXR0ZXJzIHZvb3IgaGV0IHBvcHVsYXRpZWdlbWlkZGVsZGUgJFxtdSQgYnYuIGdlbWlkZGVsZGUgZW4gbWVkaWFhbi4KCi0gTWFhciAkXGJhcntYfSQgaXMgZGUgb3ZlcnRla2VuZGUgc2NoYXR0ZXIgdmFuICRcbXUkIG1ldCBkZSBrbGVpbnN0ZSBzdGFuZGFhcmQgZXJyb3IKCi0gICRcYmFye1h9JCB3aWprdCBtaW5kZXIgYWYgdmFuIGhldCBnZW1pZGRlbGRlICRcbXUkIGRhbiBkZSBtZWRpYWFuCgotIFdlIGlsbHVzdHJlcmVuIGRpdCB2b29yIGhlcmhhYWxkZSBzdGVla3Byb2V2ZW4gbWV0IHN0ZWVrcHJvZWZncm9vdHRlIDEwCgpgYGB7cn0KcmVzICU+JQogIGZpbHRlcihuID09IDEwKSAlPiUKICBzZWxlY3QobWVhbixtZWRpYW4pICU+JQogIGdhdGhlcih0eXBlLGVzdGltYXRlKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB0eXBlLHkgPSBlc3RpbWF0ZSkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gZmVtJERpcmVjdENob2wgJT4lCiAgICBsb2cyICU+JQogICAgbWVhbikgKwogIGdndGl0bGUoIjEwIHBlcnNvbmVuIikKYGBgCgpWZXJ2b2xnZW5zIHZlcmdlbGlqa2VuIHdlIGRlIHZlcmRlbGluZyB2YW4gaGV0IGdlbWlkZGVsZGUgZW4gZGUgbWVkaWFhbiBpbiBoZXJoYWFsZGUgc3RlZWtwcm9ldmVuIHZhbiBzdGVla3Byb2VmZ3Jvb3R0ZSA1MC4KCmBgYHtyfQpyZXMgJT4lCiAgZmlsdGVyKG4gPT0gNTApICU+JQogIHNlbGVjdChtZWFuLCBtZWRpYW4pICU+JQogIGdhdGhlcih0eXBlLCBlc3RpbWF0ZSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdHlwZSx5ID0gZXN0aW1hdGUpKSArCiAgZ2VvbV9ib3hwbG90KCkrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gZmVtJERpcmVjdENob2wgJT4lCiAgICBsb2cyICU+JQogICAgbWVhbikgKwogIGdndGl0bGUoIjUwIHBlcnNvbmVuIikKYGBgCgojIyBWZXJkZWxpbmcgdmFuIGhldCBzdGVla3Byb2VmZ2VtaWRkZWxkZQoKCi0gSG9lIHZhcmllZXJ0ICRcYmFyIFgkIHZhbiBzdGVla3Byb2VmIHRvdCBzdGVla3Byb2VmPwotIFZlcmRlbGluZyB2YW4gJFxiYXIgWCQ/Ci0gQWxzICRcYmFyIFgkIG5vcm1hYWwgdmVyZGVlbGQgaXMsIGhlZWZ0IGRlIHN0YW5kYWFyZCBlcnJvciBlZW4gZ29lZGUgaW50ZXJwcmV0YXRpZTogZGUgU0UgaXMgZGUgc3RhbmRhYXJkIGRldmlhdGllIHZhbiBoZXQgc3RlZWtwcm9lZmdlbWlkZGVsZGUuCi0gQWxzIGRlIGRhdGEgJFhfaSQgbm9ybWFhbCB2ZXJkZWVsZCB6aWpuLCBpcyBoZXQgc3RlZWtwcm9lZmdlbWlkZGVsZGUgb29rIG5vcm1hYWwgdmVyZGVlbGQuCgokJFhfaSBcc2ltIE4oXG11LFxzaWdtYV4yKSBccmlnaHRhcnJvdyAgXGJhciBYIFxzaW0gTihcbXUsICBcc2lnbWFeMi9uKSQkCgotLS0KCiMjIyBOSEFORVM6IGNob2xlc3Rlcm9sCgpXZSBpbGx1c3RyZXJlbiBkaXQgbm9nbWFhbHMgbWV0IGVlbiBzaW11bGF0aWUgZ2VicnVpayBtYWtlbmRlIHZhbiBkZSBOSEFORVMtc3R1ZGllLgpEZSBsb2cyLWNob2xlc3Rlcm9sd2FhcmRlbiB6aWpuIG5vcm1hYWwgdmVyZGVlbGQuCgpgYGB7cn0KIGZlbSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBEaXJlY3RDaG9sICU+JSBsb2cyKSkrCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiwgZmlsbCA9IC4uY291bnQuLikpICsKICB4bGFiKCJEaXJlY3QgY2hvbGVzdGVyb2wgKGxvZzIpIikgKwogIHN0YXRfZnVuY3Rpb24oCiAgICBmdW4gPSBkbm9ybSwKICAgIGNvbG9yID0gInJlZCIsCiAgICBhcmdzID0gbGlzdCgKICAgICAgbWVhbj1tZWFuKGZlbSREaXJlY3RDaG9sJT4lbG9nMiksCiAgICAgIHNkID0gc2QoZmVtJERpcmVjdENob2wlPiVsb2cyKQogICAgICApCiAgICApICsKICBnZ3RpdGxlKCJBbGxlIHZyb3V3ZW4gaW4gTkhBTkVTIHN0dWRpZSIpCgpmZW0gJT4lCiAgZ2dwbG90KGFlcyhzYW1wbGUgPSBEaXJlY3RDaG9sICU+JSBsb2cyKSkgKwogIHN0YXRfcXEoKSArCiAgc3RhdF9xcV9saW5lKCkgKwogIGdndGl0bGUoIkFsbGUgdnJvdXdlbiBpbiBOSEFORVMgc3R1ZHkiKQpgYGAKCi0tLQoKIyMjIyMgRXZhbHVlZXIgZGUgdmVyZGVsaW5nIHZhbiBoZXQgZ2VtaWRkZWxkZSB2b29yIHN0ZWVrcHJvZXZlbiB2YW4gZ3Jvb3R0ZSAxMAoKV2Ugb25kZXJ6b2VrZW4gZGUgcmVzdWx0YXRlbiB2b29yIGRlIHN0ZWVrcHJvZWZncm9vdHRlIHZhbiAxMC4KCldlIGJla2lqa2VuIGVlcnN0IGRlIHBsb3Qgdm9vciBkZSBlZXJzdGUgc3RlZWtwcm9lZi4KCmBgYHtyfQpmZW1TYW1wMTBbLDFdICU+JQogIGxvZzIgJT4lCiAgYXMuZGF0YS5mcmFtZSAlPiUKICBnZ3Bsb3QoYWVzKHg9LikpKwogICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHk9Li5kZW5zaXR5Li4sIGZpbGw9Li5jb3VudC4uKSxiaW5zPTEwKSArCiAgICB4bGFiKCJEaXJlY3QgY2hvbGVzdGVyb2wgKGxvZzIpIikgKwogICAgc3RhdF9mdW5jdGlvbigKICAgICAgZnVuPWRub3JtLAogICAgICBjb2xvcj0icmVkIiwKICAgICAgYXJncz1saXN0KAogICAgICAgIG1lYW49ZmVtU2FtcDEwWywxXSU+JWxvZzIlPiVtZWFuLCBzZD1mZW1TYW1wMTBbLDFdJT4lbG9nMiU+JXNkKQogICAgICApICsKICAgIGdndGl0bGUoIjEwIHJhbmRvbSBmZW1hbGVzIikgKwogICAgeGxpbShmZW0kRGlyZWN0Q2hvbCAlPiUgbG9nMiAlPiUgcmFuZ2UpCmBgYAoKVmVydm9sZ2VucyBraWprZW4gd2UgbmFhciBkZSB2ZXJkZWxpbmcgdmFuIGhldCBzdGVla3Byb2VmZ2VtaWRkZWxkZSBvdmVyIDEwMDAgc3RlZWtwcm9ldmVuIHZhbiBzdGVla3Byb2VmZ3Jvb3R0ZSAxMC4KCmBgYHtyfQpmZW1TYW1wMTAgJT4lCiAgbG9nMiAlPiUKICBjb2xNZWFucyAlPiUKICBhcy5kYXRhLmZyYW1lICU+JQogIGdncGxvdChhZXMoeD0uKSkgKwogIGdlb21faGlzdG9ncmFtKGFlcyh5PS4uZGVuc2l0eS4uLCBmaWxsPS4uY291bnQuLiksYmlucz0xNSkgKwogIHhsYWIoIk1lYW4gY2hvbGVzdGVyb2wgKGxvZzIpIikgKwogIHN0YXRfZnVuY3Rpb24oCiAgICBmdW49ZG5vcm0sCiAgICBjb2xvcj0icmVkIiwKICAgIGFyZ3M9bGlzdCgKICAgICAgbWVhbj1mZW1TYW1wMTAlPiVsb2cyJT4lIGNvbE1lYW5zICU+JSBtZWFuLAogICAgICBzZD1mZW1TYW1wMTAlPiVsb2cyJT4lIGNvbE1lYW5zICU+JSBzZCkKICAgICkgKwogIGdndGl0bGUoIk1lYW5zIG9uIDEwIGZlbWFsZXMiKQoKZmVtU2FtcDEwICU+JQogIGxvZzIlPiUKICBjb2xNZWFucyAlPiUKICBhcy5kYXRhLmZyYW1lICU+JSAgCiAgZ2dwbG90KGFlcyhzYW1wbGU9LikpICsKICBzdGF0X3FxKCkgKwogIHN0YXRfcXFfbGluZSgpICsKICBnZ3RpdGxlKCJNZWFucyBvbiAxMCBmZW1hbGVzIikKYGBgCgoqKldlIGhlYmJlbiBkdXMgYmV2ZXN0aWdkIGRhdCBoZXQgZ2VtaWRkZWxkZSBvbmdldmVlciBub3JtYWFsIHZlcmRlZWxkIGlzIHZvb3Igc3R1ZGllcyBtZXQgNSBlbiAxMCB2cm91d2VuLCB0ZXJ3aWpsIGRlIG9yaWdpbmVsZSBnZWdldmVucyBvbmdldmVlciBub3JtYWFsIHZlcmRlZWxkIHppam4uKioKCi0tLQoKIyMjIyBDYXB0b3ByaWwgc3R1ZGllCgotIERlIHN5c3RvbGlzY2hlIGJsb2VkZHJ1a3ZlcnNjaGlsbGVuIGluIGRlIENhcHRvcHJpbCBzdHVkaWUgemlqbiBiaWogYmVuYWRlcmluZyBub3JtYWFsIHZlcmRlZWxkLgoKLSBzLmUuPSAyLjMyIG1tIEhnCgotIEluIDk1IHZhbiBkZSAxMDAgc3R1ZGllcyBtZXQgbiA9IDE1IHByb2VmcGVyc29uZW4gdmVyd2FjaHRlbiB3ZSBkYXQgaGV0IHN0ZWVrcHJvZWZnZW1pZGRlbGRlIHZhbiBkZSBzeXN0b2xpc2NoZSBibG9lZGRydWt2ZXJzY2hpbGxlbiAoJFxiYXIgWCQpIG9wIG1pbmRlciBkYW4gJDIgXHRpbWVzIDIuMzIgPSA0LjY0JG1tIEhnIHZhbiBoZXQgd2Vya2VsaWprIHBvcHVsYXRpZWdlbWlkZGVsZGUgdmFuIGRlIGJsb2VkZHJ1a3ZlcnNjaGlsbGVuIGdlc2NoYXQgd29yZHQuCgotLS0KCiMjIyBOaWV0LW5vcm1hYWwgdmVyZGVlbGRlIGRhdGEKCi0gQWxzIGluZGl2aWR1ZWxlIG9ic2VydmF0aWVzIGdlZW4gbm9ybWFsZSB2ZXJkZWxpbmcgaGViYmVuLCAgaXMgJFxiYXIgWCQgbm9nIHN0ZWVkcyBcdGV4dGl0e29uZ2V2ZWVyfSBub3JtYWFsIHZlcmRlZWxkCndhbm5lZXIgaGV0IGFhbnRhYWwgb2JzZXJ2YXRpZXMgZ3Jvb3QgZ2Vub2VnIGlzLgoKLSBIb2UgZ3Jvb3QgbW9ldCBkZSBzdGVla3Byb2VmIHppam4gb20gZGUgbm9ybWFsZSBiZW5hZGVyaW5nIHRlIGxhdGVuIHdlcmtlbj8KCi0gRGl0IGhhbmd0IGFmIHZhbiBkZSBzY2hlZWZoZWlkIHZhbiBkZSBkaXN0cmlidXRpZSEKCi0tLQoKIyMjIyBOSEFORVM6IGNob2xlc3Rlcm9sCgotIFdlIGt1bm5lbiBkaXQgZXZhbHVlcmVuIGluIGRlIE5IYW5lcy1zdHVkaWUgYWxzIHdlIGRlIGdlZ2V2ZW5zIG5pZXQgbG9nMiB0cmFuc2Zvcm1lcmVuLgoKYGBge3J9CmZlbSAlPiUKICAgZ2dwbG90KGFlcyh4PURpcmVjdENob2wpKSsKICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHk9Li5kZW5zaXR5Li4sIGZpbGw9Li5jb3VudC4uKSkgKwogICB4bGFiKCJEaXJlY3QgY2hvbGVzdGVyb2wiKSArCiAgIHN0YXRfZnVuY3Rpb24oCiAgICAgZnVuPWRub3JtLAogICAgIGNvbG9yPSJyZWQiLAogICAgIGFyZ3M9bGlzdCgKICAgICAgIG1lYW49bWVhbihmZW0kRGlyZWN0Q2hvbCksCiAgICAgICBzZD1zZChmZW0kRGlyZWN0Q2hvbCkpCgogICAgKSArCiAgIGdndGl0bGUoIkFsbCBmZW1hbGVzIGluIE5oYW5lcyBzdHVkeSIpCgogZmVtICU+JQogIGdncGxvdChhZXMoc2FtcGxlPURpcmVjdENob2wpKSArCiAgc3RhdF9xcSgpICsKICBzdGF0X3FxX2xpbmUoKSArCiAgZ2d0aXRsZSgiQWxsIGZlbWFsZXMgaW4gTmhhbmVzIHN0dWR5IikKYGBgCgpEZSBjaG9sZXN0ZXJvbCBkYXRhIHppam4gZHVpZGVsaWprIG5pZXQtbm9ybWFhbCB2ZXJkZWVsZC4KCiMjIyMjIFZlcmRlbGluZyB2YW4gaGV0IHN0ZWVrcHJvZWZnZW1pZGRlbGRlIHZvb3IgdmVyc2NoaWxsZW5kZSBzdGVla3Byb2VmZ3Jvb3R0ZXMKCmBgYHtyfQpzZXQuc2VlZCgxMjEpCmZlbVNhbXA1IDwtIHNhcHBseSgKICAxOjEwMDAsCiAgZnVuY3Rpb24oaix4LHNpemUpIHNhbXBsZSh4LHNpemUpLAogIHNpemUgPSA1LAogIHggPSBmZW0kRGlyZWN0Q2hvbCkKCmZlbVNhbXA1ICU+JQogIGNvbE1lYW5zICU+JQogIGFzLmRhdGEuZnJhbWUgJT4lIGdncGxvdChhZXMoeD0uKSkgKwogIGdlb21faGlzdG9ncmFtKGFlcyh5PS4uZGVuc2l0eS4uLCBmaWxsPS4uY291bnQuLiksYmlucz0xNSkgKwogIHhsYWIoIk1lYW4gY2hvbGVzdGVyb2wiKSArCiAgc3RhdF9mdW5jdGlvbigKICAgIGZ1bj1kbm9ybSwKICAgIGNvbG9yPSJyZWQiLAogICAgYXJncz1saXN0KAogICAgICBtZWFuPWZlbVNhbXA1JT4lIGNvbE1lYW5zICU+JSBtZWFuLAogICAgICBzZD1mZW1TYW1wNSU+JSBjb2xNZWFucyAlPiUgc2QpCiAgICApICsKICBnZ3RpdGxlKCJNZWFucyBvbiA1IGZlbWFsZXMiKQoKZmVtU2FtcDUgJT4lCiAgY29sTWVhbnMgJT4lCiAgYXMuZGF0YS5mcmFtZSAlPiUgIAogIGdncGxvdChhZXMoc2FtcGxlPS4pKSArCiAgc3RhdF9xcSgpICsKICBzdGF0X3FxX2xpbmUoKSArCiAgZ2d0aXRsZSgiTWVhbnMgb24gNSBmZW1hbGVzIikKCgpmZW1TYW1wMTAgJT4lCiAgY29sTWVhbnMgJT4lCiAgYXMuZGF0YS5mcmFtZSAlPiUgZ2dwbG90KGFlcyh4PS4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHk9Li5kZW5zaXR5Li4sIGZpbGw9Li5jb3VudC4uKSxiaW5zPTE1KSArCiAgeGxhYigiTWVhbiBjaG9sZXN0ZXJvbCIpICsKICBzdGF0X2Z1bmN0aW9uKAogICAgZnVuPWRub3JtLAogICAgY29sb3I9InJlZCIsCiAgICBhcmdzPWxpc3QoCiAgICAgIG1lYW49ZmVtU2FtcDEwJT4lIGNvbE1lYW5zICU+JSBtZWFuLAogICAgICBzZD1mZW1TYW1wMTAlPiUgY29sTWVhbnMgJT4lIHNkKQogICAgKSArCmdndGl0bGUoIk1lYW5zIG9uIDEwIGZlbWFsZXMiKQoKZmVtU2FtcDEwICU+JQogIGNvbE1lYW5zICU+JQogIGFzLmRhdGEuZnJhbWUgJT4lICAKICBnZ3Bsb3QoYWVzKHNhbXBsZT0uKSkgKwogIHN0YXRfcXEoKSArCiAgc3RhdF9xcV9saW5lKCkgKwogIGdndGl0bGUoIk1lYW5zIG9uIDEwIGZlbWFsZXMiKQoKZmVtU2FtcDUwICU+JQogIGNvbE1lYW5zICU+JQogIGFzLmRhdGEuZnJhbWUgJT4lICAKICBnZ3Bsb3QoYWVzKHNhbXBsZT0uKSkgKwogIHN0YXRfcXEoKSArCiAgc3RhdF9xcV9saW5lKCkgKwogIGdndGl0bGUoIk1lYW5zIG9uIDUwIGZlbWFsZXMiKQoKZmVtU2FtcDEwMCAlPiUKICBjb2xNZWFucyAlPiUKICBhcy5kYXRhLmZyYW1lICU+JSAgCiAgZ2dwbG90KGFlcyhzYW1wbGU9LikpICsKICBzdGF0X3FxKCkgKwogIHN0YXRfcXFfbGluZSgpICsKICBnZ3RpdGxlKCJNZWFucyBvbiAxMDAgZmVtYWxlcyIpCmBgYAoKLSAqKldlIG1lcmtlbiBvcCBkYXQgd2FubmVlciBkZSBkYXRhIG5pZXQgbm9ybWFhbCB2ZXJkZWVsZCB6aWpuLCBkZSB2ZXJkZWxpbmcgdmFuIGhldCBzdGVla3Byb2VmZ2VtaWRkZWxkZSBuaWV0IG5vcm1hYWwgdmVyZGVlbGQgaXMgb3ZlciBrbGVpbmUgc3RlZWtwcm9ldmVuKioKCi0gKipWb29yIGdyb3RlIHN0ZWVrcHJvZXZlbiBpcyBoZXQgc3RlZWtwcm9lZmdlbWlkZGVsZGUgdmFuIG5pZXQtbm9ybWFsZSBnZWdldmVucyBlY2h0ZXIgbm9nIHN0ZWVkcyBvbmdldmVlciBub3JtYWFsIHZlcmRlZWxkLioqCgotLS0KCiMjIyBDZW50cmFsZSBsaW1pZXRzdGVsbGluZwoKTGFhdCAkWF8xLCBcbGRvdHMsIFhfbiQgZWVuIHJlZWtzIHdpbGxla2V1cmlnZSB2YXJpYWJlbGVuIHppam4gZGllIG9uYWZoYW5rZWxpamsgdmFuIGRlemVsZmRlIHZlcmRlbGluZyAocG9wdWxhdGllKSB3b3JkZW4gZ2V0cm9ra2VuLiBab2xhbmcgZGUgc3RlZWtwcm9lZmdyb290dGUgbiB2b2xkb2VuZGUgZ3Jvb3QgaXMsIGlzIGhldCBzdGVla3Byb2VmZ2VtaWRkZWxkZSAkXGJhciBYJCBvbmdldmVlciBub3JtYWFsIHZlcmRlZWxkLCBvbmdlYWNodCBkZSB2ZXJkZWxpbmcgdmFuIGRlIHdhYXJuZW1pbmdlbiAkWF9pJC4KCiMjIyBPdmVyemljaHQgdmFuIGRlIHZlcmRlbGluZyB2YW4gaGV0IGdlbWlkZGVsZGUKCiFbXShodHRwczovL3d3dy5uYXR1cmUuY29tL2FydGljbGVzL25tZXRoLjI2MTMucGRmKXt3aWR0aD0xMDAlfQoKLS0tCgojIEludGVydmFsIHNjaGF0dGVycwoKLSAkXGJhciBYJCB2YXJpZWVydCByb25kICRcbXUkCgotIGhpZXIgenVsbGVuIHdlIGVlbiBpbnRlcnZhbCBvbnR3aWtrZWxlbiByb25kICRcYmFyIFgkIGRhdCBkZSB3YWFyZGUgJFxtdSQgYmV2YXQgbWV0IGVlbiB3YWFyc2NoaWpubGlqa2hlaWQgdmFuIDk1JSB2b29yIGVlbiB3aWxsZWtldXJpZ2Ugc3RlZWtwcm9lZi4KCi0gV2UgbmVtZW4gZWVyc3QgYWFuIGRhdCAkXHNpZ21hXjIkIGJla2VuZCBpcyBlbiB3ZSB6dWxsZW4gZGV6ZSBhYW5uYW1lIGxhdGVyIHZlcnNvZXBlbGVuLgoKLS0tCgojIyBOb3JtYWFsIHZlcmRlZWxkZSBkYXRhIG1ldCBnZWtlbmRlIHZhcmlhbnRpZQoKLSAkWFxzaW0gTihcbXUsXHNpZ21hXjIpIFxyaWdodGFycm93IFxiYXIgWFxzaW0gTlxsZWZ0KFxtdSxcZnJhY3tcc2lnbWFeMn17bn1ccmlnaHQpJAoKLSA5NSUgcmVmZXJlbnRpZS1pbnRlcnZhbCB2b29yIGhldCBzdGVla3Byb2VmZ2VtaWRkZWxkZQoKXGJlZ2lue2VxdWF0aW9uKn0KXGxlZnRbXG11IC0gMS45NiBcZnJhY3tcc2lnbWF9e1xzcXJ0e259fSxcbXUgKyAxLjk2IFxmcmFje1xzaWdtYX17XHNxcnR7bn19JQpccmlnaHRdClxlbmR7ZXF1YXRpb24qfQoKLSBIZXQgaW50ZXJ2YWwgYmV2YXQgaGV0IHN0ZWVrcHJvZWZnZW1pZGRlbGRlIHZhbiBlZW4gd2lsbGVrZXVyaWdlIHN0ZWVrcHJvZWYgbWV0IGVlbiBrYW5zIHZhbiA5NSUuCgotIFdlIGt1bm5lbiBkaXQgbmlldCBiZXJla2VuZW4gYWFuZ2V6aWVuICRcbXUkIG5pZXQgZ2VrZW5kIGlzLgoKLSBTY2hhdCAkXG11JCBtZXQgJFxiYXIgWCQuICAKXGJlZ2lue2VxdWF0aW9uKn0KXGxlZnRbXGJhciBYIC0gMS45NiBcZnJhY3tcc2lnbWF9e1xzcXJ0e259fSxcYmFyIFggKyAxLjk2IFxmcmFje1xzaWdtYX17XHNxcnR7bn19XHJpZ2h0XQpcZW5ke2VxdWF0aW9uKn0KCgotIE1lZXIgYnJ1aWtiYXJlIGludGVycHJldGF0aWU6Clx2c3BhY2V7MTVwdH0KLSBoZXJzY2hyaWpmICRcbXUgLSAxLjk2IFwgXHNpZ21hL1xzcXJ0e259IDwgXGJhcntYfSQgYXMgJFxtdSA8IFxiYXJ7WH0gKyAxLjk2IFwgXHNpZ21hL1xzcXJ0e259JC4KClpvZGF0IHdlIGt1bm5lbiBzY2hyaWp2ZW4KXGJlZ2lue2VxbmFycmF5Kn0KOTVcJSAmPSYgUCggXG11IC0gMS45NiBcIFxzaWdtYS9cc3FydHtufSA8IFxiYXJ7WH0gPCBcbXUgKyAxLjk2IFwgXHNpZ21hL1xzcXJ0e259ICkgXFwKJj0mUCggXGJhcntYfSAtIDEuOTYgXCBcc2lnbWEvXHNxcnR7bn0gPCBcbXUgPCBcYmFye1h9ICsgMS45NiBcIFxzaWdtYS9cc3FydHtufSApClxlbmR7ZXFuYXJyYXkqfQoKLS0tCgoqKkRlZmluaXRpZSB2YW4gOTUlIGJldHJvdXdiYWFyaGVpZHMgaW50ZXJ2YWwgb3AgaGV0IGdlbWlkZGVsZGUqKgpWb29yIGVlbiB3aWxsZWtldXJpZ2Ugc3RlZWtwcm9lZiBiZXZhdCBoZXQgaW50ZXJ2YWwKXGJlZ2lue2VxdWF0aW9ufSAgCltcYmFye1h9IC0gMS45NiBcIFxzaWdtYS9cc3FydHtufSAsIFxiYXJ7WH0gKyAxLjk2IFwgXHNpZ21hL1xzcXJ0e259IF0sClxlbmR7ZXF1YXRpb259CmhldCBwb3B1bGF0aWVnZW1pZGRlbGRlICRcbXUkIG1ldCBlZW4ga2FucyB2YW4gOTUlLgoKLS0tCgotIERlIGthbnMgZGF0IGhldCBCSSB2b29yIGVlbiB3aWxsZWtldXJpZ2Ugc3RlZWtwcm9lZiBkZSBwb3B1bGF0aWVwYXJhbWV0ZXIKICRcbXUkIGJldmF0LCBkdXMgOTUlLCB3b3JkdCBvb2sgd2VsIGhldCAqKmJldHJvdXdiYWFyaGVpZHNuaXZlYXUqKiBnZW5vZW1kLgoKLSBNZXJrIG9wIGRhdCBkZSBvbmRlci0gZW4gYm92ZW5ncmVucyB2YW4gaGV0IGludGVydmFsIG9vayB3aWxsZWtldXJpZ2UgdmFyaWFiZWxlbiB6aWpuIGRpZSB2YW4gc3RlZWtwcm9lZiB0b3Qgc3RlZWtwcm9lZiB2YXJpw6tyZW4uIFZlcnNjaGlsbGVuZGUgc3RlZWtwcm9ldmVuIHJlc3VsdGVyZW4gaW5kZXJkYWFkIGluIHZlcnNjaGlsbGVuZGUgYmV0cm91d2JhYXJoZWlkc2ludGVydmFsbGVuIG9tZGF0IHplIGdlYmFzZWVyZCB6aWpuIG9wIHZlcnNjaGlsbGVuZGUgd2Fhcm5lbWluZ2VuLgoKLSBIZXQgemlqbiBkdXMgKnN0b2NoYXN0aXNjaGUgaW50ZXJ2YWxsZW4qCgotIDk1JSB2YW4gZGUgc3RlZWtwcm9ldmVuIHp1bGxlbiBlZW4gOTUlIGJldHJvdXdiYWFyaGVpZHNpbnRlcnZhbCBwcm9kdWNlcmVuIGRhdCBoZXQgcG9wdWxhdGllZ2VtaWRkZWxkZSAkXG11JCB6YWwgYmV2YXR0ZW4uIERlIG92ZXJpZ2UgNSUgenVsbGVuIGludGVydmFsbGVuIHByb2R1Y2VyZW4gZGllIGhldCBwb3B1bGF0aWVnZW1pZGRlbGRlIG5pZXQgYmV2YXR0ZW4uCgotIE9wIGJhc2lzIHZhbiDDqcOpbiBpbnRlcnZhbCBrdW4gamUgbmlldCBjb25jbHVkZXJlbiBkYXQgaGV0IGRlIHdlcmtlbGlqa2UgcG9wdWxhdGllcGFyYW1ldGVyIGJldmF0LCBvbWRhdCBkZSB3YWFyZGUgZXJ2YW4gb25iZWtlbmQgaXMuCgpPdmVyIGhldCBhbGdlbWVlbiBpcyBkZSBzdGFuZGFhcmRkZXZpYXRpZSBvbmdla2VuZCBlbiBtb2V0IGhldCBnZXNjaGF0IHdvcmRlbi4KCi0gVm9vciBncm90ZSAkbiQsIHphbCAkW1xiYXJ7WH0gLSAxLjk2IFwgcy9cc3FydHtufSAsIFxiYXJ7WH0gKyAxLjk2IFwgcy9cc3FydHtufSBdJCBoZXQgcG9wdWxhdGllZ2VtaWRkZWxkZSBiZXZhdHRlbiBtZXQgZWVuIHByb2JhYmlsaXRlaXQgdmFuIDk1JS4KCi0tLQoKIyMjIE5IQU5FUyBsb2cyIGNob2xlc3Rlcm9sIHZvb3JiZWVsZAoKIyMjIyAxIHN0ZWVrcHJvZWYKCmBgYHtyfQpzZXQuc2VlZCgzMTQ2KQpzYW1wNTAgPC0gc2FtcGxlKGZlbSREaXJlY3RDaG9sLDUwKQoKbGwgPC0gbWVhbihzYW1wNTAgJT4lIGxvZzIpIC0gMS45NipzZChzYW1wNTAgJT4lIGxvZzIpL3NxcnQoNTApCnVsIDwtIG1lYW4oc2FtcDUwICU+JSBsb2cyKSArIDEuOTYqc2Qoc2FtcDUwICU+JSBsb2cyKS9zcXJ0KDUwKQpwb3BNZWFuIDwtIG1lYW4oZmVtJERpcmVjdENob2wlPiVsb2cyKQoKYyhsbD1sbCx1bD11bCxwb3BNZWFuPXBvcE1lYW4pCmBgYAoKIyMjIyBIZXJoYWFsZGUgc3RlZWtwcm9ldmVuCgpgYGB7cn0KcmVzJGxsIDwtIHJlcyRtZWFuLTEuOTYqcmVzJHNlCnJlcyR1bCA8LSByZXMkbWVhbisxLjk2KnJlcyRzZQptdSA8LSBmZW0kRGlyZWN0Q2hvbCU+JQogIGxvZzIlPiUKICBtZWFuCgpyZXMkaW5zaWRlPC0gcmVzJGxsIDw9IG11ICYgbXUgPD0gcmVzJHVsCnJlcyRuIDwtIGFzLmZhY3RvcihyZXMkbikKcmVzICU+JQogIGdyb3VwX2J5KG4pICU+JQogIHN1bW1hcml6ZShjb3ZlcmFnZT1tZWFuKGluc2lkZSkpICU+JQogIHNwcmVhZChuLGNvdmVyYWdlKQpgYGAKCi0gTWVyayBvcCBkYXQgZGUgb212YW5nIGluIGRlIHN0ZWVrcHJvZXZlbiBtZXQgMTAgd2Fhcm5lbWluZ2VuIHRlIGxhYWcgaXMgb21kYXQgd2UgZ2VlbiByZWtlbmluZyBob3VkZW4gbWV0IGRlIG9uemVrZXJoZWlkIGluIGRlIHNjaGF0dGluZyB2YW4gZGUgc3RhbmRhYXJkZGV2aWF0aWUuCgotIEFscyB3ZSBraWprZW4gbmFhciBkZSBlZXJzdGUgMjAgaW50ZXJ2YWxsZW4sIGJldmF0IGByIHN1bSgoIXJlc1tyZXMkbj09MTAsImluc2lkZSJdKVsxOjIwXSlgICB2YW4gZGUgMjAgbmlldCBoZXQgcG9wdWxhdGllZ2VtaWRkZWxkZS4KCmBgYHtyfQpyZXMgJT4lCiAgZmlsdGVyKG49PTEwKSAlPiUKICBzbGljZSgxOjIwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzYW1wbGUseSA9IG1lYW4sY29sb3IgPSBpbnNpZGUpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbi0xLjk2KnNlLHltYXggPSBtZWFuKzEuOTYqc2UpKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBmZW0kRGlyZWN0Q2hvbCAlPiUgbG9nMiAlPiUgbWVhbikgKwogIGdndGl0bGUoIjIwIENJIGZvciBOID0gMTAiKSArCiAgeWxpbShyYW5nZShmZW0kRGlyZWN0Q2hvbCAlPiUgbG9nMikpCmBgYAoKLS0tCgotIFZvb3IgZ3JvdGUgc3RlZWtwcm9ldmVuICgxMDApIGlzIGRlIG9tdmFuZyBwcmltYSBvbWRhdCB3ZSBkZSBzdGFuZGFhcmRkZXZpYXRpZSBtZXQgZWVuIHJlbGF0aWVmIGhvZ2UgcHJlY2lzaWUga3VubmVuIHNjaGF0dGVuLgoKYGBge3J9CnJlcyAlPiUKICBmaWx0ZXIobiA9PSA1MCkgJT4lCiAgc2xpY2UoMToyMCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2FtcGxlLHkgPSBtZWFuLGNvbG9yID0gaW5zaWRlKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG1lYW4tMS45NipzZSx5bWF4ID0gbWVhbisxLjk2KnNlKSkrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gZmVtJERpcmVjdENob2wgJT4lIGxvZzIgJT4lIG1lYW4pICsKICBnZ3RpdGxlKCIyMCBDSSBmb3IgTiA9IDUwIikgKwogIHlsaW0ocmFuZ2UoZmVtJERpcmVjdENob2wgJT4lIGxvZzIpKQoKcmVzICU+JQogIGZpbHRlcihuID09IDEwMCkgJT4lCiAgc2xpY2UoMToyMCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2FtcGxlLHkgPSBtZWFuLGNvbG9yID0gaW5zaWRlKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG1lYW4tMS45NipzZSx5bWF4ID0gbWVhbisxLjk2KnNlKSkrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gZmVtJERpcmVjdENob2wgJT4lIGxvZzIgJT4lIG1lYW4pICsKICBnZ3RpdGxlKCIyMCBDSSBmb3IgTiA9IDEwMCIpICsKICB5bGltKHJhbmdlKGZlbSREaXJlY3RDaG9sICU+JSBsb2cyKSkKYGBgCgotIFdhdCBoZWIgamUgZ2VvYnNlcnZlZXJkIHZvb3IgZGUgaW50ZXJ2YWxicmVlZHRlPwoKLS0tCgojIyMgQW5kZXJlIGJldHJvdXdiYWFyaGVpZHNuaXZlYXVzCgotIFdlIGt1bm5lbiAkel97Mi41XCV9PTEuOTYkIHZlcnZhbmdlbiBkb29yIGVlbiBhbmRlciBrd2FudGllbCB2YW4gZGUgbm9ybWFsZSB2ZXJkZWxpbmcgJHpfe1xhbHBoYS8yfSBvbSBlZW4gaW50ZXJ2YWwgdGUga3JpamdlbiBtZXQgZWVuIGFuZGVyIGJldHJvdXdiYWFyaGVpZHNuaXZlYXUgJDEtXGFscGhhJC4KCi0gQmV0cm91d2JhYXJoZWlkc2ludGVydmFsbGVuIHdvcmRlbiBuaWV0IGFsbGVlbiBnZWJydWlrdCB2b29yIGhldCBnZW1pZGRlbGRlLCBtYWFyIG9vayB2b29yIGFuZGVyZSBwb3B1bGF0aWVwYXJhbWV0ZXJzLgoKLS0tCgojIyBPbmdla2VuZGUgdmFyaWFudGllCgpJbiBlY2h0ZSB2b29yYmVlbGRlbiBpcyAkXHNpZ21hJCBvbmdla2VuZCBlbiB3b3JkdCBoZXQgZ2VzY2hhdCBvcCBiYXNpcyB2YW4gZGUgc3RlZWtwcm9lZiBtZXQgYmVodWxwIHZhbiBkZSBzdGFuZGFhcmRkZXZpYXRpZSAkUyQuCgotIERlIHZvcmlnZSBpbnRlcnZhbGxlbiB3YXJlbiBpZXRzIHRlIGtsZWluIG9tZGF0IHplIGdlZW4gcmVrZW5pbmcgaGllbGRlbiBtZXQgZGUgb256ZWtlcmhlaWQgb3ZlciBkZSBzY2hhdHRpbmcgdmFuICRTJC4KCi0gQWxzICRuJCBncm9vdCBpcywgbGlndCAkUyQgaW4gZGUgYnV1cnQgdmFuICRcc2lnbWEkLgoKLSBWYW5kYWFyIGRhdCAkeyhcYmFye1h9IC0gXG11KX0veyhTL1xzcXJ0e259KSB9JCBvbmdldmVlciBzdGFuZGFhcmQgbm9ybWFhbCB2ZXJkZWVsZCBpcyBlbgpcYmVnaW57ZXF1YXRpb24qfQpcbGVmdFtcYmFye1h9IC0gel97XGFscGhhLzJ9IFwgXGZyYWN7U317XHNxcnR7bn19ICwgXGJhcntYfSArIHpfe1xhbHBoYS8yfSBcClxmcmFje1N9e1xzcXJ0e259fVxyaWdodF0KXGVuZHtlcXVhdGlvbip9CmlzIGVlbiBnZXNjaGF0dGUgJCgxLSBcYWxwaGEpMTAwXCUkIENJIHZvb3IgJFxtdSQuCgotIFZvb3Iga2xlaW5lIHN0ZWVrcHJvZXZlbiBnZWxkdCBkaXQgbmlldCBtZWVyIChlLmcuIG49MTApCgpEZSBzY2hhdHRpbmcgdmFuICRTJCBpbnRyb2R1Y2VlcnQgZXh0cmEgb256ZWtlcmhlaWQgaW4gZGUgZ2VzdGFuZGFhcmRpc2VlcmRlIHdhYXJkZSAkeyhcYmFye1h9IC0gXG11KX0veyhTL1xzcXJ0e259KX0kLiBaaWpuIGRpc3RyaWJ1dGllCgotIGlzIG5vZyBzdGVlZHMgc3ltbWV0cmlzY2ggbWFhciBoZWVmdCB6d2FhcmRlcmUgc3RhYXJ0ZW4gZGFuIGRlIG5vcm1hbGUgdmVyZGVsaW5nLgoKLSBIZXQgaGFuZ3QgdmFuICRuJCBhZiBob2V2ZWVsIHp3YWFyZGVyIGRlIHN0YWFydGVuIHppam4KCi0gaXMgZWVuIChTdHVkZW50KSAkdCQtdmVyZGVsaW5nIG1ldCAkbi0xJCAqdnJpamhlaWRzZ3JhZGVuKi4KCi0tLQoKIyMjIFQtdmVyZGVsaW5nCgpGb3JtZWVsOiBMZXQgJFhfMSwgWF8yLCAuLi4sIFhfbiQgZWVuIG9uYWZoYW5rZWxpamtlIHdpbGxla2V1cmlnZSBzdGVla3Byb2VmIHppam4gdWl0IGVlbiBub3JtYWxlIHZlcmRlbGluZyAkTihcbXUsIFxzaWdtYV4yKSQsIGRhbiB2b2xndCAkKFxiYXJ7WH0gLSBcbXUpLyhTL1xzcXJ0e259KSQgZWVuICR0JC12ZXJkZWxpbmcgbWV0ICRuLTEkIHZyaWpoZWlkc2dyYWRlbi4KCkRlIGRlbnNpdGVpdCB2YW4gZWVuIHQtdmVyZGVsaW5nIGthbiB3b3JkZW4gYmVyZWtlbmQgaW4gUiBtZXQgZGUgZnVuY3RpZSBgZHRgLiBIZXQgaGVlZnQgYXJndW1lbnRlbiAneCcgdm9vciBoZXQga3dhbnRpZWwgZW4gJ2RmJyB2b29yIGRlIHZyaWpoZWlkc2dyYWRlbi4KCmBgYHtyfQpncmlkIDwtIHNlcSgtNSw1LC4xKQpkZW5zRGlzdCA8LSBjYmluZChncmlkLGRub3JtKGdyaWQpLCBzYXBwbHkoYygyLDUsMTApLGR0LHg9Z3JpZCkpCmNvbG5hbWVzKGRlbnNEaXN0KSA8LSBjKCJ4Iiwibm9ybWFsIixwYXN0ZTAoInQiLGMoMiw1LDEwKSkpCgpkZW5zRGlzdCAlPiUKICBhcy5kYXRhLmZyYW1lICU+JQogIGdhdGhlcihkaXN0LGRlbnMsLXgpICU+JQogIGdncGxvdChhZXMoeD14LHk9ZGVucyxjb2xvcj1kaXN0KSkgKwogIGdlb21fbGluZSgpICsKICB4bGFiKCJ4IikgKwogIHlsYWIoIkRlbnNpdGVpdCIpCmBgYAoKCnQtdmVyZGVsaW5nZW4gaGViYmVuIHp3YWFyZGVyZSBzdGFhcnRlbiBkYW4gZGUgbm9ybWFsZSB2ZXJkZWxpbmcgJFxyaWdodGFycm93JCBncm90ZXJlIGthbnRpZWxlbiwgZHVzIGJyZWRlcmUgaW50ZXJ2YWxsZW4gdm9vciBoZXR6ZWxmZGUgYmV0cm91d2JhYXJoZWlkc25pdmVhdS4KCi0gRGl0IGdlZWZ0IGRlIGV4dHJhIG9uemVrZXJoZWlkIHdlZXIgdm9vciBoZXQgc2NoYXR0ZW4gdmFuICRTJC4KCi0gQWxzICRuIFxyaWdodGFycm93IFxpbmZ0eSQgZGFuICR0KGRmKSBccmlnaHRhcnJvdyBOKDAsMSkkCgoKLSBrd2FudGllbGVuIHZhbiBkZSAkdCQtdmVyZGVsaW5nIGt1bm5lbiB3b3JkZW4gYmVyZWtlbmQgaW4gUiBtZXQgYmVodWxwIHZhbiBgcXRgLiBidi4gOTUlLCA5Ny41JSwgOTkuNSUga3dhbnRpZWwgdm9vciBlZW4gdC12ZXJkZWxpbmcgbWV0IDE0IHZyaWpoZWlkc2dyYWRlbi4KYGBge3J9CnF0KC45NzUsZGY9MTQpCnF0KGMoLjk1LC45NzUsLjk5NSksZGY9MTQpCmBgYAoKLSBEZXplIGt3YW50aWVsZW4ga3VubmVuIGdlYnJ1aWt0IHdvcmRlbiBvbSBkZSA5MCUsIDk1JSBhbmQgOTklIENJIHRlIGJlcmVrZW5lbi4KCi0gOTcuNSUga3dhbnRpZWxgciByb3VuZChxdCguOTc1LGRmPTE0KSwyKWAgdmFuIGVlbiB0LXZlcmRlbGluZyBtZXQgJG4tMT0xNCQgdnJpamhlaWRzZ3JhZGVuIGlzIGluZGVyZGFhZCBncm90ZXIgZGFuIGRpZSB2YW4gZWVuIHN0YW5kYWFyZCBub3JtYWxlIHZlcmRlbGluZyBgciByb3VuZChxbm9ybSguOTc1KSwyKWAuCgotLS0KIyMjIEJldHJvdXdiYWFyaGVpZHNpbnRlcnZhbCBnZWJhc2VlcmQgb3AgZGUgdC12ZXJkZWxpbmcKCkRlICQxMDBcJSAoMS1cYWxwaGEpJCBDSSB2b29yIGhldCBnZW1pZGRlbGRlICRcbXUkIHZhbiBlZW4gbm9ybWFhbCB2ZXJkZWVsZGUgd2lsbGVrZXVyaWdlIHZhcmlhYmVsZSAkWCQgbWV0IG9uZ2VrZW5kZSB2YXJpYW50aWUgaXMKClxiZWdpbntlcXVhdGlvbip9ClxsZWZ0W1xiYXJ7WH0gLSB0X3tuLTEsIFxhbHBoYS8yfSBcZnJhY3tzfXtcc3FydHtufX0gLCBcYmFye1h9ICsgdF97bi0xLApcYWxwaGEvMn0gXGZyYWN7c317XHNxcnR7bn19XHJpZ2h0XQpcZW5ke2VxdWF0aW9uKn0KCi0gV2UgdmVydmFuZ2VuIGVlbnZvdWRpZyBoZXQgJCgxLVxhbHBoYS8yKTEwMFwlJCBrd2FudGllbCB2YW4gZGUgbm9ybWFsZSB2ZXJkZWxpbmcgZG9vciBkaWUgdmFuIGRlIHQtdmVyZGVsaW5nIG1ldCAkbi0xJCB2cmlqaGVpZHNncmFkZW4uCgojIyMgQ2FwdG9wcmlsIHZvb3JiZWVsZAoKCjk1JSBDSSB2b29yIGRlIGdlbWlkZGVsZGUgYmxvZWRkcnVrdmVyYW5kZXJpbmcgd29yZHQKCmBgYHtyfQptZWFuKGNhcHRvcHJpbCRkZWx0YVNCUCkgLSAgcXQoLjk3NSxkZj0xNCkqc2QoY2FwdG9wcmlsJGRlbHRhU0JQKS9zcXJ0KDE1KQptZWFuKGNhcHRvcHJpbCRkZWx0YVNCUCkgKyBxdCguOTc1LGRmPTE0KSpzZChjYXB0b3ByaWwkZGVsdGFTQlApL3NxcnQoMTUpCmBgYAoKSGV0IDk5JSBDSSBpcyBnZWdldmVuIGRvb3IKYGBge3J9Cm1lYW4oY2FwdG9wcmlsJGRlbHRhU0JQKSAtICBxdCguOTk1LGRmPTE0KSpzZChjYXB0b3ByaWwkZGVsdGFTQlApL3NxcnQoMTUpCm1lYW4oY2FwdG9wcmlsJGRlbHRhU0JQKSArIHF0KC45OTUsZGY9MTQpKnNkKGNhcHRvcHJpbCRkZWx0YVNCUCkvc3FydCgxNSkKYGBgCgpNZXJrIG9wIGRhdCBudWwgYnVpdGVuIGhldCBpbnRlcnZhbCBsaWd0IGVuIGRhdCBoZXQgZ2VoZWxlIGludGVydmFsIG5lZ2F0aWVmIGlzLCB3YXQgYWFuZ2VlZnQgZGF0IGVyIGdlbWlkZGVsZCBlZW4gZ3Jvb3QgZWZmZWN0IGlzIHZhbiBoZXQgdG9lZGllbmVuIHZhbiBjYXB0b3ByaWwgb3AgZGUgYmxvZWRkcnVrIHZhbiBwYXRpw6tudGVuIG1ldCBoeXBlcnRlbnNpZS4KCi0tLQoKIyMjIEludGVycHJldGF0aWUgdmFuIGhldCBiZXRyb3V3YmFhcmhlaWRzaW50ZXJ2YWwKCi0gV2UgenVsbGVuIG9wbmlldXcgc3RlZWtwcm9ldmVuIHRyZWtrZW4gdmFuIGRlIGdyb3RlIE5IQU5FUyBzdHVkaWUgZW4gZGV6ZSBrZWVyIEJJJ3MgYmVzdHVkZXJlbiB2b29yIGxvZzItY2hvbGVzdGVyb2wgc3RlZWtwcm9lZndhYXJkZW4uIFdlIHZvZXJlbiBlZXJzdCBoZXJoYWFsZGUgZXhwZXJpbWVudGVuIHVpdCBtZXQgc3RlZWtwcm9lZmdyb290dGUgMTAuCgpgYGB7cn0KcmVzJG4gPC0gYXMuY2hhcmFjdGVyKHJlcyRuKSAlPiUKICBhcy5kb3VibGUocmVzJG4pCgpyZXMkbGwgPC0gcmVzJG1lYW4tcXQoMC45NzUsZGY9cmVzJG4tMSkqcmVzJHNlCnJlcyR1bCA8LSByZXMkbWVhbitxdCgwLjk3NSxkZj1yZXMkbi0xKSpyZXMkc2UKCm11IDwtIGZlbSREaXJlY3RDaG9sJT4lbG9nMiU+JW1lYW4KCnJlcyRpbnNpZGUgPC0gcmVzJGxsPD1tdSAmIG11PD1yZXMkdWwKcmVzJG4gPC0gYXMuZmFjdG9yKHJlcyRuKQoKcmVzICU+JQogIGdyb3VwX2J5KG4pICU+JQogIHN1bW1hcml6ZShjb3ZlcmFnZT1tZWFuKGluc2lkZSkpICU+JQogIHNwcmVhZChuLGNvdmVyYWdlKQpgYGAKCldlIHppZW4gZGF0IGRlIG9tdmFuZyB2YW4gZGUgaW50ZXJ2YWxsZW4gbnUgd29yZGVuIGdlY29udHJvbGVlcmQgb3AgaHVuIG5vbWluYWxlIGJldHJvdXdiYWFyaGVpZHNuaXZlYXUgdmFuIDk1JS4KCmBgYHtyfQpyZXMgJT4lCiAgZmlsdGVyKG49PTEwKSAlPiUKICBzbGljZSgxOjIwKSAlPiUKICBnZ3Bsb3QoYWVzKHg9c2FtcGxlLHk9bWVhbixjb2xvcj1pbnNpZGUpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2Vycm9yYmFyKAogICAgYWVzKHltaW49bWVhbi1xdCgwLjk3NSxkZj05KSpzZSwKICAgIHltYXg9bWVhbitxdCgwLjk3NSxkZj05KSpzZSkpKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGZlbSREaXJlY3RDaG9sICU+JSBsb2cyICU+JSBtZWFuKSArCiAgZ2d0aXRsZSgiMjAgQ0kgZm9yIE49MTAiKSArCiAgeWxpbShyYW5nZShmZW0kRGlyZWN0Q2hvbCAlPiUgbG9nMikpCmBgYAoKLS0tCk9wZHJhY2h0CgpWb2VyIGRlIGJvdmVuc3RhYW5kZSBzaW11bGF0aWUgc3R1ZGllIG9wbmlldXcgdWl0IG1hYXIgdmVyZHViYmVsIGRlIHN0ZWVrcHJvZWZncm9vdHRlLiBXZWxrZSBpbXBhY3QgaGVlZnQgZGl0IG9wIGRlIEJJcz8KLS0tCgohW10oaHR0cHM6Ly93d3cubmF0dXJlLmNvbS9hcnRpY2xlcy9ubWV0aC4yNjU5LnBkZil7d2lkdGg9MTAwJX0KCi0tLQoKIyMgUmFwcG9ydGVyZW4/CgoKLSBSYXBwb3J0ZWVyIGFsdGlqZCBkZSBvbnpla2VyaGVpZCBvdmVyIGRlIHJlc3VsdGF0ZW4hCgotIENvbmNsdXNpZXMgb3AgYmFzaXMgdmFuIGVlbiBwdW50c2NoYXR0aW5nIGt1bm5lbiBlcmcgbWlzbGVpZGVuZCB6aWpuLgoKLSBCaWogZWVuIHN0YXRpc3Rpc2NoZSBhbmFseXNlIHJhcHBvcnRlcmVuIHdlIGRhYXJvbSBhbHRpamQgYmV0cm91d2JhYXJoZWlkc2ludGVydmFsbGVuCgotIFplIHppam4ga2xlaW4gZ2Vub2VnIG9tIGluZm9ybWF0aWVmIHRlIHppam4sIG1hYXIgYmlqbmEgbm9vaXQgbWlzbGVpZGVuZAoKLSBaZSB2b3JtZW4gZWVuIGdvZWRlIGFmd2VnaW5nIHR1c3NlbiBzdGF0aXN0aXNjaGUgc2lnbmlmaWNhbnRpZSBlbiBiaW9sb2dpc2NoZSByZWxldmFudGllLgoKCi0gUmFwcG9ydGVlciBhbHRpamQgZGUgb256ZWtlcmhlaWQgb3AgZGUgcmVzdWx0YXRlbiEKCi0gQmlqIGVlbiBzdGF0aXN0aXNjaGUgYW5hbHlzZSByYXBwb3J0ZXJlbiB3ZSBkYWFyb20gYWx0aWpkIGJldHJvdXdiYWFyaGVpZHNpbnRlcnZhbGxlbgoKLSBEZSBpbnRlcnZhbGxlbiB6aWpuIGtsZWluIGdlbm9lZyBvbSBpbmZvcm1hdGllZiB0ZSB6aWpuLCBtYWFyIGJpam5hIG5vb2l0IG1pc2xlaWRlbmQKCi0gWmUgdm9ybWVuIGVlbiBnb2VkZSBhZndlZ2luZyB0dXNzZW4gc3RhdGlzdGlzY2hlIHNpZ25pZmljYW50aWUgZW4gYmlvbG9naXNjaGUgcmVsZXZhbnRpZS4KCi0gV2UgY29uY2x1ZGVyZW4gZGF0IGRlIHBvcHVsYXRpZXBhcmFtZXRlciBpbiBoZXQgaW50ZXJ2YWwgbGlndCBlbiB3ZXRlbiBkYXQgZGV6ZSBzdGVsbGluZyBnZWxkdCBtZXQgZWVuIHByb2JhYmlsaXRlaXQgdmFuIDk1JSB2b29yIHdpbGxla2V1cmlnZSBzdGVla3Byb2V2ZW4uCgojIyMgQ2FwdG9wcmlsIHZvb3JiZWVsZAoKV2UgY29uY2x1ZGVyZW4gZGF0IGRlIGJsb2VkZHJ1ayBnZW1pZGRlbGQgbWV0CmByIGFicyhyb3VuZChtZWFuKGNhcHRvcHJpbCRkZWx0YVNCUCksMSkpYG1tSGcgdmVybWluZGVydCBuYSB0b2VkaWVuaW5nIHZhbiBjYXB0b3ByaWwgKDk1JSBDSSBbYHIgcGFzdGUocm91bmQobWVhbihjYXB0b3ByaWwkZGVsdGFTQlApK3F0KGMoMC4wMjUsLjk3NSksbi0xKSpzZChjYXB0b3ByaWwkZGVsdGFTQlApL3NxcnQobiksMSksY29sbGFwc2U9IiwiKWBdbW1IZykuCgpPcCBiYXNpcyB2YW4gZGV6ZSByZXN1bHRhdGVuIGlzIGhldCBkdWlkZWxpamsgZGF0IGRlIGJlaGFuZGVsaW5nIGVlbiBzdGVya2UgYmxvZWRkcnVrZGFsaW5nIHZlcm9vcnphYWt0IGJpaiBwYXRpw6tudGVuIG1ldCBoeXBlcnRlbnNpZS4KCiMgSHlwb3RoZXNlIHRlc3RlbgoKIyMgQ2FwdG9wcmlsIHZvb3JiZWVsZDoKT25kZXJ6b2VrZXJzIHdpbGxlbiBiZW9vcmRlbGVuIG9mIGhldCBtZWRpY2lqbiBjYXB0b3ByaWwgZGUgYmxvZWRkcnVrIHZlcmxhYWd0IGJpaiBwYXRpw6tudGVuIG1ldCBoeXBlcnRlbnNpZS4KCi0gSGVlZnQgaGV0IHRvZWRpZW5lbiB2YW4gY2FwdG9wcmlsIHdlbCBvZiBnZWVuIGVmZmVjdCBvcCBkZSBzeXN0b2xpc2NoZSBibG9lZGRydWs/CgotIEhldCBsaWd0IG5pZXQgdm9vciBkZSBoYW5kIG9tIGRlcmdlbGlqa2UgY29uY2x1c2llcyB0ZSB0cmVra2VuIG9wIGJhc2lzIHZhbiBlZW4ga2xlaW5lIHN0ZWVrcHJvZWYKCi0gSGV0IGlzIG9uemVrZXIgb2Ygd2UgZGUgb2JzZXJ2YXRpZXMgaW4gZGUgc3RlZWtwcm9lZiBuYWFyIGRlIHBvcHVsYXRpZSBrdW5uZW4gdmVyYWxnZW1lbmVuIQoKLSAgSXMgaGV0IHNjaGlqbmJhYXIgZ3Vuc3RpZ2UgZWZmZWN0IHN5c3RlbWF0aXNjaCBvZiB3aWxsZWtldXJpZz8KCmBgYHtyfQpjYXB0b3ByaWxUaWR5ICU+JQogIGZpbHRlcih0eXBlJWluJWMoIlNCUGEiLCJTQlBiIikpICU+JQogIG11dGF0ZSh0eXBlPWZhY3Rvcih0eXBlLGxldmVscz1jKCJTQlBiIiwiU0JQYSIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXR5cGUseT1icCkpICsKICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gaWQpKSArCiAgZ2VvbV9wb2ludCgpCmBgYAoKYGBge3J9CmNhcHRvcHJpbCRkZWx0YVNCUCA8LSBjYXB0b3ByaWwkU0JQYS1jYXB0b3ByaWwkU0JQYgpjYXB0b3ByaWwlPiUKICBnZ3Bsb3QoYWVzKHg9IlN5c3RvbGljIGJsb29kIHByZXNzdXJlIix5PWRlbHRhU0JQKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlPU5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbj0iaml0dGVyIikrCiAgeWxhYigiRGlmZmVyZW5jZSAobW0gbWVyY3VyeSkiKSArCiAgeGxhYigiIikKYGBgCgoKLSBIZXQgZ2VtaWRkZWxkZSBibG9lZGRydWt2ZXJzY2hpbCAkXGJhciBYJCBpcyBlZW4gbmF0dXVybGlqa2UgYmFzaXMgb20gb256ZSBiZXNsaXNzaW5nZW4gb3AgdGUgYmFzZXJlbi4KCiQkXGJhciB4XHRleHR7PWByIHJvdW5kKG1lYW4oY2FwdG9wcmlsJGRlbHRhU0JQKSwyKWAgKHM9YHIgcm91bmQoc2QoY2FwdG9wcmlsJGRlbHRhU0JQKSwyKWAsIFNFPWByIHJvdW5kKHNkKGNhcHRvcHJpbCRkZWx0YVNCUCkvc3FydCgxNSksMilgKX0kJAoKLSBIZXQgaXMgbmlldCB2b2xkb2VuZGUgZGF0ICRcYmFye3h9PCAwJCBvbSB0ZSBjb25jbHVkZXJlbiBkYXQgZGUgc3lzdG9saXNjaGUgYmxvZWRkcnVrIGdlbWlkZGVsZCBsYWdlciBpcyBiaWogdG9lZGllbmluZyB2YW4gQ2FwdG9wcmlsICpvcCBoZXQgbml2ZWF1IHZhbiBkZSBnZWhlbGUgcG9wdWxhdGllKi4KCi0gT20gaGV0IGVmZmVjdCBkYXQgd2UgaW4gZGUgc3RlZWtwcm9lZiB3YWFybmVtZW4gdGUgdmVyYWxnZW1lbmVuIG5hYXIgZGUgcG9wdWxhdGllLCBtb2V0IGhldCB2b2xkb2VuZGUgZ3Jvb3Qgemlqbi4KCi0gTWFhciBob2UgZ3Jvb3Q/CgotLS0KCiMjIyBIeXBvdGhlc2UgdGVzdGVuCgotIFZvb3IgZGl0IGRvZWwgemlqbiBzdGF0aXN0aXNjaGUgaHlwb3RoZXNldGVzdHMgb250d2lra2VsZAotIERlemUgZ2V2ZW4gZWVuIHp3YXJ0L3dpdCBhbnR3b29yZAotIEhldCBpcyBiaWpuYSBvbm1vZ2VsaWprIG9tIGVlbiB3ZXRlbnNjaGFwcGVsaWprZSBwdWJsaWNhdGUgdGUgbGV6ZW4gem9uZGVyIHJlc3VsdGF0ZW4gdmFuIHN0YXRpc3Rpc2NoZSB0ZXN0ZW4KLSBWb2xnZW5zIGhldCAqZmFsc2lmaWNhdGllIHByaW5jaXBlKiB2YW4gUG9wcGVyIGt1bm5lbiB3ZSBub29pdCBlZW4gaHlwb3RoZXNlIGJld2lqemVuIG9wIGJhc2lzIHZhbiBnZWdldmVucy4KCiAgICAtIERhYXJvbSBpbnRyb2R1Y2VyZW4gd2UgdHdlZSBoeXBvdGhlc2VuOiBlZW4gbnVsaHlwb3RoZXNlICRIXzAkIGVuIGVlbiBhbHRlcm5hdGlldmUgaHlwb3RoZXNlICRIXzEkLgoKICAgIC0gV2UgenVsbGVuIHByb2JlcmVuIGRlIG51bGh5cG90aGVzZSB0ZSBvbnRrcmFjaHRlbiBvcCBiYXNpcyB2YW4gZGUgc3RhdGlzdGlzY2hlIHRlc3QuCgojIyMjIENhcHRvcHJpbAoKLSBPcCBiYXNpcyB2YW4gZGUgc3RlZWtwcm9lZiBrdW5uZW4gd2UgbmlldCBiZXdpanplbiBkYXQgZXIgZWVuIGVmZmVjdCBpcyB2YW4gaGV0IHRvZWRpZW5lbiB2YW4gY2FwdG9wcmlsICgkSF8xJCwgYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSkuCgotIFdlIHZlcm9uZGVyc3RlbGxlbiBkYWFyb20gZGF0IGVyIGdlZW4gZWZmZWN0IGlzIHZhbiBjYXB0b3ByaWwKCiAgICAtIFdlIG5vZW1lbiBkaXQgZGUgbnVsaHlwb3RoZXNlICRIXzAkLgoKICAgIC0gRmFsc2lmeSAoInByb2JlZXIgdGUgb250a3JhY2h0ZW4iKSBkZSAkSF8wJC4KCiAgICAtIEhvZSB3YWFyc2NoaWpubGlqayBpcyBoZXQgb20gZWVuIGVmZmVjdCB3YWFyIHRlIG5lbWVuIGRhdCBtaW5zdGVucyB6byBncm9vdCBpcyBhbHMgd2F0IHdlIGluIGRlIHN0ZWVrcHJvZWYgaW4gZWVuIHdpbGxla2V1cmlnZSBzdGVla3Byb2VmIGhlYmJlbiBnZXppZW4gYWxzICRIXzAkIHdhYXIgaXM/ICAKCi0tLQoKCiMjIyMgUGVybXV0YXRpZSB0ZXN0CgoKLSBPbmRlciAkSF8wJCB6aWpuIGRlIGJsb2VkZHJ1a21ldGluZ2VuIHZvb3IgZW4gbmEgdG9lZGllbmluZyB2YW4gY2FwdG9wcmlsIHR3ZWUgImJhc2UgbGluZSIgYmxvZWRkcnVrbWV0aW5nZW4gdm9vciBlZW4gcGF0acOrbnQKCi0gT25kZXIgSCRfMCQga3VubmVuIHdlIGRlIGJsb2VkZHJ1a21ldGluZ2VuIHZvb3IgaWVkZXJlIHBhdGnDq250IGluIHdpbGxla2V1cmlnZSB2b2xnb3JkZSBwbGFhdHNlbiAocGVybXV0ZXJlbikuCgoKYGBge3J9CnNldC5zZWVkKDM1KQpjYXB0b3ByaWxTYW1wIDwtIGNhcHRvcHJpbApwZXJtIDwtIHNhbXBsZShjKEZBTFNFLCBUUlVFKSwgMTUsIHJlcGxhY2UgPSBUUlVFKQpjYXB0b3ByaWxTYW1wJFNCUGFbcGVybV0gPC0gY2FwdG9wcmlsJFNCUGJbcGVybV0KY2FwdG9wcmlsU2FtcCRTQlBiW3Blcm1dIDwtIGNhcHRvcHJpbCRTQlBhW3Blcm1dCmNhcHRvcHJpbFNhbXAkZGVsdGFTQlAgPC0gY2FwdG9wcmlsU2FtcCRTQlBhLWNhcHRvcHJpbFNhbXAkU0JQYgpjYXB0b3ByaWxTYW1wICU+JQogIGdhdGhlcih0eXBlLCBicCwgLWlkKSAlPiUKICBmaWx0ZXIodHlwZSAlaW4lIGMoIlNCUGEiLCJTQlBiIikpICU+JQogIG11dGF0ZSh0eXBlID0gZmFjdG9yKHR5cGUsIGxldmVscyA9IGMoIlNCUGIiLCAiU0JQYSIpKSklPiUKICBnZ3Bsb3QoYWVzKHggPSB0eXBlLHkgPSBicCkpICsKICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gaWQpKSArCiAgZ2VvbV9wb2ludCgpCmBgYAoKCgoKYGBge3J9CmRhdGEuZnJhbWUoCiAgZGVsdGFTQlAgPSBjKGNhcHRvcHJpbCRkZWx0YVNCUCxjYXB0b3ByaWxTYW1wJGRlbHRhU0JQKSwKICBzaHVmZmxlZD1yZXAoYyhGQUxTRSxUUlVFKSxlYWNoPTE1KQogICkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2h1ZmZsZWQsIHkgPSBkZWx0YVNCUCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9ICJqaXR0ZXIiKSsKICBzdGF0X3N1bW1hcnkoCiAgICBmdW4ueSA9IG1lYW4sCiAgICBnZW9tID0gInBvaW50IiwKICAgIHNoYXBlID0gMTksCiAgICBzaXplID0gMywKICAgIGNvbG9yID0gInJlZCIsCiAgICBmaWxsID0gInJlZCIpICsKICB5bGFiKCJEaWZmZXJlbmNlIChtbSBtZXJjdXJ5KSIpCmBgYAoKV2UgcGVybXV0ZXJlbiBvcG5pZXV3CgoKYGBge3J9CmNhcHRvcHJpbFNhbXAgPC0gY2FwdG9wcmlsCnBlcm0gPC0gc2FtcGxlKGMoRkFMU0UsVFJVRSksIDE1LCByZXBsYWNlID0gVFJVRSkKY2FwdG9wcmlsU2FtcCRTQlBhW3Blcm1dIDwtIGNhcHRvcHJpbCRTQlBiW3Blcm1dCmNhcHRvcHJpbFNhbXAkU0JQYltwZXJtXSA8LSBjYXB0b3ByaWwkU0JQYVtwZXJtXQpjYXB0b3ByaWxTYW1wJGRlbHRhU0JQIDwtIGNhcHRvcHJpbFNhbXAkU0JQYS1jYXB0b3ByaWxTYW1wJFNCUGIKY2FwdG9wcmlsU2FtcCAlPiUKICBnYXRoZXIodHlwZSwgYnAsIC1pZCkgJT4lCiAgZmlsdGVyKHR5cGUgJWluJSBjKCJTQlBhIiwiU0JQYiIpKSAlPiUKICBtdXRhdGUodHlwZSA9IGZhY3Rvcih0eXBlLCBsZXZlbHMgPSBjKCJTQlBiIiwgIlNCUGEiKSkpJT4lCiAgZ2dwbG90KGFlcyh4ID0gdHlwZSx5ID0gYnApKSArCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IGlkKSkgKwogIGdlb21fcG9pbnQoKQoKZGF0YS5mcmFtZSgKICBkZWx0YVNCUCA9IGMoY2FwdG9wcmlsJGRlbHRhU0JQLGNhcHRvcHJpbFNhbXAkZGVsdGFTQlApLAogIHNodWZmbGVkPXJlcChjKEZBTFNFLFRSVUUpLGVhY2g9MTUpCiAgKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzaHVmZmxlZCwgeSA9IGRlbHRhU0JQKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gImppdHRlciIpKwogIHN0YXRfc3VtbWFyeSgKICAgIGZ1bi55ID0gbWVhbiwKICAgIGdlb20gPSAicG9pbnQiLAogICAgc2hhcGUgPSAxOSwKICAgIHNpemUgPSAzLAogICAgY29sb3IgPSAicmVkIiwKICAgIGZpbGwgPSAicmVkIikgKwogIHlsYWIoIkRpZmZlcmVuY2UgKG1tIG1lcmN1cnkpIikKYGBgCgoKLSBFciB6aWpuICQyXnsxNX0kID0gYHIgZm9ybWF0KDJeMTUpYCBtb2dlbGlqa2UgcGVybXV0YXRpZXMhCi0gV2UgaG9ldmVuIGluIHByaW5jaXBlIGFsbGVlbiBkZSB0ZWtlbnMgdmFuIGRlIHdhYXJnZW5vbWVuIGJsb2VkZHJ1a3ZlcnNjaGlsbGVuICR4JCB0ZSB3aXNzZWxlbiBhbHMgd2UgcGVybXV0ZXJlbi4KCmBgYHtyfQpwZXJtSCA8LSBleHBhbmQuZ3JpZCgKICByZXBsaWNhdGUoCiAgICAxNSwKICAgIGMoLTEsMSksCiAgICBzaW1wbGlmeT1GQUxTRSkKICApICU+JQogIHQKCnBlcm1IWywxOjVdCmBgYAoKLSBXZSB6dWxsZW4gZGl0IHZvb3IgYWxsZSBtb2dlbGlqa2UgcGVybXV0YXRpZXMgZG9lbiBlbiB3ZSB6dWxsZW4gaGV0IGdlbWlkZGVsZGUgYmlqaG91ZGVuLgoKCmBgYHtyfQojY2FsY3VsYXRlIHRoZSBtZWFucyBmb3IgdGhlIHBlcm11dGVkIGRhdGEKbXVQZXJtIDwtIGNvbE1lYW5zKHBlcm1IKmNhcHRvcHJpbCRkZWx0YVNCUCkKbXVQZXJtICU+JQogIGFzLmRhdGEuZnJhbWUgJT4lCiAgZ2dwbG90KGFlcyh4PS4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oKSArCiAgZ2VvbV92bGluZSgKICAgIHhpbnRlcmNlcHQgPSBtZWFuKGNhcHRvcHJpbCRkZWx0YVNCUCksCiAgICBjb2wgPSAiYmx1ZSIpCgpzdW0obXVQZXJtIDw9IG1lYW4oY2FwdG9wcmlsJGRlbHRhU0JQKSkKbWVhbihtdVBlcm0gPD0gbWVhbihjYXB0b3ByaWwkZGVsdGFTQlApKQpgYGAKCi0gIFdlIHppZW4gZGF0IG1hYXIgMSB2YW4gZGUgZ2VtaWRkZWxkZW4gZGllIHdlcmRlbiB2ZXJrcmVnZW4gb25kZXIgJEhfMCQgKGRvb3IgcGVybXV0YXRpZSkgem8gZXh0cmVlbSB3YXMgYWxzIGhldCBzdGVla3Byb2VmZ2VtaWRkZWxkZSBkYXQgd2UgaW4gZGUgY2FwdG9wcmlsLXN0dWRpZSBoZWJiZW4gd2Fhcmdlbm9tZW4uCgotIER1cyBkZSBrYW5zIG9tIGVlbiBibG9lZGRydWtkYWxpbmcgd2FhciB0ZSBuZW1lbiBkaWUgZ3JvdGVyIG9mIGdlbGlqayBpcyBkYW4gZGllIGluIGRlIGNhcHRvcHJpbC1zdHVkaWUgaW4gZWVuIHdpbGxla2V1cmlnZSBzdGVla3Byb2VmIG9uZGVyIGRlIG51bGh5cG90aGVzZSwgaXMgMSBvcCBkZSBgciBmb3JtYXQoMl4xNSlgLgoKV2UgaGViYmVuIGR1cyBzdGVyayBiZXdpanMgZGF0ICRIXzAkIG9uanVpc3QgaXMgZW4gZGFhcm9tIHZlcndlcnBlbiB3ZSAkSF8wJCBlbiBjb25jbHVkZXJlbiAkSF8xJDogaGV0IHRvZWRpZW5lbiB2YW4gY2FwdG9wcmlsIGhlZWZ0IGVlbiBlZmZlY3Qgb3AgZGUgYmxvZWRkcnVrIHZhbiBwYXRpw6tudGVuIG1ldCBoeXBlcnRlbnNpZS4KCi0tLQoKIyMjIFBpdm90CgotIEluIGRlIHByYWt0aWprIGdlYnJ1aWtlbiB3ZSBhbHRpamQgc3RhdGlzdGlla2VuIGRpZSBkZSBlZmZlY3Rncm9vdHRlIChnZW1pZGRlbGQgdmVyc2NoaWwpIGFmd2VnZW4gdGVnZW4gcnVpcyAoc3RhbmRhYXJkIGVycm9yKQoKLSBBbHMgd2UgZGUgbnVsaHlwb3RoZXNlIG9udGtyYWNodGVuLCBzdGFuZGFhcmRpc2VyZW4gd2UgaGV0IGdlbWlkZGVsZGUgcm9uZCAkXG11XzAgPSAwJCBoZXQgZ2VtaWRkZWxkZSBvbmRlciAkSF8wJAoKJCR0PVxmcmFje1xiYXIgWC1cbXVfMH17c2Vfe1xiYXIgWH19JCQKCi0gVm9vciBoZXQgQ2FwdG9wcmlsIHZvb3JiZWVsZCB3b3JkdCBkaXQ6CiQkXGZyYWN7YHIgcm91bmQobWVhbihjYXB0b3ByaWwkZGVsdGFTQlApLDIpYC0wfXtgciByb3VuZChzZChjYXB0b3ByaWwkZGVsdGFTQlApL3NxcnQoMTUpLDIpYH09YHIgcm91bmQobWVhbihjYXB0b3ByaWwkZGVsdGFTQlApLyhzZChjYXB0b3ByaWwkZGVsdGFTQlApL3NxcnQoMTUpKSwyKWAkJAoKCldlIGJlcGFsZW4gbnUgZGUgbnVsdmVyZGVsaW5nIHZhbiB0ZXN0c3RhdGlzdGllayB0IG1ldCBwZXJtdXRhdGllLgoKYGBge3J9CmRlbHRhUGVybXMgPC0gcGVybUgqY2FwdG9wcmlsJGRlbHRhU0JQCnRQZXJtIDwtIGNvbE1lYW5zKGRlbHRhUGVybXMpLyhhcHBseShkZWx0YVBlcm1zLDIsc2QpL3NxcnQoMTUpKQp0T3JpZyA8LSBtZWFuKGNhcHRvcHJpbCRkZWx0YVNCUCkvc2QoY2FwdG9wcmlsJGRlbHRhU0JQKSpzcXJ0KDE1KQoKdFBlcm1QbG90IDwtIHRQZXJtICU+JQogIGFzLmRhdGEuZnJhbWUgJT4lCiAgZ2dwbG90KGFlcyh4ID0gLikpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uLCBmaWxsID0gLi5jb3VudC4uKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IHRPcmlnLGNvbCA9ICJibHVlIikKdFBlcm1QbG90CmBgYAoKLSBPcG5pZXV3IGhlZWZ0IHNsZWNodHMgMSB2YW4gZGUgcGVybXV0YXRpZXMgZWVuIHQtc3RhdGlzdGllayBkaWUgem8gZXh0cmVlbSBpcyBhbHMgZGUgc3RhdGlzdGllayBkaWUgd29yZHQgd2Fhcmdlbm9tZW4gaW4gZGUgY2FwdG9wcmlsLXN0dWRpZS4KCldhbm5lZXIgZXIgZ2VlbiBlZmZlY3QgdmFuIGNhcHRvcHJpbCBpcywgaXMgaGV0IGJpam5hIG9ubW9nZWxpamsgb20gZWVuIAsLdGVzdHN0YXRpc3RpZWsgdGUgdmVya3JpamdlbiBkaWUgem8gZXh0cmVlbSBpcyBhbHMgZGVnZW5lIGRpZSB3ZXJkIHdhYXJnZW5vbWVuICggIHQ9YHIgcm91bmQodE9yaWcsMilgKS4KCi1EZSBrYW5zIG9tIGVlbiBncm90ZXJlIGJsb2VkZHJ1a2RhbGluZyB3YWFyIHRlIG5lbWVuIGRhbiBkZWdlbmUgZGllIHdlIGluIG9uemUgc3RlZWtwcm9lZiBoZWJiZW4gd2Fhcmdlbm9tZW4gaW4gZWVuIHdpbGxla2V1cmlnZSBzdGVla3Byb2VmIG9uZGVyICRIXzAkIGlzIDEvYHIgZm9ybWF0KDJeMTUpYC4KCi0gV2Ugbm9lbWVuIGRlemUga2FucyBkZSAqcC13YWFyZGUqLgoKLSBIZXQgbWVldCBkZSBzdGVya3RlIHZhbiBoZXQgYmV3aWpzIHRlZ2VuIGRlIG51bHdhYXJkZTogaG9lIGtsZWluZXIgZGUgcC13YWFyZGUsIGhvZSBtZWVyIGJld2lqcyB3ZSBoZWJiZW4gZGF0IGRlIG51bHdhYXJkZSBuaWV0IHdhYXIgaXMuCgotIERlIHZlcmRlbGluZyBoZWVmdCBlZW4gbW9vaWUga2xva3Zvcm0uCgotLS0KCiMjIyBIb2UgYmVzbGlzc2VuIHdlPwoKV2FubmVlciBpcyBkZSBwLXdhYXJkZSBrbGVpbiBnZW5vZWcgb20gdGUgY29uY2x1ZGVyZW4gZGF0IGVyIHN0ZXJrIGJld2lqcyBpcyB0ZWdlbiBkZSBudWxoeXBvdGhlc2U/CgotIFdlIHdlcmtlbiBkb29yZ2FhbnMgbWV0IGVlbiBzaWduaWZpY2FudGllbml2ZWF1IHZhbiAkXGFscGhhID0gMCwwNSQKCi0gV2Ugc3RlbGxlbiBkYXQgd2UgZGUgdGVzdCBoZWJiZW4gdWl0Z2V2b2VyZCBvcCBoZXQgc2lnbmlmaWNhbnRpZW5pdmVhdSB2YW4gNSUKCi0tLQoKCiMjIyBQZXJtdXRhdGlldGVzdHMgemlqbiBjb21wdXRhdGlvbmVlbCB2ZWVsZWlzZW5kCgotIEt1bm5lbiB3ZSBiZW9vcmRlbGVuIGhvZSBleHRyZWVtIGRlIGJsb2VkZHJ1a2RhbGluZyB3YXMgem9uZGVyIHBlcm11dGF0aWU/CgotIFdlIHdldGVuIGRhdCBkZSBibG9lZGRydWt2ZXJzY2hpbGxlbiBvbmdldmVlciBub3JtYWFsIHZlcmRlZWxkIHppam4sIGR1cwoKJCR0PVxmcmFje1xiYXIgWCAtIFxtdX17c2Vfe1xiYXIgWH19JCQKCnZvbGd0IGVlbiB0LXZlcmRlbGluZyAobWV0IDE0IHZyaWpoZWlkc2dyYWRlbiB2b29yIGhldCBDYXB0b3ByaWwgdm9vcmJlZWxkKS4KCgotIE9uZGVyIEgkXzAkICRcbXU9MCQgZW4gJCR0PVxmcmFje1xiYXIgWC0wfXtzZV97XGJhciBYfX1cc2ltIGZfe1QsMTR9JCQKCmBgYHtyfQp0UGVybVBsb3QgKwogIHN0YXRfZnVuY3Rpb24oCiAgICBmdW4gPSBkdCwKICAgIGNvbG9yID0gInJlZCIsCiAgICBhcmdzID0gbGlzdChkZj0xNCkpCmBgYAoKCi0gTWVyayBvcCBkYXQgZGUgcGVybXV0YXRpZS1udWx2ZXJkZWxpbmcgaW5kZXJkYWFkIG92ZXJlZW5rb210IG1ldCBlZW4gdC12ZXJkZWxpbmcgbWV0IDE0IHZyaWpoZWlkc2dyYWRlbi4KCi0gWm9kYXQgd2UgZGUgc3RhdGlzdGlzY2hlIHRlc3Qga3VubmVuIHVpdHZvZXJlbiBtZXQgYmVodWxwIHZhbiBzdGF0aXN0aXNjaGUgbW9kZWxsZW4gdmFuIGRlIGdlZ2V2ZW5zLgoKLSBIaWVydm9vciBtb2V0ZW4gd2UgYXNzdW1wdGllcyBtYWtlbiwgZGllIHdlIHZlcmlmacOrcmVuIGluIGRlIGRhdGEgZXhwbG9yYXRpZS4KCgotLS0KCgojIyBIeXBvdGhlc2VzCgpWZXJ0YWFsIGRlIG9uZGVyem9la3N2cmFhZyBuYWFyIGVlbiBudWxoeXBvdGhlc2UgKCRIXzAkKSBlbiBlZW4gYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSAoJEhfMSQpCgpFZXJzdCBtb2V0ZW4gd2UgZGUgb25kZXJ6b2Vrc3ZyYWFnIHZlcnRhbGVuIG5hYXIgZWVuIGdlcGFyYW1ldHJpc2VlcmQgc3RhdGlzdGlzY2ggbW9kZWwuICAKCi0gVWl0IGhldCBleHBlcmltZW50ZWxlIG9udHdlcnAgdm9sZ3QgZGF0ICAkJFhfMSwuLi4sWF9uIFx0ZXh0eyBpLmkuZCB9IGYoWCksJCQgbWV0ICRmKFgpJCBkZSBkaWNodGhlaWRzZnVuY3RpZSB2YW4gYmxvZWRkcnVrdmVyc2NoaWxsZW4uCgotICoqdmVyZWVudm91ZGlnKio6IG5lZW0gYWFuIGRhdCAkZihYKSQgZ2VrZW5kIGlzIG1ldCB1aXR6b25kZXJpbmcgdmFuIGVlbiBlaW5kaWcgZGltZW5zaW9uYWxlIHNldCBwYXJhbWV0ZXJzICRcbWF0aGJme1x0aGV0YX0kIGRpZSBub2cgbW9ldCB3b3JkZW4gZ2VzY2hhdCAocGFyYW1ldHJpc2NoIHN0YXRpc3Rpc2NoIG1vZGVsKS4KCiMjIyBDYXB0b3ByaWwgdm9vcmJlZWxkCgokWCBcc2ltIE4oXG11LFxzaWdtYV4yKSQgd2l0aCAkXG1hdGhiZntcdGhldGF9PShcbXUsXHNpZ21hXjIpJCwgdGhlIG1lYW4gJFxtdSQgYW5kIHZhcmlhbmNlICRcc2lnbWFeMiQuCgpEZSBvbmRlcnpvZWtzdnJhYWcgaXMgbnUgdmVydGFhbGQgaW4gdGVybWVuIHZhbiBkZSBnZW1pZGRlbGRlIGJsb2VkZHJ1a2RhbGluZzo6ICRcbXUgPSBFX2ZbWF0kLgoKRGUgKiphbHRlcm5hdGlldmUgaHlwb3RoZXNlKiogIGlzIGdlZm9ybXVsZWVyZCBpbiB0ZXJtZW4gdmFuIGVlbiBwYXJhbWV0ZXIgdmFuICRmKFgpJCAgbW9ldCB1aXRkcnVra2VuIHdhdCBkZSBvbmRlcnpvZWtlcnMgbWV0IGhldCBvbmRlcnpvZWsgd2lsbGVuIGJld2lqemVuLgoKLSBoaWVyOgokJEhfMTogXG11PDAuJCQgR2VtaWRkZWxkIGRhYWx0IGRlIGJsb2VkZHJ1ayB2YW4gcGF0acOrbnRlbiBtZXQgaHlwZXJ0ZW5zaWUgbmEgdG9lZGllbmluZyB2YW4gY2FwdG9wcmlsLgoKCkRlICoqbnVsIGh5cG90aGVzZSoqIGRydWt0IG92ZXIgaGV0IGFsZ2VtZWVuIGVlbiBudWx2b29yd2FhcmRlIHVpdCwgZC53Lnogd2FubmVlciBlciBuaWV0cyB1aXR6b25kZXJsaWprcyBnZWJldXJ0LgoKLSBPbmRlcnpvZWtlcnMgcHJvYmVyZW4gZG9vcmdhYW5zIHZpYSBlbXBpcmlzY2ggb25kZXJ6b2VrIGFhbiB0ZSB0b25lbiBkYXQgaGV0IG9ic2VydmVyZW4gdmFuIGRlIGdlZ2V2ZW5zIG9uZGVyIGRlIG51bCBob29nc3Qgb253YWFyc2NoaWpubGlqayBpcywgem9kYXQgemUgZGUgbnVsaHlwb3RoZXNlIGt1bm5lbiB2ZXJ3ZXJwZW46CioqRmFsc2lmaWNhdGllIHByaW5jaXBlKiouCgotIERlICoqbnVsIGh5cG90aGVzZSB3b3JkdCBkb29yZ2FhbnMgdWl0Z2VkcnVrdCBtZXQgZGV6ZWxmZGUgbW9kZWxwYXJhbWV0ZXIgYWxzIGRpZSB3b3JkdCBnZWJydWlrdCB2b29yICRIXzEkLioqCgotIEhpZXI6CiQkSF8wIDogXG11PTAkJCBkLncuei4gZ2VtaWRkZWxkIGJsaWpmdCBkZSBzeXN0b2xpc2NoZSBibG9lZGRydWsgb25nZXdpanppZ2QgbmEgdG9lZGllbmluZyB2YW4gY2FwdG9wcmlsLgoKCi0tLQoKIyMgVGVzdC1zdGF0aXN0aWVrCgoKClpvZHJhIGRlIHBvcHVsYXRpZSwgZGUgcGFyYW1ldGVycyBlbiAkSF8wJCBlbiAkSF8xJCB6aWpuIGJlcGFhbGQsIHZvbGd0IG1lbiBiaWogaHlwb3RoZXNldGVzdGVuIGRlIHZvbGdlbmRlIHJhdGlvbmFsZToKCkNvbnN0cnVlZXIgZWVuIHRlc3RzdGF0aXN0aWVrIHpvZGF0IGRlemUKCjEuIGhldCBiZXdpanMgbWVldCBpbiBkZSBzdGVla3Byb2VmLApcdnNwYWNlezEwcHR9CjIuIHRlZ2VuIGRlIG51bGh5cG90aGVzZSwgZW4KXHZzcGFjZXsxMHB0fQozLiBpbiBoZXQgdm9vcmRlZWwgdmFuIGRlIGFsdGVybmF0aWV2ZSBoeXBvdGhlc2UuCgpFZW4gdGVzdHN0YXRpc3RpZWsgbW9ldCBkdXMgZWVuIGZ1bmN0aWUgemlqbiB2YW4gZGUgd2Fhcm5lbWluZ2VuIGluIGRlIHN0ZWVrcHJvZWYuCgoKIyMjIENhcHRvcHJpbCB2b29yYmVlbGQKCgokJFQ9XGZyYWN7XGJhcntYfS1cbXVfMH17XHRleHR7U0V9X3tcYmFyIFh9fSQkCk1ldCAkXG11XzA9MCQgb25kZXIgJEhfMCQKCk9wbmlldXcKCi0gQWxzICRIXzAkIGdlbGR0LCBpcyBlciBnZWVuIGVmZmVjdCB2YW4gY2FwdG9wcmlsIG9wIGRlIGJsb2VkZHJ1ayBpbiBkZSBwb3B1bGF0aWUgZW4gZGFuIHZlcndhY2h0ZW4gd2UgdGVzdHN0YXRpc3RpZWsgJFQkIGRpY2h0IGJpaiAwLgoKLSBBbHMgJEhfMSQgd2FhciBpcywgdmVyd2FjaHRlbiB3ZSAkVCA8MCQuCgotIEluIGhldCBjYXB0b3ByaWwgdm9vcmJlZWxkIG9ic2VydmVyZW4gd2UgJHQ9KC0xOC45My0wKS8yLjMzPS04LjEyJC4KCi0gSXMgJHQgPSAtOC4xMiQgaW4gYWJzb2x1dGUgd2FhcmRlIGdyb290IGdlbm9lZyBvbSB0ZSBjb25jbHVkZXJlbiBkYXQgICRcbXUgPCAwJCBlbiBtZXQgd2VsayB2ZXJ0cm91d2VuIGt1bm5lbiB3ZSBkZXplIGNvbmNsdXNpZSB0cmVra2VuPwoKLSBXZSB3ZXRlbiBkYXQgdCBlZW4gdC12ZXJkZWxpbmcgdm9sZ3QgbWV0IDE0IHZyaWpoZWlkc2dyYWRlbiBvbmRlciAkSF8wJCAgCgoKLS0tCgojIyBwLXdhYXJkZQoKRGUgcC13YWFyZGUgaXMgZGUgcHJvYmFiaWxpdGVpdCBkaWUgJEhfMCQgZW4gJEhfMSQgYWZ3ZWVndC4KCkRlIG1hbmllciB3YWFyb3Agd2UgaGV0IGJlcmVrZW5lbiBpcyBjb250ZXh0YWZoYW5rZWxpamsKCi0gVm9vciBoZXQgQ2FwdG9wcmlsIHZvb3JiZWVsZCBoZWJiZW4gd2UKICAkJAogICAgcCA9IFBcbGVmdFtUIFxsZXEgdCBcbWlkIEhfMFxyaWdodF0gPSBcdGV4dHtQfV8wXGxlZnRbVFxsZXEgdFxyaWdodF0sCiAgJCQKRGUgaW5kZXggIjAiIGluICRcdGV4dHtQfV8wXGxlZnRbLlxyaWdodF0kIGdlZWZ0IGFhbiBkYXQgZGUga2FucyB3b3JkdCBiZXJla2VuZCBvbmRlciAkSF8wJC4KCkhldCBnZWVmdCBkZSBrYW5zIHdlZXIgb20gZWVuIHRlc3RzdGF0aXN0aWVrICRUJCB0ZSBiZWtvbWVuIGRpZSBsYWdlciBvZiBnZWxpamsgaXMgYWFuIGRlIHdhYXJkZSBkaWUgd29yZHQgd2Fhcmdlbm9tZW4gaW4gZGUgaHVpZGlnZSBzdGVla3Byb2VmIGluIGVlbiB3aWxsZWtldXJpZ2Ugc3RlZWtwcm9lZiBvbmRlciAkSF8wJCB3YWFyIHRlIG5lbWVuLgogICAgLSBkLncuei4gZGUga2FucyBvbSBlZW4gdGVzdHN0YXRpc3RpZWsgJFQkIHRlIHZpbmRlbiBpbiBlZW4gd2lsbGVrZXVyaWdlIHN0ZWVrcHJvZWYgb25kZXIgJEhfMCQgbWV0IGVlbiB3YWFyZGUgZGllIGV4dHJlbWVyIGlzIChtZWVyIGluIGRlIHJpY2h0aW5nIHZhbiAkSF8xJCkgZGFuIGRpZSB3YWFyZ2Vub21lbiBpbiBkZSBodWlkaWdlIHN0ZWVrcHJvZWYuCgojIyMgQ2FwdG9wcmlsIFZvb3JiZWVsZAoKCi0gRGUgJHAkLXdhYXJkZSB2b29yIGhldCBjYXB0b3ByaWwgdm9vcmJlZWxkIHdvcmR0IGFscyB2b2xndCBiZXJla2VuZC4KICAkJHA9IFx0ZXh0e1B9XzBcbGVmdFtUXGxlcSAtOC4xMlxyaWdodF09Rl90KC04LjEyOzE0KSA9IDAuNlwgMTBeey02fS4kJAoKICBtZXQgJEZfdCg7MTQpJCAgZGUgY3VtdWxhdGlldmUgdmVyZGVsaW5nc2Z1bmN0aWUgdmFuIGVlbiB0LXZlcmRlbGluZyBtZXQgMTQgdnJpamhlaWRzZ3JhZGVuOgoKJCRGX3QoeDsxNCk9XGludFxsaW1pdHNfey1caW5mdHl9Xnt4fSBmX3QoeDsxNCkuJCQKCmVuICRmX3QoLjsxNCkkIGRlIGRpY2h0aGVpZHNmdW5jdGllIHZhbiBkZSB0LXZlcmRlbGluZy4KCi0gV2UgYmVyZWtlbmVuIGRlemUga2FucyBpbiBSIG1ldCBgcHQoeCxkZilgCgogICAgLSBEZSB3YWFyZGUgdmFuIGRlIHdhYXJnZW5vbWVuIHRlc3RzdGF0aXN0aWVrIGB4YCBlbgogICAgLSBoZXQgYWFudGFsIHZyaWpoZWlkc2dyYWRlbiB2YW4gZGUgdC12ZXJkZWxpbmcgImRmIi4KCi0gYHB0KHgsZGYpYCBiZXJla2VudCBkZSBrYW5zIG9tIGVlbiB3YWFyZGUga2xlaW5lciBvZiBnZWxpamsgYWFuIHggd2FhciB0ZSBuZW1lbiBhbHMgd2UgZWVuIHdpbGxla2V1cmlnZSBzdGVla3Byb2VmIHpvdWRlbiB0cmVra2VuIHVpdCBlZW4gdC12ZXJkZWxpbmcgbWV0IGRmIHZyaWpoZWlkc2dyYWRlbi4KCmBgYHtyfQpuIDwtIGxlbmd0aChjYXB0b3ByaWwkZGVsdGFTQlApCnN0YXQgPC0gKG1lYW4oY2FwdG9wcmlsJGRlbHRhU0JQKS0wKS8oc2QoY2FwdG9wcmlsJGRlbHRhU0JQKS9zcXJ0KG4pKQpzdGF0CnB0KHN0YXQsbi0xKQpgYGAKCgpJbiBkZSBwcmFrdGlqayBnYWFuIHdlIGRlIHRlc3QgbmlldCB6ZWxmIGJlcmVrZW5lbiwgbWFhciBnZWJydWlrZW4gd2UgZGUgZnVuY3RpZSB0LnRlc3Q6CgpgYGB7cn0KdC50ZXN0KGNhcHRvcHJpbCRkZWx0YVNCUCwgYWx0ZXJuYXRpdmUgPSAibGVzcyIpCmBgYAoKTWVyayBvcCBkYXQgd2UgaGV0IGFyZ3VtZW50IGBhbHRlcm5hdGl2ZT0ibGVzcyJgIG1vZXRlbiBzcGVjaWZpY2VyZW4sIHpvZGF0IGRlIHAtd2FhcmRlIGluIGRlIGxpbmtlciBzdGFhcnQgd29yZHQgYmVyZWtlbmQuCgoKRGUgZnVuY3RpZSBnZWVmdCBvb2sgZWVuIGVlbnppamRpZyBpbnRlcnZhbCBvbWRhdCB3ZSBpbiDDqcOpbiByaWNodGluZyB0ZXN0ZW4uCgotLS0KCiMjIyBEZWZpbml0aWUgdmFuIGRlIHAtd2FhcmRlCgpEZSAqKnAtd2FhcmRlKiogKG9vayB3ZWwgaGV0ICoqIHdhYXJnZW5vbWVuIHNpZ25pZmljYW50aWVuaXZlYXUgKiogZ2Vub2VtZCkgaXMgZGUga2FucyBvbSBlZW4gdGVzdHN0YXRpc3RpZWsgaW4gZWVuIHdpbGxla2V1cmlnZSBzdGVla3Byb2VmIHdhYXIgdGUgbmVtZW4gb25kZXIgZGUgbnVsaHlwb3RoZXNlIGRpZSBldmVuIGV4dHJlZW0gb2YgZXh0cmVtZXIgaXMgZGFuIGRlIHRlc3RzdGF0aXN0aWVrIGRpZSBpbiBkZSBodWlkaWdlIHN0ZWVrcHJvZWYgaXMgd2Fhcmdlbm9tZW4KCgotIEhvZSBrbGVpbmVyIGRlIGthbnMsIGhvZSBtZWVyIGJld2lqcyB0ZWdlbiAkSF8wJC4KCi0gTWVyayBvcCBkYXQgZGUgcC13YWFyZGUgKiogbmlldCAqKiBkZSBrYW5zIGlzIGRhdCBkZSBudWxoeXBvdGhlc2Ugd2FhciBpcyEKCi0gSGV0IHdvb3JkICJleHRyZWVtIiBnZWVmdCBhYW4gaW4gd2Vsa2UgcmljaHRpbmcgZGUgdGVzdHN0YXRpc3RpZWsgd2FhcnNjaGlqbmxpamtlciBpcyBvbmRlciBkZSBhbHRlcm5hdGlldmUgaHlwb3RoZXNlLgoKLSBJbiBoZXQgdm9vcmJlZWxkICRIXzE6IFxtdSA8IDAkIG4gd2UgdmVyd2FjaHRlbiBkdXMgemVlciBuZWdhdGlldmUgd2FhcmRlbiB2b29yICR0JCBvbmRlciAkSF8xJC4KCi0gVmFudWl0IGRlIGRlZmluaXRpZSBnZXZlbiBrbGVpbmUgcC13YWFyZGVuIGFhbiBkYXQgZGUgZ2VvYnNlcnZlZXJkZSB0ZXN0c3RhdGlzdGllayBvbndhYXJzY2hpam5pbGprIGlzIGluIGRlIHZlcm9uZGVyc3RlbGxpbmcgZGF0ICRIXzAkIGNvcnJlY3QgaXMuCgotIER1cyBlZW4ga2xlaW5lIHdhYXJkZSB2YW4gJHAkLXdhYXJkZSBiZXRla2VudCBkYXQgd2UgKiogJEhfMCQgKiogbW9ldGVuIGFmd2lqemVuIHRlbiBndW5zdGUgdmFuICRIXzEkLgoKLSBEZSBkcmVtcGVsIGRpZSB3ZSBnZWJydWlrZW4gb20gZGUgJHAkLXdhYXJkZSB0ZSB2ZXJnZWxpamtlbiwgd29yZHQgaGV0ICoqc2lnbmlmaWNhbnRpZSBuaWV2YXUqKiBnZW5vZW1kIGVuIHdvcmR0IGFhbmdlZ2V2ZW4gbWV0ICRcYWxwaGEkLgoKLSBFZW4gc3RhdGlzdGlzY2hlIHRlc3QgdWl0Z2V2b2VyZCBvcCBoZXQgJFxhbHBoYSQgc2lnbmlmaWNhbnRpZSBuaXZlYXUgd29yZHQgb29rIHdlbCBlZW4gKipuaXZlYXUtJFxhbHBoYSQgdGVzdCoqLgoKRWVuIHRlc3QgcmVzdWx0YWF0IGlzICpzdGF0aXN0aXNjaCBzaWduaWZpY2FudCogYWxzICRwPFxhbHBoYSQKCi0gJFxhbHBoYSQgd29yZHQgZ2V3b29ubGlqayBnZXpldCBvcCA1XCUuCgotIEhvZSBrbGVpbmVyIGRlIHAtd2FhcmRlIGhvZSBgc2lnbmlmaWNhbnRlcicgaGV0IHRlc3RyZXN1bHRhYXQgYWZ3aWprdCB2YW4gd2F0IG9uZGVyICRIXzAkIHZlcndhY2h0IGthbiB3b3JkZW4uCgotIEhldCB2YXQgaGV0IGJld2lqcyB0ZWdlbiBkZSBudWwgc2FtZW4uCgokJFxiZWdpbnthcnJheX17Y2x9PjAuMTAgJiBcdGV4dHsgbm9uIHNpZ25pZmljYW50IChubyBldmlkZW5jZSl9XFwwLjA1LTAuMTAgJiBcdGV4dHsgbWFyZ2luYWwgc2lnbmlmaWNhbnQsIHdlYWsgZXZpZGVuY2UgKGRvIG5vdCB1c2UgdGhpcyB5b3Vyc2VsZil9XFwwLjAxLTAuMDUgJiBcdGV4dHsgc2lnbmlmaWNhbnR9XFwwLjAwMS0wLjAxICYgXHRleHR7c3Ryb25nbHkgc2lnbmlmaWNhbnR9XFw8MC4wMDEgJiBcdGV4dHsgZXh0cmVtZWx5IHNpZ25pZmljYW50fVxlbmR7YXJyYXl9JCQKCi0tLQoKIyMgS3JpdGlla2Ugd2FhcmRlCgpgYGB7ciAgb3V0LndpZHRoPScxMDAlJywgZmlnLmFzcD0uOCwgZmlnLmFsaWduPSdjZW50ZXInLGVjaG89RkFMU0V9CnBhcihtYXI9Yyg2LDYsNiwyKSkKZ3JpZCA8LXNlcSgtMTAsMTAsLjAxKQp0Y3JpdCA8LSBxdCgwLjA1LG4tMSkKcmVqZWN0IDwtIGMoZ3JpZFtncmlkPHRjcml0XSx0Y3JpdCkKcGxvdChncmlkLGR0KGdyaWQsbi0xKSx0eXBlPSJsIixsd2Q9Mix4bGFiPSJ0LXN0YXRpc3RpYyIseWxhYj0iZGVuc2l0eSIsY2V4LmxhYj0yLGNleC5heGlzPTIsY2V4Lm1haW49MikKYWJsaW5lKHY9bWVhbihjYXB0b3ByaWwkZGVsdGFTQlApL3NlLGNvbD0yLGx3ZD0yLGx0eT0yKQphYmxpbmUodj1xdChjKC4wNSksbi0xKSxjb2w9MixsdHk9MSxsd2Q9MikKdGV4dChjKC01LC01LDUsNSksYyguMjEsLjE5LC4yMSwuMTkpLGxhYmVsPWMoInJlamVjdGlvbi0iLCJyZWdpb24iLCJhY2NlcHRpb24tIiwicmVnaW9uIiksY29sPWMoMiwyLDQsNCkpCmFycm93cygtMTAwLC40LG1lYW4oY2FwdG9wcmlsJGRlbHRhU0JQKS9zZSwuNCxsd2Q9Mixjb2w9MixhbmdsZT0yMCxsZW5ndGg9LjEpCnRleHQoLTEwLC4zNSxsYWJlbD0icC12YWx1ZSIsc3J0PTkwLGNvbD0yKQphcnJvd3MoLTEwMCwuMix0Y3JpdCwuMixsd2Q9Mixjb2w9MixhbmdsZT0yMCxsZW5ndGg9LjEpCnRleHQocG9zPTQsbWVhbihjYXB0b3ByaWwkZGVsdGFTQlApL3NlLC4wMixsYWJlbD1wYXN0ZSgidD0iLHJvdW5kKG1lYW4oY2FwdG9wcmlsJGRlbHRhU0JQKS9zZSwyKSksY29sPTIpCmFycm93cygxMDAsLjIsdGNyaXQsLjIsbHdkPTIsY29sPTQsYW5nbGU9MjAsbGVuZ3RoPS4xKQp0ZXh0KHBvcz00LHRjcml0LC4wMixsYWJlbD1wYXN0ZSgidC1jcml0PSIscm91bmQodGNyaXQsMikpLGNvbD0yKQpwb2x5Z29uKGMocmVqZWN0LHRjcml0LC0xMCksYyhkdChyZWplY3Qsbi0xKSwwLDApLGNvbD0yLGJvcmRlcj0yKQp0ZXh0KC0zLjUsLjA1LGxhYmVsPWV4cHJlc3Npb24ocGFzdGUoYWxwaGEsIj0wLjA1IikpLGNvbD0yKQphcnJvd3MoLTIsMC4wMiwtMy41LC4wNCxjb2w9Mixsd2Q9MixhbmdsZT0yMCxsZW5ndGg9LjEpCmBgYAoKLS0tCgojIyBCZXNsaXNzaW5nc2ZvdXRlbgoKRGUgYmVzbGlzc2luZyBvbSAkSF8wJCB0ZSBhY2NlcHRlcmVuIG9mIHRlIHZlcndlcnBlbiB3b3JkdCBnZW5vbWVuIG9wIGJhc2lzIHZhbiBlZW4gZW5rZWxlIHN0ZWVrcHJvZWYuCkVyIGthbiBlZW4gdmVya2VlcmRlIGJlc2xpc3NpbmcgemlqbiBnZW5vbWVuLgoKYGBge3IsZWNobz1GQUxTRX0KbGlicmFyeSgia2FibGVFeHRyYSIpCkRlY2lzaW9uRXJyb3JzPWRhdGEuZnJhbWUoQ29uY2x1c2lvbj1jKCJBY2NlcHQgSDAiLCJSZWplY3QgSDAiKSwiSDAiPWMoIk9LIiwiVHlwZSBJICgkXFxhbHBoYSQpIiksIkgxIj1jKCJUeXBlIElJICgkXFxiZXRhJCkiLCJPSyIpKQprbml0cjo6a2FibGUoRGVjaXNpb25FcnJvcnMsLGFsaWduPSJjIiklPiUKICBrYWJsZV9zdHlsaW5nKCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUKICBhZGRfaGVhZGVyX2Fib3ZlKGMoIiAiID0gMSwgIlJlYWxpdHkiID0gMikpCmBgYAogLSBUeXBlIEkgZXJyb3IsICRcYWxwaGEkOiBkZSBudWwgaHlwb3RoZXNlIHdvcmR0IHRlbiBvbnJlY2h0ZSB2ZXJ3b3JwZW4gKHZhbHMgcG9zaXRpZWYpCiBcdnNwYWNlezEwcHR9CiAtIFR5cGUgSUkgZXJyb3IsICRcYmV0YSQ6IGRlIG51bGh5cG90aGVzZSB3b3JkdCB0ZW4gb25yZWNodGUgYWFudmFhcmQKCiAtIEJlc2xpc3NpbmcgaXMgb29rIHN0b2NoYXN0aXNjaCEgWmllIGVlcnN0ZSBob29mZHN0dWsgdmFuIGRlIGN1cnN1cwoKIyMjIENhcHRvcHJpbCBWb29yYmVlbGQKCi0gJEhfMCQ6IEhldCB0b2VkaWVuZW4gdmFuIGNhcHRvcHJpbCBoZWVmdCBnZWVuIGVmZmVjdCBvcCBkZSBzeXN0b2xpc2NoZSBibG9lZGRydWsKCi0gJEhfMSQ6IEhldCB0b2VkaWVuZW4gdmFuIGNhcHRvcHJpbCBsZWlkdCBnZW1pZGRlbGQgdG90IGVlbiB2ZXJsYWdpbmcgdmFuIGRlIGJsb2VkZHJ1awoKLSAqKlR5cGUgSSBlcnJvcioqOiBlciBpcyBnZW1pZGRlbGQgZ2VlbiBibG9lZGRydWtkYWxpbmcgYmlqIHRvZWRpZW5pbmcgdmFuIGNhcHRvcHJpbCwgbWFhciB3ZSBjb25jbHVkZXJlbiBkYXQgZXIgZWVuIGVmZmVjdCBpcyB2YW4gY2FwdG9wcmlsLgoKLSAqKlR5cGUgSUkgZXJyb3IqKjogZXIgaXMgZ2VtaWRkZWxkIGVlbiBibG9lZGRydWtkYWxpbmcgYmlqIHRvZWRpZW5pbmcgdmFuIGNhcHRvcHJpbCwgbWFhciBkZXplIHdvcmR0IG5pZXQgb3BnZW1lcmt0IGRvb3IgZGUgc3RhdGlzdGlzY2hlIHRlc3QuCgotLS0KCiMjIyBUeXBlIEkgZm91dCB3b3JkdCBnZWNvbnRyb2xlZXJkCgoKRGUgdHlwZSBJLWZvdXQgd29yZHQgZ2Vjb250cm9sZWVyZCBkb29yIGRlIGNvbnN0cnVjdGllIHZhbiBkZSBzdGF0aXN0aXNjaGUgdGVzdC4KCiQkXHRleHR7UH1cbGVmdFtcdGV4dHt0eXBlIEkgZXJyb3J9XHJpZ2h0XT1cdGV4dHtQfVxsZWZ0W1x0ZXh0e3JlamVjdCB9SF8wIFxtaWQgSF8wXHJpZ2h0XSA9IFx0ZXh0e1B9XzBcbGVmdFtUPHRfe24tMTsxLVxhbHBoYX1ccmlnaHRdPVxhbHBoYSAkJAoKCi0gSGV0IHNpZ25pZmljYW50aWVuaXZlYXUgJFxhbHBoYSQgaXMgZGUga2FucyBvbSBlZW4gdHlwZSBJLWZvdXQgdGUgbWFrZW4uCgotIERlIHN0YXRpc3Rpc2NoZSB0ZXN0IHpvcmd0IGVydm9vciBkYXQgZGUga2FucyBvcCBlZW4gdHlwZSBJLWZvdXQgd29yZHQgZ2Vjb250cm9sZWVyZCBvcCBoZXQgc2lnbmlmaWNhbnRpZW5pdmVhdSAkXGFscGhhJC4KCi0gRGUga2FucyBvbSAkSF8wJCBjb3JyZWN0IHRlIGFjY2VwdGVyZW4gaXMgJDEtXGFscGhhJC4KCi0gV2Uga3VubmVuIGFhbnRvbmVuIGRhdCBkZSBwLXdhYXJkZSBvbmRlciAkSF8wJCB1bmlmb3JtIHZlcmRlZWxkIGlzLgoKLSBIZXQgdGVzdGVuIHZhbiBzdGF0aXN0aXNjaGUgaHlwb3RoZXNlbiBsZWlkdCBkdXMgdG90IGVlbiB1bmlmb3JtZSBiZXNsaXNzaW5nc3N0cmF0ZWdpZS4KCldlIGlsbHVzdHJlcmVuIGRpdCBpbiBlZW4gc2ltdWxhdGllc3R1ZGllCgotIG49MTUKLSAkXG11PTAkIG1tSGcsIGVyIGlzIGR1cyBnZWVuIGVmZmVjdCB2YW4gZGUgYmVoYW5kZWxpbmcKLSAkXHNpZ21hID05JCBtbUhnCi0gMTAwMCBnZXNpbXVsZWVyZGUgc3RlZWtwcm9ldmVuCgpgYGB7cn0KbnNpbSA8LSAxMDAwMApuIDwtIDE1CnNpZ21hIDwtIDkKbXUgPC0gMAptdTAgPC0gMAphbHBoYSA8LSAwLjA1Cgojc2ltdWxhdGUgbnNpbSBzYW1wbGVzIG9mIHNpemUgbgpkZWx0YVNpbSA8LSBtYXRyaXgoCiAgcm5vcm0obipuc2ltLG11LHNpZ21hKSwKICBucm93PW4sCiAgbmNvbD1uc2ltKQoKcFNpbSA8LSBhcHBseSgKICBkZWx0YVNpbSwKICAyLAogIGZ1bmN0aW9uKHgsIG11LCBhbHRlcm5hdGl2ZSkgICAgCiAgICB0LnRlc3QoeCwKICAgICAgbXUgPSBtdSwKICAgICAgYWx0ZXJuYXRpdmUgPSBhbHRlcm5hdGl2ZSkkcC52YWx1ZSwKICAgICAgbXUgPSBtdTAsCiAgICAgIGFsdGVybmF0aXZlPSJsZXNzIgogICkKCm1lYW4ocFNpbTxhbHBoYSkKCnBTaW0gJT4lCiAgYXMuZGF0YS5mcmFtZSAlPiUKICBnZ3Bsb3QoYWVzKHg9LikpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICB4bGltKDAsMSkKYGBgCgotIERlIHR5cGUgSS1mb3V0IGlzIGluZGVyZGFhZCBvbmdldmVlciAwLDA1Ci0gRGUgcC13YWFyZGVuIHppam4gdW5pZm9ybQotLS0KCiMjIyBUeXBlIElJIGZvdXQKCi0gVHlwZSBJSS1mb3V0IGJlcGFsZW4gaXMgbWluZGVyIGR1aWRlbGlqay4KLSBXZSBtb2V0ZW4gcmVkZW5lcmVuIG9uZGVyICRIXzEkCi0gSW4gdGhlIGNhcHRvcHJpbCB2b29yYmVlbGQgaXMgJEhfMTogXG11PDAkCi0gRXIgemlqbiB2ZWVsIG1vZ2VsaWprZSBhbHRlcm5hdGlldmVuCi0gRGUgdmVyZGVsaW5nIG9uZGVyICRIXzEkIGlzIG5pZXQgdm9sbGVkaWcgZ2VzcGVjaWZpY2VlcmQKCi0gKm9wbG9zc2luZzoqIGtpZXMgZWVuIHNwZWNpZmlla2UgZGlzdHJpYnV0aWUgb25kZXIgJEhfMSQuCgogJCRIXzEoXGRlbHRhKTogXG11PTAtXGRlbHRhIFx0ZXh0eyBmb3IgfVxkZWx0YT4wLiQkCgotIGJpanYuIGVlbiBibG9lZGRydWt2ZXJzY2hpbCB2YW4gMiBtbUhnCgotIHR5cGUgSUkgd29yZHQgb29rIHdlbCBkZSAqKmtyYWNodCoqIG9mICJwb3dlciIgZ2Vub2VtZC4gSGV0IGlzIGRlIGthbnMgb20gZGUgYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSB0ZSBhYW52YWFyZGVuLgoKLSBIZXQgd29yZHQgbmlldCBnZWdhcmFuZGVlcmQgZG9vciBoZXQgZGVzaWduIHZhbiBkZSB0ZXN0CgotIEhldCBoYW5ndCBhZiB2YW4gZGUgZXhwZXJpbWVudGVsZSBvcHpldCB2YW4gZGUgc3R1ZGllCgoKYGBge3J9Cm5zaW0gPC0gMTAwMDAKbiA8LSAxNQpzaWdtYSA8LSA5Cm11IDwtIC0yCm11MCA8LSAwCmFscGhhIDwtIDAuMDUKCiNzaW11bGF0ZSBuc2ltIHNhbXBsZXMgb2Ygc2l6ZSBuCmRlbHRhU2ltIDwtIG1hdHJpeCgKICBybm9ybShuKm5zaW0sIG11LCBzaWdtYSksCiAgbnJvdz1uLAogIG5jb2w9bnNpbSkKCnBTaW0gPC0gYXBwbHkoCiAgZGVsdGFTaW0sCiAgMiwKICBmdW5jdGlvbih4LG11LGFsdGVybmF0aXZlKSAgICAgICAgICAKICAgIHQudGVzdCh4LAogICAgICBtdSA9IG11LAogICAgICBhbHRlcm5hdGl2ZSA9IGFsdGVybmF0aXZlKSRwLnZhbHVlLAogICAgICBtdSA9IG11MCwKICAgICAgYWx0ZXJuYXRpdmUgPSAibGVzcyIKICApCgptZWFuKHBTaW08YWxwaGEpCnBTaW0gJT4lCiAgYXMuZGF0YS5mcmFtZSAlPiUKICBnZ3Bsb3QoYWVzKHg9LikpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICB4bGltKDAsMSkKYGBgCi0gV2Ugb2JzZXJ2ZXJlbiBkYXQgZWVuIHBvd2VyIHZhbiBgciBtZWFuKHBTaW08YWxwaGEpYCBvZiBlZW4gdHlwZSBJSSBlcnJvciB2YW4gYHIgMS1tZWFuKHBTaW08YWxwaGEpYC4KCi0tLQoKLSBXYW5uZWVyIHdlIGRlIHN0ZWVrcHJvZWZncm9vdHRlIHZlcmdyb3RlbgoKCmBgYHtyfQpuc2ltIDwtIDEwMDAwCm4gPC0gMzAKc2lnbWEgPC0gOQptdSA8LSAtMgptdTAgPC0gMAphbHBoYSA8LSAwLjA1Cgojc2ltdWxhdGUgbnNpbSBzYW1wbGVzIG9mIHNpemUgbgpkZWx0YVNpbSA8LSBtYXRyaXgoCiAgcm5vcm0obipuc2ltLCBtdSwgc2lnbWEpLAogIG5yb3c9biwKICBuY29sPW5zaW0pCgpwU2ltIDwtIGFwcGx5KAogIGRlbHRhU2ltLAogIDIsCiAgZnVuY3Rpb24oeCxtdSxhbHRlcm5hdGl2ZSkgICAgICAgICAgCiAgICB0LnRlc3QoeCwKICAgICAgbXUgPSBtdSwKICAgICAgYWx0ZXJuYXRpdmUgPSBhbHRlcm5hdGl2ZSkkcC52YWx1ZSwKICAgICAgbXUgPSBtdTAsCiAgICAgIGFsdGVybmF0aXZlID0gImxlc3MiCiAgKQoKbWVhbihwU2ltIDwgYWxwaGEpCnBTaW0gJT4lCiAgYXMuZGF0YS5mcmFtZSAlPiUKICBnZ3Bsb3QoYWVzKHg9LikpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICB4bGltKDAsMSkKYGBgCgotIEhldCB2ZXJncm90ZW4gdmFuIGRlIHN0ZWVrcHJvZWZncm9vdHRlIGxlaWR0IHRvdCBlZW4gaG9nZXJlIHBvd2VyLgotIFRvY2ggYmxpamZ0IGRlIHBvd2VyIG9tIHpvJ24ga2xlaW5lIGJsb2VkZHJ1a2RhbGluZyBvcCB0ZSB2YW5nZW4gZXJnIGxhYWcuCi0gRWVuIGRhbGluZyB2YW4gMiBtbUhnIGlzIG9vayBuaWV0IHJlbGV2YW50IHZvb3IgZmFybWFjZXV0aXNjaGUgYmVkcmlqdmVuLgoKIVtdKGh0dHBzOi8vd3d3Lm5hdHVyZS5jb20vYXJ0aWNsZXMvbm1ldGguMjczOC5wZGYpe3dpZHRoPTEwMCV9CgotLS0KCiMjIyBJbnRlcnByZXRhdGllCgpTdGVsIGRhdCBlZW4gYmVwYWFsZGUgc3RlZWtwcm9lZiAkcCA8IFxhbHBoYSQsIGQudy56LiAkSF8wJCAgYWZ3aWp6ZW4KCi0gVHdlZSBtb2dlbGlqa2hlZGVuCgogICAgLSBDb3JyZWN0ZSBiZXNsaXNzaW5nLAoJICAtIG9mIHR5cGUgSSBmb3V0LgoKLSBXZSB3ZXRlbiBkYXQgZGUga2FucyBvcCBlZW4gdHlwZS1JIGZvdXQga2xlaW4gaXMsIGQudy56LiAkXGFscGhhPTAuMDUkLgoKCkFhbiBkZSBhbmRlcmUga2FudCBhbHMgJHBcZ2VxXGFscGhhJCBlbiB3ZSAkSF8wJCBuaWV0IGFmd2lqemVuIGhlYmJlbiB3ZSBvb2sgdHdlZSBvcHRpZXM6CgogIC0gQ29ycmVjdGUgYmVzbGlzc2luZywKICAtIG9mIHdlIGhlYmJlbiBlZW4gdHlwZSBJSSBmb3V0IGdlbWFha3QuCgpEZSBrYW5zIG9wIGVlbiB0eXBlIElJIGZvdXQgKCRcYmV0YSQpIHdvcmR0IG5pZXQgZ2Vjb250cm9sZWVyZCBvcCBlZW4gc3BlY2lmaWVrZSB3YWFyZGUuCgpTdGF0aXN0aXNjaGUgdGVzdCBpcyBnZWNvbnN0cnVlZXJkIG9tIGFsbGVlbiBkZSBrYW5zIG9wIGVlbiB0eXBlIEktZm91dCBvcCAgJFxhbHBoYSQgdGUgY29udHJvbGVyZW4uCgpPbSB3ZXRlbnNjaGFwcGVsaWprIGNvcnJlY3QgdGUgemlqbiwgbW9ldGVuIHdlIGVlbiBwZXNzaW1pc3Rpc2NoZSBob3VkaW5nIGFhbm5lbWVuIGVuIG1vZXRlbiB3ZSB0b2VnZXZlbiBkYXQgJFxiZXRhJCBncm9vdCBrYW4gemlqbiAoZC53LnouIGVlbiBrbGVpbmUgcG93ZXIgb20gaGV0IGFsdGVybmF0aWVmIHRlIGRldGVjdGVyZW4pLgoKRHVzLAoKLSAkcCA8IFxhbHBoYSQgd2UgdmVyd2VycGVuICRIXzAkCgogICAgLSBXZSBjb25jbHVkZXJlbiBkYXQgJEhfMSQgd2FhcnNjaGlqbmxpamsgY29ycmVjdCBpcwoJICAtIFdlIG5vZW1lbiBkaXQgZWVuIHN0ZXJrZSBjb25jbHVzaWUKCi0gJHAgXGdlcSBcYWxwaGEkIGFjY2VwdGVlciAkSF8wJCAgCgoJICAtIEJldGVrZW50IG5pZXQgZGF0IHdlICRIXzAkIGNvcnJlY3QgYWNjZXB0ZXJlbi4KICAJLSBXZSBrdW5uZW4gZW5rZWwgY29uY2x1ZGVyZW4gZGF0IGRlIGdlZ2V2ZW5zIG9udm9sZG9lbmRlIGJld3ppanMgaGViYmVuIHRlZ2VuIGRlICRIXzAkIGluIHZvb3JkZWVsIHZhbiAkSF8xJC4KICAgIC0gRGl0IG5vZW1lbiB3ZSBlZW4gendha2tlIGNvbmNsdXNpZQogICAgLSBXZSBjb25jbHVkZXJlbiBkb29yZ2FhbnMgZGF0IGhldCBlZmZlY3QgdmFuIGRlIGJlaGFuZGVsaW5nIG5pZXQgc2lnbmlmaWNhbnQgaXMuCgotLS0KCiMjIENvbmNsdXNpZXMgY2FwdG9wcmlsIHZvb3JiZWVsZAoKCkRlIHRlc3QgZGllIHdlIGhlYmJlbiB1aXRnZXZvZXJkLCB3b3JkdCBhYW5nZWR1aWQgYWxzCgoKLSBEZSAqKmVua2VsZSBzdGVla3Byb2VmIHQtdGVzdCoqIG9wIGhldCB2ZXJzY2hpbCBvZgoKLSBlZW4gKipnZXBhYXJkZSB0LXRlc3QqKi4gV2UgYmVzY2hpa2tlbiBpbmRlcmRhYWQgb3ZlciBnZXBhYXJkZSBvYnNlcnZhdGllcyB2b29yIGVsa2UgcGF0acOrbnQuCgotIERlIHRlc3QgaXMgZWVuemlqZGlnIGdlZGFhbiBvbWRhdCB3ZSB0ZXN0ZW4gdGVnZW4gaGV0IGFsdGVybmF0aWVmIHZhbiBlZW4gYmxvZWRkcnVrZGFsaW5nLgoKLSBCZWlkZSB0ZXN0cyAow6nDqW4gdm9vcmJlZWxkIHZhbiBlZW4gdC10ZXN0IG9wIGhldCB2ZXJzY2hpbCBlbiBlZW4gZ2VwYWFyZGUgdC10ZXN0KSBnZXZlbiBkZXplbGZkZSByZXN1bHRhdGVuOgoKYGBge3J9CnQudGVzdChjYXB0b3ByaWwkZGVsdGFTQlAsYWx0ZXJuYXRpdmU9Imxlc3MiKQpgYGAKCmBgYHtyfQp0LnRlc3QoY2FwdG9wcmlsJFNCUGEsY2FwdG9wcmlsJFNCUGIscGFpcmVkPVRSVUUsYWx0ZXJuYXRpdmU9Imxlc3MiKQpgYGAKCi0tLQoKIyMjIENvbmNsdXNpZQoKRXIgaXMgZ2VtaWRkZWxkIGVlbiBleHRyZWVtIHNpZ25pZmljYW50ZSBibG9lZGRydWtkYWxpbmcgYmlqIHRvZWRpZW5pbmcgdmFuIGNhcHRvcHJpbCBhYW4gcGF0acOrbnRlbiBtZXQgaHlwZXJ0ZW5zaWUuIERlIHN5c3RvbGlzY2hlIGJsb2VkZHJ1ayBkYWFsdCBnZW1pZGRlbGQgbWV0IDE4LDkgbW1IZyBiaWogZGUgYmVoYW5kZWxpbmcgbWV0IGNhcHRvcHJpbCAgKDk1JSBDSSBbJC1caW5mdHksLTE0LjgyJF0gbW1IZykuCgpMZXQgb3AgZGF0CgoxLiBFciB3b3JkdCBlZW4gZWVuemlqZGlnIGludGVydmFsIGdlcmFwcG9ydGVlcmQgb21kYXQgd2UgYWxsZWVuIGdlw69udGVyZXNzZWVyZCB6aWpuIGluIGVlbiBibG9lZGRydWtkYWxpbmcuCgoyLiBWYW53ZWdlIGRlIHByZXRlc3QgLyBwb3N0dGVzdCBvcHpldCBrdW5uZW4gd2UgZ2VlbiBvbmRlcnNjaGVpZCBtYWtlbiB0dXNzZW4gaGV0IGVmZmVjdCB2YW4gZGUgYmVoYW5kZWxpbmcgZW4gZWVuIHBsYWNlYm8tZWZmZWN0LiBFciB3YXMgZ2VlbiBnb2VkZSBjb250cm9sZSEgSGV0IG9udGJyZWtlbiB2YW4gZWVuIGdvZWRlIGNvbnRyb2xlIGtvbXQgbWVlc3RhbCB2b29yIGJpaiBwcmUtdGVzdCAvIHBvc3QtdGVzdCBkZXNpZ25zLiBIb2UgaGFkZGVuIHdlIGhldCBkZXNpZ24ga3VubmVuIHZlcmJldGVyZW4/CgotLS0KCiMjIGVlbnppamRpZyBvciB0d2VlemlqZGlnZSB0ZXN0ZW4/CgpEZSB0ZXN0IGluIGhldCBjYXB0b3ByaWwtdm9vcmJlZWxkIHdhcyBlZW4gZWVuemlqZGlnZSB0ZXN0LiBXZSBwcm9iZXJlbiBhbGxlZW4gdGUgZGV0ZWN0ZXJlbiBvZiBkZSBjYXB0b3ByaWxiZWhhbmRlbGluZyBnZW1pZGRlbGQgZGUgYmxvZWRkcnVrIHZlcmxhYWd0LgoKClN0ZWwgZGF0IHdlIGhldCBibG9lZGRydWt2ZXJzY2hpbCBoZWJiZW4gZ2VkZWZpbmllZXJkIGFscyAgJFhfe2l9XlxwcmltZT1ZX3tpfV5cdGV4dHtiZWZvcmV9LVlfe2l9Xlx0ZXh0e2FmdGVyfSQKCi0gTnUgZHVpZHQgZWVuIHBvc2l0aWV2ZSB3YWFyZGUgb3AgZWVuIGJsb2VkZHJ1a2RhbGluZwoKLSBEZSBnZW1pZGRlbGRlIHZlcmFuZGVyaW5nIGluIGJsb2VkZHJ1ayB3b3JkdCBudSBhYW5nZWR1aWQgYWxzICRcbXVeXHByaW1lPVx0ZXh0e0V9W1heXHByaW1lXSQuCgotIER1cyBudSBtb2V0ZW4gd2UgZWVuIGVlbnppamRpZ2UgdGVzdCBnZWJydWlrZW4gb20gJEhfMDogXG11XlxwcmltZT0wJCB0ZSBiZW9vcmRlbGVuIHRlZ2VuICRIXzE6IFxtdV5ccHJpbWU+MCQuCgotIHAtd2FhcmRlIHdvcmR0IG51OgokJHA9XHRleHR7UH1fMFxsZWZ0W1RcZ2VxIHRccmlnaHRdLiQkCgotLS0KCkFuYWx5c2UgZ2ViYXNlZXJkIG9wICRYXlxwcmltZSQ6IEFyZ3VtZW50IGBhbHRlcm5hdGl2ZT0iZ3JlYXRlciJgIFpvIGRhdCB3ZSAkSF8xOiBcbXVeXHByaW1lPjAkIGdlYnJ1aWtlbjoKYGBge3J9CnQudGVzdChjYXB0b3ByaWwkU0JQYi1jYXB0b3ByaWwkU0JQYSwgYWx0ZXJuYXRpdmU9ImdyZWF0ZXIiKQpgYGAKCgpOYXR1dXJsaWprIGJlaGFsZW4gd2UgZGV6ZWxmZGUgcmVzdWx0YXRlbi4gQWxsZWVuIGhldCB0ZWtlbiBpcyB2ZXJ3aXNzZWxkLgoKCiMjIyBUd2VlemlqZGlnZSB0ZXN0CgoKU3RlbCBkYXQgb25kZXJ6b2VrZXJzIGhldCB3ZXJraW5nc21lY2hhbmlzbWUgdmFuIGhldCBuaWV1d2UgbWVkaWNpam4gY2FwdG9wcmlsIGluIGRlIG9udHdlcnBmYXNlIHdpbGRlbiBiZW9vcmRlbGVuIGVuIHZlcm9uZGVyc3RlbCBkYXQgZ2V6b25kZSBwcm9lZnBlcnNvbmVuIGluIGVlbiB2cm9lZ2UgZmFzZSB2YW4gZGUgbWVkaWNpam5vbnR3aWtrZWxpbmcgd2VyZGVuIGdlYnJ1aWt0LgoKSW4gZGl0IGdldmFsIHpvdSBoZXQgaW50ZXJlc3NhbnQgemlqbiBnZXdlZXN0IG9tIHpvd2VsIGJsb2VkZHJ1a2RhbGluZ2VuIGFscyBzdGlqZ2luZ2VuIHdhYXIgdGUgbmVtZW4uCgpEYW4gaGViYmVuIHdlIGVlbiB0d2VlemlqZGlnZSB0ZXN0c3RyYXRlZ2llIG5vZGlnCgokJEhfMDogXG11PTAkJAp0ZWdlbiBkZSBhbHRlcm5hdGlldmUgaHlwb3RoZXNlCgokJEhfMTogXG11XG5lcTAsJCQKCnpvZGF0IGhldCBnZW1pZGRlbGRlIG9uZGVyIGhldCBhbHRlcm5hdGllZiB2ZXJzY2hpbHQgdmFuIG51bC4KCkhldCBrdW5uZW4gem93ZWwgcG9zaXRpZXZlIGFscyBuZWdhdGlldmUgdmVyYW5kZXJpbmdlbiB6aWpuIGVuIHdlIHdpc3RlbiB2YW4gdGV2b3JlbiBuaWV0IGluIHdlbGtlIHJpY2h0aW5nIGhldCB3ZXJrZWxpamtlIGdlbWlkZGVsZGUgemFsIGFmd2lqa2VuIHZhbiAkSF8xJC4KCgpXZSBrdW5uZW4gZWVuIHR3ZWV6aWpkaWdlIHRlc3QgdWl0dm9lcmVuIG9wIGhldCAkXGFscGhhPTVcJSQgc2lnbmlmaWNhbnRpZW5pdmVhdSBkb29yCgpgYGB7ciBvdXQud2lkdGg9JzEwMCUnLCBmaWcuYXNwPS44LCBmaWcuYWxpZ249J2NlbnRlcicsZWNobz1GQUxTRX0KZ3JpZCA8LXNlcSgtMTAsMTAsLjAxKQp0Y3JpdCA8LSBxdCgwLjk3NSxuLTEpCnJlamVjdDEgPC0gYyhncmlkW2dyaWQ8IC10Y3JpdF0sLXRjcml0KQpyZWplY3QyIDwtIGModGNyaXQsZ3JpZFtncmlkPnRjcml0XSkKCnBsb3QoZ3JpZCxkdChncmlkLG4tMSksdHlwZT0ibCIsbHdkPTIseGxhYj0idC1zdGF0aXN0aWMiLHlsYWI9ImRlbnNpdHkiLHlsaW09YygtLjA1LC40KSkKYWJsaW5lKHY9YygtMSwxKSptZWFuKGNhcHRvcHJpbCRkZWx0YVNCUCkvc2UsY29sPTIsbHdkPTIsbHR5PTIpCmFibGluZSh2PWMoLTEsMSkqdGNyaXQsY29sPTIsbHR5PTEsbHdkPTIpCnRleHQoYygtNSwtNSw1LDUpLGMoLS4wMywtLjA1LC0uMDMsLS4wNSksbGFiZWw9YygicmVqZWN0aW9uLSIsInJlZ2lvbiIsInJlamVjdGlvbi0iLCJyZWdpb24iKSxjb2w9YygyLDIsMiwyKSkKdGV4dChjKDAsMCksYygtLjAzLC0uMDUpLGxhYmVsPWMoImFjY2VwdGlvbi0iLCJyZWdpbyIpLGNvbD1jKDQsNCkpCgphcnJvd3MoLTEwMCwuNCwtYWJzKG1lYW4oY2FwdG9wcmlsJGRlbHRhU0JQKS9zZSksLjQsbHdkPTIsY29sPTIsYW5nbGU9MjAsbGVuZ3RoPS4xKQphcnJvd3MoMTAwLC40LGFicyhtZWFuKGNhcHRvcHJpbCRkZWx0YVNCUCkvc2UpLC40LGx3ZD0yLGNvbD0yLGFuZ2xlPTIwLGxlbmd0aD0uMSkKdGV4dCgtMTAsLjM1LGxhYmVsPSJwLXZhbHVlIixzcnQ9OTAsY29sPTIpCnRleHQoMTAsLjM1LGxhYmVsPSJwLXZhbHVlIixzcnQ9OTAsY29sPTIpCgphcnJvd3MoLTEwMCwtLjA0LC10Y3JpdCwtLjA0LGx3ZD0yLGNvbD0yLGFuZ2xlPTIwLGxlbmd0aD0uMSkKYXJyb3dzKDEwMCwtLjA0LHRjcml0LC0uMDQsbHdkPTIsY29sPTIsYW5nbGU9MjAsbGVuZ3RoPS4xKQoKcG9seWdvbihjKHJlamVjdDEsLXRjcml0LC0xMCksYyhkdChyZWplY3QxLG4tMSksMCwwKSxjb2w9Mixib3JkZXI9MikKcG9seWdvbihjKHRjcml0LHJlamVjdDIsdGNyaXQpLGMoMCxkdChyZWplY3QyLG4tMSksMCksY29sPTIsYm9yZGVyPTIpCgp0ZXh0KC0zLjUsLjA1LGxhYmVsPWV4cHJlc3Npb24ocGFzdGUoYWxwaGEsIi8yPTIuNSUiKSksY29sPTIpCnRleHQoMy42LC4wNSxsYWJlbD1leHByZXNzaW9uKHBhc3RlKGFscGhhLCIvMj0yLjUlIikpLGNvbD0yKQphcnJvd3MoLTMsMC4wMiwtMy41LC4wNCxjb2w9Mixsd2Q9MixhbmdsZT0yMCxsZW5ndGg9LjEpCmFycm93cygzLDAuMDIsMy41LC4wNCxjb2w9Mixsd2Q9MixhbmdsZT0yMCxsZW5ndGg9LjEpCmBgYAoKLS0tCgpIZXQgYXJndW1lbnQgYGFsdGVybmF0aXZlYCB2YW4gIGRlIGB0LnRlc3RgIGZ1bmN0aWUgaXMgaGVlZnQgZGVmYXVsdCB3YWFyZGUgYGFsdGVybmF0aXZlPSJ0d28uc2lkZWQiYC4KCmBgYHtyfQp0LnRlc3QoY2FwdG9wcmlsJGRlbHRhU0JQKQpgYGAKCi0gV2UgYmVoYWxlbiBub2cgc3RlZWRzIGVlbiBidWl0ZW5nZXdvb24gc2lnbmlmaWNhbnQgcmVzdWx0YWF0LgotIERlIHAtd2FhcmRlIGlzIGR1YmJlbCB6byBncm9vdCBvbWRhdCB3ZSB0d2VlemlqZGlnIHRlc3Rlbi4KCkluZGVyZGFhZAoKJCRwPVBfMFtUIFxsZXEgLVx2ZXJ0IHQgXHZlcnRdICsgUF8wW1QgXGdlcSBcdmVydCB0IFx2ZXJ0XSA9IFBfMFtcdmVydCBUIFx2ZXJ0IFxnZXEgXHZlcnQgdCBcdmVydF0gPSAyIFx0aW1lcyBQXzBbVCBcZ2VxIFx2ZXJ0IHQgXHZlcnRdJCQKCgotIFdlIHZlcmtyaWpnZW4gb29rIGVlbiB0d2VlemlqZGlnIGJldHJvdXdiYWFyaGVpZHNpbnRlcnZhbAoKLS0tCgojIyMgRcOpbnppamRpZ2Ugb2YgdHdlZXppamRpZ2UgdGVzdD8KCk1ldCBlZW4gZWVuemlqZGlnZSB0ZXN0IGt1bm5lbiB3ZSAkSF8wJCBnZW1ha2tlbGlqa2VyIGFmd2lqemVuIG9wIHZvb3J3YWFyZGUgZGF0ICRIXzEkIHdhYXIgaXMgZGFuIG1ldCBlZW4gdHdlZXppamRpZ2UgdGVzdC4KCgotIEFsbGUgaW5mb3JtYXRpZSB3b3JkdCBnZWJydWlrdCBvbSBpbiDDqcOpbiByaWNodGluZyB0ZSB0ZXN0ZW4KCi0gRGUgYmVzbGlzc2luZyBvbSBlZW56aWpkaWcgdGUgdGVzdGVuIG1vZXQgaW4gZGUgb250d2VycGZhc2Ugd29yZGVuIGdlbm9tZW4gdm9vcmRhdCBoZXQgZXhwZXJpbWVudCB3b3JkdCB1aXRnZXZvZXJkCgotIFplbGZzIGFscyB3ZSBzdGVya2UgYSBwcmlvcmkgYWFubmFtZXMgaGViYmVuLCB6aWpuIHdlIGVyIG5pZXQgaGVsZW1hYWwgemVrZXIgdmFuLCBhbmRlcnMgem91ZGVuIHdlIGdlZW4gcmVkZW4gaGViYmVuIG9tIGhldCBvbmRlcnpvZWsgdGUgZG9lbi4KCi0gQWxzIHdlIGluIGRlIG9udHdlcnBmYXNlIGVlbiBlZW56aWpkaWdlIHRlc3Qgdm9vcnN0ZWxsZW4gZW4gd2UgemllbiBlZW4gcmVzdWx0YWF0IGluIHRlZ2VuZ2VzdGVsZGUgcmljaHRpbmcgZGF0IHN0YXRpc3Rpc2NoIHNpZ25pZmljYW50IHpvdSB6aWpuLCBrdW5uZW4gd2UgZ2VlbiBjb25jbHVzaWVzIHRyZWtrZW4gdWl0IGhldCBleHBlcmltZW50LgoKLSBJbiBkZSBvbnR3ZXJwZmFzZSBoZWJiZW4gd2UgZGl0IHJlc3VsdGFhdCB1aXRnZXNsb3RlbiBvbWRhdCBoZXQgem8gb252ZXJ3YWNodCBpcyBkYXQgaGV0IGVlbiB2YWxzIHBvc2l0aWVmIG1vZXQgemlqbi4KCi0gRGFhcm9tIHdvcmRlbiBlZW56aWpkaWdlIHRlc3RzIG5pZXQgYWFuYmV2b2xlbi4KCkVlbiB0d2VlemlqZGlnZSB0ZXN0IGthbiBhbHRpamQgd29yZGVuIHZlcmRlZGlnZCBlbiBzdGVsdCB1IGluIHN0YWF0IGVsa2UgYWZ3aWpraW5nIHZhbiAkSF8wJCB0ZSBkZXRlY3RlcmVuIGVuIHdvcmR0IHRlbiB6ZWVyc3RlIGFhbmJldm9sZW4uCgoKSGV0IGlzICoqbm9vaXQgdG9lZ2VzdGFhbioqIG9tIGVlbiB0d2VlemlqZGlnZSB0ZXN0IHRlIHZlcmFuZGVyZW4gaW4gZWVuIGVlbnppamRpZ2UgdGVzdCBvcCBiYXNpcyB2YW4gd2F0IGVyIGluIGRlIHN0ZWVrcHJvZWYgaXMgd2Fhcmdlbm9tZW4hIEFuZGVycyB3b3JkdCBkZSB0eXBlIEktZm91dCB2YW4gZGUgdGVzdHN0cmF0ZWdpZSBuaWV0IGNvcnJlY3QgZ2Vjb250cm9sZWVyZC4KCi0tLQoKV2UgaWxsdXN0cmVyZW4gZGl0IGluIG9uZGVyc3RhYW5kZSBzaW11bGF0aWVzdHVkaWU6CgoxLiBjb3JyZWN0ZSB0d2VlemlqZGlnZSB0ZXN0IGVuCjIuIGVlbnppamRpZ2UgdGVzdCBtZXQgemlqbiB0ZWtlbiBnZWJhc2VlcmQgb3Agd2F0IHdlcmQgd2Fhcmdlbm9tZW4gaW4gZGUgc3RlZWtwcm9lZi4KCgpgYGB7cn0Kc2V0LnNlZWQoMTE1KQptdSA8LSAwCnNpZ21hIDwtIDkuMApuU2ltIDwtIDEwMDAKYWxwaGEgPC0gMC4wNQpuIDwtIDE1CgpwdmFsc0NvciA8LQogIHB2YWxzSW5Db3IgPC0KICBhcnJheSgwLG5TaW0pCgpmb3IgKGkgaW4gMTpuU2ltKQp7Cgl4IDwtIHJub3JtKG4sIG1lYW4gPSBtdSwgc2QgPSBzaWdtYSkKCXB2YWxzQ29yW2ldIDwtIHQudGVzdCh4KSRwLnZhbHVlCglpZiAobWVhbih4KSA8IDApCgkJcHZhbHNJbkNvcltpXSA8LSB0LnRlc3QoeCwgYWx0ZXJuYXRpdmUgPSAibGVzcyIpJHAudmFsdWUgZWxzZQoJCXB2YWxzSW5Db3JbaV0gPC0gdC50ZXN0KHgsIGFsdGVybmF0aXZlID0gImdyZWF0ZXIiKSRwLnZhbHVlCn0KCm1lYW4ocHZhbHNDb3IgPCAwLjA1KQptZWFuKHB2YWxzSW5Db3IgPCAwLjA1KQpgYGAKCi0gVHlwZSBJLWZvdXQgY29ycmVjdCBnZWNvbnRyb2xlZXJkIG9wICAkXGFscGhhJCB2b29yIHR3ZWV6aWpkaWdlIHRlc3QuCi0gVHlwZSBJLWZvdXQgbmlldCBjb3JyZWN0IGdlY29udHJvbGVlcmQgd2FubmVlciB3ZSBlZW56aWpkaWcgdGVzdGVuIG9wIGJhc2lzIHZhbiB3YXQgd2UgaW4gZGUgc3RlZWtwcm9lZiBoZWJiZW4gd2Fhcmdlbm9tZW4uCgojIE5hdHVyZSBjb2x1bW4gb3ZlciB0ZXN0ZW4KCiFbXShodHRwczovL3d3dy5uYXR1cmUuY29tL2FydGljbGVzL25tZXRoLjI2OTgucGRmKXt3aWR0aD0xMDAlfQoKIyBHZWNsdXN0ZXJkZSBtZXRpbmdlbgoKLSBEYXRhIG5pZXQgYWx0aWpkIG9uYWZoYW5rZWxpamsuCi0gQ29uc2VxdWVudGllcyB2b29yIHNjaGF0dGVuIHZhbiBzdGFuZGFhcmQgZXJyb3JzCgojIyBWb29yYmVlbGQKCi0gU3R1ZGllZGVzaWduIG1ldCAkbiQgcGxhbnRlbgotIEV4cHJlc3NpZSB2YW4gYmVwYWFsZCBnZW4gd29yZHQgMiBtYWFsIGdlbWV0ZW4KLSBNZW4gaXMgZ2XDr250ZXJlc3NlZXJkIGluIGdlbWlkZGVsZGUgZ2VuZXhwcmVzc2llLgotICRZX3tpMX0kIGVuICRZX3tpMn0kIGRlIGVlcnN0ZSBlbiB0d2VlZGUgbWV0aW5nCnZvb3IgcGxhbnQgJGk9MSwuLi4sbiQ6ClxiZWdpbntlcXVhdGlvbip9ClxiYXIgWSA9IFxzdW1fe2k9MX1ebiBcZnJhY3tZX3tpMX0rWV97aTJ9fXsybn0KXGVuZHtlcXVhdGlvbip9CgotIFN0ZWwgcGxhbnRlbiBvbmFmaGFua2VsaWprCi0gRWVyc3RlIGVuIHR3ZWVkZSBtZXRpbmdlbiBldmVuIHZhcmlhYmVsICgpJFx0ZXh0e1Zhcn0oWV97aTF9KT1cdGV4dHtWYXJ9KFlfe2kyfSk9XHNpZ21hXjIkKQotIFZhcmlhbnRpZSBvcCBzdGVla3Byb2VmZ2VtaWRkZWxkZToKXGJlZ2lue2VxbmFycmF5Kn0KXHRleHR7VmFyfShcYmFyIFkpJj0mXHN1bV97aT0xfV5uIFxmcmFje1x0ZXh0e1Zhcn0oWV97aTF9K1lfe2kyfSl9ezRuXjJ9IFxcCiY9JlxzdW1fe2k9MX1ebiBcZnJhY3tcc2lnbWFeMitcc2lnbWFeMisyXHRleHR7Q29yfShZX3tpMX0sWV97aTJ9KVxzaWdtYV4yfXslCjRuXjJ9IFxcCiY9JlxmcmFje1xzaWdtYV4yfXsybn1cezErXHRleHR7Q29yfShZX3sxfSxZX3syfSlcfQpcZW5ke2VxbmFycmF5Kn0KCi0gTWV0aW5nZW4gYWZrb21zdGlnIHZhbiB6ZWxmZGUgcGxhbnQgZG9vcmdhYW5zCnBvc2l0aWVmIG1ldCBlbGthYXIgZ2Vjb3JyZWxlZXJkIHppam4KLSAkU0Vfe1xiYXIgWX0kIGR1cwpncm90ZXIgZGFuIGJpaiAkMm4kIG1ldGluZ2VuIHZhbiAkMm4kIHZlcnNjaGlsbGVuZGUKcGxhbnRlbgotIEdlZ2V2ZW4gZWVyc3RlIG1ldGluZyAkWV97aTF9JCBicmVuZ3QgZGUgdHdlZWRlIG1ldGluZyAkWV97aTJ9JCBnZWVuIHZvbGxlZGlnIG5pZXV3ZSBpbmZvcm1hdGllIGJpagotIEVyIGlzIGJpamdldm9sZyBtaW5kZXIgaW5mb3JtYXRpZSBiZXNjaGlrYmFhciBvbSBoZXQgZ2VtaWRkZWxkZSB0ZQpzY2hhdHRlbiBkYW4gd2FubmVlciBhbGxlIGdlZ2V2ZW5zIHZhbiB2ZXJzY2hpbGxlbmRlIHBsYW50ZW4gYWZrb21zdGlnCndhcmVuLgoKV2F0IGJpaiB0d2VlIGV4dHJlbWVuOgoKLSBTdGVsIGRhdCAkXHRleHR7Q29yfShZX3sxfSxZX3syfSk9MSQgdHdlZWRlIG1ldGluZyBnZWVuIG5pZXV3ZSBpbmZvcm1hdGllIGVuIHplbGZkZSBuYXV3a2V1cmlnaGVpZCBhbHMgd2FubmVlciB3ZSBhbGxlZW4gZGUgbiBlZXJzdGUgbWV0aW5nZW4gYmVzY2hvdXdlbgotIFdhbm5lZXIgJFx0ZXh0e0Nvcn0oWV97MX0sWV97Mn0pPTAkLCB0d2VlZGUgbWV0aW5nIHZvbGxlZGlnIG5pZXV3ZSBpbmZvcm1hdGllIGVuIGR1cyBlZW56ZWxmZGUgbmF1d2tldXJpZ2hlaWQgYWxzIGJpaiAxIG1ldGluZyB2b29yICQybiQgaS5wLnYuICRuJCB2ZXJzY2hpbGxlbmRlIHBsYW50ZW4uIFZlcm1pdHMKXFtcZnJhY3tcc2lnbWFeMn17Mm59XHsxK1x0ZXh0e0Nvcn0oWV97MX0sWV97Mn0pXH1cZ2VxIFxmcmFje1xzaWdtYV4yfXsybn1cXQoKKldhbm5lZXIgZGUgY29ycmVsYXRpZSB0dXNzZW4gaGVyaGFhbGRlIGdlbmV4cHJlc3NpZSBtZXRpbmdlbiBwb3NpdGllZiBpcyAoaGV0Z2VlbiB3ZSB2ZXJ3YWNodGVuKSwgemFsIG1lbiBpbiBkZSBwcmFrdGlqayBtZWVyIHByZWNpZXNlIHJlc3VsdGF0ZW4gYmVrb21lbiBkb29yIDEgbWV0aW5nIHRlIGJlcGFsZW4gdm9vciAkMm4kIHZlcnNjaGlsbGVuZGUgcGxhbnRlbiBkYW4gZG9vciAyIG1ldGluZ2VuIHRlIGJlcGFsZW4gdm9vciAkbiQgdmVyc2NoaWxsZW5kZSBwbGFudGVuLioKCi0gQWxzIGVyIGV2ZW52ZWVsIGhlcmhhYWxkZSBtZXRpbmdlbiB6aWpuIHZvb3IgZWxrIHN1YmplY3QvZXhwZXJpbWVudGVsZSB1bml0ICh2YiBwbGFudCkgZGFuIGthbiBtZW4gbWV0aW5nZW4gb29rIHJlZHVjZXJlbiBuYWFyICRuJCBvbmFmaGFua2VsaWprZSBtZXRpbmdlbiBkb29yIGhldCBnZW1pZGRlbGRlIHRlIGJlcmVrZW5lbiBwZXIgZXhwZXJpbWVudGVsZSB1bml0LgotIE9tZGF0IGRlIGdlbWlkZGVsZGVzIHBlciBleHBlcmltZW50ZWxlIHVuaXQgemlqbiBnZWJhc2VlcmQgb3AgZXZlbnZlZWwgaGVyaGFhbGRlIG1ldGluZ2VuIHphbCBkZSBwcmVjaXNpZSB2YW4gZGllIGdlbWlkZGVsZGVzIGhldHplbGZkZSB6aWpuLgotIEJpaiB2ZXJzY2hpbGxlbmQgYWFudGFsIGhlcmhhYWxkZSBtZXRpbmdlbiBwZXIgZXhwZXJpbWVudGVsZSB1bml0IGthbiBtZW4gTklFVCBtZXQgZ2VtaWRkZWxkZXMgcGVyIEV4cC4gdW5pdCB3ZXJrZW4gd2FudCBkaWUgaGViYmVuIGFuZGVycyBlZW4gdmVyc2NoaWxsZW5kZSBwcmVjaXNpZQokbG9uZ3JpZ2h0YXJyb3ckIGRhbiB6aWpuIG1lZXIgZ2VhdmFuY2VlcmRlIG1ldGhvZGVuIG5vZGlnIQoKIyMgQ2FwdG9wcmlsCgotIE1ldGluZ2VuIGdlY2x1c3RlcmQ6IHR3ZWUgc3lzdG9saXNjaGUgYmxvZWRkcnVrbWV0aW5nZW4gcGVyIHBhdGnDq250CgogICAgLSAxIG1ldGluZyB2b29yIGVuCiAgICAtIDEgbWV0aW5nIG5hIGhldCB0b2VkaWVuZW4gdmFuIGNhcHRvcHJpbC4KCi0gR2VtaWRkZWxkZSBibG9lZGRydWt2ZXJhbmRlcmluZyAkXG11JCAgc2NoYXR0ZW4gYS5kLmgudi4gZ2VnZXZlbnMKJCQoWV97aTF9ICwgWV97aTJ9KSwkJAp2b29yIHN1YmplY3RlbiAkaSA9IDEsIC4uLiwgbiQuCgokJFxiYXIgWCA9IFxzdW1fe2k9MX1ebiBcZnJhY3tZX3tpMn0tWV97aTF9fXtufSQkCgpVaXQgcmVrZW5yZWdlbHMgdm9vciB2YXJpYW50aWU6ClxiZWdpbntlcW5hcnJheSp9Clx0ZXh0e1Zhcn1cbGVmdFtcYmFyIFhccmlnaHRdJj0mXHN1bV97aT0xfV5uIFxmcmFje1x0ZXh0e1Zhcn1cbGVmdFtZX3tpMX0tWV97aTJ9XHJpZ2h0XX17bl4yfVxcCiY9JlxzdW1fe2k9MX1ebiBcZnJhY3tcc2lnbWFeMl8xK1xzaWdtYV4yXzItMlx0ZXh0e0Nvcn1cbGVmdFtZX3tpMX0sWV97aTJ9XHJpZ2h0XVxzaWdtYV8xXHNpZ21hXzJ9e25eMn1cXAomPSZcZnJhY3tcc2lnbWFeMl8xK1xzaWdtYV4yXzItMlx0ZXh0e0Nvcn1cbGVmdFtZX3tpMX0sWV97aTJ9XHJpZ2h0XVxzaWdtYV8xXHNpZ21hXzJ9e259LFxcClxlbmR7ZXFuYXJyYXkqfQoKYGBge3J9CiNmdW5jdGllIHZhciBvcCBlZW4gbWF0cml4IGJlcmVrZW50IHZhcmlhbnRpZXMgc2lnbWFfMV4yLCBzaWdtYV8yXjIKI2NvdmFyaWFudGllIHNpZ21hX3sxMn0KdmFycyA8LSB2YXIoY2FwdG9wcmlsWyxjKCJTQlBiIiwiU0JQYSIpXSkKdmFycwpjb3IoY2FwdG9wcmlsJFNCUGEsY2FwdG9wcmlsJFNCUGIpCgp2YXJYYmFyRGVsdGEgPC0gKHZhcnNbMSwxXSt2YXJzWzIsMl0tMip2YXJzWzEsMl0pLzE1CnNxcnQodmFyWGJhckRlbHRhKQpgYGAKCi0gTWV0aW5nZW4gaGVlbCBzdGVyayBnZWNvcnJlbGVlcmQuICBWYXJpYW50aWUgb3AgaGV0IHZlcnNjaGlsIHZlZWwgbGFnZXIgZGFuIG9wIGRlIG9yaWdpbmVsZSBtZXRpbmdlbiEKCi0gYWx0ZXJuYXRpZXZlIG1ldGhvZGUgb20gZGUgc3RhbmRhcmQgZXJyb3IgdGUgYmVwYWxlbjoKCiAgLSBnZWNvcnJlbGVlcmRlIG1ldGluZ2VuIHRvdCAxIG1ldGluZyB0ZSByZWR1Y2VyZW4KICAtIGthbiBlbmtlbCB2b29yIGRlc2lnbiBtZXQgZ2VwYWFyZGUgbWV0aW5nZW4gKDIgbWV0aW5nZW4gcGVyIHBhdGllbnQpCiAgLSBBbGxlIHZlcnNjaGlsbGVuIHppam4gb25hZmhhbmtlbGlqay4KCiQkWF97aX09WV97YWl9LVlfe2JpfSQkCiAgIC0gdmVydm9sZ2VucyBzdGFuZGFyZCBlcnJvciBvcCAkXGJhciBYJC4KCkluIGhldCBjYXB0b3ByaWwgdm9vcmJlZWxkIHdvcmR0IGRlIHNjaGF0dGluZwpgYGB7cn0Kc2QoY2FwdG9wcmlsJGRlbHRhU0JQKS9zcXJ0KDE1KQpgYGAKCi0gRXhhY3QgZGV6ZWxmZGUgc2NoYXR0aW5nIHZvb3Igc3RhbmRhcmQgZXJyb3IKCi0gR3Jvb3Qgdm9vcmRlZWwgdmFuIGRlc2lnbjoKCiAgICAtIGJsb2VkZHJ1a21ldGluZ2VuIHZvb3IgZW4gbmEgc3RlcmsgcG9zaXRpZWYgZ2Vjb3JyZWxlZXJkICRcbG9uZ3JpZ2h0YXJyb3ckIHZhcmlhbnRpZSB2YW4gdmVyc2NoaWwgdmVlbCBsYWdlciBkYW4gZGF0IG9wIG9yaWdpbmVsZSBibG9lZGRydWttZXRpbmdlbgoKICAgIC0gSWVkZXJlIHBhdGnDq250IGRpZW50IGltbWVycyBhbHMgemlqbiBlaWdlbiBjb250cm9sZQogICAgLSBXZSBrdW5uZW4gdmFyaWFiaWxpdGVpdCBpbiBibG9lZGRydWttZXRpbmdlbiB0dXNzZW4gcGF0acOrbnRlbiB1aXQgZGUgYW5hbHlzZSB2ZXJ3aWpkZXJlbiEKCi0gRWVuIGdlcGFhcmQgZXhwZXJpbWVudCBpcyBzcGVjaWFsZSB2b3JtIHZhbiByYW5kb21pemVkIGNvbXBsZXRlIGJsb2NrIGRlc2lnbjoKCiAgICAtIEVsa2UgcGVyc29vbiBpcyBlZW4gYmxvayBlbgogICAgLSBFbGtlIGJlaGFuZGVsaW5nIGdldGVzdCBibG9rOiBlZW4gY29udHJvbGUgYmxvZWRkcnVrbWV0aW5nIGVuIGVlbiBibG9lZGRydWttZXRpbmcgbmEgdG9lZGllbmVuIHZhbiBjYXB0b3ByaWwKICAgIC0gRXIgaXMgZWVuIGdyb3RlIHZhcmlhYmlsaXRlaXQgdHVzc2VuIGJsb2trZW4hICRcbG9uZ3JpZ2h0YXJyb3ckIEJsb2VkZHJ1ayBob29nIHZvb3IgbWVlc3RhbCBvb2sgYmxvZWRkcnVrIGhvb2cgbmEgY2FwdG9wcmlsIGJlaGFuZGVsaW5nLgogICAgLSBzdGFuZGFhcmRkZXZpYXRpZSBpbiBibG9lZGRydWsgdHVzc2VuIHBhdGllbnRlbiB2b29yIHRvZWRpZW5lbiB2YW4gY2FwdG9wcmlsIGJlZHJhYWd0ICBgciByb3VuZChzZChjYXB0b3ByaWwkU0JQYiksMSlgIG1tSGcuCgogICAgLSBFZmZlY3QgdmFuIGNhcHRvcHJpbCBzY2hhdHRlbiBiaW5uZW4gcGF0aWVudC4KICAgIC0gRG9vciBoZXQgYmxva2Rlc2lnbiB2YXJpYWJpbGl0ZWl0IHR1c3NlbiBwYXRpw6tudGVuIHVpdCBkZSBhbmFseXNlIHdlcmVuLgogICAgLSBWb29yIGVlbiBnZXBhYXJkIGRlc2lnbiBrYW4gZGF0IGRvb3IgYi52LiBhbmFseXNlIG9wIGJsb2VkZHJ1a3ZlcnNjaGlsbGVuLgogICAgLSBTdGFuZGFhcmQgZXJyb3Igb3AgYmxvZWRkcnVrIHZlcnNjaGlsbGVuIHR1c3NlbiBwYXRpw6tudGVuIGlzIGluZGVyZGFhZCB2ZWVsIGxhZ2VyIGByIHJvdW5kKHNkKGNhcHRvcHJpbCRkZWx0YVNCUCksMilgLgogICAgLSBWb29yIGJsb2sgZGVzaWduIG1ldCBtZWVyIG1ldGluZ2VuIHBlciBibG9rIGFuYWx5c2UgbWV0IG1lZXJ2b3VkaWcgcmVncmVzc2llIG1vZGVsIChIb29mZHN0dWsgMTApLgoKSG9lIGt1bm5lbiB3ZSBoZXQgY2FwdG9wcmlsIGV4cGVyaW1lbnQgdmVyZGVyIHZlcmJldGVyZW4/CgotLS0KCiMgW0hvbWVdKGh0dHBzOi8vc3RhdG9taWNzLmdpdGh1Yi5pby9zYmMyMCkgey19Cg==