KOMPUTASI STATISTIKA

~ Ujian Tengah Semester ~


Kontak : \(\downarrow\)
Email
Instagram https://www.instagram.com/dsciencelabs/
RPubs https://rpubs.com/dsciencelabs/

Data Set

Tugas 1

Lakukan proses persiapan data dengan R dan Python, dengan beberapa langkah berikut:

Import Data

loan_train <- read.csv("loan-train.csv", stringsAsFactors = T, na.strings=c("","","NA"))

Penanganan Data Hilang

Kita cek tipe data dan nilai NA dari data :

summary(loan_train)
##     ï..Loan_ID     Gender    Married    Dependents        Education  
##  LP001002:  1   Female:112   No  :213   0   :345   Graduate    :480  
##  LP001003:  1   Male  :489   Yes :398   1   :102   Not Graduate:134  
##  LP001005:  1   NA's  : 13   NA's:  3   2   :101                     
##  LP001006:  1                           3+  : 51                     
##  LP001008:  1                           NA's: 15                     
##  LP001011:  1                                                        
##  (Other) :608                                                        
##  Self_Employed ApplicantIncome CoapplicantIncome   LoanAmount   
##  No  :500      Min.   :  150   Min.   :    0     Min.   :  9.0  
##  Yes : 82      1st Qu.: 2878   1st Qu.:    0     1st Qu.:100.0  
##  NA's: 32      Median : 3812   Median : 1188     Median :128.0  
##                Mean   : 5403   Mean   : 1621     Mean   :146.4  
##                3rd Qu.: 5795   3rd Qu.: 2297     3rd Qu.:168.0  
##                Max.   :81000   Max.   :41667     Max.   :700.0  
##                                                  NA's   :22     
##  Loan_Amount_Term Credit_History     Property_Area Loan_Status
##  Min.   : 12      Min.   :0.0000   Rural    :179   N:192      
##  1st Qu.:360      1st Qu.:1.0000   Semiurban:233   Y:422      
##  Median :360      Median :1.0000   Urban    :202              
##  Mean   :342      Mean   :0.8422                              
##  3rd Qu.:360      3rd Qu.:1.0000                              
##  Max.   :480      Max.   :1.0000                              
##  NA's   :14       NA's   :50
glimpse(loan_train)
## Rows: 614
## Columns: 13
## $ ï..Loan_ID        <fct> LP001002, LP001003, LP001005, LP001006, LP001008, LP~
## $ Gender            <fct> Male, Male, Male, Male, Male, Male, Male, Male, Male~
## $ Married           <fct> No, Yes, Yes, Yes, No, Yes, Yes, Yes, Yes, Yes, Yes,~
## $ Dependents        <fct> 0, 1, 0, 0, 0, 2, 0, 3+, 2, 1, 2, 2, 2, 0, 2, 0, 1, ~
## $ Education         <fct> Graduate, Graduate, Graduate, Not Graduate, Graduate~
## $ Self_Employed     <fct> No, No, Yes, No, No, Yes, No, No, No, No, No, NA, No~
## $ ApplicantIncome   <int> 5849, 4583, 3000, 2583, 6000, 5417, 2333, 3036, 4006~
## $ CoapplicantIncome <dbl> 0, 1508, 0, 2358, 0, 4196, 1516, 2504, 1526, 10968, ~
## $ LoanAmount        <int> NA, 128, 66, 120, 141, 267, 95, 158, 168, 349, 70, 1~
## $ Loan_Amount_Term  <int> 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 36~
## $ Credit_History    <int> 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, NA, ~
## $ Property_Area     <fct> Urban, Rural, Urban, Urban, Urban, Urban, Urban, Sem~
## $ Loan_Status       <fct> Y, N, Y, Y, Y, Y, Y, N, Y, N, Y, Y, Y, N, Y, Y, Y, N~
anyNA(loan_train)
## [1] TRUE
colSums(is.na(loan_train))
##        ï..Loan_ID            Gender           Married        Dependents 
##                 0                13                 3                15 
##         Education     Self_Employed   ApplicantIncome CoapplicantIncome 
##                 0                32                 0                 0 
##        LoanAmount  Loan_Amount_Term    Credit_History     Property_Area 
##                22                14                50                 0 
##       Loan_Status 
##                 0

Ada dua tipe data yang perlu diubah:

  • Loan_Amount_Term : Ubah sebagai tipe data faktor
  • Credit_History : Ubah sebagai tipe data faktor
names(loan_train)[1] <- "Loan_ID"
loan.train <- loan_train %>% 
  dplyr::select(-Loan_ID) %>% 
  mutate(Loan_Amount_Term = as.factor(Loan_Amount_Term),
         Credit_History = as.factor(Credit_History))

head(loan.train)

Ada juga nilai NA berdasarkan pemeriksaan awal pada:

  • LoanAmount
  • Loan_Amount_Term
  • Credit_History

Fungsi untuk data cleansing :

Mode = function(x){
  a = table(x)
  b = max(a)
  if(all(a == b))
    mod = NA
  else if(is.numeric(x))
    mod = as.numeric(names(a))[a==b]
    else
      mod = names(a)[a==b]
  return(mod)
}

Untuk membuat hasil keseluruhan yang lebih baik, kita akan mencoba mengganti nilai yang hilang/ NA berdasarkan tipenya:

  • Data dengan nilai tipe Numerik yang hilang akan diganti dengan nilai rata-ratanya (menggunakan fungsi mean()).
  • Nilai data dengan tipe data faktor akan diganti dengan nilai yang memiliki jumlah kemunculan tertinggi dalam kumpulan datanya (menggunakan fungsi mode()).
loan.train$Gender[is.na(loan.train$Gender)] <-  Mode(loan.train$Gender)
loan.train$Married[is.na(loan.train$Married)] <- Mode(loan.train$Married)
loan.train$Dependents[is.na(loan.train$Dependents)] <-  Mode(loan.train$Dependents)
loan.train$Credit_History[is.na(loan.train$Credit_History)] <- Mode(loan.train$Credit_History)
loan.train$LoanAmount[is.na(loan.train$LoanAmount)] <- mean(loan.train$LoanAmount, na.rm = T)
loan.train$Loan_Amount_Term[is.na(loan.train$Loan_Amount_Term)] <- mean(loan.train$Loan_Amount_Term, na.rm = T)
summary(loan.train)
##     Gender    Married   Dependents        Education   Self_Employed
##  Female:112   No :213   0 :360     Graduate    :480   No  :500     
##  Male  :502   Yes:401   1 :102     Not Graduate:134   Yes : 82     
##                         2 :101                        NA's: 32     
##                         3+: 51                                     
##                                                                    
##                                                                    
##                                                                    
##  ApplicantIncome CoapplicantIncome   LoanAmount    Loan_Amount_Term
##  Min.   :  150   Min.   :    0     Min.   :  9.0   360    :512     
##  1st Qu.: 2878   1st Qu.:    0     1st Qu.:100.2   180    : 44     
##  Median : 3812   Median : 1188     Median :129.0   480    : 15     
##  Mean   : 5403   Mean   : 1621     Mean   :146.4   300    : 13     
##  3rd Qu.: 5795   3rd Qu.: 2297     3rd Qu.:164.8   84     :  4     
##  Max.   :81000   Max.   :41667     Max.   :700.0   (Other): 12     
##                                                    NA's   : 14     
##  Credit_History   Property_Area Loan_Status
##  0: 89          Rural    :179   N:192      
##  1:525          Semiurban:233   Y:422      
##                 Urban    :202              
##                                            
##                                            
##                                            
## 
na.omit(loan.train)

Periksa Data Duplikat

sum(duplicated(loan.train))
## [1] 0

Tidak ada data duplikat

Pemisahan Data Kategori dan Numerik

Kategori

Cat_data <- loan.train%>% dplyr::select_if(is.factor)
names(Cat_data)
## [1] "Gender"           "Married"          "Dependents"       "Education"       
## [5] "Self_Employed"    "Loan_Amount_Term" "Credit_History"   "Property_Area"   
## [9] "Loan_Status"

Numerik

Num_data <- loan.train%>% dplyr::select_if(is.numeric)
names(Num_data)
## [1] "ApplicantIncome"   "CoapplicantIncome" "LoanAmount"

Penanganan Data Numerik

Penganann Data Pencilan

Penanganan Data Kategorikal

Tugas 2

Lakukan Proses Visualisasi Data dengan menggunakan R dan Python dengan beberapa langkah berikut:

Visualisasi Univariabel

Categorical

Gender

plotdata <- loan.train %>% 
  count(Gender) %>%
  mutate(pct = n / sum(n),
         pctlabel = paste0(round(pct*100), "%"))

ggplot(plotdata, 
       aes(x = reorder(Gender, -pct),
           y = pct)) + 
  geom_bar(stat = "identity", 
          color = "azure4") +
  geom_text(aes(label = pctlabel), 
            vjust = -0.25) +
  theme_minimal() +                                  # use a minimal theme
  scale_y_continuous(labels = percent) +
  labs(x = "Gender", 
       y = "Percent", 
       title  = "Loan by gender")

Married

plotdata <- loan.train %>% 
  count(Married) %>%
  mutate(pct = n / sum(n),
         pctlabel = paste0(round(pct*100), "%"))

ggplot(plotdata, 
       aes(x = reorder(Married, -pct),
           y = pct)) + 
  geom_bar(stat = "identity", 
          color = "azure4") +
  geom_text(aes(label = pctlabel), 
            vjust = -0.25) +
  theme_minimal() +                                  # use a minimal theme
  scale_y_continuous(labels = percent) +
  labs(x = "Married", 
       y = "Percent", 
       title  = "Loan by married")

Dependents

plotdata <- loan.train %>% 
  count(Dependents) %>%
  mutate(pct = n / sum(n),
         pctlabel = paste0(round(pct*100), "%"))

ggplot(plotdata, 
       aes(x = reorder(Dependents, -pct),
           y = pct)) + 
  geom_bar(stat = "identity", 
          color = "azure4") +
  geom_text(aes(label = pctlabel), 
            vjust = -0.25) +
  theme_minimal() +                                  # use a minimal theme
  scale_y_continuous(labels = percent) +
  labs(x = "Dependents", 
       y = "Percent", 
       title  = "Loan by Dependents")

Education

plotdata <- loan.train %>% 
  count(Education) %>%
  mutate(pct = n / sum(n),
         pctlabel = paste0(round(pct*100), "%"))

ggplot(plotdata, 
       aes(x = reorder(Education, -pct),
           y = pct)) + 
  geom_bar(stat = "identity", 
          color = "azure4") +
  geom_text(aes(label = pctlabel), 
            vjust = -0.25) +
  theme_minimal() +                                  # use a minimal theme
  scale_y_continuous(labels = percent) +
  labs(x = "Education", 
       y = "Percent", 
       title  = "Loan by Education")

Self_employed

plotdata <- loan.train %>% 
  count(Self_Employed) %>%
  mutate(pct = n / sum(n),
         pctlabel = paste0(round(pct*100), "%"))

ggplot(plotdata, 
       aes(x = reorder(Self_Employed, -pct),
           y = pct)) + 
  geom_bar(stat = "identity", 
          color = "azure4") +
  geom_text(aes(label = pctlabel), 
            vjust = -0.25) +
  theme_minimal() +                                  # use a minimal theme
  scale_y_continuous(labels = percent) +
  labs(x = "Self_Employed", 
       y = "Percent", 
       title  = "Loan by Self_Employed")

Loan_Amount_Term

plotdata <- loan.train %>% 
  count(Loan_Amount_Term) %>%
  mutate(pct = n / sum(n),
         pctlabel = paste0(round(pct*100), "%"))

ggplot(plotdata, 
       aes(x = reorder(Loan_Amount_Term, -pct),
           y = pct)) + 
  geom_bar(stat = "identity", 
          color = "azure4") +
  geom_text(aes(label = pctlabel), 
            vjust = -0.25) +
  theme_minimal() +                                  
  scale_y_continuous(labels = percent) +
  labs(x = "Loan_Amount_Term", 
       y = "Percent", 
       title  = "Loan by Loan_Amount_Term")

Credit_History

plotdata <- loan.train %>% 
  count(Credit_History) %>%
  mutate(pct = n / sum(n),
         pctlabel = paste0(round(pct*100), "%"))

ggplot(plotdata, 
       aes(x = reorder(Credit_History, -pct),
           y = pct)) + 
  geom_bar(stat = "identity", 
          color = "azure4") +
  geom_text(aes(label = pctlabel), 
            vjust = -0.25) +
  theme_minimal() +                                  
  scale_y_continuous(labels = percent) +
  labs(x = "Credit_History", 
       y = "Percent", 
       title  = "Loan by Credit_History")

Property_Area

plotdata <- loan.train %>% 
  count(Property_Area) %>%
  mutate(pct = n / sum(n),
         pctlabel = paste0(round(pct*100), "%"))

ggplot(plotdata, 
       aes(x = reorder(Property_Area, -pct),
           y = pct)) + 
  geom_bar(stat = "identity", 
          color = "azure4") +
  geom_text(aes(label = pctlabel), 
            vjust = -0.25) +
  theme_minimal() +                                  
  scale_y_continuous(labels = percent) +
  labs(x = "Property_Area", 
       y = "Percent", 
       title  = "Loan by Property_Area")

Numerical

ApplicantIncome

ggplot(loan.train, aes(x = ApplicantIncome)) +
  geom_histogram(fill = "cornflowerblue", 
                 color = "white",bins = 20) + 
  theme_minimal() +                                  # use a minimal theme
  labs(title="Loan by ApplicantIncome",
       x = "ApplicantIncome")

CoapplicantIncome

ggplot(loan.train, aes(x = CoapplicantIncome)) +
  geom_histogram(fill = "cornflowerblue", 
                 color = "white",bins = 20) + 
  theme_minimal() +                                  # use a minimal theme
  labs(title="Loan by CoapplicantIncome",
       x = "CoapplicantIncome")

LoanAmount

ggplot(loan.train, aes(x = LoanAmount)) +
  geom_histogram(fill = "cornflowerblue", 
                 color = "white",bins = 20) + 
  theme_minimal() +                                  # use a minimal theme
  labs(title="Loan by LoanAmount",
       x = "LoanAmount")

Visualisasi Bivariabel

Categorical vs Categorical

Gender vs Married

ggplot(loan.train, 
       aes(x = Gender, 
           fill = Married)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Gender vs Education

ggplot(loan.train, 
       aes(x = Gender, 
           fill = Education)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Gender vs Dependents

ggplot(loan.train, 
       aes(x = Gender, 
           fill = Dependents)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Gender vs Self_Employed

ggplot(loan.train, 
       aes(x = Gender, 
           fill = Self_Employed)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Gender vs loanAmountTerm

ggplot(loan.train, 
       aes(x = Gender, 
           fill = Loan_Amount_Term)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Gender vs credit_history

ggplot(loan.train, 
       aes(x = Gender, 
           fill = Credit_History)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Gender vs PropertyArea

ggplot(loan.train, 
       aes(x = Gender, 
           fill = Property_Area)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Gender vs LoanStatus

ggplot(loan.train, 
       aes(x = Gender, 
           fill = Loan_Status )) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Married vs Dependents

ggplot(loan.train, 
       aes(x = Married, 
           fill = Education)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Married vs Education

ggplot(loan.train, 
       aes(x = Married, 
           fill = Dependents)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Married vs Self_Employed

ggplot(loan.train, 
       aes(x = Married, 
           fill = Self_Employed)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Married vs loanAmountTerm

ggplot(loan.train, 
       aes(x = Married, 
           fill = Loan_Amount_Term)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Married vs credit_history

ggplot(loan.train, 
       aes(x = Married, 
           fill = Credit_History)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Married vs PropertyArea

ggplot(loan.train, 
       aes(x = Married, 
           fill = Property_Area)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Married vs LoanStatus

ggplot(loan.train, 
       aes(x = Married, 
           fill = Loan_Status )) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Dependents vs Education

ggplot(loan.train, 
       aes(x = Dependents, 
           fill = Education)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Dependents vs Self_Employed

ggplot(loan.train, 
       aes(x = Dependents, 
           fill = Self_Employed)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Dependents vs loanAmountTerm

ggplot(loan.train, 
       aes(x = Dependents, 
           fill = Loan_Amount_Term)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Dependents vs credit_history

ggplot(loan.train, 
       aes(x = Dependents, 
           fill = Credit_History)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Dependents vs PropertyArea

ggplot(loan.train, 
       aes(x = Dependents, 
           fill = Property_Area)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Dependents vs LoanStatus

ggplot(loan.train, 
       aes(x = Dependents, 
           fill = Loan_Status )) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Education vs Self_Employed

ggplot(loan.train, 
       aes(x = Education, 
           fill = Self_Employed)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Education vs loanAmountTerm

ggplot(loan.train, 
       aes(x = Education, 
           fill = Loan_Amount_Term)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Education vs credit_history

ggplot(loan.train, 
       aes(x = Education, 
           fill = Credit_History)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Education vs PropertyArea

ggplot(loan.train, 
       aes(x = Education, 
           fill = Property_Area)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Education vs LoanStatus

ggplot(loan.train, 
       aes(x = Education, 
           fill = Loan_Status )) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Self_Employed vs loanAmountTerm

ggplot(loan.train, 
       aes(x = Self_Employed, 
           fill = Loan_Amount_Term)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Self_Employed vs credit_history

ggplot(loan.train, 
       aes(x = Self_Employed, 
           fill = Credit_History)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Self_Employed vs PropertyArea

ggplot(loan.train, 
       aes(x = Self_Employed, 
           fill = Property_Area)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Self_Employed vs LoanStatus

ggplot(loan.train, 
       aes(x = Self_Employed, 
           fill = Loan_Status )) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Loan_Amount_Term vs credit_history

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           fill = Credit_History)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Loan_Amount_Term vs PropertyArea

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           fill = Property_Area)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Loan_Amount_Term vs LoanStatus

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           fill = Loan_Status )) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Credit_History vs PropertyArea

ggplot(loan.train, 
       aes(x = Credit_History, 
           fill = Property_Area)) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Credit_History vs LoanStatus

ggplot(loan.train, 
       aes(x = Credit_History, 
           fill = Loan_Status )) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Property_Area vs LoanStatus

ggplot(loan.train, 
       aes(x = Property_Area, 
           fill = Loan_Status )) + 
  geom_bar(position = "fill") +
  theme_minimal() +                                  
  labs(y = "Proportion")

Numerical vs Numerical

ApplicantIncome vs CoapplicantIncome

ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           y = CoapplicantIncome)) +
  geom_point(color="cornflowerblue", 
             size = 1.5, 
             alpha=.8) +
  scale_y_continuous(label = scales::dollar, 
                     limits = c(0, 50000)) +
  scale_x_continuous(breaks = seq(0, 40000, 5000), 
                     limits=c(0, 50000)) +
  theme_minimal() +                                  # use a minimal theme
  labs(x = "ApplicantIncome",
       y = "",
       title = "ApplicantIncome vs CoapplicantIncome")

CoapplicantIncome vs LoanAmount

ggplot(loan.train, 
       aes(x = CoapplicantIncome, 
           y = LoanAmount)) +
  geom_point(color="cornflowerblue", 
             size = 1.5, 
             alpha=.8) +
  scale_y_continuous(label = scales::dollar, 
                     limits = c(0, 800)) +
  scale_x_continuous(breaks = seq(0, 40000, 5000), 
                     limits=c(0, 50000)) +
  theme_minimal() +                                  # use a minimal theme
  labs(x = "CoapplicantIncome",
       y = "",
       title = "CoapplicantIncome vs LoanAmount")

ApplicantIncome vs LoanAmount

ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           y = LoanAmount)) +
  geom_point(color="cornflowerblue", 
             size = 1, 
             alpha=.8) +
  scale_y_continuous(label = scales::dollar, 
                     limits = c(0, 800)) +
  scale_x_continuous(breaks = seq(0, 40000, 5000), 
                     limits=c(0, 50000)) +
  theme_minimal() +                                  # use a minimal theme
  labs(x = "ApplicantIncome",
       y = "",
       title = "ApplicantIncome vs LoanAmount")

Categorical vs Numerical

ApplicantIncome vs Gender

ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           fill = Gender)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "Applicant Income by Gender")

ApplicantIncome vs Married

ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           fill = Married)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "Applicant Income by Married")

ApplicantIncome vs Dependents

ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           fill = Dependents)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "Applicant Income by Dependents")

ApplicantIncome vs Education

ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           fill = Education)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "Applicant Income by Education")

ApplicantIncome vs Self_Employed

ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           fill = Self_Employed)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "Applicant Income by Self_Employed")

ApplicantIncome vs Loan_Amount_Term

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           y = Loan_Amount_Term, 
           fill = Loan_Amount_Term)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

ApplicantIncome vs Credit_History

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           y = Credit_History, 
           fill = Credit_History)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

ApplicantIncome vs Property_Area

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           y = Property_Area, 
           fill = Property_Area)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

ApplicantIncome vs Loan_Status

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           y = Loan_Status, 
           fill = Loan_Status)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

CoapplicantIncome vs Gender

ggplot(loan.train, 
       aes(x = CoapplicantIncome, 
           fill = Gender)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Gender")

CoapplicantIncome vs Married

ggplot(loan.train, 
       aes(x = CoapplicantIncome, 
           fill = Married)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Married")

CoapplicantIncome vs Dependents

ggplot(loan.train, 
       aes(x = CoapplicantIncome, 
           fill = Dependents)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Dependents")

CoapplicantIncome vs Education

ggplot(loan.train, 
       aes(x = CoapplicantIncome, 
           fill = Education)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Education")

CoapplicantIncome vs Self_Employed

ggplot(loan.train, 
       aes(x = ApplicantIncome, 
           fill = Self_Employed)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Self_Employed")

CoapplicantIncome vs Loan_Amount_Term

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = CoapplicantIncome, 
           y = Loan_Amount_Term, 
           fill = Loan_Amount_Term)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

CoapplicantIncome vs Credit_History

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = CoapplicantIncome, 
           y = Credit_History, 
           fill = Credit_History)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

CoapplicantIncome vs Property_Area

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = CoapplicantIncome, 
           y = Property_Area, 
           fill = Property_Area)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

CoapplicantIncome vs Loan_Status

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = CoapplicantIncome, 
           y = Loan_Status, 
           fill = Loan_Status)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

LoanAmount vs Gender

ggplot(loan.train, 
       aes(x = LoanAmount, 
           fill = Gender)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "LoanAmount by Gender")

LoanAmount vs Married

ggplot(loan.train, 
       aes(x = LoanAmount, 
           fill = Married)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "LoanAmount by Married")

LoanAmount vs Dependents

ggplot(loan.train, 
       aes(x = LoanAmount, 
           fill = Dependents)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "LoanAmount by Dependents")

LoanAmount vs Education

ggplot(loan.train, 
       aes(x = LoanAmount, 
           fill = Education)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "LoanAmount by Education")

LoanAmount vs Self_Employed

ggplot(loan.train, 
       aes(x = LoanAmount, 
           fill = Self_Employed)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(title = "LoanAmount by Self_Employed")

LoanAmount vs Loan_Amount_Term

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = LoanAmount, 
           y = Loan_Amount_Term, 
           fill = Loan_Amount_Term)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

LoanAmount vs Credit_History

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = CoapplicantIncome, 
           y = Credit_History, 
           fill = Credit_History)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

LoanAmount vs Property_Area

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = LoanAmount, 
           y = Property_Area, 
           fill = Property_Area)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

LoanAmount vs Loan_Status

library(ggridges)                                    # to handle overlapping visulization
ggplot(loan.train, 
       aes(x = LoanAmount, 
           y = Loan_Status, 
           fill = Loan_Status)) +
  geom_density_ridges(alpha = 0.7) + 
  theme_ridges() +
  theme(legend.position = "none")

  • Visualisasi Multivariabel

Visualisasi Multivariabel

ApplicantIncome by Married, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = ApplicantIncome, 
           color = Married, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "ApplicantIncome by Married, Gender, and Loan Term")

ApplicantIncome by Education, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = ApplicantIncome, 
           color = Education, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "ApplicantIncome by Married, Gender, and Loan Term")

ApplicantIncome by Dependents, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = ApplicantIncome, 
           color = Dependents, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "ApplicantIncome by Dependents, Gender, and Loan Term")

ApplicantIncome by Self_Employed, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = ApplicantIncome, 
           color = Self_Employed, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "ApplicantIncome by Self_Employed, Gender, and Loan Term")

ApplicantIncome by Credit_History, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = ApplicantIncome, 
           color = Credit_History, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "ApplicantIncome by Credit_History, Gender, and Loan Term")

ApplicantIncome by Property_Area, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = ApplicantIncome, 
           color = Property_Area, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "ApplicantIncome by Property_Area, Gender, and Loan Term")

ApplicantIncome by Loan_Status, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = ApplicantIncome, 
           color = Loan_Status, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "ApplicantIncome by Loan_Status, Gender, and Loan Term")

CoapplicantIncome by Married, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = CoapplicantIncome, 
           color = Married, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Married, Gender, and Loan Term")

CoapplicantIncome by Education, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = CoapplicantIncome, 
           color = Education, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Married, Gender, and Loan Term")

CoapplicantIncome by Dependents, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = CoapplicantIncome, 
           color = Dependents, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Dependents, Gender, and Loan Term")

CoapplicantIncome by Self_Employed, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = CoapplicantIncome, 
           color = Self_Employed, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Self_Employed, Gender, and Loan Term")

CoapplicantIncome by Credit_History, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = CoapplicantIncome, 
           color = Credit_History, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Credit_History, Gender, and Loan Term")

CoapplicantIncome by Property_Area, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = CoapplicantIncome, 
           color = Property_Area, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Property_Area, Gender, and Loan Term")

CoapplicantIncome by Loan_Status, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = CoapplicantIncome, 
           color = Loan_Status, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "CoapplicantIncome by Loan_Status, Gender, and Loan Term")

LoanAmount by Married, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = LoanAmount, 
           color = Married, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "LoanAmount by Married, Gender, and Loan Term")

LoanAmount by Education, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = LoanAmount, 
           color = Education, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "LoanAmount by Married, Gender, and Loan Term")

LoanAmount by Dependents, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = LoanAmount, 
           color = Dependents, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "LoanAmount by Dependents, Gender, and Loan Term")

LoanAmount by Self_Employed, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = LoanAmount, 
           color = Self_Employed, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "LoanAmount by Self_Employed, Gender, and Loan Term")

LoanAmount by Credit_History, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = LoanAmount, 
           color = Credit_History, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "LoanAmount by Credit_History, Gender, and Loan Term")

LoanAmount by Property_Area, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = LoanAmount, 
           color = Property_Area, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "LoanAmount by Property_Area, Gender, and Loan Term")

LoanAmount by Loan_Status, Gender, and Loan Term

ggplot(loan.train, 
       aes(x = Loan_Amount_Term, 
           y = LoanAmount, 
           color = Loan_Status, 
           shape = Gender)) +
  geom_point(size = 3, alpha = .6) +
  theme_minimal() +
  labs(title = "LoanAmount by Loan_Status, Gender, and Loan Term")

Tugas 3

Lakukan proses analisa data secara deskriptif menggunakan R dan Python dengan beberapa langkah berikut:

Kualitatif

Kategori Univariat

Loan_ID LP001002, LP001003, LP001005, LP001006, LP001008, LP001011,~ $ Gender Male, Male, Male, Male, Male, Male, Male, Male, Male, Male,~ $ Married No, Yes, Yes, Yes, No, Yes, Yes, Yes, Yes, Yes, Yes, Yes, Y~ $ Dependents 0, 1, 0, 0, 0, 2, 0, 3+, 2, 1, 2, 2, 2, 0, 2, 0, 1, 0, 0, 0~ $ Education Graduate, Graduate, Graduate, Not Graduate, Graduate, Gradu~ $ Self_Employed No, No, Yes, No, No, Yes, No, No, No, No, No, NA, No, No, N~ $ ApplicantIncome 5849, 4583, 3000, 2583, 6000, 5417, 2333, 3036, 4006, 12841~ $ CoapplicantIncome 0, 1508, 0, 2358, 0, 4196, 1516, 2504, 1526, 10968, 700, 18~ $ LoanAmount NA, 128, 66, 120, 141, 267, 95, 158, 168, 349, 70, 109, 200~ $ Loan_Amount_Term 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,~ $ Credit_History 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, NA, 0, 1, 1~ $ Property_Area Urban, Rural, Urban, Urban, Urban, Urban, Urban, Semiurban,~ $ Loan_Status Y, N, Y, Y, Y, Y, Y, N, Y, N, Y, Y, Y, N, Y, Y, Y, N, N, Y,~

Cat1 <- table(loan.train$Gender)
Cat1
## 
## Female   Male 
##    112    502
Cat2 <- table(loan.train$Married)
Cat2
## 
##  No Yes 
## 213 401
Cat3 <- table(loan.train$Dependents)
Cat3
## 
##   0   1   2  3+ 
## 360 102 101  51
Cat4 <- table(loan.train$Education)
Cat4
## 
##     Graduate Not Graduate 
##          480          134
Cat5 <- table(loan.train$Self_Employed)
Cat5
## 
##  No Yes 
## 500  82
Cat6 <- table(loan.train$Loan_Amount_Term)
Cat6
## 
##  12  36  60  84 120 180 240 300 360 480 
##   1   2   2   4   3  44   4  13 512  15
Cat7 <- table(loan.train$Credit_History)
Cat7
## 
##   0   1 
##  89 525
Cat8 <- table(loan.train$Property_Area)
Cat8
## 
##     Rural Semiurban     Urban 
##       179       233       202
Cat9 <- table(loan.train$Loan_Status)
Cat9
## 
##   N   Y 
## 192 422

Kategori Bivariat

bicat1<- loan.train %>%dplyr::select(Gender, Married) %>%table()
bicat1
##         Married
## Gender    No Yes
##   Female  80  32
##   Male   133 369
bicat2<- loan.train %>%dplyr::select(Gender, Dependents) %>%table()
bicat2
##         Dependents
## Gender     0   1   2  3+
##   Female  83  19   7   3
##   Male   277  83  94  48
bicat3<- loan.train %>%dplyr::select(Gender, Education) %>%table()
bicat3
##         Education
## Gender   Graduate Not Graduate
##   Female       92           20
##   Male        388          114
bicat4<- loan.train %>%dplyr::select(Gender, Self_Employed) %>%table()
bicat4
##         Self_Employed
## Gender    No Yes
##   Female  89  15
##   Male   411  67
bicat5<- loan.train %>%dplyr::select(Gender, Loan_Amount_Term) %>%table()
bicat5
##         Loan_Amount_Term
## Gender    12  36  60  84 120 180 240 300 360 480
##   Female   0   1   0   1   0   3   1   1  98   4
##   Male     1   1   2   3   3  41   3  12 414  11
bicat6<- loan.train %>%dplyr::select(Gender, Credit_History) %>%table()
bicat6
##         Credit_History
## Gender     0   1
##   Female  17  95
##   Male    72 430
bicat7<- loan.train %>%dplyr::select(Gender, Property_Area) %>%table()
bicat7
##         Property_Area
## Gender   Rural Semiurban Urban
##   Female    24        55    33
##   Male     155       178   169
bicat8<- loan.train %>%dplyr::select(Gender, Loan_Status) %>%table()
bicat8
##         Loan_Status
## Gender     N   Y
##   Female  37  75
##   Male   155 347
bicat9<- loan.train %>%dplyr::select(Married, Dependents) %>%table()
bicat9
##        Dependents
## Married   0   1   2  3+
##     No  175  23   8   7
##     Yes 185  79  93  44
bicat10<- loan.train %>%dplyr::select(Married, Education) %>%table()
bicat10
##        Education
## Married Graduate Not Graduate
##     No       168           45
##     Yes      312           89
bicat11<- loan.train %>%dplyr::select(Married, Self_Employed) %>%table()
bicat11
##        Self_Employed
## Married  No Yes
##     No  171  28
##     Yes 329  54
bicat12<- loan.train %>%dplyr::select(Married, Loan_Amount_Term) %>%table()
bicat12
##        Loan_Amount_Term
## Married  12  36  60  84 120 180 240 300 360 480
##     No    0   2   1   0   1   8   1   3 183   9
##     Yes   1   0   1   4   2  36   3  10 329   6
bicat13<- loan.train %>%dplyr::select(Married, Credit_History) %>%table()
bicat13
##        Credit_History
## Married   0   1
##     No   32 181
##     Yes  57 344
bicat14<- loan.train %>%dplyr::select(Married, Property_Area) %>%table()
bicat14
##        Property_Area
## Married Rural Semiurban Urban
##     No     63        80    70
##     Yes   116       153   132
bicat15<- loan.train %>%dplyr::select(Married, Loan_Status) %>%table()
bicat15
##        Loan_Status
## Married   N   Y
##     No   79 134
##     Yes 113 288
bicat16<- loan.train %>%dplyr::select(Dependents, Education) %>%table()
bicat16
##           Education
## Dependents Graduate Not Graduate
##         0       286           74
##         1        81           21
##         2        77           24
##         3+       36           15
bicat17<- loan.train %>%dplyr::select(Dependents, Self_Employed) %>%table()
bicat17
##           Self_Employed
## Dependents  No Yes
##         0  302  39
##         1   76  20
##         2   80  16
##         3+  42   7
bicat18<- loan.train %>%dplyr::select(Dependents, Loan_Amount_Term) %>%table()
bicat18
##           Loan_Amount_Term
## Dependents  12  36  60  84 120 180 240 300 360 480
##         0    1   1   1   0   2  19   1   6 306  11
##         1    0   1   0   2   0  11   2   2  82   1
##         2    0   0   0   2   1   6   1   3  86   2
##         3+   0   0   1   0   0   8   0   2  38   1
bicat19<- loan.train %>%dplyr::select(Dependents, Credit_History) %>%table()
bicat19
##           Credit_History
## Dependents   0   1
##         0   50 310
##         1   14  88
##         2   14  87
##         3+  11  40
bicat20<- loan.train %>%dplyr::select(Dependents, Property_Area) %>%table()
bicat20
##           Property_Area
## Dependents Rural Semiurban Urban
##         0    111       136   113
##         1     21        40    41
##         2     29        37    35
##         3+    18        20    13
bicat21<- loan.train %>%dplyr::select(Dependents, Loan_Status) %>%table()
bicat21
##           Loan_Status
## Dependents   N   Y
##         0  113 247
##         1   36  66
##         2   25  76
##         3+  18  33
bicat22<- loan.train %>%dplyr::select(Education, Self_Employed) %>%table()
bicat22
##               Self_Employed
## Education       No Yes
##   Graduate     389  65
##   Not Graduate 111  17
bicat23<- loan.train %>%dplyr::select(Education, Loan_Amount_Term) %>%table()
bicat23
##               Loan_Amount_Term
## Education       12  36  60  84 120 180 240 300 360 480
##   Graduate       1   1   1   4   2  28   3  10 411  11
##   Not Graduate   0   1   1   0   1  16   1   3 101   4
bicat25<- loan.train %>%dplyr::select(Education, Credit_History) %>%table()
bicat25
##               Credit_History
## Education        0   1
##   Graduate      63 417
##   Not Graduate  26 108
bicat26<- loan.train %>%dplyr::select(Education, Property_Area) %>%table()
bicat26
##               Property_Area
## Education      Rural Semiurban Urban
##   Graduate       131       187   162
##   Not Graduate    48        46    40
bicat27<- loan.train %>%dplyr::select(Education, Loan_Status) %>%table()
bicat27
##               Loan_Status
## Education        N   Y
##   Graduate     140 340
##   Not Graduate  52  82
bicat28<- loan.train %>%dplyr::select(Self_Employed, Loan_Amount_Term) %>%table()
bicat28
##              Loan_Amount_Term
## Self_Employed  12  36  60  84 120 180 240 300 360 480
##           No    1   2   1   3   2  35   3  10 418  14
##           Yes   0   0   1   1   1   5   1   3  67   1
bicat29<- loan.train %>%dplyr::select(Self_Employed, Credit_History) %>%table()
bicat29
##              Credit_History
## Self_Employed   0   1
##           No   76 424
##           Yes  12  70
bicat30<- loan.train %>%dplyr::select(Self_Employed, Property_Area) %>%table()
bicat30
##              Property_Area
## Self_Employed Rural Semiurban Urban
##           No    143       191   166
##           Yes    26        32    24
bicat31<- loan.train %>%dplyr::select(Self_Employed, Loan_Status) %>%table()
bicat31
##              Loan_Status
## Self_Employed   N   Y
##           No  157 343
##           Yes  26  56
bicat32<- loan.train %>%dplyr::select(Loan_Amount_Term, Credit_History) %>%table()
bicat32
##                 Credit_History
## Loan_Amount_Term   0   1
##              12    0   1
##              36    0   2
##              60    0   2
##              84    0   4
##              120   0   3
##              180  10  34
##              240   0   4
##              300   3  10
##              360  66 446
##              480   4  11
bicat33<- loan.train %>%dplyr::select(Loan_Amount_Term, Property_Area) %>%table()
bicat33
##                 Property_Area
## Loan_Amount_Term Rural Semiurban Urban
##              12      0         0     1
##              36      0         2     0
##              60      0         0     2
##              84      2         1     1
##              120     0         2     1
##              180    11        10    23
##              240     0         2     2
##              300     4         6     3
##              360   156       200   156
##              480     2         7     6
bicat34<- loan.train %>%dplyr::select(Loan_Amount_Term, Loan_Status) %>%table()
bicat34
##                 Loan_Status
## Loan_Amount_Term   N   Y
##              12    0   1
##              36    2   0
##              60    0   2
##              84    1   3
##              120   0   3
##              180  15  29
##              240   1   3
##              300   5   8
##              360 153 359
##              480   9   6
bicat35<- loan.train %>%dplyr::select(Credit_History, Property_Area) %>%table()
bicat35
##               Property_Area
## Credit_History Rural Semiurban Urban
##              0    28        30    31
##              1   151       203   171
bicat36<- loan.train %>%dplyr::select(Credit_History, Loan_Status) %>%table()
bicat36
##               Loan_Status
## Credit_History   N   Y
##              0  82   7
##              1 110 415
bicat37<- loan.train %>%dplyr::select(Property_Area, Loan_Status) %>%table()
bicat37
##              Loan_Status
## Property_Area   N   Y
##     Rural      69 110
##     Semiurban  54 179
##     Urban      69 133

Kategori Multivariat

mulcat1 <- loan.train %>%dplyr::select(Gender, Married, Dependents) %>% ftable()
mulcat1
##                Dependents   0   1   2  3+
## Gender Married                           
## Female No                  62  13   2   3
##        Yes                 21   6   5   0
## Male   No                 113  10   6   4
##        Yes                164  73  88  44
mulcat2 <- loan.train %>%dplyr::select(Gender, Married, Education) %>% ftable()
mulcat2
##                Education Graduate Not Graduate
## Gender Married                                
## Female No                      66           14
##        Yes                     26            6
## Male   No                     102           31
##        Yes                    286           83
mulcat3 <- loan.train %>%dplyr::select(Gender, Married, Self_Employed) %>% ftable()
mulcat3
##                Self_Employed  No Yes
## Gender Married                      
## Female No                     63  11
##        Yes                    26   4
## Male   No                    108  17
##        Yes                   303  50
mulcat4 <- loan.train %>%dplyr::select(Gender, Married, Loan_Amount_Term) %>% ftable()
mulcat4
##                Loan_Amount_Term  12  36  60  84 120 180 240 300 360 480
## Gender Married                                                         
## Female No                         0   1   0   0   0   2   0   1  70   3
##        Yes                        0   0   0   1   0   1   1   0  28   1
## Male   No                         0   1   1   0   1   6   1   2 113   6
##        Yes                        1   0   1   3   2  35   2  10 301   5
mulcat5 <- loan.train %>%dplyr::select(Gender, Married, Credit_History) %>% ftable()
mulcat5
##                Credit_History   0   1
## Gender Married                       
## Female No                      13  67
##        Yes                      4  28
## Male   No                      19 114
##        Yes                     53 316
mulcat6 <- loan.train %>%dplyr::select(Gender, Married, Property_Area) %>% ftable()
mulcat6
##                Property_Area Rural Semiurban Urban
## Gender Married                                    
## Female No                       19        34    27
##        Yes                       5        21     6
## Male   No                       44        46    43
##        Yes                     111       132   126
mulcat7 <- loan.train %>%dplyr::select(Gender, Married, Loan_Status) %>% ftable()
mulcat7
##                Loan_Status   N   Y
## Gender Married                    
## Female No                   29  51
##        Yes                   8  24
## Male   No                   50  83
##        Yes                 105 264
mulcat8 <- loan.train %>%dplyr::select(Married, Dependents, Education) %>% ftable()
mulcat8
##                    Education Graduate Not Graduate
## Married Dependents                                
## No      0                         139           36
##         1                          16            7
##         2                           8            0
##         3+                          5            2
## Yes     0                         147           38
##         1                          65           14
##         2                          69           24
##         3+                         31           13
mulcat9 <- loan.train %>%dplyr::select(Married, Dependents, Self_Employed) %>% ftable()
mulcat9
##                    Self_Employed  No Yes
## Married Dependents                      
## No      0                        145  21
##         1                         14   6
##         2                          7   0
##         3+                         5   1
## Yes     0                        157  18
##         1                         62  14
##         2                         73  16
##         3+                        37   6
mulcat11 <- loan.train %>%dplyr::select(Married, Dependents, Loan_Amount_Term) %>% ftable()
mulcat11
##                    Loan_Amount_Term  12  36  60  84 120 180 240 300 360 480
## Married Dependents                                                         
## No      0                             0   1   1   0   1   5   0   3 150   9
##         1                             0   1   0   0   0   2   1   0  19   0
##         2                             0   0   0   0   0   0   0   0   8   0
##         3+                            0   0   0   0   0   1   0   0   6   0
## Yes     0                             1   0   0   0   1  14   1   3 156   2
##         1                             0   0   0   2   0   9   1   2  63   1
##         2                             0   0   0   2   1   6   1   3  78   2
##         3+                            0   0   1   0   0   7   0   2  32   1
mulcat12 <- loan.train %>%dplyr::select(Married, Dependents, Credit_History) %>% ftable()
mulcat12
##                    Credit_History   0   1
## Married Dependents                       
## No      0                          26 149
##         1                           2  21
##         2                           3   5
##         3+                          1   6
## Yes     0                          24 161
##         1                          12  67
##         2                          11  82
##         3+                         10  34
mulcat13 <- loan.train %>%dplyr::select(Married, Dependents, Property_Area) %>% ftable()
mulcat13
##                    Property_Area Rural Semiurban Urban
## Married Dependents                                    
## No      0                           53        63    59
##         1                            3        12     8
##         2                            4         3     1
##         3+                           3         2     2
## Yes     0                           58        73    54
##         1                           18        28    33
##         2                           25        34    34
##         3+                          15        18    11
mulcat14 <- loan.train %>%dplyr::select(Married, Dependents, Loan_Status) %>% ftable()
mulcat14
##                    Loan_Status   N   Y
## Married Dependents                    
## No      0                       63 112
##         1                       10  13
##         2                        3   5
##         3+                       3   4
## Yes     0                       50 135
##         1                       26  53
##         2                       22  71
##         3+                      15  29
mulcat15 <- loan.train %>%dplyr::select( Dependents, Self_Employed, Loan_Amount_Term) %>% ftable()
mulcat15
##                          Loan_Amount_Term  12  36  60  84 120 180 240 300 360 480
## Dependents Self_Employed                                                         
## 0          No                               1   1   1   0   1  14   1   5 259  10
##            Yes                              0   0   0   0   1   3   0   1  31   1
## 1          No                               0   1   0   2   0   8   2   1  60   1
##            Yes                              0   0   0   0   0   2   0   1  17   0
## 2          No                               0   0   0   1   1   6   0   2  68   2
##            Yes                              0   0   0   1   0   0   1   1  13   0
## 3+         No                               0   0   0   0   0   7   0   2  31   1
##            Yes                              0   0   1   0   0   0   0   0   6   0
mulcat16 <- loan.train %>%dplyr::select(Dependents, Self_Employed, Credit_History) %>% ftable()
mulcat16
##                          Credit_History   0   1
## Dependents Self_Employed                       
## 0          No                            45 257
##            Yes                            5  34
## 1          No                             9  67
##            Yes                            5  15
## 2          No                            11  69
##            Yes                            2  14
## 3+         No                            11  31
##            Yes                            0   7
mulcat17 <- loan.train %>%dplyr::select(Dependents, Self_Employed, Property_Area) %>% ftable()
mulcat17
##                          Property_Area Rural Semiurban Urban
## Dependents Self_Employed                                    
## 0          No                             93       117    92
##            Yes                            10        15    14
## 1          No                             15        28    33
##            Yes                             5         9     6
## 2          No                             19        30    31
##            Yes                             9         4     3
## 3+         No                             16        16    10
##            Yes                             2         4     1
mulcat18 <- loan.train %>%dplyr::select(Dependents, Self_Employed, Loan_Status) %>% ftable()
mulcat18
##                          Loan_Status   N   Y
## Dependents Self_Employed                    
## 0          No                         97 205
##            Yes                        11  28
## 1          No                         24  52
##            Yes                        10  10
## 2          No                         19  61
##            Yes                         5  11
## 3+         No                         17  25
##            Yes                         0   7
mulcat25 <- loan.train %>%dplyr::select(Dependents, Self_Employed, Married) %>% ftable()
mulcat25
##                          Married  No Yes
## Dependents Self_Employed                
## 0          No                    145 157
##            Yes                    21  18
## 1          No                     14  62
##            Yes                     6  14
## 2          No                      7  73
##            Yes                     0  16
## 3+         No                      5  37
##            Yes                     1   6
mulcat26 <- loan.train %>%dplyr::select(Dependents, Self_Employed, Gender) %>% ftable()
mulcat26
##                          Gender Female Male
## Dependents Self_Employed                   
## 0          No                       70  232
##            Yes                      10   29
## 1          No                       12   64
##            Yes                       5   15
## 2          No                        5   75
##            Yes                       0   16
## 3+         No                        2   40
##            Yes                       0    7
mulcat27 <- loan.train %>%dplyr::select(Dependents, Self_Employed, Education) %>% ftable()
mulcat27
##                          Education Graduate Not Graduate
## Dependents Self_Employed                                
## 0          No                           241           61
##            Yes                           30            9
## 1          No                            59           17
##            Yes                           17            3
## 2          No                            59           21
##            Yes                           14            2
## 3+         No                            30           12
##            Yes                            4            3
mulcat19 <- loan.train %>%dplyr::select(Self_Employed, Credit_History, Education) %>% ftable()
mulcat19
##                              Education Graduate Not Graduate
## Self_Employed Credit_History                                
## No            0                              52           24
##               1                             337           87
## Yes           0                              10            2
##               1                              55           15
mulcat20 <- loan.train %>%dplyr::select(Self_Employed, Credit_History, Property_Area) %>% ftable()
mulcat20
##                              Property_Area Rural Semiurban Urban
## Self_Employed Credit_History                                    
## No            0                               23        27    26
##               1                              120       164   140
## Yes           0                                5         2     5
##               1                               21        30    19
mulcat21 <- loan.train %>%dplyr::select(Self_Employed, Credit_History, Loan_Status) %>% ftable()
mulcat21
##                              Loan_Status   N   Y
## Self_Employed Credit_History                    
## No            0                           69   7
##               1                           88 336
## Yes           0                           12   0
##               1                           14  56
mulcat22 <- loan.train %>%dplyr::select(Self_Employed, Credit_History, Married) %>% ftable()
mulcat22
##                              Married  No Yes
## Self_Employed Credit_History                
## No            0                       28  48
##               1                      143 281
## Yes           0                        4   8
##               1                       24  46
mulcat23 <- loan.train %>%dplyr::select(Self_Employed, Credit_History, Gender) %>% ftable()
mulcat23
##                              Gender Female Male
## Self_Employed Credit_History                   
## No            0                         14   62
##               1                         75  349
## Yes           0                          3    9
##               1                         12   58
mulcat24 <- loan.train %>%dplyr::select(Self_Employed, Credit_History, Loan_Amount_Term) %>% ftable()
mulcat24
##                              Loan_Amount_Term  12  36  60  84 120 180 240 300 360 480
## Self_Employed Credit_History                                                         
## No            0                                 0   0   0   0   0   8   0   2  56   4
##               1                                 1   2   1   3   2  27   3   8 362  10
## Yes           0                                 0   0   0   0   0   2   0   1   9   0
##               1                                 0   0   1   1   1   3   1   2  58   1
mulcat28 <- loan.train %>%dplyr::select(Credit_History, Property_Area, Education) %>% ftable()
mulcat28
##                              Education Graduate Not Graduate
## Credit_History Property_Area                                
## 0              Rural                         20            8
##                Semiurban                     24            6
##                Urban                         19           12
## 1              Rural                        111           40
##                Semiurban                    163           40
##                Urban                        143           28
mulcat29 <- loan.train %>%dplyr::select(Credit_History, Property_Area, Dependents) %>% ftable()
mulcat29
##                              Dependents   0   1   2  3+
## Credit_History Property_Area                           
## 0              Rural                     15   5   6   2
##                Semiurban                 16   3   5   6
##                Urban                     19   6   3   3
## 1              Rural                     96  16  23  16
##                Semiurban                120  37  32  14
##                Urban                     94  35  32  10
mulcat30 <- loan.train %>%dplyr::select(Credit_History, Property_Area, Loan_Status) %>% ftable()
mulcat30
##                              Loan_Status   N   Y
## Credit_History Property_Area                    
## 0              Rural                      26   2
##                Semiurban                  26   4
##                Urban                      30   1
## 1              Rural                      43 108
##                Semiurban                  28 175
##                Urban                      39 132
mulcat31 <- loan.train %>%dplyr::select(Credit_History, Property_Area, Married) %>% ftable()
mulcat31
##                              Married  No Yes
## Credit_History Property_Area                
## 0              Rural                   8  20
##                Semiurban              12  18
##                Urban                  12  19
## 1              Rural                  55  96
##                Semiurban              68 135
##                Urban                  58 113
mulcat32 <- loan.train %>%dplyr::select(Credit_History, Property_Area, Gender) %>% ftable()
mulcat32
##                              Gender Female Male
## Credit_History Property_Area                   
## 0              Rural                     1   27
##                Semiurban                 8   22
##                Urban                     8   23
## 1              Rural                    23  128
##                Semiurban                47  156
##                Urban                    25  146
mulcat33 <- loan.train %>%dplyr::select(Credit_History, Property_Area, Loan_Amount_Term) %>% ftable()
mulcat3
##                Self_Employed  No Yes
## Gender Married                      
## Female No                     63  11
##        Yes                    26   4
## Male   No                    108  17
##        Yes                   303  50

Memahami distribusi data terhadap status pinjaman (yaitu variabel target) memvisualisasikan variabel kategori dan status pinjaman

train.new <- loan.train %>% 
  filter(Loan_Status!="test") %>%
  mutate(Loan_Status=ifelse(Loan_Status=="Y",1,0))

train.new %>% 
  group_by(Loan_Status) %>% 
  summarise(n.count=n()) %>%
  mutate(percent=round(n.count/nrow(train.new)*100,1),
         Loan_Status=as.factor(Loan_Status)) %>%
  ungroup() %>%
  ggplot(aes(x=Loan_Status, y=percent, fill=Loan_Status)) +
  geom_bar(stat="identity")+
  theme_economist_white()

# buat fungsi untuk memplot banyak variabel kategori dan bagaimana mereka berinteraksi dengan variabel target

PlotSimple <- function(dataframe,x,y){
  aaa <- enquo(x)
  bbb <- enquo(y)
  dataframe %>%
    filter(!is.na(!! aaa), !is.na(!! bbb))  %>%
    group_by(!! aaa,!! bbb) %>%
    summarise(n=n())%>%
    mutate(percent=n/nrow(dataframe)) %>%
    ggplot(aes_(fill=aaa, y=~percent, x=bbb)) +
    geom_bar(position="dodge", stat="identity") +
    theme_economist_white()
}

xvars <- list(as.name("Married"),
              as.name("Credit_History"),
              as.name("Gender"),
              as.name("Education"),
              as.name("Self_Employed"),
              as.name("Property_Area"))

cat.data <- loan.train%>% dplyr::select_if(is.factor)

all_plots<-lapply (xvars, PlotSimple, dataframe=cat.data, y =Loan_Status)
cowplot::plot_grid(plotlist = all_plots)

60% dari klien memiliki pinjaman mereka disetujui. Demikian pula, 60% klien yang memiliki riwayat kredit kemungkinan besar akan menyetujui pinjaman mereka. Ini merupakan indikasi sejarah kredit dan persetujuan pinjaman memiliki beberapa korelasi. 29,2% Pemohon yang tinggal di area properti semi-perkotaan cenderung menyetujui pinjaman mereka. Menikah cenderung memiliki status pinjaman disetujui

Kuantitatif

Univariat numerik

Mean

mean(loan.train$ApplicantIncome)
## [1] 5403.459
mean(loan.train$CoapplicantIncome)
## [1] 1621.246
mean(loan.train$LoanAmount)
## [1] 146.4122

Quantile

quantile(loan.train$ApplicantIncome)
##      0%     25%     50%     75%    100% 
##   150.0  2877.5  3812.5  5795.0 81000.0
quantile(loan.train$CoapplicantIncome)
##       0%      25%      50%      75%     100% 
##     0.00     0.00  1188.50  2297.25 41667.00
quantile(loan.train$LoanAmount)
##     0%    25%    50%    75%   100% 
##   9.00 100.25 129.00 164.75 700.00

Median

median(loan.train$ApplicantIncome)
## [1] 3812.5
median(loan.train$CoapplicantIncome)
## [1] 1188.5
median(loan.train$LoanAmount)
## [1] 129

Mode

mode(loan.train$ApplicantIncome)
## [1] "numeric"
mode(loan.train$CoapplicantIncome)
## [1] "numeric"
mode(loan.train$LoanAmount)
## [1] "numeric"
loantrain <- loan.train%>% dplyr::select_if(is.numeric)
summary(loantrain)
##  ApplicantIncome CoapplicantIncome   LoanAmount   
##  Min.   :  150   Min.   :    0     Min.   :  9.0  
##  1st Qu.: 2878   1st Qu.:    0     1st Qu.:100.2  
##  Median : 3812   Median : 1188     Median :129.0  
##  Mean   : 5403   Mean   : 1621     Mean   :146.4  
##  3rd Qu.: 5795   3rd Qu.: 2297     3rd Qu.:164.8  
##  Max.   :81000   Max.   :41667     Max.   :700.0

Var

var(loan.train$ApplicantIncome)
## [1] 37320390
var(loan.train$CoapplicantIncome)
## [1] 8562930
var(loan.train$LoanAmount)
## [1] 7062.296

standar deviation

sd(loan.train$ApplicantIncome)
## [1] 6109.042
sd(loan.train$CoapplicantIncome)
## [1] 2926.248
sd(loan.train$LoanAmount)
## [1] 84.03747

Media Absolute Deviation

mad(loan.train$ApplicantIncome)
## [1] 1822.857
mad(loan.train$CoapplicantIncome)
## [1] 1762.07
mad(loan.train$LoanAmount)
## [1] 45.2193

IQR

IQR(loan.train$ApplicantIncome)
## [1] 2917.5
IQR(loan.train$CoapplicantIncome)
## [1] 2297.25
IQR(loan.train$LoanAmount)
## [1] 64.5

Skewness

library(e1071)   
skewness(loan.train$ApplicantIncome)
## [1] 6.507596
skewness(loan.train$CoapplicantIncome)
## [1] 7.454967
skewness(loan.train$LoanAmount)
## [1] 2.713293

Kurtosis

kurtosis(loan.train$ApplicantIncome)
## [1] 59.83387
kurtosis(loan.train$CoapplicantIncome)
## [1] 83.97239
kurtosis(loan.train$LoanAmount)
## [1] 10.75326

Bivariat numerik

Z-score

cov(loan.train$ApplicantIncome,loan.train$CoapplicantIncome)
## [1] -2084490
cov(loan.train$ApplicantIncome,loan.train$LoanAmount)
## [1] 290383
cov(loan.train$CoapplicantIncome,loan.train$LoanAmount)
## [1] 46189.73
cor(loan.train$ApplicantIncome,loan.train$CoapplicantIncome)
## [1] -0.1166046
cor(loan.train$ApplicantIncome,loan.train$LoanAmount)
## [1] 0.5656205
cor(loan.train$CoapplicantIncome,loan.train$LoanAmount)
## [1] 0.1878284
zscore_applicantincome=(loan.train$ApplicantIncome-mean(loan.train$ApplicantIncome))/sd(loan.train$ApplicantIncome)
zscore_coapplicantincome=(loan.train$CoapplicantIncome-mean(loan.train$CoapplicantIncome))/sd(loan.train$CoapplicantIncome)
zscore_LoanAmount=(loan.train$LoanAmount-mean(loan.train$LoanAmount))/sd(loan.train$LoanAmount)

Multivariat numerik

cov(loantrain)
##                   ApplicantIncome CoapplicantIncome LoanAmount
## ApplicantIncome          37320390       -2084490.34 290382.977
## CoapplicantIncome        -2084490        8562929.52  46189.726
## LoanAmount                 290383          46189.73   7062.296
cor(loantrain)
##                   ApplicantIncome CoapplicantIncome LoanAmount
## ApplicantIncome         1.0000000        -0.1166046  0.5656205
## CoapplicantIncome      -0.1166046         1.0000000  0.1878284
## LoanAmount              0.5656205         0.1878284  1.0000000
train.new <- train.new %>%
  mutate(Loan_Status=as.factor(Loan_Status))

varlist <- c("ApplicantIncome", "CoapplicantIncome", "LoanAmount")

PlotFast <- function(varName) {

train.new %>% 
group_by_("Loan_Status") %>% 
dplyr::select_("Loan_Status",varName) %>% 
ggplot(aes_string("Loan_Status",varName,fill="Loan_Status")) + 
    geom_boxplot() +
    theme_economist_white()

}

all_plot_cont<-lapply(varlist,PlotFast)
cowplot::plot_grid(plotlist = all_plot_cont, ncol=3)

rm(train.new)

Sulit untuk melihat pola khusus di antara variabel kontinu saat ini. Ini mungkin berarti bahwa kasus yang disetujui dan tidak disetujui memiliki jumlah pinjaman yang sama, pendapatan pemohon/pemohon.

EDA dengan cara Malas

library(funModeling) 
library(tidyverse) 
library(Hmisc)
library(skimr)
basic_eda <- function(loan.train)
{
  glimpse(loan.train)
  skim(loan.train)
  df_status(loan.train)
  freq(loan.train) 
  profiling_num(loan.train)
  plot_num(loan.train)
  describe(loan.train)
}
basic_eda(loan.train)
## Rows: 614
## Columns: 12
## $ Gender            <fct> Male, Male, Male, Male, Male, Male, Male, Male, Male~
## $ Married           <fct> No, Yes, Yes, Yes, No, Yes, Yes, Yes, Yes, Yes, Yes,~
## $ Dependents        <fct> 0, 1, 0, 0, 0, 2, 0, 3+, 2, 1, 2, 2, 2, 0, 2, 0, 1, ~
## $ Education         <fct> Graduate, Graduate, Graduate, Not Graduate, Graduate~
## $ Self_Employed     <fct> No, No, Yes, No, No, Yes, No, No, No, No, No, NA, No~
## $ ApplicantIncome   <int> 5849, 4583, 3000, 2583, 6000, 5417, 2333, 3036, 4006~
## $ CoapplicantIncome <dbl> 0, 1508, 0, 2358, 0, 4196, 1516, 2504, 1526, 10968, ~
## $ LoanAmount        <dbl> 146.4122, 128.0000, 66.0000, 120.0000, 141.0000, 267~
## $ Loan_Amount_Term  <fct> 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 36~
## $ Credit_History    <fct> 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0~
## $ Property_Area     <fct> Urban, Rural, Urban, Urban, Urban, Urban, Urban, Sem~
## $ Loan_Status       <fct> Y, N, Y, Y, Y, Y, Y, N, Y, N, Y, Y, Y, N, Y, Y, Y, N~
##             variable q_zeros p_zeros q_na p_na q_inf p_inf    type unique
## 1             Gender       0    0.00    0 0.00     0     0  factor      2
## 2            Married       0    0.00    0 0.00     0     0  factor      2
## 3         Dependents     360   58.63    0 0.00     0     0  factor      4
## 4          Education       0    0.00    0 0.00     0     0  factor      2
## 5      Self_Employed       0    0.00   32 5.21     0     0  factor      2
## 6    ApplicantIncome       0    0.00    0 0.00     0     0 integer    505
## 7  CoapplicantIncome     273   44.46    0 0.00     0     0 numeric    287
## 8         LoanAmount       0    0.00    0 0.00     0     0 numeric    204
## 9   Loan_Amount_Term       0    0.00   14 2.28     0     0  factor     10
## 10    Credit_History      89   14.50    0 0.00     0     0  factor      2
## 11     Property_Area       0    0.00    0 0.00     0     0  factor      3
## 12       Loan_Status       0    0.00    0 0.00     0     0  factor      2

##   Gender frequency percentage cumulative_perc
## 1   Male       502      81.76           81.76
## 2 Female       112      18.24          100.00

##   Married frequency percentage cumulative_perc
## 1     Yes       401      65.31           65.31
## 2      No       213      34.69          100.00

##   Dependents frequency percentage cumulative_perc
## 1          0       360      58.63           58.63
## 2          1       102      16.61           75.24
## 3          2       101      16.45           91.69
## 4         3+        51       8.31          100.00

##      Education frequency percentage cumulative_perc
## 1     Graduate       480      78.18           78.18
## 2 Not Graduate       134      21.82          100.00

##   Self_Employed frequency percentage cumulative_perc
## 1            No       500      81.43           81.43
## 2           Yes        82      13.36           94.79
## 3          <NA>        32       5.21          100.00

##    Loan_Amount_Term frequency percentage cumulative_perc
## 1               360       512      83.39           83.39
## 2               180        44       7.17           90.56
## 3               480        15       2.44           93.00
## 4              <NA>        14       2.28           95.28
## 5               300        13       2.12           97.40
## 6                84         4       0.65           98.05
## 7               240         4       0.65           98.70
## 8               120         3       0.49           99.19
## 9                36         2       0.33           99.52
## 10               60         2       0.33           99.85
## 11               12         1       0.16          100.00

##   Credit_History frequency percentage cumulative_perc
## 1              1       525       85.5            85.5
## 2              0        89       14.5           100.0

##   Property_Area frequency percentage cumulative_perc
## 1     Semiurban       233      37.95           37.95
## 2         Urban       202      32.90           70.85
## 3         Rural       179      29.15          100.00

##   Loan_Status frequency percentage cumulative_perc
## 1           Y       422      68.73           68.73
## 2           N       192      31.27          100.00

## loan.train 
## 
##  12  Variables      614  Observations
## --------------------------------------------------------------------------------
## Gender 
##        n  missing distinct 
##      614        0        2 
##                         
## Value      Female   Male
## Frequency     112    502
## Proportion  0.182  0.818
## --------------------------------------------------------------------------------
## Married 
##        n  missing distinct 
##      614        0        2 
##                       
## Value         No   Yes
## Frequency    213   401
## Proportion 0.347 0.653
## --------------------------------------------------------------------------------
## Dependents 
##        n  missing distinct 
##      614        0        4 
##                                   
## Value          0     1     2    3+
## Frequency    360   102   101    51
## Proportion 0.586 0.166 0.164 0.083
## --------------------------------------------------------------------------------
## Education 
##        n  missing distinct 
##      614        0        2 
##                                     
## Value          Graduate Not Graduate
## Frequency           480          134
## Proportion        0.782        0.218
## --------------------------------------------------------------------------------
## Self_Employed 
##        n  missing distinct 
##      582       32        2 
##                       
## Value         No   Yes
## Frequency    500    82
## Proportion 0.859 0.141
## --------------------------------------------------------------------------------
## ApplicantIncome 
##        n  missing distinct     Info     Mean      Gmd      .05      .10 
##      614        0      505        1     5403     4183     1898     2216 
##      .25      .50      .75      .90      .95 
##     2878     3812     5795     9460    14583 
## 
## lowest :   150   210   416   645   674, highest: 39147 39999 51763 63337 81000
## --------------------------------------------------------------------------------
## CoapplicantIncome 
##        n  missing distinct     Info     Mean      Gmd      .05      .10 
##      614        0      287    0.912     1621     2118        0        0 
##      .25      .50      .75      .90      .95 
##        0     1188     2297     3782     4997 
## 
## lowest :     0.00    16.12   189.00   240.00   242.00
## highest: 10968.00 11300.00 20000.00 33837.00 41667.00
## --------------------------------------------------------------------------------
## LoanAmount 
##        n  missing distinct     Info     Mean      Gmd      .05      .10 
##      614        0      204        1    146.4    77.79     57.3     72.3 
##      .25      .50      .75      .90      .95 
##    100.2    129.0    164.8    229.4    293.4 
## 
## lowest :   9  17  25  26  30, highest: 500 570 600 650 700
## --------------------------------------------------------------------------------
## Loan_Amount_Term 
##        n  missing distinct 
##      600       14       10 
## 
## lowest : 12  36  60  84  120, highest: 180 240 300 360 480
##                                                                       
## Value         12    36    60    84   120   180   240   300   360   480
## Frequency      1     2     2     4     3    44     4    13   512    15
## Proportion 0.002 0.003 0.003 0.007 0.005 0.073 0.007 0.022 0.853 0.025
## --------------------------------------------------------------------------------
## Credit_History 
##        n  missing distinct 
##      614        0        2 
##                       
## Value          0     1
## Frequency     89   525
## Proportion 0.145 0.855
## --------------------------------------------------------------------------------
## Property_Area 
##        n  missing distinct 
##      614        0        3 
##                                         
## Value          Rural Semiurban     Urban
## Frequency        179       233       202
## Proportion     0.292     0.379     0.329
## --------------------------------------------------------------------------------
## Loan_Status 
##        n  missing distinct 
##      614        0        2 
##                       
## Value          N     Y
## Frequency    192   422
## Proportion 0.313 0.687
## --------------------------------------------------------------------------------

Tugas 4

Lakukan pemeriksaan distribusi densitas menggunakan R dan Python pada setiap variabel kuantitatif dengan beberapa bagian sebagai berikut:

Univariat numerik

Applicant Income

ggplot(loan.train, aes(x = ApplicantIncome)) +
  geom_density()

Coapplicant Income

ggplot(loan.train, aes(x = CoapplicantIncome)) +
  geom_density()

Loan Amount

ggplot(loan.train, aes(x = LoanAmount)) +
  geom_density()

Bivariat numerik

Applicant Income vs Coapplicant Income

p1 <- ggplot(loan.train, aes(x = ApplicantIncome, y = CoapplicantIncome)) +
  geom_point(alpha = .5) +
  geom_density_2d()
ggplotly(p1)

Coapplicant Income vs LoanAmount

p2 <-ggplot(loan.train, aes(x = CoapplicantIncome, y = LoanAmount)) +
  geom_point(alpha = .5) +
  geom_density_2d()
ggplotly(p2)

ApplicantIncome vs LoanAmount

p3 <- ggplot(loan.train, aes(x = ApplicantIncome, y = LoanAmount)) +
  geom_point(alpha = .5) +
  geom_density_2d()
ggplotly(p3)

Multivariat numerik

library(GGally)
ggpairs(loantrain)

Tugas 5

Lakukan proses pengujian Hipotesis menggunakan R dan Python pada setiap variabel kuantitatif dengan beberapa bagian sebagai berikut:

Hitunglah margin of error dan estimasi interval untuk proporsi peminjam bejenis kelamin perempuan dalam pada tingkat kepercayaan 95%.

library(MASS)                                           
k = sum(loan.train$Gender == "Female")
n = length(loan.train$Gender)
pbar = k/n                                             
SE = sqrt(pbar*(1-pbar)/n); SE   
## [1] 0.01558505
E = qnorm(0.975)*SE; E
## [1] 0.03054614
pbar + c(-E, E)
## [1] 0.1518643 0.2129566

Pada tingkat kepercayaan 95%, antara 15,2% dan 21,3% peminjam bejenis kelamin perempuan, dan margin of error adalah 3,05%.

Jika anda berencana menggunakan perkiraan proporsi 50% data konsumen berjenis kelamin perempuan, temukan ukuran sampel yang diperlukan untuk mencapai margin kesalahan 5% untuk data obeservasi pada tingkat kepercayaan 95%.

zstar = qnorm(.975)                                    
p = 0.5                                                
E = 0.05                                               
zstar^2*p*(1-p)/E^2     
## [1] 384.1459

Lakukan pembuktian kebenaran assumsi dengan tingakat signifikansi 0.05, jika Bank mengklaim bahwa pinjaman rata-rata konsumen adalah:

Lebih besar $ 150.

mu0 = 150
xbar = mean(loan.train$LoanAmount)
s = sd(loan.train$LoanAmount)
n = length(loan.train$LoanAmount)
t = (xbar-mu0)/(s/sqrt(n)) ; t
## [1] -1.057899
alpha = 0.05
t.alpha = qt(1-alpha, df=n-1)
-t.alpha
## [1] -1.647343

Karena \(\mu_0 \ge \mu\), dalam hal ini kita harus fokus pada nilai kritis left tail. Di sini, ditemukan bahwa statistik uji -1.057899 lebih besar dari nilai kritis -1.644854. Akibatnya, pada tingkat signifikansi 0,05, kami menolak klaim bahwa rata-rata pinjaman konsumen lebih dari 150 dolar.

Lebih kecil $ 150

mu0 = 150
xbar = mean(loan.train$LoanAmount)
s = sd(loan.train$LoanAmount)
n = length(loan.train$LoanAmount)
t = (xbar-mu0)/(s/sqrt(n)) ; t
## [1] -1.057899
alpha = 0.05
t.alpha = qt(1-alpha, df=n-1)
t.alpha
## [1] 1.647343

Nilai statistiknya -1.058 lebih kecil dari nilai kritis yaitu 1.645. maka pada tingkat signifikan 0.05, kita menerima bahwa rata-rata pinjaman konsumen kurang dari 150 dolar.

Sama dengan $ 150.

mu0 = 150
xbar = mean(loan.train$LoanAmount)
s = sd(loan.train$LoanAmount)
n = length(loan.train$LoanAmount)
t = (xbar-mu0)/(s/sqrt(n)) ; t
## [1] -1.057899
alpha = .05                                           
t.half.alpha = qt(1-alpha/2, df=n-1)                        
c(-t.half.alpha, t.half.alpha)                             
## [1] -1.963841  1.963841

Statistik uji -1.057899 terletak di antara nilai kritis -1,96 dan 1,96. Oleh karena itu, pada tingkat signifikansi 0,05, kita tidak menolak hipotesis nol bahwa rata-rata penguin tidak jauh berbeda dari 150.

Lakukan pembuktian kebenaran assumsi dengan tingakat signifikansi 0.05, seperti diatas jika diketahui simpangan baku pinjaman adalah $ 85.

Lebih besar $ 150.

mu0 = 150
xbar = mean(loan.train$LoanAmount)
sigma = 85 
n = length(loan.train$LoanAmount)
z = (xbar-mu0)/(sigma/sqrt(n)) ; z
## [1] -1.045919
alpha = 0.05
z.alpha = qnorm(1-alpha)
-z.alpha
## [1] -1.644854

Karena \(\mu_0 \ge \mu\), dalam hal ini kita harus fokus pada nilai kritis left tail. Di sini, ditemukan bahwa statistik uji -1.045 lebih besar dari nilai kritis -1.644854. Akibatnya, pada tingkat signifikansi 0,05, kami menolak klaim bahwa rata-rata pinjaman konsumen lebih dari 150 dolar.

Lebih kecil $ 150

mu0 = 150
xbar = mean(loan.train$LoanAmount)
sigma = 85
n = length(loan.train$LoanAmount)
z = (xbar-mu0)/(sigma/sqrt(n)) ; z
## [1] -1.045919
alpha = 0.05
z.alpha = qnorm(1-alpha)
z.alpha
## [1] 1.644854

Nilai statistiknya -1.046 lebih kecil dari nilai kritis yaitu 1.645. maka pada tingkat signifikan 0.05, kita menerima bahwa rata-rata pinjaman konsumen kurang dari 150 dolar.

Sama dengan $ 150.

mu0 = 150
xbar = mean(loan.train$LoanAmount)
sigma = 85
n = length(loan.train$LoanAmount)
z = (xbar-mu0)/(sigma/sqrt(n)) ; z
## [1] -1.045919
alpha = .05                                           
z.half.alpha = qnorm(1-alpha/2)                        
c(-z.half.alpha, z.half.alpha)                             
## [1] -1.959964  1.959964

Statistik uji -1.046 terletak di antara nilai kritis -1,96 dan 1,96. Oleh karena itu, pada tingkat signifikansi 0,05, kita tidak menolak hipotesis nol bahwa rata-rata penguin tidak jauh berbeda dari 150.

LS0tDQp0aXRsZTogIktPTVBVVEFTSSBTVEFUSVNUSUtBIg0Kc3VidGl0bGU6ICJ+IFVqaWFuIFRlbmdhaCBTZW1lc3RlciB+Ig0KYXV0aG9yOiAiVmFuZXNzYSBTVXBpdCINCmRhdGU6ICAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6DQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOiAgICMgaHR0cHM6Ly9naXRodWIuY29tL2p1YmEvcm1kZm9ybWF0cw0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQogICAgdGh1bWJuYWlsczogdHJ1ZQ0KICAgIGxpZ2h0Ym94OiB0cnVlDQogICAgZ2FsbGVyeTogdHJ1ZQ0KICAgIGxpYl9kaXI6IGxpYnMNCiAgICBkZl9wcmludDogInBhZ2VkIg0KICAgIGNvZGVfZm9sZGluZzogInNob3ciDQogICAgY29kZV9kb3dubG9hZDogeWVzDQoNCi0tLQ0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNsYXNzLnNvdXJjZSA9ICJub2NvcHkiLA0KICAgICAgICAgICAgICAgICAgICAgIGNsYXNzLm91dHB1dCA9ICJub2NvcHkiLA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGLA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGKQ0KDQpsaWJyYXJ5KHJldGljdWxhdGUpDQpsaWJyYXJ5KFJjcHApDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KG12dG5vcm0pDQpsaWJyYXJ5KE1BU1MpDQpsaWJyYXJ5KGdndGhlbWVzKQ0KbGlicmFyeShycGFydC5wbG90KQ0KbGlicmFyeShjb3dwbG90KQ0KYGBgDQoNCjxicj4NCg0KDQp8DQo6LS0tLSB8Oi0tLS0NCioqS29udGFrKip8ICoqOiAkXGRvd25hcnJvdyQqKg0KRW1haWx8IGRzY2llbmNlbGFic0BvdXRsb29rLmNvbQ0KSW5zdGFncmFtIHwgaHR0cHM6Ly93d3cuaW5zdGFncmFtLmNvbS9kc2NpZW5jZWxhYnMvIA0KUlB1YnMgIHwgaHR0cHM6Ly9ycHVicy5jb20vZHNjaWVuY2VsYWJzLyANCg0KKioqDQoNCiMgRGF0YSBTZXQNCg0KDQoNCiMgVHVnYXMgMQ0KDQpMYWt1a2FuIHByb3NlcyBwZXJzaWFwYW4gZGF0YSBkZW5nYW4gUiBkYW4gUHl0aG9uLCBkZW5nYW4gYmViZXJhcGEgbGFuZ2thaCBiZXJpa3V0Og0KDQojIyBJbXBvcnQgRGF0YQ0KDQpgYGB7cn0NCmxvYW5fdHJhaW4gPC0gcmVhZC5jc3YoImxvYW4tdHJhaW4uY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IFQsIG5hLnN0cmluZ3M9YygiIiwiIiwiTkEiKSkNCmBgYA0KDQojIyBQZW5hbmdhbmFuIERhdGEgSGlsYW5nDQoNCktpdGEgY2VrIHRpcGUgZGF0YSBkYW4gbmlsYWkgTkEgZGFyaSBkYXRhIDoNCmBgYHtyfQ0Kc3VtbWFyeShsb2FuX3RyYWluKQ0KZ2xpbXBzZShsb2FuX3RyYWluKQ0KYGBgDQoNCmBgYHtyfQ0KYW55TkEobG9hbl90cmFpbikNCmNvbFN1bXMoaXMubmEobG9hbl90cmFpbikpDQpgYGANCg0KQWRhIGR1YSB0aXBlIGRhdGEgeWFuZyBwZXJsdSBkaXViYWg6IA0KDQoqIExvYW5fQW1vdW50X1Rlcm0gOiBVYmFoIHNlYmFnYWkgdGlwZSBkYXRhIGZha3RvciANCiogQ3JlZGl0X0hpc3RvcnkgOiBVYmFoIHNlYmFnYWkgdGlwZSBkYXRhIGZha3Rvcg0KDQpgYGB7cn0NCm5hbWVzKGxvYW5fdHJhaW4pWzFdIDwtICJMb2FuX0lEIg0KbG9hbi50cmFpbiA8LSBsb2FuX3RyYWluICU+JSANCiAgZHBseXI6OnNlbGVjdCgtTG9hbl9JRCkgJT4lIA0KICBtdXRhdGUoTG9hbl9BbW91bnRfVGVybSA9IGFzLmZhY3RvcihMb2FuX0Ftb3VudF9UZXJtKSwNCiAgICAgICAgIENyZWRpdF9IaXN0b3J5ID0gYXMuZmFjdG9yKENyZWRpdF9IaXN0b3J5KSkNCg0KaGVhZChsb2FuLnRyYWluKQ0KYGBgDQpBZGEganVnYSBuaWxhaSBOQSBiZXJkYXNhcmthbiBwZW1lcmlrc2FhbiBhd2FsIHBhZGE6DQoNCiogTG9hbkFtb3VudA0KKiBMb2FuX0Ftb3VudF9UZXJtDQoqIENyZWRpdF9IaXN0b3J5DQoNCg0KRnVuZ3NpIHVudHVrIGRhdGEgY2xlYW5zaW5nIDoNCmBgYHtyfQ0KTW9kZSA9IGZ1bmN0aW9uKHgpew0KICBhID0gdGFibGUoeCkNCiAgYiA9IG1heChhKQ0KICBpZihhbGwoYSA9PSBiKSkNCiAgICBtb2QgPSBOQQ0KICBlbHNlIGlmKGlzLm51bWVyaWMoeCkpDQogICAgbW9kID0gYXMubnVtZXJpYyhuYW1lcyhhKSlbYT09Yl0NCiAgICBlbHNlDQogICAgICBtb2QgPSBuYW1lcyhhKVthPT1iXQ0KICByZXR1cm4obW9kKQ0KfQ0KYGBgDQoNClVudHVrIG1lbWJ1YXQgaGFzaWwga2VzZWx1cnVoYW4geWFuZyBsZWJpaCBiYWlrLCBraXRhIGFrYW4gbWVuY29iYSBtZW5nZ2FudGkgbmlsYWkgeWFuZyBoaWxhbmcvIE5BIGJlcmRhc2Fya2FuIHRpcGVueWE6IA0KDQoqIERhdGEgZGVuZ2FuIG5pbGFpIHRpcGUgTnVtZXJpayB5YW5nIGhpbGFuZyBha2FuIGRpZ2FudGkgZGVuZ2FuIG5pbGFpIHJhdGEtcmF0YW55YSAobWVuZ2d1bmFrYW4gZnVuZ3NpIG1lYW4oKSkuIA0KKiBOaWxhaSBkYXRhIGRlbmdhbiB0aXBlIGRhdGEgZmFrdG9yIGFrYW4gZGlnYW50aSBkZW5nYW4gbmlsYWkgeWFuZyBtZW1pbGlraSBqdW1sYWgga2VtdW5jdWxhbiB0ZXJ0aW5nZ2kgZGFsYW0ga3VtcHVsYW4gZGF0YW55YSAobWVuZ2d1bmFrYW4gZnVuZ3NpIG1vZGUoKSkuDQoNCmBgYHtyfQ0KbG9hbi50cmFpbiRHZW5kZXJbaXMubmEobG9hbi50cmFpbiRHZW5kZXIpXSA8LSAgTW9kZShsb2FuLnRyYWluJEdlbmRlcikNCmxvYW4udHJhaW4kTWFycmllZFtpcy5uYShsb2FuLnRyYWluJE1hcnJpZWQpXSA8LSBNb2RlKGxvYW4udHJhaW4kTWFycmllZCkNCmxvYW4udHJhaW4kRGVwZW5kZW50c1tpcy5uYShsb2FuLnRyYWluJERlcGVuZGVudHMpXSA8LSAgTW9kZShsb2FuLnRyYWluJERlcGVuZGVudHMpDQpsb2FuLnRyYWluJENyZWRpdF9IaXN0b3J5W2lzLm5hKGxvYW4udHJhaW4kQ3JlZGl0X0hpc3RvcnkpXSA8LSBNb2RlKGxvYW4udHJhaW4kQ3JlZGl0X0hpc3RvcnkpDQpgYGANCg0KYGBge3J9DQpsb2FuLnRyYWluJExvYW5BbW91bnRbaXMubmEobG9hbi50cmFpbiRMb2FuQW1vdW50KV0gPC0gbWVhbihsb2FuLnRyYWluJExvYW5BbW91bnQsIG5hLnJtID0gVCkNCmxvYW4udHJhaW4kTG9hbl9BbW91bnRfVGVybVtpcy5uYShsb2FuLnRyYWluJExvYW5fQW1vdW50X1Rlcm0pXSA8LSBtZWFuKGxvYW4udHJhaW4kTG9hbl9BbW91bnRfVGVybSwgbmEucm0gPSBUKQ0Kc3VtbWFyeShsb2FuLnRyYWluKQ0KbmEub21pdChsb2FuLnRyYWluKQ0KYGBgDQoNCiMjIFBlcmlrc2EgRGF0YSBEdXBsaWthdA0KDQpgYGB7cn0NCnN1bShkdXBsaWNhdGVkKGxvYW4udHJhaW4pKQ0KYGBgDQpUaWRhayBhZGEgZGF0YSBkdXBsaWthdA0KDQojIyBQZW1pc2FoYW4gRGF0YSBLYXRlZ29yaSBkYW4gTnVtZXJpaw0KDQpLYXRlZ29yaQ0KYGBge3J9DQpDYXRfZGF0YSA8LSBsb2FuLnRyYWluJT4lIGRwbHlyOjpzZWxlY3RfaWYoaXMuZmFjdG9yKQ0KbmFtZXMoQ2F0X2RhdGEpDQpgYGANCg0KTnVtZXJpaw0KYGBge3J9DQpOdW1fZGF0YSA8LSBsb2FuLnRyYWluJT4lIGRwbHlyOjpzZWxlY3RfaWYoaXMubnVtZXJpYykNCm5hbWVzKE51bV9kYXRhKQ0KYGBgDQoNCiMjIFBlbmFuZ2FuYW4gRGF0YSBOdW1lcmlrDQojIyBQZW5nYW5hbm4gRGF0YSBQZW5jaWxhbg0KDQojIyBQZW5hbmdhbmFuIERhdGEgS2F0ZWdvcmlrYWwNCg0KDQojIFR1Z2FzIDINCg0KTGFrdWthbiBQcm9zZXMgVmlzdWFsaXNhc2kgRGF0YSBkZW5nYW4gbWVuZ2d1bmFrYW4gUiBkYW4gUHl0aG9uIGRlbmdhbiBiZWJlcmFwYSBsYW5na2FoIGJlcmlrdXQ6DQoNCiMjIFZpc3VhbGlzYXNpIFVuaXZhcmlhYmVsDQoNCiMjIyBDYXRlZ29yaWNhbCANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHNjYWxlcykgDQpgYGANCg0KKipHZW5kZXIqKg0KDQpgYGB7cn0NCnBsb3RkYXRhIDwtIGxvYW4udHJhaW4gJT4lIA0KICBjb3VudChHZW5kZXIpICU+JQ0KICBtdXRhdGUocGN0ID0gbiAvIHN1bShuKSwNCiAgICAgICAgIHBjdGxhYmVsID0gcGFzdGUwKHJvdW5kKHBjdCoxMDApLCAiJSIpKQ0KDQpnZ3Bsb3QocGxvdGRhdGEsIA0KICAgICAgIGFlcyh4ID0gcmVvcmRlcihHZW5kZXIsIC1wY3QpLA0KICAgICAgICAgICB5ID0gcGN0KSkgKyANCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIA0KICAgICAgICAgIGNvbG9yID0gImF6dXJlNCIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBjdGxhYmVsKSwgDQogICAgICAgICAgICB2anVzdCA9IC0wLjI1KSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdXNlIGEgbWluaW1hbCB0aGVtZQ0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudCkgKw0KICBsYWJzKHggPSAiR2VuZGVyIiwgDQogICAgICAgeSA9ICJQZXJjZW50IiwgDQogICAgICAgdGl0bGUgID0gIkxvYW4gYnkgZ2VuZGVyIikNCg0KYGBgDQoNCg0KKipNYXJyaWVkKiogDQoNCmBgYHtyfQ0KcGxvdGRhdGEgPC0gbG9hbi50cmFpbiAlPiUgDQogIGNvdW50KE1hcnJpZWQpICU+JQ0KICBtdXRhdGUocGN0ID0gbiAvIHN1bShuKSwNCiAgICAgICAgIHBjdGxhYmVsID0gcGFzdGUwKHJvdW5kKHBjdCoxMDApLCAiJSIpKQ0KDQpnZ3Bsb3QocGxvdGRhdGEsIA0KICAgICAgIGFlcyh4ID0gcmVvcmRlcihNYXJyaWVkLCAtcGN0KSwNCiAgICAgICAgICAgeSA9IHBjdCkpICsgDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCANCiAgICAgICAgICBjb2xvciA9ICJhenVyZTQiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwY3RsYWJlbCksIA0KICAgICAgICAgICAgdmp1c3QgPSAtMC4yNSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBhIG1pbmltYWwgdGhlbWUNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnQpICsNCiAgbGFicyh4ID0gIk1hcnJpZWQiLCANCiAgICAgICB5ID0gIlBlcmNlbnQiLCANCiAgICAgICB0aXRsZSAgPSAiTG9hbiBieSBtYXJyaWVkIikNCg0KYGBgDQoNCioqRGVwZW5kZW50cyoqIA0KDQpgYGB7cn0NCnBsb3RkYXRhIDwtIGxvYW4udHJhaW4gJT4lIA0KICBjb3VudChEZXBlbmRlbnRzKSAlPiUNCiAgbXV0YXRlKHBjdCA9IG4gLyBzdW0obiksDQogICAgICAgICBwY3RsYWJlbCA9IHBhc3RlMChyb3VuZChwY3QqMTAwKSwgIiUiKSkNCg0KZ2dwbG90KHBsb3RkYXRhLCANCiAgICAgICBhZXMoeCA9IHJlb3JkZXIoRGVwZW5kZW50cywgLXBjdCksDQogICAgICAgICAgIHkgPSBwY3QpKSArIA0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgDQogICAgICAgICAgY29sb3IgPSAiYXp1cmU0IikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGN0bGFiZWwpLCANCiAgICAgICAgICAgIHZqdXN0ID0gLTAuMjUpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB1c2UgYSBtaW5pbWFsIHRoZW1lDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50KSArDQogIGxhYnMoeCA9ICJEZXBlbmRlbnRzIiwgDQogICAgICAgeSA9ICJQZXJjZW50IiwgDQogICAgICAgdGl0bGUgID0gIkxvYW4gYnkgRGVwZW5kZW50cyIpDQoNCmBgYA0KDQoqKkVkdWNhdGlvbioqIA0KDQpgYGB7cn0NCnBsb3RkYXRhIDwtIGxvYW4udHJhaW4gJT4lIA0KICBjb3VudChFZHVjYXRpb24pICU+JQ0KICBtdXRhdGUocGN0ID0gbiAvIHN1bShuKSwNCiAgICAgICAgIHBjdGxhYmVsID0gcGFzdGUwKHJvdW5kKHBjdCoxMDApLCAiJSIpKQ0KDQpnZ3Bsb3QocGxvdGRhdGEsIA0KICAgICAgIGFlcyh4ID0gcmVvcmRlcihFZHVjYXRpb24sIC1wY3QpLA0KICAgICAgICAgICB5ID0gcGN0KSkgKyANCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIA0KICAgICAgICAgIGNvbG9yID0gImF6dXJlNCIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBjdGxhYmVsKSwgDQogICAgICAgICAgICB2anVzdCA9IC0wLjI1KSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdXNlIGEgbWluaW1hbCB0aGVtZQ0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudCkgKw0KICBsYWJzKHggPSAiRWR1Y2F0aW9uIiwgDQogICAgICAgeSA9ICJQZXJjZW50IiwgDQogICAgICAgdGl0bGUgID0gIkxvYW4gYnkgRWR1Y2F0aW9uIikNCg0KYGBgDQoNCioqU2VsZl9lbXBsb3llZCoqDQoNCg0KYGBge3J9DQpwbG90ZGF0YSA8LSBsb2FuLnRyYWluICU+JSANCiAgY291bnQoU2VsZl9FbXBsb3llZCkgJT4lDQogIG11dGF0ZShwY3QgPSBuIC8gc3VtKG4pLA0KICAgICAgICAgcGN0bGFiZWwgPSBwYXN0ZTAocm91bmQocGN0KjEwMCksICIlIikpDQoNCmdncGxvdChwbG90ZGF0YSwgDQogICAgICAgYWVzKHggPSByZW9yZGVyKFNlbGZfRW1wbG95ZWQsIC1wY3QpLA0KICAgICAgICAgICB5ID0gcGN0KSkgKyANCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIA0KICAgICAgICAgIGNvbG9yID0gImF6dXJlNCIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBjdGxhYmVsKSwgDQogICAgICAgICAgICB2anVzdCA9IC0wLjI1KSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdXNlIGEgbWluaW1hbCB0aGVtZQ0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudCkgKw0KICBsYWJzKHggPSAiU2VsZl9FbXBsb3llZCIsIA0KICAgICAgIHkgPSAiUGVyY2VudCIsIA0KICAgICAgIHRpdGxlICA9ICJMb2FuIGJ5IFNlbGZfRW1wbG95ZWQiKQ0KDQpgYGANCg0KKipMb2FuX0Ftb3VudF9UZXJtKioNCg0KDQpgYGB7cn0NCnBsb3RkYXRhIDwtIGxvYW4udHJhaW4gJT4lIA0KICBjb3VudChMb2FuX0Ftb3VudF9UZXJtKSAlPiUNCiAgbXV0YXRlKHBjdCA9IG4gLyBzdW0obiksDQogICAgICAgICBwY3RsYWJlbCA9IHBhc3RlMChyb3VuZChwY3QqMTAwKSwgIiUiKSkNCg0KZ2dwbG90KHBsb3RkYXRhLCANCiAgICAgICBhZXMoeCA9IHJlb3JkZXIoTG9hbl9BbW91bnRfVGVybSwgLXBjdCksDQogICAgICAgICAgIHkgPSBwY3QpKSArIA0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgDQogICAgICAgICAgY29sb3IgPSAiYXp1cmU0IikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGN0bGFiZWwpLCANCiAgICAgICAgICAgIHZqdXN0ID0gLTAuMjUpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50KSArDQogIGxhYnMoeCA9ICJMb2FuX0Ftb3VudF9UZXJtIiwgDQogICAgICAgeSA9ICJQZXJjZW50IiwgDQogICAgICAgdGl0bGUgID0gIkxvYW4gYnkgTG9hbl9BbW91bnRfVGVybSIpDQoNCmBgYA0KDQoqKkNyZWRpdF9IaXN0b3J5KioNCg0KYGBge3J9DQpwbG90ZGF0YSA8LSBsb2FuLnRyYWluICU+JSANCiAgY291bnQoQ3JlZGl0X0hpc3RvcnkpICU+JQ0KICBtdXRhdGUocGN0ID0gbiAvIHN1bShuKSwNCiAgICAgICAgIHBjdGxhYmVsID0gcGFzdGUwKHJvdW5kKHBjdCoxMDApLCAiJSIpKQ0KDQpnZ3Bsb3QocGxvdGRhdGEsIA0KICAgICAgIGFlcyh4ID0gcmVvcmRlcihDcmVkaXRfSGlzdG9yeSwgLXBjdCksDQogICAgICAgICAgIHkgPSBwY3QpKSArIA0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgDQogICAgICAgICAgY29sb3IgPSAiYXp1cmU0IikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGN0bGFiZWwpLCANCiAgICAgICAgICAgIHZqdXN0ID0gLTAuMjUpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50KSArDQogIGxhYnMoeCA9ICJDcmVkaXRfSGlzdG9yeSIsIA0KICAgICAgIHkgPSAiUGVyY2VudCIsIA0KICAgICAgIHRpdGxlICA9ICJMb2FuIGJ5IENyZWRpdF9IaXN0b3J5IikNCg0KYGBgDQoNCg0KKipQcm9wZXJ0eV9BcmVhKioNCg0KYGBge3J9DQpwbG90ZGF0YSA8LSBsb2FuLnRyYWluICU+JSANCiAgY291bnQoUHJvcGVydHlfQXJlYSkgJT4lDQogIG11dGF0ZShwY3QgPSBuIC8gc3VtKG4pLA0KICAgICAgICAgcGN0bGFiZWwgPSBwYXN0ZTAocm91bmQocGN0KjEwMCksICIlIikpDQoNCmdncGxvdChwbG90ZGF0YSwgDQogICAgICAgYWVzKHggPSByZW9yZGVyKFByb3BlcnR5X0FyZWEsIC1wY3QpLA0KICAgICAgICAgICB5ID0gcGN0KSkgKyANCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIA0KICAgICAgICAgIGNvbG9yID0gImF6dXJlNCIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBjdGxhYmVsKSwgDQogICAgICAgICAgICB2anVzdCA9IC0wLjI1KSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudCkgKw0KICBsYWJzKHggPSAiUHJvcGVydHlfQXJlYSIsIA0KICAgICAgIHkgPSAiUGVyY2VudCIsIA0KICAgICAgIHRpdGxlICA9ICJMb2FuIGJ5IFByb3BlcnR5X0FyZWEiKQ0KDQpgYGANCg0KIyMjIE51bWVyaWNhbCANCg0KKipBcHBsaWNhbnRJbmNvbWUqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCBhZXMoeCA9IEFwcGxpY2FudEluY29tZSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oZmlsbCA9ICJjb3JuZmxvd2VyYmx1ZSIsIA0KICAgICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsYmlucyA9IDIwKSArIA0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBhIG1pbmltYWwgdGhlbWUNCiAgbGFicyh0aXRsZT0iTG9hbiBieSBBcHBsaWNhbnRJbmNvbWUiLA0KICAgICAgIHggPSAiQXBwbGljYW50SW5jb21lIikNCmBgYA0KDQoqKkNvYXBwbGljYW50SW5jb21lKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgYWVzKHggPSBDb2FwcGxpY2FudEluY29tZSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oZmlsbCA9ICJjb3JuZmxvd2VyYmx1ZSIsIA0KICAgICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsYmlucyA9IDIwKSArIA0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBhIG1pbmltYWwgdGhlbWUNCiAgbGFicyh0aXRsZT0iTG9hbiBieSBDb2FwcGxpY2FudEluY29tZSIsDQogICAgICAgeCA9ICJDb2FwcGxpY2FudEluY29tZSIpDQpgYGANCg0KKipMb2FuQW1vdW50KioNCg0KYGBge3J9DQoNCmdncGxvdChsb2FuLnRyYWluLCBhZXMoeCA9IExvYW5BbW91bnQpKSArDQogIGdlb21faGlzdG9ncmFtKGZpbGwgPSAiY29ybmZsb3dlcmJsdWUiLCANCiAgICAgICAgICAgICAgICAgY29sb3IgPSAid2hpdGUiLGJpbnMgPSAyMCkgKyANCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB1c2UgYSBtaW5pbWFsIHRoZW1lDQogIGxhYnModGl0bGU9IkxvYW4gYnkgTG9hbkFtb3VudCIsDQogICAgICAgeCA9ICJMb2FuQW1vdW50IikNCg0KYGBgDQoNCiMjIFZpc3VhbGlzYXNpIEJpdmFyaWFiZWwNCg0KIyMjIENhdGVnb3JpY2FsIHZzIENhdGVnb3JpY2FsDQoNCioqR2VuZGVyIHZzIE1hcnJpZWQqKg0KDQpgYGB7cn0NCg0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gR2VuZGVyLCANCiAgICAgICAgICAgZmlsbCA9IE1hcnJpZWQpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqR2VuZGVyIHZzIEVkdWNhdGlvbioqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gR2VuZGVyLCANCiAgICAgICAgICAgZmlsbCA9IEVkdWNhdGlvbikpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBsYWJzKHkgPSAiUHJvcG9ydGlvbiIpDQpgYGANCg0KKipHZW5kZXIgdnMgRGVwZW5kZW50cyoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gR2VuZGVyLCANCiAgICAgICAgICAgZmlsbCA9IERlcGVuZGVudHMpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqR2VuZGVyIHZzIFNlbGZfRW1wbG95ZWQqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IEdlbmRlciwgDQogICAgICAgICAgIGZpbGwgPSBTZWxmX0VtcGxveWVkKSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKkdlbmRlciB2cyBsb2FuQW1vdW50VGVybSoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gR2VuZGVyLCANCiAgICAgICAgICAgZmlsbCA9IExvYW5fQW1vdW50X1Rlcm0pKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqR2VuZGVyIHZzIGNyZWRpdF9oaXN0b3J5KioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBHZW5kZXIsIA0KICAgICAgICAgICBmaWxsID0gQ3JlZGl0X0hpc3RvcnkpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqR2VuZGVyIHZzIFByb3BlcnR5QXJlYSoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gR2VuZGVyLCANCiAgICAgICAgICAgZmlsbCA9IFByb3BlcnR5X0FyZWEpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqR2VuZGVyIHZzIExvYW5TdGF0dXMqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IEdlbmRlciwgDQogICAgICAgICAgIGZpbGwgPSBMb2FuX1N0YXR1cyApKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqTWFycmllZCB2cyBEZXBlbmRlbnRzKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBNYXJyaWVkLCANCiAgICAgICAgICAgZmlsbCA9IEVkdWNhdGlvbikpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBsYWJzKHkgPSAiUHJvcG9ydGlvbiIpDQpgYGANCg0KKipNYXJyaWVkIHZzIEVkdWNhdGlvbioqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gTWFycmllZCwgDQogICAgICAgICAgIGZpbGwgPSBEZXBlbmRlbnRzKSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKk1hcnJpZWQgdnMgU2VsZl9FbXBsb3llZCoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gTWFycmllZCwgDQogICAgICAgICAgIGZpbGwgPSBTZWxmX0VtcGxveWVkKSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKk1hcnJpZWQgdnMgbG9hbkFtb3VudFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IE1hcnJpZWQsIA0KICAgICAgICAgICBmaWxsID0gTG9hbl9BbW91bnRfVGVybSkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBsYWJzKHkgPSAiUHJvcG9ydGlvbiIpDQpgYGANCg0KKipNYXJyaWVkIHZzIGNyZWRpdF9oaXN0b3J5KioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBNYXJyaWVkLCANCiAgICAgICAgICAgZmlsbCA9IENyZWRpdF9IaXN0b3J5KSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKk1hcnJpZWQgdnMgUHJvcGVydHlBcmVhKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBNYXJyaWVkLCANCiAgICAgICAgICAgZmlsbCA9IFByb3BlcnR5X0FyZWEpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqTWFycmllZCB2cyBMb2FuU3RhdHVzKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBNYXJyaWVkLCANCiAgICAgICAgICAgZmlsbCA9IExvYW5fU3RhdHVzICkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBsYWJzKHkgPSAiUHJvcG9ydGlvbiIpDQpgYGANCg0KKipEZXBlbmRlbnRzIHZzIEVkdWNhdGlvbioqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gRGVwZW5kZW50cywgDQogICAgICAgICAgIGZpbGwgPSBFZHVjYXRpb24pKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqRGVwZW5kZW50cyB2cyBTZWxmX0VtcGxveWVkKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBEZXBlbmRlbnRzLCANCiAgICAgICAgICAgZmlsbCA9IFNlbGZfRW1wbG95ZWQpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqRGVwZW5kZW50cyB2cyBsb2FuQW1vdW50VGVybSoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gRGVwZW5kZW50cywgDQogICAgICAgICAgIGZpbGwgPSBMb2FuX0Ftb3VudF9UZXJtKSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKkRlcGVuZGVudHMgdnMgY3JlZGl0X2hpc3RvcnkqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IERlcGVuZGVudHMsIA0KICAgICAgICAgICBmaWxsID0gQ3JlZGl0X0hpc3RvcnkpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqRGVwZW5kZW50cyB2cyBQcm9wZXJ0eUFyZWEqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IERlcGVuZGVudHMsIA0KICAgICAgICAgICBmaWxsID0gUHJvcGVydHlfQXJlYSkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBsYWJzKHkgPSAiUHJvcG9ydGlvbiIpDQpgYGANCg0KKipEZXBlbmRlbnRzIHZzIExvYW5TdGF0dXMqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IERlcGVuZGVudHMsIA0KICAgICAgICAgICBmaWxsID0gTG9hbl9TdGF0dXMgKSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKkVkdWNhdGlvbiB2cyBTZWxmX0VtcGxveWVkKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBFZHVjYXRpb24sIA0KICAgICAgICAgICBmaWxsID0gU2VsZl9FbXBsb3llZCkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBsYWJzKHkgPSAiUHJvcG9ydGlvbiIpDQpgYGANCg0KKipFZHVjYXRpb24gdnMgbG9hbkFtb3VudFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IEVkdWNhdGlvbiwgDQogICAgICAgICAgIGZpbGwgPSBMb2FuX0Ftb3VudF9UZXJtKSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKkVkdWNhdGlvbiB2cyBjcmVkaXRfaGlzdG9yeSoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gRWR1Y2F0aW9uLCANCiAgICAgICAgICAgZmlsbCA9IENyZWRpdF9IaXN0b3J5KSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKkVkdWNhdGlvbiB2cyBQcm9wZXJ0eUFyZWEqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IEVkdWNhdGlvbiwgDQogICAgICAgICAgIGZpbGwgPSBQcm9wZXJ0eV9BcmVhKSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKkVkdWNhdGlvbiB2cyBMb2FuU3RhdHVzKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBFZHVjYXRpb24sIA0KICAgICAgICAgICBmaWxsID0gTG9hbl9TdGF0dXMgKSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKlNlbGZfRW1wbG95ZWQgdnMgbG9hbkFtb3VudFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IFNlbGZfRW1wbG95ZWQsIA0KICAgICAgICAgICBmaWxsID0gTG9hbl9BbW91bnRfVGVybSkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBsYWJzKHkgPSAiUHJvcG9ydGlvbiIpDQpgYGANCg0KKipTZWxmX0VtcGxveWVkIHZzIGNyZWRpdF9oaXN0b3J5KioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBTZWxmX0VtcGxveWVkLCANCiAgICAgICAgICAgZmlsbCA9IENyZWRpdF9IaXN0b3J5KSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKlNlbGZfRW1wbG95ZWQgdnMgUHJvcGVydHlBcmVhKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBTZWxmX0VtcGxveWVkLCANCiAgICAgICAgICAgZmlsbCA9IFByb3BlcnR5X0FyZWEpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqU2VsZl9FbXBsb3llZCB2cyBMb2FuU3RhdHVzKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBTZWxmX0VtcGxveWVkLCANCiAgICAgICAgICAgZmlsbCA9IExvYW5fU3RhdHVzICkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBsYWJzKHkgPSAiUHJvcG9ydGlvbiIpDQpgYGANCg0KKipMb2FuX0Ftb3VudF9UZXJtIHZzIGNyZWRpdF9oaXN0b3J5KioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgZmlsbCA9IENyZWRpdF9IaXN0b3J5KSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKkxvYW5fQW1vdW50X1Rlcm0gdnMgUHJvcGVydHlBcmVhKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgZmlsbCA9IFByb3BlcnR5X0FyZWEpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqTG9hbl9BbW91bnRfVGVybSB2cyBMb2FuU3RhdHVzKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgZmlsbCA9IExvYW5fU3RhdHVzICkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBsYWJzKHkgPSAiUHJvcG9ydGlvbiIpDQpgYGANCg0KKipDcmVkaXRfSGlzdG9yeSB2cyBQcm9wZXJ0eUFyZWEqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IENyZWRpdF9IaXN0b3J5LCANCiAgICAgICAgICAgZmlsbCA9IFByb3BlcnR5X0FyZWEpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCioqQ3JlZGl0X0hpc3RvcnkgdnMgTG9hblN0YXR1cyoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gQ3JlZGl0X0hpc3RvcnksIA0KICAgICAgICAgICBmaWxsID0gTG9hbl9TdGF0dXMgKSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIikNCmBgYA0KDQoqKlByb3BlcnR5X0FyZWEgdnMgTG9hblN0YXR1cyoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gUHJvcGVydHlfQXJlYSwgDQogICAgICAgICAgIGZpbGwgPSBMb2FuX1N0YXR1cyApKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iKQ0KYGBgDQoNCg0KIyMjIE51bWVyaWNhbCB2cyBOdW1lcmljYWwNCg0KKipBcHBsaWNhbnRJbmNvbWUgdnMgQ29hcHBsaWNhbnRJbmNvbWUqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IEFwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIHkgPSBDb2FwcGxpY2FudEluY29tZSkpICsNCiAgZ2VvbV9wb2ludChjb2xvcj0iY29ybmZsb3dlcmJsdWUiLCANCiAgICAgICAgICAgICBzaXplID0gMS41LCANCiAgICAgICAgICAgICBhbHBoYT0uOCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWwgPSBzY2FsZXM6OmRvbGxhciwgDQogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsIDUwMDAwKSkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDQwMDAwLCA1MDAwKSwgDQogICAgICAgICAgICAgICAgICAgICBsaW1pdHM9YygwLCA1MDAwMCkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB1c2UgYSBtaW5pbWFsIHRoZW1lDQogIGxhYnMoeCA9ICJBcHBsaWNhbnRJbmNvbWUiLA0KICAgICAgIHkgPSAiIiwNCiAgICAgICB0aXRsZSA9ICJBcHBsaWNhbnRJbmNvbWUgdnMgQ29hcHBsaWNhbnRJbmNvbWUiKQ0KYGBgDQoNCioqQ29hcHBsaWNhbnRJbmNvbWUgdnMgTG9hbkFtb3VudCoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gQ29hcHBsaWNhbnRJbmNvbWUsIA0KICAgICAgICAgICB5ID0gTG9hbkFtb3VudCkpICsNCiAgZ2VvbV9wb2ludChjb2xvcj0iY29ybmZsb3dlcmJsdWUiLCANCiAgICAgICAgICAgICBzaXplID0gMS41LCANCiAgICAgICAgICAgICBhbHBoYT0uOCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWwgPSBzY2FsZXM6OmRvbGxhciwgDQogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsIDgwMCkpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCA0MDAwMCwgNTAwMCksIA0KICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwgNTAwMDApKSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdXNlIGEgbWluaW1hbCB0aGVtZQ0KICBsYWJzKHggPSAiQ29hcHBsaWNhbnRJbmNvbWUiLA0KICAgICAgIHkgPSAiIiwNCiAgICAgICB0aXRsZSA9ICJDb2FwcGxpY2FudEluY29tZSB2cyBMb2FuQW1vdW50IikNCmBgYA0KDQoqKkFwcGxpY2FudEluY29tZSB2cyBMb2FuQW1vdW50KioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBBcHBsaWNhbnRJbmNvbWUsIA0KICAgICAgICAgICB5ID0gTG9hbkFtb3VudCkpICsNCiAgZ2VvbV9wb2ludChjb2xvcj0iY29ybmZsb3dlcmJsdWUiLCANCiAgICAgICAgICAgICBzaXplID0gMSwgDQogICAgICAgICAgICAgYWxwaGE9LjgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVsID0gc2NhbGVzOjpkb2xsYXIsIA0KICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLCA4MDApKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNDAwMDAsIDUwMDApLCANCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cz1jKDAsIDUwMDAwKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBhIG1pbmltYWwgdGhlbWUNCiAgbGFicyh4ID0gIkFwcGxpY2FudEluY29tZSIsDQogICAgICAgeSA9ICIiLA0KICAgICAgIHRpdGxlID0gIkFwcGxpY2FudEluY29tZSB2cyBMb2FuQW1vdW50IikNCmBgYA0KDQojIyMgQ2F0ZWdvcmljYWwgdnMgTnVtZXJpY2FsDQoNCioqQXBwbGljYW50SW5jb21lIHZzIEdlbmRlcioqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gQXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgZmlsbCA9IEdlbmRlcikpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC40KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiQXBwbGljYW50IEluY29tZSBieSBHZW5kZXIiKQ0KYGBgDQoNCioqQXBwbGljYW50SW5jb21lIHZzIE1hcnJpZWQqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IEFwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIGZpbGwgPSBNYXJyaWVkKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjQpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJBcHBsaWNhbnQgSW5jb21lIGJ5IE1hcnJpZWQiKQ0KYGBgDQoNCg0KKipBcHBsaWNhbnRJbmNvbWUgdnMgRGVwZW5kZW50cyoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gQXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgZmlsbCA9IERlcGVuZGVudHMpKSArDQogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkFwcGxpY2FudCBJbmNvbWUgYnkgRGVwZW5kZW50cyIpDQpgYGANCg0KKipBcHBsaWNhbnRJbmNvbWUgdnMgRWR1Y2F0aW9uKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBBcHBsaWNhbnRJbmNvbWUsIA0KICAgICAgICAgICBmaWxsID0gRWR1Y2F0aW9uKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjQpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJBcHBsaWNhbnQgSW5jb21lIGJ5IEVkdWNhdGlvbiIpDQpgYGANCg0KKipBcHBsaWNhbnRJbmNvbWUgdnMgU2VsZl9FbXBsb3llZCoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gQXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgZmlsbCA9IFNlbGZfRW1wbG95ZWQpKSArDQogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkFwcGxpY2FudCBJbmNvbWUgYnkgU2VsZl9FbXBsb3llZCIpDQpgYGANCg0KKipBcHBsaWNhbnRJbmNvbWUgdnMgTG9hbl9BbW91bnRfVGVybSoqDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3JpZGdlcykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRvIGhhbmRsZSBvdmVybGFwcGluZyB2aXN1bGl6YXRpb24NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IEFwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIHkgPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgZmlsbCA9IExvYW5fQW1vdW50X1Rlcm0pKSArDQogIGdlb21fZGVuc2l0eV9yaWRnZXMoYWxwaGEgPSAwLjcpICsgDQogIHRoZW1lX3JpZGdlcygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYGBgDQoNCioqQXBwbGljYW50SW5jb21lIHZzIENyZWRpdF9IaXN0b3J5KioNCg0KYGBge3J9DQpsaWJyYXJ5KGdncmlkZ2VzKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdG8gaGFuZGxlIG92ZXJsYXBwaW5nIHZpc3VsaXphdGlvbg0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gQXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgeSA9IENyZWRpdF9IaXN0b3J5LCANCiAgICAgICAgICAgZmlsbCA9IENyZWRpdF9IaXN0b3J5KSkgKw0KICBnZW9tX2RlbnNpdHlfcmlkZ2VzKGFscGhhID0gMC43KSArIA0KICB0aGVtZV9yaWRnZXMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0KDQoqKkFwcGxpY2FudEluY29tZSB2cyBQcm9wZXJ0eV9BcmVhKioNCg0KYGBge3J9DQpsaWJyYXJ5KGdncmlkZ2VzKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdG8gaGFuZGxlIG92ZXJsYXBwaW5nIHZpc3VsaXphdGlvbg0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gQXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgeSA9IFByb3BlcnR5X0FyZWEsIA0KICAgICAgICAgICBmaWxsID0gUHJvcGVydHlfQXJlYSkpICsNCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhhbHBoYSA9IDAuNykgKyANCiAgdGhlbWVfcmlkZ2VzKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpgYGANCg0KKipBcHBsaWNhbnRJbmNvbWUgdnMgTG9hbl9TdGF0dXMqKg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dyaWRnZXMpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0byBoYW5kbGUgb3ZlcmxhcHBpbmcgdmlzdWxpemF0aW9uDQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBBcHBsaWNhbnRJbmNvbWUsIA0KICAgICAgICAgICB5ID0gTG9hbl9TdGF0dXMsIA0KICAgICAgICAgICBmaWxsID0gTG9hbl9TdGF0dXMpKSArDQogIGdlb21fZGVuc2l0eV9yaWRnZXMoYWxwaGEgPSAwLjcpICsgDQogIHRoZW1lX3JpZGdlcygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYGBgDQoNCioqQ29hcHBsaWNhbnRJbmNvbWUgdnMgR2VuZGVyKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBDb2FwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIGZpbGwgPSBHZW5kZXIpKSArDQogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkNvYXBwbGljYW50SW5jb21lIGJ5IEdlbmRlciIpDQpgYGANCg0KKipDb2FwcGxpY2FudEluY29tZSB2cyBNYXJyaWVkKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBDb2FwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIGZpbGwgPSBNYXJyaWVkKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjQpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJDb2FwcGxpY2FudEluY29tZSBieSBNYXJyaWVkIikNCmBgYA0KDQoNCioqQ29hcHBsaWNhbnRJbmNvbWUgdnMgRGVwZW5kZW50cyoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gQ29hcHBsaWNhbnRJbmNvbWUsIA0KICAgICAgICAgICBmaWxsID0gRGVwZW5kZW50cykpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC40KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiQ29hcHBsaWNhbnRJbmNvbWUgYnkgRGVwZW5kZW50cyIpDQpgYGANCg0KKipDb2FwcGxpY2FudEluY29tZSB2cyBFZHVjYXRpb24qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IENvYXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgZmlsbCA9IEVkdWNhdGlvbikpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC40KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiQ29hcHBsaWNhbnRJbmNvbWUgYnkgRWR1Y2F0aW9uIikNCmBgYA0KDQoqKkNvYXBwbGljYW50SW5jb21lIHZzIFNlbGZfRW1wbG95ZWQqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IEFwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIGZpbGwgPSBTZWxmX0VtcGxveWVkKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjQpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJDb2FwcGxpY2FudEluY29tZSBieSBTZWxmX0VtcGxveWVkIikNCmBgYA0KDQoqKkNvYXBwbGljYW50SW5jb21lIHZzIExvYW5fQW1vdW50X1Rlcm0qKg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dyaWRnZXMpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0byBoYW5kbGUgb3ZlcmxhcHBpbmcgdmlzdWxpemF0aW9uDQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBDb2FwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIHkgPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgZmlsbCA9IExvYW5fQW1vdW50X1Rlcm0pKSArDQogIGdlb21fZGVuc2l0eV9yaWRnZXMoYWxwaGEgPSAwLjcpICsgDQogIHRoZW1lX3JpZGdlcygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYGBgDQoNCioqQ29hcHBsaWNhbnRJbmNvbWUgdnMgQ3JlZGl0X0hpc3RvcnkqKg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dyaWRnZXMpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0byBoYW5kbGUgb3ZlcmxhcHBpbmcgdmlzdWxpemF0aW9uDQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBDb2FwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIHkgPSBDcmVkaXRfSGlzdG9yeSwgDQogICAgICAgICAgIGZpbGwgPSBDcmVkaXRfSGlzdG9yeSkpICsNCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhhbHBoYSA9IDAuNykgKyANCiAgdGhlbWVfcmlkZ2VzKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpgYGANCg0KKipDb2FwcGxpY2FudEluY29tZSB2cyBQcm9wZXJ0eV9BcmVhKioNCg0KYGBge3J9DQpsaWJyYXJ5KGdncmlkZ2VzKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdG8gaGFuZGxlIG92ZXJsYXBwaW5nIHZpc3VsaXphdGlvbg0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gQ29hcHBsaWNhbnRJbmNvbWUsIA0KICAgICAgICAgICB5ID0gUHJvcGVydHlfQXJlYSwgDQogICAgICAgICAgIGZpbGwgPSBQcm9wZXJ0eV9BcmVhKSkgKw0KICBnZW9tX2RlbnNpdHlfcmlkZ2VzKGFscGhhID0gMC43KSArIA0KICB0aGVtZV9yaWRnZXMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0KDQoqKkNvYXBwbGljYW50SW5jb21lIHZzIExvYW5fU3RhdHVzKioNCg0KYGBge3J9DQpsaWJyYXJ5KGdncmlkZ2VzKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdG8gaGFuZGxlIG92ZXJsYXBwaW5nIHZpc3VsaXphdGlvbg0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gQ29hcHBsaWNhbnRJbmNvbWUsIA0KICAgICAgICAgICB5ID0gTG9hbl9TdGF0dXMsIA0KICAgICAgICAgICBmaWxsID0gTG9hbl9TdGF0dXMpKSArDQogIGdlb21fZGVuc2l0eV9yaWRnZXMoYWxwaGEgPSAwLjcpICsgDQogIHRoZW1lX3JpZGdlcygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYGBgDQoNCioqTG9hbkFtb3VudCB2cyBHZW5kZXIqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5BbW91bnQsIA0KICAgICAgICAgICBmaWxsID0gR2VuZGVyKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjQpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJMb2FuQW1vdW50IGJ5IEdlbmRlciIpDQpgYGANCg0KKipMb2FuQW1vdW50IHZzIE1hcnJpZWQqKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5BbW91bnQsIA0KICAgICAgICAgICBmaWxsID0gTWFycmllZCkpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC40KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiTG9hbkFtb3VudCBieSBNYXJyaWVkIikNCmBgYA0KDQoNCioqTG9hbkFtb3VudCB2cyBEZXBlbmRlbnRzKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuQW1vdW50LCANCiAgICAgICAgICAgZmlsbCA9IERlcGVuZGVudHMpKSArDQogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkxvYW5BbW91bnQgYnkgRGVwZW5kZW50cyIpDQpgYGANCg0KKipMb2FuQW1vdW50IHZzIEVkdWNhdGlvbioqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gTG9hbkFtb3VudCwgDQogICAgICAgICAgIGZpbGwgPSBFZHVjYXRpb24pKSArDQogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkxvYW5BbW91bnQgYnkgRWR1Y2F0aW9uIikNCmBgYA0KDQoqKkxvYW5BbW91bnQgdnMgU2VsZl9FbXBsb3llZCoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gTG9hbkFtb3VudCwgDQogICAgICAgICAgIGZpbGwgPSBTZWxmX0VtcGxveWVkKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjQpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJMb2FuQW1vdW50IGJ5IFNlbGZfRW1wbG95ZWQiKQ0KYGBgDQoNCioqTG9hbkFtb3VudCB2cyBMb2FuX0Ftb3VudF9UZXJtKioNCg0KYGBge3J9DQpsaWJyYXJ5KGdncmlkZ2VzKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdG8gaGFuZGxlIG92ZXJsYXBwaW5nIHZpc3VsaXphdGlvbg0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gTG9hbkFtb3VudCwgDQogICAgICAgICAgIHkgPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgZmlsbCA9IExvYW5fQW1vdW50X1Rlcm0pKSArDQogIGdlb21fZGVuc2l0eV9yaWRnZXMoYWxwaGEgPSAwLjcpICsgDQogIHRoZW1lX3JpZGdlcygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYGBgDQoNCioqTG9hbkFtb3VudCB2cyBDcmVkaXRfSGlzdG9yeSoqDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3JpZGdlcykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRvIGhhbmRsZSBvdmVybGFwcGluZyB2aXN1bGl6YXRpb24NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IENvYXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgeSA9IENyZWRpdF9IaXN0b3J5LCANCiAgICAgICAgICAgZmlsbCA9IENyZWRpdF9IaXN0b3J5KSkgKw0KICBnZW9tX2RlbnNpdHlfcmlkZ2VzKGFscGhhID0gMC43KSArIA0KICB0aGVtZV9yaWRnZXMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0KDQoqKkxvYW5BbW91bnQgdnMgUHJvcGVydHlfQXJlYSoqDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3JpZGdlcykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRvIGhhbmRsZSBvdmVybGFwcGluZyB2aXN1bGl6YXRpb24NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5BbW91bnQsIA0KICAgICAgICAgICB5ID0gUHJvcGVydHlfQXJlYSwgDQogICAgICAgICAgIGZpbGwgPSBQcm9wZXJ0eV9BcmVhKSkgKw0KICBnZW9tX2RlbnNpdHlfcmlkZ2VzKGFscGhhID0gMC43KSArIA0KICB0aGVtZV9yaWRnZXMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0KDQoqKkxvYW5BbW91bnQgdnMgTG9hbl9TdGF0dXMqKg0KYGBge3J9DQpsaWJyYXJ5KGdncmlkZ2VzKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdG8gaGFuZGxlIG92ZXJsYXBwaW5nIHZpc3VsaXphdGlvbg0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gTG9hbkFtb3VudCwgDQogICAgICAgICAgIHkgPSBMb2FuX1N0YXR1cywgDQogICAgICAgICAgIGZpbGwgPSBMb2FuX1N0YXR1cykpICsNCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhhbHBoYSA9IDAuNykgKyANCiAgdGhlbWVfcmlkZ2VzKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpgYGANCg0KKiBWaXN1YWxpc2FzaSBNdWx0aXZhcmlhYmVsDQoNCg0KIyMgVmlzdWFsaXNhc2kgTXVsdGl2YXJpYWJlbA0KDQoNCioqQXBwbGljYW50SW5jb21lIGJ5IE1hcnJpZWQsIEdlbmRlciwgYW5kIExvYW4gVGVybSoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gTG9hbl9BbW91bnRfVGVybSwgDQogICAgICAgICAgIHkgPSBBcHBsaWNhbnRJbmNvbWUsIA0KICAgICAgICAgICBjb2xvciA9IE1hcnJpZWQsIA0KICAgICAgICAgICBzaGFwZSA9IEdlbmRlcikpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAuNikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkFwcGxpY2FudEluY29tZSBieSBNYXJyaWVkLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0iKQ0KYGBgDQoNCioqQXBwbGljYW50SW5jb21lIGJ5IEVkdWNhdGlvbiwgR2VuZGVyLCBhbmQgTG9hbiBUZXJtKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgeSA9IEFwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIGNvbG9yID0gRWR1Y2F0aW9uLCANCiAgICAgICAgICAgc2hhcGUgPSBHZW5kZXIpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFscGhhID0gLjYpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJBcHBsaWNhbnRJbmNvbWUgYnkgTWFycmllZCwgR2VuZGVyLCBhbmQgTG9hbiBUZXJtIikNCmBgYA0KDQoqKkFwcGxpY2FudEluY29tZSBieSBEZXBlbmRlbnRzLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5fQW1vdW50X1Rlcm0sIA0KICAgICAgICAgICB5ID0gQXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgY29sb3IgPSBEZXBlbmRlbnRzLCANCiAgICAgICAgICAgc2hhcGUgPSBHZW5kZXIpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFscGhhID0gLjYpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJBcHBsaWNhbnRJbmNvbWUgYnkgRGVwZW5kZW50cywgR2VuZGVyLCBhbmQgTG9hbiBUZXJtIikNCmBgYA0KDQoqKkFwcGxpY2FudEluY29tZSBieSBTZWxmX0VtcGxveWVkLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5fQW1vdW50X1Rlcm0sIA0KICAgICAgICAgICB5ID0gQXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgY29sb3IgPSBTZWxmX0VtcGxveWVkLCANCiAgICAgICAgICAgc2hhcGUgPSBHZW5kZXIpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFscGhhID0gLjYpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJBcHBsaWNhbnRJbmNvbWUgYnkgU2VsZl9FbXBsb3llZCwgR2VuZGVyLCBhbmQgTG9hbiBUZXJtIikNCmBgYA0KDQoqKkFwcGxpY2FudEluY29tZSBieSBDcmVkaXRfSGlzdG9yeSwgR2VuZGVyLCBhbmQgTG9hbiBUZXJtKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgeSA9IEFwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIGNvbG9yID0gQ3JlZGl0X0hpc3RvcnksIA0KICAgICAgICAgICBzaGFwZSA9IEdlbmRlcikpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAuNikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkFwcGxpY2FudEluY29tZSBieSBDcmVkaXRfSGlzdG9yeSwgR2VuZGVyLCBhbmQgTG9hbiBUZXJtIikNCmBgYA0KDQoqKkFwcGxpY2FudEluY29tZSBieSBQcm9wZXJ0eV9BcmVhLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5fQW1vdW50X1Rlcm0sIA0KICAgICAgICAgICB5ID0gQXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgY29sb3IgPSBQcm9wZXJ0eV9BcmVhLCANCiAgICAgICAgICAgc2hhcGUgPSBHZW5kZXIpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFscGhhID0gLjYpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJBcHBsaWNhbnRJbmNvbWUgYnkgUHJvcGVydHlfQXJlYSwgR2VuZGVyLCBhbmQgTG9hbiBUZXJtIikNCmBgYA0KDQoqKkFwcGxpY2FudEluY29tZSBieSBMb2FuX1N0YXR1cywgR2VuZGVyLCBhbmQgTG9hbiBUZXJtKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgeSA9IEFwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIGNvbG9yID0gTG9hbl9TdGF0dXMsIA0KICAgICAgICAgICBzaGFwZSA9IEdlbmRlcikpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAuNikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkFwcGxpY2FudEluY29tZSBieSBMb2FuX1N0YXR1cywgR2VuZGVyLCBhbmQgTG9hbiBUZXJtIikNCmBgYA0KDQoqKkNvYXBwbGljYW50SW5jb21lIGJ5IE1hcnJpZWQsIEdlbmRlciwgYW5kIExvYW4gVGVybSoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gTG9hbl9BbW91bnRfVGVybSwgDQogICAgICAgICAgIHkgPSBDb2FwcGxpY2FudEluY29tZSwgDQogICAgICAgICAgIGNvbG9yID0gTWFycmllZCwgDQogICAgICAgICAgIHNoYXBlID0gR2VuZGVyKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzLCBhbHBoYSA9IC42KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiQ29hcHBsaWNhbnRJbmNvbWUgYnkgTWFycmllZCwgR2VuZGVyLCBhbmQgTG9hbiBUZXJtIikNCmBgYA0KDQoqKkNvYXBwbGljYW50SW5jb21lIGJ5IEVkdWNhdGlvbiwgR2VuZGVyLCBhbmQgTG9hbiBUZXJtKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgeSA9IENvYXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgY29sb3IgPSBFZHVjYXRpb24sIA0KICAgICAgICAgICBzaGFwZSA9IEdlbmRlcikpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAuNikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkNvYXBwbGljYW50SW5jb21lIGJ5IE1hcnJpZWQsIEdlbmRlciwgYW5kIExvYW4gVGVybSIpDQpgYGANCg0KKipDb2FwcGxpY2FudEluY29tZSBieSBEZXBlbmRlbnRzLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5fQW1vdW50X1Rlcm0sIA0KICAgICAgICAgICB5ID0gQ29hcHBsaWNhbnRJbmNvbWUsIA0KICAgICAgICAgICBjb2xvciA9IERlcGVuZGVudHMsIA0KICAgICAgICAgICBzaGFwZSA9IEdlbmRlcikpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAuNikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkNvYXBwbGljYW50SW5jb21lIGJ5IERlcGVuZGVudHMsIEdlbmRlciwgYW5kIExvYW4gVGVybSIpDQpgYGANCg0KKipDb2FwcGxpY2FudEluY29tZSBieSBTZWxmX0VtcGxveWVkLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5fQW1vdW50X1Rlcm0sIA0KICAgICAgICAgICB5ID0gQ29hcHBsaWNhbnRJbmNvbWUsIA0KICAgICAgICAgICBjb2xvciA9IFNlbGZfRW1wbG95ZWQsIA0KICAgICAgICAgICBzaGFwZSA9IEdlbmRlcikpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAuNikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkNvYXBwbGljYW50SW5jb21lIGJ5IFNlbGZfRW1wbG95ZWQsIEdlbmRlciwgYW5kIExvYW4gVGVybSIpDQpgYGANCg0KKipDb2FwcGxpY2FudEluY29tZSBieSBDcmVkaXRfSGlzdG9yeSwgR2VuZGVyLCBhbmQgTG9hbiBUZXJtKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgeSA9IENvYXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgY29sb3IgPSBDcmVkaXRfSGlzdG9yeSwgDQogICAgICAgICAgIHNoYXBlID0gR2VuZGVyKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzLCBhbHBoYSA9IC42KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiQ29hcHBsaWNhbnRJbmNvbWUgYnkgQ3JlZGl0X0hpc3RvcnksIEdlbmRlciwgYW5kIExvYW4gVGVybSIpDQpgYGANCg0KKipDb2FwcGxpY2FudEluY29tZSBieSBQcm9wZXJ0eV9BcmVhLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5fQW1vdW50X1Rlcm0sIA0KICAgICAgICAgICB5ID0gQ29hcHBsaWNhbnRJbmNvbWUsIA0KICAgICAgICAgICBjb2xvciA9IFByb3BlcnR5X0FyZWEsIA0KICAgICAgICAgICBzaGFwZSA9IEdlbmRlcikpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAuNikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkNvYXBwbGljYW50SW5jb21lIGJ5IFByb3BlcnR5X0FyZWEsIEdlbmRlciwgYW5kIExvYW4gVGVybSIpDQpgYGANCg0KKipDb2FwcGxpY2FudEluY29tZSBieSBMb2FuX1N0YXR1cywgR2VuZGVyLCBhbmQgTG9hbiBUZXJtKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgeSA9IENvYXBwbGljYW50SW5jb21lLCANCiAgICAgICAgICAgY29sb3IgPSBMb2FuX1N0YXR1cywgDQogICAgICAgICAgIHNoYXBlID0gR2VuZGVyKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzLCBhbHBoYSA9IC42KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiQ29hcHBsaWNhbnRJbmNvbWUgYnkgTG9hbl9TdGF0dXMsIEdlbmRlciwgYW5kIExvYW4gVGVybSIpDQpgYGANCg0KKipMb2FuQW1vdW50IGJ5IE1hcnJpZWQsIEdlbmRlciwgYW5kIExvYW4gVGVybSoqDQoNCmBgYHtyfQ0KZ2dwbG90KGxvYW4udHJhaW4sIA0KICAgICAgIGFlcyh4ID0gTG9hbl9BbW91bnRfVGVybSwgDQogICAgICAgICAgIHkgPSBMb2FuQW1vdW50LCANCiAgICAgICAgICAgY29sb3IgPSBNYXJyaWVkLCANCiAgICAgICAgICAgc2hhcGUgPSBHZW5kZXIpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFscGhhID0gLjYpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJMb2FuQW1vdW50IGJ5IE1hcnJpZWQsIEdlbmRlciwgYW5kIExvYW4gVGVybSIpDQpgYGANCg0KKipMb2FuQW1vdW50IGJ5IEVkdWNhdGlvbiwgR2VuZGVyLCBhbmQgTG9hbiBUZXJtKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgeSA9IExvYW5BbW91bnQsIA0KICAgICAgICAgICBjb2xvciA9IEVkdWNhdGlvbiwgDQogICAgICAgICAgIHNoYXBlID0gR2VuZGVyKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzLCBhbHBoYSA9IC42KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiTG9hbkFtb3VudCBieSBNYXJyaWVkLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0iKQ0KYGBgDQoNCioqTG9hbkFtb3VudCBieSBEZXBlbmRlbnRzLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5fQW1vdW50X1Rlcm0sIA0KICAgICAgICAgICB5ID0gTG9hbkFtb3VudCwgDQogICAgICAgICAgIGNvbG9yID0gRGVwZW5kZW50cywgDQogICAgICAgICAgIHNoYXBlID0gR2VuZGVyKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzLCBhbHBoYSA9IC42KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiTG9hbkFtb3VudCBieSBEZXBlbmRlbnRzLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0iKQ0KYGBgDQoNCioqTG9hbkFtb3VudCBieSBTZWxmX0VtcGxveWVkLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5fQW1vdW50X1Rlcm0sIA0KICAgICAgICAgICB5ID0gTG9hbkFtb3VudCwgDQogICAgICAgICAgIGNvbG9yID0gU2VsZl9FbXBsb3llZCwgDQogICAgICAgICAgIHNoYXBlID0gR2VuZGVyKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzLCBhbHBoYSA9IC42KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiTG9hbkFtb3VudCBieSBTZWxmX0VtcGxveWVkLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0iKQ0KYGBgDQoNCioqTG9hbkFtb3VudCBieSBDcmVkaXRfSGlzdG9yeSwgR2VuZGVyLCBhbmQgTG9hbiBUZXJtKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgeSA9IExvYW5BbW91bnQsIA0KICAgICAgICAgICBjb2xvciA9IENyZWRpdF9IaXN0b3J5LCANCiAgICAgICAgICAgc2hhcGUgPSBHZW5kZXIpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFscGhhID0gLjYpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJMb2FuQW1vdW50IGJ5IENyZWRpdF9IaXN0b3J5LCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0iKQ0KYGBgDQoNCioqTG9hbkFtb3VudCBieSBQcm9wZXJ0eV9BcmVhLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0qKg0KDQpgYGB7cn0NCmdncGxvdChsb2FuLnRyYWluLCANCiAgICAgICBhZXMoeCA9IExvYW5fQW1vdW50X1Rlcm0sIA0KICAgICAgICAgICB5ID0gTG9hbkFtb3VudCwgDQogICAgICAgICAgIGNvbG9yID0gUHJvcGVydHlfQXJlYSwgDQogICAgICAgICAgIHNoYXBlID0gR2VuZGVyKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzLCBhbHBoYSA9IC42KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiTG9hbkFtb3VudCBieSBQcm9wZXJ0eV9BcmVhLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0iKQ0KYGBgDQoNCioqTG9hbkFtb3VudCBieSBMb2FuX1N0YXR1cywgR2VuZGVyLCBhbmQgTG9hbiBUZXJtKioNCg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgDQogICAgICAgYWVzKHggPSBMb2FuX0Ftb3VudF9UZXJtLCANCiAgICAgICAgICAgeSA9IExvYW5BbW91bnQsIA0KICAgICAgICAgICBjb2xvciA9IExvYW5fU3RhdHVzLCANCiAgICAgICAgICAgc2hhcGUgPSBHZW5kZXIpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFscGhhID0gLjYpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJMb2FuQW1vdW50IGJ5IExvYW5fU3RhdHVzLCBHZW5kZXIsIGFuZCBMb2FuIFRlcm0iKQ0KYGBgDQoNCg0KDQojIFR1Z2FzIDMNCg0KTGFrdWthbiBwcm9zZXMgYW5hbGlzYSBkYXRhIHNlY2FyYSBkZXNrcmlwdGlmIG1lbmdndW5ha2FuIFIgZGFuIFB5dGhvbiBkZW5nYW4gYmViZXJhcGEgbGFuZ2thaCBiZXJpa3V0Og0KDQojIyBLdWFsaXRhdGlmDQojIyMgS2F0ZWdvcmkgVW5pdmFyaWF0DQpMb2FuX0lEICAgICAgICAgICA8ZmN0PiBMUDAwMTAwMiwgTFAwMDEwMDMsIExQMDAxMDA1LCBMUDAwMTAwNiwgTFAwMDEwMDgsIExQMDAxMDExLH4NCiQgR2VuZGVyICAgICAgICAgICAgPGZjdD4gTWFsZSwgTWFsZSwgTWFsZSwgTWFsZSwgTWFsZSwgTWFsZSwgTWFsZSwgTWFsZSwgTWFsZSwgTWFsZSx+DQokIE1hcnJpZWQgICAgICAgICAgIDxmY3Q+IE5vLCBZZXMsIFllcywgWWVzLCBObywgWWVzLCBZZXMsIFllcywgWWVzLCBZZXMsIFllcywgWWVzLCBZfg0KJCBEZXBlbmRlbnRzICAgICAgICA8ZmN0PiAwLCAxLCAwLCAwLCAwLCAyLCAwLCAzKywgMiwgMSwgMiwgMiwgMiwgMCwgMiwgMCwgMSwgMCwgMCwgMH4NCiQgRWR1Y2F0aW9uICAgICAgICAgPGZjdD4gR3JhZHVhdGUsIEdyYWR1YXRlLCBHcmFkdWF0ZSwgTm90IEdyYWR1YXRlLCBHcmFkdWF0ZSwgR3JhZHV+DQokIFNlbGZfRW1wbG95ZWQgICAgIDxmY3Q+IE5vLCBObywgWWVzLCBObywgTm8sIFllcywgTm8sIE5vLCBObywgTm8sIE5vLCBOQSwgTm8sIE5vLCBOfg0KJCBBcHBsaWNhbnRJbmNvbWUgICA8aW50PiA1ODQ5LCA0NTgzLCAzMDAwLCAyNTgzLCA2MDAwLCA1NDE3LCAyMzMzLCAzMDM2LCA0MDA2LCAxMjg0MX4NCiQgQ29hcHBsaWNhbnRJbmNvbWUgPGRibD4gMCwgMTUwOCwgMCwgMjM1OCwgMCwgNDE5NiwgMTUxNiwgMjUwNCwgMTUyNiwgMTA5NjgsIDcwMCwgMTh+DQokIExvYW5BbW91bnQgICAgICAgIDxpbnQ+IE5BLCAxMjgsIDY2LCAxMjAsIDE0MSwgMjY3LCA5NSwgMTU4LCAxNjgsIDM0OSwgNzAsIDEwOSwgMjAwfg0KJCBMb2FuX0Ftb3VudF9UZXJtICA8aW50PiAzNjAsIDM2MCwgMzYwLCAzNjAsIDM2MCwgMzYwLCAzNjAsIDM2MCwgMzYwLCAzNjAsIDM2MCwgMzYwLH4NCiQgQ3JlZGl0X0hpc3RvcnkgICAgPGludD4gMSwgMSwgMSwgMSwgMSwgMSwgMSwgMCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgTkEsIDAsIDEsIDF+DQokIFByb3BlcnR5X0FyZWEgICAgIDxmY3Q+IFVyYmFuLCBSdXJhbCwgVXJiYW4sIFVyYmFuLCBVcmJhbiwgVXJiYW4sIFVyYmFuLCBTZW1pdXJiYW4sfg0KJCBMb2FuX1N0YXR1cyAgICAgICA8ZmN0PiBZLCBOLCBZLCBZLCBZLCBZLCBZLCBOLCBZLCBOLCBZLCBZLCBZLCBOLCBZLCBZLCBZLCBOLCBOLCBZLH4NCmBgYHtyfQ0KQ2F0MSA8LSB0YWJsZShsb2FuLnRyYWluJEdlbmRlcikNCkNhdDENCkNhdDIgPC0gdGFibGUobG9hbi50cmFpbiRNYXJyaWVkKQ0KQ2F0Mg0KQ2F0MyA8LSB0YWJsZShsb2FuLnRyYWluJERlcGVuZGVudHMpDQpDYXQzDQpDYXQ0IDwtIHRhYmxlKGxvYW4udHJhaW4kRWR1Y2F0aW9uKQ0KQ2F0NA0KQ2F0NSA8LSB0YWJsZShsb2FuLnRyYWluJFNlbGZfRW1wbG95ZWQpDQpDYXQ1DQpDYXQ2IDwtIHRhYmxlKGxvYW4udHJhaW4kTG9hbl9BbW91bnRfVGVybSkNCkNhdDYNCkNhdDcgPC0gdGFibGUobG9hbi50cmFpbiRDcmVkaXRfSGlzdG9yeSkNCkNhdDcNCkNhdDggPC0gdGFibGUobG9hbi50cmFpbiRQcm9wZXJ0eV9BcmVhKQ0KQ2F0OA0KQ2F0OSA8LSB0YWJsZShsb2FuLnRyYWluJExvYW5fU3RhdHVzKQ0KQ2F0OQ0KYGBgDQoNCiMjIyBLYXRlZ29yaSBCaXZhcmlhdA0KYGBge3J9DQpiaWNhdDE8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoR2VuZGVyLCBNYXJyaWVkKSAlPiV0YWJsZSgpDQpiaWNhdDENCmJpY2F0MjwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChHZW5kZXIsIERlcGVuZGVudHMpICU+JXRhYmxlKCkNCmJpY2F0Mg0KYmljYXQzPC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KEdlbmRlciwgRWR1Y2F0aW9uKSAlPiV0YWJsZSgpDQpiaWNhdDMNCmJpY2F0NDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChHZW5kZXIsIFNlbGZfRW1wbG95ZWQpICU+JXRhYmxlKCkNCmJpY2F0NA0KYmljYXQ1PC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KEdlbmRlciwgTG9hbl9BbW91bnRfVGVybSkgJT4ldGFibGUoKQ0KYmljYXQ1DQpiaWNhdDY8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoR2VuZGVyLCBDcmVkaXRfSGlzdG9yeSkgJT4ldGFibGUoKQ0KYmljYXQ2DQpiaWNhdDc8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoR2VuZGVyLCBQcm9wZXJ0eV9BcmVhKSAlPiV0YWJsZSgpDQpiaWNhdDcNCmJpY2F0ODwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChHZW5kZXIsIExvYW5fU3RhdHVzKSAlPiV0YWJsZSgpDQpiaWNhdDgNCg0KYmljYXQ5PC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KE1hcnJpZWQsIERlcGVuZGVudHMpICU+JXRhYmxlKCkNCmJpY2F0OQ0KYmljYXQxMDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChNYXJyaWVkLCBFZHVjYXRpb24pICU+JXRhYmxlKCkNCmJpY2F0MTANCmJpY2F0MTE8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoTWFycmllZCwgU2VsZl9FbXBsb3llZCkgJT4ldGFibGUoKQ0KYmljYXQxMQ0KYmljYXQxMjwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChNYXJyaWVkLCBMb2FuX0Ftb3VudF9UZXJtKSAlPiV0YWJsZSgpDQpiaWNhdDEyDQpiaWNhdDEzPC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KE1hcnJpZWQsIENyZWRpdF9IaXN0b3J5KSAlPiV0YWJsZSgpDQpiaWNhdDEzDQpiaWNhdDE0PC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KE1hcnJpZWQsIFByb3BlcnR5X0FyZWEpICU+JXRhYmxlKCkNCmJpY2F0MTQNCmJpY2F0MTU8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoTWFycmllZCwgTG9hbl9TdGF0dXMpICU+JXRhYmxlKCkNCmJpY2F0MTUNCg0KYmljYXQxNjwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChEZXBlbmRlbnRzLCBFZHVjYXRpb24pICU+JXRhYmxlKCkNCmJpY2F0MTYNCmJpY2F0MTc8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoRGVwZW5kZW50cywgU2VsZl9FbXBsb3llZCkgJT4ldGFibGUoKQ0KYmljYXQxNw0KYmljYXQxODwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChEZXBlbmRlbnRzLCBMb2FuX0Ftb3VudF9UZXJtKSAlPiV0YWJsZSgpDQpiaWNhdDE4DQpiaWNhdDE5PC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KERlcGVuZGVudHMsIENyZWRpdF9IaXN0b3J5KSAlPiV0YWJsZSgpDQpiaWNhdDE5DQpiaWNhdDIwPC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KERlcGVuZGVudHMsIFByb3BlcnR5X0FyZWEpICU+JXRhYmxlKCkNCmJpY2F0MjANCmJpY2F0MjE8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoRGVwZW5kZW50cywgTG9hbl9TdGF0dXMpICU+JXRhYmxlKCkNCmJpY2F0MjENCg0KYmljYXQyMjwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChFZHVjYXRpb24sIFNlbGZfRW1wbG95ZWQpICU+JXRhYmxlKCkNCmJpY2F0MjINCmJpY2F0MjM8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoRWR1Y2F0aW9uLCBMb2FuX0Ftb3VudF9UZXJtKSAlPiV0YWJsZSgpDQpiaWNhdDIzDQpiaWNhdDI1PC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KEVkdWNhdGlvbiwgQ3JlZGl0X0hpc3RvcnkpICU+JXRhYmxlKCkNCmJpY2F0MjUNCmJpY2F0MjY8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoRWR1Y2F0aW9uLCBQcm9wZXJ0eV9BcmVhKSAlPiV0YWJsZSgpDQpiaWNhdDI2DQpiaWNhdDI3PC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KEVkdWNhdGlvbiwgTG9hbl9TdGF0dXMpICU+JXRhYmxlKCkNCmJpY2F0MjcNCg0KYmljYXQyODwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChTZWxmX0VtcGxveWVkLCBMb2FuX0Ftb3VudF9UZXJtKSAlPiV0YWJsZSgpDQpiaWNhdDI4DQpiaWNhdDI5PC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KFNlbGZfRW1wbG95ZWQsIENyZWRpdF9IaXN0b3J5KSAlPiV0YWJsZSgpDQpiaWNhdDI5DQpiaWNhdDMwPC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KFNlbGZfRW1wbG95ZWQsIFByb3BlcnR5X0FyZWEpICU+JXRhYmxlKCkNCmJpY2F0MzANCmJpY2F0MzE8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoU2VsZl9FbXBsb3llZCwgTG9hbl9TdGF0dXMpICU+JXRhYmxlKCkNCmJpY2F0MzENCg0KYmljYXQzMjwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChMb2FuX0Ftb3VudF9UZXJtLCBDcmVkaXRfSGlzdG9yeSkgJT4ldGFibGUoKQ0KYmljYXQzMg0KYmljYXQzMzwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChMb2FuX0Ftb3VudF9UZXJtLCBQcm9wZXJ0eV9BcmVhKSAlPiV0YWJsZSgpDQpiaWNhdDMzDQpiaWNhdDM0PC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KExvYW5fQW1vdW50X1Rlcm0sIExvYW5fU3RhdHVzKSAlPiV0YWJsZSgpDQpiaWNhdDM0DQoNCmJpY2F0MzU8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoQ3JlZGl0X0hpc3RvcnksIFByb3BlcnR5X0FyZWEpICU+JXRhYmxlKCkNCmJpY2F0MzUNCmJpY2F0MzY8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoQ3JlZGl0X0hpc3RvcnksIExvYW5fU3RhdHVzKSAlPiV0YWJsZSgpDQpiaWNhdDM2DQoNCmJpY2F0Mzc8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoUHJvcGVydHlfQXJlYSwgTG9hbl9TdGF0dXMpICU+JXRhYmxlKCkNCmJpY2F0MzcNCmBgYA0KDQojIyMgS2F0ZWdvcmkgTXVsdGl2YXJpYXQNCmBgYHtyfQ0KbXVsY2F0MSA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoR2VuZGVyLCBNYXJyaWVkLCBEZXBlbmRlbnRzKSAlPiUgZnRhYmxlKCkNCm11bGNhdDENCm11bGNhdDIgPC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KEdlbmRlciwgTWFycmllZCwgRWR1Y2F0aW9uKSAlPiUgZnRhYmxlKCkNCm11bGNhdDINCm11bGNhdDMgPC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KEdlbmRlciwgTWFycmllZCwgU2VsZl9FbXBsb3llZCkgJT4lIGZ0YWJsZSgpDQptdWxjYXQzDQptdWxjYXQ0IDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChHZW5kZXIsIE1hcnJpZWQsIExvYW5fQW1vdW50X1Rlcm0pICU+JSBmdGFibGUoKQ0KbXVsY2F0NA0KbXVsY2F0NSA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoR2VuZGVyLCBNYXJyaWVkLCBDcmVkaXRfSGlzdG9yeSkgJT4lIGZ0YWJsZSgpDQptdWxjYXQ1DQptdWxjYXQ2IDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChHZW5kZXIsIE1hcnJpZWQsIFByb3BlcnR5X0FyZWEpICU+JSBmdGFibGUoKQ0KbXVsY2F0Ng0KbXVsY2F0NyA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoR2VuZGVyLCBNYXJyaWVkLCBMb2FuX1N0YXR1cykgJT4lIGZ0YWJsZSgpDQptdWxjYXQ3DQoNCm11bGNhdDggPC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KE1hcnJpZWQsIERlcGVuZGVudHMsIEVkdWNhdGlvbikgJT4lIGZ0YWJsZSgpDQptdWxjYXQ4DQptdWxjYXQ5IDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChNYXJyaWVkLCBEZXBlbmRlbnRzLCBTZWxmX0VtcGxveWVkKSAlPiUgZnRhYmxlKCkNCm11bGNhdDkNCm11bGNhdDExIDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChNYXJyaWVkLCBEZXBlbmRlbnRzLCBMb2FuX0Ftb3VudF9UZXJtKSAlPiUgZnRhYmxlKCkNCm11bGNhdDExDQptdWxjYXQxMiA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoTWFycmllZCwgRGVwZW5kZW50cywgQ3JlZGl0X0hpc3RvcnkpICU+JSBmdGFibGUoKQ0KbXVsY2F0MTINCm11bGNhdDEzIDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChNYXJyaWVkLCBEZXBlbmRlbnRzLCBQcm9wZXJ0eV9BcmVhKSAlPiUgZnRhYmxlKCkNCm11bGNhdDEzDQptdWxjYXQxNCA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoTWFycmllZCwgRGVwZW5kZW50cywgTG9hbl9TdGF0dXMpICU+JSBmdGFibGUoKQ0KbXVsY2F0MTQNCg0KbXVsY2F0MTUgPC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KCBEZXBlbmRlbnRzLCBTZWxmX0VtcGxveWVkLCBMb2FuX0Ftb3VudF9UZXJtKSAlPiUgZnRhYmxlKCkNCm11bGNhdDE1DQptdWxjYXQxNiA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoRGVwZW5kZW50cywgU2VsZl9FbXBsb3llZCwgQ3JlZGl0X0hpc3RvcnkpICU+JSBmdGFibGUoKQ0KbXVsY2F0MTYNCm11bGNhdDE3IDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChEZXBlbmRlbnRzLCBTZWxmX0VtcGxveWVkLCBQcm9wZXJ0eV9BcmVhKSAlPiUgZnRhYmxlKCkNCm11bGNhdDE3DQptdWxjYXQxOCA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoRGVwZW5kZW50cywgU2VsZl9FbXBsb3llZCwgTG9hbl9TdGF0dXMpICU+JSBmdGFibGUoKQ0KbXVsY2F0MTgNCm11bGNhdDI1IDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChEZXBlbmRlbnRzLCBTZWxmX0VtcGxveWVkLCBNYXJyaWVkKSAlPiUgZnRhYmxlKCkNCm11bGNhdDI1DQptdWxjYXQyNiA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoRGVwZW5kZW50cywgU2VsZl9FbXBsb3llZCwgR2VuZGVyKSAlPiUgZnRhYmxlKCkNCm11bGNhdDI2DQptdWxjYXQyNyA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoRGVwZW5kZW50cywgU2VsZl9FbXBsb3llZCwgRWR1Y2F0aW9uKSAlPiUgZnRhYmxlKCkNCm11bGNhdDI3DQoNCm11bGNhdDE5IDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChTZWxmX0VtcGxveWVkLCBDcmVkaXRfSGlzdG9yeSwgRWR1Y2F0aW9uKSAlPiUgZnRhYmxlKCkNCm11bGNhdDE5DQptdWxjYXQyMCA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoU2VsZl9FbXBsb3llZCwgQ3JlZGl0X0hpc3RvcnksIFByb3BlcnR5X0FyZWEpICU+JSBmdGFibGUoKQ0KbXVsY2F0MjANCm11bGNhdDIxIDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChTZWxmX0VtcGxveWVkLCBDcmVkaXRfSGlzdG9yeSwgTG9hbl9TdGF0dXMpICU+JSBmdGFibGUoKQ0KbXVsY2F0MjENCm11bGNhdDIyIDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChTZWxmX0VtcGxveWVkLCBDcmVkaXRfSGlzdG9yeSwgTWFycmllZCkgJT4lIGZ0YWJsZSgpDQptdWxjYXQyMg0KbXVsY2F0MjMgPC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KFNlbGZfRW1wbG95ZWQsIENyZWRpdF9IaXN0b3J5LCBHZW5kZXIpICU+JSBmdGFibGUoKQ0KbXVsY2F0MjMNCm11bGNhdDI0IDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChTZWxmX0VtcGxveWVkLCBDcmVkaXRfSGlzdG9yeSwgTG9hbl9BbW91bnRfVGVybSkgJT4lIGZ0YWJsZSgpDQptdWxjYXQyNA0KDQptdWxjYXQyOCA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoQ3JlZGl0X0hpc3RvcnksIFByb3BlcnR5X0FyZWEsIEVkdWNhdGlvbikgJT4lIGZ0YWJsZSgpDQptdWxjYXQyOA0KbXVsY2F0MjkgPC0gbG9hbi50cmFpbiAlPiVkcGx5cjo6c2VsZWN0KENyZWRpdF9IaXN0b3J5LCBQcm9wZXJ0eV9BcmVhLCBEZXBlbmRlbnRzKSAlPiUgZnRhYmxlKCkNCm11bGNhdDI5DQptdWxjYXQzMCA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoQ3JlZGl0X0hpc3RvcnksIFByb3BlcnR5X0FyZWEsIExvYW5fU3RhdHVzKSAlPiUgZnRhYmxlKCkNCm11bGNhdDMwDQptdWxjYXQzMSA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoQ3JlZGl0X0hpc3RvcnksIFByb3BlcnR5X0FyZWEsIE1hcnJpZWQpICU+JSBmdGFibGUoKQ0KbXVsY2F0MzENCm11bGNhdDMyIDwtIGxvYW4udHJhaW4gJT4lZHBseXI6OnNlbGVjdChDcmVkaXRfSGlzdG9yeSwgUHJvcGVydHlfQXJlYSwgR2VuZGVyKSAlPiUgZnRhYmxlKCkNCm11bGNhdDMyDQptdWxjYXQzMyA8LSBsb2FuLnRyYWluICU+JWRwbHlyOjpzZWxlY3QoQ3JlZGl0X0hpc3RvcnksIFByb3BlcnR5X0FyZWEsIExvYW5fQW1vdW50X1Rlcm0pICU+JSBmdGFibGUoKQ0KbXVsY2F0Mw0KDQpgYGANCg0KDQoNCk1lbWFoYW1pIGRpc3RyaWJ1c2kgZGF0YSB0ZXJoYWRhcCBzdGF0dXMgcGluamFtYW4gKHlhaXR1IHZhcmlhYmVsIHRhcmdldCkgbWVtdmlzdWFsaXNhc2lrYW4gdmFyaWFiZWwga2F0ZWdvcmkgZGFuIHN0YXR1cyBwaW5qYW1hbg0KDQpgYGB7cn0NCnRyYWluLm5ldyA8LSBsb2FuLnRyYWluICU+JSANCiAgZmlsdGVyKExvYW5fU3RhdHVzIT0idGVzdCIpICU+JQ0KICBtdXRhdGUoTG9hbl9TdGF0dXM9aWZlbHNlKExvYW5fU3RhdHVzPT0iWSIsMSwwKSkNCg0KdHJhaW4ubmV3ICU+JSANCiAgZ3JvdXBfYnkoTG9hbl9TdGF0dXMpICU+JSANCiAgc3VtbWFyaXNlKG4uY291bnQ9bigpKSAlPiUNCiAgbXV0YXRlKHBlcmNlbnQ9cm91bmQobi5jb3VudC9ucm93KHRyYWluLm5ldykqMTAwLDEpLA0KICAgICAgICAgTG9hbl9TdGF0dXM9YXMuZmFjdG9yKExvYW5fU3RhdHVzKSkgJT4lDQogIHVuZ3JvdXAoKSAlPiUNCiAgZ2dwbG90KGFlcyh4PUxvYW5fU3RhdHVzLCB5PXBlcmNlbnQsIGZpbGw9TG9hbl9TdGF0dXMpKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikrDQogIHRoZW1lX2Vjb25vbWlzdF93aGl0ZSgpDQpgYGANCg0KYGBge3J9DQojIGJ1YXQgZnVuZ3NpIHVudHVrIG1lbXBsb3QgYmFueWFrIHZhcmlhYmVsIGthdGVnb3JpIGRhbiBiYWdhaW1hbmEgbWVyZWthIGJlcmludGVyYWtzaSBkZW5nYW4gdmFyaWFiZWwgdGFyZ2V0DQoNClBsb3RTaW1wbGUgPC0gZnVuY3Rpb24oZGF0YWZyYW1lLHgseSl7DQogIGFhYSA8LSBlbnF1byh4KQ0KICBiYmIgPC0gZW5xdW8oeSkNCiAgZGF0YWZyYW1lICU+JQ0KICAgIGZpbHRlcighaXMubmEoISEgYWFhKSwgIWlzLm5hKCEhIGJiYikpICAlPiUNCiAgICBncm91cF9ieSghISBhYWEsISEgYmJiKSAlPiUNCiAgICBzdW1tYXJpc2Uobj1uKCkpJT4lDQogICAgbXV0YXRlKHBlcmNlbnQ9bi9ucm93KGRhdGFmcmFtZSkpICU+JQ0KICAgIGdncGxvdChhZXNfKGZpbGw9YWFhLCB5PX5wZXJjZW50LCB4PWJiYikpICsNCiAgICBnZW9tX2Jhcihwb3NpdGlvbj0iZG9kZ2UiLCBzdGF0PSJpZGVudGl0eSIpICsNCiAgICB0aGVtZV9lY29ub21pc3Rfd2hpdGUoKQ0KfQ0KDQp4dmFycyA8LSBsaXN0KGFzLm5hbWUoIk1hcnJpZWQiKSwNCiAgICAgICAgICAgICAgYXMubmFtZSgiQ3JlZGl0X0hpc3RvcnkiKSwNCiAgICAgICAgICAgICAgYXMubmFtZSgiR2VuZGVyIiksDQogICAgICAgICAgICAgIGFzLm5hbWUoIkVkdWNhdGlvbiIpLA0KICAgICAgICAgICAgICBhcy5uYW1lKCJTZWxmX0VtcGxveWVkIiksDQogICAgICAgICAgICAgIGFzLm5hbWUoIlByb3BlcnR5X0FyZWEiKSkNCg0KY2F0LmRhdGEgPC0gbG9hbi50cmFpbiU+JSBkcGx5cjo6c2VsZWN0X2lmKGlzLmZhY3RvcikNCg0KYWxsX3Bsb3RzPC1sYXBwbHkgKHh2YXJzLCBQbG90U2ltcGxlLCBkYXRhZnJhbWU9Y2F0LmRhdGEsIHkgPUxvYW5fU3RhdHVzKQ0KY293cGxvdDo6cGxvdF9ncmlkKHBsb3RsaXN0ID0gYWxsX3Bsb3RzKQ0KYGBgDQoNCjYwJSBkYXJpIGtsaWVuIG1lbWlsaWtpIHBpbmphbWFuIG1lcmVrYSBkaXNldHVqdWkuIERlbWlraWFuIHB1bGEsIDYwJSBrbGllbiB5YW5nIG1lbWlsaWtpIHJpd2F5YXQga3JlZGl0IGtlbXVuZ2tpbmFuIGJlc2FyIGFrYW4gbWVueWV0dWp1aSBwaW5qYW1hbiBtZXJla2EuIEluaSBtZXJ1cGFrYW4gaW5kaWthc2kgc2VqYXJhaCBrcmVkaXQgZGFuIHBlcnNldHVqdWFuIHBpbmphbWFuIG1lbWlsaWtpIGJlYmVyYXBhIGtvcmVsYXNpLiAyOSwyJSBQZW1vaG9uIHlhbmcgdGluZ2dhbCBkaSBhcmVhIHByb3BlcnRpIHNlbWktcGVya290YWFuIGNlbmRlcnVuZyBtZW55ZXR1anVpIHBpbmphbWFuIG1lcmVrYS4gTWVuaWthaCBjZW5kZXJ1bmcgbWVtaWxpa2kgc3RhdHVzIHBpbmphbWFuIGRpc2V0dWp1aQ0KDQojIyBLdWFudGl0YXRpZg0KIyMjIFVuaXZhcmlhdCBudW1lcmlrDQoNCioqTWVhbioqDQpgYGB7cn0NCm1lYW4obG9hbi50cmFpbiRBcHBsaWNhbnRJbmNvbWUpDQptZWFuKGxvYW4udHJhaW4kQ29hcHBsaWNhbnRJbmNvbWUpDQptZWFuKGxvYW4udHJhaW4kTG9hbkFtb3VudCkNCmBgYA0KDQoqKlF1YW50aWxlKioNCmBgYHtyfQ0KcXVhbnRpbGUobG9hbi50cmFpbiRBcHBsaWNhbnRJbmNvbWUpDQpxdWFudGlsZShsb2FuLnRyYWluJENvYXBwbGljYW50SW5jb21lKQ0KcXVhbnRpbGUobG9hbi50cmFpbiRMb2FuQW1vdW50KQ0KYGBgDQoNCioqTWVkaWFuKioNCmBgYHtyfQ0KbWVkaWFuKGxvYW4udHJhaW4kQXBwbGljYW50SW5jb21lKQ0KbWVkaWFuKGxvYW4udHJhaW4kQ29hcHBsaWNhbnRJbmNvbWUpDQptZWRpYW4obG9hbi50cmFpbiRMb2FuQW1vdW50KQ0KYGBgDQoNCg0KKipNb2RlKioNCmBgYHtyfQ0KbW9kZShsb2FuLnRyYWluJEFwcGxpY2FudEluY29tZSkNCm1vZGUobG9hbi50cmFpbiRDb2FwcGxpY2FudEluY29tZSkNCm1vZGUobG9hbi50cmFpbiRMb2FuQW1vdW50KQ0KYGBgDQoNCmBgYHtyfQ0KbG9hbnRyYWluIDwtIGxvYW4udHJhaW4lPiUgZHBseXI6OnNlbGVjdF9pZihpcy5udW1lcmljKQ0Kc3VtbWFyeShsb2FudHJhaW4pDQpgYGANCioqVmFyKioNCmBgYHtyfQ0KdmFyKGxvYW4udHJhaW4kQXBwbGljYW50SW5jb21lKQ0KdmFyKGxvYW4udHJhaW4kQ29hcHBsaWNhbnRJbmNvbWUpDQp2YXIobG9hbi50cmFpbiRMb2FuQW1vdW50KQ0KYGBgDQoNCioqc3RhbmRhciBkZXZpYXRpb24qKg0KYGBge3J9DQpzZChsb2FuLnRyYWluJEFwcGxpY2FudEluY29tZSkNCnNkKGxvYW4udHJhaW4kQ29hcHBsaWNhbnRJbmNvbWUpDQpzZChsb2FuLnRyYWluJExvYW5BbW91bnQpDQpgYGANCg0KKipNZWRpYSBBYnNvbHV0ZSBEZXZpYXRpb24qKg0KYGBge3J9DQptYWQobG9hbi50cmFpbiRBcHBsaWNhbnRJbmNvbWUpDQptYWQobG9hbi50cmFpbiRDb2FwcGxpY2FudEluY29tZSkNCm1hZChsb2FuLnRyYWluJExvYW5BbW91bnQpDQpgYGANCg0KKipJUVIqKg0KYGBge3J9DQpJUVIobG9hbi50cmFpbiRBcHBsaWNhbnRJbmNvbWUpDQpJUVIobG9hbi50cmFpbiRDb2FwcGxpY2FudEluY29tZSkNCklRUihsb2FuLnRyYWluJExvYW5BbW91bnQpDQpgYGANCg0KKipTa2V3bmVzcyoqDQpgYGB7cn0NCmxpYnJhcnkoZTEwNzEpICAgDQpza2V3bmVzcyhsb2FuLnRyYWluJEFwcGxpY2FudEluY29tZSkNCnNrZXduZXNzKGxvYW4udHJhaW4kQ29hcHBsaWNhbnRJbmNvbWUpDQpza2V3bmVzcyhsb2FuLnRyYWluJExvYW5BbW91bnQpDQpgYGANCg0KKipLdXJ0b3NpcyoqDQpgYGB7cn0NCmt1cnRvc2lzKGxvYW4udHJhaW4kQXBwbGljYW50SW5jb21lKQ0Ka3VydG9zaXMobG9hbi50cmFpbiRDb2FwcGxpY2FudEluY29tZSkNCmt1cnRvc2lzKGxvYW4udHJhaW4kTG9hbkFtb3VudCkNCmBgYA0KIyMjIEJpdmFyaWF0IG51bWVyaWsNClotc2NvcmUNCmBgYHtyfQ0KY292KGxvYW4udHJhaW4kQXBwbGljYW50SW5jb21lLGxvYW4udHJhaW4kQ29hcHBsaWNhbnRJbmNvbWUpDQpjb3YobG9hbi50cmFpbiRBcHBsaWNhbnRJbmNvbWUsbG9hbi50cmFpbiRMb2FuQW1vdW50KQ0KY292KGxvYW4udHJhaW4kQ29hcHBsaWNhbnRJbmNvbWUsbG9hbi50cmFpbiRMb2FuQW1vdW50KQ0KDQpjb3IobG9hbi50cmFpbiRBcHBsaWNhbnRJbmNvbWUsbG9hbi50cmFpbiRDb2FwcGxpY2FudEluY29tZSkNCmNvcihsb2FuLnRyYWluJEFwcGxpY2FudEluY29tZSxsb2FuLnRyYWluJExvYW5BbW91bnQpDQpjb3IobG9hbi50cmFpbiRDb2FwcGxpY2FudEluY29tZSxsb2FuLnRyYWluJExvYW5BbW91bnQpDQoNCnpzY29yZV9hcHBsaWNhbnRpbmNvbWU9KGxvYW4udHJhaW4kQXBwbGljYW50SW5jb21lLW1lYW4obG9hbi50cmFpbiRBcHBsaWNhbnRJbmNvbWUpKS9zZChsb2FuLnRyYWluJEFwcGxpY2FudEluY29tZSkNCnpzY29yZV9jb2FwcGxpY2FudGluY29tZT0obG9hbi50cmFpbiRDb2FwcGxpY2FudEluY29tZS1tZWFuKGxvYW4udHJhaW4kQ29hcHBsaWNhbnRJbmNvbWUpKS9zZChsb2FuLnRyYWluJENvYXBwbGljYW50SW5jb21lKQ0KenNjb3JlX0xvYW5BbW91bnQ9KGxvYW4udHJhaW4kTG9hbkFtb3VudC1tZWFuKGxvYW4udHJhaW4kTG9hbkFtb3VudCkpL3NkKGxvYW4udHJhaW4kTG9hbkFtb3VudCkNCmBgYA0KDQojIyMgTXVsdGl2YXJpYXQgbnVtZXJpaw0KDQpgYGB7cn0NCmNvdihsb2FudHJhaW4pDQpjb3IobG9hbnRyYWluKQ0KYGBgDQoNCg0KYGBge3J9DQp0cmFpbi5uZXcgPC0gdHJhaW4ubmV3ICU+JQ0KICBtdXRhdGUoTG9hbl9TdGF0dXM9YXMuZmFjdG9yKExvYW5fU3RhdHVzKSkNCg0KdmFybGlzdCA8LSBjKCJBcHBsaWNhbnRJbmNvbWUiLCAiQ29hcHBsaWNhbnRJbmNvbWUiLCAiTG9hbkFtb3VudCIpDQoNClBsb3RGYXN0IDwtIGZ1bmN0aW9uKHZhck5hbWUpIHsNCg0KdHJhaW4ubmV3ICU+JSANCmdyb3VwX2J5XygiTG9hbl9TdGF0dXMiKSAlPiUgDQpkcGx5cjo6c2VsZWN0XygiTG9hbl9TdGF0dXMiLHZhck5hbWUpICU+JSANCmdncGxvdChhZXNfc3RyaW5nKCJMb2FuX1N0YXR1cyIsdmFyTmFtZSxmaWxsPSJMb2FuX1N0YXR1cyIpKSArIA0KICAgIGdlb21fYm94cGxvdCgpICsNCiAgICB0aGVtZV9lY29ub21pc3Rfd2hpdGUoKQ0KDQp9DQoNCmFsbF9wbG90X2NvbnQ8LWxhcHBseSh2YXJsaXN0LFBsb3RGYXN0KQ0KY293cGxvdDo6cGxvdF9ncmlkKHBsb3RsaXN0ID0gYWxsX3Bsb3RfY29udCwgbmNvbD0zKQ0KYGBgDQpgYGB7cn0NCnJtKHRyYWluLm5ldykNCmBgYA0KDQpTdWxpdCB1bnR1ayBtZWxpaGF0IHBvbGEga2h1c3VzIGRpIGFudGFyYSB2YXJpYWJlbCBrb250aW51IHNhYXQgaW5pLiBJbmkgbXVuZ2tpbiBiZXJhcnRpIGJhaHdhIGthc3VzIHlhbmcgZGlzZXR1anVpIGRhbiB0aWRhayBkaXNldHVqdWkgbWVtaWxpa2kganVtbGFoIHBpbmphbWFuIHlhbmcgc2FtYSwgcGVuZGFwYXRhbiBwZW1vaG9uL3BlbW9ob24uDQoNCiMjIEVEQSBkZW5nYW4gY2FyYSBNYWxhcyANCg0KYGBge3J9DQpsaWJyYXJ5KGZ1bk1vZGVsaW5nKSANCmxpYnJhcnkodGlkeXZlcnNlKSANCmxpYnJhcnkoSG1pc2MpDQpsaWJyYXJ5KHNraW1yKQ0KYmFzaWNfZWRhIDwtIGZ1bmN0aW9uKGxvYW4udHJhaW4pDQp7DQogIGdsaW1wc2UobG9hbi50cmFpbikNCiAgc2tpbShsb2FuLnRyYWluKQ0KICBkZl9zdGF0dXMobG9hbi50cmFpbikNCiAgZnJlcShsb2FuLnRyYWluKSANCiAgcHJvZmlsaW5nX251bShsb2FuLnRyYWluKQ0KICBwbG90X251bShsb2FuLnRyYWluKQ0KICBkZXNjcmliZShsb2FuLnRyYWluKQ0KfQ0KYmFzaWNfZWRhKGxvYW4udHJhaW4pDQpgYGANCg0KDQojIFR1Z2FzIDQgDQoNCkxha3VrYW4gcGVtZXJpa3NhYW4gZGlzdHJpYnVzaSBkZW5zaXRhcyAgbWVuZ2d1bmFrYW4gUiBkYW4gUHl0aG9uIHBhZGEgc2V0aWFwIHZhcmlhYmVsIGt1YW50aXRhdGlmIGRlbmdhbiBiZWJlcmFwYSBiYWdpYW4gc2ViYWdhaSBiZXJpa3V0Og0KDQojIyBVbml2YXJpYXQgbnVtZXJpaw0KDQoqKkFwcGxpY2FudCBJbmNvbWUqKg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgYWVzKHggPSBBcHBsaWNhbnRJbmNvbWUpKSArDQogIGdlb21fZGVuc2l0eSgpDQpgYGANCg0KKipDb2FwcGxpY2FudCBJbmNvbWUqKg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgYWVzKHggPSBDb2FwcGxpY2FudEluY29tZSkpICsNCiAgZ2VvbV9kZW5zaXR5KCkNCmBgYA0KDQoNCioqTG9hbiBBbW91bnQqKg0KYGBge3J9DQpnZ3Bsb3QobG9hbi50cmFpbiwgYWVzKHggPSBMb2FuQW1vdW50KSkgKw0KICBnZW9tX2RlbnNpdHkoKQ0KYGBgDQoNCg0KIyMgQml2YXJpYXQgbnVtZXJpaw0KDQoqKkFwcGxpY2FudCBJbmNvbWUgdnMgQ29hcHBsaWNhbnQgSW5jb21lKioNCg0KYGBge3J9DQpwMSA8LSBnZ3Bsb3QobG9hbi50cmFpbiwgYWVzKHggPSBBcHBsaWNhbnRJbmNvbWUsIHkgPSBDb2FwcGxpY2FudEluY29tZSkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IC41KSArDQogIGdlb21fZGVuc2l0eV8yZCgpDQpnZ3Bsb3RseShwMSkNCmBgYA0KDQoqKkNvYXBwbGljYW50IEluY29tZSB2cyBMb2FuQW1vdW50KioNCg0KYGBge3J9DQpwMiA8LWdncGxvdChsb2FuLnRyYWluLCBhZXMoeCA9IENvYXBwbGljYW50SW5jb21lLCB5ID0gTG9hbkFtb3VudCkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IC41KSArDQogIGdlb21fZGVuc2l0eV8yZCgpDQpnZ3Bsb3RseShwMikNCmBgYA0KKipBcHBsaWNhbnRJbmNvbWUgdnMgTG9hbkFtb3VudCoqDQoNCmBgYHtyfQ0KcDMgPC0gZ2dwbG90KGxvYW4udHJhaW4sIGFlcyh4ID0gQXBwbGljYW50SW5jb21lLCB5ID0gTG9hbkFtb3VudCkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IC41KSArDQogIGdlb21fZGVuc2l0eV8yZCgpDQpnZ3Bsb3RseShwMykNCmBgYA0KDQojIyBNdWx0aXZhcmlhdCBudW1lcmlrDQoNCmBgYHtyfQ0KbGlicmFyeShHR2FsbHkpDQpnZ3BhaXJzKGxvYW50cmFpbikNCmBgYA0KDQoNCiMgVHVnYXMgNQ0KDQpMYWt1a2FuIHByb3NlcyBwZW5ndWppYW4gSGlwb3Rlc2lzICBtZW5nZ3VuYWthbiBSIGRhbiBQeXRob24gcGFkYSBzZXRpYXAgdmFyaWFiZWwga3VhbnRpdGF0aWYgZGVuZ2FuIGJlYmVyYXBhIGJhZ2lhbiBzZWJhZ2FpIGJlcmlrdXQ6DQoNCiMjIEhpdHVuZ2xhaCBtYXJnaW4gb2YgZXJyb3IgZGFuIGVzdGltYXNpIGludGVydmFsIHVudHVrIHByb3BvcnNpIHBlbWluamFtIGJlamVuaXMga2VsYW1pbiBwZXJlbXB1YW4gZGFsYW0gcGFkYSB0aW5na2F0IGtlcGVyY2F5YWFuIDk1JS4gDQoNCmBgYHtyfQ0KbGlicmFyeShNQVNTKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCmsgPSBzdW0obG9hbi50cmFpbiRHZW5kZXIgPT0gIkZlbWFsZSIpDQpuID0gbGVuZ3RoKGxvYW4udHJhaW4kR2VuZGVyKQ0KcGJhciA9IGsvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KU0UgPSBzcXJ0KHBiYXIqKDEtcGJhcikvbik7IFNFICAgDQpFID0gcW5vcm0oMC45NzUpKlNFOyBFDQpwYmFyICsgYygtRSwgRSkNCmBgYA0KUGFkYSB0aW5na2F0IGtlcGVyY2F5YWFuIDk1JSwgYW50YXJhIDE1LDIlIGRhbiAyMSwzJSBwZW1pbmphbSBiZWplbmlzIGtlbGFtaW4gcGVyZW1wdWFuLCBkYW4gbWFyZ2luIG9mIGVycm9yIGFkYWxhaCAzLDA1JS4NCg0KIyMgSmlrYSBhbmRhIGJlcmVuY2FuYSBtZW5nZ3VuYWthbiBwZXJraXJhYW4gcHJvcG9yc2kgNTAlIGRhdGEga29uc3VtZW4gYmVyamVuaXMga2VsYW1pbiBwZXJlbXB1YW4sIHRlbXVrYW4gdWt1cmFuIHNhbXBlbCB5YW5nIGRpcGVybHVrYW4gdW50dWsgbWVuY2FwYWkgbWFyZ2luIGtlc2FsYWhhbiA1JSB1bnR1ayAgZGF0YSBvYmVzZXJ2YXNpIHBhZGEgdGluZ2thdCBrZXBlcmNheWFhbiA5NSUuDQoNCmBgYHtyfQ0KenN0YXIgPSBxbm9ybSguOTc1KSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KcCA9IDAuNSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KRSA9IDAuMDUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KenN0YXJeMipwKigxLXApL0VeMiAgICAgDQpgYGANCg0KIyMgTGFrdWthbiBwZW1idWt0aWFuIGtlYmVuYXJhbiBhc3N1bXNpIGRlbmdhbiB0aW5nYWthdCBzaWduaWZpa2Fuc2kgMC4wNSwgamlrYSBCYW5rIG1lbmdrbGFpbSBiYWh3YSBwaW5qYW1hbiByYXRhLXJhdGEga29uc3VtZW4gYWRhbGFoOg0KDQojIyMgTGViaWggYmVzYXIgJCAxNTAuIA0KYGBge3J9DQptdTAgPSAxNTANCnhiYXIgPSBtZWFuKGxvYW4udHJhaW4kTG9hbkFtb3VudCkNCnMgPSBzZChsb2FuLnRyYWluJExvYW5BbW91bnQpDQpuID0gbGVuZ3RoKGxvYW4udHJhaW4kTG9hbkFtb3VudCkNCnQgPSAoeGJhci1tdTApLyhzL3NxcnQobikpIDsgdA0KYGBgDQpgYGB7cn0NCmFscGhhID0gMC4wNQ0KdC5hbHBoYSA9IHF0KDEtYWxwaGEsIGRmPW4tMSkNCi10LmFscGhhDQpgYGANCkthcmVuYSAkXG11XzAgXGdlIFxtdSQsIGRhbGFtIGhhbCBpbmkga2l0YSBoYXJ1cyBmb2t1cyBwYWRhIG5pbGFpIGtyaXRpcyBsZWZ0IHRhaWwuIERpIHNpbmksIGRpdGVtdWthbiBiYWh3YSBzdGF0aXN0aWsgdWppIC0xLjA1Nzg5OSBsZWJpaCBiZXNhciBkYXJpIG5pbGFpIGtyaXRpcyAtMS42NDQ4NTQuIEFraWJhdG55YSwgcGFkYSB0aW5na2F0IHNpZ25pZmlrYW5zaSAwLDA1LCBrYW1pIG1lbm9sYWsga2xhaW0gYmFod2EgcmF0YS1yYXRhIHBpbmphbWFuIGtvbnN1bWVuIGxlYmloIGRhcmkgMTUwIGRvbGFyLiANCg0KIyMjIExlYmloIGtlY2lsICQgMTUwDQpgYGB7cn0NCm11MCA9IDE1MA0KeGJhciA9IG1lYW4obG9hbi50cmFpbiRMb2FuQW1vdW50KQ0KcyA9IHNkKGxvYW4udHJhaW4kTG9hbkFtb3VudCkNCm4gPSBsZW5ndGgobG9hbi50cmFpbiRMb2FuQW1vdW50KQ0KdCA9ICh4YmFyLW11MCkvKHMvc3FydChuKSkgOyB0DQpgYGANCg0KYGBge3J9DQphbHBoYSA9IDAuMDUNCnQuYWxwaGEgPSBxdCgxLWFscGhhLCBkZj1uLTEpDQp0LmFscGhhDQpgYGANCk5pbGFpIHN0YXRpc3Rpa255YSAtMS4wNTggbGViaWgga2VjaWwgZGFyaSBuaWxhaSBrcml0aXMgeWFpdHUgMS42NDUuIG1ha2EgcGFkYSB0aW5na2F0IHNpZ25pZmlrYW4gMC4wNSwga2l0YSBtZW5lcmltYSBiYWh3YSByYXRhLXJhdGEgcGluamFtYW4ga29uc3VtZW4ga3VyYW5nIGRhcmkgMTUwIGRvbGFyLiANCg0KIyMjIFNhbWEgZGVuZ2FuICQgMTUwLg0KDQpgYGB7cn0NCm11MCA9IDE1MA0KeGJhciA9IG1lYW4obG9hbi50cmFpbiRMb2FuQW1vdW50KQ0KcyA9IHNkKGxvYW4udHJhaW4kTG9hbkFtb3VudCkNCm4gPSBsZW5ndGgobG9hbi50cmFpbiRMb2FuQW1vdW50KQ0KdCA9ICh4YmFyLW11MCkvKHMvc3FydChuKSkgOyB0DQpgYGANCg0KYGBge3J9DQphbHBoYSA9IC4wNSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCnQuaGFsZi5hbHBoYSA9IHF0KDEtYWxwaGEvMiwgZGY9bi0xKSAgICAgICAgICAgICAgICAgICAgICAgIA0KYygtdC5oYWxmLmFscGhhLCB0LmhhbGYuYWxwaGEpICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCmBgYA0KU3RhdGlzdGlrIHVqaSAtMS4wNTc4OTkgdGVybGV0YWsgZGkgYW50YXJhIG5pbGFpIGtyaXRpcyAtMSw5NiBkYW4gMSw5Ni4gT2xlaCBrYXJlbmEgaXR1LCBwYWRhIHRpbmdrYXQgc2lnbmlmaWthbnNpIDAsMDUsIGtpdGEgdGlkYWsgbWVub2xhayBoaXBvdGVzaXMgbm9sIGJhaHdhIHJhdGEtcmF0YSBwZW5ndWluIHRpZGFrIGphdWggYmVyYmVkYSBkYXJpIDE1MC4NCg0KIyMgTGFrdWthbiBwZW1idWt0aWFuIGtlYmVuYXJhbiBhc3N1bXNpIGRlbmdhbiB0aW5nYWthdCBzaWduaWZpa2Fuc2kgMC4wNSwgc2VwZXJ0aSBkaWF0YXMgamlrYSBkaWtldGFodWkgc2ltcGFuZ2FuIGJha3UgcGluamFtYW4gYWRhbGFoICQgODUuIA0KDQojIyMgTGViaWggYmVzYXIgJCAxNTAuIA0KYGBge3J9DQptdTAgPSAxNTANCnhiYXIgPSBtZWFuKGxvYW4udHJhaW4kTG9hbkFtb3VudCkNCnNpZ21hID0gODUgDQpuID0gbGVuZ3RoKGxvYW4udHJhaW4kTG9hbkFtb3VudCkNCnogPSAoeGJhci1tdTApLyhzaWdtYS9zcXJ0KG4pKSA7IHoNCmBgYA0KDQpgYGB7cn0NCmFscGhhID0gMC4wNQ0Kei5hbHBoYSA9IHFub3JtKDEtYWxwaGEpDQotei5hbHBoYQ0KYGBgDQpLYXJlbmEgJFxtdV8wIFxnZSBcbXUkLCBkYWxhbSBoYWwgaW5pIGtpdGEgaGFydXMgZm9rdXMgcGFkYSBuaWxhaSBrcml0aXMgbGVmdCB0YWlsLiBEaSBzaW5pLCBkaXRlbXVrYW4gYmFod2Egc3RhdGlzdGlrIHVqaSAtMS4wNDUgbGViaWggYmVzYXIgZGFyaSBuaWxhaSBrcml0aXMgLTEuNjQ0ODU0LiBBa2liYXRueWEsIHBhZGEgdGluZ2thdCBzaWduaWZpa2Fuc2kgMCwwNSwga2FtaSBtZW5vbGFrIGtsYWltIGJhaHdhIHJhdGEtcmF0YSBwaW5qYW1hbiBrb25zdW1lbiBsZWJpaCBkYXJpIDE1MCBkb2xhci4gDQoNCiMjIyBMZWJpaCBrZWNpbCAkIDE1MA0KYGBge3J9DQptdTAgPSAxNTANCnhiYXIgPSBtZWFuKGxvYW4udHJhaW4kTG9hbkFtb3VudCkNCnNpZ21hID0gODUNCm4gPSBsZW5ndGgobG9hbi50cmFpbiRMb2FuQW1vdW50KQ0KeiA9ICh4YmFyLW11MCkvKHNpZ21hL3NxcnQobikpIDsgeg0KYGBgDQoNCmBgYHtyfQ0KYWxwaGEgPSAwLjA1DQp6LmFscGhhID0gcW5vcm0oMS1hbHBoYSkNCnouYWxwaGENCmBgYA0KTmlsYWkgc3RhdGlzdGlrbnlhIC0xLjA0NiBsZWJpaCBrZWNpbCBkYXJpIG5pbGFpIGtyaXRpcyB5YWl0dSAxLjY0NS4gbWFrYSBwYWRhIHRpbmdrYXQgc2lnbmlmaWthbiAwLjA1LCBraXRhIG1lbmVyaW1hIGJhaHdhIHJhdGEtcmF0YSBwaW5qYW1hbiBrb25zdW1lbiBrdXJhbmcgZGFyaSAxNTAgZG9sYXIuIA0KDQojIyMgU2FtYSBkZW5nYW4gJCAxNTAuDQoNCmBgYHtyfQ0KbXUwID0gMTUwDQp4YmFyID0gbWVhbihsb2FuLnRyYWluJExvYW5BbW91bnQpDQpzaWdtYSA9IDg1DQpuID0gbGVuZ3RoKGxvYW4udHJhaW4kTG9hbkFtb3VudCkNCnogPSAoeGJhci1tdTApLyhzaWdtYS9zcXJ0KG4pKSA7IHoNCmBgYA0KDQpgYGB7cn0NCmFscGhhID0gLjA1ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0Kei5oYWxmLmFscGhhID0gcW5vcm0oMS1hbHBoYS8yKSAgICAgICAgICAgICAgICAgICAgICAgIA0KYygtei5oYWxmLmFscGhhLCB6LmhhbGYuYWxwaGEpICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCmBgYA0KU3RhdGlzdGlrIHVqaSAtMS4wNDYgdGVybGV0YWsgZGkgYW50YXJhIG5pbGFpIGtyaXRpcyAtMSw5NiBkYW4gMSw5Ni4gT2xlaCBrYXJlbmEgaXR1LCBwYWRhIHRpbmdrYXQgc2lnbmlmaWthbnNpIDAsMDUsIGtpdGEgdGlkYWsgbWVub2xhayBoaXBvdGVzaXMgbm9sIGJhaHdhIHJhdGEtcmF0YSBwZW5ndWluIHRpZGFrIGphdWggYmVyYmVkYSBkYXJpIDE1MC4NCg0KIyBSZWZlcmVuc2kNCg0KMS4gICBodHRwczovL2Jvb2tkb3duLm9yZy9CYWt0aVNpcmVnYXIvZGF0YS1zY2llbmNlLWZvci1iZWdpbm5lcnMtcGFydC0yLzMtSHlwb3RoZXNpcy1UZXN0aW5nLmh0bWwjb25lLXRhaWxlZC1wb3B1bGF0aW9uLW1lYW4tYW5kLXVua25vd24tc3RhbmRhcmQtZGV2aWF0aW9uDQoyLiAgIHJlZiAyDQozLiAgIHJlZiAzDQoNCg0KDQoNCg==