(Danke an Denise, May und Sophia fürs Korrekturlesen)

Das hier ist eine semi-interaktive Formelsammlung über alle wichtigen Formeln der Statistik 2 Vorlesung. Zu den meisten Formeln und Tests sind entsprechende R Beispiele zur Berechnung beigefügt, diese am besten per Copy-Paste in RStudio einfügen und eigene Werte einsetzen. Alternativ kann das ganze Notebook in RStudio ausgeführt werden: rechts oben auf Code -> Download Rmd klicken und die heruntergeladene Datei in RStudio öffnen.

Download für Offline-Nutzung: Rechtsklick irgendwo auf die Seite -> Speichern unter -> Website, nur HTML (wichtig). Anschließend das gespeicherte Dokument einfach mit dem Browser öffnen.

Falls zu unübersichtlich: rechts oben auf Code -> Hide all Code klicken. Anschließend beim entsprechenden Abschnitt rechts auf Code klicken, um die passenden wieder einzublenden.

Folgende Pakete werden zum Ausführen der Codebeispiele benötigt:

install.packages(c("DescTools", "effsize", "MBESS", "pwr", "multcomp", "forcats", "car"))
Zurück zur Homepage

Inhaltsverzeichnis

Mehrere Hypothesentests

Sonderfall: Mehrere nicht zusammengesetzte Hypothesentests mit unterschiedlichen Hypothesen \(\rightarrow\) niedrige FDR sicherstellen, aber keine Korrektur

Zusammengesetzte Hypothesentests

Zusammengesetzte Hypothese mit oder

\[\large \begin{array}{r} H_{0}: H_{01} \text { und } H_{02} \text { und } \ldots \text { und } H_{0 N} \\ H_{1}: H_{11} \text { oder } H_{12} \text { oder } \ldots \text { oder } H_{1 N} \end{array}\]

Zusammengesetzte Hypothese mit und

\[\large \begin{aligned} H_{0}: H_{01} \text { oder } H_{02} \text { oder } \ldots \text { oder } H_{0 N} \\ H_{1}: H_{11} \text { und } H_{12} \text { und } \ldots \text { und } H_{1 N} \end{aligned}\]

Korrektur des Signifikanzniveaus

Grundsätzlich gilt: Nur zusammengesetzte Hypothesen mit oder müssen korrigiert werden.

\(\alpha\): Comparison Wise Error Rate (einzelne Tests)

\(\alpha^{*}\): Family Wise Error Rate (zusammengesetzter Test)

  • Wahrscheinlichkeit, bei einer Gruppe von HT mindestens einen Fehler erster Art zu machen

\[\large \alpha^{*}=1-(1-\alpha)^{N}\]

alpha = 0.005
N = 5

1-(1-alpha)^N
Sidak

Für unabhängige Hypothesentests

\[\large \alpha=1-\sqrt[N]{1-\alpha^{*}}\]

fwer = 0.005
N = 5

1-(1-fwer)^(1 / N)
Bonferroni

Auch für abhängige Hypothesentests

\[\large \alpha=\frac{\alpha^{\prime}}{N}\] \[\large \alpha^{*} \leq \alpha^{\prime}\]

fwer = 0.005
N = 5

fwer/N

Alternativ: p-Werte korrigieren

\[\large p_{j} \leq \frac{\alpha^{\prime}}{N} \Leftrightarrow N \cdot p_{j} \leq \alpha^{\prime}\]

p_werte = c(0.003, 0.004)
p.adjust(p_werte, method = 'bonferroni')
Tukey

Auch für abhängige Hypothesentests, jedoch nur in varianzanalytischen Modellen und Regressionsmodellen möglich. Hier höhere Power als Bonferroni.

FWER für zusammengesetzte Hypothesen mit “und”

\[\large \alpha^{*}=\alpha^{k} \cdot(1-\beta)^{n-k}\]

# Anzahl Studien
n = 3

# Anzahl Studien, in denen H0 korrekt ist (n*Basisrate)
k = 1

alpha = 0.05
power = 0.8


alpha**k*(power)**(n-k)

Metaanalyse (mit festen Effekten)

Mehrere Hypothesentests aus verschiedenen Stichproben mit identischen Hypothesen

Ausgangslage: N Studien schätzen Effektstärke \(\theta\) mit Funktion \(\hat{\theta}_{j}\), Annahme: \(\hat{\theta}_{j} \stackrel{i n d}{\sim} N\left(\theta, \sigma_{j}^{2}\right)\)

Schätzfunktion:

\[\large \hat{\theta}=\frac{1}{\sum_{j=1}^{N} W_{j}} \sum_{j=1}^{N} W_{j} \cdot \hat{\theta}_{j}\]

weights = c(0.5, 0.5, 0.8)
thetas = c(-0.2, 0.5, 0.4)
  
1/(sum(weights)) * sum(weights * thetas)

\[\large W_{j}=\frac{1}{\hat{\sigma}_{j}^{2}}\]

varj = 2.5

1/varj

\[\large \hat{\sigma}_{j \text { wert }}^{2}=\frac{n_{1 j}+n_{2 j}}{n_{1 j} \cdot n_{2 j}}+\frac{d_{j}^{2}}{2 \cdot\left(n_{1 j}+n_{2 j}\right)}\]

n1=20
n2=20
d = 1.0

((n1+n2)/(n1*n2))+(d*d/(2*(n1+n2)))

\[\large d_{j}=t_{j} \cdot \sqrt{\frac{n_{1 j}+n_{2 j}}{n_{1 j} \cdot n_{2 j}}}\]

n1=20
n2=20
t = 3.2

t*sqrt((n1+n2)/(n1*n2))

\[\large d_{j}=\frac{\bar{x}_{1 j}-\bar{x}_{2 j}}{s_{\text {pool }, j}}\]

data1 = c(0,0,-1)
data2 = c(2,0,1)
n1 = length(data1)
n2 = length(data2)
x1_quer = mean(data1)
x2_quer = mean(data2)
xdiff_quer = x1_quer-x2_quer
s2_1 = var(data1)
s2_2 = var(data2)
s2pool = ((n1-1)*s2_1+(n2-1)*s2_2)/(n1+n2-2)
xdiff_quer/sqrt(s2pool)

Intervall mit approximativem Konfidenzniveau von \(1-\alpha\):

\[\large I\left(\hat{\theta}_{1}, \hat{\theta}_{2}, \ldots, \hat{\theta}_{N}\right)=\left[\hat{\theta}-z_{1-\frac{\alpha}{2}} \cdot \frac{1}{\sqrt{\sum_{j=1}^{N} W_{j}}}, \hat{\theta}+z_{1-\frac{\alpha}{2}} \cdot \frac{1}{\sqrt{\sum_{j=1}^{N} W_{j}}}\right]\]

conf.level = 0.95

weights = c(0.5, 0.5, 0.8)
thetas = c(-0.2, 0.5, 0.4)
theta_est = 1/(sum(weights)) * sum(weights * thetas)


c = qnorm(1-((1-conf.level)/2))/sqrt(sum(weights))
c(theta_est - c, theta_est + c)

Hypothesentest Metaanalyse:

Hypothesen:

\[\large \begin{aligned} &\mathrm{H}_{0}: \delta \leq 0 \\ &\mathrm{H}_{1}: \delta>0 \end{aligned}\]

Teststatistik:

\[\large T=\left(\hat{\theta}-\theta_{0}\right) \sqrt{\sum_{j=1}^{N} W_{j}} \stackrel{\mathrm{a}}{\sim} N(0,1)\]

alpha = 0.005
theta0 = 0 

weights = c(0.5, 0.5, 0.8)
thetas = c(-0.2, 0.5, 0.4)
theta_est = 1/(sum(weights)) * sum(weights * thetas)


t = (theta_est-theta0) * sqrt(sum(weights))
t

# Drei moegliche Hypothesentests
print("less/linksgerichtet:")
paste("Krit. Bereich: ] -INF;", qnorm(alpha),"]", sep="")
p = pnorm(t)
p

if(p <= alpha) print("H1 annehmen") else print("H0 annehmen")

print("greater/rechtsgerichtet:")
paste("Krit. Bereich: [", qnorm(1-alpha),";INF[", sep="")
p = 1-pnorm(t)
p

if(p <= alpha) print("H1 annehmen") else print("H0 annehmen")

print("two.sided/ungerichtet:")
paste("Krit. Bereich: ]-INF;", qnorm(alpha/2),"] [", qnorm(1-(alpha/2)), "; INF[", sep="")
p = if(t <= 0) 2*pnorm(t) else 2*pnorm(-t)
p

if(p <= alpha) print("H1 annehmen") else print("H0 annehmen")

Varianzanalyse (ANalysis Of VAriance)

Einfaktorielles statistisches Modell

Modellgleichung m-fach gestufter Faktor (erste Darstellungsform):

\[\large Y_{i j}=\mu_{j}+\varepsilon_{i j} \quad \text { mit } j=1, \ldots, m \text { und } i=1, \ldots, n_{j}\]

\[\large Y_{i j} \stackrel{\text { ind }}{\sim} N\left(\mu_{j}, \sigma^{2}\right) \text { bzw. } \varepsilon_{i j} \stackrel{\text { iid }}{\sim} N\left(0, \sigma^{2}\right)\]

Modellgleichung m-fach gestufter Faktor (zweite Darstellungsform): \[\large Y_{i j}=\mu+\alpha_{j}+\varepsilon_{i j} \quad \text { wobei } \quad \alpha_{j}=\mu_{j}-\mu \text { mit } j=1, \ldots, m \text { und } \mu=\frac{1}{m} \sum_{j=1}^{m} \mu_{j}\]

\[\large Y_{i j} \stackrel{\text { ind }}{\sim} N\left(\mu+\alpha_{j}, \sigma^{2}\right) \text { bzw. } \varepsilon_{i j} \stackrel{\text { iid }}{\sim} N\left(0, \sigma^{2}\right)\]

Schätzfunktionen:

\(\mu_{j}\) \[\hat{\mu}_{j}=\bar{Y}_{j}=\frac{1}{n_{j}} \sum_{i=1}^{n} Y_{i j}\]

\(\alpha_{j}\) \[\hat{\alpha}_{j}=\bar{Y}_{j}-\bar{Y}\]

\(\sigma^{2}\) (falls \(n_{1}=n_{2}=\cdots=n_{m}=n\))

\[\large \hat{\sigma}^{2}=S_{\text {pool }}^{2}=\frac{1}{m(n-1)}\left(\sum_{j=1}^{m} \sum_{i=1}^{n}\left(Y_{i j}-\bar{Y}_{j}\right)^{2}\right)\]

Omnibustest

Wichtig: nur ein Test, deshalb keine Korrektur des Signifikanznivaus nötig

Erste Darstellungsform:

\[\large \begin{array}{l} H_{0}: \mu_{1}=\mu_{2}=\ldots=\mu_{k} \ldots=\mu_{m}\\ H_{1}: \mu_{j} \neq \mu_{k} \quad \text { für mindestens ein Paar } j, k \text { mit } j \neq k \end{array}\] Zweite Darstellungsform:

\[\large \begin{array}{ll} H_{0}: \alpha_{j}=0 & \text { für alle } j \\ H_{1}: \alpha_{j} \neq 0 & \text { für mindestens ein } j \end{array}\]

Quadratsummen

Quadratsumme innerhalb:

\[\large Q S_{i n n}=\sum_{i=1}^{n} \sum_{j=1}^{m}\left(Y_{i j}-\bar{Y}_{j}\right)^{2}\]

Quadratsumme zwischen:

\[\large Q S_{z w}=\sum_{j=1}^{m} n \cdot\left(\bar{Y}_{j}-\bar{Y}\right)^{2}\] \[\large \bar{Y}=\frac{1}{m} \frac{1}{n} \sum_{j=1}^{m} \sum_{i=1}^{n} Y_{i j}\]

Quadratsumme gesamt:

\[\large Q S_{g e s}=\sum_{j=1}^{m} \sum_{i=1}^{n}\left(Y_{i j}-\bar{Y}\right)^{2}\] \[\large Q S_{g e s}=Q S_{z w}+Q S_{i n n}\]

uv = c("A","A","A","B","B","B","C","C","C") 
av = c(1,2,3,4,5,6,7,8,9)
data = data.frame(uv,av)

qs_inn = sum(
  sapply(unique(uv),
         function(group) sum((data[data$uv==group,]$av - mean(data[data$uv==group,]$av))^2)
  )
) 

qs_zw = sum( 
  sapply(unique(uv),
         function(group) nrow(data[data$uv==group,])*(mean(data[data$uv==group,]$av) - mean(data$av))^2
  )
)

qs_inn + qs_zw

Mittlere Quadratsumme zwischen:

\[\large M Q S_{z w}=\frac{Q S_{z w}}{d f_{z w}}\] \[\large df_{z w}=m-1\] Mittlere Quadratsumme innerhalb:

\[\large M Q S_{i n n}=\frac{Q S_{i n n}}{d f_{i n n}}\] \[\large df_{\text {inn }}=m(n-1)\]

\[\large M Q S_{i n n}=S_{\text {pool }}^{2}\] Weitere Eigenschaften:

\[\large E\left(M Q S_{i n n}\right)=E\left(S_{\text {pool }}^{2}\right)=\sigma^{2}\]

\[\large E\left(M Q S_{z w}\right)=\sigma^{2}+\frac{\sum_{j=1}^{m} n \cdot \alpha_{j}^{2}}{d f_{z w}}=\sigma^{2}+\frac{\sum_{j=1}^{m} n\left(\mu_{j}-\mu\right)^{2}}{m-1}\]

Teststatistik Omnibustest

\[\large T=\frac{Q S_{z w} / d f_{z w}}{Q S_{i n n} / d f_{i n n}}=\frac{M Q S_{z w}}{M Q S_{i n n}} \stackrel{H_{0}}{\sim} F\left(d f_{z w}, d f_{i n n}\right)\]

F-Verteilung

\[\large X \sim F\left(v_{1}, v_{2}\right)\] \[\large E(X)=\frac{v_{2}}{v_{2}-2} \]

df1 = 2
df2 = 10
pf(q=2, df1, df2) # Verteilungsfunktion
qf(p=0.25, df1, df2) # Quantile
Kritischer Bereich Omnibustest

\[\large K_{T}=[k_{rechts}, \infty[\]

R Code
uv = c("A","A","A","B","B","B","C","C","C") 
av = c(1,2,3,4,5,6,7,8,9)
alpha = 0.005

data = data.frame(uv,av)

# Omnibustest (unkorrigiert) von Hand - Wenn nur konkrete Werte vorliegen und keine Datenvektoren, die folgenden Variablen durch eigene Werte ersetzen

m = length(unique(uv))
n = nrow(data[data$uv==uv[[1]],]) # balanciertes design

df_zw = m-1
df_inn = m*(n-1) 

qs_inn = sum(
  sapply(unique(uv),
         function(group) sum((data[data$uv==group,]$av - mean(data[data$uv==group,]$av))^2)
  )
) 

qs_zw = sum( 
  sapply(unique(uv),
         function(group) nrow(data[data$uv==group,])*(mean(data[data$uv==group,]$av) - mean(data$av))^2
  )
)

paste("QSges: ", qs_inn + qs_zw, sep="")

mqs_in = qs_inn / df_inn
mqs_zw = (qs_zw) / df_zw

paste("Krit. Bereich: [", qf(1-alpha, df1=df_zw, df2=df_inn),";INF[", sep="")

t = mqs_zw/mqs_in
t

p = 1-pf(mqs_zw/mqs_in, df1 = df_zw, df2 = df_inn)
p

if(p <= alpha) print("H1 annehmen") else print("H0 annehmen")


# Omnibustest mit R Funktion 1 (unkorrigiert)
fit = aov(av~uv, data=data)
summary(fit)

# Omnibustest mit R Funktion 2 (korrigiert - wenn Varianzgleichheit verletzt)
oneway.test(av~uv, data) 
# Welcher Wert entspricht welchem output von R?

uv = c("A","A","A","B","B","B","C","C","C") 
av = c(1,2,3,4,5,6,7,8,9)
data = data.frame(uv,av)

fit <- aov(av ~ uv, data=data)
#str(summary(fit))

df_zw = summary(fit)[[1]]$'Df'[[1]]
df_inn = summary(fit)[[1]]$'Df'[[2]]

qs_zw = summary(fit)[[1]]$'Sum Sq'[[1]]
qs_inn = summary(fit)[[1]]$'Sum Sq'[[2]]

mqs_zw = summary(fit)[[1]]$'Mean Sq'[[1]]
mqs_inn = summary(fit)[[1]]$'Mean Sq'[[2]]

f = summary(fit)[[1]]$'F value'[[1]]

p = summary(fit)[[1]]$'Pr(>F)'[[1]]

Effektgröße im einfaktoriellen varianzanalytischen Modell

Anteil an der Gesamtvarianz der AV in der Population, der durch die UV (bzw. durch den Faktor) erklärt werden kann.

\[\large \eta^{2}=\frac{\sigma_{z w}^{2}}{\sigma_{g e s}^{2}}\]

\[\large \hat{\sigma}_{z w}^{2}=\frac{1}{m \cdot n} Q S_{z w}\]

\[\large \hat{\sigma}_{ges}^{2}=\frac{1}{m \cdot n} Q S_{ges}\]

Schätzfunktion:

\[\large \hat{\eta}^{2}=\frac{Q S_{z w}}{Q S_{\text {ges }}}\]

uv = c("A","A","A","B","B","B","C","C","C") 
av = c(1,2,3,4,5,6,7,8,9)

data = data.frame(uv,av)

# Berechnung Eta von Hand - Wenn nur konkrete Werte vorliegen und keine Datenvektoren, die folgenden Variablen durch eigene Werte ersetzen

n = length(unique(uv))
m = nrow(data[data$uv==uv[[1]],]) # balanciertes design

df_zw = n-1
df_inn = n*(m-1) 

qs_inn = sum(
  sapply(unique(uv),
         function(group) sum((data[data$uv==group,]$av - mean(data[data$uv==group,]$av))^2)
  )
) 

qs_zw = sum( 
  sapply(unique(uv),
         function(group) nrow(data[data$uv==group,])*(mean(data[data$uv==group,]$av) - mean(data$av))^2
  )
)

qs_zw/(qs_inn + qs_zw)


# Berechnung Eta mit R Funktion
library(DescTools)
fit = aov(av~uv, data=data)
EtaSq(fit)

# Berchnung Konfidenzintevall für Eta
library(MBESS)
ci.pvaf(summary(fit)[[1]][["F value"]][[1]] ,df.1 = df_zw, df.2 = df_inn, N=nrow(data), conf.level = 0.95)

Die statistische Hypothese des Omnibus-Tests könnte alternativ so geschrieben werden:

\[\large \begin{aligned} &H_{0}: \eta^{2}=0 \\ &H_{1}: \eta^{2}>0 \end{aligned}\]

Stichprobenplanung für Omnibustest

R funktion nimmt \(\eta^{2}\) nicht direkt, wir müssen umrechnen: \[\large f=\sqrt{\frac{\eta^{2}}{1-\eta^{2}}}\]

library(pwr)

eta = 0.05
alpha = 0.005
power = 0.8
factors=3

f = sqrt(eta/(1-eta))

pwr.anova.test(k=factors, f=f, power=power, sig.level=alpha)

Weitere statistische Verfahren im einfaktoriellen varianzanalytischen Modell - Kontrastmatrix

Ausgangspunkt:

Formulierung von Parameterbeziehungen mit \[\large \sum_{j=1}^{m} a_{j} \cdot \mu_{j}\]

Diese Parameterbeziehng wird “Kontrast” genannt, falls die Konstanten folgende Eigenschaft haben:

\[\large \sum_{j=1}^{m} a_{j}=0\]

Schätzfunktion für \(\mu_{j}-\mu_{k}\)

\[\large \bar{Y}_{j}-\bar{Y}_{k}\] Ein Konfidenzintervall mit Konfidenzniveau \(1-\alpha\) für \(\mu_{j}-\mu_{k}\)

\[\large \left[\left(\bar{Y}_{j}-\bar{Y}_{k}\right)-t_{1-\frac{\alpha}{2}} \cdot \sqrt{\frac{S_{p o o l}^{2}}{n}+\frac{S_{p o o l}^{2}}{n}},\left(\bar{Y}_{j}-\bar{Y}_{k}\right)+t_{1-\frac{\alpha}{2}} \cdot \sqrt{\frac{S_{p o o l}^{2}}{n}+\frac{S_{\text {pool }}^{2}}{n}}\right]\] \[\large t{\sim} t(m(n-1))\] \[\large S_{\text {pool }}^{2}=M Q S_{\text {inn }}\]

Teststatistik für den Hypothesentest bezüglich \(\mu_{j}-\mu_{k}\)

\[\large T=\frac{\left(\bar{Y}_{j}-\bar{Y}_{k}\right)-\mu_{0}}{\sqrt{\frac{S_{\text {pool }}^{2}}{n}+\frac{S_{\text {pool }}^{2}}{n}}} \stackrel{H_{0}}{\sim} t(m(n-1))\]

R Code Konfidenzintervall, ungerichteter Hypothesentest
library(multcomp)
uv = c("A","A","A","B","B","B","C","C","C") 
av = c(1,2,3,4,5,6,7,8,9)

data = data.frame(uv,av, stringsAsFactors = TRUE)

fit_aov <- aov(av ~ uv, data = data)

# "Nullhypothesen"
hyps = c(
  "A - B == 0",
  "A - C == 0"
)


# Kontrast Matrix
contrasts <- mcp(uv = hyps)
fit <- glht(fit_aov, linfct = contrasts)

confint(fit, level = 0.95, calpha = univariate_calpha())
# "single-step": Tukey Methode, univariate(): Keine Korrektur, "bonferroni": Bonferroni
summary(fit, test = adjusted(type = "single-step")) 
R Code gerichteter Hypothesentest
library(multcomp)
uv = c("A","A","A","B","B","B","C","C","C") 
av = c(1,2,3,4,5,6,7,8,9)

data = data.frame(uv,av, stringsAsFactors = TRUE)

fit_aov <- aov(av ~ uv, data = data)

# Nullhypothesen
hyps = c(
  "A - B <= 0",
  "A - C <= 0"
)


# Kontrast Matrix
contrasts <- mcp(uv = hyps)
fit <- glht(fit_aov, linfct = contrasts)

# "single-step": Tukey Methode, univariate(): Keine Korrektur, "bonferroni": Bonferroni
summary(fit, test = adjusted(type = "single-step")) 

Zweifaktorielles statistisches Modell

Modellgleichung m-fach gestufter Faktor (erste Darstellungsform):

\[\large Y_{i j k}=\mu_{j k}+\varepsilon_{i j k} \text { mit } i=1, \ldots, n_{j k} ; j=1, \ldots, r \text { und } k=1, \ldots, c\] \[\large Y_{i j k} \stackrel{\mathrm{ind}}{\sim} N\left(\mu_{j k}, \sigma^{2}\right) \mathrm{bzw} . \varepsilon_{i j k} \stackrel{\mathrm{iid}}{\sim} N\left(0, \sigma^{2}\right)\] Mittlere AV über bestimmte Populationen:

\[\large \begin{array}{c} \mu=\frac{1}{r \cdot c} \sum_{j=1}^{r} \sum_{k=1}^{c} \mu_{j k} \\ \mu_{j} .=\frac{1}{c} \sum_{k=1}^{c} \mu_{j k} \\ \mu_{\cdot k}=\frac{1}{r} \sum_{j=1}^{r} \mu_{j k} \end{array}\] Modellgleichung m-fach gestufter Faktor (zweite Darstellungsform):

\[\large Y_{i j k}=\mu+\alpha_{j}+\beta_{k}+\gamma_{j k}+\varepsilon_{i j k} \quad \text { mit } i=1, \ldots, n_{j k} ; j=1, \ldots, r \text { und } k=1, \ldots, c\] \[\large Y_{i j k} \stackrel{\text { ind }}{\sim} N\left(\mu+\alpha_{j}+\beta_{k}+\gamma_{j k}, \sigma^{2}\right) \text { bzw. } \varepsilon_{i j k} \stackrel{\text { iid }}{\sim} N\left(0, \sigma^{2}\right)\]

  • \(\alpha_{j}=\mu_{j .}-\mu\) Effekt der Kategorie j des Faktors A auf die AV
  • \(\beta_{k}=\mu_{. k}-\mu\) Effekt der Kategorie k des Faktors B auf die AV
  • \(\gamma_{j k}=\mu_{j k}-\mu-\alpha_{j}-\beta_{k}\) Interaktionseffekt bezogen auf die Population jk
Schätzfunktionen für Parameter

Für \(\mu_{j k}\): \[\large \hat{\mu}_{j k}=\bar{Y}_{j k}=\frac{1}{n} \sum_{i=1}^{n} Y_{i j k}\]

Für \(\sigma^{2}\): \[\large \hat{\sigma}^{2}=S_{\text {pool }}^{2}=\frac{1}{r \cdot c(n-1)}\left(\sum_{j=1}^{r} \sum_{k=1}^{c} \sum_{i=1}^{n}\left(Y_{i j k}-\bar{Y}_{j k}\right)^{2}\right)\]

Omnibustest

Omnibustest für die Interaktion:

  • \(H_{0}: \gamma_{j k}=0\) für alle Kombinationen \(j k\)

  • \(H_{1}: \gamma_{j k} \neq 0\) für mindestens eine Kombination \(j k\)

Omnibustest für den Faktor A (UV 1):

  • \(H_{0}: \alpha_{j}=0\) für alle \(j\)
  • \(H_{1}: \alpha_{j} \neq 0\) für mindestens ein \(j\)

Omnibustest für den Faktor B (UV 2):

  • \(H_{0}: \beta_{k}=0\) für alle \(k\)
  • \(H_{1}: \beta_{k} \neq 0\) für mindestens ein \(k\)

Wichtig:

  • Die \(H_{0}\) bedeutet nicht unbedingt, das der Faktor A/B keinen Einfluss auf die AV hat.
  • Die \(H_{1}\) bedeutet nicht unbedingt, dass der Faktor A/B auf allen Faktorstufen des Faktors B/A einen Einfluss auf die AV hat.

Quadratsummen: \[\large Q S_{g e s}=Q S_{A}+Q S_{B}+Q S_{A x B}+Q S_{i n n}\]

Teststatistiken für Faktoren:

  • \(T_{A}=\frac{M Q S_{A}}{M Q S_{i n n}}\) folgt einer \(F\) -Verteilung mit \(v_{1}=d f_{A}\) und \(v_{2}=d f_{\text {inn }} .\)
  • \(T_{B}=\frac{M Q S_{B}}{M Q S_{i n n}}\) folgt einer \(F\) -Verteilung mit \(v_{1}=d f_{B}\) und \(v_{2}=d f_{\text {inn }}\).
  • \(T_{A x B}=\frac{M Q S_{A x B}}{M Q S_{i n n}}\) folgt einer \(F\) -Verteilung mit \(v_{1}=d f_{A x B}\) und \(v_{2}=d f_{\text {inn }} .\)
uv1 = c("A","A","A","B","B","B","C","C","C") 
uv2 = c("X","X","Y","Y","Y","X","X","Y","Y")
av = c(1,2,3,4,5,6,7,8,9)

data = data.frame(uv1, uv2, av, stringsAsFactors = TRUE)


# Omnibustest mit R Funktion 1 (unkorrigiert)
fit <- aov(av ~ uv1 * uv2, data)
summary(fit)

# Omnibustest mit R Funktion 2 (korrigiert - wenn Varianzgleichheit verletzt), nur mit vielen Beobachtungen
#oneway.test(av~uv1*uv2, data) 
Effektgröße

Gesamtvarianz in zweifaktoriellen Modell:

\[\large \sigma_{\text {ges }}^{2}=\sigma_{A}^{2}+\sigma_{B}^{2}+\sigma_{A x B}^{2}+\sigma^{2}\] Effektgrößen:

  • Anteil der Gesamtvarianz der AV, der durch den Haupteffekt von Faktor A erklärt werden kann: \[\large \eta_{A}^{2}=\frac{\sigma_{A}^{2}}{\sigma_{g e s}^{2}}\]
  • Anteil der Gesamtvarianz der AV, der durch den Haupteffekt von Faktor B erklärt werden kann : \[\large \eta_{B}^{2}=\frac{\sigma_{B}^{2}}{\sigma_{g e s}^{2}}\]
  • Anteil der Gesamtvarianz der AV, der durch die Interaktion der beiden Faktoren erklärt werden kann: \[\large \eta_{A x B}^{2}=\frac{\sigma_{A x B}^{2}}{\sigma_{g e s}^{2}}\]
  • Partielles Eta-Quadrat: Anteil an der auf Faktor A und den Fehler zurückgehenden Varianz der AV, der durch den Haupteffekt von Faktor A erklärt werden kann: \[\large \eta_{\text {par }, A}^{2}=\frac{\sigma_{A}^{2}}{\sigma_{A}^{2}+\sigma^{2}}\]
uv1 = c("A","A","A","B","B","B","C","C","C") 
uv2 = c("X","X","Y","Y","Y","X","X","Y","Y")
av = c(1,2,3,4,5,6,7,8,9)

data = data.frame(uv1, uv2, av, stringsAsFactors = TRUE)
fit = aov(av ~ uv1 * uv2, data)

#Effekt
library(DescTools)
EtaSq(fit)

library(MBESS)
conf.level = 0.95

# Effekt uv1 Konfidenzintervall
ci.pvaf(summary(fit)[[1]][["F value"]][[1]] ,df.1 = summary(fit)[[1]][["Df"]][[1]], df.2 = summary(fit)[[1]][["Df"]][[4]], N=nrow(data), conf.level = conf.level)

# Effekt uv2 Konfidenzintervall
ci.pvaf(summary(fit)[[1]][["F value"]][[2]] ,df.1 = summary(fit)[[1]][["Df"]][[2]], df.2 = summary(fit)[[1]][["Df"]][[4]], N=nrow(data), conf.level = conf.level)

# Effekt uv1:uv2 Konfidenzintervall
ci.pvaf(summary(fit)[[1]][["F value"]][[3]] ,df.1 = summary(fit)[[1]][["Df"]][[3]], df.2 = summary(fit)[[1]][["Df"]][[4]], N=nrow(data), conf.level = conf.level)
Varianzanalyse - Kontrastmatrix

Konfidenzintervall, Hypothesentest:

library(multcomp)
library(forcats)


uv1 = c("A","A","A","B","B","B","C","C","C") 
uv2 = c("X","X","Y","Y","Y","X","X","Y","Y")
av = c(1,2,3,4,5,6,7,8,9)

data = data.frame(uv1, uv2, av, stringsAsFactors = TRUE)

data$uv1_uv2 = fct_cross(data$uv1, data$uv2, sep = '_')

fit_aov = aov(av ~ uv1_uv2, data)

# H0
hyps = mcp(uv1_uv2 = c(
  "A_X - B_X == 0",
  "B_Y - A_Y == 0")
)

fit = glht(fit_aov, hyps)
confint(fit, level = 0.95, calpha = univariate_calpha())

# "single-step": Tukey Methode, univariate(): Keine Korrektur, "bonferroni": Bonferroni
summary(fit, test=univariate())
Interaktionsplots
uv1 = c("A","A","A","B","B","B","C","C","C") 
uv2 = c("X","X","Y","Y","Y","X","X","Y","Y")
av = c(1,2,3,4,5,6,7,8,9)
    
data = data.frame(uv1, uv2, av, stringsAsFactors = TRUE)   

interaction.plot(data$uv1, data$uv2, data$av)
interaction.plot(data$uv2, data$uv1, data$av)

Regressionsanalyse

Einfache Lineare Regression

Parameterschätzung

\[\large Y_{i}=\alpha+\beta \cdot X_{i}+\varepsilon_{i} \quad \text { wobei } \varepsilon_{i} \stackrel{\text { iid }}{\sim} N\left(0, \sigma^{2}\right) \] \[\large E\left(Y_{i} \mid X_{i}=x_{i}\right)=\mu_{i}=\alpha+\beta \cdot x_{i} \]

\[\large \varepsilon_{i}=Y_{i}-E\left(Y_{i} \mid X_{i}=x_{i}\right) \]

Parameter:

  • \(\alpha\) Intercept, Achsenabschnitt
  • \(\beta\) Slope, Steigungsparameter
  • \(\large \sigma^{2}\) Fehlervarianz (Realisation s von \(sqrt(\sigma^{2})\) iste der “Standardschätzfehler”)

Schätzfunktionen:

\[\large \hat{\beta}=B=\frac{\operatorname{cov}(X, Y)}{S_{x}^{2}} \]

\[\large \hat{\alpha}=A=\bar{Y}-B \cdot \bar{X} \]

\[\large \hat{\sigma}^{2}=S^{2}=\frac{1}{n-2} \sum_{i=1}^{n}\left(Y_{i}-\left(A+B \cdot X_{i}\right)\right)^{2} = \frac{1}{n-2} \sum_{i=1}^{n} E_{i}^{2} \]

Gleichung der Geschätzten Regressionsgeraden:

\[\large \widehat{E}\left(Y_{i} \mid x_{i}\right)=a+b \cdot x_{i}\]

data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(0,23,80,90,140,182,220,300))

fit <- lm(AV ~ UV, data = data)
#summary(fit)

# a
fit$coefficients[["(Intercept)"]]

# b
fit$coefficients[["UV"]]

# Konfidenzointervall für Parameter
confint(fit, level=0.95)

# standard error
summary(fit)$sigma

Zentrierung einer ZV: \[\large X_{c, i}=X_{i}-\bar{X}\]

data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(0,23,80,90,140,182,220,300))

data$UV <- data$UV - mean(data$UV)
# oder
data$UV <- scale(data$UV, center = TRUE, scale = FALSE)

data

# Vorhersage für durchschnittlichen UV Wert
lm(AV ~ UV, data = data)$coefficients[["(Intercept)"]]

Vorhersagewert Subjekt i: Schätzwert für \(\mu_i\): \(\hat{Y}_{i}=\hat{\mu}_{i}=A+B \cdot X_{i}\)

data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV, data = data)

new_uv_value = 50
data_pred <- data.frame(UV=new_uv_value)

# Alternative Berechnung des Vorhersagewerts "von Hand"
#fit$coefficients[["(Intercept)"]]+fit$coefficients[["UV"]]*new_uv_value

# Berechnung des Vorhersagewerts mit Konfidenzintervall
predict(fit, data_pred, interval="prediction", level=0.95)

Residuum Differenz zwischen Beobachtung und Realisation: \(E_{i}=Y_{i}-\widehat{Y}_{i}\)

Hypothesentests

Hypothesentest für \(\beta\): Hypothesen: \[ \large \begin{aligned} &H_{0}: \beta=\beta_{0}=0 \\ &H_{1}: \beta \neq \beta_{0} = 0 \end{aligned} \]

Teststatistik:

\[\large T=\frac{B-\beta_{0}}{\sqrt{\hat{V} a r(B)}} \sim t(n-2)\]

\[\large \operatorname{Var}(B)=\frac{\sigma^{2}}{\sum_{i=1}^{n}\left(x_{i}-\bar{x}\right)^{2}}\]

\[\large \hat{V} \operatorname{ar}(B)=\frac{S^{2}}{\sum_{i=1}^{n}\left(x_{i}-\bar{x}\right)^{2}}=\frac{\frac{1}{n-2} \sum_{i=1}^{n} E_{i}^{2}}{\sum_{i=1}^{n}\left(x_{i}-\bar{x}\right)^{2}}\]

data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV, data = data)
#summary(fit)

# p Wert für b
summary(fit)$coefficients[,4][["UV"]]

Multiple Regression

Parameterschätzung

\[\large Y_{i}=\alpha+\beta_{1} \cdot X_{i 1}+\beta_{2} \cdot X_{i 2}+\varepsilon_{i} \quad \text { wobei } \varepsilon_{i} \stackrel{i i d}{\sim} N\left(0, \sigma^{2}\right)\]

\[\large E\left(Y_{i} \mid X_{i 1}=x_{i 1}, X_{i 2}=x_{i 2}\right)=\mu_{i}=\alpha+\beta_{1} \cdot x_{i 1}+\beta_{2} \cdot x_{i 2}\]

wobei \(r_{x 1 x 2}^{2}\) die quadrierte Korrelation zwischen den beiden Prädiktoren ist.

Konfidenzintervall für beta1 beta2

\[\large \left[B_{j} \pm t_{1-\frac{\alpha}{2}} \cdot \widehat{S E}\left(B_{j}\right)\right]\]

mit t-Verteilung mit v = n - 3.

\[\large S^{2}=\hat{\sigma}^{2}=\frac{1}{n-3} \sum_{i=1}^{n}\left(Y_{i}-\left(A+B_{1} \cdot X_{i 1}+B_{2} \cdot X_{i 2}\right)\right)^{2}=\frac{1}{n-3} \sum_{i=1}^{n} E_{i}^{2}\]

data <- data.frame(UV1 = c(1,2,6,7,13,15,20,30), UV2 = c(1,2,3,4,5,6,7,8), AV = c(0,23,80,90,140,182,220,300))

fit <- lm(AV ~ UV1 + UV2, data = data)
#summary(fit)

# a
fit$coefficients[["(Intercept)"]]

# b1
fit$coefficients[["UV1"]]

# b2
fit$coefficients[["UV2"]]

# Konfidenzointervall für Parameter
confint(fit, level=0.95)

# standard error
summary(fit)$sigma

\[ \large \begin{aligned} &S E\left(B_{1}\right)=\sqrt{\operatorname{Var}\left(B_{1}\right)}=\sqrt{\frac{1}{1-r_{x 1 x 2}^{2}} \cdot \frac{\sigma^{2}}{\sum_{i=1}^{n}\left(x_{i 1}-\bar{x}_{1}\right)^{2}}} \end{aligned} \]

Vorhersage

\[\large \hat{y}_{i}=a+b_{1} \cdot x_{i 1}+b_{2} \cdot x_{i 2}\]

Hypothesentests

Einzelne Prädiktoren
  • Bei einer MLR mit zwei Prädiktoren können folgenden zwei Hypothesen überprüft werden:

\[ \large \begin{aligned} &H_{0}: \beta_{1}=0 \\ &H_{1}: \beta_{1} \neq 0 \\\\ &H_{0}: \beta_{2}=0 \\ &H_{1}: \beta_{2} \neq 0 \end{aligned} \]

Teststatistik: \[ \large T_{1}=\frac{B_{1}}{\sqrt{\hat{V} a r\left(B_{1}\right)}} \sim t(n-3)\]

data <- data.frame(UV1 = c(1,2,6,7,13,15,20,30), UV2 = c(1,2,3,4,5,6,7,8), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV1 + UV2, data = data)
summary(fit)
Omnibustest

Hypothese:

\[\large \begin{aligned} &H_{0}: \beta_{1}=\beta_{2}=0\\ &H_{1}: \beta_{j} \neq 0 &\text { für mindestens ein } j \text { mit } j=1,2 \end{aligned} \]

Teststatistik:

\[\large F=\frac{\frac{1}{2} \sum_{i=1}^{n}\left(\hat{Y}_{i}-\bar{Y}\right)^{2}}{S^{2}} \]

Kollinearität

  • Man spricht von Kollinearität, wenn einer oder mehrere der Prädiktoren stark mit den jeweils anderen Prädiktoren zusammenhängen

  • Entstehende Probleme:

    • Größere Konfidenzintervalle
    • Geringere Power der Hypothesentests
  • Nicht beeinflusst:

    • Konfidenzintervalle für \(\rho^{2}\)
    • Der Omnibustest im Rahmen der MLR

\[\large SE\left(B_{j}\right)=\sqrt{\operatorname{Var}\left(B_{j}\right)}=\sqrt{\frac{1}{1-r_{j}^{2}} \cdot \frac{\sigma^{2}}{\sum_{i=1}^{n}\left(x_{i j}-\bar{x}_{j}\right)^{2}}}\]

Hierbei ist \(r^{2}_{j}\) der Determinationskoeffizient eines Regressionsmodells, in das der Prädiktor 𝑗 als Kriterium und alle anderen Prädiktoren als Prädiktoren aufgenommen werden.

Varianzinflationsfaktor
  • Kennwert für Kollinearität

  • Zeigt: Negative Auswirkungen der Kollinearität können mit großen Stichproben aufgehoben werden

\[\large VIF_{j}=\frac{1}{1-r_{j}^{2}}\]

data <- data.frame(UV1 = c(1,2,6,7,13,15,20,30), UV2 = c(1,2,3,4,5,6,7,8), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV1 + UV2, data = data)

# Beachte: Bei 2 Variablen sind beide VIFs identisch

# Berechnung von Punkt und KI mit R
library(car)
vif(fit)

library(MBESS)
ci.R2(R2 = summary(fit)$r.squared, p=ncol(data)-1, conf.level = 0.95, N=nrow(data))


# Berechnung von Punktschätzer "per Hand"
fit_uv1 <- lm(UV1 ~ UV2, data = data)
1/(1-summary(fit_uv1)$r.squared)

Effektgrößen

Effektgröße \(\rho^{2}\)
  • Stärke des Zusammenhangs, Einheitsunabhängig

Schätzfunktion:

\[\large \hat{\rho}^{2}=R^{2}=\frac{\hat{\sigma}_{\mu_{i}}^{2}}{\hat{\sigma}_{g e s}^{2}}=\frac{\frac{1}{n} \sum_{i=1}^{n}\left(\hat{Y}_{i}-\bar{Y}\right)^{2}}{\frac{1}{n} \sum_{i=1}^{n}\left(Y_{i}-\bar{Y}\right)^{2}}=\frac{\sum_{i=1}^{n}\left(\hat{Y}_{i}-\bar{Y}\right)^{2}}{\sum_{i=1}^{n}\left(Y_{i}-\bar{Y}\right)^{2}}\]

ERL (eine UV)

  • Anteil der Gesamtvarianz der AV, der durch die UV erklärt werden kann
data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV, data = data)

# Punktschätzung rho2
rho2 <- summary(fit)$r.squared
rho2

# Konfidenzintervall rho2
library(MBESS)
ci.R2(rho2, p = 1, N = nrow(data), conf.level=0.95)

MLR (mehrere UVs)

  • Gesamte Effektstärke aller Prädiktoren im MLR Modell
  • Anteil der Gesamtvarianz der AV, die durch alle UVs gemeinsam erklärt werden kann
data <- data.frame(UV1 = c(1,2,6,7,13,15,20,30), UV2 = c(1,2,3,4,5,6,7,8), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV1 + UV2, data = data)

# Punktschätzung rho2
rho2 <- summary(fit)$r.squared
rho2

# Konfidenzintervall rho2
library(MBESS)
ci.R2(rho2, p = 2, N = nrow(data), conf.level=0.95)
Effektgröße \(\rho^{2}_{j}\) für MLR
  • Effektstärke eines einzelnen Prädiktors im MLR Modell

  • Anteil der Gesamtvarianz der AV, der über die anderen Prädiktoren hinaus nur durch UV j erklärt werden kann

\[\large \rho_{j}^{2}=\rho^{2}-\rho_{-j}^{2}\]

wobei \(\rho_{-j}^{2}\) demjenigen \(\rho^{2}\) entspricht, das man erhält, wenn man den Prädiktor \(j\) aus dem MLR-Modell entfernt.

data <- data.frame(UV1 = c(1,2,6,7,13,15,20,30), UV2 = c(1,2,3,4,5,6,7,8), AV = c(0,23,80,90,140,182,220,300))

# Punktschätzung rho2
fit <- lm(AV ~ UV1 + UV2, data = data)
rho2 <- summary(fit)$r.squared

# Punktschätzung rho2_1
fit2 <- lm(AV ~ UV2, data = data)
summary(fit)$r.squared - summary(fit2)$r.squared

# Punktschätzung rho2_2
fit1 <- lm(AV ~ UV1, data = data)
summary(fit)$r.squared - summary(fit1)$r.squared
Effektgröße \(\beta_{z}\) für ELR
  • Stärke des Zusammenhangs, Richtung des Zusammenhangs, Einheitsunabhängig
  • im Rahmen der ELR identisch mit der Pearson-Korrelation (zwischen AV und UV) in der Stichprobe
  • “normales” \(\beta\) falls AV und UV z-standardisiert werden

\[\large \rho^{2}=\beta_{z}^{2} \]

data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(scale(AV) ~ scale(UV), data = data)

# Punktschätzung beta_z
fit$coefficients[["scale(UV)"]]

# Konfidenzintervall beta_z
confint(fit, level=0.95)

Effektgröße \(\beta_{z_{j}}\) für MLR

  • Effektstärke eines einzelnen Prädiktors im MLR Modell
  • Stärke des Zusammenhangs, Richtung des Zusammenhangs, Einheitsunabhängig
  • Gibt an, wie stark die jeweilige UV bei Konstanthaltung aller anderen UVs mit der AV zusammenhängt.
  • Nicht (!) identisch mit Pearson Korrelation
data <- data.frame(UV1 = c(1,2,6,7,13,15,20,30), UV2 = c(1,2,3,4,5,6,7,8), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV1 + UV2, data = data.frame(scale(data)))

# Punktschätzung beta_z_1
fit$coefficients[["UV1"]]

# Punktschätzung beta_z_2
fit$coefficients[["UV2"]]

# Konfidenzintervall beta_z
confint(fit, level=0.95)

Stichprobenplanung

  • \(n = v + k + 1\) wobei k die Anzahl der Prädiktoren ist
ELR - Eine UV

Hypothese:

\[\large \begin{aligned} &H_{0}: \beta=0 \\ &H_{1}: \beta \neq 0 \end{aligned}\]

Benötigt alternative Effektgröße:

\[\large f^{2}=\frac{\beta_{z}^{2}}{1-\beta_{z}^{2}}=\frac{\rho^{2}}{1-\rho^{2}}\]

rho2 <- 0.1
f2 <- rho2/(1-rho2)

library(pwr)
pwr_analysis <- pwr.f2.test(u=1, f2 = f2, sig.level = 0.005, power = 0.8)
pwr_analysis

# Anzahl benötigte Versuchspersonen
ceiling(pwr_analysis$v + 2)
MLR - mehrere UVs

Einzelne Parameter

\[\large \begin{aligned} &H_{0}: \beta_{j}=0 \\ &H_{1}: \beta_{j} \neq 0 \end{aligned}\]

Benötigt alternative Effektgröße:

\[\large f_{j}^{2}=\frac{\rho_{j}^{2}}{1-\rho^{2}}\]

rho2_1 <- 0.05
rho2 <- 0.1
num_of_predictors = 2

f2_1 <- rho2_1/(1-rho2)

library(pwr)
pwr_analyses <- pwr.f2.test(u=1, f2 = f2_1, sig.level = 0.005, power = 0.8)
pwr_analyses

ceiling(pwr_analyses$v + num_of_predictors + 1)

Omnibustest

\[\large \begin{gathered} H_{0}: \beta_{j}=0 \text { für alle } j \\ H_{1}: \beta_{j} \neq 0 \text { für mindestens ein } j \end{gathered}\]

\[\large f^{2}=\frac{\rho^{2}}{1-\rho^{2}}\]

rho2 <- 0.1
num_of_predictors = 2

f2 <- rho2/(1-rho2)

library(pwr)
pwr_analyses <- pwr.f2.test(u=2, f2 = f2, sig.level = 0.005, power = 0.8)
pwr_analyses

ceiling(pwr_analyses$v + num_of_predictors + 1)

Regressionsdiagnostik

Überprüfung der Modellannahmen + Außreißeranalyse

Modellannahmen:

  1. Die UV und AV hängen linear zusammen

  2. Alle Fehler \(\large \epsilon_{i}\) sind unabhängig voneinander und folgen einer Normalverteilung mit Erwartugnswert 0 und konstanter Varianz \(\large \sigma^{2}\)

(Achtung: Residuen müssen standardisiert werden)

Linearität

Eine stetige UV

data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV, data = data)

plot(AV~UV, data=data)
abline(fit)

Zwei stetige UVs

data <- data.frame(UV1 = c(1,2,6,7,13,15,20,30), UV2 = c(1,2,3,4,5,6,7,8), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV1 + UV2, data = data)

# Component + Residual Plots
library(car)
crPlots(fit)

Normalverteilung

data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV, data = data)

hist(rstandard(fit))

Homoskedastizität

Varianz in Y Richtung soll für gesamten Wertebereich der UV ähnlich sein

data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV, data = data)

plot(fit$fitted.values, rstandard(fit))

Ausreißer

  • Hebelwert (Leverage): Ungewöhnlich große Abweichung des UV-Werts vom Durchschnitt

  • Diskrepanzwert (Discrepancy): Ungewöhnlich große Abweichung des AV-Werts vom Durchschnitt

  • Einflusswert (Influence): Kombination aus Hebel- und Diskrepanzwert ! Vor allem problematisch !

Cook’s Distaz: Wie stark würden sich alle Vorhersagewerte ändern, wenn diese Beobachtung noicht mit ins Modell einfließt (Empfehlung: Werte mit distance > \(\frac{4}{n}\) ausschließen)

data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UV, data = data)

cutoff <- 4/nrow(data)
plot(cooks.distance(fit))
abline(h=cutoff)

which(cooks.distance(fit) > cutoff)

Diskrete Prädiktoren

Dummy-Kodierung

\[\large D_{i}=\left\{\begin{array}{l} 1, \text { falls Person i nicht zur Referenzkategorie gehört } \\ 0, \text { falls Person i zur Referenzkategorie gehört } \end{array}\right.\]

Modellgleichung:

\[\large Y_{i}=\alpha+\beta \cdot D_{i}+\varepsilon_{i} \quad \text { mit } \varepsilon_{i} \stackrel{i i d}{\sim} N\left(0, \sigma^{2}\right)\]

  • Referenzkategorie:

\[\large E\left(Y_{i}\right)=E\left(\alpha+\varepsilon_{i}\right)=\alpha+0=\alpha\]

  • andere Kategorie

\[\large E\left(Y_{i}\right)=E\left(\alpha+\beta+\varepsilon_{i}\right)=\alpha+\beta+0=\alpha+\beta\]

Mehrere Stufen

\[\large D_{j i}=\left\{\begin{array}{l} 1, \text { falls Person i zur Kategorie j gehört } \\ 0, \text { falls Person i nicht zur Kategorie j gehört } \end{array}\right.\]

  • Referenzkategorie: \(D_{ij} = 0\) für alle \(j\)
  • Diskreter Prädiktor mit k Ausprägungen benötigt k - 1 Dummy Variablen

\[\large Y_{i}=\alpha+\beta_{1} \cdot D_{1 i}+\cdots+\beta_{(k-1)} \cdot D_{(k-1) i}+\varepsilon_{i} \quad \text { mit } \varepsilon_{i} \stackrel{i i d}{\sim} N\left(0, \sigma^{2}\right)\]

  • Damit ergibt sich:
    • \(\alpha\) ist der Erwartungswert der \(\mathrm{AV}\) in der Referenzkategorie.
    • \(\alpha+\beta_{j}\) ist der Erwartungswert der \(\mathrm{AV}\) in Kategorie j.
    • \(\beta_{j}\) ist die Erwartungswertdifferenz der \(A V\) zwischen der Kategorie \(j\) und der Referenzkategorie.

Kombination von diskret und stetig

\[\large Y_{i}=\alpha+\beta_{1} \cdot X_{i}+\beta_{2} \cdot D_{i}+\beta_{3}\left(X_{i} \cdot D_{i}\right)+\varepsilon_{i} \quad \text { mit } \varepsilon_{i} \stackrel{i i d}{\sim} N\left(0, \sigma^{2}\right)\]

  • Modell für Referenzkategorie

\[ \large Y_{i} =\alpha+\beta_{1} \cdot X_{i}+\varepsilon_{i}\]

  • Modell für andere Kategorie

\[\large Y_{i} =\left(\alpha+\beta_{2}\right)+\left(\beta_{1}+\beta_{3}\right) \cdot X_{i}+\varepsilon_{i}\]

  • Damit ergibt sich die folgende Interpretation der Parameter:
    • \(\alpha\) ist der Intercept in der Referenzkategorie.
    • \(\beta_{1}\) ist der Steigungsparameter in der Referenzkategorie.
    • \(\alpha+\beta_{2}\) ist der Intercept in der anderen Kategorie.
    • \(\beta_{1}+\beta_{3}\) ist der Steigungsparameter in der anderen Kategorie.
    • \(\beta_{2}\) ist die Differenz der Intercepts der anderen Kategorie und der Referenzkategorie.
    • \(\beta_{3}\) ist die Differenz der Steigungsparameter der anderen Kategorie und der Referenzkategorie.
data <- data.frame(UVS = c(1,2,6,7,13,15,20,30), UVD = c(1,0,1,0,0,0,1,0), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UVS * UVD, data = data)

#summary(fit)

# a
fit$coefficients[["(Intercept)"]]

# b1
fit$coefficients[["UVS"]]

# b2
fit$coefficients[["UVD"]]

# b3
fit$coefficients[["UVS:UVD"]]

# Konfidenzointervall für Parameter
confint(fit, level=0.95)

# standard error
summary(fit)$sigma
Hypothesentests

Beispiele:

Gibt es einen Zusammenhang zwischen UV und AV in der Referenzkategorie?

\[\large H_{0}: \beta_{1}=0 \\ H_{1}: \beta_{1} \neq 0\]

Ist der Zusammenhang zwischen UV und AV unterschiedlich groß in den Kategorien?

\[\large H_{0}: \beta_{3}=0 \\ H_{1}: \beta_{3} \neq 0\]

data <- data.frame(UVS = c(1,2,6,7,13,15,20,30), UVD = c(1,0,1,0,0,0,1,0), AV = c(0,23,80,90,140,182,220,300))
fit <- lm(AV ~ UVS * UVD, data = data)
summary(fit)
# Komlexere Fragestellungen
# Bsp: Gibt es für mindestens eine Kategorie der UVD einen positiven Zusammenhang zwischen UVS und AV?
library(multcomp)
data <- data.frame(UVS = c(1,2,6,7,13,15,20,30), UVD = c(1,0,1,0,0,0,1,0), AV = c(0,23,80,90,140,182,220,300))
fit_lm <- lm(AV ~ UVS * UVD, data = data)

hyps <- c('UVS <= 0',
          'UVS + UVS:UVD <= 0')
fit <- glht(fit_lm, hyps)

## unkorrigierte p-Werte
summary(fit, test = univariate())
## Tukey-korrigierte p-Werte
summary(fit, test = adjusted('single-step'))

Interaktion zwischen stetigen Prädiktoren

\[\large Y_{i}=\alpha+\beta_{1} \cdot X_{i 1}+\beta_{2} \cdot X_{i 2}+\beta_{3}\left(X_{i 1} \cdot X_{i 2}\right)+\varepsilon_{i} \text { mit } \varepsilon_{i} \stackrel{i i d}{\sim} N\left(0, \sigma^{2}\right)\]

  • Moderator \(X_{i 2}\)

\[\large Y_{i}=\alpha+\beta_{2} \cdot X_{i 2}+\left(\beta_{1}+\beta_{3} \cdot X_{i 2}\right) \cdot X_{i 1}+\varepsilon_{i}\]

  • Moderator \(X_{i 1}\)

\[\large Y_{i}=\alpha+\beta_{1} \cdot X_{i 1}+\left(\beta_{2}+\beta_{3} \cdot X_{i 1}\right) \cdot X_{i 2}+\varepsilon_{i}\]

Logistische Regression

\[\large P\left(Y_{i}=1 \mid x_{i}\right)=s\left(\alpha+\beta x_{i}\right)=\frac{e^{\alpha+\beta x_{i}}}{1+e^{\alpha+\beta x_{i}}}\]

Odds:

  • “Wie viel mal wahrscheinlicher ist 1 als 0”

\[\large \frac{P\left(Y_{i}=1 \mid x_{i}\right)}{P\left(Y_{i}=0 \mid x_{i}\right)}=e^{\alpha+\beta x_{i}}=e^{\alpha} \cdot e^{\beta x_{i}}\]

\[\large \frac{P\left(Y_{i}=1 \mid x_{i}+1\right)}{P\left(Y_{i}=0 \mid x_{i}+1\right)}=e^{\alpha} \cdot e^{\beta\left(x_{i}+1\right)}=e^{\alpha} \cdot e^{\beta x_{i}} \cdot e^{\beta}=\frac{P\left(Y_{i}=1 \mid x_{i}\right)}{P\left(Y_{i}=0 \mid x_{i}\right)} \cdot e^{\beta}\]

\[\large \frac{P\left(Y_{i}=1 \mid x_{i}=0\right)}{P\left(Y_{i}=0 \mid x_{i}=0\right)}=e^{\alpha} \cdot e^{\beta \cdot 0}=e^{\alpha}\]

Log-Odds:

\[\large \ln \left(\frac{P\left(Y_{i}=1 \mid x_{i}\right)}{P\left(Y_{i}=0 \mid x_{i}\right)}\right)=\ln \left(e^{\alpha+\beta x_{i}}\right)=\alpha+\beta x_{i}\]

Die Log-Odds sind genau dann gleich 0, wenn \(P\left(Y_{i}=1 \mid x_{i}\right)=0.5\) ist. Sie sind negativ, wenn \(P\left(Y_{i}=1 \mid x_{i}\right)<P\left(Y_{i}=0 \mid x_{i}\right)\) ist, und positiv, wenn \(P\left(Y_{i}=1 \mid x_{i}\right)>P\left(Y_{i}=0 \mid x_{i}\right)\) ist.

# probability(Y=1) -> odds, log odds

p = 0.7

odds <- p/(1-p)
odds

log_odds <- log(odds)
log_odds
# odds -> log odds, probability(Y=1)

odds <- 3

log_odds <- log(odds)
log_odds

p <- odds/(odds+1)
p
# log odds -> odds, probability(Y=1)

log_odds <- 0.8

odds <- exp(log_odds)
odds

p <- odds/(odds+1)
p

Für Multiple Regression:

\[\large P\left(Y_{i}=1 \mid x_{i 1}, \ldots, x_{i k}\right)=\frac{e^{\alpha+\beta_{1} x_{i 1}+\cdots+\beta_{k} x_{i k}}}{1+e^{\alpha+\beta_{1} x_{i 1}+\cdots+\beta_{k} x_{i k}}}\]

Interpretation Basics:

  • Aus der Odds-Schreibweise ergibt sich:
    • \(e^{\alpha}\) entspricht den Odds von Personen, die auf allen UVs den Wert 0 haben.
    • \(e^{\beta_{j}}\) entspricht dem Faktor, um den sich die Odds erhöhen, falls sich die UV \(j\) um eine Einheit erhöht und alle anderen UVs konstant bleiben.
  • Aus der Log-Odds-Schreibweise ergibt sich:
    • \(\alpha\) entspricht den Log-Odds von Personen, die auf allen UVs den Wert 0 haben.
    • Falls sich die UV \(j\) um eine Einheit erhöht und alle anderen UVs konstant bleiben, erhöhen sich die Log-Odds um \(\beta_{j}\).
data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(1,0,1,0,0,0,1,0))
fit <- glm(AV ~ UV, family="binomial", data = data)
#summary(fit)


# Log Odds
fit$coefficients[["(Intercept)"]]
fit$coefficients[["UV"]]
confint(fit, level=0.95)


# Odds
exp(fit$coefficients[["(Intercept)"]])
exp(fit$coefficients[["UV"]])
exp(confint(fit, level=0.95))

Modelle mit diskreten Prädiktoren:

\[\large \frac{P\left(Y_{i}=1 \mid 1\right)}{P\left(Y_{i}=0 \mid 1\right)}=e^{\alpha} \cdot e^{\beta \cdot 1}=\frac{P\left(Y_{i}=1 \mid 0\right)}{P\left(Y_{i}=0 \mid 0\right)} \cdot e^{\beta}\] Odds Ratio:

  • Wieviel mal sind die Odds in der Nicht-Referenzkategorie größer als in der Referenzkategorie?

\[\large \frac{\frac{P\left(Y_{i}=1 \mid 1\right)}{P\left(Y_{i}=0 \mid 1\right)}}{\frac{P\left(Y_{i}=1 \mid 0\right)}{P\left(Y_{i}=0 \mid 0\right)}}=e^{\beta}\]

# Odds Ratio aus Modell errechnen  
data <- data.frame(UV = c(0,1,1,1,0,0,0,0,1,1), AV = c(1,0,1,0,1,1,1,0,0,0))
fit <- glm(AV ~ UV, family="binomial", data = data)

exp(fit$coefficients[["UV"]])
# Odds Ratio aus Wahrscheinlichkeiten (Y=1)
p_ref = 0.7
p_nicht_ref = 0.5

(p_nicht_ref/(1-p_nicht_ref))/(p_ref/(1-p_ref))

Risk Ratio:

  • Um welchen Faktor ist das Auftreten von \(Y_{i}=1\) in der Nicht-Referenzkategorie wahrscheinlicher ist als in der Referenzkategorie?

\[\large \frac{P\left(Y_{i}=1 \mid 1\right)}{P\left(Y_{i}=1 \mid 0\right)} = \frac{1+e^{-\alpha}}{1+e^{-\alpha-\beta}}\]

# Risk Ratio aus Modell errechnen  
data <- data.frame(UV = c(0,1,1,1,0,0,0,0,1,1), AV = c(1,0,1,0,1,1,1,0,0,0))
fit <- glm(AV ~ UV, family="binomial", data = data)

(1+exp(-fit$coefficients[["(Intercept)"]]))/(1+exp(-fit$coefficients[["(Intercept)"]]-fit$coefficients[["UV"]]))
# Risk Ratio aus alpha und beta
alpha = 0.7
beta = 0.5

(1+exp(-alpha))/(1+exp(-alpha-beta))

Vorhersage

\[\large \hat{y}_{i}=\left\{\begin{array}{lc} 1, & \text { falls } & \frac{e^{a+b_{1} x_{i 1}+\cdots+b_{k} x_{i k}}}{1+e^{a+b_{1} x_{i 1}+\cdots+b_{k} x_{i k}}} \geq 0.5 \\ 0, & \text { sonst } \end{array}\right.\]

\[\large \hat{y}_{i}=\left\{\begin{array}{lc} 1, & \text { falls } a+b_{1} x_{i 1}+\cdots+b_{k} x_{i k} \geq 0 \\ 0, & \text { sonst } \end{array}\right.\]

data <- data.frame(UV = c(1,2,6,7,13,15,20,30), AV = c(1,0,1,0,0,0,1,0))
fit <- glm(AV ~ UV, family="binomial", data = data)

# Vorhersage mit R
data_new <- data.frame(UV = 8)
predict(fit, newdata = data_new, type="response")
alpha = 3
beta = 0.2

uv_val = 10

# Vorhersage per Hand
exp(alpha+beta*uv_val)/(1+exp(alpha+beta*uv_val))

Interpretationen bei Standardisierung

Beispiel mit 2 stetigen UVs ohne Interaktion, anwendbar auf beliebige Fälle (Achtung: bei logistischer regression erhöhen sich logodds, nicht AV Werte!)

UV

Normal
  • Intercept: Durchschnittlicher AV-Wert für Personen mit UV1=0 und UV2=0
  • Slope_1: Falls sich UV1 um eine Einheit erhöht und UV2 konstant bleibt, erhöht sich die AV um Slope_1
Zentriert

Parameter können eventuell sinnvoller interpretiert werden

  • Intercept: Durchschnittlicher AV-Wert für Personen mit durchschnittlichen UV1 und UV2
  • Slope_1: Falls sich UV1 um eine Einheit erhöht und UV2 konstant bleibt, erhöht sich die AV um Slope_1
z-Standardisiert

Parameter können eventuell sinnvoller interpretiert werden, VIF ist geringer

  • Intercept: Durchschnittlicher AV-Wert für Personen mit durchschnittlichen UV1 und UV2
  • Slope_1: Falls sich UV1 um eine Standardabweichung erhöht und UV2 konstant bleibt, erhöht sich die AV um Slope_1

AV

Normal
  • … erhöht sich die (Erwarteter) AV um Slope
z-standardisiert
  • … erhöht sich die (Erwarteter) AV um Slope Stanbdardabweichungen
LS0tDQp0aXRsZTogIlN0YXRpc3RpayAyIEZvcm1lbHNhbW1sdW5nICsgUiBDb2RlIg0KYXV0aG9yOiAiQWRyaWFuIFN0ZWZmYW4iDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQotLS0NCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCiAgYm9keXsNCiAgZm9udC1zaXplOiAxMXB0Ow0KICB9DQogIGgxLGgyLGgzLGg0LGg1IHsNCiAgICBtYXJnaW4tdG9wOiAzMHB4Ow0KICB9DQo8L3N0eWxlPg0KDQojIyMjIyMgKERhbmtlIGFuIERlbmlzZSwgTWF5IHVuZCBTb3BoaWEgZsO8cnMgS29ycmVrdHVybGVzZW4pDQoNCkRhcyBoaWVyIGlzdCBlaW5lIHNlbWktaW50ZXJha3RpdmUgRm9ybWVsc2FtbWx1bmcgw7xiZXIgYWxsZSB3aWNodGlnZW4gRm9ybWVsbiBkZXIgU3RhdGlzdGlrIDIgVm9ybGVzdW5nLiBadSBkZW4gbWVpc3RlbiBGb3JtZWxuIHVuZCBUZXN0cyBzaW5kIGVudHNwcmVjaGVuZGUgUiBCZWlzcGllbGUgenVyIEJlcmVjaG51bmcgYmVpZ2Vmw7xndCwgZGllc2UgYW0gYmVzdGVuIHBlciBDb3B5LVBhc3RlIGluIFJTdHVkaW8gZWluZsO8Z2VuIHVuZCBlaWdlbmUgV2VydGUgZWluc2V0emVuLiBBbHRlcm5hdGl2IGthbm4gZGFzIGdhbnplIE5vdGVib29rIGluIFJTdHVkaW8gYXVzZ2Vmw7xocnQgd2VyZGVuOiByZWNodHMgb2JlbiBhdWYgYENvZGUgLT4gRG93bmxvYWQgUm1kYCBrbGlja2VuIHVuZCBkaWUgaGVydW50ZXJnZWxhZGVuZSBEYXRlaSBpbiBSU3R1ZGlvIMO2ZmZuZW4uDQoNCkRvd25sb2FkIGbDvHIgT2ZmbGluZS1OdXR6dW5nOiBSZWNodHNrbGljayBpcmdlbmR3byBhdWYgZGllIFNlaXRlIC0+IGBTcGVpY2hlcm4gdW50ZXJgIC0+IGBXZWJzaXRlLCBudXIgSFRNTGAgKHdpY2h0aWcpLiBBbnNjaGxpZcOfZW5kIGRhcyBnZXNwZWljaGVydGUgRG9rdW1lbnQgZWluZmFjaCBtaXQgZGVtIEJyb3dzZXIgw7ZmZm5lbi4NCg0KRmFsbHMgenUgdW7DvGJlcnNpY2h0bGljaDogcmVjaHRzIG9iZW4gYXVmIGBDb2RlIC0+IEhpZGUgYWxsIENvZGVgIGtsaWNrZW4uDQpBbnNjaGxpZcOfZW5kIGJlaW0gZW50c3ByZWNoZW5kZW4gQWJzY2huaXR0IHJlY2h0cyBhdWYgYENvZGVgIGtsaWNrZW4sIHVtIGRpZSBwYXNzZW5kZW4gd2llZGVyIGVpbnp1YmxlbmRlbi4NCg0KDQpGb2xnZW5kZSBQYWtldGUgd2VyZGVuIHp1bSBBdXNmw7xocmVuIGRlciBDb2RlYmVpc3BpZWxlIGJlbsO2dGlndDoNCmBgYA0KaW5zdGFsbC5wYWNrYWdlcyhjKCJEZXNjVG9vbHMiLCAiZWZmc2l6ZSIsICJNQkVTUyIsICJwd3IiLCAibXVsdGNvbXAiLCAiZm9yY2F0cyIsICJjYXIiKSkNCmBgYA0KDQojIyMjIyMgW1p1csO8Y2sgenVyIEhvbWVwYWdlXShodHRwczovL2FkcmlhbnN0ZWZmYW4uY29tL2Rvd25sb2Fkcy9wc3ljaG9sb2d5KSANCg0KIyMjIEluaGFsdHN2ZXJ6ZWljaG5pcw0KDQoqIFtNZWhyZXJlIEh5cG90aGVzZW50ZXN0c10oPCNNZWhyZXJlSHlwb3RoZXNlbnRlc3RzPikNCiAgICAqIFtadXNhbW1lbmdlc2V0enRlIEh5cG90aGVzZW50ZXN0c10oI1p1c2FtbWVuZ2VzZXR6dGVIeXBvdGhlc2VudGVzdHMpDQogICAgKiBbTWV0YWFuYWx5c2VdKCNNZXRhYW5hbHlzZSkNCiogW1ZhcmlhbnphbmFseXNlXSg8I1ZhcmlhbnphbmFseXNlPikNCiAgICAqIFtFaW5mYWt0b3JpZWxsXSgjRWluZmFrdG9yaWVsbCkNCiAgICAgICAgKiBbT21uaWJ1c3Rlc3RdKCNPbW5pYnVzdGVzdEVpbikNCiAgICAgICAgKiBbRWZmZWt0Z3LDtsOfZV0oI0VmZmVrdGdyw7bDn2VFaW4pDQogICAgICAgICogW1ZhcmlhbnphbmFseXNlIEtvbnRyYXN0bWF0cml4XSgjVmFyaWFuemFuYWx5c2VFaW4pDQogICAgKiBbWndlaWZha3RvcmllbGxdKCNad2VpZmFrdG9yaWVsbCkNCiAgICAgICAgKiBbT21uaWJ1c3Rlc3RdKCNPbW5pYnVzdGVzdFp3ZWkpDQogICAgICAgICogW0VmZmVrdGdyw7bDn2VdKCNFZmZla3RncsO2w59lWndlaSkNCiAgICAgICAgKiBbVmFyaWFuemFuYWx5c2UgS29udHJhc3RtYXRyaXhdKCNWYXJpYW56YW5hbHlzZVp3ZWkpDQoqIFtSZWdyZXNzaW9uc2FuYWx5c2VdKCNSZWdyZXNzaW9uc2FuYWx5c2UpDQogICAgKiBbRWluZmFjaGUgTGluZWFyZSBSZWdyZXNzaW9uXSgjRUxSKQ0KICAgICAgICAqIFtQYXJhbWV0ZXJzY2jDpHR6dW5nXSgjUGFyYW1ldGVyc2Now6R0enVuZ0VMUikNCiAgICAgICAgKiBbSHlwb3RoZXNlbnRlc3RdKCNIeXBvdGhlc2VudGVzdEVMUikNCiAgICAqIFtNdWx0aXBsZSBMaW5lYXJlIFJlZ3Jlc3Npb25dKCNNTFIpDQogICAgICAgICogW1BhcmFtZXRlcnNjaMOkdHp1bmddKCNQYXJhbWV0ZXJzY2jDpHR6dW5nTUxSKQ0KICAgICAgICAqIFtIeXBvdGhlc2VudGVzdF0oI0h5cG90aGVzZW50ZXN0TUxSKQ0KICAgICAgICAqIFtLb2xsaW5lYXJpdMOkdF0oI0tvbGxpbmVhcml0w6R0KQ0KICAgICogW0VmZmVrdGdyw7bDn2VuXSgjRWZmZWt0Z3LDtsOfZW5MUikNCiAgICAqIFtTdGljaHByb2JlbnBsYW51bmddKCNTdGljaHByb2JlbnBsYW51bmdMUikNCiAgICAqIFtSZWdyZXNzaW9uc2RpYWdub3N0aWtdKCNSZWdyZXNzaW9uc2RpYWdub3N0aWspDQogICAgKiBbRGlza3JldGUgUHLDpGRpa3RvcmVuXSgjRGlza3JldGVQcsOkZGlrdG9yZW4pDQogICAgKiBbTG9naXN0aXNjaGUgUmVncmVzc2lvbl0oI0xvZ2lzdGlzY2hlUmVncmVzc2lvbikNCiAgICAqIFtJbnRlcnByZXRhdGlvbmVuIGJlaSBTdGFuZGFyZGlzaWVydW5nXSgjU3RhbmRhcmRpc2llcnVuZykNCiAgICANCg0KDQojIyBNZWhyZXJlIEh5cG90aGVzZW50ZXN0cyB7I01laHJlcmVIeXBvdGhlc2VudGVzdHN9DQoNClNvbmRlcmZhbGw6IE1laHJlcmUgbmljaHQgenVzYW1tZW5nZXNldHp0ZSBIeXBvdGhlc2VudGVzdHMgbWl0IHVudGVyc2NoaWVkbGljaGVuIEh5cG90aGVzZW4gJFxyaWdodGFycm93JCBuaWVkcmlnZSBGRFIgc2ljaGVyc3RlbGxlbiwgYWJlciBrZWluZSBLb3JyZWt0dXINCg0KIyMjIFp1c2FtbWVuZ2VzZXR6dGUgSHlwb3RoZXNlbnRlc3RzIHsjWnVzYW1tZW5nZXNldHp0ZUh5cG90aGVzZW50ZXN0c30NCiMjIyMgWnVzYW1tZW5nZXNldHp0ZSBIeXBvdGhlc2UgbWl0IG9kZXINCg0KJCRcbGFyZ2UgXGJlZ2lue2FycmF5fXtyfQ0KSF97MH06IEhfezAxfSBcdGV4dCB7IHVuZCB9IEhfezAyfSBcdGV4dCB7IHVuZCB9IFxsZG90cyBcdGV4dCB7IHVuZCB9IEhfezAgTn0gXFwNCkhfezF9OiBIX3sxMX0gXHRleHQgeyBvZGVyIH0gSF97MTJ9IFx0ZXh0IHsgb2RlciB9IFxsZG90cyBcdGV4dCB7IG9kZXIgfSBIX3sxIE59DQpcZW5ke2FycmF5fSQkDQoNCg0KIyMjIyBadXNhbW1lbmdlc2V0enRlIEh5cG90aGVzZSBtaXQgdW5kDQoNCiQkXGxhcmdlIFxiZWdpbnthbGlnbmVkfQ0KSF97MH06IEhfezAxfSBcdGV4dCB7IG9kZXIgfSBIX3swMn0gXHRleHQgeyBvZGVyIH0gXGxkb3RzIFx0ZXh0IHsgb2RlciB9IEhfezAgTn0gXFwNCkhfezF9OiBIX3sxMX0gXHRleHQgeyB1bmQgfSBIX3sxMn0gXHRleHQgeyB1bmQgfSBcbGRvdHMgXHRleHQgeyB1bmQgfSBIX3sxIE59DQpcZW5ke2FsaWduZWR9JCQNCg0KDQoNCiMjIyMgS29ycmVrdHVyIGRlcyBTaWduaWZpa2Fuem5pdmVhdXMNCg0KR3J1bmRzw6R0emxpY2ggZ2lsdDogTnVyIHp1c2FtbWVuZ2VzZXR6dGUgSHlwb3RoZXNlbiBtaXQgKipvZGVyKiogbcO8c3NlbiBrb3JyaWdpZXJ0IHdlcmRlbi4NCg0KJFxhbHBoYSQ6IENvbXBhcmlzb24gV2lzZSBFcnJvciBSYXRlIChlaW56ZWxuZSBUZXN0cykNCg0KJFxhbHBoYV57Kn0kOiBGYW1pbHkgV2lzZSBFcnJvciBSYXRlICh6dXNhbW1lbmdlc2V0enRlciBUZXN0KQ0KDQoqIFdhaHJzY2hlaW5saWNoa2VpdCwgYmVpIGVpbmVyIEdydXBwZSB2b24gSFQgbWluZGVzdGVucyBlaW5lbiBGZWhsZXIgZXJzdGVyIEFydCB6dSBtYWNoZW4NCg0KJCRcbGFyZ2UgXGFscGhhXnsqfT0xLSgxLVxhbHBoYSlee059JCQNCmBgYHtyfQ0KYWxwaGEgPSAwLjAwNQ0KTiA9IDUNCg0KMS0oMS1hbHBoYSleTg0KYGBgDQoNCiMjIyMjIFNpZGFrDQoNCkbDvHIgKip1bmFiaMOkbmdpZ2UqKiBIeXBvdGhlc2VudGVzdHMNCg0KJCRcbGFyZ2UgXGFscGhhPTEtXHNxcnRbTl17MS1cYWxwaGFeeyp9fSQkDQoNCmBgYHtyfQ0KZndlciA9IDAuMDA1DQpOID0gNQ0KDQoxLSgxLWZ3ZXIpXigxIC8gTikNCmBgYA0KIyMjIyMgQm9uZmVycm9uaQ0KDQpBdWNoIGbDvHIgKiphYmjDpG5naWdlKiogSHlwb3RoZXNlbnRlc3RzDQoNCiQkXGxhcmdlIFxhbHBoYT1cZnJhY3tcYWxwaGFee1xwcmltZX19e059JCQNCiQkXGxhcmdlIFxhbHBoYV57Kn0gXGxlcSBcYWxwaGFee1xwcmltZX0kJA0KDQpgYGB7cn0NCmZ3ZXIgPSAwLjAwNQ0KTiA9IDUNCg0KZndlci9ODQpgYGANCg0KQWx0ZXJuYXRpdjogcC1XZXJ0ZSBrb3JyaWdpZXJlbg0KDQokJFxsYXJnZSBwX3tqfSBcbGVxIFxmcmFje1xhbHBoYV57XHByaW1lfX17Tn0gXExlZnRyaWdodGFycm93IE4gXGNkb3QgcF97an0gXGxlcSBcYWxwaGFee1xwcmltZX0kJA0KYGBge3J9DQpwX3dlcnRlID0gYygwLjAwMywgMC4wMDQpDQpwLmFkanVzdChwX3dlcnRlLCBtZXRob2QgPSAnYm9uZmVycm9uaScpDQpgYGANCg0KIyMjIyMgVHVrZXkNCg0KQXVjaCBmw7xyICoqYWJow6RuZ2lnZSoqIEh5cG90aGVzZW50ZXN0cywgamVkb2NoIG51ciBpbiB2YXJpYW56YW5hbHl0aXNjaGVuIE1vZGVsbGVuIHVuZCBSZWdyZXNzaW9uc21vZGVsbGVuIG3DtmdsaWNoLiBIaWVyIGjDtmhlcmUgUG93ZXIgYWxzIEJvbmZlcnJvbmkuDQoNCg0KIyMjIyBGV0VSIGbDvHIgenVzYW1tZW5nZXNldHp0ZSBIeXBvdGhlc2VuIG1pdCAidW5kIg0KDQokJFxsYXJnZSBcYWxwaGFeeyp9PVxhbHBoYV57a30gXGNkb3QoMS1cYmV0YSlee24ta30kJA0KDQpgYGB7cn0NCiMgQW56YWhsIFN0dWRpZW4NCm4gPSAzDQoNCiMgQW56YWhsIFN0dWRpZW4sIGluIGRlbmVuIEgwIGtvcnJla3QgaXN0IChuKkJhc2lzcmF0ZSkNCmsgPSAxDQoNCmFscGhhID0gMC4wNQ0KcG93ZXIgPSAwLjgNCg0KDQphbHBoYSoqayoocG93ZXIpKioobi1rKQ0KDQpgYGANCg0KIyMjIE1ldGFhbmFseXNlIChtaXQgZmVzdGVuIEVmZmVrdGVuKSB7I01ldGFhbmFseXNlfQ0KDQpNZWhyZXJlIEh5cG90aGVzZW50ZXN0cyBhdXMgdmVyc2NoaWVkZW5lbiBTdGljaHByb2JlbiBtaXQgaWRlbnRpc2NoZW4NCkh5cG90aGVzZW4NCg0KQXVzZ2FuZ3NsYWdlOiBOIFN0dWRpZW4gc2Now6R0emVuIEVmZmVrdHN0w6Rya2UgJFx0aGV0YSQgbWl0IEZ1bmt0aW9uICRcaGF0e1x0aGV0YX1fe2p9JCwgQW5uYWhtZTogJFxoYXR7XHRoZXRhfV97an0gXHN0YWNrcmVse2kgbiBkfXtcc2ltfSBOXGxlZnQoXHRoZXRhLCBcc2lnbWFfe2p9XnsyfVxyaWdodCkkDQoNClNjaMOkdHpmdW5rdGlvbjoNCg0KDQokJFxsYXJnZSBcaGF0e1x0aGV0YX09XGZyYWN7MX17XHN1bV97aj0xfV57Tn0gV197an19IFxzdW1fe2o9MX1ee059IFdfe2p9IFxjZG90IFxoYXR7XHRoZXRhfV97an0kJA0KYGBge3J9DQp3ZWlnaHRzID0gYygwLjUsIDAuNSwgMC44KQ0KdGhldGFzID0gYygtMC4yLCAwLjUsIDAuNCkNCiAgDQoxLyhzdW0od2VpZ2h0cykpICogc3VtKHdlaWdodHMgKiB0aGV0YXMpDQpgYGANCg0KDQokJFxsYXJnZSBXX3tqfT1cZnJhY3sxfXtcaGF0e1xzaWdtYX1fe2p9XnsyfX0kJA0KYGBge3J9DQp2YXJqID0gMi41DQoNCjEvdmFyag0KYGBgDQoNCg0KJCRcbGFyZ2UgXGhhdHtcc2lnbWF9X3tqIFx0ZXh0IHsgd2VydCB9fV57Mn09XGZyYWN7bl97MSBqfStuX3syIGp9fXtuX3sxIGp9IFxjZG90IG5fezIgan19K1xmcmFje2Rfe2p9XnsyfX17MiBcY2RvdFxsZWZ0KG5fezEgan0rbl97MiBqfVxyaWdodCl9JCQNCg0KYGBge3J9DQpuMT0yMA0KbjI9MjANCmQgPSAxLjANCg0KKChuMStuMikvKG4xKm4yKSkrKGQqZC8oMioobjErbjIpKSkNCmBgYA0KDQokJFxsYXJnZSBkX3tqfT10X3tqfSBcY2RvdCBcc3FydHtcZnJhY3tuX3sxIGp9K25fezIgan19e25fezEgan0gXGNkb3Qgbl97MiBqfX19JCQNCmBgYHtyfQ0KbjE9MjANCm4yPTIwDQp0ID0gMy4yDQoNCnQqc3FydCgobjErbjIpLyhuMSpuMikpDQpgYGANCg0KDQokJFxsYXJnZSBkX3tqfT1cZnJhY3tcYmFye3h9X3sxIGp9LVxiYXJ7eH1fezIgan19e3Nfe1x0ZXh0IHtwb29sIH0sIGp9fSQkDQoNCmBgYHtyfQ0KZGF0YTEgPSBjKDAsMCwtMSkNCmRhdGEyID0gYygyLDAsMSkNCm4xID0gbGVuZ3RoKGRhdGExKQ0KbjIgPSBsZW5ndGgoZGF0YTIpDQp4MV9xdWVyID0gbWVhbihkYXRhMSkNCngyX3F1ZXIgPSBtZWFuKGRhdGEyKQ0KeGRpZmZfcXVlciA9IHgxX3F1ZXIteDJfcXVlcg0KczJfMSA9IHZhcihkYXRhMSkNCnMyXzIgPSB2YXIoZGF0YTIpDQpzMnBvb2wgPSAoKG4xLTEpKnMyXzErKG4yLTEpKnMyXzIpLyhuMStuMi0yKQ0KeGRpZmZfcXVlci9zcXJ0KHMycG9vbCkNCmBgYA0KDQoNCkludGVydmFsbCBtaXQgYXBwcm94aW1hdGl2ZW0gS29uZmlkZW56bml2ZWF1IHZvbiAkMS1cYWxwaGEkOg0KDQokJFxsYXJnZSBJXGxlZnQoXGhhdHtcdGhldGF9X3sxfSwgXGhhdHtcdGhldGF9X3syfSwgXGxkb3RzLCBcaGF0e1x0aGV0YX1fe059XHJpZ2h0KT1cbGVmdFtcaGF0e1x0aGV0YX0tel97MS1cZnJhY3tcYWxwaGF9ezJ9fSBcY2RvdCBcZnJhY3sxfXtcc3FydHtcc3VtX3tqPTF9XntOfSBXX3tqfX19LCBcaGF0e1x0aGV0YX0rel97MS1cZnJhY3tcYWxwaGF9ezJ9fSBcY2RvdCBcZnJhY3sxfXtcc3FydHtcc3VtX3tqPTF9XntOfSBXX3tqfX19XHJpZ2h0XSQkDQoNCg0KDQoNCg0KYGBge3J9DQpjb25mLmxldmVsID0gMC45NQ0KDQp3ZWlnaHRzID0gYygwLjUsIDAuNSwgMC44KQ0KdGhldGFzID0gYygtMC4yLCAwLjUsIDAuNCkNCnRoZXRhX2VzdCA9IDEvKHN1bSh3ZWlnaHRzKSkgKiBzdW0od2VpZ2h0cyAqIHRoZXRhcykNCg0KDQpjID0gcW5vcm0oMS0oKDEtY29uZi5sZXZlbCkvMikpL3NxcnQoc3VtKHdlaWdodHMpKQ0KYyh0aGV0YV9lc3QgLSBjLCB0aGV0YV9lc3QgKyBjKQ0KYGBgDQojIyMjIEh5cG90aGVzZW50ZXN0IE1ldGFhbmFseXNlOg0KDQpIeXBvdGhlc2VuOg0KDQokJFxsYXJnZSBcYmVnaW57YWxpZ25lZH0NCiZcbWF0aHJte0h9X3swfTogXGRlbHRhIFxsZXEgMCBcXA0KJlxtYXRocm17SH1fezF9OiBcZGVsdGE+MA0KXGVuZHthbGlnbmVkfSQkDQoNClRlc3RzdGF0aXN0aWs6IA0KDQokJFxsYXJnZSBUPVxsZWZ0KFxoYXR7XHRoZXRhfS1cdGhldGFfezB9XHJpZ2h0KSBcc3FydHtcc3VtX3tqPTF9XntOfSBXX3tqfX0gXHN0YWNrcmVse1xtYXRocm17YX19e1xzaW19IE4oMCwxKSQkDQoNCmBgYHtyfQ0KYWxwaGEgPSAwLjAwNQ0KdGhldGEwID0gMCANCg0Kd2VpZ2h0cyA9IGMoMC41LCAwLjUsIDAuOCkNCnRoZXRhcyA9IGMoLTAuMiwgMC41LCAwLjQpDQp0aGV0YV9lc3QgPSAxLyhzdW0od2VpZ2h0cykpICogc3VtKHdlaWdodHMgKiB0aGV0YXMpDQoNCg0KdCA9ICh0aGV0YV9lc3QtdGhldGEwKSAqIHNxcnQoc3VtKHdlaWdodHMpKQ0KdA0KDQojIERyZWkgbW9lZ2xpY2hlIEh5cG90aGVzZW50ZXN0cw0KcHJpbnQoImxlc3MvbGlua3NnZXJpY2h0ZXQ6IikNCnBhc3RlKCJLcml0LiBCZXJlaWNoOiBdIC1JTkY7IiwgcW5vcm0oYWxwaGEpLCJdIiwgc2VwPSIiKQ0KcCA9IHBub3JtKHQpDQpwDQoNCmlmKHAgPD0gYWxwaGEpIHByaW50KCJIMSBhbm5laG1lbiIpIGVsc2UgcHJpbnQoIkgwIGFubmVobWVuIikNCg0KcHJpbnQoImdyZWF0ZXIvcmVjaHRzZ2VyaWNodGV0OiIpDQpwYXN0ZSgiS3JpdC4gQmVyZWljaDogWyIsIHFub3JtKDEtYWxwaGEpLCI7SU5GWyIsIHNlcD0iIikNCnAgPSAxLXBub3JtKHQpDQpwDQoNCmlmKHAgPD0gYWxwaGEpIHByaW50KCJIMSBhbm5laG1lbiIpIGVsc2UgcHJpbnQoIkgwIGFubmVobWVuIikNCg0KcHJpbnQoInR3by5zaWRlZC91bmdlcmljaHRldDoiKQ0KcGFzdGUoIktyaXQuIEJlcmVpY2g6IF0tSU5GOyIsIHFub3JtKGFscGhhLzIpLCJdIFsiLCBxbm9ybSgxLShhbHBoYS8yKSksICI7IElORlsiLCBzZXA9IiIpDQpwID0gaWYodCA8PSAwKSAyKnBub3JtKHQpIGVsc2UgMipwbm9ybSgtdCkNCnANCg0KaWYocCA8PSBhbHBoYSkgcHJpbnQoIkgxIGFubmVobWVuIikgZWxzZSBwcmludCgiSDAgYW5uZWhtZW4iKQ0KDQpgYGANCg0KDQoNCg0KDQojIyBWYXJpYW56YW5hbHlzZSAoKipBTioqYWx5c2lzICoqTyoqZiAqKlZBKipyaWFuY2UpIHsjVmFyaWFuemFuYWx5c2V9DQoNCiMjIyBFaW5mYWt0b3JpZWxsZXMgc3RhdGlzdGlzY2hlcyBNb2RlbGwgeyNFaW5mYWt0b3JpZWxsfQ0KTW9kZWxsZ2xlaWNodW5nIG0tZmFjaCBnZXN0dWZ0ZXIgRmFrdG9yIChlcnN0ZSBEYXJzdGVsbHVuZ3Nmb3JtKToNCg0KJCRcbGFyZ2UgWV97aSBqfT1cbXVfe2p9K1x2YXJlcHNpbG9uX3tpIGp9IFxxdWFkIFx0ZXh0IHsgbWl0IH0gaj0xLCBcbGRvdHMsIG0gXHRleHQgeyB1bmQgfSBpPTEsIFxsZG90cywgbl97an0kJA0KDQokJFxsYXJnZSBZX3tpIGp9IFxzdGFja3JlbHtcdGV4dCB7IGluZCB9fXtcc2ltfSBOXGxlZnQoXG11X3tqfSwgXHNpZ21hXnsyfVxyaWdodCkgXHRleHQgeyBiencuIH0gXHZhcmVwc2lsb25fe2kgan0gXHN0YWNrcmVse1x0ZXh0IHsgaWlkIH19e1xzaW19IE5cbGVmdCgwLCBcc2lnbWFeezJ9XHJpZ2h0KSQkDQoNCk1vZGVsbGdsZWljaHVuZyBtLWZhY2ggZ2VzdHVmdGVyIEZha3RvciAoendlaXRlIERhcnN0ZWxsdW5nc2Zvcm0pOg0KJCRcbGFyZ2UgWV97aSBqfT1cbXUrXGFscGhhX3tqfStcdmFyZXBzaWxvbl97aSBqfSBccXVhZCBcdGV4dCB7IHdvYmVpIH0gXHF1YWQgXGFscGhhX3tqfT1cbXVfe2p9LVxtdSBcdGV4dCB7IG1pdCB9IGo9MSwgXGxkb3RzLCBtIFx0ZXh0IHsgdW5kIH0gXG11PVxmcmFjezF9e219IFxzdW1fe2o9MX1ee219IFxtdV97an0kJA0KDQokJFxsYXJnZSBZX3tpIGp9IFxzdGFja3JlbHtcdGV4dCB7IGluZCB9fXtcc2ltfSBOXGxlZnQoXG11K1xhbHBoYV97an0sIFxzaWdtYV57Mn1ccmlnaHQpIFx0ZXh0IHsgYnp3LiB9IFx2YXJlcHNpbG9uX3tpIGp9IFxzdGFja3JlbHtcdGV4dCB7IGlpZCB9fXtcc2ltfSBOXGxlZnQoMCwgXHNpZ21hXnsyfVxyaWdodCkkJA0KDQojIyMjIyBTY2jDpHR6ZnVua3Rpb25lbjogDQoNCiRcbXVfe2p9JA0KJCRcaGF0e1xtdX1fe2p9PVxiYXJ7WX1fe2p9PVxmcmFjezF9e25fe2p9fSBcc3VtX3tpPTF9XntufSBZX3tpIGp9JCQNCg0KDQokXGFscGhhX3tqfSQNCiQkXGhhdHtcYWxwaGF9X3tqfT1cYmFye1l9X3tqfS1cYmFye1l9JCQNCg0KDQokXHNpZ21hXnsyfSQgKGZhbGxzICRuX3sxfT1uX3syfT1cY2RvdHM9bl97bX09biQpDQoNCiQkXGxhcmdlIFxoYXR7XHNpZ21hfV57Mn09U197XHRleHQge3Bvb2wgfX1eezJ9PVxmcmFjezF9e20obi0xKX1cbGVmdChcc3VtX3tqPTF9XnttfSBcc3VtX3tpPTF9XntufVxsZWZ0KFlfe2kgan0tXGJhcntZfV97an1ccmlnaHQpXnsyfVxyaWdodCkkJA0KDQojIyMjIE9tbmlidXN0ZXN0IHsjT21uaWJ1c3Rlc3RFaW59DQoNCldpY2h0aWc6IG51ciAqKmVpbioqIFRlc3QsIGRlc2hhbGIga2VpbmUgS29ycmVrdHVyIGRlcyBTaWduaWZpa2Fuem5pdmF1cyBuw7Z0aWcNCg0KRXJzdGUgRGFyc3RlbGx1bmdzZm9ybToNCg0KJCRcbGFyZ2UgXGJlZ2lue2FycmF5fXtsfQ0KSF97MH06IFxtdV97MX09XG11X3syfT1cbGRvdHM9XG11X3trfSBcbGRvdHM9XG11X3ttfVxcDQpIX3sxfTogXG11X3tqfSBcbmVxIFxtdV97a30gXHF1YWQgXHRleHQgeyBmw7xyIG1pbmRlc3RlbnMgZWluIFBhYXIgfSBqLCBrIFx0ZXh0IHsgbWl0IH0gaiBcbmVxIGsNClxlbmR7YXJyYXl9JCQNClp3ZWl0ZSBEYXJzdGVsbHVuZ3Nmb3JtOg0KDQokJFxsYXJnZSBcYmVnaW57YXJyYXl9e2xsfQ0KSF97MH06IFxhbHBoYV97an09MCAmIFx0ZXh0IHsgZsO8ciBhbGxlIH0gaiBcXA0KSF97MX06IFxhbHBoYV97an0gXG5lcSAwICYgXHRleHQgeyBmw7xyIG1pbmRlc3RlbnMgZWluIH0gag0KXGVuZHthcnJheX0kJA0KDQojIyMjIyBRdWFkcmF0c3VtbWVuDQoNClF1YWRyYXRzdW1tZSBpbm5lcmhhbGI6DQoNCiQkXGxhcmdlIFEgU197aSBuIG59PVxzdW1fe2k9MX1ee259IFxzdW1fe2o9MX1ee219XGxlZnQoWV97aSBqfS1cYmFye1l9X3tqfVxyaWdodCleezJ9JCQNCg0KDQpRdWFkcmF0c3VtbWUgendpc2NoZW46DQoNCiQkXGxhcmdlIFEgU197eiB3fT1cc3VtX3tqPTF9XnttfSBuIFxjZG90XGxlZnQoXGJhcntZfV97an0tXGJhcntZfVxyaWdodCleezJ9JCQNCiQkXGxhcmdlIFxiYXJ7WX09XGZyYWN7MX17bX0gXGZyYWN7MX17bn0gXHN1bV97aj0xfV57bX0gXHN1bV97aT0xfV57bn0gWV97aSBqfSQkDQoNCg0KUXVhZHJhdHN1bW1lIGdlc2FtdDoNCg0KJCRcbGFyZ2UgUSBTX3tnIGUgc309XHN1bV97aj0xfV57bX0gXHN1bV97aT0xfV57bn1cbGVmdChZX3tpIGp9LVxiYXJ7WX1ccmlnaHQpXnsyfSQkDQokJFxsYXJnZSBRIFNfe2cgZSBzfT1RIFNfe3ogd30rUSBTX3tpIG4gbn0kJA0KDQoNCmBgYHtyfQ0KdXYgPSBjKCJBIiwiQSIsIkEiLCJCIiwiQiIsIkIiLCJDIiwiQyIsIkMiKSANCmF2ID0gYygxLDIsMyw0LDUsNiw3LDgsOSkNCmRhdGEgPSBkYXRhLmZyYW1lKHV2LGF2KQ0KDQpxc19pbm4gPSBzdW0oDQogIHNhcHBseSh1bmlxdWUodXYpLA0KICAgICAgICAgZnVuY3Rpb24oZ3JvdXApIHN1bSgoZGF0YVtkYXRhJHV2PT1ncm91cCxdJGF2IC0gbWVhbihkYXRhW2RhdGEkdXY9PWdyb3VwLF0kYXYpKV4yKQ0KICApDQopIA0KDQpxc196dyA9IHN1bSggDQogIHNhcHBseSh1bmlxdWUodXYpLA0KICAgICAgICAgZnVuY3Rpb24oZ3JvdXApIG5yb3coZGF0YVtkYXRhJHV2PT1ncm91cCxdKSoobWVhbihkYXRhW2RhdGEkdXY9PWdyb3VwLF0kYXYpIC0gbWVhbihkYXRhJGF2KSleMg0KICApDQopDQoNCnFzX2lubiArIHFzX3p3DQoNCmBgYA0KDQoNCk1pdHRsZXJlIFF1YWRyYXRzdW1tZSB6d2lzY2hlbjoNCg0KJCRcbGFyZ2UgTSBRIFNfe3ogd309XGZyYWN7USBTX3t6IHd9fXtkIGZfe3ogd319JCQNCiQkXGxhcmdlIGRmX3t6IHd9PW0tMSQkDQpNaXR0bGVyZSBRdWFkcmF0c3VtbWUgaW5uZXJoYWxiOg0KDQokJFxsYXJnZSBNIFEgU197aSBuIG59PVxmcmFje1EgU197aSBuIG59fXtkIGZfe2kgbiBufX0kJA0KJCRcbGFyZ2UgZGZfe1x0ZXh0IHtpbm4gfX09bShuLTEpJCQNCg0KJCRcbGFyZ2UgTSBRIFNfe2kgbiBufT1TX3tcdGV4dCB7cG9vbCB9fV57Mn0kJA0KV2VpdGVyZSBFaWdlbnNjaGFmdGVuOg0KDQokJFxsYXJnZSBFXGxlZnQoTSBRIFNfe2kgbiBufVxyaWdodCk9RVxsZWZ0KFNfe1x0ZXh0IHtwb29sIH19XnsyfVxyaWdodCk9XHNpZ21hXnsyfSQkDQoNCiQkXGxhcmdlIEVcbGVmdChNIFEgU197eiB3fVxyaWdodCk9XHNpZ21hXnsyfStcZnJhY3tcc3VtX3tqPTF9XnttfSBuIFxjZG90IFxhbHBoYV97an1eezJ9fXtkIGZfe3ogd319PVxzaWdtYV57Mn0rXGZyYWN7XHN1bV97aj0xfV57bX0gblxsZWZ0KFxtdV97an0tXG11XHJpZ2h0KV57Mn19e20tMX0kJA0KDQojIyMjIyBUZXN0c3RhdGlzdGlrIE9tbmlidXN0ZXN0DQoNCiQkXGxhcmdlIFQ9XGZyYWN7USBTX3t6IHd9IC8gZCBmX3t6IHd9fXtRIFNfe2kgbiBufSAvIGQgZl97aSBuIG59fT1cZnJhY3tNIFEgU197eiB3fX17TSBRIFNfe2kgbiBufX0gXHN0YWNrcmVse0hfezB9fXtcc2ltfSBGXGxlZnQoZCBmX3t6IHd9LCBkIGZfe2kgbiBufVxyaWdodCkkJA0KDQoNCiMjIyMjIEYtVmVydGVpbHVuZyANCiQkXGxhcmdlIFggXHNpbSBGXGxlZnQodl97MX0sIHZfezJ9XHJpZ2h0KSQkDQokJFxsYXJnZSBFKFgpPVxmcmFje3ZfezJ9fXt2X3syfS0yfSAkJA0KDQpgYGB7cn0NCmRmMSA9IDINCmRmMiA9IDEwDQpwZihxPTIsIGRmMSwgZGYyKSAjIFZlcnRlaWx1bmdzZnVua3Rpb24NCnFmKHA9MC4yNSwgZGYxLCBkZjIpICMgUXVhbnRpbGUNCmBgYA0KDQoNCg0KIyMjIyMgS3JpdGlzY2hlciBCZXJlaWNoIE9tbmlidXN0ZXN0DQoNCiQkXGxhcmdlIEtfe1R9PVtrX3tyZWNodHN9LCBcaW5mdHlbJCQNCg0KIyMjIyMgUiBDb2RlDQoNCmBgYHtyfQ0KdXYgPSBjKCJBIiwiQSIsIkEiLCJCIiwiQiIsIkIiLCJDIiwiQyIsIkMiKSANCmF2ID0gYygxLDIsMyw0LDUsNiw3LDgsOSkNCmFscGhhID0gMC4wMDUNCg0KZGF0YSA9IGRhdGEuZnJhbWUodXYsYXYpDQoNCiMgT21uaWJ1c3Rlc3QgKHVua29ycmlnaWVydCkgdm9uIEhhbmQgLSBXZW5uIG51ciBrb25rcmV0ZSBXZXJ0ZSB2b3JsaWVnZW4gdW5kIGtlaW5lIERhdGVudmVrdG9yZW4sIGRpZSBmb2xnZW5kZW4gVmFyaWFibGVuIGR1cmNoIGVpZ2VuZSBXZXJ0ZSBlcnNldHplbg0KDQptID0gbGVuZ3RoKHVuaXF1ZSh1dikpDQpuID0gbnJvdyhkYXRhW2RhdGEkdXY9PXV2W1sxXV0sXSkgIyBiYWxhbmNpZXJ0ZXMgZGVzaWduDQoNCmRmX3p3ID0gbS0xDQpkZl9pbm4gPSBtKihuLTEpIA0KDQpxc19pbm4gPSBzdW0oDQogIHNhcHBseSh1bmlxdWUodXYpLA0KICAgICAgICAgZnVuY3Rpb24oZ3JvdXApIHN1bSgoZGF0YVtkYXRhJHV2PT1ncm91cCxdJGF2IC0gbWVhbihkYXRhW2RhdGEkdXY9PWdyb3VwLF0kYXYpKV4yKQ0KICApDQopIA0KDQpxc196dyA9IHN1bSggDQogIHNhcHBseSh1bmlxdWUodXYpLA0KICAgICAgICAgZnVuY3Rpb24oZ3JvdXApIG5yb3coZGF0YVtkYXRhJHV2PT1ncm91cCxdKSoobWVhbihkYXRhW2RhdGEkdXY9PWdyb3VwLF0kYXYpIC0gbWVhbihkYXRhJGF2KSleMg0KICApDQopDQoNCnBhc3RlKCJRU2dlczogIiwgcXNfaW5uICsgcXNfencsIHNlcD0iIikNCg0KbXFzX2luID0gcXNfaW5uIC8gZGZfaW5uDQptcXNfencgPSAocXNfencpIC8gZGZfencNCg0KcGFzdGUoIktyaXQuIEJlcmVpY2g6IFsiLCBxZigxLWFscGhhLCBkZjE9ZGZfencsIGRmMj1kZl9pbm4pLCI7SU5GWyIsIHNlcD0iIikNCg0KdCA9IG1xc196dy9tcXNfaW4NCnQNCg0KcCA9IDEtcGYobXFzX3p3L21xc19pbiwgZGYxID0gZGZfencsIGRmMiA9IGRmX2lubikNCnANCg0KaWYocCA8PSBhbHBoYSkgcHJpbnQoIkgxIGFubmVobWVuIikgZWxzZSBwcmludCgiSDAgYW5uZWhtZW4iKQ0KDQoNCiMgT21uaWJ1c3Rlc3QgbWl0IFIgRnVua3Rpb24gMSAodW5rb3JyaWdpZXJ0KQ0KZml0ID0gYW92KGF2fnV2LCBkYXRhPWRhdGEpDQpzdW1tYXJ5KGZpdCkNCg0KIyBPbW5pYnVzdGVzdCBtaXQgUiBGdW5rdGlvbiAyIChrb3JyaWdpZXJ0IC0gd2VubiBWYXJpYW56Z2xlaWNoaGVpdCB2ZXJsZXR6dCkNCm9uZXdheS50ZXN0KGF2fnV2LCBkYXRhKSANCmBgYA0KDQoNCmBgYHtyfQ0KIyBXZWxjaGVyIFdlcnQgZW50c3ByaWNodCB3ZWxjaGVtIG91dHB1dCB2b24gUj8NCg0KdXYgPSBjKCJBIiwiQSIsIkEiLCJCIiwiQiIsIkIiLCJDIiwiQyIsIkMiKSANCmF2ID0gYygxLDIsMyw0LDUsNiw3LDgsOSkNCmRhdGEgPSBkYXRhLmZyYW1lKHV2LGF2KQ0KDQpmaXQgPC0gYW92KGF2IH4gdXYsIGRhdGE9ZGF0YSkNCiNzdHIoc3VtbWFyeShmaXQpKQ0KDQpkZl96dyA9IHN1bW1hcnkoZml0KVtbMV1dJCdEZidbWzFdXQ0KZGZfaW5uID0gc3VtbWFyeShmaXQpW1sxXV0kJ0RmJ1tbMl1dDQoNCnFzX3p3ID0gc3VtbWFyeShmaXQpW1sxXV0kJ1N1bSBTcSdbWzFdXQ0KcXNfaW5uID0gc3VtbWFyeShmaXQpW1sxXV0kJ1N1bSBTcSdbWzJdXQ0KDQptcXNfencgPSBzdW1tYXJ5KGZpdClbWzFdXSQnTWVhbiBTcSdbWzFdXQ0KbXFzX2lubiA9IHN1bW1hcnkoZml0KVtbMV1dJCdNZWFuIFNxJ1tbMl1dDQoNCmYgPSBzdW1tYXJ5KGZpdClbWzFdXSQnRiB2YWx1ZSdbWzFdXQ0KDQpwID0gc3VtbWFyeShmaXQpW1sxXV0kJ1ByKD5GKSdbWzFdXQ0KDQpgYGANCg0KIyMjIyBFZmZla3RncsO2w59lIGltIGVpbmZha3RvcmllbGxlbiB2YXJpYW56YW5hbHl0aXNjaGVuIE1vZGVsbCB7I0VmZmVrdGdyw7bDn2VFaW59DQoNCkFudGVpbCBhbiBkZXIgR2VzYW10dmFyaWFueiBkZXIgQVYgaW4gZGVyIFBvcHVsYXRpb24sIGRlciBkdXJjaCBkaWUNClVWIChiencuIGR1cmNoIGRlbiBGYWt0b3IpIGVya2zDpHJ0IHdlcmRlbiBrYW5uLg0KDQokJFxsYXJnZSBcZXRhXnsyfT1cZnJhY3tcc2lnbWFfe3ogd31eezJ9fXtcc2lnbWFfe2cgZSBzfV57Mn19JCQNCg0KJCRcbGFyZ2UgXGhhdHtcc2lnbWF9X3t6IHd9XnsyfT1cZnJhY3sxfXttIFxjZG90IG59IFEgU197eiB3fSQkDQoNCiQkXGxhcmdlIFxoYXR7XHNpZ21hfV97Z2VzfV57Mn09XGZyYWN7MX17bSBcY2RvdCBufSBRIFNfe2dlc30kJA0KDQoNClNjaMOkdHpmdW5rdGlvbjoNCg0KJCRcbGFyZ2UgXGhhdHtcZXRhfV57Mn09XGZyYWN7USBTX3t6IHd9fXtRIFNfe1x0ZXh0IHtnZXMgfX19JCQNCg0KYGBge3J9DQp1diA9IGMoIkEiLCJBIiwiQSIsIkIiLCJCIiwiQiIsIkMiLCJDIiwiQyIpIA0KYXYgPSBjKDEsMiwzLDQsNSw2LDcsOCw5KQ0KDQpkYXRhID0gZGF0YS5mcmFtZSh1dixhdikNCg0KIyBCZXJlY2hudW5nIEV0YSB2b24gSGFuZCAtIFdlbm4gbnVyIGtvbmtyZXRlIFdlcnRlIHZvcmxpZWdlbiB1bmQga2VpbmUgRGF0ZW52ZWt0b3JlbiwgZGllIGZvbGdlbmRlbiBWYXJpYWJsZW4gZHVyY2ggZWlnZW5lIFdlcnRlIGVyc2V0emVuDQoNCm4gPSBsZW5ndGgodW5pcXVlKHV2KSkNCm0gPSBucm93KGRhdGFbZGF0YSR1dj09dXZbWzFdXSxdKSAjIGJhbGFuY2llcnRlcyBkZXNpZ24NCg0KZGZfencgPSBuLTENCmRmX2lubiA9IG4qKG0tMSkgDQoNCnFzX2lubiA9IHN1bSgNCiAgc2FwcGx5KHVuaXF1ZSh1diksDQogICAgICAgICBmdW5jdGlvbihncm91cCkgc3VtKChkYXRhW2RhdGEkdXY9PWdyb3VwLF0kYXYgLSBtZWFuKGRhdGFbZGF0YSR1dj09Z3JvdXAsXSRhdikpXjIpDQogICkNCikgDQoNCnFzX3p3ID0gc3VtKCANCiAgc2FwcGx5KHVuaXF1ZSh1diksDQogICAgICAgICBmdW5jdGlvbihncm91cCkgbnJvdyhkYXRhW2RhdGEkdXY9PWdyb3VwLF0pKihtZWFuKGRhdGFbZGF0YSR1dj09Z3JvdXAsXSRhdikgLSBtZWFuKGRhdGEkYXYpKV4yDQogICkNCikNCg0KcXNfencvKHFzX2lubiArIHFzX3p3KQ0KDQoNCiMgQmVyZWNobnVuZyBFdGEgbWl0IFIgRnVua3Rpb24NCmxpYnJhcnkoRGVzY1Rvb2xzKQ0KZml0ID0gYW92KGF2fnV2LCBkYXRhPWRhdGEpDQpFdGFTcShmaXQpDQoNCiMgQmVyY2hudW5nIEtvbmZpZGVuemludGV2YWxsIGbDvHIgRXRhDQpsaWJyYXJ5KE1CRVNTKQ0KY2kucHZhZihzdW1tYXJ5KGZpdClbWzFdXVtbIkYgdmFsdWUiXV1bWzFdXSAsZGYuMSA9IGRmX3p3LCBkZi4yID0gZGZfaW5uLCBOPW5yb3coZGF0YSksIGNvbmYubGV2ZWwgPSAwLjk1KQ0KYGBgDQoNCg0KRGllIHN0YXRpc3Rpc2NoZSBIeXBvdGhlc2UgZGVzIE9tbmlidXMtVGVzdHMga8O2bm50ZSBhbHRlcm5hdGl2IHNvIGdlc2NocmllYmVuIHdlcmRlbjoNCg0KJCRcbGFyZ2UgXGJlZ2lue2FsaWduZWR9DQomSF97MH06IFxldGFeezJ9PTAgXFwNCiZIX3sxfTogXGV0YV57Mn0+MA0KXGVuZHthbGlnbmVkfSQkDQoNCg0KIyMjIyMgU3RpY2hwcm9iZW5wbGFudW5nIGbDvHIgT21uaWJ1c3Rlc3QNCg0KUiBmdW5rdGlvbiBuaW1tdCAkXGV0YV57Mn0kIG5pY2h0IGRpcmVrdCwgd2lyIG3DvHNzZW4gdW1yZWNobmVuOg0KJCRcbGFyZ2UgZj1cc3FydHtcZnJhY3tcZXRhXnsyfX17MS1cZXRhXnsyfX19JCQNCg0KYGBge3J9DQpsaWJyYXJ5KHB3cikNCg0KZXRhID0gMC4wNQ0KYWxwaGEgPSAwLjAwNQ0KcG93ZXIgPSAwLjgNCmZhY3RvcnM9Mw0KDQpmID0gc3FydChldGEvKDEtZXRhKSkNCg0KcHdyLmFub3ZhLnRlc3Qoaz1mYWN0b3JzLCBmPWYsIHBvd2VyPXBvd2VyLCBzaWcubGV2ZWw9YWxwaGEpDQpgYGANCg0KDQoNCiMjIyMgV2VpdGVyZSBzdGF0aXN0aXNjaGUgVmVyZmFocmVuIGltIGVpbmZha3RvcmllbGxlbiB2YXJpYW56YW5hbHl0aXNjaGVuIE1vZGVsbCAtIEtvbnRyYXN0bWF0cml4IHsjVmFyaWFuemFuYWx5c2VFaW59DQoNCkF1c2dhbmdzcHVua3Q6DQoNCkZvcm11bGllcnVuZyB2b24gUGFyYW1ldGVyYmV6aWVodW5nZW4gbWl0DQokJFxsYXJnZSBcc3VtX3tqPTF9XnttfSBhX3tqfSBcY2RvdCBcbXVfe2p9JCQNCg0KDQpEaWVzZSBQYXJhbWV0ZXJiZXppZWhuZyB3aXJkICJLb250cmFzdCIgZ2VuYW5udCwgZmFsbHMgZGllIEtvbnN0YW50ZW4gZm9sZ2VuZGUgRWlnZW5zY2hhZnQgaGFiZW46DQoNCiQkXGxhcmdlIFxzdW1fe2o9MX1ee219IGFfe2p9PTAkJA0KDQoNClNjaMOkdHpmdW5rdGlvbiBmw7xyICRcbXVfe2p9LVxtdV97a30kDQoNCiQkXGxhcmdlIFxiYXJ7WX1fe2p9LVxiYXJ7WX1fe2t9JCQNCkVpbiBLb25maWRlbnppbnRlcnZhbGwgbWl0IEtvbmZpZGVuem5pdmVhdSAkMS1cYWxwaGEkIGbDvHIgJFxtdV97an0tXG11X3trfSQNCg0KJCRcbGFyZ2UgXGxlZnRbXGxlZnQoXGJhcntZfV97an0tXGJhcntZfV97a31ccmlnaHQpLXRfezEtXGZyYWN7XGFscGhhfXsyfX0gXGNkb3QgXHNxcnR7XGZyYWN7U197cCBvIG8gbH1eezJ9fXtufStcZnJhY3tTX3twIG8gbyBsfV57Mn19e259fSxcbGVmdChcYmFye1l9X3tqfS1cYmFye1l9X3trfVxyaWdodCkrdF97MS1cZnJhY3tcYWxwaGF9ezJ9fSBcY2RvdCBcc3FydHtcZnJhY3tTX3twIG8gbyBsfV57Mn19e259K1xmcmFje1Nfe1x0ZXh0IHtwb29sIH19XnsyfX17bn19XHJpZ2h0XSQkDQokJFxsYXJnZSB0e1xzaW19IHQobShuLTEpKSQkDQokJFxsYXJnZSBTX3tcdGV4dCB7cG9vbCB9fV57Mn09TSBRIFNfe1x0ZXh0IHtpbm4gfX0kJA0KDQoNClRlc3RzdGF0aXN0aWsgZsO8ciBkZW4gSHlwb3RoZXNlbnRlc3QgYmV6w7xnbGljaCAkXG11X3tqfS1cbXVfe2t9JA0KDQokJFxsYXJnZSBUPVxmcmFje1xsZWZ0KFxiYXJ7WX1fe2p9LVxiYXJ7WX1fe2t9XHJpZ2h0KS1cbXVfezB9fXtcc3FydHtcZnJhY3tTX3tcdGV4dCB7cG9vbCB9fV57Mn19e259K1xmcmFje1Nfe1x0ZXh0IHtwb29sIH19XnsyfX17bn19fSBcc3RhY2tyZWx7SF97MH19e1xzaW19IHQobShuLTEpKSQkDQoNCg0KIyMjIyMgUiBDb2RlIEtvbmZpZGVuemludGVydmFsbCwgdW5nZXJpY2h0ZXRlciBIeXBvdGhlc2VudGVzdA0KDQpgYGB7cn0NCmxpYnJhcnkobXVsdGNvbXApDQp1diA9IGMoIkEiLCJBIiwiQSIsIkIiLCJCIiwiQiIsIkMiLCJDIiwiQyIpIA0KYXYgPSBjKDEsMiwzLDQsNSw2LDcsOCw5KQ0KDQpkYXRhID0gZGF0YS5mcmFtZSh1dixhdiwgc3RyaW5nc0FzRmFjdG9ycyA9IFRSVUUpDQoNCmZpdF9hb3YgPC0gYW92KGF2IH4gdXYsIGRhdGEgPSBkYXRhKQ0KDQojICJOdWxsaHlwb3RoZXNlbiINCmh5cHMgPSBjKA0KICAiQSAtIEIgPT0gMCIsDQogICJBIC0gQyA9PSAwIg0KKQ0KDQoNCiMgS29udHJhc3QgTWF0cml4DQpjb250cmFzdHMgPC0gbWNwKHV2ID0gaHlwcykNCmZpdCA8LSBnbGh0KGZpdF9hb3YsIGxpbmZjdCA9IGNvbnRyYXN0cykNCg0KY29uZmludChmaXQsIGxldmVsID0gMC45NSwgY2FscGhhID0gdW5pdmFyaWF0ZV9jYWxwaGEoKSkNCiMgInNpbmdsZS1zdGVwIjogVHVrZXkgTWV0aG9kZSwgdW5pdmFyaWF0ZSgpOiBLZWluZSBLb3JyZWt0dXIsICJib25mZXJyb25pIjogQm9uZmVycm9uaQ0Kc3VtbWFyeShmaXQsIHRlc3QgPSBhZGp1c3RlZCh0eXBlID0gInNpbmdsZS1zdGVwIikpIA0KYGBgDQoNCiMjIyMjIFIgQ29kZSBnZXJpY2h0ZXRlciBIeXBvdGhlc2VudGVzdA0KDQpgYGB7cn0NCmxpYnJhcnkobXVsdGNvbXApDQp1diA9IGMoIkEiLCJBIiwiQSIsIkIiLCJCIiwiQiIsIkMiLCJDIiwiQyIpIA0KYXYgPSBjKDEsMiwzLDQsNSw2LDcsOCw5KQ0KDQpkYXRhID0gZGF0YS5mcmFtZSh1dixhdiwgc3RyaW5nc0FzRmFjdG9ycyA9IFRSVUUpDQoNCmZpdF9hb3YgPC0gYW92KGF2IH4gdXYsIGRhdGEgPSBkYXRhKQ0KDQojIE51bGxoeXBvdGhlc2VuDQpoeXBzID0gYygNCiAgIkEgLSBCIDw9IDAiLA0KICAiQSAtIEMgPD0gMCINCikNCg0KDQojIEtvbnRyYXN0IE1hdHJpeA0KY29udHJhc3RzIDwtIG1jcCh1diA9IGh5cHMpDQpmaXQgPC0gZ2xodChmaXRfYW92LCBsaW5mY3QgPSBjb250cmFzdHMpDQoNCiMgInNpbmdsZS1zdGVwIjogVHVrZXkgTWV0aG9kZSwgdW5pdmFyaWF0ZSgpOiBLZWluZSBLb3JyZWt0dXIsICJib25mZXJyb25pIjogQm9uZmVycm9uaQ0Kc3VtbWFyeShmaXQsIHRlc3QgPSBhZGp1c3RlZCh0eXBlID0gInNpbmdsZS1zdGVwIikpIA0KYGBgDQoNCg0KDQojIyMjIFp3ZWlmYWt0b3JpZWxsZXMgc3RhdGlzdGlzY2hlcyBNb2RlbGwgeyNad2VpZmFrdG9yaWVsbH0NCk1vZGVsbGdsZWljaHVuZyBtLWZhY2ggZ2VzdHVmdGVyIEZha3RvciAoZXJzdGUgRGFyc3RlbGx1bmdzZm9ybSk6DQoNCiQkXGxhcmdlIFlfe2kgaiBrfT1cbXVfe2oga30rXHZhcmVwc2lsb25fe2kgaiBrfSBcdGV4dCB7IG1pdCB9IGk9MSwgXGxkb3RzLCBuX3tqIGt9IDsgaj0xLCBcbGRvdHMsIHIgXHRleHQgeyB1bmQgfSBrPTEsIFxsZG90cywgYyQkDQokJFxsYXJnZSBZX3tpIGoga30gXHN0YWNrcmVse1xtYXRocm17aW5kfX17XHNpbX0gTlxsZWZ0KFxtdV97aiBrfSwgXHNpZ21hXnsyfVxyaWdodCkgXG1hdGhybXtiend9IC4gXHZhcmVwc2lsb25fe2kgaiBrfSBcc3RhY2tyZWx7XG1hdGhybXtpaWR9fXtcc2ltfSBOXGxlZnQoMCwgXHNpZ21hXnsyfVxyaWdodCkkJA0KTWl0dGxlcmUgQVYgw7xiZXIgYmVzdGltbXRlIFBvcHVsYXRpb25lbjoNCg0KJCRcbGFyZ2UgXGJlZ2lue2FycmF5fXtjfQ0KXG11PVxmcmFjezF9e3IgXGNkb3QgY30gXHN1bV97aj0xfV57cn0gXHN1bV97az0xfV57Y30gXG11X3tqIGt9IFxcDQpcbXVfe2p9IC49XGZyYWN7MX17Y30gXHN1bV97az0xfV57Y30gXG11X3tqIGt9IFxcDQpcbXVfe1xjZG90IGt9PVxmcmFjezF9e3J9IFxzdW1fe2o9MX1ee3J9IFxtdV97aiBrfQ0KXGVuZHthcnJheX0kJA0KTW9kZWxsZ2xlaWNodW5nIG0tZmFjaCBnZXN0dWZ0ZXIgRmFrdG9yICh6d2VpdGUgRGFyc3RlbGx1bmdzZm9ybSk6DQoNCiQkXGxhcmdlIFlfe2kgaiBrfT1cbXUrXGFscGhhX3tqfStcYmV0YV97a30rXGdhbW1hX3tqIGt9K1x2YXJlcHNpbG9uX3tpIGoga30gXHF1YWQgXHRleHQgeyBtaXQgfSBpPTEsIFxsZG90cywgbl97aiBrfSA7IGo9MSwgXGxkb3RzLCByIFx0ZXh0IHsgdW5kIH0gaz0xLCBcbGRvdHMsIGMkJA0KJCRcbGFyZ2UgWV97aSBqIGt9IFxzdGFja3JlbHtcdGV4dCB7IGluZCB9fXtcc2ltfSBOXGxlZnQoXG11K1xhbHBoYV97an0rXGJldGFfe2t9K1xnYW1tYV97aiBrfSwgXHNpZ21hXnsyfVxyaWdodCkgXHRleHQgeyBiencuIH0gXHZhcmVwc2lsb25fe2kgaiBrfSBcc3RhY2tyZWx7XHRleHQgeyBpaWQgfX17XHNpbX0gTlxsZWZ0KDAsIFxzaWdtYV57Mn1ccmlnaHQpJCQNCg0KKiAkXGFscGhhX3tqfT1cbXVfe2ogLn0tXG11JCBFZmZla3QgZGVyIEthdGVnb3JpZSBqIGRlcyBGYWt0b3JzIEEgYXVmIGRpZSBBVg0KKiAkXGJldGFfe2t9PVxtdV97LiBrfS1cbXUkIEVmZmVrdCBkZXIgS2F0ZWdvcmllIGsgZGVzIEZha3RvcnMgQiBhdWYgZGllIEFWDQoqICRcZ2FtbWFfe2oga309XG11X3tqIGt9LVxtdS1cYWxwaGFfe2p9LVxiZXRhX3trfSQgSW50ZXJha3Rpb25zZWZmZWt0IGJlem9nZW4gYXVmIGRpZQ0KUG9wdWxhdGlvbiBqaw0KDQoNCiMjIyMjIFNjaMOkdHpmdW5rdGlvbmVuIGbDvHIgUGFyYW1ldGVyDQoNCkbDvHIgJFxtdV97aiBrfSQ6DQokJFxsYXJnZSBcaGF0e1xtdX1fe2oga309XGJhcntZfV97aiBrfT1cZnJhY3sxfXtufSBcc3VtX3tpPTF9XntufSBZX3tpIGoga30kJA0KDQpGw7xyICRcc2lnbWFeezJ9JDoNCiQkXGxhcmdlIFxoYXR7XHNpZ21hfV57Mn09U197XHRleHQge3Bvb2wgfX1eezJ9PVxmcmFjezF9e3IgXGNkb3QgYyhuLTEpfVxsZWZ0KFxzdW1fe2o9MX1ee3J9IFxzdW1fe2s9MX1ee2N9IFxzdW1fe2k9MX1ee259XGxlZnQoWV97aSBqIGt9LVxiYXJ7WX1fe2oga31ccmlnaHQpXnsyfVxyaWdodCkkJA0KDQoNCiMjIyMjIE9tbmlidXN0ZXN0IHsjT21uaWJ1c3Rlc3Rad2VpfQ0KDQpPbW5pYnVzdGVzdCBmw7xyIGRpZSBJbnRlcmFrdGlvbjoNCg0KKiAkSF97MH06IFxnYW1tYV97aiBrfT0wJCBmw7xyIGFsbGUgS29tYmluYXRpb25lbiAkaiBrJCANCg0KKiAkSF97MX06IFxnYW1tYV97aiBrfSBcbmVxIDAkIGbDvHIgbWluZGVzdGVucyBlaW5lIEtvbWJpbmF0aW9uICRqIGskDQoNCk9tbmlidXN0ZXN0IGbDvHIgZGVuIEZha3RvciBBIChVViAxKToNCg0KKiAkSF97MH06IFxhbHBoYV97an09MCQgZsO8ciBhbGxlICRqJA0KKiAkSF97MX06IFxhbHBoYV97an0gXG5lcSAwJCBmw7xyIG1pbmRlc3RlbnMgZWluICRqJA0KDQpPbW5pYnVzdGVzdCBmw7xyIGRlbiBGYWt0b3IgQiAoVVYgMik6DQoNCiogJEhfezB9OiBcYmV0YV97a309MCQgZsO8ciBhbGxlICRrJA0KKiAkSF97MX06IFxiZXRhX3trfSBcbmVxIDAkIGbDvHIgbWluZGVzdGVucyBlaW4gJGskDQoNCldpY2h0aWc6DQoNCiogRGllICRIX3swfSQgYmVkZXV0ZXQgbmljaHQgdW5iZWRpbmd0LCBkYXMgZGVyIEZha3RvciBBL0Iga2VpbmVuIEVpbmZsdXNzIGF1ZiBkaWUgQVYgaGF0Lg0KKiBEaWUgJEhfezF9JCBiZWRldXRldCBuaWNodCB1bmJlZGluZ3QsIGRhc3MgZGVyIEZha3RvciBBL0IgYXVmIGFsbGVuIEZha3RvcnN0dWZlbiBkZXMgRmFrdG9ycyBCL0EgZWluZW4gRWluZmx1c3MgYXVmIGRpZSBBViBoYXQuDQoNClF1YWRyYXRzdW1tZW46IA0KJCRcbGFyZ2UgUSBTX3tnIGUgc309USBTX3tBfStRIFNfe0J9K1EgU197QSB4IEJ9K1EgU197aSBuIG59JCQNCg0KVGVzdHN0YXRpc3Rpa2VuIGbDvHIgRmFrdG9yZW46IA0KDQoqICRUX3tBfT1cZnJhY3tNIFEgU197QX19e00gUSBTX3tpIG4gbn19JCBmb2xndCBlaW5lciAkRiQgLVZlcnRlaWx1bmcgbWl0ICR2X3sxfT1kIGZfe0F9JCB1bmQgJHZfezJ9PWQgZl97XHRleHQge2lubiB9fSAuJA0KKiAkVF97Qn09XGZyYWN7TSBRIFNfe0J9fXtNIFEgU197aSBuIG59fSQgZm9sZ3QgZWluZXIgJEYkIC1WZXJ0ZWlsdW5nIG1pdCAkdl97MX09ZCBmX3tCfSQgdW5kICR2X3syfT1kIGZfe1x0ZXh0IHtpbm4gfX0kLg0KKiAkVF97QSB4IEJ9PVxmcmFje00gUSBTX3tBIHggQn19e00gUSBTX3tpIG4gbn19JCBmb2xndCBlaW5lciAkRiQgLVZlcnRlaWx1bmcgbWl0ICR2X3sxfT1kIGZfe0EgeCBCfSQgdW5kICR2X3syfT1kIGZfe1x0ZXh0IHtpbm4gfX0gLiQNCg0KDQpgYGB7cn0NCnV2MSA9IGMoIkEiLCJBIiwiQSIsIkIiLCJCIiwiQiIsIkMiLCJDIiwiQyIpIA0KdXYyID0gYygiWCIsIlgiLCJZIiwiWSIsIlkiLCJYIiwiWCIsIlkiLCJZIikNCmF2ID0gYygxLDIsMyw0LDUsNiw3LDgsOSkNCg0KZGF0YSA9IGRhdGEuZnJhbWUodXYxLCB1djIsIGF2LCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkNCg0KDQojIE9tbmlidXN0ZXN0IG1pdCBSIEZ1bmt0aW9uIDEgKHVua29ycmlnaWVydCkNCmZpdCA8LSBhb3YoYXYgfiB1djEgKiB1djIsIGRhdGEpDQpzdW1tYXJ5KGZpdCkNCg0KIyBPbW5pYnVzdGVzdCBtaXQgUiBGdW5rdGlvbiAyIChrb3JyaWdpZXJ0IC0gd2VubiBWYXJpYW56Z2xlaWNoaGVpdCB2ZXJsZXR6dCksIG51ciBtaXQgdmllbGVuIEJlb2JhY2h0dW5nZW4NCiNvbmV3YXkudGVzdChhdn51djEqdXYyLCBkYXRhKSANCmBgYA0KDQoNCiMjIyMjIEVmZmVrdGdyw7bDn2UgeyNFZmZla3RncsO2w59lWndlaX0NCg0KR2VzYW10dmFyaWFueiBpbiB6d2VpZmFrdG9yaWVsbGVuIE1vZGVsbDoNCg0KJCRcbGFyZ2UgXHNpZ21hX3tcdGV4dCB7Z2VzIH19XnsyfT1cc2lnbWFfe0F9XnsyfStcc2lnbWFfe0J9XnsyfStcc2lnbWFfe0EgeCBCfV57Mn0rXHNpZ21hXnsyfSQkDQpFZmZla3RncsO2w59lbjoNCg0KKiBBbnRlaWwgZGVyIEdlc2FtdHZhcmlhbnogZGVyIEFWLCBkZXIgZHVyY2ggZGVuIEhhdXB0ZWZmZWt0IHZvbiBGYWt0b3IgQSBlcmtsw6RydCB3ZXJkZW4ga2FubjogDQokJFxsYXJnZSBcZXRhX3tBfV57Mn09XGZyYWN7XHNpZ21hX3tBfV57Mn19e1xzaWdtYV97ZyBlIHN9XnsyfX0kJA0KKiBBbnRlaWwgZGVyIEdlc2FtdHZhcmlhbnogZGVyIEFWLCBkZXIgZHVyY2ggZGVuIEhhdXB0ZWZmZWt0IHZvbiBGYWt0b3IgQiBlcmtsw6RydCB3ZXJkZW4ga2FubiA6IA0KJCRcbGFyZ2UgXGV0YV97Qn1eezJ9PVxmcmFje1xzaWdtYV97Qn1eezJ9fXtcc2lnbWFfe2cgZSBzfV57Mn19JCQNCiogQW50ZWlsIGRlciBHZXNhbXR2YXJpYW56IGRlciBBViwgZGVyIGR1cmNoIGRpZSBJbnRlcmFrdGlvbiBkZXIgYmVpZGVuIEZha3RvcmVuIGVya2zDpHJ0IHdlcmRlbiBrYW5uOiANCiQkXGxhcmdlIFxldGFfe0EgeCBCfV57Mn09XGZyYWN7XHNpZ21hX3tBIHggQn1eezJ9fXtcc2lnbWFfe2cgZSBzfV57Mn19JCQNCiogUGFydGllbGxlcyBFdGEtUXVhZHJhdDogQW50ZWlsIGFuIGRlciBhdWYgRmFrdG9yIEEgdW5kIGRlbiBGZWhsZXIgenVyw7xja2dlaGVuZGVuIFZhcmlhbnogZGVyIEFWLCBkZXIgZHVyY2ggZGVuIEhhdXB0ZWZmZWt0IHZvbiBGYWt0b3IgQSBlcmtsw6RydCB3ZXJkZW4ga2FubjoNCiQkXGxhcmdlIFxldGFfe1x0ZXh0IHtwYXIgfSwgQX1eezJ9PVxmcmFje1xzaWdtYV97QX1eezJ9fXtcc2lnbWFfe0F9XnsyfStcc2lnbWFeezJ9fSQkDQoNCmBgYHtyfQ0KdXYxID0gYygiQSIsIkEiLCJBIiwiQiIsIkIiLCJCIiwiQyIsIkMiLCJDIikgDQp1djIgPSBjKCJYIiwiWCIsIlkiLCJZIiwiWSIsIlgiLCJYIiwiWSIsIlkiKQ0KYXYgPSBjKDEsMiwzLDQsNSw2LDcsOCw5KQ0KDQpkYXRhID0gZGF0YS5mcmFtZSh1djEsIHV2MiwgYXYsIHN0cmluZ3NBc0ZhY3RvcnMgPSBUUlVFKQ0KZml0ID0gYW92KGF2IH4gdXYxICogdXYyLCBkYXRhKQ0KDQojRWZmZWt0DQpsaWJyYXJ5KERlc2NUb29scykNCkV0YVNxKGZpdCkNCg0KbGlicmFyeShNQkVTUykNCmNvbmYubGV2ZWwgPSAwLjk1DQoNCiMgRWZmZWt0IHV2MSBLb25maWRlbnppbnRlcnZhbGwNCmNpLnB2YWYoc3VtbWFyeShmaXQpW1sxXV1bWyJGIHZhbHVlIl1dW1sxXV0gLGRmLjEgPSBzdW1tYXJ5KGZpdClbWzFdXVtbIkRmIl1dW1sxXV0sIGRmLjIgPSBzdW1tYXJ5KGZpdClbWzFdXVtbIkRmIl1dW1s0XV0sIE49bnJvdyhkYXRhKSwgY29uZi5sZXZlbCA9IGNvbmYubGV2ZWwpDQoNCiMgRWZmZWt0IHV2MiBLb25maWRlbnppbnRlcnZhbGwNCmNpLnB2YWYoc3VtbWFyeShmaXQpW1sxXV1bWyJGIHZhbHVlIl1dW1syXV0gLGRmLjEgPSBzdW1tYXJ5KGZpdClbWzFdXVtbIkRmIl1dW1syXV0sIGRmLjIgPSBzdW1tYXJ5KGZpdClbWzFdXVtbIkRmIl1dW1s0XV0sIE49bnJvdyhkYXRhKSwgY29uZi5sZXZlbCA9IGNvbmYubGV2ZWwpDQoNCiMgRWZmZWt0IHV2MTp1djIgS29uZmlkZW56aW50ZXJ2YWxsDQpjaS5wdmFmKHN1bW1hcnkoZml0KVtbMV1dW1siRiB2YWx1ZSJdXVtbM11dICxkZi4xID0gc3VtbWFyeShmaXQpW1sxXV1bWyJEZiJdXVtbM11dLCBkZi4yID0gc3VtbWFyeShmaXQpW1sxXV1bWyJEZiJdXVtbNF1dLCBOPW5yb3coZGF0YSksIGNvbmYubGV2ZWwgPSBjb25mLmxldmVsKQ0KDQpgYGANCg0KIyMjIyMgVmFyaWFuemFuYWx5c2UgLSBLb250cmFzdG1hdHJpeCB7I1ZhcmlhbnphbmFseXNlWndlaX0NCg0KS29uZmlkZW56aW50ZXJ2YWxsLCBIeXBvdGhlc2VudGVzdDoNCg0KYGBge3J9DQpsaWJyYXJ5KG11bHRjb21wKQ0KbGlicmFyeShmb3JjYXRzKQ0KDQoNCnV2MSA9IGMoIkEiLCJBIiwiQSIsIkIiLCJCIiwiQiIsIkMiLCJDIiwiQyIpIA0KdXYyID0gYygiWCIsIlgiLCJZIiwiWSIsIlkiLCJYIiwiWCIsIlkiLCJZIikNCmF2ID0gYygxLDIsMyw0LDUsNiw3LDgsOSkNCg0KZGF0YSA9IGRhdGEuZnJhbWUodXYxLCB1djIsIGF2LCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkNCg0KZGF0YSR1djFfdXYyID0gZmN0X2Nyb3NzKGRhdGEkdXYxLCBkYXRhJHV2Miwgc2VwID0gJ18nKQ0KDQpmaXRfYW92ID0gYW92KGF2IH4gdXYxX3V2MiwgZGF0YSkNCg0KIyBIMA0KaHlwcyA9IG1jcCh1djFfdXYyID0gYygNCiAgIkFfWCAtIEJfWCA9PSAwIiwNCiAgIkJfWSAtIEFfWSA9PSAwIikNCikNCg0KZml0ID0gZ2xodChmaXRfYW92LCBoeXBzKQ0KY29uZmludChmaXQsIGxldmVsID0gMC45NSwgY2FscGhhID0gdW5pdmFyaWF0ZV9jYWxwaGEoKSkNCg0KIyAic2luZ2xlLXN0ZXAiOiBUdWtleSBNZXRob2RlLCB1bml2YXJpYXRlKCk6IEtlaW5lIEtvcnJla3R1ciwgImJvbmZlcnJvbmkiOiBCb25mZXJyb25pDQpzdW1tYXJ5KGZpdCwgdGVzdD11bml2YXJpYXRlKCkpDQoNCmBgYA0KDQoNCiMjIyMjIEludGVyYWt0aW9uc3Bsb3RzDQoNCmBgYHtyfQ0KdXYxID0gYygiQSIsIkEiLCJBIiwiQiIsIkIiLCJCIiwiQyIsIkMiLCJDIikgDQp1djIgPSBjKCJYIiwiWCIsIlkiLCJZIiwiWSIsIlgiLCJYIiwiWSIsIlkiKQ0KYXYgPSBjKDEsMiwzLDQsNSw2LDcsOCw5KQ0KICAgIA0KZGF0YSA9IGRhdGEuZnJhbWUodXYxLCB1djIsIGF2LCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkgICANCg0KaW50ZXJhY3Rpb24ucGxvdChkYXRhJHV2MSwgZGF0YSR1djIsIGRhdGEkYXYpDQppbnRlcmFjdGlvbi5wbG90KGRhdGEkdXYyLCBkYXRhJHV2MSwgZGF0YSRhdikNCmBgYA0KDQohW10oaHR0cHM6Ly9zaGlueS5hZHJpYW5zdGVmZmFuLmNvbS9hc3NldHMvc3RhdHMyL2ltYWdlcy9pbnRlcmFjdGlvbnMucG5nKQ0KDQojIyBSZWdyZXNzaW9uc2FuYWx5c2UgeyNSZWdyZXNzaW9uc2FuYWx5c2V9DQoNCiogVVY6IFByw6RkaWt0b3INCiogQVY6IEtyaXRlcml1bQ0KDQojIyMgRWluZmFjaGUgTGluZWFyZSBSZWdyZXNzaW9uIHsjRUxSfQ0KDQojIyMjIFBhcmFtZXRlcnNjaMOkdHp1bmcgeyNQYXJhbWV0ZXJzY2jDpHR6dW5nRUxSfQ0KDQokJFxsYXJnZSBZX3tpfT1cYWxwaGErXGJldGEgXGNkb3QgWF97aX0rXHZhcmVwc2lsb25fe2l9IFxxdWFkIFx0ZXh0IHsgd29iZWkgfSBcdmFyZXBzaWxvbl97aX0gXHN0YWNrcmVse1x0ZXh0IHsgaWlkIH19e1xzaW19IE5cbGVmdCgwLCBcc2lnbWFeezJ9XHJpZ2h0KSAkJA0KJCRcbGFyZ2UgRVxsZWZ0KFlfe2l9IFxtaWQgWF97aX09eF97aX1ccmlnaHQpPVxtdV97aX09XGFscGhhK1xiZXRhIFxjZG90IHhfe2l9ICQkDQoNCiQkXGxhcmdlIFx2YXJlcHNpbG9uX3tpfT1ZX3tpfS1FXGxlZnQoWV97aX0gXG1pZCBYX3tpfT14X3tpfVxyaWdodCkgJCQNCg0KDQpQYXJhbWV0ZXI6DQoNCiogJFxhbHBoYSQgSW50ZXJjZXB0LCBBY2hzZW5hYnNjaG5pdHQNCiogJFxiZXRhJCBTbG9wZSwgU3RlaWd1bmdzcGFyYW1ldGVyDQoqICRcbGFyZ2UgXHNpZ21hXnsyfSQgRmVobGVydmFyaWFueiAoUmVhbGlzYXRpb24gcyB2b24gJHNxcnQoXHNpZ21hXnsyfSkkIGlzdGUgZGVyICJTdGFuZGFyZHNjaMOkdHpmZWhsZXIiKQ0KDQpTY2jDpHR6ZnVua3Rpb25lbjoNCg0KJCRcbGFyZ2UgXGhhdHtcYmV0YX09Qj1cZnJhY3tcb3BlcmF0b3JuYW1le2Nvdn0oWCwgWSl9e1Nfe3h9XnsyfX0gJCQNCg0KJCRcbGFyZ2UgXGhhdHtcYWxwaGF9PUE9XGJhcntZfS1CIFxjZG90IFxiYXJ7WH0gJCQNCg0KJCRcbGFyZ2UgXGhhdHtcc2lnbWF9XnsyfT1TXnsyfT1cZnJhY3sxfXtuLTJ9IFxzdW1fe2k9MX1ee259XGxlZnQoWV97aX0tXGxlZnQoQStCIFxjZG90IFhfe2l9XHJpZ2h0KVxyaWdodCleezJ9ID0gXGZyYWN7MX17bi0yfSBcc3VtX3tpPTF9XntufSBFX3tpfV57Mn0gJCQNCg0KR2xlaWNodW5nIGRlciBHZXNjaMOkdHp0ZW4gUmVncmVzc2lvbnNnZXJhZGVuOg0KDQokJFxsYXJnZSBcd2lkZWhhdHtFfVxsZWZ0KFlfe2l9IFxtaWQgeF97aX1ccmlnaHQpPWErYiBcY2RvdCB4X3tpfSQkDQoNCmBgYHtyfQ0KZGF0YSA8LSBkYXRhLmZyYW1lKFVWID0gYygxLDIsNiw3LDEzLDE1LDIwLDMwKSwgQVYgPSBjKDAsMjMsODAsOTAsMTQwLDE4MiwyMjAsMzAwKSkNCg0KZml0IDwtIGxtKEFWIH4gVVYsIGRhdGEgPSBkYXRhKQ0KI3N1bW1hcnkoZml0KQ0KDQojIGENCmZpdCRjb2VmZmljaWVudHNbWyIoSW50ZXJjZXB0KSJdXQ0KDQojIGINCmZpdCRjb2VmZmljaWVudHNbWyJVViJdXQ0KDQojIEtvbmZpZGVuem9pbnRlcnZhbGwgZsO8ciBQYXJhbWV0ZXINCmNvbmZpbnQoZml0LCBsZXZlbD0wLjk1KQ0KDQojIHN0YW5kYXJkIGVycm9yDQpzdW1tYXJ5KGZpdCkkc2lnbWENCmBgYA0KWmVudHJpZXJ1bmcgZWluZXIgWlY6IA0KJCRcbGFyZ2UgWF97YywgaX09WF97aX0tXGJhcntYfSQkDQoNCmBgYHtyfQ0KZGF0YSA8LSBkYXRhLmZyYW1lKFVWID0gYygxLDIsNiw3LDEzLDE1LDIwLDMwKSwgQVYgPSBjKDAsMjMsODAsOTAsMTQwLDE4MiwyMjAsMzAwKSkNCg0KZGF0YSRVViA8LSBkYXRhJFVWIC0gbWVhbihkYXRhJFVWKQ0KIyBvZGVyDQpkYXRhJFVWIDwtIHNjYWxlKGRhdGEkVVYsIGNlbnRlciA9IFRSVUUsIHNjYWxlID0gRkFMU0UpDQoNCmRhdGENCg0KIyBWb3JoZXJzYWdlIGbDvHIgZHVyY2hzY2huaXR0bGljaGVuIFVWIFdlcnQNCmxtKEFWIH4gVVYsIGRhdGEgPSBkYXRhKSRjb2VmZmljaWVudHNbWyIoSW50ZXJjZXB0KSJdXQ0KYGBgDQoNCg0KVm9yaGVyc2FnZXdlcnQgU3ViamVrdCBpOiBTY2jDpHR6d2VydCBmw7xyICRcbXVfaSQ6ICRcaGF0e1l9X3tpfT1caGF0e1xtdX1fe2l9PUErQiBcY2RvdCBYX3tpfSQNCg0KYGBge3J9DQpkYXRhIDwtIGRhdGEuZnJhbWUoVVYgPSBjKDEsMiw2LDcsMTMsMTUsMjAsMzApLCBBViA9IGMoMCwyMyw4MCw5MCwxNDAsMTgyLDIyMCwzMDApKQ0KZml0IDwtIGxtKEFWIH4gVVYsIGRhdGEgPSBkYXRhKQ0KDQpuZXdfdXZfdmFsdWUgPSA1MA0KZGF0YV9wcmVkIDwtIGRhdGEuZnJhbWUoVVY9bmV3X3V2X3ZhbHVlKQ0KDQojIEFsdGVybmF0aXZlIEJlcmVjaG51bmcgZGVzIFZvcmhlcnNhZ2V3ZXJ0cyAidm9uIEhhbmQiDQojZml0JGNvZWZmaWNpZW50c1tbIihJbnRlcmNlcHQpIl1dK2ZpdCRjb2VmZmljaWVudHNbWyJVViJdXSpuZXdfdXZfdmFsdWUNCg0KIyBCZXJlY2hudW5nIGRlcyBWb3JoZXJzYWdld2VydHMgbWl0IEtvbmZpZGVuemludGVydmFsbA0KcHJlZGljdChmaXQsIGRhdGFfcHJlZCwgaW50ZXJ2YWw9InByZWRpY3Rpb24iLCBsZXZlbD0wLjk1KQ0KYGBgDQoNClJlc2lkdXVtIERpZmZlcmVueiB6d2lzY2hlbiBCZW9iYWNodHVuZyB1bmQgUmVhbGlzYXRpb246ICRFX3tpfT1ZX3tpfS1cd2lkZWhhdHtZfV97aX0kDQoNCg0KDQojIyMjIEh5cG90aGVzZW50ZXN0cyB7I0h5cG90aGVzZW50ZXN0RUxSfQ0KDQpIeXBvdGhlc2VudGVzdCBmw7xyICRcYmV0YSQ6DQpIeXBvdGhlc2VuOiANCiQkIFxsYXJnZQ0KXGJlZ2lue2FsaWduZWR9DQomSF97MH06IFxiZXRhPVxiZXRhX3swfT0wIFxcDQomSF97MX06IFxiZXRhIFxuZXEgXGJldGFfezB9ID0gMA0KXGVuZHthbGlnbmVkfQ0KJCQNCg0KVGVzdHN0YXRpc3RpazoNCg0KJCRcbGFyZ2UgVD1cZnJhY3tCLVxiZXRhX3swfX17XHNxcnR7XGhhdHtWfSBhIHIoQil9fSBcc2ltIHQobi0yKSQkDQoNCiQkXGxhcmdlIFxvcGVyYXRvcm5hbWV7VmFyfShCKT1cZnJhY3tcc2lnbWFeezJ9fXtcc3VtX3tpPTF9XntufVxsZWZ0KHhfe2l9LVxiYXJ7eH1ccmlnaHQpXnsyfX0kJA0KDQokJFxsYXJnZSBcaGF0e1Z9IFxvcGVyYXRvcm5hbWV7YXJ9KEIpPVxmcmFje1NeezJ9fXtcc3VtX3tpPTF9XntufVxsZWZ0KHhfe2l9LVxiYXJ7eH1ccmlnaHQpXnsyfX09XGZyYWN7XGZyYWN7MX17bi0yfSBcc3VtX3tpPTF9XntufSBFX3tpfV57Mn19e1xzdW1fe2k9MX1ee259XGxlZnQoeF97aX0tXGJhcnt4fVxyaWdodCleezJ9fSQkDQoNCg0KYGBge3J9DQpkYXRhIDwtIGRhdGEuZnJhbWUoVVYgPSBjKDEsMiw2LDcsMTMsMTUsMjAsMzApLCBBViA9IGMoMCwyMyw4MCw5MCwxNDAsMTgyLDIyMCwzMDApKQ0KZml0IDwtIGxtKEFWIH4gVVYsIGRhdGEgPSBkYXRhKQ0KI3N1bW1hcnkoZml0KQ0KDQojIHAgV2VydCBmw7xyIGINCnN1bW1hcnkoZml0KSRjb2VmZmljaWVudHNbLDRdW1siVVYiXV0NCg0KYGBgDQoNCg0KDQojIyMgTXVsdGlwbGUgUmVncmVzc2lvbiB7I01MUn0NCg0KIyMjIyBQYXJhbWV0ZXJzY2jDpHR6dW5nIHsjUGFyYW1ldGVyc2Now6R0enVuZ01MUn0NCg0KJCRcbGFyZ2UgWV97aX09XGFscGhhK1xiZXRhX3sxfSBcY2RvdCBYX3tpIDF9K1xiZXRhX3syfSBcY2RvdCBYX3tpIDJ9K1x2YXJlcHNpbG9uX3tpfSBccXVhZCBcdGV4dCB7IHdvYmVpIH0gXHZhcmVwc2lsb25fe2l9IFxzdGFja3JlbHtpIGkgZH17XHNpbX0gTlxsZWZ0KDAsIFxzaWdtYV57Mn1ccmlnaHQpJCQNCg0KJCRcbGFyZ2UgRVxsZWZ0KFlfe2l9IFxtaWQgWF97aSAxfT14X3tpIDF9LCBYX3tpIDJ9PXhfe2kgMn1ccmlnaHQpPVxtdV97aX09XGFscGhhK1xiZXRhX3sxfSBcY2RvdCB4X3tpIDF9K1xiZXRhX3syfSBcY2RvdCB4X3tpIDJ9JCQNCg0KDQp3b2JlaSAkcl97eCAxIHggMn1eezJ9JCBkaWUgcXVhZHJpZXJ0ZSBLb3JyZWxhdGlvbiB6d2lzY2hlbiBkZW4gYmVpZGVuIFByw6RkaWt0b3JlbiBpc3QuDQoNCktvbmZpZGVuemludGVydmFsbCBmw7xyIGJldGExIGJldGEyDQoNCiQkXGxhcmdlIFxsZWZ0W0Jfe2p9IFxwbSB0X3sxLVxmcmFje1xhbHBoYX17Mn19IFxjZG90IFx3aWRlaGF0e1MgRX1cbGVmdChCX3tqfVxyaWdodClccmlnaHRdJCQNCg0KbWl0IHQtVmVydGVpbHVuZyBtaXQgdiA9IG4gLSAzLg0KDQokJFxsYXJnZSBTXnsyfT1caGF0e1xzaWdtYX1eezJ9PVxmcmFjezF9e24tM30gXHN1bV97aT0xfV57bn1cbGVmdChZX3tpfS1cbGVmdChBK0JfezF9IFxjZG90IFhfe2kgMX0rQl97Mn0gXGNkb3QgWF97aSAyfVxyaWdodClccmlnaHQpXnsyfT1cZnJhY3sxfXtuLTN9IFxzdW1fe2k9MX1ee259IEVfe2l9XnsyfSQkDQoNCg0KYGBge3J9DQpkYXRhIDwtIGRhdGEuZnJhbWUoVVYxID0gYygxLDIsNiw3LDEzLDE1LDIwLDMwKSwgVVYyID0gYygxLDIsMyw0LDUsNiw3LDgpLCBBViA9IGMoMCwyMyw4MCw5MCwxNDAsMTgyLDIyMCwzMDApKQ0KDQpmaXQgPC0gbG0oQVYgfiBVVjEgKyBVVjIsIGRhdGEgPSBkYXRhKQ0KI3N1bW1hcnkoZml0KQ0KDQojIGENCmZpdCRjb2VmZmljaWVudHNbWyIoSW50ZXJjZXB0KSJdXQ0KDQojIGIxDQpmaXQkY29lZmZpY2llbnRzW1siVVYxIl1dDQoNCiMgYjINCmZpdCRjb2VmZmljaWVudHNbWyJVVjIiXV0NCg0KIyBLb25maWRlbnpvaW50ZXJ2YWxsIGbDvHIgUGFyYW1ldGVyDQpjb25maW50KGZpdCwgbGV2ZWw9MC45NSkNCg0KIyBzdGFuZGFyZCBlcnJvcg0Kc3VtbWFyeShmaXQpJHNpZ21hDQpgYGANCg0KJCQgXGxhcmdlDQpcYmVnaW57YWxpZ25lZH0NCiZTIEVcbGVmdChCX3sxfVxyaWdodCk9XHNxcnR7XG9wZXJhdG9ybmFtZXtWYXJ9XGxlZnQoQl97MX1ccmlnaHQpfT1cc3FydHtcZnJhY3sxfXsxLXJfe3ggMSB4IDJ9XnsyfX0gXGNkb3QgXGZyYWN7XHNpZ21hXnsyfX17XHN1bV97aT0xfV57bn1cbGVmdCh4X3tpIDF9LVxiYXJ7eH1fezF9XHJpZ2h0KV57Mn19fQ0KXGVuZHthbGlnbmVkfQ0KJCQNCg0KIyMjIyMgVm9yaGVyc2FnZQ0KDQokJFxsYXJnZSANClxoYXR7eX1fe2l9PWErYl97MX0gXGNkb3QgeF97aSAxfStiX3syfSBcY2RvdCB4X3tpIDJ9JCQNCg0KDQojIyMjIEh5cG90aGVzZW50ZXN0cyB7I0h5cG90aGVzZW50ZXN0TUxSfQ0KDQojIyMjIyBFaW56ZWxuZSBQcsOkZGlrdG9yZW4NCg0KKiBCZWkgZWluZXIgTUxSIG1pdCB6d2VpIFByw6RkaWt0b3JlbiBrw7ZubmVuIGZvbGdlbmRlbiB6d2VpIEh5cG90aGVzZW4gw7xiZXJwcsO8ZnQgd2VyZGVuOg0KDQokJCBcbGFyZ2UNClxiZWdpbnthbGlnbmVkfQ0KJkhfezB9OiBcYmV0YV97MX09MCBcXA0KJkhfezF9OiBcYmV0YV97MX0gXG5lcSAwIFxcXFwNCiZIX3swfTogXGJldGFfezJ9PTAgXFwNCiZIX3sxfTogXGJldGFfezJ9IFxuZXEgMA0KXGVuZHthbGlnbmVkfQ0KJCQNCg0KVGVzdHN0YXRpc3RpazoNCiQkIFxsYXJnZSBUX3sxfT1cZnJhY3tCX3sxfX17XHNxcnR7XGhhdHtWfSBhIHJcbGVmdChCX3sxfVxyaWdodCl9fSBcc2ltIHQobi0zKSQkDQoNCmBgYHtyfQ0KZGF0YSA8LSBkYXRhLmZyYW1lKFVWMSA9IGMoMSwyLDYsNywxMywxNSwyMCwzMCksIFVWMiA9IGMoMSwyLDMsNCw1LDYsNyw4KSwgQVYgPSBjKDAsMjMsODAsOTAsMTQwLDE4MiwyMjAsMzAwKSkNCmZpdCA8LSBsbShBViB+IFVWMSArIFVWMiwgZGF0YSA9IGRhdGEpDQpzdW1tYXJ5KGZpdCkNCg0KYGBgDQoNCg0KIyMjIyMgT21uaWJ1c3Rlc3QNCg0KSHlwb3RoZXNlOg0KDQokJFxsYXJnZQ0KXGJlZ2lue2FsaWduZWR9DQomSF97MH06IFxiZXRhX3sxfT1cYmV0YV97Mn09MFxcDQomSF97MX06IFxiZXRhX3tqfSBcbmVxIDAgJlx0ZXh0IHsgZsO8ciBtaW5kZXN0ZW5zIGVpbiB9IGogXHRleHQgeyBtaXQgfSBqPTEsMg0KXGVuZHthbGlnbmVkfQ0KJCQNCg0KVGVzdHN0YXRpc3RpazoNCg0KJCRcbGFyZ2UNCkY9XGZyYWN7XGZyYWN7MX17Mn0gXHN1bV97aT0xfV57bn1cbGVmdChcaGF0e1l9X3tpfS1cYmFye1l9XHJpZ2h0KV57Mn19e1NeezJ9fQ0KJCQNCg0KDQoNCiMjIyMgS29sbGluZWFyaXTDpHQgeyNLb2xsaW5lYXJpdMOkdH0NCg0KKiBNYW4gc3ByaWNodCB2b24gS29sbGluZWFyaXTDpHQsIHdlbm4gZWluZXIgb2RlciBtZWhyZXJlIGRlciBQcsOkZGlrdG9yZW4gc3RhcmsgbWl0IGRlbiBqZXdlaWxzIGFuZGVyZW4gUHLDpGRpa3RvcmVuIHp1c2FtbWVuaMOkbmdlbg0KDQoqIEVudHN0ZWhlbmRlIFByb2JsZW1lOg0KICAgICogR3LDtsOfZXJlIEtvbmZpZGVuemludGVydmFsbGUNCiAgICAqIEdlcmluZ2VyZSBQb3dlciBkZXIgSHlwb3RoZXNlbnRlc3RzDQogICAgDQoqIE5pY2h0IGJlZWluZmx1c3N0Og0KICAgICogS29uZmlkZW56aW50ZXJ2YWxsZSBmw7xyICRccmhvXnsyfSQNCiAgICAqIERlciBPbW5pYnVzdGVzdCBpbSBSYWhtZW4gZGVyIE1MUg0KICAgIA0KDQokJFxsYXJnZSBTRVxsZWZ0KEJfe2p9XHJpZ2h0KT1cc3FydHtcb3BlcmF0b3JuYW1le1Zhcn1cbGVmdChCX3tqfVxyaWdodCl9PVxzcXJ0e1xmcmFjezF9ezEtcl97an1eezJ9fSBcY2RvdCBcZnJhY3tcc2lnbWFeezJ9fXtcc3VtX3tpPTF9XntufVxsZWZ0KHhfe2kgan0tXGJhcnt4fV97an1ccmlnaHQpXnsyfX19JCQNCg0KSGllcmJlaSBpc3QgJHJeezJ9X3tqfSQgZGVyIERldGVybWluYXRpb25za29lZmZpemllbnQgZWluZXMgUmVncmVzc2lvbnNtb2RlbGxzLCBpbiBkYXMgZGVyDQpQcsOkZGlrdG9yIPCdkZcgYWxzIEtyaXRlcml1bSB1bmQgYWxsZSBhbmRlcmVuIFByw6RkaWt0b3JlbiBhbHMgUHLDpGRpa3RvcmVuIGF1Zmdlbm9tbWVuDQp3ZXJkZW4uDQoNCg0KIyMjIyMgVmFyaWFuemluZmxhdGlvbnNmYWt0b3INCg0KDQoqIEtlbm53ZXJ0IGbDvHIgS29sbGluZWFyaXTDpHQNCg0KKiBaZWlndDogTmVnYXRpdmUgQXVzd2lya3VuZ2VuIGRlciBLb2xsaW5lYXJpdMOkdCBrw7ZubmVuIG1pdCBncm/Dn2VuIFN0aWNocHJvYmVuIGF1ZmdlaG9iZW4gd2VyZGVuDQoNCg0KJCRcbGFyZ2UgVklGX3tqfT1cZnJhY3sxfXsxLXJfe2p9XnsyfX0kJA0KDQpgYGB7cn0NCmRhdGEgPC0gZGF0YS5mcmFtZShVVjEgPSBjKDEsMiw2LDcsMTMsMTUsMjAsMzApLCBVVjIgPSBjKDEsMiwzLDQsNSw2LDcsOCksIEFWID0gYygwLDIzLDgwLDkwLDE0MCwxODIsMjIwLDMwMCkpDQpmaXQgPC0gbG0oQVYgfiBVVjEgKyBVVjIsIGRhdGEgPSBkYXRhKQ0KDQojIEJlYWNodGU6IEJlaSAyIFZhcmlhYmxlbiBzaW5kIGJlaWRlIFZJRnMgaWRlbnRpc2NoDQoNCiMgQmVyZWNobnVuZyB2b24gUHVua3QgdW5kIEtJIG1pdCBSDQpsaWJyYXJ5KGNhcikNCnZpZihmaXQpDQoNCmxpYnJhcnkoTUJFU1MpDQpjaS5SMihSMiA9IHN1bW1hcnkoZml0KSRyLnNxdWFyZWQsIHA9bmNvbChkYXRhKS0xLCBjb25mLmxldmVsID0gMC45NSwgTj1ucm93KGRhdGEpKQ0KDQoNCiMgQmVyZWNobnVuZyB2b24gUHVua3RzY2jDpHR6ZXIgInBlciBIYW5kIg0KZml0X3V2MSA8LSBsbShVVjEgfiBVVjIsIGRhdGEgPSBkYXRhKQ0KMS8oMS1zdW1tYXJ5KGZpdF91djEpJHIuc3F1YXJlZCkNCg0KDQpgYGANCg0KDQoNCiMjIyBFZmZla3RncsO2w59lbiB7I0VmZmVrdGdyw7bDn2VuTFJ9DQoNCg0KIyMjIyMgRWZmZWt0Z3LDtsOfZSAkXHJob157Mn0kDQoNCg0KKiBTdMOkcmtlIGRlcyBadXNhbW1lbmhhbmdzLCBFaW5oZWl0c3VuYWJow6RuZ2lnDQoNCg0KU2Now6R0emZ1bmt0aW9uOg0KDQokJFxsYXJnZQ0KXGhhdHtccmhvfV57Mn09Ul57Mn09XGZyYWN7XGhhdHtcc2lnbWF9X3tcbXVfe2l9fV57Mn19e1xoYXR7XHNpZ21hfV97ZyBlIHN9XnsyfX09XGZyYWN7XGZyYWN7MX17bn0gXHN1bV97aT0xfV57bn1cbGVmdChcaGF0e1l9X3tpfS1cYmFye1l9XHJpZ2h0KV57Mn19e1xmcmFjezF9e259IFxzdW1fe2k9MX1ee259XGxlZnQoWV97aX0tXGJhcntZfVxyaWdodCleezJ9fT1cZnJhY3tcc3VtX3tpPTF9XntufVxsZWZ0KFxoYXR7WX1fe2l9LVxiYXJ7WX1ccmlnaHQpXnsyfX17XHN1bV97aT0xfV57bn1cbGVmdChZX3tpfS1cYmFye1l9XHJpZ2h0KV57Mn19JCQNCg0KDQpFUkwgKGVpbmUgVVYpDQoNCg0KKiBBbnRlaWwgZGVyIEdlc2FtdHZhcmlhbnogZGVyIEFWLCBkZXIgZHVyY2ggZGllIFVWIGVya2zDpHJ0IHdlcmRlbiBrYW5uDQoNCg0KYGBge3J9DQpkYXRhIDwtIGRhdGEuZnJhbWUoVVYgPSBjKDEsMiw2LDcsMTMsMTUsMjAsMzApLCBBViA9IGMoMCwyMyw4MCw5MCwxNDAsMTgyLDIyMCwzMDApKQ0KZml0IDwtIGxtKEFWIH4gVVYsIGRhdGEgPSBkYXRhKQ0KDQojIFB1bmt0c2Now6R0enVuZyByaG8yDQpyaG8yIDwtIHN1bW1hcnkoZml0KSRyLnNxdWFyZWQNCnJobzINCg0KIyBLb25maWRlbnppbnRlcnZhbGwgcmhvMg0KbGlicmFyeShNQkVTUykNCmNpLlIyKHJobzIsIHAgPSAxLCBOID0gbnJvdyhkYXRhKSwgY29uZi5sZXZlbD0wLjk1KQ0KYGBgDQoNCg0KTUxSIChtZWhyZXJlIFVWcykNCg0KKiBHZXNhbXRlIEVmZmVrdHN0w6Rya2UgYWxsZXIgUHLDpGRpa3RvcmVuIGltIE1MUiBNb2RlbGwNCiogQW50ZWlsIGRlciBHZXNhbXR2YXJpYW56IGRlciBBViwgZGllIGR1cmNoIGFsbGUgVVZzIGdlbWVpbnNhbSBlcmtsw6RydCB3ZXJkZW4ga2Fubg0KDQoNCmBgYHtyfQ0KZGF0YSA8LSBkYXRhLmZyYW1lKFVWMSA9IGMoMSwyLDYsNywxMywxNSwyMCwzMCksIFVWMiA9IGMoMSwyLDMsNCw1LDYsNyw4KSwgQVYgPSBjKDAsMjMsODAsOTAsMTQwLDE4MiwyMjAsMzAwKSkNCmZpdCA8LSBsbShBViB+IFVWMSArIFVWMiwgZGF0YSA9IGRhdGEpDQoNCiMgUHVua3RzY2jDpHR6dW5nIHJobzINCnJobzIgPC0gc3VtbWFyeShmaXQpJHIuc3F1YXJlZA0KcmhvMg0KDQojIEtvbmZpZGVuemludGVydmFsbCByaG8yDQpsaWJyYXJ5KE1CRVNTKQ0KY2kuUjIocmhvMiwgcCA9IDIsIE4gPSBucm93KGRhdGEpLCBjb25mLmxldmVsPTAuOTUpDQpgYGANCg0KDQojIyMjIyBFZmZla3RncsO2w59lICRccmhvXnsyfV97an0kIGbDvHIgTUxSDQoNCg0KKiBFZmZla3RzdMOkcmtlIGVpbmVzIGVpbnplbG5lbiBQcsOkZGlrdG9ycyBpbSBNTFIgTW9kZWxsDQoNCiogQW50ZWlsIGRlciBHZXNhbXR2YXJpYW56IGRlciBBViwgZGVyIMO8YmVyIGRpZSBhbmRlcmVuIFByw6RkaWt0b3JlbiBoaW5hdXMgbnVyIGR1cmNoIFVWIGogZXJrbMOkcnQgd2VyZGVuIGthbm4NCg0KDQokJFxsYXJnZQ0KXHJob197an1eezJ9PVxyaG9eezJ9LVxyaG9fey1qfV57Mn0kJA0KDQp3b2JlaSAkXHJob197LWp9XnsyfSQgZGVtamVuaWdlbiAkXHJob157Mn0kIGVudHNwcmljaHQsIGRhcyBtYW4gZXJow6RsdCwgd2VubiBtYW4gZGVuIFByw6RkaWt0b3IgJGokIGF1cyBkZW0gTUxSLU1vZGVsbCBlbnRmZXJudC4NCg0KDQpgYGB7cn0NCmRhdGEgPC0gZGF0YS5mcmFtZShVVjEgPSBjKDEsMiw2LDcsMTMsMTUsMjAsMzApLCBVVjIgPSBjKDEsMiwzLDQsNSw2LDcsOCksIEFWID0gYygwLDIzLDgwLDkwLDE0MCwxODIsMjIwLDMwMCkpDQoNCiMgUHVua3RzY2jDpHR6dW5nIHJobzINCmZpdCA8LSBsbShBViB+IFVWMSArIFVWMiwgZGF0YSA9IGRhdGEpDQpyaG8yIDwtIHN1bW1hcnkoZml0KSRyLnNxdWFyZWQNCg0KIyBQdW5rdHNjaMOkdHp1bmcgcmhvMl8xDQpmaXQyIDwtIGxtKEFWIH4gVVYyLCBkYXRhID0gZGF0YSkNCnN1bW1hcnkoZml0KSRyLnNxdWFyZWQgLSBzdW1tYXJ5KGZpdDIpJHIuc3F1YXJlZA0KDQojIFB1bmt0c2Now6R0enVuZyByaG8yXzINCmZpdDEgPC0gbG0oQVYgfiBVVjEsIGRhdGEgPSBkYXRhKQ0Kc3VtbWFyeShmaXQpJHIuc3F1YXJlZCAtIHN1bW1hcnkoZml0MSkkci5zcXVhcmVkDQoNCmBgYA0KDQojIyMjIyBFZmZla3RncsO2w59lICRcYmV0YV97en0kIGbDvHIgRUxSDQoNCg0KKiBTdMOkcmtlIGRlcyBadXNhbW1lbmhhbmdzLCBSaWNodHVuZyBkZXMgWnVzYW1tZW5oYW5ncywgRWluaGVpdHN1bmFiaMOkbmdpZw0KKiBpbSBSYWhtZW4gZGVyIEVMUiBpZGVudGlzY2ggbWl0IGRlciBQZWFyc29uLUtvcnJlbGF0aW9uICh6d2lzY2hlbiBBViB1bmQgVVYpIGluIGRlciBTdGljaHByb2JlIA0KKiAibm9ybWFsZXMiICRcYmV0YSQgZmFsbHMgQVYgdW5kIFVWIHotc3RhbmRhcmRpc2llcnQgd2VyZGVuDQoNCg0KJCRcbGFyZ2UNClxyaG9eezJ9PVxiZXRhX3t6fV57Mn0NCiQkDQoNCg0KYGBge3J9DQpkYXRhIDwtIGRhdGEuZnJhbWUoVVYgPSBjKDEsMiw2LDcsMTMsMTUsMjAsMzApLCBBViA9IGMoMCwyMyw4MCw5MCwxNDAsMTgyLDIyMCwzMDApKQ0KZml0IDwtIGxtKHNjYWxlKEFWKSB+IHNjYWxlKFVWKSwgZGF0YSA9IGRhdGEpDQoNCiMgUHVua3RzY2jDpHR6dW5nIGJldGFfeg0KZml0JGNvZWZmaWNpZW50c1tbInNjYWxlKFVWKSJdXQ0KDQojIEtvbmZpZGVuemludGVydmFsbCBiZXRhX3oNCmNvbmZpbnQoZml0LCBsZXZlbD0wLjk1KQ0KYGBgDQoNCg0KIyMjIyBFZmZla3RncsO2w59lICRcYmV0YV97el97an19JCBmw7xyIE1MUg0KDQoNCiogRWZmZWt0c3TDpHJrZSBlaW5lcyBlaW56ZWxuZW4gUHLDpGRpa3RvcnMgaW0gTUxSIE1vZGVsbA0KKiBTdMOkcmtlIGRlcyBadXNhbW1lbmhhbmdzLCBSaWNodHVuZyBkZXMgWnVzYW1tZW5oYW5ncywgRWluaGVpdHN1bmFiaMOkbmdpZw0KKiBHaWJ0IGFuLCB3aWUgc3RhcmsgZGllIGpld2VpbGlnZSBVViBiZWkgS29uc3RhbnRoYWx0dW5nIGFsbGVyIGFuZGVyZW4gVVZzIG1pdCBkZXIgQVYgenVzYW1tZW5ow6RuZ3QuDQoqIE5pY2h0ICghKSBpZGVudGlzY2ggbWl0IFBlYXJzb24gS29ycmVsYXRpb24NCg0KDQoNCg0KDQpgYGB7cn0NCmRhdGEgPC0gZGF0YS5mcmFtZShVVjEgPSBjKDEsMiw2LDcsMTMsMTUsMjAsMzApLCBVVjIgPSBjKDEsMiwzLDQsNSw2LDcsOCksIEFWID0gYygwLDIzLDgwLDkwLDE0MCwxODIsMjIwLDMwMCkpDQpmaXQgPC0gbG0oQVYgfiBVVjEgKyBVVjIsIGRhdGEgPSBkYXRhLmZyYW1lKHNjYWxlKGRhdGEpKSkNCg0KIyBQdW5rdHNjaMOkdHp1bmcgYmV0YV96XzENCmZpdCRjb2VmZmljaWVudHNbWyJVVjEiXV0NCg0KIyBQdW5rdHNjaMOkdHp1bmcgYmV0YV96XzINCmZpdCRjb2VmZmljaWVudHNbWyJVVjIiXV0NCg0KIyBLb25maWRlbnppbnRlcnZhbGwgYmV0YV96DQpjb25maW50KGZpdCwgbGV2ZWw9MC45NSkNCmBgYA0KDQoNCiMjIyBTdGljaHByb2JlbnBsYW51bmcgeyNTdGljaHByb2JlbnBsYW51bmdMUn0NCg0KKiAkbiA9IHYgKyBrICsgMSQgIHdvYmVpIGsgZGllIEFuemFobCBkZXIgUHLDpGRpa3RvcmVuIGlzdA0KDQojIyMjIyAqKkVMUiAtIEVpbmUgVVYqKg0KDQoNCkh5cG90aGVzZToNCg0KDQokJFxsYXJnZSBcYmVnaW57YWxpZ25lZH0NCiZIX3swfTogXGJldGE9MCBcXA0KJkhfezF9OiBcYmV0YSBcbmVxIDANClxlbmR7YWxpZ25lZH0kJA0KDQpCZW7DtnRpZ3QgYWx0ZXJuYXRpdmUgRWZmZWt0Z3LDtsOfZToNCg0KJCRcbGFyZ2UgZl57Mn09XGZyYWN7XGJldGFfe3p9XnsyfX17MS1cYmV0YV97en1eezJ9fT1cZnJhY3tccmhvXnsyfX17MS1ccmhvXnsyfX0kJA0KDQpgYGB7cn0NCnJobzIgPC0gMC4xDQpmMiA8LSByaG8yLygxLXJobzIpDQoNCmxpYnJhcnkocHdyKQ0KcHdyX2FuYWx5c2lzIDwtIHB3ci5mMi50ZXN0KHU9MSwgZjIgPSBmMiwgc2lnLmxldmVsID0gMC4wMDUsIHBvd2VyID0gMC44KQ0KcHdyX2FuYWx5c2lzDQoNCiMgQW56YWhsIGJlbsO2dGlndGUgVmVyc3VjaHNwZXJzb25lbg0KY2VpbGluZyhwd3JfYW5hbHlzaXMkdiArIDIpDQoNCmBgYA0KDQoNCiMjIyMjICoqTUxSIC0gbWVocmVyZSBVVnMqKg0KDQoNCioqRWluemVsbmUgUGFyYW1ldGVyKioNCg0KDQokJFxsYXJnZQ0KXGJlZ2lue2FsaWduZWR9DQomSF97MH06IFxiZXRhX3tqfT0wIFxcDQomSF97MX06IFxiZXRhX3tqfSBcbmVxIDANClxlbmR7YWxpZ25lZH0kJA0KDQpCZW7DtnRpZ3QgYWx0ZXJuYXRpdmUgRWZmZWt0Z3LDtsOfZToNCg0KJCRcbGFyZ2UgZl97an1eezJ9PVxmcmFje1xyaG9fe2p9XnsyfX17MS1ccmhvXnsyfX0kJA0KIA0KDQpgYGB7cn0NCnJobzJfMSA8LSAwLjA1DQpyaG8yIDwtIDAuMQ0KbnVtX29mX3ByZWRpY3RvcnMgPSAyDQoNCmYyXzEgPC0gcmhvMl8xLygxLXJobzIpDQoNCmxpYnJhcnkocHdyKQ0KcHdyX2FuYWx5c2VzIDwtIHB3ci5mMi50ZXN0KHU9MSwgZjIgPSBmMl8xLCBzaWcubGV2ZWwgPSAwLjAwNSwgcG93ZXIgPSAwLjgpDQpwd3JfYW5hbHlzZXMNCg0KY2VpbGluZyhwd3JfYW5hbHlzZXMkdiArIG51bV9vZl9wcmVkaWN0b3JzICsgMSkNCmBgYA0KDQoqKk9tbmlidXN0ZXN0KioNCg0KDQokJFxsYXJnZQ0KXGJlZ2lue2dhdGhlcmVkfQ0KSF97MH06IFxiZXRhX3tqfT0wIFx0ZXh0IHsgZsO8ciBhbGxlIH0gaiBcXA0KSF97MX06IFxiZXRhX3tqfSBcbmVxIDAgXHRleHQgeyBmw7xyIG1pbmRlc3RlbnMgZWluIH0gag0KXGVuZHtnYXRoZXJlZH0kJA0KDQokJFxsYXJnZSBmXnsyfT1cZnJhY3tccmhvXnsyfX17MS1ccmhvXnsyfX0kJA0KDQoNCmBgYHtyfQ0KcmhvMiA8LSAwLjENCm51bV9vZl9wcmVkaWN0b3JzID0gMg0KDQpmMiA8LSByaG8yLygxLXJobzIpDQoNCmxpYnJhcnkocHdyKQ0KcHdyX2FuYWx5c2VzIDwtIHB3ci5mMi50ZXN0KHU9MiwgZjIgPSBmMiwgc2lnLmxldmVsID0gMC4wMDUsIHBvd2VyID0gMC44KQ0KcHdyX2FuYWx5c2VzDQoNCmNlaWxpbmcocHdyX2FuYWx5c2VzJHYgKyBudW1fb2ZfcHJlZGljdG9ycyArIDEpDQpgYGANCg0KDQojIyMgUmVncmVzc2lvbnNkaWFnbm9zdGlrIHsjUmVncmVzc2lvbnNkaWFnbm9zdGlrfQ0KDQrDnGJlcnByw7xmdW5nIGRlciBNb2RlbGxhbm5haG1lbiArIEF1w59yZWnDn2VyYW5hbHlzZQ0KDQpNb2RlbGxhbm5haG1lbjogDQoNCjEuIERpZSBVViB1bmQgQVYgaMOkbmdlbiBsaW5lYXIgenVzYW1tZW4NCg0KMi4gQWxsZSBGZWhsZXIgJFxsYXJnZSBcZXBzaWxvbl97aX0kIHNpbmQgdW5hYmjDpG5naWcgdm9uZWluYW5kZXIgdW5kIGZvbGdlbiBlaW5lciBOb3JtYWx2ZXJ0ZWlsdW5nIG1pdCBFcndhcnR1Z25zd2VydCAwIHVuZCBrb25zdGFudGVyIFZhcmlhbnogJFxsYXJnZSBcc2lnbWFeezJ9JA0KDQooQWNodHVuZzogUmVzaWR1ZW4gbcO8c3NlbiBzdGFuZGFyZGlzaWVydCB3ZXJkZW4pDQoNCiMjIyMgTGluZWFyaXTDpHQNCg0KRWluZSBzdGV0aWdlIFVWDQpgYGB7cn0NCmRhdGEgPC0gZGF0YS5mcmFtZShVViA9IGMoMSwyLDYsNywxMywxNSwyMCwzMCksIEFWID0gYygwLDIzLDgwLDkwLDE0MCwxODIsMjIwLDMwMCkpDQpmaXQgPC0gbG0oQVYgfiBVViwgZGF0YSA9IGRhdGEpDQoNCnBsb3QoQVZ+VVYsIGRhdGE9ZGF0YSkNCmFibGluZShmaXQpDQoNCmBgYA0KDQpad2VpIHN0ZXRpZ2UgVVZzDQpgYGB7cn0NCmRhdGEgPC0gZGF0YS5mcmFtZShVVjEgPSBjKDEsMiw2LDcsMTMsMTUsMjAsMzApLCBVVjIgPSBjKDEsMiwzLDQsNSw2LDcsOCksIEFWID0gYygwLDIzLDgwLDkwLDE0MCwxODIsMjIwLDMwMCkpDQpmaXQgPC0gbG0oQVYgfiBVVjEgKyBVVjIsIGRhdGEgPSBkYXRhKQ0KDQojIENvbXBvbmVudCArIFJlc2lkdWFsIFBsb3RzDQpsaWJyYXJ5KGNhcikNCmNyUGxvdHMoZml0KQ0KDQpgYGANCg0KIyMjIyBOb3JtYWx2ZXJ0ZWlsdW5nDQoNCmBgYHtyfQ0KZGF0YSA8LSBkYXRhLmZyYW1lKFVWID0gYygxLDIsNiw3LDEzLDE1LDIwLDMwKSwgQVYgPSBjKDAsMjMsODAsOTAsMTQwLDE4MiwyMjAsMzAwKSkNCmZpdCA8LSBsbShBViB+IFVWLCBkYXRhID0gZGF0YSkNCg0KaGlzdChyc3RhbmRhcmQoZml0KSkNCg0KYGBgDQoNCiMjIyMgSG9tb3NrZWRhc3Rpeml0w6R0DQoNClZhcmlhbnogaW4gWSBSaWNodHVuZyBzb2xsIGbDvHIgZ2VzYW10ZW4gV2VydGViZXJlaWNoIGRlciBVViDDpGhubGljaCBzZWluIA0KDQpgYGB7cn0NCmRhdGEgPC0gZGF0YS5mcmFtZShVViA9IGMoMSwyLDYsNywxMywxNSwyMCwzMCksIEFWID0gYygwLDIzLDgwLDkwLDE0MCwxODIsMjIwLDMwMCkpDQpmaXQgPC0gbG0oQVYgfiBVViwgZGF0YSA9IGRhdGEpDQoNCnBsb3QoZml0JGZpdHRlZC52YWx1ZXMsIHJzdGFuZGFyZChmaXQpKQ0KDQpgYGANCg0KIyMjIyBBdXNyZWnDn2VyDQoNCiogSGViZWx3ZXJ0IChMZXZlcmFnZSk6IFVuZ2V3w7ZobmxpY2ggZ3Jvw59lIEFid2VpY2h1bmcgZGVzICoqVVYqKi1XZXJ0cyB2b20gRHVyY2hzY2huaXR0DQoNCiogRGlza3JlcGFuendlcnQgKERpc2NyZXBhbmN5KTogVW5nZXfDtmhubGljaCBncm/Dn2UgQWJ3ZWljaHVuZyBkZXMgKipBVioqLVdlcnRzIHZvbSBEdXJjaHNjaG5pdHQNCg0KKiBFaW5mbHVzc3dlcnQgKEluZmx1ZW5jZSk6IEtvbWJpbmF0aW9uIGF1cyBIZWJlbC0gdW5kIERpc2tyZXBhbnp3ZXJ0ICoqISBWb3IgYWxsZW0gcHJvYmxlbWF0aXNjaCAhKioNCg0KQ29vaydzIERpc3RhejogV2llIHN0YXJrIHfDvHJkZW4gc2ljaCBhbGxlIFZvcmhlcnNhZ2V3ZXJ0ZSDDpG5kZXJuLCB3ZW5uIGRpZXNlIEJlb2JhY2h0dW5nIG5vaWNodCBtaXQgaW5zIE1vZGVsbCBlaW5mbGllw590IChFbXBmZWhsdW5nOiBXZXJ0ZSBtaXQgZGlzdGFuY2UgPiAkXGZyYWN7NH17bn0kIGF1c3NjaGxpZcOfZW4pDQoNCmBgYHtyfQ0KZGF0YSA8LSBkYXRhLmZyYW1lKFVWID0gYygxLDIsNiw3LDEzLDE1LDIwLDMwKSwgQVYgPSBjKDAsMjMsODAsOTAsMTQwLDE4MiwyMjAsMzAwKSkNCmZpdCA8LSBsbShBViB+IFVWLCBkYXRhID0gZGF0YSkNCg0KY3V0b2ZmIDwtIDQvbnJvdyhkYXRhKQ0KcGxvdChjb29rcy5kaXN0YW5jZShmaXQpKQ0KYWJsaW5lKGg9Y3V0b2ZmKQ0KDQp3aGljaChjb29rcy5kaXN0YW5jZShmaXQpID4gY3V0b2ZmKQ0KDQpgYGANCg0KIyMjIERpc2tyZXRlIFByw6RkaWt0b3JlbiB7I0Rpc2tyZXRlUHLDpGRpa3RvcmVufQ0KDQojIyMjIER1bW15LUtvZGllcnVuZw0KDQokJFxsYXJnZSBEX3tpfT1cbGVmdFx7XGJlZ2lue2FycmF5fXtsfQ0KMSwgXHRleHQgeyBmYWxscyBQZXJzb24gaSBuaWNodCB6dXIgUmVmZXJlbnprYXRlZ29yaWUgZ2Vow7ZydCB9IFxcDQowLCBcdGV4dCB7IGZhbGxzIFBlcnNvbiBpIHp1ciBSZWZlcmVuemthdGVnb3JpZSBnZWjDtnJ0IH0NClxlbmR7YXJyYXl9XHJpZ2h0LiQkDQoNCk1vZGVsbGdsZWljaHVuZzoNCg0KJCRcbGFyZ2UgWV97aX09XGFscGhhK1xiZXRhIFxjZG90IERfe2l9K1x2YXJlcHNpbG9uX3tpfSBccXVhZCBcdGV4dCB7IG1pdCB9IFx2YXJlcHNpbG9uX3tpfSBcc3RhY2tyZWx7aSBpIGR9e1xzaW19IE5cbGVmdCgwLCBcc2lnbWFeezJ9XHJpZ2h0KSQkDQoNCiogUmVmZXJlbnprYXRlZ29yaWU6DQoNCiQkXGxhcmdlIEVcbGVmdChZX3tpfVxyaWdodCk9RVxsZWZ0KFxhbHBoYStcdmFyZXBzaWxvbl97aX1ccmlnaHQpPVxhbHBoYSswPVxhbHBoYSQkDQoNCiogYW5kZXJlIEthdGVnb3JpZQ0KDQokJFxsYXJnZSBFXGxlZnQoWV97aX1ccmlnaHQpPUVcbGVmdChcYWxwaGErXGJldGErXHZhcmVwc2lsb25fe2l9XHJpZ2h0KT1cYWxwaGErXGJldGErMD1cYWxwaGErXGJldGEkJA0KDQoNCiMjIyMgTWVocmVyZSBTdHVmZW4NCg0KJCRcbGFyZ2UgRF97aiBpfT1cbGVmdFx7XGJlZ2lue2FycmF5fXtsfQ0KMSwgXHRleHQgeyBmYWxscyBQZXJzb24gaSB6dXIgS2F0ZWdvcmllIGogZ2Vow7ZydCB9IFxcDQowLCBcdGV4dCB7IGZhbGxzIFBlcnNvbiBpIG5pY2h0IHp1ciBLYXRlZ29yaWUgaiBnZWjDtnJ0IH0NClxlbmR7YXJyYXl9XHJpZ2h0LiQkDQoNCiogUmVmZXJlbnprYXRlZ29yaWU6ICREX3tpan0gPSAwJCBmw7xyIGFsbGUgJGokDQoqIERpc2tyZXRlciBQcsOkZGlrdG9yIG1pdCBrIEF1c3Byw6RndW5nZW4gYmVuw7Z0aWd0IGsgLSAxIER1bW15IFZhcmlhYmxlbiANCg0KJCRcbGFyZ2UgWV97aX09XGFscGhhK1xiZXRhX3sxfSBcY2RvdCBEX3sxIGl9K1xjZG90cytcYmV0YV97KGstMSl9IFxjZG90IERfeyhrLTEpIGl9K1x2YXJlcHNpbG9uX3tpfSBccXVhZCBcdGV4dCB7IG1pdCB9IFx2YXJlcHNpbG9uX3tpfSBcc3RhY2tyZWx7aSBpIGR9e1xzaW19IE5cbGVmdCgwLCBcc2lnbWFeezJ9XHJpZ2h0KSQkDQoNCg0KDQoqIERhbWl0IGVyZ2lidCBzaWNoOg0KICAgICogJFxhbHBoYSQgaXN0IGRlciBFcndhcnR1bmdzd2VydCBkZXIgJFxtYXRocm17QVZ9JCBpbiBkZXIgUmVmZXJlbnprYXRlZ29yaWUuDQogICAgKiAkXGFscGhhK1xiZXRhX3tqfSQgaXN0IGRlciBFcndhcnR1bmdzd2VydCBkZXIgJFxtYXRocm17QVZ9JCBpbiBLYXRlZ29yaWUgai4NCiAgICAqICRcYmV0YV97an0kIGlzdCBkaWUgRXJ3YXJ0dW5nc3dlcnRkaWZmZXJlbnogZGVyICRBIFYkIHp3aXNjaGVuIGRlciBLYXRlZ29yaWUgJGokIHVuZCBkZXIgUmVmZXJlbnprYXRlZ29yaWUuDQoNCg0KDQojIyMjIEtvbWJpbmF0aW9uIHZvbiBkaXNrcmV0IHVuZCBzdGV0aWcNCg0KJCRcbGFyZ2UgDQpZX3tpfT1cYWxwaGErXGJldGFfezF9IFxjZG90IFhfe2l9K1xiZXRhX3syfSBcY2RvdCBEX3tpfStcYmV0YV97M31cbGVmdChYX3tpfSBcY2RvdCBEX3tpfVxyaWdodCkrXHZhcmVwc2lsb25fe2l9IFxxdWFkIFx0ZXh0IHsgbWl0IH0gXHZhcmVwc2lsb25fe2l9IFxzdGFja3JlbHtpIGkgZH17XHNpbX0gTlxsZWZ0KDAsIFxzaWdtYV57Mn1ccmlnaHQpJCQNCg0KKiBNb2RlbGwgZsO8ciBSZWZlcmVuemthdGVnb3JpZQ0KDQokJCBcbGFyZ2UNCllfe2l9ID1cYWxwaGErXGJldGFfezF9IFxjZG90IFhfe2l9K1x2YXJlcHNpbG9uX3tpfSQkDQoNCiogTW9kZWxsIGbDvHIgYW5kZXJlIEthdGVnb3JpZQ0KDQokJFxsYXJnZQ0KWV97aX0gPVxsZWZ0KFxhbHBoYStcYmV0YV97Mn1ccmlnaHQpK1xsZWZ0KFxiZXRhX3sxfStcYmV0YV97M31ccmlnaHQpIFxjZG90IFhfe2l9K1x2YXJlcHNpbG9uX3tpfSQkDQoNCg0KKiBEYW1pdCBlcmdpYnQgc2ljaCBkaWUgZm9sZ2VuZGUgSW50ZXJwcmV0YXRpb24gZGVyIFBhcmFtZXRlcjoNCiAgICAqICRcYWxwaGEkIGlzdCBkZXIgSW50ZXJjZXB0IGluIGRlciBSZWZlcmVuemthdGVnb3JpZS4NCiAgICAqICRcYmV0YV97MX0kIGlzdCBkZXIgU3RlaWd1bmdzcGFyYW1ldGVyIGluIGRlciBSZWZlcmVuemthdGVnb3JpZS4NCiAgICAqICRcYWxwaGErXGJldGFfezJ9JCBpc3QgZGVyIEludGVyY2VwdCBpbiBkZXIgYW5kZXJlbiBLYXRlZ29yaWUuDQogICAgKiAkXGJldGFfezF9K1xiZXRhX3szfSQgaXN0IGRlciBTdGVpZ3VuZ3NwYXJhbWV0ZXIgaW4gZGVyIGFuZGVyZW4gS2F0ZWdvcmllLg0KICAgICogJFxiZXRhX3syfSQgaXN0IGRpZSBEaWZmZXJlbnogZGVyIEludGVyY2VwdHMgZGVyIGFuZGVyZW4gS2F0ZWdvcmllIHVuZCBkZXIgUmVmZXJlbnprYXRlZ29yaWUuDQogICAgKiAkXGJldGFfezN9JCBpc3QgZGllIERpZmZlcmVueiBkZXIgU3RlaWd1bmdzcGFyYW1ldGVyIGRlciBhbmRlcmVuIEthdGVnb3JpZSB1bmQgZGVyIFJlZmVyZW56a2F0ZWdvcmllLg0KDQoNCg0KYGBge3J9DQpkYXRhIDwtIGRhdGEuZnJhbWUoVVZTID0gYygxLDIsNiw3LDEzLDE1LDIwLDMwKSwgVVZEID0gYygxLDAsMSwwLDAsMCwxLDApLCBBViA9IGMoMCwyMyw4MCw5MCwxNDAsMTgyLDIyMCwzMDApKQ0KZml0IDwtIGxtKEFWIH4gVVZTICogVVZELCBkYXRhID0gZGF0YSkNCg0KI3N1bW1hcnkoZml0KQ0KDQojIGENCmZpdCRjb2VmZmljaWVudHNbWyIoSW50ZXJjZXB0KSJdXQ0KDQojIGIxDQpmaXQkY29lZmZpY2llbnRzW1siVVZTIl1dDQoNCiMgYjINCmZpdCRjb2VmZmljaWVudHNbWyJVVkQiXV0NCg0KIyBiMw0KZml0JGNvZWZmaWNpZW50c1tbIlVWUzpVVkQiXV0NCg0KIyBLb25maWRlbnpvaW50ZXJ2YWxsIGbDvHIgUGFyYW1ldGVyDQpjb25maW50KGZpdCwgbGV2ZWw9MC45NSkNCg0KIyBzdGFuZGFyZCBlcnJvcg0Kc3VtbWFyeShmaXQpJHNpZ21hDQoNCg0KYGBgDQoNCiMjIyMjIEh5cG90aGVzZW50ZXN0cw0KDQpCZWlzcGllbGU6DQoNCkdpYnQgZXMgZWluZW4gWnVzYW1tZW5oYW5nIHp3aXNjaGVuIFVWIHVuZCBBViBpbiBkZXIgUmVmZXJlbnprYXRlZ29yaWU/DQoNCg0KJCRcbGFyZ2UgSF97MH06IFxiZXRhX3sxfT0wIFxcDQpIX3sxfTogXGJldGFfezF9IFxuZXEgMCQkDQoNCg0KSXN0IGRlciBadXNhbW1lbmhhbmcgendpc2NoZW4gVVYgdW5kIEFWIHVudGVyc2NoaWVkbGljaCBncm/DnyBpbiBkZW4gS2F0ZWdvcmllbj8NCg0KJCRcbGFyZ2UgSF97MH06IFxiZXRhX3szfT0wIFxcDQpIX3sxfTogXGJldGFfezN9IFxuZXEgMCQkDQoNCg0KYGBge3J9DQpkYXRhIDwtIGRhdGEuZnJhbWUoVVZTID0gYygxLDIsNiw3LDEzLDE1LDIwLDMwKSwgVVZEID0gYygxLDAsMSwwLDAsMCwxLDApLCBBViA9IGMoMCwyMyw4MCw5MCwxNDAsMTgyLDIyMCwzMDApKQ0KZml0IDwtIGxtKEFWIH4gVVZTICogVVZELCBkYXRhID0gZGF0YSkNCnN1bW1hcnkoZml0KQ0KYGBgDQoNCg0KYGBge3J9DQojIEtvbWxleGVyZSBGcmFnZXN0ZWxsdW5nZW4NCiMgQnNwOiBHaWJ0IGVzIGbDvHIgbWluZGVzdGVucyBlaW5lIEthdGVnb3JpZSBkZXIgVVZEIGVpbmVuIHBvc2l0aXZlbiBadXNhbW1lbmhhbmcgendpc2NoZW4gVVZTIHVuZCBBVj8NCmxpYnJhcnkobXVsdGNvbXApDQpkYXRhIDwtIGRhdGEuZnJhbWUoVVZTID0gYygxLDIsNiw3LDEzLDE1LDIwLDMwKSwgVVZEID0gYygxLDAsMSwwLDAsMCwxLDApLCBBViA9IGMoMCwyMyw4MCw5MCwxNDAsMTgyLDIyMCwzMDApKQ0KZml0X2xtIDwtIGxtKEFWIH4gVVZTICogVVZELCBkYXRhID0gZGF0YSkNCg0KaHlwcyA8LSBjKCdVVlMgPD0gMCcsDQogICAgICAgICAgJ1VWUyArIFVWUzpVVkQgPD0gMCcpDQpmaXQgPC0gZ2xodChmaXRfbG0sIGh5cHMpDQoNCiMjIHVua29ycmlnaWVydGUgcC1XZXJ0ZQ0Kc3VtbWFyeShmaXQsIHRlc3QgPSB1bml2YXJpYXRlKCkpDQojIyBUdWtleS1rb3JyaWdpZXJ0ZSBwLVdlcnRlDQpzdW1tYXJ5KGZpdCwgdGVzdCA9IGFkanVzdGVkKCdzaW5nbGUtc3RlcCcpKQ0KYGBgDQoNCkludGVyYWt0aW9uIHp3aXNjaGVuIHN0ZXRpZ2VuIFByw6RkaWt0b3Jlbg0KDQoNCiQkXGxhcmdlDQpZX3tpfT1cYWxwaGErXGJldGFfezF9IFxjZG90IFhfe2kgMX0rXGJldGFfezJ9IFxjZG90IFhfe2kgMn0rXGJldGFfezN9XGxlZnQoWF97aSAxfSBcY2RvdCBYX3tpIDJ9XHJpZ2h0KStcdmFyZXBzaWxvbl97aX0gXHRleHQgeyBtaXQgfSBcdmFyZXBzaWxvbl97aX0gXHN0YWNrcmVse2kgaSBkfXtcc2ltfSBOXGxlZnQoMCwgXHNpZ21hXnsyfVxyaWdodCkkJA0KDQoNCiogTW9kZXJhdG9yICRYX3tpIDJ9JA0KDQokJFxsYXJnZSBZX3tpfT1cYWxwaGErXGJldGFfezJ9IFxjZG90IFhfe2kgMn0rXGxlZnQoXGJldGFfezF9K1xiZXRhX3szfSBcY2RvdCBYX3tpIDJ9XHJpZ2h0KSBcY2RvdCBYX3tpIDF9K1x2YXJlcHNpbG9uX3tpfSQkDQoNCg0KKiBNb2RlcmF0b3IgJFhfe2kgMX0kDQoNCiQkXGxhcmdlIFlfe2l9PVxhbHBoYStcYmV0YV97MX0gXGNkb3QgWF97aSAxfStcbGVmdChcYmV0YV97Mn0rXGJldGFfezN9IFxjZG90IFhfe2kgMX1ccmlnaHQpIFxjZG90IFhfe2kgMn0rXHZhcmVwc2lsb25fe2l9JCQNCg0KDQoNCiMjIyBMb2dpc3Rpc2NoZSBSZWdyZXNzaW9uIHsjTG9naXN0aXNjaGVSZWdyZXNzaW9ufQ0KDQoNCiQkXGxhcmdlIFBcbGVmdChZX3tpfT0xIFxtaWQgeF97aX1ccmlnaHQpPXNcbGVmdChcYWxwaGErXGJldGEgeF97aX1ccmlnaHQpPVxmcmFje2Vee1xhbHBoYStcYmV0YSB4X3tpfX19ezErZV57XGFscGhhK1xiZXRhIHhfe2l9fX0kJA0KDQpPZGRzOg0KDQoqICJXaWUgdmllbCBtYWwgd2FocnNjaGVpbmxpY2hlciBpc3QgMSBhbHMgMCINCg0KJCRcbGFyZ2UgXGZyYWN7UFxsZWZ0KFlfe2l9PTEgXG1pZCB4X3tpfVxyaWdodCl9e1BcbGVmdChZX3tpfT0wIFxtaWQgeF97aX1ccmlnaHQpfT1lXntcYWxwaGErXGJldGEgeF97aX19PWVee1xhbHBoYX0gXGNkb3QgZV57XGJldGEgeF97aX19JCQNCg0KJCRcbGFyZ2UgXGZyYWN7UFxsZWZ0KFlfe2l9PTEgXG1pZCB4X3tpfSsxXHJpZ2h0KX17UFxsZWZ0KFlfe2l9PTAgXG1pZCB4X3tpfSsxXHJpZ2h0KX09ZV57XGFscGhhfSBcY2RvdCBlXntcYmV0YVxsZWZ0KHhfe2l9KzFccmlnaHQpfT1lXntcYWxwaGF9IFxjZG90IGVee1xiZXRhIHhfe2l9fSBcY2RvdCBlXntcYmV0YX09XGZyYWN7UFxsZWZ0KFlfe2l9PTEgXG1pZCB4X3tpfVxyaWdodCl9e1BcbGVmdChZX3tpfT0wIFxtaWQgeF97aX1ccmlnaHQpfSBcY2RvdCBlXntcYmV0YX0kJA0KDQokJFxsYXJnZSBcZnJhY3tQXGxlZnQoWV97aX09MSBcbWlkIHhfe2l9PTBccmlnaHQpfXtQXGxlZnQoWV97aX09MCBcbWlkIHhfe2l9PTBccmlnaHQpfT1lXntcYWxwaGF9IFxjZG90IGVee1xiZXRhIFxjZG90IDB9PWVee1xhbHBoYX0kJA0KDQpMb2ctT2RkczoNCg0KJCRcbGFyZ2UgXGxuIFxsZWZ0KFxmcmFje1BcbGVmdChZX3tpfT0xIFxtaWQgeF97aX1ccmlnaHQpfXtQXGxlZnQoWV97aX09MCBcbWlkIHhfe2l9XHJpZ2h0KX1ccmlnaHQpPVxsbiBcbGVmdChlXntcYWxwaGErXGJldGEgeF97aX19XHJpZ2h0KT1cYWxwaGErXGJldGEgeF97aX0kJA0KDQoNCkRpZSBMb2ctT2RkcyBzaW5kIGdlbmF1IGRhbm4gZ2xlaWNoIDAsIHdlbm4gJFBcbGVmdChZX3tpfT0xIFxtaWQgeF97aX1ccmlnaHQpPTAuNSQgaXN0LiBTaWUgc2luZCBuZWdhdGl2LCB3ZW5uICRQXGxlZnQoWV97aX09MSBcbWlkIHhfe2l9XHJpZ2h0KTxQXGxlZnQoWV97aX09MCBcbWlkIHhfe2l9XHJpZ2h0KSQgaXN0LCB1bmQgcG9zaXRpdiwgd2VubiAkUFxsZWZ0KFlfe2l9PTEgXG1pZCB4X3tpfVxyaWdodCk+UFxsZWZ0KFlfe2l9PTAgXG1pZCB4X3tpfVxyaWdodCkkIGlzdC4NCg0KDQoNCmBgYHtyfQ0KIyBwcm9iYWJpbGl0eShZPTEpIC0+IG9kZHMsIGxvZyBvZGRzDQoNCnAgPSAwLjcNCg0Kb2RkcyA8LSBwLygxLXApDQpvZGRzDQoNCmxvZ19vZGRzIDwtIGxvZyhvZGRzKQ0KbG9nX29kZHMNCg0KYGBgDQoNCg0KYGBge3J9DQojIG9kZHMgLT4gbG9nIG9kZHMsIHByb2JhYmlsaXR5KFk9MSkNCg0Kb2RkcyA8LSAzDQoNCmxvZ19vZGRzIDwtIGxvZyhvZGRzKQ0KbG9nX29kZHMNCg0KcCA8LSBvZGRzLyhvZGRzKzEpDQpwDQoNCmBgYA0KDQoNCmBgYHtyfQ0KIyBsb2cgb2RkcyAtPiBvZGRzLCBwcm9iYWJpbGl0eShZPTEpDQoNCmxvZ19vZGRzIDwtIDAuOA0KDQpvZGRzIDwtIGV4cChsb2dfb2RkcykNCm9kZHMNCg0KcCA8LSBvZGRzLyhvZGRzKzEpDQpwDQoNCmBgYA0KDQoNCkbDvHIgTXVsdGlwbGUgUmVncmVzc2lvbjoNCg0KJCRcbGFyZ2UgUFxsZWZ0KFlfe2l9PTEgXG1pZCB4X3tpIDF9LCBcbGRvdHMsIHhfe2kga31ccmlnaHQpPVxmcmFje2Vee1xhbHBoYStcYmV0YV97MX0geF97aSAxfStcY2RvdHMrXGJldGFfe2t9IHhfe2kga319fXsxK2Vee1xhbHBoYStcYmV0YV97MX0geF97aSAxfStcY2RvdHMrXGJldGFfe2t9IHhfe2kga319fSQkDQoNCkludGVycHJldGF0aW9uIEJhc2ljczoNCg0KKiBBdXMgZGVyIE9kZHMtU2NocmVpYndlaXNlIGVyZ2lidCBzaWNoOg0KICAgICogJGVee1xhbHBoYX0kIGVudHNwcmljaHQgZGVuIE9kZHMgdm9uIFBlcnNvbmVuLCBkaWUgYXVmIGFsbGVuIFVWcyBkZW4gV2VydCAwIGhhYmVuLg0KICAgICogJGVee1xiZXRhX3tqfX0kIGVudHNwcmljaHQgZGVtIEZha3RvciwgdW0gZGVuIHNpY2ggZGllIE9kZHMgZXJow7ZoZW4sIGZhbGxzIHNpY2ggZGllIFVWICRqJCB1bSBlaW5lIEVpbmhlaXQgZXJow7ZodCB1bmQgYWxsZSBhbmRlcmVuIFVWcyBrb25zdGFudCBibGVpYmVuLg0KKiBBdXMgZGVyIExvZy1PZGRzLVNjaHJlaWJ3ZWlzZSBlcmdpYnQgc2ljaDoNCiAgICAqICRcYWxwaGEkIGVudHNwcmljaHQgZGVuIExvZy1PZGRzIHZvbiBQZXJzb25lbiwgZGllIGF1ZiBhbGxlbiBVVnMgZGVuIFdlcnQgMCBoYWJlbi4NCiAgICAqIEZhbGxzIHNpY2ggZGllIFVWICRqJCB1bSBlaW5lIEVpbmhlaXQgZXJow7ZodCB1bmQgYWxsZSBhbmRlcmVuIFVWcyBrb25zdGFudCBibGVpYmVuLCBlcmjDtmhlbiBzaWNoIGRpZSBMb2ctT2RkcyB1bSAkXGJldGFfe2p9JC4NCg0KDQpgYGB7cn0NCmRhdGEgPC0gZGF0YS5mcmFtZShVViA9IGMoMSwyLDYsNywxMywxNSwyMCwzMCksIEFWID0gYygxLDAsMSwwLDAsMCwxLDApKQ0KZml0IDwtIGdsbShBViB+IFVWLCBmYW1pbHk9ImJpbm9taWFsIiwgZGF0YSA9IGRhdGEpDQojc3VtbWFyeShmaXQpDQoNCg0KIyBMb2cgT2Rkcw0KZml0JGNvZWZmaWNpZW50c1tbIihJbnRlcmNlcHQpIl1dDQpmaXQkY29lZmZpY2llbnRzW1siVVYiXV0NCmNvbmZpbnQoZml0LCBsZXZlbD0wLjk1KQ0KDQoNCiMgT2Rkcw0KZXhwKGZpdCRjb2VmZmljaWVudHNbWyIoSW50ZXJjZXB0KSJdXSkNCmV4cChmaXQkY29lZmZpY2llbnRzW1siVVYiXV0pDQpleHAoY29uZmludChmaXQsIGxldmVsPTAuOTUpKQ0KDQpgYGANCg0KDQoNCg0KDQpNb2RlbGxlIG1pdCBkaXNrcmV0ZW4gUHLDpGRpa3RvcmVuOg0KDQokJFxsYXJnZSBcZnJhY3tQXGxlZnQoWV97aX09MSBcbWlkIDFccmlnaHQpfXtQXGxlZnQoWV97aX09MCBcbWlkIDFccmlnaHQpfT1lXntcYWxwaGF9IFxjZG90IGVee1xiZXRhIFxjZG90IDF9PVxmcmFje1BcbGVmdChZX3tpfT0xIFxtaWQgMFxyaWdodCl9e1BcbGVmdChZX3tpfT0wIFxtaWQgMFxyaWdodCl9IFxjZG90IGVee1xiZXRhfSQkDQpPZGRzIFJhdGlvOg0KDQoNCiogV2lldmllbCBtYWwgc2luZCBkaWUgT2RkcyBpbiBkZXIgTmljaHQtUmVmZXJlbnprYXRlZ29yaWUgZ3LDtsOfZXIgYWxzIGluIGRlciBSZWZlcmVuemthdGVnb3JpZT8NCg0KDQokJFxsYXJnZSBcZnJhY3tcZnJhY3tQXGxlZnQoWV97aX09MSBcbWlkIDFccmlnaHQpfXtQXGxlZnQoWV97aX09MCBcbWlkIDFccmlnaHQpfX17XGZyYWN7UFxsZWZ0KFlfe2l9PTEgXG1pZCAwXHJpZ2h0KX17UFxsZWZ0KFlfe2l9PTAgXG1pZCAwXHJpZ2h0KX19PWVee1xiZXRhfSQkDQoNCg0KYGBge3J9DQojIE9kZHMgUmF0aW8gYXVzIE1vZGVsbCBlcnJlY2huZW4gIA0KZGF0YSA8LSBkYXRhLmZyYW1lKFVWID0gYygwLDEsMSwxLDAsMCwwLDAsMSwxKSwgQVYgPSBjKDEsMCwxLDAsMSwxLDEsMCwwLDApKQ0KZml0IDwtIGdsbShBViB+IFVWLCBmYW1pbHk9ImJpbm9taWFsIiwgZGF0YSA9IGRhdGEpDQoNCmV4cChmaXQkY29lZmZpY2llbnRzW1siVVYiXV0pDQoNCmBgYA0KDQpgYGB7cn0NCiMgT2RkcyBSYXRpbyBhdXMgV2FocnNjaGVpbmxpY2hrZWl0ZW4gKFk9MSkNCnBfcmVmID0gMC43DQpwX25pY2h0X3JlZiA9IDAuNQ0KDQoocF9uaWNodF9yZWYvKDEtcF9uaWNodF9yZWYpKS8ocF9yZWYvKDEtcF9yZWYpKQ0KDQpgYGANCg0KUmlzayBSYXRpbzoNCg0KKiBVbSB3ZWxjaGVuIEZha3RvciBpc3QgZGFzIEF1ZnRyZXRlbiB2b24gJFlfe2l9PTEkIGluIGRlciBOaWNodC1SZWZlcmVuemthdGVnb3JpZSB3YWhyc2NoZWlubGljaGVyIGlzdCBhbHMgaW4gZGVyIFJlZmVyZW56a2F0ZWdvcmllPw0KDQoNCiQkXGxhcmdlICBcZnJhY3tQXGxlZnQoWV97aX09MSBcbWlkIDFccmlnaHQpfXtQXGxlZnQoWV97aX09MSBcbWlkIDBccmlnaHQpfSA9IFxmcmFjezErZV57LVxhbHBoYX19ezErZV57LVxhbHBoYS1cYmV0YX19JCQNCg0KDQpgYGB7cn0NCiMgUmlzayBSYXRpbyBhdXMgTW9kZWxsIGVycmVjaG5lbiAgDQpkYXRhIDwtIGRhdGEuZnJhbWUoVVYgPSBjKDAsMSwxLDEsMCwwLDAsMCwxLDEpLCBBViA9IGMoMSwwLDEsMCwxLDEsMSwwLDAsMCkpDQpmaXQgPC0gZ2xtKEFWIH4gVVYsIGZhbWlseT0iYmlub21pYWwiLCBkYXRhID0gZGF0YSkNCg0KKDErZXhwKC1maXQkY29lZmZpY2llbnRzW1siKEludGVyY2VwdCkiXV0pKS8oMStleHAoLWZpdCRjb2VmZmljaWVudHNbWyIoSW50ZXJjZXB0KSJdXS1maXQkY29lZmZpY2llbnRzW1siVVYiXV0pKQ0KYGBgDQoNCmBgYHtyfQ0KIyBSaXNrIFJhdGlvIGF1cyBhbHBoYSB1bmQgYmV0YQ0KYWxwaGEgPSAwLjcNCmJldGEgPSAwLjUNCg0KKDErZXhwKC1hbHBoYSkpLygxK2V4cCgtYWxwaGEtYmV0YSkpDQoNCmBgYA0KDQpWb3JoZXJzYWdlDQoNCiQkXGxhcmdlIFxoYXR7eX1fe2l9PVxsZWZ0XHtcYmVnaW57YXJyYXl9e2xjfQ0KMSwgJiBcdGV4dCB7IGZhbGxzIH0gJiBcZnJhY3tlXnthK2JfezF9IHhfe2kgMX0rXGNkb3RzK2Jfe2t9IHhfe2kga319fXsxK2Vee2ErYl97MX0geF97aSAxfStcY2RvdHMrYl97a30geF97aSBrfX19IFxnZXEgMC41IFxcDQowLCAmIFx0ZXh0IHsgc29uc3QgfQ0KXGVuZHthcnJheX1ccmlnaHQuJCQNCg0KDQokJFxsYXJnZSBcaGF0e3l9X3tpfT1cbGVmdFx7XGJlZ2lue2FycmF5fXtsY30NCjEsICYgXHRleHQgeyBmYWxscyB9IGErYl97MX0geF97aSAxfStcY2RvdHMrYl97a30geF97aSBrfSBcZ2VxIDAgXFwNCjAsICYgXHRleHQgeyBzb25zdCB9DQpcZW5ke2FycmF5fVxyaWdodC4kJA0KDQoNCg0KDQoNCmBgYHtyfQ0KZGF0YSA8LSBkYXRhLmZyYW1lKFVWID0gYygxLDIsNiw3LDEzLDE1LDIwLDMwKSwgQVYgPSBjKDEsMCwxLDAsMCwwLDEsMCkpDQpmaXQgPC0gZ2xtKEFWIH4gVVYsIGZhbWlseT0iYmlub21pYWwiLCBkYXRhID0gZGF0YSkNCg0KIyBWb3JoZXJzYWdlIG1pdCBSDQpkYXRhX25ldyA8LSBkYXRhLmZyYW1lKFVWID0gOCkNCnByZWRpY3QoZml0LCBuZXdkYXRhID0gZGF0YV9uZXcsIHR5cGU9InJlc3BvbnNlIikNCmBgYA0KDQoNCmBgYHtyfQ0KYWxwaGEgPSAzDQpiZXRhID0gMC4yDQoNCnV2X3ZhbCA9IDEwDQoNCiMgVm9yaGVyc2FnZSBwZXIgSGFuZA0KZXhwKGFscGhhK2JldGEqdXZfdmFsKS8oMStleHAoYWxwaGErYmV0YSp1dl92YWwpKQ0KDQpgYGANCg0KDQojIyMgSW50ZXJwcmV0YXRpb25lbiBiZWkgU3RhbmRhcmRpc2llcnVuZyB7I1N0YW5kYXJkaXNpZXJ1bmd9DQoNCkJlaXNwaWVsIG1pdCAyIHN0ZXRpZ2VuIFVWcyBvaG5lIEludGVyYWt0aW9uLCBhbndlbmRiYXIgYXVmIGJlbGllYmlnZSBGw6RsbGUgDQooQWNodHVuZzogYmVpIGxvZ2lzdGlzY2hlciByZWdyZXNzaW9uIGVyaMO2aGVuIHNpY2ggbG9nb2RkcywgbmljaHQgQVYgV2VydGUhKQ0KDQojIyMjIFVWDQoNCg0KIyMjIyMgTm9ybWFsDQoNCiogSW50ZXJjZXB0OiBEdXJjaHNjaG5pdHRsaWNoZXIgQVYtV2VydCBmw7xyIFBlcnNvbmVuIG1pdCAqKlVWMT0wIHVuZCBVVjI9MCoqIA0KKiBTbG9wZV8xOiBGYWxscyBzaWNoIFVWMSB1bSAqKmVpbmUgRWluaGVpdCoqIGVyaMO2aHQgdW5kIFVWMiBrb25zdGFudCBibGVpYnQsIGVyaMO2aHQgc2ljaCBkaWUgQVYgdW0gU2xvcGVfMQ0KDQojIyMjIyBaZW50cmllcnQNCg0KUGFyYW1ldGVyIGvDtm5uZW4gZXZlbnR1ZWxsIHNpbm52b2xsZXIgaW50ZXJwcmV0aWVydCB3ZXJkZW4NCg0KKiBJbnRlcmNlcHQ6IER1cmNoc2Nobml0dGxpY2hlciBBVi1XZXJ0IGbDvHIgUGVyc29uZW4gbWl0ICoqZHVyY2hzY2huaXR0bGljaGVuKiogVVYxIHVuZCBVVjIgDQoqIFNsb3BlXzE6IEZhbGxzIHNpY2ggVVYxIHVtICoqZWluZSBFaW5oZWl0KiogZXJow7ZodCB1bmQgVVYyIGtvbnN0YW50IGJsZWlidCwgZXJow7ZodCBzaWNoIGRpZSBBViB1bSBTbG9wZV8xDQoNCiMjIyMjIHotU3RhbmRhcmRpc2llcnQNCg0KUGFyYW1ldGVyIGvDtm5uZW4gZXZlbnR1ZWxsIHNpbm52b2xsZXIgaW50ZXJwcmV0aWVydCB3ZXJkZW4sIFZJRiBpc3QgZ2VyaW5nZXINCg0KKiBJbnRlcmNlcHQ6IER1cmNoc2Nobml0dGxpY2hlciBBVi1XZXJ0IGbDvHIgUGVyc29uZW4gbWl0ICoqZHVyY2hzY2huaXR0bGljaGVuKiogVVYxIHVuZCBVVjIgDQoqIFNsb3BlXzE6IEZhbGxzIHNpY2ggVVYxIHVtICoqZWluZSBTdGFuZGFyZGFid2VpY2h1bmcqKiBlcmjDtmh0IHVuZCBVVjIga29uc3RhbnQgYmxlaWJ0LCBlcmjDtmh0IHNpY2ggZGllIEFWIHVtIFNsb3BlXzENCg0KDQojIyMjIEFWDQoNCg0KIyMjIyMgTm9ybWFsDQoNCiogLi4uIGVyaMO2aHQgc2ljaCBkaWUgKEVyd2FydGV0ZXIpIEFWICoqdW0gU2xvcGUqKg0KDQojIyMjIyB6LXN0YW5kYXJkaXNpZXJ0DQoNCiogLi4uIGVyaMO2aHQgc2ljaCBkaWUgKEVyd2FydGV0ZXIpIEFWICoqdW0gU2xvcGUgU3RhbmJkYXJkYWJ3ZWljaHVuZ2VuKioNCg0KDQoNCg==