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.

  1. How many rows are in mpg? How many columns?
  1. What does the drv variable describe?
?mpg

it descrives f=front-wheel drive, r=rear wheel drive, 4=4wd

  1. Make a scatterplot of hwy vs cyl
ggplot(data = mpg)  + 
  geom_point(mapping = aes(x = cyl, y = hwy))

  1. 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

  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

  1. Which variables in mpg are categorical? Which variables are continous?
mpg

R/ - categoricas : manufacturer, model, year, trans, fl, class - continuas: displ, cyl, cty, hwy

  1. 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

  1. 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

  1. What does the stroke aesthetic do? what shapes does it work with?
?geom_point

R/ Modifica el ancho de las figuras de la grafica

  1. 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

  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.

  1. 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

  1. 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

  1. 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.

  1. 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.

  1. 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

  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

  1. 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.

  1. 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.

  1. 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.

  1. 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

  1. 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

  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",
  )

  1. 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.

  1. 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.

  1. What variables does stat_smooth() compute? What parameters control its behavior?

R/ la funcion calcula las siguientes estadistincas

variable descripcion
y valor predecido
ymin valor minimo del intervalo de confianza
ymax valor maximo del intervalo de confianza
se Error standard
  1. 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

  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")

  1. 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.

  1. 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.

  1. 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