AZMP cruise data was searched manually to find cruises where there were both Winkler and probe measurements. Within Gordana’s files there were three cruises which qualified, HUD2011004, HUD2011043 and HUD2012042

These files were read in as csv’s using the BCD flagged files to provide the most accurate and up to date QC. Once the files were copied from the shared drive to the local drive they were read in as seen below (caution this section will not run unless file paths are exact)

#read in BCD files
H11004_bcd <- read.csv('HUD2011004/HUD2011004_BCD_flagged.csv')
H11043_bcd <- read.csv('HUD2011043/HUD2011043_BCD_flagged.csv')
H12042_bcd <- read.csv('HUD2012042/HUD2012042_BCD_flagged.csv')

Once files were read into R, Winkler and probe data was found and pulled.

#find rows with winkler data
H11004_wink <- grep(H11004_bcd$DATA_TYPE_METHOD, pattern = 'O2_Winkler_Auto')
H11043_wink <- grep(H11043_bcd$DATA_TYPE_METHOD, pattern = 'O2_Winkler_Auto')
H12042_wink <- grep(H12042_bcd$DATA_TYPE_METHOD, pattern = 'O2_Winkler_Auto')
#find rows with probe data
H11004_elec <- grep(H11004_bcd$DATA_TYPE_METHOD, pattern = 'O2_Electrode_mll')
H11043_elec <- grep(H11043_bcd$DATA_TYPE_METHOD, pattern = 'O2_Electrode_mll')
H12042_elec <- grep(H12042_bcd$DATA_TYPE_METHOD, pattern = 'O2_Electrode_mll')
#pull winkler data
H11004_wink_data <- H11004_bcd$DIS_DETAIL_DATA_VALUE[H11004_wink]
H11004_wink_dpth <- H11004_bcd$DIS_HEADER_START_DEPTH[H11004_wink]
H11043_wink_data <- H11043_bcd$DIS_DETAIL_DATA_VALUE[H11043_wink]
H11043_wink_dpth <- H11043_bcd$DIS_HEADER_START_DEPTH[H11043_wink]
H12042_wink_data <- H12042_bcd$DIS_DETAIL_DATA_VALUE[H12042_wink]
H12042_wink_dpth <- H12042_bcd$DIS_HEADER_START_DEPTH[H12042_wink]
#pull probe data
H11004_elec_data <- H11004_bcd$DIS_DETAIL_DATA_VALUE[H11004_elec]
H11004_elec_dpth <- H11004_bcd$DIS_HEADER_START_DEPTH[H11004_elec]
H11043_elec_data <- H11043_bcd$DIS_DETAIL_DATA_VALUE[H11043_elec]
H11043_elec_dpth <- H11043_bcd$DIS_HEADER_START_DEPTH[H11043_elec]
H12042_elec_data <- H12042_bcd$DIS_DETAIL_DATA_VALUE[H12042_elec]
H12042_elec_dpth <- H12042_bcd$DIS_HEADER_START_DEPTH[H12042_elec]

Once probe and Winkler data has been isolated, an initial plot gives a general idea of the data set for each cruise.

plot(H11004_wink_data, H11004_wink_dpth, ylim = c(5000, 0), xlim = c(3, 9), col = 'blue', ylab = 'Depth (m)', xlab = 'O2 concentration (ml/l)',main = 'Oxygen data from HUD2011004', sub = 'Winkler vs Probe(Orion 842)')
par(new = TRUE)
plot(H11004_elec_data, H11004_elec_dpth, ylim = c(5000, 0), xlim = c(3, 9), axes = FALSE, col = 'black', xlab = '', ylab = '')
legend('bottomleft', legend = c('WINKLER', 'PROBE'), col = c('blue', 'black'), lty = 1, cex = 0.6)

plot(H11043_wink_data, H11043_wink_dpth, ylim = c(5000, 0), xlim = c(2, 9), col = 'blue', ylab = 'Depth (m)', xlab = 'O2 concentration (ml/l)',main = 'Oxygen data from HUD2011043', sub = 'Winkler vs Probe(Orion 842)')
par(new = TRUE)
plot(H11043_elec_data, H11043_elec_dpth, ylim = c(5000, 0), xlim = c(2, 9), axes = FALSE, col = 'black', xlab = '', ylab = '')
legend('bottomleft', legend = c('WINKLER', 'PROBE'), col = c('blue', 'black'), lty = 1, cex = 0.6)

plot(H12042_wink_data, H12042_wink_dpth, ylim = c(5000, 0), xlim = c(1, 9), col = 'blue', ylab = 'Depth (m)', xlab = 'O2 concentration (ml/l)',main = 'Oxygen data from HUD2012042', sub = 'Winkler vs Probe(Orion 842)')
par(new = TRUE)
plot(H12042_elec_data, H12042_elec_dpth, ylim = c(5000, 0), xlim = c(1, 9), axes = FALSE, col = 'black', xlab = '', ylab = '')
legend('bottomleft', legend = c('WINKLER', 'PROBE'), col = c('blue', 'black'), lty = 1, cex = 0.6)

The next step in analysis was to match the sample ID’s for each measurement method so that DO could be directly compared. There was a minor bug with the length of the vectors but this was easily solved.

#isolate individual bottles
#hud2011004
#pull sample ids
H11004_wink_id <- H11004_bcd$DIS_DETAIL_COLLECTOR_SAMP_ID[H11004_wink] #length = 137
H11004_elec_id <- H11004_bcd$DIS_DETAIL_COLLECTOR_SAMP_ID[H11004_elec] #length = 176
#These are different lengths meaning not all sample ids can match
length(H11004_wink_id) <- 176 #fix length issue
#combine lists
H11004_id <- cbind(H11004_wink_id, H11004_elec_id)
#compare lists
H11004_id_match <- H11004_wink_id == H11004_elec_id #useless
#most sample id's match but they are ordered differently, must compare 1 by 1
#create matching list wink:elec
match <- list()
for (i in 1:176){
  h <- H11004_wink_id[i] == H11004_elec_id
  m <- grep(h, pattern = TRUE)
  #m <- grep(pattern = H11004_wink_id[i], H11004_elec_id)
  if(length(m >0)){
  match[i] <- m
  }else{
    match[i] <- NULL
  }
}
#name list wink:elec
    #why is list only 175 items, should be 176, last is NULL?
names(match) <- c(1:175)
H11004_wink_elec <- list()
for (i in 1:175){
  if(!is.null(match[[i]])){
H11004_wink_elec[i] <- H11004_wink_data[[i]] - H11004_elec_data[[match[[i]]]]
  }else{
  H11004_wink_elec[i] <- NULL
}
}
#keeps subtracting one from length?
length(H11004_wink_elec) <- 175

Once individual sample ID’s could be compared it was possible to plot the difference between methods.

#plot differences (wink-elec)
plot(unlist(match), unlist(H11004_wink_elec), type = 'h', xlab = 'sample ID', ylab = 'Winkler - electrode value')
mtext('Difference between Winkler and Electrode values 
      (HUD2011004)')

Some summary statistics were also calculated at this point and presented in the report.

This process was then repeated for each cruise.

HUD2011043

#hud2011043
#pull sample ids
H11043_wink_id <- H11043_bcd$DIS_DETAIL_COLLECTOR_SAMP_ID[H11043_wink] #length = 310
H11043_elec_id <- H11043_bcd$DIS_DETAIL_COLLECTOR_SAMP_ID[H11043_elec] #length = 71
#These are different lengths meaning not all sample ids can match
length(H11043_elec_id) <- 310 #fix length issue
#combine lists
H11043_id <- cbind(H11043_wink_id, H11043_elec_id)
#compare lists
H11043_id_match <- H11043_wink_id == H11043_elec_id #useless
#most sample id's match but they are ordered differently, must compare 1 by 1
#create matching list wink:elec
match2 <- list()
for (i in 1:310){
  h <- H11043_wink_id[i] == H11043_elec_id
  m <- grep(h, pattern = TRUE)
  #m <- grep(pattern = H11004_wink_id[i], H11004_elec_id)
  if(length(m >0)){
    match2[i] <- m
  }else{
    match2[i] <- NULL
  }
}
#name list wink:elec
#why is list one short of full length?
names(match2) <- c(1:309)
H11043_wink_elec <- list()
for (i in 1:309){
  if(!is.null(match2[[i]])){
    H11043_wink_elec[i] <- H11043_wink_data[[i]] - H11043_elec_data[[match2[[i]]]]
  }else{
    H11043_wink_elec[i] <- NULL
  }
}
#keeps subtracting one from length?
length(H11043_wink_elec) <- 310
#plot differences (wink-elec)
plot(unlist(match2), unlist(H11043_wink_elec), type = 'h', xlab = 'sample ID', ylab = 'Winkler - electrode value')
mtext('Difference between Winkler and Electrode values 
      (HUD2011043)')

HUD2012042

#Hud2012042
#pull sample ids
H12042_wink_id <- H12042_bcd$DIS_DETAIL_COLLECTOR_SAMP_ID[H12042_wink] #length = 486
H12042_elec_id <- H12042_bcd$DIS_DETAIL_COLLECTOR_SAMP_ID[H12042_elec] #length = 207
#These are different lengths meaning not all sample ids can match
length(H12042_elec_id) <- 486 #fix length issue
#combine lists
H12042_id <- cbind(H12042_wink_id, H12042_elec_id)
#compare lists
H12042_id_match <- H12042_wink_id == H12042_elec_id #useless
#most sample id's match but they are ordered differently, must compare 1 by 1
#create matching list wink:elec
match3 <- list()
for (i in 1:486){
  h <- H12042_wink_id[i] == H12042_elec_id
  m <- grep(h, pattern = TRUE)
  #m <- grep(pattern = H11004_wink_id[i], H11004_elec_id)
  if(length(m >0)){
    match3[i] <- m
  }else{
    match3[i] <- NULL
  }
}
#name list wink:elec
#why is list only 175 items, should be 176, last is NULL?
names(match3) <- c(1:486)
H12042_wink_elec <- list()
for (i in 1:486){
  if(!is.null(match3[[i]])){
    H12042_wink_elec[i] <- H12042_wink_data[[i]] - H12042_elec_data[[match3[[i]]]]
  }else{
    H12042_wink_elec[i] <- NULL
  }
}
#keeps subtracting one from length?
length(H12042_wink_elec) <- 486
#plot differences (wink-elec)
plot(unlist(match3), unlist(H12042_wink_elec), type = 'h', xlab = 'sample ID', ylab = 'Winkler - electrode value')
mtext('Difference between Winkler and Electrode values 
      (HUD2012042)')

Further statistics were calculated including a t test and confidence intervals

##is the mean difference significantly diffrent from zero?
  #t test
a <- 0.01
H12042_t <- t.test(x = unlist(H12042_wink_elec))
H11043_t <- t.test(x = unlist(H11043_wink_elec))
H11004_t <- t.test(x = unlist(H11004_wink_elec))
ci1 <- H11004_t$conf.int
ci2 <- H11043_t$conf.int
ci3 <- H12042_t$conf.int
x <- c(1: 200)
a <- unlist(H11004_wink_elec)
b <- unlist(H11043_wink_elec)
c <- unlist(H12042_wink_elec)
length(a) <- 200
length(b) <- 200
length(c) <- 200
plot(x, a, col = 'black', ylim = c(-2.5, 2.5), xlab = 'Sample ID', ylab = "Difference Winkler - Electrode (ml/l)" )
mtext('Difference between 
      Winkler and Electrode Methods')
mtext("Black: HUD2011004,
  Blue: HUD2011043, 
  Red: HUD2012042", side = 1, cex = 0.8, line = -2)
par(new = TRUE)
plot(x, b, col = 'blue', ylim = c(-2.5, 2.5), axes = FALSE, xlab = '', ylab = '')
par(new = TRUE)
plot(x, c, col = 'red', ylim = c(-2.5, 2.5), axes = FALSE, xlab = '', ylab = '')
#confidence interval lines
abline(h = ci1[[1]], col = 'black')
abline(h = ci1[[2]], col = 'black')
abline(h = ci2[[1]], col = 'blue')
abline(h = ci2[[2]], col = 'blue')
abline(h = ci3[[1]], col = 'red')
abline(h = ci3[[2]], col = 'red')

The next step of analysis was to remove outliers in the Winkler data using Andrew Cogswell’s method of eliminating points outside 1.5*IQR

#eliminate outliers (past 1.5 IQT, and flagged values)
#calculate iqt
H11004_iqr<- IQR(H11004_wink_data, na.rm = TRUE)
H11043_iqr <- IQR(H11043_wink_data, na.rm = TRUE)
H12042_iqr <- IQR(H12042_wink_data, na.rm = TRUE)
#calculate 1.5 iqt
H11004_iqr_1.5 <- 1.5*(H11004_iqr)
H11043_iqr_1.5 <- 1.5*(H11043_iqr)
H12042_iqr_1.5 <- 1.5*(H12042_iqr)
#calculate mean
H11004_wink_mean <- mean(H11004_wink_data)
H11043_wink_mean <- mean(H11043_wink_data)
H12042_wink_mean <- mean(H12042_wink_data)

This was then plotted so data could be visualized and ensure correct removal of outliers

#hud2011004
plot( c(1:length(H11004_wink_data)), unlist(H11004_wink_data), xlab = 'Sample ID', ylab = 'Oxygen COncentration (ml/L)')
mtext('Dissolved Oxygen Winkler Measurements
      HUD2011004')
par(new = TRUE)
abline(h = H11004_wink_mean, col = 'blue')
uiqr <- 0.5*(H11004_iqr_1.5) + H11004_wink_mean
liqr <- H11004_wink_mean - 0.5*(H11004_iqr_1.5) 
abline(h = uiqr, col = 'red')
abline(h = liqr, col = 'red')

#null values outside 1.5 iqt
H11004_wink_data[H11004_wink_data > uiqr] <- NA
H11004_wink_data[H11004_wink_data < liqr] <- NA
plot(c(1:length(H11004_wink_data)), unlist(H11004_wink_data), ylim = c(3,9), xlab = 'Sample ID', ylab = 'Dissolved OXygen (ml/L)')
mtext('Winkler Oxygen Measurements after QC
      HUD2011004')
mtext('Red lines represent 1.5 IQT', side = 1, cex = 0.8)
abline(h = uiqr, col = 'red')
abline(h = liqr, col = 'red')

#hud2011043
plot( c(1:length(H11043_wink_data)), unlist(H11043_wink_data), xlab = 'Sample ID', ylab = 'Oxygen COncentration (ml/L)')
mtext('Dissolved Oxygen Winkler Measurements
      HUD2011043')
par(new = TRUE)
abline(h = H11043_wink_mean, col = 'blue')
uiqr2 <- 0.5*(H11043_iqr_1.5) + H11043_wink_mean
liqr2 <- H11043_wink_mean - 0.5*(H11043_iqr_1.5) 
abline(h = uiqr2, col = 'red')
abline(h = liqr2, col = 'red')

#null values outside 1.5 iqt
H11043_wink_data[H11043_wink_data > uiqr2] <- NA
H11043_wink_data[H11043_wink_data < liqr2] <- NA
plot(c(1:length(H11043_wink_data)), unlist(H11043_wink_data), ylim = c(3, 7), xlab = 'Sample ID', ylab = 'Dissolved OXygen (ml/L)')
mtext('Winkler Oxygen Measurements after QC
      HUD2011043')
mtext('Red lines represent 1.5 IQT', side = 1, cex = 0.8)
abline(h = uiqr2, col = 'red')
abline(h = liqr2, col = 'red')

#hud2012042
plot( c(1:length(H12042_wink_data)), unlist(H12042_wink_data), xlab = 'Sample ID', ylab = 'Oxygen Concentration (ml/L)')
mtext('Dissolved Oxygen Winkler Measurements
      HUD2012042')
par(new = TRUE)
abline(h = H12042_wink_mean, col = 'blue')
uiqr3 <- 0.5*(H12042_iqr_1.5) + H12042_wink_mean
liqr3 <- H12042_wink_mean - 0.5*(H12042_iqr_1.5) 
abline(h = uiqr3, col = 'red')
abline(h = liqr3, col = 'red')

#null values outside 1.5 iqt
H12042_wink_data[H12042_wink_data > uiqr3] <- NA
H12042_wink_data[H12042_wink_data < liqr3] <- NA
plot(c(1:length(H12042_wink_data)), unlist(H12042_wink_data), ylim = c(2,7), xlab = 'Sample ID', ylab = 'Dissolved Oxygen (ml/L)')
mtext('Winkler Oxygen Measurements after QC
      HUD2012042')
mtext('Red lines represent 1.5 IQT', side = 1, cex = 0.8)
abline(h = uiqr3, col = 'red')
abline(h = liqr3, col = 'red')

Differences within individual sample ID’s were then recalculated, removing any samples where the Winkler value was null due to being an outlier.

#plot differences after removal
#hud2011004
H11004_wink_elec_1 <- list()
for( i in 1:175){
  if(!is.null(match[[i]])){
    H11004_wink_elec_1[i] <- H11004_wink_data[[i]] - H11004_elec_data[[match[[i]]]]
  }else{
    H11004_wink_elec_1[i] <- NULL
  }
}
plot(unlist(match), unlist(H11004_wink_elec_1), type = 'h', xlab = 'Sample ID', ylab = 'Winkler - Electrode (DO , ml/L)')
mtext('Difference between Winkler and Electrode values (post QC)
      HUD2011004')

#hud2011043
H11043_wink_elec_1 <- list()
for( i in 1:309){
  if(!is.null(match2[[i]])){
    H11043_wink_elec_1[i] <- H11043_wink_data[[i]] - H11043_elec_data[[match2[[i]]]]
  }else{
    H11043_wink_elec_1[i] <- NULL
  }
}
plot(unlist(match2), unlist(H11043_wink_elec_1), type = 'h', xlab = 'Sample ID', ylab = 'Winkler - Electrode (DO , ml/L)')
mtext('Difference between Winkler and Electrode values (post QC)
      HUD2011043')

#hud2012042
H12042_wink_elec_1 <- list()
for( i in 1:486){
  if(!is.null(match3[[i]])){
    H12042_wink_elec_1[i] <- H12042_wink_data[[i]] - H12042_elec_data[[match3[[i]]]]
  }else{
    H12042_wink_elec_1[i] <- NULL
  }
}
plot(unlist(match3), unlist(H12042_wink_elec_1), type = 'h', xlab = 'Sample ID', ylab = 'Winkler - Electrode (DO , ml/L)')
mtext('Difference between Winkler and Electrode values (post QC)
      HUD2012042')

Depth profiles were then visualized again to see if there were any significant visual patterns or relationship between depth and offset between Winkler and probe data.

##post QC depth profiles
plot(H11004_wink_data, H11004_wink_dpth, ylim = (c(5000, 0)), xlim = c(4,9), xlab = 'DO ml/L', ylab = 'Depth (m)', main = 'HUD2011004')
par(new = TRUE)
plot(H11004_elec_data, H11004_elec_dpth, ylim = (c(5000, 0)),xlim = c(4,9), axes = FALSE, col = 'blue', xlab = '', ylab = '')
legend('bottomright',  c('Winkler', 'Electrode'), col = c('black', 'blue'), lty = 1)

plot(H11043_wink_data, H11043_wink_dpth, ylim = (c(5000, 0)), xlim = c(4,9), xlab = 'DO ml/L', ylab = 'Depth (m)', main = 'HUD2011043')
par(new = TRUE)
plot(H11043_elec_data, H11043_elec_dpth, ylim = (c(5000, 0)),xlim = c(4,9), axes = FALSE, col = 'blue', xlab = '', ylab = '')
legend('bottomright',  c('Winkler', 'Electrode'), col = c('black', 'blue'), lty = 1)

plot(H12042_wink_data, H12042_wink_dpth, ylim = (c(5000, 0)), xlim = c(4,9), xlab = 'DO ml/L', ylab = 'Depth (m)', main = 'HUD2012042')
par(new = TRUE)
plot(H12042_elec_data, H12042_elec_dpth, ylim = (c(5000, 0)),xlim = c(4,9), axes = FALSE, col = 'blue', xlab = '', ylab = '')
legend('bottomright',  c('Winkler', 'Electrode'), col = c('black', 'blue'), lty = 1, cex = 0.8)

The next step in Analysis was to plot Winkler and Electrode data against each other for each cruise to attempt a linear regression. In an ideal situtation the data would have presented with a 1:1 relationship, high correlation and minimal offset (intercept).

For cruise HUD2011004

H11004_winkelec <- matrix(NA, nrow = 175, ncol = 2)
for( i in 1:175){
  if(!is.null(match[[i]])){
    H11004_winkelec[i,1] <- H11004_wink_data[[i]] 
    H11004_winkelec[i,2] <- H11004_elec_data[[match[[i]]]]
  # }else{
  #   H11004_winkelec[i,] <- NULL
   }
}
plot(H11004_winkelec[,1], H11004_winkelec[,2], xlim = c(0,7), ylim = c(0,7),xlab = 'Winkler Data', ylab = 'Electrode Data')
par(new = TRUE)
lm <- lm(H11004_winkelec[,1] ~ H11004_winkelec[,2])
abline(lm)
abline(coef = c(0, 1), col = 'red')
title(main = 'HUD2011004')
title(sub = 'R^2 = 0.9844')

Where black line represents simple linear regression on the data and red line represents perfect 1:1 relationship with 0 intercept.

Statistic summary

summary(lm)

Call:
lm(formula = H11004_winkelec[, 1] ~ H11004_winkelec[, 2])

Residuals:
     Min       1Q   Median       3Q      Max 
-0.75153 -0.08761  0.01495  0.10951  0.43717 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)          -1.30733    0.10351  -12.63   <2e-16 ***
H11004_winkelec[, 2]  1.27511    0.01592   80.10   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1696 on 102 degrees of freedom
  (71 observations deleted due to missingness)
Multiple R-squared:  0.9844,    Adjusted R-squared:  0.9842 
F-statistic:  6417 on 1 and 102 DF,  p-value: < 2.2e-16
plot(lm)

For cruise HUD2011043

H11043_winkelec <- matrix(NA, nrow = 310, ncol = 2)
for( i in 1:309){
  if(!is.null(match2[[i]])){
    H11043_winkelec[i,1] <- H11043_wink_data[[i]] 
    H11043_winkelec[i,2] <- H11043_elec_data[[match2[[i]]]]
  # }else{
  #   H11043_winkelec[i,] <- NULL
   }
}
plot(H11043_winkelec[,1], H11043_winkelec[,2], xlim = c(0, 7), ylim = c(0,7), xlab = 'Winkler Data', ylab = 'Electrode Data')
par(new = TRUE)
lm2 <- lm(H11043_winkelec[,1] ~ H11043_winkelec[,2])
abline(lm2)
abline(coef = c(0, 1), col = 'red')
title(main = 'HUD2011043')
title(sub = 'R^2 = 0.3697')

Where black line represents simple linear regression on the data and red line represents perfect 1:1 relationship with 0 intercept.

Statistic summary

summary(lm2)

Call:
lm(formula = H11043_winkelec[, 1] ~ H11043_winkelec[, 2])

Residuals:
     Min       1Q   Median       3Q      Max 
-0.77188 -0.15051  0.04768  0.19181  0.49000 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)            2.8913     0.6757   4.279 0.000159 ***
H11043_winkelec[, 2]   0.5370     0.1240   4.332 0.000136 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2698 on 32 degrees of freedom
  (276 observations deleted due to missingness)
Multiple R-squared:  0.3697,    Adjusted R-squared:   0.35 
F-statistic: 18.77 on 1 and 32 DF,  p-value: 0.0001365
plot(lm2)

For cruise HUD2012042

length(H12042_elec_data) <- 486
H12042_winkelec <- matrix(NA, nrow = 486, ncol = 2)
for( i in 1:486){
  if(!is.null(match3[[i]])){
    H12042_winkelec[i,1] <- H12042_wink_data[[i]] 
    H12042_winkelec[i,2] <- H12042_elec_data[[match3[[i]]]]
   # }else{
   #   H12042_winkelec[i,] <- NULL
   }
}
plot(H12042_winkelec[,1], H12042_winkelec[,2],xlim = c(0,7), ylim = c(0,7), xlab = 'Winkler Data', ylab = 'Electrode Data')
par(new = TRUE)
lm3 <- lm(H12042_winkelec[,1] ~ H12042_winkelec[,2])
abline(lm3)
abline(coef = c(0, 1), col = 'red')
title(main = 'HUD2012042')
title(sub = 'R^2 = 0.4968')

Where black line represents simple linear regression on the data and red line represents perfect 1:1 relationship with 0 intercept.

Statistic summary

summary(lm3)

Call:
lm(formula = H12042_winkelec[, 1] ~ H12042_winkelec[, 2])

Residuals:
    Min      1Q  Median      3Q     Max 
-1.3420 -0.1528  0.1133  0.2371  0.5601 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)           0.89119    0.46932   1.899   0.0607 .  
H12042_winkelec[, 2]  0.82843    0.08693   9.530 2.22e-15 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.3978 on 92 degrees of freedom
  (392 observations deleted due to missingness)
Multiple R-squared:  0.4968,    Adjusted R-squared:  0.4913 
F-statistic: 90.83 on 1 and 92 DF,  p-value: 2.221e-15
plot(lm3)

In order to determine if the relationship between Winkler and electrode data was pressure dependent the differences by cruise were plotted over depth along with simple linear regression and summary statistics

For HUD2011004

length(H11004_wink_dpth) <- 131
plot( H11004_wink_dpth, unlist(H11004_wink_elec_1), ylim = c(-2, 2), xlab = 'Depth (m)', ylab = 'Difference (Winkler - electrode)')
abline(h = 0, col = 'blue')
ll <- lm( unlist(H11004_wink_elec_1) ~ H11004_wink_dpth)
abline(ll, col = 'red')
title(main = 'HUD2011004', sub = 'R^2 = 0.01128')

summary(ll)

Call:
lm(formula = unlist(H11004_wink_elec_1) ~ H11004_wink_dpth)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.88809 -0.21947  0.09733  0.25251  0.70152 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)      4.405e-01  3.675e-02  11.988   <2e-16 ***
H11004_wink_dpth 3.770e-05  3.494e-05   1.079    0.283    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.3342 on 102 degrees of freedom
  (27 observations deleted due to missingness)
Multiple R-squared:  0.01128,   Adjusted R-squared:  0.00159 
F-statistic: 1.164 on 1 and 102 DF,  p-value: 0.2832
plot(ll)

For HUD2011043

dp2 <- list()
for (i in 1:length(H11043_wink_elec_1)){
  if(is.null(H11043_wink_elec_1[[i]])){
    dp2[i] <- NULL
  } else{
    dp2[i] <- H11043_wink_dpth[[i]]
  }
}
plot(unlist(dp2), unlist(H11043_wink_elec_1), ylim = c(-2, 2), xlab = 'Depth (m)', ylab = 'Difference (Winkler - Electrode)')
abline(h = 0, col = 'blue')
ll2 <- lm(unlist(H11043_wink_elec_1) ~ unlist(dp2))
abline(ll2, col = 'red')
title(main = 'HUD2011043', sub = 'R^2 = 0.00944')

summary(ll2)

Call:
lm(formula = unlist(H11043_wink_elec_1) ~ unlist(dp2))

Residuals:
     Min       1Q   Median       3Q      Max 
-0.84757 -0.12671  0.06725  0.16245  0.56277 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  3.893e-01  6.233e-02   6.245 5.35e-07 ***
unlist(dp2) -2.088e-05  3.780e-05  -0.552    0.585    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.3218 on 32 degrees of freedom
  (22 observations deleted due to missingness)
Multiple R-squared:  0.009444,  Adjusted R-squared:  -0.02151 
F-statistic: 0.3051 on 1 and 32 DF,  p-value: 0.5845
plot(ll2)

For HUD2012042

dp3 <- list()
for (i in 1:length(H12042_wink_elec_1)){
  if(is.null(H12042_wink_elec_1[[i]])){
    dp3[i] <- NULL
  } else{
    dp3[i] <- H12042_wink_dpth[[i]]
  }
}
plot(unlist(dp3), unlist(H12042_wink_elec_1), ylim = c(-2, 2), xlab = 'Depth (m)', ylab = 'Difference (Winkler - Electrode)')
abline(h = 0, col = 'blue')
ll3 <- lm(unlist(H12042_wink_elec_1) ~ unlist(dp3))
abline(ll3, col = 'red')
title(main = 'HUD2012042', sub = 'R^2 = 0.7767')

summary(ll3)

Call:
lm(formula = unlist(H12042_wink_elec_1) ~ unlist(dp3))

Residuals:
     Min       1Q   Median       3Q      Max 
-1.33694 -0.07307  0.13191  0.23863  0.49426 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)   
(Intercept) -7.746e-02  4.348e-02  -1.782  0.07812 . 
unlist(dp3)  9.929e-05  3.567e-05   2.783  0.00653 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.3901 on 92 degrees of freedom
  (72 observations deleted due to missingness)
Multiple R-squared:  0.07767,   Adjusted R-squared:  0.06765 
F-statistic: 7.748 on 1 and 92 DF,  p-value: 0.006527
plot(ll3)

This procedure was done to mimic CTD QC procedure but may not have signifcant bearing on the statistical results. In theory there should be no relationship between pressure and Winkler - electrode measurements since both measurements are made a t the surface, although there may be some relationship between accuracy/ offset between methods and dissolved oxygen concentration which will be tested next.

Difference (winkler - electrode measurement per sample ID) was plotted over DO concentration for each cruise, blue line are at y = 0 and red lines represent simple linear regression of the data.

For HUD2011004

wd <- list()
for (i in 1:length(H11004_wink_data)){
  if (is.null(H11004_wink_elec_1[[i]])){
    wd[[i]] <- NULL
  } else{
    wd[[i]] <- H11004_wink_data[[i]]
  }
}
length(H11004_wink_elec_1) <- length(wd)
plot(unlist(wd), unlist(H11004_wink_elec_1), ylim = c(-3,3), xlab = 'DO Concentrations, ml/l', ylab = 'Difference (Winkler - electrode)')
abline(h = 0, col = 'blue')
lh <- lm(unlist(H11004_wink_elec_1) ~ unlist(wd))
abline(lh, col = 'red')
title(main = 'HUD2011004')

summary(lh)

Call:
lm(formula = unlist(H11004_wink_elec_1) ~ unlist(wd))

Residuals:
     Min       1Q   Median       3Q      Max 
-0.57249 -0.07691  0.01129  0.09296  0.32293 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) -1.109656   0.067524  -16.43   <2e-16 ***
unlist(wd)   0.228027   0.009637   23.66   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1319 on 102 degrees of freedom
  (27 observations deleted due to missingness)
Multiple R-squared:  0.8459,    Adjusted R-squared:  0.8444 
F-statistic: 559.9 on 1 and 102 DF,  p-value: < 2.2e-16
plot(lh)

For HUD2011043

wd2 <- list()
for (i in 1:length(H11043_wink_elec_1)){
  if (is.null(H11043_wink_elec_1[[i]])){
    wd2[[i]] <- NULL
  } else{
    wd2[[i]] <- H11043_wink_data[[i]]
  }
}
wd2 <- unlist(wd2)
length(wd2) <- 56
plot(wd2, unlist(H11043_wink_elec_1), ylim = c(-3,3), xlab = 'DO Concentrations, ml/l', ylab = 'Difference (Winkler - electrode)')
abline(h = 0, col = 'blue')
lh2 <- lm(unlist(H11043_wink_elec_1) ~ wd2)
abline(lh2, col = 'red')
title(main = 'HUD2011043')

summary(lh2)

Call:
lm(formula = unlist(H11043_wink_elec_1) ~ wd2)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.95656 -0.06824  0.02838  0.13253  0.53755 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)  
(Intercept)  -1.4374     0.9250  -1.554   0.1301  
wd2           0.3115     0.1589   1.961   0.0587 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.3055 on 32 degrees of freedom
  (22 observations deleted due to missingness)
Multiple R-squared:  0.1072,    Adjusted R-squared:  0.07933 
F-statistic: 3.844 on 1 and 32 DF,  p-value: 0.05869
plot(lh2)

For HUD2012042

wd3 <- list()
for (i in 1:length(H12042_wink_elec_1)){
  if (is.null(H12042_wink_elec_1[[i]])){
    wd3[[i]] <- NULL
    }
  else{
    wd3[[i]] <- H12042_wink_data[[i]]
  }
}
plot(unlist(wd3), unlist(H12042_wink_elec_1), ylim = c(-3,3), xlab = 'DO Concentrations, ml/l', ylab = 'Difference (Winkler - electrode)')
abline(h = 0, col = 'blue')
lh3 <- lm(unlist(H12042_wink_elec_1) ~ unlist(wd3))
abline(lh3, col = 'red')
title(main = 'HUD2012042')

summary(lh3)

Call:
lm(formula = unlist(H12042_wink_elec_1) ~ unlist(wd3))

Residuals:
     Min       1Q   Median       3Q      Max 
-1.29387 -0.08654  0.05764  0.21150  0.52617 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) -2.17202    0.33825  -6.421 5.83e-09 ***
unlist(wd3)  0.40032    0.06292   6.362 7.63e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.3385 on 92 degrees of freedom
  (72 observations deleted due to missingness)
Multiple R-squared:  0.3055,    Adjusted R-squared:  0.298 
F-statistic: 40.48 on 1 and 92 DF,  p-value: 7.628e-09
plot(lh3)

These plots show some interesting trends of accuracy over DO concentrations.

The trend seems to be a slightly increased under estimation by the electrode at higher DO concentrations. Keeping in mind the small range of DO concentrations that are visible in this data this may be a significant trend.

Groundfish surveys were also analyzed in order to bulk up the data set. A total of 55 new data points were discovered where winkler and lectrode measurments were performed for the same sample ID.

#read in groundfish data
data <- readxl::read_xlsx('C:/Users/ChisholmE/Desktop/BIOCHEM/GROUNDFISH OXYGEN DATA.xlsx' )
#isolate by cruise
NED2013022 <- (5:935)
NED2014018 <- (937:1669)
NED2015017 <- (1674:2161) #CAUTIOUS OF DUPLICATE VALUE, x__4 IS ELECTRODE VALUE AVERAGED BETWEEN REPS
#read data column containing difference (Winkler- electrode)
DIFF <- as.numeric(as.character(data$X__6[-1]))
diff <- na.omit(DIFF)
#plot differences over both cruises due to minimal data points
plot(diff, type = 'h', xlab = 'Sample ID', ylab = 'Difference between methods (Winkler - Electrode)', main = 'Difference in O2 measurments from Groundfish surveys')
m <- mean(diff)
abline(h = m, col = 'red')

Plotting these difference over dissolved oxygen concetrations revealed trends consistent with AZMP data

#isolate concentrations from Winkler measurments for relevant sample IDs
conc <- list()
for ( i in 1:2648){
  if(is.na(data$X__6[-1][i]) ){
    conc[i] <- NA
  }else{
    conc[i] <- as.numeric(data$X__5[-1][i]) 
  }
}
  
c <- na.omit(unlist(conc))
#conc <- data$X__5[!is.na(DIFF) ]
#plot differences over concentration
plot(conc, DIFF, xlab = 'Dissolved Oxygen Concentration (ml/L)', ylab = 'Difference between measurements (Winkler - electrode)')
abline(h = 0, col = 'blue')
#linear regression
cm <- lm(unlist(DIFF) ~unlist(conc))
abline(cm, col = 'red')
#plot potential correction factors 
#of 2, 4, 6 %
twoperc <- list()
for (i in 1:length(conc)){
  twoperc[i] <- as.numeric(conc[i]) *0.02
}
pm <- lm(unlist(twoperc)~unlist(conc))
abline(pm, col = 'green')
fourperc <- list()
for (i in 1:length(conc)){
  fourperc[i] <- as.numeric(conc[i]) *0.04
}
fm <- lm(unlist(fourperc)~unlist(conc))
abline(fm, col = 'orange')
sixperc <- list()
for (i in 1:length(conc)){
  sixperc[i] <- as.numeric(conc[i]) *0.06
}
sm <- lm(unlist(sixperc)~unlist(conc))
abline(sm, col = 'purple')
legend('bottomright', legend = c('2%', '4%', '6%'), col = c('green', 'orange', 'purple'), lty = 2, cex = 0.5 )

Potential correction factors of 2, 4,6 % of dissolved oxygen concentrations were also plotted. Through visual inspection it appears the 4% correction factors agrees best with the data although there is still signifcant unexplained variability particularly at higher DO concentration values which may indicate a non linear trend.

Regression was performed over groundfish surveys and AZMP cruies to find a common trend in the total data set.

#plot original data
plot(wt, et, xlim = c(0, 10), ylim = c(0,10), col = 'red', xlab = 'Winkler (ml/L)', ylab = 'Electrode (ml/L)')
#regression of original data
ttlm <- lm(wt ~as.numeric(et))
abline(ttlm, col = 'red', lty = 2)
#plot 1:1 line reference
abline(coef = c(0,1), col = 'blue')
#apply correction factor following ttlm regression equation
eet <- list()
for (i in 1:length(et)){
  eet[i] <- as.numeric(et[i])*1.1424 - 0.6171
}
#plot corrected data for comparision
par(new = TRUE)
plot(wt, eet, xlim = c(0,10), ylim = c(0,10), xlab = '', ylab = '', axes = FALSE, col = 'blue')
mtext(side = 3, 'Original data (red), Corrected data (blue)')

#regress corrected data to ensure high correlation and 1.00 slope
ttcor <- lm(wt ~ unlist(eet))

Differences were analyzed before and after correction

#calculate original and corrected differences
wt_et <- list()
for (i in 1:length(wt)){
  wt_et[i] <- as.numeric(wt)[i] - as.numeric(et)[i]
}
wt_eet <- list()
for (i in 1:length(wt)){
  wt_eet[i] <- as.numeric(wt[i]) - as.numeric(eet[i])
}
#plot differences
plot(unlist(wt_et), type = 'h', ylim = c(-1,1), col = 'red', xlab = 'Sample ID', ylab = 'Difference (Winkler - electrode)')
par(new = TRUE)
plot(unlist(wt_eet), type = 'h', ylim = c(-1,1), axes = FALSE, xlab = '', ylab = '')
etm <- mean(unlist(wt_et), na.rm = TRUE)
eetm <- mean(unlist(wt_eet), na.rm = TRUE)
abline(h = etm, col = 'red', lty = 2)
abline(h = eetm, col = 'black', lty = 2)
mtext(side = 3, 'Original data differences (red), corrected data differences (black)')

Then differences over dissolved oxygen concentration were analyzed to ensure that there was random scatter around zero rather than increasing trend observed in original data

#plot new corrected data over DO concentration
plot(eet, wt_eet, xlim = c(2,9), ylim = c(-1,1), ylab = 'Differences (Winkler - Electrode**corrected)', xlab = "Dissolved oxygen concentration (ml/L)")

Gordana suggested plotting differences between WInkler and Electrode measurements over lab - in situ temparture differences to see if the temperature difference had a significant effect on the dissolved oxygen readings.

x <- readxl::read_xlsx('C:/Users/ChisholmE/Desktop/BIOCHEM/hud2011004_tdiff_exercise.xlsx')
w_e_diff <- x$`W - E difference`
t_diff <- x$`lab - in situ temp (mean)`
plot(t_diff, w_e_diff, xlab = 'Temperature difference (lab - in situ) degC', ylab = 'Oxygen difference (Winkler - Electrode) ml/l')
abline(h = 0, lty = 2)

This plot shows no significant trends in dissolved oxygen concentration over temperature differences.The points are mostly scattered around zero with some outliers at lower temperature differences, as well as some low values between 3 and 5 deg C temperature differences.

Plotting differences in oxygen over lab temperature was inconclusive. Samples are from HUD2011004

x <- readxl::read_xlsx('C:/Users/ChisholmE/Desktop/BIOCHEM/hud2011004_tdiff_exercise.xlsx' )
w_e_diff <- x$`W - E difference`
plot(x$X__11, w_e_diff, xlab = 'Temperature (degC)', ylab = 'Oxygen Difference (Winkler - electrode) ml/l')
NAs introduced by coercion

LS0tDQp0aXRsZTogIkRpc3NvbHZlZCBPeHlnZW4gUmVjb3ZlcnkgUHJvamVjdCAiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KQVpNUCBjcnVpc2UgZGF0YSB3YXMgc2VhcmNoZWQgbWFudWFsbHkgdG8gZmluZCBjcnVpc2VzIHdoZXJlIHRoZXJlIHdlcmUgYm90aCBXaW5rbGVyIGFuZCBwcm9iZSBtZWFzdXJlbWVudHMuIFdpdGhpbiBHb3JkYW5hJ3MgZmlsZXMgdGhlcmUgd2VyZSB0aHJlZSBjcnVpc2VzIHdoaWNoIHF1YWxpZmllZCwgSFVEMjAxMTAwNCwgSFVEMjAxMTA0MyBhbmQgSFVEMjAxMjA0Mg0KDQpUaGVzZSBmaWxlcyB3ZXJlIHJlYWQgaW4gYXMgY3N2J3MgdXNpbmcgdGhlIEJDRCBmbGFnZ2VkIGZpbGVzIHRvIHByb3ZpZGUgdGhlIG1vc3QgYWNjdXJhdGUgYW5kIHVwIHRvIGRhdGUgUUMuIE9uY2UgdGhlIGZpbGVzIHdlcmUgY29waWVkIGZyb20gdGhlIHNoYXJlZCBkcml2ZSB0byB0aGUgbG9jYWwgZHJpdmUgdGhleSB3ZXJlIHJlYWQgaW4gYXMgc2VlbiBiZWxvdyAoY2F1dGlvbiB0aGlzIHNlY3Rpb24gd2lsbCBub3QgcnVuIHVubGVzcyBmaWxlIHBhdGhzIGFyZSBleGFjdCkNCg0KYGBge3J9DQojcmVhZCBpbiBCQ0QgZmlsZXMNCkgxMTAwNF9iY2QgPC0gcmVhZC5jc3YoJ0hVRDIwMTEwMDQvSFVEMjAxMTAwNF9CQ0RfZmxhZ2dlZC5jc3YnKQ0KSDExMDQzX2JjZCA8LSByZWFkLmNzdignSFVEMjAxMTA0My9IVUQyMDExMDQzX0JDRF9mbGFnZ2VkLmNzdicpDQpIMTIwNDJfYmNkIDwtIHJlYWQuY3N2KCdIVUQyMDEyMDQyL0hVRDIwMTIwNDJfQkNEX2ZsYWdnZWQuY3N2JykNCg0KYGBgDQoNCk9uY2UgZmlsZXMgd2VyZSByZWFkIGludG8gUiwgV2lua2xlciBhbmQgcHJvYmUgZGF0YSB3YXMgZm91bmQgYW5kIHB1bGxlZC4gDQoNCmBgYHtyfQ0KI2ZpbmQgcm93cyB3aXRoIHdpbmtsZXIgZGF0YQ0KSDExMDA0X3dpbmsgPC0gZ3JlcChIMTEwMDRfYmNkJERBVEFfVFlQRV9NRVRIT0QsIHBhdHRlcm4gPSAnTzJfV2lua2xlcl9BdXRvJykNCkgxMTA0M193aW5rIDwtIGdyZXAoSDExMDQzX2JjZCREQVRBX1RZUEVfTUVUSE9ELCBwYXR0ZXJuID0gJ08yX1dpbmtsZXJfQXV0bycpDQpIMTIwNDJfd2luayA8LSBncmVwKEgxMjA0Ml9iY2QkREFUQV9UWVBFX01FVEhPRCwgcGF0dGVybiA9ICdPMl9XaW5rbGVyX0F1dG8nKQ0KDQojZmluZCByb3dzIHdpdGggcHJvYmUgZGF0YQ0KSDExMDA0X2VsZWMgPC0gZ3JlcChIMTEwMDRfYmNkJERBVEFfVFlQRV9NRVRIT0QsIHBhdHRlcm4gPSAnTzJfRWxlY3Ryb2RlX21sbCcpDQpIMTEwNDNfZWxlYyA8LSBncmVwKEgxMTA0M19iY2QkREFUQV9UWVBFX01FVEhPRCwgcGF0dGVybiA9ICdPMl9FbGVjdHJvZGVfbWxsJykNCkgxMjA0Ml9lbGVjIDwtIGdyZXAoSDEyMDQyX2JjZCREQVRBX1RZUEVfTUVUSE9ELCBwYXR0ZXJuID0gJ08yX0VsZWN0cm9kZV9tbGwnKQ0KDQojcHVsbCB3aW5rbGVyIGRhdGENCkgxMTAwNF93aW5rX2RhdGEgPC0gSDExMDA0X2JjZCRESVNfREVUQUlMX0RBVEFfVkFMVUVbSDExMDA0X3dpbmtdDQpIMTEwMDRfd2lua19kcHRoIDwtIEgxMTAwNF9iY2QkRElTX0hFQURFUl9TVEFSVF9ERVBUSFtIMTEwMDRfd2lua10NCg0KSDExMDQzX3dpbmtfZGF0YSA8LSBIMTEwNDNfYmNkJERJU19ERVRBSUxfREFUQV9WQUxVRVtIMTEwNDNfd2lua10NCkgxMTA0M193aW5rX2RwdGggPC0gSDExMDQzX2JjZCRESVNfSEVBREVSX1NUQVJUX0RFUFRIW0gxMTA0M193aW5rXQ0KDQpIMTIwNDJfd2lua19kYXRhIDwtIEgxMjA0Ml9iY2QkRElTX0RFVEFJTF9EQVRBX1ZBTFVFW0gxMjA0Ml93aW5rXQ0KSDEyMDQyX3dpbmtfZHB0aCA8LSBIMTIwNDJfYmNkJERJU19IRUFERVJfU1RBUlRfREVQVEhbSDEyMDQyX3dpbmtdDQoNCiNwdWxsIHByb2JlIGRhdGENCkgxMTAwNF9lbGVjX2RhdGEgPC0gSDExMDA0X2JjZCRESVNfREVUQUlMX0RBVEFfVkFMVUVbSDExMDA0X2VsZWNdDQpIMTEwMDRfZWxlY19kcHRoIDwtIEgxMTAwNF9iY2QkRElTX0hFQURFUl9TVEFSVF9ERVBUSFtIMTEwMDRfZWxlY10NCg0KSDExMDQzX2VsZWNfZGF0YSA8LSBIMTEwNDNfYmNkJERJU19ERVRBSUxfREFUQV9WQUxVRVtIMTEwNDNfZWxlY10NCkgxMTA0M19lbGVjX2RwdGggPC0gSDExMDQzX2JjZCRESVNfSEVBREVSX1NUQVJUX0RFUFRIW0gxMTA0M19lbGVjXQ0KDQpIMTIwNDJfZWxlY19kYXRhIDwtIEgxMjA0Ml9iY2QkRElTX0RFVEFJTF9EQVRBX1ZBTFVFW0gxMjA0Ml9lbGVjXQ0KSDEyMDQyX2VsZWNfZHB0aCA8LSBIMTIwNDJfYmNkJERJU19IRUFERVJfU1RBUlRfREVQVEhbSDEyMDQyX2VsZWNdDQpgYGANCg0KT25jZSBwcm9iZSBhbmQgV2lua2xlciBkYXRhIGhhcyBiZWVuIGlzb2xhdGVkLCBhbiBpbml0aWFsIHBsb3QgZ2l2ZXMgYSBnZW5lcmFsIGlkZWEgb2YgdGhlIGRhdGEgc2V0IGZvciBlYWNoIGNydWlzZS4NCg0KYGBge3J9DQpwbG90KEgxMTAwNF93aW5rX2RhdGEsIEgxMTAwNF93aW5rX2RwdGgsIHlsaW0gPSBjKDUwMDAsIDApLCB4bGltID0gYygzLCA5KSwgY29sID0gJ2JsdWUnLCB5bGFiID0gJ0RlcHRoIChtKScsIHhsYWIgPSAnTzIgY29uY2VudHJhdGlvbiAobWwvbCknLG1haW4gPSAnT3h5Z2VuIGRhdGEgZnJvbSBIVUQyMDExMDA0Jywgc3ViID0gJ1dpbmtsZXIgdnMgUHJvYmUoT3Jpb24gODQyKScpDQpwYXIobmV3ID0gVFJVRSkNCnBsb3QoSDExMDA0X2VsZWNfZGF0YSwgSDExMDA0X2VsZWNfZHB0aCwgeWxpbSA9IGMoNTAwMCwgMCksIHhsaW0gPSBjKDMsIDkpLCBheGVzID0gRkFMU0UsIGNvbCA9ICdibGFjaycsIHhsYWIgPSAnJywgeWxhYiA9ICcnKQ0KbGVnZW5kKCdib3R0b21sZWZ0JywgbGVnZW5kID0gYygnV0lOS0xFUicsICdQUk9CRScpLCBjb2wgPSBjKCdibHVlJywgJ2JsYWNrJyksIGx0eSA9IDEsIGNleCA9IDAuNikNCg0KDQpwbG90KEgxMTA0M193aW5rX2RhdGEsIEgxMTA0M193aW5rX2RwdGgsIHlsaW0gPSBjKDUwMDAsIDApLCB4bGltID0gYygyLCA5KSwgY29sID0gJ2JsdWUnLCB5bGFiID0gJ0RlcHRoIChtKScsIHhsYWIgPSAnTzIgY29uY2VudHJhdGlvbiAobWwvbCknLG1haW4gPSAnT3h5Z2VuIGRhdGEgZnJvbSBIVUQyMDExMDQzJywgc3ViID0gJ1dpbmtsZXIgdnMgUHJvYmUoT3Jpb24gODQyKScpDQpwYXIobmV3ID0gVFJVRSkNCnBsb3QoSDExMDQzX2VsZWNfZGF0YSwgSDExMDQzX2VsZWNfZHB0aCwgeWxpbSA9IGMoNTAwMCwgMCksIHhsaW0gPSBjKDIsIDkpLCBheGVzID0gRkFMU0UsIGNvbCA9ICdibGFjaycsIHhsYWIgPSAnJywgeWxhYiA9ICcnKQ0KbGVnZW5kKCdib3R0b21sZWZ0JywgbGVnZW5kID0gYygnV0lOS0xFUicsICdQUk9CRScpLCBjb2wgPSBjKCdibHVlJywgJ2JsYWNrJyksIGx0eSA9IDEsIGNleCA9IDAuNikNCg0KDQpwbG90KEgxMjA0Ml93aW5rX2RhdGEsIEgxMjA0Ml93aW5rX2RwdGgsIHlsaW0gPSBjKDUwMDAsIDApLCB4bGltID0gYygxLCA5KSwgY29sID0gJ2JsdWUnLCB5bGFiID0gJ0RlcHRoIChtKScsIHhsYWIgPSAnTzIgY29uY2VudHJhdGlvbiAobWwvbCknLG1haW4gPSAnT3h5Z2VuIGRhdGEgZnJvbSBIVUQyMDEyMDQyJywgc3ViID0gJ1dpbmtsZXIgdnMgUHJvYmUoT3Jpb24gODQyKScpDQpwYXIobmV3ID0gVFJVRSkNCnBsb3QoSDEyMDQyX2VsZWNfZGF0YSwgSDEyMDQyX2VsZWNfZHB0aCwgeWxpbSA9IGMoNTAwMCwgMCksIHhsaW0gPSBjKDEsIDkpLCBheGVzID0gRkFMU0UsIGNvbCA9ICdibGFjaycsIHhsYWIgPSAnJywgeWxhYiA9ICcnKQ0KbGVnZW5kKCdib3R0b21sZWZ0JywgbGVnZW5kID0gYygnV0lOS0xFUicsICdQUk9CRScpLCBjb2wgPSBjKCdibHVlJywgJ2JsYWNrJyksIGx0eSA9IDEsIGNleCA9IDAuNikNCg0KDQoNCmBgYA0KDQpUaGUgbmV4dCBzdGVwIGluIGFuYWx5c2lzIHdhcyB0byBtYXRjaCB0aGUgc2FtcGxlIElEJ3MgZm9yIGVhY2ggbWVhc3VyZW1lbnQgbWV0aG9kIHNvIHRoYXQgRE8gY291bGQgYmUgZGlyZWN0bHkgY29tcGFyZWQuIFRoZXJlIHdhcyBhIG1pbm9yIGJ1ZyB3aXRoIHRoZSBsZW5ndGggb2YgdGhlIHZlY3RvcnMgYnV0IHRoaXMgd2FzIGVhc2lseSBzb2x2ZWQuDQoNCmBgYHtyfQ0KI2lzb2xhdGUgaW5kaXZpZHVhbCBib3R0bGVzDQojaHVkMjAxMTAwNA0KI3B1bGwgc2FtcGxlIGlkcw0KSDExMDA0X3dpbmtfaWQgPC0gSDExMDA0X2JjZCRESVNfREVUQUlMX0NPTExFQ1RPUl9TQU1QX0lEW0gxMTAwNF93aW5rXSAjbGVuZ3RoID0gMTM3DQpIMTEwMDRfZWxlY19pZCA8LSBIMTEwMDRfYmNkJERJU19ERVRBSUxfQ09MTEVDVE9SX1NBTVBfSURbSDExMDA0X2VsZWNdICNsZW5ndGggPSAxNzYNCiNUaGVzZSBhcmUgZGlmZmVyZW50IGxlbmd0aHMgbWVhbmluZyBub3QgYWxsIHNhbXBsZSBpZHMgY2FuIG1hdGNoDQoNCmxlbmd0aChIMTEwMDRfd2lua19pZCkgPC0gMTc2ICNmaXggbGVuZ3RoIGlzc3VlDQojY29tYmluZSBsaXN0cw0KSDExMDA0X2lkIDwtIGNiaW5kKEgxMTAwNF93aW5rX2lkLCBIMTEwMDRfZWxlY19pZCkNCiNjb21wYXJlIGxpc3RzDQpIMTEwMDRfaWRfbWF0Y2ggPC0gSDExMDA0X3dpbmtfaWQgPT0gSDExMDA0X2VsZWNfaWQgI3VzZWxlc3MNCiNtb3N0IHNhbXBsZSBpZCdzIG1hdGNoIGJ1dCB0aGV5IGFyZSBvcmRlcmVkIGRpZmZlcmVudGx5LCBtdXN0IGNvbXBhcmUgMSBieSAxDQoNCiNjcmVhdGUgbWF0Y2hpbmcgbGlzdCB3aW5rOmVsZWMNCm1hdGNoIDwtIGxpc3QoKQ0KZm9yIChpIGluIDE6MTc2KXsNCiAgaCA8LSBIMTEwMDRfd2lua19pZFtpXSA9PSBIMTEwMDRfZWxlY19pZA0KICBtIDwtIGdyZXAoaCwgcGF0dGVybiA9IFRSVUUpDQogICNtIDwtIGdyZXAocGF0dGVybiA9IEgxMTAwNF93aW5rX2lkW2ldLCBIMTEwMDRfZWxlY19pZCkNCiAgaWYobGVuZ3RoKG0gPjApKXsNCiAgbWF0Y2hbaV0gPC0gbQ0KICB9ZWxzZXsNCiAgICBtYXRjaFtpXSA8LSBOVUxMDQogIH0NCn0NCg0KI25hbWUgbGlzdCB3aW5rOmVsZWMNCiAgICAjd2h5IGlzIGxpc3Qgb25seSAxNzUgaXRlbXMsIHNob3VsZCBiZSAxNzYsIGxhc3QgaXMgTlVMTD8NCm5hbWVzKG1hdGNoKSA8LSBjKDE6MTc1KQ0KDQpIMTEwMDRfd2lua19lbGVjIDwtIGxpc3QoKQ0KZm9yIChpIGluIDE6MTc1KXsNCiAgaWYoIWlzLm51bGwobWF0Y2hbW2ldXSkpew0KSDExMDA0X3dpbmtfZWxlY1tpXSA8LSBIMTEwMDRfd2lua19kYXRhW1tpXV0gLSBIMTEwMDRfZWxlY19kYXRhW1ttYXRjaFtbaV1dXV0NCiAgfWVsc2V7DQogIEgxMTAwNF93aW5rX2VsZWNbaV0gPC0gTlVMTA0KfQ0KfQ0KI2tlZXBzIHN1YnRyYWN0aW5nIG9uZSBmcm9tIGxlbmd0aD8NCmxlbmd0aChIMTEwMDRfd2lua19lbGVjKSA8LSAxNzUNCg0KDQpgYGANCg0KT25jZSBpbmRpdmlkdWFsIHNhbXBsZSBJRCdzIGNvdWxkIGJlIGNvbXBhcmVkIGl0IHdhcyBwb3NzaWJsZSB0byBwbG90IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gbWV0aG9kcy4gDQoNCmBgYHtyfQ0KI3Bsb3QgZGlmZmVyZW5jZXMgKHdpbmstZWxlYykNCg0KcGxvdCh1bmxpc3QobWF0Y2gpLCB1bmxpc3QoSDExMDA0X3dpbmtfZWxlYyksIHR5cGUgPSAnaCcsIHhsYWIgPSAnc2FtcGxlIElEJywgeWxhYiA9ICdXaW5rbGVyIC0gZWxlY3Ryb2RlIHZhbHVlJykNCm10ZXh0KCdEaWZmZXJlbmNlIGJldHdlZW4gV2lua2xlciBhbmQgRWxlY3Ryb2RlIHZhbHVlcyANCiAgICAgIChIVUQyMDExMDA0KScpDQpgYGANCg0KU29tZSBzdW1tYXJ5IHN0YXRpc3RpY3Mgd2VyZSBhbHNvIGNhbGN1bGF0ZWQgYXQgdGhpcyBwb2ludCBhbmQgcHJlc2VudGVkIGluIHRoZSByZXBvcnQuIA0KDQpUaGlzIHByb2Nlc3Mgd2FzIHRoZW4gcmVwZWF0ZWQgZm9yIGVhY2ggY3J1aXNlLg0KDQpIVUQyMDExMDQzDQoNCg0KYGBge3J9DQojaHVkMjAxMTA0Mw0KDQojcHVsbCBzYW1wbGUgaWRzDQpIMTEwNDNfd2lua19pZCA8LSBIMTEwNDNfYmNkJERJU19ERVRBSUxfQ09MTEVDVE9SX1NBTVBfSURbSDExMDQzX3dpbmtdICNsZW5ndGggPSAzMTANCkgxMTA0M19lbGVjX2lkIDwtIEgxMTA0M19iY2QkRElTX0RFVEFJTF9DT0xMRUNUT1JfU0FNUF9JRFtIMTEwNDNfZWxlY10gI2xlbmd0aCA9IDcxDQojVGhlc2UgYXJlIGRpZmZlcmVudCBsZW5ndGhzIG1lYW5pbmcgbm90IGFsbCBzYW1wbGUgaWRzIGNhbiBtYXRjaA0KDQpsZW5ndGgoSDExMDQzX2VsZWNfaWQpIDwtIDMxMCAjZml4IGxlbmd0aCBpc3N1ZQ0KI2NvbWJpbmUgbGlzdHMNCkgxMTA0M19pZCA8LSBjYmluZChIMTEwNDNfd2lua19pZCwgSDExMDQzX2VsZWNfaWQpDQojY29tcGFyZSBsaXN0cw0KSDExMDQzX2lkX21hdGNoIDwtIEgxMTA0M193aW5rX2lkID09IEgxMTA0M19lbGVjX2lkICN1c2VsZXNzDQojbW9zdCBzYW1wbGUgaWQncyBtYXRjaCBidXQgdGhleSBhcmUgb3JkZXJlZCBkaWZmZXJlbnRseSwgbXVzdCBjb21wYXJlIDEgYnkgMQ0KDQojY3JlYXRlIG1hdGNoaW5nIGxpc3Qgd2luazplbGVjDQptYXRjaDIgPC0gbGlzdCgpDQpmb3IgKGkgaW4gMTozMTApew0KICBoIDwtIEgxMTA0M193aW5rX2lkW2ldID09IEgxMTA0M19lbGVjX2lkDQogIG0gPC0gZ3JlcChoLCBwYXR0ZXJuID0gVFJVRSkNCiAgI20gPC0gZ3JlcChwYXR0ZXJuID0gSDExMDA0X3dpbmtfaWRbaV0sIEgxMTAwNF9lbGVjX2lkKQ0KICBpZihsZW5ndGgobSA+MCkpew0KICAgIG1hdGNoMltpXSA8LSBtDQogIH1lbHNlew0KICAgIG1hdGNoMltpXSA8LSBOVUxMDQogIH0NCn0NCg0KI25hbWUgbGlzdCB3aW5rOmVsZWMNCiN3aHkgaXMgbGlzdCBvbmUgc2hvcnQgb2YgZnVsbCBsZW5ndGg/DQpuYW1lcyhtYXRjaDIpIDwtIGMoMTozMDkpDQoNCkgxMTA0M193aW5rX2VsZWMgPC0gbGlzdCgpDQpmb3IgKGkgaW4gMTozMDkpew0KICBpZighaXMubnVsbChtYXRjaDJbW2ldXSkpew0KICAgIEgxMTA0M193aW5rX2VsZWNbaV0gPC0gSDExMDQzX3dpbmtfZGF0YVtbaV1dIC0gSDExMDQzX2VsZWNfZGF0YVtbbWF0Y2gyW1tpXV1dXQ0KICB9ZWxzZXsNCiAgICBIMTEwNDNfd2lua19lbGVjW2ldIDwtIE5VTEwNCiAgfQ0KfQ0KI2tlZXBzIHN1YnRyYWN0aW5nIG9uZSBmcm9tIGxlbmd0aD8NCmxlbmd0aChIMTEwNDNfd2lua19lbGVjKSA8LSAzMTANCg0KDQojcGxvdCBkaWZmZXJlbmNlcyAod2luay1lbGVjKQ0KDQpwbG90KHVubGlzdChtYXRjaDIpLCB1bmxpc3QoSDExMDQzX3dpbmtfZWxlYyksIHR5cGUgPSAnaCcsIHhsYWIgPSAnc2FtcGxlIElEJywgeWxhYiA9ICdXaW5rbGVyIC0gZWxlY3Ryb2RlIHZhbHVlJykNCm10ZXh0KCdEaWZmZXJlbmNlIGJldHdlZW4gV2lua2xlciBhbmQgRWxlY3Ryb2RlIHZhbHVlcyANCiAgICAgIChIVUQyMDExMDQzKScpDQpgYGANCg0KSFVEMjAxMjA0Mg0KDQpgYGB7cn0NCiNIdWQyMDEyMDQyDQojcHVsbCBzYW1wbGUgaWRzDQpIMTIwNDJfd2lua19pZCA8LSBIMTIwNDJfYmNkJERJU19ERVRBSUxfQ09MTEVDVE9SX1NBTVBfSURbSDEyMDQyX3dpbmtdICNsZW5ndGggPSA0ODYNCkgxMjA0Ml9lbGVjX2lkIDwtIEgxMjA0Ml9iY2QkRElTX0RFVEFJTF9DT0xMRUNUT1JfU0FNUF9JRFtIMTIwNDJfZWxlY10gI2xlbmd0aCA9IDIwNw0KI1RoZXNlIGFyZSBkaWZmZXJlbnQgbGVuZ3RocyBtZWFuaW5nIG5vdCBhbGwgc2FtcGxlIGlkcyBjYW4gbWF0Y2gNCg0KbGVuZ3RoKEgxMjA0Ml9lbGVjX2lkKSA8LSA0ODYgI2ZpeCBsZW5ndGggaXNzdWUNCiNjb21iaW5lIGxpc3RzDQpIMTIwNDJfaWQgPC0gY2JpbmQoSDEyMDQyX3dpbmtfaWQsIEgxMjA0Ml9lbGVjX2lkKQ0KI2NvbXBhcmUgbGlzdHMNCkgxMjA0Ml9pZF9tYXRjaCA8LSBIMTIwNDJfd2lua19pZCA9PSBIMTIwNDJfZWxlY19pZCAjdXNlbGVzcw0KI21vc3Qgc2FtcGxlIGlkJ3MgbWF0Y2ggYnV0IHRoZXkgYXJlIG9yZGVyZWQgZGlmZmVyZW50bHksIG11c3QgY29tcGFyZSAxIGJ5IDENCg0KI2NyZWF0ZSBtYXRjaGluZyBsaXN0IHdpbms6ZWxlYw0KbWF0Y2gzIDwtIGxpc3QoKQ0KZm9yIChpIGluIDE6NDg2KXsNCiAgaCA8LSBIMTIwNDJfd2lua19pZFtpXSA9PSBIMTIwNDJfZWxlY19pZA0KICBtIDwtIGdyZXAoaCwgcGF0dGVybiA9IFRSVUUpDQogICNtIDwtIGdyZXAocGF0dGVybiA9IEgxMTAwNF93aW5rX2lkW2ldLCBIMTEwMDRfZWxlY19pZCkNCiAgaWYobGVuZ3RoKG0gPjApKXsNCiAgICBtYXRjaDNbaV0gPC0gbQ0KICB9ZWxzZXsNCiAgICBtYXRjaDNbaV0gPC0gTlVMTA0KICB9DQp9DQoNCiNuYW1lIGxpc3Qgd2luazplbGVjDQojd2h5IGlzIGxpc3Qgb25seSAxNzUgaXRlbXMsIHNob3VsZCBiZSAxNzYsIGxhc3QgaXMgTlVMTD8NCm5hbWVzKG1hdGNoMykgPC0gYygxOjQ4NikNCg0KSDEyMDQyX3dpbmtfZWxlYyA8LSBsaXN0KCkNCmZvciAoaSBpbiAxOjQ4Nil7DQogIGlmKCFpcy5udWxsKG1hdGNoM1tbaV1dKSl7DQogICAgSDEyMDQyX3dpbmtfZWxlY1tpXSA8LSBIMTIwNDJfd2lua19kYXRhW1tpXV0gLSBIMTIwNDJfZWxlY19kYXRhW1ttYXRjaDNbW2ldXV1dDQogIH1lbHNlew0KICAgIEgxMjA0Ml93aW5rX2VsZWNbaV0gPC0gTlVMTA0KICB9DQp9DQoja2VlcHMgc3VidHJhY3Rpbmcgb25lIGZyb20gbGVuZ3RoPw0KbGVuZ3RoKEgxMjA0Ml93aW5rX2VsZWMpIDwtIDQ4Ng0KDQoNCiNwbG90IGRpZmZlcmVuY2VzICh3aW5rLWVsZWMpDQoNCnBsb3QodW5saXN0KG1hdGNoMyksIHVubGlzdChIMTIwNDJfd2lua19lbGVjKSwgdHlwZSA9ICdoJywgeGxhYiA9ICdzYW1wbGUgSUQnLCB5bGFiID0gJ1dpbmtsZXIgLSBlbGVjdHJvZGUgdmFsdWUnKQ0KbXRleHQoJ0RpZmZlcmVuY2UgYmV0d2VlbiBXaW5rbGVyIGFuZCBFbGVjdHJvZGUgdmFsdWVzIA0KICAgICAgKEhVRDIwMTIwNDIpJykNCmBgYA0KDQpGdXJ0aGVyIHN0YXRpc3RpY3Mgd2VyZSBjYWxjdWxhdGVkIGluY2x1ZGluZyBhIHQgdGVzdCBhbmQgY29uZmlkZW5jZSBpbnRlcnZhbHMNCg0KYGBge3J9DQojI2lzIHRoZSBtZWFuIGRpZmZlcmVuY2Ugc2lnbmlmaWNhbnRseSBkaWZmcmVudCBmcm9tIHplcm8/DQogICN0IHRlc3QNCg0KYSA8LSAwLjAxDQoNCkgxMjA0Ml90IDwtIHQudGVzdCh4ID0gdW5saXN0KEgxMjA0Ml93aW5rX2VsZWMpKQ0KDQpIMTEwNDNfdCA8LSB0LnRlc3QoeCA9IHVubGlzdChIMTEwNDNfd2lua19lbGVjKSkNCg0KSDExMDA0X3QgPC0gdC50ZXN0KHggPSB1bmxpc3QoSDExMDA0X3dpbmtfZWxlYykpDQoNCmNpMSA8LSBIMTEwMDRfdCRjb25mLmludA0KY2kyIDwtIEgxMTA0M190JGNvbmYuaW50DQpjaTMgPC0gSDEyMDQyX3QkY29uZi5pbnQNCg0KeCA8LSBjKDE6IDIwMCkNCg0KYSA8LSB1bmxpc3QoSDExMDA0X3dpbmtfZWxlYykNCmIgPC0gdW5saXN0KEgxMTA0M193aW5rX2VsZWMpDQpjIDwtIHVubGlzdChIMTIwNDJfd2lua19lbGVjKQ0KDQpsZW5ndGgoYSkgPC0gMjAwDQpsZW5ndGgoYikgPC0gMjAwDQpsZW5ndGgoYykgPC0gMjAwDQpwbG90KHgsIGEsIGNvbCA9ICdibGFjaycsIHlsaW0gPSBjKC0yLjUsIDIuNSksIHhsYWIgPSAnU2FtcGxlIElEJywgeWxhYiA9ICJEaWZmZXJlbmNlIFdpbmtsZXIgLSBFbGVjdHJvZGUgKG1sL2wpIiApDQptdGV4dCgnRGlmZmVyZW5jZSBiZXR3ZWVuIA0KICAgICAgV2lua2xlciBhbmQgRWxlY3Ryb2RlIE1ldGhvZHMnKQ0KbXRleHQoIkJsYWNrOiBIVUQyMDExMDA0LA0KICBCbHVlOiBIVUQyMDExMDQzLCANCiAgUmVkOiBIVUQyMDEyMDQyIiwgc2lkZSA9IDEsIGNleCA9IDAuOCwgbGluZSA9IC0yKQ0KcGFyKG5ldyA9IFRSVUUpDQpwbG90KHgsIGIsIGNvbCA9ICdibHVlJywgeWxpbSA9IGMoLTIuNSwgMi41KSwgYXhlcyA9IEZBTFNFLCB4bGFiID0gJycsIHlsYWIgPSAnJykNCnBhcihuZXcgPSBUUlVFKQ0KcGxvdCh4LCBjLCBjb2wgPSAncmVkJywgeWxpbSA9IGMoLTIuNSwgMi41KSwgYXhlcyA9IEZBTFNFLCB4bGFiID0gJycsIHlsYWIgPSAnJykNCg0KI2NvbmZpZGVuY2UgaW50ZXJ2YWwgbGluZXMNCmFibGluZShoID0gY2kxW1sxXV0sIGNvbCA9ICdibGFjaycpDQphYmxpbmUoaCA9IGNpMVtbMl1dLCBjb2wgPSAnYmxhY2snKQ0KYWJsaW5lKGggPSBjaTJbWzFdXSwgY29sID0gJ2JsdWUnKQ0KYWJsaW5lKGggPSBjaTJbWzJdXSwgY29sID0gJ2JsdWUnKQ0KYWJsaW5lKGggPSBjaTNbWzFdXSwgY29sID0gJ3JlZCcpDQphYmxpbmUoaCA9IGNpM1tbMl1dLCBjb2wgPSAncmVkJykNCmBgYA0KDQpUaGUgbmV4dCBzdGVwIG9mIGFuYWx5c2lzIHdhcyB0byByZW1vdmUgb3V0bGllcnMgaW4gdGhlIFdpbmtsZXIgZGF0YSB1c2luZyBBbmRyZXcgQ29nc3dlbGwncyBtZXRob2Qgb2YgZWxpbWluYXRpbmcgcG9pbnRzIG91dHNpZGUgMS41KklRUg0KDQpgYGB7cn0NCiNlbGltaW5hdGUgb3V0bGllcnMgKHBhc3QgMS41IElRVCwgYW5kIGZsYWdnZWQgdmFsdWVzKQ0KDQojY2FsY3VsYXRlIGlxdA0KSDExMDA0X2lxcjwtIElRUihIMTEwMDRfd2lua19kYXRhLCBuYS5ybSA9IFRSVUUpDQpIMTEwNDNfaXFyIDwtIElRUihIMTEwNDNfd2lua19kYXRhLCBuYS5ybSA9IFRSVUUpDQpIMTIwNDJfaXFyIDwtIElRUihIMTIwNDJfd2lua19kYXRhLCBuYS5ybSA9IFRSVUUpDQoNCiNjYWxjdWxhdGUgMS41IGlxdA0KSDExMDA0X2lxcl8xLjUgPC0gMS41KihIMTEwMDRfaXFyKQ0KSDExMDQzX2lxcl8xLjUgPC0gMS41KihIMTEwNDNfaXFyKQ0KSDEyMDQyX2lxcl8xLjUgPC0gMS41KihIMTIwNDJfaXFyKQ0KDQojY2FsY3VsYXRlIG1lYW4NCkgxMTAwNF93aW5rX21lYW4gPC0gbWVhbihIMTEwMDRfd2lua19kYXRhKQ0KSDExMDQzX3dpbmtfbWVhbiA8LSBtZWFuKEgxMTA0M193aW5rX2RhdGEpDQpIMTIwNDJfd2lua19tZWFuIDwtIG1lYW4oSDEyMDQyX3dpbmtfZGF0YSkNCmBgYA0KDQpUaGlzIHdhcyB0aGVuIHBsb3R0ZWQgc28gZGF0YSBjb3VsZCBiZSB2aXN1YWxpemVkIGFuZCBlbnN1cmUgY29ycmVjdCByZW1vdmFsIG9mIG91dGxpZXJzDQoNCmBgYHtyfQ0KI2h1ZDIwMTEwMDQNCnBsb3QoIGMoMTpsZW5ndGgoSDExMDA0X3dpbmtfZGF0YSkpLCB1bmxpc3QoSDExMDA0X3dpbmtfZGF0YSksIHhsYWIgPSAnU2FtcGxlIElEJywgeWxhYiA9ICdPeHlnZW4gQ09uY2VudHJhdGlvbiAobWwvTCknKQ0KbXRleHQoJ0Rpc3NvbHZlZCBPeHlnZW4gV2lua2xlciBNZWFzdXJlbWVudHMNCiAgICAgIEhVRDIwMTEwMDQnKQ0KcGFyKG5ldyA9IFRSVUUpDQphYmxpbmUoaCA9IEgxMTAwNF93aW5rX21lYW4sIGNvbCA9ICdibHVlJykNCnVpcXIgPC0gMC41KihIMTEwMDRfaXFyXzEuNSkgKyBIMTEwMDRfd2lua19tZWFuDQpsaXFyIDwtIEgxMTAwNF93aW5rX21lYW4gLSAwLjUqKEgxMTAwNF9pcXJfMS41KSANCmFibGluZShoID0gdWlxciwgY29sID0gJ3JlZCcpDQphYmxpbmUoaCA9IGxpcXIsIGNvbCA9ICdyZWQnKQ0KDQojbnVsbCB2YWx1ZXMgb3V0c2lkZSAxLjUgaXF0DQpIMTEwMDRfd2lua19kYXRhW0gxMTAwNF93aW5rX2RhdGEgPiB1aXFyXSA8LSBOQQ0KSDExMDA0X3dpbmtfZGF0YVtIMTEwMDRfd2lua19kYXRhIDwgbGlxcl0gPC0gTkENCg0KcGxvdChjKDE6bGVuZ3RoKEgxMTAwNF93aW5rX2RhdGEpKSwgdW5saXN0KEgxMTAwNF93aW5rX2RhdGEpLCB5bGltID0gYygzLDkpLCB4bGFiID0gJ1NhbXBsZSBJRCcsIHlsYWIgPSAnRGlzc29sdmVkIE9YeWdlbiAobWwvTCknKQ0KbXRleHQoJ1dpbmtsZXIgT3h5Z2VuIE1lYXN1cmVtZW50cyBhZnRlciBRQw0KICAgICAgSFVEMjAxMTAwNCcpDQptdGV4dCgnUmVkIGxpbmVzIHJlcHJlc2VudCAxLjUgSVFUJywgc2lkZSA9IDEsIGNleCA9IDAuOCkNCmFibGluZShoID0gdWlxciwgY29sID0gJ3JlZCcpDQphYmxpbmUoaCA9IGxpcXIsIGNvbCA9ICdyZWQnKQ0KDQojaHVkMjAxMTA0Mw0KcGxvdCggYygxOmxlbmd0aChIMTEwNDNfd2lua19kYXRhKSksIHVubGlzdChIMTEwNDNfd2lua19kYXRhKSwgeGxhYiA9ICdTYW1wbGUgSUQnLCB5bGFiID0gJ094eWdlbiBDT25jZW50cmF0aW9uIChtbC9MKScpDQptdGV4dCgnRGlzc29sdmVkIE94eWdlbiBXaW5rbGVyIE1lYXN1cmVtZW50cw0KICAgICAgSFVEMjAxMTA0MycpDQpwYXIobmV3ID0gVFJVRSkNCmFibGluZShoID0gSDExMDQzX3dpbmtfbWVhbiwgY29sID0gJ2JsdWUnKQ0KdWlxcjIgPC0gMC41KihIMTEwNDNfaXFyXzEuNSkgKyBIMTEwNDNfd2lua19tZWFuDQpsaXFyMiA8LSBIMTEwNDNfd2lua19tZWFuIC0gMC41KihIMTEwNDNfaXFyXzEuNSkgDQphYmxpbmUoaCA9IHVpcXIyLCBjb2wgPSAncmVkJykNCmFibGluZShoID0gbGlxcjIsIGNvbCA9ICdyZWQnKQ0KDQojbnVsbCB2YWx1ZXMgb3V0c2lkZSAxLjUgaXF0DQpIMTEwNDNfd2lua19kYXRhW0gxMTA0M193aW5rX2RhdGEgPiB1aXFyMl0gPC0gTkENCkgxMTA0M193aW5rX2RhdGFbSDExMDQzX3dpbmtfZGF0YSA8IGxpcXIyXSA8LSBOQQ0KDQpwbG90KGMoMTpsZW5ndGgoSDExMDQzX3dpbmtfZGF0YSkpLCB1bmxpc3QoSDExMDQzX3dpbmtfZGF0YSksIHlsaW0gPSBjKDMsIDcpLCB4bGFiID0gJ1NhbXBsZSBJRCcsIHlsYWIgPSAnRGlzc29sdmVkIE9YeWdlbiAobWwvTCknKQ0KbXRleHQoJ1dpbmtsZXIgT3h5Z2VuIE1lYXN1cmVtZW50cyBhZnRlciBRQw0KICAgICAgSFVEMjAxMTA0MycpDQptdGV4dCgnUmVkIGxpbmVzIHJlcHJlc2VudCAxLjUgSVFUJywgc2lkZSA9IDEsIGNleCA9IDAuOCkNCmFibGluZShoID0gdWlxcjIsIGNvbCA9ICdyZWQnKQ0KYWJsaW5lKGggPSBsaXFyMiwgY29sID0gJ3JlZCcpDQoNCiNodWQyMDEyMDQyDQpwbG90KCBjKDE6bGVuZ3RoKEgxMjA0Ml93aW5rX2RhdGEpKSwgdW5saXN0KEgxMjA0Ml93aW5rX2RhdGEpLCB4bGFiID0gJ1NhbXBsZSBJRCcsIHlsYWIgPSAnT3h5Z2VuIENvbmNlbnRyYXRpb24gKG1sL0wpJykNCm10ZXh0KCdEaXNzb2x2ZWQgT3h5Z2VuIFdpbmtsZXIgTWVhc3VyZW1lbnRzDQogICAgICBIVUQyMDEyMDQyJykNCnBhcihuZXcgPSBUUlVFKQ0KYWJsaW5lKGggPSBIMTIwNDJfd2lua19tZWFuLCBjb2wgPSAnYmx1ZScpDQp1aXFyMyA8LSAwLjUqKEgxMjA0Ml9pcXJfMS41KSArIEgxMjA0Ml93aW5rX21lYW4NCmxpcXIzIDwtIEgxMjA0Ml93aW5rX21lYW4gLSAwLjUqKEgxMjA0Ml9pcXJfMS41KSANCmFibGluZShoID0gdWlxcjMsIGNvbCA9ICdyZWQnKQ0KYWJsaW5lKGggPSBsaXFyMywgY29sID0gJ3JlZCcpDQoNCiNudWxsIHZhbHVlcyBvdXRzaWRlIDEuNSBpcXQNCkgxMjA0Ml93aW5rX2RhdGFbSDEyMDQyX3dpbmtfZGF0YSA+IHVpcXIzXSA8LSBOQQ0KSDEyMDQyX3dpbmtfZGF0YVtIMTIwNDJfd2lua19kYXRhIDwgbGlxcjNdIDwtIE5BDQoNCnBsb3QoYygxOmxlbmd0aChIMTIwNDJfd2lua19kYXRhKSksIHVubGlzdChIMTIwNDJfd2lua19kYXRhKSwgeWxpbSA9IGMoMiw3KSwgeGxhYiA9ICdTYW1wbGUgSUQnLCB5bGFiID0gJ0Rpc3NvbHZlZCBPeHlnZW4gKG1sL0wpJykNCm10ZXh0KCdXaW5rbGVyIE94eWdlbiBNZWFzdXJlbWVudHMgYWZ0ZXIgUUMNCiAgICAgIEhVRDIwMTIwNDInKQ0KbXRleHQoJ1JlZCBsaW5lcyByZXByZXNlbnQgMS41IElRVCcsIHNpZGUgPSAxLCBjZXggPSAwLjgpDQphYmxpbmUoaCA9IHVpcXIzLCBjb2wgPSAncmVkJykNCmFibGluZShoID0gbGlxcjMsIGNvbCA9ICdyZWQnKQ0KDQpgYGANCg0KRGlmZmVyZW5jZXMgd2l0aGluIGluZGl2aWR1YWwgc2FtcGxlIElEJ3Mgd2VyZSB0aGVuIHJlY2FsY3VsYXRlZCwgcmVtb3ZpbmcgYW55IHNhbXBsZXMgd2hlcmUgdGhlIFdpbmtsZXIgdmFsdWUgd2FzIG51bGwgZHVlIHRvIGJlaW5nIGFuIG91dGxpZXIuDQoNCg0KYGBge3J9DQojcGxvdCBkaWZmZXJlbmNlcyBhZnRlciByZW1vdmFsDQojaHVkMjAxMTAwNA0KSDExMDA0X3dpbmtfZWxlY18xIDwtIGxpc3QoKQ0KZm9yKCBpIGluIDE6MTc1KXsNCiAgaWYoIWlzLm51bGwobWF0Y2hbW2ldXSkpew0KICAgIEgxMTAwNF93aW5rX2VsZWNfMVtpXSA8LSBIMTEwMDRfd2lua19kYXRhW1tpXV0gLSBIMTEwMDRfZWxlY19kYXRhW1ttYXRjaFtbaV1dXV0NCiAgfWVsc2V7DQogICAgSDExMDA0X3dpbmtfZWxlY18xW2ldIDwtIE5VTEwNCiAgfQ0KfQ0KcGxvdCh1bmxpc3QobWF0Y2gpLCB1bmxpc3QoSDExMDA0X3dpbmtfZWxlY18xKSwgdHlwZSA9ICdoJywgeGxhYiA9ICdTYW1wbGUgSUQnLCB5bGFiID0gJ1dpbmtsZXIgLSBFbGVjdHJvZGUgKERPICwgbWwvTCknKQ0KbXRleHQoJ0RpZmZlcmVuY2UgYmV0d2VlbiBXaW5rbGVyIGFuZCBFbGVjdHJvZGUgdmFsdWVzIChwb3N0IFFDKQ0KICAgICAgSFVEMjAxMTAwNCcpDQoNCg0KDQojaHVkMjAxMTA0Mw0KSDExMDQzX3dpbmtfZWxlY18xIDwtIGxpc3QoKQ0KZm9yKCBpIGluIDE6MzA5KXsNCiAgaWYoIWlzLm51bGwobWF0Y2gyW1tpXV0pKXsNCiAgICBIMTEwNDNfd2lua19lbGVjXzFbaV0gPC0gSDExMDQzX3dpbmtfZGF0YVtbaV1dIC0gSDExMDQzX2VsZWNfZGF0YVtbbWF0Y2gyW1tpXV1dXQ0KICB9ZWxzZXsNCiAgICBIMTEwNDNfd2lua19lbGVjXzFbaV0gPC0gTlVMTA0KICB9DQp9DQpwbG90KHVubGlzdChtYXRjaDIpLCB1bmxpc3QoSDExMDQzX3dpbmtfZWxlY18xKSwgdHlwZSA9ICdoJywgeGxhYiA9ICdTYW1wbGUgSUQnLCB5bGFiID0gJ1dpbmtsZXIgLSBFbGVjdHJvZGUgKERPICwgbWwvTCknKQ0KbXRleHQoJ0RpZmZlcmVuY2UgYmV0d2VlbiBXaW5rbGVyIGFuZCBFbGVjdHJvZGUgdmFsdWVzIChwb3N0IFFDKQ0KICAgICAgSFVEMjAxMTA0MycpDQoNCiNodWQyMDEyMDQyDQpIMTIwNDJfd2lua19lbGVjXzEgPC0gbGlzdCgpDQpmb3IoIGkgaW4gMTo0ODYpew0KICBpZighaXMubnVsbChtYXRjaDNbW2ldXSkpew0KICAgIEgxMjA0Ml93aW5rX2VsZWNfMVtpXSA8LSBIMTIwNDJfd2lua19kYXRhW1tpXV0gLSBIMTIwNDJfZWxlY19kYXRhW1ttYXRjaDNbW2ldXV1dDQogIH1lbHNlew0KICAgIEgxMjA0Ml93aW5rX2VsZWNfMVtpXSA8LSBOVUxMDQogIH0NCn0NCnBsb3QodW5saXN0KG1hdGNoMyksIHVubGlzdChIMTIwNDJfd2lua19lbGVjXzEpLCB0eXBlID0gJ2gnLCB4bGFiID0gJ1NhbXBsZSBJRCcsIHlsYWIgPSAnV2lua2xlciAtIEVsZWN0cm9kZSAoRE8gLCBtbC9MKScpDQptdGV4dCgnRGlmZmVyZW5jZSBiZXR3ZWVuIFdpbmtsZXIgYW5kIEVsZWN0cm9kZSB2YWx1ZXMgKHBvc3QgUUMpDQogICAgICBIVUQyMDEyMDQyJykNCg0KDQpgYGANCg0KDQpEZXB0aCBwcm9maWxlcyB3ZXJlIHRoZW4gdmlzdWFsaXplZCBhZ2FpbiB0byBzZWUgaWYgdGhlcmUgd2VyZSBhbnkgc2lnbmlmaWNhbnQgdmlzdWFsIHBhdHRlcm5zIG9yIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGRlcHRoIGFuZCBvZmZzZXQgYmV0d2VlbiBXaW5rbGVyIGFuZCBwcm9iZSBkYXRhLg0KDQpgYGB7cn0NCiMjcG9zdCBRQyBkZXB0aCBwcm9maWxlcw0KDQpwbG90KEgxMTAwNF93aW5rX2RhdGEsIEgxMTAwNF93aW5rX2RwdGgsIHlsaW0gPSAoYyg1MDAwLCAwKSksIHhsaW0gPSBjKDQsOSksIHhsYWIgPSAnRE8gbWwvTCcsIHlsYWIgPSAnRGVwdGggKG0pJywgbWFpbiA9ICdIVUQyMDExMDA0JykNCnBhcihuZXcgPSBUUlVFKQ0KcGxvdChIMTEwMDRfZWxlY19kYXRhLCBIMTEwMDRfZWxlY19kcHRoLCB5bGltID0gKGMoNTAwMCwgMCkpLHhsaW0gPSBjKDQsOSksIGF4ZXMgPSBGQUxTRSwgY29sID0gJ2JsdWUnLCB4bGFiID0gJycsIHlsYWIgPSAnJykNCmxlZ2VuZCgnYm90dG9tcmlnaHQnLCAgYygnV2lua2xlcicsICdFbGVjdHJvZGUnKSwgY29sID0gYygnYmxhY2snLCAnYmx1ZScpLCBsdHkgPSAxKQ0KDQpwbG90KEgxMTA0M193aW5rX2RhdGEsIEgxMTA0M193aW5rX2RwdGgsIHlsaW0gPSAoYyg1MDAwLCAwKSksIHhsaW0gPSBjKDQsOSksIHhsYWIgPSAnRE8gbWwvTCcsIHlsYWIgPSAnRGVwdGggKG0pJywgbWFpbiA9ICdIVUQyMDExMDQzJykNCnBhcihuZXcgPSBUUlVFKQ0KcGxvdChIMTEwNDNfZWxlY19kYXRhLCBIMTEwNDNfZWxlY19kcHRoLCB5bGltID0gKGMoNTAwMCwgMCkpLHhsaW0gPSBjKDQsOSksIGF4ZXMgPSBGQUxTRSwgY29sID0gJ2JsdWUnLCB4bGFiID0gJycsIHlsYWIgPSAnJykNCmxlZ2VuZCgnYm90dG9tcmlnaHQnLCAgYygnV2lua2xlcicsICdFbGVjdHJvZGUnKSwgY29sID0gYygnYmxhY2snLCAnYmx1ZScpLCBsdHkgPSAxKQ0KDQpwbG90KEgxMjA0Ml93aW5rX2RhdGEsIEgxMjA0Ml93aW5rX2RwdGgsIHlsaW0gPSAoYyg1MDAwLCAwKSksIHhsaW0gPSBjKDQsOSksIHhsYWIgPSAnRE8gbWwvTCcsIHlsYWIgPSAnRGVwdGggKG0pJywgbWFpbiA9ICdIVUQyMDEyMDQyJykNCnBhcihuZXcgPSBUUlVFKQ0KcGxvdChIMTIwNDJfZWxlY19kYXRhLCBIMTIwNDJfZWxlY19kcHRoLCB5bGltID0gKGMoNTAwMCwgMCkpLHhsaW0gPSBjKDQsOSksIGF4ZXMgPSBGQUxTRSwgY29sID0gJ2JsdWUnLCB4bGFiID0gJycsIHlsYWIgPSAnJykNCmxlZ2VuZCgnYm90dG9tcmlnaHQnLCAgYygnV2lua2xlcicsICdFbGVjdHJvZGUnKSwgY29sID0gYygnYmxhY2snLCAnYmx1ZScpLCBsdHkgPSAxLCBjZXggPSAwLjgpDQoNCmBgYA0KDQpUaGUgbmV4dCBzdGVwIGluIEFuYWx5c2lzIHdhcyB0byBwbG90IFdpbmtsZXIgYW5kIEVsZWN0cm9kZSBkYXRhIGFnYWluc3QgZWFjaCBvdGhlciBmb3IgZWFjaCBjcnVpc2UgdG8gYXR0ZW1wdCBhIGxpbmVhciByZWdyZXNzaW9uLiBJbiBhbiBpZGVhbCBzaXR1dGF0aW9uIHRoZSBkYXRhIHdvdWxkIGhhdmUgcHJlc2VudGVkIHdpdGggYSAxOjEgcmVsYXRpb25zaGlwLCBoaWdoIGNvcnJlbGF0aW9uIGFuZCBtaW5pbWFsIG9mZnNldCAoaW50ZXJjZXB0KS4gDQoNCg0KRm9yIGNydWlzZSBIVUQyMDExMDA0DQoNCmBgYHtyfQ0KSDExMDA0X3dpbmtlbGVjIDwtIG1hdHJpeChOQSwgbnJvdyA9IDE3NSwgbmNvbCA9IDIpDQpmb3IoIGkgaW4gMToxNzUpew0KICBpZighaXMubnVsbChtYXRjaFtbaV1dKSl7DQogICAgSDExMDA0X3dpbmtlbGVjW2ksMV0gPC0gSDExMDA0X3dpbmtfZGF0YVtbaV1dIA0KICAgIEgxMTAwNF93aW5rZWxlY1tpLDJdIDwtIEgxMTAwNF9lbGVjX2RhdGFbW21hdGNoW1tpXV1dXQ0KICAjIH1lbHNlew0KICAjICAgSDExMDA0X3dpbmtlbGVjW2ksXSA8LSBOVUxMDQogICB9DQp9DQoNCnBsb3QoSDExMDA0X3dpbmtlbGVjWywxXSwgSDExMDA0X3dpbmtlbGVjWywyXSwgeGxpbSA9IGMoMCw3KSwgeWxpbSA9IGMoMCw3KSx4bGFiID0gJ1dpbmtsZXIgRGF0YScsIHlsYWIgPSAnRWxlY3Ryb2RlIERhdGEnKQ0KcGFyKG5ldyA9IFRSVUUpDQpsbSA8LSBsbShIMTEwMDRfd2lua2VsZWNbLDFdIH4gSDExMDA0X3dpbmtlbGVjWywyXSkNCmFibGluZShsbSkNCmFibGluZShjb2VmID0gYygwLCAxKSwgY29sID0gJ3JlZCcpDQp0aXRsZShtYWluID0gJ0hVRDIwMTEwMDQnKQ0KdGl0bGUoc3ViID0gJ1JeMiA9IDAuOTg0NCcpDQpgYGANCldoZXJlIGJsYWNrIGxpbmUgcmVwcmVzZW50cyBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gb24gdGhlIGRhdGEgYW5kIHJlZCBsaW5lIHJlcHJlc2VudHMgcGVyZmVjdCAxOjEgcmVsYXRpb25zaGlwIHdpdGggMCBpbnRlcmNlcHQuDQoNClN0YXRpc3RpYyBzdW1tYXJ5DQoNCmBgYHtyfQ0Kc3VtbWFyeShsbSkNCnBsb3QobG0pDQpgYGANCg0KDQpGb3IgY3J1aXNlIEhVRDIwMTEwNDMNCg0KYGBge3J9DQpIMTEwNDNfd2lua2VsZWMgPC0gbWF0cml4KE5BLCBucm93ID0gMzEwLCBuY29sID0gMikNCmZvciggaSBpbiAxOjMwOSl7DQogIGlmKCFpcy5udWxsKG1hdGNoMltbaV1dKSl7DQogICAgSDExMDQzX3dpbmtlbGVjW2ksMV0gPC0gSDExMDQzX3dpbmtfZGF0YVtbaV1dIA0KICAgIEgxMTA0M193aW5rZWxlY1tpLDJdIDwtIEgxMTA0M19lbGVjX2RhdGFbW21hdGNoMltbaV1dXV0NCiAgIyB9ZWxzZXsNCiAgIyAgIEgxMTA0M193aW5rZWxlY1tpLF0gPC0gTlVMTA0KICAgfQ0KfQ0KDQpwbG90KEgxMTA0M193aW5rZWxlY1ssMV0sIEgxMTA0M193aW5rZWxlY1ssMl0sIHhsaW0gPSBjKDAsIDcpLCB5bGltID0gYygwLDcpLCB4bGFiID0gJ1dpbmtsZXIgRGF0YScsIHlsYWIgPSAnRWxlY3Ryb2RlIERhdGEnKQ0KcGFyKG5ldyA9IFRSVUUpDQpsbTIgPC0gbG0oSDExMDQzX3dpbmtlbGVjWywxXSB+IEgxMTA0M193aW5rZWxlY1ssMl0pDQphYmxpbmUobG0yKQ0KYWJsaW5lKGNvZWYgPSBjKDAsIDEpLCBjb2wgPSAncmVkJykNCnRpdGxlKG1haW4gPSAnSFVEMjAxMTA0MycpDQp0aXRsZShzdWIgPSAnUl4yID0gMC4zNjk3JykNCg0KYGBgDQpXaGVyZSBibGFjayBsaW5lIHJlcHJlc2VudHMgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIG9uIHRoZSBkYXRhIGFuZCByZWQgbGluZSByZXByZXNlbnRzIHBlcmZlY3QgMToxIHJlbGF0aW9uc2hpcCB3aXRoIDAgaW50ZXJjZXB0Lg0KDQpTdGF0aXN0aWMgc3VtbWFyeQ0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShsbTIpDQpwbG90KGxtMikNCmBgYA0KDQpGb3IgY3J1aXNlIEhVRDIwMTIwNDINCg0KYGBge3J9DQpsZW5ndGgoSDEyMDQyX2VsZWNfZGF0YSkgPC0gNDg2DQoNCkgxMjA0Ml93aW5rZWxlYyA8LSBtYXRyaXgoTkEsIG5yb3cgPSA0ODYsIG5jb2wgPSAyKQ0KZm9yKCBpIGluIDE6NDg2KXsNCiAgaWYoIWlzLm51bGwobWF0Y2gzW1tpXV0pKXsNCiAgICBIMTIwNDJfd2lua2VsZWNbaSwxXSA8LSBIMTIwNDJfd2lua19kYXRhW1tpXV0gDQogICAgSDEyMDQyX3dpbmtlbGVjW2ksMl0gPC0gSDEyMDQyX2VsZWNfZGF0YVtbbWF0Y2gzW1tpXV1dXQ0KICAgIyB9ZWxzZXsNCiAgICMgICBIMTIwNDJfd2lua2VsZWNbaSxdIDwtIE5VTEwNCiAgIH0NCn0NCg0KcGxvdChIMTIwNDJfd2lua2VsZWNbLDFdLCBIMTIwNDJfd2lua2VsZWNbLDJdLHhsaW0gPSBjKDAsNyksIHlsaW0gPSBjKDAsNyksIHhsYWIgPSAnV2lua2xlciBEYXRhJywgeWxhYiA9ICdFbGVjdHJvZGUgRGF0YScpDQpwYXIobmV3ID0gVFJVRSkNCmxtMyA8LSBsbShIMTIwNDJfd2lua2VsZWNbLDFdIH4gSDEyMDQyX3dpbmtlbGVjWywyXSkNCmFibGluZShsbTMpDQphYmxpbmUoY29lZiA9IGMoMCwgMSksIGNvbCA9ICdyZWQnKQ0KdGl0bGUobWFpbiA9ICdIVUQyMDEyMDQyJykNCnRpdGxlKHN1YiA9ICdSXjIgPSAwLjQ5NjgnKQ0KDQpgYGANCldoZXJlIGJsYWNrIGxpbmUgcmVwcmVzZW50cyBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gb24gdGhlIGRhdGEgYW5kIHJlZCBsaW5lIHJlcHJlc2VudHMgcGVyZmVjdCAxOjEgcmVsYXRpb25zaGlwIHdpdGggMCBpbnRlcmNlcHQuDQoNCg0KU3RhdGlzdGljIHN1bW1hcnkNCg0KYGBge3J9DQpzdW1tYXJ5KGxtMykNCnBsb3QobG0zKQ0KYGBgDQogDQoNCg0KSW4gb3JkZXIgdG8gZGV0ZXJtaW5lIGlmIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBXaW5rbGVyIGFuZCBlbGVjdHJvZGUgZGF0YSB3YXMgcHJlc3N1cmUgZGVwZW5kZW50IHRoZSBkaWZmZXJlbmNlcyBieSBjcnVpc2Ugd2VyZSBwbG90dGVkIG92ZXIgZGVwdGggYWxvbmcgd2l0aCBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gYW5kIHN1bW1hcnkgc3RhdGlzdGljcw0KDQpGb3IgSFVEMjAxMTAwNA0KDQpgYGB7cn0NCmxlbmd0aChIMTEwMDRfd2lua19kcHRoKSA8LSAxMzENCnBsb3QoIEgxMTAwNF93aW5rX2RwdGgsIHVubGlzdChIMTEwMDRfd2lua19lbGVjXzEpLCB5bGltID0gYygtMiwgMiksIHhsYWIgPSAnRGVwdGggKG0pJywgeWxhYiA9ICdEaWZmZXJlbmNlIChXaW5rbGVyIC0gZWxlY3Ryb2RlKScpDQphYmxpbmUoaCA9IDAsIGNvbCA9ICdibHVlJykNCmxsIDwtIGxtKCB1bmxpc3QoSDExMDA0X3dpbmtfZWxlY18xKSB+IEgxMTAwNF93aW5rX2RwdGgpDQphYmxpbmUobGwsIGNvbCA9ICdyZWQnKQ0KdGl0bGUobWFpbiA9ICdIVUQyMDExMDA0Jywgc3ViID0gJ1JeMiA9IDAuMDExMjgnKQ0KDQpgYGANCmBgYHtyfQ0Kc3VtbWFyeShsbCkNCnBsb3QobGwpDQpgYGANCg0KDQpGb3IgSFVEMjAxMTA0Mw0KDQpgYGB7cn0NCmRwMiA8LSBsaXN0KCkNCmZvciAoaSBpbiAxOmxlbmd0aChIMTEwNDNfd2lua19lbGVjXzEpKXsNCiAgaWYoaXMubnVsbChIMTEwNDNfd2lua19lbGVjXzFbW2ldXSkpew0KICAgIGRwMltpXSA8LSBOVUxMDQogIH0gZWxzZXsNCiAgICBkcDJbaV0gPC0gSDExMDQzX3dpbmtfZHB0aFtbaV1dDQogIH0NCn0NCnBsb3QodW5saXN0KGRwMiksIHVubGlzdChIMTEwNDNfd2lua19lbGVjXzEpLCB5bGltID0gYygtMiwgMiksIHhsYWIgPSAnRGVwdGggKG0pJywgeWxhYiA9ICdEaWZmZXJlbmNlIChXaW5rbGVyIC0gRWxlY3Ryb2RlKScpDQphYmxpbmUoaCA9IDAsIGNvbCA9ICdibHVlJykNCmxsMiA8LSBsbSh1bmxpc3QoSDExMDQzX3dpbmtfZWxlY18xKSB+IHVubGlzdChkcDIpKQ0KYWJsaW5lKGxsMiwgY29sID0gJ3JlZCcpDQp0aXRsZShtYWluID0gJ0hVRDIwMTEwNDMnLCBzdWIgPSAnUl4yID0gMC4wMDk0NCcpDQoNCmBgYA0KYGBge3J9DQpzdW1tYXJ5KGxsMikNCnBsb3QobGwyKQ0KYGBgDQoNCg0KRm9yIEhVRDIwMTIwNDINCg0KYGBge3J9DQpkcDMgPC0gbGlzdCgpDQpmb3IgKGkgaW4gMTpsZW5ndGgoSDEyMDQyX3dpbmtfZWxlY18xKSl7DQogIGlmKGlzLm51bGwoSDEyMDQyX3dpbmtfZWxlY18xW1tpXV0pKXsNCiAgICBkcDNbaV0gPC0gTlVMTA0KICB9IGVsc2V7DQogICAgZHAzW2ldIDwtIEgxMjA0Ml93aW5rX2RwdGhbW2ldXQ0KICB9DQp9DQpwbG90KHVubGlzdChkcDMpLCB1bmxpc3QoSDEyMDQyX3dpbmtfZWxlY18xKSwgeWxpbSA9IGMoLTIsIDIpLCB4bGFiID0gJ0RlcHRoIChtKScsIHlsYWIgPSAnRGlmZmVyZW5jZSAoV2lua2xlciAtIEVsZWN0cm9kZSknKQ0KYWJsaW5lKGggPSAwLCBjb2wgPSAnYmx1ZScpDQpsbDMgPC0gbG0odW5saXN0KEgxMjA0Ml93aW5rX2VsZWNfMSkgfiB1bmxpc3QoZHAzKSkNCmFibGluZShsbDMsIGNvbCA9ICdyZWQnKQ0KdGl0bGUobWFpbiA9ICdIVUQyMDEyMDQyJywgc3ViID0gJ1JeMiA9IDAuNzc2NycpDQoNCmBgYA0KYGBge3J9DQpzdW1tYXJ5KGxsMykNCnBsb3QobGwzKQ0KYGBgDQoNClRoaXMgcHJvY2VkdXJlIHdhcyBkb25lIHRvIG1pbWljIENURCBRQyBwcm9jZWR1cmUgYnV0IG1heSBub3QgaGF2ZSBzaWduaWZjYW50IGJlYXJpbmcgb24gdGhlIHN0YXRpc3RpY2FsIHJlc3VsdHMuIEluIHRoZW9yeSB0aGVyZSBzaG91bGQgYmUgbm8gcmVsYXRpb25zaGlwIGJldHdlZW4gcHJlc3N1cmUgYW5kIFdpbmtsZXIgLSBlbGVjdHJvZGUgbWVhc3VyZW1lbnRzIHNpbmNlIGJvdGggbWVhc3VyZW1lbnRzIGFyZSBtYWRlIGEgdCB0aGUgc3VyZmFjZSwgYWx0aG91Z2ggdGhlcmUgbWF5IGJlIHNvbWUgcmVsYXRpb25zaGlwIGJldHdlZW4gYWNjdXJhY3kvIG9mZnNldCBiZXR3ZWVuIG1ldGhvZHMgYW5kIGRpc3NvbHZlZCBveHlnZW4gY29uY2VudHJhdGlvbiB3aGljaCB3aWxsIGJlIHRlc3RlZCBuZXh0LiANCg0KDQpEaWZmZXJlbmNlICh3aW5rbGVyIC0gZWxlY3Ryb2RlIG1lYXN1cmVtZW50IHBlciBzYW1wbGUgSUQpIHdhcyBwbG90dGVkIG92ZXIgRE8gY29uY2VudHJhdGlvbiBmb3IgZWFjaCBjcnVpc2UsIGJsdWUgbGluZSBhcmUgYXQgeSA9IDAgYW5kIHJlZCBsaW5lcyByZXByZXNlbnQgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIG9mIHRoZSBkYXRhLg0KDQpGb3IgSFVEMjAxMTAwNA0KDQpgYGB7cn0NCndkIDwtIGxpc3QoKQ0KZm9yIChpIGluIDE6bGVuZ3RoKEgxMTAwNF93aW5rX2RhdGEpKXsNCiAgaWYgKGlzLm51bGwoSDExMDA0X3dpbmtfZWxlY18xW1tpXV0pKXsNCiAgICB3ZFtbaV1dIDwtIE5VTEwNCiAgfSBlbHNlew0KICAgIHdkW1tpXV0gPC0gSDExMDA0X3dpbmtfZGF0YVtbaV1dDQogIH0NCn0NCg0KbGVuZ3RoKEgxMTAwNF93aW5rX2VsZWNfMSkgPC0gbGVuZ3RoKHdkKQ0KcGxvdCh1bmxpc3Qod2QpLCB1bmxpc3QoSDExMDA0X3dpbmtfZWxlY18xKSwgeWxpbSA9IGMoLTMsMyksIHhsYWIgPSAnRE8gQ29uY2VudHJhdGlvbnMsIG1sL2wnLCB5bGFiID0gJ0RpZmZlcmVuY2UgKFdpbmtsZXIgLSBlbGVjdHJvZGUpJykNCmFibGluZShoID0gMCwgY29sID0gJ2JsdWUnKQ0KbGggPC0gbG0odW5saXN0KEgxMTAwNF93aW5rX2VsZWNfMSkgfiB1bmxpc3Qod2QpKQ0KYWJsaW5lKGxoLCBjb2wgPSAncmVkJykNCnRpdGxlKG1haW4gPSAnSFVEMjAxMTAwNCcpDQoNCmBgYA0KYGBge3J9DQpzdW1tYXJ5KGxoKQ0KcGxvdChsaCkNCmBgYA0KDQpGb3IgSFVEMjAxMTA0Mw0KDQpgYGB7cn0NCndkMiA8LSBsaXN0KCkNCmZvciAoaSBpbiAxOmxlbmd0aChIMTEwNDNfd2lua19lbGVjXzEpKXsNCiAgaWYgKGlzLm51bGwoSDExMDQzX3dpbmtfZWxlY18xW1tpXV0pKXsNCiAgICB3ZDJbW2ldXSA8LSBOVUxMDQogIH0gZWxzZXsNCiAgICB3ZDJbW2ldXSA8LSBIMTEwNDNfd2lua19kYXRhW1tpXV0NCiAgfQ0KfQ0KDQp3ZDIgPC0gdW5saXN0KHdkMikNCmxlbmd0aCh3ZDIpIDwtIDU2DQpwbG90KHdkMiwgdW5saXN0KEgxMTA0M193aW5rX2VsZWNfMSksIHlsaW0gPSBjKC0zLDMpLCB4bGFiID0gJ0RPIENvbmNlbnRyYXRpb25zLCBtbC9sJywgeWxhYiA9ICdEaWZmZXJlbmNlIChXaW5rbGVyIC0gZWxlY3Ryb2RlKScpDQphYmxpbmUoaCA9IDAsIGNvbCA9ICdibHVlJykNCmxoMiA8LSBsbSh1bmxpc3QoSDExMDQzX3dpbmtfZWxlY18xKSB+IHdkMikNCmFibGluZShsaDIsIGNvbCA9ICdyZWQnKQ0KdGl0bGUobWFpbiA9ICdIVUQyMDExMDQzJykNCg0KYGBgDQpgYGB7cn0NCnN1bW1hcnkobGgyKQ0KcGxvdChsaDIpDQpgYGANCg0KRm9yIEhVRDIwMTIwNDINCg0KYGBge3J9DQp3ZDMgPC0gbGlzdCgpDQoNCmZvciAoaSBpbiAxOmxlbmd0aChIMTIwNDJfd2lua19lbGVjXzEpKXsNCiAgaWYgKGlzLm51bGwoSDEyMDQyX3dpbmtfZWxlY18xW1tpXV0pKXsNCiAgICB3ZDNbW2ldXSA8LSBOVUxMDQogICAgfQ0KICBlbHNlew0KICAgIHdkM1tbaV1dIDwtIEgxMjA0Ml93aW5rX2RhdGFbW2ldXQ0KICB9DQp9DQoNCnBsb3QodW5saXN0KHdkMyksIHVubGlzdChIMTIwNDJfd2lua19lbGVjXzEpLCB5bGltID0gYygtMywzKSwgeGxhYiA9ICdETyBDb25jZW50cmF0aW9ucywgbWwvbCcsIHlsYWIgPSAnRGlmZmVyZW5jZSAoV2lua2xlciAtIGVsZWN0cm9kZSknKQ0KYWJsaW5lKGggPSAwLCBjb2wgPSAnYmx1ZScpDQpsaDMgPC0gbG0odW5saXN0KEgxMjA0Ml93aW5rX2VsZWNfMSkgfiB1bmxpc3Qod2QzKSkNCmFibGluZShsaDMsIGNvbCA9ICdyZWQnKQ0KdGl0bGUobWFpbiA9ICdIVUQyMDEyMDQyJykNCmBgYA0KYGBge3J9DQpzdW1tYXJ5KGxoMykNCnBsb3QobGgzKQ0KYGBgDQoNCg0KVGhlc2UgcGxvdHMgc2hvdyBzb21lIGludGVyZXN0aW5nIHRyZW5kcyBvZiBhY2N1cmFjeSBvdmVyIERPIGNvbmNlbnRyYXRpb25zLiANCg0KVGhlIHRyZW5kIHNlZW1zIHRvIGJlIGEgc2xpZ2h0bHkgaW5jcmVhc2VkIHVuZGVyIGVzdGltYXRpb24gYnkgdGhlIGVsZWN0cm9kZSBhdCBoaWdoZXIgRE8gY29uY2VudHJhdGlvbnMuIEtlZXBpbmcgaW4gbWluZCB0aGUgc21hbGwgcmFuZ2Ugb2YgRE8gY29uY2VudHJhdGlvbnMgdGhhdCBhcmUgdmlzaWJsZSBpbiB0aGlzIGRhdGEgdGhpcyBtYXkgYmUgYSBzaWduaWZpY2FudCB0cmVuZC4gDQoNCg0KR3JvdW5kZmlzaCBzdXJ2ZXlzIHdlcmUgYWxzbyBhbmFseXplZCBpbiBvcmRlciB0byBidWxrIHVwIHRoZSBkYXRhIHNldC4gQSB0b3RhbCBvZiA1NSBuZXcgZGF0YSBwb2ludHMgd2VyZSBkaXNjb3ZlcmVkIHdoZXJlIHdpbmtsZXIgYW5kIGxlY3Ryb2RlIG1lYXN1cm1lbnRzIHdlcmUgcGVyZm9ybWVkIGZvciB0aGUgc2FtZSBzYW1wbGUgSUQuIA0KDQpgYGB7cn0NCiNyZWFkIGluIGdyb3VuZGZpc2ggZGF0YQ0KZGF0YSA8LSByZWFkeGw6OnJlYWRfeGxzeCgnQzovVXNlcnMvQ2hpc2hvbG1FL0Rlc2t0b3AvQklPQ0hFTS9HUk9VTkRGSVNIIE9YWUdFTiBEQVRBLnhsc3gnICkNCiNpc29sYXRlIGJ5IGNydWlzZQ0KTkVEMjAxMzAyMiA8LSAoNTo5MzUpDQpORUQyMDE0MDE4IDwtICg5Mzc6MTY2OSkNCk5FRDIwMTUwMTcgPC0gKDE2NzQ6MjE2MSkgI0NBVVRJT1VTIE9GIERVUExJQ0FURSBWQUxVRSwgeF9fNCBJUyBFTEVDVFJPREUgVkFMVUUgQVZFUkFHRUQgQkVUV0VFTiBSRVBTDQoNCg0KI3JlYWQgZGF0YSBjb2x1bW4gY29udGFpbmluZyBkaWZmZXJlbmNlIChXaW5rbGVyLSBlbGVjdHJvZGUpDQpESUZGIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGRhdGEkWF9fNlstMV0pKQ0KZGlmZiA8LSBuYS5vbWl0KERJRkYpDQoNCg0KI3Bsb3QgZGlmZmVyZW5jZXMgb3ZlciBib3RoIGNydWlzZXMgZHVlIHRvIG1pbmltYWwgZGF0YSBwb2ludHMNCnBsb3QoZGlmZiwgdHlwZSA9ICdoJywgeGxhYiA9ICdTYW1wbGUgSUQnLCB5bGFiID0gJ0RpZmZlcmVuY2UgYmV0d2VlbiBtZXRob2RzIChXaW5rbGVyIC0gRWxlY3Ryb2RlKScsIG1haW4gPSAnRGlmZmVyZW5jZSBpbiBPMiBtZWFzdXJtZW50cyBmcm9tIEdyb3VuZGZpc2ggc3VydmV5cycpDQptIDwtIG1lYW4oZGlmZikNCmFibGluZShoID0gbSwgY29sID0gJ3JlZCcpDQpgYGANCg0KUGxvdHRpbmcgdGhlc2UgZGlmZmVyZW5jZSBvdmVyIGRpc3NvbHZlZCBveHlnZW4gY29uY2V0cmF0aW9ucyByZXZlYWxlZCB0cmVuZHMgY29uc2lzdGVudCB3aXRoIEFaTVAgZGF0YQ0KDQpgYGB7cn0NCiNpc29sYXRlIGNvbmNlbnRyYXRpb25zIGZyb20gV2lua2xlciBtZWFzdXJtZW50cyBmb3IgcmVsZXZhbnQgc2FtcGxlIElEcw0KY29uYyA8LSBsaXN0KCkNCmZvciAoIGkgaW4gMToyNjQ4KXsNCiAgaWYoaXMubmEoZGF0YSRYX182Wy0xXVtpXSkgKXsNCiAgICBjb25jW2ldIDwtIE5BDQogIH1lbHNlew0KICAgIGNvbmNbaV0gPC0gYXMubnVtZXJpYyhkYXRhJFhfXzVbLTFdW2ldKSANCiAgfQ0KfQ0KICANCg0KYyA8LSBuYS5vbWl0KHVubGlzdChjb25jKSkNCiNjb25jIDwtIGRhdGEkWF9fNVshaXMubmEoRElGRikgXQ0KDQojcGxvdCBkaWZmZXJlbmNlcyBvdmVyIGNvbmNlbnRyYXRpb24NCnBsb3QoY29uYywgRElGRiwgeGxhYiA9ICdEaXNzb2x2ZWQgT3h5Z2VuIENvbmNlbnRyYXRpb24gKG1sL0wpJywgeWxhYiA9ICdEaWZmZXJlbmNlIGJldHdlZW4gbWVhc3VyZW1lbnRzIChXaW5rbGVyIC0gZWxlY3Ryb2RlKScpDQphYmxpbmUoaCA9IDAsIGNvbCA9ICdibHVlJykNCiNsaW5lYXIgcmVncmVzc2lvbg0KY20gPC0gbG0odW5saXN0KERJRkYpIH51bmxpc3QoY29uYykpDQphYmxpbmUoY20sIGNvbCA9ICdyZWQnKQ0KDQojcGxvdCBwb3RlbnRpYWwgY29ycmVjdGlvbiBmYWN0b3JzIA0KI29mIDIsIDQsIDYgJQ0KdHdvcGVyYyA8LSBsaXN0KCkNCmZvciAoaSBpbiAxOmxlbmd0aChjb25jKSl7DQogIHR3b3BlcmNbaV0gPC0gYXMubnVtZXJpYyhjb25jW2ldKSAqMC4wMg0KfQ0KDQpwbSA8LSBsbSh1bmxpc3QodHdvcGVyYyl+dW5saXN0KGNvbmMpKQ0KYWJsaW5lKHBtLCBjb2wgPSAnZ3JlZW4nKQ0KDQpmb3VycGVyYyA8LSBsaXN0KCkNCmZvciAoaSBpbiAxOmxlbmd0aChjb25jKSl7DQogIGZvdXJwZXJjW2ldIDwtIGFzLm51bWVyaWMoY29uY1tpXSkgKjAuMDQNCn0NCg0KZm0gPC0gbG0odW5saXN0KGZvdXJwZXJjKX51bmxpc3QoY29uYykpDQphYmxpbmUoZm0sIGNvbCA9ICdvcmFuZ2UnKQ0KDQpzaXhwZXJjIDwtIGxpc3QoKQ0KZm9yIChpIGluIDE6bGVuZ3RoKGNvbmMpKXsNCiAgc2l4cGVyY1tpXSA8LSBhcy5udW1lcmljKGNvbmNbaV0pICowLjA2DQp9DQoNCnNtIDwtIGxtKHVubGlzdChzaXhwZXJjKX51bmxpc3QoY29uYykpDQphYmxpbmUoc20sIGNvbCA9ICdwdXJwbGUnKQ0KDQpsZWdlbmQoJ2JvdHRvbXJpZ2h0JywgbGVnZW5kID0gYygnMiUnLCAnNCUnLCAnNiUnKSwgY29sID0gYygnZ3JlZW4nLCAnb3JhbmdlJywgJ3B1cnBsZScpLCBsdHkgPSAyLCBjZXggPSAwLjUgKQ0KYGBgDQoNClBvdGVudGlhbCBjb3JyZWN0aW9uIGZhY3RvcnMgb2YgMiwgNCw2ICUgb2YgZGlzc29sdmVkIG94eWdlbiBjb25jZW50cmF0aW9ucyB3ZXJlIGFsc28gcGxvdHRlZC4gVGhyb3VnaCB2aXN1YWwgaW5zcGVjdGlvbiBpdCBhcHBlYXJzIHRoZSA0JSBjb3JyZWN0aW9uIGZhY3RvcnMgYWdyZWVzIGJlc3Qgd2l0aCB0aGUgZGF0YSBhbHRob3VnaCB0aGVyZSBpcyBzdGlsbCBzaWduaWZjYW50IHVuZXhwbGFpbmVkIHZhcmlhYmlsaXR5IHBhcnRpY3VsYXJseSBhdCBoaWdoZXIgRE8gY29uY2VudHJhdGlvbiB2YWx1ZXMgd2hpY2ggbWF5IGluZGljYXRlIGEgbm9uIGxpbmVhciB0cmVuZC4gDQoNClJlZ3Jlc3Npb24gd2FzIHBlcmZvcm1lZCBvdmVyIGdyb3VuZGZpc2ggc3VydmV5cyBhbmQgQVpNUCBjcnVpZXMgdG8gZmluZCBhIGNvbW1vbiB0cmVuZCBpbiB0aGUgdG90YWwgZGF0YSBzZXQuIA0KDQpgYGB7cn0NCg0KI3Bsb3Qgb3JpZ2luYWwgZGF0YQ0KcGxvdCh3dCwgZXQsIHhsaW0gPSBjKDAsIDEwKSwgeWxpbSA9IGMoMCwxMCksIGNvbCA9ICdyZWQnLCB4bGFiID0gJ1dpbmtsZXIgKG1sL0wpJywgeWxhYiA9ICdFbGVjdHJvZGUgKG1sL0wpJykNCiNyZWdyZXNzaW9uIG9mIG9yaWdpbmFsIGRhdGENCnR0bG0gPC0gbG0od3QgfmFzLm51bWVyaWMoZXQpKQ0KYWJsaW5lKHR0bG0sIGNvbCA9ICdyZWQnLCBsdHkgPSAyKQ0KI3Bsb3QgMToxIGxpbmUgcmVmZXJlbmNlDQphYmxpbmUoY29lZiA9IGMoMCwxKSwgY29sID0gJ2JsdWUnKQ0KDQojYXBwbHkgY29ycmVjdGlvbiBmYWN0b3IgZm9sbG93aW5nIHR0bG0gcmVncmVzc2lvbiBlcXVhdGlvbg0KZWV0IDwtIGxpc3QoKQ0KZm9yIChpIGluIDE6bGVuZ3RoKGV0KSl7DQogIGVldFtpXSA8LSBhcy5udW1lcmljKGV0W2ldKSoxLjE0MjQgLSAwLjYxNzENCn0NCiNwbG90IGNvcnJlY3RlZCBkYXRhIGZvciBjb21wYXJpc2lvbg0KcGFyKG5ldyA9IFRSVUUpDQpwbG90KHd0LCBlZXQsIHhsaW0gPSBjKDAsMTApLCB5bGltID0gYygwLDEwKSwgeGxhYiA9ICcnLCB5bGFiID0gJycsIGF4ZXMgPSBGQUxTRSwgY29sID0gJ2JsdWUnKQ0KbXRleHQoc2lkZSA9IDMsICdPcmlnaW5hbCBkYXRhIChyZWQpLCBDb3JyZWN0ZWQgZGF0YSAoYmx1ZSknKQ0KI3JlZ3Jlc3MgY29ycmVjdGVkIGRhdGEgdG8gZW5zdXJlIGhpZ2ggY29ycmVsYXRpb24gYW5kIDEuMDAgc2xvcGUNCnR0Y29yIDwtIGxtKHd0IH4gdW5saXN0KGVldCkpDQpgYGANCg0KRGlmZmVyZW5jZXMgd2VyZSBhbmFseXplZCBiZWZvcmUgYW5kIGFmdGVyIGNvcnJlY3Rpb24NCg0KDQpgYGB7cn0NCiNjYWxjdWxhdGUgb3JpZ2luYWwgYW5kIGNvcnJlY3RlZCBkaWZmZXJlbmNlcw0Kd3RfZXQgPC0gbGlzdCgpDQpmb3IgKGkgaW4gMTpsZW5ndGgod3QpKXsNCiAgd3RfZXRbaV0gPC0gYXMubnVtZXJpYyh3dClbaV0gLSBhcy5udW1lcmljKGV0KVtpXQ0KfQ0Kd3RfZWV0IDwtIGxpc3QoKQ0KZm9yIChpIGluIDE6bGVuZ3RoKHd0KSl7DQogIHd0X2VldFtpXSA8LSBhcy5udW1lcmljKHd0W2ldKSAtIGFzLm51bWVyaWMoZWV0W2ldKQ0KfQ0KDQojcGxvdCBkaWZmZXJlbmNlcw0KcGxvdCh1bmxpc3Qod3RfZXQpLCB0eXBlID0gJ2gnLCB5bGltID0gYygtMSwxKSwgY29sID0gJ3JlZCcsIHhsYWIgPSAnU2FtcGxlIElEJywgeWxhYiA9ICdEaWZmZXJlbmNlIChXaW5rbGVyIC0gZWxlY3Ryb2RlKScpDQpwYXIobmV3ID0gVFJVRSkNCnBsb3QodW5saXN0KHd0X2VldCksIHR5cGUgPSAnaCcsIHlsaW0gPSBjKC0xLDEpLCBheGVzID0gRkFMU0UsIHhsYWIgPSAnJywgeWxhYiA9ICcnKQ0KDQpldG0gPC0gbWVhbih1bmxpc3Qod3RfZXQpLCBuYS5ybSA9IFRSVUUpDQplZXRtIDwtIG1lYW4odW5saXN0KHd0X2VldCksIG5hLnJtID0gVFJVRSkNCg0KYWJsaW5lKGggPSBldG0sIGNvbCA9ICdyZWQnLCBsdHkgPSAyKQ0KYWJsaW5lKGggPSBlZXRtLCBjb2wgPSAnYmxhY2snLCBsdHkgPSAyKQ0KbXRleHQoc2lkZSA9IDMsICdPcmlnaW5hbCBkYXRhIGRpZmZlcmVuY2VzIChyZWQpLCBjb3JyZWN0ZWQgZGF0YSBkaWZmZXJlbmNlcyAoYmxhY2spJykNCmBgYA0KDQpUaGVuIGRpZmZlcmVuY2VzIG92ZXIgZGlzc29sdmVkIG94eWdlbiBjb25jZW50cmF0aW9uIHdlcmUgYW5hbHl6ZWQgdG8gZW5zdXJlIHRoYXQgdGhlcmUgd2FzIHJhbmRvbSBzY2F0dGVyIGFyb3VuZCB6ZXJvIHJhdGhlciB0aGFuIGluY3JlYXNpbmcgdHJlbmQgb2JzZXJ2ZWQgaW4gb3JpZ2luYWwgZGF0YQ0KDQpgYGB7cn0NCiNwbG90IG5ldyBjb3JyZWN0ZWQgZGF0YSBvdmVyIERPIGNvbmNlbnRyYXRpb24NCnBsb3QoZWV0LCB3dF9lZXQsIHhsaW0gPSBjKDIsOSksIHlsaW0gPSBjKC0xLDEpLCB5bGFiID0gJ0RpZmZlcmVuY2VzIChXaW5rbGVyIC0gRWxlY3Ryb2RlKipjb3JyZWN0ZWQpJywgeGxhYiA9ICJEaXNzb2x2ZWQgb3h5Z2VuIGNvbmNlbnRyYXRpb24gKG1sL0wpIikNCmBgYA0KDQpHb3JkYW5hIHN1Z2dlc3RlZCBwbG90dGluZyBkaWZmZXJlbmNlcyBiZXR3ZWVuIFdJbmtsZXIgYW5kIEVsZWN0cm9kZSBtZWFzdXJlbWVudHMgb3ZlciBsYWIgLSBpbiBzaXR1IHRlbXBhcnR1cmUgZGlmZmVyZW5jZXMgdG8gc2VlIGlmIHRoZSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlIGhhZCBhIHNpZ25pZmljYW50IGVmZmVjdCBvbiB0aGUgZGlzc29sdmVkIG94eWdlbiByZWFkaW5ncy4gDQoNCmBgYHtyfQ0KeCA8LSByZWFkeGw6OnJlYWRfeGxzeCgnQzovVXNlcnMvQ2hpc2hvbG1FL0Rlc2t0b3AvQklPQ0hFTS9odWQyMDExMDA0X3RkaWZmX2V4ZXJjaXNlLnhsc3gnKQ0KDQp3X2VfZGlmZiA8LSB4JGBXIC0gRSBkaWZmZXJlbmNlYA0KdF9kaWZmIDwtIHgkYGxhYiAtIGluIHNpdHUgdGVtcCAobWVhbilgDQoNCnBsb3QodF9kaWZmLCB3X2VfZGlmZiwgeGxhYiA9ICdUZW1wZXJhdHVyZSBkaWZmZXJlbmNlIChsYWIgLSBpbiBzaXR1KSBkZWdDJywgeWxhYiA9ICdPeHlnZW4gZGlmZmVyZW5jZSAoV2lua2xlciAtIEVsZWN0cm9kZSkgbWwvbCcpDQphYmxpbmUoaCA9IDAsIGx0eSA9IDIpDQoNCmBgYA0KDQpUaGlzIHBsb3Qgc2hvd3Mgbm8gc2lnbmlmaWNhbnQgdHJlbmRzIGluIGRpc3NvbHZlZCBveHlnZW4gY29uY2VudHJhdGlvbiBvdmVyIHRlbXBlcmF0dXJlIGRpZmZlcmVuY2VzLlRoZSBwb2ludHMgYXJlIG1vc3RseSBzY2F0dGVyZWQgYXJvdW5kIHplcm8gd2l0aCBzb21lIG91dGxpZXJzIGF0IGxvd2VyIHRlbXBlcmF0dXJlIGRpZmZlcmVuY2VzLCBhcyB3ZWxsIGFzIHNvbWUgbG93IHZhbHVlcyBiZXR3ZWVuIDMgYW5kIDUgZGVnIEMgdGVtcGVyYXR1cmUgZGlmZmVyZW5jZXMuIA0KDQoNCg0KDQpQbG90dGluZyBkaWZmZXJlbmNlcyBpbiBveHlnZW4gb3ZlciBsYWIgdGVtcGVyYXR1cmUgd2FzIGluY29uY2x1c2l2ZS4gDQpTYW1wbGVzIGFyZSBmcm9tIEhVRDIwMTEwMDQNCg0KDQpgYGB7cn0NCnggPC0gcmVhZHhsOjpyZWFkX3hsc3goJ0M6L1VzZXJzL0NoaXNob2xtRS9EZXNrdG9wL0JJT0NIRU0vaHVkMjAxMTAwNF90ZGlmZl9leGVyY2lzZS54bHN4JyApDQoNCndfZV9kaWZmIDwtIHgkYFcgLSBFIGRpZmZlcmVuY2VgDQoNCnBsb3QoeCRYX18xMSwgd19lX2RpZmYsIHhsYWIgPSAnVGVtcGVyYXR1cmUgKGRlZ0MpJywgeWxhYiA9ICdPeHlnZW4gRGlmZmVyZW5jZSAoV2lua2xlciAtIGVsZWN0cm9kZSkgbWwvbCcpDQpgYGANCg0K