Use daily climate station time series from DWD, downloaded here: https://opendata.dwd.de/climate_environment/CDC/observations_germany/climate/daily/kl/historical/

Chose stations - No 3289 Schmierits-Weltwitz (01.10.1972 - current) near SESO - Data missing - start analysis ti fit Hai, which only starts in 2005

filename = "tageswerte_KL_03289_19721001_20221231_hist/produkt_klima_tag_19721001_20221231_03289.txt" # Schmierits-Weltwitz
There were 28 warnings (use warnings() to see them)

Check which period is covered, whether years are complete


data$date <- as.Date(as.character(data$MESS_DATUM),format='%Y%m%d')
years <- as.numeric(unique(format(data$date,'%Y')))

data$year <- format(data$date,'%Y')
data$month <- format(data$date,'%m')
data$daymonth <- format(data$date,'%d%m')
data$day <- format(data$date,'%d')

(days_per_year <- rle(data$year))
Run Length Encoding
  lengths: int [1:49] 92 365 365 365 366 365 365 365 366 365 ...
  values : chr [1:49] "1972" "1973" "1974" "1975" "1976" "1977" "1978" "1979" "1980" "1981" "1982" "1983" "1984" ...

Select only a subset of years: 2005 - 2021 (will yields 16 hydrological years) which is aligned with the data availability of Hainich. Incidentally, it covers 2014-2021 (8 years), and the preceding 8 years.

data = subset(data, ((year >= 2005) & (year<= 2021)))
years <- as.numeric(unique(format(data$date,'%Y')))
(nyears = length(years))
[1] 17
(days_per_year <- rle(data$year))
Run Length Encoding
  lengths: int [1:17] 365 365 365 366 365 365 365 366 365 365 ...
  values : chr [1:17] "2005" "2006" "2007" "2008" "2009" "2010" "2011" "2012" "2013" "2014" "2015" "2016" "2017" ...
days_per_year[[1]]
 [1] 365 365 365 366 365 365 365 366 365 365 365 366 365 365 365 366 365

Selected years are complete.

remove Feb 29

ind_feb29<-which(as.character(data$date,'%d%m') == c("2902"))
data<-data[-ind_feb29,]

Check whether there are any missing data that need to be taken care of.

(a <- which(data$TMK == -999)) # daily mean temp, 
integer(0)
(a <- which(data$TXK == -999)) # daily max temp, 
integer(0)
(a <- which(data$TNK == -999)) # daily min temp, 
integer(0)
#(data$date[a])

(b <- which(data$RSK == -999)) # daily precipitation
[1] 5334
(data$date[b]) # need to check surrounging stations, e.g. Stadtroda For now take as zero
[1] "2019-08-09"
data$RSK[b] <- 0

Data for temperature is complete. Missing precipitation in August 2019. Need to double check. For now set to zero.

Add a column indicating the daily difference between minimum and maximum temperature. This is a measure for the potential evapotranspiration.

data$DeltaT <- data$TXK - data$TMK

Calculation of the hydrological variables

Potential ET

Calculation, taking the equation of Hargreaves-Samani (1985), see review by Hargreaves and Allen (2003). This takes a bit.

library(sirad)

a <- extrat(dayOfYear(data$date), Lat_data) # calculate extraterrestrial radiation for the specific day and latitude
data$Ra <- a[[1]]
data$lEpot <- 0.0023 * data$Ra * (data$TMK + 17.8) * sqrt(data$DeltaT) # calculate potential latent heat flux in MJ/m2d
data$Epot <- (data$lEpot/2.5e6)*1e6# calculate potential ET in mm/d assume latent heat of evaporation l = 2.5e6 J/kg and density of water of 1000 kg/m3

Atmospheric water deficit

The water deficit can either be calculated over each the hydrological year (October - September) separately or over the entire period.

over each hydrological year separately
hydro.startyear = years[1]
hydro.endyear = years[length(years)]

hydro.startdate = as.Date(paste(hydro.startyear,"10","01", sep="-"), "%Y-%m-%d")
hydro.enddate = as.Date(paste(hydro.endyear,"09","30", sep="-"), "%Y-%m-%d")

#hydro.startdate = as.POSIXlt(paste(hydro.startyear,"10","01", sep="-"), "%Y-%m-%d")
#hydro.enddate = as.POSIXlt(paste(hydro.endyear,"09","30", sep="-"), "%Y-%m-%d")

h.data <- subset.data.frame(data, (date >= hydro.startdate & date <= hydro.enddate))
h.data$def <- NA


for (year in years[1:length(years)-1]) {
        startday = as.Date(paste(year,"10","01", sep="-"), "%Y-%m-%d")
        endday = as.Date(paste(year+1,"09","30", sep="-"), "%Y-%m-%d")
        ind.thisyear <- which(h.data$date >= startday & h.data$date <= endday)
        h.data$def[ind.thisyear] <- cumsum(h.data$RSK[ind.thisyear]-h.data$Epot[ind.thisyear]) 

}

Basic features of the temperature dataset

Check whether the distribution of rainfall and other variables changed between

Since the time series of SESO is a bit shorter (2016-2021), create an alterative subset, to be able to look only at some of the analysis for this smaller range.

For orientation plot the dayliy climatology over the entire timeseries, 2005-2022

# subset for periods
data_2014_2017 <- data[which(data$year>=2014 & data$year<=2017),] 
data_2018_2021 <- data[which(data$year>=2018 & data$year<=2021),] 

data_2016_2018 <- data[which(data$year>=2016 & data$year<=2018),] 
data_2019_2021 <- data[which(data$year>=2019 & data$year<=2021),] 



# climatology over the entire time series
T.clim <- aggregate(TMK ~ day+month, data = data, FUN = mean)
plot(T.clim$TMK, ylim = c(-7, 28),
     xlab = "Doy of year",
     ylab = "Average daily temperature in deg C")

# averge over periods
T.clim.2014_2017 <- aggregate(TMK ~ day+month, data = data_2014_2017, FUN = mean)
points(T.clim.2014_2017$TMK, col="blue")

# 2018-2021
T.clim.2018_2021 <-aggregate(TMK ~ day+month, data = data_2018_2021, FUN = mean)
points(T.clim.2018_2021$TMK, col="red")
legend(x = "topleft",          # Position
       legend = c("clim", "2014-2017", "2018-2021"),  # Legend texts
       pch = c(1,1,1), # point type
       col = c("black", "blue", "red")) # point colors



plot(T.clim$TMK-T.clim.2014_2017$TMK, col="blue",
     xlab=c("Day of year"),
     ylab = "Temperature anomaly in degC")
points(T.clim$TMK-T.clim.2018_2021$TMK, col = "red")
legend(x = "topleft",          # Position
       legend = c("2014-2017", "2018-2021"),  # Legend texts
       pch = c(1,1), # point type
       col = c("blue", "red")) # point colors



par(mfrow=c(1,2))

bins = seq(-6,6,1)
hist(T.clim.2014_2017$TMK-T.clim$TMK,
     xlab = "Deviation in temperature from climatology",
     main = "2014-2018",
     breaks = bins)
hist(T.clim.2018_2021$TMK-T.clim$TMK,
     xlab = "Deviation in temperature from climatology",
     main = "2018-2021",
     breaks = bins)

(quantile(T.clim.2014_2017$TMK-T.clim$TMK, c(0.1,0.5,0.9)))
       10%        50%        90% 
-1.7426471  0.4970588  2.4404412 
(quantile(T.clim.2018_2021$TMK-T.clim$TMK, c(0.1,0.5,0.9)))
      10%       50%       90% 
-1.336029  0.425000  2.625735 
# temperature anomalies
data$Tclim <- NA
ind <- which(data$year>years[1])
data$Tclim[ind] <- rep(T.clim$TMK,length(ind)/365) 
number of items to replace is not a multiple of replacement length
data$Tano <- data$TMK - data$Tclim

plot(data$date,data$Tano,
     xlab = "Date",
     ylab = "Temperature anomalies in degC")

boxplot(Tano ~ year, data=data,
        xlab = "Year",
        ylab = "Temperature anomalies in degC")


lm.Tanom <- lm(Tano ~ as.numeric(year), data = data)
summary(lm.Tanom)

Call:
lm(formula = Tano ~ as.numeric(year), data = data)

Residuals:
     Min       1Q   Median       3Q      Max 
-18.5489  -2.7984   0.0051   2.7944  12.3997 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)      -117.16155   23.14910  -5.061 4.29e-07 ***
as.numeric(year)    0.05821    0.01150   5.063 4.26e-07 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 4.051 on 5842 degrees of freedom
  (365 observations deleted due to missingness)
Multiple R-squared:  0.004368,  Adjusted R-squared:  0.004198 
F-statistic: 25.63 on 1 and 5842 DF,  p-value: 4.261e-07

Both periods were warmer than the entire reference periods from 2005-2022, while 2018-2021 was overall roughly 0.05 degree warmer than the previous 2014-2017 period. There are no strong effects in temperature per se. ALso the anomalies are slightly increasing with time by 0.06 degree per year.

Difference in the daily temperature indicating cloudiness.

(delta_T = T_max - T_min)

DeltaT.clim <- aggregate(DeltaT ~ day+month, data = data, FUN = mean)
plot(DeltaT.clim$DeltaT, ylim = c(1,10))

# averge over periods 2014-2017
DeltaT.clim.2014_2017 <- aggregate(DeltaT ~ day+month, data = data_2014_2017, FUN = mean)
points(DeltaT.clim.2014_2017$DeltaT, col="blue")

# averge over periods 2018-2021
DeltaT.clim.2018_2021 <- aggregate(DeltaT ~ day+month, data = data_2018_2021, FUN = mean)
points(DeltaT.clim.2018_2021$DeltaT, col="red")



# averge over periods 2016-2018
DeltaT.clim.2016_2018 <- aggregate(DeltaT ~ day+month, data = data_2016_2018, FUN = mean)
#points(DeltaT.clim.2016_2018$DeltaT, col="blue")

# averge over periods 2019-2021
DeltaT.clim.2019_2021 <- aggregate(DeltaT ~ day+month, data = data_2019_2021, FUN = mean)
#points(DeltaT.clim.2019_2021$DeltaT, col="red")

bins = seq(0.5,10,0.25)

h.DeltaT_daily.clim <- hist(DeltaT.clim$DeltaT, breaks = bins, plot = FALSE)
h.DeltaT_daily.2014_2017 <- hist(DeltaT.clim.2014_2017$DeltaT, breaks = bins, plot = FALSE)
h.DeltaT_daily.2018_2021 <- hist(DeltaT.clim.2018_2021$DeltaT, breaks = bins, plot = FALSE)
h.DeltaT_daily.2016_2018 <- hist(DeltaT.clim.2016_2018$DeltaT, breaks = bins, plot = FALSE)
h.DeltaT_daily.2019_2021 <- hist(DeltaT.clim.2019_2021$DeltaT, breaks = bins, plot = FALSE)




plot(h.DeltaT_daily.clim$mids, cumsum(h.DeltaT_daily.clim$density)/4, 
     xlab = "Daily temperature difference, degC",
     ylab = "cumulative frequency")
points(h.DeltaT_daily.2014_2017$mids, cumsum(h.DeltaT_daily.2014_2017$density)/4, 
       pch = 19, col = "blue")
points(h.DeltaT_daily.2018_2021$mids, cumsum(h.DeltaT_daily.2018_2021$density)/4, 
       pch = 19, col = "red")
legend(x = "bottomright",          # Position
       legend = c("clim", "2014-2017", "2018-2021"),  # Legend texts
       pch = c(1, 19, 19), # point types
       col = c("black", "blue", "red"), # point colors
       )           



plot(h.DeltaT_daily.clim$mids, cumsum(h.DeltaT_daily.clim$density)/4, 
     xlab = "Daily temperature difference, degC",
     ylab = "cumulative frequency")
points(h.DeltaT_daily.2016_2018$mids, cumsum(h.DeltaT_daily.2016_2018$density)/4, 
       pch = 19, col = "blue")
points(h.DeltaT_daily.2019_2021$mids, cumsum(h.DeltaT_daily.2019_2021$density)/4, 
       pch = 19, col = "red")
legend(x = "bottomright",          # Position
       legend = c("clim", "2016-2018", "2019-2021"),  # Legend texts
       pch = c(1, 19, 19), # point types
       col = c("black", "blue", "red"), # point colors
       )           



#hist(DeltaT.clim.2014_2017$DeltaT-DeltaT.clim$DeltaT)

#hist(DeltaT.clim.2018_2021$DeltaT-DeltaT.clim$DeltaT)

deltaT <- as.data.frame(cbind(h.DeltaT_daily.clim$mids, cumsum(h.DeltaT_daily.clim$density)/4, cumsum(h.DeltaT_daily.2014_2017$density)/4, cumsum(h.DeltaT_daily.2018_2021$density)/4))
colnames(deltaT) <- c("delta_T", "freq_2005_2021", "freq_2014_2017", "freq_2018_2021")

write.csv(deltaT, file="daltaT_15yrs_3289.csv")

The difference between minumum and maxumim temperature increases in both periods, esply in times were temperature differences are high (in summer). Thus in general the variation in temperature at a daily scale has increased, indicating an increase in sunshine hours and decrease in cloudiness.

Potential Evapotranspiration, daily


Epot.clim <- aggregate(Epot ~ day+month, data = data, FUN = mean)
plot(Epot.clim$Epot, ylim = c(0,5),
     xlab = "Day of year",
     ylab = "Potential evapotranspiration in mm/day")
legend(x = "topright",          # Position
       legend = c("clim", "2014-2017", "2018-2021"),  # Legend texts
        pch = c(1, 1, 1), # point types
        col = c("black", "blue", "red")) # point colors


# averge over periods
Epot.clim.2014_2017 <- aggregate(Epot ~ day+month, data = data_2014_2017, FUN = mean)
points(Epot.clim.2014_2017$Epot, col="blue")

# averge over periods
Epot.clim.2018_2021 <- aggregate(Epot ~ day+month, data = data_2018_2021, FUN = mean)
points(Epot.clim.2018_2021$Epot, col="red")


bins = seq(0,5,0.1)

h.Epot_daily.clim <- hist(Epot.clim$Epot, breaks = bins, plot = FALSE)
h.Epot_daily.2014_2017 <- hist(Epot.clim.2014_2017$Epot, breaks = bins, plot = FALSE)
h.Epot_daily.2018_2021 <- hist(Epot.clim.2018_2021$Epot, breaks = bins, plot = FALSE)

plot(h.Epot_daily.clim$mids, cumsum(h.Epot_daily.clim$density)/10, 
     xlab = "Daily potential evapotranspiration, mm/d",
     ylab = "cumulative frequency")
points(h.Epot_daily.2014_2017$mids, cumsum(h.Epot_daily.2014_2017$density)/10, 
       pch = 19, col = "blue")
points(h.Epot_daily.2018_2021$mids, cumsum(h.Epot_daily.2018_2021$density)/10, 
       pch = 19, col = "red")
legend(x = "bottomright",          # Position
       legend = c("clim", "2014-2017", "2018-2021"),  # Legend texts
       pch = c(1, 19, 19), # point types
       col = c("black", "blue", "red"), # point colors
       )           

At the daily scale, the potential evapotranspiration has slightly increased especially in summer.

Potential evapotranspiration, precipitation weekly

library(tidyr)
package 'tidyr' was built under R version 4.0.5
# Aggregate to weekly data as 5 daily averages perform better than daily 
data$date <- as.POSIXlt(data$date)
data.w.Epot <- aggregate(data$Epot ~ format(date,"%Y-%W"), data=data, FUN = mean) # weekly data
names(data.w.Epot)[1:2] = c("date", "Epot")
data.w.Epot<-data.w.Epot %>% separate(date, c("year","week")) # tidyr

# subset for periods once more
data.w.Epot_2014_2017 <- data.w.Epot[which(data.w.Epot$year>=2014 & data.w.Epot$year<=2017),] 
data.w.Epot_2018_2021 <- data.w.Epot[which(data.w.Epot$year>=2018 & data.w.Epot$year<=2021),] 

Epot.clim <- aggregate(Epot ~ week, data = data.w.Epot, FUN = mean) # weekly climatology

Epot.clim.2014_2017 <- aggregate(Epot ~ week, data = data.w.Epot_2014_2017, FUN = mean) # weekly climatology 2014-2017
Epot.clim.2018_2021 <- aggregate(Epot ~ week, data = data.w.Epot_2018_2021, FUN = mean) # weekly climatology 2018-2021

plot(Epot.clim$Epot,
     xlab = "Calendar week",
     ylab = "Average PET in mm/d")
points(Epot.clim.2014_2017$Epot, 
       pch = 19, col = "blue")
points(Epot.clim.2018_2021$Epot, 
       pch = 19, col = "red")
legend(x = "topleft",          # Position
       legend = c("clim", "2014-2017", "2018-2021"),  # Legend texts
       pch = c(1, 19, 19), # point types
       col = c("black", "blue", "red"), # point colors
       )           



plot(cumsum(Epot.clim$Epot*7),
     xlab = "Calendar week",
     ylab = "Cumulated PET in mm")
points(cumsum(Epot.clim.2014_2017$Epot*7), 
       pch = 19, col = "blue")
points(cumsum(Epot.clim.2018_2021$Epot*7), 
       pch = 19, col = "red")
legend(x = "bottomright",          # Position
       legend = c("clim", "2014-2017", "2018-2021"),  # Legend texts
       pch = c(1, 19, 19), # point types
       col = c("black", "blue", "red"), # point colors
       ) 

NA
NA
NA

This gives the cumulative potential evapotranspiration, which has slightly increased in the second period compared to the first. The first is similar to the climatology.

Monthly precipitation and potential evapotranspiration


prec.monthly <- aggregate(RSK ~ month+year, data = data, FUN = sum)
clim.prec.monthly <- aggregate(RSK ~ month, data = prec.monthly, FUN = mean)
plot(clim.prec.monthly,
     ylim = c(0,150),
     type = "l",
     ylab = "Monthly flux, mm")

# period 2014-2017
prec.monthly.2014_2017 <- aggregate(RSK ~ month+year, data = data_2014_2017, FUN = sum)
clim.prec.monthly.2014_2017 <- aggregate(RSK ~ month, data = prec.monthly.2014_2017, FUN = mean)
lines(clim.prec.monthly.2014_2017,
     type = "l",
     col = "blue")

# period 2018-2021
prec.monthly.2018_2021 <- aggregate(RSK ~ month+year, data = data_2018_2021, FUN = sum)
clim.prec.monthly.2018_2021 <- aggregate(RSK ~ month, data = prec.monthly.2018_2021, FUN = mean)
lines(clim.prec.monthly.2018_2021,
     type = "l",
     col = "red")


# all years
Epot.monthly <- aggregate(Epot ~ month+year, data = data, FUN = sum)
clim.Epot.monthly <- aggregate(Epot ~ month, data = Epot.monthly, FUN = mean)

# period 2014-2017
Epot.monthly.2014_2017 <- aggregate(Epot ~ month+year, data = data_2014_2017, FUN = sum)
clim.Epot.monthly.2014_2017 <- aggregate(Epot ~ month, data = Epot.monthly.2014_2017, FUN = mean)

# period 2018-2021
Epot.monthly.2018_2021 <- aggregate(Epot ~ month+year, data = data_2018_2021, FUN = sum)
clim.Epot.monthly.2018_2021 <- aggregate(Epot ~ month, data = Epot.monthly.2018_2021, FUN = mean)

lines(clim.Epot.monthly,
     type = "l",
     lty = "dashed")
lines(clim.Epot.monthly.2014_2017,
     type = "l",
     col="blue",
     lty = "dashed")
lines(clim.Epot.monthly.2018_2021,
     type = "l",
     col="red",
     lty = "dashed")

legend(x = "topleft",          # Position
       legend = c("precipitation","Epot", "all", "2014-2017", "2018-2021"),  # Legend texts
       lty = c("solid", "dashed", "solid", "solid","solid"), # point types
       col = c("black", "black", "black", "blue", "red"), # point colors
       ) 

Precipitation varies more between the focus periods than potential evaporation.

Water balance, per hydrological year

water deficit = precipitation - potential evaporation

plot(h.data$date, h.data$def, 
#     ylim = c(-200,250),
     xlab = "Date",
     ylab = "P - PET since Oct 1 each year")

In this plot, all hydrological years are considered separately. The water deficit is set to zero at the beginning of each hydrological year (corresponds to the end of the vegetation period) at Oct 1.

We see that the variation within the years increased with time.


def.yearly.mat <- matrix(h.data$def, nrow=365, ncol=length(years)-1 )
h.years = years[-1]

def.min.year <- apply(def.yearly.mat,2,min)
def.max.year <- apply(def.yearly.mat,2,max)
def.range.year <- def.max.year - def.min.year
def.sd.year <- apply(def.yearly.mat,2,sd)  
def.mean.year <- apply(def.yearly.mat,2,mean)


plot(years[1:length(years)-1], def.range.year,
     ylab=c("Range of water availability"),
     xlab=c("Calendar year"))    


ind.2014_2021 = c(10:17)

lm.def.range <- lm(def.range.year ~ years[2:length(years)])
(summary(lm.def.range))

Call:
lm(formula = def.range.year ~ years[2:length(years)])

Residuals:
   Min     1Q Median     3Q    Max 
-95.92 -35.84 -12.64  51.49 137.85 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)
(Intercept)            2293.103   7661.781   0.299    0.769
years[2:length(years)]   -1.033      3.805  -0.271    0.790

Residual standard error: 70.16 on 14 degrees of freedom
Multiple R-squared:  0.005234,  Adjusted R-squared:  -0.06582 
F-statistic: 0.07366 on 1 and 14 DF,  p-value: 0.79
lm.def.sd <- lm(def.sd.year ~ years[2:length(years)])
(summary(lm.def.sd))

Call:
lm(formula = def.sd.year ~ years[2:length(years)])

Residuals:
    Min      1Q  Median      3Q     Max 
-25.337 -15.246  -6.222  11.149  43.015 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)
(Intercept)             265.6458  2381.2035   0.112    0.913
years[2:length(years)]   -0.1044     1.1826  -0.088    0.931

Residual standard error: 21.81 on 14 degrees of freedom
Multiple R-squared:  0.0005562, Adjusted R-squared:  -0.07083 
F-statistic: 0.007791 on 1 and 14 DF,  p-value: 0.9309
#plot(years[1:length(years)-1], def.sd.year,
#     ylab="variation of water availability",
#     xlab="calendar year")    

#plot(years[1:length(years)-1], def.mean.year,
#     ylab=c("mean annual water deficit"),
#     xlab=c("calendar year"))    

#plot(years[1:length(years)-1], def.min.year,
#     ylab=c("minimum water availability"),
#     xlab=c("calendar year"))


#plot(years[1:length(years)-1], def.max.year, 
#     ylab=c("maximum water availability"),
#     xlab=c("calendar year"))

This plot shows the difference between the yearly maximum surplus and minimum water deficit, called “range in water deficit” (positive values of water deficit are surplus). The range decreases significantly in the recent years.

clim.def <- apply(def.yearly.mat,1,mean)

c2014_2017 <- which(h.years>=2014 & h.years<=2017)
c2018_2021 <- which(h.years>=2018 & h.years<=2021)

h.clim.date = h.data$date[1:365]
clim.def.mean.2014_2017 <- apply(def.yearly.mat[,c2014_2017],1,mean)
clim.def.min.2014_2017 <- apply(def.yearly.mat[,c2014_2017],1,min)
clim.def.max.2014_2017 <- apply(def.yearly.mat[,c2014_2017],1,max)

clim.def.mean.2018_2021 <- apply(def.yearly.mat[,c2018_2021],1,mean)
clim.def.max.2018_2021 <- apply(def.yearly.mat[,c2018_2021],1,max)
clim.def.min.2018_2021 <- apply(def.yearly.mat[,c2018_2021],1,min)


plot(h.clim.date, clim.def,
     ylim = c(-100, 100),
     xlab = "Date",
     ylab = "Water deficit/surplus = P-PET in mm")
points(h.clim.date, clim.def.mean.2014_2017,
       col="blue")
points(h.clim.date, clim.def.mean.2018_2021,
       col="red")
legend(x = "topleft",          # Position
       legend = c("clim", "2014-2017", "2018-2021"),  # Legend texts
       pch = c(1, 19, 19), # point types
       col = c("black", "blue", "red"), # point colors
       )

NA
NA

When aggreagating over the two periods, we see the general dynamics. There is a surplus of water in the winter, because ET is low, and a slight decrease in summer, when ET is larger, but also P increases. The averge multiannual surplus is 264 mm/year! The most striking difference between the first and second period is that the met water balance in 2014-2017 was above average (353 mm).

#plot(h.clim.date, clim.def,
#     ylim = c(-100, 150),
#     xlab = "date",
#     ylab = "water deficit in P-PET in mm",
#     type = "l")
#polygon(c(h.clim.date), rev(h.clim.date), 
#          c(clim.def.max.2014_2017, rev(clim.def.min.2014_2017)),
#        col = "#6BD7AF")

days = c(1:365)
daysmonth = c(31,30,31,31,28,31,30,31,30,31,31,30)
months = c("Oct","Nov","Dec","Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep")
axisticks = c(31/2,cumsum(daysmonth[1:11]) + daysmonth[2:12]/2)

plot(days, clim.def,
    xaxt = "n" ,
    ylim = c(-200, 400),
    xlim = c(0,365),
     xlab = "Date",
     ylab = "Water deficit in P-PET in mm",
     type = "l")
axis(1,at = axisticks, labels = months)
polygon(c(days, rev(days)), 
          c(clim.def.max.2014_2017, rev(clim.def.min.2014_2017)),
        col = "#AED6F1AA")
polygon(c(days, rev(days)), 
          c(clim.def.max.2018_2021, rev(clim.def.min.2018_2021)),
        col = "#F5B7B1AA")

Same plot as above, shading the between maximum and minimum of the periods: Blue is 2014-2017, red is 2018-2021.


Epot.yearly.mat <- matrix(h.data$Epot, nrow=365, ncol=length(years)-1 )
P.yearly.mat <- matrix(h.data$RSK, nrow=365, ncol=length(years)-1 )

Epot.yearly <- apply(Epot.yearly.mat,2,sum)
P.yearly <- apply(P.yearly.mat,2,sum)

(mean(Epot.yearly))
[1] 675.0327
(mean(P.yearly))
[1] 665.9937
plot(h.years, P.yearly,
     pch = 19,
     xlab = "Hydrological year 2015/16 - 2021/22",
     ylim = c(0,900),
     ylab = "Flux in mm / hydrological year")
points(h.years, Epot.yearly,
       pch = 19,
       col = "red")
legend(x="topright",
       legend = c("precip", "Epot"),
       pch = c(1, 1),
       col = c("black", "red"))

       

lm.P <- lm(P.yearly ~ h.years)
(summary(lm.P))

Call:
lm(formula = P.yearly ~ h.years)

Residuals:
     Min       1Q   Median       3Q      Max 
-184.190  -72.007   -7.682   73.639  191.949 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept) 15023.729  12721.873   1.181    0.257
h.years        -7.131      6.318  -1.129    0.278

Residual standard error: 116.5 on 14 degrees of freedom
Multiple R-squared:  0.08339,   Adjusted R-squared:  0.01792 
F-statistic: 1.274 on 1 and 14 DF,  p-value: 0.278
lm.Epot <- lm(Epot.yearly ~ h.years)
(summary(lm.Epot))

Call:
lm(formula = Epot.yearly ~ h.years)

Residuals:
    Min      1Q  Median      3Q     Max 
-55.072  -9.141   4.969  22.300  35.472 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept) -5117.087   3197.800  -1.600   0.1319  
h.years         2.877      1.588   1.811   0.0916 .
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 29.28 on 14 degrees of freedom
Multiple R-squared:  0.1899,    Adjusted R-squared:  0.132 
F-statistic: 3.281 on 1 and 14 DF,  p-value: 0.0916
table_3289 <- c(h.years,  P.yearly, Epot.yearly)
write.csv(table_3289, file="P_PET_30yrs_3289.csv")

Annual PET significantly increases by 1.6 mm / year (due both the average temperature increase, and increase in daily temperature range). The average was 662 mm. Precipitation is more variable throughout the period 1992-2022. The average was 672 mm, no significant changes.

def.yearly <- P.yearly - Epot.yearly
plot(h.years, def.yearly,
    xlab = "Hydrological year 1991/2 - 2021/22",
    ylab = "Water deficit or surplus in mm / hydrological year",
    main = "No 3289 Schmieritz-Weltwitz")


lm.def.yearly <- lm(def.yearly ~ h.years)
(summary(lm.def.yearly))

Call:
lm(formula = def.yearly ~ h.years)

Residuals:
     Min       1Q   Median       3Q      Max 
-207.856  -86.016   -9.599   66.005  236.317 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept) 20140.817  14693.334   1.371    0.192
h.years       -10.007      7.297  -1.371    0.192

Residual standard error: 134.6 on 14 degrees of freedom
Multiple R-squared:  0.1184,    Adjusted R-squared:  0.05545 
F-statistic: 1.881 on 1 and 14 DF,  p-value: 0.1918

Also the difference of the two (which is the meteorological surplus when positive or water deficit when negative) also decreases significantly by 5.6 mm/year.

plot(P.yearly, Epot.yearly,
     xlab = "Annual precipitation in mm / hydrological year",
     ylab = "Annual PET in mm / hydrological year")


lm.Epot.P <- lm(P.yearly ~ Epot.yearly)
summary(lm.Epot.P)

Call:
lm(formula = P.yearly ~ Epot.yearly)

Residuals:
     Min       1Q   Median       3Q      Max 
-163.578  -53.982   -0.215   24.785  237.514 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept) 2155.4621   545.3838   3.952  0.00145 **
Epot.yearly   -2.2065     0.8071  -2.734  0.01615 * 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 98.26 on 14 degrees of freedom
Multiple R-squared:  0.348, Adjusted R-squared:  0.3015 
F-statistic: 7.474 on 1 and 14 DF,  p-value: 0.01615

There is a significant relation between potential evapotranspiration and precipitation (calculated over the hydrological year). The peak of the precipitation is in summer. Hence, when precipitation is high, probably cloudiness is high and temperatures lower. In contrast, when precipitation is low, raindays less, sunshine hours increased, also the potential evaporation is high. T

Multiannual cumulative water deficit

Multiannual water deficit, starting the water balance in Octber 2005 and NOT resetting each year. The negative numbers can be intepreted as the water storage in the subsurface that would be required to compensate for the lack of precipitation.

h.data$cumdef <- cumsum(h.data$RSK - h.data$Epot) # longterm cumulated water deficit

plot(h.data$date, h.data$cumdef, 
#     ylim = c(-200,250),
     xlab = "Date",
     ylab = "P - PET since Oct 1 1991 in mm",
     main = "No 3289 Schmieritz-Weltwitz")

Here we are looking at the surplus building up over several years than disappearing again.


h.data$cumEpot <- cumsum(h.data$Epot) # longterm cumulated water deficit


plot(h.data$date, cumsum(h.data$RSK), 
     ylim = c(0,25000),
     xlab = "Date",
     ylab = "Cumulared flux since Oct 1 2005 in mm")
points(h.data$date, cumsum(h.data$Epot), 
#     ylim = c(-200,250),
     xlab = "date",
     col = "red")
legend(x = "topleft",          # Position
       legend = c("precipitation", "Epot"),  # Legend texts
       pch = c(1, 1),
       col = c("black", "red")
       ) # point colors

NA
NA

QQplot.

write.csv(Table_QP, "Table_QP_3289.csv")
There were 50 or more warnings (use warnings() to see the first 50)

Number of days with given rainfall

Check whether certain types of daily precipitation were more or less common along the time series. For this I use the entire time series, to be able to see trends (if applicable).

I will test for

Looking for extreme rainfall requires a dataset in hourly or six hourly resolution, and cannot be done using this daily dataset. But the data is available from DWD.

# intialize
ndays = array(data=NA,dim = nyears, dimnames = NULL)
noraindays = array(data=NA,dim = nyears, dimnames = NULL)
strongraindays = array(data=NA,dim = nyears, dimnames = NULL)
P = array(data=NA,dim = nyears, dimnames = NULL)
P_strong = array(data=NA,dim = nyears, dimnames = NULL)

P_thresh = 5

#i=1
for (i in 1:nyears) {
data_yr = subset(data, format(data$date,'%Y') == as.character(years[i]))
noraindays[i] = length(which(data_yr$RSK<0.1))
raindays = nrow(data_yr)-noraindays
strongraindays[i] = length(which(data_yr$RSK>P_thresh ))
P[i] <- sum(data_yr$RSK)
P_strong[i] <- sum(data_yr$RSK[which(data_yr$RSK>P_thresh )])
ndays[i] = nrow(data_yr)

}

Annual precipitation time series


par(mfrow=c(1,3))
plot(years, P,
     ylab = "annual precpitation in mm/a",
     main = "all days")

plot(years, P-P_strong,
     ylab = "annual precpitation < 5 mm in mm/a",
     main = "small precipitation")

plot(years, P_strong,
     ylab = "annual precpitation > 5mm in mm/a",
     main = "precipitation > 5 mm/d")

NA
NA
lm.p_yr <-lm(P~years) # all years
summary(lm.p_yr)

Call:
lm(formula = P ~ years)

Residuals:
    Min      1Q  Median      3Q     Max 
-179.55 -104.16  -36.83   66.32  235.59 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept) 12680.607  11987.351   1.058    0.307
years          -5.970      5.955  -1.003    0.332

Residual standard error: 120.3 on 15 degrees of freedom
Multiple R-squared:  0.0628,    Adjusted R-squared:  0.0003183 
F-statistic: 1.005 on 1 and 15 DF,  p-value: 0.332
yrs_2014_2021 = c(10:17)

lm.p_yr.2014_2021 <-lm(P[yrs_2014_2021]~years[yrs_2014_2021]) # 2014-2021 only
summary(lm.p_yr.2014_2021)

Call:
lm(formula = P[yrs_2014_2021] ~ years[yrs_2014_2021])

Residuals:
    Min      1Q  Median      3Q     Max 
-173.79  -23.39   21.09   54.62   78.09 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)
(Intercept)          -8199.161  28258.937  -0.290    0.781
years[yrs_2014_2021]     4.374     14.007   0.312    0.765

Residual standard error: 90.78 on 6 degrees of freedom
Multiple R-squared:  0.01599,   Adjusted R-squared:  -0.148 
F-statistic: 0.09751 on 1 and 6 DF,  p-value: 0.7654

No obvious temporal trend in annual precipitation.

P_weak <- P-P_strong
lm.p_weak_yr <-lm(P_weak~years) # all years
summary(lm.p_weak_yr)

Call:
lm(formula = P_weak ~ years)

Residuals:
    Min      1Q  Median      3Q     Max 
-44.821  -8.814  -2.297  20.382  27.672 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept) 3421.610   2170.207   1.577    0.136
years         -1.597      1.078  -1.481    0.159

Residual standard error: 21.78 on 15 degrees of freedom
Multiple R-squared:  0.1276,    Adjusted R-squared:  0.0694 
F-statistic: 2.193 on 1 and 15 DF,  p-value: 0.1593
yrs_2014_2018 = c(10:17)

lm.pw_eak_yr.2014_2021 <-lm(P_weak[yrs_2014_2021]~years[yrs_2014_2021]) # 2014-2021 only
summary(lm.pw_eak_yr.2014_2021)

Call:
lm(formula = P_weak[yrs_2014_2021] ~ years[yrs_2014_2021])

Residuals:
    Min      1Q  Median      3Q     Max 
-37.499 -15.698  -0.501  17.806  36.596 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)
(Intercept)          -4538.796   8754.746  -0.518    0.623
years[yrs_2014_2021]     2.348      4.339   0.541    0.608

Residual standard error: 28.12 on 6 degrees of freedom
Multiple R-squared:  0.04651,   Adjusted R-squared:  -0.1124 
F-statistic: 0.2927 on 1 and 6 DF,  p-value: 0.608

Decrease of low intensity precipitation (P<5 mm/d) part of annual precipitation over the entire period, but not significant over the shorter period.

lm.p_strong_yr <-lm(P_strong~years) # all years
summary(lm.p_strong_yr)

Call:
lm(formula = P_strong ~ years)

Residuals:
     Min       1Q   Median       3Q      Max 
-141.015  -92.271    7.991   51.532  234.097 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept)  9258.997  11158.878   0.830    0.420
years          -4.374      5.543  -0.789    0.442

Residual standard error: 112 on 15 degrees of freedom
Multiple R-squared:  0.03984,   Adjusted R-squared:  -0.02417 
F-statistic: 0.6225 on 1 and 15 DF,  p-value: 0.4424
yrs_2014_2018 = c(10:17)

lm.p_strong_yr.2014_2021 <-lm(P_strong[yrs_2014_2021]~years[yrs_2014_2021]) # 2014-2021 only
summary(lm.p_strong_yr.2014_2021)

Call:
lm(formula = P_strong[yrs_2014_2021] ~ years[yrs_2014_2021])

Residuals:
    Min      1Q  Median      3Q     Max 
-136.29  -48.55   38.50   45.45   63.13 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)
(Intercept)          -3660.364  23756.482  -0.154    0.883
years[yrs_2014_2021]     2.026     11.775   0.172    0.869

Residual standard error: 76.31 on 6 degrees of freedom
Multiple R-squared:  0.004911,  Adjusted R-squared:  -0.1609 
F-statistic: 0.02961 on 1 and 6 DF,  p-value: 0.869
summary(lm(P_weak/P~ years))

Call:
lm(formula = P_weak/P ~ years)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.08636 -0.01678 -0.00061  0.03590  0.06078 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)
(Intercept)  0.6461596  4.6297328   0.140    0.891
years       -0.0001623  0.0022999  -0.071    0.945

Residual standard error: 0.04646 on 15 degrees of freedom
Multiple R-squared:  0.0003319, Adjusted R-squared:  -0.06631 
F-statistic: 0.004981 on 1 and 15 DF,  p-value: 0.9447

Days per year without precipitation.

summary(lm.norain)

Call:
lm(formula = noraindays ~ years)

Residuals:
    Min      1Q  Median      3Q     Max 
-22.235  -5.691  -1.029   3.779  26.368 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)
(Intercept) -1559.2794  1319.2090  -1.182    0.256
years           0.8676     0.6553   1.324    0.205

Residual standard error: 13.24 on 15 degrees of freedom
Multiple R-squared:  0.1046,    Adjusted R-squared:  0.04494 
F-statistic: 1.753 on 1 and 15 DF,  p-value: 0.2053

Days with some rain

weakraindays = raindays - strongraindays
plot(years, weakraindays)

lm.weakrain <- lm(weakraindays~years)
summary(lm.weakrain)

Call:
lm(formula = weakraindays ~ years)

Residuals:
    Min      1Q  Median      3Q     Max 
-19.743  -7.404   1.397   4.228  18.919 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept)  479.0221  1069.1685   0.448    0.661
years         -0.1691     0.5311  -0.318    0.755

Residual standard error: 10.73 on 15 degrees of freedom
Multiple R-squared:  0.006714,  Adjusted R-squared:  -0.05951 
F-statistic: 0.1014 on 1 and 15 DF,  p-value: 0.7546

Days with substantial rain

plot(years, strongraindays)

lm.strongrain <- lm(strongraindays~years)
summary(lm.strongrain)

Call:
lm(formula = strongraindays ~ years)

Residuals:
     Min       1Q   Median       3Q      Max 
-10.0221  -6.8162   0.2794   6.0882  16.7868 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept) 1445.2574   788.3681   1.833   0.0867 .
years         -0.6985     0.3916  -1.784   0.0947 .
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 7.911 on 15 degrees of freedom
Multiple R-squared:  0.175, Adjusted R-squared:   0.12 
F-statistic: 3.181 on 1 and 15 DF,  p-value: 0.09473
table_PET_P <- as.data.frame(cbind(h.years,  P.yearly, Epot.yearly))
colnames(table_PET_P) <- c("years", "P", "PET")
write.csv(table_PET_P, file="P_PET_16yrs_3289.csv")

Ptable <- as.data.frame(cbind(years, P, P-P_strong, P_strong, noraindays, weakraindays, strongraindays))

colnames(Ptable) <- c("year", "P","P_small", "P_subst", "ndays_norain","ndays_weakrain","ndays_substrain")
write.csv(Ptable, file <- "Ptable_16yrs_3289.csv")
LS0tCnRpdGxlOiAiU0VTTyBUZW1wZXJhdHVyZSAvIFdhdGVyIGJhbGFuY2UgYW5hbHlzaXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCgpVc2UgZGFpbHkgY2xpbWF0ZSBzdGF0aW9uIHRpbWUgc2VyaWVzIGZyb20gRFdELCBkb3dubG9hZGVkIGhlcmU6Cmh0dHBzOi8vb3BlbmRhdGEuZHdkLmRlL2NsaW1hdGVfZW52aXJvbm1lbnQvQ0RDL29ic2VydmF0aW9uc19nZXJtYW55L2NsaW1hdGUvZGFpbHkva2wvaGlzdG9yaWNhbC8KCkNob3NlIHN0YXRpb25zCi0gTm8gMzI4OSBTY2htaWVyaXRzLVdlbHR3aXR6ICgwMS4xMC4xOTcyIC0gY3VycmVudCkgbmVhciBTRVNPCi0gRGF0YSBtaXNzaW5nIAotIHN0YXJ0IGFuYWx5c2lzIHRpIGZpdCBIYWksIHdoaWNoIG9ubHkgc3RhcnRzIGluIDIwMDUKCmBgYHtyfQpmaWxlbmFtZSA9ICJ0YWdlc3dlcnRlX0tMXzAzMjg5XzE5NzIxMDAxXzIwMjIxMjMxX2hpc3QvcHJvZHVrdF9rbGltYV90YWdfMTk3MjEwMDFfMjAyMjEyMzFfMDMyODkudHh0IiAjIFNjaG1pZXJpdHMtV2VsdHdpdHoKZGF0YT1yZWFkLmNzdihmaWxlbmFtZSwgaGVhZGVyID0gVFJVRSwgc2VwPSI7IikKTGF0X2RhdGEgPC0gNTAuNzI4IyBsYXRpdHVkZSBvZiB0aGUgY2xpbWF0ZSBzdGF0aW9uLCB0YWtlbiBmcm9tIERXRCBtZXRhZGF0YQoKYGBgCgpDaGVjayB3aGljaCBwZXJpb2QgaXMgY292ZXJlZCwgd2hldGhlciB5ZWFycyBhcmUgY29tcGxldGUKCmBgYHtyfQoKZGF0YSRkYXRlIDwtIGFzLkRhdGUoYXMuY2hhcmFjdGVyKGRhdGEkTUVTU19EQVRVTSksZm9ybWF0PSclWSVtJWQnKQp5ZWFycyA8LSBhcy5udW1lcmljKHVuaXF1ZShmb3JtYXQoZGF0YSRkYXRlLCclWScpKSkKCmRhdGEkeWVhciA8LSBmb3JtYXQoZGF0YSRkYXRlLCclWScpCmRhdGEkbW9udGggPC0gZm9ybWF0KGRhdGEkZGF0ZSwnJW0nKQpkYXRhJGRheW1vbnRoIDwtIGZvcm1hdChkYXRhJGRhdGUsJyVkJW0nKQpkYXRhJGRheSA8LSBmb3JtYXQoZGF0YSRkYXRlLCclZCcpCgooZGF5c19wZXJfeWVhciA8LSBybGUoZGF0YSR5ZWFyKSkKCmBgYAoKClNlbGVjdCBvbmx5IGEgc3Vic2V0IG9mIHllYXJzOiAyMDA1IC0gMjAyMSAod2lsbCB5aWVsZHMgMTYgaHlkcm9sb2dpY2FsIHllYXJzKSB3aGljaCBpcyBhbGlnbmVkIHdpdGggdGhlIGRhdGEgYXZhaWxhYmlsaXR5IG9mIEhhaW5pY2guIEluY2lkZW50YWxseSwgaXQgY292ZXJzIDIwMTQtMjAyMSAoOCB5ZWFycyksIGFuZCB0aGUgcHJlY2VkaW5nIDggeWVhcnMuCgpgYGB7cn0KZGF0YSA9IHN1YnNldChkYXRhLCAoKHllYXIgPj0gMjAwNSkgJiAoeWVhcjw9IDIwMjEpKSkKeWVhcnMgPC0gYXMubnVtZXJpYyh1bmlxdWUoZm9ybWF0KGRhdGEkZGF0ZSwnJVknKSkpCihueWVhcnMgPSBsZW5ndGgoeWVhcnMpKQooZGF5c19wZXJfeWVhciA8LSBybGUoZGF0YSR5ZWFyKSkKZGF5c19wZXJfeWVhcltbMV1dCmBgYApTZWxlY3RlZCB5ZWFycyBhcmUgY29tcGxldGUuCgpyZW1vdmUgRmViIDI5CgpgYGB7cn0KaW5kX2ZlYjI5PC13aGljaChhcy5jaGFyYWN0ZXIoZGF0YSRkYXRlLCclZCVtJykgPT0gYygiMjkwMiIpKQpkYXRhPC1kYXRhWy1pbmRfZmViMjksXQpgYGAKCkNoZWNrIHdoZXRoZXIgdGhlcmUgYXJlIGFueSBtaXNzaW5nIGRhdGEgdGhhdCBuZWVkIHRvIGJlIHRha2VuIGNhcmUgb2YuCmBgYHtyfQooYSA8LSB3aGljaChkYXRhJFRNSyA9PSAtOTk5KSkgIyBkYWlseSBtZWFuIHRlbXAsIAooYSA8LSB3aGljaChkYXRhJFRYSyA9PSAtOTk5KSkgIyBkYWlseSBtYXggdGVtcCwgCihhIDwtIHdoaWNoKGRhdGEkVE5LID09IC05OTkpKSAjIGRhaWx5IG1pbiB0ZW1wLCAKIyhkYXRhJGRhdGVbYV0pCgooYiA8LSB3aGljaChkYXRhJFJTSyA9PSAtOTk5KSkgIyBkYWlseSBwcmVjaXBpdGF0aW9uCihkYXRhJGRhdGVbYl0pICMgbmVlZCB0byBjaGVjayBzdXJyb3VuZ2luZyBzdGF0aW9ucywgZS5nLiBTdGFkdHJvZGEgRm9yIG5vdyB0YWtlIGFzIHplcm8KCmRhdGEkUlNLW2JdIDwtIDAKCmBgYAoKRGF0YSBmb3IgdGVtcGVyYXR1cmUgaXMgY29tcGxldGUuIE1pc3NpbmcgcHJlY2lwaXRhdGlvbiBpbiBBdWd1c3QgMjAxOS4gTmVlZCB0byBkb3VibGUgY2hlY2suIEZvciBub3cgc2V0IHRvIHplcm8uCgoKQWRkIGEgY29sdW1uIGluZGljYXRpbmcgdGhlIGRhaWx5IGRpZmZlcmVuY2UgYmV0d2VlbiBtaW5pbXVtIGFuZCBtYXhpbXVtIHRlbXBlcmF0dXJlLiBUaGlzIGlzIGEgbWVhc3VyZSBmb3IgdGhlIHBvdGVudGlhbCBldmFwb3RyYW5zcGlyYXRpb24uCgpgYGB7cn0KZGF0YSREZWx0YVQgPC0gZGF0YSRUWEsgLSBkYXRhJFRNSwpgYGAKCiMjIyBDYWxjdWxhdGlvbiBvZiB0aGUgaHlkcm9sb2dpY2FsIHZhcmlhYmxlcwojIyMjIFBvdGVudGlhbCBFVAoKQ2FsY3VsYXRpb24sIHRha2luZyB0aGUgZXF1YXRpb24gb2YgSGFyZ3JlYXZlcy1TYW1hbmkgKDE5ODUpLCBzZWUgcmV2aWV3IGJ5IEhhcmdyZWF2ZXMgYW5kIEFsbGVuICgyMDAzKS4gVGhpcyB0YWtlcyBhIGJpdC4KCmBgYHtyfQpsaWJyYXJ5KHNpcmFkKQoKYSA8LSBleHRyYXQoZGF5T2ZZZWFyKGRhdGEkZGF0ZSksIExhdF9kYXRhKSAjIGNhbGN1bGF0ZSBleHRyYXRlcnJlc3RyaWFsIHJhZGlhdGlvbiBmb3IgdGhlIHNwZWNpZmljIGRheSBhbmQgbGF0aXR1ZGUKZGF0YSRSYSA8LSBhW1sxXV0KZGF0YSRsRXBvdCA8LSAwLjAwMjMgKiBkYXRhJFJhICogKGRhdGEkVE1LICsgMTcuOCkgKiBzcXJ0KGRhdGEkRGVsdGFUKSAjIGNhbGN1bGF0ZSBwb3RlbnRpYWwgbGF0ZW50IGhlYXQgZmx1eCBpbiBNSi9tMmQKZGF0YSRFcG90IDwtIChkYXRhJGxFcG90LzIuNWU2KSoxZTYjIGNhbGN1bGF0ZSBwb3RlbnRpYWwgRVQgaW4gbW0vZCBhc3N1bWUgbGF0ZW50IGhlYXQgb2YgZXZhcG9yYXRpb24gbCA9IDIuNWU2IEova2cgYW5kIGRlbnNpdHkgb2Ygd2F0ZXIgb2YgMTAwMCBrZy9tMwoKYGBgCgojIyMjIEF0bW9zcGhlcmljIHdhdGVyIGRlZmljaXQKClRoZSB3YXRlciBkZWZpY2l0IGNhbiBlaXRoZXIgYmUgY2FsY3VsYXRlZCBvdmVyIGVhY2ggdGhlIGh5ZHJvbG9naWNhbCB5ZWFyIChPY3RvYmVyIC0gU2VwdGVtYmVyKSBzZXBhcmF0ZWx5IG9yIG92ZXIgdGhlIGVudGlyZSBwZXJpb2QuIAoKIyMjIyMgb3ZlciBlYWNoIGh5ZHJvbG9naWNhbCB5ZWFyIHNlcGFyYXRlbHkKCmBgYHtyfQpoeWRyby5zdGFydHllYXIgPSB5ZWFyc1sxXQpoeWRyby5lbmR5ZWFyID0geWVhcnNbbGVuZ3RoKHllYXJzKV0KCmh5ZHJvLnN0YXJ0ZGF0ZSA9IGFzLkRhdGUocGFzdGUoaHlkcm8uc3RhcnR5ZWFyLCIxMCIsIjAxIiwgc2VwPSItIiksICIlWS0lbS0lZCIpCmh5ZHJvLmVuZGRhdGUgPSBhcy5EYXRlKHBhc3RlKGh5ZHJvLmVuZHllYXIsIjA5IiwiMzAiLCBzZXA9Ii0iKSwgIiVZLSVtLSVkIikKCiNoeWRyby5zdGFydGRhdGUgPSBhcy5QT1NJWGx0KHBhc3RlKGh5ZHJvLnN0YXJ0eWVhciwiMTAiLCIwMSIsIHNlcD0iLSIpLCAiJVktJW0tJWQiKQojaHlkcm8uZW5kZGF0ZSA9IGFzLlBPU0lYbHQocGFzdGUoaHlkcm8uZW5keWVhciwiMDkiLCIzMCIsIHNlcD0iLSIpLCAiJVktJW0tJWQiKQoKaC5kYXRhIDwtIHN1YnNldC5kYXRhLmZyYW1lKGRhdGEsIChkYXRlID49IGh5ZHJvLnN0YXJ0ZGF0ZSAmIGRhdGUgPD0gaHlkcm8uZW5kZGF0ZSkpCgpgYGAKCgoKYGBge3J9CmguZGF0YSRkZWYgPC0gTkEKCgpmb3IgKHllYXIgaW4geWVhcnNbMTpsZW5ndGgoeWVhcnMpLTFdKSB7CiAgICAgICAgc3RhcnRkYXkgPSBhcy5EYXRlKHBhc3RlKHllYXIsIjEwIiwiMDEiLCBzZXA9Ii0iKSwgIiVZLSVtLSVkIikKICAgICAgICBlbmRkYXkgPSBhcy5EYXRlKHBhc3RlKHllYXIrMSwiMDkiLCIzMCIsIHNlcD0iLSIpLCAiJVktJW0tJWQiKQogICAgICAgIGluZC50aGlzeWVhciA8LSB3aGljaChoLmRhdGEkZGF0ZSA+PSBzdGFydGRheSAmIGguZGF0YSRkYXRlIDw9IGVuZGRheSkKICAgICAgICBoLmRhdGEkZGVmW2luZC50aGlzeWVhcl0gPC0gY3Vtc3VtKGguZGF0YSRSU0tbaW5kLnRoaXN5ZWFyXS1oLmRhdGEkRXBvdFtpbmQudGhpc3llYXJdKSAKCn0KYGBgCgoKIyMgQmFzaWMgZmVhdHVyZXMgb2YgdGhlIHRlbXBlcmF0dXJlIGRhdGFzZXQKCkNoZWNrIHdoZXRoZXIgdGhlIGRpc3RyaWJ1dGlvbiBvZiByYWluZmFsbCBhbmQgb3RoZXIgdmFyaWFibGVzIGNoYW5nZWQgYmV0d2VlbiAKCiogMjAxNC0yMDE3IGFuZCAKCiogMjAxOC0yMDIxLiAKClNpbmNlIHRoZSB0aW1lIHNlcmllcyBvZiBTRVNPIGlzIGEgYml0IHNob3J0ZXIgKDIwMTYtMjAyMSksIGNyZWF0ZSBhbiBhbHRlcmF0aXZlIHN1YnNldCwgdG8gYmUgYWJsZSB0byBsb29rIG9ubHkgYXQgc29tZSBvZiB0aGUgYW5hbHlzaXMgZm9yIHRoaXMgc21hbGxlciByYW5nZS4KCiogMjAxNi0yMDE4IGFuZCAKCiogMjAxOS0yMDIxLiAKCgpGb3Igb3JpZW50YXRpb24gcGxvdCB0aGUgZGF5bGl5IGNsaW1hdG9sb2d5IG92ZXIgdGhlIGVudGlyZSB0aW1lc2VyaWVzLCAyMDA1LTIwMjIKCmBgYHtyfQojIHN1YnNldCBmb3IgcGVyaW9kcwpkYXRhXzIwMTRfMjAxNyA8LSBkYXRhW3doaWNoKGRhdGEkeWVhcj49MjAxNCAmIGRhdGEkeWVhcjw9MjAxNyksXSAKZGF0YV8yMDE4XzIwMjEgPC0gZGF0YVt3aGljaChkYXRhJHllYXI+PTIwMTggJiBkYXRhJHllYXI8PTIwMjEpLF0gCgpkYXRhXzIwMTZfMjAxOCA8LSBkYXRhW3doaWNoKGRhdGEkeWVhcj49MjAxNiAmIGRhdGEkeWVhcjw9MjAxOCksXSAKZGF0YV8yMDE5XzIwMjEgPC0gZGF0YVt3aGljaChkYXRhJHllYXI+PTIwMTkgJiBkYXRhJHllYXI8PTIwMjEpLF0gCgoKCiMgY2xpbWF0b2xvZ3kgb3ZlciB0aGUgZW50aXJlIHRpbWUgc2VyaWVzClQuY2xpbSA8LSBhZ2dyZWdhdGUoVE1LIH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YSwgRlVOID0gbWVhbikKcGxvdChULmNsaW0kVE1LLCB5bGltID0gYygtNywgMjgpLAogICAgIHhsYWIgPSAiRG95IG9mIHllYXIiLAogICAgIHlsYWIgPSAiQXZlcmFnZSBkYWlseSB0ZW1wZXJhdHVyZSBpbiBkZWcgQyIpCgojIGF2ZXJnZSBvdmVyIHBlcmlvZHMKVC5jbGltLjIwMTRfMjAxNyA8LSBhZ2dyZWdhdGUoVE1LIH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YV8yMDE0XzIwMTcsIEZVTiA9IG1lYW4pCnBvaW50cyhULmNsaW0uMjAxNF8yMDE3JFRNSywgY29sPSJibHVlIikKCiMgMjAxOC0yMDIxClQuY2xpbS4yMDE4XzIwMjEgPC1hZ2dyZWdhdGUoVE1LIH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YV8yMDE4XzIwMjEsIEZVTiA9IG1lYW4pCnBvaW50cyhULmNsaW0uMjAxOF8yMDIxJFRNSywgY29sPSJyZWQiKQpsZWdlbmQoeCA9ICJ0b3BsZWZ0IiwgICAgICAgICAgIyBQb3NpdGlvbgogICAgICAgbGVnZW5kID0gYygiY2xpbSIsICIyMDE0LTIwMTciLCAiMjAxOC0yMDIxIiksICAjIExlZ2VuZCB0ZXh0cwogICAgICAgcGNoID0gYygxLDEsMSksICMgcG9pbnQgdHlwZQogICAgICAgY29sID0gYygiYmxhY2siLCAiYmx1ZSIsICJyZWQiKSkgIyBwb2ludCBjb2xvcnMKCgpwbG90KFQuY2xpbSRUTUstVC5jbGltLjIwMTRfMjAxNyRUTUssIGNvbD0iYmx1ZSIsCiAgICAgeGxhYj1jKCJEYXkgb2YgeWVhciIpLAogICAgIHlsYWIgPSAiVGVtcGVyYXR1cmUgYW5vbWFseSBpbiBkZWdDIikKcG9pbnRzKFQuY2xpbSRUTUstVC5jbGltLjIwMThfMjAyMSRUTUssIGNvbCA9ICJyZWQiKQpsZWdlbmQoeCA9ICJ0b3BsZWZ0IiwgICAgICAgICAgIyBQb3NpdGlvbgogICAgICAgbGVnZW5kID0gYygiMjAxNC0yMDE3IiwgIjIwMTgtMjAyMSIpLCAgIyBMZWdlbmQgdGV4dHMKICAgICAgIHBjaCA9IGMoMSwxKSwgIyBwb2ludCB0eXBlCiAgICAgICBjb2wgPSBjKCJibHVlIiwgInJlZCIpKSAjIHBvaW50IGNvbG9ycwoKCgpwYXIobWZyb3c9YygxLDIpKQpiaW5zID0gc2VxKC02LDYsMSkKaGlzdChULmNsaW0uMjAxNF8yMDE3JFRNSy1ULmNsaW0kVE1LLAogICAgIHhsYWIgPSAiRGV2aWF0aW9uIGluIHRlbXBlcmF0dXJlIGZyb20gY2xpbWF0b2xvZ3kiLAogICAgIG1haW4gPSAiMjAxNC0yMDE4IiwKICAgICBicmVha3MgPSBiaW5zKQpoaXN0KFQuY2xpbS4yMDE4XzIwMjEkVE1LLVQuY2xpbSRUTUssCiAgICAgeGxhYiA9ICJEZXZpYXRpb24gaW4gdGVtcGVyYXR1cmUgZnJvbSBjbGltYXRvbG9neSIsCiAgICAgbWFpbiA9ICIyMDE4LTIwMjEiLAogICAgIGJyZWFrcyA9IGJpbnMpCihxdWFudGlsZShULmNsaW0uMjAxNF8yMDE3JFRNSy1ULmNsaW0kVE1LLCBjKDAuMSwwLjUsMC45KSkpCihxdWFudGlsZShULmNsaW0uMjAxOF8yMDIxJFRNSy1ULmNsaW0kVE1LLCBjKDAuMSwwLjUsMC45KSkpCgojIHRlbXBlcmF0dXJlIGFub21hbGllcwpkYXRhJFRjbGltIDwtIE5BCmluZCA8LSB3aGljaChkYXRhJHllYXI+eWVhcnNbMV0pCmRhdGEkVGNsaW1baW5kXSA8LSByZXAoVC5jbGltJFRNSyxsZW5ndGgoaW5kKS8zNjUpIApkYXRhJFRhbm8gPC0gZGF0YSRUTUsgLSBkYXRhJFRjbGltCgpwbG90KGRhdGEkZGF0ZSxkYXRhJFRhbm8sCiAgICAgeGxhYiA9ICJEYXRlIiwKICAgICB5bGFiID0gIlRlbXBlcmF0dXJlIGFub21hbGllcyBpbiBkZWdDIikKCmJveHBsb3QoVGFubyB+IHllYXIsIGRhdGE9ZGF0YSwKICAgICAgICB4bGFiID0gIlllYXIiLAogICAgICAgIHlsYWIgPSAiVGVtcGVyYXR1cmUgYW5vbWFsaWVzIGluIGRlZ0MiKQoKbG0uVGFub20gPC0gbG0oVGFubyB+IGFzLm51bWVyaWMoeWVhciksIGRhdGEgPSBkYXRhKQpzdW1tYXJ5KGxtLlRhbm9tKQoKYGBgCgpCb3RoIHBlcmlvZHMgd2VyZSB3YXJtZXIgdGhhbiB0aGUgZW50aXJlIHJlZmVyZW5jZSBwZXJpb2RzIGZyb20gMjAwNS0yMDIyLCB3aGlsZSAyMDE4LTIwMjEgd2FzIG92ZXJhbGwgcm91Z2hseSAwLjA1IGRlZ3JlZSB3YXJtZXIgdGhhbiB0aGUgcHJldmlvdXMgMjAxNC0yMDE3IHBlcmlvZC4gVGhlcmUgYXJlIG5vIHN0cm9uZyBlZmZlY3RzIGluIHRlbXBlcmF0dXJlIHBlciBzZS4gQUxzbyB0aGUgYW5vbWFsaWVzIGFyZSBzbGlnaHRseSBpbmNyZWFzaW5nIHdpdGggdGltZSBieSAwLjA2IGRlZ3JlZSBwZXIgeWVhci4KCiMjIyBEaWZmZXJlbmNlIGluIHRoZSBkYWlseSB0ZW1wZXJhdHVyZSBpbmRpY2F0aW5nIGNsb3VkaW5lc3MuCgooZGVsdGFfVCA9IFRfbWF4IC0gVF9taW4pCgpgYGB7cn0KRGVsdGFULmNsaW0gPC0gYWdncmVnYXRlKERlbHRhVCB+IGRheSttb250aCwgZGF0YSA9IGRhdGEsIEZVTiA9IG1lYW4pCnBsb3QoRGVsdGFULmNsaW0kRGVsdGFULCB5bGltID0gYygxLDEwKSkKCiMgYXZlcmdlIG92ZXIgcGVyaW9kcyAyMDE0LTIwMTcKRGVsdGFULmNsaW0uMjAxNF8yMDE3IDwtIGFnZ3JlZ2F0ZShEZWx0YVQgfiBkYXkrbW9udGgsIGRhdGEgPSBkYXRhXzIwMTRfMjAxNywgRlVOID0gbWVhbikKcG9pbnRzKERlbHRhVC5jbGltLjIwMTRfMjAxNyREZWx0YVQsIGNvbD0iYmx1ZSIpCgojIGF2ZXJnZSBvdmVyIHBlcmlvZHMgMjAxOC0yMDIxCkRlbHRhVC5jbGltLjIwMThfMjAyMSA8LSBhZ2dyZWdhdGUoRGVsdGFUIH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YV8yMDE4XzIwMjEsIEZVTiA9IG1lYW4pCnBvaW50cyhEZWx0YVQuY2xpbS4yMDE4XzIwMjEkRGVsdGFULCBjb2w9InJlZCIpCgoKIyBhdmVyZ2Ugb3ZlciBwZXJpb2RzIDIwMTYtMjAxOApEZWx0YVQuY2xpbS4yMDE2XzIwMTggPC0gYWdncmVnYXRlKERlbHRhVCB+IGRheSttb250aCwgZGF0YSA9IGRhdGFfMjAxNl8yMDE4LCBGVU4gPSBtZWFuKQojcG9pbnRzKERlbHRhVC5jbGltLjIwMTZfMjAxOCREZWx0YVQsIGNvbD0iYmx1ZSIpCgojIGF2ZXJnZSBvdmVyIHBlcmlvZHMgMjAxOS0yMDIxCkRlbHRhVC5jbGltLjIwMTlfMjAyMSA8LSBhZ2dyZWdhdGUoRGVsdGFUIH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YV8yMDE5XzIwMjEsIEZVTiA9IG1lYW4pCiNwb2ludHMoRGVsdGFULmNsaW0uMjAxOV8yMDIxJERlbHRhVCwgY29sPSJyZWQiKQoKYmlucyA9IHNlcSgwLjUsMTAsMC4yNSkKCmguRGVsdGFUX2RhaWx5LmNsaW0gPC0gaGlzdChEZWx0YVQuY2xpbSREZWx0YVQsIGJyZWFrcyA9IGJpbnMsIHBsb3QgPSBGQUxTRSkKaC5EZWx0YVRfZGFpbHkuMjAxNF8yMDE3IDwtIGhpc3QoRGVsdGFULmNsaW0uMjAxNF8yMDE3JERlbHRhVCwgYnJlYWtzID0gYmlucywgcGxvdCA9IEZBTFNFKQpoLkRlbHRhVF9kYWlseS4yMDE4XzIwMjEgPC0gaGlzdChEZWx0YVQuY2xpbS4yMDE4XzIwMjEkRGVsdGFULCBicmVha3MgPSBiaW5zLCBwbG90ID0gRkFMU0UpCmguRGVsdGFUX2RhaWx5LjIwMTZfMjAxOCA8LSBoaXN0KERlbHRhVC5jbGltLjIwMTZfMjAxOCREZWx0YVQsIGJyZWFrcyA9IGJpbnMsIHBsb3QgPSBGQUxTRSkKaC5EZWx0YVRfZGFpbHkuMjAxOV8yMDIxIDwtIGhpc3QoRGVsdGFULmNsaW0uMjAxOV8yMDIxJERlbHRhVCwgYnJlYWtzID0gYmlucywgcGxvdCA9IEZBTFNFKQoKCgoKcGxvdChoLkRlbHRhVF9kYWlseS5jbGltJG1pZHMsIGN1bXN1bShoLkRlbHRhVF9kYWlseS5jbGltJGRlbnNpdHkpLzQsIAogICAgIHhsYWIgPSAiRGFpbHkgdGVtcGVyYXR1cmUgZGlmZmVyZW5jZSwgZGVnQyIsCiAgICAgeWxhYiA9ICJjdW11bGF0aXZlIGZyZXF1ZW5jeSIpCnBvaW50cyhoLkRlbHRhVF9kYWlseS4yMDE0XzIwMTckbWlkcywgY3Vtc3VtKGguRGVsdGFUX2RhaWx5LjIwMTRfMjAxNyRkZW5zaXR5KS80LCAKICAgICAgIHBjaCA9IDE5LCBjb2wgPSAiYmx1ZSIpCnBvaW50cyhoLkRlbHRhVF9kYWlseS4yMDE4XzIwMjEkbWlkcywgY3Vtc3VtKGguRGVsdGFUX2RhaWx5LjIwMThfMjAyMSRkZW5zaXR5KS80LCAKICAgICAgIHBjaCA9IDE5LCBjb2wgPSAicmVkIikKbGVnZW5kKHggPSAiYm90dG9tcmlnaHQiLCAgICAgICAgICAjIFBvc2l0aW9uCiAgICAgICBsZWdlbmQgPSBjKCJjbGltIiwgIjIwMTQtMjAxNyIsICIyMDE4LTIwMjEiKSwgICMgTGVnZW5kIHRleHRzCiAgICAgICBwY2ggPSBjKDEsIDE5LCAxOSksICMgcG9pbnQgdHlwZXMKICAgICAgIGNvbCA9IGMoImJsYWNrIiwgImJsdWUiLCAicmVkIiksICMgcG9pbnQgY29sb3JzCiAgICAgICApICAgICAgICAgICAKCgpwbG90KGguRGVsdGFUX2RhaWx5LmNsaW0kbWlkcywgY3Vtc3VtKGguRGVsdGFUX2RhaWx5LmNsaW0kZGVuc2l0eSkvNCwgCiAgICAgeGxhYiA9ICJEYWlseSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlLCBkZWdDIiwKICAgICB5bGFiID0gImN1bXVsYXRpdmUgZnJlcXVlbmN5IikKcG9pbnRzKGguRGVsdGFUX2RhaWx5LjIwMTZfMjAxOCRtaWRzLCBjdW1zdW0oaC5EZWx0YVRfZGFpbHkuMjAxNl8yMDE4JGRlbnNpdHkpLzQsIAogICAgICAgcGNoID0gMTksIGNvbCA9ICJibHVlIikKcG9pbnRzKGguRGVsdGFUX2RhaWx5LjIwMTlfMjAyMSRtaWRzLCBjdW1zdW0oaC5EZWx0YVRfZGFpbHkuMjAxOV8yMDIxJGRlbnNpdHkpLzQsIAogICAgICAgcGNoID0gMTksIGNvbCA9ICJyZWQiKQpsZWdlbmQoeCA9ICJib3R0b21yaWdodCIsICAgICAgICAgICMgUG9zaXRpb24KICAgICAgIGxlZ2VuZCA9IGMoImNsaW0iLCAiMjAxNi0yMDE4IiwgIjIwMTktMjAyMSIpLCAgIyBMZWdlbmQgdGV4dHMKICAgICAgIHBjaCA9IGMoMSwgMTksIDE5KSwgIyBwb2ludCB0eXBlcwogICAgICAgY29sID0gYygiYmxhY2siLCAiYmx1ZSIsICJyZWQiKSwgIyBwb2ludCBjb2xvcnMKICAgICAgICkgICAgICAgICAgIAoKCiNoaXN0KERlbHRhVC5jbGltLjIwMTRfMjAxNyREZWx0YVQtRGVsdGFULmNsaW0kRGVsdGFUKQoKI2hpc3QoRGVsdGFULmNsaW0uMjAxOF8yMDIxJERlbHRhVC1EZWx0YVQuY2xpbSREZWx0YVQpCgpkZWx0YVQgPC0gYXMuZGF0YS5mcmFtZShjYmluZChoLkRlbHRhVF9kYWlseS5jbGltJG1pZHMsIGN1bXN1bShoLkRlbHRhVF9kYWlseS5jbGltJGRlbnNpdHkpLzQsIGN1bXN1bShoLkRlbHRhVF9kYWlseS4yMDE0XzIwMTckZGVuc2l0eSkvNCwgY3Vtc3VtKGguRGVsdGFUX2RhaWx5LjIwMThfMjAyMSRkZW5zaXR5KS80KSkKY29sbmFtZXMoZGVsdGFUKSA8LSBjKCJkZWx0YV9UIiwgImZyZXFfMjAwNV8yMDIxIiwgImZyZXFfMjAxNF8yMDE3IiwgImZyZXFfMjAxOF8yMDIxIikKCndyaXRlLmNzdihkZWx0YVQsIGZpbGU9ImRhbHRhVF8xNXlyc18zMjg5LmNzdiIpCgoKCmBgYAoKVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBtaW51bXVtIGFuZCBtYXh1bWltIHRlbXBlcmF0dXJlIGluY3JlYXNlcyBpbiBib3RoIHBlcmlvZHMsIGVzcGx5IGluIHRpbWVzIHdlcmUgdGVtcGVyYXR1cmUgZGlmZmVyZW5jZXMgYXJlIGhpZ2ggKGluIHN1bW1lcikuIFRodXMgaW4gZ2VuZXJhbCB0aGUgdmFyaWF0aW9uIGluIHRlbXBlcmF0dXJlIGF0IGEgZGFpbHkgc2NhbGUgaGFzIGluY3JlYXNlZCwgaW5kaWNhdGluZyBhbiBpbmNyZWFzZSBpbiBzdW5zaGluZSBob3VycyBhbmQgZGVjcmVhc2UgaW4gY2xvdWRpbmVzcy4gCgojIyMgUG90ZW50aWFsIEV2YXBvdHJhbnNwaXJhdGlvbiwgZGFpbHkKCmBgYHtyfQoKRXBvdC5jbGltIDwtIGFnZ3JlZ2F0ZShFcG90IH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YSwgRlVOID0gbWVhbikKcGxvdChFcG90LmNsaW0kRXBvdCwgeWxpbSA9IGMoMCw1KSwKICAgICB4bGFiID0gIkRheSBvZiB5ZWFyIiwKICAgICB5bGFiID0gIlBvdGVudGlhbCBldmFwb3RyYW5zcGlyYXRpb24gaW4gbW0vZGF5IikKbGVnZW5kKHggPSAidG9wcmlnaHQiLCAgICAgICAgICAjIFBvc2l0aW9uCiAgICAgICBsZWdlbmQgPSBjKCJjbGltIiwgIjIwMTQtMjAxNyIsICIyMDE4LTIwMjEiKSwgICMgTGVnZW5kIHRleHRzCiAgICAgICAgcGNoID0gYygxLCAxLCAxKSwgIyBwb2ludCB0eXBlcwogICAgICAgIGNvbCA9IGMoImJsYWNrIiwgImJsdWUiLCAicmVkIikpICMgcG9pbnQgY29sb3JzCgoKIyBhdmVyZ2Ugb3ZlciBwZXJpb2RzCkVwb3QuY2xpbS4yMDE0XzIwMTcgPC0gYWdncmVnYXRlKEVwb3QgfiBkYXkrbW9udGgsIGRhdGEgPSBkYXRhXzIwMTRfMjAxNywgRlVOID0gbWVhbikKcG9pbnRzKEVwb3QuY2xpbS4yMDE0XzIwMTckRXBvdCwgY29sPSJibHVlIikKCiMgYXZlcmdlIG92ZXIgcGVyaW9kcwpFcG90LmNsaW0uMjAxOF8yMDIxIDwtIGFnZ3JlZ2F0ZShFcG90IH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YV8yMDE4XzIwMjEsIEZVTiA9IG1lYW4pCnBvaW50cyhFcG90LmNsaW0uMjAxOF8yMDIxJEVwb3QsIGNvbD0icmVkIikKCmJpbnMgPSBzZXEoMCw1LDAuMSkKCmguRXBvdF9kYWlseS5jbGltIDwtIGhpc3QoRXBvdC5jbGltJEVwb3QsIGJyZWFrcyA9IGJpbnMsIHBsb3QgPSBGQUxTRSkKaC5FcG90X2RhaWx5LjIwMTRfMjAxNyA8LSBoaXN0KEVwb3QuY2xpbS4yMDE0XzIwMTckRXBvdCwgYnJlYWtzID0gYmlucywgcGxvdCA9IEZBTFNFKQpoLkVwb3RfZGFpbHkuMjAxOF8yMDIxIDwtIGhpc3QoRXBvdC5jbGltLjIwMThfMjAyMSRFcG90LCBicmVha3MgPSBiaW5zLCBwbG90ID0gRkFMU0UpCgpwbG90KGguRXBvdF9kYWlseS5jbGltJG1pZHMsIGN1bXN1bShoLkVwb3RfZGFpbHkuY2xpbSRkZW5zaXR5KS8xMCwgCiAgICAgeGxhYiA9ICJEYWlseSBwb3RlbnRpYWwgZXZhcG90cmFuc3BpcmF0aW9uLCBtbS9kIiwKICAgICB5bGFiID0gImN1bXVsYXRpdmUgZnJlcXVlbmN5IikKcG9pbnRzKGguRXBvdF9kYWlseS4yMDE0XzIwMTckbWlkcywgY3Vtc3VtKGguRXBvdF9kYWlseS4yMDE0XzIwMTckZGVuc2l0eSkvMTAsIAogICAgICAgcGNoID0gMTksIGNvbCA9ICJibHVlIikKcG9pbnRzKGguRXBvdF9kYWlseS4yMDE4XzIwMjEkbWlkcywgY3Vtc3VtKGguRXBvdF9kYWlseS4yMDE4XzIwMjEkZGVuc2l0eSkvMTAsIAogICAgICAgcGNoID0gMTksIGNvbCA9ICJyZWQiKQpsZWdlbmQoeCA9ICJib3R0b21yaWdodCIsICAgICAgICAgICMgUG9zaXRpb24KICAgICAgIGxlZ2VuZCA9IGMoImNsaW0iLCAiMjAxNC0yMDE3IiwgIjIwMTgtMjAyMSIpLCAgIyBMZWdlbmQgdGV4dHMKICAgICAgIHBjaCA9IGMoMSwgMTksIDE5KSwgIyBwb2ludCB0eXBlcwogICAgICAgY29sID0gYygiYmxhY2siLCAiYmx1ZSIsICJyZWQiKSwgIyBwb2ludCBjb2xvcnMKICAgICAgICkgICAgICAgICAgIAoKYGBgCgpBdCB0aGUgZGFpbHkgc2NhbGUsIHRoZSBwb3RlbnRpYWwgZXZhcG90cmFuc3BpcmF0aW9uIGhhcyBzbGlnaHRseSBpbmNyZWFzZWQgZXNwZWNpYWxseSBpbiBzdW1tZXIuCgojIyMgUG90ZW50aWFsIGV2YXBvdHJhbnNwaXJhdGlvbiwgcHJlY2lwaXRhdGlvbiB3ZWVrbHkKCmBgYHtyfQpsaWJyYXJ5KHRpZHlyKQojIEFnZ3JlZ2F0ZSB0byB3ZWVrbHkgZGF0YSBhcyA1IGRhaWx5IGF2ZXJhZ2VzIHBlcmZvcm0gYmV0dGVyIHRoYW4gZGFpbHkgCmRhdGEkZGF0ZSA8LSBhcy5QT1NJWGx0KGRhdGEkZGF0ZSkKZGF0YS53LkVwb3QgPC0gYWdncmVnYXRlKGRhdGEkRXBvdCB+IGZvcm1hdChkYXRlLCIlWS0lVyIpLCBkYXRhPWRhdGEsIEZVTiA9IG1lYW4pICMgd2Vla2x5IGRhdGEKbmFtZXMoZGF0YS53LkVwb3QpWzE6Ml0gPSBjKCJkYXRlIiwgIkVwb3QiKQpkYXRhLncuRXBvdDwtZGF0YS53LkVwb3QgJT4lIHNlcGFyYXRlKGRhdGUsIGMoInllYXIiLCJ3ZWVrIikpICMgdGlkeXIKCiMgc3Vic2V0IGZvciBwZXJpb2RzIG9uY2UgbW9yZQpkYXRhLncuRXBvdF8yMDE0XzIwMTcgPC0gZGF0YS53LkVwb3Rbd2hpY2goZGF0YS53LkVwb3QkeWVhcj49MjAxNCAmIGRhdGEudy5FcG90JHllYXI8PTIwMTcpLF0gCmRhdGEudy5FcG90XzIwMThfMjAyMSA8LSBkYXRhLncuRXBvdFt3aGljaChkYXRhLncuRXBvdCR5ZWFyPj0yMDE4ICYgZGF0YS53LkVwb3QkeWVhcjw9MjAyMSksXSAKCkVwb3QuY2xpbSA8LSBhZ2dyZWdhdGUoRXBvdCB+IHdlZWssIGRhdGEgPSBkYXRhLncuRXBvdCwgRlVOID0gbWVhbikgIyB3ZWVrbHkgY2xpbWF0b2xvZ3kKCkVwb3QuY2xpbS4yMDE0XzIwMTcgPC0gYWdncmVnYXRlKEVwb3QgfiB3ZWVrLCBkYXRhID0gZGF0YS53LkVwb3RfMjAxNF8yMDE3LCBGVU4gPSBtZWFuKSAjIHdlZWtseSBjbGltYXRvbG9neSAyMDE0LTIwMTcKRXBvdC5jbGltLjIwMThfMjAyMSA8LSBhZ2dyZWdhdGUoRXBvdCB+IHdlZWssIGRhdGEgPSBkYXRhLncuRXBvdF8yMDE4XzIwMjEsIEZVTiA9IG1lYW4pICMgd2Vla2x5IGNsaW1hdG9sb2d5IDIwMTgtMjAyMQoKcGxvdChFcG90LmNsaW0kRXBvdCwKICAgICB4bGFiID0gIkNhbGVuZGFyIHdlZWsiLAogICAgIHlsYWIgPSAiQXZlcmFnZSBQRVQgaW4gbW0vZCIpCnBvaW50cyhFcG90LmNsaW0uMjAxNF8yMDE3JEVwb3QsIAogICAgICAgcGNoID0gMTksIGNvbCA9ICJibHVlIikKcG9pbnRzKEVwb3QuY2xpbS4yMDE4XzIwMjEkRXBvdCwgCiAgICAgICBwY2ggPSAxOSwgY29sID0gInJlZCIpCmxlZ2VuZCh4ID0gInRvcGxlZnQiLCAgICAgICAgICAjIFBvc2l0aW9uCiAgICAgICBsZWdlbmQgPSBjKCJjbGltIiwgIjIwMTQtMjAxNyIsICIyMDE4LTIwMjEiKSwgICMgTGVnZW5kIHRleHRzCiAgICAgICBwY2ggPSBjKDEsIDE5LCAxOSksICMgcG9pbnQgdHlwZXMKICAgICAgIGNvbCA9IGMoImJsYWNrIiwgImJsdWUiLCAicmVkIiksICMgcG9pbnQgY29sb3JzCiAgICAgICApICAgICAgICAgICAKCgpwbG90KGN1bXN1bShFcG90LmNsaW0kRXBvdCo3KSwKICAgICB4bGFiID0gIkNhbGVuZGFyIHdlZWsiLAogICAgIHlsYWIgPSAiQ3VtdWxhdGVkIFBFVCBpbiBtbSIpCnBvaW50cyhjdW1zdW0oRXBvdC5jbGltLjIwMTRfMjAxNyRFcG90KjcpLCAKICAgICAgIHBjaCA9IDE5LCBjb2wgPSAiYmx1ZSIpCnBvaW50cyhjdW1zdW0oRXBvdC5jbGltLjIwMThfMjAyMSRFcG90KjcpLCAKICAgICAgIHBjaCA9IDE5LCBjb2wgPSAicmVkIikKbGVnZW5kKHggPSAiYm90dG9tcmlnaHQiLCAgICAgICAgICAjIFBvc2l0aW9uCiAgICAgICBsZWdlbmQgPSBjKCJjbGltIiwgIjIwMTQtMjAxNyIsICIyMDE4LTIwMjEiKSwgICMgTGVnZW5kIHRleHRzCiAgICAgICBwY2ggPSBjKDEsIDE5LCAxOSksICMgcG9pbnQgdHlwZXMKICAgICAgIGNvbCA9IGMoImJsYWNrIiwgImJsdWUiLCAicmVkIiksICMgcG9pbnQgY29sb3JzCiAgICAgICApIAoKCgpgYGAKClRoaXMgZ2l2ZXMgdGhlIGN1bXVsYXRpdmUgcG90ZW50aWFsIGV2YXBvdHJhbnNwaXJhdGlvbiwgd2hpY2ggaGFzIHNsaWdodGx5IGluY3JlYXNlZCBpbiB0aGUgc2Vjb25kIHBlcmlvZCBjb21wYXJlZCB0byB0aGUgZmlyc3QuIFRoZSBmaXJzdCBpcyBzaW1pbGFyIHRvIHRoZSBjbGltYXRvbG9neS4KCgojIyMgTW9udGhseSBwcmVjaXBpdGF0aW9uIGFuZCBwb3RlbnRpYWwgZXZhcG90cmFuc3BpcmF0aW9uCgpgYGB7cn0KCnByZWMubW9udGhseSA8LSBhZ2dyZWdhdGUoUlNLIH4gbW9udGgreWVhciwgZGF0YSA9IGRhdGEsIEZVTiA9IHN1bSkKY2xpbS5wcmVjLm1vbnRobHkgPC0gYWdncmVnYXRlKFJTSyB+IG1vbnRoLCBkYXRhID0gcHJlYy5tb250aGx5LCBGVU4gPSBtZWFuKQpwbG90KGNsaW0ucHJlYy5tb250aGx5LAogICAgIHlsaW0gPSBjKDAsMTUwKSwKICAgICB0eXBlID0gImwiLAogICAgIHlsYWIgPSAiTW9udGhseSBmbHV4LCBtbSIpCgojIHBlcmlvZCAyMDE0LTIwMTcKcHJlYy5tb250aGx5LjIwMTRfMjAxNyA8LSBhZ2dyZWdhdGUoUlNLIH4gbW9udGgreWVhciwgZGF0YSA9IGRhdGFfMjAxNF8yMDE3LCBGVU4gPSBzdW0pCmNsaW0ucHJlYy5tb250aGx5LjIwMTRfMjAxNyA8LSBhZ2dyZWdhdGUoUlNLIH4gbW9udGgsIGRhdGEgPSBwcmVjLm1vbnRobHkuMjAxNF8yMDE3LCBGVU4gPSBtZWFuKQpsaW5lcyhjbGltLnByZWMubW9udGhseS4yMDE0XzIwMTcsCiAgICAgdHlwZSA9ICJsIiwKICAgICBjb2wgPSAiYmx1ZSIpCgojIHBlcmlvZCAyMDE4LTIwMjEKcHJlYy5tb250aGx5LjIwMThfMjAyMSA8LSBhZ2dyZWdhdGUoUlNLIH4gbW9udGgreWVhciwgZGF0YSA9IGRhdGFfMjAxOF8yMDIxLCBGVU4gPSBzdW0pCmNsaW0ucHJlYy5tb250aGx5LjIwMThfMjAyMSA8LSBhZ2dyZWdhdGUoUlNLIH4gbW9udGgsIGRhdGEgPSBwcmVjLm1vbnRobHkuMjAxOF8yMDIxLCBGVU4gPSBtZWFuKQpsaW5lcyhjbGltLnByZWMubW9udGhseS4yMDE4XzIwMjEsCiAgICAgdHlwZSA9ICJsIiwKICAgICBjb2wgPSAicmVkIikKCgojIGFsbCB5ZWFycwpFcG90Lm1vbnRobHkgPC0gYWdncmVnYXRlKEVwb3QgfiBtb250aCt5ZWFyLCBkYXRhID0gZGF0YSwgRlVOID0gc3VtKQpjbGltLkVwb3QubW9udGhseSA8LSBhZ2dyZWdhdGUoRXBvdCB+IG1vbnRoLCBkYXRhID0gRXBvdC5tb250aGx5LCBGVU4gPSBtZWFuKQoKIyBwZXJpb2QgMjAxNC0yMDE3CkVwb3QubW9udGhseS4yMDE0XzIwMTcgPC0gYWdncmVnYXRlKEVwb3QgfiBtb250aCt5ZWFyLCBkYXRhID0gZGF0YV8yMDE0XzIwMTcsIEZVTiA9IHN1bSkKY2xpbS5FcG90Lm1vbnRobHkuMjAxNF8yMDE3IDwtIGFnZ3JlZ2F0ZShFcG90IH4gbW9udGgsIGRhdGEgPSBFcG90Lm1vbnRobHkuMjAxNF8yMDE3LCBGVU4gPSBtZWFuKQoKIyBwZXJpb2QgMjAxOC0yMDIxCkVwb3QubW9udGhseS4yMDE4XzIwMjEgPC0gYWdncmVnYXRlKEVwb3QgfiBtb250aCt5ZWFyLCBkYXRhID0gZGF0YV8yMDE4XzIwMjEsIEZVTiA9IHN1bSkKY2xpbS5FcG90Lm1vbnRobHkuMjAxOF8yMDIxIDwtIGFnZ3JlZ2F0ZShFcG90IH4gbW9udGgsIGRhdGEgPSBFcG90Lm1vbnRobHkuMjAxOF8yMDIxLCBGVU4gPSBtZWFuKQoKbGluZXMoY2xpbS5FcG90Lm1vbnRobHksCiAgICAgdHlwZSA9ICJsIiwKICAgICBsdHkgPSAiZGFzaGVkIikKbGluZXMoY2xpbS5FcG90Lm1vbnRobHkuMjAxNF8yMDE3LAogICAgIHR5cGUgPSAibCIsCiAgICAgY29sPSJibHVlIiwKICAgICBsdHkgPSAiZGFzaGVkIikKbGluZXMoY2xpbS5FcG90Lm1vbnRobHkuMjAxOF8yMDIxLAogICAgIHR5cGUgPSAibCIsCiAgICAgY29sPSJyZWQiLAogICAgIGx0eSA9ICJkYXNoZWQiKQoKbGVnZW5kKHggPSAidG9wbGVmdCIsICAgICAgICAgICMgUG9zaXRpb24KICAgICAgIGxlZ2VuZCA9IGMoInByZWNpcGl0YXRpb24iLCJFcG90IiwgImFsbCIsICIyMDE0LTIwMTciLCAiMjAxOC0yMDIxIiksICAjIExlZ2VuZCB0ZXh0cwogICAgICAgbHR5ID0gYygic29saWQiLCAiZGFzaGVkIiwgInNvbGlkIiwgInNvbGlkIiwic29saWQiKSwgIyBwb2ludCB0eXBlcwogICAgICAgY29sID0gYygiYmxhY2siLCAiYmxhY2siLCAiYmxhY2siLCAiYmx1ZSIsICJyZWQiKSwgIyBwb2ludCBjb2xvcnMKICAgICAgICkgCgpgYGAKClByZWNpcGl0YXRpb24gdmFyaWVzIG1vcmUgYmV0d2VlbiB0aGUgZm9jdXMgcGVyaW9kcyB0aGFuIHBvdGVudGlhbCBldmFwb3JhdGlvbi4gCgoKCiMjIyBXYXRlciBiYWxhbmNlLCBwZXIgaHlkcm9sb2dpY2FsIHllYXIKCndhdGVyIGRlZmljaXQgPSBwcmVjaXBpdGF0aW9uIC0gcG90ZW50aWFsIGV2YXBvcmF0aW9uCgpgYGB7cn0KcGxvdChoLmRhdGEkZGF0ZSwgaC5kYXRhJGRlZiwgCiMgICAgIHlsaW0gPSBjKC0yMDAsMjUwKSwKICAgICB4bGFiID0gIkRhdGUiLAogICAgIHlsYWIgPSAiUCAtIFBFVCBzaW5jZSBPY3QgMSBlYWNoIHllYXIiKQoKYGBgCgpJbiB0aGlzIHBsb3QsIGFsbCBoeWRyb2xvZ2ljYWwgeWVhcnMgYXJlIGNvbnNpZGVyZWQgc2VwYXJhdGVseS4gVGhlIHdhdGVyIGRlZmljaXQgaXMgc2V0IHRvIHplcm8gYXQgdGhlIGJlZ2lubmluZyBvZiBlYWNoIGh5ZHJvbG9naWNhbCB5ZWFyIChjb3JyZXNwb25kcyB0byB0aGUgZW5kIG9mIHRoZSB2ZWdldGF0aW9uIHBlcmlvZCkgYXQgT2N0IDEuIAoKV2Ugc2VlIHRoYXQgdGhlIHZhcmlhdGlvbiB3aXRoaW4gdGhlIHllYXJzIGluY3JlYXNlZCB3aXRoIHRpbWUuIAoKYGBge3J9CgpkZWYueWVhcmx5Lm1hdCA8LSBtYXRyaXgoaC5kYXRhJGRlZiwgbnJvdz0zNjUsIG5jb2w9bGVuZ3RoKHllYXJzKS0xICkKaC55ZWFycyA9IHllYXJzWy0xXQoKZGVmLm1pbi55ZWFyIDwtIGFwcGx5KGRlZi55ZWFybHkubWF0LDIsbWluKQpkZWYubWF4LnllYXIgPC0gYXBwbHkoZGVmLnllYXJseS5tYXQsMixtYXgpCmRlZi5yYW5nZS55ZWFyIDwtIGRlZi5tYXgueWVhciAtIGRlZi5taW4ueWVhcgpkZWYuc2QueWVhciA8LSBhcHBseShkZWYueWVhcmx5Lm1hdCwyLHNkKSAgCmRlZi5tZWFuLnllYXIgPC0gYXBwbHkoZGVmLnllYXJseS5tYXQsMixtZWFuKQoKCnBsb3QoeWVhcnNbMTpsZW5ndGgoeWVhcnMpLTFdLCBkZWYucmFuZ2UueWVhciwKICAgICB5bGFiPWMoIlJhbmdlIG9mIHdhdGVyIGF2YWlsYWJpbGl0eSIpLAogICAgIHhsYWI9YygiQ2FsZW5kYXIgeWVhciIpKSAgICAKCmluZC4yMDE0XzIwMjEgPSBjKDEwOjE3KQoKbG0uZGVmLnJhbmdlIDwtIGxtKGRlZi5yYW5nZS55ZWFyIH4geWVhcnNbMjpsZW5ndGgoeWVhcnMpXSkKKHN1bW1hcnkobG0uZGVmLnJhbmdlKSkKCmxtLmRlZi5zZCA8LSBsbShkZWYuc2QueWVhciB+IHllYXJzWzI6bGVuZ3RoKHllYXJzKV0pCihzdW1tYXJ5KGxtLmRlZi5zZCkpCgoKI3Bsb3QoeWVhcnNbMTpsZW5ndGgoeWVhcnMpLTFdLCBkZWYuc2QueWVhciwKIyAgICAgeWxhYj0idmFyaWF0aW9uIG9mIHdhdGVyIGF2YWlsYWJpbGl0eSIsCiMgICAgIHhsYWI9ImNhbGVuZGFyIHllYXIiKSAgICAKCiNwbG90KHllYXJzWzE6bGVuZ3RoKHllYXJzKS0xXSwgZGVmLm1lYW4ueWVhciwKIyAgICAgeWxhYj1jKCJtZWFuIGFubnVhbCB3YXRlciBkZWZpY2l0IiksCiMgICAgIHhsYWI9YygiY2FsZW5kYXIgeWVhciIpKSAgICAKCiNwbG90KHllYXJzWzE6bGVuZ3RoKHllYXJzKS0xXSwgZGVmLm1pbi55ZWFyLAojICAgICB5bGFiPWMoIm1pbmltdW0gd2F0ZXIgYXZhaWxhYmlsaXR5IiksCiMgICAgIHhsYWI9YygiY2FsZW5kYXIgeWVhciIpKQoKCiNwbG90KHllYXJzWzE6bGVuZ3RoKHllYXJzKS0xXSwgZGVmLm1heC55ZWFyLCAKIyAgICAgeWxhYj1jKCJtYXhpbXVtIHdhdGVyIGF2YWlsYWJpbGl0eSIpLAojICAgICB4bGFiPWMoImNhbGVuZGFyIHllYXIiKSkKCmBgYAoKVGhpcyBwbG90IHNob3dzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHllYXJseSBtYXhpbXVtIHN1cnBsdXMgYW5kIG1pbmltdW0gd2F0ZXIgZGVmaWNpdCwgY2FsbGVkICJyYW5nZSBpbiB3YXRlciBkZWZpY2l0IiAocG9zaXRpdmUgdmFsdWVzIG9mIHdhdGVyIGRlZmljaXQgYXJlIHN1cnBsdXMpLiBUaGUgcmFuZ2UgZGVjcmVhc2VzIHNpZ25pZmljYW50bHkgaW4gdGhlIHJlY2VudCB5ZWFycy4KCmBgYHtyfQpjbGltLmRlZiA8LSBhcHBseShkZWYueWVhcmx5Lm1hdCwxLG1lYW4pCgpjMjAxNF8yMDE3IDwtIHdoaWNoKGgueWVhcnM+PTIwMTQgJiBoLnllYXJzPD0yMDE3KQpjMjAxOF8yMDIxIDwtIHdoaWNoKGgueWVhcnM+PTIwMTggJiBoLnllYXJzPD0yMDIxKQoKaC5jbGltLmRhdGUgPSBoLmRhdGEkZGF0ZVsxOjM2NV0KY2xpbS5kZWYubWVhbi4yMDE0XzIwMTcgPC0gYXBwbHkoZGVmLnllYXJseS5tYXRbLGMyMDE0XzIwMTddLDEsbWVhbikKY2xpbS5kZWYubWluLjIwMTRfMjAxNyA8LSBhcHBseShkZWYueWVhcmx5Lm1hdFssYzIwMTRfMjAxN10sMSxtaW4pCmNsaW0uZGVmLm1heC4yMDE0XzIwMTcgPC0gYXBwbHkoZGVmLnllYXJseS5tYXRbLGMyMDE0XzIwMTddLDEsbWF4KQoKY2xpbS5kZWYubWVhbi4yMDE4XzIwMjEgPC0gYXBwbHkoZGVmLnllYXJseS5tYXRbLGMyMDE4XzIwMjFdLDEsbWVhbikKY2xpbS5kZWYubWF4LjIwMThfMjAyMSA8LSBhcHBseShkZWYueWVhcmx5Lm1hdFssYzIwMThfMjAyMV0sMSxtYXgpCmNsaW0uZGVmLm1pbi4yMDE4XzIwMjEgPC0gYXBwbHkoZGVmLnllYXJseS5tYXRbLGMyMDE4XzIwMjFdLDEsbWluKQoKCnBsb3QoaC5jbGltLmRhdGUsIGNsaW0uZGVmLAogICAgIHlsaW0gPSBjKC0xMDAsIDEwMCksCiAgICAgeGxhYiA9ICJEYXRlIiwKICAgICB5bGFiID0gIldhdGVyIGRlZmljaXQvc3VycGx1cyA9IFAtUEVUIGluIG1tIikKcG9pbnRzKGguY2xpbS5kYXRlLCBjbGltLmRlZi5tZWFuLjIwMTRfMjAxNywKICAgICAgIGNvbD0iYmx1ZSIpCnBvaW50cyhoLmNsaW0uZGF0ZSwgY2xpbS5kZWYubWVhbi4yMDE4XzIwMjEsCiAgICAgICBjb2w9InJlZCIpCmxlZ2VuZCh4ID0gInRvcGxlZnQiLCAgICAgICAgICAjIFBvc2l0aW9uCiAgICAgICBsZWdlbmQgPSBjKCJjbGltIiwgIjIwMTQtMjAxNyIsICIyMDE4LTIwMjEiKSwgICMgTGVnZW5kIHRleHRzCiAgICAgICBwY2ggPSBjKDEsIDE5LCAxOSksICMgcG9pbnQgdHlwZXMKICAgICAgIGNvbCA9IGMoImJsYWNrIiwgImJsdWUiLCAicmVkIiksICMgcG9pbnQgY29sb3JzCiAgICAgICApCgoKYGBgCgpXaGVuIGFnZ3JlYWdhdGluZyBvdmVyIHRoZSB0d28gcGVyaW9kcywgd2Ugc2VlIHRoZSBnZW5lcmFsIGR5bmFtaWNzLiBUaGVyZSBpcyBhIHN1cnBsdXMgb2Ygd2F0ZXIgaW4gdGhlIHdpbnRlciwgYmVjYXVzZSBFVCBpcyBsb3csIGFuZCBhIHNsaWdodCBkZWNyZWFzZSBpbiBzdW1tZXIsIHdoZW4gRVQgaXMgbGFyZ2VyLCBidXQgYWxzbyBQIGluY3JlYXNlcy4gVGhlIGF2ZXJnZSBtdWx0aWFubnVhbCBzdXJwbHVzIGlzIDI2NCBtbS95ZWFyISBUaGUgbW9zdCBzdHJpa2luZyBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGZpcnN0IGFuZCBzZWNvbmQgcGVyaW9kIGlzIHRoYXQgdGhlIG1ldCB3YXRlciBiYWxhbmNlIGluIDIwMTQtMjAxNyB3YXMgYWJvdmUgYXZlcmFnZSAoMzUzIG1tKS4KCgoKYGBge3J9CiNwbG90KGguY2xpbS5kYXRlLCBjbGltLmRlZiwKIyAgICAgeWxpbSA9IGMoLTEwMCwgMTUwKSwKIyAgICAgeGxhYiA9ICJkYXRlIiwKIyAgICAgeWxhYiA9ICJ3YXRlciBkZWZpY2l0IGluIFAtUEVUIGluIG1tIiwKIyAgICAgdHlwZSA9ICJsIikKI3BvbHlnb24oYyhoLmNsaW0uZGF0ZSksIHJldihoLmNsaW0uZGF0ZSksIAojICAgICAgICAgIGMoY2xpbS5kZWYubWF4LjIwMTRfMjAxNywgcmV2KGNsaW0uZGVmLm1pbi4yMDE0XzIwMTcpKSwKIyAgICAgICAgY29sID0gIiM2QkQ3QUYiKQoKZGF5cyA9IGMoMTozNjUpCmRheXNtb250aCA9IGMoMzEsMzAsMzEsMzEsMjgsMzEsMzAsMzEsMzAsMzEsMzEsMzApCm1vbnRocyA9IGMoIk9jdCIsIk5vdiIsIkRlYyIsIkphbiIsICJGZWIiLCAiTWFyIiwgIkFwciIsICJNYXkiLCAiSnVuIiwgIkp1bCIsICJBdWciLCAiU2VwIikKYXhpc3RpY2tzID0gYygzMS8yLGN1bXN1bShkYXlzbW9udGhbMToxMV0pICsgZGF5c21vbnRoWzI6MTJdLzIpCgpwbG90KGRheXMsIGNsaW0uZGVmLAogICAgeGF4dCA9ICJuIiAsCiAgICB5bGltID0gYygtMjAwLCA0MDApLAogICAgeGxpbSA9IGMoMCwzNjUpLAogICAgIHhsYWIgPSAiRGF0ZSIsCiAgICAgeWxhYiA9ICJXYXRlciBkZWZpY2l0IGluIFAtUEVUIGluIG1tIiwKICAgICB0eXBlID0gImwiKQpheGlzKDEsYXQgPSBheGlzdGlja3MsIGxhYmVscyA9IG1vbnRocykKcG9seWdvbihjKGRheXMsIHJldihkYXlzKSksIAogICAgICAgICAgYyhjbGltLmRlZi5tYXguMjAxNF8yMDE3LCByZXYoY2xpbS5kZWYubWluLjIwMTRfMjAxNykpLAogICAgICAgIGNvbCA9ICIjQUVENkYxQUEiKQpwb2x5Z29uKGMoZGF5cywgcmV2KGRheXMpKSwgCiAgICAgICAgICBjKGNsaW0uZGVmLm1heC4yMDE4XzIwMjEsIHJldihjbGltLmRlZi5taW4uMjAxOF8yMDIxKSksCiAgICAgICAgY29sID0gIiNGNUI3QjFBQSIpCgpgYGAKClNhbWUgcGxvdCBhcyBhYm92ZSwgc2hhZGluZyB0aGUgYmV0d2VlbiBtYXhpbXVtIGFuZCBtaW5pbXVtIG9mIHRoZSBwZXJpb2RzOiBCbHVlIGlzIDIwMTQtMjAxNywgcmVkIGlzIDIwMTgtMjAyMS4KCmBgYHtyfQoKRXBvdC55ZWFybHkubWF0IDwtIG1hdHJpeChoLmRhdGEkRXBvdCwgbnJvdz0zNjUsIG5jb2w9bGVuZ3RoKHllYXJzKS0xICkKUC55ZWFybHkubWF0IDwtIG1hdHJpeChoLmRhdGEkUlNLLCBucm93PTM2NSwgbmNvbD1sZW5ndGgoeWVhcnMpLTEgKQoKRXBvdC55ZWFybHkgPC0gYXBwbHkoRXBvdC55ZWFybHkubWF0LDIsc3VtKQpQLnllYXJseSA8LSBhcHBseShQLnllYXJseS5tYXQsMixzdW0pCgoobWVhbihFcG90LnllYXJseSkpCihtZWFuKFAueWVhcmx5KSkKCnBsb3QoaC55ZWFycywgUC55ZWFybHksCiAgICAgcGNoID0gMTksCiAgICAgeGxhYiA9ICJIeWRyb2xvZ2ljYWwgeWVhciAyMDE1LzE2IC0gMjAyMS8yMiIsCiAgICAgeWxpbSA9IGMoMCw5MDApLAogICAgIHlsYWIgPSAiRmx1eCBpbiBtbSAvIGh5ZHJvbG9naWNhbCB5ZWFyIikKcG9pbnRzKGgueWVhcnMsIEVwb3QueWVhcmx5LAogICAgICAgcGNoID0gMTksCiAgICAgICBjb2wgPSAicmVkIikKbGVnZW5kKHg9InRvcHJpZ2h0IiwKICAgICAgIGxlZ2VuZCA9IGMoInByZWNpcCIsICJFcG90IiksCiAgICAgICBwY2ggPSBjKDEsIDEpLAogICAgICAgY29sID0gYygiYmxhY2siLCAicmVkIikpCiAgICAgICAKCmxtLlAgPC0gbG0oUC55ZWFybHkgfiBoLnllYXJzKQooc3VtbWFyeShsbS5QKSkKCmxtLkVwb3QgPC0gbG0oRXBvdC55ZWFybHkgfiBoLnllYXJzKQooc3VtbWFyeShsbS5FcG90KSkKCgp0YWJsZV8zMjg5IDwtIGMoaC55ZWFycywgIFAueWVhcmx5LCBFcG90LnllYXJseSkKd3JpdGUuY3N2KHRhYmxlXzMyODksIGZpbGU9IlBfUEVUXzMweXJzXzMyODkuY3N2IikKCmBgYAoKQW5udWFsIFBFVCBzaWduaWZpY2FudGx5IGluY3JlYXNlcyBieSAxLjYgbW0gLyB5ZWFyIChkdWUgYm90aCB0aGUgYXZlcmFnZSB0ZW1wZXJhdHVyZSBpbmNyZWFzZSwgYW5kIGluY3JlYXNlIGluIGRhaWx5IHRlbXBlcmF0dXJlIHJhbmdlKS4gVGhlIGF2ZXJhZ2Ugd2FzIDY2MiBtbS4gUHJlY2lwaXRhdGlvbiBpcyBtb3JlIHZhcmlhYmxlIHRocm91Z2hvdXQgdGhlIHBlcmlvZCAxOTkyLTIwMjIuIFRoZSBhdmVyYWdlIHdhcyA2NzIgbW0sIG5vIHNpZ25pZmljYW50IGNoYW5nZXMuIAoKCmBgYHtyfQoKYGBgCgoKCmBgYHtyfQpkZWYueWVhcmx5IDwtIFAueWVhcmx5IC0gRXBvdC55ZWFybHkKcGxvdChoLnllYXJzLCBkZWYueWVhcmx5LAogICAgeGxhYiA9ICJIeWRyb2xvZ2ljYWwgeWVhciAxOTkxLzIgLSAyMDIxLzIyIiwKICAgIHlsYWIgPSAiV2F0ZXIgZGVmaWNpdCBvciBzdXJwbHVzIGluIG1tIC8gaHlkcm9sb2dpY2FsIHllYXIiLAogICAgbWFpbiA9ICJObyAzMjg5IFNjaG1pZXJpdHotV2VsdHdpdHoiKQoKbG0uZGVmLnllYXJseSA8LSBsbShkZWYueWVhcmx5IH4gaC55ZWFycykKKHN1bW1hcnkobG0uZGVmLnllYXJseSkpCmBgYAoKQWxzbyB0aGUgZGlmZmVyZW5jZSBvZiB0aGUgdHdvICh3aGljaCBpcyB0aGUgbWV0ZW9yb2xvZ2ljYWwgc3VycGx1cyB3aGVuIHBvc2l0aXZlIG9yIHdhdGVyIGRlZmljaXQgd2hlbiBuZWdhdGl2ZSkgYWxzbyBkZWNyZWFzZXMgc2lnbmlmaWNhbnRseSBieSA1LjYgbW0veWVhci4gCgpgYGB7cn0KcGxvdChQLnllYXJseSwgRXBvdC55ZWFybHksCiAgICAgeGxhYiA9ICJBbm51YWwgcHJlY2lwaXRhdGlvbiBpbiBtbSAvIGh5ZHJvbG9naWNhbCB5ZWFyIiwKICAgICB5bGFiID0gIkFubnVhbCBQRVQgaW4gbW0gLyBoeWRyb2xvZ2ljYWwgeWVhciIpCgpsbS5FcG90LlAgPC0gbG0oUC55ZWFybHkgfiBFcG90LnllYXJseSkKc3VtbWFyeShsbS5FcG90LlApCgpgYGAKClRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgcmVsYXRpb24gYmV0d2VlbiBwb3RlbnRpYWwgZXZhcG90cmFuc3BpcmF0aW9uIGFuZCBwcmVjaXBpdGF0aW9uIChjYWxjdWxhdGVkIG92ZXIgdGhlIGh5ZHJvbG9naWNhbCB5ZWFyKS4gVGhlIHBlYWsgb2YgdGhlIHByZWNpcGl0YXRpb24gaXMgaW4gc3VtbWVyLiBIZW5jZSwgd2hlbiBwcmVjaXBpdGF0aW9uIGlzIGhpZ2gsIHByb2JhYmx5IGNsb3VkaW5lc3MgaXMgaGlnaCBhbmQgdGVtcGVyYXR1cmVzIGxvd2VyLiBJbiBjb250cmFzdCwgd2hlbiBwcmVjaXBpdGF0aW9uIGlzIGxvdywgcmFpbmRheXMgbGVzcywgc3Vuc2hpbmUgaG91cnMgaW5jcmVhc2VkLCBhbHNvIHRoZSBwb3RlbnRpYWwgZXZhcG9yYXRpb24gaXMgaGlnaC4gVAoKCiMjIyBNdWx0aWFubnVhbCBjdW11bGF0aXZlIHdhdGVyIGRlZmljaXQKCk11bHRpYW5udWFsIHdhdGVyIGRlZmljaXQsIHN0YXJ0aW5nIHRoZSB3YXRlciBiYWxhbmNlIGluIE9jdGJlciAyMDA1IGFuZCAqKk5PVCoqIHJlc2V0dGluZyBlYWNoIHllYXIuIFRoZSBuZWdhdGl2ZSBudW1iZXJzIGNhbiBiZSBpbnRlcHJldGVkIGFzIHRoZSB3YXRlciBzdG9yYWdlIGluIHRoZSBzdWJzdXJmYWNlIHRoYXQgd291bGQgYmUgcmVxdWlyZWQgdG8gY29tcGVuc2F0ZSBmb3IgdGhlIGxhY2sgb2YgcHJlY2lwaXRhdGlvbi4gCgpgYGB7cn0KaC5kYXRhJGN1bWRlZiA8LSBjdW1zdW0oaC5kYXRhJFJTSyAtIGguZGF0YSRFcG90KSAjIGxvbmd0ZXJtIGN1bXVsYXRlZCB3YXRlciBkZWZpY2l0CgpwbG90KGguZGF0YSRkYXRlLCBoLmRhdGEkY3VtZGVmLCAKIyAgICAgeWxpbSA9IGMoLTIwMCwyNTApLAogICAgIHhsYWIgPSAiRGF0ZSIsCiAgICAgeWxhYiA9ICJQIC0gUEVUIHNpbmNlIE9jdCAxIDE5OTEgaW4gbW0iLAogICAgIG1haW4gPSAiTm8gMzI4OSBTY2htaWVyaXR6LVdlbHR3aXR6IikKYGBgCkhlcmUgd2UgYXJlIGxvb2tpbmcgYXQgdGhlIHN1cnBsdXMgYnVpbGRpbmcgdXAgb3ZlciBzZXZlcmFsIHllYXJzIHRoYW4gZGlzYXBwZWFyaW5nIGFnYWluLgoKYGBge3J9CgpoLmRhdGEkY3VtRXBvdCA8LSBjdW1zdW0oaC5kYXRhJEVwb3QpICMgbG9uZ3Rlcm0gY3VtdWxhdGVkIHdhdGVyIGRlZmljaXQKCgpwbG90KGguZGF0YSRkYXRlLCBjdW1zdW0oaC5kYXRhJFJTSyksIAogICAgIHlsaW0gPSBjKDAsMjUwMDApLAogICAgIHhsYWIgPSAiRGF0ZSIsCiAgICAgeWxhYiA9ICJDdW11bGFyZWQgZmx1eCBzaW5jZSBPY3QgMSAyMDA1IGluIG1tIikKcG9pbnRzKGguZGF0YSRkYXRlLCBjdW1zdW0oaC5kYXRhJEVwb3QpLCAKIyAgICAgeWxpbSA9IGMoLTIwMCwyNTApLAogICAgIHhsYWIgPSAiZGF0ZSIsCiAgICAgY29sID0gInJlZCIpCmxlZ2VuZCh4ID0gInRvcGxlZnQiLCAgICAgICAgICAjIFBvc2l0aW9uCiAgICAgICBsZWdlbmQgPSBjKCJwcmVjaXBpdGF0aW9uIiwgIkVwb3QiKSwgICMgTGVnZW5kIHRleHRzCiAgICAgICBwY2ggPSBjKDEsIDEpLAogICAgICAgY29sID0gYygiYmxhY2siLCAicmVkIikKICAgICAgICkgIyBwb2ludCBjb2xvcnMKCgpgYGAKClFRcGxvdC4KCmBgYHtyfQoKcS5wX2RhaWx5LmFsbCA8LSBxdWFudGlsZShkYXRhJFJTSywgc2VxKDAuMDI1LDEsMC4wMjUpKQpxLnBfZGFpbHkuMjAxNF8yMDE3IDwtIHF1YW50aWxlKGRhdGFfMjAxNF8yMDE3JFJTSywgc2VxKDAuMDI1LDEsMC4wMjUpKQpxLnBfZGFpbHkuMjAxOF8yMDIxIDwtIHF1YW50aWxlKGRhdGFfMjAxOF8yMDIxJFJTSywgc2VxKDAuMDI1LDEsMC4wMjUpKQoKcS5wX2RhaWx5LjIwMTZfMjAxOCA8LSBxdWFudGlsZShkYXRhXzIwMTZfMjAxOCAkUlNLLCBzZXEoMC4wMjUsMSwwLjAyNSkpCnEucF9kYWlseS4yMDE5XzIwMjEgPC0gcXVhbnRpbGUoZGF0YV8yMDE5XzIwMjEkUlNLLCBzZXEoMC4wMjUsMSwwLjAyNSkpCgoKcGxvdChxLnBfZGFpbHkuYWxsLCBxLnBfZGFpbHkuMjAxNF8yMDE3LCAKICAgICB4bGFiID0gIlF1YW50aWxlcyBvZiBkYWlseSBwcmVjaXBpdGF0aW9uIDIwMDUtMjAyMSIsCiAgICAgeWxhYiA9ICJRdWFudGlsZXMgb2YgZGFpbHkgcHJlY2lwaXRhdGlvbiBpbiB0aGUgb2JzZXJ2YXRpb24gcGVyaW9kIiwKICAgICB4bGltID0gYygwLDEwMCksCiAgICAgeWxpbSA9IGMoMCwxMDApKQpwb2ludHMocS5wX2RhaWx5LmFsbCwgcS5wX2RhaWx5LjIwMThfMjAyMSwgCiAgICAgICAgY29sID0gInJlZCIpCgphYmxpbmUoYT0wLCBiPTEsICc6JykKCnBsb3QocS5wX2RhaWx5LjIwMTRfMjAxNywgcS5wX2RhaWx5LjIwMThfMjAyMSwgCiAgICAgeWxpbSA9IGMoMCwxMDApLAogICAgIHhsYWIgPSAiUXVhbnRpbGVzIG9mIGRhaWx5IHByZWNpcGl0YXRpb24gMjAxNC0yMDE3IiwKICAgICB5bGFiID0gIlF1YW50aWxlcyBvZiBkYWlseSBwcmVjaXBpdGF0aW9uIDIwMTgtMjAyMSIpCmFibGluZShhPTAsIGI9MSwgJzonKQoKCnBsb3QocS5wX2RhaWx5LjIwMTZfMjAxOCwgcS5wX2RhaWx5LjIwMThfMjAyMSwgCiAgICAgeWxpbSA9IGMoMCwxMDApLAogICAgIHhsYWIgPSAiUXVhbnRpbGVzIG9mIGRhaWx5IHByZWNpcGl0YXRpb24gMjAxNi0yMDE4IiwKICAgICB5bGFiID0gIlF1YW50aWxlcyBvZiBkYWlseSBwcmVjaXBpdGF0aW9uIDIwMTktMjAyMSIpCmFibGluZShhPTAsIGI9MSwgJzonKQoKcGxvdChsb2cocS5wX2RhaWx5LjIwMTZfMjAxOCsxKSwgbG9nKHEucF9kYWlseS4yMDE4XzIwMjErMSksIAogICAgIHlsaW0gPSBjKDAsNCksCiAgICAgeGxpbSA9IGMoMCw0KSwKICAgICB4bGFiID0gImxvZyBvZiBRdWFudGlsZXMgb2YgZGFpbHkgcHJlY2lwaXRhdGlvbiAyMDE2LTIwMTgiLAogICAgIHlsYWIgPSAibG9nIFF1YW50aWxlcyBvZiBkYWlseSBwcmVjaXBpdGF0aW9uIDIwMTktMjAyMSIpCmFibGluZShhPTAsIGI9MSwgJzonKQoKClRhYmxlX1FQIDwtIGFzLmRhdGEuZnJhbWUoY2JpbmQoc2VxKDAuMDI1LDEsMC4wMjUpLCBxLnBfZGFpbHkuMjAxNl8yMDE4LCBxLnBfZGFpbHkuMjAxOF8yMDIxKSkKbmFtZXMoVGFibGVfUVApIDwtIGMoIlAiLCAiUVBfMjAxNl8yMDE4IiwgIlFQXzIwMTlfMjAyMSIpCgp3cml0ZS5jc3YoVGFibGVfUVAsICJUYWJsZV9RUF8zMjg5LmNzdiIpCgpgYGAKCiMjIE51bWJlciBvZiBkYXlzIHdpdGggZ2l2ZW4gcmFpbmZhbGwKCkNoZWNrIHdoZXRoZXIgY2VydGFpbiB0eXBlcyBvZiBkYWlseSBwcmVjaXBpdGF0aW9uIHdlcmUgbW9yZSBvciBsZXNzIGNvbW1vbiBhbG9uZyB0aGUgdGltZSBzZXJpZXMuIEZvciB0aGlzIEkgdXNlIHRoZSBlbnRpcmUgdGltZSBzZXJpZXMsIHRvIGJlIGFibGUgdG8gc2VlIHRyZW5kcyAoaWYgYXBwbGljYWJsZSkuCgpJIHdpbGwgdGVzdCBmb3IKCi0gbnVtYmVyIG9mIGRheXMgcGVyIHllYXIgd2l0aG91dCBwcmVjaXBpdGF0aW9uICh0aHJlc2hvbGQgMC4xIG1tKQoKLSBkYXlzIHN1cnBhc3Npbmcgc21hbGwgcHJlY2lwaXRhdGlvbiAodGhyZXNob2xkIHNldCB0byA1IG1tKQoKTG9va2luZyBmb3IgZXh0cmVtZSByYWluZmFsbCByZXF1aXJlcyBhIGRhdGFzZXQgaW4gaG91cmx5IG9yIHNpeCBob3VybHkgcmVzb2x1dGlvbiwgYW5kIGNhbm5vdCBiZSBkb25lIHVzaW5nIHRoaXMgZGFpbHkgZGF0YXNldC4gQnV0IHRoZSBkYXRhIGlzIGF2YWlsYWJsZSBmcm9tIERXRC4KCmBgYHtyfQojIGludGlhbGl6ZQpuZGF5cyA9IGFycmF5KGRhdGE9TkEsZGltID0gbnllYXJzLCBkaW1uYW1lcyA9IE5VTEwpCm5vcmFpbmRheXMgPSBhcnJheShkYXRhPU5BLGRpbSA9IG55ZWFycywgZGltbmFtZXMgPSBOVUxMKQpzdHJvbmdyYWluZGF5cyA9IGFycmF5KGRhdGE9TkEsZGltID0gbnllYXJzLCBkaW1uYW1lcyA9IE5VTEwpClAgPSBhcnJheShkYXRhPU5BLGRpbSA9IG55ZWFycywgZGltbmFtZXMgPSBOVUxMKQpQX3N0cm9uZyA9IGFycmF5KGRhdGE9TkEsZGltID0gbnllYXJzLCBkaW1uYW1lcyA9IE5VTEwpCgpQX3RocmVzaCA9IDUKCiNpPTEKZm9yIChpIGluIDE6bnllYXJzKSB7CmRhdGFfeXIgPSBzdWJzZXQoZGF0YSwgZm9ybWF0KGRhdGEkZGF0ZSwnJVknKSA9PSBhcy5jaGFyYWN0ZXIoeWVhcnNbaV0pKQpub3JhaW5kYXlzW2ldID0gbGVuZ3RoKHdoaWNoKGRhdGFfeXIkUlNLPDAuMSkpCnJhaW5kYXlzID0gbnJvdyhkYXRhX3lyKS1ub3JhaW5kYXlzCnN0cm9uZ3JhaW5kYXlzW2ldID0gbGVuZ3RoKHdoaWNoKGRhdGFfeXIkUlNLPlBfdGhyZXNoICkpClBbaV0gPC0gc3VtKGRhdGFfeXIkUlNLKQpQX3N0cm9uZ1tpXSA8LSBzdW0oZGF0YV95ciRSU0tbd2hpY2goZGF0YV95ciRSU0s+UF90aHJlc2ggKV0pCm5kYXlzW2ldID0gbnJvdyhkYXRhX3lyKQoKfQoKYGBgCgoKIyMjIyBBbm51YWwgcHJlY2lwaXRhdGlvbiB0aW1lIHNlcmllcwpgYGB7cn0KCnBhcihtZnJvdz1jKDEsMykpCnBsb3QoeWVhcnMsIFAsCiAgICAgeWxhYiA9ICJhbm51YWwgcHJlY3BpdGF0aW9uIGluIG1tL2EiLAogICAgIG1haW4gPSAiYWxsIGRheXMiKQoKcGxvdCh5ZWFycywgUC1QX3N0cm9uZywKICAgICB5bGFiID0gImFubnVhbCBwcmVjcGl0YXRpb24gPCA1IG1tIGluIG1tL2EiLAogICAgIG1haW4gPSAic21hbGwgcHJlY2lwaXRhdGlvbiIpCgpwbG90KHllYXJzLCBQX3N0cm9uZywKICAgICB5bGFiID0gImFubnVhbCBwcmVjcGl0YXRpb24gPiA1bW0gaW4gbW0vYSIsCiAgICAgbWFpbiA9ICJwcmVjaXBpdGF0aW9uID4gNSBtbS9kIikKCgpgYGAKCgpgYGB7cn0KbG0ucF95ciA8LWxtKFB+eWVhcnMpICMgYWxsIHllYXJzCnN1bW1hcnkobG0ucF95cikKCnlyc18yMDE0XzIwMjEgPSBjKDEwOjE3KQoKbG0ucF95ci4yMDE0XzIwMjEgPC1sbShQW3lyc18yMDE0XzIwMjFdfnllYXJzW3lyc18yMDE0XzIwMjFdKSAjIDIwMTQtMjAyMSBvbmx5CnN1bW1hcnkobG0ucF95ci4yMDE0XzIwMjEpCgpgYGAKCgpObyBvYnZpb3VzIHRlbXBvcmFsIHRyZW5kIGluIGFubnVhbCBwcmVjaXBpdGF0aW9uLgoKYGBge3J9ClBfd2VhayA8LSBQLVBfc3Ryb25nCmxtLnBfd2Vha195ciA8LWxtKFBfd2Vha355ZWFycykgIyBhbGwgeWVhcnMKc3VtbWFyeShsbS5wX3dlYWtfeXIpCgp5cnNfMjAxNF8yMDE4ID0gYygxMDoxNykKCmxtLnB3X2Vha195ci4yMDE0XzIwMjEgPC1sbShQX3dlYWtbeXJzXzIwMTRfMjAyMV1+eWVhcnNbeXJzXzIwMTRfMjAyMV0pICMgMjAxNC0yMDIxIG9ubHkKc3VtbWFyeShsbS5wd19lYWtfeXIuMjAxNF8yMDIxKQoKYGBgCkRlY3JlYXNlIG9mIGxvdyBpbnRlbnNpdHkgcHJlY2lwaXRhdGlvbiAoUDw1IG1tL2QpIHBhcnQgb2YgYW5udWFsIHByZWNpcGl0YXRpb24gb3ZlciB0aGUgZW50aXJlIHBlcmlvZCwgYnV0IG5vdCBzaWduaWZpY2FudCBvdmVyIHRoZSBzaG9ydGVyIHBlcmlvZC4KCgpgYGB7cn0KbG0ucF9zdHJvbmdfeXIgPC1sbShQX3N0cm9uZ355ZWFycykgIyBhbGwgeWVhcnMKc3VtbWFyeShsbS5wX3N0cm9uZ195cikKCnlyc18yMDE0XzIwMTggPSBjKDEwOjE3KQoKbG0ucF9zdHJvbmdfeXIuMjAxNF8yMDIxIDwtbG0oUF9zdHJvbmdbeXJzXzIwMTRfMjAyMV1+eWVhcnNbeXJzXzIwMTRfMjAyMV0pICMgMjAxNC0yMDIxIG9ubHkKc3VtbWFyeShsbS5wX3N0cm9uZ195ci4yMDE0XzIwMjEpCmBgYAoKCgpgYGB7cn0KcGxvdCh5ZWFycywgUF9zdHJvbmcvUCkKcGxvdCh5ZWFycywgc3Ryb25ncmFpbmRheXMvcmFpbmRheXMpCgoKc3VtbWFyeShsbShzdHJvbmdyYWluZGF5cyB+IHllYXJzKSkKc3VtbWFyeShsbShQX3N0cm9uZy9QfiB5ZWFycykpCnN1bW1hcnkobG0oUF93ZWFrL1B+IHllYXJzKSkKc3VtbWFyeShsbShQfiB5ZWFycykpCgoKYGBgCgoKIyMjIyBEYXlzIHBlciB5ZWFyIHdpdGhvdXQgcHJlY2lwaXRhdGlvbi4gCgpgYGB7cn0KcGxvdCh5ZWFycywgbm9yYWluZGF5cykKbG0ubm9yYWluIDwtIGxtKG5vcmFpbmRheXN+eWVhcnMpICMgYWxsIHllYXJzCnN1bW1hcnkobG0ubm9yYWluKQoKbG0ubm9yYWluLjIwMTRfMjAyMSA8LSBsbShub3JhaW5kYXlzW3lyc18yMDE0XzIwMThdfnllYXJzW3lyc18yMDE0XzIwMThdKSAjIGFsbCB5ZWFycwpzdW1tYXJ5KGxtLm5vcmFpbi4yMDE0XzIwMjEpCmBgYAoKIyMjIyBEYXlzIHdpdGggc29tZSByYWluCgpgYGB7cn0Kd2Vha3JhaW5kYXlzID0gcmFpbmRheXMgLSBzdHJvbmdyYWluZGF5cwpwbG90KHllYXJzLCB3ZWFrcmFpbmRheXMpCmxtLndlYWtyYWluIDwtIGxtKHdlYWtyYWluZGF5c355ZWFycykKc3VtbWFyeShsbS53ZWFrcmFpbikKYGBgCgojIyMjIERheXMgd2l0aCBzdWJzdGFudGlhbCByYWluCgpgYGB7cn0KcGxvdCh5ZWFycywgc3Ryb25ncmFpbmRheXMpCmxtLnN0cm9uZ3JhaW4gPC0gbG0oc3Ryb25ncmFpbmRheXN+eWVhcnMpCnN1bW1hcnkobG0uc3Ryb25ncmFpbikKCmBgYAoKCmBgYHtyfQp0YWJsZV9QRVRfUCA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKGgueWVhcnMsICBQLnllYXJseSwgRXBvdC55ZWFybHkpKQpjb2xuYW1lcyh0YWJsZV9QRVRfUCkgPC0gYygieWVhcnMiLCAiUCIsICJQRVQiKQp3cml0ZS5jc3YodGFibGVfUEVUX1AsIGZpbGU9IlBfUEVUXzE2eXJzXzMyODkuY3N2IikKClB0YWJsZSA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKHllYXJzLCBQLCBQLVBfc3Ryb25nLCBQX3N0cm9uZywgbm9yYWluZGF5cywgd2Vha3JhaW5kYXlzLCBzdHJvbmdyYWluZGF5cykpCgpjb2xuYW1lcyhQdGFibGUpIDwtIGMoInllYXIiLCAiUCIsIlBfc21hbGwiLCAiUF9zdWJzdCIsICJuZGF5c19ub3JhaW4iLCJuZGF5c193ZWFrcmFpbiIsIm5kYXlzX3N1YnN0cmFpbiIpCndyaXRlLmNzdihQdGFibGUsIGZpbGUgPC0gIlB0YWJsZV8xNnlyc18zMjg5LmNzdiIpCgpgYGAKCgoKCgoK