目錄

前言:從交易記錄到顧客價值

善用商業數據分析的工具和技巧,光靠一份最簡單的交易紀錄(只有顧客ID、交易日期和交易金額三個欄位),我們就可以做一系列很深入、很有價值的顧客價值分析和行銷策略規劃,包括:

圖一、顧客價值管理的層次

圖一、顧客價值管理的層次


從這一些分析我們可以看到公司主要的營收和獲利的重要來源,我們也可以看到這一些產生獲利的群組是不是有成長或者衰退的趨勢;據此我們可以設定行銷的重點,決定行銷的策略,和規劃行銷的工具。除了上述的敘述統計、集群分析、和資料視覺化之外,我們還可以利用這些簡單的交易紀錄:


利用這一些預測我們就可以進行全面客製化的:

圖二、顧客價值管理流程

圖二、顧客價值管理流程


現在行銷重視客製化不同客戶的廣告,來達到精準行銷。主要有兩個階段:


回到目錄



Setup
Sys.setlocale("LC_ALL","C")
[1] "C"
packages = c(
  "dplyr","ggplot2","googleVis","devtools","magrittr","caTools","ROCR","caTools")
existing = as.character(installed.packages()[,1])
for(pkg in packages[!(packages %in% existing)]) install.packages(pkg)
if(!is.element("chorddiag", existing))
  devtools::install_github("mattflor/chorddiag")
Library
rm(list=ls(all=T))
options(digits=4, scipen=12)
library(dplyr)
library(ggplot2)
library(caTools)
package 'caTools' was built under R version 3.5.1
library(ROCR)
package 'ROCR' was built under R version 3.5.1Loading required package: gplots
package 'gplots' was built under R version 3.5.1
Attaching package: 'gplots'

The following object is masked from 'package:stats':

    lowess
library(googleVis)
library(chorddiag)


1. 資料整理

1.1 交易資料 (X)
  • 使用read.table()讀入資料,並設定欄位名稱
X = read.table(
  'purchases.txt', header=FALSE, sep='\t', stringsAsFactors=F)
names(X) = c('cid','amount','date')
X$date = as.Date(X$date)
summary(X)        # 交易次數 51243  # x: transaction 
      cid             amount          date           
 Min.   :    10   Min.   :   5   Min.   :2005-01-02  
 1st Qu.: 57720   1st Qu.:  25   1st Qu.:2009-01-17  
 Median :102440   Median :  30   Median :2011-11-23  
 Mean   :108935   Mean   :  62   Mean   :2011-07-14  
 3rd Qu.:160525   3rd Qu.:  60   3rd Qu.:2013-12-29  
 Max.   :264200   Max.   :4500   Max.   :2015-12-31  
  • 長條圖顯示出交易數目逐年上升
  • 產生直方圖查看資料統計數量
par(cex=0.7)
hist(X$date, "years", las=1, freq=T, xlab="", main="No. Transaction by Year")

  • n_distinct即number of distinct,查看有幾個不一樣的值(多少個顧客)
n_distinct(X$cid) # 18417
[1] 18417
1.2 顧客資料 (A)
  • 將截止日期(2016-01-01)距離交易日期的天數做為變數days,用來計算最近/最遠日購買,以及單一顧客總購買次數、平均購買金額
  • A: 顧客資料
  • 將「交易筆數」匯集成「顧客」
  • mutate: 長出一個新欄位
A = X %>% 
  mutate(days = as.integer(as.Date("2016-01-01") - date)) %>% 
  group_by(cid) %>% summarise(
    recent = min(days),     # 最近購買距今天數
    freq = n(),             # 購買次數
    money = mean(amount),   # 平均購買金額
    senior = max(days),     # 第一次購買距今天數
    since = min(date)       # 第一次購買日期
  ) %>% data.frame
1.4 顧客資料摘要
summary(A)
      cid             recent          freq      
 Min.   :    10   Min.   :   1   Min.   : 1.00  
 1st Qu.: 81990   1st Qu.: 244   1st Qu.: 1.00  
 Median :136430   Median :1070   Median : 2.00  
 Mean   :137574   Mean   :1253   Mean   : 2.78  
 3rd Qu.:195100   3rd Qu.:2130   3rd Qu.: 3.00  
 Max.   :264200   Max.   :4014   Max.   :45.00  
     money          senior         since           
 Min.   :   5   Min.   :   1   Min.   :2005-01-02  
 1st Qu.:  22   1st Qu.: 988   1st Qu.:2007-10-23  
 Median :  30   Median :2087   Median :2010-04-15  
 Mean   :  58   Mean   :1984   Mean   :2010-07-26  
 3rd Qu.:  50   3rd Qu.:2992   3rd Qu.:2013-04-18  
 Max.   :4500   Max.   :4016   Max.   :2015-12-31  
1.5 變數的分布狀況
  • recency:愈小表示顧客最近有來消費;愈大則代表很久沒來光顧
    • 左比右高,代表一直有顧客來消費
  • seniority:愈小是新進顧客;愈大則是老顧客
    • 第一次消費到截止日的時間會受到第一次日期影響,越短的消費日期不一定代表是一次性消費的顧客,可能會包含持續消費的顧客
    • 若要分析是否為忠誠顧客,必須考慮到消費頻率
  • frequency: 愈大表示顧客很常光顧(頻率高)
    • 消費次數多落在1次左右,而消費過10次的人也有,表示有忠實顧客群
  • money:一般做分析時,金錢相關的變數都需取log
    • 取10筆來進行log處理,x軸值再乘以10轉換成原始消費數字,消費金額多落在30元左右(1:10元, 1.5:30元, 2:100元, 2.5:300元, 3:1000元, 3.5:3000元)
  • 圖形上越長的條狀,是指該期間吸收很多新顧客
  • pmin()主要用途是設一個上限,並明確做出一個範圍
p0 = par(cex=0.8, mfrow=c(2,2), mar=c(3,3,4,2))
hist(A$recent,20,main="recency",ylab="",xlab="")
hist(pmin(A$freq, 10),0:10,main="frequency",ylab="",xlab="")
hist(A$senior,20,main="seniority",ylab="",xlab="")
hist(log(A$money,10),main="log(money)",ylab="",xlab="")


回到目錄



2. 層級式集群分析(靜態分群)

2.1 RFM顧客分群
  • 依照統計方式分群
  • 1-10代表分10群,數字為族群大小
  • 資料量大,故做k-mean會比較保險
  • 集群分析,需要做距離矩陣
set.seed(111)
A$grp = kmeans(scale(A[,2:4]),10)$cluster   
table(A$grp)

   1    2    3    4    5    6    7    8    9   10 
1073 2266 1296 2237 3207 1942 1781 2392 2096  127 
2.2 顧客群組屬性
  • 泡泡圖 同時顯示4種屬性:x軸、y軸、大小(反映族群對店家的營收貢獻)、顏色
    • 除了能視覺化之外,泡泡隨時間的動態變化更重要
    • 藉由動態資料的方式(不要把全部的資料做aggration),能夠看到屬性隨著時間的變換
    • 以10年為例,可以依照不同年份年底做一次統計,這樣泡泡就會動(但可能每一年的分群規則都不一樣)
    • 泡泡圖圓圈裡的數字代表該族群有多少人
  • 我們最希望看到圈圈是紅色且出現在右上角
    • 頻率高
    • 客單價高
    • 最近有消費
  • 主力顧客群為:圓圈127
    • 重點放在保留這一族群的顧客
    • 希望提高他的購買頻率(往右拉)
    • 可採用促銷打折的行銷方案
  • 愈紅代表沉睡顧客,即將流失的顧客
  • X軸與Y軸分別放最重要的變數,並表示出各族群的貢獻
  • 選擇重要的變數來表達目前各族群顧客的活動狀況:
group_by(A, grp) %>% summarise(
  recent=mean(recent), 
  freq=mean(freq), 
  money=mean(money), 
  size=n() ) %>% 
  mutate( revenue = size*money/1000 )  %>% 
  filter(size > 1) %>% 
  ggplot(aes(x=freq, y=money)) +
  geom_point(aes(size=revenue, col=recent),alpha=0.5) +
  scale_size(range=c(4,30)) +
  scale_color_gradient(low="green",high="red") +
  scale_x_log10() + scale_y_log10(limits=c(30,3000)) + 
  geom_text(aes(label = size ),size=3) +
  theme_bw() + guides(size=F) +
  labs(title="Customer Segements",
       subtitle="(bubble_size:revenue_contribution; text:group_size)",
       color="Recency") +
  xlab("Frequency (log)") + ylab("Average Transaction Amount (log)")  


回到目錄



3. 規則分群(動態趨勢)

3.1 顧客分群規則
  • 設定顧客族群名稱
  • 依照該年度整體表現區分顧客群
STS = c("N1","N2","R1","R2","S1","S2","S3")
Status = function(rx,fx,mx,sx,K) {factor(
  ifelse(sx < 2*K,
         ifelse(fx*mx > 50, "N2", "N1"),
         ifelse(rx < 2*K,
                ifelse(sx/fx < 0.75*K,"R2","R1"),
                ifelse(rx < 3*K,"S1",
                       ifelse(rx < 4*K,"S2","S3")))), STS)}

圖三、顧客分群規則

  • N1:新顧客
  • N2:新潛力顧客
  • R1:主力顧客
  • R2:核心顧客
  • S1:瞌睡顧客
  • S2:半睡顧客
  • S3:沉睡顧客

補充:鯨魚圖

補充:鯨魚圖

  • 藍線是公司的累積獲利,依據顧客對公司獲利的貢獻度由大到小:
    • 淺藍色(頭):讓公司獲利增加的顧客
      • 最理想的組合
      • 人數很少
      • 容易被搶走
      • 選擇性保留
    • 水藍色(背):讓公司獲利打平的顧客
      • 幫助不大
      • 人數最多,產生規模經濟
      • 選擇性吸收
    • 深藍色(尾):讓公司虧錢的顧客
      • 選擇性發展


3.2 平均購買週期
  • 找「有購買過2次以上的購買顧客」的平均購買週期
  • 回購顧客的平均購買週期 K = 521 days,意思是平均兩年才買一次。
  • 也可以用實際的狀況來做分群,A$freq>1 是指購買頻率。
K = as.integer(sum(A$senior[A$freq>1]) / sum(A$freq[A$freq>1])); K
[1] 521
3.3 滑動資料窗格
Y = list()              # 建立一個空的LIST
for(y in 2010:2015) {   # 每年年底將顧客資料彙整成一個資料框
  D = as.Date(paste0(c(y, y-1),"-12-31")) # 當期、前期的期末日期 
  Y[[paste0("Y",y)]] = X %>%        # 從交易資料做起
    filter(date <= D[1]) %>%        # 將資料切齊到期末日期
    mutate(days = 1 + as.integer(D[1] - date)) %>%   # 交易距期末天數
    group_by(cid) %>% summarise(    # 依顧客彙總 ...
      recent = min(days),           #   最後一次購買距期末天數   
      freq = n(),                   #   購買次數 (至期末為止)   
      money = mean(amount),         #   平均購買金額 (至期末為止)
      senior = max(days),           #   第一次購買距期末天數
      status = Status(recent,freq,money,senior,K),  # 期末狀態
      since = min(date),                      # 第一次購買日期
      y_freq = sum(date > D[2]),              # 當期購買次數
      y_revenue = sum(amount[date > D[2]])    # 當期購買金額
    ) %>% data.frame }    # 整個y,是一個迴圈變數,將所有dataframe置入
  • 每一個顧客,會隨時間而有不同的結果產生(「行銷滑水道」重點:水缸大小、水缸間流動的速度有多大)
  • 當有很多元件時,可以用這種Y$Y2015方法。
  • 同一個顧客值會不一樣。
head(Y$Y2015)
  cid recent freq  money senior status      since
1  10   3829    1  30.00   3829     S3 2005-07-08
2  80    343    7  71.43   3751     R1 2005-09-24
3  90    758   10 115.80   3783     R2 2005-08-23
4 120   1401    1  20.00   1401     S1 2012-03-01
5 130   2970    2  50.00   3710     S3 2005-11-04
6 160   2963    2  30.00   3577     S3 2006-03-17
  y_freq y_revenue
1      0         0
2      1        80
3      0         0
4      0         0
5      0         0
6      0         0
3.4 每年年底的累計顧客人數
sapply(Y, nrow)   # list 配上 sapply,非常好用
Y2010 Y2011 Y2012 Y2013 Y2014 Y2015 
10407 11674 13562 15468 16905 18417 
3.5 族群大小變化趨勢
  • 用sapply就是將Y每一個元素做nrow這個動作,並計算每年底這時間為止有多少資料總筆數。
  • s1(含)以下的皆為目前有消費行為的顧客
  • s3會從2010逐漸累積到2015,因此需要在分析時注意累積的問題
  • 活躍顧客:淺藍色以下(2014達到巔峰,後續便沒有什麼成長)
cols = c("gold","orange","blue","green","pink","magenta","darkred")
sapply(Y, function(df) table(df$status)) %>% barplot(col=cols)
legend("topleft",rev(STS),fill=rev(cols))

3.6 族群屬性動態分析
CustSegments = do.call(rbind, lapply(Y, function(d) {
  group_by(d, status) %>% summarise(      #以顧客族群做為分群標準,以下以族群為單位
    average_frequency = mean(freq),       #平均消費次數
    average_amount = mean(money),         #平均消費金額
    total_revenue = sum(y_revenue),       #總消費收益
    total_no_orders = sum(y_freq),        #所有消費次數
    average_recency = mean(recent),       #最後一次消費距今的平均天數
    average_seniority = mean(senior),     #第一次消費距今的平均天數
    group_size = n()                      #計算族群大小
  )})) %>% ungroup %>% 
  mutate(year=rep(2010:2015, each=7)) %>% data.frame   #以年區分各族群表現
head(CustSegments)
  status average_frequency average_amount total_revenue
1     N1             1.154          26.96         41046
2     N2             2.263          96.00        121034
3     R1             2.674          43.25         19407
4     R2             5.406          60.31        108631
5     S1             1.267          44.61             0
6     S2             1.167          60.65             0
  total_no_orders average_recency average_seniority
1            1500           449.2             507.1
2            1416           241.2             629.9
3             435           492.4            1470.0
4            1588           157.1            1547.3
5               0          1289.3            1373.1
6               0          1889.7            1922.4
  group_size year
1       3330 2010
2       1655 2010
3       1298 2010
4       1547 2010
5       2203 2010
6        360 2010
  • 依據客群與年份,顯示參數之間的動態泡泡圖
plot( gvisMotionChart(
  CustSegments, "status", "year",
  options=list(width=900, height=600) ) )

圖四、顧客分群規則

補充:apply系列公式

補充:apply系列公式

  • 因為用傳統的方式要重複做好幾遍,Debug不易,因此有了apply系列
  • Lapply和sapply本質上差不多(sapply是進階版)
    • Lapply會把回傳的資料放進一個list裡,list的elements可以是不同長度、資料型態或三個模型
    • Sapply會把回傳的資料,依據資料型態,自動生成一個vector或matrix


3.7 族群屬性動態分析
  • 整合2014及2015年各族群消費資料
  • 流量矩陣(做一個table即可,可看到群間的流動數度)
df = merge(Y$Y2014[,c(1,6)], Y$Y2015[,c(1,6)],
           by="cid", all.x=T)
tx = table(df$status.x, df$status.y) %>% 
  as.data.frame.matrix() %>% as.matrix()
tx   
     N1   N2   R1   R2  S1   S2   S3
N1 1705  381  144   45 831    0    0
N2    0 1131  267  430 263    0    0
R1    0    0 1240   43 819    0    0
R2    0    0  199 1742  75    0    0
S1    0    0  115    3 819 1026    0
S2    0    0   78    1   0  692 1339
S3    0    0   97    0   0    0 3420
  • 可以做個table簡單的矩陣,以表現出目前流量比較
tx %>% prop.table(1) %>% round(3)   # 流量矩陣(%),並計算到小數點第三位
      N1    N2    R1    R2    S1    S2    S3
N1 0.549 0.123 0.046 0.014 0.268 0.000 0.000
N2 0.000 0.541 0.128 0.206 0.126 0.000 0.000
R1 0.000 0.000 0.590 0.020 0.390 0.000 0.000
R2 0.000 0.000 0.099 0.864 0.037 0.000 0.000
S1 0.000 0.000 0.059 0.002 0.417 0.523 0.000
S2 0.000 0.000 0.037 0.000 0.000 0.328 0.635
S3 0.000 0.000 0.028 0.000 0.000 0.000 0.972
3.8 互動式流量分析
  • 各族群流量,包含流入、不變、流出
  • chore diagram(和弦圖、樂譜符號圖,可以變動,可以看出流數)
  • 圓周弧度:族群人數
  • 中間的小丘:保留在族群內的人
  • 中間的弧線:族群間流動的人數
chorddiag(tx, groupColors=cols)     


回到目錄



4. 建立模型

在這個案例裡面,我們的資料是收到Y2015年底,所以我們可以假設現在的時間是Y2015年底,我們想要用現有的資料建立模型,來預測每一位顧客:

但是,我們並沒有Y2016的資料,為了要建立模型,我們需要先把時間回推一期,也就是說:

假如Y2016的情況(跟Y2015比)沒有太大的變化的話,接下來我們就可以

4.1 準備資料

我們用Y2014年底的資料做自變數,Y2015年的資料做應變數

  • y在2015的資料當中
  • left_join:2個資料框,類似查表的概念,結合兩個資料框,使用cid,把後面的資料抄到前面的資料(如果欄位表頭不一致,以left為主)
  • .x和.y:R當中自動加的
  • y_revenue.y:2015來買多少錢
  • y_freq.y:2015會不會來買
CX = left_join(Y$Y2014, Y$Y2015[,c(1,8,9)], by="cid") 
head(CX)
  cid recent freq money senior status      since
1  10   3464    1  30.0   3464     S3 2005-07-08
2  80    302    6  70.0   3386     R1 2005-09-24
3  90    393   10 115.8   3418     R2 2005-08-23
4 120   1036    1  20.0   1036     N1 2012-03-01
5 130   2605    2  50.0   3345     S3 2005-11-04
6 160   2598    2  30.0   3212     S3 2006-03-17
  y_freq.x y_revenue.x y_freq.y y_revenue.y
1        0           0        0           0
2        1          80        1          80
3        0           0        0           0
4        0           0        0           0
5        0           0        0           0
6        0           0        0           0
  • X=Y\(Y2014 Y=Y\)Y2015[,c(1,8,9):1是cid,並用這個欄位來做建置。
  • left_join()兩邊都要有cid才有辦法做join,但如果我只有一列那我只留下左邊。
  • y_freq.x y_revenue.x y_freq.y 需要兩個Y,做類別變數。
  • 需要看2015年會不會再次購買,需要看y_freq.y,Retain (保留率)需要大於0
names(CX)[8:11] = c("freq0","revenue0","Retain", "Revenue")
CX$Retain = CX$Retain > 0      
head(CX)
  cid recent freq money senior status      since freq0
1  10   3464    1  30.0   3464     S3 2005-07-08     0
2  80    302    6  70.0   3386     R1 2005-09-24     1
3  90    393   10 115.8   3418     R2 2005-08-23     0
4 120   1036    1  20.0   1036     N1 2012-03-01     0
5 130   2605    2  50.0   3345     S3 2005-11-04     0
6 160   2598    2  30.0   3212     S3 2006-03-17     0
  revenue0 Retain Revenue
1        0  FALSE       0
2       80   TRUE      80
3        0  FALSE       0
4        0  FALSE       0
5        0  FALSE       0
6        0  FALSE       0
  • Retain()保留機率 用y_revenue=y
  • Retai做類別模型的Y Revenue做回歸模型的Y
table(CX$Retain) %>% prop.table()  # 平均保留機率 = 22.54%

 FALSE   TRUE 
0.7701 0.2299 
4.2 建立類別模型
mRet = glm(Retain ~ ., CX[,c(2:3,6,8:10)], family=binomial())
summary(mRet)

Call:
glm(formula = Retain ~ ., family = binomial(), data = CX[, c(2:3, 
    6, 8:10)])

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-3.689  -0.473  -0.298  -0.142   3.386  

Coefficients:
             Estimate Std. Error z value
(Intercept) -1.074007   0.089431  -12.01
recent      -0.002067   0.000131  -15.73
freq         0.095217   0.013882    6.86
statusN2     0.669429   0.070234    9.53
statusR1     0.488321   0.084389    5.79
statusR2     1.290002   0.110841   11.64
statusS1     0.670604   0.146532    4.58
statusS2     1.353554   0.208210    6.50
statusS3     2.573689   0.275786    9.33
freq0        0.566557   0.065532    8.65
revenue0    -0.000132   0.000135   -0.98
                   Pr(>|z|)    
(Intercept)         < 2e-16 ***
recent              < 2e-16 ***
freq        0.0000000000069 ***
statusN2            < 2e-16 ***
statusR1    0.0000000071864 ***
statusR2            < 2e-16 ***
statusS1    0.0000047279944 ***
statusS2    0.0000000000798 ***
statusS3            < 2e-16 ***
freq0               < 2e-16 ***
revenue0               0.33    
---
Signif. codes:  
0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 18228  on 16904  degrees of freedom
Residual deviance: 11766  on 16894  degrees of freedom
AIC: 11788

Number of Fisher Scoring iterations: 6
4.3 估計類別模型的準確性
  • 混淆矩陣 (Confusion Matrix)
pred = predict(mRet,type="response")
table(pred>0.5,CX$Retain) 
       
        FALSE  TRUE
  FALSE 12045  1530
  TRUE    974  2356
table(pred>0.5,CX$Retain) %>% 
  {sum(diag(.))/sum(.)}            # 正確率(ACC): 85.19% 
[1] 0.8519
colAUC(pred,CX$Retain)             # 辯識率(AUC): 87.92%
                 [,1]
FALSE vs. TRUE 0.8792
prediction(pred, CX$Retain) %>%    # ROC CURVE 
  performance("tpr", "fpr") %>% 
  plot(print.cutoffs.at=seq(0,1,0.1))

4.4 建立數量模型
dx = subset(CX, Revenue > 0)   # 只對有來購買的人做模型(假如有來買的人,會買多少錢?)
mRev = lm(log(Revenue) ~ recent + freq + log(1+money) + senior +
          status + freq0 + log(1+revenue0), dx)  
summary(mRev)   # 判定係數:R2 = 0.713   # 比較取了log()的R-square

Call:
lm(formula = log(Revenue) ~ recent + freq + log(1 + money) + 
    senior + status + freq0 + log(1 + revenue0), data = dx)

Residuals:
   Min     1Q Median     3Q    Max 
-3.245 -0.209 -0.067  0.205  3.435 

Coefficients:
                    Estimate Std. Error t value
(Intercept)        0.0587930  0.0458344    1.28
recent             0.0003541  0.0000507    6.98
freq               0.0526850  0.0046504   11.33
log(1 + money)     0.9320818  0.0135203   68.94
senior            -0.0001369  0.0000182   -7.52
statusN2           0.0127716  0.0262656    0.49
statusR1           0.1927532  0.0407579    4.73
statusR2           0.0297685  0.0352479    0.84
statusS1           0.0082406  0.0630355    0.13
statusS2          -0.2406398  0.0865731   -2.78
statusS3          -0.3667341  0.1181061   -3.11
freq0              0.0103133  0.0172551    0.60
log(1 + revenue0)  0.0632756  0.0094003    6.73
                          Pr(>|t|)    
(Intercept)                 0.1997    
recent            0.00000000000337 ***
freq                       < 2e-16 ***
log(1 + money)             < 2e-16 ***
senior            0.00000000000007 ***
statusN2                    0.6268    
statusR1          0.00000233405019 ***
statusR2                    0.3984    
statusS1                    0.8960    
statusS2                    0.0055 ** 
statusS3                    0.0019 ** 
freq0                       0.5501    
log(1 + revenue0) 0.00000000001930 ***
---
Signif. codes:  
0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.463 on 3873 degrees of freedom
Multiple R-squared:  0.713, Adjusted R-squared:  0.712 
F-statistic:  802 on 12 and 3873 DF,  p-value: <2e-16
plot(log(dx$Revenue), predict(mRev), col='pink', cex=0.65)
abline(0,1,col='red') 

  • Revenue要做線性模時必須log來做
  • 紅線是預測值,粉紅小圈圈是實際值


回到目錄



5. 估計顧客終生價值(CLV)

5.1 Y2016的預測值
  • 因為沒有未來的資料,需要把時間往回推一期,也就是使用模型對Y2015年底的資料做預測,對資料 中的每一位顧客,預測她們在Y2016的保留率和購買金額。
CX = Y$Y2015
names(CX)[8:9] = c("freq0","revenue0")
CX$ProbRetain = predict(mRet,CX,type='response')   # 預測Y2016保留率
CX$PredRevenue = exp(predict(mRev,CX))   # 預測Y2016購買金額
par(mfrow=c(1,2), mar=c(5,3,3,2), cex=0.8)
hist(CX$ProbRetain,main="ProbRetain", ylab="")   #顧客保留率落在0.1左右,這部分代表有些顧客消費並不頻繁
hist(log(CX$PredRevenue,10),main="log(PredRevenue)", ylab="")  #根據直方圖顯示,預測出來的總收益分布與原先的分布情況相似


5.2 估計顧客終生價值(CLV)
顧客\(i\)的終生價值

\[ V_i = \sum_{t=0}^N g \times m_i \frac{r_i^t}{(1+d)^t} = g \times m_i \sum_{t=0}^N (\frac{r_i}{1+d})^t \]

Assume顧客不會永遠忠實,因此採期數計算,由公式得出每個顧客對公司值多少錢:

\(m_i\)\(r_i\):顧客\(i\)的預期(每期)營收貢獻、保留機率
\(g\)\(d\):公司的(稅前)營業利潤利率、資金成本
g = 0.5   # (稅前)獲利率
N = 5     # 期數 = 5
d = 0.1   # 利率 = 10%
CX$CLV = g * CX$PredRevenue * rowSums(sapply(
  0:N, function(i) (CX$ProbRetain/(1+d))^i ) )
summary(CX$CLV)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
      3      16      24      51      45    5094 
par(mar=c(3,3,3,1), cex=0.8)
hist(log(CX$CLV,10), xlab="", ylab="")   # CLV是用錢算出來的,所以也是錢,需要用log來算   # 取log後所得的值約為30塊/一顧客

5.3 比較各族群的價值

  • 消費金額高的顧客不少(尾巴長)
  • 新顧客與沉睡顧客的價值差不多
  • 新顧客變成主力顧客的機率不大
sapply(CX[,10:12], tapply, CX$status, mean)   # 各族群的平均營收貢獻、保留機率、終生價值
   ProbRetain PredRevenue    CLV
N1    0.20269       31.98  20.17
N2    0.44075      131.23 110.89
R1    0.34150       69.85  54.60
R2    0.74925       91.27 136.31
S1    0.05724       56.10  29.66
S2    0.03475       49.48  25.58
S3    0.02326       49.36  25.17
  • 新顧客(N1)跟睡著的顧客(S1、S2、S3)所帶給這間店的價值其實差不多
par(mar=c(3,3,4,2), cex=0.8)
boxplot(log(CLV)~status, CX, main="CLV by Groups")


回到目錄



6. 設定行銷策略、規劃行銷工具

首先進行各族群的屬性統整,再設定行銷策略與工具。


回到目錄



7. 選擇行銷對象

給定某一行銷工具的成本和預期效益,選擇可以施行這項工具的對象。

7.1 對R2族群進行保留

R2族群的預測保留率和購買金額

par(mfrow=c(1,2), mar=c(4,3,3,2), cex=0.8)
hist(CX$ProbRetain[CX$status=="R2"],main="ProbRetain",xlab="")
hist(log(CX$PredRevenue[CX$status=="R2"],10),main="PredRevenue",xlab="")

7.2 估計預期報酬

假設行銷工具的成本和預期效益為以下(給定假設)

  • 成本:藉由過去經驗所得到之行銷工具成本的假設數值
  • 效益:顧客接受到該行銷工具所產生的購買行為(下一期的購買機率)
cost = 10        
effect = 0.75    

估計這項行銷工具對每一位R2顧客的預期報酬

Target = subset(CX, status=="R2")
Target$ExpReturn = (effect - Target$ProbRetain) * Target$PredRevenue - cost
summary(Target$ExpReturn)   # 因為保留機率(ProbRetain)設定為0.75,即表示>0.75的族群不能使用這支程式(會導致預期報償為負值)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 -515.8   -15.4   -11.5   -10.3    -8.1   646.9 
  • 這一項工具對R2顧客的預期報酬是負的,商業數據分析不能用平均值做分析
7.3 選擇行銷對象

但是,我們還是可以從R2中挑出許多預期報酬很大的行銷對象

Target %>% arrange(desc(ExpReturn)) %>% select(cid, ExpReturn) %>% head(15)  #找出ExpReturn前15名
      cid ExpReturn
1  141340    646.85
2  164930    609.02
3    2190    323.38
4  172750    305.75
5  156280    289.41
6  190570    236.91
7  134030    199.29
8  141430    150.73
9  123480    134.52
10  65830    110.61
11 150890    107.18
12 134590     99.48
13  72000     92.55
14 133080     84.54
15 147510     77.18
  • 針對性行銷: 將決定下到每個人身上,而不再是以群體為分析對象,可以得到addition revenue
sum(Target$ExpReturn > 0)       # 可實施對象:258
[1] 258

在R2之中,有258人的預期報酬大於零,如果對這258人使用這項工具,我們的期望報酬是:

sum(Target$ExpReturn[Target$ExpReturn > 0])   # 預期報酬:6464
[1] 6464
QUIZ:

我們可以算出對所有的族群實施這項工具的期望報酬

Target = CX
Target$ExpReturn = (effect - Target$ProbRetain) * Target$PredRevenue - cost
filter(Target, Target$ExpReturn > 0) %>%
  group_by(status) %>% summarise(
    No.Target = n(),
    AvgROI = mean(ExpReturn),
    TotalROI = sum(ExpReturn) ) %>% data.frame
  status No.Target AvgROI TotalROI
1     N1      2211  9.973    22049
2     N2      1459 47.238    68920
3     R1      1596 25.459    40633
4     R2       258 25.054     6464
5     S1      2645 30.592    80915
6     S2      1609 27.134    43658
7     S3      4495 27.598   124052

這個結果是合理的嗎? 你想要怎麼修正這項分析的程序呢?

  • 數據顯示對已無多少價值的沉睡顧客S3使用此行銷工具,比對主力顧客R2的預期報酬還好超過20倍,實在不合理
  • 設定行銷工具的成本和效益應隨不同族群與過往經驗而變,當報償矩陣裡面的設定值發生變動後,得到的期望報酬也就不同
  • 可能修正的方向:
    • 新顧客群(N1,N2):
      • 由前面的觀察,N1族群的價值與S系列族群CLV差不多,他們是一群流動率很高的人,不需花費太多精力或花招去吸引他們,其投資報酬率太低
      • 相對起來,N2是一群很有潛力的族群,我們可以好好發展,培養他們成為主力客群,因此應投入較多的成本,我們預估在這裡的效益不錯,但不能確定多高
    • 主力顧客群(R1,R2):CLV最高的族群,他們忠實且穩定是我們最想留住並成長的對象,卻開始逐漸出現流失現象,因此應花最多成本在保留他們,增加其黏著度,其投資報酬率可以預見是相當高的。
    • 沉睡顧客群(S1,S2,S3):對於愈來愈龐大的沉睡顧客,我們很難再喚醒他們,最好的方式是從根本解決(不要讓R系列的流失),因此對於S系列,我們不打算投入太多成本


回到目錄



8. 結論

如果你只有顧客ID、交易日期、交易金額三個欄位的話,你可以做的分析包括:

一般而言,這一些分析的結果,足夠讓我們制定顧客發展和顧客保留策略;至於顧客吸收策略,我們通常還需要從CRM撈出顧客個人屬性資料才能做到。


回到目錄







LS0tDQp0aXRsZTogIkNWTe+8mumhp+WuouWDueWAvOeuoeeQhiAiDQphdXRob3I6ICLnrKzkupTntYTvvJrmlr3ph4flvaPjgIHllJDmgJ3nkKrjgIHmpYrlh7HlgKvjgIHpmbPmgKHlrokiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQo8YnI+DQoNCiMjIyA8YSBpZD0idG9wIj48YS8+IOebrumMhA0KDQojIyMjIOeroOevgOethuiomA0KDQpb5YmN6KiA77ya5b6e5Lqk5piT6KiY6YyE5Yiw6aGn5a6i5YO55YC8XSgjbjApIDxicj4NClsxLiDos4fmlpnmlbTnkIZdKCNuMSkgPGJyPg0KWzIuIOWxpOe0muW8j+mbhue+pOWIhuaekF0oI24yKSA8YnI+DQpbMy4g6KaP5YmH5YiG576kXSgjbjMpIDxicj4NCls0LiDlu7rnq4vmqKHlnotdKCNuNCkgPGJyPg0KWzUuIOS8sOioiOmhp+Wuoue1gueUn+WDueWAvF0oI241KSA8YnI+DQpbNi4g6Kit5a6a6KGM6Yq3562W55Wl44CB6KaP5YqD6KGM6Yq35bel5YW3XSgjbjYpIDxicj4NCls3LiDpgbjmk4fooYzpirflsI3osaFdKCNuNykgPGJyPg0KWzguIOe1kOirll0oI244KSA8YnI+DQoNCiMjIyMg5bCP57WE6YeN6bue5pW055CGDQpbMS4g6aGn5a6i5YO55YC8566h55CG5rWB56iL5ZyWXSgjZzApIDxicj4NClsyLiBSRk3lkI3oqZ7op6Pph4tdKCNnMSkgPGJyPg0KWzMuIOazoeazoeWcluWIhuaekF0oI2cyKSA8YnI+DQpbNC4g6aGn5a6i5YiG576k5ZG95ZCNXSgjZzMpIDxicj4NCls1LiDpr6jprZrlnJZdKCNnNCkgPGJyPg0KWzYuIGxhcHBseSB2cyBzYXBwbHldKCNnNSkgPGJyPg0KWzcuIENMVuWIhuaekF0oI2c2KSA8YnI+DQpbOC4g6KGM6Yq3562W55Wl6IiH5bel5YW3XSgjZzcpIDxicj4NCls5LiBRVUlaXSgjZzgpIDxicj4NCg0KDQo8YnI+PGhyPg0KDQojIyMgPGEgaWQ9Im4wIj48L2E+IOWJjeiogO+8muW+nuS6pOaYk+iomOmMhOWIsOmhp+WuouWDueWAvA0KDQrlloTnlKjllYbmpa3mlbjmk5rliIbmnpDnmoTlt6XlhbflkozmioDlt6fvvIzlhYnpnaDkuIDku73mnIDnsKHllq7nmoTkuqTmmJPntIDpjIQo5Y+q5pyJ6aGn5a6iSUTjgIHkuqTmmJPml6XmnJ/lkozkuqTmmJPph5HpoY3kuInlgIvmrITkvY0p77yM5oiR5YCR5bCx5Y+v5Lul5YGa5LiA57O75YiX5b6I5rex5YWl44CB5b6I5pyJ5YO55YC855qE6aGn5a6i5YO55YC85YiG5p6Q5ZKM6KGM6Yq3562W55Wl6KaP5YqD77yM5YyF5ous77yaDQoNCisgKirkuqTmmJPoqJjpjITliIbmnpAqKu+8mg0KICAgICsg5pWY6L+w57Wx6KiIDQogICAgKyDotqjli6LjgIHkuqTlj4nliIbmnpANCiAgICArIOizh+aWmeimluimuuWMlg0KDQorICoq6aGn5a6i576k57WE6IiH5qiZ57GkKirvvJoNCiAgICArIOmbhue+pOWIhuaekA0KICAgICsg576k57WE5bGs5oCn5YiG5p6QDQogICAgKyDntYTplpPmtYHli5XmqZ/njocNCiAgICArIOmhp+WuoijlgIvkurop5rWB5YuV5qmf546HDQoNCg0KPGNlbnRlcj4NCg0KIVvlnJbkuIDjgIHpoaflrqLlg7nlgLznrqHnkIbnmoTlsaTmrKFdKGZpZy9maWcxLnBuZykNCg0KPC9jZW50ZXI+DQoNCjxicj7lvp7pgJnkuIDkupvliIbmnpDmiJHlgJHlj6/ku6XnnIvliLDlhazlj7jkuLvopoHnmoTnh5/mlLblkoznjbLliKnnmoTph43opoHkvobmupDvvIzmiJHlgJHkuZ/lj6/ku6XnnIvliLDpgJnkuIDkupvnlKLnlJ/njbLliKnnmoTnvqTntYTmmK/kuI3mmK/mnInmiJDplbfmiJbogIXoobDpgIDnmoTotqjli6LvvJvmk5rmraTmiJHlgJHlj6/ku6XoqK3lrprooYzpirfnmoTph43pu57vvIzmsbrlrprooYzpirfnmoTnrZbnlaXvvIzlkozopo/lioPooYzpirfnmoTlt6XlhbfjgILpmaTkuobkuIrov7DnmoTmlZjov7DntbHoqIjjgIHpm4bnvqTliIbmnpDjgIHlkozos4fmlpnoppboprrljJbkuYvlpJbvvIzmiJHlgJHpgoTlj6/ku6XliKnnlKjpgJnkupvnsKHllq7nmoTkuqTmmJPntIDpjITvvJoNCg0KKyAqKuW7uueri+mgkOa4rOaAp+aooeWeiyoq77yM6aCQ5ris5q+P5LiA5L2N6aGn5a6i55qE77yaDQogICAgKyDkv53nlZnmqZ/njocNCiAgICArIOmgkOacn+eHn+aUtg0KICAgICsg57WE6ZaT6K6K5o+b5qmf546HDQogICAgKyDkuIvmrKHlj6/og73os7zosrfmmYLplpMNCg0KPGJyPuWIqeeUqOmAmeS4gOS6m+mgkOa4rOaIkeWAkeWwseWPr+S7pemAsuihjOWFqOmdouWuouijveWMlueahO+8miANCg0KKyAqKumhp+WuouWDueWAvOeuoeeQhioq77yaDQogICAgKyDpoaflrqLntYLnlJ/lg7nlgLwNCiAgICArIOmhp+WuouWQuOaUtuetlueVpQ0KICAgICsg6aGn5a6i55m85bGV562W55WlDQogICAgKyDpoaflrqLkv53nlZnnrZbnlaUNCg0KKyAqKumHneWwjeaAp+ihjOmKtyoq77yaDQogICAgKyDoqK3oqIjooYzpirfmlrnmoYgNCiAgICArIOmBuOaTh+ihjOmKt+aWueahiA0KICAgICsg6YG45pOH6KGM6Yq35bCN6LGhDQoNCjxjZW50ZXI+DQoNCiA8YSBpZD0iZzAiPjwvYT4gIA0KIA0KICFb5ZyW5LqM44CB6aGn5a6i5YO55YC8566h55CG5rWB56iLXShmaWcvZmlnMi5wbmcpDQoNCjwvY2VudGVyPg0KDQo8YnI+54++5Zyo6KGM6Yq36YeN6KaW5a6i6KO95YyW5LiN5ZCM5a6i5oi255qE5buj5ZGK77yM5L6G6YGU5Yiw57K+5rqW6KGM6Yq344CC5Li76KaB5pyJ5YWp5YCL6ZqO5q6177yaDQoNCisg56ys5LiA6ZqO5q6177ya5YWI5YiG576k77yM5YGa5Ye65LiN5ZCM6Zq76Z2i5bCN5LiN5ZCM5raI6LK75peP576k55qE5buj5ZGKDQorIOesrOS6jOmajuaute+8mumgkOa4rOWQhOaXj+e+pOS4re+8jOacieWTquS6m+S6uuacg+m7nuaTiumAmeWAi+W7o+WRiu+8jOWGjeWwjeS7luaKleaUvg0KDQogPGJyPg0KIA0KW+WbnuWIsOebrumMhF0oI3RvcCkgPGJyPg0KDQo8YnI+PGhyPg0KDQojIyMjIyBTZXR1cCANCmBgYHtyfQ0KU3lzLnNldGxvY2FsZSgiTENfQUxMIiwiQyIpDQpwYWNrYWdlcyA9IGMoDQogICJkcGx5ciIsImdncGxvdDIiLCJnb29nbGVWaXMiLCJkZXZ0b29scyIsIm1hZ3JpdHRyIiwiY2FUb29scyIsIlJPQ1IiLCJjYVRvb2xzIikNCmV4aXN0aW5nID0gYXMuY2hhcmFjdGVyKGluc3RhbGxlZC5wYWNrYWdlcygpWywxXSkNCmZvcihwa2cgaW4gcGFja2FnZXNbIShwYWNrYWdlcyAlaW4lIGV4aXN0aW5nKV0pIGluc3RhbGwucGFja2FnZXMocGtnKQ0KDQppZighaXMuZWxlbWVudCgiY2hvcmRkaWFnIiwgZXhpc3RpbmcpKQ0KICBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoIm1hdHRmbG9yL2Nob3JkZGlhZyIpDQpgYGANCg0KIyMjIyMgTGlicmFyeQ0KYGBge3IgZWNobz1ULCBtZXNzYWdlPUYsIGNhY2hlPUYsIHdhcm5pbmc9Rn0NCnJtKGxpc3Q9bHMoYWxsPVQpKQ0Kb3B0aW9ucyhkaWdpdHM9NCwgc2NpcGVuPTEyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoY2FUb29scykNCmxpYnJhcnkoUk9DUikNCmxpYnJhcnkoZ29vZ2xlVmlzKQ0KbGlicmFyeShjaG9yZGRpYWcpDQpgYGANCjxicj48aHI+DQoNCg0KIyMjIDxhIGlkPSJuMSI+PC9hPiAxLiDos4fmlpnmlbTnkIYNCg0KIyMjIyMgMS4xIOS6pOaYk+izh+aWmSAoWCkNCg0KKyDkvb/nlKhyZWFkLnRhYmxlKCnoroDlhaXos4fmlpnvvIzkuKboqK3lrprmrITkvY3lkI3nqLENCmBgYHtyfQ0KWCA9IHJlYWQudGFibGUoDQogICdwdXJjaGFzZXMudHh0JywgaGVhZGVyPUZBTFNFLCBzZXA9J1x0Jywgc3RyaW5nc0FzRmFjdG9ycz1GKQ0KbmFtZXMoWCkgPSBjKCdjaWQnLCdhbW91bnQnLCdkYXRlJykNClgkZGF0ZSA9IGFzLkRhdGUoWCRkYXRlKQ0Kc3VtbWFyeShYKSAgICAgICAgIyDkuqTmmJPmrKHmlbggNTEyNDMgICMgeDogdHJhbnNhY3Rpb24gDQpgYGANCg0KKyDplbfmop3lnJbpoa/npLrlh7rkuqTmmJPmlbjnm67pgJDlubTkuIrljYcNCisg55Si55Sf55u05pa55ZyW5p+l55yL6LOH5paZ57Wx6KiI5pW46YePDQoNCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTcuMn0NCnBhcihjZXg9MC43KQ0KaGlzdChYJGRhdGUsICJ5ZWFycyIsIGxhcz0xLCBmcmVxPVQsIHhsYWI9IiIsIG1haW49Ik5vLiBUcmFuc2FjdGlvbiBieSBZZWFyIikNCmBgYA0KDQorIG5fZGlzdGluY3TljbNudW1iZXIgb2YgZGlzdGluY3TvvIzmn6XnnIvmnInlub7lgIvkuI3kuIDmqKPnmoTlgLzvvIjlpJrlsJHlgIvpoaflrqLvvIkNCg0KYGBge3J9DQpuX2Rpc3RpbmN0KFgkY2lkKSAjIDE4NDE3DQpgYGANCg0KIyMjIyMgMS4yIOmhp+Wuouizh+aWmSAoQSkNCg0KKyDlsIfmiKrmraLml6XmnJ8oMjAxNi0wMS0wMSnot53pm6LkuqTmmJPml6XmnJ/nmoTlpKnmlbjlgZrngrrorormlbhkYXlz77yM55So5L6G6KiI566X5pyA6L+RL+acgOmBoOaXpeizvOiyt++8jOS7peWPiuWWruS4gOmhp+Wuoue4veizvOiyt+asoeaVuOOAgeW5s+Wdh+izvOiyt+mHkemhjQ0KKyBBOiDpoaflrqLos4fmlpkNCisg5bCH44CM5Lqk5piT562G5pW444CN5Yyv6ZuG5oiQ44CM6aGn5a6i44CNDQorIG11dGF0ZTog6ZW35Ye65LiA5YCL5paw5qyE5L2NDQoNCmBgYHtyfQ0KQSA9IFggJT4lIA0KICBtdXRhdGUoZGF5cyA9IGFzLmludGVnZXIoYXMuRGF0ZSgiMjAxNi0wMS0wMSIpIC0gZGF0ZSkpICU+JSANCiAgZ3JvdXBfYnkoY2lkKSAlPiUgc3VtbWFyaXNlKA0KICAgIHJlY2VudCA9IG1pbihkYXlzKSwgICAgICMg5pyA6L+R6LO86LK36Led5LuK5aSp5pW4DQogICAgZnJlcSA9IG4oKSwgICAgICAgICAgICAgIyDos7zosrfmrKHmlbgNCiAgICBtb25leSA9IG1lYW4oYW1vdW50KSwgICAjIOW5s+Wdh+izvOiyt+mHkemhjQ0KICAgIHNlbmlvciA9IG1heChkYXlzKSwgICAgICMg56ys5LiA5qyh6LO86LK36Led5LuK5aSp5pW4DQogICAgc2luY2UgPSBtaW4oZGF0ZSkgICAgICAgIyDnrKzkuIDmrKHos7zosrfml6XmnJ8NCiAgKSAlPiUgZGF0YS5mcmFtZQ0KYGBgDQoNCiMjIyMjIDEuNCDpoaflrqLos4fmlpnmkZjopoENCmBgYHtyfQ0Kc3VtbWFyeShBKQ0KYGBgDQoNCiMjIyMjIDxhIGlkPSJnMSI+PC9hPiAxLjUg6K6K5pW455qE5YiG5biD54uA5rOBDQoNCisgcmVjZW5jee+8muaEiOWwj+ihqOekuumhp+WuouacgOi/keacieS+hua2iOiyu++8m+aEiOWkp+WJh+S7o+ihqOW+iOS5heaykuS+huWFiemhpw0KICAgICsg5bem5q+U5Y+z6auY77yM5Luj6KGo5LiA55u05pyJ6aGn5a6i5L6G5raI6LK7DQorIHNlbmlvcml0ee+8muaEiOWwj+aYr+aWsOmAsumhp+Wuou+8m+aEiOWkp+WJh+aYr+iAgemhp+Wuog0KICAgICsg56ys5LiA5qyh5raI6LK75Yiw5oiq5q2i5pel55qE5pmC6ZaT5pyD5Y+X5Yiw56ys5LiA5qyh5pel5pyf5b2x6Z+/77yM6LaK55+t55qE5raI6LK75pel5pyf5LiN5LiA5a6a5Luj6KGo5piv5LiA5qyh5oCn5raI6LK755qE6aGn5a6i77yM5Y+v6IO95pyD5YyF5ZCr5oyB57qM5raI6LK755qE6aGn5a6iDQogICAgKyDoi6XopoHliIbmnpDmmK/lkKbngrrlv6DoqqDpoaflrqLvvIzlv4XpoIjogIPmha7liLDmtojosrvpoLvnjocNCisgZnJlcXVlbmN5OiDmhIjlpKfooajnpLrpoaflrqLlvojluLjlhYnpoaco6aC7546H6auYKQ0KICAgICsg5raI6LK75qyh5pW45aSa6JC95ZyoMeasoeW3puWPs++8jOiAjOa2iOiyu+mBjjEw5qyh55qE5Lq65Lmf5pyJ77yM6KGo56S65pyJ5b+g5a+m6aGn5a6i576kDQorIG1vbmV577ya5LiA6Iis5YGa5YiG5p6Q5pmC77yM6YeR6Yyi55u46Zec55qE6K6K5pW46YO96ZyA5Y+WbG9nDQogICAgKyDlj5YxMOethuS+humAsuihjGxvZ+iZleeQhu+8jHjou7jlgLzlho3kuZjku6UxMOi9ieaPm+aIkOWOn+Wni+a2iOiyu+aVuOWtl++8jOa2iOiyu+mHkemhjeWkmuiQveWcqDMw5YWD5bem5Y+zKDHvvJoxMOWFgywgMS4177yaMzDlhYMsIDLvvJoxMDDlhYMsIDIuNe+8mjMwMOWFgywgM++8mjEwMDDlhYMsIDMuNe+8mjMwMDDlhYMpDQorIOWcluW9ouS4iui2iumVt+eahOaineeLgO+8jOaYr+aMh+ipsuacn+mWk+WQuOaUtuW+iOWkmuaWsOmhp+Wuog0KKyBwbWluKCnkuLvopoHnlKjpgJTmmK/oqK3kuIDlgIvkuIrpmZDvvIzkuKbmmI7norrlgZrlh7rkuIDlgIvnr4TlnI0NCg0KYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OH0NCnAwID0gcGFyKGNleD0wLjgsIG1mcm93PWMoMiwyKSwgbWFyPWMoMywzLDQsMikpDQpoaXN0KEEkcmVjZW50LDIwLG1haW49InJlY2VuY3kiLHlsYWI9IiIseGxhYj0iIikNCmhpc3QocG1pbihBJGZyZXEsIDEwKSwwOjEwLG1haW49ImZyZXF1ZW5jeSIseWxhYj0iIix4bGFiPSIiKQ0KaGlzdChBJHNlbmlvciwyMCxtYWluPSJzZW5pb3JpdHkiLHlsYWI9IiIseGxhYj0iIikNCmhpc3QobG9nKEEkbW9uZXksMTApLG1haW49ImxvZyhtb25leSkiLHlsYWI9IiIseGxhYj0iIikNCmBgYA0KIDxicj4NCiANClvlm57liLDnm67pjIRdKCN0b3ApDQoNCjxicj48aHI+DQoNCiMjIyA8YSBpZD0ibjIiPjwvYT4gMi4g5bGk57Sa5byP6ZuG576k5YiG5p6QKOmdnOaFi+WIhue+pCkNCg0KIyMjIyMgPGEgaWQ9ImcyIj48L2E+IDIuMSBSRk3poaflrqLliIbnvqQNCg0KKyDkvp3nhafntbHoqIjmlrnlvI/liIbnvqQNCisgMS0xMOS7o+ihqOWIhjEw576k77yM5pW45a2X54K65peP576k5aSn5bCPDQorIOizh+aWmemHj+Wkp++8jOaVheWBmmstbWVhbuacg+avlOi8g+S/nemaqg0KKyDpm4bnvqTliIbmnpDvvIzpnIDopoHlgZrot53pm6Lnn6npmaMNCg0KYGBge3J9DQpzZXQuc2VlZCgxMTEpDQpBJGdycCA9IGttZWFucyhzY2FsZShBWywyOjRdKSwxMCkkY2x1c3RlciAgIA0KdGFibGUoQSRncnApDQpgYGANCg0KIyMjIyMgMi4yIOmhp+Wuoue+pOe1hOWxrOaApw0KDQorIOazoeazoeWclg0KICAgIOWQjOaZgumhr+ekujTnqK7lsazmgKfvvJp46Lu444CBeei7uOOAgeWkp+Wwj++8iOWPjeaYoOaXj+e+pOWwjeW6l+WutueahOeHn+aUtuiyoueNu++8ieOAgemhj+iJsg0KICAgICsg6Zmk5LqG6IO96KaW6Ka65YyW5LmL5aSW77yM5rOh5rOh6Zqo5pmC6ZaT55qE5YuV5oWL6K6K5YyW5pu06YeN6KaBDQogICAgKyDol4nnlLHli5XmhYvos4fmlpnnmoTmlrnlvI/vvIjkuI3opoHmiorlhajpg6jnmoTos4fmlpnlgZphZ2dyYXRpb27vvInvvIzog73lpKDnnIvliLDlsazmgKfpmqjokZfmmYLplpPnmoTorormj5sNCiAgICArIOS7pTEw5bm054K65L6L77yM5Y+v5Lul5L6d54Wn5LiN5ZCM5bm05Lu95bm05bqV5YGa5LiA5qyh57Wx6KiI77yM6YCZ5qij5rOh5rOh5bCx5pyD5YuV77yI5L2G5Y+v6IO95q+P5LiA5bm055qE5YiG576k6KaP5YmH6YO95LiN5LiA5qij77yJDQogICAgKyDms6Hms6HlnJblnJPlnIjoo6HnmoTmlbjlrZfku6PooajoqbLml4/nvqTmnInlpJrlsJHkuroNCisg5oiR5YCR5pyA5biM5pyb55yL5Yiw5ZyI5ZyI5piv57SF6Imy5LiU5Ye654++5Zyo5Y+z5LiK6KeSDQogICAgKyDpoLvnjofpq5gNCiAgICArIOWuouWWruWDuemrmA0KICAgICsg5pyA6L+R5pyJ5raI6LK7DQorIOS4u+WKm+mhp+Wuoue+pOeCuu+8muWck+WciDEyNw0KICAgICsg6YeN6bue5pS+5Zyo5L+d55WZ6YCZ5LiA5peP576k55qE6aGn5a6iDQogICAgKyDluIzmnJvmj5Dpq5jku5bnmoTos7zosrfpoLvnjoco5b6A5Y+z5ouJKQ0KICAgICsg5Y+v5o6h55So5L+D6Yq35omT5oqY55qE6KGM6Yq35pa55qGIDQorIOaEiOe0heS7o+ihqOayieedoemhp+Wuou+8jOWNs+Wwh+a1geWkseeahOmhp+Wuog0KKyBY6Lu46IiHWei7uOWIhuWIpeaUvuacgOmHjeimgeeahOiuiuaVuO+8jOS4puihqOekuuWHuuWQhOaXj+e+pOeahOiyoueNuw0KKyDpgbjmk4fph43opoHnmoTorormlbjkvobooajpgZTnm67liY3lkITml4/nvqTpoaflrqLnmoTmtLvli5Xni4Dms4HvvJoNCg0KYGBge3IgZmlnLmhlaWdodD00LjUsIGZpZy53aWR0aD04fQ0KZ3JvdXBfYnkoQSwgZ3JwKSAlPiUgc3VtbWFyaXNlKA0KICByZWNlbnQ9bWVhbihyZWNlbnQpLCANCiAgZnJlcT1tZWFuKGZyZXEpLCANCiAgbW9uZXk9bWVhbihtb25leSksIA0KICBzaXplPW4oKSApICU+JSANCiAgbXV0YXRlKCByZXZlbnVlID0gc2l6ZSptb25leS8xMDAwICkgICU+JSANCiAgZmlsdGVyKHNpemUgPiAxKSAlPiUgDQogIGdncGxvdChhZXMoeD1mcmVxLCB5PW1vbmV5KSkgKw0KICBnZW9tX3BvaW50KGFlcyhzaXplPXJldmVudWUsIGNvbD1yZWNlbnQpLGFscGhhPTAuNSkgKw0KICBzY2FsZV9zaXplKHJhbmdlPWMoNCwzMCkpICsNCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93PSJncmVlbiIsaGlnaD0icmVkIikgKw0KICBzY2FsZV94X2xvZzEwKCkgKyBzY2FsZV95X2xvZzEwKGxpbWl0cz1jKDMwLDMwMDApKSArIA0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc2l6ZSApLHNpemU9MykgKw0KICB0aGVtZV9idygpICsgZ3VpZGVzKHNpemU9RikgKw0KICBsYWJzKHRpdGxlPSJDdXN0b21lciBTZWdlbWVudHMiLA0KICAgICAgIHN1YnRpdGxlPSIoYnViYmxlX3NpemU6cmV2ZW51ZV9jb250cmlidXRpb247IHRleHQ6Z3JvdXBfc2l6ZSkiLA0KICAgICAgIGNvbG9yPSJSZWNlbmN5IikgKw0KICB4bGFiKCJGcmVxdWVuY3kgKGxvZykiKSArIHlsYWIoIkF2ZXJhZ2UgVHJhbnNhY3Rpb24gQW1vdW50IChsb2cpIikgIA0KYGBgDQogPGJyPg0KIA0KW+WbnuWIsOebrumMhF0oI3RvcCkNCg0KPGJyPjxocj4NCg0KDQojIyMgPGEgaWQ9Im4zIj48L2E+IDMuIOimj+WJh+WIhue+pCjli5XmhYvotqjli6IpDQoNCiMjIyMjIDMuMSDpoaflrqLliIbnvqTopo/liYcNCg0KKyDoqK3lrprpoaflrqLml4/nvqTlkI3nqLENCisg5L6d54Wn6Kmy5bm05bqm5pW06auU6KGo54++5Y2A5YiG6aGn5a6i576kDQoNCmBgYHtyfQ0KU1RTID0gYygiTjEiLCJOMiIsIlIxIiwiUjIiLCJTMSIsIlMyIiwiUzMiKQ0KU3RhdHVzID0gZnVuY3Rpb24ocngsZngsbXgsc3gsSykge2ZhY3RvcigNCiAgaWZlbHNlKHN4IDwgMipLLA0KICAgICAgICAgaWZlbHNlKGZ4Km14ID4gNTAsICJOMiIsICJOMSIpLA0KICAgICAgICAgaWZlbHNlKHJ4IDwgMipLLA0KICAgICAgICAgICAgICAgIGlmZWxzZShzeC9meCA8IDAuNzUqSywiUjIiLCJSMSIpLA0KICAgICAgICAgICAgICAgIGlmZWxzZShyeCA8IDMqSywiUzEiLA0KICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocnggPCA0KkssIlMyIiwiUzMiKSkpKSwgU1RTKX0NCmBgYA0KDQo8YSBpZD0iZzMiPjwvYT4gDQoNCiFb5ZyW5LiJ44CB6aGn5a6i5YiG576k6KaP5YmHXShmaWcvZmlnMy5qZmlmKQ0KDQoNCisgTjHvvJrmlrDpoaflrqINCisgTjLvvJrmlrDmvZvlipvpoaflrqINCisgUjHvvJrkuLvlipvpoaflrqINCisgUjLvvJrmoLjlv4PpoaflrqINCisgUzHvvJrnnoznnaHpoaflrqINCisgUzLvvJrljYrnnaHpoaflrqINCisgUzPvvJrmsonnnaHpoaflrqINCg0KPGEgaWQ9Imc0Ij48L2E+IA0KDQohW+ijnOWFhe+8mumvqOmtmuWcll0oZmlnLzEuanBnKQ0KDQorIOiXjee3muaYr+WFrOWPuOeahOe0r+epjeeNsuWIqe+8jOS+neaTmumhp+WuouWwjeWFrOWPuOeNsuWIqeeahOiyoueNu+W6pueUseWkp+WIsOWwj++8mg0KICAgICsg5re66JeN6Imy77yI6aCt77yJ77ya6K6T5YWs5Y+4542y5Yip5aKe5Yqg55qE6aGn5a6iDQogICAgICAgICsg5pyA55CG5oOz55qE57WE5ZCIDQogICAgICAgICsg5Lq65pW45b6I5bCRDQogICAgICAgICsg5a655piT6KKr5pC26LWwDQogICAgICAgICsg6YG45pOH5oCn5L+d55WZDQogICAgKyDmsLTol43oibLvvIjog4zvvInvvJrorpPlhazlj7jnjbLliKnmiZPlubPnmoTpoaflrqINCiAgICAgICAgKyDluavliqnkuI3lpKcNCiAgICAgICAgKyDkurrmlbjmnIDlpJrvvIznlKLnlJ/opo/mqKHntpPmv58NCiAgICAgICAgKyDpgbjmk4fmgKflkLjmlLYNCiAgICArIOa3seiXjeiJsu+8iOWwvu+8ie+8muiuk+WFrOWPuOiZp+mMoueahOmhp+Wuog0KICAgICAgICArIOmBuOaTh+aAp+eZvOWxlQ0KDQo8YnI+DQoNCiMjIyMjIDMuMiDlubPlnYfos7zosrfpgLHmnJ8NCg0KKyDmib7jgIzmnInos7zosrfpgY4y5qyh5Lul5LiK55qE6LO86LK36aGn5a6i44CN55qE5bmz5Z2H6LO86LK36YCx5pyfDQorIOWbnuizvOmhp+WuoueahOW5s+Wdh+izvOiyt+mAseacnyBgSyA9IDUyMSBkYXlzYO+8jOaEj+aAneaYr+W5s+Wdh+WFqeW5tOaJjeiyt+S4gOasoeOAgg0KKyDkuZ/lj6/ku6XnlKjlr6bpmpvnmoTni4Dms4HkvoblgZrliIbnvqTvvIxBJGZyZXE+MSDmmK/mjIfos7zosrfpoLvnjofjgIINCg0KYGBge3J9DQpLID0gYXMuaW50ZWdlcihzdW0oQSRzZW5pb3JbQSRmcmVxPjFdKSAvIHN1bShBJGZyZXFbQSRmcmVxPjFdKSk7IEsNCmBgYA0KDQojIyMjIyAzLjMg5ruR5YuV6LOH5paZ56qX5qC8DQoNCmBgYHtyfQ0KWSA9IGxpc3QoKSAgICAgICAgICAgICAgIyDlu7rnq4vkuIDlgIvnqbrnmoRMSVNUDQpmb3IoeSBpbiAyMDEwOjIwMTUpIHsgICAjIOavj+W5tOW5tOW6leWwh+mhp+Wuouizh+aWmeW9meaVtOaIkOS4gOWAi+izh+aWmeahhg0KICBEID0gYXMuRGF0ZShwYXN0ZTAoYyh5LCB5LTEpLCItMTItMzEiKSkgIyDnlbbmnJ/jgIHliY3mnJ/nmoTmnJ/mnKvml6XmnJ8gDQogIFlbW3Bhc3RlMCgiWSIseSldXSA9IFggJT4lICAgICAgICAjIOW+nuS6pOaYk+izh+aWmeWBmui1tw0KICAgIGZpbHRlcihkYXRlIDw9IERbMV0pICU+JSAgICAgICAgIyDlsIfos4fmlpnliIfpvYrliLDmnJ/mnKvml6XmnJ8NCiAgICBtdXRhdGUoZGF5cyA9IDEgKyBhcy5pbnRlZ2VyKERbMV0gLSBkYXRlKSkgJT4lICAgIyDkuqTmmJPot53mnJ/mnKvlpKnmlbgNCiAgICBncm91cF9ieShjaWQpICU+JSBzdW1tYXJpc2UoICAgICMg5L6d6aGn5a6i5b2Z57i9IC4uLg0KICAgICAgcmVjZW50ID0gbWluKGRheXMpLCAgICAgICAgICAgIyAgIOacgOW+jOS4gOasoeizvOiyt+i3neacn+acq+WkqeaVuCAgIA0KICAgICAgZnJlcSA9IG4oKSwgICAgICAgICAgICAgICAgICAgIyAgIOizvOiyt+asoeaVuCAo6Iez5pyf5pyr54K65q2iKSAgIA0KICAgICAgbW9uZXkgPSBtZWFuKGFtb3VudCksICAgICAgICAgIyAgIOW5s+Wdh+izvOiyt+mHkemhjSAo6Iez5pyf5pyr54K65q2iKQ0KICAgICAgc2VuaW9yID0gbWF4KGRheXMpLCAgICAgICAgICAgIyAgIOesrOS4gOasoeizvOiyt+i3neacn+acq+WkqeaVuA0KICAgICAgc3RhdHVzID0gU3RhdHVzKHJlY2VudCxmcmVxLG1vbmV5LHNlbmlvcixLKSwgICMg5pyf5pyr54uA5oWLDQogICAgICBzaW5jZSA9IG1pbihkYXRlKSwgICAgICAgICAgICAgICAgICAgICAgIyDnrKzkuIDmrKHos7zosrfml6XmnJ8NCiAgICAgIHlfZnJlcSA9IHN1bShkYXRlID4gRFsyXSksICAgICAgICAgICAgICAjIOeVtuacn+izvOiyt+asoeaVuA0KICAgICAgeV9yZXZlbnVlID0gc3VtKGFtb3VudFtkYXRlID4gRFsyXV0pICAgICMg55W25pyf6LO86LK36YeR6aGNDQogICAgKSAlPiUgZGF0YS5mcmFtZSB9ICAgICMg5pW05YCLee+8jOaYr+S4gOWAi+i/tOWciOiuiuaVuO+8jOWwh+aJgOaciWRhdGFmcmFtZee9ruWFpQ0KYGBgDQoNCisg5q+P5LiA5YCL6aGn5a6i77yM5pyD6Zqo5pmC6ZaT6ICM5pyJ5LiN5ZCM55qE57WQ5p6c55Si55SfKOOAjOihjOmKt+a7keawtOmBk+OAjemHjem7nu+8muawtOe8uOWkp+Wwj+OAgeawtOe8uOmWk+a1geWLleeahOmAn+W6puacieWkmuWkpykNCisg55W25pyJ5b6I5aSa5YWD5Lu25pmC77yM5Y+v5Lul55So6YCZ56iuWSRZMjAxNeaWueazleOAgg0KKyDlkIzkuIDlgIvpoaflrqLlgLzmnIPkuI3kuIDmqKPjgIINCmBgYHtyfQ0KaGVhZChZJFkyMDE1KQ0KYGBgDQoNCiMjIyMjIDMuNCDmr4/lubTlubTlupXnmoTntK/oqIjpoaflrqLkurrmlbgNCmBgYHtyfQ0Kc2FwcGx5KFksIG5yb3cpICAgIyBsaXN0IOmFjeS4iiBzYXBwbHnvvIzpnZ7luLjlpb3nlKgNCmBgYA0KDQojIyMjIyAzLjUg5peP576k5aSn5bCP6K6K5YyW6Lao5YuiDQoNCisg55Soc2FwcGx55bCx5piv5bCHWeavj+S4gOWAi+WFg+e0oOWBmm5yb3fpgJnlgIvli5XkvZzvvIzkuKboqIjnrpfmr4/lubTlupXpgJnmmYLplpPngrrmraLmnInlpJrlsJHos4fmlpnnuL3nrYbmlbjjgIINCisgczEo5ZCrKeS7peS4i+eahOeahueCuuebruWJjeaciea2iOiyu+ihjOeCuueahOmhp+Wuog0KKyBzM+acg+W+njIwMTDpgJDmvLjntK/nqY3liLAyMDE177yM5Zug5q2k6ZyA6KaB5Zyo5YiG5p6Q5pmC5rOo5oSP57Sv56mN55qE5ZWP6aGMDQorIOa0u+i6jemhp+Wuou+8mua3uuiXjeiJsuS7peS4iygyMDE06YGU5Yiw5beU5bOw77yM5b6M57qM5L6/5rKS5pyJ5LuA6bq85oiQ6ZW3KQ0KDQpgYGB7ciBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQ0KY29scyA9IGMoImdvbGQiLCJvcmFuZ2UiLCJibHVlIiwiZ3JlZW4iLCJwaW5rIiwibWFnZW50YSIsImRhcmtyZWQiKQ0Kc2FwcGx5KFksIGZ1bmN0aW9uKGRmKSB0YWJsZShkZiRzdGF0dXMpKSAlPiUgYmFycGxvdChjb2w9Y29scykNCmxlZ2VuZCgidG9wbGVmdCIscmV2KFNUUyksZmlsbD1yZXYoY29scykpDQpgYGANCg0KIyMjIyMgMy42IOaXj+e+pOWxrOaAp+WLleaFi+WIhuaekA0KYGBge3J9DQpDdXN0U2VnbWVudHMgPSBkby5jYWxsKHJiaW5kLCBsYXBwbHkoWSwgZnVuY3Rpb24oZCkgew0KICBncm91cF9ieShkLCBzdGF0dXMpICU+JSBzdW1tYXJpc2UoICAgICAgI+S7pemhp+WuouaXj+e+pOWBmueCuuWIhue+pOaomea6lu+8jOS7peS4i+S7peaXj+e+pOeCuuWWruS9jQ0KICAgIGF2ZXJhZ2VfZnJlcXVlbmN5ID0gbWVhbihmcmVxKSwgICAgICAgI+W5s+Wdh+a2iOiyu+asoeaVuA0KICAgIGF2ZXJhZ2VfYW1vdW50ID0gbWVhbihtb25leSksICAgICAgICAgI+W5s+Wdh+a2iOiyu+mHkemhjQ0KICAgIHRvdGFsX3JldmVudWUgPSBzdW0oeV9yZXZlbnVlKSwgICAgICAgI+e4vea2iOiyu+aUtuebig0KICAgIHRvdGFsX25vX29yZGVycyA9IHN1bSh5X2ZyZXEpLCAgICAgICAgI+aJgOaciea2iOiyu+asoeaVuA0KICAgIGF2ZXJhZ2VfcmVjZW5jeSA9IG1lYW4ocmVjZW50KSwgICAgICAgI+acgOW+jOS4gOasoea2iOiyu+i3neS7iueahOW5s+Wdh+WkqeaVuA0KICAgIGF2ZXJhZ2Vfc2VuaW9yaXR5ID0gbWVhbihzZW5pb3IpLCAgICAgI+esrOS4gOasoea2iOiyu+i3neS7iueahOW5s+Wdh+WkqeaVuA0KICAgIGdyb3VwX3NpemUgPSBuKCkgICAgICAgICAgICAgICAgICAgICAgI+ioiOeul+aXj+e+pOWkp+Wwjw0KICApfSkpICU+JSB1bmdyb3VwICU+JSANCiAgbXV0YXRlKHllYXI9cmVwKDIwMTA6MjAxNSwgZWFjaD03KSkgJT4lIGRhdGEuZnJhbWUgICAj5Lul5bm05Y2A5YiG5ZCE5peP576k6KGo54++DQpoZWFkKEN1c3RTZWdtZW50cykNCmBgYA0KDQorIOS+neaTmuWuoue+pOiIh+W5tOS7ve+8jOmhr+ekuuWPg+aVuOS5i+mWk+eahOWLleaFi+azoeazoeWclg0KYGBge3IgZXZhbD1GfQ0KcGxvdCggZ3Zpc01vdGlvbkNoYXJ0KA0KICBDdXN0U2VnbWVudHMsICJzdGF0dXMiLCAieWVhciIsDQogIG9wdGlvbnM9bGlzdCh3aWR0aD05MDAsIGhlaWdodD02MDApICkgKQ0KYGBgDQoNCg0KPGNlbnRlcj4NCg0KDQohW+WcluWbm+OAgemhp+WuouWIhue+pOimj+WJh10oZmlnL2ZpZzQuamZpZikNCg0KPGEgaWQ9Imc1Ij48L2E+IA0KDQohW+ijnOWFhe+8mmFwcGx557O75YiX5YWs5byPXShmaWcvMi5qcGcpDQoNCjwvY2VudGVyPg0KDQorIOWboOeCuueUqOWCs+e1seeahOaWueW8j+imgemHjeikh+WBmuWlveW5vumBje+8jERlYnVn5LiN5piT77yM5Zug5q2k5pyJ5LqGYXBwbHnns7vliJcNCisgTGFwcGx55ZKMc2FwcGx55pys6LOq5LiK5beu5LiN5aSa77yIc2FwcGx55piv6YCy6ZqO54mI77yJDQogICAgKyBMYXBwbHnmnIPmiorlm57lgrPnmoTos4fmlpnmlL7pgLLkuIDlgItsaXN06KOh77yMbGlzdOeahGVsZW1lbnRz5Y+v5Lul5piv5LiN5ZCM6ZW35bqm44CB6LOH5paZ5Z6L5oWL5oiW5LiJ5YCL5qih5Z6LDQogICAgKyBTYXBwbHnmnIPmiorlm57lgrPnmoTos4fmlpnvvIzkvp3mk5ros4fmlpnlnovmhYvvvIzoh6rli5XnlJ/miJDkuIDlgIt2ZWN0b3LmiJZtYXRyaXgNCg0KPGJyPg0KDQojIyMjIyAzLjcg5peP576k5bGs5oCn5YuV5oWL5YiG5p6QDQoNCisg5pW05ZCIMjAxNOWPijIwMTXlubTlkITml4/nvqTmtojosrvos4fmlpkNCisg5rWB6YeP55+p6ZmjKOWBmuS4gOWAi3RhYmxl5Y2z5Y+v77yM5Y+v55yL5Yiw576k6ZaT55qE5rWB5YuV5pW45bqmKQ0KDQpgYGB7cn0NCmRmID0gbWVyZ2UoWSRZMjAxNFssYygxLDYpXSwgWSRZMjAxNVssYygxLDYpXSwNCiAgICAgICAgICAgYnk9ImNpZCIsIGFsbC54PVQpDQp0eCA9IHRhYmxlKGRmJHN0YXR1cy54LCBkZiRzdGF0dXMueSkgJT4lIA0KICBhcy5kYXRhLmZyYW1lLm1hdHJpeCgpICU+JSBhcy5tYXRyaXgoKQ0KdHggICANCmBgYA0KDQorIOWPr+S7peWBmuWAi3RhYmxl57Ch5Zau55qE55+p6Zmj77yM5Lul6KGo54++5Ye655uu5YmN5rWB6YeP5q+U6LyDDQoNCmBgYHtyfQ0KdHggJT4lIHByb3AudGFibGUoMSkgJT4lIHJvdW5kKDMpICAgIyDmtYHph4/nn6npmaMoJSnvvIzkuKboqIjnrpfliLDlsI/mlbjpu57nrKzkuInkvY0NCmBgYA0KDQoNCiMjIyMjIDMuOCDkupLli5XlvI/mtYHph4/liIbmnpANCg0KKyDlkITml4/nvqTmtYHph4/vvIzljIXlkKvmtYHlhaXjgIHkuI3ororjgIHmtYHlh7oNCisgY2hvcmUgZGlhZ3Jhbe+8iOWSjOW8puWcluOAgeaoguitnOespuiZn+Wclu+8jOWPr+S7peiuiuWLle+8jOWPr+S7peeci+WHuua1geaVuO+8iQ0KKyDlnJPlkajlvKfluqbvvJrml4/nvqTkurrmlbgNCisg5Lit6ZaT55qE5bCP5LiY77ya5L+d55WZ5Zyo5peP576k5YWn55qE5Lq6DQorIOS4remWk+eahOW8p+e3mu+8muaXj+e+pOmWk+a1geWLleeahOS6uuaVuA0KDQpgYGB7cn0NCmNob3JkZGlhZyh0eCwgZ3JvdXBDb2xvcnM9Y29scykgICAgIA0KYGBgDQoNCiFbXShmaWcvY2hvcmQuanBnKQ0KDQogPGJyPg0KIA0KW+WbnuWIsOebrumMhF0oI3RvcCkNCg0KPGJyPjxocj4NCg0KIyMjIDxhIGlkPSJuNCI+PC9hPiA0LiDlu7rnq4vmqKHlnosNCg0K5Zyo6YCZ5YCL5qGI5L6L6KOh6Z2i77yM5oiR5YCR55qE6LOH5paZ5piv5pS25YiwWTIwMTXlubTlupXvvIzmiYDku6XmiJHlgJHlj6/ku6XlgYfoqK3nj77lnKjnmoTmmYLplpPmmK9ZMjAxNeW5tOW6le+8jOaIkeWAkeaDs+imgeeUqOePvuacieeahOizh+aWmeW7uueri+aooeWei++8jOS+humgkOa4rOavj+S4gOS9jemhp+Wuou+8mg0KDQorIOWcqFkyMDE25bm05piv5ZCm5pyD5L6G6LO86LK3ICjkv53nlZnnjofvvJpSZXRhaW4pDQorIOWlueS+huizvOiyt+eahOipse+8jOacg+iyt+WkmuWwkemMoiAo6LO86LK36YeR6aGN77yaUmV2ZW51ZSkNCg0K5L2G5piv77yM5oiR5YCR5Lim5rKS5pyJWTIwMTbnmoTos4fmlpnvvIzngrrkuobopoHlu7rnq4vmqKHlnovvvIzmiJHlgJHpnIDopoHlhYjmiormmYLplpPlm57mjqjkuIDmnJ/vvIzkuZ/lsLHmmK/oqqrvvJoNCg0KKyDnlKhZMjAxNOW5tOW6leS7peWJjeeahOizh+aWmeaVtOeQhuWHuumgkOa4rOiuiuaVuChYKSANCisg55SoWTIwMTXlubTnmoTos4fmlpnmlbTnkIblh7rnm67mqJnorormlbgoWSkgDQoNCuWBh+WmglkyMDE255qE5oOF5rOBKOi3n1kyMDE15q+UKeaykuacieWkquWkp+eahOiuiuWMlueahOipse+8jOaOpeS4i+S+huaIkeWAkeWwseWPr+S7pQ0KDQorIOS9v+eUqOipsuaooeWei++8jOS7pVkyMDE15bm05bqV55qE6LOH5paZ77yM6aCQ5risWTIwMTbnmoTni4Dms4ENCg0KIyMjIyMgNC4xIOa6luWCmeizh+aWmQ0K5oiR5YCR55SoWTIwMTTlubTlupXnmoTos4fmlpnlgZroh6rorormlbjvvIxZMjAxNeW5tOeahOizh+aWmeWBmuaHieiuiuaVuA0KDQorIHnlnKgyMDE155qE6LOH5paZ55W25LitDQorIGxlZnRfam9pbu+8mjLlgIvos4fmlpnmoYbvvIzpoZ7kvLzmn6XooajnmoTmpoLlv7XvvIzntZDlkIjlhanlgIvos4fmlpnmoYbvvIzkvb/nlKhjaWTvvIzmiorlvozpnaLnmoTos4fmlpnmioTliLDliY3pnaLnmoTos4fmlpko5aaC5p6c5qyE5L2N6KGo6aCt5LiN5LiA6Ie077yM5LulbGVmdOeCuuS4uykNCisgLnjlkowuee+8mlLnlbbkuK3oh6rli5XliqDnmoQNCisgeV9yZXZlbnVlLnnvvJoyMDE15L6G6LK35aSa5bCR6YyiDQorIHlfZnJlcS5577yaMjAxNeacg+S4jeacg+S+huiytw0KDQpgYGB7cn0NCkNYID0gbGVmdF9qb2luKFkkWTIwMTQsIFkkWTIwMTVbLGMoMSw4LDkpXSwgYnk9ImNpZCIpIA0KaGVhZChDWCkNCmBgYA0KDQorIFg9WSRZMjAxNA0KICBZPVkkWTIwMTVbLGMoMSw4LDkp77yaMeaYr2NpZO+8jOS4pueUqOmAmeWAi+ashOS9jeS+huWBmuW7uue9ruOAgg0KKyBsZWZ0X2pvaW4oKeWFqemCiumDveimgeaciWNpZOaJjeaciei+puazleWBmmpvaW7vvIzkvYblpoLmnpzmiJHlj6rmnInkuIDliJfpgqPmiJHlj6rnlZnkuIvlt6bpgorjgIINCisgeV9mcmVxLnggeV9yZXZlbnVlLnggeV9mcmVxLnkg6ZyA6KaB5YWp5YCLWe+8jOWBmumhnuWIpeiuiuaVuOOAgg0KKyDpnIDopoHnnIsyMDE15bm05pyD5LiN5pyD5YaN5qyh6LO86LK377yM6ZyA6KaB55yLeV9mcmVxLnnvvIxSZXRhaW4gKOS/neeVmeeOhynpnIDopoHlpKfmlrwwDQoNCmBgYHtyfQ0KbmFtZXMoQ1gpWzg6MTFdID0gYygiZnJlcTAiLCJyZXZlbnVlMCIsIlJldGFpbiIsICJSZXZlbnVlIikNCkNYJFJldGFpbiA9IENYJFJldGFpbiA+IDAgICAgICANCmhlYWQoQ1gpDQpgYGANCg0KKyBSZXRhaW7vvIjvvInkv53nlZnmqZ/njocNCiAg55SoeV9yZXZlbnVl77yd772ZDQorIFJldGFp5YGa6aGe5Yil5qih5Z6L55qE77y5DQogIFJldmVudWXlgZrlm57mrbjmqKHlnovnmoTvvLkNCg0KYGBge3J9DQp0YWJsZShDWCRSZXRhaW4pICU+JSBwcm9wLnRhYmxlKCkgICMg5bmz5Z2H5L+d55WZ5qmf546HID0gMjIuNTQlDQpgYGANCg0KIyMjIyMgNC4yIOW7uueri+mhnuWIpeaooeWeiw0KYGBge3J9DQptUmV0ID0gZ2xtKFJldGFpbiB+IC4sIENYWyxjKDI6Myw2LDg6MTApXSwgZmFtaWx5PWJpbm9taWFsKCkpDQpzdW1tYXJ5KG1SZXQpDQpgYGANCg0KIyMjIyMgNC4zIOS8sOioiOmhnuWIpeaooeWei+eahOa6lueiuuaApw0KDQorIOa3t+a3huefqemZoyAoQ29uZnVzaW9uIE1hdHJpeCkgIA0KYGBge3J9DQpwcmVkID0gcHJlZGljdChtUmV0LHR5cGU9InJlc3BvbnNlIikNCnRhYmxlKHByZWQ+MC41LENYJFJldGFpbikgDQpgYGANCg0KYGBge3J9DQp0YWJsZShwcmVkPjAuNSxDWCRSZXRhaW4pICU+JSANCiAge3N1bShkaWFnKC4pKS9zdW0oLil9ICAgICAgICAgICAgIyDmraPnorrnjocoQUNDKTogODUuMTklIA0KYGBgDQoNCmBgYHtyfQ0KY29sQVVDKHByZWQsQ1gkUmV0YWluKSAgICAgICAgICAgICAjIOi+r+itmOeOhyhBVUMpOiA4Ny45MiUNCmBgYA0KDQpgYGB7ciBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD00fQ0KcHJlZGljdGlvbihwcmVkLCBDWCRSZXRhaW4pICU+JSAgICAjIFJPQyBDVVJWRSANCiAgcGVyZm9ybWFuY2UoInRwciIsICJmcHIiKSAlPiUgDQogIHBsb3QocHJpbnQuY3V0b2Zmcy5hdD1zZXEoMCwxLDAuMSkpDQpgYGANCg0KIyMjIyMgNC40IOW7uueri+aVuOmHj+aooeWeiw0KYGBge3J9DQpkeCA9IHN1YnNldChDWCwgUmV2ZW51ZSA+IDApICAgIyDlj6rlsI3mnInkvobos7zosrfnmoTkurrlgZrmqKHlnoso5YGH5aaC5pyJ5L6G6LK355qE5Lq677yM5pyD6LK35aSa5bCR6YyiPykNCm1SZXYgPSBsbShsb2coUmV2ZW51ZSkgfiByZWNlbnQgKyBmcmVxICsgbG9nKDErbW9uZXkpICsgc2VuaW9yICsNCiAgICAgICAgICBzdGF0dXMgKyBmcmVxMCArIGxvZygxK3JldmVudWUwKSwgZHgpICANCnN1bW1hcnkobVJldikgICAjIOWIpOWumuS/guaVuO+8mlIyID0gMC43MTMgICAjIOavlOi8g+WPluS6hmxvZ++8iO+8ieeahFItc3F1YXJlDQpgYGANCg0KYGBge3IgZmlnLmhlaWdodD00LjUsIGZpZy53aWR0aD00LjV9DQpwbG90KGxvZyhkeCRSZXZlbnVlKSwgcHJlZGljdChtUmV2KSwgY29sPSdwaW5rJywgY2V4PTAuNjUpDQphYmxpbmUoMCwxLGNvbD0ncmVkJykgDQpgYGANCg0KKyBSZXZlbnVl6KaB5YGa57ea5oCn5qih5pmC5b+F6aCIbG9n5L6G5YGaDQorIOe0hee3muaYr+mgkOa4rOWAvO+8jOeyiee0heWwj+WciOWciOaYr+Wvpumam+WAvA0KDQogPGJyPg0KIA0KW+WbnuWIsOebrumMhF0oI3RvcCkNCg0KPGJyPjxocj4NCg0KIyMjIDxhIGlkPSJuNSI+PC9hPiA1LiDkvLDoqIjpoaflrqLntYLnlJ/lg7nlgLwoQ0xWKQ0KDQojIyMjIyA1LjEgWTIwMTbnmoTpoJDmuKzlgLwNCg0KKyDlm6DngrrmspLmnInmnKrkvobnmoTos4fmlpnvvIzpnIDopoHmiormmYLplpPlvoDlm57mjqjkuIDmnJ/vvIzkuZ/lsLHmmK/kvb/nlKjmqKHlnovlsI1ZMjAxNeW5tOW6leeahOizh+aWmeWBmumgkOa4rO+8jOWwjeizh+aWmSAgIOS4reeahOavj+S4gOS9jemhp+Wuou+8jOmgkOa4rOWlueWAkeWcqFkyMDE255qE5L+d55WZ546H5ZKM6LO86LK36YeR6aGN44CCDQpgYGB7cn0NCkNYID0gWSRZMjAxNQ0KbmFtZXMoQ1gpWzg6OV0gPSBjKCJmcmVxMCIsInJldmVudWUwIikNCkNYJFByb2JSZXRhaW4gPSBwcmVkaWN0KG1SZXQsQ1gsdHlwZT0ncmVzcG9uc2UnKSAgICMg6aCQ5risWTIwMTbkv53nlZnnjocNCkNYJFByZWRSZXZlbnVlID0gZXhwKHByZWRpY3QobVJldixDWCkpICAgIyDpoJDmuKxZMjAxNuizvOiyt+mHkemhjQ0KYGBgDQoNCmBgYHtyIGZpZy5oZWlnaHQ9Mi41LCBmaWcud2lkdGg9OH0NCnBhcihtZnJvdz1jKDEsMiksIG1hcj1jKDUsMywzLDIpLCBjZXg9MC44KQ0KaGlzdChDWCRQcm9iUmV0YWluLG1haW49IlByb2JSZXRhaW4iLCB5bGFiPSIiKSAgICPpoaflrqLkv53nlZnnjofokL3lnKgwLjHlt6blj7PvvIzpgJnpg6jliIbku6PooajmnInkupvpoaflrqLmtojosrvkuKbkuI3poLvnuYENCmhpc3QobG9nKENYJFByZWRSZXZlbnVlLDEwKSxtYWluPSJsb2coUHJlZFJldmVudWUpIiwgeWxhYj0iIikgICPmoLnmk5rnm7TmlrnlnJbpoa/npLrvvIzpoJDmuKzlh7rkvobnmoTnuL3mlLbnm4rliIbluIPoiIfljp/lhYjnmoTliIbluIPmg4Xms4Hnm7jkvLwNCmBgYA0KPGJyPg0KDQojIyMjIyA1LjIg5Lyw6KiI6aGn5a6i57WC55Sf5YO55YC8KENMVikNCg0KPGNlbnRlcj7poaflrqIkaSTnmoTntYLnlJ/lg7nlgLw8L2NlbnRlcj4NCg0KJCQgVl9pID0gXHN1bV97dD0wfV5OIGcgXHRpbWVzIG1faSBcZnJhY3tyX2ledH17KDErZCledH0gPSBnIFx0aW1lcyBtX2kgXHN1bV97dD0wfV5OIChcZnJhY3tyX2l9ezErZH0pXnQgICQkDQoNCjxjZW50ZXI+DQoNCkFzc3VtZemhp+WuouS4jeacg+awuOmBoOW/oOWvpu+8jOWboOatpOaOoeacn+aVuOioiOeul++8jOeUseWFrOW8j+W+l+WHuuavj+WAi+mhp+WuouWwjeWFrOWPuOWAvOWkmuWwkemMou+8mg0KDQo8L2NlbnRlcj4NCg0KPGNlbnRlcj4kbV9pJOOAgSRyX2kk77ya6aGn5a6iJGkk55qE6aCQ5pyfKOavj+acnynnh5/mlLbosqLnjbvjgIHkv53nlZnmqZ/njoc8L2NlbnRlcj4NCg0KPGNlbnRlcj4kZyTjgIEkZCTvvJrlhazlj7jnmoQo56iF5YmNKeeHn+alreWIqea9pOWIqeeOh+OAgeizh+mHkeaIkOacrDwvY2VudGVyPg0KDQpgYGB7cn0NCmcgPSAwLjUgICAjICjnqIXliY0p542y5Yip546HDQpOID0gNSAgICAgIyDmnJ/mlbggPSA1DQpkID0gMC4xICAgIyDliKnnjocgPSAxMCUNCkNYJENMViA9IGcgKiBDWCRQcmVkUmV2ZW51ZSAqIHJvd1N1bXMoc2FwcGx5KA0KICAwOk4sIGZ1bmN0aW9uKGkpIChDWCRQcm9iUmV0YWluLygxK2QpKV5pICkgKQ0Kc3VtbWFyeShDWCRDTFYpDQpgYGANCg0KYGBge3IgZmlnLmhlaWdodD0yLjUsIGZpZy53aWR0aD03LjJ9DQpwYXIobWFyPWMoMywzLDMsMSksIGNleD0wLjgpDQpoaXN0KGxvZyhDWCRDTFYsMTApLCB4bGFiPSIiLCB5bGFiPSIiKSAgICMgQ0xW5piv55So6Yyi566X5Ye65L6G55qE77yM5omA5Lul5Lmf5piv6Yyi77yM6ZyA6KaB55SobG9n5L6G566XICAgIyDlj5Zsb2flvozmiYDlvpfnmoTlgLzntITngrozMOWhii/kuIDpoaflrqINCmBgYA0KDQojIyMjIyA1LjMg5q+U6LyD5ZCE5peP576k55qE5YO55YC8DQoNCiA8YSBpZD0iZzYiPjwvYT4gDQoNCisg5raI6LK76YeR6aGN6auY55qE6aGn5a6i5LiN5bCR77yI5bC+5be06ZW377yJDQorIOaWsOmhp+WuouiIh+ayieedoemhp+WuoueahOWDueWAvOW3ruS4jeWkmg0KKyDmlrDpoaflrqLorormiJDkuLvlipvpoaflrqLnmoTmqZ/njofkuI3lpKcNCg0KYGBge3J9DQpzYXBwbHkoQ1hbLDEwOjEyXSwgdGFwcGx5LCBDWCRzdGF0dXMsIG1lYW4pICAgIyDlkITml4/nvqTnmoTlubPlnYfnh5/mlLbosqLnjbvjgIHkv53nlZnmqZ/njofjgIHntYLnlJ/lg7nlgLwNCmBgYA0KDQorIOaWsOmhp+WuoihOMSnot5/nnaHokZfnmoTpoaflrqIoUzHjgIFTMuOAgVMzKeaJgOW4tue1pumAmemWk+W6l+eahOWDueWAvOWFtuWvpuW3ruS4jeWkmg0KDQpgYGB7cn0NCnBhcihtYXI9YygzLDMsNCwyKSwgY2V4PTAuOCkNCmJveHBsb3QobG9nKENMVil+c3RhdHVzLCBDWCwgbWFpbj0iQ0xWIGJ5IEdyb3VwcyIpDQpgYGANCg0KIDxicj4NCiANClvlm57liLDnm67pjIRdKCN0b3ApDQoNCjxicj48aHI+DQoNCiMjIyA8YSBpZD0ibjYiPjwvYT4gNi4g6Kit5a6a6KGM6Yq3562W55Wl44CB6KaP5YqD6KGM6Yq35bel5YW3DQoNCjxhIGlkPSJnNyI+PC9hPiANCg0K6aaW5YWI6YCy6KGM5ZCE5peP576k55qE5bGs5oCn57Wx5pW077yM5YaN6Kit5a6a6KGM6Yq3562W55Wl6IiH5bel5YW344CCDQoNCisg5bGs5oCn5YiG5p6QDQogICAgKyBOMe+8iOaWsOmhp+Wuou+8iQ0KICAgICAgICArIENMVuS9jg0KICAgICAgICArIOS6uuaVuOS6m+W+rua1ruWLle+8jOWkp+mrlOS4gOiHtA0KICAgICAgICArIOa1geWQkVMxID4gTjIgPiBSMe+8iOWKoOe4veW/q+S4gOWNiu+8iQ0KDQogICAgKyBOMu+8iOaWsOa9m+WKm+mhp+Wuou+8iQ0KICAgICAgICArIENMVuasoemrmA0KICAgICAgICArIOS6uuaVuOeojeW+ruacieWQkeS4iui2qOWLou+8jOS9hjIwMTXlubTlj4jkupvlvq7muJvlsJENCiAgICAgICAgKyDmtYHlkJFSMiA+IFIxID4gUzHvvIjliqDnuL3kuIDljYrvvIkNCg0KICAgICsgUjHvvIjkuLvlipvpoaflrqLvvIkNCiAgICAgICAgKyBDTFbmma7pgJoNCiAgICAgICAgKyDkurrmlbjov5HlubTnqanlrpoNCiAgICAgICAgKyDlv6vkuIDljYrmtYHlkJFTMQ0KDQogICAgKyBSMu+8iOaguOW/g+mhp+Wuou+8iQ0KICAgICAgICArIENMVuacgOmrmA0KICAgICAgICArIOS6uuaVuOavj+W5tOepqeWumg0KICAgICAgICArIOWwkeaVuOa1geWQkVIxDQoNCiAgICArIFMx77yI556M552h6aGn5a6i77yJDQogICAgICAgICsgQ0xW5L2ODQogICAgICAgICsg5Lq65pW456iN5b6u6K6K5aSaDQogICAgICAgICsg5LiA5Y2K5rWB5ZCRUzINCiAgICAgICAgDQogICAgKyBTMu+8iOWNiuedoemhp+Wuou+8iQ0KICAgICAgICArIENMVuS9jg0KICAgICAgICArIOS6uuaVuOeojeeCuua4m+WwkQ0KICAgICAgICArIOS4ieWIhuS5i+S4gOa1geWQkVMzDQoNCiAgICArIFMz77yI5rKJ552h6aGn5a6i77yJDQogICAgICAgICsgQ0xW5L2ODQogICAgICAgICsg5Lq65pW46YCQ5bm05LiK5Y2HDQogICAgICAgICsg5aSn6YOo5YiG57at5oyB5Y6f5ZywDQoNCiAgICArIOaVtOmrlOiAjOiogO+8jOWQhOaXj+e+pOWkp+Wwj+W3ruS4jeWkmg0KICAgICAgICArIOaDn1Mz5YGP5aSn77yI5LuL5pa85pW06auU5Zub5YiG5Yiw5LiJ5YiG5LmL5LiA77yJDQogICAgICAgICsgUzHlkIxOMeasoeWkpw0KICAgICAgICArIE4yLCBSMeiIh1Iy5beu5LiN5aSaDQogICAgICAgICsgUzLmnIDlsJENCisg6KGM6Yq3562W55Wl6IiH5bel5YW3DQogICAgKyBTMSwgUzIsIFMz5q2j5Zyo6YCQ5ry45pO05aSn5LiU5LiN5pa35b6AUzPliY3pgLLvvIzpnIDopoHmipHliLbmraTnj77osaHvvIzlj6/ku6Xol4nnlLHkuIDoiKzntrLot6/kuIrnmoTooYzpirflt6Xlhbflop4NCiAgICAgIOWKoOWTgeeJjOW9ouixoe+8jOaIlueUqOW7o+WRiui/vei5pOeahOaWueW8j++8jOS4jeaWt+mcsuWHuuiIh+abneWFie+8jOS7peWinuWKoOipsuaXj+e+pOWwjeWTgeeJjOeahOWNsOixoeOAgg0KICAgICsgUjHkuZ/mvLjmvLjmtYHlpLHvvIzmh4nmjqjlh7pWSVDlj4rlrqLoo73ljJbnrYnmnI3li5nliqDlvLdSMeiIh1Iy55qE6buP6JGX5bqm77yM5Lim6KaP5YqD55+t5pyf5L+D6Yq35rS75YuV5ZC45byV5YW25rOoDQogICAgICDmhI/lipvvvIzkuKblj6/ku6Xkvb/nlKjnmoTooYzpirflt6XlhbfvvIzkvovlpoJMSU5FK++8jOWPr+S7pemHneWwjeS4u+WKm+WuouaItuacieWwiOWxrOihjOmKt+aWueahiO+8jOWQjOaZguWuouaItuWPr+S7pQ0KICAgICAg55SoTElORSvoqaLllY/kuKbmlrnkvr/vvIzmpa3kuLvlop7liqDoiIfkuLvlipvlrqLmiLbnmoTpu4/okZflipvvvIzku6Xpno/lm7rkuLvlipvlrqLmiLbnmoTlv6DoqqDluqbjgIINCiAgICArIOeUseaWvE4x5rWu5YuV546H5aSq5aSn5LiU54Sh6YGO5aSa5YO55YC877yM5LiN5oeJ6Iqx6LK75aSq5aSa5pmC6ZaT5Zyo6YCZ5Lqb5Lq66Lqr5LiKDQogICAgKyDkvYblsI3mlrxOMuWJh+S4jeWQjO+8jOS7luWAkeeahENMVuW+iOmrmO+8jOS9hjIwMTXlubTkurrmlbjljbvnqoHnhLbkuIvpmY3vvIzmh4nlsIfnsr7lipvmlL7lnKjntpPnh59OMuaXj+e+pO+8jOWPr+S7pQ0KICAgICAg6YCP6YGORkLnsonntbLlnJjnmoTntpPnh5/mlrnlvI/vvIzlrprmnJ/nmbzpgIHmlofmoYjvvIzkuKblsIflk4HniYzmt7HljJbos6rmhJ/ntpPnh5/vvIzku6XmipPkvY9OMua2iOiyu+iAheeahOe2k+eHn+OAgg0KDQogPGJyPg0KIA0KW+WbnuWIsOebrumMhF0oI3RvcCkNCg0KPGJyPjxocj4NCg0KIyMjIDxhIGlkPSJuNyI+PC9hPiA3LiDpgbjmk4fooYzpirflsI3osaENCg0K57Wm5a6a5p+Q5LiA6KGM6Yq35bel5YW355qE5oiQ5pys5ZKM6aCQ5pyf5pWI55uK77yM6YG45pOH5Y+v5Lul5pa96KGM6YCZ6aCF5bel5YW355qE5bCN6LGh44CCIA0KDQojIyMjIyA3LjEg5bCNUjLml4/nvqTpgLLooYzkv53nlZkNClIy5peP576k55qE6aCQ5ris5L+d55WZ546H5ZKM6LO86LK36YeR6aGNDQpgYGB7ciBmaWcuaGVpZ2h0PTIuNSwgZmlnLndpZHRoPTh9DQpwYXIobWZyb3c9YygxLDIpLCBtYXI9Yyg0LDMsMywyKSwgY2V4PTAuOCkNCmhpc3QoQ1gkUHJvYlJldGFpbltDWCRzdGF0dXM9PSJSMiJdLG1haW49IlByb2JSZXRhaW4iLHhsYWI9IiIpDQpoaXN0KGxvZyhDWCRQcmVkUmV2ZW51ZVtDWCRzdGF0dXM9PSJSMiJdLDEwKSxtYWluPSJQcmVkUmV2ZW51ZSIseGxhYj0iIikNCmBgYA0KDQojIyMjIyA3LjIg5Lyw6KiI6aCQ5pyf5aCx6YWsDQrlgYfoqK3ooYzpirflt6XlhbfnmoTmiJDmnKzlkozpoJDmnJ/mlYjnm4rngrrku6XkuIvvvIjntablrprlgYfoqK3vvIkNCg0KKyDmiJDmnKzvvJrol4nnlLHpgY7ljrvntpPpqZfmiYDlvpfliLDkuYvooYzpirflt6XlhbfmiJDmnKznmoTlgYfoqK3mlbjlgLwNCisg5pWI55uK77ya6aGn5a6i5o6l5Y+X5Yiw6Kmy6KGM6Yq35bel5YW35omA55Si55Sf55qE6LO86LK36KGM54K677yI5LiL5LiA5pyf55qE6LO86LK35qmf546H77yJDQpgYGB7cn0NCmNvc3QgPSAxMCAgICAgICAgDQplZmZlY3QgPSAwLjc1ICAgIA0KYGBgDQoNCuS8sOioiOmAmemgheihjOmKt+W3peWFt+Wwjeavj+S4gOS9jVIy6aGn5a6i55qE6aCQ5pyf5aCx6YWsDQpgYGB7cn0NClRhcmdldCA9IHN1YnNldChDWCwgc3RhdHVzPT0iUjIiKQ0KVGFyZ2V0JEV4cFJldHVybiA9IChlZmZlY3QgLSBUYXJnZXQkUHJvYlJldGFpbikgKiBUYXJnZXQkUHJlZFJldmVudWUgLSBjb3N0DQpzdW1tYXJ5KFRhcmdldCRFeHBSZXR1cm4pICAgIyDlm6Dngrrkv53nlZnmqZ/njofvvIhQcm9iUmV0YWlu77yJ6Kit5a6a54K6MC43Ne+8jOWNs+ihqOekuu+8njAuNzXnmoTml4/nvqTkuI3og73kvb/nlKjpgJnmlK/nqIvlvI/vvIjmnIPlsI7oh7TpoJDmnJ/loLHlhJ/ngrrosqDlgLzvvIkNCmBgYA0KKyDpgJnkuIDpoIXlt6XlhbflsI1SMumhp+WuoueahOmgkOacn+WgsemFrOaYr+iyoOeahO+8jOWVhualreaVuOaTmuWIhuaekOS4jeiDveeUqOW5s+Wdh+WAvOWBmuWIhuaekA0KDQojIyMjIyA3LjMg6YG45pOH6KGM6Yq35bCN6LGhDQrkvYbmmK/vvIzmiJHlgJHpgoTmmK/lj6/ku6Xlvp5SMuS4reaMkeWHuuioseWkmumgkOacn+WgsemFrOW+iOWkp+eahOihjOmKt+WwjeixoQ0KYGBge3J9DQpUYXJnZXQgJT4lIGFycmFuZ2UoZGVzYyhFeHBSZXR1cm4pKSAlPiUgc2VsZWN0KGNpZCwgRXhwUmV0dXJuKSAlPiUgaGVhZCgxNSkgICPmib7lh7pFeHBSZXR1cm7liY0xNeWQjQ0KYGBgDQoNCisg6Yed5bCN5oCn6KGM6Yq3OiDlsIfmsbrlrprkuIvliLDmr4/lgIvkurrouqvkuIrvvIzogIzkuI3lho3mmK/ku6XnvqTpq5TngrrliIbmnpDlsI3osaHvvIzlj6/ku6XlvpfliLBhZGRpdGlvbiByZXZlbnVlDQoNCmBgYHtyfQ0Kc3VtKFRhcmdldCRFeHBSZXR1cm4gPiAwKSAgICAgICAjIOWPr+WvpuaWveWwjeixoe+8mjI1OA0KYGBgDQrlnKhSMuS5i+S4re+8jOaciTI1OOS6uueahOmgkOacn+WgsemFrOWkp+aWvOmbtu+8jOWmguaenOWwjemAmTI1OOS6uuS9v+eUqOmAmemgheW3peWFt++8jOaIkeWAkeeahOacn+acm+WgsemFrOaYr++8mg0KYGBge3J9DQpzdW0oVGFyZ2V0JEV4cFJldHVybltUYXJnZXQkRXhwUmV0dXJuID4gMF0pICAgIyDpoJDmnJ/loLHphazvvJo2NDY0DQpgYGANCg0KIyMjIyMgPGEgaWQ9Imc4Ij48L2E+IFFVSVo6DQrmiJHlgJHlj6/ku6Xnrpflh7rlsI3miYDmnInnmoTml4/nvqTlr6bmlr3pgJnpoIXlt6XlhbfnmoTmnJ/mnJvloLHphawNCmBgYHtyfQ0KVGFyZ2V0ID0gQ1gNClRhcmdldCRFeHBSZXR1cm4gPSAoZWZmZWN0IC0gVGFyZ2V0JFByb2JSZXRhaW4pICogVGFyZ2V0JFByZWRSZXZlbnVlIC0gY29zdA0KZmlsdGVyKFRhcmdldCwgVGFyZ2V0JEV4cFJldHVybiA+IDApICU+JQ0KICBncm91cF9ieShzdGF0dXMpICU+JSBzdW1tYXJpc2UoDQogICAgTm8uVGFyZ2V0ID0gbigpLA0KICAgIEF2Z1JPSSA9IG1lYW4oRXhwUmV0dXJuKSwNCiAgICBUb3RhbFJPSSA9IHN1bShFeHBSZXR1cm4pICkgJT4lIGRhdGEuZnJhbWUNCmBgYA0K6YCZ5YCL57WQ5p6c5piv5ZCI55CG55qE5ZeO77yfIOS9oOaDs+imgeaAjum6vOS/ruato+mAmemgheWIhuaekOeahOeoi+W6j+WRou+8nw0KDQorIOaVuOaTmumhr+ekuuWwjeW3sueEoeWkmuWwkeWDueWAvOeahOayieedoemhp+WuolMz5L2/55So5q2k6KGM6Yq35bel5YW377yM5q+U5bCN5Li75Yqb6aGn5a6iUjLnmoTpoJDmnJ/loLHphazpgoTlpb3otoXpgY4yMOWAje+8jOWvpuWcqOS4jeWQiOeQhg0KKyDoqK3lrprooYzpirflt6XlhbfnmoTmiJDmnKzlkozmlYjnm4rmh4npmqjkuI3lkIzml4/nvqToiIfpgY7lvoDntpPpqZfogIzororvvIznlbbloLHlhJ/nn6npmaPoo6HpnaLnmoToqK3lrprlgLznmbznlJ/ororli5XlvozvvIzlvpfliLDnmoTmnJ/mnJvloLHphazkuZ/lsLHkuI3lkIwNCisg5Y+v6IO95L+u5q2j55qE5pa55ZCR77yaDQogICAgKyDmlrDpoaflrqLnvqQoTjEsTjIp77yaDQogICAgICAgICsg55Sx5YmN6Z2i55qE6KeA5a+f77yMTjHml4/nvqTnmoTlg7nlgLzoiIdT57O75YiX5peP576kQ0xW5beu5LiN5aSa77yM5LuW5YCR5piv5LiA576k5rWB5YuV546H5b6I6auY55qE5Lq677yM5LiN6ZyA6Iqx6LK75aSq5aSa57K+5Yqb5oiW6Iqx5oub5Y675ZC45byV5LuW5YCR77yM5YW25oqV6LOH5aCx6YWs546H5aSq5L2ODQogICAgICAgICsg55u45bCN6LW35L6G77yMTjLmmK/kuIDnvqTlvojmnInmvZvlipvnmoTml4/nvqTvvIzmiJHlgJHlj6/ku6Xlpb3lpb3nmbzlsZXvvIzln7nppIrku5blgJHmiJDngrrkuLvlipvlrqLnvqTvvIzlm6DmraTmh4nmipXlhaXovIPlpJrnmoTmiJDmnKzvvIzmiJHlgJHpoJDkvLDlnKjpgJnoo6HnmoTmlYjnm4rkuI3pjK/vvIzkvYbkuI3og73norrlrprlpJrpq5gNCiAgICArIOS4u+WKm+mhp+Wuoue+pChSMSxSMinvvJpDTFbmnIDpq5jnmoTml4/nvqTvvIzku5blgJHlv6Dlr6bkuJTnqanlrprmmK/miJHlgJHmnIDmg7PnlZnkvY/kuKbmiJDplbfnmoTlsI3osaHvvIzljbvplovlp4vpgJDmvLjlh7rnj77mtYHlpLHnj77osaHvvIzlm6DmraTmh4noirHmnIDlpJrmiJDmnKzlnKjkv53nlZnku5blgJHvvIzlop7liqDlhbbpu4/okZfluqbvvIzlhbbmipXos4floLHphaznjoflj6/ku6XpoJDopovmmK/nm7jnlbbpq5jnmoTjgIINCiAgICArIOayieedoemhp+Wuoue+pChTMSxTMixTMynvvJrlsI3mlrzmhIjkvobmhIjpvpDlpKfnmoTmsonnnaHpoaflrqLvvIzmiJHlgJHlvojpm6Plho3llprphpLku5blgJHvvIzmnIDlpb3nmoTmlrnlvI/mmK/lvp7moLnmnKzop6Pmsboo5LiN6KaB6K6TUuezu+WIl+eahOa1geWksSnvvIzlm6DmraTlsI3mlrxT57O75YiX77yM5oiR5YCR5LiN5omT566X5oqV5YWl5aSq5aSa5oiQ5pysDQogICAgDQogPGJyPg0KIA0KW+WbnuWIsOebrumMhF0oI3RvcCkNCg0KPGJyPjxocj4NCg0KIyMjIDxhIGlkPSJuOCI+PC9hPiA4LiDntZDoq5YNCg0K5aaC5p6c5L2g5Y+q5pyJ6aGn5a6iSUTjgIHkuqTmmJPml6XmnJ/jgIHkuqTmmJPph5HpoY3kuInlgIvmrITkvY3nmoToqbHvvIzkvaDlj6/ku6XlgZrnmoTliIbmnpDljIXmi6zvvJoNCg0KKyDlhajpq5TpoaflrqLlkozmr4/kuIDlgIvpoaflrqLliIbnvqTnmoTvvJoNCiAgICArIOaXj+e+pOWkp+Wwj+iIh+aIkOmVt+i2qOWLog0KICAgICsg5peP576k5bGs5oCn5YiG5p6Q77ya5aaC5bmz5Z2HQ0xW44CB5bmz5Z2H54ef5pS26LKi542744CB5oiQ6ZW3546H44CB5q+b5Yip546HKOmcgOimgeacieaIkOacrOizh+aWmSnnrYnnrYkNCiAgICArIOe1hOmWk+a1gemHj+WSjOW5s+Wdh+a1geWLleapn+eOhw0KDQorIOavj+S4gOWAi+mhp+WuoueahO+8mg0KICAgICsg5L+d55WZ546H44CB6aCQ5pyf6LO86LK36YeR6aGN44CB57WC6Lqr5YO55YC8DQogICAgKyDnm67liY3miYDlnKjnvqTntYTvvIzku6Xlj4rkuIvkuIDmnJ/mnIPovYnliLDlgIvnvqTntYTnmoTmqZ/njocNCiAgICArIOWmguaenOacieihjOmKt+W3peWFt+eahOS9v+eUqOe0gOmMhOeahOipse+8jOaIkeWAkeS5n+WPr+S7peS8sOioiOavj+S4gOaoo+ihjOmKt+W3peWFt+OAgeWwjeavj+S4gOS9jemhp+WuoueahOaIkOWKn+apn+eOhw0KDQrkuIDoiKzogIzoqIDvvIzpgJnkuIDkupvliIbmnpDnmoTntZDmnpzvvIzotrPlpKDorpPmiJHlgJHliLblrprpoaflrqLnmbzlsZXlkozpoaflrqLkv53nlZnnrZbnlaXvvJvoh7PmlrzpoaflrqLlkLjmlLbnrZbnlaXvvIzmiJHlgJHpgJrluLjpgoTpnIDopoHlvp5DUk3mkojlh7rpoaflrqLlgIvkurrlsazmgKfos4fmlpnmiY3og73lgZrliLDjgIIgDQoNCjxicj4NCiANClvlm57liLDnm67pjIRdKCN0b3ApDQoNCjxicj48YnI+PGhyPjxicj48YnI+PGJyPg0KDQo8c3R5bGU+DQouY2FwdGlvbiB7DQogIGNvbG9yOiAjNzc3Ow0KICBtYXJnaW4tdG9wOiAxMHB4Ow0KfQ0KcCBjb2RlIHsNCiAgd2hpdGUtc3BhY2U6IGluaGVyaXQ7DQp9DQpwcmUgew0KICB3b3JkLWJyZWFrOiBub3JtYWw7DQogIHdvcmQtd3JhcDogbm9ybWFsOw0KICBsaW5lLWhlaWdodDogMTsNCn0NCnByZSBjb2RlIHsNCiAgd2hpdGUtc3BhY2U6IGluaGVyaXQ7DQp9DQpwLGxpIHsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCi5yew0KICBsaW5lLWhlaWdodDogMS4yOw0KfQ0KDQp0aXRsZXsNCiAgY29sb3I6ICNjYzAwMDA7DQogIGZvbnQtZmFtaWx5OiAiVHJlYnVjaGV0IE1TIiwgIuW+rui7n+ato+m7kemrlCIsICJNaWNyb3NvZnQgSmhlbmdIZWkiOw0KfQ0KDQpib2R5ew0KICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsNCn0NCg0KaDEsaDIsaDMsaDQsaDV7DQogIGNvbG9yOiAjMDA4ODAwOw0KICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsNCn0NCg0KaDN7DQogIGNvbG9yOiAjMDA4ODAwOw0KICBiYWNrZ3JvdW5kOiAjZTZmZmU2Ow0KICBsaW5lLWhlaWdodDogMjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQp9DQoNCmg1ew0KICBjb2xvcjogIzAwNjAwMDsNCiAgYmFja2dyb3VuZDogI2Y4ZjhmODsNCiAgbGluZS1oZWlnaHQ6IDEuNTsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQp9DQoNCmVtew0KICBjb2xvcjogIzAwMDBjMDsNCiAgYmFja2dyb3VuZDogI2YwZjBmMDsNCiAgfQ0KPC9zdHlsZT4=