Exercises 3.2.4
1 Run ggplot(data=mpg). What do you see?
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy))

Se ve solo un cuadro gris, a menos que le agreguemos la geometria de los puntos.
- How many rows are in mpg? How many columns?
- What does the
drv variable describe?
?mpg
it descrives f=front-wheel drive, r=rear wheel drive, 4=4wd
- Make a scatterplot of
hwy vs cyl
ggplot(data = mpg) +
geom_point(mapping = aes(x = cyl, y = hwy))

- What happens if you make a scatterplot of
class vs drv ? Why is the plot not useful
ggplot(data = mpg) +
geom_point(mapping = aes(x = drv, y =class))

R/ Porque la data de class es discreta y clasificativa al igual que drv
Exercises 3.3.1
- What’s gone wrong with this code? why are the points not blue
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy, color = "red"))

R/ In the color parameter it’s expecting a label not a color
- Which variables in
mpg are categorical? Which variables are continous?
mpg
R/ - categoricas : manufacturer, model, year, trans, fl, class - continuas: displ, cyl, cty, hwy
- Map a continous variable to
color, size and shape
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy, color = displ, size=cyl, shape=class))

R/ Para color y size lo acepta pero para shape solo acepta valores discretos
- What happens if you map the same variable to multple aesthetics
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy, color = class, size=class, shape=class))

R/ a cada categoria se le asigna una figura, tamano y color
- What does the
stroke aesthetic do? what shapes does it work with?
?geom_point
R/ Modifica el ancho de las figuras de la grafica
- What happens if you map aesthetic to something other than a variable name, like
aes(colour = displ < 5)
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy, color = displ < 5))

R/ Asigna dos colores ya que tiene dos categorias, Verdadero y falso
Exercises 3.5.1
- What happens if you facet on a continous variable?
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
facet_wrap(~ hwy, nrow = 2)

R/ Divide la grafica en demasiadas partes y pierde su proposito y legibilidad.
- What do the empty cells in plot with
facet_grid(drv ~ cyl) mean? How do they relate to this plot?
ggplot(data = mpg) +
geom_point(mapping = aes(x = drv, y = cyl)) +
facet_grid(drv ~ cyl)

R/ Agrega un punto por cada facet
- What plots does the following code make? What does . do?
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
facet_grid(drv ~ .)

R/ Segmente la data en 3 grupos de filas, agrupandolos por la variable drv
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
facet_grid(. ~ cyl)

R/ Segmente la data en 3 grupos de columnas, agrupandolos por la variable cyl
- Take the first faceted plot in this section:
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
facet_wrap(~ class, nrow = 2)

ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy, colour = class))

R/ Resulta mucho mas facil visualizar como se esparcen los grupos al separarlo por facet que por color.
- Read
?facet_wrap. What does nrow do? What does ncol do? What other options control the layout of the individual panels? Why doesn’t facet_grid() have nrow and ncol arguments?
?facet_wrap
R/ nrow y ncol limita el numero de filas y columnas a mostrar por el facet, tenemos tambien labeller le agrega etiquedas a cada panel, drop permite quitar ciertos paneles segun una condicion.
?facet_grid
R/ facet_grid() no tiene la funcion de nrow ni ncol porque divide las formas en una matriz segun la data que recibe.
- When using
facet_grid() you should usually put the variable with more unique levels in the columns. Why?
R/ Porque facet_grid() divide en una matriz segun los valores de la columna asignada, entre mas valores unicos tenga, mas divisiones tendra la grafica.
Exercises 3.6.1
- What geom would you use to draw a line chart? A boxplot? A histogram? An area chart?
R/ - line chart: geom_smooth - boxplot: geom_boxplot - histogram: geom_histogram - area chart: geom_area
- Run this code in your head and predict what the output will look like. Then, run the code in R and check your predictions.
ggplot(data = mpg, mapping = aes(x = displ, y = hwy, color = drv)) +
geom_point() +
geom_smooth(se = FALSE)

R/ Dice si debe agregar capas en las leyendas.
- What does show.legend = FALSE do? What happens if you remove it? Why do you think I used it earlier in the chapter?
ggplot(data = mpg, mapping = aes(x = displ, y = hwy, color = drv)) +
geom_point() +
geom_smooth(show.legend = FALSE)

R/ Agrega un area de dispercion para los puntos en la linea que dibuja.
- What does the
se argument to geom_smooth() do?
?geom_smooth
R/ agrega un area que despliega el intervalo de confianza sobre cada punto de las lineas de smooth.
- Will these two graphs look different? Why/why not?
ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth()

ggplot() +
geom_point(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_smooth(data = mpg, mapping = aes(x = displ, y = hwy))

R/ Si son iguales ya que las dos utilizan el mismo aesthetic, la diferencia es que una vez definido el aesthetic en el ggplot, no es necesario replicarlo en el geom_point ni en el geom_smooth
- Recreate the R code necessary to generate the following graphs
ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth(se=FALSE)

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth(mapping = aes(x = displ, y = hwy, group = drv), se = FALSE)

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point(mapping = aes(x = displ, y = hwy, color=drv)) +
geom_smooth(mapping = aes(x = displ, y = hwy, group = drv, color = drv), se = FALSE)

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point(mapping = aes(x = displ, y = hwy, color=drv)) +
geom_smooth(se = FALSE)

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point(mapping = aes(x = displ, y = hwy, color=drv)) +
geom_smooth(mapping = aes(x = displ, y = hwy, linetype=drv), se = FALSE)

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point(size = 4, color = "white") +
geom_point(aes(colour = drv))

Exercises 3.7.1
- What is the default geom associated with
stat_summary()? How could you rewrite the previous plot to use that geom function instead of the stat function?
R/ el default es geom_pointrange()
ggplot(data = diamonds) +
geom_pointrange(
mapping = aes(x = cut, y = depth),
stat = "summary",
)

- What does
geom_col() do? How is it different to geom_bar()?
/R geom_col() se diferencia de geom_bar() en que la geom_col() espera que la data este preprocesada en valores de x y y para representar la altura de las barras.
- Most geoms and stats come in pairs that are almost always used in concert. Read through the documentation and make a list of all the pairs. What do they have in common?
?ggplot
R/ - geom_bar() - geom_col(): controlan graficas de barras - geom_abline() - geom_hline(): Hace referencia a lineas horizontales, verticales y diagonales - geom_freqpoly() - geom_histogram(): permiten crear graficas de histograma y frecuencia - geom_cross() - geom_errorbar() - geom_linerange() - geom_pointrage(): intervalos verticales, lineas, crossbars y errorbars
Como vemos las geom viene en grupos que permiten controlar un tipo determinado de grafica, como por ejemplo geom_bar y geom_col, ambos permiten crear graficas de barras pero de diferente perspectiva y datos.
- What variables does
stat_smooth() compute? What parameters control its behavior?
R/ la funcion calcula las siguientes estadistincas
y |
valor predecido |
ymin |
valor minimo del intervalo de confianza |
ymax |
valor maximo del intervalo de confianza |
se |
Error standard |
- In our proportion bar chart, we need to set
group = 1 Why? In other words what is the problem with these two graphs?
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, y = ..prop..))

ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, fill = color, y = ..prop..))

R/ Si el group es 1 entonces todas las barras tienen prop == 1, entonces la funcion geom_bar() asume que todos los grupos son iguales.
Esto se puede arreglar de la siguiente manera
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, y = ..prop.., group = 1))

ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, fill = color, y = ..prop.., group = color))

Exercise 3.8.1
- What is the problem with this plot? How could you improve it?
ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) +
geom_point()

R/ El problema es que la data se ve demasiado esparcida y uniforme, esto se puede arreglar usando la geom_point() con position='jitter'
ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) +
geom_point(position = "jitter")

- What parameters to
geom_jitter() control the amount of jittering?
?geom_jitter
R/ geom_jitter() controla width y height que permiten definir el espaciado vertical y horizaontal
ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) +
geom_jitter(width = 1, height=1)

Como vemos en la grafica debemos buscar un balance entre width y height de manera que se vea bien la grafica ya que un valor muy alto solo de un parametro afecta la simetria de la grafica.
- Compare and contrast
geom_jitter() with geom_count().
ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) +
geom_jitter()

ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) +
geom_count()

R/ Como vemos geom_jitter() agregar aleatoriamente ruido a cada punto, lo que garantiza que cada punto quede un lugar unico, lo que nos permite mas esparcida la data. geom_count() lo que hace es que le agrega mayor tamano a los puntos con mas densidad o mayores ocurrencias.
- What’s the default position adjustment for
geom_boxplot()? Create a visualisation of the mpg dataset that demonstrates it.
?geom_boxplot
R/ La posicion default es dodge
LS0tDQp0aXRsZTogIkhvamEgZGUgVHJhYmFqbyAyIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3IgZWNobz1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KYGBgDQoNCiMjIEV4ZXJjaXNlcyAzLjIuNA0KDQoxIFJ1biBgZ2dwbG90KGRhdGE9bXBnKWAuIFdoYXQgZG8geW91IHNlZT8NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZykgICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpKQ0KYGBgDQoNClNlIHZlIHNvbG8gdW4gY3VhZHJvIGdyaXMsIGEgbWVub3MgcXVlIGxlIGFncmVndWVtb3MgbGEgZ2VvbWV0cmlhIGRlIGxvcyBwdW50b3MuDQoNCjIuIEhvdyBtYW55IHJvd3MgYXJlIGluIG1wZz8gSG93IG1hbnkgY29sdW1ucz8NCg0KLSByb3dzOiAqKmByIG5yb3cobXBnKWAqKg0KLSBjb2xzOiAqKmByIG5jb2wobXBnKWAqKg0KDQozLiBXaGF0IGRvZXMgdGhlIGBkcnZgIHZhcmlhYmxlIGRlc2NyaWJlPw0KDQpgYGB7cn0NCj9tcGcNCmBgYA0KDQppdCBkZXNjcml2ZXMgYGY9ZnJvbnQtd2hlZWwgZHJpdmUsIHI9cmVhciB3aGVlbCBkcml2ZSwgND00d2RgDQoNCjQuIE1ha2UgYSBzY2F0dGVycGxvdCBvZiBgaHd5YCB2cyBgY3lsYA0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZykgICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gY3lsLCB5ID0gaHd5KSkNCmBgYA0KDQo1LiBXaGF0IGhhcHBlbnMgaWYgeW91IG1ha2UgYSBzY2F0dGVycGxvdCBvZiBgY2xhc3NgIHZzIGBkcnZgID8gV2h5IGlzIHRoZSBwbG90IG5vdCB1c2VmdWwNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZykgICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZHJ2LCB5ID1jbGFzcykpDQpgYGANCg0KUi8gUG9ycXVlIGxhIGRhdGEgZGUgYGNsYXNzYCBlcyBkaXNjcmV0YSB5IGNsYXNpZmljYXRpdmEgYWwgaWd1YWwgcXVlIGRydg0KDQojIyBFeGVyY2lzZXMgMy4zLjENCg0KMS4gV2hhdCdzIGdvbmUgd3Jvbmcgd2l0aCB0aGlzIGNvZGU/IHdoeSBhcmUgdGhlIHBvaW50cyBub3QgYmx1ZQ0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbXBnKSArIA0KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBjb2xvciA9ICJyZWQiKSkNCmBgYA0KDQpSLyBJbiB0aGUgY29sb3IgcGFyYW1ldGVyIGl0J3MgZXhwZWN0aW5nIGEgbGFiZWwgbm90IGEgY29sb3INCg0KMi4gV2hpY2ggdmFyaWFibGVzIGluIGBtcGdgIGFyZSBjYXRlZ29yaWNhbD8gV2hpY2ggdmFyaWFibGVzIGFyZSBjb250aW5vdXM/IA0KDQpgYGB7cn0NCm1wZw0KYGBgDQpSLyANCi0gY2F0ZWdvcmljYXMgOiBtYW51ZmFjdHVyZXIsIG1vZGVsLCB5ZWFyLCB0cmFucywgZmwsIGNsYXNzDQotIGNvbnRpbnVhczogZGlzcGwsIGN5bCwgY3R5LCBod3kNCg0KMy4gTWFwIGEgY29udGlub3VzIHZhcmlhYmxlIHRvIGBjb2xvcmAsIGBzaXplYCBhbmQgYHNoYXBlYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbXBnKSArIA0KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBjb2xvciA9IGRpc3BsLCBzaXplPWN5bCwgc2hhcGU9Y2xhc3MpKQ0KYGBgDQoNClIvIFBhcmEgYGNvbG9yYCB5IGBzaXplYCBsbyBhY2VwdGEgcGVybyBwYXJhIGBzaGFwZWAgc29sbyBhY2VwdGEgdmFsb3JlcyBkaXNjcmV0b3MNCg0KNC4gV2hhdCBoYXBwZW5zIGlmIHlvdSBtYXAgdGhlIHNhbWUgdmFyaWFibGUgdG8gbXVsdHBsZSBhZXN0aGV0aWNzDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3ksIGNvbG9yID0gY2xhc3MsIHNpemU9Y2xhc3MsIHNoYXBlPWNsYXNzKSkNCmBgYA0KDQpSLyBhIGNhZGEgY2F0ZWdvcmlhIHNlIGxlIGFzaWduYSB1bmEgZmlndXJhLCB0YW1hbm8geSBjb2xvcg0KDQo1LiBXaGF0IGRvZXMgdGhlIGBzdHJva2VgIGFlc3RoZXRpYyBkbz8gd2hhdCBzaGFwZXMgZG9lcyBpdCB3b3JrIHdpdGg/DQoNCmBgYHtyfQ0KP2dlb21fcG9pbnQNCmBgYA0KDQpSLyBNb2RpZmljYSBlbCBhbmNobyBkZSBsYXMgZmlndXJhcyBkZSBsYSBncmFmaWNhDQoNCjYuIFdoYXQgaGFwcGVucyBpZiB5b3UgbWFwIGFlc3RoZXRpYyB0byBzb21ldGhpbmcgb3RoZXIgdGhhbiBhIHZhcmlhYmxlIG5hbWUsIGxpa2UgYGFlcyhjb2xvdXIgPSBkaXNwbCA8IDUpYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbXBnKSArIA0KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBjb2xvciA9IGRpc3BsIDwgNSkpDQpgYGANCg0KUi8gQXNpZ25hIGRvcyBjb2xvcmVzIHlhIHF1ZSB0aWVuZSBkb3MgY2F0ZWdvcmlhcywgVmVyZGFkZXJvIHkgZmFsc28NCg0KIyMgRXhlcmNpc2VzIDMuNS4xDQoNCjEuIFdoYXQgaGFwcGVucyBpZiB5b3UgZmFjZXQgb24gYSBjb250aW5vdXMgdmFyaWFibGU/DQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpKSArIA0KICBmYWNldF93cmFwKH4gaHd5LCBucm93ID0gMikNCmBgYA0KDQpSLyBEaXZpZGUgbGEgZ3JhZmljYSBlbiBkZW1hc2lhZGFzIHBhcnRlcyB5IHBpZXJkZSBzdSBwcm9wb3NpdG8geSBsZWdpYmlsaWRhZC4NCg0KMi4gV2hhdCBkbyB0aGUgZW1wdHkgY2VsbHMgaW4gcGxvdCB3aXRoIGBmYWNldF9ncmlkKGRydiB+IGN5bClgIG1lYW4/IEhvdyBkbyB0aGV5IHJlbGF0ZSB0byB0aGlzIHBsb3Q/DQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZHJ2LCB5ID0gY3lsKSkgKw0KICBmYWNldF9ncmlkKGRydiB+IGN5bCkNCmBgYA0KDQpSLyBBZ3JlZ2EgdW4gcHVudG8gcG9yIGNhZGEgZmFjZXQNCg0KMy4gV2hhdCBwbG90cyBkb2VzIHRoZSBmb2xsb3dpbmcgY29kZSBtYWtlPyBXaGF0IGRvZXMgLiBkbz8NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZykgKyANCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBkaXNwbCwgeSA9IGh3eSkpICsNCiAgZmFjZXRfZ3JpZChkcnYgfiAuKQ0KDQpgYGANClIvIFNlZ21lbnRlIGxhIGRhdGEgZW4gMyBncnVwb3MgZGUgZmlsYXMsIGFncnVwYW5kb2xvcyBwb3IgbGEgdmFyaWFibGUgYGRydmANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZykgKyANCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBkaXNwbCwgeSA9IGh3eSkpICsNCiAgZmFjZXRfZ3JpZCguIH4gY3lsKQ0KYGBgDQoNClIvIFNlZ21lbnRlIGxhIGRhdGEgZW4gMyBncnVwb3MgZGUgY29sdW1uYXMsIGFncnVwYW5kb2xvcyBwb3IgbGEgdmFyaWFibGUgYGN5bGANCg0KNC4gVGFrZSB0aGUgZmlyc3QgZmFjZXRlZCBwbG90IGluIHRoaXMgc2VjdGlvbjoNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZykgKyANCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBkaXNwbCwgeSA9IGh3eSkpICsgDQogIGZhY2V0X3dyYXAofiBjbGFzcywgbnJvdyA9IDIpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZykgKyANCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBkaXNwbCwgeSA9IGh3eSwgY29sb3VyID0gY2xhc3MpKQ0KYGBgDQoNClIvIFJlc3VsdGEgbXVjaG8gbWFzIGZhY2lsIHZpc3VhbGl6YXIgY29tbyBzZSBlc3BhcmNlbiBsb3MgZ3J1cG9zIGFsIHNlcGFyYXJsbyBwb3IgZmFjZXQgcXVlIHBvciBjb2xvci4NCg0KNS4gUmVhZCBgP2ZhY2V0X3dyYXBgLiBXaGF0IGRvZXMgYG5yb3dgIGRvPyBXaGF0IGRvZXMgYG5jb2xgIGRvPyBXaGF0IG90aGVyIG9wdGlvbnMgY29udHJvbCB0aGUgbGF5b3V0IG9mIHRoZSBpbmRpdmlkdWFsIHBhbmVscz8gV2h5IGRvZXNu4oCZdCBgZmFjZXRfZ3JpZCgpYCBoYXZlIGBucm93YCBhbmQgYG5jb2xgIGFyZ3VtZW50cz8NCg0KYGBge3J9DQo/ZmFjZXRfd3JhcA0KYGBgDQoNClIvIGBucm93YCB5IGBuY29sYCBsaW1pdGEgZWwgbnVtZXJvIGRlIGZpbGFzIHkgY29sdW1uYXMgYSBtb3N0cmFyIHBvciBlbCBmYWNldCwgdGVuZW1vcyB0YW1iaWVuIGBsYWJlbGxlcmAgbGUgYWdyZWdhIGV0aXF1ZWRhcyBhIGNhZGEgcGFuZWwsIGBkcm9wYCBwZXJtaXRlIHF1aXRhciBjaWVydG9zIHBhbmVsZXMgc2VndW4gdW5hIGNvbmRpY2lvbi4NCg0KYGBge3J9DQo/ZmFjZXRfZ3JpZA0KYGBgDQoNClIvIGBmYWNldF9ncmlkKClgIG5vIHRpZW5lIGxhIGZ1bmNpb24gZGUgYG5yb3dgIG5pIGBuY29sYCBwb3JxdWUgZGl2aWRlIGxhcyBmb3JtYXMgZW4gdW5hIG1hdHJpeiBzZWd1biBsYSBkYXRhIHF1ZSByZWNpYmUuDQoNCjYuIFdoZW4gdXNpbmcgYGZhY2V0X2dyaWQoKWAgeW91IHNob3VsZCB1c3VhbGx5IHB1dCB0aGUgdmFyaWFibGUgd2l0aCBtb3JlIHVuaXF1ZSBsZXZlbHMgaW4gdGhlIGNvbHVtbnMuIFdoeT8NCg0KUi8gUG9ycXVlIGBmYWNldF9ncmlkKClgIGRpdmlkZSBlbiB1bmEgbWF0cml6IHNlZ3VuIGxvcyB2YWxvcmVzIGRlIGxhIGNvbHVtbmEgYXNpZ25hZGEsIGVudHJlIG1hcyB2YWxvcmVzIHVuaWNvcyB0ZW5nYSwgbWFzIGRpdmlzaW9uZXMgdGVuZHJhIGxhIGdyYWZpY2EuDQoNCiMjIEV4ZXJjaXNlcyAzLjYuMQ0KDQoxLiBXaGF0IGdlb20gd291bGQgeW91IHVzZSB0byBkcmF3IGEgbGluZSBjaGFydD8gQSBib3hwbG90PyBBIGhpc3RvZ3JhbT8gQW4gYXJlYSBjaGFydD8NCg0KUi8gDQotIGxpbmUgY2hhcnQ6IGdlb21fc21vb3RoDQotIGJveHBsb3Q6IGdlb21fYm94cGxvdA0KLSBoaXN0b2dyYW06IGdlb21faGlzdG9ncmFtDQotIGFyZWEgY2hhcnQ6IGdlb21fYXJlYQ0KDQoyLiBSdW4gdGhpcyBjb2RlIGluIHlvdXIgaGVhZCBhbmQgcHJlZGljdCB3aGF0IHRoZSBvdXRwdXQgd2lsbCBsb29rIGxpa2UuIFRoZW4sIHJ1biB0aGUgY29kZSBpbiBSIGFuZCBjaGVjayB5b3VyIHByZWRpY3Rpb25zLg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbXBnLCBtYXBwaW5nID0gYWVzKHggPSBkaXNwbCwgeSA9IGh3eSwgY29sb3IgPSBkcnYpKSArIA0KICBnZW9tX3BvaW50KCkgKyANCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSkNCmBgYA0KDQpSLyBEaWNlIHNpIGRlYmUgYWdyZWdhciBjYXBhcyBlbiBsYXMgbGV5ZW5kYXMuDQoNCjMuIFdoYXQgZG9lcyBzaG93LmxlZ2VuZCA9IEZBTFNFIGRvPyBXaGF0IGhhcHBlbnMgaWYgeW91IHJlbW92ZSBpdD8gV2h5IGRvIHlvdSB0aGluayBJIHVzZWQgaXQgZWFybGllciBpbiB0aGUgY2hhcHRlcj8NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZywgbWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3ksIGNvbG9yID0gZHJ2KSkgKyANCiAgZ2VvbV9wb2ludCgpICsgDQogIGdlb21fc21vb3RoKHNob3cubGVnZW5kID0gRkFMU0UpDQpgYGANCg0KUi8gQWdyZWdhIHVuIGFyZWEgZGUgZGlzcGVyY2lvbiBwYXJhIGxvcyBwdW50b3MgZW4gbGEgbGluZWEgcXVlIGRpYnVqYS4NCg0KNC4gV2hhdCBkb2VzIHRoZSBgc2VgIGFyZ3VtZW50IHRvIGBnZW9tX3Ntb290aCgpYCBkbz8NCg0KYGBge3J9DQo/Z2VvbV9zbW9vdGgNCmBgYA0KDQpSLyBhZ3JlZ2EgdW4gYXJlYSBxdWUgZGVzcGxpZWdhIGVsIGludGVydmFsbyBkZSBjb25maWFuemEgc29icmUgY2FkYSBwdW50byBkZSBsYXMgbGluZWFzIGRlIHNtb290aC4NCg0KNS4gV2lsbCB0aGVzZSB0d28gZ3JhcGhzIGxvb2sgZGlmZmVyZW50PyBXaHkvd2h5IG5vdD8NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZywgbWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpKSArIA0KICBnZW9tX3BvaW50KCkgKyANCiAgZ2VvbV9zbW9vdGgoKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KCkgKyANCiAgZ2VvbV9wb2ludChkYXRhID0gbXBnLCBtYXBwaW5nID0gYWVzKHggPSBkaXNwbCwgeSA9IGh3eSkpICsgDQogIGdlb21fc21vb3RoKGRhdGEgPSBtcGcsIG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5KSkNCmBgYA0KUi8gU2kgc29uIGlndWFsZXMgeWEgcXVlIGxhcyBkb3MgdXRpbGl6YW4gZWwgbWlzbW8gYWVzdGhldGljLCBsYSBkaWZlcmVuY2lhIGVzIHF1ZSB1bmEgdmV6IGRlZmluaWRvIGVsIGFlc3RoZXRpYyBlbiBlbCBnZ3Bsb3QsIG5vIGVzIG5lY2VzYXJpbyByZXBsaWNhcmxvIGVuIGVsIGBnZW9tX3BvaW50YCBuaSBlbiBlbCBgZ2VvbV9zbW9vdGhgDQoNCjYuIFJlY3JlYXRlIHRoZSBSIGNvZGUgbmVjZXNzYXJ5IHRvIGdlbmVyYXRlIHRoZSBmb2xsb3dpbmcgZ3JhcGhzDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcsIG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5KSkgKyANCiAgZ2VvbV9wb2ludCgpICsgDQogIGdlb21fc21vb3RoKHNlPUZBTFNFKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcsIG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5KSkgKyANCiAgZ2VvbV9wb2ludCgpICsgDQogIGdlb21fc21vb3RoKG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBncm91cCA9IGRydiksIHNlID0gRkFMU0UpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZywgbWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpKSArIA0KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBjb2xvcj1kcnYpKSArIA0KICBnZW9tX3Ntb290aChtYXBwaW5nID0gYWVzKHggPSBkaXNwbCwgeSA9IGh3eSwgZ3JvdXAgPSBkcnYsIGNvbG9yID0gZHJ2KSwgc2UgPSBGQUxTRSkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbXBnLCBtYXBwaW5nID0gYWVzKHggPSBkaXNwbCwgeSA9IGh3eSkpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3ksIGNvbG9yPWRydikpICsgDQogIGdlb21fc21vb3RoKHNlID0gRkFMU0UpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZywgbWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpKSArIA0KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBjb2xvcj1kcnYpKSArIA0KICBnZW9tX3Ntb290aChtYXBwaW5nID0gYWVzKHggPSBkaXNwbCwgeSA9IGh3eSwgbGluZXR5cGU9ZHJ2KSwgc2UgPSBGQUxTRSkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbXBnLCBtYXBwaW5nID0gYWVzKHggPSBkaXNwbCwgeSA9IGh3eSkpICsgDQogICBnZW9tX3BvaW50KHNpemUgPSA0LCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IGRydikpDQpgYGANCg0KIyMgRXhlcmNpc2VzIDMuNy4xDQoNCjEuIFdoYXQgaXMgdGhlIGRlZmF1bHQgZ2VvbSBhc3NvY2lhdGVkIHdpdGggYHN0YXRfc3VtbWFyeSgpYD8gSG93IGNvdWxkIHlvdSByZXdyaXRlIHRoZSBwcmV2aW91cyBwbG90IHRvIHVzZSB0aGF0IGdlb20gZnVuY3Rpb24gaW5zdGVhZCBvZiB0aGUgc3RhdCBmdW5jdGlvbj8NCg0KUi8gZWwgZGVmYXVsdCBlcyBnZW9tX3BvaW50cmFuZ2UoKQ0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gZGlhbW9uZHMpICsNCiAgZ2VvbV9wb2ludHJhbmdlKA0KICAgIG1hcHBpbmcgPSBhZXMoeCA9IGN1dCwgeSA9IGRlcHRoKSwNCiAgICBzdGF0ID0gInN1bW1hcnkiLA0KICApDQpgYGANCg0KMi4gV2hhdCBkb2VzIGBnZW9tX2NvbCgpYCBkbz8gSG93IGlzIGl0IGRpZmZlcmVudCB0byBgZ2VvbV9iYXIoKWA/DQoNCi9SICBgZ2VvbV9jb2woKWAgc2UgZGlmZXJlbmNpYSBkZSBgZ2VvbV9iYXIoKWAgZW4gcXVlIGxhIGBnZW9tX2NvbCgpYCBlc3BlcmEgcXVlIGxhIGRhdGEgZXN0ZSBwcmVwcm9jZXNhZGEgZW4gdmFsb3JlcyBkZSBgeGAgeSBgeWAgcGFyYSByZXByZXNlbnRhciBsYSBhbHR1cmEgZGUgbGFzIGJhcnJhcy4NCg0KMy4gTW9zdCBnZW9tcyBhbmQgc3RhdHMgY29tZSBpbiBwYWlycyB0aGF0IGFyZSBhbG1vc3QgYWx3YXlzIHVzZWQgaW4gY29uY2VydC4gUmVhZCB0aHJvdWdoIHRoZSBkb2N1bWVudGF0aW9uIGFuZCBtYWtlIGEgbGlzdCBvZiBhbGwgdGhlIHBhaXJzLiBXaGF0IGRvIHRoZXkgaGF2ZSBpbiBjb21tb24/DQoNCmBgYHtyfQ0KP2dncGxvdA0KYGBgDQoNClIvIA0KLSBgZ2VvbV9iYXIoKWAgLSBgZ2VvbV9jb2woKWA6IGNvbnRyb2xhbiBncmFmaWNhcyBkZSBiYXJyYXMNCi0gYGdlb21fYWJsaW5lKClgIC0gYGdlb21faGxpbmUoKWA6IEhhY2UgcmVmZXJlbmNpYSBhIGxpbmVhcyBob3Jpem9udGFsZXMsIHZlcnRpY2FsZXMgeSBkaWFnb25hbGVzDQotIGBnZW9tX2ZyZXFwb2x5KClgIC0gYGdlb21faGlzdG9ncmFtKClgOiBwZXJtaXRlbiBjcmVhciBncmFmaWNhcyBkZSBoaXN0b2dyYW1hIHkgZnJlY3VlbmNpYQ0KLSBgZ2VvbV9jcm9zcygpYCAtIGBnZW9tX2Vycm9yYmFyKClgIC0gYGdlb21fbGluZXJhbmdlKClgIC0gYGdlb21fcG9pbnRyYWdlKClgOiBpbnRlcnZhbG9zIHZlcnRpY2FsZXMsIGxpbmVhcywgY3Jvc3NiYXJzIHkgZXJyb3JiYXJzDQoNCkNvbW8gdmVtb3MgbGFzIGdlb20gdmllbmUgZW4gZ3J1cG9zIHF1ZSBwZXJtaXRlbiBjb250cm9sYXIgdW4gdGlwbyBkZXRlcm1pbmFkbyBkZSBncmFmaWNhLCBjb21vIHBvciBlamVtcGxvIGdlb21fYmFyIHkgZ2VvbV9jb2wsIGFtYm9zIHBlcm1pdGVuIGNyZWFyIGdyYWZpY2FzIGRlIGJhcnJhcyBwZXJvIGRlIGRpZmVyZW50ZSBwZXJzcGVjdGl2YSB5IGRhdG9zLg0KDQo0LiBXaGF0IHZhcmlhYmxlcyBkb2VzIGBzdGF0X3Ntb290aCgpYCBjb21wdXRlPyBXaGF0IHBhcmFtZXRlcnMgY29udHJvbCBpdHMgYmVoYXZpb3I/DQoNClIvIGxhIGZ1bmNpb24gY2FsY3VsYSBsYXMgc2lndWllbnRlcyBlc3RhZGlzdGluY2FzDQoNCnwgdmFyaWFibGUgfCBkZXNjcmlwY2lvbnwNCnwtLS0tLS0tLS0tfC0tLS0tLS0tLS0tLXwNCnxgeWAgICAgICAgfCB2YWxvciBwcmVkZWNpZG98DQp8YHltaW5gICAgIHwgdmFsb3IgbWluaW1vIGRlbCBpbnRlcnZhbG8gZGUgY29uZmlhbnphfA0KfGB5bWF4YCAgICB8IHZhbG9yIG1heGltbyBkZWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YXwNCnxgc2VgICAgICAgfCBFcnJvciBzdGFuZGFyZCB8DQoNCjUuIEluIG91ciBwcm9wb3J0aW9uIGJhciBjaGFydCwgd2UgbmVlZCB0byBzZXQgYGdyb3VwID0gMWAgV2h5PyBJbiBvdGhlciB3b3JkcyB3aGF0IGlzIHRoZSBwcm9ibGVtIHdpdGggdGhlc2UgdHdvIGdyYXBocz8NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzKSArIA0KICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKHggPSBjdXQsIHkgPSAuLnByb3AuLikpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzKSArIA0KICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKHggPSBjdXQsIGZpbGwgPSBjb2xvciwgeSA9IC4ucHJvcC4uKSkNCmBgYA0KUi8gU2kgZWwgYGdyb3VwYCBlcyAxIGVudG9uY2VzIHRvZGFzIGxhcyBiYXJyYXMgdGllbmVuIGBwcm9wID09IDFgLCBlbnRvbmNlcyBsYSBmdW5jaW9uIGBnZW9tX2JhcigpYCBhc3VtZSBxdWUgdG9kb3MgbG9zIGdydXBvcyBzb24gaWd1YWxlcy4NCg0KRXN0byBzZSBwdWVkZSBhcnJlZ2xhciBkZSBsYSBzaWd1aWVudGUgbWFuZXJhDQpgYGB7cn0NCmdncGxvdChkYXRhID0gZGlhbW9uZHMpICsNCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyh4ID0gY3V0LCB5ID0gLi5wcm9wLi4sIGdyb3VwID0gMSkpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzKSArDQogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IGN1dCwgZmlsbCA9IGNvbG9yLCB5ID0gLi5wcm9wLi4sIGdyb3VwID0gY29sb3IpKQ0KYGBgDQoNCiMjIEV4ZXJjaXNlIDMuOC4xDQoNCjEuIFdoYXQgaXMgdGhlIHByb2JsZW0gd2l0aCB0aGlzIHBsb3Q/IEhvdyBjb3VsZCB5b3UgaW1wcm92ZSBpdD8NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZywgbWFwcGluZyA9IGFlcyh4ID0gY3R5LCB5ID0gaHd5KSkgKyANCiAgZ2VvbV9wb2ludCgpDQpgYGANCg0KUi8gRWwgcHJvYmxlbWEgZXMgcXVlIGxhIGRhdGEgc2UgdmUgZGVtYXNpYWRvIGVzcGFyY2lkYSB5IHVuaWZvcm1lLCBlc3RvIHNlIHB1ZWRlIGFycmVnbGFyIHVzYW5kbyBsYSBgZ2VvbV9wb2ludCgpYCBjb24gYHBvc2l0aW9uPSdqaXR0ZXInYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbXBnLCBtYXBwaW5nID0gYWVzKHggPSBjdHksIHkgPSBod3kpKSArDQogIGdlb21fcG9pbnQocG9zaXRpb24gPSAiaml0dGVyIikNCmBgYA0KDQoyLiBXaGF0IHBhcmFtZXRlcnMgdG8gYGdlb21faml0dGVyKClgIGNvbnRyb2wgdGhlIGFtb3VudCBvZiBqaXR0ZXJpbmc/DQoNCmBgYHtyfQ0KP2dlb21faml0dGVyDQpgYGANCg0KUi8gYGdlb21faml0dGVyKClgIGNvbnRyb2xhIGB3aWR0aGAgeSBgaGVpZ2h0YCBxdWUgcGVybWl0ZW4gZGVmaW5pciBlbCBlc3BhY2lhZG8gdmVydGljYWwgeSBob3JpemFvbnRhbCANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZywgbWFwcGluZyA9IGFlcyh4ID0gY3R5LCB5ID0gaHd5KSkgKw0KICBnZW9tX2ppdHRlcih3aWR0aCA9IDEsIGhlaWdodD0xKQ0KYGBgDQpDb21vIHZlbW9zIGVuIGxhIGdyYWZpY2EgZGViZW1vcyBidXNjYXIgdW4gYmFsYW5jZSBlbnRyZSBgd2lkdGhgIHkgYGhlaWdodGAgZGUgbWFuZXJhIHF1ZSBzZSB2ZWEgYmllbiBsYSBncmFmaWNhIHlhIHF1ZSB1biB2YWxvciBtdXkgYWx0byBzb2xvIGRlIHVuIHBhcmFtZXRybyBhZmVjdGEgbGEgc2ltZXRyaWEgZGUgbGEgZ3JhZmljYS4NCg0KMy4gQ29tcGFyZSBhbmQgY29udHJhc3QgYGdlb21faml0dGVyKClgIHdpdGggYGdlb21fY291bnQoKWAuDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcsIG1hcHBpbmcgPSBhZXMoeCA9IGN0eSwgeSA9IGh3eSkpICsNCiAgZ2VvbV9qaXR0ZXIoKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcsIG1hcHBpbmcgPSBhZXMoeCA9IGN0eSwgeSA9IGh3eSkpICsNCiAgZ2VvbV9jb3VudCgpDQpgYGANCg0KUi8gQ29tbyB2ZW1vcyBgZ2VvbV9qaXR0ZXIoKWAgYWdyZWdhciBhbGVhdG9yaWFtZW50ZSBydWlkbyBhIGNhZGEgcHVudG8sIGxvIHF1ZSBnYXJhbnRpemEgcXVlIGNhZGEgcHVudG8gcXVlZGUgdW4gbHVnYXIgdW5pY28sIGxvIHF1ZSBub3MgcGVybWl0ZSBtYXMgZXNwYXJjaWRhIGxhIGRhdGEuIGBnZW9tX2NvdW50KClgIGxvIHF1ZSBoYWNlIGVzIHF1ZSBsZSBhZ3JlZ2EgbWF5b3IgdGFtYW5vIGEgbG9zIHB1bnRvcyBjb24gbWFzIGRlbnNpZGFkIG8gbWF5b3JlcyBvY3VycmVuY2lhcy4NCg0KNC4gV2hhdOKAmXMgdGhlIGRlZmF1bHQgcG9zaXRpb24gYWRqdXN0bWVudCBmb3IgYGdlb21fYm94cGxvdCgpYD8gQ3JlYXRlIGEgdmlzdWFsaXNhdGlvbiBvZiB0aGUgbXBnIGRhdGFzZXQgdGhhdCBkZW1vbnN0cmF0ZXMgaXQuDQoNCmBgYHtyfQ0KP2dlb21fYm94cGxvdA0KYGBgDQoNClIvIExhIHBvc2ljaW9uIGRlZmF1bHQgZXMgYGRvZGdlYA0K