Primero la Sección de Librerías de Funciones:

```{r INSTALACION LIBRERIAS }
Error: attempt to use zero-length variable name

Llamada a LIBRERIAS:

# Adicionales Octubre 2021:
library(sqldf) # Para SQL en R
Loading required package: gsubfn
Loading required package: proto
Loading required package: RSQLite

A partir de aquí la Sección de Importación de Datasets:

```{r DATA }
Error: attempt to use zero-length variable name

REVISION RAPIDA DEL DATAFRAME:

#View(database)
summary(database) # Summary Estadístico.
     name                year        length_min        genre           average_rating  cost_millions        foreign    age_restriction
 Length:30          Min.   :1936   Min.   : 81.00   Length:30          Min.   :5.200   Min.   :  0.400   Min.   :0.0   Min.   : 0.00  
 Class :character   1st Qu.:1988   1st Qu.: 99.25   Class :character   1st Qu.:7.925   1st Qu.:  3.525   1st Qu.:0.0   1st Qu.:12.00  
 Mode  :character   Median :1998   Median :110.50   Mode  :character   Median :8.300   Median : 13.000   Median :0.0   Median :14.00  
                    Mean   :1996   Mean   :116.80                      Mean   :8.103   Mean   : 22.300   Mean   :0.4   Mean   :12.93  
                    3rd Qu.:2008   3rd Qu.:124.25                      3rd Qu.:8.500   3rd Qu.: 25.000   3rd Qu.:1.0   3rd Qu.:16.00  
                    Max.   :2015   Max.   :179.00                      Max.   :9.300   Max.   :165.000   Max.   :1.0   Max.   :18.00  
head(database) # Primeros 6.
names(database) # Names de columnas.
[1] "name"            "year"            "length_min"      "genre"           "average_rating"  "cost_millions"   "foreign"         "age_restriction"
print(is.data.frame(database))
[1] TRUE
#attach(database) #only if there is only 1 dataset 
# CONTENIDO DE TABLA:
# database es la tabla con datos de películas.

ANALIZAMOS LA ESTRCUTURA DE LA TABLA:

Función str: structure Lab08-importingData

# Prints out the structure of your table.
str(database) # es la función structure
tibble [30 x 8] (S3: tbl_df/tbl/data.frame)
 $ name           : chr [1:30] "Toy Story" "Akira" "The Breakfast Club" "The Artist" ...
 $ year           : num [1:30] 1995 1998 1985 2011 1936 ...
 $ length_min     : num [1:30] 81 125 97 100 87 139 130 119 121 122 ...
 $ genre          : chr [1:30] "Animation" "Animation" "Drama" "Romance" ...
 $ average_rating : num [1:30] 8.3 8.1 7.9 8 8.6 8.9 8.7 7.9 8.7 8.4 ...
 $ cost_millions  : num [1:30] 30 10.4 1 15 1.5 63 3.3 25 11 15 ...
 $ foreign        : num [1:30] 0 1 0 1 0 0 1 0 0 0 ...
 $ age_restriction: num [1:30] 0 14 14 12 10 18 18 14 10 14 ...

A partir de aquí inicia el Cuerpo del Script:

EJERCICIO FUNCIONES PROPIAS EN R

# UDF - User Defined Functions

sum( 111 , 222 )
[1] 333
prod( 111 , 222 )
[1] 24642
log( 8 , 2 )
[1] 3
# library(ggplot2)
# ggplot()


#Incremento Porcentual
( 
Importe <- 256
)
[1] 256
(
Impuesto <- 3.2/100
)
[1] 0.032
(
Precio.de.Venta <- Importe * ( 1+Impuesto )
)
[1] 264.192
(
Variación <- Precio.de.Venta/Importe - 1
)
[1] 0.032
# Function Increase_percentaje
Increase_percentaje <- function( Importe , Prc_Impuesto ){
  Precio.de.Venta <- Importe * ( 1+Prc_Impuesto/100 )
  Precio.de.Venta <- round( Precio.de.Venta , 2 )
  
  print( paste( "Increasing ", Importe ,
                " en ", Prc_Impuesto , 
                "% resulta en: ", Precio.de.Venta , " USD.",
                sep = "" ))
  return(Precio.de.Venta)
}

#Llamar a la function
Precio.de.Venta.1 <- Increase_percentaje( 256 , 3.2 ) 
[1] "Increasing 256 en 3.2% resulta en: 264.19 USD."
Precio.de.Venta.1
[1] 264.19

OTRA FUNCION:

# Function Increase_percentaje2
Increase_percentaje2 <- function( Importe , Prc_Impuesto ){
  Precio.de.Venta <- Importe * ( 1+Prc_Impuesto/100 )
  Precio.de.Venta <- round( Precio.de.Venta , 2 )
  
  if( Importe <= 0 ){
    print("Error. Importe <= 0.")
    return(NULL)
  }else if( Prc_Impuesto <= 0 ){
    print("Error. Prc_Impuesto <= 0.")
    return(NULL)
  }else{
  
  print( paste( "Increasing ", Importe ,
                " en ", Prc_Impuesto , 
                "% resulta en: ", Precio.de.Venta , " USD.",
                sep = "" ))
  return(Precio.de.Venta)
  }
}
#Llamar a la function
Precio.de.Venta.1 <- Increase_percentaje2( 256 , 3.2 ) 
[1] "Increasing 256 en 3.2% resulta en: 264.19 USD."
str(Precio.de.Venta.1)
 num 264
#Precio.de.Venta.1
Precio.de.Venta.2 <- Increase_percentaje2( -256 , 3.2 ) 
[1] "Error. Importe <= 0."
str(Precio.de.Venta.2)
 NULL
#Precio.de.Venta.2
Precio.de.Venta.3 <- Increase_percentaje2( 256 , -3.2 ) 
[1] "Error. Prc_Impuesto <= 0."
str(Precio.de.Venta.3)
 NULL
#Precio.de.Venta.2

EJEMPLO BUCLE FOR:

for( i in 1:5){
  print( i^2 )
}
[1] 1
[1] 4
[1] 9
[1] 16
[1] 25
Vector.1a5 <- c(1:5)
#Vector.1a5
Vector.1a5^2
[1]  1  4  9 16 25
for( i in Vector.1a5 ){
  print( i^2 )
}
[1] 1
[1] 4
[1] 9
[1] 16
[1] 25
Dataframe.1a5 <- as.data.frame( c(1:5) )
#Dataframe.1a5
names(Dataframe.1a5)
[1] "c(1:5)"
Dataframe.1a5$c
[1] 1 2 3 4 5
for( i in Dataframe.1a5$c ){
  print( i^2 )
}  
[1] 1
[1] 4
[1] 9
[1] 16
[1] 25
sqldf("SELECT cyl , count( cyl ) as Cilindros FROM mtcars GROUP BY cyl ")
df_pivot_sql <- sqldf( " SELECT cyl , 
                                COUNT( cyl ) as Cilindros 
                         FROM mtcars 
                         GROUP BY cyl ")
df_pivot_sql

EJERCICIOS ADICIONALES CON mtcars:

#mtcars
tabla.1 <- table( mtcars$cyl )
#tabla.1

colores <- c( "orange" , 
              "green" , 
              "yellow" )
#colores

plot.1 <- barplot( tabla.1 , 
                   xlab = "Cilindros" , 
                   ylab = "Frequencia" , 
                   main = "Nro de Cilindros" ,
                   col = colores )

plot.1
     [,1]
[1,]  0.7
[2,]  1.9
[3,]  3.1

CONTINUACION CON mtcars :


plot.2 <- ggplot( mtcars ,
                  aes( cyl )) +
          geom_bar( fill = colores ) + 
          labs( x= "Cilindros" , 
                y = "Frecuencias" , 
                title = "Numero de Cilindros")
plot.2  

NA

REPASO DE MATRICES:

matrix.1 <- matrix( 1:10 , 
            nrow = 5 , 
            ncol = 4 )
matrix.1
     [,1] [,2] [,3] [,4]
[1,]    1    6    1    6
[2,]    2    7    2    7
[3,]    3    8    3    8
[4,]    4    9    4    9
[5,]    5   10    5   10
dim(matrix.1)
[1] 5 4
matrix.1[2,4]
[1] 7
matrix.1[2, ]
[1] 2 7 2 7
matrix.1[ ,4]
[1]  6  7  8  9 10
df_matrix.1 <- as.data.frame( matrix.1 , row.names = NULL, 
                              optional = FALSE , 
                              make.names = TRUE , 
               stringsAsFactors = default.stringsAsFactors() )
#df_matrix.1
#df_matrix.1$V4
df_matrix.1['V4']
NA

EJERCICIOS:

summary(database)
     name                year        length_min        genre           average_rating  cost_millions        foreign    age_restriction
 Length:30          Min.   :1936   Min.   : 81.00   Length:30          Min.   :5.200   Min.   :  0.400   Min.   :0.0   Min.   : 0.00  
 Class :character   1st Qu.:1988   1st Qu.: 99.25   Class :character   1st Qu.:7.925   1st Qu.:  3.525   1st Qu.:0.0   1st Qu.:12.00  
 Mode  :character   Median :1998   Median :110.50   Mode  :character   Median :8.300   Median : 13.000   Median :0.0   Median :14.00  
                    Mean   :1996   Mean   :116.80                      Mean   :8.103   Mean   : 22.300   Mean   :0.4   Mean   :12.93  
                    3rd Qu.:2008   3rd Qu.:124.25                      3rd Qu.:8.500   3rd Qu.: 25.000   3rd Qu.:1.0   3rd Qu.:16.00  
                    Max.   :2015   Max.   :179.00                      Max.   :9.300   Max.   :165.000   Max.   :1.0   Max.   :18.00  
matrix_summary <- do.call(cbind, lapply(database, summary))
matrix_summary
        name        year      length_min genre       average_rating     cost_millions foreign age_restriction   
Min.    "30"        "1936"    "81"       "30"        "5.2"              "0.4"         "0"     "0"               
1st Qu. "character" "1987.75" "99.25"    "character" "7.925"            "3.525"       "0"     "12"              
Median  "character" "1998.5"  "110.5"    "character" "8.3"              "13"          "0"     "14"              
Mean    "30"        "1995.5"  "116.8"    "30"        "8.10333333333333" "22.3"        "0.4"   "12.9333333333333"
3rd Qu. "character" "2007.5"  "124.25"   "character" "8.5"              "25"          "1"     "16"              
Max.    "character" "2015"    "179"      "character" "9.3"              "165"         "1"     "18"              
str(matrix_summary)
 chr [1:6, 1:8] "30" "character" "character" "30" "character" "character" "1936" "1987.75" "1998.5" "1995.5" "2007.5" "2015" "81" "99.25" ...
 - attr(*, "dimnames")=List of 2
  ..$ : chr [1:6] "Min." "1st Qu." "Median" "Mean" ...
  ..$ : chr [1:8] "name" "year" "length_min" "genre" ...
df_summary <- as.data.frame(matrix_summary, row.names = NULL, optional = FALSE,
              make.names = TRUE, 
              stringsAsFactors = default.stringsAsFactors())
df_summary

summary( database$cost_millions )
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.400   3.525  13.000  22.300  25.000 165.000 
# Retrieve a subset_dataframe of the data frame consisting of the "genre" columns
database['genre']

# Retrieve the data for the "name" column in the data frame in a vector
database$genre
 [1] "Animation" "Animation" "Drama"     "Romance"   "Comedy"    "Drama"     "Crime"     "Drama"     "Action"    "Drama"     "Drama"     "Comedy"   
[13] "Horror"    "Comedy"    "Comedy"    "Horror"    "Crime"     "Crime"     "Adventure" "Biography" "Biography" "Romance"   "Thriller"  "Sci-fi"   
[25] "Thriller"  "Drama"     "Crime"     "Fantasy"   "Drama"     "Comedy"   
# Retrieve the first row of the data frame.
database[3,]

# Retrieve the third row of the data frame, but only the "name" and "length_min" columns.
database[3, c("name","length_min")]

summary(database)
     name                year        length_min        genre           average_rating  cost_millions        foreign    age_restriction
 Length:30          Min.   :1936   Min.   : 81.00   Length:30          Min.   :5.200   Min.   :  0.400   Min.   :0.0   Min.   : 0.00  
 Class :character   1st Qu.:1988   1st Qu.: 99.25   Class :character   1st Qu.:7.925   1st Qu.:  3.525   1st Qu.:0.0   1st Qu.:12.00  
 Mode  :character   Median :1998   Median :110.50   Mode  :character   Median :8.300   Median : 13.000   Median :0.0   Median :14.00  
                    Mean   :1996   Mean   :116.80                      Mean   :8.103   Mean   : 22.300   Mean   :0.4   Mean   :12.93  
                    3rd Qu.:2008   3rd Qu.:124.25                      3rd Qu.:8.500   3rd Qu.: 25.000   3rd Qu.:1.0   3rd Qu.:16.00  
                    Max.   :2015   Max.   :179.00                      Max.   :9.300   Max.   :165.000   Max.   :1.0   Max.   :18.00  
histograma <- hist(database$length_min ,col="yellow",breaks = 10)

histograma
$breaks
 [1]  80  90 100 110 120 130 140 150 160 170 180

$counts
 [1] 2 8 5 5 4 1 2 0 1 2

$density
 [1] 0.006666667 0.026666667 0.016666667 0.016666667 0.013333333 0.003333333 0.006666667 0.000000000 0.003333333 0.006666667

$mids
 [1]  85  95 105 115 125 135 145 155 165 175

$xname
[1] "database$length_min"

$equidist
[1] TRUE

attr(,"class")
[1] "histogram"

time = gsub(":", "-", Sys.time())

#- exporta en formato .csv el df df_summary al fichero "df_summary.csv". Se guardará en la subcarpeta "datos/pruebas/" del proyecto
folder_path <- "./output_databases/"
filename <- "df_summary"
filetype <-".csv"
path <- paste(folder_path,filename," ",time,filetype, sep="")
write_csv(df_summary, path)

Hay varios packages que graban datos en formato .xls. Pero el más sencillo es el package xlsx. Veámoslo:

# install.packages("xlsx")
# library(xlsx)
write.xlsx(df_summary, "./output_databases/df_summary.xlsx")

La función write.xlsx() permite añadir datos a un archivo .xlsx preexistente; para ello tenemos que usar la opción append = TRUE:

# library(xlsx)
write.xlsx(df_summary, "./output_databases/df_summary.xlsx", sheetName = "summary", append = TRUE)

DEL EJERCICIO DE EJECUTAR SQL QUERY en UN R NOTEBOOK:

write.xlsx( df_pivot_sql , 
            "./output_databases/df_pivot_sql.xlsx", 
            sheetName = "df_pivot_sql" )

GRAFICA

#**********************************************************************
#*# Publication quality graphs require 600dpi
dpi=600    #pixels per square inch
carpeta = "./output_images/"
archivo = "histograma"
time = gsub(":", "-", Sys.time())
carpeta_y_archivo = paste(carpeta,archivo," ",time,".tif", sep="")
nombre_de_tif = carpeta_y_archivo
tiff(nombre_de_tif, width=6*dpi, height=5*dpi, res=dpi)
#**********************************************************************
histograma <- hist(database$length_min ,col="yellow",breaks = 10)
histograma
$breaks
 [1]  80  90 100 110 120 130 140 150 160 170 180

$counts
 [1] 2 8 5 5 4 1 2 0 1 2

$density
 [1] 0.006666667 0.026666667 0.016666667 0.016666667 0.013333333 0.003333333 0.006666667 0.000000000 0.003333333 0.006666667

$mids
 [1]  85  95 105 115 125 135 145 155 165 175

$xname
[1] "database$length_min"

$equidist
[1] TRUE

attr(,"class")
[1] "histogram"
#**********************************************************************
dev.off()
null device 
          1 
print(paste("Finalizado procesamiento de",archivo," ",time, sep=""))
[1] "Finalizado procesamiento dehistograma 2021-10-03 16-59-51"
#**********************************************************************
citation()

To cite R in publications use:

  R Core Team (2021). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna,
  Austria. URL https://www.R-project.org/.

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {R: A Language and Environment for Statistical Computing},
    author = {{R Core Team}},
    organization = {R Foundation for Statistical Computing},
    address = {Vienna, Austria},
    year = {2021},
    url = {https://www.R-project.org/},
  }

We have invested a lot of time and effort in creating R, please cite it when using it for data analysis. See also
‘citation("pkgname")’ for citing R packages.
citation("readxl") 

To cite package ‘readxl’ in publications use:

  Hadley Wickham and Jennifer Bryan (2019). readxl: Read Excel Files. R package version 1.3.1.
  https://CRAN.R-project.org/package=readxl

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {readxl: Read Excel Files},
    author = {Hadley Wickham and Jennifer Bryan},
    year = {2019},
    note = {R package version 1.3.1},
    url = {https://CRAN.R-project.org/package=readxl},
  }
# 
help("readxl") # Documentacion de la library readxl
LS0tDQp0aXRsZTogIkdHcGxvdDIsIFF1ZXJ5IFNRTCBlbiAgUiBOb3RlYm9vayAocGl2b3QgdGFibGUpLCBidWNsZSBmb3IgJiBmdW5jaW9uZXMsIEBFQ1IncyBNYXN0ZXIgUiBOb3RlYm9vayBUZW1wbGF0ZSAyMDIxLUlJIg0KYXV0aG9yOiAiSW5nLiBFcm5lc3RvIENhbmNoby1Sb2RyaWd1ZXosIE1CQSBHZW9yZ2UgV2FzaGluZ3RvbiBVbml2ZXJzaXR5Ig0KZW1haWw6ICJlcm5lc3RvLmNhbmNob0B1bm1zbS5lZHUucGUiDQpkYXRlOiAiMjAyMS4xMC4wMyINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgd29yZF9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQoNClByaW1lcm8gbGEgU2VjY2nDs24gZGUgTGlicmVyw61hcyBkZSBGdW5jaW9uZXM6IA0KDQpgYGB7ciBJTlNUQUxBQ0lPTiBMSUJSRVJJQVMgfQ0KIyByb3duYW1lcyhpbnN0YWxsZWQucGFja2FnZXMoKSkNCmxpc3Qub2YucGFja2FnZXMgPC0gYygNCiJhcm0iICwgDQoiYnJvb20iICwgDQoiY29ycnBsb3QiICwgDQoiY293cGxvdCIgLCANCiJkYXRhc2V0cyIgLCANCiJkYXRhc2V0cyIgLCANCiJkcGx5ciIgLCANCiJlZXB0b29scyIgLCANCiJlc3RpbWF0ciIgLCANCiJGaW5DYWwiICwgDQoiZm9ybWF0UiIgLCANCiJnZ2ZvcnRpZnkiICwgDQoiZ2dwdWJyIiAsIA0KImhhdmVuIiAsIA0KIkhtaXNjIiAsIA0KImluZmVyIiAsIA0KImtuaXRyIiAsIA0KImxtdGVzdCIgLCANCiJtYXJnaW5zIiAsIA0KIm55Y2ZsaWdodHMxMyIgLCANCiJwc3ljaCIgLCANCiJyZWFkeGwiICwgDQoicmVzaGFwZTIiICwgDQoicm1zIiAsIA0KInNraW1yIiAsIA0KInN0YXJnYXplciIgLCANCiJzdHJpbmdyIiAsIA0KInN1cnZpdmFsIiAsIA0KInRhYmxlb25lIiAsIA0KInRpZHlyIiAsIA0KInRpZHl2ZXJzZSIgLCANCiJUVFIiICwgDQoid29vbGRyaWRnZSIgLCANCiJ4bHN4IiwNCiMgQWRpY2lvbmFsZXMgT2N0dWJyZSAyMDIxOg0KInNxbGRmIiwgIyBQYXJhIFNRTCBlbiBSDQoiUk9EQkMiICAjIFBhcmEgQ29uZXhpb24gU1FMIHkgUiBTdHVkaW8NCikNCmhhcyAgIDwtIGxpc3Qub2YucGFja2FnZXMgJWluJSByb3duYW1lcyhpbnN0YWxsZWQucGFja2FnZXMoKSkNCmlmKGFueSghaGFzKSkgaW5zdGFsbC5wYWNrYWdlcyhsaXN0Lm9mLnBhY2thZ2VzWyFoYXNdKQ0KDQpgYGANCg0KDQpMbGFtYWRhIGEgTElCUkVSSUFTOg0KYGBge3IgTExBTUFEQSBBIExJQlJFUklBU30NCiMgbGlicmFyeShhcm0pIA0KIyBsaWJyYXJ5KGJyb29tKSANCiMgbGlicmFyeShjb3JycGxvdCkgDQojIGxpYnJhcnkoY293cGxvdCkgDQojIGxpYnJhcnkoZGF0YXNldHMpIA0KbGlicmFyeShkcGx5cikgDQojIGxpYnJhcnkoZWVwdG9vbHMpIA0KIyBsaWJyYXJ5KGVzdGltYXRyKSANCmxpYnJhcnkoRmluQ2FsKSANCiMgbGlicmFyeShmb3JtYXRSKSANCiMgbGlicmFyeShnZ2ZvcnRpZnkpIA0KIyBsaWJyYXJ5KGdncHVicikgDQogbGlicmFyeShnZ3Bsb3QyKSANCiMgbGlicmFyeShoYXZlbikgI3BhcmEgbGEgbGVjdHVyYSBkZSBhcmNoaXZvcyBEVEEgZGUgU3RhdGENCiMgbGlicmFyeShIbWlzYykgDQojIGxpYnJhcnkoaW5mZXIpIA0KIyBsaWJyYXJ5KGtuaXRyKSANCiMgbGlicmFyeShsbXRlc3QpIA0KIyBsaWJyYXJ5KG1hcmdpbnMpIA0KIyBsaWJyYXJ5KG55Y2ZsaWdodHMxMykgDQojIGxpYnJhcnkocHN5Y2gpIA0KbGlicmFyeShyZWFkeGwpIA0KbGlicmFyeShyZXNoYXBlMikgI3BhcmEgaGFjZXIgUmVTaGFwZSAoUGl2b3QgVGFibGVzKQ0KIyBsaWJyYXJ5KHJtcykgDQojIGxpYnJhcnkoc2tpbXIpIA0KIyBsaWJyYXJ5KHN0YXJnYXplcikgDQojIGxpYnJhcnkoc3RyaW5ncikgDQojIGxpYnJhcnkoc3Vydml2YWwpIA0KIyBsaWJyYXJ5KHRhYmxlb25lKSANCmxpYnJhcnkodGlkeXIpICNwYXJhIGhhY2VyIFJlU2hhcGUgKFBpdm90IFRhYmxlcykNCmxpYnJhcnkodGlkeXZlcnNlKSANCmxpYnJhcnkoVFRSKSAjcGFyYSBsYXMgZ3JhZmljYXMgZGUgc2VyaWVzIGRlIHRpZW1wbw0KIyBsaWJyYXJ5KHdvb2xkcmlkZ2UpIA0KbGlicmFyeSh4bHN4KSAjcGFyYSBleHBvcnRhciBhIEV4Y2VsIGZpbGUNCg0KIyBBZGljaW9uYWxlcyBPY3R1YnJlIDIwMjE6DQpsaWJyYXJ5KHNxbGRmKSAjIFBhcmEgU1FMIGVuIFINCmxpYnJhcnkoUk9EQkMpICMgUGFyYSBDb25leGlvbiBTUUwgeSBSIFN0dWRpbw0KYGBgDQoNCg0KQSBwYXJ0aXIgZGUgYXF1w60gbGEgU2VjY2nDs24gZGUgSW1wb3J0YWNpw7NuIGRlIERhdGFzZXRzOg0KYGBge3IgREFUQSB9DQpwcmludCgiV29ya2luZyBEaXJlY3Rvcnk6ICIpOyBnZXR3ZCgpICNnZXQgdG8gc2hvdyBtZSB0aGUgY3VycmVudCBXb3JraW5nIERpcmVjdG9yeSANCiMjIyBDYXJnYW5kbyBCQkREOiBuNWF5NXFhZGZlN2Uxbm5zdjVzMDFvZTF4NjJtcTUxai5jc3YgIyMjIw0KIyBWZXJzaW9uIGRlIEJCREQ6IDIwMjEuMDkuMjQgdjENCiMgUlVUQTogaHR0cHM6Ly9pYm0uYm94LmNvbS9zaGFyZWQvc3RhdGljLw0KDQojIFhMUyBmaWxlLCAgRG93bmxvYWQgZGF0YXNldHMNCiMgZG93bmxvYWQuZmlsZSggImh0dHBzOi8vaWJtLmJveC5jb20vc2hhcmVkL3N0YXRpYy9ueDBvaGQ5c3EwaXozcDg3MXpnOGVoYzFtMzlpYnB4Ni54bHMiICwgDQojICAgICAgICAgICAgICAgIGRlc3RmaWxlPSJtb3ZpZXMtZGIueGxzIiApDQoNCiMgQ1NWIGZpbGUsICBEb3dubG9hZCBkYXRhc2V0cw0KZG93bmxvYWQuZmlsZSgiaHR0cHM6Ly9pYm0uYm94LmNvbS9zaGFyZWQvc3RhdGljL241YXk1cWFkZmU3ZTFubnN2NXMwMW9lMXg2Mm1xNTFqLmNzdiIsIA0KICAgICAgICAgICAgICBkZXN0ZmlsZT0ibW92aWVzLWRiLmNzdiIpDQpkYXRhYmFzZV9jc3YgPC0gcmVhZC5jc3YoIm1vdmllcy1kYi5jc3YiLCBoZWFkZXI9VFJVRSwgc2VwPSIsIikNCg0KZmlsZS5leGlzdHMoIm1vdmllcy1kYi54bHN4IikNCiMgUmVhZCBkYXRhIGZyb20gdGhlIFhMUyBmaWxlIGFuZCBhdHRyaWJ1dGUgdGhlIHRhYmxlIHRvIHRoZSBteV9leGNlbF9kYXRhIHZhcmlhYmxlLg0KZGF0YWJhc2VfeGxzeCA8LSByZWFkX2V4Y2VsKCJtb3ZpZXMtZGIueGxzeCIpDQpkYXRhYmFzZV94bHN4DQoNCiNtb3ZpZXNfZGF0YQ0KKA0KZGF0YWJhc2UgPC0gZGF0YWJhc2VfeGxzeA0KKQ0KDQoNCmBgYA0KUkVWSVNJT04gUkFQSURBIERFTCBEQVRBRlJBTUU6DQpgYGB7cn0NCiNWaWV3KGRhdGFiYXNlKQ0Kc3VtbWFyeShkYXRhYmFzZSkgIyBTdW1tYXJ5IEVzdGFkw61zdGljby4NCmhlYWQoZGF0YWJhc2UpICMgUHJpbWVyb3MgNi4NCm5hbWVzKGRhdGFiYXNlKSAjIE5hbWVzIGRlIGNvbHVtbmFzLg0KcHJpbnQoaXMuZGF0YS5mcmFtZShkYXRhYmFzZSkpDQojYXR0YWNoKGRhdGFiYXNlKSAjb25seSBpZiB0aGVyZSBpcyBvbmx5IDEgZGF0YXNldCANCiMgQ09OVEVOSURPIERFIFRBQkxBOg0KIyBkYXRhYmFzZSBlcyBsYSB0YWJsYSBjb24gZGF0b3MgZGUgcGVsw61jdWxhcy4NCmBgYA0KDQpBTkFMSVpBTU9TIExBIEVTVFJDVVRVUkEgREUgTEEgVEFCTEE6DQoNCkZ1bmNpw7NuIHN0cjogc3RydWN0dXJlDQpMYWIwOC1pbXBvcnRpbmdEYXRhIA0KYGBge3IgQ1VFUlBPfQ0KDQojIFByaW50cyBvdXQgdGhlIHN0cnVjdHVyZSBvZiB5b3VyIHRhYmxlLg0Kc3RyKGRhdGFiYXNlKSAjIGVzIGxhIGZ1bmNpw7NuIHN0cnVjdHVyZQ0KDQoNCmBgYA0KDQoNCkEgcGFydGlyIGRlIGFxdcOtIGluaWNpYSBlbCBDdWVycG8gZGVsIFNjcmlwdDoNCg0KRUpFUkNJQ0lPIEZVTkNJT05FUyBQUk9QSUFTIEVOIFINCmBgYHtyfQ0KIyBVREYgLSBVc2VyIERlZmluZWQgRnVuY3Rpb25zDQoNCnN1bSggMTExICwgMjIyICkNCnByb2QoIDExMSAsIDIyMiApDQpsb2coIDggLCAyICkNCg0KIyBsaWJyYXJ5KGdncGxvdDIpDQojIGdncGxvdCgpDQoNCg0KI0luY3JlbWVudG8gUG9yY2VudHVhbA0KKCANCkltcG9ydGUgPC0gMjU2DQopDQooDQpJbXB1ZXN0byA8LSAzLjIvMTAwDQopDQooDQpQcmVjaW8uZGUuVmVudGEgPC0gSW1wb3J0ZSAqICggMStJbXB1ZXN0byApDQopDQooDQpWYXJpYWNpw7NuIDwtIFByZWNpby5kZS5WZW50YS9JbXBvcnRlIC0gMQ0KKQ0KDQojIEZ1bmN0aW9uIEluY3JlYXNlX3BlcmNlbnRhamUNCkluY3JlYXNlX3BlcmNlbnRhamUgPC0gZnVuY3Rpb24oIEltcG9ydGUgLCBQcmNfSW1wdWVzdG8gKXsNCiAgUHJlY2lvLmRlLlZlbnRhIDwtIEltcG9ydGUgKiAoIDErUHJjX0ltcHVlc3RvLzEwMCApDQogIFByZWNpby5kZS5WZW50YSA8LSByb3VuZCggUHJlY2lvLmRlLlZlbnRhICwgMiApDQogIA0KICBwcmludCggcGFzdGUoICJJbmNyZWFzaW5nICIsIEltcG9ydGUgLA0KICAgICAgICAgICAgICAgICIgZW4gIiwgUHJjX0ltcHVlc3RvICwgDQogICAgICAgICAgICAgICAgIiUgcmVzdWx0YSBlbjogIiwgUHJlY2lvLmRlLlZlbnRhICwgIiBVU0QuIiwNCiAgICAgICAgICAgICAgICBzZXAgPSAiIiApKQ0KICByZXR1cm4oUHJlY2lvLmRlLlZlbnRhKQ0KfQ0KDQojTGxhbWFyIGEgbGEgZnVuY3Rpb24NClByZWNpby5kZS5WZW50YS4xIDwtIEluY3JlYXNlX3BlcmNlbnRhamUoIDI1NiAsIDMuMiApIA0KUHJlY2lvLmRlLlZlbnRhLjENCg0KYGBgDQoNCk9UUkEgRlVOQ0lPTjoNCmBgYHtyfQ0KIyBGdW5jdGlvbiBJbmNyZWFzZV9wZXJjZW50YWplMg0KSW5jcmVhc2VfcGVyY2VudGFqZTIgPC0gZnVuY3Rpb24oIEltcG9ydGUgLCBQcmNfSW1wdWVzdG8gKXsNCiAgUHJlY2lvLmRlLlZlbnRhIDwtIEltcG9ydGUgKiAoIDErUHJjX0ltcHVlc3RvLzEwMCApDQogIFByZWNpby5kZS5WZW50YSA8LSByb3VuZCggUHJlY2lvLmRlLlZlbnRhICwgMiApDQogIA0KICBpZiggSW1wb3J0ZSA8PSAwICl7DQogICAgcHJpbnQoIkVycm9yLiBJbXBvcnRlIDw9IDAuIikNCiAgICByZXR1cm4oTlVMTCkNCiAgfWVsc2UgaWYoIFByY19JbXB1ZXN0byA8PSAwICl7DQogICAgcHJpbnQoIkVycm9yLiBQcmNfSW1wdWVzdG8gPD0gMC4iKQ0KICAgIHJldHVybihOVUxMKQ0KICB9ZWxzZXsNCiAgDQogIHByaW50KCBwYXN0ZSggIkluY3JlYXNpbmcgIiwgSW1wb3J0ZSAsDQogICAgICAgICAgICAgICAgIiBlbiAiLCBQcmNfSW1wdWVzdG8gLCANCiAgICAgICAgICAgICAgICAiJSByZXN1bHRhIGVuOiAiLCBQcmVjaW8uZGUuVmVudGEgLCAiIFVTRC4iLA0KICAgICAgICAgICAgICAgIHNlcCA9ICIiICkpDQogIHJldHVybihQcmVjaW8uZGUuVmVudGEpDQogIH0NCn0NCiNMbGFtYXIgYSBsYSBmdW5jdGlvbg0KUHJlY2lvLmRlLlZlbnRhLjEgPC0gSW5jcmVhc2VfcGVyY2VudGFqZTIoIDI1NiAsIDMuMiApIA0Kc3RyKFByZWNpby5kZS5WZW50YS4xKQ0KI1ByZWNpby5kZS5WZW50YS4xDQpQcmVjaW8uZGUuVmVudGEuMiA8LSBJbmNyZWFzZV9wZXJjZW50YWplMiggLTI1NiAsIDMuMiApIA0Kc3RyKFByZWNpby5kZS5WZW50YS4yKQ0KI1ByZWNpby5kZS5WZW50YS4yDQpQcmVjaW8uZGUuVmVudGEuMyA8LSBJbmNyZWFzZV9wZXJjZW50YWplMiggMjU2ICwgLTMuMiApIA0Kc3RyKFByZWNpby5kZS5WZW50YS4zKQ0KI1ByZWNpby5kZS5WZW50YS4yDQpgYGANCg0KRUpFTVBMTyBCVUNMRSBGT1I6DQpgYGB7cn0NCmZvciggaSBpbiAxOjUpew0KICBwcmludCggaV4yICkNCn0NCg0KVmVjdG9yLjFhNSA8LSBjKDE6NSkNCiNWZWN0b3IuMWE1DQpWZWN0b3IuMWE1XjINCg0KZm9yKCBpIGluIFZlY3Rvci4xYTUgKXsNCiAgcHJpbnQoIGleMiApDQp9DQoNCkRhdGFmcmFtZS4xYTUgPC0gYXMuZGF0YS5mcmFtZSggYygxOjUpICkNCiNEYXRhZnJhbWUuMWE1DQpuYW1lcyhEYXRhZnJhbWUuMWE1KQ0KRGF0YWZyYW1lLjFhNSRjDQpmb3IoIGkgaW4gRGF0YWZyYW1lLjFhNSRjICl7DQogIHByaW50KCBpXjIgKQ0KfSAgDQoNCmBgYA0KDQoNCg0KYGBge3J9DQojaGVscCgic3FsZGYiKQ0KDQptdGNhcnMNCiNWaWV3KG10Y2FycykNCg0KYGBgDQoNCmBgYHtyfQ0KZGZfcXVlcnkgPC0gc3FsZGYoInNlbGVjdCAqIGZyb20gbXRjYXJzIikNCmRmX3F1ZXJ5DQojc3RyKGRmX3F1ZXJ5KQ0KDQpgYGANCmBgYHtyfQ0Kc3FsZGYoIlNFTEVDVCBjeWwgLCBjb3VudCggY3lsICkgYXMgQ2lsaW5kcm9zIEZST00gbXRjYXJzIEdST1VQIEJZIGN5bCAiKQ0KYGBgDQoNCmBgYHtyfQ0KZGZfcGl2b3Rfc3FsIDwtIHNxbGRmKCAiIFNFTEVDVCBjeWwgLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09VTlQoIGN5bCApIGFzIENpbGluZHJvcyANCiAgICAgICAgICAgICAgICAgICAgICAgICBGUk9NIG10Y2FycyANCiAgICAgICAgICAgICAgICAgICAgICAgICBHUk9VUCBCWSBjeWwgIikNCmRmX3Bpdm90X3NxbA0KYGBgDQoNCkVKRVJDSUNJT1MgQURJQ0lPTkFMRVMgQ09OIG10Y2FyczoNCg0KYGBge3J9DQojbXRjYXJzDQp0YWJsYS4xIDwtIHRhYmxlKCBtdGNhcnMkY3lsICkNCiN0YWJsYS4xDQoNCmNvbG9yZXMgPC0gYyggIm9yYW5nZSIgLCANCiAgICAgICAgICAgICAgImdyZWVuIiAsIA0KICAgICAgICAgICAgICAieWVsbG93IiApDQojY29sb3Jlcw0KDQpwbG90LjEgPC0gYmFycGxvdCggdGFibGEuMSAsIA0KICAgICAgICAgICAgICAgICAgIHhsYWIgPSAiQ2lsaW5kcm9zIiAsIA0KICAgICAgICAgICAgICAgICAgIHlsYWIgPSAiRnJlcXVlbmNpYSIgLCANCiAgICAgICAgICAgICAgICAgICBtYWluID0gIk5ybyBkZSBDaWxpbmRyb3MiICwNCiAgICAgICAgICAgICAgICAgICBjb2wgPSBjb2xvcmVzICkNCnBsb3QuMQ0KYGBgDQoNCkNPTlRJTlVBQ0lPTiBDT04gbXRjYXJzIDogDQoNCmBgYHtyfQ0KDQpwbG90LjIgPC0gZ2dwbG90KCBtdGNhcnMgLA0KICAgICAgICAgICAgICAgICAgYWVzKCBjeWwgKSkgKw0KICAgICAgICAgIGdlb21fYmFyKCBmaWxsID0gY29sb3JlcyApICsgDQogICAgICAgICAgbGFicyggeD0gIkNpbGluZHJvcyIgLCANCiAgICAgICAgICAgICAgICB5ID0gIkZyZWN1ZW5jaWFzIiAsIA0KICAgICAgICAgICAgICAgIHRpdGxlID0gIk51bWVybyBkZSBDaWxpbmRyb3MiKQ0KcGxvdC4yICANCiAgDQpgYGANCg0KDQoNClJFUEFTTyBERSBNQVRSSUNFUzoNCmBgYHtyfQ0KbWF0cml4LjEgPC0gbWF0cml4KCAxOjEwICwgDQogICAgICAgICAgICBucm93ID0gNSAsIA0KICAgICAgICAgICAgbmNvbCA9IDQgKQ0KbWF0cml4LjENCg0KZGltKG1hdHJpeC4xKQ0KDQptYXRyaXguMVsyLDRdDQptYXRyaXguMVsyLCBdDQptYXRyaXguMVsgLDRdDQpkZl9tYXRyaXguMSA8LSBhcy5kYXRhLmZyYW1lKCBtYXRyaXguMSAsIHJvdy5uYW1lcyA9IE5VTEwsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWwgPSBGQUxTRSAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFrZS5uYW1lcyA9IFRSVUUgLCANCiAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBkZWZhdWx0LnN0cmluZ3NBc0ZhY3RvcnMoKSApDQojZGZfbWF0cml4LjENCiNkZl9tYXRyaXguMSRWNA0KZGZfbWF0cml4LjFbJ1Y0J10NCg0KYGBgDQoNCg0KDQpFSkVSQ0lDSU9TOg0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShkYXRhYmFzZSkNCm1hdHJpeF9zdW1tYXJ5IDwtIGRvLmNhbGwoY2JpbmQsIGxhcHBseShkYXRhYmFzZSwgc3VtbWFyeSkpDQptYXRyaXhfc3VtbWFyeQ0Kc3RyKG1hdHJpeF9zdW1tYXJ5KQ0KZGZfc3VtbWFyeSA8LSBhcy5kYXRhLmZyYW1lKG1hdHJpeF9zdW1tYXJ5LCByb3cubmFtZXMgPSBOVUxMLCBvcHRpb25hbCA9IEZBTFNFLA0KICAgICAgICAgICAgICBtYWtlLm5hbWVzID0gVFJVRSwgDQogICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBkZWZhdWx0LnN0cmluZ3NBc0ZhY3RvcnMoKSkNCmRmX3N1bW1hcnkNCg0Kc3VtbWFyeSggZGF0YWJhc2UkY29zdF9taWxsaW9ucyApDQoNCiMgUmV0cmlldmUgYSBzdWJzZXRfZGF0YWZyYW1lIG9mIHRoZSBkYXRhIGZyYW1lIGNvbnNpc3Rpbmcgb2YgdGhlICJnZW5yZSIgY29sdW1ucw0KZGF0YWJhc2VbJ2dlbnJlJ10NCg0KIyBSZXRyaWV2ZSB0aGUgZGF0YSBmb3IgdGhlICJuYW1lIiBjb2x1bW4gaW4gdGhlIGRhdGEgZnJhbWUgaW4gYSB2ZWN0b3INCmRhdGFiYXNlJGdlbnJlDQoNCmBgYA0KDQpgYGB7cn0NCiMgUmV0cmlldmUgdGhlIGZpcnN0IHJvdyBvZiB0aGUgZGF0YSBmcmFtZS4NCmRhdGFiYXNlWzMsXQ0KDQojIFJldHJpZXZlIHRoZSB0aGlyZCByb3cgb2YgdGhlIGRhdGEgZnJhbWUsIGJ1dCBvbmx5IHRoZSAibmFtZSIgYW5kICJsZW5ndGhfbWluIiBjb2x1bW5zLg0KZGF0YWJhc2VbMywgYygibmFtZSIsImxlbmd0aF9taW4iKV0NCmBgYA0KYGBge3J9DQoNCnN1bW1hcnkoZGF0YWJhc2UpDQpoaXN0b2dyYW1hIDwtIGhpc3QoZGF0YWJhc2UkbGVuZ3RoX21pbiAsY29sPSJ5ZWxsb3ciLGJyZWFrcyA9IDEwKQ0KaGlzdG9ncmFtYQ0KYGBgDQpgYGB7cn0NCg0KdGltZSA9IGdzdWIoIjoiLCAiLSIsIFN5cy50aW1lKCkpDQoNCiMtIGV4cG9ydGEgZW4gZm9ybWF0byAuY3N2IGVsIGRmIGRmX3N1bW1hcnkgYWwgZmljaGVybyAiZGZfc3VtbWFyeS5jc3YiLiBTZSBndWFyZGFyw6EgZW4gbGEgc3ViY2FycGV0YSAiZGF0b3MvcHJ1ZWJhcy8iIGRlbCBwcm95ZWN0bw0KZm9sZGVyX3BhdGggPC0gIi4vb3V0cHV0X2RhdGFiYXNlcy8iDQpmaWxlbmFtZSA8LSAiZGZfc3VtbWFyeSINCmZpbGV0eXBlIDwtIi5jc3YiDQpwYXRoIDwtIHBhc3RlKGZvbGRlcl9wYXRoLGZpbGVuYW1lLCIgIix0aW1lLGZpbGV0eXBlLCBzZXA9IiIpDQp3cml0ZV9jc3YoZGZfc3VtbWFyeSwgcGF0aCkNCg0KDQpgYGANCkhheSB2YXJpb3MgcGFja2FnZXMgcXVlIGdyYWJhbiBkYXRvcyBlbiBmb3JtYXRvIC54bHMuIFBlcm8gZWwgbcOhcyBzZW5jaWxsbyBlcyBlbCBwYWNrYWdlIHhsc3guIFZlw6Ftb3NsbzoNCmBgYHtyfQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJ4bHN4IikNCiMgbGlicmFyeSh4bHN4KQ0Kd3JpdGUueGxzeChkZl9zdW1tYXJ5LCAiLi9vdXRwdXRfZGF0YWJhc2VzL2RmX3N1bW1hcnkueGxzeCIsIHNoZWV0TmFtZSA9ICJkZl9zdW1tYXJ5IiApDQoNCmBgYA0KDQpMYSBmdW5jacOzbiB3cml0ZS54bHN4KCkgcGVybWl0ZSBhw7FhZGlyIGRhdG9zIGEgdW4gYXJjaGl2byAueGxzeCBwcmVleGlzdGVudGU7IHBhcmEgZWxsbyB0ZW5lbW9zIHF1ZSB1c2FyIGxhIG9wY2nDs24gYXBwZW5kID0gVFJVRToNCmBgYHtyfQ0KIyBsaWJyYXJ5KHhsc3gpDQp3cml0ZS54bHN4KGRmX3N1bW1hcnksICIuL291dHB1dF9kYXRhYmFzZXMvZGZfc3VtbWFyeS54bHN4Iiwgc2hlZXROYW1lID0gInN1bW1hcnkiLCBhcHBlbmQgPSBUUlVFKQ0KYGBgDQoNCg0KREVMIEVKRVJDSUNJTyBERSBFSkVDVVRBUiBTUUwgUVVFUlkgZW4gVU4gUiBOT1RFQk9PSzoNCmBgYHtyfQ0Kd3JpdGUueGxzeCggZGZfcGl2b3Rfc3FsICwgDQogICAgICAgICAgICAiLi9vdXRwdXRfZGF0YWJhc2VzL2RmX3Bpdm90X3NxbC54bHN4IiwgDQogICAgICAgICAgICBzaGVldE5hbWUgPSAiZGZfcGl2b3Rfc3FsIiApDQpgYGANCg0KDQoNCg0KR1JBRklDQQ0KYGBge3J9DQojKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg0KIyojIFB1YmxpY2F0aW9uIHF1YWxpdHkgZ3JhcGhzIHJlcXVpcmUgNjAwZHBpDQpkcGk9NjAwICAgICNwaXhlbHMgcGVyIHNxdWFyZSBpbmNoDQpjYXJwZXRhID0gIi4vb3V0cHV0X2ltYWdlcy8iDQphcmNoaXZvID0gImhpc3RvZ3JhbWEiDQp0aW1lID0gZ3N1YigiOiIsICItIiwgU3lzLnRpbWUoKSkNCmNhcnBldGFfeV9hcmNoaXZvID0gcGFzdGUoY2FycGV0YSxhcmNoaXZvLCIgIix0aW1lLCIudGlmIiwgc2VwPSIiKQ0Kbm9tYnJlX2RlX3RpZiA9IGNhcnBldGFfeV9hcmNoaXZvDQp0aWZmKG5vbWJyZV9kZV90aWYsIHdpZHRoPTYqZHBpLCBoZWlnaHQ9NSpkcGksIHJlcz1kcGkpDQojKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg0KaGlzdG9ncmFtYSA8LSBoaXN0KGRhdGFiYXNlJGxlbmd0aF9taW4gLGNvbD0ieWVsbG93IixicmVha3MgPSAxMCkNCmhpc3RvZ3JhbWENCiMqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqDQpkZXYub2ZmKCkNCnByaW50KHBhc3RlKCJGaW5hbGl6YWRvIHByb2Nlc2FtaWVudG8gZGUiLGFyY2hpdm8sIiAiLHRpbWUsIHNlcD0iIikpDQojKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg0KYGBgDQoNCmBgYHtyfQ0KY2l0YXRpb24oKQ0KY2l0YXRpb24oInJlYWR4bCIpIA0KIyANCmhlbHAoInJlYWR4bCIpICMgRG9jdW1lbnRhY2lvbiBkZSBsYSBsaWJyYXJ5IHJlYWR4bA0KDQpgYGA=