Go back to the Contents page.


Press Show to reveal the code chunks.


# Create a clipboard button on the rendered HTML page
source(here::here("clipboard.R")); clipboard
# Set seed for reproducibility
set.seed(1982) 
# Set global options for all code chunks
knitr::opts_chunk$set(
  # Disable messages printed by R code chunks
  message = FALSE,    
  # Disable warnings printed by R code chunks
  warning = FALSE,    
  # Show R code within code chunks in output
  echo = TRUE,        
  # Include both R code and its results in output
  include = TRUE,     
  # Evaluate R code chunks
  eval = FALSE,       
  # Enable caching of R code chunks for faster rendering
  cache = FALSE,      
  # Align figures in the center of the output
  fig.align = "center",
  # Enable retina display for high-resolution figures
  retina = 2,
  # Show errors in the output instead of stopping rendering
  error = TRUE,
  # Do not collapse code and output into a single block
  collapse = FALSE
)
# Start the figure counter
fig_count <- 0
# Define the captioner function
captioner <- function(caption) {
  fig_count <<- fig_count + 1
  paste0("Figure ", fig_count, ": ", caption)
}
library(MetricGraph)
library(ggplot2)
library(reshape2)
library(dplyr)
library(viridis)
library(plotly)
library(patchwork)
library(slackr)
source("keys.R")
slackr_setup(token = token) # token comes from keys.R
## [1] "Successfully connected to Slack"
library(reticulate)
py_config()
## python:         /home/rierasl/miniconda3/envs/phdenv/bin/python
## libpython:      /home/rierasl/miniconda3/envs/phdenv/lib/libpython3.11.so
## pythonhome:     /home/rierasl/miniconda3/envs/phdenv:/home/rierasl/miniconda3/envs/phdenv
## version:        3.11.14 (main, Oct 21 2025, 18:31:21) [GCC 11.2.0]
## numpy:          /home/rierasl/miniconda3/envs/phdenv/lib/python3.11/site-packages/numpy
## numpy_version:  2.4.2
## 
## NOTE: Python version was forced by RETICULATE_PYTHON
capture.output(
  knitr::purl(here::here("functionality1.Rmd"), output = here::here("functionality1.R")),
  file = here::here("old/purl_log.txt")
)
source(here::here("functionality1.R"))

Press the Show button below to reveal the code.


1 Part 1

1.1 Interval graph

Below we plot the interval graph \(\Gamma_I = (\mathcal{V}, \mathcal{E})\) with \(\mathcal{V} = \{v_1, v_2\}\) and \(\mathcal{E} = \{e_1\}\), where \(e_1\) is the edge connecting \(v_1\) and \(v_2\).

e1_ini_x <- 0; e1_ini_y <- 0; e1_ini_z <- 0
e1_fin_x <- 1; e1_fin_y <- 0; e1_fin_z <- 0

# Midpoint
xm1 <- (e1_fin_x + e1_ini_x)/2
ym1 <- (e1_fin_y + e1_ini_y)/2
zm1 <- (e1_fin_z + e1_ini_z)/2

# Direction vector
dx1 <- e1_fin_x - e1_ini_x
dy1 <- e1_fin_y - e1_ini_y
dz1 <- e1_fin_z - e1_ini_z


e2_ini_x <- 0; e2_ini_y <- 1; e2_ini_z <- 0
e2_fin_x <- 0; e2_fin_y <- 0; e2_fin_z <- 0

# Midpoint
xm2 <- (e2_fin_x + e2_ini_x)/2
ym2 <- (e2_fin_y + e2_ini_y)/2
zm2 <- (e2_fin_z + e2_ini_z)/2

# Direction vector
dx2 <- e2_fin_x - e2_ini_x
dy2 <- e2_fin_y - e2_ini_y
dz2 <- e2_fin_z - e2_ini_z

# for the circle
r <- 1/pi
cx <- 1 + r
cy <- 0

# parameter value where the cone will be placed
t0 <- 0

# position on the curve
x0 <- cx + r*cos(t0)
y0 <- cy + r*sin(t0)
z0 <- 0

# tangent vector (derivative)
dx <- -r*sin(t0)
dy <-  r*cos(t0)
dz <- 0

sizeref <- 0.1
n <- 3#333
graph <- gets.graph.interval(n = n)

notes_int <- list(annotations = list(
             list(
               x = 0, y = 0, z = 0,
               text = TeX("v_1"),
               textangle = 0, ax = 0, ay = 35,
               font = list(color = "black", size = gfsize),
               arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
             list(
               x = 0, y = 1, z = 0,
               text = TeX("v_2"),
               textangle = 0, ax = 0, ay = 35,
               font = list(color = "black", size = gfsize),
               arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
             list(
               x = 0, y = 0.5, z = 0,
               text = TeX("e_1"),
               textangle = 0, ax = 0, ay = 35,
               font = list(color = "black", size = gfsize),
               arrowcolor = "rgba(0,0,0,0)")))

layout_int <- list(xaxis = list(title = list(text = "x", font = list(color = colaxnn)),  tickfont = list(color = colaxnn)),
              yaxis = list(title = list(text = "y", font = list(color = colaxnn)),  tickfont = list(color = colaxnn)),
              zaxis = list(title = list(text = "z", font = list(color = colaxnn)),  tickfont = list(color = colaxnn)),
  camera = list(eye = list(x = 2.3, 
                                       y = 2.3, 
                                       z = 2.3),
                            center = list(x = 0, 
                                          y = 0, 
                                          z = 0)))

p11 <- graph$plot_function(rep(0,nrow(graph$mesh$V)), 
                           vertex_size = gsw,
                           type = "plotly", 
                           line_width = gsw, 
                           edge_width = gsw, 
                           line_color = "black")|>
  config(mathjax = 'cdn') |>
    add_trace(
  type = "cone",
  x = ym1,
  y = xm1,
  z = zm1,
  u = dy1,
  v = dx1,
  w = dz1,
  sizemode = "absolute",
  sizeref = sizeref,
  showscale = FALSE,
  showlegend = FALSE,
  colorscale = list(c(0, 1), c("green", "green")),
  cmin = 0,
  cmax = 1
) |>
  layout(font = list(family = "Palatino"),
         scene =  c(notes_int, layout_int),
         margin = list(l = 0, r = 0, b = 0, t = 0),
         showlegend = FALSE,
         font = list(family = "Palatino"))



p2int <- graph$plot_function(rep(0,nrow(graph$mesh$V)), 
                           vertex_size = gsw,
                           type = "plotly", 
                           line_width = gsw, 
                           edge_width = gsw, 
                           line_color = "black")|>
  config(mathjax = 'cdn') |>
    add_trace(
  type = "cone",
  x = xm2,
  y = ym2,
  z = zm2,
  u = dx2,
  v = dy2,
  w = dz2,
  sizemode = "absolute",
  sizeref = sizeref,
  showscale = FALSE,
  showlegend = FALSE,
  colorscale = list(c(0, 1), c("green", "green")),
  cmin = 0,
  cmax = 1
) |>
  layout(font = list(family = "Palatino"),
         scene =  c(notes_int, layout_int),
         margin = list(l = 0, r = 0, b = 0, t = 0),
         showlegend = FALSE,
         font = list(family = "Palatino"))


save(p11, file = here::here("data_files/interval_graph.Rdata"))
save(p2int, file = here::here("data_files/interval_graph_flip_edge.Rdata"))

1.2 Circle graph

Below we plot the circle graph \(\Gamma_C = (\mathcal{V}, \mathcal{E})\) with \(\mathcal{V} = \{v_2\}\) and \(\mathcal{E} = \{e_2\}\), where \(e_2\) is the edge connecting \(v_2\) to itself.

n <- 6#666
graph <- gets.graph.circle(n = n)

notes_cir <- list(annotations = list(
             list(
               x = 0, y = 1, z = 0,
               text = TeX("v_2"),
               textangle = 0, ax = 0, ay = 35,
               font = list(color = "black", size = gfsize),
               arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
             list(
               x = 0, y = 1 + 2/pi, z = 0,
               text = TeX("e_2"),
               textangle = 0, ax = 0, ay = 35,
               font = list(color = "black", size = gfsize),
               arrowcolor = "rgba(0,0,0,0)")))
  
  
p22 <- graph$plot_function(rep(0,nrow(graph$mesh$V)), 
                           vertex_size = gsw,
                           type = "plotly", 
                           line_width = gsw, 
                           edge_width = gsw, 
                           line_color = "black") %>% 
  config(mathjax = 'cdn') %>% 
  add_trace(
    type = "cone",
    x = y0,
    y = x0,
    z = z0,
    u = dy,
    v = dx,
    w = dz,
    sizemode = "absolute",
    sizeref = sizeref,
    showscale = FALSE,
    showlegend = FALSE,
    colorscale = list(c(0,1), c("green","green")),
    cmin = 0,
    cmax = 1
  ) |>
  layout(font = list(family = "Palatino"),
         scene =  c(notes_cir, layout_int),
         margin = list(l = 0, r = 0, b = 0, t = 0),
         showlegend = FALSE,
         font = list(family = "Palatino"))
save(p22, file = here::here("data_files/circle_graph.Rdata"))

1.3 Tadpole graph

Below we plot the tadpole graph \(\Gamma_T = (\mathcal{V}, \mathcal{E})\) with \(\mathcal{V} = \{v_1, v_2\}\) and \(\mathcal{E} = \{e_1, e_2\}\), where \(e_1\) is the edge connecting \(v_1\) and \(v_2\), and \(e_2\) is the edge connecting \(v_2\) to itself.

graph <- gets.graph.tadpole(h = 1/4)

notes_tad_1 <- list(annotations = list(
             list(
               x = 0, y = 0, z = 0,
               text = TeX("v_1"),
               textangle = 0, ax = 0, ay = 35,
               font = list(color = "black", size = gfsize),
               arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
             list(
               x = 0, y = 1, z = 0,
               text = TeX("v_2"),
               textangle = 0, ax = 0, ay = 35,
               font = list(color = "black", size = gfsize),
               arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
             list(
               x = 0, y = 0.5, z = 0,
               text = TeX("e_1"),
               textangle = 0, ax = 0, ay = 35,
               font = list(color = "black", size = gfsize),
               arrowcolor = "rgba(0,0,0,0)"),
             list(
               x = 0, y = 1+2/pi, z = 0,
               text = TeX("e_2"),
               textangle = 0, ax = 0, ay = 35,
               font = list(color = "black", size = gfsize),
               arrowcolor = "rgba(0,0,0,0)")))

p33 <- graph$plot_function(rep(0,nrow(graph$mesh$V)), 
                           vertex_size = gsw,
                           type = "plotly", 
                           line_width = gsw, 
                           edge_width = gsw, 
                           line_color = "black") |>
  config(mathjax = 'cdn') |>
      add_trace(
  type = "cone",
  x = ym1,
  y = xm1,
  z = zm1,
  u = dy1,
  v = dx1,
  w = dz1,
  sizemode = "absolute",
  sizeref = sizeref,
  showscale = FALSE,
  showlegend = FALSE,
  colorscale = list(c(0, 1), c("green", "green")),
  cmin = 0,
  cmax = 1
) |>
  add_trace(
    type = "cone",
    x = y0,
    y = x0,
    z = z0,
    u = dy,
    v = dx,
    w = dz,
    sizemode = "absolute",
    sizeref = sizeref,
    showscale = FALSE,
    showlegend = FALSE,
    colorscale = list(c(0,1), c("green","green")),
    cmin = 0,
    cmax = 1
  ) |>
  layout(font = list(family = "Palatino"),
         scene =  c(notes_tad_1, layout_int),
         margin = list(l = 0, r = 0, b = 0, t = 0),
         showlegend = FALSE,
         font = list(family = "Palatino"))
save(p33, file = here::here("data_files/tadpole_graph.Rdata"))

2 Part 2

2.1 Functions on a graph and geodesic distance illustration

Below we plot the function \(f = \gamma\big|_\Gamma\) where \(\gamma(x,y) = e^{-x^2-y^2}\), together with a path on the graph that illustrates the geodesic distance between points \(s_1\) and \(s_2\).

graph_to_get_loc <- gets.graph.tadpole(h = 1/40)
loc <- graph_to_get_loc$get_mesh_locations()

A <- as.matrix(graph$fem_basis(loc))
A <- apply(A, 2, function(x) plotting.order(x, graph_to_get_loc))
A <- rbind(A, rep(NA, ncol(A))) # Add a row of NAs for the plotting

x_g <- graph_to_get_loc$mesh$V[, 1]
y_g <- graph_to_get_loc$mesh$V[, 2]
f_g <- exp(-x_g^2 - y_g^2)


x <- c(plotting.order(x_g, graph_to_get_loc), NA)
y <- c(plotting.order(y_g, graph_to_get_loc), NA)
f <- c(plotting.order(f_g, graph_to_get_loc), NA)


x_range <- range(x, na.rm = TRUE)*1.001
y_range <- range(y, na.rm = TRUE)*1.001
z_range <- c(0,1)
notes1 <- list(annotations = list(
                   list(
                     x = 0, y = 0, z = 0,
                     text = TeX("v_1"),
                     textangle = 0, ax = 0, ay = 35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = 1, y = 0, z = 0,
                     text = TeX("v_2"),
                     textangle = 0, ax = 0, ay = 35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = 0.5, y = 0, z = 0,
                     text = TeX("e_1"),
                     textangle = 0, ax = 0, ay = 35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "rgba(0,0,0,0)"),
                   list(
                     x = 1+2/pi, y = 0, z = 0,
                     text = TeX("e_2"),
                     textangle = 0, ax = 0, ay = 35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "rgba(0,0,0,0)"),
                   list(
                     x = 0.25, y = 0, z = 0,
                     text = TeX("s_1"),
                     textangle = 0, ax = 0, ay = 35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = 1+1/pi, y = 1/pi, z = 0,
                     text = TeX("s_2"),
                     textangle = 0, ax = 0, ay = 35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = 0.25, y = 0, z = 1,
                     text = TeX("f=\\gamma\\big|_\\Gamma"),
                     textangle = 0, ax = -40, ay = 0,
                     font = list(color = "rgb(0,0,200)", size = gfsize),
                     arrowcolor = "rgba(0,0,0,0)")))
    
# to plot the path 
theta <- seq(from = pi/2, to = pi, length.out = 100)
SSTHETA <- seq(from = -pi, to = pi/2, length.out = 300)
SS1 <- data.frame(x = c(0, 0.25), 
                  y = c(0,0), 
                  z = c(0,0))
SS2 <- data.frame(x = 1+1/pi+cos(SSTHETA)/pi, 
                  y = sin(SSTHETA)/pi, 
                  z = rep(0, length(SSTHETA)))
df1 <- data.frame(x = c(0.25,1), 
                  y = c(0,0), 
                  z = c(0,0))
df2 <- data.frame(x = 1+1/pi+cos(theta)/pi, 
                  y = sin(theta)/pi, 
                  z = rep(0, length(theta)))

p1 <- plot_ly() |> 
  config(mathjax = 'cdn') |>
  add_trace(x = 0, y = 0, z = 0, mode = "markers", type = "scatter3d", 
            marker = list(size = gsw, color = "black", symbol = 104),
            showlegend = FALSE) |>
  add_trace(x = 1, y = 0, z = 0, mode = "markers", type = "scatter3d", 
            marker = list(size = gsw, color = "black", symbol = 104),
            showlegend = FALSE) |>
  add_trace(x = 0.25, y = 0, z = 0, mode = "markers", type = "scatter3d", 
            marker = list(size = gsw, color = "red", symbol = 104),
            showlegend = FALSE) |> 
  add_trace(x = 1+1/pi, y = 1/pi, z = 0, mode = "markers", type = "scatter3d", 
            marker = list(size = gsw, color = "red", symbol = 104),
            showlegend = FALSE) |> 
  add_trace(data = SS1, x = ~x, y = ~y, z = ~z, mode = "lines", type = "scatter3d",
            line = list(width = gsw, color = "black", symbol = 104),
            showlegend = FALSE) |>
  add_trace(data = SS2, x = ~x, y = ~y, z = ~z, mode = "lines", type = "scatter3d",
            line = list(width = gsw, color = "black", symbol = 104),
            showlegend = FALSE) |>
  add_trace(data = df1, x = ~x, y = ~y, z = ~z, mode = "lines", type = "scatter3d",
            line = list(width = gsw, color = "red", symbol = 104),
            showlegend = FALSE) |>
  add_trace(data = df2, x = ~x, y = ~y, z = ~z, mode = "lines", type = "scatter3d",
            line = list(width = gsw, color = "red", symbol = 104),
            showlegend = FALSE) |>
  add_trace(x = x, 
            y = y, 
            z = f, 
            type = "scatter3d",
            mode = "lines",  
            line = list(color = "rgb(0,0,200)", width = gsw),
            showlegend = FALSE) |>
  add_trace(x = rep(x, each = 3), 
            y = rep(y, each = 3), 
            z = unlist(lapply(f, function(zj) c(0, zj, NA))),
            type = "scatter3d", 
            mode = "lines",
            line = list(color = "lightgray", width = 0.5),
            showlegend = FALSE) |>
  layout(font = list(family = "Palatino"),
         scene = c(tadpole.layout(x_range, y_range, z_range),notes1),
         margin = list(l = 0, r = 0, b = 0, t = 0),
         showlegend = FALSE,
         font = list(family = "Palatino"))
save(p1, file = here::here("data_files/tadpole_graph_function.Rdata"))

2.2 Mesh

Below we plot the mesh of the tadpole graph.

df3 <- data.frame(x = graph$mesh$V[, 1], 
                  y = graph$mesh$V[, 2], 
                  z = rep(0, length(graph$mesh$V[, 1])))
df4 <- df3[6:nrow(df3), ]


notes2 <- list(annotations = list(
                   list(
                     x = 0, y = 0, z = 0,
                     text = TeX("v_1"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = 1, y = 0, z = 0,
                     text = TeX("v_2"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = df4[1,1], y = df4[1,2], z = 0,
                     text = TeX("x_1^{e_2}"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = df4[2,1], y = df4[2,2], z = 0,
                     text = TeX("x_2^{e_2}"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = df4[3,1], y = df4[3,2], z = 0,
                     text = TeX("x_3^{e_2}"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = df4[4,1], y = df4[4,2], z = 0,
                     text = TeX("x_4^{e_2}"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = df4[5,1], y = df4[5,2], z = 0,
                     text = TeX("x_5^{e_2}"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = df4[6,1], y = df4[6,2], z = 0,
                     text = TeX("x_6^{e_2}"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = df4[7,1], y = df4[7,2], z = 0,
                     text = TeX("x_7^{e_2}"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = 0.25, y = 0, z = 0,
                     text = TeX("x_1^{e_1}"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = 0.5, y = 0, z = 0,
                     text = TeX("x_2^{e_1}"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = 0.75, y = 0, z = 0,
                     text = TeX("x_3^{e_1}"),
                     textangle = 0, ax = 0, ay = -35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1)))

p2 <- plot_ly() |> 
  config(mathjax = 'cdn') |>
  add_trace(x = x, 
            y = y, 
            z = x*0, 
            type = "scatter3d",
            mode = "lines",  
            line = list(color = "black", width = gsw),
            showlegend = FALSE) |>
  add_trace(data = df3, x = ~x, y = ~y, z = ~z, mode = "markers", type = "scatter3d", 
            marker = list(size = gsw, color = "gray", symbol = 104)) |>
  add_trace(x = 0, y = 0, z = 0, mode = "markers", type = "scatter3d", 
            marker = list(size = gsw, color = "black", symbol = 104),
            showlegend = FALSE) |>
  add_trace(x = 1, y = 0, z = 0, mode = "markers", type = "scatter3d", 
            marker = list(size = gsw, color = "black", symbol = 104),
            showlegend = FALSE) |>
  layout(font = list(family = "Palatino"),
         scene = c(tadpole.layout(x_range, y_range, z_range), notes2),
         margin = list(l = 0, r = 0, b = 0, t = 0),
         showlegend = FALSE,
         font = list(family = "Palatino"))
save(p2, file = here::here("data_files/tadpole_graph_mesh.Rdata"))

2.3 Basis functions on a metric graph

Let each edge \(e\in\mathcal{E}\) be subdivided into \(n_{e}\geq 2\) regular segments of length \(h_{e}\), and be delimited by the nodes \(0 = x_0^{e},x_1^{e},\dots,x_{n_{e}-1}^{e}, x_{n_{e}}^{e} = \ell_{e}\). For each \(j = 1,\dots,n_{e}-1\), we consider the following standard hat basis functions \[\begin{equation*} \varphi_j^{e}(x)=\begin{cases} 1-\dfrac{|x_j^{e}-x|}{h_{e}},&\text{ if }x_{j-1}^{e}\leq x\leq x_{j+1}^{e},\\ 0,&\text{ otherwise}. \end{cases} \end{equation*}\] For each \(e\in\mathcal{E}\), the set of hat functions \(\left\{\varphi_1^{e},\dots,\varphi_{n_{e}-1}^{e}\right\}\) is a basis for the space \[\begin{equation*} V_{h_{e}} = \left\{w\in H_0^1(e)\;\Big|\;\forall j = 0,1,\dots,n_{e}-1:w|_{[x_j^{e}, x_{j+1}^{e}]}\in\mathbb{P}^1\right\}, \end{equation*}\] where \(\mathbb{P}^1\) is the space of linear functions on \([0,\ell_{e}]\). For each vertex \(v\in\mathcal{V}\), we define \[\begin{equation*} \mathcal{N}_v = \left\{\bigcup_{e\in\left\{e\in\mathcal{E}_v: v = x_0^e\right\}}[v,x_1^e]\right\}\bigcup\left\{\bigcup_{e\in\left\{e\in\mathcal{E}_v: v = x^e_{n_e}\right\}}[x^e_{n_e-1},v]\right\}, \end{equation*}\] which is a star-shaped set with center at \(v\) and rays made of the segments contiguous to \(v\). On \(\mathcal{N}_v\), we define the hat functions as \[\begin{equation*} \phi_v(x)=\begin{cases} 1-\dfrac{|x_v^{e}-x|}{h_{e}},&\text{ if }x\in\mathcal{N}_v\cap e \text{ and }e\in\mathcal{E}_v,\\ 0,&\text{ otherwise}, \end{cases} \end{equation*}\] where \(x_v^e\) is either \(x_0^e\) or \(x_{n_e}^e\) depending on the edge direction and its parameterization. See (Arioli and Benzi 2018) for more. Figure 3 below provides an illustration of the system of basis functions \(\{\varphi_j^e, \phi_v\}\) together with the set \(\mathcal{N}_v\).

notes3 <- list(annotations = list(
                   list(
                     x = 0, y = 0, z = 1,
                     text = TeX("\\phi_{v_1}"),
                     textangle = 0, ax = 0, ay = -15,
                     font = list(color = "red", size = gfsize),
                     arrowcolor = "rgba(0,0,0,0)"),
                   list(
                     x = 0, y = 0, z = 0,
                     text = TeX("\\mathcal{N}_{v_1}"),
                     textangle = 0, ax = 25, ay = 5,
                     font = list(color = "green", size = gfsize),
                     arrowcolor = "rgba(0,0,0,0)"),
                   list(
                     x = 1, y = 0, z = 1,
                     text = TeX("\\phi_{v_2}"),
                     textangle = 0, ax = 0, ay = -15,
                     font = list(color = "red", size = gfsize),
                     arrowcolor = "rgba(0,0,0,0)"),
                   list(
                     x = 0, y = 0, z = 0,
                     text = TeX("v_1"),
                     textangle = 0, ax = 0, ay = 35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = 1, y = 0, z = 0,
                     text = TeX("v_2"),
                     textangle = 0, ax = 0, ay = 35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = 1, y = 0, z = 0,
                     text = TeX("\\mathcal{N}_{v_2}"),
                     textangle = 0, ax = 40, ay = -10,
                     font = list(color = "green", size = gfsize),
                     arrowcolor = "rgba(0,0,0,0)"),
                   list(
                     x = df4[5,1], y = df4[5,2], z = 0,
                     text = TeX("x_5^{e_2}"),
                     textangle = 0, ax = 0, ay = 35,
                     font = list(color = "black", size = gfsize),
                     arrowcolor = "gray", arrowsize = 1, arrowwidth = 0.5, arrowhead = 1),
                   list(
                     x = df4[5,1], y = df4[5,2], z = 1,
                     text = TeX("\\varphi_5^{e_2}"),
                     textangle = 0, ax = 0, ay = -15,
                     font = list(color = "rgb(0,0,200)", size = gfsize),
                     arrowcolor = "rgba(0,0,0,0)")))

p3 <- plot_ly(
  #width = 1500, height = 2000
         ) |> 
  config(mathjax = 'cdn') |>
  add_trace(x = rep(x, times = graph$nV), 
            y = rep(y, times = graph$nV), 
            z = as.vector(A[, 1:graph$nV]), 
            type = "scatter3d", 
            mode = "lines",
            line = list(color = "red", width = gsw), 
            showlegend = FALSE) |>
  add_trace(x = rep(x, times = ncol(A) - graph$nV), 
            y = rep(y, times = ncol(A) - graph$nV), 
            z = as.vector(A[, (graph$nV+1):ncol(A)]), 
            type = "scatter3d",
            mode = "lines", 
            line = list(color = "darkgray", width = gsw), 
            showlegend = FALSE) |>
  add_trace(x = rep(x, each = 3), 
            y = rep(y, each = 3), 
            z = unlist(lapply(apply(A, 1, max, na.rm = TRUE), function(zj) c(0, zj, NA))),
            type = "scatter3d", 
            mode = "lines",
            line = list(color = "lightgray", width = 0.5),
            showlegend = FALSE) |>
  add_trace(x = x, 
            y = y, 
            z = as.vector(A[, 10]), 
            type = "scatter3d",
            mode = "lines",  
            line = list(color = "rgb(0,0,200)", width = gsw),
            showlegend = FALSE) |>
  add_trace(x = x, 
            y = y, 
            z = x*0, 
            type = "scatter3d",
            mode = "lines",  
            line = list(color = "black", width = gsw),
            showlegend = FALSE) |>
  add_trace(x = rep(x, times = graph$nV), 
            y = rep(y, times = graph$nV), 
            z = c(replace(rep(NA, nrow(A)), 1:11, 0), 
                  replace(rep(NA, nrow(A)), c(31:51, 111:121), 0)), 
            type = "scatter3d", 
            mode = "lines",
            line = list(color = "green", width = gsw), 
            showlegend = FALSE) |>
  add_trace(x = df4[5,1], y = df4[5,2], z = 0, mode = "markers", type = "scatter3d", 
            marker = list(size = gsw, color = "rgb(0,0,200)", symbol = 104),
            showlegend = FALSE) |>
  add_trace(x = 0, y = 0, z = 0, mode = "markers", type = "scatter3d", 
            marker = list(size = gsw, color = "black", symbol = 104),
            showlegend = FALSE) |>
  add_trace(x = 1, y = 0, z = 0, mode = "markers", type = "scatter3d", 
            marker = list(size = gsw, color = "black", symbol = 104),
            showlegend = FALSE) |>
  layout(font = list(family = "Palatino"),
         scene = c(tadpole.layout(x_range, y_range, z_range), notes3),
         margin = list(l = 0, r = 0, b = 0, t = 0),
  paper_bgcolor = "white",  # the overall canvas background
  plot_bgcolor  = "white",   # the area inside axes
         showlegend = FALSE,
         font = list(family = "Palatino"))
save(p3, file = here::here("data_files/tadpole_graph_basis_functions.Rdata"))

# combine_plotly_grid_pdf(list(p1,p2,p3), output_pdf = here::here("data_files/plotlypic/tadpole_graph_basis_functions.pdf"), ncol = 3)
# combine_plotly_pdf_single(p3, here::here("data_files/plotlypic/p3.pdf"))

3 Plots part 1

load(here::here("data_files/interval_graph.Rdata"))
p11

Figure 1: Interval graph \(\Gamma_I = (\mathcal{V}, \mathcal{E})\) with \(\mathcal{V} = \{v_1, v_2\}\) and \(\mathcal{E} = \{e_1\}\).

load(here::here("data_files/circle_graph.Rdata"))
p22

Figure 2: Circle graph \(\Gamma_C = (\mathcal{V}, \mathcal{E})\) with \(\mathcal{V} = \{v_1\}\) and \(\mathcal{E} = \{e_1\}\).

load(here::here("data_files/tadpole_graph.Rdata"))
p33

Figure 3: Tadpole graph \(\Gamma_T = (\mathcal{V}, \mathcal{E})\) with \(\mathcal{V} = \{v_1, v_2\}\) and \(\mathcal{E} = \{e_1,e_2\}\).

4 Plots part 2

load(here::here("data_files/tadpole_graph_function.Rdata"))
p1

Figure 4: A function \(f=\gamma\big|_\Gamma\) on the tadpole graph, where \(\gamma(x,y) = e^{-x^2-y^2}\), together with a path that illustrates the geodesic distance between points \(s_1\) and \(s_2\).

load(here::here("data_files/tadpole_graph_mesh.Rdata"))
p2

Figure 5: Mesh nodes on the tadpole graph.

load(here::here("data_files/tadpole_graph_basis_functions.Rdata"))
p3

Figure 6: Basis functions on the tadpole graph.

5 Plots part 3

load(here::here("data_files/interval_graph.Rdata"))
p11

Figure 7: Interval graph \(\Gamma_I = (\mathcal{V}, \mathcal{E})\) with \(\mathcal{V} = \{v_1, v_2\}\) and \(\mathcal{E} = \{e_1\}\).

load(here::here("data_files/interval_graph_flip_edge.Rdata"))
p2int

Figure 8: Interval graph \(\Gamma_I = (\mathcal{V}, \mathcal{E})\) with \(\mathcal{V} = \{v_1, v_2\}\) and \(\mathcal{E} = \{e_1\}\), where \(e_1\) is flipped.

6 References

grateful::cite_packages(output = "paragraph", out.dir = ".")

We used R version 4.5.2 (R Core Team 2025a) and the following R packages: cowplot v. 1.2.0 (Wilke 2025), ggmap v. 4.0.2 (Kahle and Wickham 2013), ggpubr v. 0.6.3 (Kassambara 2026), ggtext v. 0.1.2 (Wilke and Wiernik 2022), glue v. 1.8.0 (Hester and Bryan 2024), grid v. 4.5.2 (R Core Team 2025b), here v. 1.0.1 (Müller 2020), htmltools v. 0.5.8.1 (Cheng et al. 2024), INLA v. 25.11.22 (Rue, Martino, and Chopin 2009; Lindgren, Rue, and Lindström 2011; Martins et al. 2013; Lindgren and Rue 2015; De Coninck et al. 2016; Rue et al. 2017; Verbosio et al. 2017; Bakka et al. 2018; Kourounis, Fuchs, and Schenk 2018), inlabru v. 2.13.0 (Yuan et al. 2017; Bachl et al. 2019), knitr v. 1.50 (Xie 2014, 2015, 2025), latex2exp v. 0.9.8 (Meschiari 2026), Matrix v. 1.7.3 (Bates, Maechler, and Jagan 2025), MetricGraph v. 1.5.0.9000 (Bolin, Simas, and Wallin 2023a, 2023b, 2024, 2025; Bolin et al. 2024), OpenStreetMap v. 0.4.1 (Fellows and Stotz 2025), patchwork v. 1.3.1 (Pedersen 2025), plotly v. 4.11.0 (Sievert 2020), plotrix v. 3.8.14 (J 2006), renv v. 1.1.7 (Ushey and Wickham 2026), reshape2 v. 1.4.4 (Wickham 2007), reticulate v. 1.44.1 (Ushey, Allaire, and Tang 2025), rmarkdown v. 2.30 (Xie, Allaire, and Grolemund 2018; Xie, Dervieux, and Riederer 2020; Allaire et al. 2025), rSPDE v. 2.5.2.9000 (Bolin and Kirchner 2020; Bolin and Simas 2023; Bolin, Simas, and Xiong 2024), scales v. 1.4.0 (Wickham, Pedersen, and Seidel 2025), sf v. 1.1.0 (E. Pebesma 2018; E. Pebesma and Bivand 2023), slackr v. 3.4.0 (Kaye et al. 2025), sp v. 2.2.1 (E. J. Pebesma and Bivand 2005; Bivand, Pebesma, and Gomez-Rubio 2013), tidyverse v. 2.0.0 (Wickham et al. 2019), tikzDevice v. 0.12.6 (Sharpsteen and Bracken 2023), viridis v. 0.6.5 (Garnier et al. 2024), xaringanExtra v. 0.8.0 (Aden-Buie and Warkentin 2024).

Aden-Buie, Garrick, and Matthew T. Warkentin. 2024. xaringanExtra: Extras and Extensions for xaringan Slides. https://doi.org/10.32614/CRAN.package.xaringanExtra.
Allaire, JJ, Yihui Xie, Christophe Dervieux, Jonathan McPherson, Javier Luraschi, Kevin Ushey, Aron Atkins, et al. 2025. rmarkdown: Dynamic Documents for r. https://github.com/rstudio/rmarkdown.
Arioli, Mario, and Michele Benzi. 2018. “A Finite Element Method for Quantum Graphs.” IMA J. Numer. Anal. 38 (3): 1119–63.
Bachl, Fabian E., Finn Lindgren, David L. Borchers, and Janine B. Illian. 2019. inlabru: An R Package for Bayesian Spatial Modelling from Ecological Survey Data.” Methods in Ecology and Evolution 10: 760–66. https://doi.org/10.1111/2041-210X.13168.
Bakka, Haakon, Håvard Rue, Geir-Arne Fuglstad, Andrea I. Riebler, David Bolin, Janine Illian, Elias Krainski, Daniel P. Simpson, and Finn K. Lindgren. 2018. “Spatial Modelling with INLA: A Review.” WIRES (Invited Extended Review) xx (Feb): xx–. http://arxiv.org/abs/1802.06350.
Bates, Douglas, Martin Maechler, and Mikael Jagan. 2025. Matrix: Sparse and Dense Matrix Classes and Methods. https://doi.org/10.32614/CRAN.package.Matrix.
Bivand, Roger S., Edzer Pebesma, and Virgilio Gomez-Rubio. 2013. Applied Spatial Data Analysis with R, Second Edition. Springer, NY. https://asdar-book.org/.
Bolin, David, and Kristin Kirchner. 2020. “The Rational SPDE Approach for Gaussian Random Fields with General Smoothness.” Journal of Computational and Graphical Statistics 29 (2): 274–85. https://doi.org/10.1080/10618600.2019.1665537.
Bolin, David, Mihály Kovács, Vivek Kumar, and Alexandre B. Simas. 2024. “Regularity and Numerical Approximation of Fractional Elliptic Differential Equations on Compact Metric Graphs.” Mathematics of Computation 93 (349): 2439–72. https://doi.org/10.1090/mcom/3929.
Bolin, David, and Alexandre B. Simas. 2023. rSPDE: Rational Approximations of Fractional Stochastic Partial Differential Equations. https://CRAN.R-project.org/package=rSPDE.
Bolin, David, Alexandre B. Simas, and Jonas Wallin. 2023a. MetricGraph: Random Fields on Metric Graphs. https://CRAN.R-project.org/package=MetricGraph.
———. 2023b. “Statistical Inference for Gaussian Whittle-Matérn Fields on Metric Graphs.” arXiv Preprint arXiv:2304.10372. https://doi.org/10.48550/arXiv.2304.10372.
———. 2024. “Gaussian Whittle-Matérn Fields on Metric Graphs.” Bernoulli 30 (2): 1611–39. https://doi.org/10.3150/23-BEJ1647.
———. 2025. “Markov Properties of Gaussian Random Fields on Compact Metric Graphs.” Bernoulli. https://doi.org/10.48550/arXiv.2304.03190.
Bolin, David, Alexandre B. Simas, and Zhen Xiong. 2024. “Covariance-Based Rational Approximations of Fractional SPDEs for Computationally Efficient Bayesian Inference.” Journal of Computational and Graphical Statistics 33 (1): 64–74. https://doi.org/10.1080/10618600.2023.2231051.
Cheng, Joe, Carson Sievert, Barret Schloerke, Winston Chang, Yihui Xie, and Jeff Allen. 2024. htmltools: Tools for HTML. https://github.com/rstudio/htmltools.
De Coninck, Arne, Bernard De Baets, Drosos Kourounis, Fabio Verbosio, Olaf Schenk, Steven Maenhout, and Jan Fostier. 2016. Needles: Toward Large-Scale Genomic Prediction with Marker-by-Environment Interaction.” Genetics 203 (1): 543–55. https://doi.org/10.1534/genetics.115.179887.
Fellows, Ian, and Jan-Peter Stotz. 2025. OpenStreetMap: Access to Open Street Map Raster Images. https://doi.org/10.32614/CRAN.package.OpenStreetMap.
Garnier, Simon, Ross, Noam, Rudis, Robert, Camargo, et al. 2024. viridis(Lite) - Colorblind-Friendly Color Maps for r. https://doi.org/10.5281/zenodo.4679423.
Hester, Jim, and Jennifer Bryan. 2024. glue: Interpreted String Literals. https://glue.tidyverse.org/.
J, Lemon. 2006. Plotrix: A Package in the Red Light District of r.” R-News 6 (4): 8–12.
Kahle, David, and Hadley Wickham. 2013. ggmap: Spatial Visualization with Ggplot2.” The R Journal 5 (1): 144–61. https://journal.r-project.org/archive/2013-1/kahle-wickham.pdf.
Kassambara, Alboukadel. 2026. ggpubr: ggplot2 Based Publication Ready Plots. https://doi.org/10.32614/CRAN.package.ggpubr.
Kaye, Matt, Bob Rudis, Andrie de Vries, and Jonathan Sidi. 2025. slackr: Send Messages, Images, r Objects and Files to Slack Channels/Users. https://github.com/mrkaye97/slackr.
Kourounis, D., A. Fuchs, and O. Schenk. 2018. “Towards the Next Generation of Multiperiod Optimal Power Flow Solvers.” IEEE Transactions on Power Systems PP (99): 1–10. https://doi.org/10.1109/TPWRS.2017.2789187.
Lindgren, Finn, and Håvard Rue. 2015. “Bayesian Spatial Modelling with R-INLA.” Journal of Statistical Software 63 (19): 1–25. http://www.jstatsoft.org/v63/i19/.
Lindgren, Finn, Håvard Rue, and Johan Lindström. 2011. “An Explicit Link Between Gaussian Fields and Gaussian Markov Random Fields: The Stochastic Partial Differential Equation Approach (with Discussion).” Journal of the Royal Statistical Society B 73 (4): 423–98.
Martins, Thiago G., Daniel Simpson, Finn Lindgren, and Håvard Rue. 2013. “Bayesian Computing with INLA: New Features.” Computational Statistics and Data Analysis 67: 68–83.
Meschiari, Stefano. 2026. Latex2exp: Use LaTeX Expressions in Plots. https://doi.org/10.32614/CRAN.package.latex2exp.
Müller, Kirill. 2020. here: A Simpler Way to Find Your Files. https://doi.org/10.32614/CRAN.package.here.
Pebesma, Edzer. 2018. Simple Features for R: Standardized Support for Spatial Vector Data.” The R Journal 10 (1): 439–46. https://doi.org/10.32614/RJ-2018-009.
Pebesma, Edzer J., and Roger Bivand. 2005. “Classes and Methods for Spatial Data in R.” R News 5 (2): 9–13. https://CRAN.R-project.org/doc/Rnews/.
Pebesma, Edzer, and Roger Bivand. 2023. Spatial Data Science: With applications in R. Chapman and Hall/CRC. https://doi.org/10.1201/9780429459016.
Pedersen, Thomas Lin. 2025. patchwork: The Composer of Plots. https://doi.org/10.32614/CRAN.package.patchwork.
R Core Team. 2025a. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
———. 2025b. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
Rue, Håvard, Sara Martino, and Nicholas Chopin. 2009. “Approximate Bayesian Inference for Latent Gaussian Models Using Integrated Nested Laplace Approximations (with Discussion).” Journal of the Royal Statistical Society B 71: 319–92.
Rue, Håvard, Andrea I. Riebler, Sigrunn H. Sørbye, Janine B. Illian, Daniel P. Simpson, and Finn K. Lindgren. 2017. “Bayesian Computing with INLA: A Review.” Annual Reviews of Statistics and Its Applications 4 (March): 395–421. http://arxiv.org/abs/1604.00860.
Sharpsteen, Charlie, and Cameron Bracken. 2023. tikzDevice: R Graphics Output in LaTeX Format. https://doi.org/10.32614/CRAN.package.tikzDevice.
Sievert, Carson. 2020. Interactive Web-Based Data Visualization with r, Plotly, and Shiny. Chapman; Hall/CRC. https://plotly-r.com.
Ushey, Kevin, JJ Allaire, and Yuan Tang. 2025. reticulate: Interface to Python. https://doi.org/10.32614/CRAN.package.reticulate.
Ushey, Kevin, and Hadley Wickham. 2026. renv: Project Environments. https://doi.org/10.32614/CRAN.package.renv.
Verbosio, Fabio, Arne De Coninck, Drosos Kourounis, and Olaf Schenk. 2017. “Enhancing the Scalability of Selected Inversion Factorization Algorithms in Genomic Prediction.” Journal of Computational Science 22 (Supplement C): 99–108. https://doi.org/10.1016/j.jocs.2017.08.013.
Wickham, Hadley. 2007. “Reshaping Data with the reshape Package.” Journal of Statistical Software 21 (12): 1–20. http://www.jstatsoft.org/v21/i12/.
Wickham, Hadley, Mara Averick, Jennifer Bryan, Winston Chang, Lucy D’Agostino McGowan, Romain François, Garrett Grolemund, et al. 2019. “Welcome to the tidyverse.” Journal of Open Source Software 4 (43): 1686. https://doi.org/10.21105/joss.01686.
Wickham, Hadley, Thomas Lin Pedersen, and Dana Seidel. 2025. scales: Scale Functions for Visualization. https://scales.r-lib.org.
Wilke, Claus O. 2025. cowplot: Streamlined Plot Theme and Plot Annotations for ggplot2. https://doi.org/10.32614/CRAN.package.cowplot.
Wilke, Claus O., and Brenton M. Wiernik. 2022. ggtext: Improved Text Rendering Support for ggplot2. https://doi.org/10.32614/CRAN.package.ggtext.
Xie, Yihui. 2014. knitr: A Comprehensive Tool for Reproducible Research in R.” In Implementing Reproducible Computational Research, edited by Victoria Stodden, Friedrich Leisch, and Roger D. Peng. Chapman; Hall/CRC.
———. 2015. Dynamic Documents with R and Knitr. 2nd ed. Boca Raton, Florida: Chapman; Hall/CRC. https://yihui.org/knitr/.
———. 2025. knitr: A General-Purpose Package for Dynamic Report Generation in R. https://yihui.org/knitr/.
Xie, Yihui, J. J. Allaire, and Garrett Grolemund. 2018. R Markdown: The Definitive Guide. Boca Raton, Florida: Chapman; Hall/CRC. https://bookdown.org/yihui/rmarkdown.
Xie, Yihui, Christophe Dervieux, and Emily Riederer. 2020. R Markdown Cookbook. Boca Raton, Florida: Chapman; Hall/CRC. https://bookdown.org/yihui/rmarkdown-cookbook.
Yuan, Yuan, Bachl, Fabian E., Lindgren, Finn, Borchers, et al. 2017. “Point Process Models for Spatio-Temporal Distance Sampling Data from a Large-Scale Survey of Blue Whales.” Ann. Appl. Stat. 11 (4): 2270–97. https://doi.org/10.1214/17-AOAS1078.
LS0tCnRpdGxlOiAiU2ltcGxlc3QgZ3JhcGhzIGFuZCBtb3JlIgpkYXRlOiAiTGFzdCBtb2RpZmllZDogYHIgZm9ybWF0KFN5cy50aW1lKCksICclZC0lbS0lWS4nKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgbWF0aGpheDogImh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbWF0aGpheEAzL2VzNS90ZXgtbW1sLWNodG1sLmpzIgogICAgaGlnaGxpZ2h0OiBweWdtZW50cwogICAgdGhlbWU6IGZsYXRseQogICAgY29kZV9mb2xkaW5nOiBoaWRlICMgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSIgdG8gaGlkZSBjb2RlIGFuZCBhZGQgYSBidXR0b24gdG8gc2hvdyBpdAogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNzczogdmlzdWFsLmNzcwphbHdheXNfYWxsb3dfaHRtbDogdHJ1ZQpiaWJsaW9ncmFwaHk6IAogIC0gcmVmZXJlbmNlcy5iaWIKICAtIGdyYXRlZnVsLXJlZnMuYmliCmhlYWRlci1pbmNsdWRlczoKICAtIFxuZXdjb21tYW5ke1xhcn17XG1hdGhiYntSfX0KICAtIFxuZXdjb21tYW5ke1xsbGF2fVsxXXtcbGVmdFx7IzFccmlnaHRcfX0KICAtIFxuZXdjb21tYW5ke1xwYXJlfVsxXXtcbGVmdCgjMVxyaWdodCl9CiAgLSBcbmV3Y29tbWFuZHtcTmNhbH17XG1hdGhjYWx7Tn19CiAgLSBcbmV3Y29tbWFuZHtcVmNhbH17XG1hdGhjYWx7Vn19CiAgLSBcbmV3Y29tbWFuZHtcRWNhbH17XG1hdGhjYWx7RX19CiAgLSBcbmV3Y29tbWFuZHtcV2NhbH17XG1hdGhjYWx7V319CiAgLSBcbmV3Y29tbWFuZHtcYWxtb3N0ZXZlcnl3aGVyZX17XG1hdGhybXthLmUufVw7fQotLS0KCkdvIGJhY2sgdG8gdGhlIFtDb250ZW50c10oYWJvdXQuaHRtbCkgcGFnZS4KCjxkaXYgc3R5bGU9ImNvbG9yOiAjMmMzZTUwOyB0ZXh0LWFsaWduOiByaWdodDsiPgoqKioqKioqKiAgCjxzdHJvbmc+UHJlc3MgU2hvdyB0byByZXZlYWwgdGhlIGNvZGUgY2h1bmtzLjwvc3Ryb25nPiAgCgoqKioqKioqKgo8L2Rpdj4KCgpgYGB7cn0KIyBDcmVhdGUgYSBjbGlwYm9hcmQgYnV0dG9uIG9uIHRoZSByZW5kZXJlZCBIVE1MIHBhZ2UKc291cmNlKGhlcmU6OmhlcmUoImNsaXBib2FyZC5SIikpOyBjbGlwYm9hcmQKIyBTZXQgc2VlZCBmb3IgcmVwcm9kdWNpYmlsaXR5CnNldC5zZWVkKDE5ODIpIAojIFNldCBnbG9iYWwgb3B0aW9ucyBmb3IgYWxsIGNvZGUgY2h1bmtzCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICAjIERpc2FibGUgbWVzc2FnZXMgcHJpbnRlZCBieSBSIGNvZGUgY2h1bmtzCiAgbWVzc2FnZSA9IEZBTFNFLCAgICAKICAjIERpc2FibGUgd2FybmluZ3MgcHJpbnRlZCBieSBSIGNvZGUgY2h1bmtzCiAgd2FybmluZyA9IEZBTFNFLCAgICAKICAjIFNob3cgUiBjb2RlIHdpdGhpbiBjb2RlIGNodW5rcyBpbiBvdXRwdXQKICBlY2hvID0gVFJVRSwgICAgICAgIAogICMgSW5jbHVkZSBib3RoIFIgY29kZSBhbmQgaXRzIHJlc3VsdHMgaW4gb3V0cHV0CiAgaW5jbHVkZSA9IFRSVUUsICAgICAKICAjIEV2YWx1YXRlIFIgY29kZSBjaHVua3MKICBldmFsID0gRkFMU0UsICAgICAgIAogICMgRW5hYmxlIGNhY2hpbmcgb2YgUiBjb2RlIGNodW5rcyBmb3IgZmFzdGVyIHJlbmRlcmluZwogIGNhY2hlID0gRkFMU0UsICAgICAgCiAgIyBBbGlnbiBmaWd1cmVzIGluIHRoZSBjZW50ZXIgb2YgdGhlIG91dHB1dAogIGZpZy5hbGlnbiA9ICJjZW50ZXIiLAogICMgRW5hYmxlIHJldGluYSBkaXNwbGF5IGZvciBoaWdoLXJlc29sdXRpb24gZmlndXJlcwogIHJldGluYSA9IDIsCiAgIyBTaG93IGVycm9ycyBpbiB0aGUgb3V0cHV0IGluc3RlYWQgb2Ygc3RvcHBpbmcgcmVuZGVyaW5nCiAgZXJyb3IgPSBUUlVFLAogICMgRG8gbm90IGNvbGxhcHNlIGNvZGUgYW5kIG91dHB1dCBpbnRvIGEgc2luZ2xlIGJsb2NrCiAgY29sbGFwc2UgPSBGQUxTRQopCiMgU3RhcnQgdGhlIGZpZ3VyZSBjb3VudGVyCmZpZ19jb3VudCA8LSAwCiMgRGVmaW5lIHRoZSBjYXB0aW9uZXIgZnVuY3Rpb24KY2FwdGlvbmVyIDwtIGZ1bmN0aW9uKGNhcHRpb24pIHsKICBmaWdfY291bnQgPDwtIGZpZ19jb3VudCArIDEKICBwYXN0ZTAoIkZpZ3VyZSAiLCBmaWdfY291bnQsICI6ICIsIGNhcHRpb24pCn0KCmBgYAoKYGBge3IsIGV2YWwgPSBUUlVFfQpsaWJyYXJ5KE1ldHJpY0dyYXBoKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocmVzaGFwZTIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodmlyaWRpcykKbGlicmFyeShwbG90bHkpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KHNsYWNrcikKc291cmNlKCJrZXlzLlIiKQpzbGFja3Jfc2V0dXAodG9rZW4gPSB0b2tlbikgIyB0b2tlbiBjb21lcyBmcm9tIGtleXMuUgoKbGlicmFyeShyZXRpY3VsYXRlKQpweV9jb25maWcoKQpgYGAKCgpgYGB7cn0KY2FwdHVyZS5vdXRwdXQoCiAga25pdHI6OnB1cmwoaGVyZTo6aGVyZSgiZnVuY3Rpb25hbGl0eTEuUm1kIiksIG91dHB1dCA9IGhlcmU6OmhlcmUoImZ1bmN0aW9uYWxpdHkxLlIiKSksCiAgZmlsZSA9IGhlcmU6OmhlcmUoIm9sZC9wdXJsX2xvZy50eHQiKQopCnNvdXJjZShoZXJlOjpoZXJlKCJmdW5jdGlvbmFsaXR5MS5SIikpCmBgYAoKCgo8ZGl2IHN0eWxlPSJjb2xvcjogYmx1ZTsiPgoqKioqKioqKgoqKlByZXNzIHRoZSBTaG93IGJ1dHRvbiBiZWxvdyB0byByZXZlYWwgdGhlIGNvZGUuKioKCioqKioqKioqCjwvZGl2PgoKIyBQYXJ0IDEKCiMjIEludGVydmFsIGdyYXBoCgpCZWxvdyB3ZSBwbG90IHRoZSBpbnRlcnZhbCBncmFwaCAkXEdhbW1hX0kgPSAoXG1hdGhjYWx7Vn0sIFxtYXRoY2Fse0V9KSQgd2l0aCAkXG1hdGhjYWx7Vn0gPSBce3ZfMSwgdl8yXH0kIGFuZCAkXG1hdGhjYWx7RX0gPSBce2VfMVx9JCwgd2hlcmUgJGVfMSQgaXMgdGhlIGVkZ2UgY29ubmVjdGluZyAkdl8xJCBhbmQgJHZfMiQuIAoKYGBge3J9CmUxX2luaV94IDwtIDA7IGUxX2luaV95IDwtIDA7IGUxX2luaV96IDwtIDAKZTFfZmluX3ggPC0gMTsgZTFfZmluX3kgPC0gMDsgZTFfZmluX3ogPC0gMAoKIyBNaWRwb2ludAp4bTEgPC0gKGUxX2Zpbl94ICsgZTFfaW5pX3gpLzIKeW0xIDwtIChlMV9maW5feSArIGUxX2luaV95KS8yCnptMSA8LSAoZTFfZmluX3ogKyBlMV9pbmlfeikvMgoKIyBEaXJlY3Rpb24gdmVjdG9yCmR4MSA8LSBlMV9maW5feCAtIGUxX2luaV94CmR5MSA8LSBlMV9maW5feSAtIGUxX2luaV95CmR6MSA8LSBlMV9maW5feiAtIGUxX2luaV96CgoKZTJfaW5pX3ggPC0gMDsgZTJfaW5pX3kgPC0gMTsgZTJfaW5pX3ogPC0gMAplMl9maW5feCA8LSAwOyBlMl9maW5feSA8LSAwOyBlMl9maW5feiA8LSAwCgojIE1pZHBvaW50CnhtMiA8LSAoZTJfZmluX3ggKyBlMl9pbmlfeCkvMgp5bTIgPC0gKGUyX2Zpbl95ICsgZTJfaW5pX3kpLzIKem0yIDwtIChlMl9maW5feiArIGUyX2luaV96KS8yCgojIERpcmVjdGlvbiB2ZWN0b3IKZHgyIDwtIGUyX2Zpbl94IC0gZTJfaW5pX3gKZHkyIDwtIGUyX2Zpbl95IC0gZTJfaW5pX3kKZHoyIDwtIGUyX2Zpbl96IC0gZTJfaW5pX3oKCiMgZm9yIHRoZSBjaXJjbGUKciA8LSAxL3BpCmN4IDwtIDEgKyByCmN5IDwtIDAKCiMgcGFyYW1ldGVyIHZhbHVlIHdoZXJlIHRoZSBjb25lIHdpbGwgYmUgcGxhY2VkCnQwIDwtIDAKCiMgcG9zaXRpb24gb24gdGhlIGN1cnZlCngwIDwtIGN4ICsgcipjb3ModDApCnkwIDwtIGN5ICsgcipzaW4odDApCnowIDwtIDAKCiMgdGFuZ2VudCB2ZWN0b3IgKGRlcml2YXRpdmUpCmR4IDwtIC1yKnNpbih0MCkKZHkgPC0gIHIqY29zKHQwKQpkeiA8LSAwCgpzaXplcmVmIDwtIDAuMQpgYGAKCgpgYGB7cn0KbiA8LSAzIzMzMwpncmFwaCA8LSBnZXRzLmdyYXBoLmludGVydmFsKG4gPSBuKQoKbm90ZXNfaW50IDwtIGxpc3QoYW5ub3RhdGlvbnMgPSBsaXN0KAogICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgeCA9IDAsIHkgPSAwLCB6ID0gMCwKICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgidl8xIiksCiAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAzNSwKICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJncmF5IiwgYXJyb3dzaXplID0gMSwgYXJyb3d3aWR0aCA9IDAuNSwgYXJyb3doZWFkID0gMSksCiAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICB4ID0gMCwgeSA9IDEsIHogPSAwLAogICAgICAgICAgICAgICB0ZXh0ID0gVGVYKCJ2XzIiKSwKICAgICAgICAgICAgICAgdGV4dGFuZ2xlID0gMCwgYXggPSAwLCBheSA9IDM1LAogICAgICAgICAgICAgICBmb250ID0gbGlzdChjb2xvciA9ICJibGFjayIsIHNpemUgPSBnZnNpemUpLAogICAgICAgICAgICAgICBhcnJvd2NvbG9yID0gImdyYXkiLCBhcnJvd3NpemUgPSAxLCBhcnJvd3dpZHRoID0gMC41LCBhcnJvd2hlYWQgPSAxKSwKICAgICAgICAgICAgIGxpc3QoCiAgICAgICAgICAgICAgIHggPSAwLCB5ID0gMC41LCB6ID0gMCwKICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgiZV8xIiksCiAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAzNSwKICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJyZ2JhKDAsMCwwLDApIikpKQoKbGF5b3V0X2ludCA8LSBsaXN0KHhheGlzID0gbGlzdCh0aXRsZSA9IGxpc3QodGV4dCA9ICJ4IiwgZm9udCA9IGxpc3QoY29sb3IgPSBjb2xheG5uKSksICB0aWNrZm9udCA9IGxpc3QoY29sb3IgPSBjb2xheG5uKSksCiAgICAgICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gbGlzdCh0ZXh0ID0gInkiLCBmb250ID0gbGlzdChjb2xvciA9IGNvbGF4bm4pKSwgIHRpY2tmb250ID0gbGlzdChjb2xvciA9IGNvbGF4bm4pKSwKICAgICAgICAgICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSBsaXN0KHRleHQgPSAieiIsIGZvbnQgPSBsaXN0KGNvbG9yID0gY29sYXhubikpLCAgdGlja2ZvbnQgPSBsaXN0KGNvbG9yID0gY29sYXhubikpLAogIGNhbWVyYSA9IGxpc3QoZXllID0gbGlzdCh4ID0gMi4zLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IDIuMywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHogPSAyLjMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VudGVyID0gbGlzdCh4ID0gMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeiA9IDApKSkKCnAxMSA8LSBncmFwaCRwbG90X2Z1bmN0aW9uKHJlcCgwLG5yb3coZ3JhcGgkbWVzaCRWKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJ0ZXhfc2l6ZSA9IGdzdywKICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJwbG90bHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZV93aWR0aCA9IGdzdywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkZ2Vfd2lkdGggPSBnc3csIAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lX2NvbG9yID0gImJsYWNrIil8PgogIGNvbmZpZyhtYXRoamF4ID0gJ2NkbicpIHw+CiAgICBhZGRfdHJhY2UoCiAgdHlwZSA9ICJjb25lIiwKICB4ID0geW0xLAogIHkgPSB4bTEsCiAgeiA9IHptMSwKICB1ID0gZHkxLAogIHYgPSBkeDEsCiAgdyA9IGR6MSwKICBzaXplbW9kZSA9ICJhYnNvbHV0ZSIsCiAgc2l6ZXJlZiA9IHNpemVyZWYsCiAgc2hvd3NjYWxlID0gRkFMU0UsCiAgc2hvd2xlZ2VuZCA9IEZBTFNFLAogIGNvbG9yc2NhbGUgPSBsaXN0KGMoMCwgMSksIGMoImdyZWVuIiwgImdyZWVuIikpLAogIGNtaW4gPSAwLAogIGNtYXggPSAxCikgfD4KICBsYXlvdXQoZm9udCA9IGxpc3QoZmFtaWx5ID0gIlBhbGF0aW5vIiksCiAgICAgICAgIHNjZW5lID0gIGMobm90ZXNfaW50LCBsYXlvdXRfaW50KSwKICAgICAgICAgbWFyZ2luID0gbGlzdChsID0gMCwgciA9IDAsIGIgPSAwLCB0ID0gMCksCiAgICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRSwKICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gIlBhbGF0aW5vIikpCgoKCnAyaW50IDwtIGdyYXBoJHBsb3RfZnVuY3Rpb24ocmVwKDAsbnJvdyhncmFwaCRtZXNoJFYpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcnRleF9zaXplID0gZ3N3LAogICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gInBsb3RseSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lX3dpZHRoID0gZ3N3LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRnZV93aWR0aCA9IGdzdywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVfY29sb3IgPSAiYmxhY2siKXw+CiAgY29uZmlnKG1hdGhqYXggPSAnY2RuJykgfD4KICAgIGFkZF90cmFjZSgKICB0eXBlID0gImNvbmUiLAogIHggPSB4bTIsCiAgeSA9IHltMiwKICB6ID0gem0yLAogIHUgPSBkeDIsCiAgdiA9IGR5MiwKICB3ID0gZHoyLAogIHNpemVtb2RlID0gImFic29sdXRlIiwKICBzaXplcmVmID0gc2l6ZXJlZiwKICBzaG93c2NhbGUgPSBGQUxTRSwKICBzaG93bGVnZW5kID0gRkFMU0UsCiAgY29sb3JzY2FsZSA9IGxpc3QoYygwLCAxKSwgYygiZ3JlZW4iLCAiZ3JlZW4iKSksCiAgY21pbiA9IDAsCiAgY21heCA9IDEKKSB8PgogIGxheW91dChmb250ID0gbGlzdChmYW1pbHkgPSAiUGFsYXRpbm8iKSwKICAgICAgICAgc2NlbmUgPSAgYyhub3Rlc19pbnQsIGxheW91dF9pbnQpLAogICAgICAgICBtYXJnaW4gPSBsaXN0KGwgPSAwLCByID0gMCwgYiA9IDAsIHQgPSAwKSwKICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFLAogICAgICAgICBmb250ID0gbGlzdChmYW1pbHkgPSAiUGFsYXRpbm8iKSkKCgpzYXZlKHAxMSwgZmlsZSA9IGhlcmU6OmhlcmUoImRhdGFfZmlsZXMvaW50ZXJ2YWxfZ3JhcGguUmRhdGEiKSkKc2F2ZShwMmludCwgZmlsZSA9IGhlcmU6OmhlcmUoImRhdGFfZmlsZXMvaW50ZXJ2YWxfZ3JhcGhfZmxpcF9lZGdlLlJkYXRhIikpCmBgYAoKIyMgQ2lyY2xlIGdyYXBoCgpCZWxvdyB3ZSBwbG90IHRoZSBjaXJjbGUgZ3JhcGggJFxHYW1tYV9DID0gKFxtYXRoY2Fse1Z9LCBcbWF0aGNhbHtFfSkkIHdpdGggJFxtYXRoY2Fse1Z9ID0gXHt2XzJcfSQgYW5kICRcbWF0aGNhbHtFfSA9IFx7ZV8yXH0kLCB3aGVyZSAkZV8yJCBpcyB0aGUgZWRnZSBjb25uZWN0aW5nICR2XzIkIHRvIGl0c2VsZi4KCmBgYHtyfQpuIDwtIDYjNjY2CmdyYXBoIDwtIGdldHMuZ3JhcGguY2lyY2xlKG4gPSBuKQoKbm90ZXNfY2lyIDwtIGxpc3QoYW5ub3RhdGlvbnMgPSBsaXN0KAogICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgeCA9IDAsIHkgPSAxLCB6ID0gMCwKICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgidl8yIiksCiAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAzNSwKICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJncmF5IiwgYXJyb3dzaXplID0gMSwgYXJyb3d3aWR0aCA9IDAuNSwgYXJyb3doZWFkID0gMSksCiAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICB4ID0gMCwgeSA9IDEgKyAyL3BpLCB6ID0gMCwKICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgiZV8yIiksCiAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAzNSwKICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJyZ2JhKDAsMCwwLDApIikpKQogIAogIApwMjIgPC0gZ3JhcGgkcGxvdF9mdW5jdGlvbihyZXAoMCxucm93KGdyYXBoJG1lc2gkVikpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVydGV4X3NpemUgPSBnc3csCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAicGxvdGx5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVfd2lkdGggPSBnc3csIAogICAgICAgICAgICAgICAgICAgICAgICAgICBlZGdlX3dpZHRoID0gZ3N3LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZV9jb2xvciA9ICJibGFjayIpICU+JSAKICBjb25maWcobWF0aGpheCA9ICdjZG4nKSAlPiUgCiAgYWRkX3RyYWNlKAogICAgdHlwZSA9ICJjb25lIiwKICAgIHggPSB5MCwKICAgIHkgPSB4MCwKICAgIHogPSB6MCwKICAgIHUgPSBkeSwKICAgIHYgPSBkeCwKICAgIHcgPSBkeiwKICAgIHNpemVtb2RlID0gImFic29sdXRlIiwKICAgIHNpemVyZWYgPSBzaXplcmVmLAogICAgc2hvd3NjYWxlID0gRkFMU0UsCiAgICBzaG93bGVnZW5kID0gRkFMU0UsCiAgICBjb2xvcnNjYWxlID0gbGlzdChjKDAsMSksIGMoImdyZWVuIiwiZ3JlZW4iKSksCiAgICBjbWluID0gMCwKICAgIGNtYXggPSAxCiAgKSB8PgogIGxheW91dChmb250ID0gbGlzdChmYW1pbHkgPSAiUGFsYXRpbm8iKSwKICAgICAgICAgc2NlbmUgPSAgYyhub3Rlc19jaXIsIGxheW91dF9pbnQpLAogICAgICAgICBtYXJnaW4gPSBsaXN0KGwgPSAwLCByID0gMCwgYiA9IDAsIHQgPSAwKSwKICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFLAogICAgICAgICBmb250ID0gbGlzdChmYW1pbHkgPSAiUGFsYXRpbm8iKSkKc2F2ZShwMjIsIGZpbGUgPSBoZXJlOjpoZXJlKCJkYXRhX2ZpbGVzL2NpcmNsZV9ncmFwaC5SZGF0YSIpKQpgYGAKCiMjIFRhZHBvbGUgZ3JhcGgKCkJlbG93IHdlIHBsb3QgdGhlIHRhZHBvbGUgZ3JhcGggJFxHYW1tYV9UID0gKFxtYXRoY2Fse1Z9LCBcbWF0aGNhbHtFfSkkIHdpdGggJFxtYXRoY2Fse1Z9ID0gXHt2XzEsIHZfMlx9JCBhbmQgJFxtYXRoY2Fse0V9ID0gXHtlXzEsIGVfMlx9JCwgd2hlcmUgJGVfMSQgaXMgdGhlIGVkZ2UgY29ubmVjdGluZyAkdl8xJCBhbmQgJHZfMiQsIGFuZCAkZV8yJCBpcyB0aGUgZWRnZSBjb25uZWN0aW5nICR2XzIkIHRvIGl0c2VsZi4KCmBgYHtyfQoKZ3JhcGggPC0gZ2V0cy5ncmFwaC50YWRwb2xlKGggPSAxLzQpCgpub3Rlc190YWRfMSA8LSBsaXN0KGFubm90YXRpb25zID0gbGlzdCgKICAgICAgICAgICAgIGxpc3QoCiAgICAgICAgICAgICAgIHggPSAwLCB5ID0gMCwgeiA9IDAsCiAgICAgICAgICAgICAgIHRleHQgPSBUZVgoInZfMSIpLAogICAgICAgICAgICAgICB0ZXh0YW5nbGUgPSAwLCBheCA9IDAsIGF5ID0gMzUsCiAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAiZ3JheSIsIGFycm93c2l6ZSA9IDEsIGFycm93d2lkdGggPSAwLjUsIGFycm93aGVhZCA9IDEpLAogICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgeCA9IDAsIHkgPSAxLCB6ID0gMCwKICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgidl8yIiksCiAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAzNSwKICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJncmF5IiwgYXJyb3dzaXplID0gMSwgYXJyb3d3aWR0aCA9IDAuNSwgYXJyb3doZWFkID0gMSksCiAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICB4ID0gMCwgeSA9IDAuNSwgeiA9IDAsCiAgICAgICAgICAgICAgIHRleHQgPSBUZVgoImVfMSIpLAogICAgICAgICAgICAgICB0ZXh0YW5nbGUgPSAwLCBheCA9IDAsIGF5ID0gMzUsCiAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAicmdiYSgwLDAsMCwwKSIpLAogICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgeCA9IDAsIHkgPSAxKzIvcGksIHogPSAwLAogICAgICAgICAgICAgICB0ZXh0ID0gVGVYKCJlXzIiKSwKICAgICAgICAgICAgICAgdGV4dGFuZ2xlID0gMCwgYXggPSAwLCBheSA9IDM1LAogICAgICAgICAgICAgICBmb250ID0gbGlzdChjb2xvciA9ICJibGFjayIsIHNpemUgPSBnZnNpemUpLAogICAgICAgICAgICAgICBhcnJvd2NvbG9yID0gInJnYmEoMCwwLDAsMCkiKSkpCgpwMzMgPC0gZ3JhcGgkcGxvdF9mdW5jdGlvbihyZXAoMCxucm93KGdyYXBoJG1lc2gkVikpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVydGV4X3NpemUgPSBnc3csCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAicGxvdGx5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVfd2lkdGggPSBnc3csIAogICAgICAgICAgICAgICAgICAgICAgICAgICBlZGdlX3dpZHRoID0gZ3N3LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZV9jb2xvciA9ICJibGFjayIpIHw+CiAgY29uZmlnKG1hdGhqYXggPSAnY2RuJykgfD4KICAgICAgYWRkX3RyYWNlKAogIHR5cGUgPSAiY29uZSIsCiAgeCA9IHltMSwKICB5ID0geG0xLAogIHogPSB6bTEsCiAgdSA9IGR5MSwKICB2ID0gZHgxLAogIHcgPSBkejEsCiAgc2l6ZW1vZGUgPSAiYWJzb2x1dGUiLAogIHNpemVyZWYgPSBzaXplcmVmLAogIHNob3dzY2FsZSA9IEZBTFNFLAogIHNob3dsZWdlbmQgPSBGQUxTRSwKICBjb2xvcnNjYWxlID0gbGlzdChjKDAsIDEpLCBjKCJncmVlbiIsICJncmVlbiIpKSwKICBjbWluID0gMCwKICBjbWF4ID0gMQopIHw+CiAgYWRkX3RyYWNlKAogICAgdHlwZSA9ICJjb25lIiwKICAgIHggPSB5MCwKICAgIHkgPSB4MCwKICAgIHogPSB6MCwKICAgIHUgPSBkeSwKICAgIHYgPSBkeCwKICAgIHcgPSBkeiwKICAgIHNpemVtb2RlID0gImFic29sdXRlIiwKICAgIHNpemVyZWYgPSBzaXplcmVmLAogICAgc2hvd3NjYWxlID0gRkFMU0UsCiAgICBzaG93bGVnZW5kID0gRkFMU0UsCiAgICBjb2xvcnNjYWxlID0gbGlzdChjKDAsMSksIGMoImdyZWVuIiwiZ3JlZW4iKSksCiAgICBjbWluID0gMCwKICAgIGNtYXggPSAxCiAgKSB8PgogIGxheW91dChmb250ID0gbGlzdChmYW1pbHkgPSAiUGFsYXRpbm8iKSwKICAgICAgICAgc2NlbmUgPSAgYyhub3Rlc190YWRfMSwgbGF5b3V0X2ludCksCiAgICAgICAgIG1hcmdpbiA9IGxpc3QobCA9IDAsIHIgPSAwLCBiID0gMCwgdCA9IDApLAogICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UsCiAgICAgICAgIGZvbnQgPSBsaXN0KGZhbWlseSA9ICJQYWxhdGlubyIpKQpzYXZlKHAzMywgZmlsZSA9IGhlcmU6OmhlcmUoImRhdGFfZmlsZXMvdGFkcG9sZV9ncmFwaC5SZGF0YSIpKQpgYGAKCiMgUGFydCAyCgojIyBGdW5jdGlvbnMgb24gYSBncmFwaCBhbmQgZ2VvZGVzaWMgZGlzdGFuY2UgaWxsdXN0cmF0aW9uCgpCZWxvdyB3ZSBwbG90IHRoZSBmdW5jdGlvbiAkZiA9IFxnYW1tYVxiaWd8X1xHYW1tYSQgd2hlcmUgJFxnYW1tYSh4LHkpID0gZV57LXheMi15XjJ9JCwgdG9nZXRoZXIgd2l0aCBhIHBhdGggb24gdGhlIGdyYXBoIHRoYXQgaWxsdXN0cmF0ZXMgdGhlIGdlb2Rlc2ljIGRpc3RhbmNlIGJldHdlZW4gcG9pbnRzICRzXzEkIGFuZCAkc18yJC4gCgpgYGB7cn0KZ3JhcGhfdG9fZ2V0X2xvYyA8LSBnZXRzLmdyYXBoLnRhZHBvbGUoaCA9IDEvNDApCmxvYyA8LSBncmFwaF90b19nZXRfbG9jJGdldF9tZXNoX2xvY2F0aW9ucygpCgpBIDwtIGFzLm1hdHJpeChncmFwaCRmZW1fYmFzaXMobG9jKSkKQSA8LSBhcHBseShBLCAyLCBmdW5jdGlvbih4KSBwbG90dGluZy5vcmRlcih4LCBncmFwaF90b19nZXRfbG9jKSkKQSA8LSByYmluZChBLCByZXAoTkEsIG5jb2woQSkpKSAjIEFkZCBhIHJvdyBvZiBOQXMgZm9yIHRoZSBwbG90dGluZwoKeF9nIDwtIGdyYXBoX3RvX2dldF9sb2MkbWVzaCRWWywgMV0KeV9nIDwtIGdyYXBoX3RvX2dldF9sb2MkbWVzaCRWWywgMl0KZl9nIDwtIGV4cCgteF9nXjIgLSB5X2deMikKCgp4IDwtIGMocGxvdHRpbmcub3JkZXIoeF9nLCBncmFwaF90b19nZXRfbG9jKSwgTkEpCnkgPC0gYyhwbG90dGluZy5vcmRlcih5X2csIGdyYXBoX3RvX2dldF9sb2MpLCBOQSkKZiA8LSBjKHBsb3R0aW5nLm9yZGVyKGZfZywgZ3JhcGhfdG9fZ2V0X2xvYyksIE5BKQoKCnhfcmFuZ2UgPC0gcmFuZ2UoeCwgbmEucm0gPSBUUlVFKSoxLjAwMQp5X3JhbmdlIDwtIHJhbmdlKHksIG5hLnJtID0gVFJVRSkqMS4wMDEKel9yYW5nZSA8LSBjKDAsMSkKYGBgCgpgYGB7cn0Kbm90ZXMxIDwtIGxpc3QoYW5ub3RhdGlvbnMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgeCA9IDAsIHkgPSAwLCB6ID0gMCwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgidl8xIiksCiAgICAgICAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAzNSwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJncmF5IiwgYXJyb3dzaXplID0gMSwgYXJyb3d3aWR0aCA9IDAuNSwgYXJyb3doZWFkID0gMSksCiAgICAgICAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICAgICAgICB4ID0gMSwgeSA9IDAsIHogPSAwLAogICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gVGVYKCJ2XzIiKSwKICAgICAgICAgICAgICAgICAgICAgdGV4dGFuZ2xlID0gMCwgYXggPSAwLCBheSA9IDM1LAogICAgICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChjb2xvciA9ICJibGFjayIsIHNpemUgPSBnZnNpemUpLAogICAgICAgICAgICAgICAgICAgICBhcnJvd2NvbG9yID0gImdyYXkiLCBhcnJvd3NpemUgPSAxLCBhcnJvd3dpZHRoID0gMC41LCBhcnJvd2hlYWQgPSAxKSwKICAgICAgICAgICAgICAgICAgIGxpc3QoCiAgICAgICAgICAgICAgICAgICAgIHggPSAwLjUsIHkgPSAwLCB6ID0gMCwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgiZV8xIiksCiAgICAgICAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAzNSwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJyZ2JhKDAsMCwwLDApIiksCiAgICAgICAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICAgICAgICB4ID0gMSsyL3BpLCB5ID0gMCwgeiA9IDAsCiAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBUZVgoImVfMiIpLAogICAgICAgICAgICAgICAgICAgICB0ZXh0YW5nbGUgPSAwLCBheCA9IDAsIGF5ID0gMzUsCiAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAicmdiYSgwLDAsMCwwKSIpLAogICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgeCA9IDAuMjUsIHkgPSAwLCB6ID0gMCwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgic18xIiksCiAgICAgICAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAzNSwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJncmF5IiwgYXJyb3dzaXplID0gMSwgYXJyb3d3aWR0aCA9IDAuNSwgYXJyb3doZWFkID0gMSksCiAgICAgICAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICAgICAgICB4ID0gMSsxL3BpLCB5ID0gMS9waSwgeiA9IDAsCiAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBUZVgoInNfMiIpLAogICAgICAgICAgICAgICAgICAgICB0ZXh0YW5nbGUgPSAwLCBheCA9IDAsIGF5ID0gMzUsCiAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAiZ3JheSIsIGFycm93c2l6ZSA9IDEsIGFycm93d2lkdGggPSAwLjUsIGFycm93aGVhZCA9IDEpLAogICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgeCA9IDAuMjUsIHkgPSAwLCB6ID0gMSwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgiZj1cXGdhbW1hXFxiaWd8X1xcR2FtbWEiKSwKICAgICAgICAgICAgICAgICAgICAgdGV4dGFuZ2xlID0gMCwgYXggPSAtNDAsIGF5ID0gMCwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAicmdiKDAsMCwyMDApIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAicmdiYSgwLDAsMCwwKSIpKSkKICAgIAojIHRvIHBsb3QgdGhlIHBhdGggCnRoZXRhIDwtIHNlcShmcm9tID0gcGkvMiwgdG8gPSBwaSwgbGVuZ3RoLm91dCA9IDEwMCkKU1NUSEVUQSA8LSBzZXEoZnJvbSA9IC1waSwgdG8gPSBwaS8yLCBsZW5ndGgub3V0ID0gMzAwKQpTUzEgPC0gZGF0YS5mcmFtZSh4ID0gYygwLCAwLjI1KSwgCiAgICAgICAgICAgICAgICAgIHkgPSBjKDAsMCksIAogICAgICAgICAgICAgICAgICB6ID0gYygwLDApKQpTUzIgPC0gZGF0YS5mcmFtZSh4ID0gMSsxL3BpK2NvcyhTU1RIRVRBKS9waSwgCiAgICAgICAgICAgICAgICAgIHkgPSBzaW4oU1NUSEVUQSkvcGksIAogICAgICAgICAgICAgICAgICB6ID0gcmVwKDAsIGxlbmd0aChTU1RIRVRBKSkpCmRmMSA8LSBkYXRhLmZyYW1lKHggPSBjKDAuMjUsMSksIAogICAgICAgICAgICAgICAgICB5ID0gYygwLDApLCAKICAgICAgICAgICAgICAgICAgeiA9IGMoMCwwKSkKZGYyIDwtIGRhdGEuZnJhbWUoeCA9IDErMS9waStjb3ModGhldGEpL3BpLCAKICAgICAgICAgICAgICAgICAgeSA9IHNpbih0aGV0YSkvcGksIAogICAgICAgICAgICAgICAgICB6ID0gcmVwKDAsIGxlbmd0aCh0aGV0YSkpKQoKcDEgPC0gcGxvdF9seSgpIHw+IAogIGNvbmZpZyhtYXRoamF4ID0gJ2NkbicpIHw+CiAgYWRkX3RyYWNlKHggPSAwLCB5ID0gMCwgeiA9IDAsIG1vZGUgPSAibWFya2VycyIsIHR5cGUgPSAic2NhdHRlcjNkIiwgCiAgICAgICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IGdzdywgY29sb3IgPSAiYmxhY2siLCBzeW1ib2wgPSAxMDQpLAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgYWRkX3RyYWNlKHggPSAxLCB5ID0gMCwgeiA9IDAsIG1vZGUgPSAibWFya2VycyIsIHR5cGUgPSAic2NhdHRlcjNkIiwgCiAgICAgICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IGdzdywgY29sb3IgPSAiYmxhY2siLCBzeW1ib2wgPSAxMDQpLAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgYWRkX3RyYWNlKHggPSAwLjI1LCB5ID0gMCwgeiA9IDAsIG1vZGUgPSAibWFya2VycyIsIHR5cGUgPSAic2NhdHRlcjNkIiwgCiAgICAgICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IGdzdywgY29sb3IgPSAicmVkIiwgc3ltYm9sID0gMTA0KSwKICAgICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFKSB8PiAKICBhZGRfdHJhY2UoeCA9IDErMS9waSwgeSA9IDEvcGksIHogPSAwLCBtb2RlID0gIm1hcmtlcnMiLCB0eXBlID0gInNjYXR0ZXIzZCIsIAogICAgICAgICAgICBtYXJrZXIgPSBsaXN0KHNpemUgPSBnc3csIGNvbG9yID0gInJlZCIsIHN5bWJvbCA9IDEwNCksCiAgICAgICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRSkgfD4gCiAgYWRkX3RyYWNlKGRhdGEgPSBTUzEsIHggPSB+eCwgeSA9IH55LCB6ID0gfnosIG1vZGUgPSAibGluZXMiLCB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICAgICAgICAgIGxpbmUgPSBsaXN0KHdpZHRoID0gZ3N3LCBjb2xvciA9ICJibGFjayIsIHN5bWJvbCA9IDEwNCksCiAgICAgICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRSkgfD4KICBhZGRfdHJhY2UoZGF0YSA9IFNTMiwgeCA9IH54LCB5ID0gfnksIHogPSB+eiwgbW9kZSA9ICJsaW5lcyIsIHR5cGUgPSAic2NhdHRlcjNkIiwKICAgICAgICAgICAgbGluZSA9IGxpc3Qod2lkdGggPSBnc3csIGNvbG9yID0gImJsYWNrIiwgc3ltYm9sID0gMTA0KSwKICAgICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFKSB8PgogIGFkZF90cmFjZShkYXRhID0gZGYxLCB4ID0gfngsIHkgPSB+eSwgeiA9IH56LCBtb2RlID0gImxpbmVzIiwgdHlwZSA9ICJzY2F0dGVyM2QiLAogICAgICAgICAgICBsaW5lID0gbGlzdCh3aWR0aCA9IGdzdywgY29sb3IgPSAicmVkIiwgc3ltYm9sID0gMTA0KSwKICAgICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFKSB8PgogIGFkZF90cmFjZShkYXRhID0gZGYyLCB4ID0gfngsIHkgPSB+eSwgeiA9IH56LCBtb2RlID0gImxpbmVzIiwgdHlwZSA9ICJzY2F0dGVyM2QiLAogICAgICAgICAgICBsaW5lID0gbGlzdCh3aWR0aCA9IGdzdywgY29sb3IgPSAicmVkIiwgc3ltYm9sID0gMTA0KSwKICAgICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFKSB8PgogIGFkZF90cmFjZSh4ID0geCwgCiAgICAgICAgICAgIHkgPSB5LCAKICAgICAgICAgICAgeiA9IGYsIAogICAgICAgICAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICAgICAgICAgIG1vZGUgPSAibGluZXMiLCAgCiAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gInJnYigwLDAsMjAwKSIsIHdpZHRoID0gZ3N3KSwKICAgICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFKSB8PgogIGFkZF90cmFjZSh4ID0gcmVwKHgsIGVhY2ggPSAzKSwgCiAgICAgICAgICAgIHkgPSByZXAoeSwgZWFjaCA9IDMpLCAKICAgICAgICAgICAgeiA9IHVubGlzdChsYXBwbHkoZiwgZnVuY3Rpb24oemopIGMoMCwgemosIE5BKSkpLAogICAgICAgICAgICB0eXBlID0gInNjYXR0ZXIzZCIsIAogICAgICAgICAgICBtb2RlID0gImxpbmVzIiwKICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAibGlnaHRncmF5Iiwgd2lkdGggPSAwLjUpLAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgbGF5b3V0KGZvbnQgPSBsaXN0KGZhbWlseSA9ICJQYWxhdGlubyIpLAogICAgICAgICBzY2VuZSA9IGModGFkcG9sZS5sYXlvdXQoeF9yYW5nZSwgeV9yYW5nZSwgel9yYW5nZSksbm90ZXMxKSwKICAgICAgICAgbWFyZ2luID0gbGlzdChsID0gMCwgciA9IDAsIGIgPSAwLCB0ID0gMCksCiAgICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRSwKICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gIlBhbGF0aW5vIikpCnNhdmUocDEsIGZpbGUgPSBoZXJlOjpoZXJlKCJkYXRhX2ZpbGVzL3RhZHBvbGVfZ3JhcGhfZnVuY3Rpb24uUmRhdGEiKSkKYGBgCgojIyBNZXNoCgpCZWxvdyB3ZSBwbG90IHRoZSBtZXNoIG9mIHRoZSB0YWRwb2xlIGdyYXBoLgoKYGBge3J9CgpkZjMgPC0gZGF0YS5mcmFtZSh4ID0gZ3JhcGgkbWVzaCRWWywgMV0sIAogICAgICAgICAgICAgICAgICB5ID0gZ3JhcGgkbWVzaCRWWywgMl0sIAogICAgICAgICAgICAgICAgICB6ID0gcmVwKDAsIGxlbmd0aChncmFwaCRtZXNoJFZbLCAxXSkpKQpkZjQgPC0gZGYzWzY6bnJvdyhkZjMpLCBdCgoKbm90ZXMyIDwtIGxpc3QoYW5ub3RhdGlvbnMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgeCA9IDAsIHkgPSAwLCB6ID0gMCwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgidl8xIiksCiAgICAgICAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAtMzUsCiAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAiZ3JheSIsIGFycm93c2l6ZSA9IDEsIGFycm93d2lkdGggPSAwLjUsIGFycm93aGVhZCA9IDEpLAogICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgeCA9IDEsIHkgPSAwLCB6ID0gMCwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgidl8yIiksCiAgICAgICAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAtMzUsCiAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAiZ3JheSIsIGFycm93c2l6ZSA9IDEsIGFycm93d2lkdGggPSAwLjUsIGFycm93aGVhZCA9IDEpLAogICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgeCA9IGRmNFsxLDFdLCB5ID0gZGY0WzEsMl0sIHogPSAwLAogICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gVGVYKCJ4XzFee2VfMn0iKSwKICAgICAgICAgICAgICAgICAgICAgdGV4dGFuZ2xlID0gMCwgYXggPSAwLCBheSA9IC0zNSwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJncmF5IiwgYXJyb3dzaXplID0gMSwgYXJyb3d3aWR0aCA9IDAuNSwgYXJyb3doZWFkID0gMSksCiAgICAgICAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICAgICAgICB4ID0gZGY0WzIsMV0sIHkgPSBkZjRbMiwyXSwgeiA9IDAsCiAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBUZVgoInhfMl57ZV8yfSIpLAogICAgICAgICAgICAgICAgICAgICB0ZXh0YW5nbGUgPSAwLCBheCA9IDAsIGF5ID0gLTM1LAogICAgICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChjb2xvciA9ICJibGFjayIsIHNpemUgPSBnZnNpemUpLAogICAgICAgICAgICAgICAgICAgICBhcnJvd2NvbG9yID0gImdyYXkiLCBhcnJvd3NpemUgPSAxLCBhcnJvd3dpZHRoID0gMC41LCBhcnJvd2hlYWQgPSAxKSwKICAgICAgICAgICAgICAgICAgIGxpc3QoCiAgICAgICAgICAgICAgICAgICAgIHggPSBkZjRbMywxXSwgeSA9IGRmNFszLDJdLCB6ID0gMCwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgieF8zXntlXzJ9IiksCiAgICAgICAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAtMzUsCiAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAiZ3JheSIsIGFycm93c2l6ZSA9IDEsIGFycm93d2lkdGggPSAwLjUsIGFycm93aGVhZCA9IDEpLAogICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgeCA9IGRmNFs0LDFdLCB5ID0gZGY0WzQsMl0sIHogPSAwLAogICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gVGVYKCJ4XzRee2VfMn0iKSwKICAgICAgICAgICAgICAgICAgICAgdGV4dGFuZ2xlID0gMCwgYXggPSAwLCBheSA9IC0zNSwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJncmF5IiwgYXJyb3dzaXplID0gMSwgYXJyb3d3aWR0aCA9IDAuNSwgYXJyb3doZWFkID0gMSksCiAgICAgICAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICAgICAgICB4ID0gZGY0WzUsMV0sIHkgPSBkZjRbNSwyXSwgeiA9IDAsCiAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBUZVgoInhfNV57ZV8yfSIpLAogICAgICAgICAgICAgICAgICAgICB0ZXh0YW5nbGUgPSAwLCBheCA9IDAsIGF5ID0gLTM1LAogICAgICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChjb2xvciA9ICJibGFjayIsIHNpemUgPSBnZnNpemUpLAogICAgICAgICAgICAgICAgICAgICBhcnJvd2NvbG9yID0gImdyYXkiLCBhcnJvd3NpemUgPSAxLCBhcnJvd3dpZHRoID0gMC41LCBhcnJvd2hlYWQgPSAxKSwKICAgICAgICAgICAgICAgICAgIGxpc3QoCiAgICAgICAgICAgICAgICAgICAgIHggPSBkZjRbNiwxXSwgeSA9IGRmNFs2LDJdLCB6ID0gMCwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgieF82XntlXzJ9IiksCiAgICAgICAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAtMzUsCiAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAiZ3JheSIsIGFycm93c2l6ZSA9IDEsIGFycm93d2lkdGggPSAwLjUsIGFycm93aGVhZCA9IDEpLAogICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgeCA9IGRmNFs3LDFdLCB5ID0gZGY0WzcsMl0sIHogPSAwLAogICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gVGVYKCJ4Xzdee2VfMn0iKSwKICAgICAgICAgICAgICAgICAgICAgdGV4dGFuZ2xlID0gMCwgYXggPSAwLCBheSA9IC0zNSwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJncmF5IiwgYXJyb3dzaXplID0gMSwgYXJyb3d3aWR0aCA9IDAuNSwgYXJyb3doZWFkID0gMSksCiAgICAgICAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICAgICAgICB4ID0gMC4yNSwgeSA9IDAsIHogPSAwLAogICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gVGVYKCJ4XzFee2VfMX0iKSwKICAgICAgICAgICAgICAgICAgICAgdGV4dGFuZ2xlID0gMCwgYXggPSAwLCBheSA9IC0zNSwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJncmF5IiwgYXJyb3dzaXplID0gMSwgYXJyb3d3aWR0aCA9IDAuNSwgYXJyb3doZWFkID0gMSksCiAgICAgICAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICAgICAgICB4ID0gMC41LCB5ID0gMCwgeiA9IDAsCiAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBUZVgoInhfMl57ZV8xfSIpLAogICAgICAgICAgICAgICAgICAgICB0ZXh0YW5nbGUgPSAwLCBheCA9IDAsIGF5ID0gLTM1LAogICAgICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChjb2xvciA9ICJibGFjayIsIHNpemUgPSBnZnNpemUpLAogICAgICAgICAgICAgICAgICAgICBhcnJvd2NvbG9yID0gImdyYXkiLCBhcnJvd3NpemUgPSAxLCBhcnJvd3dpZHRoID0gMC41LCBhcnJvd2hlYWQgPSAxKSwKICAgICAgICAgICAgICAgICAgIGxpc3QoCiAgICAgICAgICAgICAgICAgICAgIHggPSAwLjc1LCB5ID0gMCwgeiA9IDAsCiAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBUZVgoInhfM157ZV8xfSIpLAogICAgICAgICAgICAgICAgICAgICB0ZXh0YW5nbGUgPSAwLCBheCA9IDAsIGF5ID0gLTM1LAogICAgICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChjb2xvciA9ICJibGFjayIsIHNpemUgPSBnZnNpemUpLAogICAgICAgICAgICAgICAgICAgICBhcnJvd2NvbG9yID0gImdyYXkiLCBhcnJvd3NpemUgPSAxLCBhcnJvd3dpZHRoID0gMC41LCBhcnJvd2hlYWQgPSAxKSkpCgpwMiA8LSBwbG90X2x5KCkgfD4gCiAgY29uZmlnKG1hdGhqYXggPSAnY2RuJykgfD4KICBhZGRfdHJhY2UoeCA9IHgsIAogICAgICAgICAgICB5ID0geSwgCiAgICAgICAgICAgIHogPSB4KjAsIAogICAgICAgICAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICAgICAgICAgIG1vZGUgPSAibGluZXMiLCAgCiAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gImJsYWNrIiwgd2lkdGggPSBnc3cpLAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgYWRkX3RyYWNlKGRhdGEgPSBkZjMsIHggPSB+eCwgeSA9IH55LCB6ID0gfnosIG1vZGUgPSAibWFya2VycyIsIHR5cGUgPSAic2NhdHRlcjNkIiwgCiAgICAgICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IGdzdywgY29sb3IgPSAiZ3JheSIsIHN5bWJvbCA9IDEwNCkpIHw+CiAgYWRkX3RyYWNlKHggPSAwLCB5ID0gMCwgeiA9IDAsIG1vZGUgPSAibWFya2VycyIsIHR5cGUgPSAic2NhdHRlcjNkIiwgCiAgICAgICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IGdzdywgY29sb3IgPSAiYmxhY2siLCBzeW1ib2wgPSAxMDQpLAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgYWRkX3RyYWNlKHggPSAxLCB5ID0gMCwgeiA9IDAsIG1vZGUgPSAibWFya2VycyIsIHR5cGUgPSAic2NhdHRlcjNkIiwgCiAgICAgICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IGdzdywgY29sb3IgPSAiYmxhY2siLCBzeW1ib2wgPSAxMDQpLAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgbGF5b3V0KGZvbnQgPSBsaXN0KGZhbWlseSA9ICJQYWxhdGlubyIpLAogICAgICAgICBzY2VuZSA9IGModGFkcG9sZS5sYXlvdXQoeF9yYW5nZSwgeV9yYW5nZSwgel9yYW5nZSksIG5vdGVzMiksCiAgICAgICAgIG1hcmdpbiA9IGxpc3QobCA9IDAsIHIgPSAwLCBiID0gMCwgdCA9IDApLAogICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UsCiAgICAgICAgIGZvbnQgPSBsaXN0KGZhbWlseSA9ICJQYWxhdGlubyIpKQpzYXZlKHAyLCBmaWxlID0gaGVyZTo6aGVyZSgiZGF0YV9maWxlcy90YWRwb2xlX2dyYXBoX21lc2guUmRhdGEiKSkKYGBgCgoKIyMgQmFzaXMgZnVuY3Rpb25zIG9uIGEgbWV0cmljIGdyYXBoCgpMZXQgZWFjaCBlZGdlICRlXGluXEVjYWwkIGJlIHN1YmRpdmlkZWQgaW50byAkbl97ZX1cZ2VxIDIkIHJlZ3VsYXIgc2VnbWVudHMgb2YgbGVuZ3RoICRoX3tlfSQsIGFuZCBiZSBkZWxpbWl0ZWQgYnkgdGhlIG5vZGVzICQwID0geF8wXntlfSx4XzFee2V9LFxkb3RzLHhfe25fe2V9LTF9XntlfSwgeF97bl97ZX19XntlfSA9IFxlbGxfe2V9JC4gRm9yIGVhY2ggJGogPSAxLFxkb3RzLG5fe2V9LTEkLCB3ZSBjb25zaWRlciB0aGUgZm9sbG93aW5nIHN0YW5kYXJkIGhhdCBiYXNpcyBmdW5jdGlvbnMgClxiZWdpbntlcXVhdGlvbip9CiAgICBcdmFycGhpX2pee2V9KHgpPVxiZWdpbntjYXNlc30KICAgICAgICAxLVxkZnJhY3t8eF9qXntlfS14fH17aF97ZX19LCZcdGV4dHsgaWYgfXhfe2otMX1ee2V9XGxlcSB4XGxlcSB4X3tqKzF9XntlfSxcXAogICAgICAgIDAsJlx0ZXh0eyBvdGhlcndpc2V9LgogICAgXGVuZHtjYXNlc30KXGVuZHtlcXVhdGlvbip9CkZvciBlYWNoICRlXGluXEVjYWwkLCB0aGUgc2V0IG9mIGhhdCBmdW5jdGlvbnMgJFxsbGF2e1x2YXJwaGlfMV57ZX0sXGRvdHMsXHZhcnBoaV97bl97ZX0tMX1ee2V9fSQgaXMgYSBiYXNpcyBmb3IgdGhlIHNwYWNlClxiZWdpbntlcXVhdGlvbip9CiAgICBWX3toX3tlfX0gPSBcbGxhdnt3XGluIEhfMF4xKGUpXDtcQmlnfFw7XGZvcmFsbCBqID0gMCwxLFxkb3RzLG5fe2V9LTE6d3xfe1t4X2pee2V9LCB4X3tqKzF9XntlfV19XGluXG1hdGhiYntQfV4xfSwKXGVuZHtlcXVhdGlvbip9CndoZXJlICRcbWF0aGJie1B9XjEkIGlzIHRoZSBzcGFjZSBvZiBsaW5lYXIgZnVuY3Rpb25zIG9uICRbMCxcZWxsX3tlfV0kLiBGb3IgZWFjaCB2ZXJ0ZXggJHZcaW5cVmNhbCQsIHdlIGRlZmluZQpcYmVnaW57ZXF1YXRpb24qfQogICAgXE5jYWxfdiA9IFxsbGF2e1xiaWdjdXBfe2VcaW5cbGxhdntlXGluXEVjYWxfdjogdiA9IHhfMF5lfX1bdix4XzFeZV19XGJpZ2N1cFxsbGF2e1xiaWdjdXBfe2VcaW5cbGxhdntlXGluXEVjYWxfdjogdiA9IHheZV97bl9lfX19W3heZV97bl9lLTF9LHZdfSwKXGVuZHtlcXVhdGlvbip9CndoaWNoIGlzIGEgc3Rhci1zaGFwZWQgc2V0IHdpdGggY2VudGVyIGF0ICR2JCBhbmQgcmF5cyBtYWRlIG9mIHRoZSBzZWdtZW50cyBjb250aWd1b3VzIHRvICR2JC4gT24gJFxtYXRoY2Fse059X3YkLCB3ZSBkZWZpbmUgdGhlIGhhdCBmdW5jdGlvbnMgYXMKXGJlZ2lue2VxdWF0aW9uKn0KICAgIFxwaGlfdih4KT1cYmVnaW57Y2FzZXN9CiAgICAgICAgMS1cZGZyYWN7fHhfdl57ZX0teHx9e2hfe2V9fSwmXHRleHR7IGlmIH14XGluXG1hdGhjYWx7Tn1fdlxjYXAgZSBcdGV4dHsgYW5kIH1lXGluXEVjYWxfdixcXAogICAgICAgIDAsJlx0ZXh0eyBvdGhlcndpc2V9LAogICAgXGVuZHtjYXNlc30KXGVuZHtlcXVhdGlvbip9CndoZXJlICR4X3ZeZSQgaXMgZWl0aGVyICR4XzBeZSQgb3IgJHhfe25fZX1eZSQgZGVwZW5kaW5nIG9uIHRoZSBlZGdlIGRpcmVjdGlvbiBhbmQgaXRzIHBhcmFtZXRlcml6YXRpb24uIFNlZSBbQEFyaW9saTIwMThBRmluaXRlXSBmb3IgbW9yZS4gRmlndXJlIDMgYmVsb3cgcHJvdmlkZXMgYW4gaWxsdXN0cmF0aW9uIG9mIHRoZSBzeXN0ZW0gb2YgYmFzaXMgZnVuY3Rpb25zICRce1x2YXJwaGlfal5lLCBccGhpX3ZcfSQgdG9nZXRoZXIgd2l0aCB0aGUgc2V0ICRcTmNhbF92JC4KCgpgYGB7cn0Kbm90ZXMzIDwtIGxpc3QoYW5ub3RhdGlvbnMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgeCA9IDAsIHkgPSAwLCB6ID0gMSwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgiXFxwaGlfe3ZfMX0iKSwKICAgICAgICAgICAgICAgICAgICAgdGV4dGFuZ2xlID0gMCwgYXggPSAwLCBheSA9IC0xNSwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAicmVkIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAicmdiYSgwLDAsMCwwKSIpLAogICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgeCA9IDAsIHkgPSAwLCB6ID0gMCwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgiXFxtYXRoY2Fse059X3t2XzF9IiksCiAgICAgICAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMjUsIGF5ID0gNSwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiZ3JlZW4iLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJyZ2JhKDAsMCwwLDApIiksCiAgICAgICAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICAgICAgICB4ID0gMSwgeSA9IDAsIHogPSAxLAogICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gVGVYKCJcXHBoaV97dl8yfSIpLAogICAgICAgICAgICAgICAgICAgICB0ZXh0YW5nbGUgPSAwLCBheCA9IDAsIGF5ID0gLTE1LAogICAgICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChjb2xvciA9ICJyZWQiLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJyZ2JhKDAsMCwwLDApIiksCiAgICAgICAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICAgICAgICB4ID0gMCwgeSA9IDAsIHogPSAwLAogICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gVGVYKCJ2XzEiKSwKICAgICAgICAgICAgICAgICAgICAgdGV4dGFuZ2xlID0gMCwgYXggPSAwLCBheSA9IDM1LAogICAgICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChjb2xvciA9ICJibGFjayIsIHNpemUgPSBnZnNpemUpLAogICAgICAgICAgICAgICAgICAgICBhcnJvd2NvbG9yID0gImdyYXkiLCBhcnJvd3NpemUgPSAxLCBhcnJvd3dpZHRoID0gMC41LCBhcnJvd2hlYWQgPSAxKSwKICAgICAgICAgICAgICAgICAgIGxpc3QoCiAgICAgICAgICAgICAgICAgICAgIHggPSAxLCB5ID0gMCwgeiA9IDAsCiAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBUZVgoInZfMiIpLAogICAgICAgICAgICAgICAgICAgICB0ZXh0YW5nbGUgPSAwLCBheCA9IDAsIGF5ID0gMzUsCiAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAiZ3JheSIsIGFycm93c2l6ZSA9IDEsIGFycm93d2lkdGggPSAwLjUsIGFycm93aGVhZCA9IDEpLAogICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgeCA9IDEsIHkgPSAwLCB6ID0gMCwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgiXFxtYXRoY2Fse059X3t2XzJ9IiksCiAgICAgICAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gNDAsIGF5ID0gLTEwLAogICAgICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChjb2xvciA9ICJncmVlbiIsIHNpemUgPSBnZnNpemUpLAogICAgICAgICAgICAgICAgICAgICBhcnJvd2NvbG9yID0gInJnYmEoMCwwLDAsMCkiKSwKICAgICAgICAgICAgICAgICAgIGxpc3QoCiAgICAgICAgICAgICAgICAgICAgIHggPSBkZjRbNSwxXSwgeSA9IGRmNFs1LDJdLCB6ID0gMCwKICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IFRlWCgieF81XntlXzJ9IiksCiAgICAgICAgICAgICAgICAgICAgIHRleHRhbmdsZSA9IDAsIGF4ID0gMCwgYXkgPSAzNSwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gZ2ZzaXplKSwKICAgICAgICAgICAgICAgICAgICAgYXJyb3djb2xvciA9ICJncmF5IiwgYXJyb3dzaXplID0gMSwgYXJyb3d3aWR0aCA9IDAuNSwgYXJyb3doZWFkID0gMSksCiAgICAgICAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICAgICAgICB4ID0gZGY0WzUsMV0sIHkgPSBkZjRbNSwyXSwgeiA9IDEsCiAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBUZVgoIlxcdmFycGhpXzVee2VfMn0iKSwKICAgICAgICAgICAgICAgICAgICAgdGV4dGFuZ2xlID0gMCwgYXggPSAwLCBheSA9IC0xNSwKICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAicmdiKDAsMCwyMDApIiwgc2l6ZSA9IGdmc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgIGFycm93Y29sb3IgPSAicmdiYSgwLDAsMCwwKSIpKSkKCnAzIDwtIHBsb3RfbHkoCiAgI3dpZHRoID0gMTUwMCwgaGVpZ2h0ID0gMjAwMAogICAgICAgICApIHw+IAogIGNvbmZpZyhtYXRoamF4ID0gJ2NkbicpIHw+CiAgYWRkX3RyYWNlKHggPSByZXAoeCwgdGltZXMgPSBncmFwaCRuViksIAogICAgICAgICAgICB5ID0gcmVwKHksIHRpbWVzID0gZ3JhcGgkblYpLCAKICAgICAgICAgICAgeiA9IGFzLnZlY3RvcihBWywgMTpncmFwaCRuVl0pLCAKICAgICAgICAgICAgdHlwZSA9ICJzY2F0dGVyM2QiLCAKICAgICAgICAgICAgbW9kZSA9ICJsaW5lcyIsCiAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gInJlZCIsIHdpZHRoID0gZ3N3KSwgCiAgICAgICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRSkgfD4KICBhZGRfdHJhY2UoeCA9IHJlcCh4LCB0aW1lcyA9IG5jb2woQSkgLSBncmFwaCRuViksIAogICAgICAgICAgICB5ID0gcmVwKHksIHRpbWVzID0gbmNvbChBKSAtIGdyYXBoJG5WKSwgCiAgICAgICAgICAgIHogPSBhcy52ZWN0b3IoQVssIChncmFwaCRuVisxKTpuY29sKEEpXSksIAogICAgICAgICAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICAgICAgICAgIG1vZGUgPSAibGluZXMiLCAKICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAiZGFya2dyYXkiLCB3aWR0aCA9IGdzdyksIAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgYWRkX3RyYWNlKHggPSByZXAoeCwgZWFjaCA9IDMpLCAKICAgICAgICAgICAgeSA9IHJlcCh5LCBlYWNoID0gMyksIAogICAgICAgICAgICB6ID0gdW5saXN0KGxhcHBseShhcHBseShBLCAxLCBtYXgsIG5hLnJtID0gVFJVRSksIGZ1bmN0aW9uKHpqKSBjKDAsIHpqLCBOQSkpKSwKICAgICAgICAgICAgdHlwZSA9ICJzY2F0dGVyM2QiLCAKICAgICAgICAgICAgbW9kZSA9ICJsaW5lcyIsCiAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gImxpZ2h0Z3JheSIsIHdpZHRoID0gMC41KSwKICAgICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFKSB8PgogIGFkZF90cmFjZSh4ID0geCwgCiAgICAgICAgICAgIHkgPSB5LCAKICAgICAgICAgICAgeiA9IGFzLnZlY3RvcihBWywgMTBdKSwgCiAgICAgICAgICAgIHR5cGUgPSAic2NhdHRlcjNkIiwKICAgICAgICAgICAgbW9kZSA9ICJsaW5lcyIsICAKICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAicmdiKDAsMCwyMDApIiwgd2lkdGggPSBnc3cpLAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgYWRkX3RyYWNlKHggPSB4LCAKICAgICAgICAgICAgeSA9IHksIAogICAgICAgICAgICB6ID0geCowLCAKICAgICAgICAgICAgdHlwZSA9ICJzY2F0dGVyM2QiLAogICAgICAgICAgICBtb2RlID0gImxpbmVzIiwgIAogICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICJibGFjayIsIHdpZHRoID0gZ3N3KSwKICAgICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFKSB8PgogIGFkZF90cmFjZSh4ID0gcmVwKHgsIHRpbWVzID0gZ3JhcGgkblYpLCAKICAgICAgICAgICAgeSA9IHJlcCh5LCB0aW1lcyA9IGdyYXBoJG5WKSwgCiAgICAgICAgICAgIHogPSBjKHJlcGxhY2UocmVwKE5BLCBucm93KEEpKSwgMToxMSwgMCksIAogICAgICAgICAgICAgICAgICByZXBsYWNlKHJlcChOQSwgbnJvdyhBKSksIGMoMzE6NTEsIDExMToxMjEpLCAwKSksIAogICAgICAgICAgICB0eXBlID0gInNjYXR0ZXIzZCIsIAogICAgICAgICAgICBtb2RlID0gImxpbmVzIiwKICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAiZ3JlZW4iLCB3aWR0aCA9IGdzdyksIAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgYWRkX3RyYWNlKHggPSBkZjRbNSwxXSwgeSA9IGRmNFs1LDJdLCB6ID0gMCwgbW9kZSA9ICJtYXJrZXJzIiwgdHlwZSA9ICJzY2F0dGVyM2QiLCAKICAgICAgICAgICAgbWFya2VyID0gbGlzdChzaXplID0gZ3N3LCBjb2xvciA9ICJyZ2IoMCwwLDIwMCkiLCBzeW1ib2wgPSAxMDQpLAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgYWRkX3RyYWNlKHggPSAwLCB5ID0gMCwgeiA9IDAsIG1vZGUgPSAibWFya2VycyIsIHR5cGUgPSAic2NhdHRlcjNkIiwgCiAgICAgICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IGdzdywgY29sb3IgPSAiYmxhY2siLCBzeW1ib2wgPSAxMDQpLAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgYWRkX3RyYWNlKHggPSAxLCB5ID0gMCwgeiA9IDAsIG1vZGUgPSAibWFya2VycyIsIHR5cGUgPSAic2NhdHRlcjNkIiwgCiAgICAgICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IGdzdywgY29sb3IgPSAiYmxhY2siLCBzeW1ib2wgPSAxMDQpLAogICAgICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UpIHw+CiAgbGF5b3V0KGZvbnQgPSBsaXN0KGZhbWlseSA9ICJQYWxhdGlubyIpLAogICAgICAgICBzY2VuZSA9IGModGFkcG9sZS5sYXlvdXQoeF9yYW5nZSwgeV9yYW5nZSwgel9yYW5nZSksIG5vdGVzMyksCiAgICAgICAgIG1hcmdpbiA9IGxpc3QobCA9IDAsIHIgPSAwLCBiID0gMCwgdCA9IDApLAogIHBhcGVyX2JnY29sb3IgPSAid2hpdGUiLCAgIyB0aGUgb3ZlcmFsbCBjYW52YXMgYmFja2dyb3VuZAogIHBsb3RfYmdjb2xvciAgPSAid2hpdGUiLCAgICMgdGhlIGFyZWEgaW5zaWRlIGF4ZXMKICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFLAogICAgICAgICBmb250ID0gbGlzdChmYW1pbHkgPSAiUGFsYXRpbm8iKSkKc2F2ZShwMywgZmlsZSA9IGhlcmU6OmhlcmUoImRhdGFfZmlsZXMvdGFkcG9sZV9ncmFwaF9iYXNpc19mdW5jdGlvbnMuUmRhdGEiKSkKCiMgY29tYmluZV9wbG90bHlfZ3JpZF9wZGYobGlzdChwMSxwMixwMyksIG91dHB1dF9wZGYgPSBoZXJlOjpoZXJlKCJkYXRhX2ZpbGVzL3Bsb3RseXBpYy90YWRwb2xlX2dyYXBoX2Jhc2lzX2Z1bmN0aW9ucy5wZGYiKSwgbmNvbCA9IDMpCiMgY29tYmluZV9wbG90bHlfcGRmX3NpbmdsZShwMywgaGVyZTo6aGVyZSgiZGF0YV9maWxlcy9wbG90bHlwaWMvcDMucGRmIikpCmBgYAoKCgojIFBsb3RzIHBhcnQgMQoKOjo6OiB7c3R5bGU9ImRpc3BsYXk6IGdyaWQ7IGdyaWQtdGVtcGxhdGUtY29sdW1uczogNDg1cHggNDg1cHggNDg1cHg7IGdyaWQtY29sdW1uLWdhcDogMHB4OyJ9CgoKOjo6IHt9CgpgYGB7ciwgZXZhbCA9VFJVRSwgZmlnLmhlaWdodCA9IDcsIG91dC53aWR0aCA9ICIxMDAlIiwgZmlnLmNhcCA9IGNhcHRpb25lcigiSW50ZXJ2YWwgZ3JhcGggJFxcR2FtbWFfSSA9IChcXG1hdGhjYWx7Vn0sIFxcbWF0aGNhbHtFfSkkIHdpdGggJFxcbWF0aGNhbHtWfSA9IFxce3ZfMSwgdl8yXFx9JCBhbmQgJFxcbWF0aGNhbHtFfSA9IFxce2VfMVxcfSQuIil9CmxvYWQoaGVyZTo6aGVyZSgiZGF0YV9maWxlcy9pbnRlcnZhbF9ncmFwaC5SZGF0YSIpKQpwMTEKYGBgCgo6OjoKCgo6Ojoge30KCmBgYHtyLCBldmFsID1UUlVFLCBmaWcuaGVpZ2h0ID0gNywgb3V0LndpZHRoID0gIjEwMCUiLCBmaWcuY2FwID0gY2FwdGlvbmVyKCJDaXJjbGUgZ3JhcGggJFxcR2FtbWFfQyA9IChcXG1hdGhjYWx7Vn0sIFxcbWF0aGNhbHtFfSkkIHdpdGggJFxcbWF0aGNhbHtWfSA9IFxce3ZfMVxcfSQgYW5kICRcXG1hdGhjYWx7RX0gPSBcXHtlXzFcXH0kLiIpfQpsb2FkKGhlcmU6OmhlcmUoImRhdGFfZmlsZXMvY2lyY2xlX2dyYXBoLlJkYXRhIikpCnAyMgpgYGAKCgo6OjoKCgoKOjo6IHt9CgoKYGBge3IsIGV2YWwgPVRSVUUsIGZpZy5oZWlnaHQgPSA3LCBvdXQud2lkdGggPSAiMTAwJSIsIGZpZy5jYXAgPSBjYXB0aW9uZXIoIlRhZHBvbGUgZ3JhcGggJFxcR2FtbWFfVCA9IChcXG1hdGhjYWx7Vn0sIFxcbWF0aGNhbHtFfSkkIHdpdGggJFxcbWF0aGNhbHtWfSA9IFxce3ZfMSwgdl8yXFx9JCBhbmQgJFxcbWF0aGNhbHtFfSA9IFxce2VfMSxlXzJcXH0kLiIpfQpsb2FkKGhlcmU6OmhlcmUoImRhdGFfZmlsZXMvdGFkcG9sZV9ncmFwaC5SZGF0YSIpKQpwMzMKYGBgCgoKOjo6CgoKOjo6OgoKCiMgUGxvdHMgcGFydCAyCgo6Ojo6IHtzdHlsZT0iZGlzcGxheTogZ3JpZDsgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiA0ODVweCA0ODVweCA0ODVweDsgZ3JpZC1jb2x1bW4tZ2FwOiAwcHg7In0KCgo6Ojoge30KCmBgYHtyLCBldmFsID1UUlVFLCBmaWcuaGVpZ2h0ID0gNywgb3V0LndpZHRoID0gIjEwMCUiLCBmaWcuY2FwID0gY2FwdGlvbmVyKCJBIGZ1bmN0aW9uICRmPVxcZ2FtbWFcXGJpZ3xfXFxHYW1tYSQgb24gdGhlIHRhZHBvbGUgZ3JhcGgsIHdoZXJlICRcXGdhbW1hKHgseSkgPSBlXnsteF4yLXleMn0kLCB0b2dldGhlciB3aXRoIGEgcGF0aCB0aGF0IGlsbHVzdHJhdGVzIHRoZSBnZW9kZXNpYyBkaXN0YW5jZSBiZXR3ZWVuIHBvaW50cyAkc18xJCBhbmQgJHNfMiQuIil9CmxvYWQoaGVyZTo6aGVyZSgiZGF0YV9maWxlcy90YWRwb2xlX2dyYXBoX2Z1bmN0aW9uLlJkYXRhIikpCnAxCmBgYAoKOjo6CgoKOjo6IHt9CgpgYGB7ciwgZXZhbCA9VFJVRSwgZmlnLmhlaWdodCA9IDcsIG91dC53aWR0aCA9ICIxMDAlIiwgZmlnLmNhcCA9IGNhcHRpb25lcigiTWVzaCBub2RlcyBvbiB0aGUgdGFkcG9sZSBncmFwaC4iKX0KbG9hZChoZXJlOjpoZXJlKCJkYXRhX2ZpbGVzL3RhZHBvbGVfZ3JhcGhfbWVzaC5SZGF0YSIpKQpwMgpgYGAKCgo6OjoKCgoKOjo6IHt9CgoKYGBge3IsIGV2YWwgPVRSVUUsIGZpZy5oZWlnaHQgPSA3LCBvdXQud2lkdGggPSAiMTAwJSIsIGZpZy5jYXAgPSBjYXB0aW9uZXIoIkJhc2lzIGZ1bmN0aW9ucyBvbiB0aGUgdGFkcG9sZSBncmFwaC4iKX0KbG9hZChoZXJlOjpoZXJlKCJkYXRhX2ZpbGVzL3RhZHBvbGVfZ3JhcGhfYmFzaXNfZnVuY3Rpb25zLlJkYXRhIikpCnAzCmBgYAoKCjo6OgoKCjo6OjoKCgojIFBsb3RzIHBhcnQgMwoKOjo6OiB7c3R5bGU9ImRpc3BsYXk6IGdyaWQ7IGdyaWQtdGVtcGxhdGUtY29sdW1uczogNDg1cHggNDg1cHggNDg1cHg7IGdyaWQtY29sdW1uLWdhcDogMHB4OyJ9CgoKOjo6IHt9CgpgYGB7ciwgZXZhbCA9VFJVRSwgZmlnLmhlaWdodCA9IDcsIG91dC53aWR0aCA9ICIxMDAlIiwgZmlnLmNhcCA9IGNhcHRpb25lcigiSW50ZXJ2YWwgZ3JhcGggJFxcR2FtbWFfSSA9IChcXG1hdGhjYWx7Vn0sIFxcbWF0aGNhbHtFfSkkIHdpdGggJFxcbWF0aGNhbHtWfSA9IFxce3ZfMSwgdl8yXFx9JCBhbmQgJFxcbWF0aGNhbHtFfSA9IFxce2VfMVxcfSQuIil9CmxvYWQoaGVyZTo6aGVyZSgiZGF0YV9maWxlcy9pbnRlcnZhbF9ncmFwaC5SZGF0YSIpKQpwMTEKYGBgCgo6OjoKCgo6Ojoge30KCmBgYHtyLCBldmFsID1UUlVFLCBmaWcuaGVpZ2h0ID0gNywgb3V0LndpZHRoID0gIjEwMCUiLCBmaWcuY2FwID0gY2FwdGlvbmVyKCJJbnRlcnZhbCBncmFwaCAkXFxHYW1tYV9JID0gKFxcbWF0aGNhbHtWfSwgXFxtYXRoY2Fse0V9KSQgd2l0aCAkXFxtYXRoY2Fse1Z9ID0gXFx7dl8xLCB2XzJcXH0kIGFuZCAkXFxtYXRoY2Fse0V9ID0gXFx7ZV8xXFx9JCwgd2hlcmUgJGVfMSQgaXMgZmxpcHBlZC4iKX0KbG9hZChoZXJlOjpoZXJlKCJkYXRhX2ZpbGVzL2ludGVydmFsX2dyYXBoX2ZsaXBfZWRnZS5SZGF0YSIpKQpwMmludApgYGAKCgo6OjoKCgoKCjo6OjoKCgojIFJlZmVyZW5jZXMKCmBgYHtyLCBldmFsID1UUlVFfQpncmF0ZWZ1bDo6Y2l0ZV9wYWNrYWdlcyhvdXRwdXQgPSAicGFyYWdyYXBoIiwgb3V0LmRpciA9ICIuIikKYGBgCg==