Zadanie
Teraz Wasza kolej ;-)
Waszym zadaniem dzisiaj jest zamodelowanie - porównanie KMNK oraz
regresji kwantylowej (różno-poziomowej) dla zmiennej “earnings” -
wynagrodzenia.
Dobierz i przetestuj predyktory, kwantyle dla modeli. Wykonaj testy
różnic współczynnikow dla finalnych modeli.
W przypadku problemów - obejrzyj video tutorial (włącz polskie
napisy) oraz wejdź na jego stronę ze źródłami. Możesz również
wykorzystać w/w przykłady.
Na początku wczytujemy dane:
data("CPSSW9298")
#?CPSSW9298
Zestaw danych CPSSW9298 jest używany do analizy rynku pracy. Obejmuje
następujące zmienne:
-year: Rok, w którym dane zostały zebrane -earnings: Wynagrodzenie
badanej osoby (wyrażone w tysiącach) -degree: Poziom wykształcenia
badanej osoby, np. “highschool” (szkoła średnia), “bachelor” (tytuł
licencjata) -gender: Płeć osoby, np. “male” (mężczyzna), “female”
(kobieta) -age: Wiek badanej osoby
Wizualizacja danych
Teraz zostanie przeprowadzona analiza kilku wykresów, aby zbadać i
lepiej zrozumieć zależności pomiędzy różnymi zmiennymi.
ggplot(CPSSW9298, aes(x = earnings)) +
geom_histogram(bins = 30, fill = "mediumpurple", color = "black") +
labs(
title = "Rozkład wynagrodzeń",
x = "Wynagrodzenie (w tysiącach)",
y = "Liczba obserwacji"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, color = "black"),
axis.title = element_text(size = 12, color = "black"),
axis.text = element_text(size = 10)
)

Rozkład wynagrodzeń jest asymetryczny, z wyraźnym prawostronnym
ogonem, co oznacza, że większa liczba osób zarabia niższe wynagrodzenia,
podczas gdy wyższe wynagrodzenia są rzadsze. Kształt sugeruje, że
wynagrodzenia mogą być rozkładem skośnym (skośność
prawostronna).Najwięcej osób zarabia około 10 tysięcy (zauważalny
najwyższy słupek histogramu w tej okolicy).
ggplot(CPSSW9298, aes(x = degree, y = earnings, fill = degree)) +
geom_boxplot() +
scale_fill_manual(values = c("mediumpurple", "gold")) +
labs(
title = "Wynagrodzenie względem wykształcenia",
x = "Poziom wykształcenia",
y = "Wynagrodzenie (w tysiącach)"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, color = "black"),
axis.title = element_text(size = 12, color = "black"),
axis.text = element_text(size = 10),
legend.position = "none"
)

Osoby z wykształceniem “bachelor” (licencjackim) mają wyższą medianę
wynagrodzeń w porównaniu do osób z wykształceniem “highschool”
(średnim).Wynagrodzenia dla obu grup są zróżnicowane, ale rozstęp
międzykwartylowy (odległość między dolnym i górnym kwartylem) jest
większy dla osób z wykształceniem licencjackim, co wskazuje na większe
zróżnicowanie wynagrodzeń w tej grupie.W obu grupach widać obecność
wartości odstających (outliers), czyli osób zarabiających znacznie
więcej niż większość. Liczba wartości odstających jest wyższa w grupie z
wykształceniem “bachelor”.
ggplot(CPSSW9298, aes(x = year, y = earnings)) +
stat_summary(fun = "mean", geom = "line", aes(group = 1), color = "darkorchid", linewidth = 1) +
stat_summary(fun = "mean", geom = "point", color = "purple", size = 2) +
labs(
title = "Średnie wynagrodzenie w czasie",
x = "Rok",
y = "Średnie wynagrodzenie (w tysiącach)"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, color = "black"),
axis.title = element_text(size = 12, color = "black"),
axis.text = element_text(size = 10)
)

Średnie wynagrodzenie systematycznie rosło w czasie w analizowanym
okresie (1992–1998). Taki wzrost może wynikać z ogólnej poprawy
gospodarki, inflacji, lub zmian w strukturze rynku pracy.
ggplot(CPSSW9298, aes(x = gender, y = earnings, fill = gender)) +
geom_boxplot() +
scale_fill_manual(values = c("mediumpurple", "gold")) +
labs(
title = "Wynagrodzenie względem płci",
x = "Płeć",
y = "Wynagrodzenie (w tysiącach)"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, color = "black"),
axis.title = element_text(size = 12, color = "black"),
axis.text = element_text(size = 10),
legend.position = "none"
)

Mężczyźni (“male”) mają wyższą medianę wynagrodzeń w porównaniu do
kobiet (“female”).Wynagrodzenia zarówno mężczyzn, jak i kobiet
charakteryzują się obecnością wartości odstających, ale mężczyźni mają
większy rozstęp maksymalnych wynagrodzeń.
ggplot(CPSSW9298, aes(x = earnings, fill = gender)) +
geom_histogram(alpha = 0.7, bins = 30, position = "identity") +
scale_fill_manual(values = c("mediumpurple", "gold")) +
labs(
title = "Rozkład wynagrodzeń według płci",
x = "Wynagrodzenie (w tysiącach)",
y = "Liczba obserwacji"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
axis.title = element_text(size = 14),
axis.text = element_text(size = 12),
legend.title = element_blank()
)

Wynagrodzenia dla obu płci mają prawostronną skośność – większość
osób zarabia w dolnym zakresie wynagrodzeń (poniżej 20 tysięcy), a
liczba osób zarabiających więcej systematycznie maleje. Mężczyźni
osiągają szerszy zakres wynagrodzeń, w tym najwyższe zarobki, co
potwierdzają dłuższe „ogony” fioletowego rozkładu.
ggplot(CPSSW9298, aes(x = age, y = earnings)) +
geom_point(alpha = 0.7, color = "mediumpurple") +
geom_smooth(aes(x = age, y = earnings), method = "lm", formula = y ~ x, se = FALSE, linetype = "dashed", color = "gold") +
labs(
title = "Wynagrodzenie względem wieku",
x = "wiek",
y = "wynagrodzenie (w tysiącach)"
) +
facet_grid(gender ~ degree) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
axis.title = element_text(size = 14),
axis.text = element_text(size = 12)
)

Powyższy wykres potwierdza dotychczasowe obserwacje.Osoby z
wykształceniem “bachelor” (licencjackim) osiągają wyższe wynagrodzenia w
porównaniu do osób z wykształceniem “highschool” (średnim). Jest to
widoczne zarówno w przypadku mężczyzn, jak i kobiet.Różnica między
wynagrodzeniami mężczyzn i kobiet jest widoczna zarówno w grupie osób z
wykształceniem średnim, jak i licencjackim.
Model liniowy
model_lm <- lm(CPSSW9298$earnings ~ CPSSW9298$degree + CPSSW9298$gender + CPSSW9298$age)
summary(model_lm)
##
## Call:
## lm(formula = CPSSW9298$earnings ~ CPSSW9298$degree + CPSSW9298$gender +
## CPSSW9298$age)
##
## Residuals:
## Min 1Q Median 3Q Max
## -15.023 -3.735 -0.819 2.755 33.526
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.70477 0.52435 3.251 0.00115 **
## CPSSW9298$degreebachelor 4.91123 0.09938 49.418 < 2e-16 ***
## CPSSW9298$genderfemale -2.24217 0.09902 -22.643 < 2e-16 ***
## CPSSW9298$age 0.33245 0.01740 19.106 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 5.665 on 13497 degrees of freedom
## Multiple R-squared: 0.1877, Adjusted R-squared: 0.1876
## F-statistic: 1040 on 3 and 13497 DF, p-value: < 2.2e-16
Interpretacje:
- Osoby z wykształceniem licencjackim zarabiają średnio o 4.91 tys.
więcej niż osoby z wykształceniem średnim (przy stałej płci i
wieku).
- Kobiety zarabiają średnio o 2.24 tys. mniej niż mężczyźni (przy
stałym poziomie wykształcenia i wieku).
- Każdy dodatkowy rok życia zwiększa zarobki średnio o 0.33 tys. (przy
stałej płci i wykształceniu).
Model wyjaśnia około 18.77% zmienności w zarobkach. Oznacza to, że
model nie uwzględnia wielu innych czynników, które wpływają na zarobki
(np. branża, lokalizacja, doświadczenie zawodowe).
Regresja kwantylowa
data <- CPSSW9298
kwantyle <- c(0.25, 0.50, 0.75)
reg_kwantylowa <- rq(earnings ~ age + degree + gender , tau = kwantyle, data = data)
summary(reg_kwantylowa, se = "boot")
##
## Call: rq(formula = earnings ~ age + degree + gender, tau = kwantyle,
## data = data)
##
## tau: [1] 0.25
##
## Coefficients:
## Value Std. Error t value Pr(>|t|)
## (Intercept) 2.67308 0.38777 6.89339 0.00000
## age 0.17308 0.01365 12.67920 0.00000
## degreebachelor 3.59188 0.06431 55.84980 0.00000
## genderfemale -1.32265 0.07062 -18.72785 0.00000
##
## Call: rq(formula = earnings ~ age + degree + gender, tau = kwantyle,
## data = data)
##
## tau: [1] 0.5
##
## Coefficients:
## Value Std. Error t value Pr(>|t|)
## (Intercept) 1.45427 0.49704 2.92588 0.00344
## age 0.31389 0.01729 18.15274 0.00000
## degreebachelor 4.70043 0.11085 42.40338 0.00000
## genderfemale -2.12970 0.09624 -22.12868 0.00000
##
## Call: rq(formula = earnings ~ age + degree + gender, tau = kwantyle,
## data = data)
##
## tau: [1] 0.75
##
## Coefficients:
## Value Std. Error t value Pr(>|t|)
## (Intercept) 1.53846 0.92264 1.66747 0.09544
## age 0.43269 0.02998 14.43478 0.00000
## degreebachelor 5.75962 0.15277 37.70122 0.00000
## genderfemale -2.97009 0.12878 -23.06241 0.00000
Analiza wpływu wieku, wykształcenia i płci na zarobki w różnych
kwantylach dostarcza interesujących wniosków. Wyniki wskazują, że
starszy wiek ma większy wpływ na zarobki osób znajdujących się w
wyższych kwantylach wynagrodzeń. W dolnym 25% zarobków każdy rok życia
zwiększa wynagrodzenie o 0.17 tys., podczas gdy w grupie najlepiej
zarabiających (75%) wzrost wynosi już 0.43 tys. Oznacza to, że starszy
wiek bardziej korzystnie wpływa na osoby osiągające wyższe dochody.
Wykształcenie licencjackie również odgrywa istotną rolę, szczególnie
w medianie i górnych kwantylach. W grupie osób z najniższymi zarobkami
wykształcenie licencjackie zwiększa wynagrodzenie średnio o 3.59 tys.,
ale w medianie i wśród najlepiej zarabiających wpływ ten rośnie do 4.70
tys. Świadczy to o tym, że wyższe wykształcenie ma szczególną wartość
wśród osób z wyższymi dochodami.
Różnice w wynagrodzeniach między płciami są widoczne we wszystkich
kwantylach, ale najbardziej niepokojące są w górnym 25% zarobków.
Kobiety zarabiają mniej niż mężczyźni, a różnice te rosną w zależności
od poziomu dochodów: od 1.32 tys. w najniższych zarobkach do 2.97 tys.
wśród najlepiej zarabiających.
plot(rq(earnings ~ age + degree + gender, tau = c(0.25, 0.5, 0.75), data = data))

kwantyle <- c(0.25, 0.50, 0.75)
model_q25 <- rq(earnings ~ age + degree + gender, tau = 0.25, data = data)
model_q50 <- rq(earnings ~ age + degree + gender, tau = 0.50, data = data)
model_q75 <- rq(earnings ~ age + degree + gender, tau = 0.75, data = data)
coef_q25 <- coef(model_q25)
coef_q50 <- coef(model_q50)
coef_q75 <- coef(model_q75)
coef_table <- data.frame(
Kwantyl = c(0.25, 0.50, 0.75),
Intercept = c(coef_q25[1], coef_q50[1], coef_q75[1]),
Age = c(coef_q25["age"], coef_q50["age"], coef_q75["age"]),
Degree = c(coef_q25["degreebachelor"], coef_q50["degreebachelor"], coef_q75["degreebachelor"]),
Gender = c(coef_q25["genderfemale"], coef_q50["genderfemale"], coef_q75["genderfemale"])
)
print(coef_table)
## Kwantyl Intercept Age Degree Gender
## 1 0.25 2.673078 0.1730769 3.591880 -1.322649
## 2 0.50 1.454274 0.3138889 4.700427 -2.129701
## 3 0.75 1.538464 0.4326922 5.759616 -2.970085
Tabela przedstawia wyniki regresji kwantylowej dla trzech wybranych
kwantyli: 0.25 (dolne 25% zarobków), 0.50 (mediana zarobków), i 0.75
(górne 25% zarobków). Jest to analiza, która pozwala zobaczyć, jak
zmienne niezależne wpływają na zarobki w różnych częściach rozkładu
wynagrodzeń, a nie tylko na średnią (jak w klasycznej regresji
liniowej).
Weryfikacja statystyczna istotności różnic między pierwszym, drugim
i trzecim kwartylem
anova(reg_kwantylowa, test = "Wald", joint=TRUE)
## Quantile Regression Analysis of Deviance Table
##
## Model: earnings ~ age + degree + gender
## Joint Test of Equality of Slopes: tau in { 0.25 0.5 0.75 }
##
## Df Resid Df F value Pr(>F)
## 1 6 40497 90.65 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Hipoteza zerowa: Współczynniki dla kwantyli są takie same. Hipoteza
alternatywna: Współczynniki różnią się między kwantylami.
Ponieważ wartość p jest bardzo niska, odrzucamy hipotezę zerową.
Oznacza to, że wpływ zmiennych (wiek, wykształcenie, płeć) różni się w
różnych częściach rozkładu zarobków.
anova(reg_kwantylowa, test = "Wald", joint=FALSE)
## Quantile Regression Analysis of Deviance Table
##
## Model: earnings ~ age + degree + gender
## Tests of Equality of Distinct Slopes: tau in { 0.25 0.5 0.75 }
##
## Df Resid Df F value Pr(>F)
## age 2 40501 72.465 < 2.2e-16 ***
## degreebachelor 2 40501 117.817 < 2.2e-16 ***
## genderfemale 2 40501 88.771 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Wszystkie zmienne (age, degreebachelor, genderfemale) mają istotnie
różny wpływ na zarobki w zależności od kwantyla.
Dobroć dopasowania
# Obliczenie reszt dla modeli
reszty_lm <- resid(model_lm)
model2 <- rq(earnings ~ 1, tau = 0.25, data = data)
reszty_2 <- resid(model2)
model3 <- rq(earnings ~ 1, tau = 0.75,data=data)
reszty3 <- resid(model3)
par(mfrow = c(1, 3)) # Podziel przestrzeń na 3 kolumny
# Histogram dla modelu liniowego
hist(reszty_lm,
main = "Histogram reszt (model liniowy)",
xlab = "Reszty",
col = "black", border = "grey")
# Histogram dla modelu kwantylowego tau = 0.25
hist(reszty_2,
main = "Histogram reszt (tau = 0.25)",
xlab = "Reszty",
col = "gold", border = "black")
# Histogram dla modelu kwantylowego tau = 0.75
hist(reszty3,
main = "Histogram reszt (tau = 0.75)",
xlab = "Reszty",
col = "purple", border = "black")

coef_long <- reshape2::melt(coef_table, id.vars = "Kwantyl",
variable.name = "Zmienna", value.name = "Współczynnik")
ggplot(coef_long, aes(x = Kwantyl, y = Współczynnik, color = Zmienna)) +
geom_line(size = 1) +
geom_point(size = 2) +
labs(
title = "Współczynniki regresji kwantylowej",
x = "Kwantyl",
y = "Współczynnik",
color = "Zmienna"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 16),
axis.title = element_text(size = 12),
legend.title = element_text(size = 12)
)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Wpływ zmiennych jest zróżnicowany w różnych częściach rozkładu
zarobków, co wskazuje na to, że klasyczna regresja liniowa (która
zakłada stały wpływ zmiennych na całość rozkładu) mogłaby nie uchwycić
tych różnic.
-Wpływ wieku rośnie wraz ze wzrostem kwantyla. Starszy wiek ma
największy wpływ na zarobki w grupie najlepiej zarabiających, co jest
zgodne z oczekiwaniem, że doświadczenie zawodowe bardziej się opłaca w
tej grupie. - Wykształcenie ma rosnący wpływ w miarę wzrostu kwantyla.
Sugeruje to, że wartość wyższego wykształcenia jest bardziej doceniana w
grupie osób osiągających najwyższe dochody. - Wartości ujemne
współczynnika Gender wskazują na niższe zarobki kobiet w porównaniu do
mężczyzn.
LS0tDQp0aXRsZTogJ1JlZ3Jlc2phIGt3YW50eWxvd2EnDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQphdXRob3I6ICJNYcWCZ29yemF0YSBEdWRhbm93aWN6Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0aGVtZTogY2VydWxlYW4NCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlDQogICAgZm9udHNpemU6IDEwcHQNCiAgICB0b2M6IHllcw0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogbm8NCiAgICBkZl9wcmludDogZGVmYXVsdA0KICAgIHRvY19kZXB0aDogNQ0KZWRpdG9yX29wdGlvbnM6IA0KICBtYXJrZG93bjogDQogICAgd3JhcDogNzINCi0tLQ0KDQpgYGB7ciBwcmVyZXFzLCBtZXNzYWdlID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0NCmxpYnJhcnkoQ1ZYUikNCmxpYnJhcnkoQUVSKQ0KbGlicmFyeShzdGFyZ2F6ZXIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkocXVhbnRyZWcpDQpsaWJyYXJ5KFBvZ3JvbWN5RGFueWNoKQ0KbGlicmFyeSh2Y2QpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KYGBgDQoNCiMjIERsYWN6ZWdvIGt3YW50eWxvd2E/DQoNCkRsYWN6ZWdvIHBvdHJ6ZWJ1amVteSByZWdyZXNqaSBrd2FudHlsb3dlaiAoUVIpPw0KDQpXIHN6Y3plZ8OzbG5vxZtjaSwgUVI6DQoNCi0gICBqZXN0IG9kcG9ybmEgbmEgcHVua3R5IG9kc3RhasSFY2UgaSB3cMWCeXdvd2UNCg0KLSAgIG5pZSB6YWvFgmFkYSBzdGHFgmVqIHdhcmlhbmNqaSAoem5hbmVqIGpha28gaG9tb3NrZWRhc3R5Y3pub8WbxIcpIGRsYQ0KICAgIHptaWVubmVqIG9kcG93aWVkemkgbHViIHJlc3p0DQoNCi0gICBuaWUgemFrxYJhZGEgbm9ybWFsbm/Fm2NpIGFsZSBnxYLDs3duxIUgemFsZXTEhSBRUiB3IHBvcsOzd25hbml1IHogcmVncmVzasSFDQogICAgbGluaW93xIUgKExSKSBqZXN0IHRvLCDFvGUgUVIgYmFkYSByw7PFvG5lIHdhcnRvxZtjaSB6bWllbm5laiBvZHBvd2llZHppLA0KICAgIGEgbmllIHR5bGtvIMWbcmVkbmnEhSwgaSBkb3N0YXJjemEgdyB6d2nEhXprdSB6IHR5bSBwZcWCbmllanN6ZWdvIG9icmF6dQ0KICAgIHp3acSFemvDs3cgbWnEmWR6eSB6bWllbm55bWkhDQoNCiMjIFdwcm93YWR6ZW5pZQ0KDQpSZWdyZXNqYSBrd2FudHlsb3dhIChhbmcuIHF1YW50aWxlIHJlZ3Jlc3Npb24pIHpvc3RhxYJhIHphcHJvcG9ub3dhbmENCnByemV6IEtvZW5rZXJhIGkgQmFzc2V0dGEgKDE5NzgpLiBTemN6ZWfDs2xueSBwcnp5cGFkZWsgcmVncmVzamkNCmt3YW50eWxvd2VqIGRsYSBrd2FudHlsYSByesSZZHUgMCw1IChjenlsaSBtZWRpYW55KSBqZXN0IHLDs3dub3dhxbxueQ0KZXN0eW1hdG9yb3dpIExBRCAoYW5nLiBMZWFzdCBBYnNvbHV0ZSBEZXZpYXRpb24pIC0tIG1pbmltYWxpenVqZSBzdW3EmQ0KYmV6d3pnbMSZZG55Y2ggYsWCxJlkw7N3LlwNCldwcm93YWR6ZW5pZSByw7PFvG55Y2gga3dhbnR5bGkgcmVncmVzamkgZGFqZSBwZcWCbmllanN6eSBvcGlzIHJvemvFgmFkw7N3DQp3YXJ1bmtvd3ljaCB6d8WCYXN6Y3phIHcgcHJ6eXBhZGt1IHJvemvFgmFkw7N3IGFzeW1ldHJ5Y3pueWNoIGx1YiB1Y2nEmXR5Y2guDQoNCg0KIyMgV3ltYWdhbmlhDQoNCld5bWFnYW5hIGplc3QgamVkbmEgbGljemJvd2Egem1pZW5uYSB6YWxlxbxuYS4gWm1pZW5uYSBwcnpld2lkeXdhbmEgbXVzaQ0KYnnEhyB6bWllbm7EhSBpbG/Fm2Npb3fEhS4gUHJlZHlrdG9yeSBtb2fEhSBiecSHIHptaWVubnltaSBpbG/Fm2Npb3d5bWkgbHViDQpzenR1Y3pueW1pIHptaWVubnltaSB3IHByenlwYWRrdSBwcmVkeWt0b3LDs3cgamFrb8WbY2lvd3ljaC4gQWJ5IG1vxbxuYQ0KYnnFgm8gdXJ1Y2hvbWnEhyBhbmFsaXrEmSwgd3ltYWdhbnkgamVzdCB3eXJheiB3b2xueSBsdWIgY28gbmFqbW5pZWogamVkZW4NCnByZWR5a3Rvci4NCg0KUmVncmVzamEga3dhbnR5bG93YSBuaWUgY3p5bmkgemHFgm/FvGXFhCBkb3R5Y3rEhWN5Y2ggcm96a8WCYWR1IHptaWVubmVqDQpwcnpld2lkeXdhbmVqIGkgamVzdCBvZHBvcm5hIG5hIHdwxYJ5dyBvYnNlcndhY2ppIG9kc3RhasSFY3ljaC4NCg0KQW5hbGl6YSBrd2FudHlsb3dhIGplc3QgcG9rcmV3bmEgcmVncmVzamkgbWV0b2TEhSBuYWptbmllanN6eWNoDQprd2FkcmF0w7N3Lg0KDQojIyBaYWRhbmllDQoNClRlcmF6IFdhc3phIGtvbGVqIDstKQ0KDQpXYXN6eW0gemFkYW5pZW0gZHppc2lhaiBqZXN0IHphbW9kZWxvd2FuaWUgLSBwb3LDs3duYW5pZSBLTU5LIG9yYXoNCnJlZ3Jlc2ppIGt3YW50eWxvd2VqIChyw7PFvG5vLXBvemlvbW93ZWopIGRsYSB6bWllbm5laiAiZWFybmluZ3MiIC0NCnd5bmFncm9kemVuaWEuDQoNCkRvYmllcnogaSBwcnpldGVzdHVqIHByZWR5a3RvcnksIGt3YW50eWxlIGRsYSBtb2RlbGkuIFd5a29uYWogdGVzdHkNCnLDs8W8bmljIHdzcMOzxYJjenlubmlrb3cgZGxhIGZpbmFsbnljaCBtb2RlbGkuDQoNClcgcHJ6eXBhZGt1IHByb2JsZW3Ds3cgLSBvYmVqcnp5aiB2aWRlbyB0dXRvcmlhbCAod8WCxIVjeiBwb2xza2llIG5hcGlzeSkNCm9yYXogd2VqZMW6IG5hIGplZ28gc3Ryb27EmSB6ZSDFunLDs2TFgmFtaS4gTW/FvGVzeiByw7N3bmllxbwgd3lrb3J6eXN0YcSHIHcvdw0KcHJ6eWvFgmFkeS4NCg0KTmEgcG9jesSFdGt1IHdjenl0dWplbXkgZGFuZToNCg0KYGBge3J9DQpkYXRhKCJDUFNTVzkyOTgiKQ0KIz9DUFNTVzkyOTggDQpgYGANCg0KWmVzdGF3IGRhbnljaCBDUFNTVzkyOTggamVzdCB1xbx5d2FueSBkbyBhbmFsaXp5IHJ5bmt1IHByYWN5LiBPYmVqbXVqZSBuYXN0xJlwdWrEhWNlIHptaWVubmU6DQoNCi15ZWFyOiBSb2ssIHcga3TDs3J5bSBkYW5lIHpvc3RhxYJ5IHplYnJhbmUNCi1lYXJuaW5nczogV3luYWdyb2R6ZW5pZSBiYWRhbmVqIG9zb2J5ICh3eXJhxbxvbmUgdyB0eXNpxIVjYWNoKQ0KLWRlZ3JlZTogUG96aW9tIHd5a3N6dGHFgmNlbmlhIGJhZGFuZWogb3NvYnksIG5wLiAiaGlnaHNjaG9vbCIgKHN6a2/FgmEgxZtyZWRuaWEpLCAiYmFjaGVsb3IiICh0eXR1xYIgbGljZW5jamF0YSkNCi1nZW5kZXI6IFDFgmXEhyBvc29ieSwgbnAuICJtYWxlIiAobcSZxbxjenl6bmEpLCAiZmVtYWxlIiAoa29iaWV0YSkNCi1hZ2U6IFdpZWsgYmFkYW5laiBvc29ieQ0KDQojIyMgV2l6dWFsaXphY2phIGRhbnljaA0KDQpUZXJheiB6b3N0YW5pZSBwcnplcHJvd2Fkem9uYSBhbmFsaXphIGtpbGt1IHd5a3Jlc8OzdywgYWJ5IHpiYWRhxIcgaSBsZXBpZWogenJvenVtaWXEhyB6YWxlxbxub8WbY2kgcG9tacSZZHp5IHLDs8W8bnltaSB6bWllbm55bWkuIA0KDQpgYGB7cn0NCmdncGxvdChDUFNTVzkyOTgsIGFlcyh4ID0gZWFybmluZ3MpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCwgZmlsbCA9ICJtZWRpdW1wdXJwbGUiLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJSb3prxYJhZCB3eW5hZ3JvZHplxYQiLA0KICAgIHggPSAiV3luYWdyb2R6ZW5pZSAodyB0eXNpxIVjYWNoKSIsDQogICAgeSA9ICJMaWN6YmEgb2JzZXJ3YWNqaSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNiwgY29sb3IgPSAiYmxhY2siKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiYmxhY2siKSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQ0KICApDQpgYGANCg0KUm96a8WCYWQgd3luYWdyb2R6ZcWEIGplc3QgYXN5bWV0cnljem55LCB6IHd5cmHFum55bSBwcmF3b3N0cm9ubnltIG9nb25lbSwgY28gb3puYWN6YSwgxbxlIHdpxJlrc3phIGxpY3piYSBvc8OzYiB6YXJhYmlhIG5pxbxzemUgd3luYWdyb2R6ZW5pYSwgcG9kY3phcyBnZHkgd3nFvHN6ZSB3eW5hZ3JvZHplbmlhIHPEhSByemFkc3plLiBLc3p0YcWCdCBzdWdlcnVqZSwgxbxlIHd5bmFncm9kemVuaWEgbW9nxIUgYnnEhyByb3prxYJhZGVtIHNrb8WbbnltIChza2/Fm25vxZvEhyBwcmF3b3N0cm9ubmEpLk5handpxJljZWogb3PDs2IgemFyYWJpYSBva2/Fgm8gMTAgdHlzacSZY3kgKHphdXdhxbxhbG55IG5hand5xbxzenkgc8WCdXBlayBoaXN0b2dyYW11IHcgdGVqIG9rb2xpY3kpLg0KDQpgYGB7cn0NCmdncGxvdChDUFNTVzkyOTgsIGFlcyh4ID0gZGVncmVlLCB5ID0gZWFybmluZ3MsIGZpbGwgPSBkZWdyZWUpKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygibWVkaXVtcHVycGxlIiwgImdvbGQiKSkgKyANCiAgbGFicygNCiAgICB0aXRsZSA9ICJXeW5hZ3JvZHplbmllIHd6Z2zEmWRlbSB3eWtzenRhxYJjZW5pYSIsDQogICAgeCA9ICJQb3ppb20gd3lrc3p0YcWCY2VuaWEiLA0KICAgIHkgPSAiV3luYWdyb2R6ZW5pZSAodyB0eXNpxIVjYWNoKSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNiwgY29sb3IgPSAiYmxhY2siKSwgIA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJibGFjayIpLCAgDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiDQogICkNCmBgYA0KDQpPc29ieSB6IHd5a3N6dGHFgmNlbmllbSAiYmFjaGVsb3IiIChsaWNlbmNqYWNraW0pIG1hasSFIHd5xbxzesSFIG1lZGlhbsSZIHd5bmFncm9kemXFhCB3IHBvcsOzd25hbml1IGRvIG9zw7NiIHogd3lrc3p0YcWCY2VuaWVtICJoaWdoc2Nob29sIiAoxZtyZWRuaW0pLld5bmFncm9kemVuaWEgZGxhIG9idSBncnVwIHPEhSB6csOzxbxuaWNvd2FuZSwgYWxlIHJvenN0xJlwIG1pxJlkenlrd2FydHlsb3d5IChvZGxlZ8WCb8WbxIcgbWnEmWR6eSBkb2xueW0gaSBnw7NybnltIGt3YXJ0eWxlbSkgamVzdCB3acSZa3N6eSBkbGEgb3PDs2IgeiB3eWtzenRhxYJjZW5pZW0gbGljZW5jamFja2ltLCBjbyB3c2thenVqZSBuYSB3acSZa3N6ZSB6csOzxbxuaWNvd2FuaWUgd3luYWdyb2R6ZcWEIHcgdGVqIGdydXBpZS5XIG9idSBncnVwYWNoIHdpZGHEhyBvYmVjbm/Fm8SHIHdhcnRvxZtjaSBvZHN0YWrEhWN5Y2ggKG91dGxpZXJzKSwgY3p5bGkgb3PDs2IgemFyYWJpYWrEhWN5Y2ggem5hY3puaWUgd2nEmWNlaiBuacW8IHdpxJlrc3pvxZvEhy4gTGljemJhIHdhcnRvxZtjaSBvZHN0YWrEhWN5Y2ggamVzdCB3ecW8c3phIHcgZ3J1cGllIHogd3lrc3p0YcWCY2VuaWVtICJiYWNoZWxvciIuDQoNCmBgYHtyfQ0KZ2dwbG90KENQU1NXOTI5OCwgYWVzKHggPSB5ZWFyLCB5ID0gZWFybmluZ3MpKSArDQogIHN0YXRfc3VtbWFyeShmdW4gPSAibWVhbiIsIGdlb20gPSAibGluZSIsIGFlcyhncm91cCA9IDEpLCBjb2xvciA9ICJkYXJrb3JjaGlkIiwgbGluZXdpZHRoID0gMSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuID0gIm1lYW4iLCBnZW9tID0gInBvaW50IiwgY29sb3IgPSAicHVycGxlIiwgc2l6ZSA9IDIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICLFmnJlZG5pZSB3eW5hZ3JvZHplbmllIHcgY3phc2llIiwNCiAgICB4ID0gIlJvayIsDQogICAgeSA9ICLFmnJlZG5pZSB3eW5hZ3JvZHplbmllICh3IHR5c2nEhWNhY2gpIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE2LCBjb2xvciA9ICJibGFjayIpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJibGFjayIpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApDQogICkNCg0KYGBgDQoNCsWacmVkbmllIHd5bmFncm9kemVuaWUgc3lzdGVtYXR5Y3puaWUgcm9zxYJvIHcgY3phc2llIHcgYW5hbGl6b3dhbnltIG9rcmVzaWUgKDE5OTLigJMxOTk4KS4gVGFraSB3enJvc3QgbW/FvGUgd3luaWthxIcgeiBvZ8OzbG5laiBwb3ByYXd5IGdvc3BvZGFya2ksIGluZmxhY2ppLCBsdWIgem1pYW4gdyBzdHJ1a3R1cnplIHJ5bmt1IHByYWN5Lg0KDQpgYGB7cn0NCmdncGxvdChDUFNTVzkyOTgsIGFlcyh4ID0gZ2VuZGVyLCB5ID0gZWFybmluZ3MsIGZpbGwgPSBnZW5kZXIpKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygibWVkaXVtcHVycGxlIiwgImdvbGQiKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIld5bmFncm9kemVuaWUgd3pnbMSZZGVtIHDFgmNpIiwNCiAgICB4ID0gIlDFgmXEhyIsDQogICAgeSA9ICJXeW5hZ3JvZHplbmllICh3IHR5c2nEhWNhY2gpIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE2LCBjb2xvciA9ICJibGFjayIpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJibGFjayIpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIg0KICApDQpgYGANCg0KTcSZxbxjennFum5pICgibWFsZSIpIG1hasSFIHd5xbxzesSFIG1lZGlhbsSZIHd5bmFncm9kemXFhCB3IHBvcsOzd25hbml1IGRvIGtvYmlldCAoImZlbWFsZSIpLld5bmFncm9kemVuaWEgemFyw7N3bm8gbcSZxbxjenl6biwgamFrIGkga29iaWV0IGNoYXJha3Rlcnl6dWrEhSBzacSZIG9iZWNub8WbY2nEhSB3YXJ0b8WbY2kgb2RzdGFqxIVjeWNoLCBhbGUgbcSZxbxjennFum5pIG1hasSFIHdpxJlrc3p5IHJvenN0xJlwIG1ha3N5bWFsbnljaCB3eW5hZ3JvZHplxYQuDQoNCmBgYHtyfQ0KZ2dwbG90KENQU1NXOTI5OCwgYWVzKHggPSBlYXJuaW5ncywgZmlsbCA9IGdlbmRlcikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWxwaGEgPSAwLjcsIGJpbnMgPSAzMCwgcG9zaXRpb24gPSAiaWRlbnRpdHkiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIm1lZGl1bXB1cnBsZSIsICJnb2xkIikpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJSb3prxYJhZCB3eW5hZ3JvZHplxYQgd2VkxYJ1ZyBwxYJjaSIsDQogICAgeCA9ICJXeW5hZ3JvZHplbmllICh3IHR5c2nEhWNhY2gpIiwNCiAgICB5ID0gIkxpY3piYSBvYnNlcndhY2ppIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpDQogICkNCmBgYA0KDQpXeW5hZ3JvZHplbmlhIGRsYSBvYnUgcMWCY2kgbWFqxIUgcHJhd29zdHJvbm7EhSBza2/Fm25vxZvEhyDigJMgd2nEmWtzem/Fm8SHIG9zw7NiIHphcmFiaWEgdyBkb2xueW0gemFrcmVzaWUgd3luYWdyb2R6ZcWEIChwb25pxbxlaiAyMCB0eXNpxJljeSksIGEgbGljemJhIG9zw7NiIHphcmFiaWFqxIVjeWNoIHdpxJljZWogc3lzdGVtYXR5Y3puaWUgbWFsZWplLiBNxJnFvGN6ecW6bmkgb3NpxIVnYWrEhSBzemVyc3p5IHpha3JlcyB3eW5hZ3JvZHplxYQsIHcgdHltIG5hand5xbxzemUgemFyb2JraSwgY28gcG90d2llcmR6YWrEhSBkxYJ1xbxzemUg4oCeb2dvbnnigJ0gZmlvbGV0b3dlZ28gcm96a8WCYWR1Lg0KDQpgYGB7cn0NCmdncGxvdChDUFNTVzkyOTgsIGFlcyh4ID0gYWdlLCB5ID0gZWFybmluZ3MpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjcsIGNvbG9yID0gIm1lZGl1bXB1cnBsZSIpICsNCiAgZ2VvbV9zbW9vdGgoYWVzKHggPSBhZ2UsIHkgPSBlYXJuaW5ncyksIG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSB5IH4geCwgc2UgPSBGQUxTRSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ29sZCIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJXeW5hZ3JvZHplbmllIHd6Z2zEmWRlbSB3aWVrdSIsDQogICAgeCA9ICJ3aWVrIiwNCiAgICB5ID0gInd5bmFncm9kemVuaWUgKHcgdHlzacSFY2FjaCkiDQogICkgKw0KICBmYWNldF9ncmlkKGdlbmRlciB+IGRlZ3JlZSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKQ0KICApDQpgYGANCg0KUG93ecW8c3p5IHd5a3JlcyBwb3R3aWVyZHphIGRvdHljaGN6YXNvd2Ugb2JzZXJ3YWNqZS5Pc29ieSB6IHd5a3N6dGHFgmNlbmllbSAiYmFjaGVsb3IiIChsaWNlbmNqYWNraW0pIG9zacSFZ2FqxIUgd3nFvHN6ZSB3eW5hZ3JvZHplbmlhIHcgcG9yw7N3bmFuaXUgZG8gb3PDs2IgeiB3eWtzenRhxYJjZW5pZW0gImhpZ2hzY2hvb2wiICjFm3JlZG5pbSkuIEplc3QgdG8gd2lkb2N6bmUgemFyw7N3bm8gdyBwcnp5cGFka3UgbcSZxbxjenl6biwgamFrIGkga29iaWV0LlLDs8W8bmljYSBtacSZZHp5IHd5bmFncm9kemVuaWFtaSBtxJnFvGN6eXpuIGkga29iaWV0IGplc3Qgd2lkb2N6bmEgemFyw7N3bm8gdyBncnVwaWUgb3PDs2IgeiB3eWtzenRhxYJjZW5pZW0gxZtyZWRuaW0sIGphayBpIGxpY2VuY2phY2tpbS4NCg0KIyMjIE1vZGVsIGxpbmlvd3kNCg0KYGBge3J9DQptb2RlbF9sbSA8LSBsbShDUFNTVzkyOTgkZWFybmluZ3MgfiBDUFNTVzkyOTgkZGVncmVlICsgQ1BTU1c5Mjk4JGdlbmRlciArIENQU1NXOTI5OCRhZ2UpDQpzdW1tYXJ5KG1vZGVsX2xtKSAgDQpgYGANCg0KSW50ZXJwcmV0YWNqZToNCg0KLSBPc29ieSB6IHd5a3N6dGHFgmNlbmllbSBsaWNlbmNqYWNraW0gemFyYWJpYWrEhSDFm3JlZG5pbyBvIDQuOTEgdHlzLiB3acSZY2VqIG5pxbwgb3NvYnkgeiB3eWtzenRhxYJjZW5pZW0gxZtyZWRuaW0gKHByenkgc3RhxYJlaiBwxYJjaSBpIHdpZWt1KS4NCi0gS29iaWV0eSB6YXJhYmlhasSFIMWbcmVkbmlvIG8gMi4yNCB0eXMuIG1uaWVqIG5pxbwgbcSZxbxjennFum5pIChwcnp5IHN0YcWCeW0gcG96aW9taWUgd3lrc3p0YcWCY2VuaWEgaSB3aWVrdSkuDQotIEthxbxkeSBkb2RhdGtvd3kgcm9rIMW8eWNpYSB6d2nEmWtzemEgemFyb2JraSDFm3JlZG5pbyBvIDAuMzMgdHlzLiAocHJ6eSBzdGHFgmVqIHDFgmNpIGkgd3lrc3p0YcWCY2VuaXUpLg0KDQpNb2RlbCB3eWphxZtuaWEgb2tvxYJvIDE4Ljc3JSB6bWllbm5vxZtjaSB3IHphcm9ia2FjaC4gT3puYWN6YSB0bywgxbxlIG1vZGVsIG5pZSB1d3pnbMSZZG5pYSB3aWVsdSBpbm55Y2ggY3p5bm5pa8Ozdywga3TDs3JlIHdwxYJ5d2FqxIUgbmEgemFyb2JraSAobnAuIGJyYW7FvGEsIGxva2FsaXphY2phLCBkb8Wbd2lhZGN6ZW5pZSB6YXdvZG93ZSkuDQoNCiMjIyBSZWdyZXNqYSBrd2FudHlsb3dhDQoNCmBgYHtyfQ0KZGF0YSA8LSBDUFNTVzkyOTgNCmt3YW50eWxlIDwtIGMoMC4yNSwgMC41MCwgMC43NSkNCnJlZ19rd2FudHlsb3dhIDwtIHJxKGVhcm5pbmdzIH4gYWdlICsgZGVncmVlICsgZ2VuZGVyICwgdGF1ID0ga3dhbnR5bGUsIGRhdGEgPSBkYXRhKQ0Kc3VtbWFyeShyZWdfa3dhbnR5bG93YSwgc2UgPSAiYm9vdCIpDQpgYGANCg0KQW5hbGl6YSB3cMWCeXd1IHdpZWt1LCB3eWtzenRhxYJjZW5pYSBpIHDFgmNpIG5hIHphcm9ia2kgdyByw7PFvG55Y2gga3dhbnR5bGFjaCBkb3N0YXJjemEgaW50ZXJlc3VqxIVjeWNoIHduaW9za8Ozdy4gV3luaWtpIHdza2F6dWrEhSwgxbxlIHN0YXJzenkgd2llayBtYSB3acSZa3N6eSB3cMWCeXcgbmEgemFyb2JraSBvc8OzYiB6bmFqZHVqxIVjeWNoIHNpxJkgdyB3ecW8c3p5Y2gga3dhbnR5bGFjaCB3eW5hZ3JvZHplxYQuIFcgZG9sbnltIDI1JSB6YXJvYmvDs3cga2HFvGR5IHJvayDFvHljaWEgendpxJlrc3phIHd5bmFncm9kemVuaWUgbyAwLjE3IHR5cy4sIHBvZGN6YXMgZ2R5IHcgZ3J1cGllIG5hamxlcGllaiB6YXJhYmlhasSFY3ljaCAoNzUlKSB3enJvc3Qgd3lub3NpIGp1xbwgMC40MyB0eXMuIE96bmFjemEgdG8sIMW8ZSBzdGFyc3p5IHdpZWsgYmFyZHppZWoga29yenlzdG5pZSB3cMWCeXdhIG5hIG9zb2J5IG9zacSFZ2FqxIVjZSB3ecW8c3plIGRvY2hvZHkuDQoNCld5a3N6dGHFgmNlbmllIGxpY2VuY2phY2tpZSByw7N3bmllxbwgb2Rncnl3YSBpc3RvdG7EhSByb2zEmSwgc3pjemVnw7NsbmllIHcgbWVkaWFuaWUgaSBnw7NybnljaCBrd2FudHlsYWNoLiBXIGdydXBpZSBvc8OzYiB6IG5ham5pxbxzenltaSB6YXJvYmthbWkgd3lrc3p0YcWCY2VuaWUgbGljZW5jamFja2llIHp3acSZa3N6YSB3eW5hZ3JvZHplbmllIMWbcmVkbmlvIG8gMy41OSB0eXMuLCBhbGUgdyBtZWRpYW5pZSBpIHfFm3LDs2QgbmFqbGVwaWVqIHphcmFiaWFqxIVjeWNoIHdwxYJ5dyB0ZW4gcm/Fm25pZSBkbyA0LjcwIHR5cy4gxZp3aWFkY3p5IHRvIG8gdHltLCDFvGUgd3nFvHN6ZSB3eWtzenRhxYJjZW5pZSBtYSBzemN6ZWfDs2xuxIUgd2FydG/Fm8SHIHfFm3LDs2Qgb3PDs2IgeiB3ecW8c3p5bWkgZG9jaG9kYW1pLg0KDQpSw7PFvG5pY2UgdyB3eW5hZ3JvZHplbmlhY2ggbWnEmWR6eSBwxYJjaWFtaSBzxIUgd2lkb2N6bmUgd2Ugd3N6eXN0a2ljaCBrd2FudHlsYWNoLCBhbGUgbmFqYmFyZHppZWogbmllcG9rb2rEhWNlIHPEhSB3IGfDs3JueW0gMjUlIHphcm9ia8Ozdy4gS29iaWV0eSB6YXJhYmlhasSFIG1uaWVqIG5pxbwgbcSZxbxjennFum5pLCBhIHLDs8W8bmljZSB0ZSByb3NuxIUgdyB6YWxlxbxub8WbY2kgb2QgcG96aW9tdSBkb2Nob2TDs3c6IG9kIDEuMzIgdHlzLiB3IG5ham5pxbxzenljaCB6YXJvYmthY2ggZG8gMi45NyB0eXMuIHfFm3LDs2QgbmFqbGVwaWVqIHphcmFiaWFqxIVjeWNoLiANCg0KYGBge3J9DQpwbG90KHJxKGVhcm5pbmdzIH4gYWdlICsgZGVncmVlICsgZ2VuZGVyLCB0YXUgPSBjKDAuMjUsIDAuNSwgMC43NSksIGRhdGEgPSBkYXRhKSkNCmBgYA0KDQpgYGB7cn0NCmt3YW50eWxlIDwtIGMoMC4yNSwgMC41MCwgMC43NSkNCm1vZGVsX3EyNSA8LSBycShlYXJuaW5ncyB+IGFnZSArIGRlZ3JlZSArIGdlbmRlciwgdGF1ID0gMC4yNSwgZGF0YSA9IGRhdGEpDQptb2RlbF9xNTAgPC0gcnEoZWFybmluZ3MgfiBhZ2UgKyBkZWdyZWUgKyBnZW5kZXIsIHRhdSA9IDAuNTAsIGRhdGEgPSBkYXRhKQ0KbW9kZWxfcTc1IDwtIHJxKGVhcm5pbmdzIH4gYWdlICsgZGVncmVlICsgZ2VuZGVyLCB0YXUgPSAwLjc1LCBkYXRhID0gZGF0YSkNCmNvZWZfcTI1IDwtIGNvZWYobW9kZWxfcTI1KQ0KY29lZl9xNTAgPC0gY29lZihtb2RlbF9xNTApDQpjb2VmX3E3NSA8LSBjb2VmKG1vZGVsX3E3NSkNCg0KY29lZl90YWJsZSA8LSBkYXRhLmZyYW1lKA0KICBLd2FudHlsID0gYygwLjI1LCAwLjUwLCAwLjc1KSwNCiAgSW50ZXJjZXB0ID0gYyhjb2VmX3EyNVsxXSwgY29lZl9xNTBbMV0sIGNvZWZfcTc1WzFdKSwNCiAgQWdlID0gYyhjb2VmX3EyNVsiYWdlIl0sIGNvZWZfcTUwWyJhZ2UiXSwgY29lZl9xNzVbImFnZSJdKSwNCiAgRGVncmVlID0gYyhjb2VmX3EyNVsiZGVncmVlYmFjaGVsb3IiXSwgY29lZl9xNTBbImRlZ3JlZWJhY2hlbG9yIl0sIGNvZWZfcTc1WyJkZWdyZWViYWNoZWxvciJdKSwNCiAgR2VuZGVyID0gYyhjb2VmX3EyNVsiZ2VuZGVyZmVtYWxlIl0sIGNvZWZfcTUwWyJnZW5kZXJmZW1hbGUiXSwgY29lZl9xNzVbImdlbmRlcmZlbWFsZSJdKQ0KKQ0KDQpwcmludChjb2VmX3RhYmxlKQ0KYGBgDQoNClRhYmVsYSBwcnplZHN0YXdpYSB3eW5pa2kgcmVncmVzamkga3dhbnR5bG93ZWogZGxhIHRyemVjaCB3eWJyYW55Y2gga3dhbnR5bGk6IDAuMjUgKGRvbG5lIDI1JSB6YXJvYmvDs3cpLCAwLjUwIChtZWRpYW5hIHphcm9ia8OzdyksIGkgMC43NSAoZ8Ozcm5lIDI1JSB6YXJvYmvDs3cpLiBKZXN0IHRvIGFuYWxpemEsIGt0w7NyYSBwb3p3YWxhIHpvYmFjennEhywgamFrIHptaWVubmUgbmllemFsZcW8bmUgd3DFgnl3YWrEhSBuYSB6YXJvYmtpIHcgcsOzxbxueWNoIGN6xJnFm2NpYWNoIHJvemvFgmFkdSB3eW5hZ3JvZHplxYQsIGEgbmllIHR5bGtvIG5hIMWbcmVkbmnEhSAoamFrIHcga2xhc3ljem5laiByZWdyZXNqaSBsaW5pb3dlaikuDQoNCiMjIyBXZXJ5ZmlrYWNqYSBzdGF0eXN0eWN6bmEgaXN0b3Rub8WbY2kgcsOzxbxuaWMgbWnEmWR6eSBwaWVyd3N6eW0sIGRydWdpbSBpIHRyemVjaW0ga3dhcnR5bGVtDQoNCmBgYHtyfQ0KYW5vdmEocmVnX2t3YW50eWxvd2EsIHRlc3QgPSAiV2FsZCIsIGpvaW50PVRSVUUpDQpgYGANCg0KSGlwb3RlemEgemVyb3dhOiBXc3DDs8WCY3p5bm5pa2kgZGxhIGt3YW50eWxpIHPEhSB0YWtpZSBzYW1lLg0KSGlwb3RlemEgYWx0ZXJuYXR5d25hOiBXc3DDs8WCY3p5bm5pa2kgcsOzxbxuacSFIHNpxJkgbWnEmWR6eSBrd2FudHlsYW1pLg0KDQpQb25pZXdhxbwgd2FydG/Fm8SHIHAgamVzdCBiYXJkem8gbmlza2EsIG9kcnp1Y2FteSBoaXBvdGV6xJkgemVyb3fEhS4gT3puYWN6YSB0bywgxbxlIHdwxYJ5dyB6bWllbm55Y2ggKHdpZWssIHd5a3N6dGHFgmNlbmllLCBwxYJlxIcpIHLDs8W8bmkgc2nEmSB3IHLDs8W8bnljaCBjesSZxZtjaWFjaCByb3prxYJhZHUgemFyb2Jrw7N3Lg0KDQpgYGB7cn0NCmFub3ZhKHJlZ19rd2FudHlsb3dhLCB0ZXN0ID0gIldhbGQiLCBqb2ludD1GQUxTRSkNCmBgYA0KDQpXc3p5c3RraWUgem1pZW5uZSAoYWdlLCBkZWdyZWViYWNoZWxvciwgZ2VuZGVyZmVtYWxlKSBtYWrEhSBpc3RvdG5pZSByw7PFvG55IHdwxYJ5dyBuYSB6YXJvYmtpIHcgemFsZcW8bm/Fm2NpIG9kIGt3YW50eWxhLg0KDQojIyMgRG9icm/EhyBkb3Bhc293YW5pYQ0KDQpgYGB7cn0NCiMgT2JsaWN6ZW5pZSByZXN6dCBkbGEgbW9kZWxpDQpyZXN6dHlfbG0gPC0gcmVzaWQobW9kZWxfbG0pICANCm1vZGVsMiA8LSBycShlYXJuaW5ncyB+IDEsIHRhdSA9IDAuMjUsIGRhdGEgPSBkYXRhKSAgDQpyZXN6dHlfMiA8LSByZXNpZChtb2RlbDIpIA0KbW9kZWwzIDwtIHJxKGVhcm5pbmdzIH4gMSwgdGF1ID0gMC43NSxkYXRhPWRhdGEpDQpyZXN6dHkzIDwtIHJlc2lkKG1vZGVsMykNCg0KcGFyKG1mcm93ID0gYygxLCAzKSkgICMgUG9kemllbCBwcnplc3RyemXFhCBuYSAzIGtvbHVtbnkNCg0KIyBIaXN0b2dyYW0gZGxhIG1vZGVsdSBsaW5pb3dlZ28NCmhpc3QocmVzenR5X2xtLA0KICAgICBtYWluID0gIkhpc3RvZ3JhbSByZXN6dCAobW9kZWwgbGluaW93eSkiLA0KICAgICB4bGFiID0gIlJlc3p0eSIsDQogICAgIGNvbCA9ICJibGFjayIsIGJvcmRlciA9ICJncmV5IikNCg0KIyBIaXN0b2dyYW0gZGxhIG1vZGVsdSBrd2FudHlsb3dlZ28gdGF1ID0gMC4yNQ0KaGlzdChyZXN6dHlfMiwNCiAgICAgbWFpbiA9ICJIaXN0b2dyYW0gcmVzenQgKHRhdSA9IDAuMjUpIiwNCiAgICAgeGxhYiA9ICJSZXN6dHkiLA0KICAgICBjb2wgPSAiZ29sZCIsIGJvcmRlciA9ICJibGFjayIpDQoNCiMgSGlzdG9ncmFtIGRsYSBtb2RlbHUga3dhbnR5bG93ZWdvIHRhdSA9IDAuNzUNCmhpc3QocmVzenR5MywNCiAgICAgbWFpbiA9ICJIaXN0b2dyYW0gcmVzenQgKHRhdSA9IDAuNzUpIiwNCiAgICAgeGxhYiA9ICJSZXN6dHkiLA0KICAgICBjb2wgPSAicHVycGxlIiwgYm9yZGVyID0gImJsYWNrIikNCg0KYGBgDQoNCmBgYHtyfQ0KDQpjb2VmX2xvbmcgPC0gcmVzaGFwZTI6Om1lbHQoY29lZl90YWJsZSwgaWQudmFycyA9ICJLd2FudHlsIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUubmFtZSA9ICJabWllbm5hIiwgdmFsdWUubmFtZSA9ICJXc3DDs8WCY3p5bm5payIpDQpnZ3Bsb3QoY29lZl9sb25nLCBhZXMoeCA9IEt3YW50eWwsIHkgPSBXc3DDs8WCY3p5bm5paywgY29sb3IgPSBabWllbm5hKSkgKw0KICBnZW9tX2xpbmUoc2l6ZSA9IDEpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIldzcMOzxYJjenlubmlraSByZWdyZXNqaSBrd2FudHlsb3dlaiIsDQogICAgeCA9ICJLd2FudHlsIiwNCiAgICB5ID0gIldzcMOzxYJjenlubmlrIiwNCiAgICBjb2xvciA9ICJabWllbm5hIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE2KSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikNCiAgKQ0KYGBgDQoNCldwxYJ5dyB6bWllbm55Y2ggamVzdCB6csOzxbxuaWNvd2FueSB3IHLDs8W8bnljaCBjesSZxZtjaWFjaCByb3prxYJhZHUgemFyb2Jrw7N3LCBjbyB3c2thenVqZSBuYSB0bywgxbxlIGtsYXN5Y3puYSByZWdyZXNqYSBsaW5pb3dhIChrdMOzcmEgemFrxYJhZGEgc3RhxYJ5IHdwxYJ5dyB6bWllbm55Y2ggbmEgY2HFgm/Fm8SHIHJvemvFgmFkdSkgbW9nxYJhYnkgbmllIHVjaHd5Y2nEhyB0eWNoIHLDs8W8bmljLg0KDQotV3DFgnl3IHdpZWt1IHJvxZtuaWUgd3JheiB6ZSB3enJvc3RlbSBrd2FudHlsYS4gU3RhcnN6eSB3aWVrIG1hIG5handpxJlrc3p5IHdwxYJ5dyBuYSB6YXJvYmtpIHcgZ3J1cGllIG5hamxlcGllaiB6YXJhYmlhasSFY3ljaCwgY28gamVzdCB6Z29kbmUgeiBvY3pla2l3YW5pZW0sIMW8ZSBkb8Wbd2lhZGN6ZW5pZSB6YXdvZG93ZSBiYXJkemllaiBzacSZIG9wxYJhY2EgdyB0ZWogZ3J1cGllLg0KLSBXeWtzenRhxYJjZW5pZSBtYSByb3NuxIVjeSB3cMWCeXcgdyBtaWFyxJkgd3pyb3N0dSBrd2FudHlsYS4gU3VnZXJ1amUgdG8sIMW8ZSB3YXJ0b8WbxIcgd3nFvHN6ZWdvIHd5a3N6dGHFgmNlbmlhIGplc3QgYmFyZHppZWogZG9jZW5pYW5hIHcgZ3J1cGllIG9zw7NiIG9zacSFZ2FqxIVjeWNoIG5hand5xbxzemUgZG9jaG9keS4NCi0gV2FydG/Fm2NpIHVqZW1uZSB3c3DDs8WCY3p5bm5pa2EgR2VuZGVyIHdza2F6dWrEhSBuYSBuacW8c3plIHphcm9ia2kga29iaWV0IHcgcG9yw7N3bmFuaXUgZG8gbcSZxbxjenl6bi4NCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=