Data Description

Project 538 provided over thirty-thousand rows of data from the 2016, 2020, 2024 presidential elections. Twenty-thousand rows related to specific states were excluded.

Key variables included:

Methods

Load assessment data

Load spending data

New names:
• `` -> `...73`
• `` -> `...74`
• `` -> `...75`
• `` -> `...76`
• `` -> `...77`
• `` -> `...78`
• `` -> `...79`
• `` -> `...80`
• `` -> `...81`
• `` -> `...82`
• `` -> `...83`
• `` -> `...84`
• `` -> `...85`
• `` -> `...86`
• `` -> `...87`
• `` -> `...88`
• `` -> `...89`
• `` -> `...90`
• `` -> `...91`
• `` -> `...92`
• `` -> `...93`
• `` -> `...94`
• `` -> `...95`
• `` -> `...96`
• `` -> `...97`
• `` -> `...98`
• `` -> `...99`
• `` -> `...100`
• `` -> `...101`
• `` -> `...102`
• `` -> `...103`
• `` -> `...104`
• `` -> `...105`
• `` -> `...106`
• `` -> `...107`
• `` -> `...108`
• `` -> `...109`
• `` -> `...110`
• `` -> `...111`
• `` -> `...112`
• `` -> `...113`
• `` -> `...114`
• `` -> `...115`
• `` -> `...116`
• `` -> `...117`
• `` -> `...118`
• `` -> `...119`
• `` -> `...120`
• `` -> `...121`
• `` -> `...122`
• `` -> `...123`
• `` -> `...124`
• `` -> `...125`
• `` -> `...126`
• `` -> `...127`
• `` -> `...128`
• `` -> `...129`
• `` -> `...130`
• `` -> `...131`
• `` -> `...132`
• `` -> `...133`
• `` -> `...134`
• `` -> `...135`
• `` -> `...136`
• `` -> `...137`
• `` -> `...138`
• `` -> `...139`
• `` -> `...140`
• `` -> `...141`
• `` -> `...142`
• `` -> `...143`
• `` -> `...144`
• `` -> `...145`
• `` -> `...146`
• `` -> `...147`
• `` -> `...148`
• `` -> `...149`
• `` -> `...150`
• `` -> `...151`
• `` -> `...152`
• `` -> `...153`
• `` -> `...154`
• `` -> `...155`
• `` -> `...156`
• `` -> `...157`
• `` -> `...158`
• `` -> `...159`
• `` -> `...160`
• `` -> `...161`
• `` -> `...162`
• `` -> `...163`
• `` -> `...164`
• `` -> `...165`
• `` -> `...166`
• `` -> `...167`
• `` -> `...168`
• `` -> `...169`
• `` -> `...170`
• `` -> `...171`
• `` -> `...172`
• `` -> `...173`
• `` -> `...174`
• `` -> `...175`
• `` -> `...176`
• `` -> `...177`
• `` -> `...178`
• `` -> `...179`
• `` -> `...180`
• `` -> `...181`
• `` -> `...182`
• `` -> `...183`
• `` -> `...184`

Load demographic data

Warning: One or more parsing issues, call `problems()` on your data frame
for details, e.g.:
  dat <- vroom(...)
  problems(dat)
Rows: 62 Columns: 5
── Column specification ────────────────────────────────────────────
Delimiter: ","
chr (3): County, FIPS, Rank within US (of 3143 counties)
dbl (2): Value (Percent), People (Unemployed)

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Adding in new data

Warning: One or more parsing issues, call `problems()` on your data frame
for details, e.g.:
  dat <- vroom(...)
  problems(dat)
Rows: 64 Columns: 5
── Column specification ────────────────────────────────────────────
Delimiter: ","
chr (2): County, Rank within US (of 3143 counties)
dbl (3): FIPS, Value (Percent), People (Education: Less Than 9th...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Warning: One or more parsing issues, call `problems()` on your data frame
for details, e.g.:
  dat <- vroom(...)
  problems(dat)
Rows: 64 Columns: 5
── Column specification ────────────────────────────────────────────
Delimiter: ","
chr (2): County, Rank within US (of 3143 counties)
dbl (3): FIPS, Value (Percent), People(Education: Less Than High...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Warning: One or more parsing issues, call `problems()` on your data frame
for details, e.g.:
  dat <- vroom(...)
  problems(dat)
Rows: 64 Columns: 5
── Column specification ────────────────────────────────────────────
Delimiter: ","
chr (2): County, Rank within US (of 3143 counties)
dbl (3): FIPS, Value (Percent), People (Education: At Least Bach...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Warning: One or more parsing issues, call `problems()` on your data frame
for details, e.g.:
  dat <- vroom(...)
  problems(dat)
Rows: 65 Columns: 4
── Column specification ────────────────────────────────────────────
Delimiter: ","
chr (2): County, Rank within US (of 3142 counties)
dbl (1): FIPS
num (1): Value (Dollars)

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Warning: One or more parsing issues, call `problems()` on your data frame
for details, e.g.:
  dat <- vroom(...)
  problems(dat)
Rows: 65 Columns: 4
── Column specification ────────────────────────────────────────────
Delimiter: ","
chr (2): County, Rank within US (of 3142 counties)
dbl (1): FIPS
num (1): Value (Dollars)

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Warning: One or more parsing issues, call `problems()` on your data frame
for details, e.g.:
  dat <- vroom(...)
  problems(dat)
Rows: 64 Columns: 4
── Column specification ────────────────────────────────────────────
Delimiter: ","
chr (2): County, Rank within US (of 3135 counties)
dbl (1): FIPS
num (1): Value (Dollars)

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Joined data

Correlations

Create test/training data

Linear Regression Model


Call:
lm(formula = proficiency ~ enroll + tlocrev + ppcstot + unemployed + 
    at_least_bachelor_education + household_income, data = t_train)

Residuals:
    Min      1Q  Median      3Q     Max 
-6.7360 -2.9337 -0.2146  2.3756  8.5571 

Coefficients:
                               Estimate  Std. Error t value Pr(>|t|)   
(Intercept)                  8.59405726 10.62009737   0.809  0.42418   
enroll                       0.00045645  0.00052416   0.871  0.39014   
tlocrev                     -0.00001838  0.00008596  -0.214  0.83201   
ppcstot                      0.00070458  0.00044490   1.584  0.12281   
unemployed                  -0.19554527  0.27793175  -0.704  0.48663   
at_least_bachelor_education  0.39826973  0.13013574   3.060  0.00437 **
household_income             0.00007607  0.00012306   0.618  0.54074   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.912 on 33 degrees of freedom
Multiple R-squared:  0.5629,    Adjusted R-squared:  0.4834 
F-statistic: 7.082 on 6 and 33 DF,  p-value: 0.00006584

Root Mean Squared Error (RMSE): 4.939345 
R-squared: 0.3152698 
Error in usmap::map_with_data(data, values = values, include = include,  : 
  `data` must be a data.frame containing either a `state` or `fips` column.

pca

k-means

Decision Tree

Cross-fold validation

Bootstrapping

We don’t have equal number of spam and non-spam messages. We can use bootstrapping to create a more balanced dataset.

Note that we re-used the function from earlier to return a t_train and a t_test using our bootstrapped sample.

LS0tDQp0aXRsZTogIlIgUHJvamVjdCAzIg0KYXV0aG9yOiAiSm9zaCBGcmVlbWFuIg0KZGF0ZTogIjExLzIyLzIwMjQiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyBUaGVzaXM6IFRoZSBQcm9qZWN0IDUzOCBwcmVkaWN0aW9uIG1vZGVscyBvdmVyZXN0aW1hdGUgdGhlIHBvcHVsYXIgdm90ZSBzdXBwb3J0IGZvciB0aGlyZC1wYXJ0eSBjYW5kaWRhdGVzLCByZXN1bHRpbmcgaW4gYW4gdW5kZXJlc3RpbWF0aW9uIG9mIFJlcHVibGljYW4gcG9wdWxhciB2b3RlIHN1cHBvcnQgYW5kIGNyZWF0aW5nIHRoZSBmYWxzZSBpbXByZXNzaW9uIHRoYXQgdGhlIHJhY2UgaXMgbGVzcyBjb21wZXRpdGl2ZSB0aGFuIGl0IHRydWx5IGlzLg0KDQpUaGlzIGFuYWx5c2lzIHVzZXMgcG9wdWxhciB2b3RlIGRhdGEgZnJvbSAyMDE2IGFuZCAyMDIwIHRvIHByZWRpY3QgdGhlIHBvcHVsYXIgdm90ZSBwZXIgY2FuZGlkYXRlIGZvciB0aGUgMjAyNCBlbGVjdGlvbi4gSXRzIGRhdGEgaW5jbHVkZXMgdGhlIGVsZWN0aW9uIHllYXIsIHRoZSBjYW5kaWRhdGUsIHRoZSBncmFkZSBvZiB0aGUgcG9sbHN0ZXIsIGFuZCB0aGUgcG9wdWxhciB2b3RlIHByZWRpY3Rpb24gcGVyIHBvbGxzdGVyLiBJZiBQcm9qZWN0IDUzOCBwb2xsc3RlciBkYXRhIG92ZXIgcHJlZGljdHMgdGhlIHRoaXJkLXBhcnR5IGNhbmRpZGF0ZSBhbmQgdW5kZXIgcHJlZGljdHMgdGhlIHJlcHVibGljYW4gYW5kIGRlbW9jcmF0aWMgY2FuZGlkYXRlLCBJIGV4cGVjdCB0aGUgYWN0dWFsIHBvcHVsYXIgdm90ZSB0byBoYXZlIGxlc3Mgdm90ZXMgZm9yIHRoZSB0aGlyZC1wYXJ0eSBjYW5kaWRhdGUgYW5kIG1vcmUgdm90ZXMgZm9yIHJlcHVibGljYW4gYW5kIGRlbW9jcmF0aWMgY2FuZGlkYXRlcy4gUHJvcG9ydGlvbmFsbHksIHRob3VnaCwgdGhlIHJlcHVibGljYW4gY2FuZGlkYXRlIHNob3VsZCBnZXQgbW9yZSBvZiB0aGUgdGhpcmQtcGFydHkgdm90ZXMgdGhhbiB0aGUgZGVtb2NyYXRpYyBjYW5kaWRhdGUuIEhvd2V2ZXIsIGlmIHRoZSBwcmVkaWN0aW9ucyBmb3IgdGhlIHJlcHVibGljYW4sIGRlbW9jcmF0aWMsIGFuZCB0aGlyZC1wYXJ0eSBjYW5kaWRhdGUgYXJlIGFjY3VyYXRlLCB0aGUgUHJvamVjdCA1MzggcG9sbHN0ZXIgZGF0YSBpcyBhY2N1cmF0ZSBhcyBpcy4NCg0KDQojIyBEYXRhIERlc2NyaXB0aW9uDQoNClByb2plY3QgNTM4IHByb3ZpZGVkIG92ZXIgdGhpcnR5LXRob3VzYW5kIHJvd3Mgb2YgZGF0YSBmcm9tIHRoZSAyMDE2LCAyMDIwLCAyMDI0IHByZXNpZGVudGlhbCBlbGVjdGlvbnMuIFR3ZW50eS10aG91c2FuZCByb3dzIHJlbGF0ZWQgdG8gc3BlY2lmaWMgc3RhdGVzIHdlcmUgZXhjbHVkZWQuDQoNCktleSB2YXJpYWJsZXMgaW5jbHVkZWQ6DQoNCi0gKipDYW5kaWRhdGUqKjogVGhlIHByZXNpZGVudGlhbCBjYW5kaWRhdGUgdGVybWVkIGVpdGhlciBieSByZXB1YmxpY2FuLCBkZW1vY3JhdCwgb3Igb3RoZXIuDQotICoqQXZlcmFnZSBFcnJvcioqOiBUaGUgZXJyb3Igb2YgYWN0dWFsIHBlcmNlbnRhZ2UgbWludXMgcHJlZGljdGVkIHBlcmNlbnRhZ2Ugb24gYXZlcmFnZSBwZXIgY2FuZGlkYXRlLg0KLSAqKlByZWRpY3RlZCBQZXJjZW50YWdlKio6IFRoZSBwZXJjZW50YWdlIG9mIHRoZSBwb3B1bGFyIHZvdGUgcGVyIGNhbmRpZGF0ZSB0aGF0IHdhcyBwcmVkaWN0ZWQgYnkgdGhlIDUzOCBwb2xsc3RlciBkYXRhLg0KLSAqKkV4cGVjdGVkIFBlcmNlbnRhZ2UqKjogVGhlIHBlcmNlbnRhZ2Ugb2YgdGhlIHBvcHVsYXIgdm90ZSBwZXIgY2FuZGlkYXRlIHRoYXQgaXMgZXhwZWN0ZWQgYmFzZWQgb24gdGhlIDUzOCBwb2xsc3RlciBkYXRhIHByZWRpY3Rpb25zLg0KLSAqKkFjdHVhbCBQZXJjZW50YWdlKio6IFRoZSBwZXJjZW50YWdlIG9mIHRoZSBwb3B1bGFyIHZvdGUgcGVyIGNhbmRpZGF0ZSB0aGF0IGFjdHVhbGx5IG9jY3VycmVkIGZvciBwcmV2aW91cyBlbGVjdGlvbnMuDQotICoqQXZlcmFnZSBQZXJjZW50YWdlKio6IFRoZSBhdmVyYWdlIHBlcmNlbnRhZ2Ugb2YgdGhlIHBvcHVsYXIgdm90ZSBwZXIgY2FuZGlkYXRlIHByZWRpY3RlZCB3aXRoIGFuZCB3aXRob3V0IGEgbW9kZWwuDQotICoqRnJlcXVlbmN5Kio6IFRoZSBudW1iZXIgb2YgdGltZXMgYSB2YWx1ZSBvY2N1cnMuDQotICoqUmVzaWR1YWxzKio6IFRoZSBhY3R1YWwgcGVyY2VudGFnZSByZXN1bHQgcGVyIGNhbmRpZGF0ZSBtaW51cyB0aGUgcHJlZGljdGVkIHBlcmNlbnRhZ2UgcmVzdWx0IHBlciBjYW5kaWRhdGUuDQoNCiMjIE1ldGhvZHMNCg0KIyMjIExvYWQgYXNzZXNzbWVudCBkYXRhDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KHJwYXJ0KQ0KbGlicmFyeShyZWFkeGwpDQphc3Nlc3NtZW50X3BhdGggPC0gJy4vd3YgZWQgc3R1ZGVudCBhY2hpZXZlbWVudC9IaXN0b3JpY2FsX0Fzc2Vzc21lbnRSZXN1bHRzX1NZMTUtdG8tU1kyMS54bHN4Jw0KDQoNCnRfYXNzZXNzX3Jhd19zY2hvb2wgPC0gcmVhZF9leGNlbChwYXRoID0gYXNzZXNzbWVudF9wYXRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAnU1kyMSBTY2hvb2wgJiBEaXN0cmljdCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZSA9ICdiMjpmNzMxMicpDQoNCg0KdF9hc3Nlc3NfcmF3X3NjaWVuY2UgPC0gcmVhZF9leGNlbChwYXRoID0gYXNzZXNzbWVudF9wYXRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAnU1kyMSBTY2hvb2wgJiBEaXN0cmljdCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZSA9ICdkYjM6ZGI3MzEyJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xfbmFtZXMgPSBjKCdzY2llbmNlX3Byb2ZpY2llbmN5JyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBuYSA9ICcqKicpDQoNCnRfYXNzZXNzIDwtIHRfYXNzZXNzX3Jhd19zY2hvb2wgJT4lDQogIGJpbmRfY29scyh0X2Fzc2Vzc19yYXdfc2NpZW5jZSkgJT4lIA0KICBqYW5pdG9yOjpjbGVhbl9uYW1lcygpICU+JSANCiAgZmlsdGVyKHNjaG9vbCA9PSA5OTkpICU+JSANCiAgZmlsdGVyKHBvcHVsYXRpb25fZ3JvdXAgPT0gJ1RvdGFsIFBvcHVsYXRpb24nKSAlPiUgDQogIGZpbHRlcihjb3VudHkgIT0gJ1N0YXRld2lkZScpICU+JSANCiAgbXV0YXRlKHByb2ZpY2llbmN5ID0gc2NpZW5jZV9wcm9maWNpZW5jeSkgIA0KDQp2aWV3KHRfYXNzZXNzKQ0KYGBgDQoNCiMjIyBMb2FkIHNwZW5kaW5nIGRhdGENCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kc3BlbmRpbmdfcGF0aCA8LSAnLi91cyBjZW5zdXMgZWQgc3BlbmRpbmcvZWxzZWMyMnQueGxzJw0KDQp0X3NwZW5kaW5nX3JhdyA8LSByZWFkX2V4Y2VsKHBhdGggPSBzcGVuZGluZ19wYXRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAnZWxzZWMyMnQnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UgPSAnYTE6Z2IxNDEwNicpICU+JSANCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKQ0KDQoNCmNvb3BlcmF0ZXMgPC0gYygnTU9VTlRBSU4gU1RBVEUgRURVQ0FUSU9OQUwgU0VSVklDRVMgQ09PUEVSQVRJVkUnLA0KICAgICAgICAgICAgICAgICdFQVNURVJOIFBBTkhBTkRMRSBJTlNUUlVDVElPTkFMIENPT1BFUkFUSVZFJywNCiAgICAgICAgICAgICAgICAnU09VVEhFUk4gRURVQ0FUSU9OQUwgU0VSVklDRVMgQ09PUEVSQVRJVkUnKQ0KDQp0X3NwZW5kaW5nIDwtIHRfc3BlbmRpbmdfcmF3ICU+JSANCiAgZmlsdGVyKHN0YXRlID09IDQ5KSAlPiUgDQogIGZpbHRlcighbmFtZSAlaW4lIGNvb3BlcmF0ZXMpICU+JSANCiAgc2VsZWN0KG5hbWUsIGVucm9sbCwgdGZlZHJldiwgdHN0cmV2LCB0bG9jcmV2LCB0b3RhbGV4cCwgcHBjc3RvdCkgJT4lIA0KICBtdXRhdGUoY291bnR5ID0gc3RyX3RvX3RpdGxlKHN0cl9zcGxpdF9pKG5hbWUsICcgJywxKSksDQogICAgICAgICBjb3VudHkgPSBpZmVsc2UoY291bnR5ID09ICdNYycsICdNY0Rvd2VsbCcsIGNvdW50eSkpICU+JSANCiAgbXV0YXRlKGNvdW50eSA9IHBhc3RlMChjb3VudHksICIgQ291bnR5IikpDQoNCg0Kdmlldyh0X3NwZW5kaW5nKQ0KYGBgDQoNCiMjIyBMb2FkIGRlbW9ncmFwaGljIGRhdGENCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KdF9kZW1vZ3JhcGhpY3MgPC0gcmVhZF9jc3YoJy4vZGVtb2dyYXBoaWNzL3VuZW1wbG95ZWQuY3N2JywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2tpcCA9IDQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEgPSAnTi9BJykgJT4lDQogIGphbml0b3I6OmNsZWFuX25hbWVzKCkgJT4lIA0KICBmaWx0ZXIoY291bnR5ICE9ICdXZXN0IFZpcmdpbmlhJywNCiAgICAgICAgIGNvdW50eSAhPSAnVW5pdGVkIFN0YXRlcycsDQogICAgICAgICAhaXMubmEodmFsdWVfcGVyY2VudCkgKSAlPiUgDQogIHNlbGVjdChjb3VudHksIHZhbHVlX3BlcmNlbnQpICU+JQ0KICByZW5hbWUodW5lbXBsb3llZCA9IHZhbHVlX3BlcmNlbnQpDQoNCnZpZXcodF9kZW1vZ3JhcGhpY3MpDQpgYGANCg0KIyMjIEFkZGluZyBpbiBuZXcgZGF0YQ0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBBZGRpbmcgaW4gbWF0aCBhbmQgcmVhZGluZyBwcm9maWNpZW5jeQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KHJwYXJ0KQ0KbGlicmFyeShyZWFkeGwpDQoNCmFzc2Vzc21lbnRfcGF0aCA8LSAnLi93diBlZCBzdHVkZW50IGFjaGlldmVtZW50L0hpc3RvcmljYWxfQXNzZXNzbWVudFJlc3VsdHNfU1kxNS10by1TWTIxLnhsc3gnDQoNCg0KdF9hc3Nlc3NfcmF3X3NjaG9vbCA8LSByZWFkX2V4Y2VsKHBhdGggPSBhc3Nlc3NtZW50X3BhdGgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzaGVldCA9ICdTWTIxIFNjaG9vbCAmIERpc3RyaWN0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlID0gJ2IyOmY3MzEyJykNCg0KDQp0X2Fzc2Vzc19yYXdfbWF0aCA8LSByZWFkX2V4Y2VsKHBhdGggPSBhc3Nlc3NtZW50X3BhdGgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzaGVldCA9ICdTWTIxIFNjaG9vbCAmIERpc3RyaWN0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlID0gJ2F0MzphdDczMTInLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbF9uYW1lcyA9IGMoJ21hdGhfcHJvZmljaWVuY3knKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hID0gJyoqJykNCg0KdF9hc3Nlc3NfcmF3X3JlYWRpbmcgPC0gcmVhZF9leGNlbChwYXRoID0gYXNzZXNzbWVudF9wYXRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAnU1kyMSBTY2hvb2wgJiBEaXN0cmljdCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZSA9ICdjaDM6Y2g3MzEyJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xfbmFtZXMgPSBjKCdyZWFkaW5nX3Byb2ZpY2llbmN5JyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBuYSA9ICcqKicpDQoNCnRfYXNzZXNzIDwtIHRfYXNzZXNzX3Jhd19zY2hvb2wgJT4lDQogIGJpbmRfY29scyh0X2Fzc2Vzc19yYXdfc2NpZW5jZSkgJT4lIA0KICBiaW5kX2NvbHModF9hc3Nlc3NfcmF3X21hdGgpICU+JSANCiAgYmluZF9jb2xzKHRfYXNzZXNzX3Jhd19yZWFkaW5nKSAlPiUgDQogIGphbml0b3I6OmNsZWFuX25hbWVzKCkgJT4lIA0KICBmaWx0ZXIoc2Nob29sID09IDk5OSkgJT4lIA0KICBmaWx0ZXIocG9wdWxhdGlvbl9ncm91cCA9PSAnVG90YWwgUG9wdWxhdGlvbicpICU+JSANCiAgZmlsdGVyKGNvdW50eSAhPSAnU3RhdGV3aWRlJykgJT4lIA0KICBtdXRhdGUocHJvZmljaWVuY3kgPSAoc2NpZW5jZV9wcm9maWNpZW5jeSArIG1hdGhfcHJvZmljaWVuY3kgKyByZWFkaW5nX3Byb2ZpY2llbmN5KSAvIDMpICU+JSANCiAgbXV0YXRlKGNvdW50eSA9IHBhc3RlMChjb3VudHksICIgQ291bnR5IikpDQoNCnZpZXcodF9hc3Nlc3MpDQoNCiMgQWRkaW5nIGluIGVkdWNhdGlvbmFsIGRhdGENCg0KIyMgbGVzcyB0aGFuIDl0aCBncmFkZQ0KDQplZHVjYXRpb25fOXRoX3BhdGggPC0gJy4vd3YgZWR1Y2F0aW9uIGRhdGEvV1ZFZHVjYXRpb25MZXNzVGhhbjl0aEdyYWRlLmNzdicNCg0KdF9lZHVjYXRpb25fOXRoIDwtIHJlYWRfY3N2KGVkdWNhdGlvbl85dGhfcGF0aCwNCnNraXAgPSA1LA0KbmEgPSAiTi9BIikgJT4lIA0KICBqYW5pdG9yOjpjbGVhbl9uYW1lcygpICU+JSANCiAgZmlsdGVyKGNvdW50eSAhPSAnV2VzdCBWaXJnaW5pYScsDQogICAgICAgICBjb3VudHkgIT0gJ1VuaXRlZCBTdGF0ZXMnLA0KICAgICAgICAgIWlzLm5hKHZhbHVlX3BlcmNlbnQpICkgJT4lIA0KICBzZWxlY3QoY291bnR5LCB2YWx1ZV9wZXJjZW50KSAlPiUNCiAgcmVuYW1lKGxlc3NfdGhhbl85dGhfZ3JhZGVfZWR1Y2F0aW9uID0gdmFsdWVfcGVyY2VudCkNCg0Kdmlldyh0X2VkdWNhdGlvbl85dGgpDQoNCiMjIGxlc3MgdGhhbiAxMnRoIGdyYWRlDQoNCmVkdWNhdGlvbl9oaWdoX3NjaG9vbF9wYXRoIDwtICcuL3d2IGVkdWNhdGlvbiBkYXRhL1dWRWR1Y2F0aW9uTGVzc1RoYW5IaWdoU2Nob29sLmNzdicNCg0KdF9lZHVjYXRpb25faGlnaF9zY2hvb2wgPC0gcmVhZF9jc3YoZWR1Y2F0aW9uX2hpZ2hfc2Nob29sX3BhdGgsDQpza2lwID0gNSwNCm5hID0gIk4vQSIpICU+JSANCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgDQogIGZpbHRlcihjb3VudHkgIT0gJ1dlc3QgVmlyZ2luaWEnLA0KICAgICAgICAgY291bnR5ICE9ICdVbml0ZWQgU3RhdGVzJywNCiAgICAgICAgICFpcy5uYSh2YWx1ZV9wZXJjZW50KSApICU+JSANCiAgc2VsZWN0KGNvdW50eSwgdmFsdWVfcGVyY2VudCkgJT4lDQogIHJlbmFtZShsZXNzX3RoYW5faGlnaF9zY2hvb2xfZ3JhZGVfZWR1Y2F0aW9uID0gdmFsdWVfcGVyY2VudCkNCg0Kdmlldyh0X2VkdWNhdGlvbl9oaWdoX3NjaG9vbCkNCg0KIyMgYXQgbGVhc3QgYSBiYWNoZWxvcnMNCg0KZWR1Y2F0aW9uX2JhY2hlbG9yX3BhdGggPC0gJy4vd3YgZWR1Y2F0aW9uIGRhdGEvV1ZFZHVjYXRpb25BdExlYXN0QmFjaGVsb3JzRGVncmVlLmNzdicNCg0KdF9lZHVjYXRpb25fYmFjaGVsb3IgPC0gcmVhZF9jc3YoZWR1Y2F0aW9uX2JhY2hlbG9yX3BhdGgsDQpza2lwID0gNSwNCm5hID0gIk4vQSIpICU+JSANCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgDQogIGZpbHRlcihjb3VudHkgIT0gJ1dlc3QgVmlyZ2luaWEnLA0KICAgICAgICAgY291bnR5ICE9ICdVbml0ZWQgU3RhdGVzJywNCiAgICAgICAgICFpcy5uYSh2YWx1ZV9wZXJjZW50KSApICU+JSANCiAgc2VsZWN0KGNvdW50eSwgdmFsdWVfcGVyY2VudCkgJT4lDQogIHJlbmFtZShhdF9sZWFzdF9iYWNoZWxvcl9lZHVjYXRpb24gPSB2YWx1ZV9wZXJjZW50KQ0KDQp2aWV3KHRfZWR1Y2F0aW9uX2JhY2hlbG9yKQ0KDQojIEFkZGluZyBpbiBpbmNvbWUgZGF0YQ0KDQojIyBmYW1pbHkgaW5jb21lDQoNCmZhbWlseV9pbmNvbWVfcGF0aCA8LSAnLi93diBpbmNvbWUgZGF0YS9XVkZhbWlseUluY29tZS5jc3YnDQoNCnRfZmFtaWx5X2luY29tZSA8LSByZWFkX2NzdihmYW1pbHlfaW5jb21lX3BhdGgsDQpza2lwID0gNCwNCm5hID0gIk4vQSIpICU+JSANCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgDQogIGZpbHRlcihjb3VudHkgIT0gJ1dlc3QgVmlyZ2luaWEnLA0KICAgICAgICAgY291bnR5ICE9ICdVbml0ZWQgU3RhdGVzJywNCiAgICAgICAgICFpcy5uYSh2YWx1ZV9kb2xsYXJzKSApICU+JSANCiAgc2VsZWN0KGNvdW50eSwgdmFsdWVfZG9sbGFycykgJT4lDQogIHJlbmFtZShmYW1pbHlfaW5jb21lID0gdmFsdWVfZG9sbGFycykNCg0Kdmlldyh0X2ZhbWlseV9pbmNvbWUpDQoNCiMjIGhvdXNlaG9sZCBpbmNvbWUNCg0KaG91c2Vob2xkX2luY29tZV9wYXRoIDwtICcuL3d2IGluY29tZSBkYXRhL1dWSG91c2Vob2xkSW5jb21lLmNzdicNCg0KdF9ob3VzZWhvbGRfaW5jb21lIDwtIHJlYWRfY3N2KGhvdXNlaG9sZF9pbmNvbWVfcGF0aCwNCnNraXAgPSA0LA0KbmEgPSAiTi9BIikgJT4lIA0KICBqYW5pdG9yOjpjbGVhbl9uYW1lcygpICU+JSANCiAgZmlsdGVyKGNvdW50eSAhPSAnV2VzdCBWaXJnaW5pYScsDQogICAgICAgICBjb3VudHkgIT0gJ1VuaXRlZCBTdGF0ZXMnLA0KICAgICAgICAgIWlzLm5hKHZhbHVlX2RvbGxhcnMpICkgJT4lIA0KICBzZWxlY3QoY291bnR5LCB2YWx1ZV9kb2xsYXJzKSAlPiUNCiAgcmVuYW1lKGhvdXNlaG9sZF9pbmNvbWUgPSB2YWx1ZV9kb2xsYXJzKQ0KDQp2aWV3KHRfaG91c2Vob2xkX2luY29tZSkNCg0KIyMgdmFzdCBtYWpvcml0eSBpbmNvbWUNCg0KdmFzdF9tYWpvcml0eV9pbmNvbWVfcGF0aCA8LSAnLi93diBpbmNvbWUgZGF0YS9XVlZhc3RNYWpvcml0eUluY29tZS5jc3YnDQoNCnRfdmFzdF9tYWpvcml0eV9pbmNvbWUgPC0gcmVhZF9jc3YodmFzdF9tYWpvcml0eV9pbmNvbWVfcGF0aCwNCnNraXAgPSA1LA0KbmEgPSAiTi9BIikgJT4lIA0KICBqYW5pdG9yOjpjbGVhbl9uYW1lcygpICU+JSANCiAgZmlsdGVyKGNvdW50eSAhPSAnV2VzdCBWaXJnaW5pYScsDQogICAgICAgICBjb3VudHkgIT0gJ1VuaXRlZCBTdGF0ZXMnLA0KICAgICAgICAgIWlzLm5hKHZhbHVlX2RvbGxhcnMpICkgJT4lIA0KICBzZWxlY3QoY291bnR5LCB2YWx1ZV9kb2xsYXJzKSAlPiUNCiAgcmVuYW1lKHZhc3RfbWFqb3JpdHlfaW5jb21lID0gdmFsdWVfZG9sbGFycykNCg0Kdmlldyh0X3Zhc3RfbWFqb3JpdHlfaW5jb21lKQ0KDQpgYGANCg0KIyMjIEpvaW5lZCBkYXRhDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwdXJycikNCg0KIyBMaXN0IG9mIGFsbCB0YWJsZSBuYW1lcw0KdGFibGVzIDwtIGxpc3QoDQogIHRfYXNzZXNzLA0KICB0X2RlbW9ncmFwaGljcywNCiAgdF9lZHVjYXRpb25fOXRoLA0KICB0X2VkdWNhdGlvbl9iYWNoZWxvciwNCiAgdF9lZHVjYXRpb25faGlnaF9zY2hvb2wsDQogIHRfZmFtaWx5X2luY29tZSwNCiAgdF9ob3VzZWhvbGRfaW5jb21lLA0KICB0X3NwZW5kaW5nLA0KICB0X3Zhc3RfbWFqb3JpdHlfaW5jb21lDQopDQoNCiMgSm9pbiBhbGwgdGFibGVzIG9uIHRoZSAnY291bnR5JyBjb2x1bW4NCnQgPC0gcmVkdWNlKHRhYmxlcywgZnVsbF9qb2luLCBieSA9ICJjb3VudHkiKQ0KDQp0IDwtIHQgJT4lIA0KICBzZWxlY3QoLXNjaG9vbCwgLXNjaG9vbF9uYW1lLCAtcG9wdWxhdGlvbl9ncm91cCwgLXN1Ymdyb3VwLCAtbmFtZSkNCnQgPC0gdCAlPiUgDQogIHNlbGVjdChjb3VudHksIGVucm9sbCwgdGZlZHJldiwgdHN0cmV2LCB0bG9jcmV2LCB0b3RhbGV4cCwgcHBjc3RvdCwgdW5lbXBsb3llZCwgbGVzc190aGFuXzl0aF9ncmFkZV9lZHVjYXRpb24sIGxlc3NfdGhhbl9oaWdoX3NjaG9vbF9ncmFkZV9lZHVjYXRpb24sIGF0X2xlYXN0X2JhY2hlbG9yX2VkdWNhdGlvbiwgdmFzdF9tYWpvcml0eV9pbmNvbWUsIGhvdXNlaG9sZF9pbmNvbWUsIGZhbWlseV9pbmNvbWUsIHByb2ZpY2llbmN5KQ0KDQp2aWV3KHQpDQpgYGANCg0KDQojIyMgQ29ycmVsYXRpb25zDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGdnY29ycnBsb3QpDQpjIDwtIGNvcih0ICU+JSBzZWxlY3Qod2hlcmUoaXMubnVtZXJpYykpKQ0KDQpnZ2NvcnJwbG90KGMsIA0KICAgICAgICAgICBoYy5vcmRlciA9IFRSVUUsIA0KICAgICAgICAgICB0eXBlID0gImxvd2VyIiwgDQogICAgICAgICAgIGxhYiA9IEZBTFNFLCANCiAgICAgICAgICAgbGFiX3NpemUgPSAxMDAsIA0KICAgICAgICAgICBtZXRob2QgPSAiY2lyY2xlIikNCg0KYGBgDQoNCiMjIyBDcmVhdGUgdGVzdC90cmFpbmluZyBkYXRhDQoNCmBgYHt1bmRlZmluZWQgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KIyBDcmVhdGUgdHJhaW5pbmcvdGVzdCBzcGxpdA0Kc2FtcGxlIDwtIHNhbXBsZShjKDEsIDApLCBzaXplID0gbnJvdyh0KSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuNywgMC4zKSkNCnRfdHJhaW4gPC0gdFtzYW1wbGUgPT0gMSwgXQ0KdF90ZXN0IDwtIHRbc2FtcGxlID09IDAsIF0NCg0KYGBgDQoNCiMjIyBMaW5lYXIgUmVncmVzc2lvbiBNb2RlbA0KDQpgYGB7dW5kZWZpbmVkIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIEVuc3VyZSBjb3VudHkgaXMgYSBmYWN0b3IgaW4gYm90aCBkYXRhc2V0cw0KdF90cmFpbiRjb3VudHkgPC0gYXMuZmFjdG9yKHRfdHJhaW4kY291bnR5KQ0KdF90ZXN0JGNvdW50eSA8LSBmYWN0b3IodF90ZXN0JGNvdW50eSwgbGV2ZWxzID0gbGV2ZWxzKHRfdHJhaW4kY291bnR5KSkNCg0KIyBCdWlsZCB0aGUgbW9kZWwgZXhjbHVkaW5nIGNvdW50eQ0KbW9kZWwgPC0gbG0ocHJvZmljaWVuY3kgfiBlbnJvbGwgKyB0bG9jcmV2ICsgcHBjc3RvdCArIHVuZW1wbG95ZWQgKyBhdF9sZWFzdF9iYWNoZWxvcl9lZHVjYXRpb24gKyBob3VzZWhvbGRfaW5jb21lLCBkYXRhID0gdF90cmFpbikNCnN1bW1hcnkobW9kZWwpDQoNCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCnByZWRpY3RlZF9wcm9maWNpZW5jeSA8LSBwcmVkaWN0KG1vZGVsLCBuZXdkYXRhID0gdF90ZXN0KQ0KDQojIEFkZCBwcmVkaWN0aW9ucyBhbmQgcmVzaWR1YWxzIHRvIHRoZSB0ZXN0IGRhdGFzZXQNCnRfdGVzdCA8LSB0X3Rlc3QgJT4lDQogIG11dGF0ZShwcmVkaWN0aW9uID0gcHJlZGljdGVkX3Byb2ZpY2llbmN5LCANCiAgICAgICAgIHJlc2lkdWFscyA9IHByb2ZpY2llbmN5IC0gcHJlZGljdGlvbikNCg0KIyBIYW5kbGUgTkFzIGluIHJlc2lkdWFscyAoaWYgYW55KQ0KdF90ZXN0IDwtIHRfdGVzdCAlPiUgZmlsdGVyKCFpcy5uYShwcmVkaWN0aW9uKSwgIWlzLm5hKHByb2ZpY2llbmN5KSkNCg0KIyBFdmFsdWF0ZSB0aGUgbW9kZWwNCm9wdGlvbnMoc2NpcGVuID0gOTk5KQ0KDQojIFBsb3QgcmVzaWR1YWxzDQpoaXN0KHRfdGVzdCRyZXNpZHVhbHMsIA0KICAgICBtYWluID0gIkhpc3RvZ3JhbSBvZiBSZXNpZHVhbHMiLCANCiAgICAgeGxhYiA9ICJSZXNpZHVhbHMiLCANCiAgICAgY29sID0gImxpZ2h0Ymx1ZSIsIA0KICAgICBib3JkZXIgPSAiYmxhY2siKQ0KDQojIENhbGN1bGF0ZSBSTVNFDQpybXNlIDwtIHNxcnQobWVhbigodF90ZXN0JHByb2ZpY2llbmN5IC0gdF90ZXN0JHByZWRpY3Rpb24pXjIpKQ0KY2F0KCJSb290IE1lYW4gU3F1YXJlZCBFcnJvciAoUk1TRSk6Iiwgcm1zZSwgIlxuIikNCg0KIyBDYWxjdWxhdGUgUi1zcXVhcmVkDQpTU1QgPC0gc3VtKCh0X3Rlc3QkcHJvZmljaWVuY3kgLSBtZWFuKHRfdGVzdCRwcm9maWNpZW5jeSkpXjIpDQpTU0UgPC0gc3VtKCh0X3Rlc3QkcHJvZmljaWVuY3kgLSB0X3Rlc3QkcHJlZGljdGlvbileMikNCnJfc3F1YXJlZCA8LSAxIC0gKFNTRSAvIFNTVCkNCmNhdCgiUi1zcXVhcmVkOiIsIHJfc3F1YXJlZCwgIlxuIikNCg0KYGBgDQoNCg0KYGBge3VuZGVmaW5lZCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh1c21hcCkNCg0KcGxvdF91c21hcChkYXRhID0gdCwgDQogICAgICAgICAgIHZhbHVlcyA9ICJwcm9maWNpZW5jeSIsIA0KICAgICAgICAgICBpbmNsdWRlID0gJ1dlc3QgVmlyZ2luaWEnKSArIA0KICBzY2FsZV9maWxsX2NvbnRpbnVvdXMobmFtZSA9ICJQcm9maWNpZW5jeSIsDQogICAgICAgICAgICAgICAgICAgICAgICBsb3cgPSAncmVkJywNCiAgICAgICAgICAgICAgICAgICAgICAgIGhpZ2ggPSAnYmx1ZScpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpICsNCiAgbGFicygnUHJvZmljaWVuY3knKQ0KDQoNCg0KYGBgDQoNCg0KIyMjIHBjYQ0KDQpgYGB7dW5kZWZpbmVkIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCnRfaW5ncmVkaWVudHMgPC0gdCAlPiUgc2VsZWN0KHdoZXJlKGlzLm51bWVyaWMpKSAlPiUgIHNlbGVjdChzdGFydHNfd2l0aCgnaSAnKSkNCg0KcGNhX3Jlc3VsdHMgPC0gcHJjb21wKHRfaW5ncmVkaWVudHMsIHNjYWxlID0gVFJVRSwgY2VudGVyID0gVFJVRSwgcmFuayA9IDIpDQoNCiMgU2hvdyBuZXcgY29tcG9uZW50cw0Kc3VtbWFyeShwY2FfcmVzdWx0cykNCnByaW50KHBjYV9yZXN1bHRzKQ0KDQpnZ3Bsb3QoZGF0YSA9IGFzLmRhdGEuZnJhbWUocGNhX3Jlc3VsdHMkcm90YXRpb24pLCANCiAgICAgICBhZXMoeCA9IFBDMSwgeSA9IFBDMiwgbGFiZWwgPSByb3duYW1lcyhwY2FfcmVzdWx0cyRyb3RhdGlvbikpKSArIA0KICBnZW9tX3RleHQoKSArIA0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQoNCmBgYHt1bmRlZmluZWQgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkocGxvdGx5KQ0KDQojIGFkZCB0aXRsZSBhbmQgY2F0ZWdvcnkgYmFjaw0KIyBhZGQgUEMxIGFuZCBQQzIgYmFjayB0byB0X2luZ3JlZGllbnRzIGFzIG5ldyB2YXJpYWJsZXMNCnRfaW5ncmVkaWVudHMgPC0gdF9pbmdyZWRpZW50cyAlPiUgIA0KICBiaW5kX2NvbHModGl0bGUgPSB0JHRpdGxlKSAlPiUgDQogIGJpbmRfY29scyhmaXJzdF9jYXRlZ29yeSA9IHQkZmlyc3RfY2F0ZWdvcnkpICU+JSANCiAgYmluZF9jb2xzKGFzLmRhdGEuZnJhbWUocGNhX3Jlc3VsdHMkeCkpDQoNCiMgUGljayBhIHJhbmRvbSBzYW1wbGUgb2YgMTAwMCBpdGVtcyBmb3IgdGhlIHBsb3QNCnNldC5zZWVkKDEyMykNCnRfaW5ncmVkaWVudHNfc2FtcGxlIDwtIHRfaW5ncmVkaWVudHNbc2FtcGxlKG5yb3codF9pbmdyZWRpZW50cyksIDEwMDApLF0NCg0KIyBQbG90IHNvbWUgaXRlbXMgd2l0aCBsYWJlbHMgDQpwbG90IDwtIGdncGxvdChkYXRhID0gdF9pbmdyZWRpZW50c19zYW1wbGUsLA0KICAgICAgIG1hcHBpbmcgPSBhZXMoIHggPSBqaXR0ZXIoUEMxKSwgeSA9IGppdHRlcihQQzIpLCB0ZXh0ID0gdGl0bGUsIGNvbG9yID0gZmlyc3RfY2F0ZWdvcnkpICkgKyANCiAgZ2VvbV9wb2ludCggKSArIA0KICB0aGVtZV9taW5pbWFsKCkgDQoNCg0KZ2dwbG90bHkocGxvdCwgdG9vbHRpcCA9ICd0ZXh0JykNCg0KYGBgDQoNCg0KDQojIyMgay1tZWFucw0KDQpgYGB7dW5kZWZpbmVkIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCnRfa21lYW5zIDwtIHQgJT4lIHNlbGVjdCh3aGVyZShpcy5udW1lcmljKSkgJT4lICBzZWxlY3Qoc3RhcnRzX3dpdGgoJ2kgJykpIA0KDQprcmVzdWx0IDwtIGttZWFucygNCiAgeCA9IHRfa21lYW5zLA0KICBjZW50ZXJzID0gMywNCiAgbnN0YXJ0ID0gMTANCikNCg0KIyBBZGQgdGhlIG5ldyBrbWVhbnMyIGNvbHVtbiwgdXNpbmcga3Jlc3VsdCdzIGNsdXN0ZXIgdmVjdG9yLg0KIyBVc2UgZmFjdG9yIHRvIHR1cm4gdGhlIGNsdXN0ZXIgZnJvbSBhIG51bWJlciB0byBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlLg0KdF9rbWVhbnMgPC0gdF9rbWVhbnMgJT4lIA0KICBtdXRhdGUoa21lYW5zID0gZmFjdG9yKGtyZXN1bHQkY2x1c3RlcikpICU+JSANCiAgYmluZF9jb2xzKHRpdGxlID0gdCR0aXRsZSkgJT4lIA0KICBiaW5kX2NvbHMoZmlyc3RfY2F0ZWdvcnkgPSB0JGZpcnN0X2NhdGVnb3J5KSAgJT4lIA0KICBiaW5kX2NvbHMoYmluZF9jb2xzKGFzLmRhdGEuZnJhbWUocGNhX3Jlc3VsdHMkeCkpKQ0KDQoNCiMgUGljayBhIHJhbmRvbSBzYW1wbGUgb2YgMTAwMCBpdGVtcyBmb3IgdGhlIHBsb3QNCnNldC5zZWVkKDEyMykNCnRfa21lYW5zX3NhbXBsZSA8LSB0X2ttZWFuc1tzYW1wbGUobnJvdyh0X2ttZWFucyksIDEwMDApLF0NCg0KIyBBZGQgdGhlIG5ldyBrbWVhbnMyIGNvbHVtbg0KcGxvdCA8LSBnZ3Bsb3QoKSArIA0KICBnZW9tX3BvaW50KA0KICAgIGRhdGEgPSB0X2ttZWFuc19zYW1wbGUsIA0KICAgIG1hcHBpbmcgPSBhZXMoIHggPSBqaXR0ZXIoUEMxKSwgeSA9IGppdHRlcihQQzIpLCB0ZXh0ID0gdGl0bGUsIGNvbG9yID0ga21lYW5zKSANCiAgKSArDQogIGxhYnMoIA0KICAgIHRpdGxlID0gJ0lyaXMgZGF0YXNldDogay1tZWFucyBjbHVzdGVyaW5nJywNCiAgICBzdWJ0aXRsZSA9IHBhc3RlKCdFcnJvcjonLCByb3VuZChrcmVzdWx0JHRvdC53aXRoaW5zcywyKSkNCiAgICApDQoNCmdncGxvdGx5KHBsb3QsIHRvb2x0aXAgPSAndGV4dCcpDQoNCmBgYA0KDQoNCg0KIyMjIERlY2lzaW9uIFRyZWUNCg0KYGBge3VuZGVmaW5lZCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHJwYXJ0KQ0KbGlicmFyeShycGFydC5wbG90KQ0KDQojc2FtcGxlX3ZlY3RvciA8LSBzYW1wbGUoeCA9IGMoMCwgMSksIHNpemU9bnJvdyh0KSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuNywgMC4zKSkNCg0KdF9kdCA8LSB0ICU+JSANCiAgc2VsZWN0KGZpcnN0X2NhdGVnb3J5LCBzdGFydHNfd2l0aCgnaSAnKSkgIA0KIyAgbXV0YXRlKHNhbXBsZSA9IHNhbXBsZV92ZWN0b3IpIA0KDQojI3RfZHRfdGVzdCA8LSBmaWx0ZXIodF9kdCwgc2FtcGxlID09IDApDQojdF9kdF90cmFpbiA8LSBmaWx0ZXIodF9kdCwgc2FtcGxlID09IDEpDQoNCm0gPC0gcnBhcnQoZm9ybXVsYSA9IGZpcnN0X2NhdGVnb3J5IH4gLiwNCiAgICAgICAgICAgZGF0YSA9IHRfZHQsDQogICAgICAgICAgIG1pbnNwbGl0ID0gMTAsDQogICAgICAgICAgIG1pbmJ1Y2tldCA9IDEwLA0KICAgICAgICAgICBtZXRob2QgPSAiY2xhc3MiKQ0KDQojIFNob3cgcmVzdWx0cyBvZiBtb2RlbA0KcnBhcnQucGxvdChtKQ0KDQpgYGANCg0KDQpgYGB7dW5kZWZpbmVkIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCiMgQ3JlYXRlIHRoZSBwcmVkaWN0ZWQgdmFsdWUgYW5kIGFkZCBpdCB0byBvdXIgdGliYmxlDQpwcmVkaWN0ZWQgPC0gcHJlZGljdChtLCB0X2R0LCB0eXBlID0gJ2NsYXNzJykNCnRfZHQgPC0gbXV0YXRlKCB0X2R0LCANCiAgICAgICAgICAgICBwcmVkaWN0ZWQgPSBwcmVkaWN0ZWQsDQogICAgICAgICAgICAgaXNfY29ycmVjdCA9IHByZWRpY3RlZCA9PWZpcnN0X2NhdGVnb3J5KQ0KDQojIFBlcmNlbnRhZ2UgY29ycmVjdA0KcHJpbnQobWVhbih0X2R0JGlzX2NvcnJlY3QpKQ0KDQojIFNob3cgYSBjb25mdXNpb24gbWF0cml4DQojIFByZWRpY3RlZCB2YWx1ZXMgYXJlIGluIHVwcGVyIGNhc2UuDQp0YWJsZShzdHJfdG9fdXBwZXIodF9kdCRwcmVkaWN0ZWQpLCB0X2R0JGZpcnN0X2NhdGVnb3J5KQ0KcHJvcC50YWJsZSh0YWJsZShzdHJfdG9fdXBwZXIodF9kdCRwcmVkaWN0ZWQpLCB0X2R0JGZpcnN0X2NhdGVnb3J5KSwgMikNCmBgYA0KDQoNCmBgYHt1bmRlZmluZWQgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KIyBSZWZhY3RvciBjb2RlIHRvIGV2YWx1YXRlIGEgTk4NCg0KZXZhbHVhdGVfbW9kZWwgPC0gZnVuY3Rpb24odF9kYXRhLCB2ZWN0b3Jfb3V0Y29tZXMsIHByaW50X291dGNvbWVzID0gRkFMU0UpIHsNCiAgICANCiAgdmVjdG9yX3ByZWRpY3RlZCA8LSBwcmVkaWN0KG4sIHRfZGF0YSkNCiAgdmVjdG9yX3ByZWRpY3RlZCA8LSByb3VuZCh2ZWN0b3JfcHJlZGljdGVkLCBkaWdpdHMgPSAwKQ0KICANCiAgYWNjdXJhY3kgPC0gbWVhbih2ZWN0b3JfcHJlZGljdGVkID09IHZlY3Rvcl9vdXRjb21lcykNCg0KICBpZihwcmludF9vdXRjb21lcykgew0KICAgIHByaW50KHRhYmxlKHZlY3Rvcl9wcmVkaWN0ZWQsIHZlY3Rvcl9vdXRjb21lcykpDQogIH0NCiAgDQogIHJldHVybihhY2N1cmFjeSkNCn0NCg0KcmVzdWx0cyA8LSBjKGV2YWx1YXRlX21vZGVsKHRfdHJhaW4sIHRfdHJhaW4kaXNfc3BhbSksDQogICAgICAgICAgICAgIGV2YWx1YXRlX21vZGVsKHRfdGVzdCwgdF90ZXN0JGlzX3NwYW0pKQ0KDQpwcmludChyZXN1bHRzKQ0KYGBgDQoNCiMjIyBDcm9zcy1mb2xkIHZhbGlkYXRpb24NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KIyBDcmVhdGUgYSBmdW5jdGlvbiBmb3IgY3JlYXRpbmcgYSBzYW1wbGUNCg0KY3JlYXRlX3NwbGl0IDwtIGZ1bmN0aW9uKHQsIHRyYWluX3NpemUgPSAwLjUpIHsNCiAgc2FtcGxlIDwtIHNhbXBsZShjKDEsIDApLCANCiAgICAgICAgICAgICAgICAgICBzaXplID0gbnJvdyh0KSwgDQogICAgICAgICAgICAgICAgICAgcmVwbGFjZSA9IFRSVUUsIA0KICAgICAgICAgICAgICAgICAgIHByb2IgPSBjKHRyYWluX3NpemUsIDEgLSB0cmFpbl9zaXplKSkNCiAgDQogIHRfdHJhaW4gPC0gdFtzYW1wbGUgPT0gMSwgXQ0KICB0X3Rlc3QgPC0gdFtzYW1wbGUgPT0gMCwgXQ0KICANCiAgcmV0dXJuKGxpc3QodF90cmFpbiA9IHRfdHJhaW4sIHRfdGVzdCA9IHRfdGVzdCkpDQp9DQoNCg0KIyBDcmVhdGUgdmVjdG9ycyB0byBzdG9yZSByZXN1bHRzDQp0cmFpbmluZ19yZXN1bHRzIDwtIGMoKQ0KdGVzdF9yZXN1bHRzIDwtIGMoKQ0KDQojIFJ1biB0aGUgbW9kZWwgbXVsdGlwbGUgdGltZXMgYW5kIHJlY29yZCB0aGUgcmVzdWx0cw0KZm9yIChpIGluIDE6NTApIHsNCiAgc3BsaXQgPC0gY3JlYXRlX3NwbGl0KHQsIDAuNzApDQogIA0KICBuIDwtIG5ldXJhbG5ldCggaXNfc3BhbSB+IC4sDQogICAgICAgICAgICAgICAgICBkYXRhID0gc3BsaXQkdF90cmFpbiwNCiAgICAgICAgICAgICAgICAgIGhpZGRlbiA9IDEsDQogICAgICAgICAgICAgICAgICBsaW5lYXIub3V0cHV0ID0gRkFMU0UNCiAgKQ0KICANCiAgdHJhaW5pbmdfcmVzdWx0cyA8LSBjKHRyYWluaW5nX3Jlc3VsdHMsIGV2YWx1YXRlX21vZGVsKHRfdHJhaW4sIHRfdHJhaW4kaXNfc3BhbSkpDQogIHRlc3RfcmVzdWx0cyA8LSBjKHRlc3RfcmVzdWx0cywgZXZhbHVhdGVfbW9kZWwodF90ZXN0LCB0X3Rlc3QkaXNfc3BhbSkpDQogIA0KfQ0KDQpwcmludCh0ZXN0X3Jlc3VsdHMpDQpoaXN0KHRlc3RfcmVzdWx0cykNCmBgYA0KDQoNCiMjIyBCb290c3RyYXBwaW5nDQoNCldlIGRvbid0IGhhdmUgZXF1YWwgbnVtYmVyIG9mIHNwYW0gYW5kIG5vbi1zcGFtIG1lc3NhZ2VzLiBXZSBjYW4gdXNlIGJvb3RzdHJhcHBpbmcgdG8gY3JlYXRlIGEgbW9yZSBiYWxhbmNlZCBkYXRhc2V0Lg0KDQpOb3RlIHRoYXQgd2UgcmUtdXNlZCB0aGUgZnVuY3Rpb24gZnJvbSBlYXJsaWVyIHRvIHJldHVybiBhIHRfdHJhaW4gYW5kDQphIHRfdGVzdCB1c2luZyBvdXIgYm9vdHN0cmFwcGVkIHNhbXBsZS4NCg0KYGBge3VuZGVmaW5lZCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQojIENyZWF0ZSBhIGZ1bmN0aW9uIGZvciBjcmVhdGluZyBhIHNhbXBsZQ0KY3JlYXRlX2Jvb3RzdHJhcHBlZF9iYWxhbmNlZF9zcGxpdCA8LSBmdW5jdGlvbih0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyX29mX3NhbXBsZXNfcGVyX2dyb3VwID0gMTAwMCkgew0KDQogICAgDQogICMgQ3JlYXRlIHRpYmJsZXMgb2YganVzdCBzcGFtIGFuZCBub24tc3BhbQ0KICB0X3NwYW0gPC0gdFt0JGlzX3NwYW0gPT0gMSwgXQ0KICB0X2hhbSA8LSB0W3QkaXNfc3BhbSA9PSAwLCBdDQogIA0KICANCiAgIyBCdWlsZCBzcGFtIHNhbXBsZSwgZ3JhYmJpbmcgaW5kZXhlcyB3aXRoIHJlcGxhY2VtZW50IHRvIHRoZSBsZW5ndGggb2YgdF9zcGFtDQogIHNhbXBsZV9zcGFtIDwtIHNhbXBsZSgxOm5yb3codF9zcGFtKSwNCiAgICAgICAgICAgICAgICAgICBzaXplID0gbnVtYmVyX29mX3NhbXBsZXNfcGVyX2dyb3VwLA0KICAgICAgICAgICAgICAgICAgIHJlcGxhY2UgPSBUUlVFKQ0KICB0X3NhbXBsZV9zcGFtIDwtIHRfc3BhbVtzYW1wbGVfc3BhbSwgXQ0KICB0X3Vuc2FtcGxlZF9zcGFtIDwtIHRfc3BhbVstc2FtcGxlX3NwYW0sIF0NCiAgDQogICMgVGVzdCB0byBtYWtlIHN1cmUgdGhhdCB3ZSBoYXZlIGF0IGxlYXN0IDEwMCB1bnNhbXBsZWQgaXRlbXMNCiAgaWYobnJvdyh0X3Vuc2FtcGxlZF9zcGFtKSA8IDEwMCkgew0KICAgIHN0b3AoIk5vdCBlbm91Z2ggdW5zYW1wbGVkIHNwYW0iKQ0KICB9DQogIA0KICANCiAgIyBidWlsZCBoYW0gc2FtcGxlDQogICAgc2FtcGxlX2hhbSA8LSBzYW1wbGUoMTpucm93KHRfaGFtKSwNCiAgICAgICAgICAgICAgICAgICBzaXplID0gbnVtYmVyX29mX3NhbXBsZXNfcGVyX2dyb3VwLA0KICAgICAgICAgICAgICAgICAgIHJlcGxhY2UgPSBUUlVFKQ0KICB0X3NhbXBsZV9oYW0gPC0gdF9oYW1bc2FtcGxlX2hhbSwgXQ0KICB0X3Vuc2FtcGxlZF9oYW0gPC0gdF9oYW1bLXNhbXBsZV9oYW0sIF0NCiAgDQogICMgVGVzdCB0byBtYWtlIHN1cmUgdGhhdCB3ZSBoYXZlIGF0IGxlYXN0IDEwMCB1bnNhbXBsZWQgaXRlbXMNCiAgaWYobnJvdyh0X3Vuc2FtcGxlZF9oYW0pIDwgMTAwKSB7DQogICAgc3RvcCgiTm90IGVub3VnaCB1bnNhbXBsZWQgaGFtIikNCiAgfQ0KICANCg0KICANCiAgIyBhcHBlbmQgdGhlIHR3byB0aWJibGVzIGludG8gYSBjb2hlc2l2ZSBzYW1wbGUNCiAgdF90cmFpbiA8LSBiaW5kX3Jvd3ModF9zYW1wbGVfc3BhbSwgdF9zYW1wbGVfaGFtKQ0KICB0X3Rlc3QgPC0gYmluZF9yb3dzKHRfdW5zYW1wbGVkX3NwYW0sIHRfdW5zYW1wbGVkX2hhbSkNCiAgDQogIHJldHVybihsaXN0KHRfdHJhaW4gPSB0X3RyYWluLCB0X3Rlc3QgPSB0X3Rlc3QpKQ0KfQ0KDQojIEV2YWx1YXRlIHRoZSBtb2RlbCB1c2luZyBib290c3RyYXBwaW5nDQoNCiMgQ3JlYXRlIHZlY3RvcnMgdG8gc3RvcmUgcmVzdWx0cw0KdHJhaW5pbmdfcmVzdWx0cyA8LSBjKCkNCnRlc3RfcmVzdWx0cyA8LSBjKCkNCg0KIyBSdW4gdGhlIG1vZGVsIG11bHRpcGxlIHRpbWVzIGFuZCByZWNvcmQgdGhlIHJlc3VsdHMNCmZvciAoaSBpbiAxOjEwKSB7DQogIHNwbGl0IDwtIGNyZWF0ZV9ib290c3RyYXBwZWRfYmFsYW5jZWRfc3BsaXQodCwgMjAwKQ0KICANCiAgbiA8LSBuZXVyYWxuZXQoIGlzX3NwYW0gfiAuLA0KICAgICAgICAgICAgICAgICAgZGF0YSA9IHNwbGl0JHRfdHJhaW4sDQogICAgICAgICAgICAgICAgICBoaWRkZW4gPSAxLA0KICAgICAgICAgICAgICAgICAgbGluZWFyLm91dHB1dCA9IEZBTFNFDQogICkNCiAgDQogIHRyYWluaW5nX3Jlc3VsdHMgPC0gYyh0cmFpbmluZ19yZXN1bHRzLCBldmFsdWF0ZV9tb2RlbCh0X3RyYWluLCB0X3RyYWluJGlzX3NwYW0pKQ0KICB0ZXN0X3Jlc3VsdHMgPC0gYyh0ZXN0X3Jlc3VsdHMsIGV2YWx1YXRlX21vZGVsKHRfdGVzdCwgdF90ZXN0JGlzX3NwYW0pKQ0KICANCn0NCg0KcHJpbnQodGVzdF9yZXN1bHRzKQ0KaGlzdCh0ZXN0X3Jlc3VsdHMpDQoNCmBgYA==