SQL Interview Questions

Data Analysis

Run libraries

library(devtools)
library(DBI)
library(tidyverse)
library(RSQLite)
library(DescTools)
library(DT)
library(Datatablethemes)
airbnb_search_details <- read.csv(file = 'airbnb_search_details.csv')
airbnb_reviews <- read.csv(file = 'airbnb_reviews.csv')
airbnb_hosts <- read.csv(file = 'airbnb_hosts.csv')
airbnb_host_searches <- read.csv(file = 'airbnb_host_searches.csv')
product_pricing <- read.csv(file = 'product_pricing.csv')
product_sales <- read.csv(file = 'product_sales.csv')
orders <- read.csv(file = "orders.csv")
vendor_spend <- read.csv(file = 'Vendor_spend.csv')
candidateColleges <- read.csv(file = 'candidateColleges.csv')
candidateInterviews <- read.csv(file = 'candidateInterviews.csv')

3 Bed Minimum (easy)

Find the average number of beds in each neighborhood that has at least 3 beds in total.

Output results along with the neighborhood name and sort the results based on the number of average beds in descending order.

Table: airbnb_search_details

airbnb_search_details %>% 
  group_by(neighbourhood) %>% 
  summarise(SUM_beds = sum(beds), AVG_beds = mean(beds)) %>% 
  filter(SUM_beds >=3) %>% 
  arrange(desc(AVG_beds)) %>% 
  select(neighbourhood, AVG_beds) %>% 
  Datatablethemes::Datatable_green()

Favorite Host Nationality (Medium)

For each guest reviewer, find the nationality of the reviewer’s favorite host based on the guest’s highest review score given to a host. Output the user ID of the guest along with their favorite host’s nationality. In case there is more than one favorite host from the same country, list that country only once (remove duplicates).

Both the from_user and to_user columns are user IDs.

Tables: airbnb_reviews, airbnb_hosts

airbnb_reviews %>% 
  filter(from_type == "guest") %>% 
  left_join(., airbnb_hosts %>% 
              group_by(host_id) %>% 
              summarise(nationality = max(nationality)),
            by = c("to_user" = "host_id")) %>%
  group_by(from_user) %>% 
  mutate(max_review_score = max(review_score)) %>% 
  select(1,6,5,7) %>% 
  arrange(from_user) %>% 
  filter(review_score == max_review_score) %>% 
  group_by(from_user, nationality) %>% 
  summarise() %>% 
  Datatablethemes::Datatable_blue()

Host Popularity Rental Prices (Hard)

You’re given a table of rental property searches by users. The table consists of search results and outputs host information for searchers. Find the minimum, average, maximum rental prices for each host’s popularity rating. The host’s popularity rating is defined as below:

Tip: The id column in the table refers to the search ID. You’ll need to create your own host_id by concating price, room_type, host_since, zipcode, and number_of_reviews.

Output host popularity rating and their minimum, average and maximum rental prices.

Table: airbnb_host_searches

airbnb_host_searches %>% 
  unite('Host_id', c(room_type, host_since, zipcode, number_of_reviews), remove = FALSE, sep = "") %>% 
  mutate(Popularity_Rating = case_when(
    number_of_reviews == 0 | number_of_reviews == NA ~ "New",
    number_of_reviews < 6 ~ "Rising",
    number_of_reviews < 16 ~ "Trending Up",
    number_of_reviews < 41 ~ "Popular",
    TRUE ~ "Hot" ## Same as saying Else
  )) %>% 
  group_by(Host_id, price, Popularity_Rating) %>% 
  summarise() %>% 
  group_by(Popularity_Rating) %>% 
  summarise(min_price = dollar(min(price)), 
            avg_price = dollar(mean(price)),
            max_price = dollar(max(price))) %>% 
  Datatablethemes::Datatable_red()

Beverage Sales (Easy)

Suppose you’re provided two tables, as shown below. One table contains the price for a given product in a given region, while another contains sales for the past week. Given the two tables write a SQL query to pull the total earnings for each product/region combination.

Table: product_pricing, product_sales

product_pricing %>% 
  mutate(price = gsub(price, pattern = "$", fixed = T, replacement = "")) %>% 
  mutate(price = as.numeric(price)) %>% 
  left_join(., product_sales, by = c("region", "product")) %>% 
  mutate(revenue = dollar(price * num_sales)) %>% 
  select(1,2,5) %>% 
  Datatable_purple()

Monthly Revenue growth (Medium)

Given the table below, called ‘orders’, write a SQL query to show the monthly revenue growth. To calculate the monthly revenue growth, you can apply the following logic:

revenue growth = (current month’s revenue-prior month’s revenue)/prior month’s revenue.

orders %>% 
  group_by(rev_month) %>% 
  summarise(monthly_revenue = sum(revenue)) %>% 
  mutate(lm_revenue = lag(monthly_revenue)) %>% 
  mutate(rev_growth = (monthly_revenue - lm_revenue) / lm_revenue) %>% 
  Datatable_green()

Ranking Vendors by spend (Easy)

Suppose you have a table called ‘vendor_spend’ containing vendor spend data, as shown.

Table: vendor_spend

vendor_spend %>% 
  group_by(name) %>% 
  summarise(spend = sum(total_spend)) %>% 
  filter(spend > quantile(spend, .5)) %>% 
  arrange(desc(spend)) %>% 
  mutate(spend = dollar(spend)) %>% 
  Datatable_blue()

Top Candidates by college (Easy)

Suppose your team interviews undergraduate candidates across many different colleges. You are looking to check which candidates scored the highest from each college.

Given the below table, write a SQL query (using a window function) to show which candidates scored the highest from each college.

Tables: candidateColleges, candidateInterviews

candidateColleges %>% 
  left_join(., candidateInterviews, by = "candidate_name") %>% 
  group_by(college_id) %>% 
  mutate(Rank = rank(-Interview_score, ties.method = "min")) %>% 
  filter(Rank == 1) %>% 
  select(2,4,1,5) %>% 
  Datatable_red()

Twitch Content Creators (Hard)

You are working for a company like Twitch.tv. Twitch is a live streaming platform, where content creators (e.g. the people creating content on the live streams) can get donations from viewers for producing content they support.

Your company is trying to launch a new product that will benefit content creators that get a large amount of donations per streaming session. See tables below

Given this, write an SQL query to find the top 10 content creators in 2018 that have the highest average donations per viewer.

Tables: all_donations, sessions_info, session_viewers

all_donations
Column Name Data Type Description
creator_id integer Unique id of content creator
viewer_id integer Unique id of viewer
session_id integer unique session id of stream
date string format is ‘YYYY-MM-DD’
donation_amount integer amount donated in USD
sessions_info
Column Name Data Type Description
creator_id integer Unique id of content creator
session_id integer unique session id of stream
date string format is ‘YYYY-MM-DD’
length integer length of session
session_viewers
Column Name Data Type Description
creator_id integer Unique id of content creator
viewer_id integer Unique id of viewer
session_id integer unique session id of stream
date string format is ‘YYYY-MM-DD’
mins_viewed integer The stream
all_donations %>% 
  filter(date >= '2018-01-01' & date <= '2019-01-01') %>% 
  group_by(creator_id) %>% 
  summarise(avg_donation = sum(donation_amount) / length(viewer_id)) %>% 
  arrange(desc(avg_donation)) %>% 
  head(10)
LS0tDQphdXRob3I6ICJFcmlrIFJhbmRhbGwiDQpkYXRlOiAiMjAyMi0wOS0xNiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdGhlbWU6IHBhcGVyDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IHllcw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFKQ0KYGBgDQoNCiMgKipTUUwgSW50ZXJ2aWV3IFF1ZXN0aW9ucyoqIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQ0KDQojIyAqKkRhdGEgQW5hbHlzaXMqKg0KDQojIyMjICoqUnVuIGxpYnJhcmllcyoqDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KGRldnRvb2xzKQ0KbGlicmFyeShEQkkpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoUlNRTGl0ZSkNCmxpYnJhcnkoRGVzY1Rvb2xzKQ0KbGlicmFyeShEVCkNCmxpYnJhcnkoRGF0YXRhYmxldGhlbWVzKQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KGRvd25sb2FkdGhpcykNCmBgYA0KDQotLS0NCmxpYnJhcnkoZGV2dG9vbHMpDQpsaWJyYXJ5KERCSSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShSU1FMaXRlKQ0KbGlicmFyeShEZXNjVG9vbHMpDQpsaWJyYXJ5KERUKQ0KbGlicmFyeShEYXRhdGFibGV0aGVtZXMpDQotLS0NCg0KYGBge3J9DQphaXJibmJfc2VhcmNoX2RldGFpbHMgPC0gcmVhZC5jc3YoZmlsZSA9ICdhaXJibmJfc2VhcmNoX2RldGFpbHMuY3N2JykNCmFpcmJuYl9yZXZpZXdzIDwtIHJlYWQuY3N2KGZpbGUgPSAnYWlyYm5iX3Jldmlld3MuY3N2JykNCmFpcmJuYl9ob3N0cyA8LSByZWFkLmNzdihmaWxlID0gJ2FpcmJuYl9ob3N0cy5jc3YnKQ0KYWlyYm5iX2hvc3Rfc2VhcmNoZXMgPC0gcmVhZC5jc3YoZmlsZSA9ICdhaXJibmJfaG9zdF9zZWFyY2hlcy5jc3YnKQ0KcHJvZHVjdF9wcmljaW5nIDwtIHJlYWQuY3N2KGZpbGUgPSAncHJvZHVjdF9wcmljaW5nLmNzdicpDQpwcm9kdWN0X3NhbGVzIDwtIHJlYWQuY3N2KGZpbGUgPSAncHJvZHVjdF9zYWxlcy5jc3YnKQ0Kb3JkZXJzIDwtIHJlYWQuY3N2KGZpbGUgPSAib3JkZXJzLmNzdiIpDQp2ZW5kb3Jfc3BlbmQgPC0gcmVhZC5jc3YoZmlsZSA9ICdWZW5kb3Jfc3BlbmQuY3N2JykNCmNhbmRpZGF0ZUNvbGxlZ2VzIDwtIHJlYWQuY3N2KGZpbGUgPSAnY2FuZGlkYXRlQ29sbGVnZXMuY3N2JykNCmNhbmRpZGF0ZUludGVydmlld3MgPC0gcmVhZC5jc3YoZmlsZSA9ICdjYW5kaWRhdGVJbnRlcnZpZXdzLmNzdicpDQpgYGANCg0KIyMjICoqMyBCZWQgTWluaW11bSAoZWFzeSkqKg0KDQojIyMjIEZpbmQgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIGJlZHMgaW4gZWFjaCBuZWlnaGJvcmhvb2QgdGhhdCBoYXMgYXQgbGVhc3QgMyBiZWRzIGluIHRvdGFsLg0KDQojIyMjIE91dHB1dCByZXN1bHRzIGFsb25nIHdpdGggdGhlIG5laWdoYm9yaG9vZCBuYW1lIGFuZCBzb3J0IHRoZSByZXN1bHRzIGJhc2VkIG9uIHRoZSBudW1iZXIgb2YgYXZlcmFnZSBiZWRzIGluIGRlc2NlbmRpbmcgb3JkZXIuDQoNCiMjIyMgKipUYWJsZToqKiBbYWlyYm5iX3NlYXJjaF9kZXRhaWxzXXtzdHlsZT0iY29sb3I6Ymx1ZSJ9DQoNCmBgYHtyfQ0KYWlyYm5iX3NlYXJjaF9kZXRhaWxzICU+JSANCiAgZ3JvdXBfYnkobmVpZ2hib3VyaG9vZCkgJT4lIA0KICBzdW1tYXJpc2UoU1VNX2JlZHMgPSBzdW0oYmVkcyksIEFWR19iZWRzID0gbWVhbihiZWRzKSkgJT4lIA0KICBmaWx0ZXIoU1VNX2JlZHMgPj0zKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhBVkdfYmVkcykpICU+JSANCiAgc2VsZWN0KG5laWdoYm91cmhvb2QsIEFWR19iZWRzKSAlPiUgDQogIERhdGF0YWJsZXRoZW1lczo6RGF0YXRhYmxlX2dyZWVuKCkNCmBgYA0KDQojIyMgKipGYXZvcml0ZSBIb3N0IE5hdGlvbmFsaXR5IChNZWRpdW0pKioNCg0KIyMjIyBGb3IgZWFjaCBndWVzdCByZXZpZXdlciwgZmluZCB0aGUgbmF0aW9uYWxpdHkgb2YgdGhlIHJldmlld2VyJ3MgZmF2b3JpdGUgaG9zdCBiYXNlZCBvbiB0aGUgZ3Vlc3QncyBoaWdoZXN0IHJldmlldyBzY29yZSBnaXZlbiB0byBhIGhvc3QuIE91dHB1dCB0aGUgdXNlciBJRCBvZiB0aGUgZ3Vlc3QgYWxvbmcgd2l0aCB0aGVpciBmYXZvcml0ZSBob3N0J3MgbmF0aW9uYWxpdHkuIEluIGNhc2UgdGhlcmUgaXMgbW9yZSB0aGFuIG9uZSBmYXZvcml0ZSBob3N0IGZyb20gdGhlIHNhbWUgY291bnRyeSwgbGlzdCB0aGF0IGNvdW50cnkgb25seSBvbmNlIChyZW1vdmUgZHVwbGljYXRlcykuDQoNCiMjIyMgQm90aCB0aGUgZnJvbV91c2VyIGFuZCB0b191c2VyIGNvbHVtbnMgYXJlIHVzZXIgSURzLg0KDQojIyMjICoqVGFibGVzOioqIFthaXJibmJfcmV2aWV3cywgYWlyYm5iX2hvc3RzXXtzdHlsZT0iY29sb3I6Ymx1ZSJ9DQoNCmBgYHtyfQ0KYWlyYm5iX3Jldmlld3MgJT4lIA0KICBmaWx0ZXIoZnJvbV90eXBlID09ICJndWVzdCIpICU+JSANCiAgbGVmdF9qb2luKC4sIGFpcmJuYl9ob3N0cyAlPiUgDQogICAgICAgICAgICAgIGdyb3VwX2J5KGhvc3RfaWQpICU+JSANCiAgICAgICAgICAgICAgc3VtbWFyaXNlKG5hdGlvbmFsaXR5ID0gbWF4KG5hdGlvbmFsaXR5KSksDQogICAgICAgICAgICBieSA9IGMoInRvX3VzZXIiID0gImhvc3RfaWQiKSkgJT4lDQogIGdyb3VwX2J5KGZyb21fdXNlcikgJT4lIA0KICBtdXRhdGUobWF4X3Jldmlld19zY29yZSA9IG1heChyZXZpZXdfc2NvcmUpKSAlPiUgDQogIHNlbGVjdCgxLDYsNSw3KSAlPiUgDQogIGFycmFuZ2UoZnJvbV91c2VyKSAlPiUgDQogIGZpbHRlcihyZXZpZXdfc2NvcmUgPT0gbWF4X3Jldmlld19zY29yZSkgJT4lIA0KICBncm91cF9ieShmcm9tX3VzZXIsIG5hdGlvbmFsaXR5KSAlPiUgDQogIHN1bW1hcmlzZSgpICU+JSANCiAgRGF0YXRhYmxldGhlbWVzOjpEYXRhdGFibGVfYmx1ZSgpDQpgYGANCg0KIyMjICoqSG9zdCBQb3B1bGFyaXR5IFJlbnRhbCBQcmljZXMgKEhhcmQpKioNCg0KIyMjIyBZb3UncmUgZ2l2ZW4gYSB0YWJsZSBvZiByZW50YWwgcHJvcGVydHkgc2VhcmNoZXMgYnkgdXNlcnMuIFRoZSB0YWJsZSBjb25zaXN0cyBvZiBzZWFyY2ggcmVzdWx0cyBhbmQgb3V0cHV0cyBob3N0IGluZm9ybWF0aW9uIGZvciBzZWFyY2hlcnMuIEZpbmQgdGhlIG1pbmltdW0sIGF2ZXJhZ2UsIG1heGltdW0gcmVudGFsIHByaWNlcyBmb3IgZWFjaCBob3N0J3MgcG9wdWxhcml0eSByYXRpbmcuIFRoZSBob3N0J3MgcG9wdWxhcml0eSByYXRpbmcgaXMgZGVmaW5lZCBhcyBiZWxvdzoNCg0KIyMjIyAwIHJldmlld3M6IE5ldzxicj4xIHRvIDUgcmV2aWV3czogUmlzaW5nPGJyPjYgdG8gMTUgcmV2aWV3czogVHJlbmRpbmcgVXA8YnI+MTYgdG8gNDAgcmV2aWV3czogUG9wdWxhcjxicj5tb3JlIHRoYW4gNDAgcmV2aWV3czogSG90DQoNCiMjIyMgKipUaXA6KiogVGhlIGlkIGNvbHVtbiBpbiB0aGUgdGFibGUgcmVmZXJzIHRvIHRoZSBzZWFyY2ggSUQuIFlvdSdsbCBuZWVkIHRvIGNyZWF0ZSB5b3VyIG93biBob3N0X2lkIGJ5IGNvbmNhdGluZyBwcmljZSwgcm9vbV90eXBlLCBob3N0X3NpbmNlLCB6aXBjb2RlLCBhbmQgbnVtYmVyX29mX3Jldmlld3MuDQoNCiMjIyMgT3V0cHV0IGhvc3QgcG9wdWxhcml0eSByYXRpbmcgYW5kIHRoZWlyIG1pbmltdW0sIGF2ZXJhZ2UgYW5kIG1heGltdW0gcmVudGFsIHByaWNlcy4NCg0KIyMjIyAqKlRhYmxlOioqIFthaXJibmJfaG9zdF9zZWFyY2hlc117c3R5bGU9ImNvbG9yOmJsdWUifQ0KDQpgYGB7cn0NCmFpcmJuYl9ob3N0X3NlYXJjaGVzICU+JSANCiAgdW5pdGUoJ0hvc3RfaWQnLCBjKHJvb21fdHlwZSwgaG9zdF9zaW5jZSwgemlwY29kZSwgbnVtYmVyX29mX3Jldmlld3MpLCByZW1vdmUgPSBGQUxTRSwgc2VwID0gIiIpICU+JSANCiAgbXV0YXRlKFBvcHVsYXJpdHlfUmF0aW5nID0gY2FzZV93aGVuKA0KICAgIG51bWJlcl9vZl9yZXZpZXdzID09IDAgfCBudW1iZXJfb2ZfcmV2aWV3cyA9PSBOQSB+ICJOZXciLA0KICAgIG51bWJlcl9vZl9yZXZpZXdzIDwgNiB+ICJSaXNpbmciLA0KICAgIG51bWJlcl9vZl9yZXZpZXdzIDwgMTYgfiAiVHJlbmRpbmcgVXAiLA0KICAgIG51bWJlcl9vZl9yZXZpZXdzIDwgNDEgfiAiUG9wdWxhciIsDQogICAgVFJVRSB+ICJIb3QiICMjIFNhbWUgYXMgc2F5aW5nIEVsc2UNCiAgKSkgJT4lIA0KICBncm91cF9ieShIb3N0X2lkLCBwcmljZSwgUG9wdWxhcml0eV9SYXRpbmcpICU+JSANCiAgc3VtbWFyaXNlKCkgJT4lIA0KICBncm91cF9ieShQb3B1bGFyaXR5X1JhdGluZykgJT4lIA0KICBzdW1tYXJpc2UobWluX3ByaWNlID0gZG9sbGFyKG1pbihwcmljZSkpLCANCiAgICAgICAgICAgIGF2Z19wcmljZSA9IGRvbGxhcihtZWFuKHByaWNlKSksDQogICAgICAgICAgICBtYXhfcHJpY2UgPSBkb2xsYXIobWF4KHByaWNlKSkpICU+JSANCiAgRGF0YXRhYmxldGhlbWVzOjpEYXRhdGFibGVfcmVkKCkNCmBgYA0KDQojIyMgKipCZXZlcmFnZSBTYWxlcyAoRWFzeSkqKg0KDQojIyMjIFN1cHBvc2UgeW91J3JlIHByb3ZpZGVkIHR3byB0YWJsZXMsIGFzIHNob3duIGJlbG93LiBPbmUgdGFibGUgY29udGFpbnMgdGhlIHByaWNlIGZvciBhIGdpdmVuIHByb2R1Y3QgaW4gYSBnaXZlbiByZWdpb24sIHdoaWxlIGFub3RoZXIgY29udGFpbnMgc2FsZXMgZm9yIHRoZSBwYXN0IHdlZWsuIEdpdmVuIHRoZSB0d28gdGFibGVzIHdyaXRlIGEgU1FMIHF1ZXJ5IHRvIHB1bGwgdGhlIHRvdGFsIGVhcm5pbmdzIGZvciBlYWNoIHByb2R1Y3QvcmVnaW9uIGNvbWJpbmF0aW9uLg0KDQojIyMjICoqVGFibGU6KiogW3Byb2R1Y3RfcHJpY2luZywgcHJvZHVjdF9zYWxlc117c3R5bGU9ImNvbG9yOmJsdWUifQ0KDQpgYGB7cn0NCnByb2R1Y3RfcHJpY2luZyAlPiUgDQogIG11dGF0ZShwcmljZSA9IGdzdWIocHJpY2UsIHBhdHRlcm4gPSAiJCIsIGZpeGVkID0gVCwgcmVwbGFjZW1lbnQgPSAiIikpICU+JSANCiAgbXV0YXRlKHByaWNlID0gYXMubnVtZXJpYyhwcmljZSkpICU+JSANCiAgbGVmdF9qb2luKC4sIHByb2R1Y3Rfc2FsZXMsIGJ5ID0gYygicmVnaW9uIiwgInByb2R1Y3QiKSkgJT4lIA0KICBtdXRhdGUocmV2ZW51ZSA9IGRvbGxhcihwcmljZSAqIG51bV9zYWxlcykpICU+JSANCiAgc2VsZWN0KDEsMiw1KSAlPiUgDQogIERhdGF0YWJsZV9wdXJwbGUoKQ0KYGBgDQoNCiMjIyAqKk1vbnRobHkgUmV2ZW51ZSBncm93dGggKE1lZGl1bSkqKg0KDQojIyMjIEdpdmVuIHRoZSB0YWJsZSBiZWxvdywgY2FsbGVkICdvcmRlcnMnLCB3cml0ZSBhIFNRTCBxdWVyeSB0byBzaG93IHRoZSBtb250aGx5IHJldmVudWUgZ3Jvd3RoLiBUbyBjYWxjdWxhdGUgdGhlIG1vbnRobHkgcmV2ZW51ZSBncm93dGgsIHlvdSBjYW4gYXBwbHkgdGhlIGZvbGxvd2luZyBsb2dpYzoNCg0KIyMjIyByZXZlbnVlIGdyb3d0aCA9IChjdXJyZW50IG1vbnRoJ3MgcmV2ZW51ZS1wcmlvciBtb250aCdzIHJldmVudWUpL3ByaW9yIG1vbnRoJ3MgcmV2ZW51ZS4NCg0KYGBge3J9DQpvcmRlcnMgJT4lIA0KICBncm91cF9ieShyZXZfbW9udGgpICU+JSANCiAgc3VtbWFyaXNlKG1vbnRobHlfcmV2ZW51ZSA9IHN1bShyZXZlbnVlKSkgJT4lIA0KICBtdXRhdGUobG1fcmV2ZW51ZSA9IGxhZyhtb250aGx5X3JldmVudWUpKSAlPiUgDQogIG11dGF0ZShyZXZfZ3Jvd3RoID0gKG1vbnRobHlfcmV2ZW51ZSAtIGxtX3JldmVudWUpIC8gbG1fcmV2ZW51ZSkgJT4lIA0KICBEYXRhdGFibGVfZ3JlZW4oKQ0KYGBgDQoNCiMjIyAqKlJhbmtpbmcgVmVuZG9ycyBieSBzcGVuZCAoRWFzeSkqKg0KDQojIyMjIFN1cHBvc2UgeW91IGhhdmUgYSB0YWJsZSBjYWxsZWQgJ3ZlbmRvcl9zcGVuZCcgY29udGFpbmluZyB2ZW5kb3Igc3BlbmQgZGF0YSwgYXMgc2hvd24uDQoNCiMjIyMgKipUYWJsZToqKiBbdmVuZG9yX3NwZW5kXXtzdHlsZT0iY29sb3I6Ymx1ZSJ9DQoNCmBgYHtyfQ0KdmVuZG9yX3NwZW5kICU+JSANCiAgZ3JvdXBfYnkobmFtZSkgJT4lIA0KICBzdW1tYXJpc2Uoc3BlbmQgPSBzdW0odG90YWxfc3BlbmQpKSAlPiUgDQogIGZpbHRlcihzcGVuZCA+IHF1YW50aWxlKHNwZW5kLCAuNSkpICU+JSANCiAgYXJyYW5nZShkZXNjKHNwZW5kKSkgJT4lIA0KICBtdXRhdGUoc3BlbmQgPSBkb2xsYXIoc3BlbmQpKSAlPiUgDQogIERhdGF0YWJsZV9ibHVlKCkNCmBgYA0KDQojIyMgKipUb3AgQ2FuZGlkYXRlcyBieSBjb2xsZWdlIChFYXN5KSoqDQoNCiMjIyMgU3VwcG9zZSB5b3VyIHRlYW0gaW50ZXJ2aWV3cyB1bmRlcmdyYWR1YXRlIGNhbmRpZGF0ZXMgYWNyb3NzIG1hbnkgZGlmZmVyZW50IGNvbGxlZ2VzLiBZb3UgYXJlIGxvb2tpbmcgdG8gY2hlY2sgd2hpY2ggY2FuZGlkYXRlcyBzY29yZWQgdGhlIGhpZ2hlc3QgZnJvbSBlYWNoIGNvbGxlZ2UuIA0KDQojIyMjIEdpdmVuIHRoZSBiZWxvdyB0YWJsZSwgd3JpdGUgYSBTUUwgcXVlcnkgKHVzaW5nIGEgd2luZG93IGZ1bmN0aW9uKSB0byBzaG93IHdoaWNoIGNhbmRpZGF0ZXMgc2NvcmVkIHRoZSBoaWdoZXN0IGZyb20gZWFjaCBjb2xsZWdlLg0KDQojIyMjICoqVGFibGVzOioqIFtjYW5kaWRhdGVDb2xsZWdlcywgY2FuZGlkYXRlSW50ZXJ2aWV3c117c3R5bGU9ImNvbG9yOmJsdWUifQ0KDQpgYGB7cn0NCmNhbmRpZGF0ZUNvbGxlZ2VzICU+JSANCiAgbGVmdF9qb2luKC4sIGNhbmRpZGF0ZUludGVydmlld3MsIGJ5ID0gImNhbmRpZGF0ZV9uYW1lIikgJT4lIA0KICBncm91cF9ieShjb2xsZWdlX2lkKSAlPiUgDQogIG11dGF0ZShSYW5rID0gcmFuaygtSW50ZXJ2aWV3X3Njb3JlLCB0aWVzLm1ldGhvZCA9ICJtaW4iKSkgJT4lIA0KICBmaWx0ZXIoUmFuayA9PSAxKSAlPiUgDQogIHNlbGVjdCgyLDQsMSw1KSAlPiUgDQogIERhdGF0YWJsZV9yZWQoKQ0KYGBgDQoNCiMjIyAqKlR3aXRjaCBDb250ZW50IENyZWF0b3JzIChIYXJkKSoqDQoNCiMjIyMgWW91IGFyZSB3b3JraW5nIGZvciBhIGNvbXBhbnkgbGlrZSBUd2l0Y2gudHYuIFR3aXRjaCBpcyBhIGxpdmUgc3RyZWFtaW5nIHBsYXRmb3JtLCB3aGVyZSBjb250ZW50IGNyZWF0b3JzIChlLmcuIHRoZSBwZW9wbGUgY3JlYXRpbmcgY29udGVudCBvbiB0aGUgbGl2ZSBzdHJlYW1zKSBjYW4gZ2V0IGRvbmF0aW9ucyBmcm9tIHZpZXdlcnMgZm9yIHByb2R1Y2luZyBjb250ZW50IHRoZXkgc3VwcG9ydC4gDQoNCiMjIyMgWW91ciBjb21wYW55IGlzIHRyeWluZyB0byBsYXVuY2ggYSBuZXcgcHJvZHVjdCB0aGF0IHdpbGwgYmVuZWZpdCBjb250ZW50IGNyZWF0b3JzIHRoYXQgZ2V0IGEgbGFyZ2UgYW1vdW50IG9mIGRvbmF0aW9ucyBwZXIgc3RyZWFtaW5nIHNlc3Npb24uIFNlZSB0YWJsZXMgYmVsb3cNCg0KIyMjIyBHaXZlbiB0aGlzLCB3cml0ZSBhbiBTUUwgcXVlcnkgdG8gZmluZCB0aGUgdG9wIDEwIGNvbnRlbnQgY3JlYXRvcnMgaW4gMjAxOCB0aGF0IGhhdmUgdGhlIGhpZ2hlc3QgYXZlcmFnZSBkb25hdGlvbnMgcGVyICB2aWV3ZXIuDQoNCiMjIyMgKipUYWJsZXM6KiogW2FsbF9kb25hdGlvbnMsIHNlc3Npb25zX2luZm8sIHNlc3Npb25fdmlld2Vyc117c3R5bGU9ImNvbG9yOmJsdWUifQ0KDQojIyMjIyBbYWxsX2RvbmF0aW9uc117c3R5bGU9ImNvbG9yOnJlZCJ9DQoNCkNvbHVtbiBOYW1lIHwgRGF0YSBUeXBlIHwgRGVzY3JpcHRpb24NCi0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0NCmNyZWF0b3JfaWQgIHwgaW50ZWdlciAgIHwgVW5pcXVlIGlkIG9mIGNvbnRlbnQgY3JlYXRvcg0Kdmlld2VyX2lkICAgfCBpbnRlZ2VyICAgfCBVbmlxdWUgaWQgb2Ygdmlld2VyDQpzZXNzaW9uX2lkICB8IGludGVnZXIgICB8IHVuaXF1ZSBzZXNzaW9uIGlkIG9mIHN0cmVhbQ0KZGF0ZSAgICAgICAgfCBzdHJpbmcgICAgfCBmb3JtYXQgaXMgJ1lZWVktTU0tREQnDQpkb25hdGlvbl9hbW91bnQgfCBpbnRlZ2VyIHwgYW1vdW50IGRvbmF0ZWQgaW4gVVNEDQoNCiMjIyMjIFtzZXNzaW9uc19pbmZvXXtzdHlsZT0iY29sb3I6cmVkIn0NCg0KQ29sdW1uIE5hbWUgfCBEYXRhIFR5cGUgfCBEZXNjcmlwdGlvbg0KLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0gfCAtLS0tLS0tLS0tLQ0KY3JlYXRvcl9pZCAgfCBpbnRlZ2VyICAgfCBVbmlxdWUgaWQgb2YgY29udGVudCBjcmVhdG9yDQpzZXNzaW9uX2lkICB8IGludGVnZXIgICB8IHVuaXF1ZSBzZXNzaW9uIGlkIG9mIHN0cmVhbQ0KZGF0ZSAgICAgICAgfCBzdHJpbmcgICAgfCBmb3JtYXQgaXMgJ1lZWVktTU0tREQnDQpsZW5ndGggICAgICB8IGludGVnZXIgICB8IGxlbmd0aCBvZiBzZXNzaW9uDQoNCiMjIyMjIFtzZXNzaW9uX3ZpZXdlcnNde3N0eWxlPSJjb2xvcjpyZWQifQ0KDQpDb2x1bW4gTmFtZSB8IERhdGEgVHlwZSB8IERlc2NyaXB0aW9uDQotLS0tLS0tLS0tLSB8IC0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tDQpjcmVhdG9yX2lkICB8IGludGVnZXIgICB8IFVuaXF1ZSBpZCBvZiBjb250ZW50IGNyZWF0b3INCnZpZXdlcl9pZCAgIHwgaW50ZWdlciAgIHwgVW5pcXVlIGlkIG9mIHZpZXdlcg0Kc2Vzc2lvbl9pZCAgfCBpbnRlZ2VyICAgfCB1bmlxdWUgc2Vzc2lvbiBpZCBvZiBzdHJlYW0NCmRhdGUgICAgICAgIHwgc3RyaW5nICAgIHwgZm9ybWF0IGlzICdZWVlZLU1NLUREJw0KbWluc192aWV3ZWQgfCBpbnRlZ2VyICAgfCBUaGUgc3RyZWFtDQoNCmBgYHtyLCBldmFsPUZBTFNFLCBlY2hvPVRSVUV9DQphbGxfZG9uYXRpb25zICU+JSANCiAgZmlsdGVyKGRhdGUgPj0gJzIwMTgtMDEtMDEnICYgZGF0ZSA8PSAnMjAxOS0wMS0wMScpICU+JSANCiAgZ3JvdXBfYnkoY3JlYXRvcl9pZCkgJT4lIA0KICBzdW1tYXJpc2UoYXZnX2RvbmF0aW9uID0gc3VtKGRvbmF0aW9uX2Ftb3VudCkgLyBsZW5ndGgodmlld2VyX2lkKSkgJT4lIA0KICBhcnJhbmdlKGRlc2MoYXZnX2RvbmF0aW9uKSkgJT4lIA0KICBoZWFkKDEwKQ0KYGBgDQoNCiMjICoqRXhjZWwgRmlsZXMqKg0KDQojIyMjICoqMyBCZWQgTWluaW11bSAoZWFzeSkqKg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KYWlyYm5iX3NlYXJjaF9kZXRhaWxzIDwtIHJlYWQuY3N2KGZpbGUgPSAnYWlyYm5iX3NlYXJjaF9kZXRhaWxzLmNzdicpDQoNCmFpcmJuYl9zZWFyY2hfZGV0YWlscyAlPiUgDQogIGRvd25sb2FkX3RoaXMoDQogICAgb3V0cHV0X25hbWUgPSAiYWlyYm5iX3NlYXJjaF9kZXRhaWxzIiwNCiAgICBvdXRwdXRfZXh0ZW5zaW9uID0gIi54bHN4IiwNCiAgICBidXR0b25fbGFiZWwgPSAiRG93bmxvYWQgYWlyYm5iX3NlYXJjaF9kZXRhaWxzIGluIEV4Y2VsIiwNCiAgICBidXR0b25fdHlwZSA9ICJkZWZhdWx0IiwNCiAgICBoYXNfaWNvbiA9IFRSVUUsDQogICAgaWNvbiA9ICJmYSBmYS1zYXZlIikNCmBgYA0KDQojIyMjICoqRmF2b3JpdGUgSG9zdCBOYXRpb25hbGl0eSAoTWVkaXVtKSoqDQoNCmBgYHtyIGVjaG89RkFMU0V9DQphaXJibmJfcmV2aWV3cyA8LSByZWFkLmNzdihmaWxlID0gJ2FpcmJuYl9yZXZpZXdzLmNzdicpDQphaXJibmJfaG9zdHMgPC0gcmVhZC5jc3YoZmlsZSA9ICdhaXJibmJfaG9zdHMuY3N2JykNCg0KYWlyYm5iX3Jldmlld3MgJT4lIA0KICBkb3dubG9hZF90aGlzKA0KICAgIG91dHB1dF9uYW1lID0gImFpcmJuYl9yZXZpZXdzIiwNCiAgICBvdXRwdXRfZXh0ZW5zaW9uID0gIi54bHN4IiwNCiAgICBidXR0b25fbGFiZWwgPSAiRG93bmxvYWQgYWlyYm5iX3Jldmlld3MgaW4gRXhjZWwiLA0KICAgIGJ1dHRvbl90eXBlID0gImRlZmF1bHQiLA0KICAgIGhhc19pY29uID0gVFJVRSwNCiAgICBpY29uID0gImZhIGZhLXNhdmUiKQ0KDQphaXJibmJfaG9zdHMgJT4lIA0KICBkb3dubG9hZF90aGlzKA0KICAgIG91dHB1dF9uYW1lID0gImFpcmJuYl9ob3N0cyIsDQogICAgb3V0cHV0X2V4dGVuc2lvbiA9ICIueGxzeCIsDQogICAgYnV0dG9uX2xhYmVsID0gIkRvd25sb2FkIGFpcmJuYl9ob3N0cyBpbiBFeGNlbCIsDQogICAgYnV0dG9uX3R5cGUgPSAiZGVmYXVsdCIsDQogICAgaGFzX2ljb24gPSBUUlVFLA0KICAgIGljb24gPSAiZmEgZmEtc2F2ZSIpDQpgYGANCg0KIyMjIyAqKkhvc3QgUG9wdWxhcml0eSBSZW50YWwgUHJpY2VzIChIYXJkKSoqDQoNCmBgYHtyIGVjaG89RkFMU0V9DQphaXJibmJfaG9zdF9zZWFyY2hlcyA8LSByZWFkLmNzdihmaWxlID0gJ2FpcmJuYl9ob3N0X3NlYXJjaGVzLmNzdicpDQoNCmFpcmJuYl9ob3N0X3NlYXJjaGVzICU+JSANCiAgZG93bmxvYWRfdGhpcygNCiAgICBvdXRwdXRfbmFtZSA9ICJhaXJibmJfaG9zdF9zZWFyY2hlcyIsDQogICAgb3V0cHV0X2V4dGVuc2lvbiA9ICIueGxzeCIsDQogICAgYnV0dG9uX2xhYmVsID0gIkRvd25sb2FkIGFpcmJuYl9ob3N0X3NlYXJjaGVzIGluIEV4Y2VsIiwNCiAgICBidXR0b25fdHlwZSA9ICJkZWZhdWx0IiwNCiAgICBoYXNfaWNvbiA9IFRSVUUsDQogICAgaWNvbiA9ICJmYSBmYS1zYXZlIikNCmBgYA0KDQojIyMjICoqQmV2ZXJhZ2UgU2FsZXMgKEVhc3kpKioNCg0KYGBge3IgZWNobz1GQUxTRX0NCnByb2R1Y3RfcHJpY2luZyA8LSByZWFkLmNzdihmaWxlID0gJ3Byb2R1Y3RfcHJpY2luZy5jc3YnKQ0KcHJvZHVjdF9zYWxlcyA8LSByZWFkLmNzdihmaWxlID0gJ3Byb2R1Y3Rfc2FsZXMuY3N2JykNCg0KcHJvZHVjdF9wcmljaW5nICU+JSANCiAgZG93bmxvYWRfdGhpcygNCiAgICBvdXRwdXRfbmFtZSA9ICJwcm9kdWN0X3ByaWNpbmciLA0KICAgIG91dHB1dF9leHRlbnNpb24gPSAiLnhsc3giLA0KICAgIGJ1dHRvbl9sYWJlbCA9ICJEb3dubG9hZCBwcm9kdWN0X3ByaWNpbmcgaW4gRXhjZWwiLA0KICAgIGJ1dHRvbl90eXBlID0gImRlZmF1bHQiLA0KICAgIGhhc19pY29uID0gVFJVRSwNCiAgICBpY29uID0gImZhIGZhLXNhdmUiKQ0KDQpwcm9kdWN0X3NhbGVzICU+JSANCiAgZG93bmxvYWRfdGhpcygNCiAgICBvdXRwdXRfbmFtZSA9ICJwcm9kdWN0X3NhbGVzIiwNCiAgICBvdXRwdXRfZXh0ZW5zaW9uID0gIi54bHN4IiwNCiAgICBidXR0b25fbGFiZWwgPSAiRG93bmxvYWQgcHJvZHVjdF9zYWxlcyBpbiBFeGNlbCIsDQogICAgYnV0dG9uX3R5cGUgPSAiZGVmYXVsdCIsDQogICAgaGFzX2ljb24gPSBUUlVFLA0KICAgIGljb24gPSAiZmEgZmEtc2F2ZSIpDQpgYGANCg0KIyMjIyAqKk1vbnRobHkgUmV2ZW51ZSBncm93dGggKE1lZGl1bSkqKg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0Kb3JkZXJzIDwtIHJlYWQuY3N2KGZpbGUgPSAib3JkZXJzLmNzdiIpDQoNCm9yZGVycyAlPiUgDQogIGRvd25sb2FkX3RoaXMoDQogICAgb3V0cHV0X25hbWUgPSAib3JkZXJzIiwNCiAgICBvdXRwdXRfZXh0ZW5zaW9uID0gIi54bHN4IiwNCiAgICBidXR0b25fbGFiZWwgPSAiRG93bmxvYWQgb3JkZXJzIGluIEV4Y2VsIiwNCiAgICBidXR0b25fdHlwZSA9ICJkZWZhdWx0IiwNCiAgICBoYXNfaWNvbiA9IFRSVUUsDQogICAgaWNvbiA9ICJmYSBmYS1zYXZlIikNCmBgYA0KDQojIyMjICoqUmFua2luZyBWZW5kb3JzIGJ5IHNwZW5kIChFYXN5KSoqDQoNCmBgYHtyIGVjaG89RkFMU0V9DQp2ZW5kb3Jfc3BlbmQgPC0gcmVhZC5jc3YoZmlsZSA9ICdWZW5kb3Jfc3BlbmQuY3N2JykNCg0KdmVuZG9yX3NwZW5kICU+JSANCiAgZG93bmxvYWRfdGhpcygNCiAgICBvdXRwdXRfbmFtZSA9ICJ2ZW5kb3Jfc3BlbmQiLA0KICAgIG91dHB1dF9leHRlbnNpb24gPSAiLnhsc3giLA0KICAgIGJ1dHRvbl9sYWJlbCA9ICJEb3dubG9hZCB2ZW5kb3Jfc3BlbmQgaW4gRXhjZWwiLA0KICAgIGJ1dHRvbl90eXBlID0gImRlZmF1bHQiLA0KICAgIGhhc19pY29uID0gVFJVRSwNCiAgICBpY29uID0gImZhIGZhLXNhdmUiKQ0KYGBgDQoNCiMjIyMgKipUb3AgQ2FuZGlkYXRlcyBieSBjb2xsZWdlIChFYXN5KSoqDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpjYW5kaWRhdGVDb2xsZWdlcyA8LSByZWFkLmNzdihmaWxlID0gJ2NhbmRpZGF0ZUNvbGxlZ2VzLmNzdicpDQpjYW5kaWRhdGVJbnRlcnZpZXdzIDwtIHJlYWQuY3N2KGZpbGUgPSAnY2FuZGlkYXRlSW50ZXJ2aWV3cy5jc3YnKQ0KDQpjYW5kaWRhdGVDb2xsZWdlcyAlPiUgDQogIGRvd25sb2FkX3RoaXMoDQogICAgb3V0cHV0X25hbWUgPSAiY2FuZGlkYXRlQ29sbGVnZXMiLA0KICAgIG91dHB1dF9leHRlbnNpb24gPSAiLnhsc3giLA0KICAgIGJ1dHRvbl9sYWJlbCA9ICJEb3dubG9hZCBjYW5kaWRhdGVDb2xsZWdlcyBpbiBFeGNlbCIsDQogICAgYnV0dG9uX3R5cGUgPSAiZGVmYXVsdCIsDQogICAgaGFzX2ljb24gPSBUUlVFLA0KICAgIGljb24gPSAiZmEgZmEtc2F2ZSIpDQoNCmNhbmRpZGF0ZUludGVydmlld3MgJT4lIA0KICBkb3dubG9hZF90aGlzKA0KICAgIG91dHB1dF9uYW1lID0gImNhbmRpZGF0ZUludGVydmlld3MiLA0KICAgIG91dHB1dF9leHRlbnNpb24gPSAiLnhsc3giLA0KICAgIGJ1dHRvbl9sYWJlbCA9ICJEb3dubG9hZCBjYW5kaWRhdGVJbnRlcnZpZXdzIGluIEV4Y2VsIiwNCiAgICBidXR0b25fdHlwZSA9ICJkZWZhdWx0IiwNCiAgICBoYXNfaWNvbiA9IFRSVUUsDQogICAgaWNvbiA9ICJmYSBmYS1zYXZlIikNCmBgYA==