# 載入所需的套件(Loading package)
library(dplyr)
library(plyr)
library(ggplot2)
library(readr)
library(reshape)
library(ROCR)
library(caret)
library(randomForest)
library(pROC)
# 更改R的預設語系
Sys.setlocale("LC_ALL",'C')      
[1] "C"



資料前處理



(處理後)資料集資訊



載入資料集(Loading dataset):[LOLgamedata.csv]

我們透過組員自身的遊戲經驗,挑出我們認為較顯著之資料欄位進行變數型態轉換

lol <- read.csv("LOLgamedata.csv",header = T)
# View(lol)
# 將欄位進行型態轉換(transfer our data as factor)
lol$winner <- as.factor(lol$winner)
lol$firstBlood <- as.factor(lol$firstBlood)
lol$firstTower <- as.factor(lol$firstTower)
lol$firstInhibitor <- as.factor(lol$firstInhibitor)
lol$firstBaron <- as.factor(lol$firstBaron)
lol$firstDragon <- as.factor(lol$firstDragon)
lol$firstRiftHerald <- as.factor(lol$firstRiftHerald)



新增變數

lol$tower_gap <- (lol$t1_towerKills - lol$t2_towerKills)                              # 勝負隊伍塔差
# lol_train$tower_gap <- (lol_train$t1_towerKills - lol_train$t2_towerKills)
# summary(glm(winner ~ lol_train$tower_gap, data= lol_train, family = "binomial"))
lol$dragon_gap <- (lol$t1_dragonKills - lol$t2_dragonKills)                           # 勝負隊伍殺小龍數量差異
lol$baron_gap <- (lol$t1_baronKills - lol$t2_baronKills)                              # 勝負隊伍殺巴隆數量差異
lol$inhibitorKills_gap <- (lol$t1_inhibitorKills - lol$t2_inhibitorKills)             # 勝負隊伍水晶兵營數量差異



邏輯式迴歸(glm)

# 將資料切割成Training Set(lol_train), Testing Set(lol_test)
set.seed(2018)
train_idx <- sample(1:nrow(lol), size = 0.8 * nrow(lol), replace = F)
lol_train <- lol[train_idx,] 
lol_test <- lol[-train_idx,] 
summary(glm(winner ~ firstBlood + firstTower + firstInhibitor + firstBaron + firstDragon + firstRiftHerald, data = lol_train, family = "binomial"))

Call:
glm(formula = winner ~ firstBlood + firstTower + firstInhibitor + 
    firstBaron + firstDragon + firstRiftHerald, family = "binomial", 
    data = lol_train)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-2.9057  -0.3409  -0.1809   0.3495   2.8710  

Coefficients:
                 Estimate Std. Error z value Pr(>|z|)    
(Intercept)      -0.72064    0.11624  -6.199 5.67e-10 ***
firstBlood2       0.28354    0.03497   8.108 5.14e-16 ***
firstTower2       0.82213    0.03631  22.644  < 2e-16 ***
firstInhibitor1  -2.02436    0.05042 -40.153  < 2e-16 ***
firstInhibitor2   1.91971    0.05078  37.805  < 2e-16 ***
firstBaron1      -0.91436    0.04685 -19.518  < 2e-16 ***
firstBaron2       1.18904    0.04549  26.141  < 2e-16 ***
firstDragon1     -0.26268    0.11836  -2.219   0.0265 *  
firstDragon2      0.54305    0.11849   4.583 4.58e-06 ***
firstRiftHerald1 -0.18285    0.04329  -4.224 2.40e-05 ***
firstRiftHerald2  0.16980    0.04365   3.890   0.0001 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 55288  on 39883  degrees of freedom
Residual deviance: 23077  on 39873  degrees of freedom
AIC: 23099

Number of Fisher Scoring iterations: 6
# 預測(glm prediction)(common sense)
model1 <- glm(winner ~ firstBlood + firstTower + firstInhibitor + firstBaron + firstDragon + firstRiftHerald, data = lol_train ,family = "binomial")
result <- predict(model1,newdata = lol_test, type = "response")
table(lol_test$winner, result>0.5) %>% {sum(diag(.))/sum(.)}         # ACC = 0.9044324
[1] 0.9044324
# 預測(glm prediction)(加入towel_gap)
model1 <- glm(winner ~ firstBlood + firstTower + firstInhibitor + firstBaron + firstDragon + firstRiftHerald + tower_gap, data = lol_train ,family = "binomial")
result <- predict(model1,newdata = lol_test, type = "response")
table(lol_test$winner, result>0.5) %>% {sum(diag(.))/sum(.)}         # ACC = 0.9736262
[1] 0.9736262
# 預測(glm prediction)(加入towel_gap,並拿掉不顯著之變數)
model1 <- glm(winner ~ firstTower + firstInhibitor + firstRiftHerald + tower_gap, data = lol_train ,family = "binomial")
result <- predict(model1,newdata = lol_test, type = "response")
table(lol_test$winner, result>0.5) %>% {sum(diag(.))/sum(.)}         # ACC = 0.9731247
[1] 0.9731247
# 預測(glm prediction)(加入towel_gap, dragon_gap, baron_gap, inhibitorKills_gap, gameDuration)
model1 <- glm(winner ~ firstBlood + firstTower + firstInhibitor + firstBaron + firstDragon + firstRiftHerald + tower_gap + dragon_gap + baron_gap + inhibitorKills_gap + gameDuration, data = lol_train ,family = "binomial")
result <- predict(model1,newdata = lol_test, type = "response")
table(lol_test$winner, result>0.5) %>% {sum(diag(.))/sum(.)}         # ACC = 0.9742278
[1] 0.9742278
summary(model1)

Call:
glm(formula = winner ~ firstBlood + firstTower + firstInhibitor + 
    firstBaron + firstDragon + firstRiftHerald + tower_gap + 
    dragon_gap + baron_gap + inhibitorKills_gap + gameDuration, 
    family = "binomial", data = lol_train)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-3.8432  -0.0338  -0.0023   0.0325   4.7229  

Coefficients:
                   Estimate Std. Error z value Pr(>|z|)    
(Intercept)         0.37382    0.27022   1.383 0.166540    
firstBlood2        -0.12787    0.07033  -1.818 0.069042 .  
firstTower2        -0.87222    0.07553 -11.548  < 2e-16 ***
firstInhibitor1     0.51610    0.13912   3.710 0.000207 ***
firstInhibitor2    -0.58941    0.14017  -4.205 2.61e-05 ***
firstBaron1         0.52945    0.13253   3.995 6.47e-05 ***
firstBaron2        -0.08496    0.13143  -0.646 0.518002    
firstDragon1        0.47420    0.26300   1.803 0.071388 .  
firstDragon2        0.59231    0.26366   2.246 0.024673 *  
firstRiftHerald1    0.22080    0.08751   2.523 0.011634 *  
firstRiftHerald2   -0.59453    0.08857  -6.713 1.91e-11 ***
tower_gap          -1.28958    0.02374 -54.313  < 2e-16 ***
dragon_gap          0.04511    0.02163   2.086 0.037020 *  
baron_gap          -0.62911    0.05491 -11.456  < 2e-16 ***
inhibitorKills_gap  0.10260    0.03776   2.717 0.006591 ** 
gameDuration       -0.01023    0.00544  -1.880 0.060134 .  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 55287.7  on 39883  degrees of freedom
Residual deviance:  5838.7  on 39868  degrees of freedom
AIC: 5870.7

Number of Fisher Scoring iterations: 9



邏輯式迴歸ROC(ROC curve of Logistic Regression)

pred <- prediction(result, lol_test$winner)
perf <- performance(pred, measure = "tpr", x.measure = "fpr")
auc <- performance(pred, "auc")
# 繪製ROC curve之圖形,並算出AUC
plot(perf, main = "ROC curve(Logistic Regression)", xlab = "Specificity(FPR)", ylab = "Sensitivity(TPR)")
abline(0, 1)
text(0.5, 0.5, as.character(auc@y.values[[1]]))           # AUC = 0.9966



邏輯式迴歸交叉驗證(Cross-Validation(CV) of Logistic Regession)

# Get k-fold CV confusion matrix for Logistic Regression model
# f: formula, d: data, k: number of folds, cutoff: cutoff point 0-1
k_fold_CV_logit = function(f, d, k, cutoff){
  numOfRec = nrow(d) # number of observations
  reponse_var = all.vars(f)[1] # name of the response variable
  # k indices used to split data into k parts
  sample_idx_k = rep(sample(1:k),round(numOfRec / k) + 1)[1:numOfRec]
  # k models for k subsets of data
  k_fits = Map( function(x) glm(f, d[sample_idx_k != x, ],
                                family = "binomial"), 1:k)
  # Predicted & actual classes for each hold-out subset
  predActualClass = Map(function(x){
    predictedProb = predict(k_fits[[x]], d[sample_idx_k == x,],
                            type = "response")
    predictedClass = ifelse(predictedProb > cutoff, 1, 0)
    return(data.frame("predictedClass" = predictedClass,
                      "actualClass" = d[sample_idx_k == x, reponse_var] ) )
  }, 1:k)
  # A data frame with all predicted & actual classes
  output_DF = Reduce(function(x, y) rbind(x, y), predActualClass)
  output_DF$predictedClass = factor(output_DF$predictedClass,
                                    levels=c(0,1),labels = c("No", "Yes"))
  return( table(output_DF$predictedClass, output_DF$actualClass))
}
Map(function(cutoff) k_fold_CV_logit(winner ~ firstBlood+firstTower+firstInhibitor+firstBaron+firstDragon+firstRiftHerald,
                                     lol[train_idx,], 10, cutoff), list(0.9, 0.8, 0.7, 0.6, 0.5, 0.45, 0.4, 0.3, 0.2, 0.1)) # 0.5
[[1]]
     
          1     2
  No  19504  7456
  Yes   618 12306

[[2]]
     
          1     2
  No  19129  4829
  Yes   993 14933

[[3]]
     
          1     2
  No  18822  3285
  Yes  1300 16477

[[4]]
     
          1     2
  No  18674  2637
  Yes  1448 17125

[[5]]
     
          1     2
  No  18233  1978
  Yes  1889 17784

[[6]]
     
          1     2
  No  17860  1664
  Yes  2262 18098

[[7]]
     
          1     2
  No  17692  1587
  Yes  2430 18175

[[8]]
     
          1     2
  No  16964  1335
  Yes  3158 18427

[[9]]
     
          1     2
  No  15230   975
  Yes  4892 18787

[[10]]
     
          1     2
  No  12439   526
  Yes  7683 19236



隨機森林(randomForest)

# 試藉由組員自身遊戲經驗所找出之變數跑randomForest
set.seed(2018)
lol_tree <- randomForest(winner ~ firstBlood + firstTower + firstInhibitor + firstBaron + firstDragon + firstRiftHerald, lol_train, ntree = 500)
result_tree <- predict(lol_tree,newdata = lol_test)
lol_tree

Call:
 randomForest(formula = winner ~ firstBlood + firstTower + firstInhibitor +      firstBaron + firstDragon + firstRiftHerald, data = lol_train,      ntree = 500) 
               Type of random forest: classification
                     Number of trees: 500
No. of variables tried at each split: 2

        OOB estimate of  error rate: 9.36%
Confusion matrix:
      1     2 class.error
1 18342  1780  0.08846039
2  1954 17808  0.09887663
    # Confusion matrix:
    #       1     2 class.error
    # 1 18345  1777  0.08831130
    # 2  1973 17789  0.09983807
# 透過importance()來找出較重要之變數
importance(lol_tree)
                MeanDecreaseGini
firstBlood               49.4587
firstTower             1481.5744
firstInhibitor         8485.8823
firstBaron             2454.6815
firstDragon             718.0792
firstRiftHerald         210.8131
    #                 MeanDecreaseGini
    # firstTower            1059.24050
    # firstInhibitor        9253.06155
    # firstBaron            2451.38878
    # firstDragon            745.84541
    # firstRiftHerald         91.45326 (最低)
# 移除firstRiftHerald變數,再次進行建模
lol_tree <- randomForest(winner ~ firstTower+firstInhibitor+firstBaron+firstDragon+firstRiftHerald,lol_train, ntree=500)
result_tree <- predict(lol_tree,newdata = lol_test)
lol_tree

Call:
 randomForest(formula = winner ~ firstTower + firstInhibitor +      firstBaron + firstDragon + firstRiftHerald, data = lol_train,      ntree = 500) 
               Type of random forest: classification
                     Number of trees: 500
No. of variables tried at each split: 2

        OOB estimate of  error rate: 9.42%
Confusion matrix:
      1     2 class.error
1 18316  1806  0.08975251
2  1953 17809  0.09882603
    # Confusion matrix:
    #       1     2 class.error
    # 1 18322  1800  0.08945433
    # 2  1966 17796  0.09948386
# 預測(randomForest prediction)(加入towel_gap, dragon_gap, baron_gap, inhibitorKills_gap, gameDuration)
lol_tree <- randomForest(winner ~ firstBlood + firstTower + firstInhibitor + firstBaron + firstDragon + firstRiftHerald + tower_gap + dragon_gap + baron_gap + inhibitorKills_gap + gameDuration,lol_train, ntree = 500)
result_tree <- predict(lol_tree,newdata = lol_test)
lol_tree

Call:
 randomForest(formula = winner ~ firstBlood + firstTower + firstInhibitor +      firstBaron + firstDragon + firstRiftHerald + tower_gap +      dragon_gap + baron_gap + inhibitorKills_gap + gameDuration,      data = lol_train, ntree = 500) 
               Type of random forest: classification
                     Number of trees: 500
No. of variables tried at each split: 3

        OOB estimate of  error rate: 2.4%
Confusion matrix:
      1     2 class.error
1 19649   473  0.02350661
2   484 19278  0.02449145
summary(lol_tree)
                Length Class  Mode     
call                4  -none- call     
type                1  -none- character
predicted       39884  factor numeric  
err.rate         1500  -none- numeric  
confusion           6  -none- numeric  
votes           79768  matrix numeric  
oob.times       39884  -none- numeric  
classes             2  -none- character
importance         11  -none- numeric  
importanceSD        0  -none- NULL     
localImportance     0  -none- NULL     
proximity           0  -none- NULL     
ntree               1  -none- numeric  
mtry                1  -none- numeric  
forest             14  -none- list     
y               39884  factor numeric  
test                0  -none- NULL     
inbag               0  -none- NULL     
terms               3  terms  call     



隨機森林ROC(ROC curve of Random Forest)

# 繪製隨機森林的ROC曲線,繪製ROC curve之圖形,並算出AUC
rf.pred <- predict(lol_tree, lol_test, type = "prob")
rf.roc <- prediction(rf.pred[,2], lol_test$winner)
rf.auc <- performance(rf.roc, 'tpr', 'fpr')
# rf.auc
plot(rf.auc)
abline(0, 1)

# text(0.5, 0.5, as.character(rf.auc@y.values[[1]]))  



邏輯式迴歸與隨機森林在ROC曲線與AUC之比較

# 將邏輯式迴歸跟隨機森林所繪製出之ROC曲線進行比較
layout(matrix(c(1,2),1,2,byrow = F))
# 邏輯式迴歸
plot(perf, main = "ROC curve", xlab = "False positive rate", ylab = "True positive rate")
abline(0, 1)
text(0.5, 0.5, as.character(auc@y.values[[1]]))           # AUC = 0.9408
# 隨機森林
plot(rf.auc)
abline(0, 1)



計算平均平方誤差MSE(Mean Square Error)

# mean((result-lol_test$winner)^2)
dim(lol_test)       #  9972    71
[1] 9972   75
dim(lol_train)      # 39884    71
[1] 39884    75
summary(model1)

Call:
glm(formula = winner ~ firstBlood + firstTower + firstInhibitor + 
    firstBaron + firstDragon + firstRiftHerald + tower_gap + 
    dragon_gap + baron_gap + inhibitorKills_gap + gameDuration, 
    family = "binomial", data = lol_train)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-3.8432  -0.0338  -0.0023   0.0325   4.7229  

Coefficients:
                   Estimate Std. Error z value Pr(>|z|)    
(Intercept)         0.37382    0.27022   1.383 0.166540    
firstBlood2        -0.12787    0.07033  -1.818 0.069042 .  
firstTower2        -0.87222    0.07553 -11.548  < 2e-16 ***
firstInhibitor1     0.51610    0.13912   3.710 0.000207 ***
firstInhibitor2    -0.58941    0.14017  -4.205 2.61e-05 ***
firstBaron1         0.52945    0.13253   3.995 6.47e-05 ***
firstBaron2        -0.08496    0.13143  -0.646 0.518002    
firstDragon1        0.47420    0.26300   1.803 0.071388 .  
firstDragon2        0.59231    0.26366   2.246 0.024673 *  
firstRiftHerald1    0.22080    0.08751   2.523 0.011634 *  
firstRiftHerald2   -0.59453    0.08857  -6.713 1.91e-11 ***
tower_gap          -1.28958    0.02374 -54.313  < 2e-16 ***
dragon_gap          0.04511    0.02163   2.086 0.037020 *  
baron_gap          -0.62911    0.05491 -11.456  < 2e-16 ***
inhibitorKills_gap  0.10260    0.03776   2.717 0.006591 ** 
gameDuration       -0.01023    0.00544  -1.880 0.060134 .  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 55287.7  on 39883  degrees of freedom
Residual deviance:  5838.7  on 39868  degrees of freedom
AIC: 5870.7

Number of Fisher Scoring iterations: 9



【敘述統計】 欲瞭解當獲勝方為藍方時,閃現(flash)放在D鍵與F鍵的比例

summary(glm(winner ~ firstDragon, data= lol_train, family = "binomial"))

Call:
glm(formula = winner ~ firstDragon, family = "binomial", data = lol_train)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.4984  -0.8730  -0.8730   0.8873   1.5161  

Coefficients:
             Estimate Std. Error z value Pr(>|z|)    
(Intercept)  -0.27006    0.08775  -3.078  0.00209 ** 
firstDragon1 -0.49825    0.08908  -5.593 2.23e-08 ***
firstDragon2  0.99897    0.08906  11.217  < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 55288  on 39883  degrees of freedom
Residual deviance: 50130  on 39881  degrees of freedom
AIC: 50136

Number of Fisher Scoring iterations: 4
test1 <- subset(lol_train,lol_train$firstDragon!=0)
summary(glm(test1$winner ~ as.factor(test1$firstDragon),family = "binomial"))

Call:
glm(formula = test1$winner ~ as.factor(test1$firstDragon), family = "binomial")

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.4984  -0.8730  -0.8730   0.8873   1.5161  

Coefficients:
                              Estimate Std. Error z value Pr(>|z|)    
(Intercept)                   -0.76831    0.01535  -50.05   <2e-16 ***
as.factor(test1$firstDragon)2  1.49723    0.02159   69.34   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 54555  on 39354  degrees of freedom
Residual deviance: 49406  on 39353  degrees of freedom
AIC: 49410

Number of Fisher Scoring iterations: 4
summary(glm(lol_train$winner ~ lol_train$t1_champ1_sum1,family = "binomial"))

Call:
glm(formula = lol_train$winner ~ lol_train$t1_champ1_sum1, family = "binomial")

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.202  -1.170  -1.150   1.185   1.247  

Coefficients:
                                 Estimate Std. Error z value Pr(>|z|)
(Intercept)                      -0.06454    0.08717  -0.740    0.459
lol_train$t1_champ1_sum1Cleanse  -0.09710    0.20017  -0.485    0.628
lol_train$t1_champ1_sum1Exhaust   0.01274    0.09496   0.134    0.893
lol_train$t1_champ1_sum1Flash     0.04615    0.08821   0.523    0.601
lol_train$t1_champ1_sum1Ghost     0.12308    0.12037   1.022    0.307
lol_train$t1_champ1_sum1Heal      0.06510    0.09337   0.697    0.486
lol_train$t1_champ1_sum1Ignite    0.04496    0.09459   0.475    0.635
lol_train$t1_champ1_sum1Smite     0.04236    0.09317   0.455    0.649
lol_train$t1_champ1_sum1Teleport  0.06080    0.09310   0.653    0.514

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 55288  on 39883  degrees of freedom
Residual deviance: 55285  on 39875  degrees of freedom
AIC: 55303

Number of Fisher Scoring iterations: 3
a <- lol[,c(5,13,16,19,22,25)]
summary(a)
 winner     t1_champ1_sum1   t1_champ2_sum1   t1_champ3_sum1   t1_champ4_sum1   t1_champ5_sum1 
 1:25211   Flash   :27295   Flash   :27144   Flash   :27117   Flash   :27104   Flash   :27085  
 2:24645   Teleport: 4784   Heal    : 4763   Heal    : 4737   Heal    : 4801   Teleport: 4899  
           Smite   : 4556   Smite   : 4626   Smite   : 4649   Smite   : 4519   Smite   : 4636  
           Heal    : 4439   Teleport: 4426   Teleport: 4529   Teleport: 4515   Heal    : 4352  
           Ignite  : 3700   Exhaust : 3770   Exhaust : 3808   Exhaust : 3863   Ignite  : 3794  
           Exhaust : 3544   Ignite  : 3697   Ignite  : 3656   Ignite  : 3668   Exhaust : 3634  
           (Other) : 1538   (Other) : 1430   (Other) : 1360   (Other) : 1386   (Other) : 1456  
b <- lol[,c(5,38,41,44,47,50)]
summary(b)
 winner     t2_champ1_sum1   t2_champ2_sum1   t2_champ3_sum1   t2_champ4_sum1   t2_champ5_sum1 
 1:25211   Flash   :27312   Flash   :27150   Flash   :27280   Flash   :27166   Flash   :26937  
 2:24645   Teleport: 4790   Heal    : 4704   Heal    : 4687   Heal    : 4757   Teleport: 4880  
           Smite   : 4451   Smite   : 4561   Teleport: 4576   Smite   : 4743   Smite   : 4624  
           Heal    : 4325   Teleport: 4533   Smite   : 4470   Teleport: 4456   Heal    : 4428  
           Ignite  : 3799   Exhaust : 3782   Exhaust : 3813   Exhaust : 3734   Ignite  : 3840  
           Exhaust : 3660   Ignite  : 3693   Ignite  : 3642   Ignite  : 3583   Exhaust : 3759  
           (Other) : 1519   (Other) : 1433   (Other) : 1388   (Other) : 1417   (Other) : 1388  
c <- a[a$winner=="1",]
d <- b[b$winner=="1",]
summary(c)
 winner     t1_champ1_sum1   t1_champ2_sum1   t1_champ3_sum1   t1_champ4_sum1   t1_champ5_sum1 
 1:25211   Flash   :13819   Flash   :13715   Flash   :13708   Flash   :13614   Flash   :13681  
 2:    0   Teleport: 2428   Heal    : 2392   Smite   : 2398   Heal    : 2482   Teleport: 2543  
           Smite   : 2296   Smite   : 2296   Heal    : 2381   Smite   : 2310   Smite   : 2334  
           Heal    : 2230   Teleport: 2215   Teleport: 2241   Teleport: 2251   Heal    : 2135  
           Ignite  : 1870   Exhaust : 1940   Exhaust : 1926   Exhaust : 1984   Ignite  : 1926  
           Exhaust : 1792   Ignite  : 1924   Ignite  : 1866   Ignite  : 1832   Exhaust : 1858  
           (Other) :  776   (Other) :  729   (Other) :  691   (Other) :  738   (Other) :  734  
summary(d)
 winner     t2_champ1_sum1   t2_champ2_sum1   t2_champ3_sum1   t2_champ4_sum1   t2_champ5_sum1 
 1:25211   Flash   :13769   Flash   :13727   Flash   :13857   Flash   :13659   Flash   :13572  
 2:    0   Teleport: 2475   Heal    : 2415   Teleport: 2361   Smite   : 2394   Teleport: 2450  
           Smite   : 2249   Smite   : 2295   Heal    : 2330   Heal    : 2363   Smite   : 2394  
           Heal    : 2241   Teleport: 2240   Smite   : 2181   Teleport: 2337   Heal    : 2269  
           Ignite  : 1855   Exhaust : 1926   Exhaust : 1938   Exhaust : 1954   Ignite  : 1939  
           Exhaust : 1841   Ignite  : 1875   Ignite  : 1856   Ignite  : 1810   Exhaust : 1882  
           (Other) :  781   (Other) :  733   (Other) :  688   (Other) :  694   (Other) :  705  
s1 <- 13819 + 13715 + 13708 + 13614 + 13681
s2 <- 13769 + 13727 + 13857 + 13659 + 13572
s1 / (25211 * 5)                                  # 獲勝方為藍方時,將閃現放在D鍵的比例          # 0.5437071
[1] 0.5437071
s2 / (25211 * 5)                                  # 獲勝方為藍方時,將閃現放在F鍵的比例          # 0.54408
[1] 0.54408
LS0tDQp0aXRsZTogIjEwNzHlt6jph4/mnJ/mnKvlsIjmoYgiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQo8YnI+DQoNCi0tLQ0KDQoNCmBgYHtyfQ0KIyDovInlhaXmiYDpnIDnmoTlpZfku7YoTG9hZGluZyBwYWNrYWdlKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KHJlc2hhcGUpDQpsaWJyYXJ5KFJPQ1IpDQpsaWJyYXJ5KGNhcmV0KQ0KbGlicmFyeShyYW5kb21Gb3Jlc3QpDQpsaWJyYXJ5KHBST0MpDQoNCiMg5pu05pS5UueahOmgkOioreiqnuezuw0KU3lzLnNldGxvY2FsZSgiTENfQUxMIiwnQycpICAgICAgDQpgYGANCg0KPGJyPg0KPGJyPg0KKiros4fmlpnliY3omZXnkIYqKg0KDQorIOWwh+inkuiJsuWQjemChOacieWQhOWAi+inkuiJsueahOmhnuWeiyjkvovlpoJzdXBwb3J0562JKeaUvuWFpeizh+aWmembhueVtuS4re+8jOS9huaykuacieS/neeVmeWOn+acieaVuOWtl+eahOmDqOWIhu+8jOS7pemBv+WFjeizh+aWmembhumBjuaWvOa3t+S6guOAgg0KDQorIOWwh2dhbWVEdXJhdGlvbijpgYrmiLLpgLLooYzmmYLplpPnmoTpg6jliIYp5o+b566X5oiQ5Lul44CM5YiG6ZCY44CN54K65Zau5L2N44CCDQoNCisg5Yiq6Zmk5LiN5ZCI55CG55qE5YC877yM5L6L5aaC6aaW5q6654K6MCjku6PooajoqbLloLTpgYrmiLLnhKHkurrmi7/liLDpppbmrropLOesrOS4gOW6p+WhlOeCujAo5Luj6KGo6Kmy5aC06YGK5oiy54Sh5Lq65ou/5Yiw56ys5LiA5bqn5aGUKeS7peWPiumBiuaIsuaZgumWk+WwkeaWvDE15YiG6ZCY55qE6LOH5paZ44CCDQoNCisg55Sx5pa85pys6LOH5paZ6ZuG54Sh5Lu75L2V56m65YC877yM5omA5Lul5rKS5YGa56m65YC855u46Zec6JmV55CG44CCDQoNCmBgYHtyfQ0KYGBgDQoNCjxicj4NCjxicj4NCioqKOiZleeQhuW+jCnos4fmlpnpm4bos4foqIoqKg0KDQorIOWJqeS4izQ5LDg1Nuethijljp/lhYjmnIk1MSw0OTDnrYYpIOOAgg0KDQorIOaWsOWinjEw5YCL5qyE5L2N77yM57i96KiI5YWxNzHlgIvmrITkvY0odDE66JeN5pa544CBdDI657SF5pa577yM6ZuZ5pa55ZCE6ZqK5YiG5YilNeS9jeeOqeWutu+8jOe4veioiOWFsTEw5L2N546p5a6277yM6K6K5pW46Kqq5piO5Zyo5q2k6JmV5LiN6LSF6L+wKe+8mg0KICAgICsgZ2FtZUlkOumBiuaIsue3qOiZnw0KICAgICsgY3JlYXRpb25UaW1lOumBiuaIsuWJteeri+aZgumWkw0KICAgICsgZ2FtZUR1cmF0aW9uOumBiuaIsuaZgumWkw0KICAgICsgc2Vhc29uSWQ656ys5bm+5a2jDQogICAgKyB3aW5uZXI65ZOq5LiA6ZqK6LSPDQogICAgKyBmaXJzdEJsb29kOuWTquS4gOmaiuaLv+WIsOmmluauug0KICAgICsgZmlyc3RUb3dlcjrlk6rkuIDpmormi7/liLDpppbloZQNCiAgICArIGZpcnN0SW5oaWJpdG9yOuWTquS4gOmaiuaLv+WIsOmmluWFteeHnw0KICAgICsgZmlyc3RCYXJvbjrlk6rkuIDpmormi7/liLDpppblt7Tpvo0NCiAgICArIGZpcnN0RHJhZ29uOuWTquS4gOmaiuaLv+WIsOmmluWwj+m+jQ0KICAgICsgZmlyc3RSaWZ0SGVhcmxkOuWTquS4gOmaiuaLv+WIsOmmlumgkOekuuiAhQ0KICAgICsgdDFfY2hhbXAxaWQ66JeN5pa556ys5LiA5YCL6KeS6Imy5ZCN56ixDQogICAgKyB0MV9jaGFtcDFpZF90YWdzOuiXjeaWueesrOS4gOWAi+inkuiJsueorumhng0KICAgICsgdDFfY2hhbXAxX3N1bTHjgIFzdW0yOuiXjeaWueesrOS4gOWAi+inkuiJsuWPrOWWmuW4q+aKgOiDvTHjgIEyDQogICAgKyAuLi4NCiAgICArIHQxX3Rvd2VyS2lsbHM66JeN5pa55ouG5LqG5bm+5YCL5aGUDQogICAgKyB0MV9pbmhpYml0b3JLaWxsczrol43mlrnmi4bkuoblub7lgIvlhbXnh58NCiAgICArIHQxX2Jhcm9uS2lsbHM66JeN5pa55ou/5LqG5bm+6Zq75be06b6NDQogICAgKyB0MV9kcmFnb25LaWxsczrol43mlrnmi7/kuoblub7pmrvlsI/pvo0NCiAgICArIHQxX3JpZnRIZXJhbGRLaWxsczrol43mlrnmi7/kuoblub7pmrvpoJDnpLrogIUNCiAgICArIHQxX2JhbjE66JeN5pa556ys5LiAYmFuDQogICAgKyAuLi4NCiAgICArIHQy5ZCM5LiKDQoNCjxicj4NCjxicj4NCioq6LyJ5YWl6LOH5paZ6ZuGKExvYWRpbmcgZGF0YXNldCnvvJpbTE9MZ2FtZWRhdGEuY3N2XSoqDQoNCuaIkeWAkemAj+mBjue1hOWToeiHqui6q+eahOmBiuaIsue2k+mpl++8jOaMkeWHuuaIkeWAkeiqjeeCuui8g+mhr+iRl+S5i+izh+aWmeashOS9jemAsuihjOiuiuaVuOWei+aFi+i9ieaPmw0KYGBge3J9DQpsb2wgPC0gcmVhZC5jc3YoIkxPTGdhbWVkYXRhLmNzdiIsaGVhZGVyID0gVCkNCg0KIyBWaWV3KGxvbCkNCg0KIyDlsIfmrITkvY3pgLLooYzlnovmhYvovYnmj5sodHJhbnNmZXIgb3VyIGRhdGEgYXMgZmFjdG9yKQ0KbG9sJHdpbm5lciA8LSBhcy5mYWN0b3IobG9sJHdpbm5lcikNCmxvbCRmaXJzdEJsb29kIDwtIGFzLmZhY3Rvcihsb2wkZmlyc3RCbG9vZCkNCmxvbCRmaXJzdFRvd2VyIDwtIGFzLmZhY3Rvcihsb2wkZmlyc3RUb3dlcikNCmxvbCRmaXJzdEluaGliaXRvciA8LSBhcy5mYWN0b3IobG9sJGZpcnN0SW5oaWJpdG9yKQ0KbG9sJGZpcnN0QmFyb24gPC0gYXMuZmFjdG9yKGxvbCRmaXJzdEJhcm9uKQ0KbG9sJGZpcnN0RHJhZ29uIDwtIGFzLmZhY3Rvcihsb2wkZmlyc3REcmFnb24pDQpsb2wkZmlyc3RSaWZ0SGVyYWxkIDwtIGFzLmZhY3Rvcihsb2wkZmlyc3RSaWZ0SGVyYWxkKQ0KYGBgDQoNCjxicj4NCjxicj4NCioq5paw5aKe6K6K5pW4KioNCmBgYHtyfQ0KbG9sJHRvd2VyX2dhcCA8LSAobG9sJHQxX3Rvd2VyS2lsbHMgLSBsb2wkdDJfdG93ZXJLaWxscykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIOWLneiyoOmaiuS8jeWhlOW3rg0KIyBsb2xfdHJhaW4kdG93ZXJfZ2FwIDwtIChsb2xfdHJhaW4kdDFfdG93ZXJLaWxscyAtIGxvbF90cmFpbiR0Ml90b3dlcktpbGxzKQ0KIyBzdW1tYXJ5KGdsbSh3aW5uZXIgfiBsb2xfdHJhaW4kdG93ZXJfZ2FwLCBkYXRhPSBsb2xfdHJhaW4sIGZhbWlseSA9ICJiaW5vbWlhbCIpKQ0KbG9sJGRyYWdvbl9nYXAgPC0gKGxvbCR0MV9kcmFnb25LaWxscyAtIGxvbCR0Ml9kcmFnb25LaWxscykgICAgICAgICAgICAgICAgICAgICAgICAgICAjIOWLneiyoOmaiuS8jeauuuWwj+m+jeaVuOmHj+W3rueVsA0KbG9sJGJhcm9uX2dhcCA8LSAobG9sJHQxX2Jhcm9uS2lsbHMgLSBsb2wkdDJfYmFyb25LaWxscykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIOWLneiyoOmaiuS8jeauuuW3tOmahuaVuOmHj+W3rueVsA0KbG9sJGluaGliaXRvcktpbGxzX2dhcCA8LSAobG9sJHQxX2luaGliaXRvcktpbGxzIC0gbG9sJHQyX2luaGliaXRvcktpbGxzKSAgICAgICAgICAgICAjIOWLneiyoOmaiuS8jeawtOaZtuWFteeHn+aVuOmHj+W3rueVsA0KYGBgDQoNCjxicj4NCjxicj4NCioq6YKP6Lyv5byP6L+05q24KGdsbSkqKg0KYGBge3J9DQojIOWwh+izh+aWmeWIh+WJsuaIkFRyYWluaW5nIFNldChsb2xfdHJhaW4pLCBUZXN0aW5nIFNldChsb2xfdGVzdCkNCnNldC5zZWVkKDIwMTgpDQp0cmFpbl9pZHggPC0gc2FtcGxlKDE6bnJvdyhsb2wpLCBzaXplID0gMC44ICogbnJvdyhsb2wpLCByZXBsYWNlID0gRikNCmxvbF90cmFpbiA8LSBsb2xbdHJhaW5faWR4LF0gDQpsb2xfdGVzdCA8LSBsb2xbLXRyYWluX2lkeCxdIA0Kc3VtbWFyeShnbG0od2lubmVyIH4gZmlyc3RCbG9vZCArIGZpcnN0VG93ZXIgKyBmaXJzdEluaGliaXRvciArIGZpcnN0QmFyb24gKyBmaXJzdERyYWdvbiArIGZpcnN0UmlmdEhlcmFsZCwgZGF0YSA9IGxvbF90cmFpbiwgZmFtaWx5ID0gImJpbm9taWFsIikpDQoNCiMg6aCQ5risKGdsbSBwcmVkaWN0aW9uKShjb21tb24gc2Vuc2UpDQptb2RlbDEgPC0gZ2xtKHdpbm5lciB+IGZpcnN0Qmxvb2QgKyBmaXJzdFRvd2VyICsgZmlyc3RJbmhpYml0b3IgKyBmaXJzdEJhcm9uICsgZmlyc3REcmFnb24gKyBmaXJzdFJpZnRIZXJhbGQsIGRhdGEgPSBsb2xfdHJhaW4gLGZhbWlseSA9ICJiaW5vbWlhbCIpDQpyZXN1bHQgPC0gcHJlZGljdChtb2RlbDEsbmV3ZGF0YSA9IGxvbF90ZXN0LCB0eXBlID0gInJlc3BvbnNlIikNCnRhYmxlKGxvbF90ZXN0JHdpbm5lciwgcmVzdWx0PjAuNSkgJT4lIHtzdW0oZGlhZyguKSkvc3VtKC4pfSAgICAgICAgICMgQUNDID0gMC45MDQ0MzI0DQoNCiMg6aCQ5risKGdsbSBwcmVkaWN0aW9uKSjliqDlhaV0b3dlbF9nYXApDQptb2RlbDEgPC0gZ2xtKHdpbm5lciB+IGZpcnN0Qmxvb2QgKyBmaXJzdFRvd2VyICsgZmlyc3RJbmhpYml0b3IgKyBmaXJzdEJhcm9uICsgZmlyc3REcmFnb24gKyBmaXJzdFJpZnRIZXJhbGQgKyB0b3dlcl9nYXAsIGRhdGEgPSBsb2xfdHJhaW4gLGZhbWlseSA9ICJiaW5vbWlhbCIpDQpyZXN1bHQgPC0gcHJlZGljdChtb2RlbDEsbmV3ZGF0YSA9IGxvbF90ZXN0LCB0eXBlID0gInJlc3BvbnNlIikNCnRhYmxlKGxvbF90ZXN0JHdpbm5lciwgcmVzdWx0PjAuNSkgJT4lIHtzdW0oZGlhZyguKSkvc3VtKC4pfSAgICAgICAgICMgQUNDID0gMC45NzM2MjYyDQoNCiMg6aCQ5risKGdsbSBwcmVkaWN0aW9uKSjliqDlhaV0b3dlbF9nYXAs5Lim5ou/5o6J5LiN6aGv6JGX5LmL6K6K5pW4KQ0KbW9kZWwxIDwtIGdsbSh3aW5uZXIgfiBmaXJzdFRvd2VyICsgZmlyc3RJbmhpYml0b3IgKyBmaXJzdFJpZnRIZXJhbGQgKyB0b3dlcl9nYXAsIGRhdGEgPSBsb2xfdHJhaW4gLGZhbWlseSA9ICJiaW5vbWlhbCIpDQpyZXN1bHQgPC0gcHJlZGljdChtb2RlbDEsbmV3ZGF0YSA9IGxvbF90ZXN0LCB0eXBlID0gInJlc3BvbnNlIikNCnRhYmxlKGxvbF90ZXN0JHdpbm5lciwgcmVzdWx0PjAuNSkgJT4lIHtzdW0oZGlhZyguKSkvc3VtKC4pfSAgICAgICAgICMgQUNDID0gMC45NzMxMjQ3DQoNCiMg6aCQ5risKGdsbSBwcmVkaWN0aW9uKSjliqDlhaV0b3dlbF9nYXAsIGRyYWdvbl9nYXAsIGJhcm9uX2dhcCwgaW5oaWJpdG9yS2lsbHNfZ2FwLCBnYW1lRHVyYXRpb24pDQptb2RlbDEgPC0gZ2xtKHdpbm5lciB+IGZpcnN0Qmxvb2QgKyBmaXJzdFRvd2VyICsgZmlyc3RJbmhpYml0b3IgKyBmaXJzdEJhcm9uICsgZmlyc3REcmFnb24gKyBmaXJzdFJpZnRIZXJhbGQgKyB0b3dlcl9nYXAgKyBkcmFnb25fZ2FwICsgYmFyb25fZ2FwICsgaW5oaWJpdG9yS2lsbHNfZ2FwICsgZ2FtZUR1cmF0aW9uLCBkYXRhID0gbG9sX3RyYWluICxmYW1pbHkgPSAiYmlub21pYWwiKQ0KcmVzdWx0IDwtIHByZWRpY3QobW9kZWwxLG5ld2RhdGEgPSBsb2xfdGVzdCwgdHlwZSA9ICJyZXNwb25zZSIpDQp0YWJsZShsb2xfdGVzdCR3aW5uZXIsIHJlc3VsdD4wLjUpICU+JSB7c3VtKGRpYWcoLikpL3N1bSguKX0gICAgICAgICAjIEFDQyA9IDAuOTc0MjI3OA0KDQpzdW1tYXJ5KG1vZGVsMSkNCmBgYA0KDQo8YnI+DQo8YnI+DQoqKumCj+i8r+W8j+i/tOatuFJPQyhST0MgY3VydmUgb2YgTG9naXN0aWMgUmVncmVzc2lvbikqKg0KYGBge3J9DQpwcmVkIDwtIHByZWRpY3Rpb24ocmVzdWx0LCBsb2xfdGVzdCR3aW5uZXIpDQpwZXJmIDwtIHBlcmZvcm1hbmNlKHByZWQsIG1lYXN1cmUgPSAidHByIiwgeC5tZWFzdXJlID0gImZwciIpDQphdWMgPC0gcGVyZm9ybWFuY2UocHJlZCwgImF1YyIpDQoNCiMg57mq6KO9Uk9DIGN1cnZl5LmL5ZyW5b2i77yM5Lim566X5Ye6QVVDDQpwbG90KHBlcmYsIG1haW4gPSAiUk9DIGN1cnZlKExvZ2lzdGljIFJlZ3Jlc3Npb24pIiwgeGxhYiA9ICJTcGVjaWZpY2l0eShGUFIpIiwgeWxhYiA9ICJTZW5zaXRpdml0eShUUFIpIikNCmFibGluZSgwLCAxKQ0KdGV4dCgwLjUsIDAuNSwgYXMuY2hhcmFjdGVyKGF1Y0B5LnZhbHVlc1tbMV1dKSkgICAgICAgICAgICMgQVVDID0gMC45OTY2DQpgYGANCg0KPGJyPg0KPGJyPg0KKirpgo/ovK/lvI/ov7TmrbjkuqTlj4npqZforYkoQ3Jvc3MtVmFsaWRhdGlvbihDVikgb2YgTG9naXN0aWMgUmVnZXNzaW9uKSoqDQpgYGB7cn0NCiMgR2V0IGstZm9sZCBDViBjb25mdXNpb24gbWF0cml4IGZvciBMb2dpc3RpYyBSZWdyZXNzaW9uIG1vZGVsDQojIGY6IGZvcm11bGEsIGQ6IGRhdGEsIGs6IG51bWJlciBvZiBmb2xkcywgY3V0b2ZmOiBjdXRvZmYgcG9pbnQgMC0xDQprX2ZvbGRfQ1ZfbG9naXQgPSBmdW5jdGlvbihmLCBkLCBrLCBjdXRvZmYpew0KICBudW1PZlJlYyA9IG5yb3coZCkgIyBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zDQogIHJlcG9uc2VfdmFyID0gYWxsLnZhcnMoZilbMV0gIyBuYW1lIG9mIHRoZSByZXNwb25zZSB2YXJpYWJsZQ0KICAjIGsgaW5kaWNlcyB1c2VkIHRvIHNwbGl0IGRhdGEgaW50byBrIHBhcnRzDQogIHNhbXBsZV9pZHhfayA9IHJlcChzYW1wbGUoMTprKSxyb3VuZChudW1PZlJlYyAvIGspICsgMSlbMTpudW1PZlJlY10NCiAgIyBrIG1vZGVscyBmb3IgayBzdWJzZXRzIG9mIGRhdGENCiAga19maXRzID0gTWFwKCBmdW5jdGlvbih4KSBnbG0oZiwgZFtzYW1wbGVfaWR4X2sgIT0geCwgXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gImJpbm9taWFsIiksIDE6aykNCiAgIyBQcmVkaWN0ZWQgJiBhY3R1YWwgY2xhc3NlcyBmb3IgZWFjaCBob2xkLW91dCBzdWJzZXQNCiAgcHJlZEFjdHVhbENsYXNzID0gTWFwKGZ1bmN0aW9uKHgpew0KICAgIHByZWRpY3RlZFByb2IgPSBwcmVkaWN0KGtfZml0c1tbeF1dLCBkW3NhbXBsZV9pZHhfayA9PSB4LF0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJyZXNwb25zZSIpDQogICAgcHJlZGljdGVkQ2xhc3MgPSBpZmVsc2UocHJlZGljdGVkUHJvYiA+IGN1dG9mZiwgMSwgMCkNCiAgICByZXR1cm4oZGF0YS5mcmFtZSgicHJlZGljdGVkQ2xhc3MiID0gcHJlZGljdGVkQ2xhc3MsDQogICAgICAgICAgICAgICAgICAgICAgImFjdHVhbENsYXNzIiA9IGRbc2FtcGxlX2lkeF9rID09IHgsIHJlcG9uc2VfdmFyXSApICkNCiAgfSwgMTprKQ0KICAjIEEgZGF0YSBmcmFtZSB3aXRoIGFsbCBwcmVkaWN0ZWQgJiBhY3R1YWwgY2xhc3Nlcw0KICBvdXRwdXRfREYgPSBSZWR1Y2UoZnVuY3Rpb24oeCwgeSkgcmJpbmQoeCwgeSksIHByZWRBY3R1YWxDbGFzcykNCiAgb3V0cHV0X0RGJHByZWRpY3RlZENsYXNzID0gZmFjdG9yKG91dHB1dF9ERiRwcmVkaWN0ZWRDbGFzcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscz1jKDAsMSksbGFiZWxzID0gYygiTm8iLCAiWWVzIikpDQogIHJldHVybiggdGFibGUob3V0cHV0X0RGJHByZWRpY3RlZENsYXNzLCBvdXRwdXRfREYkYWN0dWFsQ2xhc3MpKQ0KfQ0KDQpNYXAoZnVuY3Rpb24oY3V0b2ZmKSBrX2ZvbGRfQ1ZfbG9naXQod2lubmVyIH4gZmlyc3RCbG9vZCtmaXJzdFRvd2VyK2ZpcnN0SW5oaWJpdG9yK2ZpcnN0QmFyb24rZmlyc3REcmFnb24rZmlyc3RSaWZ0SGVyYWxkLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvbFt0cmFpbl9pZHgsXSwgMTAsIGN1dG9mZiksIGxpc3QoMC45LCAwLjgsIDAuNywgMC42LCAwLjUsIDAuNDUsIDAuNCwgMC4zLCAwLjIsIDAuMSkpICMgMC41DQpgYGANCg0KDQo8YnI+DQo8YnI+DQoqKumaqOapn+ajruaelyhyYW5kb21Gb3Jlc3QpKioNCg0KKyDoqabol4nnlLHntYTlk6Hoh6rouqvpgYrmiLLntpPpqZfmiYDmib7lh7rkuYvorormlbjot5FyYW5kb21Gb3Jlc3QNCiAgICANCiAgICArIOiuiuaVuO+8mmZpcnN0Qmxvb2QsIGZpcnN0VG93ZXIsIGZpcnN0SW5oaWJpdG9yLCBmaXJzdEJhcm9uLCBmaXJzdERyYWdvbiwgZmlyc3RSaWZ0SGVyYWxkLCBsb2xfdHJhaW4NCiAgICANCiAgICArIG50cmVlID0gNTAwDQoNCisg6YCP6YGOaW1wb3J0YW5jZSgp5L6G5om+5Ye66LyD6YeN6KaB5LmL6K6K5pW4DQoNCiAgICArIOeZvOePvmZpcnN0UmlmdEhlcmFsZOiuiuaVuOmHjeimgeW6puacgOS9ju+8jOaVheWYl+ippuenu+mZpGZpcnN0UmlmdEhlcmFsZOiuiuaVuO+8jOWGjeasoemAsuihjOW7uuaooQ0KICAgIA0KICAgICsg6YeN5paw5bu65qih5b6M77yM55m854++6YCP6YGOaW1wb3RhbmNlKCnmiYDmjJHlh7rnmoTorormlbjmiYDoqIjnrpflh7rnmoTntZDmnpzkuKbmspLmnInmr5TovIPlpb0NCiAgICANCisg56K65a6a5qih5Z6L5bu6572uDQpgYGB7cn0NCiMg6Kmm6JeJ55Sx57WE5ZOh6Ieq6Lqr6YGK5oiy57aT6amX5omA5om+5Ye65LmL6K6K5pW46LeRcmFuZG9tRm9yZXN0DQpzZXQuc2VlZCgyMDE4KQ0KbG9sX3RyZWUgPC0gcmFuZG9tRm9yZXN0KHdpbm5lciB+IGZpcnN0Qmxvb2QgKyBmaXJzdFRvd2VyICsgZmlyc3RJbmhpYml0b3IgKyBmaXJzdEJhcm9uICsgZmlyc3REcmFnb24gKyBmaXJzdFJpZnRIZXJhbGQsIGxvbF90cmFpbiwgbnRyZWUgPSA1MDApDQpyZXN1bHRfdHJlZSA8LSBwcmVkaWN0KGxvbF90cmVlLG5ld2RhdGEgPSBsb2xfdGVzdCkNCmxvbF90cmVlDQogICAgIyBDb25mdXNpb24gbWF0cml4Og0KICAgICMgICAgICAgMSAgICAgMiBjbGFzcy5lcnJvcg0KICAgICMgMSAxODM0NSAgMTc3NyAgMC4wODgzMTEzMA0KICAgICMgMiAgMTk3MyAxNzc4OSAgMC4wOTk4MzgwNw0KDQojIOmAj+mBjmltcG9ydGFuY2UoKeS+huaJvuWHuui8g+mHjeimgeS5i+iuiuaVuA0KaW1wb3J0YW5jZShsb2xfdHJlZSkNCiAgICAjICAgICAgICAgICAgICAgICBNZWFuRGVjcmVhc2VHaW5pDQogICAgIyBmaXJzdFRvd2VyICAgICAgICAgICAgMTA1OS4yNDA1MA0KICAgICMgZmlyc3RJbmhpYml0b3IgICAgICAgIDkyNTMuMDYxNTUNCiAgICAjIGZpcnN0QmFyb24gICAgICAgICAgICAyNDUxLjM4ODc4DQogICAgIyBmaXJzdERyYWdvbiAgICAgICAgICAgIDc0NS44NDU0MQ0KICAgICMgZmlyc3RSaWZ0SGVyYWxkICAgICAgICAgOTEuNDUzMjYgKOacgOS9jikNCg0KIyDnp7vpmaRmaXJzdFJpZnRIZXJhbGTorormlbjvvIzlho3mrKHpgLLooYzlu7rmqKENCmxvbF90cmVlIDwtIHJhbmRvbUZvcmVzdCh3aW5uZXIgfiBmaXJzdFRvd2VyK2ZpcnN0SW5oaWJpdG9yK2ZpcnN0QmFyb24rZmlyc3REcmFnb24rZmlyc3RSaWZ0SGVyYWxkLGxvbF90cmFpbiwgbnRyZWU9NTAwKQ0KcmVzdWx0X3RyZWUgPC0gcHJlZGljdChsb2xfdHJlZSxuZXdkYXRhID0gbG9sX3Rlc3QpDQpsb2xfdHJlZQ0KICAgICMgQ29uZnVzaW9uIG1hdHJpeDoNCiAgICAjICAgICAgIDEgICAgIDIgY2xhc3MuZXJyb3INCiAgICAjIDEgMTgzMjIgIDE4MDAgIDAuMDg5NDU0MzMNCiAgICAjIDIgIDE5NjYgMTc3OTYgIDAuMDk5NDgzODYNCg0KIyDpoJDmuKwocmFuZG9tRm9yZXN0IHByZWRpY3Rpb24pKOWKoOWFpXRvd2VsX2dhcCwgZHJhZ29uX2dhcCwgYmFyb25fZ2FwLCBpbmhpYml0b3JLaWxsc19nYXAsIGdhbWVEdXJhdGlvbikNCmxvbF90cmVlIDwtIHJhbmRvbUZvcmVzdCh3aW5uZXIgfiBmaXJzdEJsb29kICsgZmlyc3RUb3dlciArIGZpcnN0SW5oaWJpdG9yICsgZmlyc3RCYXJvbiArIGZpcnN0RHJhZ29uICsgZmlyc3RSaWZ0SGVyYWxkICsgdG93ZXJfZ2FwICsgZHJhZ29uX2dhcCArIGJhcm9uX2dhcCArIGluaGliaXRvcktpbGxzX2dhcCArIGdhbWVEdXJhdGlvbixsb2xfdHJhaW4sIG50cmVlID0gNTAwKQ0KcmVzdWx0X3RyZWUgPC0gcHJlZGljdChsb2xfdHJlZSxuZXdkYXRhID0gbG9sX3Rlc3QpDQpsb2xfdHJlZQ0Kc3VtbWFyeShsb2xfdHJlZSkNCmBgYA0KDQo8YnI+DQo8YnI+DQoqKumaqOapn+ajruael1JPQyhST0MgY3VydmUgb2YgUmFuZG9tIEZvcmVzdCkqKg0KYGBge3J9DQojIOe5quijvemaqOapn+ajruael+eahFJPQ+absue3mu+8jOe5quijvVJPQyBjdXJ2ZeS5i+WcluW9ou+8jOS4pueul+WHukFVQw0KcmYucHJlZCA8LSBwcmVkaWN0KGxvbF90cmVlLCBsb2xfdGVzdCwgdHlwZSA9ICJwcm9iIikNCnJmLnJvYyA8LSBwcmVkaWN0aW9uKHJmLnByZWRbLDJdLCBsb2xfdGVzdCR3aW5uZXIpDQpyZi5hdWMgPC0gcGVyZm9ybWFuY2UocmYucm9jLCAndHByJywgJ2ZwcicpDQojIHJmLmF1Yw0KcGxvdChyZi5hdWMpDQphYmxpbmUoMCwgMSkNCiMgdGV4dCgwLjUsIDAuNSwgYXMuY2hhcmFjdGVyKHJmLmF1Y0B5LnZhbHVlc1tbMV1dKSkgIA0KYGBgDQoNCjxicj4NCjxicj4NCioq6YKP6Lyv5byP6L+05q246IiH6Zqo5qmf5qOu5p6X5ZyoUk9D5puy57ea6IiHQVVD5LmL5q+U6LyDKioNCmBgYHtyfSANCiMg5bCH6YKP6Lyv5byP6L+05q246Lef6Zqo5qmf5qOu5p6X5omA57mq6KO95Ye65LmLUk9D5puy57ea6YCy6KGM5q+U6LyDDQpsYXlvdXQobWF0cml4KGMoMSwyKSwxLDIsYnlyb3cgPSBGKSkNCg0KIyDpgo/ovK/lvI/ov7TmrbgNCnBsb3QocGVyZiwgbWFpbiA9ICJST0MgY3VydmUiLCB4bGFiID0gIkZhbHNlIHBvc2l0aXZlIHJhdGUiLCB5bGFiID0gIlRydWUgcG9zaXRpdmUgcmF0ZSIpDQphYmxpbmUoMCwgMSkNCnRleHQoMC41LCAwLjUsIGFzLmNoYXJhY3RlcihhdWNAeS52YWx1ZXNbWzFdXSkpICAgICAgICAgICAjIEFVQyA9IDAuOTQwOA0KDQojIOmaqOapn+ajruaelw0KcGxvdChyZi5hdWMpDQphYmxpbmUoMCwgMSkNCmBgYA0KDQo8YnI+DQo8YnI+DQoqKuioiOeul+W5s+Wdh+W5s+aWueiqpOW3rk1TRShNZWFuIFNxdWFyZSBFcnJvcikqKg0KYGBge3J9DQojIG1lYW4oKHJlc3VsdC1sb2xfdGVzdCR3aW5uZXIpXjIpDQpkaW0obG9sX3Rlc3QpICAgICAgICMgIDk5NzIgICAgNzENCmRpbShsb2xfdHJhaW4pICAgICAgIyAzOTg4NCAgICA3MQ0Kc3VtbWFyeShtb2RlbDEpDQpgYGANCg0KPGJyPg0KPGJyPg0KKirjgJDmlZjov7DntbHoqIjjgJEqKg0KKirmrLLnnq3op6PnlbbnjbLli53mlrnngrrol43mlrnmmYLvvIzploPnj74oZmxhc2gp5pS+5ZyoROmNteiIh0bpjbXnmoTmr5TkvosqKg0KYGBge3J9DQpzdW1tYXJ5KGdsbSh3aW5uZXIgfiBmaXJzdERyYWdvbiwgZGF0YT0gbG9sX3RyYWluLCBmYW1pbHkgPSAiYmlub21pYWwiKSkNCnRlc3QxIDwtIHN1YnNldChsb2xfdHJhaW4sbG9sX3RyYWluJGZpcnN0RHJhZ29uIT0wKQ0Kc3VtbWFyeShnbG0odGVzdDEkd2lubmVyIH4gYXMuZmFjdG9yKHRlc3QxJGZpcnN0RHJhZ29uKSxmYW1pbHkgPSAiYmlub21pYWwiKSkNCg0Kc3VtbWFyeShnbG0obG9sX3RyYWluJHdpbm5lciB+IGxvbF90cmFpbiR0MV9jaGFtcDFfc3VtMSxmYW1pbHkgPSAiYmlub21pYWwiKSkNCmEgPC0gbG9sWyxjKDUsMTMsMTYsMTksMjIsMjUpXQ0Kc3VtbWFyeShhKQ0KYiA8LSBsb2xbLGMoNSwzOCw0MSw0NCw0Nyw1MCldDQpzdW1tYXJ5KGIpDQpjIDwtIGFbYSR3aW5uZXI9PSIxIixdDQpkIDwtIGJbYiR3aW5uZXI9PSIxIixdDQpzdW1tYXJ5KGMpDQpzdW1tYXJ5KGQpDQpzMSA8LSAxMzgxOSArIDEzNzE1ICsgMTM3MDggKyAxMzYxNCArIDEzNjgxDQpzMiA8LSAxMzc2OSArIDEzNzI3ICsgMTM4NTcgKyAxMzY1OSArIDEzNTcyDQpzMSAvICgyNTIxMSAqIDUpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMg542y5Yud5pa554K66JeN5pa55pmC77yM5bCH6ZaD54++5pS+5ZyoROmNteeahOavlOS+iyAgICAgICAgICAjIDAuNTQzNzA3MQ0KczIgLyAoMjUyMTEgKiA1KSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIOeNsuWLneaWueeCuuiXjeaWueaZgu+8jOWwh+mWg+ePvuaUvuWcqEbpjbXnmoTmr5TkvosgICAgICAgICAgIyAwLjU0NDA4DQpgYGANCg0KYGBge3J9DQoNCmBgYA0KDQo=