Student Details

Student Name (s3868685)

Problem Statement

The dataset contains 3 variables for two cities of Melbourne and Sydney, of 3 months of the year that are Dec2021-Jan 2022 and Feb-2022, collected from: Data Source: http://www.bom.gov.au/climate/data/stations/ http://www.bom.gov.au/climate/data/index.shtml?bookmark=136

Variables selected in the dataset:

1- Solar exposure: The Daily global solar exposure is the total solar energy for a day falling on a horizontal surface. It is measured from midnight to midnight. The values are usually highest in clear sun conditions during the summer and lowest during winter or very cloudy days and

2- Maximum temperature: It is the highest temperature recorded in the 24 hours from 9 am.

The objective of this statistical analysis is to see the variation between the solar exposure and maximum temperatures observed for both cities Melbourne and Sydney. It is interesting to see the variations in both variables for cities which are located at different geographical locations and have different weathers.

Load Packages

# This is a chunk where you can load the necessary packages required to reproduce the report
library(colorspace)
library(dplyr)
library(evaluate)
library(epitools)
library(forcats)
library(ggplot2)
library(grid)
library(gridExtra)
library(Hmisc)
library(htmlwidgets)
library(knitr)
library(lattice)
library(lubridate)
library(magrittr)
library(MVN)
library(outliers)
library(Rcpp)
library(readr)
library(readxl)
library(rmarkdown)
library(sp)
library(stringr)
library(tibble)
library(tidyr)
library(tidyselect)
library(tidyverse)
library(validate)

Data

Import the climate data and prepare it for analysis. Show your code.

# This is a chunk for your Data section. 

#Importing datasets
Climate_Melb <- read_csv("C:/Users/praam/OneDrive - RMIT University/Data-Applied Analytics/Climate Data Melbourne.csv")
Rows: 90 Columns: 7── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): Day
dbl (6): Station number, Year, Month, Maximum Temperature, Solar Exposure, Wind speed
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Climate_Syd <- read_csv("C:/Users/praam/OneDrive - RMIT University/Data-Applied Analytics/Climate Data Sydney.csv")
New names:Rows: 90 Columns: 8── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): Day
dbl (6): Station number, Year, Month, Maximum Temperature, Solar Exposure, maximum wind speed
lgl (1): ...6
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#Scanning/Checking the header of imported datasets
head(Climate_Melb)
head(Climate_Syd)

#Renaming column names for dataset imported
Climate_Melb <- Climate_Melb %>% rename_at('Station number', ~'Station')
Climate_Melb <- Climate_Melb %>% rename_at('Maximum Temperature', ~'Temperature')
Climate_Melb <- Climate_Melb %>% rename_at('Solar Exposure', ~'Solar_expo')
Climate_Melb <- Climate_Melb %>% rename_at('Wind speed', ~'Wind_speed')

#Deleting the blank column and ensuring that both cities data sets have same variable names 
Climate_Syd <- Climate_Syd[, c(-6)]
colnames(Climate_Syd) <- c(colnames(Climate_Melb))

# replace Station numbers with City names
Climate_Melb$Station <- as.character(Climate_Melb$Station)
Climate_Melb['Station'][Climate_Melb['Station'] == 86282] <- "Melbourne"

Climate_Syd$Station <- as.character(Climate_Syd$Station)
Climate_Syd['Station'][Climate_Syd['Station'] == 66212] <- "Sydney"

#Extracting day number from day character and creating additional date column 
Climate_Melb$Day <- as.numeric(str_replace_all(Climate_Melb$Day, pattern = "[a-z]", replacement = ""))
Climate_Syd$Day <- as.numeric(str_replace_all(Climate_Syd$Day, pattern = "[a-z]", replacement = ""))

#Rearranging column variables and shifting of newly added date column after station number
Climate_Melb<- Climate_Melb %>% mutate(Date = make_date(Year, Month, Day),.after = "Station") 
Climate_Syd<- Climate_Syd %>% mutate(Date = make_date(Year, Month, Day),.after = "Station")

head(Climate_Melb)
head(Climate_Syd)

#Data type conversions
Climate_Melb$Year <- factor(Climate_Melb$Year)
Climate_Melb$Month <- factor(Climate_Melb$Month)
Climate_Melb$Day <- factor(Climate_Melb$Day)

Climate_Syd$Year <- factor(Climate_Syd$Year)
Climate_Syd$Month <- factor(Climate_Syd$Month)
Climate_Syd$Day <- factor(Climate_Syd$Day)

#Merging of both data cities/ station number datasets
Climate_cities <- as.data.frame(bind_rows(Climate_Melb, Climate_Syd))
Climate_cities$Station<- factor(Climate_cities$Station)
head(Climate_cities)

# Select specific variables from the data and store them in a new data frame

#Creating a subset of dataset with Station name, Date, Max temperature and solar exposure for Melbourne

Melb <- Climate_Melb[,c(-3,-4,-5,-8)] %>% as.data.frame(Melb)

#Creating a subset of dataset with Station name, Date, Max temperature and solar exposure for Sydney
Syd <- Climate_Syd[,c(-3,-4,-5,-8)] %>% as.data.frame(Syd)

#On investigating the imported data it is observed that there is one NA value which can alter the results and hence will be replaced by mean of temperatures for Sydney
Syd$Temperature <- impute(Syd$Temperature, fun = mean)

#Creating a subset of dataset with Station name, Date, Max temperature and solar exposure for both cities

Cities <- table(Climate_cities$Solar_expo, Climate_cities$Temperature)

Summary Statistics

Calculate descriptive statistics (i.e., mean, median, standard deviation, first and third quartile, interquartile range, minimum and maximum values) of the selected variable grouped by city.

# This is a chunk for your Summary Statistics section. 

#Summary statistic of Temperature variable grouped by city 
City_Temp <- Climate_cities %>% group_by(Station) %>% summarise(Min = min(Temperature,na.rm = TRUE),
                                         Q1 = quantile(Temperature,probs = .25,na.rm = TRUE),
                                         Median = median(Temperature, na.rm = TRUE),
                                         Q3 = quantile(Temperature,probs = .75,na.rm = TRUE),
                                         Max = max(Temperature,na.rm = TRUE),
                                         Mean = mean(Temperature, na.rm = TRUE),
                                         SD = sd(Temperature, na.rm = TRUE),
                                         n = n(),
                                         Missing = sum(is.na(Temperature)))
City_Temp

#On investigating the summary it is observed that there is one NA value which can alter the results and hence will be replaced by mean of temperatures for Sydney

Climate_cities$Temperature <- impute(Climate_cities$Temperature, fun = mean)

#Rerun the summary statistic after NA replacement with median
City_Temp <- Climate_cities %>% group_by(Station) %>% summarise(Min = min(Temperature,na.rm = TRUE),
                                         Q1 = quantile(Temperature,probs = .25,na.rm = TRUE),
                                         Median = median(Temperature, na.rm = TRUE),
                                         Q3 = quantile(Temperature,probs = .75,na.rm = TRUE),
                                         Max = max(Temperature,na.rm = TRUE),
                                         Mean = mean(Temperature, na.rm = TRUE),
                                         SD = sd(Temperature, na.rm = TRUE),
                                         n = n(),
                                         Missing = sum(is.na(Temperature)))
#Summary statistic of Max. temperature variables grouped by city
City_Temp
City_Temp_Melb <- City_Temp %>% filter(City_Temp$Station == "Melbourne")
City_Temp_Syd <- City_Temp %>% filter(City_Temp$Station == "Sydney")

#Summary statistic of Solar exposure variable grouped by city 
City_Solar_expo <- Climate_cities %>% group_by(Station) %>% summarise(Min = min(Solar_expo,na.rm = TRUE),
                                         Q1 = quantile(Solar_expo,probs = .25,na.rm = TRUE),
                                         Median = median(Solar_expo, na.rm = TRUE),
                                         Q3 = quantile(Solar_expo,probs = .75,na.rm = TRUE),
                                         Max = max(Solar_expo,na.rm = TRUE),
                                         Mean = mean(Solar_expo, na.rm = TRUE),
                                         SD = sd(Solar_expo, na.rm = TRUE),
                                         n = n(),
                                         Missing = sum(is.na(Solar_expo)))
City_Solar_expo
City_Solar_Melb <- City_Solar_expo %>% filter(City_Solar_expo$Station == "Melbourne")
City_Solar_Syd <- City_Solar_expo %>% filter(City_Solar_expo$Station == "Sydney")

Distribution Fitting

Compare the empirical distribution of selected variable to a normal distribution separately in Melbourne and in Sydney. You need to do this visually by plotting the histogram with normal distribution overlay. Show your code.

# This is a chunk for your Distribution Fitting section.

#Plotting histogram for City temperatures to observe behavior/pattern of temperatures across cities

par(mfrow = c(2, 2))
#Histogram with normal distribution overlay for Melbourne temperature variable
x <- rnorm(1000, mean= 0, sd =1)
x1<-rnorm(n=City_Temp_Melb$n,mean = City_Temp_Melb$Mean, sd = City_Temp_Melb$SD)
hist(x1, freq= FALSE, xlim=c(10, 50), breaks=15)
curve(dnorm(x,mean(x1),sd(x1)), add= TRUE)
abline(v=mean(x1),col='red',lw=2)

#Histogram with normal distribution overlay for Sydney temperature variable
x2<-rnorm(n=City_Temp_Syd$n,mean = City_Temp_Syd$Mean, sd = City_Temp_Syd$SD)
hist(x2, freq= FALSE, xlim=c(10, 50),breaks=15)
curve(dnorm(x,mean(x2),sd(x2)), add= TRUE)
abline(v=mean(x2),col='red',lw=2)

#Histogram with normal distribution overlay for Melbourne solar exposure variable)
x3<-rnorm(n=City_Solar_Melb$n,mean = City_Solar_Melb$Mean, sd = City_Solar_Melb$SD)
hist(x3, freq= FALSE, xlim=c(0, 40),breaks=15)
curve(dnorm(x,mean(x3),sd(x3)), add= TRUE)
abline(v=mean(x3),col='red',lw=2)

#Histogram with normal distribution overlay for Sydney solar exposure variable
x4<-rnorm(n=City_Solar_Syd$n,mean = City_Solar_Syd$Mean, sd = City_Solar_Syd$SD)
hist(x4, freq= FALSE, xlim=c(0, 40),breaks=15)
curve(dnorm(x,mean(x4),sd(x4)), add= TRUE)
abline(v=mean(x4),col='red',lw=2)

Interpretation

Going back to your problem statement, what insight has been gained from the investigation?

After plotting the respective variables histograms along with normal distribution curves and analyzing empirical data, following can be inferred, for the months of Dec-22 to Feb-23

  1. Melbourne temperatures The melbourne max. temperatures are generally more spread or unevenly distributed. There are more variations in daily max. temperaure which is reflected by density plot.

  2. Sydney temperatures When compared to Melbourne temperatures, Sydney temperatures are more evenly distributed. There are less variations, which is also reflected in high density plot.

Also, difference, between min and max. temperatures is less for Sydney than Melbourne daily temperatures.

  1. Melbourne Solar exposure Solar exposure in Melbourne case seems to be evenly distributed across normal distribution curve indicating uniform distribution.

  2. Sydney Solar exposure Solar exposure in Sydney seems to be more uniform across normal distribution curve indicating more consistency/less weather predictability. On comparison between solar exposure of both cities Melbourne and Sydney, there doesn’t seems to be more difference and distribution. This is also indicated by similar Mean values. However, there are days which have more solar exposure than remaining days, in case of Melbourne than Sydney which is also reflected by Median values of solar exposure of both cities.

LS0tDQp0aXRsZTogIk1BVEgxMzI0IEFzc2lnbm1lbnQgMSINCnN1YnRpdGxlOiBTdGF0aXN0aWNhbCBhbmFseXNpcyBvZiBDbGltYXRlIGRhdGENCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQojIyBTdHVkZW50IERldGFpbHMNCg0KDQpTdHVkZW50IE5hbWUgKHMzODY4Njg1KQ0KDQojIyBQcm9ibGVtIFN0YXRlbWVudA0KDQpUaGUgZGF0YXNldCBjb250YWlucyAzIHZhcmlhYmxlcyBmb3IgdHdvIGNpdGllcyBvZiBNZWxib3VybmUgYW5kIFN5ZG5leSwgb2YgMyBtb250aHMgb2YgdGhlIHllYXIgdGhhdCBhcmUgRGVjMjAyMS1KYW4gMjAyMiBhbmQgRmViLTIwMjIsIGNvbGxlY3RlZCBmcm9tOiANCkRhdGEgU291cmNlOiBodHRwOi8vd3d3LmJvbS5nb3YuYXUvY2xpbWF0ZS9kYXRhL3N0YXRpb25zLw0KaHR0cDovL3d3dy5ib20uZ292LmF1L2NsaW1hdGUvZGF0YS9pbmRleC5zaHRtbD9ib29rbWFyaz0xMzYNCg0KVmFyaWFibGVzIHNlbGVjdGVkIGluIHRoZSBkYXRhc2V0Og0KDQoxLSBTb2xhciBleHBvc3VyZTogVGhlIERhaWx5IGdsb2JhbCBzb2xhciBleHBvc3VyZSBpcyB0aGUgdG90YWwgc29sYXIgZW5lcmd5IGZvciBhIGRheSBmYWxsaW5nIG9uIGEgaG9yaXpvbnRhbCBzdXJmYWNlLiBJdCBpcyBtZWFzdXJlZCBmcm9tIG1pZG5pZ2h0IHRvIG1pZG5pZ2h0LiBUaGUgdmFsdWVzIGFyZSB1c3VhbGx5IGhpZ2hlc3QgaW4gY2xlYXIgc3VuIGNvbmRpdGlvbnMgZHVyaW5nIHRoZSBzdW1tZXIgYW5kIGxvd2VzdCBkdXJpbmcgd2ludGVyIG9yIHZlcnkgY2xvdWR5IGRheXMgYW5kDQoNCjItIE1heGltdW0gdGVtcGVyYXR1cmU6IEl0IGlzIHRoZSBoaWdoZXN0IHRlbXBlcmF0dXJlIHJlY29yZGVkIGluIHRoZSAyNCBob3VycyBmcm9tIDkgYW0uDQoNClRoZSBvYmplY3RpdmUgb2YgdGhpcyBzdGF0aXN0aWNhbCBhbmFseXNpcyBpcyB0byBzZWUgdGhlIHZhcmlhdGlvbiBiZXR3ZWVuIHRoZSBzb2xhciBleHBvc3VyZSBhbmQgbWF4aW11bSB0ZW1wZXJhdHVyZXMgb2JzZXJ2ZWQgZm9yIGJvdGggY2l0aWVzIE1lbGJvdXJuZSBhbmQgU3lkbmV5LiBJdCBpcyBpbnRlcmVzdGluZyB0byBzZWUgdGhlIHZhcmlhdGlvbnMgaW4gYm90aCB2YXJpYWJsZXMgZm9yIGNpdGllcyB3aGljaCBhcmUgbG9jYXRlZCBhdCBkaWZmZXJlbnQgZ2VvZ3JhcGhpY2FsIGxvY2F0aW9ucyBhbmQgaGF2ZSBkaWZmZXJlbnQgd2VhdGhlcnMuIA0KDQojIyBMb2FkIFBhY2thZ2VzDQoNCmBgYHtyfQ0KIyBUaGlzIGlzIGEgY2h1bmsgd2hlcmUgeW91IGNhbiBsb2FkIHRoZSBuZWNlc3NhcnkgcGFja2FnZXMgcmVxdWlyZWQgdG8gcmVwcm9kdWNlIHRoZSByZXBvcnQNCmxpYnJhcnkoY29sb3JzcGFjZSkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGV2YWx1YXRlKQ0KbGlicmFyeShlcGl0b29scykNCmxpYnJhcnkoZm9yY2F0cykNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZ3JpZCkNCmxpYnJhcnkoZ3JpZEV4dHJhKQ0KbGlicmFyeShIbWlzYykNCmxpYnJhcnkoaHRtbHdpZGdldHMpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShsYXR0aWNlKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KbGlicmFyeShNVk4pDQpsaWJyYXJ5KG91dGxpZXJzKQ0KbGlicmFyeShSY3BwKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShybWFya2Rvd24pDQpsaWJyYXJ5KHNwKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeSh0aWJibGUpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeSh0aWR5c2VsZWN0KQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHZhbGlkYXRlKQ0KYGBgDQoNCiMjIERhdGENCg0KSW1wb3J0IHRoZSBjbGltYXRlIGRhdGEgYW5kIHByZXBhcmUgaXQgZm9yIGFuYWx5c2lzLiBTaG93IHlvdXIgY29kZS4NCg0KYGBge3J9DQojIFRoaXMgaXMgYSBjaHVuayBmb3IgeW91ciBEYXRhIHNlY3Rpb24uIA0KDQojSW1wb3J0aW5nIGRhdGFzZXRzDQpDbGltYXRlX01lbGIgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL3ByYWFtL09uZURyaXZlIC0gUk1JVCBVbml2ZXJzaXR5L0RhdGEtQXBwbGllZCBBbmFseXRpY3MvQ2xpbWF0ZSBEYXRhIE1lbGJvdXJuZS5jc3YiKQ0KQ2xpbWF0ZV9TeWQgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL3ByYWFtL09uZURyaXZlIC0gUk1JVCBVbml2ZXJzaXR5L0RhdGEtQXBwbGllZCBBbmFseXRpY3MvQ2xpbWF0ZSBEYXRhIFN5ZG5leS5jc3YiKQ0KDQojU2Nhbm5pbmcvQ2hlY2tpbmcgdGhlIGhlYWRlciBvZiBpbXBvcnRlZCBkYXRhc2V0cw0KaGVhZChDbGltYXRlX01lbGIpDQpoZWFkKENsaW1hdGVfU3lkKQ0KDQojUmVuYW1pbmcgY29sdW1uIG5hbWVzIGZvciBkYXRhc2V0IGltcG9ydGVkDQpDbGltYXRlX01lbGIgPC0gQ2xpbWF0ZV9NZWxiICU+JSByZW5hbWVfYXQoJ1N0YXRpb24gbnVtYmVyJywgfidTdGF0aW9uJykNCkNsaW1hdGVfTWVsYiA8LSBDbGltYXRlX01lbGIgJT4lIHJlbmFtZV9hdCgnTWF4aW11bSBUZW1wZXJhdHVyZScsIH4nVGVtcGVyYXR1cmUnKQ0KQ2xpbWF0ZV9NZWxiIDwtIENsaW1hdGVfTWVsYiAlPiUgcmVuYW1lX2F0KCdTb2xhciBFeHBvc3VyZScsIH4nU29sYXJfZXhwbycpDQpDbGltYXRlX01lbGIgPC0gQ2xpbWF0ZV9NZWxiICU+JSByZW5hbWVfYXQoJ1dpbmQgc3BlZWQnLCB+J1dpbmRfc3BlZWQnKQ0KDQojRGVsZXRpbmcgdGhlIGJsYW5rIGNvbHVtbiBhbmQgZW5zdXJpbmcgdGhhdCBib3RoIGNpdGllcyBkYXRhIHNldHMgaGF2ZSBzYW1lIHZhcmlhYmxlIG5hbWVzIA0KQ2xpbWF0ZV9TeWQgPC0gQ2xpbWF0ZV9TeWRbLCBjKC02KV0NCmNvbG5hbWVzKENsaW1hdGVfU3lkKSA8LSBjKGNvbG5hbWVzKENsaW1hdGVfTWVsYikpDQoNCiMgcmVwbGFjZSBTdGF0aW9uIG51bWJlcnMgd2l0aCBDaXR5IG5hbWVzDQpDbGltYXRlX01lbGIkU3RhdGlvbiA8LSBhcy5jaGFyYWN0ZXIoQ2xpbWF0ZV9NZWxiJFN0YXRpb24pDQpDbGltYXRlX01lbGJbJ1N0YXRpb24nXVtDbGltYXRlX01lbGJbJ1N0YXRpb24nXSA9PSA4NjI4Ml0gPC0gIk1lbGJvdXJuZSINCg0KQ2xpbWF0ZV9TeWQkU3RhdGlvbiA8LSBhcy5jaGFyYWN0ZXIoQ2xpbWF0ZV9TeWQkU3RhdGlvbikNCkNsaW1hdGVfU3lkWydTdGF0aW9uJ11bQ2xpbWF0ZV9TeWRbJ1N0YXRpb24nXSA9PSA2NjIxMl0gPC0gIlN5ZG5leSINCg0KI0V4dHJhY3RpbmcgZGF5IG51bWJlciBmcm9tIGRheSBjaGFyYWN0ZXIgYW5kIGNyZWF0aW5nIGFkZGl0aW9uYWwgZGF0ZSBjb2x1bW4gDQpDbGltYXRlX01lbGIkRGF5IDwtIGFzLm51bWVyaWMoc3RyX3JlcGxhY2VfYWxsKENsaW1hdGVfTWVsYiREYXksIHBhdHRlcm4gPSAiW2Etel0iLCByZXBsYWNlbWVudCA9ICIiKSkNCkNsaW1hdGVfU3lkJERheSA8LSBhcy5udW1lcmljKHN0cl9yZXBsYWNlX2FsbChDbGltYXRlX1N5ZCREYXksIHBhdHRlcm4gPSAiW2Etel0iLCByZXBsYWNlbWVudCA9ICIiKSkNCg0KI1JlYXJyYW5naW5nIGNvbHVtbiB2YXJpYWJsZXMgYW5kIHNoaWZ0aW5nIG9mIG5ld2x5IGFkZGVkIGRhdGUgY29sdW1uIGFmdGVyIHN0YXRpb24gbnVtYmVyDQpDbGltYXRlX01lbGI8LSBDbGltYXRlX01lbGIgJT4lIG11dGF0ZShEYXRlID0gbWFrZV9kYXRlKFllYXIsIE1vbnRoLCBEYXkpLC5hZnRlciA9ICJTdGF0aW9uIikgDQpDbGltYXRlX1N5ZDwtIENsaW1hdGVfU3lkICU+JSBtdXRhdGUoRGF0ZSA9IG1ha2VfZGF0ZShZZWFyLCBNb250aCwgRGF5KSwuYWZ0ZXIgPSAiU3RhdGlvbiIpDQoNCmhlYWQoQ2xpbWF0ZV9NZWxiKQ0KaGVhZChDbGltYXRlX1N5ZCkNCg0KI0RhdGEgdHlwZSBjb252ZXJzaW9ucw0KQ2xpbWF0ZV9NZWxiJFllYXIgPC0gZmFjdG9yKENsaW1hdGVfTWVsYiRZZWFyKQ0KQ2xpbWF0ZV9NZWxiJE1vbnRoIDwtIGZhY3RvcihDbGltYXRlX01lbGIkTW9udGgpDQpDbGltYXRlX01lbGIkRGF5IDwtIGZhY3RvcihDbGltYXRlX01lbGIkRGF5KQ0KDQpDbGltYXRlX1N5ZCRZZWFyIDwtIGZhY3RvcihDbGltYXRlX1N5ZCRZZWFyKQ0KQ2xpbWF0ZV9TeWQkTW9udGggPC0gZmFjdG9yKENsaW1hdGVfU3lkJE1vbnRoKQ0KQ2xpbWF0ZV9TeWQkRGF5IDwtIGZhY3RvcihDbGltYXRlX1N5ZCREYXkpDQoNCiNNZXJnaW5nIG9mIGJvdGggZGF0YSBjaXRpZXMvIHN0YXRpb24gbnVtYmVyIGRhdGFzZXRzDQpDbGltYXRlX2NpdGllcyA8LSBhcy5kYXRhLmZyYW1lKGJpbmRfcm93cyhDbGltYXRlX01lbGIsIENsaW1hdGVfU3lkKSkNCkNsaW1hdGVfY2l0aWVzJFN0YXRpb248LSBmYWN0b3IoQ2xpbWF0ZV9jaXRpZXMkU3RhdGlvbikNCmhlYWQoQ2xpbWF0ZV9jaXRpZXMpDQoNCiMgU2VsZWN0IHNwZWNpZmljIHZhcmlhYmxlcyBmcm9tIHRoZSBkYXRhIGFuZCBzdG9yZSB0aGVtIGluIGEgbmV3IGRhdGEgZnJhbWUNCg0KI0NyZWF0aW5nIGEgc3Vic2V0IG9mIGRhdGFzZXQgd2l0aCBTdGF0aW9uIG5hbWUsIERhdGUsIE1heCB0ZW1wZXJhdHVyZSBhbmQgc29sYXIgZXhwb3N1cmUgZm9yIE1lbGJvdXJuZQ0KDQpNZWxiIDwtIENsaW1hdGVfTWVsYlssYygtMywtNCwtNSwtOCldICU+JSBhcy5kYXRhLmZyYW1lKE1lbGIpDQoNCiNDcmVhdGluZyBhIHN1YnNldCBvZiBkYXRhc2V0IHdpdGggU3RhdGlvbiBuYW1lLCBEYXRlLCBNYXggdGVtcGVyYXR1cmUgYW5kIHNvbGFyIGV4cG9zdXJlIGZvciBTeWRuZXkNClN5ZCA8LSBDbGltYXRlX1N5ZFssYygtMywtNCwtNSwtOCldICU+JSBhcy5kYXRhLmZyYW1lKFN5ZCkNCg0KI09uIGludmVzdGlnYXRpbmcgdGhlIGltcG9ydGVkIGRhdGEgaXQgaXMgb2JzZXJ2ZWQgdGhhdCB0aGVyZSBpcyBvbmUgTkEgdmFsdWUgd2hpY2ggY2FuIGFsdGVyIHRoZSByZXN1bHRzIGFuZCBoZW5jZSB3aWxsIGJlIHJlcGxhY2VkIGJ5IG1lYW4gb2YgdGVtcGVyYXR1cmVzIGZvciBTeWRuZXkNClN5ZCRUZW1wZXJhdHVyZSA8LSBpbXB1dGUoU3lkJFRlbXBlcmF0dXJlLCBmdW4gPSBtZWFuKQ0KDQojQ3JlYXRpbmcgYSBzdWJzZXQgb2YgZGF0YXNldCB3aXRoIFN0YXRpb24gbmFtZSwgRGF0ZSwgTWF4IHRlbXBlcmF0dXJlIGFuZCBzb2xhciBleHBvc3VyZSBmb3IgYm90aCBjaXRpZXMNCg0KQ2l0aWVzIDwtIHRhYmxlKENsaW1hdGVfY2l0aWVzJFNvbGFyX2V4cG8sIENsaW1hdGVfY2l0aWVzJFRlbXBlcmF0dXJlKQ0KDQpgYGANCg0KDQojIyBTdW1tYXJ5IFN0YXRpc3RpY3MNCg0KDQpDYWxjdWxhdGUgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyAoaS5lLiwgbWVhbiwgbWVkaWFuLCBzdGFuZGFyZCBkZXZpYXRpb24sIGZpcnN0IGFuZCB0aGlyZCBxdWFydGlsZSwgaW50ZXJxdWFydGlsZSByYW5nZSwgbWluaW11bSBhbmQgbWF4aW11bSB2YWx1ZXMpIG9mIHRoZSBzZWxlY3RlZCB2YXJpYWJsZSBncm91cGVkIGJ5IGNpdHkuDQoNCmBgYHtyfQ0KIyBUaGlzIGlzIGEgY2h1bmsgZm9yIHlvdXIgU3VtbWFyeSBTdGF0aXN0aWNzIHNlY3Rpb24uIA0KDQojU3VtbWFyeSBzdGF0aXN0aWMgb2YgVGVtcGVyYXR1cmUgdmFyaWFibGUgZ3JvdXBlZCBieSBjaXR5IA0KQ2l0eV9UZW1wIDwtIENsaW1hdGVfY2l0aWVzICU+JSBncm91cF9ieShTdGF0aW9uKSAlPiUgc3VtbWFyaXNlKE1pbiA9IG1pbihUZW1wZXJhdHVyZSxuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRMSA9IHF1YW50aWxlKFRlbXBlcmF0dXJlLHByb2JzID0gLjI1LG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1lZGlhbiA9IG1lZGlhbihUZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUTMgPSBxdWFudGlsZShUZW1wZXJhdHVyZSxwcm9icyA9IC43NSxuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYXggPSBtYXgoVGVtcGVyYXR1cmUsbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWVhbiA9IG1lYW4oVGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNEID0gc2QoVGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSBuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1pc3NpbmcgPSBzdW0oaXMubmEoVGVtcGVyYXR1cmUpKSkNCkNpdHlfVGVtcA0KDQojT24gaW52ZXN0aWdhdGluZyB0aGUgc3VtbWFyeSBpdCBpcyBvYnNlcnZlZCB0aGF0IHRoZXJlIGlzIG9uZSBOQSB2YWx1ZSB3aGljaCBjYW4gYWx0ZXIgdGhlIHJlc3VsdHMgYW5kIGhlbmNlIHdpbGwgYmUgcmVwbGFjZWQgYnkgbWVhbiBvZiB0ZW1wZXJhdHVyZXMgZm9yIFN5ZG5leQ0KDQpDbGltYXRlX2NpdGllcyRUZW1wZXJhdHVyZSA8LSBpbXB1dGUoQ2xpbWF0ZV9jaXRpZXMkVGVtcGVyYXR1cmUsIGZ1biA9IG1lYW4pDQoNCiNSZXJ1biB0aGUgc3VtbWFyeSBzdGF0aXN0aWMgYWZ0ZXIgTkEgcmVwbGFjZW1lbnQgd2l0aCBtZWRpYW4NCkNpdHlfVGVtcCA8LSBDbGltYXRlX2NpdGllcyAlPiUgZ3JvdXBfYnkoU3RhdGlvbikgJT4lIHN1bW1hcmlzZShNaW4gPSBtaW4oVGVtcGVyYXR1cmUsbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUTEgPSBxdWFudGlsZShUZW1wZXJhdHVyZSxwcm9icyA9IC4yNSxuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNZWRpYW4gPSBtZWRpYW4oVGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFEzID0gcXVhbnRpbGUoVGVtcGVyYXR1cmUscHJvYnMgPSAuNzUsbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWF4ID0gbWF4KFRlbXBlcmF0dXJlLG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1lYW4gPSBtZWFuKFRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTRCA9IHNkKFRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNaXNzaW5nID0gc3VtKGlzLm5hKFRlbXBlcmF0dXJlKSkpDQojU3VtbWFyeSBzdGF0aXN0aWMgb2YgTWF4LiB0ZW1wZXJhdHVyZSB2YXJpYWJsZXMgZ3JvdXBlZCBieSBjaXR5DQpDaXR5X1RlbXANCkNpdHlfVGVtcF9NZWxiIDwtIENpdHlfVGVtcCAlPiUgZmlsdGVyKENpdHlfVGVtcCRTdGF0aW9uID09ICJNZWxib3VybmUiKQ0KQ2l0eV9UZW1wX1N5ZCA8LSBDaXR5X1RlbXAgJT4lIGZpbHRlcihDaXR5X1RlbXAkU3RhdGlvbiA9PSAiU3lkbmV5IikNCg0KI1N1bW1hcnkgc3RhdGlzdGljIG9mIFNvbGFyIGV4cG9zdXJlIHZhcmlhYmxlIGdyb3VwZWQgYnkgY2l0eSANCkNpdHlfU29sYXJfZXhwbyA8LSBDbGltYXRlX2NpdGllcyAlPiUgZ3JvdXBfYnkoU3RhdGlvbikgJT4lIHN1bW1hcmlzZShNaW4gPSBtaW4oU29sYXJfZXhwbyxuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRMSA9IHF1YW50aWxlKFNvbGFyX2V4cG8scHJvYnMgPSAuMjUsbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWVkaWFuID0gbWVkaWFuKFNvbGFyX2V4cG8sIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFEzID0gcXVhbnRpbGUoU29sYXJfZXhwbyxwcm9icyA9IC43NSxuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYXggPSBtYXgoU29sYXJfZXhwbyxuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNZWFuID0gbWVhbihTb2xhcl9leHBvLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTRCA9IHNkKFNvbGFyX2V4cG8sIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSBuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1pc3NpbmcgPSBzdW0oaXMubmEoU29sYXJfZXhwbykpKQ0KQ2l0eV9Tb2xhcl9leHBvDQpDaXR5X1NvbGFyX01lbGIgPC0gQ2l0eV9Tb2xhcl9leHBvICU+JSBmaWx0ZXIoQ2l0eV9Tb2xhcl9leHBvJFN0YXRpb24gPT0gIk1lbGJvdXJuZSIpDQpDaXR5X1NvbGFyX1N5ZCA8LSBDaXR5X1NvbGFyX2V4cG8gJT4lIGZpbHRlcihDaXR5X1NvbGFyX2V4cG8kU3RhdGlvbiA9PSAiU3lkbmV5IikNCg0KYGBgDQoNCg0KIyMgRGlzdHJpYnV0aW9uIEZpdHRpbmcNCg0KQ29tcGFyZSB0aGUgZW1waXJpY2FsIGRpc3RyaWJ1dGlvbiBvZiBzZWxlY3RlZCB2YXJpYWJsZSB0byBhIG5vcm1hbCBkaXN0cmlidXRpb24gc2VwYXJhdGVseSBpbiBNZWxib3VybmUgYW5kIGluIFN5ZG5leS4gWW91IG5lZWQgdG8gZG8gdGhpcyB2aXN1YWxseSBieSBwbG90dGluZyB0aGUgaGlzdG9ncmFtIHdpdGggbm9ybWFsIGRpc3RyaWJ1dGlvbiBvdmVybGF5LiBTaG93IHlvdXIgY29kZS4NCg0KDQpgYGB7cn0NCiMgVGhpcyBpcyBhIGNodW5rIGZvciB5b3VyIERpc3RyaWJ1dGlvbiBGaXR0aW5nIHNlY3Rpb24uDQoNCiNQbG90dGluZyBoaXN0b2dyYW0gZm9yIENpdHkgdGVtcGVyYXR1cmVzIHRvIG9ic2VydmUgYmVoYXZpb3IvcGF0dGVybiBvZiB0ZW1wZXJhdHVyZXMgYWNyb3NzIGNpdGllcw0KDQpwYXIobWZyb3cgPSBjKDIsIDIpKQ0KI0hpc3RvZ3JhbSB3aXRoIG5vcm1hbCBkaXN0cmlidXRpb24gb3ZlcmxheSBmb3IgTWVsYm91cm5lIHRlbXBlcmF0dXJlIHZhcmlhYmxlDQp4IDwtIHJub3JtKDEwMDAsIG1lYW49IDAsIHNkID0xKQ0KeDE8LXJub3JtKG49Q2l0eV9UZW1wX01lbGIkbixtZWFuID0gQ2l0eV9UZW1wX01lbGIkTWVhbiwgc2QgPSBDaXR5X1RlbXBfTWVsYiRTRCkNCmhpc3QoeDEsIGZyZXE9IEZBTFNFLCB4bGltPWMoMTAsIDUwKSwgYnJlYWtzPTE1KQ0KY3VydmUoZG5vcm0oeCxtZWFuKHgxKSxzZCh4MSkpLCBhZGQ9IFRSVUUpDQphYmxpbmUodj1tZWFuKHgxKSxjb2w9J3JlZCcsbHc9MikNCg0KI0hpc3RvZ3JhbSB3aXRoIG5vcm1hbCBkaXN0cmlidXRpb24gb3ZlcmxheSBmb3IgU3lkbmV5IHRlbXBlcmF0dXJlIHZhcmlhYmxlDQp4Mjwtcm5vcm0obj1DaXR5X1RlbXBfU3lkJG4sbWVhbiA9IENpdHlfVGVtcF9TeWQkTWVhbiwgc2QgPSBDaXR5X1RlbXBfU3lkJFNEKQ0KaGlzdCh4MiwgZnJlcT0gRkFMU0UsIHhsaW09YygxMCwgNTApLGJyZWFrcz0xNSkNCmN1cnZlKGRub3JtKHgsbWVhbih4Miksc2QoeDIpKSwgYWRkPSBUUlVFKQ0KYWJsaW5lKHY9bWVhbih4MiksY29sPSdyZWQnLGx3PTIpDQoNCiNIaXN0b2dyYW0gd2l0aCBub3JtYWwgZGlzdHJpYnV0aW9uIG92ZXJsYXkgZm9yIE1lbGJvdXJuZSBzb2xhciBleHBvc3VyZSB2YXJpYWJsZSkNCngzPC1ybm9ybShuPUNpdHlfU29sYXJfTWVsYiRuLG1lYW4gPSBDaXR5X1NvbGFyX01lbGIkTWVhbiwgc2QgPSBDaXR5X1NvbGFyX01lbGIkU0QpDQpoaXN0KHgzLCBmcmVxPSBGQUxTRSwgeGxpbT1jKDAsIDQwKSxicmVha3M9MTUpDQpjdXJ2ZShkbm9ybSh4LG1lYW4oeDMpLHNkKHgzKSksIGFkZD0gVFJVRSkNCmFibGluZSh2PW1lYW4oeDMpLGNvbD0ncmVkJyxsdz0yKQ0KDQojSGlzdG9ncmFtIHdpdGggbm9ybWFsIGRpc3RyaWJ1dGlvbiBvdmVybGF5IGZvciBTeWRuZXkgc29sYXIgZXhwb3N1cmUgdmFyaWFibGUNCng0PC1ybm9ybShuPUNpdHlfU29sYXJfU3lkJG4sbWVhbiA9IENpdHlfU29sYXJfU3lkJE1lYW4sIHNkID0gQ2l0eV9Tb2xhcl9TeWQkU0QpDQpoaXN0KHg0LCBmcmVxPSBGQUxTRSwgeGxpbT1jKDAsIDQwKSxicmVha3M9MTUpDQpjdXJ2ZShkbm9ybSh4LG1lYW4oeDQpLHNkKHg0KSksIGFkZD0gVFJVRSkNCmFibGluZSh2PW1lYW4oeDQpLGNvbD0ncmVkJyxsdz0yKQ0KDQpgYGANCg0KIyMgSW50ZXJwcmV0YXRpb24NCg0KR29pbmcgYmFjayB0byB5b3VyIHByb2JsZW0gc3RhdGVtZW50LCB3aGF0IGluc2lnaHQgaGFzIGJlZW4gZ2FpbmVkIGZyb20gdGhlIGludmVzdGlnYXRpb24/IA0KDQpBZnRlciBwbG90dGluZyB0aGUgcmVzcGVjdGl2ZSB2YXJpYWJsZXMgaGlzdG9ncmFtcyBhbG9uZyB3aXRoIG5vcm1hbCBkaXN0cmlidXRpb24gY3VydmVzIGFuZCBhbmFseXppbmcgZW1waXJpY2FsIGRhdGEsIGZvbGxvd2luZyBjYW4gYmUgaW5mZXJyZWQsIGZvciB0aGUgbW9udGhzIG9mIERlYy0yMiB0byBGZWItMjMNCg0KMSkgTWVsYm91cm5lIHRlbXBlcmF0dXJlcw0KVGhlIG1lbGJvdXJuZSBtYXguIHRlbXBlcmF0dXJlcyBhcmUgZ2VuZXJhbGx5IG1vcmUgc3ByZWFkIG9yIHVuZXZlbmx5IGRpc3RyaWJ1dGVkLiBUaGVyZSBhcmUgbW9yZSB2YXJpYXRpb25zIGluIGRhaWx5IG1heC4gdGVtcGVyYXVyZSB3aGljaCBpcyByZWZsZWN0ZWQgYnkgZGVuc2l0eSBwbG90Lg0KDQoyKSBTeWRuZXkgdGVtcGVyYXR1cmVzDQpXaGVuIGNvbXBhcmVkIHRvIE1lbGJvdXJuZSB0ZW1wZXJhdHVyZXMsIFN5ZG5leSB0ZW1wZXJhdHVyZXMgYXJlIG1vcmUgZXZlbmx5IGRpc3RyaWJ1dGVkLiBUaGVyZSBhcmUgbGVzcyB2YXJpYXRpb25zLCB3aGljaCBpcyBhbHNvIHJlZmxlY3RlZCBpbiBoaWdoIGRlbnNpdHkgcGxvdC4gDQoNCkFsc28sIGRpZmZlcmVuY2UsIGJldHdlZW4gbWluIGFuZCBtYXguIHRlbXBlcmF0dXJlcyBpcyBsZXNzIGZvciBTeWRuZXkgdGhhbiBNZWxib3VybmUgZGFpbHkgdGVtcGVyYXR1cmVzLg0KDQozKSBNZWxib3VybmUgU29sYXIgZXhwb3N1cmUNClNvbGFyIGV4cG9zdXJlIGluIE1lbGJvdXJuZSBjYXNlIHNlZW1zIHRvIGJlIGV2ZW5seSBkaXN0cmlidXRlZCBhY3Jvc3Mgbm9ybWFsIGRpc3RyaWJ1dGlvbiBjdXJ2ZSBpbmRpY2F0aW5nIHVuaWZvcm0gZGlzdHJpYnV0aW9uLiANCg0KNCkgU3lkbmV5IFNvbGFyIGV4cG9zdXJlDQpTb2xhciBleHBvc3VyZSBpbiBTeWRuZXkgc2VlbXMgdG8gYmUgbW9yZSB1bmlmb3JtIGFjcm9zcyBub3JtYWwgZGlzdHJpYnV0aW9uIGN1cnZlIGluZGljYXRpbmcgbW9yZSBjb25zaXN0ZW5jeS9sZXNzIHdlYXRoZXIgcHJlZGljdGFiaWxpdHkuIE9uIGNvbXBhcmlzb24gYmV0d2VlbiBzb2xhciBleHBvc3VyZSBvZiBib3RoIGNpdGllcyBNZWxib3VybmUgYW5kIFN5ZG5leSwgdGhlcmUgZG9lc24ndCBzZWVtcyB0byBiZSBtb3JlIGRpZmZlcmVuY2UgYW5kIGRpc3RyaWJ1dGlvbi4gVGhpcyBpcyBhbHNvIGluZGljYXRlZCBieSBzaW1pbGFyIE1lYW4gIHZhbHVlcy4gSG93ZXZlciwgdGhlcmUgYXJlIGRheXMgd2hpY2ggaGF2ZSBtb3JlIHNvbGFyIGV4cG9zdXJlIHRoYW4gcmVtYWluaW5nIGRheXMsIGluIGNhc2Ugb2YgTWVsYm91cm5lIHRoYW4gU3lkbmV5IHdoaWNoIGlzIGFsc28gcmVmbGVjdGVkIGJ5IE1lZGlhbiB2YWx1ZXMgb2Ygc29sYXIgZXhwb3N1cmUgb2YgYm90aCBjaXRpZXMu