About

Load Packages in R/RStudio

We are going to use tidyverse a collection of R packages designed for data science.

Web Scraping Functions


# This function to creates a URL for the www.dice.com website and extract the data 
create_url <- function(website, title, location, radius, page){
  url <- paste0(website, "?q=", title, "&l=", location, "&radius=", radius)
  url <- paste0(url, "&startPage=", page, "&jobs")
  return(url)
}

# This function use the unstructure data from the html file to create a dataframe
# with only the data that is needed for analysis
create_tibble <- function(html){
  
  search_title <- html %>% 
    html_nodes(".complete-serp-result-div") %>%
    html_nodes(xpath = "//a/@title") %>%
    html_text()
  
  search_region <- html %>% 
    html_nodes(".complete-serp-result-div") %>% 
    html_nodes('[itemprop="address"]') %>%
    html_nodes("[itemprop=addressRegion]") %>%
    html_text()
  
  search_zipcode <- html %>% 
    html_nodes(".complete-serp-result-div") %>% 
    html_nodes('[itemprop="address"]') %>%
    html_nodes("[itemprop=postalCode]") %>%
    html_text()
  
  search_address <- html %>% 
    html_nodes(".complete-serp-result-div") %>% 
    html_nodes('[itemprop="address"]') %>%
    html_nodes("[itemprop=streetAddress]") %>%
    html_text() %>% 
    str_replace(pattern = paste0(", ",search_region), "")
  
  search_company <- html %>% 
    html_nodes(".complete-serp-result-div") %>% 
    html_nodes('[itemprop="hiringOrganization"]') %>%
    html_nodes("[itemprop=name]") %>%
    html_text()
  
    df <- tibble(title = search_title,
                 company = search_company,
                 city = search_address, 
                 state = search_region,
                 zipcode = search_zipcode)

    return(df)
}

Task 1: Data Collection - Web Scraping


1B) From the target website determine the number of pages for the given search. Create a variable “num_pages” equal to the max number of pages for the job search. Create a variable “url” using the create_url() function with the same parameters than the previous search, for the page number use “i” as we are looping over all the pages.

  • Commands: create_url(website = JOBSITE , title = JOBTITLE, location = STATE, radius = NUM_MILES, page = PAG_NUM)
#site = JOB_WEBSITE
#job = "Data+Analyst"
#region = STATE_TWO_LETTERS
#miles = MILES_NUM
#pag = PAG_NUM

num_pages= 92

# COMMENT: Loop over the max number of pages for the job search
for (i in 1:num_pages) {
  
  # TODO: Create a url for the job search
  #url <- create_url()
url <- create_url(website = site, title = job, location = region, radius = 30, page = i)  
  
  # COMMENT: read the created URL and collects the html code
  web_html <- read_html(url)

    
  # COMMENT: If statement to create the first dataframe
  if(i == 1) {
    
    # COMMENT: Creates a tibble dataframe extracting information from the html code
    job_data <- create_tibble(html = web_html)
    
  }else{
  
      # COMMENT: We add new observation to the first dataframe
    df <- create_tibble(html = web_html)
    job_data <- bind_rows(job_data, df)
  }
  
  # COMMENT: We have to wait a couple of seconds before moving to the next page
  Sys.sleep(0.5)
}

1C) Make sure that the data was collected correctly. By using the functions to inspect and summarize the data. Describe the summary statistics and note any significant observations.

  • Dataframe: job_data
  • Commands: head() summary()
summary(job_data)
head(job_data)

1D) After making sure that the data was collected correctly, save the data as csv file.

  • Commands: write_csv(x = DATAFRAME, path = “data/DATAFRAME” )
write_csv(x = job_data, path = "data/dice-ny.csv" )

Task 2: Visualization Analysis - Tableau


2A) Upload your data in csv format to Tableau, make any changes to the data types (GEOLOCATION, TEXT, NUMERIC). Take an screenshot of Tableu’s data inspection.

knitr::include_graphics('2A.PNG')

2B) Using tableau geolocation features map cities using bubbles where the size of the bubble is cumulative number of jobs listing in that city. Note any interesting patterns, add an screenshot of your visualization.

knitr::include_graphics('2B.PNG')

This image shows the number of Data Analyst positions around New York City. There are more jobs closer to the city rather than further which makes sense because the city is a natural hub for companies to have offices.

2C) Create a tree map, to compare the different cities and the cumulative number of job posting in each city. Note any interesting patterns, add an screenshot of your visualization.

knitr::include_graphics('2C.PNG')

Clearly the state will have more open positions than the individual citie. As someone not from/very familiar with cities in New York state, it is interesting to note that the cities I have heard of are listed. This makes sense because most people are more familiar with larger cities which have more job opportunities.

2D) Create a Bar plot by State and City. To display the cumulative number of jobs in each city. Note any interesting patterns, add an screenshot of your visualization.

knitr::include_graphics('2D.PNG')

According to the graph, NYC has the most opportunities followed by Rochester.

2E) Create a dashboard to display the three plots above. Use half of the dashboard to display the map with the location of the cities. On the bottom of the dashboard place the other two charts, add titles to each chart. Note any interesting patterns, add an screenshot of your visualization.

knitr::include_graphics('2E.PNG')

Because the data throughout this process was consistent, the dashboard gives the same conclusions that each of the graphs showed: larger, more populated cities have greater numbers of job prospects.

Task 3: Watson Analysis


To complete the last task, follow the directions found below. Make sure to screenshot and attach any pictures of the results obtained or any questions asked.

3A) Upload you data to watson, explore the different insights. Take 3 screenshots of your insights and describe your findings.

knitr::include_graphics('3A.PNG')

I thought it would be interesting to include the same graph shown in tableau to see if it produced the same results. It did, so there is not any new information, but it demonstrates consistency in the findings.

3B) Watson Analytics Insights, describe your findings.

knitr::include_graphics('3B.PNG')

While I couldn’t get a good screenshot, this graph was a decision tree that broke down job title based on location which was super interesting. So as it filtered through you could see which jobs were more suited to find in which locations and how frequently they were posted. ### 3C) Watson Analytics Insights, describe your findings.

knitr::include_graphics('3C.PNG')

This broke down the number of companies located in each area. All of the companies were in New York, so clearly that had the highest concentration, but it was interesting that when you broke it down by company and not position it was more evenly dispersed which shows that there may not be more companies in larger cities but rather the same number of companies, but with a larger need for new employees.

DQoNCi0tLQ0KdGl0bGU6ICJXZWIgU2NyYXBpbmcgYW5kIFZpc3VhbCBBbmFseXRpY3MiDQphdXRob3I6ICJKYXggRmFycXVoYXIiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdA0KZGF0ZTogIlNwcmluZyAyMDE4Ig0Kc3VidGl0bGU6ICJDTUUgR3JvdXAgRm91bmRhdGlvbiBCdXNpbmVzcyBBbmFseXRpY3MgTGFiIg0KLS0tDQoNCi0tLS0tLS0tLS0tLS0NCg0KKiBGb3IgeW91ciBhc3NpZ25tZW50IHlvdSBtYXkgYmUgdXNpbmcgZGlmZmVyZW50IGRhdGFzZXQgdGhhbiB3aGF0IGlzIGluY2x1ZGVkIGhlcmUuIA0KDQoqIEFsd2F5cyByZWFkIGNhcmVmdWxseSB0aGUgaW5zdHJ1Y3Rpb25zIG9uIFNha2FpLiAgDQoNCiogVGFza3MvcXVlc3Rpb25zIHRvIGJlIGNvbXBsZXRlZC9hbnN3ZXJlZCBhcmUgaGlnaGxpZ2h0ZWQgaW4gbGFyZ2VyIGJvbGRlZCBmb250cyBhbmQgbnVtYmVyZWQgYWNjb3JkaW5nIHRvIHRoZWlyIHNlY3Rpb24uDQoNCiMjIyBBYm91dA0KDQoqIFdlYiBzY3JhcGluZywgd2ViIGhhcnZlc3RpbmcsIG9yIHdlYiBkYXRhIGV4dHJhY3Rpb24gaXMgZGF0YSBzY3JhcGluZyB1c2VkIGZvciBleHRyYWN0aW5nIGRhdGEgZnJvbSB3ZWJzaXRlcy4NCg0KKiBUaGlzIHRlY2huaXF1ZSBtb3N0bHkgZm9jdXNlcyBvbiB0aGUgdHJhbnNmb3JtYXRpb24gb2YgdW5zdHJ1Y3R1cmVkIGRhdGEgKEhUTUwgZm9ybWF0KSBvbiB0aGUgd2ViIGludG8gc3RydWN0dXJlZCBkYXRhIChkYXRhYmFzZSBvciBzcHJlYWRzaGVldCkgDQoNCiogQSBmaWN0aXRpb3VzIExvbmRvbi1iYXNlZCB0cmFpbmluZyBjb21wYW55LCBXZVRyYWluWW91LCB3YW50cyB0byBzdGFydCBhIGxvY2FsIHRyYWluaW5nIGZhY2lsaXR5IGluIENhbGlmb3JuaWEuIEl0IGlzIGxvb2tpbmcgZm9yIGEgY2l0eSB3aGVyZSBhbXBsZSBTYWxlc2ZvcmNlKiBkZXZlbG9wbWVudCBqb2JzIGFyZSBhdmFpbGFibGUuIA0KDQoqIEl0cyBnb2FsIGlzIHRvIHRyYWluIGVuZ2luZWVycyBhbmQgZnVsZmlsbCBmdWxsLXRpbWUgYW5kIHBhcnQtdGltZSBqb2JzLiBXZVRyYWluWW91IGhhcyBoaXJlZCB5b3UgdG8gZGV0ZXJtaW5lIHdoZXJlIHRoZXkgc2hvdWxkIHNldCB1cCB0aGUgYnVzaW5lc3MuDQoNCiogQ2FzZSBTdHVkeTogaHR0cHM6Ly9zb2Z0d2FyZS5pbnRlbC5jb20vZW4tdXMvYXJ0aWNsZXMvdXNpbmctdmlzdWFsaXphdGlvbi10by10ZWxsLWEtY29tcGVsbGluZy1kYXRhLXN0b3J5DQoNCg0KIyMjIExvYWQgUGFja2FnZXMgaW4gUi9SU3R1ZGlvIA0KDQpXZSBhcmUgZ29pbmcgdG8gdXNlIHRpZHl2ZXJzZSBhIGNvbGxlY3Rpb24gb2YgUiBwYWNrYWdlcyBkZXNpZ25lZCBmb3IgZGF0YSBzY2llbmNlLiANCg0KKiBJbmZvOiBodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLw0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KDQojIEhlcmUgd2UgYXJlIGNoZWNraW5nIGlmIHRoZSBwYWNrYWdlIGlzIGluc3RhbGxlZA0KaWYoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKXsNCiAgDQogICMgSWYgdGhlIHBhY2thZ2UgaXMgbm90IGluIHRoZSBzeXN0ZW0gdGhlbiBpdCB3aWxsIGJlIGluc3RhbGwNCiAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIiwgZGVwZW5kZW5jaWVzID0gVFJVRSkNCiAgDQogICMgSGVyZSB3ZSBhcmUgbG9hZGluZyB0aGUgcGFja2FnZQ0KICBsaWJyYXJ5KCJ0aWR5dmVyc2UiKQ0KfQ0KDQojIEhlcmUgd2UgYXJlIGNoZWNraW5nIGlmIHRoZSBwYWNrYWdlIGlzIGluc3RhbGxlZA0KaWYoIXJlcXVpcmUoInJ2ZXN0Iikpew0KICANCiAgIyBJZiB0aGUgcGFja2FnZSBpcyBub3QgaW4gdGhlIHN5c3RlbSB0aGVuIGl0IHdpbGwgYmUgaW5zdGFsbA0KICBpbnN0YWxsLnBhY2thZ2VzKCJydmVzdCIsIGRlcGVuZGVuY2llcyA9IFRSVUUpDQogIA0KICAjIEhlcmUgd2UgYXJlIGxvYWRpbmcgdGhlIHBhY2thZ2UNCiAgbGlicmFyeSgicnZlc3QiKQ0KfQ0KDQpgYGANCg0KDQojIyMjIFdlYiBTY3JhcGluZyBGdW5jdGlvbnMNCg0KYGBge3J9DQoNCiMgVGhpcyBmdW5jdGlvbiB0byBjcmVhdGVzIGEgVVJMIGZvciB0aGUgd3d3LmRpY2UuY29tIHdlYnNpdGUgYW5kIGV4dHJhY3QgdGhlIGRhdGEgDQpjcmVhdGVfdXJsIDwtIGZ1bmN0aW9uKHdlYnNpdGUsIHRpdGxlLCBsb2NhdGlvbiwgcmFkaXVzLCBwYWdlKXsNCiAgdXJsIDwtIHBhc3RlMCh3ZWJzaXRlLCAiP3E9IiwgdGl0bGUsICImbD0iLCBsb2NhdGlvbiwgIiZyYWRpdXM9IiwgcmFkaXVzKQ0KICB1cmwgPC0gcGFzdGUwKHVybCwgIiZzdGFydFBhZ2U9IiwgcGFnZSwgIiZqb2JzIikNCiAgcmV0dXJuKHVybCkNCn0NCg0KIyBUaGlzIGZ1bmN0aW9uIHVzZSB0aGUgdW5zdHJ1Y3R1cmUgZGF0YSBmcm9tIHRoZSBodG1sIGZpbGUgdG8gY3JlYXRlIGEgZGF0YWZyYW1lDQojIHdpdGggb25seSB0aGUgZGF0YSB0aGF0IGlzIG5lZWRlZCBmb3IgYW5hbHlzaXMNCmNyZWF0ZV90aWJibGUgPC0gZnVuY3Rpb24oaHRtbCl7DQogIA0KICBzZWFyY2hfdGl0bGUgPC0gaHRtbCAlPiUgDQogICAgaHRtbF9ub2RlcygiLmNvbXBsZXRlLXNlcnAtcmVzdWx0LWRpdiIpICU+JQ0KICAgIGh0bWxfbm9kZXMoeHBhdGggPSAiLy9hL0B0aXRsZSIpICU+JQ0KICAgIGh0bWxfdGV4dCgpDQogIA0KICBzZWFyY2hfcmVnaW9uIDwtIGh0bWwgJT4lIA0KICAgIGh0bWxfbm9kZXMoIi5jb21wbGV0ZS1zZXJwLXJlc3VsdC1kaXYiKSAlPiUgDQogICAgaHRtbF9ub2RlcygnW2l0ZW1wcm9wPSJhZGRyZXNzIl0nKSAlPiUNCiAgICBodG1sX25vZGVzKCJbaXRlbXByb3A9YWRkcmVzc1JlZ2lvbl0iKSAlPiUNCiAgICBodG1sX3RleHQoKQ0KICANCiAgc2VhcmNoX3ppcGNvZGUgPC0gaHRtbCAlPiUgDQogICAgaHRtbF9ub2RlcygiLmNvbXBsZXRlLXNlcnAtcmVzdWx0LWRpdiIpICU+JSANCiAgICBodG1sX25vZGVzKCdbaXRlbXByb3A9ImFkZHJlc3MiXScpICU+JQ0KICAgIGh0bWxfbm9kZXMoIltpdGVtcHJvcD1wb3N0YWxDb2RlXSIpICU+JQ0KICAgIGh0bWxfdGV4dCgpDQogIA0KICBzZWFyY2hfYWRkcmVzcyA8LSBodG1sICU+JSANCiAgICBodG1sX25vZGVzKCIuY29tcGxldGUtc2VycC1yZXN1bHQtZGl2IikgJT4lIA0KICAgIGh0bWxfbm9kZXMoJ1tpdGVtcHJvcD0iYWRkcmVzcyJdJykgJT4lDQogICAgaHRtbF9ub2RlcygiW2l0ZW1wcm9wPXN0cmVldEFkZHJlc3NdIikgJT4lDQogICAgaHRtbF90ZXh0KCkgJT4lIA0KICAgIHN0cl9yZXBsYWNlKHBhdHRlcm4gPSBwYXN0ZTAoIiwgIixzZWFyY2hfcmVnaW9uKSwgIiIpDQogIA0KICBzZWFyY2hfY29tcGFueSA8LSBodG1sICU+JSANCiAgICBodG1sX25vZGVzKCIuY29tcGxldGUtc2VycC1yZXN1bHQtZGl2IikgJT4lIA0KICAgIGh0bWxfbm9kZXMoJ1tpdGVtcHJvcD0iaGlyaW5nT3JnYW5pemF0aW9uIl0nKSAlPiUNCiAgICBodG1sX25vZGVzKCJbaXRlbXByb3A9bmFtZV0iKSAlPiUNCiAgICBodG1sX3RleHQoKQ0KICANCiAgICBkZiA8LSB0aWJibGUodGl0bGUgPSBzZWFyY2hfdGl0bGUsDQogICAgICAgICAgICAgICAgIGNvbXBhbnkgPSBzZWFyY2hfY29tcGFueSwNCiAgICAgICAgICAgICAgICAgY2l0eSA9IHNlYXJjaF9hZGRyZXNzLCANCiAgICAgICAgICAgICAgICAgc3RhdGUgPSBzZWFyY2hfcmVnaW9uLA0KICAgICAgICAgICAgICAgICB6aXBjb2RlID0gc2VhcmNoX3ppcGNvZGUpDQoNCiAgICByZXR1cm4oZGYpDQp9DQoNCmBgYA0KDQoNCi0tLS0tLS0tLS0tLS0NCg0KIyMgVGFzayAxOiBEYXRhIENvbGxlY3Rpb24gLSBXZWIgU2NyYXBpbmcNCg0KLS0tLS0tLS0tLS0tLQ0KDQojIyMgMUEpIFVzZSB0aGUgY3JlYXRlX3VybCgpIGZ1bmN0aW9uIGFuZCB0aGUgZ2l2ZW4gd2Vic2l0ZSB0byBzY29wZSB0aGUgZGF0YSB0aGF0IHlvdSB3aWxsIGNvbGxlY3Rpb24uIEluIHRoZSBmdW5jdGlvbiBmb3IgInRpdGxlIiB1c2Ugb25lIG9mIHRoZSAiVHJlbmRpbmcgU2VhcmNoZXMiIGZyb20gdGhlIHdlYnNpdGUgb3IgYSBqb2IgdGl0bGUgdGhhdCB5b3UgYXJlIGludGVyZXN0ZWQuIEZvciAibG9jYXRpb24iIHVzZSBhIFVTIFN0YXRlIChDQSwgSUwsIC4uLiksIGZvciAicmFkaW91cyIgdXNlIDMwIG1pbGVzLCBmaW5hbGx5IHdlIGFyZSBvbmx5IGludGVyZXN0ZWQgaW4gdGhlIGZpcnN0IHBhZ2UuIFRha2UgYW4gc2NyZWVuc2hvdCBvZiBvbmx5IHRoZSBkYXRhIHRoYXQgeW91IG5lZWQNCg0KKiBUcmVuZGluZyBTZWFyY2hlczogd3d3LmRpY2UuY29tDQoqIEpvYiBXZWJzaXRlOiAiaHR0cHM6Ly93d3cuZGljZS5jb20vam9icyINCiogQ29tbWFuZHM6IGNyZWF0ZV91cmwod2Vic2l0ZSA9IEpPQlNJVEUgLCB0aXRsZSA9IEpPQlRJVExFLCBsb2NhdGlvbiA9IFNUQVRFLCByYWRpdXMgPSBOVU1fTUlMRVMsIHBhZ2UgPSBQQUdfTlVNKQ0KDQojIyMjIENyZWF0ZSB0aGUgdXJsIHRoZW4gZ28gdG8gdGhlIHVybCB1c2luZyB0aGUgYnJvd3NlciBhbmQgcG9zdCBhbiBzY3JlZW5zaG90IG9mIG9ubHkgdGhlIGRhdGEgdGhhdCB5b3UgbmVlZA0KYGBge3J9DQpzaXRlID0gImh0dHBzOi8vd3d3LmRpY2UuY29tL2pvYnMiDQpqb2IgPSAiRGF0YStBbmFseXN0Ig0KcmVnaW9uID0gIk5ZIg0KbWlsZXMgPSAzMA0KcGFnID0gMQ0KDQp1cmwgPC0gY3JlYXRlX3VybCh3ZWJzaXRlID0gc2l0ZSwgdGl0bGUgPSBqb2IsIGxvY2F0aW9uID0gcmVnaW9uLCByYWRpdXMgPSBtaWxlcywgcGFnZSA9IDEpDQp1cmwNCg0KDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnMUEnKQ0KYGBgDQoNCg0KIyMjIDFCKSBGcm9tIHRoZSB0YXJnZXQgd2Vic2l0ZSBkZXRlcm1pbmUgdGhlIG51bWJlciBvZiBwYWdlcyBmb3IgdGhlIGdpdmVuIHNlYXJjaC4gQ3JlYXRlIGEgdmFyaWFibGUgIm51bV9wYWdlcyIgZXF1YWwgdG8gdGhlIG1heCBudW1iZXIgb2YgcGFnZXMgZm9yIHRoZSBqb2Igc2VhcmNoLiBDcmVhdGUgYSB2YXJpYWJsZSAidXJsIiB1c2luZyB0aGUgY3JlYXRlX3VybCgpIGZ1bmN0aW9uIHdpdGggdGhlIHNhbWUgcGFyYW1ldGVycyB0aGFuIHRoZSBwcmV2aW91cyBzZWFyY2gsIGZvciB0aGUgcGFnZSBudW1iZXIgdXNlICJpIiBhcyB3ZSBhcmUgbG9vcGluZyBvdmVyIGFsbCB0aGUgcGFnZXMuDQoNCiogQ29tbWFuZHM6IGNyZWF0ZV91cmwod2Vic2l0ZSA9IEpPQlNJVEUgLCB0aXRsZSA9IEpPQlRJVExFLCBsb2NhdGlvbiA9IFNUQVRFLCByYWRpdXMgPSBOVU1fTUlMRVMsIHBhZ2UgPSBQQUdfTlVNKQ0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCg0KI3NpdGUgPSBKT0JfV0VCU0lURQ0KI2pvYiA9ICJEYXRhK0FuYWx5c3QiDQojcmVnaW9uID0gU1RBVEVfVFdPX0xFVFRFUlMNCiNtaWxlcyA9IE1JTEVTX05VTQ0KI3BhZyA9IFBBR19OVU0NCg0KbnVtX3BhZ2VzPSA5Mg0KDQojIENPTU1FTlQ6IExvb3Agb3ZlciB0aGUgbWF4IG51bWJlciBvZiBwYWdlcyBmb3IgdGhlIGpvYiBzZWFyY2gNCmZvciAoaSBpbiAxOm51bV9wYWdlcykgew0KICANCiAgIyBUT0RPOiBDcmVhdGUgYSB1cmwgZm9yIHRoZSBqb2Igc2VhcmNoDQogICN1cmwgPC0gY3JlYXRlX3VybCgpDQp1cmwgPC0gY3JlYXRlX3VybCh3ZWJzaXRlID0gc2l0ZSwgdGl0bGUgPSBqb2IsIGxvY2F0aW9uID0gcmVnaW9uLCByYWRpdXMgPSAzMCwgcGFnZSA9IGkpICANCiAgDQogICMgQ09NTUVOVDogcmVhZCB0aGUgY3JlYXRlZCBVUkwgYW5kIGNvbGxlY3RzIHRoZSBodG1sIGNvZGUNCiAgd2ViX2h0bWwgPC0gcmVhZF9odG1sKHVybCkNCg0KDQogICAgDQogICMgQ09NTUVOVDogSWYgc3RhdGVtZW50IHRvIGNyZWF0ZSB0aGUgZmlyc3QgZGF0YWZyYW1lDQogIGlmKGkgPT0gMSkgew0KICAgIA0KICAgICMgQ09NTUVOVDogQ3JlYXRlcyBhIHRpYmJsZSBkYXRhZnJhbWUgZXh0cmFjdGluZyBpbmZvcm1hdGlvbiBmcm9tIHRoZSBodG1sIGNvZGUNCiAgICBqb2JfZGF0YSA8LSBjcmVhdGVfdGliYmxlKGh0bWwgPSB3ZWJfaHRtbCkNCiAgICANCiAgfWVsc2V7DQogIA0KICAgICAgIyBDT01NRU5UOiBXZSBhZGQgbmV3IG9ic2VydmF0aW9uIHRvIHRoZSBmaXJzdCBkYXRhZnJhbWUNCiAgICBkZiA8LSBjcmVhdGVfdGliYmxlKGh0bWwgPSB3ZWJfaHRtbCkNCiAgICBqb2JfZGF0YSA8LSBiaW5kX3Jvd3Moam9iX2RhdGEsIGRmKQ0KICB9DQogIA0KICAjIENPTU1FTlQ6IFdlIGhhdmUgdG8gd2FpdCBhIGNvdXBsZSBvZiBzZWNvbmRzIGJlZm9yZSBtb3ZpbmcgdG8gdGhlIG5leHQgcGFnZQ0KICBTeXMuc2xlZXAoMC41KQ0KfQ0KDQpgYGANCg0KIyMjIDFDKSBNYWtlIHN1cmUgdGhhdCB0aGUgZGF0YSB3YXMgY29sbGVjdGVkIGNvcnJlY3RseS4gQnkgdXNpbmcgdGhlIGZ1bmN0aW9ucyB0byBpbnNwZWN0IGFuZCBzdW1tYXJpemUgdGhlIGRhdGEuIERlc2NyaWJlIHRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MgYW5kIG5vdGUgYW55IHNpZ25pZmljYW50IG9ic2VydmF0aW9ucy4NCg0KKiBEYXRhZnJhbWU6IGpvYl9kYXRhDQoqIENvbW1hbmRzOiBoZWFkKCkgc3VtbWFyeSgpIA0KDQpgYGB7cn0NCnN1bW1hcnkoam9iX2RhdGEpDQpoZWFkKGpvYl9kYXRhKQ0KYGBgDQoNCiMjIyAxRCkgQWZ0ZXIgbWFraW5nIHN1cmUgdGhhdCB0aGUgZGF0YSB3YXMgY29sbGVjdGVkIGNvcnJlY3RseSwgc2F2ZSB0aGUgZGF0YSBhcyBjc3YgZmlsZS4NCg0KKiBDb21tYW5kczogd3JpdGVfY3N2KHggPSBEQVRBRlJBTUUsIHBhdGggPSAiZGF0YS9EQVRBRlJBTUUiICkNCg0KYGBge3J9DQp3cml0ZV9jc3YoeCA9IGpvYl9kYXRhLCBwYXRoID0gImRhdGEvZGljZS1ueS5jc3YiICkNCmBgYA0KDQoNCi0tLS0tLS0tLS0tLS0NCg0KIyMgVGFzayAyOiBWaXN1YWxpemF0aW9uIEFuYWx5c2lzIC0gVGFibGVhdQ0KDQotLS0tLS0tLS0tLS0tDQoNCiMjIyAyQSkgVXBsb2FkIHlvdXIgZGF0YSBpbiBjc3YgZm9ybWF0IHRvIFRhYmxlYXUsIG1ha2UgYW55IGNoYW5nZXMgdG8gdGhlIGRhdGEgdHlwZXMgKEdFT0xPQ0FUSU9OLCBURVhULCBOVU1FUklDKS4gVGFrZSBhbiBzY3JlZW5zaG90IG9mIFRhYmxldSdzIGRhdGEgaW5zcGVjdGlvbi4gDQoNCmBgYHtyfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJzJBLlBORycpDQpgYGANCg0KDQojIyMgMkIpIFVzaW5nIHRhYmxlYXUgZ2VvbG9jYXRpb24gZmVhdHVyZXMgbWFwIGNpdGllcyB1c2luZyBidWJibGVzIHdoZXJlIHRoZSBzaXplIG9mIHRoZSBidWJibGUgaXMgY3VtdWxhdGl2ZSBudW1iZXIgb2Ygam9icyBsaXN0aW5nIGluIHRoYXQgY2l0eS4gTm90ZSBhbnkgaW50ZXJlc3RpbmcgcGF0dGVybnMsIGFkZCBhbiBzY3JlZW5zaG90IG9mIHlvdXIgdmlzdWFsaXphdGlvbi4NCg0KYGBge3J9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnMkIuUE5HJykNCmBgYA0KVGhpcyBpbWFnZSBzaG93cyB0aGUgbnVtYmVyIG9mIERhdGEgQW5hbHlzdCBwb3NpdGlvbnMgYXJvdW5kIE5ldyBZb3JrIENpdHkuIFRoZXJlIGFyZSBtb3JlIGpvYnMgY2xvc2VyIHRvIHRoZSBjaXR5IHJhdGhlciB0aGFuIGZ1cnRoZXIgd2hpY2ggbWFrZXMgc2Vuc2UgYmVjYXVzZSB0aGUgY2l0eSBpcyBhIG5hdHVyYWwgaHViIGZvciBjb21wYW5pZXMgdG8gaGF2ZSBvZmZpY2VzLg0KDQojIyMgMkMpIENyZWF0ZSBhIHRyZWUgbWFwLCB0byBjb21wYXJlIHRoZSBkaWZmZXJlbnQgY2l0aWVzIGFuZCB0aGUgY3VtdWxhdGl2ZSBudW1iZXIgb2Ygam9iIHBvc3RpbmcgaW4gZWFjaCBjaXR5LiBOb3RlIGFueSBpbnRlcmVzdGluZyBwYXR0ZXJucywgYWRkIGFuIHNjcmVlbnNob3Qgb2YgeW91ciB2aXN1YWxpemF0aW9uLg0KDQpgYGB7cn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCcyQy5QTkcnKQ0KYGBgDQpDbGVhcmx5IHRoZSBzdGF0ZSB3aWxsIGhhdmUgbW9yZSBvcGVuIHBvc2l0aW9ucyB0aGFuIHRoZSBpbmRpdmlkdWFsIGNpdGllLiBBcyBzb21lb25lIG5vdCBmcm9tL3ZlcnkgZmFtaWxpYXIgd2l0aCBjaXRpZXMgaW4gTmV3IFlvcmsgc3RhdGUsIGl0IGlzIGludGVyZXN0aW5nIHRvIG5vdGUgdGhhdCB0aGUgY2l0aWVzIEkgaGF2ZSBoZWFyZCBvZiBhcmUgbGlzdGVkLiBUaGlzIG1ha2VzIHNlbnNlIGJlY2F1c2UgbW9zdCBwZW9wbGUgYXJlIG1vcmUgZmFtaWxpYXIgd2l0aCBsYXJnZXIgY2l0aWVzIHdoaWNoIGhhdmUgbW9yZSBqb2Igb3Bwb3J0dW5pdGllcy4NCg0KIyMjIDJEKSBDcmVhdGUgYSBCYXIgcGxvdCBieSBTdGF0ZSBhbmQgQ2l0eS4gVG8gZGlzcGxheSB0aGUgY3VtdWxhdGl2ZSBudW1iZXIgb2Ygam9icyBpbiBlYWNoIGNpdHkuIE5vdGUgYW55IGludGVyZXN0aW5nIHBhdHRlcm5zLCBhZGQgYW4gc2NyZWVuc2hvdCBvZiB5b3VyIHZpc3VhbGl6YXRpb24uDQoNCmBgYHtyfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJzJELlBORycpDQpgYGANCkFjY29yZGluZyB0byB0aGUgZ3JhcGgsIE5ZQyBoYXMgdGhlIG1vc3Qgb3Bwb3J0dW5pdGllcyBmb2xsb3dlZCBieSBSb2NoZXN0ZXIuDQoNCiMjIyAyRSkgQ3JlYXRlIGEgZGFzaGJvYXJkIHRvIGRpc3BsYXkgdGhlIHRocmVlIHBsb3RzIGFib3ZlLiBVc2UgaGFsZiBvZiB0aGUgZGFzaGJvYXJkIHRvIGRpc3BsYXkgdGhlIG1hcCB3aXRoIHRoZSBsb2NhdGlvbiBvZiB0aGUgY2l0aWVzLiBPbiB0aGUgYm90dG9tIG9mIHRoZSBkYXNoYm9hcmQgcGxhY2UgdGhlIG90aGVyIHR3byBjaGFydHMsIGFkZCB0aXRsZXMgdG8gZWFjaCBjaGFydC4gTm90ZSBhbnkgaW50ZXJlc3RpbmcgcGF0dGVybnMsIGFkZCBhbiBzY3JlZW5zaG90IG9mIHlvdXIgdmlzdWFsaXphdGlvbi4NCmBgYHtyfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJzJFLlBORycpDQpgYGANCkJlY2F1c2UgdGhlIGRhdGEgdGhyb3VnaG91dCB0aGlzIHByb2Nlc3Mgd2FzIGNvbnNpc3RlbnQsIHRoZSBkYXNoYm9hcmQgZ2l2ZXMgdGhlIHNhbWUgY29uY2x1c2lvbnMgdGhhdCBlYWNoIG9mIHRoZSBncmFwaHMgc2hvd2VkOiBsYXJnZXIsIG1vcmUgcG9wdWxhdGVkIGNpdGllcyBoYXZlIGdyZWF0ZXIgbnVtYmVycyBvZiBqb2IgcHJvc3BlY3RzLg0KLS0tLS0tLS0tLS0tLQ0KDQojIyBUYXNrIDM6IFdhdHNvbiBBbmFseXNpcw0KDQotLS0tLS0tLS0tLS0tDQoNClRvIGNvbXBsZXRlIHRoZSBsYXN0IHRhc2ssIGZvbGxvdyB0aGUgZGlyZWN0aW9ucyBmb3VuZCBiZWxvdy4gTWFrZSBzdXJlIHRvIHNjcmVlbnNob3QgYW5kIGF0dGFjaCBhbnkgcGljdHVyZXMgb2YgdGhlIHJlc3VsdHMgb2J0YWluZWQgb3IgYW55IHF1ZXN0aW9ucyBhc2tlZC4gDQoNCiMjIyAzQSkgVXBsb2FkIHlvdSBkYXRhIHRvIHdhdHNvbiwgZXhwbG9yZSB0aGUgZGlmZmVyZW50IGluc2lnaHRzLiBUYWtlIDMgc2NyZWVuc2hvdHMgb2YgeW91ciBpbnNpZ2h0cyBhbmQgZGVzY3JpYmUgeW91ciBmaW5kaW5ncy4NCg0KYGBge3J9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnM0EuUE5HJykNCg0KYGBgDQpJIHRob3VnaHQgaXQgd291bGQgYmUgaW50ZXJlc3RpbmcgdG8gaW5jbHVkZSB0aGUgc2FtZSBncmFwaCBzaG93biBpbiB0YWJsZWF1IHRvIHNlZSBpZiBpdCBwcm9kdWNlZCB0aGUgc2FtZSByZXN1bHRzLiBJdCBkaWQsIHNvIHRoZXJlIGlzIG5vdCBhbnkgbmV3IGluZm9ybWF0aW9uLCBidXQgaXQgZGVtb25zdHJhdGVzIGNvbnNpc3RlbmN5IGluIHRoZSBmaW5kaW5ncy4NCg0KIyMjIDNCKSBXYXRzb24gQW5hbHl0aWNzIEluc2lnaHRzLCBkZXNjcmliZSB5b3VyIGZpbmRpbmdzLg0KYGBge3J9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnM0IuUE5HJykNCmBgYA0KV2hpbGUgSSBjb3VsZG4ndCBnZXQgYSBnb29kIHNjcmVlbnNob3QsIHRoaXMgZ3JhcGggd2FzIGEgZGVjaXNpb24gdHJlZSB0aGF0IGJyb2tlIGRvd24gam9iIHRpdGxlIGJhc2VkIG9uIGxvY2F0aW9uIHdoaWNoIHdhcyBzdXBlciBpbnRlcmVzdGluZy4gU28gYXMgaXQgZmlsdGVyZWQgdGhyb3VnaCB5b3UgY291bGQgc2VlIHdoaWNoIGpvYnMgd2VyZSBtb3JlIHN1aXRlZCB0byBmaW5kIGluIHdoaWNoIGxvY2F0aW9ucyBhbmQgaG93IGZyZXF1ZW50bHkgdGhleSB3ZXJlIHBvc3RlZC4gDQojIyMgM0MpIFdhdHNvbiBBbmFseXRpY3MgSW5zaWdodHMsIGRlc2NyaWJlIHlvdXIgZmluZGluZ3MuDQpgYGB7cn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCczQy5QTkcnKQ0KYGBgDQpUaGlzIGJyb2tlIGRvd24gdGhlIG51bWJlciBvZiBjb21wYW5pZXMgbG9jYXRlZCBpbiBlYWNoIGFyZWEuIEFsbCBvZiB0aGUgY29tcGFuaWVzIHdlcmUgaW4gTmV3IFlvcmssIHNvIGNsZWFybHkgdGhhdCBoYWQgdGhlIGhpZ2hlc3QgY29uY2VudHJhdGlvbiwgYnV0IGl0IHdhcyBpbnRlcmVzdGluZyB0aGF0IHdoZW4geW91IGJyb2tlIGl0IGRvd24gYnkgY29tcGFueSBhbmQgbm90IHBvc2l0aW9uIGl0IHdhcyBtb3JlIGV2ZW5seSBkaXNwZXJzZWQgd2hpY2ggc2hvd3MgdGhhdCB0aGVyZSBtYXkgbm90IGJlIG1vcmUgY29tcGFuaWVzIGluIGxhcmdlciBjaXRpZXMgYnV0IHJhdGhlciB0aGUgc2FtZSBudW1iZXIgb2YgY29tcGFuaWVzLCBidXQgd2l0aCBhIGxhcmdlciBuZWVkIGZvciBuZXcgZW1wbG95ZWVzLg0KDQo=