rm(list=ls(all=T))
options(digits=4, scipen=12)
library(dplyr); library(ggplot2)

Introduction

議題:使用歌曲的屬性,預測它會不會進入流行歌曲排行榜的前10名

學習重點:



1 基本的資料處理 Understanding the Data

1.1】How many observations (songs) are from the year 2010?

A = read.csv("data/songs.csv")
nrow(subset(A,A$year == 2010)) #373
[1] 373

1.2】How many songs does the dataset include for which the artist name is “Michael Jackson”?

nrow(subset(A,A$artistname == "Michael Jackson"))
[1] 18

1.3】Which of these songs by Michael Jackson made it to the Top 10? Select all that apply.

1.4】(a) What are the values of timesignature that occur in our dataset? (b) Which timesignature value is the most frequent among songs in our dataset?

table(A$timesignature) #4

   0    1    3    4    5    7 
  10  143  503 6787  112   19 

1.5】 Which of the following songs has the highest tempo?

A[which.max(A$tempo), 1:5] #Wanna Be Startin' Somethin'



2 建立模型 Creating Our Prediction Model

We wish to predict whether or not a song will make it to the Top 10. To do this, first use the subset function to split the data into a training set “SongsTrain” consisting of all the observations up to and including 2009 song releases, and a testing set “SongsTest”, consisting of the 2010 song releases.

2.1 依時間分割資料】How many observations (songs) are in the training set?

TR = subset(A,A$year <= 2009)
TS = subset(A,A$year == 2010)
nrow(TR)
[1] 7201

2.2 建立模型、模型摘要】What is the value of the Akaike Information Criterion (AIC)?

nonvars = c("year", "songtitle", "artistname", "songID", "artistID")
#去除非numeric的屬性
TR = TR[ , !(names(TR) %in% nonvars) ]
TS = TS[ , !(names(TS) %in% nonvars) ]
glm1 = glm(Top10~.,TR,family = binomial())
summary(glm1)

Call:
glm(formula = Top10 ~ ., family = binomial(), data = TR)

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.922  -0.540  -0.346  -0.184   3.077  

Coefficients:
                            Estimate  Std. Error z value
(Intercept)               14.6999882   1.8063875    8.14
timesignature              0.1263948   0.0867357    1.46
timesignature_confidence   0.7449923   0.1953053    3.81
loudness                   0.2998794   0.0291654   10.28
tempo                      0.0003634   0.0016915    0.21
tempo_confidence           0.4732270   0.1421740    3.33
key                        0.0158820   0.0103895    1.53
key_confidence             0.3086751   0.1411562    2.19
energy                    -1.5021445   0.3099240   -4.85
pitch                    -44.9077399   6.8348831   -6.57
timbre_0_min               0.0231589   0.0042562    5.44
timbre_0_max              -0.3309820   0.0256926  -12.88
timbre_1_min               0.0058810   0.0007798    7.54
timbre_1_max              -0.0002449   0.0007152   -0.34
timbre_2_min              -0.0021274   0.0011260   -1.89
timbre_2_max               0.0006586   0.0009066    0.73
timbre_3_min               0.0006920   0.0005985    1.16
timbre_3_max              -0.0029673   0.0005815   -5.10
timbre_4_min               0.0103956   0.0019850    5.24
timbre_4_max               0.0061105   0.0015503    3.94
timbre_5_min              -0.0055980   0.0012767   -4.38
timbre_5_max               0.0000774   0.0007935    0.10
timbre_6_min              -0.0168562   0.0022640   -7.45
timbre_6_max               0.0036681   0.0021895    1.68
timbre_7_min              -0.0045492   0.0017815   -2.55
timbre_7_max              -0.0037737   0.0018320   -2.06
timbre_8_min               0.0039110   0.0028510    1.37
timbre_8_max               0.0040113   0.0030030    1.34
timbre_9_min               0.0013673   0.0029981    0.46
timbre_9_max               0.0016027   0.0024336    0.66
timbre_10_min              0.0041263   0.0018391    2.24
timbre_10_max              0.0058250   0.0017694    3.29
timbre_11_min             -0.0262523   0.0036933   -7.11
timbre_11_max              0.0196734   0.0033855    5.81
                                   Pr(>|z|)    
(Intercept)              0.0000000000000004 ***
timesignature                       0.14505    
timesignature_confidence            0.00014 ***
loudness                            < 2e-16 ***
tempo                               0.82989    
tempo_confidence                    0.00087 ***
key                                 0.12635    
key_confidence                      0.02876 *  
energy                   0.0000012545913310 ***
pitch                    0.0000000000501890 ***
timbre_0_min             0.0000000529331342 ***
timbre_0_max                        < 2e-16 ***
timbre_1_min             0.0000000000000464 ***
timbre_1_max                        0.73209    
timbre_2_min                        0.05884 .  
timbre_2_max                        0.46757    
timbre_3_min                        0.24758    
timbre_3_max             0.0000003344570390 ***
timbre_4_min             0.0000001632385067 ***
timbre_4_max             0.0000809670432888 ***
timbre_5_min             0.0000116146773897 ***
timbre_5_max                        0.92234    
timbre_6_min             0.0000000000000966 ***
timbre_6_max                        0.09388 .  
timbre_7_min                        0.01066 *  
timbre_7_max                        0.03941 *  
timbre_8_min                        0.17012    
timbre_8_max                        0.18162    
timbre_9_min                        0.64836    
timbre_9_max                        0.51019    
timbre_10_min                       0.02485 *  
timbre_10_max                       0.00099 ***
timbre_11_min            0.0000000000011760 ***
timbre_11_max            0.0000000062068661 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 6017.5  on 7200  degrees of freedom
Residual deviance: 4759.2  on 7167  degrees of freedom
AIC: 4827

Number of Fisher Scoring iterations: 6

2.3 模型係數判讀】The LOWER or HIGHER our confidence about time signature, key and tempo, the more likely the song is to be in the Top 10

#HIGHER 因為estimate都是正的 

2.4 進行推論】What does Model 1 suggest in terms of complexity?

#Mainstream listeners tend to prefer less complex songs
#signature,key,tempo的confidence低,代表歌的複雜度高。但模型顯示confidence高,越能進入top10,代表大眾較喜愛不複雜的歌

2.5 檢查異常係數】 Songs with heavier instrumentation tend to be louder (have higher values in the variable “loudness”) and more energetic (have higher values in the variable “energy”).

  1. By inspecting the coefficient of the variable “loudness”, what does Model 1 suggest? (b) By inspecting the coefficient of the variable “energy”, do we draw the same conclusions as above?
#loudness的estimate為正
#energy的esimate為負
#(a) Mainstream listeners prefer songs with heavy instrumentation
#(b) 與a相反



3 處理共線性 Beware of Multicollinearity Issues!

3.1 檢查相關係數】What is the correlation between loudness and energy in the training set?

cor(TR$loudness,TR$energy)
[1] 0.7399

Create Model 2, which is Model 1 without the independent variable “loudness”. This can be done with the following command:

SongsLog2 = glm(Top10 ~ . - loudness, data=SongsTrain, family=binomial)

We just subtracted the variable loudness. We couldn’t do this with the variables “songtitle” and “artistname”, because they are not numeric variables, and we might get different values in the test set that the training set has never seen. But this approach (subtracting the variable from the model formula) will always work when you want to remove numeric variables.

Look at the summary of SongsLog2, and inspect the coefficient of the variable “energy”. What do you observe?

3.2 重新建立模型、檢查係數】Look at the summary of SongsLog2, and inspect the coefficient of the variable “energy”. What do you observe?

lm2 = glm(Top10~.-loudness,data= TR,family = binomial)
#以Top10其他全部屬性為independent var(減去loudness)
summary(lm2)

Call:
glm(formula = Top10 ~ . - loudness, family = binomial, data = TR)

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-2.098  -0.561  -0.360  -0.190   3.311  

Coefficients:
                           Estimate Std. Error z value
(Intercept)               -2.240612   0.746484   -3.00
timesignature              0.162461   0.087341    1.86
timesignature_confidence   0.688471   0.192419    3.58
tempo                      0.000552   0.001665    0.33
tempo_confidence           0.549657   0.140736    3.91
key                        0.017403   0.010256    1.70
key_confidence             0.295367   0.139446    2.12
energy                     0.181260   0.260768    0.70
pitch                    -51.498579   6.856544   -7.51
timbre_0_min               0.024789   0.004240    5.85
timbre_0_max              -0.100697   0.011776   -8.55
timbre_1_min               0.007143   0.000771    9.27
timbre_1_max              -0.000783   0.000706   -1.11
timbre_2_min              -0.001579   0.001109   -1.42
timbre_2_max               0.000389   0.000896    0.43
timbre_3_min               0.000650   0.000595    1.09
timbre_3_max              -0.002462   0.000567   -4.34
timbre_4_min               0.009115   0.001952    4.67
timbre_4_max               0.006306   0.001532    4.12
timbre_5_min              -0.005641   0.001255   -4.50
timbre_5_max               0.000694   0.000781    0.89
timbre_6_min              -0.016122   0.002235   -7.21
timbre_6_max               0.003814   0.002157    1.77
timbre_7_min              -0.005102   0.001755   -2.91
timbre_7_max              -0.003158   0.001811   -1.74
timbre_8_min               0.004488   0.002810    1.60
timbre_8_max               0.006422   0.002950    2.18
timbre_9_min              -0.000428   0.002955   -0.14
timbre_9_max               0.003525   0.002377    1.48
timbre_10_min              0.002993   0.001804    1.66
timbre_10_max              0.007367   0.001731    4.25
timbre_11_min             -0.028370   0.003630   -7.82
timbre_11_max              0.018294   0.003341    5.48
                                   Pr(>|z|)    
(Intercept)                         0.00269 ** 
timesignature                       0.06287 .  
timesignature_confidence            0.00035 ***
tempo                               0.74023    
tempo_confidence         0.0000940005473689 ***
key                                 0.08974 .  
key_confidence                      0.03416 *  
energy                              0.48699    
pitch                    0.0000000000000587 ***
timbre_0_min             0.0000000050055433 ***
timbre_0_max                        < 2e-16 ***
timbre_1_min                        < 2e-16 ***
timbre_1_max                        0.26765    
timbre_2_min                        0.15453    
timbre_2_max                        0.66443    
timbre_3_min                        0.27452    
timbre_3_max             0.0000143015554481 ***
timbre_4_min             0.0000030176578261 ***
timbre_4_max             0.0000387139806484 ***
timbre_5_min             0.0000069522013076 ***
timbre_5_max                        0.37426    
timbre_6_min             0.0000000000005452 ***
timbre_6_max                        0.07698 .  
timbre_7_min                        0.00364 ** 
timbre_7_max                        0.08109 .  
timbre_8_min                        0.11025    
timbre_8_max                        0.02950 *  
timbre_9_min                        0.88479    
timbre_9_max                        0.13802    
timbre_10_min                       0.09700 .  
timbre_10_max            0.0000209292079939 ***
timbre_11_min            0.0000000000000055 ***
timbre_11_max            0.0000000434235974 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 6017.5  on 7200  degrees of freedom
Residual deviance: 4871.8  on 7168  degrees of freedom
AIC: 4938

Number of Fisher Scoring iterations: 6
#Model 2 suggests that songs with high energy levels tend to be more popular. This contradicts our observation in Model 1.
#energy的estimate為正,但沒有顯著

3.3 選擇模型】 Now, create Model 3, which should be exactly like Model 1, but without the variable “energy”.

Look at the summary of Model 3 and inspect the coefficient of the variable “loudness”. Remembering that higher loudness and energy both occur in songs with heavier instrumentation, do we make the same observation about the popularity of heavy instrumentation as we did with Model 2?

do we make the same observation about the popularity of heavy instrumentation as we did with Model 2?

lm3 = glm(Top10~. -energy,data = TR , family = binomial)
summary(lm3)

Call:
glm(formula = Top10 ~ . - energy, family = binomial, data = TR)

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.918  -0.542  -0.348  -0.187   3.417  

Coefficients:
                            Estimate  Std. Error z value
(Intercept)               11.9605621   1.7141947    6.98
timesignature              0.1150942   0.0872615    1.32
timesignature_confidence   0.7142698   0.1946175    3.67
loudness                   0.2305565   0.0252798    9.12
tempo                     -0.0006460   0.0016655   -0.39
tempo_confidence           0.3840930   0.1398350    2.75
key                        0.0164946   0.0103514    1.59
key_confidence             0.3394064   0.1408744    2.41
pitch                    -53.2840575   6.7328544   -7.91
timbre_0_min               0.0220452   0.0042394    5.20
timbre_0_max              -0.3104800   0.0253654  -12.24
timbre_1_min               0.0054160   0.0007643    7.09
timbre_1_max              -0.0005115   0.0007110   -0.72
timbre_2_min              -0.0022544   0.0011203   -2.01
timbre_2_max               0.0004119   0.0009020    0.46
timbre_3_min               0.0003179   0.0005869    0.54
timbre_3_max              -0.0029637   0.0005758   -5.15
timbre_4_min               0.0110465   0.0019779    5.58
timbre_4_max               0.0064668   0.0015413    4.20
timbre_5_min              -0.0051345   0.0012690   -4.05
timbre_5_max               0.0002979   0.0007856    0.38
timbre_6_min              -0.0178447   0.0022460   -7.94
timbre_6_max               0.0034469   0.0021821    1.58
timbre_7_min              -0.0051284   0.0017685   -2.90
timbre_7_max              -0.0033935   0.0018198   -1.86
timbre_8_min               0.0036861   0.0028331    1.30
timbre_8_max               0.0046578   0.0029879    1.56
timbre_9_min              -0.0000932   0.0029569   -0.03
timbre_9_max               0.0013417   0.0024239    0.55
timbre_10_min              0.0040500   0.0018270    2.22
timbre_10_max              0.0057925   0.0017586    3.29
timbre_11_min             -0.0263767   0.0036829   -7.16
timbre_11_max              0.0198361   0.0033646    5.90
                                   Pr(>|z|)    
(Intercept)              0.0000000000030077 ***
timesignature                       0.18718    
timesignature_confidence            0.00024 ***
loudness                            < 2e-16 ***
tempo                               0.69811    
tempo_confidence                    0.00602 ** 
key                                 0.11106    
key_confidence                      0.01598 *  
pitch                    0.0000000000000025 ***
timbre_0_min             0.0000001992236315 ***
timbre_0_max                        < 2e-16 ***
timbre_1_min             0.0000000000013757 ***
timbre_1_max                        0.47193    
timbre_2_min                        0.04419 *  
timbre_2_max                        0.64791    
timbre_3_min                        0.58808    
timbre_3_max             0.0000002640646649 ***
timbre_4_min             0.0000000233875661 ***
timbre_4_max             0.0000272139788370 ***
timbre_5_min             0.0000520513667576 ***
timbre_5_max                        0.70453    
timbre_6_min             0.0000000000000019 ***
timbre_6_max                        0.11420    
timbre_7_min                        0.00373 ** 
timbre_7_max                        0.06221 .  
timbre_8_min                        0.19323    
timbre_8_max                        0.11902    
timbre_9_min                        0.97486    
timbre_9_max                        0.57990    
timbre_10_min                       0.02664 *  
timbre_10_max                       0.00099 ***
timbre_11_min            0.0000000000007958 ***
timbre_11_max            0.0000000037350899 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 6017.5  on 7200  degrees of freedom
Residual deviance: 4782.7  on 7168  degrees of freedom
AIC: 4849

Number of Fisher Scoring iterations: 6
#loudness 顯著,estimate為正
#Yes



4 驗證模型 Validating Our Model

4.1 正確性】What is the accuracy of Model 3 on the test set, using a threshold of 0.45?

pred = predict(lm3, newdata=TS, type="response") 
#type= "response" 代表output為機率
x = table(actual = TS$Top10, predict = pred >= 0.45); x
      predict
actual FALSE TRUE
     0   309    5
     1    40   19
#confusion matrix,actural和predict為matrix上、左名稱
#threshold 0.45,代表>0.45才會被視為y=1
#ACC = TN+TP/全部
diag(x) #回傳矩陣對角 309,19
[1] 309  19
sum(diag(x))/sum(x)  # ACC = 0.8794 
[1] 0.8794

4.2 底線正確率】What would the accuracy of the baseline model be on the test set? ?

table(TS$Top10)

  0   1 
314  59 
1 - mean(TS$Top10)
[1] 0.8418
#? 為什麼直接減mean

4.3 正確性 vs. 辨識率】How many songs does Model 3 correctly predict as Top 10 hits in 2010? How many non-hit songs does Model 3 predict will be Top 10 hits?

#lm3在testing data的TP = 19, FP = 5

Q】不能大幅度增加正確性的模型也會有用嗎?為甚麼?

我認為ACC不是一個很好代表模型好壞的指標,所以不能大幅增加應該也沒關係

4.4 敏感性 & 明確性】What is the sensitivity and specificity of Model 3 on the test set, using a threshold of 0.45?

#sensitivity = TP/TP+FN(在實際上為1的狀況下找到他的機率)
sen = 19 / (19+40) ; sen
[1] 0.322
#specificity = TN/TN+FP
spec = 309 / (309+5) ; spec
[1] 0.9841

4.5 結論】What conclusions can you make about our model?

#Model 3 has a very high specificity, meaning that it favors specificity over sensitivity. While Model 3 only captures less than half of the Top 10 songs, it still can offer a competitive edge, since it is very conservative in its predictions.

#model3有較高的specificity
#但sensitivity只有0.32,不到0.5,代表他只抓不到一半的TOP10歌曲


Q】從這個結論我們學到什麼?





LS0tCnRpdGxlOiAiQVMzLTEgUG9wdWxhcml0eSBvZiBtdXNpYyByZWNvcmRzIgphdXRob3I6ICJCMDM0MDIwMDI3IOmZs+mfu+WNiSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3IgZWNobz1ULCBtZXNzYWdlPUYsIGNhY2hlPUYsIHdhcm5pbmc9Rn0Kcm0obGlzdD1scyhhbGw9VCkpCm9wdGlvbnMoZGlnaXRzPTQsIHNjaXBlbj0xMikKbGlicmFyeShkcGx5cik7IGxpYnJhcnkoZ2dwbG90MikKYGBgCgotIC0gLQoKIyMjIEludHJvZHVjdGlvbgoK6K2w6aGM77ya5L2/55So5q2M5puy55qE5bGs5oCn77yM6aCQ5ris5a6D5pyD5LiN5pyD6YCy5YWl5rWB6KGM5q2M5puy5o6S6KGM5qac55qE5YmNMTDlkI0KCuWtuOe/kumHjem7nu+8mgoKKyDkvp3mmYLplpPliIblibLos4fmlpkKKyBtb2RlbCBmb3JtdWxhIOeahOWvq+azlQorIOmrmOebuOmXnCjlhbHnt5rmgKcp6Ieq6K6K5pW45LmL6ZaT55qE6YG45pOHCisgYWNjdXJhY3ksIHNlbnNpdGl2aXR5LCBzcGVjaWZpY2l0eeeahOWvpumam+aEj+e+qSAKKyDlpoLkvZXoqr/mlbToh6jnlYzmqZ/njofkvobmrIrooaHvvJpURlIvc2Vuc2l0aXZpdHkgdnMuIEZQUi9zcGVjaWZpY2l0eSAKCjxicj4KCi0gLSAtCgojIyMgMSDln7rmnKznmoTos4fmlpnomZXnkIYgVW5kZXJzdGFuZGluZyB0aGUgRGF0YQoK44CQKioxLjEqKuOAkUhvdyBtYW55IG9ic2VydmF0aW9ucyAoc29uZ3MpIGFyZSBmcm9tIHRoZSB5ZWFyIDIwMTA/CmBgYHtyfQpBID0gcmVhZC5jc3YoImRhdGEvc29uZ3MuY3N2IikKbnJvdyhzdWJzZXQoQSxBJHllYXIgPT0gMjAxMCkpICMzNzMKCmBgYAoK44CQKioxLjIqKuOAkUhvdyBtYW55IHNvbmdzIGRvZXMgdGhlIGRhdGFzZXQgaW5jbHVkZSBmb3Igd2hpY2ggdGhlIGFydGlzdCBuYW1lIGlzICJNaWNoYWVsIEphY2tzb24iPwpgYGB7cn0KbnJvdyhzdWJzZXQoQSxBJGFydGlzdG5hbWUgPT0gIk1pY2hhZWwgSmFja3NvbiIpKQpgYGAKCuOAkCoqMS4zKirjgJFXaGljaCBvZiB0aGVzZSBzb25ncyBieSBNaWNoYWVsIEphY2tzb24gbWFkZSBpdCB0byB0aGUgVG9wIDEwPyBTZWxlY3QgYWxsIHRoYXQgYXBwbHkuCmBgYHtyfQpzdWJzZXQoQSxBJGFydGlzdG5hbWUgPT0gIk1pY2hhZWwgSmFja3NvbiIgJiBBJFRvcDEwID09IDEpCgpgYGAKCuOAkCoqMS40KirjgJEoYSkgV2hhdCBhcmUgdGhlIHZhbHVlcyBvZiBgdGltZXNpZ25hdHVyZWAgdGhhdCBvY2N1ciBpbiBvdXIgZGF0YXNldD8gKGIpIFdoaWNoIHRpbWVzaWduYXR1cmUgdmFsdWUgaXMgdGhlIG1vc3QgZnJlcXVlbnQgYW1vbmcgc29uZ3MgaW4gb3VyIGRhdGFzZXQ/IApgYGB7cn0KdGFibGUoQSR0aW1lc2lnbmF0dXJlKSAjNAoKYGBgCgrjgJAqKjEuNSoq44CRIFdoaWNoIG9mIHRoZSBmb2xsb3dpbmcgc29uZ3MgaGFzIHRoZSBoaWdoZXN0IHRlbXBvPwpgYGB7cn0KQVt3aGljaC5tYXgoQSR0ZW1wbyksIDE6NV0gI1dhbm5hIEJlIFN0YXJ0aW4nIFNvbWV0aGluJwpgYGAKPGJyPgoKLSAtIC0KCiMjIyAyIOW7uueri+aooeWeiyBDcmVhdGluZyBPdXIgUHJlZGljdGlvbiBNb2RlbAoKV2Ugd2lzaCB0byBwcmVkaWN0IHdoZXRoZXIgb3Igbm90IGEgc29uZyB3aWxsIG1ha2UgaXQgdG8gdGhlIFRvcCAxMC4gVG8gZG8gdGhpcywgZmlyc3QgdXNlIHRoZSBzdWJzZXQgZnVuY3Rpb24gdG8gc3BsaXQgdGhlIGRhdGEgaW50byBhIHRyYWluaW5nIHNldCAiU29uZ3NUcmFpbiIgY29uc2lzdGluZyBvZiBhbGwgdGhlIG9ic2VydmF0aW9ucyB1cCB0byBhbmQgaW5jbHVkaW5nIDIwMDkgc29uZyByZWxlYXNlcywgYW5kIGEgdGVzdGluZyBzZXQgIlNvbmdzVGVzdCIsIGNvbnNpc3Rpbmcgb2YgdGhlIDIwMTAgc29uZyByZWxlYXNlcy4KCuOAkCoqMi4xIOS+neaZgumWk+WIhuWJsuizh+aWmSoq44CRSG93IG1hbnkgb2JzZXJ2YXRpb25zIChzb25ncykgYXJlIGluIHRoZSB0cmFpbmluZyBzZXQ/CmBgYHtyfQpUUiA9IHN1YnNldChBLEEkeWVhciA8PSAyMDA5KQpUUyA9IHN1YnNldChBLEEkeWVhciA9PSAyMDEwKQoKbnJvdyhUUikKCmBgYAoK44CQKioyLjIg5bu656uL5qih5Z6L44CB5qih5Z6L5pGY6KaBKirjgJFXaGF0IGlzIHRoZSB2YWx1ZSBvZiB0aGUgQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbiAoQUlDKT8KYGBge3J9Cm5vbnZhcnMgPSBjKCJ5ZWFyIiwgInNvbmd0aXRsZSIsICJhcnRpc3RuYW1lIiwgInNvbmdJRCIsICJhcnRpc3RJRCIpCiPljrvpmaTpnZ5udW1lcmlj55qE5bGs5oCnClRSID0gVFJbICwgIShuYW1lcyhUUikgJWluJSBub252YXJzKSBdClRTID0gVFNbICwgIShuYW1lcyhUUykgJWluJSBub252YXJzKSBdCgpnbG0xID0gZ2xtKFRvcDEwfi4sVFIsZmFtaWx5ID0gYmlub21pYWwoKSkKc3VtbWFyeShnbG0xKSAjQUlDID0gNDgyNwpgYGAKCuOAkCoqMi4zIOaooeWei+S/guaVuOWIpOiugCoq44CRVGhlIGBMT1dFUmAgb3IgYEhJR0hFUmAgb3VyIGNvbmZpZGVuY2UgYWJvdXQgdGltZSBzaWduYXR1cmUsIGtleSBhbmQgdGVtcG8sIHRoZSBtb3JlIGxpa2VseSB0aGUgc29uZyBpcyB0byBiZSBpbiB0aGUgVG9wIDEwCmBgYHtyfQojSElHSEVSIOWboOeCumVzdGltYXRl6YO95piv5q2j55qEIApgYGAKCuOAkCoqMi40IOmAsuihjOaOqOirlioq44CRV2hhdCBkb2VzIE1vZGVsIDEgc3VnZ2VzdCBpbiB0ZXJtcyBvZiBjb21wbGV4aXR5PwpgYGB7cn0KI01haW5zdHJlYW0gbGlzdGVuZXJzIHRlbmQgdG8gcHJlZmVyIGxlc3MgY29tcGxleCBzb25ncwojc2lnbmF0dXJlLGtleSx0ZW1wb+eahGNvbmZpZGVuY2XkvY7vvIzku6PooajmrYznmoTopIfpm5zluqbpq5jjgILkvYbmqKHlnovpoa/npLpjb25maWRlbmNl6auY77yM6LaK6IO96YCy5YWldG9wMTDvvIzku6PooajlpKfnnL7ovIPllpzmhJvkuI3opIfpm5znmoTmrYwKCiM/IOS7gOm6vOaYr2NvbmZpZGVuY3QKYGBgCgrjgJAqKjIuNSDmqqLmn6XnlbDluLjkv4LmlbgqKuOAkSAKU29uZ3Mgd2l0aCBoZWF2aWVyIGluc3RydW1lbnRhdGlvbiB0ZW5kIHRvIGJlIGxvdWRlciAoaGF2ZSBoaWdoZXIgdmFsdWVzIGluIHRoZSB2YXJpYWJsZSAibG91ZG5lc3MiKSBhbmQgbW9yZSBlbmVyZ2V0aWMgKGhhdmUgaGlnaGVyIHZhbHVlcyBpbiB0aGUgdmFyaWFibGUgImVuZXJneSIpLgoKKGEpIEJ5IGluc3BlY3RpbmcgdGhlIGNvZWZmaWNpZW50IG9mIHRoZSB2YXJpYWJsZSAibG91ZG5lc3MiLCB3aGF0IGRvZXMgTW9kZWwgMSBzdWdnZXN0PyAoYikgQnkgaW5zcGVjdGluZyB0aGUgY29lZmZpY2llbnQgb2YgdGhlIHZhcmlhYmxlICJlbmVyZ3kiLCBkbyB3ZSBkcmF3IHRoZSBzYW1lIGNvbmNsdXNpb25zIGFzIGFib3ZlPwpgYGB7cn0KI2xvdWRuZXNz55qEZXN0aW1hdGXngrrmraMKI2VuZXJneeeahGVzaW1hdGXngrrosqAKCiMoYSkgTWFpbnN0cmVhbSBsaXN0ZW5lcnMgcHJlZmVyIHNvbmdzIHdpdGggaGVhdnkgaW5zdHJ1bWVudGF0aW9uCiMoYikg6IiHYeebuOWPjQoKYGBgCjxicj4KCi0gLSAtCgojIyMgMyDomZXnkIblhbHnt5rmgKcgQmV3YXJlIG9mIE11bHRpY29sbGluZWFyaXR5IElzc3VlcyEKCuOAkCoqMy4xIOaqouafpeebuOmXnOS/guaVuCoq44CRV2hhdCBpcyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBgbG91ZG5lc3NgIGFuZCBgZW5lcmd5YCBpbiB0aGUgdHJhaW5pbmcgc2V0PwpgYGB7cn0KY29yKFRSJGxvdWRuZXNzLFRSJGVuZXJneSkKCmBgYAoKQ3JlYXRlIE1vZGVsIDIsIHdoaWNoIGlzIE1vZGVsIDEgd2l0aG91dCB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUgImxvdWRuZXNzIi4gVGhpcyBjYW4gYmUgZG9uZSB3aXRoIHRoZSBmb2xsb3dpbmcgY29tbWFuZDoKCiAgICBTb25nc0xvZzIgPSBnbG0oVG9wMTAgfiAuIC0gbG91ZG5lc3MsIGRhdGE9U29uZ3NUcmFpbiwgZmFtaWx5PWJpbm9taWFsKQoKV2UganVzdCBzdWJ0cmFjdGVkIHRoZSB2YXJpYWJsZSBsb3VkbmVzcy4gV2UgY291bGRuJ3QgZG8gdGhpcyB3aXRoIHRoZSB2YXJpYWJsZXMgInNvbmd0aXRsZSIgYW5kICJhcnRpc3RuYW1lIiwgYmVjYXVzZSB0aGV5IGFyZSBub3QgbnVtZXJpYyB2YXJpYWJsZXMsIGFuZCB3ZSBtaWdodCBnZXQgZGlmZmVyZW50IHZhbHVlcyBpbiB0aGUgdGVzdCBzZXQgdGhhdCB0aGUgdHJhaW5pbmcgc2V0IGhhcyBuZXZlciBzZWVuLiBCdXQgdGhpcyBhcHByb2FjaCAoc3VidHJhY3RpbmcgdGhlIHZhcmlhYmxlIGZyb20gdGhlIG1vZGVsIGZvcm11bGEpIHdpbGwgYWx3YXlzIHdvcmsgd2hlbiB5b3Ugd2FudCB0byByZW1vdmUgbnVtZXJpYyB2YXJpYWJsZXMuCgpMb29rIGF0IHRoZSBzdW1tYXJ5IG9mIFNvbmdzTG9nMiwgYW5kIGluc3BlY3QgdGhlIGNvZWZmaWNpZW50IG9mIHRoZSB2YXJpYWJsZSAiZW5lcmd5Ii4gV2hhdCBkbyB5b3Ugb2JzZXJ2ZT8KCuOAkCoqMy4yIOmHjeaWsOW7uueri+aooeWei+OAgeaqouafpeS/guaVuCoq44CRTG9vayBhdCB0aGUgc3VtbWFyeSBvZiBTb25nc0xvZzIsIGFuZCBpbnNwZWN0IHRoZSBjb2VmZmljaWVudCBvZiB0aGUgdmFyaWFibGUgImVuZXJneSIuIFdoYXQgZG8geW91IG9ic2VydmU/CmBgYHtyfQpsbTIgPSBnbG0oVG9wMTB+Li1sb3VkbmVzcyxkYXRhPSBUUixmYW1pbHkgPSBiaW5vbWlhbCkKI+S7pVRvcDEw5YW25LuW5YWo6YOo5bGs5oCn54K6aW5kZXBlbmRlbnQgdmFy77yI5rib5Y67bG91ZG5lc3PvvIkKc3VtbWFyeShsbTIpCiNNb2RlbCAyIHN1Z2dlc3RzIHRoYXQgc29uZ3Mgd2l0aCBoaWdoIGVuZXJneSBsZXZlbHMgdGVuZCB0byBiZSBtb3JlIHBvcHVsYXIuIFRoaXMgY29udHJhZGljdHMgb3VyIG9ic2VydmF0aW9uIGluIE1vZGVsIDEuCgojZW5lcmd555qEZXN0aW1hdGXngrrmraPvvIzkvYbmspLmnInpoa/okZcKCmBgYAoK44CQKiozLjMg6YG45pOH5qih5Z6LKirjgJEgCk5vdywgY3JlYXRlIE1vZGVsIDMsIHdoaWNoIHNob3VsZCBiZSBleGFjdGx5IGxpa2UgTW9kZWwgMSwgYnV0IHdpdGhvdXQgdGhlIHZhcmlhYmxlICJlbmVyZ3kiLgoKTG9vayBhdCB0aGUgc3VtbWFyeSBvZiBNb2RlbCAzIGFuZCBpbnNwZWN0IHRoZSBjb2VmZmljaWVudCBvZiB0aGUgdmFyaWFibGUgImxvdWRuZXNzIi4gUmVtZW1iZXJpbmcgdGhhdCBoaWdoZXIgbG91ZG5lc3MgYW5kIGVuZXJneSBib3RoIG9jY3VyIGluIHNvbmdzIHdpdGggaGVhdmllciBpbnN0cnVtZW50YXRpb24sIGRvIHdlIG1ha2UgdGhlIHNhbWUgb2JzZXJ2YXRpb24gYWJvdXQgdGhlIHBvcHVsYXJpdHkgb2YgaGVhdnkgaW5zdHJ1bWVudGF0aW9uIGFzIHdlIGRpZCB3aXRoIE1vZGVsIDI/CgpkbyB3ZSBtYWtlIHRoZSBzYW1lIG9ic2VydmF0aW9uIGFib3V0IHRoZSBwb3B1bGFyaXR5IG9mIGhlYXZ5IGluc3RydW1lbnRhdGlvbiBhcyB3ZSBkaWQgd2l0aCBNb2RlbCAyPwpgYGB7cn0KbG0zID0gZ2xtKFRvcDEwfi4gLWVuZXJneSxkYXRhID0gVFIgLCBmYW1pbHkgPSBiaW5vbWlhbCkKc3VtbWFyeShsbTMpCiNsb3VkbmVzcyDpoa/okZfvvIxlc3RpbWF0ZeeCuuatowojWWVzCmBgYAo8YnI+CgotIC0gLQoKIyMjIDQg6amX6K2J5qih5Z6LIFZhbGlkYXRpbmcgT3VyIE1vZGVsCgrjgJAqKjQuMSDmraPnorrmgKcqKuOAkVdoYXQgaXMgdGhlIGFjY3VyYWN5IG9mIE1vZGVsIDMgb24gdGhlIHRlc3Qgc2V0LCB1c2luZyBhIHRocmVzaG9sZCBvZiAwLjQ1PyAKYGBge3J9CnByZWQgPSBwcmVkaWN0KGxtMywgbmV3ZGF0YT1UUywgdHlwZT0icmVzcG9uc2UiKSAKI3R5cGU9ICJyZXNwb25zZSIg5Luj6KGob3V0cHV054K65qmf546HCgoKeCA9IHRhYmxlKGFjdHVhbCA9IFRTJFRvcDEwLCBwcmVkaWN0ID0gcHJlZCA+PSAwLjQ1KTsgeAojY29uZnVzaW9uIG1hdHJpeCxhY3R1cmFs5ZKMcHJlZGljdOeCum1hdHJpeOS4iuOAgeW3puWQjeeosQojdGhyZXNob2xkIDAuNDXvvIzku6Pooag+MC40NeaJjeacg+iiq+imlueCunk9MQoKI0FDQyA9IFROK1RQL+WFqOmDqApkaWFnKHgpICPlm57lgrPnn6npmaPlsI3op5IgMzA5LDE5CnN1bShkaWFnKHgpKS9zdW0oeCkgICMgQUNDID0gMC44Nzk0IAoKCmBgYAoK44CQKio0LjIg5bqV57ea5q2j56K6546HKirjgJFXaGF0IHdvdWxkIHRoZSBhY2N1cmFjeSBvZiB0aGUgYmFzZWxpbmUgbW9kZWwgYmUgb24gdGhlIHRlc3Qgc2V0PyA/IApgYGB7cn0KI3RhYmxlKFRTJFRvcDEwKQoxIC0gbWVhbihUUyRUb3AxMCkKIz8g54K65LuA6bq855u05o6l5ribbWVhbgoKYGBgCgrjgJAqKjQuMyDmraPnorrmgKcgdnMuIOi+qOitmOeOhyoq44CRSG93IG1hbnkgc29uZ3MgZG9lcyBNb2RlbCAzIGNvcnJlY3RseSBwcmVkaWN0IGFzIFRvcCAxMCBoaXRzIGluIDIwMTA/ICBIb3cgbWFueSBub24taGl0IHNvbmdzIGRvZXMgTW9kZWwgMyBwcmVkaWN0IHdpbGwgYmUgVG9wIDEwIGhpdHM/CmBgYHtyfQojbG0z5ZyodGVzdGluZyBkYXRh55qEVFAgPSAxOSwgRlAgPSA1CgpgYGAKCuOAkCoqUSoq44CR5LiN6IO95aSn5bmF5bqm5aKe5Yqg5q2j56K65oCn55qE5qih5Z6L5Lmf5pyD5pyJ55So5ZeO77yf54K655Sa6bq877yfCgrmiJHoqo3ngrpBQ0PkuI3mmK/kuIDlgIvlvojlpb3ku6PooajmqKHlnovlpb3lo57nmoTmjIfmqJnvvIzmiYDku6XkuI3og73lpKfluYXlop7liqDmh4noqbLkuZ/mspLpl5zkv4IKCuOAkCoqNC40IOaVj+aEn+aApyAmIOaYjueiuuaApyoq44CRV2hhdCBpcyB0aGUgYHNlbnNpdGl2aXR5YCBhbmQgYHNwZWNpZmljaXR5YCBvZiBNb2RlbCAzIG9uIHRoZSB0ZXN0IHNldCwgdXNpbmcgYSB0aHJlc2hvbGQgb2YgMC40NT8KYGBge3J9CiNzZW5zaXRpdml0eSA9IFRQL1RQK0ZOKOWcqOWvpumam+S4iueCujHnmoTni4Dms4HkuIvmib7liLDku5bnmoTmqZ/njocpCnNlbiA9IDE5IC8gKDE5KzQwKSA7IHNlbgoKI3NwZWNpZmljaXR5ID0gVE4vVE4rRlAKc3BlYyA9IDMwOSAvICgzMDkrNSkgOyBzcGVjCgpgYGAKCuOAkCoqNC41IOe1kOirlioq44CRV2hhdCBjb25jbHVzaW9ucyBjYW4geW91IG1ha2UgYWJvdXQgb3VyIG1vZGVsPwpgYGB7cn0KI01vZGVsIDMgaGFzIGEgdmVyeSBoaWdoIHNwZWNpZmljaXR5LCBtZWFuaW5nIHRoYXQgaXQgZmF2b3JzIHNwZWNpZmljaXR5IG92ZXIgc2Vuc2l0aXZpdHkuIFdoaWxlIE1vZGVsIDMgb25seSBjYXB0dXJlcyBsZXNzIHRoYW4gaGFsZiBvZiB0aGUgVG9wIDEwIHNvbmdzLCBpdCBzdGlsbCBjYW4gb2ZmZXIgYSBjb21wZXRpdGl2ZSBlZGdlLCBzaW5jZSBpdCBpcyB2ZXJ5IGNvbnNlcnZhdGl2ZSBpbiBpdHMgcHJlZGljdGlvbnMuCgojbW9kZWwz5pyJ6LyD6auY55qEc3BlY2lmaWNpdHkKI+S9hnNlbnNpdGl2aXR55Y+q5pyJMC4zMu+8jOS4jeWIsDAuNe+8jOS7o+ihqOS7luWPquaKk+S4jeWIsOS4gOWNiueahFRPUDEw5q2M5puyCgpgYGAKCjxicj4KCuOAkCoqUSoq44CR5b6e6YCZ5YCL57WQ6KuW5oiR5YCR5a245Yiw5LuA6bq877yfCgoKLSAtIC0KCjxicj48YnI+PGJyPgo=