From timviecnhanh.com

#=======================================
#  Collect data from timviecnhanh.com
#=======================================

rm(list = ls()) # Clear workspace. 

library(rvest)
library(tidyverse)
library(lubridate)
library(stringi)

# Helper function: 

read_html_NE <- function(x) {
  
  Page.src <- try(read_html(x), silent = T)
  
  # Test if Page.src is erroneous: 
  
  if (class(Page.src)[1] == "try-error") {
    
    error.cond <- attr(Page.src, "condition")
    
    # Check if error condition contains “Timed out” phrase.  If regexpr cannot find a
    # match it returns -1: 
    
    timed.out <- regexpr("Timed out", error.cond, ignore.case = T) != -1
    
    # We want to continue only on “timed out” error: 
    
    if (timed.out == TRUE) {
      
      # Print information in the console: 
      
      print(paste(x, ": Timed out. Trying to reconnect in 1s. Please wait..."))
      Sys.sleep(1 / 5)
      
      return(html_NE(x))
    }
  }
  
  return(Page.src)
}

# Function extract job descriptions with a specific job link selected: 

get_job_timviecnhanh <- function(job_link) {
  
  job_link %>% 
    read_html_NE() -> content
  
  content %>% 
    html_nodes(xpath = '//*[@id="left-content"]/article/div[5]/div[1]') %>% 
    html_text(trim = TRUE) -> inf1
  
  inf1 %>% 
    stri_trans_general("Latin-ASCII") %>% 
    str_replace_all(" ", "") %>% 
    str_split("\n", simplify = TRUE) %>% 
    as.data.frame() %>% 
    select(V2, V6, V9, V14, V19) %>% 
    rename(salary = V2, exprience = V6, qualification = V9, location = V14, job_type = V19) -> df1
  
  content %>% 
    html_nodes(xpath = '//*[@id="left-content"]/article/div[5]/div[2]') %>% 
    html_text(trim = TRUE) -> inf2
  
  inf2 %>% 
    stri_trans_general("Latin-ASCII") %>% 
    str_replace_all(" ", "") %>% 
    str_split("\n", simplify = TRUE) %>% 
    as.data.frame() %>% 
    select(V2, V5, V8, V11, V14) %>% 
    rename(numbers_hired = V2, gender = V5, tinh_chat = V8, hinh_thuc = V11, thu_viec = V14) -> df2
  
  content %>% 
    html_nodes(xpath = '//*[@id="left-content"]/article/div[1]') %>% 
    html_text() %>% 
    stri_trans_general("Latin-ASCII") %>% 
    str_replace_all(" ", "") %>% 
    str_split("\n", simplify = TRUE) %>% 
    as.data.frame() %>% 
    pull(V3) -> update_and_Nviews 
  
  content %>% 
    html_nodes(xpath = '//*[@id="left-content"]/article/div[2]/h3') %>% 
    html_text() %>% 
    stri_trans_general("Latin-ASCII") %>%
    str_squish() -> firm_name
  
  content %>% 
    html_nodes(xpath = '//*[@id="left-content"]/article/div[2]/span') %>% 
    html_text() %>% 
    stri_trans_general("Latin-ASCII") %>%
    str_squish() -> firm_add
  
  content %>% 
    html_nodes(xpath = '//*[@id="left-content"]/article/table/tbody/tr[2]/td[2]/p') %>% 
    html_text() %>% 
    stri_trans_general("Latin-ASCII") %>%
    str_squish() -> requirement
  
  content %>% 
    html_nodes(xpath = '//*[@id="left-content"]/article/table/tbody/tr[3]') %>% 
    html_text() %>% 
    stri_trans_general("Latin-ASCII") %>%
    str_squish() -> benefits
  
  content %>% 
    html_nodes(xpath = '//*[@id="left-content"]/article/table/tbody/tr[4]') %>% 
    html_text() %>% 
    stri_trans_general("Latin-ASCII") %>%
    str_squish() -> deadline 
  
  bind_cols(df1, df2) %>% 
    mutate(update_and_Nviews = update_and_Nviews, 
           firm_name = firm_name,
           firm_add = firm_add, 
           requirement = requirement, 
           benefits = benefits, 
           deadline = deadline) %>% 
    mutate_all(function(x) {stri_trans_general(x, "Latin-ASCII")})-> df_info
  
  return(df_info %>% mutate(link = job_link, data_date = now() %>% as.character()))
  
}


# Function extracts all link from a web page: 

extract_all_links_page <- function(page_link) {
  page_link %>% 
    read_html_NE() %>% 
    html_nodes(xpath = '/html/body/section/div/div[1]/div/div/article/table/tbody') %>% 
    html_nodes("a") %>% 
    html_attr("href") %>% 
    return()
}

# Get all job links: 

lapply(paste0("https://www.timviecnhanh.com/vieclam/timkiem?&page=", 1:300), extract_all_links_page) -> all_links

all_links %>% unlist() %>% unique() -> all_job_links


# Collect descriptions for all jobs: 

n <- length(all_job_links)

list_job_info <- vector("list", n)


system.time(for(i in 1:n) {
  list_job_info[[i]] <- tryCatch(get_job_timviecnhanh(all_job_links[i]), error = function(e) {data.frame(link = all_job_links[i])})
  })


do.call("bind_rows", list_job_info) -> df_timviecnhanh

# Save data: 

today_time <- today() %>% as.character()
write_csv(df_timviecnhanh, paste0("df_timviecnhanh", today_time, ".csv"))

From vieclam24h.vn

#=======================================
#  Collect data from vieclam24h.vn
#=======================================

# Function extracts all link from a web page: 

extract_all_links_page <- function(page_link) {
  
  page_link %>% 
    read_html_NE() %>% 
    html_nodes(".font12+ .box_shadow .text_grey2") %>% 
    html_attr("href") -> pref_link
  
  paste0("https://vieclam24h.vn", pref_link) -> all_links
  
  return(all_links)
}



# Function extracts all descriptions for a specific job link: 

get_job_vieclam24h <- function(job_link) {

  job_link %>% 
    read_html() -> content
  
  content %>% 
    html_nodes(xpath = '//*[@id="block_body_main"]/div[2]/div[4]') %>% 
    html_text(trim = TRUE) -> inf1
  
  inf1 %>% 
    stri_trans_general("Latin-ASCII") %>% 
    str_replace_all(" ", "") %>% 
    str_replace_all("\n", "") %>% 
    str_split(":", simplify = TRUE) %>% 
    as.data.frame() %>% 
    select(salary = V2, experience = V3, qualificatiin = V4, 
           numbers_hired = V5, job_type = V6, location = V7, 
           hinh_thuc = V8, tinh_chat = V9, gender = V10, age_requirement = V11) -> df_info
  
  content %>% 
    html_nodes(xpath = '//*[@id="block_body_main"]/div[2]/div[2]/div[1]/span') %>% 
    html_text(trim = TRUE) -> deadline
  
  content %>% 
    html_nodes(xpath = '//*[@id="block_body_main"]/div[2]/div[2]/div[1]/p') %>% 
    html_text(trim = TRUE) -> update_and_Nviews
  
  content %>% 
    html_nodes(xpath = '//*[@id="block_body_main"]/div[2]/div[1]/div/p/a') %>% 
    html_text(trim = TRUE) -> firm_name 
  
  content %>% 
    html_nodes(xpath = '//*[@id="ttd_detail"]/div[2]/div[3]/p') %>% 
    html_text(trim = TRUE) -> firm_add
  
  content %>% 
    html_nodes(xpath = '//*[@id="ttd_detail"]/div[1]/div[2]/div[3]/p') %>% 
    html_text(trim = TRUE) -> requirement  
  
  content %>% 
    html_nodes(xpath = '//*[@id="ttd_detail"]/div[1]/div[2]/div[2]/p') %>% 
    html_text(trim = TRUE) -> benefits 
  
  df_info %>% 
    mutate(deadline = deadline, update_and_Nviews = update_and_Nviews, 
           firm_name = firm_name, firm_add = firm_add, requirement = requirement, 
           benefits = benefits, link = job_link, data_date = as.character(now())) -> job_info
  
  return(job_info %>% mutate_all(function(x) {stri_trans_general(x, "Latin-ASCII")}))
}


# Extract all job links: 

paste0("https://vieclam24h.vn/tim-kiem-viec-lam-nhanh/?hdn_tu_khoa=&hdn_nganh_nghe_cap1=&hdn_dia_diem=&key=ttv_nangcao&page=", 1:130) -> all_pages

lapply(all_pages, extract_all_links_page) %>% unlist() %>% unique() -> list_all_job_links

# Collect descriptions for all jobs: 

n <- length(list_all_job_links)

list_job_info <- vector("list", n)


system.time(
  for(i in 1:n) {list_job_info[[i]] <- tryCatch(get_job_vieclam24h(list_all_job_links[i]), error = function(e) {data.frame(link = list_all_job_links[i])})}
  )


do.call("bind_rows", list_job_info) -> df_vieclam24h

# Save data: 

today_time <- today() %>% as.character()
write_csv(df_vieclam24h, paste0("df_vieclam24h", today_time, ".csv"))

From viectotnhat.com

#========================================================================================================================
#   Collect data from viectotnhat
#   References: 
#   1. https://stackoverflow.com/questions/45414913/gsub-and-remove-all-characters-between-and-in-r
#   2. https://datascience.stackexchange.com/questions/8922/removing-strings-after-a-certain-character-in-a-given-text
#========================================================================================================================

# Function extracts all link from a web page: 

extract_all_links_page <- function(page_link) {
  
  page_link %>% 
    read_html() %>% 
    html_nodes(".col-sm-6 .margin0 a") %>% 
    html_attr("href") -> all_links
  
  return(all_links)
}

# Function extracts all descriptions for a specific job link: 

get_job_viectotnhat <- function(job_link) {
  
  job_link %>% 
    read_html() -> content
  
  content %>% 
    html_nodes(xpath = '//*[@id="style-ipad"]/ul') %>% 
    html_text(trim = TRUE) -> inf1
  
  inf1 %>% 
    stri_trans_general("Latin-ASCII") %>% 
    str_replace_all("\\(", "<") %>% 
    str_replace_all("\\)", ">") %>% 
    str_replace_all("<[^>]+>", "") %>% 
    str_replace_all("\n", "") %>% 
    str_flatten() %>% 
    str_split(":", simplify = TRUE) %>% 
    as.data.frame() %>% 
    mutate_all(function(x) {str_squish(x)}) -> df1
  
  df1 %>% 
    select(salary = V2, experience = V3, qualification = V4, 
           numbers_hired = V5, job_type = V6, location = V7, 
           hinh_thuc = V8, tinh_chat = V9, gender = V10) -> df1
  
  content %>% 
    html_nodes(xpath = '//*[@id="main-content"]/div/div/div[1]/div[4]/div[1]/div[2]/span[2]') %>% 
    html_text(trim = TRUE) -> deadline
  
  content %>% 
    html_nodes(xpath = '//*[@id="main-content"]/div/div/div[1]/div[4]/div[3]') %>% 
    html_text(trim = TRUE) -> update_and_Nviews
  
  content %>% 
    html_nodes(xpath = '//*[@id="main-content"]/div/div/div[1]/div[4]/div[1]/a[1]/h2') %>% 
    html_text(trim = TRUE) -> firm_name 
  
  content %>% 
    html_nodes(xpath = '//*[@id="main-content"]/div/div/div[1]/div[6]/div/div[2]/div[1]/div[2]') %>% 
    html_text(trim = TRUE) -> firm_add
  
  content %>% 
    html_nodes(xpath = '//*[@id="main-content"]/div/div/div[1]/div[6]/div/div[1]/div[1]/div[7]') %>% 
    html_text(trim = TRUE) -> requirement  
  
  content %>% 
    html_nodes(xpath = '//*[@id="main-content"]/div/div/div[1]/div[6]/div/div[1]/div[1]/div[9]') %>% 
    html_text(trim = TRUE) -> benefits 
  
  df1 %>% 
    mutate(deadline = deadline, update_and_Nviews = update_and_Nviews, 
           firm_name = firm_name, firm_add = firm_add, requirement = requirement, 
           benefits = benefits, link = job_link, data_date = as.character(now())) -> job_info
  
  return(job_info %>% mutate_all(function(x) {stri_trans_general(x, "Latin-ASCII")}))
}



# All pages: 

paste0("https://viectotnhat.com/viec-lam/tim-kiem?tu_khoa=&nganh_nghe=0&muc_luong=0&tinh_thanh=0&loai_hinh=0&kinh_nghiem=0&trinh_do=0&gioi_tinh=0&page=", 1:500) -> all_pages


# Get all job links: 

system.time(
  lapply(all_pages, extract_all_links_page) -> list_all_jobs
)


list_all_jobs %>% unlist() %>% unique() -> all_job_links


# Collect descriptions for all jobs: 

n <- length(all_job_links)

list_job_info <- vector("list", n)


system.time(
  for(i in 1:n) {list_job_info[[i]] <- tryCatch(get_job_viectotnhat(all_job_links[i]), error = function(e) {data.frame(link = all_job_links[i])})}
)


do.call("bind_rows", list_job_info) -> df_vieclamtotnhat


# Save data (should be saved in .rds form): 

today_time <- today() %>% as.character()
write_csv(df_vieclamtotnhat, paste0("df_vieclamtotnhat", today_time, ".csv"))
LS0tDQp0aXRsZTogJ0NyYXdsIERhdGEgZnJvbSBWaWV0bmFtIEpvYiBXZWJzaXRlcycNCmF1dGhvcjogJ0F1dGhvcjogTmd1eWVuIENoaSBEdW5nJw0Kc3VidGl0bGU6ICJSIGZvciBGdW4iDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICAjIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGhpZ2hsaWdodDogemVuYnVybg0KICAgICMgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0aGVtZTogImZsYXRseSINCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCi0tLQ0KDQpgYGB7ciBzZXR1cCxpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgY2FjaGUgPSBUUlVFLCBldmFsID0gRkFMU0UpDQoNCmBgYA0KDQojIEZyb20gdGltdmllY25oYW5oLmNvbQ0KDQpgYGB7cn0NCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgIENvbGxlY3QgZGF0YSBmcm9tIHRpbXZpZWNuaGFuaC5jb20NCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0Kcm0obGlzdCA9IGxzKCkpICMgQ2xlYXIgd29ya3NwYWNlLiANCg0KbGlicmFyeShydmVzdCkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KHN0cmluZ2kpDQoNCiMgSGVscGVyIGZ1bmN0aW9uOiANCg0KcmVhZF9odG1sX05FIDwtIGZ1bmN0aW9uKHgpIHsNCiAgDQogIFBhZ2Uuc3JjIDwtIHRyeShyZWFkX2h0bWwoeCksIHNpbGVudCA9IFQpDQogIA0KICAjIFRlc3QgaWYgUGFnZS5zcmMgaXMgZXJyb25lb3VzOiANCiAgDQogIGlmIChjbGFzcyhQYWdlLnNyYylbMV0gPT0gInRyeS1lcnJvciIpIHsNCiAgICANCiAgICBlcnJvci5jb25kIDwtIGF0dHIoUGFnZS5zcmMsICJjb25kaXRpb24iKQ0KICAgIA0KICAgICMgQ2hlY2sgaWYgZXJyb3IgY29uZGl0aW9uIGNvbnRhaW5zIOKAnFRpbWVkIG91dOKAnSBwaHJhc2UuICBJZiByZWdleHByIGNhbm5vdCBmaW5kIGENCiAgICAjIG1hdGNoIGl0IHJldHVybnMgLTE6IA0KICAgIA0KICAgIHRpbWVkLm91dCA8LSByZWdleHByKCJUaW1lZCBvdXQiLCBlcnJvci5jb25kLCBpZ25vcmUuY2FzZSA9IFQpICE9IC0xDQogICAgDQogICAgIyBXZSB3YW50IHRvIGNvbnRpbnVlIG9ubHkgb24g4oCcdGltZWQgb3V04oCdIGVycm9yOiANCiAgICANCiAgICBpZiAodGltZWQub3V0ID09IFRSVUUpIHsNCiAgICAgIA0KICAgICAgIyBQcmludCBpbmZvcm1hdGlvbiBpbiB0aGUgY29uc29sZTogDQogICAgICANCiAgICAgIHByaW50KHBhc3RlKHgsICI6IFRpbWVkIG91dC4gVHJ5aW5nIHRvIHJlY29ubmVjdCBpbiAxcy4gUGxlYXNlIHdhaXQuLi4iKSkNCiAgICAgIFN5cy5zbGVlcCgxIC8gNSkNCiAgICAgIA0KICAgICAgcmV0dXJuKGh0bWxfTkUoeCkpDQogICAgfQ0KICB9DQogIA0KICByZXR1cm4oUGFnZS5zcmMpDQp9DQoNCiMgRnVuY3Rpb24gZXh0cmFjdCBqb2IgZGVzY3JpcHRpb25zIHdpdGggYSBzcGVjaWZpYyBqb2IgbGluayBzZWxlY3RlZDogDQoNCmdldF9qb2JfdGltdmllY25oYW5oIDwtIGZ1bmN0aW9uKGpvYl9saW5rKSB7DQogIA0KICBqb2JfbGluayAlPiUgDQogICAgcmVhZF9odG1sX05FKCkgLT4gY29udGVudA0KICANCiAgY29udGVudCAlPiUgDQogICAgaHRtbF9ub2Rlcyh4cGF0aCA9ICcvLypbQGlkPSJsZWZ0LWNvbnRlbnQiXS9hcnRpY2xlL2Rpdls1XS9kaXZbMV0nKSAlPiUgDQogICAgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAtPiBpbmYxDQogIA0KICBpbmYxICU+JSANCiAgICBzdHJpX3RyYW5zX2dlbmVyYWwoIkxhdGluLUFTQ0lJIikgJT4lIA0KICAgIHN0cl9yZXBsYWNlX2FsbCgiICIsICIiKSAlPiUgDQogICAgc3RyX3NwbGl0KCJcbiIsIHNpbXBsaWZ5ID0gVFJVRSkgJT4lIA0KICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgc2VsZWN0KFYyLCBWNiwgVjksIFYxNCwgVjE5KSAlPiUgDQogICAgcmVuYW1lKHNhbGFyeSA9IFYyLCBleHByaWVuY2UgPSBWNiwgcXVhbGlmaWNhdGlvbiA9IFY5LCBsb2NhdGlvbiA9IFYxNCwgam9iX3R5cGUgPSBWMTkpIC0+IGRmMQ0KICANCiAgY29udGVudCAlPiUgDQogICAgaHRtbF9ub2Rlcyh4cGF0aCA9ICcvLypbQGlkPSJsZWZ0LWNvbnRlbnQiXS9hcnRpY2xlL2Rpdls1XS9kaXZbMl0nKSAlPiUgDQogICAgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAtPiBpbmYyDQogIA0KICBpbmYyICU+JSANCiAgICBzdHJpX3RyYW5zX2dlbmVyYWwoIkxhdGluLUFTQ0lJIikgJT4lIA0KICAgIHN0cl9yZXBsYWNlX2FsbCgiICIsICIiKSAlPiUgDQogICAgc3RyX3NwbGl0KCJcbiIsIHNpbXBsaWZ5ID0gVFJVRSkgJT4lIA0KICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgc2VsZWN0KFYyLCBWNSwgVjgsIFYxMSwgVjE0KSAlPiUgDQogICAgcmVuYW1lKG51bWJlcnNfaGlyZWQgPSBWMiwgZ2VuZGVyID0gVjUsIHRpbmhfY2hhdCA9IFY4LCBoaW5oX3RodWMgPSBWMTEsIHRodV92aWVjID0gVjE0KSAtPiBkZjINCiAgDQogIGNvbnRlbnQgJT4lIA0KICAgIGh0bWxfbm9kZXMoeHBhdGggPSAnLy8qW0BpZD0ibGVmdC1jb250ZW50Il0vYXJ0aWNsZS9kaXZbMV0nKSAlPiUgDQogICAgaHRtbF90ZXh0KCkgJT4lIA0KICAgIHN0cmlfdHJhbnNfZ2VuZXJhbCgiTGF0aW4tQVNDSUkiKSAlPiUgDQogICAgc3RyX3JlcGxhY2VfYWxsKCIgIiwgIiIpICU+JSANCiAgICBzdHJfc3BsaXQoIlxuIiwgc2ltcGxpZnkgPSBUUlVFKSAlPiUgDQogICAgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgICBwdWxsKFYzKSAtPiB1cGRhdGVfYW5kX052aWV3cyANCiAgDQogIGNvbnRlbnQgJT4lIA0KICAgIGh0bWxfbm9kZXMoeHBhdGggPSAnLy8qW0BpZD0ibGVmdC1jb250ZW50Il0vYXJ0aWNsZS9kaXZbMl0vaDMnKSAlPiUgDQogICAgaHRtbF90ZXh0KCkgJT4lIA0KICAgIHN0cmlfdHJhbnNfZ2VuZXJhbCgiTGF0aW4tQVNDSUkiKSAlPiUNCiAgICBzdHJfc3F1aXNoKCkgLT4gZmlybV9uYW1lDQogIA0KICBjb250ZW50ICU+JSANCiAgICBodG1sX25vZGVzKHhwYXRoID0gJy8vKltAaWQ9ImxlZnQtY29udGVudCJdL2FydGljbGUvZGl2WzJdL3NwYW4nKSAlPiUgDQogICAgaHRtbF90ZXh0KCkgJT4lIA0KICAgIHN0cmlfdHJhbnNfZ2VuZXJhbCgiTGF0aW4tQVNDSUkiKSAlPiUNCiAgICBzdHJfc3F1aXNoKCkgLT4gZmlybV9hZGQNCiAgDQogIGNvbnRlbnQgJT4lIA0KICAgIGh0bWxfbm9kZXMoeHBhdGggPSAnLy8qW0BpZD0ibGVmdC1jb250ZW50Il0vYXJ0aWNsZS90YWJsZS90Ym9keS90clsyXS90ZFsyXS9wJykgJT4lIA0KICAgIGh0bWxfdGV4dCgpICU+JSANCiAgICBzdHJpX3RyYW5zX2dlbmVyYWwoIkxhdGluLUFTQ0lJIikgJT4lDQogICAgc3RyX3NxdWlzaCgpIC0+IHJlcXVpcmVtZW50DQogIA0KICBjb250ZW50ICU+JSANCiAgICBodG1sX25vZGVzKHhwYXRoID0gJy8vKltAaWQ9ImxlZnQtY29udGVudCJdL2FydGljbGUvdGFibGUvdGJvZHkvdHJbM10nKSAlPiUgDQogICAgaHRtbF90ZXh0KCkgJT4lIA0KICAgIHN0cmlfdHJhbnNfZ2VuZXJhbCgiTGF0aW4tQVNDSUkiKSAlPiUNCiAgICBzdHJfc3F1aXNoKCkgLT4gYmVuZWZpdHMNCiAgDQogIGNvbnRlbnQgJT4lIA0KICAgIGh0bWxfbm9kZXMoeHBhdGggPSAnLy8qW0BpZD0ibGVmdC1jb250ZW50Il0vYXJ0aWNsZS90YWJsZS90Ym9keS90cls0XScpICU+JSANCiAgICBodG1sX3RleHQoKSAlPiUgDQogICAgc3RyaV90cmFuc19nZW5lcmFsKCJMYXRpbi1BU0NJSSIpICU+JQ0KICAgIHN0cl9zcXVpc2goKSAtPiBkZWFkbGluZSANCiAgDQogIGJpbmRfY29scyhkZjEsIGRmMikgJT4lIA0KICAgIG11dGF0ZSh1cGRhdGVfYW5kX052aWV3cyA9IHVwZGF0ZV9hbmRfTnZpZXdzLCANCiAgICAgICAgICAgZmlybV9uYW1lID0gZmlybV9uYW1lLA0KICAgICAgICAgICBmaXJtX2FkZCA9IGZpcm1fYWRkLCANCiAgICAgICAgICAgcmVxdWlyZW1lbnQgPSByZXF1aXJlbWVudCwgDQogICAgICAgICAgIGJlbmVmaXRzID0gYmVuZWZpdHMsIA0KICAgICAgICAgICBkZWFkbGluZSA9IGRlYWRsaW5lKSAlPiUgDQogICAgbXV0YXRlX2FsbChmdW5jdGlvbih4KSB7c3RyaV90cmFuc19nZW5lcmFsKHgsICJMYXRpbi1BU0NJSSIpfSktPiBkZl9pbmZvDQogIA0KICByZXR1cm4oZGZfaW5mbyAlPiUgbXV0YXRlKGxpbmsgPSBqb2JfbGluaywgZGF0YV9kYXRlID0gbm93KCkgJT4lIGFzLmNoYXJhY3RlcigpKSkNCiAgDQp9DQoNCg0KIyBGdW5jdGlvbiBleHRyYWN0cyBhbGwgbGluayBmcm9tIGEgd2ViIHBhZ2U6IA0KDQpleHRyYWN0X2FsbF9saW5rc19wYWdlIDwtIGZ1bmN0aW9uKHBhZ2VfbGluaykgew0KICBwYWdlX2xpbmsgJT4lIA0KICAgIHJlYWRfaHRtbF9ORSgpICU+JSANCiAgICBodG1sX25vZGVzKHhwYXRoID0gJy9odG1sL2JvZHkvc2VjdGlvbi9kaXYvZGl2WzFdL2Rpdi9kaXYvYXJ0aWNsZS90YWJsZS90Ym9keScpICU+JSANCiAgICBodG1sX25vZGVzKCJhIikgJT4lIA0KICAgIGh0bWxfYXR0cigiaHJlZiIpICU+JSANCiAgICByZXR1cm4oKQ0KfQ0KDQojIEdldCBhbGwgam9iIGxpbmtzOiANCg0KbGFwcGx5KHBhc3RlMCgiaHR0cHM6Ly93d3cudGltdmllY25oYW5oLmNvbS92aWVjbGFtL3RpbWtpZW0/JnBhZ2U9IiwgMTozMDApLCBleHRyYWN0X2FsbF9saW5rc19wYWdlKSAtPiBhbGxfbGlua3MNCg0KYWxsX2xpbmtzICU+JSB1bmxpc3QoKSAlPiUgdW5pcXVlKCkgLT4gYWxsX2pvYl9saW5rcw0KDQoNCiMgQ29sbGVjdCBkZXNjcmlwdGlvbnMgZm9yIGFsbCBqb2JzOiANCg0KbiA8LSBsZW5ndGgoYWxsX2pvYl9saW5rcykNCg0KbGlzdF9qb2JfaW5mbyA8LSB2ZWN0b3IoImxpc3QiLCBuKQ0KDQoNCnN5c3RlbS50aW1lKGZvcihpIGluIDE6bikgew0KICBsaXN0X2pvYl9pbmZvW1tpXV0gPC0gdHJ5Q2F0Y2goZ2V0X2pvYl90aW12aWVjbmhhbmgoYWxsX2pvYl9saW5rc1tpXSksIGVycm9yID0gZnVuY3Rpb24oZSkge2RhdGEuZnJhbWUobGluayA9IGFsbF9qb2JfbGlua3NbaV0pfSkNCiAgfSkNCg0KDQpkby5jYWxsKCJiaW5kX3Jvd3MiLCBsaXN0X2pvYl9pbmZvKSAtPiBkZl90aW12aWVjbmhhbmgNCg0KIyBTYXZlIGRhdGE6IA0KDQp0b2RheV90aW1lIDwtIHRvZGF5KCkgJT4lIGFzLmNoYXJhY3RlcigpDQp3cml0ZV9jc3YoZGZfdGltdmllY25oYW5oLCBwYXN0ZTAoImRmX3RpbXZpZWNuaGFuaCIsIHRvZGF5X3RpbWUsICIuY3N2IikpDQoNCmBgYA0KDQojIEZyb20gdmllY2xhbTI0aC52bg0KDQpgYGB7cn0NCg0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAgQ29sbGVjdCBkYXRhIGZyb20gdmllY2xhbTI0aC52bg0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQojIEZ1bmN0aW9uIGV4dHJhY3RzIGFsbCBsaW5rIGZyb20gYSB3ZWIgcGFnZTogDQoNCmV4dHJhY3RfYWxsX2xpbmtzX3BhZ2UgPC0gZnVuY3Rpb24ocGFnZV9saW5rKSB7DQogIA0KICBwYWdlX2xpbmsgJT4lIA0KICAgIHJlYWRfaHRtbF9ORSgpICU+JSANCiAgICBodG1sX25vZGVzKCIuZm9udDEyKyAuYm94X3NoYWRvdyAudGV4dF9ncmV5MiIpICU+JSANCiAgICBodG1sX2F0dHIoImhyZWYiKSAtPiBwcmVmX2xpbmsNCiAgDQogIHBhc3RlMCgiaHR0cHM6Ly92aWVjbGFtMjRoLnZuIiwgcHJlZl9saW5rKSAtPiBhbGxfbGlua3MNCiAgDQogIHJldHVybihhbGxfbGlua3MpDQp9DQoNCg0KDQojIEZ1bmN0aW9uIGV4dHJhY3RzIGFsbCBkZXNjcmlwdGlvbnMgZm9yIGEgc3BlY2lmaWMgam9iIGxpbms6IA0KDQpnZXRfam9iX3ZpZWNsYW0yNGggPC0gZnVuY3Rpb24oam9iX2xpbmspIHsNCg0KICBqb2JfbGluayAlPiUgDQogICAgcmVhZF9odG1sKCkgLT4gY29udGVudA0KICANCiAgY29udGVudCAlPiUgDQogICAgaHRtbF9ub2Rlcyh4cGF0aCA9ICcvLypbQGlkPSJibG9ja19ib2R5X21haW4iXS9kaXZbMl0vZGl2WzRdJykgJT4lIA0KICAgIGh0bWxfdGV4dCh0cmltID0gVFJVRSkgLT4gaW5mMQ0KICANCiAgaW5mMSAlPiUgDQogICAgc3RyaV90cmFuc19nZW5lcmFsKCJMYXRpbi1BU0NJSSIpICU+JSANCiAgICBzdHJfcmVwbGFjZV9hbGwoIiAiLCAiIikgJT4lIA0KICAgIHN0cl9yZXBsYWNlX2FsbCgiXG4iLCAiIikgJT4lIA0KICAgIHN0cl9zcGxpdCgiOiIsIHNpbXBsaWZ5ID0gVFJVRSkgJT4lIA0KICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgc2VsZWN0KHNhbGFyeSA9IFYyLCBleHBlcmllbmNlID0gVjMsIHF1YWxpZmljYXRpaW4gPSBWNCwgDQogICAgICAgICAgIG51bWJlcnNfaGlyZWQgPSBWNSwgam9iX3R5cGUgPSBWNiwgbG9jYXRpb24gPSBWNywgDQogICAgICAgICAgIGhpbmhfdGh1YyA9IFY4LCB0aW5oX2NoYXQgPSBWOSwgZ2VuZGVyID0gVjEwLCBhZ2VfcmVxdWlyZW1lbnQgPSBWMTEpIC0+IGRmX2luZm8NCiAgDQogIGNvbnRlbnQgJT4lIA0KICAgIGh0bWxfbm9kZXMoeHBhdGggPSAnLy8qW0BpZD0iYmxvY2tfYm9keV9tYWluIl0vZGl2WzJdL2RpdlsyXS9kaXZbMV0vc3BhbicpICU+JSANCiAgICBodG1sX3RleHQodHJpbSA9IFRSVUUpIC0+IGRlYWRsaW5lDQogIA0KICBjb250ZW50ICU+JSANCiAgICBodG1sX25vZGVzKHhwYXRoID0gJy8vKltAaWQ9ImJsb2NrX2JvZHlfbWFpbiJdL2RpdlsyXS9kaXZbMl0vZGl2WzFdL3AnKSAlPiUgDQogICAgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAtPiB1cGRhdGVfYW5kX052aWV3cw0KICANCiAgY29udGVudCAlPiUgDQogICAgaHRtbF9ub2Rlcyh4cGF0aCA9ICcvLypbQGlkPSJibG9ja19ib2R5X21haW4iXS9kaXZbMl0vZGl2WzFdL2Rpdi9wL2EnKSAlPiUgDQogICAgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAtPiBmaXJtX25hbWUgDQogIA0KICBjb250ZW50ICU+JSANCiAgICBodG1sX25vZGVzKHhwYXRoID0gJy8vKltAaWQ9InR0ZF9kZXRhaWwiXS9kaXZbMl0vZGl2WzNdL3AnKSAlPiUgDQogICAgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAtPiBmaXJtX2FkZA0KICANCiAgY29udGVudCAlPiUgDQogICAgaHRtbF9ub2Rlcyh4cGF0aCA9ICcvLypbQGlkPSJ0dGRfZGV0YWlsIl0vZGl2WzFdL2RpdlsyXS9kaXZbM10vcCcpICU+JSANCiAgICBodG1sX3RleHQodHJpbSA9IFRSVUUpIC0+IHJlcXVpcmVtZW50ICANCiAgDQogIGNvbnRlbnQgJT4lIA0KICAgIGh0bWxfbm9kZXMoeHBhdGggPSAnLy8qW0BpZD0idHRkX2RldGFpbCJdL2RpdlsxXS9kaXZbMl0vZGl2WzJdL3AnKSAlPiUgDQogICAgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAtPiBiZW5lZml0cyANCiAgDQogIGRmX2luZm8gJT4lIA0KICAgIG11dGF0ZShkZWFkbGluZSA9IGRlYWRsaW5lLCB1cGRhdGVfYW5kX052aWV3cyA9IHVwZGF0ZV9hbmRfTnZpZXdzLCANCiAgICAgICAgICAgZmlybV9uYW1lID0gZmlybV9uYW1lLCBmaXJtX2FkZCA9IGZpcm1fYWRkLCByZXF1aXJlbWVudCA9IHJlcXVpcmVtZW50LCANCiAgICAgICAgICAgYmVuZWZpdHMgPSBiZW5lZml0cywgbGluayA9IGpvYl9saW5rLCBkYXRhX2RhdGUgPSBhcy5jaGFyYWN0ZXIobm93KCkpKSAtPiBqb2JfaW5mbw0KICANCiAgcmV0dXJuKGpvYl9pbmZvICU+JSBtdXRhdGVfYWxsKGZ1bmN0aW9uKHgpIHtzdHJpX3RyYW5zX2dlbmVyYWwoeCwgIkxhdGluLUFTQ0lJIil9KSkNCn0NCg0KDQojIEV4dHJhY3QgYWxsIGpvYiBsaW5rczogDQoNCnBhc3RlMCgiaHR0cHM6Ly92aWVjbGFtMjRoLnZuL3RpbS1raWVtLXZpZWMtbGFtLW5oYW5oLz9oZG5fdHVfa2hvYT0maGRuX25nYW5oX25naGVfY2FwMT0maGRuX2RpYV9kaWVtPSZrZXk9dHR2X25hbmdjYW8mcGFnZT0iLCAxOjEzMCkgLT4gYWxsX3BhZ2VzDQoNCmxhcHBseShhbGxfcGFnZXMsIGV4dHJhY3RfYWxsX2xpbmtzX3BhZ2UpICU+JSB1bmxpc3QoKSAlPiUgdW5pcXVlKCkgLT4gbGlzdF9hbGxfam9iX2xpbmtzDQoNCiMgQ29sbGVjdCBkZXNjcmlwdGlvbnMgZm9yIGFsbCBqb2JzOiANCg0KbiA8LSBsZW5ndGgobGlzdF9hbGxfam9iX2xpbmtzKQ0KDQpsaXN0X2pvYl9pbmZvIDwtIHZlY3RvcigibGlzdCIsIG4pDQoNCg0Kc3lzdGVtLnRpbWUoDQogIGZvcihpIGluIDE6bikge2xpc3Rfam9iX2luZm9bW2ldXSA8LSB0cnlDYXRjaChnZXRfam9iX3ZpZWNsYW0yNGgobGlzdF9hbGxfam9iX2xpbmtzW2ldKSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7ZGF0YS5mcmFtZShsaW5rID0gbGlzdF9hbGxfam9iX2xpbmtzW2ldKX0pfQ0KICApDQoNCg0KZG8uY2FsbCgiYmluZF9yb3dzIiwgbGlzdF9qb2JfaW5mbykgLT4gZGZfdmllY2xhbTI0aA0KDQojIFNhdmUgZGF0YTogDQoNCnRvZGF5X3RpbWUgPC0gdG9kYXkoKSAlPiUgYXMuY2hhcmFjdGVyKCkNCndyaXRlX2NzdihkZl92aWVjbGFtMjRoLCBwYXN0ZTAoImRmX3ZpZWNsYW0yNGgiLCB0b2RheV90aW1lLCAiLmNzdiIpKQ0KDQoNCmBgYA0KDQojIEZyb20gdmllY3RvdG5oYXQuY29tDQoNCmBgYHtyfQ0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAgIENvbGxlY3QgZGF0YSBmcm9tIHZpZWN0b3RuaGF0DQojICAgUmVmZXJlbmNlczogDQojICAgMS4gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNDU0MTQ5MTMvZ3N1Yi1hbmQtcmVtb3ZlLWFsbC1jaGFyYWN0ZXJzLWJldHdlZW4tYW5kLWluLXINCiMgICAyLiBodHRwczovL2RhdGFzY2llbmNlLnN0YWNrZXhjaGFuZ2UuY29tL3F1ZXN0aW9ucy84OTIyL3JlbW92aW5nLXN0cmluZ3MtYWZ0ZXItYS1jZXJ0YWluLWNoYXJhY3Rlci1pbi1hLWdpdmVuLXRleHQNCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KIyBGdW5jdGlvbiBleHRyYWN0cyBhbGwgbGluayBmcm9tIGEgd2ViIHBhZ2U6IA0KDQpleHRyYWN0X2FsbF9saW5rc19wYWdlIDwtIGZ1bmN0aW9uKHBhZ2VfbGluaykgew0KICANCiAgcGFnZV9saW5rICU+JSANCiAgICByZWFkX2h0bWwoKSAlPiUgDQogICAgaHRtbF9ub2RlcygiLmNvbC1zbS02IC5tYXJnaW4wIGEiKSAlPiUgDQogICAgaHRtbF9hdHRyKCJocmVmIikgLT4gYWxsX2xpbmtzDQogIA0KICByZXR1cm4oYWxsX2xpbmtzKQ0KfQ0KDQojIEZ1bmN0aW9uIGV4dHJhY3RzIGFsbCBkZXNjcmlwdGlvbnMgZm9yIGEgc3BlY2lmaWMgam9iIGxpbms6IA0KDQpnZXRfam9iX3ZpZWN0b3RuaGF0IDwtIGZ1bmN0aW9uKGpvYl9saW5rKSB7DQogIA0KICBqb2JfbGluayAlPiUgDQogICAgcmVhZF9odG1sKCkgLT4gY29udGVudA0KICANCiAgY29udGVudCAlPiUgDQogICAgaHRtbF9ub2Rlcyh4cGF0aCA9ICcvLypbQGlkPSJzdHlsZS1pcGFkIl0vdWwnKSAlPiUgDQogICAgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAtPiBpbmYxDQogIA0KICBpbmYxICU+JSANCiAgICBzdHJpX3RyYW5zX2dlbmVyYWwoIkxhdGluLUFTQ0lJIikgJT4lIA0KICAgIHN0cl9yZXBsYWNlX2FsbCgiXFwoIiwgIjwiKSAlPiUgDQogICAgc3RyX3JlcGxhY2VfYWxsKCJcXCkiLCAiPiIpICU+JSANCiAgICBzdHJfcmVwbGFjZV9hbGwoIjxbXj5dKz4iLCAiIikgJT4lIA0KICAgIHN0cl9yZXBsYWNlX2FsbCgiXG4iLCAiIikgJT4lIA0KICAgIHN0cl9mbGF0dGVuKCkgJT4lIA0KICAgIHN0cl9zcGxpdCgiOiIsIHNpbXBsaWZ5ID0gVFJVRSkgJT4lIA0KICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgbXV0YXRlX2FsbChmdW5jdGlvbih4KSB7c3RyX3NxdWlzaCh4KX0pIC0+IGRmMQ0KICANCiAgZGYxICU+JSANCiAgICBzZWxlY3Qoc2FsYXJ5ID0gVjIsIGV4cGVyaWVuY2UgPSBWMywgcXVhbGlmaWNhdGlvbiA9IFY0LCANCiAgICAgICAgICAgbnVtYmVyc19oaXJlZCA9IFY1LCBqb2JfdHlwZSA9IFY2LCBsb2NhdGlvbiA9IFY3LCANCiAgICAgICAgICAgaGluaF90aHVjID0gVjgsIHRpbmhfY2hhdCA9IFY5LCBnZW5kZXIgPSBWMTApIC0+IGRmMQ0KICANCiAgY29udGVudCAlPiUgDQogICAgaHRtbF9ub2Rlcyh4cGF0aCA9ICcvLypbQGlkPSJtYWluLWNvbnRlbnQiXS9kaXYvZGl2L2RpdlsxXS9kaXZbNF0vZGl2WzFdL2RpdlsyXS9zcGFuWzJdJykgJT4lIA0KICAgIGh0bWxfdGV4dCh0cmltID0gVFJVRSkgLT4gZGVhZGxpbmUNCiAgDQogIGNvbnRlbnQgJT4lIA0KICAgIGh0bWxfbm9kZXMoeHBhdGggPSAnLy8qW0BpZD0ibWFpbi1jb250ZW50Il0vZGl2L2Rpdi9kaXZbMV0vZGl2WzRdL2RpdlszXScpICU+JSANCiAgICBodG1sX3RleHQodHJpbSA9IFRSVUUpIC0+IHVwZGF0ZV9hbmRfTnZpZXdzDQogIA0KICBjb250ZW50ICU+JSANCiAgICBodG1sX25vZGVzKHhwYXRoID0gJy8vKltAaWQ9Im1haW4tY29udGVudCJdL2Rpdi9kaXYvZGl2WzFdL2Rpdls0XS9kaXZbMV0vYVsxXS9oMicpICU+JSANCiAgICBodG1sX3RleHQodHJpbSA9IFRSVUUpIC0+IGZpcm1fbmFtZSANCiAgDQogIGNvbnRlbnQgJT4lIA0KICAgIGh0bWxfbm9kZXMoeHBhdGggPSAnLy8qW0BpZD0ibWFpbi1jb250ZW50Il0vZGl2L2Rpdi9kaXZbMV0vZGl2WzZdL2Rpdi9kaXZbMl0vZGl2WzFdL2RpdlsyXScpICU+JSANCiAgICBodG1sX3RleHQodHJpbSA9IFRSVUUpIC0+IGZpcm1fYWRkDQogIA0KICBjb250ZW50ICU+JSANCiAgICBodG1sX25vZGVzKHhwYXRoID0gJy8vKltAaWQ9Im1haW4tY29udGVudCJdL2Rpdi9kaXYvZGl2WzFdL2Rpdls2XS9kaXYvZGl2WzFdL2RpdlsxXS9kaXZbN10nKSAlPiUgDQogICAgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAtPiByZXF1aXJlbWVudCAgDQogIA0KICBjb250ZW50ICU+JSANCiAgICBodG1sX25vZGVzKHhwYXRoID0gJy8vKltAaWQ9Im1haW4tY29udGVudCJdL2Rpdi9kaXYvZGl2WzFdL2Rpdls2XS9kaXYvZGl2WzFdL2RpdlsxXS9kaXZbOV0nKSAlPiUgDQogICAgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAtPiBiZW5lZml0cyANCiAgDQogIGRmMSAlPiUgDQogICAgbXV0YXRlKGRlYWRsaW5lID0gZGVhZGxpbmUsIHVwZGF0ZV9hbmRfTnZpZXdzID0gdXBkYXRlX2FuZF9Odmlld3MsIA0KICAgICAgICAgICBmaXJtX25hbWUgPSBmaXJtX25hbWUsIGZpcm1fYWRkID0gZmlybV9hZGQsIHJlcXVpcmVtZW50ID0gcmVxdWlyZW1lbnQsIA0KICAgICAgICAgICBiZW5lZml0cyA9IGJlbmVmaXRzLCBsaW5rID0gam9iX2xpbmssIGRhdGFfZGF0ZSA9IGFzLmNoYXJhY3Rlcihub3coKSkpIC0+IGpvYl9pbmZvDQogIA0KICByZXR1cm4oam9iX2luZm8gJT4lIG11dGF0ZV9hbGwoZnVuY3Rpb24oeCkge3N0cmlfdHJhbnNfZ2VuZXJhbCh4LCAiTGF0aW4tQVNDSUkiKX0pKQ0KfQ0KDQoNCg0KIyBBbGwgcGFnZXM6IA0KDQpwYXN0ZTAoImh0dHBzOi8vdmllY3RvdG5oYXQuY29tL3ZpZWMtbGFtL3RpbS1raWVtP3R1X2tob2E9Jm5nYW5oX25naGU9MCZtdWNfbHVvbmc9MCZ0aW5oX3RoYW5oPTAmbG9haV9oaW5oPTAma2luaF9uZ2hpZW09MCZ0cmluaF9kbz0wJmdpb2lfdGluaD0wJnBhZ2U9IiwgMTo1MDApIC0+IGFsbF9wYWdlcw0KDQoNCiMgR2V0IGFsbCBqb2IgbGlua3M6IA0KDQpzeXN0ZW0udGltZSgNCiAgbGFwcGx5KGFsbF9wYWdlcywgZXh0cmFjdF9hbGxfbGlua3NfcGFnZSkgLT4gbGlzdF9hbGxfam9icw0KKQ0KDQoNCmxpc3RfYWxsX2pvYnMgJT4lIHVubGlzdCgpICU+JSB1bmlxdWUoKSAtPiBhbGxfam9iX2xpbmtzDQoNCg0KIyBDb2xsZWN0IGRlc2NyaXB0aW9ucyBmb3IgYWxsIGpvYnM6IA0KDQpuIDwtIGxlbmd0aChhbGxfam9iX2xpbmtzKQ0KDQpsaXN0X2pvYl9pbmZvIDwtIHZlY3RvcigibGlzdCIsIG4pDQoNCg0Kc3lzdGVtLnRpbWUoDQogIGZvcihpIGluIDE6bikge2xpc3Rfam9iX2luZm9bW2ldXSA8LSB0cnlDYXRjaChnZXRfam9iX3ZpZWN0b3RuaGF0KGFsbF9qb2JfbGlua3NbaV0pLCBlcnJvciA9IGZ1bmN0aW9uKGUpIHtkYXRhLmZyYW1lKGxpbmsgPSBhbGxfam9iX2xpbmtzW2ldKX0pfQ0KKQ0KDQoNCmRvLmNhbGwoImJpbmRfcm93cyIsIGxpc3Rfam9iX2luZm8pIC0+IGRmX3ZpZWNsYW10b3RuaGF0DQoNCg0KIyBTYXZlIGRhdGEgKHNob3VsZCBiZSBzYXZlZCBpbiAucmRzIGZvcm0pOiANCg0KdG9kYXlfdGltZSA8LSB0b2RheSgpICU+JSBhcy5jaGFyYWN0ZXIoKQ0Kd3JpdGVfY3N2KGRmX3ZpZWNsYW10b3RuaGF0LCBwYXN0ZTAoImRmX3ZpZWNsYW10b3RuaGF0IiwgdG9kYXlfdGltZSwgIi5jc3YiKSkNCg0KYGBgDQoNCg==