DATA Preparation

Introduction

GRE.Score - GRE 점수 TOEFL.Score - 토플 점수 University.Ranking - 학부 대학 레이팅 SOP - 자기 소개서 점수 LOR - 추천서 점수 CGPA - 학부 점수 Research - 연구 경험의 유무 Chance of Admit - 대학원 합격 확률

  1. Target Variable 이 있는가?

Target Variable 에 따라 지도/비지도학습으로 나눌 수 있기 때문에 중요

Taraget 있음 - 지도 학습 설정

## 'data.frame':    500 obs. of  8 variables:
##  $ GRE.Score        : int  337 324 316 322 314 330 321 308 302 323 ...
##  $ TOEFL.Score      : int  118 107 104 110 103 115 109 101 102 108 ...
##  $ University.Rating: int  4 4 3 3 2 5 3 2 1 3 ...
##  $ SOP              : num  4.5 4 3 3.5 2 4.5 3 3 2 3.5 ...
##  $ LOR              : num  4.5 4.5 3.5 2.5 3 3 4 4 1.5 3 ...
##  $ CGPA             : num  9.65 8.87 8 8.67 8.21 9.34 8.2 7.9 8 8.6 ...
##  $ Research         : int  1 1 1 1 0 1 1 0 0 0 ...
##  $ Chance.of.Admit  : num  0.92 0.76 0.72 0.8 0.65 0.9 0.75 0.68 0.5 0.45 ...

Preprocessing : NA

##         GRE.Score       TOEFL.Score University.Rating               SOP 
##                 0                 0                 0                 0 
##               LOR              CGPA          Research   Chance.of.Admit 
##                 0                 0                 0                 0
## [1] 0

Preprocessing : Histogram & Boxplot

##  [1] 337 324 316 322 314 330 321 308 302 323 325 327 328 307 311 317 319 318 303
## [20] 312 334 336 340 298 295 310 300 338 331 320 299 304 313 332 326 329 339 309
## [39] 315 301 296 294 306 305 290 335 333 297 293

## null device 
##           1
## 
##   0   1 
## 220 280
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.3400  0.6300  0.7200  0.7217  0.8200  0.9700
## null device 
##           1

Modelling

Target 이 명목 - Classification VS 연속 - Regression

Target 의 범위가 0~1 사이의 제한이 있기 때문에, Logistic Regression 으로 진행

  1. 로지스틱 회귀 분석

  2. 엘라스틱 넷

  3. 랜덤 포레스트

  4. SVM

  5. 커널 서포트 벡터 머신

Logistic Modelling

## Generalized Linear Model 
## 
## 350 samples
##   7 predictor
## 
## Pre-processing: centered (7), scaled (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 314, 314, 314, 317, 317, 315, ... 
## Resampling results:
## 
##   RMSE        Rsquared   MAE       
##   0.06088181  0.8226372  0.04426021
  1. RMSE : 작을 수록 좋음 (실제 - 예측)

1.1 RMSE 구하는 방법

postResample()

RMSE()

직접 계산 

postResample

##       RMSE   Rsquared        MAE 
## 0.05797190 0.81681161 0.04105176

RMSE

## [1] 0.0579719

직접계산

## [1] 0.0579719
  1. R-square

직접 계산

## [1] 0.8146877
  1. MAE (MEAN Absoulte Error) - 오차항의 절대값

    |실제값 - 예측값|

##       RMSE   Rsquared        MAE 
## 0.05797190 0.81681161 0.04105176
## [1] 0.04105176

Elastic Net

머신 러닝의 목적은 -> 최적화 (optimaztion) -> Objective Function (목적 함수)

Object Function = 오차 제곱합 (Error: 실제- 추청) 을 줄이는 것

<목적 함수를 최적화 한다는 것은?>

오차제곱합을 최소화 시키는 모수를 추정한다는 것.

Elastic Net - Penalty : 목적함수의 최적화를 도와주는 역할 (=contraint, regularization)

목적함수 + 패널티 = 최적화된 모수

Penalty 종류

사진

사진

최소화 시키는 B를 찾는것이 목적이며, Elastic Net 은 L1 (라쏘) + L2 (릿지) 패널티를 사용한다.

L1 : B는 마름모 안에 있어야 한다. 걸쳐있어도 괜찮음 (네모) : Lasso Regression

L2 : B의 제곱합 안에 있어야한다. (타원형) :Ridge Regression

## glmnet 
## 
## 350 samples
##   7 predictor
## 
## Pre-processing: centered (7), scaled (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 316, 315, 315, 314, 314, 314, ... 
## Resampling results across tuning parameters:
## 
##   alpha  lambda        RMSE        Rsquared   MAE       
##   0.10   0.0002548148  0.06115579  0.8215358  0.04432927
##   0.10   0.0025481481  0.06113681  0.8216559  0.04429890
##   0.10   0.0254814812  0.06225507  0.8180528  0.04486913
##   0.55   0.0002548148  0.06115361  0.8215213  0.04430084
##   0.55   0.0025481481  0.06115367  0.8216010  0.04425493
##   0.55   0.0254814812  0.06404851  0.8204819  0.04686890
##   1.00   0.0002548148  0.06116789  0.8214258  0.04430305
##   1.00   0.0025481481  0.06122845  0.8212661  0.04426004
##   1.00   0.0254814812  0.06831794  0.8094939  0.05130325
## 
## RMSE was used to select the optimal model using the smallest value.
## The final values used for the model were alpha = 0.1 and lambda = 0.002548148.

<결과 해석>

  1. alpha = 1 이다. 즉, 라쏘 / alpha=0 즉, Ridge 다

    정규화의 비율을 나타내는 모수

  2. lamdba

    전체 제약식의 크기를 나타낸다.

##       RMSE   Rsquared        MAE 
## 0.05759752 0.81881695 0.04075955

Random Forest

Decision Tree 가 여러번 그려서 예측하게 만드는 것. 각 Tree 의 결과를 붙이는 것

rf() 사용

## Random Forest 
## 
## 350 samples
##   7 predictor
## 
## Pre-processing: centered (7), scaled (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 315, 314, 316, 314, 315, 315, ... 
## Resampling results across tuning parameters:
## 
##   mtry  RMSE        Rsquared   MAE       
##   2     0.06330474  0.8076945  0.04467191
##   4     0.06420105  0.8024873  0.04487456
##   7     0.06622380  0.7907155  0.04640276
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was mtry = 2.

mtry =2인 값이 최적화된 값

RMSE 값은 낮을 수록 좋음 (하단 그림)

##       RMSE   Rsquared        MAE 
## 0.05784775 0.81636321 0.04135581

SVM

## Support Vector Machines with Linear Kernel 
## 
## 350 samples
##   7 predictor
## 
## Pre-processing: centered (7), scaled (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 316, 314, 315, 315, 314, 315, ... 
## Resampling results:
## 
##   RMSE        Rsquared   MAE       
##   0.06203925  0.8194168  0.04323064
## 
## Tuning parameter 'C' was held constant at a value of 1
##       RMSE   Rsquared        MAE 
## 0.05871683 0.82091845 0.04052400

커널 SVM

## Support Vector Machines with Polynomial Kernel 
## 
## 350 samples
##   7 predictor
## 
## Pre-processing: centered (7), scaled (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 316, 315, 316, 314, 315, 314, ... 
## Resampling results across tuning parameters:
## 
##   degree  scale  C     RMSE        Rsquared   MAE       
##   1       0.001  0.25  0.11101217  0.7986452  0.08763644
##   1       0.001  0.50  0.09038984  0.8003988  0.06932875
##   1       0.001  1.00  0.07375383  0.8035701  0.05308638
##   1       0.010  0.25  0.06698655  0.8101050  0.04689173
##   1       0.010  0.50  0.06420095  0.8163621  0.04460727
##   1       0.010  1.00  0.06283496  0.8209871  0.04373283
##   1       0.100  0.25  0.06189390  0.8240876  0.04311051
##   1       0.100  0.50  0.06160267  0.8248343  0.04302902
##   1       0.100  1.00  0.06151960  0.8247830  0.04306234
##   2       0.001  0.25  0.09038852  0.8004018  0.06932513
##   2       0.001  0.50  0.07376284  0.8035875  0.05308453
##   2       0.001  1.00  0.06785106  0.8088417  0.04771846
##   2       0.010  0.25  0.06415825  0.8166842  0.04459720
##   2       0.010  0.50  0.06262941  0.8216866  0.04354784
##   2       0.010  1.00  0.06177907  0.8243951  0.04303447
##   2       0.100  0.25  0.06074884  0.8274281  0.04226873
##   2       0.100  0.50  0.06052952  0.8277168  0.04213215
##   2       0.100  1.00  0.06058939  0.8269039  0.04216885
##   3       0.001  0.25  0.07932900  0.8019707  0.05867723
##   3       0.001  0.50  0.06956808  0.8066014  0.04921830
##   3       0.001  1.00  0.06610394  0.8116417  0.04609460
##   3       0.010  0.25  0.06301703  0.8204469  0.04378371
##   3       0.010  0.50  0.06192837  0.8239894  0.04314165
##   3       0.010  1.00  0.06119671  0.8266704  0.04259881
##   3       0.100  0.25  0.06049868  0.8282863  0.04201662
##   3       0.100  0.50  0.06125080  0.8231222  0.04260882
##   3       0.100  1.00  0.06219942  0.8170933  0.04337886
## 
## RMSE was used to select the optimal model using the smallest value.
## The final values used for the model were degree = 3, scale = 0.1 and C = 0.25.

##       RMSE   Rsquared        MAE 
## 0.05834794 0.82775010 0.04118332

Clustering - K-Mean, Hclustering

  1. K-MEANS

##    GRE.Score TOEFL.Score University.Rating         SOP         LOR         CGPA
## 1 -1.1146540 -1.11227795       -1.07754185 -1.20759122 -1.05344377 -1.174945070
## 2  0.1775932  0.05064234       -0.08683261 -0.02866969 -0.05421848  0.002846773
## 3 -0.4080599 -0.28218199       -0.17021701 -0.03154183 -0.01321067 -0.235724231
## 4  1.1466053  1.15733680        1.16496729  1.08188691  0.96069732  1.216050779
##     Research
## 1 -0.6879234
## 2  0.8855184
## 3 -1.1270234
## 4  0.7307075

## null device 
##           1
  1. Hclust

Logistic Regression

  1. KNN
  2. Boosted 로지스틱 회귀
  3. Penalized 로지스틱 회귀
  4. 나이브 베이즈
  5. 랜덤 포레스트
  6. 서포트 벡터 머신
  7. 커널 서포트 벡터 머신

##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.3400  0.6300  0.7200  0.7217  0.8200  0.9700
## [1] 0.72
##  Factor w/ 2 levels "0","1": 2 2 2 2 1 2 2 1 1 1 ...
## [1] 1 0
## Levels: 0 1

KNN

가장 가까운 K 개의 이웃을 보는 것

## k-Nearest Neighbors 
## 
## 350 samples
##   7 predictor
##   2 classes: '0', '1' 
## 
## Pre-processing: centered (7), scaled (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 314, 315, 315, 315, 316, 315, ... 
## Resampling results across tuning parameters:
## 
##   k   Accuracy   Kappa    
##    1  0.8370672  0.6724243
##    2  0.8387983  0.6761329
##    3  0.8695565  0.7380581
##    4  0.8616013  0.7219644
##    5  0.8832250  0.7652513
##    6  0.8831447  0.7650922
##    7  0.8860364  0.7708929
##    8  0.8842717  0.7673118
##    9  0.8883212  0.7756319
##   10  0.8848926  0.7686115
##   11  0.8871951  0.7736279
##   12  0.8849244  0.7689364
##   13  0.8911307  0.7815553
##   14  0.8871130  0.7735362
##   15  0.8837488  0.7668651
##   16  0.8820654  0.7635209
##   17  0.8792082  0.7578016
##   18  0.8775415  0.7544751
##   19  0.8831933  0.7657717
##   20  0.8820504  0.7635590
## 
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was k = 13.

K=15 일때 0.8925로 가장 높은 정확도를 가진다.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 54 12
##          1 18 66
##                                          
##                Accuracy : 0.8            
##                  95% CI : (0.727, 0.8608)
##     No Information Rate : 0.52           
##     P-Value [Acc > NIR] : 9.977e-13      
##                                          
##                   Kappa : 0.5981         
##                                          
##  Mcnemar's Test P-Value : 0.3613         
##                                          
##             Sensitivity : 0.7500         
##             Specificity : 0.8462         
##          Pos Pred Value : 0.8182         
##          Neg Pred Value : 0.7857         
##              Prevalence : 0.4800         
##          Detection Rate : 0.3600         
##    Detection Prevalence : 0.4400         
##       Balanced Accuracy : 0.7981         
##                                          
##        'Positive' Class : 0              
## 

Boosted Logistic

method = “LogitBoost”

가장 간단한 모형을 만들어서 발전을 시키는 것

## Boosted Logistic Regression 
## 
## 350 samples
##   7 predictor
##   2 classes: '0', '1' 
## 
## Pre-processing: scaled (7), centered (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 315, 314, 315, 315, 316, 314, ... 
## Resampling results across tuning parameters:
## 
##   nIter  Accuracy   Kappa    
##   11     0.8651727  0.7284506
##   21     0.8563576  0.7109251
##   31     0.8513585  0.7005781
## 
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was nIter = 11.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 51  9
##          1 21 69
##                                          
##                Accuracy : 0.8            
##                  95% CI : (0.727, 0.8608)
##     No Information Rate : 0.52           
##     P-Value [Acc > NIR] : 9.977e-13      
##                                          
##                   Kappa : 0.5968         
##                                          
##  Mcnemar's Test P-Value : 0.04461        
##                                          
##             Sensitivity : 0.7083         
##             Specificity : 0.8846         
##          Pos Pred Value : 0.8500         
##          Neg Pred Value : 0.7667         
##              Prevalence : 0.4800         
##          Detection Rate : 0.3400         
##    Detection Prevalence : 0.4000         
##       Balanced Accuracy : 0.7965         
##                                          
##        'Positive' Class : 0              
## 

Penalized Logistic

method = plr

정규화 -> 모델의 복잡성 조절 -> 오버피팅 방지

## Penalized Logistic Regression 
## 
## 350 samples
##   7 predictor
##   2 classes: '0', '1' 
## 
## Pre-processing: scaled (7), centered (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 316, 316, 316, 314, 315, 314, ... 
## Resampling results across tuning parameters:
## 
##   lambda  Accuracy   Kappa    
##   0e+00   0.8851914  0.7697735
##   1e-04   0.8851914  0.7697735
##   1e-01   0.8857302  0.7709273
## 
## Tuning parameter 'cp' was held constant at a value of bic
## Accuracy was used to select the optimal model using the largest value.
## The final values used for the model were lambda = 0.1 and cp = bic.

cp (complexity parameter 복잡성) - 모형 평가 방법 중, BIC 기준

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 58 11
##          1 14 67
##                                           
##                Accuracy : 0.8333          
##                  95% CI : (0.7639, 0.8891)
##     No Information Rate : 0.52            
##     P-Value [Acc > NIR] : 8.444e-16       
##                                           
##                   Kappa : 0.6656          
##                                           
##  Mcnemar's Test P-Value : 0.6892          
##                                           
##             Sensitivity : 0.8056          
##             Specificity : 0.8590          
##          Pos Pred Value : 0.8406          
##          Neg Pred Value : 0.8272          
##              Prevalence : 0.4800          
##          Detection Rate : 0.3867          
##    Detection Prevalence : 0.4600          
##       Balanced Accuracy : 0.8323          
##                                           
##        'Positive' Class : 0               
## 

Naive Bayes

각 feature들을 독립으로 보고, 조건부 확률로 분석하는 기법

## Naive Bayes 
## 
## 350 samples
##   7 predictor
##   2 classes: '0', '1' 
## 
## Pre-processing: scaled (7), centered (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 315, 315, 315, 314, 314, 316, ... 
## Resampling results across tuning parameters:
## 
##   usekernel  Accuracy   Kappa    
##   FALSE      0.8905910  0.7816522
##    TRUE      0.8905742  0.7811957
## 
## Tuning parameter 'laplace' was held constant at a value of 0
## Tuning
##  parameter 'adjust' was held constant at a value of 1
## Accuracy was used to select the optimal model using the largest value.
## The final values used for the model were laplace = 0, usekernel = FALSE
##  and adjust = 1.

usekernerl = 히스토그램을 사용해서 추정하는 것 커널 밀도 함수 사용여부 adjust = 커널 밀도함수의 bandwidth 값을 조절 laplace = 라플라스 스무딩 파라미터 값 조절

Random Forest

## Random Forest 
## 
## 350 samples
##   7 predictor
##   2 classes: '0', '1' 
## 
## Pre-processing: scaled (7), centered (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 315, 315, 315, 316, 314, 314, ... 
## Resampling results across tuning parameters:
## 
##   mtry  Accuracy   Kappa    
##   2     0.8760831  0.7516461
##   4     0.8727040  0.7445861
##   7     0.8618254  0.7223609
## 
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was mtry = 2.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 53 11
##          1 19 67
##                                          
##                Accuracy : 0.8            
##                  95% CI : (0.727, 0.8608)
##     No Information Rate : 0.52           
##     P-Value [Acc > NIR] : 9.977e-13      
##                                          
##                   Kappa : 0.5976         
##                                          
##  Mcnemar's Test P-Value : 0.2012         
##                                          
##             Sensitivity : 0.7361         
##             Specificity : 0.8590         
##          Pos Pred Value : 0.8281         
##          Neg Pred Value : 0.7791         
##              Prevalence : 0.4800         
##          Detection Rate : 0.3533         
##    Detection Prevalence : 0.4267         
##       Balanced Accuracy : 0.7975         
##                                          
##        'Positive' Class : 0              
## 

#SVM

## Support Vector Machines with Linear Kernel 
## 
## 350 samples
##   7 predictor
##   2 classes: '0', '1' 
## 
## Pre-processing: scaled (7), centered (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 316, 316, 315, 315, 314, 315, ... 
## Resampling results:
## 
##   Accuracy   Kappa    
##   0.8898095  0.7793358
## 
## Tuning parameter 'C' was held constant at a value of 1
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 56 10
##          1 16 68
##                                           
##                Accuracy : 0.8267          
##                  95% CI : (0.7564, 0.8835)
##     No Information Rate : 0.52            
##     P-Value [Acc > NIR] : 3.796e-15       
##                                           
##                   Kappa : 0.6517          
##                                           
##  Mcnemar's Test P-Value : 0.3268          
##                                           
##             Sensitivity : 0.7778          
##             Specificity : 0.8718          
##          Pos Pred Value : 0.8485          
##          Neg Pred Value : 0.8095          
##              Prevalence : 0.4800          
##          Detection Rate : 0.3733          
##    Detection Prevalence : 0.4400          
##       Balanced Accuracy : 0.8248          
##                                           
##        'Positive' Class : 0               
## 
## Support Vector Machines with Polynomial Kernel 
## 
## 350 samples
##   7 predictor
##   2 classes: '0', '1' 
## 
## Pre-processing: centered (7), scaled (7) 
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 315, 315, 314, 316, 315, 315, ... 
## Resampling results across tuning parameters:
## 
##   degree  scale  C     Accuracy   Kappa    
##   1       0.001  0.25  0.5314379  0.0000000
##   1       0.001  0.50  0.8644641  0.7245690
##   1       0.001  1.00  0.8881307  0.7761674
##   1       0.010  0.25  0.8812726  0.7628816
##   1       0.010  0.50  0.8823828  0.7646292
##   1       0.010  1.00  0.8789860  0.7581030
##   1       0.100  0.25  0.8823828  0.7646898
##   1       0.100  0.50  0.8927049  0.7849915
##   1       0.100  1.00  0.8949748  0.7894334
##   2       0.001  0.25  0.8639085  0.7234510
##   2       0.001  0.50  0.8892736  0.7783921
##   2       0.001  1.00  0.8853221  0.7711291
##   2       0.010  0.25  0.8835257  0.7668870
##   2       0.010  0.50  0.8789860  0.7581030
##   2       0.010  1.00  0.8807003  0.7614249
##   2       0.100  0.25  0.8841457  0.7676057
##   2       0.100  0.50  0.8864155  0.7719207
##   2       0.100  1.00  0.8846022  0.7682575
##   3       0.001  0.25  0.8892726  0.7776995
##   3       0.001  0.50  0.8875761  0.7751015
##   3       0.001  1.00  0.8807330  0.7616250
##   3       0.010  0.25  0.8813044  0.7626467
##   3       0.010  0.50  0.8812400  0.7624807
##   3       0.010  1.00  0.8858123  0.7714050
##   3       0.100  0.25  0.8880980  0.7752829
##   3       0.100  0.50  0.8891587  0.7773534
##   3       0.100  1.00  0.8840299  0.7669015
## 
## Accuracy was used to select the optimal model using the largest value.
## The final values used for the model were degree = 1, scale = 0.1 and C = 1.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 54 10
##          1 18 68
##                                           
##                Accuracy : 0.8133          
##                  95% CI : (0.7416, 0.8722)
##     No Information Rate : 0.52            
##     P-Value [Acc > NIR] : 6.705e-14       
##                                           
##                   Kappa : 0.6245          
##                                           
##  Mcnemar's Test P-Value : 0.1859          
##                                           
##             Sensitivity : 0.7500          
##             Specificity : 0.8718          
##          Pos Pred Value : 0.8438          
##          Neg Pred Value : 0.7907          
##              Prevalence : 0.4800          
##          Detection Rate : 0.3600          
##    Detection Prevalence : 0.4267          
##       Balanced Accuracy : 0.8109          
##                                           
##        'Positive' Class : 0               
## 
LS0tDQp0aXRsZTogIlByZWRpY3Rpb25fdW5pdmVyc2l0eSINCmF1dGhvcjogIkRPRVVOIg0KZGF0ZTogJzIwMjEgMyA5ICcNCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgICMgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgaGlnaGxpZ2h0OiB6ZW5idXJuDQogICAgIyBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRoZW1lOiAiZmxhdGx5Ig0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KLS0tDQoNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQoNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGNhY2hlID0gVFJVRSkNCg0KI2luc3RhbGwucGFja2FnZXMoInVzZWZ1bCIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShmYWN0b2V4dHJhKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGNhcmV0KQ0KYGBgDQoNCiMgREFUQSBQcmVwYXJhdGlvbiANCg0KICBJbnRyb2R1Y3Rpb24gDQogIA0KICBHUkUuU2NvcmUgLSBHUkUg7KCQ7IiYIA0KICBUT0VGTC5TY29yZSAtIO2GoO2UjCDsoJDsiJggDQogIFVuaXZlcnNpdHkuUmFua2luZyAtIO2Vmeu2gCDrjIDtlZkg66CI7J207YyFIA0KICBTT1AgLSDsnpDquLAg7IaM6rCc7IScIOygkOyImCANCiAgTE9SIC0g7LaU7LKc7IScIOygkOyImCANCiAgQ0dQQSAtIO2Vmeu2gCDsoJDsiJggDQogIFJlc2VhcmNoIC0g7Jew6rWsIOqyve2XmOydmCDsnKDrrLQgDQogIENoYW5jZSBvZiBBZG1pdCAtIOuMgO2VmeybkCDtlanqsqkg7ZmV66WgDQogIA0KICAxKSBUYXJnZXQgVmFyaWFibGUg7J20IOyeiOuKlOqwgD8gDQogIA0KICBUYXJnZXQgVmFyaWFibGUg7JeQIOuUsOudvCDsp4Drj4Qv67mE7KeA64+E7ZWZ7Iq17Jy866GcIOuCmOuIjCDsiJgg7J6I6riwIOuVjOusuOyXkCDspJHsmpQgDQogIA0KICBUYXJhZ2V0IOyeiOydjCAtICoqKuyngOuPhCDtlZnsirUqKiog7ISk7KCVIA0KIA0KYGBge3IgY2Fyc30NCg0Kc2V0d2QoJ0M6L1VzZXJzL0FkbWluaXN0cmF0b3IvRGVza3RvcC9SIEFuYWx5c2lzL0Zhc3QgQ2FtcHVzJykNCg0KcmVhZC5jc3YoJ3VuaXZlcnNpdHkuY3N2JywgaGVhZGVyID0gVCkgLT4gcmF3X2RhdGExDQoNCg0Kc3RyKHJhd19kYXRhMSkNCmBgYA0KDQojIFByZXByb2Nlc3NpbmcgOiBOQQ0KDQpgYGB7ciBwcmVzc3VyZSwgZWNobz1GQUxTRX0NCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojICAg6rKw7Lih7LmYIO2ZleyduO2VmOq4sCANCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KY29sU3Vtcyhpcy5uYShyYXdfZGF0YTEpKQ0KDQpzdW0oaXMubmEocmF3X2RhdGExKSkNCg0KDQpgYGANCg0KIyBQcmVwcm9jZXNzaW5nIDogSGlzdG9ncmFtICYgQm94cGxvdCANCg0KYGBge3J9DQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgICBVbmlxdWUg7ZWo7IiY66W8IOyCrOyaqe2VtOyEnCDrtoTtj6zrj4Trpbwg7ZmV7J247ZWc64ukLiDsnbTsg4HsuZgg64SI66y0IOyekeqxsOuCmCDtgbAg6rKDLCDtmLnsnYAg7Yq57IiY66y47J6Q65OkIO2ZleyduCANCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnVuaXF1ZShyYXdfZGF0YTEkR1JFLlNjb3JlKQ0KDQpwYXIobWZyb3c9KGMoMiwzKSkpDQoNCmhpc3QocmF3X2RhdGExJEdSRS5TY29yZSwgeGxhYiA9ICJHUkUg7KCQ7IiYIikNCg0KaGlzdChyYXdfZGF0YTEkVE9FRkwuU2NvcmUsIHhsYWI9ICJUT0VGTCDsoJDsiJgiKQ0KDQpoaXN0KHJhd19kYXRhMSRTT1ApDQoNCmhpc3QocmF3X2RhdGExJExPUikNCg0KaGlzdChyYXdfZGF0YTEkVW5pdmVyc2l0eS5SYXRpbmcpDQoNCmhpc3QocmF3X2RhdGExJENoYW5jZS5vZi5BZG1pdCkNCg0KZGV2Lm9mZigpDQoNCiMgWCDstpUg6riw7KSAIOqwgSDrtoTtj6zrj4Trpbwg7ZmV7J24IA0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgIFVOSVFVRSBSZXNhcmNoIC0gTm9taW5hbCBvciBCaW5hcnk/IA0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQp0YWJsZShyYXdfZGF0YTEkUmVzZWFyY2gpDQoNCg0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojICAgVGFyZ2V0IC0gQ2hhbmNlIG9mIEFkbWluIA0KIyAgIDEpIE1BWCwgTUlOIOulvCDtmZXsnbjtlbTslbztlZzri6QuIDB+MSDsgqzsnbTsnZgg6rCSICjsnbTsg4HsuZgg7ZmV7J24KQ0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpzdW1tYXJ5KHJhd19kYXRhMSRDaGFuY2Uub2YuQWRtaXQpDQoNCg0KcGFyKG1mcm93PShjKDIsMykpKQ0KYm94cGxvdChyYXdfZGF0YTEkR1JFLlNjb3JlLCB4bGFiID0gIkdSRSDsoJDsiJgiKQ0KDQpib3hwbG90KHJhd19kYXRhMSRUT0VGTC5TY29yZSwgeGxhYj0gIlRPRUZMIOygkOyImCIpDQoNCmJveHBsb3QocmF3X2RhdGExJFNPUCkNCg0KYm94cGxvdChyYXdfZGF0YTEkTE9SKQ0KDQpib3hwbG90KHJhd19kYXRhMSRVbml2ZXJzaXR5LlJhdGluZykNCg0KYm94cGxvdChyYXdfZGF0YTEkQ2hhbmNlLm9mLkFkbWl0KQ0KDQpkZXYub2ZmKCkNCg0KDQoNCg0KDQpgYGANCg0KDQoNCmBgYHtyfQ0KcGxvdChyYXdfZGF0YTEpDQpgYGANCg0KIyAgTW9kZWxsaW5nICB7LnRhYnNldH0NCg0KIFRhcmdldCDsnbQg66qF66qpIC0gQ2xhc3NpZmljYXRpb24gVlMg7Jew7IaNIC0gUmVncmVzc2lvbiANCiANCiBUYXJnZXQg7J2YIOuylOychOqwgCAwfjEg7IKs7J207J2YIOygnO2VnOydtCDsnojquLAg65WM66y47JeQLCBMb2dpc3RpYyBSZWdyZXNzaW9uIOycvOuhnCDsp4TtlokgDQogDQogMSkg66Gc7KeA7Iqk7YuxIO2ajOq3gCDrtoTshJ0gDQogDQogMikg7JeY65287Iqk7YuxIOuEtyANCiANCiAzKSDrnpzrjaQg7Y+s66CI7Iqk7Yq4IA0KIA0KIDQpIFNWTSANCiANCiA1KSDsu6TrhJAg7ISc7Y+s7Yq4IOuyoe2EsCDrqLjsi6AgDQoNCiMjIExvZ2lzdGljIE1vZGVsbGluZyANCg0KYGBge3J9DQoNCnNldC5zZWVkKDIwMjApDQoNCnJhd19kYXRhMSAtPiBkZg0KDQpzb3J0KHNhbXBsZShucm93KGRmKSwgbnJvdyhkZikqMC43KSkgLT4gZmxhZw0KDQoNCnRyYWluIDwtIGRmW2ZsYWcsXQ0KdGVzdCA8LSBkZlstZmxhZyxdDQoNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgU2V0dGluZyB0aGUgbW9kZWwgY29udHJvbHMgDQojICBtZXRyaWMgPSBSTVNFIDog7Jew7IaN7ZiV7J206riwIOuWhOusuOyXkCwgQWNjdXJhY3kgKOu2hOulmCkNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoNCnRyYWluQ29udHJvbChtZXRob2QgPSAicmVwZWF0ZWRjdiIsIHJlcGVhdHMgPSA1KSAtPiBjdHJsIA0KDQp0cmFpbihDaGFuY2Uub2YuQWRtaXR+LiwgDQogICAgICBkYXRhPSB0cmFpbiwgDQogICAgICBtZXRob2QgPSAiZ2xtIiwgDQogICAgICB0ckNvbnRyb2w9IGN0cmwsIA0KICAgICAgcHJlUHJvY2Vzcz0gYygiY2VudGVyIiwgInNjYWxlIiksDQogICAgICBtZXRyaWMgPSAiUk1TRSIpIC0+IGxvZ2lzdGljX2ZpdA0KDQoNCmxvZ2lzdGljX2ZpdA0KYGBgDQoNCg0KMS4gUk1TRSA6IOyekeydhCDsiJjroZ0g7KKL7J2MICjsi6TsoJwgLSDsmIjsuKEpDQoNCiAxLjEgUk1TRSDqtaztlZjripQg67Cp67KVIA0KIA0KICAgIHBvc3RSZXNhbXBsZSgpDQogICAgDQogICAgUk1TRSgpDQogICAgDQogICAg7KeB7KCRIOqzhOyCsCANCg0KKioqcG9zdFJlc2FtcGxlKioqDQpgYGB7cn0NCg0KcHJlZGljdChsb2dpc3RpY19maXQsIG5ld2RhdGEgPSB0ZXN0KSAtPiBsb2dpc3RpY19wcmVkDQoNCg0KcG9zdFJlc2FtcGxlKHByZWQgPSBsb2dpc3RpY19wcmVkLCBvYnM9IHRlc3QkQ2hhbmNlLm9mLkFkbWl0KQ0KYGBgDQoNCg0KKioqUk1TRSoqKg0KYGBge3J9DQoNCg0KUk1TRShsb2dpc3RpY19wcmVkLCB0ZXN0JENoYW5jZS5vZi5BZG1pdCkNCmBgYA0KDQoqKirsp4HsoJHqs4TsgrAqKioNCmBgYHtyfQ0KDQpzcXJ0KG1lYW4oKGxvZ2lzdGljX3ByZWQgLSB0ZXN0JENoYW5jZS5vZi5BZG1pdCleMikpDQoNCiAgICAgICAgICAj7JiI7Lih6rCSIC0g7Iuk7KCc6rCSIOygnOqzsSArIG1lYW4gDQpgYGANCg0KDQoyLiBSLXNxdWFyZSANCg0KDQoqKirsp4HsoJEg6rOE7IKwKioqDQoNCmBgYHtyfQ0KDQp5X2JhciA9IG1lYW4odGVzdCRDaGFuY2Uub2YuQWRtaXQpDQoNCjEgLSAoc3VtKChsb2dpc3RpY19wcmVkIC0gdGVzdCRDaGFuY2Uub2YuQWRtaXQpXjIpIC9zdW0oKHRlc3QkQ2hhbmNlLm9mLkFkbWl0LXlfYmFyKV4yKSkNCmBgYA0KDQoNCjMuIE1BRSAoTUVBTiBBYnNvdWx0ZSBFcnJvcikgLSDsmKTssKjtla3snZgg7KCI64yA6rCSIA0KDQogICB87Iuk7KCc6rCSIC0g7JiI7Lih6rCSfCANCiAgIA0KICAgDQpgYGB7cn0NCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgcG9zdFJlc2FtcGxlDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KDQpwb3N0UmVzYW1wbGUobG9naXN0aWNfcHJlZCwgb2JzPXRlc3QkQ2hhbmNlLm9mLkFkbWl0KQ0KDQoNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgTUFFDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KTUFFKGxvZ2lzdGljX3ByZWQsIHRlc3QkQ2hhbmNlLm9mLkFkbWl0KQ0KDQoNCmBgYA0KDQoNCiMjIEVsYXN0aWMgTmV0IA0KDQogICDrqLjsi6Ag65+s64ud7J2YIOuqqeyggeydgCAtPiDstZzsoIHtmZQgKG9wdGltYXp0aW9uKSAtPiBPYmplY3RpdmUgRnVuY3Rpb24gKOuqqeyggSDtlajsiJgpDQogICANCiAgIE9iamVjdCBGdW5jdGlvbiA9IOyYpOywqCDsoJzqs7HtlakgKEVycm9yOiDsi6TsoJwtIOy2lOyyrSkg7J2EIOykhOydtOuKlCDqsoMNCiAgIA0KICAgKioqPOuqqeyggSDtlajsiJjrpbwg7LWc7KCB7ZmUIO2VnOuLpOuKlCDqsoPsnYA/PioqKg0KICAgDQogICDsmKTssKjsoJzqs7HtlansnYQg7LWc7IaM7ZmUIOyLnO2CpOuKlCDrqqjsiJjrpbwg7LaU7KCV7ZWc64uk64qUIOqygy4gDQogICANCiAgIEVsYXN0aWMgTmV0IC0gUGVuYWx0eSA6IOuqqeygge2VqOyImOydmCDstZzsoIHtmZTrpbwg64+E7JmA7KO864qUIOyXre2VoCAoPWNvbnRyYWludCwgcmVndWxhcml6YXRpb24pDQogICANCiAgICoqKuuqqeygge2VqOyImCArIO2MqOuEkO2LsCA9IOy1nOygge2ZlOuQnCDrqqjsiJgqKiogDQogIA0KICAgUGVuYWx0eSDsooXrpZggDQogICANCiAgICFb7IKs7KeEXShDOi9Vc2Vycy9pbWFnZV8zLnBuZykNCg0KICDstZzshoztmZQg7Iuc7YKk64qUIELrpbwg7LC+64qU6rKD7J20IOuqqeyggeydtOupsCwgRWxhc3RpYyBOZXQg7J2AIEwxICjrnbzsj5gpICsgTDIgKOumv+yngCkg7Yyo64SQ7Yuw66W8IOyCrOyaqe2VnOuLpC4gDQogICANCiAgTDEgOiBC64qUIOuniOumhOuqqCDslYjsl5Ag7J6I7Ja07JW8IO2VnOuLpC4g6rG47LOQ7J6I7Ja064+EIOq0nOywruydjCAo64Sk66qoKSA6IExhc3NvIFJlZ3Jlc3Npb24NCiAgDQogIEwyIDogQuydmCDsoJzqs7Htlakg7JWI7JeQIOyeiOyWtOyVvO2VnOuLpC4gKO2DgOybkO2YlSkgOlJpZGdlIFJlZ3Jlc3Npb24gDQoNCg0KYGBge3J9DQoNCmN0cmwgPC0gdHJhaW5Db250cm9sKG1ldGhvZCA9ICJyZXBlYXRlZGN2IiwgcmVwZWF0cyA9IDUpDQoNCnRyYWluKENoYW5jZS5vZi5BZG1pdH4uLA0KICAgICAgZGF0YT10cmFpbiwgDQogICAgICBtZXRob2QgPSAiZ2xtbmV0IiwgDQogICAgICBwcmVQcm9jZXNzPSBjKCJjZW50ZXIiLCJzY2FsZSIpLCANCiAgICAgIHRyQ29udHJvbD1jdHJsLA0KICAgICAgbWV0cmljPSAiUk1TRSIpIC0+IGxvZ2l0X3BlbmFsX2ZpdCANCg0KDQpsb2dpdF9wZW5hbF9maXQNCmBgYA0KDQoNCjzqsrDqs7wg7ZW07ISdPg0KDQogMSkgYWxwaGEgPSAxIOydtOuLpC4g7KaJLCDrnbzsj5ggLyBhbHBoYT0wICDspoksIFJpZGdlIOuLpCANCiANCiAgICDsoJXqt5ztmZTsnZgg67mE7Jyo7J2EIOuCmO2DgOuCtOuKlCDrqqjsiJggDQogDQogMikgbGFtZGJhIA0KIA0KICAgICDsoITssrQg7KCc7JW97Iud7J2YIO2BrOq4sOulvCDrgpjtg4Drgrjri6QuIA0KICAgICANCiAgICANCmBgYHtyfQ0KcGxvdChsb2dpdF9wZW5hbF9maXQpDQpgYGANCg0KDQpgYGB7cn0NCg0KcHJlZGljdChsb2dpdF9wZW5hbF9maXQsIG5ld2RhdGEgPSB0ZXN0KSAtPiBsb2dpdF9wZW5hbF9wcmVkDQoNCg0KcG9zdFJlc2FtcGxlKGxvZ2l0X3BlbmFsX3ByZWQsIG9icz10ZXN0JENoYW5jZS5vZi5BZG1pdCkNCmBgYA0KDQoNCiMjIFJhbmRvbSBGb3Jlc3QgDQoNCiBEZWNpc2lvbiBUcmVlIOqwgCDsl6zrn6zrsogg6re466Ck7IScIOyYiOy4oe2VmOqyjCDrp4zrk5zripQg6rKDLiDqsIEgVHJlZSDsnZgg6rKw6rO866W8IOu2meydtOuKlCDqsoMgDQogDQogcmYoKSDsgqzsmqkgDQoNCmBgYHtyfQ0KDQpjdHJsIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSJyZXBlYXRlZGN2IiwgcmVwZWF0cyA9IDUpDQoNCg0KdHJhaW4oQ2hhbmNlLm9mLkFkbWl0IH4gLiwNCiAgICAgIGRhdGE9dHJhaW4sIA0KICAgICAgbWV0aG9kID0gJ3JmJywgDQogICAgICB0ckNvbnRyb2wgPSBjdHJsLCANCiAgICAgIHByZVByb2Nlc3M9IGMoImNlbnRlciIsICJzY2FsZSIpLCANCiAgICAgIG1ldHJpYyA9ICJSTVNFIikgLT4gcmZfZml0DQoNCg0KcmZfZml0DQpgYGANCg0KDQptdHJ5ID0y7J24IOqwkuydtCDstZzsoIHtmZTrkJwg6rCSDQoNClJNU0Ug6rCS7J2AIOuCruydhCDsiJjroZ0g7KKL7J2MICjtlZjri6gg6re466a8KQ0KDQpgYGB7cn0NCnBsb3QocmZfZml0KQ0KYGBgDQoNCg0KYGBge3J9DQpwcmVkaWN0KHJmX2ZpdCwgbmV3ZGF0YSA9IHRlc3QpIC0+IHJmX3ByZWQNCg0KcG9zdFJlc2FtcGxlKHJmX3ByZWQsIG9icz10ZXN0JENoYW5jZS5vZi5BZG1pdCkNCg0KYGBgDQoNCiMjIFNWTSANCg0KYGBge3J9DQoNCmN0cmwgPC0gdHJhaW5Db250cm9sKG1ldGhvZD0icmVwZWF0ZWRjdiIscmVwZWF0cyA9IDUpDQpzdm1fbGluZWFyX2ZpdCA8LSB0cmFpbihDaGFuY2Uub2YuQWRtaXQgfiAuLA0KICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHRyYWluLA0KICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInN2bUxpbmVhciIsDQogICAgICAgICAgICAgICAgICAgICAgICB0ckNvbnRyb2wgPSBjdHJsLA0KICAgICAgICAgICAgICAgICAgICAgICAgcHJlUHJvY2VzcyA9IGMoImNlbnRlciIsInNjYWxlIiksDQogICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWM9IlJNU0UiKQ0Kc3ZtX2xpbmVhcl9maXQNCg0KDQpgYGANCg0KDQpgYGB7cn0NCg0KcHJlZGljdChzdm1fbGluZWFyX2ZpdCwgbmV3ZGF0YSA9IHRlc3QpIC0+IHN2bV9saW5lYXJfcHJlZA0KDQpwb3N0UmVzYW1wbGUoc3ZtX2xpbmVhcl9wcmVkLCBvYnM9dGVzdCRDaGFuY2Uub2YuQWRtaXQpDQpgYGANCg0KDQojIyDsu6TrhJAgU1ZNDQoNCmBgYHtyfQ0KY3RybCA8LSB0cmFpbkNvbnRyb2wobWV0aG9kPSJyZXBlYXRlZGN2IixyZXBlYXRzID0gNSkNCg0KDQogICAgICAgICAgICBzdm1fcG9seV9maXQgPC0gdHJhaW4oQ2hhbmNlLm9mLkFkbWl0IH4gLiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gdHJhaW4sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInN2bVBvbHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyQ29udHJvbCA9IGN0cmwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlUHJvY2VzcyA9IGMoImNlbnRlciIsInNjYWxlIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljPSJSTVNFIikNCnN2bV9wb2x5X2ZpdA0KDQpgYGANCg0KDQpgYGB7cn0NCnBsb3Qoc3ZtX3BvbHlfZml0KQ0KYGBgDQoNCg0KYGBge3J9DQpzdm1fcG9seV9wcmVkIDwtIHByZWRpY3Qoc3ZtX3BvbHlfZml0LCBuZXdkYXRhPXRlc3QpDQpwb3N0UmVzYW1wbGUocHJlZCA9IHN2bV9wb2x5X3ByZWQsIG9icyA9IHRlc3QkQ2hhbmNlLm9mLkFkbWl0KQ0KYGBgDQoNCg0KIyBDbHVzdGVyaW5nIC0gSy1NZWFuLCBIY2x1c3RlcmluZyANCg0KDQoxLiBLLU1FQU5TDQoNCg0KYGBge3J9DQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgIFNURVAgMSkg7ZGc7KSA7ZmUIFNjYWxpbmcgIA0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCnJhd19kYXRhMSAtPmRmDQoNCmRmWywtOF0gLT5kZg0KDQpzY2FsZShkZikgLT4gZGYuc2NhbGUNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojICBTVEVQIDIpIOycoO2BtOumrOuUlOyViCDtlonroKwgLSDqsbDrpqzqsIAg6rCA6rmM7Jq0IOyInOyEnOuMgOuhnCDtmZXsnbggDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KZGlzdChkZi5zY2FsZSwgbWV0aG9kID0gJ2V1Y2xpZGVhbicpICU+JSANCiAgYXMubWF0cml4KCkgLT4gZGYuZGlzdA0KDQoNCg0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgIFNURVAgMykgSyDqsK/siJggV1NTLCDsi6Tro6jsl6MgDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KZnZpel9uYmNsdXN0KGRmLnNjYWxlLCANCiAgICAgICAgICAgICBrbWVhbnMsIA0KICAgICAgICAgICAgIG1ldGhvZCA9ICd3c3MnLA0KICAgICAgICAgICAgIGsubWF4ID0gMTApDQoNCg0KZnZpel9uYmNsdXN0KGRmLnNjYWxlLCANCiAgICAgICAgICAgICBrbWVhbnMsIA0KICAgICAgICAgICAgIG1ldGhvZCA9ICdzaWxob3VldHRlJywNCiAgICAgICAgICAgICBrLm1heCA9IDEwKQ0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgU1RFUCA0KSBNb2RlbGxpbmcgIDTqsJzroZwg7Iuc64+EIA0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCg0Ka21lYW5zKGRmLnNjYWxlLCBjZW50ZXJzID0gNCwgaXRlci5tYXggPSAxMDAwKSAtPiBkZi5rbWVhbnMNCg0KZGYua21lYW5zJGNlbnRlcnMgI+qwgSDqtbDsp5Hrs4Qg7Y+J6reg6rCSIA0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgIFNURVAgNSkg7Iuc6rCB7ZmUIA0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCg0KDQpiYXJwbG90KHQoZGYua21lYW5zJGNlbnRlcnMpLCBiZXNpZGUgPSBULCBjb2w9Mjo3KQ0KbGVnZW5kKCJ0b3ByaWdodCIsIGNvbG5hbWVzKGRmLnNjYWxlKSwgZmlsbCA9IDI6NywgY2V4PTAuNSkNCg0KZGV2Lm9mZigpDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgU1RFUCA2KSBDbHVzdGVyaW5nIEFsbG9jYXRpb24gICANCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoNCmRmJGttZWFuX2NsdXN0ZXIgPC0gZGYua21lYW5zJGNsdXN0ZXINCg0KYGBgDQoNCg0KMi4gSGNsdXN0IA0KDQpgYGB7cn0NCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojICBTVEVQIDEpIEZpbmRpbmcgb3B0aW1hbCBLIHVzaW5nIGhjdXQgICANCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpmdml6X25iY2x1c3QoZGYuc2NhbGUsIA0KICAgICAgICAgICAgIGhjdXQsIA0KICAgICAgICAgICAgIG1ldGhvZCA9J3dzcycsDQogICAgICAgICAgICAgay5tYXggPSAxMCkNCg0KDQpmdml6X25iY2x1c3QoZGYuc2NhbGUsDQogICAgICAgICAgICAgaGN1dCwgDQogICAgICAgICAgICAgbWV0aG9kID0gJ3NpbGhvdWV0dGUnLCANCiAgICAgICAgICAgICBrLm1heCA9IDEwKQ0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgU1RFUCAyKSBDcmVhdCBjbHVzdGVyIHVzaW5nIHNpbmdsZSwgY29tcGxldGUsIHdhcmQsIGF2ZXJhZ2UgIA0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCmhjbHVzdChkaXN0KGRmLnNjYWxlKSwgbWV0aG9kID0gJ3dhcmQuRCcpIC0+IGhsdXN0X3dhcmQNCg0KDQpwbG90KGhsdXN0X3dhcmQpDQpyZWN0LmhjbHVzdChobHVzdF93YXJkLCBrPTMpDQoNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojICBTVEVQIDMpIENsdXN0ZXIgQWxsb2NhdGlvbiANCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoNCmN1dHJlZShobHVzdF93YXJkLCBrPTMpIC0+IGhjbHVzdGVyDQoNCmRmJGhjdWxzdGVyIDwtIGhjbHVzdGVyDQoNCg0KYGBgDQoNCiMgQ29ycmVsYXRpb24gDQoNCmBgYHtyfQ0KbGlicmFyeShjb3JycGxvdCkNCg0KY29yKGRmLnNjYWxlKSAtPiBNDQoNCg0KY29sIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiI0JCNDQ0NCIsICIjRUU5OTg4IiwgIiNGRkZGRkYiLCAiIzc3QUFERCIsICIjNDQ3N0FBIikpDQpjb3JycGxvdChNLCBtZXRob2QgPSAiY29sb3IiLCBjb2wgPSBjb2woMjAwKSwgIA0KICAgICAgICAgdHlwZSA9ICJ1cHBlciIsIG9yZGVyID0gImhjbHVzdCIsIA0KICAgICAgICAgYWRkQ29lZi5jb2wgPSAiYmxhY2siLCAjIEFkZCBjb2VmZmljaWVudCBvZiBjb3JyZWxhdGlvbg0KICAgICAgICAgdGwuY29sID0gImRhcmtibHVlIiwgdGwuc3J0ID0gNDUsICNUZXh0IGxhYmVsIGNvbG9yIGFuZCByb3RhdGlvbg0KICAgICAgICAgIyBDb21iaW5lIHdpdGggc2lnbmlmaWNhbmNlIGxldmVsDQogICAgICAgICBzaWcubGV2ZWwgPSAwLjAxLCAgDQogICAgICAgICAjIGhpZGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgb24gdGhlIHByaW5jaXBhbCBkaWFnb25hbA0KICAgICAgICAgZGlhZyA9IEZBTFNFIA0KICAgICAgICAgKQ0KDQpgYGANCg0KDQpgYGB7cn0NCg0KI2luc3RhbGwucGFja2FnZXMoIlBlcmZvcm1hbmNlQW5hbHl0aWNzIikNCmxpYnJhcnkoIlBlcmZvcm1hbmNlQW5hbHl0aWNzIikNCg0KDQpjaGFydC5Db3JyZWxhdGlvbihyYXdfZGF0YTEsIGhpc3RvZ3JhbSA9IFQsIHBjaD0yMCxjZXguY29yLnNjYWxlPTIpDQpgYGANCg0KIyBMb2dpc3RpYyBSZWdyZXNzaW9uIHsudGFic2V0fQ0KDQoxKSBLTk4NCjIpIEJvb3N0ZWQg66Gc7KeA7Iqk7YuxIO2ajOq3gA0KMykgUGVuYWxpemVkIOuhnOyngOyKpO2LsSDtmozqt4ANCjQpIOuCmOydtOu4jCDrsqDsnbTspogNCjUpIOuenOuNpCDtj6zroIjsiqTtirgNCjYpIOyEnO2PrO2KuCDrsqHthLAg66i47IugDQo3KSDsu6TrhJAg7ISc7Y+s7Yq4IOuyoe2EsCDrqLjsi6AgDQoNCmBgYHtyfQ0KDQoNCnNldHdkKCdDOi9Vc2Vycy9BZG1pbmlzdHJhdG9yL0Rlc2t0b3AvUiBBbmFseXNpcy9GYXN0IENhbXB1cycpDQoNCnJlYWQuY3N2KCd1bml2ZXJzaXR5LmNzdicsIGhlYWRlciA9IFQpIC0+IHJhd19kYXRhMQ0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojICDrqoXrqqntmJUg67aE66WYIOusuOygnOuhnCDrtoTshJ0gDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KcGFyKG1mcm93PSBjKDEsMiksIG1hcj1jKDUuMSw0LjEsNC4xLDIuMSkpDQpoaXN0b2dyYW0ocmF3X2RhdGExJENoYW5jZS5vZi5BZG1pdCkNCmJveHBsb3QocmF3X2RhdGExJENoYW5jZS5vZi5BZG1pdCkNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgIO2VqeqyqSDqtazrtoTsnYQg7Ja065a76rKMIO2VoCDqsoPsnbjqsIA/IA0KIyAgMC41IOq4sOykgOydmCDsoJXqt5wg67aE7Y+s6rCAIOyVhOuLiOq4sCDrlYzrrLjsl5AsIOykkeyLrOydtCAwLjfsnLzroZwg67O07Jes7KeE64ukLg0KIyAg7KCI67CY7J2YIOyngOybkOyekOuTpOydtCAwLjfsnbTsg4HsnbTrnbzripQg6rKDDQojICDrsJXsiqQg7ZSM66Gv7J2YIE1lZGlhbiDquLDspIDsnLzroZwg67aI7ZWp6rKpL+2VqeqyqeycvOuhnCDrgpjriITslrTrs7jri6QuIA0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0Kc3VtbWFyeShyYXdfZGF0YTEkQ2hhbmNlLm9mLkFkbWl0KQ0KDQoNCg0KDQp0YXJnZXRfbWVkaWFuIDwtIG1lZGlhbihyYXdfZGF0YTEkQ2hhbmNlLm9mLkFkbWl0KQ0KdGFyZ2V0X21lZGlhbg0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojICAwLjcyIOq4sOykgOycvOuhnCAwLDEgRmFjdG9y7ZiV7Jy866GcIOuzgO2ZmCAgDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpyYXdfZGF0YTEgJT4lIA0KICBtdXRhdGUoQ2hhbmNlLm9mLkFkbWl0ID0gaWZlbHNlKENoYW5jZS5vZi5BZG1pdCA8IDAuNzIsIDAsMSkgJT4lIA0KICAgICAgICAgYXMuZmFjdG9yKCkpIC0+IGRmDQoNCnN0cihkZiRDaGFuY2Uub2YuQWRtaXQpDQoNCnVuaXF1ZShkZiRDaGFuY2Uub2YuQWRtaXQpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojICBUcmFpbiwgVGVzdCDrgpjriITquLAgIA0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnNldC5zZWVkKDIwMjApDQoNCnNvcnQoc2FtcGxlKG5yb3coZGYpLCBucm93KGRmKSowLjcpKSAtPiBmbGFnDQoNCmRmW2ZsYWcsXSAtPiB0cmFpbjINCg0KZGZbLWZsYWcsXSAtPiB0ZXN0Mg0KDQpgYGANCg0KIyBLTk4gDQoNCg0K6rCA7J6lIOqwgOq5jOyatCBLIOqwnOydmCDsnbTsm4PsnYQg67O064qUIOqygyANCg0KYGBge3J9DQoNCmN0cmwgPC0gdHJhaW5Db250cm9sKG1ldGhvZCA9ICJyZXBlYXRlZGN2IiwgDQogICAgICAgICAgICAgICAgICAgICByZXBlYXRzID0gNSkNCg0KDQpleHBhbmQuZ3JpZChrPTE6MjApIC0+Y3VzdG9tR3JpZCANCg0KDQp0cmFpbihDaGFuY2Uub2YuQWRtaXR+LiwNCiAgICAgIGRhdGE9dHJhaW4yLA0KICAgICAgbWV0aG9kID0gImtubiIsDQogICAgICB0ckNvbnRyb2w9Y3RybCwNCiAgICAgIHByZVByb2Nlc3M9IGMoImNlbnRlciIsInNjYWxlIiksIA0KICAgICAgdHVuZUdyaWQgPSBjdXN0b21HcmlkLCANCiAgICAgIG1ldHJpYz0iQWNjdXJhY3kiKSAtPiBrbm5fZml0Mg0KDQoNCg0Ka25uX2ZpdDINCmBgYA0KDQoNCg0KDQpgYGB7cn0NCg0KcGxvdChrbm5fZml0MikNCmBgYA0KDQoNCks9MTUg7J2865WMIDAuODkyNeuhnCDqsIDsnqUg64aS7J2AIOygle2ZleuPhOulvCDqsIDsp4Tri6QuIA0KDQpgYGB7cn0NCg0KcHJlZGljdChrbm5fZml0MiwgbmV3ZGF0YSA9IHRlc3QyKSAtPiBrbm5fcHJlZDINCg0KY29uZnVzaW9uTWF0cml4KGtubl9wcmVkMiwgdGVzdDIkQ2hhbmNlLm9mLkFkbWl0KQ0KYGBgDQoNCiMgQm9vc3RlZCBMb2dpc3RpYyANCg0KbWV0aG9kID0gIkxvZ2l0Qm9vc3QiIA0KDQrqsIDsnqUg6rCE64uo7ZWcIOuqqO2YleydhCDrp4zrk6TslrTshJwg67Cc7KCE7J2EIOyLnO2CpOuKlCDqsoMgDQoNCmBgYHtyfQ0KDQpjdHJsIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSJyZXBlYXRlZGN2IiwgDQogICAgICAgICAgICAgICAgICAgICByZXBlYXRzID0gNSkNCg0KDQp0cmFpbihDaGFuY2Uub2YuQWRtaXR+LiwgDQogICAgICBkYXRhPSB0cmFpbjIsDQogICAgICBtZXRob2QgPSAiTG9naXRCb29zdCIsDQogICAgICB0ckNvbnRyb2w9Y3RybCwgDQogICAgICBwcmVQcm9jZXNzPSBjKCJzY2FsZSIsImNlbnRlciIpLCANCiAgICAgIG1ldHJpYyA9ICJBY2N1cmFjeSIpIC0+IGxvZ2l0X2Jvb3N0DQoNCg0KbG9naXRfYm9vc3QNCmBgYA0KDQoNCmBgYHtyfQ0KDQoNCnBsb3QobG9naXRfYm9vc3QpDQpwcmVkaWN0KGxvZ2l0X2Jvb3N0LCBuZXdkYXRhID0gdGVzdDIpIC0+IHByZWRfbG9nYm9vc3QNCmNvbmZ1c2lvbk1hdHJpeChwcmVkX2xvZ2Jvb3N0LCB0ZXN0MiRDaGFuY2Uub2YuQWRtaXQpDQoNCmBgYA0KDQojIFBlbmFsaXplZCBMb2dpc3RpYyANCg0KbWV0aG9kID0gcGxyDQoNCuygleq3nO2ZlCAtPiDrqqjrjbjsnZgg67O17J6h7ISxIOyhsOygiCAtPiDsmKTrsoTtlLztjIUg67Cp7KeAIA0KDQpgYGB7cn0NCg0KY3RybCA8LSB0cmFpbkNvbnRyb2wobWV0aG9kID0icmVwZWF0ZWRjdiIsIA0KICAgICAgICAgICAgICAgICAgICAgcmVwZWF0cyA9IDUpDQoNCg0KdHJhaW4oQ2hhbmNlLm9mLkFkbWl0fi4sIA0KICAgICAgZGF0YT0gdHJhaW4yLA0KICAgICAgbWV0aG9kID0gInBsciIsDQogICAgICB0ckNvbnRyb2w9Y3RybCwgDQogICAgICBwcmVQcm9jZXNzPSBjKCJzY2FsZSIsImNlbnRlciIpLCANCiAgICAgIG1ldHJpYyA9ICJBY2N1cmFjeSIpIC0+IGxvZ2l0X3BlbmFsIA0KDQpsb2dpdF9wZW5hbA0KDQpgYGANCg0KY3AgKGNvbXBsZXhpdHkgcGFyYW1ldGVyIOuzteyeoeyEsSkgLSDrqqjtmJUg7Y+J6rCAIOuwqeuylSDspJEsIEJJQyDquLDspIAgDQpgYGB7cn0NCnBsb3QobG9naXRfcGVuYWwpDQpgYGANCg0KDQpgYGB7cn0NCnByZWRpY3QobG9naXRfcGVuYWwsIG5ld2RhdGEgPSB0ZXN0MikgLT4gcHJlZF9wbHINCmNvbmZ1c2lvbk1hdHJpeChwcmVkX3BsciwgdGVzdDIkQ2hhbmNlLm9mLkFkbWl0KQ0KYGBgDQoNCiMgTmFpdmUgQmF5ZXMgDQoNCuqwgSBmZWF0dXJl65Ok7J2EIOuPheumveycvOuhnCDrs7Tqs6AsIOyhsOqxtOu2gCDtmZXrpaDroZwg67aE7ISd7ZWY64qUIOq4sOuylSANCg0KYGBge3J9DQoNCg0KY3RybCA8LSB0cmFpbkNvbnRyb2wobWV0aG9kID0icmVwZWF0ZWRjdiIsIA0KICAgICAgICAgICAgICAgICAgICAgcmVwZWF0cyA9IDUpDQoNCg0KdHJhaW4oQ2hhbmNlLm9mLkFkbWl0fi4sIA0KICAgICAgZGF0YT0gdHJhaW4yLA0KICAgICAgbWV0aG9kID0gIm5haXZlX2JheWVzIiwNCiAgICAgIHRyQ29udHJvbD1jdHJsLCANCiAgICAgIHByZVByb2Nlc3M9IGMoInNjYWxlIiwiY2VudGVyIiksIA0KICAgICAgbWV0cmljID0gIkFjY3VyYWN5IikgLT4gbmJfZml0cyANCg0KbmJfZml0cw0KYGBgDQoNCnVzZWtlcm5lcmwgPSDtnojsiqTthqDqt7jrnqjsnYQg7IKs7Jqp7ZW07IScIOy2lOygle2VmOuKlCDqsoMg7Luk64SQIOuwgOuPhCDtlajsiJgg7IKs7Jqp7Jes67aADQphZGp1c3QgPSDsu6TrhJAg67CA64+E7ZWo7IiY7J2YIGJhbmR3aWR0aCDqsJLsnYQg7KGw7KCIIA0KbGFwbGFjZSA9IOudvO2UjOudvOyKpCDsiqTrrLTrlKkg7YyM652866+47YSwIOqwkiDsobDsoIggDQoNCiMgUmFuZG9tIEZvcmVzdCANCg0KYGBge3J9DQpjdHJsIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSJyZXBlYXRlZGN2IiwgDQogICAgICAgICAgICAgICAgICAgICByZXBlYXRzID0gNSkNCg0KDQp0cmFpbihDaGFuY2Uub2YuQWRtaXR+LiwgDQogICAgICBkYXRhPSB0cmFpbjIsDQogICAgICBtZXRob2QgPSAicmYiLA0KICAgICAgdHJDb250cm9sPWN0cmwsIA0KICAgICAgcHJlUHJvY2Vzcz0gYygic2NhbGUiLCJjZW50ZXIiKSwgDQogICAgICBtZXRyaWMgPSAiQWNjdXJhY3kiKSAtPiByZl9maXRzIA0KDQpyZl9maXRzDQpgYGANCg0KDQpgYGB7cn0NCnBsb3QocmZfZml0cykNCmBgYA0KDQoNCmBgYHtyfQ0KcHJlZGljdChyZl9maXRzLCBuZXdkYXRhID0gdGVzdDIpIC0+IHByZWRfcmYNCg0KY29uZnVzaW9uTWF0cml4KHByZWRfcmYsIHRlc3QyJENoYW5jZS5vZi5BZG1pdCkNCmBgYA0KDQojU1ZNIA0KDQoNCg0KYGBge3J9DQpjdHJsIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSJyZXBlYXRlZGN2IiwgDQogICAgICAgICAgICAgICAgICAgICByZXBlYXRzID0gNSkNCg0KDQp0cmFpbihDaGFuY2Uub2YuQWRtaXR+LiwgDQogICAgICBkYXRhPSB0cmFpbjIsDQogICAgICBtZXRob2QgPSAic3ZtTGluZWFyIiwNCiAgICAgIHRyQ29udHJvbD1jdHJsLCANCiAgICAgIHByZVByb2Nlc3M9IGMoInNjYWxlIiwiY2VudGVyIiksIA0KICAgICAgbWV0cmljID0gIkFjY3VyYWN5IikgLT4gc3ZtX2xpbmVhcl9maXQyIA0KDQpzdm1fbGluZWFyX2ZpdDINCmBgYA0KDQoNCmBgYHtyfQ0Kc3ZtX2xpbmVhcl9wcmVkMiA8LSBwcmVkaWN0KHN2bV9saW5lYXJfZml0MiwgbmV3ZGF0YT10ZXN0MikNCmNvbmZ1c2lvbk1hdHJpeChzdm1fbGluZWFyX3ByZWQyLCB0ZXN0MiRDaGFuY2Uub2YuQWRtaXQpDQpgYGANCg0KDQpgYGB7cn0NCmN0cmwgPC0gdHJhaW5Db250cm9sKG1ldGhvZD0icmVwZWF0ZWRjdiIscmVwZWF0cyA9IDUpDQpzdm1fcG9seV9maXQyIDwtIHRyYWluKENoYW5jZS5vZi5BZG1pdCB+IC4sDQpkYXRhID0gdHJhaW4yLA0KbWV0aG9kID0gInN2bVBvbHkiLA0KdHJDb250cm9sID0gY3RybCwNCnByZVByb2Nlc3MgPSBjKCJjZW50ZXIiLCJzY2FsZSIpLA0KbWV0cmljPSJBY2N1cmFjeSIpDQpzdm1fcG9seV9maXQyDQpgYGANCg0KDQpgYGB7cn0NCnBsb3Qoc3ZtX3BvbHlfZml0MikNCmBgYA0KDQoNCmBgYHtyfQ0Kc3ZtX3BvbHlfcHJlZDIgPC0gcHJlZGljdChzdm1fcG9seV9maXQyLCBuZXdkYXRhPXRlc3QyKQ0KY29uZnVzaW9uTWF0cml4KHN2bV9wb2x5X3ByZWQyLCB0ZXN0MiRDaGFuY2Uub2YuQWRtaXQpDQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KDQo=