rm(list=ls())
library(data.table)
library(here)
library(DiagrammeR)
library(yaml)
library(igraph)
library(ggraph)
library(ggplot2)
here::here("~/code/cadre/data-analysis-plotting/Simulated-Data-Analysis/r")
[1] "~/code/cadre/data-analysis-plotting/Simulated-Data-Analysis/r"
input_params <- read_yaml("../../../python/myparams/model_params.yaml") #input params
network_dt <- fread("../../../python/output/network_log_11.csv") #simulated network data
agent_dt <- fread("../../../python/output/agent_log_11.csv") #simulated network data
last_tick <- max(network_dt$tick)
Let’s focus on the last tick for which we have agent and network
data:
last_tick_network_dt <- network_dt[tick==last_tick,]
last_tick_agent_dt <- agent_dt[tick == last_tick,]
print(last_tick_network_dt)
print(last_tick_agent_dt)
Visualize using DiagrammeR:
# Identify the IDs of the recently released agents
recently_released_agents <- last_tick_agent_dt$id[last_tick_agent_dt$last_release_tick > (last_tick - 365)]
# Get the network data for the recently released agents
network_recently_released <- last_tick_network_dt[(last_tick_network_dt$p1 %in% recently_released_agents) |
(last_tick_network_dt$p2 %in% recently_released_agents),]
# Get the first-degree network (neighbors) for each agent
first_degree_neighbors <- unique(c(network_recently_released$p1, network_recently_released$p2))
# Get agent data for the first-degree neighbors
first_degree_neighbors_agent_data <- last_tick_agent_dt[last_tick_agent_dt$id %in% first_degree_neighbors,]
# Create an edge data frame from your network data
edf <- data.frame(from = network_recently_released$p1,
to = network_recently_released$p2)
# Create a node data frame with your agent data
ndf <- data.frame(id = first_degree_neighbors_agent_data$id,
smoking_status = first_degree_neighbors_agent_data$smoking_status,
alc_use_status = first_degree_neighbors_agent_data$alc_use_status,
recently_released = ifelse(first_degree_neighbors_agent_data$id %in% recently_released_agents, "yes", "no"))
# Create a graph with DiagrammeR
graph <- create_graph(nodes_df = ndf,
edges_df = edf,
directed = FALSE)
# Customize the node fillcolor based on smoking_status, alc_use_status and recently_released
graph <- set_node_attrs(graph, "fillcolor", ifelse(ndf$smoking_status == "Current", "red",
ifelse(ndf$alc_use_status == 3, "blue",
ifelse(ndf$recently_released == "yes", "black", "white"))))
# Customize the node color based on smoking_status, alc_use_status and recently_released
graph <- set_node_attrs(graph, "color", ifelse(ndf$smoking_status == "Current", "red",
ifelse(ndf$alc_use_status == 3, "blue",
ifelse(ndf$recently_released == "yes", "black", "gray"))))
# Customize the node shape based on recently_released
graph <- set_node_attrs(graph, "shape", ifelse(ndf$recently_released == "yes", "square", "circle"))
# Remove labels from nodes to make them stand out more
graph <- set_node_attrs(graph, "label", "")
# Customize the edge color and line type
graph <- set_edge_attrs(graph, "color", "black") # Change the edge color to gray
graph <- set_edge_attrs(graph, "style", "solid") # Change the edge line type to dashed
# Customize the edge thickness
graph <- set_edge_attrs(graph, "penwidth", 2) # Increase the edge thickness
# Customize the outline color of all nodes
graph <- set_node_attrs(graph, "color", "darkgray")
# Render the graph
render_graph(graph)
# Create a legend
legend <- rbind(data.frame(group = "Recently Released", shape = "square", color = "black"),
data.frame(group = "Currently Smoking", shape = "circle", color = "red"),
data.frame(group = "AUD", shape = "circle", color = "blue"))
Prevalence of Current Smoking and AUD among network members:
# Number of agents with Current Smoking status
num_current_smoking <- sum(first_degree_neighbors_agent_data$smoking_status == "Current")
# Number of agents with AUD
num_aud <- sum(first_degree_neighbors_agent_data$alc_use_status == 3)
# Total number of agents in the network
total_agents <- nrow(first_degree_neighbors_agent_data)
# Calculate prevalence
prevalence_smoking <- num_current_smoking / total_agents
prevalence_aud <- num_aud / total_agents
# Print the results
cat("Prevalence of Current Smoking in networks of recently released agents: ", prevalence_smoking, "\n")
Prevalence of Current Smoking in networks of recently released agents: 0.1899441
cat("Prevalence of AUD in networks of recently released agents: ", prevalence_aud, "\n")
Prevalence of AUD in networks of recently released agents: 0.0726257
Prevalence of Cyrrent Smoking and AUD among this set of egos:
# Define selected_agents_df, which contains the data for the selected agents
recently_released_agents_df <- last_tick_agent_dt[last_tick_agent_dt$id %in% recently_released_agents,]
# Number of selected agents who are current smokers
num_ego_current_smoking <- sum(recently_released_agents_df$smoking_status == "Current")
# Number of selected agents with AUD
num_ego_aud <- sum(recently_released_agents_df$alc_use_status == 3)
# Total number of selected agents
total_ego_agents <- length(recently_released_agents)
# Calculate prevalence
prevalence_ego_smoking <- num_ego_current_smoking / total_ego_agents
prevalence_ego_aud <- num_ego_aud / total_ego_agents
# Print the results
cat("Prevalence of Current Smoking among recently released agents: ", prevalence_ego_smoking, "\n")
Prevalence of Current Smoking among recently released agents: 0.1944444
cat("Prevalence of AUD among recently released agents: ", prevalence_ego_aud, "\n")
Prevalence of AUD among recently released agents: 0.1111111
# Create a legend
legend <- rbind(
data.frame(group = "Recently Released", shape = "square", color = "black"),
data.frame(group = "Recently Released & Currently Smoking", shape = "square", color = "red"),
data.frame(group = "Recently Released & AUD", shape = "square", color = "blue"),
data.frame(group = "Currently Smoking", shape = "circle", color = "red"),
data.frame(group = "AUD", shape = "circle", color = "blue")
)
# The ggplot call
p <- ggplot() +
geom_point(data = legend,
aes(x = 1, y = group, color = color, fill = color, shape = shape),
size = 5) +
geom_text(data = legend,
aes(x = 1.1, y = group, label = group),
hjust = 0) +
scale_color_identity() +
scale_fill_identity() +
scale_shape_manual(values=c("square"=22, "circle"=21)) +
theme_void() +
theme(legend.position = "none") +
coord_cartesian(xlim = c(1, 2)) # Adjust as necessary to ensure labels fit
# Print the plot
p

Alternate legend:
# Create a legend
legend <- data.frame(
group = c("Recently Released", "Network Member"),
shape = c("square", "circle"),
fillcolor = c("black", "white"),
color = c("black", "black")
)
# Map the attributes for smoking and alcohol use to the legend
smoking_legend <- data.frame(
group = c("Current Smoking"),
shape = c("circle"),
fillcolor = c("blue"),
color = c("blue")
)
alc_legend <- data.frame(
group = c("Alcohol Use Disorder"),
shape = c("circle"),
fillcolor = c("red"),
color = c("red")
)
# Combine the legend data frames
legend <- rbind(legend, smoking_legend, alc_legend)
# The ggplot call
legend_p_2 <- ggplot() +
geom_point(data = legend,
aes(x = 1, y = group, fill = fillcolor, color = color, shape = shape),
size = 5) +
geom_text(data = legend,
aes(x = 1.1, y = group, label = group),
hjust = 0) +
scale_fill_identity() +
scale_color_identity() +
scale_shape_manual(values = c("square" = 22, "circle" = 21)) +
theme_void() +
theme(
legend.position = "none") +
coord_cartesian(xlim = c(1, 2)) # Adjust as necessary to ensure labels fit
# Print the plot
legend_p_2

legend_p_2

Horizontal legend alignment:
# Create a legend
legend <- data.frame(
group = c("Recently Released", "Network Member", "Current Smoking", "Alcohol Use Disorder"),
shape = c("square", "circle", "circle", "circle"),
fillcolor = c("black", "white", "blue", "red"),
color = c("black", "black", "blue", "red")
)
# The ggplot call
horizontal_legend_p <- ggplot() +
geom_point(data = legend,
aes(x = group, y = 1, fill = fillcolor, color = color, shape = shape),
size = 5) +
geom_text(data = legend,
aes(x = group, y = 1.1, label = group),
vjust = -0.5, angle = 45, hjust = 1) +
scale_fill_identity() +
scale_color_identity() +
scale_shape_manual(values = c("square" = 22, "circle" = 21)) +
theme_void() +
theme(
legend.position = "none"
) +
coord_cartesian(ylim = c(0.8, 2)) # Adjust as necessary to ensure labels fit
# Print the plot
horizontal_legend_p

Plot AUD and Current Smking in the networks of a same number of
agents who have never been incarcerated:
# Set seed for reproducibility
set.seed(Sys.time())
# Identify the IDs of the agents who have never been incarcerated
never_incarcerated_agents <- last_tick_agent_dt$id[last_tick_agent_dt$n_incarcerations == 0]
# Randomly select 36 agents who have never been incarcerated
selected_agents <- sample(never_incarcerated_agents,
size = length(recently_released_agents))
# Get the network data for the selected agents
network_selected_agents <- last_tick_network_dt[(last_tick_network_dt$p1 %in% selected_agents) |
(last_tick_network_dt$p2 %in% selected_agents),]
# Get the first-degree network (neighbors) for each agent
first_degree_neighbors <- unique(c(network_selected_agents$p1, network_selected_agents$p2))
# Get agent data for the first-degree neighbors
first_degree_neighbors_agent_data <- last_tick_agent_dt[last_tick_agent_dt$id %in% first_degree_neighbors,]
# Create an edge data frame from your network data
edf <- data.frame(from = network_selected_agents$p1,
to = network_selected_agents$p2)
# Create a node data frame with your agent data
ndf <- data.frame(id = first_degree_neighbors_agent_data$id,
smoking_status = first_degree_neighbors_agent_data$smoking_status,
alc_use_status = first_degree_neighbors_agent_data$alc_use_status)
# Create a graph with DiagrammeR
graph <- create_graph(nodes_df = ndf,
edges_df = edf,
directed = FALSE)
# Customize the node fillcolor based on smoking_status and alc_use_status
graph <- set_node_attrs(graph, "fillcolor", ifelse(ndf$smoking_status == "Current", "red",
ifelse(ndf$alc_use_status == 3, "blue", "white")))
# Customize the node color based on smoking_status and alc_use_status
graph <- set_node_attrs(graph, "color", ifelse(ndf$smoking_status == "Current", "red",
ifelse(ndf$alc_use_status == 3, "blue", "gray")))
# Remove labels from nodes to make them stand out more
graph <- set_node_attrs(graph, "label", "")
# Render the graph
render_graph(graph)
NA
Numerical prevalence of AUD and Current Smoking in this network:
# Number of agents with Current Smoking status
num_current_smoking <- sum(first_degree_neighbors_agent_data$smoking_status == "Current")
# Number of agents with AUD
num_aud <- sum(first_degree_neighbors_agent_data$alc_use_status == 3)
# Total number of agents in the network
total_agents <- nrow(first_degree_neighbors_agent_data)
# Calculate prevalence
prevalence_smoking <- num_current_smoking / total_agents
prevalence_aud <- num_aud / total_agents
# Print the results
cat("Prevalence of Current Smoking in the networks of randomly
selected never incarcerated persons: ", prevalence_smoking, "\n")
Prevalence of Current Smoking in the networks of randomly
selected never incarcerated persons: 0.1414141
cat("Prevalence of AUD in the networks of randomly
selected never incarcerated persons: ", prevalence_aud, "\n")
Prevalence of AUD in the networks of randomly
selected never incarcerated persons: 0.07575758
Smoking and AUD among the egos:
# Define selected_agents_df, which contains the data for the selected agents
selected_agents_df <- last_tick_agent_dt[last_tick_agent_dt$id %in% selected_agents,]
# Number of selected agents who are current smokers
num_ego_current_smoking <- sum(selected_agents_df$smoking_status == "Current")
# Number of selected agents with AUD
num_ego_aud <- sum(selected_agents_df$alc_use_status == 3)
# Total number of selected agents
total_ego_agents <- length(selected_agents)
# Calculate prevalence
prevalence_ego_smoking <- num_ego_current_smoking / total_ego_agents
prevalence_ego_aud <- num_ego_aud / total_ego_agents
# Print the results
cat("Prevalence of Current Smoking among selected agents: ", prevalence_ego_smoking, "\n")
Prevalence of Current Smoking among selected agents: 0.1111111
cat("Prevalence of AUD among selected agents: ", prevalence_ego_aud, "\n")
Prevalence of AUD among selected agents: 0.08333333
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CnJtKGxpc3Q9bHMoKSkKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoRGlhZ3JhbW1lUikKbGlicmFyeSh5YW1sKQpsaWJyYXJ5KGlncmFwaCkKbGlicmFyeShnZ3JhcGgpCmxpYnJhcnkoZ2dwbG90MikKaGVyZTo6aGVyZSgifi9jb2RlL2NhZHJlL2RhdGEtYW5hbHlzaXMtcGxvdHRpbmcvU2ltdWxhdGVkLURhdGEtQW5hbHlzaXMvciIpCmBgYAoKYGBge3J9CmlucHV0X3BhcmFtcyA8LSByZWFkX3lhbWwoIi4uLy4uLy4uL3B5dGhvbi9teXBhcmFtcy9tb2RlbF9wYXJhbXMueWFtbCIpICNpbnB1dCBwYXJhbXMKbmV0d29ya19kdCA8LSBmcmVhZCgiLi4vLi4vLi4vcHl0aG9uL291dHB1dC9uZXR3b3JrX2xvZ18xMS5jc3YiKSAjc2ltdWxhdGVkIG5ldHdvcmsgZGF0YQphZ2VudF9kdCA8LSBmcmVhZCgiLi4vLi4vLi4vcHl0aG9uL291dHB1dC9hZ2VudF9sb2dfMTEuY3N2IikgI3NpbXVsYXRlZCBuZXR3b3JrIGRhdGEKbGFzdF90aWNrIDwtIG1heChuZXR3b3JrX2R0JHRpY2spIApgYGAKIAoKTGV0J3MgZm9jdXMgb24gdGhlIGxhc3QgdGljayBmb3Igd2hpY2ggd2UgaGF2ZSBhZ2VudCBhbmQgbmV0d29yayBkYXRhOgoKYGBge3J9Cmxhc3RfdGlja19uZXR3b3JrX2R0IDwtIG5ldHdvcmtfZHRbdGljaz09bGFzdF90aWNrLF0KbGFzdF90aWNrX2FnZW50X2R0IDwtIGFnZW50X2R0W3RpY2sgPT0gbGFzdF90aWNrLF0KcHJpbnQobGFzdF90aWNrX25ldHdvcmtfZHQpCnByaW50KGxhc3RfdGlja19hZ2VudF9kdCkKYGBgCgpWaXN1YWxpemUgdXNpbmcgYERpYWdyYW1tZVJgOgoKCmBgYHtyfQojIElkZW50aWZ5IHRoZSBJRHMgb2YgdGhlIHJlY2VudGx5IHJlbGVhc2VkIGFnZW50cwpyZWNlbnRseV9yZWxlYXNlZF9hZ2VudHMgPC0gbGFzdF90aWNrX2FnZW50X2R0JGlkW2xhc3RfdGlja19hZ2VudF9kdCRsYXN0X3JlbGVhc2VfdGljayA+IChsYXN0X3RpY2sgLSAzNjUpXQoKIyBHZXQgdGhlIG5ldHdvcmsgZGF0YSBmb3IgdGhlIHJlY2VudGx5IHJlbGVhc2VkIGFnZW50cwpuZXR3b3JrX3JlY2VudGx5X3JlbGVhc2VkIDwtIGxhc3RfdGlja19uZXR3b3JrX2R0WyhsYXN0X3RpY2tfbmV0d29ya19kdCRwMSAlaW4lIHJlY2VudGx5X3JlbGVhc2VkX2FnZW50cykgfCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChsYXN0X3RpY2tfbmV0d29ya19kdCRwMiAlaW4lIHJlY2VudGx5X3JlbGVhc2VkX2FnZW50cyksXQoKIyBHZXQgdGhlIGZpcnN0LWRlZ3JlZSBuZXR3b3JrIChuZWlnaGJvcnMpIGZvciBlYWNoIGFnZW50CmZpcnN0X2RlZ3JlZV9uZWlnaGJvcnMgPC0gdW5pcXVlKGMobmV0d29ya19yZWNlbnRseV9yZWxlYXNlZCRwMSwgbmV0d29ya19yZWNlbnRseV9yZWxlYXNlZCRwMikpCgojIEdldCBhZ2VudCBkYXRhIGZvciB0aGUgZmlyc3QtZGVncmVlIG5laWdoYm9ycwpmaXJzdF9kZWdyZWVfbmVpZ2hib3JzX2FnZW50X2RhdGEgPC0gbGFzdF90aWNrX2FnZW50X2R0W2xhc3RfdGlja19hZ2VudF9kdCRpZCAlaW4lIGZpcnN0X2RlZ3JlZV9uZWlnaGJvcnMsXQoKIyBDcmVhdGUgYW4gZWRnZSBkYXRhIGZyYW1lIGZyb20geW91ciBuZXR3b3JrIGRhdGEKZWRmIDwtIGRhdGEuZnJhbWUoZnJvbSA9IG5ldHdvcmtfcmVjZW50bHlfcmVsZWFzZWQkcDEsIAogICAgICAgICAgICAgICAgICB0byA9IG5ldHdvcmtfcmVjZW50bHlfcmVsZWFzZWQkcDIpCgojIENyZWF0ZSBhIG5vZGUgZGF0YSBmcmFtZSB3aXRoIHlvdXIgYWdlbnQgZGF0YQpuZGYgPC0gZGF0YS5mcmFtZShpZCA9IGZpcnN0X2RlZ3JlZV9uZWlnaGJvcnNfYWdlbnRfZGF0YSRpZCwgCiAgICAgICAgICAgICAgICAgIHNtb2tpbmdfc3RhdHVzID0gZmlyc3RfZGVncmVlX25laWdoYm9yc19hZ2VudF9kYXRhJHNtb2tpbmdfc3RhdHVzLAogICAgICAgICAgICAgICAgICBhbGNfdXNlX3N0YXR1cyA9IGZpcnN0X2RlZ3JlZV9uZWlnaGJvcnNfYWdlbnRfZGF0YSRhbGNfdXNlX3N0YXR1cywKICAgICAgICAgICAgICAgICAgcmVjZW50bHlfcmVsZWFzZWQgPSBpZmVsc2UoZmlyc3RfZGVncmVlX25laWdoYm9yc19hZ2VudF9kYXRhJGlkICVpbiUgcmVjZW50bHlfcmVsZWFzZWRfYWdlbnRzLCAieWVzIiwgIm5vIikpCgojIENyZWF0ZSBhIGdyYXBoIHdpdGggRGlhZ3JhbW1lUgpncmFwaCA8LSBjcmVhdGVfZ3JhcGgobm9kZXNfZGYgPSBuZGYsIAogICAgICAgICAgICAgICAgICAgICAgZWRnZXNfZGYgPSBlZGYsCiAgICAgICAgICAgICAgICAgICAgICBkaXJlY3RlZCA9IEZBTFNFKQoKIyBDdXN0b21pemUgdGhlIG5vZGUgZmlsbGNvbG9yIGJhc2VkIG9uIHNtb2tpbmdfc3RhdHVzLCBhbGNfdXNlX3N0YXR1cyBhbmQgcmVjZW50bHlfcmVsZWFzZWQKZ3JhcGggPC0gc2V0X25vZGVfYXR0cnMoZ3JhcGgsICJmaWxsY29sb3IiLCBpZmVsc2UobmRmJHNtb2tpbmdfc3RhdHVzID09ICJDdXJyZW50IiwgInJlZCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UobmRmJGFsY191c2Vfc3RhdHVzID09IDMsICJibHVlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UobmRmJHJlY2VudGx5X3JlbGVhc2VkID09ICJ5ZXMiLCAiYmxhY2siLCAid2hpdGUiKSkpKQoKIyBDdXN0b21pemUgdGhlIG5vZGUgY29sb3IgYmFzZWQgb24gc21va2luZ19zdGF0dXMsIGFsY191c2Vfc3RhdHVzIGFuZCByZWNlbnRseV9yZWxlYXNlZApncmFwaCA8LSBzZXRfbm9kZV9hdHRycyhncmFwaCwgImNvbG9yIiwgaWZlbHNlKG5kZiRzbW9raW5nX3N0YXR1cyA9PSAiQ3VycmVudCIsICJyZWQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UobmRmJGFsY191c2Vfc3RhdHVzID09IDMsICJibHVlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShuZGYkcmVjZW50bHlfcmVsZWFzZWQgPT0gInllcyIsICJibGFjayIsICJncmF5IikpKSkKCiMgQ3VzdG9taXplIHRoZSBub2RlIHNoYXBlIGJhc2VkIG9uIHJlY2VudGx5X3JlbGVhc2VkCmdyYXBoIDwtIHNldF9ub2RlX2F0dHJzKGdyYXBoLCAic2hhcGUiLCBpZmVsc2UobmRmJHJlY2VudGx5X3JlbGVhc2VkID09ICJ5ZXMiLCAic3F1YXJlIiwgImNpcmNsZSIpKQoKIyBSZW1vdmUgbGFiZWxzIGZyb20gbm9kZXMgdG8gbWFrZSB0aGVtIHN0YW5kIG91dCBtb3JlCmdyYXBoIDwtIHNldF9ub2RlX2F0dHJzKGdyYXBoLCAibGFiZWwiLCAiIikKCiMgQ3VzdG9taXplIHRoZSBlZGdlIGNvbG9yIGFuZCBsaW5lIHR5cGUKZ3JhcGggPC0gc2V0X2VkZ2VfYXR0cnMoZ3JhcGgsICJjb2xvciIsICJibGFjayIpICAjIENoYW5nZSB0aGUgZWRnZSBjb2xvciB0byBncmF5CmdyYXBoIDwtIHNldF9lZGdlX2F0dHJzKGdyYXBoLCAic3R5bGUiLCAic29saWQiKSAgIyBDaGFuZ2UgdGhlIGVkZ2UgbGluZSB0eXBlIHRvIGRhc2hlZAoKIyBDdXN0b21pemUgdGhlIGVkZ2UgdGhpY2tuZXNzCmdyYXBoIDwtIHNldF9lZGdlX2F0dHJzKGdyYXBoLCAicGVud2lkdGgiLCAyKSAgIyBJbmNyZWFzZSB0aGUgZWRnZSB0aGlja25lc3MKCiMgQ3VzdG9taXplIHRoZSBvdXRsaW5lIGNvbG9yIG9mIGFsbCBub2RlcwpncmFwaCA8LSBzZXRfbm9kZV9hdHRycyhncmFwaCwgImNvbG9yIiwgImRhcmtncmF5IikgCgojIFJlbmRlciB0aGUgZ3JhcGgKcmVuZGVyX2dyYXBoKGdyYXBoKQoKIyBDcmVhdGUgYSBsZWdlbmQKbGVnZW5kIDwtIHJiaW5kKGRhdGEuZnJhbWUoZ3JvdXAgPSAiUmVjZW50bHkgUmVsZWFzZWQiLCBzaGFwZSA9ICJzcXVhcmUiLCBjb2xvciA9ICJibGFjayIpLAogICAgICAgICAgICAgICAgZGF0YS5mcmFtZShncm91cCA9ICJDdXJyZW50bHkgU21va2luZyIsIHNoYXBlID0gImNpcmNsZSIsIGNvbG9yID0gInJlZCIpLAogICAgICAgICAgICAgICAgZGF0YS5mcmFtZShncm91cCA9ICJBVUQiLCBzaGFwZSA9ICJjaXJjbGUiLCBjb2xvciA9ICJibHVlIikpCgpgYGAKClByZXZhbGVuY2Ugb2YgQ3VycmVudCBTbW9raW5nIGFuZCBBVUQgYW1vbmcgbmV0d29yayBtZW1iZXJzOgoKYGBge3J9CiMgTnVtYmVyIG9mIGFnZW50cyB3aXRoIEN1cnJlbnQgU21va2luZyBzdGF0dXMKbnVtX2N1cnJlbnRfc21va2luZyA8LSBzdW0oZmlyc3RfZGVncmVlX25laWdoYm9yc19hZ2VudF9kYXRhJHNtb2tpbmdfc3RhdHVzID09ICJDdXJyZW50IikKCiMgTnVtYmVyIG9mIGFnZW50cyB3aXRoIEFVRApudW1fYXVkIDwtIHN1bShmaXJzdF9kZWdyZWVfbmVpZ2hib3JzX2FnZW50X2RhdGEkYWxjX3VzZV9zdGF0dXMgPT0gMykKCiMgVG90YWwgbnVtYmVyIG9mIGFnZW50cyBpbiB0aGUgbmV0d29yawp0b3RhbF9hZ2VudHMgPC0gbnJvdyhmaXJzdF9kZWdyZWVfbmVpZ2hib3JzX2FnZW50X2RhdGEpCgojIENhbGN1bGF0ZSBwcmV2YWxlbmNlCnByZXZhbGVuY2Vfc21va2luZyA8LSBudW1fY3VycmVudF9zbW9raW5nIC8gdG90YWxfYWdlbnRzCnByZXZhbGVuY2VfYXVkIDwtIG51bV9hdWQgLyB0b3RhbF9hZ2VudHMKCiMgUHJpbnQgdGhlIHJlc3VsdHMKY2F0KCJQcmV2YWxlbmNlIG9mIEN1cnJlbnQgU21va2luZyBpbiBuZXR3b3JrcyBvZiByZWNlbnRseSByZWxlYXNlZCBhZ2VudHM6ICIsIHByZXZhbGVuY2Vfc21va2luZywgIlxuIikKY2F0KCJQcmV2YWxlbmNlIG9mIEFVRCBpbiBuZXR3b3JrcyBvZiByZWNlbnRseSByZWxlYXNlZCBhZ2VudHM6ICIsIHByZXZhbGVuY2VfYXVkLCAiXG4iKQoKYGBgCgpQcmV2YWxlbmNlIG9mIEN5cnJlbnQgU21va2luZyBhbmQgQVVEIGFtb25nIHRoaXMgc2V0IG9mIGVnb3M6CgpgYGB7cn0KIyBEZWZpbmUgc2VsZWN0ZWRfYWdlbnRzX2RmLCB3aGljaCBjb250YWlucyB0aGUgZGF0YSBmb3IgdGhlIHNlbGVjdGVkIGFnZW50cwpyZWNlbnRseV9yZWxlYXNlZF9hZ2VudHNfZGYgPC0gbGFzdF90aWNrX2FnZW50X2R0W2xhc3RfdGlja19hZ2VudF9kdCRpZCAlaW4lIHJlY2VudGx5X3JlbGVhc2VkX2FnZW50cyxdCgojIE51bWJlciBvZiBzZWxlY3RlZCBhZ2VudHMgd2hvIGFyZSBjdXJyZW50IHNtb2tlcnMKbnVtX2Vnb19jdXJyZW50X3Ntb2tpbmcgPC0gc3VtKHJlY2VudGx5X3JlbGVhc2VkX2FnZW50c19kZiRzbW9raW5nX3N0YXR1cyA9PSAiQ3VycmVudCIpCgojIE51bWJlciBvZiBzZWxlY3RlZCBhZ2VudHMgd2l0aCBBVUQKbnVtX2Vnb19hdWQgPC0gc3VtKHJlY2VudGx5X3JlbGVhc2VkX2FnZW50c19kZiRhbGNfdXNlX3N0YXR1cyA9PSAzKQoKIyBUb3RhbCBudW1iZXIgb2Ygc2VsZWN0ZWQgYWdlbnRzCnRvdGFsX2Vnb19hZ2VudHMgPC0gbGVuZ3RoKHJlY2VudGx5X3JlbGVhc2VkX2FnZW50cykKCiMgQ2FsY3VsYXRlIHByZXZhbGVuY2UKcHJldmFsZW5jZV9lZ29fc21va2luZyA8LSBudW1fZWdvX2N1cnJlbnRfc21va2luZyAvIHRvdGFsX2Vnb19hZ2VudHMKcHJldmFsZW5jZV9lZ29fYXVkIDwtIG51bV9lZ29fYXVkIC8gdG90YWxfZWdvX2FnZW50cwoKIyBQcmludCB0aGUgcmVzdWx0cwpjYXQoIlByZXZhbGVuY2Ugb2YgQ3VycmVudCBTbW9raW5nIGFtb25nIHJlY2VudGx5IHJlbGVhc2VkIGFnZW50czogIiwgcHJldmFsZW5jZV9lZ29fc21va2luZywgIlxuIikKY2F0KCJQcmV2YWxlbmNlIG9mIEFVRCBhbW9uZyByZWNlbnRseSByZWxlYXNlZCBhZ2VudHM6ICIsIHByZXZhbGVuY2VfZWdvX2F1ZCwgIlxuIikKCmBgYAoKCmBgYHtyfQojIENyZWF0ZSBhIGxlZ2VuZApsZWdlbmQgPC0gcmJpbmQoCiAgZGF0YS5mcmFtZShncm91cCA9ICJSZWNlbnRseSBSZWxlYXNlZCIsIHNoYXBlID0gInNxdWFyZSIsIGNvbG9yID0gImJsYWNrIiksCiAgZGF0YS5mcmFtZShncm91cCA9ICJSZWNlbnRseSBSZWxlYXNlZCAmIEN1cnJlbnRseSBTbW9raW5nIiwgc2hhcGUgPSAic3F1YXJlIiwgY29sb3IgPSAicmVkIiksCiAgZGF0YS5mcmFtZShncm91cCA9ICJSZWNlbnRseSBSZWxlYXNlZCAmIEFVRCIsIHNoYXBlID0gInNxdWFyZSIsIGNvbG9yID0gImJsdWUiKSwKICBkYXRhLmZyYW1lKGdyb3VwID0gIkN1cnJlbnRseSBTbW9raW5nIiwgc2hhcGUgPSAiY2lyY2xlIiwgY29sb3IgPSAicmVkIiksCiAgZGF0YS5mcmFtZShncm91cCA9ICJBVUQiLCBzaGFwZSA9ICJjaXJjbGUiLCBjb2xvciA9ICJibHVlIikKKQoKCiMgVGhlIGdncGxvdCBjYWxsCnAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGxlZ2VuZCwgCiAgICAgICAgICAgICBhZXMoeCA9IDEsIHkgPSBncm91cCwgY29sb3IgPSBjb2xvciwgZmlsbCA9IGNvbG9yLCBzaGFwZSA9IHNoYXBlKSwgCiAgICAgICAgICAgICBzaXplID0gNSkgKwogIGdlb21fdGV4dChkYXRhID0gbGVnZW5kLCAKICAgICAgICAgICAgYWVzKHggPSAxLjEsIHkgPSBncm91cCwgbGFiZWwgPSBncm91cCksIAogICAgICAgICAgICBoanVzdCA9IDApICsKICBzY2FsZV9jb2xvcl9pZGVudGl0eSgpICsKICBzY2FsZV9maWxsX2lkZW50aXR5KCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9Yygic3F1YXJlIj0yMiwgImNpcmNsZSI9MjEpKSArCiAgdGhlbWVfdm9pZCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMSwgMikpICAjIEFkanVzdCBhcyBuZWNlc3NhcnkgdG8gZW5zdXJlIGxhYmVscyBmaXQKCiMgUHJpbnQgdGhlIHBsb3QKcAoKYGBgCgpBbHRlcm5hdGUgbGVnZW5kOgoKYGBge3J9CiMgQ3JlYXRlIGEgbGVnZW5kCmxlZ2VuZCA8LSBkYXRhLmZyYW1lKAogIGdyb3VwID0gYygiUmVjZW50bHkgUmVsZWFzZWQiLCAiTmV0d29yayBNZW1iZXIiKSwKICBzaGFwZSA9IGMoInNxdWFyZSIsICJjaXJjbGUiKSwKICBmaWxsY29sb3IgPSBjKCJibGFjayIsICJ3aGl0ZSIpLAogIGNvbG9yID0gYygiYmxhY2siLCAiYmxhY2siKQopCgojIE1hcCB0aGUgYXR0cmlidXRlcyBmb3Igc21va2luZyBhbmQgYWxjb2hvbCB1c2UgdG8gdGhlIGxlZ2VuZApzbW9raW5nX2xlZ2VuZCA8LSBkYXRhLmZyYW1lKAogIGdyb3VwID0gYygiQ3VycmVudCBTbW9raW5nIiksCiAgc2hhcGUgPSBjKCJjaXJjbGUiKSwKICBmaWxsY29sb3IgPSBjKCJibHVlIiksCiAgY29sb3IgPSBjKCJibHVlIikKKQoKYWxjX2xlZ2VuZCA8LSBkYXRhLmZyYW1lKAogIGdyb3VwID0gYygiQWxjb2hvbCBVc2UgRGlzb3JkZXIiKSwKICBzaGFwZSA9IGMoImNpcmNsZSIpLAogIGZpbGxjb2xvciA9IGMoInJlZCIpLAogIGNvbG9yID0gYygicmVkIikKKQoKIyBDb21iaW5lIHRoZSBsZWdlbmQgZGF0YSBmcmFtZXMKbGVnZW5kIDwtIHJiaW5kKGxlZ2VuZCwgc21va2luZ19sZWdlbmQsIGFsY19sZWdlbmQpCgojIFRoZSBnZ3Bsb3QgY2FsbApsZWdlbmRfcF8yIDwtIGdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSBsZWdlbmQsIAogICAgICAgICAgICAgYWVzKHggPSAxLCB5ID0gZ3JvdXAsIGZpbGwgPSBmaWxsY29sb3IsIGNvbG9yID0gY29sb3IsIHNoYXBlID0gc2hhcGUpLCAKICAgICAgICAgICAgIHNpemUgPSA1KSArCiAgZ2VvbV90ZXh0KGRhdGEgPSBsZWdlbmQsIAogICAgICAgICAgICBhZXMoeCA9IDEuMSwgeSA9IGdyb3VwLCBsYWJlbCA9IGdyb3VwKSwgCiAgICAgICAgICAgIGhqdXN0ID0gMCkgKwogIHNjYWxlX2ZpbGxfaWRlbnRpdHkoKSArCiAgc2NhbGVfY29sb3JfaWRlbnRpdHkoKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoInNxdWFyZSIgPSAyMiwgImNpcmNsZSIgPSAyMSkpICsKICB0aGVtZV92b2lkKCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDEsIDIpKSAgIyBBZGp1c3QgYXMgbmVjZXNzYXJ5IHRvIGVuc3VyZSBsYWJlbHMgZml0CgojIFByaW50IHRoZSBwbG90CmxlZ2VuZF9wXzIKCmBgYAoKYGBge3J9CmxlZ2VuZF9wXzIKYGBgCgpIb3Jpem9udGFsIGxlZ2VuZCBhbGlnbm1lbnQ6CgpgYGB7cn0KIyBDcmVhdGUgYSBsZWdlbmQKbGVnZW5kIDwtIGRhdGEuZnJhbWUoCiAgZ3JvdXAgPSBjKCJSZWNlbnRseSBSZWxlYXNlZCIsICJOZXR3b3JrIE1lbWJlciIsICJDdXJyZW50IFNtb2tpbmciLCAiQWxjb2hvbCBVc2UgRGlzb3JkZXIiKSwKICBzaGFwZSA9IGMoInNxdWFyZSIsICJjaXJjbGUiLCAiY2lyY2xlIiwgImNpcmNsZSIpLAogIGZpbGxjb2xvciA9IGMoImJsYWNrIiwgIndoaXRlIiwgImJsdWUiLCAicmVkIiksCiAgY29sb3IgPSBjKCJibGFjayIsICJibGFjayIsICJibHVlIiwgInJlZCIpCikKCiMgVGhlIGdncGxvdCBjYWxsCmhvcml6b250YWxfbGVnZW5kX3AgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGxlZ2VuZCwgCiAgICAgICAgICAgICBhZXMoeCA9IGdyb3VwLCB5ID0gMSwgZmlsbCA9IGZpbGxjb2xvciwgY29sb3IgPSBjb2xvciwgc2hhcGUgPSBzaGFwZSksIAogICAgICAgICAgICAgc2l6ZSA9IDUpICsKICBnZW9tX3RleHQoZGF0YSA9IGxlZ2VuZCwgCiAgICAgICAgICAgIGFlcyh4ID0gZ3JvdXAsIHkgPSAxLjEsIGxhYmVsID0gZ3JvdXApLCAKICAgICAgICAgICAgdmp1c3QgPSAtMC41LCBhbmdsZSA9IDQ1LCBoanVzdCA9IDEpICsKICBzY2FsZV9maWxsX2lkZW50aXR5KCkgKwogIHNjYWxlX2NvbG9yX2lkZW50aXR5KCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKCJzcXVhcmUiID0gMjIsICJjaXJjbGUiID0gMjEpKSArCiAgdGhlbWVfdm9pZCgpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIgogICkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLjgsIDIpKSAgIyBBZGp1c3QgYXMgbmVjZXNzYXJ5IHRvIGVuc3VyZSBsYWJlbHMgZml0CgojIFByaW50IHRoZSBwbG90Cmhvcml6b250YWxfbGVnZW5kX3AKCmBgYAoKUGxvdCBBVUQgYW5kIEN1cnJlbnQgU21raW5nIGluIHRoZSBuZXR3b3JrcyBvZiBhIHNhbWUgbnVtYmVyIG9mIGFnZW50cyB3aG8gaGF2ZSBuZXZlciBiZWVuIGluY2FyY2VyYXRlZDoKCmBgYHtyfQojIFNldCBzZWVkIGZvciByZXByb2R1Y2liaWxpdHkKc2V0LnNlZWQoU3lzLnRpbWUoKSkKCiMgSWRlbnRpZnkgdGhlIElEcyBvZiB0aGUgYWdlbnRzIHdobyBoYXZlIG5ldmVyIGJlZW4gaW5jYXJjZXJhdGVkCm5ldmVyX2luY2FyY2VyYXRlZF9hZ2VudHMgPC0gbGFzdF90aWNrX2FnZW50X2R0JGlkW2xhc3RfdGlja19hZ2VudF9kdCRuX2luY2FyY2VyYXRpb25zID09IDBdCgojIFJhbmRvbWx5IHNlbGVjdCAzNiBhZ2VudHMgd2hvIGhhdmUgbmV2ZXIgYmVlbiBpbmNhcmNlcmF0ZWQKc2VsZWN0ZWRfYWdlbnRzIDwtIHNhbXBsZShuZXZlcl9pbmNhcmNlcmF0ZWRfYWdlbnRzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gbGVuZ3RoKHJlY2VudGx5X3JlbGVhc2VkX2FnZW50cykpCgojIEdldCB0aGUgbmV0d29yayBkYXRhIGZvciB0aGUgc2VsZWN0ZWQgYWdlbnRzCm5ldHdvcmtfc2VsZWN0ZWRfYWdlbnRzIDwtIGxhc3RfdGlja19uZXR3b3JrX2R0WyhsYXN0X3RpY2tfbmV0d29ya19kdCRwMSAlaW4lIHNlbGVjdGVkX2FnZW50cykgfCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGxhc3RfdGlja19uZXR3b3JrX2R0JHAyICVpbiUgc2VsZWN0ZWRfYWdlbnRzKSxdCgojIEdldCB0aGUgZmlyc3QtZGVncmVlIG5ldHdvcmsgKG5laWdoYm9ycykgZm9yIGVhY2ggYWdlbnQKZmlyc3RfZGVncmVlX25laWdoYm9ycyA8LSB1bmlxdWUoYyhuZXR3b3JrX3NlbGVjdGVkX2FnZW50cyRwMSwgbmV0d29ya19zZWxlY3RlZF9hZ2VudHMkcDIpKQoKIyBHZXQgYWdlbnQgZGF0YSBmb3IgdGhlIGZpcnN0LWRlZ3JlZSBuZWlnaGJvcnMKZmlyc3RfZGVncmVlX25laWdoYm9yc19hZ2VudF9kYXRhIDwtIGxhc3RfdGlja19hZ2VudF9kdFtsYXN0X3RpY2tfYWdlbnRfZHQkaWQgJWluJSBmaXJzdF9kZWdyZWVfbmVpZ2hib3JzLF0KCiMgQ3JlYXRlIGFuIGVkZ2UgZGF0YSBmcmFtZSBmcm9tIHlvdXIgbmV0d29yayBkYXRhCmVkZiA8LSBkYXRhLmZyYW1lKGZyb20gPSBuZXR3b3JrX3NlbGVjdGVkX2FnZW50cyRwMSwgCiAgICAgICAgICAgICAgICAgIHRvID0gbmV0d29ya19zZWxlY3RlZF9hZ2VudHMkcDIpCgojIENyZWF0ZSBhIG5vZGUgZGF0YSBmcmFtZSB3aXRoIHlvdXIgYWdlbnQgZGF0YQpuZGYgPC0gZGF0YS5mcmFtZShpZCA9IGZpcnN0X2RlZ3JlZV9uZWlnaGJvcnNfYWdlbnRfZGF0YSRpZCwgCiAgICAgICAgICAgICAgICAgIHNtb2tpbmdfc3RhdHVzID0gZmlyc3RfZGVncmVlX25laWdoYm9yc19hZ2VudF9kYXRhJHNtb2tpbmdfc3RhdHVzLAogICAgICAgICAgICAgICAgICBhbGNfdXNlX3N0YXR1cyA9IGZpcnN0X2RlZ3JlZV9uZWlnaGJvcnNfYWdlbnRfZGF0YSRhbGNfdXNlX3N0YXR1cykKCiMgQ3JlYXRlIGEgZ3JhcGggd2l0aCBEaWFncmFtbWVSCmdyYXBoIDwtIGNyZWF0ZV9ncmFwaChub2Rlc19kZiA9IG5kZiwgCiAgICAgICAgICAgICAgICAgICAgICBlZGdlc19kZiA9IGVkZiwKICAgICAgICAgICAgICAgICAgICAgIGRpcmVjdGVkID0gRkFMU0UpCgojIEN1c3RvbWl6ZSB0aGUgbm9kZSBmaWxsY29sb3IgYmFzZWQgb24gc21va2luZ19zdGF0dXMgYW5kIGFsY191c2Vfc3RhdHVzCmdyYXBoIDwtIHNldF9ub2RlX2F0dHJzKGdyYXBoLCAiZmlsbGNvbG9yIiwgaWZlbHNlKG5kZiRzbW9raW5nX3N0YXR1cyA9PSAiQ3VycmVudCIsICJyZWQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKG5kZiRhbGNfdXNlX3N0YXR1cyA9PSAzLCAiYmx1ZSIsICJ3aGl0ZSIpKSkKCiMgQ3VzdG9taXplIHRoZSBub2RlIGNvbG9yIGJhc2VkIG9uIHNtb2tpbmdfc3RhdHVzIGFuZCBhbGNfdXNlX3N0YXR1cwpncmFwaCA8LSBzZXRfbm9kZV9hdHRycyhncmFwaCwgImNvbG9yIiwgaWZlbHNlKG5kZiRzbW9raW5nX3N0YXR1cyA9PSAiQ3VycmVudCIsICJyZWQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UobmRmJGFsY191c2Vfc3RhdHVzID09IDMsICJibHVlIiwgImdyYXkiKSkpCgojIFJlbW92ZSBsYWJlbHMgZnJvbSBub2RlcyB0byBtYWtlIHRoZW0gc3RhbmQgb3V0IG1vcmUKZ3JhcGggPC0gc2V0X25vZGVfYXR0cnMoZ3JhcGgsICJsYWJlbCIsICIiKQoKIyBSZW5kZXIgdGhlIGdyYXBoCnJlbmRlcl9ncmFwaChncmFwaCkKCmBgYAoKTnVtZXJpY2FsIHByZXZhbGVuY2Ugb2YgQVVEIGFuZCBDdXJyZW50IFNtb2tpbmcgaW4gdGhpcyBuZXR3b3JrOgpgYGB7cn0KIyBOdW1iZXIgb2YgYWdlbnRzIHdpdGggQ3VycmVudCBTbW9raW5nIHN0YXR1cwpudW1fY3VycmVudF9zbW9raW5nIDwtIHN1bShmaXJzdF9kZWdyZWVfbmVpZ2hib3JzX2FnZW50X2RhdGEkc21va2luZ19zdGF0dXMgPT0gIkN1cnJlbnQiKQoKIyBOdW1iZXIgb2YgYWdlbnRzIHdpdGggQVVECm51bV9hdWQgPC0gc3VtKGZpcnN0X2RlZ3JlZV9uZWlnaGJvcnNfYWdlbnRfZGF0YSRhbGNfdXNlX3N0YXR1cyA9PSAzKQoKIyBUb3RhbCBudW1iZXIgb2YgYWdlbnRzIGluIHRoZSBuZXR3b3JrCnRvdGFsX2FnZW50cyA8LSBucm93KGZpcnN0X2RlZ3JlZV9uZWlnaGJvcnNfYWdlbnRfZGF0YSkKCiMgQ2FsY3VsYXRlIHByZXZhbGVuY2UKcHJldmFsZW5jZV9zbW9raW5nIDwtIG51bV9jdXJyZW50X3Ntb2tpbmcgLyB0b3RhbF9hZ2VudHMKcHJldmFsZW5jZV9hdWQgPC0gbnVtX2F1ZCAvIHRvdGFsX2FnZW50cwoKIyBQcmludCB0aGUgcmVzdWx0cwpjYXQoIlByZXZhbGVuY2Ugb2YgQ3VycmVudCBTbW9raW5nIGluIHRoZSBuZXR3b3JrcyBvZiByYW5kb21seSAKICAgIHNlbGVjdGVkIG5ldmVyIGluY2FyY2VyYXRlZCBwZXJzb25zOiAiLCBwcmV2YWxlbmNlX3Ntb2tpbmcsICJcbiIpCmNhdCgiUHJldmFsZW5jZSBvZiBBVUQgaW4gdGhlIG5ldHdvcmtzIG9mIHJhbmRvbWx5IAogICAgc2VsZWN0ZWQgbmV2ZXIgaW5jYXJjZXJhdGVkIHBlcnNvbnM6ICIsIHByZXZhbGVuY2VfYXVkLCAiXG4iKQoKYGBgCgpTbW9raW5nIGFuZCBBVUQgYW1vbmcgdGhlIGVnb3M6CgpgYGB7cn0KIyBEZWZpbmUgc2VsZWN0ZWRfYWdlbnRzX2RmLCB3aGljaCBjb250YWlucyB0aGUgZGF0YSBmb3IgdGhlIHNlbGVjdGVkIGFnZW50cwpzZWxlY3RlZF9hZ2VudHNfZGYgPC0gbGFzdF90aWNrX2FnZW50X2R0W2xhc3RfdGlja19hZ2VudF9kdCRpZCAlaW4lIHNlbGVjdGVkX2FnZW50cyxdCgojIE51bWJlciBvZiBzZWxlY3RlZCBhZ2VudHMgd2hvIGFyZSBjdXJyZW50IHNtb2tlcnMKbnVtX2Vnb19jdXJyZW50X3Ntb2tpbmcgPC0gc3VtKHNlbGVjdGVkX2FnZW50c19kZiRzbW9raW5nX3N0YXR1cyA9PSAiQ3VycmVudCIpCgojIE51bWJlciBvZiBzZWxlY3RlZCBhZ2VudHMgd2l0aCBBVUQKbnVtX2Vnb19hdWQgPC0gc3VtKHNlbGVjdGVkX2FnZW50c19kZiRhbGNfdXNlX3N0YXR1cyA9PSAzKQoKIyBUb3RhbCBudW1iZXIgb2Ygc2VsZWN0ZWQgYWdlbnRzCnRvdGFsX2Vnb19hZ2VudHMgPC0gbGVuZ3RoKHNlbGVjdGVkX2FnZW50cykKCiMgQ2FsY3VsYXRlIHByZXZhbGVuY2UKcHJldmFsZW5jZV9lZ29fc21va2luZyA8LSBudW1fZWdvX2N1cnJlbnRfc21va2luZyAvIHRvdGFsX2Vnb19hZ2VudHMKcHJldmFsZW5jZV9lZ29fYXVkIDwtIG51bV9lZ29fYXVkIC8gdG90YWxfZWdvX2FnZW50cwoKIyBQcmludCB0aGUgcmVzdWx0cwpjYXQoIlByZXZhbGVuY2Ugb2YgQ3VycmVudCBTbW9raW5nIGFtb25nIHNlbGVjdGVkIGFnZW50czogIiwgcHJldmFsZW5jZV9lZ29fc21va2luZywgIlxuIikKY2F0KCJQcmV2YWxlbmNlIG9mIEFVRCBhbW9uZyBzZWxlY3RlZCBhZ2VudHM6ICIsIHByZXZhbGVuY2VfZWdvX2F1ZCwgIlxuIikKCmBgYAoK