主要議題:依顧客屬性做市場區隔

學習重點:

小組討論:

rm(list=ls(all=T))
Sys.setlocale("LC_ALL","C")
[1] "C"
options(digits=4, scipen=12)
library(dplyr)
library(caret)



1. 資料常態化

1.1 資料摘要

Read the dataset AirlinesCluster.csv into R and call it “airlines”. Looking at the summary of airlines,

A = read.csv('data/AirlinesCluster.csv')
summary(A)
    Balance          QualMiles       BonusMiles    
 Min.   :      0   Min.   :    0   Min.   :     0  
 1st Qu.:  18528   1st Qu.:    0   1st Qu.:  1250  
 Median :  43097   Median :    0   Median :  7171  
 Mean   :  73601   Mean   :  144   Mean   : 17145  
 3rd Qu.:  92404   3rd Qu.:    0   3rd Qu.: 23800  
 Max.   :1704838   Max.   :11148   Max.   :263685  
   BonusTrans    FlightMiles     FlightTrans   
 Min.   : 0.0   Min.   :    0   Min.   : 0.00  
 1st Qu.: 3.0   1st Qu.:    0   1st Qu.: 0.00  
 Median :12.0   Median :    0   Median : 0.00  
 Mean   :11.6   Mean   :  460   Mean   : 1.37  
 3rd Qu.:17.0   3rd Qu.:  311   3rd Qu.: 1.00  
 Max.   :86.0   Max.   :30817   Max.   :53.00  
 DaysSinceEnroll
 Min.   :   2   
 1st Qu.:2330   
 Median :4096   
 Mean   :4119   
 3rd Qu.:5790   
 Max.   :8296   
colMeans(A) %>% sort
    FlightTrans      BonusTrans       QualMiles 
          1.374          11.602         144.115 
    FlightMiles DaysSinceEnroll      BonusMiles 
        460.056        4118.559       17144.846 
        Balance 
      73601.328 

which TWO variables have (on average) the smallest values?

  • FlightTrans
  • BonusTrans

Which TWO variables have (on average) the largest values?

  • BonusMiles
  • Balance
1.1小組討論
  • summary看資料四分位數分布
  • colMeans & sort 方便我們看出各個欄位平均值高低
1.2 為甚麼要做資料常態化

In this problem, we will normalize our data before we run the clustering algorithms.

Why is it important to normalize the data before clustering?

  • 如果變數的scale不同,例如血壓與薪水,這樣在計算距離的時候會受到sacle較大的變數(薪水)影響

  • 作資料常態化我們計算變數的平均,以離均差來表示scale,這樣可以使每個變數的scale比較接近,計算距離時也比較不會受到影響

1.3 使用caret套件做資料常態化

Let’s go ahead and normalize our data. You can normalize the variables in a data frame by using the preProcess function in the “caret” package. You should already have this package installed from Week 4, but if not, go ahead and install it with install.packages(“caret”). Then load the package with library(caret).

Now, create a normalized data frame called “airlinesNorm” by running the following commands:

preproc = preProcess(airlines)

airlinesNorm = predict(preproc, airlines)

The first command pre-processes the data, and the second command performs the normalization. If you look at the summary of airlinesNorm, you should see that all of the variables now have mean zero. You can also see that each of the variables has standard deviation 1 by using the sd() function.

library(caret)
preproc = preProcess(A)
AN = predict(preproc, A)  
summary(AN)
    Balance         QualMiles        BonusMiles    
 Min.   :-0.730   Min.   :-0.186   Min.   :-0.710  
 1st Qu.:-0.546   1st Qu.:-0.186   1st Qu.:-0.658  
 Median :-0.303   Median :-0.186   Median :-0.413  
 Mean   : 0.000   Mean   : 0.000   Mean   : 0.000  
 3rd Qu.: 0.187   3rd Qu.:-0.186   3rd Qu.: 0.276  
 Max.   :16.187   Max.   :14.223   Max.   :10.208  
   BonusTrans      FlightMiles      FlightTrans    
 Min.   :-1.208   Min.   :-0.329   Min.   :-0.362  
 1st Qu.:-0.896   1st Qu.:-0.329   1st Qu.:-0.362  
 Median : 0.041   Median :-0.329   Median :-0.362  
 Mean   : 0.000   Mean   : 0.000   Mean   : 0.000  
 3rd Qu.: 0.562   3rd Qu.:-0.106   3rd Qu.:-0.098  
 Max.   : 7.747   Max.   :21.680   Max.   :13.610  
 DaysSinceEnroll  
 Min.   :-1.9934  
 1st Qu.:-0.8661  
 Median :-0.0109  
 Mean   : 0.0000  
 3rd Qu.: 0.8096  
 Max.   : 2.0228  
apply(AN, 2, mean) %>% round(3)
        Balance       QualMiles      BonusMiles 
              0               0               0 
     BonusTrans     FlightMiles     FlightTrans 
              0               0               0 
DaysSinceEnroll 
              0 
apply(AN, 2, sd) %>% round(3)
        Balance       QualMiles      BonusMiles 
              1               1               1 
     BonusTrans     FlightMiles     FlightTrans 
              1               1               1 
DaysSinceEnroll 
              1 
apply(AN, 2, max) %>% sort
DaysSinceEnroll      BonusTrans      BonusMiles 
          2.023           7.747          10.208 
    FlightTrans       QualMiles         Balance 
         13.610          14.223          16.187 
    FlightMiles 
         21.680 

In the normalized data, which variable has the largest maximum value?

  • 從上表可發現FlightMiles的平均值是所有變數裡最大的
apply(AN, 2, min) %>% sort
DaysSinceEnroll      BonusTrans         Balance      BonusMiles     FlightTrans 
        -1.9934         -1.2081         -0.7303         -0.7099         -0.3621 
    FlightMiles       QualMiles 
        -0.3286         -0.1863 

In the normalized data, which variable has the smallest minimum value?

  • 從上表可發現FlightTrans的平均值是所有變數裡面最小的
1.3小組討論
  • 分群前先看一下變數scale,不要被scale大的變數影響了距離。
  • 學習scale函數或者caret套件
  • apply家族 & sort方便我們看最大值或最小值。



2. 層級式集群分析

2.1 依據樹狀圖和應用需求決定群數

Compute the distances between data points (using euclidean distance) and then run the Hierarchical clustering algorithm (using method=“ward.D”) on the normalized data. It may take a few minutes for the commands to finish since the dataset has a large number of observations for hierarchical clustering.

Then, plot the dendrogram of the hierarchical clustering process. Suppose the airline is looking for somewhere between 2 and 10 clusters.

d = dist(AN,method="euclidean")
hc = hclust(d, method='ward.D')
plot(hc)
# Select 3 clusters
rect.hclust(hc, k = 6, border = "red")

According to the dendrogram, which of the following is NOT a good choice for the number of clusters?

  • 如上圖,分成6群的時候到中心點的距離比較短,表示比較難區分群間的距離
  • 所以分成6群比較不是一個好的選擇(就2~7群而言)
2.2 分割群組

Suppose that after looking at the dendrogram and discussing with the marketing department, the airline decides to proceed with 5 clusters. Divide the data points into 5 clusters by using the cutree function.

kg = cutree(hc, k=5)
table(kg)
kg
   1    2    3    4    5 
 776  519  494  868 1342 

How many data points are in Cluster 1?

  • 使用table函數可以看到Cluster1有776個資料點
2.3 從區隔變數的平均值推論族群特性

Now, use tapply to compare the average values in each of the variables for the 5 clusters (the centroids of the clusters). You may want to compute the average values of the unnormalized data so that it is easier to interpret. You can do this for the variable “Balance” with the following command:

tapply(airlines$Balance, clusterGroups, mean)

sapply(split(A,kg), colMeans) %>% round(2) 
                       1         2         3        4        5
Balance         57866.90 110669.27 198191.57 52335.91 36255.91
QualMiles           0.64   1065.98     30.35     4.85     2.51
BonusMiles      10360.12  22881.76  55795.86 20788.77  2264.79
BonusTrans         10.82     18.23     19.66    17.09     2.97
FlightMiles        83.18   2613.42    327.68   111.57   119.32
FlightTrans         0.30      7.40      1.07     0.34     0.44
DaysSinceEnroll  6235.36   4402.41   5615.71  2840.82  3060.08

Compared to the other clusters, Cluster 1 has the largest average values in which variables (if any)? Select all that apply.

  • DaysSinceEnroll

How would you describe the customers in Cluster 1?

  • Cluster1註冊的天數最久,但是他們的miles最少
  • 所以是Infrequent but loyal customers
2.4 Cluster 2
split(AN,kg) %>% sapply(colMeans) %>% round(2)
                    1    2     3     4     5
Balance         -0.16 0.37  1.24 -0.21 -0.37
QualMiles       -0.19 1.19 -0.15 -0.18 -0.18
BonusMiles      -0.28 0.24  1.60  0.15 -0.62
BonusTrans      -0.08 0.69  0.84  0.57 -0.90
FlightMiles     -0.27 1.54 -0.09 -0.25 -0.24
FlightTrans     -0.28 1.59 -0.08 -0.27 -0.25
DaysSinceEnroll  1.03 0.14  0.72 -0.62 -0.51
par(cex=0.8)
split(AN,kg) %>% sapply(colMeans) %>% barplot(beside=T,col=rainbow(7))
legend('topright',legend=colnames(A),fill=rainbow(7))

Compared to the other clusters, Cluster 2 has the largest average values in which variables (if any)? Select all that apply.

  • QualMiles
  • FlightMiles
  • FlightTrans

How would you describe the customers in Cluster 2?

  • Cluster2累積了很多miles,而且有最多的flight transactions
  • 所以是Customers who have accumulated a large amount of miles, and the ones with the largest number of flight transactions. 正确
2.5 Cluster 3

Compared to the other clusters, Cluster 3 has the largest average values in which variables (if any)? Select all that apply.

  • Balance
  • BonusMiles
  • BonusTrans

How would you describe the customers in Cluster 3?

  • Cluster3的顧客累積很多的miles,是透過non-flight transactions累積
  • 所以是Customers who have accumulated a large amount of miles, mostly through non-flight transactions.
2.6 Cluster 4

Compared to the other clusters, Cluster 4 has the largest average values in which variables (if any)? Select all that apply.

  • Cluster4沒有比其他Cluster還要大的變數

How would you describe the customers in Cluster 4?

  • Cluster4註冊天數是最年輕的,是比較新的顧客,且透過non-flight transactions累積了一些miles
  • 所以是Relatively new customers who seem to be accumulating miles, mostly through non-flight transactions
2.7 Cluster 5

Compared to the other clusters, Cluster 5 has the largest average values in which variables (if any)? Select all that apply.

  • Cluster5沒有比其他Cluster還要大的變數

How would you describe the customers in Cluster 5?

  • Cluster5的顧客很新且也沒有累積什麼miles
  • 所以是Relatively new customers who don’t use the airline very often
小組討論2
  • 用這個資料學習用分群來分出不同的族群,並進一步分析找到這些族群的特性。

  • 相對於我們一開始對整份資料沒有分析的想法,我們做分群以後發現不同族群有不同特性。所以我們可以為這些不同族群量身打造不同的方案來迎合顧客的需求。

  • 所以我們學到如何用分群來留住核心顧客,怎麼喚醒沉睡顧客等等。我們要先針對不同的顧客分析出特性,進一步做決策,如此便可以大大的提升效率


3. K-Means集群分析

3.1 K-Means集群分析

Now run the k-means clustering algorithm on the normalized data, again creating 5 clusters. Set the seed to 88 right before running the clustering algorithm, and set the argument iter.max to 1000.

set.seed(88)
km = kmeans(AN, 5, iter.max = 1000)
kg2 = km$cluster
table(kg2)
kg2
   1    2    3    4    5 
 408  141  993 1182 1275 

How many clusters have more than 1,000 observations?

  • Cluster4有1182個、Cluster5有1275個
  • 共兩個Cluster擁有超過1000個Observations
par(cex=0.8)
km$centers %>% round(2) %>% t %>% barplot(beside=T,col=rainbow(7))
legend('topright',legend=colnames(A),fill=rainbow(7))

3.2 Hierarchical和K-Means集群的對應關係

Now, compare the cluster centroids to each other either by dividing the data points into groups and then using tapply, or by looking at the output of kmeansClust\(centers, where "kmeansClust" is the name of the output of the kmeans function. (Note that the output of kmeansClust\)centers will be for the normalized data. If you want to look at the average values for the unnormalized data, you need to use tapply like we did for hierarchical clustering.)

table(Hierarchical=kg, KMeans=kg2)
            KMeans
Hierarchical    1    2    3    4    5
           1    4    0   98  673    1
           2   92  137  105   92   93
           3  300    4  132   58    0
           4   12    0  653   30  173
           5    0    0    5  329 1008

Do you expect Cluster 1 of the K-Means clustering output to necessarily be similar to Cluster 1 of the Hierarchical clustering output?

  • Kmeans計算群的中心點並且遞迴的將離中心點最近的資料點歸類為該群
  • Kmeans演算法每次分群都不會一樣的結果,所以本來就不會跟hierarchical的分群結果一樣


【討論問題】

請你們為這五個族群各起一個名稱 (2.4 Cluster 2的那張圖)

  • 第一群:沉睡顧客;最久的顧客,但所有里程數都小於平均
  • 第二群:核心顧客
  • 第三群:間接顧客(透過協力廠商拉到的會員)
  • 第四群:潛力顧客
  • 第五群:新顧客

請你們為這五個族群各設計一個行銷策略

  • 第一群:偶爾提供顧客一些優惠,促使他們時常搭乘
  • 第二群:累積點數
  • 第三群:偕同促銷方案(機票+住宿優惠)
  • 第四群:提供折價券,喚起老顧客的注意
  • 第五群:根據新顧客的需求推薦適合的組合優惠

統計上最好的分群也是實務上最好的分群嗎?

  • 不一定,統計讓我們可以假設一下資料的分布,實際上我們還是要看一下真實資料的分布以及視覺化分群出來的樣貌
  • 通常統計上我們可以評估分群的效果,看能不能良好的區分不同群的資料。但實務上我們因為要依照不同族群來量身打造不同的方案,所以當然實務上我們可以應該要自己衡量應該要增加群數或者減少群數
  • 簡單來說,統計輔助我們評估分群好壞,但做決策的是人。統計讓我們比較方便的找到不同族群的特色,實際上我們依照現實情況可能會有不同的考量。

除了考慮群間和群間距離之外,實務上的分群通常還需要考慮那些因數?

  • 資料量大小也要考慮,如資料量大我們用Kmeans;量少用Hierarchical
  • 我們要考慮是否有noise data,要拿掉,否則會破壞分群
  • 通常還會考量群內變異數來衡量分群的好壞
小組總結
  • 這個範例我們用分群來達到行銷的STP。
  • 一開始我們對於整份資料沒有分析想法的時候,我們利用分群將族群分出來,找到不同族群的特性。
  • 我們在做市場區隔前首要先了解不同的顧客你要把它放到哪個市場,所以我們做分群。然後發現不同族群有不同的特性,這時我們可以投其所好,量身打造一些行銷策略。所以我們用對的行銷策略放在對的人事物上,整個就提升效率了。
  • 以後我們在做市場區隔的時候要懂得利用分群來分析族群的特性,然後我們才能去制定決策。






LS0tDQp0aXRsZTogIkFTNi0yIOiIquepuuWFrOWPuOeahOW4guWgtOWNgOmalCINCmF1dGhvcjogIkdyb3VwMSwgMjAxOC8wNy8zMCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCjxicj4NCg0KKirkuLvopoHorbDpoYzvvJrkvp3poaflrqLlsazmgKflgZrluILloLTljYDpmpQqKg0KDQoqKuWtuOe/kumHjem7nu+8mioqDQoNCisgPGEgaHJlZj0nI1MxJz7liKnnlKjpm4bnvqTliIbmnpDlgZrluILloLTljYDpmpQ8L2E+DQorIDxhIGhyZWY9JyNTMic+6LOH5paZ5bi45oWL5YyWPC9hPg0KKyA8YSBocmVmPScjUzMnPuizh+aWmeimluimuuWMljwvYT4NCisgPGEgaHJlZj0nI1M0Jz7ml4/nvqTnibnmgKfoiIfooYzpirfnrZbnlaU8L2E+DQorIDxhIGhyZWY9JyNTNSc+6KGM6Yq35bel5YW3dnPooYzpirflsI3osaE8L2E+DQoNCg0KKirlsI/ntYToqI7oq5bvvJoqKg0KDQorIDxhIGhyZWY9JyNEMS4xJz4xLjE8L2E+DQorIDxhIGhyZWY9JyNEMS4zJz4xLjM8L2E+DQorIDxhIGhyZWY9JyNEMic+MjwvYT4NCisgPGEgaHJlZj0nI21hcmtldDEnPuWNgOWIhumhp+WuojwvYT4NCisgPGEgaHJlZj0nI0NMJz7lsI/ntYTnuL3ntZA8L2E+DQoNCg0KYGBge3IgZWNobz1ULCBtZXNzYWdlPUYsIGNhY2hlPUYsIHdhcm5pbmc9Rn0NCnJtKGxpc3Q9bHMoYWxsPVQpKQ0KU3lzLnNldGxvY2FsZSgiTENfQUxMIiwiQyIpDQpvcHRpb25zKGRpZ2l0cz00LCBzY2lwZW49MTIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShjYXJldCkNCmBgYA0KPGJyPg0KDQotIC0gLQ0KDQojIyMgIDxzcGFuIGlkPSdTMic+MS4g6LOH5paZ5bi45oWL5YyWPC9zcGFuPg0KDQojIyMjIyAxLjEg6LOH5paZ5pGY6KaBDQpSZWFkIHRoZSBkYXRhc2V0IEFpcmxpbmVzQ2x1c3Rlci5jc3YgaW50byBSIGFuZCBjYWxsIGl0ICJhaXJsaW5lcyIuIExvb2tpbmcgYXQgdGhlIHN1bW1hcnkgb2YgYWlybGluZXMsIA0KYGBge3J9DQpBID0gcmVhZC5jc3YoJ2RhdGEvQWlybGluZXNDbHVzdGVyLmNzdicpDQpzdW1tYXJ5KEEpDQpgYGANCmBgYHtyfQ0KY29sTWVhbnMoQSkgJT4lIHNvcnQNCmBgYA0KDQpfd2hpY2ggVFdPIHZhcmlhYmxlcyBoYXZlIChvbiBhdmVyYWdlKSB0aGUgc21hbGxlc3QgdmFsdWVzP18NCg0KKyBGbGlnaHRUcmFucw0KKyBCb251c1RyYW5zDQorIA0KDQpfV2hpY2ggVFdPIHZhcmlhYmxlcyBoYXZlIChvbiBhdmVyYWdlKSB0aGUgbGFyZ2VzdCB2YWx1ZXM/Xw0KDQorIEJvbnVzTWlsZXMNCisgQmFsYW5jZQ0KKyANCg0KDQojIyMjIyMgPHNwYW4gaWQ9J0QxLjEnPjEuMeWwj+e1hOiojuirljwvc3Bhbj4NCisgc3VtbWFyeeeci+izh+aWmeWbm+WIhuS9jeaVuOWIhuW4gw0KKyBjb2xNZWFucyAmIHNvcnQg5pa55L6/5oiR5YCR55yL5Ye65ZCE5YCL5qyE5L2N5bmz5Z2H5YC86auY5L2ODQoNCiMjIyMjIDEuMiDngrrnlJrpurzopoHlgZros4fmlpnluLjmhYvljJYNCkluIHRoaXMgcHJvYmxlbSwgd2Ugd2lsbCBub3JtYWxpemUgb3VyIGRhdGEgYmVmb3JlIHdlIHJ1biB0aGUgY2x1c3RlcmluZyBhbGdvcml0aG1zLiANCg0KX1doeSBpcyBpdCBpbXBvcnRhbnQgdG8gbm9ybWFsaXplIHRoZSBkYXRhIGJlZm9yZSBjbHVzdGVyaW5nP18NCg0KKyDlpoLmnpzorormlbjnmoRzY2FsZeS4jeWQjO+8jOS+i+WmguihgOWjk+iIh+iWquawtO+8jOmAmeaoo+WcqOioiOeul+i3nemboueahOaZguWAmeacg+WPl+WIsHNhY2xl6LyD5aSn55qE6K6K5pW4KOiWquawtCnlvbHpn78NCg0KKyDkvZzos4fmlpnluLjmhYvljJbmiJHlgJHoqIjnrpforormlbjnmoTlubPlnYfvvIzku6Xpm6LlnYflt67kvobooajnpLpzY2FsZe+8jOmAmeaoo+WPr+S7peS9v+avj+WAi+iuiuaVuOeahHNjYWxl5q+U6LyD5o6l6L+R77yM6KiI566X6Led6Zui5pmC5Lmf5q+U6LyD5LiN5pyD5Y+X5Yiw5b2x6Z+/DQoNCiMjIyMjIDEuMyDkvb/nlKhgY2FyZXRg5aWX5Lu25YGa6LOH5paZ5bi45oWL5YyWDQpMZXQncyBnbyBhaGVhZCBhbmQgbm9ybWFsaXplIG91ciBkYXRhLiBZb3UgY2FuIG5vcm1hbGl6ZSB0aGUgdmFyaWFibGVzIGluIGEgZGF0YSBmcmFtZSBieSB1c2luZyB0aGUgcHJlUHJvY2VzcyBmdW5jdGlvbiBpbiB0aGUgImNhcmV0IiBwYWNrYWdlLiBZb3Ugc2hvdWxkIGFscmVhZHkgaGF2ZSB0aGlzIHBhY2thZ2UgaW5zdGFsbGVkIGZyb20gV2VlayA0LCBidXQgaWYgbm90LCBnbyBhaGVhZCBhbmQgaW5zdGFsbCBpdCB3aXRoIGluc3RhbGwucGFja2FnZXMoImNhcmV0IikuIFRoZW4gbG9hZCB0aGUgcGFja2FnZSB3aXRoIGxpYnJhcnkoY2FyZXQpLg0KDQpOb3csIGNyZWF0ZSBhIG5vcm1hbGl6ZWQgZGF0YSBmcmFtZSBjYWxsZWQgImFpcmxpbmVzTm9ybSIgYnkgcnVubmluZyB0aGUgZm9sbG93aW5nIGNvbW1hbmRzOg0KDQpwcmVwcm9jID0gcHJlUHJvY2VzcyhhaXJsaW5lcykNCg0KYWlybGluZXNOb3JtID0gcHJlZGljdChwcmVwcm9jLCBhaXJsaW5lcykNCg0KVGhlIGZpcnN0IGNvbW1hbmQgcHJlLXByb2Nlc3NlcyB0aGUgZGF0YSwgYW5kIHRoZSBzZWNvbmQgY29tbWFuZCBwZXJmb3JtcyB0aGUgbm9ybWFsaXphdGlvbi4gSWYgeW91IGxvb2sgYXQgdGhlIHN1bW1hcnkgb2YgYWlybGluZXNOb3JtLCB5b3Ugc2hvdWxkIHNlZSB0aGF0IGFsbCBvZiB0aGUgdmFyaWFibGVzIG5vdyBoYXZlIG1lYW4gemVyby4gWW91IGNhbiBhbHNvIHNlZSB0aGF0IGVhY2ggb2YgdGhlIHZhcmlhYmxlcyBoYXMgc3RhbmRhcmQgZGV2aWF0aW9uIDEgYnkgdXNpbmcgdGhlIHNkKCkgZnVuY3Rpb24uDQoNCmBgYHtyfQ0KbGlicmFyeShjYXJldCkNCnByZXByb2MgPSBwcmVQcm9jZXNzKEEpDQpBTiA9IHByZWRpY3QocHJlcHJvYywgQSkgIA0Kc3VtbWFyeShBTikNCmFwcGx5KEFOLCAyLCBtZWFuKSAlPiUgcm91bmQoMykNCmFwcGx5KEFOLCAyLCBzZCkgJT4lIHJvdW5kKDMpDQpgYGANCg0KYGBge3J9DQphcHBseShBTiwgMiwgbWF4KSAlPiUgc29ydA0KYGBgDQoNCkluIHRoZSBub3JtYWxpemVkIGRhdGEsIF93aGljaCB2YXJpYWJsZSBoYXMgdGhlIGxhcmdlc3QgbWF4aW11bSB2YWx1ZT9fDQoNCisg5b6e5LiK6KGo5Y+v55m854++RmxpZ2h0TWlsZXPnmoTlubPlnYflgLzmmK/miYDmnInorormlbjoo6HmnIDlpKfnmoQNCisNCg0KYGBge3J9DQphcHBseShBTiwgMiwgbWluKSAlPiUgc29ydA0KYGBgDQoNCkluIHRoZSBub3JtYWxpemVkIGRhdGEsIF93aGljaCB2YXJpYWJsZSBoYXMgdGhlIHNtYWxsZXN0IG1pbmltdW0gdmFsdWU/Xw0KDQorIOW+nuS4iuihqOWPr+eZvOePvkZsaWdodFRyYW5z55qE5bmz5Z2H5YC85piv5omA5pyJ6K6K5pW46KOh6Z2i5pyA5bCP55qEDQoNCg0KIyMjIyMjIDxzcGFuIGlkPSdEMS4zJz4xLjPlsI/ntYToqI7oq5Y8L3NwYW4+DQorIOWIhue+pOWJjeWFiOeci+S4gOS4i+iuiuaVuHNjYWxl77yM5LiN6KaB6KKrc2NhbGXlpKfnmoTorormlbjlvbHpn7/kuobot53pm6LjgIINCisg5a2457+Sc2NhbGXlh73mlbjmiJbogIVjYXJldOWll+S7tg0KKyBhcHBseeWutuaXjyAmIHNvcnTmlrnkvr/miJHlgJHnnIvmnIDlpKflgLzmiJbmnIDlsI/lgLzjgIINCg0KPGJyPg0KDQotIC0gLQ0KDQojIyMgMi4g5bGk57Sa5byP6ZuG576k5YiG5p6QDQoNCiMjIyMjIDIuMSDkvp3mk5rmqLnni4DlnJblkozmh4nnlKjpnIDmsYLmsbrlrprnvqTmlbgNCkNvbXB1dGUgdGhlIGRpc3RhbmNlcyBiZXR3ZWVuIGRhdGEgcG9pbnRzICh1c2luZyBldWNsaWRlYW4gZGlzdGFuY2UpIGFuZCB0aGVuIHJ1biB0aGUgSGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcgYWxnb3JpdGhtICh1c2luZyBtZXRob2Q9IndhcmQuRCIpIG9uIHRoZSBub3JtYWxpemVkIGRhdGEuIEl0IG1heSB0YWtlIGEgZmV3IG1pbnV0ZXMgZm9yIHRoZSBjb21tYW5kcyB0byBmaW5pc2ggc2luY2UgdGhlIGRhdGFzZXQgaGFzIGEgbGFyZ2UgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBmb3IgaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcuDQoNClRoZW4sIHBsb3QgdGhlIGRlbmRyb2dyYW0gb2YgdGhlIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nIHByb2Nlc3MuIFN1cHBvc2UgdGhlIGFpcmxpbmUgaXMgbG9va2luZyBmb3Igc29tZXdoZXJlIGJldHdlZW4gMiBhbmQgMTAgY2x1c3RlcnMuIA0KYGBge3J9DQpkID0gZGlzdChBTixtZXRob2Q9ImV1Y2xpZGVhbiIpDQpoYyA9IGhjbHVzdChkLCBtZXRob2Q9J3dhcmQuRCcpDQpwbG90KGhjKQ0KIyBTZWxlY3QgNiBjbHVzdGVycw0KcmVjdC5oY2x1c3QoaGMsIGsgPSA2LCBib3JkZXIgPSAicmVkIikNCmBgYA0KQWNjb3JkaW5nIHRvIHRoZSBkZW5kcm9ncmFtLCBfd2hpY2ggb2YgdGhlIGZvbGxvd2luZyBpcyBOT1QgYSBnb29kIGNob2ljZSBmb3IgdGhlIG51bWJlciBvZiBjbHVzdGVycz9fDQoNCisg5aaC5LiK5ZyW77yM5YiG5oiQNue+pOeahOaZguWAmeWIsOS4reW/g+m7nueahOi3nembouavlOi8g+efre+8jOihqOekuuavlOi8g+mbo+WNgOWIhue+pOmWk+eahOi3nembog0KKyDmiYDku6XliIbmiJA2576k5q+U6LyD5LiN5piv5LiA5YCL5aW955qE6YG45pOHKOWwsTJ+N+e+pOiAjOiogCkNCg0KIyMjIyMgMi4yIOWIhuWJsue+pOe1hA0KU3VwcG9zZSB0aGF0IGFmdGVyIGxvb2tpbmcgYXQgdGhlIGRlbmRyb2dyYW0gYW5kIGRpc2N1c3Npbmcgd2l0aCB0aGUgbWFya2V0aW5nIGRlcGFydG1lbnQsIHRoZSBhaXJsaW5lIGRlY2lkZXMgdG8gcHJvY2VlZCB3aXRoIDUgY2x1c3RlcnMuIERpdmlkZSB0aGUgZGF0YSBwb2ludHMgaW50byA1IGNsdXN0ZXJzIGJ5IHVzaW5nIHRoZSBjdXRyZWUgZnVuY3Rpb24uIA0KYGBge3J9DQprZyA9IGN1dHJlZShoYywgaz01KQ0KdGFibGUoa2cpDQpgYGANCl9Ib3cgbWFueSBkYXRhIHBvaW50cyBhcmUgaW4gQ2x1c3RlciAxP18NCg0KKyDkvb/nlKh0YWJsZeWHveaVuOWPr+S7peeci+WIsENsdXN0ZXIx5pyJNzc25YCL6LOH5paZ6bueDQoNCg0KIyMjIyMgMi4zIOW+nuWNgOmalOiuiuaVuOeahOW5s+Wdh+WAvOaOqOirluaXj+e+pOeJueaApw0KTm93LCB1c2UgdGFwcGx5IHRvIGNvbXBhcmUgdGhlIGF2ZXJhZ2UgdmFsdWVzIGluIGVhY2ggb2YgdGhlIHZhcmlhYmxlcyBmb3IgdGhlIDUgY2x1c3RlcnMgKHRoZSBjZW50cm9pZHMgb2YgdGhlIGNsdXN0ZXJzKS4gWW91IG1heSB3YW50IHRvIGNvbXB1dGUgdGhlIGF2ZXJhZ2UgdmFsdWVzIG9mIHRoZSB1bm5vcm1hbGl6ZWQgZGF0YSBzbyB0aGF0IGl0IGlzIGVhc2llciB0byBpbnRlcnByZXQuIFlvdSBjYW4gZG8gdGhpcyBmb3IgdGhlIHZhcmlhYmxlICJCYWxhbmNlIiB3aXRoIHRoZSBmb2xsb3dpbmcgY29tbWFuZDoNCg0KdGFwcGx5KGFpcmxpbmVzJEJhbGFuY2UsIGNsdXN0ZXJHcm91cHMsIG1lYW4pDQpgYGB7cn0NCnNhcHBseShzcGxpdChBLGtnKSwgY29sTWVhbnMpICU+JSByb3VuZCgyKSANCmBgYA0KQ29tcGFyZWQgdG8gdGhlIG90aGVyIGNsdXN0ZXJzLCBfQ2x1c3RlciAxIGhhcyB0aGUgbGFyZ2VzdCBhdmVyYWdlIHZhbHVlcyBpbiB3aGljaCB2YXJpYWJsZXMgKGlmIGFueSk/IFNlbGVjdCBhbGwgdGhhdCBhcHBseS5fDQoNCisgRGF5c1NpbmNlRW5yb2xsDQoNCg0KX0hvdyB3b3VsZCB5b3UgZGVzY3JpYmUgdGhlIGN1c3RvbWVycyBpbiBDbHVzdGVyIDE/Xw0KDQorICBDbHVzdGVyMeiou+WGiueahOWkqeaVuOacgOS5he+8jOS9huaYr+S7luWAkeeahG1pbGVz5pyA5bCRDQorIOaJgOS7peaYr0luZnJlcXVlbnQgYnV0IGxveWFsIGN1c3RvbWVycw0KDQojIyMjIyAyLjQgQ2x1c3RlciAyDQpgYGB7cn0NCnNwbGl0KEFOLGtnKSAlPiUgc2FwcGx5KGNvbE1lYW5zKSAlPiUgcm91bmQoMikNCmBgYA0KDQpgYGB7cn0NCnBhcihjZXg9MC44KQ0Kc3BsaXQoQU4sa2cpICU+JSBzYXBwbHkoY29sTWVhbnMpICU+JSBiYXJwbG90KGJlc2lkZT1ULGNvbD1yYWluYm93KDcpKQ0KbGVnZW5kKCd0b3ByaWdodCcsbGVnZW5kPWNvbG5hbWVzKEEpLGZpbGw9cmFpbmJvdyg3KSkNCmBgYA0KDQpDb21wYXJlZCB0byB0aGUgb3RoZXIgY2x1c3RlcnMsIF9DbHVzdGVyIDIgaGFzIHRoZSBsYXJnZXN0IGF2ZXJhZ2UgdmFsdWVzIGluIHdoaWNoIHZhcmlhYmxlcyAoaWYgYW55KT8gU2VsZWN0IGFsbCB0aGF0IGFwcGx5Ll8NCg0KKyBRdWFsTWlsZXMNCisgRmxpZ2h0TWlsZXMNCisgRmxpZ2h0VHJhbnMNCg0KX0hvdyB3b3VsZCB5b3UgZGVzY3JpYmUgdGhlIGN1c3RvbWVycyBpbiBDbHVzdGVyIDI/Xw0KDQorICBDbHVzdGVyMue0r+epjeS6huW+iOWkmm1pbGVz77yM6ICM5LiU5pyJ5pyA5aSa55qEZmxpZ2h0IHRyYW5zYWN0aW9ucw0KKyAg5omA5Lul5pivQ3VzdG9tZXJzIHdobyBoYXZlIGFjY3VtdWxhdGVkIGEgbGFyZ2UgYW1vdW50IG9mIG1pbGVzLCBhbmQgdGhlIG9uZXMgd2l0aCB0aGUgbGFyZ2VzdCBudW1iZXIgb2YgZmxpZ2h0IHRyYW5zYWN0aW9ucy4g5q2j56GuDQorDQoNCiMjIyMjIDIuNSBDbHVzdGVyIDMNCkNvbXBhcmVkIHRvIHRoZSBvdGhlciBjbHVzdGVycywgX0NsdXN0ZXIgMyBoYXMgdGhlIGxhcmdlc3QgYXZlcmFnZSB2YWx1ZXMgaW4gd2hpY2ggdmFyaWFibGVzIChpZiBhbnkpPyBTZWxlY3QgYWxsIHRoYXQgYXBwbHkuXw0KDQorIEJhbGFuY2UNCisgQm9udXNNaWxlcw0KKyBCb251c1RyYW5zDQoNCl9Ib3cgd291bGQgeW91IGRlc2NyaWJlIHRoZSBjdXN0b21lcnMgaW4gQ2x1c3RlciAzP18NCg0KKyBDbHVzdGVyM+eahOmhp+Wuoue0r+epjeW+iOWkmueahG1pbGVz77yM5piv6YCP6YGObm9uLWZsaWdodCB0cmFuc2FjdGlvbnPntK/nqY0NCisg5omA5Lul5pivQ3VzdG9tZXJzIHdobyBoYXZlIGFjY3VtdWxhdGVkIGEgbGFyZ2UgYW1vdW50IG9mIG1pbGVzLCBtb3N0bHkgdGhyb3VnaCBub24tZmxpZ2h0IHRyYW5zYWN0aW9ucy4NCg0KDQojIyMjIyAyLjYgQ2x1c3RlciA0DQpDb21wYXJlZCB0byB0aGUgb3RoZXIgY2x1c3RlcnMsIF9DbHVzdGVyIDQgaGFzIHRoZSBsYXJnZXN0IGF2ZXJhZ2UgdmFsdWVzIGluIHdoaWNoIHZhcmlhYmxlcyAoaWYgYW55KT8gU2VsZWN0IGFsbCB0aGF0IGFwcGx5Ll8NCg0KKyBDbHVzdGVyNOaykuacieavlOWFtuS7lkNsdXN0ZXLpgoTopoHlpKfnmoTorormlbgNCg0KDQoNCl9Ib3cgd291bGQgeW91IGRlc2NyaWJlIHRoZSBjdXN0b21lcnMgaW4gQ2x1c3RlciA0P18NCg0KKyBDbHVzdGVyNOiou+WGiuWkqeaVuOaYr+acgOW5tOi8leeahO+8jOaYr+avlOi8g+aWsOeahOmhp+Wuou+8jOS4lOmAj+mBjm5vbi1mbGlnaHQgdHJhbnNhY3Rpb25z57Sv56mN5LqG5LiA5LqbbWlsZXMNCisg5omA5Lul5pivUmVsYXRpdmVseSBuZXcgY3VzdG9tZXJzIHdobyBzZWVtIHRvIGJlIGFjY3VtdWxhdGluZyBtaWxlcywgbW9zdGx5IHRocm91Z2ggbm9uLWZsaWdodCB0cmFuc2FjdGlvbnMNCg0KDQojIyMjIyAyLjcgQ2x1c3RlciA1DQoNCkNvbXBhcmVkIHRvIHRoZSBvdGhlciBjbHVzdGVycywgX0NsdXN0ZXIgNSBoYXMgdGhlIGxhcmdlc3QgYXZlcmFnZSB2YWx1ZXMgaW4gd2hpY2ggdmFyaWFibGVzIChpZiBhbnkpPyBTZWxlY3QgYWxsIHRoYXQgYXBwbHkuXw0KDQorIENsdXN0ZXI15rKS5pyJ5q+U5YW25LuWQ2x1c3RlcumChOimgeWkp+eahOiuiuaVuA0KDQoNCg0KX0hvdyB3b3VsZCB5b3UgZGVzY3JpYmUgdGhlIGN1c3RvbWVycyBpbiBDbHVzdGVyIDU/Xw0KDQorIENsdXN0ZXI155qE6aGn5a6i5b6I5paw5LiU5Lmf5rKS5pyJ57Sv56mN5LuA6bq8bWlsZXMNCisg5omA5Lul5pivUmVsYXRpdmVseSBuZXcgY3VzdG9tZXJzIHdobyBkb24ndCB1c2UgdGhlIGFpcmxpbmUgdmVyeSBvZnRlbg0KDQoNCg0KIyMjIyMjIDxzcGFuIGlkPSdEMic+5bCP57WE6KiO6KuWMjwvc3Bhbj4NCisg55So6YCZ5YCL6LOH5paZ5a2457+S55So5YiG576k5L6G5YiG5Ye65LiN5ZCM55qE5peP576k77yM5Lim6YCy5LiA5q2l5YiG5p6Q5om+5Yiw6YCZ5Lqb5peP576k55qE54m55oCn44CCDQoNCisg55u45bCN5pa85oiR5YCR5LiA6ZaL5aeL5bCN5pW05Lu96LOH5paZ5rKS5pyJ5YiG5p6Q55qE5oOz5rOV77yM5oiR5YCR5YGa5YiG576k5Lul5b6M55m854++5LiN5ZCM5peP576k5pyJ5LiN5ZCM54m55oCn44CC5omA5Lul5oiR5YCR5Y+v5Lul54K66YCZ5Lqb5LiN5ZCM5peP576k6YeP6Lqr5omT6YCg5LiN5ZCM55qE5pa55qGI5L6G6L+O5ZCI6aGn5a6i55qE6ZyA5rGC44CCDQoNCisg5omA5Lul5oiR5YCR5a245Yiw5aaC5L2V55So5YiG576k5L6G55WZ5L2P5qC45b+D6aGn5a6i77yM5oCO6bq85Zaa6YaS5rKJ552h6aGn5a6i562J562J44CC5oiR5YCR6KaB5YWI6Yed5bCN5LiN5ZCM55qE6aGn5a6i5YiG5p6Q5Ye654m55oCn77yM6YCy5LiA5q2l5YGa5rG6562W77yM5aaC5q2k5L6/5Y+v5Lul5aSn5aSn55qE5o+Q5Y2H5pWI546HDQoNCi0gLSAtDQoNCiMjIyAzLiBLLU1lYW5z6ZuG576k5YiG5p6QDQoNCiMjIyMjIDMuMSBLLU1lYW5z6ZuG576k5YiG5p6QDQpOb3cgcnVuIHRoZSBrLW1lYW5zIGNsdXN0ZXJpbmcgYWxnb3JpdGhtIG9uIHRoZSBub3JtYWxpemVkIGRhdGEsIGFnYWluIGNyZWF0aW5nIDUgY2x1c3RlcnMuIFNldCB0aGUgc2VlZCB0byA4OCByaWdodCBiZWZvcmUgcnVubmluZyB0aGUgY2x1c3RlcmluZyBhbGdvcml0aG0sIGFuZCBzZXQgdGhlIGFyZ3VtZW50IGl0ZXIubWF4IHRvIDEwMDAuDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoODgpDQprbSA9IGttZWFucyhBTiwgNSwgaXRlci5tYXggPSAxMDAwKQ0Ka2cyID0ga20kY2x1c3Rlcg0KdGFibGUoa2cyKQ0KYGBgDQpfSG93IG1hbnkgY2x1c3RlcnMgaGF2ZSBtb3JlIHRoYW4gMSwwMDAgb2JzZXJ2YXRpb25zP18NCg0KKyAgQ2x1c3RlcjTmnIkxMTgy5YCL44CBQ2x1c3RlcjXmnIkxMjc15YCLDQorICDlhbHlhanlgItDbHVzdGVy5pOB5pyJ6LaF6YGOMTAwMOWAi09ic2VydmF0aW9ucw0KDQoNCmBgYHtyfQ0KcGFyKGNleD0wLjgpDQprbSRjZW50ZXJzICU+JSByb3VuZCgyKSAlPiUgdCAlPiUgYmFycGxvdChiZXNpZGU9VCxjb2w9cmFpbmJvdyg3KSkNCmxlZ2VuZCgndG9wcmlnaHQnLGxlZ2VuZD1jb2xuYW1lcyhBKSxmaWxsPXJhaW5ib3coNykpDQpgYGANCg0KIyMjIyMgMy4yIEhpZXJhcmNoaWNhbOWSjEstTWVhbnPpm4bnvqTnmoTlsI3mh4npl5zkv4INCk5vdywgY29tcGFyZSB0aGUgY2x1c3RlciBjZW50cm9pZHMgdG8gZWFjaCBvdGhlciBlaXRoZXIgYnkgZGl2aWRpbmcgdGhlIGRhdGEgcG9pbnRzIGludG8gZ3JvdXBzIGFuZCB0aGVuIHVzaW5nIHRhcHBseSwgb3IgYnkgbG9va2luZyBhdCB0aGUgb3V0cHV0IG9mIGttZWFuc0NsdXN0JGNlbnRlcnMsIHdoZXJlICJrbWVhbnNDbHVzdCIgaXMgdGhlIG5hbWUgb2YgdGhlIG91dHB1dCBvZiB0aGUga21lYW5zIGZ1bmN0aW9uLiAoTm90ZSB0aGF0IHRoZSBvdXRwdXQgb2Yga21lYW5zQ2x1c3QkY2VudGVycyB3aWxsIGJlIGZvciB0aGUgbm9ybWFsaXplZCBkYXRhLiBJZiB5b3Ugd2FudCB0byBsb29rIGF0IHRoZSBhdmVyYWdlIHZhbHVlcyBmb3IgdGhlIHVubm9ybWFsaXplZCBkYXRhLCB5b3UgbmVlZCB0byB1c2UgdGFwcGx5IGxpa2Ugd2UgZGlkIGZvciBoaWVyYXJjaGljYWwgY2x1c3RlcmluZy4pDQpgYGB7cn0NCnRhYmxlKEhpZXJhcmNoaWNhbD1rZywgS01lYW5zPWtnMikNCmBgYA0KDQpfRG8geW91IGV4cGVjdCBDbHVzdGVyIDEgb2YgdGhlIEstTWVhbnMgY2x1c3RlcmluZyBvdXRwdXQgdG8gbmVjZXNzYXJpbHkgYmUgc2ltaWxhciB0byBDbHVzdGVyIDEgb2YgdGhlIEhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nIG91dHB1dD9fDQoNCisgIEttZWFuc+ioiOeul+e+pOeahOS4reW/g+m7nuS4puS4lOmBnui/tOeahOWwh+mbouS4reW/g+m7nuacgOi/keeahOizh+aWmem7nuatuOmhnueCuuipsue+pA0KKyAgS21lYW5z5ryU566X5rOV5q+P5qyh5YiG576k6YO95LiN5pyD5LiA5qij55qE57WQ5p6c77yM5omA5Lul5pys5L6G5bCx5LiN5pyD6LefaGllcmFyY2hpY2Fs55qE5YiG576k57WQ5p6c5LiA5qijDQoNCg0KPGJyPg0KDQojIyMjIyDjgJDoqI7oq5bllY/poYzjgJENCg0K6KuL5L2g5YCR54K66YCZ5LqU5YCL5peP576k5ZCE6LW35LiA5YCL5ZCN56ixDQooMi40IENsdXN0ZXIgMueahOmCo+W8teWclikNCg0KDQo8aW1nIGlkPSdtYXJrZXQxJyBzcmM9J2RhdGEvbWFya2V0MS5qcGcnPg0KDQo8aW1nIGlkPSdtYXJrZXQyJyBzcmM9J2RhdGEvbWFya2V0Mi5wbmcnPg0KDQorIOesrOS4gOe+pDrmsonnnaHpoaflrqI75pyA5LmF55qE6aGn5a6i77yM5L2G5omA5pyJ6YeM56iL5pW46YO95bCP5pa85bmz5Z2HDQorIOesrOS6jOe+pDrmoLjlv4PpoaflrqINCisg56ys5LiJ576kOumWk+aOpemhp+WuoijpgI/pgY7ljZTlipvlu6DllYbmi4nliLDnmoTmnIPlk6EpDQorIOesrOWbm+e+pDrmvZvlipvpoaflrqINCisg56ys5LqU576kOuaWsOmhp+Wuog0KDQroq4vkvaDlgJHngrrpgJnkupTlgIvml4/nvqTlkIToqK3oqIjkuIDlgIvooYzpirfnrZbnlaUNCg0KKyDnrKzkuIDnvqQ65YG254i+5o+Q5L6b6aGn5a6i5LiA5Lqb5YSq5oOg77yM5L+D5L2/5LuW5YCR5pmC5bi45pCt5LmYDQorIOesrOS6jOe+pDrntK/nqY3pu57mlbgNCisg56ys5LiJ576kOuWBleWQjOS/g+mKt+aWueahiCjmqZ/npagr5L2P5a6/5YSq5oOgKQ0KKyDnrKzlm5vnvqQ65o+Q5L6b5oqY5YO55Yi477yM5Zaa6LW36ICB6aGn5a6i55qE5rOo5oSPDQorIOesrOS6lOe+pDrmoLnmk5rmlrDpoaflrqLnmoTpnIDmsYLmjqjolqbpganlkIjnmoTntYTlkIjlhKrmg6ANCg0K57Wx6KiI5LiK5pyA5aW955qE5YiG576k5Lmf5piv5a+m5YuZ5LiK5pyA5aW955qE5YiG576k5ZeO77yfIA0KDQorIOS4jeS4gOWumu+8jOe1seioiOiuk+aIkeWAkeWPr+S7peWBh+ioreS4gOS4i+izh+aWmeeahOWIhuW4g++8jOWvpumam+S4iuaIkeWAkemChOaYr+imgeeci+S4gOS4i+ecn+Wvpuizh+aWmeeahOWIhuW4g+S7peWPiuimluimuuWMluWIhue+pOWHuuS+hueahOaoo+iyjA0KKyDpgJrluLjntbHoqIjkuIrmiJHlgJHlj6/ku6XoqZXkvLDliIbnvqTnmoTmlYjmnpzvvIznnIvog73kuI3og73oia/lpb3nmoTljYDliIbkuI3lkIznvqTnmoTos4fmlpnjgILkvYblr6bli5nkuIrmiJHlgJHlm6DngrropoHkvp3nhafkuI3lkIzml4/nvqTkvobph4/ouqvmiZPpgKDkuI3lkIznmoTmlrnmoYjvvIzmiYDku6XnlbbnhLblr6bli5nkuIrmiJHlgJHlj6/ku6Xmh4noqbLopoHoh6rlt7HooaHph4/mh4noqbLopoHlop7liqDnvqTmlbjmiJbogIXmuJvlsJHnvqTmlbgNCisg57Ch5Zau5L6G6Kqq77yM57Wx6KiI6LyU5Yqp5oiR5YCR6KmV5Lyw5YiG576k5aW95aOe77yM5L2G5YGa5rG6562W55qE5piv5Lq644CC57Wx6KiI6K6T5oiR5YCR5q+U6LyD5pa55L6/55qE5om+5Yiw5LiN5ZCM5peP576k55qE54m56Imy77yM5a+m6Zqb5LiK5oiR5YCR5L6d54Wn54++5a+m5oOF5rOB5Y+v6IO95pyD5pyJ5LiN5ZCM55qE6ICD6YeP44CCDQoNCumZpOS6huiAg+aFrue+pOmWk+WSjOe+pOmWk+i3nembouS5i+Wklu+8jOWvpuWLmeS4iueahOWIhue+pOmAmuW4uOmChOmcgOimgeiAg+aFrumCo+S6m+WboOaVuO+8nyANCg0KKyAg6LOH5paZ6YeP5aSn5bCP5Lmf6KaB6ICD5oWu77yM5aaC6LOH5paZ6YeP5aSn5oiR5YCR55SoS21lYW5z77yb6YeP5bCR55SoSGllcmFyY2hpY2FsDQorICDmiJHlgJHopoHogIPmha7mmK/lkKbmnIlub2lzZSBkYXRh77yM6KaB5ou/5o6J77yM5ZCm5YmH5pyD56C05aOe5YiG576kDQorICDpgJrluLjpgoTmnIPogIPph4/nvqTlhaforornlbDmlbjkvobooaHph4/liIbnvqTnmoTlpb3lo54NCg0KDQoNCiMjIyMjIyA8c3BhbiBpZD0nQ0wnPuWwj+e1hOe4vee1kDwvc3Bhbj4NCg0KKyDpgJnlgIvnr4TkvovmiJHlgJHnlKjliIbnvqTkvobpgZTliLDooYzpirfnmoRTVFDjgIINCisg5LiA6ZaL5aeL5oiR5YCR5bCN5pa85pW05Lu96LOH5paZ5rKS5pyJ5YiG5p6Q5oOz5rOV55qE5pmC5YCZ77yM5oiR5YCR5Yip55So5YiG576k5bCH5peP576k5YiG5Ye65L6G77yM5om+5Yiw5LiN5ZCM5peP576k55qE54m55oCn44CCDQorIOaIkeWAkeWcqOWBmuW4guWgtOWNgOmalOWJjemmluimgeWFiOS6huino+S4jeWQjOeahOmhp+WuouS9oOimgeaKiuWug+aUvuWIsOWTquWAi+W4guWgtO+8jOaJgOS7peaIkeWAkeWBmuWIhue+pOOAgueEtuW+jOeZvOePvuS4jeWQjOaXj+e+pOacieS4jeWQjOeahOeJueaAp++8jOmAmeaZguaIkeWAkeWPr+S7peaKleWFtuaJgOWlve+8jOmHj+i6q+aJk+mAoOS4gOS6m+ihjOmKt+etlueVpeOAguaJgOS7peaIkeWAkeeUqOWwjeeahOihjOmKt+etlueVpeaUvuWcqOWwjeeahOS6uuS6i+eJqeS4iu+8jOaVtOWAi+WwseaPkOWNh+aViOeOh+S6huOAgg0KKyDku6XlvozmiJHlgJHlnKjlgZrluILloLTljYDpmpTnmoTmmYLlgJnopoHmh4LlvpfliKnnlKjliIbnvqTkvobliIbmnpDml4/nvqTnmoTnibnmgKfvvIznhLblvozmiJHlgJHmiY3og73ljrvliLblrprmsbrnrZbjgIINCg0KDQoNCg0KDQotIC0gLQ0KDQo8YnI+PGJyPjxicj48YnI+PGJyPg0KDQo8c3R5bGU+DQouY2FwdGlvbiB7DQogIGNvbG9yOiAjNzc3Ow0KICBtYXJnaW4tdG9wOiAxMHB4Ow0KfQ0KcCBjb2RlIHsNCiAgd2hpdGUtc3BhY2U6IGluaGVyaXQ7DQp9DQpwcmUgew0KICB3b3JkLWJyZWFrOiBub3JtYWw7DQogIHdvcmQtd3JhcDogbm9ybWFsOw0KICBsaW5lLWhlaWdodDogMTsNCn0NCnByZSBjb2RlIHsNCiAgd2hpdGUtc3BhY2U6IGluaGVyaXQ7DQp9DQpwLGxpIHsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCi5yew0KICBsaW5lLWhlaWdodDogMS4yOw0KfQ0KDQp0aXRsZXsNCiAgY29sb3I6ICNjYzAwMDA7DQogIGZvbnQtZmFtaWx5OiAiVHJlYnVjaGV0IE1TIiwgIuW+rui7n+ato+m7kemrlCIsICJNaWNyb3NvZnQgSmhlbmdIZWkiOw0KfQ0KDQpib2R5ew0KICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsNCn0NCg0KaDEsaDIsaDMsaDQsaDV7DQogIGNvbG9yOiAjMDA4ODAwOw0KICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsNCn0NCg0KaDN7DQogIGNvbG9yOiAjYjM2YjAwOw0KICBiYWNrZ3JvdW5kOiAjZmZlMGIzOw0KICBsaW5lLWhlaWdodDogMjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQp9DQoNCmg1ew0KICBjb2xvcjogIzAwNjAwMDsNCiAgYmFja2dyb3VuZDogI2ZmZmZlMDsNCiAgbGluZS1oZWlnaHQ6IDI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KfQ0KaDZ7DQogIGNvbG9yOiAjMDA2MDAwOw0KICBiYWNrZ3JvdW5kOiAjMDBmZmZmOw0KICBsaW5lLWhlaWdodDogMjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQoNCn0NCmVtew0KICBjb2xvcjogIzAwMDBjMDsNCiAgYmFja2dyb3VuZDogI2YwZjBmMDsNCiAgfQ0KPC9zdHlsZT4NCg0K