Exercise 1.

Using data on credit card applications’ status please present the frequency table with the nice, kable format for average monthly credit card expenditures of applicants.

data(CreditCard)
CreditCard <- CreditCard %>% filter(months!=0) %>% filter(card == "yes")%>% mutate(monthly_expenditure = expenditure / months)


tabela4<-Freq(CreditCard$monthly_expenditure,useNA="ifany")

#using frequency_df to make sure that every second column/row will look diffrently
frequency_df <- as.data.frame(tabela4)

tabela4 %>%
kable(col.names = c("Avg Mon_Exp in kUSD  ","Frequency  ","Percentage %  ","Cumulative frequency  ","Cumulative percentage %  ")) %>%
kable_styling(bootstrap_options = "bordered") %>% 
column_spec(seq(1, ncol(frequency_df), by = 2), italic = T, background = "lightgray") %>%
row_spec(seq(1, nrow(frequency_df), by = 2), italic = T, bold = TRUE, background = "darkgray")
Avg Mon_Exp in kUSD Frequency Percentage % Cumulative frequency Cumulative percentage %
[0,50] 937 0.9168297 937 0.9168297
(50,100] 44 0.0430528 981 0.9598826
(100,150] 14 0.0136986 995 0.9735812
(150,200] 12 0.0117417 1007 0.9853229
(200,250] 8 0.0078278 1015 0.9931507
(250,300] 1 0.0009785 1016 0.9941292
(300,350] 0 0.0000000 1016 0.9941292
(350,400] 1 0.0009785 1017 0.9951076
(400,450] 1 0.0009785 1018 0.9960861
(450,500] 4 0.0039139 1022 1.0000000

Exercise 2.

The data comes from https://flixgem.com/ (dataset version as of March 12, 2021). The data contains information on 9425 movies and series available on Netlix.

Answer with the most appropriate data visualization for the following questions:

1.What is the distribution of Imdb scores for Polish movies and movie-series?

#Reading the database
netflix_data <- read.csv("https://raw.githubusercontent.com/kflisikowski/ds/master/netflix-dataset.csv")

polish <- netflix_data[netflix_data$Languages == "Polish", ]

# Distribution of IMDb scores for Polish movies and movie-series
ggplot(polish) +
  geom_histogram(aes(x = IMDb.Score), fill = "lightgreen", color = "black") +
  scale_x_continuous(breaks = seq(0, 10, by = 0.5)) +
  labs(title = "Distribution of IMDb Scores for Polish Movies and Movie-Series",
       x = "IMDb Scores",
       y = "Amount")

2.What is the density function of Imdb scores for Polish movies and movie-series?

# Filter Polish movies and series
polish_movies <- polish[polish$`Series.or.Movie` == "Movie", ]
polish_series <- polish[polish$`Series.or.Movie` == "Series", ]

# Plot density function separately for movies and series
ggplot() +
  geom_density(data = polish_movies, aes(x = IMDb.Score, fill = "Movie"), alpha = 0.5) +
  geom_density(data = polish_series, aes(x = IMDb.Score, fill = "Series"), alpha = 0.5) +
  labs(title = "Density Function of IMDb Scores for Polish Movies and Series",
       x = "IMDb Scores",
       y = "Density") +
  scale_fill_manual(values = c("darkred", "lightblue"), labels = c("Movie", "Series")) +
  guides(fill = guide_legend(title = "Type"))

3.What are the most popular languages available on Netflix?

# Spliting the data, becouse there can be two or more languages
netflix_data <- netflix_data %>%
  separate_rows(Languages, sep = ", ") %>%
  filter(!is.na(Languages))

# Count occurences of each language
language_counts <- netflix_data %>%
  group_by(Languages) %>%
  summarize(count = n()) %>%
  arrange(desc(count))

# Creating visual reprezentation
ggplot(language_counts[1:10, ], aes(x = reorder(Languages, -count), y = count)) +
  geom_bar(stat = "identity", fill = "pink", color = "black") +
  labs(title = "Top 10 Most Popular Languages on Netflix",
       x = "Language",
       y = "Count") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Extra challenge 1

Create a chart showing actors starring in the most popular productions.

#top 25 film by IMDb.Votes
top_films <- netflix_data %>%
  arrange(desc(`IMDb.Votes`)) %>%
  head(25)

# Count occurences of each actor in the top films
actor_counts <- top_films %>%
  filter(!is.na(Actors)) %>%
  separate_rows(Actors, sep = ", ") %>%
  group_by(Actors) %>%
  summarize(count = n()) %>%
  arrange(desc(count))

# create data visualization
ggplot(actor_counts[1:10, ], aes(x = reorder(Actors, -count), y = count)) +
  geom_bar(stat = "identity", fill = "gold", color = "black") +
  labs(title = "Top 10 Actors with most apparencess in 25 most popular productions",
       x = "Actor",
       y = "Count") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Extra challenge 2

For movies and series, create rating charts from the various portals (Hidden Gem, IMDb, Rotten Tomatoes, Metacritic). Hint: it’s a good idea to reshape the data to long format.

#resheping data in long format
ratings_long <- netflix_data %>%
  select(-Title, -Languages, -Genre, -TMDb.Trailer, -Trailer.Site, -Poster, -Tags, -Country.Availability, -Runtime, -Director, -Writer, -Actors, -View.Rating, -Awards.Received, -Awards.Nominated.For, -Boxoffice, -Release.Date, -Netflix.Release.Date, -Production.House, -Netflix.Link, -IMDb.Link, -Summary, -IMDb.Votes, -Image) %>%
  pivot_longer(cols = ends_with("Score"), names_to = "Portal", values_to = "Rating") %>%
  mutate(Portal = gsub("Rating.", "", Portal),
         Portal = gsub("\\.", " ", Portal)) %>%  # Replace periods with spaces
  group_by(`Series.or.Movie`, Portal) %>%
  summarize(mean_rating = mean(Rating, na.rm = TRUE)) 

# Create data Visualization
ggplot(ratings_long, aes(x = Portal, y = mean_rating, color = `Series.or.Movie`, group = `Series.or.Movie`)) +
  geom_line() +
  labs(title = "Rating Charts from Various Portals for Movies and Series",
       x = "Portal",
       y = "Mean Rating") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Extra challenge 3

Which film studios produce the most and how has this changed over the years?

netflix_data$Release_Year <- as.integer(format(as.Date(netflix_data$`Release.Date`, format = "%m/%d/%Y"), "%Y"))

filtered_data <- netflix_data %>%
  filter(Production.House != "")

# Group the data by film studio and year, count the number of movies
studio_year_counts <- filtered_data %>%
  filter(!is.na(Release_Year)) %>%  # Filter out rows with missing release year
  group_by(`Production.House`, Release_Year) %>%
  summarize(num_movies = n()) %>%
  ungroup()

# Find the top film studios by total number of movies produced
top_studios <- studio_year_counts %>%
  group_by(`Production.House`) %>%
  summarize(total_movies = sum(num_movies)) %>%
  top_n(10, total_movies)  # Select top 10 studios

# Filter data for top film studios
top_studio_data <- studio_year_counts %>%
  filter(`Production.House` %in% top_studios$`Production.House`)

# Creating data visaulization
ggplot(top_studio_data, aes(x = Release_Year, y = num_movies, color = `Production.House`)) +
  geom_line() +
  labs(title = "Trend of Movie Production by Top Film Studios Over the Years",
       x = "Release Year",
       y = "Number of Movies") +
  theme(legend.position = "right", legend.title = element_blank())

The top studio

total_studio_movies <- studio_year_counts %>%
  group_by(Production.House) %>%
  summarize(total_movies = sum(num_movies)) %>%
  arrange(desc(total_movies))

# Select the top studio
top_studio <- total_studio_movies$Production.House[1]

# Filter data for the top studio
top_studio_data <- studio_year_counts %>%
  filter(Production.House == top_studio)

# Creating data visaulization
ggplot(top_studio_data, aes(x = Release_Year, y = num_movies)) +
  geom_line(color = "purple", size = 1.5) +  # Increase line thickness
  labs(title = paste("Trend of Movie Production for", top_studio, "Over the Years"),
       x = "Release Year",
       y = "Number of Movies") +
  scale_y_continuous(breaks = seq(0, max(top_studio_data$num_movies), by = 0.5))

LS0tDQp0aXRsZTogIkRhdGEgVmlzdWFsaXphdGlvbiINCmF1dGhvcjogIlN6eW1vbiBTa2FyYmVrIEN5cnlsIFVmbmHFgiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdGhlbWU6IGNlcnVsZWFuDQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQ0KICAgIGZvbnRzaXplOiA4cHQNCiAgICB0b2M6IHllcw0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogbm8NCiAgICBkZl9wcmludDogZGVmYXVsdA0KICAgIHRvY19kZXB0aDogNQ0KZWRpdG9yX29wdGlvbnM6IA0KICBtYXJrZG93bjogDQogICAgd3JhcDogNzINCi0tLQ0KDQoNCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQojIyBHbG9iYWwgb3B0aW9ucw0Kb3B0aW9ucyhxd3JhcHMyX21hcmt1cCA9ICJtYXJrZG93biIpDQpsaWJyYXJ5KHF3cmFwczIpDQpsaWJyYXJ5KGFyc2VuYWwpDQpsaWJyYXJ5KGUxMDcxKQ0KbGlicmFyeShoYXZlbikNCmxpYnJhcnkocGFwZVIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpsaWJyYXJ5KHN1bW1hcnl0b29scykNCmxpYnJhcnkoY2xhc3NJbnQpDQpsaWJyYXJ5KHBhc3RlY3MpDQpsaWJyYXJ5KHJlcG9ydHRvb2xzKQ0KbGlicmFyeShkZXNjdGFibGUpDQpsaWJyYXJ5KERlc2NUb29scykNCmxpYnJhcnkoZnJlcXVlbmN5KQ0KbGlicmFyeShnZ3B1YnIpDQpsaWJyYXJ5KGRsb29rcikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkodGlueXRleCkNCmxpYnJhcnkoQUVSKQ0KbGlicmFyeShnZ1RoZW1lQXNzaXN0KQ0KbGlicmFyeShTbWFydGVyUG9sYW5kKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFKQ0KYGBgDQoNCg0KIyMgRXhlcmNpc2UgMS4NClVzaW5nIGRhdGEgb24gY3JlZGl0IGNhcmQgYXBwbGljYXRpb25z4oCZIHN0YXR1cyBwbGVhc2UgcHJlc2VudCB0aGUgZnJlcXVlbmN5IHRhYmxlIHdpdGggdGhlIG5pY2UsIGthYmxlIGZvcm1hdCBmb3IgYXZlcmFnZSBtb250aGx5IGNyZWRpdCBjYXJkIGV4cGVuZGl0dXJlcyBvZiBhcHBsaWNhbnRzLg0KDQpgYGB7ciBFeGVyY2lzZSAxfQ0KZGF0YShDcmVkaXRDYXJkKQ0KQ3JlZGl0Q2FyZCA8LSBDcmVkaXRDYXJkICU+JSBmaWx0ZXIobW9udGhzIT0wKSAlPiUgZmlsdGVyKGNhcmQgPT0gInllcyIpJT4lIG11dGF0ZShtb250aGx5X2V4cGVuZGl0dXJlID0gZXhwZW5kaXR1cmUgLyBtb250aHMpDQoNCg0KdGFiZWxhNDwtRnJlcShDcmVkaXRDYXJkJG1vbnRobHlfZXhwZW5kaXR1cmUsdXNlTkE9ImlmYW55IikNCg0KI3VzaW5nIGZyZXF1ZW5jeV9kZiB0byBtYWtlIHN1cmUgdGhhdCBldmVyeSBzZWNvbmQgY29sdW1uL3JvdyB3aWxsIGxvb2sgZGlmZnJlbnRseQ0KZnJlcXVlbmN5X2RmIDwtIGFzLmRhdGEuZnJhbWUodGFiZWxhNCkNCg0KdGFiZWxhNCAlPiUNCmthYmxlKGNvbC5uYW1lcyA9IGMoIkF2ZyBNb25fRXhwIGluIGtVU0QgICIsIkZyZXF1ZW5jeSAgIiwiUGVyY2VudGFnZSAlICAiLCJDdW11bGF0aXZlIGZyZXF1ZW5jeSAgIiwiQ3VtdWxhdGl2ZSBwZXJjZW50YWdlICUgICIpKSAlPiUNCmthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAiYm9yZGVyZWQiKSAlPiUgDQpjb2x1bW5fc3BlYyhzZXEoMSwgbmNvbChmcmVxdWVuY3lfZGYpLCBieSA9IDIpLCBpdGFsaWMgPSBULCBiYWNrZ3JvdW5kID0gImxpZ2h0Z3JheSIpICU+JQ0Kcm93X3NwZWMoc2VxKDEsIG5yb3coZnJlcXVlbmN5X2RmKSwgYnkgPSAyKSwgaXRhbGljID0gVCwgYm9sZCA9IFRSVUUsIGJhY2tncm91bmQgPSAiZGFya2dyYXkiKQ0KYGBgDQoNCiMjIEV4ZXJjaXNlIDIuDQpUaGUgZGF0YSBjb21lcyBmcm9tIGh0dHBzOi8vZmxpeGdlbS5jb20vIChkYXRhc2V0IHZlcnNpb24gYXMgb2YgTWFyY2ggMTIsIDIwMjEpLiBUaGUgZGF0YSBjb250YWlucyBpbmZvcm1hdGlvbiBvbiA5NDI1IG1vdmllcyBhbmQgc2VyaWVzIGF2YWlsYWJsZSBvbiBOZXRsaXguDQoNCkFuc3dlciB3aXRoIHRoZSBtb3N0IGFwcHJvcHJpYXRlIGRhdGEgdmlzdWFsaXphdGlvbiBmb3IgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6DQoNCjEuV2hhdCBpcyB0aGUgZGlzdHJpYnV0aW9uIG9mIEltZGIgc2NvcmVzIGZvciBQb2xpc2ggbW92aWVzIGFuZCBtb3ZpZS1zZXJpZXM/DQoNCmBgYHtyIGRpc3RyaWJ1dGlvbn0NCiNSZWFkaW5nIHRoZSBkYXRhYmFzZQ0KbmV0ZmxpeF9kYXRhIDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20va2ZsaXNpa293c2tpL2RzL21hc3Rlci9uZXRmbGl4LWRhdGFzZXQuY3N2IikNCg0KcG9saXNoIDwtIG5ldGZsaXhfZGF0YVtuZXRmbGl4X2RhdGEkTGFuZ3VhZ2VzID09ICJQb2xpc2giLCBdDQoNCiMgRGlzdHJpYnV0aW9uIG9mIElNRGIgc2NvcmVzIGZvciBQb2xpc2ggbW92aWVzIGFuZCBtb3ZpZS1zZXJpZXMNCmdncGxvdChwb2xpc2gpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBJTURiLlNjb3JlKSwgZmlsbCA9ICJsaWdodGdyZWVuIiwgY29sb3IgPSAiYmxhY2siKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMTAsIGJ5ID0gMC41KSkgKw0KICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBJTURiIFNjb3JlcyBmb3IgUG9saXNoIE1vdmllcyBhbmQgTW92aWUtU2VyaWVzIiwNCiAgICAgICB4ID0gIklNRGIgU2NvcmVzIiwNCiAgICAgICB5ID0gIkFtb3VudCIpDQpgYGANCg0KMi5XaGF0IGlzIHRoZSBkZW5zaXR5IGZ1bmN0aW9uIG9mIEltZGIgc2NvcmVzIGZvciBQb2xpc2ggbW92aWVzIGFuZCBtb3ZpZS1zZXJpZXM/DQpgYGB7ciBkZW5zaXR5fQ0KIyBGaWx0ZXIgUG9saXNoIG1vdmllcyBhbmQgc2VyaWVzDQpwb2xpc2hfbW92aWVzIDwtIHBvbGlzaFtwb2xpc2gkYFNlcmllcy5vci5Nb3ZpZWAgPT0gIk1vdmllIiwgXQ0KcG9saXNoX3NlcmllcyA8LSBwb2xpc2hbcG9saXNoJGBTZXJpZXMub3IuTW92aWVgID09ICJTZXJpZXMiLCBdDQoNCiMgUGxvdCBkZW5zaXR5IGZ1bmN0aW9uIHNlcGFyYXRlbHkgZm9yIG1vdmllcyBhbmQgc2VyaWVzDQpnZ3Bsb3QoKSArDQogIGdlb21fZGVuc2l0eShkYXRhID0gcG9saXNoX21vdmllcywgYWVzKHggPSBJTURiLlNjb3JlLCBmaWxsID0gIk1vdmllIiksIGFscGhhID0gMC41KSArDQogIGdlb21fZGVuc2l0eShkYXRhID0gcG9saXNoX3NlcmllcywgYWVzKHggPSBJTURiLlNjb3JlLCBmaWxsID0gIlNlcmllcyIpLCBhbHBoYSA9IDAuNSkgKw0KICBsYWJzKHRpdGxlID0gIkRlbnNpdHkgRnVuY3Rpb24gb2YgSU1EYiBTY29yZXMgZm9yIFBvbGlzaCBNb3ZpZXMgYW5kIFNlcmllcyIsDQogICAgICAgeCA9ICJJTURiIFNjb3JlcyIsDQogICAgICAgeSA9ICJEZW5zaXR5IikgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJkYXJrcmVkIiwgImxpZ2h0Ymx1ZSIpLCBsYWJlbHMgPSBjKCJNb3ZpZSIsICJTZXJpZXMiKSkgKw0KICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJUeXBlIikpDQpgYGANCg0KMy5XaGF0IGFyZSB0aGUgbW9zdCBwb3B1bGFyIGxhbmd1YWdlcyBhdmFpbGFibGUgb24gTmV0ZmxpeD8NCg0KYGBge3IgbW9zdCBwb3B1bGFyIGxhbmd1YWdlc30NCiMgU3BsaXRpbmcgdGhlIGRhdGEsIGJlY291c2UgdGhlcmUgY2FuIGJlIHR3byBvciBtb3JlIGxhbmd1YWdlcw0KbmV0ZmxpeF9kYXRhIDwtIG5ldGZsaXhfZGF0YSAlPiUNCiAgc2VwYXJhdGVfcm93cyhMYW5ndWFnZXMsIHNlcCA9ICIsICIpICU+JQ0KICBmaWx0ZXIoIWlzLm5hKExhbmd1YWdlcykpDQoNCiMgQ291bnQgb2NjdXJlbmNlcyBvZiBlYWNoIGxhbmd1YWdlDQpsYW5ndWFnZV9jb3VudHMgPC0gbmV0ZmxpeF9kYXRhICU+JQ0KICBncm91cF9ieShMYW5ndWFnZXMpICU+JQ0KICBzdW1tYXJpemUoY291bnQgPSBuKCkpICU+JQ0KICBhcnJhbmdlKGRlc2MoY291bnQpKQ0KDQojIENyZWF0aW5nIHZpc3VhbCByZXByZXplbnRhdGlvbg0KZ2dwbG90KGxhbmd1YWdlX2NvdW50c1sxOjEwLCBdLCBhZXMoeCA9IHJlb3JkZXIoTGFuZ3VhZ2VzLCAtY291bnQpLCB5ID0gY291bnQpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInBpbmsiLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJUb3AgMTAgTW9zdCBQb3B1bGFyIExhbmd1YWdlcyBvbiBOZXRmbGl4IiwNCiAgICAgICB4ID0gIkxhbmd1YWdlIiwNCiAgICAgICB5ID0gIkNvdW50IikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQoNCiMjIEV4dHJhIGNoYWxsZW5nZSAxDQpDcmVhdGUgYSBjaGFydCBzaG93aW5nIGFjdG9ycyBzdGFycmluZyBpbiB0aGUgbW9zdCBwb3B1bGFyIHByb2R1Y3Rpb25zLg0KYGBge3IgY2hhbGxlbmdlIDF9DQojdG9wIDI1IGZpbG0gYnkgSU1EYi5Wb3Rlcw0KdG9wX2ZpbG1zIDwtIG5ldGZsaXhfZGF0YSAlPiUNCiAgYXJyYW5nZShkZXNjKGBJTURiLlZvdGVzYCkpICU+JQ0KICBoZWFkKDI1KQ0KDQojIENvdW50IG9jY3VyZW5jZXMgb2YgZWFjaCBhY3RvciBpbiB0aGUgdG9wIGZpbG1zDQphY3Rvcl9jb3VudHMgPC0gdG9wX2ZpbG1zICU+JQ0KICBmaWx0ZXIoIWlzLm5hKEFjdG9ycykpICU+JQ0KICBzZXBhcmF0ZV9yb3dzKEFjdG9ycywgc2VwID0gIiwgIikgJT4lDQogIGdyb3VwX2J5KEFjdG9ycykgJT4lDQogIHN1bW1hcml6ZShjb3VudCA9IG4oKSkgJT4lDQogIGFycmFuZ2UoZGVzYyhjb3VudCkpDQoNCiMgY3JlYXRlIGRhdGEgdmlzdWFsaXphdGlvbg0KZ2dwbG90KGFjdG9yX2NvdW50c1sxOjEwLCBdLCBhZXMoeCA9IHJlb3JkZXIoQWN0b3JzLCAtY291bnQpLCB5ID0gY291bnQpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gImdvbGQiLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJUb3AgMTAgQWN0b3JzIHdpdGggbW9zdCBhcHBhcmVuY2VzcyBpbiAyNSBtb3N0IHBvcHVsYXIgcHJvZHVjdGlvbnMiLA0KICAgICAgIHggPSAiQWN0b3IiLA0KICAgICAgIHkgPSAiQ291bnQiKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANCg0KIyMgRXh0cmEgY2hhbGxlbmdlIDINCkZvciBtb3ZpZXMgYW5kIHNlcmllcywgY3JlYXRlIHJhdGluZyBjaGFydHMgZnJvbSB0aGUgdmFyaW91cyBwb3J0YWxzIChIaWRkZW4gR2VtLCBJTURiLCBSb3R0ZW4gVG9tYXRvZXMsIE1ldGFjcml0aWMpLiBIaW50OiBpdOKAmXMgYSBnb29kIGlkZWEgdG8gcmVzaGFwZSB0aGUgZGF0YSB0byBsb25nIGZvcm1hdC4NCg0KYGBge3IgY2hhbGxlbmdlIDJ9DQojcmVzaGVwaW5nIGRhdGEgaW4gbG9uZyBmb3JtYXQNCnJhdGluZ3NfbG9uZyA8LSBuZXRmbGl4X2RhdGEgJT4lDQogIHNlbGVjdCgtVGl0bGUsIC1MYW5ndWFnZXMsIC1HZW5yZSwgLVRNRGIuVHJhaWxlciwgLVRyYWlsZXIuU2l0ZSwgLVBvc3RlciwgLVRhZ3MsIC1Db3VudHJ5LkF2YWlsYWJpbGl0eSwgLVJ1bnRpbWUsIC1EaXJlY3RvciwgLVdyaXRlciwgLUFjdG9ycywgLVZpZXcuUmF0aW5nLCAtQXdhcmRzLlJlY2VpdmVkLCAtQXdhcmRzLk5vbWluYXRlZC5Gb3IsIC1Cb3hvZmZpY2UsIC1SZWxlYXNlLkRhdGUsIC1OZXRmbGl4LlJlbGVhc2UuRGF0ZSwgLVByb2R1Y3Rpb24uSG91c2UsIC1OZXRmbGl4LkxpbmssIC1JTURiLkxpbmssIC1TdW1tYXJ5LCAtSU1EYi5Wb3RlcywgLUltYWdlKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBlbmRzX3dpdGgoIlNjb3JlIiksIG5hbWVzX3RvID0gIlBvcnRhbCIsIHZhbHVlc190byA9ICJSYXRpbmciKSAlPiUNCiAgbXV0YXRlKFBvcnRhbCA9IGdzdWIoIlJhdGluZy4iLCAiIiwgUG9ydGFsKSwNCiAgICAgICAgIFBvcnRhbCA9IGdzdWIoIlxcLiIsICIgIiwgUG9ydGFsKSkgJT4lICAjIFJlcGxhY2UgcGVyaW9kcyB3aXRoIHNwYWNlcw0KICBncm91cF9ieShgU2VyaWVzLm9yLk1vdmllYCwgUG9ydGFsKSAlPiUNCiAgc3VtbWFyaXplKG1lYW5fcmF0aW5nID0gbWVhbihSYXRpbmcsIG5hLnJtID0gVFJVRSkpIA0KDQojIENyZWF0ZSBkYXRhIFZpc3VhbGl6YXRpb24NCmdncGxvdChyYXRpbmdzX2xvbmcsIGFlcyh4ID0gUG9ydGFsLCB5ID0gbWVhbl9yYXRpbmcsIGNvbG9yID0gYFNlcmllcy5vci5Nb3ZpZWAsIGdyb3VwID0gYFNlcmllcy5vci5Nb3ZpZWApKSArDQogIGdlb21fbGluZSgpICsNCiAgbGFicyh0aXRsZSA9ICJSYXRpbmcgQ2hhcnRzIGZyb20gVmFyaW91cyBQb3J0YWxzIGZvciBNb3ZpZXMgYW5kIFNlcmllcyIsDQogICAgICAgeCA9ICJQb3J0YWwiLA0KICAgICAgIHkgPSAiTWVhbiBSYXRpbmciKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANCg0KIyMgRXh0cmEgY2hhbGxlbmdlIDMNCldoaWNoIGZpbG0gc3R1ZGlvcyBwcm9kdWNlIHRoZSBtb3N0IGFuZCBob3cgaGFzIHRoaXMgY2hhbmdlZCBvdmVyIHRoZSB5ZWFycz8NCmBgYHtyIGNoYWxsZW5nZSAzfQ0KbmV0ZmxpeF9kYXRhJFJlbGVhc2VfWWVhciA8LSBhcy5pbnRlZ2VyKGZvcm1hdChhcy5EYXRlKG5ldGZsaXhfZGF0YSRgUmVsZWFzZS5EYXRlYCwgZm9ybWF0ID0gIiVtLyVkLyVZIiksICIlWSIpKQ0KDQpmaWx0ZXJlZF9kYXRhIDwtIG5ldGZsaXhfZGF0YSAlPiUNCiAgZmlsdGVyKFByb2R1Y3Rpb24uSG91c2UgIT0gIiIpDQoNCiMgR3JvdXAgdGhlIGRhdGEgYnkgZmlsbSBzdHVkaW8gYW5kIHllYXIsIGNvdW50IHRoZSBudW1iZXIgb2YgbW92aWVzDQpzdHVkaW9feWVhcl9jb3VudHMgPC0gZmlsdGVyZWRfZGF0YSAlPiUNCiAgZmlsdGVyKCFpcy5uYShSZWxlYXNlX1llYXIpKSAlPiUgICMgRmlsdGVyIG91dCByb3dzIHdpdGggbWlzc2luZyByZWxlYXNlIHllYXINCiAgZ3JvdXBfYnkoYFByb2R1Y3Rpb24uSG91c2VgLCBSZWxlYXNlX1llYXIpICU+JQ0KICBzdW1tYXJpemUobnVtX21vdmllcyA9IG4oKSkgJT4lDQogIHVuZ3JvdXAoKQ0KDQojIEZpbmQgdGhlIHRvcCBmaWxtIHN0dWRpb3MgYnkgdG90YWwgbnVtYmVyIG9mIG1vdmllcyBwcm9kdWNlZA0KdG9wX3N0dWRpb3MgPC0gc3R1ZGlvX3llYXJfY291bnRzICU+JQ0KICBncm91cF9ieShgUHJvZHVjdGlvbi5Ib3VzZWApICU+JQ0KICBzdW1tYXJpemUodG90YWxfbW92aWVzID0gc3VtKG51bV9tb3ZpZXMpKSAlPiUNCiAgdG9wX24oMTAsIHRvdGFsX21vdmllcykgICMgU2VsZWN0IHRvcCAxMCBzdHVkaW9zDQoNCiMgRmlsdGVyIGRhdGEgZm9yIHRvcCBmaWxtIHN0dWRpb3MNCnRvcF9zdHVkaW9fZGF0YSA8LSBzdHVkaW9feWVhcl9jb3VudHMgJT4lDQogIGZpbHRlcihgUHJvZHVjdGlvbi5Ib3VzZWAgJWluJSB0b3Bfc3R1ZGlvcyRgUHJvZHVjdGlvbi5Ib3VzZWApDQoNCiMgQ3JlYXRpbmcgZGF0YSB2aXNhdWxpemF0aW9uDQpnZ3Bsb3QodG9wX3N0dWRpb19kYXRhLCBhZXMoeCA9IFJlbGVhc2VfWWVhciwgeSA9IG51bV9tb3ZpZXMsIGNvbG9yID0gYFByb2R1Y3Rpb24uSG91c2VgKSkgKw0KICBnZW9tX2xpbmUoKSArDQogIGxhYnModGl0bGUgPSAiVHJlbmQgb2YgTW92aWUgUHJvZHVjdGlvbiBieSBUb3AgRmlsbSBTdHVkaW9zIE92ZXIgdGhlIFllYXJzIiwNCiAgICAgICB4ID0gIlJlbGVhc2UgWWVhciIsDQogICAgICAgeSA9ICJOdW1iZXIgb2YgTW92aWVzIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQoNCmBgYA0KDQpUaGUgdG9wIHN0dWRpbw0KYGBge3IgdG9wIHN0dWRpb30NCg0KDQp0b3RhbF9zdHVkaW9fbW92aWVzIDwtIHN0dWRpb195ZWFyX2NvdW50cyAlPiUNCiAgZ3JvdXBfYnkoUHJvZHVjdGlvbi5Ib3VzZSkgJT4lDQogIHN1bW1hcml6ZSh0b3RhbF9tb3ZpZXMgPSBzdW0obnVtX21vdmllcykpICU+JQ0KICBhcnJhbmdlKGRlc2ModG90YWxfbW92aWVzKSkNCg0KIyBTZWxlY3QgdGhlIHRvcCBzdHVkaW8NCnRvcF9zdHVkaW8gPC0gdG90YWxfc3R1ZGlvX21vdmllcyRQcm9kdWN0aW9uLkhvdXNlWzFdDQoNCiMgRmlsdGVyIGRhdGEgZm9yIHRoZSB0b3Agc3R1ZGlvDQp0b3Bfc3R1ZGlvX2RhdGEgPC0gc3R1ZGlvX3llYXJfY291bnRzICU+JQ0KICBmaWx0ZXIoUHJvZHVjdGlvbi5Ib3VzZSA9PSB0b3Bfc3R1ZGlvKQ0KDQojIENyZWF0aW5nIGRhdGEgdmlzYXVsaXphdGlvbg0KZ2dwbG90KHRvcF9zdHVkaW9fZGF0YSwgYWVzKHggPSBSZWxlYXNlX1llYXIsIHkgPSBudW1fbW92aWVzKSkgKw0KICBnZW9tX2xpbmUoY29sb3IgPSAicHVycGxlIiwgc2l6ZSA9IDEuNSkgKyAgIyBJbmNyZWFzZSBsaW5lIHRoaWNrbmVzcw0KICBsYWJzKHRpdGxlID0gcGFzdGUoIlRyZW5kIG9mIE1vdmllIFByb2R1Y3Rpb24gZm9yIiwgdG9wX3N0dWRpbywgIk92ZXIgdGhlIFllYXJzIiksDQogICAgICAgeCA9ICJSZWxlYXNlIFllYXIiLA0KICAgICAgIHkgPSAiTnVtYmVyIG9mIE1vdmllcyIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCBtYXgodG9wX3N0dWRpb19kYXRhJG51bV9tb3ZpZXMpLCBieSA9IDAuNSkpDQpgYGA=