Motivation
It is undoubtedly obvious that compared to traditional cab service drivers, Uber drivers are younger, whiter, more female, and more part-time. Though I have continuously noted these distinctions since growing accustomed to Uber over recent years, I did not think that there was data for illustrating these distinctions quantitatively. However, I recently came across the paper “An Analysis of the Labor Market for Uber’s Driver-Partners in the United States,” written by (Economists!) Jonathan Hall and Alan Krueger. The paper supplies tables that summarize characteristics of both Uber drivers and their conventional taxi driver/chauffeur counterparts. This allows for an exercise in visually depicting the differences between the two opposing sets of drivers—allowing us to then accurately define the characteristics of a new kind of cabbie.
1. Age range
Load libraries:
library(ggplot2);library(ggthemes);library(plyr);library(reshape);library(grid);library(scales);library(RColorBrewer);library(gridExtra)
Create my custom theme:
my_theme <- function() {
# Define colors for the chart
palette <- brewer.pal("Greys", n=9)
color.background = palette[2]
color.grid.major = palette[4]
color.panel = palette[3]
color.axis.text = palette[9]
color.axis.title = palette[9]
color.title = palette[9]
# Create basic construction of chart
theme_bw(base_size=9, base_family="Palatino") +
# Set the entire chart region to a light gray color
theme(panel.background=element_rect(fill=color.panel, color=color.background)) +
theme(plot.background=element_rect(fill=color.background, color=color.background)) +
theme(panel.border=element_rect(color=color.background)) +
# Format grid
theme(panel.grid.major=element_line(color=color.grid.major,size=.25)) +
theme(panel.grid.minor=element_blank()) +
theme(axis.ticks=element_blank()) +
# Format legend
theme(legend.position="right") +
theme(legend.background = element_rect(fill=color.panel)) +
theme(legend.text = element_text(size=8,color=color.axis.title)) +
theme(legend.title=element_blank())+
# Format title and axes labels these and tick marks
theme(plot.title=element_text(color=color.title, size=15, vjust=0.5, hjust=0, face="bold")) +
theme(axis.text.x=element_text(size=8,color=color.axis.text)) +
theme(axis.text.y=element_text(size=8,color=color.axis.text)) +
theme(axis.title.x=element_text(size=0,color=color.axis.title, vjust=-1, face="italic")) +
theme(axis.title.y=element_text(size=0,color=color.axis.title, vjust=1.8, face="italic")) +
# Plot margins
theme(plot.margin = unit(c(0, 0, 0, 0), "cm"))
}
Let’s load the data for ages and plot it:
age <- read.csv('raw_data/age.csv')
newage<-melt(age, id=c("Attribute"))
#set colors for uber and taxi driver bars
pal2 <- c("#636363", "#ffff00")
#plot graph
age<-ggplot(data=newage, aes(x=Attribute, y=value, fill=variable))+
geom_bar(stat="identity", position=position_dodge(), colour="black")+
scale_fill_manual(values = pal2) +
theme(legend.key = element_rect(colour = "black"))+
my_theme()+
guides(fill = guide_legend(override.aes = list(colour = NULL)))+
scale_y_continuous(breaks=seq(0,40,5))+
ggtitle("Ubers vs. Taxis: Age Range", subtitle="Percentage (%) of drivers in a given age range")
#add source and credit
grid.arrange(age, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))

Save to pdf
#save to pdf
pdf("age.pdf", width = 6, height = 4) # Open a new pdf file
grid.arrange(age, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))
dev.off()
null device
1
2. Hours worked
Load data and plot:
h <- read.csv('raw_data/hours.csv')
hour<-melt(h, id=c("Attribute"))
#set colors for uber and driver driver bars
pal2 <- c("#636363", "#ffff00")
#define graph
hours<-ggplot(data=hour, aes(x=Attribute, y=value, fill=variable))+
geom_bar(stat="identity", position=position_dodge(), colour="black")+
scale_fill_manual(values = pal2, guide_legend(colour="black")) +
theme(legend.key = element_rect(colour = "black"))+
my_theme()+
guides(fill = guide_legend(override.aes = list(colour = NULL)))+
ggtitle("Ubers vs. Taxis: Hours Worked", subtitle = "Percentage (%) of drivers working a given range of hours/week")+
scale_x_discrete(labels=c("1-15", "16-34", "35-49", "50+"))
#add source and credit
grid.arrange(hours, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))

Save to pdf
#save to pdf
pdf("hours.pdf", width = 6, height = 4) # Open a new pdf file
grid.arrange(hours, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))
dev.off()
null device
1
3. Education level
Load data and plot:
ed <- read.csv('raw_data/education.csv')
newed<-melt(ed, id=c("Attribute"))
#set colors for uber and taxi driver bars
pal2 <- c("#636363", "#ffff00")
#plot graph
education<-ggplot(data=newed, aes(x=Attribute, y=value, fill=variable))+
geom_bar(stat="identity", position=position_dodge(), colour="black")+
scale_fill_manual(values = pal2, guide_legend(colour="black")) +
theme(legend.key = element_rect(colour = "black"))+
my_theme()+
theme(axis.text.x=element_text(size=6.5)) +
guides(fill = guide_legend(override.aes = list(colour = NULL)))+
scale_x_discrete(labels=c("Less than High School", "High School", "Some College/Associate's", "College Degree","Postgraduate Degree"))+
ggtitle("Ubers vs. Taxis: Education Level", subtitle="Percentage (%) of drivers by highest level of education")
#add source and credit
grid.arrange(education, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))

Save to pdf
#save to pdf
pdf("educ.pdf", width = 6, height = 4) # Open a new pdf file
grid.arrange(education, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))
dev.off()
null device
1
4. Earnings by city
Load data and plot:
#load data
ea <- read.csv('raw_data/earning.csv')
earn<-melt(ea, id=c("Attribute"))
#set colors for uber and taxi driver bars
pal2 <- c("#636363", "#ffff00")
#plot graph
ear<-ggplot(data=earn, aes(x=Attribute, y=value, fill=variable))+
geom_bar(stat="identity", position=position_dodge(), colour="black")+
scale_fill_manual(values = pal2, guide_legend(colour="black")) +
theme(legend.key = element_rect(colour = "black"))+
my_theme()+
guides(fill = guide_legend(override.aes = list(colour = NULL)))+
ggtitle("Ubers vs. Taxis: Earnings by City", subtitle="Median earnings ($) per hour by city")
#add source and credit
grid.arrange(ear, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))

Save to pdf
#save to pdf
pdf("earning_by_city.pdf", width = 6, height = 4) # Open a new pdf file
grid.arrange(ear, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))
dev.off()
null device
1
5. Hours worked by city
Load data and plot:
ed <- read.csv('raw_data/citiesuberx.csv')
cit<-melt(ed, id=c("City"))
#plot graph
city<-ggplot(data = cit, aes(x = City, y=value, fill = variable)) +
geom_bar(stat="identity", colour="black")+ coord_flip()+
theme(legend.key = element_rect(colour = "black"))+
my_theme()+
guides(fill = guide_legend(override.aes = list(colour = NULL)))+
scale_fill_brewer(palette="GnBu", name ="Hours/Week", breaks=c("X1.to.15", "X16.to.34","X35.to.49","X50.or.more"), labels=c("1-15", "16-34","35-49","50+"))+
ggtitle("Uber: Hours Worked by City", subtitle="Percentage (%) of drivers working a given range of hours/week")
#add source and credit
grid.arrange(city, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))

Save to pdf
#save to pdf
pdf("city.pdf", width = 6, height = 4) # Open a new pdf file
grid.arrange(city, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))
dev.off()
null device
1
6. Race
Load data and plot:
race <- read.csv('raw_data/race.csv')
newrace<-melt(race, id=c("Attribute"))
#set colors for uber and taxi driver bars
pal2 <- c("#636363", "#ffff00")
#plot graph
race<-ggplot(data=newrace, aes(x=Attribute, y=value, fill=variable))+
geom_bar(stat="identity", position=position_dodge(), colour="black")+
scale_fill_manual(values = pal2, guide_legend(colour="black")) +
theme(legend.key = element_rect(colour = "black"))+
my_theme()+
theme(axis.text.x=element_text(size=6.5)) +
guides(fill = guide_legend(override.aes = list(colour = NULL)))+
ggtitle("Ubers vs. Taxis: Race", subtitle="Percentage (%) of drivers of a given race")
#add source and credit
grid.arrange(race, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))

Save to pdf
#save to pdf
pdf("race.pdf", width = 6, height = 4) # Open a new pdf file
grid.arrange(race, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))
dev.off()
null device
1
7. Gender
Load data and plot:
#load numbers--since it's only three percentages it's not worth loading in the gender.csv file
DF <- data.frame(type = c("Ubers","Taxis","NYC Taxis"), per = c(13.8,8,1))
#place percentages in the middle of the bars
DF <- ddply(DF, .(type), transform, pos = cumsum(per) - (0.5 * per))
#plot graph
fem<-ggplot(DF, aes(x = type, y = per)) +
my_theme()+
geom_bar(stat = "identity", fill = "firebrick", colour="black") +
labs(title= "Ubers vs. Taxis: Gender \nPercentage of female drivers", x="", y="")+
ggtitle("Ubers vs. Taxis: Gender", subtitle="Percentage of female drivers") +
theme(plot.margin = unit(c(0, 1, 0, 0), "cm"))+
geom_text(aes(label = c("1%", "8%","13.8%"), y = pos), size = 5, family="Palatino", face="bold")
#add source and credit
grid.arrange(fem, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))

Save to pdf
#save to pdf
pdf("gender.pdf", width = 6, height = 4) # Open a new pdf file
grid.arrange(fem, ncol=1, nrow=1, bottom=textGrob("Data source: Hall and Krueger (2015) | Visualization via Alex Albright (thelittledataset.com)", hjust=.21, gp=gpar(fontsize=7, font=3, fontfamily="Palatino")))
dev.off()
null device
1
We have now finished plotting/saving all the graphs in the article.
LS0tCnRpdGxlOiAiVGhlIFJpc2Ugb2YgdGhlIE5ldyBLaW5kIG9mIENhYmJpZTogQSBDb21wYXJpc29uIG9mIFViZXIgYW5kIFRheGkgRHJpdmVycyIKb3V0cHV0OiBodG1sX25vdGVib29rCmF1dGhvcjogQWxleCBBbGJyaWdodApkYXRlOiA3LTI3LTE3Ci0tLQojIENvbXBhcmluZyBVYmVyIGFuZCBUYXhpIERyaXZlcnMgClRoaXMgbm90ZWJvb2sgZ2VuZXJhdGVzIHVwZGF0ZWQgdmlzdWFscyBmb3IgW215IGJsb2cgcG9zdCAiVGhlIFJpc2Ugb2YgdGhlIE5ldyBLaW5kIG9mIENhYmJpZTogQSBDb21wYXJpc29uIG9mIFViZXIgYW5kIFRheGkgRHJpdmVycy4iXShodHRwczovL3RoZWxpdHRsZWRhdGFzZXQuY29tLzIwMTUvMDMvMzAvdGhlLXJpc2Utb2YtdGhlLW5ldy1raW5kLW9mLWNhYmJpZS1hLWNvbXBhcmlzb24tb2YtdWJlci1hbmQtdGF4aS1kcml2ZXJzLykgCgojIE1vdGl2YXRpb24KSXQgaXMgdW5kb3VidGVkbHkgb2J2aW91cyB0aGF0IGNvbXBhcmVkIHRvIHRyYWRpdGlvbmFsIGNhYiBzZXJ2aWNlIGRyaXZlcnMsIFViZXIgZHJpdmVycyBhcmUgKnlvdW5nZXIsIHdoaXRlciwgbW9yZSBmZW1hbGUsIGFuZCBtb3JlIHBhcnQtdGltZS4qIFRob3VnaCBJIGhhdmUgY29udGludW91c2x5IG5vdGVkIHRoZXNlIGRpc3RpbmN0aW9ucyBzaW5jZSBncm93aW5nIGFjY3VzdG9tZWQgdG8gVWJlciBvdmVyIHJlY2VudCB5ZWFycywgSSBkaWQgbm90IHRoaW5rIHRoYXQgdGhlcmUgd2FzIGRhdGEgZm9yIGlsbHVzdHJhdGluZyB0aGVzZSBkaXN0aW5jdGlvbnMgcXVhbnRpdGF0aXZlbHkuIEhvd2V2ZXIsIEkgcmVjZW50bHkgY2FtZSBhY3Jvc3MgdGhlIHBhcGVyIFvigJxBbiBBbmFseXNpcyBvZiB0aGUgTGFib3IgTWFya2V0IGZvciBVYmVy4oCZcyBEcml2ZXItUGFydG5lcnMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMs4oCdIHdyaXR0ZW4gYnkgKEVjb25vbWlzdHMhKSBKb25hdGhhbiBIYWxsIGFuZCBBbGFuIEtydWVnZXIuXShodHRwczovL2lycy5wcmluY2V0b24uZWR1L3NpdGVzL2lycy9maWxlcy9BbiUyMEFuYWx5c2lzJTIwb2YlMjB0aGUlMjBMYWJvciUyME1hcmtldCUyMGZvciUyMFViZXIlRTIlODAlOTlzJTIwRHJpdmVyLVBhcnRuZXJzJTIwaW4lMjB0aGUlMjBVbml0ZWQlMjBTdGF0ZXMlMjA1ODcucGRmKSBUaGUgcGFwZXIgc3VwcGxpZXMgdGFibGVzIHRoYXQgc3VtbWFyaXplIGNoYXJhY3RlcmlzdGljcyBvZiBib3RoIFViZXIgZHJpdmVycyBhbmQgdGhlaXIgY29udmVudGlvbmFsIHRheGkgZHJpdmVyL2NoYXVmZmV1ciBjb3VudGVycGFydHMuIFRoaXMgYWxsb3dzIGZvciBhbiBleGVyY2lzZSBpbiB2aXN1YWxseSBkZXBpY3RpbmcgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHR3byBvcHBvc2luZyBzZXRzIG9mIGRyaXZlcnPigJRhbGxvd2luZyB1cyB0byB0aGVuIGFjY3VyYXRlbHkgZGVmaW5lIHRoZSBjaGFyYWN0ZXJpc3RpY3Mgb2YgYSBuZXcga2luZCBvZiBjYWJiaWUuICAKCiMjIDEuIEFnZSByYW5nZSAKCkxvYWQgbGlicmFyaWVzOgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShnZ3Bsb3QyKTtsaWJyYXJ5KGdndGhlbWVzKTtsaWJyYXJ5KHBseXIpO2xpYnJhcnkocmVzaGFwZSk7bGlicmFyeShncmlkKTtsaWJyYXJ5KHNjYWxlcyk7bGlicmFyeShSQ29sb3JCcmV3ZXIpO2xpYnJhcnkoZ3JpZEV4dHJhKQpgYGAKQ3JlYXRlIG15IGN1c3RvbSB0aGVtZToKYGBge3J9Cm15X3RoZW1lIDwtIGZ1bmN0aW9uKCkgewoKICAjIERlZmluZSBjb2xvcnMgZm9yIHRoZSBjaGFydAogIHBhbGV0dGUgPC0gYnJld2VyLnBhbCgiR3JleXMiLCBuPTkpCiAgY29sb3IuYmFja2dyb3VuZCA9IHBhbGV0dGVbMl0KICBjb2xvci5ncmlkLm1ham9yID0gcGFsZXR0ZVs0XQogIGNvbG9yLnBhbmVsID0gcGFsZXR0ZVszXQogIGNvbG9yLmF4aXMudGV4dCA9IHBhbGV0dGVbOV0KICBjb2xvci5heGlzLnRpdGxlID0gcGFsZXR0ZVs5XQogIGNvbG9yLnRpdGxlID0gcGFsZXR0ZVs5XQoKICAjIENyZWF0ZSBiYXNpYyBjb25zdHJ1Y3Rpb24gb2YgY2hhcnQKICB0aGVtZV9idyhiYXNlX3NpemU9OSwgYmFzZV9mYW1pbHk9IlBhbGF0aW5vIikgKyAKCiAgIyBTZXQgdGhlIGVudGlyZSBjaGFydCByZWdpb24gdG8gYSBsaWdodCBncmF5IGNvbG9yCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X3JlY3QoZmlsbD1jb2xvci5wYW5lbCwgY29sb3I9Y29sb3IuYmFja2dyb3VuZCkpICsKICB0aGVtZShwbG90LmJhY2tncm91bmQ9ZWxlbWVudF9yZWN0KGZpbGw9Y29sb3IuYmFja2dyb3VuZCwgY29sb3I9Y29sb3IuYmFja2dyb3VuZCkpICsKICB0aGVtZShwYW5lbC5ib3JkZXI9ZWxlbWVudF9yZWN0KGNvbG9yPWNvbG9yLmJhY2tncm91bmQpKSArCgogICMgRm9ybWF0IGdyaWQKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yPWVsZW1lbnRfbGluZShjb2xvcj1jb2xvci5ncmlkLm1ham9yLHNpemU9LjI1KSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3I9ZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50aWNrcz1lbGVtZW50X2JsYW5rKCkpICsKCiAgIyBGb3JtYXQgbGVnZW5kCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPWNvbG9yLnBhbmVsKSkgKwogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9OCxjb2xvcj1jb2xvci5heGlzLnRpdGxlKSkgKwogIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpKwoKICAjIEZvcm1hdCB0aXRsZSBhbmQgYXhlcyBsYWJlbHMgdGhlc2UgYW5kIHRpY2sgbWFya3MKICB0aGVtZShwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChjb2xvcj1jb2xvci50aXRsZSwgc2l6ZT0xNSwgdmp1c3Q9MC41LCBoanVzdD0wLCBmYWNlPSJib2xkIikpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT04LGNvbG9yPWNvbG9yLmF4aXMudGV4dCkpICsKICB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT04LGNvbG9yPWNvbG9yLmF4aXMudGV4dCkpICsKICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF90ZXh0KHNpemU9MCxjb2xvcj1jb2xvci5heGlzLnRpdGxlLCB2anVzdD0tMSwgZmFjZT0iaXRhbGljIikpICsKICB0aGVtZShheGlzLnRpdGxlLnk9ZWxlbWVudF90ZXh0KHNpemU9MCxjb2xvcj1jb2xvci5heGlzLnRpdGxlLCB2anVzdD0xLjgsIGZhY2U9Iml0YWxpYyIpKSArCgogICMgUGxvdCBtYXJnaW5zCiAgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpKQp9CmBgYApMZXQncyBsb2FkIHRoZSBkYXRhIGZvciBhZ2VzIGFuZCBwbG90IGl0OgpgYGB7cn0KYWdlIDwtIHJlYWQuY3N2KCdyYXdfZGF0YS9hZ2UuY3N2JykKCm5ld2FnZTwtbWVsdChhZ2UsIGlkPWMoIkF0dHJpYnV0ZSIpKQoKI3NldCBjb2xvcnMgZm9yIHViZXIgYW5kIHRheGkgZHJpdmVyIGJhcnMKcGFsMiA8LSBjKCIjNjM2MzYzIiwgIiNmZmZmMDAiKQoKI3Bsb3QgZ3JhcGgKYWdlPC1nZ3Bsb3QoZGF0YT1uZXdhZ2UsIGFlcyh4PUF0dHJpYnV0ZSwgeT12YWx1ZSwgZmlsbD12YXJpYWJsZSkpKyAKCWdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoKSwgY29sb3VyPSJibGFjayIpKwoJc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsMikgKwoJdGhlbWUobGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siKSkrCglteV90aGVtZSgpKwoJZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChjb2xvdXIgPSBOVUxMKSkpKwoJc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1zZXEoMCw0MCw1KSkrCglnZ3RpdGxlKCJVYmVycyB2cy4gVGF4aXM6IEFnZSBSYW5nZSIsIHN1YnRpdGxlPSJQZXJjZW50YWdlICglKSBvZiBkcml2ZXJzIGluIGEgZ2l2ZW4gYWdlIHJhbmdlIikgCgojYWRkIHNvdXJjZSBhbmQgY3JlZGl0IApncmlkLmFycmFuZ2UoYWdlLCBuY29sPTEsIG5yb3c9MSwgYm90dG9tPXRleHRHcm9iKCJEYXRhIHNvdXJjZTogSGFsbCBhbmQgS3J1ZWdlciAoMjAxNSkgfCBWaXN1YWxpemF0aW9uIHZpYSBBbGV4IEFsYnJpZ2h0ICh0aGVsaXR0bGVkYXRhc2V0LmNvbSkiLCBoanVzdD0uMjEsIGdwPWdwYXIoZm9udHNpemU9NywgZm9udD0zLCBmb250ZmFtaWx5PSJQYWxhdGlubyIpKSkKYGBgClNhdmUgdG8gcGRmCmBgYHtyfQojc2F2ZSB0byBwZGYKcGRmKCJhZ2UucGRmIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA0KSAjIE9wZW4gYSBuZXcgcGRmIGZpbGUKZ3JpZC5hcnJhbmdlKGFnZSwgbmNvbD0xLCBucm93PTEsIGJvdHRvbT10ZXh0R3JvYigiRGF0YSBzb3VyY2U6IEhhbGwgYW5kIEtydWVnZXIgKDIwMTUpIHwgVmlzdWFsaXphdGlvbiB2aWEgQWxleCBBbGJyaWdodCAodGhlbGl0dGxlZGF0YXNldC5jb20pIiwgaGp1c3Q9LjIxLCBncD1ncGFyKGZvbnRzaXplPTcsIGZvbnQ9MywgZm9udGZhbWlseT0iUGFsYXRpbm8iKSkpCmRldi5vZmYoKQpgYGAKIyMgMi4gSG91cnMgd29ya2VkCkxvYWQgZGF0YSBhbmQgcGxvdDoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmggPC0gcmVhZC5jc3YoJ3Jhd19kYXRhL2hvdXJzLmNzdicpCgpob3VyPC1tZWx0KGgsIGlkPWMoIkF0dHJpYnV0ZSIpKQoKI3NldCBjb2xvcnMgZm9yIHViZXIgYW5kIGRyaXZlciBkcml2ZXIgYmFycwpwYWwyIDwtIGMoIiM2MzYzNjMiLCAiI2ZmZmYwMCIpCgojZGVmaW5lIGdyYXBoCmhvdXJzPC1nZ3Bsb3QoZGF0YT1ob3VyLCBhZXMoeD1BdHRyaWJ1dGUsIHk9dmFsdWUsIGZpbGw9dmFyaWFibGUpKSsgCglnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKCksIGNvbG91cj0iYmxhY2siKSsKCXNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbDIsIGd1aWRlX2xlZ2VuZChjb2xvdXI9ImJsYWNrIikpICsKCXRoZW1lKGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIikpKwoJbXlfdGhlbWUoKSsKCWd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoY29sb3VyID0gTlVMTCkpKSsKICBnZ3RpdGxlKCJVYmVycyB2cy4gVGF4aXM6IEhvdXJzIFdvcmtlZCIsIHN1YnRpdGxlID0gIlBlcmNlbnRhZ2UgKCUpIG9mIGRyaXZlcnMgd29ya2luZyBhIGdpdmVuIHJhbmdlIG9mIGhvdXJzL3dlZWsiKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCIxLTE1IiwgIjE2LTM0IiwgIjM1LTQ5IiwgIjUwKyIpKQoKI2FkZCBzb3VyY2UgYW5kIGNyZWRpdCAgICAKZ3JpZC5hcnJhbmdlKGhvdXJzLCBuY29sPTEsIG5yb3c9MSwgYm90dG9tPXRleHRHcm9iKCJEYXRhIHNvdXJjZTogSGFsbCBhbmQgS3J1ZWdlciAoMjAxNSkgfCBWaXN1YWxpemF0aW9uIHZpYSBBbGV4IEFsYnJpZ2h0ICh0aGVsaXR0bGVkYXRhc2V0LmNvbSkiLCBoanVzdD0uMjEsIGdwPWdwYXIoZm9udHNpemU9NywgZm9udD0zLCBmb250ZmFtaWx5PSJQYWxhdGlubyIpKSkKYGBgClNhdmUgdG8gcGRmCmBgYHtyfQojc2F2ZSB0byBwZGYKcGRmKCJob3Vycy5wZGYiLCB3aWR0aCA9IDYsIGhlaWdodCA9IDQpICMgT3BlbiBhIG5ldyBwZGYgZmlsZQpncmlkLmFycmFuZ2UoaG91cnMsIG5jb2w9MSwgbnJvdz0xLCBib3R0b209dGV4dEdyb2IoIkRhdGEgc291cmNlOiBIYWxsIGFuZCBLcnVlZ2VyICgyMDE1KSB8IFZpc3VhbGl6YXRpb24gdmlhIEFsZXggQWxicmlnaHQgKHRoZWxpdHRsZWRhdGFzZXQuY29tKSIsIGhqdXN0PS4yMSwgZ3A9Z3Bhcihmb250c2l6ZT03LCBmb250PTMsIGZvbnRmYW1pbHk9IlBhbGF0aW5vIikpKQpkZXYub2ZmKCkKYGBgCiMjIDMuIEVkdWNhdGlvbiBsZXZlbApMb2FkIGRhdGEgYW5kIHBsb3Q6CmBgYHtyfQplZCA8LSByZWFkLmNzdigncmF3X2RhdGEvZWR1Y2F0aW9uLmNzdicpCm5ld2VkPC1tZWx0KGVkLCBpZD1jKCJBdHRyaWJ1dGUiKSkKCiNzZXQgY29sb3JzIGZvciB1YmVyIGFuZCB0YXhpIGRyaXZlciBiYXJzCnBhbDIgPC0gYygiIzYzNjM2MyIsICIjZmZmZjAwIikKCiNwbG90IGdyYXBoCmVkdWNhdGlvbjwtZ2dwbG90KGRhdGE9bmV3ZWQsIGFlcyh4PUF0dHJpYnV0ZSwgeT12YWx1ZSwgZmlsbD12YXJpYWJsZSkpKyAKCWdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoKSwgY29sb3VyPSJibGFjayIpKwoJc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsMiwgZ3VpZGVfbGVnZW5kKGNvbG91cj0iYmxhY2siKSkgKwoJdGhlbWUobGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siKSkrCglteV90aGVtZSgpKyAKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02LjUpKSArCglndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGNvbG91ciA9IE5VTEwpKSkrCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9YygiTGVzcyB0aGFuIEhpZ2ggU2Nob29sIiwgIkhpZ2ggU2Nob29sIiwgIlNvbWUgQ29sbGVnZS9Bc3NvY2lhdGUncyIsICJDb2xsZWdlIERlZ3JlZSIsIlBvc3RncmFkdWF0ZSBEZWdyZWUiKSkrCglnZ3RpdGxlKCJVYmVycyB2cy4gVGF4aXM6IEVkdWNhdGlvbiBMZXZlbCIsIHN1YnRpdGxlPSJQZXJjZW50YWdlICglKSBvZiBkcml2ZXJzIGJ5IGhpZ2hlc3QgbGV2ZWwgb2YgZWR1Y2F0aW9uIikgCgojYWRkIHNvdXJjZSBhbmQgY3JlZGl0ICAgIApncmlkLmFycmFuZ2UoZWR1Y2F0aW9uLCBuY29sPTEsIG5yb3c9MSwgYm90dG9tPXRleHRHcm9iKCJEYXRhIHNvdXJjZTogSGFsbCBhbmQgS3J1ZWdlciAoMjAxNSkgfCBWaXN1YWxpemF0aW9uIHZpYSBBbGV4IEFsYnJpZ2h0ICh0aGVsaXR0bGVkYXRhc2V0LmNvbSkiLCBoanVzdD0uMjEsIGdwPWdwYXIoZm9udHNpemU9NywgZm9udD0zLCBmb250ZmFtaWx5PSJQYWxhdGlubyIpKSkKYGBgClNhdmUgdG8gcGRmCmBgYHtyfQojc2F2ZSB0byBwZGYKcGRmKCJlZHVjLnBkZiIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNCkgIyBPcGVuIGEgbmV3IHBkZiBmaWxlCmdyaWQuYXJyYW5nZShlZHVjYXRpb24sIG5jb2w9MSwgbnJvdz0xLCBib3R0b209dGV4dEdyb2IoIkRhdGEgc291cmNlOiBIYWxsIGFuZCBLcnVlZ2VyICgyMDE1KSB8IFZpc3VhbGl6YXRpb24gdmlhIEFsZXggQWxicmlnaHQgKHRoZWxpdHRsZWRhdGFzZXQuY29tKSIsIGhqdXN0PS4yMSwgZ3A9Z3Bhcihmb250c2l6ZT03LCBmb250PTMsIGZvbnRmYW1pbHk9IlBhbGF0aW5vIikpKQpkZXYub2ZmKCkKYGBgCiMjIDQuIEVhcm5pbmdzIGJ5IGNpdHkKTG9hZCBkYXRhIGFuZCBwbG90OgpgYGB7cn0KI2xvYWQgZGF0YQplYSA8LSByZWFkLmNzdigncmF3X2RhdGEvZWFybmluZy5jc3YnKQoKZWFybjwtbWVsdChlYSwgaWQ9YygiQXR0cmlidXRlIikpCgojc2V0IGNvbG9ycyBmb3IgdWJlciBhbmQgdGF4aSBkcml2ZXIgYmFycwpwYWwyIDwtIGMoIiM2MzYzNjMiLCAiI2ZmZmYwMCIpCgojcGxvdCBncmFwaAplYXI8LWdncGxvdChkYXRhPWVhcm4sIGFlcyh4PUF0dHJpYnV0ZSwgeT12YWx1ZSwgZmlsbD12YXJpYWJsZSkpKyAKCWdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoKSwgY29sb3VyPSJibGFjayIpKwoJc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsMiwgZ3VpZGVfbGVnZW5kKGNvbG91cj0iYmxhY2siKSkgKwoJdGhlbWUobGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siKSkrCglteV90aGVtZSgpKwoJZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChjb2xvdXIgPSBOVUxMKSkpKwoJZ2d0aXRsZSgiVWJlcnMgdnMuIFRheGlzOiBFYXJuaW5ncyBieSBDaXR5Iiwgc3VidGl0bGU9Ik1lZGlhbiBlYXJuaW5ncyAoJCkgcGVyIGhvdXIgYnkgY2l0eSIpIAoKI2FkZCBzb3VyY2UgYW5kIGNyZWRpdCAgICAKZ3JpZC5hcnJhbmdlKGVhciwgbmNvbD0xLCBucm93PTEsIGJvdHRvbT10ZXh0R3JvYigiRGF0YSBzb3VyY2U6IEhhbGwgYW5kIEtydWVnZXIgKDIwMTUpIHwgVmlzdWFsaXphdGlvbiB2aWEgQWxleCBBbGJyaWdodCAodGhlbGl0dGxlZGF0YXNldC5jb20pIiwgaGp1c3Q9LjIxLCBncD1ncGFyKGZvbnRzaXplPTcsIGZvbnQ9MywgZm9udGZhbWlseT0iUGFsYXRpbm8iKSkpCmBgYApTYXZlIHRvIHBkZgpgYGB7cn0KI3NhdmUgdG8gcGRmCnBkZigiZWFybmluZ19ieV9jaXR5LnBkZiIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNCkgIyBPcGVuIGEgbmV3IHBkZiBmaWxlCmdyaWQuYXJyYW5nZShlYXIsIG5jb2w9MSwgbnJvdz0xLCBib3R0b209dGV4dEdyb2IoIkRhdGEgc291cmNlOiBIYWxsIGFuZCBLcnVlZ2VyICgyMDE1KSB8IFZpc3VhbGl6YXRpb24gdmlhIEFsZXggQWxicmlnaHQgKHRoZWxpdHRsZWRhdGFzZXQuY29tKSIsIGhqdXN0PS4yMSwgZ3A9Z3Bhcihmb250c2l6ZT03LCBmb250PTMsIGZvbnRmYW1pbHk9IlBhbGF0aW5vIikpKQpkZXYub2ZmKCkKYGBgCiMjIDUuIEhvdXJzIHdvcmtlZCBieSBjaXR5CkxvYWQgZGF0YSBhbmQgcGxvdDoKYGBge3J9CmVkIDwtIHJlYWQuY3N2KCdyYXdfZGF0YS9jaXRpZXN1YmVyeC5jc3YnKQoKY2l0PC1tZWx0KGVkLCBpZD1jKCJDaXR5IikpCgojcGxvdCBncmFwaApjaXR5PC1nZ3Bsb3QoZGF0YSA9IGNpdCwgYWVzKHggPSBDaXR5LCB5PXZhbHVlLCBmaWxsID0gdmFyaWFibGUpKSArIAoJZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBjb2xvdXI9ImJsYWNrIikrIGNvb3JkX2ZsaXAoKSsgCgl0aGVtZShsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIpKSsKCW15X3RoZW1lKCkrCglndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGNvbG91ciA9IE5VTEwpKSkrCglzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJHbkJ1IiwgbmFtZSA9IkhvdXJzL1dlZWsiLCBicmVha3M9YygiWDEudG8uMTUiLCAiWDE2LnRvLjM0IiwiWDM1LnRvLjQ5IiwiWDUwLm9yLm1vcmUiKSwgbGFiZWxzPWMoIjEtMTUiLCAiMTYtMzQiLCIzNS00OSIsIjUwKyIpKSsKCWdndGl0bGUoIlViZXI6IEhvdXJzIFdvcmtlZCBieSBDaXR5Iiwgc3VidGl0bGU9IlBlcmNlbnRhZ2UgKCUpIG9mIGRyaXZlcnMgd29ya2luZyBhIGdpdmVuIHJhbmdlIG9mIGhvdXJzL3dlZWsiKSAKCiNhZGQgc291cmNlIGFuZCBjcmVkaXQgICAgCmdyaWQuYXJyYW5nZShjaXR5LCBuY29sPTEsIG5yb3c9MSwgYm90dG9tPXRleHRHcm9iKCJEYXRhIHNvdXJjZTogSGFsbCBhbmQgS3J1ZWdlciAoMjAxNSkgfCBWaXN1YWxpemF0aW9uIHZpYSBBbGV4IEFsYnJpZ2h0ICh0aGVsaXR0bGVkYXRhc2V0LmNvbSkiLCBoanVzdD0uMjEsIGdwPWdwYXIoZm9udHNpemU9NywgZm9udD0zLCBmb250ZmFtaWx5PSJQYWxhdGlubyIpKSkKYGBgClNhdmUgdG8gcGRmCmBgYHtyfQojc2F2ZSB0byBwZGYKcGRmKCJjaXR5LnBkZiIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNCkgIyBPcGVuIGEgbmV3IHBkZiBmaWxlCmdyaWQuYXJyYW5nZShjaXR5LCBuY29sPTEsIG5yb3c9MSwgYm90dG9tPXRleHRHcm9iKCJEYXRhIHNvdXJjZTogSGFsbCBhbmQgS3J1ZWdlciAoMjAxNSkgfCBWaXN1YWxpemF0aW9uIHZpYSBBbGV4IEFsYnJpZ2h0ICh0aGVsaXR0bGVkYXRhc2V0LmNvbSkiLCBoanVzdD0uMjEsIGdwPWdwYXIoZm9udHNpemU9NywgZm9udD0zLCBmb250ZmFtaWx5PSJQYWxhdGlubyIpKSkKZGV2Lm9mZigpCmBgYAojIyA2LiBSYWNlCkxvYWQgZGF0YSBhbmQgcGxvdDoKYGBge3J9CnJhY2UgPC0gcmVhZC5jc3YoJ3Jhd19kYXRhL3JhY2UuY3N2JykKCm5ld3JhY2U8LW1lbHQocmFjZSwgaWQ9YygiQXR0cmlidXRlIikpCgojc2V0IGNvbG9ycyBmb3IgdWJlciBhbmQgdGF4aSBkcml2ZXIgYmFycwpwYWwyIDwtIGMoIiM2MzYzNjMiLCAiI2ZmZmYwMCIpCgojcGxvdCBncmFwaApyYWNlPC1nZ3Bsb3QoZGF0YT1uZXdyYWNlLCBhZXMoeD1BdHRyaWJ1dGUsIHk9dmFsdWUsIGZpbGw9dmFyaWFibGUpKSsgCglnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKCksIGNvbG91cj0iYmxhY2siKSsKCXNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbDIsIGd1aWRlX2xlZ2VuZChjb2xvdXI9ImJsYWNrIikpICsKCXRoZW1lKGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIikpKwoJbXlfdGhlbWUoKSsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02LjUpKSArCglndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGNvbG91ciA9IE5VTEwpKSkrCglnZ3RpdGxlKCJVYmVycyB2cy4gVGF4aXM6IFJhY2UiLCBzdWJ0aXRsZT0iUGVyY2VudGFnZSAoJSkgb2YgZHJpdmVycyBvZiBhIGdpdmVuIHJhY2UiKQoKI2FkZCBzb3VyY2UgYW5kIGNyZWRpdCAgICAKZ3JpZC5hcnJhbmdlKHJhY2UsIG5jb2w9MSwgbnJvdz0xLCBib3R0b209dGV4dEdyb2IoIkRhdGEgc291cmNlOiBIYWxsIGFuZCBLcnVlZ2VyICgyMDE1KSB8IFZpc3VhbGl6YXRpb24gdmlhIEFsZXggQWxicmlnaHQgKHRoZWxpdHRsZWRhdGFzZXQuY29tKSIsIGhqdXN0PS4yMSwgZ3A9Z3Bhcihmb250c2l6ZT03LCBmb250PTMsIGZvbnRmYW1pbHk9IlBhbGF0aW5vIikpKQpgYGAKU2F2ZSB0byBwZGYKYGBge3J9CiNzYXZlIHRvIHBkZgpwZGYoInJhY2UucGRmIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA0KSAjIE9wZW4gYSBuZXcgcGRmIGZpbGUKZ3JpZC5hcnJhbmdlKHJhY2UsIG5jb2w9MSwgbnJvdz0xLCBib3R0b209dGV4dEdyb2IoIkRhdGEgc291cmNlOiBIYWxsIGFuZCBLcnVlZ2VyICgyMDE1KSB8IFZpc3VhbGl6YXRpb24gdmlhIEFsZXggQWxicmlnaHQgKHRoZWxpdHRsZWRhdGFzZXQuY29tKSIsIGhqdXN0PS4yMSwgZ3A9Z3Bhcihmb250c2l6ZT03LCBmb250PTMsIGZvbnRmYW1pbHk9IlBhbGF0aW5vIikpKQpkZXYub2ZmKCkKYGBgCiMjIDcuIEdlbmRlcgpMb2FkIGRhdGEgYW5kIHBsb3Q6CmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojbG9hZCBudW1iZXJzLS1zaW5jZSBpdCdzIG9ubHkgdGhyZWUgcGVyY2VudGFnZXMgaXQncyBub3Qgd29ydGggbG9hZGluZyBpbiB0aGUgZ2VuZGVyLmNzdiBmaWxlIApERiA8LSBkYXRhLmZyYW1lKHR5cGUgPSBjKCJVYmVycyIsIlRheGlzIiwiTllDIFRheGlzIiksIHBlciA9IGMoMTMuOCw4LDEpKSAKIAojcGxhY2UgcGVyY2VudGFnZXMgaW4gdGhlIG1pZGRsZSBvZiB0aGUgYmFycwogREYgPC0gZGRwbHkoREYsIC4odHlwZSksIHRyYW5zZm9ybSwgcG9zID0gY3Vtc3VtKHBlcikgLSAoMC41ICogcGVyKSkKIAojcGxvdCBncmFwaCAKZmVtPC1nZ3Bsb3QoREYsIGFlcyh4ID0gdHlwZSwgeSA9IHBlcikpICsgCglteV90aGVtZSgpKwoJZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiZmlyZWJyaWNrIiwgY29sb3VyPSJibGFjayIpICsgCglsYWJzKHRpdGxlPSAiVWJlcnMgdnMuIFRheGlzOiBHZW5kZXIgXG5QZXJjZW50YWdlIG9mIGZlbWFsZSBkcml2ZXJzIiwgeD0iIiwgeT0iIikrCglnZ3RpdGxlKCJVYmVycyB2cy4gVGF4aXM6IEdlbmRlciIsIHN1YnRpdGxlPSJQZXJjZW50YWdlIG9mIGZlbWFsZSBkcml2ZXJzIikgKwogIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDEsIDAsIDApLCAiY20iKSkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGMoIjElIiwgIjglIiwiMTMuOCUiKSwgeSA9IHBvcyksIHNpemUgPSA1LCBmYW1pbHk9IlBhbGF0aW5vIiwgZmFjZT0iYm9sZCIpCgojYWRkIHNvdXJjZSBhbmQgY3JlZGl0ICAgIApncmlkLmFycmFuZ2UoZmVtLCBuY29sPTEsIG5yb3c9MSwgYm90dG9tPXRleHRHcm9iKCJEYXRhIHNvdXJjZTogSGFsbCBhbmQgS3J1ZWdlciAoMjAxNSkgfCBWaXN1YWxpemF0aW9uIHZpYSBBbGV4IEFsYnJpZ2h0ICh0aGVsaXR0bGVkYXRhc2V0LmNvbSkiLCBoanVzdD0uMjEsIGdwPWdwYXIoZm9udHNpemU9NywgZm9udD0zLCBmb250ZmFtaWx5PSJQYWxhdGlubyIpKSkKYGBgClNhdmUgdG8gcGRmCmBgYHtyfQojc2F2ZSB0byBwZGYKcGRmKCJnZW5kZXIucGRmIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA0KSAjIE9wZW4gYSBuZXcgcGRmIGZpbGUKZ3JpZC5hcnJhbmdlKGZlbSwgbmNvbD0xLCBucm93PTEsIGJvdHRvbT10ZXh0R3JvYigiRGF0YSBzb3VyY2U6IEhhbGwgYW5kIEtydWVnZXIgKDIwMTUpIHwgVmlzdWFsaXphdGlvbiB2aWEgQWxleCBBbGJyaWdodCAodGhlbGl0dGxlZGF0YXNldC5jb20pIiwgaGp1c3Q9LjIxLCBncD1ncGFyKGZvbnRzaXplPTcsIGZvbnQ9MywgZm9udGZhbWlseT0iUGFsYXRpbm8iKSkpCmRldi5vZmYoKQpgYGAKV2UgaGF2ZSBub3cgZmluaXNoZWQgcGxvdHRpbmcvc2F2aW5nIGFsbCB0aGUgZ3JhcGhzIGluIHRoZSBhcnRpY2xlLgoKIyBUaGUgRW5kCgo=