1 Introduction

In this note, I will introduce the steps for taking random samples from the study population. The Bank load data set is treated as a population. We will use this data set as a population to implement various sampling plans.

The original data set was split into 9 subsets that are stored on GitHub. We first load these data sets to R and then combine them as a single data set.

# Read in the dataset
loan01 = read.csv("https://pengdsci.github.io/datasets/SBAloan/w06-SBAnational01.csv", header = TRUE)[, -1]
loan02 = read.csv("https://pengdsci.github.io/datasets/SBAloan/w06-SBAnational02.csv", header = TRUE)[, -1]
loan03 = read.csv("https://pengdsci.github.io/datasets/SBAloan/w06-SBAnational03.csv", header = TRUE)[, -1]
loan04 = read.csv("https://pengdsci.github.io/datasets/SBAloan/w06-SBAnational04.csv", header = TRUE)[, -1]
loan05 = read.csv("https://pengdsci.github.io/datasets/SBAloan/w06-SBAnational05.csv", header = TRUE)[, -1]
loan06 = read.csv("https://pengdsci.github.io/datasets/SBAloan/w06-SBAnational06.csv", header = TRUE)[, -1]
loan07 = read.csv("https://pengdsci.github.io/datasets/SBAloan/w06-SBAnational07.csv", header = TRUE)[, -1]
loan08 = read.csv("https://pengdsci.github.io/datasets/SBAloan/w06-SBAnational08.csv", header = TRUE)[, -1]
loan09 = read.csv("https://pengdsci.github.io/datasets/SBAloan/w06-SBAnational09.csv", header = TRUE)[, -1]
loan = rbind(loan01, loan02, loan03, loan04, loan05, loan06, loan07, loan08, loan09)
# dim(bankLoan)
#names(bankLoan)
## Remove NAs from MIS_status
library(tidyverse)
bankLoan <- loan
##convert dollars to numeric
##Variables DisbursementGross, BalanceGross, ChgOffPrinGr, GrAppv, SBA_Appv
colnames(bankLoan)
 [1] "LoanNr_ChkDgt"     "Name"              "City"             
 [4] "State"             "Zip"               "Bank"             
 [7] "BankState"         "NAICS"             "ApprovalDate"     
[10] "ApprovalFY"        "Term"              "NoEmp"            
[13] "NewExist"          "CreateJob"         "RetainedJob"      
[16] "FranchiseCode"     "UrbanRural"        "RevLineCr"        
[19] "LowDoc"            "ChgOffDate"        "DisbursementDate" 
[22] "DisbursementGross" "BalanceGross"      "MIS_Status"       
[25] "ChgOffPrinGr"      "GrAppv"            "SBA_Appv"         
bankLoan$DisbursementGross <- as.numeric(gsub('[$,]', '', bankLoan$DisbursementGross))
bankLoan$BalanceGross <- as.numeric(gsub('[$,]', '', bankLoan$BalanceGross))
bankLoan$ChgOffPrinGr <- as.numeric(gsub('[$,]', '', bankLoan$ChgOffPrinGr))
bankLoan$GrAppv <- as.numeric(gsub('[$,]', '', bankLoan$GrAppv))
bankLoan$SBA_Appv <- as.numeric(gsub('[$,]', '', bankLoan$SBA_Appv))

1.1 Stratifcation Variable

Here is the distribution of original Number of Employees variable. This will help us make our groupings for this variable.

hist(bankLoan$NoEmp)

1.2 Combining Categories

We now combine the number of employees the business has into categories. We created a new variable NoEmpBin based off of NoEmp that grouped it into five different categories. NoEmpBin will be our operational stratification variable.

# Re-group the number of business employees
library(dplyr)
bankLoan <- bankLoan %>% 
  mutate( NoEmpBin = case_when(NoEmp <= 5 ~ '<=5',
                                     NoEmp > 5 & NoEmp <= 25 ~ '6-25',
                                     NoEmp > 25 & NoEmp <=50 ~ '26-50',
                                     NoEmp > 50 & NoEmp <= 100 ~ '51-100',
                                     NoEmp > 100  ~ '101+')) 

1.3 Loan Default Rates By Number of Employees

We now find the loan default rates by the number of employees defined by the stratification variable NoEmpBin The loan default status can be defined by the variable MIS_Status.

x.table = table(bankLoan$NoEmpBin, bankLoan$MIS_Status)
no.lab = x.table[,1]  # first column consists of unknown default label
default = x.table[,2]
no.default = x.table[,3]
default.rate = round(100*default/(default+no.default),1)
default.status.rate = cbind(no.lab = no.lab, 
                          default = default, 
                          no.default = no.default,
                          default.rate=default.rate)
kable(default.status.rate)
no.lab default no.default default.rate
<=5 1568 109463 412788 21.0
101+ 36 419 6998 5.6
26-50 29 4619 48068 8.8
51-100 26 1301 18571 6.5
6-25 338 41756 253184 14.2

1.4 Study Population

Based on the above frequency distribution of the modified number of employees bins.

study.pop = bankLoan
kable(t(table(bankLoan$NoEmpBin))) # Checking correctness operation
<=5 101+ 26-50 51-100 6-25
523819 7453 52716 19898 295278

So we have defined our study population!

2 Sampling Plans

In this section, we are implementing three sampling plans. In each sampling plan, we select 4000 observations in the corresponding samples.

2.1 Simple Random Sampling

We define a sampling list and add it to the study population.

study.pop$sampling.frame = 1:length(study.pop$GrAppv)   
# sampling list
# names(study.pop)                                     
# checking the sampling list variable
sampled.list = sample(1:length(study.pop$GrAppv), 4000) 
# sampling the list
SRS.sample = study.pop[sampled.list,]                  
# extract the sampling units (observations)
## dimension check
dimension.SRS = dim(SRS.sample)
names(dimension.SRS) = c("Size", "Var.count")
kable(t(dimension.SRS))   # checking the sample size
Size Var.count
4000 29

2.2 Systematic sampling

jump.size = dim(study.pop)[1]%/%4000  
# find the jump size in the systematic sampling
# jump.size
rand.starting.pt=sample(2:jump.size,1) # find the random starting value
sampling.id = seq(rand.starting.pt, dim(study.pop)[1], jump.size)  # sampling IDs
#length(sampling.id)
sys.sample=study.pop[sampling.id,]    
# extract the sampling units of systematic samples
sys.Sample.dim = dim(sys.sample)
names(sys.Sample.dim) = c("Size", "Var.count")
kable(t(sys.Sample.dim))
Size Var.count
4014 29

Because the jump size involves rounding error and the population is large, the actual systematic sample size is slightly different from the target size. In this report, I used the integer part of the actual jump size. The actual systematic sampling size is slightly bigger than the target size. We can take away some records random from the systematic sample to make the size to be equal to the target size.

2.3 Stratified Sampling

We take an SRS from each stratum. The sample size should be approximately proportional to the size of the corresponding stratum.

First, we calculate the SRS size for each stratum and then take the SRS from the corresponding stratum.

freq.table = table(study.pop$NoEmpBin)  # frequency table of strNAICS
rel.freq = freq.table/sum(freq.table)   # relative frequency 
strata.size = round(rel.freq*4000)      # strata size allocation
strata.names=names(strata.size)         # extract strNAICS names for accuracy checking
kable(t(strata.size))  # make a nice-looking table using kable().
<=5 101+ 26-50 51-100 6-25
2330 33 235 89 1314

In the following code chunk, we take stratified samples.

strata.sample = study.pop[1,]    # create a reference data frame
strata.sample$add.id = 1   # add a temporary ID to because in the loop
                           # i =2 testing a single iteration
for (i in 1:length(strata.names)){
   ith.strata.names = strata.names[i]   # extract data frame names
   ith.strata.size = strata.size[i]     # allocated stratum size
   # The following code identifies observations to be selected
   ith.sampling.id = which(study.pop$NoEmpBin==ith.strata.names) 
   ith.strata = study.pop[ith.sampling.id,]  # i-th stratified population
   ith.strata$add.id = 1:dim(ith.strata)[1]  # add sampling list/frame
   # The following code generates a subset of random ID
   ith.sampling.id = sample(1:dim(ith.strata)[1], ith.strata.size) 
   ## Create a selection status -- pay attention to the operator: %in% 
   ith.sample =ith.strata[ith.strata$add.id %in%ith.sampling.id,]
   ## dim(ith.sample)         $ check the sample
   strata.sample = rbind(strata.sample, ith.sample)  # stack all data frame!
 }
 # dim(strata.sample)
 strat.sample.final = strata.sample[-1,]  # drop the temporary stratum ID
 #kable(head(strat.sample.final))         # accuracy check!

2.4 Cluster Sampling

Here we will do a cluster sampling method based off of zip codes. We will cluster the data by zip codes and then take a random sample of zip codes. Our sample size is roughly around 4000.

#unique zip codes
unizip <- unique(study.pop$Zip)

#random sample of zip codes
# checking the sampling list variable
sampled.zip = sample(unizip, 170) 

# join the data to the zip codes
cluster <- study.pop[study.pop$Zip %in% sampled.zip, ]

sys.clsuter = dim(cluster)
names(sys.clsuter) = c("Size", "Var.count")
kable(t(sys.clsuter))
Size Var.count
4598 29
LS0tDQp0aXRsZTogIkltcGxlbWVudGluZyBSYW1kb20gU2FtcGxpbmcgUGxhbnMgIg0KYXV0aG9yOiAiR2lhbm5hIExhRnJhbmNlIg0KZGF0ZTogIiAgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgZmlnX3dpZHRoOiA2DQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQogICAgdGhlbWU6IHJlYWRhYmxlDQogICAgZmlnX2hlaWdodDogNA0KLS0tDQoNCmBgYHs9aHRtbH0NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMjBweDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuYXV0aG9yIHsgDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmRhdGUgeyANCiAgZm9udC1zaXplOiAxOHB4Ow0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMSB7DQogICAgZm9udC1zaXplOiAyMnB4Ow0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmgyIHsNCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KZGl2I1RPQyBsaSB7DQogICAgbGlzdC1zdHlsZTpub25lOw0KfQ0KPC9zdHlsZT4NCmBgYA0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgibGVzc1IiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygibGVzc1IiKQ0KICAgbGlicmFyeShsZXNzUikNCn0NCg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5ncyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkEpDQpgYGANCg0KDQojIEludHJvZHVjdGlvbg0KDQoNCkluIHRoaXMgbm90ZSwgSSB3aWxsIGludHJvZHVjZSB0aGUgc3RlcHMgZm9yIHRha2luZyByYW5kb20gc2FtcGxlcyBmcm9tIHRoZSBzdHVkeSBwb3B1bGF0aW9uLiBUaGUgQmFuayBsb2FkIGRhdGEgc2V0IGlzIHRyZWF0ZWQgYXMgYSBwb3B1bGF0aW9uLiBXZSB3aWxsIHVzZSB0aGlzIGRhdGEgc2V0IGFzIGEgcG9wdWxhdGlvbiB0byBpbXBsZW1lbnQgdmFyaW91cyBzYW1wbGluZyBwbGFucy4NCg0KVGhlIG9yaWdpbmFsIGRhdGEgc2V0IHdhcyBzcGxpdCBpbnRvIDkgc3Vic2V0cyB0aGF0IGFyZSBzdG9yZWQgb24gR2l0SHViLiBXZSBmaXJzdCBsb2FkIHRoZXNlIGRhdGEgc2V0cyB0byBSIGFuZCB0aGVuIGNvbWJpbmUgdGhlbSBhcyBhIHNpbmdsZSBkYXRhIHNldC4NCg0KYGBge3IgZGF0YXNldH0NCiMgUmVhZCBpbiB0aGUgZGF0YXNldA0KbG9hbjAxID0gcmVhZC5jc3YoImh0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL2RhdGFzZXRzL1NCQWxvYW4vdzA2LVNCQW5hdGlvbmFsMDEuY3N2IiwgaGVhZGVyID0gVFJVRSlbLCAtMV0NCmxvYW4wMiA9IHJlYWQuY3N2KCJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9kYXRhc2V0cy9TQkFsb2FuL3cwNi1TQkFuYXRpb25hbDAyLmNzdiIsIGhlYWRlciA9IFRSVUUpWywgLTFdDQpsb2FuMDMgPSByZWFkLmNzdigiaHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vZGF0YXNldHMvU0JBbG9hbi93MDYtU0JBbmF0aW9uYWwwMy5jc3YiLCBoZWFkZXIgPSBUUlVFKVssIC0xXQ0KbG9hbjA0ID0gcmVhZC5jc3YoImh0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL2RhdGFzZXRzL1NCQWxvYW4vdzA2LVNCQW5hdGlvbmFsMDQuY3N2IiwgaGVhZGVyID0gVFJVRSlbLCAtMV0NCmxvYW4wNSA9IHJlYWQuY3N2KCJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9kYXRhc2V0cy9TQkFsb2FuL3cwNi1TQkFuYXRpb25hbDA1LmNzdiIsIGhlYWRlciA9IFRSVUUpWywgLTFdDQpsb2FuMDYgPSByZWFkLmNzdigiaHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vZGF0YXNldHMvU0JBbG9hbi93MDYtU0JBbmF0aW9uYWwwNi5jc3YiLCBoZWFkZXIgPSBUUlVFKVssIC0xXQ0KbG9hbjA3ID0gcmVhZC5jc3YoImh0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL2RhdGFzZXRzL1NCQWxvYW4vdzA2LVNCQW5hdGlvbmFsMDcuY3N2IiwgaGVhZGVyID0gVFJVRSlbLCAtMV0NCmxvYW4wOCA9IHJlYWQuY3N2KCJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9kYXRhc2V0cy9TQkFsb2FuL3cwNi1TQkFuYXRpb25hbDA4LmNzdiIsIGhlYWRlciA9IFRSVUUpWywgLTFdDQpsb2FuMDkgPSByZWFkLmNzdigiaHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vZGF0YXNldHMvU0JBbG9hbi93MDYtU0JBbmF0aW9uYWwwOS5jc3YiLCBoZWFkZXIgPSBUUlVFKVssIC0xXQ0KbG9hbiA9IHJiaW5kKGxvYW4wMSwgbG9hbjAyLCBsb2FuMDMsIGxvYW4wNCwgbG9hbjA1LCBsb2FuMDYsIGxvYW4wNywgbG9hbjA4LCBsb2FuMDkpDQojIGRpbShiYW5rTG9hbikNCiNuYW1lcyhiYW5rTG9hbikNCmBgYA0KDQpgYGB7cn0NCiMjIFJlbW92ZSBOQXMgZnJvbSBNSVNfc3RhdHVzDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmJhbmtMb2FuIDwtIGxvYW4NCmBgYA0KDQpgYGB7cn0NCiMjY29udmVydCBkb2xsYXJzIHRvIG51bWVyaWMNCiMjVmFyaWFibGVzIERpc2J1cnNlbWVudEdyb3NzLCBCYWxhbmNlR3Jvc3MsIENoZ09mZlByaW5HciwgR3JBcHB2LCBTQkFfQXBwdg0KY29sbmFtZXMoYmFua0xvYW4pDQoNCmJhbmtMb2FuJERpc2J1cnNlbWVudEdyb3NzIDwtIGFzLm51bWVyaWMoZ3N1YignWyQsXScsICcnLCBiYW5rTG9hbiREaXNidXJzZW1lbnRHcm9zcykpDQpiYW5rTG9hbiRCYWxhbmNlR3Jvc3MgPC0gYXMubnVtZXJpYyhnc3ViKCdbJCxdJywgJycsIGJhbmtMb2FuJEJhbGFuY2VHcm9zcykpDQpiYW5rTG9hbiRDaGdPZmZQcmluR3IgPC0gYXMubnVtZXJpYyhnc3ViKCdbJCxdJywgJycsIGJhbmtMb2FuJENoZ09mZlByaW5HcikpDQpiYW5rTG9hbiRHckFwcHYgPC0gYXMubnVtZXJpYyhnc3ViKCdbJCxdJywgJycsIGJhbmtMb2FuJEdyQXBwdikpDQpiYW5rTG9hbiRTQkFfQXBwdiA8LSBhcy5udW1lcmljKGdzdWIoJ1skLF0nLCAnJywgYmFua0xvYW4kU0JBX0FwcHYpKQ0KDQpgYGANCg0KDQojIyBTdHJhdGlmY2F0aW9uIFZhcmlhYmxlDQoNCg0KSGVyZSBpcyB0aGUgZGlzdHJpYnV0aW9uIG9mIG9yaWdpbmFsIE51bWJlciBvZiBFbXBsb3llZXMgdmFyaWFibGUuIFRoaXMgd2lsbCBoZWxwIHVzIG1ha2Ugb3VyIGdyb3VwaW5ncyBmb3IgdGhpcyB2YXJpYWJsZS4NCg0KYGBge3IgZGF0YS1zaXplfQ0KaGlzdChiYW5rTG9hbiROb0VtcCkNCmBgYA0KDQoNCiMjIENvbWJpbmluZyBDYXRlZ29yaWVzDQoNCldlIG5vdyBjb21iaW5lIHRoZSBudW1iZXIgb2YgZW1wbG95ZWVzIHRoZSBidXNpbmVzcyBoYXMgaW50byBjYXRlZ29yaWVzLiBXZSBjcmVhdGVkIGEgbmV3IHZhcmlhYmxlIE5vRW1wQmluIGJhc2VkIG9mZiBvZiBOb0VtcCB0aGF0IGdyb3VwZWQgaXQgaW50byBmaXZlIGRpZmZlcmVudCBjYXRlZ29yaWVzLiBOb0VtcEJpbiB3aWxsIGJlIG91ciBvcGVyYXRpb25hbCBzdHJhdGlmaWNhdGlvbiB2YXJpYWJsZS4NCg0KDQpgYGB7cn0NCiMgUmUtZ3JvdXAgdGhlIG51bWJlciBvZiBidXNpbmVzcyBlbXBsb3llZXMNCmxpYnJhcnkoZHBseXIpDQpiYW5rTG9hbiA8LSBiYW5rTG9hbiAlPiUgDQogIG11dGF0ZSggTm9FbXBCaW4gPSBjYXNlX3doZW4oTm9FbXAgPD0gNSB+ICc8PTUnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5vRW1wID4gNSAmIE5vRW1wIDw9IDI1IH4gJzYtMjUnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5vRW1wID4gMjUgJiBOb0VtcCA8PTUwIH4gJzI2LTUwJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOb0VtcCA+IDUwICYgTm9FbXAgPD0gMTAwIH4gJzUxLTEwMCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTm9FbXAgPiAxMDAgIH4gJzEwMSsnKSkgDQoNCmBgYA0KDQoNCiMjIExvYW4gRGVmYXVsdCBSYXRlcyBCeSBOdW1iZXIgb2YgRW1wbG95ZWVzDQoNCldlIG5vdyBmaW5kIHRoZSBsb2FuIGRlZmF1bHQgcmF0ZXMgYnkgdGhlIG51bWJlciBvZiBlbXBsb3llZXMgZGVmaW5lZCBieSB0aGUgc3RyYXRpZmljYXRpb24gdmFyaWFibGUgTm9FbXBCaW4gVGhlIGxvYW4gZGVmYXVsdCBzdGF0dXMgY2FuIGJlIGRlZmluZWQgYnkgdGhlIHZhcmlhYmxlIE1JU19TdGF0dXMuDQoNCmBgYHtyfQ0KeC50YWJsZSA9IHRhYmxlKGJhbmtMb2FuJE5vRW1wQmluLCBiYW5rTG9hbiRNSVNfU3RhdHVzKQ0Kbm8ubGFiID0geC50YWJsZVssMV0gICMgZmlyc3QgY29sdW1uIGNvbnNpc3RzIG9mIHVua25vd24gZGVmYXVsdCBsYWJlbA0KZGVmYXVsdCA9IHgudGFibGVbLDJdDQpuby5kZWZhdWx0ID0geC50YWJsZVssM10NCmRlZmF1bHQucmF0ZSA9IHJvdW5kKDEwMCpkZWZhdWx0LyhkZWZhdWx0K25vLmRlZmF1bHQpLDEpDQpkZWZhdWx0LnN0YXR1cy5yYXRlID0gY2JpbmQobm8ubGFiID0gbm8ubGFiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdCA9IGRlZmF1bHQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBuby5kZWZhdWx0ID0gbm8uZGVmYXVsdCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdC5yYXRlPWRlZmF1bHQucmF0ZSkNCmthYmxlKGRlZmF1bHQuc3RhdHVzLnJhdGUpDQpgYGANCg0KIyMgU3R1ZHkgUG9wdWxhdGlvbg0KDQpCYXNlZCBvbiB0aGUgYWJvdmUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBvZiB0aGUgbW9kaWZpZWQgbnVtYmVyIG9mIGVtcGxveWVlcyBiaW5zLg0KDQpgYGB7cn0NCnN0dWR5LnBvcCA9IGJhbmtMb2FuDQprYWJsZSh0KHRhYmxlKGJhbmtMb2FuJE5vRW1wQmluKSkpICMgQ2hlY2tpbmcgY29ycmVjdG5lc3Mgb3BlcmF0aW9uDQpgYGANCg0KU28gd2UgaGF2ZSBkZWZpbmVkIG91ciBzdHVkeSBwb3B1bGF0aW9uIQ0KDQojIFNhbXBsaW5nIFBsYW5zDQoNCkluIHRoaXMgc2VjdGlvbiwgd2UgYXJlIGltcGxlbWVudGluZyB0aHJlZSBzYW1wbGluZyBwbGFucy4gSW4gZWFjaCBzYW1wbGluZyBwbGFuLCB3ZSBzZWxlY3QgNDAwMCBvYnNlcnZhdGlvbnMgaW4gdGhlIGNvcnJlc3BvbmRpbmcgc2FtcGxlcy4NCg0KIyMgU2ltcGxlIFJhbmRvbSBTYW1wbGluZw0KDQpXZSBkZWZpbmUgYSBzYW1wbGluZyBsaXN0IGFuZCBhZGQgaXQgdG8gdGhlIHN0dWR5IHBvcHVsYXRpb24uDQoNCmBgYHtyfQ0Kc3R1ZHkucG9wJHNhbXBsaW5nLmZyYW1lID0gMTpsZW5ndGgoc3R1ZHkucG9wJEdyQXBwdikgICANCiMgc2FtcGxpbmcgbGlzdA0KIyBuYW1lcyhzdHVkeS5wb3ApICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KIyBjaGVja2luZyB0aGUgc2FtcGxpbmcgbGlzdCB2YXJpYWJsZQ0Kc2FtcGxlZC5saXN0ID0gc2FtcGxlKDE6bGVuZ3RoKHN0dWR5LnBvcCRHckFwcHYpLCA0MDAwKSANCiMgc2FtcGxpbmcgdGhlIGxpc3QNClNSUy5zYW1wbGUgPSBzdHVkeS5wb3Bbc2FtcGxlZC5saXN0LF0gICAgICAgICAgICAgICAgICANCiMgZXh0cmFjdCB0aGUgc2FtcGxpbmcgdW5pdHMgKG9ic2VydmF0aW9ucykNCiMjIGRpbWVuc2lvbiBjaGVjaw0KZGltZW5zaW9uLlNSUyA9IGRpbShTUlMuc2FtcGxlKQ0KbmFtZXMoZGltZW5zaW9uLlNSUykgPSBjKCJTaXplIiwgIlZhci5jb3VudCIpDQprYWJsZSh0KGRpbWVuc2lvbi5TUlMpKSAgICMgY2hlY2tpbmcgdGhlIHNhbXBsZSBzaXplDQpgYGANCg0KIyMgU3lzdGVtYXRpYyBzYW1wbGluZw0KDQpgYGB7cn0NCmp1bXAuc2l6ZSA9IGRpbShzdHVkeS5wb3ApWzFdJS8lNDAwMCAgDQojIGZpbmQgdGhlIGp1bXAgc2l6ZSBpbiB0aGUgc3lzdGVtYXRpYyBzYW1wbGluZw0KIyBqdW1wLnNpemUNCnJhbmQuc3RhcnRpbmcucHQ9c2FtcGxlKDI6anVtcC5zaXplLDEpICMgZmluZCB0aGUgcmFuZG9tIHN0YXJ0aW5nIHZhbHVlDQpzYW1wbGluZy5pZCA9IHNlcShyYW5kLnN0YXJ0aW5nLnB0LCBkaW0oc3R1ZHkucG9wKVsxXSwganVtcC5zaXplKSAgIyBzYW1wbGluZyBJRHMNCiNsZW5ndGgoc2FtcGxpbmcuaWQpDQpzeXMuc2FtcGxlPXN0dWR5LnBvcFtzYW1wbGluZy5pZCxdICAgIA0KIyBleHRyYWN0IHRoZSBzYW1wbGluZyB1bml0cyBvZiBzeXN0ZW1hdGljIHNhbXBsZXMNCnN5cy5TYW1wbGUuZGltID0gZGltKHN5cy5zYW1wbGUpDQpuYW1lcyhzeXMuU2FtcGxlLmRpbSkgPSBjKCJTaXplIiwgIlZhci5jb3VudCIpDQprYWJsZSh0KHN5cy5TYW1wbGUuZGltKSkNCmBgYA0KDQpCZWNhdXNlIHRoZSBqdW1wIHNpemUgaW52b2x2ZXMgcm91bmRpbmcgZXJyb3IgYW5kIHRoZSBwb3B1bGF0aW9uIGlzIGxhcmdlLCB0aGUgYWN0dWFsIHN5c3RlbWF0aWMgc2FtcGxlIHNpemUgaXMgc2xpZ2h0bHkgZGlmZmVyZW50IGZyb20gdGhlIHRhcmdldCBzaXplLiBJbiB0aGlzIHJlcG9ydCwgSSB1c2VkIHRoZSBpbnRlZ2VyIHBhcnQgb2YgdGhlIGFjdHVhbCBqdW1wIHNpemUuIFRoZSBhY3R1YWwgc3lzdGVtYXRpYyBzYW1wbGluZyBzaXplIGlzIHNsaWdodGx5IGJpZ2dlciB0aGFuIHRoZSB0YXJnZXQgc2l6ZS4gV2UgY2FuIHRha2UgYXdheSBzb21lIHJlY29yZHMgcmFuZG9tIGZyb20gdGhlIHN5c3RlbWF0aWMgc2FtcGxlIHRvIG1ha2UgdGhlIHNpemUgdG8gYmUgZXF1YWwgdG8gdGhlIHRhcmdldCBzaXplLg0KDQojIyBTdHJhdGlmaWVkIFNhbXBsaW5nDQoNCldlIHRha2UgYW4gU1JTIGZyb20gZWFjaCBzdHJhdHVtLiBUaGUgc2FtcGxlIHNpemUgc2hvdWxkIGJlIGFwcHJveGltYXRlbHkgcHJvcG9ydGlvbmFsIHRvIHRoZSBzaXplIG9mIHRoZSBjb3JyZXNwb25kaW5nIHN0cmF0dW0uDQoNCkZpcnN0LCB3ZSBjYWxjdWxhdGUgdGhlIFNSUyBzaXplIGZvciBlYWNoIHN0cmF0dW0gYW5kIHRoZW4gdGFrZSB0aGUgU1JTIGZyb20gdGhlIGNvcnJlc3BvbmRpbmcgc3RyYXR1bS4NCg0KYGBge3J9DQpmcmVxLnRhYmxlID0gdGFibGUoc3R1ZHkucG9wJE5vRW1wQmluKSAgIyBmcmVxdWVuY3kgdGFibGUgb2Ygc3RyTkFJQ1MNCnJlbC5mcmVxID0gZnJlcS50YWJsZS9zdW0oZnJlcS50YWJsZSkgICAjIHJlbGF0aXZlIGZyZXF1ZW5jeSANCnN0cmF0YS5zaXplID0gcm91bmQocmVsLmZyZXEqNDAwMCkgICAgICAjIHN0cmF0YSBzaXplIGFsbG9jYXRpb24NCnN0cmF0YS5uYW1lcz1uYW1lcyhzdHJhdGEuc2l6ZSkgICAgICAgICAjIGV4dHJhY3Qgc3RyTkFJQ1MgbmFtZXMgZm9yIGFjY3VyYWN5IGNoZWNraW5nDQpgYGANCg0KYGBge3J9DQprYWJsZSh0KHN0cmF0YS5zaXplKSkgICMgbWFrZSBhIG5pY2UtbG9va2luZyB0YWJsZSB1c2luZyBrYWJsZSgpLg0KYGBgDQoNCkluIHRoZSBmb2xsb3dpbmcgY29kZSBjaHVuaywgd2UgdGFrZSBzdHJhdGlmaWVkIHNhbXBsZXMuDQoNCmBgYHtyfQ0Kc3RyYXRhLnNhbXBsZSA9IHN0dWR5LnBvcFsxLF0gICAgIyBjcmVhdGUgYSByZWZlcmVuY2UgZGF0YSBmcmFtZQ0Kc3RyYXRhLnNhbXBsZSRhZGQuaWQgPSAxICAgIyBhZGQgYSB0ZW1wb3JhcnkgSUQgdG8gYmVjYXVzZSBpbiB0aGUgbG9vcA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpID0yIHRlc3RpbmcgYSBzaW5nbGUgaXRlcmF0aW9uDQpmb3IgKGkgaW4gMTpsZW5ndGgoc3RyYXRhLm5hbWVzKSl7DQogICBpdGguc3RyYXRhLm5hbWVzID0gc3RyYXRhLm5hbWVzW2ldICAgIyBleHRyYWN0IGRhdGEgZnJhbWUgbmFtZXMNCiAgIGl0aC5zdHJhdGEuc2l6ZSA9IHN0cmF0YS5zaXplW2ldICAgICAjIGFsbG9jYXRlZCBzdHJhdHVtIHNpemUNCiAgICMgVGhlIGZvbGxvd2luZyBjb2RlIGlkZW50aWZpZXMgb2JzZXJ2YXRpb25zIHRvIGJlIHNlbGVjdGVkDQogICBpdGguc2FtcGxpbmcuaWQgPSB3aGljaChzdHVkeS5wb3AkTm9FbXBCaW49PWl0aC5zdHJhdGEubmFtZXMpIA0KICAgaXRoLnN0cmF0YSA9IHN0dWR5LnBvcFtpdGguc2FtcGxpbmcuaWQsXSAgIyBpLXRoIHN0cmF0aWZpZWQgcG9wdWxhdGlvbg0KICAgaXRoLnN0cmF0YSRhZGQuaWQgPSAxOmRpbShpdGguc3RyYXRhKVsxXSAgIyBhZGQgc2FtcGxpbmcgbGlzdC9mcmFtZQ0KICAgIyBUaGUgZm9sbG93aW5nIGNvZGUgZ2VuZXJhdGVzIGEgc3Vic2V0IG9mIHJhbmRvbSBJRA0KICAgaXRoLnNhbXBsaW5nLmlkID0gc2FtcGxlKDE6ZGltKGl0aC5zdHJhdGEpWzFdLCBpdGguc3RyYXRhLnNpemUpIA0KICAgIyMgQ3JlYXRlIGEgc2VsZWN0aW9uIHN0YXR1cyAtLSBwYXkgYXR0ZW50aW9uIHRvIHRoZSBvcGVyYXRvcjogJWluJSANCiAgIGl0aC5zYW1wbGUgPWl0aC5zdHJhdGFbaXRoLnN0cmF0YSRhZGQuaWQgJWluJWl0aC5zYW1wbGluZy5pZCxdDQogICAjIyBkaW0oaXRoLnNhbXBsZSkgICAgICAgICAkIGNoZWNrIHRoZSBzYW1wbGUNCiAgIHN0cmF0YS5zYW1wbGUgPSByYmluZChzdHJhdGEuc2FtcGxlLCBpdGguc2FtcGxlKSAgIyBzdGFjayBhbGwgZGF0YSBmcmFtZSENCiB9DQogIyBkaW0oc3RyYXRhLnNhbXBsZSkNCiBzdHJhdC5zYW1wbGUuZmluYWwgPSBzdHJhdGEuc2FtcGxlWy0xLF0gICMgZHJvcCB0aGUgdGVtcG9yYXJ5IHN0cmF0dW0gSUQNCiAja2FibGUoaGVhZChzdHJhdC5zYW1wbGUuZmluYWwpKSAgICAgICAgICMgYWNjdXJhY3kgY2hlY2shDQpgYGANCg0KIyMgQ2x1c3RlciBTYW1wbGluZw0KDQpIZXJlIHdlIHdpbGwgZG8gYSBjbHVzdGVyIHNhbXBsaW5nIG1ldGhvZCBiYXNlZCBvZmYgb2YgemlwIGNvZGVzLiBXZSB3aWxsIGNsdXN0ZXIgdGhlIGRhdGEgYnkgemlwIGNvZGVzIGFuZCB0aGVuIHRha2UgYSByYW5kb20gc2FtcGxlIG9mIHppcCBjb2Rlcy4gT3VyIHNhbXBsZSBzaXplIGlzIHJvdWdobHkgYXJvdW5kIDQwMDAuDQoNCmBgYHtyfQ0KI3VuaXF1ZSB6aXAgY29kZXMNCnVuaXppcCA8LSB1bmlxdWUoc3R1ZHkucG9wJFppcCkNCg0KI3JhbmRvbSBzYW1wbGUgb2YgemlwIGNvZGVzDQojIGNoZWNraW5nIHRoZSBzYW1wbGluZyBsaXN0IHZhcmlhYmxlDQpzYW1wbGVkLnppcCA9IHNhbXBsZSh1bml6aXAsIDE3MCkgDQoNCiMgam9pbiB0aGUgZGF0YSB0byB0aGUgemlwIGNvZGVzDQpjbHVzdGVyIDwtIHN0dWR5LnBvcFtzdHVkeS5wb3AkWmlwICVpbiUgc2FtcGxlZC56aXAsIF0NCg0Kc3lzLmNsc3V0ZXIgPSBkaW0oY2x1c3RlcikNCm5hbWVzKHN5cy5jbHN1dGVyKSA9IGMoIlNpemUiLCAiVmFyLmNvdW50IikNCmthYmxlKHQoc3lzLmNsc3V0ZXIpKQ0KDQpgYGANCg0KDQo=