Muddiest point?
Grammar of Graphics
- Lots of new terminology this week
- Can you describe each of these terms?
- Frame
- Glyph
- Aesthetic
- Scale
- Guide
- Facet
Grammar of Graphics
- Wilkinson’s 2005 book The Grammer of Graphics (2nd Ed.)
provides the principles and philosophy
- the
ggplot2
R package implements this framework
- Goal: flexible tools for building rich, intuitive
graphics
- Data Visualization is critical to our goals for high quality
Exploratory Data Analysis (EDA)
- Examine the data source: variable types, coding,
missingness, summary statistics/plots, who/what/when/where/why/how data
were collected
- Discover features that influence may modeling
decisions: investigate potential outliers, consideration for
recoding variables (e.g., numeric data that’s functionally dichotomous),
evaluate correlation structure (e.g., autocorrelation, hierarchy,
spatial/temporal proximity)
- 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:
“Aesthetic”?
Q: In general, what’s your intuition about the meaning of
aesthetic?
- How might you describe the aesthetic of a favorite coffee shop or
restaurant?
Data Glyph Properties: Aesthetics
Aesthetics are visual properties of a glyph.
- Aesthetics for points: location (x and y), shape, color, size,
transparency
- Each glyph has its own set of aesthetics.


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.


- Labels on faceted graphics

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

- x is determined by
sbp
and sex
- basically a separate frame for each
sex
- uses same x and y twice (or once for each facet)
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.
- choices depend on what information you want to convey.
- practice reading graphics and critique which ways of arranging thing
are better or worse.
- A basic principle is that a graphic is about comparison.
Good graphics:
- make it easy for people to perceive things that are similar and
things that are different.
- put the things to be compared in proximity to one another (e.g.,
“side-by-side”)
Critique this graphic…
- What sort of comparisons might you want to make?
- Do you find it easy or hard to make those comparisons?
- How might this graph be improved?
p + geom_point(aes(color = sex, size = smoker), alpha = .85)

Perception and Comparison
In roughly descending order of human ability to compare nearby
objects:
- Position
- Length
- Area
- Angle
- Shape (but only a very few different shapes)
- Color
Color is the most difficult…
- color gradients — we’re better at
- discrete colors — must be carefully selected.
- lots of people are color blind (1 in 12 men; 1 in 200
women)
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:
- There is one row for each glyph to be drawn.
- The variables in that row are mapped to aesthetics of the glyph
(including position)
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)

- one layer has points
- another layer has the curves
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
Eye-training
- recognize and describe glyphs, aesthetics, scales, etc.
- identify data required for a plot
Data wrangling
- get data into glyph-ready format (
dplyr
,
tidyr
, tidyverse
)
- (we’ll start doing this next week!)
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
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

- Using the graph, what can you say about the following?
- Frame
- Glyph
- Aesthetic
- Scale
- Guide
- Facet
LS0tCnRpdGxlOiAiV2VlayA0OiBHcmFwaGljcywgR2x5cGhzLCBGcmFtZXMsIGFuZCBTY2FsZXMiCnN1YnRpdGxlOiAiRGF0YSBDb21wdXRpbmcgQ2hhcHRlcnMgNSAmIDYiCmF1dGhvcjogIlByb2YgQmVja21hbiIKZGF0ZTogIiIKb3V0cHV0OiAKICAgIHNsaWR5X3ByZXNlbnRhdGlvbjogZGVmYXVsdAogICAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAoKLS0tCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KG1vc2FpYykKbGlicmFyeShOSEFORVMpCmxpYnJhcnkoZGNEYXRhKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShlc3F1aXNzZSkKCmBgYAoKIyMgTXVkZGllc3QgcG9pbnQ/CgoKCiMjIEdyYW1tYXIgb2YgR3JhcGhpY3MKCi0gTG90cyBvZiBuZXcgdGVybWlub2xvZ3kgdGhpcyB3ZWVrCi0gQ2FuIHlvdSBkZXNjcmliZSBlYWNoIG9mIHRoZXNlIHRlcm1zPwogICAgLSBGcmFtZQogICAgLSBHbHlwaAogICAgLSBBZXN0aGV0aWMKICAgIC0gU2NhbGUKICAgIC0gR3VpZGUKICAgIC0gRmFjZXQKCgojIyBHcmFtbWFyIG9mIEdyYXBoaWNzCgotIFdpbGtpbnNvbidzIDIwMDUgYm9vayAqVGhlIEdyYW1tZXIgb2YgR3JhcGhpY3MgKDJuZCBFZC4pKiBwcm92aWRlcyB0aGUgcHJpbmNpcGxlcyBhbmQgcGhpbG9zb3BoeSAKICAgIC0gdGhlIGBnZ3Bsb3QyYCBSIHBhY2thZ2UgaW1wbGVtZW50cyB0aGlzIGZyYW1ld29yawogICAgLSAqKkdvYWwqKjogZmxleGlibGUgdG9vbHMgZm9yIGJ1aWxkaW5nIHJpY2gsIGludHVpdGl2ZSBncmFwaGljcwoKLSBEYXRhIFZpc3VhbGl6YXRpb24gaXMgY3JpdGljYWwgdG8gb3VyIGdvYWxzIGZvciBoaWdoIHF1YWxpdHkgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcyAoRURBKQogICAgMS4gKipFeGFtaW5lIHRoZSBkYXRhIHNvdXJjZToqKiB2YXJpYWJsZSB0eXBlcywgY29kaW5nLCBtaXNzaW5nbmVzcywgc3VtbWFyeSBzdGF0aXN0aWNzL3Bsb3RzLCB3aG8vd2hhdC93aGVuL3doZXJlL3doeS9ob3cgZGF0YSB3ZXJlIGNvbGxlY3RlZAogICAgMi4gKipEaXNjb3ZlciBmZWF0dXJlcyB0aGF0IGluZmx1ZW5jZSBtYXkgbW9kZWxpbmcgZGVjaXNpb25zOioqIGludmVzdGlnYXRlIHBvdGVudGlhbCBvdXRsaWVycywgY29uc2lkZXJhdGlvbiBmb3IgcmVjb2RpbmcgdmFyaWFibGVzIChlLmcuLCBudW1lcmljIGRhdGEgdGhhdCdzIGZ1bmN0aW9uYWxseSBkaWNob3RvbW91cyksIGV2YWx1YXRlIGNvcnJlbGF0aW9uIHN0cnVjdHVyZSAoZS5nLiwgYXV0b2NvcnJlbGF0aW9uLCBoaWVyYXJjaHksIHNwYXRpYWwvdGVtcG9yYWwgcHJveGltaXR5KQozLiAqKkFkZHJlc3MgcmVzZWFyY2ggcXVlc3Rpb25zOioqIGJ1aWxkIGludHVpdGlvbiBhbmQgbm90ZSBwcmVsaW1pbmFyeSBvYnNlcnZhdGlvbnMvY29uY2x1c2lvbnMgcmVsYXRlZCB0byBlYWNoIHJlc2VhcmNoIHF1ZXN0aW9uLiAgQWxzbywgbm90ZSBvYnNlcnZhdGlvbnMgdGhhdCBwcm9tcHQgeW91IHRvIHJlZmluZSB5b3VyIHJlc2VhcmNoIHF1ZXN0aW9ucyBvciBhZGQgbmV3IHF1ZXN0aW9ucyB0byBpbnZlc3RpZ2F0ZQoKIVtdKGdyYW1tYXJHcmFwaGljcy5wbmcpCgoKIyMgR2x5cGhzIGFuZCBEYXRhCgpJbiBhcmNoYWVvbG9neSwgYSBHTFlQSCBpcyBhIHN5bWJvbCBvciAibWFyayIgdXNlZCB0byBpbXBhcnQgbWVhbmluZzoKCkhlaXJvR0xZUEggfCBNYXlhbiBHTFlQSAotLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLToKIVtIZWlyb2dseXBoXShJbWFnZXMvaGFuZC5qcGcpIHwgIVtNYXlhbiBnbHlwaF0oSW1hZ2VzL21heWFuLWdseXBoLnBuZykgCgojIyBEYXRhIEdseXBoCgoKIyMjIEEgZGF0YSBnbHlwaCBpcyBhbHNvIGEgIm1hcmsiIG9uIGEgZ3JhcGgsIGUuZy4gCgohW10oSW1hZ2VzL2dlb21fcmVjdC5wbmcpICFbXShJbWFnZXMvZ2VvbV9zZWdtZW50LnBuZykgIVtdKEltYWdlcy9nZW9tX3RleHQucG5nKSAhW10oSW1hZ2VzL2dlb21fY3Jvc3NiYXIucG5nKSAhW10oSW1hZ2VzL2dlb21fcGF0aC5wbmcpICFbXShJbWFnZXMvZ2VvbV9saW5lLnBuZykgIVtdKEltYWdlcy9nZW9tX3BvaW50cmFuZ2UucG5nKSAhW10oSW1hZ2VzL2dlb21fcmliYm9uLnBuZykgIVtdKEltYWdlcy9nZW9tX3BvaW50LnBuZykgIVtdKEltYWdlcy9nZW9tX3BvbHlnb24ucG5nKSAhW10oSW1hZ2VzL2dlb21faGlzdG9ncmFtLnBuZykgIVtdKEltYWdlcy9nZW9tX2RvdHBsb3QucG5nKSAhW10oSW1hZ2VzL2dlb21fZnJlcXBvbHkucG5nKSAhW10oSW1hZ2VzL2dlb21fZGVuc2l0eS5wbmcpICFbXShJbWFnZXMvZ2VvbV92aW9saW4ucG5nKSAKClRoZSBmZWF0dXJlcyBvZiBhIGRhdGEgZ2x5cGggZW5jb2RlcyB0aGUgdmFsdWUgb2YgdmFyaWFibGVzLiAKCi0gU29tZSBhcmUgdmVyeSBzaW1wbGUsIGUuZy4gYSBkb3Q6ICFbXShJbWFnZXMvZ2VvbV9wb2ludC5wbmcpCi0gU29tZSBjb21iaW5lIGRpZmZlcmVudCBlbGVtZW50cywgZS5nLiBhIHBvaW50cmFuZ2U6ICFbXShJbWFnZXMvZ2VvbV9wb2ludHJhbmdlLnBuZykKLSBTb21lIGFyZSBtb3JlIGNvbXBsZXgsIGUuZy4gYSB2aW9saW46ICFbXShJbWFnZXMvZ2VvbV92aW9saW4ucG5nKQoKU2VlOiAqPGh0dHA6Ly9kb2NzLmdncGxvdDIub3JnL2N1cnJlbnQvPioKCgojIyAiQWVzdGhldGljIj8KClE6IEluIGdlbmVyYWwsIHdoYXQncyB5b3VyIGludHVpdGlvbiBhYm91dCB0aGUgbWVhbmluZyBvZiBhZXN0aGV0aWM/CgotIEhvdyBtaWdodCB5b3UgZGVzY3JpYmUgdGhlIGFlc3RoZXRpYyBvZiBhIGZhdm9yaXRlIGNvZmZlZSBzaG9wIG9yIHJlc3RhdXJhbnQ/CgoKIyMgRGF0YSBHbHlwaCBQcm9wZXJ0aWVzOiBBZXN0aGV0aWNzCgpBZXN0aGV0aWNzIGFyZSAqKnZpc3VhbCBwcm9wZXJ0aWVzKiogb2YgYSBnbHlwaC4KCiAgKiBBZXN0aGV0aWNzIGZvciBwb2ludHM6IGxvY2F0aW9uICh4IGFuZCB5KSwgc2hhcGUsIGNvbG9yLCBzaXplLCB0cmFuc3BhcmVuY3kKICAqIEVhY2ggZ2x5cGggaGFzIGl0cyBvd24gc2V0IG9mIGFlc3RoZXRpY3MuCgpgYGB7ciBlY2hvPUZBTFNFLCBmaWcua2VlcD0nYWxsJywgb3V0LndpZHRoPSI1MCUiLCBpbmNsdWRlPUZBTFNFfQpzZXQuc2VlZCgxMDIpCm4gPC0gMzAKVG1wIDwtIGRhdGEuZnJhbWUoCiAgc2JwID0gIHJvdW5kKHJ1bmlmKG4sIG1pbiA9IDgwLCBtYXggPSAxODApKSwKICBkYnAgPSByb3VuZChydW5pZihuLCBtaW4gPSA0MCwgbWF4ID0gMTEwKSksCiAgZ3JvdXAgPSBzYW1wbGUoYygiVHIiLCJDdGwiKSwgc2l6ZSA9IG4sIHJlcGxhY2UgPSBUUlVFKSwKICByZWFjdCA9IHNhbXBsZSggYygiTG93IiwgIlNldiIsICJNb2QiKSwgc2l6ZSA9IG4sIHJlcGxhY2UgPSBUUlVFKQopClRtcCA8LSBUbXAgJT4lIG11dGF0ZShkYnAgPSBwbWluKHNicCwgZGJwKSkgCnAgPC0gZ2dwbG90KFRtcCwgYWVzKHggPSBzYnAsIHkgPSBkYnApKSArIHhsYWIoIlN5c3RvbGljIEJQIikgKyB5bGFiKCJEaWFzdG9saWMgQlAiKQpwICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBncm91cCwgc2l6ZSA9IHJlYWN0KSkgCnAgKyBnZW9tX3BvaW50KHNpemUgPSA1LCBhZXMoc2hhcGUgPSBncm91cCwgY29sb3IgPSByZWFjdCkpCmBgYAoKYGBge3IgZWNobz1GQUxTRSwgZmlnLmtlZXA9J2FsbCcsIG91dC53aWR0aD0iNTAlIn0Kc2V0LnNlZWQoMTAyKQpyZXF1aXJlKE5IQU5FUykKCm4gPC0gNzUKVG1wIDwtIAogIE5IQU5FUyAlPiUKICBtdXRhdGUoCiAgICBzbW9rZXIgPSBkZXJpdmVkRmFjdG9yKAogICAgICBuZXZlciA9IFNtb2tlMTAwID09ICJObyIsCiAgICAgIGZvcm1lciA9IFNtb2tlTm93ID09ICJObyIsCiAgICAgIGN1cnJlbnQgPSBTbW9rZU5vdyA9PSAiWWVzIiwKICAgICAgLm9yZGVyZWQgPSBUUlVFCiAgICApLAogICAgc2JwID0gQlBTeXNBdmUsCiAgICBkYnAgPSBCUERpYUF2ZSwKICAgIHNleCA9IEdlbmRlcgogICkgJT4lCiAgc2VsZWN0KCBzYnAsIGRicCwgc2V4LCBzbW9rZXIgKSAlPiUKICBzYW1wbGVfbihuKSAlPiUKICBmaWx0ZXIoY29tcGxldGUuY2FzZXMoLikpICU+JSAKICBkYXRhLmZyYW1lKCkKCgpwIDwtIGdncGxvdChUbXAsIGFlcyh4ID0gc2JwLCB5ID0gZGJwKSkgKyAKICB4bGFiKCJTeXN0b2xpYyBCUCIpICsgeWxhYigiRGlhc3RvbGljIEJQIikKcCArIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gc2V4LCBzaXplID0gc21va2VyKSwgYWxwaGEgPSAuOCkgCnAgKyBnZW9tX3BvaW50KHNpemUgPSA1LCBhZXMoc2hhcGUgPSBzZXgsIGNvbG9yID0gc21va2VyKSwgYWxwaGEgPSAuOCkKYGBgCgoKCiMjIFNvbWUgR3JhcGhpY3MgQ29tcG9uZW50cwoKIyMjIyAqKmdseXBoKioKCi0gVGhlIGJhc2ljIGdyYXBoaWNhbCB1bml0IG9mdGVuIGNvcnJlc3BvbmRpbmcgdG8gb25lIGNhc2UuCi0gT3RoZXIgdGVybXMgdXNlZCBpbmNsdWRlICptYXJrKiBhbmQgKnN5bWJvbCouIAoKIyMjIyAqKmFlc3RoZXRpYyoqCgotIGEgdmlzdWFsIHByb3BlcnR5IG9mIGEgZ2x5cGggc3VjaCBhcyBwb3NpdGlvbiwgc2l6ZSwgc2hhcGUsIGNvbG9yLCBldGMuICAKLSBtYXkgYmUgKiptYXBwZWQqKiBiYXNlZCBvbiBkYXRhIHZhbHVlczogYHNleCBpcyBtYXBwZWQgdG8gY29sb3JgIAotIG1heSBiZSAqKnNldCoqIHRvIHBhcnRpY3VsYXIgbm9uLWRhdGEgcmVsYXRlZCB2YWx1ZXM6IGBjb2xvciBpcyBibGFja2AKCiMjIyMgKipzY2FsZSoqCgoqIEEgbWFwcGluZyB0aGF0IHRyYW5zbGF0ZXMgZGF0YSB2YWx1ZXMgaW50byBhZXN0aGV0aWNzLiAgRm9yIGV4YW1wbGUsCiogQSBzY2F0dGVyIHBsb3Qgb2YgaGVhbHRoIHJpc2tzIG1heSBpZGVudGlmeSBjaWdhcmV0dGUgc21va2luZzogIAogICAgLSA8Zm9udCBjb2xvcj0iYmx1ZSI+Ymx1ZTwvZm9udD4gcmVwcmVzZW50cyAiTm8iCiAgICAtIDxmb250IGNvbG9yPSJyZWQiPnJlZDwvZm9udD4gcmVwcmVzZW50cyAiWWVzIgoqIEEgcHJpbnRlZCBtYXAgb2YgY2FtcHVzIHVzZXMgYSBzY2FsZWQgcmVwcmVzZW50YXRpb24gb2YgZGlzdGFuY2UKICAgIC0gYSBjZW50aW1ldGVyIG9uIHRoZSBwcmludGVkIG1hcCByZXByZXNlbnRzIDEwMCBtZXRlcnMgb2YgZGlzdGFuY2Ugb24gY2FtcHVzCgojIyMjICoqZnJhbWUqKgoKLSBUaGUgcG9zaXRpb24gc2NhbGUgZGVzY3JpYmluZyBob3cgZGF0YSBhcmUgbWFwcGVkIHRvIHRoZSBjb29yZGluYXRlIHN5c3RlbSBpbiB1c2UKLSBRdWl0ZSBvZnRlbiwgdGhlIGZyYW1lIGRlZmluZXMgdGhlIHgtYXhpcyBhbmQgeS1heGlzIG9mIGEgMi1kaW1lbnNpb25hbCBjYXJ0ZXNpYW4gcGxhbmUKCgojIyMjICoqZ3VpZGUqKgoKKiBBbiBpbmRpY2F0aW9uIGZvciB0aGUgaHVtYW4gdmlld2VyIG9mIHRoZSBzY2FsZS4gIFRoaXMgYWxsb3dzIHRoZSB2aWV3ZXIgdG8gdHJhbnNsYXRlIGFlc3RoZXRpY3MgYmFjayBpbnRvIGRhdGEgdmFsdWVzLgoqIEZvciBleGFtcGxlLCAKICAgIC0gYSBsZWdlbmQgbWFrZXMgZXhwbGljaXQgdGhlIG1lYW5pbmcgb2YgUmVkICYgQmx1ZSBwb2ludHMgb24gdGhlIGNoYXJ0CiAgICAtIGEgMSBjbSBsZW5ndGggcHJpbnRlZCBvbiBhIG1hcCB0byBpbmZvcm0gdGhlIHJlYWRlciB0aGF0IGl0IGNvcnJlc3BvbmRzIHRvIDEwMCBtZXRlcnMgb24gY2FtcHVzCgoKIyMgU2NhbGVzCgojIyMjIFRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdmFyaWFibGUgdmFsdWUgYW5kIHRoZSB2YWx1ZSBvZiB0aGUgYWVzdGhldGljIHRoZSB2YXJpYWJsZSBpcyBtYXBwZWQgdG8uCgoqIFN5c3RvbGljIEJsb29kIFByZXNzdXJlIChTQlApIGhhcyB1bml0cyBvZiBtbUhnIChtaWxsaW1ldGVycyBvZiBtZXJjdXJ5KQoqIFBvc2l0aW9uIG9uIHRoZSB4LWF4aXMgbWVhc3VyZWQgaW4gZGlzdGFuY2UsIGUuZy4gaW5jaGVzLgoKVGhlIGNvbnZlcnNpb24gZnJvbSBTQlAgdG8gcG9zaXRpb24gaXMgYSAqc2NhbGUqLgoKKiBTbW9rZXIgaXMgIm5ldmVyIiwgImZvcm1lciIsICJjdXJyZW50IgoqIENvbG9yIGlzIHJlZCwgZ3JlZW4sIGJsdWUsIC4uLgoKVGhlIGNvbnZlcnNpb24gZnJvbSBTbW9rZXIgdG8gY29sb3IgaXMgYSAqc2NhbGUqLgoKCiMjIEd1aWRlcwoKIyMjIyBHdWlkZTogYW4gaW5kaWNhdGlvbiB0byBhIGh1bWFuIHZpZXdlciBvZiB3aGF0IHRoZSBzY2FsZSBpcy4KCiogQXhpcyB0aWNrcyBhbmQgbnVtYmVycwoKIVtdKEltYWdlcy94LWF4aXMtc2NhbGUucG5nKQoKKiBMZWdlbmRzCgohW10oSW1hZ2VzL2NvbG9yLXNjYWxlLnBuZykgCiFbXShJbWFnZXMvc2hhcGUtc2NhbGUucG5nKSAKCgoqIExhYmVscyBvbiBmYWNldGVkIGdyYXBoaWNzCgohW10oSW1hZ2VzL2ZhY2V0LXNjYWxlLnBuZykKCiMjIEZhY2V0cyAKCmBgYHtyIGZpZy5oZWlnaHQ9M30KZ2dwbG90KGRhdGEgPSBUbXAsIGFlcyh4ID0gc2JwLCB5ID0gZGJwLCBjb2xvciA9IHNtb2tlcikpICsKICBnZW9tX3BvaW50KCkgKwogIGZhY2V0X2dyaWQoIH4gc2V4KQpgYGAKCiAqIHggaXMgZGV0ZXJtaW5lZCBieSBgc2JwYCBhbmQgYHNleGAKICogYmFzaWNhbGx5IGEgc2VwYXJhdGUgZnJhbWUgZm9yIGVhY2ggYHNleGAKICogdXNlcyBzYW1lIHggYW5kIHkgdHdpY2UgKG9yIG9uY2UgZm9yIGVhY2ggZmFjZXQpCiAKCiMjIERlc2lnbmluZyBHcmFwaGljcwoKR3JhcGhpY3MgYXJlIGRlc2lnbmVkIGJ5IHRoZSBodW1hbiBleHBlcnQgKHlvdSEpIGluIG9yZGVyIHRvIHJldmVhbCBpbmZvcm1hdGlvbiB0aGF0J3MgcHJlc2VudCBpbiB0aGUgZGF0YS4KCiMjIyMgRGVzaWduIGNob2ljZXMKCgoqIFdoYXQga2luZCBvZiBnbHlwaCwgZS5nLiBzY2F0dGVyLCBkZW5zaXR5LCBiYXIsIC4uLiBtYW55IG90aGVycwoqIFdoYXQgdmFyaWFibGVzIGNvbnN0aXR1dGUgdGhlIGZyYW1lLiBBbmQgc29tZSBkZXRhaWxzOgogICAgLSBheGlzIGxpbWl0cwogICAgLSBsb2dhcml0aG1pYyBheGVzLCBldGMuCiogV2hhdCB2YXJpYWJsZXMgc2hvdWxkIGJlIG1hcHBlZCB0byBvdGhlciBhZXN0aGV0aWNzIG9mIHRoZSBnbHlwaC4KKiBXaGV0aGVyIHRvIGZhY2V0IGFuZCB3aXRoIHdoYXQgdmFyaWFibGUuCgpNb3JlIGRldGFpbHMsIC4uLiwgZS5nLiBzZXR0aW5nIG9mIGFlc3RoZXRpY3MgdG8gY29uc3RhbnRzCgoKIyMgR29vZCBhbmQgQmFkIEdyYXBoaWNzCgpSZW1lbWJlciAuLi4gCgo+IEdyYXBoaWNzIGFyZSBkZXNpZ25lZCBieSB0aGUgaHVtYW4gZXhwZXJ0ICh5b3UhKSBpbiBvcmRlciB0byByZXZlYWwgaW5mb3JtYXRpb24gdGhhdCdzIHByZXNlbnQgaW4gdGhlIGRhdGEuCgotIGNob2ljZXMgZGVwZW5kIG9uIHdoYXQgaW5mb3JtYXRpb24geW91IHdhbnQgdG8gY29udmV5LgotIHByYWN0aWNlIHJlYWRpbmcgZ3JhcGhpY3MgYW5kIGNyaXRpcXVlIHdoaWNoIHdheXMgb2YgYXJyYW5naW5nIHRoaW5nIGFyZSBiZXR0ZXIgb3Igd29yc2UuCi0gQSBiYXNpYyBwcmluY2lwbGUgaXMgdGhhdCBhIGdyYXBoaWMgaXMgYWJvdXQgKmNvbXBhcmlzb24qLiAgR29vZCBncmFwaGljczogCiAgICAtIG1ha2UgaXQgZWFzeSBmb3IgcGVvcGxlIHRvIHBlcmNlaXZlIHRoaW5ncyB0aGF0IGFyZSBzaW1pbGFyIGFuZCB0aGluZ3MgdGhhdCBhcmUgZGlmZmVyZW50LiAgCiAgICAtIHB1dCB0aGUgdGhpbmdzIHRvIGJlIGNvbXBhcmVkIGluIHByb3hpbWl0eSB0byBvbmUgYW5vdGhlciAoZS5nLiwgInNpZGUtYnktc2lkZSIpIAoKCgojIyBDcml0aXF1ZSB0aGlzIGdyYXBoaWMuLi4KCi0gV2hhdCBzb3J0IG9mIGNvbXBhcmlzb25zIG1pZ2h0IHlvdSB3YW50IHRvIG1ha2U/Ci0gRG8geW91IGZpbmQgaXQgZWFzeSBvciBoYXJkIHRvIG1ha2UgdGhvc2UgY29tcGFyaXNvbnM/Ci0gSG93IG1pZ2h0IHRoaXMgZ3JhcGggYmUgaW1wcm92ZWQ/CgpgYGB7cn0KcCArIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gc2V4LCBzaXplID0gc21va2VyKSwgYWxwaGEgPSAuODUpIApgYGAKCiMjIFBlcmNlcHRpb24gYW5kIENvbXBhcmlzb24KCkluIHJvdWdobHkgZGVzY2VuZGluZyBvcmRlciBvZiBodW1hbiBhYmlsaXR5IHRvIGNvbXBhcmUgbmVhcmJ5IG9iamVjdHM6CgoxLiBQb3NpdGlvbgoyLiBMZW5ndGgKMy4gQXJlYQo0LiBBbmdsZQo1LiBTaGFwZSAoYnV0IG9ubHkgYSB2ZXJ5IGZldyBkaWZmZXJlbnQgc2hhcGVzKQo2LiBDb2xvcgoKQ29sb3IgaXMgdGhlIG1vc3QgZGlmZmljdWx0Li4uICAgIAoKICAtIGNvbG9yIGdyYWRpZW50cyAtLS0gd2UncmUgYmV0dGVyIGF0CiAgLSBkaXNjcmV0ZSBjb2xvcnMgLS0tIG11c3QgYmUgY2FyZWZ1bGx5IHNlbGVjdGVkLgogIC0gbG90cyBvZiBwZW9wbGUgYXJlIGNvbG9yIGJsaW5kIChbMSBpbiAxMiBtZW47IDEgaW4gMjAwIHdvbWVuXShodHRwOi8vd3d3LmNvbG91cmJsaW5kYXdhcmVuZXNzLm9yZy8pKQogIApGb3IgbW9yZSwgc2VlOgoKQ2xldmVsYW5kIFcuICgxOTg1KS4gKlRoZSBlbGVtZW50cyBvZiBncmFwaGluZyBkYXRhKi4gQmVsbCBUZWxlcGhvbmUgTGFib3JhdG9yaWVzOiBNdXJyYXkgSGlsbCwgTkouCgoKIyMgR2x5cGgtUmVhZHkgRGF0YQoKR2x5cGgtcmVhZHkgZGF0YSBoYXMgdGhpcyBmb3JtOgoKICAqIFRoZXJlIGlzIG9uZSByb3cgZm9yIGVhY2ggZ2x5cGggdG8gYmUgZHJhd24uIAogICogVGhlIHZhcmlhYmxlcyBpbiB0aGF0IHJvdyBhcmUgbWFwcGVkIHRvIGFlc3RoZXRpY3Mgb2YgdGhlIGdseXBoIChpbmNsdWRpbmcgcG9zaXRpb24pCgoKPGRpdiBjbGFzcz0iY29sdW1ucy0yIj4KKipHbHlwaC1yZWFkeSBkYXRhKioKYGBge3IgZWNobz1GQUxTRX0KaGVhZChUbXAsNikKYGBgCgoqKk1hcHBpbmcgb2YgZGF0YSB0byBhZXN0aGV0aWNzKioKCmBgYAogICBzYnAgaXMgbWFwcGVkIHRvIHggcG9zaXRpb24gICAgICAKICAgZGJwIGlzIG1hcHBlZCB0byB5IHBvc2l0aW9uICAgIApzbW9rZXIgaXMgbWFwcGVkIHRvIGNvbG9yCiAgIHNleCBpcyBtYXBwZWQgdG8gc2hhcGUKYGBgCgpTY2FsZXMgZGV0ZXJtaW5lIGRldGFpbHMgb2YgdHJhbnNsYXRpb24gZnJvbQoKYHZhcmlhYmxlIGlzIG1hcHBlZCB0byBhZXN0aGV0aWNgIAoKYGBge3IgaW5jbHVkZT1GQUxTRX0KVG1wMiA8LSBUbXAgJT4lCiAgcmVuYW1lKHggPSBzYnAsIHkgPSBkYnAsIGNvbG9yID0gc21va2VyLCBzaGFwZSA9IHNleCApCmhlYWQoVG1wMikKYGBgCjwvZGl2PgoKPCEtLQpJdCdzIGFzIGlmIHRoZSB2YXJpYWJsZXMgd2VyZSBnaXZlbiB0aGUgbmFtZSBvZiB0aGUgYWVzdGhldGljLgotLT4KCgoKIyMgTGF5ZXJzIC0tIGJ1aWxkaW5nIHVwIGNvbXBsZXggcGxvdHMgCgpFYWNoIGxheWVyIG1heSBoYXZlIGl0cyBvd24gZGF0YSwgZ2x5cGhzLCBhZXN0aGV0aWMgbWFwcGluZywgZXRjLgoKYGBge3J9CmdncGxvdChkYXRhID0gVG1wLCBhZXMoeCA9IHNicCwgeSA9IGRicCwgY29sb3VyID0gc2V4KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSkgCmBgYAoKICogb25lIGxheWVyIGhhcyBwb2ludHMKICogYW5vdGhlciBsYXllciBoYXMgdGhlIGN1cnZlcwoKIyMgU3RhdHM6IERhdGEgVHJhbnNmb3JtYXRpb25zCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBUbXAsIGFlcyh4ID0gc2JwKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTApCmBgYAoKICAqIFdoYXQgYXJlIHRoZSBnbHlwaHMsIGFlc3RoZXRpY3MsIGd1aWRlcywgZXRjLiBmb3IgdGhpcyBwbG90PwogICogSG93IGlzIHRoZSBkYXRhIGZvciB0aGlzIHBsb3QgcmVsYXRlZCB0byB0aGUgInJhdyIgZGF0YT8KICAKYGBge3J9CmhlYWQoVG1wLCA0KQpgYGAKCiMjIENoYWxsZW5nZSBUYXNrCgpTb3VyY2U6IOKAnENvbGxlZ2UsIHRoZSBHcmVhdCBVbmxldmVsZXLigJ0sIE5ldyBZb3JrIFRpbWVzLCAwMy0wMS0yMDE0IAoKIVtdKGltYWdlcy9DaGFsbGVuZ2UucG5nKQoKIyMjIyBMZWZ0IFBhbmVsIFF1ZXN0aW9uczogCi0gTGVmdCBwYW5lbDogV2hhdCB2YXJpYWJsZXMgbWFrZSB1cCB0aGUgKipmcmFtZSoqPwotIExlZnQgcGFuZWw6IFdoYXQgYXJlIHRoZSAqKmd1aWRlcyoqPwotIExlZnQgcGFuZWw6IFdoYXQgYXJlIHRoZSAqKmdseXBocyoqIGFuZCB3aGF0IGRvIHRoZXkgcmVwcmVzZW50PwotIExlZnQgcGFuZWw6IFNrZXRjaCBhIGZldyByb3dzIG9mIHRoZSBnbHlwaC1yZWFkeSBkYXRhLgoKIyMjIyBSaWdodCBQYW5lbCBRdWVzdGlvbnM6Ci0gUmlnaHQgcGFuZWw6IFdoYXQgYXJlIHRoZSAqKmdseXBocyoqIGFuZCB3aGF0IGRvIHRoZXkgcmVwcmVzZW50PwotIFJpZ2h0IHBhbmVsOiBEZXNjcmliZSB0aHJlZSAqKmFlc3RoZXRpY3MqKiBtYXBwZWQgdG8gdGhlIGdseXBocz8KLSBSaWdodCBwYW5lbDogU2tldGNoIGEgZmV3IHJvd3Mgb2YgdGhlIGdseXBoLXJlYWR5IGRhdGEuCi0gUmlnaHQgcGFuZWw6IE1ha2UgYSByb3VnaCBza2V0Y2ggb2YgYSBzdGFja2VkIGJhciBjaGFydCBzaG93aW5nIHRoZSBzYW1lIGluZm9ybWF0aW9uLgoKIyMgUGFydGlhbCBTb2x1dGlvbiB0byBDaGFsbGVuZ2UgVGFzawoKIyMjIyBMZWZ0IFBhbmVsIFF1ZXN0aW9uczogCi0gTGVmdCBwYW5lbCAqKmZyYW1lKio6IEZyYWN0aW9uIG9mIGZhbWlseSBpbmNvbWUgdG8gcGF5IGZvciBvbmUgeWVhciBvZiBjb2xsZWdlLCBhbmQgeWVhci4gCi0gTGVmdCBwYW5lbCAqKmd1aWRlcyoqOiAKICAgIC0gTGFiZWxzIGZvciB0aGUgZGlmZmVyZW50IHF1aW50aWxlcyBvZiBmYW1pbHkgaW5jb21lLgogICAgLSBBIGxpbmUgc2NhbGluZyB0aGUgYXhpcywgc2hvd2luZyB3aGVyZSB0aGUgZnJhY3Rpb24gb2YgZmFtaWx5IGluY29tZSBpcyAxMDAlLgogICAgLSBUZXh0IHRvIGxhYmVsIHRoZSBleHRlbnQgb2YgdGhlIGhvcml6b250YWwgYXhpcywgZnJvbSAxOTcxIHRvIDIwMTAuCi0gTGVmdCBwYW5lbCAqKmdseXBocyoqOiAKICAgIC0gUG9pbnRzIHJlcHJlc2VudGluZyBmcmFjdGlvbiBvZiBpbmNvbWUKICAgIC0gTGluZXMgY29ubmVjdGluZyAxOTcxIHJlc3VsdCB0byAyMDExIHJlc3VsdCAKLSBMZWZ0IHBhbmVsOiBTa2V0Y2ggYSBmZXcgcm93cyBvZiB0aGUgZ2x5cGgtcmVhZHkgZGF0YS4KCgojIyMjIFJpZ2h0IFBhbmVsIFF1ZXN0aW9uczoKLSBSaWdodCBwYW5lbCAqKmdseXBocyoqOiBzZWdtZW50cyBvZiB0aGUgY2lyY2xlcwotIFJpZ2h0IHBhbmVsIHRocmVlICoqYWVzdGhldGljcyoqOiBjb2xvciwgbGVuZ3RoLCBzaXplIChpLmUuLCByYWRpdXMgb2YgY2lyY2xlKQotIFJpZ2h0IHBhbmVsOiBTa2V0Y2ggYSBmZXcgcm93cyBvZiB0aGUgZ2x5cGgtcmVhZHkgZGF0YS4KLSBSaWdodCBwYW5lbDogTWFrZSBhIHJvdWdoIHNrZXRjaCBvZiBhIHN0YWNrZWQgYmFyIGNoYXJ0IHNob3dpbmcgdGhlIHNhbWUgaW5mb3JtYXRpb24uCgoKIyMgUGF0aCB0byBzdWNjZXNzCgogMS4gKipFeWUtdHJhaW5pbmcqKiAKIAogICAgLSByZWNvZ25pemUgYW5kIGRlc2NyaWJlIGdseXBocywgYWVzdGhldGljcywgc2NhbGVzLCBldGMuCiAgICAtIGlkZW50aWZ5IGRhdGEgcmVxdWlyZWQgZm9yIGEgcGxvdAogICAgCiAyLiAqKkRhdGEgd3JhbmdsaW5nKiogCiAKICAgIC0gZ2V0IGRhdGEgaW50byBnbHlwaC1yZWFkeSBmb3JtYXQgKGBkcGx5cmAsIGB0aWR5cmAsIGB0aWR5dmVyc2VgKQogICAgLSAod2UnbGwgc3RhcnQgZG9pbmcgdGhpcyBuZXh0IHdlZWshKQogICAgCiAzLiAqKkdyYXBoaWNzIGNvbnN0cnVjdGlvbioqIAogICAgCiAgICAtIE5ld2JpZXM6IG1hdGNoIHZhcmlhYmxlcyB0byBhZXN0aGV0aWNzICoqaW50ZXJhY3RpdmVseSoqOiAKICAgICAgICAtIGBlc3F1aXNzZWAgcGFja2FnZSB1c2luZyBgZXNxdWlzc2VyKCApYCAgCiAgICAgICAgLSBgbW9zYWljYCBwYWNrYWdlIHVzaW5nIGBtcGxvdCggKWAgCiAgICAgICAgLSBCT1RIIGdlbmVyYXRlIGBnZ3Bsb3QyYCBzeW50YXggCiAgICAtIFByb3M6IGxlYXJuIHRvIHdyaXRlIGBnZ3Bsb3QyYCBjb2RlIGRpcmVjdGx5CgoKPCEtLSAgLSBgRGF0YUNvbXB1dGluZ2AgcGFja2FnZSB1c2luZyBgc2NhdHRlckdyYXBoSGVscGVyKCApYCwgYGJhckdyYXBoSGVscGVyKCApYCwgYGRlbnNpdHlHcmFwaEhlbHBlciggKWAgLS0+CgoKIyMgUmV2aXNpdGluZyBUaGUgQmlnIE1hYyBJbmRleAoKPGh0dHBzOi8vZ2l0aHViLmNvbS9yZm9yZGF0YXNjaWVuY2UvdGlkeXR1ZXNkYXkvdHJlZS9tYXN0ZXIvZGF0YS8yMDIwLzIwMjAtMTItMjI+CgpgYGB7ciBtZXNzYWdlPUZBTFNFfQojIFRoZXNlIGRhdGEgYXJlIGF2YWlsYWJsZSBmcm9tIHRoZSBgdGlkeXR1ZXNkYXlSYCBwYWNrYWdlIAojIEluc3RhbGwgcGFja2FnZSBmcm9tIENSQU4gdmlhOiBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dHVlc2RheVIiKQoKbGlicmFyeSh0aWR5dHVlc2RheVIpCgpUaWR5VHVlc0RhdGEgPC0gdGlkeXR1ZXNkYXlSOjp0dF9sb2FkKDIwMjAsIHdlZWsgPSA1MikKQmlnTWFjIDwtIFRpZHlUdWVzRGF0YVtbImJpZy1tYWMiXV0KCmBgYAoKCiMjIEJpZyBNYWMgUHJpY2UgdnMgR1BEIHBlciBDYXBpdGE/CgpMZXQncyB1c2UgdGhlIGBlc3F1aXNzZWAgcGFja2FnZSB0byBleHBsb3JlIHRoZSBkYXRhIQoKSW4gdGhlIGNvbnNvbGU6IAoKYGVzcXVpc3NlcihCaWdNYWMpYAoKCmBgYHtyfQpsaWJyYXJ5KGVzcXVpc3NlKQoKIyB1c2UgYGVzcXVpc3NlciggKWAgdG8gZHJhZnQgYSBwbG90IGFuZCB0aGVuIGdlbmVyYXRlIFIgY29kZSB0byBwdXQgaGVyZSEKCmBgYAoKCiMjIyBIZXJlJ3MgYW4gZXhhbXBsZToKCmBgYHtyIGVjaG89RkFMU0V9CmdncGxvdChCaWdNYWMpICsKIGFlcyh4ID0gZ2RwX2RvbGxhciwgeSA9IGRvbGxhcl9wcmljZSkgKwogZ2VvbV9wb2ludChzaXplID0gMUwsIGNvbG91ciA9ICIjMGM0YzhhIikgKwogbGFicyh0aXRsZSA9ICJCaWcgTWFjIFByaWNlIEFyb3VuZCB0aGUgV29ybGQgdnMgR0RQIHBlciBDYXBpdGEiKSArCiB0aGVtZV9taW5pbWFsKCkKYGBgCgotIFVzaW5nIHRoZSBncmFwaCwgd2hhdCBjYW4geW91IHNheSBhYm91dCB0aGUgZm9sbG93aW5nPwogIC0gRnJhbWUgIAogIC0gR2x5cGgKICAtIEFlc3RoZXRpYwogIC0gU2NhbGUKICAtIEd1aWRlCiAgLSBGYWNldAoKCiMjIFZhbHVlIG9mIEJpZyBNYWMgYXJvdW5kIHRoZSB3b3JsZAoKYGBge3J9CiMgdXNpbmcgYG1Xb3JsZE1hcCggKWAgZnJvbSBgbW9zYWljYCBwYWNrYWdlCmxpYnJhcnkobW9zYWljKQoKIyBga2V5YCBhcmd1bWVudCB0YWtlcyB0aGUgSUQgdmFyaWFibGU7IGBmaWxsYCB0YWtlcyB0aGUgbWVhc3VyZWQgdmFyaWFibGUgCm1Xb3JsZE1hcChCaWdNYWMsIGtleSA9ICJpc29fYTMiLCBmaWxsID0gImRvbGxhcl9wcmljZSIpCmBgYAoKLSBVc2luZyB0aGUgZ3JhcGgsIHdoYXQgY2FuIHlvdSBzYXkgYWJvdXQgdGhlIGZvbGxvd2luZz8KICAtIEZyYW1lICAKICAtIEdseXBoCiAgLSBBZXN0aGV0aWMKICAtIFNjYWxlCiAgLSBHdWlkZQogIC0gRmFjZXQKCgoKCgo8IS0tICMjIEFjdGl2aXR5OiAgLS0+Cgo8IS0tIFlvdSdyZSBnb2luZyB0byBwcmFjdGljZSByZXByb2R1Y2luZyBncmFwaHMgdXNpbmcgdGhlIGludGVyYWN0aXZlIFIgZnVuY3Rpb25zIGludHJvZHVjZWQgaW4gdGhlIHJlYWRpbmc6ICAgLS0+CgoKPCEtLSAjIyMjIEhvbWV3b3JrICAgLS0+Cgo8IS0tICoqQWxsIGhvbWV3b3JrLCBhY3Rpdml0aWVzLCBhc3NpZ25tZW50cyBldGMuIGZyb20gbm93IG9uIG11c3QgYmUgc3VibWl0dGVkIHRvIENhbnZhcyBhcyBIVE1MIGZpbGVzIHdpdGggZW1iZWRkZWQgLlJtZCB1bmxlc3Mgb3RoZXJ3aXNlIHN0YXRlZC4qKiAgIC0tPgoKPCEtLSAtIFR1cm4gaW4gR3JhcGggUmVwbGljYXRpb24gQWN0aXZpdHkgKEhUTUwgdG8gQ2FudmFzKSAtLT4KPCEtLSAtIERDIENoIDUgJiA2IEV4ZXJjaXNlcyAoSFRNTCB0byBDYW52YXMpOiA1LjEsIDUuMiwgNi41LCA2LjYsIDYuNywgNi44ICAgLS0+CjwhLS0gLSBEQyBjaGFwdGVyIDcgcmVhZGluZyBxdWl6IG9uIENhbnZhcyAgICAgLS0+Cgo=