Introduction

La question de la stationnarité et de l’autocorrélation font partie d’un thème plus large qui a rapport à l’endogénéité et l’exogénéité des variables dans une régression. On cherche à connaître le comportement d’une variable si elle n’était affectée que par ses propres chocs idiosyncratiques - donc si elle était totalement exogène au système. Il faut donc l’isoler de l’influence du temps, mais aussi des chocs provenant d’autres variables endogènes. Ici, on va faire uniquement des rappels de cours, et faire l’essentiel du code sur des données simulées afin de montrer que toutes les séries, même si elles peuvent avoir une dynamique similaire, ne peuvent et ne doivent pas être traitées de la même façon.

On va d’abord définir la stationnarité, et les implications liées à la non-stationnarité d’une série temporelle.

Processus stationnaires et non-stationnaires

Il faut partir du postulat que n’importe quelle série qu’on observe est une suite de chocs idiosyncratiques, c’est-à-dire que son comportement ne change pas dans le temps (sa variance, sa moyenne, sont donc constantes). On parle souvent d’une suite de bruits blancs. Les seules choses qui impactent l’évolution d’une série sont des chocs idiosyncratiques, donc propre à la série uniquement. On parle alors généralement de processus stationnaire : l’évolution de la série est indépendante du temps. Généralement, ces hypothèses de départ sont formulées de la façon suivante: \[\begin{align} & E(y_t) = 0 \\ & E(y_t)=E(y_{t+h}) \\ & Var(y_t)=\sigma^2_y \end{align}\] Littéralement, la série a une espérance (moyenne) nulle \(E(y_t) = 0\) et constante (indépendente du temps) \(E(y_t)=E(y_{t+h})\) et a une variance constante (\(Var(y_t)=\sigma^2_y\)).

Dans ce cas précis, la série est purement aléatoire, et son évolution est uniquement le fruit de chocs idiosyncratiques eux-mêmes aléatoires (on dit qu’ils suivent une loi Normale de moyenne nulle et de variance \(\sigma^2_\varepsilon\)):

\[\begin{align} & y_t = \varepsilon_t \\ & \varepsilon \sim N(0,\sigma^2_\varepsilon) \end{align}\]

On peut générer ce genre de variable dans R :

set.seed(123)          # reproductibilité
n  <- 200              # longueur des séries
t  <- 1:n

df <- data.frame(
  t = t, # crée une suite de 1 à 100
  variable = rnorm(n, mean = 0, sd = 1) #distribution avec moyenne à 0, écart-type de 1
)

ggplot(df, aes(x = t, y = variable)) +
  geom_line()+
  theme_bw()

On peut voir que la moyenne et la variance sont relativement constantes dans le temps, et que la distribution est autour de 0.

Dans la réalité, on ne peut que très rarement observer ce processus pour des variables macro/micro-économiques. Par exemple, si on prend le PIB :

donnees <- read_excel("C:/users/fkraus/Desktop/data_schularick.xlsx") 

data_pib <- donnees %>%
  filter(country=="France") %>%
  select(year, gdp)

ggplot(data_pib, aes(x=year, y=gdp))+
  geom_line(lwd=1)+
  theme_bw()

On se retrouve avec une série qui a une moyenne éloignée de 0, et ni sa moyenne, ni sa variance ne sont constantes dans le temps.

A partir du moment où une série est dépendante du temps, on parle alors de processus non-stationnaire. Le problème avec ce genre de séries est que - en économétrie des séries temporelles - les processus non-stationnaires rendent les estimations moins fiables. En effet, on essaye - lors d’une régression - d’identifier l’effet causal d’une variable sur une autre, un effet clairement identifié. Si l’influence d’autres variables (comme le temps) n’est pas prise en compte, alors l’identification sera critiquable (on va faire des régressions fallacieuses, les coefficients estimés seront faux).

En séries temporelles (1 individu, avec plusieurs observations dans le temps), l’essentiel est de bien isoler l’influence du temps sur les variables - ce qui explique tout le processus de stationnarisation. En panel (plusieurs individus, plusieurs observations dans le temps), on part du principe que l’influence du temps est absorbée par les effets fixes individuels (des variables qui sont communes à tous les individus et qui évoluent dans le temps), donc il y a moins ces questions de stationnarisation.

Autocorrélation

On peut dans un premier temps regarder si la série est influencée par elle-même, autrement dit si \(y_{t-1}\) a une influence sur \(y_t\). On parle d’autocorrélation lorsque la corrélation entre \(y_{t-1}\) et \(y_{t}\) est non-nulle (significativement différente de 0). Si cette autocorrélation est présente, alors il faudra la prendre en compte dans la régression, soit en retirant le trend (processus TS), soit en passant en différence première (processus DS) : ça sera la partie stationnarisation de la série.

On peut mesurer assez simplement l’autocorrélation d’ordre 1 d’une série, donc littéralement : \[\begin{equation} y_t=\alpha_0 + \beta y_{t-1}+\varepsilon_t \end{equation}\]

require(fixest)
reg <- feols(gdp ~ lag(gdp,1), data_pib)
etable(reg, se.below=TRUE)
                          reg
Dependent Var.:           gdp
                             
Constant        0e-16        
                   (7.56e-14)
lag(gdp,1)          1.000*** 
                   (1.38e-17)
_______________ _____________
S.E. type                 IID
Observations              151
R2                          1
Adj. R2                     1
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Le résultat de la régression montre que le PIB à la période précendente explique parfaitement le PIB à la période actuelle. Le coefficient est significativement différent de 0, on en conclut donc que la série dépend du temps, et qu’il y a présence d’autocorrélation.

Potentiellement, ce n’est pas seulement le PIB à la période précédente qui explique l’évolution future du PIB, mais peut-être plusieurs délais. On peut le vérifier avec l’autocorrélogramme

acf(data_pib$gdp)

Chaque tiret vertical représente l’influence d’un délai (lag) particulier sur l’évolution de la série à la période \(t\). Le premier tiret peut être négligé ici, c’est l’influence de la série sur elle-même à la même période (donc c’est forcément 1). En l’absence d’autocorrélation en revanche, le reste des tirets est censé être non-significatif (donc les tirets ne doivent pas dépasser la ligne horizontale bleue). Ici, on voit bien que les délais jusqu’à 20 périodes (donc 20 ans avant) influencent la série à la période \(t\). C’est une indications très forte que la série n’est pas stationnaire. Mais ce n’est pas un test formel, c’est un moyen visuel d’identifier la non-stationnarité.

Comment savoir le type de non-stationnarité ? TS vs DS

Afin de s’assurer, avec un test formel, de la stationnarité (ou non-stationnarité) d’une série, il existe de nombreux tests. Il faut également déterminer pour les séries non-stationnaires quel type de non-stationnarité est détectée, car chaque type entraîne des stratégies de stationnarisation différentes qui peuvent créer des perturbations artificielles dans la dynamique d’une série si elles sont mal appliquées.

L’ensemble de ce processus peut être résumé par la Stratégie Séquentielle d’Identification que vous pouvez voir sur ce lien : https://deep-nectarine-155.notion.site/Strat-gie-s-quentielle-28fdaa6a390080f6b63cf102991f522a

La première étape est de tester la présence d’une trend déterministe, pour savoir si le processus est stationnaire en tendance (TS) éventuellement :

Stationnarisation

Une fois qu’on a identifié le fait que la série n’est pas stationnaire, il faut la rendre stationnaire. Il existe deux moyens principaux pour stationnariser une série, en fonction du type de non-stationnarité : passer la série en différence première, ou retirer la tendence (detrend).

Processus DS

Dans le cas des processus stationnaires en différence (DS), il suffit (en général) de passer la série en différence \(\Delta Y_t = Y_t - Y_{t-1}\) pour la rendre stationnaire.

Série en différence première (différence d’ordre 1)

set.seed(123)
n  <- 200              # longueur des séries
t  <- 1:n              # variable qui va de 1 à 200


u <- rnorm(n, mean = 0, sd = 1)   # pour la I(1)
e <- rnorm(n, mean = 0, sd = 1)   # pour la I(2)

# 1) Série I(1) : Random Walk avec léger drift
#    y_t = y_{t-1} + d + u_t
d <- 0.03
y1 <- cumsum(d + u)

difference <- data.frame(t, y1) %>%
  mutate(dy1 = c(NA, diff(y1)))

ggplot(difference, aes(x=t, y=y1))+
  geom_line()+
  labs(title="Série Y1 en niveau")+
  theme_bw()


ggplot(difference, aes(x=t, y=dy1))+
  geom_line()+
  labs(title="Série Y1 en différence première")+
  theme_bw()

Ici, il a suffit de passer la série en différence première pour la stationnariser. On dit aussi que la série est intégrée d’ordre 1 \(I(1)\) (voir séance 7 ARIMA et Cointégration).

Série en différence d’ordre supérieur à 1

Dans certains cas, passer en différence première ne suffit pas à stationnariser une série non-stationnaire. Dans ce cas, on continue de différencier la série, avec autant d’ordres qu’il faut pour la stationnariser.

y2 <- cumsum(cumsum(e)) # série aléatoire

difference2 <- data.frame(t, y2)%>%
  mutate(dy2 = c(NA, diff(y2)))%>% #différence première
  mutate(ddy2 = c(NA, diff(dy2))) # deuxième différence

ggplot(difference2, aes(x=t, y=y2))+
  geom_line()+
  labs(title="Série Y2 en niveau")+
  theme_bw()


ggplot(difference2, aes(x=t, y=dy2))+
  geom_line()+
  labs(title="Série Y2 en différence première")+
  theme_bw()


ggplot(difference2, aes(x=t, y=ddy2))+
  geom_line()+
  labs(title="Série Y2 en deuxième différence")+
  theme_bw()

Ici, la transformation en différence première ne suffit pas à rendre la série stationnaire a priori. En revanche, la deuxième différence semble suffire. On parle ici d’intégration d’ordre 2 \(I(2)\). Dans la majorité des cas, il n’y a pas besoin d’aller plus loin pour stationnariser, mais en théorie on peut répéter l’opération autant de fois que nécessaire.

Série en différence de logarithme

Souvent, les chercheurs transforment directement leurs variable en différence de logarithme parce que ça permet de stationnariser une série tout en gardant une interprétation logique : la série en niveau (sans transformation) devient une série en taux de croissance (voir séance 1 pour faire une différence de log).

Processus TS

Dans le cas des processus stationnaires en tendance (TS), il suffit de retirer la tendance de la série pour la rendre stationnaire. Un processus TS peut suivre un processus additif, ou un processus multiplicatif. Il faut imaginer qu’une série \(Y_t\) est impactée par toutes sortes de chocs. Pour faire simple, on va simplement dire qu’il y a une tendance \(T\) et des chocs idiosyncratiques \(E_t\). Dans la réalité, d’autres composantes entrent en jeu : la saisonnalité S et le cycle C par exemple.

Processus Additifs

Dans le cas d’un processus additif, l’équation de la série est : \[\begin{equation} Y_t = T + E_t \end{equation}\]

Visualisation Processus Additif

Visuellement, une série qui suit un processus additif va ressembler à ceci :


# 1) Série à tendance ADDITIVE: Y_t = T_t + E_t
#    - Tendance linéaire
#    - Chocs idiosyncratiques ~ N(0, sigma^2)
T_add <- 0.5 * t + 5                 # tendance (droite croissante) + constante
E_add <- rnorm(n, mean = 0, sd = 0.8) # "bruit" additif
Y_add <- T_add + E_add

additive <- data.frame(t, Y_add)
head(additive)
ggplot(additive, aes(x=t, y=Y_add))+
  geom_line()+
  labs(title="Série Y_add (processus additif) en niveau")+
  theme_bw()

On voit bien que la série suit une tendance linéaire, et qu’elle est distribuée assez équitablement autour de cette tendance.

Stationnarisation de processus additif

\[\begin{equation} y_t = a_0 + \beta t + \varepsilon_t \end{equation}\] Les résidus \(\varepsilon_t\) peuvent donc être écrits, en réorganisant l’équation : \[\begin{equation} \varepsilon_t = y_t - a_0 - \beta t \end{equation}\] Ils représentent donc la série \(y_t\), moins la constante \(a_0\) et moins l’influence de la tendence \(\beta t\).

detrend <- feols(Y_add ~ t, data=additive) 
etable(detrend)
                           detrend
Dependent Var.:              Y_add
                                  
Constant         5.080*** (0.1098)
t               0.4995*** (0.0009)
_______________ __________________
S.E. type                      IID
Observations                   200
R2                         0.99929
Adj. R2                    0.99929
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
trend_hat_add <- fitted(detrend)      # tendance estimée
resid_add <- resid(detrend)           # résidus (série "dé-tendancée")

detrending_additive <- data.frame(additive, trend_hat_add, resid_add)
head(detrending_additive)

ggplot(detrending_additive, aes(x=t, y=Y_add))+
  geom_line(lwd=1)+
  geom_line(aes(y=trend_hat_add), lty=4, color="red", lwd=1)+
  labs(title="Série Y_add (additive) et tendance associée")+
  theme_bw()


ggplot(detrending_additive, aes(x=t, y=resid_add))+
  geom_line()+
  labs(title="Série Y_add (additive) détrendée")+
  theme_bw()

Processus Multiplicatifs

Dans le cas d’un processus multiplicatif, l’équation de la série est : \[\begin{equation} Y_t = T \times E_t \end{equation}\]

Visualisation Processus Multiplicatif

Visuellement, une série qui suit un processus multiplicatif va ressembler à ceci :

# 2) Série à tendance MULTIPLICATIVE: Y_t = T_t * E_t
#    - Même tendance linéaire mais multipliée par des chocs > 0

T_mult <- 0.5 * t + 5
E_mult <- rlnorm(n, meanlog = 0, sdlog = 0.3)   # chocs multiplicatifs centrés autour de 1
Y_mult <- T_mult * E_mult

multiplicative <- data.frame(t, Y_mult)
head(multiplicative)

ggplot(multiplicative, aes(x=t, y=Y_mult))+
  geom_line()+
  labs(title="Série Y_mult (processus multiplicatif) en niveau")+
  theme_bw()

Ici, la distribution de la série semble moins suivre la tendance linéaire que dans le processus additif.

Stationnarisation de processus multiplicatif

Pour le processus multiplicatif, la même méthode pour détrendée va donner les résultats suivants :

detrend_mult <- feols(Y_mult ~ t, data=multiplicative)
etable(detrend_mult)
                      detrend_mult
Dependent Var.:             Y_mult
                                  
Constant             3.926 (2.859)
t               0.5423*** (0.0247)
_______________ __________________
S.E. type                      IID
Observations                   200
R2                         0.70935
Adj. R2                    0.70788
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
trend_hat_mult <- fitted(detrend_mult)      # tendance estimée
resid_mult <- resid(detrend_mult)           # résidus (série "dé-tendancée")

detrending_multiplicative <- data.frame(multiplicative, trend_hat_mult, resid_mult)

head(detrending_multiplicative)

ggplot(detrending_multiplicative, aes(x=t, y=Y_mult))+
  geom_line()+
  geom_line(aes(y=trend_hat_mult), color="red", lty=2, lwd=1)+
  theme_bw()


ggplot(detrending_multiplicative, aes(x=t, y=resid_mult))+
  geom_line()+
  theme_bw()

Ici, si on reprend le même processus de dé-stationnarisation, on voit que, effectivement les résidus sont distribués autour de 0, et que l’espérance des résidus est bien 0. En revanche, la variance des résidus n’est pas constante (=heteroscédasticité): elle augmente avec le temps.

Un autre moyen, qui ne règle pas toujours le problème (mais qui, en général capte les autres composantes de la variation de \(Y_t\) comme le cycle par exemple) et de mesurer la moyenne mobile de la série, et de retirer cette moyenne mobile :

require(zoo)

detrending_multiplicative2<-detrending_multiplicative%>%
  mutate(moving_average = rollapply(Y_mult, FUN=mean, width=5, fill=NA, align="right"))%>%
  mutate(detrended_serie = Y_mult - moving_average)%>%
  na.omit()

detrending_multiplicative2%>%
  ggplot(aes(x=t, y=Y_mult))+
  geom_line()+
  geom_line(aes(y=moving_average), col="red", lty=2, lwd=1)+
  theme_bw()


detrending_multiplicative2 %>%
  ggplot(aes(x=t, y=detrended_serie))+
  geom_line()+
  theme_bw()

Ici, ça n’a pas aidé à retirer l’hétéroscédasticité, mais c’est une bonne alternative (et c’est très souvent utilisé dans la recherche. Par exemple, cet article de la BCE (https://www.ecb.europa.eu/pub/pdf/scpwps/ecb.wp2868~0c2ad2e6e7.en.pdf) utilise la moyenne mobile des 15 dernières périodes pour détrender une série (page 14). Idem pour cet article de 1993 : https://academic.oup.com/qje/article-pdf/108/4/905/5365099/108-4-905.pdf).

Ici, comme l’hétéroscédasticité est encore présente, il faudrait éventuellement modéliser empiriquement le fait que l’hétéroscédasticité fait partie du processus de la série, dans un modèle ARCH (Auto-Regressive Conditional Heteroskdasticity) ou GARCH (Generalized ARCH) du type : \[\begin{align*} &y_t = a_0 + \varepsilon_t \\ &\varepsilon_t \sim N(0, h_t) \\ &h_t = \beta h_{t-1} + \mu_t \end{align*}\] Les chocs idiosyncratiques ont une distribution normale autour de 0, mais avec une variance \(h\) qui dépend du temps (\(h_t\)), et notamment qui dépend de la variance passée. Les modèles ARCH/GARCH, qu’on ne verra pas pendant ces séances, sont des extensions des modèles AR/MA/ARIMA que l’on verra dans les séance 5, 6 et 7.

Aussi, il faut bien se rappeler que le but de la stationnarisation n’est pas de transformer une série en une suite parfaite de bruits blancs. Dans la réalité, les variables (\(Y_t\)) sont affectées par leur tendance, le cycle, la saisonnalité. En revanche, stationnariser une série permet de l’isoler de l’influence du temps, et améliore l’estimation de l’effet d’autres variables sur la série.

#Exemple de stationnarisation

On va d’abord simuler des données :

set.seed(123)
n  <- 200              # longueur des séries
t  <- 1:n              # variable qui va de 1 à 200

u <- rnorm(n, mean = 0, sd = 1)   # loi normale de moyenne nulle et d'écart type 1

# 1) Série I(1) : Random Walk avec léger drift
#    y_t = y_{t-1} + d + u_t
d <- 0.03
y1 <- cumsum(d + u)
difference <- data.frame(t, y1) %>%
  mutate(dy1 = c(NA, diff(y1)))
head(difference)

La première étape est donc de tester la présence d’un trend :


require(urca)
summary(ur.df(difference$y1, type="trend"))

############################################### 
# Augmented Dickey-Fuller Test Unit Root Test # 
############################################### 

Test regression trend 


Call:
lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.18117 -0.54020 -0.08912  0.56928  2.95658 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)  
(Intercept)  0.3172463  0.1542791   2.056   0.0411 *
z.lag.1     -0.0656894  0.0256276  -2.563   0.0111 *
tt           0.0002116  0.0012502   0.169   0.8658  
z.diff.lag  -0.0365851  0.0716882  -0.510   0.6104  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.935 on 194 degrees of freedom
Multiple R-squared:  0.04006,   Adjusted R-squared:  0.02522 
F-statistic: 2.699 on 3 and 194 DF,  p-value: 0.04701


Value of test-statistic is: -2.5632 2.4736 3.6261 

Critical values for test statistics: 
      1pct  5pct 10pct
tau3 -3.99 -3.43 -3.13
phi2  6.22  4.75  4.07
phi3  8.43  6.49  5.47

Le résultat test de Dickey-Fuller se lit de la façon suivante :

  • une première partie représente le résultat (tableau de régression) de l’équation appliquée
  • une deuxième partie représente les statistiques du test de Dickey-Fuller Augmenté, où il faut comparer les valeurs de la t-stat (test-statistic) avec les valeurs critiques à 5%.

Le coefficient associé à la tendance tt n’est pas significatif, donc il n’y a pas de tendance déterministe détectée. On sait donc que ce n’est pas un processus TS. En revanche, quand on regarde les t-stats, on peut voir que la valeur du test pour tau3 (la première valeur sur la ligne Value of test-statistic is: -2.5632 2.4736 3.6261) n’excède pas (en valeur absolue) la valeur critique à 5% : on sait donc que la série n’est donc pas stationnaire.

On test ensuite avec le modèle avec drift (donc avec une constante notée Intercept dans la régression).

summary(ur.df(difference$y1, type="drift"))

############################################### 
# Augmented Dickey-Fuller Test Unit Root Test # 
############################################### 

Test regression drift 


Call:
lm(formula = z.diff ~ z.lag.1 + 1 + z.diff.lag)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.1913 -0.5481 -0.1001  0.5614  2.9738 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)  0.33101    0.13078   2.531  0.01216 * 
z.lag.1     -0.06410    0.02379  -2.694  0.00767 **
z.diff.lag  -0.03780    0.07115  -0.531  0.59583   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.9326 on 195 degrees of freedom
Multiple R-squared:  0.03992,   Adjusted R-squared:  0.03007 
F-statistic: 4.054 on 2 and 195 DF,  p-value: 0.01884


Value of test-statistic is: -2.6944 3.7146 

Critical values for test statistics: 
      1pct  5pct 10pct
tau2 -3.46 -2.88 -2.57
phi1  6.52  4.63  3.81

Ici, on peut voir que le coefficient associé à la constante dan sle tableau de régression est significatif à 5%. Il semble donc que la série soit affectée par un drift. Aussi, quand on compare la valeur de la t-stat avec la valeur critique associée à tau2, on voit que la valeur de la t-stat n’excède pas (en valeur absolue) la valeur critique à 5%, donc la série n’est pas stationnaire. On sait donc que la série n’est pas stationnaire, et qu’elle suit un processus DS. Il suffirait donc de la passer en différence pour qu’elle devienne stationnaire. On peut le vérifier en faisant le test de stationnarité (sans trend ni constante) sur la série en différence dy1 :

summary(ur.df(difference$dy1 %>% na.omit()))

############################################### 
# Augmented Dickey-Fuller Test Unit Root Test # 
############################################### 

Test regression none 


Call:
lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.13867 -0.57418 -0.03455  0.63940  3.10357 

Coefficients:
           Estimate Std. Error t value Pr(>|t|)    
z.lag.1    -1.15030    0.10402 -11.058   <2e-16 ***
z.diff.lag  0.08256    0.07121   1.159    0.248    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.9403 on 195 degrees of freedom
Multiple R-squared:  0.536, Adjusted R-squared:  0.5312 
F-statistic: 112.6 on 2 and 195 DF,  p-value: < 2.2e-16


Value of test-statistic is: -11.0583 

Critical values for test statistics: 
      1pct  5pct 10pct
tau1 -2.58 -1.95 -1.62

Ici, la t-stat excède la valeur critique à 1% en valeur absolue, ce qui indique que la série en différence est effectivement stationnaire. On peut donc l’utiliser dans le cadre d’une régression.

LS0tDQp0aXRsZTogJ1NlYW5jZSAyOiBTdGF0aW9ubmFyaXTDqSBldCBBdXRvY29ycsOpbGF0aW9uIC0gUmFwcGVscyBkZSBjb3VycycNCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0OiBmYWxzZQ0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQoNCg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KIyDilIDilIAgMCkgSW5zdGFsbGVyIHBhY21hbiBzaSBiZXNvaW4g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSADQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoInBhY21hbiIsIHF1aWV0bHkgPSBUUlVFKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iLCByZXBvcyA9ICJodHRwczovL2Nsb3VkLnItcHJvamVjdC5vcmciKQ0KfQ0KbGlicmFyeShwYWNtYW4pDQoNCiMg4pSA4pSAIDEpIETDqWZpbmlyIGxlcyBwYXF1ZXRzIHV0aWxlcyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIANCnBrZ3MgPC0gYygNCiAgIyBEZW1hbmRlIGRlIGwndXRpbGlzYXRldXINCiAgInRpZHl2ZXJzZSIsICJnZ3Bsb3QyIiwgInJlYWR4bCIsICJ1cmNhIiwgImZpeGVzdCIsDQogICMgRGF0YSB3cmFuZ2xpbmcgLyBJL08NCiAgImRhdGEudGFibGUiLCAiamFuaXRvciIsICJoZXJlIiwgImdsdWUiLA0KICAjIFN0YXRzIC8gw6ljbw0KICAiYnJvb20iLCAic2FuZHdpY2giLCAibG10ZXN0IiwNCiAgIyBTw6lyaWVzIHRlbXBvcmVsbGVzDQogICJ6b28iLCAieHRzIiwgInRzYm94IiwgImZvcmVjYXN0IiwNCiAgIyBWaXogJiBtaXNlIGVuIHBhZ2UNCiAgInNjYWxlcyIsICJwYXRjaHdvcmsiLCAiY293cGxvdCIsDQogICMgTm90ZWJvb2sgLyByZXBvcnRpbmcNCiAgImtuaXRyIiwgInJtYXJrZG93biIsICJrYWJsZUV4dHJhIiwgIkRUIg0KKQ0KDQojIOKUgOKUgCAyKSBJbnN0YWxsZXIgJiBjaGFyZ2VyIGQndW4gY291cCAocF9sb2FkIGluc3RhbGxlIHNpIGFic2VudCkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSADQpwYWNtYW46OnBfbG9hZChjaGFyID0gcGtncywgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKQ0KDQojIChPcHRpb25uZWwpIFBvdXIgZXhwb3J0ZXIgZW4gUERGIGRlcHVpcyBSIE1hcmtkb3duIDoNCiMgcGFjbWFuOjpwX2xvYWQodGlueXRleCk7IHRpbnl0ZXg6Omluc3RhbGxfdGlueXRleCgpICAjIHVuZSBzZXVsZSBmb2lzDQoNCmBgYA0KDQoNCg0KIyBJbnRyb2R1Y3Rpb24NCg0KTGEgcXVlc3Rpb24gZGUgbGEgc3RhdGlvbm5hcml0w6kgZXQgZGUgbCdhdXRvY29ycsOpbGF0aW9uIGZvbnQgcGFydGllIGQndW4gdGjDqG1lIHBsdXMgbGFyZ2UgcXVpIGEgcmFwcG9ydCDDoCBsJyoqZW5kb2fDqW7DqWl0w6kqKiBldCBsJyoqZXhvZ8OpbsOpaXTDqSoqIGRlcyB2YXJpYWJsZXMgZGFucyB1bmUgcsOpZ3Jlc3Npb24uIE9uIGNoZXJjaGUgw6AgY29ubmHDrnRyZSBsZSBjb21wb3J0ZW1lbnQgZCd1bmUgdmFyaWFibGUgc2kgZWxsZSBuJ8OpdGFpdCBhZmZlY3TDqWUgcXVlIHBhciBzZXMgcHJvcHJlcyBjaG9jcyBpZGlvc3luY3JhdGlxdWVzIC0gZG9uYyBzaSBlbGxlIMOpdGFpdCB0b3RhbGVtZW50IGV4b2fDqG5lIGF1IHN5c3TDqG1lLiBJbCBmYXV0IGRvbmMgbCdpc29sZXIgZGUgbCdpbmZsdWVuY2UgZHUgdGVtcHMsIG1haXMgYXVzc2kgZGVzIGNob2NzIHByb3ZlbmFudCBkJ2F1dHJlcyB2YXJpYWJsZXMgZW5kb2fDqG5lcy4gSWNpLCBvbiB2YSBmYWlyZSB1bmlxdWVtZW50IGRlcyByYXBwZWxzIGRlIGNvdXJzLCBldCBmYWlyZSBsJ2Vzc2VudGllbCBkdSBjb2RlIHN1ciBkZXMgZG9ubsOpZXMgc2ltdWzDqWVzIGFmaW4gZGUgbW9udHJlciBxdWUgdG91dGVzIGxlcyBzw6lyaWVzLCBtw6ptZSBzaSBlbGxlcyBwZXV2ZW50IGF2b2lyIHVuZSBkeW5hbWlxdWUgc2ltaWxhaXJlLCBuZSBwZXV2ZW50IGV0IG5lIGRvaXZlbnQgcGFzIMOqdHJlIHRyYWl0w6llcyBkZSBsYSBtw6ptZSBmYcOnb24uDQoNCk9uIHZhIGQnYWJvcmQgZMOpZmluaXIgbGEgc3RhdGlvbm5hcml0w6ksIGV0IGxlcyBpbXBsaWNhdGlvbnMgbGnDqWVzIMOgIGxhIG5vbi1zdGF0aW9ubmFyaXTDqSBkJ3VuZSBzw6lyaWUgdGVtcG9yZWxsZS4NCg0KIyMgUHJvY2Vzc3VzIHN0YXRpb25uYWlyZXMgZXQgbm9uLXN0YXRpb25uYWlyZXMgDQoNCg0KSWwgZmF1dCBwYXJ0aXIgZHUgcG9zdHVsYXQgcXVlIG4naW1wb3J0ZSBxdWVsbGUgc8OpcmllIHF1J29uIG9ic2VydmUgZXN0IHVuZSBzdWl0ZSBkZSBjaG9jcyAqKmlkaW9zeW5jcmF0aXF1ZXMqKiwgYydlc3Qtw6AtZGlyZSBxdWUgc29uIGNvbXBvcnRlbWVudCBuZSBjaGFuZ2UgcGFzIGRhbnMgbGUgdGVtcHMgKHNhIHZhcmlhbmNlLCBzYSBtb3llbm5lLCBzb250IGRvbmMgY29uc3RhbnRlcykuICpPbiBwYXJsZSBzb3V2ZW50IGQndW5lIHN1aXRlIGRlIGJydWl0cyBibGFuY3MqLiBMZXMgc2V1bGVzIGNob3NlcyBxdWkgaW1wYWN0ZW50IGwnw6l2b2x1dGlvbiBkJ3VuZSBzw6lyaWUgc29udCBkZXMgKmNob2NzIGlkaW9zeW5jcmF0aXF1ZXMqLCBkb25jIHByb3ByZSDDoCBsYSBzw6lyaWUgdW5pcXVlbWVudC4gT24gcGFybGUgYWxvcnMgZ8OpbsOpcmFsZW1lbnQgZGUgKipwcm9jZXNzdXMgc3RhdGlvbm5haXJlKiogOiBsJ8Opdm9sdXRpb24gZGUgbGEgc8OpcmllIGVzdCBpbmTDqXBlbmRhbnRlIGR1IHRlbXBzLiBHw6luw6lyYWxlbWVudCwgY2VzIGh5cG90aMOoc2VzIGRlIGTDqXBhcnQgc29udCBmb3JtdWzDqWVzIGRlIGxhIGZhw6dvbiBzdWl2YW50ZToNClxiZWdpbnthbGlnbn0NCiYgRSh5X3QpID0gMCBcXA0KJiBFKHlfdCk9RSh5X3t0K2h9KSBcXA0KJiBWYXIoeV90KT1cc2lnbWFeMl95DQpcZW5ke2FsaWdufSBMaXR0w6lyYWxlbWVudCwgbGEgc8OpcmllIGEgdW5lICoqZXNww6lyYW5jZSoqIChtb3llbm5lKSAqKm51bGxlKiogJEUoeV90KSA9IDAkIGV0ICoqY29uc3RhbnRlKiogKGluZMOpcGVuZGVudGUgZHUgdGVtcHMpICRFKHlfdCk9RSh5X3t0K2h9KSQgZXQgYSB1bmUgKip2YXJpYW5jZSBjb25zdGFudGUqKiAoJFZhcih5X3QpPVxzaWdtYV4yX3kkKS4NCg0KRGFucyBjZSBjYXMgcHLDqWNpcywgbGEgc8OpcmllIGVzdCBwdXJlbWVudCBhbMOpYXRvaXJlLCBldCBzb24gw6l2b2x1dGlvbiBlc3QgdW5pcXVlbWVudCBsZSBmcnVpdCBkZSBjaG9jcyBpZGlvc3luY3JhdGlxdWVzIGV1eC1tw6ptZXMgYWzDqWF0b2lyZXMgKG9uIGRpdCBxdSdpbHMgc3VpdmVudCB1bmUgbG9pIE5vcm1hbGUgZGUgbW95ZW5uZSBudWxsZSBldCBkZSB2YXJpYW5jZSAkXHNpZ21hXjJfXHZhcmVwc2lsb24kKToNCg0KYGBgez10ZXh9DQpcYmVnaW57YWxpZ259DQomIHlfdCA9IFx2YXJlcHNpbG9uX3QgXFwNCiYgXHZhcmVwc2lsb24gXHNpbSBOKDAsXHNpZ21hXjJfXHZhcmVwc2lsb24pDQpcZW5ke2FsaWdufQ0KYGBgDQpPbiBwZXV0IGfDqW7DqXJlciBjZSBnZW5yZSBkZSB2YXJpYWJsZSBkYW5zIFIgOg0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMykgICAgICAgICAgIyByZXByb2R1Y3RpYmlsaXTDqQ0KbiAgPC0gMjAwICAgICAgICAgICAgICAjIGxvbmd1ZXVyIGRlcyBzw6lyaWVzDQp0ICA8LSAxOm4NCmBgYA0KDQpgYGB7cn0NCg0KZGYgPC0gZGF0YS5mcmFtZSgNCiAgdCA9IHQsICMgY3LDqWUgdW5lIHN1aXRlIGRlIDEgw6AgMTAwDQogIHZhcmlhYmxlID0gcm5vcm0obiwgbWVhbiA9IDAsIHNkID0gMSkgI2Rpc3RyaWJ1dGlvbiBhdmVjIG1veWVubmUgw6AgMCwgw6ljYXJ0LXR5cGUgZGUgMQ0KKQ0KDQpnZ3Bsb3QoZGYsIGFlcyh4ID0gdCwgeSA9IHZhcmlhYmxlKSkgKw0KICBnZW9tX2xpbmUoKSsNCiAgdGhlbWVfYncoKQ0KYGBgDQoNCk9uIHBldXQgdm9pciBxdWUgbGEgbW95ZW5uZSBldCBsYSB2YXJpYW5jZSBzb250IHJlbGF0aXZlbWVudCBjb25zdGFudGVzIGRhbnMgbGUgdGVtcHMsIGV0IHF1ZSBsYSBkaXN0cmlidXRpb24gZXN0IGF1dG91ciBkZSAwLg0KDQpEYW5zIGxhIHLDqWFsaXTDqSwgb24gbmUgcGV1dCBxdWUgdHLDqHMgcmFyZW1lbnQgb2JzZXJ2ZXIgY2UgcHJvY2Vzc3VzIHBvdXIgZGVzIHZhcmlhYmxlcyBtYWNyby9taWNyby3DqWNvbm9taXF1ZXMuIFBhciBleGVtcGxlLCBzaSBvbiBwcmVuZCBsZSBQSUIgOg0KDQpgYGB7cn0NCmRvbm5lZXMgPC0gcmVhZF9leGNlbCgiQzovdXNlcnMvZmtyYXVzL0Rlc2t0b3AvZGF0YV9zY2h1bGFyaWNrLnhsc3giKSANCg0KZGF0YV9waWIgPC0gZG9ubmVlcyAlPiUNCiAgZmlsdGVyKGNvdW50cnk9PSJGcmFuY2UiKSAlPiUNCiAgc2VsZWN0KHllYXIsIGdkcCkNCg0KZ2dwbG90KGRhdGFfcGliLCBhZXMoeD15ZWFyLCB5PWdkcCkpKw0KICBnZW9tX2xpbmUobHdkPTEpKw0KICB0aGVtZV9idygpDQpgYGANCg0KT24gc2UgcmV0cm91dmUgYXZlYyB1bmUgc8OpcmllIHF1aSBhIHVuZSBtb3llbm5lIMOpbG9pZ27DqWUgZGUgMCwgZXQgbmkgc2EgbW95ZW5uZSwgbmkgc2EgdmFyaWFuY2UgbmUgc29udCBjb25zdGFudGVzIGRhbnMgbGUgdGVtcHMuDQoNCkEgcGFydGlyIGR1IG1vbWVudCBvw7kgdW5lIHPDqXJpZSBlc3QgZMOpcGVuZGFudGUgZHUgdGVtcHMsIG9uIHBhcmxlIGFsb3JzIGRlICoqcHJvY2Vzc3VzIG5vbi1zdGF0aW9ubmFpcmUqKi4gTGUgcHJvYmzDqG1lIGF2ZWMgY2UgZ2VucmUgZGUgc8OpcmllcyBlc3QgcXVlIC0gZW4gw6ljb25vbcOpdHJpZSBkZXMgc8OpcmllcyB0ZW1wb3JlbGxlcyAtIGxlcyBwcm9jZXNzdXMgbm9uLXN0YXRpb25uYWlyZXMgcmVuZGVudCBsZXMgZXN0aW1hdGlvbnMgbW9pbnMgZmlhYmxlcy4gRW4gZWZmZXQsIG9uIGVzc2F5ZSAtIGxvcnMgZOKAmXVuZSByw6lncmVzc2lvbiAtIGTigJlpZGVudGlmaWVyIGzigJllZmZldCAqKmNhdXNhbCoqIGTigJl1bmUgdmFyaWFibGUgc3VyIHVuZSBhdXRyZSwgdW4gZWZmZXQgY2xhaXJlbWVudCBpZGVudGlmacOpLiAqKlNpIGzigJlpbmZsdWVuY2UgZOKAmWF1dHJlcyB2YXJpYWJsZXMgKGNvbW1lIGxlIHRlbXBzKSBu4oCZZXN0IHBhcyBwcmlzZSBlbiBjb21wdGUsIGFsb3JzIGzigJlpZGVudGlmaWNhdGlvbiBzZXJhIGNyaXRpcXVhYmxlKiogKG9uIHZhIGZhaXJlIGRlcyByw6lncmVzc2lvbnMgZmFsbGFjaWV1c2VzLCBsZXMgY29lZmZpY2llbnRzIGVzdGltw6lzIHNlcm9udCBmYXV4KS4gDQoNCipFbiBzw6lyaWVzIHRlbXBvcmVsbGVzICgxIGluZGl2aWR1LCBhdmVjIHBsdXNpZXVycyBvYnNlcnZhdGlvbnMgZGFucyBsZSB0ZW1wcyksIGwnZXNzZW50aWVsIGVzdCBkZSBiaWVuIGlzb2xlciBsJ2luZmx1ZW5jZSBkdSB0ZW1wcyBzdXIgbGVzIHZhcmlhYmxlcyAtIGNlIHF1aSBleHBsaXF1ZSB0b3V0IGxlIHByb2Nlc3N1cyBkZSBzdGF0aW9ubmFyaXNhdGlvbi4gRW4gcGFuZWwgKHBsdXNpZXVycyBpbmRpdmlkdXMsIHBsdXNpZXVycyBvYnNlcnZhdGlvbnMgZGFucyBsZSB0ZW1wcyksIG9uIHBhcnQgZHUgcHJpbmNpcGUgcXVlIGzigJlpbmZsdWVuY2UgZHUgdGVtcHMgZXN0IGFic29yYsOpZSBwYXIgbGVzIGVmZmV0cyBmaXhlcyBpbmRpdmlkdWVscyAoZGVzIHZhcmlhYmxlcyBxdWkgc29udCBjb21tdW5lcyDDoCB0b3VzIGxlcyBpbmRpdmlkdXMgZXQgcXVpIMOpdm9sdWVudCBkYW5zIGxlIHRlbXBzKSwgZG9uYyBpbCB5IGEgbW9pbnMgY2VzIHF1ZXN0aW9ucyBkZSBzdGF0aW9ubmFyaXNhdGlvbi4qDQoNCiMjIEF1dG9jb3Jyw6lsYXRpb24NCg0KT24gcGV1dCBkYW5zIHVuIHByZW1pZXIgdGVtcHMgcmVnYXJkZXIgc2kgbGEgc8OpcmllIGVzdCBpbmZsdWVuY8OpZSBwYXIgZWxsZS1tw6ptZSwgYXV0cmVtZW50IGRpdCBzaSAkeV97dC0xfSQgYSB1bmUgaW5mbHVlbmNlIHN1ciAkeV90JC4gT24gcGFybGUgZOKAmSoqYXV0b2NvcnLDqWxhdGlvbioqIGxvcnNxdWUgbGEgY29ycsOpbGF0aW9uIGVudHJlICR5X3t0LTF9JCBldCAkeV97dH0kIGVzdCAqbm9uLW51bGxlKiAoc2lnbmlmaWNhdGl2ZW1lbnQgZGlmZsOpcmVudGUgZGUgMCkuIFNpIGNldHRlIGF1dG9jb3Jyw6lsYXRpb24gZXN0IHByw6lzZW50ZSwgYWxvcnMgaWwgZmF1ZHJhIGxhIHByZW5kcmUgZW4gY29tcHRlIGRhbnMgbGEgcsOpZ3Jlc3Npb24sIHNvaXQgZW4gcmV0aXJhbnQgbGUgKip0cmVuZCoqIChwcm9jZXNzdXMgVFMpLCBzb2l0IGVuIHBhc3NhbnQgZW4gKipkaWZmw6lyZW5jZSBwcmVtacOocmUqKiAocHJvY2Vzc3VzIERTKSA6IMOnYSBzZXJhIGxhIHBhcnRpZSAqKnN0YXRpb25uYXJpc2F0aW9uIGRlIGxhIHPDqXJpZSoqLiANCg0KT24gcGV1dCBtZXN1cmVyIGFzc2V6IHNpbXBsZW1lbnQgbOKAmSphdXRvY29ycsOpbGF0aW9uIGTigJlvcmRyZSAxKiBk4oCZdW5lIHPDqXJpZSwgZG9uYyBsaXR0w6lyYWxlbWVudCA6DQpcYmVnaW57ZXF1YXRpb259DQp5X3Q9XGFscGhhXzAgKyBcYmV0YSB5X3t0LTF9K1x2YXJlcHNpbG9uX3QNClxlbmR7ZXF1YXRpb259DQoNCmBgYHtyfQ0KcmVxdWlyZShmaXhlc3QpDQpyZWcgPC0gZmVvbHMoZ2RwIH4gbGFnKGdkcCwxKSwgZGF0YV9waWIpDQpldGFibGUocmVnLCBzZS5iZWxvdz1UUlVFKQ0KYGBgDQpMZSByw6lzdWx0YXQgZGUgbGEgcsOpZ3Jlc3Npb24gbW9udHJlIHF1ZSBsZSBQSUIgw6AgbGEgcMOpcmlvZGUgcHLDqWNlbmRlbnRlIGV4cGxpcXVlICoqcGFyZmFpdGVtZW50KiogbGUgUElCIMOgIGxhIHDDqXJpb2RlIGFjdHVlbGxlLiBMZSBjb2VmZmljaWVudCBlc3Qgc2lnbmlmaWNhdGl2ZW1lbnQgZGlmZsOpcmVudCBkZSAwLCBvbiBlbiBjb25jbHV0IGRvbmMgcXVlIGxhIHPDqXJpZSBkw6lwZW5kIGR1IHRlbXBzLCBldCBxdSdpbCB5IGEgcHLDqXNlbmNlIGQnYXV0b2NvcnLDqWxhdGlvbi4NCg0KUG90ZW50aWVsbGVtZW50LCBjZSBuJ2VzdCBwYXMgc2V1bGVtZW50IGxlIFBJQiDDoCBsYSBww6lyaW9kZSBwcsOpY8OpZGVudGUgcXVpIGV4cGxpcXVlIGwnw6l2b2x1dGlvbiBmdXR1cmUgZHUgUElCLCBtYWlzIHBldXQtw6p0cmUgcGx1c2lldXJzIGTDqWxhaXMuIE9uIHBldXQgbGUgdsOpcmlmaWVyIGF2ZWMgKipsJ2F1dG9jb3Jyw6lsb2dyYW1tZSoqDQpgYGB7cn0NCmFjZihkYXRhX3BpYiRnZHApDQpgYGANCkNoYXF1ZSB0aXJldCB2ZXJ0aWNhbCByZXByw6lzZW50ZSBsJ2luZmx1ZW5jZSBkJ3VuIGTDqWxhaSAoKmxhZyopIHBhcnRpY3VsaWVyIHN1ciBsJ8Opdm9sdXRpb24gZGUgbGEgc8OpcmllIMOgIGxhIHDDqXJpb2RlICR0JC4gTGUgcHJlbWllciB0aXJldCBwZXV0IMOqdHJlIG7DqWdsaWfDqSBpY2ksIGMnZXN0IGwnaW5mbHVlbmNlIGRlIGxhIHPDqXJpZSBzdXIgZWxsZS1tw6ptZSDDoCBsYSBtw6ptZSBww6lyaW9kZSAoZG9uYyBjJ2VzdCBmb3Jjw6ltZW50IDEpLiBFbiBsJ2Fic2VuY2UgZCdhdXRvY29ycsOpbGF0aW9uIGVuIHJldmFuY2hlLCBsZSByZXN0ZSBkZXMgdGlyZXRzIGVzdCBjZW5zw6kgw6p0cmUgbm9uLXNpZ25pZmljYXRpZiAoZG9uYyBsZXMgdGlyZXRzIG5lIGRvaXZlbnQgcGFzIGTDqXBhc3NlciBsYSBsaWduZSBob3Jpem9udGFsZSBibGV1ZSkuIEljaSwgb24gdm9pdCBiaWVuIHF1ZSBsZXMgZMOpbGFpcyBqdXNxdSfDoCAyMCBww6lyaW9kZXMgKGRvbmMgMjAgYW5zIGF2YW50KSBpbmZsdWVuY2VudCBsYSBzw6lyaWUgw6AgbGEgcMOpcmlvZGUgJHQkLiBDJ2VzdCB1bmUgaW5kaWNhdGlvbnMgdHLDqHMgZm9ydGUgcXVlIGxhIHPDqXJpZSBuJ2VzdCAqKnBhcyBzdGF0aW9ubmFpcmUqKi4gTWFpcyBjZSBuJ2VzdCBwYXMgdW4gKnRlc3QgZm9ybWVsKiwgYydlc3QgdW4gbW95ZW4gdmlzdWVsIGQnaWRlbnRpZmllciBsYSBub24tc3RhdGlvbm5hcml0w6kuIA0KDQoNCg0KIyBDb21tZW50IHNhdm9pciBsZSB0eXBlIGRlIG5vbi1zdGF0aW9ubmFyaXTDqSA/IFRTIHZzIERTICAgIA0KDQpBZmluIGRlIHMnYXNzdXJlciwgYXZlYyB1biB0ZXN0IGZvcm1lbCwgZGUgbGEgc3RhdGlvbm5hcml0w6kgKG91IG5vbi1zdGF0aW9ubmFyaXTDqSkgZCd1bmUgc8OpcmllLCBpbCBleGlzdGUgZGUgbm9tYnJldXggdGVzdHMuIElsIGZhdXQgw6lnYWxlbWVudCBkw6l0ZXJtaW5lciBwb3VyIGxlcyBzw6lyaWVzIG5vbi1zdGF0aW9ubmFpcmVzIHF1ZWwgdHlwZSBkZSBub24tc3RhdGlvbm5hcml0w6kgZXN0IGTDqXRlY3TDqWUsIGNhciBjaGFxdWUgdHlwZSBlbnRyYcOubmUgZGVzIHN0cmF0w6lnaWVzIGRlIHN0YXRpb25uYXJpc2F0aW9uIGRpZmbDqXJlbnRlcyBxdWkgcGV1dmVudCBjcsOpZXIgZGVzIHBlcnR1cmJhdGlvbnMgYXJ0aWZpY2llbGxlcyBkYW5zIGxhIGR5bmFtaXF1ZSBkJ3VuZSBzw6lyaWUgc2kgZWxsZXMgc29udCBtYWwgYXBwbGlxdcOpZXMuDQoNCkwnZW5zZW1ibGUgZGUgY2UgcHJvY2Vzc3VzIHBldXQgw6p0cmUgcsOpc3Vtw6kgcGFyIGxhIFN0cmF0w6lnaWUgU8OpcXVlbnRpZWxsZSBkJ0lkZW50aWZpY2F0aW9uIHF1ZSB2b3VzIHBvdXZleiB2b2lyIHN1ciBjZSBsaWVuIDogaHR0cHM6Ly9kZWVwLW5lY3RhcmluZS0xNTUubm90aW9uLnNpdGUvU3RyYXQtZ2llLXMtcXVlbnRpZWxsZS0yOGZkYWE2YTM5MDA4MGY2YjYzY2YxMDI5OTFmNTIyYQ0KDQpMYSBwcmVtacOocmUgw6l0YXBlIGVzdCBkZSB0ZXN0ZXIgbGEgcHLDqXNlbmNlIGQndW5lIHRyZW5kIGTDqXRlcm1pbmlzdGUsIHBvdXIgc2F2b2lyIHNpIGxlIHByb2Nlc3N1cyBlc3Qgc3RhdGlvbm5haXJlIGVuIHRlbmRhbmNlIChUUykgw6l2ZW50dWVsbGVtZW50IDogDQoNCi0gT24gdGVzdCB0b3V0IGQnYWJvcmQgbGEgcHLDqXNlbmNlIHNpZ25pZmljYXRpdmUgZCd1bmUgdGVuZGFuY2UuDQogIC0gU2kgdW5lIHRlbmRhbmNlIGVzdCBkw6l0ZWN0w6llLCBvbiB0ZXN0ZSBzaSBsJ2F1dG9jb3Jyw6lsYXRpb24gZXN0IHNpZ25pZmljYXRpdmUgOg0KICAgIC0gU2kgYydlc3QgbGUgY2FzLCBjJ2VzdCB1biAqKkRTKiouDQogICAgLSBTaW5vbiwgYydlc3QgdW4gKipUUyoqLg0KICAtIFNpIGF1Y3VuZSB0ZW5kYW5jZSBuJ2VzdCBkw6l0ZWN0w6llLCBvbiB0ZXN0ZSBlbnN1aXRlIGxlIG1vZMOobGUgYXZlYyBkcmlmdCwgYWZpbiBkZSB0ZXN0ZXIgc2kgdW5lIGNvbnN0YW50ZSBhZmZlY3RlIGxhIGR5bmFtaXF1ZSBkZSBsYSBzw6lyaWUgOg0KICAgIC0gU2kgdW4gZHJpZnQgZXN0IGTDqXRlY3TDqSwgb24gdGVzdGUgc2kgbCdhdXRvY29ycsOpbGF0aW9uIGVzdCBzaWduaWZpY2F0aXZlLg0KICAgICAgICAtIFNpIGMnZXN0IGxlIGNhcywgYydlc3QgdW4gKipEUyoqLg0KICAgICAgICAtIFNpbm9uLCBsYSBzw6lyaWUgZXN0ICoqc3RhdGlvbm5haXJlKiouDQogICAgLSBTaSBhdWN1biBkcmlmdCAoYXVjdW5lIGNvbnN0YW50ZSkgbidlc3QgZMOpdGVjdMOpLCBvbiB0ZXN0ZSBsZSBtb2TDqGxlIHF1aSBuZSB0aWVudCBjb21wdGUgcXVlIGRlIGwnYXV0b2NvcnLDqWxhdGlvbi4NCiAgICAgICAgLSBTaSBsZSBjb2VmZmljaWVudCBhc3NvY2nDqSDDoCBsJ2F1dG9jb3Jyw6lsYXRpb24gZXN0IHNpZ25pZmljYXRpZiwgYydlc3QgdW4gKipEUyoqLg0KICAgICAgICAtIFNpbm9uLCBsYSBzw6lyaWUgZXN0ICoqc3RhdGlvbm5haXJlKiouDQoNCg0KDQojIFN0YXRpb25uYXJpc2F0aW9uDQoNClVuZSBmb2lzIHF14oCZb24gYSBpZGVudGlmacOpIGxlIGZhaXQgcXVlIGxhIHPDqXJpZSBu4oCZZXN0IHBhcyBzdGF0aW9ubmFpcmUsIGlsIGZhdXQgbGEgcmVuZHJlIHN0YXRpb25uYWlyZS4gSWwgZXhpc3RlIGRldXggbW95ZW5zIHByaW5jaXBhdXggcG91ciBzdGF0aW9ubmFyaXNlciB1bmUgc8OpcmllLCBlbiAqKmZvbmN0aW9uIGR1IHR5cGUgZGUgbm9uLXN0YXRpb25uYXJpdMOpKiogOiBwYXNzZXIgbGEgc8OpcmllIGVuIGRpZmbDqXJlbmNlIHByZW1pw6hyZSwgb3UgcmV0aXJlciBsYSB0ZW5kZW5jZSAoKmRldHJlbmQqKS4gDQoNCiMjIFByb2Nlc3N1cyBEUw0KRGFucyBsZSBjYXMgZGVzIHByb2Nlc3N1cyAqKnN0YXRpb25uYWlyZXMgZW4gZGlmZsOpcmVuY2UqKiAoRFMpLCBpbCBzdWZmaXQgKGVuIGfDqW7DqXJhbCkgZGUgcGFzc2VyIGxhIHPDqXJpZSBlbiBkaWZmw6lyZW5jZSAkXERlbHRhIFlfdCA9IFlfdCAtIFlfe3QtMX0kIHBvdXIgbGEgcmVuZHJlIHN0YXRpb25uYWlyZS4gDQoNCiMjIyBTw6lyaWUgZW4gZGlmZsOpcmVuY2UgcHJlbWnDqHJlIChkaWZmw6lyZW5jZSBkJ29yZHJlIDEpDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzKQ0KbiAgPC0gMjAwICAgICAgICAgICAgICAjIGxvbmd1ZXVyIGRlcyBzw6lyaWVzDQp0ICA8LSAxOm4gICAgICAgICAgICAgICMgdmFyaWFibGUgcXVpIHZhIGRlIDEgw6AgMjAwDQoNCg0KdSA8LSBybm9ybShuLCBtZWFuID0gMCwgc2QgPSAxKSAgICMgcG91ciBsYSBJKDEpDQplIDwtIHJub3JtKG4sIG1lYW4gPSAwLCBzZCA9IDEpICAgIyBwb3VyIGxhIEkoMikNCg0KIyAxKSBTw6lyaWUgSSgxKSA6IFJhbmRvbSBXYWxrIGF2ZWMgbMOpZ2VyIGRyaWZ0DQojICAgIHlfdCA9IHlfe3QtMX0gKyBkICsgdV90DQpkIDwtIDAuMDMNCnkxIDwtIGN1bXN1bShkICsgdSkNCg0KZGlmZmVyZW5jZSA8LSBkYXRhLmZyYW1lKHQsIHkxKSAlPiUNCiAgbXV0YXRlKGR5MSA9IGMoTkEsIGRpZmYoeTEpKSkNCg0KZ2dwbG90KGRpZmZlcmVuY2UsIGFlcyh4PXQsIHk9eTEpKSsNCiAgZ2VvbV9saW5lKCkrDQogIGxhYnModGl0bGU9IlPDqXJpZSBZMSBlbiBuaXZlYXUiKSsNCiAgdGhlbWVfYncoKQ0KDQpnZ3Bsb3QoZGlmZmVyZW5jZSwgYWVzKHg9dCwgeT1keTEpKSsNCiAgZ2VvbV9saW5lKCkrDQogIGxhYnModGl0bGU9IlPDqXJpZSBZMSBlbiBkaWZmw6lyZW5jZSBwcmVtacOocmUiKSsNCiAgdGhlbWVfYncoKQ0KYGBgDQpJY2ksIGlsIGEgc3VmZml0IGRlIHBhc3NlciBsYSBzw6lyaWUgZW4gZGlmZsOpcmVuY2UgcHJlbWnDqHJlIHBvdXIgbGEgc3RhdGlvbm5hcmlzZXIuIE9uIGRpdCBhdXNzaSBxdWUgbGEgc8OpcmllIGVzdCBpbnTDqWdyw6llIGQnb3JkcmUgMSAkSSgxKSQgKHZvaXIgc8OpYW5jZSA3IEFSSU1BIGV0IENvaW50w6lncmF0aW9uKS4NCg0KIyMjIFPDqXJpZSBlbiBkaWZmw6lyZW5jZSBkJ29yZHJlIHN1cMOpcmlldXIgw6AgMQ0KRGFucyBjZXJ0YWlucyBjYXMsIHBhc3NlciBlbiBkaWZmw6lyZW5jZSBwcmVtacOocmUgbmUgc3VmZml0IHBhcyDDoCBzdGF0aW9ubmFyaXNlciB1bmUgc8OpcmllIG5vbi1zdGF0aW9ubmFpcmUuIERhbnMgY2UgY2FzLCBvbiBjb250aW51ZSBkZSBkaWZmw6lyZW5jaWVyIGxhIHPDqXJpZSwgYXZlYyBhdXRhbnQgZCdvcmRyZXMgcXUnaWwgZmF1dCBwb3VyIGxhIHN0YXRpb25uYXJpc2VyLg0KDQpgYGB7cn0NCnkyIDwtIGN1bXN1bShjdW1zdW0oZSkpICMgc8OpcmllIGFsw6lhdG9pcmUNCg0KZGlmZmVyZW5jZTIgPC0gZGF0YS5mcmFtZSh0LCB5MiklPiUNCiAgbXV0YXRlKGR5MiA9IGMoTkEsIGRpZmYoeTIpKSklPiUgI2RpZmbDqXJlbmNlIHByZW1pw6hyZQ0KICBtdXRhdGUoZGR5MiA9IGMoTkEsIGRpZmYoZHkyKSkpICMgZGV1eGnDqG1lIGRpZmbDqXJlbmNlDQoNCmdncGxvdChkaWZmZXJlbmNlMiwgYWVzKHg9dCwgeT15MikpKw0KICBnZW9tX2xpbmUoKSsNCiAgbGFicyh0aXRsZT0iU8OpcmllIFkyIGVuIG5pdmVhdSIpKw0KICB0aGVtZV9idygpDQoNCmdncGxvdChkaWZmZXJlbmNlMiwgYWVzKHg9dCwgeT1keTIpKSsNCiAgZ2VvbV9saW5lKCkrDQogIGxhYnModGl0bGU9IlPDqXJpZSBZMiBlbiBkaWZmw6lyZW5jZSBwcmVtacOocmUiKSsNCiAgdGhlbWVfYncoKQ0KDQpnZ3Bsb3QoZGlmZmVyZW5jZTIsIGFlcyh4PXQsIHk9ZGR5MikpKw0KICBnZW9tX2xpbmUoKSsNCiAgbGFicyh0aXRsZT0iU8OpcmllIFkyIGVuIGRldXhpw6htZSBkaWZmw6lyZW5jZSIpKw0KICB0aGVtZV9idygpDQoNCmBgYA0KSWNpLCBsYSB0cmFuc2Zvcm1hdGlvbiBlbiBkaWZmw6lyZW5jZSBwcmVtacOocmUgbmUgc3VmZml0IHBhcyDDoCByZW5kcmUgbGEgc8OpcmllIHN0YXRpb25uYWlyZSBhIHByaW9yaS4gRW4gcmV2YW5jaGUsIGxhIGRldXhpw6htZSBkaWZmw6lyZW5jZSBzZW1ibGUgc3VmZmlyZS4gT24gcGFybGUgaWNpIGQnaW50w6lncmF0aW9uIGQnb3JkcmUgMiAkSSgyKSQuIERhbnMgbGEgbWFqb3JpdMOpIGRlcyBjYXMsIGlsIG4neSBhIHBhcyBiZXNvaW4gZCdhbGxlciBwbHVzIGxvaW4gcG91ciBzdGF0aW9ubmFyaXNlciwgbWFpcyBlbiB0aMOpb3JpZSBvbiBwZXV0IHLDqXDDqXRlciBsJ29ww6lyYXRpb24gYXV0YW50IGRlIGZvaXMgcXVlIG7DqWNlc3NhaXJlLg0KDQoNCiMjIyBTw6lyaWUgZW4gZGlmZsOpcmVuY2UgZGUgbG9nYXJpdGhtZQ0KU291dmVudCwgbGVzIGNoZXJjaGV1cnMgdHJhbnNmb3JtZW50IGRpcmVjdGVtZW50IGxldXJzIHZhcmlhYmxlIGVuIGRpZmbDqXJlbmNlIGRlIGxvZ2FyaXRobWUgcGFyY2UgcXVlIMOnYSBwZXJtZXQgZGUgc3RhdGlvbm5hcmlzZXIgdW5lIHPDqXJpZSB0b3V0IGVuIGdhcmRhbnQgdW5lIGludGVycHLDqXRhdGlvbiBsb2dpcXVlIDogbGEgc8OpcmllIGVuIG5pdmVhdSAoc2FucyB0cmFuc2Zvcm1hdGlvbikgZGV2aWVudCB1bmUgc8OpcmllIGVuIHRhdXggZGUgY3JvaXNzYW5jZSAodm9pciBzw6lhbmNlIDEgcG91ciBmYWlyZSB1bmUgZGlmZsOpcmVuY2UgZGUgbG9nKS4NCg0KDQoNCiMjIFByb2Nlc3N1cyBUUw0KRGFucyBsZSBjYXMgZGVzIHByb2Nlc3N1cyAqKnN0YXRpb25uYWlyZXMgZW4gdGVuZGFuY2UqKiAoVFMpLCBpbCBzdWZmaXQgZGUgcmV0aXJlciBsYSB0ZW5kYW5jZSBkZSBsYSBzw6lyaWUgcG91ciBsYSByZW5kcmUgc3RhdGlvbm5haXJlLiBVbiBwcm9jZXNzdXMgVFMgcGV1dCBzdWl2cmUgdW4gcHJvY2Vzc3VzIGFkZGl0aWYsIG91IHVuIHByb2Nlc3N1cyBtdWx0aXBsaWNhdGlmLiBJbCBmYXV0IGltYWdpbmVyIHF1J3VuZSBzw6lyaWUgJFlfdCQgZXN0IGltcGFjdMOpZSBwYXIgdG91dGVzIHNvcnRlcyBkZSBjaG9jcy4gUG91ciBmYWlyZSBzaW1wbGUsIG9uIHZhIHNpbXBsZW1lbnQgZGlyZSBxdSdpbCB5IGEgdW5lIHRlbmRhbmNlICRUJCBldCBkZXMgY2hvY3MgaWRpb3N5bmNyYXRpcXVlcyAkRV90JC4gKkRhbnMgbGEgcsOpYWxpdMOpLCBkJ2F1dHJlcyBjb21wb3NhbnRlcyBlbnRyZW50IGVuIGpldSA6IGxhIHNhaXNvbm5hbGl0w6kgUyBldCBsZSBjeWNsZSBDIHBhciBleGVtcGxlKi4NCg0KDQojIyMgUHJvY2Vzc3VzIEFkZGl0aWZzDQoNCkRhbnMgbGUgY2FzIGQndW4gcHJvY2Vzc3VzIGFkZGl0aWYsIGwnw6lxdWF0aW9uIGRlIGxhIHPDqXJpZSBlc3QgOg0KXGJlZ2lue2VxdWF0aW9ufQ0KWV90ID0gVCArIEVfdA0KXGVuZHtlcXVhdGlvbn0NCg0KIyMjIyBWaXN1YWxpc2F0aW9uIFByb2Nlc3N1cyBBZGRpdGlmDQpWaXN1ZWxsZW1lbnQsIHVuZSBzw6lyaWUgcXVpIHN1aXQgdW4gcHJvY2Vzc3VzIGFkZGl0aWYgdmEgcmVzc2VtYmxlciDDoCBjZWNpIDoNCg0KYGBge3J9DQoNCiMgMSkgU8OpcmllIMOgIHRlbmRhbmNlIEFERElUSVZFOiBZX3QgPSBUX3QgKyBFX3QNCiMgICAgLSBUZW5kYW5jZSBsaW7DqWFpcmUNCiMgICAgLSBDaG9jcyBpZGlvc3luY3JhdGlxdWVzIH4gTigwLCBzaWdtYV4yKQ0KVF9hZGQgPC0gMC41ICogdCArIDUgICAgICAgICAgICAgICAgICMgdGVuZGFuY2UgKGRyb2l0ZSBjcm9pc3NhbnRlKSArIGNvbnN0YW50ZQ0KRV9hZGQgPC0gcm5vcm0obiwgbWVhbiA9IDAsIHNkID0gMC44KSAjICJicnVpdCIgYWRkaXRpZg0KWV9hZGQgPC0gVF9hZGQgKyBFX2FkZA0KDQphZGRpdGl2ZSA8LSBkYXRhLmZyYW1lKHQsIFlfYWRkKQ0KaGVhZChhZGRpdGl2ZSkNCmdncGxvdChhZGRpdGl2ZSwgYWVzKHg9dCwgeT1ZX2FkZCkpKw0KICBnZW9tX2xpbmUoKSsNCiAgbGFicyh0aXRsZT0iU8OpcmllIFlfYWRkIChwcm9jZXNzdXMgYWRkaXRpZikgZW4gbml2ZWF1IikrDQogIHRoZW1lX2J3KCkNCmBgYA0KDQpPbiB2b2l0IGJpZW4gcXVlIGxhIHPDqXJpZSBzdWl0IHVuZSB0ZW5kYW5jZSBsaW7DqWFpcmUsIGV0IHF1J2VsbGUgZXN0IGRpc3RyaWJ1w6llIGFzc2V6IMOpcXVpdGFibGVtZW50IGF1dG91ciBkZSBjZXR0ZSB0ZW5kYW5jZS4NCg0KIyMjIyBTdGF0aW9ubmFyaXNhdGlvbiBkZSBwcm9jZXNzdXMgYWRkaXRpZg0KDQpcYmVnaW57ZXF1YXRpb259DQogIHlfdCA9IGFfMCArIFxiZXRhIHQgKyBcdmFyZXBzaWxvbl90DQpcZW5ke2VxdWF0aW9ufQ0KTGVzIHLDqXNpZHVzICRcdmFyZXBzaWxvbl90JCBwZXV2ZW50IGRvbmMgw6p0cmUgw6ljcml0cywgZW4gcsOpb3JnYW5pc2FudCBsJ8OpcXVhdGlvbiA6DQpcYmVnaW57ZXF1YXRpb259DQogICBcdmFyZXBzaWxvbl90ID0geV90IC0gYV8wIC0gXGJldGEgdA0KXGVuZHtlcXVhdGlvbn0NCklscyByZXByw6lzZW50ZW50IGRvbmMgbGEgc8OpcmllICR5X3QkLCBtb2lucyBsYSBjb25zdGFudGUgJGFfMCQgZXQgbW9pbnMgbCdpbmZsdWVuY2UgZGUgbGEgdGVuZGVuY2UgJFxiZXRhIHQkLg0KYGBge3J9DQpkZXRyZW5kIDwtIGZlb2xzKFlfYWRkIH4gdCwgZGF0YT1hZGRpdGl2ZSkgDQpldGFibGUoZGV0cmVuZCkNCnRyZW5kX2hhdF9hZGQgPC0gZml0dGVkKGRldHJlbmQpICAgICAgIyB0ZW5kYW5jZSBlc3RpbcOpZQ0KcmVzaWRfYWRkIDwtIHJlc2lkKGRldHJlbmQpICAgICAgICAgICAjIHLDqXNpZHVzIChzw6lyaWUgImTDqS10ZW5kYW5jw6llIikNCg0KZGV0cmVuZGluZ19hZGRpdGl2ZSA8LSBkYXRhLmZyYW1lKGFkZGl0aXZlLCB0cmVuZF9oYXRfYWRkLCByZXNpZF9hZGQpDQpoZWFkKGRldHJlbmRpbmdfYWRkaXRpdmUpDQoNCmdncGxvdChkZXRyZW5kaW5nX2FkZGl0aXZlLCBhZXMoeD10LCB5PVlfYWRkKSkrDQogIGdlb21fbGluZShsd2Q9MSkrDQogIGdlb21fbGluZShhZXMoeT10cmVuZF9oYXRfYWRkKSwgbHR5PTQsIGNvbG9yPSJyZWQiLCBsd2Q9MSkrDQogIGxhYnModGl0bGU9IlPDqXJpZSBZX2FkZCAoYWRkaXRpdmUpIGV0IHRlbmRhbmNlIGFzc29jacOpZSIpKw0KICB0aGVtZV9idygpDQoNCmdncGxvdChkZXRyZW5kaW5nX2FkZGl0aXZlLCBhZXMoeD10LCB5PXJlc2lkX2FkZCkpKw0KICBnZW9tX2xpbmUoKSsNCiAgbGFicyh0aXRsZT0iU8OpcmllIFlfYWRkIChhZGRpdGl2ZSkgZMOpdHJlbmTDqWUiKSsNCiAgdGhlbWVfYncoKQ0KYGBgDQoNCg0KDQoNCiMjIyBQcm9jZXNzdXMgTXVsdGlwbGljYXRpZnMNCkRhbnMgbGUgY2FzIGQndW4gcHJvY2Vzc3VzIG11bHRpcGxpY2F0aWYsIGwnw6lxdWF0aW9uIGRlIGxhIHPDqXJpZSBlc3QgOg0KXGJlZ2lue2VxdWF0aW9ufQ0KWV90ID0gVCBcdGltZXMgRV90DQpcZW5ke2VxdWF0aW9ufQ0KDQojIyMgVmlzdWFsaXNhdGlvbiBQcm9jZXNzdXMgTXVsdGlwbGljYXRpZg0KVmlzdWVsbGVtZW50LCB1bmUgc8OpcmllIHF1aSBzdWl0IHVuIHByb2Nlc3N1cyBtdWx0aXBsaWNhdGlmIHZhIHJlc3NlbWJsZXIgw6AgY2VjaSA6DQoNCmBgYHtyfQ0KIyAyKSBTw6lyaWUgw6AgdGVuZGFuY2UgTVVMVElQTElDQVRJVkU6IFlfdCA9IFRfdCAqIEVfdA0KIyAgICAtIE3Dqm1lIHRlbmRhbmNlIGxpbsOpYWlyZSBtYWlzIG11bHRpcGxpw6llIHBhciBkZXMgY2hvY3MgPiAwDQoNClRfbXVsdCA8LSAwLjUgKiB0ICsgNQ0KRV9tdWx0IDwtIHJsbm9ybShuLCBtZWFubG9nID0gMCwgc2Rsb2cgPSAwLjMpICAgIyBjaG9jcyBtdWx0aXBsaWNhdGlmcyBjZW50csOpcyBhdXRvdXIgZGUgMQ0KWV9tdWx0IDwtIFRfbXVsdCAqIEVfbXVsdA0KDQptdWx0aXBsaWNhdGl2ZSA8LSBkYXRhLmZyYW1lKHQsIFlfbXVsdCkNCmhlYWQobXVsdGlwbGljYXRpdmUpDQoNCmdncGxvdChtdWx0aXBsaWNhdGl2ZSwgYWVzKHg9dCwgeT1ZX211bHQpKSsNCiAgZ2VvbV9saW5lKCkrDQogIGxhYnModGl0bGU9IlPDqXJpZSBZX211bHQgKHByb2Nlc3N1cyBtdWx0aXBsaWNhdGlmKSBlbiBuaXZlYXUiKSsNCiAgdGhlbWVfYncoKQ0KYGBgDQpJY2ksIGxhIGRpc3RyaWJ1dGlvbiBkZSBsYSBzw6lyaWUgc2VtYmxlIG1vaW5zIHN1aXZyZSBsYSB0ZW5kYW5jZSBsaW7DqWFpcmUgcXVlIGRhbnMgbGUgcHJvY2Vzc3VzIGFkZGl0aWYuDQoNCg0KIyMjIyBTdGF0aW9ubmFyaXNhdGlvbiBkZSBwcm9jZXNzdXMgbXVsdGlwbGljYXRpZiANClBvdXIgbGUgcHJvY2Vzc3VzIG11bHRpcGxpY2F0aWYsIGxhIG3Dqm1lIG3DqXRob2RlIHBvdXIgZMOpdHJlbmTDqWUgdmEgZG9ubmVyIGxlcyByw6lzdWx0YXRzIHN1aXZhbnRzIDogDQoNCmBgYHtyfQ0KZGV0cmVuZF9tdWx0IDwtIGZlb2xzKFlfbXVsdCB+IHQsIGRhdGE9bXVsdGlwbGljYXRpdmUpDQpldGFibGUoZGV0cmVuZF9tdWx0KQ0KdHJlbmRfaGF0X211bHQgPC0gZml0dGVkKGRldHJlbmRfbXVsdCkgICAgICAjIHRlbmRhbmNlIGVzdGltw6llDQpyZXNpZF9tdWx0IDwtIHJlc2lkKGRldHJlbmRfbXVsdCkgICAgICAgICAgICMgcsOpc2lkdXMgKHPDqXJpZSAiZMOpLXRlbmRhbmPDqWUiKQ0KDQpkZXRyZW5kaW5nX211bHRpcGxpY2F0aXZlIDwtIGRhdGEuZnJhbWUobXVsdGlwbGljYXRpdmUsIHRyZW5kX2hhdF9tdWx0LCByZXNpZF9tdWx0KQ0KDQpoZWFkKGRldHJlbmRpbmdfbXVsdGlwbGljYXRpdmUpDQoNCmdncGxvdChkZXRyZW5kaW5nX211bHRpcGxpY2F0aXZlLCBhZXMoeD10LCB5PVlfbXVsdCkpKw0KICBnZW9tX2xpbmUoKSsNCiAgZ2VvbV9saW5lKGFlcyh5PXRyZW5kX2hhdF9tdWx0KSwgY29sb3I9InJlZCIsIGx0eT0yLCBsd2Q9MSkrDQogIHRoZW1lX2J3KCkNCg0KZ2dwbG90KGRldHJlbmRpbmdfbXVsdGlwbGljYXRpdmUsIGFlcyh4PXQsIHk9cmVzaWRfbXVsdCkpKw0KICBnZW9tX2xpbmUoKSsNCiAgdGhlbWVfYncoKQ0KYGBgDQpJY2ksIHNpIG9uIHJlcHJlbmQgbGUgbcOqbWUgcHJvY2Vzc3VzIGRlIGTDqS1zdGF0aW9ubmFyaXNhdGlvbiwgb24gdm9pdCBxdWUsIGVmZmVjdGl2ZW1lbnQgbGVzIHLDqXNpZHVzIHNvbnQgZGlzdHJpYnXDqXMgYXV0b3VyIGRlIDAsIGV0IHF1ZSBsJ2VzcMOpcmFuY2UgZGVzIHLDqXNpZHVzIGVzdCBiaWVuIDAuIEVuIHJldmFuY2hlLCBsYSB2YXJpYW5jZSBkZXMgcsOpc2lkdXMgbidlc3QgcGFzIGNvbnN0YW50ZSAoPSoqaGV0ZXJvc2PDqWRhc3RpY2l0w6kqKik6IGVsbGUgYXVnbWVudGUgYXZlYyBsZSB0ZW1wcy4gDQoNClVuIGF1dHJlIG1veWVuLCBxdWkgbmUgcsOoZ2xlIHBhcyB0b3Vqb3VycyBsZSBwcm9ibMOobWUgKG1haXMgcXVpLCBlbiBnw6luw6lyYWwgY2FwdGUgbGVzIGF1dHJlcyBjb21wb3NhbnRlcyBkZSBsYSB2YXJpYXRpb24gZGUgJFlfdCQgY29tbWUgbGUgY3ljbGUgcGFyIGV4ZW1wbGUpIGV0IGRlIG1lc3VyZXIgbGEgbW95ZW5uZSBtb2JpbGUgZGUgbGEgc8OpcmllLCBldCBkZSByZXRpcmVyIGNldHRlIG1veWVubmUgbW9iaWxlIDoNCmBgYHtyfQ0KcmVxdWlyZSh6b28pDQoNCmRldHJlbmRpbmdfbXVsdGlwbGljYXRpdmUyPC1kZXRyZW5kaW5nX211bHRpcGxpY2F0aXZlJT4lDQogIG11dGF0ZShtb3ZpbmdfYXZlcmFnZSA9IHJvbGxhcHBseShZX211bHQsIEZVTj1tZWFuLCB3aWR0aD01LCBmaWxsPU5BLCBhbGlnbj0icmlnaHQiKSklPiUNCiAgbXV0YXRlKGRldHJlbmRlZF9zZXJpZSA9IFlfbXVsdCAtIG1vdmluZ19hdmVyYWdlKSU+JQ0KICBuYS5vbWl0KCkNCg0KZGV0cmVuZGluZ19tdWx0aXBsaWNhdGl2ZTIlPiUNCiAgZ2dwbG90KGFlcyh4PXQsIHk9WV9tdWx0KSkrDQogIGdlb21fbGluZSgpKw0KICBnZW9tX2xpbmUoYWVzKHk9bW92aW5nX2F2ZXJhZ2UpLCBjb2w9InJlZCIsIGx0eT0yLCBsd2Q9MSkrDQogIHRoZW1lX2J3KCkNCg0KZGV0cmVuZGluZ19tdWx0aXBsaWNhdGl2ZTIgJT4lDQogIGdncGxvdChhZXMoeD10LCB5PWRldHJlbmRlZF9zZXJpZSkpKw0KICBnZW9tX2xpbmUoKSsNCiAgdGhlbWVfYncoKQ0KDQpgYGANCkljaSwgw6dhIG4nYSBwYXMgYWlkw6kgw6AgcmV0aXJlciBsJ2jDqXTDqXJvc2PDqWRhc3RpY2l0w6ksIG1haXMgYydlc3QgdW5lIGJvbm5lIGFsdGVybmF0aXZlIChldCBjJ2VzdCB0csOocyBzb3V2ZW50IHV0aWxpc8OpIGRhbnMgbGEgcmVjaGVyY2hlLiBQYXIgZXhlbXBsZSwgY2V0IGFydGljbGUgZGUgbGEgQkNFIChodHRwczovL3d3dy5lY2IuZXVyb3BhLmV1L3B1Yi9wZGYvc2Nwd3BzL2VjYi53cDI4Njh+MGMyYWQyZTZlNy5lbi5wZGYpIHV0aWxpc2UgbGEgbW95ZW5uZSBtb2JpbGUgZGVzIDE1IGRlcm5pw6hyZXMgcMOpcmlvZGVzIHBvdXIgZMOpdHJlbmRlciB1bmUgc8OpcmllIChwYWdlIDE0KS4gSWRlbSBwb3VyIGNldCBhcnRpY2xlIGRlIDE5OTMgOiBodHRwczovL2FjYWRlbWljLm91cC5jb20vcWplL2FydGljbGUtcGRmLzEwOC80LzkwNS81MzY1MDk5LzEwOC00LTkwNS5wZGYpLiANCg0KSWNpLCBjb21tZSBsJ2jDqXTDqXJvc2PDqWRhc3RpY2l0w6kgZXN0IGVuY29yZSBwcsOpc2VudGUsIGlsIGZhdWRyYWl0IMOpdmVudHVlbGxlbWVudCBtb2TDqWxpc2VyIGVtcGlyaXF1ZW1lbnQgbGUgZmFpdCBxdWUgbCdow6l0w6lyb3Njw6lkYXN0aWNpdMOpIGZhaXQgcGFydGllIGR1IHByb2Nlc3N1cyBkZSBsYSBzw6lyaWUsIGRhbnMgdW4gbW9kw6hsZSBBUkNIIChBdXRvLVJlZ3Jlc3NpdmUgQ29uZGl0aW9uYWwgSGV0ZXJvc2tkYXN0aWNpdHkpIG91IEdBUkNIIChHZW5lcmFsaXplZCBBUkNIKSBkdSB0eXBlIDoNClxiZWdpbnthbGlnbip9DQogJnlfdCA9IGFfMCArIFx2YXJlcHNpbG9uX3QgXFwNCiAmXHZhcmVwc2lsb25fdCBcc2ltIE4oMCwgaF90KSBcXA0KICZoX3QgPSBcYmV0YSBoX3t0LTF9ICsgXG11X3QNClxlbmR7YWxpZ24qfQ0KKkxlcyBjaG9jcyBpZGlvc3luY3JhdGlxdWVzIG9udCB1bmUgZGlzdHJpYnV0aW9uIG5vcm1hbGUgYXV0b3VyIGRlIDAsIG1haXMgYXZlYyB1bmUgdmFyaWFuY2UgJGgkIHF1aSBkw6lwZW5kIGR1IHRlbXBzICgkaF90JCksIGV0IG5vdGFtbWVudCBxdWkgZMOpcGVuZCBkZSBsYSB2YXJpYW5jZSBwYXNzw6llLioNCkxlcyBtb2TDqGxlcyBBUkNIL0dBUkNILCBxdSdvbiBuZSB2ZXJyYSBwYXMgcGVuZGFudCBjZXMgc8OpYW5jZXMsIHNvbnQgZGVzIGV4dGVuc2lvbnMgZGVzIG1vZMOobGVzIEFSL01BL0FSSU1BIHF1ZSBsJ29uIHZlcnJhIGRhbnMgbGVzIHPDqWFuY2UgNSwgNiBldCA3LiANCg0KDQpBdXNzaSwgaWwgZmF1dCBiaWVuIHNlIHJhcHBlbGVyIHF1ZSBsZSBidXQgZGUgbGEgc3RhdGlvbm5hcmlzYXRpb24gbidlc3QgcGFzIGRlIHRyYW5zZm9ybWVyIHVuZSBzw6lyaWUgZW4gdW5lIHN1aXRlIHBhcmZhaXRlIGRlIGJydWl0cyBibGFuY3MuIERhbnMgbGEgcsOpYWxpdMOpLCBsZXMgdmFyaWFibGVzICgkWV90JCkgc29udCBhZmZlY3TDqWVzIHBhciBsZXVyIHRlbmRhbmNlLCBsZSBjeWNsZSwgbGEgc2Fpc29ubmFsaXTDqS4gRW4gcmV2YW5jaGUsICoqc3RhdGlvbm5hcmlzZXIgdW5lIHPDqXJpZSBwZXJtZXQgZGUgbCdpc29sZXIgZGUgbCdpbmZsdWVuY2UgZHUgdGVtcHMqKiwgZXQgKiphbcOpbGlvcmUgbCdlc3RpbWF0aW9uIGRlIGwnZWZmZXQgZCdhdXRyZXMgdmFyaWFibGVzIHN1ciBsYSBzw6lyaWUqKi4NCg0KDQoNCg0KDQoNCiNFeGVtcGxlIGRlIHN0YXRpb25uYXJpc2F0aW9uDQoNCk9uIHZhIGQnYWJvcmQgc2ltdWxlciBkZXMgZG9ubsOpZXMgOg0KYGBge3J9DQpzZXQuc2VlZCgxMjMpDQpuICA8LSAyMDAgICAgICAgICAgICAgICMgbG9uZ3VldXIgZGVzIHPDqXJpZXMNCnQgIDwtIDE6biAgICAgICAgICAgICAgIyB2YXJpYWJsZSBxdWkgdmEgZGUgMSDDoCAyMDANCg0KdSA8LSBybm9ybShuLCBtZWFuID0gMCwgc2QgPSAxKSAgICMgbG9pIG5vcm1hbGUgZGUgbW95ZW5uZSBudWxsZSBldCBkJ8OpY2FydCB0eXBlIDENCg0KIyAxKSBTw6lyaWUgSSgxKSA6IFJhbmRvbSBXYWxrIGF2ZWMgbMOpZ2VyIGRyaWZ0DQojICAgIHlfdCA9IHlfe3QtMX0gKyBkICsgdV90DQpkIDwtIDAuMDMNCnkxIDwtIGN1bXN1bShkICsgdSkNCmRpZmZlcmVuY2UgPC0gZGF0YS5mcmFtZSh0LCB5MSkgJT4lDQogIG11dGF0ZShkeTEgPSBjKE5BLCBkaWZmKHkxKSkpDQpoZWFkKGRpZmZlcmVuY2UpDQpgYGANCg0KDQoNCkxhIHByZW1pw6hyZSDDqXRhcGUgZXN0IGRvbmMgZGUgdGVzdGVyIGxhIHByw6lzZW5jZSBkJ3VuIHRyZW5kIDoNCg0KYGBge3J9DQoNCnJlcXVpcmUodXJjYSkNCnN1bW1hcnkodXIuZGYoZGlmZmVyZW5jZSR5MSwgdHlwZT0idHJlbmQiKSkNCmBgYA0KDQoNCkxlIHLDqXN1bHRhdCB0ZXN0IGRlIERpY2tleS1GdWxsZXIgc2UgbGl0IGRlIGxhIGZhw6dvbiBzdWl2YW50ZSA6DQoNCiAgLSB1bmUgcHJlbWnDqHJlIHBhcnRpZSByZXByw6lzZW50ZSBsZSByw6lzdWx0YXQgKHRhYmxlYXUgZGUgcsOpZ3Jlc3Npb24pIGRlIGwnw6lxdWF0aW9uIGFwcGxpcXXDqWUgDQogIC0gdW5lIGRldXhpw6htZSBwYXJ0aWUgcmVwcsOpc2VudGUgbGVzIHN0YXRpc3RpcXVlcyBkdSB0ZXN0IGRlIERpY2tleS1GdWxsZXIgQXVnbWVudMOpLCBvw7kgaWwgZmF1dCBjb21wYXJlciBsZXMgdmFsZXVycyBkZSBsYSAqdC1zdGF0KiAoYHRlc3Qtc3RhdGlzdGljYCkgYXZlYyBsZXMgdmFsZXVycyBjcml0aXF1ZXMgw6AgNSUuDQogIA0KTGUgY29lZmZpY2llbnQgYXNzb2Npw6kgw6AgbGEgdGVuZGFuY2UgYHR0YCBuJ2VzdCBwYXMgc2lnbmlmaWNhdGlmLCBkb25jIGlsIG4neSBhIHBhcyBkZSB0ZW5kYW5jZSBkw6l0ZXJtaW5pc3RlIGTDqXRlY3TDqWUuIE9uIHNhaXQgZG9uYyBxdWUgY2Ugbidlc3QgcGFzIHVuIHByb2Nlc3N1cyBUUy4gRW4gcmV2YW5jaGUsIHF1YW5kIG9uIHJlZ2FyZGUgbGVzICp0LXN0YXRzKiwgb24gcGV1dCB2b2lyIHF1ZSBsYSB2YWxldXIgZHUgdGVzdCBwb3VyIGB0YXUzYCAobGEgcHJlbWnDqHJlIHZhbGV1ciBzdXIgbGEgbGlnbmUgYFZhbHVlIG9mIHRlc3Qtc3RhdGlzdGljIGlzOiAtMi41NjMyIDIuNDczNiAzLjYyNjEgYCkgIG4nZXhjw6hkZSBwYXMgKGVuIHZhbGV1ciBhYnNvbHVlKSBsYSB2YWxldXIgY3JpdGlxdWUgw6AgNSUgOiBvbiBzYWl0IGRvbmMgcXVlIGxhIHPDqXJpZSBuJ2VzdCBkb25jIHBhcyBzdGF0aW9ubmFpcmUuDQoNCk9uIHRlc3QgZW5zdWl0ZSBhdmVjIGxlIG1vZMOobGUgYXZlYyBkcmlmdCAoZG9uYyBhdmVjIHVuZSBjb25zdGFudGUgbm90w6llIGBJbnRlcmNlcHRgIGRhbnMgbGEgcsOpZ3Jlc3Npb24pLg0KDQpgYGB7cn0NCnN1bW1hcnkodXIuZGYoZGlmZmVyZW5jZSR5MSwgdHlwZT0iZHJpZnQiKSkNCmBgYA0KDQoNCkljaSwgb24gcGV1dCB2b2lyIHF1ZSBsZSBjb2VmZmljaWVudCBhc3NvY2nDqSDDoCBsYSBjb25zdGFudGUgZGFuIHNsZSB0YWJsZWF1IGRlIHLDqWdyZXNzaW9uIGVzdCBzaWduaWZpY2F0aWYgw6AgNSUuIElsIHNlbWJsZSBkb25jIHF1ZSBsYSBzw6lyaWUgc29pdCBhZmZlY3TDqWUgcGFyIHVuIGRyaWZ0LiBBdXNzaSwgcXVhbmQgb24gY29tcGFyZSBsYSB2YWxldXIgZGUgbGEgKnQtc3RhdCogYXZlYyBsYSB2YWxldXIgY3JpdGlxdWUgYXNzb2Npw6llIMOgIGB0YXUyYCwgb24gdm9pdCBxdWUgbGEgdmFsZXVyIGRlIGxhICp0LXN0YXQqIG4nZXhjw6hkZSBwYXMgKGVuIHZhbGV1ciBhYnNvbHVlKSBsYSB2YWxldXIgY3JpdGlxdWUgw6AgNSUsIGRvbmMgbGEgc8OpcmllIG4nZXN0IHBhcyBzdGF0aW9ubmFpcmUuIE9uIHNhaXQgZG9uYyBxdWUgbGEgc8OpcmllIG4nZXN0IHBhcyBzdGF0aW9ubmFpcmUsIGV0IHF1J2VsbGUgc3VpdCB1biBwcm9jZXNzdXMgRFMuIElsIHN1ZmZpcmFpdCBkb25jIGRlIGxhIHBhc3NlciBlbiBkaWZmw6lyZW5jZSBwb3VyIHF1J2VsbGUgZGV2aWVubmUgc3RhdGlvbm5haXJlLiBPbiBwZXV0IGxlIHbDqXJpZmllciBlbiBmYWlzYW50IGxlIHRlc3QgZGUgc3RhdGlvbm5hcml0w6kgKHNhbnMgdHJlbmQgbmkgY29uc3RhbnRlKSBzdXIgbGEgc8OpcmllIGVuIGRpZmbDqXJlbmNlIGBkeTFgIDoNCg0KYGBge3J9DQpzdW1tYXJ5KHVyLmRmKGRpZmZlcmVuY2UkZHkxICU+JSBuYS5vbWl0KCkpKQ0KYGBgDQpJY2ksIGxhICp0LXN0YXQqIGV4Y8OoZGUgbGEgdmFsZXVyIGNyaXRpcXVlIMOgIDElIGVuIHZhbGV1ciBhYnNvbHVlLCBjZSBxdWkgaW5kaXF1ZSBxdWUgbGEgc8OpcmllIGVuIGRpZmbDqXJlbmNlIGVzdCBlZmZlY3RpdmVtZW50IHN0YXRpb25uYWlyZS4gT24gcGV1dCBkb25jIGwndXRpbGlzZXIgZGFucyBsZSBjYWRyZSBkJ3VuZSByw6lncmVzc2lvbi4NCg0K