library(dplyr)
library(ggplot2)
library(readr)
library(tidyverse)
── Attaching core tidyverse packages ────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ lubridate 1.9.4     ✔ tibble    3.2.1
✔ purrr     1.0.2     ✔ tidyr     1.3.1── Conflicts ──────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(conflicted)
library(skimr)
library(ggcorrplot)
#Reading the data set and printing first 5rows
data <- read.csv("dataset.csv")

conflicted::conflicts_prefer(dplyr::filter)
[conflicted] Removing existing preference.[conflicted] Will prefer dplyr::filter over any other package.
# Filtering dataset where explicit is "True" and taking a sample of 9,000 rows
sample_data <- data |> filter(explicit == "True") |> sample_n(9000)
data <- sample_data
nrow(data)
[1] 9000
# Display first few rows
head(data)

Step 1: Grouping Data and Analyzing Probabilities

Group 1: Grouping by Track Genre

group1 <- data |> 
  group_by(track_genre) |>
  summarise(Count = n(), Mean_Popularity = mean(popularity, na.rm = TRUE))
print(group1)

The genres with lower counts have a lower probability of occurrence in the dataset(black-metal).


ggplot(group1, aes(x =reorder(track_genre, -Mean_Popularity), y = Mean_Popularity)) +
  geom_bar(stat = "identity", fill = "blue") +
  labs(title = "Mean Popularity by Track Genre",
       x = "Track Genre",
       y = "Mean Popularity") +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5,size = 6),  
    panel.grid.major.x = element_blank(),   # Remove vertical grid lines
    plot.margin = margin(b = 100)           # Add bottom margin for labels
  )

The graph shows a clear hierarchy in genre popularity, with the highest-rated genres reaching nearly 60 on the popularity scale while the lowest-rated genres fall below 10, demonstrating significant variation in listener preferences.

Group2: Grouping by Genre and Explicit Content

group2 <- data |>
  group_by(track_genre, explicit) |>
  summarise(Count = n(), Median_Danceability = median(danceability, na.rm = TRUE))
`summarise()` has grouped output by 'track_genre'. You can override using the `.groups` argument.
print(group2)
# Create faceted bar chart
ggplot(group2, aes(x = reorder(track_genre, -Median_Danceability), 
                   y = Median_Danceability,
                   fill = explicit)) +
  geom_bar(stat = "identity") +
  facet_wrap(~explicit) +
  scale_fill_manual(values = c( "True" = "coral")) +
  labs(title = "Median Danceability by Genre and Explicit Content",
       x = "Track Genre",
       y = "Median Danceability",
       fill = "Explicit") +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 90,
                              hjust = 1, vjust = 0.5,
                              size = 4),
    legend.position = "none",
    
    panel.grid.major.x = element_blank(),
    plot.margin = margin(b = 100) 
  )

By grouping and graph, we can know-

Most genres have significantly more non-explicit tracks than explicit ones - for example, acoustic has 948 non-explicit vs only 52 explicit tracks, and ambient has 995 non-explicit tracks, showing a clear preference for clean content in these genres.

Alternative music shows the highest proportion of explicit content (164 explicit tracks out of 1000) compared to other genres, while ambient and afrobeat have very few explicit tracks (less than 20 each).

Danceability varies notably between explicit and non-explicit tracks within the same genre - for instance, alternative music shows higher danceability in explicit tracks (0.663) compared to non-explicit ones (0.538), while acoustic music shows the opposite trend with non-explicit tracks being more danceable (0.564 vs 0.491).

Group 3: Grouping by Binned Popularity Scores

data <- data |> mutate(Popularity_Bin = cut(popularity, breaks = 5))
group3 <- data |>
  group_by(track_genre, Popularity_Bin) |>
  summarise(Count = n())
`summarise()` has grouped output by 'track_genre'. You can override using the `.groups` argument.
print(group3)
ggplot(group3, aes(x = Count, y = track_genre, fill = Popularity_Bin)) +
  geom_bar(stat = "identity", position = "stack") +
  scale_fill_brewer(palette = "RdYlBu") +
  labs(title = "Distribution of Popularity Scores Across Music Genres",
       x = "Number of Tracks",
       y = "Genre") +
  theme_minimal() +
  theme(
    axis.text.y = element_text(size = 5,    # Increase text size
                              margin = margin(r = 10)), # Add right margin
    plot.margin = margin(r = 8),            # Add right margin for legend
    legend.position = "right",
    legend.title = element_text(size = 10),
    legend.text = element_text(size = 9),
    panel.grid.major.y = element_blank() 
  )

Popularity Distribution is Skewed: Most genres show a concentration of tracks in the middle popularity ranges (20-60), with very few tracks reaching the highest popularity bracket (80-100). For example, acoustic has only 1 track in the highest range but 518 tracks in the middle range (40-60).

Genre-Specific Patterns: Different genres show distinct popularity patterns:

Acoustic music has a bell-shaped distribution with most tracks in the middle ranges Afrobeat shows a left-skewed distribution with most tracks in lower popularity ranges (482 tracks in the lowest bracket) Alt-rock demonstrates a similar pattern to afrobeat with high counts in lower popularity ranges Extreme Popularity is Rare: Across all genres, very few tracks achieve the highest popularity bracket (80-100), suggesting that reaching top popularity is exceptionally challenging regardless of genre. The middle ranges (20-60) contain the bulk of tracks for most genres.

Step 2 : Investigating Combinations of Genre and Explicitness

category_combinations <- data |> count(track_genre, explicit)
print(category_combinations)


# Find missing combinations
all_combinations <- expand.grid(unique(data$track_genre), unique(data$explicit))
missing_combinations <- anti_join(all_combinations, category_combinations, by = c("Var1" = "track_genre", "Var2" ="explicit"))
print(missing_combinations)

Step 3 : Finding combinations

# Find missing combinations
all_combinations <- expand.grid(unique(data$track_genre), unique(data$explicit))
missing_combinations <- anti_join(all_combinations, category_combinations, by = c("Var1" = "track_genre", "Var2" ="explicit"))
print(missing_combinations)
# Most common combinations
common_combinations <- group3 |>
  group_by(track_genre, Popularity_Bin) |>
  summarise(Count = n()) |>
  arrange(desc(Count))

# Least common combinations
least_common_combinations <- group3 |>
  group_by(track_genre, Popularity_Bin) |>
  summarise(Count = n()) |>
  arrange(Count)

# Display the most common combinations
print("Most common combinations:")
head(common_combinations, 10)  # Views top 10 most common combinations

# Display the least common combinations
print("Least common combinations:")
head(least_common_combinations, 10)  # Views top 10 least common combinations

From the least common and most common combinations, we can notice- 1. Music genres like “acoustic,” “afrobeat,” and “alt-rock” are spread across multiple popularity bins.
2. The count distribution is relatively even across different popularity bins.
3. Some genres may perform better in higher popularity ranges, like “alt-rock.”
4. Certain genres, like “acoustic” and “afrobeat,” could appeal to niche audiences.

Summary:

Grouping by different categorical variables reveals patterns in occurrence probabilities. The rarest groups can be identified and analyzed for anomalies. Missing genre-explicitness combinations hint at structured gaps in the dataset. Visualizations enhance interpretability and hypothesis testing.

Further Questions to Investigate-

What factors contribute to the rarity of high-popularity tracks across all genres?

Is there a temporal component affecting popularity distributions?

How do other track features (danceability, energy) correlate with these popularity patterns?

Are there regional or cultural factors influencing these distributions?

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShjb25mbGljdGVkKQ0KbGlicmFyeShza2ltcikNCmxpYnJhcnkoZ2djb3JycGxvdCkNCmBgYA0KDQpgYGB7cn0NCiNSZWFkaW5nIHRoZSBkYXRhIHNldCBhbmQgcHJpbnRpbmcgZmlyc3QgNXJvd3MNCmRhdGEgPC0gcmVhZC5jc3YoImRhdGFzZXQuY3N2IikNCg0KY29uZmxpY3RlZDo6Y29uZmxpY3RzX3ByZWZlcihkcGx5cjo6ZmlsdGVyKQ0KDQojIEZpbHRlcmluZyBkYXRhc2V0IHdoZXJlIGV4cGxpY2l0IGlzICJUcnVlIiBhbmQgdGFraW5nIGEgc2FtcGxlIG9mIDksMDAwIHJvd3MNCnNhbXBsZV9kYXRhIDwtIGRhdGEgfD4gZmlsdGVyKGV4cGxpY2l0ID09ICJUcnVlIikgfD4gc2FtcGxlX24oOTAwMCkNCmRhdGEgPC0gc2FtcGxlX2RhdGENCm5yb3coZGF0YSkNCg0KIyBEaXNwbGF5IGZpcnN0IGZldyByb3dzDQpoZWFkKGRhdGEpDQpgYGANCiMjIyBTdGVwIDE6IEdyb3VwaW5nIERhdGEgYW5kIEFuYWx5emluZyBQcm9iYWJpbGl0aWVzDQojIyMgR3JvdXAgMTogR3JvdXBpbmcgYnkgVHJhY2sgR2VucmUNCmBgYHtyfQ0KZ3JvdXAxIDwtIGRhdGEgfD4gDQogIGdyb3VwX2J5KHRyYWNrX2dlbnJlKSB8Pg0KICBzdW1tYXJpc2UoQ291bnQgPSBuKCksIE1lYW5fUG9wdWxhcml0eSA9IG1lYW4ocG9wdWxhcml0eSwgbmEucm0gPSBUUlVFKSkNCnByaW50KGdyb3VwMSkNCmBgYA0KVGhlIGdlbnJlcyB3aXRoIGxvd2VyIGNvdW50cyBoYXZlIGEgbG93ZXIgcHJvYmFiaWxpdHkgb2Ygb2NjdXJyZW5jZSBpbiB0aGUgZGF0YXNldChibGFjay1tZXRhbCkuDQpgYGB7cn0NCg0KZ2dwbG90KGdyb3VwMSwgYWVzKHggPXJlb3JkZXIodHJhY2tfZ2VucmUsIC1NZWFuX1BvcHVsYXJpdHkpLCB5ID0gTWVhbl9Qb3B1bGFyaXR5KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJibHVlIikgKw0KICBsYWJzKHRpdGxlID0gIk1lYW4gUG9wdWxhcml0eSBieSBUcmFjayBHZW5yZSIsDQogICAgICAgeCA9ICJUcmFjayBHZW5yZSIsDQogICAgICAgeSA9ICJNZWFuIFBvcHVsYXJpdHkiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgdmp1c3QgPSAwLjUsc2l6ZSA9IDYpLCAgDQogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLCAgICMgUmVtb3ZlIHZlcnRpY2FsIGdyaWQgbGluZXMNCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihiID0gMTAwKSAgICAgICAgICAgIyBBZGQgYm90dG9tIG1hcmdpbiBmb3IgbGFiZWxzDQogICkNCmBgYA0KVGhlIGdyYXBoIHNob3dzIGEgY2xlYXIgaGllcmFyY2h5IGluIGdlbnJlIHBvcHVsYXJpdHksIHdpdGggdGhlIGhpZ2hlc3QtcmF0ZWQgZ2VucmVzIHJlYWNoaW5nIG5lYXJseSA2MCBvbiB0aGUgcG9wdWxhcml0eSBzY2FsZSB3aGlsZSB0aGUgbG93ZXN0LXJhdGVkIGdlbnJlcyBmYWxsIGJlbG93IDEwLCBkZW1vbnN0cmF0aW5nIHNpZ25pZmljYW50IHZhcmlhdGlvbiBpbiBsaXN0ZW5lciBwcmVmZXJlbmNlcy4NCg0KIyMjIEdyb3VwMjogR3JvdXBpbmcgYnkgR2VucmUgYW5kIEV4cGxpY2l0IENvbnRlbnQNCmBgYHtyfQ0KZ3JvdXAyIDwtIGRhdGEgfD4NCiAgZ3JvdXBfYnkodHJhY2tfZ2VucmUsIGV4cGxpY2l0KSB8Pg0KICBzdW1tYXJpc2UoQ291bnQgPSBuKCksIE1lZGlhbl9EYW5jZWFiaWxpdHkgPSBtZWRpYW4oZGFuY2VhYmlsaXR5LCBuYS5ybSA9IFRSVUUpKQ0KcHJpbnQoZ3JvdXAyKQ0KYGBgDQoNCmBgYHtyfQ0KIyBDcmVhdGUgZmFjZXRlZCBiYXIgY2hhcnQNCmdncGxvdChncm91cDIsIGFlcyh4ID0gcmVvcmRlcih0cmFja19nZW5yZSwgLU1lZGlhbl9EYW5jZWFiaWxpdHkpLCANCiAgICAgICAgICAgICAgICAgICB5ID0gTWVkaWFuX0RhbmNlYWJpbGl0eSwNCiAgICAgICAgICAgICAgICAgICBmaWxsID0gZXhwbGljaXQpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogIGZhY2V0X3dyYXAofmV4cGxpY2l0KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoICJUcnVlIiA9ICJjb3JhbCIpKSArDQogIGxhYnModGl0bGUgPSAiTWVkaWFuIERhbmNlYWJpbGl0eSBieSBHZW5yZSBhbmQgRXhwbGljaXQgQ29udGVudCIsDQogICAgICAgeCA9ICJUcmFjayBHZW5yZSIsDQogICAgICAgeSA9ICJNZWRpYW4gRGFuY2VhYmlsaXR5IiwNCiAgICAgICBmaWxsID0gIkV4cGxpY2l0IikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxLCB2anVzdCA9IDAuNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSA0KSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgDQogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKGIgPSAxMDApIA0KICApDQpgYGANCiMjIyBCeSBncm91cGluZyBhbmQgZ3JhcGgsIHdlIGNhbiBrbm93LQ0KDQpNb3N0IGdlbnJlcyBoYXZlIHNpZ25pZmljYW50bHkgbW9yZSBub24tZXhwbGljaXQgdHJhY2tzIHRoYW4gZXhwbGljaXQgb25lcyAtIGZvciBleGFtcGxlLCBhY291c3RpYyBoYXMgOTQ4IG5vbi1leHBsaWNpdCB2cyBvbmx5IDUyIGV4cGxpY2l0IHRyYWNrcywgYW5kIGFtYmllbnQgaGFzIDk5NSBub24tZXhwbGljaXQgdHJhY2tzLCBzaG93aW5nIGEgY2xlYXIgcHJlZmVyZW5jZSBmb3IgY2xlYW4gY29udGVudCBpbiB0aGVzZSBnZW5yZXMuDQoNCkFsdGVybmF0aXZlIG11c2ljIHNob3dzIHRoZSBoaWdoZXN0IHByb3BvcnRpb24gb2YgZXhwbGljaXQgY29udGVudCAoMTY0IGV4cGxpY2l0IHRyYWNrcyBvdXQgb2YgMTAwMCkgY29tcGFyZWQgdG8gb3RoZXIgZ2VucmVzLCB3aGlsZSBhbWJpZW50IGFuZCBhZnJvYmVhdCBoYXZlIHZlcnkgZmV3IGV4cGxpY2l0IHRyYWNrcyAobGVzcyB0aGFuIDIwIGVhY2gpLg0KDQpEYW5jZWFiaWxpdHkgdmFyaWVzIG5vdGFibHkgYmV0d2VlbiBleHBsaWNpdCBhbmQgbm9uLWV4cGxpY2l0IHRyYWNrcyB3aXRoaW4gdGhlIHNhbWUgZ2VucmUgLSBmb3IgaW5zdGFuY2UsIGFsdGVybmF0aXZlIG11c2ljIHNob3dzIGhpZ2hlciBkYW5jZWFiaWxpdHkgaW4gZXhwbGljaXQgdHJhY2tzICgwLjY2MykgY29tcGFyZWQgdG8gbm9uLWV4cGxpY2l0IG9uZXMgKDAuNTM4KSwgd2hpbGUgYWNvdXN0aWMgbXVzaWMgc2hvd3MgdGhlIG9wcG9zaXRlIHRyZW5kIHdpdGggbm9uLWV4cGxpY2l0IHRyYWNrcyBiZWluZyBtb3JlIGRhbmNlYWJsZSAoMC41NjQgdnMgMC40OTEpLg0KDQojIyMgR3JvdXAgMzogR3JvdXBpbmcgYnkgQmlubmVkIFBvcHVsYXJpdHkgU2NvcmVzDQpgYGB7cn0NCmRhdGEgPC0gZGF0YSB8PiBtdXRhdGUoUG9wdWxhcml0eV9CaW4gPSBjdXQocG9wdWxhcml0eSwgYnJlYWtzID0gNSkpDQpncm91cDMgPC0gZGF0YSB8Pg0KICBncm91cF9ieSh0cmFja19nZW5yZSwgUG9wdWxhcml0eV9CaW4pIHw+DQogIHN1bW1hcmlzZShDb3VudCA9IG4oKSkNCnByaW50KGdyb3VwMykNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZ3JvdXAzLCBhZXMoeCA9IENvdW50LCB5ID0gdHJhY2tfZ2VucmUsIGZpbGwgPSBQb3B1bGFyaXR5X0JpbikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gInN0YWNrIikgKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlJkWWxCdSIpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUG9wdWxhcml0eSBTY29yZXMgQWNyb3NzIE11c2ljIEdlbnJlcyIsDQogICAgICAgeCA9ICJOdW1iZXIgb2YgVHJhY2tzIiwNCiAgICAgICB5ID0gIkdlbnJlIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gNSwgICAgIyBJbmNyZWFzZSB0ZXh0IHNpemUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IG1hcmdpbihyID0gMTApKSwgIyBBZGQgcmlnaHQgbWFyZ2luDQogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ociA9IDgpLCAgICAgICAgICAgICMgQWRkIHJpZ2h0IG1hcmdpbiBmb3IgbGVnZW5kDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksDQogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpIA0KICApDQpgYGANClBvcHVsYXJpdHkgRGlzdHJpYnV0aW9uIGlzIFNrZXdlZDogTW9zdCBnZW5yZXMgc2hvdyBhIGNvbmNlbnRyYXRpb24gb2YgdHJhY2tzIGluIHRoZSBtaWRkbGUgcG9wdWxhcml0eSByYW5nZXMgKDIwLTYwKSwgd2l0aCB2ZXJ5IGZldyB0cmFja3MgcmVhY2hpbmcgdGhlIGhpZ2hlc3QgcG9wdWxhcml0eSBicmFja2V0ICg4MC0xMDApLiBGb3IgZXhhbXBsZSwgYWNvdXN0aWMgaGFzIG9ubHkgMSB0cmFjayBpbiB0aGUgaGlnaGVzdCByYW5nZSBidXQgNTE4IHRyYWNrcyBpbiB0aGUgbWlkZGxlIHJhbmdlICg0MC02MCkuDQoNCkdlbnJlLVNwZWNpZmljIFBhdHRlcm5zOiBEaWZmZXJlbnQgZ2VucmVzIHNob3cgZGlzdGluY3QgcG9wdWxhcml0eSBwYXR0ZXJuczoNCg0KQWNvdXN0aWMgbXVzaWMgaGFzIGEgYmVsbC1zaGFwZWQgZGlzdHJpYnV0aW9uIHdpdGggbW9zdCB0cmFja3MgaW4gdGhlIG1pZGRsZSByYW5nZXMNCkFmcm9iZWF0IHNob3dzIGEgbGVmdC1za2V3ZWQgZGlzdHJpYnV0aW9uIHdpdGggbW9zdCB0cmFja3MgaW4gbG93ZXIgcG9wdWxhcml0eSByYW5nZXMgKDQ4MiB0cmFja3MgaW4gdGhlIGxvd2VzdCBicmFja2V0KQ0KQWx0LXJvY2sgZGVtb25zdHJhdGVzIGEgc2ltaWxhciBwYXR0ZXJuIHRvIGFmcm9iZWF0IHdpdGggaGlnaCBjb3VudHMgaW4gbG93ZXIgcG9wdWxhcml0eSByYW5nZXMNCkV4dHJlbWUgUG9wdWxhcml0eSBpcyBSYXJlOiBBY3Jvc3MgYWxsIGdlbnJlcywgdmVyeSBmZXcgdHJhY2tzIGFjaGlldmUgdGhlIGhpZ2hlc3QgcG9wdWxhcml0eSBicmFja2V0ICg4MC0xMDApLCBzdWdnZXN0aW5nIHRoYXQgcmVhY2hpbmcgdG9wIHBvcHVsYXJpdHkgaXMgZXhjZXB0aW9uYWxseSBjaGFsbGVuZ2luZyByZWdhcmRsZXNzIG9mIGdlbnJlLiBUaGUgbWlkZGxlIHJhbmdlcyAoMjAtNjApIGNvbnRhaW4gdGhlIGJ1bGsgb2YgdHJhY2tzIGZvciBtb3N0IGdlbnJlcy4NCg0KIyMjIFN0ZXAgMiA6IEludmVzdGlnYXRpbmcgQ29tYmluYXRpb25zIG9mIEdlbnJlIGFuZCBFeHBsaWNpdG5lc3MNCmBgYHtyfQ0KY2F0ZWdvcnlfY29tYmluYXRpb25zIDwtIGRhdGEgfD4gY291bnQodHJhY2tfZ2VucmUsIGV4cGxpY2l0KQ0KcHJpbnQoY2F0ZWdvcnlfY29tYmluYXRpb25zKQ0KYGBgDQoNCiMjIyBTdGVwIDMgOiBGaW5kaW5nIGNvbWJpbmF0aW9ucw0KYGBge3J9DQojIEZpbmQgbWlzc2luZyBjb21iaW5hdGlvbnMNCmFsbF9jb21iaW5hdGlvbnMgPC0gZXhwYW5kLmdyaWQodW5pcXVlKGRhdGEkdHJhY2tfZ2VucmUpLCB1bmlxdWUoZGF0YSRleHBsaWNpdCkpDQptaXNzaW5nX2NvbWJpbmF0aW9ucyA8LSBhbnRpX2pvaW4oYWxsX2NvbWJpbmF0aW9ucywgY2F0ZWdvcnlfY29tYmluYXRpb25zLCBieSA9IGMoIlZhcjEiID0gInRyYWNrX2dlbnJlIiwgIlZhcjIiID0iZXhwbGljaXQiKSkNCnByaW50KG1pc3NpbmdfY29tYmluYXRpb25zKQ0KYGBgDQoNCmBgYHtyfQ0KIyBNb3N0IGNvbW1vbiBjb21iaW5hdGlvbnMNCmNvbW1vbl9jb21iaW5hdGlvbnMgPC0gZ3JvdXAzIHw+DQogIGdyb3VwX2J5KHRyYWNrX2dlbnJlLCBQb3B1bGFyaXR5X0JpbikgfD4NCiAgc3VtbWFyaXNlKENvdW50ID0gbigpKSB8Pg0KICBhcnJhbmdlKGRlc2MoQ291bnQpKQ0KDQojIExlYXN0IGNvbW1vbiBjb21iaW5hdGlvbnMNCmxlYXN0X2NvbW1vbl9jb21iaW5hdGlvbnMgPC0gZ3JvdXAzIHw+DQogIGdyb3VwX2J5KHRyYWNrX2dlbnJlLCBQb3B1bGFyaXR5X0JpbikgfD4NCiAgc3VtbWFyaXNlKENvdW50ID0gbigpKSB8Pg0KICBhcnJhbmdlKENvdW50KQ0KDQojIERpc3BsYXkgdGhlIG1vc3QgY29tbW9uIGNvbWJpbmF0aW9ucw0KcHJpbnQoIk1vc3QgY29tbW9uIGNvbWJpbmF0aW9uczoiKQ0KaGVhZChjb21tb25fY29tYmluYXRpb25zLCAxMCkgICMgVmlld3MgdG9wIDEwIG1vc3QgY29tbW9uIGNvbWJpbmF0aW9ucw0KDQojIERpc3BsYXkgdGhlIGxlYXN0IGNvbW1vbiBjb21iaW5hdGlvbnMNCnByaW50KCJMZWFzdCBjb21tb24gY29tYmluYXRpb25zOiIpDQpoZWFkKGxlYXN0X2NvbW1vbl9jb21iaW5hdGlvbnMsIDEwKSAgIyBWaWV3cyB0b3AgMTAgbGVhc3QgY29tbW9uIGNvbWJpbmF0aW9ucw0KDQpgYGANCkZyb20gdGhlIGxlYXN0IGNvbW1vbiBhbmQgbW9zdCBjb21tb24gY29tYmluYXRpb25zLCB3ZSBjYW4gbm90aWNlLQ0KMS4gTXVzaWMgZ2VucmVzIGxpa2UgImFjb3VzdGljLCIgImFmcm9iZWF0LCIgYW5kICJhbHQtcm9jayIgYXJlIHNwcmVhZCBhY3Jvc3MgbXVsdGlwbGUgcG9wdWxhcml0eSBiaW5zLiAgDQoyLiBUaGUgY291bnQgZGlzdHJpYnV0aW9uIGlzIHJlbGF0aXZlbHkgZXZlbiBhY3Jvc3MgZGlmZmVyZW50IHBvcHVsYXJpdHkgYmlucy4gIA0KMy4gU29tZSBnZW5yZXMgbWF5IHBlcmZvcm0gYmV0dGVyIGluIGhpZ2hlciBwb3B1bGFyaXR5IHJhbmdlcywgbGlrZSAiYWx0LXJvY2suIiAgDQo0LiBDZXJ0YWluIGdlbnJlcywgbGlrZSAiYWNvdXN0aWMiIGFuZCAiYWZyb2JlYXQsIiBjb3VsZCBhcHBlYWwgdG8gbmljaGUgYXVkaWVuY2VzLg0KDQoNCiMjIyBTdW1tYXJ5Og0KR3JvdXBpbmcgYnkgZGlmZmVyZW50IGNhdGVnb3JpY2FsIHZhcmlhYmxlcyByZXZlYWxzIHBhdHRlcm5zIGluIG9jY3VycmVuY2UgcHJvYmFiaWxpdGllcy4NClRoZSByYXJlc3QgZ3JvdXBzIGNhbiBiZSBpZGVudGlmaWVkIGFuZCBhbmFseXplZCBmb3IgYW5vbWFsaWVzLg0KTWlzc2luZyBnZW5yZS1leHBsaWNpdG5lc3MgY29tYmluYXRpb25zIGhpbnQgYXQgc3RydWN0dXJlZCBnYXBzIGluIHRoZSBkYXRhc2V0Lg0KVmlzdWFsaXphdGlvbnMgZW5oYW5jZSBpbnRlcnByZXRhYmlsaXR5IGFuZCBoeXBvdGhlc2lzIHRlc3RpbmcuDQoNCiMjIyBGdXJ0aGVyIFF1ZXN0aW9ucyB0byBJbnZlc3RpZ2F0ZS0NCldoYXQgZmFjdG9ycyBjb250cmlidXRlIHRvIHRoZSByYXJpdHkgb2YgaGlnaC1wb3B1bGFyaXR5IHRyYWNrcyBhY3Jvc3MgYWxsIGdlbnJlcz8NCg0KSXMgdGhlcmUgYSB0ZW1wb3JhbCBjb21wb25lbnQgYWZmZWN0aW5nIHBvcHVsYXJpdHkgZGlzdHJpYnV0aW9ucz8NCg0KSG93IGRvIG90aGVyIHRyYWNrIGZlYXR1cmVzIChkYW5jZWFiaWxpdHksIGVuZXJneSkgY29ycmVsYXRlIHdpdGggdGhlc2UgcG9wdWxhcml0eSBwYXR0ZXJucz8NCg0KQXJlIHRoZXJlIHJlZ2lvbmFsIG9yIGN1bHR1cmFsIGZhY3RvcnMgaW5mbHVlbmNpbmcgdGhlc2UgZGlzdHJpYnV0aW9ucz8NCg==