In this project, I scraped, cleaned, and transformed data of Marvel Cinematic Universe films from https://en.wikipedia.org/wiki/List_of_Marvel_Cinematic_Universe_films. Afterwards, I analyzed the data and visualized my findings with ggplot2. ***This information is valid until April 2019.

Loading packages

library(rvest)
library(dplyr)
library(ggplot2)
library(tidyr)
library(ggrepel)
library(gridExtra)
library(zoo)
library(reshape2)
library(car)
library(plotly)

Scraping two tables from Wikipedia: Critical Response table and Box Office Performance table. Afterwards, I cleaned and merged them into a single data frame.

movie_table <- read_html("https://en.wikipedia.org/wiki/List_of_Marvel_Cinematic_Universe_films")
boxoff <- html_table(html_nodes(movie_table, "table")[[10]],fill=T)[c(-1,-24),c(-3,-4,-6,-7,-9)] 
critical <- html_table(html_nodes(movie_table, "table")[[11]],fill=T)[-23,]
merged <- merge(boxoff,critical,by.x="Film",by.y="Film")
colnames(merged)[3] <- "Box.Office.Gross.Worldwide"
colnames(merged)[2] <- "Year"
colnames(merged) <- make.names(colnames(merged))
merged
The data in the table is not ready for analysis because there are symbols (commas, dollar signs, spaces) and useless words. Now I will start by cleaning the data by keeping the columns: Box office gross worldwide, release year, Budget, Rotten Tomatoes scores, and Metacritic scores. Also, I will create a ‘Revenue’ column in the table.

Removing the days and months while keeping the year and converting to numeric values

a=regexpr("[[:digit:]]{4}", merged$Year)
merged$Year <- regmatches(merged$Year,a) %>% as.numeric() 

Removing the “$” and “,” from the gross column and converting to numeric values

merged$Box.Office.Gross.Worldwide <- gsub("(\\$|,)", "", merged$Box.Office.Gross.Worldwide) %>% as.numeric()

Removed symbols and converted the net budget to numeric values by multiplying by 1000000

c=gsub("(\\$|\\s{1}million)", "", merged$Budget) 
merged$Budget <- gsub("[[:digit:]]{3}(\\–){1}","",c) %>% as.numeric()*1000000

Removed symbols and only kept the scores as numeric values

merged$Rotten.Tomatoes <- substr(merged$Rotten.Tomatoes,1,2) %>% as.numeric()

Removed symbols and only kept the scores as numeric values

merged$`Metacritic` <- substr(merged$`Metacritic`,1,2) %>% as.numeric()

Adding new ‘Revenue’ feature to the merged data frame

merged <- mutate(merged, Revenue=Box.Office.Gross.Worldwide-Budget)

Cleaned and merged table

write.csv(merged, "CleanedMarvel.csv")
merged

Moving averages of Box Office Gross Worldwide and Budget over time

The budget seems to be fairly constant throughout the years however gross has fallen slightly in 2015 - 2017 and begins increasing again in 2017 more at a higher rate than previous years

ggplot(data=merged, aes(x=Year)) + 
  geom_point(aes(y=Box.Office.Gross.Worldwide)) +
  geom_smooth(method="loess", aes(y=Box.Office.Gross.Worldwide, colour="Gross_Loess")) +
    geom_smooth(method="lm", se=F,aes(y=Box.Office.Gross.Worldwide, colour="Gross_Linear")) +
  geom_point(data=merged,aes(y=Budget, colour="Budget_MovingAvg")) +
  geom_line(data=merged,aes(y=rollapplyr(merged$Budget,width=10,FUN=mean,partial=T),colour="Budget_MovingAvg")) +
  scale_x_continuous(breaks=c(2008:2019)) +
  labs(title="Box Office Gross worldwide and Budget income over time for MCU movies") +
  ylab(label="Dollars") 

  #scale_colour_manual(name="", values=c(Gross_MovingAvg="#00BA38", Budget_MovingAvg="#F8766D", Gross_Loess="#619CFF")) 

What is the distribution of revenue for Marvel movies?

The red dashed line represents the mean revenue and the black surve represents the density curve. Before taking the log of the revenue, the distribution appears to be positively skewed to the right. After the transformation, the distribution appears to be closer to a normal distribution.

ggplot(data=merged, aes(x=Revenue)) +
  geom_density(color="black") +
  geom_vline(xintercept = mean(merged$Revenue), color = "red", linetype = "dashed") +
  labs(title="Distribution of Revenue for MCU movies") +
  xlab(label="Revenue in Dollars") +
  ylab(label="Density")


ggplot(data=merged, aes(x=log(Revenue))) +
  geom_density(color="black") +
  geom_vline(xintercept = mean(log(merged$Revenue)), color = "red", linetype = "dashed") +
  labs(title="Distribution of log(Revenue) for MCU movies") +
  xlab(label="log(Revenue) in Dollars") +
  ylab(label="Density")

Which years did MCU movies bring in the most revenue?

The graphs show that 2018 and 2019 MCU movies brought in the highest Revenue income. However there were 2 MCU released in 2019 and 3 in 2018. A film released in 2019 generated significantly more revenue than movies from previous years. (Avengers: Endgame)

merged %>%
  group_by(Year) %>%
  summarize(Total.Revenue=sum(Revenue)) %>%
  ggplot(aes(x=Year, y=Total.Revenue)) + 
  geom_bar(stat="identity", fill="#F8766D", position="dodge") +
  geom_text(aes(label=Total.Revenue), position=position_dodge(width=0.1), size=2.3, vjust=-.25,) +
  scale_x_continuous(breaks=c(2008:2019)) +
  labs(title="Total Revenue vs Year of MCU movies") +
  ylab(label="Total Revenue")


ggplot(merged, aes(x=Film, y=Revenue)) + 
  geom_bar(stat="identity") + facet_wrap(~Year) + 
  theme(axis.text.x=element_blank(), axis.ticks.x=element_blank()) +
  labs(title="Revenue of MCU movies from 2008-2019")

Relationship of Budget and Gross Revenue

The linear regression model suggests that they have a positive relationship and the moving average and loess curve of budget is rising but starts dropping when revenue reaches ~$1.75 million. The summary of the simple linear regression with Budget as the predictor and Revenue as the response shows that Budget is a a significant factor that influences the revenue positively. However since the sample size is small, it is not clear. The residual plot is not very unsual, however there are a few outliers (4 and 3). The normal QQ plot shows that the residuals are approximately normally dsitributed.

ggplot(merged, aes(x=Budget, y=Revenue)) +
  geom_point() +
  geom_smooth(aes(colour="Loess"), method="loess",size=.6, se=F) +
  geom_smooth(aes(colour="Linear Regression"), method="lm", se=F, size=.6) +
  xlab(label="Budget (Dollars)") +
  ylab(label="Revenue (Dollars)") +
  labs(title="REvenue vs Budget for MCU movies") 

revfit <- lm(Revenue ~ Budget,data=merged)
summary(revfit)

Call:
lm(formula = Revenue ~ Budget, data = merged)

Residuals:
       Min         1Q     Median         3Q        Max 
-588368455 -173496574  -38885727  137761684  816134505 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -3.263e+08  2.108e+08  -1.548    0.137    
Budget       5.348e+00  9.685e-01   5.522  2.1e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 336500000 on 20 degrees of freedom
Multiple R-squared:  0.6039,    Adjusted R-squared:  0.5841 
F-statistic: 30.49 on 1 and 20 DF,  p-value: 2.097e-05
plot(revfit,1:2)

Do Rotten Tomatoes and Metacritic agree?

They seem to have a positive relatiionship, however it is not proportional. Metacritic appears to give lower ratings than Rotten Tomatoes.

ggplot(merged, aes(x=Metacritic, Rotten.Tomatoes)) +
  geom_point( size=.5) +
  geom_text_repel(label=merged$Film, size=3) +
  xlim(50,100) +
  ylim(50,100) +
  geom_line(colour="darkred", alpha=.6, method="loess", stat="smooth", size=1.3) +
  labs(title="Metacritic ratings vs Rotten Tomatoes ratings of MCU Movies") +
  ylab(label="Rotten Tomatoes scores") +
  xlab(label="Metacritic scores")


ggplot(merged) +
  geom_bar(aes(x=reorder(Film, Rotten.Tomatoes), y=Rotten.Tomatoes, fill="Rotten Tomatoes"), stat="identity", alpha=1) +
  geom_bar(aes(x=reorder(Film, Metacritic), y=Metacritic, fill="Metacritic"), stat="identity",alpha=1) +
  coord_flip() +
  scale_color_manual(values=c(a="red",b="blue")) +
  scale_fill_discrete("") +
  labs(title="Ratings of MCU movies") +
  ylab("Rating") +
  xlab("Movies")

How have the ratings evolved over time?

In general, Rotten Tomatoes reviewers appears to give more generous ratings than Metacritic reviewers. The graphs suggests that the ratings are increasing the but have fallen a bit since 2018.

plot1 <- ggplot(merged, aes(x=Year, y=Metacritic)) + 
  geom_point() +
  geom_smooth(method="loess") +
  scale_x_continuous(breaks=c(2008:2019)) +
  theme(axis.text.x=element_text(angle = 60, hjust=1)) +
  ylim(50,100) +
  labs(title="Metacritic rating scores \n over time of MCU movies") +
  ylab(label="Metacritic Scores")

plot2 <- ggplot(merged, aes(x=Year, y=Rotten.Tomatoes)) + 
  geom_point() +
  geom_smooth(method="loess") +
  scale_x_continuous(breaks=c(2008:2019)) +
  ylim(50,100) +
  theme(axis.text.x=element_text(angle = 60, hjust=1)) +
  labs(title="Rotten Tomatoes rating scores \n over time of MCU movies") +
  ylab(label="Rotten Tomatoes scores")

grid.arrange(plot2, plot1, ncol=2)

Conlusion

  1. Budget appears to be somewhat constant while Gross is on an upward trend
  2. Rotten tomatoes tends to give higher ratings than Metacritic
  3. The highest by Rotten Tomatoes and Metacritic is Black Panther
  4. The movie that brought in the most revenue was Avengers:Endgame in 2019
  5. Budget is a significant predictor of Revenue
LS0tCnRpdGxlOiAiRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcyBvZiBNYXJ2ZWwgQ2luZW1hdGljIFVuaXZlcnNlIGZpbG1zIGZyb20gMjAwOCAtIDIwMTkiCmF1dGhvcjogIkFsZXhhbmRlciBMbyIKZGF0ZTogIjI2LzAzLzIwMTkiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAotLS0KCmBgYHtyLGNhY2hlPVRSVUUsZWNobz1GQUxTRSx3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0UpCmBgYAoKSW4gdGhpcyBwcm9qZWN0LCBJIHNjcmFwZWQsIGNsZWFuZWQsIGFuZCB0cmFuc2Zvcm1lZCBkYXRhIG9mIE1hcnZlbCBDaW5lbWF0aWMgVW5pdmVyc2UgZmlsbXMgZnJvbSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MaXN0X29mX01hcnZlbF9DaW5lbWF0aWNfVW5pdmVyc2VfZmlsbXMuIEFmdGVyd2FyZHMsIEkgYW5hbHl6ZWQgdGhlIGRhdGEgYW5kIHZpc3VhbGl6ZWQgbXkgZmluZGluZ3Mgd2l0aCBnZ3Bsb3QyLiAqKipUaGlzIGluZm9ybWF0aW9uIGlzIHZhbGlkIHVudGlsIEFwcmlsIDIwMTkuCgpMb2FkaW5nIHBhY2thZ2VzCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkocnZlc3QpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeSh6b28pCmxpYnJhcnkocmVzaGFwZTIpCmBgYAoKClNjcmFwaW5nIHR3byB0YWJsZXMgZnJvbSBXaWtpcGVkaWE6IENyaXRpY2FsIFJlc3BvbnNlIHRhYmxlIGFuZCBCb3ggT2ZmaWNlIFBlcmZvcm1hbmNlIHRhYmxlLiBBZnRlcndhcmRzLCBJIGNsZWFuZWQgYW5kIG1lcmdlZCB0aGVtIGludG8gYSBzaW5nbGUgZGF0YSBmcmFtZS4KYGBge3J9Cm1vdmllX3RhYmxlIDwtIHJlYWRfaHRtbCgiaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGlzdF9vZl9NYXJ2ZWxfQ2luZW1hdGljX1VuaXZlcnNlX2ZpbG1zIikKYm94b2ZmIDwtIGh0bWxfdGFibGUoaHRtbF9ub2Rlcyhtb3ZpZV90YWJsZSwgInRhYmxlIilbWzEwXV0sZmlsbD1UKVtjKC0xLC0yNCksYygtMywtNCwtNiwtNywtOSldIApjcml0aWNhbCA8LSBodG1sX3RhYmxlKGh0bWxfbm9kZXMobW92aWVfdGFibGUsICJ0YWJsZSIpW1sxMV1dLGZpbGw9VClbLTIzLF0KbWVyZ2VkIDwtIG1lcmdlKGJveG9mZixjcml0aWNhbCxieS54PSJGaWxtIixieS55PSJGaWxtIikKY29sbmFtZXMobWVyZ2VkKVszXSA8LSAiQm94Lk9mZmljZS5Hcm9zcy5Xb3JsZHdpZGUiCmNvbG5hbWVzKG1lcmdlZClbMl0gPC0gIlllYXIiCmNvbG5hbWVzKG1lcmdlZCkgPC0gbWFrZS5uYW1lcyhjb2xuYW1lcyhtZXJnZWQpKQptZXJnZWQKYGBgCgojIyMjIyBUaGUgZGF0YSBpbiB0aGUgdGFibGUgaXMgbm90IHJlYWR5IGZvciBhbmFseXNpcyBiZWNhdXNlIHRoZXJlIGFyZSBzeW1ib2xzIChjb21tYXMsIGRvbGxhciBzaWducywgc3BhY2VzKSBhbmQgdXNlbGVzcyB3b3Jkcy4gTm93IEkgd2lsbCBzdGFydCBieSBjbGVhbmluZyB0aGUgZGF0YSBieSBrZWVwaW5nIHRoZSBjb2x1bW5zOiBCb3ggb2ZmaWNlIGdyb3NzIHdvcmxkd2lkZSwgcmVsZWFzZSB5ZWFyLCBCdWRnZXQsIFJvdHRlbiBUb21hdG9lcyBzY29yZXMsIGFuZCBNZXRhY3JpdGljIHNjb3Jlcy4gQWxzbywgSSB3aWxsIGNyZWF0ZSBhICdSZXZlbnVlJyBjb2x1bW4gaW4gdGhlIHRhYmxlLgoKClJlbW92aW5nIHRoZSBkYXlzIGFuZCBtb250aHMgd2hpbGUga2VlcGluZyB0aGUgeWVhciBhbmQgY29udmVydGluZyB0byBudW1lcmljIHZhbHVlcwpgYGB7cn0KYT1yZWdleHByKCJbWzpkaWdpdDpdXXs0fSIsIG1lcmdlZCRZZWFyKQptZXJnZWQkWWVhciA8LSByZWdtYXRjaGVzKG1lcmdlZCRZZWFyLGEpICU+JSBhcy5udW1lcmljKCkgCmBgYAoKUmVtb3ZpbmcgdGhlICIkIiBhbmQgIiwiIGZyb20gdGhlIGdyb3NzIGNvbHVtbiBhbmQgY29udmVydGluZyB0byBudW1lcmljIHZhbHVlcwpgYGB7cn0KbWVyZ2VkJEJveC5PZmZpY2UuR3Jvc3MuV29ybGR3aWRlIDwtIGdzdWIoIihcXCR8LCkiLCAiIiwgbWVyZ2VkJEJveC5PZmZpY2UuR3Jvc3MuV29ybGR3aWRlKSAlPiUgYXMubnVtZXJpYygpCmBgYAoKUmVtb3ZlZCBzeW1ib2xzIGFuZCBjb252ZXJ0ZWQgdGhlIG5ldCBidWRnZXQgdG8gbnVtZXJpYyB2YWx1ZXMgYnkgbXVsdGlwbHlpbmcgYnkgMTAwMDAwMApgYGB7cn0KYz1nc3ViKCIoXFwkfFxcc3sxfW1pbGxpb24pIiwgIiIsIG1lcmdlZCRCdWRnZXQpIAptZXJnZWQkQnVkZ2V0IDwtIGdzdWIoIltbOmRpZ2l0Ol1dezN9KFxc4oCTKXsxfSIsIiIsYykgJT4lIGFzLm51bWVyaWMoKSoxMDAwMDAwCmBgYAoKUmVtb3ZlZCBzeW1ib2xzIGFuZCBvbmx5IGtlcHQgdGhlIHNjb3JlcyBhcyBudW1lcmljIHZhbHVlcwpgYGB7cn0KbWVyZ2VkJFJvdHRlbi5Ub21hdG9lcyA8LSBzdWJzdHIobWVyZ2VkJFJvdHRlbi5Ub21hdG9lcywxLDIpICU+JSBhcy5udW1lcmljKCkKYGBgCgpSZW1vdmVkIHN5bWJvbHMgYW5kIG9ubHkga2VwdCB0aGUgc2NvcmVzIGFzIG51bWVyaWMgdmFsdWVzCmBgYHtyfQptZXJnZWQkYE1ldGFjcml0aWNgIDwtIHN1YnN0cihtZXJnZWQkYE1ldGFjcml0aWNgLDEsMikgJT4lIGFzLm51bWVyaWMoKQpgYGAKCkFkZGluZyBuZXcgJ1JldmVudWUnIGZlYXR1cmUgdG8gdGhlIG1lcmdlZCBkYXRhIGZyYW1lCmBgYHtyfQptZXJnZWQgPC0gbXV0YXRlKG1lcmdlZCwgUmV2ZW51ZT1Cb3guT2ZmaWNlLkdyb3NzLldvcmxkd2lkZS1CdWRnZXQpCmBgYAoKQ2xlYW5lZCBhbmQgbWVyZ2VkIHRhYmxlCmBgYHtyfQp3cml0ZS5jc3YobWVyZ2VkLCAiQ2xlYW5lZE1hcnZlbC5jc3YiKQptZXJnZWQKYGBgCgojIyMgTW92aW5nIGF2ZXJhZ2VzIG9mIEJveCBPZmZpY2UgR3Jvc3MgV29ybGR3aWRlIGFuZCBCdWRnZXQgb3ZlciB0aW1lClRoZSBidWRnZXQgc2VlbXMgdG8gYmUgZmFpcmx5IGNvbnN0YW50IHRocm91Z2hvdXQgdGhlIHllYXJzIGhvd2V2ZXIgZ3Jvc3MgaGFzIGZhbGxlbiBzbGlnaHRseSBpbiAyMDE1IC0gMjAxNyBhbmQgYmVnaW5zIGluY3JlYXNpbmcgYWdhaW4gaW4gMjAxNyBtb3JlIGF0IGEgaGlnaGVyIHJhdGUgdGhhbiBwcmV2aW91cyB5ZWFycwpgYGB7cn0KZ2dwbG90KGRhdGE9bWVyZ2VkLCBhZXMoeD1ZZWFyKSkgKyAKICBnZW9tX3BvaW50KGFlcyh5PUJveC5PZmZpY2UuR3Jvc3MuV29ybGR3aWRlKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBhZXMoeT1Cb3guT2ZmaWNlLkdyb3NzLldvcmxkd2lkZSwgY29sb3VyPSJHcm9zc19Mb2VzcyIpKSArCiAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgc2U9RixhZXMoeT1Cb3guT2ZmaWNlLkdyb3NzLldvcmxkd2lkZSwgY29sb3VyPSJHcm9zc19MaW5lYXIiKSkgKwogIGdlb21fcG9pbnQoZGF0YT1tZXJnZWQsYWVzKHk9QnVkZ2V0LCBjb2xvdXI9IkJ1ZGdldF9Nb3ZpbmdBdmciKSkgKwogIGdlb21fbGluZShkYXRhPW1lcmdlZCxhZXMoeT1yb2xsYXBwbHlyKG1lcmdlZCRCdWRnZXQsd2lkdGg9MTAsRlVOPW1lYW4scGFydGlhbD1UKSxjb2xvdXI9IkJ1ZGdldF9Nb3ZpbmdBdmciKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9YygyMDA4OjIwMTkpKSArCiAgbGFicyh0aXRsZT0iQm94IE9mZmljZSBHcm9zcyB3b3JsZHdpZGUgYW5kIEJ1ZGdldCBpbmNvbWUgb3ZlciB0aW1lIGZvciBNQ1UgbW92aWVzIikgKwogIHlsYWIobGFiZWw9IkRvbGxhcnMiKSAKICAjc2NhbGVfY29sb3VyX21hbnVhbChuYW1lPSIiLCB2YWx1ZXM9YyhHcm9zc19Nb3ZpbmdBdmc9IiMwMEJBMzgiLCBCdWRnZXRfTW92aW5nQXZnPSIjRjg3NjZEIiwgR3Jvc3NfTG9lc3M9IiM2MTlDRkYiKSkgCmBgYAoKIyMjIFdoYXQgaXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiByZXZlbnVlIGZvciBNYXJ2ZWwgbW92aWVzPyAKVGhlIHJlZCBkYXNoZWQgbGluZSByZXByZXNlbnRzIHRoZSBtZWFuIHJldmVudWUgYW5kIHRoZSBibGFjayBzdXJ2ZSByZXByZXNlbnRzIHRoZSBkZW5zaXR5IGN1cnZlLiBCZWZvcmUgdGFraW5nIHRoZSBsb2cgb2YgdGhlIHJldmVudWUsIHRoZSBkaXN0cmlidXRpb24gYXBwZWFycyB0byBiZSBwb3NpdGl2ZWx5IHNrZXdlZCB0byB0aGUgcmlnaHQuIEFmdGVyIHRoZSB0cmFuc2Zvcm1hdGlvbiwgdGhlIGRpc3RyaWJ1dGlvbiBhcHBlYXJzIHRvIGJlIGNsb3NlciB0byBhIG5vcm1hbCBkaXN0cmlidXRpb24uCmBgYHtyfQpnZ3Bsb3QoZGF0YT1tZXJnZWQsIGFlcyh4PVJldmVudWUpKSArCiAgZ2VvbV9kZW5zaXR5KGNvbG9yPSJibGFjayIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuKG1lcmdlZCRSZXZlbnVlKSwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGxhYnModGl0bGU9IkRpc3RyaWJ1dGlvbiBvZiBSZXZlbnVlIGZvciBNQ1UgbW92aWVzIikgKwogIHhsYWIobGFiZWw9IlJldmVudWUgaW4gRG9sbGFycyIpICsKICB5bGFiKGxhYmVsPSJEZW5zaXR5IikKCmdncGxvdChkYXRhPW1lcmdlZCwgYWVzKHg9bG9nKFJldmVudWUpKSkgKwogIGdlb21fZGVuc2l0eShjb2xvcj0iYmxhY2siKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVhbihsb2cobWVyZ2VkJFJldmVudWUpKSwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGxhYnModGl0bGU9IkRpc3RyaWJ1dGlvbiBvZiBsb2coUmV2ZW51ZSkgZm9yIE1DVSBtb3ZpZXMiKSArCiAgeGxhYihsYWJlbD0ibG9nKFJldmVudWUpIGluIERvbGxhcnMiKSArCiAgeWxhYihsYWJlbD0iRGVuc2l0eSIpCmBgYAoKIyMjIFdoaWNoIHllYXJzIGRpZCBNQ1UgbW92aWVzIGJyaW5nIGluIHRoZSBtb3N0IHJldmVudWU/IApUaGUgZ3JhcGhzIHNob3cgdGhhdCAyMDE4IGFuZCAyMDE5IE1DVSBtb3ZpZXMgYnJvdWdodCBpbiB0aGUgaGlnaGVzdCBSZXZlbnVlIGluY29tZS4gSG93ZXZlciB0aGVyZSB3ZXJlIDIgTUNVIHJlbGVhc2VkIGluIDIwMTkgYW5kIDMgaW4gMjAxOC4gQSBmaWxtIHJlbGVhc2VkIGluIDIwMTkgZ2VuZXJhdGVkIHNpZ25pZmljYW50bHkgbW9yZSByZXZlbnVlIHRoYW4gbW92aWVzIGZyb20gcHJldmlvdXMgeWVhcnMuIChBdmVuZ2VyczogRW5kZ2FtZSkKYGBge3J9Cm1lcmdlZCAlPiUKICBncm91cF9ieShZZWFyKSAlPiUKICBzdW1tYXJpemUoVG90YWwuUmV2ZW51ZT1zdW0oUmV2ZW51ZSkpICU+JQogIGdncGxvdChhZXMoeD1ZZWFyLCB5PVRvdGFsLlJldmVudWUpKSArIAogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgZmlsbD0iI0Y4NzY2RCIsIHBvc2l0aW9uPSJkb2RnZSIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsPVRvdGFsLlJldmVudWUpLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjEpLCBzaXplPTIuMywgdmp1c3Q9LS4yNSwpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPWMoMjAwODoyMDE5KSkgKwogIGxhYnModGl0bGU9IlRvdGFsIFJldmVudWUgdnMgWWVhciBvZiBNQ1UgbW92aWVzIikgKwogIHlsYWIobGFiZWw9IlRvdGFsIFJldmVudWUiKQoKZ2dwbG90KG1lcmdlZCwgYWVzKHg9RmlsbSwgeT1SZXZlbnVlKSkgKyAKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsgZmFjZXRfd3JhcCh+WWVhcikgKyAKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKHRpdGxlPSJSZXZlbnVlIG9mIE1DVSBtb3ZpZXMgZnJvbSAyMDA4LTIwMTkiKQpgYGAKCiMjIyBSZWxhdGlvbnNoaXAgb2YgQnVkZ2V0IGFuZCBHcm9zcyBSZXZlbnVlClRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBzdWdnZXN0cyB0aGF0IHRoZXkgaGF2ZSBhIHBvc2l0aXZlIHJlbGF0aW9uc2hpcCBhbmQgdGhlIG1vdmluZyBhdmVyYWdlIGFuZCBsb2VzcyBjdXJ2ZSBvZiBidWRnZXQgaXMgcmlzaW5nIGJ1dCBzdGFydHMgZHJvcHBpbmcgd2hlbiByZXZlbnVlIHJlYWNoZXMgfiQxLjc1IG1pbGxpb24uIFRoZSBzdW1tYXJ5IG9mIHRoZSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gd2l0aCBCdWRnZXQgYXMgdGhlIHByZWRpY3RvciBhbmQgUmV2ZW51ZSBhcyB0aGUgcmVzcG9uc2Ugc2hvd3MgdGhhdCBCdWRnZXQgaXMgYSBhIHNpZ25pZmljYW50IGZhY3RvciB0aGF0IGluZmx1ZW5jZXMgdGhlIHJldmVudWUgcG9zaXRpdmVseS4gSG93ZXZlciBzaW5jZSB0aGUgc2FtcGxlIHNpemUgaXMgc21hbGwsIGl0IGlzIG5vdCBjbGVhci4gIFRoZSByZXNpZHVhbCBwbG90IGlzIG5vdCB2ZXJ5IHVuc3VhbCwgaG93ZXZlciB0aGVyZSBhcmUgYSBmZXcgb3V0bGllcnMgKDQgYW5kIDMpLiBUaGUgbm9ybWFsIFFRIHBsb3Qgc2hvd3MgdGhhdCB0aGUgcmVzaWR1YWxzIGFyZSBhcHByb3hpbWF0ZWx5IG5vcm1hbGx5IGRzaXRyaWJ1dGVkLgpgYGB7cn0KZ2dwbG90KG1lcmdlZCwgYWVzKHg9QnVkZ2V0LCB5PVJldmVudWUpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChhZXMoY29sb3VyPSJMb2VzcyIpLCBtZXRob2Q9ImxvZXNzIixzaXplPS42LCBzZT1GKSArCiAgZ2VvbV9zbW9vdGgoYWVzKGNvbG91cj0iTGluZWFyIFJlZ3Jlc3Npb24iKSwgbWV0aG9kPSJsbSIsIHNlPUYsIHNpemU9LjYpICsKICB4bGFiKGxhYmVsPSJCdWRnZXQgKERvbGxhcnMpIikgKwogIHlsYWIobGFiZWw9IlJldmVudWUgKERvbGxhcnMpIikgKwogIGxhYnModGl0bGU9IlJFdmVudWUgdnMgQnVkZ2V0IGZvciBNQ1UgbW92aWVzIikgCnJldmZpdCA8LSBsbShSZXZlbnVlIH4gQnVkZ2V0LGRhdGE9bWVyZ2VkKQpzdW1tYXJ5KHJldmZpdCkKcGxvdChyZXZmaXQsMToyKQpgYGAKCiMjIyBEbyBSb3R0ZW4gVG9tYXRvZXMgYW5kIE1ldGFjcml0aWMgYWdyZWU/IApUaGV5IHNlZW0gdG8gaGF2ZSBhIHBvc2l0aXZlIHJlbGF0aWlvbnNoaXAsIGhvd2V2ZXIgaXQgaXMgbm90IHByb3BvcnRpb25hbC4gTWV0YWNyaXRpYyBhcHBlYXJzIHRvIGdpdmUgbG93ZXIgcmF0aW5ncyB0aGFuIFJvdHRlbiBUb21hdG9lcy4KYGBge3J9CmdncGxvdChtZXJnZWQsIGFlcyh4PU1ldGFjcml0aWMsIFJvdHRlbi5Ub21hdG9lcykpICsKICBnZW9tX3BvaW50KCBzaXplPS41KSArCiAgZ2VvbV90ZXh0X3JlcGVsKGxhYmVsPW1lcmdlZCRGaWxtLCBzaXplPTMpICsKICB4bGltKDUwLDEwMCkgKwogIHlsaW0oNTAsMTAwKSArCiAgZ2VvbV9saW5lKGNvbG91cj0iZGFya3JlZCIsIGFscGhhPS42LCBtZXRob2Q9ImxvZXNzIiwgc3RhdD0ic21vb3RoIiwgc2l6ZT0xLjMpICsKICBsYWJzKHRpdGxlPSJNZXRhY3JpdGljIHJhdGluZ3MgdnMgUm90dGVuIFRvbWF0b2VzIHJhdGluZ3Mgb2YgTUNVIE1vdmllcyIpICsKICB5bGFiKGxhYmVsPSJSb3R0ZW4gVG9tYXRvZXMgc2NvcmVzIikgKwogIHhsYWIobGFiZWw9Ik1ldGFjcml0aWMgc2NvcmVzIikKCmdncGxvdChtZXJnZWQpICsKICBnZW9tX2JhcihhZXMoeD1yZW9yZGVyKEZpbG0sIFJvdHRlbi5Ub21hdG9lcyksIHk9Um90dGVuLlRvbWF0b2VzLCBmaWxsPSJSb3R0ZW4gVG9tYXRvZXMiKSwgc3RhdD0iaWRlbnRpdHkiLCBhbHBoYT0xKSArCiAgZ2VvbV9iYXIoYWVzKHg9cmVvcmRlcihGaWxtLCBNZXRhY3JpdGljKSwgeT1NZXRhY3JpdGljLCBmaWxsPSJNZXRhY3JpdGljIiksIHN0YXQ9ImlkZW50aXR5IixhbHBoYT0xKSArCiAgY29vcmRfZmxpcCgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoYT0icmVkIixiPSJibHVlIikpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKCIiKSArCiAgbGFicyh0aXRsZT0iUmF0aW5ncyBvZiBNQ1UgbW92aWVzIikgKwogIHlsYWIoIlJhdGluZyIpICsKICB4bGFiKCJNb3ZpZXMiKQoKYGBgCgojIyMgSG93IGhhdmUgdGhlIHJhdGluZ3MgZXZvbHZlZCBvdmVyIHRpbWU/CkluIGdlbmVyYWwsIFJvdHRlbiBUb21hdG9lcyByZXZpZXdlcnMgYXBwZWFycyB0byBnaXZlIG1vcmUgZ2VuZXJvdXMgcmF0aW5ncyB0aGFuIE1ldGFjcml0aWMgcmV2aWV3ZXJzLiBUaGUgZ3JhcGhzIHN1Z2dlc3RzIHRoYXQgdGhlIHJhdGluZ3MgYXJlIGluY3JlYXNpbmcgdGhlIGJ1dCBoYXZlIGZhbGxlbiBhIGJpdCBzaW5jZSAyMDE4LgpgYGB7cn0KcGxvdDEgPC0gZ2dwbG90KG1lcmdlZCwgYWVzKHg9WWVhciwgeT1NZXRhY3JpdGljKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1jKDIwMDg6MjAxOSkpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3Q9MSkpICsKICB5bGltKDUwLDEwMCkgKwogIGxhYnModGl0bGU9Ik1ldGFjcml0aWMgcmF0aW5nIHNjb3JlcyBcbiBvdmVyIHRpbWUgb2YgTUNVIG1vdmllcyIpICsKICB5bGFiKGxhYmVsPSJNZXRhY3JpdGljIFNjb3JlcyIpCgpwbG90MiA8LSBnZ3Bsb3QobWVyZ2VkLCBhZXMoeD1ZZWFyLCB5PVJvdHRlbi5Ub21hdG9lcykpICsgCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9YygyMDA4OjIwMTkpKSArCiAgeWxpbSg1MCwxMDApICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3Q9MSkpICsKICBsYWJzKHRpdGxlPSJSb3R0ZW4gVG9tYXRvZXMgcmF0aW5nIHNjb3JlcyBcbiBvdmVyIHRpbWUgb2YgTUNVIG1vdmllcyIpICsKICB5bGFiKGxhYmVsPSJSb3R0ZW4gVG9tYXRvZXMgc2NvcmVzIikKCmdyaWQuYXJyYW5nZShwbG90MiwgcGxvdDEsIG5jb2w9MikKYGBgCgojIyMgQ29ubHVzaW9uCjEuIEJ1ZGdldCBhcHBlYXJzIHRvIGJlIHNvbWV3aGF0IGNvbnN0YW50IHdoaWxlIEdyb3NzIGlzIG9uIGFuIHVwd2FyZCB0cmVuZAoyLiBSb3R0ZW4gdG9tYXRvZXMgdGVuZHMgdG8gZ2l2ZSBoaWdoZXIgcmF0aW5ncyB0aGFuIE1ldGFjcml0aWMKMy4gVGhlIGhpZ2hlc3QgYnkgUm90dGVuIFRvbWF0b2VzIGFuZCBNZXRhY3JpdGljIGlzIEJsYWNrIFBhbnRoZXIKNC4gVGhlIG1vdmllIHRoYXQgYnJvdWdodCBpbiB0aGUgbW9zdCByZXZlbnVlIHdhcyBBdmVuZ2VyczpFbmRnYW1lIGluIDIwMTkKNS4gQnVkZ2V0IGlzIGEgc2lnbmlmaWNhbnQgcHJlZGljdG9yIG9mIFJldmVudWUKCg==