
(https://img.youtube.com/vi/QYlR7_F6clo/hqdefault.jpg)](https://youtu.be/QYlR7_F6clo)
Introduction
Keputusan investasi di era modern menjadi semakin kompleks karena
dipengaruhi oleh berbagai faktor ekonomi dan pribadi, seperti usia,
pendapatan, tujuan keuangan, dan toleransi risiko. Perbedaan ini
menghasilkan variasi dalam imbal hasil, volatilitas, dan pertumbuhan
aset.
Dataset ini mencakup variabel kategoris (seperti segmen investor,
wilayah, dan jenis investasi) serta variabel numerik (jumlah investasi,
skor risiko, diversifikasi portofolio, dan imbal hasil tahunan).
Melalui analisis statistik deskriptif—termasuk ukuran tendensi
sentral dan dispersi—serta visualisasi data, dapat diperoleh gambaran
yang lebih jelas mengenai pola, distribusi, dan kinerja investor secara
keseluruhan.
Data preparation
library(readr)
library(DT)
data_investment5 <- read_csv("C:/Users/Adinda/Downloads/Midterm Exam3.csv")
datatable(
data_investment5,
options = list(pageLength = 10), # tampil 10 baris per halaman
caption = "Tabel Interaktif Data CSV"
)
Visualizations
Data
Barchart
Interpretasi
Visualisasi di atas menunjukkan perbandingan jumlah investor pada
setiap jenis investasi. Terlihat bahwa beberapa jenis investasi memiliki
jumlah investor yang jauh lebih tinggi dibanding lainnya, menandakan
adanya preferensi atau minat yang lebih besar terhadap jenis investasi
tertentu.
dapat disimpulkan bahwa jenis investasi dengan jumlah investor
tertinggi merupakan pilihan yang paling populer dan dianggap lebih aman
atau menguntungkan oleh mayoritas responden, sedangkan jenis dengan
jumlah investor paling sedikit mungkin memiliki risiko atau tingkat
kepercayaan yang lebih rendah.
Histogram
Interpretasi
Histogram diatas menunjukkan distribusi usia para investor dalam
dataset. Sebagian besar investor berada pada rentang usia produktif
(sekitar 30–45 tahun), yang menandakan bahwa kelompok usia ini paling
aktif dalam kegiatan investasi. Distribusi terlihat relatif normal,
meskipun ada kemungkinan sedikit kemiringan (skewness) ke kanan yang
menunjukkan sebagian kecil investor berusia lebih tua. Hal ini dapat
diartikan bahwa partisipasi investasi cenderung menurun pada usia
lanjut, sementara kelompok usia menengah mendominasi pasar karena
memiliki kestabilan finansial dan minat investasi yang tinggi.
Scatter plot
library(ggplot2)
library(plotly)
# Scatter plot dengan garis tren
scatter_plot <- ggplot(data_investment5, aes(x = Age, y = AnnualReturn)) +
geom_point(color = "#2E86AB", alpha = 0.7, size = 3) + # Titik data
geom_smooth(method = "lm", color = "lightpink", se = TRUE, linewidth = 1) + # Garis tren linear
theme_minimal() +
labs(
title = "Hubungan antara Usia Investor dan Tingkat Keuntungan Tahunan",
x = "Usia Investor (Tahun)",
y = "Keuntungan Tahunan (%)",
caption = "Sumber data: Midterm Exam Investment Data"
)
# Ubah plot interaktif
interactive_scatter <- ggplotly(scatter_plot)
interactive_scatter
Interpretasi
Visualisasi ini menunjukkan hubungan antara usia investor dan tingkat
keuntungan tahunan (annual return). Titik-titik data menggambarkan
sebaran nilai return di berbagai kelompok usia, sementara garis tren
linear memperlihatkan arah hubungan umum di antara keduanya.
Dari grafik terlihat bahwa tidak ada hubungan linear yang kuat antara
usia dan tingkat keuntungan tahunan — artinya, peningkatan usia tidak
secara konsisten diikuti oleh peningkatan atau penurunan return. Sebaran
titik yang cukup luas menunjukkan adanya variasi (dispersi) yang tinggi
antarindividu, menandakan bahwa faktor lain selain usia (seperti
pengalaman atau profil risiko) kemungkinan berpengaruh lebih besar
terhadap hasil investasi.
Box plot
library(plotly)
p_box_soft <- plot_ly(
data = data_investment5,
x = ~RiskProfile,
y = ~AnnualReturn,
color = ~RiskProfile,
type = "box",
colors = c("#CDE8E5", "#E8DFF5", "#FDE2E4"),
boxmean = TRUE,
hoverinfo = "text",
text = ~paste(
"Risk Profile: ", RiskProfile,
"<br>Annual Return: ", round(AnnualReturn, 2), "%"
),
marker = list(outliercolor = '#9E9E9E', opacity = 0.7)
) %>%
layout(
title = list(
text = "Distribusi Annual Return Berdasarkan Risk Profile",
x = 0.5,
font = list(size = 18, color = "#333333", family = "Arial Black")
),
xaxis = list(title = "Risk Profile", titlefont = list(size = 14)),
yaxis = list(title = "Annual Return (%)", titlefont = list(size = 14)),
plot_bgcolor = "#FFFFFF",
paper_bgcolor = "#FFFFFF",
font = list(family = "Arial", color = "#444444")
)
p_box_soft
Interpretasi
Visualisasi box plot ini menunjukkan perbedaan sebaran annual return
berdasarkan kategori risk profile investor. Investor dengan profil
risiko tinggi (High Risk) cenderung memiliki annual return yang lebih
besar, namun dengan sebaran nilai yang juga lebih luas — menandakan
variabilitas (dispersi) yang tinggi dan potensi risiko lebih besar.
Sebaliknya, profil risiko rendah (Low Risk) menampilkan rentang nilai
return yang sempit, mencerminkan stabilitas dan konsistensi hasil
investasi. Profil risiko sedang (Moderate) berada di antara keduanya,
menunjukkan keseimbangan antara risiko dan potensi imbal hasil.
Line chart
Interpretasi
Grafik menunjukkan bahwa semakin tinggi tingkat pengalaman investasi,
semakin besar rata-rata Annual Return yang diperoleh investor. Tren
garis yang meningkat menandakan adanya hubungan positif antara
pengalaman dan kinerja investasi. Hal ini mengindikasikan bahwa
pengalaman berperan penting dalam kemampuan investor mengelola risiko
dan memaksimalkan keuntungan.
Tidak terlihat adanya outlier atau fluktuasi ekstrem, yang berarti
data relatif konsisten dan stabil di setiap tingkat pengalaman. Dengan
demikian, variabel InvestmentExperience dapat dianggap memiliki pengaruh
yang signifikan terhadap AnnualReturn, serta memperlihatkan pola
distribusi yang proporsional dan mudah diinterpretasikan secara
visual.
Central Tendency
Analisis ini dilakukan untuk memahami ukuran pemusatan data dari dua
variabel numerik, yaitu Age (usia investor) dan AnnualReturn (persentase
hasil investasi tahunan). Kedua variabel ini dipilih karena:
Dengan menghitung mean, median, dan mode, kita dapat mengidentifikasi
apakah distribusi data bersifat simetris, miring ke kanan
(right-skewed), atau miring ke kiri (left-skewed).
Ukuran pemusatan data yang digunakan terdiri dari tiga jenis
utama:
- Mean (Rata-rata)
Rumus:
\[
\mathbf{Mean} = \frac{\sum x_i}{n}
\]
Keterangan:
- \(x_i\) = nilai ke-i dari
data
- \(n\) = jumlah total data
Artinya, semua nilai dijumlahkan lalu dibagi dengan jumlah data.
- Median (Nilai Tengah)
Median adalah nilai yang berada di tengah setelah data diurutkan dari
yang terkecil ke terbesar.
Jika jumlah data ganjil, median = nilai di posisi
tengah.
Jika jumlah data genap, median = rata-rata dari dua
nilai tengah.
- Mode (Modus)
Mode adalah nilai yang paling sering muncul dalam suatu kumpulan
data.
Jika hanya ada satu nilai yang sering muncul →
unimodal,
jika dua nilai → bimodal,
dan jika lebih dari dua → multimodal.
Perhitungan (mean,
meadian, mode)
# --- Library yang digunakan ---
library(readr)
library(dplyr)
library(ggplot2)
# --- Membaca dataset ---
data_investment5 <- read_csv("C:/Users/Adinda/Downloads/Midterm Exam3.csv")
# --- Menghitung Mean, Median, dan Mode untuk dua variabel numerik ---
# Variabel 1: Age
mean_age <- mean(data_investment5$Age, na.rm = TRUE)
median_age <- median(data_investment5$Age, na.rm = TRUE)
mode_age <- as.numeric(names(sort(table(data_investment5$Age), decreasing = TRUE)[1]))
# --- Menyusun hasil perhitungan ke dalam tabel ---
tabel_central <- data.frame(
Variable = c("Age"),
Mean = c(mean_age),
Median = c(median_age),
Mode = c(mode_age)
)
# --- Menampilkan tabel hasil ---
tabel_central
Measures of
Dispersion
Bagian ini bertujuan untuk mengukur sebaran (dispersi) dari data
numerik dalam dataset. Ukuran penyebaran membantu kita memahami seberapa
jauh data menyebar dari nilai rata-ratanya. Dua variabel yang
digunakan:
Ukuran-ukuran penyebaran meliputi:
- Range (Jangkauan)
\[
\textbf{Range} = X_{max} - X_{min}
\] # Menghitung range
range_age <- max(data_investment5$Age, na.rm = TRUE) - min(data_investment5$Age, na.rm = TRUE)
range_return <- max(data_investment5$AnnualReturn, na.rm = TRUE) - min(data_investment5$AnnualReturn, na.rm = TRUE)
data.frame(
Variable = c("Age", "Annual Return"),
Range = c(range_age, range_return)
)
Range menunjukkan perbedaan antara nilai terbesar dan nilai
terkecil dalam data.
Semakin besar nilai range, semakin lebar pula sebaran data.
Namun, ukuran ini sensitif terhadap outlier, sehingga
tidak selalu mencerminkan distribusi sebenarnya. Sedangkan pada
perhitungan rage di atas menunjukan Range jarak antara nilai tertinggi
dan terendah dalam data. Nilai yang besar menandakan adanya variasi
ekstrem, sedangkan nilai kecil berarti data relatif homogen.
Berdasarkan hasil perhitungan range menunjukkan
selisih antara nilai maksimum dan minimum pada suatu variabel.
Untuk Age, range yang relatif kecil
mengindikasikan bahwa rentang usia responden tidak terlalu lebar,
artinya mayoritas investor memiliki usia yang berdekatan.
Untuk Annual Return, range yang jauh lebih besar
menunjukkan adanya perbedaan signifikan antara tingkat pengembalian
investasi tertinggi dan terendah di antara responden.
- Variance (Ragam)
\[
\textbf{s}^2 = \frac{\sum_{i=1}^{n}(X_i - \bar{X})^2}{n - 1}
\]
# Menghitung varians
var_age <- var(data_investment5$Age, na.rm = TRUE)
var_return <- var(data_investment5$AnnualReturn, na.rm = TRUE)
data.frame(
Variable = c("Age", "Annual Return"),
Variance = c(var_age, var_return)
)
Variance mengukur rata-rata kuadrat deviasi setiap
nilai terhadap mean.
Nilai variansi besar berarti data memiliki keragaman
tinggi, sedangkan nilai kecil menunjukkan bahwa data
berkumpul di sekitar mean.
Satuan variansi adalah kuadrat dari satuan data
aslinya.
Berdasarkan hasil perhitungan varians:
Variabel Age memiliki nilai varians yang relatif
kecil, artinya sebaran umur responden cukup seragam. Mayoritas responden
berada dalam rentang usia yang tidak terlalu jauh.
Variabel Annual Return memiliki nilai varians
yang jauh lebih besar, menandakan bahwa tingkat pengembalian investasi
antar responden bervariasi cukup tinggi. Beberapa investor mungkin
memperoleh hasil yang jauh lebih tinggi atau rendah dibanding
rata-rata.
Dengan kata lain, semakin besar nilai varians, semakin tinggi tingkat
ketidakkonsistenan data. Dalam konteks ini, Annual Return memiliki
tingkat fluktuasi yang lebih besar dibanding Age.
- Standard Deviation (Simpangan Baku)
\[
\textbf{s} = \sqrt{s^2} = \sqrt{\frac{\sum_{i=1}^{n}(X_i - \bar{X})^2}{n
- 1}}
\]
# Menghitung standar deviasi
sd_age <- sd(data_investment5$Age, na.rm = TRUE)
sd_return <- sd(data_investment5$AnnualReturn, na.rm = TRUE)
data.frame(
Variable = c("Age", "Annual Return"),
Standard_Deviation = c(sd_age, sd_return)
)
Standard deviation merupakan akar dari variansi,
sehingga kembali pada satuan data aslinya.
Nilai simpangan baku menunjukkan seberapa jauh data tersebar dari nilai
rata-rata.
Jika standar deviasi kecil, maka data lebih homogen;
jika besar, maka data lebih bervariasi.
Berdasarkan hasil perhitungan Standar Deviation
Nilai standar deviasi Age kecil → menunjukkan bahwa sebagian
besar nilai umur mendekati rata-rata.
Nilai standar deviasi Annual Return besar → menggambarkan bahwa
tingkat pengembalian memiliki penyimpangan yang besar dari
rata-ratanya.
- Interquartile Range (IQR)
\[
\textbf{IQR} = Q_3 - Q_1
\]
# Menghitung IQR
iqr_age <- IQR(data_investment5$Age, na.rm = TRUE)
iqr_return <- IQR(data_investment5$AnnualReturn, na.rm = TRUE)
data.frame(
Variable = c("Age", "Annual Return"),
IQR = c(iqr_age, iqr_return)
)
IQR mengukur rentang data tengah (50%) dengan
mengabaikan pengaruh outlier.
IQR berguna untuk melihat penyebaran data utama tanpa
dipengaruhi nilai ekstrem.
Berdasarkan hasil perhitungan IQR
Visualisasi Measures
of Dispersion
Interpretasi
Visualisasi box plot menunjukkan bahwa InitialInvestment memiliki
penyebaran (dispersi) yang lebih besar dibanding AnnualReturn. Hal ini
terlihat dari rentang dan IQR yang lebih lebar serta adanya beberapa
outlier pada nilai investasi awal, menandakan perbedaan modal antar
investor cukup tinggi. Sementara itu, AnnualReturn memiliki sebaran yang
lebih sempit dan sedikit outlier, menunjukkan hasil tahunan antar
investor relatif stabil. Dengan demikian, dapat disimpulkan bahwa modal
awal bervariasi tinggi, sedangkan hasil tahunan lebih konsisten, sesuai
dengan konsep Measures of Dispersion yang menekankan variasi dan
kestabilan data.
Histogram

Interpretasi
Visualisasi histogram di atas memperlihatkan sebaran dua variabel
numerik, yaitu Monthly Saving dan Annual Return, untuk memahami pola
distribusi dan tingkat penyebaran datanya.
Pada histogram Monthly Saving, terlihat bahwa sebagian besar
investor memiliki jumlah tabungan bulanan pada kisaran menengah.
Distribusi ini menunjukkan bahwa data cenderung simetris dengan sedikit
variasi di sekitar nilai tengah, yang berarti tingkat kemampuan menabung
antar investor relatif seragam dan tidak terlalu menyimpang
jauh.
Sementara itu, histogram Annual Return menunjukkan bahwa sebagian
besar imbal hasil tahunan berkumpul di sekitar nilai rata-rata dengan
sedikit nilai ekstrem (outlier) di sisi kanan. Hal ini mengindikasikan
adanya beberapa investor dengan tingkat pengembalian yang jauh lebih
tinggi dibanding lainnya, menandakan penyebaran data yang lebih besar
pada variabel ini dibanding Monthly Saving.
Secara keseluruhan, hasil ini menunjukkan bahwa Annual Return
memiliki variasi yang lebih tinggi, sedangkan Monthly Saving lebih
konsisten, yang berarti risiko dan hasil investasi berbeda antar
individu, tetapi kemampuan menabung relatif stabil.
Scatter plot
library(plotly)
library(dplyr)
# Gunakan dataset yang benar
data_investment <- data_investment %>%
mutate(
RiskScore = as.numeric(RiskScore),
AnnualReturn = as.numeric(AnnualReturn)
)
# Fit model regresi linear
model <- lm(AnnualReturn ~ RiskScore, data = data_investment)
# Prediksi nilai untuk garis tren
pred <- data.frame(
RiskScore = seq(min(data_investment$RiskScore, na.rm = TRUE),
max(data_investment$RiskScore, na.rm = TRUE),
length.out = 100)
)
pred$AnnualReturn <- predict(model, newdata = pred)
# Scatter plot interaktif + garis tren
fig <- plot_ly(
data = data_investment,
x = ~RiskScore,
y = ~AnnualReturn,
type = 'scatter',
mode = 'markers',
marker = list(color = 'lightpink', size = 8, opacity = 0.7),
hoverinfo = 'text',
text = ~paste('Risk Score:', RiskScore,
'<br>Annual Return:', AnnualReturn)
) %>%
add_trace(
data = pred,
x = ~RiskScore,
y = ~AnnualReturn,
type = 'scatter',
mode = 'lines',
line = list(color = 'darkred', width = 2),
name = 'Trend Line'
) %>%
layout(
title = list(text = "Hubungan antara Risk Score dan Annual Return (dengan Garis Tren)", x = 0.5),
xaxis = list(title = "Risk Score"),
yaxis = list(title = "Annual Return (%)"),
plot_bgcolor = "#f7f9fb",
paper_bgcolor = "#f7f9fb"
)
fig # tampilkan grafik interaktif
Interpretasi
Scatter plot menunjukkan hubungan positif antara Risk Score dan
Annual Return. Pola ini mengindikasikan bahwa semakin tinggi risiko yang
diambil, semakin besar potensi imbal hasilnya. Sebaran titik yang cukup
luas menandakan adanya variasi atau dispersi tinggi pada hasil
investasi.
Summary and
Interpretation
Berdasarkan hasil analisis data investasi, diperoleh bahwa variabel
numerik yang dianalisis, yaitu Age dan Annual Return, menunjukkan
karakteristik penyebaran yang berbeda.
Variabel Age memiliki nilai rata-rata, median,
dan modus yang berdekatan, menandakan distribusi yang relatif simetris
tanpa adanya outlier yang signifikan. Hal ini juga didukung oleh nilai
varians, standar deviasi, dan IQR yang kecil, sehingga dapat disimpulkan
bahwa data usia investor cukup konsisten dan homogen.
Sebaliknya, variabel Annual Return memiliki
perbedaan cukup besar antara nilai rata-rata dan median, yang
mengindikasikan adanya kemencengan (skewness) pada distribusi data.
Nilai dispersi yang tinggi menunjukkan bahwa tingkat pengembalian
investasi antar investor sangat bervariasi. Kondisi ini dapat disebabkan
oleh perbedaan strategi, tingkat risiko, dan pengalaman
investasi.
Secara keseluruhan, hasil visualisasi dan analisis statistik
menggambarkan bahwa Age merupakan variabel yang paling stabil, sedangkan
Annual Return menunjukkan variabilitas paling tinggi. Hal ini memberikan
gambaran bahwa kinerja investasi lebih dipengaruhi oleh faktor eksternal
dibandingkan faktor demografis seperti usia.
LS0tDQp0aXRsZTogIkludmVzdG1lbnQgRGF0YSIgIyBNYWluIHRpdGxlIG9mIHRoZSBkb2N1bWVudA0Kc3VidGl0bGU6ICJNaWR0ZXJtIEV4YW0iICMgU3VidGl0bGUgb3IgdG9waWMgZm9yIHdlZWsgMg0KYXV0aG9yOiANCi0gIkFkaW5kYSBBZGVsaWEgZnV0cmkiDQotICJBZGluZGEgTWFpemEgaXNoZmFoYW5pIiANCi0gIkNocmljeWVzaWEgVy5GLlV2YXMiDQotICJKYW51YXJpYSBUZXJlc2luaGEiIA0KLSAiT2N0YXZpYSBNYWlhIFJlZ28iICAgICAgICAgICMgUmVwbGFjZSB3aXRoIHlvdXIgZnVsbCBuYW1lDQpkYXRlOiAgImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIiAjIEF1dG8gZGlzcGxheXMgdGhlIGN1cnJlbnQgZGF0ZQ0Kb3V0cHV0OiAgICAgICAgICAgICAgICAgICAgICAgICAjIE91dHB1dCBzZWN0aW9uIGRlZmluZXMgdGhlIGZvcm1hdCBhbmQgbGF5b3V0IA0KICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjogICAgICAjIGh0dHBzOi8vZ2l0aHViLmNvbS9qdWJhL3JtZGZvcm1hdHMNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZSAgICAgICAgIyBFbWJlZHMgYWxsIHJlc291cmNlcyAoQ1NTLCBKUywgaW1hZ2VzKSANCiAgICB0aHVtYm5haWxzOiB0cnVlICAgICAgICAgICAgIyBEaXNwbGF5cyBpbWFnZSB0aHVtYm5haWxzIGluIHRoZSBkb2MNCiAgICBsaWdodGJveDogdHJ1ZSAgICAgICAgICAgICAgIyBFbmFibGVzIGNsaWNrIHRvIGVubGFyZ2UgaW1hZ2VzDQogICAgZ2FsbGVyeTogdHJ1ZSAgICAgICAgICAgICAgICMgR3JvdXBzIGltYWdlcyBpbnRvIGFuIGludGVyYWN0aXZlIGdhbGxlcnkNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUgICAgICAgIyBBdXRvbWF0aWNhbGx5IG51bWJlcnMgYWxsIHNlY3Rpb25zDQogICAgbGliX2RpcjogbGlicyAgICAgICAgICAgICAgICMgRGlyZWN0b3J5IHdoZXJlIEphdmFTY3JpcHQvQ1NTIGxpYnJhcmllcw0KICAgIGRmX3ByaW50OiAicGFnZWQiICAgICAgICAgICAjIERpc3BsYXlzIGRhdGEgZnJhbWVzIGFzIGludGVyYWN0aXZlIHBhZ2VkIA0KICAgIGNvZGVfZm9sZGluZzogInNob3ciICAgICAgICAjIEFsbG93cyBmb2xkaW5nL3VuZm9sZGluZyBSIGNvZGUgYmxvY2tzIA0KICAgIGNvZGVfZG93bmxvYWQ6IHllcyAgICAgICAgICAjIEFkZHMgYSBidXR0b24gdG8gZG93bmxvYWQgYWxsIFIgY29kZQ0KLS0tDQo8aW1nIGlkPSJGb3RvIiBzcmM9Imh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9hZGluZGFhZGVsaWFmdXRyaTYtZ2lmL2tlbG9tcG9rc3RhdGlzdGlrNS9tYWluL2tlbG9tcG9rNS5qcGVnIiBhbHQ9IkxvZ28iIHN0eWxlPSJ3aWR0aDoyMDBweDsgZGlzcGxheTogYmxvY2s7IG1hcmdpbjogYXV0bzsiPg0KDQoNCjxjZW50ZXI+PGlmcmFtZSB3aWR0aD0iNzAwIiBoZWlnaHQ9IjQwMCIgc3JjPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC9RWWxSN19GNmNsbyIgZnJhbWVib3JkZXI9IjAiIGFsbG93ZnVsbHNjcmVlbj48L2lmcmFtZT48L2NlbnRlcj4NCg0KKGh0dHBzOi8vaW1nLnlvdXR1YmUuY29tL3ZpL1FZbFI3X0Y2Y2xvL2hxZGVmYXVsdC5qcGcpXShodHRwczovL3lvdXR1LmJlL1FZbFI3X0Y2Y2xvKQ0KDQoNCiMgSW50cm9kdWN0aW9uDQpLZXB1dHVzYW4gaW52ZXN0YXNpIGRpIGVyYSBtb2Rlcm4gbWVuamFkaSBzZW1ha2luIGtvbXBsZWtzIGthcmVuYSBkaXBlbmdhcnVoaSBvbGVoIGJlcmJhZ2FpIGZha3RvciBla29ub21pIGRhbiBwcmliYWRpLCBzZXBlcnRpIHVzaWEsIHBlbmRhcGF0YW4sIHR1anVhbiBrZXVhbmdhbiwgZGFuIHRvbGVyYW5zaSByaXNpa28uIFBlcmJlZGFhbiBpbmkgbWVuZ2hhc2lsa2FuIHZhcmlhc2kgZGFsYW0gaW1iYWwgaGFzaWwsIHZvbGF0aWxpdGFzLCBkYW4gcGVydHVtYnVoYW4gYXNldC4NCg0KRGF0YXNldCBpbmkgbWVuY2FrdXAgdmFyaWFiZWwga2F0ZWdvcmlzIChzZXBlcnRpIHNlZ21lbiBpbnZlc3Rvciwgd2lsYXlhaCwgZGFuIGplbmlzIGludmVzdGFzaSkgc2VydGEgdmFyaWFiZWwgbnVtZXJpayAoanVtbGFoIGludmVzdGFzaSwgc2tvciByaXNpa28sIGRpdmVyc2lmaWthc2kgcG9ydG9mb2xpbywgZGFuIGltYmFsIGhhc2lsIHRhaHVuYW4pLg0KDQpNZWxhbHVpIGFuYWxpc2lzIHN0YXRpc3RpayBkZXNrcmlwdGlm4oCUdGVybWFzdWsgdWt1cmFuIHRlbmRlbnNpIHNlbnRyYWwgZGFuIGRpc3BlcnNp4oCUc2VydGEgdmlzdWFsaXNhc2kgZGF0YSwgZGFwYXQgZGlwZXJvbGVoIGdhbWJhcmFuIHlhbmcgbGViaWggamVsYXMgbWVuZ2VuYWkgcG9sYSwgZGlzdHJpYnVzaSwgZGFuIGtpbmVyamEgaW52ZXN0b3Igc2VjYXJhIGtlc2VsdXJ1aGFuLg0KDQoNCiMgRGF0YSBwcmVwYXJhdGlvbg0KYGBge3IgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShEVCkNCg0KZGF0YV9pbnZlc3RtZW50NSA8LSByZWFkX2NzdigiQzovVXNlcnMvQWRpbmRhL0Rvd25sb2Fkcy9NaWR0ZXJtIEV4YW0zLmNzdiIpDQoNCmRhdGF0YWJsZSgNCiAgZGF0YV9pbnZlc3RtZW50NSwNCiAgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDEwKSwgICMgdGFtcGlsIDEwIGJhcmlzIHBlciBoYWxhbWFuDQogIGNhcHRpb24gPSAiVGFiZWwgSW50ZXJha3RpZiBEYXRhIENTViINCikNCg0KYGBgDQoNCiMgVmlzdWFsaXphdGlvbnMgRGF0YQ0KIyMgQmFyY2hhcnQNCg0KYGBge3IgaW52ZXN0bWVudC10eXBlLWludGVyYWN0aXZlLXNvZnQsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9NH0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHBsb3RseSkNCg0KIyBIaXR1bmcgZnJla3VlbnNpIGplbmlzIGludmVzdGFzaSBkYW4gdXJ1dGthbiBkYXJpIHRlcmJhbnlhayBrZSB0ZXJrZWNpbA0KaW52ZXN0bWVudF9jb3VudHMgPC0gZGF0YV9pbnZlc3RtZW50NSAlPiUNCiAgY291bnQoSW52ZXN0bWVudFR5cGUpICU+JQ0KICBhcnJhbmdlKGRlc2MobikpDQoNCiMgQnVhdCBncmFmaWsgYmF0YW5nIGRlbmdhbiB3YXJuYSBncmFkYXNpIGJpcnUtdG9za2EgbGVtYnV0DQpwIDwtIGdncGxvdChpbnZlc3RtZW50X2NvdW50cywgYWVzKA0KICB4ID0gcmVvcmRlcihJbnZlc3RtZW50VHlwZSwgLW4pLA0KICB5ID0gbiwNCiAgZmlsbCA9IG4sDQogIHRleHQgPSBwYXN0ZTAoDQogICAgIjxiPkplbmlzIEludmVzdGFzaTo8L2I+ICIsIEludmVzdG1lbnRUeXBlLA0KICAgICI8YnI+PGI+SnVtbGFoIEludmVzdG9yOjwvYj4gIiwgbg0KICApDQopKSArDQogIGdlb21fY29sKHdpZHRoID0gMC43LCBjb2xvciA9ICJ3aGl0ZSIsIGFscGhhID0gMC45NSkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50KA0KICAgIGxvdyA9ICIjQTlDQ0UzIiwgICMgYmlydSBtdWRhIGxlbWJ1dA0KICAgIGhpZ2ggPSAiIzI4NzRBNiIsICMgYmlydSB0ZWdhcyB0YXBpIHRldGFwIHNvZnQNCiAgICBndWlkZSA9ICJub25lIiAgICAjIGxlZ2VuZCBkaWhhcHVzIHRvdGFsDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3RyaWJ1c2kgSnVtbGFoIEludmVzdG9yIEJlcmRhc2Fya2FuIEplbmlzIEludmVzdGFzaSIsDQogICAgeCA9ICJKZW5pcyBJbnZlc3Rhc2kiLA0KICAgIHkgPSAiSnVtbGFoIEludmVzdG9yIg0KICApICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41LCBzaXplID0gMTYpLA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDExKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAuNSksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDIwLCAyMCwgMjAsIDIwKQ0KICApDQoNCiMgVWJhaCBrZSBiZW50dWsgaW50ZXJha3RpZiAoem9vbSArIHRvb2x0aXApDQpnZ3Bsb3RseShwLCB0b29sdGlwID0gInRleHQiKQ0KYGBgDQoNCiMjIyBJbnRlcnByZXRhc2kNClZpc3VhbGlzYXNpIGRpIGF0YXMgbWVudW5qdWtrYW4gcGVyYmFuZGluZ2FuIGp1bWxhaCBpbnZlc3RvciBwYWRhIHNldGlhcCBqZW5pcyBpbnZlc3Rhc2kuIFRlcmxpaGF0IGJhaHdhIGJlYmVyYXBhIGplbmlzIGludmVzdGFzaSBtZW1pbGlraSBqdW1sYWggaW52ZXN0b3IgeWFuZyBqYXVoIGxlYmloIHRpbmdnaSBkaWJhbmRpbmcgbGFpbm55YSwgbWVuYW5kYWthbiBhZGFueWEgcHJlZmVyZW5zaSBhdGF1IG1pbmF0IHlhbmcgbGViaWggYmVzYXIgdGVyaGFkYXAgamVuaXMgaW52ZXN0YXNpIHRlcnRlbnR1Lg0KDQpkYXBhdCBkaXNpbXB1bGthbiBiYWh3YSBqZW5pcyBpbnZlc3Rhc2kgZGVuZ2FuIGp1bWxhaCBpbnZlc3RvciB0ZXJ0aW5nZ2kgbWVydXBha2FuIHBpbGloYW4geWFuZyBwYWxpbmcgcG9wdWxlciBkYW4gZGlhbmdnYXAgbGViaWggYW1hbiBhdGF1IG1lbmd1bnR1bmdrYW4gb2xlaCBtYXlvcml0YXMgcmVzcG9uZGVuLCBzZWRhbmdrYW4gamVuaXMgZGVuZ2FuIGp1bWxhaCBpbnZlc3RvciBwYWxpbmcgc2VkaWtpdCBtdW5na2luIG1lbWlsaWtpIHJpc2lrbyBhdGF1IHRpbmdrYXQga2VwZXJjYXlhYW4geWFuZyBsZWJpaCByZW5kYWguDQoNCiMjIEhpc3RvZ3JhbQ0KYGBge3IgaGlzdG9ncmFtLWFnZS1ncm91cGVkLWludGVyYWN0aXZlLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTR9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwbG90bHkpDQoNCiMgUGFzdGlrYW4ga29sb20gYWdlIG51bWVyaWsNCg0KZGF0YV9pbnZlc3RtZW50NSA8LSBkYXRhX2ludmVzdG1lbnQ1ICU+JQ0KbXV0YXRlKEFnZSA9IGFzLm51bWVyaWMoQWdlKSkgICMgZGlzZXN1YWlrYW4NCg0KIyBLZWxvbXBva2thbiB1c2lhIGRhbGFtIGludGVydmFsDQoNCmRhdGFfaW52ZXN0bWVudDUgPC0gZGF0YV9pbnZlc3RtZW50NSAlPiUNCm11dGF0ZShBZ2VHcm91cCA9IGN1dCgNCkFnZSwNCmJyZWFrcyA9IHNlcSgyMCwgNzAsIGJ5ID0gMTApLA0KbGFiZWxzID0gYygiMjDigJMyOSIsICIzMOKAkzM5IiwgIjQw4oCTNDkiLCAiNTDigJM1OSIsICI2MOKAkzY5IiksDQpyaWdodCA9IEZBTFNFDQopKQ0KDQojIEhpdHVuZyBmcmVrdWVuc2kgZGFuIHVydXRrYW4NCg0KYWdlX2dyb3VwX2ZyZXEgPC0gZGF0YV9pbnZlc3RtZW50NSAlPiUNCmNvdW50KEFnZUdyb3VwKSAlPiUNCmFycmFuZ2UoZGVzYyhuKSkNCg0KIyBQbG90IGJhdGFuZyB1cnV0ICsgdG9vbHRpcCBpbnRlcmFrdGlmDQoNCnAgPC0gZ2dwbG90KGFnZV9ncm91cF9mcmVxLCBhZXMoDQp4ID0gcmVvcmRlcihBZ2VHcm91cCwgLW4pLA0KeSA9IG4sDQp0ZXh0ID0gcGFzdGUoDQoiS2Vsb21wb2sgVXNpYToiLCBBZ2VHcm91cCwNCiI8YnI+SnVtbGFoIEludmVzdG9yOiIsIG4NCikNCikpICsNCmdlb21fY29sKA0KZmlsbCA9ICIjQUVENkYxIiwNCmNvbG9yID0gIndoaXRlIiwNCndpZHRoID0gMC42NSwNCmFscGhhID0gMC45NQ0KKSArDQpsYWJzKA0KdGl0bGUgPSAiRGlzdHJpYnVzaSBLZWxvbXBvayBVc2lhIEludmVzdG9yIiwNCnggPSAiS2Vsb21wb2sgVXNpYSAoVGFodW4pIiwNCnkgPSAiRnJla3VlbnNpIg0KKSArDQp0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEzKSArDQp0aGVtZSgNCnBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNSwgZmFjZSA9ICJib2xkIiksDQpheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQpheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCnBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwNCnBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkNCikNCg0KIyBKYWRpa2FuIGludGVyYWt0aWYNCg0KZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lDQpsYXlvdXQoZHJhZ21vZGUgPSAiem9vbSIpDQoNCmBgYA0KDQojIyMgSW50ZXJwcmV0YXNpDQpIaXN0b2dyYW0gZGlhdGFzIG1lbnVuanVra2FuIGRpc3RyaWJ1c2kgdXNpYSBwYXJhIGludmVzdG9yIGRhbGFtIGRhdGFzZXQuDQpTZWJhZ2lhbiBiZXNhciBpbnZlc3RvciBiZXJhZGEgcGFkYSByZW50YW5nIHVzaWEgcHJvZHVrdGlmIChzZWtpdGFyIDMw4oCTNDUgdGFodW4pLCB5YW5nIG1lbmFuZGFrYW4gYmFod2Ega2Vsb21wb2sgdXNpYSBpbmkgcGFsaW5nIGFrdGlmIGRhbGFtIGtlZ2lhdGFuIGludmVzdGFzaS4NCkRpc3RyaWJ1c2kgdGVybGloYXQgcmVsYXRpZiBub3JtYWwsIG1lc2tpcHVuIGFkYSBrZW11bmdraW5hbiBzZWRpa2l0IGtlbWlyaW5nYW4gKHNrZXduZXNzKSBrZSBrYW5hbiB5YW5nIG1lbnVuanVra2FuIHNlYmFnaWFuIGtlY2lsIGludmVzdG9yIGJlcnVzaWEgbGViaWggdHVhLg0KSGFsIGluaSBkYXBhdCBkaWFydGlrYW4gYmFod2EgcGFydGlzaXBhc2kgaW52ZXN0YXNpIGNlbmRlcnVuZyBtZW51cnVuIHBhZGEgdXNpYSBsYW5qdXQsIHNlbWVudGFyYSBrZWxvbXBvayB1c2lhIG1lbmVuZ2FoIG1lbmRvbWluYXNpIHBhc2FyIGthcmVuYSBtZW1pbGlraSBrZXN0YWJpbGFuIGZpbmFuc2lhbCBkYW4gbWluYXQgaW52ZXN0YXNpIHlhbmcgdGluZ2dpLg0KDQojIyBTY2F0dGVyIHBsb3QNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD00fQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwbG90bHkpDQoNCiMgU2NhdHRlciBwbG90IGRlbmdhbiBnYXJpcyB0cmVuDQpzY2F0dGVyX3Bsb3QgPC0gZ2dwbG90KGRhdGFfaW52ZXN0bWVudDUsIGFlcyh4ID0gQWdlLCB5ID0gQW5udWFsUmV0dXJuKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gIiMyRTg2QUIiLCBhbHBoYSA9IDAuNywgc2l6ZSA9IDMpICsgICMgVGl0aWsgZGF0YQ0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICJsaWdodHBpbmsiLCBzZSA9IFRSVUUsIGxpbmV3aWR0aCA9IDEpICsgICMgR2FyaXMgdHJlbiBsaW5lYXINCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJIdWJ1bmdhbiBhbnRhcmEgVXNpYSBJbnZlc3RvciBkYW4gVGluZ2thdCBLZXVudHVuZ2FuIFRhaHVuYW4iLA0KICAgIHggPSAiVXNpYSBJbnZlc3RvciAoVGFodW4pIiwNCiAgICB5ID0gIktldW50dW5nYW4gVGFodW5hbiAoJSkiLA0KICAgIGNhcHRpb24gPSAiU3VtYmVyIGRhdGE6IE1pZHRlcm0gRXhhbSBJbnZlc3RtZW50IERhdGEiDQogICkNCg0KIyBVYmFoIHBsb3QgaW50ZXJha3RpZg0KaW50ZXJhY3RpdmVfc2NhdHRlciA8LSBnZ3Bsb3RseShzY2F0dGVyX3Bsb3QpDQppbnRlcmFjdGl2ZV9zY2F0dGVyDQpgYGANCg0KIyMjIEludGVycHJldGFzaQ0KVmlzdWFsaXNhc2kgaW5pIG1lbnVuanVra2FuIGh1YnVuZ2FuIGFudGFyYSB1c2lhIGludmVzdG9yIGRhbiB0aW5na2F0IGtldW50dW5nYW4gdGFodW5hbiAoYW5udWFsIHJldHVybikuIFRpdGlrLXRpdGlrIGRhdGEgbWVuZ2dhbWJhcmthbiBzZWJhcmFuIG5pbGFpIHJldHVybiBkaSBiZXJiYWdhaSBrZWxvbXBvayB1c2lhLCBzZW1lbnRhcmEgZ2FyaXMgdHJlbiBsaW5lYXIgbWVtcGVybGloYXRrYW4gYXJhaCBodWJ1bmdhbiB1bXVtIGRpIGFudGFyYSBrZWR1YW55YS4NCg0KRGFyaSBncmFmaWsgdGVybGloYXQgYmFod2EgdGlkYWsgYWRhIGh1YnVuZ2FuIGxpbmVhciB5YW5nIGt1YXQgYW50YXJhIHVzaWEgZGFuIHRpbmdrYXQga2V1bnR1bmdhbiB0YWh1bmFuIOKAlCBhcnRpbnlhLCBwZW5pbmdrYXRhbiB1c2lhIHRpZGFrIHNlY2FyYSBrb25zaXN0ZW4gZGlpa3V0aSBvbGVoIHBlbmluZ2thdGFuIGF0YXUgcGVudXJ1bmFuIHJldHVybi4gU2ViYXJhbiB0aXRpayB5YW5nIGN1a3VwIGx1YXMgbWVudW5qdWtrYW4gYWRhbnlhIHZhcmlhc2kgKGRpc3BlcnNpKSB5YW5nIHRpbmdnaSBhbnRhcmluZGl2aWR1LCBtZW5hbmRha2FuIGJhaHdhIGZha3RvciBsYWluIHNlbGFpbiB1c2lhIChzZXBlcnRpIHBlbmdhbGFtYW4gYXRhdSBwcm9maWwgcmlzaWtvKSBrZW11bmdraW5hbiBiZXJwZW5nYXJ1aCBsZWJpaCBiZXNhciB0ZXJoYWRhcCBoYXNpbCBpbnZlc3Rhc2kuDQoNCiMjIEJveCBwbG90IA0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD00LCBvdXQud2lkdGg9JzgwJSd9DQpsaWJyYXJ5KHBsb3RseSkNCg0KcF9ib3hfc29mdCA8LSBwbG90X2x5KA0KICBkYXRhID0gZGF0YV9pbnZlc3RtZW50NSwNCiAgeCA9IH5SaXNrUHJvZmlsZSwNCiAgeSA9IH5Bbm51YWxSZXR1cm4sDQogIGNvbG9yID0gflJpc2tQcm9maWxlLA0KICB0eXBlID0gImJveCIsDQogIGNvbG9ycyA9IGMoIiNDREU4RTUiLCAiI0U4REZGNSIsICIjRkRFMkU0IiksDQogIGJveG1lYW4gPSBUUlVFLA0KICBob3ZlcmluZm8gPSAidGV4dCIsDQogIHRleHQgPSB+cGFzdGUoDQogICAgIlJpc2sgUHJvZmlsZTogIiwgUmlza1Byb2ZpbGUsDQogICAgIjxicj5Bbm51YWwgUmV0dXJuOiAiLCByb3VuZChBbm51YWxSZXR1cm4sIDIpLCAiJSINCiAgKSwNCiAgbWFya2VyID0gbGlzdChvdXRsaWVyY29sb3IgPSAnIzlFOUU5RScsIG9wYWNpdHkgPSAwLjcpDQopICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSBsaXN0KA0KICAgICAgdGV4dCA9ICJEaXN0cmlidXNpIEFubnVhbCBSZXR1cm4gQmVyZGFzYXJrYW4gUmlzayBQcm9maWxlIiwNCiAgICAgIHggPSAwLjUsDQogICAgICBmb250ID0gbGlzdChzaXplID0gMTgsIGNvbG9yID0gIiMzMzMzMzMiLCBmYW1pbHkgPSAiQXJpYWwgQmxhY2siKQ0KICAgICksDQogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlJpc2sgUHJvZmlsZSIsIHRpdGxlZm9udCA9IGxpc3Qoc2l6ZSA9IDE0KSksDQogICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkFubnVhbCBSZXR1cm4gKCUpIiwgdGl0bGVmb250ID0gbGlzdChzaXplID0gMTQpKSwNCiAgICBwbG90X2JnY29sb3IgPSAiI0ZGRkZGRiIsDQogICAgcGFwZXJfYmdjb2xvciA9ICIjRkZGRkZGIiwNCiAgICBmb250ID0gbGlzdChmYW1pbHkgPSAiQXJpYWwiLCBjb2xvciA9ICIjNDQ0NDQ0IikNCiAgKQ0KDQpwX2JveF9zb2Z0DQoNCmBgYA0KDQojIyMgSW50ZXJwcmV0YXNpDQpWaXN1YWxpc2FzaSBib3ggcGxvdCBpbmkgbWVudW5qdWtrYW4gcGVyYmVkYWFuIHNlYmFyYW4gYW5udWFsIHJldHVybiBiZXJkYXNhcmthbiBrYXRlZ29yaSByaXNrIHByb2ZpbGUgaW52ZXN0b3IuDQpJbnZlc3RvciBkZW5nYW4gcHJvZmlsIHJpc2lrbyB0aW5nZ2kgKEhpZ2ggUmlzaykgY2VuZGVydW5nIG1lbWlsaWtpIGFubnVhbCByZXR1cm4geWFuZyBsZWJpaCBiZXNhciwgbmFtdW4gZGVuZ2FuIHNlYmFyYW4gbmlsYWkgeWFuZyBqdWdhIGxlYmloIGx1YXMg4oCUIG1lbmFuZGFrYW4gdmFyaWFiaWxpdGFzIChkaXNwZXJzaSkgeWFuZyB0aW5nZ2kgZGFuIHBvdGVuc2kgcmlzaWtvIGxlYmloIGJlc2FyLg0KU2ViYWxpa255YSwgcHJvZmlsIHJpc2lrbyByZW5kYWggKExvdyBSaXNrKSBtZW5hbXBpbGthbiByZW50YW5nIG5pbGFpIHJldHVybiB5YW5nIHNlbXBpdCwgbWVuY2VybWlua2FuIHN0YWJpbGl0YXMgZGFuIGtvbnNpc3RlbnNpIGhhc2lsIGludmVzdGFzaS4NClByb2ZpbCByaXNpa28gc2VkYW5nIChNb2RlcmF0ZSkgYmVyYWRhIGRpIGFudGFyYSBrZWR1YW55YSwgbWVudW5qdWtrYW4ga2VzZWltYmFuZ2FuIGFudGFyYSByaXNpa28gZGFuIHBvdGVuc2kgaW1iYWwgaGFzaWwuDQoNCiMjIExpbmUgY2hhcnQNCmBgYHtyIGxpbmVjaGFydC1leHBlcmllbmNlLWludGVyYWN0aXZlLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTR9DQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZHBseXIpDQoNCiMgSGl0dW5nIHJhdGEtcmF0YSByZXR1cm4gcGVyIHRpbmdrYXQgcGVuZ2FsYW1hbiBpbnZlc3Rhc2kNCnJldHVybl9leHAgPC0gZGF0YV9pbnZlc3RtZW50NSAlPiUNCiAgZ3JvdXBfYnkoSW52ZXN0bWVudEV4cGVyaWVuY2UpICU+JQ0KICBzdW1tYXJpc2UoQXZlcmFnZVJldHVybiA9IG1lYW4oQW5udWFsUmV0dXJuLCBuYS5ybSA9IFRSVUUpKQ0KDQojIEJ1YXQgbGluZSBjaGFydCBpbnRlcmFrdGlmDQpmaWcgPC0gcGxvdF9seSgNCiAgZGF0YSA9IHJldHVybl9leHAsDQogIHggPSB+SW52ZXN0bWVudEV4cGVyaWVuY2UsDQogIHkgPSB+QXZlcmFnZVJldHVybiwNCiAgdHlwZSA9ICdzY2F0dGVyJywNCiAgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywNCiAgbGluZSA9IGxpc3QoY29sb3IgPSAnIzg5Q0ZGMCcsIHdpZHRoID0gMyksICAjIEJpcnUgc29mdCBwYXN0ZWwNCiAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjQTdDN0U3Jywgc2l6ZSA9IDgsIGxpbmUgPSBsaXN0KGNvbG9yID0gJyM0RjhGQzAnLCB3aWR0aCA9IDEpKSwNCiAgdGV4dCA9IH5wYXN0ZSgNCiAgICAiPGI+VGluZ2thdCBQZW5nYWxhbWFuOjwvYj4iLCBJbnZlc3RtZW50RXhwZXJpZW5jZSwNCiAgICAiPGJyPjxiPlJhdGEtcmF0YSBSZXR1cm46PC9iPiIsIHJvdW5kKEF2ZXJhZ2VSZXR1cm4sIDIpLCAiJSINCiAgKSwNCiAgaG92ZXJpbmZvID0gJ3RleHQnDQopICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSBsaXN0KA0KICAgICAgdGV4dCA9ICJSYXRhLXJhdGEgQW5udWFsIFJldHVybiBCZXJkYXNhcmthbiBQZW5nYWxhbWFuIEludmVzdGFzaSIsDQogICAgICB4ID0gMC41LA0KICAgICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDE4LCBjb2xvciA9ICcjM0EzQTNBJykNCiAgICApLA0KICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJUaW5na2F0IFBlbmdhbGFtYW4gSW52ZXN0YXNpIiwgdGl0bGVmb250ID0gbGlzdChzaXplID0gMTQpKSwNCiAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiUmF0YS1yYXRhIEFubnVhbCBSZXR1cm4gKCUpIiwgdGl0bGVmb250ID0gbGlzdChzaXplID0gMTQpKSwNCiAgICBwbG90X2JnY29sb3IgPSAnI0Y5RkFGQicsDQogICAgcGFwZXJfYmdjb2xvciA9ICcjRjlGQUZCJw0KICApDQoNCmZpZw0KDQpgYGANCg0KIyMjIEludGVycHJldGFzaQ0KDQpHcmFmaWsgbWVudW5qdWtrYW4gYmFod2Egc2VtYWtpbiB0aW5nZ2kgdGluZ2thdCBwZW5nYWxhbWFuIGludmVzdGFzaSwgc2VtYWtpbiBiZXNhciByYXRhLXJhdGEgQW5udWFsIFJldHVybiB5YW5nIGRpcGVyb2xlaCBpbnZlc3Rvci4gVHJlbiBnYXJpcyB5YW5nIG1lbmluZ2thdCBtZW5hbmRha2FuIGFkYW55YSBodWJ1bmdhbiBwb3NpdGlmIGFudGFyYSBwZW5nYWxhbWFuIGRhbiBraW5lcmphIGludmVzdGFzaS4gSGFsIGluaSBtZW5naW5kaWthc2lrYW4gYmFod2EgcGVuZ2FsYW1hbiBiZXJwZXJhbiBwZW50aW5nIGRhbGFtIGtlbWFtcHVhbiBpbnZlc3RvciBtZW5nZWxvbGEgcmlzaWtvIGRhbiBtZW1ha3NpbWFsa2FuIGtldW50dW5nYW4uDQoNClRpZGFrIHRlcmxpaGF0IGFkYW55YSBvdXRsaWVyIGF0YXUgZmx1a3R1YXNpIGVrc3RyZW0sIHlhbmcgYmVyYXJ0aSBkYXRhIHJlbGF0aWYga29uc2lzdGVuIGRhbiBzdGFiaWwgZGkgc2V0aWFwIHRpbmdrYXQgcGVuZ2FsYW1hbi4gRGVuZ2FuIGRlbWlraWFuLCB2YXJpYWJlbCBJbnZlc3RtZW50RXhwZXJpZW5jZSBkYXBhdCBkaWFuZ2dhcCBtZW1pbGlraSBwZW5nYXJ1aCB5YW5nIHNpZ25pZmlrYW4gdGVyaGFkYXAgQW5udWFsUmV0dXJuLCBzZXJ0YSBtZW1wZXJsaWhhdGthbiBwb2xhIGRpc3RyaWJ1c2kgeWFuZyBwcm9wb3JzaW9uYWwgZGFuIG11ZGFoIGRpaW50ZXJwcmV0YXNpa2FuIHNlY2FyYSB2aXN1YWwuDQoNCg0KIyBDZW50cmFsIFRlbmRlbmN5DQpBbmFsaXNpcyBpbmkgZGlsYWt1a2FuIHVudHVrIG1lbWFoYW1pIHVrdXJhbiBwZW11c2F0YW4gZGF0YSBkYXJpIGR1YSB2YXJpYWJlbCBudW1lcmlrLCB5YWl0dSBBZ2UgKHVzaWEgaW52ZXN0b3IpIGRhbiBBbm51YWxSZXR1cm4gKHBlcnNlbnRhc2UgaGFzaWwgaW52ZXN0YXNpIHRhaHVuYW4pLg0KS2VkdWEgdmFyaWFiZWwgaW5pIGRpcGlsaWgga2FyZW5hOg0KDQotIEFnZSBtZW5nZ2FtYmFya2FuIGZha3RvciBkZW1vZ3JhZmlzIGludmVzdG9yIHlhbmcgYmVyc2lmYXQgc3RhYmlsIGRhbiBrb250aW51Lg0KDQotIEFubnVhbFJldHVybiBtZW51bmp1a2thbiBwZXJmb3JtYSBpbnZlc3Rhc2kgeWFuZyBiaXNhIG1lbmNlcm1pbmthbiB2YXJpYXNpIHRpbmdrYXQgcmlzaWtvIGRhbiBrZXVudHVuZ2FuLg0KDQpEZW5nYW4gbWVuZ2hpdHVuZyBtZWFuLCBtZWRpYW4sIGRhbiBtb2RlLCBraXRhIGRhcGF0IG1lbmdpZGVudGlmaWthc2kgYXBha2FoIGRpc3RyaWJ1c2kgZGF0YSBiZXJzaWZhdCBzaW1ldHJpcywgbWlyaW5nIGtlIGthbmFuIChyaWdodC1za2V3ZWQpLCBhdGF1IG1pcmluZyBrZSBraXJpIChsZWZ0LXNrZXdlZCkuDQoNClVrdXJhbiBwZW11c2F0YW4gZGF0YSB5YW5nIGRpZ3VuYWthbiB0ZXJkaXJpIGRhcmkgdGlnYSBqZW5pcyB1dGFtYToNCg0KKiotIE1lYW4gKFJhdGEtcmF0YSkqKg0KDQogICBSdW11czogIA0KICAgXFsNCiAgIFxtYXRoYmZ7TWVhbn0gPSBcZnJhY3tcc3VtIHhfaX17bn0NCiAgIFxdDQoNCioqS2V0ZXJhbmdhbjoqKg0KDQotIFwoIHhfaSBcKSA9IG5pbGFpIGtlLWkgZGFyaSBkYXRhICANCi0gXCggbiBcKSA9IGp1bWxhaCB0b3RhbCBkYXRhICANCg0KQXJ0aW55YSwgc2VtdWEgbmlsYWkgZGlqdW1sYWhrYW4gbGFsdSBkaWJhZ2kgZGVuZ2FuIGp1bWxhaCBkYXRhLg0KDQoqKi0gTWVkaWFuIChOaWxhaSBUZW5nYWgpKioNCg0KTWVkaWFuIGFkYWxhaCBuaWxhaSB5YW5nIGJlcmFkYSBkaSB0ZW5nYWggc2V0ZWxhaCBkYXRhIGRpdXJ1dGthbiBkYXJpIHlhbmcgdGVya2VjaWwga2UgdGVyYmVzYXIuICANCkppa2EganVtbGFoIGRhdGEgKipnYW5qaWwqKiwgbWVkaWFuID0gbmlsYWkgZGkgcG9zaXNpIHRlbmdhaC4gIA0KSmlrYSBqdW1sYWggZGF0YSAqKmdlbmFwKiosIG1lZGlhbiA9IHJhdGEtcmF0YSBkYXJpIGR1YSBuaWxhaSB0ZW5nYWguDQoNCioqLSBNb2RlIChNb2R1cykqKg0KDQpNb2RlIGFkYWxhaCBuaWxhaSB5YW5nIHBhbGluZyBzZXJpbmcgbXVuY3VsIGRhbGFtIHN1YXR1IGt1bXB1bGFuIGRhdGEuICANCkppa2EgaGFueWEgYWRhIHNhdHUgbmlsYWkgeWFuZyBzZXJpbmcgbXVuY3VsIOKGkiAqKnVuaW1vZGFsKiosICANCmppa2EgZHVhIG5pbGFpIOKGkiAqKmJpbW9kYWwqKiwgIA0KZGFuIGppa2EgbGViaWggZGFyaSBkdWEg4oaSICoqbXVsdGltb2RhbCoqLg0KDQojIyBQZXJoaXR1bmdhbiAobWVhbiwgbWVhZGlhbiwgbW9kZSkNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Nywgb3V0LndpZHRoPSc4MCUnfQ0KIyAtLS0gTGlicmFyeSB5YW5nIGRpZ3VuYWthbiAtLS0NCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIC0tLSBNZW1iYWNhIGRhdGFzZXQgLS0tDQpkYXRhX2ludmVzdG1lbnQ1IDwtIHJlYWRfY3N2KCJDOi9Vc2Vycy9BZGluZGEvRG93bmxvYWRzL01pZHRlcm0gRXhhbTMuY3N2IikNCg0KIyAtLS0gTWVuZ2hpdHVuZyBNZWFuLCBNZWRpYW4sIGRhbiBNb2RlIHVudHVrIGR1YSB2YXJpYWJlbCBudW1lcmlrIC0tLQ0KIyBWYXJpYWJlbCAxOiBBZ2UNCm1lYW5fYWdlIDwtIG1lYW4oZGF0YV9pbnZlc3RtZW50NSRBZ2UsIG5hLnJtID0gVFJVRSkNCm1lZGlhbl9hZ2UgPC0gbWVkaWFuKGRhdGFfaW52ZXN0bWVudDUkQWdlLCBuYS5ybSA9IFRSVUUpDQptb2RlX2FnZSA8LSBhcy5udW1lcmljKG5hbWVzKHNvcnQodGFibGUoZGF0YV9pbnZlc3RtZW50NSRBZ2UpLCBkZWNyZWFzaW5nID0gVFJVRSlbMV0pKQ0KDQojIC0tLSBNZW55dXN1biBoYXNpbCBwZXJoaXR1bmdhbiBrZSBkYWxhbSB0YWJlbCAtLS0NCnRhYmVsX2NlbnRyYWwgPC0gZGF0YS5mcmFtZSgNCiAgVmFyaWFibGUgPSBjKCJBZ2UiKSwNCiAgTWVhbiA9IGMobWVhbl9hZ2UpLA0KICBNZWRpYW4gPSBjKG1lZGlhbl9hZ2UpLA0KICBNb2RlID0gYyhtb2RlX2FnZSkNCikNCg0KIyAtLS0gTWVuYW1waWxrYW4gdGFiZWwgaGFzaWwgLS0tDQp0YWJlbF9jZW50cmFsDQpgYGANCg0KIyMgSW50ZXJwcmV0YXNpIEhhc2lsIFBlcmhpdHVuZ2FuIChtZWFuLCBtZWRpYW4sIG1vZGUpDQoNCi0gQWdlOiBOaWxhaSBtZWFuLCBtZWRpYW4sIGRhbiBtb2RlIHNhbGluZyBiZXJkZWthdGFuIOKGkiBkaXN0cmlidXNpIGRhdGEgc2ltZXRyaXMuDQoNCi0gQW5udWFsUmV0dXJuOiBNZWFuIGxlYmloIHRpbmdnaSBkYXJpIG1lZGlhbiBkYW4gbW9kZSDihpIgZGlzdHJpYnVzaSBtaXJpbmcga2Uga2FuYW4gKHJpZ2h0LXNrZXdlZCksIG1lbmFuZGFrYW4gYWRhIGJlYmVyYXBhIGludmVzdG9yIGRlbmdhbiBoYXNpbCBzYW5nYXQgdGluZ2dpLg0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD04fQ0KbGlicmFyeShnZ3Bsb3QyKQ0KIyAtLS0gU3ltbWV0cmljYWwgZGF0YTogUGVyZmVjdCBiZWxsLXNoYXBlZCAoTm9ybWFsIERpc3RyaWJ1dGlvbiwgbm8gb3V0bGllcnMpIC0tLQ0Kc2V0LnNlZWQoMTIzKQ0KDQpkYXRhX2ludmVzdG1lbnQ1IDwtIGRhdGEuZnJhbWUoYWdlID0gcm5vcm0oMjAwLCBtZWFuID0gNTAsIHNkID0gMTApKQ0KIyAtLS0gQ29tcHV0ZSBNZWFuLCBNZWRpYW4sIE1vZGUgLS0tDQptZWFuX3ZhbCA8LSBtZWFuKGRhdGFfaW52ZXN0bWVudDUkYWdlKQ0KbWVkaWFuX3ZhbCA8LSBtZWRpYW4oZGF0YV9pbnZlc3RtZW50NSRhZ2UpDQptb2RlX3ZhbCA8LSBhcy5udW1lcmljKG5hbWVzKHNvcnQodGFibGUocm91bmQoZGF0YV9pbnZlc3RtZW50NSRhZ2UsIDApKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNyZWFzaW5nID0gVFJVRSlbMV0pKQ0KIyAtLS0gVmlzdWFsaXphdGlvbiAoSGlzdG9ncmFtICsgRGVuc2l0eSkgLS0tDQpnZ3Bsb3QoZGF0YV9pbnZlc3RtZW50NSwgYWVzKHggPSBhZ2UpKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gYWZ0ZXJfc3RhdChkZW5zaXR5KSksIA0KICAgICAgICAgICAgICAgICBiaW53aWR0aCA9IDIsIA0KICAgICAgICAgICAgICAgICBmaWxsID0gIiM1YWI0YWMiLCANCiAgICAgICAgICAgICAgICAgY29sb3IgPSAid2hpdGUiLCANCiAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjgpICsNCiAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gIiMyYjhjYmUiLCBsaW5ld2lkdGggPSAxLjMsIGFscGhhID0gMC45KSArDQogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuX3ZhbCwgY29sb3IgPSAiTWVhbiIpLCBsaW5ld2lkdGggPSAxLjIpICsNCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lZGlhbl92YWwsIGNvbG9yID0gIk1lZGlhbiIpLCANCiAgICAgICAgICAgICBsaW5ld2lkdGggPSAxLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1vZGVfdmFsLCBjb2xvciA9ICJNb2RlIiksIA0KICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEuMiwgbGluZXR5cGUgPSAiZG90ZGFzaCIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJTeW1tZXRyaWNhbCBEaXN0cmlidXRpb24gKE5vIE91dGxpZXJzKSIsDQogICAgc3VidGl0bGUgPSAiTWVhbiwgTWVkaWFuLCBhbmQgTW9kZSBjb2luY2lkZSBhdCB0aGUgY2VudGVyIG9mIHRoZSBiZWxsIGN1cnZlIiwNCiAgICB4ID0gImFnZSIsDQogICAgeSA9ICJEZW5zaXR5IiwNCiAgICBjb2xvciA9ICJNZWFzdXJlIg0KICApICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41KSwNCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIg0KICApDQoNCmBgYA0KDQojIyMgSW50ZXJwcmV0YXNpIGFnZQ0KRGlzdHJpYnVzaSBkYXRhIHBhZGEgdmFyaWFiZWwgQWdlIG1lbnVuanVra2FuIHBvbGEgc2ltZXRyaXMgYmVyYmVudHVrIGxvbmNlbmcgKGJlbGwgY3VydmUpLCBkaSBtYW5hIGdhcmlzIE1lYW4sIE1lZGlhbiwgZGFuIE1vZGUgYmVyYWRhIGRpIHBvc2lzaSB5YW5nIGhhbXBpciBzYW1hIGRpIHRlbmdhaCBkaXN0cmlidXNpLiBIYWwgaW5pIG1lbmFuZGFrYW4gYmFod2Egc2ViYWdpYW4gYmVzYXIgaW5kaXZpZHUgbWVtaWxpa2kgbmlsYWkgdXNpYSB5YW5nIGJlcmFkYSBkaSBzZWtpdGFyIHJhdGEtcmF0YSwgZGVuZ2FuIGp1bWxhaCB5YW5nIHNlaW1iYW5nIGFudGFyYSBuaWxhaSBkaSBiYXdhaCBkYW4gZGkgYXRhcyByYXRhLXJhdGEuDQoNCkthcmVuYSBrZXRpZ2EgdWt1cmFuIHRlbmRlbnNpIHNlbnRyYWwgdGVyc2VidXQgYmVyaW1waXQsIG1ha2EgdGlkYWsgdGVyZGFwYXQga2VtaXJpbmdhbiAoc2tld25lc3MpIHlhbmcgYmVyYXJ0aSBwYWRhIGRhdGEgaW5pLiBEZW5nYW4ga2F0YSBsYWluLCBkaXN0cmlidXNpIHRpZGFrIG1pcmluZyBrZSBrYW5hbiBtYXVwdW4ga2Uga2lyaS4gVmlzdWFsaXNhc2kgaW5pIGp1Z2EgbWVtcGVybGloYXRrYW4gdGlkYWsgYWRhbnlhIG91dGxpZXIgeWFuZyBla3N0cmVtLCB5YW5nIGJlcmFydGkgcGVueWViYXJhbiB1c2lhIGNlbmRlcnVuZyBzdGFiaWwuDQoNCg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9Jzg1JSd9DQojIC0tLSBMaWJyYXJ5IHlhbmcgZGlidXR1aGthbiAtLS0NCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShncmlkRXh0cmEpDQoNCiMgLS0tIE1lbWJhY2EgZGF0YSAtLS0NCmRhdGFfaW52ZXN0bWVudDUgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL0FkaW5kYS9Eb3dubG9hZHMvTWlkdGVybSBFeGFtMy5jc3YiKQ0KDQojIC0tLSBNZW5naGl0dW5nIG5pbGFpIE1lYW4sIE1lZGlhbiwgTW9kZSB1bnR1ayBBbm51YWxSZXR1cm4gLS0tDQptZWFuX3JldCA8LSBtZWFuKGRhdGFfaW52ZXN0bWVudDUkQW5udWFsUmV0dXJuLCBuYS5ybSA9IFRSVUUpDQptZWRpYW5fcmV0IDwtIG1lZGlhbihkYXRhX2ludmVzdG1lbnQ1JEFubnVhbFJldHVybiwgbmEucm0gPSBUUlVFKQ0KbW9kZV9yZXQgPC0gYXMubnVtZXJpYyhuYW1lcyhzb3J0KHRhYmxlKGRhdGFfaW52ZXN0bWVudDUkQW5udWFsUmV0dXJuKSwgZGVjcmVhc2luZyA9IFRSVUUpWzFdKSkNCg0KIyAtLS0gTWVuYW1waWxrYW4gaGFzaWwgcGVyaGl0dW5nYW4gZGFsYW0gdGFiZWwgLS0tDQpjZW50cmFsX3RlbmRlbmN5IDwtIGRhdGEuZnJhbWUoDQogIE1lYXN1cmUgPSBjKCJNZWFuIiwgIk1lZGlhbiIsICJNb2RlIiksDQogIEFubnVhbFJldHVybiA9IGMobWVhbl9yZXQsIG1lZGlhbl9yZXQsIG1vZGVfcmV0KQ0KKQ0KY2VudHJhbF90ZW5kZW5jeQ0KDQojIC0tLSBNZW1idWF0IFZpc3VhbGlzYXNpIEhpc3RvZ3JhbSArIERlbnNpdHkgUGxvdCAtLS0NCmdncGxvdChkYXRhX2ludmVzdG1lbnQ1LCBhZXMoeCA9IEFubnVhbFJldHVybikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwNCiAgICAgICAgICAgICAgICAgYmlucyA9IDMwLA0KICAgICAgICAgICAgICAgICBmaWxsID0gIiM1YWI0YWMiLA0KICAgICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICAgIGFscGhhID0gMC44KSArDQogIGdlb21fZGVuc2l0eShjb2xvciA9ICIjMmI4Y2JlIiwgbGluZXdpZHRoID0gMS4zLCBhbHBoYSA9IDAuOSkgKw0KICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbl9yZXQsIGNvbG9yID0gIk1lYW4iKSwgbGluZXdpZHRoID0gMS4yKSArDQogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWRpYW5fcmV0LCBjb2xvciA9ICJNZWRpYW4iKSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgbGluZXdpZHRoID0gMS4yKSArDQogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtb2RlX3JldCwgY29sb3IgPSAiTW9kZSIpLCBsaW5ldHlwZSA9ICJkb3RkYXNoIiwgbGluZXdpZHRoID0gMS4yKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnVzaSBBbm51YWwgUmV0dXJuIiwNCiAgICBzdWJ0aXRsZSA9ICJWaXN1YWxpc2FzaSBNZWFuLCBNZWRpYW4sIGRhbiBNb2RlIHBhZGEgVmFyaWFiZWwgQW5udWFsIFJldHVybiIsDQogICAgeCA9ICJBbm51YWwgUmV0dXJuIiwNCiAgICB5ID0gIkRlbnNpdHkiLA0KICAgIGNvbG9yID0gIndoaXRlIg0KICApICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41KSwNCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIg0KICApDQpgYGANCg0KIyMjIEludGVycHJldGFzaQ0KTmlsYWkgbWVhbiwgbWVkaWFuLCBkYW4gbW9kZSBwYWRhIHZhcmlhYmVsIEFubnVhbCBSZXR1cm4gaGFtcGlyIHNhbWEsIG1lbnVuanVra2FuIGJhaHdhIGRhdGEgbWVtaWxpa2kgZGlzdHJpYnVzaSBzaW1ldHJpcyB0YW5wYSBrZW1lbmNlbmdhbiBiZXJhcnRpLg0KR3JhZmlrIGhpc3RvZ3JhbSBtZW1iZW50dWsgcG9sYSBrdXJ2YSBsb25jZW5nLCBkaSBtYW5hIHNlYmFnaWFuIGJlc2FyIGRhdGEgdGVya29uc2VudHJhc2kgZGkgc2VraXRhciBuaWxhaSB0ZW5nYWguDQpIYWwgaW5pIG1lbmFuZGFrYW4gYmFod2EgQW5udWFsIFJldHVybiBtZW1pbGlraSBzZWJhcmFuIHlhbmcgbm9ybWFsIGRhbiBzdGFiaWwsIHRhbnBhIGFkYW55YSBvdXRsaWVyIHlhbmcgc2lnbmlmaWthbi4NCg0KIyBNZWFzdXJlcyBvZiBEaXNwZXJzaW9uDQpCYWdpYW4gaW5pIGJlcnR1anVhbiB1bnR1ayBtZW5ndWt1ciBzZWJhcmFuIChkaXNwZXJzaSkgZGFyaSBkYXRhIG51bWVyaWsgZGFsYW0gZGF0YXNldC4NClVrdXJhbiBwZW55ZWJhcmFuIG1lbWJhbnR1IGtpdGEgbWVtYWhhbWkgc2ViZXJhcGEgamF1aCBkYXRhIG1lbnllYmFyIGRhcmkgbmlsYWkgcmF0YS1yYXRhbnlhLg0KRHVhIHZhcmlhYmVsIHlhbmcgZGlndW5ha2FuOg0KDQotIEFnZSAoVXNpYSBJbnZlc3RvcikNCg0KLSBBbm51YWxSZXR1cm4gKFBlcnNlbnRhc2UgS2V1bnR1bmdhbiBUYWh1bmFuKQ0KDQpVa3VyYW4tdWt1cmFuIHBlbnllYmFyYW4gbWVsaXB1dGk6DQoNCg0KKiotIFJhbmdlIChKYW5na2F1YW4pKiogIA0KJCQNClx0ZXh0YmZ7UmFuZ2V9ID0gWF97bWF4fSAtIFhfe21pbn0NCiQkDQojIE1lbmdoaXR1bmcgcmFuZ2UNCg0KYGBge3J9DQpyYW5nZV9hZ2UgPC0gbWF4KGRhdGFfaW52ZXN0bWVudDUkQWdlLCBuYS5ybSA9IFRSVUUpIC0gbWluKGRhdGFfaW52ZXN0bWVudDUkQWdlLCBuYS5ybSA9IFRSVUUpDQpyYW5nZV9yZXR1cm4gPC0gbWF4KGRhdGFfaW52ZXN0bWVudDUkQW5udWFsUmV0dXJuLCBuYS5ybSA9IFRSVUUpIC0gbWluKGRhdGFfaW52ZXN0bWVudDUkQW5udWFsUmV0dXJuLCBuYS5ybSA9IFRSVUUpDQoNCmRhdGEuZnJhbWUoDQogIFZhcmlhYmxlID0gYygiQWdlIiwgIkFubnVhbCBSZXR1cm4iKSwNCiAgUmFuZ2UgPSBjKHJhbmdlX2FnZSwgcmFuZ2VfcmV0dXJuKQ0KKQ0KYGBgDQoNClJhbmdlIG1lbnVuanVra2FuICoqcGVyYmVkYWFuIGFudGFyYSBuaWxhaSB0ZXJiZXNhciBkYW4gbmlsYWkgdGVya2VjaWwqKiBkYWxhbSBkYXRhLiAgDQpTZW1ha2luIGJlc2FyIG5pbGFpIHJhbmdlLCBzZW1ha2luIGxlYmFyIHB1bGEgc2ViYXJhbiBkYXRhLiAgDQpOYW11biwgdWt1cmFuIGluaSAqKnNlbnNpdGlmIHRlcmhhZGFwIG91dGxpZXIqKiwgc2VoaW5nZ2EgdGlkYWsgc2VsYWx1IG1lbmNlcm1pbmthbiBkaXN0cmlidXNpIHNlYmVuYXJueWEuIFNlZGFuZ2thbiBwYWRhIHBlcmhpdHVuZ2FuIHJhZ2UgZGkgYXRhcyBtZW51bmp1a2FuIFJhbmdlIGphcmFrIGFudGFyYSBuaWxhaSB0ZXJ0aW5nZ2kgZGFuIHRlcmVuZGFoIGRhbGFtIGRhdGEuIE5pbGFpIHlhbmcgYmVzYXIgbWVuYW5kYWthbiBhZGFueWEgdmFyaWFzaSBla3N0cmVtLCBzZWRhbmdrYW4gbmlsYWkga2VjaWwgYmVyYXJ0aSBkYXRhIHJlbGF0aWYgaG9tb2dlbi4NCg0KKipCZXJkYXNhcmthbiBoYXNpbCBwZXJoaXR1bmdhbiByYW5nZSoqDQptZW51bmp1a2thbiBzZWxpc2loIGFudGFyYSBuaWxhaSBtYWtzaW11bSBkYW4gbWluaW11bSBwYWRhIHN1YXR1IHZhcmlhYmVsLg0KDQotICoqVW50dWsgQWdlKiosIHJhbmdlIHlhbmcgcmVsYXRpZiBrZWNpbCBtZW5naW5kaWthc2lrYW4gYmFod2EgcmVudGFuZyB1c2lhIHJlc3BvbmRlbiB0aWRhayB0ZXJsYWx1IGxlYmFyLCBhcnRpbnlhIG1heW9yaXRhcyBpbnZlc3RvciBtZW1pbGlraSB1c2lhIHlhbmcgYmVyZGVrYXRhbi4NCg0KLSAqKlVudHVrIEFubnVhbCBSZXR1cm4qKiwgcmFuZ2UgeWFuZyBqYXVoIGxlYmloIGJlc2FyIG1lbnVuanVra2FuIGFkYW55YSBwZXJiZWRhYW4gc2lnbmlmaWthbiBhbnRhcmEgdGluZ2thdCBwZW5nZW1iYWxpYW4gaW52ZXN0YXNpIHRlcnRpbmdnaSBkYW4gdGVyZW5kYWggZGkgYW50YXJhIHJlc3BvbmRlbi4NCg0KDQoqKi0gVmFyaWFuY2UgKFJhZ2FtKSoqICANCiQkDQpcdGV4dGJme3N9XjIgPSBcZnJhY3tcc3VtX3tpPTF9XntufShYX2kgLSBcYmFye1h9KV4yfXtuIC0gMX0NCiQkDQoNCmBgYHtyfQ0KIyBNZW5naGl0dW5nIHZhcmlhbnMNCg0KdmFyX2FnZSA8LSB2YXIoZGF0YV9pbnZlc3RtZW50NSRBZ2UsIG5hLnJtID0gVFJVRSkNCnZhcl9yZXR1cm4gPC0gdmFyKGRhdGFfaW52ZXN0bWVudDUkQW5udWFsUmV0dXJuLCBuYS5ybSA9IFRSVUUpDQoNCmRhdGEuZnJhbWUoDQpWYXJpYWJsZSA9IGMoIkFnZSIsICJBbm51YWwgUmV0dXJuIiksDQpWYXJpYW5jZSA9IGModmFyX2FnZSwgdmFyX3JldHVybikNCikNCg0KYGBgDQoNClZhcmlhbmNlIG1lbmd1a3VyICoqcmF0YS1yYXRhIGt1YWRyYXQgZGV2aWFzaSoqIHNldGlhcCBuaWxhaSB0ZXJoYWRhcCBtZWFuLiAgDQpOaWxhaSB2YXJpYW5zaSBiZXNhciBiZXJhcnRpIGRhdGEgbWVtaWxpa2kgKiprZXJhZ2FtYW4gdGluZ2dpKiosIHNlZGFuZ2thbiBuaWxhaSBrZWNpbCBtZW51bmp1a2thbiBiYWh3YSBkYXRhICoqYmVya3VtcHVsIGRpIHNla2l0YXIgbWVhbioqLiAgDQpTYXR1YW4gdmFyaWFuc2kgYWRhbGFoICoqa3VhZHJhdCBkYXJpIHNhdHVhbiBkYXRhIGFzbGlueWEqKi4NCg0KKipCZXJkYXNhcmthbiBoYXNpbCBwZXJoaXR1bmdhbiB2YXJpYW5zKio6DQoNCi0gKipWYXJpYWJlbCBBZ2UqKiBtZW1pbGlraSBuaWxhaSB2YXJpYW5zIHlhbmcgcmVsYXRpZiBrZWNpbCwgYXJ0aW55YSBzZWJhcmFuIHVtdXIgcmVzcG9uZGVuIGN1a3VwIHNlcmFnYW0uIE1heW9yaXRhcyByZXNwb25kZW4gYmVyYWRhIGRhbGFtIHJlbnRhbmcgdXNpYSB5YW5nIHRpZGFrIHRlcmxhbHUgamF1aC4NCg0KLSAqKlZhcmlhYmVsIEFubnVhbCBSZXR1cm4qKiBtZW1pbGlraSBuaWxhaSB2YXJpYW5zIHlhbmcgamF1aCBsZWJpaCBiZXNhciwgbWVuYW5kYWthbiBiYWh3YSB0aW5na2F0IHBlbmdlbWJhbGlhbiBpbnZlc3Rhc2kgYW50YXIgcmVzcG9uZGVuIGJlcnZhcmlhc2kgY3VrdXAgdGluZ2dpLiBCZWJlcmFwYSBpbnZlc3RvciBtdW5na2luIG1lbXBlcm9sZWggaGFzaWwgeWFuZyBqYXVoIGxlYmloIHRpbmdnaSBhdGF1IHJlbmRhaCBkaWJhbmRpbmcgcmF0YS1yYXRhLg0KDQpEZW5nYW4ga2F0YSBsYWluLCBzZW1ha2luIGJlc2FyIG5pbGFpIHZhcmlhbnMsIHNlbWFraW4gdGluZ2dpIHRpbmdrYXQga2V0aWRha2tvbnNpc3RlbmFuIGRhdGEuIERhbGFtIGtvbnRla3MgaW5pLCBBbm51YWwgUmV0dXJuIG1lbWlsaWtpIHRpbmdrYXQgZmx1a3R1YXNpIHlhbmcgbGViaWggYmVzYXIgZGliYW5kaW5nIEFnZS4NCg0KKiotIFN0YW5kYXJkIERldmlhdGlvbiAoU2ltcGFuZ2FuIEJha3UpKiogIA0KJCQNClx0ZXh0YmZ7c30gPSBcc3FydHtzXjJ9ID0gXHNxcnR7XGZyYWN7XHN1bV97aT0xfV57bn0oWF9pIC0gXGJhcntYfSleMn17biAtIDF9fQ0KJCQNCg0KYGBge3J9DQojIE1lbmdoaXR1bmcgc3RhbmRhciBkZXZpYXNpDQoNCnNkX2FnZSA8LSBzZChkYXRhX2ludmVzdG1lbnQ1JEFnZSwgbmEucm0gPSBUUlVFKQ0Kc2RfcmV0dXJuIDwtIHNkKGRhdGFfaW52ZXN0bWVudDUkQW5udWFsUmV0dXJuLCBuYS5ybSA9IFRSVUUpDQoNCmRhdGEuZnJhbWUoDQpWYXJpYWJsZSA9IGMoIkFnZSIsICJBbm51YWwgUmV0dXJuIiksDQpTdGFuZGFyZF9EZXZpYXRpb24gPSBjKHNkX2FnZSwgc2RfcmV0dXJuKQ0KKQ0KYGBgDQoNCg0KU3RhbmRhcmQgZGV2aWF0aW9uIG1lcnVwYWthbiAqKmFrYXIgZGFyaSB2YXJpYW5zaSoqLCBzZWhpbmdnYSBrZW1iYWxpIHBhZGEgc2F0dWFuIGRhdGEgYXNsaW55YS4gIA0KTmlsYWkgc2ltcGFuZ2FuIGJha3UgbWVudW5qdWtrYW4gc2ViZXJhcGEgamF1aCBkYXRhIHRlcnNlYmFyIGRhcmkgbmlsYWkgcmF0YS1yYXRhLiAgDQpKaWthIHN0YW5kYXIgZGV2aWFzaSBrZWNpbCwgbWFrYSBkYXRhICoqbGViaWggaG9tb2dlbioqOyBqaWthIGJlc2FyLCBtYWthIGRhdGEgKipsZWJpaCBiZXJ2YXJpYXNpKiouDQoNCioqQmVyZGFzYXJrYW4gaGFzaWwgcGVyaGl0dW5nYW4gU3RhbmRhciBEZXZpYXRpb24qKg0KDQotIE5pbGFpIHN0YW5kYXIgZGV2aWFzaSBBZ2Uga2VjaWwg4oaSIG1lbnVuanVra2FuIGJhaHdhIHNlYmFnaWFuIGJlc2FyIG5pbGFpIHVtdXIgbWVuZGVrYXRpIHJhdGEtcmF0YS4NCg0KLSBOaWxhaSBzdGFuZGFyIGRldmlhc2kgQW5udWFsIFJldHVybiBiZXNhciDihpIgbWVuZ2dhbWJhcmthbiBiYWh3YSB0aW5na2F0IHBlbmdlbWJhbGlhbiBtZW1pbGlraSBwZW55aW1wYW5nYW4geWFuZyBiZXNhciBkYXJpIHJhdGEtcmF0YW55YS4NCg0KKiotIEludGVycXVhcnRpbGUgUmFuZ2UgKElRUikqKiAgDQokJA0KXHRleHRiZntJUVJ9ID0gUV8zIC0gUV8xDQokJA0KDQpgYGB7cn0NCiMgTWVuZ2hpdHVuZyBJUVINCg0KaXFyX2FnZSA8LSBJUVIoZGF0YV9pbnZlc3RtZW50NSRBZ2UsIG5hLnJtID0gVFJVRSkNCmlxcl9yZXR1cm4gPC0gSVFSKGRhdGFfaW52ZXN0bWVudDUkQW5udWFsUmV0dXJuLCBuYS5ybSA9IFRSVUUpDQoNCmRhdGEuZnJhbWUoDQpWYXJpYWJsZSA9IGMoIkFnZSIsICJBbm51YWwgUmV0dXJuIiksDQpJUVIgPSBjKGlxcl9hZ2UsIGlxcl9yZXR1cm4pDQopDQpgYGANCg0KDQpJUVIgbWVuZ3VrdXIgKipyZW50YW5nIGRhdGEgdGVuZ2FoICg1MCUpKiogZGVuZ2FuIG1lbmdhYmFpa2FuIHBlbmdhcnVoIG91dGxpZXIuICANCklRUiBiZXJndW5hIHVudHVrIG1lbGloYXQgKipwZW55ZWJhcmFuIGRhdGEgdXRhbWEqKiB0YW5wYSBkaXBlbmdhcnVoaSBuaWxhaSBla3N0cmVtLg0KDQoqKkJlcmRhc2Fya2FuIGhhc2lsIHBlcmhpdHVuZ2FuIElRUioqDQoNCi0gSVFSIEFnZSBrZWNpbCDihpIgZGF0YSB1c2lhIGxlYmloIGtvbnNpc3RlbiBkaSB0ZW5nYWggZGlzdHJpYnVzaS4NCg0KLSBJUVIgQW5udWFsIFJldHVybiBiZXNhciDihpIgbWVuYW5kYWthbiBiYWh3YSBuaWxhaSBwZW5nZW1iYWxpYW4gbWVtaWxpa2kgdmFyaWFzaSB0aW5nZ2kgbWVza2lwdW4gZGkgYmFnaWFuIHRlbmdhaCBkYXRhLg0KDQojIyBWaXN1YWxpc2FzaSBNZWFzdXJlcyBvZiBEaXNwZXJzaW9uDQoNCiMjIyBCb3ggcGxvdA0KYGBge3IgYm94cGxvdC1kaXNwZXJzaW9uLTJ2YXIsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NH0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KHJlYWRyKQ0KDQojIEJhY2EgZGF0YQ0KZGF0YV9pbnZlc3RtZW50IDwtIHJlYWRfY3N2KCJDOi9Vc2Vycy9BZGluZGEvRG93bmxvYWRzL01pZHRlcm0gRXhhbTMuY3N2IikNCg0KIyBQaWxpaCAyIHZhcmlhYmVsIG51bWVyaWsgeWFuZyBjb2Nvaw0KZGF0YV9sb25nIDwtIGRhdGFfaW52ZXN0bWVudCAlPiUNCiAgc2VsZWN0KEluaXRpYWxJbnZlc3RtZW50LCBBbm51YWxSZXR1cm4pICU+JQ0KICBwaXZvdF9sb25nZXIoY29scyA9IGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG8gPSAiVmFyaWFibGUiLCB2YWx1ZXNfdG8gPSAiVmFsdWUiKQ0KDQojIEJ1YXQgYm94cGxvdCBpbnRlcmFrdGlmIGRlbmdhbiB3YXJuYSBzb2Z0IGJpcnUNCnAgPC0gZ2dwbG90KGRhdGFfbG9uZywgYWVzKHggPSBWYXJpYWJsZSwgeSA9IFZhbHVlLCBmaWxsID0gVmFyaWFibGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUoIlZhcmlhYmVsOiIsIFZhcmlhYmxlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+TmlsYWk6Iiwgcm91bmQoVmFsdWUsIDIpKSkpICsNCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gIiNGRjZGNjEiLCBvdXRsaWVyLnNoYXBlID0gMTYsIG91dGxpZXIuc2l6ZSA9IDIsDQogICAgICAgICAgICAgICBjb2xvciA9ICJncmF5NDAiLCBhbHBoYSA9IDAuODUsIHdpZHRoID0gMC41KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNBRUQ2RjEiLCAiIzVEQURFMiIpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUGVyYmFuZGluZ2FuIFBlbnllYmFyYW4gTmlsYWkgSW52ZXN0YXNpIGRhbiBLZXVudHVuZ2FuIFRhaHVuYW4iLA0KICAgIHN1YnRpdGxlID0gIlZpc3VhbGlzYXNpIE1lYXN1cmVzIG9mIERpc3BlcnNpb246IEluaXRpYWwgSW52ZXN0bWVudCB2cyBBbm51YWwgUmV0dXJuIiwNCiAgICB4ID0gIlZhcmlhYmVsIiwNCiAgICB5ID0gIk5pbGFpIChkYWxhbSBzYXR1YW4gbW9uZXRlcikiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEzKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNSksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDEyLCBjb2xvciA9ICJncmF5MzAiKSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiDQogICkNCg0KIyBVYmFoIGphZGkgaW50ZXJha3RpZiAoem9vbSBpbi9vdXQgKyB0b29sdGlwKQ0KZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikNCmBgYA0KIyMjIEludGVycHJldGFzaQ0KDQpWaXN1YWxpc2FzaSBib3ggcGxvdCBtZW51bmp1a2thbiBiYWh3YSBJbml0aWFsSW52ZXN0bWVudCBtZW1pbGlraSBwZW55ZWJhcmFuIChkaXNwZXJzaSkgeWFuZyBsZWJpaCBiZXNhciBkaWJhbmRpbmcgQW5udWFsUmV0dXJuLiBIYWwgaW5pIHRlcmxpaGF0IGRhcmkgcmVudGFuZyBkYW4gSVFSIHlhbmcgbGViaWggbGViYXIgc2VydGEgYWRhbnlhIGJlYmVyYXBhIG91dGxpZXIgcGFkYSBuaWxhaSBpbnZlc3Rhc2kgYXdhbCwgbWVuYW5kYWthbiBwZXJiZWRhYW4gbW9kYWwgYW50YXIgaW52ZXN0b3IgY3VrdXAgdGluZ2dpLiBTZW1lbnRhcmEgaXR1LCBBbm51YWxSZXR1cm4gbWVtaWxpa2kgc2ViYXJhbiB5YW5nIGxlYmloIHNlbXBpdCBkYW4gc2VkaWtpdCBvdXRsaWVyLCBtZW51bmp1a2thbiBoYXNpbCB0YWh1bmFuIGFudGFyIGludmVzdG9yIHJlbGF0aWYgc3RhYmlsLiBEZW5nYW4gZGVtaWtpYW4sIGRhcGF0IGRpc2ltcHVsa2FuIGJhaHdhIG1vZGFsIGF3YWwgYmVydmFyaWFzaSB0aW5nZ2ksIHNlZGFuZ2thbiBoYXNpbCB0YWh1bmFuIGxlYmloIGtvbnNpc3Rlbiwgc2VzdWFpIGRlbmdhbiBrb25zZXAgTWVhc3VyZXMgb2YgRGlzcGVyc2lvbiB5YW5nIG1lbmVrYW5rYW4gdmFyaWFzaSBkYW4ga2VzdGFiaWxhbiBkYXRhLg0KDQojIyMgSGlzdG9ncmFtDQoNCmBgYHtyICBoaXN0b2dyYW0tYWdlLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTV9DQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmxpYnJhcnkoZ2dwbG90MikNCg0KaGlzdDEgPC0gZ2dwbG90KGRhdGFfaW52ZXN0bWVudCwgYWVzKHggPSBNb250aGx5U2F2aW5nKSkgKw0KZ2VvbV9oaXN0b2dyYW0oZmlsbCA9ICIjMDBBRkJCIiwgY29sb3IgPSAid2hpdGUiLCBiaW5zID0gMjAsIGFscGhhID0gMC44KSArDQpsYWJzKA0KdGl0bGUgPSAiRGlzdHJpYnVzaSBJbnZlc3RtZW50IEFtb3VudCIsDQp4ID0gIkludmVzdG1lbnQgQW1vdW50IiwNCnkgPSAiRnJla3VlbnNpIg0KKSArDQp0aGVtZV9taW5pbWFsKCkNCg0KaGlzdDIgPC0gZ2dwbG90KGRhdGFfaW52ZXN0bWVudCwgYWVzKHggPSBBbm51YWxSZXR1cm4pKSArDQpnZW9tX2hpc3RvZ3JhbShmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG9yID0gIndoaXRlIiwgYmlucyA9IDIwLCBhbHBoYSA9IDAuOCkgKw0KbGFicygNCnRpdGxlID0gIkRpc3RyaWJ1c2kgQW5udWFsIFJldHVybiIsDQp4ID0gIkFubnVhbCBSZXR1cm4gKCUpIiwNCnkgPSAiRnJla3VlbnNpIg0KKSArDQp0aGVtZV9taW5pbWFsKCkNCg0KZ3JpZC5hcnJhbmdlKGhpc3QxLCBoaXN0MiwgbmNvbCA9IDEpDQpgYGANCg0KIyMjIEludGVycHJldGFzaQ0KVmlzdWFsaXNhc2kgaGlzdG9ncmFtIGRpIGF0YXMgbWVtcGVybGloYXRrYW4gc2ViYXJhbiBkdWEgdmFyaWFiZWwgbnVtZXJpaywgeWFpdHUgTW9udGhseSBTYXZpbmcgZGFuIEFubnVhbCBSZXR1cm4sIHVudHVrIG1lbWFoYW1pIHBvbGEgZGlzdHJpYnVzaSBkYW4gdGluZ2thdCBwZW55ZWJhcmFuIGRhdGFueWEuDQoNCi0gUGFkYSBoaXN0b2dyYW0gTW9udGhseSBTYXZpbmcsIHRlcmxpaGF0IGJhaHdhIHNlYmFnaWFuIGJlc2FyIGludmVzdG9yIG1lbWlsaWtpIGp1bWxhaCB0YWJ1bmdhbiBidWxhbmFuIHBhZGEga2lzYXJhbiBtZW5lbmdhaC4gRGlzdHJpYnVzaSBpbmkgbWVudW5qdWtrYW4gYmFod2EgZGF0YSBjZW5kZXJ1bmcgc2ltZXRyaXMgZGVuZ2FuIHNlZGlraXQgdmFyaWFzaSBkaSBzZWtpdGFyIG5pbGFpIHRlbmdhaCwgeWFuZyBiZXJhcnRpIHRpbmdrYXQga2VtYW1wdWFuIG1lbmFidW5nIGFudGFyIGludmVzdG9yIHJlbGF0aWYgc2VyYWdhbSBkYW4gdGlkYWsgdGVybGFsdSBtZW55aW1wYW5nIGphdWguDQoNCi0gU2VtZW50YXJhIGl0dSwgaGlzdG9ncmFtIEFubnVhbCBSZXR1cm4gbWVudW5qdWtrYW4gYmFod2Egc2ViYWdpYW4gYmVzYXIgaW1iYWwgaGFzaWwgdGFodW5hbiBiZXJrdW1wdWwgZGkgc2VraXRhciBuaWxhaSByYXRhLXJhdGEgZGVuZ2FuIHNlZGlraXQgbmlsYWkgZWtzdHJlbSAob3V0bGllcikgZGkgc2lzaSBrYW5hbi4gSGFsIGluaSBtZW5naW5kaWthc2lrYW4gYWRhbnlhIGJlYmVyYXBhIGludmVzdG9yIGRlbmdhbiB0aW5na2F0IHBlbmdlbWJhbGlhbiB5YW5nIGphdWggbGViaWggdGluZ2dpIGRpYmFuZGluZyBsYWlubnlhLCBtZW5hbmRha2FuIHBlbnllYmFyYW4gZGF0YSB5YW5nIGxlYmloIGJlc2FyIHBhZGEgdmFyaWFiZWwgaW5pIGRpYmFuZGluZyBNb250aGx5IFNhdmluZy4NCg0KU2VjYXJhIGtlc2VsdXJ1aGFuLCBoYXNpbCBpbmkgbWVudW5qdWtrYW4gYmFod2EgQW5udWFsIFJldHVybiBtZW1pbGlraSB2YXJpYXNpIHlhbmcgbGViaWggdGluZ2dpLCBzZWRhbmdrYW4gTW9udGhseSBTYXZpbmcgbGViaWgga29uc2lzdGVuLCB5YW5nIGJlcmFydGkgcmlzaWtvIGRhbiBoYXNpbCBpbnZlc3Rhc2kgYmVyYmVkYSBhbnRhciBpbmRpdmlkdSwgdGV0YXBpIGtlbWFtcHVhbiBtZW5hYnVuZyByZWxhdGlmIHN0YWJpbC4NCg0KIyMjIFNjYXR0ZXIgcGxvdA0KDQpgYGB7ciBzY2F0dGVycGxvdC0yZC10cmVuZCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD00fQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGRwbHlyKQ0KDQojIEd1bmFrYW4gZGF0YXNldCB5YW5nIGJlbmFyDQpkYXRhX2ludmVzdG1lbnQgPC0gZGF0YV9pbnZlc3RtZW50ICU+JQ0KICBtdXRhdGUoDQogICAgUmlza1Njb3JlID0gYXMubnVtZXJpYyhSaXNrU2NvcmUpLA0KICAgIEFubnVhbFJldHVybiA9IGFzLm51bWVyaWMoQW5udWFsUmV0dXJuKQ0KICApDQoNCiMgRml0IG1vZGVsIHJlZ3Jlc2kgbGluZWFyDQptb2RlbCA8LSBsbShBbm51YWxSZXR1cm4gfiBSaXNrU2NvcmUsIGRhdGEgPSBkYXRhX2ludmVzdG1lbnQpDQoNCiMgUHJlZGlrc2kgbmlsYWkgdW50dWsgZ2FyaXMgdHJlbg0KcHJlZCA8LSBkYXRhLmZyYW1lKA0KICBSaXNrU2NvcmUgPSBzZXEobWluKGRhdGFfaW52ZXN0bWVudCRSaXNrU2NvcmUsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICBtYXgoZGF0YV9pbnZlc3RtZW50JFJpc2tTY29yZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgIGxlbmd0aC5vdXQgPSAxMDApDQopDQpwcmVkJEFubnVhbFJldHVybiA8LSBwcmVkaWN0KG1vZGVsLCBuZXdkYXRhID0gcHJlZCkNCg0KIyBTY2F0dGVyIHBsb3QgaW50ZXJha3RpZiArIGdhcmlzIHRyZW4NCmZpZyA8LSBwbG90X2x5KA0KICBkYXRhID0gZGF0YV9pbnZlc3RtZW50LA0KICB4ID0gflJpc2tTY29yZSwNCiAgeSA9IH5Bbm51YWxSZXR1cm4sDQogIHR5cGUgPSAnc2NhdHRlcicsDQogIG1vZGUgPSAnbWFya2VycycsDQogIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnbGlnaHRwaW5rJywgc2l6ZSA9IDgsIG9wYWNpdHkgPSAwLjcpLA0KICBob3ZlcmluZm8gPSAndGV4dCcsDQogIHRleHQgPSB+cGFzdGUoJ1Jpc2sgU2NvcmU6JywgUmlza1Njb3JlLA0KICAgICAgICAgICAgICAgICc8YnI+QW5udWFsIFJldHVybjonLCBBbm51YWxSZXR1cm4pDQopICU+JQ0KICBhZGRfdHJhY2UoDQogICAgZGF0YSA9IHByZWQsDQogICAgeCA9IH5SaXNrU2NvcmUsDQogICAgeSA9IH5Bbm51YWxSZXR1cm4sDQogICAgdHlwZSA9ICdzY2F0dGVyJywNCiAgICBtb2RlID0gJ2xpbmVzJywNCiAgICBsaW5lID0gbGlzdChjb2xvciA9ICdkYXJrcmVkJywgd2lkdGggPSAyKSwNCiAgICBuYW1lID0gJ1RyZW5kIExpbmUnDQogICkgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9IGxpc3QodGV4dCA9ICJIdWJ1bmdhbiBhbnRhcmEgUmlzayBTY29yZSBkYW4gQW5udWFsIFJldHVybiAoZGVuZ2FuIEdhcmlzIFRyZW4pIiwgeCA9IDAuNSksDQogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlJpc2sgU2NvcmUiKSwNCiAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiQW5udWFsIFJldHVybiAoJSkiKSwNCiAgICBwbG90X2JnY29sb3IgPSAiI2Y3ZjlmYiIsDQogICAgcGFwZXJfYmdjb2xvciA9ICIjZjdmOWZiIg0KICApDQoNCmZpZyAgIyB0YW1waWxrYW4gZ3JhZmlrIGludGVyYWt0aWYNCmBgYA0KDQojIyMgSW50ZXJwcmV0YXNpDQpTY2F0dGVyIHBsb3QgbWVudW5qdWtrYW4gaHVidW5nYW4gcG9zaXRpZiBhbnRhcmEgUmlzayBTY29yZSBkYW4gQW5udWFsIFJldHVybi4gUG9sYSBpbmkgbWVuZ2luZGlrYXNpa2FuIGJhaHdhIHNlbWFraW4gdGluZ2dpIHJpc2lrbyB5YW5nIGRpYW1iaWwsIHNlbWFraW4gYmVzYXIgcG90ZW5zaSBpbWJhbCBoYXNpbG55YS4gU2ViYXJhbiB0aXRpayB5YW5nIGN1a3VwIGx1YXMgbWVuYW5kYWthbiBhZGFueWEgdmFyaWFzaSBhdGF1IGRpc3BlcnNpIHRpbmdnaSBwYWRhIGhhc2lsIGludmVzdGFzaS4NCg0KIyBTdW1tYXJ5IGFuZCBJbnRlcnByZXRhdGlvbg0KDQpCZXJkYXNhcmthbiBoYXNpbCBhbmFsaXNpcyBkYXRhIGludmVzdGFzaSwgZGlwZXJvbGVoIGJhaHdhIHZhcmlhYmVsIG51bWVyaWsgeWFuZyBkaWFuYWxpc2lzLCB5YWl0dSBBZ2UgZGFuIEFubnVhbCBSZXR1cm4sIG1lbnVuanVra2FuIGthcmFrdGVyaXN0aWsgcGVueWViYXJhbiB5YW5nIGJlcmJlZGEuIA0KDQotICoqVmFyaWFiZWwgQWdlKiogbWVtaWxpa2kgbmlsYWkgcmF0YS1yYXRhLCBtZWRpYW4sIGRhbiBtb2R1cyB5YW5nIGJlcmRla2F0YW4sIG1lbmFuZGFrYW4gZGlzdHJpYnVzaSB5YW5nIHJlbGF0aWYgc2ltZXRyaXMgdGFucGEgYWRhbnlhIG91dGxpZXIgeWFuZyBzaWduaWZpa2FuLiBIYWwgaW5pIGp1Z2EgZGlkdWt1bmcgb2xlaCBuaWxhaSB2YXJpYW5zLCBzdGFuZGFyIGRldmlhc2ksIGRhbiBJUVIgeWFuZyBrZWNpbCwgc2VoaW5nZ2EgZGFwYXQgZGlzaW1wdWxrYW4gYmFod2EgZGF0YSB1c2lhIGludmVzdG9yIGN1a3VwIGtvbnNpc3RlbiBkYW4gaG9tb2dlbi4NCg0KLSBTZWJhbGlrbnlhLCAqKnZhcmlhYmVsIEFubnVhbCBSZXR1cm4qKiBtZW1pbGlraSBwZXJiZWRhYW4gY3VrdXAgYmVzYXIgYW50YXJhIG5pbGFpIHJhdGEtcmF0YSBkYW4gbWVkaWFuLCB5YW5nIG1lbmdpbmRpa2FzaWthbiBhZGFueWEga2VtZW5jZW5nYW4gKHNrZXduZXNzKSBwYWRhIGRpc3RyaWJ1c2kgZGF0YS4gTmlsYWkgZGlzcGVyc2kgeWFuZyB0aW5nZ2kgbWVudW5qdWtrYW4gYmFod2EgdGluZ2thdCBwZW5nZW1iYWxpYW4gaW52ZXN0YXNpIGFudGFyIGludmVzdG9yIHNhbmdhdCBiZXJ2YXJpYXNpLiBLb25kaXNpIGluaSBkYXBhdCBkaXNlYmFia2FuIG9sZWggcGVyYmVkYWFuIHN0cmF0ZWdpLCB0aW5na2F0IHJpc2lrbywgZGFuIHBlbmdhbGFtYW4gaW52ZXN0YXNpLg0KDQpTZWNhcmEga2VzZWx1cnVoYW4sIGhhc2lsIHZpc3VhbGlzYXNpIGRhbiBhbmFsaXNpcyBzdGF0aXN0aWsgbWVuZ2dhbWJhcmthbiBiYWh3YSBBZ2UgbWVydXBha2FuIHZhcmlhYmVsIHlhbmcgcGFsaW5nIHN0YWJpbCwgc2VkYW5na2FuIEFubnVhbCBSZXR1cm4gbWVudW5qdWtrYW4gdmFyaWFiaWxpdGFzIHBhbGluZyB0aW5nZ2kuIEhhbCBpbmkgbWVtYmVyaWthbiBnYW1iYXJhbiBiYWh3YSBraW5lcmphIGludmVzdGFzaSBsZWJpaCBkaXBlbmdhcnVoaSBvbGVoIGZha3RvciBla3N0ZXJuYWwgZGliYW5kaW5na2FuIGZha3RvciBkZW1vZ3JhZmlzIHNlcGVydGkgdXNpYS4NCg==