library(ggplot2)
library(dplyr)
Warning: package ‘dplyr’ was built under R version 4.4.3
Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
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
✔ readr     2.1.5     ── 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(tsibble)
Registered S3 method overwritten by 'tsibble':
  method               from 
  as_tibble.grouped_df dplyr

Attaching package: ‘tsibble’

The following object is masked from ‘package:lubridate’:

    interval

The following objects are masked from ‘package:base’:

    intersect, setdiff, union
library(lubridate)
library(ggrepel)
library(xts)
Loading required package: zoo

Attaching package: ‘zoo’

The following object is masked from ‘package:tsibble’:

    index

The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric


######################### Warning from 'xts' package ##########################
#                                                                             #
# The dplyr lag() function breaks how base R's lag() function is supposed to  #
# work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or       #
# source() into this session won't work correctly.                            #
#                                                                             #
# Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
# conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop           #
# dplyr from breaking base R's lag() function.                                #
#                                                                             #
# Code in packages is not affected. It's protected by R's namespace mechanism #
# Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning.  #
#                                                                             #
###############################################################################

Attaching package: ‘xts’

The following objects are masked from ‘package:dplyr’:

    first, last
# Install the pageviews package
install.packages("pageviews")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.4/pageviews_0.6.0.zip'
Content type 'application/zip' length 37973 bytes (37 KB)
downloaded 37 KB
package ‘pageviews’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\dsjja\AppData\Local\Temp\Rtmps9iDdF\downloaded_packages
# Load the library
library(pageviews)
Warning: package ‘pageviews’ was built under R version 4.4.3
#Reading the data set
data <- read.csv("dataset.csv")
conflicted::conflicts_prefer(dplyr::filter)
[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
data
names(data)
 [1] "X"                "track_id"         "artists"          "album_name"       "track_name"       "popularity"      
 [7] "duration_ms"      "explicit"         "danceability"     "energy"           "key"              "loudness"        
[13] "mode"             "speechiness"      "acousticness"     "instrumentalness" "liveness"         "valence"         
[19] "tempo"            "time_signature"   "track_genre"     

Choose a column of data to analyze over time. This should be a “response-like” variable that is of particular interest.

I choosed popularity.

Create a tsibble object of just the date and response variable. Then, plot your data over time. Consider different windows of time.

library(tsibble)

# Ensure the date column is in Date format
spotify_views$date <- as.Date(spotify_views$date)

# Create a tsibble object with date as the index and views as the response variable
spotify_ts <- spotify_views |>
  select(date, views) |>
  rename(popularity = views) |>
  as_tsibble(index = date)

# View the time series object
head(spotify_ts)
NA
# Plot popularity over time
ggplot(spotify_ts, aes(x = date, y = popularity)) +
  geom_line(color = "steelblue", linewidth = 1) +
  labs(
    title = "Spotify Track Popularity Over Time (Based on Wikipedia Views)",
    x = "Date",
    y = "Popularity (Views)"
  ) + theme_minimal()

# Aggregate by week
weekly_ts <- spotify_ts |>
  index_by(week = ~ lubridate::floor_date(., "week")) |>
  summarise(mean_popularity = mean(popularity, na.rm = TRUE))

# Plot
ggplot(weekly_ts, aes(x = week, y = mean_popularity)) +
  geom_line(color = "darkgreen") +
  labs(title = "Weekly Average Popularity", x = "Week", y = "Avg Views") +
  theme_minimal()

# By month
monthly_ts <- spotify_ts |>
  index_by(month = ~ lubridate::floor_date(., "month")) |>
  summarise(avg_popularity = mean(popularity, na.rm = TRUE))

ggplot(monthly_ts, aes(x = month, y = avg_popularity)) +
  geom_line(color = "orange") +
  labs(title = "Monthly Trends in Popularity", x = "Month", y = "Average Views") +
  theme_minimal()

What stands out immediately?

Statistical Significance: The consistency of the downward trend across different time aggregations (daily, weekly, monthly) strongly suggests statistical significance in the overall decline, particularly for the monthly data where the trend appears strongest (as noise is reduced through aggregation).

Practical Implications: This analysis suggests that Spotify track popularity (as measured by Wikipedia views) experienced a fundamental shift downward in early 2023, potentially indicating: A major change in user behavior, Platform algorithm changes, Competition from other music services, Seasonal effects early in the year that didn’t repeat.

Use linear regression to detect any upwards or downwards trends.

# Fit the linear regression model
model <- lm(popularity ~ date, data = spotify_ts)
summary(model)

Call:
lm(formula = popularity ~ date, data = spotify_ts)

Residuals:
    Min      1Q  Median      3Q     Max 
-2778.0  -842.5    -9.7   553.9  6952.8 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  2.410e+05  1.249e+04   19.29   <2e-16 ***
date        -1.200e+01  6.393e-01  -18.77   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1287 on 363 degrees of freedom
Multiple R-squared:  0.4927,    Adjusted R-squared:  0.4913 
F-statistic: 352.5 on 1 and 363 DF,  p-value: < 2.2e-16
ggplot(spotify_ts, aes(x = date, y = popularity)) +
  geom_point(alpha = 0.5) +
  geom_smooth(method = "lm", se = TRUE, color = "blue") +
  labs(title = "Trend of Popularity over Date", 
       x = "Date", y = "Popularity") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Based on the graph showing the “Trend of Popularity over Date” from January 2023 to January 2024, Data Trend Analysis:

The graph displays a clear overall downward trend in popularity over the one-year period, with the smoothed blue line showing a decline from approximately 8,500 in January 2023 to around 4,500 by January 2024. This represents nearly a 50% decrease in popularity over the year.

Use smoothing to detect at least one season in your data, and interpret your results.

spotify_ts |> ggplot(mapping = aes(x = date, y = popularity)) + 
  geom_point(size = 1, alpha = 0.4) + 
  geom_smooth(span = 0.2, color = 'blue', se = FALSE)+theme_classic()

Interpretation of the Smoothing Result

The plot uses LOESS smoothing (with span = 0.2) to visualize the trend in the “popularity” variable over time (from January 2023 to January 2024).

Key Observations

  1. Seasonal Pattern Detected:
    • There is a clear seasonal trend in the data.
    • Early 2023: Popularity starts high, peaking around January.
    • Spring 2023: There is a sharp decline in popularity from January to around April.
    • Mid-2023: Popularity remains relatively low and stable, with minor fluctuations.
    • Late 2023: There are small increases and decreases, but no major spikes until a slight uptick at the end of the year.
  2. Possible Seasonality:
    • The initial peak and subsequent drop suggest a seasonal effect—possibly related to an event or release that caused a spike in popularity at the start of the year.
    • The smaller oscillations throughout the rest of the year may indicate minor seasonal or periodic effects, but they are less pronounced than the initial drop.
  3. Noise and Outliers:
    • The scatterplot shows some outliers (especially high values) that the smoother does not follow closely, which is expected since the smoother is designed to capture the general trend, not every fluctuation.

Can you illustrate the seasonality using ACF or PACF?

acf(spotify_ts, ci = 0.95, na.action = na.exclude)

This ACF plot for spotify_ts suggests the series is not strongly seasonal but may have a trend or be non-stationary.

pacf(spotify_ts, na.action = na.exclude, xlab = 'lag', main = "PACF for Spotify pageviews" )

This PACF plot for Spotify pageviews shows a strong correlation at lag 1 and little to no significant correlation at higher lags. This suggests that an AR(1) model could be a good starting point for modeling this time series analysis.

To detect seasonality in my data, I used LOESS smoothing with a span of 0.2, as shown in the plot. Here’s what I observed:

Clear Seasonality: At the beginning of 2023, there is a noticeable peak in popularity, with values above 10,000. This suggests a strong seasonal effect or a specific event that drove popularity up during this period.

Sharp Decline and Stabilization: After this initial peak, popularity drops sharply through the first quarter of the year, reaching a low around April 2023. From that point onward, the popularity remains relatively stable, fluctuating between 5,000 and 7,000, with only minor ups and downs.

Minor Fluctuations: Throughout the rest of the year, I noticed some smaller oscillations, but none are as dramatic as the initial drop. This indicates that while there may be some minor seasonal effects, the main seasonality is concentrated at the start of the year.

Outliers: There are a few outlier points, especially high values, that the smoother doesn’t follow closely. This is expected, as the smoothing method is designed to capture the overall trend rather than every individual fluctuation.

Conclusion:

From this analysis, I can conclude that there is at least one strong season in my data, with a major peak in popularity at the start of the year, followed by a sharp decline and a stable period. This suggests that timing plays a significant role in popularity, and it may be beneficial to align major releases or promotions with the period where the peak occurs.

If I want to understand the causes behind these trends more deeply, I could further investigate what happened during the peak period or use more advanced time series analysis techniques.

LS0tDQp0aXRsZTogIldlZWsgLSAxMiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGdncmVwZWwpDQpsaWJyYXJ5KHh0cykNCmBgYA0KDQoNCmBgYHtyfQ0KIyBJbnN0YWxsIHRoZSBwYWdldmlld3MgcGFja2FnZQ0KaW5zdGFsbC5wYWNrYWdlcygicGFnZXZpZXdzIikNCg0KIyBMb2FkIHRoZSBsaWJyYXJ5DQpsaWJyYXJ5KHBhZ2V2aWV3cykNCmBgYA0KDQpgYGB7cn0NCiNSZWFkaW5nIHRoZSBkYXRhIHNldA0KZGF0YSA8LSByZWFkLmNzdigiZGF0YXNldC5jc3YiKQ0KY29uZmxpY3RlZDo6Y29uZmxpY3RzX3ByZWZlcihkcGx5cjo6ZmlsdGVyKQ0KIyBGaWx0ZXJpbmcgZGF0YXNldCB3aGVyZSBleHBsaWNpdCBpcyAiVHJ1ZSIgYW5kIHRha2luZyBhIHNhbXBsZSBvZiA5LDAwMCByb3dzDQpzYW1wbGVfZGF0YSA8LSBkYXRhIHw+IGZpbHRlcihleHBsaWNpdCA9PSAiVHJ1ZSIpIHw+IHNhbXBsZV9uKDkwMDApDQpkYXRhIDwtIHNhbXBsZV9kYXRhDQpkYXRhDQpgYGANCmBgYHtyfQ0KbmFtZXMoZGF0YSkNCmBgYA0KIyMjIFNlbGVjdCBhIGNvbHVtbiBvZiB5b3VyIGRhdGEgdGhhdCBlbmNvZGVzIHRpbWUgKGUuZy4sICJkYXRlIiwgInRpbWVzdGFtcCIsICJ5ZWFyIiwgZXRjLikuIENvbnZlcnQgdGhpcyBpbnRvIGEgRGF0ZSBpbiBSLiBJZiB5b3UgZG8gbm90IGhhdmUgYSB0aW1lLWJhc2VkIGNvbHVtbiBvZiBkYXRhOiBmaW5kIGEgV2lraXBlZGlhIHBhZ2UgdGhhdCBpcyByZWxhdGVkIHRvIHlvdXIgZGF0YXNldC4gVGhlbiwgZXh0cmFjdCBhIHRpbWUgc2VyaWVzIG9mIHBhZ2Ugdmlld3MgZm9yIHRoYXQgcGFnZSB1c2luZyB0aGUgd2lraXBlZGlhIHBhZ2Ugdmlld3Mgd2Vic2l0ZUxpbmtzIHRvIGFuIGV4dGVybmFsIHNpdGUuIG9yIHRoZSBSIHBhY2thZ2UgdXNlZCBpbiB0aGlzIHdlZWsncyBsYWIuDQoNCmBgYHtyfQ0KIyBFeHRyYWN0IGRhaWx5IHBhZ2Ugdmlld3MgZm9yICJTcG90aWZ5IiBXaWtpcGVkaWEgcGFnZQ0Kc3BvdGlmeV92aWV3cyA8LSBhcnRpY2xlX3BhZ2V2aWV3cygNCiAgcHJvamVjdCA9ICJlbi53aWtpcGVkaWEiLA0KICBhcnRpY2xlID0gIlNwb3RpZnkiLA0KICBzdGFydCA9IGFzLkRhdGUoIjIwMjMtMDEtMDEiKSwNCiAgZW5kID0gYXMuRGF0ZSgiMjAyMy0xMi0zMSIpLA0KICB1c2VyX3R5cGUgPSAidXNlciIsICAgICAjIE9ubHkgdXNlciB0cmFmZmljIA0KICBwbGF0Zm9ybSA9ICJhbGwiICAgICAgICAjIEFsbCBwbGF0Zm9ybXM6IGRlc2t0b3AsIG1vYmlsZS13ZWIsIGV0Yy4NCikNCg0KIyBWaWV3IHRoZSBmaXJzdCBmZXcgcm93cw0KaGVhZChzcG90aWZ5X3ZpZXdzKQ0KYGBgDQoNCg0KYGBge3J9DQojIFBsb3QgdGhlIHRpbWUgc2VyaWVzIG9mIHBhZ2Ugdmlld3MNCmdncGxvdChzcG90aWZ5X3ZpZXdzLCBhZXMoeCA9IGRhdGUsIHkgPSB2aWV3cykpICsNCiAgZ2VvbV9saW5lKGNvbG9yID0gInN0ZWVsYmx1ZSIsIHNpemUgPSAxKSArDQogIGxhYnModGl0bGUgPSAiRGFpbHkgV2lraXBlZGlhIFBhZ2UgVmlld3MgZm9yICdTcG90aWZ5JyBpbiAyMDIzIiwNCiAgICAgICB4ID0gIkRhdGUiLA0KICAgICAgIHkgPSAiVmlld3MiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KYGBge3J9DQpucm93KGRhdGEpDQpucm93KHNwb3RpZnlfdmlld3MpDQpgYGANCg0KYGBge3J9DQojIFZpZXcgdGhlIGZpcnN0IGZldyByb3dzIHRvIHVuZGVyc3RhbmQgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YQ0KaGVhZChzcG90aWZ5X3ZpZXdzKQ0KYGBgDQojIyMgQ2hvb3NlIGEgY29sdW1uIG9mIGRhdGEgdG8gYW5hbHl6ZSBvdmVyIHRpbWUuIFRoaXMgc2hvdWxkIGJlIGEgInJlc3BvbnNlLWxpa2UiIHZhcmlhYmxlIHRoYXQgaXMgb2YgcGFydGljdWxhciBpbnRlcmVzdC4NCkkgY2hvb3NlZCAqKnBvcHVsYXJpdHkqKi4NCg0KIyMjIENyZWF0ZSBhIHRzaWJibGUgb2JqZWN0IG9mIGp1c3QgdGhlIGRhdGUgYW5kIHJlc3BvbnNlIHZhcmlhYmxlLiBUaGVuLCBwbG90IHlvdXIgZGF0YSBvdmVyIHRpbWUuIENvbnNpZGVyIGRpZmZlcmVudCB3aW5kb3dzIG9mIHRpbWUuDQpgYGB7cn0NCmxpYnJhcnkodHNpYmJsZSkNCg0KIyBFbnN1cmUgdGhlIGRhdGUgY29sdW1uIGlzIGluIERhdGUgZm9ybWF0DQpzcG90aWZ5X3ZpZXdzJGRhdGUgPC0gYXMuRGF0ZShzcG90aWZ5X3ZpZXdzJGRhdGUpDQoNCiMgQ3JlYXRlIGEgdHNpYmJsZSBvYmplY3Qgd2l0aCBkYXRlIGFzIHRoZSBpbmRleCBhbmQgdmlld3MgYXMgdGhlIHJlc3BvbnNlIHZhcmlhYmxlDQpzcG90aWZ5X3RzIDwtIHNwb3RpZnlfdmlld3MgfD4NCiAgc2VsZWN0KGRhdGUsIHZpZXdzKSB8Pg0KICByZW5hbWUocG9wdWxhcml0eSA9IHZpZXdzKSB8Pg0KICBhc190c2liYmxlKGluZGV4ID0gZGF0ZSkNCg0KIyBWaWV3IHRoZSB0aW1lIHNlcmllcyBvYmplY3QNCmhlYWQoc3BvdGlmeV90cykNCg0KYGBgDQoNCg0KDQpgYGB7cn0NCiMgUGxvdCBwb3B1bGFyaXR5IG92ZXIgdGltZQ0KZ2dwbG90KHNwb3RpZnlfdHMsIGFlcyh4ID0gZGF0ZSwgeSA9IHBvcHVsYXJpdHkpKSArDQogIGdlb21fbGluZShjb2xvciA9ICJzdGVlbGJsdWUiLCBsaW5ld2lkdGggPSAxKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiU3BvdGlmeSBUcmFjayBQb3B1bGFyaXR5IE92ZXIgVGltZSAoQmFzZWQgb24gV2lraXBlZGlhIFZpZXdzKSIsDQogICAgeCA9ICJEYXRlIiwNCiAgICB5ID0gIlBvcHVsYXJpdHkgKFZpZXdzKSINCiAgKSArIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KYGBge3J9DQojIEFnZ3JlZ2F0ZSBieSB3ZWVrDQp3ZWVrbHlfdHMgPC0gc3BvdGlmeV90cyB8Pg0KICBpbmRleF9ieSh3ZWVrID0gfiBsdWJyaWRhdGU6OmZsb29yX2RhdGUoLiwgIndlZWsiKSkgfD4NCiAgc3VtbWFyaXNlKG1lYW5fcG9wdWxhcml0eSA9IG1lYW4ocG9wdWxhcml0eSwgbmEucm0gPSBUUlVFKSkNCg0KIyBQbG90DQpnZ3Bsb3Qod2Vla2x5X3RzLCBhZXMoeCA9IHdlZWssIHkgPSBtZWFuX3BvcHVsYXJpdHkpKSArDQogIGdlb21fbGluZShjb2xvciA9ICJkYXJrZ3JlZW4iKSArDQogIGxhYnModGl0bGUgPSAiV2Vla2x5IEF2ZXJhZ2UgUG9wdWxhcml0eSIsIHggPSAiV2VlayIsIHkgPSAiQXZnIFZpZXdzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCiMgQnkgbW9udGgNCm1vbnRobHlfdHMgPC0gc3BvdGlmeV90cyB8Pg0KICBpbmRleF9ieShtb250aCA9IH4gbHVicmlkYXRlOjpmbG9vcl9kYXRlKC4sICJtb250aCIpKSB8Pg0KICBzdW1tYXJpc2UoYXZnX3BvcHVsYXJpdHkgPSBtZWFuKHBvcHVsYXJpdHksIG5hLnJtID0gVFJVRSkpDQoNCmdncGxvdChtb250aGx5X3RzLCBhZXMoeCA9IG1vbnRoLCB5ID0gYXZnX3BvcHVsYXJpdHkpKSArDQogIGdlb21fbGluZShjb2xvciA9ICJvcmFuZ2UiKSArDQogIGxhYnModGl0bGUgPSAiTW9udGhseSBUcmVuZHMgaW4gUG9wdWxhcml0eSIsIHggPSAiTW9udGgiLCB5ID0gIkF2ZXJhZ2UgVmlld3MiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KIyBXaGF0IHN0YW5kcyBvdXQgaW1tZWRpYXRlbHk/DQpTdGF0aXN0aWNhbCBTaWduaWZpY2FuY2U6IFRoZSBjb25zaXN0ZW5jeSBvZiB0aGUgZG93bndhcmQgdHJlbmQgYWNyb3NzIGRpZmZlcmVudCB0aW1lIGFnZ3JlZ2F0aW9ucyAoZGFpbHksIHdlZWtseSwgbW9udGhseSkgc3Ryb25nbHkgc3VnZ2VzdHMgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIGluIHRoZSBvdmVyYWxsIGRlY2xpbmUsIHBhcnRpY3VsYXJseSBmb3IgdGhlIG1vbnRobHkgZGF0YSB3aGVyZSB0aGUgdHJlbmQgYXBwZWFycyBzdHJvbmdlc3QgKGFzIG5vaXNlIGlzIHJlZHVjZWQgdGhyb3VnaCBhZ2dyZWdhdGlvbikuDQoNClByYWN0aWNhbCBJbXBsaWNhdGlvbnM6IFRoaXMgYW5hbHlzaXMgc3VnZ2VzdHMgdGhhdCBTcG90aWZ5IHRyYWNrIHBvcHVsYXJpdHkgKGFzIG1lYXN1cmVkIGJ5IFdpa2lwZWRpYSB2aWV3cykgZXhwZXJpZW5jZWQgYSBmdW5kYW1lbnRhbCBzaGlmdCBkb3dud2FyZCBpbiBlYXJseSAyMDIzLCBwb3RlbnRpYWxseSBpbmRpY2F0aW5nOiBBIG1ham9yIGNoYW5nZSBpbiB1c2VyIGJlaGF2aW9yLCBQbGF0Zm9ybSBhbGdvcml0aG0gY2hhbmdlcywgQ29tcGV0aXRpb24gZnJvbSBvdGhlciBtdXNpYyBzZXJ2aWNlcywgU2Vhc29uYWwgZWZmZWN0cyBlYXJseSBpbiB0aGUgeWVhciB0aGF0IGRpZG4ndCByZXBlYXQuDQoNCg0KIyBVc2UgbGluZWFyIHJlZ3Jlc3Npb24gdG8gZGV0ZWN0IGFueSB1cHdhcmRzIG9yIGRvd253YXJkcyB0cmVuZHMuDQoNCmBgYHtyfQ0KIyBGaXQgdGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsDQptb2RlbCA8LSBsbShwb3B1bGFyaXR5IH4gZGF0ZSwgZGF0YSA9IHNwb3RpZnlfdHMpDQpzdW1tYXJ5KG1vZGVsKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KHNwb3RpZnlfdHMsIGFlcyh4ID0gZGF0ZSwgeSA9IHBvcHVsYXJpdHkpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBjb2xvciA9ICJibHVlIikgKw0KICBsYWJzKHRpdGxlID0gIlRyZW5kIG9mIFBvcHVsYXJpdHkgb3ZlciBEYXRlIiwgDQogICAgICAgeCA9ICJEYXRlIiwgeSA9ICJQb3B1bGFyaXR5IikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KDQpgYGANCkJhc2VkIG9uIHRoZSBncmFwaCBzaG93aW5nIHRoZSAiVHJlbmQgb2YgUG9wdWxhcml0eSBvdmVyIERhdGUiIGZyb20gSmFudWFyeSAyMDIzIHRvIEphbnVhcnkgMjAyNCwgRGF0YSBUcmVuZCBBbmFseXNpczoNCg0KVGhlIGdyYXBoIGRpc3BsYXlzIGEgY2xlYXIgb3ZlcmFsbCBkb3dud2FyZCB0cmVuZCBpbiBwb3B1bGFyaXR5IG92ZXIgdGhlIG9uZS15ZWFyIHBlcmlvZCwgd2l0aCB0aGUgc21vb3RoZWQgYmx1ZSBsaW5lIHNob3dpbmcgYSBkZWNsaW5lIGZyb20gYXBwcm94aW1hdGVseSA4LDUwMCBpbiBKYW51YXJ5IDIwMjMgdG8gYXJvdW5kIDQsNTAwIGJ5IEphbnVhcnkgMjAyNC4gVGhpcyByZXByZXNlbnRzIG5lYXJseSBhIDUwJSBkZWNyZWFzZSBpbiBwb3B1bGFyaXR5IG92ZXIgdGhlIHllYXIuDQoNCg0KIyBEbyB5b3UgbmVlZCB0byBzdWJzZXQgdGhlIGRhdGEgZm9yIG11bHRpcGxlIHRyZW5kcz8NCg0KWWVzLCBzdWJzZXR0aW5nIHRoZSBkYXRhIHdvdWxkIGJlIGJlbmVmaWNpYWwgZm9yIHNldmVyYWwgcmVhc29uczoNCg0KVGhlcmUgYXBwZWFyIHRvIGJlIGRpc3RpbmN0IGNsdXN0ZXJzIGluIHRoZSBkYXRhIHRoYXQgc3VnZ2VzdCBkaWZmZXJlbnQgcGF0dGVybnMgd2l0aGluIHRoZSBvdmVyYWxsIHRyZW5kDQoNClRoZSBmaXJzdCBxdWFydGVyIG9mIDIwMjMgc2hvd3Mgc2lnbmlmaWNhbnRseSBoaWdoZXIgcG9wdWxhcml0eSB2YWx1ZXMgKDEwLDAwMC0xMywwMDAgcmFuZ2UpIGNvbXBhcmVkIHRvIG90aGVyIHBlcmlvZHMNCg0KVGhlcmUncyBhIHZpc2libGUgaW5jcmVhc2UgaW4gdmFyaWFiaWxpdHkgYW5kIHNvbWUgaGlnaGVyIHBvaW50cyBhZ2FpbiBpbiBsYXRlIDIwMjMvZWFybHkgMjAyNA0KDQpUaGUgc2ltcGxlIGxpbmVhciB0cmVuZCBsaW5lICh1c2luZyB0aGUgZm9ybXVsYSAneSB+IHgnKSBkb2Vzbid0IGNhcHR1cmUgdGhlc2UgcG90ZW50aWFsIGN5Y2xpY2FsIG9yIHNlYXNvbmFsIHBhdHRlcm5zDQoNCiMgSG93IHN0cm9uZyBhcmUgdGhlc2UgdHJlbmRzPw0KDQpUaGUgb3ZlcmFsbCBkb3dud2FyZCB0cmVuZCBhcHBlYXJzIG1vZGVyYXRlbHkgc3Ryb25nLCBldmlkZW5jZWQgYnk6DQoNClRoZSBjb25zaXN0ZW50IG5lZ2F0aXZlIHNsb3BlIG9mIHRoZSBibHVlIHRyZW5kIGxpbmUgdGhyb3VnaG91dCB0aGUgZW50aXJlIHBlcmlvZA0KDQpUaGUgcmVsYXRpdmVseSBuYXJyb3cgY29uZmlkZW5jZSBpbnRlcnZhbCAoYmx1ZSBzaGFkZWQgYXJlYSkgYXJvdW5kIHRoZSB0cmVuZCBsaW5lLCBzdWdnZXN0aW5nIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZQ0KDQpIb3dldmVyLCB0aGUgc3Vic3RhbnRpYWwgc2NhdHRlciBvZiBkYXRhIHBvaW50cyBhcm91bmQgdGhlIHRyZW5kIGxpbmUgaW5kaWNhdGVzIGhpZ2ggdmFyaWFiaWxpdHkNCg0KVGhlIGdyYXBoIHNob3dzIGNvbnNpZGVyYWJsZSBkaXNwZXJzaW9uIG9mIGRhdGEgcG9pbnRzLCB3aXRoIG1hbnkgZmFsbGluZyBmYXIgZnJvbSB0aGUgdHJlbmQgbGluZS4gVGhpcyBzdWdnZXN0cyB0aGF0IHdoaWxlIHRoZSBkb3dud2FyZCB0cmVuZCBpcyBjbGVhciwgaXQgZXhwbGFpbnMgb25seSBhIHBvcnRpb24gb2YgdGhlIHZhcmlhdGlvbiBpbiBwb3B1bGFyaXR5LiBUaGUgaGlnaCBkZWdyZWUgb2Ygc2NhdHRlciBpbmRpY2F0ZXMgdGhhdCBvdGhlciBmYWN0b3JzIGJleW9uZCB0aGUgc2ltcGxlIHRpbWUgdmFyaWFibGUgYXJlIGxpa2VseSBpbmZsdWVuY2luZyBwb3B1bGFyaXR5IHZhbHVlcy4NCg0KDQojIFVzZSBzbW9vdGhpbmcgdG8gZGV0ZWN0IGF0IGxlYXN0IG9uZSBzZWFzb24gaW4geW91ciBkYXRhLCBhbmQgaW50ZXJwcmV0IHlvdXIgcmVzdWx0cy4NCg0KYGBge3J9DQpzcG90aWZ5X3RzIHw+IGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBkYXRlLCB5ID0gcG9wdWxhcml0eSkpICsgDQogIGdlb21fcG9pbnQoc2l6ZSA9IDEsIGFscGhhID0gMC40KSArIA0KICBnZW9tX3Ntb290aChzcGFuID0gMC4yLCBjb2xvciA9ICdibHVlJywgc2UgPSBGQUxTRSkrdGhlbWVfY2xhc3NpYygpDQpgYGANCiMjIEludGVycHJldGF0aW9uIG9mIHRoZSBTbW9vdGhpbmcgUmVzdWx0DQoNClRoZSBwbG90IHVzZXMgKipMT0VTUyBzbW9vdGhpbmcqKiAod2l0aCBgc3BhbiA9IDAuMmApIHRvIHZpc3VhbGl6ZSB0aGUgdHJlbmQgaW4gdGhlICJwb3B1bGFyaXR5IiB2YXJpYWJsZSBvdmVyIHRpbWUgKGZyb20gSmFudWFyeSAyMDIzIHRvIEphbnVhcnkgMjAyNCkuDQoNCiMjIyBLZXkgT2JzZXJ2YXRpb25zDQoNCjEuICoqU2Vhc29uYWwgUGF0dGVybiBEZXRlY3RlZDoqKg0KICAgLSBUaGVyZSBpcyBhICoqY2xlYXIgc2Vhc29uYWwgdHJlbmQqKiBpbiB0aGUgZGF0YS4NCiAgIC0gKipFYXJseSAyMDIzOioqIFBvcHVsYXJpdHkgc3RhcnRzIGhpZ2gsIHBlYWtpbmcgYXJvdW5kIEphbnVhcnkuDQogICAtICoqU3ByaW5nIDIwMjM6KiogVGhlcmUgaXMgYSAqKnNoYXJwIGRlY2xpbmUqKiBpbiBwb3B1bGFyaXR5IGZyb20gSmFudWFyeSB0byBhcm91bmQgQXByaWwuDQogICAtICoqTWlkLTIwMjM6KiogUG9wdWxhcml0eSByZW1haW5zIHJlbGF0aXZlbHkgbG93IGFuZCBzdGFibGUsIHdpdGggbWlub3IgZmx1Y3R1YXRpb25zLg0KICAgLSAqKkxhdGUgMjAyMzoqKiBUaGVyZSBhcmUgc21hbGwgaW5jcmVhc2VzIGFuZCBkZWNyZWFzZXMsIGJ1dCBubyBtYWpvciBzcGlrZXMgdW50aWwgYSBzbGlnaHQgdXB0aWNrIGF0IHRoZSBlbmQgb2YgdGhlIHllYXIuDQoNCjIuICoqUG9zc2libGUgU2Vhc29uYWxpdHk6KioNCiAgIC0gVGhlICoqaW5pdGlhbCBwZWFrKiogYW5kIHN1YnNlcXVlbnQgZHJvcCBzdWdnZXN0IGEgKipzZWFzb25hbCBlZmZlY3QqKuKAlHBvc3NpYmx5IHJlbGF0ZWQgdG8gYW4gZXZlbnQgb3IgcmVsZWFzZSB0aGF0IGNhdXNlZCBhIHNwaWtlIGluIHBvcHVsYXJpdHkgYXQgdGhlIHN0YXJ0IG9mIHRoZSB5ZWFyLg0KICAgLSBUaGUgKipzbWFsbGVyIG9zY2lsbGF0aW9ucyoqIHRocm91Z2hvdXQgdGhlIHJlc3Qgb2YgdGhlIHllYXIgbWF5IGluZGljYXRlICoqbWlub3Igc2Vhc29uYWwgb3IgcGVyaW9kaWMgZWZmZWN0cyoqLCBidXQgdGhleSBhcmUgbGVzcyBwcm9ub3VuY2VkIHRoYW4gdGhlIGluaXRpYWwgZHJvcC4NCg0KMy4gKipOb2lzZSBhbmQgT3V0bGllcnM6KioNCiAgIC0gVGhlIHNjYXR0ZXJwbG90IHNob3dzIHNvbWUgKipvdXRsaWVycyoqIChlc3BlY2lhbGx5IGhpZ2ggdmFsdWVzKSB0aGF0IHRoZSBzbW9vdGhlciBkb2VzIG5vdCBmb2xsb3cgY2xvc2VseSwgd2hpY2ggaXMgZXhwZWN0ZWQgc2luY2UgdGhlIHNtb290aGVyIGlzIGRlc2lnbmVkIHRvIGNhcHR1cmUgdGhlIGdlbmVyYWwgdHJlbmQsIG5vdCBldmVyeSBmbHVjdHVhdGlvbi4NCg0KDQojIENhbiB5b3UgaWxsdXN0cmF0ZSB0aGUgc2Vhc29uYWxpdHkgdXNpbmcgQUNGIG9yIFBBQ0Y/DQoNCmBgYHtyfQ0KYWNmKHNwb3RpZnlfdHMsIGNpID0gMC45NSwgbmEuYWN0aW9uID0gbmEuZXhjbHVkZSkNCmBgYA0KVGhpcyBBQ0YgcGxvdCBmb3Igc3BvdGlmeV90cyBzdWdnZXN0cyB0aGUgc2VyaWVzIGlzIG5vdCBzdHJvbmdseSBzZWFzb25hbCBidXQgbWF5IGhhdmUgYSB0cmVuZCBvciBiZSBub24tc3RhdGlvbmFyeS4gDQoNCmBgYHtyfQ0KcGFjZihzcG90aWZ5X3RzLCBuYS5hY3Rpb24gPSBuYS5leGNsdWRlLCB4bGFiID0gJ2xhZycsIG1haW4gPSAiUEFDRiBmb3IgU3BvdGlmeSBwYWdldmlld3MiICkNCmBgYA0KVGhpcyBQQUNGIHBsb3QgZm9yIFNwb3RpZnkgcGFnZXZpZXdzIHNob3dzIGEgc3Ryb25nIGNvcnJlbGF0aW9uIGF0IGxhZyAxIGFuZCBsaXR0bGUgdG8gbm8gc2lnbmlmaWNhbnQgY29ycmVsYXRpb24gYXQgaGlnaGVyIGxhZ3MuIFRoaXMgc3VnZ2VzdHMgdGhhdCBhbiBBUigxKSBtb2RlbCBjb3VsZCBiZSBhIGdvb2Qgc3RhcnRpbmcgcG9pbnQgZm9yIG1vZGVsaW5nIHRoaXMgdGltZSBzZXJpZXMgYW5hbHlzaXMuDQoNCg0KDQoNClRvIGRldGVjdCBzZWFzb25hbGl0eSBpbiBteSBkYXRhLCBJIHVzZWQgTE9FU1Mgc21vb3RoaW5nIHdpdGggYSBzcGFuIG9mIDAuMiwgYXMgc2hvd24gaW4gdGhlIHBsb3QuIEhlcmXigJlzIHdoYXQgSSBvYnNlcnZlZDoNCg0KQ2xlYXIgU2Vhc29uYWxpdHk6DQpBdCB0aGUgYmVnaW5uaW5nIG9mIDIwMjMsIHRoZXJlIGlzIGEgbm90aWNlYWJsZSBwZWFrIGluIHBvcHVsYXJpdHksIHdpdGggdmFsdWVzIGFib3ZlIDEwLDAwMC4gVGhpcyBzdWdnZXN0cyBhIHN0cm9uZyBzZWFzb25hbCBlZmZlY3Qgb3IgYSBzcGVjaWZpYyBldmVudCB0aGF0IGRyb3ZlIHBvcHVsYXJpdHkgdXAgZHVyaW5nIHRoaXMgcGVyaW9kLg0KDQpTaGFycCBEZWNsaW5lIGFuZCBTdGFiaWxpemF0aW9uOg0KQWZ0ZXIgdGhpcyBpbml0aWFsIHBlYWssIHBvcHVsYXJpdHkgZHJvcHMgc2hhcnBseSB0aHJvdWdoIHRoZSBmaXJzdCBxdWFydGVyIG9mIHRoZSB5ZWFyLCByZWFjaGluZyBhIGxvdyBhcm91bmQgQXByaWwgMjAyMy4gRnJvbSB0aGF0IHBvaW50IG9ud2FyZCwgdGhlIHBvcHVsYXJpdHkgcmVtYWlucyByZWxhdGl2ZWx5IHN0YWJsZSwgZmx1Y3R1YXRpbmcgYmV0d2VlbiA1LDAwMCBhbmQgNywwMDAsIHdpdGggb25seSBtaW5vciB1cHMgYW5kIGRvd25zLg0KDQpNaW5vciBGbHVjdHVhdGlvbnM6DQpUaHJvdWdob3V0IHRoZSByZXN0IG9mIHRoZSB5ZWFyLCBJIG5vdGljZWQgc29tZSBzbWFsbGVyIG9zY2lsbGF0aW9ucywgYnV0IG5vbmUgYXJlIGFzIGRyYW1hdGljIGFzIHRoZSBpbml0aWFsIGRyb3AuIFRoaXMgaW5kaWNhdGVzIHRoYXQgd2hpbGUgdGhlcmUgbWF5IGJlIHNvbWUgbWlub3Igc2Vhc29uYWwgZWZmZWN0cywgdGhlIG1haW4gc2Vhc29uYWxpdHkgaXMgY29uY2VudHJhdGVkIGF0IHRoZSBzdGFydCBvZiB0aGUgeWVhci4NCg0KT3V0bGllcnM6DQpUaGVyZSBhcmUgYSBmZXcgb3V0bGllciBwb2ludHMsIGVzcGVjaWFsbHkgaGlnaCB2YWx1ZXMsIHRoYXQgdGhlIHNtb290aGVyIGRvZXNu4oCZdCBmb2xsb3cgY2xvc2VseS4gVGhpcyBpcyBleHBlY3RlZCwgYXMgdGhlIHNtb290aGluZyBtZXRob2QgaXMgZGVzaWduZWQgdG8gY2FwdHVyZSB0aGUgb3ZlcmFsbCB0cmVuZCByYXRoZXIgdGhhbiBldmVyeSBpbmRpdmlkdWFsIGZsdWN0dWF0aW9uLg0KDQojIyMgQ29uY2x1c2lvbjoNCg0KRnJvbSB0aGlzIGFuYWx5c2lzLCBJIGNhbiBjb25jbHVkZSB0aGF0IHRoZXJlIGlzIGF0IGxlYXN0IG9uZSBzdHJvbmcgc2Vhc29uIGluIG15IGRhdGEsIHdpdGggYSBtYWpvciBwZWFrIGluIHBvcHVsYXJpdHkgYXQgdGhlIHN0YXJ0IG9mIHRoZSB5ZWFyLCBmb2xsb3dlZCBieSBhIHNoYXJwIGRlY2xpbmUgYW5kIGEgc3RhYmxlIHBlcmlvZC4gVGhpcyBzdWdnZXN0cyB0aGF0IHRpbWluZyBwbGF5cyBhIHNpZ25pZmljYW50IHJvbGUgaW4gcG9wdWxhcml0eSwgYW5kIGl0IG1heSBiZSBiZW5lZmljaWFsIHRvIGFsaWduIG1ham9yIHJlbGVhc2VzIG9yIHByb21vdGlvbnMgd2l0aCB0aGUgcGVyaW9kIHdoZXJlIHRoZSBwZWFrIG9jY3Vycy4NCg0KSWYgSSB3YW50IHRvIHVuZGVyc3RhbmQgdGhlIGNhdXNlcyBiZWhpbmQgdGhlc2UgdHJlbmRzIG1vcmUgZGVlcGx5LCBJIGNvdWxkIGZ1cnRoZXIgaW52ZXN0aWdhdGUgd2hhdCBoYXBwZW5lZCBkdXJpbmcgdGhlIHBlYWsgcGVyaW9kIG9yIHVzZSBtb3JlIGFkdmFuY2VkIHRpbWUgc2VyaWVzIGFuYWx5c2lzIHRlY2huaXF1ZXMuDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==