1 Inquinamento a San Andreas

Iniziamo scaricando il dataset dal link dove ho isolato (e pulito) i dati raccolti dall’agenzia americana per la tutela dell’ambiente, relativi alle rilevazioni orarie della concentrazione delle PM10 nell’aria nella città di San Andreas, CA.

Questo dataset è una parte di un dataset molto più grande che si può trovare al link.

Una volta salvato il file nella nostra cartella data passiamo a leggere il suo contenuto.

(PM10dataSA <- read.csv("../data/PM10dataSanAndreas.csv"))

Possiamo iniziare a prendere confidenza con il dataset leggendo alcune informazioni essenziali, come la dimensione, il nome delle variabili, oppure ne possiamo esplorare la struttura, visualizzare le prime o le ultime righe.

dim(PM10dataSA)
[1] 2581   28

Vediamo subito che il dataset contiene più di 2mila osservazioni per 26 variabili. Accediamo i nomi delle variabili per vedere se riusciamo a capirne il significato.

names(PM10dataSA)
 [1] "X.2"                 "X.1"                
 [3] "X"                   "State.Code"         
 [5] "County.Code"         "Site.Num"           
 [7] "Parameter.Code"      "POC"                
 [9] "Latitude"            "Longitude"          
[11] "Datum"               "Parameter.Name"     
[13] "Date.Local"          "Time.Local"         
[15] "Date.GMT"            "Time.GMT"           
[17] "Sample.Measurement"  "Units.of.Measure"   
[19] "MDL"                 "Uncertainty"        
[21] "Qualifier"           "Method.Type"        
[23] "Method.Code"         "Method.Name"        
[25] "State.Name"          "County.Name"        
[27] "Date.of.Last.Change" "DateTime.Local"     

Proseguiamo visualizzando la struttura ed alcune righe dei dati.

str(PM10dataSA)
'data.frame':   2581 obs. of  28 variables:
 $ X.2                : int  1 2 3 4 5 6 7 8 9 10 ...
 $ X.1                : int  1 2 3 4 5 6 7 8 9 10 ...
 $ X                  : int  308088 308089 308090 308091 308092 308093 308094 308095 308096 308097 ...
 $ State.Code         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ County.Code        : int  9 9 9 9 9 9 9 9 9 9 ...
 $ Site.Num           : int  1 1 1 1 1 1 1 1 1 1 ...
 $ Parameter.Code     : int  81102 81102 81102 81102 81102 81102 81102 81102 81102 81102 ...
 $ POC                : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Latitude           : num  38.2 38.2 38.2 38.2 38.2 ...
 $ Longitude          : num  -121 -121 -121 -121 -121 ...
 $ Datum              : Factor w/ 1 level "WGS84": 1 1 1 1 1 1 1 1 1 1 ...
 $ Parameter.Name     : Factor w/ 1 level "PM10 Total 0-10um STP": 1 1 1 1 1 1 1 1 1 1 ...
 $ Date.Local         : Factor w/ 120 levels "2016-01-01","2016-01-02",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Time.Local         : Factor w/ 24 levels "00:00","01:00",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ Date.GMT           : Factor w/ 122 levels "2016-01-01","2016-01-02",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Time.GMT           : Factor w/ 24 levels "00:00","01:00",..: 9 10 11 12 13 14 15 16 17 18 ...
 $ Sample.Measurement : int  25 48 26 14 7 14 11 16 17 11 ...
 $ Units.of.Measure   : Factor w/ 1 level "Micrograms/cubic meter (25 C)": 1 1 1 1 1 1 1 1 1 1 ...
 $ MDL                : int  4 4 4 4 4 4 4 4 4 4 ...
 $ Uncertainty        : logi  NA NA NA NA NA NA ...
 $ Qualifier          : logi  NA NA NA NA NA NA ...
 $ Method.Type        : Factor w/ 1 level "FEM": 1 1 1 1 1 1 1 1 1 1 ...
 $ Method.Code        : int  122 122 122 122 122 122 122 122 122 122 ...
 $ Method.Name        : Factor w/ 1 level "INSTRUMENT MET ONE 4 MODELS - BETA ATTENUATION": 1 1 1 1 1 1 1 1 1 1 ...
 $ State.Name         : Factor w/ 1 level "California": 1 1 1 1 1 1 1 1 1 1 ...
 $ County.Name        : Factor w/ 1 level "Calaveras": 1 1 1 1 1 1 1 1 1 1 ...
 $ Date.of.Last.Change: Factor w/ 4 levels "2016-05-06","2016-05-12",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ DateTime.Local     : Factor w/ 2580 levels "2016-01-01 00:00:00",..: 1 2 3 4 5 6 7 8 9 10 ...
head(PM10dataSA)
tail(PM10dataSA)

Vediamo che i dati contengono indicazioni come coordinate geografiche e lo stato dove sono stati raccolti i dati. Nel caso del dataset originale, queste informazioni sono essenziali per individuare il luogo di raccolta dati, mentre nel nostro caso potrebbero essere omesse, dopo aver verificato che siano consistenti in tutto il dataset.

Siamo interessati a capire l’andamento delle PM10 nel nostro dataset durante il tempo in cui sono stati raccolti i dati. Per prima cosa convertiamo i dati riguardanti le date nel giusto formato, cioè in Date. Usiamo per ora solo le informazioni relative al fuso orario locale.

PM10dataSA$Date.Local <- as.Date(PM10dataSA$Date.Local)

Ora che i dati sono in formato Date, R capisce che sono numeri salvati con un particolare formato e non stringhe.

In questo modo possiamo, ad esempio, vedere il periodo temporale che coprono usano i comandi min e max.

paste(min(PM10dataSA$Date.Local), which.min(PM10dataSA$Date.Local))
[1] "2016-01-01 1"
paste(max(PM10dataSA$Date.Local), which.max(PM10dataSA$Date.Local))
[1] "2016-04-30 2559"

Possiamo notare che il dataset non supera Aprile e che il max non è assunto nell’ultima osservazione, che sarebbe la 2867. Usando il comando tail() vediamo di capire perché.

tail(PM10dataSA$Date.Local, 25)
 [1] "2016-04-29" "2016-04-29" "2016-04-30" "2016-04-30"
 [5] "2016-04-30" "2016-04-30" "2016-04-30" "2016-04-30"
 [9] "2016-04-30" "2016-04-30" "2016-04-30" "2016-04-30"
[13] "2016-04-30" "2016-04-30" "2016-04-30" "2016-04-30"
[17] "2016-04-30" "2016-04-30" "2016-04-30" "2016-04-30"
[21] "2016-04-30" "2016-04-30" "2016-04-30" "2016-04-30"
[25] "2016-04-30"

Fortunatamente vediamo che tutte le ultime 24 rilevazioni sono state fatte durante lo stesso giorno, pertanto il risultato di which.min() non è un errore. Ce lo potevamo aspettare, visto che le misurazioni sono ogni ora, ma è sempre meglio controllare.

Usando la funzione summary() estrapoliamo altre informazioni dal dataset.

summary(PM10dataSA)
      X.2            X.1             X            State.Code
 Min.   :   1   Min.   :   1   Min.   :308088   Min.   :6   
 1st Qu.: 646   1st Qu.: 771   1st Qu.:308858   1st Qu.:6   
 Median :1291   Median :1442   Median :309529   Median :6   
 Mean   :1291   Mean   :1464   Mean   :309551   Mean   :6   
 3rd Qu.:1936   3rd Qu.:2192   3rd Qu.:310279   3rd Qu.:6   
 Max.   :2581   Max.   :2867   Max.   :310954   Max.   :6   
                                                            
  County.Code    Site.Num Parameter.Code       POC   
 Min.   :9    Min.   :1   Min.   :81102   Min.   :3  
 1st Qu.:9    1st Qu.:1   1st Qu.:81102   1st Qu.:3  
 Median :9    Median :1   Median :81102   Median :3  
 Mean   :9    Mean   :1   Mean   :81102   Mean   :3  
 3rd Qu.:9    3rd Qu.:1   3rd Qu.:81102   3rd Qu.:3  
 Max.   :9    Max.   :1   Max.   :81102   Max.   :3  
                                                     
    Latitude      Longitude        Datum     
 Min.   :38.2   Min.   :-120.7   WGS84:2581  
 1st Qu.:38.2   1st Qu.:-120.7               
 Median :38.2   Median :-120.7               
 Mean   :38.2   Mean   :-120.7               
 3rd Qu.:38.2   3rd Qu.:-120.7               
 Max.   :38.2   Max.   :-120.7               
                                             
               Parameter.Name   Date.Local        
 PM10 Total 0-10um STP:2581   Min.   :2016-01-01  
                              1st Qu.:2016-02-02  
                              Median :2016-03-01  
                              Mean   :2016-03-02  
                              3rd Qu.:2016-04-02  
                              Max.   :2016-04-30  
                                                  
   Time.Local         Date.GMT       Time.GMT   
 19:00  : 116   2016-01-02:  24   03:00  : 116  
 20:00  : 116   2016-01-03:  24   04:00  : 116  
 06:00  : 113   2016-01-04:  24   02:00  : 113  
 07:00  : 113   2016-01-26:  24   05:00  : 113  
 18:00  : 113   2016-01-28:  24   14:00  : 113  
 21:00  : 113   2016-01-29:  24   15:00  : 113  
 (Other):1897   (Other)   :2437   (Other):1897  
 Sample.Measurement                      Units.of.Measure
 Min.   : 1.00      Micrograms/cubic meter (25 C):2581   
 1st Qu.: 4.00                                           
 Median : 7.00                                           
 Mean   : 8.24                                           
 3rd Qu.:11.00                                           
 Max.   :60.00                                           
                                                         
      MDL    Uncertainty    Qualifier      Method.Type
 Min.   :4   Mode:logical   Mode:logical   FEM:2581   
 1st Qu.:4   NA's:2581      NA's:2581                 
 Median :4                                            
 Mean   :4                                            
 3rd Qu.:4                                            
 Max.   :4                                            
                                                      
  Method.Code 
 Min.   :122  
 1st Qu.:122  
 Median :122  
 Mean   :122  
 3rd Qu.:122  
 Max.   :122  
              
                                         Method.Name  
 INSTRUMENT MET ONE 4 MODELS - BETA ATTENUATION:2581  
                                                      
                                                      
                                                      
                                                      
                                                      
                                                      
      State.Name      County.Name   Date.of.Last.Change
 California:2581   Calaveras:2581   2016-05-06:619     
                                    2016-05-12:656     
                                    2016-06-22:618     
                                    2016-11-08:688     
                                                       
                                                       
                                                       
             DateTime.Local
 2016-01-01 00:00:00:   1  
 2016-01-01 01:00:00:   1  
 2016-01-01 02:00:00:   1  
 2016-01-01 03:00:00:   1  
 2016-01-01 04:00:00:   1  
 (Other)            :2575  
 NA's               :   1  

Possiamo notare che alcune delle variabili sono trattate come numeriche anche se dovrebbero essere di tipo Factor. Possiamo o convertirle, o semplicemente tenerlo a mente qualora dovessimo lavorarci. Inoltre potremmo eliminare le colonne che non ci interessano usano l’assegnazione <- NULL. Ad esempio, dopo aver verificato che latitudine e longitudine sono le stesse in tutto il dataset, e corrispondono alla città di San Andreas, potremmo eliminarle. Va prima verificato che il dataset non contenga dati estranei, altrimenti eliminando una variabile, potremmo non essere più in grado di capirlo!

Tale verifica si può fare (in questo caso, ma può dipende dai dati) o usando il comando unique(), o anche leggendo i risultati di summary().

Volendo visualizzare i dati, che sono raccolti giornalmente, potrebbe fare comodo una colonna che riporta data e ora, in un formato che R riconosce. Possiamo ottenere tutto ciò con un solo comando. Va segnalato che il datset che è stato fornito, già contiene tale colonna, che è stata creata con il comando:

PM10dataSA$DateTime.Local <- as.POSIXct(paste(PM10dataSA[,c("Date.Local")] , PM10dataSA[,c("Time.Local")] ), format = "%Y-%m-%d %H:%M",  tz="America/Los_Angeles",usetz=TRUE)

Ora possiamo visualizzare i dati usando la funzione plot() aggiungendo delle opportune label lungo gli assi per migliorare la leggibilità.

plot(PM10dataSA$DateTime.Local, PM10dataSA$Sample.Measurement, xlab = "2016", ylab= "PM 10 (ug/m3)", cex = .5)

Poiché il grafico contiene un punto per ogni misurazione oraria, il grafico contiene moltissime informazioni.

Aggiungiamo una linea che indica il limite massimo giornaliero di PM 10 consentito (in Italia).

plot(PM10dataSA$DateTime.Local, PM10dataSA$Sample.Measurement, xlab = "2016", ylab= "PM 10 (ug/m3)", cex = .5)
abline(h = 50, col = "red")

# Per salviare l'immagine
#png(filename="../plot/DailyPM10.png")

Si può notare che (fortunatamente) poche misurazioni superano i limiti consentiti.

2 Dati giornalieri

Vediamo di ridurle il numero di dati, aggregandoli per avere misurazioni giornaliere. Possiamo farlo usando la funzione aggregate() che ci permette di applicare una funzione ad un dataset indicando. Possiamo, ad esempio, decidere di salvare in un nuovo dataset le misure medie e massime per i dati di SA.

DailyVal <- aggregate(PM10dataSA$Sample.Measurement ~ Date.Local, data = PM10dataSA, FUN = mean)
DailyVal[,3] <- aggregate(PM10dataSA$Sample.Measurement ~ Date.Local, data = PM10dataSA, FUN = max)[2]
head(DailyVal)

Possiamo migliorare la leggibilità del dataset cambiando i nomi delle variabili.

names(DailyVal)[2:3] <- c("mean daily PM10", "max daily PM 10")
head(DailyVal)

Visualizziamo ora i dati medi e massimi giornalieri:

plot(DailyVal$Date.Local, DailyVal$`mean daily PM10`, xlab = "2016", ylab= "PM 10 (ug/m3)", cex = .8, main = "Concentrazione media giornaliera di PM10")

plot(DailyVal$Date.Local, DailyVal$`max daily PM 10`, xlab = "2016", ylab= "PM 10 (ug/m3)", cex = .8, main = "Concentrazione massima giornaliera di PM10")
abline(h = 50, col = "red")

Potrebbe essere interessante vedere se il giorno della settimana influenza la concentrazione di PM10, ad esempio in giorni con più traffico potremmo aspettarci più inquinamento.

typeof(DailyVal$Date.Local)
[1] "double"
#Sys.setlocale("LC_TIME","C") #Nomi 
DailyVal$DayOfTheWeek <- weekdays(DailyVal$Date.Local, abbreviate = TRUE)
head(DailyVal)
#ordiniamo i giorni in modo che la settimana inizi di lunedì
# ci sarà utile dopo
DailyVal$DayOfTheWeek <- ordered(DailyVal$DayOfTheWeek, levels=c( "Lun" , "Mar", "Mer" , "Gio", "Ven" ,  "Sab", "Dom" ))

Vediamo di colorare il grafico precedente usando un colore diverso per ogni giorno della settimana.

plot(DailyVal$Date.Local, DailyVal$`max daily PM 10`, xlab = "2016", ylab= "PM 10 (ug/m3)", cex = .8, main = "Concentrazione massima giornaliera di PM10", col = DailyVal$DayOfTheWeek)
abline(h = 50, col = "red")

Vediamo che non sembra che i picchi siano raggiunti negli stessi giorni. Comunque una legenda andrebbe aggiunta. Vediamo con dei boxplot come la quantità media di polveri PM10 è distribuita rispetto ai giorni della settimana.

boxplot(`mean daily PM10` ~ DayOfTheWeek, data = DailyVal, ylab= "PM 10 (ug/m3)")

Aggiungere ad esempio una linea che indica le media delle misurazioni, aiuta a fare un confronto tra i dati.

boxplot( `mean daily PM10` ~ DayOfTheWeek, data = DailyVal, ylab= "PM 10 (ug/m3)")
abline(h = mean(DailyVal$`mean daily PM10`), col = "red")

Vediamo la data in cui è stato assunto il valore massimo:

DailyVal[DailyVal$`mean daily PM10` > 20,]

Che sarà successo quel giorno? Potrebbe essere un errore di lettura?

Se volessimo visualizzare la distribuzione dei dati rispetto ai giorni, possiamo usare la funzione hist(). Purtroppo tale funzione non supporta la notazione ~, perciò dovremo specificare un grafico per giorno della settimana.

par(mfrow = c(7,1), mar = c(2,2,1,1))
for (i in levels(DailyVal$DayOfTheWeek) ) {
  hist( DailyVal[DailyVal$DayOfTheWeek == i, "mean daily PM10"] , freq = FALSE, main = i, ylim = c(0, 0.2) , breaks = seq(0,26,2))
}

Dal grafico possiamo capire come si distribuiscono le misurazioni rispetto ai giorni della settimana. Si usi l’help per comprendere i parametri che sono stati usati.

2.1 Regressione (Esercizio)

Possiamo analizzare la relazione tra tempo e inquinamento usando un modello lineare? Proviamo e cerchiamo di capire se il modello è adeguato.

3 Inquinamento in California

Decidiamo ora di concentrare la nostra attenzione sull’inquinamento in California e dopo aver letto il dataset che contiene i valori medi giornalieri di PM10, salviamo un sottoinsieme di dati che contiene solo dati relativi alla California.

PM10data <- read.csv("../data/daily_81102_2016.csv")
dim(PM10data)
[1] 118885     29

Vediamo che il file è molto grande, contiene molte righe e molte variabili. R impiega diverso tempo a leggerlo.

(PM10dataCAL <- PM10data[PM10data$State.Name == "California",])

In questo caso il nome della variabile che ci interessa è Arithmetic.Mean.

Ora vogliamo visualizzare su una mappa quali sono lo città che superano la soglia di inquinamento consentita durante le osservazioni. In R, questa operazione è molto semplice usando i pacchetti maps o RgoogleMaps.

#install.packages("maps")
library(maps)
map("county", "california", xlim=c(-125,-114), ylim=c(32,43))
points( PM10dataCAL[PM10dataCAL$Arithmetic.Mean > 50,c("Longitude", "Latitude")] ,cex = .8, col = "red")

Se vogliamo usare una mappa di Goole Maps possiamo farlo usando il pacchetto dedicato.

map <- RgoogleMaps::GetMap(center="California", zoom = 6)
no non-missing arguments to min; returning Infno non-missing arguments to min; returning Inf
map <- RgoogleMaps::GetMap(center="California", zoom = 6)
map1 <- plotmap( lat =  PM10dataCAL[PM10dataCAL$Arithmetic.Mean > 50,c( "Latitude")], lon =  PM10dataCAL[PM10dataCAL$Arithmetic.Mean > 50,c("Longitude")]  ,map = map)

4 Inquinamento a Los Angeles

Usiamo lo stesso dataset contenente i dati giornalieri relativi alle PM10 negli Stati Uniti e concentriamoci sulla sola città di Los Angeles.

PM10dataLA <- PM10data[PM10data$City.Name== "Los Angeles",]
dim(PM10dataLA)
[1] 90 29

Vediamo che sono state raccolte 90 osservazioni relative alla sola città di LA, cerchiamo di capire quando e con che frequenza sono state raccolte.

typeof(PM10dataLA)
[1] "list"
PM10dataLA$Date.Local[1:10]
 [1] 2016-01-01 2016-01-07 2016-01-13 2016-01-19 2016-01-25
 [6] 2016-01-31 2016-02-06 2016-02-12 2016-02-18 2016-02-24
336 Levels: 2016-01-01 2016-01-02 2016-01-03 ... 2016-12-02

Vediamo che le date sono state salvate come liste. In realtà, come già visto, R prevede il formato Date che potrebbe essere utile e più maneggevole di una lista per fare “operazioni aritmetiche”. Convertiamo quindi la colonna in Date.

PM10dataLA$Date.Local <- as.Date(PM10dataLA$Date.Local)
typeof(PM10dataLA$Date.Local)
[1] "double"

La variabile ora risulta di tipo Date. Questo ci permette, ad esempio, di vedere quanti giorni passano tra una rilevazione e l’altra.

diff(PM10dataLA$Date.Local)
Time differences in days
 [1]    6    6    6    6    6    6    6    6    6    6    6
[12]    6    6    6    6    6    6    6    6    6    7    5
[23]    6    6    6    6    6    6    6    6    6    6    6
[34]    6    6    6    6    6    6    6    6    6    6   12
[45] -270    6    6    6    6    6    6    6    6    6    6
[56]    6    6    6   12    6    6    6    6    6    6    6
[67]    6    6    6    6    6    6    6    6    6    6    6
[78]    6    6    6    6    6    6    6    6    6    6    6
[89]    6

Salta all’occhio che la frequenza delle registrazioni è circa ogni 6 giorni, ma compare un dato inatteso. Investighiamo meglio cosa è successo.

unique(PM10dataLA$Date.Local)
 [1] "2016-01-01" "2016-01-07" "2016-01-13" "2016-01-19"
 [5] "2016-01-25" "2016-01-31" "2016-02-06" "2016-02-12"
 [9] "2016-02-18" "2016-02-24" "2016-03-01" "2016-03-07"
[13] "2016-03-13" "2016-03-19" "2016-03-25" "2016-03-31"
[17] "2016-04-06" "2016-04-12" "2016-04-18" "2016-04-24"
[21] "2016-04-30" "2016-05-07" "2016-05-12" "2016-05-18"
[25] "2016-05-24" "2016-05-30" "2016-06-05" "2016-06-11"
[29] "2016-06-17" "2016-06-23" "2016-06-29" "2016-07-05"
[33] "2016-07-11" "2016-07-17" "2016-07-23" "2016-07-29"
[37] "2016-08-04" "2016-08-10" "2016-08-16" "2016-08-22"
[41] "2016-08-28" "2016-09-03" "2016-09-09" "2016-09-15"
[45] "2016-09-27" "2016-05-06" "2016-09-21"
length(unique(PM10dataLA$Date.Local))
[1] 47

Capiamo che sebbene le osservazioni siano 90, non tutte si riferiscono a giorni differenti, quindi bisogna capire come gestire le misurazioni ripetute durante lo stesso giorno. Vediamo, ad esempio, cosa caratterizza le misurazioni ripetute del primo giorno dell’anno.

PM10dataLA[PM10dataLA$Date.Local== "2016-01-01",]

Possiamo osservare che ci sono almeno due siti diversi dove vengono raccolti i dati. Questa osservazione segue sia la comparsa di due diversi Site.Num per la stessa data, sia le differenze nei valori di Latitude e Longitude. Vediamo se esistono solo due siti o più.

paste(unique(PM10dataLA$Site.Num) , unique(PM10dataLA$Latitude), unique(PM10dataLA$Longitude))
[1] "1103 34.06659 -118.22688" "5005 33.9508 -118.43043" 

Abbiamo appurato che esistono due (e solo due) siti individuati da diverse coordinate geografiche.

Estrapoliamo ora alcune informazioni per le variabili numeriche usando il comando summary().

summary(PM10dataLA)
   State.Code  County.Code    Site.Num    Parameter.Code 
 Min.   :6    Min.   :37   Min.   :1103   Min.   :81102  
 1st Qu.:6    1st Qu.:37   1st Qu.:1103   1st Qu.:81102  
 Median :6    Median :37   Median :3054   Median :81102  
 Mean   :6    Mean   :37   Mean   :3054   Mean   :81102  
 3rd Qu.:6    3rd Qu.:37   3rd Qu.:5005   3rd Qu.:81102  
 Max.   :6    Max.   :37   Max.   :5005   Max.   :81102  
                                                         
      POC         Latitude       Longitude        Datum   
 Min.   :1.0   Min.   :33.95   Min.   :-118.4   NAD83: 0  
 1st Qu.:1.0   1st Qu.:33.95   1st Qu.:-118.4   WGS84:90  
 Median :1.5   Median :34.01   Median :-118.3             
 Mean   :1.5   Mean   :34.01   Mean   :-118.3             
 3rd Qu.:2.0   3rd Qu.:34.07   3rd Qu.:-118.2             
 Max.   :2.0   Max.   :34.07   Max.   :-118.2             
                                                          
               Parameter.Name      Sample.Duration
 PM10 Total 0-10um STP:90     24 HOUR      :90    
                              24-HR BLK AVG: 0    
                                                  
                                                  
                                                  
                                                  
                                                  
         Pollutant.Standard   Date.Local        
 PM10 24-hour 2006:90       Min.   :2016-01-01  
                            1st Qu.:2016-03-07  
                            Median :2016-05-15  
                            Mean   :2016-05-14  
                            3rd Qu.:2016-07-21  
                            Max.   :2016-09-27  
                                                
                      Units.of.Measure    Event.Type
 Micrograms/cubic meter (25 C):90      Excluded: 0  
                                       Included: 0  
                                       None    :90  
                                                    
                                                    
                                                    
                                                    
 Observation.Count Observation.Percent Arithmetic.Mean
 Min.   :1         Min.   :100         Min.   : 6.00  
 1st Qu.:1         1st Qu.:100         1st Qu.:16.00  
 Median :1         Median :100         Median :20.50  
 Mean   :1         Mean   :100         Mean   :22.18  
 3rd Qu.:1         3rd Qu.:100         3rd Qu.:28.00  
 Max.   :1         Max.   :100         Max.   :57.00  
                                                      
 X1st.Max.Value  X1st.Max.Hour      AQI         Method.Code
 Min.   : 6.00   Min.   :0     Min.   : 6.00   Min.   :63  
 1st Qu.:16.00   1st Qu.:0     1st Qu.:15.00   1st Qu.:63  
 Median :20.50   Median :0     Median :19.00   Median :63  
 Mean   :22.18   Mean   :0     Mean   :20.54   Mean   :63  
 3rd Qu.:28.00   3rd Qu.:0     3rd Qu.:26.00   3rd Qu.:63  
 Max.   :57.00   Max.   :0     Max.   :52.00   Max.   :63  
                                                           
                                      Method.Name
 HI-VOL SA/GMW-1200 - GRAVIMETRIC           :90  
  -                                         : 0  
 BGI Inc. Model PQ200 PM10 - Gravimetric    : 0  
 Hi Vol SSI Ecotech Model 3000 - Gravimetric: 0  
 HI-VOL-SA/GMW-321-B - GRAVIMETRIC          : 0  
 HI-VOL-WEDDING-INLET - GRAVIMETRIC         : 0  
 (Other)                                    : 0  
                                             Local.Site.Name
 LAX Hastings                                        :45    
 Los Angeles-North Main Street                       :45    
                                                     : 0    
 1 Site (Met Station and Hi-Vols BA1 and BA1-B)      : 0    
 10 METER TOWER, AT NW CORNER, U OF I RESEARCH CENTER: 0    
 19th & Burt                                         : 0    
 (Other)                                             : 0    
                                   Address        State.Name
 1630 N MAIN ST, LOS ANGELES           :45   California:90  
 7201 W. WESTCHESTER PARKWAY           :45   Alabama   : 0  
  151 NO SUNRISE BLVD, ROSEVILLE, CA   : 0   Alaska    : 0  
  201 ASHVILLE ROAD                    : 0   Arizona   : 0  
  2220 NORTH STREET, ANDERSON, CA 96007: 0   Arkansas  : 0  
  3337 Sandy Way, South Lake Tahoe, CA : 0   Colorado  : 0  
 (Other)                               : 0   (Other)   : 0  
      County.Name           City.Name 
 Los Angeles:90   Los Angeles    :90  
 Ada        : 0   Aberdeen       : 0  
 Adair      : 0   Ajo            : 0  
 Adams      : 0   Ak-Chin Village: 0  
 Alamosa    : 0   Alamosa        : 0  
 Albany     : 0   Albuquerque    : 0  
 (Other)    : 0   (Other)        : 0  
                              CBSA.Name  Date.of.Last.Change
 Los Angeles-Long Beach-Anaheim, CA:90   2016-12-20:90      
                                   : 0   2016-04-11: 0      
 Aberdeen, SD                      : 0   2016-04-15: 0      
 Albuquerque, NM                   : 0   2016-05-11: 0      
 Allentown-Bethlehem-Easton, PA-NJ : 0   2016-05-13: 0      
 Altoona, PA                       : 0   2016-05-18: 0      
 (Other)                           : 0   (Other)   : 0      

Possiamo notare che, anche in questo caso, alcune delle variabili sono trattate come numeriche anche se dovrebbero essere di tipo Factor. Possiamo o convertirle, o semplicemente tenerlo a mente qualora dovessimo lavorarci. Possiamo altrimenti rimuoverle come visto prima.

Per prima cosa, definiamo un campo di interesse. Se vogliamo, ad esempio, vedere l’andamento delle misurazioni medie di PM10 nei due siti, molte delle variabili non ci interessano. Possiamo investigare più nel dettaglio le variabili legate alla nostra indagine e non considerare le altre:

boxplot(Arithmetic.Mean ~ Site.Num, data = PM10dataLA)

Possiamo notare che uno dei due siti presenta delle misurazioni che in generale sono più alte.

plot(PM10dataLA$Date.Local , PM10dataLA$Arithmetic.Mean, col= PM10dataLA$Site.Num, xlab = "2016", ylab = "mean PM10")
legend( "topright", legend = c("1103","5005" ), col= unique(PM10dataLA$Site.Num), pch = c(1,1) )

Vediamo spazialmente dove sono posizionati i due punti di monitoraggio, questo potrebbe spiegare le differenze nelle misurazioni.

mapLA <- RgoogleMaps::GetMap(center="Los Angeles", zoom = 10)
mapLA1 <- plotmap( lat =  unique(PM10dataLA[,c( "Latitude")]), lon = unique(PM10dataLA[,c("Longitude")])  ,map = mapLA)

Dalla mappa sembra che uno dei due siti (cerchi neri) sia in centro mentre il secondo è più vicino alla spiaggia, dove possiamo aspettarci meno traffico.

Per avere una comprensione migliore visualizziamo una mappa differente, che mostra sia le strade che l’immagine satellitare della zona.

mapLA1 <- plotmap( lat =  unique(PM10dataLA[,c( "Latitude")]), lon = unique(PM10dataLA[,c("Longitude")]) , API = "google", maptype = "hybrid", zoom = 11)
TextOnStaticMap(mapLA1,lat =  unique(PM10dataLA[,c( "Latitude")]), lon = unique(PM10dataLA[,c("Longitude")]),labels= unique(PM10dataLA[,c( "Site.Num")]), add=TRUE, cex = 2, col = "green" , pch = 6) 

Vediamo che il secondo punto di osservazione, sebbene registri valori più bassi, probabilmente perché più vicino alla spiaggia, è comunque vicino all’aeroporto. Questo sicuramente influenza la qualità dell’aria e potrebbe spiegare perché sebbene più bassi, i valori non siano bassissimi. Non ci stupirebbe se altri parametri misurati fossero addirittura peggiori rispetto a quelli registrati in centro.

Senza opportuni strumenti di visualizzazione dei dati, non saremmo potuti giungere a queste conclusioni.

LS0tCnRpdGxlOiAiQW5hbGl6emFyZSBpIGRhdGFzZXQgcmVsYXRpdmkgYWxsJ2lucXVpbmFtZW50byIKYXV0aG9yOiAiRmVkZXJpY28gUmVhbGkiCmRhdGU6IDE1LzA1LzIwMTgKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IG5vCiAgICAgIHNtb290aF9zY3JvbGw6IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICB0aGVtZTogeWV0aQogICAgaGlnaGxpZ2h0OiB0YW5nbwotLS0KCiMgSW5xdWluYW1lbnRvIGEgU2FuIEFuZHJlYXMKCkluaXppYW1vIHNjYXJpY2FuZG8gaWwgZGF0YXNldCBkYWwgW2xpbmtdKGh0dHBzOi8vd3d3LmRyb3Bib3guY29tL3MvOXp4MmR0bmU5Z25hZmNtL1BNMTBkYXRhU2FuQW5kcmVhcy5jc3Y/ZGw9MCkgZG92ZSBobyBpc29sYXRvIChlIHB1bGl0bykgaSBkYXRpIHJhY2NvbHRpIGRhbGwnYWdlbnppYSBhbWVyaWNhbmEgcGVyIGxhIHR1dGVsYSBkZWxsJ2FtYmllbnRlLCByZWxhdGl2aSBhbGxlIHJpbGV2YXppb25pIG9yYXJpZSBkZWxsYSBjb25jZW50cmF6aW9uZSBkZWxsZSBQTTEwIG5lbGwnYXJpYSBuZWxsYSBjaXR0w6AgZGkgU2FuIEFuZHJlYXMsIENBLgoKUXVlc3RvIGRhdGFzZXQgw6ggdW5hIHBhcnRlIGRpIHVuIGRhdGFzZXQgbW9sdG8gcGnDuSBncmFuZGUgY2hlIHNpIHB1w7IgdHJvdmFyZSBhbCBbbGlua10oaHR0cDovL2Fxc2RyMS5lcGEuZ292L2Fxc3dlYi9hcXN0bXAvYWlyZGF0YS9kb3dubG9hZF9maWxlcy5odG1sI1JhdykuCgpVbmEgdm9sdGEgc2FsdmF0byBpbCBmaWxlIG5lbGxhIG5vc3RyYSBjYXJ0ZWxsYSBfZGF0YV8gcGFzc2lhbW8gYSBsZWdnZXJlIGlsIHN1byBjb250ZW51dG8uCgpgYGB7cn0KKFBNMTBkYXRhU0EgPC0gcmVhZC5jc3YoIi4uL2RhdGEvUE0xMGRhdGFTYW5BbmRyZWFzLmNzdiIpKQpgYGAKClBvc3NpYW1vIGluaXppYXJlIGEgcHJlbmRlcmUgY29uZmlkZW56YSBjb24gaWwgZGF0YXNldCBsZWdnZW5kbyBhbGN1bmUgaW5mb3JtYXppb25pIGVzc2VuemlhbGksIGNvbWUgbGEgZGltZW5zaW9uZSwgaWwgbm9tZSBkZWxsZSB2YXJpYWJpbGksIG9wcHVyZSBuZSBwb3NzaWFtbyBlc3Bsb3JhcmUgbGEgc3RydXR0dXJhLCB2aXN1YWxpenphcmUgbGUgcHJpbWUgbyBsZSB1bHRpbWUgcmlnaGUuCgpgYGB7cn0KZGltKFBNMTBkYXRhU0EpCmBgYAoKVmVkaWFtbyBzdWJpdG8gY2hlIGlsIGRhdGFzZXQgY29udGllbmUgcGnDuSBkaSAybWlsYSBvc3NlcnZhemlvbmkgcGVyIDI2IHZhcmlhYmlsaS4gQWNjZWRpYW1vIGkgbm9taSBkZWxsZSB2YXJpYWJpbGkgcGVyIHZlZGVyZSBzZSByaXVzY2lhbW8gYSBjYXBpcm5lIGlsIHNpZ25pZmljYXRvLgoKYGBge3J9Cm5hbWVzKFBNMTBkYXRhU0EpCmBgYApQcm9zZWd1aWFtbyB2aXN1YWxpenphbmRvIGxhIHN0cnV0dHVyYSBlZCBhbGN1bmUgcmlnaGUgZGVpIGRhdGkuCgpgYGB7cn0Kc3RyKFBNMTBkYXRhU0EpCmhlYWQoUE0xMGRhdGFTQSkKdGFpbChQTTEwZGF0YVNBKQpgYGAKClZlZGlhbW8gY2hlIGkgZGF0aSBjb250ZW5nb25vIGluZGljYXppb25pIGNvbWUgY29vcmRpbmF0ZSBnZW9ncmFmaWNoZSBlIGxvIHN0YXRvIGRvdmUgc29ubyBzdGF0aSByYWNjb2x0aSBpIGRhdGkuIE5lbCBjYXNvIGRlbCBkYXRhc2V0IG9yaWdpbmFsZSwgcXVlc3RlIGluZm9ybWF6aW9uaSBzb25vIGVzc2VuemlhbGkgcGVyIGluZGl2aWR1YXJlIGlsIGx1b2dvIGRpIHJhY2NvbHRhIGRhdGksIG1lbnRyZSBuZWwgbm9zdHJvIGNhc28gcG90cmViYmVybyBlc3NlcmUgb21lc3NlLCAqKmRvcG8qKiBhdmVyIHZlcmlmaWNhdG8gY2hlIHNpYW5vIGNvbnNpc3RlbnRpIGluIHR1dHRvIGlsIGRhdGFzZXQuCgpTaWFtbyBpbnRlcmVzc2F0aSBhIGNhcGlyZSBsJ2FuZGFtZW50byBkZWxsZSBQTTEwIG5lbCBub3N0cm8gZGF0YXNldCBkdXJhbnRlIGlsIHRlbXBvIGluIGN1aSBzb25vIHN0YXRpIHJhY2NvbHRpIGkgZGF0aS4gUGVyIHByaW1hIGNvc2EgY29udmVydGlhbW8gaSBkYXRpIHJpZ3VhcmRhbnRpIGxlIGRhdGUgbmVsIGdpdXN0byBmb3JtYXRvLCBjaW/DqCBpbiAqRGF0ZSouIFVzaWFtbyBwZXIgb3JhIHNvbG8gbGUgaW5mb3JtYXppb25pIHJlbGF0aXZlIGFsIGZ1c28gb3JhcmlvIGxvY2FsZS4KCmBgYHtyfQpQTTEwZGF0YVNBJERhdGUuTG9jYWwgPC0gYXMuRGF0ZShQTTEwZGF0YVNBJERhdGUuTG9jYWwpCmBgYApPcmEgY2hlIGkgZGF0aSBzb25vIGluIGZvcm1hdG8gKkRhdGUqLCBSIGNhcGlzY2UgY2hlIHNvbm8gbnVtZXJpIHNhbHZhdGkgY29uIHVuIHBhcnRpY29sYXJlIGZvcm1hdG8gZSBub24gc3RyaW5naGUuCgpJbiBxdWVzdG8gbW9kbyBwb3NzaWFtbywgYWQgZXNlbXBpbywgdmVkZXJlIGlsIHBlcmlvZG8gdGVtcG9yYWxlIGNoZSBjb3Byb25vIHVzYW5vIGkgY29tYW5kaSBtaW4gZSBtYXguCgpgYGB7cn0KcGFzdGUobWluKFBNMTBkYXRhU0EkRGF0ZS5Mb2NhbCksIHdoaWNoLm1pbihQTTEwZGF0YVNBJERhdGUuTG9jYWwpKQoKcGFzdGUobWF4KFBNMTBkYXRhU0EkRGF0ZS5Mb2NhbCksIHdoaWNoLm1heChQTTEwZGF0YVNBJERhdGUuTG9jYWwpKQpgYGAKUG9zc2lhbW8gbm90YXJlIGNoZSBpbCBkYXRhc2V0IG5vbiBzdXBlcmEgQXByaWxlIGUgY2hlIGlsIG1heCBub24gw6ggYXNzdW50byBuZWxsJ3VsdGltYSBvc3NlcnZhemlvbmUsIGNoZSBzYXJlYmJlIGxhIDI4NjcuIFVzYW5kbyBpbCBjb21hbmRvIGB0YWlsKClgIHZlZGlhbW8gZGkgY2FwaXJlIHBlcmNow6kuCgpgYGB7cn0KdGFpbChQTTEwZGF0YVNBJERhdGUuTG9jYWwsIDI1KQpgYGAKCkZvcnR1bmF0YW1lbnRlIHZlZGlhbW8gY2hlIHR1dHRlIGxlIHVsdGltZSAyNCByaWxldmF6aW9uaSBzb25vIHN0YXRlIGZhdHRlIGR1cmFudGUgbG8gc3Rlc3NvIGdpb3JubywgcGVydGFudG8gaWwgcmlzdWx0YXRvIGRpIGB3aGljaC5taW4oKWAgbm9uIMOoIHVuIGVycm9yZS4gQ2UgbG8gcG90ZXZhbW8gYXNwZXR0YXJlLCB2aXN0byBjaGUgbGUgbWlzdXJhemlvbmkgc29ubyBvZ25pIG9yYSwgbWEgw6ggc2VtcHJlIG1lZ2xpbyBjb250cm9sbGFyZS4KClVzYW5kbyBsYSBmdW56aW9uZSBgc3VtbWFyeSgpYCBlc3RyYXBvbGlhbW8gYWx0cmUgaW5mb3JtYXppb25pIGRhbCBkYXRhc2V0LgoKYGBge3J9CnN1bW1hcnkoUE0xMGRhdGFTQSkKYGBgCgpQb3NzaWFtbyBub3RhcmUgY2hlIGFsY3VuZSBkZWxsZSB2YXJpYWJpbGkgc29ubyB0cmF0dGF0ZSBjb21lIG51bWVyaWNoZSBhbmNoZSBzZSBkb3ZyZWJiZXJvIGVzc2VyZSBkaSB0aXBvIEZhY3Rvci4gUG9zc2lhbW8gbyBjb252ZXJ0aXJsZSwgbyBzZW1wbGljZW1lbnRlIHRlbmVybG8gYSBtZW50ZSBxdWFsb3JhIGRvdmVzc2ltbyBsYXZvcmFyY2kuIElub2x0cmUgcG90cmVtbW8gZWxpbWluYXJlIGxlIGNvbG9ubmUgY2hlIG5vbiBjaSBpbnRlcmVzc2FubyB1c2FubyBsJ2Fzc2VnbmF6aW9uZSBgPC0gTlVMTGAuIEFkIGVzZW1waW8sICoqZG9wbyoqIGF2ZXIgdmVyaWZpY2F0byBjaGUgbGF0aXR1ZGluZSBlIGxvbmdpdHVkaW5lIHNvbm8gbGUgc3Rlc3NlIGluIHR1dHRvIGlsIGRhdGFzZXQsIGUgY29ycmlzcG9uZG9ubyBhbGxhIGNpdHTDoCBkaSBTYW4gQW5kcmVhcywgcG90cmVtbW8gZWxpbWluYXJsZS4gVmEgcHJpbWEgdmVyaWZpY2F0byBjaGUgaWwgZGF0YXNldCBub24gY29udGVuZ2EgZGF0aSBlc3RyYW5laSwgYWx0cmltZW50aSBlbGltaW5hbmRvIHVuYSB2YXJpYWJpbGUsIHBvdHJlbW1vIG5vbiBlc3NlcmUgcGnDuSBpbiBncmFkbyBkaSBjYXBpcmxvIQoKVGFsZSB2ZXJpZmljYSBzaSBwdcOyIGZhcmUgKGluIHF1ZXN0byBjYXNvLCBtYSBwdcOyIGRpcGVuZGUgZGFpIGRhdGkpIG8gdXNhbmRvIGlsIGNvbWFuZG8gYHVuaXF1ZSgpYCwgbyBhbmNoZSBsZWdnZW5kbyBpIHJpc3VsdGF0aSBkaSBgc3VtbWFyeSgpYC4KClZvbGVuZG8gdmlzdWFsaXp6YXJlIGkgZGF0aSwgY2hlIHNvbm8gcmFjY29sdGkgZ2lvcm5hbG1lbnRlLCBwb3RyZWJiZSBmYXJlIGNvbW9kbyB1bmEgY29sb25uYSBjaGUgcmlwb3J0YSBkYXRhIGUgb3JhLCBpbiB1biBmb3JtYXRvIGNoZSBSIHJpY29ub3NjZS4gClBvc3NpYW1vIG90dGVuZXJlIHR1dHRvIGNpw7IgY29uIHVuIHNvbG8gY29tYW5kby4gVmEgc2VnbmFsYXRvIGNoZSBpbCBkYXRzZXQgY2hlIMOoIHN0YXRvIGZvcm5pdG8sIGdpw6AgY29udGllbmUgdGFsZSBjb2xvbm5hLCBjaGUgw6ggc3RhdGEgY3JlYXRhIGNvbiBpbCBjb21hbmRvOgoKYGBge3J9ClBNMTBkYXRhU0EkRGF0ZVRpbWUuTG9jYWwgPC0gYXMuUE9TSVhjdChwYXN0ZShQTTEwZGF0YVNBWyxjKCJEYXRlLkxvY2FsIildICwgUE0xMGRhdGFTQVssYygiVGltZS5Mb2NhbCIpXSApLCBmb3JtYXQgPSAiJVktJW0tJWQgJUg6JU0iLCAgdHo9IkFtZXJpY2EvTG9zX0FuZ2VsZXMiLHVzZXR6PVRSVUUpCgpgYGAKCk9yYSBwb3NzaWFtbyB2aXN1YWxpenphcmUgaSBkYXRpIHVzYW5kbyBsYSBmdW56aW9uZSBgcGxvdCgpYCBhZ2dpdW5nZW5kbyBkZWxsZSBvcHBvcnR1bmUgbGFiZWwgbHVuZ28gZ2xpIGFzc2kgcGVyIG1pZ2xpb3JhcmUgbGEgbGVnZ2liaWxpdMOgLgoKYGBge3J9CnBsb3QoUE0xMGRhdGFTQSREYXRlVGltZS5Mb2NhbCwgUE0xMGRhdGFTQSRTYW1wbGUuTWVhc3VyZW1lbnQsIHhsYWIgPSAiMjAxNiIsIHlsYWI9ICJQTSAxMCAodWcvbTMpIiwgY2V4ID0gLjUpCmBgYAoKUG9pY2jDqSBpbCBncmFmaWNvIGNvbnRpZW5lIHVuIHB1bnRvIHBlciBvZ25pIG1pc3VyYXppb25lIG9yYXJpYSwgaWwgZ3JhZmljbyBjb250aWVuZSBtb2x0aXNzaW1lIGluZm9ybWF6aW9uaS4gCgpBZ2dpdW5naWFtbyB1bmEgbGluZWEgY2hlIGluZGljYSBpbCBsaW1pdGUgbWFzc2ltbyBnaW9ybmFsaWVybyBkaSBQTSAxMCBjb25zZW50aXRvIChpbiBJdGFsaWEpLgoKYGBge3J9CnBsb3QoUE0xMGRhdGFTQSREYXRlVGltZS5Mb2NhbCwgUE0xMGRhdGFTQSRTYW1wbGUuTWVhc3VyZW1lbnQsIHhsYWIgPSAiMjAxNiIsIHlsYWI9ICJQTSAxMCAodWcvbTMpIiwgY2V4ID0gLjUpCmFibGluZShoID0gNTAsIGNvbCA9ICJyZWQiKQojIFBlciBzYWx2aWFyZSBsJ2ltbWFnaW5lCiNwbmcoZmlsZW5hbWU9Ii4uL3Bsb3QvRGFpbHlQTTEwLnBuZyIpCmBgYAoKU2kgcHXDsiBub3RhcmUgY2hlIChmb3J0dW5hdGFtZW50ZSkgcG9jaGUgbWlzdXJhemlvbmkgc3VwZXJhbm8gaSBsaW1pdGkgY29uc2VudGl0aS4KCiMgRGF0aSBnaW9ybmFsaWVyaQoKVmVkaWFtbyBkaSByaWR1cmxlIGlsIG51bWVybyBkaSBkYXRpLCBhZ2dyZWdhbmRvbGkgcGVyIGF2ZXJlIG1pc3VyYXppb25pIGdpb3JuYWxpZXJlLiBQb3NzaWFtbyBmYXJsbyB1c2FuZG8gbGEgZnVuemlvbmUgYGFnZ3JlZ2F0ZSgpYCBjaGUgY2kgcGVybWV0dGUgZGkgYXBwbGljYXJlIHVuYSBmdW56aW9uZSBhZCB1biBkYXRhc2V0IGluZGljYW5kby4gUG9zc2lhbW8sIGFkIGVzZW1waW8sIGRlY2lkZXJlIGRpIHNhbHZhcmUgaW4gdW4gbnVvdm8gZGF0YXNldCBsZSBtaXN1cmUgbWVkaWUgZSBtYXNzaW1lIHBlciBpIGRhdGkgZGkgU0EuCgpgYGB7cn0KRGFpbHlWYWwgPC0gYWdncmVnYXRlKFBNMTBkYXRhU0EkU2FtcGxlLk1lYXN1cmVtZW50IH4gRGF0ZS5Mb2NhbCwgZGF0YSA9IFBNMTBkYXRhU0EsIEZVTiA9IG1lYW4pCkRhaWx5VmFsWywzXSA8LSBhZ2dyZWdhdGUoUE0xMGRhdGFTQSRTYW1wbGUuTWVhc3VyZW1lbnQgfiBEYXRlLkxvY2FsLCBkYXRhID0gUE0xMGRhdGFTQSwgRlVOID0gbWF4KVsyXQpoZWFkKERhaWx5VmFsKQpgYGAKClBvc3NpYW1vIG1pZ2xpb3JhcmUgbGEgbGVnZ2liaWxpdMOgIGRlbCBkYXRhc2V0IGNhbWJpYW5kbyBpIG5vbWkgZGVsbGUgdmFyaWFiaWxpLgoKYGBge3J9Cm5hbWVzKERhaWx5VmFsKVsyOjNdIDwtIGMoIm1lYW4gZGFpbHkgUE0xMCIsICJtYXggZGFpbHkgUE0gMTAiKQpoZWFkKERhaWx5VmFsKQpgYGAKClZpc3VhbGl6emlhbW8gb3JhIGkgZGF0aSBtZWRpIGUgbWFzc2ltaSBnaW9ybmFsaWVyaToKCmBgYHtyfQpwbG90KERhaWx5VmFsJERhdGUuTG9jYWwsIERhaWx5VmFsJGBtZWFuIGRhaWx5IFBNMTBgLCB4bGFiID0gIjIwMTYiLCB5bGFiPSAiUE0gMTAgKHVnL20zKSIsIGNleCA9IC44LCBtYWluID0gIkNvbmNlbnRyYXppb25lIG1lZGlhIGdpb3JuYWxpZXJhIGRpIFBNMTAiKQpgYGAKCmBgYHtyfQpwbG90KERhaWx5VmFsJERhdGUuTG9jYWwsIERhaWx5VmFsJGBtYXggZGFpbHkgUE0gMTBgLCB4bGFiID0gIjIwMTYiLCB5bGFiPSAiUE0gMTAgKHVnL20zKSIsIGNleCA9IC44LCBtYWluID0gIkNvbmNlbnRyYXppb25lIG1hc3NpbWEgZ2lvcm5hbGllcmEgZGkgUE0xMCIpCmFibGluZShoID0gNTAsIGNvbCA9ICJyZWQiKQpgYGAKClBvdHJlYmJlIGVzc2VyZSBpbnRlcmVzc2FudGUgdmVkZXJlIHNlIGlsIGdpb3JubyBkZWxsYSBzZXR0aW1hbmEgaW5mbHVlbnphIGxhIGNvbmNlbnRyYXppb25lIGRpIFBNMTAsIGFkIGVzZW1waW8gaW4gZ2lvcm5pIGNvbiBwacO5IHRyYWZmaWNvIHBvdHJlbW1vIGFzcGV0dGFyY2kgcGnDuSBpbnF1aW5hbWVudG8uCgpgYGB7cn0KdHlwZW9mKERhaWx5VmFsJERhdGUuTG9jYWwpCiNTeXMuc2V0bG9jYWxlKCJMQ19USU1FIiwiQyIpICNOb21pIApEYWlseVZhbCREYXlPZlRoZVdlZWsgPC0gd2Vla2RheXMoRGFpbHlWYWwkRGF0ZS5Mb2NhbCwgYWJicmV2aWF0ZSA9IFRSVUUpCmhlYWQoRGFpbHlWYWwpCiNvcmRpbmlhbW8gaSBnaW9ybmkgaW4gbW9kbyBjaGUgbGEgc2V0dGltYW5hIGluaXppIGRpIGx1bmVkw6wKIyBjaSBzYXLDoCB1dGlsZSBkb3BvCkRhaWx5VmFsJERheU9mVGhlV2VlayA8LSBvcmRlcmVkKERhaWx5VmFsJERheU9mVGhlV2VlaywgbGV2ZWxzPWMoICJMdW4iICwgIk1hciIsICJNZXIiICwgIkdpbyIsICJWZW4iICwgICJTYWIiLCAiRG9tIiApKQpgYGAKClZlZGlhbW8gZGkgY29sb3JhcmUgaWwgZ3JhZmljbyBwcmVjZWRlbnRlIHVzYW5kbyB1biBjb2xvcmUgZGl2ZXJzbyBwZXIgb2duaSBnaW9ybm8gZGVsbGEgc2V0dGltYW5hLgoKYGBge3J9CnBsb3QoRGFpbHlWYWwkRGF0ZS5Mb2NhbCwgRGFpbHlWYWwkYG1heCBkYWlseSBQTSAxMGAsIHhsYWIgPSAiMjAxNiIsIHlsYWI9ICJQTSAxMCAodWcvbTMpIiwgY2V4ID0gLjgsIG1haW4gPSAiQ29uY2VudHJhemlvbmUgbWFzc2ltYSBnaW9ybmFsaWVyYSBkaSBQTTEwIiwgY29sID0gRGFpbHlWYWwkRGF5T2ZUaGVXZWVrKQphYmxpbmUoaCA9IDUwLCBjb2wgPSAicmVkIikKYGBgCgpWZWRpYW1vIGNoZSBub24gc2VtYnJhIGNoZSBpIHBpY2NoaSBzaWFubyByYWdnaXVudGkgbmVnbGkgc3Rlc3NpIGdpb3JuaS4gQ29tdW5xdWUgdW5hIGxlZ2VuZGEgYW5kcmViYmUgYWdnaXVudGEuIFZlZGlhbW8gY29uIGRlaSBib3hwbG90IGNvbWUgbGEgcXVhbnRpdMOgIG1lZGlhIGRpIHBvbHZlcmkgUE0xMCDDqCBkaXN0cmlidWl0YSByaXNwZXR0byBhaSBnaW9ybmkgZGVsbGEgc2V0dGltYW5hLgoKCmBgYHtyfQpib3hwbG90KGBtZWFuIGRhaWx5IFBNMTBgIH4gRGF5T2ZUaGVXZWVrLCBkYXRhID0gRGFpbHlWYWwsIHlsYWI9ICJQTSAxMCAodWcvbTMpIikKYGBgCgpBZ2dpdW5nZXJlIGFkIGVzZW1waW8gdW5hIGxpbmVhIGNoZSBpbmRpY2EgbGUgbWVkaWEgZGVsbGUgbWlzdXJhemlvbmksIGFpdXRhIGEgZmFyZSB1biBjb25mcm9udG8gdHJhIGkgZGF0aS4gCgpgYGB7cn0KYm94cGxvdCggYG1lYW4gZGFpbHkgUE0xMGAgfiBEYXlPZlRoZVdlZWssIGRhdGEgPSBEYWlseVZhbCwgeWxhYj0gIlBNIDEwICh1Zy9tMykiKQphYmxpbmUoaCA9IG1lYW4oRGFpbHlWYWwkYG1lYW4gZGFpbHkgUE0xMGApLCBjb2wgPSAicmVkIikKYGBgCgpWZWRpYW1vIGxhIGRhdGEgaW4gY3VpIMOoIHN0YXRvIGFzc3VudG8gaWwgdmFsb3JlIG1hc3NpbW86CgpgYGB7cn0KRGFpbHlWYWxbRGFpbHlWYWwkYG1lYW4gZGFpbHkgUE0xMGAgPiAyMCxdCmBgYAoKQ2hlIHNhcsOgIHN1Y2Nlc3NvIHF1ZWwgZ2lvcm5vPyBQb3RyZWJiZSBlc3NlcmUgdW4gZXJyb3JlIGRpIGxldHR1cmE/CgpTZSB2b2xlc3NpbW8gdmlzdWFsaXp6YXJlIGxhIGRpc3RyaWJ1emlvbmUgZGVpIGRhdGkgcmlzcGV0dG8gYWkgZ2lvcm5pLCBwb3NzaWFtbyB1c2FyZSBsYSBmdW56aW9uZSBgaGlzdCgpYC4gUHVydHJvcHBvIHRhbGUgZnVuemlvbmUgbm9uIHN1cHBvcnRhIGxhIG5vdGF6aW9uZSBgfmAsIHBlcmNpw7IgZG92cmVtbyBzcGVjaWZpY2FyZSB1biBncmFmaWNvIHBlciBnaW9ybm8gZGVsbGEgc2V0dGltYW5hLgoKYGBge3IsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gMTV9CnBhcihtZnJvdyA9IGMoNywxKSwgbWFyID0gYygyLDIsMSwxKSkKZm9yIChpIGluIGxldmVscyhEYWlseVZhbCREYXlPZlRoZVdlZWspICkgewogIGhpc3QoIERhaWx5VmFsW0RhaWx5VmFsJERheU9mVGhlV2VlayA9PSBpLCAibWVhbiBkYWlseSBQTTEwIl0gLCBmcmVxID0gRkFMU0UsIG1haW4gPSBpLCB5bGltID0gYygwLCAwLjIpICwgYnJlYWtzID0gc2VxKDAsMjYsMikpCn0KYGBgCgpEYWwgZ3JhZmljbyBwb3NzaWFtbyBjYXBpcmUgY29tZSBzaSBkaXN0cmlidWlzY29ubyBsZSBtaXN1cmF6aW9uaSByaXNwZXR0byBhaSBnaW9ybmkgZGVsbGEgc2V0dGltYW5hLiAKU2kgdXNpIGwnaGVscCBwZXIgY29tcHJlbmRlcmUgaSBwYXJhbWV0cmkgY2hlIHNvbm8gc3RhdGkgdXNhdGkuCgojIyBSZWdyZXNzaW9uZSAoRXNlcmNpemlvKQoKUG9zc2lhbW8gYW5hbGl6emFyZSBsYSByZWxhemlvbmUgdHJhIHRlbXBvIGUgaW5xdWluYW1lbnRvIHVzYW5kbyB1biBtb2RlbGxvIGxpbmVhcmU/IFByb3ZpYW1vIGUgY2VyY2hpYW1vIGRpIGNhcGlyZSBzZSBpbCBtb2RlbGxvIMOoIGFkZWd1YXRvLgoKCiMgSW5xdWluYW1lbnRvIGluIENhbGlmb3JuaWEKCkRlY2lkaWFtbyBvcmEgZGkgY29uY2VudHJhcmUgbGEgbm9zdHJhIGF0dGVuemlvbmUgc3VsbCdpbnF1aW5hbWVudG8gaW4gQ2FsaWZvcm5pYSBlIGRvcG8gYXZlciBsZXR0byBpbCBbZGF0YXNldF0oaHR0cHM6Ly93d3cuZHJvcGJveC5jb20vcy96OTI2ZG1wMmx2ZHo0OHAvZGFpbHlfODExMDJfMjAxNi5jc3Y/ZGw9MSkgY2hlIGNvbnRpZW5lIGkgdmFsb3JpICoqbWVkaSBnaW9ybmFsaWVyaSoqIGRpIFBNMTAsIHNhbHZpYW1vIHVuIHNvdHRvaW5zaWVtZSBkaSBkYXRpIGNoZSBjb250aWVuZSBzb2xvIGRhdGkgcmVsYXRpdmkgYWxsYSBDYWxpZm9ybmlhLgoKYGBge3J9ClBNMTBkYXRhIDwtIHJlYWQuY3N2KCIuLi9kYXRhL2RhaWx5XzgxMTAyXzIwMTYuY3N2IikKZGltKFBNMTBkYXRhKQpgYGAKClZlZGlhbW8gY2hlIGlsIGZpbGUgw6ggbW9sdG8gZ3JhbmRlLCBjb250aWVuZSBtb2x0ZSByaWdoZSBlIG1vbHRlIHZhcmlhYmlsaS4gUiBpbXBpZWdhIGRpdmVyc28gdGVtcG8gYSBsZWdnZXJsby4KCmBgYHtyfQooUE0xMGRhdGFDQUwgPC0gUE0xMGRhdGFbUE0xMGRhdGEkU3RhdGUuTmFtZSA9PSAiQ2FsaWZvcm5pYSIsXSkKYGBgCgpJbiBxdWVzdG8gY2FzbyBpbCBub21lIGRlbGxhIHZhcmlhYmlsZSBjaGUgY2kgaW50ZXJlc3NhIMOoICpBcml0aG1ldGljLk1lYW4qLgoKT3JhIHZvZ2xpYW1vIHZpc3VhbGl6emFyZSBzdSB1bmEgbWFwcGEgcXVhbGkgc29ubyBsbyBjaXR0w6AgY2hlIHN1cGVyYW5vIGxhIHNvZ2xpYSBkaSBpbnF1aW5hbWVudG8gY29uc2VudGl0YSBkdXJhbnRlIGxlIG9zc2VydmF6aW9uaS4gIEluIFIsIHF1ZXN0YSBvcGVyYXppb25lIMOoIG1vbHRvIHNlbXBsaWNlIHVzYW5kbyBpIHBhY2NoZXR0aSBgbWFwc2AgbyBgUmdvb2dsZU1hcHNgLgoKYGBge3IsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gMTB9CiNpbnN0YWxsLnBhY2thZ2VzKCJtYXBzIikKbGlicmFyeShtYXBzKQptYXAoImNvdW50eSIsICJjYWxpZm9ybmlhIiwgeGxpbT1jKC0xMjUsLTExNCksIHlsaW09YygzMiw0MykpCnBvaW50cyggUE0xMGRhdGFDQUxbUE0xMGRhdGFDQUwkQXJpdGhtZXRpYy5NZWFuID4gNTAsYygiTG9uZ2l0dWRlIiwgIkxhdGl0dWRlIildICxjZXggPSAuOCwgY29sID0gInJlZCIpCmBgYAoKU2Ugdm9nbGlhbW8gdXNhcmUgdW5hIG1hcHBhIGRpIEdvb2xlIE1hcHMgcG9zc2lhbW8gZmFybG8gdXNhbmRvIGlsIHBhY2NoZXR0byBkZWRpY2F0by4KCmBgYHtyLCBmaWcud2lkdGggPSAxMCwgZmlnLmhlaWdodCA9IDEwfQojaW5zdGFsbC5wYWNrYWdlcygiUmdvb2dsZU1hcHMiKQpsaWJyYXJ5KFJnb29nbGVNYXBzKQptYXAgPC0gUmdvb2dsZU1hcHM6OkdldE1hcChjZW50ZXI9IkNhbGlmb3JuaWEiLCB6b29tID0gNikKbWFwMSA8LSBwbG90bWFwKCBsYXQgPSAgUE0xMGRhdGFDQUxbUE0xMGRhdGFDQUwkQXJpdGhtZXRpYy5NZWFuID4gNTAsYyggIkxhdGl0dWRlIildLCBsb24gPSAgUE0xMGRhdGFDQUxbUE0xMGRhdGFDQUwkQXJpdGhtZXRpYy5NZWFuID4gNTAsYygiTG9uZ2l0dWRlIildICAsbWFwID0gbWFwKQpgYGAKCiMgSW5xdWluYW1lbnRvIGEgTG9zIEFuZ2VsZXMKClVzaWFtbyBsbyBzdGVzc28gZGF0YXNldCBjb250ZW5lbnRlIGkgZGF0aSBnaW9ybmFsaWVyaSByZWxhdGl2aSBhbGxlIFBNMTAgbmVnbGkgU3RhdGkgVW5pdGkgZSBjb25jZW50cmlhbW9jaSBzdWxsYSBzb2xhIGNpdHTDoCBkaSBMb3MgQW5nZWxlcy4KCmBgYHtyfQpQTTEwZGF0YUxBIDwtIFBNMTBkYXRhW1BNMTBkYXRhJENpdHkuTmFtZT09ICJMb3MgQW5nZWxlcyIsXQpkaW0oUE0xMGRhdGFMQSkKYGBgCgpWZWRpYW1vIGNoZSBzb25vIHN0YXRlIHJhY2NvbHRlIDkwIG9zc2VydmF6aW9uaSByZWxhdGl2ZSBhbGxhIHNvbGEgY2l0dMOgIGRpIExBLCBjZXJjaGlhbW8gZGkgY2FwaXJlIHF1YW5kbyBlIGNvbiBjaGUgZnJlcXVlbnphIHNvbm8gc3RhdGUgcmFjY29sdGUuCgpgYGB7cn0KdHlwZW9mKFBNMTBkYXRhTEEpClBNMTBkYXRhTEEkRGF0ZS5Mb2NhbFsxOjEwXQpgYGAKClZlZGlhbW8gY2hlIGxlIGRhdGUgc29ubyBzdGF0ZSBzYWx2YXRlIGNvbWUgbGlzdGUuIEluIHJlYWx0w6AsIGNvbWUgZ2nDoCB2aXN0bywgIFIgcHJldmVkZSBpbCBmb3JtYXRvICpEYXRlKiBjaGUgcG90cmViYmUgZXNzZXJlIHV0aWxlIGUgcGnDuSBtYW5lZ2dldm9sZSBkaSB1bmEgbGlzdGEgcGVyIGZhcmUgIm9wZXJhemlvbmkgYXJpdG1ldGljaGUiLiBDb252ZXJ0aWFtbyBxdWluZGkgbGEgY29sb25uYSBpbiAqRGF0ZSouCgpgYGB7cn0KUE0xMGRhdGFMQSREYXRlLkxvY2FsIDwtIGFzLkRhdGUoUE0xMGRhdGFMQSREYXRlLkxvY2FsKQp0eXBlb2YoUE0xMGRhdGFMQSREYXRlLkxvY2FsKQpgYGAKCkxhIHZhcmlhYmlsZSBvcmEgcmlzdWx0YSBkaSB0aXBvICpEYXRlLiogUXVlc3RvIGNpIHBlcm1ldHRlLCBhZCBlc2VtcGlvLCBkaSB2ZWRlcmUgcXVhbnRpIGdpb3JuaSBwYXNzYW5vIHRyYSB1bmEgcmlsZXZhemlvbmUgZSBsJ2FsdHJhLgoKYGBge3J9CmRpZmYoUE0xMGRhdGFMQSREYXRlLkxvY2FsKQpgYGAKClNhbHRhIGFsbCdvY2NoaW8gY2hlIGxhIGZyZXF1ZW56YSBkZWxsZSByZWdpc3RyYXppb25pIMOoIGNpcmNhIG9nbmkgNiBnaW9ybmksIG1hIGNvbXBhcmUgdW4gZGF0byBpbmF0dGVzby4gSW52ZXN0aWdoaWFtbyBtZWdsaW8gY29zYSDDqCBzdWNjZXNzby4KCmBgYHtyfQp1bmlxdWUoUE0xMGRhdGFMQSREYXRlLkxvY2FsKQpsZW5ndGgodW5pcXVlKFBNMTBkYXRhTEEkRGF0ZS5Mb2NhbCkpCmBgYAoKQ2FwaWFtbyBjaGUgc2ViYmVuZSBsZSBvc3NlcnZhemlvbmkgc2lhbm8gOTAsIG5vbiB0dXR0ZSBzaSByaWZlcmlzY29ubyBhIGdpb3JuaSBkaWZmZXJlbnRpLCBxdWluZGkgYmlzb2duYSBjYXBpcmUgY29tZSBnZXN0aXJlIGxlIG1pc3VyYXppb25pIHJpcGV0dXRlIGR1cmFudGUgbG8gc3Rlc3NvIGdpb3Juby4gVmVkaWFtbywgYWQgZXNlbXBpbywgY29zYSBjYXJhdHRlcml6emEgbGUgbWlzdXJhemlvbmkgcmlwZXR1dGUgZGVsIHByaW1vIGdpb3JubyBkZWxsJ2Fubm8uCgpgYGB7cn0KUE0xMGRhdGFMQVtQTTEwZGF0YUxBJERhdGUuTG9jYWw9PSAiMjAxNi0wMS0wMSIsXQpgYGAKClBvc3NpYW1vIG9zc2VydmFyZSBjaGUgY2kgc29ubyBhbG1lbm8gZHVlIHNpdGkgZGl2ZXJzaSBkb3ZlIHZlbmdvbm8gcmFjY29sdGkgaSBkYXRpLiBRdWVzdGEgb3NzZXJ2YXppb25lIHNlZ3VlIHNpYSBsYSBjb21wYXJzYSBkaSBkdWUgZGl2ZXJzaSAqU2l0ZS5OdW0qIHBlciBsYSBzdGVzc2EgZGF0YSwgc2lhIGxlIGRpZmZlcmVuemUgbmVpIHZhbG9yaSBkaSBfTGF0aXR1ZGVfIGUgX0xvbmdpdHVkZV8uIFZlZGlhbW8gc2UgZXNpc3Rvbm8gc29sbyBkdWUgc2l0aSBvIHBpw7kuCgpgYGB7cn0KcGFzdGUodW5pcXVlKFBNMTBkYXRhTEEkU2l0ZS5OdW0pICwgdW5pcXVlKFBNMTBkYXRhTEEkTGF0aXR1ZGUpLCB1bmlxdWUoUE0xMGRhdGFMQSRMb25naXR1ZGUpKQpgYGAKCkFiYmlhbW8gYXBwdXJhdG8gY2hlIGVzaXN0b25vIGR1ZSAoZSBzb2xvIGR1ZSkgc2l0aSBpbmRpdmlkdWF0aSBkYSBkaXZlcnNlIGNvb3JkaW5hdGUgZ2VvZ3JhZmljaGUuCgpFc3RyYXBvbGlhbW8gb3JhIGFsY3VuZSBpbmZvcm1hemlvbmkgcGVyIGxlIHZhcmlhYmlsaSBudW1lcmljaGUgdXNhbmRvIGlsIGNvbWFuZG8gYHN1bW1hcnkoKWAuCgpgYGB7cn0Kc3VtbWFyeShQTTEwZGF0YUxBKQpgYGAKClBvc3NpYW1vIG5vdGFyZSBjaGUsIGFuY2hlIGluIHF1ZXN0byBjYXNvLCBhbGN1bmUgZGVsbGUgdmFyaWFiaWxpIHNvbm8gdHJhdHRhdGUgY29tZSBudW1lcmljaGUgYW5jaGUgc2UgZG92cmViYmVybyBlc3NlcmUgZGkgdGlwbyBGYWN0b3IuIFBvc3NpYW1vIG8gY29udmVydGlybGUsIG8gc2VtcGxpY2VtZW50ZSB0ZW5lcmxvIGEgbWVudGUgcXVhbG9yYSBkb3Zlc3NpbW8gbGF2b3JhcmNpLiBQb3NzaWFtbyBhbHRyaW1lbnRpIHJpbXVvdmVybGUgY29tZSB2aXN0byBwcmltYS4gCgoKUGVyIHByaW1hIGNvc2EsIGRlZmluaWFtbyB1biBjYW1wbyBkaSBpbnRlcmVzc2UuIFNlIHZvZ2xpYW1vLCBhZCBlc2VtcGlvLCB2ZWRlcmUgbCdhbmRhbWVudG8gZGVsbGUgbWlzdXJhemlvbmkgbWVkaWUgZGkgUE0xMCBuZWkgZHVlIHNpdGksIG1vbHRlIGRlbGxlIHZhcmlhYmlsaSBub24gY2kgaW50ZXJlc3Nhbm8uIFBvc3NpYW1vIGludmVzdGlnYXJlIHBpw7kgbmVsIGRldHRhZ2xpbyBsZSB2YXJpYWJpbGkgbGVnYXRlIGFsbGEgbm9zdHJhIGluZGFnaW5lIGUgbm9uIGNvbnNpZGVyYXJlIGxlIGFsdHJlOgoKCmBgYHtyfQpib3hwbG90KEFyaXRobWV0aWMuTWVhbiB+IFNpdGUuTnVtLCBkYXRhID0gUE0xMGRhdGFMQSkKYGBgCgpQb3NzaWFtbyBub3RhcmUgY2hlIHVubyBkZWkgZHVlIHNpdGkgcHJlc2VudGEgZGVsbGUgbWlzdXJhemlvbmkgY2hlIGluIGdlbmVyYWxlIHNvbm8gcGnDuSBhbHRlLiAKCmBgYHtyfQpwbG90KFBNMTBkYXRhTEEkRGF0ZS5Mb2NhbCAsIFBNMTBkYXRhTEEkQXJpdGhtZXRpYy5NZWFuLCBjb2w9IFBNMTBkYXRhTEEkU2l0ZS5OdW0sIHhsYWIgPSAiMjAxNiIsIHlsYWIgPSAibWVhbiBQTTEwIikKbGVnZW5kKCAidG9wcmlnaHQiLCBsZWdlbmQgPSBjKCIxMTAzIiwiNTAwNSIgKSwgY29sPSB1bmlxdWUoUE0xMGRhdGFMQSRTaXRlLk51bSksIHBjaCA9IGMoMSwxKSApCmBgYAoKClZlZGlhbW8gc3BhemlhbG1lbnRlIGRvdmUgc29ubyBwb3NpemlvbmF0aSBpIGR1ZSBwdW50aSBkaSBtb25pdG9yYWdnaW8sIHF1ZXN0byBwb3RyZWJiZSBzcGllZ2FyZSBsZSBkaWZmZXJlbnplIG5lbGxlIG1pc3VyYXppb25pLgoKYGBge3IsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gMTB9Cm1hcExBIDwtIFJnb29nbGVNYXBzOjpHZXRNYXAoY2VudGVyPSJMb3MgQW5nZWxlcyIsIHpvb20gPSAxMCkKbWFwTEExIDwtIHBsb3RtYXAoIGxhdCA9ICB1bmlxdWUoUE0xMGRhdGFMQVssYyggIkxhdGl0dWRlIildKSwgbG9uID0gdW5pcXVlKFBNMTBkYXRhTEFbLGMoIkxvbmdpdHVkZSIpXSkgICxtYXAgPSBtYXBMQSkKYGBgCgpEYWxsYSBtYXBwYSBzZW1icmEgY2hlIHVubyBkZWkgZHVlIHNpdGkgKGNlcmNoaSBuZXJpKSBzaWEgaW4gY2VudHJvIG1lbnRyZSBpbCBzZWNvbmRvIMOoIHBpw7kgdmljaW5vIGFsbGEgc3BpYWdnaWEsIGRvdmUgcG9zc2lhbW8gYXNwZXR0YXJjaSBtZW5vIHRyYWZmaWNvLiAKClBlciBhdmVyZSB1bmEgY29tcHJlbnNpb25lIG1pZ2xpb3JlIHZpc3VhbGl6emlhbW8gdW5hIG1hcHBhIGRpZmZlcmVudGUsIGNoZSBtb3N0cmEgc2lhIGxlIHN0cmFkZSBjaGUgbCdpbW1hZ2luZSBzYXRlbGxpdGFyZSBkZWxsYSB6b25hLgoKYGBge3IsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gMTB9Cm1hcExBMSA8LSBwbG90bWFwKCBsYXQgPSAgdW5pcXVlKFBNMTBkYXRhTEFbLGMoICJMYXRpdHVkZSIpXSksIGxvbiA9IHVuaXF1ZShQTTEwZGF0YUxBWyxjKCJMb25naXR1ZGUiKV0pICwgQVBJID0gImdvb2dsZSIsIG1hcHR5cGUgPSAiaHlicmlkIiwgem9vbSA9IDExKQpUZXh0T25TdGF0aWNNYXAobWFwTEExLGxhdCA9ICB1bmlxdWUoUE0xMGRhdGFMQVssYyggIkxhdGl0dWRlIildKSwgbG9uID0gdW5pcXVlKFBNMTBkYXRhTEFbLGMoIkxvbmdpdHVkZSIpXSksbGFiZWxzPSB1bmlxdWUoUE0xMGRhdGFMQVssYyggIlNpdGUuTnVtIildKSwgYWRkPVRSVUUsIGNleCA9IDIsIGNvbCA9ICJncmVlbiIgLCBwY2ggPSA2KSAKYGBgCgpWZWRpYW1vIGNoZSBpbCBzZWNvbmRvIHB1bnRvIGRpIG9zc2VydmF6aW9uZSwgc2ViYmVuZSByZWdpc3RyaSB2YWxvcmkgcGnDuSBiYXNzaSwgcHJvYmFiaWxtZW50ZSBwZXJjaMOpIHBpw7kgdmljaW5vIGFsbGEgc3BpYWdnaWEsIMOoIGNvbXVucXVlIHZpY2lubyBhbGwnYWVyb3BvcnRvLiBRdWVzdG8gc2ljdXJhbWVudGUgaW5mbHVlbnphIGxhIHF1YWxpdMOgIGRlbGwnYXJpYSBlIHBvdHJlYmJlIHNwaWVnYXJlIHBlcmNow6kgc2ViYmVuZSBwacO5IGJhc3NpLCBpIHZhbG9yaSBub24gc2lhbm8gYmFzc2lzc2ltaS4gTm9uIGNpIHN0dXBpcmViYmUgc2UgYWx0cmkgcGFyYW1ldHJpIG1pc3VyYXRpIGZvc3Nlcm8gYWRkaXJpdHR1cmEgcGVnZ2lvcmkgcmlzcGV0dG8gYSBxdWVsbGkgcmVnaXN0cmF0aSBpbiBjZW50cm8uIAoKU2VuemEgb3Bwb3J0dW5pIHN0cnVtZW50aSBkaSB2aXN1YWxpenphemlvbmUgZGVpIGRhdGksIG5vbiBzYXJlbW1vIHBvdHV0aSBnaXVuZ2VyZSBhIHF1ZXN0ZSBjb25jbHVzaW9uaS4K