NOTE: Feedback should be send to goran.milovanovic_ext@wikimedia.de.

NOTE: The campaign will be run from … to … of October 2017.

0. Data Acquisiton

NOTE: the following code is not fully reproducible from this Report. The data are collected by running the script abc2017_PROD_OverallDailyUpdate.R on stat1005.eqiad.wmnet, collecting the data as .tsv and .csv files, copying manually, and processing locally. Run from stat1005 stat box by executing Rscript /home/goransm/RScripts/abc2017/abc2017_PROD_OverallDailyUpdate.R.

### --- Script: abc2017_PROD_OverallDailyUpdate.R
### --- the following runs on stat1005.eqiad.wmnet
### --- Rscript /home/goransm/RScripts/abc2017/abc2017_PROD_OverallDailyUpdate.R

### --- The script collects and wrangles all datasets
### --- for the WMDE Autumn Banner Campaign 2017.

### --- Goran S. Milovanovic, Data Analyst, WMDE
### --- September 26, 2017.

### -----------------------------------------------------------------------------
### 0. Setup
### -----------------------------------------------------------------------------

rm(list = ls())
library(dplyr)
library(tidyr)
library(stringr)
library(data.table)
startDate <- '2017-09-20'
endDate <- '2017-09-26'
bannerImpressiomnsDir <- '/home/goransm/_miscWMDE/abc2017_DataOUT/abc2017_OfficialDatasets/abc2017BannerImpressions/'
bannerClicksDir <- '/home/goransm/_miscWMDE/abc2017_DataOUT/abc2017_OfficialDatasets/abc2017BannerClicksLandingPages/'
userRegDir <- '/home/goransm/_miscWMDE/abc2017_DataOUT/abc2017_OfficialDatasets/abc2017UserReg/'
dailyUpdateDir <- '/home/goransm/_miscWMDE/abc2017_DataOUT/abc2017_OfficialDatasets/abc2017_DailyUpdate/' 

### -----------------------------------------------------------------------------
### 1. Banner Impressions
### -----------------------------------------------------------------------------

### --- Campaign Banner Tags:
# - (1) ?campaign=wmde_abc2017_bt1 - banner for Specific Task 1;
# - (2) ?campaign=wmde_abc2017_bt2 - banner for Specific Task 2;
# - (3) ?campaign=wmde_abc2017_bt3 - banner for Specific Task 3;
# - (4) ?campaign=wmde_abc2017_gib_lp - banner for the General Invitation 
# - which leads to the Landing Page upon click;
# - (5) ?campaign=wmde_abc2017_gib_rg - banner for the General Invitation 
# which leads directly to Registration upon click.

### --- from wmf.webrequest, run the following script on stat 1005
### --- to collect banner impressions
### --- Rscript /home/goransm/RScripts/abc2017/abc2017_PROD_BannerImpressions.R

### --- HiveQL for everything with ?campaign like "wmde_abc2017" 
### --- and then look for the desired tags.

### --- loop over date range, create query, fetch, and store
# dateRange <- seq(from = as.Date(startDate),
#                  to = as.Date(endDate),
#                  by = 'day')
# dateRange <- as.character(dateRange)
# # - set outDir
# outDir <- bannerImpressiomnsDir
# # - store query dir:
# qDir <- bannerImpressiomnsDir
# setwd(qDir)
# # - set HiveQL query dir:
# for (i in 1:length(dateRange)) {
#   # - construct HiveQL query:
#   y <- as.numeric(strsplit(dateRange[i], split = "-")[[1]][1])
#   m <- as.numeric(strsplit(dateRange[i], split = "-")[[1]][2])
#   d <- as.numeric(strsplit(dateRange[i], split = "-")[[1]][3])
#   q <- paste(
#     "USE wmf;
#     SELECT uri_query FROM webrequest
#     WHERE uri_host = 'de.wikipedia.org'
#     AND uri_path = '/beacon/impression'
#     AND year = ", y,
#     " AND month = ", m,
#     " AND day = ", d,
#     sep = "")
#   # - write hql
#   write(q, 'abc2017_BannerImpressions.hql')
#   # - prepare output file:
#   fileName <- "abc2017_BannerImpressions_"
#   fileName <- paste0(fileName, dateRange[i], ".tsv")
#   fileName <- paste0(outDir, "/", fileName)
#   # - execute hql script:
#   hiveArgs <-
#     'beeline -f'
#   hiveInput <- paste0('abc2017_BannerImpressions.hql > ',
#                       fileName)
#   # - command:
#   hiveCommand <- paste(hiveArgs, hiveInput)
#   system(command = hiveCommand, wait = TRUE)
# }

### -----------------------------------------------------------------------------
### 2. Banner Clicks and Landing Page Views
### -----------------------------------------------------------------------------

### --- campaign URL
# - https://de.wikipedia.org/wiki/Wikipedia:Wikimedia_Deutschland/Entdeckungen-sortieren?campaign=wmde2017summer1&wmdesource=bannerclick

### --- Campaign Banner Tags:
# - (1) ?campaign=wmde_abc2017_bt1 - banner for Specific Task 1;
# - (2) ?campaign=wmde_abc2017_bt2 - banner for Specific Task 2;
# - (3) ?campaign=wmde_abc2017_bt3 - banner for Specific Task 3;
# - (4) ?campaign=wmde_abc2017_gib_lp - banner for the General Invitation 
# - which leads to the Landing Page upon click;
# - (5) ?campaign=wmde_abc2017_gib_rg - banner for the General Invitation 
# which leads directly to Registration upon click.

### --- Landing/Registration pages:
# - Landing Page, Specific Tasks, Banner bt1:
# - https://de.wikipedia.org/wiki/Wikipedia:Wikimedia_Deutschland/Fehler_korrigieren?campaign=wmde_abc2017_bt1
# - Landing Page, Specific Tasks, Banner bt2:
# - https://de.wikipedia.org/wiki/Wikipedia:Wikimedia_Deutschland/Fehler_korrigieren?campaign=wmde_abc2017_bt2
# - Landing Page, Specific Tasks, Banner bt3:
# - https://de.wikipedia.org/wiki/Wikipedia:Wikimedia_Deutschland/Fehler_korrigieren?campaign=wmde_abc2017_bt3
# - Landing Page, General, Banner gib_lp
# - https://de.wikipedia.org/wiki/Wikipedia:Wikimedia_Deutschland/Mach_mit?campaign=wmde_abc2017_gib_lp
# - Registration Page, banner gib_rg
# - https://de.wikipedia.org/wiki/Spezial:Benutzerkonto_anlegen?campaign=wmde_abc2017_gib_rg

# campaignQuery <- c('campaign=wmde_abc2017_bt1&wmdesource=bannerclick',
#                    'campaign=wmde_abc2017_bt2&wmdesource=bannerclick',
#                    'campaign=wmde_abc2017_bt3&wmdesource=bannerclick',
#                    'campaign=wmde_abc2017_gib_lp&wmdesource=bannerclick',
#                    'campaign=wmde_abc2017_gib_rg&wmdesource=bannerclick')

### --- loop over date range, create query, fetch, and store
dateRange <- seq(from = as.Date(startDate),
                 to = as.Date(endDate),
                 by = 'day')
dateRange <- as.character(dateRange)
# - set outDir
outDir <- bannerClicksDir
# - store query dir:
qDir <- bannerClicksDir
setwd(qDir)
# - set HiveQL query dir:
for (i in 1:length(dateRange)) {
  # - construct HiveQL query:
  y <- as.numeric(strsplit(dateRange[i], split = "-")[[1]][1])
  m <- as.numeric(strsplit(dateRange[i], split = "-")[[1]][2])
  d <- as.numeric(strsplit(dateRange[i], split = "-")[[1]][3])
  q <- paste(
    "USE wmf;
    SELECT uri_path, uri_query, referer FROM webrequest
    WHERE (uri_host = 'de.wikipedia.org'
    AND (uri_path = '/wiki/Wikipedia:Wikimedia_Deutschland/Fehler_korrigieren' OR uri_path = '/wiki/Wikipedia:Wikimedia_Deutschland/Mach_mit' OR uri_path = '/wiki/Spezial:Benutzerkonto_anlegen')
    AND year = ", y,
    " AND month = ", m,
    " AND day = ", d, ");",
    sep = "")
  # - write hql
  write(q, 'abc2017_BannerClicks.hql')
  # - prepare output file:
  fileName <- "abc2017_BannerClicks_"
  fileName <- paste0(fileName, dateRange[i], ".tsv")
  fileName <- paste0(outDir, "/", fileName)
  # - execute hql script:
  hiveArgs <-
    'beeline -f'
  hiveInput <- paste0('abc2017_BannerClicks.hql > ',
                      fileName)
  # - command:
  hiveCommand <- paste(hiveArgs, hiveInput)
  system(command = hiveCommand, wait = TRUE)
}

### --- Wrangle this dataset:

### --- Landing pages:
specTaskPage <- '/wiki/Wikipedia:Wikimedia_Deutschland/Fehler_korrigieren'
genInvPage <- '/wiki/Wikipedia:Wikimedia_Deutschland/Mach_mit'
regPage <- '/wiki/Spezial:Benutzerkonto_anlegen'

### --- Banner tags:
specTaskBanner1 <- '?campaign=wmde_abc2017_bt1'
specTaskBanner2 <- '?campaign=wmde_abc2017_bt2'
specTaskBanner3 <- '?campaign=wmde_abc2017_bt3'
genInvPage_rg <- '?campaign=wmde_abc2017_gib_rg'
genInvPage_lp <- '?campaign=wmde_abc2017_gib_lp'

### --- Dataset:
# - count non-empty files:
c <- 0
lF <- list.files()
lF <- lF[grepl('.tsv', lF, fixed = T)]
dataSet <- list()
for (i in 1:length(lF)) {
  dS <- readLines(lF[i], n = -1)
  dS <- dS[8:(length(dS)-2)]
  if (length(dS > 0)) {
    c <- c + 1
    dS <- lapply(dS, function(x) {
      dat <- strsplit(x, split = "\t", fixed = T)[[1]]
      data.frame(page = dat[1], banner = dat[2], refer = dat[3], stringsAsFactors = F)
    })
  }
  dS <- rbindlist(dS)
  dS$date <- strsplit(
    strsplit(lF[i], split = "_", fixed = T)[[1]][3],
    split = ".",
    fixed = T)[[1]][1]
  dataSet[[c]] <- dS
  rm(dS); gc()
}
dataSet <- rbindlist(dataSet)
# - replace values:
dataSet$page <- sapply(dataSet$page, function(x) {
  strsplit(x, split = "/", fixed = T)[[1]][length(strsplit(x, split = "/", fixed = T)[[1]])]
})
dataSet$banner[which(dataSet$banner %in% specTaskBanner1)] <- 'BT1'
dataSet$banner[which(dataSet$banner %in% specTaskBanner2)] <- 'BT2'
dataSet$banner[which(dataSet$banner %in% specTaskBanner3)] <- 'BT3'
dataSet$banner[which(dataSet$banner %in% genInvPage_rg)] <- 'GIP_RG'
dataSet$banner[which(dataSet$banner %in% genInvPage_lp)] <- 'GIP_LP'
dataSet$banner <- paste(dataSet$banner, "_click", sep = "")
dataSet$banner[which(!(dataSet$banner %in% c('BT1_click', 'BT2_click', 'BT3_click', 'GIP_RG_click', 'GIP_LP_click')))] <- 
  'Other'
colnames(dataSet) <- c('Page', 'Source', 'Referer', 'Date')
dataSet$Source[dataSet$Page %in% 'Spezial:Benutzerkonto_anlegen' & dataSet$Source == 'Other'] <- 
  str_extract(dataSet$Referer[dataSet$Page %in% 'Spezial:Benutzerkonto_anlegen' & dataSet$Source == 'Other'],
              "campaign=wmde_abc(.)+$")
dataSet$Source[dataSet$Page %in% 'Spezial:Benutzerkonto_anlegen' & grepl("wmde_abc2017_bt1", dataSet$Source)] <- "Fehler_korrigieren_BT1"
dataSet$Source[dataSet$Page %in% 'Spezial:Benutzerkonto_anlegen' & grepl("wmde_abc2017_bt2", dataSet$Source)] <- "Fehler_korrigieren_BT2"
dataSet$Source[dataSet$Page %in% 'Spezial:Benutzerkonto_anlegen' & grepl("wmde_abc2017_bt3", dataSet$Source)] <- "Fehler_korrigieren_BT3"
dataSet$Source[dataSet$Page %in% 'Spezial:Benutzerkonto_anlegen' & grepl("wmde_abc2017_gib_rg", dataSet$Source)] <- "GIP_RG_click"
dataSet$Source[dataSet$Page %in% 'Spezial:Benutzerkonto_anlegen' & grepl("wmde_abc2017_gib_lp", dataSet$Source)] <- "Mach_mit"
dataSet$Source[dataSet$Page %in% 'Spezial:Benutzerkonto_anlegen' & dataSet$Referer %in% '-'] <- "Unknown"
dataSet$Source[dataSet$Page %in% 'Mach_mit' & dataSet$Referer %in% '-'] <- "Unknown"
dataSet$Source[dataSet$Page %in% 'Fehler_korrigieren' & dataSet$Referer %in% '-'] <- "Unknown"
dataSet$Source[is.na(dataSet$Source)] <- 'Other'
dataSet$Referer <- NULL

### --- store abc_BannerClicksPageViews_Update.csv
setwd(dailyUpdateDir)
write.csv(dataSet, file = "abc_BannerClicksPageViews_Update.csv")

### -----------------------------------------------------------------------------
### 3. User Registration Data
### -----------------------------------------------------------------------------

# - ServerSideAccountCreation_5487345
qCommand <- "mysql --defaults-file=/etc/mysql/conf.d/analytics-research-client.cnf -h analytics-store.eqiad.wmnet -A -e \"select * from log.ServerSideAccountCreation_5487345 where ((webHost = 'de.wikipedia.org') and (timestamp >= 20170920000000));\" > /home/goransm/_miscWMDE/abc2017_DataOUT/abc2017_OfficialDatasets/abc2017_DailyUpdate/abc2017_userRegistrations.tsv"
system(command = qCommand, wait = TRUE)

### -----------------------------------------------------------------------------
### 4. Guided Tour Data
### -----------------------------------------------------------------------------

### -----------------------------------------------------------------------------
### 5. User Edits Data
### -----------------------------------------------------------------------------

1. Campaign Banners

This section presents all data and statistics on the campaign relevant banners.

1.2.0 The Dataset

dataSet <- read.csv(paste('./_dailyUpdateDATA/', 'abc_BannerClicksPageViews_Update.csv', sep = ""),
                    header = T,
                    check.names = F,
                    row.names = 1,
                    stringsAsFactors = F)

1.2.1 Landing Pages: Referers

The following charts represents the breakdown of referers (i.e. sources) for the campaign pages: one registration page, and two landing pages.

### --- Banner clicks and Landing Page Views
# - Table Report
tableSet <- dataSet %>%
  dplyr::filter(!(Source %in% 'Other' | Source %in% 'Unknown')) %>% 
  dplyr::group_by(Page, Source, Date) %>% 
  dplyr::summarise(Count = n()) %>% 
  dplyr::arrange(Date, Page, Source)
# - Chart
chartCols <- brewer.pal(8, 'Set2')
ggplot(tableSet, aes(x = Page,
                    y = Count,
                    group = Source,
                    color = Source,
                    fill = Source,
                    label = Count)) +
  geom_bar(stat = "identity", 
           position = "dodge", 
           width = .5) +
  scale_fill_manual("legend", values = chartCols) +
  scale_color_manual("legend", values = chartCols) +
  ggtitle('Autumn Banner Campaign 2017:\nBreakdown of Landing Page Views sources') +
  theme_minimal() + 
  theme(axis.text.x = element_text(angle = 90, size = 8, hjust = 1)) +
  theme(plot.title = element_text(size = 10)) +
  theme(legend.title = element_blank()) +
  theme(panel.grid.major.x = element_blank()) +
  theme(panel.grid.minor.x = element_blank()) +
  theme(panel.background = element_blank())

1.2.2 Landing Pages: Referer Breakdown

The following three pie charts present a breakdown of referers (i.e. sources) for the Campaign pages (two landing pages and one registration page.

### --- Page Views: Sources
# - Spezial:Benutzerkonto_anlegen
pageSource <- dataSet %>% 
  dplyr::filter(!(Source %in% 'Other' | Source %in% 'Unknown')) %>%
  dplyr::count(Page, Source) %>%
  dplyr::group_by(Page) %>% 
  dplyr::mutate(Percent = n/sum(n))
pageSource$Percent <- paste(round(pageSource$Percent*100, 2), "%", sep = "")
pageSourcePlot <- filter(pageSource, Page %in% 'Spezial:Benutzerkonto_anlegen')
ggplot(pageSourcePlot, aes(x = '',
                           y = n,
                           color = Source,
                           fill = Source,
                           label = Percent)) +
  geom_bar(aes(x = '',
               y = n,
               color = Source,
               fill = Source), 
           stat = "identity", 
           width = 1) +
  coord_polar("y", start = 0) +
  geom_text(aes(x = 1),
            colour = "white",
            fontface = "bold",
            position = position_stack(vjust = 0.5),
            size = 3,
            show.legend = F) +
  scale_fill_manual("legend", values = chartCols) +
  scale_color_manual("legend", values = chartCols) +
  ggtitle('Autumn Banner Campaign 2017:\nPage Views Sources for Spezial:Benutzerkonto_anlegen') +
  xlab("Outter = Count") + ylab("") +
  theme_minimal() + 
  # theme(axis.text.x = element_blank()) +
  theme(plot.title = element_text(size = 10)) +
  theme(legend.title = element_blank()) +
  theme(panel.grid.major.y = element_blank()) +
  theme(panel.grid.minor.y = element_blank())

# - Fehler_korrigieren
pageSource <- dataSet %>% 
  dplyr::filter(!(Source %in% 'Other' | Source %in% 'Unknown')) %>%
  dplyr::count(Page, Source) %>%
  dplyr::group_by(Page) %>% 
  dplyr::mutate(Percent = n/sum(n))
pageSource$Percent <- paste(round(pageSource$Percent*100, 2), "%", sep = "")
pageSourcePlot <- filter(pageSource, Page %in% 'Fehler_korrigieren')
ggplot(pageSourcePlot, aes(x = '',
                           y = n,
                           color = Source,
                           fill = Source,
                           label = Percent)) +
  geom_bar(aes(x = '',
               y = n,
               color = Source,
               fill = Source), 
           stat = "identity", 
           width = 1) +
  coord_polar("y", start = 0) +
  geom_text(aes(x = 1),
            colour = "white",
            fontface = "bold",
            position = position_stack(vjust = 0.5),
            size = 3,
            show.legend = F) +
  scale_fill_manual("legend", values = chartCols) +
  scale_color_manual("legend", values = chartCols) +
  ggtitle('Autumn Banner Campaign 2017:\nPage Views Sources for Fehler_korrigieren') +
  xlab("Outter = Count") + ylab("") +
  theme_minimal() + 
  # theme(axis.text.x = element_blank()) +
  theme(plot.title = element_text(size = 10)) +
  theme(legend.title = element_blank()) +
  theme(panel.grid.major.y = element_blank()) +
  theme(panel.grid.minor.y = element_blank()) +
  theme(panel.background = element_blank())

# - Mach_mit
pageSource <- dataSet %>% 
  dplyr::filter(!(Source %in% 'Other' | Source %in% 'Unknown')) %>%
  dplyr::count(Page, Source) %>%
  dplyr::group_by(Page) %>% 
  dplyr::mutate(Percent = n/sum(n))
pageSource$Percent <- paste(round(pageSource$Percent*100, 2), "%", sep = "")
pageSourcePlot <- filter(pageSource, Page %in% 'Mach_mit')
ggplot(pageSourcePlot, aes(x = '',
                           y = n,
                           color = Source,
                           fill = Source,
                           label = Percent)) +
  geom_bar(aes(x = '',
               y = n,
               color = Source,
               fill = Source), 
           stat = "identity", 
           width = 1) +
  coord_polar("y", start = 0) +
  geom_text(aes(x = 1),
            colour = "white",
            fontface = "bold",
            position = position_stack(vjust = 0.5),
            size = 3,
            show.legend = F) +
  scale_fill_manual("legend", values = chartCols) +
  scale_color_manual("legend", values = chartCols) +
  ggtitle('Autumn Banner Campaign 2017:\nPage Views Sources for Mach_mit') +
  xlab("Outter = Count") + ylab("") +
  theme_minimal() + 
  # theme(axis.text.x = element_blank()) +
  theme(plot.title = element_text(size = 10)) +
  theme(legend.title = element_blank()) +
  theme(panel.grid.major.y = element_blank()) +
  theme(panel.grid.minor.y = element_blank()) +
  theme(panel.background = element_blank())

1.2.4 Page Views: Campaign Total

The following chart presents the number of page views for the two landing pages and one registration page during the course of the campaign, and encompassing only page views generated from the campaign.

### --- Temporal Page Views
# - Chart
pagePlotSet <- dataSet %>% 
  dplyr::filter(!(Source %in% 'Other' | Source %in% 'Unknown')) %>%
  dplyr::select(Page, Date) %>%
  dplyr::group_by(Page, Date) %>% 
  dplyr::summarise(Count = n()) %>% 
  dplyr::arrange(Date)
ggplot(pagePlotSet, aes(x = Date,
                        y = Count,
                        group = Page,
                        color = Page,
                        fill = Page,
                        label = Count)) +
  geom_bar(stat = "identity", 
           position = "dodge", 
           width = .2) +
  scale_fill_manual("legend", values = chartCols) +
  scale_color_manual("legend", values = chartCols) +
  ggtitle('Autumn Banner Campaign 2017: Page Views') +
  theme_minimal() + 
  theme(axis.text.x = element_text(angle = 90, size = 8, hjust = 1)) +
  theme(plot.title = element_text(size = 10)) +
  theme(legend.title = element_blank()) +
  theme(panel.grid.major.x = element_blank()) +
  theme(panel.grid.minor.x = element_blank()) +
  theme(panel.background = element_blank())

1.2.4 Page Views/Banner Clicks Dataset

The Page column refers to either one of the two campaign landing pages or the registration page. The Source column encompasses both campaign banner clicks and campaign pages as referers of the Page. The Count data have a daily resolution.

### --- Full Dataset (Table Report)
datatable(tableSet)

2. Campaign User Registrations

2.1 Analyze User Registration Data

### --- Campaign User Registrations
lF <- list.files(path = "./_dailyUpdateDATA/")
lF <- lF[grepl('userRegistrations', lF, fixed = T)]
userReg <- read.table(paste("./userRegDATA/", lF, sep = ""),
                      sep = "\t",
                      header = T,
                      check.names = F,
                      stringsAsFactors = F)
EOF within quoted string
userReg$timestamp <- as.character(userReg$timestamp)
userReg$timestamp <- sapply(userReg$timestamp, function(x) {
  y <- substr(x, 1, 4)
  m <- substr(x, 5, 6)
  d <- substr(x, 7, 8)
  paste(y, m, d, sep = "-")
})
userReg <- userReg %>% 
  dplyr::select(id, event_userId, timestamp, event_isSelfMade, event_campaign) %>% 
  filter(event_isSelfMade == 1)
regPlotSet <- userReg %>% 
  dplyr::filter(event_isSelfMade == 1 & grepl("wmde_abc2017", event_campaign)) %>% 
  group_by(event_campaign, timestamp) %>% 
  summarise(Registrations = n()) %>% 
  arrange(timestamp)
colnames(regPlotSet) <- c('Campaign', 'Date', 'Registrations')
regPlotSet$Campaign <- sapply(regPlotSet$Campaign, function(x) {
  out <- toupper(strsplit(x, split = "_", fixed = T)[[1]][3])
})
ggplot(regPlotSet, aes(x = Date,
                       y = Registrations,
                       group = Campaign,
                       color = Campaign,
                       fill = Campaign,
                       label = Registrations)) +
  geom_bar(stat = "identity", 
           position = "dodge", 
           width = .2) +
  scale_fill_manual("legend", values = chartCols) +
  scale_color_manual("legend", values = chartCols) +
  ggtitle('Autumn Banner Campaign 2017: User Registrations') +
  theme_minimal() + 
  theme(axis.text.x = element_text(angle = 90, size = 8, hjust = 1)) +
  theme(plot.title = element_text(size = 10)) +
  theme(legend.title = element_blank()) +
  theme(panel.grid.major.x = element_blank()) +
  theme(panel.grid.minor.x = element_blank()) +
  theme(panel.background = element_blank())

3. Campaign Guided Tour

3.1 Collect Guided Tour Data

NOTE: the following code is not fully reproducible from this Report. The data are collected by running the script abc2017_PROD_GuidedTour.R on stat1005.eqiad.wmnet, collecting the data as .csv files, copying manually, and processing locally.

### --- NOTE:
# For the guided tours it would be great to have two numbers:
# 
#     Number of people who started the guided tour / completed the first step /and than did whatever (exited, or not)
#     Number of people who completed the guided tour


# log.GuidedTourExited_8690566
# https://meta.wikimedia.org/wiki/Schema:GuidedTourExited
# ALSO TAKE A LOOK AT: log.GuidedTourGuiderHidden_8690549
# ALSO TAKE A LOOK AT: https://meta.wikimedia.org/wiki/Schema:GuidedTourGuiderHidden

### 2.1 Collect User Registration Data
### --- Script: abc2017_PROD_GuidedTour.R
### --- the following runs on stat1005.eqiad.wmnet
### --- Rscript /home/goransm/RScripts/abc2017/abc2017_PROD_Registrations.R

# - ServerSideAccountCreation_5487345
qCommand <- "mysql --defaults-file=/etc/mysql/conf.d/analytics-research-client.cnf -h analytics-store.eqiad.wmnet -A -e \"select * from log.GuidedTourExited_8690566 where ((webHost = 'de.wikipedia.org') and (timestamp >= 20170920000000));\" > /home/goransm/_miscWMDE/abc2017_DataOUT/abc_test/abc2017_guidedTours.tsv"
system(command = qCommand, wait = TRUE)

3.2 Analyze Guided Tour Data

4. User Edits

5. Campaign Evaluation

5.1 Campaign Multi-Channel Attribution Model

5.2 Campaign Causal Impact

LS0tCnRpdGxlOiAnQXV0dW1uIEJhbm5lciBDYW1wYWlnbiAyMDE3OiBSZXBvcnQnCmF1dGhvcjogIkdvcmFuIFMuIE1pbG92YW5vdmljLCBEYXRhIEFuYWx5c3QsIFdNREUiCmRhdGU6ICJTZXB0ZW1iZXIvT2N0b2JlciwgMjAxNyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRoZW1lOiBzaW1wbGV4CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA0CiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA0Ci0tLQoKCioqTk9URToqKiBGZWVkYmFjayBzaG91bGQgYmUgc2VuZCB0byBgZ29yYW4ubWlsb3Zhbm92aWNfZXh0QHdpa2ltZWRpYS5kZWAuIAoKKipOT1RFOioqIFRoZSBjYW1wYWlnbiB3aWxsIGJlIHJ1biBmcm9tIC4uLiB0byAuLi4gb2YgT2N0b2JlciAyMDE3LgoKYGBge3IsIGVjaG8gPSBGLCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CiMjIyAtLS0gU2V0dXAKcm0obGlzdCA9IGxzKCkpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkocm1hcmtkb3duKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KERUKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KHpvbykKbGlicmFyeShDYXVzYWxJbXBhY3QpCmBgYAoKIyMgMC4gRGF0YSBBY3F1aXNpdG9uCgoqKk5PVEU6KiogdGhlIGZvbGxvd2luZyBjb2RlIGlzIG5vdCBmdWxseSByZXByb2R1Y2libGUgZnJvbSB0aGlzIFJlcG9ydC4gVGhlIGRhdGEgYXJlIGNvbGxlY3RlZCBieSBydW5uaW5nIHRoZSBzY3JpcHQgYGFiYzIwMTdfUFJPRF9PdmVyYWxsRGFpbHlVcGRhdGUuUmAgb24gc3RhdDEwMDUuZXFpYWQud21uZXQsIGNvbGxlY3RpbmcgdGhlIGRhdGEgYXMgYC50c3ZgIGFuZCBgLmNzdmAgZmlsZXMsIGNvcHlpbmcgbWFudWFsbHksIGFuZCBwcm9jZXNzaW5nIGxvY2FsbHkuIFJ1biBmcm9tIHN0YXQxMDA1IHN0YXQgYm94IGJ5IGV4ZWN1dGluZyBgUnNjcmlwdCAvaG9tZS9nb3JhbnNtL1JTY3JpcHRzL2FiYzIwMTcvYWJjMjAxN19QUk9EX092ZXJhbGxEYWlseVVwZGF0ZS5SYC4KCmBgYHtyLCBlY2hvID0gVCwgZXZhbCA9IEZ9CiMjIyAtLS0gU2NyaXB0OiBhYmMyMDE3X1BST0RfT3ZlcmFsbERhaWx5VXBkYXRlLlIKIyMjIC0tLSB0aGUgZm9sbG93aW5nIHJ1bnMgb24gc3RhdDEwMDUuZXFpYWQud21uZXQKIyMjIC0tLSBSc2NyaXB0IC9ob21lL2dvcmFuc20vUlNjcmlwdHMvYWJjMjAxNy9hYmMyMDE3X1BST0RfT3ZlcmFsbERhaWx5VXBkYXRlLlIKCiMjIyAtLS0gVGhlIHNjcmlwdCBjb2xsZWN0cyBhbmQgd3JhbmdsZXMgYWxsIGRhdGFzZXRzCiMjIyAtLS0gZm9yIHRoZSBXTURFIEF1dHVtbiBCYW5uZXIgQ2FtcGFpZ24gMjAxNy4KCiMjIyAtLS0gR29yYW4gUy4gTWlsb3Zhbm92aWMsIERhdGEgQW5hbHlzdCwgV01ERQojIyMgLS0tIFNlcHRlbWJlciAyNiwgMjAxNy4KCiMjIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIyMgMC4gU2V0dXAKIyMjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpybShsaXN0ID0gbHMoKSkKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KGRhdGEudGFibGUpCnN0YXJ0RGF0ZSA8LSAnMjAxNy0wOS0yMCcKZW5kRGF0ZSA8LSAnMjAxNy0wOS0yNicKYmFubmVySW1wcmVzc2lvbW5zRGlyIDwtICcvaG9tZS9nb3JhbnNtL19taXNjV01ERS9hYmMyMDE3X0RhdGFPVVQvYWJjMjAxN19PZmZpY2lhbERhdGFzZXRzL2FiYzIwMTdCYW5uZXJJbXByZXNzaW9ucy8nCmJhbm5lckNsaWNrc0RpciA8LSAnL2hvbWUvZ29yYW5zbS9fbWlzY1dNREUvYWJjMjAxN19EYXRhT1VUL2FiYzIwMTdfT2ZmaWNpYWxEYXRhc2V0cy9hYmMyMDE3QmFubmVyQ2xpY2tzTGFuZGluZ1BhZ2VzLycKdXNlclJlZ0RpciA8LSAnL2hvbWUvZ29yYW5zbS9fbWlzY1dNREUvYWJjMjAxN19EYXRhT1VUL2FiYzIwMTdfT2ZmaWNpYWxEYXRhc2V0cy9hYmMyMDE3VXNlclJlZy8nCmRhaWx5VXBkYXRlRGlyIDwtICcvaG9tZS9nb3JhbnNtL19taXNjV01ERS9hYmMyMDE3X0RhdGFPVVQvYWJjMjAxN19PZmZpY2lhbERhdGFzZXRzL2FiYzIwMTdfRGFpbHlVcGRhdGUvJyAKCiMjIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIyMgMS4gQmFubmVyIEltcHJlc3Npb25zCiMjIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIC0tLSBDYW1wYWlnbiBCYW5uZXIgVGFnczoKIyAtICgxKSA/Y2FtcGFpZ249d21kZV9hYmMyMDE3X2J0MSAtIGJhbm5lciBmb3IgU3BlY2lmaWMgVGFzayAxOwojIC0gKDIpID9jYW1wYWlnbj13bWRlX2FiYzIwMTdfYnQyIC0gYmFubmVyIGZvciBTcGVjaWZpYyBUYXNrIDI7CiMgLSAoMykgP2NhbXBhaWduPXdtZGVfYWJjMjAxN19idDMgLSBiYW5uZXIgZm9yIFNwZWNpZmljIFRhc2sgMzsKIyAtICg0KSA/Y2FtcGFpZ249d21kZV9hYmMyMDE3X2dpYl9scCAtIGJhbm5lciBmb3IgdGhlIEdlbmVyYWwgSW52aXRhdGlvbiAKIyAtIHdoaWNoIGxlYWRzIHRvIHRoZSBMYW5kaW5nIFBhZ2UgdXBvbiBjbGljazsKIyAtICg1KSA/Y2FtcGFpZ249d21kZV9hYmMyMDE3X2dpYl9yZyAtIGJhbm5lciBmb3IgdGhlIEdlbmVyYWwgSW52aXRhdGlvbiAKIyB3aGljaCBsZWFkcyBkaXJlY3RseSB0byBSZWdpc3RyYXRpb24gdXBvbiBjbGljay4KCiMjIyAtLS0gZnJvbSB3bWYud2VicmVxdWVzdCwgcnVuIHRoZSBmb2xsb3dpbmcgc2NyaXB0IG9uIHN0YXQgMTAwNQojIyMgLS0tIHRvIGNvbGxlY3QgYmFubmVyIGltcHJlc3Npb25zCiMjIyAtLS0gUnNjcmlwdCAvaG9tZS9nb3JhbnNtL1JTY3JpcHRzL2FiYzIwMTcvYWJjMjAxN19QUk9EX0Jhbm5lckltcHJlc3Npb25zLlIKCiMjIyAtLS0gSGl2ZVFMIGZvciBldmVyeXRoaW5nIHdpdGggP2NhbXBhaWduIGxpa2UgIndtZGVfYWJjMjAxNyIgCiMjIyAtLS0gYW5kIHRoZW4gbG9vayBmb3IgdGhlIGRlc2lyZWQgdGFncy4KCiMjIyAtLS0gbG9vcCBvdmVyIGRhdGUgcmFuZ2UsIGNyZWF0ZSBxdWVyeSwgZmV0Y2gsIGFuZCBzdG9yZQojIGRhdGVSYW5nZSA8LSBzZXEoZnJvbSA9IGFzLkRhdGUoc3RhcnREYXRlKSwKIyAgICAgICAgICAgICAgICAgIHRvID0gYXMuRGF0ZShlbmREYXRlKSwKIyAgICAgICAgICAgICAgICAgIGJ5ID0gJ2RheScpCiMgZGF0ZVJhbmdlIDwtIGFzLmNoYXJhY3RlcihkYXRlUmFuZ2UpCiMgIyAtIHNldCBvdXREaXIKIyBvdXREaXIgPC0gYmFubmVySW1wcmVzc2lvbW5zRGlyCiMgIyAtIHN0b3JlIHF1ZXJ5IGRpcjoKIyBxRGlyIDwtIGJhbm5lckltcHJlc3Npb21uc0RpcgojIHNldHdkKHFEaXIpCiMgIyAtIHNldCBIaXZlUUwgcXVlcnkgZGlyOgojIGZvciAoaSBpbiAxOmxlbmd0aChkYXRlUmFuZ2UpKSB7CiMgICAjIC0gY29uc3RydWN0IEhpdmVRTCBxdWVyeToKIyAgIHkgPC0gYXMubnVtZXJpYyhzdHJzcGxpdChkYXRlUmFuZ2VbaV0sIHNwbGl0ID0gIi0iKVtbMV1dWzFdKQojICAgbSA8LSBhcy5udW1lcmljKHN0cnNwbGl0KGRhdGVSYW5nZVtpXSwgc3BsaXQgPSAiLSIpW1sxXV1bMl0pCiMgICBkIDwtIGFzLm51bWVyaWMoc3Ryc3BsaXQoZGF0ZVJhbmdlW2ldLCBzcGxpdCA9ICItIilbWzFdXVszXSkKIyAgIHEgPC0gcGFzdGUoCiMgICAgICJVU0Ugd21mOwojICAgICBTRUxFQ1QgdXJpX3F1ZXJ5IEZST00gd2VicmVxdWVzdAojICAgICBXSEVSRSB1cmlfaG9zdCA9ICdkZS53aWtpcGVkaWEub3JnJwojICAgICBBTkQgdXJpX3BhdGggPSAnL2JlYWNvbi9pbXByZXNzaW9uJwojICAgICBBTkQgeWVhciA9ICIsIHksCiMgICAgICIgQU5EIG1vbnRoID0gIiwgbSwKIyAgICAgIiBBTkQgZGF5ID0gIiwgZCwKIyAgICAgc2VwID0gIiIpCiMgICAjIC0gd3JpdGUgaHFsCiMgICB3cml0ZShxLCAnYWJjMjAxN19CYW5uZXJJbXByZXNzaW9ucy5ocWwnKQojICAgIyAtIHByZXBhcmUgb3V0cHV0IGZpbGU6CiMgICBmaWxlTmFtZSA8LSAiYWJjMjAxN19CYW5uZXJJbXByZXNzaW9uc18iCiMgICBmaWxlTmFtZSA8LSBwYXN0ZTAoZmlsZU5hbWUsIGRhdGVSYW5nZVtpXSwgIi50c3YiKQojICAgZmlsZU5hbWUgPC0gcGFzdGUwKG91dERpciwgIi8iLCBmaWxlTmFtZSkKIyAgICMgLSBleGVjdXRlIGhxbCBzY3JpcHQ6CiMgICBoaXZlQXJncyA8LQojICAgICAnYmVlbGluZSAtZicKIyAgIGhpdmVJbnB1dCA8LSBwYXN0ZTAoJ2FiYzIwMTdfQmFubmVySW1wcmVzc2lvbnMuaHFsID4gJywKIyAgICAgICAgICAgICAgICAgICAgICAgZmlsZU5hbWUpCiMgICAjIC0gY29tbWFuZDoKIyAgIGhpdmVDb21tYW5kIDwtIHBhc3RlKGhpdmVBcmdzLCBoaXZlSW5wdXQpCiMgICBzeXN0ZW0oY29tbWFuZCA9IGhpdmVDb21tYW5kLCB3YWl0ID0gVFJVRSkKIyB9CgojIyMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyMjIDIuIEJhbm5lciBDbGlja3MgYW5kIExhbmRpbmcgUGFnZSBWaWV3cwojIyMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyAtLS0gY2FtcGFpZ24gVVJMCiMgLSBodHRwczovL2RlLndpa2lwZWRpYS5vcmcvd2lraS9XaWtpcGVkaWE6V2lraW1lZGlhX0RldXRzY2hsYW5kL0VudGRlY2t1bmdlbi1zb3J0aWVyZW4/Y2FtcGFpZ249d21kZTIwMTdzdW1tZXIxJndtZGVzb3VyY2U9YmFubmVyY2xpY2sKCiMjIyAtLS0gQ2FtcGFpZ24gQmFubmVyIFRhZ3M6CiMgLSAoMSkgP2NhbXBhaWduPXdtZGVfYWJjMjAxN19idDEgLSBiYW5uZXIgZm9yIFNwZWNpZmljIFRhc2sgMTsKIyAtICgyKSA/Y2FtcGFpZ249d21kZV9hYmMyMDE3X2J0MiAtIGJhbm5lciBmb3IgU3BlY2lmaWMgVGFzayAyOwojIC0gKDMpID9jYW1wYWlnbj13bWRlX2FiYzIwMTdfYnQzIC0gYmFubmVyIGZvciBTcGVjaWZpYyBUYXNrIDM7CiMgLSAoNCkgP2NhbXBhaWduPXdtZGVfYWJjMjAxN19naWJfbHAgLSBiYW5uZXIgZm9yIHRoZSBHZW5lcmFsIEludml0YXRpb24gCiMgLSB3aGljaCBsZWFkcyB0byB0aGUgTGFuZGluZyBQYWdlIHVwb24gY2xpY2s7CiMgLSAoNSkgP2NhbXBhaWduPXdtZGVfYWJjMjAxN19naWJfcmcgLSBiYW5uZXIgZm9yIHRoZSBHZW5lcmFsIEludml0YXRpb24gCiMgd2hpY2ggbGVhZHMgZGlyZWN0bHkgdG8gUmVnaXN0cmF0aW9uIHVwb24gY2xpY2suCgojIyMgLS0tIExhbmRpbmcvUmVnaXN0cmF0aW9uIHBhZ2VzOgojIC0gTGFuZGluZyBQYWdlLCBTcGVjaWZpYyBUYXNrcywgQmFubmVyIGJ0MToKIyAtIGh0dHBzOi8vZGUud2lraXBlZGlhLm9yZy93aWtpL1dpa2lwZWRpYTpXaWtpbWVkaWFfRGV1dHNjaGxhbmQvRmVobGVyX2tvcnJpZ2llcmVuP2NhbXBhaWduPXdtZGVfYWJjMjAxN19idDEKIyAtIExhbmRpbmcgUGFnZSwgU3BlY2lmaWMgVGFza3MsIEJhbm5lciBidDI6CiMgLSBodHRwczovL2RlLndpa2lwZWRpYS5vcmcvd2lraS9XaWtpcGVkaWE6V2lraW1lZGlhX0RldXRzY2hsYW5kL0ZlaGxlcl9rb3JyaWdpZXJlbj9jYW1wYWlnbj13bWRlX2FiYzIwMTdfYnQyCiMgLSBMYW5kaW5nIFBhZ2UsIFNwZWNpZmljIFRhc2tzLCBCYW5uZXIgYnQzOgojIC0gaHR0cHM6Ly9kZS53aWtpcGVkaWEub3JnL3dpa2kvV2lraXBlZGlhOldpa2ltZWRpYV9EZXV0c2NobGFuZC9GZWhsZXJfa29ycmlnaWVyZW4/Y2FtcGFpZ249d21kZV9hYmMyMDE3X2J0MwojIC0gTGFuZGluZyBQYWdlLCBHZW5lcmFsLCBCYW5uZXIgZ2liX2xwCiMgLSBodHRwczovL2RlLndpa2lwZWRpYS5vcmcvd2lraS9XaWtpcGVkaWE6V2lraW1lZGlhX0RldXRzY2hsYW5kL01hY2hfbWl0P2NhbXBhaWduPXdtZGVfYWJjMjAxN19naWJfbHAKIyAtIFJlZ2lzdHJhdGlvbiBQYWdlLCBiYW5uZXIgZ2liX3JnCiMgLSBodHRwczovL2RlLndpa2lwZWRpYS5vcmcvd2lraS9TcGV6aWFsOkJlbnV0emVya29udG9fYW5sZWdlbj9jYW1wYWlnbj13bWRlX2FiYzIwMTdfZ2liX3JnCgojIGNhbXBhaWduUXVlcnkgPC0gYygnY2FtcGFpZ249d21kZV9hYmMyMDE3X2J0MSZ3bWRlc291cmNlPWJhbm5lcmNsaWNrJywKIyAgICAgICAgICAgICAgICAgICAgJ2NhbXBhaWduPXdtZGVfYWJjMjAxN19idDImd21kZXNvdXJjZT1iYW5uZXJjbGljaycsCiMgICAgICAgICAgICAgICAgICAgICdjYW1wYWlnbj13bWRlX2FiYzIwMTdfYnQzJndtZGVzb3VyY2U9YmFubmVyY2xpY2snLAojICAgICAgICAgICAgICAgICAgICAnY2FtcGFpZ249d21kZV9hYmMyMDE3X2dpYl9scCZ3bWRlc291cmNlPWJhbm5lcmNsaWNrJywKIyAgICAgICAgICAgICAgICAgICAgJ2NhbXBhaWduPXdtZGVfYWJjMjAxN19naWJfcmcmd21kZXNvdXJjZT1iYW5uZXJjbGljaycpCgojIyMgLS0tIGxvb3Agb3ZlciBkYXRlIHJhbmdlLCBjcmVhdGUgcXVlcnksIGZldGNoLCBhbmQgc3RvcmUKZGF0ZVJhbmdlIDwtIHNlcShmcm9tID0gYXMuRGF0ZShzdGFydERhdGUpLAogICAgICAgICAgICAgICAgIHRvID0gYXMuRGF0ZShlbmREYXRlKSwKICAgICAgICAgICAgICAgICBieSA9ICdkYXknKQpkYXRlUmFuZ2UgPC0gYXMuY2hhcmFjdGVyKGRhdGVSYW5nZSkKIyAtIHNldCBvdXREaXIKb3V0RGlyIDwtIGJhbm5lckNsaWNrc0RpcgojIC0gc3RvcmUgcXVlcnkgZGlyOgpxRGlyIDwtIGJhbm5lckNsaWNrc0RpcgpzZXR3ZChxRGlyKQojIC0gc2V0IEhpdmVRTCBxdWVyeSBkaXI6CmZvciAoaSBpbiAxOmxlbmd0aChkYXRlUmFuZ2UpKSB7CiAgIyAtIGNvbnN0cnVjdCBIaXZlUUwgcXVlcnk6CiAgeSA8LSBhcy5udW1lcmljKHN0cnNwbGl0KGRhdGVSYW5nZVtpXSwgc3BsaXQgPSAiLSIpW1sxXV1bMV0pCiAgbSA8LSBhcy5udW1lcmljKHN0cnNwbGl0KGRhdGVSYW5nZVtpXSwgc3BsaXQgPSAiLSIpW1sxXV1bMl0pCiAgZCA8LSBhcy5udW1lcmljKHN0cnNwbGl0KGRhdGVSYW5nZVtpXSwgc3BsaXQgPSAiLSIpW1sxXV1bM10pCiAgcSA8LSBwYXN0ZSgKICAgICJVU0Ugd21mOwogICAgU0VMRUNUIHVyaV9wYXRoLCB1cmlfcXVlcnksIHJlZmVyZXIgRlJPTSB3ZWJyZXF1ZXN0CiAgICBXSEVSRSAodXJpX2hvc3QgPSAnZGUud2lraXBlZGlhLm9yZycKICAgIEFORCAodXJpX3BhdGggPSAnL3dpa2kvV2lraXBlZGlhOldpa2ltZWRpYV9EZXV0c2NobGFuZC9GZWhsZXJfa29ycmlnaWVyZW4nIE9SIHVyaV9wYXRoID0gJy93aWtpL1dpa2lwZWRpYTpXaWtpbWVkaWFfRGV1dHNjaGxhbmQvTWFjaF9taXQnIE9SIHVyaV9wYXRoID0gJy93aWtpL1NwZXppYWw6QmVudXR6ZXJrb250b19hbmxlZ2VuJykKICAgIEFORCB5ZWFyID0gIiwgeSwKICAgICIgQU5EIG1vbnRoID0gIiwgbSwKICAgICIgQU5EIGRheSA9ICIsIGQsICIpOyIsCiAgICBzZXAgPSAiIikKICAjIC0gd3JpdGUgaHFsCiAgd3JpdGUocSwgJ2FiYzIwMTdfQmFubmVyQ2xpY2tzLmhxbCcpCiAgIyAtIHByZXBhcmUgb3V0cHV0IGZpbGU6CiAgZmlsZU5hbWUgPC0gImFiYzIwMTdfQmFubmVyQ2xpY2tzXyIKICBmaWxlTmFtZSA8LSBwYXN0ZTAoZmlsZU5hbWUsIGRhdGVSYW5nZVtpXSwgIi50c3YiKQogIGZpbGVOYW1lIDwtIHBhc3RlMChvdXREaXIsICIvIiwgZmlsZU5hbWUpCiAgIyAtIGV4ZWN1dGUgaHFsIHNjcmlwdDoKICBoaXZlQXJncyA8LQogICAgJ2JlZWxpbmUgLWYnCiAgaGl2ZUlucHV0IDwtIHBhc3RlMCgnYWJjMjAxN19CYW5uZXJDbGlja3MuaHFsID4gJywKICAgICAgICAgICAgICAgICAgICAgIGZpbGVOYW1lKQogICMgLSBjb21tYW5kOgogIGhpdmVDb21tYW5kIDwtIHBhc3RlKGhpdmVBcmdzLCBoaXZlSW5wdXQpCiAgc3lzdGVtKGNvbW1hbmQgPSBoaXZlQ29tbWFuZCwgd2FpdCA9IFRSVUUpCn0KCiMjIyAtLS0gV3JhbmdsZSB0aGlzIGRhdGFzZXQ6CgojIyMgLS0tIExhbmRpbmcgcGFnZXM6CnNwZWNUYXNrUGFnZSA8LSAnL3dpa2kvV2lraXBlZGlhOldpa2ltZWRpYV9EZXV0c2NobGFuZC9GZWhsZXJfa29ycmlnaWVyZW4nCmdlbkludlBhZ2UgPC0gJy93aWtpL1dpa2lwZWRpYTpXaWtpbWVkaWFfRGV1dHNjaGxhbmQvTWFjaF9taXQnCnJlZ1BhZ2UgPC0gJy93aWtpL1NwZXppYWw6QmVudXR6ZXJrb250b19hbmxlZ2VuJwoKIyMjIC0tLSBCYW5uZXIgdGFnczoKc3BlY1Rhc2tCYW5uZXIxIDwtICc/Y2FtcGFpZ249d21kZV9hYmMyMDE3X2J0MScKc3BlY1Rhc2tCYW5uZXIyIDwtICc/Y2FtcGFpZ249d21kZV9hYmMyMDE3X2J0MicKc3BlY1Rhc2tCYW5uZXIzIDwtICc/Y2FtcGFpZ249d21kZV9hYmMyMDE3X2J0MycKZ2VuSW52UGFnZV9yZyA8LSAnP2NhbXBhaWduPXdtZGVfYWJjMjAxN19naWJfcmcnCmdlbkludlBhZ2VfbHAgPC0gJz9jYW1wYWlnbj13bWRlX2FiYzIwMTdfZ2liX2xwJwoKIyMjIC0tLSBEYXRhc2V0OgojIC0gY291bnQgbm9uLWVtcHR5IGZpbGVzOgpjIDwtIDAKbEYgPC0gbGlzdC5maWxlcygpCmxGIDwtIGxGW2dyZXBsKCcudHN2JywgbEYsIGZpeGVkID0gVCldCmRhdGFTZXQgPC0gbGlzdCgpCmZvciAoaSBpbiAxOmxlbmd0aChsRikpIHsKICBkUyA8LSByZWFkTGluZXMobEZbaV0sIG4gPSAtMSkKICBkUyA8LSBkU1s4OihsZW5ndGgoZFMpLTIpXQogIGlmIChsZW5ndGgoZFMgPiAwKSkgewogICAgYyA8LSBjICsgMQogICAgZFMgPC0gbGFwcGx5KGRTLCBmdW5jdGlvbih4KSB7CiAgICAgIGRhdCA8LSBzdHJzcGxpdCh4LCBzcGxpdCA9ICJcdCIsIGZpeGVkID0gVClbWzFdXQogICAgICBkYXRhLmZyYW1lKHBhZ2UgPSBkYXRbMV0sIGJhbm5lciA9IGRhdFsyXSwgcmVmZXIgPSBkYXRbM10sIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQogICAgfSkKICB9CiAgZFMgPC0gcmJpbmRsaXN0KGRTKQogIGRTJGRhdGUgPC0gc3Ryc3BsaXQoCiAgICBzdHJzcGxpdChsRltpXSwgc3BsaXQgPSAiXyIsIGZpeGVkID0gVClbWzFdXVszXSwKICAgIHNwbGl0ID0gIi4iLAogICAgZml4ZWQgPSBUKVtbMV1dWzFdCiAgZGF0YVNldFtbY11dIDwtIGRTCiAgcm0oZFMpOyBnYygpCn0KZGF0YVNldCA8LSByYmluZGxpc3QoZGF0YVNldCkKIyAtIHJlcGxhY2UgdmFsdWVzOgpkYXRhU2V0JHBhZ2UgPC0gc2FwcGx5KGRhdGFTZXQkcGFnZSwgZnVuY3Rpb24oeCkgewogIHN0cnNwbGl0KHgsIHNwbGl0ID0gIi8iLCBmaXhlZCA9IFQpW1sxXV1bbGVuZ3RoKHN0cnNwbGl0KHgsIHNwbGl0ID0gIi8iLCBmaXhlZCA9IFQpW1sxXV0pXQp9KQpkYXRhU2V0JGJhbm5lclt3aGljaChkYXRhU2V0JGJhbm5lciAlaW4lIHNwZWNUYXNrQmFubmVyMSldIDwtICdCVDEnCmRhdGFTZXQkYmFubmVyW3doaWNoKGRhdGFTZXQkYmFubmVyICVpbiUgc3BlY1Rhc2tCYW5uZXIyKV0gPC0gJ0JUMicKZGF0YVNldCRiYW5uZXJbd2hpY2goZGF0YVNldCRiYW5uZXIgJWluJSBzcGVjVGFza0Jhbm5lcjMpXSA8LSAnQlQzJwpkYXRhU2V0JGJhbm5lclt3aGljaChkYXRhU2V0JGJhbm5lciAlaW4lIGdlbkludlBhZ2VfcmcpXSA8LSAnR0lQX1JHJwpkYXRhU2V0JGJhbm5lclt3aGljaChkYXRhU2V0JGJhbm5lciAlaW4lIGdlbkludlBhZ2VfbHApXSA8LSAnR0lQX0xQJwpkYXRhU2V0JGJhbm5lciA8LSBwYXN0ZShkYXRhU2V0JGJhbm5lciwgIl9jbGljayIsIHNlcCA9ICIiKQpkYXRhU2V0JGJhbm5lclt3aGljaCghKGRhdGFTZXQkYmFubmVyICVpbiUgYygnQlQxX2NsaWNrJywgJ0JUMl9jbGljaycsICdCVDNfY2xpY2snLCAnR0lQX1JHX2NsaWNrJywgJ0dJUF9MUF9jbGljaycpKSldIDwtIAogICdPdGhlcicKY29sbmFtZXMoZGF0YVNldCkgPC0gYygnUGFnZScsICdTb3VyY2UnLCAnUmVmZXJlcicsICdEYXRlJykKZGF0YVNldCRTb3VyY2VbZGF0YVNldCRQYWdlICVpbiUgJ1NwZXppYWw6QmVudXR6ZXJrb250b19hbmxlZ2VuJyAmIGRhdGFTZXQkU291cmNlID09ICdPdGhlciddIDwtIAogIHN0cl9leHRyYWN0KGRhdGFTZXQkUmVmZXJlcltkYXRhU2V0JFBhZ2UgJWluJSAnU3BlemlhbDpCZW51dHplcmtvbnRvX2FubGVnZW4nICYgZGF0YVNldCRTb3VyY2UgPT0gJ090aGVyJ10sCiAgICAgICAgICAgICAgImNhbXBhaWduPXdtZGVfYWJjKC4pKyQiKQpkYXRhU2V0JFNvdXJjZVtkYXRhU2V0JFBhZ2UgJWluJSAnU3BlemlhbDpCZW51dHplcmtvbnRvX2FubGVnZW4nICYgZ3JlcGwoIndtZGVfYWJjMjAxN19idDEiLCBkYXRhU2V0JFNvdXJjZSldIDwtICJGZWhsZXJfa29ycmlnaWVyZW5fQlQxIgpkYXRhU2V0JFNvdXJjZVtkYXRhU2V0JFBhZ2UgJWluJSAnU3BlemlhbDpCZW51dHplcmtvbnRvX2FubGVnZW4nICYgZ3JlcGwoIndtZGVfYWJjMjAxN19idDIiLCBkYXRhU2V0JFNvdXJjZSldIDwtICJGZWhsZXJfa29ycmlnaWVyZW5fQlQyIgpkYXRhU2V0JFNvdXJjZVtkYXRhU2V0JFBhZ2UgJWluJSAnU3BlemlhbDpCZW51dHplcmtvbnRvX2FubGVnZW4nICYgZ3JlcGwoIndtZGVfYWJjMjAxN19idDMiLCBkYXRhU2V0JFNvdXJjZSldIDwtICJGZWhsZXJfa29ycmlnaWVyZW5fQlQzIgpkYXRhU2V0JFNvdXJjZVtkYXRhU2V0JFBhZ2UgJWluJSAnU3BlemlhbDpCZW51dHplcmtvbnRvX2FubGVnZW4nICYgZ3JlcGwoIndtZGVfYWJjMjAxN19naWJfcmciLCBkYXRhU2V0JFNvdXJjZSldIDwtICJHSVBfUkdfY2xpY2siCmRhdGFTZXQkU291cmNlW2RhdGFTZXQkUGFnZSAlaW4lICdTcGV6aWFsOkJlbnV0emVya29udG9fYW5sZWdlbicgJiBncmVwbCgid21kZV9hYmMyMDE3X2dpYl9scCIsIGRhdGFTZXQkU291cmNlKV0gPC0gIk1hY2hfbWl0IgpkYXRhU2V0JFNvdXJjZVtkYXRhU2V0JFBhZ2UgJWluJSAnU3BlemlhbDpCZW51dHplcmtvbnRvX2FubGVnZW4nICYgZGF0YVNldCRSZWZlcmVyICVpbiUgJy0nXSA8LSAiVW5rbm93biIKZGF0YVNldCRTb3VyY2VbZGF0YVNldCRQYWdlICVpbiUgJ01hY2hfbWl0JyAmIGRhdGFTZXQkUmVmZXJlciAlaW4lICctJ10gPC0gIlVua25vd24iCmRhdGFTZXQkU291cmNlW2RhdGFTZXQkUGFnZSAlaW4lICdGZWhsZXJfa29ycmlnaWVyZW4nICYgZGF0YVNldCRSZWZlcmVyICVpbiUgJy0nXSA8LSAiVW5rbm93biIKZGF0YVNldCRTb3VyY2VbaXMubmEoZGF0YVNldCRTb3VyY2UpXSA8LSAnT3RoZXInCmRhdGFTZXQkUmVmZXJlciA8LSBOVUxMCgojIyMgLS0tIHN0b3JlIGFiY19CYW5uZXJDbGlja3NQYWdlVmlld3NfVXBkYXRlLmNzdgpzZXR3ZChkYWlseVVwZGF0ZURpcikKd3JpdGUuY3N2KGRhdGFTZXQsIGZpbGUgPSAiYWJjX0Jhbm5lckNsaWNrc1BhZ2VWaWV3c19VcGRhdGUuY3N2IikKCiMjIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIyMgMy4gVXNlciBSZWdpc3RyYXRpb24gRGF0YQojIyMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgLSBTZXJ2ZXJTaWRlQWNjb3VudENyZWF0aW9uXzU0ODczNDUKcUNvbW1hbmQgPC0gIm15c3FsIC0tZGVmYXVsdHMtZmlsZT0vZXRjL215c3FsL2NvbmYuZC9hbmFseXRpY3MtcmVzZWFyY2gtY2xpZW50LmNuZiAtaCBhbmFseXRpY3Mtc3RvcmUuZXFpYWQud21uZXQgLUEgLWUgXCJzZWxlY3QgKiBmcm9tIGxvZy5TZXJ2ZXJTaWRlQWNjb3VudENyZWF0aW9uXzU0ODczNDUgd2hlcmUgKCh3ZWJIb3N0ID0gJ2RlLndpa2lwZWRpYS5vcmcnKSBhbmQgKHRpbWVzdGFtcCA+PSAyMDE3MDkyMDAwMDAwMCkpO1wiID4gL2hvbWUvZ29yYW5zbS9fbWlzY1dNREUvYWJjMjAxN19EYXRhT1VUL2FiYzIwMTdfT2ZmaWNpYWxEYXRhc2V0cy9hYmMyMDE3X0RhaWx5VXBkYXRlL2FiYzIwMTdfdXNlclJlZ2lzdHJhdGlvbnMudHN2IgpzeXN0ZW0oY29tbWFuZCA9IHFDb21tYW5kLCB3YWl0ID0gVFJVRSkKCiMjIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIyMgNC4gR3VpZGVkIFRvdXIgRGF0YQojIyMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIyMgNS4gVXNlciBFZGl0cyBEYXRhCiMjIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCgoKYGBgCgojIyAxLiBDYW1wYWlnbiBCYW5uZXJzCgpUaGlzIHNlY3Rpb24gcHJlc2VudHMgYWxsIGRhdGEgYW5kIHN0YXRpc3RpY3Mgb24gdGhlIGNhbXBhaWduIHJlbGV2YW50IGJhbm5lcnMuCgojIyMgMS4xIEJhbm5lciBJbXByZXNzaW9ucwoKYGBge3IgZWNobyA9IFQsIGV2YWwgPSBGfQojIyMgLS0tIGV4dHJhY3Qgb25seSBjYW1wYWlnbiByZWxldmFudCBkYXRhCiMgLSBjYW1wYWlnbiBiYW5uZXJzOgpCVDEgPC0gJ3dtZGVfYWJjMjAxN19idDEnCkJUMiA8LSAnd21kZV9hYmMyMDE3X2J0MicKQlQzIDwtICd3bWRlX2FiYzIwMTdfYnQzJwpHSVBfUkcgPC0gJ3dtZGVfYWJjMjAxN19naWJfcmcnCkdJUF9MUCA8LSAnd21kZV9hYmMyMDE3X2dpYl9scCcKIyAtIGNvdW50IG5vbi1lbXB0eSBmaWxlczoKYyA8LSAwCmxGIDwtIGxpc3QuZmlsZXMocGF0aCA9ICIuL19kYWlseVVwZGF0ZURBVEEvIikKbEYgPC0gbEZbZ3JlcGwoJy50c3YnLCBsRiwgZml4ZWQgPSBUKV0KZGF0YVNldCA8LSBsaXN0KCkKZm9yIChpIGluIDE6bGVuZ3RoKGxGKSkgewogIGRTIDwtIHJlYWRMaW5lcyhwYXN0ZSgiLi9fZGFpbHlVcGRhdGVEQVRBLyIsbEZbaV0sIHNlcCA9ICIiKSwgbiA9IC0xKQogIGRTIDwtIGRTWzg6bGVuZ3RoKGRTKV0KICB3QyA8LSB1bm5hbWUoc2FwcGx5KGRTLCBmdW5jdGlvbih4KSB7CiAgICBncmVwbChwYXN0ZShjKEJUMSwgQlQyLCBCVDMsIEdJUF9SRywgR0lQX0xQKSwgc2VwID0gIiIsIGNvbGxhcHNlID0gInwiKSwgeCkKICB9KSkKICBpZiAobGVuZ3RoKHdoaWNoKHdDKSA+IDApKSB7CiAgICBjIDwtIGMgKyAxCiAgICBkUyA8LSBkU1t3Q10KICAgIHJtKHdDKTsgZ2MoKQogICAgZFMgPC0gZGF0YS5mcmFtZShxdWVyeSA9IGRTLCBzdHJpbmdzQXNGYWN0b3JzID0gRikKICAgIGRTJGRhdGUgPC0gc3Ryc3BsaXQoCiAgICAgIHN0cnNwbGl0KGxGW2ldLCBzcGxpdCA9ICJfIiwgZml4ZWQgPSBUKVtbMV1dWzRdLAogICAgICBzcGxpdCA9ICIuIiwKICAgICAgZml4ZWQgPSBUKVtbMV1dWzFdCiAgICBkYXRhU2V0W1tjXV0gPC0gZFMKICAgIH0KICBybShkUyk7IGdjKCkKfQpkYXRhU2V0IDwtIHJiaW5kbGlzdChkYXRhU2V0KQpkYXRhU2V0JGltcHJlc3NSYXRlIDwtIHNhcHBseShkYXRhU2V0JHF1ZXJ5LCBmdW5jdGlvbih4KSB7CiAgYXMubnVtZXJpYygKICAgIHN0cl9leHRyYWN0KAogICAgICBzdHJfZXh0cmFjdCh4LCBwYXR0ZXJuID0gInJlY29yZEltcHJlc3Npb25TYW1wbGVSYXRlPShbWzpkaWdpdDpdXXxcXC4pKyIpLAogICAgICBwYXR0ZXJuID0gIihbWzpkaWdpdDpdXXxcXC4pKyIpCiAgKQp9KQoKIyMjIC0tLSBDb3VudCBkYWlseSBiYW5uZXIgaW1wcmVzc2lvbnM6Cgprbml0cjo6a2FibGUoYmFubmVySW1wLCAKICAgICAgICAgICAgIGZvcm1hdCA9ICJodG1sIikgJT4lIAogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEYsIAogICAgICAgICAgICAgICAgcG9zaXRpb24gPSAibGVmdCIpCmJhbm5lckltcCA8LSBnYXRoZXIoYmFubmVySW1wLAogICAgICAgICAgICAgICAgICAgIGtleSA9IEJhbm5lciwKICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IEltcHJlc3Npb25zLAogICAgICAgICAgICAgICAgICAgIGBCYW5uZXIgQWA6YEJhbm5lciBCYCkKCiMgLSBWaXN1YWxpemUgdy4ge2dncGxvdDJ9CmNoYXJ0Q29scyA8LSBicmV3ZXIucGFsKDgsICdTZXQyJylbYygxLCAyLCAzLCA1LCA2KV0KZ2dwbG90KGJhbm5lckltcCwgYWVzKHggPSBEYXRlLAogICAgICAgICAgICAgICAgICAgICAgeSA9IEltcHJlc3Npb25zLAogICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBCYW5uZXIsCiAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IEJhbm5lciwKICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBCYW5uZXIsCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IEltcHJlc3Npb25zKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCAKICAgICAgICAgICBwb3NpdGlvbiA9ICJkb2RnZSIsIAogICAgICAgICAgIHdpZHRoID0gLjMpICsKICBnZW9tX2xhYmVsKGFlcyhmaWxsID0gQmFubmVyKSwgCiAgICAgICAgICAgICBjb2xvdXIgPSAid2hpdGUiLCAKICAgICAgICAgICAgIGZvbnRmYWNlID0gImJvbGQiLCAKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSwKICAgICAgICAgICAgIHNpemUgPSAyLCAKICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9maWxsX21hbnVhbCgibGVnZW5kIiwgdmFsdWVzID0gYygiQmFubmVyIEEiID0gIm9yYW5nZSIsICJCYW5uZXIgQiIgPSAiZmlyZWJyaWNrIikpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKCJsZWdlbmQiLCB2YWx1ZXMgPSBjKCJCYW5uZXIgQSIgPSAib3JhbmdlIiwgIkJhbm5lciBCIiA9ICJmaXJlYnJpY2siKSkgKwogIGdndGl0bGUoJ0F1dHVtbiBCYW5uZXIgQ2FtcGFpZ24gMjAxNzogQmFubmVyIEltcHJlc3Npb25zXG5Tb3VyY2U6IHdlYnJlcXVlc3QsIGhkZnMnKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgc2l6ZSA9IDgpKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCgojIyMgMS4yIEJhbm5lciBDbGlja3MgYW5kIExhbmRpbmcgUGFnZSBWaWV3cwoKIyMjIDEuMi4wIFRoZSBEYXRhc2V0CgpgYGB7ciBlY2hvID0gVH0KZGF0YVNldCA8LSByZWFkLmNzdihwYXN0ZSgnLi9fZGFpbHlVcGRhdGVEQVRBLycsICdhYmNfQmFubmVyQ2xpY2tzUGFnZVZpZXdzX1VwZGF0ZS5jc3YnLCBzZXAgPSAiIiksCiAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVCwKICAgICAgICAgICAgICAgICAgICBjaGVjay5uYW1lcyA9IEYsCiAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID0gMSwKICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRikKYGBgCgojIyMjIDEuMi4xIExhbmRpbmcgUGFnZXM6IFJlZmVyZXJzIAoKVGhlIGZvbGxvd2luZyBjaGFydHMgcmVwcmVzZW50cyB0aGUgYnJlYWtkb3duIG9mIHJlZmVyZXJzIChpLmUuIHNvdXJjZXMpIGZvciB0aGUgY2FtcGFpZ24gcGFnZXM6IG9uZSByZWdpc3RyYXRpb24gcGFnZSwgYW5kIHR3byBsYW5kaW5nIHBhZ2VzLgoKYGBge3IgZWNobyA9IFQsIHdhcm5pbmcgPSAnaGlkZScsIG1lc3NhZ2UgPSBGfQojIyMgLS0tIEJhbm5lciBjbGlja3MgYW5kIExhbmRpbmcgUGFnZSBWaWV3cwojIC0gVGFibGUgUmVwb3J0CnRhYmxlU2V0IDwtIGRhdGFTZXQgJT4lCiAgZHBseXI6OmZpbHRlcighKFNvdXJjZSAlaW4lICdPdGhlcicgfCBTb3VyY2UgJWluJSAnVW5rbm93bicpKSAlPiUgCiAgZHBseXI6Omdyb3VwX2J5KFBhZ2UsIFNvdXJjZSwgRGF0ZSkgJT4lIAogIGRwbHlyOjpzdW1tYXJpc2UoQ291bnQgPSBuKCkpICU+JSAKICBkcGx5cjo6YXJyYW5nZShEYXRlLCBQYWdlLCBTb3VyY2UpCgojIC0gQ2hhcnQKY2hhcnRDb2xzIDwtIGJyZXdlci5wYWwoOCwgJ1NldDInKQpnZ3Bsb3QodGFibGVTZXQsIGFlcyh4ID0gUGFnZSwKICAgICAgICAgICAgICAgICAgICB5ID0gQ291bnQsCiAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBTb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBTb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgZmlsbCA9IFNvdXJjZSwKICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IENvdW50KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCAKICAgICAgICAgICBwb3NpdGlvbiA9ICJkb2RnZSIsIAogICAgICAgICAgIHdpZHRoID0gLjUpICsKICBzY2FsZV9maWxsX21hbnVhbCgibGVnZW5kIiwgdmFsdWVzID0gY2hhcnRDb2xzKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKCJsZWdlbmQiLCB2YWx1ZXMgPSBjaGFydENvbHMpICsKICBnZ3RpdGxlKCdBdXR1bW4gQmFubmVyIENhbXBhaWduIDIwMTc6XG5CcmVha2Rvd24gb2YgTGFuZGluZyBQYWdlIFZpZXdzIHNvdXJjZXMnKSArCiAgdGhlbWVfbWluaW1hbCgpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgc2l6ZSA9IDgsIGhqdXN0ID0gMSkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyMgMS4yLjIgTGFuZGluZyBQYWdlczogUmVmZXJlciBCcmVha2Rvd24gCgpUaGUgZm9sbG93aW5nIHRocmVlIHBpZSBjaGFydHMgcHJlc2VudCBhIGJyZWFrZG93biBvZiByZWZlcmVycyAoaS5lLiBzb3VyY2VzKSBmb3IgdGhlIENhbXBhaWduIHBhZ2VzICh0d28gbGFuZGluZyBwYWdlcyBhbmQgb25lIHJlZ2lzdHJhdGlvbiBwYWdlLgoKYGBge3IgZWNobyA9IFQsIHdhcm5pbmcgPSAnaGlkZScsIG1lc3NhZ2UgPSBGfQojIyMgLS0tIFBhZ2UgVmlld3M6IFNvdXJjZXMKCiMgLSBTcGV6aWFsOkJlbnV0emVya29udG9fYW5sZWdlbgpwYWdlU291cmNlIDwtIGRhdGFTZXQgJT4lIAogIGRwbHlyOjpmaWx0ZXIoIShTb3VyY2UgJWluJSAnT3RoZXInIHwgU291cmNlICVpbiUgJ1Vua25vd24nKSkgJT4lCiAgZHBseXI6OmNvdW50KFBhZ2UsIFNvdXJjZSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KFBhZ2UpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBlcmNlbnQgPSBuL3N1bShuKSkKcGFnZVNvdXJjZSRQZXJjZW50IDwtIHBhc3RlKHJvdW5kKHBhZ2VTb3VyY2UkUGVyY2VudCoxMDAsIDIpLCAiJSIsIHNlcCA9ICIiKQpwYWdlU291cmNlUGxvdCA8LSBmaWx0ZXIocGFnZVNvdXJjZSwgUGFnZSAlaW4lICdTcGV6aWFsOkJlbnV0emVya29udG9fYW5sZWdlbicpCmdncGxvdChwYWdlU291cmNlUGxvdCwgYWVzKHggPSAnJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IG4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gU291cmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gU291cmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IFBlcmNlbnQpKSArCiAgZ2VvbV9iYXIoYWVzKHggPSAnJywKICAgICAgICAgICAgICAgeSA9IG4sCiAgICAgICAgICAgICAgIGNvbG9yID0gU291cmNlLAogICAgICAgICAgICAgICBmaWxsID0gU291cmNlKSwgCiAgICAgICAgICAgc3RhdCA9ICJpZGVudGl0eSIsIAogICAgICAgICAgIHdpZHRoID0gMSkgKwogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQgPSAwKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gMSksCiAgICAgICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIsCiAgICAgICAgICAgIGZvbnRmYWNlID0gImJvbGQiLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwKICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKCJsZWdlbmQiLCB2YWx1ZXMgPSBjaGFydENvbHMpICsKICBzY2FsZV9jb2xvcl9tYW51YWwoImxlZ2VuZCIsIHZhbHVlcyA9IGNoYXJ0Q29scykgKwogIGdndGl0bGUoJ0F1dHVtbiBCYW5uZXIgQ2FtcGFpZ24gMjAxNzpcblBhZ2UgVmlld3MgU291cmNlcyBmb3IgU3BlemlhbDpCZW51dHplcmtvbnRvX2FubGVnZW4nKSArCiAgeGxhYigiT3V0dGVyID0gQ291bnQiKSArIHlsYWIoIiIpICsKICB0aGVtZV9taW5pbWFsKCkgKyAKICAjIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpKQoKIyAtIEZlaGxlcl9rb3JyaWdpZXJlbgpwYWdlU291cmNlIDwtIGRhdGFTZXQgJT4lIAogIGRwbHlyOjpmaWx0ZXIoIShTb3VyY2UgJWluJSAnT3RoZXInIHwgU291cmNlICVpbiUgJ1Vua25vd24nKSkgJT4lCiAgZHBseXI6OmNvdW50KFBhZ2UsIFNvdXJjZSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KFBhZ2UpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBlcmNlbnQgPSBuL3N1bShuKSkKcGFnZVNvdXJjZSRQZXJjZW50IDwtIHBhc3RlKHJvdW5kKHBhZ2VTb3VyY2UkUGVyY2VudCoxMDAsIDIpLCAiJSIsIHNlcCA9ICIiKQpwYWdlU291cmNlUGxvdCA8LSBmaWx0ZXIocGFnZVNvdXJjZSwgUGFnZSAlaW4lICdGZWhsZXJfa29ycmlnaWVyZW4nKQpnZ3Bsb3QocGFnZVNvdXJjZVBsb3QsIGFlcyh4ID0gJycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBuLAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IFNvdXJjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IFNvdXJjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBQZXJjZW50KSkgKwogIGdlb21fYmFyKGFlcyh4ID0gJycsCiAgICAgICAgICAgICAgIHkgPSBuLAogICAgICAgICAgICAgICBjb2xvciA9IFNvdXJjZSwKICAgICAgICAgICAgICAgZmlsbCA9IFNvdXJjZSksIAogICAgICAgICAgIHN0YXQgPSAiaWRlbnRpdHkiLCAKICAgICAgICAgICB3aWR0aCA9IDEpICsKICBjb29yZF9wb2xhcigieSIsIHN0YXJ0ID0gMCkgKwogIGdlb21fdGV4dChhZXMoeCA9IDEpLAogICAgICAgICAgICBjb2xvdXIgPSAid2hpdGUiLAogICAgICAgICAgICBmb250ZmFjZSA9ICJib2xkIiwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksCiAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEYpICsKICBzY2FsZV9maWxsX21hbnVhbCgibGVnZW5kIiwgdmFsdWVzID0gY2hhcnRDb2xzKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKCJsZWdlbmQiLCB2YWx1ZXMgPSBjaGFydENvbHMpICsKICBnZ3RpdGxlKCdBdXR1bW4gQmFubmVyIENhbXBhaWduIDIwMTc6XG5QYWdlIFZpZXdzIFNvdXJjZXMgZm9yIEZlaGxlcl9rb3JyaWdpZXJlbicpICsKICB4bGFiKCJPdXR0ZXIgPSBDb3VudCIpICsgeWxhYigiIikgKwogIHRoZW1lX21pbmltYWwoKSArIAogICMgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKQoKIyAtIE1hY2hfbWl0CnBhZ2VTb3VyY2UgPC0gZGF0YVNldCAlPiUgCiAgZHBseXI6OmZpbHRlcighKFNvdXJjZSAlaW4lICdPdGhlcicgfCBTb3VyY2UgJWluJSAnVW5rbm93bicpKSAlPiUKICBkcGx5cjo6Y291bnQoUGFnZSwgU291cmNlKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoUGFnZSkgJT4lIAogIGRwbHlyOjptdXRhdGUoUGVyY2VudCA9IG4vc3VtKG4pKQpwYWdlU291cmNlJFBlcmNlbnQgPC0gcGFzdGUocm91bmQocGFnZVNvdXJjZSRQZXJjZW50KjEwMCwgMiksICIlIiwgc2VwID0gIiIpCnBhZ2VTb3VyY2VQbG90IDwtIGZpbHRlcihwYWdlU291cmNlLCBQYWdlICVpbiUgJ01hY2hfbWl0JykKZ2dwbG90KHBhZ2VTb3VyY2VQbG90LCBhZXMoeCA9ICcnLAogICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBTb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBTb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gUGVyY2VudCkpICsKICBnZW9tX2JhcihhZXMoeCA9ICcnLAogICAgICAgICAgICAgICB5ID0gbiwKICAgICAgICAgICAgICAgY29sb3IgPSBTb3VyY2UsCiAgICAgICAgICAgICAgIGZpbGwgPSBTb3VyY2UpLCAKICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IiwgCiAgICAgICAgICAgd2lkdGggPSAxKSArCiAgY29vcmRfcG9sYXIoInkiLCBzdGFydCA9IDApICsKICBnZW9tX3RleHQoYWVzKHggPSAxKSwKICAgICAgICAgICAgY29sb3VyID0gIndoaXRlIiwKICAgICAgICAgICAgZm9udGZhY2UgPSAiYm9sZCIsCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLAogICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSArCiAgc2NhbGVfZmlsbF9tYW51YWwoImxlZ2VuZCIsIHZhbHVlcyA9IGNoYXJ0Q29scykgKwogIHNjYWxlX2NvbG9yX21hbnVhbCgibGVnZW5kIiwgdmFsdWVzID0gY2hhcnRDb2xzKSArCiAgZ2d0aXRsZSgnQXV0dW1uIEJhbm5lciBDYW1wYWlnbiAyMDE3OlxuUGFnZSBWaWV3cyBTb3VyY2VzIGZvciBNYWNoX21pdCcpICsKICB4bGFiKCJPdXR0ZXIgPSBDb3VudCIpICsgeWxhYigiIikgKwogIHRoZW1lX21pbmltYWwoKSArIAogICMgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyMgMS4yLjMgQmFubmVyIENsaWNrczogQ2FtcGFpZ24gVG90YWwgIAoKVGhlIGZvbGxvd2luZyBjaGFydHMgcmVwcmVzZW50cyB0aGUgbnVtYmVyIG9mIGJhbm5lciBjbGlja3MgZm9yIGVhY2ggY2FtcGFpZ24gYmFubmVyIGR1cmluZyB0aGUgY291cnNlIG9mIHRoZSBjYW1wYWlnbi4KCmBgYHtyIGVjaG8gPSBULCB3YXJuaW5nID0gJ2hpZGUnLCBtZXNzYWdlID0gRn0KIyMjIC0tLSBUZW1wb3JhbCBCYW5uZXIgQ2xpY2tzCiMgLSBDaGFydApjaGFydENvbHMgPC0gYnJld2VyLnBhbCg4LCAnU2V0MicpW2MoMSwgMiwgMywgNSwgNildCmNsaWNrUGxvdFNldCA8LSBkYXRhU2V0ICU+JSAKICBkcGx5cjo6ZmlsdGVyKCEoU291cmNlICVpbiUgJ090aGVyJyB8IFNvdXJjZSAlaW4lICdVbmtub3duJykpICU+JQogIGRwbHlyOjpzZWxlY3QoU291cmNlLCBEYXRlKSAlPiUKICBkcGx5cjo6ZmlsdGVyKGdyZXBsKCJfY2xpY2siLCBTb3VyY2UpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoU291cmNlLCBEYXRlKSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShDb3VudCA9IG4oKSkgJT4lCiAgZHBseXI6OmFycmFuZ2UoRGF0ZSkKZ2dwbG90KGNsaWNrUGxvdFNldCwgYWVzKHggPSBEYXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgeSA9IENvdW50LAogICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBTb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IFNvdXJjZSwKICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBTb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IENvdW50KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCAKICAgICAgICAgICBwb3NpdGlvbiA9ICJkb2RnZSIsIAogICAgICAgICAgIHdpZHRoID0gLjUpICsKICBzY2FsZV9maWxsX21hbnVhbCgibGVnZW5kIiwgdmFsdWVzID0gY2hhcnRDb2xzKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKCJsZWdlbmQiLCB2YWx1ZXMgPSBjaGFydENvbHMpICsKICBnZ3RpdGxlKCdBdXR1bW4gQmFubmVyIENhbXBhaWduIDIwMTc6IEJhbm5lciBDbGlja3MnKSArCiAgdGhlbWVfbWluaW1hbCgpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgc2l6ZSA9IDgsIGhqdXN0ID0gMSkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyMgMS4yLjQgUGFnZSBWaWV3czogQ2FtcGFpZ24gVG90YWwgIAoKVGhlIGZvbGxvd2luZyBjaGFydCBwcmVzZW50cyB0aGUgbnVtYmVyIG9mIHBhZ2Ugdmlld3MgZm9yIHRoZSB0d28gbGFuZGluZyBwYWdlcyBhbmQgb25lIHJlZ2lzdHJhdGlvbiBwYWdlIGR1cmluZyB0aGUgY291cnNlIG9mIHRoZSBjYW1wYWlnbiwgYW5kIGVuY29tcGFzc2luZyBvbmx5IHBhZ2Ugdmlld3MgZ2VuZXJhdGVkIGZyb20gdGhlIGNhbXBhaWduLgoKYGBge3IgZWNobyA9IFQsIHdhcm5pbmcgPSAnaGlkZScsIG1lc3NhZ2UgPSBGfQojIyMgLS0tIFRlbXBvcmFsIFBhZ2UgVmlld3MKIyAtIENoYXJ0CnBhZ2VQbG90U2V0IDwtIGRhdGFTZXQgJT4lIAogIGRwbHlyOjpmaWx0ZXIoIShTb3VyY2UgJWluJSAnT3RoZXInIHwgU291cmNlICVpbiUgJ1Vua25vd24nKSkgJT4lCiAgZHBseXI6OnNlbGVjdChQYWdlLCBEYXRlKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoUGFnZSwgRGF0ZSkgJT4lIAogIGRwbHlyOjpzdW1tYXJpc2UoQ291bnQgPSBuKCkpICU+JSAKICBkcGx5cjo6YXJyYW5nZShEYXRlKQpnZ3Bsb3QocGFnZVBsb3RTZXQsIGFlcyh4ID0gRGF0ZSwKICAgICAgICAgICAgICAgICAgICAgICAgeSA9IENvdW50LAogICAgICAgICAgICAgICAgICAgICAgICBncm91cCA9IFBhZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gUGFnZSwKICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IFBhZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gQ291bnQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIAogICAgICAgICAgIHBvc2l0aW9uID0gImRvZGdlIiwgCiAgICAgICAgICAgd2lkdGggPSAuMikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKCJsZWdlbmQiLCB2YWx1ZXMgPSBjaGFydENvbHMpICsKICBzY2FsZV9jb2xvcl9tYW51YWwoImxlZ2VuZCIsIHZhbHVlcyA9IGNoYXJ0Q29scykgKwogIGdndGl0bGUoJ0F1dHVtbiBCYW5uZXIgQ2FtcGFpZ24gMjAxNzogUGFnZSBWaWV3cycpICsKICB0aGVtZV9taW5pbWFsKCkgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBzaXplID0gOCwgaGp1c3QgPSAxKSkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKIyMjIyAxLjIuNCBQYWdlIFZpZXdzL0Jhbm5lciBDbGlja3MgRGF0YXNldCAgCgpUaGUgYFBhZ2VgIGNvbHVtbiByZWZlcnMgdG8gZWl0aGVyIG9uZSBvZiB0aGUgdHdvIGNhbXBhaWduIGxhbmRpbmcgcGFnZXMgb3IgdGhlIHJlZ2lzdHJhdGlvbiBwYWdlLiBUaGUgYFNvdXJjZWAgY29sdW1uIGVuY29tcGFzc2VzIGJvdGggY2FtcGFpZ24gYmFubmVyIGNsaWNrcyBhbmQgY2FtcGFpZ24gcGFnZXMgYXMgcmVmZXJlcnMgb2YgdGhlIGBQYWdlYC4gVGhlIGBDb3VudGAgZGF0YSBoYXZlIGEgZGFpbHkgcmVzb2x1dGlvbi4gIAoKYGBge3IgZWNobyA9IFQsIHdhcm5pbmcgPSAnaGlkZScsIG1lc3NhZ2UgPSBGfQojIyMgLS0tIEZ1bGwgRGF0YXNldCAoVGFibGUgUmVwb3J0KQpkYXRhdGFibGUodGFibGVTZXQpCmBgYAoKIyMgMi4gQ2FtcGFpZ24gVXNlciBSZWdpc3RyYXRpb25zCgojIyMgMi4xIEFuYWx5emUgVXNlciBSZWdpc3RyYXRpb24gRGF0YQoKYGBge3IgZWNobyA9IFQsIHdhcm5pbmcgPSAnaGlkZScsIG1lc3NhZ2UgPSBGfQojIyMgLS0tIENhbXBhaWduIFVzZXIgUmVnaXN0cmF0aW9ucwpsRiA8LSBsaXN0LmZpbGVzKHBhdGggPSAiLi9fZGFpbHlVcGRhdGVEQVRBLyIpCmxGIDwtIGxGW2dyZXBsKCd1c2VyUmVnaXN0cmF0aW9ucycsIGxGLCBmaXhlZCA9IFQpXQp1c2VyUmVnIDwtIHJlYWQudGFibGUocGFzdGUoIi4vdXNlclJlZ0RBVEEvIiwgbEYsIHNlcCA9ICIiKSwKICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJcdCIsCiAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBULAogICAgICAgICAgICAgICAgICAgICAgY2hlY2submFtZXMgPSBGLAogICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEYpCnVzZXJSZWckdGltZXN0YW1wIDwtIGFzLmNoYXJhY3Rlcih1c2VyUmVnJHRpbWVzdGFtcCkKdXNlclJlZyR0aW1lc3RhbXAgPC0gc2FwcGx5KHVzZXJSZWckdGltZXN0YW1wLCBmdW5jdGlvbih4KSB7CiAgeSA8LSBzdWJzdHIoeCwgMSwgNCkKICBtIDwtIHN1YnN0cih4LCA1LCA2KQogIGQgPC0gc3Vic3RyKHgsIDcsIDgpCiAgcGFzdGUoeSwgbSwgZCwgc2VwID0gIi0iKQp9KQp1c2VyUmVnIDwtIHVzZXJSZWcgJT4lIAogIGRwbHlyOjpzZWxlY3QoaWQsIGV2ZW50X3VzZXJJZCwgdGltZXN0YW1wLCBldmVudF9pc1NlbGZNYWRlLCBldmVudF9jYW1wYWlnbikgJT4lIAogIGZpbHRlcihldmVudF9pc1NlbGZNYWRlID09IDEpCnJlZ1Bsb3RTZXQgPC0gdXNlclJlZyAlPiUgCiAgZHBseXI6OmZpbHRlcihldmVudF9pc1NlbGZNYWRlID09IDEgJiBncmVwbCgid21kZV9hYmMyMDE3IiwgZXZlbnRfY2FtcGFpZ24pKSAlPiUgCiAgZ3JvdXBfYnkoZXZlbnRfY2FtcGFpZ24sIHRpbWVzdGFtcCkgJT4lIAogIHN1bW1hcmlzZShSZWdpc3RyYXRpb25zID0gbigpKSAlPiUgCiAgYXJyYW5nZSh0aW1lc3RhbXApCmNvbG5hbWVzKHJlZ1Bsb3RTZXQpIDwtIGMoJ0NhbXBhaWduJywgJ0RhdGUnLCAnUmVnaXN0cmF0aW9ucycpCnJlZ1Bsb3RTZXQkQ2FtcGFpZ24gPC0gc2FwcGx5KHJlZ1Bsb3RTZXQkQ2FtcGFpZ24sIGZ1bmN0aW9uKHgpIHsKICBvdXQgPC0gdG91cHBlcihzdHJzcGxpdCh4LCBzcGxpdCA9ICJfIiwgZml4ZWQgPSBUKVtbMV1dWzNdKQp9KQpnZ3Bsb3QocmVnUGxvdFNldCwgYWVzKHggPSBEYXRlLAogICAgICAgICAgICAgICAgICAgICAgIHkgPSBSZWdpc3RyYXRpb25zLAogICAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gQ2FtcGFpZ24sCiAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBDYW1wYWlnbiwKICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gQ2FtcGFpZ24sCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBSZWdpc3RyYXRpb25zKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCAKICAgICAgICAgICBwb3NpdGlvbiA9ICJkb2RnZSIsIAogICAgICAgICAgIHdpZHRoID0gLjIpICsKICBzY2FsZV9maWxsX21hbnVhbCgibGVnZW5kIiwgdmFsdWVzID0gY2hhcnRDb2xzKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKCJsZWdlbmQiLCB2YWx1ZXMgPSBjaGFydENvbHMpICsKICBnZ3RpdGxlKCdBdXR1bW4gQmFubmVyIENhbXBhaWduIDIwMTc6IFVzZXIgUmVnaXN0cmF0aW9ucycpICsKICB0aGVtZV9taW5pbWFsKCkgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBzaXplID0gOCwgaGp1c3QgPSAxKSkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKIyMgMy4gQ2FtcGFpZ24gR3VpZGVkIFRvdXIKCiMjIyAzLjEgQ29sbGVjdCBHdWlkZWQgVG91ciBEYXRhCgoqKk5PVEU6KiogdGhlIGZvbGxvd2luZyBjb2RlIGlzIG5vdCBmdWxseSByZXByb2R1Y2libGUgZnJvbSB0aGlzIFJlcG9ydC4gVGhlIGRhdGEgYXJlIGNvbGxlY3RlZCBieSBydW5uaW5nIHRoZSBzY3JpcHQgYGFiYzIwMTdfUFJPRF9HdWlkZWRUb3VyLlJgIG9uIHN0YXQxMDA1LmVxaWFkLndtbmV0LCBjb2xsZWN0aW5nIHRoZSBkYXRhIGFzIGAuY3N2YCBmaWxlcywgY29weWluZyBtYW51YWxseSwgYW5kIHByb2Nlc3NpbmcgbG9jYWxseS4KCmBgYHtyIGVjaG8gPSBULCBldmFsID0gRn0KCiMjIyAtLS0gTk9URToKIyBGb3IgdGhlIGd1aWRlZCB0b3VycyBpdCB3b3VsZCBiZSBncmVhdCB0byBoYXZlIHR3byBudW1iZXJzOgojIAojICAgICBOdW1iZXIgb2YgcGVvcGxlIHdobyBzdGFydGVkIHRoZSBndWlkZWQgdG91ciAvIGNvbXBsZXRlZCB0aGUgZmlyc3Qgc3RlcCAvYW5kIHRoYW4gZGlkIHdoYXRldmVyIChleGl0ZWQsIG9yIG5vdCkKIyAgICAgTnVtYmVyIG9mIHBlb3BsZSB3aG8gY29tcGxldGVkIHRoZSBndWlkZWQgdG91cgoKCiMgbG9nLkd1aWRlZFRvdXJFeGl0ZWRfODY5MDU2NgojIGh0dHBzOi8vbWV0YS53aWtpbWVkaWEub3JnL3dpa2kvU2NoZW1hOkd1aWRlZFRvdXJFeGl0ZWQKIyBBTFNPIFRBS0UgQSBMT09LIEFUOiBsb2cuR3VpZGVkVG91ckd1aWRlckhpZGRlbl84NjkwNTQ5CiMgQUxTTyBUQUtFIEEgTE9PSyBBVDogaHR0cHM6Ly9tZXRhLndpa2ltZWRpYS5vcmcvd2lraS9TY2hlbWE6R3VpZGVkVG91ckd1aWRlckhpZGRlbgoKIyMjIDIuMSBDb2xsZWN0IFVzZXIgUmVnaXN0cmF0aW9uIERhdGEKIyMjIC0tLSBTY3JpcHQ6IGFiYzIwMTdfUFJPRF9HdWlkZWRUb3VyLlIKIyMjIC0tLSB0aGUgZm9sbG93aW5nIHJ1bnMgb24gc3RhdDEwMDUuZXFpYWQud21uZXQKIyMjIC0tLSBSc2NyaXB0IC9ob21lL2dvcmFuc20vUlNjcmlwdHMvYWJjMjAxNy9hYmMyMDE3X1BST0RfUmVnaXN0cmF0aW9ucy5SCgojIC0gU2VydmVyU2lkZUFjY291bnRDcmVhdGlvbl81NDg3MzQ1CnFDb21tYW5kIDwtICJteXNxbCAtLWRlZmF1bHRzLWZpbGU9L2V0Yy9teXNxbC9jb25mLmQvYW5hbHl0aWNzLXJlc2VhcmNoLWNsaWVudC5jbmYgLWggYW5hbHl0aWNzLXN0b3JlLmVxaWFkLndtbmV0IC1BIC1lIFwic2VsZWN0ICogZnJvbSBsb2cuR3VpZGVkVG91ckV4aXRlZF84NjkwNTY2IHdoZXJlICgod2ViSG9zdCA9ICdkZS53aWtpcGVkaWEub3JnJykgYW5kICh0aW1lc3RhbXAgPj0gMjAxNzA5MjAwMDAwMDApKTtcIiA+IC9ob21lL2dvcmFuc20vX21pc2NXTURFL2FiYzIwMTdfRGF0YU9VVC9hYmNfdGVzdC9hYmMyMDE3X2d1aWRlZFRvdXJzLnRzdiIKc3lzdGVtKGNvbW1hbmQgPSBxQ29tbWFuZCwgd2FpdCA9IFRSVUUpCmBgYAoKIyMjIDMuMiBBbmFseXplIEd1aWRlZCBUb3VyIERhdGEKCgojIyA0LiBVc2VyIEVkaXRzCgoKIyMgNS4gQ2FtcGFpZ24gRXZhbHVhdGlvbgoKCiMjIyA1LjEgQ2FtcGFpZ24gTXVsdGktQ2hhbm5lbCBBdHRyaWJ1dGlvbiBNb2RlbAoKCiMjIyA1LjIgQ2FtcGFpZ24gQ2F1c2FsIEltcGFjdAoKCgoKCg==