Preparation Instructions

THE DATASET

For this Challenge Problem assignment, you are going to be using the UNESCO Institute of Statistics dataset on global student to teacher ratios.1 The data includes educational information at the country-level. The original documentation for this dataset can be found on its Tidy Tuesday page. Note that the Tidy Tuesday data has been merged with another dataset so that it also contains region information:

  • region: Continent/region name

  • sub.region: Sub-region name

  • region.code: Continent/region code

  • sub.region.code: Sub-region code

The goal of this assignment is to take you through the process of creating a data visualization from a basic ggplot to one that is appealing and easy to understand. The question of interest for this assignment is:

What are the student to teacher ratios in primary education for each continent/region in the world (excluding Antarctica) in the most recent year? Note: Use the most recent year we have data for each country (this may be different across countries).

DATA VISUALIZATION EVOLUTION

  1. Is the data in the appropriate form for answering the question? Explain your reasoning.

[Hints: How many rows should there be for each country if you want the most recent year? Which educational level group are you interested in? Are there some countries with a missing value for region?] - No, the data is not in the appropriate form to answer the question. Currently, there are multiple rows for each country and for several education levels. The research question focuses on the primary education level group, so the data should be wrangled to remove countries with missing values, filter for the primary education level group, and include only one row per country.

  1. Using your answer to the previous problem, wrangle the data into the appropriate form. Be sure to save the wrangled data frame into a new object.

[Hint: You should have 165 observations in your wrangled data frame.]

S_T <- student_teacher %>%
filter(!is.na(region), indicator == "Primary Education") %>% 
  group_by(country) %>% 
  filter(year == max(year, na.rm = TRUE))

nrow(S_T)
## [1] 165
  1. Create a data visualization of student to teacher ratio by region.

[Hints: Which plot is better for comparing groups: histograms, boxplots, or density plots? No faceting allowed.]

ggplot(S_T, aes(x = student_ratio, y = region, fill = region)) + 
  geom_boxplot() + 
  theme_classic() +
  labs(x = "Student To Teacher Ratio", 
       y = "Region",
       title = "Primary Education: Student to Teacher Ratio by Region") +
  scale_fill_paletteer_d("RSkittleBrewer::smarties") +
  theme(legend.position = "none", 
  plot.title = element_text(size = 15, face = "bold", hjust = 1))

  1. Identify at least one way to improve the visualization if you were going to present it in a paper or in a presentation.
  • One way to improve visualization would be to incorporate the median or mean values for each region directly on the plot, which would make it easier to estimate student-to-teacher ratios in the different regions.
  1. Let’s improve the plot with these suggestions:

    • reorder, in descending order, the regions by the median of student to teacher ratio rather than by alphabetical order of region (HINT: if reordering outside of ggplot, e.g. using the mutate function, make sure there is no grouping structure on the data),

    • put the region variable on the y-axis and student to teacher ratio variable on the x-axis, if haven’t done so, so long labels can be seen,

    • customize the axes labels so that y has no label and x has an meaningful label, and

    • choose the classic theme for the plot.

S_T <- S_T %>%
  ungroup() %>%
  mutate(region = fct_reorder(region, student_ratio, .fun = median, .desc = TRUE))

ggplot(S_T, aes(x = student_ratio, y = region, fill = region)) + 
  geom_boxplot() + 
  theme_classic() +
  labs(x = "Student To Teacher Ratio", 
       y = NULL,
       title = "Primary Education: Student to Teacher Ratio by Region") +
  scale_fill_paletteer_d("RSkittleBrewer::smarties") +
  theme(legend.position = "none", 
  plot.title = element_text(size = 15, face = "bold", hjust = 1))

Educational Note: If this visualization was for a paper or a presentation, you could stop after this plot. However, you could add the raw data to the plot to show more detail for each region.

  1. Let’s include multiple geoms to provide even more information in one plot:

    • use the argument to remove outliers in the original geom (NOTE: proceed very carefully if doing this in practice! This is fine here because we are about to put all the points on the plot, including these),

    • modify the color of the original geom to gray60,

    • add another geom layer of jittered points that is colored by region and semi-transparent, and

    • remove the legend.

[Note: Choose a color palette that you think is visually pleasing.]

##Setting the seed so that the same jittered plot is reproduced instead of always having random points 
set.seed(20211026)
ggplot(S_T, aes(x = student_ratio, y = region, fill = region)) + 
  geom_boxplot(outlier.shape = NA, fill = "gray60") + 
  geom_jitter(aes(color = region), size = 2, alpha = 0.1) + 
  theme_classic() +
  labs(x = "Student To Teacher Ratio", 
       y = NULL,
       title = "Primary Education: Student to Teacher Ratio by Region") +
  scale_color_paletteer_d("RSkittleBrewer::smarties") +
  theme(legend.position = "none", 
  plot.title = element_text(size = 15, face = "bold", hjust = 1))

Educational Note: You might add the raw data to the visualization to identify gaps in each region (e.g., gap in Oceania) or to identify number of observations per region.

  1. Let’s suppose you decide that you want to show the distribution using violin plots instead of boxes and you also want to add a larger dot for the mean of student to teacher ratio by region:

    • add a column to the data frame that computes the mean of student to teacher ratio by region,

    • create a data visualization with the jittered points (as created previously), violin geom, and the other customizations (e.g., modified axes labels, no legend), and

    • add a larger point for the mean of student to teacher ratio by region. Be sure that the added point is colored by region.

[Note: Think about the ordering of the geoms when creating the plot.]

set.seed(20211026)
mean_S_T <- S_T %>% 
  group_by(region) %>%
  mutate(ST_mean = mean(student_ratio, na.rm = TRUE)) %>%
  ungroup()

ggplot(mean_S_T, aes(x = student_ratio, y = region, fill = region)) + 
  geom_violin()+ 
  geom_jitter(aes(color = region), size = 2, alpha = 0.1) + 
  geom_point(aes(x = ST_mean, color = region), size = 3) +
  theme_classic() +
  labs(x = "Student To Teacher Ratio", 
       y = NULL,
       title = "Primary Education: Student to Teacher Ratio Mean by Region") +
  scale_color_paletteer_d("RSkittleBrewer::smarties") +
  theme(legend.position = "none", 
  plot.title = element_text(size = 15, face = "bold", hjust = 1))

  1. Let’s add a vertical line to relate these points to a baseline (worldwide average):

    • add a vertical line at the location of the mean student to teacher ratio for all of the countries and color it gray70.

[Note: Use online resources (e.g., STHDA) for how to create a vertical line in the plot.]

set.seed(20211026)
mean_global <- mean(S_T$student_ratio, na.rm = TRUE)

ggplot(mean_S_T, aes(x = student_ratio, y = region, fill = region)) + 
  geom_violin()+ 
  geom_jitter(aes(color = region), size = 2, alpha = 0.1) + 
  geom_point(aes(x = ST_mean, color = region), size = 3) +
  geom_vline(xintercept = mean_global, color = "gray70", linewidth = 1.5) +
  theme_classic() +
  labs(x = "Student To Teacher Ratio", 
       y = NULL,
       title = "Primary Education: Student to Teacher Ratio Mean by Region") +
  scale_color_paletteer_d("RSkittleBrewer::smarties") +
  theme(legend.position = "none", 
  plot.title = element_text(size = 15, face = "bold", hjust = 1))

  1. Lastly, let’s add a meaningful title, subtitle, caption, and text annotations so the plot speaks for itself:

    • add a meaningful title for the plot, any

    • add a meaningful subtitle that summarizes the plot (you may need to use \n in your label to add a new line if have a long subtitle),

    • add one meaningful text annotation for each geom in the plot (this link is a good resource), and

    • add a meaningful caption describing the original source of the dataset.

set.seed(20211026)
ggplot(mean_S_T, aes(x = student_ratio, y = region, fill = region)) + 
  geom_violin()+ 
  geom_jitter(aes(color = region), size = 2, alpha = 0.1) + 
  geom_point(aes(x = ST_mean, color = region), size = 3) +
  geom_vline(xintercept = mean_global, color = "gray70", linewidth = 1.5) +
 annotate("text", x = 44, y = "Oceania", 
            label = "Africa had the highest distribution of student to teacher ratio", 
            color = "black", size = 3.5, hjust = 0, vjust = -0.98) +
  annotate("text", x = 37, y = "South America", 
           label = "Each semi-transparent dot represent a country", 
           color = "black", size = 3.5, hjust = 0.05, vjust = -0.5) +
  annotate("text", x = 35, y = "Europe", 
           label = "Colored circles in barplots represent the regional student to teacher mean", 
           color = "black", size = 3.5, hjust = 0., vjust = -0.5) +
  annotate("text", x = 35, y = "North America", 
           label = "The gray line represents the global student to teacher ratio mean", 
           color = "black", size = 3.5, hjust = 0, vjust = -0.8) +
  theme_classic() +
  labs(x = "Student To Teacher Ratio", 
       y = NULL,
       title = "Primary Education: Student to Teacher Ratio Mean by Region",
       subtitle = "The barplot represents regional student to teacher ratio and indicates the highest mean in Africa and the lowest mean in Europe",
       caption = "Source:UNESCO Institute of Statistics (Tidy Tuesday May 7, 2019")  +
  scale_color_paletteer_d("RSkittleBrewer::smarties") +
  theme(legend.position = "none", 
  plot.title = element_text(size = 15, face = "bold", hjust = 1),
  plot.subtitle = element_text(size = 8, hjust = 1),
  plot.caption = element_text(size = 8, face = "italic", hjust = 0.5))

CHALLENGE (optional): Another part of EDA is to identify interesting or relevant points on the plot. Using the geom_label_repel() function from the {ggrepel} package, denote the countries that have the smallest ratio with a green label on the plot and denote the countries that have the largest ratio with a red label on the plot.

set.seed(20211026)

  1. Source: Tidy Tuesday dataset from May 7, 2019.↩︎

LS0tCnRpdGxlOiAiV2VlayA3IENoYWxsZW5nZSBQcm9ibGVtIgphdXRob3I6ICJCaWxzdW1hIEFkZW1hIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDogCiAgICBkZl9wcmludDogcGFnZWQKICAgIGNvZGVfZG93bmxvYWQ6IHllcwotLS0KCiMjIyBQcmVwYXJhdGlvbiBJbnN0cnVjdGlvbnMKCi0gQmUgc3VyZSB0byBjaGFuZ2UgdGhlIGF1dGhvciBpbiB0aGUgWUFNTCB0byB5b3VyIG5hbWUuIFJlbWVtYmVyIHRvIGtlZXAgaXQgaW5zaWRlIHRoZSBxdW90ZXMuCgotIFF1ZXN0aW9ucyB0aGF0IHJlcXVpcmUgdGhlIHVzZSBvZiBSIHdpbGwgaGF2ZSBhbiBSIGNvZGUgY2h1bmsgYmVsb3cgaXQuIAoKLSBEb3dubG9hZCB0aGUgVU5FU0NPIEluc3RpdHV0ZSBvZiBTdGF0aXN0aWNzIGRhdGFzZXQgb24gZ2xvYmFsIHN0dWRlbnQgdG8gdGVhY2hlciByYXRpb3MgKHRpdGxlZCAqc3R1ZGVudF90ZWFjaGVyX3JhdGlvLmNzdiopIGZyb20gdGhlIENhbnZhcyBwYWdlIGZvciB0aGlzIGFzc2lnbm1lbnQgYW5kIHNhdmUgdGhpcyBmaWxlIHRvIHRoZSBmb2xkZXIgd2hlcmUgdGhlIFJNRCBmaWxlIGlzIGxvY2F0ZWQuIAoKLSBSZW1lbWJlciB0byBjaGFuZ2UgdGhlIGZpbGVwYXRoIGxvY2F0aW9uIGluIHRoZSBgcmVhZC5jc3YoKWAgZnVuY3Rpb24gdG8gd2hlcmUgdGhlICouY3N2KiBkYXRhc2V0IGlzIGxvY2F0ZWQgb24geW91ciBjb21wdXRlci4gWW91IGNhbiBmaW5kIHRoZSBmaWxlcGF0aCBieSB1c2luZyB0aGUgYGZpbGUuY2hvb3NlKClgIGZ1bmN0aW9uLgoKLSBTdGFydGluZyB3aXRoIHRoaXMgYXNzaWdubWVudCwgdGhlcmUgd2lsbCBiZSBsZXNzIGhhbmQtaG9sZGluZyB0aHJvdWdoIHRoZSBhbmFseXNpcyBwcm9jZXNzLgogICAgLSBUaGUgcGFja2FnZXMgdGhhdCBuZWVkIHRvIGJlIGxvYWRlZCB3aWxsIG5vIGxvbmdlciBiZSBwcm92aWRlZCBpbiB0aGUgc2V0dXAgY29kZSBjaHVuay4gWW91IGFyZSByZXNwb25zaWJsZSBmb3IgbG9hZGluZyB0aGUgYXBwcm9wcmlhdGUgcGFja2FnZXMgZm9yIHRoZSBhc3NpZ25tZW50LgogICAgLSBRdWVzdGlvbnMgb24gZXhhbWluaW5nIHRoZSBkYXRhIHdpbGwgbm8gbG9uZ2VyIGJlIHByb3ZpZGVkLiBZb3UgYXJlIHJlc3BvbnNpYmxlIGZvciBnZXR0aW5nIGEgc2Vuc2Ugb2YgdGhlIGRhdGEgcHJpb3IgdG8gY29tcGxldGluZyB0aGUgYW5hbHlzZXMuIAogICAgLSBSZW1lbWJlciB0byBjaGFuZ2UgdGhlIGZpbGVwYXRoIGxvY2F0aW9uIGluIHRoZSBgcmVhZC5jc3YoKWAgZnVuY3Rpb24gdG8gd2hlcmUgdGhlICouY3N2KiBkYXRhc2V0IGlzIGxvY2F0ZWQgb24geW91ciBjb21wdXRlciwgYW5kIHRoZW4geW91IGNhbiBkZWxldGUgdGhlIGAjYCBhdCB0aGUgc3RhcnQgb2YgbGluZSAyNi4KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KGdncmlkZ2VzKQpsaWJyYXJ5KHBhbGV0dGVlcikKCnN0dWRlbnRfdGVhY2hlcjwtcmVhZC5jc3YoIi9Vc2Vycy9iaWxzdW1hYWRlbWEvRG9jdW1lbnRzL1IgQ291cnNlIENsYXNzIDIwMjUvc3R1ZGVudF90ZWFjaGVyX3JhdGlvLmNzdiIsIGhlYWRlcj1UUlVFKQoKYGBgCgojIyMjIFRIRSBEQVRBU0VUCgpGb3IgdGhpcyBDaGFsbGVuZ2UgUHJvYmxlbSBhc3NpZ25tZW50LCB5b3UgYXJlIGdvaW5nIHRvIGJlIHVzaW5nIHRoZSBVTkVTQ08gSW5zdGl0dXRlIG9mIFN0YXRpc3RpY3MgZGF0YXNldCBvbiBnbG9iYWwgc3R1ZGVudCB0byB0ZWFjaGVyIHJhdGlvcy5eW1NvdXJjZTogW1RpZHkgVHVlc2RheSBkYXRhc2V0IGZyb20gTWF5IDcsIDIwMTldKGh0dHBzOi8vZ2l0aHViLmNvbS9yZm9yZGF0YXNjaWVuY2UvdGlkeXR1ZXNkYXkvdHJlZS9tYXN0ZXIvZGF0YS8yMDE5LzIwMTktMDUtMDcpLl0gIFRoZSBkYXRhIGluY2x1ZGVzIGVkdWNhdGlvbmFsIGluZm9ybWF0aW9uIGF0IHRoZSBjb3VudHJ5LWxldmVsLiBUaGUgb3JpZ2luYWwgZG9jdW1lbnRhdGlvbiBmb3IgdGhpcyBkYXRhc2V0IGNhbiBiZSBmb3VuZCBvbiBpdHMgW1RpZHkgVHVlc2RheSBwYWdlXShodHRwczovL2dpdGh1Yi5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5L3RyZWUvbWFzdGVyL2RhdGEvMjAxOS8yMDE5LTA1LTA3KS4gTm90ZSB0aGF0IHRoZSBUaWR5IFR1ZXNkYXkgZGF0YSBoYXMgYmVlbiBtZXJnZWQgd2l0aCBhbm90aGVyIGRhdGFzZXQgc28gdGhhdCBpdCBhbHNvIGNvbnRhaW5zIHJlZ2lvbiBpbmZvcm1hdGlvbjogCgotIGByZWdpb25gOiBDb250aW5lbnQvcmVnaW9uIG5hbWUKCi0gYHN1Yi5yZWdpb25gOiBTdWItcmVnaW9uIG5hbWUKCi0gYHJlZ2lvbi5jb2RlYDogQ29udGluZW50L3JlZ2lvbiBjb2RlCgotIGBzdWIucmVnaW9uLmNvZGVgOiBTdWItcmVnaW9uIGNvZGUKCgpUaGUgZ29hbCBvZiB0aGlzIGFzc2lnbm1lbnQgaXMgdG8gdGFrZSB5b3UgdGhyb3VnaCB0aGUgcHJvY2VzcyBvZiBjcmVhdGluZyBhIGRhdGEgdmlzdWFsaXphdGlvbiBmcm9tIGEgYmFzaWMgZ2dwbG90IHRvIG9uZSB0aGF0IGlzIGFwcGVhbGluZyBhbmQgZWFzeSB0byB1bmRlcnN0YW5kLiBUaGUgcXVlc3Rpb24gb2YgaW50ZXJlc3QgZm9yIHRoaXMgYXNzaWdubWVudCBpczoKCjxwIGFsaWduPSJjZW50ZXIiPgoqKldoYXQgYXJlIHRoZSBzdHVkZW50IHRvIHRlYWNoZXIgcmF0aW9zIGluIHByaW1hcnkgZWR1Y2F0aW9uIGZvciBlYWNoIGNvbnRpbmVudC9yZWdpb24gaW4gdGhlIHdvcmxkIChleGNsdWRpbmcgQW50YXJjdGljYSkgaW4gdGhlIG1vc3QgcmVjZW50IHllYXI/IE5vdGU6IFVzZSB0aGUgbW9zdCByZWNlbnQgeWVhciB3ZSBoYXZlIGRhdGEgZm9yICplYWNoIGNvdW50cnkqICh0aGlzIG1heSBiZSBkaWZmZXJlbnQgYWNyb3NzIGNvdW50cmllcykuICoqPC9wPgoKIyMjIyBEQVRBIFZJU1VBTElaQVRJT04gRVZPTFVUSU9OCgooQCkgSXMgdGhlIGRhdGEgaW4gdGhlIGFwcHJvcHJpYXRlIGZvcm0gZm9yIGFuc3dlcmluZyB0aGUgcXVlc3Rpb24/IEV4cGxhaW4geW91ciByZWFzb25pbmcuIAoKKltIaW50czogSG93IG1hbnkgcm93cyBzaG91bGQgdGhlcmUgYmUgZm9yIGVhY2ggY291bnRyeSBpZiB5b3Ugd2FudCB0aGUgbW9zdCByZWNlbnQgeWVhcj8gV2hpY2ggZWR1Y2F0aW9uYWwgbGV2ZWwgZ3JvdXAgYXJlIHlvdSBpbnRlcmVzdGVkIGluPyBBcmUgdGhlcmUgc29tZSBjb3VudHJpZXMgd2l0aCBhIG1pc3NpbmcgdmFsdWUgZm9yIHJlZ2lvbj9dKgotIE5vLCB0aGUgZGF0YSBpcyBub3QgaW4gdGhlIGFwcHJvcHJpYXRlIGZvcm0gdG8gYW5zd2VyIHRoZSBxdWVzdGlvbi4gQ3VycmVudGx5LCB0aGVyZSBhcmUgbXVsdGlwbGUgcm93cyBmb3IgZWFjaCBjb3VudHJ5IGFuZCBmb3Igc2V2ZXJhbCBlZHVjYXRpb24gbGV2ZWxzLiBUaGUgcmVzZWFyY2ggcXVlc3Rpb24gZm9jdXNlcyBvbiB0aGUgcHJpbWFyeSBlZHVjYXRpb24gbGV2ZWwgZ3JvdXAsIHNvIHRoZSBkYXRhIHNob3VsZCBiZSB3cmFuZ2xlZCB0byByZW1vdmUgY291bnRyaWVzIHdpdGggbWlzc2luZyB2YWx1ZXMsIGZpbHRlciBmb3IgdGhlIHByaW1hcnkgZWR1Y2F0aW9uIGxldmVsIGdyb3VwLCBhbmQgaW5jbHVkZSBvbmx5IG9uZSByb3cgcGVyIGNvdW50cnkuIAoKKEApIFVzaW5nIHlvdXIgYW5zd2VyIHRvIHRoZSBwcmV2aW91cyBwcm9ibGVtLCB3cmFuZ2xlIHRoZSBkYXRhIGludG8gdGhlIGFwcHJvcHJpYXRlIGZvcm0uIEJlIHN1cmUgdG8gc2F2ZSB0aGUgd3JhbmdsZWQgZGF0YSBmcmFtZSBpbnRvIGEgbmV3IG9iamVjdC4gCgoqW0hpbnQ6IFlvdSBzaG91bGQgaGF2ZSAxNjUgb2JzZXJ2YXRpb25zIGluIHlvdXIgd3JhbmdsZWQgZGF0YSBmcmFtZS5dKgoKYGBge3J9ClNfVCA8LSBzdHVkZW50X3RlYWNoZXIgJT4lCmZpbHRlcighaXMubmEocmVnaW9uKSwgaW5kaWNhdG9yID09ICJQcmltYXJ5IEVkdWNhdGlvbiIpICU+JSAKICBncm91cF9ieShjb3VudHJ5KSAlPiUgCiAgZmlsdGVyKHllYXIgPT0gbWF4KHllYXIsIG5hLnJtID0gVFJVRSkpCgpucm93KFNfVCkKYGBgCgooQCkgQ3JlYXRlIGEgZGF0YSB2aXN1YWxpemF0aW9uIG9mIHN0dWRlbnQgdG8gdGVhY2hlciByYXRpbyBieSByZWdpb24uIAoKKltIaW50czogV2hpY2ggcGxvdCBpcyBiZXR0ZXIgZm9yIGNvbXBhcmluZyBncm91cHM6IGhpc3RvZ3JhbXMsIGJveHBsb3RzLCBvciBkZW5zaXR5IHBsb3RzPyBObyBmYWNldGluZyBhbGxvd2VkLl0qCgpgYGB7cn0KZ2dwbG90KFNfVCwgYWVzKHggPSBzdHVkZW50X3JhdGlvLCB5ID0gcmVnaW9uLCBmaWxsID0gcmVnaW9uKSkgKyAKICBnZW9tX2JveHBsb3QoKSArIAogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGFicyh4ID0gIlN0dWRlbnQgVG8gVGVhY2hlciBSYXRpbyIsIAogICAgICAgeSA9ICJSZWdpb24iLAogICAgICAgdGl0bGUgPSAiUHJpbWFyeSBFZHVjYXRpb246IFN0dWRlbnQgdG8gVGVhY2hlciBSYXRpbyBieSBSZWdpb24iKSArCiAgc2NhbGVfZmlsbF9wYWxldHRlZXJfZCgiUlNraXR0bGVCcmV3ZXI6OnNtYXJ0aWVzIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgCiAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMSkpCmBgYAoKKEApIElkZW50aWZ5IGF0IGxlYXN0IG9uZSB3YXkgdG8gaW1wcm92ZSB0aGUgdmlzdWFsaXphdGlvbiBpZiB5b3Ugd2VyZSBnb2luZyB0byBwcmVzZW50IGl0IGluIGEgcGFwZXIgb3IgaW4gYSBwcmVzZW50YXRpb24uCi0gT25lIHdheSB0byBpbXByb3ZlIHZpc3VhbGl6YXRpb24gd291bGQgYmUgdG8gaW5jb3Jwb3JhdGUgdGhlIG1lZGlhbiBvciBtZWFuIHZhbHVlcyBmb3IgZWFjaCByZWdpb24gZGlyZWN0bHkgb24gdGhlIHBsb3QsIHdoaWNoIHdvdWxkIG1ha2UgaXQgZWFzaWVyIHRvIGVzdGltYXRlIHN0dWRlbnQtdG8tdGVhY2hlciByYXRpb3MgaW4gdGhlIGRpZmZlcmVudCByZWdpb25zLiAgCgooQCkgTGV0J3MgaW1wcm92ZSB0aGUgcGxvdCB3aXRoIHRoZXNlIHN1Z2dlc3Rpb25zOiAKCiAgICAtIHJlb3JkZXIsIGluIGRlc2NlbmRpbmcgb3JkZXIsIHRoZSByZWdpb25zIGJ5IHRoZSBtZWRpYW4gb2Ygc3R1ZGVudCB0byB0ZWFjaGVyIHJhdGlvIHJhdGhlciB0aGFuIGJ5IGFscGhhYmV0aWNhbCBvcmRlciBvZiByZWdpb24gKEhJTlQ6IGlmIHJlb3JkZXJpbmcgb3V0c2lkZSBvZiBnZ3Bsb3QsIGUuZy4gdXNpbmcgdGhlIG11dGF0ZSBmdW5jdGlvbiwgbWFrZSBzdXJlIHRoZXJlIGlzIG5vIGdyb3VwaW5nIHN0cnVjdHVyZSBvbiB0aGUgZGF0YSksIAoKICAgIC0gcHV0IHRoZSByZWdpb24gdmFyaWFibGUgb24gdGhlIHktYXhpcyBhbmQgc3R1ZGVudCB0byB0ZWFjaGVyIHJhdGlvIHZhcmlhYmxlIG9uIHRoZSB4LWF4aXMsIGlmIGhhdmVuJ3QgZG9uZSBzbywgc28gbG9uZyBsYWJlbHMgY2FuIGJlIHNlZW4sICAKCiAgICAtIGN1c3RvbWl6ZSB0aGUgYXhlcyBsYWJlbHMgc28gdGhhdCB5IGhhcyBubyBsYWJlbCBhbmQgeCBoYXMgYW4gbWVhbmluZ2Z1bCBsYWJlbCwgYW5kIAoKICAgIC0gY2hvb3NlIHRoZSBjbGFzc2ljIHRoZW1lIGZvciB0aGUgcGxvdC4KCmBgYHtyfQpTX1QgPC0gU19UICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUocmVnaW9uID0gZmN0X3Jlb3JkZXIocmVnaW9uLCBzdHVkZW50X3JhdGlvLCAuZnVuID0gbWVkaWFuLCAuZGVzYyA9IFRSVUUpKQoKZ2dwbG90KFNfVCwgYWVzKHggPSBzdHVkZW50X3JhdGlvLCB5ID0gcmVnaW9uLCBmaWxsID0gcmVnaW9uKSkgKyAKICBnZW9tX2JveHBsb3QoKSArIAogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGFicyh4ID0gIlN0dWRlbnQgVG8gVGVhY2hlciBSYXRpbyIsIAogICAgICAgeSA9IE5VTEwsCiAgICAgICB0aXRsZSA9ICJQcmltYXJ5IEVkdWNhdGlvbjogU3R1ZGVudCB0byBUZWFjaGVyIFJhdGlvIGJ5IFJlZ2lvbiIpICsKICBzY2FsZV9maWxsX3BhbGV0dGVlcl9kKCJSU2tpdHRsZUJyZXdlcjo6c21hcnRpZXMiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAxKSkKYGBgCgoqKkVkdWNhdGlvbmFsIE5vdGU6IElmIHRoaXMgdmlzdWFsaXphdGlvbiB3YXMgZm9yIGEgcGFwZXIgb3IgYSBwcmVzZW50YXRpb24sIHlvdSBjb3VsZCBzdG9wIGFmdGVyIHRoaXMgcGxvdC4gSG93ZXZlciwgeW91IGNvdWxkIGFkZCB0aGUgcmF3IGRhdGEgdG8gdGhlIHBsb3QgdG8gc2hvdyBtb3JlIGRldGFpbCBmb3IgZWFjaCByZWdpb24uKioKCihAKSBMZXQncyBpbmNsdWRlIG11bHRpcGxlIGdlb21zIHRvIHByb3ZpZGUgZXZlbiBtb3JlIGluZm9ybWF0aW9uIGluIG9uZSBwbG90OiAKCiAgICAtIHVzZSB0aGUgYXJndW1lbnQgdG8gcmVtb3ZlIG91dGxpZXJzIGluIHRoZSBvcmlnaW5hbCBnZW9tIChOT1RFOiBwcm9jZWVkIHZlcnkgY2FyZWZ1bGx5IGlmIGRvaW5nIHRoaXMgaW4gcHJhY3RpY2UhIFRoaXMgaXMgZmluZSBoZXJlIGJlY2F1c2Ugd2UgYXJlIGFib3V0IHRvIHB1dCBhbGwgdGhlIHBvaW50cyBvbiB0aGUgcGxvdCwgaW5jbHVkaW5nIHRoZXNlKSwgCiAgICAKICAgIC0gbW9kaWZ5IHRoZSBjb2xvciBvZiB0aGUgb3JpZ2luYWwgZ2VvbSB0byBgZ3JheTYwYCwgCiAgICAKICAgIC0gYWRkIGFub3RoZXIgZ2VvbSBsYXllciBvZiBqaXR0ZXJlZCBwb2ludHMgdGhhdCBpcyBjb2xvcmVkIGJ5IHJlZ2lvbiBhbmQgc2VtaS10cmFuc3BhcmVudCwgYW5kIAogICAgCiAgICAtIHJlbW92ZSB0aGUgbGVnZW5kLgoKKltOb3RlOiBDaG9vc2UgYSBjb2xvciBwYWxldHRlIHRoYXQgeW91IHRoaW5rIGlzIHZpc3VhbGx5IHBsZWFzaW5nLl0qCgpgYGB7cn0KIyNTZXR0aW5nIHRoZSBzZWVkIHNvIHRoYXQgdGhlIHNhbWUgaml0dGVyZWQgcGxvdCBpcyByZXByb2R1Y2VkIGluc3RlYWQgb2YgYWx3YXlzIGhhdmluZyByYW5kb20gcG9pbnRzIApzZXQuc2VlZCgyMDIxMTAyNikKZ2dwbG90KFNfVCwgYWVzKHggPSBzdHVkZW50X3JhdGlvLCB5ID0gcmVnaW9uLCBmaWxsID0gcmVnaW9uKSkgKyAKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BLCBmaWxsID0gImdyYXk2MCIpICsgCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yID0gcmVnaW9uKSwgc2l6ZSA9IDIsIGFscGhhID0gMC4xKSArIAogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGFicyh4ID0gIlN0dWRlbnQgVG8gVGVhY2hlciBSYXRpbyIsIAogICAgICAgeSA9IE5VTEwsCiAgICAgICB0aXRsZSA9ICJQcmltYXJ5IEVkdWNhdGlvbjogU3R1ZGVudCB0byBUZWFjaGVyIFJhdGlvIGJ5IFJlZ2lvbiIpICsKICBzY2FsZV9jb2xvcl9wYWxldHRlZXJfZCgiUlNraXR0bGVCcmV3ZXI6OnNtYXJ0aWVzIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgCiAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMSkpCmBgYAoKKipFZHVjYXRpb25hbCBOb3RlOiBZb3UgbWlnaHQgYWRkIHRoZSByYXcgZGF0YSB0byB0aGUgdmlzdWFsaXphdGlvbiB0byBpZGVudGlmeSBnYXBzIGluIGVhY2ggcmVnaW9uIChlLmcuLCBnYXAgaW4gT2NlYW5pYSkgb3IgdG8gaWRlbnRpZnkgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBwZXIgcmVnaW9uLioqCgooQCkgTGV0J3Mgc3VwcG9zZSB5b3UgZGVjaWRlIHRoYXQgeW91IHdhbnQgdG8gc2hvdyB0aGUgZGlzdHJpYnV0aW9uIHVzaW5nIHZpb2xpbiBwbG90cyBpbnN0ZWFkIG9mIGJveGVzIGFuZCB5b3UgYWxzbyB3YW50IHRvIGFkZCBhIGxhcmdlciBkb3QgZm9yIHRoZSBtZWFuIG9mIHN0dWRlbnQgdG8gdGVhY2hlciByYXRpbyBieSByZWdpb246IAoKICAgIC0gYWRkIGEgY29sdW1uIHRvIHRoZSBkYXRhIGZyYW1lIHRoYXQgY29tcHV0ZXMgdGhlIG1lYW4gb2Ygc3R1ZGVudCB0byB0ZWFjaGVyIHJhdGlvIGJ5IHJlZ2lvbiwgCiAgICAKICAgIC0gY3JlYXRlIGEgZGF0YSB2aXN1YWxpemF0aW9uIHdpdGggdGhlIGppdHRlcmVkIHBvaW50cyAoYXMgY3JlYXRlZCBwcmV2aW91c2x5KSwgdmlvbGluIGdlb20sIGFuZCB0aGUgb3RoZXIgY3VzdG9taXphdGlvbnMgKGUuZy4sIG1vZGlmaWVkIGF4ZXMgbGFiZWxzLCBubyBsZWdlbmQpLCBhbmQgCiAgICAKICAgIC0gYWRkIGEgbGFyZ2VyIHBvaW50IGZvciB0aGUgbWVhbiBvZiBzdHVkZW50IHRvIHRlYWNoZXIgcmF0aW8gYnkgcmVnaW9uLiBCZSBzdXJlIHRoYXQgdGhlIGFkZGVkIHBvaW50IGlzIGNvbG9yZWQgYnkgcmVnaW9uLgogICAgCipbTm90ZTogVGhpbmsgYWJvdXQgdGhlIG9yZGVyaW5nIG9mIHRoZSBnZW9tcyB3aGVuIGNyZWF0aW5nIHRoZSBwbG90Ll0qCgpgYGB7cn0Kc2V0LnNlZWQoMjAyMTEwMjYpCm1lYW5fU19UIDwtIFNfVCAlPiUgCiAgZ3JvdXBfYnkocmVnaW9uKSAlPiUKICBtdXRhdGUoU1RfbWVhbiA9IG1lYW4oc3R1ZGVudF9yYXRpbywgbmEucm0gPSBUUlVFKSkgJT4lCiAgdW5ncm91cCgpCgpnZ3Bsb3QobWVhbl9TX1QsIGFlcyh4ID0gc3R1ZGVudF9yYXRpbywgeSA9IHJlZ2lvbiwgZmlsbCA9IHJlZ2lvbikpICsgCiAgZ2VvbV92aW9saW4oKSsgCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yID0gcmVnaW9uKSwgc2l6ZSA9IDIsIGFscGhhID0gMC4xKSArIAogIGdlb21fcG9pbnQoYWVzKHggPSBTVF9tZWFuLCBjb2xvciA9IHJlZ2lvbiksIHNpemUgPSAzKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBsYWJzKHggPSAiU3R1ZGVudCBUbyBUZWFjaGVyIFJhdGlvIiwgCiAgICAgICB5ID0gTlVMTCwKICAgICAgIHRpdGxlID0gIlByaW1hcnkgRWR1Y2F0aW9uOiBTdHVkZW50IHRvIFRlYWNoZXIgUmF0aW8gTWVhbiBieSBSZWdpb24iKSArCiAgc2NhbGVfY29sb3JfcGFsZXR0ZWVyX2QoIlJTa2l0dGxlQnJld2VyOjpzbWFydGllcyIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LCBmYWNlID0gImJvbGQiLCBoanVzdCA9IDEpKQpgYGAKCihAKSBMZXQncyBhZGQgYSB2ZXJ0aWNhbCBsaW5lIHRvIHJlbGF0ZSB0aGVzZSBwb2ludHMgdG8gYSBiYXNlbGluZSAod29ybGR3aWRlIGF2ZXJhZ2UpOiAKCiAgICAtIGFkZCBhIHZlcnRpY2FsIGxpbmUgYXQgdGhlIGxvY2F0aW9uIG9mIHRoZSBtZWFuIHN0dWRlbnQgdG8gdGVhY2hlciByYXRpbyBmb3IgYWxsIG9mIHRoZSBjb3VudHJpZXMgYW5kIGNvbG9yIGl0IGBncmF5NzBgLiAKCipbTm90ZTogVXNlIG9ubGluZSByZXNvdXJjZXMgKGUuZy4sIFtTVEhEQV0oaHR0cDovL3d3dy5zdGhkYS5jb20vZW5nbGlzaC93aWtpL2dncGxvdDItYWRkLXN0cmFpZ2h0LWxpbmVzLXRvLWEtcGxvdC1ob3Jpem9udGFsLXZlcnRpY2FsLWFuZC1yZWdyZXNzaW9uLWxpbmVzKSkgZm9yIGhvdyB0byBjcmVhdGUgYSB2ZXJ0aWNhbCBsaW5lIGluIHRoZSBwbG90Ll0qCiAgICAKYGBge3J9CnNldC5zZWVkKDIwMjExMDI2KQptZWFuX2dsb2JhbCA8LSBtZWFuKFNfVCRzdHVkZW50X3JhdGlvLCBuYS5ybSA9IFRSVUUpCgpnZ3Bsb3QobWVhbl9TX1QsIGFlcyh4ID0gc3R1ZGVudF9yYXRpbywgeSA9IHJlZ2lvbiwgZmlsbCA9IHJlZ2lvbikpICsgCiAgZ2VvbV92aW9saW4oKSsgCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yID0gcmVnaW9uKSwgc2l6ZSA9IDIsIGFscGhhID0gMC4xKSArIAogIGdlb21fcG9pbnQoYWVzKHggPSBTVF9tZWFuLCBjb2xvciA9IHJlZ2lvbiksIHNpemUgPSAzKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVhbl9nbG9iYWwsIGNvbG9yID0gImdyYXk3MCIsIGxpbmV3aWR0aCA9IDEuNSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGFicyh4ID0gIlN0dWRlbnQgVG8gVGVhY2hlciBSYXRpbyIsIAogICAgICAgeSA9IE5VTEwsCiAgICAgICB0aXRsZSA9ICJQcmltYXJ5IEVkdWNhdGlvbjogU3R1ZGVudCB0byBUZWFjaGVyIFJhdGlvIE1lYW4gYnkgUmVnaW9uIikgKwogIHNjYWxlX2NvbG9yX3BhbGV0dGVlcl9kKCJSU2tpdHRsZUJyZXdlcjo6c21hcnRpZXMiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAxKSkKCmBgYAoKCihAKSBMYXN0bHksIGxldCdzIGFkZCBhIG1lYW5pbmdmdWwgdGl0bGUsIHN1YnRpdGxlLCBjYXB0aW9uLCBhbmQgdGV4dCBhbm5vdGF0aW9ucyBzbyB0aGUgcGxvdCBzcGVha3MgZm9yIGl0c2VsZjogCgogICAgLSBhZGQgYSBtZWFuaW5nZnVsIHRpdGxlIGZvciB0aGUgcGxvdCwgCiAgICBhbnkKICAgIC0gYWRkIGEgbWVhbmluZ2Z1bCBzdWJ0aXRsZSB0aGF0IHN1bW1hcml6ZXMgdGhlIHBsb3QgKHlvdSBtYXkgbmVlZCB0byB1c2UgYFxuYCBpbiB5b3VyIGxhYmVsIHRvIGFkZCBhIG5ldyBsaW5lIGlmIGhhdmUgYSBsb25nIHN1YnRpdGxlKSwgCiAgICAKICAgIC0gYWRkIG9uZSBtZWFuaW5nZnVsIHRleHQgYW5ub3RhdGlvbiBmb3IgZWFjaCBnZW9tIGluIHRoZSBwbG90IFsoKip0aGlzIGxpbmsgaXMgYSBnb29kIHJlc291cmNlKiopXShodHRwOi8vd3d3LnN0aGRhLmNvbS9lbmdsaXNoL3dpa2kvZ2dwbG90Mi10ZXh0cy1hZGQtdGV4dC1hbm5vdGF0aW9ucy10by1hLWdyYXBoLWluLXItc29mdHdhcmUjOn46dGV4dD1nZW9tX2xhYmVsKCklM0ElMjBkcmF3cyUyMGElMjByZWN0YW5nbGUscGFydGljdWxhciUyMGxvY2F0aW9uJTIwb24lMjB0aGUlMjBwbG90KSwgYW5kIAogICAgCiAgICAtIGFkZCBhIG1lYW5pbmdmdWwgY2FwdGlvbiBkZXNjcmliaW5nIHRoZSBvcmlnaW5hbCBzb3VyY2Ugb2YgdGhlIGRhdGFzZXQuCgpgYGB7ciwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9NSwgZHBpPTMwMH0Kc2V0LnNlZWQoMjAyMTEwMjYpCmdncGxvdChtZWFuX1NfVCwgYWVzKHggPSBzdHVkZW50X3JhdGlvLCB5ID0gcmVnaW9uLCBmaWxsID0gcmVnaW9uKSkgKyAKICBnZW9tX3Zpb2xpbigpKyAKICBnZW9tX2ppdHRlcihhZXMoY29sb3IgPSByZWdpb24pLCBzaXplID0gMiwgYWxwaGEgPSAwLjEpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IFNUX21lYW4sIGNvbG9yID0gcmVnaW9uKSwgc2l6ZSA9IDMpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuX2dsb2JhbCwgY29sb3IgPSAiZ3JheTcwIiwgbGluZXdpZHRoID0gMS41KSArCiBhbm5vdGF0ZSgidGV4dCIsIHggPSA0NCwgeSA9ICJPY2VhbmlhIiwgCiAgICAgICAgICAgIGxhYmVsID0gIkFmcmljYSBoYWQgdGhlIGhpZ2hlc3QgZGlzdHJpYnV0aW9uIG9mIHN0dWRlbnQgdG8gdGVhY2hlciByYXRpbyIsIAogICAgICAgICAgICBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzLjUsIGhqdXN0ID0gMCwgdmp1c3QgPSAtMC45OCkgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDM3LCB5ID0gIlNvdXRoIEFtZXJpY2EiLCAKICAgICAgICAgICBsYWJlbCA9ICJFYWNoIHNlbWktdHJhbnNwYXJlbnQgZG90IHJlcHJlc2VudCBhIGNvdW50cnkiLCAKICAgICAgICAgICBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzLjUsIGhqdXN0ID0gMC4wNSwgdmp1c3QgPSAtMC41KSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMzUsIHkgPSAiRXVyb3BlIiwgCiAgICAgICAgICAgbGFiZWwgPSAiQ29sb3JlZCBjaXJjbGVzIGluIGJhcnBsb3RzIHJlcHJlc2VudCB0aGUgcmVnaW9uYWwgc3R1ZGVudCB0byB0ZWFjaGVyIG1lYW4iLCAKICAgICAgICAgICBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzLjUsIGhqdXN0ID0gMC4sIHZqdXN0ID0gLTAuNSkgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDM1LCB5ID0gIk5vcnRoIEFtZXJpY2EiLCAKICAgICAgICAgICBsYWJlbCA9ICJUaGUgZ3JheSBsaW5lIHJlcHJlc2VudHMgdGhlIGdsb2JhbCBzdHVkZW50IHRvIHRlYWNoZXIgcmF0aW8gbWVhbiIsIAogICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMuNSwgaGp1c3QgPSAwLCB2anVzdCA9IC0wLjgpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxhYnMoeCA9ICJTdHVkZW50IFRvIFRlYWNoZXIgUmF0aW8iLCAKICAgICAgIHkgPSBOVUxMLAogICAgICAgdGl0bGUgPSAiUHJpbWFyeSBFZHVjYXRpb246IFN0dWRlbnQgdG8gVGVhY2hlciBSYXRpbyBNZWFuIGJ5IFJlZ2lvbiIsCiAgICAgICBzdWJ0aXRsZSA9ICJUaGUgYmFycGxvdCByZXByZXNlbnRzIHJlZ2lvbmFsIHN0dWRlbnQgdG8gdGVhY2hlciByYXRpbyBhbmQgaW5kaWNhdGVzIHRoZSBoaWdoZXN0IG1lYW4gaW4gQWZyaWNhIGFuZCB0aGUgbG93ZXN0IG1lYW4gaW4gRXVyb3BlIiwKICAgICAgIGNhcHRpb24gPSAiU291cmNlOlVORVNDTyBJbnN0aXR1dGUgb2YgU3RhdGlzdGljcyAoVGlkeSBUdWVzZGF5IE1heSA3LCAyMDE5IikgICsKICBzY2FsZV9jb2xvcl9wYWxldHRlZXJfZCgiUlNraXR0bGVCcmV3ZXI6OnNtYXJ0aWVzIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgCiAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMSksCiAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgaGp1c3QgPSAxKSwKICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgsIGZhY2UgPSAiaXRhbGljIiwgaGp1c3QgPSAwLjUpKQogICAgICAgCmBgYAoKKipDSEFMTEVOR0UgKG9wdGlvbmFsKSoqOiBBbm90aGVyIHBhcnQgb2YgRURBIGlzIHRvIGlkZW50aWZ5IGludGVyZXN0aW5nIG9yIHJlbGV2YW50IHBvaW50cyBvbiB0aGUgcGxvdC4gVXNpbmcgdGhlIGBnZW9tX2xhYmVsX3JlcGVsKClgIGZ1bmN0aW9uIGZyb20gdGhlIGB7Z2dyZXBlbH1gIHBhY2thZ2UsIGRlbm90ZSB0aGUgY291bnRyaWVzIHRoYXQgaGF2ZSB0aGUgc21hbGxlc3QgcmF0aW8gd2l0aCBhIGdyZWVuIGxhYmVsIG9uIHRoZSBwbG90IGFuZCBkZW5vdGUgdGhlIGNvdW50cmllcyB0aGF0IGhhdmUgdGhlIGxhcmdlc3QgcmF0aW8gd2l0aCBhIHJlZCBsYWJlbCBvbiB0aGUgcGxvdC4KCmBgYHtyfQpzZXQuc2VlZCgyMDIxMTAyNikKCmBgYA==