1 Gráfico de líneas

El gráfico de serie de tiempo se puede elaborar a través de un gráfico de líneas. Spotify es un conjunto de valores que se distribuye a lo largo del tiempo, un gráfico de línea o serie de tiempo es lo ideal para visualizarlo. Se puede apreciar que la canción “Despacito” fue la que mayor cantidad de reproducciones obtuvo, alcanzando el pico de 20M de reproducciones en Junio de 2017.

2 Gráfico de caja

Cuando se desea observar la variación que existe en una variable, el boxplot permite visualizar fácilmente la ubicación de los cuartiles, así como la existencia (o no) de puntos atípicos más allá de los “bigotes”. Basándonos en la mediana, Parece que Toyota es la marca que tiene más kilómetros recorridos antes de su primer re-venta, cabe señalar que es la que más variación presenta entre sus datos, teniendo además casi 10 valores muy atípicos por encima del 3er cuartil.

3 Gráficos de barras

Los gráficos de barra son ideales para visualizar variable categóricas. Cuando se emplea el apilado, es importante que no haya más de 3 categorías pues son complejos de analizar luego de observar la categoría de la base, este es útil para mostrar totales. Para hacer comparativas, suele ser más funcional el gráfico de barras agrupado. Existen dos funciones básicas: geom_bar es utilizado para hacer conteo de casos, geom_col representa las alturas de la barra en función de alguna variable.

4 Gráficos de barras con facet_wrap

La función facet_wrap permite segmentar gráficos de acuerdo a los niveles de una variable cualitativa

5 Gráficos de línea/pendiente

Para representar de forma simple la relación entre dos variables cualitativas, el gráfico de líneas o pendiente es una alternativa adecuada, sobre todo cuando las variables (factores) se pueden arreglar por niveles.

## # A tibble: 12 × 3
## # Groups:   Product_Category [3]
##    Product_Category Region    Sales
##    <chr>            <chr>     <dbl>
##  1 Furniture        Central 155294.
##  2 Furniture        East    196332.
##  3 Furniture        South   113067.
##  4 Furniture        West    196011.
##  5 Office Supplies  Central 115120.
##  6 Office Supplies  East    211784.
##  7 Office Supplies  South   112566.
##  8 Office Supplies  West    111898.
##  9 Technology       Central 177871.
## 10 Technology       East    184055.
## 11 Technology       South   131472.
## 12 Technology       West    218868.

6 Ejercicios individuales

A continuación se presentan 3 ejercicios de visualización presentados en clase sobre la base de datos ‘Super Store, iniciando con ’Total de ventas por Categoría de Producto según el Segmento del Cliente’ ## Total de ventas por Categoría de Producto según el Segmento del Cliente

## List of 136
##  $ line                            :List of 6
##   ..$ colour       : chr "black"
##   ..$ linewidth    : num 0.5
##   ..$ linetype     : num 1
##   ..$ lineend      : chr "butt"
##   ..$ arrow        : logi FALSE
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_line" "element"
##  $ rect                            :List of 5
##   ..$ fill         : chr "white"
##   ..$ colour       : chr "black"
##   ..$ linewidth    : num 0.5
##   ..$ linetype     : num 1
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_rect" "element"
##  $ text                            :List of 11
##   ..$ family       : chr ""
##   ..$ face         : chr "plain"
##   ..$ colour       : chr "black"
##   ..$ size         : num 11
##   ..$ hjust        : num 0.5
##   ..$ vjust        : num 0.5
##   ..$ angle        : num 0
##   ..$ lineheight   : num 0.9
##   ..$ margin       : 'margin' num [1:4] 0points 0points 0points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : logi FALSE
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ title                           : NULL
##  $ aspect.ratio                    : NULL
##  $ axis.title                      : NULL
##  $ axis.title.x                    :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 1
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 2.75points 0points 0points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.title.x.top                :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 0
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 0points 2.75points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.title.x.bottom             : NULL
##  $ axis.title.y                    :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 1
##   ..$ angle        : num 90
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 2.75points 0points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.title.y.left               : NULL
##  $ axis.title.y.right              :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 1
##   ..$ angle        : num -90
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 0points 0points 2.75points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.text                       :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : chr "grey30"
##   ..$ size         : 'rel' num 0.8
##   ..$ hjust        : NULL
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : NULL
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.text.x                     :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 1
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 2.2points 0points 0points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.text.x.top                 :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 0
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 0points 2.2points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.text.x.bottom              : NULL
##  $ axis.text.y                     :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : num 1
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 2.2points 0points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.text.y.left                : NULL
##  $ axis.text.y.right               :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : num 0
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 0points 0points 2.2points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.text.theta                 : NULL
##  $ axis.text.r                     :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : num 0.5
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 2.2points 0points 2.2points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.ticks                      : list()
##   ..- attr(*, "class")= chr [1:2] "element_blank" "element"
##  $ axis.ticks.x                    : NULL
##  $ axis.ticks.x.top                : NULL
##  $ axis.ticks.x.bottom             : NULL
##  $ axis.ticks.y                    : NULL
##  $ axis.ticks.y.left               : NULL
##  $ axis.ticks.y.right              : NULL
##  $ axis.ticks.theta                : NULL
##  $ axis.ticks.r                    : NULL
##  $ axis.minor.ticks.x.top          : NULL
##  $ axis.minor.ticks.x.bottom       : NULL
##  $ axis.minor.ticks.y.left         : NULL
##  $ axis.minor.ticks.y.right        : NULL
##  $ axis.minor.ticks.theta          : NULL
##  $ axis.minor.ticks.r              : NULL
##  $ axis.ticks.length               : 'simpleUnit' num 2.75points
##   ..- attr(*, "unit")= int 8
##  $ axis.ticks.length.x             : NULL
##  $ axis.ticks.length.x.top         : NULL
##  $ axis.ticks.length.x.bottom      : NULL
##  $ axis.ticks.length.y             : NULL
##  $ axis.ticks.length.y.left        : NULL
##  $ axis.ticks.length.y.right       : NULL
##  $ axis.ticks.length.theta         : NULL
##  $ axis.ticks.length.r             : NULL
##  $ axis.minor.ticks.length         : 'rel' num 0.75
##  $ axis.minor.ticks.length.x       : NULL
##  $ axis.minor.ticks.length.x.top   : NULL
##  $ axis.minor.ticks.length.x.bottom: NULL
##  $ axis.minor.ticks.length.y       : NULL
##  $ axis.minor.ticks.length.y.left  : NULL
##  $ axis.minor.ticks.length.y.right : NULL
##  $ axis.minor.ticks.length.theta   : NULL
##  $ axis.minor.ticks.length.r       : NULL
##  $ axis.line                       : list()
##   ..- attr(*, "class")= chr [1:2] "element_blank" "element"
##  $ axis.line.x                     : NULL
##  $ axis.line.x.top                 : NULL
##  $ axis.line.x.bottom              : NULL
##  $ axis.line.y                     : NULL
##  $ axis.line.y.left                : NULL
##  $ axis.line.y.right               : NULL
##  $ axis.line.theta                 : NULL
##  $ axis.line.r                     : NULL
##  $ legend.background               : list()
##   ..- attr(*, "class")= chr [1:2] "element_blank" "element"
##  $ legend.margin                   : 'margin' num [1:4] 5.5points 5.5points 5.5points 5.5points
##   ..- attr(*, "unit")= int 8
##  $ legend.spacing                  : 'simpleUnit' num 11points
##   ..- attr(*, "unit")= int 8
##  $ legend.spacing.x                : NULL
##  $ legend.spacing.y                : NULL
##  $ legend.key                      : list()
##   ..- attr(*, "class")= chr [1:2] "element_blank" "element"
##  $ legend.key.size                 : 'simpleUnit' num 1.2lines
##   ..- attr(*, "unit")= int 3
##  $ legend.key.height               : NULL
##  $ legend.key.width                : NULL
##  $ legend.key.spacing              : 'simpleUnit' num 5.5points
##   ..- attr(*, "unit")= int 8
##  $ legend.key.spacing.x            : NULL
##  $ legend.key.spacing.y            : NULL
##  $ legend.frame                    : NULL
##  $ legend.ticks                    : NULL
##  $ legend.ticks.length             : 'rel' num 0.2
##  $ legend.axis.line                : NULL
##  $ legend.text                     :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : 'rel' num 0.8
##   ..$ hjust        : NULL
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : NULL
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ legend.text.position            : NULL
##  $ legend.title                    :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : num 0
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : NULL
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ legend.title.position           : NULL
##  $ legend.position                 : chr "right"
##  $ legend.position.inside          : NULL
##  $ legend.direction                : NULL
##  $ legend.byrow                    : NULL
##  $ legend.justification            : chr "center"
##  $ legend.justification.top        : NULL
##  $ legend.justification.bottom     : NULL
##  $ legend.justification.left       : NULL
##  $ legend.justification.right      : NULL
##  $ legend.justification.inside     : NULL
##  $ legend.location                 : NULL
##  $ legend.box                      : NULL
##  $ legend.box.just                 : NULL
##  $ legend.box.margin               : 'margin' num [1:4] 0cm 0cm 0cm 0cm
##   ..- attr(*, "unit")= int 1
##  $ legend.box.background           : list()
##   ..- attr(*, "class")= chr [1:2] "element_blank" "element"
##  $ legend.box.spacing              : 'simpleUnit' num 11points
##   ..- attr(*, "unit")= int 8
##   [list output truncated]
##  - attr(*, "class")= chr [1:2] "theme" "gg"
##  - attr(*, "complete")= logi TRUE
##  - attr(*, "validate")= logi TRUE

La gráfica nos muestra que la Categoría de Producto con mas ventas es ‘Technology’, después ‘Furniture’ y, finalmente ‘Office Supplies’. En cuanto al segmento de cliente, se ve en color verde como el segmento ’Corporate; es el que mas representa las ventas, lo cual es entendible pues son los que mas tendrían dinero, por así decirlo para comprar productos para sus oficinas.

6.1 Método de envío por el segmento de cliente

Se observa que el Método de Envío ‘Number of Air’ es el mas utilizado en todos los segmentos, después le sigue el ‘Delivery Truck’. Al igual que mi suposición en la gráfica pasada, el segmento ‘Corporate’ es el que me has tiene número de pedidos, debido a que tienen mas oportunidad económicamente.

6.2 Ventas totales de cada categoría por región

Los productos de la categoría de ‘Technology’ son los más vendidos en 2 regiones: ‘South’ y ‘West’, mientras que en ‘Central’ e ‘East’ ‘Office Supplies’ lleva mas ventaja.

7 Ggplot avanzado: diagramas de dispersión

8 Ggplot avanzado: boxplot con etiquetas personalizadas

LS0tCnRpdGxlOiAiTMOtbmVhcyBkZSBBY2Npw7NuIEVzdHJhdMOpZ2ljYXMgfCBNYXLDrWEgU8OhZW56IFBhcsOhcyIKZGF0ZTogIjIwMjQtMTEtMTMiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQogICAgdG9jX2RlcHRoOiAxCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBsdW1lbgotLS0KCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0KI2luc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpCmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiMwMDMzOTk7Ij5HcsOhZmljbyBkZSBsw61uZWFzPC9zcGFuPgpFbCBncsOhZmljbyBkZSBzZXJpZSBkZSB0aWVtcG8gc2UgcHVlZGUgZWxhYm9yYXIgYSB0cmF2w6lzIGRlIHVuIGdyw6FmaWNvIGRlIGzDrW5lYXMuIFNwb3RpZnkgZXMgdW4gY29uanVudG8gZGUgdmFsb3JlcyBxdWUgc2UgZGlzdHJpYnV5ZSBhIGxvIGxhcmdvIGRlbCB0aWVtcG8sIHVuIGdyw6FmaWNvIGRlIGzDrW5lYSBvIHNlcmllIGRlIHRpZW1wbyBlcyBsbyBpZGVhbCBwYXJhIHZpc3VhbGl6YXJsby4gU2UgcHVlZGUgYXByZWNpYXIgcXVlIGxhIGNhbmNpw7NuICJEZXNwYWNpdG8iIGZ1ZSBsYSBxdWUgbWF5b3IgY2FudGlkYWQgZGUgcmVwcm9kdWNjaW9uZXMgb2J0dXZvLCAgYWxjYW56YW5kbyBlbCBwaWNvIGRlIDIwTSBkZSByZXByb2R1Y2Npb25lcyBlbiBKdW5pbyBkZSAyMDE3LiAgCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRX0Kc3BvdGlmeSA8LSByZWFkLmNzdigic3BvdGlmeS5jc3YiKQp2aWV3KHNwb3RpZnkpCgoKc3BvdGlmeV9tZWx0ZWQgPC0gcGl2b3RfbG9uZ2VyKHNwb3RpZnksU2hhcGUub2YuWW91OlVuZm9yZ2V0dGFibGUsbmFtZXNfdG8gPSAiU29uZyIsdmFsdWVzX3RvID0gIlJlcHJvZHVjdGlvbnMiKQp2aWV3KHNwb3RpZnlfbWVsdGVkKQoKZ2dwbG90KHNwb3RpZnlfbWVsdGVkLGFlcyhEYXRlLFJlcHJvZHVjdGlvbnMsY29sPVNvbmcsbGluZXR5cGUgPSBTb25nKSkgK2dlb21fbGluZSgpK3RoZW1lX21pbmltYWwoKStsYWJzKHg9IkRhdGUiKQoKZ2dwbG90KHNwb3RpZnlfbWVsdGVkLGFlcyhwYXJzZV9kYXRldGltZShEYXRlKSxSZXByb2R1Y3Rpb25zLGNvbD1Tb25nLGxpbmV0eXBlID0gU29uZykpICtnZW9tX2xpbmUoKSt0aGVtZV9taW5pbWFsKCkrbGFicyh4PSJEYXRlIikKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjojMDAzMzk5OyI+R3LDoWZpY28gZGUgY2FqYTwvc3Bhbj4KQ3VhbmRvIHNlIGRlc2VhIG9ic2VydmFyIGxhIHZhcmlhY2nDs24gcXVlIGV4aXN0ZSBlbiB1bmEgdmFyaWFibGUsIGVsIGJveHBsb3QgcGVybWl0ZSB2aXN1YWxpemFyIGbDoWNpbG1lbnRlIGxhIHViaWNhY2nDs24gZGUgbG9zIGN1YXJ0aWxlcywgYXPDrSBjb21vIGxhIGV4aXN0ZW5jaWEgKG8gbm8pIGRlIHB1bnRvcyBhdMOtcGljb3MgbcOhcyBhbGzDoSBkZSBsb3MgImJpZ290ZXMiLiBCYXPDoW5kb25vcyBlbiBsYSBtZWRpYW5hLCBQYXJlY2UgcXVlIFRveW90YSBlcyBsYSBtYXJjYSBxdWUgdGllbmUgbcOhcyBraWzDs21ldHJvcyByZWNvcnJpZG9zIGFudGVzIGRlIHN1IHByaW1lciByZS12ZW50YSwgY2FiZSBzZcOxYWxhciBxdWUgZXMgbGEgcXVlIG3DoXMgdmFyaWFjacOzbiBwcmVzZW50YSBlbnRyZSBzdXMgZGF0b3MsIHRlbmllbmRvIGFkZW3DoXMgY2FzaSAxMCB2YWxvcmVzIG11eSBhdMOtcGljb3MgcG9yIGVuY2ltYSBkZWwgM2VyIGN1YXJ0aWwuIAoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0V9CmNhcnMgPC0gcmVhZC5jc3YoIkNhcnNkYXRhc2V0LmNzdiIpCnZpZXcoY2FycykKI25hbWVzKGNhcnMpCm9wdGlvbnMoc2NpcGVuID0gOTk5KQoKY2FycyAlPiUgCiAgZmlsdGVyKGJyYW5kICVpbiUgYygiVG95b3RhIiwiVm9sa3N3YWdlbiIsIkhvbmRhIiwiRm9yZCIsIkF1ZGkiLCJCTVciKSkgJT4lIAogIGZpbHRlcihrbV9kcml2ZW48MTUwMDAwMCkgJT4lIAogIGZpbHRlcihvd25lcj09IkZpcnN0IE93bmVyIikgJT4lIAogIGdncGxvdChhZXMoeD1icmFuZCx5PWttX2RyaXZlbixmaWxsPWJyYW5kKSkrZ2VvbV9ib3hwbG90KCkrdGhlbWVfbWluaW1hbCgpK3RoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUpKStsYWJzKHg9IkNhciBicmFuZCIseT0iS21zIGRyaXZlbiIsdGl0bGU9IkttcyBkcml2ZW4gYmVmb3JlIDFzdCByZS1zYWxlIikKCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IzAwMzM5OTsiPkdyw6FmaWNvcyBkZSBiYXJyYXM8L3NwYW4+CkxvcyBncsOhZmljb3MgZGUgYmFycmEgc29uIGlkZWFsZXMgcGFyYSB2aXN1YWxpemFyIHZhcmlhYmxlIGNhdGVnw7NyaWNhcy4gQ3VhbmRvIHNlIGVtcGxlYSBlbCBhcGlsYWRvLCBlcyBpbXBvcnRhbnRlIHF1ZSBubyBoYXlhIG3DoXMgZGUgMyBjYXRlZ29yw61hcyBwdWVzIHNvbiBjb21wbGVqb3MgZGUgYW5hbGl6YXIgbHVlZ28gZGUgb2JzZXJ2YXIgbGEgY2F0ZWdvcsOtYSBkZSBsYSBiYXNlLCBlc3RlIGVzIMO6dGlsIHBhcmEgbW9zdHJhciB0b3RhbGVzLiBQYXJhIGhhY2VyIGNvbXBhcmF0aXZhcywgc3VlbGUgc2VyIG3DoXMgZnVuY2lvbmFsIGVsIGdyw6FmaWNvIGRlIGJhcnJhcyBhZ3J1cGFkby4gRXhpc3RlbiBkb3MgZnVuY2lvbmVzIGLDoXNpY2FzOiBnZW9tX2JhciBlcyB1dGlsaXphZG8gcGFyYSBoYWNlciBjb250ZW8gZGUgY2Fzb3MsIGdlb21fY29sIHJlcHJlc2VudGEgbGFzIGFsdHVyYXMgZGUgbGEgYmFycmEgZW4gZnVuY2nDs24gZGUgYWxndW5hIHZhcmlhYmxlLiAKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQpzdG9yZSA8LSByZWFkLmNzdigiU3VwZXJTdG9yZVVTLmNzdiIpCgojZ2xpbXBzZShzdG9yZSkKCm9wdGlvbnMoc2NpcGVuID0gOTk5KQoKZ2dwbG90KHN0b3JlLGFlcyh4PUN1c3RvbWVyX1NlZ21lbnQsZmlsbD1TaGlwX01vZGUpKStnZW9tX2Jhcihwb3NpdGlvbj0iZG9kZ2UiKSt0aGVtZV9taW5pbWFsKCkrbGFicyh4PSJDdXN0b21lciBzZWdtZW50Iix5PSJOdW1iZXIgb2Ygb3JkZXJzIikKCmdncGxvdChzdG9yZSxhZXMoeD1DdXN0b21lcl9TZWdtZW50LGZpbGw9U2hpcF9Nb2RlKSkrZ2VvbV9iYXIocG9zaXRpb249InN0YWNrIikrdGhlbWVfbWluaW1hbCgpK2xhYnMoeD0iQ3VzdG9tZXIgc2VnbWVudCIseT0iTnVtYmVyIG9mIG9yZGVycyIpCgpnZ3Bsb3Qoc3RvcmUsYWVzKHg9Q3VzdG9tZXJfU2VnbWVudCx5PVNhbGVzLGZpbGw9U2hpcF9Nb2RlKSkrZ2VvbV9jb2wocG9zaXRpb249InN0YWNrIikrdGhlbWVfbWluaW1hbCgpK2xhYnMoeD0iQ3VzdG9tZXIgc2VnbWVudCIseT0iVG90YWwgU2FsZXMiKQpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiMwMDMzOTk7Ij5HcsOhZmljb3MgZGUgYmFycmFzIGNvbiBmYWNldF93cmFwPC9zcGFuPgpMYSBmdW5jacOzbiBmYWNldF93cmFwIHBlcm1pdGUgc2VnbWVudGFyIGdyw6FmaWNvcyBkZSBhY3VlcmRvIGEgbG9zIG5pdmVsZXMgZGUgdW5hIHZhcmlhYmxlIGN1YWxpdGF0aXZhCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQpzdG9yZSAlPiUgCiAgZ2dwbG90KGFlcyh4PVByb2R1Y3RfQ2F0ZWdvcnkseT1TYWxlcyxsYWJlbD1zdW0oU2FsZXMpLGZpbGw9Q3VzdG9tZXJfU2VnbWVudCkpK2dlb21fY29sKHBvc2l0aW9uID0gInN0YWNrIikrdGhlbWVfbWluaW1hbCgpK2xhYnMoeD0iUHJvZHVjdCBDYXRlZ29yeSIseT0iVG90YWwgc2FsZXMiKStmYWNldF93cmFwKH5SZWdpb24pCgoKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjojMDAzMzk5OyI+R3LDoWZpY29zIGRlIGzDrW5lYS9wZW5kaWVudGU8L3NwYW4+ClBhcmEgcmVwcmVzZW50YXIgZGUgZm9ybWEgc2ltcGxlIGxhIHJlbGFjacOzbiBlbnRyZSBkb3MgdmFyaWFibGVzIGN1YWxpdGF0aXZhcywgZWwgZ3LDoWZpY28gZGUgbMOtbmVhcyBvIHBlbmRpZW50ZSBlcyB1bmEgYWx0ZXJuYXRpdmEgYWRlY3VhZGEsIHNvYnJlIHRvZG8gY3VhbmRvIGxhcyB2YXJpYWJsZXMgKGZhY3RvcmVzKSBzZSBwdWVkZW4gYXJyZWdsYXIgcG9yIG5pdmVsZXMuIAoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsICBlY2hvPUZBTFNFfQpzdG9yZTIgPC0gc3RvcmUgJT4lIAogIGdyb3VwX2J5KFByb2R1Y3RfQ2F0ZWdvcnksUmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKFNhbGVzPXN1bShTYWxlcykpCnN0b3JlMgoKZ2dwbG90KHN0b3JlMixhZXMoeD1Qcm9kdWN0X0NhdGVnb3J5LHk9U2FsZXMsY29sPVJlZ2lvbixncm91cD1SZWdpb24pKStnZW9tX2xpbmUoKStnZW9tX3BvaW50KCkrdGhlbWVfbWluaW1hbCgpCmBgYAoKCgojIDxzcGFuIHN0eWxlPSJjb2xvcjojMDAzMzk5OyI+RWplcmNpY2lvcyBpbmRpdmlkdWFsZXM8L3NwYW4+CkEgY29udGludWFjacOzbiBzZSBwcmVzZW50YW4gMyBlamVyY2ljaW9zIGRlIHZpc3VhbGl6YWNpw7NuIHByZXNlbnRhZG9zIGVuIGNsYXNlIHNvYnJlIGxhIGJhc2UgZGUgZGF0b3MgJ1N1cGVyIFN0b3JlLCBpbmljaWFuZG8gY29uICdUb3RhbCBkZSB2ZW50YXMgcG9yIENhdGVnb3LDrWEgZGUgUHJvZHVjdG8gc2Vnw7puIGVsIFNlZ21lbnRvIGRlbCBDbGllbnRlJwojIyA8c3BhbiBzdHlsZT0iY29sb3I6IzAwMzM5OTsiPlRvdGFsIGRlIHZlbnRhcyBwb3IgQ2F0ZWdvcsOtYSBkZSBQcm9kdWN0byBzZWfDum4gZWwgU2VnbWVudG8gZGVsIENsaWVudGU8L3NwYW4+CgpgYGB7ciwgZWNobz1GQUxTRX0KZ2dwbG90KHN0b3JlLCBhZXMoeCA9IFByb2R1Y3RfQ2F0ZWdvcnksIHkgPSBTYWxlcywgZmlsbCA9IEN1c3RvbWVyX1NlZ21lbnQpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAic3RhY2siKSsKICBsYWJzKHRpdGxlID0gIlRvdGFsIGRlIFZlbnRhcyBwb3IgQ2F0ZWdvcsOtYSBkZSBQcm9kdWN0byBzZWfDum4gZWwgU2VnbWVudG8gZGVsIENsaWVudGUiLAogICAgICAgeCA9ICJDYXRlZ29yw61hIGRlIFByb2R1Y3RvIiwgeSA9ICJUb3RhbCBkZSBWZW50YXMiLCBmaWxsID0gIkN1c3RvbWVyIFNlZ21lbnQiKQojK3NjYWxlX3lfY29udGludW9zKGJyZWFrcz1jKDEwMDAwMCwyMDAwMDAsMzAwMDAwLDQwMDAwMCw1MDAwMDAsNjAwMDAwLDcwMDAwMCkpLCAjbGFiZWxzPWMoIjEwMGsiLCAiMjAwayIsICIzMDBrIiwgIjQwMGsiLCAiNTAwayIsICI2MDBrIiwgIjcwMGsiKSsKICB0aGVtZV9taW5pbWFsKCkKYGBgCkxhIGdyw6FmaWNhIG5vcyBtdWVzdHJhIHF1ZSBsYSBDYXRlZ29yw61hIGRlIFByb2R1Y3RvIGNvbiBtYXMgdmVudGFzIGVzICdUZWNobm9sb2d5JywgZGVzcHXDqXMgJ0Z1cm5pdHVyZScgeSwgZmluYWxtZW50ZSAnT2ZmaWNlIFN1cHBsaWVzJy4gRW4gY3VhbnRvIGFsIHNlZ21lbnRvIGRlIGNsaWVudGUsIHNlIHZlIGVuIGNvbG9yIHZlcmRlIGNvbW8gZWwgc2VnbWVudG8gJ0NvcnBvcmF0ZTsgZXMgZWwgcXVlIG1hcyByZXByZXNlbnRhIGxhcyB2ZW50YXMsIGxvIGN1YWwgZXMgZW50ZW5kaWJsZSBwdWVzIHNvbiBsb3MgcXVlIG1hcyB0ZW5kcsOtYW4gZGluZXJvLCBwb3IgYXPDrSBkZWNpcmxvIHBhcmEgY29tcHJhciBwcm9kdWN0b3MgcGFyYSBzdXMgb2ZpY2luYXMuIAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiMwMDMzOTk7Ij5Nw6l0b2RvIGRlIGVudsOtbyBwb3IgZWwgc2VnbWVudG8gZGUgY2xpZW50ZTwvc3Bhbj4KYGBge3IsIGVjaG89RkFMU0V9CmdncGxvdChzdG9yZSwgYWVzKHggPSBDdXN0b21lcl9TZWdtZW50LCBmaWxsID0gU2hpcF9Nb2RlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKwogIGxhYnModGl0bGUgPSAiTcOpdG9kbyBkZSBFbnbDrW8gcG9yIFNlZ21lbnRvIGRlIENsaWVudGUiLAogICAgICAgeCA9ICJDdXN0b21lciBTZWdtZW50IiwgeSA9ICJOdW1iZXIgb2YgT3JkZXJzIiwgZmlsbCA9ICJNw6l0b2RvIGRlIEVudsOtbyIpICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYApTZSBvYnNlcnZhIHF1ZSBlbCBNw6l0b2RvIGRlIEVudsOtbyAnTnVtYmVyIG9mIEFpcicgZXMgZWwgbWFzIHV0aWxpemFkbyBlbiB0b2RvcyBsb3Mgc2VnbWVudG9zLCBkZXNwdcOpcyBsZSBzaWd1ZSBlbCAnRGVsaXZlcnkgVHJ1Y2snLiBBbCBpZ3VhbCBxdWUgbWkgc3Vwb3NpY2nDs24gZW4gbGEgZ3LDoWZpY2EgcGFzYWRhLCBlbCBzZWdtZW50byAnQ29ycG9yYXRlJyBlcyBlbCBxdWUgbWUgaGFzIHRpZW5lIG7Dum1lcm8gZGUgcGVkaWRvcywgZGViaWRvIGEgcXVlIHRpZW5lbiBtYXMgb3BvcnR1bmlkYWQgZWNvbsOzbWljYW1lbnRlLiAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjojMDAzMzk5OyI+VmVudGFzIHRvdGFsZXMgZGUgY2FkYSBjYXRlZ29yw61hIHBvciByZWdpw7NuPC9zcGFuPgpgYGB7ciwgZWNobz1GQUxTRX0KZ2dwbG90KHN0b3JlLCBhZXMoeCA9IFByb2R1Y3RfQ2F0ZWdvcnksIHkgPSBTYWxlcywgZmlsbCA9IFJlZ2lvbikpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBmYWNldF93cmFwKH4gUmVnaW9uKSArCiAgbGFicyh0aXRsZSA9ICJWZW50YXMgVG90YWxlcyBwb3IgQ2F0ZWdvcsOtYSBlbiBDYWRhIFJlZ2nDs24iLAogICAgICAgeCA9ICJDYXRlZ29yw61hIGRlIFByb2R1Y3RvIiwgeSA9ICJWZW50YXMgVG90YWxlcyIpICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYApMb3MgcHJvZHVjdG9zIGRlIGxhIGNhdGVnb3LDrWEgZGUgJ1RlY2hub2xvZ3knIHNvbiBsb3MgbcOhcyB2ZW5kaWRvcyBlbiAyIHJlZ2lvbmVzOiAnU291dGgnIHkgJ1dlc3QnLCBtaWVudHJhcyBxdWUgZW4gJ0NlbnRyYWwnIGUgJ0Vhc3QnICdPZmZpY2UgU3VwcGxpZXMnIGxsZXZhIG1hcyB2ZW50YWphLgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IzAwMzM5OTsiPkdncGxvdCBhdmFuemFkbzogZGlhZ3JhbWFzIGRlIGRpc3BlcnNpw7NuPC9zcGFuPgoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0V9CiNpbnN0YWxsLnBhY2thZ2VzKCJjYXIiKQpsaWJyYXJ5KGNhcikKdmlldyhTYWxhcmllcykKClNhbGFyaWVzICU+JSAKICBnZ3Bsb3QoYWVzKHg9eXJzLnNpbmNlLnBoZCx5PXNhbGFyeSkpK2dlb21fcG9pbnQoKQoKU2FsYXJpZXMgJT4lIAogIGdncGxvdChhZXMoeD15cnMuc2luY2UucGhkLHk9c2FsYXJ5LGNvbG9yPXJhbmspKStnZW9tX3BvaW50KCkrdGhlbWVfbWluaW1hbCgpCgojTm93LCBsZXQncyBjaGFuZ2UgdG8gZ2VvbV9qaXR0ZXIsIGNoYW5nZSB0aGUgc2hhcGUgaW4gZnVuY3Rpb24gb2YgdGhlIGRpc2NpcGxpbmUsIGFkZCBhIGxpbmVhciBtb2RlbCB3aGlsZSBmYWNldHRpbmcgYnkgc2V4LCBmaW5hbGx5LCB3ZSB3aWxsIGFkZCBheGlzIGxlZ2VuZCBsYWJlbHMuIAoKU2FsYXJpZXMgJT4lIAogIGdncGxvdChhZXMoeD15cnMuc2luY2UucGhkLHk9c2FsYXJ5LGNvbG9yPXJhbmspKStnZW9tX2ppdHRlcigpK3RoZW1lX21pbmltYWwoKQoKClNhbGFyaWVzICU+JSAKICBnZ3Bsb3QoYWVzKHg9eXJzLnNpbmNlLnBoZCx5PXNhbGFyeSkpK2dlb21faml0dGVyKGFlcyhjb2xvcj1yYW5rLHNoYXBlPWRpc2NpcGxpbmUpKSt0aGVtZV9taW5pbWFsKCkKClNhbGFyaWVzICU+JSAKICBnZ3Bsb3QoYWVzKHg9eXJzLnNpbmNlLnBoZCx5PXNhbGFyeSkpK2dlb21faml0dGVyKGFlcyhjb2xvcj1yYW5rLHNoYXBlPWRpc2NpcGxpbmUpKSt0aGVtZV9taW5pbWFsKCkrZmFjZXRfd3JhcCh+c2V4KStnZW9tX3Ntb290aChtZXRob2QgPSBsbSkKClNhbGFyaWVzICU+JSAKICBnZ3Bsb3QoYWVzKHg9eXJzLnNpbmNlLnBoZCx5PXNhbGFyeSkpK2dlb21faml0dGVyKGFlcyhjb2xvcj1yYW5rLHNoYXBlPWRpc2NpcGxpbmUpKSt0aGVtZV9taW5pbWFsKCkrZmFjZXRfd3JhcCh+c2V4KStnZW9tX3Ntb290aChtZXRob2QgPSBsbSkrbGFicyh0aXRsZT0iU2FsYXJ5IHZzIHllYXJzIHNpbmNlIFBoRCIseD0iWWVhcnMgc2luY2UgUGhEIix5PSJJbmNvbWUiLGNvbG9yPSJQb3NpdGlvbiIsc2hhcGU9IlJlc2VhcmNoIGFyZWEiKQoKCgoKYGBgCgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IzAwMzM5OTsiPkdncGxvdCBhdmFuemFkbzogYm94cGxvdCBjb24gZXRpcXVldGFzIHBlcnNvbmFsaXphZGFzPC9zcGFuPgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRX0KCiNHcsOhZmljbyBkZSBjYWphIHBhcmEgY29tcGFyYXIgbG9zIHNhbGFyaW9zIHBvciBnw6luZXJvLCBmaWx0cmFyZW1vcyBzYWxhcmlvcyBtZW5vcmVzIGEgMjAwLDAwMCBwYXJhIGRlc2NhcnRhciBhbGd1bm9zIHB1bnRvcyBhdMOtcGljb3MuIEVuIGVsIGVqZSB4IHNlIGRlc2VhIG9ic2VydmFyIGVsIHJhbmdvIGRlbCBwcm9mZXNvci4gCgpTYWxhcmllcyAlPiUgCiAgZmlsdGVyKHNhbGFyeTwyMDAwMDApICU+JSAKICBnZ3Bsb3QoYWVzKHg9cmFuayx5PXNhbGFyeSxmaWxsPXNleCkpK2dlb21fYm94cGxvdChhbHBoYT0wLjUpK3RoZW1lX21pbmltYWwoKQoKU2FsYXJpZXMgJT4lIAogIGZpbHRlcihzYWxhcnk8MjAwMDAwKSAlPiUgCiAgZ2dwbG90KGFlcyh4PXJhbmsseT1zYWxhcnksZmlsbD1zZXgpKStnZW9tX2JveHBsb3QoYWxwaGE9MC41KSt0aGVtZV9taW5pbWFsKCkrCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3M9YygiQXNzdFByb2YiLCJBc3NvY1Byb2YiLCJQcm9mIiksCiAgICAgIGxhYmVscz1jKCJBc3Npc3RhbnRcblByb2Zlc3NvciIsIkFzc29jaWF0ZVxuUHJvZmVzc29yIiwiRnVsbFxuUHJvZmVzc29yIikpKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3M9Yyg1MDAwMCwxMDAwMDAsMTUwMDAwLDIwMDAwMCksCiAgICAgIGxhYmVscz1jKCI1MGsiLCIxMDBrIiwiMTUwayIsIjIwMGsiKSkrCiAgbGFicyh0aXRsZT0iRmFjdWx0eSBTYWxhcnkgYnkgUmFuayBhbmQgR2VuZGVyIix4PSIiLHk9IiIsZmlsbD0iR2VuZGVyIikKCiNMZXQncyBtb3ZlIHRoZSBsZWdlbmQgaW5zaWRlIHRoZSBncmFwaAoKU2FsYXJpZXMgJT4lIAogIGZpbHRlcihzYWxhcnk8MjAwMDAwKSAlPiUgCiAgZ2dwbG90KGFlcyh4PXJhbmsseT1zYWxhcnksZmlsbD1zZXgpKStnZW9tX2JveHBsb3QoYWxwaGE9MC41KSt0aGVtZV9taW5pbWFsKCkKClNhbGFyaWVzICU+JSAKICBmaWx0ZXIoc2FsYXJ5PDIwMDAwMCkgJT4lIAogIGdncGxvdChhZXMoeD1yYW5rLHk9c2FsYXJ5LGZpbGw9c2V4KSkrZ2VvbV9ib3hwbG90KGFscGhhPTAuNSkrdGhlbWVfbWluaW1hbCgpKwogIHNjYWxlX3hfZGlzY3JldGUoYnJlYWtzPWMoIkFzc3RQcm9mIiwiQXNzb2NQcm9mIiwiUHJvZiIpLAogICAgICBsYWJlbHM9YygiQXNzaXN0YW50XG5Qcm9mZXNzb3IiLCJBc3NvY2lhdGVcblByb2Zlc3NvciIsIkZ1bGxcblByb2Zlc3NvciIpKSsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPWMoNTAwMDAsMTAwMDAwLDE1MDAwMCwyMDAwMDApLAogICAgICBsYWJlbHM9YygiNTBrIiwiMTAwayIsIjE1MGsiLCIyMDBrIikpKwogIGxhYnModGl0bGU9IkZhY3VsdHkgU2FsYXJ5IGJ5IFJhbmsgYW5kIEdlbmRlciIseD0iIix5PSIiLGZpbGw9IkdlbmRlciIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4xMSwwLjg1KSkKCgoKYGBgCgoK