Module 2: Strategies to make your private data shareable

Research papers with shared data have fewer errors, those with shared data or shared code are cited more, and shared data are used in more publications.1,2 Research involving human subjects often has restrictions on data sharing due to the nature of the information being collected. Often research like this will only be approved if data files are password protected, encrypted, or otherwise stored securely and not available outside the project team.

If this is the case for your research, there are two possible strategies that could allow publicly sharing data without releasing private information:

Follow the instructions and examples below to de-identify or create synthetic data. To be safe, check with your human subjects review board first to make sure the strategy you choose meets the data sharing limitations for your project. Once you have de-identified or created synthetic data, share it publicly through GitHub by following the steps in our GitHub module.

How to de-identify data

De-identified data is data with personally identifiable information (PII) removed so that there is not enough information to identify any individual person. Professionals in public health and related fields are concerned with one type of PII, protected health information (PHI).

The U.S. Department of Health and Human Services (HHS) provides guidance on de-identifying data files. According to the HHS, there are two ways to de-identify data so that it does not included PHI: safe harbor and expert determination.

Safe harbor is the removal of specific identifying information from each record, while expert determination is the use of statistical methods to de-identify data such as finding and removing unique cases that are identifiable. Data that are de-identified by one of these two methods are no longer restricted for use or disclosure by the HIPAA Privacy Rule because they no longer contain PHI.

From the HHS website:

The safe harbor method requires removal from the data source of the following for the individual and their relatives, employers, or household members:

  1. Names
  2. Geographic regions smaller than a state
  3. Dates other than year
  4. Telephone numbers
  5. Fax numbers
  6. Email addresses
  7. Social security numbers
  8. Medical record numbers
  9. Health plan beneficiary numbers
  10. Account numbers
  11. Certificate/license numbers
  12. Vehicle identifiers and serial numbers, including license plate numbers
  13. Device identifiers and serial numbers
  14. Web universal resource locators (URLs)
  15. Internet protocol (IP) addresses
  16. Biometric identifiers, including finger and voice prints
  17. Full-face photographs and any comparable images
  18. Any other unique identifying number, characteristic, or code

The expert determination method requires that information in the data cannot be used to identify individuals by someone with skills and knowledge of common analytic methods and access to other reasonably available data (e.g., voter registration records). A more detailed description of this method is available on the HHS website.

We strongly recommend visiting the HHS page before sharing your de-identified data to ensure you meet either the safe harbor or the expert determination requirements for de-identification. Several websites offer ideas and training that might also be useful if you are working on this:

We also encourage you to check with your Institutional Review Board before making de-identified data public to ensure you are meeting any requirements to protect human subjects.

How to create synthetic data

When de-identification is difficult, impossible, or not ideal, creating synthetic data that keeps important variables and relationships from the original data may be an option. Similar in concept to imputation, creating synthetic data entails replacing some or all observations using appropriate probability distributions to ensure important properties and relationships are maintained.3

Please note that the examples shown below are fairly simple and do not include maintaining complex relationships among variables. When creating synthetic data for distribution, review the resources listed below and thoroughly test the synthetic data to make sure it maintains logical and relevant properties including complex relationships important to the research.

R

As one example, the synthpop package in R can be used to create a synthetic data set. Using the publicly available National Health and Nutrition Examination Survey (NHANES), here is an example of creating a synthetic data set in R. Note that you will choose a seed value to enter into the code; the syn procedure will use this seed as a starting point for the simulations that generate the data. Using a set seed rather than permitting the algorithm to choose a random number ensures that the synthetic data source can be reproduced by others.

# bring in the original data name it nhanes
# this is the 2011-2012 NHANES data available from the 
# Centers for disease control and prevention
library(RNHANES)
nhanes <- nhanes_load_data("AUQ_G", "2011-2012", demographics = TRUE)

# make a smaller version of nhanes with the variables of interest
vars <- c("RIAGENDR", "RIDAGEYR", "RIDRETH1")
nhanes.small <- nhanes[, vars]

# open the synthpop library (install first)
library(synthpop)

# create nhanes.synth with default method
# use seed value for reproducibility
nhanes.synth.list <- syn(nhanes.small, seed=123456)
Synthesis
-----------
 RIAGENDR RIDAGEYR RIDRETH1
nhanes.synth <- nhanes.synth.list$syn

# example of comparing the original and synthetic data sets
# add labels to gender and ethnicity variables
# see codebook if needed 
nhanes.small$RIAGENDR <- factor(nhanes.small$RIAGENDR,
                                levels = c(1, 2),
                                labels = c("Male", "Female"))
nhanes.small$RIDRETH1 <- factor(nhanes.small$RIDRETH1,
                                levels = c(1, 2, 3, 4, 5),
                                labels = c("Mexican American", "Other Hispanic",
                                           "Non-Hispanic White", "Non-Hispanic Black",
                                           "Other Race - Including Multi-Racial"))
nhanes.synth$RIAGENDR <- factor(nhanes.synth$RIAGENDR,
                                levels = c(1, 2),
                                labels = c("Male", "Female"))
nhanes.synth$RIDRETH1 <- factor(nhanes.synth$RIDRETH1,
                                levels = c(1, 2, 3, 4, 5),
                                labels = c("Mexican American", "Other Hispanic",
                                           "Non-Hispanic White", "Non-Hispanic Black",
                                           "Other Race - Including Multi-Racial"))

# original
table(nhanes.small$RIDRETH1, nhanes.small$RIAGENDR)
                                     
                                      Male Female
  Mexican American                     645    619
  Other Hispanic                       496    536
  Non-Hispanic White                  1449   1411
  Non-Hispanic Black                  1273   1315
  Other Race - Including Multi-Racial  800    820
# synth
table(nhanes.synth$RIDRETH1, nhanes.synth$RIAGENDR)
                                     
                                      Male Female
  Mexican American                     663    606
  Other Hispanic                       498    550
  Non-Hispanic White                  1468   1403
  Non-Hispanic Black                  1229   1326
  Other Race - Including Multi-Racial  793    828

The top table shows the original data frequencies for each category of race/ethnicity across the male and female sex categories. The bottom shows the same variables in the synthetic data set. While the two data sets are not identical, they are similar.

SAS (using R to create)

There are macros for creating synthetic data from SAS data sources, however, they are difficult to use. Likewise, the synth package for Stata (resource below) will create synthetic treatment observations, but the process is not straightforward for synthesizing datasets. The R synthpop package is one alternative since R can easily open, manipulate, and export SAS or Stata files. Here are the instructions from the R example above but with the SAS version of the data source as input and a SAS or Stata data file export command added:

# bring in the original data name it brfss
# this is the 2016 BRFSS data available from the 
# Centers for disease control and prevention
# in SAS transport format

# install haven if it is not installed
# open the haven library for importing xpt files
library(haven) 

# make a temporary object that holds a zip file
brfss_url <- tempfile(fileext = ".zip") 

# download the zip file
# put the zip file in the temporary file
download.file("https://www.cdc.gov/brfss/annual_data/2016/files/LLCP2016XPT.zip", brfss_url)

# unzip the file and read it in using read_xpt
brfss <- read_xpt(brfss_url) 

# make a smaller version of brfss with the variables of interest
vars <- c("SEX", "MARITAL", "EDUCA")
brfss.small <- brfss[, vars]

# open the synthpop library (install first)
library(synthpop)

# create brfss.synth with default method
# use seed value for reproducibility
brfss.synth.list <- syn(brfss.small, seed=123456)
Synthesis
-----------
 SEX MARITAL EDUCA
brfss.synth <- brfss.synth.list$syn

# example of comparing the original and synthetic data sets
# add labels to gender and ethnicity variables
# see codebook if needed 
brfss.small$SEX <- factor(brfss.small$SEX,
                                levels = c(1, 2, 9),
                                labels = c("Male", "Female", "Refused"))
brfss.small$MARITAL <- factor(brfss.small$MARITAL,
                                levels = c(1, 2, 3, 4, 5, 6, 9),
                                labels = c("Married", "Divorced",
                                           "Widowed", "Separated",
                                           "Never married", "A member of an unmarried couple",
                                           "Refused"))
brfss.synth$SEX <- factor(brfss.synth$SEX,
                                levels = c(1, 2, 9),
                                labels = c("Male", "Female", "Refused"))
brfss.synth$MARITAL <- factor(brfss.synth$MARITAL,
                                levels = c(1, 2, 3, 4, 5, 6, 9),
                                labels = c("Married", "Divorced",
                                           "Widowed", "Separated",
                                           "Never married", "A member of an unmarried couple",
                                           "Refused"))

# original
table(brfss.small$SEX, brfss.small$MARITAL)
         
          Married Divorced Widowed Separated Never married
  Male     119350    26170   12884      4051         39602
  Female   134177    40213   48729      6103         36719
  Refused      25        4       4         0            14
         
          A member of an unmarried couple Refused
  Male                               7139    1409
  Female                             7795    1890
  Refused                               3      11
# synth
table(brfss.synth$SEX, brfss.synth$MARITAL)
         
          Married Divorced Widowed Separated Never married
  Male     118986    26409   12963      3981         39522
  Female   134286    40382   48755      6122         36620
  Refused      26        6       6         0            13
         
          A member of an unmarried couple Refused
  Male                               7232    1425
  Female                             7720    1827
  Refused                               3       4

The tables show that the synthetic data is not exactly the same as the original data, but it is close. Once the synthetic data are ready, use the haven package to write the new data to a SAS file:

# export to SAS file
# uses haven package opened earlier
# add path to write the data to inside the quote marks
write_sas(brfss.synth, path = "")

# export to Stata (*.dta) file
# uses haven package opened earlier
# add path to name and specify where to write the dataset to inside the quote marks
write_dta(brfss.synth, path = "")

SPSS

In SPSS, the SIMPLAN and SIMRUN functions can create synthetic data based on a real dataset. Use the small NHANES data created in the R example above as an example.

# Load haven library, which allows saving files to SPSS format
library(haven)
write_sav(nhanes.small, "C:/Your/Directory/NHANESorig.sav")

Run the following in an SPSS syntax editor:

* Open NHANES data saved out from R.
GET FILE = 'C:\Your\Directory\NHANESorig.sav'.
DATASET NAME orig.
DATASET ACTIVATE orig.

* Add variable labels.
VARIABLE LABELS
RIAGENDR 'Gender'
RIDAGEYR 'Age'
RIDRETH1 'Ethnicity'.

* Create simulation plan based on original NHANES data.
* Set boundaries for age to range for real data.
* N = 9364, so set that as maxcases.
SIMPLAN CREATE
/SIMINPUT INPUT = RIAGENDR RIDRETH1
/SIMINPUT INPUT = RIDAGEYR MINVAL = 1 MAXVAL = 80
/CONTINGENCY MULTIWAY = YES
/STOPCRITERIA MAXCASES = 9364
/PLAN FILE = 'C:\Your\Directory\NHANES.splan'.

* Run the simulation.
SIMRUN
/PLAN FILE = 'C:\Your\Directory\NHANES.splan'
/CRITERIA REPRESULTS = TRUE SEED = 10
/OUTFILE FILE = 'C:\Your\Directory\NHANESsynth.sav'.

* Open simulated file and take a look.
GET FILE = 'C:\Your\Directory\NHANESsynth.sav'.
DATASET NAME synth.
DATASET ACTIVATE synth.

Default procedures for the SIMPLAN command will automatically determine the best-fitting distributions for each variable included in the SIMINPUT subcommands, retain correlations between scale variables, and stop after 100,000 cases have been generated. A few modifications have been made for this data set:

  1. Simulated values for age were beyond the human lifespan with default settings, so minimum and maximum values were set based on the age range in the real data. SPSS might print a warning, but it does produce the desired result.
  2. SPSS does not automatically retain relationships between categorical variables. Specifying the CONTINGENCY subcommand will make that happen.
  3. Given the large influence that sample size has on significance testing, manually limiting the maximum number of cases to the size of the real data is recommended using the STOPCRITERIA subcommand.

The SIMRUN command uses the plan created with SIMPLAN, applies it to the original data, and creates the simulated data set. To ensure the same result each time the plan is applied, specify the CRITERIA subcommand as shown with the same seed.

Go to Help --> Topics and search for SIMPLAN and SIMRUN for more specification details and options.

* Compare original and synthetic data on ethnicity/gender.
DATASET ACTIVATE orig.
CROSSTABS
/TABLES=RIDRETH1 BY RIAGENDR
/CELLS=COUNT.
DATASET ACTIVATE synth.
CROSSTABS
/TABLES=RIDRETH1 BY RIAGENDR
/CELLS=COUNT.

Original data:

Simulated data:

While not exact, the simulated data show patterns similar to the original data.

Resources to use for creation of synthetic data in R, SPSS, Stata, and SAS are included in the Resources section below.

Resources

References

1. McKiernan EC, Bourne PE, Brown CT, et al. How open science helps researchers succeed. eLife. 2016;5:e16800.

2. Piwowar HA, Day RS, Fridsma DB. Sharing detailed research data is associated with increased citation rate. PloS One. 2007;2(3):e308.

3. Shepherd BE, Peratikos MB, Rebeiro PF, Duda SN, McGowan CC. A pragmatic approach for reproducible research with sensitive data. Am J Epidemiol. 2017;186(4):387-392.

LS0tDQp0aXRsZTogIk1vZHVsZSAyIg0Kb3V0cHV0Og0KICAgDQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIGNvZGVfZm9sZGluZzogbm9uZQ0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBkZl9wcmludDogdGliYmxlDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IA0KICAgICAgY29sbGFwc2VkOiB0cnVlDQogICAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQogICAgaW5jbHVkZXM6DQogICAgICAgYWZ0ZXJfYm9keTogRzpcXENQSFNTXFxPcGVuU2NpZW5jZVxcTW9kdWxlc1xcU3R5bGVzaGVldHNcXEZvb3QuaHRtbA0KYmlibGlvZ3JhcGh5OiBHOi9DUEhTUy9PcGVuU2NpZW5jZS9Xcml0ZVVwcy9haW0xU3VydmV5UGFwZXIvUmVwcm9TdXJ2ZXlQYXBlcl8wMjEyMjAxOC5iaWJ0ZXgNCmNzbDogRzovQ1BIU1MvT3BlblNjaWVuY2UvV3JpdGVVcHMvYWltMVN1cnZleVBhcGVyL2FtZXJpY2FuLW1lZGljYWwtYXNzb2NpYXRpb24tbm8tdXJsLkNTTA0KLS0tDQo8aGVhZHsjdG9wfT4NCg0KPHNjcmlwdCBzcmMgPSAiRzpcXENQSFNTXFxPcGVuU2NpZW5jZVxcTW9kdWxlc1xcU3R5bGVzaGVldHNcXE1haW4uanMiPjwvc2NyaXB0Pg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiB0eXBlPSJ0ZXh0L2NzcyIgaHJlZj0iRzpcXENQSFNTXFxPcGVuU2NpZW5jZVxcTW9kdWxlc1xcU3R5bGVzaGVldHNcXE1haW5TdHlsZS5jc3MiPg0KYGBge3IsIGVjaG89RkFMU0V9DQpodG1sdG9vbHM6OmluY2x1ZGVIVE1MKCJHOlxcQ1BIU1NcXE9wZW5TY2llbmNlXFxNb2R1bGVzXFxTdHlsZXNoZWV0c1xcTmF2YmFyLmh0bWwiKQ0KYGBgDQo8aW1nIGNsYXNzPSJsb2dvIiBzcmMgPSAiRzpcXENQSFNTXFxPcGVuU2NpZW5jZVxcTW9kdWxlc1xcYzJzLWxvZ28tZm9yLW1vZHVsZXMuanBnIj4NCiAgIA0KPC9oZWFkPg0KDQpgYGB7ciBzZXR1cE9wdHMsIGVjaG89RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTgsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UpDQoNCmBgYA0KI01vZHVsZSAyOiBTdHJhdGVnaWVzIHRvIG1ha2UgeW91ciBwcml2YXRlIGRhdGEgc2hhcmVhYmxlIA0KDQpSZXNlYXJjaCBwYXBlcnMgd2l0aCBzaGFyZWQgZGF0YSBoYXZlICoqZmV3ZXIgZXJyb3JzKiosIHRob3NlIHdpdGggc2hhcmVkIGRhdGEgb3Igc2hhcmVkIGNvZGUgYXJlICoqY2l0ZWQgbW9yZSoqLCBhbmQgc2hhcmVkIGRhdGEgYXJlICoqdXNlZCBpbiBtb3JlIHB1YmxpY2F0aW9ucyoqLltAUmVmV29ya3M6MjE4MTtAUmVmV29ya3M6MjMxNF0gUmVzZWFyY2ggaW52b2x2aW5nIGh1bWFuIHN1YmplY3RzIG9mdGVuIGhhcyByZXN0cmljdGlvbnMgb24gZGF0YSBzaGFyaW5nIGR1ZSB0byB0aGUgbmF0dXJlIG9mIHRoZSBpbmZvcm1hdGlvbiBiZWluZyBjb2xsZWN0ZWQuIE9mdGVuIHJlc2VhcmNoIGxpa2UgdGhpcyB3aWxsIG9ubHkgYmUgYXBwcm92ZWQgaWYgZGF0YSBmaWxlcyBhcmUgcGFzc3dvcmQgcHJvdGVjdGVkLCBlbmNyeXB0ZWQsIG9yIG90aGVyd2lzZSBzdG9yZWQgc2VjdXJlbHkgYW5kIG5vdCBhdmFpbGFibGUgb3V0c2lkZSB0aGUgcHJvamVjdCB0ZWFtLiANCg0KSWYgdGhpcyBpcyB0aGUgY2FzZSBmb3IgeW91ciByZXNlYXJjaCwgdGhlcmUgYXJlIHR3byBwb3NzaWJsZSBzdHJhdGVnaWVzIHRoYXQgY291bGQgYWxsb3cgcHVibGljbHkgc2hhcmluZyBkYXRhIHdpdGhvdXQgcmVsZWFzaW5nIHByaXZhdGUgaW5mb3JtYXRpb246DQoNCiogW0RlLWlkZW50aWZ5IGRhdGEgaW4gd2hvbGUgb3IgaW4gcGFydF0oI2RlaWRlbnRpZnkpDQoqIFtDcmVhdGUgc3ludGhldGljIGRhdGEgbWltaWNraW5nIHRoZSBvcmlnaW5hbF0oI3N5bnRoZXRpYykNCg0KRm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgYW5kIGV4YW1wbGVzIGJlbG93IHRvIGRlLWlkZW50aWZ5IG9yIGNyZWF0ZSBzeW50aGV0aWMgZGF0YS4gVG8gYmUgc2FmZSwgY2hlY2sgd2l0aCB5b3VyIGh1bWFuIHN1YmplY3RzIHJldmlldyBib2FyZCBmaXJzdCB0byBtYWtlIHN1cmUgdGhlIHN0cmF0ZWd5IHlvdSBjaG9vc2UgbWVldHMgdGhlIGRhdGEgc2hhcmluZyBsaW1pdGF0aW9ucyBmb3IgeW91ciBwcm9qZWN0LiBPbmNlIHlvdSBoYXZlIGRlLWlkZW50aWZpZWQgb3IgY3JlYXRlZCBzeW50aGV0aWMgZGF0YSwgc2hhcmUgaXQgcHVibGljbHkgdGhyb3VnaCBHaXRIdWIgYnkgZm9sbG93aW5nIHRoZSBzdGVwcyBpbiBvdXIgW0dpdEh1YiBtb2R1bGVdKE1vZDVHaXRIdWIuaHRtbCkuIA0KDQojIyBIb3cgdG8gZGUtaWRlbnRpZnkgZGF0YSB7I2RlaWRlbnRpZnl9DQoNCioqRGUtaWRlbnRpZmllZCBkYXRhKiogaXMgZGF0YSB3aXRoIHBlcnNvbmFsbHkgaWRlbnRpZmlhYmxlIGluZm9ybWF0aW9uIChQSUkpIHJlbW92ZWQgc28gdGhhdCB0aGVyZSBpcyBub3QgZW5vdWdoIGluZm9ybWF0aW9uIHRvIGlkZW50aWZ5IGFueSBpbmRpdmlkdWFsIHBlcnNvbi4gUHJvZmVzc2lvbmFscyBpbiBwdWJsaWMgaGVhbHRoIGFuZCByZWxhdGVkIGZpZWxkcyBhcmUgY29uY2VybmVkIHdpdGggb25lIHR5cGUgb2YgUElJLCAqKnByb3RlY3RlZCBoZWFsdGggaW5mb3JtYXRpb24gKFBISSkuKiogDQoNClRoZSBVLlMuIERlcGFydG1lbnQgb2YgSGVhbHRoIGFuZCBIdW1hbiBTZXJ2aWNlcyAoSEhTKSBwcm92aWRlcyBbZ3VpZGFuY2Ugb24gZGUtaWRlbnRpZnlpbmcgZGF0YSBmaWxlc10oaHR0cHM6Ly93d3cuaGhzLmdvdi9oaXBhYS9mb3ItcHJvZmVzc2lvbmFscy9wcml2YWN5L3NwZWNpYWwtdG9waWNzL2RlLWlkZW50aWZpY2F0aW9uLykuIEFjY29yZGluZyB0byB0aGUgSEhTLCB0aGVyZSBhcmUgdHdvIHdheXMgdG8gZGUtaWRlbnRpZnkgZGF0YSBzbyB0aGF0IGl0IGRvZXMgbm90IGluY2x1ZGVkIFBISTogKipzYWZlIGhhcmJvcioqIGFuZCAqKmV4cGVydCBkZXRlcm1pbmF0aW9uKiouIA0KDQoqKlNhZmUgaGFyYm9yKiogaXMgdGhlIHJlbW92YWwgb2Ygc3BlY2lmaWMgaWRlbnRpZnlpbmcgaW5mb3JtYXRpb24gZnJvbSBlYWNoIHJlY29yZCwgd2hpbGUgKipleHBlcnQgZGV0ZXJtaW5hdGlvbioqIGlzIHRoZSB1c2Ugb2Ygc3RhdGlzdGljYWwgbWV0aG9kcyB0byBkZS1pZGVudGlmeSBkYXRhIHN1Y2ggYXMgZmluZGluZyBhbmQgcmVtb3ZpbmcgdW5pcXVlIGNhc2VzIHRoYXQgYXJlIGlkZW50aWZpYWJsZS4gW0RhdGEgdGhhdCBhcmUgZGUtaWRlbnRpZmllZCBieSBvbmUgb2YgdGhlc2UgdHdvIG1ldGhvZHMgYXJlIG5vIGxvbmdlciByZXN0cmljdGVkIGZvciB1c2Ugb3IgZGlzY2xvc3VyZSBieSB0aGUgSElQQUEgUHJpdmFjeSBSdWxlIGJlY2F1c2UgdGhleSBubyBsb25nZXIgY29udGFpbiBQSEldKGh0dHBzOi8vd3d3Lmhocy5nb3YvaGlwYWEvZm9yLXByb2Zlc3Npb25hbHMvcHJpdmFjeS9zcGVjaWFsLXRvcGljcy9kZS1pZGVudGlmaWNhdGlvbi8jc3RhbmRhcmQpLg0KDQpGcm9tIHRoZSBbSEhTIHdlYnNpdGVdKGh0dHBzOi8vd3d3Lmhocy5nb3YvaGlwYWEvZm9yLXByb2Zlc3Npb25hbHMvcHJpdmFjeS9zcGVjaWFsLXRvcGljcy9kZS1pZGVudGlmaWNhdGlvbi9pbmRleC5odG1sKTogPEJSPg0KDQoNCiFbXShodHRwczovL3d3dy5oaHMuZ292L3NpdGVzL2RlZmF1bHQvZmlsZXMvb2NyL2ltYWdlcy9kZWlkZW50aWZpY2F0aW9uX2ZpZ18xLmpwZykNCg0KVGhlICoqc2FmZSBoYXJib3IqKiBtZXRob2QgcmVxdWlyZXMgcmVtb3ZhbCBmcm9tIHRoZSBkYXRhIHNvdXJjZSBvZiB0aGUgZm9sbG93aW5nIGZvciB0aGUgaW5kaXZpZHVhbCAqYW5kIHRoZWlyIHJlbGF0aXZlcywgZW1wbG95ZXJzLCBvciBob3VzZWhvbGQgbWVtYmVycyo6DQoNCmEuIE5hbWVzIA0KYi4gR2VvZ3JhcGhpYyByZWdpb25zIHNtYWxsZXIgdGhhbiBhIHN0YXRlIA0KYy4gRGF0ZXMgb3RoZXIgdGhhbiB5ZWFyDQpkLiBUZWxlcGhvbmUgbnVtYmVycw0KZS4gRmF4IG51bWJlcnMgDQpmLiBFbWFpbCBhZGRyZXNzZXMNCmcuIFNvY2lhbCBzZWN1cml0eSBudW1iZXJzDQpoLiBNZWRpY2FsIHJlY29yZCBudW1iZXJzDQppLiBIZWFsdGggcGxhbiBiZW5lZmljaWFyeSBudW1iZXJzDQpqLiBBY2NvdW50IG51bWJlcnMNCmsuIENlcnRpZmljYXRlL2xpY2Vuc2UgbnVtYmVycw0KbC4gVmVoaWNsZSBpZGVudGlmaWVycyBhbmQgc2VyaWFsIG51bWJlcnMsIGluY2x1ZGluZyBsaWNlbnNlIHBsYXRlIG51bWJlcnMNCm0uIERldmljZSBpZGVudGlmaWVycyBhbmQgc2VyaWFsIG51bWJlcnMNCm4uIFdlYiB1bml2ZXJzYWwgcmVzb3VyY2UgbG9jYXRvcnMgKFVSTHMpDQpvLiBJbnRlcm5ldCBwcm90b2NvbCAoSVApIGFkZHJlc3Nlcw0KcC4gQmlvbWV0cmljIGlkZW50aWZpZXJzLCBpbmNsdWRpbmcgZmluZ2VyIGFuZCB2b2ljZSBwcmludHMNCnEuIEZ1bGwtZmFjZSBwaG90b2dyYXBocyBhbmQgYW55IGNvbXBhcmFibGUgaW1hZ2VzDQpyLiBBbnkgb3RoZXIgdW5pcXVlIGlkZW50aWZ5aW5nIG51bWJlciwgY2hhcmFjdGVyaXN0aWMsIG9yIGNvZGUNCg0KVGhlICoqZXhwZXJ0IGRldGVybWluYXRpb24qKiBtZXRob2QgcmVxdWlyZXMgdGhhdCBpbmZvcm1hdGlvbiBpbiB0aGUgZGF0YSBjYW5ub3QgYmUgdXNlZCB0byBpZGVudGlmeSBpbmRpdmlkdWFscyBieSBzb21lb25lIHdpdGggc2tpbGxzIGFuZCBrbm93bGVkZ2Ugb2YgY29tbW9uIGFuYWx5dGljIG1ldGhvZHMgYW5kIGFjY2VzcyB0byBvdGhlciByZWFzb25hYmx5IGF2YWlsYWJsZSBkYXRhIChlLmcuLCB2b3RlciByZWdpc3RyYXRpb24gcmVjb3JkcykuIEEgbW9yZSBkZXRhaWxlZCBkZXNjcmlwdGlvbiBvZiB0aGlzIG1ldGhvZCBpcyBhdmFpbGFibGUgb24gdGhlIFtISFMgd2Vic2l0ZV0oaHR0cHM6Ly93d3cuaGhzLmdvdi9oaXBhYS9mb3ItcHJvZmVzc2lvbmFscy9wcml2YWN5L3NwZWNpYWwtdG9waWNzL2RlLWlkZW50aWZpY2F0aW9uLyNzdGFuZGFyZCkuDQoNCldlIHN0cm9uZ2x5IHJlY29tbWVuZCB2aXNpdGluZyB0aGUgW0hIUyBwYWdlXShodHRwczovL3d3dy5oaHMuZ292L2hpcGFhL2Zvci1wcm9mZXNzaW9uYWxzL3ByaXZhY3kvc3BlY2lhbC10b3BpY3MvZGUtaWRlbnRpZmljYXRpb24vI3N0YW5kYXJkKSBiZWZvcmUgc2hhcmluZyB5b3VyIGRlLWlkZW50aWZpZWQgZGF0YSB0byBlbnN1cmUgeW91IG1lZXQgZWl0aGVyIHRoZSAqKnNhZmUgaGFyYm9yKiogb3IgdGhlICoqZXhwZXJ0IGRldGVybWluYXRpb24qKiByZXF1aXJlbWVudHMgZm9yIGRlLWlkZW50aWZpY2F0aW9uLiBTZXZlcmFsIHdlYnNpdGVzIG9mZmVyIGlkZWFzIGFuZCB0cmFpbmluZyB0aGF0IG1pZ2h0IGFsc28gYmUgdXNlZnVsIGlmIHlvdSBhcmUgd29ya2luZyBvbiB0aGlzOiANCg0KKiBbSElQQUEgam91cm5hbCBhcnRpY2xlIG9uIGRlLWlkZW50aWZpY2F0aW9uXShodHRwczovL3d3dy5oaXBhYWpvdXJuYWwuY29tL2RlLWlkZW50aWZpY2F0aW9uLXByb3RlY3RlZC1oZWFsdGgtaW5mb3JtYXRpb24vKSANCiogW0NvbmNlcHRzIGFuZCBtZXRob2RzIGZvciBkZS1pZGVudGlmeWluZyBjbGluaWNhbCB0cmlhbCBkYXRhXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L2Jvb2tzL05CSzI4NTk5NC8pIA0KKiBbRGUtaWRlbnRpZmljYXRpb24gb2YgcGVyc29uYWwgaW5mb3JtYXRpb25dKGh0dHBzOi8vbnZscHVicy5uaXN0Lmdvdi9uaXN0cHVicy9pci8yMDE1L25pc3QuaXIuODA1My5wZGYpIA0KKiBbU0FTIHByaW1lciBvbiBkYXRhIHByaXZhY3ldKGh0dHBzOi8vc3VwcG9ydC5zYXMuY29tL3Jlc291cmNlcy9wYXBlcnMvcHJvY2VlZGluZ3MxNS8xODg0LTIwMTUucGRmKSANCg0KV2UgYWxzbyBlbmNvdXJhZ2UgeW91IHRvIGNoZWNrIHdpdGggeW91ciBJbnN0aXR1dGlvbmFsIFJldmlldyBCb2FyZCBiZWZvcmUgbWFraW5nIGRlLWlkZW50aWZpZWQgZGF0YSBwdWJsaWMgdG8gZW5zdXJlIHlvdSBhcmUgbWVldGluZyBhbnkgcmVxdWlyZW1lbnRzIHRvIHByb3RlY3QgaHVtYW4gc3ViamVjdHMuIA0KDQojIyBIb3cgdG8gY3JlYXRlIHN5bnRoZXRpYyBkYXRhIHsjc3ludGhldGljfQ0KDQpXaGVuIGRlLWlkZW50aWZpY2F0aW9uIGlzIGRpZmZpY3VsdCwgaW1wb3NzaWJsZSwgb3Igbm90IGlkZWFsLCBjcmVhdGluZyBzeW50aGV0aWMgZGF0YSB0aGF0IGtlZXBzIGltcG9ydGFudCB2YXJpYWJsZXMgYW5kIHJlbGF0aW9uc2hpcHMgZnJvbSB0aGUgb3JpZ2luYWwgZGF0YSBtYXkgYmUgYW4gb3B0aW9uLiBTaW1pbGFyIGluIGNvbmNlcHQgdG8gaW1wdXRhdGlvbiwgY3JlYXRpbmcgc3ludGhldGljIGRhdGEgZW50YWlscyByZXBsYWNpbmcgc29tZSBvciBhbGwgb2JzZXJ2YXRpb25zIHVzaW5nIGFwcHJvcHJpYXRlIHByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbnMgdG8gZW5zdXJlIGltcG9ydGFudCBwcm9wZXJ0aWVzIGFuZCByZWxhdGlvbnNoaXBzIGFyZSBtYWludGFpbmVkLiBbQFJlZldvcmtzOjEyMV0NCg0KKipQbGVhc2Ugbm90ZSoqIHRoYXQgdGhlIGV4YW1wbGVzIHNob3duIGJlbG93IGFyZSBmYWlybHkgc2ltcGxlIGFuZCBkbyBub3QgaW5jbHVkZSBtYWludGFpbmluZyBjb21wbGV4IHJlbGF0aW9uc2hpcHMgYW1vbmcgdmFyaWFibGVzLiBXaGVuIGNyZWF0aW5nIHN5bnRoZXRpYyBkYXRhIGZvciBkaXN0cmlidXRpb24sIHJldmlldyB0aGUgW3Jlc291cmNlc10oI3Jlc28pIGxpc3RlZCBiZWxvdyBhbmQgdGhvcm91Z2hseSB0ZXN0IHRoZSBzeW50aGV0aWMgZGF0YSB0byBtYWtlIHN1cmUgaXQgbWFpbnRhaW5zIGxvZ2ljYWwgYW5kIHJlbGV2YW50IHByb3BlcnRpZXMgaW5jbHVkaW5nIGNvbXBsZXggcmVsYXRpb25zaGlwcyBpbXBvcnRhbnQgdG8gdGhlIHJlc2VhcmNoLiANCg0KIyMjIFINCg0KQXMgb25lIGV4YW1wbGUsIHRoZSBgc3ludGhwb3BgIHBhY2thZ2UgaW4gUiBjYW4gYmUgdXNlZCB0byBjcmVhdGUgYSBzeW50aGV0aWMgZGF0YSBzZXQuIFVzaW5nIHRoZSBwdWJsaWNseSBhdmFpbGFibGUgTmF0aW9uYWwgSGVhbHRoIGFuZCBOdXRyaXRpb24gRXhhbWluYXRpb24gU3VydmV5IChOSEFORVMpLCBoZXJlIGlzIGFuIGV4YW1wbGUgb2YgY3JlYXRpbmcgYSBzeW50aGV0aWMgZGF0YSBzZXQgaW4gUi4gTm90ZSB0aGF0IHlvdSB3aWxsIGNob29zZSBhIGBzZWVkYCB2YWx1ZSB0byBlbnRlciBpbnRvIHRoZSBjb2RlOyB0aGUgYHN5bmAgcHJvY2VkdXJlIHdpbGwgdXNlIHRoaXMgc2VlZCBhcyBhIHN0YXJ0aW5nIHBvaW50IGZvciB0aGUgc2ltdWxhdGlvbnMgdGhhdCBnZW5lcmF0ZSB0aGUgZGF0YS4gVXNpbmcgYSBzZXQgc2VlZCByYXRoZXIgdGhhbiBwZXJtaXR0aW5nIHRoZSBhbGdvcml0aG0gdG8gY2hvb3NlIGEgcmFuZG9tIG51bWJlciBlbnN1cmVzIHRoYXQgdGhlIHN5bnRoZXRpYyBkYXRhIHNvdXJjZSBjYW4gYmUgcmVwcm9kdWNlZCBieSBvdGhlcnMuIA0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCiMgYnJpbmcgaW4gdGhlIG9yaWdpbmFsIGRhdGEgbmFtZSBpdCBuaGFuZXMNCiMgdGhpcyBpcyB0aGUgMjAxMS0yMDEyIE5IQU5FUyBkYXRhIGF2YWlsYWJsZSBmcm9tIHRoZSANCiMgQ2VudGVycyBmb3IgZGlzZWFzZSBjb250cm9sIGFuZCBwcmV2ZW50aW9uDQpsaWJyYXJ5KFJOSEFORVMpDQpuaGFuZXMgPC0gbmhhbmVzX2xvYWRfZGF0YSgiQVVRX0ciLCAiMjAxMS0yMDEyIiwgZGVtb2dyYXBoaWNzID0gVFJVRSkNCg0KIyBtYWtlIGEgc21hbGxlciB2ZXJzaW9uIG9mIG5oYW5lcyB3aXRoIHRoZSB2YXJpYWJsZXMgb2YgaW50ZXJlc3QNCnZhcnMgPC0gYygiUklBR0VORFIiLCAiUklEQUdFWVIiLCAiUklEUkVUSDEiKQ0KbmhhbmVzLnNtYWxsIDwtIG5oYW5lc1ssIHZhcnNdDQoNCiMgb3BlbiB0aGUgc3ludGhwb3AgbGlicmFyeSAoaW5zdGFsbCBmaXJzdCkNCmxpYnJhcnkoc3ludGhwb3ApDQoNCiMgY3JlYXRlIG5oYW5lcy5zeW50aCB3aXRoIGRlZmF1bHQgbWV0aG9kDQojIHVzZSBzZWVkIHZhbHVlIGZvciByZXByb2R1Y2liaWxpdHkNCm5oYW5lcy5zeW50aC5saXN0IDwtIHN5bihuaGFuZXMuc21hbGwsIHNlZWQ9MTIzNDU2KQ0KbmhhbmVzLnN5bnRoIDwtIG5oYW5lcy5zeW50aC5saXN0JHN5bg0KDQojIGV4YW1wbGUgb2YgY29tcGFyaW5nIHRoZSBvcmlnaW5hbCBhbmQgc3ludGhldGljIGRhdGEgc2V0cw0KIyBhZGQgbGFiZWxzIHRvIGdlbmRlciBhbmQgZXRobmljaXR5IHZhcmlhYmxlcw0KIyBzZWUgY29kZWJvb2sgaWYgbmVlZGVkIA0KbmhhbmVzLnNtYWxsJFJJQUdFTkRSIDwtIGZhY3RvcihuaGFuZXMuc21hbGwkUklBR0VORFIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoMSwgMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk1hbGUiLCAiRmVtYWxlIikpDQpuaGFuZXMuc21hbGwkUklEUkVUSDEgPC0gZmFjdG9yKG5oYW5lcy5zbWFsbCRSSURSRVRIMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygxLCAyLCAzLCA0LCA1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTWV4aWNhbiBBbWVyaWNhbiIsICJPdGhlciBIaXNwYW5pYyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vbi1IaXNwYW5pYyBXaGl0ZSIsICJOb24tSGlzcGFuaWMgQmxhY2siLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPdGhlciBSYWNlIC0gSW5jbHVkaW5nIE11bHRpLVJhY2lhbCIpKQ0KbmhhbmVzLnN5bnRoJFJJQUdFTkRSIDwtIGZhY3RvcihuaGFuZXMuc3ludGgkUklBR0VORFIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoMSwgMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk1hbGUiLCAiRmVtYWxlIikpDQpuaGFuZXMuc3ludGgkUklEUkVUSDEgPC0gZmFjdG9yKG5oYW5lcy5zeW50aCRSSURSRVRIMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygxLCAyLCAzLCA0LCA1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTWV4aWNhbiBBbWVyaWNhbiIsICJPdGhlciBIaXNwYW5pYyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vbi1IaXNwYW5pYyBXaGl0ZSIsICJOb24tSGlzcGFuaWMgQmxhY2siLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPdGhlciBSYWNlIC0gSW5jbHVkaW5nIE11bHRpLVJhY2lhbCIpKQ0KDQojIG9yaWdpbmFsDQp0YWJsZShuaGFuZXMuc21hbGwkUklEUkVUSDEsIG5oYW5lcy5zbWFsbCRSSUFHRU5EUikNCiMgc3ludGgNCnRhYmxlKG5oYW5lcy5zeW50aCRSSURSRVRIMSwgbmhhbmVzLnN5bnRoJFJJQUdFTkRSKQ0KYGBgDQoNClRoZSB0b3AgdGFibGUgc2hvd3MgdGhlIG9yaWdpbmFsIGRhdGEgZnJlcXVlbmNpZXMgZm9yIGVhY2ggY2F0ZWdvcnkgb2YgcmFjZS9ldGhuaWNpdHkgYWNyb3NzIHRoZSBtYWxlIGFuZCBmZW1hbGUgc2V4IGNhdGVnb3JpZXMuIFRoZSBib3R0b20gc2hvd3MgdGhlIHNhbWUgdmFyaWFibGVzIGluIHRoZSBzeW50aGV0aWMgZGF0YSBzZXQuIFdoaWxlIHRoZSB0d28gZGF0YSBzZXRzIGFyZSBub3QgaWRlbnRpY2FsLCB0aGV5IGFyZSBzaW1pbGFyLg0KDQojIyMgU0FTICh1c2luZyBSIHRvIGNyZWF0ZSkNCg0KVGhlcmUgYXJlIG1hY3JvcyBmb3IgY3JlYXRpbmcgc3ludGhldGljIGRhdGEgZnJvbSBTQVMgZGF0YSBzb3VyY2VzLCBob3dldmVyLCB0aGV5IGFyZSBkaWZmaWN1bHQgdG8gdXNlLiBMaWtld2lzZSwgdGhlIGBzeW50aGAgcGFja2FnZSBmb3IgU3RhdGEgKHJlc291cmNlIGJlbG93KSB3aWxsIGNyZWF0ZSBzeW50aGV0aWMgdHJlYXRtZW50IG9ic2VydmF0aW9ucywgYnV0IHRoZSBwcm9jZXNzIGlzIG5vdCBzdHJhaWdodGZvcndhcmQgZm9yIHN5bnRoZXNpemluZyBkYXRhc2V0cy4gVGhlIFIgYHN5bnRocG9wYCBwYWNrYWdlIGlzIG9uZSBhbHRlcm5hdGl2ZSBzaW5jZSBSIGNhbiBlYXNpbHkgb3BlbiwgbWFuaXB1bGF0ZSwgYW5kIGV4cG9ydCBTQVMgb3IgU3RhdGEgZmlsZXMuIEhlcmUgYXJlIHRoZSBpbnN0cnVjdGlvbnMgZnJvbSB0aGUgUiBleGFtcGxlIGFib3ZlIGJ1dCB3aXRoIHRoZSBTQVMgdmVyc2lvbiBvZiB0aGUgZGF0YSBzb3VyY2UgYXMgaW5wdXQgYW5kIGEgU0FTIG9yIFN0YXRhIGRhdGEgZmlsZSBleHBvcnQgY29tbWFuZCBhZGRlZDoNCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQojIGJyaW5nIGluIHRoZSBvcmlnaW5hbCBkYXRhIG5hbWUgaXQgYnJmc3MNCiMgdGhpcyBpcyB0aGUgMjAxNiBCUkZTUyBkYXRhIGF2YWlsYWJsZSBmcm9tIHRoZSANCiMgQ2VudGVycyBmb3IgZGlzZWFzZSBjb250cm9sIGFuZCBwcmV2ZW50aW9uDQojIGluIFNBUyB0cmFuc3BvcnQgZm9ybWF0DQoNCiMgaW5zdGFsbCBoYXZlbiBpZiBpdCBpcyBub3QgaW5zdGFsbGVkDQojIG9wZW4gdGhlIGhhdmVuIGxpYnJhcnkgZm9yIGltcG9ydGluZyB4cHQgZmlsZXMNCmxpYnJhcnkoaGF2ZW4pIA0KDQojIG1ha2UgYSB0ZW1wb3Jhcnkgb2JqZWN0IHRoYXQgaG9sZHMgYSB6aXAgZmlsZQ0KYnJmc3NfdXJsIDwtIHRlbXBmaWxlKGZpbGVleHQgPSAiLnppcCIpIA0KDQojIGRvd25sb2FkIHRoZSB6aXAgZmlsZQ0KIyBwdXQgdGhlIHppcCBmaWxlIGluIHRoZSB0ZW1wb3JhcnkgZmlsZQ0KZG93bmxvYWQuZmlsZSgiaHR0cHM6Ly93d3cuY2RjLmdvdi9icmZzcy9hbm51YWxfZGF0YS8yMDE2L2ZpbGVzL0xMQ1AyMDE2WFBULnppcCIsIGJyZnNzX3VybCkNCg0KIyB1bnppcCB0aGUgZmlsZSBhbmQgcmVhZCBpdCBpbiB1c2luZyByZWFkX3hwdA0KYnJmc3MgPC0gcmVhZF94cHQoYnJmc3NfdXJsKSANCg0KIyBtYWtlIGEgc21hbGxlciB2ZXJzaW9uIG9mIGJyZnNzIHdpdGggdGhlIHZhcmlhYmxlcyBvZiBpbnRlcmVzdA0KdmFycyA8LSBjKCJTRVgiLCAiTUFSSVRBTCIsICJFRFVDQSIpDQpicmZzcy5zbWFsbCA8LSBicmZzc1ssIHZhcnNdDQoNCiMgb3BlbiB0aGUgc3ludGhwb3AgbGlicmFyeSAoaW5zdGFsbCBmaXJzdCkNCmxpYnJhcnkoc3ludGhwb3ApDQoNCiMgY3JlYXRlIGJyZnNzLnN5bnRoIHdpdGggZGVmYXVsdCBtZXRob2QNCiMgdXNlIHNlZWQgdmFsdWUgZm9yIHJlcHJvZHVjaWJpbGl0eQ0KYnJmc3Muc3ludGgubGlzdCA8LSBzeW4oYnJmc3Muc21hbGwsIHNlZWQ9MTIzNDU2KQ0KYnJmc3Muc3ludGggPC0gYnJmc3Muc3ludGgubGlzdCRzeW4NCg0KIyBleGFtcGxlIG9mIGNvbXBhcmluZyB0aGUgb3JpZ2luYWwgYW5kIHN5bnRoZXRpYyBkYXRhIHNldHMNCiMgYWRkIGxhYmVscyB0byBnZW5kZXIgYW5kIGV0aG5pY2l0eSB2YXJpYWJsZXMNCiMgc2VlIGNvZGVib29rIGlmIG5lZWRlZCANCmJyZnNzLnNtYWxsJFNFWCA8LSBmYWN0b3IoYnJmc3Muc21hbGwkU0VYLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKDEsIDIsIDkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJNYWxlIiwgIkZlbWFsZSIsICJSZWZ1c2VkIikpDQpicmZzcy5zbWFsbCRNQVJJVEFMIDwtIGZhY3RvcihicmZzcy5zbWFsbCRNQVJJVEFMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKDEsIDIsIDMsIDQsIDUsIDYsIDkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJNYXJyaWVkIiwgIkRpdm9yY2VkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2lkb3dlZCIsICJTZXBhcmF0ZWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOZXZlciBtYXJyaWVkIiwgIkEgbWVtYmVyIG9mIGFuIHVubWFycmllZCBjb3VwbGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWZ1c2VkIikpDQpicmZzcy5zeW50aCRTRVggPC0gZmFjdG9yKGJyZnNzLnN5bnRoJFNFWCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygxLCAyLCA5KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTWFsZSIsICJGZW1hbGUiLCAiUmVmdXNlZCIpKQ0KYnJmc3Muc3ludGgkTUFSSVRBTCA8LSBmYWN0b3IoYnJmc3Muc3ludGgkTUFSSVRBTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygxLCAyLCAzLCA0LCA1LCA2LCA5KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTWFycmllZCIsICJEaXZvcmNlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldpZG93ZWQiLCAiU2VwYXJhdGVkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmV2ZXIgbWFycmllZCIsICJBIG1lbWJlciBvZiBhbiB1bm1hcnJpZWQgY291cGxlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVmdXNlZCIpKQ0KDQojIG9yaWdpbmFsDQp0YWJsZShicmZzcy5zbWFsbCRTRVgsIGJyZnNzLnNtYWxsJE1BUklUQUwpDQojIHN5bnRoDQp0YWJsZShicmZzcy5zeW50aCRTRVgsIGJyZnNzLnN5bnRoJE1BUklUQUwpDQoNCmBgYA0KDQpUaGUgdGFibGVzIHNob3cgdGhhdCB0aGUgc3ludGhldGljIGRhdGEgaXMgbm90IGV4YWN0bHkgdGhlIHNhbWUgYXMgdGhlIG9yaWdpbmFsIGRhdGEsIGJ1dCBpdCBpcyBjbG9zZS4gT25jZSB0aGUgc3ludGhldGljIGRhdGEgYXJlIHJlYWR5LCB1c2UgdGhlIGBoYXZlbmAgcGFja2FnZSB0byB3cml0ZSB0aGUgbmV3IGRhdGEgdG8gYSBTQVMgZmlsZToNCg0KYGBge3IgZXZhbCA9IEZBTFNFfQ0KIyBleHBvcnQgdG8gU0FTIGZpbGUNCiMgdXNlcyBoYXZlbiBwYWNrYWdlIG9wZW5lZCBlYXJsaWVyDQojIGFkZCBwYXRoIHRvIHdyaXRlIHRoZSBkYXRhIHRvIGluc2lkZSB0aGUgcXVvdGUgbWFya3MNCndyaXRlX3NhcyhicmZzcy5zeW50aCwgcGF0aCA9ICIiKQ0KDQojIGV4cG9ydCB0byBTdGF0YSAoKi5kdGEpIGZpbGUNCiMgdXNlcyBoYXZlbiBwYWNrYWdlIG9wZW5lZCBlYXJsaWVyDQojIGFkZCBwYXRoIHRvIG5hbWUgYW5kIHNwZWNpZnkgd2hlcmUgdG8gd3JpdGUgdGhlIGRhdGFzZXQgdG8gaW5zaWRlIHRoZSBxdW90ZSBtYXJrcw0Kd3JpdGVfZHRhKGJyZnNzLnN5bnRoLCBwYXRoID0gIiIpDQpgYGANCg0KIyMjIFNQU1MNCg0KSW4gU1BTUywgdGhlIGBTSU1QTEFOYCBhbmQgYFNJTVJVTmAgZnVuY3Rpb25zIGNhbiBjcmVhdGUgc3ludGhldGljIGRhdGEgYmFzZWQgb24gYSByZWFsIGRhdGFzZXQuIFVzZSB0aGUgc21hbGwgTkhBTkVTIGRhdGEgY3JlYXRlZCBpbiB0aGUgUiBleGFtcGxlIGFib3ZlIGFzIGFuIGV4YW1wbGUuDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBldmFsPUZBTFNFfQ0KIyBTZXR0aW5nIGV2YWwgPSBmYWxzZSBmb3Igbm93IHNvIHRoaW5ncyBkb24ndCBnZXQgb3Zlci13cml0dGVuDQojIExvYWQgaGF2ZW4gbGlicmFyeSwgd2hpY2ggYWxsb3dzIHNhdmluZyBmaWxlcyB0byBTUFNTIGZvcm1hdA0KbGlicmFyeShoYXZlbikNCndyaXRlX3NhdihuaGFuZXMuc21hbGwsICJHOlxcQ1BIU1NcXE9wZW5TY2llbmNlXFxNb2R1bGVzXFxEYXRhQ29kZVNoYXJpbmdcXFNQU1NcXE5IQU5FU29yaWcuc2F2IikNCmBgYA0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCiMgTG9hZCBoYXZlbiBsaWJyYXJ5LCB3aGljaCBhbGxvd3Mgc2F2aW5nIGZpbGVzIHRvIFNQU1MgZm9ybWF0DQpsaWJyYXJ5KGhhdmVuKQ0Kd3JpdGVfc2F2KG5oYW5lcy5zbWFsbCwgIkM6L1lvdXIvRGlyZWN0b3J5L05IQU5FU29yaWcuc2F2IikNCmBgYA0KDQoNClJ1biB0aGUgZm9sbG93aW5nIGluIGFuIFNQU1Mgc3ludGF4IGVkaXRvcjoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpodG1sdG9vbHM6OmluY2x1ZGVDU1MoIkc6XFxDUEhTU1xcT3BlblNjaWVuY2VcXE1vZHVsZXNcXFN0eWxlc2hlZXRzXFxTUFNTc3R5bGUuY3NzIikNCmh0bWx0b29sczo6aW5jbHVkZUhUTUwoIlNQU1NzaGFyZTEuaHRtbCIpDQpgYGANCg0KRGVmYXVsdCBwcm9jZWR1cmVzIGZvciB0aGUgYFNJTVBMQU5gIGNvbW1hbmQgd2lsbCBhdXRvbWF0aWNhbGx5IGRldGVybWluZSB0aGUgYmVzdC1maXR0aW5nIGRpc3RyaWJ1dGlvbnMgZm9yIGVhY2ggdmFyaWFibGUgaW5jbHVkZWQgaW4gdGhlIGBTSU1JTlBVVGAgc3ViY29tbWFuZHMsIHJldGFpbiBjb3JyZWxhdGlvbnMgYmV0d2VlbiBzY2FsZSB2YXJpYWJsZXMsIGFuZCBzdG9wIGFmdGVyIDEwMCwwMDAgY2FzZXMgaGF2ZSBiZWVuIGdlbmVyYXRlZC4gQSBmZXcgbW9kaWZpY2F0aW9ucyBoYXZlIGJlZW4gbWFkZSBmb3IgdGhpcyBkYXRhIHNldDoNCg0KMS4gU2ltdWxhdGVkIHZhbHVlcyBmb3IgYWdlIHdlcmUgYmV5b25kIHRoZSBodW1hbiBsaWZlc3BhbiB3aXRoIGRlZmF1bHQgc2V0dGluZ3MsIHNvIG1pbmltdW0gYW5kIG1heGltdW0gdmFsdWVzIHdlcmUgc2V0IGJhc2VkIG9uIHRoZSBhZ2UgcmFuZ2UgaW4gdGhlIHJlYWwgZGF0YS4gU1BTUyBtaWdodCBwcmludCBhIHdhcm5pbmcsIGJ1dCBpdCBkb2VzIHByb2R1Y2UgdGhlIGRlc2lyZWQgcmVzdWx0Lg0KMi4gU1BTUyBkb2VzIG5vdCBhdXRvbWF0aWNhbGx5IHJldGFpbiByZWxhdGlvbnNoaXBzIGJldHdlZW4gY2F0ZWdvcmljYWwgdmFyaWFibGVzLiBTcGVjaWZ5aW5nIHRoZSBgQ09OVElOR0VOQ1lgIHN1YmNvbW1hbmQgd2lsbCBtYWtlIHRoYXQgaGFwcGVuLiANCjMuIEdpdmVuIHRoZSBsYXJnZSBpbmZsdWVuY2UgdGhhdCBzYW1wbGUgc2l6ZSBoYXMgb24gc2lnbmlmaWNhbmNlIHRlc3RpbmcsIG1hbnVhbGx5IGxpbWl0aW5nIHRoZSBtYXhpbXVtIG51bWJlciBvZiBjYXNlcyB0byB0aGUgc2l6ZSBvZiB0aGUgcmVhbCBkYXRhIGlzIHJlY29tbWVuZGVkIHVzaW5nIHRoZSBgU1RPUENSSVRFUklBYCBzdWJjb21tYW5kLiANCg0KVGhlIGBTSU1SVU5gIGNvbW1hbmQgdXNlcyB0aGUgcGxhbiBjcmVhdGVkIHdpdGggYFNJTVBMQU5gLCBhcHBsaWVzIGl0IHRvIHRoZSBvcmlnaW5hbCBkYXRhLCBhbmQgY3JlYXRlcyB0aGUgc2ltdWxhdGVkIGRhdGEgc2V0LiBUbyBlbnN1cmUgdGhlIHNhbWUgcmVzdWx0IGVhY2ggdGltZSB0aGUgcGxhbiBpcyBhcHBsaWVkLCBzcGVjaWZ5IHRoZSBgQ1JJVEVSSUFgIHN1YmNvbW1hbmQgYXMgc2hvd24gd2l0aCB0aGUgc2FtZSBzZWVkLg0KDQpHbyB0byBgSGVscCAtLT4gVG9waWNzYCBhbmQgc2VhcmNoIGZvciBgU0lNUExBTmAgYW5kIGBTSU1SVU5gIGZvciBtb3JlIHNwZWNpZmljYXRpb24gZGV0YWlscyBhbmQgb3B0aW9ucy4NCg0KYGBge3IsIGVjaG89RkFMU0V9DQpodG1sdG9vbHM6OmluY2x1ZGVIVE1MKCJTUFNTc2hhcmUyLmh0bWwiKQ0KYGBgDQoNCk9yaWdpbmFsIGRhdGE6DQoNCjxpbWcgc3JjID0gIkc6XFxDUEhTU1xcT3BlblNjaWVuY2VcXE1vZHVsZXNcXERhdGFDb2RlU2hhcmluZ1xcU1BTU2Nyb3N0YWJzT3JpZy5wbmciLz4NCg0KU2ltdWxhdGVkIGRhdGE6DQoNCjxpbWcgc3JjID0gIkc6XFxDUEhTU1xcT3BlblNjaWVuY2VcXE1vZHVsZXNcXERhdGFDb2RlU2hhcmluZ1xcU1BTU2Nyb3N0YWJzU3ludGgucG5nIi8+DQoNCldoaWxlIG5vdCBleGFjdCwgdGhlIHNpbXVsYXRlZCBkYXRhIHNob3cgcGF0dGVybnMgc2ltaWxhciB0byB0aGUgb3JpZ2luYWwgZGF0YS4NCg0KUmVzb3VyY2VzIHRvIHVzZSBmb3IgY3JlYXRpb24gb2Ygc3ludGhldGljIGRhdGEgaW4gUiwgU1BTUywgU3RhdGEsIGFuZCBTQVMgYXJlIGluY2x1ZGVkIGluIHRoZSBSZXNvdXJjZXMgc2VjdGlvbiBiZWxvdy4NCg0KIyMgUmVzb3VyY2VzIHsjcmVzb30NCg0KIyMjRGF0YSBkZS1pZGVudGlmaWNhdGlvbiBhbmQgc3ludGhldGljIGRhdGEgZ2VuZXJhdGlvbiByZXNvdXJjZXMNCi0gW0RlLWlkZW50aWZ5aW5nIGRhdGFdKGh0dHA6Ly9jZWJwLmFhY3Jqb3VybmFscy5vcmcvY29udGVudC8yNi84LzEyMTkpIA0KLSBbVXNpbmcgSUNQU1IgdG8gZGUtaWRlbnRpZnkgYW5kIG1hbmFnZSBkYXRhXShodHRwczovL3d3dy5pY3Bzci51bWljaC5lZHUvaWNwc3J3ZWIvY29udGVudC9JQ1BTUi9hY2Nlc3MvcmVzdHJpY3RlZC8pICANCi0gW1I6IFNpbXVsYXRpbmcgc29tZSBzeW50aGV0aWMgZGF0YV0oaHR0cHM6Ly93d3cuci1ibG9nZ2Vycy5jb20vc2ltdWxhdGluZy1zb21lLXN5bnRoZXRpYy1kYXRhLykNCi0gW1I6IHN5bnRocG9wOiBCZXNwb2tlIENyZWF0aW9uIG9mIFN5bnRoZXRpYyBEYXRhIGluIFJdKGh0dHBzOi8vd3d3LmpzdGF0c29mdC5vcmcvYXJ0aWNsZS92aWV3L3YwNzRpMTEvdjc0aTExLnBkZikgDQotIFtSOiBPcGVuU0RQIChTeW50aGV0aWMgZGF0YSldKGh0dHBzOi8vb3BlbnNkcC5naXRodWIuaW8vZGF0YS8pIA0KLSBbU1BTUzogQ3JlYXRpbmcgc2ltdWxhdGVkIGRhdGFzZXRzXShodHRwOi8vd3d3LnN0YXRpc3RpY2FsYXNzb2NpYXRlcy5jb20vc2ltdWxhdGVkZGF0YS5wZGYpDQotIFtTUFNTOiBVc2luZyBTUFNTJ3MgU0lNUExBTiB0byBnZW5lcmF0ZSBmYWtlIGRhdGFdKGh0dHBzOi8vYW5kcmV3cHdoZWVsZXIud29yZHByZXNzLmNvbS8yMDE0LzA0LzE1L3VzaW5nLXNwc3NzLXNpbXBsYW4tdG8tZ2VuZXJhdGUtZmFrZS1kYXRhLykgDQotIFtTQVM6IEdlbmVyYXRpbmcgcmVhbGlzdGljIHN5bnRoZXRpYyB0ZXN0IGRhdGEgdXNpbmcgU0FTIHJhbmRvbSBmdW5jdGlvbnNdKGh0dHBzOi8vd3d3LnNhcy5jb20vY29udGVudC9kYW0vU0FTL2VuX2NhL1VzZXIlMjBHcm91cCUyMFByZXNlbnRhdGlvbnMvVEFTUy9rYXJpX2dlbmVyYXRpbmdfdGVzdF9kYXRhLnBkZikgDQotIFtJbmZvcm1hdGlvbiBvbiB0aGUgc3ludGggUGFja2FnZSBmb3IgTUFUTEFCLCBTdGF0YSwgYW5kIFJdKGh0dHBzOi8vd2ViLnN0YW5mb3JkLmVkdS9+amhhaW4vc3ludGhwYWdlLmh0bWwpIA0KDQojIyNSZWZlcmVuY2VzDQo=


Reproducibility Toolkit on GitHub

Top