This workflow should show the full strength of the RRatepol package for working with data types other than fossil pollen, specifically for XRF data. It should serve as step-by-step guidance starting from downloading datasets from the Neotoma and building age-depth models, to estimating rate-of-change using age uncertainty.

For a workflow using Geochemical data, see Part 1 - Geochemical data.

⚠️This workflow is only meant as an example: There may be several additional steps for data preparation, which should be done to properly implement RRatepol and assess the rate of change for your specific project.

Prerequisites

Please follow the pre-workshop instructions to make sure all packages are installed.

This is the second part of the workshop. Therefore, some steps will be omitted and/or not explained. For all details about individual steps, see Part 1 - Geochemical data.

Attach packages

library(tidyverse) # general data wrangling and visualisation ✨
library(pander) # nice tables 😍
library(RRatepol) # rate-of-vegetation change ! > v1.2.0 ! 📈
library(neotoma2) # access to the Neotoma database 🌿
library(Bchron) # age-depth modelingng 🕰️
library(janitor) # string cleaning 🧹
library(here) # for working directory 🗺️

Download a dataset from Neotoma

Here we have selected the Dářko peat record (ID = 48306) by Kletetschka, Günther.

Reference paper: Roleček, J., H. Svitavská Svobodová, E. Jamrichová, L. Dudová, P. Hájková, G. Kletetschka, P. Kuneš, and V. Abraham. 2020. Conservation targets from the perspective of a palaeoecological reconstruction: the case study of Dářko peat bog in the Czech Republic. Preslia 92(2):87-114. DOI: 10.23855/preslia.2020.087

sel_dataset_download <-
  neotoma2::get_downloads(48306)

Prepare the geochemical data

# get samples
data_samples <-
  neotoma2::samples(sel_dataset_download)  %>% 
  tibble::as_tibble()

# prepare taxa table
data_community <-
  data_samples %>%
  dplyr::mutate(sample_id = as.character(sampleid)) %>%
  dplyr::select("sample_id", "value", "variablename") %>%
  # turn into the wider format
  tidyr::pivot_wider(
    names_from = "variablename",
    values_from = "value",
    values_fill = 0
  ) %>%
  # clean names
  janitor::clean_names()  

# make table with units for later
data_units <-
  data_samples %>%
  dplyr::distinct(variablename, units) 

head(data_community)[, 1:5]
sample_id strontium yttrium zirconium niobium
445127 4e-04 9e-04 0.0013 0.0032
445128 7e-04 0.0015 0.0024 0.0035
445129 8e-04 0.0017 0.0021 0.0037
445130 7e-04 0.0015 0.0026 0.0037
445131 7e-04 0.0017 0.0023 0.0039
445132 8e-04 0.0016 0.0022 0.0041

Here, we strongly advocate that careful preparation of the datasets (with additional steps) may be needed before using R-Ratepol!

Preparation of the levels

Sample depth

Extract depth for each level

data_levels <-
  neotoma2::samples(sel_dataset_download) %>%
  tibble::as_tibble() %>%
  dplyr::mutate(sample_id = as.character(sampleid)) %>%
  dplyr::distinct(sample_id, depth) %>%
  dplyr::relocate(sample_id)

head(data_levels)
sample_id depth
445127 0
445128 0.2
445129 0.4
445130 0.6
445131 0.8
445132 1

Age-depth modelling

We will recalculate the age-depth model ‘de novo’ using the Bchron package.

Prepare chron.control table and run Bchron

The chronology control table contains all the dates (mostly radiocarbon) to create the age-depth model.

Here we only present a few of the important steps of preparation of the chronology control table. There are many more potential issues, but solving those is not the focus of this workflow.

# First, get the chronologies and check which we want to use used
sel_chron_control_table_download <-
  neotoma2::chroncontrols(sel_dataset_download)

print(sel_chron_control_table_download)
Table continues below
siteid chronologyid depth thickness agelimitolder chroncontrolid
27171 33682 0 NA -60 104411
27171 33682 25 1 645 104412
27171 33682 50 1 1795 104413
27171 33682 100 1 2400 104414
27171 33682 155 1 2810 104415
27171 33682 200 1 3590 104416
agelimityounger chroncontrolage chroncontroltype
-70 -65 Core top
585 615 Radiocarbon
1735 1765 Radiocarbon
2340 2370 Radiocarbon
2740 2775 Radiocarbon
3530 3560 Radiocarbon
# prepare the table
data_chron_control_table <-
  sel_chron_control_table_download %>%
  # Here select the ID of one of the chronology
  dplyr::filter(chronologyid == 33682) %>%
  tibble::as_tibble() %>%
  # Here we calculate the error as the average of the age `limitolder` and
  #   `agelimityounger`
  dplyr::mutate(
    error = round((agelimitolder - agelimityounger) / 2)
  ) %>%
  # As Bchron cannot accept a error of 0, we need to replace the value with 1
  dplyr::mutate(
    error = replace(error, error == 0, 1),
    error = ifelse(is.na(error), 1, error),
    thickness = ifelse(is.na(thickness), 1, thickness)
  ) %>%
  # We need to specify which calibration curve should be used for what point
  dplyr::mutate(
    curve = ifelse(as.data.frame(sel_dataset_download)["lat"] > 0, "intcal20", "shcal20"),
    curve = ifelse(chroncontroltype != "Radiocarbon", "normal", curve)
  ) %>%
  tibble::column_to_rownames("chroncontrolid") %>%
  dplyr::arrange(depth) %>%
  dplyr::select(
    chroncontrolage, error, depth, thickness, chroncontroltype, curve
  )

head(data_chron_control_table)
chroncontrolage error depth thickness chroncontroltype curve
-65 5 0 1 Core top normal
615 30 25 1 Radiocarbon intcal20
1765 30 50 1 Radiocarbon intcal20
2370 30 100 1 Radiocarbon intcal20
2775 35 155 1 Radiocarbon intcal20
3560 30 200 1 Radiocarbon intcal20

As this is just a toy example, we will use only the iteration multiplier (i_multiplier) of 0.1 to reduce the computation time. However, we strongly recommend increasing it to 5 for any normal age-depth model construction.

i_multiplier <- 0.1 # increase to 5

# Those are default values suggested by the Bchron package
n_iteration_default <- 10e3
n_burn_default <- 2e3
n_thin_default <- 8

# Let's multiply them by our i_multiplier
n_iteration <- n_iteration_default * i_multiplier
n_burn <- n_burn_default * i_multiplier
n_thin <- max(c(1, n_thin_default * i_multiplier))

# run Bchron
sel_bchron <-
  Bchron::Bchronology(
    ages = data_chron_control_table$chroncontrolage,
    ageSds = data_chron_control_table$error,
    positions = data_chron_control_table$depth,
    calCurves = data_chron_control_table$curve,
    positionThicknesses = data_chron_control_table$thickness,
    iterations = n_iteration,
    burn = n_burn,
    thin = n_thin
  )

Visually check the age-depth models

Bchron:::plot.BchronologyRun(sel_bchron) + # or just simple plot(sel_bchron)
  ggplot2::theme_bw() +
  ggplot2::theme(
    axis.title = ggplot2::element_text(size = 25),
    axis.text = ggplot2::element_text(size = 15),
    strip.text = ggplot2::element_text(size = 15),
    panel.grid = ggplot2::element_blank()
  ) +
  ggplot2::labs(
    x = "age (cal yr BP)",
    y = "depth"
  )

Predict ages

Let’s first extract posterior ages (i.e. possible ages) from the age-depth model.

age_position <-
  Bchron:::predict.BchronologyRun( # or just simple predict(sel_bchron)
    object = sel_bchron,
    newPositions = data_levels$depth
  )

age_uncertainties <-
  age_position %>%
  as.data.frame() %>%
  dplyr::mutate_all(., as.integer) %>%
  as.matrix()

colnames(age_uncertainties) <- data_levels$sample_id
data_levels_predicted <-
  data_levels %>%
  dplyr::mutate(
    age = apply(
      age_uncertainties, 2,
      stats::quantile,
      probs = 0.5
    )
  )

head(data_levels_predicted)
sample_id depth age
445127 0 -65
445128 0.2 -59
445129 0.4 -54
445130 0.6 -48
445131 0.8 -43
445132 1 -38

Visualisation of our data

Let’s now make a simple diagram with proportions of the concentrations (x-axis) against our estimated ages along the depth (y-axis).

data_community %>%
  dplyr::inner_join(
    data_levels_predicted,
    by = dplyr::join_by(sample_id)
  ) %>%
  tidyr::pivot_longer(
    cols = -c(sample_id, depth, age),
    names_to = "element",
    values_to = "value"
  ) %>%
  ggplot2::ggplot(
    mapping = ggplot2::aes(
      x = age,
      y = value,
      col = element
    ),
  ) +
  ggplot2::facet_wrap(
    ~element,
    nrow = 1,
    scales = "free_x"
  ) +
  ggplot2::coord_flip() +
  ggplot2::scale_x_continuous(trans = "reverse") +
  ggplot2::scale_y_continuous(breaks = c(0, 50, 100)) +
  ggplot2::theme(
     panel.grid.major.x = ggplot2::element_line(
      colour = "grey",
      linewidth = 0.1
    ),
    legend.position = "none",
    panel.border = ggplot2::element_blank(),
    strip.background = ggplot2::element_blank(),
    strip.text = ggplot2::element_blank(),
    axis.ticks.x = ggplot2::element_blank(),
    axis.text.x = ggplot2::element_blank()
  ) +
  ggplot2::labs(
    x = "age (cal yr BP)",
    y = "Percentage"
  ) +
  ggplot2::geom_line()

Estimation Rate-of-Change

Now we will use our prepared XRF data and age-depth model to estimate the rate of change. We will present several scenarios (i.e. approaches) to calculate RoC.

Selection of dissimilarity coefficient

We can check the units of individual measured values:

data_units %>%
  dplyr::pull("units") %>%
  table()
percent
29

As we can see, all measured values are in percentage units. Therefore, for all scenarios, we will be using the chisq dissimilarity coefficient (works with closed data), and time_standardisation == 500 (this means that all ROC values are ‘change per 500 yr’).

Scenario 1 - Estimating RoC for each level

This is the “Classic” approach that uses each sampled depth in a record (i.e. individual level) to estimate RoC.

scenario_1 <-
  RRatepol::estimate_roc(
    data_source_community = data_community,
    data_source_age = data_levels_predicted,
    dissimilarity_coefficient = "chisq",
    time_standardisation = 500,
    working_units = "levels" # here is set to use individual levels
  )
RRatepol::plot_roc(data_source = scenario_1)

Scenario 2 - Estimating RoC for each level with smoothing of data

We do the same as in Scenario 1 but now we smooth the community data before calculating RoC. This may be useful to mitigate the error of measurement. Specifically, we will add smooth_method = “shep” (i.e. Shepard’s 5-term filter).

scenario_2 <-
  RRatepol::estimate_roc(
    data_source_community = data_community,
    data_source_age = data_levels_predicted,
    dissimilarity_coefficient = "chisq",
    time_standardisation = 500,
    working_units = "levels",
    smooth_method = "shep" # Shepard's 5-term filter
  )
RRatepol::plot_roc(data_source = scenario_2)

We see that the absolute RoC scores are decreased and the pattern changed slightly (x-axis).

Scenario 3 - Using uncertainty matrix

For RoC analysis, it is important to consider age uncertainties. For each iteration, RRatepol will randomly select one age-sequence from the uncertainty matrix (see the age-depth modeling section for more info).

Because of that, we need to increase the number of randomizations. This is again a toy example for a quick computation and therefore we only do 100 randomizations. We would recommend increasing the set_randomisations to 10.000 for any real estimation.

set_randomisations <- 100

To speed the process up, you can also set use_parallel == TRUE, which will use all cores of your computer.

scenario_3 <-
  RRatepol::estimate_roc(
  data_source_community = data_community,
    data_source_age = data_levels_predicted,
    dissimilarity_coefficient = "chisq",
    time_standardisation = 500,
    smooth_method = "shep",
    age_uncertainty = age_uncertainties, # Add the uncertainty matrix
    rand = set_randomisations,  # set number of randomisations
    use_parallel = TRUE # do use parallel computing
  )
RRatepol::plot_roc(data_source = scenario_3)

We will now also visualize uncertainty around the RoC scores shown by a grey shadow. We see a substantial increase in RoC value in certain regions, this is caused by the extremely small numbers of age differences and the low number of randomizations.

Scenario 4 - Estimating RoC per bin

In order to get rid of the effect of uneven distribution of sampled depths (i.e. levels) in a record, we can bin the data.

Specifically, we will change the working_units from single levels to "bins". Here we select bins of 500 years each instead of the individual levels.

Note that one level is randomly selected as a representation of that time bin. Therefore, it is important to increase the number of randomizations.

scenario_4 <-
  RRatepol::estimate_roc(
    data_source_community = data_community,
    data_source_age = data_levels_predicted,
    dissimilarity_coefficient = "chisq",
    working_units = "bins", # change the "bins"
    bin_size = 500, # size of a time bin
    time_standardisation = 500,
    smooth_method = "shep",
    age_uncertainty = age_uncertainties,
    rand = set_randomisations, 
    use_parallel = TRUE 
  )
RRatepol::plot_roc(data_source = scenario_4)

Here we can see a drastic change in the shape of RoC but a large loss of temporal precision.

Scenario 5 - Estimating RoC with the new “Moving-window” approach

In order to reduce the temporal uncertainty and improve temporal precision, we can apply a novel approach in RRATEPOL called “moving window”.

scenario_5 <-
  RRatepol::estimate_roc(
    data_source_community = data_community,
    data_source_age = data_levels_predicted,
    dissimilarity_coefficient = "chisq",
    working_units = "MW", # change the "MW" to apply the "moving window"
    bin_size = 500,
    number_of_shifts = 5, # number of shifts
    time_standardisation = 500,
    smooth_method = "shep",
    rand = set_randomisations,
    use_parallel = TRUE,
    age_uncertainty = age_uncertainties
  )
RRatepol::plot_roc(data_source = scenario_5)

Scenario 6 - Detecting peak points

Throughout the record, there can be periods when the RoC will substantially change. We can detect RoC increases that are significant by identifying so-called peak-points. Here, we will use the “Non-linear” method, which will detect a significant change from a non-linear trend of RoC.

scenario_5_peak <-
  RRatepol::detect_peak_points(
    data_source = scenario_5,
    sel_method = "trend_non_linear"
  )

Now we will plot the RoC estimates showing the peak points. So here we can see that there were rates of vegetation change throughout the record but only at certain moments in time (green dots - peak points) these changes were significant. There you go!

RRatepol::plot_roc(
  data_source = scenario_5_peak,
  peaks = TRUE
)

LS0tDQp0aXRsZTogUGFydCAyIC0gWFJGIGRhdGENCmZvcm1hdDogDQogIGdmbToNCiAgICBmaWctd2lkdGg6IDcNCiAgICBmaWctaGVpZ2h0OiA2DQogICAgd3JhcDogbm9uZQ0KDQotLS0NCg0KYGBge3J9DQojfCBsYWJlbDogY2h1bmsgc2V0dXANCiN8IGluY2x1ZGU6IEZBTFNFIA0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBjb2xsYXBzZSA9IFRSVUUsDQogIGNvbW1lbnQgPSAiIz4iLA0KICByZXN1bHRzID0gImhpZGUiLA0KICB3YXJuaW5nID0gRkFMU0UsDQogIG1lc3NhZ2UgPSBGQUxTRSwNCiAgZmlnLmFsaWduID0gImNlbnRlciINCikNCmBgYA0KDQpUaGlzIHdvcmtmbG93IHNob3VsZCBzaG93IHRoZSBmdWxsIHN0cmVuZ3RoIG9mIHRoZSBbKlJSYXRlcG9sIHBhY2thZ2UqXShodHRwczovL2hvcGUtdWliLWJpby5naXRodWIuaW8vUi1SYXRlcG9sLXBhY2thZ2UvKSBmb3Igd29ya2luZyB3aXRoIGRhdGEgdHlwZXMgKipvdGhlcioqIHRoYW4gZm9zc2lsIHBvbGxlbiwgc3BlY2lmaWNhbGx5IGZvciAqKlhSRiBkYXRhKiouIEl0IHNob3VsZCBzZXJ2ZSBhcyBzdGVwLWJ5LXN0ZXAgZ3VpZGFuY2Ugc3RhcnRpbmcgZnJvbSBkb3dubG9hZGluZyBkYXRhc2V0cyBmcm9tIHRoZSBOZW90b21hIGFuZCBidWlsZGluZyBhZ2UtZGVwdGggbW9kZWxzLCB0byBlc3RpbWF0aW5nIHJhdGUtb2YtY2hhbmdlIHVzaW5nIGFnZSB1bmNlcnRhaW50eS4gDQoNCkZvciBhIHdvcmtmbG93IHVzaW5nICoqR2VvY2hlbWljYWwgZGF0YSoqLCBzZWUgW1BhcnQgMSAtIEdlb2NoZW1pY2FsIGRhdGFdKGh0dHBzOi8vb25kcmVqbW90dGwuZ2l0aHViLmlvL09DQ1JfUi1SYXRlcG9sX3dvcmtzaG9wL3BhcnRfMl94cmZfZGF0YS5odG1sKS4NCg0K4pqg77iPKipUaGlzIHdvcmtmbG93IGlzIG9ubHkgbWVhbnQgYXMgYW4gZXhhbXBsZSoqOiBUaGVyZSBtYXkgYmUgc2V2ZXJhbCBhZGRpdGlvbmFsIHN0ZXBzIGZvciBkYXRhIHByZXBhcmF0aW9uLCB3aGljaCBzaG91bGQgYmUgZG9uZSB0byBwcm9wZXJseSBpbXBsZW1lbnQgUlJhdGVwb2wgYW5kIGFzc2VzcyB0aGUgcmF0ZSBvZiBjaGFuZ2UgZm9yIHlvdXIgc3BlY2lmaWMgcHJvamVjdC4gDQoNCiMjIFByZXJlcXVpc2l0ZXMNCg0KUGxlYXNlIGZvbGxvdyB0aGUgW3ByZS13b3Jrc2hvcCBpbnN0cnVjdGlvbnNdKGh0dHBzOi8vb25kcmVqbW90dGwuZ2l0aHViLmlvL09DQ1JfUi1SYXRlcG9sX3dvcmtzaG9wL3ByZV93b3Jrc2hvcC5odG1sKSB0byBtYWtlIHN1cmUgYWxsIHBhY2thZ2VzIGFyZSBpbnN0YWxsZWQuDQoNClRoaXMgaXMgdGhlIHNlY29uZCBwYXJ0IG9mIHRoZSB3b3Jrc2hvcC4gVGhlcmVmb3JlLCBzb21lIHN0ZXBzIHdpbGwgYmUgb21pdHRlZCBhbmQvb3Igbm90IGV4cGxhaW5lZC4gRm9yIGFsbCBkZXRhaWxzIGFib3V0IGluZGl2aWR1YWwgc3RlcHMsIHNlZSBbUGFydCAxIC0gR2VvY2hlbWljYWwgZGF0YV0oaHR0cHM6Ly9vbmRyZWptb3R0bC5naXRodWIuaW8vT0NDUl9SLVJhdGVwb2xfd29ya3Nob3AvcGFydF8yX3hyZl9kYXRhLmh0bWwpLg0KDQojIyBBdHRhY2ggcGFja2FnZXMNCg0KYGBge3J9DQojfCBsYWJlbDogYXR0YWNoIHBhY2thZ2VzDQpsaWJyYXJ5KHRpZHl2ZXJzZSkgIyBnZW5lcmFsIGRhdGEgd3JhbmdsaW5nIGFuZCB2aXN1YWxpc2F0aW9uIOKcqA0KbGlicmFyeShwYW5kZXIpICMgbmljZSB0YWJsZXMg8J+YjQ0KbGlicmFyeShSUmF0ZXBvbCkgIyByYXRlLW9mLXZlZ2V0YXRpb24gY2hhbmdlICEgPiB2MS4yLjAgISDwn5OIDQpsaWJyYXJ5KG5lb3RvbWEyKSAjIGFjY2VzcyB0byB0aGUgTmVvdG9tYSBkYXRhYmFzZSDwn4y/DQpsaWJyYXJ5KEJjaHJvbikgIyBhZ2UtZGVwdGggbW9kZWxpbmduZyDwn5Ww77iPDQpsaWJyYXJ5KGphbml0b3IpICMgc3RyaW5nIGNsZWFuaW5nIPCfp7kNCmxpYnJhcnkoaGVyZSkgIyBmb3Igd29ya2luZyBkaXJlY3Rvcnkg8J+Xuu+4jw0KYGBgDQoNCmBgYHtyfQ0KI3wgbGFiZWw6IHRoZW1lIHNldA0KI3wgaW5jbHVkZTogRkFMU0UNCmdncGxvdDI6OnRoZW1lX3NldCgNCiAgZ2dwbG90Mjo6dGhlbWVfYncoKSArDQogICAgZ2dwbG90Mjo6dGhlbWUoDQogICAgICBheGlzLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyNSksDQogICAgICBheGlzLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwNCiAgICAgIHN0cmlwLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwNCiAgICAgIHBhbmVsLmdyaWQgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCkNCiAgICApDQopDQpgYGANCg0KDQojIyBEb3dubG9hZCBhIGRhdGFzZXQgZnJvbSBOZW90b21hDQoNCkhlcmUgd2UgaGF2ZSBzZWxlY3RlZCB0aGUgKipEw6HFmWtvIHBlYXQqKiByZWNvcmQgKElEID0gNDgzMDYpIGJ5IEtsZXRldHNjaGthLCBHw7xudGhlci4NCg0KUmVmZXJlbmNlIHBhcGVyOiBSb2xlxI1laywgSi4sIEguIFN2aXRhdnNrw6EgU3ZvYm9kb3bDoSwgRS4gSmFtcmljaG92w6EsIEwuIER1ZG92w6EsIFAuIEjDoWprb3bDoSwgRy4gS2xldGV0c2Noa2EsIFAuIEt1bmXFoSwgYW5kIFYuIEFicmFoYW0uIDIwMjAuIENvbnNlcnZhdGlvbiB0YXJnZXRzIGZyb20gdGhlIHBlcnNwZWN0aXZlIG9mIGEgcGFsYWVvZWNvbG9naWNhbCByZWNvbnN0cnVjdGlvbjogdGhlIGNhc2Ugc3R1ZHkgb2YgRMOhxZlrbyBwZWF0IGJvZyBpbiB0aGUgQ3plY2ggUmVwdWJsaWMuIFByZXNsaWEgOTIoMik6ODctMTE0LiBET0k6IDEwLjIzODU1L3ByZXNsaWEuMjAyMC4wODcNCg0KYGBge3J9DQojfCBsYWJlbDogZG93bmxvYWQgZGF0YXNldA0Kc2VsX2RhdGFzZXRfZG93bmxvYWQgPC0NCiAgbmVvdG9tYTI6OmdldF9kb3dubG9hZHMoNDgzMDYpDQpgYGANCg0KIyMgUHJlcGFyZSB0aGUgZ2VvY2hlbWljYWwgZGF0YQ0KDQpgYGB7cn0NCiN8IGxhYmVsOiBwcmVwYXJlIGdlb2NoZW1pY2FsIGRhdGENCiMgZ2V0IHNhbXBsZXMNCmRhdGFfc2FtcGxlcyA8LQ0KICBuZW90b21hMjo6c2FtcGxlcyhzZWxfZGF0YXNldF9kb3dubG9hZCkgICU+JSANCiAgdGliYmxlOjphc190aWJibGUoKQ0KDQojIHByZXBhcmUgdGF4YSB0YWJsZQ0KZGF0YV9jb21tdW5pdHkgPC0NCiAgZGF0YV9zYW1wbGVzICU+JQ0KICBkcGx5cjo6bXV0YXRlKHNhbXBsZV9pZCA9IGFzLmNoYXJhY3RlcihzYW1wbGVpZCkpICU+JQ0KICBkcGx5cjo6c2VsZWN0KCJzYW1wbGVfaWQiLCAidmFsdWUiLCAidmFyaWFibGVuYW1lIikgJT4lDQogICMgdHVybiBpbnRvIHRoZSB3aWRlciBmb3JtYXQNCiAgdGlkeXI6OnBpdm90X3dpZGVyKA0KICAgIG5hbWVzX2Zyb20gPSAidmFyaWFibGVuYW1lIiwNCiAgICB2YWx1ZXNfZnJvbSA9ICJ2YWx1ZSIsDQogICAgdmFsdWVzX2ZpbGwgPSAwDQogICkgJT4lDQogICMgY2xlYW4gbmFtZXMNCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAgDQoNCiMgbWFrZSB0YWJsZSB3aXRoIHVuaXRzIGZvciBsYXRlcg0KZGF0YV91bml0cyA8LQ0KICBkYXRhX3NhbXBsZXMgJT4lDQogIGRwbHlyOjpkaXN0aW5jdCh2YXJpYWJsZW5hbWUsIHVuaXRzKSANCg0KaGVhZChkYXRhX2NvbW11bml0eSlbLCAxOjVdDQpgYGANCg0KYGBge3J9DQojfCBsYWJlbDogZGlzcGxheSBjb21tdW5pdHkgdGFibGUNCiN8IGVjaG86IEZBTFNFDQojfCByZXN1bHRzOiAnYXNpcycNCnBhbmRlcjo6cGFuZG9jLnRhYmxlKGhlYWQoZGF0YV9jb21tdW5pdHkpWywgMTo1XSkNCmBgYA0KDQpIZXJlLCB3ZSBzdHJvbmdseSBhZHZvY2F0ZSB0aGF0IGNhcmVmdWwgcHJlcGFyYXRpb24gb2YgdGhlIGRhdGFzZXRzICh3aXRoIGFkZGl0aW9uYWwgc3RlcHMpIG1heSBiZSBuZWVkZWQgYmVmb3JlIHVzaW5nIFItUmF0ZXBvbCENCg0KIyMgUHJlcGFyYXRpb24gb2YgdGhlIGxldmVscw0KDQojIyMgU2FtcGxlIGRlcHRoDQoNCkV4dHJhY3QgZGVwdGggZm9yIGVhY2ggbGV2ZWwNCg0KYGBge3J9DQojfCBsYWJlbDogbGV2ZWwgcHJlcGFyYXRpb24NCmRhdGFfbGV2ZWxzIDwtDQogIG5lb3RvbWEyOjpzYW1wbGVzKHNlbF9kYXRhc2V0X2Rvd25sb2FkKSAlPiUNCiAgdGliYmxlOjphc190aWJibGUoKSAlPiUNCiAgZHBseXI6Om11dGF0ZShzYW1wbGVfaWQgPSBhcy5jaGFyYWN0ZXIoc2FtcGxlaWQpKSAlPiUNCiAgZHBseXI6OmRpc3RpbmN0KHNhbXBsZV9pZCwgZGVwdGgpICU+JQ0KICBkcGx5cjo6cmVsb2NhdGUoc2FtcGxlX2lkKQ0KDQpoZWFkKGRhdGFfbGV2ZWxzKQ0KYGBgDQoNCmBgYHtyfQ0KI3wgbGFiZWw6IGRpc3BsYXkgbGV2ZWwNCiN8IGVjaG86IEZBTFNFDQojfCByZXN1bHRzOiAnYXNpcycNCnBhbmRlcjo6cGFuZG9jLnRhYmxlKGhlYWQoZGF0YV9sZXZlbHMpKQ0KYGBgDQoNCiMjIyBBZ2UtZGVwdGggbW9kZWxsaW5nDQoNCldlIHdpbGwgcmVjYWxjdWxhdGUgdGhlIGFnZS1kZXB0aCBtb2RlbCAnZGUgbm92bycgdXNpbmcgdGhlIFsqQmNocm9uKiBwYWNrYWdlXShodHRwOi8vYW5kcmV3Y3Bhcm5lbGwuZ2l0aHViLmlvL0JjaHJvbi8pLiANCg0KIyMjIyBQcmVwYXJlIGNocm9uLmNvbnRyb2wgdGFibGUgYW5kIHJ1biBCY2hyb24NClRoZSBjaHJvbm9sb2d5IGNvbnRyb2wgdGFibGUgY29udGFpbnMgYWxsIHRoZSBkYXRlcyAobW9zdGx5IHJhZGlvY2FyYm9uKSB0byBjcmVhdGUgdGhlIGFnZS1kZXB0aCBtb2RlbC4NCg0KSGVyZSB3ZSBvbmx5IHByZXNlbnQgYSBmZXcgb2YgdGhlIGltcG9ydGFudCBzdGVwcyBvZiBwcmVwYXJhdGlvbiBvZiB0aGUgY2hyb25vbG9neSBjb250cm9sIHRhYmxlLiBUaGVyZSBhcmUgbWFueSBtb3JlIHBvdGVudGlhbCBpc3N1ZXMsIGJ1dCBzb2x2aW5nIHRob3NlIGlzIG5vdCB0aGUgZm9jdXMgb2YgdGhpcyB3b3JrZmxvdy4NCg0KYGBge3J9DQojfCBsYWJlbDogZ2V0IGNocm9ub2xvZ3kgdGFibGVzDQojIEZpcnN0LCBnZXQgdGhlIGNocm9ub2xvZ2llcyBhbmQgY2hlY2sgd2hpY2ggd2Ugd2FudCB0byB1c2UgdXNlZA0Kc2VsX2Nocm9uX2NvbnRyb2xfdGFibGVfZG93bmxvYWQgPC0NCiAgbmVvdG9tYTI6OmNocm9uY29udHJvbHMoc2VsX2RhdGFzZXRfZG93bmxvYWQpDQoNCnByaW50KHNlbF9jaHJvbl9jb250cm9sX3RhYmxlX2Rvd25sb2FkKQ0KYGBgDQpgYGB7cn0NCiN8IGxhYmVsOiBkaXNwbGF5IGNocm9uIGNvbnRyb2wgdGFibGVzDQojfCBlY2hvOiBGQUxTRQ0KI3wgcmVzdWx0czogJ2FzaXMnDQpwYW5kZXI6OnBhbmRvYy50YWJsZShoZWFkKHNlbF9jaHJvbl9jb250cm9sX3RhYmxlX2Rvd25sb2FkKSkNCmBgYA0KDQpgYGB7cn0NCiN8IGxhYmVsOiBwcmVwYXJlY2hyb24gY29udHJvbCB0YWJsZQ0KIyBwcmVwYXJlIHRoZSB0YWJsZQ0KZGF0YV9jaHJvbl9jb250cm9sX3RhYmxlIDwtDQogIHNlbF9jaHJvbl9jb250cm9sX3RhYmxlX2Rvd25sb2FkICU+JQ0KICAjIEhlcmUgc2VsZWN0IHRoZSBJRCBvZiBvbmUgb2YgdGhlIGNocm9ub2xvZ3kNCiAgZHBseXI6OmZpbHRlcihjaHJvbm9sb2d5aWQgPT0gMzM2ODIpICU+JQ0KICB0aWJibGU6OmFzX3RpYmJsZSgpICU+JQ0KICAjIEhlcmUgd2UgY2FsY3VsYXRlIHRoZSBlcnJvciBhcyB0aGUgYXZlcmFnZSBvZiB0aGUgYWdlIGBsaW1pdG9sZGVyYCBhbmQNCiAgIyAgIGBhZ2VsaW1pdHlvdW5nZXJgDQogIGRwbHlyOjptdXRhdGUoDQogICAgZXJyb3IgPSByb3VuZCgoYWdlbGltaXRvbGRlciAtIGFnZWxpbWl0eW91bmdlcikgLyAyKQ0KICApICU+JQ0KICAjIEFzIEJjaHJvbiBjYW5ub3QgYWNjZXB0IGEgZXJyb3Igb2YgMCwgd2UgbmVlZCB0byByZXBsYWNlIHRoZSB2YWx1ZSB3aXRoIDENCiAgZHBseXI6Om11dGF0ZSgNCiAgICBlcnJvciA9IHJlcGxhY2UoZXJyb3IsIGVycm9yID09IDAsIDEpLA0KICAgIGVycm9yID0gaWZlbHNlKGlzLm5hKGVycm9yKSwgMSwgZXJyb3IpLA0KICAgIHRoaWNrbmVzcyA9IGlmZWxzZShpcy5uYSh0aGlja25lc3MpLCAxLCB0aGlja25lc3MpDQogICkgJT4lDQogICMgV2UgbmVlZCB0byBzcGVjaWZ5IHdoaWNoIGNhbGlicmF0aW9uIGN1cnZlIHNob3VsZCBiZSB1c2VkIGZvciB3aGF0IHBvaW50DQogIGRwbHlyOjptdXRhdGUoDQogICAgY3VydmUgPSBpZmVsc2UoYXMuZGF0YS5mcmFtZShzZWxfZGF0YXNldF9kb3dubG9hZClbImxhdCJdID4gMCwgImludGNhbDIwIiwgInNoY2FsMjAiKSwNCiAgICBjdXJ2ZSA9IGlmZWxzZShjaHJvbmNvbnRyb2x0eXBlICE9ICJSYWRpb2NhcmJvbiIsICJub3JtYWwiLCBjdXJ2ZSkNCiAgKSAlPiUNCiAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXMoImNocm9uY29udHJvbGlkIikgJT4lDQogIGRwbHlyOjphcnJhbmdlKGRlcHRoKSAlPiUNCiAgZHBseXI6OnNlbGVjdCgNCiAgICBjaHJvbmNvbnRyb2xhZ2UsIGVycm9yLCBkZXB0aCwgdGhpY2tuZXNzLCBjaHJvbmNvbnRyb2x0eXBlLCBjdXJ2ZQ0KICApDQoNCmhlYWQoZGF0YV9jaHJvbl9jb250cm9sX3RhYmxlKQ0KYGBgDQoNCmBgYHtyfQ0KI3wgbGFiZWw6IGRpc3BsYXkgcHJlcGFyZWQgY2hyb24gY29udHJvbCB0YWJsZQ0KI3wgZWNobzogRkFMU0UNCiN8IHJlc3VsdHM6ICdhc2lzJw0KcGFuZGVyOjpwYW5kb2MudGFibGUoaGVhZChkYXRhX2Nocm9uX2NvbnRyb2xfdGFibGUpKQ0KYGBgDQoNCkFzIHRoaXMgaXMganVzdCBhIHRveSBleGFtcGxlLCB3ZSB3aWxsIHVzZSBvbmx5IHRoZSBpdGVyYXRpb24gbXVsdGlwbGllciAoYGlfbXVsdGlwbGllcmApIG9mIGAwLjFgIHRvIHJlZHVjZSB0aGUgY29tcHV0YXRpb24gdGltZS4gSG93ZXZlciwgd2Ugc3Ryb25nbHkgcmVjb21tZW5kIGluY3JlYXNpbmcgaXQgdG8gNSBmb3IgYW55IG5vcm1hbCBhZ2UtZGVwdGggbW9kZWwgY29uc3RydWN0aW9uLg0KYGBge3J9DQojfCBsYWJlbDogcnVuIEJjaHJvbg0KaV9tdWx0aXBsaWVyIDwtIDAuMSAjIGluY3JlYXNlIHRvIDUNCg0KIyBUaG9zZSBhcmUgZGVmYXVsdCB2YWx1ZXMgc3VnZ2VzdGVkIGJ5IHRoZSBCY2hyb24gcGFja2FnZQ0Kbl9pdGVyYXRpb25fZGVmYXVsdCA8LSAxMGUzDQpuX2J1cm5fZGVmYXVsdCA8LSAyZTMNCm5fdGhpbl9kZWZhdWx0IDwtIDgNCg0KIyBMZXQncyBtdWx0aXBseSB0aGVtIGJ5IG91ciBpX211bHRpcGxpZXINCm5faXRlcmF0aW9uIDwtIG5faXRlcmF0aW9uX2RlZmF1bHQgKiBpX211bHRpcGxpZXINCm5fYnVybiA8LSBuX2J1cm5fZGVmYXVsdCAqIGlfbXVsdGlwbGllcg0Kbl90aGluIDwtIG1heChjKDEsIG5fdGhpbl9kZWZhdWx0ICogaV9tdWx0aXBsaWVyKSkNCg0KIyBydW4gQmNocm9uDQpzZWxfYmNocm9uIDwtDQogIEJjaHJvbjo6QmNocm9ub2xvZ3koDQogICAgYWdlcyA9IGRhdGFfY2hyb25fY29udHJvbF90YWJsZSRjaHJvbmNvbnRyb2xhZ2UsDQogICAgYWdlU2RzID0gZGF0YV9jaHJvbl9jb250cm9sX3RhYmxlJGVycm9yLA0KICAgIHBvc2l0aW9ucyA9IGRhdGFfY2hyb25fY29udHJvbF90YWJsZSRkZXB0aCwNCiAgICBjYWxDdXJ2ZXMgPSBkYXRhX2Nocm9uX2NvbnRyb2xfdGFibGUkY3VydmUsDQogICAgcG9zaXRpb25UaGlja25lc3NlcyA9IGRhdGFfY2hyb25fY29udHJvbF90YWJsZSR0aGlja25lc3MsDQogICAgaXRlcmF0aW9ucyA9IG5faXRlcmF0aW9uLA0KICAgIGJ1cm4gPSBuX2J1cm4sDQogICAgdGhpbiA9IG5fdGhpbg0KICApDQpgYGANCg0KVmlzdWFsbHkgY2hlY2sgdGhlIGFnZS1kZXB0aCBtb2RlbHMNCg0KYGBge3J9DQojfCBsYWJlbDogcGxvdCBCY2hyb24NCkJjaHJvbjo6OnBsb3QuQmNocm9ub2xvZ3lSdW4oc2VsX2JjaHJvbikgKyAjIG9yIGp1c3Qgc2ltcGxlIHBsb3Qoc2VsX2JjaHJvbikNCiAgZ2dwbG90Mjo6dGhlbWVfYncoKSArDQogIGdncGxvdDI6OnRoZW1lKA0KICAgIGF4aXMudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDI1KSwNCiAgICBheGlzLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwNCiAgICBzdHJpcC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNSksDQogICAgcGFuZWwuZ3JpZCA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKQ0KICApICsNCiAgZ2dwbG90Mjo6bGFicygNCiAgICB4ID0gImFnZSAoY2FsIHlyIEJQKSIsDQogICAgeSA9ICJkZXB0aCINCiAgKQ0KYGBgDQoNCiMjIyMgUHJlZGljdCBhZ2VzDQoNCkxldCdzIGZpcnN0IGV4dHJhY3QgcG9zdGVyaW9yIGFnZXMgKGkuZS4gcG9zc2libGUgYWdlcykgZnJvbSB0aGUgYWdlLWRlcHRoIG1vZGVsLiAgDQoNCmBgYHtyfQ0KI3wgbGFiZWw6IHByZWRpY3QgYWdlcw0KYWdlX3Bvc2l0aW9uIDwtDQogIEJjaHJvbjo6OnByZWRpY3QuQmNocm9ub2xvZ3lSdW4oICMgb3IganVzdCBzaW1wbGUgcHJlZGljdChzZWxfYmNocm9uKQ0KICAgIG9iamVjdCA9IHNlbF9iY2hyb24sDQogICAgbmV3UG9zaXRpb25zID0gZGF0YV9sZXZlbHMkZGVwdGgNCiAgKQ0KDQphZ2VfdW5jZXJ0YWludGllcyA8LQ0KICBhZ2VfcG9zaXRpb24gJT4lDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUNCiAgZHBseXI6Om11dGF0ZV9hbGwoLiwgYXMuaW50ZWdlcikgJT4lDQogIGFzLm1hdHJpeCgpDQoNCmNvbG5hbWVzKGFnZV91bmNlcnRhaW50aWVzKSA8LSBkYXRhX2xldmVscyRzYW1wbGVfaWQNCmBgYA0KDQpgYGB7cn0NCiN8IGxhYmVsOiBnZXQgbWVkaWFuIGFnZQ0KZGF0YV9sZXZlbHNfcHJlZGljdGVkIDwtDQogIGRhdGFfbGV2ZWxzICU+JQ0KICBkcGx5cjo6bXV0YXRlKA0KICAgIGFnZSA9IGFwcGx5KA0KICAgICAgYWdlX3VuY2VydGFpbnRpZXMsIDIsDQogICAgICBzdGF0czo6cXVhbnRpbGUsDQogICAgICBwcm9icyA9IDAuNQ0KICAgICkNCiAgKQ0KDQpoZWFkKGRhdGFfbGV2ZWxzX3ByZWRpY3RlZCkNCmBgYA0KDQpgYGB7cn0NCiN8IGxhYmVsOiBkaXNwbGF5IG1lZGlhbiBhZ2UNCiN8IGVjaG86IEZBTFNFDQojfCByZXN1bHRzOiAnYXNpcycNCnBhbmRlcjo6cGFuZG9jLnRhYmxlKGhlYWQoZGF0YV9sZXZlbHNfcHJlZGljdGVkKSkNCmBgYA0KDQojIyMgVmlzdWFsaXNhdGlvbiBvZiBvdXIgZGF0YQ0KDQpMZXQncyBub3cgbWFrZSBhIHNpbXBsZSBkaWFncmFtIHdpdGggcHJvcG9ydGlvbnMgb2YgdGhlIGNvbmNlbnRyYXRpb25zICh4LWF4aXMpIGFnYWluc3Qgb3VyIGVzdGltYXRlZCBhZ2VzIGFsb25nIHRoZSBkZXB0aCAoeS1heGlzKS4NCg0KYGBge3J9DQojfCBsYWJlbDogcGxvdCBkYXRhIHdpdGggYWdlcw0KZGF0YV9jb21tdW5pdHkgJT4lDQogIGRwbHlyOjppbm5lcl9qb2luKA0KICAgIGRhdGFfbGV2ZWxzX3ByZWRpY3RlZCwNCiAgICBieSA9IGRwbHlyOjpqb2luX2J5KHNhbXBsZV9pZCkNCiAgKSAlPiUNCiAgdGlkeXI6OnBpdm90X2xvbmdlcigNCiAgICBjb2xzID0gLWMoc2FtcGxlX2lkLCBkZXB0aCwgYWdlKSwNCiAgICBuYW1lc190byA9ICJlbGVtZW50IiwNCiAgICB2YWx1ZXNfdG8gPSAidmFsdWUiDQogICkgJT4lDQogIGdncGxvdDI6OmdncGxvdCgNCiAgICBtYXBwaW5nID0gZ2dwbG90Mjo6YWVzKA0KICAgICAgeCA9IGFnZSwNCiAgICAgIHkgPSB2YWx1ZSwNCiAgICAgIGNvbCA9IGVsZW1lbnQNCiAgICApLA0KICApICsNCiAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCgNCiAgICB+ZWxlbWVudCwNCiAgICBucm93ID0gMSwNCiAgICBzY2FsZXMgPSAiZnJlZV94Ig0KICApICsNCiAgZ2dwbG90Mjo6Y29vcmRfZmxpcCgpICsNCiAgZ2dwbG90Mjo6c2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gInJldmVyc2UiKSArDQogIGdncGxvdDI6OnNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKDAsIDUwLCAxMDApKSArDQogIGdncGxvdDI6OnRoZW1lKA0KICAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBnZ3Bsb3QyOjplbGVtZW50X2xpbmUoDQogICAgICBjb2xvdXIgPSAiZ3JleSIsDQogICAgICBsaW5ld2lkdGggPSAwLjENCiAgICApLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICBwYW5lbC5ib3JkZXIgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCksDQogICAgc3RyaXAuYmFja2dyb3VuZCA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwNCiAgICBzdHJpcC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGlja3MueCA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKQ0KICApICsNCiAgZ2dwbG90Mjo6bGFicygNCiAgICB4ID0gImFnZSAoY2FsIHlyIEJQKSIsDQogICAgeSA9ICJQZXJjZW50YWdlIg0KICApICsNCiAgZ2dwbG90Mjo6Z2VvbV9saW5lKCkNCmBgYA0KDQoNCiMjIEVzdGltYXRpb24gUmF0ZS1vZi1DaGFuZ2UNCg0KTm93IHdlIHdpbGwgdXNlIG91ciBwcmVwYXJlZCBYUkYgZGF0YSBhbmQgYWdlLWRlcHRoIG1vZGVsIHRvIGVzdGltYXRlIHRoZSByYXRlIG9mIGNoYW5nZS4NCldlIHdpbGwgcHJlc2VudCBzZXZlcmFsIHNjZW5hcmlvcyAoaS5lLiBhcHByb2FjaGVzKSB0byBjYWxjdWxhdGUgUm9DLiANCg0KIyMjIFNlbGVjdGlvbiBvZiBkaXNzaW1pbGFyaXR5IGNvZWZmaWNpZW50IA0KDQpXZSBjYW4gY2hlY2sgdGhlIHVuaXRzIG9mIGluZGl2aWR1YWwgbWVhc3VyZWQgdmFsdWVzOg0KYGBge3J9DQojfCBsYWJlbDogZGF0YSB1bml0cw0KZGF0YV91bml0cyAlPiUNCiAgZHBseXI6OnB1bGwoInVuaXRzIikgJT4lDQogIHRhYmxlKCkNCmBgYA0KDQpgYGB7cn0NCiN8IGxhYmVsOiBkaXNwbGF5IGRhdGEgdW5pdHMNCiN8IGVjaG86IEZBTFNFDQojfCByZXN1bHRzOiAnYXNpcycNCmRhdGFfdW5pdHMgJT4lDQogIGRwbHlyOjpwdWxsKCJ1bml0cyIpICU+JQ0KICB0YWJsZSgpICU+JQ0KICBwYW5kZXI6OnBhbmRvYy50YWJsZSgpDQpgYGANCg0KQXMgd2UgY2FuIHNlZSwgYWxsIG1lYXN1cmVkIHZhbHVlcyBhcmUgaW4gcGVyY2VudGFnZSB1bml0cy4gVGhlcmVmb3JlLCBmb3IgYWxsIHNjZW5hcmlvcywgd2Ugd2lsbCBiZSB1c2luZyB0aGUgYGNoaXNxYCBkaXNzaW1pbGFyaXR5IGNvZWZmaWNpZW50ICh3b3JrcyB3aXRoIGNsb3NlZCBkYXRhKSwgYW5kIGB0aW1lX3N0YW5kYXJkaXNhdGlvbmAgPT0gNTAwICh0aGlzIG1lYW5zIHRoYXQgYWxsIFJPQyB2YWx1ZXMgYXJlICdjaGFuZ2UgcGVyIDUwMCB5cicpLg0KDQojIyMgU2NlbmFyaW8gMSAtIEVzdGltYXRpbmcgUm9DIGZvciBlYWNoIGxldmVsDQoNClRoaXMgaXMgdGhlICJDbGFzc2ljIiBhcHByb2FjaCB0aGF0IHVzZXMgZWFjaCBzYW1wbGVkIGRlcHRoIGluIGEgcmVjb3JkIChpLmUuIGluZGl2aWR1YWwgbGV2ZWwpIHRvIGVzdGltYXRlIFJvQy4NCg0KYGBge3J9DQojfCBsYWJlbDogc2NlbmFyaW8gMQ0Kc2NlbmFyaW9fMSA8LQ0KICBSUmF0ZXBvbDo6ZXN0aW1hdGVfcm9jKA0KICAgIGRhdGFfc291cmNlX2NvbW11bml0eSA9IGRhdGFfY29tbXVuaXR5LA0KICAgIGRhdGFfc291cmNlX2FnZSA9IGRhdGFfbGV2ZWxzX3ByZWRpY3RlZCwNCiAgICBkaXNzaW1pbGFyaXR5X2NvZWZmaWNpZW50ID0gImNoaXNxIiwNCiAgICB0aW1lX3N0YW5kYXJkaXNhdGlvbiA9IDUwMCwNCiAgICB3b3JraW5nX3VuaXRzID0gImxldmVscyIgIyBoZXJlIGlzIHNldCB0byB1c2UgaW5kaXZpZHVhbCBsZXZlbHMNCiAgKQ0KYGBgDQoNCmBgYHtyfQ0KI3wgbGFiZWw6IHBsb3Qgc2NlbmFyaW8gMQ0KUlJhdGVwb2w6OnBsb3Rfcm9jKGRhdGFfc291cmNlID0gc2NlbmFyaW9fMSkNCmBgYA0KDQojIyMgU2NlbmFyaW8gMiAtIEVzdGltYXRpbmcgUm9DIGZvciBlYWNoIGxldmVsIHdpdGggc21vb3RoaW5nIG9mIGRhdGENCg0KV2UgZG8gdGhlIHNhbWUgYXMgaW4gU2NlbmFyaW8gMSBidXQgbm93IHdlIHNtb290aCB0aGUgY29tbXVuaXR5IGRhdGEgYmVmb3JlIGNhbGN1bGF0aW5nIFJvQy4gVGhpcyBtYXkgYmUgdXNlZnVsIHRvIG1pdGlnYXRlIHRoZSBlcnJvciBvZiBtZWFzdXJlbWVudC4gU3BlY2lmaWNhbGx5LCB3ZSB3aWxsIGFkZCBgc21vb3RoX21ldGhvZGAgPSAic2hlcCIgKGkuZS4gU2hlcGFyZCdzIDUtdGVybSBmaWx0ZXIpLg0KDQpgYGB7cn0NCiN8IGxhYmVsOiBzY2VuYXJpbyAyDQpzY2VuYXJpb18yIDwtDQogIFJSYXRlcG9sOjplc3RpbWF0ZV9yb2MoDQogICAgZGF0YV9zb3VyY2VfY29tbXVuaXR5ID0gZGF0YV9jb21tdW5pdHksDQogICAgZGF0YV9zb3VyY2VfYWdlID0gZGF0YV9sZXZlbHNfcHJlZGljdGVkLA0KICAgIGRpc3NpbWlsYXJpdHlfY29lZmZpY2llbnQgPSAiY2hpc3EiLA0KICAgIHRpbWVfc3RhbmRhcmRpc2F0aW9uID0gNTAwLA0KICAgIHdvcmtpbmdfdW5pdHMgPSAibGV2ZWxzIiwNCiAgICBzbW9vdGhfbWV0aG9kID0gInNoZXAiICMgU2hlcGFyZCdzIDUtdGVybSBmaWx0ZXINCiAgKQ0KYGBgDQoNCmBgYHtyfQ0KI3wgbGFiZWw6IHBsb3Qgc2NlbmFyaW8gMg0KUlJhdGVwb2w6OnBsb3Rfcm9jKGRhdGFfc291cmNlID0gc2NlbmFyaW9fMikNCmBgYA0KDQpXZSBzZWUgdGhhdCB0aGUgYWJzb2x1dGUgUm9DIHNjb3JlcyBhcmUgZGVjcmVhc2VkIGFuZCB0aGUgcGF0dGVybiBjaGFuZ2VkIHNsaWdodGx5ICh4LWF4aXMpLiANCg0KIyMjIFNjZW5hcmlvIDMgLSBVc2luZyB1bmNlcnRhaW50eSBtYXRyaXgNCg0KRm9yIFJvQyBhbmFseXNpcywgaXQgaXMgaW1wb3J0YW50IHRvIGNvbnNpZGVyIGFnZSB1bmNlcnRhaW50aWVzLiBGb3IgZWFjaCBpdGVyYXRpb24sIFJSYXRlcG9sIHdpbGwgcmFuZG9tbHkgc2VsZWN0IG9uZSBhZ2Utc2VxdWVuY2UgZnJvbSB0aGUgdW5jZXJ0YWludHkgbWF0cml4IChzZWUgdGhlIGFnZS1kZXB0aCBtb2RlbGluZyBzZWN0aW9uIGZvciBtb3JlIGluZm8pLiANCg0KQmVjYXVzZSBvZiB0aGF0LCB3ZSBuZWVkIHRvIGluY3JlYXNlIHRoZSBudW1iZXIgb2YgcmFuZG9taXphdGlvbnMuIFRoaXMgaXMgYWdhaW4gYSB0b3kgZXhhbXBsZSBmb3IgYSBxdWljayBjb21wdXRhdGlvbiBhbmQgdGhlcmVmb3JlIHdlIG9ubHkgZG8gMTAwIHJhbmRvbWl6YXRpb25zLiBXZSB3b3VsZCByZWNvbW1lbmQgaW5jcmVhc2luZyB0aGUgKnNldF9yYW5kb21pc2F0aW9ucyogdG8gMTAuMDAwIGZvciBhbnkgcmVhbCBlc3RpbWF0aW9uLiANCg0KYGBge3J9DQojfCBsYWJlbDogc2V0IHJhbmRvbWlzYXRpb25zDQpzZXRfcmFuZG9taXNhdGlvbnMgPC0gMTAwDQpgYGANCg0KVG8gc3BlZWQgdGhlIHByb2Nlc3MgdXAsIHlvdSBjYW4gYWxzbyBzZXQgYHVzZV9wYXJhbGxlbGAgPT0gYFRSVUVgLCB3aGljaCB3aWxsIHVzZSBhbGwgY29yZXMgb2YgeW91ciBjb21wdXRlci4NCg0KYGBge3J9DQojfCBsYWJlbDogc2NlbmFyaW8gMw0Kc2NlbmFyaW9fMyA8LQ0KICBSUmF0ZXBvbDo6ZXN0aW1hdGVfcm9jKA0KICBkYXRhX3NvdXJjZV9jb21tdW5pdHkgPSBkYXRhX2NvbW11bml0eSwNCiAgICBkYXRhX3NvdXJjZV9hZ2UgPSBkYXRhX2xldmVsc19wcmVkaWN0ZWQsDQogICAgZGlzc2ltaWxhcml0eV9jb2VmZmljaWVudCA9ICJjaGlzcSIsDQogICAgdGltZV9zdGFuZGFyZGlzYXRpb24gPSA1MDAsDQogICAgc21vb3RoX21ldGhvZCA9ICJzaGVwIiwNCiAgICBhZ2VfdW5jZXJ0YWludHkgPSBhZ2VfdW5jZXJ0YWludGllcywgIyBBZGQgdGhlIHVuY2VydGFpbnR5IG1hdHJpeA0KICAgIHJhbmQgPSBzZXRfcmFuZG9taXNhdGlvbnMsICAjIHNldCBudW1iZXIgb2YgcmFuZG9taXNhdGlvbnMNCiAgICB1c2VfcGFyYWxsZWwgPSBUUlVFICMgZG8gdXNlIHBhcmFsbGVsIGNvbXB1dGluZw0KICApDQpgYGAgDQoNCmBgYHtyfQ0KI3wgbGFiZWw6IHBsb3Qgc2NlbmFyaW8gMw0KUlJhdGVwb2w6OnBsb3Rfcm9jKGRhdGFfc291cmNlID0gc2NlbmFyaW9fMykNCmBgYA0KDQpXZSB3aWxsIG5vdyBhbHNvIHZpc3VhbGl6ZSB1bmNlcnRhaW50eSBhcm91bmQgdGhlIFJvQyBzY29yZXMgc2hvd24gYnkgYSBncmV5IHNoYWRvdy4gV2Ugc2VlIGEgc3Vic3RhbnRpYWwgaW5jcmVhc2UgaW4gUm9DIHZhbHVlIGluIGNlcnRhaW4gcmVnaW9ucywgdGhpcyBpcyBjYXVzZWQgYnkgdGhlIGV4dHJlbWVseSBzbWFsbCBudW1iZXJzIG9mIGFnZSBkaWZmZXJlbmNlcyBhbmQgdGhlIGxvdyBudW1iZXIgb2YgcmFuZG9taXphdGlvbnMuDQoNCiMjIyBTY2VuYXJpbyA0IC0gRXN0aW1hdGluZyBSb0MgcGVyIGJpbg0KDQpJbiBvcmRlciB0byBnZXQgcmlkIG9mIHRoZSBlZmZlY3Qgb2YgdW5ldmVuIGRpc3RyaWJ1dGlvbiBvZiBzYW1wbGVkIGRlcHRocyAoaS5lLiBsZXZlbHMpIGluIGEgcmVjb3JkLCB3ZSBjYW4gYmluIHRoZSBkYXRhLg0KDQpTcGVjaWZpY2FsbHksIHdlIHdpbGwgY2hhbmdlIHRoZSBgd29ya2luZ191bml0c2AgZnJvbSBzaW5nbGUgbGV2ZWxzIHRvIGAiYmlucyJgLiBIZXJlIHdlIHNlbGVjdCBiaW5zIG9mIDUwMCB5ZWFycyBlYWNoIGluc3RlYWQgb2YgdGhlIGluZGl2aWR1YWwgbGV2ZWxzLiANCg0KTm90ZSB0aGF0IG9uZSBsZXZlbCBpcyByYW5kb21seSBzZWxlY3RlZCBhcyBhIHJlcHJlc2VudGF0aW9uIG9mIHRoYXQgdGltZSBiaW4uIFRoZXJlZm9yZSwgaXQgaXMgaW1wb3J0YW50IHRvIGluY3JlYXNlIHRoZSBudW1iZXIgb2YgcmFuZG9taXphdGlvbnMuIA0KYGBge3J9DQojfCBsYWJlbDogc2NlbmFyaW8gNA0Kc2NlbmFyaW9fNCA8LQ0KICBSUmF0ZXBvbDo6ZXN0aW1hdGVfcm9jKA0KICAgIGRhdGFfc291cmNlX2NvbW11bml0eSA9IGRhdGFfY29tbXVuaXR5LA0KICAgIGRhdGFfc291cmNlX2FnZSA9IGRhdGFfbGV2ZWxzX3ByZWRpY3RlZCwNCiAgICBkaXNzaW1pbGFyaXR5X2NvZWZmaWNpZW50ID0gImNoaXNxIiwNCiAgICB3b3JraW5nX3VuaXRzID0gImJpbnMiLCAjIGNoYW5nZSB0aGUgImJpbnMiDQogICAgYmluX3NpemUgPSA1MDAsICMgc2l6ZSBvZiBhIHRpbWUgYmluDQogICAgdGltZV9zdGFuZGFyZGlzYXRpb24gPSA1MDAsDQogICAgc21vb3RoX21ldGhvZCA9ICJzaGVwIiwNCiAgICBhZ2VfdW5jZXJ0YWludHkgPSBhZ2VfdW5jZXJ0YWludGllcywNCiAgICByYW5kID0gc2V0X3JhbmRvbWlzYXRpb25zLCANCiAgICB1c2VfcGFyYWxsZWwgPSBUUlVFIA0KICApDQpgYGANCg0KYGBge3J9DQojfCBsYWJlbDogcGxvdCBzY2VuYXJpbyA0DQpSUmF0ZXBvbDo6cGxvdF9yb2MoZGF0YV9zb3VyY2UgPSBzY2VuYXJpb180KQ0KYGBgDQoNCkhlcmUgd2UgY2FuIHNlZSBhIGRyYXN0aWMgY2hhbmdlIGluIHRoZSBzaGFwZSBvZiBSb0MgYnV0IGEgbGFyZ2UgbG9zcyBvZiB0ZW1wb3JhbCBwcmVjaXNpb24uDQoNCiMjIyBTY2VuYXJpbyA1IC0gRXN0aW1hdGluZyBSb0Mgd2l0aCB0aGUgbmV3ICJNb3Zpbmctd2luZG93IiBhcHByb2FjaA0KDQpJbiBvcmRlciB0byByZWR1Y2UgdGhlIHRlbXBvcmFsIHVuY2VydGFpbnR5IGFuZCBpbXByb3ZlIHRlbXBvcmFsIHByZWNpc2lvbiwgd2UgY2FuIGFwcGx5IGEgbm92ZWwgYXBwcm9hY2ggaW4gUlJBVEVQT0wgY2FsbGVkICJtb3Zpbmcgd2luZG93Ii4gDQoNCmBgYHtyfQ0KI3wgbGFiZWw6IHNjZW5hcmlvIDUNCnNjZW5hcmlvXzUgPC0NCiAgUlJhdGVwb2w6OmVzdGltYXRlX3JvYygNCiAgICBkYXRhX3NvdXJjZV9jb21tdW5pdHkgPSBkYXRhX2NvbW11bml0eSwNCiAgICBkYXRhX3NvdXJjZV9hZ2UgPSBkYXRhX2xldmVsc19wcmVkaWN0ZWQsDQogICAgZGlzc2ltaWxhcml0eV9jb2VmZmljaWVudCA9ICJjaGlzcSIsDQogICAgd29ya2luZ191bml0cyA9ICJNVyIsICMgY2hhbmdlIHRoZSAiTVciIHRvIGFwcGx5IHRoZSAibW92aW5nIHdpbmRvdyINCiAgICBiaW5fc2l6ZSA9IDUwMCwNCiAgICBudW1iZXJfb2Zfc2hpZnRzID0gNSwgIyBudW1iZXIgb2Ygc2hpZnRzDQogICAgdGltZV9zdGFuZGFyZGlzYXRpb24gPSA1MDAsDQogICAgc21vb3RoX21ldGhvZCA9ICJzaGVwIiwNCiAgICByYW5kID0gc2V0X3JhbmRvbWlzYXRpb25zLA0KICAgIHVzZV9wYXJhbGxlbCA9IFRSVUUsDQogICAgYWdlX3VuY2VydGFpbnR5ID0gYWdlX3VuY2VydGFpbnRpZXMNCiAgKQ0KYGBgDQoNCmBgYHtyfQ0KI3wgbGFiZWw6IHBsb3Qgc2NlbmFyaW8gNQ0KUlJhdGVwb2w6OnBsb3Rfcm9jKGRhdGFfc291cmNlID0gc2NlbmFyaW9fNSkNCmBgYA0KDQojIyMgU2NlbmFyaW8gNiAtIERldGVjdGluZyBwZWFrIHBvaW50cw0KDQpUaHJvdWdob3V0IHRoZSByZWNvcmQsIHRoZXJlIGNhbiBiZSBwZXJpb2RzIHdoZW4gdGhlIFJvQyB3aWxsIHN1YnN0YW50aWFsbHkgY2hhbmdlLiBXZSBjYW4gZGV0ZWN0IFJvQyBpbmNyZWFzZXMgdGhhdCBhcmUgc2lnbmlmaWNhbnQgYnkgaWRlbnRpZnlpbmcgc28tY2FsbGVkICpwZWFrLXBvaW50cyouIEhlcmUsIHdlIHdpbGwgdXNlIHRoZSAiTm9uLWxpbmVhciIgbWV0aG9kLCB3aGljaCB3aWxsIGRldGVjdCBhIHNpZ25pZmljYW50IGNoYW5nZSBmcm9tIGEgbm9uLWxpbmVhciB0cmVuZCBvZiBSb0MuDQoNCmBgYHtyfQ0KI3wgbGFiZWw6IHBlYWtfcG9pbnRzIA0Kc2NlbmFyaW9fNV9wZWFrIDwtDQogIFJSYXRlcG9sOjpkZXRlY3RfcGVha19wb2ludHMoDQogICAgZGF0YV9zb3VyY2UgPSBzY2VuYXJpb181LA0KICAgIHNlbF9tZXRob2QgPSAidHJlbmRfbm9uX2xpbmVhciINCiAgKQ0KYGBgDQoNCk5vdyB3ZSB3aWxsIHBsb3QgdGhlIFJvQyBlc3RpbWF0ZXMgc2hvd2luZyB0aGUgcGVhayBwb2ludHMuIFNvIGhlcmUgd2UgY2FuIHNlZSB0aGF0IHRoZXJlIHdlcmUgcmF0ZXMgb2YgdmVnZXRhdGlvbiBjaGFuZ2UgdGhyb3VnaG91dCB0aGUgcmVjb3JkIGJ1dCBvbmx5IGF0IGNlcnRhaW4gbW9tZW50cyBpbiB0aW1lIChncmVlbiBkb3RzIC0gcGVhayBwb2ludHMpIHRoZXNlIGNoYW5nZXMgd2VyZSBzaWduaWZpY2FudC4gVGhlcmUgeW91IGdvIQ0KDQpgYGB7cn0NCiN8IGxhYmVsOiBwbG90IHBlYWsgcG9pbnRzDQpSUmF0ZXBvbDo6cGxvdF9yb2MoDQogIGRhdGFfc291cmNlID0gc2NlbmFyaW9fNV9wZWFrLA0KICBwZWFrcyA9IFRSVUUNCikNCmBgYA==