In this script, we will evaluate the performance of the WATG technique for region classification in PolSAR textures.

Importing the packages

# Load some packages: 
if(!require(caret)) install.packages("caret")
if(!require(MLmetrics)) install.packages("MLmetrics")

FGPE with \(\alpha = 1\)

n.total = 160
regions = c(rep("Forest",40), rep("Sea",80), rep("Urban", 40))
Entropy.Complexity = data.frame("Entropy" = numeric(n.total), 
                                "Complexity" = numeric(n.total),
                                "Region" = character(n.total), 
                                stringsAsFactors=FALSE)
Entropy.Complexity.csv = read.csv(file="../../Data/EntropyComplexityFGPET1A1.csv", 
                                  header=TRUE, sep=",")
Entropy.Complexity$Entropy = Entropy.Complexity.csv[,1]
Entropy.Complexity$Complexity = Entropy.Complexity.csv[,2]
Entropy.Complexity$Region = regions
split = 0.85
trainIndex = createDataPartition(Entropy.Complexity$Region, p = split, list = FALSE)
x = data.frame(Entropy.Complexity$Entropy[trainIndex], Entropy.Complexity$Complexity[trainIndex])
y = factor(Entropy.Complexity$Region[trainIndex])
x_validation = data.frame("Entropy" = Entropy.Complexity$Entropy[-trainIndex], "Complexity" = Entropy.Complexity$Complexity[-trainIndex])
y_validation = factor(Entropy.Complexity$Region[-trainIndex])
Entropy.Complexity = data.frame("Entropy" = Entropy.Complexity$Entropy[trainIndex], 
                                "Complexity" = Entropy.Complexity$Complexity[trainIndex],
                                "Region" = Entropy.Complexity$Region[trainIndex], 
                                stringsAsFactors=FALSE)

Creating KNN model and predicting

set.seed(123)
ctrl = trainControl(method="repeatedcv", number = 10, repeats = 10)
knnFit = train(Region~., data = Entropy.Complexity, method = "knn", 
               trControl = ctrl, 
               preProcess = c("center","scale"), 
               tuneLength = 20)
pred = predict(knnFit, newdata = x_validation)
xtab = table(pred, y_validation)
confusionMatrix(xtab)
Confusion Matrix and Statistics

        y_validation
pred     Forest Sea Urban
  Forest      5   2     0
  Sea         1  10     0
  Urban       0   0     6

Overall Statistics
                                          
               Accuracy : 0.875           
                 95% CI : (0.6764, 0.9734)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : 0.0001386       
                                          
                  Kappa : 0.8033          
                                          
 Mcnemar's Test P-Value : NA              

Statistics by Class:

                     Class: Forest Class: Sea Class: Urban
Sensitivity                 0.8333     0.8333         1.00
Specificity                 0.8889     0.9167         1.00
Pos Pred Value              0.7143     0.9091         1.00
Neg Pred Value              0.9412     0.8462         1.00
Prevalence                  0.2500     0.5000         0.25
Detection Rate              0.2083     0.4167         0.25
Detection Prevalence        0.2917     0.4583         0.25
Balanced Accuracy           0.8611     0.8750         1.00
cat("Accuracy: ", Accuracy(pred, y_validation), " Recall: ", Recall(pred, y_validation), " Precision: ", Precision(pred, y_validation), " F1-Score: ", F1_Score(pred, y_validation), "\n")
Accuracy:  0.875  Recall:  0.7142857  Precision:  0.8333333  F1-Score:  0.7692308 

FGPE with \(\alpha = 0.5\)

n.total = 160
regions = c(rep("Forest",40), rep("Sea",80), rep("Urban", 40))
Entropy.Complexity = data.frame("Entropy" = numeric(n.total), 
                                "Complexity" = numeric(n.total),
                                "Region" = character(n.total), 
                                stringsAsFactors=FALSE)
Entropy.Complexity.csv = read.csv(file="../../Data/EntropyComplexityFGPET1A05.csv", 
                                  header=TRUE, sep=",")
Entropy.Complexity$Entropy = Entropy.Complexity.csv[,1]
Entropy.Complexity$Complexity = Entropy.Complexity.csv[,2]
Entropy.Complexity$Region = regions
split = 0.85
trainIndex = createDataPartition(Entropy.Complexity$Region, p = split, list = FALSE)
x = data.frame(Entropy.Complexity$Entropy[trainIndex], Entropy.Complexity$Complexity[trainIndex])
y = factor(Entropy.Complexity$Region[trainIndex])
x_validation = data.frame("Entropy" = Entropy.Complexity$Entropy[-trainIndex], "Complexity" = Entropy.Complexity$Complexity[-trainIndex])
y_validation = factor(Entropy.Complexity$Region[-trainIndex])
Entropy.Complexity = data.frame("Entropy" = Entropy.Complexity$Entropy[trainIndex], 
                                "Complexity" = Entropy.Complexity$Complexity[trainIndex],
                                "Region" = Entropy.Complexity$Region[trainIndex], 
                                stringsAsFactors=FALSE)

Creating KNN model and predicting

set.seed(123)
ctrl = trainControl(method="repeatedcv", number = 10, repeats = 10)
knnFit = train(Region~., data = Entropy.Complexity, method = "knn", 
               trControl = ctrl, 
               preProcess = c("center","scale"), 
               tuneLength = 20)
pred = predict(knnFit, newdata = x_validation)
xtab = table(pred, y_validation)
confusionMatrix(xtab)
Confusion Matrix and Statistics

        y_validation
pred     Forest Sea Urban
  Forest      5   0     0
  Sea         1  12     0
  Urban       0   0     6

Overall Statistics
                                          
               Accuracy : 0.9583          
                 95% CI : (0.7888, 0.9989)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : 1.49e-06        
                                          
                  Kappa : 0.9322          
                                          
 Mcnemar's Test P-Value : NA              

Statistics by Class:

                     Class: Forest Class: Sea Class: Urban
Sensitivity                 0.8333     1.0000         1.00
Specificity                 1.0000     0.9167         1.00
Pos Pred Value              1.0000     0.9231         1.00
Neg Pred Value              0.9474     1.0000         1.00
Prevalence                  0.2500     0.5000         0.25
Detection Rate              0.2083     0.5000         0.25
Detection Prevalence        0.2083     0.5417         0.25
Balanced Accuracy           0.9167     0.9583         1.00
cat("Accuracy: ", Accuracy(pred, y_validation), " Recall: ", Recall(pred, y_validation), " Precision: ", Precision(pred, y_validation), " F1-Score: ", F1_Score(pred, y_validation), "\n")
Accuracy:  0.9583333  Recall:  1  Precision:  0.8333333  F1-Score:  0.9090909 

AAPE with A = 1

n.total = 160
regions = c(rep("Forest",40), rep("Sea",80), rep("Urban", 40))
Entropy.Complexity = data.frame("Entropy" = numeric(n.total), 
                                "Complexity" = numeric(n.total),
                                "Region" = character(n.total), 
                                stringsAsFactors=FALSE)
Entropy.Complexity.csv = read.csv(file="../../Data/EntropyComplexityAAPED3T1A1.csv", 
                                  header=TRUE, sep=",")
Entropy.Complexity$Entropy = Entropy.Complexity.csv[,1]
Entropy.Complexity$Complexity = Entropy.Complexity.csv[,2]
Entropy.Complexity$Region = regions
split = 0.85
trainIndex = createDataPartition(Entropy.Complexity$Region, p = split, list = FALSE)
x = data.frame(Entropy.Complexity$Entropy[trainIndex], Entropy.Complexity$Complexity[trainIndex])
y = factor(Entropy.Complexity$Region[trainIndex])
x_validation = data.frame("Entropy" = Entropy.Complexity$Entropy[-trainIndex], "Complexity" = Entropy.Complexity$Complexity[-trainIndex])
y_validation = factor(Entropy.Complexity$Region[-trainIndex])
Entropy.Complexity = data.frame("Entropy" = Entropy.Complexity$Entropy[trainIndex], 
                                "Complexity" = Entropy.Complexity$Complexity[trainIndex],
                                "Region" = Entropy.Complexity$Region[trainIndex], 
                                stringsAsFactors=FALSE)

Creating KNN model and predicting

set.seed(123)
ctrl = trainControl(method="repeatedcv", number = 10, repeats = 10)
knnFit = train(Region~., data = Entropy.Complexity, method = "knn", 
               trControl = ctrl, 
               preProcess = c("center","scale"), 
               tuneLength = 20)
pred = predict(knnFit, newdata = x_validation)
xtab = table(pred, y_validation)
confusionMatrix(xtab)
Confusion Matrix and Statistics

        y_validation
pred     Forest Sea Urban
  Forest      3   3     0
  Sea         3   9     0
  Urban       0   0     6

Overall Statistics
                                          
               Accuracy : 0.75            
                 95% CI : (0.5329, 0.9023)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : 0.01133         
                                          
                  Kappa : 0.6             
                                          
 Mcnemar's Test P-Value : NA              

Statistics by Class:

                     Class: Forest Class: Sea Class: Urban
Sensitivity                 0.5000      0.750         1.00
Specificity                 0.8333      0.750         1.00
Pos Pred Value              0.5000      0.750         1.00
Neg Pred Value              0.8333      0.750         1.00
Prevalence                  0.2500      0.500         0.25
Detection Rate              0.1250      0.375         0.25
Detection Prevalence        0.2500      0.500         0.25
Balanced Accuracy           0.6667      0.750         1.00
cat("Accuracy: ", Accuracy(pred, y_validation), " Recall: ", Recall(pred, y_validation), " Precision: ", Precision(pred, y_validation), " F1-Score: ", F1_Score(pred, y_validation), "\n")
Accuracy:  0.75  Recall:  0.5  Precision:  0.5  F1-Score:  0.5 

AAPE with A = 0.5

n.total = 160
regions = c(rep("Forest",40), rep("Sea",80), rep("Urban", 40))
Entropy.Complexity = data.frame("Entropy" = numeric(n.total), 
                                "Complexity" = numeric(n.total),
                                "Region" = character(n.total), 
                                stringsAsFactors=FALSE)
Entropy.Complexity.csv = read.csv(file="../../Data/EntropyComplexityAAPED3T1A05.csv", 
                                  header=TRUE, sep=",")
Entropy.Complexity$Entropy = Entropy.Complexity.csv[,1]
Entropy.Complexity$Complexity = Entropy.Complexity.csv[,2]
Entropy.Complexity$Region = regions
split = 0.85
trainIndex = createDataPartition(Entropy.Complexity$Region, p = split, list = FALSE)
x = data.frame(Entropy.Complexity$Entropy[trainIndex], Entropy.Complexity$Complexity[trainIndex])
y = factor(Entropy.Complexity$Region[trainIndex])
x_validation = data.frame("Entropy" = Entropy.Complexity$Entropy[-trainIndex], "Complexity" = Entropy.Complexity$Complexity[-trainIndex])
y_validation = factor(Entropy.Complexity$Region[-trainIndex])
Entropy.Complexity = data.frame("Entropy" = Entropy.Complexity$Entropy[trainIndex], 
                                "Complexity" = Entropy.Complexity$Complexity[trainIndex],
                                "Region" = Entropy.Complexity$Region[trainIndex], 
                                stringsAsFactors=FALSE)

Creating KNN model and predicting

set.seed(123)
ctrl = trainControl(method="repeatedcv", number = 10, repeats = 10)
knnFit = train(Region~., data = Entropy.Complexity, method = "knn", 
               trControl = ctrl, 
               preProcess = c("center","scale"), 
               tuneLength = 20)
pred = predict(knnFit, newdata = x_validation)
xtab = table(pred, y_validation)
confusionMatrix(xtab)
Confusion Matrix and Statistics

        y_validation
pred     Forest Sea Urban
  Forest      2   2     0
  Sea         4  10     0
  Urban       0   0     6

Overall Statistics
                                          
               Accuracy : 0.75            
                 95% CI : (0.5329, 0.9023)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : 0.01133         
                                          
                  Kappa : 0.5862          
                                          
 Mcnemar's Test P-Value : NA              

Statistics by Class:

                     Class: Forest Class: Sea Class: Urban
Sensitivity                0.33333     0.8333         1.00
Specificity                0.88889     0.6667         1.00
Pos Pred Value             0.50000     0.7143         1.00
Neg Pred Value             0.80000     0.8000         1.00
Prevalence                 0.25000     0.5000         0.25
Detection Rate             0.08333     0.4167         0.25
Detection Prevalence       0.16667     0.5833         0.25
Balanced Accuracy          0.61111     0.7500         1.00
cat("Accuracy: ", Accuracy(pred, y_validation), " Recall: ", Recall(pred, y_validation), " Precision: ", Precision(pred, y_validation), " F1-Score: ", F1_Score(pred, y_validation), "\n")
Accuracy:  0.75  Recall:  0.5  Precision:  0.3333333  F1-Score:  0.4 
LS0tCnRpdGxlOiAiQW5hbHlzaXMgb2YgYW1wbGl0dWRlIGluZm9ybWF0aW9uIHRlY2huaXF1ZXMgaW4gY2xhc3NpZmljYXRpb24gb2YgcmVnaW9ucyIKYXV0aG9yOiAiRWR1YXJkYSBDaGFnYXMiCmRhdGU6ICJNYXkgNywgMjAyMCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKLS0tCgpJbiB0aGlzIHNjcmlwdCwgd2Ugd2lsbCBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIFdBVEcgdGVjaG5pcXVlIGZvciByZWdpb24gY2xhc3NpZmljYXRpb24gaW4gUG9sU0FSIHRleHR1cmVzLgoKIyMjSW1wb3J0aW5nIHRoZSBwYWNrYWdlcwoKYGBge3J9CiMgTG9hZCBzb21lIHBhY2thZ2VzOiAKaWYoIXJlcXVpcmUoY2FyZXQpKSBpbnN0YWxsLnBhY2thZ2VzKCJjYXJldCIpCmlmKCFyZXF1aXJlKE1MbWV0cmljcykpIGluc3RhbGwucGFja2FnZXMoIk1MbWV0cmljcyIpCgpgYGAKCiMjI0ZHUEUgd2l0aCAkXGFscGhhID0gMSQKCmBgYHtyfQpuLnRvdGFsID0gMTYwCnJlZ2lvbnMgPSBjKHJlcCgiRm9yZXN0Iiw0MCksIHJlcCgiU2VhIiw4MCksIHJlcCgiVXJiYW4iLCA0MCkpCgpFbnRyb3B5LkNvbXBsZXhpdHkgPSBkYXRhLmZyYW1lKCJFbnRyb3B5IiA9IG51bWVyaWMobi50b3RhbCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDb21wbGV4aXR5IiA9IG51bWVyaWMobi50b3RhbCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZ2lvbiIgPSBjaGFyYWN0ZXIobi50b3RhbCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpFbnRyb3B5LkNvbXBsZXhpdHkuY3N2ID0gcmVhZC5jc3YoZmlsZT0iLi4vLi4vRGF0YS9FbnRyb3B5Q29tcGxleGl0eUZHUEVUMUExLmNzdiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyPVRSVUUsIHNlcD0iLCIpCkVudHJvcHkuQ29tcGxleGl0eSRFbnRyb3B5ID0gRW50cm9weS5Db21wbGV4aXR5LmNzdlssMV0KRW50cm9weS5Db21wbGV4aXR5JENvbXBsZXhpdHkgPSBFbnRyb3B5LkNvbXBsZXhpdHkuY3N2WywyXQpFbnRyb3B5LkNvbXBsZXhpdHkkUmVnaW9uID0gcmVnaW9ucwoKCnNwbGl0ID0gMC44NQp0cmFpbkluZGV4ID0gY3JlYXRlRGF0YVBhcnRpdGlvbihFbnRyb3B5LkNvbXBsZXhpdHkkUmVnaW9uLCBwID0gc3BsaXQsIGxpc3QgPSBGQUxTRSkKCnggPSBkYXRhLmZyYW1lKEVudHJvcHkuQ29tcGxleGl0eSRFbnRyb3B5W3RyYWluSW5kZXhdLCBFbnRyb3B5LkNvbXBsZXhpdHkkQ29tcGxleGl0eVt0cmFpbkluZGV4XSkKeSA9IGZhY3RvcihFbnRyb3B5LkNvbXBsZXhpdHkkUmVnaW9uW3RyYWluSW5kZXhdKQoKeF92YWxpZGF0aW9uID0gZGF0YS5mcmFtZSgiRW50cm9weSIgPSBFbnRyb3B5LkNvbXBsZXhpdHkkRW50cm9weVstdHJhaW5JbmRleF0sICJDb21wbGV4aXR5IiA9IEVudHJvcHkuQ29tcGxleGl0eSRDb21wbGV4aXR5Wy10cmFpbkluZGV4XSkKeV92YWxpZGF0aW9uID0gZmFjdG9yKEVudHJvcHkuQ29tcGxleGl0eSRSZWdpb25bLXRyYWluSW5kZXhdKQoKRW50cm9weS5Db21wbGV4aXR5ID0gZGF0YS5mcmFtZSgiRW50cm9weSIgPSBFbnRyb3B5LkNvbXBsZXhpdHkkRW50cm9weVt0cmFpbkluZGV4XSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvbXBsZXhpdHkiID0gRW50cm9weS5Db21wbGV4aXR5JENvbXBsZXhpdHlbdHJhaW5JbmRleF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZ2lvbiIgPSBFbnRyb3B5LkNvbXBsZXhpdHkkUmVnaW9uW3RyYWluSW5kZXhdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpgYGAKCiMjIyNDcmVhdGluZyBLTk4gbW9kZWwgYW5kIHByZWRpY3RpbmcKYGBge3J9CnNldC5zZWVkKDEyMykKY3RybCA9IHRyYWluQ29udHJvbChtZXRob2Q9InJlcGVhdGVkY3YiLCBudW1iZXIgPSAxMCwgcmVwZWF0cyA9IDEwKQprbm5GaXQgPSB0cmFpbihSZWdpb25+LiwgZGF0YSA9IEVudHJvcHkuQ29tcGxleGl0eSwgbWV0aG9kID0gImtubiIsIAogICAgICAgICAgICAgICB0ckNvbnRyb2wgPSBjdHJsLCAKICAgICAgICAgICAgICAgcHJlUHJvY2VzcyA9IGMoImNlbnRlciIsInNjYWxlIiksIAogICAgICAgICAgICAgICB0dW5lTGVuZ3RoID0gMjApCgpwcmVkID0gcHJlZGljdChrbm5GaXQsIG5ld2RhdGEgPSB4X3ZhbGlkYXRpb24pCgp4dGFiID0gdGFibGUocHJlZCwgeV92YWxpZGF0aW9uKQpjb25mdXNpb25NYXRyaXgoeHRhYikKYGBgCgpgYGB7cn0KY2F0KCJBY2N1cmFjeTogIiwgQWNjdXJhY3kocHJlZCwgeV92YWxpZGF0aW9uKSwgIiBSZWNhbGw6ICIsIFJlY2FsbChwcmVkLCB5X3ZhbGlkYXRpb24pLCAiIFByZWNpc2lvbjogIiwgUHJlY2lzaW9uKHByZWQsIHlfdmFsaWRhdGlvbiksICIgRjEtU2NvcmU6ICIsIEYxX1Njb3JlKHByZWQsIHlfdmFsaWRhdGlvbiksICJcbiIpCmBgYAoKIyMjRkdQRSB3aXRoICRcYWxwaGEgPSAwLjUkCgpgYGB7cn0Kbi50b3RhbCA9IDE2MApyZWdpb25zID0gYyhyZXAoIkZvcmVzdCIsNDApLCByZXAoIlNlYSIsODApLCByZXAoIlVyYmFuIiwgNDApKQoKRW50cm9weS5Db21wbGV4aXR5ID0gZGF0YS5mcmFtZSgiRW50cm9weSIgPSBudW1lcmljKG4udG90YWwpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29tcGxleGl0eSIgPSBudW1lcmljKG4udG90YWwpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWdpb24iID0gY2hhcmFjdGVyKG4udG90YWwpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQoKRW50cm9weS5Db21wbGV4aXR5LmNzdiA9IHJlYWQuY3N2KGZpbGU9Ii4uLy4uL0RhdGEvRW50cm9weUNvbXBsZXhpdHlGR1BFVDFBMDUuY3N2IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXI9VFJVRSwgc2VwPSIsIikKRW50cm9weS5Db21wbGV4aXR5JEVudHJvcHkgPSBFbnRyb3B5LkNvbXBsZXhpdHkuY3N2WywxXQpFbnRyb3B5LkNvbXBsZXhpdHkkQ29tcGxleGl0eSA9IEVudHJvcHkuQ29tcGxleGl0eS5jc3ZbLDJdCkVudHJvcHkuQ29tcGxleGl0eSRSZWdpb24gPSByZWdpb25zCgoKc3BsaXQgPSAwLjg1CnRyYWluSW5kZXggPSBjcmVhdGVEYXRhUGFydGl0aW9uKEVudHJvcHkuQ29tcGxleGl0eSRSZWdpb24sIHAgPSBzcGxpdCwgbGlzdCA9IEZBTFNFKQoKeCA9IGRhdGEuZnJhbWUoRW50cm9weS5Db21wbGV4aXR5JEVudHJvcHlbdHJhaW5JbmRleF0sIEVudHJvcHkuQ29tcGxleGl0eSRDb21wbGV4aXR5W3RyYWluSW5kZXhdKQp5ID0gZmFjdG9yKEVudHJvcHkuQ29tcGxleGl0eSRSZWdpb25bdHJhaW5JbmRleF0pCgp4X3ZhbGlkYXRpb24gPSBkYXRhLmZyYW1lKCJFbnRyb3B5IiA9IEVudHJvcHkuQ29tcGxleGl0eSRFbnRyb3B5Wy10cmFpbkluZGV4XSwgIkNvbXBsZXhpdHkiID0gRW50cm9weS5Db21wbGV4aXR5JENvbXBsZXhpdHlbLXRyYWluSW5kZXhdKQp5X3ZhbGlkYXRpb24gPSBmYWN0b3IoRW50cm9weS5Db21wbGV4aXR5JFJlZ2lvblstdHJhaW5JbmRleF0pCgpFbnRyb3B5LkNvbXBsZXhpdHkgPSBkYXRhLmZyYW1lKCJFbnRyb3B5IiA9IEVudHJvcHkuQ29tcGxleGl0eSRFbnRyb3B5W3RyYWluSW5kZXhdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29tcGxleGl0eSIgPSBFbnRyb3B5LkNvbXBsZXhpdHkkQ29tcGxleGl0eVt0cmFpbkluZGV4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVnaW9uIiA9IEVudHJvcHkuQ29tcGxleGl0eSRSZWdpb25bdHJhaW5JbmRleF0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCmBgYAoKIyMjI0NyZWF0aW5nIEtOTiBtb2RlbCBhbmQgcHJlZGljdGluZwpgYGB7cn0Kc2V0LnNlZWQoMTIzKQpjdHJsID0gdHJhaW5Db250cm9sKG1ldGhvZD0icmVwZWF0ZWRjdiIsIG51bWJlciA9IDEwLCByZXBlYXRzID0gMTApCmtubkZpdCA9IHRyYWluKFJlZ2lvbn4uLCBkYXRhID0gRW50cm9weS5Db21wbGV4aXR5LCBtZXRob2QgPSAia25uIiwgCiAgICAgICAgICAgICAgIHRyQ29udHJvbCA9IGN0cmwsIAogICAgICAgICAgICAgICBwcmVQcm9jZXNzID0gYygiY2VudGVyIiwic2NhbGUiKSwgCiAgICAgICAgICAgICAgIHR1bmVMZW5ndGggPSAyMCkKCnByZWQgPSBwcmVkaWN0KGtubkZpdCwgbmV3ZGF0YSA9IHhfdmFsaWRhdGlvbikKCnh0YWIgPSB0YWJsZShwcmVkLCB5X3ZhbGlkYXRpb24pCmNvbmZ1c2lvbk1hdHJpeCh4dGFiKQpgYGAKCmBgYHtyfQpjYXQoIkFjY3VyYWN5OiAiLCBBY2N1cmFjeShwcmVkLCB5X3ZhbGlkYXRpb24pLCAiIFJlY2FsbDogIiwgUmVjYWxsKHByZWQsIHlfdmFsaWRhdGlvbiksICIgUHJlY2lzaW9uOiAiLCBQcmVjaXNpb24ocHJlZCwgeV92YWxpZGF0aW9uKSwgIiBGMS1TY29yZTogIiwgRjFfU2NvcmUocHJlZCwgeV92YWxpZGF0aW9uKSwgIlxuIikKYGBgCgojIyNBQVBFIHdpdGggQSA9IDEKCmBgYHtyfQpuLnRvdGFsID0gMTYwCnJlZ2lvbnMgPSBjKHJlcCgiRm9yZXN0Iiw0MCksIHJlcCgiU2VhIiw4MCksIHJlcCgiVXJiYW4iLCA0MCkpCgpFbnRyb3B5LkNvbXBsZXhpdHkgPSBkYXRhLmZyYW1lKCJFbnRyb3B5IiA9IG51bWVyaWMobi50b3RhbCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDb21wbGV4aXR5IiA9IG51bWVyaWMobi50b3RhbCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZ2lvbiIgPSBjaGFyYWN0ZXIobi50b3RhbCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpFbnRyb3B5LkNvbXBsZXhpdHkuY3N2ID0gcmVhZC5jc3YoZmlsZT0iLi4vLi4vRGF0YS9FbnRyb3B5Q29tcGxleGl0eUFBUEVEM1QxQTEuY3N2IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXI9VFJVRSwgc2VwPSIsIikKRW50cm9weS5Db21wbGV4aXR5JEVudHJvcHkgPSBFbnRyb3B5LkNvbXBsZXhpdHkuY3N2WywxXQpFbnRyb3B5LkNvbXBsZXhpdHkkQ29tcGxleGl0eSA9IEVudHJvcHkuQ29tcGxleGl0eS5jc3ZbLDJdCkVudHJvcHkuQ29tcGxleGl0eSRSZWdpb24gPSByZWdpb25zCgoKc3BsaXQgPSAwLjg1CnRyYWluSW5kZXggPSBjcmVhdGVEYXRhUGFydGl0aW9uKEVudHJvcHkuQ29tcGxleGl0eSRSZWdpb24sIHAgPSBzcGxpdCwgbGlzdCA9IEZBTFNFKQoKeCA9IGRhdGEuZnJhbWUoRW50cm9weS5Db21wbGV4aXR5JEVudHJvcHlbdHJhaW5JbmRleF0sIEVudHJvcHkuQ29tcGxleGl0eSRDb21wbGV4aXR5W3RyYWluSW5kZXhdKQp5ID0gZmFjdG9yKEVudHJvcHkuQ29tcGxleGl0eSRSZWdpb25bdHJhaW5JbmRleF0pCgp4X3ZhbGlkYXRpb24gPSBkYXRhLmZyYW1lKCJFbnRyb3B5IiA9IEVudHJvcHkuQ29tcGxleGl0eSRFbnRyb3B5Wy10cmFpbkluZGV4XSwgIkNvbXBsZXhpdHkiID0gRW50cm9weS5Db21wbGV4aXR5JENvbXBsZXhpdHlbLXRyYWluSW5kZXhdKQp5X3ZhbGlkYXRpb24gPSBmYWN0b3IoRW50cm9weS5Db21wbGV4aXR5JFJlZ2lvblstdHJhaW5JbmRleF0pCgpFbnRyb3B5LkNvbXBsZXhpdHkgPSBkYXRhLmZyYW1lKCJFbnRyb3B5IiA9IEVudHJvcHkuQ29tcGxleGl0eSRFbnRyb3B5W3RyYWluSW5kZXhdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29tcGxleGl0eSIgPSBFbnRyb3B5LkNvbXBsZXhpdHkkQ29tcGxleGl0eVt0cmFpbkluZGV4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVnaW9uIiA9IEVudHJvcHkuQ29tcGxleGl0eSRSZWdpb25bdHJhaW5JbmRleF0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCmBgYAoKIyMjI0NyZWF0aW5nIEtOTiBtb2RlbCBhbmQgcHJlZGljdGluZwpgYGB7cn0Kc2V0LnNlZWQoMTIzKQpjdHJsID0gdHJhaW5Db250cm9sKG1ldGhvZD0icmVwZWF0ZWRjdiIsIG51bWJlciA9IDEwLCByZXBlYXRzID0gMTApCmtubkZpdCA9IHRyYWluKFJlZ2lvbn4uLCBkYXRhID0gRW50cm9weS5Db21wbGV4aXR5LCBtZXRob2QgPSAia25uIiwgCiAgICAgICAgICAgICAgIHRyQ29udHJvbCA9IGN0cmwsIAogICAgICAgICAgICAgICBwcmVQcm9jZXNzID0gYygiY2VudGVyIiwic2NhbGUiKSwgCiAgICAgICAgICAgICAgIHR1bmVMZW5ndGggPSAyMCkKCnByZWQgPSBwcmVkaWN0KGtubkZpdCwgbmV3ZGF0YSA9IHhfdmFsaWRhdGlvbikKCnh0YWIgPSB0YWJsZShwcmVkLCB5X3ZhbGlkYXRpb24pCmNvbmZ1c2lvbk1hdHJpeCh4dGFiKQpgYGAKCmBgYHtyfQpjYXQoIkFjY3VyYWN5OiAiLCBBY2N1cmFjeShwcmVkLCB5X3ZhbGlkYXRpb24pLCAiIFJlY2FsbDogIiwgUmVjYWxsKHByZWQsIHlfdmFsaWRhdGlvbiksICIgUHJlY2lzaW9uOiAiLCBQcmVjaXNpb24ocHJlZCwgeV92YWxpZGF0aW9uKSwgIiBGMS1TY29yZTogIiwgRjFfU2NvcmUocHJlZCwgeV92YWxpZGF0aW9uKSwgIlxuIikKYGBgCgojIyNBQVBFIHdpdGggQSA9IDAuNQoKYGBge3J9Cm4udG90YWwgPSAxNjAKcmVnaW9ucyA9IGMocmVwKCJGb3Jlc3QiLDQwKSwgcmVwKCJTZWEiLDgwKSwgcmVwKCJVcmJhbiIsIDQwKSkKCkVudHJvcHkuQ29tcGxleGl0eSA9IGRhdGEuZnJhbWUoIkVudHJvcHkiID0gbnVtZXJpYyhuLnRvdGFsKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvbXBsZXhpdHkiID0gbnVtZXJpYyhuLnRvdGFsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVnaW9uIiA9IGNoYXJhY3RlcihuLnRvdGFsKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKCkVudHJvcHkuQ29tcGxleGl0eS5jc3YgPSByZWFkLmNzdihmaWxlPSIuLi8uLi9EYXRhL0VudHJvcHlDb21wbGV4aXR5QUFQRUQzVDFBMDUuY3N2IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXI9VFJVRSwgc2VwPSIsIikKRW50cm9weS5Db21wbGV4aXR5JEVudHJvcHkgPSBFbnRyb3B5LkNvbXBsZXhpdHkuY3N2WywxXQpFbnRyb3B5LkNvbXBsZXhpdHkkQ29tcGxleGl0eSA9IEVudHJvcHkuQ29tcGxleGl0eS5jc3ZbLDJdCkVudHJvcHkuQ29tcGxleGl0eSRSZWdpb24gPSByZWdpb25zCgoKc3BsaXQgPSAwLjg1CnRyYWluSW5kZXggPSBjcmVhdGVEYXRhUGFydGl0aW9uKEVudHJvcHkuQ29tcGxleGl0eSRSZWdpb24sIHAgPSBzcGxpdCwgbGlzdCA9IEZBTFNFKQoKeCA9IGRhdGEuZnJhbWUoRW50cm9weS5Db21wbGV4aXR5JEVudHJvcHlbdHJhaW5JbmRleF0sIEVudHJvcHkuQ29tcGxleGl0eSRDb21wbGV4aXR5W3RyYWluSW5kZXhdKQp5ID0gZmFjdG9yKEVudHJvcHkuQ29tcGxleGl0eSRSZWdpb25bdHJhaW5JbmRleF0pCgp4X3ZhbGlkYXRpb24gPSBkYXRhLmZyYW1lKCJFbnRyb3B5IiA9IEVudHJvcHkuQ29tcGxleGl0eSRFbnRyb3B5Wy10cmFpbkluZGV4XSwgIkNvbXBsZXhpdHkiID0gRW50cm9weS5Db21wbGV4aXR5JENvbXBsZXhpdHlbLXRyYWluSW5kZXhdKQp5X3ZhbGlkYXRpb24gPSBmYWN0b3IoRW50cm9weS5Db21wbGV4aXR5JFJlZ2lvblstdHJhaW5JbmRleF0pCgpFbnRyb3B5LkNvbXBsZXhpdHkgPSBkYXRhLmZyYW1lKCJFbnRyb3B5IiA9IEVudHJvcHkuQ29tcGxleGl0eSRFbnRyb3B5W3RyYWluSW5kZXhdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29tcGxleGl0eSIgPSBFbnRyb3B5LkNvbXBsZXhpdHkkQ29tcGxleGl0eVt0cmFpbkluZGV4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVnaW9uIiA9IEVudHJvcHkuQ29tcGxleGl0eSRSZWdpb25bdHJhaW5JbmRleF0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCmBgYAoKIyMjI0NyZWF0aW5nIEtOTiBtb2RlbCBhbmQgcHJlZGljdGluZwpgYGB7cn0Kc2V0LnNlZWQoMTIzKQpjdHJsID0gdHJhaW5Db250cm9sKG1ldGhvZD0icmVwZWF0ZWRjdiIsIG51bWJlciA9IDEwLCByZXBlYXRzID0gMTApCmtubkZpdCA9IHRyYWluKFJlZ2lvbn4uLCBkYXRhID0gRW50cm9weS5Db21wbGV4aXR5LCBtZXRob2QgPSAia25uIiwgCiAgICAgICAgICAgICAgIHRyQ29udHJvbCA9IGN0cmwsIAogICAgICAgICAgICAgICBwcmVQcm9jZXNzID0gYygiY2VudGVyIiwic2NhbGUiKSwgCiAgICAgICAgICAgICAgIHR1bmVMZW5ndGggPSAyMCkKCnByZWQgPSBwcmVkaWN0KGtubkZpdCwgbmV3ZGF0YSA9IHhfdmFsaWRhdGlvbikKCnh0YWIgPSB0YWJsZShwcmVkLCB5X3ZhbGlkYXRpb24pCmNvbmZ1c2lvbk1hdHJpeCh4dGFiKQpgYGAKCmBgYHtyfQpjYXQoIkFjY3VyYWN5OiAiLCBBY2N1cmFjeShwcmVkLCB5X3ZhbGlkYXRpb24pLCAiIFJlY2FsbDogIiwgUmVjYWxsKHByZWQsIHlfdmFsaWRhdGlvbiksICIgUHJlY2lzaW9uOiAiLCBQcmVjaXNpb24ocHJlZCwgeV92YWxpZGF0aW9uKSwgIiBGMS1TY29yZTogIiwgRjFfU2NvcmUocHJlZCwgeV92YWxpZGF0aW9uKSwgIlxuIikKYGBgCg==