Muddiest point?

Grammar of Graphics

Grammar of Graphics

  1. Address research questions: build intuition and note preliminary observations/conclusions related to each research question. Also, note observations that prompt you to refine your research questions or add new questions to investigate

Glyphs and Data

In archaeology, a GLYPH is a symbol or “mark” used to impart meaning:

HeiroGLYPH Mayan GLYPH
Heiroglyph Mayan glyph

Data Glyph

A data glyph is also a “mark” on a graph, e.g. 

The features of a data glyph encodes the value of variables.

  • Some are very simple, e.g. a dot:
  • Some combine different elements, e.g. a pointrange:
  • Some are more complex, e.g. a violin:

See: http://docs.ggplot2.org/current/

“Aesthetic”?

Q: In general, what’s your intuition about the meaning of aesthetic?

Data Glyph Properties: Aesthetics

Aesthetics are visual properties of a glyph.

Some Graphics Components

glyph

  • The basic graphical unit often corresponding to one case.
  • Other terms used include mark and symbol.

aesthetic

  • a visual property of a glyph such as position, size, shape, color, etc.
  • may be mapped based on data values: sex is mapped to color
  • may be set to particular non-data related values: color is black

scale

  • A mapping that translates data values into aesthetics. For example,
  • A scatter plot of health risks may identify cigarette smoking:
    • blue represents “No”
    • red represents “Yes”
  • A printed map of campus uses a scaled representation of distance
    • a centimeter on the printed map represents 100 meters of distance on campus

frame

  • The position scale describing how data are mapped to the coordinate system in use
  • Quite often, the frame defines the x-axis and y-axis of a 2-dimensional cartesian plane

guide

  • An indication for the human viewer of the scale. This allows the viewer to translate aesthetics back into data values.
  • For example,
    • a legend makes explicit the meaning of Red & Blue points on the chart
    • a 1 cm length printed on a map to inform the reader that it corresponds to 100 meters on campus

Scales

The relationship between the variable value and the value of the aesthetic the variable is mapped to.

  • Systolic Blood Pressure (SBP) has units of mmHg (millimeters of mercury)
  • Position on the x-axis measured in distance, e.g. inches.

The conversion from SBP to position is a scale.

  • Smoker is “never”, “former”, “current”
  • Color is red, green, blue, …

The conversion from Smoker to color is a scale.

Guides

Guide: an indication to a human viewer of what the scale is.

  • Axis ticks and numbers

  • Legends

  • Labels on faceted graphics

Facets

ggplot(data = Tmp, aes(x = sbp, y = dbp, color = smoker)) +
  geom_point() +
  facet_grid( ~ sex)

Designing Graphics

Graphics are designed by the human expert (you!) in order to reveal information that’s present in the data.

Design choices

  • What kind of glyph, e.g. scatter, density, bar, … many others
  • What variables constitute the frame. And some details:
    • axis limits
    • logarithmic axes, etc.
  • What variables should be mapped to other aesthetics of the glyph.
  • Whether to facet and with what variable.

More details, …, e.g. setting of aesthetics to constants

Good and Bad Graphics

Remember …

Graphics are designed by the human expert (you!) in order to reveal information that’s present in the data.

Critique this graphic…

p + geom_point(aes(color = sex, size = smoker), alpha = .85) 

Perception and Comparison

In roughly descending order of human ability to compare nearby objects:

  1. Position
  2. Length
  3. Area
  4. Angle
  5. Shape (but only a very few different shapes)
  6. Color

Color is the most difficult…

For more, see:

Cleveland W. (1985). The elements of graphing data. Bell Telephone Laboratories: Murray Hill, NJ.

Glyph-Ready Data

Glyph-ready data has this form:

Glyph-ready data

Mapping of data to aesthetics

   sbp is mapped to x position      
   dbp is mapped to y position    
smoker is mapped to color
   sex is mapped to shape

Scales determine details of translation from

variable is mapped to aesthetic

Layers – building up complex plots

Each layer may have its own data, glyphs, aesthetic mapping, etc.

ggplot(data = Tmp, aes(x = sbp, y = dbp, colour = sex)) +
  geom_point() +
  geom_smooth(se = FALSE) 

Stats: Data Transformations

ggplot(data = Tmp, aes(x = sbp)) +
  geom_histogram(binwidth = 10)

head(Tmp, 4)

Challenge Task

Source: “College, the Great Unleveler”, New York Times, 03-01-2014

Left Panel Questions:

  • Left panel: What variables make up the frame?
  • Left panel: What are the guides?
  • Left panel: What are the glyphs and what do they represent?
  • Left panel: Sketch a few rows of the glyph-ready data.

Right Panel Questions:

  • Right panel: What are the glyphs and what do they represent?
  • Right panel: Describe three aesthetics mapped to the glyphs?
  • Right panel: Sketch a few rows of the glyph-ready data.
  • Right panel: Make a rough sketch of a stacked bar chart showing the same information.

Partial Solution to Challenge Task

Left Panel Questions:

  • Left panel frame: Fraction of family income to pay for one year of college, and year.
  • Left panel guides:
    • Labels for the different quintiles of family income.
    • A line scaling the axis, showing where the fraction of family income is 100%.
    • Text to label the extent of the horizontal axis, from 1971 to 2010.
  • Left panel glyphs:
    • Points representing fraction of income
    • Lines connecting 1971 result to 2011 result
  • Left panel: Sketch a few rows of the glyph-ready data.

Right Panel Questions:

  • Right panel glyphs: segments of the circles
  • Right panel three aesthetics: color, length, size (i.e., radius of circle)
  • Right panel: Sketch a few rows of the glyph-ready data.
  • Right panel: Make a rough sketch of a stacked bar chart showing the same information.

Path to success

  1. Eye-training

    • recognize and describe glyphs, aesthetics, scales, etc.
    • identify data required for a plot
  2. Data wrangling

    • get data into glyph-ready format (dplyr, tidyr, tidyverse)
    • (we’ll start doing this next week!)
  3. Graphics construction

    • Newbies: match variables to aesthetics interactively:
      • esquisse package using esquisser( )
      • mosaic package using mplot( )
      • BOTH generate ggplot2 syntax
    • Pros: learn to write ggplot2 code directly

Revisiting The Big Mac Index

https://github.com/rfordatascience/tidytuesday/tree/master/data/2020/2020-12-22

# These data are available from the `tidytuesdayR` package 
# Install package from CRAN via: install.packages("tidytuesdayR")

library(tidytuesdayR)

TidyTuesData <- tidytuesdayR::tt_load(2020, week = 52)

    Downloading file 1 of 1: `big-mac.csv`
BigMac <- TidyTuesData[["big-mac"]]

Big Mac Price vs GPD per Capita?

Let’s use the esquisse package to explore the data!

In the console:

esquisser(BigMac)

library(esquisse)

# use `esquisser( )` to draft a plot and then generate R code to put here!

Here’s an example:

  • Using the graph, what can you say about the following?
    • Frame
    • Glyph
    • Aesthetic
    • Scale
    • Guide
    • Facet

Value of Big Mac around the world

# using `mWorldMap( )` from `mosaic` package
library(mosaic)

# `key` argument takes the ID variable; `fill` takes the measured variable 
mWorldMap(BigMac, key = "iso_a3", fill = "dollar_price")
Mapping API still under development and may change in future releases.
Warning: 33 items were not translated

LS0tCnRpdGxlOiAiV2VlayA0OiBHcmFwaGljcywgR2x5cGhzLCBGcmFtZXMsIGFuZCBTY2FsZXMiCnN1YnRpdGxlOiAiRGF0YSBDb21wdXRpbmcgQ2hhcHRlcnMgNSAmIDYiCmF1dGhvcjogIlByb2YgQmVja21hbiIKZGF0ZTogIiIKb3V0cHV0OiAKICAgIHNsaWR5X3ByZXNlbnRhdGlvbjogZGVmYXVsdAogICAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAoKLS0tCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KG1vc2FpYykKbGlicmFyeShOSEFORVMpCmxpYnJhcnkoZGNEYXRhKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShlc3F1aXNzZSkKCmBgYAoKIyMgTXVkZGllc3QgcG9pbnQ/CgoKCiMjIEdyYW1tYXIgb2YgR3JhcGhpY3MKCi0gTG90cyBvZiBuZXcgdGVybWlub2xvZ3kgdGhpcyB3ZWVrCi0gQ2FuIHlvdSBkZXNjcmliZSBlYWNoIG9mIHRoZXNlIHRlcm1zPwogICAgLSBGcmFtZQogICAgLSBHbHlwaAogICAgLSBBZXN0aGV0aWMKICAgIC0gU2NhbGUKICAgIC0gR3VpZGUKICAgIC0gRmFjZXQKCgojIyBHcmFtbWFyIG9mIEdyYXBoaWNzCgotIFdpbGtpbnNvbidzIDIwMDUgYm9vayAqVGhlIEdyYW1tZXIgb2YgR3JhcGhpY3MgKDJuZCBFZC4pKiBwcm92aWRlcyB0aGUgcHJpbmNpcGxlcyBhbmQgcGhpbG9zb3BoeSAKICAgIC0gdGhlIGBnZ3Bsb3QyYCBSIHBhY2thZ2UgaW1wbGVtZW50cyB0aGlzIGZyYW1ld29yawogICAgLSAqKkdvYWwqKjogZmxleGlibGUgdG9vbHMgZm9yIGJ1aWxkaW5nIHJpY2gsIGludHVpdGl2ZSBncmFwaGljcwoKLSBEYXRhIFZpc3VhbGl6YXRpb24gaXMgY3JpdGljYWwgdG8gb3VyIGdvYWxzIGZvciBoaWdoIHF1YWxpdHkgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcyAoRURBKQogICAgMS4gKipFeGFtaW5lIHRoZSBkYXRhIHNvdXJjZToqKiB2YXJpYWJsZSB0eXBlcywgY29kaW5nLCBtaXNzaW5nbmVzcywgc3VtbWFyeSBzdGF0aXN0aWNzL3Bsb3RzLCB3aG8vd2hhdC93aGVuL3doZXJlL3doeS9ob3cgZGF0YSB3ZXJlIGNvbGxlY3RlZAogICAgMi4gKipEaXNjb3ZlciBmZWF0dXJlcyB0aGF0IGluZmx1ZW5jZSBtYXkgbW9kZWxpbmcgZGVjaXNpb25zOioqIGludmVzdGlnYXRlIHBvdGVudGlhbCBvdXRsaWVycywgY29uc2lkZXJhdGlvbiBmb3IgcmVjb2RpbmcgdmFyaWFibGVzIChlLmcuLCBudW1lcmljIGRhdGEgdGhhdCdzIGZ1bmN0aW9uYWxseSBkaWNob3RvbW91cyksIGV2YWx1YXRlIGNvcnJlbGF0aW9uIHN0cnVjdHVyZSAoZS5nLiwgYXV0b2NvcnJlbGF0aW9uLCBoaWVyYXJjaHksIHNwYXRpYWwvdGVtcG9yYWwgcHJveGltaXR5KQozLiAqKkFkZHJlc3MgcmVzZWFyY2ggcXVlc3Rpb25zOioqIGJ1aWxkIGludHVpdGlvbiBhbmQgbm90ZSBwcmVsaW1pbmFyeSBvYnNlcnZhdGlvbnMvY29uY2x1c2lvbnMgcmVsYXRlZCB0byBlYWNoIHJlc2VhcmNoIHF1ZXN0aW9uLiAgQWxzbywgbm90ZSBvYnNlcnZhdGlvbnMgdGhhdCBwcm9tcHQgeW91IHRvIHJlZmluZSB5b3VyIHJlc2VhcmNoIHF1ZXN0aW9ucyBvciBhZGQgbmV3IHF1ZXN0aW9ucyB0byBpbnZlc3RpZ2F0ZQoKIVtdKGdyYW1tYXJHcmFwaGljcy5wbmcpCgoKIyMgR2x5cGhzIGFuZCBEYXRhCgpJbiBhcmNoYWVvbG9neSwgYSBHTFlQSCBpcyBhIHN5bWJvbCBvciAibWFyayIgdXNlZCB0byBpbXBhcnQgbWVhbmluZzoKCkhlaXJvR0xZUEggfCBNYXlhbiBHTFlQSAotLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLToKIVtIZWlyb2dseXBoXShJbWFnZXMvaGFuZC5qcGcpIHwgIVtNYXlhbiBnbHlwaF0oSW1hZ2VzL21heWFuLWdseXBoLnBuZykgCgojIyBEYXRhIEdseXBoCgoKIyMjIEEgZGF0YSBnbHlwaCBpcyBhbHNvIGEgIm1hcmsiIG9uIGEgZ3JhcGgsIGUuZy4gCgohW10oSW1hZ2VzL2dlb21fcmVjdC5wbmcpICFbXShJbWFnZXMvZ2VvbV9zZWdtZW50LnBuZykgIVtdKEltYWdlcy9nZW9tX3RleHQucG5nKSAhW10oSW1hZ2VzL2dlb21fY3Jvc3NiYXIucG5nKSAhW10oSW1hZ2VzL2dlb21fcGF0aC5wbmcpICFbXShJbWFnZXMvZ2VvbV9saW5lLnBuZykgIVtdKEltYWdlcy9nZW9tX3BvaW50cmFuZ2UucG5nKSAhW10oSW1hZ2VzL2dlb21fcmliYm9uLnBuZykgIVtdKEltYWdlcy9nZW9tX3BvaW50LnBuZykgIVtdKEltYWdlcy9nZW9tX3BvbHlnb24ucG5nKSAhW10oSW1hZ2VzL2dlb21faGlzdG9ncmFtLnBuZykgIVtdKEltYWdlcy9nZW9tX2RvdHBsb3QucG5nKSAhW10oSW1hZ2VzL2dlb21fZnJlcXBvbHkucG5nKSAhW10oSW1hZ2VzL2dlb21fZGVuc2l0eS5wbmcpICFbXShJbWFnZXMvZ2VvbV92aW9saW4ucG5nKSAKClRoZSBmZWF0dXJlcyBvZiBhIGRhdGEgZ2x5cGggZW5jb2RlcyB0aGUgdmFsdWUgb2YgdmFyaWFibGVzLiAKCi0gU29tZSBhcmUgdmVyeSBzaW1wbGUsIGUuZy4gYSBkb3Q6ICFbXShJbWFnZXMvZ2VvbV9wb2ludC5wbmcpCi0gU29tZSBjb21iaW5lIGRpZmZlcmVudCBlbGVtZW50cywgZS5nLiBhIHBvaW50cmFuZ2U6ICFbXShJbWFnZXMvZ2VvbV9wb2ludHJhbmdlLnBuZykKLSBTb21lIGFyZSBtb3JlIGNvbXBsZXgsIGUuZy4gYSB2aW9saW46ICFbXShJbWFnZXMvZ2VvbV92aW9saW4ucG5nKQoKU2VlOiAqPGh0dHA6Ly9kb2NzLmdncGxvdDIub3JnL2N1cnJlbnQvPioKCgojIyAiQWVzdGhldGljIj8KClE6IEluIGdlbmVyYWwsIHdoYXQncyB5b3VyIGludHVpdGlvbiBhYm91dCB0aGUgbWVhbmluZyBvZiBhZXN0aGV0aWM/CgotIEhvdyBtaWdodCB5b3UgZGVzY3JpYmUgdGhlIGFlc3RoZXRpYyBvZiBhIGZhdm9yaXRlIGNvZmZlZSBzaG9wIG9yIHJlc3RhdXJhbnQ/CgoKIyMgRGF0YSBHbHlwaCBQcm9wZXJ0aWVzOiBBZXN0aGV0aWNzCgpBZXN0aGV0aWNzIGFyZSAqKnZpc3VhbCBwcm9wZXJ0aWVzKiogb2YgYSBnbHlwaC4KCiAgKiBBZXN0aGV0aWNzIGZvciBwb2ludHM6IGxvY2F0aW9uICh4IGFuZCB5KSwgc2hhcGUsIGNvbG9yLCBzaXplLCB0cmFuc3BhcmVuY3kKICAqIEVhY2ggZ2x5cGggaGFzIGl0cyBvd24gc2V0IG9mIGFlc3RoZXRpY3MuCgpgYGB7ciBlY2hvPUZBTFNFLCBmaWcua2VlcD0nYWxsJywgb3V0LndpZHRoPSI1MCUiLCBpbmNsdWRlPUZBTFNFfQpzZXQuc2VlZCgxMDIpCm4gPC0gMzAKVG1wIDwtIGRhdGEuZnJhbWUoCiAgc2JwID0gIHJvdW5kKHJ1bmlmKG4sIG1pbiA9IDgwLCBtYXggPSAxODApKSwKICBkYnAgPSByb3VuZChydW5pZihuLCBtaW4gPSA0MCwgbWF4ID0gMTEwKSksCiAgZ3JvdXAgPSBzYW1wbGUoYygiVHIiLCJDdGwiKSwgc2l6ZSA9IG4sIHJlcGxhY2UgPSBUUlVFKSwKICByZWFjdCA9IHNhbXBsZSggYygiTG93IiwgIlNldiIsICJNb2QiKSwgc2l6ZSA9IG4sIHJlcGxhY2UgPSBUUlVFKQopClRtcCA8LSBUbXAgJT4lIG11dGF0ZShkYnAgPSBwbWluKHNicCwgZGJwKSkgCnAgPC0gZ2dwbG90KFRtcCwgYWVzKHggPSBzYnAsIHkgPSBkYnApKSArIHhsYWIoIlN5c3RvbGljIEJQIikgKyB5bGFiKCJEaWFzdG9saWMgQlAiKQpwICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBncm91cCwgc2l6ZSA9IHJlYWN0KSkgCnAgKyBnZW9tX3BvaW50KHNpemUgPSA1LCBhZXMoc2hhcGUgPSBncm91cCwgY29sb3IgPSByZWFjdCkpCmBgYAoKYGBge3IgZWNobz1GQUxTRSwgZmlnLmtlZXA9J2FsbCcsIG91dC53aWR0aD0iNTAlIn0Kc2V0LnNlZWQoMTAyKQpyZXF1aXJlKE5IQU5FUykKCm4gPC0gNzUKVG1wIDwtIAogIE5IQU5FUyAlPiUKICBtdXRhdGUoCiAgICBzbW9rZXIgPSBkZXJpdmVkRmFjdG9yKAogICAgICBuZXZlciA9IFNtb2tlMTAwID09ICJObyIsCiAgICAgIGZvcm1lciA9IFNtb2tlTm93ID09ICJObyIsCiAgICAgIGN1cnJlbnQgPSBTbW9rZU5vdyA9PSAiWWVzIiwKICAgICAgLm9yZGVyZWQgPSBUUlVFCiAgICApLAogICAgc2JwID0gQlBTeXNBdmUsCiAgICBkYnAgPSBCUERpYUF2ZSwKICAgIHNleCA9IEdlbmRlcgogICkgJT4lCiAgc2VsZWN0KCBzYnAsIGRicCwgc2V4LCBzbW9rZXIgKSAlPiUKICBzYW1wbGVfbihuKSAlPiUKICBmaWx0ZXIoY29tcGxldGUuY2FzZXMoLikpICU+JSAKICBkYXRhLmZyYW1lKCkKCgpwIDwtIGdncGxvdChUbXAsIGFlcyh4ID0gc2JwLCB5ID0gZGJwKSkgKyAKICB4bGFiKCJTeXN0b2xpYyBCUCIpICsgeWxhYigiRGlhc3RvbGljIEJQIikKcCArIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gc2V4LCBzaXplID0gc21va2VyKSwgYWxwaGEgPSAuOCkgCnAgKyBnZW9tX3BvaW50KHNpemUgPSA1LCBhZXMoc2hhcGUgPSBzZXgsIGNvbG9yID0gc21va2VyKSwgYWxwaGEgPSAuOCkKYGBgCgoKCiMjIFNvbWUgR3JhcGhpY3MgQ29tcG9uZW50cwoKIyMjIyAqKmdseXBoKioKCi0gVGhlIGJhc2ljIGdyYXBoaWNhbCB1bml0IG9mdGVuIGNvcnJlc3BvbmRpbmcgdG8gb25lIGNhc2UuCi0gT3RoZXIgdGVybXMgdXNlZCBpbmNsdWRlICptYXJrKiBhbmQgKnN5bWJvbCouIAoKIyMjIyAqKmFlc3RoZXRpYyoqCgotIGEgdmlzdWFsIHByb3BlcnR5IG9mIGEgZ2x5cGggc3VjaCBhcyBwb3NpdGlvbiwgc2l6ZSwgc2hhcGUsIGNvbG9yLCBldGMuICAKLSBtYXkgYmUgKiptYXBwZWQqKiBiYXNlZCBvbiBkYXRhIHZhbHVlczogYHNleCBpcyBtYXBwZWQgdG8gY29sb3JgIAotIG1heSBiZSAqKnNldCoqIHRvIHBhcnRpY3VsYXIgbm9uLWRhdGEgcmVsYXRlZCB2YWx1ZXM6IGBjb2xvciBpcyBibGFja2AKCiMjIyMgKipzY2FsZSoqCgoqIEEgbWFwcGluZyB0aGF0IHRyYW5zbGF0ZXMgZGF0YSB2YWx1ZXMgaW50byBhZXN0aGV0aWNzLiAgRm9yIGV4YW1wbGUsCiogQSBzY2F0dGVyIHBsb3Qgb2YgaGVhbHRoIHJpc2tzIG1heSBpZGVudGlmeSBjaWdhcmV0dGUgc21va2luZzogIAogICAgLSA8Zm9udCBjb2xvcj0iYmx1ZSI+Ymx1ZTwvZm9udD4gcmVwcmVzZW50cyAiTm8iCiAgICAtIDxmb250IGNvbG9yPSJyZWQiPnJlZDwvZm9udD4gcmVwcmVzZW50cyAiWWVzIgoqIEEgcHJpbnRlZCBtYXAgb2YgY2FtcHVzIHVzZXMgYSBzY2FsZWQgcmVwcmVzZW50YXRpb24gb2YgZGlzdGFuY2UKICAgIC0gYSBjZW50aW1ldGVyIG9uIHRoZSBwcmludGVkIG1hcCByZXByZXNlbnRzIDEwMCBtZXRlcnMgb2YgZGlzdGFuY2Ugb24gY2FtcHVzCgojIyMjICoqZnJhbWUqKgoKLSBUaGUgcG9zaXRpb24gc2NhbGUgZGVzY3JpYmluZyBob3cgZGF0YSBhcmUgbWFwcGVkIHRvIHRoZSBjb29yZGluYXRlIHN5c3RlbSBpbiB1c2UKLSBRdWl0ZSBvZnRlbiwgdGhlIGZyYW1lIGRlZmluZXMgdGhlIHgtYXhpcyBhbmQgeS1heGlzIG9mIGEgMi1kaW1lbnNpb25hbCBjYXJ0ZXNpYW4gcGxhbmUKCgojIyMjICoqZ3VpZGUqKgoKKiBBbiBpbmRpY2F0aW9uIGZvciB0aGUgaHVtYW4gdmlld2VyIG9mIHRoZSBzY2FsZS4gIFRoaXMgYWxsb3dzIHRoZSB2aWV3ZXIgdG8gdHJhbnNsYXRlIGFlc3RoZXRpY3MgYmFjayBpbnRvIGRhdGEgdmFsdWVzLgoqIEZvciBleGFtcGxlLCAKICAgIC0gYSBsZWdlbmQgbWFrZXMgZXhwbGljaXQgdGhlIG1lYW5pbmcgb2YgUmVkICYgQmx1ZSBwb2ludHMgb24gdGhlIGNoYXJ0CiAgICAtIGEgMSBjbSBsZW5ndGggcHJpbnRlZCBvbiBhIG1hcCB0byBpbmZvcm0gdGhlIHJlYWRlciB0aGF0IGl0IGNvcnJlc3BvbmRzIHRvIDEwMCBtZXRlcnMgb24gY2FtcHVzCgoKIyMgU2NhbGVzCgojIyMjIFRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdmFyaWFibGUgdmFsdWUgYW5kIHRoZSB2YWx1ZSBvZiB0aGUgYWVzdGhldGljIHRoZSB2YXJpYWJsZSBpcyBtYXBwZWQgdG8uCgoqIFN5c3RvbGljIEJsb29kIFByZXNzdXJlIChTQlApIGhhcyB1bml0cyBvZiBtbUhnIChtaWxsaW1ldGVycyBvZiBtZXJjdXJ5KQoqIFBvc2l0aW9uIG9uIHRoZSB4LWF4aXMgbWVhc3VyZWQgaW4gZGlzdGFuY2UsIGUuZy4gaW5jaGVzLgoKVGhlIGNvbnZlcnNpb24gZnJvbSBTQlAgdG8gcG9zaXRpb24gaXMgYSAqc2NhbGUqLgoKKiBTbW9rZXIgaXMgIm5ldmVyIiwgImZvcm1lciIsICJjdXJyZW50IgoqIENvbG9yIGlzIHJlZCwgZ3JlZW4sIGJsdWUsIC4uLgoKVGhlIGNvbnZlcnNpb24gZnJvbSBTbW9rZXIgdG8gY29sb3IgaXMgYSAqc2NhbGUqLgoKCiMjIEd1aWRlcwoKIyMjIyBHdWlkZTogYW4gaW5kaWNhdGlvbiB0byBhIGh1bWFuIHZpZXdlciBvZiB3aGF0IHRoZSBzY2FsZSBpcy4KCiogQXhpcyB0aWNrcyBhbmQgbnVtYmVycwoKIVtdKEltYWdlcy94LWF4aXMtc2NhbGUucG5nKQoKKiBMZWdlbmRzCgohW10oSW1hZ2VzL2NvbG9yLXNjYWxlLnBuZykgCiFbXShJbWFnZXMvc2hhcGUtc2NhbGUucG5nKSAKCgoqIExhYmVscyBvbiBmYWNldGVkIGdyYXBoaWNzCgohW10oSW1hZ2VzL2ZhY2V0LXNjYWxlLnBuZykKCiMjIEZhY2V0cyAKCmBgYHtyIGZpZy5oZWlnaHQ9M30KZ2dwbG90KGRhdGEgPSBUbXAsIGFlcyh4ID0gc2JwLCB5ID0gZGJwLCBjb2xvciA9IHNtb2tlcikpICsKICBnZW9tX3BvaW50KCkgKwogIGZhY2V0X2dyaWQoIH4gc2V4KQpgYGAKCiAqIHggaXMgZGV0ZXJtaW5lZCBieSBgc2JwYCBhbmQgYHNleGAKICogYmFzaWNhbGx5IGEgc2VwYXJhdGUgZnJhbWUgZm9yIGVhY2ggYHNleGAKICogdXNlcyBzYW1lIHggYW5kIHkgdHdpY2UgKG9yIG9uY2UgZm9yIGVhY2ggZmFjZXQpCiAKCiMjIERlc2lnbmluZyBHcmFwaGljcwoKR3JhcGhpY3MgYXJlIGRlc2lnbmVkIGJ5IHRoZSBodW1hbiBleHBlcnQgKHlvdSEpIGluIG9yZGVyIHRvIHJldmVhbCBpbmZvcm1hdGlvbiB0aGF0J3MgcHJlc2VudCBpbiB0aGUgZGF0YS4KCiMjIyMgRGVzaWduIGNob2ljZXMKCgoqIFdoYXQga2luZCBvZiBnbHlwaCwgZS5nLiBzY2F0dGVyLCBkZW5zaXR5LCBiYXIsIC4uLiBtYW55IG90aGVycwoqIFdoYXQgdmFyaWFibGVzIGNvbnN0aXR1dGUgdGhlIGZyYW1lLiBBbmQgc29tZSBkZXRhaWxzOgogICAgLSBheGlzIGxpbWl0cwogICAgLSBsb2dhcml0aG1pYyBheGVzLCBldGMuCiogV2hhdCB2YXJpYWJsZXMgc2hvdWxkIGJlIG1hcHBlZCB0byBvdGhlciBhZXN0aGV0aWNzIG9mIHRoZSBnbHlwaC4KKiBXaGV0aGVyIHRvIGZhY2V0IGFuZCB3aXRoIHdoYXQgdmFyaWFibGUuCgpNb3JlIGRldGFpbHMsIC4uLiwgZS5nLiBzZXR0aW5nIG9mIGFlc3RoZXRpY3MgdG8gY29uc3RhbnRzCgoKIyMgR29vZCBhbmQgQmFkIEdyYXBoaWNzCgpSZW1lbWJlciAuLi4gCgo+IEdyYXBoaWNzIGFyZSBkZXNpZ25lZCBieSB0aGUgaHVtYW4gZXhwZXJ0ICh5b3UhKSBpbiBvcmRlciB0byByZXZlYWwgaW5mb3JtYXRpb24gdGhhdCdzIHByZXNlbnQgaW4gdGhlIGRhdGEuCgotIGNob2ljZXMgZGVwZW5kIG9uIHdoYXQgaW5mb3JtYXRpb24geW91IHdhbnQgdG8gY29udmV5LgotIHByYWN0aWNlIHJlYWRpbmcgZ3JhcGhpY3MgYW5kIGNyaXRpcXVlIHdoaWNoIHdheXMgb2YgYXJyYW5naW5nIHRoaW5nIGFyZSBiZXR0ZXIgb3Igd29yc2UuCi0gQSBiYXNpYyBwcmluY2lwbGUgaXMgdGhhdCBhIGdyYXBoaWMgaXMgYWJvdXQgKmNvbXBhcmlzb24qLiAgR29vZCBncmFwaGljczogCiAgICAtIG1ha2UgaXQgZWFzeSBmb3IgcGVvcGxlIHRvIHBlcmNlaXZlIHRoaW5ncyB0aGF0IGFyZSBzaW1pbGFyIGFuZCB0aGluZ3MgdGhhdCBhcmUgZGlmZmVyZW50LiAgCiAgICAtIHB1dCB0aGUgdGhpbmdzIHRvIGJlIGNvbXBhcmVkIGluIHByb3hpbWl0eSB0byBvbmUgYW5vdGhlciAoZS5nLiwgInNpZGUtYnktc2lkZSIpIAoKCgojIyBDcml0aXF1ZSB0aGlzIGdyYXBoaWMuLi4KCi0gV2hhdCBzb3J0IG9mIGNvbXBhcmlzb25zIG1pZ2h0IHlvdSB3YW50IHRvIG1ha2U/Ci0gRG8geW91IGZpbmQgaXQgZWFzeSBvciBoYXJkIHRvIG1ha2UgdGhvc2UgY29tcGFyaXNvbnM/Ci0gSG93IG1pZ2h0IHRoaXMgZ3JhcGggYmUgaW1wcm92ZWQ/CgpgYGB7cn0KcCArIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gc2V4LCBzaXplID0gc21va2VyKSwgYWxwaGEgPSAuODUpIApgYGAKCiMjIFBlcmNlcHRpb24gYW5kIENvbXBhcmlzb24KCkluIHJvdWdobHkgZGVzY2VuZGluZyBvcmRlciBvZiBodW1hbiBhYmlsaXR5IHRvIGNvbXBhcmUgbmVhcmJ5IG9iamVjdHM6CgoxLiBQb3NpdGlvbgoyLiBMZW5ndGgKMy4gQXJlYQo0LiBBbmdsZQo1LiBTaGFwZSAoYnV0IG9ubHkgYSB2ZXJ5IGZldyBkaWZmZXJlbnQgc2hhcGVzKQo2LiBDb2xvcgoKQ29sb3IgaXMgdGhlIG1vc3QgZGlmZmljdWx0Li4uICAgIAoKICAtIGNvbG9yIGdyYWRpZW50cyAtLS0gd2UncmUgYmV0dGVyIGF0CiAgLSBkaXNjcmV0ZSBjb2xvcnMgLS0tIG11c3QgYmUgY2FyZWZ1bGx5IHNlbGVjdGVkLgogIC0gbG90cyBvZiBwZW9wbGUgYXJlIGNvbG9yIGJsaW5kIChbMSBpbiAxMiBtZW47IDEgaW4gMjAwIHdvbWVuXShodHRwOi8vd3d3LmNvbG91cmJsaW5kYXdhcmVuZXNzLm9yZy8pKQogIApGb3IgbW9yZSwgc2VlOgoKQ2xldmVsYW5kIFcuICgxOTg1KS4gKlRoZSBlbGVtZW50cyBvZiBncmFwaGluZyBkYXRhKi4gQmVsbCBUZWxlcGhvbmUgTGFib3JhdG9yaWVzOiBNdXJyYXkgSGlsbCwgTkouCgoKIyMgR2x5cGgtUmVhZHkgRGF0YQoKR2x5cGgtcmVhZHkgZGF0YSBoYXMgdGhpcyBmb3JtOgoKICAqIFRoZXJlIGlzIG9uZSByb3cgZm9yIGVhY2ggZ2x5cGggdG8gYmUgZHJhd24uIAogICogVGhlIHZhcmlhYmxlcyBpbiB0aGF0IHJvdyBhcmUgbWFwcGVkIHRvIGFlc3RoZXRpY3Mgb2YgdGhlIGdseXBoIChpbmNsdWRpbmcgcG9zaXRpb24pCgoKPGRpdiBjbGFzcz0iY29sdW1ucy0yIj4KKipHbHlwaC1yZWFkeSBkYXRhKioKYGBge3IgZWNobz1GQUxTRX0KaGVhZChUbXAsNikKYGBgCgoqKk1hcHBpbmcgb2YgZGF0YSB0byBhZXN0aGV0aWNzKioKCmBgYAogICBzYnAgaXMgbWFwcGVkIHRvIHggcG9zaXRpb24gICAgICAKICAgZGJwIGlzIG1hcHBlZCB0byB5IHBvc2l0aW9uICAgIApzbW9rZXIgaXMgbWFwcGVkIHRvIGNvbG9yCiAgIHNleCBpcyBtYXBwZWQgdG8gc2hhcGUKYGBgCgpTY2FsZXMgZGV0ZXJtaW5lIGRldGFpbHMgb2YgdHJhbnNsYXRpb24gZnJvbQoKYHZhcmlhYmxlIGlzIG1hcHBlZCB0byBhZXN0aGV0aWNgIAoKYGBge3IgaW5jbHVkZT1GQUxTRX0KVG1wMiA8LSBUbXAgJT4lCiAgcmVuYW1lKHggPSBzYnAsIHkgPSBkYnAsIGNvbG9yID0gc21va2VyLCBzaGFwZSA9IHNleCApCmhlYWQoVG1wMikKYGBgCjwvZGl2PgoKPCEtLQpJdCdzIGFzIGlmIHRoZSB2YXJpYWJsZXMgd2VyZSBnaXZlbiB0aGUgbmFtZSBvZiB0aGUgYWVzdGhldGljLgotLT4KCgoKIyMgTGF5ZXJzIC0tIGJ1aWxkaW5nIHVwIGNvbXBsZXggcGxvdHMgCgpFYWNoIGxheWVyIG1heSBoYXZlIGl0cyBvd24gZGF0YSwgZ2x5cGhzLCBhZXN0aGV0aWMgbWFwcGluZywgZXRjLgoKYGBge3J9CmdncGxvdChkYXRhID0gVG1wLCBhZXMoeCA9IHNicCwgeSA9IGRicCwgY29sb3VyID0gc2V4KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSkgCmBgYAoKICogb25lIGxheWVyIGhhcyBwb2ludHMKICogYW5vdGhlciBsYXllciBoYXMgdGhlIGN1cnZlcwoKIyMgU3RhdHM6IERhdGEgVHJhbnNmb3JtYXRpb25zCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBUbXAsIGFlcyh4ID0gc2JwKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTApCmBgYAoKICAqIFdoYXQgYXJlIHRoZSBnbHlwaHMsIGFlc3RoZXRpY3MsIGd1aWRlcywgZXRjLiBmb3IgdGhpcyBwbG90PwogICogSG93IGlzIHRoZSBkYXRhIGZvciB0aGlzIHBsb3QgcmVsYXRlZCB0byB0aGUgInJhdyIgZGF0YT8KICAKYGBge3J9CmhlYWQoVG1wLCA0KQpgYGAKCiMjIENoYWxsZW5nZSBUYXNrCgpTb3VyY2U6IOKAnENvbGxlZ2UsIHRoZSBHcmVhdCBVbmxldmVsZXLigJ0sIE5ldyBZb3JrIFRpbWVzLCAwMy0wMS0yMDE0IAoKIVtdKGltYWdlcy9DaGFsbGVuZ2UucG5nKQoKIyMjIyBMZWZ0IFBhbmVsIFF1ZXN0aW9uczogCi0gTGVmdCBwYW5lbDogV2hhdCB2YXJpYWJsZXMgbWFrZSB1cCB0aGUgKipmcmFtZSoqPwotIExlZnQgcGFuZWw6IFdoYXQgYXJlIHRoZSAqKmd1aWRlcyoqPwotIExlZnQgcGFuZWw6IFdoYXQgYXJlIHRoZSAqKmdseXBocyoqIGFuZCB3aGF0IGRvIHRoZXkgcmVwcmVzZW50PwotIExlZnQgcGFuZWw6IFNrZXRjaCBhIGZldyByb3dzIG9mIHRoZSBnbHlwaC1yZWFkeSBkYXRhLgoKIyMjIyBSaWdodCBQYW5lbCBRdWVzdGlvbnM6Ci0gUmlnaHQgcGFuZWw6IFdoYXQgYXJlIHRoZSAqKmdseXBocyoqIGFuZCB3aGF0IGRvIHRoZXkgcmVwcmVzZW50PwotIFJpZ2h0IHBhbmVsOiBEZXNjcmliZSB0aHJlZSAqKmFlc3RoZXRpY3MqKiBtYXBwZWQgdG8gdGhlIGdseXBocz8KLSBSaWdodCBwYW5lbDogU2tldGNoIGEgZmV3IHJvd3Mgb2YgdGhlIGdseXBoLXJlYWR5IGRhdGEuCi0gUmlnaHQgcGFuZWw6IE1ha2UgYSByb3VnaCBza2V0Y2ggb2YgYSBzdGFja2VkIGJhciBjaGFydCBzaG93aW5nIHRoZSBzYW1lIGluZm9ybWF0aW9uLgoKIyMgUGFydGlhbCBTb2x1dGlvbiB0byBDaGFsbGVuZ2UgVGFzawoKIyMjIyBMZWZ0IFBhbmVsIFF1ZXN0aW9uczogCi0gTGVmdCBwYW5lbCAqKmZyYW1lKio6IEZyYWN0aW9uIG9mIGZhbWlseSBpbmNvbWUgdG8gcGF5IGZvciBvbmUgeWVhciBvZiBjb2xsZWdlLCBhbmQgeWVhci4gCi0gTGVmdCBwYW5lbCAqKmd1aWRlcyoqOiAKICAgIC0gTGFiZWxzIGZvciB0aGUgZGlmZmVyZW50IHF1aW50aWxlcyBvZiBmYW1pbHkgaW5jb21lLgogICAgLSBBIGxpbmUgc2NhbGluZyB0aGUgYXhpcywgc2hvd2luZyB3aGVyZSB0aGUgZnJhY3Rpb24gb2YgZmFtaWx5IGluY29tZSBpcyAxMDAlLgogICAgLSBUZXh0IHRvIGxhYmVsIHRoZSBleHRlbnQgb2YgdGhlIGhvcml6b250YWwgYXhpcywgZnJvbSAxOTcxIHRvIDIwMTAuCi0gTGVmdCBwYW5lbCAqKmdseXBocyoqOiAKICAgIC0gUG9pbnRzIHJlcHJlc2VudGluZyBmcmFjdGlvbiBvZiBpbmNvbWUKICAgIC0gTGluZXMgY29ubmVjdGluZyAxOTcxIHJlc3VsdCB0byAyMDExIHJlc3VsdCAKLSBMZWZ0IHBhbmVsOiBTa2V0Y2ggYSBmZXcgcm93cyBvZiB0aGUgZ2x5cGgtcmVhZHkgZGF0YS4KCgojIyMjIFJpZ2h0IFBhbmVsIFF1ZXN0aW9uczoKLSBSaWdodCBwYW5lbCAqKmdseXBocyoqOiBzZWdtZW50cyBvZiB0aGUgY2lyY2xlcwotIFJpZ2h0IHBhbmVsIHRocmVlICoqYWVzdGhldGljcyoqOiBjb2xvciwgbGVuZ3RoLCBzaXplIChpLmUuLCByYWRpdXMgb2YgY2lyY2xlKQotIFJpZ2h0IHBhbmVsOiBTa2V0Y2ggYSBmZXcgcm93cyBvZiB0aGUgZ2x5cGgtcmVhZHkgZGF0YS4KLSBSaWdodCBwYW5lbDogTWFrZSBhIHJvdWdoIHNrZXRjaCBvZiBhIHN0YWNrZWQgYmFyIGNoYXJ0IHNob3dpbmcgdGhlIHNhbWUgaW5mb3JtYXRpb24uCgoKIyMgUGF0aCB0byBzdWNjZXNzCgogMS4gKipFeWUtdHJhaW5pbmcqKiAKIAogICAgLSByZWNvZ25pemUgYW5kIGRlc2NyaWJlIGdseXBocywgYWVzdGhldGljcywgc2NhbGVzLCBldGMuCiAgICAtIGlkZW50aWZ5IGRhdGEgcmVxdWlyZWQgZm9yIGEgcGxvdAogICAgCiAyLiAqKkRhdGEgd3JhbmdsaW5nKiogCiAKICAgIC0gZ2V0IGRhdGEgaW50byBnbHlwaC1yZWFkeSBmb3JtYXQgKGBkcGx5cmAsIGB0aWR5cmAsIGB0aWR5dmVyc2VgKQogICAgLSAod2UnbGwgc3RhcnQgZG9pbmcgdGhpcyBuZXh0IHdlZWshKQogICAgCiAzLiAqKkdyYXBoaWNzIGNvbnN0cnVjdGlvbioqIAogICAgCiAgICAtIE5ld2JpZXM6IG1hdGNoIHZhcmlhYmxlcyB0byBhZXN0aGV0aWNzICoqaW50ZXJhY3RpdmVseSoqOiAKICAgICAgICAtIGBlc3F1aXNzZWAgcGFja2FnZSB1c2luZyBgZXNxdWlzc2VyKCApYCAgCiAgICAgICAgLSBgbW9zYWljYCBwYWNrYWdlIHVzaW5nIGBtcGxvdCggKWAgCiAgICAgICAgLSBCT1RIIGdlbmVyYXRlIGBnZ3Bsb3QyYCBzeW50YXggCiAgICAtIFByb3M6IGxlYXJuIHRvIHdyaXRlIGBnZ3Bsb3QyYCBjb2RlIGRpcmVjdGx5CgoKPCEtLSAgLSBgRGF0YUNvbXB1dGluZ2AgcGFja2FnZSB1c2luZyBgc2NhdHRlckdyYXBoSGVscGVyKCApYCwgYGJhckdyYXBoSGVscGVyKCApYCwgYGRlbnNpdHlHcmFwaEhlbHBlciggKWAgLS0+CgoKIyMgUmV2aXNpdGluZyBUaGUgQmlnIE1hYyBJbmRleAoKPGh0dHBzOi8vZ2l0aHViLmNvbS9yZm9yZGF0YXNjaWVuY2UvdGlkeXR1ZXNkYXkvdHJlZS9tYXN0ZXIvZGF0YS8yMDIwLzIwMjAtMTItMjI+CgpgYGB7ciBtZXNzYWdlPUZBTFNFfQojIFRoZXNlIGRhdGEgYXJlIGF2YWlsYWJsZSBmcm9tIHRoZSBgdGlkeXR1ZXNkYXlSYCBwYWNrYWdlIAojIEluc3RhbGwgcGFja2FnZSBmcm9tIENSQU4gdmlhOiBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dHVlc2RheVIiKQoKbGlicmFyeSh0aWR5dHVlc2RheVIpCgpUaWR5VHVlc0RhdGEgPC0gdGlkeXR1ZXNkYXlSOjp0dF9sb2FkKDIwMjAsIHdlZWsgPSA1MikKQmlnTWFjIDwtIFRpZHlUdWVzRGF0YVtbImJpZy1tYWMiXV0KCmBgYAoKCiMjIEJpZyBNYWMgUHJpY2UgdnMgR1BEIHBlciBDYXBpdGE/CgpMZXQncyB1c2UgdGhlIGBlc3F1aXNzZWAgcGFja2FnZSB0byBleHBsb3JlIHRoZSBkYXRhIQoKSW4gdGhlIGNvbnNvbGU6IAoKYGVzcXVpc3NlcihCaWdNYWMpYAoKCmBgYHtyfQpsaWJyYXJ5KGVzcXVpc3NlKQoKIyB1c2UgYGVzcXVpc3NlciggKWAgdG8gZHJhZnQgYSBwbG90IGFuZCB0aGVuIGdlbmVyYXRlIFIgY29kZSB0byBwdXQgaGVyZSEKCmBgYAoKCiMjIyBIZXJlJ3MgYW4gZXhhbXBsZToKCmBgYHtyIGVjaG89RkFMU0V9CmdncGxvdChCaWdNYWMpICsKIGFlcyh4ID0gZ2RwX2RvbGxhciwgeSA9IGRvbGxhcl9wcmljZSkgKwogZ2VvbV9wb2ludChzaXplID0gMUwsIGNvbG91ciA9ICIjMGM0YzhhIikgKwogbGFicyh0aXRsZSA9ICJCaWcgTWFjIFByaWNlIEFyb3VuZCB0aGUgV29ybGQgdnMgR0RQIHBlciBDYXBpdGEiKSArCiB0aGVtZV9taW5pbWFsKCkKYGBgCgotIFVzaW5nIHRoZSBncmFwaCwgd2hhdCBjYW4geW91IHNheSBhYm91dCB0aGUgZm9sbG93aW5nPwogIC0gRnJhbWUgIAogIC0gR2x5cGgKICAtIEFlc3RoZXRpYwogIC0gU2NhbGUKICAtIEd1aWRlCiAgLSBGYWNldAoKCiMjIFZhbHVlIG9mIEJpZyBNYWMgYXJvdW5kIHRoZSB3b3JsZAoKYGBge3J9CiMgdXNpbmcgYG1Xb3JsZE1hcCggKWAgZnJvbSBgbW9zYWljYCBwYWNrYWdlCmxpYnJhcnkobW9zYWljKQoKIyBga2V5YCBhcmd1bWVudCB0YWtlcyB0aGUgSUQgdmFyaWFibGU7IGBmaWxsYCB0YWtlcyB0aGUgbWVhc3VyZWQgdmFyaWFibGUgCm1Xb3JsZE1hcChCaWdNYWMsIGtleSA9ICJpc29fYTMiLCBmaWxsID0gImRvbGxhcl9wcmljZSIpCmBgYAoKLSBVc2luZyB0aGUgZ3JhcGgsIHdoYXQgY2FuIHlvdSBzYXkgYWJvdXQgdGhlIGZvbGxvd2luZz8KICAtIEZyYW1lICAKICAtIEdseXBoCiAgLSBBZXN0aGV0aWMKICAtIFNjYWxlCiAgLSBHdWlkZQogIC0gRmFjZXQKCgoKCgo8IS0tICMjIEFjdGl2aXR5OiAgLS0+Cgo8IS0tIFlvdSdyZSBnb2luZyB0byBwcmFjdGljZSByZXByb2R1Y2luZyBncmFwaHMgdXNpbmcgdGhlIGludGVyYWN0aXZlIFIgZnVuY3Rpb25zIGludHJvZHVjZWQgaW4gdGhlIHJlYWRpbmc6ICAgLS0+CgoKPCEtLSAjIyMjIEhvbWV3b3JrICAgLS0+Cgo8IS0tICoqQWxsIGhvbWV3b3JrLCBhY3Rpdml0aWVzLCBhc3NpZ25tZW50cyBldGMuIGZyb20gbm93IG9uIG11c3QgYmUgc3VibWl0dGVkIHRvIENhbnZhcyBhcyBIVE1MIGZpbGVzIHdpdGggZW1iZWRkZWQgLlJtZCB1bmxlc3Mgb3RoZXJ3aXNlIHN0YXRlZC4qKiAgIC0tPgoKPCEtLSAtIFR1cm4gaW4gR3JhcGggUmVwbGljYXRpb24gQWN0aXZpdHkgKEhUTUwgdG8gQ2FudmFzKSAtLT4KPCEtLSAtIERDIENoIDUgJiA2IEV4ZXJjaXNlcyAoSFRNTCB0byBDYW52YXMpOiA1LjEsIDUuMiwgNi41LCA2LjYsIDYuNywgNi44ICAgLS0+CjwhLS0gLSBEQyBjaGFwdGVyIDcgcmVhZGluZyBxdWl6IG9uIENhbnZhcyAgICAgLS0+Cgo=