(Danke an Denise und May fürs Korrekturlesen)

Das hier ist eine semi-interaktive Formelsammlung über alle wichtigen Formeln der Statistik 1 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 Befehle wieder einzublenden.

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

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

Inhaltsverzeichnis

Deskriptive Statistik

Grundbegriffe

Absolute Häufigkeit

\[\large H(x_j)\]

vec = c("A","A","B","A","C","B")
table(vec)

Absolute kummulierte Häufigkeit

\[\large H_{kum}(x_k) = \sum_{j=1}^{k} H(x_j)\]

vec = c("A","A","B","A","C","B")
cumsum(table(vec))

Relative Häufigkeit

\[\large h(x_j) = \frac{H(x_j)}{n} \]

vec = c("A","A","B","A","C","B")
prop.table(table(vec))

Relative kummulierte Häufigkeit

\[\large h_{kum}(x_k) = \frac{H_{kum}(x_k)}{n} = \frac{\sum_{j=1}^{k} H(x_j)}{n}\]

vec = c("A","A","B","A","C","B")
cumsum(prop.table(table(vec)))

Modalwert

Die Messwertausprägung, die am häufigsten beobachtet wurde.

vec = c("A","A","B","A","C","B")
names(which.max(table(vec)))

Arithmetisches Mittel / Mean

Summe aller Messwerte geteilt durch Anzahl der Beobachtungen.

\[\large \bar{x} = \frac{1}{n}\sum_{i=1}^{n}x_i\]

vec = c(1,2,3,4,5,6)
mean(vec)

Median

(Mindestend) 50% der Merkmalsträger haben einen Messwert, der kleiner oder gleich dem Median ist. Zur Berechnung müssen die Messwerte in aufsteigender Reihenfolge geordnet sein.

\[\large Md = \begin{cases} x_{(\frac{n+1}{2})} &\text{falls n ungerade} \\ \frac{x_{(\frac{n}{2})} + x_{(\frac{n}{2}+1)}}{2} &\text{falls n gerade} \end{cases}\]

vec = c(1,3,4,5,7)
median(vec)

Empirische Varianz

\[\large s_{emp}^{2} = \frac{1}{n}\sum_{i=1}^{n} (x_i - \bar{x})^2\]

vec = c(1,2,3,4,5,6,7,10,12)
n = length(vec)
((n-1)/n)*var(vec)

Empirische Standardabweichung

\[\large s_{emp} = \sqrt{s_{emp}^{2}} = \sqrt{\frac{1}{n}\sum_{i=1}^{n} (x_i - \bar{x})^2}\]

vec = c(1,2,3,4,5,6,7,10,12)
n = length(vec)
sqrt(((n-1)/n)*var(vec))

Quantile


vec = c(1,2,3,4,5,6,7,8,9,10,11,12)
quantile(vec, probs=c(0.25,0.5,0.75))

Interquartilabstand


vec = c(1,2,3,4,5,6,7,8,9,10,11,12)
IQR(vec, type=6)

Barplot

vec = c(1,1,1,2,2,5,5,5,9)
barplot(table(vec))

Histogram

vec = c(0,1,1,1.5,2,2,3,5,5,5)
hist(vec)

Boxplot

vec = c(0,0,1,1,1,2,2,5,5,5,9,15)
boxplot(vec)

Kovarianz und Korrelation

Kovarianz (empirisch)

Richtung eines Zusammenhangs.

\[ \large \operatorname{cov}_{e m p}(x, y)=\frac{1}{n} \sum_{i=1}^{n} L_{i}=\frac{1}{n} \sum_{i=1}^{n}\left(x_{i}-\bar{x}\right)\left(y_{i}-\bar{y}\right) \] Symmetrie:

\[ \large \operatorname{cov}_{e m p}(x, y)= \operatorname{cov}_{e m p}(y, x) \]

Kovarianz mit sich selbst ist gleich der empirischen Varianz.

\[ \large \operatorname{cov}_{e m p}(x, x)=\frac{1}{n} \sum_{i=1}^{n}\left(x_{i}-\bar{x}\right)\left(x_{i}-\bar{x}\right)=\frac{1}{n} \sum_{i=1}^{n}\left(x_{i}-\bar{x}\right)^{2}=s_{e m p}^{2} \]

Zusammenhang mit Steigung der Geraden durch das Streudiagram:

\[ \large \operatorname{cov}_{e m p}(x, y)=b \cdot s_{x e m p}^{2} \]

x = c(1,2,3,4,5,6)
y = c(7,8,9,10,11,12) 

cov(x,y)

z-standardisierung

Die Transformation der z-Standardisierung ist für jeden Messwert so definiert:

\[ \large z_{i}=\frac{x_{i}-\bar{x}}{s_{e m p}} \] \[ \large \begin{aligned} \bar{z} &=0 \\ s_{emp z} &=1 \end{aligned} \]

x = c(1,2,3,4,5,6)
(x-mean(x))/sqrt(((length(x)-1)/length(x))*var(x))

Pearson Korrelation

\[ \large r_{x y}=\operatorname{cov}_{e m p}\left(z_{x}, z_{y}\right)=\frac{1}{n} \sum_{i=1}^{n}\left(z_{x_{i}}-\bar{z}_{x}\right)\left(z_{y_{i}}-\bar{z}_{y}\right)=\frac{1}{n} \sum_{i=1}^{n} z_{x_{i}} \cdot z_{y_{i}} \]

\[\large = \frac{1}{n} \sum_{i=1}^{n}\left(\frac{x_{i}-\bar{x}}{s_{e m p x}}\right)\left(\frac{y_{i}-\bar{y}}{s_{e m p y}}\right)=\frac{1}{n} \frac{\sum_{i=1}^{n}\left(x_{i}-\bar{x}\right)\left(y_{i}-\bar{y}\right)}{s_{e m p x} \cdot s_{e m p} y} \] Symmetrie:

\[ \large r_{x y}=r_{y x} \] Die Korrelation entspricht der Steigung der Gerade durch das Streudiagram

\[ \large r_{x y}=b_{z} \] Alternative Formel: \[ \large r_{x y}=\frac{\operatorname{cov}_{e m p}(x, y)}{S_{e m p x} \cdot S_{e m p} y} \]

x = c(1,2,3,4,5,6)
y = c(7,8,9,10,11,12)  
  
cor(x,y)

Wahrscheinlichkeitstheorie

Grundbegriffe

Erwartungswert von Zufallsvariablen

\[ \large E(X)=\sum_{j=1}^{m} x_{j} \cdot P\left(X=x_{j}\right)=\sum_{j=1}^{m} x_{j} \cdot f\left(x_{j}\right) \] Falls die ZV stetig ist: \[ \large E(X)=\int_{-\infty}^{+\infty} x \cdot f(x) d x \]

Rechenregeln für den Erwartungswert \[ \large \begin{array}{c} E(a)=a \\ E(X+a)=E(X)+a \\ E(a \cdot X)=a \cdot E(X) \\ E(X+Y)=E(X)+E(Y) \\ E\left(\sum_{i=1}^{n} X_{i}\right)=\sum_{i=1}^{n} E\left(X_{i}\right) \end{array} \]

# Erwartungswert aus gegebener diskreter Wahrscheinlichkeitsfunktion
x = c(-4,-3,-2,-1)
fx = c(0.3,0.1,0.4,0.2)

sum(x*fx)
# Erwartungswert aus gegebener diskreter Wahrscheinlichkeitsverteilung
x = c(-4,3,4,20,22)
Fx = c(0.1,0.2,0.3,0.8,1)

fx = c(Fx[[1]])
for(i in 2:length(Fx)){fx[i] = Fx[[i]]-Fx[[i-1]]}

sum(x*fx)

Varianz und Standardabweichung von Zufallsvariablen

Varianz: \[ \large \operatorname{Var}(X)=\sum_{j=1}^{m}\left(x_{j}-E(X)\right)^{2} \cdot P\left(X=x_{j}\right)=\sum_{j=1}^{m}\left(x_{j}-E(X)\right)^{2} \cdot f\left(x_{j}\right) \] Falls die ZV stetig ist: \[ \large \operatorname{Var}(X)=\int_{-\infty}^{+\infty}(x-E(X))^{2} \cdot f(x) d x \] Standardabweichung:

\[ \large S D(X)=\sqrt{\operatorname{Var}(X)} \] Rechenregeln für Varianz und Standardabweichung:

\[ \large \begin{array}{c} \operatorname{Var}(X+a)=\operatorname{Var}(X) \\ S D(X+a)=S D(X) \\ \operatorname{Var}(a \cdot X)=a^{2} \cdot \operatorname{Var}(X) \\ S D(a \cdot X)=a \cdot \operatorname{SD}(X) \end{array} \]

# Varianz, Standardabweichung aus gegebener diskreter Wahrscheinlichkeitsfunktion
x = c(-4,-3,-2,-1)
fx = c(0.3,0.1,0.4,0.2)

e = sum(x*fx)
varemp = sum((x-e)**2*fx)

varemp
sqrt(varemp)
# Varianz, Standardabweichung aus gegebener diskreter Wahrscheinlichkeitsverteilung
x = c(-4,3,4,20,22)
Fx = c(0.1,0.2,0.3,0.8,1)

fx = c(Fx[[1]])
for(i in 2:length(Fx)){fx[i] = Fx[[i]]-Fx[[i-1]]}

e = sum(x*fx)
varemp = sum((x-e)**2*fx)

varemp
sqrt(varemp)

z-standardisierung von Zufallsvariablen

Analog zur Deskriptivstatistik.

\[ \large Z=\frac{X-E(X)}{S D(X)} \] \[ \large \begin{array}{l} \mathrm{E}(Z)=0 \\ SD(Z)=1 \end{array} \]

Konkrete Wahrscheinlichkeitsfunktionen

Bernoulli Verteilung

\[\large X \sim \operatorname{Be}(\pi)\]

\[\large T_{x}=\{0,1\}\]

Wahrscheinlichkeitsfunktion \[ \large \begin{array}{l} f(0)=P(X=0)=1-\pi \\ f(1)=P(X=1)=\pi \end{array} \]

\[ \large f\left(x_{j}\right)=\pi^{x_{j}}(1-\pi)^{1-x_{j}}\]

Verteilungsfunktion

\[ \large \begin{array}{c} F(0)=1-\pi \\ F(1)=1 \end{array} \]

Erwartungswert, Standardabweichung:

\[ \large E(X)=\pi\]

\[ \large SD(X)=\sqrt{\pi(1-\pi)}\]

Binomialverteilung

\[\large X \sim B(n, \pi)\] \[\large T_{x}=\{0,1,2,...,n\}\]

Voraussetzungen:

\[\large X_{1}, X_{2}, \ldots, X_{n}\] \[\large X_{i} \sim Be(\pi)\]

\[\large X=\sum_{i=1}^{n} X_{i}\]

Exkurs: Binomialkoeffizient

\[\large \left(\begin{array}{l} n \\ k \end{array}\right)=\frac{n !}{k !(n-k) !}\]

Wahrscheinlichkeitsfunktion

\[ \large f\left(x_{j}\right)=\left(\begin{array}{l} n \\ x_{j} \end{array}\right) \pi^{x_{j}}(1-\pi)^{n-x_{j}}\]

Verteilungsfunktion:

\[\large F\left(x_{k}\right)=\sum_{j=1}^{k} f\left(x_{j}\right)=\sum_{j=1}^{k}\left(\begin{array}{l} n \\ x_{j} \end{array}\right) \pi^{x_{j}}(1-\pi)^{n-x_{j}}\]

Erwartungswert, Standardabweichung:

\[\large E(X)=n \pi\] \[\large S D(X)=\sqrt{n \pi(1-\pi)}\] R Funktionen

p = 0.5
n = 100

dbinom(x=40, size=n, prob=p) # Wahrscheinlichkeitsfunktion
pbinom(q=70, size=n, prob=p) # Verteilungsfunktion
qbinom(p=0.25, size=n, prob=p) # Quantile 
rbinom(n=20, size=n, prob=p) # Zufallsgeneration nach Binomialverteilung

Normalverteilung

\[\large X \sim N\left(\mu, \sigma^{2}\right)\] \[\large T_{X}=\mathbb{R}\]

Wichtige Eigenschaften:

  • Ihre Dichtefunktion hat ihr Maximum an der Stelle \(x = \mu\)
  • Ihre Dichtefunktion ist symmetrisch um \(\mu\)
    • \(f(\mu+c)=f(\mu-c)\)
    • \(P(X \leq \mu-c)=P(X \geq \mu+c)\)
    • \(P(X \leq \mu)=0.5\)
  • Je weiler x von \(\mu\) entfernt ist, desto kleiner ist die Dichte

Wahrscheinlichkeitsdichtefunktion:

\[\large f(x)=\frac{1}{\sqrt{2 \pi \sigma^{2}}} \exp \left(-\frac{1}{2} \cdot \frac{(x-\mu)^{2}}{\sigma^{2}}\right)\]

Erwartugnswert, Varianz, Standardabweichung:

\[\large E(X)=\mu\] \[\large Var(X)=\sigma^2\] \[\large SD(X)=\sigma\] R Funktionen

mu = 3
sigma = 2 

dnorm(x=3, mean = mu, sd = sigma) # Wahrscheinlichkeitsdichtefunktion
pnorm(q=0.5, mean = mu, sd = sigma) # Verteilungsfunktion
qnorm(p=0.25, mean = mu, sd = sigma) # Quantile
rnorm(n=20, mean = mu, sd = sigma) # Zufallsgeneration nach Normalverteilung

z-standardisierung (Standardnormalvcerteilung):

\[\large Z=\frac{X-E(X)}{S D(X)}=\frac{X-\mu}{\sigma}\] \[\large Z \sim N(0,1)\]

t-Verteilung

\[\large T \sim t(v)\]

\[\large T_{T}=\mathbb{R}\]

Erwartungswert (\(\nu\) > 1): \[\large E(T)=0\]

Nützliche Eigenschaft:

\[\large t_{1-\frac{\alpha}{2}}=-t \frac{\alpha}{2}\]

Bemerke: Für hohe n nähert sich die Kurve der t-Verteilung der der Standardnormalverteilung an.

R Funktionen

v = 24


pt(q=1.4, df=v) # Verteilungsfunktion
qt(p=0.25, df=v) # Quantile

dt(x=0.2, df=v) # Wahrscheinlichkeitsdichtefunktion - uninteressant
rt(n=20, df=v) # Zufallsgeneration nach Normalverteilung - uninteressant

Zentraler Grenzwertsatz

Seien \(X_{1}, X_{2}, \ldots, X_{i}, \ldots, X_{n}\) Zufallsvariablen mit \(X_{i} \stackrel{\text { iid }}{\sim} P\), wobei P eine völlig beliebige Wahrscheinlichkeitsverteilung ist. Für

\[\large Z^{*}=\frac{\bar{X}-E(\bar{X})}{\widehat{S D}(\bar{X})}\] gilt dann

\[\large \lim _{n \rightarrow \infty} P_{Z^{*}}=N(0,1)\]

also für großes n

\[\large Z^{*} \stackrel{\mathrm{a}}{\sim} N(0,1)\]

Parameterschätzung

Notation

Parameter

  • \(\mu\), \(\sigma^{2}\), \(\pi\)

Allgemeine Schätzfunktion

  • \(\hat\mu\), \(\hat\sigma^{2}\), \(\hat\pi\)

Allgemeine Schätzwerte

  • \(\hat\mu_{Wert}\), \(\hat\sigma^{2}_{Wert}\), \(\hat\pi_{Wert}\)

Konkrete Schätzwerte

  • \(\bar{x}\), \(s_{emp}^{2}\)

Gütekriterien von Schätzfunktionen

Erwarungstreue \[\large E(\hat{\theta})=\theta\] Standardfehler \[\large S E(\hat{\theta})=S D(\hat{\theta})\]

Effizienz: Erwartungstreu und kleinsten Standardfehler aller erwartungstreuen Schätzfunktionen für den Parameter

Konsistenz: \[\large \lim _{n \rightarrow \infty} SE(\hat{\theta})=0\]

Schätzung für \(\pi\) einer Bernoulli-Verteilung

\[\large X_{1}, X_{2}, \ldots, X_{n} \operatorname{mit} X_{i} \stackrel{\mathrm{iid}}{\sim} \mathrm{Be}(\pi)\]

Punkt

Schätzfunktion:

\[\large \hat{\pi}=\bar{X}=\frac{1}{n} \sum_{i=1}^{n} X_{i}\] Erwartungswert:

\[\large E(\hat{\pi})=E(\bar{X}) = \pi\]

Standardfehler:

\[\large S E(\hat{\pi})=\sqrt{\frac{\pi(1-\pi)}{n}}\]

\(\large \hat{\pi}=\bar{X}\) ist erwartungstreu, effizient und konsistent.

Konfidenzintervall

(Approximatives) Konfidenzintervall mit Konfidenzniveau \(1-\alpha\): \[\large I\left(X_{1}, \ldots, X_{n}\right)=[U, O]=\left[\bar{X}-z_{1-\frac{\alpha}{2}} \cdot \sqrt{\frac{\bar{X}(1-\bar{X})}{n}}, \bar{X}+z_{1-\frac{\alpha}{2}} \cdot \sqrt{\frac{\bar{X}(1-\bar{X})}{n}}\right]\] \[\large Z^{*} \stackrel{\mathrm{a}}{\sim} N(0,1)\]

R Code

conf.level = 0.90

vec = c(1,1,1,0,0)
n = length(vec)

#Punktschaetzung
x_quer = mean(vec) 
x_quer 

# Konfidenzintervall von Hand
c = qnorm(1-((1-conf.level)/2), mean=0,sd=1) * sqrt(((x_quer*(1-x_quer))/n))
c(x_quer - c, x_quer + c)

# Konfidenzintervall mit R Funktion
library(DescTools)
BinomCI(x_quer*n,n,method='wald', conf.level = conf.level)

Schätzung für \(\mu\) einer Normalverteilung

\[\large X_{1}, X_{2}, \ldots, X_{n} \operatorname{mit} X_{i} \stackrel{\mathrm{iid}}{\sim} N\left(\mu, \sigma^{2}\right)\]

Punkt

Schätzfunktion:

\[\large \hat{\mu}=\bar{X}=\frac{1}{n} \sum_{i=1}^{n} X_{i}\]

Erwartungswert:

\[\large E(\bar{X}) = \mu\]

Standardfehler:

\[\large SE(\bar{X})=\sqrt{\frac{\sigma^{2}}{n}}\]

\(\hat{\mu}=\bar{X}\) ist erwartungstreu, effizient und konsistent.

Konfidenzintervall

Wahrscheinlichkeitsverteilung von \(\bar{X}\) \[\large \bar{X} \sim N\left(\mu, \frac{\sigma^{2}}{n}\right)\]

Konfidenzintervall mit Konfidenzniveau \(1-\alpha\): \[\large I\left(X_{1}, \ldots, X_{n}\right)=[U, O]=\left[\bar{X}-t_{1-\frac{\alpha}{2}} \cdot \sqrt{\frac{S^{2}}{n}}, \bar{X}+t_{1-\frac{\alpha}{2}} \cdot \sqrt{\frac{S^{2}}{n}}\right]\]

\[\large T \sim t(n-1)\]

R Code

conf.level = 0.95

vec = c(100,80,90,120)
n = length(vec)

#Punktschaetzung
x_quer = mean(vec)
x_quer

s2 = var(vec)

# Konfidenzintervall von Hand
c = qt(1-((1-conf.level)/2), df=n-1) * sqrt(s2/n)
c(x_quer-c, x_quer+c)

# Konfidenzintervall mit R Funktion
t.test(vec, conf.level=conf.level)

Schätzung für \(\sigma^{2}\) einer Normalverteilung

\[\large X_{1}, X_{2}, \ldots, X_{n} \operatorname{mit} X_{i} \stackrel{\mathrm{iid}}{\sim} N\left(\mu, \sigma^{2}\right)\]

! \(S_{emp}^{2}\) ist nicht erwartungstreu für \(\sigma^{2}\) !

Schätzfunktion:

\[\large \hat{\sigma}^{2}=S^{2}=\frac{1}{n-1} \sum_{i=1}^{n}\left(X_{i}-\bar{X}\right)^{2}\] Erwartungswert: \[\large E\left(S^{2}\right)=\sigma^{2}\]

Standardfehler: \[\large S D\left(\hat{\sigma}^{2}\right)=\sqrt{\frac{2 \sigma^{4}}{n-1}}\]

\(\hat{\sigma}^{2}=S^{2}\) ist erwartungstreu, effizient und konsistent.

R Code

vec = c(100,80,90,120)
n = length(vec)

#Punktschaetzung
var(vec)

Schätzung für \(\mu_1 - \mu_2\) einer Normalverteilung für unabhängige Stichproben

\[\large X_{11}, X_{12}, \ldots, X_{1 n_{1}} \operatorname{mit} X_{1 i} \sim N\left(\mu_{1}, \sigma^{2}\right)\] \[\large X_{21}, X_{22}, \ldots, X_{2 n_{2}} \text { mit } X_{2 i} \sim N\left(\mu_{2}, \sigma^{2}\right)\]

Punkt

Schätzfunktion:

\[\large \bar{X}_{\text {Diff }}=\bar{X}_{1}-\bar{X}_{2}\] Erwartungswert:

\[\large E\left(\bar{X}_{\text {Diff }}\right)=E\left(\bar{X}_{1}-\bar{X}_{2}\right)=\mu_{1}-\mu_{2}\]

Standardfehler:

\[\large S E\left(\bar{X}_{D i f f}\right)=\sqrt{\frac{\sigma^{2}}{n_{1}}+\frac{\sigma^{2}}{n_{2}}}\] \(\bar{X}_{Diff}\) ist erwartungstreu, effizient und konsistent (für \(n_{1} \rightarrow \infty \text { und } n_{2} \rightarrow \infty\)).

Gepoolte Varianz:

\[\large S_{\text {pool }}^{2}=\frac{\left(n_{1}-1\right) \cdot S_{1}^{2}+\left(n_{2}-1\right) \cdot S_{2}^{2}}{n_{1}+n_{2}-2}\] Sonderfall für \(n_{1}=n_{2}\):

\[\large S_{\text {pool }}^{2}=\frac{S_{1}^{2}+S_{2}^{2}}{2}\]


vec1 = c(-10,0,-20,-11,-22)
vec2 = c(0,-10,5)

# Wenn nur Werte und keine Daten vorliegen, diese Werte durch eigene ersetzen
n1 = length(vec1)
n2 = length(vec2)

s2_1 = var(vec1)
s2_2 = var(vec2)

((n1-1)*s2_1+(n2-1)*s2_2)/(n1+n2-2)

Konfidenzintervall

\[\large I\left(X_{1}, \ldots, X_{n}\right)=\left[\left(\bar{X}_{1}-\bar{X}_{2}\right)-t_{1-\frac{\alpha}{2}} \cdot \sqrt{\frac{S_{\text {pool }}^{2}}{n_{1}}+\frac{S_{\text {pool }}^{2}}{n_{2}}},\left(\bar{X}_{1}-\bar{X}_{2}\right)+t_{1-\frac{\alpha}{2}} \cdot \sqrt{\frac{S_{\text {pool }}^{2}}{n_{1}}+\frac{S_{\text {pool }}^{2}}{n_{2}}}\right]\] \[\large T \sim t\left(n_{1}+n_{2}-2\right)\]

R Code

conf.level = 0.99

vec1 = c(-10,0,-20,-11,-22)
vec2 = c(0,-10,5)

x_quer1 = mean(vec1)
x_quer2 = mean(vec2)

n1 = length(vec1)
n2 = length(vec2)

# Punktschaetzung
xdiff_quer = mean(vec1)-mean(vec2)
xdiff_quer

# Konfidenzintervall von Hand
s2_1 = var(vec1)
s2_2 = var(vec2)
s2pool = ((n1-1)*s2_1+(n2-1)*s2_2)/(n1+n2-2)

c = qt(1-((1-conf.level)/2), df = n1+n2-2) * sqrt(s2pool/n1 + s2pool/n2)

c(xdiff_quer-c, xdiff_quer+c)

# Konfidenzintervall mit R Funktion
t.test(vec1,vec2,paired=FALSE,var.equal = TRUE,conf.level=conf.level)

Schätzung für \(\mu_1 - \mu_2\) einer Normalverteilung für abhängige Stichproben

\[\large X_{i \text { Diff }}=X_{i 1}-X_{i 2}\] \[\large X_{i \text { Diff }} \stackrel{\mathrm{iid}}{\sim} N\left(\mu_{1}-\mu_{2}, \sigma_{\text {Diff }}^{2}\right)\]

Punkt

Schätzfunktion:

\[\large \bar{X}_{\text {Diff }}=\bar{X}_{1}-\bar{X}_{2}\]

Erwartungswert:

\[\large E\left(\bar{X}_{\text {Diff }}\right)=E\left(\bar{X}_{1}-\bar{X}_{2}\right)=\mu_{1}-\mu_{2}\]

Standardfehler:

\[\large S E\left(\bar{X}_{\text {Diff }}\right)=\sqrt{\frac{\sigma_{\text {Diff }}^{2}}{n}}\]

\(\bar{X}_{Diff}\) ist erwartungstreu, effizient und konsistent (für \(n\rightarrow\infty\) ).

Konfidenzintervall

\[\large I\left(X_{1}, \ldots, X_{n}\right)=\left[\left(\bar{X}_{1}-\bar{X}_{2}\right)-t_{1-\frac{\alpha}{2}} \cdot \sqrt{\frac{S_{D i f f}^{2}}{n}},\left(\bar{X}_{1}-\bar{X}_{2}\right)+t_{1-\frac{\alpha}{2}} \cdot \sqrt{\frac{S_{D i f f}^{2}}{n}}\right]\]

\[\large T \sim t(n-1)\]

R Code

conf.level = 0.99

# Muessen gleiche Laenge haben
vec1 = c(3,5,7,-9,-3)
vec2 = c(-3,-3,-4,-1,0)
n = length(vec1)

#Punkschaetzung
xdiff_quer = mean(vec1)-mean(vec2)
xdiff_quer

# Konfidenzintervall von Hand
s2diff = var(vec1-vec2)
c = qt(1-((1-conf.level)/2), df = n-1) * sqrt(s2diff/n)
c(xdiff_quer - c, xdiff_quer + c)

# Konfidenzintervall mit R Funktion
t.test(vec1,vec2,paired=TRUE,var.equal = TRUE,conf.level=conf.level)  

Hypothesentests

Formulierung: [Ein/Zwei]stichproben [t-/Binomial]test (für [abhängige/unabhängige] Stichproben) über Parameter [\(\mu\) / \(\pi\) \(/\mu_1 - \mu_2\)] für [gerichtete/ungerichtete] Hypothesen

t-Wert berechnen: Punktschätzwerte bestimmen und in die jeweilige Teststatistik einsetzen

Kritischen Bereich bestimmen:

p-Wert berechnen: t-Wert berechnen und

Parameter \(\mu\)

Teststatistik

\[\large T=\frac{\bar{X}-\mu_{0}}{\sqrt{\frac{S^{2}}{n}}} \stackrel{H_{0}}{\sim} t(n-1)\]

Einstichprobe \(\mu\) ungerichtet

\[\large \begin{array}{l} H_{0}: \mu=\mu_{0} \\ H_{1}: \mu \neq \mu_{0} \end{array}\] \[\large \left.\left.K_{T}=\right]-\infty, t_{\text {krit_links }}\right] \cup\left[t_{\text {krit_rechts }},+\infty[\right.\]


alpha = 0.005
data = c(-20,-30,-70,-10,-50)
mu0 = -10


# Hypothesentest von Hand - Wenn nur Werte gegeben sind und keine Daten, diese Variablen durch eigene Werte ersetzen 
n = length(data)
x_quer = mean(data)
s2 = var(data)

klinks = qt(alpha/2,df=n-1)
krechts = qt(1-(alpha/2),df=n-1)
paste("Krit. Bereich: ]-INF;", klinks,"] [", krechts, "; INF[", sep="")

t = (x_quer-mu0)/sqrt(s2/n)
t

p = if(t <= 0) 2*pt(t, n-1) else 2*pt(-t, n-1)
p

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

# Hypothesentest mit R Funktion - basierend auf den Datenvektoren (ignorieren, falls eigene Werte verwendet werden)
t.test(data, mu = mu0, alternative = 'two.sided')

Einstichprobe \(\mu\) linksgerichtet

\[\large \begin{array}{l} H_{0}: \mu \geq \mu_{0} \\ H_{1}: \mu<\mu_{0} \end{array}\]

\[\large \left.\left.K_{T}=\right]-\infty, t_{k r i t}\right]\]

alpha = 0.005
data = c(-20,-30,-70,-10,-50)
mu0 = -10

# Hypothesentest von Hand - Wenn nur Werte gegeben sind und keine Daten, diese Variablen durch eigene Werte ersetzen
n = length(data)
x_quer = mean(data)
s2 = var(data)

klinks = qt(alpha,df=n-1)
paste("Krit. Bereich: ] -INF;", klinks,"]", sep="")

t = (x_quer-mu0)/sqrt(s2/n)
t

p = pt(t, n-1)
p

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

# Hypothesentest mit R Funktion - basierend auf den Datenvektoren (ignorieren, falls eigene Werte verwendet werden)
t.test(data, mu = mu0, alternative = 'less')

Einstichprobe \(\mu\) rechtsgerichtet

\[ \large \begin{array}{l} H_{0}: \mu \leq \mu_{0} \\ H_{1}: \mu>\mu_{0} \end{array} \]

\[\large K_{T}=\left[t_{\text {krit }},+\infty[\right.\]

alpha = 0.005
data = c(-2,3,0,-3,1)
mu0 = 3

# Hypothesentest von Hand - Wenn nur Werte gegeben sind und keine Daten, diese Variablen durch eigene Werte ersetzen
n = length(data)
x_quer = mean(data)
s2 = var(data)

krechts = qt(1-alpha,df=n-1)
paste("Krit. Bereich: [", krechts,";INF[", sep="")

t = (x_quer-mu0)/sqrt(s2/n)
t

p = 1-pt(t, n-1)
p

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

# Hypothesentest mit R Funktion - basierend auf den Datenvektoren (ignorieren, falls eigene Werte verwendet werden)
t.test(data, mu = mu0, alternative = 'greater')

Parameter \(\pi\)

Teststatistik

\[\large T=\sum_{i=1}^{n} X_{i}\stackrel{Ho}{\sim} Bin(n,\pi_0)\]

Einstichprobe \(\pi\) ungerichtet

\[\large \begin{array}{l} H_{0}: \pi=\pi_{0} \\ H_{1}: \pi \neq \pi_{0} \end{array}\]

hits = 43
n = 100
pi0 = 0.5
  
binom.test(x=hits, n=n, p=pi0, alternative='two.sided')
Einstichprobe \(\pi\) linksseitig

\[\large \begin{array}{l} H_{0}: \pi \geq \pi_{0} \\ H_{1}: \pi<\pi_{0} \end{array}\]

hits = 43
n = 100
pi0 = 0.5
  
binom.test(x=hits, n=n, p=pi0, alternative='less')

Einstichprobe \(\pi\) rechtsseitig

\[\large \begin{array}{l} H_{0}: \pi \leq \pi_{0} \\ H_{1}: \pi>\pi_{0} \end{array}\]

Besonderheit p-Wert Berechnung:

\[p = P(T \geq t)=1-P(T<t)=1-P(T \leq t-1)=1-F(t-1)\]

hits = 66
n = 100
pi0 = 0.5
  
binom.test(x=hits, n=n, p=pi0, alternative='greater')

Parameterdifferenz \(\mu_1 - \mu_2\) unabhängig

Teststatistik

\[\large T=\frac{\left(\bar{X}_{1}-\bar{X}_{2}\right)-\mu_{0}}{\sqrt{\frac{S_{p o o l}^{2}}{n_{1}}+\frac{S_{p o o l}^{2}}{n_{2}}}}\stackrel{H_{0}}{\sim} t(n_1+n_2-2)\]

Zweistichprobe \(\mu_1 - \mu_2\) unabhängig ungerichtet

\[\large \begin{array}{l} H_{0}: \mu_{1}-\mu_{2}=\mu_{0} \\ H_{1}: \mu_{1}-\mu_{2} \neq \mu_{0} \end{array}\]

\[\large \left.\left.K_{T}=\right]-\infty, t_{\text {krit_links }}\right] \cup\left[t_{\text {krit_rechts }},+\infty[\right.\]

alpha = 0.005
data1 = c(-1,-4,-4,-3,-3)
data2 = c(-2,-4,-6)
mu0 = 0

# Hypothesentest von Hand - Wenn nur Werte gegeben sind und keine Daten, diese Variablen durch eigene Werte ersetzen
n1 = length(data1)
n2 = length(data2)
xdiff_quer = mean(data1)-mean(data2)
s2_1 = var(data1)
s2_2 = var(data2)
s2pool = ((n1-1)*s2_1+(n2-1)*s2_2)/(n1+n2-2)

klinks = qt(alpha/2,df=n1+n2-2)
krechts = qt(1-alpha/2,df=n1+n2-2)
paste("Krit. Bereich: ]-INF;", klinks,"] [", krechts, "; INF[", sep="")

t = (xdiff_quer-mu0)/sqrt(s2pool/n1 + s2pool/n2)
t

p = if(t <= 0) 2*pt(t, n1+n2-2) else 2*pt(-t, n1+n2-2)
p

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

# Hypothesentest mit R Funktion - basierend auf den Datenvektoren (ignorieren, falls eigene Werte verwendet werden)
t.test(data1, data2, mu = mu0, alternative = 'two.sided', paired = FALSE, var.equal= TRUE)

Zweistichprobe \(\mu_1 - \mu_2\) unabhängig linksgerichtet

\[\large \begin{array}{l} H_{0}: \mu_{1}-\mu_{2} \geq \mu_{0} \\ H_{1}: \mu_{1}-\mu_{2}<\mu_{0} \end{array}\]

\[\large \left.\left.K_{T}=\right]-\infty, t_{k r i t}\right]\]

alpha = 0.005
data1 = c(-1,0,-2,-1,-4)
data2 = c(2,3,1,3,3)
mu0 = 1

# Hypothesentest von Hand - Wenn nur Werte gegeben sind und keine Daten, diese Variablen durch eigene Werte ersetzen
n1 = length(data1)
n2 = length(data2)
xdiff_quer = mean(data1)-mean(data2)
s2_1 = var(data1)
s2_2 = var(data2)
s2pool = ((n1-1)*s2_1+(n2-1)*s2_2)/(n1+n2-2)

klinks = qt(alpha,df=n1+n2-2)
paste("Krit. Bereich: ] -INF;", klinks,"]", sep="")

t = (xdiff_quer-mu0)/sqrt(s2pool/n1 + s2pool/n2)
t

p = pt(t, n1+n2-2)
p

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

# Hypothesentest mit R Funktion - basierend auf den Datenvektoren (ignorieren, falls eigene Werte verwendet werden)
t.test(data1, data2, mu = mu0, alternative = 'less', paired = FALSE, var.equal= TRUE)

Zweistichprobe \(\mu_1 - \mu_2\) unabhängig rechtsgerichtet

\[\large \begin{array}{l} H_{0}: \mu_{1}-\mu_{2} \leq \mu_{0} \\ H_{1}: \mu_{1}-\mu_{2}>\mu_{0} \end{array}\]

\[\large K_{T}=\left[t_{\text {krit }},+\infty[\right.\]

alpha = 0.005
data1 = c(100,200,100,200)
data2 = c(102,202,102,202,152)
mu0 = -2

# Hypothesentest von Hand - Wenn nur Werte gegeben sind und keine Daten, diese Variablen durch eigene Werte ersetzen
n1 = length(data1)
n2 = length(data2)
xdiff_quer = mean(data1)-mean(data2)
s2_1 = var(data1)
s2_2 = var(data2)
s2pool = ((n1-1)*s2_1+(n2-1)*s2_2)/(n1+n2-2)

krechts = qt(1-alpha,df=n1+n2-2)
paste("Krit. Bereich: [", krechts,";INF[", sep="")

t = (xdiff_quer-mu0)/sqrt(s2pool/n1 + s2pool/n2)
t

p = 1-pt(t, n1+n2-2)
p

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

# Hypothesentest mit R Funktion - basierend auf den Datenvektoren (ignorieren, falls eigene Werte verwendet werden)
t.test(data1, data2, mu = mu0, alternative = 'greater', paired = FALSE, var.equal= TRUE)

Parameterdifferenz \(\mu_1 - \mu_2\) abhängig

Teststatistik

\[\large T=\frac{\left(\bar{X}_{1}-\bar{X}_{2}\right)-\mu_{0}}{\sqrt{\frac{S_{D i f f}^{2}}{n}}}\stackrel{H_{0}}{\sim} t(n-1)\]

Zweistichprobe \(\mu_1 - \mu_2\) abhängig ungerichtet

\[\large \begin{array}{l} H_{0}: \mu_{1}-\mu_{2}=\mu_{0} \\ H_{1}: \mu_{1}-\mu_{2} \neq \mu_{0} \end{array}\]

\[\large \left.\left.K_{T}=\right]-\infty, t_{\text {krit_links }}\right] \cup\left[t_{\text {krit_rechts }},+\infty[\right.\]

alpha = 0.005
data1 = c(-0.3,-0.4,0.2,0.5,0.7)
data2 = c(-0.3,0.3,0.4,0,0)
mu0 = 0

# Hypothesentest von Hand - Wenn nur Werte gegeben sind und keine Daten, diese Variablen durch eigene Werte ersetzen
n = length(data1)
xdiff_quer = mean(data1)-mean(data2)
s2diff = var(data1-data2)


klinks = qt(alpha/2,df=n-1)
krechts = qt(1-alpha/2,df=n-1)
paste("Krit. Bereich: ]-INF;", klinks,"] [", krechts, "; INF[", sep="")

t = (xdiff_quer-mu0)/sqrt(s2diff/n)
t

p = if(t <= 0) 2*pt(t, n-1) else 2*pt(-t, n-1)
p

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

# Hypothesentest mit R Funktion - basierend auf den Datenvektoren (ignorieren, falls eigene Werte verwendet werden)
t.test(data1, data2, mu = mu0, alternative = 'two.sided', paired = TRUE, var.equal= TRUE)

Zweistichprobe \(\mu_1 - \mu_2\) abhängig linksgerichtet

\[\large \begin{array}{l} H_{0}: \mu_{1}-\mu_{2} \geq \mu_{0} \\ H_{1}: \mu_{1}-\mu_{2}<\mu_{0} \end{array}\]

\[\large \left.\left.K_{T}=\right]-\infty, t_{k r i t}\right]\]

alpha = 0.005
data1 = c(-10,-20,-20,-15,-8)
data2 = c(-20,-50,-70,-80,-90)
mu0 = 10

# Hypothesentest von Hand - Wenn nur Werte gegeben sind und keine Daten, diese Variablen durch eigene Werte ersetzen
n = length(data1)
xdiff_quer = mean(data1)-mean(data2)
s2diff = var(data1-data2)

klinks = qt(alpha,df=n-1)
paste("Krit. Bereich: ] -INF;", klinks,"]", sep="")

t = (xdiff_quer-mu0)/sqrt(s2diff/n)
t

p = pt(t, n-1)
p

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

# Hypothesentest mit R Funktion - basierend auf den Datenvektoren (ignorieren, falls eigene Werte verwendet werden)
t.test(data1, data2, mu = mu0, alternative = 'less', paired = TRUE, var.equal= TRUE)

Zweistichprobe \(\mu_1 - \mu_2\) abhängig rechtsgerichtet

\[\large \begin{array}{l} H_{0}: \mu_{1}-\mu_{2} \leq \mu_{0} \\ H_{1}: \mu_{1}-\mu_{2}>\mu_{0} \end{array}\]

\[\large K_{T}=\left[t_{\text {krit }},+\infty[\right.\]

alpha = 0.005
data1 = c(11,35,14,12,2)
data2 = c(10,40,30,10,15)
mu0 = 0

# Hypothesentest von Hand - Wenn nur Werte gegeben sind und keine Daten, diese Variablen durch eigene Werte ersetzen
n = length(data1)
xdiff_quer = mean(data1)-mean(data2)
s2diff = var(data1-data2)

krechts = qt(1-alpha,df=n-1)
paste("Krit. Bereich: [", krechts,";INF[", sep="")

t = (xdiff_quer-mu0)/sqrt(s2diff/n)
t

p = 1-pt(t, n-1)
p

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

# Hypothesentest mit R Funktion - basierend auf den Datenvektoren (ignorieren, falls eigene Werte verwendet werden)
t.test(data1, data2, mu = mu0, alternative = 'greater', paired = TRUE, var.equal= TRUE)

Effektstärke und Power

Cohen’s \(\delta\) (delta)

Unabhängige Stichproben:

\[\large \delta=\frac{\mu_{1}-\mu_{2}}{\sqrt{\sigma^{2}}}\] \[\large \hat{\delta}_{W e r t}=\frac{\bar{x}_{1}-\bar{x}_{2}}{\sqrt{s_{\text {pool }}^{2}}}\]

data1 = c(0,0,-1)
data2 = c(2,0,1)

# Cohens Delta von Hand
n1 = length(data1)
n2 = length(data2)
xdiff_quer = mean(data1)-mean(data2)
s2_1 = var(data1)
s2_2 = var(data2)
s2pool = ((n1-1)*s2_1+(n2-1)*s2_2)/(n1+n2-2)

xdiff_quer/sqrt(s2pool)

# Cohens Delta mit R Funktion
library(effsize)
cohen.d(data1, data2)

Abhängige Stichproben:

\[\large \delta=\frac{\mu_{1}-\mu_{2}}{\sqrt{\sigma_{\text {Diff }}^{2}}}\]

\[\large \hat{\delta}_{W e r t}=\frac{\bar{x}_{1}-\bar{x}_{2}}{\sqrt{s_{D i f f}^{2}}}\]

data1 = c(-10,-20,-20,-15,-80)
data2 = c(-20,-50,-70,-80,-90)

# Cohens Delta mit R Funktion
library(effsize)
cohen.d(data1, data2, paired=TRUE) 

Größen:

\(\delta\) 0.2 0.5 0.8
Interpretation kleiner Effekt mittlerer Effekt großer Effekt

Konfidenzintervall für Cohen’s \(\delta\)

library(MBESS)
d_est = -0.54
n1 = 18
n2 = 18

ci.smd(smd=d_est,n.1=n1,n.2=n2,conf.level = 0.95)

Stichprobenplanung für Cohens’s \(\delta\) (Anzahl pro Gruppe)

library(MBESS)

d_guess = 0.5
conf.level = 0.95
width = 0.29


ss.aipe.smd(d_guess, conf.level, width)

Power

Wahrscheinlichkeit, dass sich die Teststatistik im kritischen Bereich realisiert, falls die \(H_1\) gilt.

  • Je größer das Signifikanzniveau, desto größer die Power.
  • Je größer die Stichprobe, desto größer die Power.
  • Je größer der wahre Effekt, desto größer die Power.

4 Faktoren wirken aufeinander: Power (\(1-\beta\)), Signifikanzniveau (\(\alpha\)), Effekt (\(\delta\)) und Stichprobengröße (n). 3 dieser Werte bestimmen jeweils den 4.

Power von Hypothesentest berechnen

Für die Berechnung der Power brauchen wir: Signifikanzniveau (\(\alpha\)), (kleinst annehmbaren) Effekt (\(\delta\)) und Stichprobengröße (n).

library(pwr)
n = 1000 # Anzahl pro Gruppe
effect = -0.2
alpha = 0.005

type = 'one.sample' # oder 'two.sample' oder 'paired'
alternative = 'less' # oder 'greater' oder 'two.sided'

pwr.t.test(n=n,d=effect,sig.level=alpha, type=type, alternative=alternative)

Stichprobenplanung für Hypothesentest

Für die Planung der Stichprobengröße brauchen wir: Gewünschte Power (\(1-\beta\)), Signifikanzniveau (\(\alpha\)), Effekt (\(\delta\))

(n ist die Anzahl an Personen pro Gruppe)

library(pwr)
desired_power = 0.8
effect = -0.2
alpha = 0.005


type = 'one.sample' # oder 'two.sample' oder 'paired' - Typ des Hypothesentests
alternative = 'less' # oder 'greater' oder 'two.sided' - Richtung der H1


pwr.t.test(power=desired_power,d=effect,sig.level=alpha, type=type, alternative=alternative)

False Discovery Rate

Anzahl falsch positiver Entscheidungen

\[\large f p=\alpha \cdot \rho \cdot N\]

Anzahl richtig positiver Entscheidungen

\[\large r p=(1-\beta) \cdot(1-\rho) \cdot N\]

False Discovery Rate

\[\large F D R=\frac{f p}{g p}=\frac{f p}{f p+r p}=\frac{\alpha \cdot \rho \cdot N}{\alpha \cdot \rho \cdot N+(1-\beta) \cdot(1-\rho) \cdot N}=\frac{\alpha \cdot \rho}{\alpha \cdot \rho+(1-\beta) \cdot(1-\rho)}\]

R Code

alpha = 0.005
power = 0.95
baserate = 0.6

FDR = (alpha*baserate)/((alpha*baserate)+(power)*(1-baserate)) 
FDR



# Anzahl der false positives und right positives unter Angabe eines N
N = 10
fp = alpha*baserate*N
fp

rp = power*(1-baserate)*N
rp

Einflussgrößen

  • FDR umso niedriger ist, je kleiner das Signifikanzniveau \(\alpha\) ist.
  • FDR umso niedriger ist, je höher die Power \(1-\beta\) ist.
  • FDR umso höher ist, je höher die Basisrate \(\rho\) ist.

Annahmen Inferenzstatistik

Relative Häufigkeit einer Messwertausprägung einer diskreten Variable in einer Population.

  • Annahmen: keine
  • Verfahren:
    • Intervallschätzung für \(\pi\)
    • Hypothesentests: Binomialtest

Mittelwert einer metrischen Variable in einer Population

  • Annahmen:
    • Das Histogramm der interessierenden Variable in der Population kann durch die Dichtefunktion einer Normalverteilung approximiert werden.
  • Verfahren:
    • Intervallschätzung für \(\mu\)
    • Hypothesentests: Einstichproben t-Test

Differenz der Mittelwerte einer metrischen Variable in zwei Population. (unabhängig)

  • Annahmen:
    • Das Histogramm der interessierenden Variable kann in beiden Populationen durch die Dichtefunktion einer Normalverteilung approximiert werden. *Die empirische Varianz der interessierenden Variable ist in beiden Populationen gleich groß.
  • Verfahren:
    • Intervallschätzung: Konfidenzintervall für \(\mu_1 - \mu_2\) bei unabhängigen Stichproben
    • Hypothesentests: Zweistichproben t-Test für unabhängige Stichproben

Differenz der Mittelwerte einer metrischen Variable in zwei Population. (abhängig)

  • Annahmen:
    • Das Histogramm der interessierenden Variable kann in beiden Populationen durch die Dichtefunktion einer Normalverteilung approximiert werden.
  • Verfahren:
    • Intervallschätzung: Konfidenzintervall für \(\mu_1 - \mu_2\) bei abhängigen Stichproben
    • Hypothesentests: Zweistichproben t-Test für abhängige Stichproben

Bei großen Stichproben können Verletzungen der Annahmen vernachlässigt werden!

.

LS0tDQp0aXRsZTogIlN0YXRpc3RpayAxIEZvcm1lbHNhbW1sdW5nICsgUiBDb2RlIg0KYXV0aG9yOiAiQWRyaWFuIFN0ZWZmYW4iDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCiAgYm9keXsNCiAgZm9udC1zaXplOiAxMXB0Ow0KfQ0KaDEsaDIsaDMsaDQsaDUgew0KICAgIG1hcmdpbi10b3A6IDMwcHg7DQogIH0NCjwvc3R5bGU+DQoNCiMjIyMjIyAoRGFua2UgYW4gRGVuaXNlIHVuZCBNYXkgZsO8cnMgS29ycmVrdHVybGVzZW4pDQoNCkRhcyBoaWVyIGlzdCBlaW5lIHNlbWktaW50ZXJha3RpdmUgRm9ybWVsc2FtbWx1bmcgw7xiZXIgYWxsZSB3aWNodGlnZW4gRm9ybWVsbiBkZXIgU3RhdGlzdGlrIDEgVm9ybGVzdW5nLiBadSBkZW4gbWVpc3RlbiBGb3JtZWxuIHVuZCBUZXN0cyBzaW5kIGVudHNwcmVjaGVuZGUgUiBCZWlzcGllbGUgenVyIEJlcmVjaG51bmcgYmVpZ2Vmw7xndCwgZGllc2UgYW0gYmVzdGVuIHBlciBDb3B5LVBhc3RlIGluIFJTdHVkaW8gZWluZsO8Z2VuIHVuZCBlaWdlbmUgV2VydGUgZWluc2V0emVuLiBBbHRlcm5hdGl2IGthbm4gZGFzIGdhbnplIE5vdGVib29rIGluIFJTdHVkaW8gYXVzZ2Vmw7xocnQgd2VyZGVuOiByZWNodHMgb2JlbiBhdWYgYENvZGUgLT4gRG93bmxvYWQgUm1kYCBrbGlja2VuIHVuZCBkaWUgaGVydW50ZXJnZWxhZGVuZSBEYXRlaSBpbiBSU3R1ZGlvIMO2ZmZuZW4uDQoNCkRvd25sb2FkIGbDvHIgT2ZmbGluZS1OdXR6dW5nOiBSZWNodHNrbGljayBpcmdlbmR3byBhdWYgZGllIFNlaXRlIC0+IGBTcGVpY2hlcm4gdW50ZXJgIC0+IGBXZWJzaXRlLCBudXIgSFRNTGAgKHdpY2h0aWcpLiBBbnNjaGxpZcOfZW5kIGRhcyBnZXNwZWljaGVydGUgRG9rdW1lbnQgZWluZmFjaCBtaXQgZGVtIEJyb3dzZXIgw7ZmZm5lbi4NCg0KRmFsbHMgenUgdW7DvGJlcnNpY2h0bGljaDogcmVjaHRzIG9iZW4gYXVmIGBDb2RlIC0+IEhpZGUgYWxsIENvZGVgIGtsaWNrZW4uDQpBbnNjaGxpZcOfZW5kIGJlaW0gZW50c3ByZWNoZW5kZW4gQWJzY2huaXR0IHJlY2h0cyBhdWYgYENvZGVgIGtsaWNrZW4sIHVtIGRpZSBwYXNzZW5kZW4gQmVmZWhsZSB3aWVkZXIgZWluenVibGVuZGVuLg0KDQpGb2xnZW5kZSBQYWtldGUgd2VyZGVuIHp1bSBBdXNmw7xocmVuIGRlciBDb2RlYmVpc3BpZWxlIGJlbsO2dGlndDoNCmBgYA0KaW5zdGFsbC5wYWNrYWdlcyhjKCJEZXNjVG9vbHMiLCAiZWZmc2l6ZSIsICJNQkVTUyIsICJwd3IiKSkNCmBgYA0KDQojIyMjIyMgW1p1csO8Y2sgenVyIEhvbWVwYWdlXShodHRwczovL2FkcmlhbnN0ZWZmYW4uY29tL2Rvd25sb2Fkcy9wc3ljaG9sb2d5KQ0KDQojIyMgSW5oYWx0c3ZlcnplaWNobmlzDQoNCiogW0Rlc2tyaXB0aXZlIFN0YXRpc3Rpa10oPCNEZXNrcmlwdGl2ZVN0YXRpc3Rpaz4pDQogICAgKiBbR3J1bmRiZWdyaWZmZV0oI0dydW5kYmVncmlmZmUpDQogICAgKiBbS292YXJpYW56IHVuZCBLb3JyZWxhdGlvbl0oI0tvdmFyaWFuelVuZEtvcnJlbGF0aW9uKQ0KKiBbV2FocnNjaGVpbmxpY2hrZWl0c3RoZW9yaWVdKDwjV2FocnNjaGVpbmxpY2hrZWl0c3RoZW9yaWU+KQ0KICAgICogW0dydW5kYmVncmlmZmVdKCNHcnVuZGJlZ3JpZmZlMikNCiAgICAqIFtLb25rcmV0ZSBXYWhyc2NoZWlubGljaGtlaXRzZnVua3Rpb25lbl0oI0tvbmtyZXRlV2FocnNjaGVpbmxpY2hrZWl0c2Z1bmt0aW9uZW4pDQogICAgKiBbWmVudHJhbGVyIEdyZW56d2VydHNhdHpdKCNaZW50cmFsZXJHcmVuendlcnRzYXR6KQ0KKiBbUGFyYW1ldGVyc2Now6R0enVuZ10oPCNQYXJhbWV0ZXJzY2jDpHR6dW5nPikNCiAgICAqIFskXHBpJF0oI3BhcmFtcGkpDQogICAgKiBbJFxtdSRdKCNwYXJhbW11KQ0KICAgICogWyRcc2lnbWEkXSgjcGFyYW1zaWdtYSkNCiAgICAqIFskXG11XzEtXG11XzIkIHVuYWJow6RuZ2lnXSgjcGFyYW11bmFiaCkNCiAgICAqIFskXG11XzEtXG11XzIkIGFiaMOkbmdpZ10oI3BhcmFtYWJoKQ0KKiBbSHlwb3RoZXNlbnRlc3RzXSgjSHlwb3RoZXNlbnRlc3RzKQ0KICAgICogWyRcbXUkXSgjaHlwb211KQ0KICAgICogWyRccGkkXSgjaHlwb3BpKQ0KICAgICogWyRcbXVfMS1cbXVfMiQgdW5hYmjDpG5naWddKCNoeXBvdW5hYmgpDQogICAgKiBbJFxtdV8xLVxtdV8yJCBhYmjDpG5naWddKCNoeXBvYWJoKQ0KKiBbRWZmZWt0c3TDpHJrZSB1bmQgUG93ZXJdKCNFZmZla3RzdMOkcmtlVW5kUG93ZXIpDQogICAgKiBbQ29oZW4ncyBEZWx0YV0oI1plbnRyYWxlckdyZW56d2VydHNhdHopDQogICAgKiBbUG93ZXJdKCNQb3dlcikNCiogW0ZhbHNlIERpc2NvdmVyeSBSYXRlXSgjRkRSKQ0KKiBbSW5mZXJlbnpzdGF0aXN0aXNjaGUgQW5uYWhtZW5dKCNJbmZBbm5haG1lbikNCg0KDQojIyBEZXNrcmlwdGl2ZSBTdGF0aXN0aWsgeyNEZXNrcmlwdGl2ZVN0YXRpc3Rpa30NCg0KIyMjIEdydW5kYmVncmlmZmUgeyNHcnVuZGJlZ3JpZmZlfQ0KDQojIyMjIEFic29sdXRlIEjDpHVmaWdrZWl0DQoNCiQkXGxhcmdlIEgoeF9qKSQkDQoNCmBgYHtyfQ0KdmVjID0gYygiQSIsIkEiLCJCIiwiQSIsIkMiLCJCIikNCnRhYmxlKHZlYykNCmBgYA0KDQojIyMjIEFic29sdXRlIGt1bW11bGllcnRlIEjDpHVmaWdrZWl0DQokJFxsYXJnZSBIX3trdW19KHhfaykgPSBcc3VtX3tqPTF9XntrfSBIKHhfaikkJA0KYGBge3J9DQp2ZWMgPSBjKCJBIiwiQSIsIkIiLCJBIiwiQyIsIkIiKQ0KY3Vtc3VtKHRhYmxlKHZlYykpDQpgYGANCg0KDQojIyMjIFJlbGF0aXZlIEjDpHVmaWdrZWl0DQoNCiQkXGxhcmdlIGgoeF9qKSA9IFxmcmFje0goeF9qKX17bn0gJCQNCg0KYGBge3J9DQp2ZWMgPSBjKCJBIiwiQSIsIkIiLCJBIiwiQyIsIkIiKQ0KcHJvcC50YWJsZSh0YWJsZSh2ZWMpKQ0KYGBgDQoNCiMjIyMgUmVsYXRpdmUga3VtbXVsaWVydGUgSMOkdWZpZ2tlaXQNCiQkXGxhcmdlIGhfe2t1bX0oeF9rKSA9IFxmcmFje0hfe2t1bX0oeF9rKX17bn0gPSBcZnJhY3tcc3VtX3tqPTF9XntrfSBIKHhfail9e259JCQNCmBgYHtyfQ0KdmVjID0gYygiQSIsIkEiLCJCIiwiQSIsIkMiLCJCIikNCmN1bXN1bShwcm9wLnRhYmxlKHRhYmxlKHZlYykpKQ0KYGBgDQoNCiMjIyMgTW9kYWx3ZXJ0DQoNCkRpZSBNZXNzd2VydGF1c3Byw6RndW5nLCBkaWUgYW0gaMOkdWZpZ3N0ZW4gYmVvYmFjaHRldCB3dXJkZS4NCg0KYGBge3J9DQp2ZWMgPSBjKCJBIiwiQSIsIkIiLCJBIiwiQyIsIkIiKQ0KbmFtZXMod2hpY2gubWF4KHRhYmxlKHZlYykpKQ0KYGBgDQoNCiMjIyMgQXJpdGhtZXRpc2NoZXMgTWl0dGVsIC8gTWVhbg0KDQpTdW1tZSBhbGxlciBNZXNzd2VydGUgZ2V0ZWlsdCBkdXJjaCBBbnphaGwgZGVyIEJlb2JhY2h0dW5nZW4uDQoNCiQkXGxhcmdlIFxiYXJ7eH0gPSBcZnJhY3sxfXtufVxzdW1fe2k9MX1ee259eF9pJCQNCg0KYGBge3J9DQp2ZWMgPSBjKDEsMiwzLDQsNSw2KQ0KbWVhbih2ZWMpDQpgYGANCg0KDQojIyMjIE1lZGlhbg0KDQooTWluZGVzdGVuZCkgNTAlIGRlciBNZXJrbWFsc3Ryw6RnZXIgaGFiZW4gZWluZW4gTWVzc3dlcnQsIGRlciBrbGVpbmVyIG9kZXIgZ2xlaWNoIGRlbSBNZWRpYW4gaXN0LiBadXIgQmVyZWNobnVuZyBtw7xzc2VuIGRpZSBNZXNzd2VydGUgaW4gYXVmc3RlaWdlbmRlciBSZWloZW5mb2xnZSBnZW9yZG5ldCBzZWluLg0KDQokJFxsYXJnZSBNZCA9IFxiZWdpbntjYXNlc30NCnhfeyhcZnJhY3tuKzF9ezJ9KX0gJlx0ZXh0e2ZhbGxzIG4gdW5nZXJhZGV9ICBcXCANClxmcmFje3hfeyhcZnJhY3tufXsyfSl9ICsgeF97KFxmcmFje259ezJ9KzEpfX17Mn0gJlx0ZXh0e2ZhbGxzIG4gZ2VyYWRlfQ0KXGVuZHtjYXNlc30kJA0KDQoNCg0KYGBge3J9DQp2ZWMgPSBjKDEsMyw0LDUsNykNCm1lZGlhbih2ZWMpDQpgYGANCg0KIyMjIyBFbXBpcmlzY2hlIFZhcmlhbnoNCg0KJCRcbGFyZ2Ugc197ZW1wfV57Mn0gPSBcZnJhY3sxfXtufVxzdW1fe2k9MX1ee259ICh4X2kgLSBcYmFye3h9KV4yJCQNCg0KYGBge3J9DQp2ZWMgPSBjKDEsMiwzLDQsNSw2LDcsMTAsMTIpDQpuID0gbGVuZ3RoKHZlYykNCigobi0xKS9uKSp2YXIodmVjKQ0KYGBgDQoNCiMjIyMgRW1waXJpc2NoZSBTdGFuZGFyZGFid2VpY2h1bmcNCg0KJCRcbGFyZ2Ugc197ZW1wfSA9IFxzcXJ0e3Nfe2VtcH1eezJ9fSA9IFxzcXJ0e1xmcmFjezF9e259XHN1bV97aT0xfV57bn0gKHhfaSAtIFxiYXJ7eH0pXjJ9JCQNCg0KYGBge3J9DQp2ZWMgPSBjKDEsMiwzLDQsNSw2LDcsMTAsMTIpDQpuID0gbGVuZ3RoKHZlYykNCnNxcnQoKChuLTEpL24pKnZhcih2ZWMpKQ0KYGBgDQoNCg0KDQojIyMjIFF1YW50aWxlDQoNCmBgYHtyfQ0KDQp2ZWMgPSBjKDEsMiwzLDQsNSw2LDcsOCw5LDEwLDExLDEyKQ0KcXVhbnRpbGUodmVjLCBwcm9icz1jKDAuMjUsMC41LDAuNzUpKQ0KDQoNCmBgYA0KDQojIyMjIEludGVycXVhcnRpbGFic3RhbmQNCg0KYGBge3J9DQoNCnZlYyA9IGMoMSwyLDMsNCw1LDYsNyw4LDksMTAsMTEsMTIpDQpJUVIodmVjLCB0eXBlPTYpDQoNCg0KYGBgDQoNCiMjIyMgQmFycGxvdA0KDQpgYGB7cn0NCnZlYyA9IGMoMSwxLDEsMiwyLDUsNSw1LDkpDQpiYXJwbG90KHRhYmxlKHZlYykpDQpgYGANCg0KDQojIyMjIEhpc3RvZ3JhbQ0KDQpgYGB7cn0NCnZlYyA9IGMoMCwxLDEsMS41LDIsMiwzLDUsNSw1KQ0KaGlzdCh2ZWMpDQpgYGANCg0KIyMjIyBCb3hwbG90DQpgYGB7cn0NCnZlYyA9IGMoMCwwLDEsMSwxLDIsMiw1LDUsNSw5LDE1KQ0KYm94cGxvdCh2ZWMpDQpgYGANCg0KIyMjIEtvdmFyaWFueiB1bmQgS29ycmVsYXRpb24geyNLb3ZhcmlhbnpVbmRLb3JyZWxhdGlvbn0NCg0KIyMjIyBLb3ZhcmlhbnogKGVtcGlyaXNjaCkNCg0KUmljaHR1bmcgZWluZXMgWnVzYW1tZW5oYW5ncy4NCg0KJCQgXGxhcmdlDQpcb3BlcmF0b3JuYW1le2Nvdn1fe2UgbSBwfSh4LCB5KT1cZnJhY3sxfXtufSBcc3VtX3tpPTF9XntufSBMX3tpfT1cZnJhY3sxfXtufSBcc3VtX3tpPTF9XntufVxsZWZ0KHhfe2l9LVxiYXJ7eH1ccmlnaHQpXGxlZnQoeV97aX0tXGJhcnt5fVxyaWdodCkNCiQkDQpTeW1tZXRyaWU6DQoNCiQkIFxsYXJnZQ0KXG9wZXJhdG9ybmFtZXtjb3Z9X3tlIG0gcH0oeCwgeSk9IFxvcGVyYXRvcm5hbWV7Y292fV97ZSBtIHB9KHksIHgpDQokJA0KDQpLb3ZhcmlhbnogbWl0IHNpY2ggc2VsYnN0IGlzdCBnbGVpY2ggZGVyIGVtcGlyaXNjaGVuIFZhcmlhbnouDQoNCiQkIFxsYXJnZQ0KXG9wZXJhdG9ybmFtZXtjb3Z9X3tlIG0gcH0oeCwgeCk9XGZyYWN7MX17bn0gXHN1bV97aT0xfV57bn1cbGVmdCh4X3tpfS1cYmFye3h9XHJpZ2h0KVxsZWZ0KHhfe2l9LVxiYXJ7eH1ccmlnaHQpPVxmcmFjezF9e259IFxzdW1fe2k9MX1ee259XGxlZnQoeF97aX0tXGJhcnt4fVxyaWdodCleezJ9PXNfe2UgbSBwfV57Mn0NCiQkDQoNClp1c2FtbWVuaGFuZyBtaXQgU3RlaWd1bmcgZGVyIEdlcmFkZW4gZHVyY2ggZGFzIFN0cmV1ZGlhZ3JhbToNCg0KJCQgXGxhcmdlDQpcb3BlcmF0b3JuYW1le2Nvdn1fe2UgbSBwfSh4LCB5KT1iIFxjZG90IHNfe3ggZSBtIHB9XnsyfQ0KJCQNCg0KYGBge3J9DQp4ID0gYygxLDIsMyw0LDUsNikNCnkgPSBjKDcsOCw5LDEwLDExLDEyKSANCg0KY292KHgseSkNCmBgYA0KDQoNCiMjIyMgei1zdGFuZGFyZGlzaWVydW5nDQoNCkRpZSBUcmFuc2Zvcm1hdGlvbiBkZXIgei1TdGFuZGFyZGlzaWVydW5nIGlzdCBmw7xyIGplZGVuIE1lc3N3ZXJ0IHNvIGRlZmluaWVydDoNCg0KJCQgXGxhcmdlDQp6X3tpfT1cZnJhY3t4X3tpfS1cYmFye3h9fXtzX3tlIG0gcH19DQokJA0KJCQgXGxhcmdlDQpcYmVnaW57YWxpZ25lZH0NClxiYXJ7en0gJj0wIFxcDQpzX3tlbXAgIHp9ICY9MQ0KXGVuZHthbGlnbmVkfQ0KJCQNCmBgYHtyfQ0KeCA9IGMoMSwyLDMsNCw1LDYpDQooeC1tZWFuKHgpKS9zcXJ0KCgobGVuZ3RoKHgpLTEpL2xlbmd0aCh4KSkqdmFyKHgpKQ0KYGBgDQoNCiMjIyMgUGVhcnNvbiBLb3JyZWxhdGlvbg0KDQokJCBcbGFyZ2UNCnJfe3ggeX09XG9wZXJhdG9ybmFtZXtjb3Z9X3tlIG0gcH1cbGVmdCh6X3t4fSwgel97eX1ccmlnaHQpPVxmcmFjezF9e259IFxzdW1fe2k9MX1ee259XGxlZnQoel97eF97aX19LVxiYXJ7en1fe3h9XHJpZ2h0KVxsZWZ0KHpfe3lfe2l9fS1cYmFye3p9X3t5fVxyaWdodCk9XGZyYWN7MX17bn0gXHN1bV97aT0xfV57bn0gel97eF97aX19IFxjZG90IHpfe3lfe2l9fSAkJA0KDQokJFxsYXJnZSA9DQpcZnJhY3sxfXtufSBcc3VtX3tpPTF9XntufVxsZWZ0KFxmcmFje3hfe2l9LVxiYXJ7eH19e3Nfe2UgbSBwIHh9fVxyaWdodClcbGVmdChcZnJhY3t5X3tpfS1cYmFye3l9fXtzX3tlIG0gcCB5fX1ccmlnaHQpPVxmcmFjezF9e259IFxmcmFje1xzdW1fe2k9MX1ee259XGxlZnQoeF97aX0tXGJhcnt4fVxyaWdodClcbGVmdCh5X3tpfS1cYmFye3l9XHJpZ2h0KX17c197ZSBtIHAgeH0gXGNkb3Qgc197ZSBtIHB9IHl9DQokJA0KU3ltbWV0cmllOg0KDQokJCBcbGFyZ2UNCnJfe3ggeX09cl97eSB4fQ0KJCQNCkRpZSBLb3JyZWxhdGlvbiBlbnRzcHJpY2h0IGRlciBTdGVpZ3VuZyBkZXIgR2VyYWRlIGR1cmNoIGRhcyBTdHJldWRpYWdyYW0NCg0KJCQgXGxhcmdlDQpyX3t4IHl9PWJfe3p9DQokJA0KQWx0ZXJuYXRpdmUgRm9ybWVsOiANCiQkIFxsYXJnZQ0Kcl97eCB5fT1cZnJhY3tcb3BlcmF0b3JuYW1le2Nvdn1fe2UgbSBwfSh4LCB5KX17U197ZSBtIHAgeH0gXGNkb3QgU197ZSBtIHB9IHl9DQokJA0KDQpgYGB7cn0NCnggPSBjKDEsMiwzLDQsNSw2KQ0KeSA9IGMoNyw4LDksMTAsMTEsMTIpICANCiAgDQpjb3IoeCx5KQ0KYGBgDQoNCiMjIFdhaHJzY2hlaW5saWNoa2VpdHN0aGVvcmllIHsjV2FocnNjaGVpbmxpY2hrZWl0c3RoZW9yaWV9DQojIyMgR3J1bmRiZWdyaWZmZSB7I0dydW5kYmVncmlmZmUyfQ0KIyMjIyBFcndhcnR1bmdzd2VydCB2b24gWnVmYWxsc3ZhcmlhYmxlbg0KDQokJCBcbGFyZ2UNCkUoWCk9XHN1bV97aj0xfV57bX0geF97an0gXGNkb3QgUFxsZWZ0KFg9eF97an1ccmlnaHQpPVxzdW1fe2o9MX1ee219IHhfe2p9IFxjZG90IGZcbGVmdCh4X3tqfVxyaWdodCkNCiQkDQpGYWxscyBkaWUgWlYgc3RldGlnIGlzdDogDQokJCBcbGFyZ2UNCkUoWCk9XGludF97LVxpbmZ0eX1eeytcaW5mdHl9IHggXGNkb3QgZih4KSBkIHgNCiQkDQoNClJlY2hlbnJlZ2VsbiBmw7xyIGRlbiBFcndhcnR1bmdzd2VydA0KJCQgXGxhcmdlDQpcYmVnaW57YXJyYXl9e2N9DQpFKGEpPWEgXFwNCkUoWCthKT1FKFgpK2EgXFwNCkUoYSBcY2RvdCBYKT1hIFxjZG90IEUoWCkgXFwNCkUoWCtZKT1FKFgpK0UoWSkgXFwNCkVcbGVmdChcc3VtX3tpPTF9XntufSBYX3tpfVxyaWdodCk9XHN1bV97aT0xfV57bn0gRVxsZWZ0KFhfe2l9XHJpZ2h0KQ0KXGVuZHthcnJheX0NCiQkDQoNCmBgYHtyfQ0KIyBFcndhcnR1bmdzd2VydCBhdXMgZ2VnZWJlbmVyIGRpc2tyZXRlciBXYWhyc2NoZWlubGljaGtlaXRzZnVua3Rpb24NCnggPSBjKC00LC0zLC0yLC0xKQ0KZnggPSBjKDAuMywwLjEsMC40LDAuMikNCg0Kc3VtKHgqZngpDQpgYGANCg0KYGBge3J9DQojIEVyd2FydHVuZ3N3ZXJ0IGF1cyBnZWdlYmVuZXIgZGlza3JldGVyIFdhaHJzY2hlaW5saWNoa2VpdHN2ZXJ0ZWlsdW5nDQp4ID0gYygtNCwzLDQsMjAsMjIpDQpGeCA9IGMoMC4xLDAuMiwwLjMsMC44LDEpDQoNCmZ4ID0gYyhGeFtbMV1dKQ0KZm9yKGkgaW4gMjpsZW5ndGgoRngpKXtmeFtpXSA9IEZ4W1tpXV0tRnhbW2ktMV1dfQ0KDQpzdW0oeCpmeCkNCmBgYA0KDQojIyMjIFZhcmlhbnogdW5kIFN0YW5kYXJkYWJ3ZWljaHVuZyB2b24gWnVmYWxsc3ZhcmlhYmxlbg0KDQpWYXJpYW56Og0KJCQgXGxhcmdlDQpcb3BlcmF0b3JuYW1le1Zhcn0oWCk9XHN1bV97aj0xfV57bX1cbGVmdCh4X3tqfS1FKFgpXHJpZ2h0KV57Mn0gXGNkb3QgUFxsZWZ0KFg9eF97an1ccmlnaHQpPVxzdW1fe2o9MX1ee219XGxlZnQoeF97an0tRShYKVxyaWdodCleezJ9IFxjZG90IGZcbGVmdCh4X3tqfVxyaWdodCkNCiQkDQpGYWxscyBkaWUgWlYgc3RldGlnIGlzdDoNCiQkIFxsYXJnZQ0KXG9wZXJhdG9ybmFtZXtWYXJ9KFgpPVxpbnRfey1caW5mdHl9XnsrXGluZnR5fSh4LUUoWCkpXnsyfSBcY2RvdCBmKHgpIGQgeA0KJCQNClN0YW5kYXJkYWJ3ZWljaHVuZzoNCg0KJCQgXGxhcmdlDQpTIEQoWCk9XHNxcnR7XG9wZXJhdG9ybmFtZXtWYXJ9KFgpfQ0KJCQNClJlY2hlbnJlZ2VsbiBmw7xyIFZhcmlhbnogdW5kIFN0YW5kYXJkYWJ3ZWljaHVuZzoNCg0KJCQgXGxhcmdlDQpcYmVnaW57YXJyYXl9e2N9DQpcb3BlcmF0b3JuYW1le1Zhcn0oWCthKT1cb3BlcmF0b3JuYW1le1Zhcn0oWCkgXFwNClMgRChYK2EpPVMgRChYKSBcXA0KXG9wZXJhdG9ybmFtZXtWYXJ9KGEgXGNkb3QgWCk9YV57Mn0gXGNkb3QgXG9wZXJhdG9ybmFtZXtWYXJ9KFgpIFxcDQpTIEQoYSBcY2RvdCBYKT1hIFxjZG90IFxvcGVyYXRvcm5hbWV7U0R9KFgpDQpcZW5ke2FycmF5fQ0KJCQNCg0KYGBge3J9DQojIFZhcmlhbnosIFN0YW5kYXJkYWJ3ZWljaHVuZyBhdXMgZ2VnZWJlbmVyIGRpc2tyZXRlciBXYWhyc2NoZWlubGljaGtlaXRzZnVua3Rpb24NCnggPSBjKC00LC0zLC0yLC0xKQ0KZnggPSBjKDAuMywwLjEsMC40LDAuMikNCg0KZSA9IHN1bSh4KmZ4KQ0KdmFyZW1wID0gc3VtKCh4LWUpKioyKmZ4KQ0KDQp2YXJlbXANCnNxcnQodmFyZW1wKQ0KDQpgYGANCmBgYHtyfQ0KIyBWYXJpYW56LCBTdGFuZGFyZGFid2VpY2h1bmcgYXVzIGdlZ2ViZW5lciBkaXNrcmV0ZXIgV2FocnNjaGVpbmxpY2hrZWl0c3ZlcnRlaWx1bmcNCnggPSBjKC00LDMsNCwyMCwyMikNCkZ4ID0gYygwLjEsMC4yLDAuMywwLjgsMSkNCg0KZnggPSBjKEZ4W1sxXV0pDQpmb3IoaSBpbiAyOmxlbmd0aChGeCkpe2Z4W2ldID0gRnhbW2ldXS1GeFtbaS0xXV19DQoNCmUgPSBzdW0oeCpmeCkNCnZhcmVtcCA9IHN1bSgoeC1lKSoqMipmeCkNCg0KdmFyZW1wDQpzcXJ0KHZhcmVtcCkNCmBgYA0KDQoNCiMjIyMgei1zdGFuZGFyZGlzaWVydW5nIHZvbiBadWZhbGxzdmFyaWFibGVuDQpBbmFsb2cgenVyIERlc2tyaXB0aXZzdGF0aXN0aWsuDQoNCiQkIFxsYXJnZQ0KWj1cZnJhY3tYLUUoWCl9e1MgRChYKX0NCiQkDQokJCBcbGFyZ2UNClxiZWdpbnthcnJheX17bH0NClxtYXRocm17RX0oWik9MCBcXA0KU0QoWik9MQ0KXGVuZHthcnJheX0NCiQkDQoNCiMjIyBLb25rcmV0ZSBXYWhyc2NoZWlubGljaGtlaXRzZnVua3Rpb25lbiB7I0tvbmtyZXRlV2FocnNjaGVpbmxpY2hrZWl0c2Z1bmt0aW9uZW59DQoNCiMjIyMgQmVybm91bGxpIFZlcnRlaWx1bmcNCg0KJCRcbGFyZ2UgWCBcc2ltIFxvcGVyYXRvcm5hbWV7QmV9KFxwaSkkJA0KDQokJFxsYXJnZSBUX3t4fT1cezAsMVx9JCQNCg0KV2FocnNjaGVpbmxpY2hrZWl0c2Z1bmt0aW9uDQokJCBcbGFyZ2UNClxiZWdpbnthcnJheX17bH0NCmYoMCk9UChYPTApPTEtXHBpIFxcDQpmKDEpPVAoWD0xKT1ccGkNClxlbmR7YXJyYXl9DQokJA0KDQokJCBcbGFyZ2UgZlxsZWZ0KHhfe2p9XHJpZ2h0KT1ccGlee3hfe2p9fSgxLVxwaSleezEteF97an19JCQNCg0KVmVydGVpbHVuZ3NmdW5rdGlvbg0KDQokJCBcbGFyZ2UNClxiZWdpbnthcnJheX17Y30NCkYoMCk9MS1ccGkgXFwNCkYoMSk9MQ0KXGVuZHthcnJheX0NCiQkDQoNCkVyd2FydHVuZ3N3ZXJ0LCBTdGFuZGFyZGFid2VpY2h1bmc6DQoNCiQkIFxsYXJnZSBFKFgpPVxwaSQkDQoNCiQkIFxsYXJnZSBTRChYKT1cc3FydHtccGkoMS1ccGkpfSQkDQoNCg0KIyMjIyBCaW5vbWlhbHZlcnRlaWx1bmcNCg0KJCRcbGFyZ2UgWCBcc2ltIEIobiwgXHBpKSQkDQokJFxsYXJnZSBUX3t4fT1cezAsMSwyLC4uLixuXH0kJA0KDQpWb3JhdXNzZXR6dW5nZW46DQoNCiQkXGxhcmdlIFhfezF9LCBYX3syfSwgXGxkb3RzLCBYX3tufSQkDQokJFxsYXJnZSBYX3tpfSBcc2ltIEJlKFxwaSkkJA0KDQokJFxsYXJnZSBYPVxzdW1fe2k9MX1ee259IFhfe2l9JCQNCg0KDQpFeGt1cnM6IEJpbm9taWFsa29lZmZpemllbnQNCg0KJCRcbGFyZ2UgXGxlZnQoXGJlZ2lue2FycmF5fXtsfQ0KbiBcXA0Kaw0KXGVuZHthcnJheX1ccmlnaHQpPVxmcmFje24gIX17ayAhKG4taykgIX0kJA0KDQpXYWhyc2NoZWlubGljaGtlaXRzZnVua3Rpb24NCg0KJCQgXGxhcmdlIGZcbGVmdCh4X3tqfVxyaWdodCk9XGxlZnQoXGJlZ2lue2FycmF5fXtsfQ0KbiBcXA0KeF97an0NClxlbmR7YXJyYXl9XHJpZ2h0KSBccGlee3hfe2p9fSgxLVxwaSlee24teF97an19JCQNCg0KDQpWZXJ0ZWlsdW5nc2Z1bmt0aW9uOg0KDQokJFxsYXJnZSBGXGxlZnQoeF97a31ccmlnaHQpPVxzdW1fe2o9MX1ee2t9IGZcbGVmdCh4X3tqfVxyaWdodCk9XHN1bV97aj0xfV57a31cbGVmdChcYmVnaW57YXJyYXl9e2x9DQpuIFxcDQp4X3tqfQ0KXGVuZHthcnJheX1ccmlnaHQpIFxwaV57eF97an19KDEtXHBpKV57bi14X3tqfX0kJA0KDQpFcndhcnR1bmdzd2VydCwgU3RhbmRhcmRhYndlaWNodW5nOg0KDQokJFxsYXJnZSBFKFgpPW4gXHBpJCQNCiQkXGxhcmdlIFMgRChYKT1cc3FydHtuIFxwaSgxLVxwaSl9JCQNClIgRnVua3Rpb25lbg0KDQpgYGB7cn0NCnAgPSAwLjUNCm4gPSAxMDANCg0KZGJpbm9tKHg9NDAsIHNpemU9biwgcHJvYj1wKSAjIFdhaHJzY2hlaW5saWNoa2VpdHNmdW5rdGlvbg0KcGJpbm9tKHE9NzAsIHNpemU9biwgcHJvYj1wKSAjIFZlcnRlaWx1bmdzZnVua3Rpb24NCnFiaW5vbShwPTAuMjUsIHNpemU9biwgcHJvYj1wKSAjIFF1YW50aWxlIA0KcmJpbm9tKG49MjAsIHNpemU9biwgcHJvYj1wKSAjIFp1ZmFsbHNnZW5lcmF0aW9uIG5hY2ggQmlub21pYWx2ZXJ0ZWlsdW5nDQpgYGANCg0KDQojIyMjIE5vcm1hbHZlcnRlaWx1bmcNCg0KJCRcbGFyZ2UgWCBcc2ltIE5cbGVmdChcbXUsIFxzaWdtYV57Mn1ccmlnaHQpJCQNCiQkXGxhcmdlIFRfe1h9PVxtYXRoYmJ7Un0kJA0KDQpXaWNodGlnZSBFaWdlbnNjaGFmdGVuOg0KDQoqIElocmUgRGljaHRlZnVua3Rpb24gaGF0IGlociBNYXhpbXVtIGFuIGRlciBTdGVsbGUgJHggPSBcbXUkDQoqIElocmUgRGljaHRlZnVua3Rpb24gaXN0IHN5bW1ldHJpc2NoIHVtICRcbXUkDQogICAgKiAkZihcbXUrYyk9ZihcbXUtYykkDQogICAgKiAkUChYIFxsZXEgXG11LWMpPVAoWCBcZ2VxIFxtdStjKSQNCiAgICAqICRQKFggXGxlcSBcbXUpPTAuNSQNCiogSmUgd2VpbGVyIHggdm9uICRcbXUkIGVudGZlcm50IGlzdCwgZGVzdG8ga2xlaW5lciBpc3QgZGllIERpY2h0ZQ0KIA0KV2FocnNjaGVpbmxpY2hrZWl0c2RpY2h0ZWZ1bmt0aW9uOg0KDQokJFxsYXJnZSBmKHgpPVxmcmFjezF9e1xzcXJ0ezIgXHBpIFxzaWdtYV57Mn19fSBcZXhwIFxsZWZ0KC1cZnJhY3sxfXsyfSBcY2RvdCBcZnJhY3soeC1cbXUpXnsyfX17XHNpZ21hXnsyfX1ccmlnaHQpJCQNCg0KRXJ3YXJ0dWduc3dlcnQsIFZhcmlhbnosIFN0YW5kYXJkYWJ3ZWljaHVuZzoNCg0KJCRcbGFyZ2UgRShYKT1cbXUkJA0KJCRcbGFyZ2UgVmFyKFgpPVxzaWdtYV4yJCQNCiQkXGxhcmdlIFNEKFgpPVxzaWdtYSQkDQpSIEZ1bmt0aW9uZW4NCg0KYGBge3J9DQptdSA9IDMNCnNpZ21hID0gMiANCg0KZG5vcm0oeD0zLCBtZWFuID0gbXUsIHNkID0gc2lnbWEpICMgV2FocnNjaGVpbmxpY2hrZWl0c2RpY2h0ZWZ1bmt0aW9uDQpwbm9ybShxPTAuNSwgbWVhbiA9IG11LCBzZCA9IHNpZ21hKSAjIFZlcnRlaWx1bmdzZnVua3Rpb24NCnFub3JtKHA9MC4yNSwgbWVhbiA9IG11LCBzZCA9IHNpZ21hKSAjIFF1YW50aWxlDQpybm9ybShuPTIwLCBtZWFuID0gbXUsIHNkID0gc2lnbWEpICMgWnVmYWxsc2dlbmVyYXRpb24gbmFjaCBOb3JtYWx2ZXJ0ZWlsdW5nDQpgYGANCg0KDQp6LXN0YW5kYXJkaXNpZXJ1bmcgKFN0YW5kYXJkbm9ybWFsdmNlcnRlaWx1bmcpOg0KDQokJFxsYXJnZSBaPVxmcmFje1gtRShYKX17UyBEKFgpfT1cZnJhY3tYLVxtdX17XHNpZ21hfSQkDQokJFxsYXJnZSBaIFxzaW0gTigwLDEpJCQNCg0KIyMjIyB0LVZlcnRlaWx1bmcNCiQkXGxhcmdlIFQgXHNpbSB0KHYpJCQNCg0KJCRcbGFyZ2UgVF97VH09XG1hdGhiYntSfSQkDQoNCg0KRXJ3YXJ0dW5nc3dlcnQgKCRcbnUkID4gMSk6DQokJFxsYXJnZSBFKFQpPTAkJA0KDQpOw7x0emxpY2hlIEVpZ2Vuc2NoYWZ0Og0KDQokJFxsYXJnZSB0X3sxLVxmcmFje1xhbHBoYX17Mn19PS10IFxmcmFje1xhbHBoYX17Mn0kJA0KDQpCZW1lcmtlOiBGw7xyIGhvaGUgbiBuw6RoZXJ0IHNpY2ggZGllIEt1cnZlIGRlciB0LVZlcnRlaWx1bmcgZGVyIGRlciBTdGFuZGFyZG5vcm1hbHZlcnRlaWx1bmcgYW4uDQoNClIgRnVua3Rpb25lbg0KDQpgYGB7cn0NCnYgPSAyNA0KDQoNCnB0KHE9MS40LCBkZj12KSAjIFZlcnRlaWx1bmdzZnVua3Rpb24NCnF0KHA9MC4yNSwgZGY9dikgIyBRdWFudGlsZQ0KDQpkdCh4PTAuMiwgZGY9dikgIyBXYWhyc2NoZWlubGljaGtlaXRzZGljaHRlZnVua3Rpb24gLSB1bmludGVyZXNzYW50DQpydChuPTIwLCBkZj12KSAjIFp1ZmFsbHNnZW5lcmF0aW9uIG5hY2ggTm9ybWFsdmVydGVpbHVuZyAtIHVuaW50ZXJlc3NhbnQNCmBgYA0KDQojIyMgWmVudHJhbGVyIEdyZW56d2VydHNhdHogeyNaZW50cmFsZXJHcmVuendlcnRzYXR6fQ0KDQpTZWllbiAkWF97MX0sIFhfezJ9LCBcbGRvdHMsIFhfe2l9LCBcbGRvdHMsIFhfe259JCBadWZhbGxzdmFyaWFibGVuIG1pdCAkWF97aX0gXHN0YWNrcmVse1x0ZXh0IHsgaWlkIH19e1xzaW19IFAkLCB3b2JlaSBQIGVpbmUgdsO2bGxpZyBiZWxpZWJpZ2UgV2FocnNjaGVpbmxpY2hrZWl0c3ZlcnRlaWx1bmcgaXN0LiBGw7xyDQoNCiQkXGxhcmdlIFpeeyp9PVxmcmFje1xiYXJ7WH0tRShcYmFye1h9KX17XHdpZGVoYXR7UyBEfShcYmFye1h9KX0kJA0KZ2lsdCBkYW5uDQoNCiQkXGxhcmdlIFxsaW0gX3tuIFxyaWdodGFycm93IFxpbmZ0eX0gUF97Wl57Kn19PU4oMCwxKSQkDQoNCmFsc28gZsO8ciBncm/Dn2VzIG4NCg0KJCRcbGFyZ2UgWl57Kn0gXHN0YWNrcmVse1xtYXRocm17YX19e1xzaW19IE4oMCwxKSQkDQoNCiMjIFBhcmFtZXRlcnNjaMOkdHp1bmcgeyNQYXJhbWV0ZXJzY2jDpHR6dW5nfQ0KDQojIyMjIE5vdGF0aW9uDQoNClBhcmFtZXRlcg0KDQoqICRcbXUkLCAkXHNpZ21hXnsyfSQsICRccGkkDQoNCkFsbGdlbWVpbmUgU2Now6R0emZ1bmt0aW9uDQoNCiogJFxoYXRcbXUkLCAkXGhhdFxzaWdtYV57Mn0kLCAkXGhhdFxwaSQNCg0KQWxsZ2VtZWluZSBTY2jDpHR6d2VydGUNCg0KKiAkXGhhdFxtdV97V2VydH0kLCAkXGhhdFxzaWdtYV57Mn1fe1dlcnR9JCwgJFxoYXRccGlfe1dlcnR9JA0KDQpLb25rcmV0ZSBTY2jDpHR6d2VydGUNCg0KKiAkXGJhcnt4fSQsICRzX3tlbXB9XnsyfSQNCg0KIyMjIyBHw7x0ZWtyaXRlcmllbiB2b24gU2Now6R0emZ1bmt0aW9uZW4NCg0KRXJ3YXJ1bmdzdHJldWUNCiQkXGxhcmdlIEUoXGhhdHtcdGhldGF9KT1cdGhldGEkJA0KU3RhbmRhcmRmZWhsZXINCiQkXGxhcmdlIFMgRShcaGF0e1x0aGV0YX0pPVMgRChcaGF0e1x0aGV0YX0pJCQNCg0KRWZmaXppZW56OiBFcndhcnR1bmdzdHJldSB1bmQga2xlaW5zdGVuIFN0YW5kYXJkZmVobGVyIGFsbGVyIGVyd2FydHVuZ3N0cmV1ZW4gU2Now6R0emZ1bmt0aW9uZW4gZsO8ciBkZW4gUGFyYW1ldGVyDQoNCktvbnNpc3Rlbno6DQokJFxsYXJnZSBcbGltIF97biBccmlnaHRhcnJvdyBcaW5mdHl9IFNFKFxoYXR7XHRoZXRhfSk9MCQkDQoNCg0KIyMjIFNjaMOkdHp1bmcgZsO8ciAkXHBpJCBlaW5lciBCZXJub3VsbGktVmVydGVpbHVuZyB7I3BhcmFtcGl9DQoNCiQkXGxhcmdlIFhfezF9LCBYX3syfSwgXGxkb3RzLCBYX3tufSBcb3BlcmF0b3JuYW1le21pdH0gWF97aX0gXHN0YWNrcmVse1xtYXRocm17aWlkfX17XHNpbX0gXG1hdGhybXtCZX0oXHBpKSQkDQoNCiMjIyMgUHVua3QNCg0KU2Now6R0emZ1bmt0aW9uOiANCg0KJCRcbGFyZ2UgXGhhdHtccGl9PVxiYXJ7WH09XGZyYWN7MX17bn0gXHN1bV97aT0xfV57bn0gWF97aX0kJA0KRXJ3YXJ0dW5nc3dlcnQ6IA0KDQokJFxsYXJnZSBFKFxoYXR7XHBpfSk9RShcYmFye1h9KSA9IFxwaSQkDQoNClN0YW5kYXJkZmVobGVyOiANCg0KJCRcbGFyZ2UgUyBFKFxoYXR7XHBpfSk9XHNxcnR7XGZyYWN7XHBpKDEtXHBpKX17bn19JCQNCg0KJFxsYXJnZSBcaGF0e1xwaX09XGJhcntYfSQgaXN0IGVyd2FydHVuZ3N0cmV1LCBlZmZpemllbnQgdW5kIGtvbnNpc3RlbnQuDQoNCiMjIyMgS29uZmlkZW56aW50ZXJ2YWxsDQoNCihBcHByb3hpbWF0aXZlcykgS29uZmlkZW56aW50ZXJ2YWxsIG1pdCBLb25maWRlbnpuaXZlYXUgJDEtXGFscGhhJDoNCiQkXGxhcmdlIElcbGVmdChYX3sxfSwgXGxkb3RzLCBYX3tufVxyaWdodCk9W1UsIE9dPVxsZWZ0W1xiYXJ7WH0tel97MS1cZnJhY3tcYWxwaGF9ezJ9fSBcY2RvdCBcc3FydHtcZnJhY3tcYmFye1h9KDEtXGJhcntYfSl9e259fSwgXGJhcntYfSt6X3sxLVxmcmFje1xhbHBoYX17Mn19IFxjZG90IFxzcXJ0e1xmcmFje1xiYXJ7WH0oMS1cYmFye1h9KX17bn19XHJpZ2h0XSQkDQokJFxsYXJnZSBaXnsqfSBcc3RhY2tyZWx7XG1hdGhybXthfX17XHNpbX0gTigwLDEpJCQNCg0KIyMjIyBSIENvZGUNCg0KYGBge3J9DQpjb25mLmxldmVsID0gMC45MA0KDQp2ZWMgPSBjKDEsMSwxLDAsMCkNCm4gPSBsZW5ndGgodmVjKQ0KDQojUHVua3RzY2hhZXR6dW5nDQp4X3F1ZXIgPSBtZWFuKHZlYykgDQp4X3F1ZXIgDQoNCiMgS29uZmlkZW56aW50ZXJ2YWxsIHZvbiBIYW5kDQpjID0gcW5vcm0oMS0oKDEtY29uZi5sZXZlbCkvMiksIG1lYW49MCxzZD0xKSAqIHNxcnQoKCh4X3F1ZXIqKDEteF9xdWVyKSkvbikpDQpjKHhfcXVlciAtIGMsIHhfcXVlciArIGMpDQoNCiMgS29uZmlkZW56aW50ZXJ2YWxsIG1pdCBSIEZ1bmt0aW9uDQpsaWJyYXJ5KERlc2NUb29scykNCkJpbm9tQ0koeF9xdWVyKm4sbixtZXRob2Q9J3dhbGQnLCBjb25mLmxldmVsID0gY29uZi5sZXZlbCkNCmBgYA0KDQoNCg0KIyMjIFNjaMOkdHp1bmcgZsO8ciAkXG11JCBlaW5lciBOb3JtYWx2ZXJ0ZWlsdW5nIHsjcGFyYW1tdX0NCg0KJCRcbGFyZ2UgWF97MX0sIFhfezJ9LCBcbGRvdHMsIFhfe259IFxvcGVyYXRvcm5hbWV7bWl0fSBYX3tpfSBcc3RhY2tyZWx7XG1hdGhybXtpaWR9fXtcc2ltfSBOXGxlZnQoXG11LCBcc2lnbWFeezJ9XHJpZ2h0KSQkDQoNCiMjIyMgUHVua3QNCg0KU2Now6R0emZ1bmt0aW9uOg0KDQokJFxsYXJnZSBcaGF0e1xtdX09XGJhcntYfT1cZnJhY3sxfXtufSBcc3VtX3tpPTF9XntufSBYX3tpfSQkDQoNCkVyd2FydHVuZ3N3ZXJ0Og0KDQokJFxsYXJnZSBFKFxiYXJ7WH0pID0gXG11JCQNCg0KU3RhbmRhcmRmZWhsZXI6DQoNCiQkXGxhcmdlIFNFKFxiYXJ7WH0pPVxzcXJ0e1xmcmFje1xzaWdtYV57Mn19e259fSQkDQoNCiRcaGF0e1xtdX09XGJhcntYfSQgaXN0IGVyd2FydHVuZ3N0cmV1LCBlZmZpemllbnQgdW5kIGtvbnNpc3RlbnQuDQoNCg0KIyMjIyBLb25maWRlbnppbnRlcnZhbGwNCg0KV2FocnNjaGVpbmxpY2hrZWl0c3ZlcnRlaWx1bmcgdm9uICRcYmFye1h9JA0KJCRcbGFyZ2UgXGJhcntYfSBcc2ltIE5cbGVmdChcbXUsIFxmcmFje1xzaWdtYV57Mn19e259XHJpZ2h0KSQkDQoNCktvbmZpZGVuemludGVydmFsbCBtaXQgS29uZmlkZW56bml2ZWF1ICQxLVxhbHBoYSQ6DQokJFxsYXJnZSBJXGxlZnQoWF97MX0sIFxsZG90cywgWF97bn1ccmlnaHQpPVtVLCBPXT1cbGVmdFtcYmFye1h9LXRfezEtXGZyYWN7XGFscGhhfXsyfX0gXGNkb3QgXHNxcnR7XGZyYWN7U157Mn19e259fSwgXGJhcntYfSt0X3sxLVxmcmFje1xhbHBoYX17Mn19IFxjZG90IFxzcXJ0e1xmcmFje1NeezJ9fXtufX1ccmlnaHRdJCQNCg0KJCRcbGFyZ2UgVCBcc2ltIHQobi0xKSQkDQoNCg0KIyMjIyBSIENvZGUgDQpgYGB7cn0NCmNvbmYubGV2ZWwgPSAwLjk1DQoNCnZlYyA9IGMoMTAwLDgwLDkwLDEyMCkNCm4gPSBsZW5ndGgodmVjKQ0KDQojUHVua3RzY2hhZXR6dW5nDQp4X3F1ZXIgPSBtZWFuKHZlYykNCnhfcXVlcg0KDQpzMiA9IHZhcih2ZWMpDQoNCiMgS29uZmlkZW56aW50ZXJ2YWxsIHZvbiBIYW5kDQpjID0gcXQoMS0oKDEtY29uZi5sZXZlbCkvMiksIGRmPW4tMSkgKiBzcXJ0KHMyL24pDQpjKHhfcXVlci1jLCB4X3F1ZXIrYykNCg0KIyBLb25maWRlbnppbnRlcnZhbGwgbWl0IFIgRnVua3Rpb24NCnQudGVzdCh2ZWMsIGNvbmYubGV2ZWw9Y29uZi5sZXZlbCkNCmBgYA0KDQoNCiMjIyBTY2jDpHR6dW5nIGbDvHIgJFxzaWdtYV57Mn0kIGVpbmVyIE5vcm1hbHZlcnRlaWx1bmcgeyNwYXJhbXNpZ21hfQ0KDQokJFxsYXJnZSBYX3sxfSwgWF97Mn0sIFxsZG90cywgWF97bn0gXG9wZXJhdG9ybmFtZXttaXR9IFhfe2l9IFxzdGFja3JlbHtcbWF0aHJte2lpZH19e1xzaW19IE5cbGVmdChcbXUsIFxzaWdtYV57Mn1ccmlnaHQpJCQNCg0KISAkU197ZW1wfV57Mn0kIGlzdCBuaWNodCBlcndhcnR1bmdzdHJldSBmw7xyICRcc2lnbWFeezJ9JCAhDQoNClNjaMOkdHpmdW5rdGlvbjoNCg0KJCRcbGFyZ2UgXGhhdHtcc2lnbWF9XnsyfT1TXnsyfT1cZnJhY3sxfXtuLTF9IFxzdW1fe2k9MX1ee259XGxlZnQoWF97aX0tXGJhcntYfVxyaWdodCleezJ9JCQNCkVyd2FydHVuZ3N3ZXJ0Og0KJCRcbGFyZ2UgRVxsZWZ0KFNeezJ9XHJpZ2h0KT1cc2lnbWFeezJ9JCQNCg0KU3RhbmRhcmRmZWhsZXI6DQokJFxsYXJnZSBTIERcbGVmdChcaGF0e1xzaWdtYX1eezJ9XHJpZ2h0KT1cc3FydHtcZnJhY3syIFxzaWdtYV57NH19e24tMX19JCQNCg0KDQokXGhhdHtcc2lnbWF9XnsyfT1TXnsyfSQgaXN0IGVyd2FydHVuZ3N0cmV1LCBlZmZpemllbnQgdW5kIGtvbnNpc3RlbnQuDQoNCiMjIyMgUiBDb2RlDQpgYGB7cn0NCnZlYyA9IGMoMTAwLDgwLDkwLDEyMCkNCm4gPSBsZW5ndGgodmVjKQ0KDQojUHVua3RzY2hhZXR6dW5nDQp2YXIodmVjKQ0KYGBgDQoNCg0KIyMjIyBTY2jDpHR6dW5nIGbDvHIgJFxtdV8xIC0gXG11XzIkIGVpbmVyIE5vcm1hbHZlcnRlaWx1bmcgZsO8ciB1bmFiaMOkbmdpZ2UgU3RpY2hwcm9iZW4geyNwYXJhbXVuYWJofQ0KJCRcbGFyZ2UgWF97MTF9LCBYX3sxMn0sIFxsZG90cywgWF97MSBuX3sxfX0gXG9wZXJhdG9ybmFtZXttaXR9IFhfezEgaX0gXHNpbSBOXGxlZnQoXG11X3sxfSwgXHNpZ21hXnsyfVxyaWdodCkkJA0KJCRcbGFyZ2UgWF97MjF9LCBYX3syMn0sIFxsZG90cywgWF97MiBuX3syfX0gXHRleHQgeyBtaXQgfSBYX3syIGl9IFxzaW0gTlxsZWZ0KFxtdV97Mn0sIFxzaWdtYV57Mn1ccmlnaHQpJCQNCg0KIyMjIyBQdW5rdA0KDQpTY2jDpHR6ZnVua3Rpb246DQoNCiQkXGxhcmdlIFxiYXJ7WH1fe1x0ZXh0IHtEaWZmIH19PVxiYXJ7WH1fezF9LVxiYXJ7WH1fezJ9JCQNCkVyd2FydHVuZ3N3ZXJ0Og0KDQokJFxsYXJnZSBFXGxlZnQoXGJhcntYfV97XHRleHQge0RpZmYgfX1ccmlnaHQpPUVcbGVmdChcYmFye1h9X3sxfS1cYmFye1h9X3syfVxyaWdodCk9XG11X3sxfS1cbXVfezJ9JCQNCg0KU3RhbmRhcmRmZWhsZXI6DQoNCiQkXGxhcmdlIFMgRVxsZWZ0KFxiYXJ7WH1fe0QgaSBmIGZ9XHJpZ2h0KT1cc3FydHtcZnJhY3tcc2lnbWFeezJ9fXtuX3sxfX0rXGZyYWN7XHNpZ21hXnsyfX17bl97Mn19fSQkDQokXGJhcntYfV97RGlmZn0kIGlzdCBlcndhcnR1bmdzdHJldSwgZWZmaXppZW50IHVuZCBrb25zaXN0ZW50IChmw7xyICRuX3sxfSBccmlnaHRhcnJvdyBcaW5mdHkgXHRleHQgeyB1bmQgfSBuX3syfSBccmlnaHRhcnJvdyBcaW5mdHkkKS4NCg0KR2Vwb29sdGUgVmFyaWFuejoNCg0KJCRcbGFyZ2UgU197XHRleHQge3Bvb2wgfX1eezJ9PVxmcmFje1xsZWZ0KG5fezF9LTFccmlnaHQpIFxjZG90IFNfezF9XnsyfStcbGVmdChuX3syfS0xXHJpZ2h0KSBcY2RvdCBTX3syfV57Mn19e25fezF9K25fezJ9LTJ9JCQNClNvbmRlcmZhbGwgZsO8ciAkbl97MX09bl97Mn0kOg0KDQokJFxsYXJnZSBTX3tcdGV4dCB7cG9vbCB9fV57Mn09XGZyYWN7U197MX1eezJ9K1NfezJ9XnsyfX17Mn0kJA0KDQoNCmBgYHtyfQ0KDQp2ZWMxID0gYygtMTAsMCwtMjAsLTExLC0yMikNCnZlYzIgPSBjKDAsLTEwLDUpDQoNCiMgV2VubiBudXIgV2VydGUgdW5kIGtlaW5lIERhdGVuIHZvcmxpZWdlbiwgZGllc2UgV2VydGUgZHVyY2ggZWlnZW5lIGVyc2V0emVuDQpuMSA9IGxlbmd0aCh2ZWMxKQ0KbjIgPSBsZW5ndGgodmVjMikNCg0KczJfMSA9IHZhcih2ZWMxKQ0KczJfMiA9IHZhcih2ZWMyKQ0KDQooKG4xLTEpKnMyXzErKG4yLTEpKnMyXzIpLyhuMStuMi0yKQ0KYGBgDQoNCg0KIyMjIyBLb25maWRlbnppbnRlcnZhbGwNCg0KJCRcbGFyZ2UgSVxsZWZ0KFhfezF9LCBcbGRvdHMsIFhfe259XHJpZ2h0KT1cbGVmdFtcbGVmdChcYmFye1h9X3sxfS1cYmFye1h9X3syfVxyaWdodCktdF97MS1cZnJhY3tcYWxwaGF9ezJ9fSBcY2RvdCBcc3FydHtcZnJhY3tTX3tcdGV4dCB7cG9vbCB9fV57Mn19e25fezF9fStcZnJhY3tTX3tcdGV4dCB7cG9vbCB9fV57Mn19e25fezJ9fX0sXGxlZnQoXGJhcntYfV97MX0tXGJhcntYfV97Mn1ccmlnaHQpK3RfezEtXGZyYWN7XGFscGhhfXsyfX0gXGNkb3QgXHNxcnR7XGZyYWN7U197XHRleHQge3Bvb2wgfX1eezJ9fXtuX3sxfX0rXGZyYWN7U197XHRleHQge3Bvb2wgfX1eezJ9fXtuX3syfX19XHJpZ2h0XSQkDQokJFxsYXJnZSBUIFxzaW0gdFxsZWZ0KG5fezF9K25fezJ9LTJccmlnaHQpJCQNCg0KIyMjIyBSIENvZGUNCg0KYGBge3J9DQpjb25mLmxldmVsID0gMC45OQ0KDQp2ZWMxID0gYygtMTAsMCwtMjAsLTExLC0yMikNCnZlYzIgPSBjKDAsLTEwLDUpDQoNCnhfcXVlcjEgPSBtZWFuKHZlYzEpDQp4X3F1ZXIyID0gbWVhbih2ZWMyKQ0KDQpuMSA9IGxlbmd0aCh2ZWMxKQ0KbjIgPSBsZW5ndGgodmVjMikNCg0KIyBQdW5rdHNjaGFldHp1bmcNCnhkaWZmX3F1ZXIgPSBtZWFuKHZlYzEpLW1lYW4odmVjMikNCnhkaWZmX3F1ZXINCg0KIyBLb25maWRlbnppbnRlcnZhbGwgdm9uIEhhbmQNCnMyXzEgPSB2YXIodmVjMSkNCnMyXzIgPSB2YXIodmVjMikNCnMycG9vbCA9ICgobjEtMSkqczJfMSsobjItMSkqczJfMikvKG4xK24yLTIpDQoNCmMgPSBxdCgxLSgoMS1jb25mLmxldmVsKS8yKSwgZGYgPSBuMStuMi0yKSAqIHNxcnQoczJwb29sL24xICsgczJwb29sL24yKQ0KDQpjKHhkaWZmX3F1ZXItYywgeGRpZmZfcXVlcitjKQ0KDQojIEtvbmZpZGVuemludGVydmFsbCBtaXQgUiBGdW5rdGlvbg0KdC50ZXN0KHZlYzEsdmVjMixwYWlyZWQ9RkFMU0UsdmFyLmVxdWFsID0gVFJVRSxjb25mLmxldmVsPWNvbmYubGV2ZWwpDQpgYGANCg0KDQoNCiMjIyBTY2jDpHR6dW5nIGbDvHIgJFxtdV8xIC0gXG11XzIkIGVpbmVyIE5vcm1hbHZlcnRlaWx1bmcgZsO8ciBhYmjDpG5naWdlIFN0aWNocHJvYmVuIHsjcGFyYW1hYmh9DQoNCiQkXGxhcmdlIFhfe2kgXHRleHQgeyBEaWZmIH19PVhfe2kgMX0tWF97aSAyfSQkDQokJFxsYXJnZSBYX3tpIFx0ZXh0IHsgRGlmZiB9fSBcc3RhY2tyZWx7XG1hdGhybXtpaWR9fXtcc2ltfSBOXGxlZnQoXG11X3sxfS1cbXVfezJ9LCBcc2lnbWFfe1x0ZXh0IHtEaWZmIH19XnsyfVxyaWdodCkkJA0KDQojIyMjIFB1bmt0DQoNClNjaMOkdHpmdW5rdGlvbjoNCg0KJCRcbGFyZ2UgXGJhcntYfV97XHRleHQge0RpZmYgfX09XGJhcntYfV97MX0tXGJhcntYfV97Mn0kJA0KDQpFcndhcnR1bmdzd2VydDoNCg0KJCRcbGFyZ2UgRVxsZWZ0KFxiYXJ7WH1fe1x0ZXh0IHtEaWZmIH19XHJpZ2h0KT1FXGxlZnQoXGJhcntYfV97MX0tXGJhcntYfV97Mn1ccmlnaHQpPVxtdV97MX0tXG11X3syfSQkDQoNClN0YW5kYXJkZmVobGVyOg0KDQokJFxsYXJnZSBTIEVcbGVmdChcYmFye1h9X3tcdGV4dCB7RGlmZiB9fVxyaWdodCk9XHNxcnR7XGZyYWN7XHNpZ21hX3tcdGV4dCB7RGlmZiB9fV57Mn19e259fSQkDQoNCiRcYmFye1h9X3tEaWZmfSQgaXN0IGVyd2FydHVuZ3N0cmV1LCBlZmZpemllbnQgdW5kIGtvbnNpc3RlbnQgKGbDvHIgJG5ccmlnaHRhcnJvd1xpbmZ0eSQgKS4NCg0KIyMjIyBLb25maWRlbnppbnRlcnZhbGwNCg0KJCRcbGFyZ2UgSVxsZWZ0KFhfezF9LCBcbGRvdHMsIFhfe259XHJpZ2h0KT1cbGVmdFtcbGVmdChcYmFye1h9X3sxfS1cYmFye1h9X3syfVxyaWdodCktdF97MS1cZnJhY3tcYWxwaGF9ezJ9fSBcY2RvdCBcc3FydHtcZnJhY3tTX3tEIGkgZiBmfV57Mn19e259fSxcbGVmdChcYmFye1h9X3sxfS1cYmFye1h9X3syfVxyaWdodCkrdF97MS1cZnJhY3tcYWxwaGF9ezJ9fSBcY2RvdCBcc3FydHtcZnJhY3tTX3tEIGkgZiBmfV57Mn19e259fVxyaWdodF0kJA0KDQokJFxsYXJnZSBUIFxzaW0gdChuLTEpJCQNCg0KIyMjIyBSIENvZGUNCg0KYGBge3J9DQpjb25mLmxldmVsID0gMC45OQ0KDQojIE11ZXNzZW4gZ2xlaWNoZSBMYWVuZ2UgaGFiZW4NCnZlYzEgPSBjKDMsNSw3LC05LC0zKQ0KdmVjMiA9IGMoLTMsLTMsLTQsLTEsMCkNCm4gPSBsZW5ndGgodmVjMSkNCg0KI1B1bmtzY2hhZXR6dW5nDQp4ZGlmZl9xdWVyID0gbWVhbih2ZWMxKS1tZWFuKHZlYzIpDQp4ZGlmZl9xdWVyDQoNCiMgS29uZmlkZW56aW50ZXJ2YWxsIHZvbiBIYW5kDQpzMmRpZmYgPSB2YXIodmVjMS12ZWMyKQ0KYyA9IHF0KDEtKCgxLWNvbmYubGV2ZWwpLzIpLCBkZiA9IG4tMSkgKiBzcXJ0KHMyZGlmZi9uKQ0KYyh4ZGlmZl9xdWVyIC0gYywgeGRpZmZfcXVlciArIGMpDQoNCiMgS29uZmlkZW56aW50ZXJ2YWxsIG1pdCBSIEZ1bmt0aW9uDQp0LnRlc3QodmVjMSx2ZWMyLHBhaXJlZD1UUlVFLHZhci5lcXVhbCA9IFRSVUUsY29uZi5sZXZlbD1jb25mLmxldmVsKSAgDQpgYGANCg0KDQojIyBIeXBvdGhlc2VudGVzdHMgeyNIeXBvdGhlc2VudGVzdHN9DQoNCiogJHtIXzB9JCBpc3Qgd2FociwgZsO8ciAke0hfMX0kIGVudHNjaGllZGVuOiBGZWhsZXIgKiplcnN0ZXIqKiBBcnQNCiogJHtIXzF9JCBpc3Qgd2FociwgZsO8ciAke0hfMH0kIGVudHNjaGllZGVuOiBGZWhsZXIgKip6d2VpdGVyKiogQXJ0DQoNCg0KKipGb3JtdWxpZXJ1bmcqKjogDQpbRWluL1p3ZWldc3RpY2hwcm9iZW4gW3QtL0Jpbm9taWFsXXRlc3QgKGbDvHIgW2FiaMOkbmdpZ2UvdW5hYmjDpG5naWdlXSBTdGljaHByb2Jlbikgw7xiZXIgUGFyYW1ldGVyIFskXG11JCAvICRccGkkICQvXG11XzEgLSBcbXVfMiRdIGbDvHIgW2dlcmljaHRldGUvdW5nZXJpY2h0ZXRlXSBIeXBvdGhlc2VuDQoNCioqdC1XZXJ0IGJlcmVjaG5lbioqOiBQdW5rdHNjaMOkdHp3ZXJ0ZSBiZXN0aW1tZW4gdW5kIGluIGRpZSBqZXdlaWxpZ2UgVGVzdHN0YXRpc3RpayBlaW5zZXR6ZW4NCg0KKipLcml0aXNjaGVuIEJlcmVpY2gqKiBiZXN0aW1tZW46DQoNCiogdW5nZXJpY2h0ZXQ6ICRQXGxlZnQoVCBcbGVxIHRfe1x0ZXh0IHtrcml0X2xpbmtzIH19XHJpZ2h0KT1GXGxlZnQodF97XHRleHQge2tyaXRfbGlua3MgfX1ccmlnaHQpPVxmcmFje1xhbHBoYX17Mn0kIHVuZCAkUFxsZWZ0KFQgXGdlcSB0X3tcdGV4dCB7a3JpdF9yZWNodHMgfX1ccmlnaHQpPTEtRlxsZWZ0KHRfe1x0ZXh0IHtrcml0X3JlY2h0cyB9fVxyaWdodCk9XGZyYWN7XGFscGhhfXsyfSQgYGtsaW5rcyA9IHF0KGFscGhhLzIsZGYpDQprcmVjaHRzID0gcXQoMS0oYWxwaGEvMiksZGYpYA0KKiBsaW5rc3NlaXRpZzogJFBcbGVmdChUIFxsZXEgdF97ayByIGkgdH1ccmlnaHQpPUZcbGVmdCh0X3trIHIgaSB0fVxyaWdodCk9XGFscGhhJCBgcXQoYWxwaGEsZGYpYA0KKiByZWNodHNzZWl0aWc6ICRQXGxlZnQoVCBcZ2VxIHRfe1x0ZXh0IHtrcml0IH19XHJpZ2h0KT0xLUZcbGVmdCh0X3tcdGV4dCB7a3JpdCB9fVxyaWdodCk9XGFscGhhJCBgcXQoMS1hbHBoYSxkZilgDQoNCioqcC1XZXJ0KiogYmVyZWNobmVuOiB0LVdlcnQgYmVyZWNobmVuIHVuZA0KDQoqIGxpbmtzc2VpdGlnOiAkUChUIFxsZXEgdCkgPSBGKHQpJCBgcHQodCwgZGYpYA0KDQoqIHJlY2h0c3NlaXRpZzogJFAoVCBcZ2VxIHQpID0gMSAtIEYodCkkIGAxLXB0KHQsIGRmKWANCg0KKiB1bmdlcmljaHRldDogJFxiZWdpbnthcnJheX17bH0NCjIgXGNkb3QgUChUIFxsZXEgdCkgXHRleHQgeyBmYWxscyB9IHQ8MCBcdGV4dCB7IGlzdCwgfSBcXA0KMiBcY2RvdCBQKFQgXGxlcS10KSBcdGV4dCB7IGZhbGxzIH0gdD4wIFx0ZXh0IHsgaXN0LiB9DQpcZW5ke2FycmF5fSQgYGlmKHQgPD0gMCkgMipwdCh0LCBkZikgZWxzZSAyKnB0KC10LCBkZilgDQoNCiMjIyBQYXJhbWV0ZXIgJFxtdSQgeyNoeXBvbXV9DQoNCiMjIyMgVGVzdHN0YXRpc3Rpaw0KDQokJFxsYXJnZSBUPVxmcmFje1xiYXJ7WH0tXG11X3swfX17XHNxcnR7XGZyYWN7U157Mn19e259fX0gXHN0YWNrcmVse0hfezB9fXtcc2ltfSB0KG4tMSkkJA0KDQojIyMjIEVpbnN0aWNocHJvYmUgJFxtdSQgKip1bmdlcmljaHRldCoqDQokJFxsYXJnZSBcYmVnaW57YXJyYXl9e2x9DQpIX3swfTogXG11PVxtdV97MH0gXFwNCkhfezF9OiBcbXUgXG5lcSBcbXVfezB9DQpcZW5ke2FycmF5fSQkDQokJFxsYXJnZSBcbGVmdC5cbGVmdC5LX3tUfT1ccmlnaHRdLVxpbmZ0eSwgdF97XHRleHQge2tyaXRfbGlua3MgfX1ccmlnaHRdIFxjdXBcbGVmdFt0X3tcdGV4dCB7a3JpdF9yZWNodHMgfX0sK1xpbmZ0eVtccmlnaHQuJCQNCg0KDQpgYGB7cn0NCg0KYWxwaGEgPSAwLjAwNQ0KZGF0YSA9IGMoLTIwLC0zMCwtNzAsLTEwLC01MCkNCm11MCA9IC0xMA0KDQoNCiMgSHlwb3RoZXNlbnRlc3Qgdm9uIEhhbmQgLSBXZW5uIG51ciBXZXJ0ZSBnZWdlYmVuIHNpbmQgdW5kIGtlaW5lIERhdGVuLCBkaWVzZSBWYXJpYWJsZW4gZHVyY2ggZWlnZW5lIFdlcnRlIGVyc2V0emVuIA0KbiA9IGxlbmd0aChkYXRhKQ0KeF9xdWVyID0gbWVhbihkYXRhKQ0KczIgPSB2YXIoZGF0YSkNCg0Ka2xpbmtzID0gcXQoYWxwaGEvMixkZj1uLTEpDQprcmVjaHRzID0gcXQoMS0oYWxwaGEvMiksZGY9bi0xKQ0KcGFzdGUoIktyaXQuIEJlcmVpY2g6IF0tSU5GOyIsIGtsaW5rcywiXSBbIiwga3JlY2h0cywgIjsgSU5GWyIsIHNlcD0iIikNCg0KdCA9ICh4X3F1ZXItbXUwKS9zcXJ0KHMyL24pDQp0DQoNCnAgPSBpZih0IDw9IDApIDIqcHQodCwgbi0xKSBlbHNlIDIqcHQoLXQsIG4tMSkNCnANCg0KaWYocCA8PSBhbHBoYSkgcHJpbnQoIkgxIGFubmVobWVuIikgZWxzZSBwcmludCgiSDAgYW5uZWhtZW4iKQ0KDQojIEh5cG90aGVzZW50ZXN0IG1pdCBSIEZ1bmt0aW9uIC0gYmFzaWVyZW5kIGF1ZiBkZW4gRGF0ZW52ZWt0b3JlbiAoaWdub3JpZXJlbiwgZmFsbHMgZWlnZW5lIFdlcnRlIHZlcndlbmRldCB3ZXJkZW4pDQp0LnRlc3QoZGF0YSwgbXUgPSBtdTAsIGFsdGVybmF0aXZlID0gJ3R3by5zaWRlZCcpDQpgYGANCg0KDQoNCiMjIyMgRWluc3RpY2hwcm9iZSAkXG11JCAqKmxpbmtzZ2VyaWNodGV0KioNCg0KJCRcbGFyZ2UgXGJlZ2lue2FycmF5fXtsfQ0KSF97MH06IFxtdSBcZ2VxIFxtdV97MH0gXFwNCkhfezF9OiBcbXU8XG11X3swfQ0KXGVuZHthcnJheX0kJA0KDQokJFxsYXJnZSBcbGVmdC5cbGVmdC5LX3tUfT1ccmlnaHRdLVxpbmZ0eSwgdF97ayByIGkgdH1ccmlnaHRdJCQNCg0KDQpgYGB7cn0NCmFscGhhID0gMC4wMDUNCmRhdGEgPSBjKC0yMCwtMzAsLTcwLC0xMCwtNTApDQptdTAgPSAtMTANCg0KIyBIeXBvdGhlc2VudGVzdCB2b24gSGFuZCAtIFdlbm4gbnVyIFdlcnRlIGdlZ2ViZW4gc2luZCB1bmQga2VpbmUgRGF0ZW4sIGRpZXNlIFZhcmlhYmxlbiBkdXJjaCBlaWdlbmUgV2VydGUgZXJzZXR6ZW4NCm4gPSBsZW5ndGgoZGF0YSkNCnhfcXVlciA9IG1lYW4oZGF0YSkNCnMyID0gdmFyKGRhdGEpDQoNCmtsaW5rcyA9IHF0KGFscGhhLGRmPW4tMSkNCnBhc3RlKCJLcml0LiBCZXJlaWNoOiBdIC1JTkY7Iiwga2xpbmtzLCJdIiwgc2VwPSIiKQ0KDQp0ID0gKHhfcXVlci1tdTApL3NxcnQoczIvbikNCnQNCg0KcCA9IHB0KHQsIG4tMSkNCnANCg0KaWYocCA8PSBhbHBoYSkgcHJpbnQoIkgxIGFubmVobWVuIikgZWxzZSBwcmludCgiSDAgYW5uZWhtZW4iKQ0KDQojIEh5cG90aGVzZW50ZXN0IG1pdCBSIEZ1bmt0aW9uIC0gYmFzaWVyZW5kIGF1ZiBkZW4gRGF0ZW52ZWt0b3JlbiAoaWdub3JpZXJlbiwgZmFsbHMgZWlnZW5lIFdlcnRlIHZlcndlbmRldCB3ZXJkZW4pDQp0LnRlc3QoZGF0YSwgbXUgPSBtdTAsIGFsdGVybmF0aXZlID0gJ2xlc3MnKQ0KDQpgYGANCg0KDQojIyMjIEVpbnN0aWNocHJvYmUgJFxtdSQgKipyZWNodHNnZXJpY2h0ZXQqKg0KDQokJCBcbGFyZ2UNClxiZWdpbnthcnJheX17bH0NCkhfezB9OiBcbXUgXGxlcSBcbXVfezB9IFxcDQpIX3sxfTogXG11PlxtdV97MH0NClxlbmR7YXJyYXl9DQokJA0KDQokJFxsYXJnZSBLX3tUfT1cbGVmdFt0X3tcdGV4dCB7a3JpdCB9fSwrXGluZnR5W1xyaWdodC4kJA0KDQpgYGB7cn0NCmFscGhhID0gMC4wMDUNCmRhdGEgPSBjKC0yLDMsMCwtMywxKQ0KbXUwID0gMw0KDQojIEh5cG90aGVzZW50ZXN0IHZvbiBIYW5kIC0gV2VubiBudXIgV2VydGUgZ2VnZWJlbiBzaW5kIHVuZCBrZWluZSBEYXRlbiwgZGllc2UgVmFyaWFibGVuIGR1cmNoIGVpZ2VuZSBXZXJ0ZSBlcnNldHplbg0KbiA9IGxlbmd0aChkYXRhKQ0KeF9xdWVyID0gbWVhbihkYXRhKQ0KczIgPSB2YXIoZGF0YSkNCg0Ka3JlY2h0cyA9IHF0KDEtYWxwaGEsZGY9bi0xKQ0KcGFzdGUoIktyaXQuIEJlcmVpY2g6IFsiLCBrcmVjaHRzLCI7SU5GWyIsIHNlcD0iIikNCg0KdCA9ICh4X3F1ZXItbXUwKS9zcXJ0KHMyL24pDQp0DQoNCnAgPSAxLXB0KHQsIG4tMSkNCnANCg0KaWYocCA8PSBhbHBoYSkgcHJpbnQoIkgxIGFubmVobWVuIikgZWxzZSBwcmludCgiSDAgYW5uZWhtZW4iKQ0KDQojIEh5cG90aGVzZW50ZXN0IG1pdCBSIEZ1bmt0aW9uIC0gYmFzaWVyZW5kIGF1ZiBkZW4gRGF0ZW52ZWt0b3JlbiAoaWdub3JpZXJlbiwgZmFsbHMgZWlnZW5lIFdlcnRlIHZlcndlbmRldCB3ZXJkZW4pDQp0LnRlc3QoZGF0YSwgbXUgPSBtdTAsIGFsdGVybmF0aXZlID0gJ2dyZWF0ZXInKQ0KYGBgDQoNCg0KDQoNCiMjIyBQYXJhbWV0ZXIgJFxwaSQgeyNoeXBvcGl9DQoNCiMjIyMjIFRlc3RzdGF0aXN0aWsNCg0KJCRcbGFyZ2UgVD1cc3VtX3tpPTF9XntufSBYX3tpfVxzdGFja3JlbHtIb317XHNpbX0gQmluKG4sXHBpXzApJCQNCg0KIyMjIyBFaW5zdGljaHByb2JlICRccGkkICoqdW5nZXJpY2h0ZXQqKg0KDQokJFxsYXJnZSBcYmVnaW57YXJyYXl9e2x9DQpIX3swfTogXHBpPVxwaV97MH0gXFwNCkhfezF9OiBccGkgXG5lcSBccGlfezB9DQpcZW5ke2FycmF5fSQkDQoNCmBgYHtyfQ0KaGl0cyA9IDQzDQpuID0gMTAwDQpwaTAgPSAwLjUNCiAgDQpiaW5vbS50ZXN0KHg9aGl0cywgbj1uLCBwPXBpMCwgYWx0ZXJuYXRpdmU9J3R3by5zaWRlZCcpDQpgYGANCg0KDQojIyMjIyBFaW5zdGljaHByb2JlICRccGkkICoqbGlua3NzZWl0aWcqKg0KDQokJFxsYXJnZSBcYmVnaW57YXJyYXl9e2x9DQpIX3swfTogXHBpIFxnZXEgXHBpX3swfSBcXA0KSF97MX06IFxwaTxccGlfezB9DQpcZW5ke2FycmF5fSQkDQoNCmBgYHtyfQ0KaGl0cyA9IDQzDQpuID0gMTAwDQpwaTAgPSAwLjUNCiAgDQpiaW5vbS50ZXN0KHg9aGl0cywgbj1uLCBwPXBpMCwgYWx0ZXJuYXRpdmU9J2xlc3MnKQ0KYGBgDQoNCiMjIyMgRWluc3RpY2hwcm9iZSAkXHBpJCAqKnJlY2h0c3NlaXRpZyoqDQoNCiQkXGxhcmdlIFxiZWdpbnthcnJheX17bH0NCkhfezB9OiBccGkgXGxlcSBccGlfezB9IFxcDQpIX3sxfTogXHBpPlxwaV97MH0NClxlbmR7YXJyYXl9JCQNCg0KQmVzb25kZXJoZWl0IHAtV2VydCBCZXJlY2hudW5nOg0KDQokJHAgPSBQKFQgXGdlcSB0KT0xLVAoVDx0KT0xLVAoVCBcbGVxIHQtMSk9MS1GKHQtMSkkJA0KDQpgYGB7cn0NCmhpdHMgPSA2Ng0KbiA9IDEwMA0KcGkwID0gMC41DQogIA0KYmlub20udGVzdCh4PWhpdHMsIG49biwgcD1waTAsIGFsdGVybmF0aXZlPSdncmVhdGVyJykNCmBgYA0KDQoNCg0KIyMjIFBhcmFtZXRlcmRpZmZlcmVueiAkXG11XzEgLSBcbXVfMiQgdW5hYmjDpG5naWcgeyNoeXBvdW5hYmh9DQoNCiMjIyMjIFRlc3RzdGF0aXN0aWsNCiQkXGxhcmdlIFQ9XGZyYWN7XGxlZnQoXGJhcntYfV97MX0tXGJhcntYfV97Mn1ccmlnaHQpLVxtdV97MH19e1xzcXJ0e1xmcmFje1Nfe3AgbyBvIGx9XnsyfX17bl97MX19K1xmcmFje1Nfe3AgbyBvIGx9XnsyfX17bl97Mn19fX1cc3RhY2tyZWx7SF97MH19e1xzaW19IHQobl8xK25fMi0yKSQkDQoNCiMjIyMgWndlaXN0aWNocHJvYmUgJFxtdV8xIC0gXG11XzIkIHVuYWJow6RuZ2lnICoqdW5nZXJpY2h0ZXQqKg0KDQokJFxsYXJnZSBcYmVnaW57YXJyYXl9e2x9DQpIX3swfTogXG11X3sxfS1cbXVfezJ9PVxtdV97MH0gXFwNCkhfezF9OiBcbXVfezF9LVxtdV97Mn0gXG5lcSBcbXVfezB9DQpcZW5ke2FycmF5fSQkDQoNCiQkXGxhcmdlIFxsZWZ0LlxsZWZ0Lktfe1R9PVxyaWdodF0tXGluZnR5LCB0X3tcdGV4dCB7a3JpdF9saW5rcyB9fVxyaWdodF0gXGN1cFxsZWZ0W3Rfe1x0ZXh0IHtrcml0X3JlY2h0cyB9fSwrXGluZnR5W1xyaWdodC4kJA0KDQpgYGB7cn0NCmFscGhhID0gMC4wMDUNCmRhdGExID0gYygtMSwtNCwtNCwtMywtMykNCmRhdGEyID0gYygtMiwtNCwtNikNCm11MCA9IDANCg0KIyBIeXBvdGhlc2VudGVzdCB2b24gSGFuZCAtIFdlbm4gbnVyIFdlcnRlIGdlZ2ViZW4gc2luZCB1bmQga2VpbmUgRGF0ZW4sIGRpZXNlIFZhcmlhYmxlbiBkdXJjaCBlaWdlbmUgV2VydGUgZXJzZXR6ZW4NCm4xID0gbGVuZ3RoKGRhdGExKQ0KbjIgPSBsZW5ndGgoZGF0YTIpDQp4ZGlmZl9xdWVyID0gbWVhbihkYXRhMSktbWVhbihkYXRhMikNCnMyXzEgPSB2YXIoZGF0YTEpDQpzMl8yID0gdmFyKGRhdGEyKQ0KczJwb29sID0gKChuMS0xKSpzMl8xKyhuMi0xKSpzMl8yKS8objErbjItMikNCg0Ka2xpbmtzID0gcXQoYWxwaGEvMixkZj1uMStuMi0yKQ0Ka3JlY2h0cyA9IHF0KDEtYWxwaGEvMixkZj1uMStuMi0yKQ0KcGFzdGUoIktyaXQuIEJlcmVpY2g6IF0tSU5GOyIsIGtsaW5rcywiXSBbIiwga3JlY2h0cywgIjsgSU5GWyIsIHNlcD0iIikNCg0KdCA9ICh4ZGlmZl9xdWVyLW11MCkvc3FydChzMnBvb2wvbjEgKyBzMnBvb2wvbjIpDQp0DQoNCnAgPSBpZih0IDw9IDApIDIqcHQodCwgbjErbjItMikgZWxzZSAyKnB0KC10LCBuMStuMi0yKQ0KcA0KDQppZihwIDw9IGFscGhhKSBwcmludCgiSDEgYW5uZWhtZW4iKSBlbHNlIHByaW50KCJIMCBhbm5laG1lbiIpDQoNCiMgSHlwb3RoZXNlbnRlc3QgbWl0IFIgRnVua3Rpb24gLSBiYXNpZXJlbmQgYXVmIGRlbiBEYXRlbnZla3RvcmVuIChpZ25vcmllcmVuLCBmYWxscyBlaWdlbmUgV2VydGUgdmVyd2VuZGV0IHdlcmRlbikNCnQudGVzdChkYXRhMSwgZGF0YTIsIG11ID0gbXUwLCBhbHRlcm5hdGl2ZSA9ICd0d28uc2lkZWQnLCBwYWlyZWQgPSBGQUxTRSwgdmFyLmVxdWFsPSBUUlVFKQ0KDQpgYGANCg0KDQojIyMjIFp3ZWlzdGljaHByb2JlICRcbXVfMSAtIFxtdV8yJCB1bmFiaMOkbmdpZyAqKmxpbmtzZ2VyaWNodGV0KioNCg0KJCRcbGFyZ2UgXGJlZ2lue2FycmF5fXtsfQ0KSF97MH06IFxtdV97MX0tXG11X3syfSBcZ2VxIFxtdV97MH0gXFwNCkhfezF9OiBcbXVfezF9LVxtdV97Mn08XG11X3swfQ0KXGVuZHthcnJheX0kJA0KDQokJFxsYXJnZSBcbGVmdC5cbGVmdC5LX3tUfT1ccmlnaHRdLVxpbmZ0eSwgdF97ayByIGkgdH1ccmlnaHRdJCQNCg0KYGBge3J9DQphbHBoYSA9IDAuMDA1DQpkYXRhMSA9IGMoLTEsMCwtMiwtMSwtNCkNCmRhdGEyID0gYygyLDMsMSwzLDMpDQptdTAgPSAxDQoNCiMgSHlwb3RoZXNlbnRlc3Qgdm9uIEhhbmQgLSBXZW5uIG51ciBXZXJ0ZSBnZWdlYmVuIHNpbmQgdW5kIGtlaW5lIERhdGVuLCBkaWVzZSBWYXJpYWJsZW4gZHVyY2ggZWlnZW5lIFdlcnRlIGVyc2V0emVuDQpuMSA9IGxlbmd0aChkYXRhMSkNCm4yID0gbGVuZ3RoKGRhdGEyKQ0KeGRpZmZfcXVlciA9IG1lYW4oZGF0YTEpLW1lYW4oZGF0YTIpDQpzMl8xID0gdmFyKGRhdGExKQ0KczJfMiA9IHZhcihkYXRhMikNCnMycG9vbCA9ICgobjEtMSkqczJfMSsobjItMSkqczJfMikvKG4xK24yLTIpDQoNCmtsaW5rcyA9IHF0KGFscGhhLGRmPW4xK24yLTIpDQpwYXN0ZSgiS3JpdC4gQmVyZWljaDogXSAtSU5GOyIsIGtsaW5rcywiXSIsIHNlcD0iIikNCg0KdCA9ICh4ZGlmZl9xdWVyLW11MCkvc3FydChzMnBvb2wvbjEgKyBzMnBvb2wvbjIpDQp0DQoNCnAgPSBwdCh0LCBuMStuMi0yKQ0KcA0KDQppZihwIDw9IGFscGhhKSBwcmludCgiSDEgYW5uZWhtZW4iKSBlbHNlIHByaW50KCJIMCBhbm5laG1lbiIpDQoNCiMgSHlwb3RoZXNlbnRlc3QgbWl0IFIgRnVua3Rpb24gLSBiYXNpZXJlbmQgYXVmIGRlbiBEYXRlbnZla3RvcmVuIChpZ25vcmllcmVuLCBmYWxscyBlaWdlbmUgV2VydGUgdmVyd2VuZGV0IHdlcmRlbikNCnQudGVzdChkYXRhMSwgZGF0YTIsIG11ID0gbXUwLCBhbHRlcm5hdGl2ZSA9ICdsZXNzJywgcGFpcmVkID0gRkFMU0UsIHZhci5lcXVhbD0gVFJVRSkNCg0KYGBgDQoNCg0KDQojIyMjIFp3ZWlzdGljaHByb2JlICRcbXVfMSAtIFxtdV8yJCB1bmFiaMOkbmdpZyAqKnJlY2h0c2dlcmljaHRldCoqDQoNCiQkXGxhcmdlIFxiZWdpbnthcnJheX17bH0NCkhfezB9OiBcbXVfezF9LVxtdV97Mn0gXGxlcSBcbXVfezB9IFxcDQpIX3sxfTogXG11X3sxfS1cbXVfezJ9PlxtdV97MH0NClxlbmR7YXJyYXl9JCQNCg0KJCRcbGFyZ2UgS197VH09XGxlZnRbdF97XHRleHQge2tyaXQgfX0sK1xpbmZ0eVtccmlnaHQuJCQNCg0KYGBge3J9DQphbHBoYSA9IDAuMDA1DQpkYXRhMSA9IGMoMTAwLDIwMCwxMDAsMjAwKQ0KZGF0YTIgPSBjKDEwMiwyMDIsMTAyLDIwMiwxNTIpDQptdTAgPSAtMg0KDQojIEh5cG90aGVzZW50ZXN0IHZvbiBIYW5kIC0gV2VubiBudXIgV2VydGUgZ2VnZWJlbiBzaW5kIHVuZCBrZWluZSBEYXRlbiwgZGllc2UgVmFyaWFibGVuIGR1cmNoIGVpZ2VuZSBXZXJ0ZSBlcnNldHplbg0KbjEgPSBsZW5ndGgoZGF0YTEpDQpuMiA9IGxlbmd0aChkYXRhMikNCnhkaWZmX3F1ZXIgPSBtZWFuKGRhdGExKS1tZWFuKGRhdGEyKQ0KczJfMSA9IHZhcihkYXRhMSkNCnMyXzIgPSB2YXIoZGF0YTIpDQpzMnBvb2wgPSAoKG4xLTEpKnMyXzErKG4yLTEpKnMyXzIpLyhuMStuMi0yKQ0KDQprcmVjaHRzID0gcXQoMS1hbHBoYSxkZj1uMStuMi0yKQ0KcGFzdGUoIktyaXQuIEJlcmVpY2g6IFsiLCBrcmVjaHRzLCI7SU5GWyIsIHNlcD0iIikNCg0KdCA9ICh4ZGlmZl9xdWVyLW11MCkvc3FydChzMnBvb2wvbjEgKyBzMnBvb2wvbjIpDQp0DQoNCnAgPSAxLXB0KHQsIG4xK24yLTIpDQpwDQoNCmlmKHAgPD0gYWxwaGEpIHByaW50KCJIMSBhbm5laG1lbiIpIGVsc2UgcHJpbnQoIkgwIGFubmVobWVuIikNCg0KIyBIeXBvdGhlc2VudGVzdCBtaXQgUiBGdW5rdGlvbiAtIGJhc2llcmVuZCBhdWYgZGVuIERhdGVudmVrdG9yZW4gKGlnbm9yaWVyZW4sIGZhbGxzIGVpZ2VuZSBXZXJ0ZSB2ZXJ3ZW5kZXQgd2VyZGVuKQ0KdC50ZXN0KGRhdGExLCBkYXRhMiwgbXUgPSBtdTAsIGFsdGVybmF0aXZlID0gJ2dyZWF0ZXInLCBwYWlyZWQgPSBGQUxTRSwgdmFyLmVxdWFsPSBUUlVFKQ0KYGBgDQoNCiMjIyBQYXJhbWV0ZXJkaWZmZXJlbnogJFxtdV8xIC0gXG11XzIkIGFiaMOkbmdpZyB7I2h5cG9hYmh9DQoNCiMjIyMgVGVzdHN0YXRpc3Rpaw0KDQokJFxsYXJnZSBUPVxmcmFje1xsZWZ0KFxiYXJ7WH1fezF9LVxiYXJ7WH1fezJ9XHJpZ2h0KS1cbXVfezB9fXtcc3FydHtcZnJhY3tTX3tEIGkgZiBmfV57Mn19e259fX1cc3RhY2tyZWx7SF97MH19e1xzaW19IHQobi0xKSQkDQoNCg0KIyMjIyBad2Vpc3RpY2hwcm9iZSAkXG11XzEgLSBcbXVfMiQgYWJow6RuZ2lnICoqdW5nZXJpY2h0ZXQqKg0KDQokJFxsYXJnZSBcYmVnaW57YXJyYXl9e2x9DQpIX3swfTogXG11X3sxfS1cbXVfezJ9PVxtdV97MH0gXFwNCkhfezF9OiBcbXVfezF9LVxtdV97Mn0gXG5lcSBcbXVfezB9DQpcZW5ke2FycmF5fSQkDQoNCiQkXGxhcmdlIFxsZWZ0LlxsZWZ0Lktfe1R9PVxyaWdodF0tXGluZnR5LCB0X3tcdGV4dCB7a3JpdF9saW5rcyB9fVxyaWdodF0gXGN1cFxsZWZ0W3Rfe1x0ZXh0IHtrcml0X3JlY2h0cyB9fSwrXGluZnR5W1xyaWdodC4kJA0KDQpgYGB7cn0NCmFscGhhID0gMC4wMDUNCmRhdGExID0gYygtMC4zLC0wLjQsMC4yLDAuNSwwLjcpDQpkYXRhMiA9IGMoLTAuMywwLjMsMC40LDAsMCkNCm11MCA9IDANCg0KIyBIeXBvdGhlc2VudGVzdCB2b24gSGFuZCAtIFdlbm4gbnVyIFdlcnRlIGdlZ2ViZW4gc2luZCB1bmQga2VpbmUgRGF0ZW4sIGRpZXNlIFZhcmlhYmxlbiBkdXJjaCBlaWdlbmUgV2VydGUgZXJzZXR6ZW4NCm4gPSBsZW5ndGgoZGF0YTEpDQp4ZGlmZl9xdWVyID0gbWVhbihkYXRhMSktbWVhbihkYXRhMikNCnMyZGlmZiA9IHZhcihkYXRhMS1kYXRhMikNCg0KDQprbGlua3MgPSBxdChhbHBoYS8yLGRmPW4tMSkNCmtyZWNodHMgPSBxdCgxLWFscGhhLzIsZGY9bi0xKQ0KcGFzdGUoIktyaXQuIEJlcmVpY2g6IF0tSU5GOyIsIGtsaW5rcywiXSBbIiwga3JlY2h0cywgIjsgSU5GWyIsIHNlcD0iIikNCg0KdCA9ICh4ZGlmZl9xdWVyLW11MCkvc3FydChzMmRpZmYvbikNCnQNCg0KcCA9IGlmKHQgPD0gMCkgMipwdCh0LCBuLTEpIGVsc2UgMipwdCgtdCwgbi0xKQ0KcA0KDQppZihwIDw9IGFscGhhKSBwcmludCgiSDEgYW5uZWhtZW4iKSBlbHNlIHByaW50KCJIMCBhbm5laG1lbiIpDQoNCiMgSHlwb3RoZXNlbnRlc3QgbWl0IFIgRnVua3Rpb24gLSBiYXNpZXJlbmQgYXVmIGRlbiBEYXRlbnZla3RvcmVuIChpZ25vcmllcmVuLCBmYWxscyBlaWdlbmUgV2VydGUgdmVyd2VuZGV0IHdlcmRlbikNCnQudGVzdChkYXRhMSwgZGF0YTIsIG11ID0gbXUwLCBhbHRlcm5hdGl2ZSA9ICd0d28uc2lkZWQnLCBwYWlyZWQgPSBUUlVFLCB2YXIuZXF1YWw9IFRSVUUpDQpgYGANCg0KDQojIyMjIFp3ZWlzdGljaHByb2JlICRcbXVfMSAtIFxtdV8yJCBhYmjDpG5naWcgKipsaW5rc2dlcmljaHRldCoqDQoNCiQkXGxhcmdlIFxiZWdpbnthcnJheX17bH0NCkhfezB9OiBcbXVfezF9LVxtdV97Mn0gXGdlcSBcbXVfezB9IFxcDQpIX3sxfTogXG11X3sxfS1cbXVfezJ9PFxtdV97MH0NClxlbmR7YXJyYXl9JCQNCg0KJCRcbGFyZ2UgXGxlZnQuXGxlZnQuS197VH09XHJpZ2h0XS1caW5mdHksIHRfe2sgciBpIHR9XHJpZ2h0XSQkDQoNCmBgYHtyfQ0KYWxwaGEgPSAwLjAwNQ0KZGF0YTEgPSBjKC0xMCwtMjAsLTIwLC0xNSwtOCkNCmRhdGEyID0gYygtMjAsLTUwLC03MCwtODAsLTkwKQ0KbXUwID0gMTANCg0KIyBIeXBvdGhlc2VudGVzdCB2b24gSGFuZCAtIFdlbm4gbnVyIFdlcnRlIGdlZ2ViZW4gc2luZCB1bmQga2VpbmUgRGF0ZW4sIGRpZXNlIFZhcmlhYmxlbiBkdXJjaCBlaWdlbmUgV2VydGUgZXJzZXR6ZW4NCm4gPSBsZW5ndGgoZGF0YTEpDQp4ZGlmZl9xdWVyID0gbWVhbihkYXRhMSktbWVhbihkYXRhMikNCnMyZGlmZiA9IHZhcihkYXRhMS1kYXRhMikNCg0Ka2xpbmtzID0gcXQoYWxwaGEsZGY9bi0xKQ0KcGFzdGUoIktyaXQuIEJlcmVpY2g6IF0gLUlORjsiLCBrbGlua3MsIl0iLCBzZXA9IiIpDQoNCnQgPSAoeGRpZmZfcXVlci1tdTApL3NxcnQoczJkaWZmL24pDQp0DQoNCnAgPSBwdCh0LCBuLTEpDQpwDQoNCmlmKHAgPD0gYWxwaGEpIHByaW50KCJIMSBhbm5laG1lbiIpIGVsc2UgcHJpbnQoIkgwIGFubmVobWVuIikNCg0KIyBIeXBvdGhlc2VudGVzdCBtaXQgUiBGdW5rdGlvbiAtIGJhc2llcmVuZCBhdWYgZGVuIERhdGVudmVrdG9yZW4gKGlnbm9yaWVyZW4sIGZhbGxzIGVpZ2VuZSBXZXJ0ZSB2ZXJ3ZW5kZXQgd2VyZGVuKQ0KdC50ZXN0KGRhdGExLCBkYXRhMiwgbXUgPSBtdTAsIGFsdGVybmF0aXZlID0gJ2xlc3MnLCBwYWlyZWQgPSBUUlVFLCB2YXIuZXF1YWw9IFRSVUUpDQpgYGANCg0KDQojIyMjIFp3ZWlzdGljaHByb2JlICRcbXVfMSAtIFxtdV8yJCBhYmjDpG5naWcgKipyZWNodHNnZXJpY2h0ZXQqKg0KDQokJFxsYXJnZSBcYmVnaW57YXJyYXl9e2x9DQpIX3swfTogXG11X3sxfS1cbXVfezJ9IFxsZXEgXG11X3swfSBcXA0KSF97MX06IFxtdV97MX0tXG11X3syfT5cbXVfezB9DQpcZW5ke2FycmF5fSQkDQoNCiQkXGxhcmdlIEtfe1R9PVxsZWZ0W3Rfe1x0ZXh0IHtrcml0IH19LCtcaW5mdHlbXHJpZ2h0LiQkDQoNCmBgYHtyfQ0KYWxwaGEgPSAwLjAwNQ0KZGF0YTEgPSBjKDExLDM1LDE0LDEyLDIpDQpkYXRhMiA9IGMoMTAsNDAsMzAsMTAsMTUpDQptdTAgPSAwDQoNCiMgSHlwb3RoZXNlbnRlc3Qgdm9uIEhhbmQgLSBXZW5uIG51ciBXZXJ0ZSBnZWdlYmVuIHNpbmQgdW5kIGtlaW5lIERhdGVuLCBkaWVzZSBWYXJpYWJsZW4gZHVyY2ggZWlnZW5lIFdlcnRlIGVyc2V0emVuDQpuID0gbGVuZ3RoKGRhdGExKQ0KeGRpZmZfcXVlciA9IG1lYW4oZGF0YTEpLW1lYW4oZGF0YTIpDQpzMmRpZmYgPSB2YXIoZGF0YTEtZGF0YTIpDQoNCmtyZWNodHMgPSBxdCgxLWFscGhhLGRmPW4tMSkNCnBhc3RlKCJLcml0LiBCZXJlaWNoOiBbIiwga3JlY2h0cywiO0lORlsiLCBzZXA9IiIpDQoNCnQgPSAoeGRpZmZfcXVlci1tdTApL3NxcnQoczJkaWZmL24pDQp0DQoNCnAgPSAxLXB0KHQsIG4tMSkNCnANCg0KaWYocCA8PSBhbHBoYSkgcHJpbnQoIkgxIGFubmVobWVuIikgZWxzZSBwcmludCgiSDAgYW5uZWhtZW4iKQ0KDQojIEh5cG90aGVzZW50ZXN0IG1pdCBSIEZ1bmt0aW9uIC0gYmFzaWVyZW5kIGF1ZiBkZW4gRGF0ZW52ZWt0b3JlbiAoaWdub3JpZXJlbiwgZmFsbHMgZWlnZW5lIFdlcnRlIHZlcndlbmRldCB3ZXJkZW4pDQp0LnRlc3QoZGF0YTEsIGRhdGEyLCBtdSA9IG11MCwgYWx0ZXJuYXRpdmUgPSAnZ3JlYXRlcicsIHBhaXJlZCA9IFRSVUUsIHZhci5lcXVhbD0gVFJVRSkNCmBgYA0KDQoNCg0KIyMgRWZmZWt0c3TDpHJrZSB1bmQgUG93ZXIgeyNFZmZla3RzdMOkcmtlVW5kUG93ZXJ9DQoNCiMjIyBDb2hlbidzICRcZGVsdGEkIChkZWx0YSkgeyNDb2hlbn0NCg0KVW5hYmjDpG5naWdlIFN0aWNocHJvYmVuOg0KDQokJFxsYXJnZSBcZGVsdGE9XGZyYWN7XG11X3sxfS1cbXVfezJ9fXtcc3FydHtcc2lnbWFeezJ9fX0kJA0KJCRcbGFyZ2UgXGhhdHtcZGVsdGF9X3tXIGUgciB0fT1cZnJhY3tcYmFye3h9X3sxfS1cYmFye3h9X3syfX17XHNxcnR7c197XHRleHQge3Bvb2wgfX1eezJ9fX0kJA0KYGBge3J9DQpkYXRhMSA9IGMoMCwwLC0xKQ0KZGF0YTIgPSBjKDIsMCwxKQ0KDQojIENvaGVucyBEZWx0YSB2b24gSGFuZA0KbjEgPSBsZW5ndGgoZGF0YTEpDQpuMiA9IGxlbmd0aChkYXRhMikNCnhkaWZmX3F1ZXIgPSBtZWFuKGRhdGExKS1tZWFuKGRhdGEyKQ0KczJfMSA9IHZhcihkYXRhMSkNCnMyXzIgPSB2YXIoZGF0YTIpDQpzMnBvb2wgPSAoKG4xLTEpKnMyXzErKG4yLTEpKnMyXzIpLyhuMStuMi0yKQ0KDQp4ZGlmZl9xdWVyL3NxcnQoczJwb29sKQ0KDQojIENvaGVucyBEZWx0YSBtaXQgUiBGdW5rdGlvbg0KbGlicmFyeShlZmZzaXplKQ0KY29oZW4uZChkYXRhMSwgZGF0YTIpDQpgYGANCg0KDQpBYmjDpG5naWdlIFN0aWNocHJvYmVuOg0KDQokJFxsYXJnZSBcZGVsdGE9XGZyYWN7XG11X3sxfS1cbXVfezJ9fXtcc3FydHtcc2lnbWFfe1x0ZXh0IHtEaWZmIH19XnsyfX19JCQNCg0KJCRcbGFyZ2UgXGhhdHtcZGVsdGF9X3tXIGUgciB0fT1cZnJhY3tcYmFye3h9X3sxfS1cYmFye3h9X3syfX17XHNxcnR7c197RCBpIGYgZn1eezJ9fX0kJA0KYGBge3J9DQpkYXRhMSA9IGMoLTEwLC0yMCwtMjAsLTE1LC04MCkNCmRhdGEyID0gYygtMjAsLTUwLC03MCwtODAsLTkwKQ0KDQojIENvaGVucyBEZWx0YSBtaXQgUiBGdW5rdGlvbg0KbGlicmFyeShlZmZzaXplKQ0KY29oZW4uZChkYXRhMSwgZGF0YTIsIHBhaXJlZD1UUlVFKSANCmBgYA0KDQoNCkdyw7bDn2VuOg0KDQp8ICRcZGVsdGEkIHwgMC4yIHwgMC41IHwgMC44IHwNCnwgLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0gfA0KfCBJbnRlcnByZXRhdGlvbnwga2xlaW5lciBFZmZla3QgfCBtaXR0bGVyZXIgRWZmZWt0IHwgZ3Jvw59lciBFZmZla3QgfA0KDQoNCiMjIyMgS29uZmlkZW56aW50ZXJ2YWxsIGbDvHIgQ29oZW4ncyAkXGRlbHRhJA0KYGBge3J9DQpsaWJyYXJ5KE1CRVNTKQ0KZF9lc3QgPSAtMC41NA0KbjEgPSAxOA0KbjIgPSAxOA0KDQpjaS5zbWQoc21kPWRfZXN0LG4uMT1uMSxuLjI9bjIsY29uZi5sZXZlbCA9IDAuOTUpDQpgYGANCg0KIyMjIyBTdGljaHByb2JlbnBsYW51bmcgZsO8ciBDb2hlbnMncyAkXGRlbHRhJCAoQW56YWhsICpwcm8gR3J1cHBlKikNCg0KYGBge3J9DQpsaWJyYXJ5KE1CRVNTKQ0KDQpkX2d1ZXNzID0gMC41DQpjb25mLmxldmVsID0gMC45NQ0Kd2lkdGggPSAwLjI5DQoNCg0Kc3MuYWlwZS5zbWQoZF9ndWVzcywgY29uZi5sZXZlbCwgd2lkdGgpDQpgYGANCg0KIyMjIFBvd2VyIHsjUG93ZXJ9DQoNCldhaHJzY2hlaW5saWNoa2VpdCwgZGFzcyBzaWNoIGRpZSBUZXN0c3RhdGlzdGlrIGltIGtyaXRpc2NoZW4gQmVyZWljaCByZWFsaXNpZXJ0LCBmYWxscyBkaWUgJEhfMSQgZ2lsdC4NCg0KKiBKZSBncsO2w59lciBkYXMgU2lnbmlmaWthbnpuaXZlYXUsIGRlc3RvIGdyw7bDn2VyIGRpZSBQb3dlci4NCiogSmUgZ3LDtsOfZXIgZGllIFN0aWNocHJvYmUsIGRlc3RvIGdyw7bDn2VyIGRpZSBQb3dlci4NCiogSmUgZ3LDtsOfZXIgZGVyIHdhaHJlIEVmZmVrdCwgZGVzdG8gZ3LDtsOfZXIgZGllIFBvd2VyLg0KDQo0IEZha3RvcmVuIHdpcmtlbiBhdWZlaW5hbmRlcjogUG93ZXIgKCQxLVxiZXRhJCksIFNpZ25pZmlrYW56bml2ZWF1ICgkXGFscGhhJCksIEVmZmVrdCAoJFxkZWx0YSQpIHVuZCBTdGljaHByb2Jlbmdyw7bDn2UgKG4pLiAzIGRpZXNlciBXZXJ0ZSBiZXN0aW1tZW4gamV3ZWlscyBkZW4gNC4NCg0KIyMjIyBQb3dlciB2b24gSHlwb3RoZXNlbnRlc3QgYmVyZWNobmVuDQpGw7xyIGRpZSBCZXJlY2hudW5nIGRlciBQb3dlciBicmF1Y2hlbiB3aXI6IFNpZ25pZmlrYW56bml2ZWF1ICgkXGFscGhhJCksIChrbGVpbnN0IGFubmVobWJhcmVuKSBFZmZla3QgKCRcZGVsdGEkKSB1bmQgU3RpY2hwcm9iZW5ncsO2w59lIChuKS4NCg0KYGBge3J9DQpsaWJyYXJ5KHB3cikNCm4gPSAxMDAwICMgQW56YWhsIHBybyBHcnVwcGUNCmVmZmVjdCA9IC0wLjINCmFscGhhID0gMC4wMDUNCg0KdHlwZSA9ICdvbmUuc2FtcGxlJyAjIG9kZXIgJ3R3by5zYW1wbGUnIG9kZXIgJ3BhaXJlZCcNCmFsdGVybmF0aXZlID0gJ2xlc3MnICMgb2RlciAnZ3JlYXRlcicgb2RlciAndHdvLnNpZGVkJw0KDQpwd3IudC50ZXN0KG49bixkPWVmZmVjdCxzaWcubGV2ZWw9YWxwaGEsIHR5cGU9dHlwZSwgYWx0ZXJuYXRpdmU9YWx0ZXJuYXRpdmUpDQpgYGANCg0KIyMjIyBTdGljaHByb2JlbnBsYW51bmcgZsO8ciBIeXBvdGhlc2VudGVzdA0KDQpGw7xyIGRpZSBQbGFudW5nIGRlciBTdGljaHByb2Jlbmdyw7bDn2UgYnJhdWNoZW4gd2lyOiBHZXfDvG5zY2h0ZSBQb3dlciAoJDEtXGJldGEkKSwgU2lnbmlmaWthbnpuaXZlYXUgKCRcYWxwaGEkKSwgRWZmZWt0ICgkXGRlbHRhJCkNCg0KKG4gaXN0IGRpZSBBbnphaGwgYW4gUGVyc29uZW4gcHJvIEdydXBwZSkNCg0KYGBge3J9DQpsaWJyYXJ5KHB3cikNCmRlc2lyZWRfcG93ZXIgPSAwLjgNCmVmZmVjdCA9IC0wLjINCmFscGhhID0gMC4wMDUNCg0KDQp0eXBlID0gJ29uZS5zYW1wbGUnICMgb2RlciAndHdvLnNhbXBsZScgb2RlciAncGFpcmVkJyAtIFR5cCBkZXMgSHlwb3RoZXNlbnRlc3RzDQphbHRlcm5hdGl2ZSA9ICdsZXNzJyAjIG9kZXIgJ2dyZWF0ZXInIG9kZXIgJ3R3by5zaWRlZCcgLSBSaWNodHVuZyBkZXIgSDENCg0KDQpwd3IudC50ZXN0KHBvd2VyPWRlc2lyZWRfcG93ZXIsZD1lZmZlY3Qsc2lnLmxldmVsPWFscGhhLCB0eXBlPXR5cGUsIGFsdGVybmF0aXZlPWFsdGVybmF0aXZlKQ0KYGBgDQoNCg0KDQojIyBGYWxzZSBEaXNjb3ZlcnkgUmF0ZSB7I0ZEUn0NCg0KKiBFcyB3ZXJkZW4gTiBTdHVkaWVuIGJldHJhY2h0ZXQuDQoqIEFsbGUgZsO8aHJlbiBzdGF0aXN0aXNjaGUgSHlwb3RoZXNlbnRlc3RzIG1pdCBkZW0gU2lnbmlmaWthbnpuaXZlYXUgJFxhbHBoYSQgZHVyY2gNCiogJFxyaG8kIGlzdCBkZXIgQW50ZWlsIGRlciBTdHVkaWVuLCBpbiBkZW5lbiBkaWUgJEhfMCQgd2FociBpc3QuIChCYXNpc3JhdGUpDQoqIEFsbGUgSHlwb3RoZXNlbnRlc3RzIGhhYmVuIGVpbmUgUG93ZXIgdm9uICQoMS1cYmV0YSkkDQoNCiMjIyMgQW56YWhsIGZhbHNjaCBwb3NpdGl2ZXIgRW50c2NoZWlkdW5nZW4NCg0KJCRcbGFyZ2UgZiBwPVxhbHBoYSBcY2RvdCBccmhvIFxjZG90IE4kJA0KDQojIyMgQW56YWhsIHJpY2h0aWcgcG9zaXRpdmVyIEVudHNjaGVpZHVuZ2VuDQoNCiQkXGxhcmdlIHIgcD0oMS1cYmV0YSkgXGNkb3QoMS1ccmhvKSBcY2RvdCBOJCQNCg0KIyMjIEZhbHNlIERpc2NvdmVyeSBSYXRlDQoNCiQkXGxhcmdlIEYgRCBSPVxmcmFje2YgcH17ZyBwfT1cZnJhY3tmIHB9e2YgcCtyIHB9PVxmcmFje1xhbHBoYSBcY2RvdCBccmhvIFxjZG90IE59e1xhbHBoYSBcY2RvdCBccmhvIFxjZG90IE4rKDEtXGJldGEpIFxjZG90KDEtXHJobykgXGNkb3QgTn09XGZyYWN7XGFscGhhIFxjZG90IFxyaG99e1xhbHBoYSBcY2RvdCBccmhvKygxLVxiZXRhKSBcY2RvdCgxLVxyaG8pfSQkDQoNCiMjIyBSIENvZGUNCmBgYHtyfQ0KYWxwaGEgPSAwLjAwNQ0KcG93ZXIgPSAwLjk1DQpiYXNlcmF0ZSA9IDAuNg0KDQpGRFIgPSAoYWxwaGEqYmFzZXJhdGUpLygoYWxwaGEqYmFzZXJhdGUpKyhwb3dlcikqKDEtYmFzZXJhdGUpKSANCkZEUg0KDQoNCg0KIyBBbnphaGwgZGVyIGZhbHNlIHBvc2l0aXZlcyB1bmQgcmlnaHQgcG9zaXRpdmVzIHVudGVyIEFuZ2FiZSBlaW5lcyBODQpOID0gMTANCmZwID0gYWxwaGEqYmFzZXJhdGUqTg0KZnANCg0KcnAgPSBwb3dlciooMS1iYXNlcmF0ZSkqTg0KcnANCmBgYA0KDQojIyMgRWluZmx1c3NncsO2w59lbg0KDQoqIEZEUiB1bXNvIG5pZWRyaWdlciBpc3QsIGplIGtsZWluZXIgZGFzIFNpZ25pZmlrYW56bml2ZWF1ICRcYWxwaGEkIGlzdC4NCiogRkRSIHVtc28gbmllZHJpZ2VyIGlzdCwgamUgaMO2aGVyIGRpZSBQb3dlciAkMS1cYmV0YSQgaXN0Lg0KKiBGRFIgdW1zbyBow7ZoZXIgaXN0LCBqZSBow7ZoZXIgZGllIEJhc2lzcmF0ZSAkXHJobyQgaXN0Lg0KDQoNCg0KIyMgQW5uYWhtZW4gSW5mZXJlbnpzdGF0aXN0aWsgeyNJbmZBbm5haG1lbn0NCg0KIyMjIyBSZWxhdGl2ZSBIw6R1Zmlna2VpdCBlaW5lciBNZXNzd2VydGF1c3Byw6RndW5nIGVpbmVyIGRpc2tyZXRlbiBWYXJpYWJsZSBpbiBlaW5lciBQb3B1bGF0aW9uLg0KDQoqIEFubmFobWVuOiBrZWluZQ0KKiBWZXJmYWhyZW46IA0KICAgICogSW50ZXJ2YWxsc2Now6R0enVuZyBmw7xyICRccGkkDQogICAgKiBIeXBvdGhlc2VudGVzdHM6IEJpbm9taWFsdGVzdA0KICAgIA0KDQojIyMjIE1pdHRlbHdlcnQgZWluZXIgbWV0cmlzY2hlbiBWYXJpYWJsZSBpbiBlaW5lciBQb3B1bGF0aW9uDQoNCiogQW5uYWhtZW46IA0KICAgICogRGFzIEhpc3RvZ3JhbW0gZGVyIGludGVyZXNzaWVyZW5kZW4gVmFyaWFibGUgaW4gZGVyIFBvcHVsYXRpb24ga2FubiBkdXJjaCBkaWUgRGljaHRlZnVua3Rpb24gZWluZXIgTm9ybWFsdmVydGVpbHVuZyBhcHByb3hpbWllcnQgd2VyZGVuLg0KKiBWZXJmYWhyZW46IA0KICAgICogSW50ZXJ2YWxsc2Now6R0enVuZyBmw7xyICRcbXUkDQogICAgKiBIeXBvdGhlc2VudGVzdHM6IEVpbnN0aWNocHJvYmVuIHQtVGVzdA0KIA0KICAgIA0KIyMjIyBEaWZmZXJlbnogZGVyIE1pdHRlbHdlcnRlIGVpbmVyIG1ldHJpc2NoZW4gVmFyaWFibGUgaW4gendlaSBQb3B1bGF0aW9uLiAodW5hYmjDpG5naWcpDQoNCiogQW5uYWhtZW46IA0KICAgICogRGFzIEhpc3RvZ3JhbW0gZGVyIGludGVyZXNzaWVyZW5kZW4gVmFyaWFibGUga2FubiBpbiBiZWlkZW4gUG9wdWxhdGlvbmVuIGR1cmNoIGRpZSBEaWNodGVmdW5rdGlvbiBlaW5lciBOb3JtYWx2ZXJ0ZWlsdW5nIGFwcHJveGltaWVydCB3ZXJkZW4uDQogICAgKkRpZSBlbXBpcmlzY2hlIFZhcmlhbnogZGVyIGludGVyZXNzaWVyZW5kZW4gVmFyaWFibGUgaXN0IGluIGJlaWRlbiBQb3B1bGF0aW9uZW4gZ2xlaWNoIGdyb8OfLg0KKiBWZXJmYWhyZW46IA0KICAgICogSW50ZXJ2YWxsc2Now6R0enVuZzogS29uZmlkZW56aW50ZXJ2YWxsIGbDvHIgJFxtdV8xIC0gXG11XzIkIGJlaSB1bmFiaMOkbmdpZ2VuIFN0aWNocHJvYmVuDQogICAgKiBIeXBvdGhlc2VudGVzdHM6IFp3ZWlzdGljaHByb2JlbiB0LVRlc3QgZsO8ciB1bmFiaMOkbmdpZ2UgU3RpY2hwcm9iZW4NCg0KDQoNCiMjIyMgRGlmZmVyZW56IGRlciBNaXR0ZWx3ZXJ0ZSBlaW5lciBtZXRyaXNjaGVuIFZhcmlhYmxlIGluIHp3ZWkgUG9wdWxhdGlvbi4gKGFiaMOkbmdpZykNCg0KKiBBbm5haG1lbjogDQogICAgKiBEYXMgSGlzdG9ncmFtbSBkZXIgaW50ZXJlc3NpZXJlbmRlbiBWYXJpYWJsZSBrYW5uIGluIGJlaWRlbiBQb3B1bGF0aW9uZW4gZHVyY2ggZGllIERpY2h0ZWZ1bmt0aW9uIGVpbmVyIE5vcm1hbHZlcnRlaWx1bmcgYXBwcm94aW1pZXJ0IHdlcmRlbi4NCiogVmVyZmFocmVuOiANCiAgICAqIEludGVydmFsbHNjaMOkdHp1bmc6IEtvbmZpZGVuemludGVydmFsbCBmw7xyICRcbXVfMSAtIFxtdV8yJCBiZWkgYWJow6RuZ2lnZW4gU3RpY2hwcm9iZW4NCiAgICAqIEh5cG90aGVzZW50ZXN0czogWndlaXN0aWNocHJvYmVuIHQtVGVzdCBmw7xyIGFiaMOkbmdpZ2UgU3RpY2hwcm9iZW4NCg0KDQojIyMjIEJlaSBncm/Dn2VuIFN0aWNocHJvYmVuIGvDtm5uZW4gVmVybGV0enVuZ2VuIGRlciBBbm5haG1lbiB2ZXJuYWNobMOkc3NpZ3Qgd2VyZGVuIQ0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KLg==