install from private guthub

#set config
usethis::use_git_config(user.name = "Rlhoove1", user.email = "rlhoove1@asu.edu")
#usethis::create_github_token() 
credentials::set_github_pat('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')
library('devtools')
devtools::install_github('plaisier-lab/scRegNet/scRegNet', force = FALSE)
library(scRegNet)
library(igraph)
library(tidyverse)
library(ggraph)
library(dplyr)
## Set variables
species = 'mouse'
gene_id = 'ensembl'
## Load data
seurat_obj = readRDS('endocrinogenesis/pancreas_normalizedSeuratObj_allGenesEnsemblID_ccAFv2.rds')
beta_traj = read.csv('endocrinogenesis/pancreas_trajectoryOrder_Beta.csv', row.names=1, header=T)
traj = rownames(beta_traj)[beta_traj[,1]]
degs = read.csv('endocrinogenesis/pancreas_SCT_markerGenes_ensemblIDs.csv', row.names=1, header=T)
marker_genes = degs[degs[,'cluster']=='Beta' & degs[,'avg_log2FC']>=1.5 & degs[,'p_val_adj']<=0.05,'gene']
## Collect expression data
expressed_genes = row.names(seurat_obj@assays[['SCT']]@data)
m = seurat_obj@assays[['SCT']]@scale.data
exprs_matrix = m[, traj]
## Test mechanistic function
mech_tfs = scRegNet::mechanistic(marker_genes, expressed_genes, species, gene_id)
Loading up data for anlaysis...
Number of genes used for comparisons: 19697
Conduct TF target gene enrichment analysis...

  |                                                                                                 
  |                                                                                           |   0%
  |                                                                                                 
  |                                                                                           |   1%
  |                                                                                                 
  |=                                                                                          |   1%
  |                                                                                                 
  |=                                                                                          |   2%
  |                                                                                                 
  |==                                                                                         |   2%
  |                                                                                                 
  |==                                                                                         |   3%
  |                                                                                                 
  |===                                                                                        |   3%
  |                                                                                                 
  |===                                                                                        |   4%
  |                                                                                                 
  |====                                                                                       |   4%
  |                                                                                                 
  |====                                                                                       |   5%
  |                                                                                                 
  |=====                                                                                      |   5%
  |                                                                                                 
  |=====                                                                                      |   6%
  |                                                                                                 
  |======                                                                                     |   6%
  |                                                                                                 
  |======                                                                                     |   7%
  |                                                                                                 
  |=======                                                                                    |   7%
  |                                                                                                 
  |=======                                                                                    |   8%
  |                                                                                                 
  |========                                                                                   |   8%
  |                                                                                                 
  |========                                                                                   |   9%
  |                                                                                                 
  |=========                                                                                  |   9%
  |                                                                                                 
  |=========                                                                                  |  10%
  |                                                                                                 
  |==========                                                                                 |  10%
  |                                                                                                 
  |==========                                                                                 |  11%
  |                                                                                                 
  |==========                                                                                 |  12%
  |                                                                                                 
  |===========                                                                                |  12%
  |                                                                                                 
  |===========                                                                                |  13%
  |                                                                                                 
  |============                                                                               |  13%
  |                                                                                                 
  |============                                                                               |  14%
  |                                                                                                 
  |=============                                                                              |  14%
  |                                                                                                 
  |=============                                                                              |  15%
  |                                                                                                 
  |==============                                                                             |  15%
  |                                                                                                 
  |==============                                                                             |  16%
  |                                                                                                 
  |===============                                                                            |  16%
  |                                                                                                 
  |===============                                                                            |  17%
  |                                                                                                 
  |================                                                                           |  17%
  |                                                                                                 
  |================                                                                           |  18%
  |                                                                                                 
  |=================                                                                          |  18%
  |                                                                                                 
  |=================                                                                          |  19%
  |                                                                                                 
  |==================                                                                         |  19%
  |                                                                                                 
  |==================                                                                         |  20%
  |                                                                                                 
  |===================                                                                        |  20%
  |                                                                                                 
  |===================                                                                        |  21%
  |                                                                                                 
  |====================                                                                       |  21%
  |                                                                                                 
  |====================                                                                       |  22%
  |                                                                                                 
  |=====================                                                                      |  23%
  |                                                                                                 
  |=====================                                                                      |  24%
  |                                                                                                 
  |======================                                                                     |  24%
  |                                                                                                 
  |======================                                                                     |  25%
  |                                                                                                 
  |=======================                                                                    |  25%
  |                                                                                                 
  |=======================                                                                    |  26%
  |                                                                                                 
  |========================                                                                   |  26%
  |                                                                                                 
  |========================                                                                   |  27%
  |                                                                                                 
  |=========================                                                                  |  27%
  |                                                                                                 
  |=========================                                                                  |  28%
  |                                                                                                 
  |==========================                                                                 |  28%
  |                                                                                                 
  |==========================                                                                 |  29%
  |                                                                                                 
  |===========================                                                                |  29%
  |                                                                                                 
  |===========================                                                                |  30%
  |                                                                                                 
  |============================                                                               |  30%
  |                                                                                                 
  |============================                                                               |  31%
  |                                                                                                 
  |=============================                                                              |  31%
  |                                                                                                 
  |=============================                                                              |  32%
  |                                                                                                 
  |==============================                                                             |  32%
  |                                                                                                 
  |==============================                                                             |  33%
  |                                                                                                 
  |===============================                                                            |  34%
  |                                                                                                 
  |===============================                                                            |  35%
  |                                                                                                 
  |================================                                                           |  35%
  |                                                                                                 
  |================================                                                           |  36%
  |                                                                                                 
  |=================================                                                          |  36%
  |                                                                                                 
  |=================================                                                          |  37%
  |                                                                                                 
  |==================================                                                         |  37%
  |                                                                                                 
  |==================================                                                         |  38%
  |                                                                                                 
  |===================================                                                        |  38%
  |                                                                                                 
  |===================================                                                        |  39%
  |                                                                                                 
  |====================================                                                       |  39%
  |                                                                                                 
  |====================================                                                       |  40%
  |                                                                                                 
  |=====================================                                                      |  40%
  |                                                                                                 
  |=====================================                                                      |  41%
  |                                                                                                 
  |======================================                                                     |  41%
  |                                                                                                 
  |======================================                                                     |  42%
  |                                                                                                 
  |=======================================                                                    |  42%
  |                                                                                                 
  |=======================================                                                    |  43%
  |                                                                                                 
  |========================================                                                   |  43%
  |                                                                                                 
  |========================================                                                   |  44%
  |                                                                                                 
  |=========================================                                                  |  45%
  |                                                                                                 
  |=========================================                                                  |  46%
  |                                                                                                 
  |==========================================                                                 |  46%
  |                                                                                                 
  |==========================================                                                 |  47%
  |                                                                                                 
  |===========================================                                                |  47%
  |                                                                                                 
  |===========================================                                                |  48%
  |                                                                                                 
  |============================================                                               |  48%
  |                                                                                                 
  |============================================                                               |  49%
  |                                                                                                 
  |=============================================                                              |  49%
  |                                                                                                 
  |=============================================                                              |  50%
  |                                                                                                 
  |==============================================                                             |  50%
  |                                                                                                 
  |==============================================                                             |  51%
  |                                                                                                 
  |===============================================                                            |  51%
  |                                                                                                 
  |===============================================                                            |  52%
  |                                                                                                 
  |================================================                                           |  52%
  |                                                                                                 
  |================================================                                           |  53%
  |                                                                                                 
  |=================================================                                          |  53%
  |                                                                                                 
  |=================================================                                          |  54%
  |                                                                                                 
  |==================================================                                         |  54%
  |                                                                                                 
  |==================================================                                         |  55%
  |                                                                                                 
  |===================================================                                        |  56%
  |                                                                                                 
  |===================================================                                        |  57%
  |                                                                                                 
  |====================================================                                       |  57%
  |                                                                                                 
  |====================================================                                       |  58%
  |                                                                                                 
  |=====================================================                                      |  58%
  |                                                                                                 
  |=====================================================                                      |  59%
  |                                                                                                 
  |======================================================                                     |  59%
  |                                                                                                 
  |======================================================                                     |  60%
  |                                                                                                 
  |=======================================================                                    |  60%
  |                                                                                                 
  |=======================================================                                    |  61%
  |                                                                                                 
  |========================================================                                   |  61%
  |                                                                                                 
  |========================================================                                   |  62%
  |                                                                                                 
  |=========================================================                                  |  62%
  |                                                                                                 
  |=========================================================                                  |  63%
  |                                                                                                 
  |==========================================================                                 |  63%
  |                                                                                                 
  |==========================================================                                 |  64%
  |                                                                                                 
  |===========================================================                                |  64%
  |                                                                                                 
  |===========================================================                                |  65%
  |                                                                                                 
  |============================================================                               |  65%
  |                                                                                                 
  |============================================================                               |  66%
  |                                                                                                 
  |=============================================================                              |  67%
  |                                                                                                 
  |=============================================================                              |  68%
  |                                                                                                 
  |==============================================================                             |  68%
  |                                                                                                 
  |==============================================================                             |  69%
  |                                                                                                 
  |===============================================================                            |  69%
  |                                                                                                 
  |===============================================================                            |  70%
  |                                                                                                 
  |================================================================                           |  70%
  |                                                                                                 
  |================================================================                           |  71%
  |                                                                                                 
  |=================================================================                          |  71%
  |                                                                                                 
  |=================================================================                          |  72%
  |                                                                                                 
  |==================================================================                         |  72%
  |                                                                                                 
  |==================================================================                         |  73%
  |                                                                                                 
  |===================================================================                        |  73%
  |                                                                                                 
  |===================================================================                        |  74%
  |                                                                                                 
  |====================================================================                       |  74%
  |                                                                                                 
  |====================================================================                       |  75%
  |                                                                                                 
  |=====================================================================                      |  75%
  |                                                                                                 
  |=====================================================================                      |  76%
  |                                                                                                 
  |======================================================================                     |  76%
  |                                                                                                 
  |======================================================================                     |  77%
  |                                                                                                 
  |=======================================================================                    |  78%
  |                                                                                                 
  |=======================================================================                    |  79%
  |                                                                                                 
  |========================================================================                   |  79%
  |                                                                                                 
  |========================================================================                   |  80%
  |                                                                                                 
  |=========================================================================                  |  80%
  |                                                                                                 
  |=========================================================================                  |  81%
  |                                                                                                 
  |==========================================================================                 |  81%
  |                                                                                                 
  |==========================================================================                 |  82%
  |                                                                                                 
  |===========================================================================                |  82%
  |                                                                                                 
  |===========================================================================                |  83%
  |                                                                                                 
  |============================================================================               |  83%
  |                                                                                                 
  |============================================================================               |  84%
  |                                                                                                 
  |=============================================================================              |  84%
  |                                                                                                 
  |=============================================================================              |  85%
  |                                                                                                 
  |==============================================================================             |  85%
  |                                                                                                 
  |==============================================================================             |  86%
  |                                                                                                 
  |===============================================================================            |  86%
  |                                                                                                 
  |===============================================================================            |  87%
  |                                                                                                 
  |================================================================================           |  87%
  |                                                                                                 
  |================================================================================           |  88%
  |                                                                                                 
  |=================================================================================          |  88%
  |                                                                                                 
  |=================================================================================          |  89%
  |                                                                                                 
  |=================================================================================          |  90%
  |                                                                                                 
  |==================================================================================         |  90%
  |                                                                                                 
  |==================================================================================         |  91%
  |                                                                                                 
  |===================================================================================        |  91%
  |                                                                                                 
  |===================================================================================        |  92%
  |                                                                                                 
  |====================================================================================       |  92%
  |                                                                                                 
  |====================================================================================       |  93%
  |                                                                                                 
  |=====================================================================================      |  93%
  |                                                                                                 
  |=====================================================================================      |  94%
  |                                                                                                 
  |======================================================================================     |  94%
  |                                                                                                 
  |======================================================================================     |  95%
  |                                                                                                 
  |=======================================================================================    |  95%
  |                                                                                                 
  |=======================================================================================    |  96%
  |                                                                                                 
  |========================================================================================   |  96%
  |                                                                                                 
  |========================================================================================   |  97%
  |                                                                                                 
  |=========================================================================================  |  97%
  |                                                                                                 
  |=========================================================================================  |  98%
  |                                                                                                 
  |========================================================================================== |  98%
  |                                                                                                 
  |========================================================================================== |  99%
  |                                                                                                 
  |===========================================================================================|  99%
  |                                                                                                 
  |===========================================================================================| 100%
Adding multiple hypothesis correction...
Done.
write.csv(mech_tfs, 'enrichment_endocrinogenesis.csv')
#mech_tfs = read.csv('enrichment_endocrinogenesis_fixed.csv', header=T, row.names=1)
## Test associate_with_expression
associations = scRegNet::associate_with_expression(exprs_matrix, mech_tfs, species=species, gene_id=gene_id, method=c('pearson'))
Compare TF expression versus enriched marker eigengene...
    Run mode: pearson
Error in txtProgressBar(min = 0, max = length(unlist(sig_mech_tfs)), initial = 0,  : 
  must have 'max' > 'min'
library(Seurat)
DimPlot(seurat_obj, reduction = "umap", group.by = "clusters", label = TRUE) 

# UMAP plot colored by velocity pseudotime
FeaturePlot(seurat_obj, features = "velocity_pseudotime", reduction = "umap") 

library(Seurat)
FeaturePlot(seurat_obj, features = "ENSMUSG00000004366", reduction ="umap")

network graph practice

df <- data.frame(animal=c('koala', 'armadillo', 'sloth', 'sloth','panda','rori'), 
                             country=c('Australia', 'USA', 'Peru', 'Peru', 'China', 'USA'),
                             fruit=c("leaves apples limes", "leaves arugala berries",
                                     "grass roots apples","roots lemons limes",
                                     "bamboo berries leaves","berries coffee arugala"))
df <- df %>%
  separate_rows(fruit, sep = " ")
print(df)

edges <- data.frame(
  from = c(df$country, df$animal), 
  to = c(df$animal, df$fruit)
)


nodes <- data.frame(
  name = unique(c(edges$from, edges$to))
)
nodes$type <- ifelse(nodes$name %in% df$country, "country",
                     ifelse(nodes$name %in% df$animal, "animal", "fruit"))


graph <- graph_from_data_frame(d=edges, vertices=nodes, directed=TRUE)


ggraph(graph, layout="auto") + 
  geom_edge_link(aes(start_cap = label_rect(node1.name), end_cap = label_rect(node2.name)), 
                 arrow = arrow(length = unit(4, 'mm')), end_cap = circle(3, 'mm')) +
  geom_node_point(aes(color=type, size=type)) + 
  geom_node_text(aes(label=name), repel=TRUE, size=5) + 
  theme_void() +
  scale_color_manual(values=c("country"="red", "animal"="blue", "fruit"="green")) +
  scale_size_manual(values=c("country"=6, "animal"=5, "fruit"=4)) +
  ggtitle("super sleepers")
Using "sugiyama" as default layout


df <- df[df$fruit == "berries", ]

edges <- data.frame(
  from = c(df$country, df$animal), 
  to = c(df$animal, df$fruit))

nodes <- data.frame(
  name = unique(c(edges$from, edges$to)))

nodes$type <- ifelse(nodes$name %in% df$country, "country",
                     ifelse(nodes$name %in% df$animal, "animal", "fruit"))


graph <- graph_from_data_frame(d=edges, vertices=nodes, directed=TRUE)

ggraph(graph, layout="auto") + 
  geom_edge_link(aes(start_cap = label_rect(node1.name), end_cap = label_rect(node2.name)), 
                 arrow = arrow(length = unit(4, 'mm')), end_cap = circle(3, 'mm')) +
  geom_node_point(aes(color=type, size=type)) + 
  geom_node_text(aes(label=name), repel=TRUE, size=5) + 
  theme_void() +
  scale_color_manual(values=c("country"="red", "animal"="blue", "fruit"="green")) +
  scale_size_manual(values=c("country"=6, "animal"=5, "fruit"=4)) +
  ggtitle("who eats berries?")
Using "sugiyama" as default layout

#function to plot TFs acting on one gene

gene ="ENSMUSG00000022265"
gene_to_TF <- function(input, gene, ly="stress", rank=TRUE) {
  df<- input
  
  df <- input %>%
  separate_rows(TF_targets, sep = " ")

  df2 <- input %>%
  separate_rows(TF_targets_symbol, sep = " ")

  df$TF_targets_symbol <-df2$TF_targets_symbol
  
  df$TF_symbol_Motif_Pair <- paste(df$TF_symbol, "(", df$Motif, ")", sep = "")
  
  input<- df
  
  df <- df[df$TF_targets_symbol ==  gene,]
  if(length(df$Motif) == 0){
    df<- input
    df <- df[df$TF_targets ==  gene,]
  }
  
  edges <- data.frame(
        from = gene,
        to = df$TF_symbol_Motif_Pair)
  n = unique(c(gene, edges$to))
  nodes <- data.frame(name = n,
                      type = ifelse(n %in% df$TF_symbol_Motif_Pair, "TF Motif Pair", "gene"))
  
  if (rank) { 
     max_of = max(df$PC1_var_exp)
    nodes$size <- c(max_of, df$PC1_var_exp)
  }
    else {
      nodes$size <- rep(1, length(nodes$name))
   }
  
  outs <- ggraph(graph_from_data_frame(d = edges, vertices = nodes, directed = TRUE), layout = ly) +
    geom_edge_link(aes(start_cap = label_rect(node1.name), end_cap = label_rect(node2.name)), 
                   arrow = arrow(length = unit(2, 'mm')), end_cap = circle(3, 'mm')) +
    geom_node_point(aes(color = type, size = size)) +
    geom_node_text(aes(label = c('', name[2:length(name)])), repel = TRUE, size = 3) +
    theme_void() +
    scale_color_manual(values = c("TF" = "red", "gene" = "blue")) +
    ggtitle(paste0('TFS for ', nodes$name[1]))
  show(outs)
  return(df$TF_symbol_Motif_Pair)
}

its nice wwhen they look like this

gene_to_TF(associations, "Arxes1", ly="stress", rank=TRUE)
Error: object 'associations' not found

but most look like this, how can we fix this problem

gene_to_TF(associations,"ENSMUSG00000022265", ly="stress", rank=TRUE) 
Error: object 'associations' not found

#function to plot motifs related to a TF

TF_to_Motif <- function(input, tf, ly="stress", rank=FALSE) {
  df<- input
  df <- df[df$TF_symbol ==  tf,]
  if(length(df$Motif) == 0){
    df<- input
    df <- df[df$TF ==  tf,]
  }
  
  edges <- data.frame(
        from = tf,
        to = df$Motif)
  n = c(tf, edges$to)
  nodes <- data.frame(name = n,
                      type = ifelse(n %in% df$Motif, "Motif", "TF"))
  
 if (rank) { 
   max_of = max(df$PC1_var_exp)
   nodes$size <- c(max_of, df$PC1_var_exp)
 }
  else {
    nodes$size <- rep(1, length(nodes$name))
  }
  
  outs <- ggraph(graph_from_data_frame(d = edges, vertices = nodes, directed = TRUE), layout = ly) +
    geom_edge_link(aes(start_cap = label_rect(node1.name), end_cap = label_rect(node2.name)), 
                   arrow = arrow(length = unit(2, 'mm')), end_cap = circle(3, 'mm')) +
    geom_node_point(aes(color = type, size = size)) +
    geom_node_text(aes(label = c('', name[2:length(name)])), repel = TRUE, size = 3) +
    theme_void() +
    scale_color_manual(values = c("Motif" = "red", "TF" = "blue")) +
    ggtitle(paste0('Motifs for ', nodes$name[1]))
  show(outs)
  return(df$Motif)
}
TF_to_Motif( associations, "Bcl6b")
[1] "Bcl6b.2"           "V_BCL6B_04_M02844"


plot_expression_worse <- function(seurat_obj, gene, assay="RNA"){
  DefaultAssay(seurat_obj) <- assay 
  df <- FetchData(seurat_obj, vars = gene)
  df$Cluster <- seurat_obj@meta.data$clusters
  df$Pseudotime <- seurat_obj@meta.data$velocity_pseudotime
  colnames(df)[colnames(df) == gene] <- "Expression"
  ggplot(df, aes(x = Pseudotime, y = Expression, color = Cluster)) +
  geom_point(alpha = 0.5) +
  labs(title = paste("Expression of", gene, "over Pseudotime"),
       x = "Pseudotime",
       y = "Expression Level",
       color = "Cluster") +  
  theme_minimal()
}
plot_expression_worse(seurat_obj, gene="ENSMUSG00000054667", assay="SCT")

 library(dplyr)

df <- seurat_obj@meta.data %>%
  select(clusters, velocity_pseudotime)

pseudotime_ranges <- df %>%
  group_by(clusters) %>%
  summarise(
    min_pseudotime = min(velocity_pseudotime),
    max_pseudotime = max(velocity_pseudotime),
    mean_pseudotime = mean(velocity_pseudotime)
  )

print(pseudotime_ranges)

ggplot(df, aes(x = velocity_pseudotime, y = as.factor(clusters))) +
  geom_boxplot() +
  labs(x = "Velocity Pseudotime", y = "Clusters", title = "Pseudotime Distribution by Cluster") +
  theme_minimal()


plot_expression <- function(seurat_obj, gene, assay="RNA", celltype ){
  DefaultAssay(seurat_obj) <- assay 
  
  df <- FetchData(seurat_obj, vars = gene)
  df$Cluster <- seurat_obj@meta.data$clusters
  df$Pseudotime <- seurat_obj@meta.data$velocity_pseudotime
  colnames(df)[colnames(df) == gene] <- "Expression"

  if (celltype == "Epsilon") {
    df <- df[!df$Cluster %in% c("Beta", "Alpha", "Delta"), ]
  } else if (celltype == "Beta") {
    df <- df[!df$Cluster %in% c("Epsilon", "Alpha", "Delta"), ]
  } else if (celltype == "Alpha") {
    df <- df[!df$Cluster %in% c("Epsilon", "Beta", "Delta"), ]
  } else if (celltype == "Delta") {
    df <- df[!df$Cluster %in% c("Epsilon", "Alpha", "Beta"), ]
  }
  
cluster_colors <- c(
    "Alpha" = "darkmagenta",
    "Beta" = "cyan2",
    "Delta" = "coral2",
    "Ductal" = "cornflowerblue",
    "Epsilon" = "deeppink",
    "Ngn3 high EP" = "darkgoldenrod2",
    "Ngn3 low EP" = "chartreuse",
    "Pre-endocrine" = "hotpink2"
  )
  
  ggplot(df, aes(x = Pseudotime, y = Expression, color = Cluster)) +
  geom_point(alpha = 0.5) +
  scale_color_manual(values = cluster_colors) + 
  labs(title = paste( gene ),
         x = "Pseudotime",
         y = "Expression Level",
         color = "Cluster") +  
  theme_minimal()+
  theme(plot.title = element_text(size = 10))
}

regenerate figures

if you put in nonsense it still works but you cant put in nothing for celltype

plot_expression(seurat_obj, gene="ENSMUSG00000056758", celltype = "duck", assay="SCT") #Hmg2a

 
library(patchwork)
p1 <- plot_expression(seurat_obj, gene="ENSMUSG00000064177", celltype = "Epsilon", assay="SCT") #Ghrl
p2 <- plot_expression(seurat_obj, gene="ENSMUSG00000000215", celltype = "Beta", assay="SCT") #Ins2
p3 <- plot_expression(seurat_obj, gene="ENSMUSG00000004366", celltype = "Delta", assay="SCT") #Sst
p4 <- plot_expression(seurat_obj, gene="ENSMUSG00000000394", celltype = "Alpha", assay="SCT") #Gcg


(p1 | p2) /
(p3 | p4)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCmVkaXRvcl9vcHRpb25zOiAKICBtYXJrZG93bjogCiAgICB3cmFwOiA3MgotLS0KCmluc3RhbGwgZnJvbSBwcml2YXRlIGd1dGh1YgpgYGB7cn0KI3NldCBjb25maWcKdXNldGhpczo6dXNlX2dpdF9jb25maWcodXNlci5uYW1lID0gIlJsaG9vdmUxIiwgdXNlci5lbWFpbCA9ICJybGhvb3ZlMUBhc3UuZWR1IikKI3VzZXRoaXM6OmNyZWF0ZV9naXRodWJfdG9rZW4oKSAKY3JlZGVudGlhbHM6OnNldF9naXRodWJfcGF0KCdnaHBfWDdSaEhvS2hvSmc0TkhabjlKbk9LUzl5RVVmZFZyNDRGYTJsJykKbGlicmFyeSgnZGV2dG9vbHMnKQpkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoJ3BsYWlzaWVyLWxhYi9zY1JlZ05ldC9zY1JlZ05ldCcsIGZvcmNlID0gRkFMU0UpCmxpYnJhcnkoc2NSZWdOZXQpCmxpYnJhcnkoaWdyYXBoKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3JhcGgpCmxpYnJhcnkoZHBseXIpCmBgYAoKYGBge3J9CiMjIFNldCB2YXJpYWJsZXMKc3BlY2llcyA9ICdtb3VzZScKZ2VuZV9pZCA9ICdlbnNlbWJsJwpgYGAKCmBgYHtyfQojIyBMb2FkIGRhdGEKc2V1cmF0X29iaiA9IHJlYWRSRFMoJ2VuZG9jcmlub2dlbmVzaXMvcGFuY3JlYXNfbm9ybWFsaXplZFNldXJhdE9ial9hbGxHZW5lc0Vuc2VtYmxJRF9jY0FGdjIucmRzJykKYmV0YV90cmFqID0gcmVhZC5jc3YoJ2VuZG9jcmlub2dlbmVzaXMvcGFuY3JlYXNfdHJhamVjdG9yeU9yZGVyX0JldGEuY3N2Jywgcm93Lm5hbWVzPTEsIGhlYWRlcj1UKQp0cmFqID0gcm93bmFtZXMoYmV0YV90cmFqKVtiZXRhX3RyYWpbLDFdXQpkZWdzID0gcmVhZC5jc3YoJ2VuZG9jcmlub2dlbmVzaXMvcGFuY3JlYXNfU0NUX21hcmtlckdlbmVzX2Vuc2VtYmxJRHMuY3N2Jywgcm93Lm5hbWVzPTEsIGhlYWRlcj1UKQptYXJrZXJfZ2VuZXMgPSBkZWdzW2RlZ3NbLCdjbHVzdGVyJ109PSdCZXRhJyAmIGRlZ3NbLCdhdmdfbG9nMkZDJ10+PTEuNSAmIGRlZ3NbLCdwX3ZhbF9hZGonXTw9MC4wNSwnZ2VuZSddCmBgYAoKYGBge3J9CiMjIENvbGxlY3QgZXhwcmVzc2lvbiBkYXRhCmV4cHJlc3NlZF9nZW5lcyA9IHJvdy5uYW1lcyhzZXVyYXRfb2JqQGFzc2F5c1tbJ1NDVCddXUBkYXRhKQptID0gc2V1cmF0X29iakBhc3NheXNbWydTQ1QnXV1Ac2NhbGUuZGF0YQpleHByc19tYXRyaXggPSBtWywgdHJhal0KYGBgCgoKYGBge3J9CiMjIFRlc3QgbWVjaGFuaXN0aWMgZnVuY3Rpb24KbWVjaF90ZnMgPSBzY1JlZ05ldDo6bWVjaGFuaXN0aWMobWFya2VyX2dlbmVzLCBleHByZXNzZWRfZ2VuZXMsIHNwZWNpZXMsIGdlbmVfaWQpCndyaXRlLmNzdihtZWNoX3RmcywgJ2VucmljaG1lbnRfZW5kb2NyaW5vZ2VuZXNpcy5jc3YnKQojbWVjaF90ZnMgPSByZWFkLmNzdignZW5yaWNobWVudF9lbmRvY3Jpbm9nZW5lc2lzX2ZpeGVkLmNzdicsIGhlYWRlcj1ULCByb3cubmFtZXM9MSkKYGBgCmBgYHtyfQojIyBUZXN0IGFzc29jaWF0ZV93aXRoX2V4cHJlc3Npb24KYXNzb2NpYXRpb25zID0gc2NSZWdOZXQ6OmFzc29jaWF0ZV93aXRoX2V4cHJlc3Npb24oZXhwcnNfbWF0cml4LCBtZWNoX3Rmcywgc3BlY2llcz1zcGVjaWVzLCBnZW5lX2lkPWdlbmVfaWQsIG1ldGhvZD1jKCdwZWFyc29uJykpCndyaXRlLmNzdihhc3NvY2lhdGlvbnMsICdhc3NvY2lhdGlvbl9leHByZXNzaW9uLmNzdicpCmBgYAoKYGBge3J9CmxpYnJhcnkoU2V1cmF0KQpEaW1QbG90KHNldXJhdF9vYmosIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAiY2x1c3RlcnMiLCBsYWJlbCA9IFRSVUUpIApgYGAKCmBgYHtyfQojIFVNQVAgcGxvdCBjb2xvcmVkIGJ5IHZlbG9jaXR5IHBzZXVkb3RpbWUKRmVhdHVyZVBsb3Qoc2V1cmF0X29iaiwgZmVhdHVyZXMgPSAidmVsb2NpdHlfcHNldWRvdGltZSIsIHJlZHVjdGlvbiA9ICJ1bWFwIikgCmBgYAoKYGBge3J9CmxpYnJhcnkoU2V1cmF0KQpGZWF0dXJlUGxvdChzZXVyYXRfb2JqLCBmZWF0dXJlcyA9ICJFTlNNVVNHMDAwMDAwMDQzNjYiLCByZWR1Y3Rpb24gPSJ1bWFwIikKYGBgCgpuZXR3b3JrIGdyYXBoIHByYWN0aWNlIApgYGB7cn0KZGYgPC0gZGF0YS5mcmFtZShhbmltYWw9Yygna29hbGEnLCAnYXJtYWRpbGxvJywgJ3Nsb3RoJywgJ3Nsb3RoJywncGFuZGEnLCdyb3JpJyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cnk9YygnQXVzdHJhbGlhJywgJ1VTQScsICdQZXJ1JywgJ1BlcnUnLCAnQ2hpbmEnLCAnVVNBJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJ1aXQ9YygibGVhdmVzIGFwcGxlcyBsaW1lcyIsICJsZWF2ZXMgYXJ1Z2FsYSBiZXJyaWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJncmFzcyByb290cyBhcHBsZXMiLCJyb290cyBsZW1vbnMgbGltZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJhbWJvbyBiZXJyaWVzIGxlYXZlcyIsImJlcnJpZXMgY29mZmVlIGFydWdhbGEiKSkKZGYgPC0gZGYgJT4lCiAgc2VwYXJhdGVfcm93cyhmcnVpdCwgc2VwID0gIiAiKQpwcmludChkZikKCmVkZ2VzIDwtIGRhdGEuZnJhbWUoCiAgZnJvbSA9IGMoZGYkY291bnRyeSwgZGYkYW5pbWFsKSwgCiAgdG8gPSBjKGRmJGFuaW1hbCwgZGYkZnJ1aXQpKQoKCm5vZGVzIDwtIGRhdGEuZnJhbWUoCiAgbmFtZSA9IHVuaXF1ZShjKGVkZ2VzJGZyb20sIGVkZ2VzJHRvKSkpCgpub2RlcyR0eXBlIDwtIGlmZWxzZShub2RlcyRuYW1lICVpbiUgZGYkY291bnRyeSwgImNvdW50cnkiLAogICAgICAgICAgICAgICAgICAgICBpZmVsc2Uobm9kZXMkbmFtZSAlaW4lIGRmJGFuaW1hbCwgImFuaW1hbCIsICJmcnVpdCIpKQoKCmdyYXBoIDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShkPWVkZ2VzLCB2ZXJ0aWNlcz1ub2RlcywgZGlyZWN0ZWQ9VFJVRSkKCmdncmFwaChncmFwaCwgbGF5b3V0PSJhdXRvIikgKyAKICBnZW9tX2VkZ2VfbGluayhhZXMoc3RhcnRfY2FwID0gbGFiZWxfcmVjdChub2RlMS5uYW1lKSwgZW5kX2NhcCA9IGxhYmVsX3JlY3Qobm9kZTIubmFtZSkpLCAKICAgICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoNCwgJ21tJykpLCBlbmRfY2FwID0gY2lyY2xlKDMsICdtbScpKSArCiAgZ2VvbV9ub2RlX3BvaW50KGFlcyhjb2xvcj10eXBlLCBzaXplPXR5cGUpKSArIAogIGdlb21fbm9kZV90ZXh0KGFlcyhsYWJlbD1uYW1lKSwgcmVwZWw9VFJVRSwgc2l6ZT01KSArIAogIHRoZW1lX3ZvaWQoKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCJjb3VudHJ5Ij0icmVkIiwgImFuaW1hbCI9ImJsdWUiLCAiZnJ1aXQiPSJncmVlbiIpKSArCiAgc2NhbGVfc2l6ZV9tYW51YWwodmFsdWVzPWMoImNvdW50cnkiPTYsICJhbmltYWwiPTUsICJmcnVpdCI9NCkpICsKICBnZ3RpdGxlKCJzdXBlciBzbGVlcGVycyIpCmBgYAoKYGBge3J9CgpkZiA8LSBkZltkZiRmcnVpdCA9PSAiYmVycmllcyIsIF0KCmVkZ2VzIDwtIGRhdGEuZnJhbWUoCiAgZnJvbSA9IGMoZGYkY291bnRyeSwgZGYkYW5pbWFsKSwgCiAgdG8gPSBjKGRmJGFuaW1hbCwgZGYkZnJ1aXQpKQoKbm9kZXMgPC0gZGF0YS5mcmFtZSgKICBuYW1lID0gdW5pcXVlKGMoZWRnZXMkZnJvbSwgZWRnZXMkdG8pKSkKCm5vZGVzJHR5cGUgPC0gaWZlbHNlKG5vZGVzJG5hbWUgJWluJSBkZiRjb3VudHJ5LCAiY291bnRyeSIsCiAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShub2RlcyRuYW1lICVpbiUgZGYkYW5pbWFsLCAiYW5pbWFsIiwgImZydWl0IikpCgoKZ3JhcGggPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGQ9ZWRnZXMsIHZlcnRpY2VzPW5vZGVzLCBkaXJlY3RlZD1UUlVFKQoKZ2dyYXBoKGdyYXBoLCBsYXlvdXQ9ImF1dG8iKSArIAogIGdlb21fZWRnZV9saW5rKGFlcyhzdGFydF9jYXAgPSBsYWJlbF9yZWN0KG5vZGUxLm5hbWUpLCBlbmRfY2FwID0gbGFiZWxfcmVjdChub2RlMi5uYW1lKSksIAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCg0LCAnbW0nKSksIGVuZF9jYXAgPSBjaXJjbGUoMywgJ21tJykpICsKICBnZW9tX25vZGVfcG9pbnQoYWVzKGNvbG9yPXR5cGUsIHNpemU9dHlwZSkpICsgCiAgZ2VvbV9ub2RlX3RleHQoYWVzKGxhYmVsPW5hbWUpLCByZXBlbD1UUlVFLCBzaXplPTUpICsgCiAgdGhlbWVfdm9pZCgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImNvdW50cnkiPSJyZWQiLCAiYW5pbWFsIj0iYmx1ZSIsICJmcnVpdCI9ImdyZWVuIikpICsKICBzY2FsZV9zaXplX21hbnVhbCh2YWx1ZXM9YygiY291bnRyeSI9NiwgImFuaW1hbCI9NSwgImZydWl0Ij00KSkgKwogIGdndGl0bGUoIndobyBlYXRzIGJlcnJpZXM/IikKYGBgCgojZnVuY3Rpb24gdG8gcGxvdCBURnMgYWN0aW5nIG9uIG9uZSBnZW5lCmBgYHtyfQpnZW5lID0iRU5TTVVTRzAwMDAwMDIyMjY1IgpnZW5lX3RvX1RGIDwtIGZ1bmN0aW9uKGlucHV0LCBnZW5lLCBseT0ic3RyZXNzIiwgcmFuaz1UUlVFKSB7CiAgZGY8LSBpbnB1dAogIAogIGRmIDwtIGlucHV0ICU+JQogIHNlcGFyYXRlX3Jvd3MoVEZfdGFyZ2V0cywgc2VwID0gIiAiKQoKICBkZjIgPC0gaW5wdXQgJT4lCiAgc2VwYXJhdGVfcm93cyhURl90YXJnZXRzX3N5bWJvbCwgc2VwID0gIiAiKQoKICBkZiRURl90YXJnZXRzX3N5bWJvbCA8LWRmMiRURl90YXJnZXRzX3N5bWJvbAogIAogIGRmJFRGX3N5bWJvbF9Nb3RpZl9QYWlyIDwtIHBhc3RlKGRmJFRGX3N5bWJvbCwgIigiLCBkZiRNb3RpZiwgIikiLCBzZXAgPSAiIikKICAKICBpbnB1dDwtIGRmCiAgCiAgZGYgPC0gZGZbZGYkVEZfdGFyZ2V0c19zeW1ib2wgPT0gIGdlbmUsXQogIGlmKGxlbmd0aChkZiRNb3RpZikgPT0gMCl7CiAgICBkZjwtIGlucHV0CiAgICBkZiA8LSBkZltkZiRURl90YXJnZXRzID09ICBnZW5lLF0KICB9CiAgCiAgZWRnZXMgPC0gZGF0YS5mcmFtZSgKICAgICAgICBmcm9tID0gZ2VuZSwKICAgICAgICB0byA9IGRmJFRGX3N5bWJvbF9Nb3RpZl9QYWlyKQogIG4gPSB1bmlxdWUoYyhnZW5lLCBlZGdlcyR0bykpCiAgbm9kZXMgPC0gZGF0YS5mcmFtZShuYW1lID0gbiwKICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSBpZmVsc2UobiAlaW4lIGRmJFRGX3N5bWJvbF9Nb3RpZl9QYWlyLCAiVEYgTW90aWYgUGFpciIsICJnZW5lIikpCiAgCiAgaWYgKHJhbmspIHsgCiAgICAgbWF4X29mID0gbWF4KGRmJFBDMV92YXJfZXhwKQogICAgbm9kZXMkc2l6ZSA8LSBjKG1heF9vZiwgZGYkUEMxX3Zhcl9leHApCiAgfQogICAgZWxzZSB7CiAgICAgIG5vZGVzJHNpemUgPC0gcmVwKDEsIGxlbmd0aChub2RlcyRuYW1lKSkKICAgfQogIAogIG91dHMgPC0gZ2dyYXBoKGdyYXBoX2Zyb21fZGF0YV9mcmFtZShkID0gZWRnZXMsIHZlcnRpY2VzID0gbm9kZXMsIGRpcmVjdGVkID0gVFJVRSksIGxheW91dCA9IGx5KSArCiAgICBnZW9tX2VkZ2VfbGluayhhZXMoc3RhcnRfY2FwID0gbGFiZWxfcmVjdChub2RlMS5uYW1lKSwgZW5kX2NhcCA9IGxhYmVsX3JlY3Qobm9kZTIubmFtZSkpLCAKICAgICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgyLCAnbW0nKSksIGVuZF9jYXAgPSBjaXJjbGUoMywgJ21tJykpICsKICAgIGdlb21fbm9kZV9wb2ludChhZXMoY29sb3IgPSB0eXBlLCBzaXplID0gc2l6ZSkpICsKICAgIGdlb21fbm9kZV90ZXh0KGFlcyhsYWJlbCA9IGMoJycsIG5hbWVbMjpsZW5ndGgobmFtZSldKSksIHJlcGVsID0gVFJVRSwgc2l6ZSA9IDMpICsKICAgIHRoZW1lX3ZvaWQoKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiVEYiID0gInJlZCIsICJnZW5lIiA9ICJibHVlIikpICsKICAgIGdndGl0bGUocGFzdGUwKCdURlMgZm9yICcsIG5vZGVzJG5hbWVbMV0pKQogIHNob3cob3V0cykKICByZXR1cm4oZGYkVEZfc3ltYm9sX01vdGlmX1BhaXIpCn0KCmBgYAoKaXRzIG5pY2Ugd3doZW4gdGhleSBsb29rIGxpa2UgdGhpcyAKYGBge3J9CmdlbmVfdG9fVEYoYXNzb2NpYXRpb25zLCAiQXJ4ZXMxIiwgbHk9InN0cmVzcyIsIHJhbms9VFJVRSkKYGBgCgpidXQgbW9zdCBsb29rIGxpa2UgdGhpcywgaG93IGNhbiB3ZSBmaXggdGhpcyBwcm9ibGVtCmBgYHtyfQpnZW5lX3RvX1RGKGFzc29jaWF0aW9ucywiRU5TTVVTRzAwMDAwMDIyMjY1IiwgbHk9InN0cmVzcyIsIHJhbms9VFJVRSkgCmBgYAoKI2Z1bmN0aW9uIHRvIHBsb3QgbW90aWZzIHJlbGF0ZWQgdG8gYSBURiAKYGBge3J9ClRGX3RvX01vdGlmIDwtIGZ1bmN0aW9uKGlucHV0LCB0ZiwgbHk9InN0cmVzcyIsIHJhbms9RkFMU0UpIHsKICBkZjwtIGlucHV0CiAgZGYgPC0gZGZbZGYkVEZfc3ltYm9sID09ICB0ZixdCiAgaWYobGVuZ3RoKGRmJE1vdGlmKSA9PSAwKXsKICAgIGRmPC0gaW5wdXQKICAgIGRmIDwtIGRmW2RmJFRGID09ICB0ZixdCiAgfQogIAogIGVkZ2VzIDwtIGRhdGEuZnJhbWUoCiAgICAgICAgZnJvbSA9IHRmLAogICAgICAgIHRvID0gZGYkTW90aWYpCiAgbiA9IGModGYsIGVkZ2VzJHRvKQogIG5vZGVzIDwtIGRhdGEuZnJhbWUobmFtZSA9IG4sCiAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gaWZlbHNlKG4gJWluJSBkZiRNb3RpZiwgIk1vdGlmIiwgIlRGIikpCiAgCiBpZiAocmFuaykgeyAKICAgbWF4X29mID0gbWF4KGRmJFBDMV92YXJfZXhwKQogICBub2RlcyRzaXplIDwtIGMobWF4X29mLCBkZiRQQzFfdmFyX2V4cCkKIH0KICBlbHNlIHsKICAgIG5vZGVzJHNpemUgPC0gcmVwKDEsIGxlbmd0aChub2RlcyRuYW1lKSkKICB9CiAgCiAgb3V0cyA8LSBnZ3JhcGgoZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGQgPSBlZGdlcywgdmVydGljZXMgPSBub2RlcywgZGlyZWN0ZWQgPSBUUlVFKSwgbGF5b3V0ID0gbHkpICsKICAgIGdlb21fZWRnZV9saW5rKGFlcyhzdGFydF9jYXAgPSBsYWJlbF9yZWN0KG5vZGUxLm5hbWUpLCBlbmRfY2FwID0gbGFiZWxfcmVjdChub2RlMi5uYW1lKSksIAogICAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDIsICdtbScpKSwgZW5kX2NhcCA9IGNpcmNsZSgzLCAnbW0nKSkgKwogICAgZ2VvbV9ub2RlX3BvaW50KGFlcyhjb2xvciA9IHR5cGUsIHNpemUgPSBzaXplKSkgKwogICAgZ2VvbV9ub2RlX3RleHQoYWVzKGxhYmVsID0gYygnJywgbmFtZVsyOmxlbmd0aChuYW1lKV0pKSwgcmVwZWwgPSBUUlVFLCBzaXplID0gMykgKwogICAgdGhlbWVfdm9pZCgpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJNb3RpZiIgPSAicmVkIiwgIlRGIiA9ICJibHVlIikpICsKICAgIGdndGl0bGUocGFzdGUwKCdNb3RpZnMgZm9yICcsIG5vZGVzJG5hbWVbMV0pKQogIHNob3cob3V0cykKICByZXR1cm4oZGYkTW90aWYpCn0KYGBgCgpgYGB7cn0KVEZfdG9fTW90aWYoIGFzc29jaWF0aW9ucywgIkJjbDZiIikKYGBgCgpgYGB7cn0KVEZfdG9fTW90aWYoIGFzc29jaWF0aW9ucywgJ0VOU01VU0cwMDAwMDAyODY0MCcpCiMiRU5TTVVTRzAwMDAwMDI4NjQwIgpgYGAKCmBgYHtyfQoKcGxvdF9leHByZXNzaW9uX3dvcnNlIDwtIGZ1bmN0aW9uKHNldXJhdF9vYmosIGdlbmUsIGFzc2F5PSJSTkEiKXsKICBEZWZhdWx0QXNzYXkoc2V1cmF0X29iaikgPC0gYXNzYXkgCiAgZGYgPC0gRmV0Y2hEYXRhKHNldXJhdF9vYmosIHZhcnMgPSBnZW5lKQogIGRmJENsdXN0ZXIgPC0gc2V1cmF0X29iakBtZXRhLmRhdGEkY2x1c3RlcnMKICBkZiRQc2V1ZG90aW1lIDwtIHNldXJhdF9vYmpAbWV0YS5kYXRhJHZlbG9jaXR5X3BzZXVkb3RpbWUKICBjb2xuYW1lcyhkZilbY29sbmFtZXMoZGYpID09IGdlbmVdIDwtICJFeHByZXNzaW9uIgogIGdncGxvdChkZiwgYWVzKHggPSBQc2V1ZG90aW1lLCB5ID0gRXhwcmVzc2lvbiwgY29sb3IgPSBDbHVzdGVyKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIkV4cHJlc3Npb24gb2YiLCBnZW5lLCAib3ZlciBQc2V1ZG90aW1lIiksCiAgICAgICB4ID0gIlBzZXVkb3RpbWUiLAogICAgICAgeSA9ICJFeHByZXNzaW9uIExldmVsIiwKICAgICAgIGNvbG9yID0gIkNsdXN0ZXIiKSArICAKICB0aGVtZV9taW5pbWFsKCkKfQoKYGBgCgpgYGB7cn0KcGxvdF9leHByZXNzaW9uX3dvcnNlKHNldXJhdF9vYmosIGdlbmU9IkVOU01VU0cwMDAwMDA1NDY2NyIsIGFzc2F5PSJTQ1QiKQpgYGAKYGBge3J9CiBsaWJyYXJ5KGRwbHlyKQoKZGYgPC0gc2V1cmF0X29iakBtZXRhLmRhdGEgJT4lCiAgc2VsZWN0KGNsdXN0ZXJzLCB2ZWxvY2l0eV9wc2V1ZG90aW1lKQoKcHNldWRvdGltZV9yYW5nZXMgPC0gZGYgJT4lCiAgZ3JvdXBfYnkoY2x1c3RlcnMpICU+JQogIHN1bW1hcmlzZSgKICAgIG1pbl9wc2V1ZG90aW1lID0gbWluKHZlbG9jaXR5X3BzZXVkb3RpbWUpLAogICAgbWF4X3BzZXVkb3RpbWUgPSBtYXgodmVsb2NpdHlfcHNldWRvdGltZSksCiAgICBtZWFuX3BzZXVkb3RpbWUgPSBtZWFuKHZlbG9jaXR5X3BzZXVkb3RpbWUpCiAgKQoKcHJpbnQocHNldWRvdGltZV9yYW5nZXMpCgpnZ3Bsb3QoZGYsIGFlcyh4ID0gdmVsb2NpdHlfcHNldWRvdGltZSwgeSA9IGFzLmZhY3RvcihjbHVzdGVycykpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGxhYnMoeCA9ICJWZWxvY2l0eSBQc2V1ZG90aW1lIiwgeSA9ICJDbHVzdGVycyIsIHRpdGxlID0gIlBzZXVkb3RpbWUgRGlzdHJpYnV0aW9uIGJ5IENsdXN0ZXIiKSArCiAgdGhlbWVfbWluaW1hbCgpCgpgYGAKCgpgYGB7cn0KCnBsb3RfZXhwcmVzc2lvbiA8LSBmdW5jdGlvbihzZXVyYXRfb2JqLCBnZW5lLCBhc3NheT0iUk5BIiwgY2VsbHR5cGUgKXsKICBEZWZhdWx0QXNzYXkoc2V1cmF0X29iaikgPC0gYXNzYXkgCiAgCiAgZGYgPC0gRmV0Y2hEYXRhKHNldXJhdF9vYmosIHZhcnMgPSBnZW5lKQogIGRmJENsdXN0ZXIgPC0gc2V1cmF0X29iakBtZXRhLmRhdGEkY2x1c3RlcnMKICBkZiRQc2V1ZG90aW1lIDwtIHNldXJhdF9vYmpAbWV0YS5kYXRhJHZlbG9jaXR5X3BzZXVkb3RpbWUKICBjb2xuYW1lcyhkZilbY29sbmFtZXMoZGYpID09IGdlbmVdIDwtICJFeHByZXNzaW9uIgoKICBpZiAoY2VsbHR5cGUgPT0gIkVwc2lsb24iKSB7CiAgICBkZiA8LSBkZlshZGYkQ2x1c3RlciAlaW4lIGMoIkJldGEiLCAiQWxwaGEiLCAiRGVsdGEiKSwgXQogIH0gZWxzZSBpZiAoY2VsbHR5cGUgPT0gIkJldGEiKSB7CiAgICBkZiA8LSBkZlshZGYkQ2x1c3RlciAlaW4lIGMoIkVwc2lsb24iLCAiQWxwaGEiLCAiRGVsdGEiKSwgXQogIH0gZWxzZSBpZiAoY2VsbHR5cGUgPT0gIkFscGhhIikgewogICAgZGYgPC0gZGZbIWRmJENsdXN0ZXIgJWluJSBjKCJFcHNpbG9uIiwgIkJldGEiLCAiRGVsdGEiKSwgXQogIH0gZWxzZSBpZiAoY2VsbHR5cGUgPT0gIkRlbHRhIikgewogICAgZGYgPC0gZGZbIWRmJENsdXN0ZXIgJWluJSBjKCJFcHNpbG9uIiwgIkFscGhhIiwgIkJldGEiKSwgXQogIH0KICAKY2x1c3Rlcl9jb2xvcnMgPC0gYygKICAgICJBbHBoYSIgPSAiZGFya21hZ2VudGEiLAogICAgIkJldGEiID0gImN5YW4yIiwKICAgICJEZWx0YSIgPSAiY29yYWwyIiwKICAgICJEdWN0YWwiID0gImNvcm5mbG93ZXJibHVlIiwKICAgICJFcHNpbG9uIiA9ICJkZWVwcGluayIsCiAgICAiTmduMyBoaWdoIEVQIiA9ICJkYXJrZ29sZGVucm9kMiIsCiAgICAiTmduMyBsb3cgRVAiID0gImNoYXJ0cmV1c2UiLAogICAgIlByZS1lbmRvY3JpbmUiID0gImhvdHBpbmsyIgogICkKICAKICBnZ3Bsb3QoZGYsIGFlcyh4ID0gUHNldWRvdGltZSwgeSA9IEV4cHJlc3Npb24sIGNvbG9yID0gQ2x1c3RlcikpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC41KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNsdXN0ZXJfY29sb3JzKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSggZ2VuZSApLAogICAgICAgICB4ID0gIlBzZXVkb3RpbWUiLAogICAgICAgICB5ID0gIkV4cHJlc3Npb24gTGV2ZWwiLAogICAgICAgICBjb2xvciA9ICJDbHVzdGVyIikgKyAgCiAgdGhlbWVfbWluaW1hbCgpKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKfQoKYGBgCiMgcmVnZW5lcmF0ZSBmaWd1cmVzCmlmIHlvdSBwdXQgaW4gbm9uc2Vuc2UgaXQgc3RpbGwgd29ya3MgYnV0IHlvdSBjYW50IHB1dCBpbiBub3RoaW5nIGZvciBjZWxsdHlwZQpgYGB7cn0KcGxvdF9leHByZXNzaW9uKHNldXJhdF9vYmosIGdlbmU9IkVOU01VU0cwMDAwMDA1Njc1OCIsIGNlbGx0eXBlID0gImR1Y2siLCBhc3NheT0iU0NUIikgI0htZzJhCgpgYGAKCmBgYHtyfQogCmxpYnJhcnkocGF0Y2h3b3JrKQpwMSA8LSBwbG90X2V4cHJlc3Npb24oc2V1cmF0X29iaiwgZ2VuZT0iRU5TTVVTRzAwMDAwMDY0MTc3IiwgY2VsbHR5cGUgPSAiRXBzaWxvbiIsIGFzc2F5PSJTQ1QiKSAjR2hybApwMiA8LSBwbG90X2V4cHJlc3Npb24oc2V1cmF0X29iaiwgZ2VuZT0iRU5TTVVTRzAwMDAwMDAwMjE1IiwgY2VsbHR5cGUgPSAiQmV0YSIsIGFzc2F5PSJTQ1QiKSAjSW5zMgpwMyA8LSBwbG90X2V4cHJlc3Npb24oc2V1cmF0X29iaiwgZ2VuZT0iRU5TTVVTRzAwMDAwMDA0MzY2IiwgY2VsbHR5cGUgPSAiRGVsdGEiLCBhc3NheT0iU0NUIikgI1NzdApwNCA8LSBwbG90X2V4cHJlc3Npb24oc2V1cmF0X29iaiwgZ2VuZT0iRU5TTVVTRzAwMDAwMDAwMzk0IiwgY2VsbHR5cGUgPSAiQWxwaGEiLCBhc3NheT0iU0NUIikgI0djZwoKCihwMSB8IHAyKSAvCihwMyB8IHA0KQpgYGAK