Rex W. Douglass
Director Machine Learning for Social Science Lab (MSSL)
Center for Peace and Security Studies (cPASS)
Department of Political Science
University of California San Diego
rexdouglass@gmail.com
www.rexdouglass.com
@rexdouglass

1 Course Overview

Please bring a two sided coin(s) and scratch paper to class for passing notes for the demonstrations.

This is a 6 hour introduction to machine learning spread across two three-hour lectures. The goal of this very short course is narrow: to give you enough of an overview, vocabulary, and intuition, so that you can identify machine learning problems in the wild and begin your own research into relevant literatures and possible approaches. The goal is not to train you to execute a particular machine learning solution. There are far too many approaches available; they may not cover whatever problem you find; and the state of the art will be different in a year or two anyway. Instead, we will learn how to think about and classify problems into broad types, how to define and measure the efficacy of different solutions to that problem, how to avoid some common and subtle mistakes, and how to think about a full machine learning pipeline from start to finish.

1.2 Readings Policy

Math and programming are not something you learn, they’re something you get used to. The readings of this course are, with a few exceptions, voluntary and intended for self study. They are to help point you in the right direction when you realize you need to start brushing up on a particular set of tools in order to tackle a particular problem.

1.3 Textbooks

Do not purchase any books - each of these should be available for free on-line at the link given. Any individual one would provide a decent background to the field of machine learning. For this course, I’ve picked select chapters when I thought they did a good job reviewing a specific subtopic.

1.6 Software and Programming

Students are not expected to know any particular language or set of software. We will be demonstrating best practices as used in the Machine Learning for Social Science Lab at the Center for Peace and Security Studies, UCSD. In that lab, our software stack consists of Python and R for data preparation and analysis, Spark for database management, Keras/Tensorflow for deep learning, Github for revision control, and Ubuntu for our operating system and command-line tools.

1.7 Applications

1.8 Notes on this Guide

This guide is written as an R notebook using R-Studio. It renders output as static HTML that you should be able to view on a regular web browser.

#install.packages("pacman")
library(pacman)
p_load(infotheo)
p_load(tidyverse)
The following packages have been unloaded:
tidyverse

Installing package into 㤼㸱C:/Users/skynetmini/Documents/R/win-library/3.4㤼㸲
(as 㤼㸱lib㤼㸲 is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/3.4/tidyverse_1.2.1.zip'
InternetOpenUrl failed: 'The operation timed out'Error in download.file(url, destfile, method, mode = "wb", ...) : 
  cannot open URL 'https://cran.rstudio.com/bin/windows/contrib/3.4/tidyverse_1.2.1.zip'
download of package 㤼㸱tidyverse㤼㸲 failed
tidyverse installed
Failed to install/load:
tidyverse
p_load(ggplot2)
p_load(cowplot)
p_load(mlbench)
p_load(Metrics)
set.seed(123)

2 Introduction

2.1 What is machine learning?

  • (CIML), Chapter 1,
  • (WMLW 1.0) “Introduction”
  • (ISL) “Chapter 2 Statistical Learning”"

2.2 What isn’t machine learning?

2.2.1 Statistics

3 Information Theory

4 Information Sources \(Y\)

4.1 Random Variables and Distributions

4.2 Entropy

4.3 Zero-Bit source

  • Zero-Bit information sources are constants that don’t vary.
  • Zero-Bit source, Zero-Bit message: No variation and no measurement.
  • Zero-Bit information source, One-Bit message: No variation, but a single measurement with variation between two states.
  • Zero-Bit information source, N-Bit message: No variation, and an arbitrary number of measurements with arbitrary number of states

  • “Design, Inference, and the Strategic Logic of Suicide Terrorism”, SCOTT ASHWORTH, JOSHUA D. CLINTON, ADAM MEIROWITZ, and KRISTOPHER W. RAMSAY, 2008, APSR

4.4 Binary Source (\(<=1bit\))

One-Bit information sources are variables that can take on two different states, e.g. a coin flip. Call \(Y\) the true state at the source, and \(\hat{Y}\) the mental model of the state at the destination.

(IntroMachineLearningWithR) “Chapter 3 Example datasets” * Binary_classification

library(infotheo)
N <- 699 #Flip a coin N times (Matched to Breast Cancer Dataset Below)
sample_space <- c(1,0) #Heads and Tails

4.4.1 Fair Coin

A fair coin has equal likelihood of both heads and tails. Estimated entropy is close to the true value of 1 bit.

p <- 0.5 #Fair Coin
Y_coin_fair <- sample(sample_space, size = N,  replace = TRUE,  prob = c(p, 1 - p))  
print(table(Y_coin_fair))
Y_coin_fair
  0   1 
358 341 
print(natstobits(entropy(Y_coin_fair, method="emp")))
[1] 0.9995733

4.4.2 Unfair Coin (p=0.8)

An unfair coin is weighted to be more likely to land heads or tails. Estimated entropy is less than a full bit. There is less surprise than from a full fair coin flip.

p <- 0.8 #Unfair Coin
Y_coin_unfair <- sample(sample_space, size = N,  replace = TRUE,  prob = c(p, 1 - p))  
print(table(Y_coin_unfair))
Y_coin_unfair
  0   1 
126 573 
print(natstobits(entropy(Y_coin_unfair, method="emp")))
[1] 0.68064

4.4.3 Two Headed Coin

A two headed coin will only ever land one way.

p <- 1 #Two headed coin
Y_coin_twoheaded <- sample(sample_space, size = N,  replace = TRUE,  prob = c(p, 1 - p))  
print(table(Y_coin_twoheaded))
Y_coin_twoheaded
  1 
699 
print(natstobits(entropy(Y_coin_twoheaded, method="emp")))
[1] 1.281371e-15

4.4.4 UCI Breast Cancer Dataset

“Breast Cancer”, Raul Eulogio, January 26, 2018

data(BreastCancer)
glimpse(BreastCancer)
Observations: 699
Variables: 11
$ Id              <chr> "1000025", "1002945", "1015425", "1016277", "1017023", "1017122", "101...
$ Cl.thickness    <ord> 5, 5, 3, 6, 4, 8, 1, 2, 2, 4, 1, 2, 5, 1, 8, 7, 4, 4, 10, 6, 7, 10, 3,...
$ Cell.size       <ord> 1, 4, 1, 8, 1, 10, 1, 1, 1, 2, 1, 1, 3, 1, 7, 4, 1, 1, 7, 1, 3, 5, 1, ...
$ Cell.shape      <ord> 1, 4, 1, 8, 1, 10, 1, 2, 1, 1, 1, 1, 3, 1, 5, 6, 1, 1, 7, 1, 2, 5, 1, ...
$ Marg.adhesion   <ord> 1, 5, 1, 1, 3, 8, 1, 1, 1, 1, 1, 1, 3, 1, 10, 4, 1, 1, 6, 1, 10, 3, 1,...
$ Epith.c.size    <ord> 2, 7, 2, 3, 2, 7, 2, 2, 2, 2, 1, 2, 2, 2, 7, 6, 2, 2, 4, 2, 5, 6, 2, 2...
$ Bare.nuclei     <fct> 1, 10, 2, 4, 1, 10, 10, 1, 1, 1, 1, 1, 3, 3, 9, 1, 1, 1, 10, 1, 10, 7,...
$ Bl.cromatin     <fct> 3, 3, 3, 3, 3, 9, 3, 3, 1, 2, 3, 2, 4, 3, 5, 4, 2, 3, 4, 3, 5, 7, 2, 7...
$ Normal.nucleoli <fct> 1, 2, 1, 7, 1, 7, 1, 1, 1, 1, 1, 1, 4, 1, 5, 3, 1, 1, 1, 1, 4, 10, 1, ...
$ Mitoses         <fct> 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 4, 1, 1, 1, 2, 1, 4, 1, 1, 1...
$ Class           <fct> benign, benign, benign, benign, benign, malignant, benign, benign, ben...
summary(BreastCancer$Class)
   benign malignant 
      458       241 
print(natstobits(entropy(BreastCancer$Class, method="emp")))
[1] 0.9293179

4.5 Multi-class Sources

4.5.1 Iris Dataset

data(iris)
glimpse(iris)
Observations: 150
Variables: 5
$ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3, 5.8...
$ Sepal.Width  <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3.0, 3.0, 4.0...
$ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2...
$ Petal.Width  <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2...
$ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, s...
summary(iris$Species)
    setosa versicolor  virginica 
        50         50         50 
print(natstobits(entropy(iris$Species, method="emp")))
[1] 1.584962

4.6 Real Valued Sources

4.6.1 Boston Housing Data

data(BostonHousing)
glimpse(BostonHousing)
Observations: 506
Variables: 14
$ crim    <dbl> 0.00632, 0.02731, 0.02729, 0.03237, 0.06905, 0.02985, 0.08829, 0.14455, 0.2112...
$ zn      <dbl> 18.0, 0.0, 0.0, 0.0, 0.0, 0.0, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 0.0, ...
$ indus   <dbl> 2.31, 7.07, 7.07, 2.18, 2.18, 2.18, 7.87, 7.87, 7.87, 7.87, 7.87, 7.87, 7.87, ...
$ chas    <fct> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
$ nox     <dbl> 0.538, 0.469, 0.469, 0.458, 0.458, 0.458, 0.524, 0.524, 0.524, 0.524, 0.524, 0...
$ rm      <dbl> 6.575, 6.421, 7.185, 6.998, 7.147, 6.430, 6.012, 6.172, 5.631, 6.004, 6.377, 6...
$ age     <dbl> 65.2, 78.9, 61.1, 45.8, 54.2, 58.7, 66.6, 96.1, 100.0, 85.9, 94.3, 82.9, 39.0,...
$ dis     <dbl> 4.0900, 4.9671, 4.9671, 6.0622, 6.0622, 6.0622, 5.5605, 5.9505, 6.0821, 6.5921...
$ rad     <dbl> 1, 2, 2, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, ...
$ tax     <dbl> 296, 242, 242, 222, 222, 222, 311, 311, 311, 311, 311, 311, 311, 307, 307, 307...
$ ptratio <dbl> 15.3, 17.8, 17.8, 18.7, 18.7, 18.7, 15.2, 15.2, 15.2, 15.2, 15.2, 15.2, 15.2, ...
$ b       <dbl> 396.90, 396.90, 392.83, 394.63, 396.90, 394.12, 395.60, 396.90, 386.63, 386.71...
$ lstat   <dbl> 4.98, 9.14, 4.03, 2.94, 5.33, 5.21, 12.43, 19.15, 29.93, 17.10, 20.45, 13.27, ...
$ medv    <dbl> 24.0, 21.6, 34.7, 33.4, 36.2, 28.7, 22.9, 27.1, 16.5, 18.9, 15.0, 18.9, 21.7, ...
summary(BostonHousing$medv)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   5.00   17.02   21.20   22.53   25.00   50.00 
print(natstobits(entropy(discretize(BostonHousing$medv), method="emp")))
[1] 2.80701

5 Comparing \(Y\) and \(\hat{Y}\)

(IntroMachineLearningWithR) 5.4 Classification performance

5.1 Binary

How should we compare the true reality \(Y\) to our mental model of it \(\hat{Y}\)?

5.1.1 Confusion Matrix

table(BreastCancer$Class, BreastCancer$Class)
           
            benign malignant
  benign       458         0
  malignant      0       241
table(BreastCancer$Class, Y_coin_fair)
           Y_coin_fair
              0   1
  benign    239 219
  malignant 119 122
table(BreastCancer$Class, Y_coin_unfair)
           Y_coin_unfair
              0   1
  benign     84 374
  malignant  42 199
table(BreastCancer$Class, Y_coin_twoheaded)
           Y_coin_twoheaded
              1
  benign    458
  malignant 241

5.1.2 Accuracy

p_load(Metrics)
BreastCancer$Class_binary <- as.numeric(BreastCancer$Class=="malignant")
accuracy(BreastCancer$Class_binary, BreastCancer$Class_binary)
[1] 1
accuracy(BreastCancer$Class_binary, Y_coin_fair)
[1] 0.5164521
accuracy(BreastCancer$Class_binary, Y_coin_unfair)
[1] 0.4048641
accuracy(BreastCancer$Class_binary, Y_coin_twoheaded)
[1] 0.3447783

5.1.3 Precision

p_load(Metrics)
Metrics::precision(BreastCancer$Class_binary,
         BreastCancer$Class_binary)
[1] 1
Metrics::precision(BreastCancer$Class_binary, Y_coin_fair)
[1] 0.3577713
Metrics::precision(BreastCancer$Class_binary, Y_coin_unfair)
[1] 0.3472949
Metrics::precision(BreastCancer$Class_binary, Y_coin_twoheaded)
[1] 0.3447783

5.1.4 Recall

p_load(Metrics)
Metrics::recall(BreastCancer$Class_binary,
         BreastCancer$Class_binary)
[1] 1
Metrics::recall(BreastCancer$Class_binary, Y_coin_fair)
[1] 0.5062241
Metrics::recall(BreastCancer$Class_binary, Y_coin_unfair)
[1] 0.8257261
Metrics::recall(BreastCancer$Class_binary, Y_coin_twoheaded) 
[1] 1

5.1.5 F1

#Note Metrics::f1 doesn't give the correct values
p_load(MLmetrics)
F1_Score(BreastCancer$Class_binary,
         BreastCancer$Class_binary)
[1] 1
F1_Score(BreastCancer$Class_binary, Y_coin_fair)
[1] 0.5857843
F1_Score(BreastCancer$Class_binary, Y_coin_unfair)
[1] 0.2876712
#F1_Score(BreastCancer$Class_binary, Y_coin_twoheaded) 
#Not happy about all 1 prediction
print( (0.3447783*1)/(0.3447783+1)*2 ) #Calculate by hand
[1] 0.512766

5.2 Probalistic Predictions

5.2.1 Log Loss

Log Loss

MLmetrics::LogLoss(BreastCancer$Class_binary,
         BreastCancer$Class_binary)
[1] 9.992007e-16
MLmetrics::LogLoss(BreastCancer$Class_binary, Y_coin_fair)
[1] 16.70129
MLmetrics::LogLoss(BreastCancer$Class_binary, Y_coin_unfair)
[1] 20.55531
MLmetrics::LogLoss(BreastCancer$Class_binary, Y_coin_twoheaded) 
[1] 22.63056

5.2.2 Area Under the Curve

Measuring classifier performance: a coherent alternative to the area under the ROC curve, David J. Hand, Mach Learn (2009) 77: 103–123

Generate ROC Curve Charts for Print and Interactive Use, Michael C Sachs, 2018-06-23 Illustrated Guide to ROC and AUC, Raffael Vogler, June 23, 2015

#Simulate a probalistic prediction
noised_prediction <- function(prediction){ noised <-runif(N,0,0.5) ; noised[prediction==1] <-noised[prediction==1]+0.5; return(noised)   }
AUC(noised_prediction(BreastCancer$Class_binary), BreastCancer$Class_binary)
[1] 1
AUC(noised_prediction(Y_coin_fair), BreastCancer$Class_binary)
[1] 0.5230118
AUC(noised_prediction(Y_coin_unfair), BreastCancer$Class_binary)
[1] 0.5179384
AUC(noised_prediction(Y_coin_twoheaded), BreastCancer$Class_binary)
[1] 0.4781388
p_load(plotROC)
Installing package into 㤼㸱C:/Users/skynetmini/Documents/R/win-library/3.4㤼㸲
(as 㤼㸱lib㤼㸲 is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/3.4/plotROC_2.2.1.zip'
InternetOpenUrl failed: 'A connection with the server could not be established'Error in download.file(url, destfile, method, mode = "wb", ...) : 
  cannot open URL 'https://cran.rstudio.com/bin/windows/contrib/3.4/plotROC_2.2.1.zip'
download of package 㤼㸱plotROC㤼㸲 failedthere is no package called 㤼㸱plotROC㤼㸲Failed to install/load:
plotROC
set.seed(2529)
D.ex <- rbinom(200, size = 1, prob = .5)
M1 <- rnorm(200, mean = D.ex, sd = .65)
M2 <- rnorm(200, mean = D.ex, sd = 1.5)
test <- data.frame(D = D.ex, D.str = c("Healthy", "Ill")[D.ex + 1], 
                   M1 = M1, M2 = M2, stringsAsFactors = FALSE)
basicplot <- ggplot(test, aes(d = D, m = M1)) + geom_roc(labels = FALSE)
Error in is_list(x) : object 'rlang_is_list' not found

5.2.4 Others

5.2.5 Imbalanced Data

5.3 Multiclass

5.4 Real Valued

y_hat=mean(BostonHousing$medv)
MAE(BostonHousing$medv, y_hat)
MSE(BostonHousing$medv, y_hat)

6 Transmitters and Receivers

Function_(mathematics)
* Inverse_function

6.1 What makes a good receiver?

6.1.1 Risk Analysis

  • PRML 1.5 “Decision Theory”
  • ESL 2.4 Statistical Decision Theory

6.1.2 Bias-Variance Tradeoff

6.1.4 No Free Lunch

6.2 Ommitted Variable Bias

6.3 Feature Selection / Included Variable Bias

6.4 Feature Engineering

6.5 Bandwidth / Under determination

6.6 Curse of Dimensionality

LS0tDQp0aXRsZTogIkludHJvZHVjdGlvbiB0byBNYWNoaW5lIExlYXJuaW5nIChTeWxsYWJ1cy9Db2RlIGZvciBEYXkgMSk6IEluZm9ybWF0aW9uIFRoZW9yeSBhbmQgUHJvYmxlbXMgaW4gTGVhcm5pbmciDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogdHJ1ZSAjIHRhYmxlIG9mIGNvbnRlbnQgdHJ1ZQ0KICAgIHRvY19kZXB0aDogMyAgIyB1cHRvIHRocmVlIGRlcHRocyBvZiBoZWFkaW5ncyAoc3BlY2lmaWVkIGJ5ICMsICMjIGFuZCAjIyMpDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlICAjIyBpZiB5b3Ugd2FudCBudW1iZXIgc2VjdGlvbnMgYXQgZWFjaCB0YWJsZSBoZWFkZXINCiAgICBoaWdobGlnaHQ6IHRhbmdvICAjIHNwZWNpZmllcyB0aGUgc3ludGF4IGhpZ2hsaWdodGluZyBzdHlsZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KLS0tDQoNCg0KYGBge2Nzc30NCg0KcHJlIGNvZGUsIHByZSwgY29kZSB7DQogIHdoaXRlLXNwYWNlOiBwcmUgIWltcG9ydGFudDsNCiAgb3ZlcmZsb3cteDogIXNjcm9sbCAhaW1wb3J0YW50Ow0KICB3b3JkLWJyZWFrOiBrZWVwLWFsbCAhaW1wb3J0YW50Ow0KICB3b3JkLXdyYXA6IGluaXRpYWwgIWltcG9ydGFudDsNCn0NCg0KY29kZS5yew0KICBvdmVyZmxvdy14OiAhc2Nyb2xsICFpbXBvcnRhbnQ7DQp9DQoNCmBgYA0KDQpSZXggVy4gRG91Z2xhc3M8YnIvPg0KRGlyZWN0b3IgTWFjaGluZSBMZWFybmluZyBmb3IgU29jaWFsIFNjaWVuY2UgTGFiIChNU1NMKTxici8+DQpDZW50ZXIgZm9yIFBlYWNlIGFuZCBTZWN1cml0eSBTdHVkaWVzIChjUEFTUyk8YnIvPg0KRGVwYXJ0bWVudCBvZiBQb2xpdGljYWwgU2NpZW5jZTxici8+DQpVbml2ZXJzaXR5IG9mIENhbGlmb3JuaWEgU2FuIERpZWdvPGJyLz4NCnJleGRvdWdsYXNzQGdtYWlsLmNvbTxici8+DQp3d3cucmV4ZG91Z2xhc3MuY29tPGJyLz4NCkByZXhkb3VnbGFzcyANCg0KIyBDb3Vyc2UgT3ZlcnZpZXcNCg0KUGxlYXNlIGJyaW5nIGEgdHdvIHNpZGVkIGNvaW4ocykgYW5kIHNjcmF0Y2ggcGFwZXIgdG8gY2xhc3MgZm9yIHBhc3Npbmcgbm90ZXMgZm9yIHRoZSBkZW1vbnN0cmF0aW9ucy4NCg0KVGhpcyBpcyBhIDYgaG91ciBpbnRyb2R1Y3Rpb24gdG8gbWFjaGluZSBsZWFybmluZyBzcHJlYWQgYWNyb3NzIHR3byB0aHJlZS1ob3VyIGxlY3R1cmVzLiBUaGUgZ29hbCBvZiB0aGlzIHZlcnkgc2hvcnQgY291cnNlIGlzIG5hcnJvdzogdG8gZ2l2ZSB5b3UgZW5vdWdoIG9mIGFuIG92ZXJ2aWV3LCB2b2NhYnVsYXJ5LCBhbmQgaW50dWl0aW9uLCBzbyB0aGF0IHlvdSBjYW4gaWRlbnRpZnkgbWFjaGluZSBsZWFybmluZyBwcm9ibGVtcyBpbiB0aGUgd2lsZCBhbmQgYmVnaW4geW91ciBvd24gcmVzZWFyY2ggaW50byByZWxldmFudCBsaXRlcmF0dXJlcyBhbmQgcG9zc2libGUgYXBwcm9hY2hlcy4gVGhlIGdvYWwgaXMgbm90IHRvIHRyYWluIHlvdSB0byBleGVjdXRlIGEgcGFydGljdWxhciBtYWNoaW5lIGxlYXJuaW5nIHNvbHV0aW9uLiBUaGVyZSBhcmUgZmFyIHRvbyBtYW55IGFwcHJvYWNoZXMgYXZhaWxhYmxlOyB0aGV5IG1heSBub3QgY292ZXIgd2hhdGV2ZXIgcHJvYmxlbSB5b3UgZmluZDsgYW5kIHRoZSBzdGF0ZSBvZiB0aGUgYXJ0IHdpbGwgYmUgZGlmZmVyZW50IGluIGEgeWVhciBvciB0d28gYW55d2F5LiBJbnN0ZWFkLCB3ZSB3aWxsIGxlYXJuIGhvdyB0byB0aGluayBhYm91dCBhbmQgY2xhc3NpZnkgcHJvYmxlbXMgaW50byBicm9hZCB0eXBlcywgaG93IHRvIGRlZmluZSBhbmQgbWVhc3VyZSB0aGUgZWZmaWNhY3kgb2YgZGlmZmVyZW50IHNvbHV0aW9ucyB0byB0aGF0IHByb2JsZW0sIGhvdyB0byBhdm9pZCBzb21lIGNvbW1vbiBhbmQgc3VidGxlIG1pc3Rha2VzLCBhbmQgaG93IHRvIHRoaW5rIGFib3V0IGEgZnVsbCBtYWNoaW5lIGxlYXJuaW5nIHBpcGVsaW5lIGZyb20gc3RhcnQgdG8gZmluaXNoLg0KDQoNCiMjIENvdXJzZSBTbGlkZXMNCiogW0NvdXJzZSBTbGlkZXMgKDFBKV0oaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vcHJlc2VudGF0aW9uL2QvMTlpMm9tX2p3SzhtM2Etak52Z3RNLVdNVDFsMUhBR2FHdVdlYjRiZ0xzVE0vZWRpdD91c3A9c2hhcmluZykNCiogW0NvdXJzZSBTbGlkZXMgKDFCKV0oaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vcHJlc2VudGF0aW9uL2QvMVo4NTdmRlM2OTJpanBwWFp6clBWanNWeHNsbHdES3pvRkJXT2NoUmpEZlUvZWRpdD91c3A9c2hhcmluZykNCiogW0NvdXJzZSBTbGlkZXMgKDJBKV0oaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vcHJlc2VudGF0aW9uL2QvMUhSelJUanozMXZ0X0h3T2tLRV9qTlVZaGcxYTJMck94UzZMTTNSSTlkRTQvZWRpdD91c3A9c2hhcmluZykNCiogW0NvdXJzZSBTbGlkZXMgKDJCKV0oaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vcHJlc2VudGF0aW9uL2QvMUdTS1Flb1lXVFZsSWZXUUlWOXBYeW9aVzNEVmRMMnlsbWFVVTVkTjlzR0EvZWRpdD91c3A9c2hhcmluZykNCg0KIyMgUmVhZGluZ3MgUG9saWN5DQpNYXRoIGFuZCBwcm9ncmFtbWluZyBhcmUgbm90IHNvbWV0aGluZyB5b3UgbGVhcm4sIHRoZXkncmUgc29tZXRoaW5nIHlvdSBnZXQgdXNlZCB0by4gVGhlIHJlYWRpbmdzIG9mIHRoaXMgY291cnNlIGFyZSwgd2l0aCBhIGZldyBleGNlcHRpb25zLCB2b2x1bnRhcnkgYW5kIGludGVuZGVkIGZvciBzZWxmIHN0dWR5LiBUaGV5IGFyZSB0byBoZWxwIHBvaW50IHlvdSBpbiB0aGUgcmlnaHQgZGlyZWN0aW9uIHdoZW4geW91IHJlYWxpemUgeW91IG5lZWQgdG8gc3RhcnQgYnJ1c2hpbmcgdXAgb24gYSBwYXJ0aWN1bGFyIHNldCBvZiB0b29scyBpbiBvcmRlciB0byB0YWNrbGUgYSBwYXJ0aWN1bGFyIHByb2JsZW0uDQoNCiMjIFRleHRib29rcw0KDQpEbyBub3QgcHVyY2hhc2UgYW55IGJvb2tzIC0gZWFjaCBvZiB0aGVzZSBzaG91bGQgYmUgYXZhaWxhYmxlIGZvciBmcmVlIG9uLWxpbmUgYXQgdGhlIGxpbmsgZ2l2ZW4uIEFueSBpbmRpdmlkdWFsIG9uZSB3b3VsZCBwcm92aWRlIGEgZGVjZW50IGJhY2tncm91bmQgdG8gdGhlIGZpZWxkIG9mIG1hY2hpbmUgbGVhcm5pbmcuIEZvciB0aGlzIGNvdXJzZSwgSSd2ZSBwaWNrZWQgc2VsZWN0IGNoYXB0ZXJzIHdoZW4gSSB0aG91Z2h0IHRoZXkgZGlkIGEgZ29vZCBqb2IgcmV2aWV3aW5nIGEgc3BlY2lmaWMgc3VidG9waWMuDQoNCiogKENJTUwpICBbQSBjb3Vyc2UgaW4gbWFjaGluZSBsZWFybmluZ10oY2ltbC5pbmZvLyksIEhhbCBEYXVtZSBJSUkNCiogKEVTTCkgW0VsZW1lbnRzIG9mIFN0YXRpc3RpY2FsIExlYXJuaW5nXShodHRwczovL3dlYi5zdGFuZm9yZC5lZHUvfmhhc3RpZS9FbGVtU3RhdExlYXJuLyksIFRyZXZvciBIYXN0aWUgYW5kIFJvYmVydCBUaWJzaGlyYW5pDQoqIChJU0wpIFtBbiBpbnRyb2R1Y3Rpb24gdG8gc3RhdGlzdGljYWwgbGVhcm5pbmc6IHdpdGggYXBwbGljYXRpb24gaW4gUiwgR2FyZXRoIEphbWVzXShodHRwczovL3d3dy1iY2YudXNjLmVkdS9+Z2FyZXRoL0lTTC9JU0xSJTIwU2V2ZW50aCUyMFByaW50aW5nLnBkZiksIERhbmllbGEgV2l0dGVuLCBUcmV2b3IgSGFzdGllLCBhbmQgUm9iZXJ0IFRpYnNoaXJhbmkNCiogKElNTCkgW0ludHJvZHVjdGlvbiB0byBNYWNoaW5lIExlYXJuaW5nXShodHRwOi8vYWxleC5zbW9sYS5vcmcvZHJhZnRzL3RoZWJvb2sucGRmKSwgQWxleCBTbW9sYSBhbmQgUy5WLk4uIFZpc2h3YW5hdGhhbg0KKiAoSW50cm9NYWNoaW5lTGVhcm5pbmdXaXRoUikgWyJBbiBJbnRyb2R1Y3Rpb24gdG8gTWFjaGluZSBMZWFybmluZyB3aXRoIFIiXShodHRwczovL2xnYXR0by5naXRodWIuaW8vSW50cm9NYWNoaW5lTGVhcm5pbmdXaXRoUi9pbmRleC5odG1sKSxMYXVyZW50IEdhdHRvLCAyMDE3LTEwLTE4DQoqIChNTCkgW01hY2hpbmUgTGVhcm5pbmc6IFRoZSBhcnQgYW5kIHNjaWVuY2Ugb2YgYWxnb3JpdGhtcyB0aGF0IG1ha2Ugc2Vuc2Ugb2YgZGF0YV0oaHR0cDovL2RzZC5mdXR1cmUtbGFiLmNuL21lbWJlcnMvMjAxNW5scC9QZXRlcl9GbGFjaF9NYWNoaW5lX0xlYXJuaW5nLl9UaGVfQXJ0X2FuZF9TY2llbmMoQm9va1paLm9yZykucGRmKSwgRmxhY2gNCiogKE1MUFApIFtNYWNoaW5lIExlYXJuaW5nOiBBIFByb2JhYmlsaXN0aWMgUGVyc3BlY3RpdmVdKGh0dHBzOi8vd3d3LmNzLnViYy5jYS9+bXVycGh5ay9NTGJvb2svKSwgS2V2aW4gTXVycGh5DQoqIChQUk1MKSBbUGF0dGVyIHJlY29nbml0aW9uIGFuZCBtYWNoaW5lIGxlYXJuaW5nXShodHRwOi8vdXNlcnMuaXNyLmlzdC51dGwucHQvfnd1cm1kL0xpdnJvcy9zY2hvb2wvQmlzaG9wJTIwLSUyMFBhdHRlcm4lMjBSZWNvZ25pdGlvbiUyMEFuZCUyME1hY2hpbmUlMjBMZWFybmluZyUyMC0lMjBTcHJpbmdlciUyMCUyMDIwMDYucGRmKSwgQ2hyaXN0b3BoZXIgTS4gQmlzaG9wDQoqIChXTUxXKSBbIldIWSBNQUNISU5FIExFQVJOSU5HIFdPUktTIl0oaHR0cDovL3d3dy5jcy5jbXUuZWR1L35nbW9udGFuZS9tb250YW5lel9kaXNzZXJ0YXRpb24ucGRmKSwgR2VvcmdlIEQuIE1vbnRhbmV6LCBNYXkgMjAxNywgRGlzc2VydGF0aW9uDQoNCiMjIEdlbmVyYWwgUmVzb3VyY2VzDQoNClJlbGF0ZWQgQ2xhc3Nlcw0KKltDT01TIFc0NzIxIE1hY2hpbmUgTGVhcm5pbmcgZm9yIERhdGEgU2NpZW5jZV0oaHR0cDovL3d3dy5jb2x1bWJpYS5lZHUvfmp3cDIxMjgvVGVhY2hpbmcvVzQ3MjEvU3ByaW5nMjAxNy9XNDcyMVNwcmluZzIwMTcuaHRtbCkNCg0KVGhlcmUgYXJlIGEgbnVtYmVyIHBsYWNlcyBvbi1saW5lIGZvciBjb25zdGFudCB1cGRhdGVzIG9uIG1hY2hpbmUgbGVhcm5pbmcgPGJyLz4NCiogW1JlZGRpdCBNYWNoaW5lIExlYXJuaW5nIFN1YnJlZGRpdF0oaHR0cHM6Ly93d3cucmVkZGl0LmNvbS9yL01hY2hpbmVMZWFybmluZy8pPGJyLz4NCiogW2FyeGl2XShodHRwczovL3R3aXR0ZXIuY29tL2FyeGl2X29yZyk8YnIvPg0KKiBbQXJ4aXYgU2FuaXR5IFByZXNlcnZlcl0oaHR0cDovL3d3dy5hcnhpdi1zYW5pdHkuY29tLyk8YnIvPg0KKiBbTXkgdHdpdHRlciBmZWVkXShodHRwczovL3R3aXR0ZXIuY29tL1JleERvdWdsYXNzKTxici8+DQoqIFtQb2xpdGljYWwgQW5hbHlzaXNdKGh0dHBzOi8vd3d3LmNhbWJyaWRnZS5vcmcvY29yZS9qb3VybmFscy9wb2xpdGljYWwtYW5hbHlzaXMpPGJyLz4NCiogW29wZW5yZXZpZXddKGh0dHBzOi8vb3BlbnJldmlldy5uZXQvKTxici8+DQoqIFtEaXN0aWxsXShodHRwczovL2Rpc3RpbGwucHViLyk8YnIvPg0KDQpDb25mZXJlbmNlcyA8YnIvPg0KKiBbVG9wIENvbmZlcmVuY2VzIGZvciBNYWNoaW5lIExlYXJuaW5nICYgQXJ0aS4gSW50ZWxsaWdlbmNlXShodHRwOi8vd3d3Lmd1aWRlMnJlc2VhcmNoLmNvbS90b3Bjb25mL21hY2hpbmUtbGVhcm5pbmcpIDxici8+DQoqIFtOZXVyYWwgSW5mb3JtYXRpb24gUHJvY2Vzc2luZyBTeXN0ZW1zIChOSVBTKV0oaHR0cHM6Ly9uaXBzLmNjLykgPGJyLz4NCiogW0ludGVybmF0aW9uYWwgQ29uZmVyZW5jZSBvbiBNYWNoaW5lIExlYXJuaW5nXShodHRwczovL2ljbWwuY2MvKSA8YnIvPg0KDQojIyBEYXRhIEFyY2hpdmVzDQoqIFtVQyBJcnZpbmUgTWFjaGluZSBMZWFybmluZyBSZXBvc2l0b3J5XShodHRwOi8vYXJjaGl2ZS5pY3MudWNpLmVkdS9tbC9pbmRleC5waHApPGJyLz4NCiogW0thZ2dsZSBEYXRhc2V0c10oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cz9zb3J0Qnk9dm90ZXMmZ3JvdXA9YWxsKTxici8+DQoqIFtMaXN0X29mX2RhdGFzZXRzX2Zvcl9tYWNoaW5lX2xlYXJuaW5nX3Jlc2VhcmNoXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MaXN0X29mX2RhdGFzZXRzX2Zvcl9tYWNoaW5lX2xlYXJuaW5nX3Jlc2VhcmNoKTxici8+DQoNCiMjIFNvZnR3YXJlIGFuZCBQcm9ncmFtbWluZw0KDQpTdHVkZW50cyBhcmUgbm90IGV4cGVjdGVkIHRvIGtub3cgYW55IHBhcnRpY3VsYXIgbGFuZ3VhZ2Ugb3Igc2V0IG9mIHNvZnR3YXJlLiBXZSB3aWxsIGJlIGRlbW9uc3RyYXRpbmcgYmVzdCBwcmFjdGljZXMgYXMgdXNlZCBpbiB0aGUgTWFjaGluZSBMZWFybmluZyBmb3IgU29jaWFsIFNjaWVuY2UgTGFiIGF0IHRoZSBDZW50ZXIgZm9yIFBlYWNlIGFuZCBTZWN1cml0eSBTdHVkaWVzLCBVQ1NELiBJbiB0aGF0IGxhYiwgb3VyIHNvZnR3YXJlIHN0YWNrIGNvbnNpc3RzIG9mIFB5dGhvbiBhbmQgUiBmb3IgZGF0YSBwcmVwYXJhdGlvbiBhbmQgYW5hbHlzaXMsIFNwYXJrIGZvciBkYXRhYmFzZSBtYW5hZ2VtZW50LCBLZXJhcy9UZW5zb3JmbG93IGZvciBkZWVwIGxlYXJuaW5nLCBHaXRodWIgZm9yIHJldmlzaW9uIGNvbnRyb2wsIGFuZCBVYnVudHUgZm9yIG91ciBvcGVyYXRpbmcgc3lzdGVtIGFuZCBjb21tYW5kLWxpbmUgdG9vbHMuDQoNCiogW01BQ1MgMzA1MDAxIC0gQ29tcHV0aW5nIGZvciB0aGUgU29jaWFsIFNjaWVuY2VzXShodHRwczovL2Nmc3MudWNoaWNhZ28uZWR1L2luZGV4Lmh0bWwpLEJlbmphbWluIFNvbHRvZmYNCiogWyJSIGZvciBEYXRhIFNjaWVuY2UiXShodHRwOi8vcjRkcy5oYWQuY28ubnovKSwgR2FycmV0dCBHcm9sZW11bmQNCiogWyJTcGFyayBhbmQgc3BhcmtseXIsIl0oaHR0cHM6Ly9jZnNzLnVjaGljYWdvLmVkdS9kaXN0cmliMDAzX3NwYXJrLmh0bWwpDQoqIFsiR2l0SHViIGFuZCBSU3R1ZGlvLCJdKGh0dHBzOi8vcmVzb3VyY2VzLmdpdGh1Yi5jb20vYXJ0aWNsZXMvZ2l0aHViLWFuZC1yc3R1ZGlvLykNCiogWyJEYXRhIFNjaWVuY2UgYXQgdGhlIENvbW1hbmQgTGluZSwiXShodHRwczovL3d3dy5kYXRhc2NpZW5jZWF0dGhlY29tbWFuZGxpbmUuY29tLyksIEplcm9lbiBKYW5zc2VucywgRmVicnVhcnkgOCwgMjAxOA0KKiBbIkRhdGEgVmlzdWFsaXphdGlvbjogQSBwcmFjdGljYWwgaW50cm9kdWN0aW9uIl0oaHR0cDovL3NvY3Zpei5jby9pbmRleC5odG1sP3V0bV9jb250ZW50PWJ1ZmZlcjA5NzEwJnV0bV9tZWRpdW09c29jaWFsJnV0bV9zb3VyY2U9dHdpdHRlci5jb20mdXRtX2NhbXBhaWduPWJ1ZmZlciksS2llcmFuIEhlYWx5DQoqIFsiSW50cm9kdWN0aW9uIHRvIFZhbGlkYXRlLCIgaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3ZhbGlkYXRlL3ZpZ25ldHRlcy9pbnRyb2R1Y3Rpb24uaHRtbCkNCiogWyJBbiBpbnRyb2R1Y3Rpb24gdG8gcmVndWxhciBleHByZXNzaW9ucyJdKGh0dHBzOi8vd3d3Lm9yZWlsbHkuY29tL2lkZWFzL2FuLWludHJvZHVjdGlvbi10by1yZWd1bGFyLWV4cHJlc3Npb25zKSwgVGhvbWFzIE5pZWxkLCBEZWNlbWJlciAxMywgMjAxNyAsDQoqIFtSZWdFeHBsYWluXSgiaHR0cHM6Ly9naXRodWIuY29tL2dhZGVuYnVpZS9yZWdleHBsYWluLyNyZWFkbWUiKQ0KKiBbIlRoZSBQbGFpbiBQZXJzb27igJlzIEd1aWRlIHRvIFBsYWluIFRleHQgU29jaWFsIFNjaWVuY2UiXShodHRwOi8vcGxhaW4tdGV4dC5jby8pLCBLaWVyYW4gSGVhbHksIDIwMTgtMDQtMjgNCiogIlN0YXRpc3RpY2FsIERhdGEgQ2xlYW5pbmcgd2l0aCBBcHBsaWNhdGlvbnMgaW4gUiINCiogW3NjaWtpdC1sZWFybl0oaHR0cDovL3NjaWtpdC1sZWFybi5vcmcvc3RhYmxlLykNCiogW0d1aWRlIHRvIFN1cGVyTGVhcm5lcl0oZnRwOi8vY3Jhbi5yLXByb2plY3Qub3JnL3B1Yi9SL3dlYi9wYWNrYWdlcy9TdXBlckxlYXJuZXIvdmlnbmV0dGVzL0d1aWRlLXRvLVN1cGVyTGVhcm5lci5odG1sKSwgQ2hyaXMgS2VubmVkeSwgTWFyY2ggMTYsIDIwMTcNCg0KIyMgQXBwbGljYXRpb25zDQoqIFsiVmlFV1M6IGEgcG9saXRpY2FsIFZpb2xlbmNlIEVhcmx5LVdhcm5pbmcgU3lzdGVtLCJdKGh0dHA6Ly9wY3IudXUuc2UvcmVzZWFyY2gvdmlld3MvKSA8YnIvPg0KKiBbIlNhZmUgRGlzcG9zYWwgb2YgVW5leHBsb2RlZCBXV0lJIEJvbWJzLCJdKGh0dHA6Ly9zdGFmZi5tYXRoLnN1LnNlL2hvZWhsZS9ibG9nLzIwMTgvMDUvMjUvdXhiLmh0bWwpIE1pY2hhZWwgSMO2aGxlLCBNYXkgMjUsIDIwMTgsIDxici8+DQoqIFsiUHJlZGljdGluZyBSYWNlIGFuZCBFdGhuaWNpdHkgRnJvbSB0aGUgU2VxdWVuY2Ugb2YgQ2hhcmFjdGVycyBpbiBhIE5hbWUsIl0oaHR0cHM6Ly9hcnhpdi5vcmcvcGRmLzE4MDUuMDIxMDkucGRmKSxHYXVyYXYgU29vZCBhbmQgU3VyaXlhbiBMYW9oYXByYXBhbm9uLCBNYXkgOCwgMjAxOCwgIDxici8+DQoqIFsiZXRobmljb2xyOiBQcmVkaWN0IFJhY2UgYW5kIEV0aG5pY2l0eSBGcm9tIE5hbWUsIl0oaHR0cHM6Ly9naXRodWIuY29tL2FwcGVsZXIvZXRobmljb2xyKTxici8+DQoqIFdlaWRtYW5uLCBOaWxzIEIuIGFuZCBTZWJhc3RpYW4gU2NodXR0ZS4gVXNpbmcgTmlnaHQgTGlnaHRzIGZvciB0aGUgUHJlZGljdGlvbiBvZiBMb2NhbCBXZWFsdGguIEpvdXJuYWwNCm9mIFBlYWNlIFJlc2VhcmNoIDU0KDIpLg0KDQoNCiMjIE5vdGVzIG9uIHRoaXMgR3VpZGUNCg0KVGhpcyBndWlkZSBpcyB3cml0dGVuIGFzIGFuIFtSIG5vdGVib29rXShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vbm90ZWJvb2suaHRtbCkgdXNpbmcgW1ItU3R1ZGlvXShodHRwczovL3d3dy5yc3R1ZGlvLmNvbS8pLiBJdCByZW5kZXJzIG91dHB1dCBhcyBzdGF0aWMgSFRNTCB0aGF0IHlvdSBzaG91bGQgYmUgYWJsZSB0byB2aWV3IG9uIGEgcmVndWxhciB3ZWIgYnJvd3Nlci4NCg0KYGBge3J9DQojaW5zdGFsbC5wYWNrYWdlcygicGFjbWFuIikNCmxpYnJhcnkocGFjbWFuKQ0KcF9sb2FkKGluZm90aGVvKQ0KcF9sb2FkKHRpZHl2ZXJzZSkNCnBfbG9hZChnZ3Bsb3QyKQ0KcF9sb2FkKGNvd3Bsb3QpDQpwX2xvYWQobWxiZW5jaCkNCnBfbG9hZChNZXRyaWNzKQ0KDQpzZXQuc2VlZCgxMjMpDQoNCmBgYA0KDQojIEludHJvZHVjdGlvbg0KDQojIyBXaGF0IGlzIG1hY2hpbmUgbGVhcm5pbmc/DQoqIChDSU1MKSwgW0NoYXB0ZXIgMSxdKGh0dHA6Ly9jaW1sLmluZm8vZGwvdjBfOTkvY2ltbC12MF85OS1jaDAxLnBkZikgPGJyLz4NCiogKFdNTFcgMS4wKSAiSW50cm9kdWN0aW9uIiA8YnIvPg0KKiAoSVNMKSAiQ2hhcHRlciAyIFN0YXRpc3RpY2FsIExlYXJuaW5nIiINCg0KIyMgV2hhdCBpc24ndCBtYWNoaW5lIGxlYXJuaW5nPw0KDQojIyMgU3RhdGlzdGljcw0KKiBbIlN0YXRpc3RpY2FsIE1vZGVsaW5nOiBUaGUgVHdvIEN1bHR1cmVzICh3aXRoIGNvbW1lbnRzIGFuZCBhIHJlam9pbmRlciBieSB0aGUgIGF1dGhvciksIl0oaHR0cHM6Ly9wcm9qZWN0ZXVjbGlkLm9yZy9kb3dubG9hZC9wZGZfMS9ldWNsaWQuc3MvMTAwOTIxMzcyNikgTGVvIEJyZWltYW4sIFN0YXRpc3RpY2FsIFNjaWVuY2UsIDIwMDEsIFZvbC4gMTYsIE5vLiAzLCAxOTnigJMyMzEgPGJyLz4NCg0KIyMjIENhdXNhbCBJbmZlcmVuY2UNCiogSm9zaHVhIEQuIEFuZ3Jpc3QgJiBKw7Zybi1TdGVmZmVuIFBpc2Noa2UsICJNb3N0bHkgSGFybWxlc3MgRWNvbm9tZXRyaWNzIEFuIEVtcGlyaWNpc3QncyBDb21wYW5pb24sIiAyMDA5DQoqIFsiQmFzaWMgQ29uY2VwdHMgb2YgU3RhdGlzdGljYWwgSW5mZXJlbmNlIGZvciBDYXVzYWwgRWZmZWN0cyBpbiBFeHBlcmltZW50cyBhbmQgT2JzZXJ2YXRpb25hbCBTdHVkaWVzLCJdKGh0dHA6Ly93d3cuc3RhdC5jb2x1bWJpYS5lZHUvfmNvb2svcXIzMy5wZGYpIERvbmFsZCBCLiBSdWJpbiwgMjAwNCA8YnIvPg0KKiBbIldoZW4gYW5kIEhvdyBTaG91bGQgT25lIFVzZSBEZWVwIExlYXJuaW5nIGZvciBDYXVzYWwgRWZmZWN0IEluZmVyZW5jZSJdKGh0dHBzOi8vdGVjaG5pb25tYWlsLW15LnNoYXJlcG9pbnQuY29tL3BlcnNvbmFsL3VyaXNoYWxpdF90ZWNobmlvbl9hY19pbC9fbGF5b3V0cy8xNS9vbmVkcml2ZS5hc3B4P2lkPSUyRnBlcnNvbmFsJTJGdXJpc2hhbGl0X3RlY2huaW9uX2FjX2lsJTJGRG9jdW1lbnRzJTJGUHJlc2VudGF0aW9ucyUyRklBUzIwMTglMkZJQVMyMDE4XzJfZm9yX3B1YmxpYyUyRXBkZiZwYXJlbnQ9JTJGcGVyc29uYWwlMkZ1cmlzaGFsaXRfdGVjaG5pb25fYWNfaWwlMkZEb2N1bWVudHMlMkZQcmVzZW50YXRpb25zJTJGSUFTMjAxOCZzbHJpZD1hYWEyNzU5ZS05MDllLTUwMDAtZmQxNi0zZTMzY2FiZjkyNmYpDQoqIFsiQ29tcGFyaW5nIENvdmFyaWF0ZSBQcmlvcml0aXphdGlvbiB2aWEgTWF0Y2hpbmcgdG8gTWFjaGluZSBMZWFybmluZyBNZXRob2RzIGZvciBDYXVzYWwgSW5mZXJlbmNlIHVzaW5nIEZpdmUgRW1waXJpY2FsIEFwcGxpY2F0aW9ucywiXShodHRwczovL2FyeGl2Lm9yZy9wZGYvMTgwNS4wMzc0My5wZGYpLEx1a2UgS2VlbGUsIER5bGFuIFNtYWxsLCBNYXkgMTEsIDIwMTgsIA0KDQojIEluZm9ybWF0aW9uIFRoZW9yeQ0KDQoqIFtJbmZvcm1hdGlvbl90aGVvcnldKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0luZm9ybWF0aW9uX3RoZW9yeSkNCiogWyJWaXN1YWwgSW5mb3JtYXRpb24gVGhlb3J5LCJdKGh0dHA6Ly9jb2xhaC5naXRodWIuaW8vcG9zdHMvMjAxNS0wOS1WaXN1YWwtSW5mb3JtYXRpb24vKSBDaHJpc3RvcGhlciBPbGFoLCAsIE9jdG9iZXIgMTQsIDIwMTUsIDxici8+DQoqIFtTaGFubm9uIFdlYXZlciBNb2RlbF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2hhbm5vbiVFMiU4MCU5M1dlYXZlcl9tb2RlbCk8YnIvPg0KKiBQUk1MIDEuNiAiSW5mb3JtYXRpb24gVGhlb3J5IiA8YnIvPg0KKiBbIkEgTWF0aGVtYXRpY2FsIFRoZW9yeSBvZiBDb21tdW5pY2F0aW9uLCJdKGh0dHA6Ly9tYXRoLmhhcnZhcmQuZWR1L35jdG0vaG9tZS90ZXh0L290aGVycy9zaGFubm9uL2VudHJvcHkvZW50cm9weS5wZGYpLCBDLiBFLiBTSEFOTk9OLCBPY3RvYmVyIDE5NDgsICBUaGUgQmVsbCBTeXN0ZW0gKiBUZWNobmljYWwgSm91cm5hbCwgVm9sLiAyNywgcHAuIDM3OeKAkzQyMywgNjIz4oCTNjU2LCBKdWx5LCA8YnIvPg0KDQojIEluZm9ybWF0aW9uIFNvdXJjZXMgJFkkIA0KDQojIyBSYW5kb20gVmFyaWFibGVzIGFuZCBEaXN0cmlidXRpb25zDQoqIFtSYW5kb21fdmFyaWFibGVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JhbmRvbV92YXJpYWJsZSkNCiogW0Jpbm9taWFsX2Rpc3RyaWJ1dGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQmlub21pYWxfZGlzdHJpYnV0aW9uKQ0KKiBbIlJldmlldyBvZiBQcm9iYWJpbGl0eSBUaGVvcnkiXShodHRwOi8vY3MyMjkuc3RhbmZvcmQuZWR1L3NlY3Rpb24vY3MyMjktcHJvYi5wZGYpLCBBcmlhbiBNYWxla2kgYW5kIFRvbSBEbyA8YnIvPg0KKiBQUk1MIDIuMCA8YnIvPg0KDQojIyBFbnRyb3B5DQoqIFtFbnRyb3B5IChpbmZvcm1hdGlvbl90aGVvcnkpXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9FbnRyb3B5XyhpbmZvcm1hdGlvbl90aGVvcnkpKTxici8+DQoNCiogW1BhY2thZ2Ug4oCYZW50cm9weSzigJkgIkVzdGltYXRpb24gb2YgRW50cm9weSwgTXV0dWFsIEluZm9ybWF0aW9uIGFuZCBSZWxhdGVkIFF1YW50aXRpZXMsIl0oaHR0cDovL3N0cmltbWVybGFiLm9yZy9zb2Z0d2FyZS9lbnRyb3B5LyksIEZlYnJ1YXJ5IDE5LCAyMDE1ICA8YnIvPg0KKiBbaW5mb3RoZW9dKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9pbmZvdGhlby9pbmRleC5odG1sKSwgUGF0cmljayBFLiBNZXllciwgMjAxNC0wNy0yNiwgUiBQYWNrYWdlIDxici8+DQoqIFtQaGlsZW50cm9weTogSW5mb3JtYXRpb24gVGhlb3J5IGFuZCBEaXN0YW5jZSBRdWFudGlmaWNhdGlvbiB3aXRoIFIuXShodHRwczovL2RvaS5vcmcvMTAuMjExMDUvam9zcy4wMDc2NSksIERyb3N0LCAoMjAxOCksIEpvdXJuYWwgb2YgT3BlbiBTb3VyY2UgU29mdHdhcmUsIDMoMjYpLCA3NjUgIDxici8+DQoNCiMjIFplcm8tQml0IHNvdXJjZQ0KDQoqIFplcm8tQml0IGluZm9ybWF0aW9uIHNvdXJjZXMgYXJlIGNvbnN0YW50cyB0aGF0IGRvbid0IHZhcnkuDQoqIFplcm8tQml0IHNvdXJjZSwgWmVyby1CaXQgbWVzc2FnZTogTm8gdmFyaWF0aW9uIGFuZCBubyBtZWFzdXJlbWVudC4gPGJyLz4NCiogWmVyby1CaXQgaW5mb3JtYXRpb24gc291cmNlLCBPbmUtQml0IG1lc3NhZ2U6IE5vIHZhcmlhdGlvbiwgYnV0IGEgc2luZ2xlIG1lYXN1cmVtZW50IHdpdGggdmFyaWF0aW9uIGJldHdlZW4gdHdvIHN0YXRlcy4gPGJyLz4NCiogWmVyby1CaXQgaW5mb3JtYXRpb24gc291cmNlLCBOLUJpdCBtZXNzYWdlOiBObyB2YXJpYXRpb24sIGFuZCBhbiBhcmJpdHJhcnkgbnVtYmVyIG9mIG1lYXN1cmVtZW50cyB3aXRoIGFyYml0cmFyeSBudW1iZXIgb2Ygc3RhdGVzIDxici8+DQoNCiogWyJEZXNpZ24sIEluZmVyZW5jZSwgYW5kIHRoZSBTdHJhdGVnaWMgTG9naWMgb2YgU3VpY2lkZSBUZXJyb3Jpc20iXShodHRwczovL3BkZnMuc2VtYW50aWNzY2hvbGFyLm9yZy9mMTkyL2NmNjk5MDhjODRkOTJkMjY5ZWY1MmMzMzdmYTQ4N2Q2YjY1ZS5wZGYpLCBTQ09UVCBBU0hXT1JUSCwgSk9TSFVBIEQuIENMSU5UT04sIEFEQU0gTUVJUk9XSVRaLCBhbmQgS1JJU1RPUEhFUiBXLiBSQU1TQVksIDIwMDgsIEFQU1INCg0KIyMgQmluYXJ5IFNvdXJjZSAoJDw9MWJpdCQpDQoNCk9uZS1CaXQgaW5mb3JtYXRpb24gc291cmNlcyBhcmUgdmFyaWFibGVzIHRoYXQgY2FuIHRha2Ugb24gdHdvIGRpZmZlcmVudCBzdGF0ZXMsIGUuZy4gYSBjb2luIGZsaXAuIENhbGwgJFkkIHRoZSB0cnVlIHN0YXRlIGF0IHRoZSBzb3VyY2UsIGFuZCAkXGhhdHtZfSQgdGhlIG1lbnRhbCBtb2RlbCBvZiB0aGUgc3RhdGUgYXQgdGhlIGRlc3RpbmF0aW9uLg0KDQooSW50cm9NYWNoaW5lTGVhcm5pbmdXaXRoUikgIkNoYXB0ZXIgMyBFeGFtcGxlIGRhdGFzZXRzIg0KKiBbQmluYXJ5X2NsYXNzaWZpY2F0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9CaW5hcnlfY2xhc3NpZmljYXRpb24pDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGluZm90aGVvKQ0KTiA8LSA2OTkgI0ZsaXAgYSBjb2luIE4gdGltZXMgKE1hdGNoZWQgdG8gQnJlYXN0IENhbmNlciBEYXRhc2V0IEJlbG93KQ0Kc2FtcGxlX3NwYWNlIDwtIGMoMSwwKSAjSGVhZHMgYW5kIFRhaWxzDQpgYGANCg0KIyMjIEZhaXIgQ29pbiANCg0KQSBmYWlyIGNvaW4gaGFzIGVxdWFsIGxpa2VsaWhvb2Qgb2YgYm90aCBoZWFkcyBhbmQgdGFpbHMuIEVzdGltYXRlZCBlbnRyb3B5IGlzIGNsb3NlIHRvIHRoZSB0cnVlIHZhbHVlIG9mIDEgYml0Lg0KDQpgYGB7cn0NCnAgPC0gMC41ICNGYWlyIENvaW4NCllfY29pbl9mYWlyIDwtIHNhbXBsZShzYW1wbGVfc3BhY2UsIHNpemUgPSBOLCAgcmVwbGFjZSA9IFRSVUUsICBwcm9iID0gYyhwLCAxIC0gcCkpICANCnByaW50KHRhYmxlKFlfY29pbl9mYWlyKSkNCnByaW50KG5hdHN0b2JpdHMoZW50cm9weShZX2NvaW5fZmFpciwgbWV0aG9kPSJlbXAiKSkpDQpgYGANCg0KIyMjIFVuZmFpciBDb2luIChwPTAuOCkNCkFuIHVuZmFpciBjb2luIGlzIHdlaWdodGVkIHRvIGJlIG1vcmUgbGlrZWx5IHRvIGxhbmQgaGVhZHMgb3IgdGFpbHMuIEVzdGltYXRlZCBlbnRyb3B5IGlzIGxlc3MgdGhhbiBhIGZ1bGwgYml0LiBUaGVyZSBpcyBsZXNzIHN1cnByaXNlIHRoYW4gZnJvbSBhIGZ1bGwgZmFpciBjb2luIGZsaXAuDQoNCmBgYHtyfQ0KcCA8LSAwLjggI1VuZmFpciBDb2luDQpZX2NvaW5fdW5mYWlyIDwtIHNhbXBsZShzYW1wbGVfc3BhY2UsIHNpemUgPSBOLCAgcmVwbGFjZSA9IFRSVUUsICBwcm9iID0gYyhwLCAxIC0gcCkpICANCnByaW50KHRhYmxlKFlfY29pbl91bmZhaXIpKQ0KcHJpbnQobmF0c3RvYml0cyhlbnRyb3B5KFlfY29pbl91bmZhaXIsIG1ldGhvZD0iZW1wIikpKQ0KYGBgDQoNCiMjIyBUd28gSGVhZGVkIENvaW4NCkEgdHdvIGhlYWRlZCBjb2luIHdpbGwgb25seSBldmVyIGxhbmQgb25lIHdheS4NCmBgYHtyfQ0KcCA8LSAxICNUd28gaGVhZGVkIGNvaW4NCllfY29pbl90d29oZWFkZWQgPC0gc2FtcGxlKHNhbXBsZV9zcGFjZSwgc2l6ZSA9IE4sICByZXBsYWNlID0gVFJVRSwgIHByb2IgPSBjKHAsIDEgLSBwKSkgIA0KcHJpbnQodGFibGUoWV9jb2luX3R3b2hlYWRlZCkpDQpwcmludChuYXRzdG9iaXRzKGVudHJvcHkoWV9jb2luX3R3b2hlYWRlZCwgbWV0aG9kPSJlbXAiKSkpDQpgYGANCg0KIyMjIFtVQ0kgQnJlYXN0IENhbmNlciBEYXRhc2V0XShodHRwczovL2FyY2hpdmUuaWNzLnVjaS5lZHUvbWwvZGF0YXNldHMvQnJlYXN0K0NhbmNlcitXaXNjb25zaW4rKERpYWdub3N0aWMpKQ0KWyJCcmVhc3QgQ2FuY2VyIl0oaHR0cHM6Ly9ycHVicy5jb20vcmF2aW9sbGk3Ny8zNTI5NTYpLCBSYXVsIEV1bG9naW8sIEphbnVhcnkgMjYsIDIwMTgNCmBgYHtyfQ0KZGF0YShCcmVhc3RDYW5jZXIpDQpnbGltcHNlKEJyZWFzdENhbmNlcikNCnN1bW1hcnkoQnJlYXN0Q2FuY2VyJENsYXNzKQ0KYGBgDQoNCmBgYHtyfQ0KcHJpbnQobmF0c3RvYml0cyhlbnRyb3B5KEJyZWFzdENhbmNlciRDbGFzcywgbWV0aG9kPSJlbXAiKSkpDQpgYGANCg0KIyMgTXVsdGktY2xhc3MgU291cmNlcw0KDQojIyMgW0lyaXMgRGF0YXNldF0oaHR0cHM6Ly9hcmNoaXZlLmljcy51Y2kuZWR1L21sL2RhdGFzZXRzL2lyaXMpDQoNCmBgYHtyfQ0KZGF0YShpcmlzKQ0KZ2xpbXBzZShpcmlzKQ0Kc3VtbWFyeShpcmlzJFNwZWNpZXMpDQpwcmludChuYXRzdG9iaXRzKGVudHJvcHkoaXJpcyRTcGVjaWVzLCBtZXRob2Q9ImVtcCIpKSkNCmBgYA0KDQojIyBSZWFsIFZhbHVlZCBTb3VyY2VzDQoNCiMjIyBbQm9zdG9uIEhvdXNpbmcgRGF0YV0oaHR0cHM6Ly93d3cuY3MudG9yb250by5lZHUvfmRlbHZlL2RhdGEvYm9zdG9uL2Jvc3RvbkRldGFpbC5odG1sKQ0KDQpgYGB7ciwgZWNobz1GfQ0KI2NyaW0gcGVyIGNhcGl0YSBjcmltZSByYXRlIGJ5IHRvd24NCiN6biBwcm9wb3J0aW9uIG9mIHJlc2lkZW50aWFsIGxhbmQgem9uZWQgZm9yIGxvdHMgb3ZlciAyNSwwMDAgc3EuZnQNCiNpbmR1cyBwcm9wb3J0aW9uIG9mIG5vbi1yZXRhaWwgYnVzaW5lc3MgYWNyZXMgcGVyIHRvd24NCiNjaGFzIENoYXJsZXMgUml2ZXIgZHVtbXkgdmFyaWFibGUgKD0gMSBpZiB0cmFjdCBib3VuZHMgcml2ZXI7IDAgb3RoZXJ3aXNlKQ0KI25veCBuaXRyaWMgb3hpZGVzIGNvbmNlbnRyYXRpb24gKHBhcnRzIHBlciAxMCBtaWxsaW9uKQ0KI3JtIGF2ZXJhZ2UgbnVtYmVyIG9mIHJvb21zIHBlciBkd2VsbGluZw0KI2FnZSBwcm9wb3J0aW9uIG9mIG93bmVyLW9jY3VwaWVkIHVuaXRzIGJ1aWx0IHByaW9yIHRvIDE5NDANCiNkaXMgd2VpZ2h0ZWQgZGlzdGFuY2VzIHRvIGZpdmUgQm9zdG9uIGVtcGxveW1lbnQgY2VudHJlcw0KI3JhZCBpbmRleCBvZiBhY2Nlc3NpYmlsaXR5IHRvIHJhZGlhbCBoaWdod2F5cw0KI3RheCBmdWxsLXZhbHVlIHByb3BlcnR5LXRheCByYXRlIHBlciBVU0QgMTAsMDAwDQojcHRyYXRpbyBwdXBpbC10ZWFjaGVyIHJhdGlvIGJ5IHRvd24NCiNiIDEwMDAoQiDiiJIgMC42MykyIHdoZXJlIEIgaXMgdGhlIHByb3BvcnRpb24gb2YgYmxhY2tzIGJ5IHRvd24NCiNsc3RhdCBwZXJjZW50YWdlIG9mIGxvd2VyIHN0YXR1cyBvZiB0aGUgcG9wdWxhdGlvbg0KI21lZHYgbWVkaWFuIHZhbHVlIG9mIG93bmVyLW9jY3VwaWVkIGhvbWVzIGluIFVTRCAxMDAw4oCZcw0KYGBgDQoNCmBgYHtyfQ0KZGF0YShCb3N0b25Ib3VzaW5nKQ0KZ2xpbXBzZShCb3N0b25Ib3VzaW5nKQ0Kc3VtbWFyeShCb3N0b25Ib3VzaW5nJG1lZHYpDQpwcmludChuYXRzdG9iaXRzKGVudHJvcHkoZGlzY3JldGl6ZShCb3N0b25Ib3VzaW5nJG1lZHYpLCBtZXRob2Q9ImVtcCIpKSkNCmBgYA0KDQojIENvbXBhcmluZyAkWSQgYW5kICRcaGF0e1l9JA0KDQooSW50cm9NYWNoaW5lTGVhcm5pbmdXaXRoUikgNS40IENsYXNzaWZpY2F0aW9uIHBlcmZvcm1hbmNlDQoNCiMjIEJpbmFyeQ0KDQpIb3cgc2hvdWxkIHdlIGNvbXBhcmUgdGhlIHRydWUgcmVhbGl0eSAkWSQgdG8gb3VyIG1lbnRhbCBtb2RlbCBvZiBpdCAkXGhhdHtZfSQ/DQoNCiogW1Njb3JpbmcgUnVsZXNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1Njb3JpbmdfcnVsZSk8YnIvPg0KKiBbRXZhbHVhdGlvbl9vZl9iaW5hcnlfY2xhc3NpZmllcnNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0V2YWx1YXRpb25fb2ZfYmluYXJ5X2NsYXNzaWZpZXJzKTxici8+DQoqIFtDb25mdXNpb25fbWF0cml4XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db25mdXNpb25fbWF0cml4KTxici8+DQoNCiMjIyBDb25mdXNpb24gTWF0cml4DQoNCmBgYHtyfQ0KdGFibGUoQnJlYXN0Q2FuY2VyJENsYXNzLCBCcmVhc3RDYW5jZXIkQ2xhc3MpDQp0YWJsZShCcmVhc3RDYW5jZXIkQ2xhc3MsIFlfY29pbl9mYWlyKQ0KdGFibGUoQnJlYXN0Q2FuY2VyJENsYXNzLCBZX2NvaW5fdW5mYWlyKQ0KdGFibGUoQnJlYXN0Q2FuY2VyJENsYXNzLCBZX2NvaW5fdHdvaGVhZGVkKQ0KYGBgDQojIyMgQWNjdXJhY3kNCmBgYHtyfQ0KcF9sb2FkKE1ldHJpY3MpDQpCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5IDwtIGFzLm51bWVyaWMoQnJlYXN0Q2FuY2VyJENsYXNzPT0ibWFsaWduYW50IikNCmFjY3VyYWN5KEJyZWFzdENhbmNlciRDbGFzc19iaW5hcnksIEJyZWFzdENhbmNlciRDbGFzc19iaW5hcnkpDQphY2N1cmFjeShCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5LCBZX2NvaW5fZmFpcikNCmFjY3VyYWN5KEJyZWFzdENhbmNlciRDbGFzc19iaW5hcnksIFlfY29pbl91bmZhaXIpDQphY2N1cmFjeShCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5LCBZX2NvaW5fdHdvaGVhZGVkKQ0KYGBgDQoNCiMjIyBQcmVjaXNpb24NCg0KKiBbUHJlY2lzaW9uX2FuZF9yZWNhbGxdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1ByZWNpc2lvbl9hbmRfcmVjYWxsKTxici8+DQpgYGB7cn0NCnBfbG9hZChNZXRyaWNzKQ0KTWV0cmljczo6cHJlY2lzaW9uKEJyZWFzdENhbmNlciRDbGFzc19iaW5hcnksDQogICAgICAgICBCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5KQ0KTWV0cmljczo6cHJlY2lzaW9uKEJyZWFzdENhbmNlciRDbGFzc19iaW5hcnksIFlfY29pbl9mYWlyKQ0KTWV0cmljczo6cHJlY2lzaW9uKEJyZWFzdENhbmNlciRDbGFzc19iaW5hcnksIFlfY29pbl91bmZhaXIpDQpNZXRyaWNzOjpwcmVjaXNpb24oQnJlYXN0Q2FuY2VyJENsYXNzX2JpbmFyeSwgWV9jb2luX3R3b2hlYWRlZCkNCmBgYA0KDQojIyMgUmVjYWxsDQoNCmBgYHtyfQ0KcF9sb2FkKE1ldHJpY3MpDQpNZXRyaWNzOjpyZWNhbGwoQnJlYXN0Q2FuY2VyJENsYXNzX2JpbmFyeSwNCiAgICAgICAgIEJyZWFzdENhbmNlciRDbGFzc19iaW5hcnkpDQpNZXRyaWNzOjpyZWNhbGwoQnJlYXN0Q2FuY2VyJENsYXNzX2JpbmFyeSwgWV9jb2luX2ZhaXIpDQpNZXRyaWNzOjpyZWNhbGwoQnJlYXN0Q2FuY2VyJENsYXNzX2JpbmFyeSwgWV9jb2luX3VuZmFpcikNCk1ldHJpY3M6OnJlY2FsbChCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5LCBZX2NvaW5fdHdvaGVhZGVkKSANCmBgYA0KDQojIyMgRjENCiogW0YxX3Njb3JlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GMV9zY29yZSk8YnIvPg0KYGBge3J9DQojTm90ZSBNZXRyaWNzOjpmMSBkb2Vzbid0IGdpdmUgdGhlIGNvcnJlY3QgdmFsdWVzDQpwX2xvYWQoTUxtZXRyaWNzKQ0KRjFfU2NvcmUoQnJlYXN0Q2FuY2VyJENsYXNzX2JpbmFyeSwNCiAgICAgICAgIEJyZWFzdENhbmNlciRDbGFzc19iaW5hcnkpDQpGMV9TY29yZShCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5LCBZX2NvaW5fZmFpcikNCkYxX1Njb3JlKEJyZWFzdENhbmNlciRDbGFzc19iaW5hcnksIFlfY29pbl91bmZhaXIpDQojRjFfU2NvcmUoQnJlYXN0Q2FuY2VyJENsYXNzX2JpbmFyeSwgWV9jb2luX3R3b2hlYWRlZCkgDQojTm90IGhhcHB5IGFib3V0IGFsbCAxIHByZWRpY3Rpb24NCnByaW50KCAoMC4zNDQ3NzgzKjEpLygwLjM0NDc3ODMrMSkqMiApICNDYWxjdWxhdGUgYnkgaGFuZA0KYGBgDQoNCg0KKiBbU2Vuc2l0aXZpdHlfYW5kX3NwZWNpZmljaXR5XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TZW5zaXRpdml0eV9hbmRfc3BlY2lmaWNpdHkpPGJyLz4NCiogWyJGaW5kaW5nIFNpbWlsYXIgSXRlbXMiXShodHRwOi8vaW5mb2xhYi5zdGFuZm9yZC5lZHUvfnVsbG1hbi9tbWRzL2NoMy5wZGYpLCBKdXJlIExlc2tvdmVjLCBBbmFuZCBSYWphcmFtYW4sIEplZmYgVWxsbWFuLCBDaGFwdGVyIDMsIFtNaW5pbmcgb2YgTWFzc2l2ZSBEYXRhc2V0c10oaHR0cDovL3d3dy5tbWRzLm9yZy8pLCAyMDE0PGJyLz4NCg0KIyMgUHJvYmFsaXN0aWMgUHJlZGljdGlvbnMNCiogW1Byb3BlciBTY29yaW5nIFJ1bGVzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TY29yaW5nX3J1bGUjUHJvcGVyU2NvcmluZ1J1bGVzKTxici8+DQoNCiMjIyBMb2cgTG9zcw0KDQpbTG9nIExvc3NdKGh0dHA6Ly93aWtpLmZhc3QuYWkvaW5kZXgucGhwL0xvZ19Mb3NzKQ0KDQpgYGB7cn0NCk1MbWV0cmljczo6TG9nTG9zcyhCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5LA0KICAgICAgICAgQnJlYXN0Q2FuY2VyJENsYXNzX2JpbmFyeSkNCk1MbWV0cmljczo6TG9nTG9zcyhCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5LCBZX2NvaW5fZmFpcikNCk1MbWV0cmljczo6TG9nTG9zcyhCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5LCBZX2NvaW5fdW5mYWlyKQ0KTUxtZXRyaWNzOjpMb2dMb3NzKEJyZWFzdENhbmNlciRDbGFzc19iaW5hcnksIFlfY29pbl90d29oZWFkZWQpIA0KYGBgDQoNCiMjIyBBcmVhIFVuZGVyIHRoZSBDdXJ2ZQ0KKiBbUmVjZWl2ZXIgb3BlcmF0aW5nIGNoYXJhY3RlcmlzdGljXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9SZWNlaXZlcl9vcGVyYXRpbmdfY2hhcmFjdGVyaXN0aWMpPGJyLz4NCiogW0FuIGludHJvZHVjdGlvbiB0byBST0MgYW5hbHlzaXNdKGh0dHA6Ly9wZW9wbGUuaW5mLmVsdGUuaHUva2lzcy8xM2R3aGRtL3JvYy5wZGYpLCBUb20gRmF3Y2V0dCwgMjAwNiwgUGF0dGVybiBSZWNvbmduaXRpb24gTGV0dGVyczxici8+DQoqIFt3aGF0LWRvZXMtYXVjLXN0YW5kLWZvci1hbmQtd2hhdC1pcy1pdF0oaHR0cHM6Ly9zdGF0cy5zdGFja2V4Y2hhbmdlLmNvbS9xdWVzdGlvbnMvMTMyNzc3L3doYXQtZG9lcy1hdWMtc3RhbmQtZm9yLWFuZC13aGF0LWlzLWl0KTxici8+DQoqIFtyb2MtYW5kLXByZWNpc2lvbi1yZWNhbGwtd2l0aC1pbWJhbGFuY2VkLWRhdGFzZXRzXShodHRwczovL2NsYXNzZXZhbC53b3JkcHJlc3MuY29tL3NpbXVsYXRpb24tYW5hbHlzaXMvcm9jLWFuZC1wcmVjaXNpb24tcmVjYWxsLXdpdGgtaW1iYWxhbmNlZC1kYXRhc2V0cy8pDQoNCltNZWFzdXJpbmcgY2xhc3NpZmllciBwZXJmb3JtYW5jZTogYSBjb2hlcmVudCBhbHRlcm5hdGl2ZSB0byB0aGUgYXJlYSB1bmRlciB0aGUgUk9DIGN1cnZlXShodHRwOi8vd2ViLmNzLmlhc3RhdGUuZWR1L35jczU3M3gvTm90ZXMvaGFuZC1hcnRpY2xlLnBkZiksIERhdmlkIEouIEhhbmQsIE1hY2ggTGVhcm4gKDIwMDkpIDc3OiAxMDPigJMxMjMNCg0KW0dlbmVyYXRlIFJPQyBDdXJ2ZSBDaGFydHMgZm9yIFByaW50IGFuZCBJbnRlcmFjdGl2ZSBVc2VdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9wbG90Uk9DL3ZpZ25ldHRlcy9leGFtcGxlcy5odG1sKSwgTWljaGFlbCBDIFNhY2hzLCAyMDE4LTA2LTIzDQpbSWxsdXN0cmF0ZWQgR3VpZGUgdG8gUk9DIGFuZCBBVUNdKGh0dHBzOi8vd3d3LnItYmxvZ2dlcnMuY29tL2lsbHVzdHJhdGVkLWd1aWRlLXRvLXJvYy1hbmQtYXVjLyksIFJhZmZhZWwgVm9nbGVyLCBKdW5lIDIzLCAyMDE1DQoNCmBgYHtyfQ0KI1NpbXVsYXRlIGEgcHJvYmFsaXN0aWMgcHJlZGljdGlvbg0Kbm9pc2VkX3ByZWRpY3Rpb24gPC0gZnVuY3Rpb24ocHJlZGljdGlvbil7IG5vaXNlZCA8LXJ1bmlmKE4sMCwwLjUpIDsgbm9pc2VkW3ByZWRpY3Rpb249PTFdIDwtbm9pc2VkW3ByZWRpY3Rpb249PTFdKzAuNTsgcmV0dXJuKG5vaXNlZCkgICB9DQpBVUMobm9pc2VkX3ByZWRpY3Rpb24oQnJlYXN0Q2FuY2VyJENsYXNzX2JpbmFyeSksIEJyZWFzdENhbmNlciRDbGFzc19iaW5hcnkpDQpBVUMobm9pc2VkX3ByZWRpY3Rpb24oWV9jb2luX2ZhaXIpLCBCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5KQ0KQVVDKG5vaXNlZF9wcmVkaWN0aW9uKFlfY29pbl91bmZhaXIpLCBCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5KQ0KQVVDKG5vaXNlZF9wcmVkaWN0aW9uKFlfY29pbl90d29oZWFkZWQpLCBCcmVhc3RDYW5jZXIkQ2xhc3NfYmluYXJ5KQ0KYGBgDQoNCmBgYHtyfQ0KcF9sb2FkKHBsb3RST0MpDQpzZXQuc2VlZCgyNTI5KQ0KRC5leCA8LSByYmlub20oMjAwLCBzaXplID0gMSwgcHJvYiA9IC41KQ0KTTEgPC0gcm5vcm0oMjAwLCBtZWFuID0gRC5leCwgc2QgPSAuNjUpDQpNMiA8LSBybm9ybSgyMDAsIG1lYW4gPSBELmV4LCBzZCA9IDEuNSkNCg0KdGVzdCA8LSBkYXRhLmZyYW1lKEQgPSBELmV4LCBELnN0ciA9IGMoIkhlYWx0aHkiLCAiSWxsIilbRC5leCArIDFdLCANCiAgICAgICAgICAgICAgICAgICBNMSA9IE0xLCBNMiA9IE0yLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpiYXNpY3Bsb3QgPC0gZ2dwbG90KHRlc3QsIGFlcyhkID0gRCwgbSA9IE0xKSkgKyBnZW9tX3JvYyhsYWJlbHMgPSBGQUxTRSkNCmJhc2ljcGxvdA0KDQoNCkQuZXggPC0gcmJpbm9tKDUwLCAxLCAuNSkNCnJvY2RhdGEgPC0gZGF0YS5mcmFtZShEID0gYyhELmV4LCBELmV4KSwgDQogICAgICAgICAgICAgICAgICAgTSA9IGMocm5vcm0oNTAsIG1lYW4gPSBELmV4LCBzZCA9IC40KSwgcm5vcm0oNTAsIG1lYW4gPSBELmV4LCBzZCA9IDEpKSwgDQogICAgICAgICAgICAgICAgICAgWiA9IGMocmVwKCJBIiwgNTApLCByZXAoIkIiLCA1MCkpKQ0KDQpnZ3Bsb3Qocm9jZGF0YSwgYWVzKG0gPSBNLCBkID0gRCkpICsgZ2VvbV9yb2MoKQ0KDQpkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoInNhY2hzbWMvcGxvdFJPQyIpDQoNCmdncGxvdChyb2NkYXRhLCBhZXMobSA9IE0sIGQgPSBELCBjb2xvciA9IFopKSArIGdlb21fcm9jKCkNCg0KDQpgYGANCg0KIyMjDQoNClsiSW50cm9kdWN0aW9uIHRvIHRoZSBwcmVjaXNpb24tcmVjYWxsIHBsb3QiXShodHRwczovL2NsYXNzZXZhbC53b3JkcHJlc3MuY29tL2ludHJvZHVjdGlvbi9pbnRyb2R1Y3Rpb24tdG8tdGhlLXByZWNpc2lvbi1yZWNhbGwtcGxvdC8pLCANCg0KIyMjIE90aGVycw0KKiBbQnJpZXJfc2NvcmVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0JyaWVyX3Njb3JlKTxici8+DQoNCiMjIyBJbWJhbGFuY2VkIERhdGENCg0KKiBbIkZhY2luZyBJbWJhbGFuY2VkIERhdGEgUmVjb21tZW5kYXRpb25zIGZvciB0aGUgVXNlIG9mIFBlcmZvcm1hbmNlIE1ldHJpY3MiXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUM0Mjg1MzU1LyksIEzDoXN6bMOzIEEuIEplbmksMSBKZWZmcmV5IEYuIENvaG4sMSwyIGFuZCBGZXJuYW5kbyBEZSBMYSBUb3JyZSwgSW50IENvbmYgQWZmZWN0IENvbXB1dCBJbnRlbGwgSW50ZXJhY3QgV29ya3Nob3BzLiAyMDEzOyAyMDEzOiAyNDXigJMyNTEuDQoNCiMjIE11bHRpY2xhc3MNCg0KKiBbTXVsdGljbGFzc19jbGFzc2lmaWNhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTXVsdGljbGFzc19jbGFzc2lmaWNhdGlvbikgPGJyLz4NCiogW0Nyb3NzIEVudHJvcHldKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzX2VudHJvcHkpIDxici8+DQoqIFRvbSBGYXdjZXR0ICgyMDA2KSDigJxBbiBpbnRyb2R1Y3Rpb24gdG8gUk9DIGFuYWx5c2lz4oCdLiBQYXR0ZXJuIFJlY29nbml0aW9uIExldHRlcnMgMjcsIDg2MeKAkzg3NC4gRE9JOiAxMC4xMDE2L2oucGF0cmVjLjIwMDUuMTAuMDEwLiA8YnIvPg0KKiBEYXZpZCBKLiBIYW5kIGFuZCBSb2JlcnQgSi4gVGlsbCAoMjAwMSkuIEEgU2ltcGxlIEdlbmVyYWxpc2F0aW9uIG9mIHRoZSBBcmVhIFVuZGVyIHRoZSBST0MgQ3VydmUgZm9yIE11bHRpcGxlIENsYXNzIENsYXNzaWZpY2F0aW9uIFByb2JsZW1zLiBNYWNoaW5lIExlYXJuaW5nIDQ1KDIpLCBwLiAxNzHigJMxODYuIERPSTogMTAuMTAyMy9BOjEwMTA5MjA4MTk4MzEuIDxici8+DQoqIFsicFJPQzogRGlzcGxheSBhbmQgQW5hbHl6ZSBST0MgQ3VydmVzIl0oaHR0cHM6Ly93ZWIuZXhwYXN5Lm9yZy9wUk9DLyksIDIwMTgtMDUtMDYgPGJyLz4NCiogW3BST0M6IGFuIG9wZW4tc291cmNlIHBhY2thZ2UgZm9yIFIgYW5kIFMrIHRvIGFuYWx5emUgYW5kIGNvbXBhcmUgUk9DIGN1cnZlc10oaHR0cHM6Ly9ibWNiaW9pbmZvcm1hdGljcy5iaW9tZWRjZW50cmFsLmNvbS9hcnRpY2xlcy8xMC4xMTg2LzE0NzEtMjEwNS0xMi03NyksIFhhdmllciAqICogUm9iaW4sIE5hdGFjaGEgVHVyY2ssIEFsZXhhbmRyZSBIYWluYXJkLCBOYXRhbGlhIFRpYmVydGksIEZyw6lkw6lyaXF1ZSBMaXNhY2VrLCBKZWFuLUNoYXJsZXMgU2FuY2hleiBhbmQgTWFya3VzIE3DvGxsZXIgKDIwMTEpLiBCTUMgQmlvaW5mb3JtYXRpY3MsIDEyLCBwLiA3NyA8YnIvPg0KDQoNCiMjIFJlYWwgVmFsdWVkDQoNCiogW01lYW5fc3F1YXJlZF9lcnJvcl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTWVhbl9zcXVhcmVkX2Vycm9yKQ0KKiBbSHViZXIgTG9zc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSHViZXJfbG9zcykNCg0KYGBge3J9DQp5X2hhdD1tZWFuKEJvc3RvbkhvdXNpbmckbWVkdikNCk1BRShCb3N0b25Ib3VzaW5nJG1lZHYsIHlfaGF0KQ0KTVNFKEJvc3RvbkhvdXNpbmckbWVkdiwgeV9oYXQpDQpgYGANCg0KIyBUcmFuc21pdHRlcnMgYW5kIFJlY2VpdmVycw0KW0Z1bmN0aW9uXyhtYXRoZW1hdGljcyldKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Z1bmN0aW9uXyhtYXRoZW1hdGljcykpPGJyLz4NCiogW0ludmVyc2VfZnVuY3Rpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0ludmVyc2VfZnVuY3Rpb24pPGJyLz4NCg0KYGBge3IsIGluY2x1ZGU9Rn0NCm49MTAwDQpZX3VuaWY9cnVuaWYobj1uKQ0KYmV0YV8xPS41DQpYPShZX3VuaWYpL2JldGFfMSAjZXBzaWxvbl9nYXVzc2lhbg0KcDEgPC0gZGF0YS5mcmFtZShYLFlfdW5pZikgJT4lIGdncGxvdChhZXMoeD1ZX3VuaWYseT1YKSkgKyBnZW9tX3BvaW50KCkNCg0KZXBzaWxvbl9nYXVzc2lhbj1ybm9ybShuPW4sIG1lYW4gPSAwLCBzZCA9IDEpDQpiZXRhXzE9LjUNClg9KFlfdW5pZikvYmV0YV8xICsgKFlfdW5pZl4yKS9iZXRhXzEgI2Vwc2lsb25fZ2F1c3NpYW4NCnAyIDwtIGRhdGEuZnJhbWUoWCxZX3VuaWYpICU+JSBnZ3Bsb3QoYWVzKHg9WV91bmlmLHk9WCkpICsgZ2VvbV9wb2ludCgpDQoNClg9IFlfdW5pZiA+IC41DQpwMyA8LSBkYXRhLmZyYW1lKFgsWV91bmlmKSAlPiUgZ2dwbG90KGFlcyh4PVlfdW5pZix5PVgpKSArIGdlb21fcG9pbnQoKQ0KDQpYPSBjb3MoWV91bmlmKQ0KcDQgPC0gZGF0YS5mcmFtZShYLFlfdW5pZikgJT4lIGdncGxvdChhZXMoeD1ZX3VuaWYseT1YKSkgKyBnZW9tX3BvaW50KCkNCg0KcGxvdF9ncmlkKHAxLHAyLHAzLHA0LCBsYWJlbHMgPSBjKCJBIiwgIkIiLCAiQyIsICJEIiksIG5jb2wgPSAyKQ0KDQpgYGANCg0KDQojIyBXaGF0IG1ha2VzIGEgZ29vZCByZWNlaXZlcj8NCg0KIyMjIFJpc2sgQW5hbHlzaXMNCiogUFJNTCAxLjUgIkRlY2lzaW9uIFRoZW9yeSIgPGJyLz4NCiogRVNMIDIuNCBTdGF0aXN0aWNhbCBEZWNpc2lvbiBUaGVvcnkNCg0KIyMjIEJpYXMtVmFyaWFuY2UgVHJhZGVvZmYgPGJyLz4NCiogWyJVbmRlcnN0YW5kaW5nIHRoZSBCaWFzLVZhcmlhbmNlIFRyYWRlb2ZmLCJdKGh0dHA6Ly9zY290dC5mb3J0bWFubi1yb2UuY29tL2RvY3MvQmlhc1ZhcmlhbmNlLmh0bWwpLCBTY290dCBGb3J0bWFubi1Sb2UsICAyMDEyLCA8YnIvPg0KDQojIyMgT3ZlcmZpdHRpbmcNCiogW092ZXJmaXR0aW5nXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9PdmVyZml0dGluZyk8YnIvPg0KKiBbVHJhaW5pbmcsX3Rlc3QsX2FuZF92YWxpZGF0aW9uX3NldHNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1RyYWluaW5nLF90ZXN0LF9hbmRfdmFsaWRhdGlvbl9zZXRzKTxici8+DQoNCiMjIyBObyBGcmVlIEx1bmNoDQoNCiogV01MVyAyLjAgIlJlbGF0ZWQgV29yayINCiogWyJObyBGcmVlIEx1bmNoIFRoZW9yZW1zIGZvciBPcHRpbWl6YXRpb24sIl0oaHR0cHM6Ly90aS5hcmMubmFzYS5nb3YvbS9wcm9maWxlL2Rody9wYXBlcnMvNzgucGRmKSBEYXZpZCBILiBXb2xwZXJ0IGFuZCBXaWxsaWFtIEcuIE1hY3JlYWR5LCAxOTk3LCA8YnIvPg0KDQojIyBPbW1pdHRlZCBWYXJpYWJsZSBCaWFzDQoqIFtTaW1wc29ucyBQYXJhZG94XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TaW1wc29uJTI3c19wYXJhZG94KTxici8+DQoNCiMjIEZlYXR1cmUgU2VsZWN0aW9uIC8gSW5jbHVkZWQgVmFyaWFibGUgQmlhcw0KKiBbTGV04oCZcyBQdXQgR2FyYmFnZeKAlENhbiBSZWdyZXNzaW9ucyBhbmQgR2FyYmFnZeKAlENhbiBQcm9iaXRzIFdoZXJlIFRoZXkgQmVsb25nXShodHRwOi8vd3d3LmNvbHVtYmlhLmVkdS9+Z2p3MTAvYWNoZW4wNC5wZGYpLCBDaHJpc3RvcGhlciBILiBBY2hlbiwgQ29uZmxpY3QgTWFuYWdlbWVudCBhbmQgUGVhY2UgU2NpZW5jZSwgMjAwNQ0KKiBbIlRoZSBQaGFudG9tIE1lbmFjZTogT21pdHRlZCBWYXJpYWJsZSBCaWFzIGluIEVjb25vbWV0cmljIFJlc2VhcmNoIl0oaHR0cDovL3d3dy5zYXJhbWl0Y2hlbGwub3JnL2NsYXJrZTA1LnBkZiksIEtldmluIEEuIENsYXJrZSwgMjAwNSwgQ29uZmxpY3QgTWFuYWdlbWVudCBhbmQgUGVhY2UgU2NpZW5jZQ0KKiBbIkFjaGlldmluZyBTdGF0aXN0aWNhbCBTaWduaWZpY2FuY2Ugd2l0aCBDb3ZhcmlhdGVzIGFuZCB3aXRob3V0IFRyYW5zcGFyZW5jeSJdKGh0dHBzOi8vZHJpdmUuZ29vZ2xlLmNvbS9maWxlL2QvMEIxM0dyU2RqdTRDcGNqQktNR1U1Wm1Sak4yYy92aWV3KSwgR2FicmllbCBMZW56LCBBbGV4YW5kZXIgU2FobiwgTm92ZW1iZXIgMjcsIDIwMTcNCg0KKiBbU0NBTk5JTkcgREVBRCBTQUxNT04gSU4gRk1SSSBNQUNISU5FIEhJR0hMSUdIVFMgUklTSyBPRiBSRUQgSEVSUklOR1NdKGh0dHBzOi8vd3d3LndpcmVkLmNvbS8yMDA5LzA5L2ZtcmlzYWxtb24vKQ0KKiBb4oCcRG8gV2UgUmVhbGx5IEtub3cgdGhlIFdUTyBDdXJlcyBDYW5jZXI/4oCdXShodHRwOi8vd3d3LnN0ZXBoZW5jaGF1ZG9pbi5jb20vQ0hIX0NhbmNlcl8yMDE0XzA5XzE4LnBkZikgU3RlcGhlbiBDaGF1ZG9pbiwgSnVkZSBIYXlzIGFuZCBSYXltb25kIEhpY2tzLCBCcml0aXNoIEpvdXJuYWwgb2YgUG9saXRpY2FsIFNjaWVuY2UuDQoNCiogW0ZlYXR1cmVfc2VsZWN0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GZWF0dXJlX3NlbGVjdGlvbik8YnIvPg0KKiBbQ29uZm91bmRpbmddKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NvbmZvdW5kaW5nKTxici8+DQoqIFsiU3RhdGlzdGljYWwgbGVhcm5pbmcgYW5kIHNlbGVjdGl2ZSBpbmZlcmVuY2UiXShodHRwOi8vd3d3LnBuYXMub3JnL2NvbnRlbnQvcG5hcy8xMTIvMjUvNzYyOS5mdWxsLnBkZikgSm9uYXRoYW4gVGF5bG9yYSBhbmQgUm9iZXJ0IEouIFRpYnNoaXJhbmksIEp1bmUgMjMsIDIwMTU8YnIvPg0KKiBbIlRoZSBnYXJkZW4gb2YgZm9ya2luZyBwYXRoczogV2h5IG11bHRpcGxlIGNvbXBhcmlzb25zIGNhbiBiZSBhIHByb2JsZW0sICB3aGVuIHRoZXJlIGlzIG5vIOKAnGZpc2hpbmcgZXhwZWRpdGlvbuKAnSBvciDigJxwLWhhY2tpbmfigJ0gYW5kIHRoZSByZXNlYXJjaCAgd2FzIHBvc2l0ZWQgYWhlYWQgb2YgdGltZSJdKGh0dHA6Ly93d3cuc3RhdC5jb2x1bWJpYS5lZHUvfmdlbG1hbi9yZXNlYXJjaC91bnB1Ymxpc2hlZC9wX2hhY2tpbmcucGRmKSwgQW5kcmV3IEdlbG1hbiBhbmQgRXJpYyBMb2tlbiwgMTQgTm92IDIwMTMsIFVucHVibGlzaGVkIE1hbnVzY3JpcHQ8YnIvPg0KKiBbUC1IYWNraW5nXShodHRwczovL3Byb2plY3RzLmZpdmV0aGlydHllaWdodC5jb20vcC1oYWNraW5nLyk8YnIvPg0KDQojIyBGZWF0dXJlIEVuZ2luZWVyaW5nDQoqIFtGZWF0dXJlX2VuZ2luZWVyaW5nXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GZWF0dXJlX2VuZ2luZWVyaW5nKTxici8+DQoNCiMjIEJhbmR3aWR0aCAvIFVuZGVyIGRldGVybWluYXRpb24NCg0KKiBbVW5kZXJkZXRlcm1pbmVkIHN5c3RlbV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVW5kZXJkZXRlcm1pbmVkX3N5c3RlbSkNCg0KKiBbT3ZlcmRldGVybWluZWRfc3lzdGVtXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9PdmVyZGV0ZXJtaW5lZF9zeXN0ZW0pPGJyLz4NCg0KIyMgQ3Vyc2Ugb2YgRGltZW5zaW9uYWxpdHkNCg0KKiBbQ3Vyc2Vfb2ZfZGltZW5zaW9uYWxpdHldKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0N1cnNlX29mX2RpbWVuc2lvbmFsaXR5KSA8YnIvPg0KKiBbVGhlIEN1cnNlIG9mIERpbWVuc2lvbmFsaXR5IGluIGNsYXNzaWZpY2F0aW9uXShodHRwOi8vd3d3LnZpc2lvbmR1bW15LmNvbS8yMDE0LzA0L2N1cnNlLWRpbWVuc2lvbmFsaXR5LWFmZmVjdC1jbGFzc2lmaWNhdGlvbi8pLCBWaW5jZW50IFNwcnV5dCA8YnIvPg0KKFBSTUwpICIxLjQgVGhlIEN1cnNlIG9mIERpbWVuc2lvbmFsaXR5Ig0KDQo=