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 6305 Mühlhausen/Thüringen-Görmar (01.12.2004 - current) Kläranlage

filename_mhlsn = "tageswerte_KL_06305_20041201_20221231_hist/produkt_klima_tag_20041201_20221231_06305.txt" # Mühlhausen - nearest dwd precip station
There were 20 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:19] 31 365 365 365 366 365 365 365 366 365 ...
  values : chr [1:19] "2004" "2005" "2006" "2007" "2008" "2009" "2010" "2011" "2012" "2013" "2014" "2015" "2016" ...

Select only a subset of years: 2005 - 2021 (will yields 16 hydrological years). 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)
days_per_year[[1]]
 [1] 365 365 365 366 365 365 365 366 365 365 365 366 365 365 365 366 365
nyears = length(years)

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, no missing values
integer(0)
(a <- which(data$TXK == -999)) # daily max temp, no missing values
integer(0)
(a <- which(data$TNK == -999)) # daily min temp, no missing values
integer(0)
#(a <- which(data$SDK == -999)) # daily sunshine duration, no missing values
#a <- which(data$NM == -999) # daily cloudcover, very many missing values, dó not use this

(b <- which(data$RSK == -999)) # daily precipitation duration, one missing value. Replace with zero
[1] 5671
data$date[b]
[1] "2020-07-15"
data$RSK[b] <- 0

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)-1]

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 changed between

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),] 

# 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.4079412  0.4441176  2.0923529 
(quantile(T.clim.2018_2021$TMK-T.clim$TMK, c(0.1,0.5,0.9)))
       10%        50%        90% 
-1.2870588  0.5073529  2.4188235 
# temperature anomalies
data$Tclim <- NA
ind <- which(data$year>2004)
data$Tclim[ind] <- rep(T.clim$TMK,length(ind)/365) 
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 
-16.5431  -2.2387   0.0319   2.3763  11.4615 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)      -1.100e+02  1.855e+01  -5.929 3.22e-09 ***
as.numeric(year)  5.465e-02  9.217e-03   5.929 3.21e-09 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 3.557 on 6203 degrees of freedom
Multiple R-squared:  0.005635,  Adjusted R-squared:  0.005475 
F-statistic: 35.15 on 1 and 6203 DF,  p-value: 3.215e-09

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
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
DeltaT.clim.2018_2021 <- aggregate(DeltaT ~ day+month, data = data_2018_2021, FUN = mean)
points(DeltaT.clim.2018_2021$DeltaT, col="red")


bins = seq(1,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)

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
       )           


#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_6305.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)
# 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,100),
     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 )
data length [5475] is not a sub-multiple or multiple of the number of columns [16]
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 <- which(h.years>=2014 & h.years<=2017)

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 
-82.504 -32.596  -4.361  20.374 143.675 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)
(Intercept)            -8581.370   6188.733  -1.387    0.187
years[2:length(years)]     4.372      3.074   1.422    0.177

Residual standard error: 56.67 on 14 degrees of freedom
Multiple R-squared:  0.1263,    Adjusted R-squared:  0.06385 
F-statistic: 2.023 on 1 and 14 DF,  p-value: 0.1768
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 
-28.995 -12.252  -5.939   9.934  51.333 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)
(Intercept)            -2051.748   2272.299  -0.903    0.382
years[2:length(years)]     1.049      1.129   0.930    0.368

Residual standard error: 20.81 on 14 degrees of freedom
Multiple R-squared:  0.05817,   Adjusted R-squared:  -0.009108 
F-statistic: 0.8646 on 1 and 14 DF,  p-value: 0.3682
#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 increases in the recent years, and arguably the variation in the water balance as well. The increase is not significant however.

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, 150),
     xlab = "Date",
     ylab = "Water deficit in 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 negative balance in summer, whhn ET is larger. The most striking difference between the first and second period is that the surplus in winter is smaller in the second period. The deficit does not necessarily develop earlier in summer though (the red curve is still positive in July, while the blue one is already negative at this point).

#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, 200),
    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.

There were 28 warnings (use warnings() to see them)
Epot.yearly.mat <- matrix(h.data$Epot, nrow=365, ncol=length(years)-1 )
data length [5475] is not a sub-multiple or multiple of the number of columns [16]
P.yearly.mat <- matrix(h.data$RSK, nrow=365, ncol=length(years)-1 )
data length [5475] is not a sub-multiple or multiple of the number of columns [16]
Epot.yearly <- apply(Epot.yearly.mat,2,sum)
P.yearly <- apply(P.yearly.mat,2,sum)

(mean(Epot.yearly))
[1] 547.6599
(mean(P.yearly))
[1] 502.55
plot(h.years, P.yearly,
     pch = 19,
     xlab = "Hydrological year 2005/06 - 2020/21",
     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 
-96.74 -71.16 -22.68  76.34 135.55 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept) 8772.113   8730.571   1.005    0.332
h.years       -4.107      4.336  -0.947    0.360

Residual standard error: 79.95 on 14 degrees of freedom
Multiple R-squared:  0.06023,   Adjusted R-squared:  -0.006902 
F-statistic: 0.8972 on 1 and 14 DF,  p-value: 0.3596
lm.Epot <- lm(Epot.yearly ~ h.years)
(summary(lm.Epot))

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

Residuals:
    Min      1Q  Median      3Q     Max 
-34.560 -11.125  -0.157  14.449  45.870 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept) -3965.249   2264.320  -1.751   0.1018  
h.years         2.241      1.125   1.993   0.0661 .
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 20.74 on 14 degrees of freedom
Multiple R-squared:  0.221, Adjusted R-squared:  0.1654 
F-statistic: 3.972 on 1 and 14 DF,  p-value: 0.06612

Annual PET slightly increases (due both the average temperature increase, and increase in daily temperature range) not significantly, but with the trend. The average was 548 mm. Precipitation is more variable throughout the period 2005/6-2021/22. The average was 501 mm there was no trend.

def.yearly <- P.yearly - Epot.yearly
Error: object 'P.yearly' not found

Also the difference of the two (which is the water deficit) does not give a significant relation. Overall, since the hydrological year 2017/18 the water deficit has not been positive, therefore adding up to a substantial water deficit at the end of 2021 seen below.

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 
-96.14 -46.27 -21.75  43.70 155.65 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept) 1583.6581   425.2127   3.724  0.00227 **
Epot.yearly   -1.9741     0.7758  -2.545  0.02336 * 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 68.2 on 14 degrees of freedom
Multiple R-squared:  0.3162,    Adjusted R-squared:  0.2674 
F-statistic: 6.475 on 1 and 14 DF,  p-value: 0.02336

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. The combination leads to a substantial build up of water deficit that cannot be cured with one good year of precipitation.

Multiannual cumulative water deficit

Most impressive is the 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 2005 in mm",
     main = "No 6305 Muehlhausen")

Here we are looking at the deficit building up over several years. Note this was calculated using the potential evapotranspiration, not the real one. Regardless, the meteolorogical water deficit defenitiely built up, specifically since 2014. While the water deficit was rather balanced until the year 2014, the meteorological water balance went strongly negative since 2015, with some recovery in spring 2018 and an even stronger drop in summer 2018. The deficit at the end of 2021 corresponds roughly to one year of precipitation.


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


plot(h.data$date, cumsum(h.data$RSK), 
     ylim = c(0,9500),
     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

The precipitation and potential evaporation were almost equal until roughly 2015, when they started to deviate for several years in a row. The plot shows that the discrepancy built up since 2015, but was much more pronounced after 2018.

Precipitation analysis

QQplot.


q.p_daily.all <- quantile(data$RSK, seq(0.025,1,0.025))
q.p_daily.2014_2017 <- quantile(data_2014_2017$RSK, seq(0.025,1,0.025))
q.p_daily.2018_2021 <- quantile(data_2018_2021$RSK, seq(0.025,1,0.025))

plot(q.p_daily.all, q.p_daily.2014_2017, 
     xlab = "Quantiles of daily precipitation 2005-2021",
     ylab = "Quantiles of daily precipitation in the observation period",
     xlim = c(0,100),
     ylim = c(0,100))
points(q.p_daily.all, q.p_daily.2018_2021, 
        col = "red")

abline(a=0, b=1, ':')
NAs introduced by coercion

plot(log(q.p_daily.2014_2017+1), log(q.p_daily.2018_2021+1), 
     ylim = c(0,3),
     xlim = c(0,3),
     xlab = "Quantiles of daily precipitation 2014-2017",
     ylab = "Quantiles of daily precipitation 2018-2021")
abline(a=0, b=1, ':')
NAs introduced by coercion

Table_QP <- as.data.frame(cbind(seq(0.025,1,0.025), q.p_daily.2014_2017, q.p_daily.2018_2021))
names(Table_QP) <- c("P", "QP_2014_2017", "QP_2018_2021")

write.csv(Table_QP, "Table_QP_6305.csv")

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 
-139.367  -65.589   -7.811   50.507  155.185 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept) 7431.272   8308.957   0.894    0.385
years         -3.441      4.128  -0.834    0.418

Residual standard error: 83.37 on 15 degrees of freedom
Multiple R-squared:  0.04427,   Adjusted R-squared:  -0.01944 
F-statistic: 0.6948 on 1 and 15 DF,  p-value: 0.4176
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 
-133.244  -27.769    5.306   32.660  122.169 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)
(Intercept)           -755.3821 24724.7872  -0.031    0.977
years[yrs_2014_2021]     0.6131    12.2552   0.050    0.962

Residual standard error: 79.42 on 6 degrees of freedom
Multiple R-squared:  0.000417,  Adjusted R-squared:  -0.1662 
F-statistic: 0.002503 on 1 and 6 DF,  p-value: 0.9617

No obvious temporal trend in annual precipitation.

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

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

Residuals:
      Min        1Q    Median        3Q       Max 
-0.092882 -0.047994 -0.002891  0.039094  0.158030 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept)  7.420787   6.861925   1.081    0.297
years       -0.003494   0.003409  -1.025    0.322

Residual standard error: 0.06885 on 15 degrees of freedom
Multiple R-squared:  0.06546,   Adjusted R-squared:  0.00316 
F-statistic: 1.051 on 1 and 15 DF,  p-value: 0.3216
lm.weak_raindays <-lm(weakraindays~years) # all years
summary(lm.weak_raindays)

Call:
lm(formula = weakraindays ~ years)

Residuals:
    Min      1Q  Median      3Q     Max 
-16.029  -6.824  -3.618   8.147  17.559 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept) 2565.5000  1057.7118   2.426   0.0284 *
years         -1.2059     0.5254  -2.295   0.0366 *
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 10.61 on 15 degrees of freedom
Multiple R-squared:  0.2599,    Adjusted R-squared:  0.2105 
F-statistic: 5.267 on 1 and 15 DF,  p-value: 0.03658
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 
-33.168 -15.161  -8.182  17.986  35.904 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)
(Intercept)          4647.496   8238.362   0.564    0.593
years[yrs_2014_2021]   -2.214      4.083  -0.542    0.607

Residual standard error: 26.46 on 6 degrees of freedom
Multiple R-squared:  0.04672,   Adjusted R-squared:  -0.1122 
F-statistic: 0.294 on 1 and 6 DF,  p-value: 0.6072

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 
-127.52  -54.25   18.68   28.69  148.96 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept) 1770.0581  7998.7252   0.221    0.828
years         -0.7238     3.9735  -0.182    0.858

Residual standard error: 80.26 on 15 degrees of freedom
Multiple R-squared:  0.002207,  Adjusted R-squared:  -0.06431 
F-statistic: 0.03318 on 1 and 15 DF,  p-value: 0.8579
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 
-100.076  -34.065    3.583   30.440   90.651 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)
(Intercept)          -5402.879  19812.165  -0.273    0.794
years[yrs_2014_2021]     2.827      9.820   0.288    0.783

Residual standard error: 63.64 on 6 degrees of freedom
Multiple R-squared:  0.01363,   Adjusted R-squared:  -0.1508 
F-statistic: 0.0829 on 1 and 6 DF,  p-value: 0.7831
plot(years, P_strong/P)
There were 25 warnings (use warnings() to see them)

plot(years, strongraindays/raindays)


summary(lm(P_strong/P~years))

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

Residuals:
      Min        1Q    Median        3Q       Max 
-0.158030 -0.039094  0.002891  0.047994  0.092882 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept) -6.420787   6.861925  -0.936    0.364
years        0.003494   0.003409   1.025    0.322

Residual standard error: 0.06885 on 15 degrees of freedom
Multiple R-squared:  0.06546,   Adjusted R-squared:  0.00316 
F-statistic: 1.051 on 1 and 15 DF,  p-value: 0.3216
summary(lm(strongraindays/raindays~years))

Call:
lm(formula = strongraindays/raindays ~ years)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.058075 -0.026681  0.001203  0.018081  0.061480 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept) -2.547222   3.582053  -0.711    0.488
years        0.001356   0.001779   0.762    0.458

Residual standard error: 0.03594 on 15 degrees of freedom
Multiple R-squared:  0.03728,   Adjusted R-squared:  -0.0269 
F-statistic: 0.5809 on 1 and 15 DF,  p-value: 0.4578

Days per year without precipitation.

summary(lm.norain)

Call:
lm(formula = noraindays ~ years)

Residuals:
    Min      1Q  Median      3Q     Max 
-16.360 -10.135  -2.973   5.703  26.091 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)  
(Intercept) -2206.8309  1281.8557  -1.722   0.1057  
years           1.1936     0.6368   1.874   0.0805 .
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 12.86 on 15 degrees of freedom
Multiple R-squared:  0.1898,    Adjusted R-squared:  0.1358 
F-statistic: 3.514 on 1 and 15 DF,  p-value: 0.08048

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 
-16.029  -6.824  -3.618   8.147  17.559 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept) 2565.5000  1057.7118   2.426   0.0284 *
years         -1.2059     0.5254  -2.295   0.0366 *
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 10.61 on 15 degrees of freedom
Multiple R-squared:  0.2599,    Adjusted R-squared:  0.2105 
F-statistic: 5.267 on 1 and 15 DF,  p-value: 0.03658

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.061  -4.902  -1.073   4.951  12.049 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept)   6.33088  715.85100   0.009    0.993
years         0.01225    0.35561   0.034    0.973

Residual standard error: 7.183 on 15 degrees of freedom
Multiple R-squared:  7.917e-05, Adjusted R-squared:  -0.06658 
F-statistic: 0.001188 on 1 and 15 DF,  p-value: 0.973
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_6305.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_6305.csv")
LS0tCnRpdGxlOiAiSGFpbmljaCBUZW1wZXJhdHVyZSAvIFdhdGVyIGJhbGFuY2UgYW5hbHlzaXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClVzZSBkYWlseSBjbGltYXRlIHN0YXRpb24gdGltZSBzZXJpZXMgZnJvbSBEV0QsIGRvd25sb2FkZWQgaGVyZToKaHR0cHM6Ly9vcGVuZGF0YS5kd2QuZGUvY2xpbWF0ZV9lbnZpcm9ubWVudC9DREMvb2JzZXJ2YXRpb25zX2dlcm1hbnkvY2xpbWF0ZS9kYWlseS9rbC9oaXN0b3JpY2FsLwoKQ2hvc2Ugc3RhdGlvbnMKLSBObyA2MzA1IE3DvGhsaGF1c2VuL1Row7xyaW5nZW4tR8O2cm1hciAoMDEuMTIuMjAwNCAtIGN1cnJlbnQpIEtsw6RyYW5sYWdlCgoKYGBge3J9CmZpbGVuYW1lX21obHNuID0gInRhZ2Vzd2VydGVfS0xfMDYzMDVfMjAwNDEyMDFfMjAyMjEyMzFfaGlzdC9wcm9kdWt0X2tsaW1hX3RhZ18yMDA0MTIwMV8yMDIyMTIzMV8wNjMwNS50eHQiICMgTcO8aGxoYXVzZW4gLSBuZWFyZXN0IGR3ZCBwcmVjaXAgc3RhdGlvbgpkYXRhPXJlYWQuY3N2KGZpbGVuYW1lX21obHNuLCBoZWFkZXIgPSBUUlVFLCBzZXA9IjsiKQpMYXRfZGF0YSA8LSA1MS4yMDYxIyBsYXRpdHVkZSBvZiB0aGUgY2xpbWF0ZSBzdGF0aW9uLCB0YWtlbiBmcm9tIERXRCBtZXRhZGF0YQoKYGBgCgpDaGVjayB3aGljaCBwZXJpb2QgaXMgY292ZXJlZCwgd2hldGhlciB5ZWFycyBhcmUgY29tcGxldGUKCmBgYHtyfQoKZGF0YSRkYXRlIDwtIGFzLkRhdGUoYXMuY2hhcmFjdGVyKGRhdGEkTUVTU19EQVRVTSksZm9ybWF0PSclWSVtJWQnKQp5ZWFycyA8LSBhcy5udW1lcmljKHVuaXF1ZShmb3JtYXQoZGF0YSRkYXRlLCclWScpKSkKCmRhdGEkeWVhciA8LSBmb3JtYXQoZGF0YSRkYXRlLCclWScpCmRhdGEkbW9udGggPC0gZm9ybWF0KGRhdGEkZGF0ZSwnJW0nKQpkYXRhJGRheW1vbnRoIDwtIGZvcm1hdChkYXRhJGRhdGUsJyVkJW0nKQpkYXRhJGRheSA8LSBmb3JtYXQoZGF0YSRkYXRlLCclZCcpCgooZGF5c19wZXJfeWVhciA8LSBybGUoZGF0YSR5ZWFyKSkKCmBgYAoKU2VsZWN0IG9ubHkgYSBzdWJzZXQgb2YgeWVhcnM6IDIwMDUgLSAyMDIxICh3aWxsIHlpZWxkcyAxNiBoeWRyb2xvZ2ljYWwgeWVhcnMpLiBJbmNpZGVudGFsbHksIGl0IGNvdmVycyAyMDE0LTIwMjEgKDggeWVhcnMpLCBhbmQgdGhlIHByZWNlZGluZyA4IHllYXJzLgoKYGBge3J9CmRhdGEgPSBzdWJzZXQoZGF0YSwgKCh5ZWFyID49IDIwMDUpICYgKHllYXI8PSAyMDIxKSkpCnllYXJzIDwtIGFzLm51bWVyaWModW5pcXVlKGZvcm1hdChkYXRhJGRhdGUsJyVZJykpKQoobnllYXJzID0gbGVuZ3RoKHllYXJzKSkKZGF5c19wZXJfeWVhciA8LSBybGUoZGF0YSR5ZWFyKQpkYXlzX3Blcl95ZWFyW1sxXV0KYGBgCgoKYGBge3J9Cm55ZWFycyA9IGxlbmd0aCh5ZWFycykKYGBgCgpyZW1vdmUgRmViIDI5CgpgYGB7cn0KaW5kX2ZlYjI5PC13aGljaChhcy5jaGFyYWN0ZXIoZGF0YSRkYXRlLCclZCVtJykgPT0gYygiMjkwMiIpKQpkYXRhPC1kYXRhWy1pbmRfZmViMjksXQpgYGAKCkNoZWNrIHdoZXRoZXIgdGhlcmUgYXJlIGFueSBtaXNzaW5nIGRhdGEgdGhhdCBuZWVkIHRvIGJlIHRha2VuIGNhcmUgb2YKYGBge3J9CihhIDwtIHdoaWNoKGRhdGEkVE1LID09IC05OTkpKSAjIGRhaWx5IG1lYW4gdGVtcCwgbm8gbWlzc2luZyB2YWx1ZXMKKGEgPC0gd2hpY2goZGF0YSRUWEsgPT0gLTk5OSkpICMgZGFpbHkgbWF4IHRlbXAsIG5vIG1pc3NpbmcgdmFsdWVzCihhIDwtIHdoaWNoKGRhdGEkVE5LID09IC05OTkpKSAjIGRhaWx5IG1pbiB0ZW1wLCBubyBtaXNzaW5nIHZhbHVlcwoKIyhhIDwtIHdoaWNoKGRhdGEkU0RLID09IC05OTkpKSAjIGRhaWx5IHN1bnNoaW5lIGR1cmF0aW9uLCBubyBtaXNzaW5nIHZhbHVlcwojYSA8LSB3aGljaChkYXRhJE5NID09IC05OTkpICMgZGFpbHkgY2xvdWRjb3ZlciwgdmVyeSBtYW55IG1pc3NpbmcgdmFsdWVzLCBkw7Mgbm90IHVzZSB0aGlzCgooYiA8LSB3aGljaChkYXRhJFJTSyA9PSAtOTk5KSkgIyBkYWlseSBwcmVjaXBpdGF0aW9uIGR1cmF0aW9uLCBvbmUgbWlzc2luZyB2YWx1ZS4gUmVwbGFjZSB3aXRoIHplcm8KZGF0YSRkYXRlW2JdCmRhdGEkUlNLW2JdIDwtIDAKCmBgYAoKCgpBZGQgYSBjb2x1bW4gaW5kaWNhdGluZyB0aGUgZGFpbHkgZGlmZmVyZW5jZSBiZXR3ZWVuIG1pbmltdW0gYW5kIG1heGltdW0gdGVtcGVyYXR1cmUuIFRoaXMgaXMgYSBtZWFzdXJlIGZvciB0aGUgcG90ZW50aWFsIGV2YXBvdHJhbnNwaXJhdGlvbi4KCmBgYHtyfQpkYXRhJERlbHRhVCA8LSBkYXRhJFRYSyAtIGRhdGEkVE1LCmBgYAoKIyMjIENhbGN1bGF0aW9uIG9mIHRoZSBoeWRyb2xvZ2ljYWwgdmFyaWFibGVzCiMjIyMgUG90ZW50aWFsIEVUCgpDYWxjdWxhdGlvbiwgdGFraW5nIHRoZSBlcXVhdGlvbiBvZiBIYXJncmVhdmVzLVNhbWFuaSAoMTk4NSksIHNlZSByZXZpZXcgYnkgSGFyZ3JlYXZlcyBhbmQgQWxsZW4gKDIwMDMpLiBUaGlzIHRha2VzIGEgYml0LgoKYGBge3J9CmxpYnJhcnkoc2lyYWQpCgphIDwtIGV4dHJhdChkYXlPZlllYXIoZGF0YSRkYXRlKSwgTGF0X2RhdGEpICMgY2FsY3VsYXRlIGV4dHJhdGVycmVzdHJpYWwgcmFkaWF0aW9uIGZvciB0aGUgc3BlY2lmaWMgZGF5IGFuZCBsYXRpdHVkZQpkYXRhJFJhIDwtIGFbWzFdXQpkYXRhJGxFcG90IDwtIDAuMDAyMyAqIGRhdGEkUmEgKiAoZGF0YSRUTUsgKyAxNy44KSAqIHNxcnQoZGF0YSREZWx0YVQpICMgY2FsY3VsYXRlIHBvdGVudGlhbCBsYXRlbnQgaGVhdCBmbHV4IGluIE1KL20yZApkYXRhJEVwb3QgPC0gKGRhdGEkbEVwb3QvMi41ZTYpKjFlNiMgY2FsY3VsYXRlIHBvdGVudGlhbCBFVCBpbiBtbS9kIGFzc3VtZSBsYXRlbnQgaGVhdCBvZiBldmFwb3JhdGlvbiBsID0gMi41ZTYgSi9rZyBhbmQgZGVuc2l0eSBvZiB3YXRlciBvZiAxMDAwIGtnL20zCgpgYGAKCiMjIyMgQXRtb3NwaGVyaWMgd2F0ZXIgZGVmaWNpdAoKVGhlIHdhdGVyIGRlZmljaXQgY2FuIGVpdGhlciBiZSBjYWxjdWxhdGVkIG92ZXIgZWFjaCB0aGUgaHlkcm9sb2dpY2FsIHllYXIgKE9jdG9iZXIgLSBTZXB0ZW1iZXIpIHNlcGFyYXRlbHkgb3Igb3ZlciB0aGUgZW50aXJlIHBlcmlvZC4gCgojIyMjIyBvdmVyIGVhY2ggaHlkcm9sb2dpY2FsIHllYXIgc2VwYXJhdGVseQoKYGBge3J9Cmh5ZHJvLnN0YXJ0eWVhciA9IHllYXJzWzFdCmh5ZHJvLmVuZHllYXIgPSB5ZWFyc1tsZW5ndGgoeWVhcnMpLTFdCgpoeWRyby5zdGFydGRhdGUgPSBhcy5EYXRlKHBhc3RlKGh5ZHJvLnN0YXJ0eWVhciwiMTAiLCIwMSIsIHNlcD0iLSIpLCAiJVktJW0tJWQiKQpoeWRyby5lbmRkYXRlID0gYXMuRGF0ZShwYXN0ZShoeWRyby5lbmR5ZWFyLCIwOSIsIjMwIiwgc2VwPSItIiksICIlWS0lbS0lZCIpCgojaHlkcm8uc3RhcnRkYXRlID0gYXMuUE9TSVhsdChwYXN0ZShoeWRyby5zdGFydHllYXIsIjEwIiwiMDEiLCBzZXA9Ii0iKSwgIiVZLSVtLSVkIikKI2h5ZHJvLmVuZGRhdGUgPSBhcy5QT1NJWGx0KHBhc3RlKGh5ZHJvLmVuZHllYXIsIjA5IiwiMzAiLCBzZXA9Ii0iKSwgIiVZLSVtLSVkIikKCmguZGF0YSA8LSBzdWJzZXQuZGF0YS5mcmFtZShkYXRhLCAoZGF0ZSA+PSBoeWRyby5zdGFydGRhdGUgJiBkYXRlIDw9IGh5ZHJvLmVuZGRhdGUpKQoKYGBgCgoKCmBgYHtyfQpoLmRhdGEkZGVmIDwtIE5BCgoKZm9yICh5ZWFyIGluIHllYXJzWzE6bGVuZ3RoKHllYXJzKS0xXSkgewogICAgICAgIHN0YXJ0ZGF5ID0gYXMuRGF0ZShwYXN0ZSh5ZWFyLCIxMCIsIjAxIiwgc2VwPSItIiksICIlWS0lbS0lZCIpCiAgICAgICAgZW5kZGF5ID0gYXMuRGF0ZShwYXN0ZSh5ZWFyKzEsIjA5IiwiMzAiLCBzZXA9Ii0iKSwgIiVZLSVtLSVkIikKICAgICAgICBpbmQudGhpc3llYXIgPC0gd2hpY2goaC5kYXRhJGRhdGUgPj0gc3RhcnRkYXkgJiBoLmRhdGEkZGF0ZSA8PSBlbmRkYXkpCiAgICAgICAgaC5kYXRhJGRlZltpbmQudGhpc3llYXJdIDwtIGN1bXN1bShoLmRhdGEkUlNLW2luZC50aGlzeWVhcl0taC5kYXRhJEVwb3RbaW5kLnRoaXN5ZWFyXSkgCiAKICAgICAgICAKfQpgYGAKCgojIyBCYXNpYyBmZWF0dXJlcyBvZiB0aGUgdGVtcGVyYXR1cmUgZGF0YXNldAoKQ2hlY2sgd2hldGhlciB0aGUgZGlzdHJpYnV0aW9uIG9mIHJhaW5mYWxsIGNoYW5nZWQgYmV0d2VlbiAKCiogMjAxNC0yMDE3IGFuZCAKCiogMjAxOC0yMDIxLiAKCkZvciBvcmllbnRhdGlvbiBwbG90IHRoZSBkYXlsaXkgY2xpbWF0b2xvZ3kgb3ZlciB0aGUgZW50aXJlIHRpbWVzZXJpZXMsIDIwMDUtMjAyMgoKYGBge3J9CiMgc3Vic2V0IGZvciBwZXJpb2RzCmRhdGFfMjAxNF8yMDE3IDwtIGRhdGFbd2hpY2goZGF0YSR5ZWFyPj0yMDE0ICYgZGF0YSR5ZWFyPD0yMDE3KSxdIApkYXRhXzIwMThfMjAyMSA8LSBkYXRhW3doaWNoKGRhdGEkeWVhcj49MjAxOCAmIGRhdGEkeWVhcjw9MjAyMSksXSAKCiMgY2xpbWF0b2xvZ3kgb3ZlciB0aGUgZW50aXJlIHRpbWUgc2VyaWVzClQuY2xpbSA8LSBhZ2dyZWdhdGUoVE1LIH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YSwgRlVOID0gbWVhbikKcGxvdChULmNsaW0kVE1LLCB5bGltID0gYygtNywgMjgpLAogICAgIHhsYWIgPSAiRG95IG9mIHllYXIiLAogICAgIHlsYWIgPSAiQXZlcmFnZSBkYWlseSB0ZW1wZXJhdHVyZSBpbiBkZWcgQyIpCgojIGF2ZXJnZSBvdmVyIHBlcmlvZHMKVC5jbGltLjIwMTRfMjAxNyA8LSBhZ2dyZWdhdGUoVE1LIH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YV8yMDE0XzIwMTcsIEZVTiA9IG1lYW4pCnBvaW50cyhULmNsaW0uMjAxNF8yMDE3JFRNSywgY29sPSJibHVlIikKCiMgMjAxOC0yMDIxClQuY2xpbS4yMDE4XzIwMjEgPC1hZ2dyZWdhdGUoVE1LIH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YV8yMDE4XzIwMjEsIEZVTiA9IG1lYW4pCnBvaW50cyhULmNsaW0uMjAxOF8yMDIxJFRNSywgY29sPSJyZWQiKQpsZWdlbmQoeCA9ICJ0b3BsZWZ0IiwgICAgICAgICAgIyBQb3NpdGlvbgogICAgICAgbGVnZW5kID0gYygiY2xpbSIsICIyMDE0LTIwMTciLCAiMjAxOC0yMDIxIiksICAjIExlZ2VuZCB0ZXh0cwogICAgICAgcGNoID0gYygxLDEsMSksICMgcG9pbnQgdHlwZQogICAgICAgY29sID0gYygiYmxhY2siLCAiYmx1ZSIsICJyZWQiKSkgIyBwb2ludCBjb2xvcnMKCgpwbG90KFQuY2xpbSRUTUstVC5jbGltLjIwMTRfMjAxNyRUTUssIGNvbD0iYmx1ZSIsCiAgICAgeGxhYj1jKCJEYXkgb2YgeWVhciIpLAogICAgIHlsYWIgPSAiVGVtcGVyYXR1cmUgYW5vbWFseSBpbiBkZWdDIikKcG9pbnRzKFQuY2xpbSRUTUstVC5jbGltLjIwMThfMjAyMSRUTUssIGNvbCA9ICJyZWQiKQpsZWdlbmQoeCA9ICJ0b3BsZWZ0IiwgICAgICAgICAgIyBQb3NpdGlvbgogICAgICAgbGVnZW5kID0gYygiMjAxNC0yMDE3IiwgIjIwMTgtMjAyMSIpLCAgIyBMZWdlbmQgdGV4dHMKICAgICAgIHBjaCA9IGMoMSwxKSwgIyBwb2ludCB0eXBlCiAgICAgICBjb2wgPSBjKCJibHVlIiwgInJlZCIpKSAjIHBvaW50IGNvbG9ycwoKCgpwYXIobWZyb3c9YygxLDIpKQpiaW5zID0gc2VxKC02LDYsMSkKaGlzdChULmNsaW0uMjAxNF8yMDE3JFRNSy1ULmNsaW0kVE1LLAogICAgIHhsYWIgPSAiRGV2aWF0aW9uIGluIHRlbXBlcmF0dXJlIGZyb20gY2xpbWF0b2xvZ3kiLAogICAgIG1haW4gPSAiMjAxNC0yMDE4IiwKICAgICBicmVha3MgPSBiaW5zKQpoaXN0KFQuY2xpbS4yMDE4XzIwMjEkVE1LLVQuY2xpbSRUTUssCiAgICAgeGxhYiA9ICJEZXZpYXRpb24gaW4gdGVtcGVyYXR1cmUgZnJvbSBjbGltYXRvbG9neSIsCiAgICAgbWFpbiA9ICIyMDE4LTIwMjEiLAogICAgIGJyZWFrcyA9IGJpbnMpCihxdWFudGlsZShULmNsaW0uMjAxNF8yMDE3JFRNSy1ULmNsaW0kVE1LLCBjKDAuMSwwLjUsMC45KSkpCihxdWFudGlsZShULmNsaW0uMjAxOF8yMDIxJFRNSy1ULmNsaW0kVE1LLCBjKDAuMSwwLjUsMC45KSkpCgojIHRlbXBlcmF0dXJlIGFub21hbGllcwpkYXRhJFRjbGltIDwtIE5BCmluZCA8LSB3aGljaChkYXRhJHllYXI+MjAwNCkKZGF0YSRUY2xpbVtpbmRdIDwtIHJlcChULmNsaW0kVE1LLGxlbmd0aChpbmQpLzM2NSkgCmRhdGEkVGFubyA8LSBkYXRhJFRNSyAtIGRhdGEkVGNsaW0KCnBsb3QoZGF0YSRkYXRlLGRhdGEkVGFubywKICAgICB4bGFiID0gIkRhdGUiLAogICAgIHlsYWIgPSAiVGVtcGVyYXR1cmUgYW5vbWFsaWVzIGluIGRlZ0MiKQoKYm94cGxvdChUYW5vIH4geWVhciwgZGF0YT1kYXRhLAogICAgICAgIHhsYWIgPSAiWWVhciIsCiAgICAgICAgeWxhYiA9ICJUZW1wZXJhdHVyZSBhbm9tYWxpZXMgaW4gZGVnQyIpCgpsbS5UYW5vbSA8LSBsbShUYW5vIH4gYXMubnVtZXJpYyh5ZWFyKSwgZGF0YSA9IGRhdGEpCnN1bW1hcnkobG0uVGFub20pCgpgYGAKCkJvdGggcGVyaW9kcyB3ZXJlIHdhcm1lciB0aGFuIHRoZSBlbnRpcmUgcmVmZXJlbmNlIHBlcmlvZHMgZnJvbSAyMDA1LTIwMjIsIHdoaWxlIDIwMTgtMjAyMSB3YXMgb3ZlcmFsbCByb3VnaGx5IDAuMDUgZGVncmVlIHdhcm1lciB0aGFuIHRoZSBwcmV2aW91cyAyMDE0LTIwMTcgcGVyaW9kLiBUaGVyZSBhcmUgbm8gc3Ryb25nIGVmZmVjdHMgaW4gdGVtcGVyYXR1cmUgcGVyIHNlLiBBTHNvIHRoZSBhbm9tYWxpZXMgYXJlIHNsaWdodGx5IGluY3JlYXNpbmcgd2l0aCB0aW1lIGJ5IDAuMDYgZGVncmVlIHBlciB5ZWFyLgoKIyMjIERpZmZlcmVuY2UgaW4gdGhlIGRhaWx5IHRlbXBlcmF0dXJlIGluZGljYXRpbmcgY2xvdWRpbmVzcy4KCihkZWx0YV9UID0gVF9tYXggLSBUX21pbikKCmBgYHtyfQpEZWx0YVQuY2xpbSA8LSBhZ2dyZWdhdGUoRGVsdGFUIH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YSwgRlVOID0gbWVhbikKcGxvdChEZWx0YVQuY2xpbSREZWx0YVQsIHlsaW0gPSBjKDEsMTApKQoKIyBhdmVyZ2Ugb3ZlciBwZXJpb2RzCkRlbHRhVC5jbGltLjIwMTRfMjAxNyA8LSBhZ2dyZWdhdGUoRGVsdGFUIH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YV8yMDE0XzIwMTcsIEZVTiA9IG1lYW4pCnBvaW50cyhEZWx0YVQuY2xpbS4yMDE0XzIwMTckRGVsdGFULCBjb2w9ImJsdWUiKQoKIyBhdmVyZ2Ugb3ZlciBwZXJpb2RzCkRlbHRhVC5jbGltLjIwMThfMjAyMSA8LSBhZ2dyZWdhdGUoRGVsdGFUIH4gZGF5K21vbnRoLCBkYXRhID0gZGF0YV8yMDE4XzIwMjEsIEZVTiA9IG1lYW4pCnBvaW50cyhEZWx0YVQuY2xpbS4yMDE4XzIwMjEkRGVsdGFULCBjb2w9InJlZCIpCgpiaW5zID0gc2VxKDEsMTAsMC4yNSkKCmguRGVsdGFUX2RhaWx5LmNsaW0gPC0gaGlzdChEZWx0YVQuY2xpbSREZWx0YVQsIGJyZWFrcyA9IGJpbnMsIHBsb3QgPSBGQUxTRSkKaC5EZWx0YVRfZGFpbHkuMjAxNF8yMDE3IDwtIGhpc3QoRGVsdGFULmNsaW0uMjAxNF8yMDE3JERlbHRhVCwgYnJlYWtzID0gYmlucywgcGxvdCA9IEZBTFNFKQpoLkRlbHRhVF9kYWlseS4yMDE4XzIwMjEgPC0gaGlzdChEZWx0YVQuY2xpbS4yMDE4XzIwMjEkRGVsdGFULCBicmVha3MgPSBiaW5zLCBwbG90ID0gRkFMU0UpCgpwbG90KGguRGVsdGFUX2RhaWx5LmNsaW0kbWlkcywgY3Vtc3VtKGguRGVsdGFUX2RhaWx5LmNsaW0kZGVuc2l0eSkvNCwgCiAgICAgeGxhYiA9ICJEYWlseSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlLCBkZWdDIiwKICAgICB5bGFiID0gImN1bXVsYXRpdmUgZnJlcXVlbmN5IikKcG9pbnRzKGguRGVsdGFUX2RhaWx5LjIwMTRfMjAxNyRtaWRzLCBjdW1zdW0oaC5EZWx0YVRfZGFpbHkuMjAxNF8yMDE3JGRlbnNpdHkpLzQsIAogICAgICAgcGNoID0gMTksIGNvbCA9ICJibHVlIikKcG9pbnRzKGguRGVsdGFUX2RhaWx5LjIwMThfMjAyMSRtaWRzLCBjdW1zdW0oaC5EZWx0YVRfZGFpbHkuMjAxOF8yMDIxJGRlbnNpdHkpLzQsIAogICAgICAgcGNoID0gMTksIGNvbCA9ICJyZWQiKQpsZWdlbmQoeCA9ICJib3R0b21yaWdodCIsICAgICAgICAgICMgUG9zaXRpb24KICAgICAgIGxlZ2VuZCA9IGMoImNsaW0iLCAiMjAxNC0yMDE3IiwgIjIwMTgtMjAyMSIpLCAgIyBMZWdlbmQgdGV4dHMKICAgICAgIHBjaCA9IGMoMSwgMTksIDE5KSwgIyBwb2ludCB0eXBlcwogICAgICAgY29sID0gYygiYmxhY2siLCAiYmx1ZSIsICJyZWQiKSwgIyBwb2ludCBjb2xvcnMKICAgICAgICkgICAgICAgICAgIAoKI2hpc3QoRGVsdGFULmNsaW0uMjAxNF8yMDE3JERlbHRhVC1EZWx0YVQuY2xpbSREZWx0YVQpCgojaGlzdChEZWx0YVQuY2xpbS4yMDE4XzIwMjEkRGVsdGFULURlbHRhVC5jbGltJERlbHRhVCkKCmRlbHRhVCA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKGguRGVsdGFUX2RhaWx5LmNsaW0kbWlkcywgY3Vtc3VtKGguRGVsdGFUX2RhaWx5LmNsaW0kZGVuc2l0eSkvNCwgY3Vtc3VtKGguRGVsdGFUX2RhaWx5LjIwMTRfMjAxNyRkZW5zaXR5KS80LCBjdW1zdW0oaC5EZWx0YVRfZGFpbHkuMjAxOF8yMDIxJGRlbnNpdHkpLzQpKQpjb2xuYW1lcyhkZWx0YVQpIDwtIGMoImRlbHRhX1QiLCAiZnJlcV8yMDA1XzIwMjEiLCAiZnJlcV8yMDE0XzIwMTciLCAiZnJlcV8yMDE4XzIwMjEiKQoKd3JpdGUuY3N2KGRlbHRhVCwgZmlsZT0iZGFsdGFUXzE1eXJzXzYzMDUuY3N2IikKCgoKYGBgCgpUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIG1pbnVtdW0gYW5kIG1heHVtaW0gdGVtcGVyYXR1cmUgaW5jcmVhc2VzIGluIGJvdGggcGVyaW9kcywgZXNwbHkgaW4gdGltZXMgd2VyZSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlcyBhcmUgaGlnaCAoaW4gc3VtbWVyKS4gVGh1cyBpbiBnZW5lcmFsIHRoZSB2YXJpYXRpb24gaW4gdGVtcGVyYXR1cmUgYXQgYSBkYWlseSBzY2FsZSBoYXMgaW5jcmVhc2VkLCBpbmRpY2F0aW5nIGFuIGluY3JlYXNlIGluIHN1bnNoaW5lIGhvdXJzIGFuZCBkZWNyZWFzZSBpbiBjbG91ZGluZXNzLiAKCiMjIyBQb3RlbnRpYWwgRXZhcG90cmFuc3BpcmF0aW9uLCBkYWlseQoKYGBge3J9CgpFcG90LmNsaW0gPC0gYWdncmVnYXRlKEVwb3QgfiBkYXkrbW9udGgsIGRhdGEgPSBkYXRhLCBGVU4gPSBtZWFuKQpwbG90KEVwb3QuY2xpbSRFcG90LCB5bGltID0gYygwLDUpLAogICAgIHhsYWIgPSAiRGF5IG9mIHllYXIiLAogICAgIHlsYWIgPSAiUG90ZW50aWFsIGV2YXBvdHJhbnNwaXJhdGlvbiBpbiBtbS9kYXkiKQpsZWdlbmQoeCA9ICJ0b3ByaWdodCIsICAgICAgICAgICMgUG9zaXRpb24KICAgICAgIGxlZ2VuZCA9IGMoImNsaW0iLCAiMjAxNC0yMDE3IiwgIjIwMTgtMjAyMSIpLCAgIyBMZWdlbmQgdGV4dHMKICAgICAgICBwY2ggPSBjKDEsIDEsIDEpLCAjIHBvaW50IHR5cGVzCiAgICAgICAgY29sID0gYygiYmxhY2siLCAiYmx1ZSIsICJyZWQiKSkgIyBwb2ludCBjb2xvcnMKCgojIGF2ZXJnZSBvdmVyIHBlcmlvZHMKRXBvdC5jbGltLjIwMTRfMjAxNyA8LSBhZ2dyZWdhdGUoRXBvdCB+IGRheSttb250aCwgZGF0YSA9IGRhdGFfMjAxNF8yMDE3LCBGVU4gPSBtZWFuKQpwb2ludHMoRXBvdC5jbGltLjIwMTRfMjAxNyRFcG90LCBjb2w9ImJsdWUiKQoKIyBhdmVyZ2Ugb3ZlciBwZXJpb2RzCkVwb3QuY2xpbS4yMDE4XzIwMjEgPC0gYWdncmVnYXRlKEVwb3QgfiBkYXkrbW9udGgsIGRhdGEgPSBkYXRhXzIwMThfMjAyMSwgRlVOID0gbWVhbikKcG9pbnRzKEVwb3QuY2xpbS4yMDE4XzIwMjEkRXBvdCwgY29sPSJyZWQiKQoKYmlucyA9IHNlcSgwLDUsMC4xKQoKaC5FcG90X2RhaWx5LmNsaW0gPC0gaGlzdChFcG90LmNsaW0kRXBvdCwgYnJlYWtzID0gYmlucywgcGxvdCA9IEZBTFNFKQpoLkVwb3RfZGFpbHkuMjAxNF8yMDE3IDwtIGhpc3QoRXBvdC5jbGltLjIwMTRfMjAxNyRFcG90LCBicmVha3MgPSBiaW5zLCBwbG90ID0gRkFMU0UpCmguRXBvdF9kYWlseS4yMDE4XzIwMjEgPC0gaGlzdChFcG90LmNsaW0uMjAxOF8yMDIxJEVwb3QsIGJyZWFrcyA9IGJpbnMsIHBsb3QgPSBGQUxTRSkKCnBsb3QoaC5FcG90X2RhaWx5LmNsaW0kbWlkcywgY3Vtc3VtKGguRXBvdF9kYWlseS5jbGltJGRlbnNpdHkpLzEwLCAKICAgICB4bGFiID0gIkRhaWx5IHBvdGVudGlhbCBldmFwb3RyYW5zcGlyYXRpb24sIG1tL2QiLAogICAgIHlsYWIgPSAiY3VtdWxhdGl2ZSBmcmVxdWVuY3kiKQpwb2ludHMoaC5FcG90X2RhaWx5LjIwMTRfMjAxNyRtaWRzLCBjdW1zdW0oaC5FcG90X2RhaWx5LjIwMTRfMjAxNyRkZW5zaXR5KS8xMCwgCiAgICAgICBwY2ggPSAxOSwgY29sID0gImJsdWUiKQpwb2ludHMoaC5FcG90X2RhaWx5LjIwMThfMjAyMSRtaWRzLCBjdW1zdW0oaC5FcG90X2RhaWx5LjIwMThfMjAyMSRkZW5zaXR5KS8xMCwgCiAgICAgICBwY2ggPSAxOSwgY29sID0gInJlZCIpCmxlZ2VuZCh4ID0gImJvdHRvbXJpZ2h0IiwgICAgICAgICAgIyBQb3NpdGlvbgogICAgICAgbGVnZW5kID0gYygiY2xpbSIsICIyMDE0LTIwMTciLCAiMjAxOC0yMDIxIiksICAjIExlZ2VuZCB0ZXh0cwogICAgICAgcGNoID0gYygxLCAxOSwgMTkpLCAjIHBvaW50IHR5cGVzCiAgICAgICBjb2wgPSBjKCJibGFjayIsICJibHVlIiwgInJlZCIpLCAjIHBvaW50IGNvbG9ycwogICAgICAgKSAgICAgICAgICAgCgpgYGAKCkF0IHRoZSBkYWlseSBzY2FsZSwgdGhlIHBvdGVudGlhbCBldmFwb3RyYW5zcGlyYXRpb24gaGFzIHNsaWdodGx5IGluY3JlYXNlZCBlc3BlY2lhbGx5IGluIHN1bW1lci4KCiMjIyBQb3RlbnRpYWwgZXZhcG90cmFuc3BpcmF0aW9uLCBwcmVjaXBpdGF0aW9uIHdlZWtseQoKYGBge3J9CmxpYnJhcnkodGlkeXIpCiMgQWdncmVnYXRlIHRvIHdlZWtseSBkYXRhIGFzIDUgZGFpbHkgYXZlcmFnZXMgcGVyZm9ybSBiZXR0ZXIgdGhhbiBkYWlseSAKZGF0YSRkYXRlIDwtIGFzLlBPU0lYbHQoZGF0YSRkYXRlKQpkYXRhLncuRXBvdCA8LSBhZ2dyZWdhdGUoZGF0YSRFcG90IH4gZm9ybWF0KGRhdGUsIiVZLSVXIiksIGRhdGE9ZGF0YSwgRlVOID0gbWVhbikgIyB3ZWVrbHkgZGF0YQpuYW1lcyhkYXRhLncuRXBvdClbMToyXSA9IGMoImRhdGUiLCAiRXBvdCIpCmRhdGEudy5FcG90PC1kYXRhLncuRXBvdCAlPiUgc2VwYXJhdGUoZGF0ZSwgYygieWVhciIsIndlZWsiKSkgIyB0aWR5cgoKIyBzdWJzZXQgZm9yIHBlcmlvZHMgb25jZSBtb3JlCmRhdGEudy5FcG90XzIwMTRfMjAxNyA8LSBkYXRhLncuRXBvdFt3aGljaChkYXRhLncuRXBvdCR5ZWFyPj0yMDE0ICYgZGF0YS53LkVwb3QkeWVhcjw9MjAxNyksXSAKZGF0YS53LkVwb3RfMjAxOF8yMDIxIDwtIGRhdGEudy5FcG90W3doaWNoKGRhdGEudy5FcG90JHllYXI+PTIwMTggJiBkYXRhLncuRXBvdCR5ZWFyPD0yMDIxKSxdIAoKRXBvdC5jbGltIDwtIGFnZ3JlZ2F0ZShFcG90IH4gd2VlaywgZGF0YSA9IGRhdGEudy5FcG90LCBGVU4gPSBtZWFuKSAjIHdlZWtseSBjbGltYXRvbG9neQoKRXBvdC5jbGltLjIwMTRfMjAxNyA8LSBhZ2dyZWdhdGUoRXBvdCB+IHdlZWssIGRhdGEgPSBkYXRhLncuRXBvdF8yMDE0XzIwMTcsIEZVTiA9IG1lYW4pICMgd2Vla2x5IGNsaW1hdG9sb2d5IDIwMTQtMjAxNwpFcG90LmNsaW0uMjAxOF8yMDIxIDwtIGFnZ3JlZ2F0ZShFcG90IH4gd2VlaywgZGF0YSA9IGRhdGEudy5FcG90XzIwMThfMjAyMSwgRlVOID0gbWVhbikgIyB3ZWVrbHkgY2xpbWF0b2xvZ3kgMjAxOC0yMDIxCgpwbG90KEVwb3QuY2xpbSRFcG90LAogICAgIHhsYWIgPSAiQ2FsZW5kYXIgd2VlayIsCiAgICAgeWxhYiA9ICJBdmVyYWdlIFBFVCBpbiBtbS9kIikKcG9pbnRzKEVwb3QuY2xpbS4yMDE0XzIwMTckRXBvdCwgCiAgICAgICBwY2ggPSAxOSwgY29sID0gImJsdWUiKQpwb2ludHMoRXBvdC5jbGltLjIwMThfMjAyMSRFcG90LCAKICAgICAgIHBjaCA9IDE5LCBjb2wgPSAicmVkIikKbGVnZW5kKHggPSAidG9wbGVmdCIsICAgICAgICAgICMgUG9zaXRpb24KICAgICAgIGxlZ2VuZCA9IGMoImNsaW0iLCAiMjAxNC0yMDE3IiwgIjIwMTgtMjAyMSIpLCAgIyBMZWdlbmQgdGV4dHMKICAgICAgIHBjaCA9IGMoMSwgMTksIDE5KSwgIyBwb2ludCB0eXBlcwogICAgICAgY29sID0gYygiYmxhY2siLCAiYmx1ZSIsICJyZWQiKSwgIyBwb2ludCBjb2xvcnMKICAgICAgICkgICAgICAgICAgIAoKCnBsb3QoY3Vtc3VtKEVwb3QuY2xpbSRFcG90KjcpLAogICAgIHhsYWIgPSAiQ2FsZW5kYXIgd2VlayIsCiAgICAgeWxhYiA9ICJDdW11bGF0ZWQgUEVUIGluIG1tIikKcG9pbnRzKGN1bXN1bShFcG90LmNsaW0uMjAxNF8yMDE3JEVwb3QqNyksIAogICAgICAgcGNoID0gMTksIGNvbCA9ICJibHVlIikKcG9pbnRzKGN1bXN1bShFcG90LmNsaW0uMjAxOF8yMDIxJEVwb3QqNyksIAogICAgICAgcGNoID0gMTksIGNvbCA9ICJyZWQiKQpsZWdlbmQoeCA9ICJib3R0b21yaWdodCIsICAgICAgICAgICMgUG9zaXRpb24KICAgICAgIGxlZ2VuZCA9IGMoImNsaW0iLCAiMjAxNC0yMDE3IiwgIjIwMTgtMjAyMSIpLCAgIyBMZWdlbmQgdGV4dHMKICAgICAgIHBjaCA9IGMoMSwgMTksIDE5KSwgIyBwb2ludCB0eXBlcwogICAgICAgY29sID0gYygiYmxhY2siLCAiYmx1ZSIsICJyZWQiKSwgIyBwb2ludCBjb2xvcnMKICAgICAgICkgCgoKCmBgYAoKVGhpcyBnaXZlcyB0aGUgY3VtdWxhdGl2ZSBwb3RlbnRpYWwgZXZhcG90cmFuc3BpcmF0aW9uLCB3aGljaCBoYXMgc2xpZ2h0bHkgaW5jcmVhc2VkIGluIHRoZSBzZWNvbmQgcGVyaW9kIGNvbXBhcmVkIHRvIHRoZSBmaXJzdC4gVGhlIGZpcnN0IGlzIHNpbWlsYXIgdG8gdGhlIGNsaW1hdG9sb2d5LgoKCiMjIyBNb250aGx5IHByZWNpcGl0YXRpb24gYW5kIHBvdGVudGlhbCBldmFwb3RyYW5zcGlyYXRpb24KCmBgYHtyfQoKcHJlYy5tb250aGx5IDwtIGFnZ3JlZ2F0ZShSU0sgfiBtb250aCt5ZWFyLCBkYXRhID0gZGF0YSwgRlVOID0gc3VtKQpjbGltLnByZWMubW9udGhseSA8LSBhZ2dyZWdhdGUoUlNLIH4gbW9udGgsIGRhdGEgPSBwcmVjLm1vbnRobHksIEZVTiA9IG1lYW4pCnBsb3QoY2xpbS5wcmVjLm1vbnRobHksCiAgICAgeWxpbSA9IGMoMCwxMDApLAogICAgIHR5cGUgPSAibCIsCiAgICAgeWxhYiA9ICJNb250aGx5IGZsdXgsIG1tIikKCiMgcGVyaW9kIDIwMTQtMjAxNwpwcmVjLm1vbnRobHkuMjAxNF8yMDE3IDwtIGFnZ3JlZ2F0ZShSU0sgfiBtb250aCt5ZWFyLCBkYXRhID0gZGF0YV8yMDE0XzIwMTcsIEZVTiA9IHN1bSkKY2xpbS5wcmVjLm1vbnRobHkuMjAxNF8yMDE3IDwtIGFnZ3JlZ2F0ZShSU0sgfiBtb250aCwgZGF0YSA9IHByZWMubW9udGhseS4yMDE0XzIwMTcsIEZVTiA9IG1lYW4pCmxpbmVzKGNsaW0ucHJlYy5tb250aGx5LjIwMTRfMjAxNywKICAgICB0eXBlID0gImwiLAogICAgIGNvbCA9ICJibHVlIikKCiMgcGVyaW9kIDIwMTgtMjAyMQpwcmVjLm1vbnRobHkuMjAxOF8yMDIxIDwtIGFnZ3JlZ2F0ZShSU0sgfiBtb250aCt5ZWFyLCBkYXRhID0gZGF0YV8yMDE4XzIwMjEsIEZVTiA9IHN1bSkKY2xpbS5wcmVjLm1vbnRobHkuMjAxOF8yMDIxIDwtIGFnZ3JlZ2F0ZShSU0sgfiBtb250aCwgZGF0YSA9IHByZWMubW9udGhseS4yMDE4XzIwMjEsIEZVTiA9IG1lYW4pCmxpbmVzKGNsaW0ucHJlYy5tb250aGx5LjIwMThfMjAyMSwKICAgICB0eXBlID0gImwiLAogICAgIGNvbCA9ICJyZWQiKQoKCiMgYWxsIHllYXJzCkVwb3QubW9udGhseSA8LSBhZ2dyZWdhdGUoRXBvdCB+IG1vbnRoK3llYXIsIGRhdGEgPSBkYXRhLCBGVU4gPSBzdW0pCmNsaW0uRXBvdC5tb250aGx5IDwtIGFnZ3JlZ2F0ZShFcG90IH4gbW9udGgsIGRhdGEgPSBFcG90Lm1vbnRobHksIEZVTiA9IG1lYW4pCgojIHBlcmlvZCAyMDE0LTIwMTcKRXBvdC5tb250aGx5LjIwMTRfMjAxNyA8LSBhZ2dyZWdhdGUoRXBvdCB+IG1vbnRoK3llYXIsIGRhdGEgPSBkYXRhXzIwMTRfMjAxNywgRlVOID0gc3VtKQpjbGltLkVwb3QubW9udGhseS4yMDE0XzIwMTcgPC0gYWdncmVnYXRlKEVwb3QgfiBtb250aCwgZGF0YSA9IEVwb3QubW9udGhseS4yMDE0XzIwMTcsIEZVTiA9IG1lYW4pCgojIHBlcmlvZCAyMDE4LTIwMjEKRXBvdC5tb250aGx5LjIwMThfMjAyMSA8LSBhZ2dyZWdhdGUoRXBvdCB+IG1vbnRoK3llYXIsIGRhdGEgPSBkYXRhXzIwMThfMjAyMSwgRlVOID0gc3VtKQpjbGltLkVwb3QubW9udGhseS4yMDE4XzIwMjEgPC0gYWdncmVnYXRlKEVwb3QgfiBtb250aCwgZGF0YSA9IEVwb3QubW9udGhseS4yMDE4XzIwMjEsIEZVTiA9IG1lYW4pCgpsaW5lcyhjbGltLkVwb3QubW9udGhseSwKICAgICB0eXBlID0gImwiLAogICAgIGx0eSA9ICJkYXNoZWQiKQpsaW5lcyhjbGltLkVwb3QubW9udGhseS4yMDE0XzIwMTcsCiAgICAgdHlwZSA9ICJsIiwKICAgICBjb2w9ImJsdWUiLAogICAgIGx0eSA9ICJkYXNoZWQiKQpsaW5lcyhjbGltLkVwb3QubW9udGhseS4yMDE4XzIwMjEsCiAgICAgdHlwZSA9ICJsIiwKICAgICBjb2w9InJlZCIsCiAgICAgbHR5ID0gImRhc2hlZCIpCgpsZWdlbmQoeCA9ICJ0b3BsZWZ0IiwgICAgICAgICAgIyBQb3NpdGlvbgogICAgICAgbGVnZW5kID0gYygicHJlY2lwaXRhdGlvbiIsIkVwb3QiLCAiYWxsIiwgIjIwMTQtMjAxNyIsICIyMDE4LTIwMjEiKSwgICMgTGVnZW5kIHRleHRzCiAgICAgICBsdHkgPSBjKCJzb2xpZCIsICJkYXNoZWQiLCAic29saWQiLCAic29saWQiLCJzb2xpZCIpLCAjIHBvaW50IHR5cGVzCiAgICAgICBjb2wgPSBjKCJibGFjayIsICJibGFjayIsICJibGFjayIsICJibHVlIiwgInJlZCIpLCAjIHBvaW50IGNvbG9ycwogICAgICAgKSAKCmBgYAoKUHJlY2lwaXRhdGlvbiB2YXJpZXMgbW9yZSBiZXR3ZWVuIHRoZSBmb2N1cyBwZXJpb2RzIHRoYW4gcG90ZW50aWFsIGV2YXBvcmF0aW9uLiAKCgoKIyMjIFdhdGVyIGJhbGFuY2UsIHBlciBoeWRyb2xvZ2ljYWwgeWVhcgoKd2F0ZXIgZGVmaWNpdCA9IHByZWNpcGl0YXRpb24gLSBwb3RlbnRpYWwgZXZhcG9yYXRpb24KCmBgYHtyfQpwbG90KGguZGF0YSRkYXRlLCBoLmRhdGEkZGVmLCAKIyAgICAgeWxpbSA9IGMoLTIwMCwyNTApLAogICAgIHhsYWIgPSAiRGF0ZSIsCiAgICAgeWxhYiA9ICJQIC0gUEVUIHNpbmNlIE9jdCAxIGVhY2ggeWVhciIpCgpgYGAKCkluIHRoaXMgcGxvdCwgYWxsIGh5ZHJvbG9naWNhbCB5ZWFycyBhcmUgY29uc2lkZXJlZCBzZXBhcmF0ZWx5LiBUaGUgd2F0ZXIgZGVmaWNpdCBpcyBzZXQgdG8gemVybyBhdCB0aGUgYmVnaW5uaW5nIG9mIGVhY2ggaHlkcm9sb2dpY2FsIHllYXIgKGNvcnJlc3BvbmRzIHRvIHRoZSBlbmQgb2YgdGhlIHZlZ2V0YXRpb24gcGVyaW9kKSBhdCBPY3QgMS4gCgpXZSBzZWUgdGhhdCB0aGUgdmFyaWF0aW9uIHdpdGhpbiB0aGUgeWVhcnMgaW5jcmVhc2VkIHdpdGggdGltZS4gCgpgYGB7cn0KCmRlZi55ZWFybHkubWF0IDwtIG1hdHJpeChoLmRhdGEkZGVmLCBucm93PTM2NSwgbmNvbD1sZW5ndGgoeWVhcnMpLTEgKQpoLnllYXJzID0geWVhcnNbLTFdCgpkZWYubWluLnllYXIgPC0gYXBwbHkoZGVmLnllYXJseS5tYXQsMixtaW4pCmRlZi5tYXgueWVhciA8LSBhcHBseShkZWYueWVhcmx5Lm1hdCwyLG1heCkKZGVmLnJhbmdlLnllYXIgPC0gZGVmLm1heC55ZWFyIC0gZGVmLm1pbi55ZWFyCmRlZi5zZC55ZWFyIDwtIGFwcGx5KGRlZi55ZWFybHkubWF0LDIsc2QpICAKZGVmLm1lYW4ueWVhciA8LSBhcHBseShkZWYueWVhcmx5Lm1hdCwyLG1lYW4pCgoKcGxvdCh5ZWFyc1sxOmxlbmd0aCh5ZWFycyktMV0sIGRlZi5yYW5nZS55ZWFyLAogICAgIHlsYWI9YygiUmFuZ2Ugb2Ygd2F0ZXIgYXZhaWxhYmlsaXR5IiksCiAgICAgeGxhYj1jKCJDYWxlbmRhciB5ZWFyIikpICAgIAoKaW5kLjIwMTRfMjAyMSA8LSB3aGljaChoLnllYXJzPj0yMDE0ICYgaC55ZWFyczw9MjAxNykKCmxtLmRlZi5yYW5nZSA8LSBsbShkZWYucmFuZ2UueWVhciB+IHllYXJzWzI6bGVuZ3RoKHllYXJzKV0pCihzdW1tYXJ5KGxtLmRlZi5yYW5nZSkpCgpsbS5kZWYuc2QgPC0gbG0oZGVmLnNkLnllYXIgfiB5ZWFyc1syOmxlbmd0aCh5ZWFycyldKQooc3VtbWFyeShsbS5kZWYuc2QpKQoKCiNwbG90KHllYXJzWzE6bGVuZ3RoKHllYXJzKS0xXSwgZGVmLnNkLnllYXIsCiMgICAgIHlsYWI9InZhcmlhdGlvbiBvZiB3YXRlciBhdmFpbGFiaWxpdHkiLAojICAgICB4bGFiPSJjYWxlbmRhciB5ZWFyIikgICAgCgojcGxvdCh5ZWFyc1sxOmxlbmd0aCh5ZWFycyktMV0sIGRlZi5tZWFuLnllYXIsCiMgICAgIHlsYWI9YygibWVhbiBhbm51YWwgd2F0ZXIgZGVmaWNpdCIpLAojICAgICB4bGFiPWMoImNhbGVuZGFyIHllYXIiKSkgICAgCgojcGxvdCh5ZWFyc1sxOmxlbmd0aCh5ZWFycyktMV0sIGRlZi5taW4ueWVhciwKIyAgICAgeWxhYj1jKCJtaW5pbXVtIHdhdGVyIGF2YWlsYWJpbGl0eSIpLAojICAgICB4bGFiPWMoImNhbGVuZGFyIHllYXIiKSkKCgojcGxvdCh5ZWFyc1sxOmxlbmd0aCh5ZWFycyktMV0sIGRlZi5tYXgueWVhciwgCiMgICAgIHlsYWI9YygibWF4aW11bSB3YXRlciBhdmFpbGFiaWxpdHkiKSwKIyAgICAgeGxhYj1jKCJjYWxlbmRhciB5ZWFyIikpCgpgYGAKClRoaXMgcGxvdCBzaG93cyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB5ZWFybHkgbWF4aW11bSBzdXJwbHVzIGFuZCBtaW5pbXVtIHdhdGVyIGRlZmljaXQsIGNhbGxlZCAicmFuZ2UgaW4gd2F0ZXIgZGVmaWNpdCIgKHBvc2l0aXZlIHZhbHVlcyBvZiB3YXRlciBkZWZpY2l0IGFyZSBzdXJwbHVzKS4gVGhlIHJhbmdlIGluY3JlYXNlcyBpbiB0aGUgcmVjZW50IHllYXJzLCBhbmQgYXJndWFibHkgdGhlIHZhcmlhdGlvbiBpbiB0aGUgd2F0ZXIgYmFsYW5jZSBhcyB3ZWxsLiBUaGUgaW5jcmVhc2UgaXMgbm90IHNpZ25pZmljYW50IGhvd2V2ZXIuCgpgYGB7cn0KY2xpbS5kZWYgPC0gYXBwbHkoZGVmLnllYXJseS5tYXQsMSxtZWFuKQoKYzIwMTRfMjAxNyA8LSB3aGljaChoLnllYXJzPj0yMDE0ICYgaC55ZWFyczw9MjAxNykKYzIwMThfMjAyMSA8LSB3aGljaChoLnllYXJzPj0yMDE4ICYgaC55ZWFyczw9MjAyMSkKCgpoLmNsaW0uZGF0ZSA9IGguZGF0YSRkYXRlWzE6MzY1XQpjbGltLmRlZi5tZWFuLjIwMTRfMjAxNyA8LSBhcHBseShkZWYueWVhcmx5Lm1hdFssYzIwMTRfMjAxN10sMSxtZWFuKQpjbGltLmRlZi5taW4uMjAxNF8yMDE3IDwtIGFwcGx5KGRlZi55ZWFybHkubWF0WyxjMjAxNF8yMDE3XSwxLG1pbikKY2xpbS5kZWYubWF4LjIwMTRfMjAxNyA8LSBhcHBseShkZWYueWVhcmx5Lm1hdFssYzIwMTRfMjAxN10sMSxtYXgpCgpjbGltLmRlZi5tZWFuLjIwMThfMjAyMSA8LSBhcHBseShkZWYueWVhcmx5Lm1hdFssYzIwMThfMjAyMV0sMSxtZWFuKQpjbGltLmRlZi5tYXguMjAxOF8yMDIxIDwtIGFwcGx5KGRlZi55ZWFybHkubWF0WyxjMjAxOF8yMDIxXSwxLG1heCkKY2xpbS5kZWYubWluLjIwMThfMjAyMSA8LSBhcHBseShkZWYueWVhcmx5Lm1hdFssYzIwMThfMjAyMV0sMSxtaW4pCgoKcGxvdChoLmNsaW0uZGF0ZSwgY2xpbS5kZWYsCiAgICAgeWxpbSA9IGMoLTEwMCwgMTUwKSwKICAgICB4bGFiID0gIkRhdGUiLAogICAgIHlsYWIgPSAiV2F0ZXIgZGVmaWNpdCBpbiBQLVBFVCBpbiBtbSIpCnBvaW50cyhoLmNsaW0uZGF0ZSwgY2xpbS5kZWYubWVhbi4yMDE0XzIwMTcsCiAgICAgICBjb2w9ImJsdWUiKQpwb2ludHMoaC5jbGltLmRhdGUsIGNsaW0uZGVmLm1lYW4uMjAxOF8yMDIxLAogICAgICAgY29sPSJyZWQiKQpsZWdlbmQoeCA9ICJ0b3BsZWZ0IiwgICAgICAgICAgIyBQb3NpdGlvbgogICAgICAgbGVnZW5kID0gYygiY2xpbSIsICIyMDE0LTIwMTciLCAiMjAxOC0yMDIxIiksICAjIExlZ2VuZCB0ZXh0cwogICAgICAgcGNoID0gYygxLCAxOSwgMTkpLCAjIHBvaW50IHR5cGVzCiAgICAgICBjb2wgPSBjKCJibGFjayIsICJibHVlIiwgInJlZCIpLCAjIHBvaW50IGNvbG9ycwogICAgICAgKQoKCmBgYAoKV2hlbiBhZ2dyZWFnYXRpbmcgb3ZlciB0aGUgdHdvIHBlcmlvZHMsIHdlIHNlZSB0aGUgZ2VuZXJhbCBkeW5hbWljcy4gVGhlcmUgaXMgYSBzdXJwbHVzIG9mIHdhdGVyIGluIHRoZSB3aW50ZXIsIGJlY2F1c2UgRVQgaXMgbG93LCBhbmQgYSBuZWdhdGl2ZSBiYWxhbmNlIGluIHN1bW1lciwgd2hobiBFVCBpcyBsYXJnZXIuIFRoZSBtb3N0IHN0cmlraW5nIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgZmlyc3QgYW5kIHNlY29uZCBwZXJpb2QgaXMgdGhhdCB0aGUgc3VycGx1cyBpbiB3aW50ZXIgaXMgc21hbGxlciBpbiB0aGUgc2Vjb25kIHBlcmlvZC4gVGhlIGRlZmljaXQgZG9lcyBub3QgbmVjZXNzYXJpbHkgZGV2ZWxvcCBlYXJsaWVyIGluIHN1bW1lciB0aG91Z2ggKHRoZSByZWQgY3VydmUgaXMgc3RpbGwgcG9zaXRpdmUgaW4gSnVseSwgd2hpbGUgdGhlIGJsdWUgb25lIGlzIGFscmVhZHkgbmVnYXRpdmUgYXQgdGhpcyBwb2ludCkuCgoKCmBgYHtyfQojcGxvdChoLmNsaW0uZGF0ZSwgY2xpbS5kZWYsCiMgICAgIHlsaW0gPSBjKC0xMDAsIDE1MCksCiMgICAgIHhsYWIgPSAiZGF0ZSIsCiMgICAgIHlsYWIgPSAid2F0ZXIgZGVmaWNpdCBpbiBQLVBFVCBpbiBtbSIsCiMgICAgIHR5cGUgPSAibCIpCiNwb2x5Z29uKGMoaC5jbGltLmRhdGUpLCByZXYoaC5jbGltLmRhdGUpLCAKIyAgICAgICAgICBjKGNsaW0uZGVmLm1heC4yMDE0XzIwMTcsIHJldihjbGltLmRlZi5taW4uMjAxNF8yMDE3KSksCiMgICAgICAgIGNvbCA9ICIjNkJEN0FGIikKCmRheXMgPSBjKDE6MzY1KQpkYXlzbW9udGggPSBjKDMxLDMwLDMxLDMxLDI4LDMxLDMwLDMxLDMwLDMxLDMxLDMwKQptb250aHMgPSBjKCJPY3QiLCJOb3YiLCJEZWMiLCJKYW4iLCAiRmViIiwgIk1hciIsICJBcHIiLCAiTWF5IiwgIkp1biIsICJKdWwiLCAiQXVnIiwgIlNlcCIpCmF4aXN0aWNrcyA9IGMoMzEvMixjdW1zdW0oZGF5c21vbnRoWzE6MTFdKSArIGRheXNtb250aFsyOjEyXS8yKQoKcGxvdChkYXlzLCBjbGltLmRlZiwKICAgIHhheHQgPSAibiIgLAogICAgeWxpbSA9IGMoLTIwMCwgMjAwKSwKICAgIHhsaW0gPSBjKDAsMzY1KSwKICAgICB4bGFiID0gIkRhdGUiLAogICAgIHlsYWIgPSAiV2F0ZXIgZGVmaWNpdCBpbiBQLVBFVCBpbiBtbSIsCiAgICAgdHlwZSA9ICJsIikKYXhpcygxLGF0ID0gYXhpc3RpY2tzLCBsYWJlbHMgPSBtb250aHMpCnBvbHlnb24oYyhkYXlzLCByZXYoZGF5cykpLCAKICAgICAgICAgIGMoY2xpbS5kZWYubWF4LjIwMTRfMjAxNywgcmV2KGNsaW0uZGVmLm1pbi4yMDE0XzIwMTcpKSwKICAgICAgICBjb2wgPSAiI0FFRDZGMUFBIikKcG9seWdvbihjKGRheXMsIHJldihkYXlzKSksIAogICAgICAgICAgYyhjbGltLmRlZi5tYXguMjAxOF8yMDIxLCByZXYoY2xpbS5kZWYubWluLjIwMThfMjAyMSkpLAogICAgICAgIGNvbCA9ICIjRjVCN0IxQUEiKQoKYGBgCgpTYW1lIHBsb3QgYXMgYWJvdmUsIHNoYWRpbmcgdGhlIGJldHdlZW4gbWF4aW11bSBhbmQgbWluaW11bSBvZiB0aGUgcGVyaW9kczogQmx1ZSBpcyAyMDE0LTIwMTcsIHJlZCBpcyAyMDE4LTIwMjEuCgpgYGB7cn0KCkVwb3QueWVhcmx5Lm1hdCA8LSBtYXRyaXgoaC5kYXRhJEVwb3QsIG5yb3c9MzY1LCBuY29sPWxlbmd0aCh5ZWFycyktMSApClAueWVhcmx5Lm1hdCA8LSBtYXRyaXgoaC5kYXRhJFJTSywgbnJvdz0zNjUsIG5jb2w9bGVuZ3RoKHllYXJzKS0xICkKCkVwb3QueWVhcmx5IDwtIGFwcGx5KEVwb3QueWVhcmx5Lm1hdCwyLHN1bSkKUC55ZWFybHkgPC0gYXBwbHkoUC55ZWFybHkubWF0LDIsc3VtKQoKKG1lYW4oRXBvdC55ZWFybHkpKQoobWVhbihQLnllYXJseSkpCgpwbG90KGgueWVhcnMsIFAueWVhcmx5LAogICAgIHBjaCA9IDE5LAogICAgIHhsYWIgPSAiSHlkcm9sb2dpY2FsIHllYXIgMjAwNS8wNiAtIDIwMjAvMjEiLAogICAgIHlsYWIgPSAiRmx1eCBpbiBtbSAvIGh5ZHJvbG9naWNhbCB5ZWFyIikKcG9pbnRzKGgueWVhcnMsIEVwb3QueWVhcmx5LAogICAgICAgcGNoID0gMTksCiAgICAgICBjb2wgPSAicmVkIikKbGVnZW5kKHg9InRvcHJpZ2h0IiwKICAgICAgIGxlZ2VuZCA9IGMoInByZWNpcCIsICJFcG90IiksCiAgICAgICBwY2ggPSBjKDEsIDEpLAogICAgICAgY29sID0gYygiYmxhY2siLCAicmVkIikpCiAgICAgICAKCmxtLlAgPC0gbG0oUC55ZWFybHkgfiBoLnllYXJzKQooc3VtbWFyeShsbS5QKSkKCmxtLkVwb3QgPC0gbG0oRXBvdC55ZWFybHkgfiBoLnllYXJzKQooc3VtbWFyeShsbS5FcG90KSkKCmBgYAoKQW5udWFsIFBFVCBzbGlnaHRseSBpbmNyZWFzZXMgKGR1ZSBib3RoIHRoZSBhdmVyYWdlIHRlbXBlcmF0dXJlIGluY3JlYXNlLCBhbmQgaW5jcmVhc2UgaW4gZGFpbHkgdGVtcGVyYXR1cmUgcmFuZ2UpIG5vdCBzaWduaWZpY2FudGx5LCBidXQgd2l0aCB0aGUgdHJlbmQuIFRoZSBhdmVyYWdlIHdhcyA1NDggbW0uIFByZWNpcGl0YXRpb24gaXMgbW9yZSB2YXJpYWJsZSB0aHJvdWdob3V0IHRoZSBwZXJpb2QgMjAwNS82LTIwMjEvMjIuIFRoZSBhdmVyYWdlIHdhcyA1MDEgbW0gdGhlcmUgd2FzIG5vIHRyZW5kLiAKCgpgYGB7cn0KZGVmLnllYXJseSA8LSBQLnllYXJseSAtIEVwb3QueWVhcmx5CnBsb3QoaC55ZWFycywgZGVmLnllYXJseSwKICAgIHhsYWIgPSAiSHlkcm9sb2dpY2FsIHllYXIgMjAwNS8wNiAtIDIwMjAvMjEiLAogICAgeWxhYiA9ICJXYXRlciBkZWZpY2l0IGluIG1tIC8gaHlkcm9sb2dpY2FsIHllYXIiKQoKbG0uZGVmLnllYXJseSA8LSBsbShkZWYueWVhcmx5IH4gaC55ZWFycykKKHN1bW1hcnkobG0uZGVmLnllYXJseSkpCmBgYAoKQWxzbyB0aGUgZGlmZmVyZW5jZSBvZiB0aGUgdHdvICh3aGljaCBpcyB0aGUgd2F0ZXIgZGVmaWNpdCkgZG9lcyBub3QgZ2l2ZSBhIHNpZ25pZmljYW50IHJlbGF0aW9uLiBPdmVyYWxsLCBzaW5jZSB0aGUgaHlkcm9sb2dpY2FsIHllYXIgMjAxNy8xOCB0aGUgd2F0ZXIgZGVmaWNpdCBoYXMgbm90IGJlZW4gcG9zaXRpdmUsIHRoZXJlZm9yZSBhZGRpbmcgdXAgdG8gYSBzdWJzdGFudGlhbCB3YXRlciBkZWZpY2l0IGF0IHRoZSBlbmQgb2YgMjAyMSBzZWVuIGJlbG93LgoKYGBge3J9CnBsb3QoUC55ZWFybHksIEVwb3QueWVhcmx5LAogICAgIHhsYWIgPSAiQW5udWFsIHByZWNpcGl0YXRpb24gaW4gbW0gLyBoeWRyb2xvZ2ljYWwgeWVhciIsCiAgICAgeWxhYiA9ICJBbm51YWwgUEVUIGluIG1tIC8gaHlkcm9sb2dpY2FsIHllYXIiKQoKbG0uRXBvdC5QIDwtIGxtKFAueWVhcmx5IH4gRXBvdC55ZWFybHkpCnN1bW1hcnkobG0uRXBvdC5QKQoKYGBgCgpUaGVyZSBpcyBhIHNpZ25pZmljYW50IHJlbGF0aW9uIGJldHdlZW4gcG90ZW50aWFsIGV2YXBvdHJhbnNwaXJhdGlvbiBhbmQgcHJlY2lwaXRhdGlvbiAoY2FsY3VsYXRlZCBvdmVyIHRoZSBoeWRyb2xvZ2ljYWwgeWVhcikuIFRoZSBwZWFrIG9mIHRoZSBwcmVjaXBpdGF0aW9uIGlzIGluIHN1bW1lci4gSGVuY2UsIHdoZW4gcHJlY2lwaXRhdGlvbiBpcyBoaWdoLCBwcm9iYWJseSBjbG91ZGluZXNzIGlzIGhpZ2ggYW5kIHRlbXBlcmF0dXJlcyBsb3dlci4gSW4gY29udHJhc3QsIHdoZW4gcHJlY2lwaXRhdGlvbiBpcyBsb3csIHJhaW5kYXlzIGxlc3MsIHN1bnNoaW5lIGhvdXJzIGluY3JlYXNlZCwgYWxzbyB0aGUgcG90ZW50aWFsIGV2YXBvcmF0aW9uIGlzIGhpZ2guIFRoZSBjb21iaW5hdGlvbiBsZWFkcyB0byBhIHN1YnN0YW50aWFsIGJ1aWxkIHVwIG9mIHdhdGVyIGRlZmljaXQgdGhhdCBjYW5ub3QgYmUgY3VyZWQgd2l0aCBvbmUgZ29vZCB5ZWFyIG9mIHByZWNpcGl0YXRpb24uCgoKCiMjIyBNdWx0aWFubnVhbCBjdW11bGF0aXZlIHdhdGVyIGRlZmljaXQKCk1vc3QgaW1wcmVzc2l2ZSBpcyB0aGUgbXVsdGlhbm51YWwgd2F0ZXIgZGVmaWNpdCwgc3RhcnRpbmcgdGhlIHdhdGVyIGJhbGFuY2UgaW4gT2N0YmVyIDIwMDUgYW5kICoqTk9UKiogcmVzZXR0aW5nIGVhY2ggeWVhci4gVGhlIG5lZ2F0aXZlIG51bWJlcnMgY2FuIGJlIGludGVwcmV0ZWQgYXMgdGhlIHdhdGVyIHN0b3JhZ2UgaW4gdGhlIHN1YnN1cmZhY2UgdGhhdCB3b3VsZCBiZSByZXF1aXJlZCB0byBjb21wZW5zYXRlIGZvciB0aGUgbGFjayBvZiBwcmVjaXBpdGF0aW9uLiAKCmBgYHtyfQpoLmRhdGEkY3VtZGVmIDwtIGN1bXN1bShoLmRhdGEkUlNLIC0gaC5kYXRhJEVwb3QpICMgbG9uZ3Rlcm0gY3VtdWxhdGVkIHdhdGVyIGRlZmljaXQKCnBsb3QoaC5kYXRhJGRhdGUsIGguZGF0YSRjdW1kZWYsIAojICAgICB5bGltID0gYygtMjAwLDI1MCksCiAgICAgeGxhYiA9ICJEYXRlIiwKICAgICB5bGFiID0gIlAgLSBQRVQgc2luY2UgT2N0IDEgMjAwNSBpbiBtbSIsCiAgICAgbWFpbiA9ICJObyA2MzA1IE11ZWhsaGF1c2VuIikKYGBgCkhlcmUgd2UgYXJlIGxvb2tpbmcgYXQgdGhlIGRlZmljaXQgYnVpbGRpbmcgdXAgb3ZlciBzZXZlcmFsIHllYXJzLiBOb3RlIHRoaXMgd2FzIGNhbGN1bGF0ZWQgdXNpbmcgdGhlIHBvdGVudGlhbCBldmFwb3RyYW5zcGlyYXRpb24sIG5vdCB0aGUgcmVhbCBvbmUuIFJlZ2FyZGxlc3MsIHRoZSBtZXRlb2xvcm9naWNhbCB3YXRlciBkZWZpY2l0IGRlZmVuaXRpZWx5IGJ1aWx0IHVwLCBzcGVjaWZpY2FsbHkgc2luY2UgMjAxNC4gV2hpbGUgdGhlIHdhdGVyIGRlZmljaXQgd2FzIHJhdGhlciBiYWxhbmNlZCB1bnRpbCB0aGUgeWVhciAyMDE0LCB0aGUgbWV0ZW9yb2xvZ2ljYWwgd2F0ZXIgYmFsYW5jZSB3ZW50IHN0cm9uZ2x5IG5lZ2F0aXZlIHNpbmNlIDIwMTUsIHdpdGggc29tZSByZWNvdmVyeSBpbiBzcHJpbmcgMjAxOCBhbmQgYW4gZXZlbiBzdHJvbmdlciBkcm9wIGluIHN1bW1lciAyMDE4LiBUaGUgZGVmaWNpdCBhdCB0aGUgZW5kIG9mIDIwMjEgY29ycmVzcG9uZHMgcm91Z2hseSB0byBvbmUgeWVhciBvZiBwcmVjaXBpdGF0aW9uLiAKCmBgYHtyfQoKaC5kYXRhJGN1bUVwb3QgPC0gY3Vtc3VtKGguZGF0YSRFcG90KSAjIGxvbmd0ZXJtIGN1bXVsYXRlZCB3YXRlciBkZWZpY2l0CgoKcGxvdChoLmRhdGEkZGF0ZSwgY3Vtc3VtKGguZGF0YSRSU0spLCAKICAgICB5bGltID0gYygwLDk1MDApLAogICAgIHhsYWIgPSAiRGF0ZSIsCiAgICAgeWxhYiA9ICJDdW11bGFyZWQgZmx1eCBzaW5jZSBPY3QgMSAyMDA1IGluIG1tIikKcG9pbnRzKGguZGF0YSRkYXRlLCBjdW1zdW0oaC5kYXRhJEVwb3QpLCAKIyAgICAgeWxpbSA9IGMoLTIwMCwyNTApLAogICAgIHhsYWIgPSAiZGF0ZSIsCiAgICAgY29sID0gInJlZCIpCmxlZ2VuZCh4ID0gInRvcGxlZnQiLCAgICAgICAgICAjIFBvc2l0aW9uCiAgICAgICBsZWdlbmQgPSBjKCJwcmVjaXBpdGF0aW9uIiwgIkVwb3QiKSwgICMgTGVnZW5kIHRleHRzCiAgICAgICBwY2ggPSBjKDEsIDEpLAogICAgICAgY29sID0gYygiYmxhY2siLCAicmVkIikKICAgICAgICkgIyBwb2ludCBjb2xvcnMKCgpgYGAKClRoZSBwcmVjaXBpdGF0aW9uIGFuZCBwb3RlbnRpYWwgZXZhcG9yYXRpb24gd2VyZSBhbG1vc3QgZXF1YWwgdW50aWwgcm91Z2hseSAyMDE1LCB3aGVuIHRoZXkgc3RhcnRlZCB0byBkZXZpYXRlIGZvciBzZXZlcmFsIHllYXJzIGluIGEgcm93LiBUaGUgcGxvdCBzaG93cyB0aGF0IHRoZSBkaXNjcmVwYW5jeSBidWlsdCB1cCBzaW5jZSAyMDE1LCBidXQgd2FzIG11Y2ggbW9yZSBwcm9ub3VuY2VkIGFmdGVyIDIwMTguCgoKIyMgUHJlY2lwaXRhdGlvbiBhbmFseXNpcwoKClFRcGxvdC4KCmBgYHtyfQoKcS5wX2RhaWx5LmFsbCA8LSBxdWFudGlsZShkYXRhJFJTSywgc2VxKDAuMDI1LDEsMC4wMjUpKQpxLnBfZGFpbHkuMjAxNF8yMDE3IDwtIHF1YW50aWxlKGRhdGFfMjAxNF8yMDE3JFJTSywgc2VxKDAuMDI1LDEsMC4wMjUpKQpxLnBfZGFpbHkuMjAxOF8yMDIxIDwtIHF1YW50aWxlKGRhdGFfMjAxOF8yMDIxJFJTSywgc2VxKDAuMDI1LDEsMC4wMjUpKQoKcGxvdChxLnBfZGFpbHkuYWxsLCBxLnBfZGFpbHkuMjAxNF8yMDE3LCAKICAgICB4bGFiID0gIlF1YW50aWxlcyBvZiBkYWlseSBwcmVjaXBpdGF0aW9uIDIwMDUtMjAyMSIsCiAgICAgeWxhYiA9ICJRdWFudGlsZXMgb2YgZGFpbHkgcHJlY2lwaXRhdGlvbiBpbiB0aGUgb2JzZXJ2YXRpb24gcGVyaW9kIiwKICAgICB4bGltID0gYygwLDEwMCksCiAgICAgeWxpbSA9IGMoMCwxMDApKQpwb2ludHMocS5wX2RhaWx5LmFsbCwgcS5wX2RhaWx5LjIwMThfMjAyMSwgCiAgICAgICAgY29sID0gInJlZCIpCgphYmxpbmUoYT0wLCBiPTEsICc6JykKCnBsb3QobG9nKHEucF9kYWlseS4yMDE0XzIwMTcrMSksIGxvZyhxLnBfZGFpbHkuMjAxOF8yMDIxKzEpLCAKICAgICB5bGltID0gYygwLDMpLAogICAgIHhsaW0gPSBjKDAsMyksCiAgICAgeGxhYiA9ICJRdWFudGlsZXMgb2YgZGFpbHkgcHJlY2lwaXRhdGlvbiAyMDE0LTIwMTciLAogICAgIHlsYWIgPSAiUXVhbnRpbGVzIG9mIGRhaWx5IHByZWNpcGl0YXRpb24gMjAxOC0yMDIxIikKYWJsaW5lKGE9MCwgYj0xLCAnOicpCgpUYWJsZV9RUCA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKHNlcSgwLjAyNSwxLDAuMDI1KSwgcS5wX2RhaWx5LjIwMTRfMjAxNywgcS5wX2RhaWx5LjIwMThfMjAyMSkpCm5hbWVzKFRhYmxlX1FQKSA8LSBjKCJQIiwgIlFQXzIwMTRfMjAxNyIsICJRUF8yMDE4XzIwMjEiKQoKd3JpdGUuY3N2KFRhYmxlX1FQLCAiVGFibGVfUVBfNjMwNS5jc3YiKQoKCmBgYAoKIyMgTnVtYmVyIG9mIGRheXMgd2l0aCBnaXZlbiByYWluZmFsbAoKQ2hlY2sgd2hldGhlciBjZXJ0YWluIHR5cGVzIG9mIGRhaWx5IHByZWNpcGl0YXRpb24gd2VyZSBtb3JlIG9yIGxlc3MgY29tbW9uIGFsb25nIHRoZSB0aW1lIHNlcmllcy4gRm9yIHRoaXMgSSB1c2UgdGhlIGVudGlyZSB0aW1lIHNlcmllcywgdG8gYmUgYWJsZSB0byBzZWUgdHJlbmRzIChpZiBhcHBsaWNhYmxlKS4KCkkgd2lsbCB0ZXN0IGZvcgoKLSBudW1iZXIgb2YgZGF5cyBwZXIgeWVhciB3aXRob3V0IHByZWNpcGl0YXRpb24gKHRocmVzaG9sZCAwLjEgbW0pCgotIGRheXMgc3VycGFzc2luZyBzbWFsbCBwcmVjaXBpdGF0aW9uICh0aHJlc2hvbGQgc2V0IHRvIDUgbW0pCgpMb29raW5nIGZvciBleHRyZW1lIHJhaW5mYWxsIHJlcXVpcmVzIGEgZGF0YXNldCBpbiBob3VybHkgb3Igc2l4IGhvdXJseSByZXNvbHV0aW9uLCBhbmQgY2Fubm90IGJlIGRvbmUgdXNpbmcgdGhpcyBkYWlseSBkYXRhc2V0LiBCdXQgdGhlIGRhdGEgaXMgYXZhaWxhYmxlIGZyb20gRFdELgoKYGBge3J9CiMgaW50aWFsaXplCm5kYXlzID0gYXJyYXkoZGF0YT1OQSxkaW0gPSBueWVhcnMsIGRpbW5hbWVzID0gTlVMTCkKbm9yYWluZGF5cyA9IGFycmF5KGRhdGE9TkEsZGltID0gbnllYXJzLCBkaW1uYW1lcyA9IE5VTEwpCnN0cm9uZ3JhaW5kYXlzID0gYXJyYXkoZGF0YT1OQSxkaW0gPSBueWVhcnMsIGRpbW5hbWVzID0gTlVMTCkKUCA9IGFycmF5KGRhdGE9TkEsZGltID0gbnllYXJzLCBkaW1uYW1lcyA9IE5VTEwpClBfc3Ryb25nID0gYXJyYXkoZGF0YT1OQSxkaW0gPSBueWVhcnMsIGRpbW5hbWVzID0gTlVMTCkKClBfdGhyZXNoID0gNQoKI2k9MQpmb3IgKGkgaW4gMTpueWVhcnMpIHsKZGF0YV95ciA9IHN1YnNldChkYXRhLCBmb3JtYXQoZGF0YSRkYXRlLCclWScpID09IGFzLmNoYXJhY3Rlcih5ZWFyc1tpXSkpCm5vcmFpbmRheXNbaV0gPSBsZW5ndGgod2hpY2goZGF0YV95ciRSU0s8MC4xKSkKcmFpbmRheXMgPSBucm93KGRhdGFfeXIpLW5vcmFpbmRheXMKc3Ryb25ncmFpbmRheXNbaV0gPSBsZW5ndGgod2hpY2goZGF0YV95ciRSU0s+UF90aHJlc2ggKSkKUFtpXSA8LSBzdW0oZGF0YV95ciRSU0spClBfc3Ryb25nW2ldIDwtIHN1bShkYXRhX3lyJFJTS1t3aGljaChkYXRhX3lyJFJTSz5QX3RocmVzaCApXSkKbmRheXNbaV0gPSBucm93KGRhdGFfeXIpCgp9CgpgYGAKCgojIyMjIEFubnVhbCBwcmVjaXBpdGF0aW9uIHRpbWUgc2VyaWVzCmBgYHtyfQoKcGFyKG1mcm93PWMoMSwzKSkKcGxvdCh5ZWFycywgUCwKICAgICB5bGFiID0gImFubnVhbCBwcmVjcGl0YXRpb24gaW4gbW0vYSIsCiAgICAgbWFpbiA9ICJhbGwgZGF5cyIpCgpwbG90KHllYXJzLCBQLVBfc3Ryb25nLAogICAgIHlsYWIgPSAiYW5udWFsIHByZWNwaXRhdGlvbiA8IDUgbW0gaW4gbW0vYSIsCiAgICAgbWFpbiA9ICJzbWFsbCBwcmVjaXBpdGF0aW9uIikKCnBsb3QoeWVhcnMsIFBfc3Ryb25nLAogICAgIHlsYWIgPSAiYW5udWFsIHByZWNwaXRhdGlvbiA+IDVtbSBpbiBtbS9hIiwKICAgICBtYWluID0gInByZWNpcGl0YXRpb24gPiA1IG1tL2QiKQoKCmBgYAoKCmBgYHtyfQpsbS5wX3lyIDwtbG0oUH55ZWFycykgIyBhbGwgeWVhcnMKc3VtbWFyeShsbS5wX3lyKQoKeXJzXzIwMTRfMjAyMSA9IGMoMTA6MTcpCgpsbS5wX3lyLjIwMTRfMjAyMSA8LWxtKFBbeXJzXzIwMTRfMjAyMV1+eWVhcnNbeXJzXzIwMTRfMjAyMV0pICMgMjAxNC0yMDIxIG9ubHkKc3VtbWFyeShsbS5wX3lyLjIwMTRfMjAyMSkKCmBgYAoKCk5vIG9idmlvdXMgdGVtcG9yYWwgdHJlbmQgaW4gYW5udWFsIHByZWNpcGl0YXRpb24uCgpgYGB7cn0KUF93ZWFrIDwtIFAtUF9zdHJvbmcKbG0ucF93ZWFrX3lyIDwtbG0oUF93ZWFrfnllYXJzKSMgYWxsIHllYXJzCnN1bW1hcnkobG0ucF93ZWFrX3lyKQoKCnN1bW1hcnkobG0oUF93ZWFrL1B+eWVhcnMpKSAjIGNvbnRyaWJ1dGlvbiBvZiB3ZWFrIHByZWNpcCB0byB0b3RhbCBwcmVjaXAKCmxtLndlYWtfcmFpbmRheXMgPC1sbSh3ZWFrcmFpbmRheXN+eWVhcnMpICMgYWxsIHllYXJzCnN1bW1hcnkobG0ud2Vha19yYWluZGF5cykKCnlyc18yMDE0XzIwMTggPSBjKDEwOjE3KQoKbG0ucHdfZWFrX3lyLjIwMTRfMjAyMSA8LWxtKFBfd2Vha1t5cnNfMjAxNF8yMDIxXX55ZWFyc1t5cnNfMjAxNF8yMDIxXSkgIyAyMDE0LTIwMjEgb25seQpzdW1tYXJ5KGxtLnB3X2Vha195ci4yMDE0XzIwMjEpCgpgYGAKRGVjcmVhc2Ugb2YgbG93IGludGVuc2l0eSBwcmVjaXBpdGF0aW9uIChQPDUgbW0vZCkgcGFydCBvZiBhbm51YWwgcHJlY2lwaXRhdGlvbiBvdmVyIHRoZSBlbnRpcmUgcGVyaW9kLCBidXQgbm90IHNpZ25pZmljYW50IG92ZXIgdGhlIHNob3J0ZXIgcGVyaW9kLgoKCmBgYHtyfQpsbS5wX3N0cm9uZ195ciA8LWxtKFBfc3Ryb25nfnllYXJzKSAjIGFsbCB5ZWFycwpzdW1tYXJ5KGxtLnBfc3Ryb25nX3lyKQoKeXJzXzIwMTRfMjAxOCA9IGMoMTA6MTcpCgpsbS5wX3N0cm9uZ195ci4yMDE0XzIwMjEgPC1sbShQX3N0cm9uZ1t5cnNfMjAxNF8yMDIxXX55ZWFyc1t5cnNfMjAxNF8yMDIxXSkgIyAyMDE0LTIwMjEgb25seQpzdW1tYXJ5KGxtLnBfc3Ryb25nX3lyLjIwMTRfMjAyMSkKYGBgCgoKCmBgYHtyfQpwbG90KHllYXJzLCBQX3N0cm9uZy9QKQpwbG90KHllYXJzLCBzdHJvbmdyYWluZGF5cy9yYWluZGF5cykKCnN1bW1hcnkobG0oUF9zdHJvbmcvUH55ZWFycykpCnN1bW1hcnkobG0oc3Ryb25ncmFpbmRheXMvcmFpbmRheXN+eWVhcnMpKQoKYGBgCgoKIyMjIyBEYXlzIHBlciB5ZWFyIHdpdGhvdXQgcHJlY2lwaXRhdGlvbi4gCgpgYGB7cn0KcGxvdCh5ZWFycywgbm9yYWluZGF5cykKbG0ubm9yYWluIDwtIGxtKG5vcmFpbmRheXN+eWVhcnMpICMgYWxsIHllYXJzCnN1bW1hcnkobG0ubm9yYWluKQoKbG0ubm9yYWluLjIwMTRfMjAyMSA8LSBsbShub3JhaW5kYXlzW3lyc18yMDE0XzIwMThdfnllYXJzW3lyc18yMDE0XzIwMThdKSAjIGFsbCB5ZWFycwpzdW1tYXJ5KGxtLm5vcmFpbi4yMDE0XzIwMjEpCmBgYAoKIyMjIyBEYXlzIHdpdGggc29tZSByYWluCgpgYGB7cn0Kd2Vha3JhaW5kYXlzID0gcmFpbmRheXMgLSBzdHJvbmdyYWluZGF5cwpwbG90KHllYXJzLCB3ZWFrcmFpbmRheXMpCmxtLndlYWtyYWluIDwtIGxtKHdlYWtyYWluZGF5c355ZWFycykKc3VtbWFyeShsbS53ZWFrcmFpbikKYGBgCgojIyMjIERheXMgd2l0aCBzdWJzdGFudGlhbCByYWluCgpgYGB7cn0KcGxvdCh5ZWFycywgc3Ryb25ncmFpbmRheXMpCmxtLnN0cm9uZ3JhaW4gPC0gbG0oc3Ryb25ncmFpbmRheXN+eWVhcnMpCnN1bW1hcnkobG0uc3Ryb25ncmFpbikKCmBgYAoKCmBgYHtyfQp0YWJsZV9QRVRfUCA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKGgueWVhcnMsICBQLnllYXJseSwgRXBvdC55ZWFybHkpKQpjb2xuYW1lcyh0YWJsZV9QRVRfUCkgPC0gYygieWVhcnMiLCAiUCIsICJQRVQiKQp3cml0ZS5jc3YodGFibGVfUEVUX1AsIGZpbGU9IlBfUEVUXzE2eXJzXzYzMDUuY3N2IikKClB0YWJsZSA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKHllYXJzLCBQLCBQLVBfc3Ryb25nLCBQX3N0cm9uZywgbm9yYWluZGF5cywgd2Vha3JhaW5kYXlzLCBzdHJvbmdyYWluZGF5cykpCgpjb2xuYW1lcyhQdGFibGUpIDwtIGMoInllYXIiLCAiUCIsIlBfc21hbGwiLCAiUF9zdWJzdCIsICJuZGF5c19ub3JhaW4iLCJuZGF5c193ZWFrcmFpbiIsIm5kYXlzX3N1YnN0cmFpbiIpCndyaXRlLmNzdihQdGFibGUsIGZpbGUgPC0gIlB0YWJsZV8xNnlyc182MzA1LmNzdiIpCgpgYGAKCgoKCgo=