library(dplyr)
library(readr)
library(tidyverse)
library(ggplot2)
library(conflicted)
Selecting Data
#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)
Making Random Subsamples
# Determine sample size (50% of data) from 9000 rows
sample_size <- min(9000, round(nrow(data) * 0.5))
# Create 5 random samples with replacement
df_1 <- data |> sample_n(sample_size, replace = TRUE)
df_2 <- data |> sample_n(sample_size, replace = TRUE)
df_3 <- data |> sample_n(sample_size, replace = TRUE)
df_4 <- data |> sample_n(sample_size, replace = TRUE)
df_5 <- data |> sample_n(sample_size, replace = TRUE)
# Verify
dim(df_1); dim(df_2); dim(df_3); dim(df_4); dim(df_5)
[1] 4500 21
[1] 4500 21
[1] 4500 21
[1] 4500 21
[1] 4500 21
Summarising df_1
df_1 |>
group_by(track_genre) |>
summarise(
count = n(),
avg_popularity = mean(popularity, na.rm = TRUE),
avg_danceability = mean(danceability, na.rm = TRUE),
avg_energy = mean(energy, na.rm = TRUE),
avg_acousticness = mean(acousticness, na.rm = TRUE),
mode_key = names(sort(table(key), decreasing = TRUE))[1]
) |>
arrange(desc(avg_popularity))
Summarisng df_2
df_2 |>
group_by(track_genre) |>
summarise(
count = n(),
avg_popularity = mean(popularity, na.rm = TRUE),
avg_danceability = mean(danceability, na.rm = TRUE),
avg_energy = mean(energy, na.rm = TRUE),
avg_acousticness = mean(acousticness, na.rm = TRUE),
mode_key = names(sort(table(key), decreasing = TRUE)[1])
) |>
arrange(desc(avg_popularity))
Summarising df_3
df_3 |>
group_by(track_genre) |>
summarise(
count = n(),
avg_popularity = mean(popularity, na.rm = TRUE),
avg_danceability = mean(danceability, na.rm = TRUE),
avg_energy = mean(energy, na.rm = TRUE),
avg_acousticness = mean(acousticness, na.rm = TRUE),
mode_key = names(sort(table(key), decreasing = TRUE)[1])
) |>
arrange(desc(avg_popularity))
Summarising df_4
df_4 |>
group_by(track_genre) |>
summarise(
count = n(),
avg_popularity = mean(popularity, na.rm = TRUE),
avg_danceability = mean(danceability, na.rm = TRUE),
avg_energy = mean(energy, na.rm = TRUE),
avg_acousticness = mean(acousticness, na.rm = TRUE),
mode_key = names(sort(table(key), decreasing = TRUE)[1])
) |>
arrange(desc(avg_popularity))
Summarising df_5
df_5 |>
group_by(track_genre) |>
summarise(
count = n(),
avg_popularity = mean(popularity, na.rm = TRUE),
avg_danceability = mean(danceability, na.rm = TRUE),
avg_energy = mean(energy, na.rm = TRUE),
avg_acousticness = mean(acousticness, na.rm = TRUE),
mode_key = names(sort(table(key), decreasing = TRUE)[1])
) |>
arrange(desc(avg_popularity))
Summarising all dfs as a list using ‘’lapply’
# Summarising using lapply
#lapply(list(df_1, df_2, df_3, df_4, df_5), summary)
dfs <- list(df_1, df_2, df_3, df_4, df_5)
# Apply summarization to each dataframe in the list
summarized_dfs <- lapply(dfs, function(df) {
df |>
group_by(track_genre) |>
summarise(
count = n(),
avg_popularity = mean(popularity, na.rm = TRUE),
avg_danceability = mean(danceability, na.rm = TRUE),
avg_energy = mean(energy, na.rm = TRUE),
avg_acousticness = mean(acousticness, na.rm = TRUE),
mode_key = names(sort(table(key), decreasing = TRUE)[1])
) |>
arrange(desc(avg_popularity))
})
# To view the summarized dataframes
summarized_dfs
[[1]]
[[2]]
[[3]]
[[4]]
[[5]]
NA
1. How different are they?
For comparing random sub-samples of tracks,
Popularity: Tracks with higher popularity
(popularity score of 80 or more) are having higher
energy, danceability, and
loudness values. In contrast, less popular tracks are
having lower values in these features.
Genre-Based Differences: Acoustic tracks have
lower energy and danceability, with
higher acousticness and
instrumentalness compared to electronic or pop
genres.
2. What would you have called an anomaly in one sub-sample
that you wouldn’t in another?
For this dataset, anomalies vary across sub-samples like:
A track with a popularity score of 50 or below is an anomaly in a
sub-sample of tracks with popularity mostly above 70. Conversely, in a
sub-sample with mostly low-popularity tracks, a track with popularity
over 70 is unusual.
A track with exceptionally low energy (e.g., below 0.2) is an
anomaly in a sub-sample focused on energetic genres like pop or EDM, but
normal in a sub-sample of classical or acoustic music.
In Duration (ms): A track that is significantly longer (e.g.,
over 7 minutes) is an anomaly in a typical 3-4 minute pop/rock
sub-sample but not unusual in a classical or ambient
sub-sample.
3. Are there aspects of the data that are consistent among
all sub-samples?
- Common Features Across Sub-samples:
- From the dfs, Tempo is fairly consistent across
most tracks, though certain genres like electronic or dance are having
higher tempos. In all sub-samples, there is likely to be a wide range of
valence (mood), danceability, and
loudness, reflecting the diversity in music
styles.
- Key and mode values (musical key
and scale) are relatively consistent within certain genres (e.g., pop
tracks will likely have more common modes and keys).
- Time signature staying the same (mostly 4/4 time)
across a large number of tracks, though genres like jazz or classical
might feature a broader range of signatures.
Conclusion
Analysing subsample summaries on the spotify dataset by grouping data
based on probability. We got to know the key findings of the spotify
dataset using subsamples and the summarization operation grouped the
data by track_genre and calculated several summary statistics, including
the count of records, average values for features like popularity,
danceability, energy, and acousticness, as well as the most frequent key
for each genre.
In the future, this experience suggests that it’s important to: 1.
Examine sampling methods carefully to ensure that both
categorical and numeric variables are appropriately represented. 2.
Use stratified sampling or ensure a balanced
representation of categories if we’re working with imbalanced datasets
or when certain groups are crucial for the analysis. 3. Consider
the context of missing variables when interpreting results—if a
certain category is underrepresented, it might skew results or lead to
faulty conclusions about the relationships within the data.
Monte Carlo Simulation
set.seed(4)
n_simulations <- 1000
sample_size <- 4500
mc_results <- replicate(n_simulations, {
subsample <- music_data |> sample_n(sample_size, replace = TRUE)
mean(subsample$Track_Length, na.rm = TRUE)
})
# Plotting the histogram
hist(
mc_results,
breaks = 30,
col = "skyblue",
border = "white",
main = "Monte Carlo Simulation: Distribution of Average Track Length",
xlab = "Average Track Length (seconds)",
ylab = "Frequency"
)

Explnation:
The histogram of the simulation results shows a roughly normal
distribution centered around an average track length of approximately
268 seconds. The spread (standard deviation) of the average track
lengths is relatively small, indicating consistency in the sample
averages.
Next Steps:
I could expand the simulation to track how often different categories
appear and explore if some categories are more prone to being sampled
over others. Validate whether the assumption of normality holds for the
distribution of average track lengths or if alternative distributions
better fit the data.
LS0tDQp0aXRsZTogIlJfRGF0YURpdmU0Ig0KYXV0aG9yOiAiRFNKIg0KZGF0ZTogIjIwMjUtMDItMDkiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGNvbmZsaWN0ZWQpDQpgYGANCiMjIyBTZWxlY3RpbmcgRGF0YQ0KYGBge3J9DQojUmVhZGluZyB0aGUgZGF0YSBzZXQgYW5kIHByaW50aW5nIGZpcnN0IDVyb3dzDQpkYXRhIDwtIHJlYWQuY3N2KCJkYXRhc2V0LmNzdiIpDQoNCmNvbmZsaWN0ZWQ6OmNvbmZsaWN0c19wcmVmZXIoZHBseXI6OmZpbHRlcikNCg0KIyBGaWx0ZXJpbmcgZGF0YXNldCB3aGVyZSBleHBsaWNpdCBpcyAiVHJ1ZSIgYW5kIHRha2luZyBhIHNhbXBsZSBvZiA5LDAwMCByb3dzDQpzYW1wbGVfZGF0YSA8LSBkYXRhIHw+IGZpbHRlcihleHBsaWNpdCA9PSAiVHJ1ZSIpIHw+IHNhbXBsZV9uKDkwMDApDQpkYXRhIDwtIHNhbXBsZV9kYXRhDQpucm93KGRhdGEpDQoNCiMgRGlzcGxheSBmaXJzdCBmZXcgcm93cw0KaGVhZChkYXRhKQ0KYGBgDQojIyMgTWFraW5nIFJhbmRvbSBTdWJzYW1wbGVzDQpgYGB7cn0NCiMgRGV0ZXJtaW5lIHNhbXBsZSBzaXplICg1MCUgb2YgZGF0YSkgZnJvbSA5MDAwIHJvd3MNCnNhbXBsZV9zaXplIDwtIG1pbig5MDAwLCByb3VuZChucm93KGRhdGEpICogMC41KSkNCg0KIyBDcmVhdGUgNSByYW5kb20gc2FtcGxlcyB3aXRoIHJlcGxhY2VtZW50DQpkZl8xIDwtIGRhdGEgfD4gc2FtcGxlX24oc2FtcGxlX3NpemUsIHJlcGxhY2UgPSBUUlVFKQ0KZGZfMiA8LSBkYXRhIHw+IHNhbXBsZV9uKHNhbXBsZV9zaXplLCByZXBsYWNlID0gVFJVRSkNCmRmXzMgPC0gZGF0YSB8PiBzYW1wbGVfbihzYW1wbGVfc2l6ZSwgcmVwbGFjZSA9IFRSVUUpDQpkZl80IDwtIGRhdGEgfD4gc2FtcGxlX24oc2FtcGxlX3NpemUsIHJlcGxhY2UgPSBUUlVFKQ0KZGZfNSA8LSBkYXRhIHw+IHNhbXBsZV9uKHNhbXBsZV9zaXplLCByZXBsYWNlID0gVFJVRSkNCg0KIyBWZXJpZnkNCmRpbShkZl8xKTsgZGltKGRmXzIpOyBkaW0oZGZfMyk7IGRpbShkZl80KTsgZGltKGRmXzUpDQpgYGANCiMjIyBTdW1tYXJpc2luZyBkZl8xDQpgYGB7cn0NCmRmXzEgfD4gDQogIGdyb3VwX2J5KHRyYWNrX2dlbnJlKSB8PiANCiAgc3VtbWFyaXNlKA0KICAgIGNvdW50ID0gbigpLA0KICAgIGF2Z19wb3B1bGFyaXR5ID0gbWVhbihwb3B1bGFyaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgIGF2Z19kYW5jZWFiaWxpdHkgPSBtZWFuKGRhbmNlYWJpbGl0eSwgbmEucm0gPSBUUlVFKSwNCiAgICBhdmdfZW5lcmd5ID0gbWVhbihlbmVyZ3ksIG5hLnJtID0gVFJVRSksDQogICAgYXZnX2Fjb3VzdGljbmVzcyA9IG1lYW4oYWNvdXN0aWNuZXNzLCBuYS5ybSA9IFRSVUUpLA0KICAgIG1vZGVfa2V5ID0gbmFtZXMoc29ydCh0YWJsZShrZXkpLCBkZWNyZWFzaW5nID0gVFJVRSkpWzFdDQogICkgfD4gDQogIGFycmFuZ2UoZGVzYyhhdmdfcG9wdWxhcml0eSkpDQpgYGANCiMjIyBTdW1tYXJpc25nIGRmXzINCmBgYHtyfQ0KZGZfMiB8PiANCiAgZ3JvdXBfYnkodHJhY2tfZ2VucmUpIHw+IA0KICBzdW1tYXJpc2UoDQogICAgY291bnQgPSBuKCksDQogICAgYXZnX3BvcHVsYXJpdHkgPSBtZWFuKHBvcHVsYXJpdHksIG5hLnJtID0gVFJVRSksDQogICAgYXZnX2RhbmNlYWJpbGl0eSA9IG1lYW4oZGFuY2VhYmlsaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgIGF2Z19lbmVyZ3kgPSBtZWFuKGVuZXJneSwgbmEucm0gPSBUUlVFKSwNCiAgICBhdmdfYWNvdXN0aWNuZXNzID0gbWVhbihhY291c3RpY25lc3MsIG5hLnJtID0gVFJVRSksDQogICAgbW9kZV9rZXkgPSBuYW1lcyhzb3J0KHRhYmxlKGtleSksIGRlY3JlYXNpbmcgPSBUUlVFKVsxXSkNCiAgKSB8PiANCiAgYXJyYW5nZShkZXNjKGF2Z19wb3B1bGFyaXR5KSkNCmBgYA0KIyMjIFN1bW1hcmlzaW5nIGRmXzMNCmBgYHtyfQ0KZGZfMyB8PiANCiAgZ3JvdXBfYnkodHJhY2tfZ2VucmUpIHw+IA0KICBzdW1tYXJpc2UoDQogICAgY291bnQgPSBuKCksDQogICAgYXZnX3BvcHVsYXJpdHkgPSBtZWFuKHBvcHVsYXJpdHksIG5hLnJtID0gVFJVRSksDQogICAgYXZnX2RhbmNlYWJpbGl0eSA9IG1lYW4oZGFuY2VhYmlsaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgIGF2Z19lbmVyZ3kgPSBtZWFuKGVuZXJneSwgbmEucm0gPSBUUlVFKSwNCiAgICBhdmdfYWNvdXN0aWNuZXNzID0gbWVhbihhY291c3RpY25lc3MsIG5hLnJtID0gVFJVRSksDQogICAgbW9kZV9rZXkgPSBuYW1lcyhzb3J0KHRhYmxlKGtleSksIGRlY3JlYXNpbmcgPSBUUlVFKVsxXSkNCiAgKSB8PiANCiAgYXJyYW5nZShkZXNjKGF2Z19wb3B1bGFyaXR5KSkNCmBgYA0KIyMjIFN1bW1hcmlzaW5nIGRmXzQNCmBgYHtyfQ0KZGZfNCB8PiANCiAgZ3JvdXBfYnkodHJhY2tfZ2VucmUpIHw+IA0KICBzdW1tYXJpc2UoDQogICAgY291bnQgPSBuKCksDQogICAgYXZnX3BvcHVsYXJpdHkgPSBtZWFuKHBvcHVsYXJpdHksIG5hLnJtID0gVFJVRSksDQogICAgYXZnX2RhbmNlYWJpbGl0eSA9IG1lYW4oZGFuY2VhYmlsaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgIGF2Z19lbmVyZ3kgPSBtZWFuKGVuZXJneSwgbmEucm0gPSBUUlVFKSwNCiAgICBhdmdfYWNvdXN0aWNuZXNzID0gbWVhbihhY291c3RpY25lc3MsIG5hLnJtID0gVFJVRSksDQogICAgbW9kZV9rZXkgPSBuYW1lcyhzb3J0KHRhYmxlKGtleSksIGRlY3JlYXNpbmcgPSBUUlVFKVsxXSkNCiAgKSB8PiANCiAgYXJyYW5nZShkZXNjKGF2Z19wb3B1bGFyaXR5KSkNCmBgYA0KIyMjIFN1bW1hcmlzaW5nIGRmXzUNCmBgYHtyfQ0KZGZfNSB8PiANCiAgZ3JvdXBfYnkodHJhY2tfZ2VucmUpIHw+IA0KICBzdW1tYXJpc2UoDQogICAgY291bnQgPSBuKCksDQogICAgYXZnX3BvcHVsYXJpdHkgPSBtZWFuKHBvcHVsYXJpdHksIG5hLnJtID0gVFJVRSksDQogICAgYXZnX2RhbmNlYWJpbGl0eSA9IG1lYW4oZGFuY2VhYmlsaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgIGF2Z19lbmVyZ3kgPSBtZWFuKGVuZXJneSwgbmEucm0gPSBUUlVFKSwNCiAgICBhdmdfYWNvdXN0aWNuZXNzID0gbWVhbihhY291c3RpY25lc3MsIG5hLnJtID0gVFJVRSksDQogICAgbW9kZV9rZXkgPSBuYW1lcyhzb3J0KHRhYmxlKGtleSksIGRlY3JlYXNpbmcgPSBUUlVFKVsxXSkNCiAgKSB8PiANCiAgYXJyYW5nZShkZXNjKGF2Z19wb3B1bGFyaXR5KSkNCmBgYA0KIyMjIFN1bW1hcmlzaW5nIGFsbCBkZnMgYXMgYSBsaXN0IHVzaW5nICcnbGFwcGx5Jw0KYGBge3J9DQojIFN1bW1hcmlzaW5nIHVzaW5nIGxhcHBseQ0KI2xhcHBseShsaXN0KGRmXzEsIGRmXzIsIGRmXzMsIGRmXzQsIGRmXzUpLCBzdW1tYXJ5KQ0KDQpkZnMgPC0gbGlzdChkZl8xLCBkZl8yLCBkZl8zLCBkZl80LCBkZl81KQ0KDQojIEFwcGx5IHN1bW1hcml6YXRpb24gdG8gZWFjaCBkYXRhZnJhbWUgaW4gdGhlIGxpc3QNCnN1bW1hcml6ZWRfZGZzIDwtIGxhcHBseShkZnMsIGZ1bmN0aW9uKGRmKSB7DQogIGRmIHw+IA0KICAgIGdyb3VwX2J5KHRyYWNrX2dlbnJlKSB8PiANCiAgICBzdW1tYXJpc2UoDQogICAgICBjb3VudCA9IG4oKSwNCiAgICAgIGF2Z19wb3B1bGFyaXR5ID0gbWVhbihwb3B1bGFyaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgYXZnX2RhbmNlYWJpbGl0eSA9IG1lYW4oZGFuY2VhYmlsaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgYXZnX2VuZXJneSA9IG1lYW4oZW5lcmd5LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgYXZnX2Fjb3VzdGljbmVzcyA9IG1lYW4oYWNvdXN0aWNuZXNzLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgbW9kZV9rZXkgPSBuYW1lcyhzb3J0KHRhYmxlKGtleSksIGRlY3JlYXNpbmcgPSBUUlVFKVsxXSkNCiAgICApIHw+IA0KICAgIGFycmFuZ2UoZGVzYyhhdmdfcG9wdWxhcml0eSkpDQp9KQ0KDQojIFRvIHZpZXcgdGhlIHN1bW1hcml6ZWQgZGF0YWZyYW1lcw0Kc3VtbWFyaXplZF9kZnMNCmBgYA0KDQojIyMgMS4gKipIb3cgZGlmZmVyZW50IGFyZSB0aGV5PyoqDQogICBGb3IgY29tcGFyaW5nICoqcmFuZG9tIHN1Yi1zYW1wbGVzKiogb2YgdHJhY2tzLA0KICAgDQogICAtICoqUG9wdWxhcml0eToqKiBUcmFja3Mgd2l0aCBoaWdoZXIgcG9wdWxhcml0eSAocG9wdWxhcml0eSBzY29yZSBvZiA4MCBvciBtb3JlKSBhcmUgaGF2aW5nIGhpZ2hlciAqKmVuZXJneSoqLCAqKmRhbmNlYWJpbGl0eSoqLCBhbmQgKipsb3VkbmVzcyoqIHZhbHVlcy4gSW4gY29udHJhc3QsIGxlc3MgcG9wdWxhciB0cmFja3MgYXJlIGhhdmluZyBsb3dlciB2YWx1ZXMgaW4gdGhlc2UgZmVhdHVyZXMuDQogICANCiAgIC0gKipHZW5yZS1CYXNlZCBEaWZmZXJlbmNlczoqKiBBY291c3RpYyB0cmFja3MgaGF2ZSBsb3dlciAqKmVuZXJneSoqIGFuZCAqKmRhbmNlYWJpbGl0eSoqLCB3aXRoIGhpZ2hlciAqKmFjb3VzdGljbmVzcyoqIGFuZCAqKmluc3RydW1lbnRhbG5lc3MqKiBjb21wYXJlZCB0byBlbGVjdHJvbmljIG9yIHBvcCBnZW5yZXMuDQogICANCg0KIyMjIDIuICoqV2hhdCB3b3VsZCB5b3UgaGF2ZSBjYWxsZWQgYW4gYW5vbWFseSBpbiBvbmUgc3ViLXNhbXBsZSB0aGF0IHlvdSB3b3VsZG4ndCBpbiBhbm90aGVyPyoqDQogICBGb3IgdGhpcyBkYXRhc2V0LCBhbm9tYWxpZXMgdmFyeSBhY3Jvc3Mgc3ViLXNhbXBsZXMgbGlrZToNCiAgIA0KICAgLSBBIHRyYWNrIHdpdGggYSBwb3B1bGFyaXR5IHNjb3JlIG9mIDUwIG9yIGJlbG93IGlzIGFuIGFub21hbHkgaW4gYSBzdWItc2FtcGxlIG9mIHRyYWNrcyB3aXRoIHBvcHVsYXJpdHkgbW9zdGx5IGFib3ZlIDcwLiBDb252ZXJzZWx5LCBpbiBhIHN1Yi1zYW1wbGUgd2l0aCBtb3N0bHkgbG93LXBvcHVsYXJpdHkgdHJhY2tzLCBhIHRyYWNrIHdpdGggcG9wdWxhcml0eSBvdmVyIDcwIGlzIHVudXN1YWwuDQogICANCiAgIC0gQSB0cmFjayB3aXRoIGV4Y2VwdGlvbmFsbHkgbG93IGVuZXJneSAoZS5nLiwgYmVsb3cgMC4yKSBpcyBhbiBhbm9tYWx5IGluIGEgc3ViLXNhbXBsZSBmb2N1c2VkIG9uIGVuZXJnZXRpYyBnZW5yZXMgbGlrZSBwb3Agb3IgRURNLCBidXQgbm9ybWFsIGluIGEgc3ViLXNhbXBsZSBvZiBjbGFzc2ljYWwgb3IgYWNvdXN0aWMgbXVzaWMuDQogICANCiAgIC0gSW4gRHVyYXRpb24gKG1zKTogQSB0cmFjayB0aGF0IGlzIHNpZ25pZmljYW50bHkgbG9uZ2VyIChlLmcuLCBvdmVyIDcgbWludXRlcykgaXMgYW4gYW5vbWFseSBpbiBhIHR5cGljYWwgMy00IG1pbnV0ZSBwb3Avcm9jayBzdWItc2FtcGxlIGJ1dCBub3QgdW51c3VhbCBpbiBhIGNsYXNzaWNhbCBvciBhbWJpZW50IHN1Yi1zYW1wbGUuDQoNCiMjIyAzLiAqKkFyZSB0aGVyZSBhc3BlY3RzIG9mIHRoZSBkYXRhIHRoYXQgYXJlIGNvbnNpc3RlbnQgYW1vbmcgYWxsIHN1Yi1zYW1wbGVzPyoqDQogICAtICoqQ29tbW9uIEZlYXR1cmVzIEFjcm9zcyBTdWItc2FtcGxlczoqKg0KICAgICAtIEZyb20gdGhlIGRmcywgKipUZW1wbyoqIGlzIGZhaXJseSBjb25zaXN0ZW50IGFjcm9zcyBtb3N0IHRyYWNrcywgdGhvdWdoIGNlcnRhaW4gZ2VucmVzIGxpa2UgZWxlY3Ryb25pYyBvciBkYW5jZSBhcmUgaGF2aW5nIGhpZ2hlciB0ZW1wb3MuIEluIGFsbCBzdWItc2FtcGxlcywgdGhlcmUgaXMgbGlrZWx5IHRvIGJlIGEgd2lkZSByYW5nZSBvZiAqKnZhbGVuY2UqKiAobW9vZCksICoqZGFuY2VhYmlsaXR5KiosIGFuZCAqKmxvdWRuZXNzKiosIHJlZmxlY3RpbmcgdGhlIGRpdmVyc2l0eSBpbiBtdXNpYyBzdHlsZXMuDQogICAgIC0gKipLZXkqKiBhbmQgKiptb2RlKiogdmFsdWVzIChtdXNpY2FsIGtleSBhbmQgc2NhbGUpIGFyZSByZWxhdGl2ZWx5IGNvbnNpc3RlbnQgd2l0aGluIGNlcnRhaW4gZ2VucmVzIChlLmcuLCBwb3AgdHJhY2tzIHdpbGwgbGlrZWx5IGhhdmUgbW9yZSBjb21tb24gbW9kZXMgYW5kIGtleXMpLg0KICAgICAtICoqVGltZSBzaWduYXR1cmUqKiBzdGF5aW5nIHRoZSBzYW1lIChtb3N0bHkgNC80IHRpbWUpIGFjcm9zcyBhIGxhcmdlIG51bWJlciBvZiB0cmFja3MsIHRob3VnaCBnZW5yZXMgbGlrZSBqYXp6IG9yIGNsYXNzaWNhbCBtaWdodCBmZWF0dXJlIGEgYnJvYWRlciByYW5nZSBvZiBzaWduYXR1cmVzLg0KICAgICANCiMjIyBDb25jbHVzaW9uDQpBbmFseXNpbmcgc3Vic2FtcGxlIHN1bW1hcmllcyBvbiB0aGUgc3BvdGlmeSBkYXRhc2V0IGJ5IGdyb3VwaW5nIGRhdGEgYmFzZWQgb24gcHJvYmFiaWxpdHkuIFdlIGdvdCB0byBrbm93IHRoZSBrZXkgZmluZGluZ3Mgb2YgdGhlIHNwb3RpZnkgZGF0YXNldCB1c2luZyBzdWJzYW1wbGVzIGFuZCB0aGUgc3VtbWFyaXphdGlvbiBvcGVyYXRpb24gZ3JvdXBlZCB0aGUgZGF0YSBieSB0cmFja19nZW5yZSBhbmQgY2FsY3VsYXRlZCBzZXZlcmFsIHN1bW1hcnkgc3RhdGlzdGljcywgaW5jbHVkaW5nIHRoZSBjb3VudCBvZiByZWNvcmRzLCBhdmVyYWdlIHZhbHVlcyBmb3IgZmVhdHVyZXMgbGlrZSBwb3B1bGFyaXR5LCBkYW5jZWFiaWxpdHksIGVuZXJneSwgYW5kIGFjb3VzdGljbmVzcywgYXMgd2VsbCBhcyB0aGUgbW9zdCBmcmVxdWVudCBrZXkgZm9yIGVhY2ggZ2VucmUuDQoNCkluIHRoZSBmdXR1cmUsIHRoaXMgZXhwZXJpZW5jZSBzdWdnZXN0cyB0aGF0IGl0J3MgaW1wb3J0YW50IHRvOg0KMS4gKipFeGFtaW5lIHNhbXBsaW5nIG1ldGhvZHMqKiBjYXJlZnVsbHkgdG8gZW5zdXJlIHRoYXQgYm90aCBjYXRlZ29yaWNhbCBhbmQgbnVtZXJpYyB2YXJpYWJsZXMgYXJlIGFwcHJvcHJpYXRlbHkgcmVwcmVzZW50ZWQuDQoyLiAqKlVzZSBzdHJhdGlmaWVkIHNhbXBsaW5nKiogb3IgZW5zdXJlIGEgYmFsYW5jZWQgcmVwcmVzZW50YXRpb24gb2YgY2F0ZWdvcmllcyBpZiB3ZSdyZSB3b3JraW5nIHdpdGggaW1iYWxhbmNlZCBkYXRhc2V0cyBvciB3aGVuIGNlcnRhaW4gZ3JvdXBzIGFyZSBjcnVjaWFsIGZvciB0aGUgYW5hbHlzaXMuDQozLiAqKkNvbnNpZGVyIHRoZSBjb250ZXh0IG9mIG1pc3NpbmcgdmFyaWFibGVzKiogd2hlbiBpbnRlcnByZXRpbmcgcmVzdWx0c+KAlGlmIGEgY2VydGFpbiBjYXRlZ29yeSBpcyB1bmRlcnJlcHJlc2VudGVkLCBpdCBtaWdodCBza2V3IHJlc3VsdHMgb3IgbGVhZCB0byBmYXVsdHkgY29uY2x1c2lvbnMgYWJvdXQgdGhlIHJlbGF0aW9uc2hpcHMgd2l0aGluIHRoZSBkYXRhLg0KDQogICAgIA0KIyMjIE1vbnRlIENhcmxvIFNpbXVsYXRpb24gDQpgYGB7cn0NCnNldC5zZWVkKDQpDQpuX3NpbXVsYXRpb25zIDwtIDEwMDANCnNhbXBsZV9zaXplIDwtIDQ1MDAgIA0KbWNfcmVzdWx0cyA8LSByZXBsaWNhdGUobl9zaW11bGF0aW9ucywgeyAgDQogIHN1YnNhbXBsZSA8LSBtdXNpY19kYXRhIHw+IHNhbXBsZV9uKHNhbXBsZV9zaXplLCByZXBsYWNlID0gVFJVRSkgIA0KICBtZWFuKHN1YnNhbXBsZSRUcmFja19MZW5ndGgsIG5hLnJtID0gVFJVRSkgDQp9KSAgDQoNCiMgUGxvdHRpbmcgdGhlIGhpc3RvZ3JhbQ0KaGlzdCggIA0KICBtY19yZXN1bHRzLCAgDQogIGJyZWFrcyA9IDMwLCAgDQogIGNvbCA9ICJza3libHVlIiwgIA0KICBib3JkZXIgPSAid2hpdGUiLCAgDQogIG1haW4gPSAiTW9udGUgQ2FybG8gU2ltdWxhdGlvbjogRGlzdHJpYnV0aW9uIG9mIEF2ZXJhZ2UgVHJhY2sgTGVuZ3RoIiwgIA0KICB4bGFiID0gIkF2ZXJhZ2UgVHJhY2sgTGVuZ3RoIChzZWNvbmRzKSIsICANCiAgeWxhYiA9ICJGcmVxdWVuY3kiICANCikNCmBgYA0KDQojIyMgRXhwbG5hdGlvbjoNCg0KVGhlIGhpc3RvZ3JhbSBvZiB0aGUgc2ltdWxhdGlvbiByZXN1bHRzIHNob3dzIGEgcm91Z2hseSBub3JtYWwgZGlzdHJpYnV0aW9uIGNlbnRlcmVkIGFyb3VuZCBhbiBhdmVyYWdlIHRyYWNrIGxlbmd0aCBvZiBhcHByb3hpbWF0ZWx5IDI2OCBzZWNvbmRzLiBUaGUgc3ByZWFkIChzdGFuZGFyZCBkZXZpYXRpb24pIG9mIHRoZSBhdmVyYWdlIHRyYWNrIGxlbmd0aHMgaXMgcmVsYXRpdmVseSBzbWFsbCwgaW5kaWNhdGluZyBjb25zaXN0ZW5jeSBpbiB0aGUgc2FtcGxlIGF2ZXJhZ2VzLg0KDQojIyMgTmV4dCBTdGVwczoNCg0KSSBjb3VsZCBleHBhbmQgdGhlIHNpbXVsYXRpb24gdG8gdHJhY2sgaG93IG9mdGVuIGRpZmZlcmVudCBjYXRlZ29yaWVzIGFwcGVhciBhbmQgZXhwbG9yZSBpZiBzb21lIGNhdGVnb3JpZXMgYXJlIG1vcmUgcHJvbmUgdG8gYmVpbmcgc2FtcGxlZCBvdmVyIG90aGVycy4NClZhbGlkYXRlIHdoZXRoZXIgdGhlIGFzc3VtcHRpb24gb2Ygbm9ybWFsaXR5IGhvbGRzIGZvciB0aGUgZGlzdHJpYnV0aW9uIG9mIGF2ZXJhZ2UgdHJhY2sgbGVuZ3RocyBvciBpZiBhbHRlcm5hdGl2ZSBkaXN0cmlidXRpb25zIGJldHRlciBmaXQgdGhlIGRhdGEu