資料彙整流程

Fig-1: Pata Preparation

Fig-1: Pata Preparation


1. 交易項目計錄:Z

rm(list=ls(all=T))
Sys.setlocale("LC_ALL","C")
library(dplyr)
library(ggplot2)
library(caTools)
1.1 The do.call-rbind-lapply Combo
Z = do.call(rbind, lapply(
    dir('data/TaFengDataSet','.*csv$',full.names=T),
    read.csv, header=F) 
  ) %>% 
  setNames(c("date","cust","age","area","cat","prod","qty","cost","price"))
nrow(Z)
[1] 817741
Data Convresion
Z$date = as.Date(as.character(Z$date))
summary(Z)
      date                 cust               age              area             cat        
 Min.   :2000-11-01   Min.   :    1069   D      :181213   E      :312501   Min.   :100101  
 1st Qu.:2000-11-28   1st Qu.:  969222   E      :151023   F      :245213   1st Qu.:110106  
 Median :2001-01-01   Median : 1587722   C      :140805   G      : 72092   Median :130106  
 Mean   :2000-12-30   Mean   : 1406620   F      : 99719   C      : 71640   Mean   :284950  
 3rd Qu.:2001-01-30   3rd Qu.: 1854930   B      : 66432   H      : 40666   3rd Qu.:520314  
 Max.   :2001-02-28   Max.   :20002000   G      : 53719   D      : 38674   Max.   :780510  
                                         (Other):124830   (Other): 36955                   
      prod                    qty               cost            price       
 Min.   :     20008819   Min.   :   1.00   Min.   :     0   Min.   :     1  
 1st Qu.:4710085127020   1st Qu.:   1.00   1st Qu.:    35   1st Qu.:    42  
 Median :4710421090060   Median :   1.00   Median :    62   Median :    76  
 Mean   :4461639280530   Mean   :   1.38   Mean   :   112   Mean   :   132  
 3rd Qu.:4712500125130   3rd Qu.:   1.00   3rd Qu.:   112   3rd Qu.:   132  
 Max.   :9789579967620   Max.   :1200.00   Max.   :432000   Max.   :444000  
                                                                            
Quantile of Variables
sapply(Z[,7:9], quantile, prob=c(.99, .999, .9995))
       qty   cost  price
99%      6  858.0 1014.0
99.9%   14 2722.0 3135.8
99.95%  24 3799.3 3999.0
Get rid of Outliers
Z = subset(Z, qty<=24 & cost<=3800 & price<=4000) 
nrow(Z)  
[1] 817182
Assign Transaction ID
Z$tid = group_indices(Z, date, cust)
No. Customers, Categories, Product Items & Transactions
sapply(Z[,c("cust","cat","prod","tid")], n_distinct)
  cust    cat   prod    tid 
 32256   2007  23789 119422 
Summary of Item Records
summary(Z)
      date                 cust               age              area             cat        
 Min.   :2000-11-01   Min.   :    1069   D      :181089   E      :312358   Min.   :100101  
 1st Qu.:2000-11-28   1st Qu.:  968775   E      :150947   F      :245079   1st Qu.:110106  
 Median :2001-01-01   Median : 1587685   C      :140721   G      : 71905   Median :130106  
 Mean   :2000-12-30   Mean   : 1406500   F      : 99641   C      : 71600   Mean   :284784  
 3rd Qu.:2001-01-30   3rd Qu.: 1854701   B      : 66353   H      : 40647   3rd Qu.:520311  
 Max.   :2001-02-28   Max.   :20002000   G      : 53689   D      : 38654   Max.   :780510  
                                         (Other):124742   (Other): 36939                   
      prod                    qty             cost          price           tid        
 Min.   :     20008819   Min.   : 1.00   Min.   :   0   Min.   :   1   Min.   :     1  
 1st Qu.:4710085127020   1st Qu.: 1.00   1st Qu.:  35   1st Qu.:  42   1st Qu.: 28783  
 Median :4710421090060   Median : 1.00   Median :  62   Median :  76   Median : 59391  
 Mean   :4461978778400   Mean   : 1.36   Mean   : 106   Mean   : 126   Mean   : 58845  
 3rd Qu.:4712500125130   3rd Qu.: 1.00   3rd Qu.: 112   3rd Qu.: 132   3rd Qu.: 87391  
 Max.   :9789579967620   Max.   :24.00   Max.   :3798   Max.   :4000   Max.   :119422  
                                                                                       


2. 交易計錄:X

交易資料彙整
X = group_by(Z, tid) %>% summarise(
  date = first(date),  # 交易日期
  cust = first(cust),  # 顧客 ID
  age = first(age),    # 顧客 年齡級別
  area = first(area),  # 顧客 居住區別
  items = n(),                # 交易項目(總)數
  pieces = sum(qty),          # 產品(總)件數
  total = sum(price),         # 交易(總)金額
  gross = sum(price - cost)   # 毛利
  ) %>% data.frame  # 119422
交易摘要
summary(X)    
      tid              date                 cust               age             area      
 Min.   :     1   Min.   :2000-11-01   Min.   :    1069   D      :23775   E      :50532  
 1st Qu.: 29856   1st Qu.:2000-11-29   1st Qu.:  927093   C      :19661   F      :33826  
 Median : 59712   Median :2001-01-01   Median : 1615661   E      :19596   G      : 9498  
 Mean   : 59712   Mean   :2000-12-31   Mean   : 1402548   F      :13992   C      : 8527  
 3rd Qu.: 89567   3rd Qu.:2001-02-02   3rd Qu.: 1894493   B      :10515   H      : 7502  
 Max.   :119422   Max.   :2001-02-28   Max.   :20002000   G      : 8493   D      : 5108  
                                                          (Other):23390   (Other): 4429  
     items            pieces           total           gross      
 Min.   :  1.00   Min.   :  1.00   Min.   :    5   Min.   :-1645  
 1st Qu.:  2.00   1st Qu.:  3.00   1st Qu.:  227   1st Qu.:   21  
 Median :  5.00   Median :  6.00   Median :  510   Median :   68  
 Mean   :  6.84   Mean   :  9.29   Mean   :  859   Mean   :  132  
 3rd Qu.:  9.00   3rd Qu.: 12.00   3rd Qu.: 1082   3rd Qu.:  169  
 Max.   :112.00   Max.   :339.00   Max.   :30171   Max.   : 8069  
                                                                  
Check Quantile & Remove Outliers
sapply(X[,6:9], quantile, prob=c(.999, .9995, .9999))
       items pieces   total  gross
99.9%     54  81.00  9009.6 1824.7
99.95%    62  94.29 10611.6 2179.8
99.99%    82 133.00 16044.4 3226.5
X = subset(X, items<=62 & pieces<95 & total<16000) # 119328
Weekly Transactions
par(cex=0.8)
hist(X$date, "weeks", freq=T, border='lightgray', col='darkcyan', 
     las=2, main="No. Transaction per Week")



3. 顧客資料:A

顧客資料彙整
d0 = max(X$date)
A = group_by(X, cust) %>% summarise(
  r = 1 + as.integer(difftime(d0, max(date), units="days")), # recency
  s = 1 + as.integer(difftime(d0, min(date), units="days")), # seniority
  f = n(),            # frquency
  m = mean(total),    # monetary
  rev = sum(total),   # total revenue contribution
  raw = sum(gross),   # total gross profit contribution
  age = first(age),   # age group
  area = first(area), # area code
  ) %>% data.frame    # 33241
顧客摘要
summary(A) 
      cust                r               s               f              m        
 Min.   :    1069   Min.   :  1.0   Min.   :  1.0   Min.   : 1.0   Min.   :    8  
 1st Qu.: 1088519   1st Qu.:  9.0   1st Qu.: 56.0   1st Qu.: 1.0   1st Qu.:  365  
 Median : 1663402   Median : 26.0   Median : 92.0   Median : 2.0   Median :  706  
 Mean   : 1473585   Mean   : 37.5   Mean   : 80.8   Mean   : 3.7   Mean   :  993  
 3rd Qu.: 1958089   3rd Qu.: 60.0   3rd Qu.:110.0   3rd Qu.: 4.0   3rd Qu.: 1291  
 Max.   :20002000   Max.   :120.0   Max.   :120.0   Max.   :85.0   Max.   :12636  
                                                                                  
      rev              raw             age            area      
 Min.   :     8   Min.   : -784   D      :6580   E      :10800  
 1st Qu.:   707   1st Qu.:   75   C      :5915   F      : 8539  
 Median :  1750   Median :  241   E      :5080   G      : 3695  
 Mean   :  3152   Mean   :  485   F      :3719   C      : 3683  
 3rd Qu.:  3968   3rd Qu.:  612   B      :3193   D      : 2166  
 Max.   :127686   Max.   :20273   G      :2183   H      : 1453  
                                  (Other):5571   (Other): 1905  
par(mfrow=c(3,2), mar=c(3,3,4,2))
for(x in c('r','s','f','m')) 
  hist(A[,x],freq=T,main=x,xlab="",ylab="",cex.main=2)
hist(pmin(A$f,10),0:10,freq=T,xlab="",ylab="",cex.main=2)
hist(log(A$m,10),freq=T,xlab="",ylab="",cex.main=2)

Dupliate & Save
A0 = A; X0 = X; Z0 = Z
save(Z0, X0, A0, file="data/tf0.rdata")


4. Objective of the Contest

range(X$date)
[1] "2000-11-01" "2001-02-28"

使用一月底(含2001-01-31)以前的資料,建立模型來預測每一位顧客:

  1. 她在2月份(2001-02-01 ~ 2001-02-28)會不會來買?
  2. 如果她來買的話,會買多少錢?


The Basic Questions of Analysis

【Q】 What are the Unit of Analysis?

【Q】 What are the Target of Analysis? Should we model for every customers in the dataset? Why not?

【Q】 How to make the Training/Testing Data Split?

【Q】 What are the Predicting and Targeted Variables?

The Target of Analysis

Screen out the new customers (who arrive after 2001-02-01)

A = filter(A0, s > 28)  # 28584
The Baseline Probability
mean(A$r <= 28)
[1] 0.4633
Spliting Factor and Spliting Ratio
library(caTools)
set.seed(1234); spl = sample.split(A$r <= 28, SplitRatio=0.75)
cid1 = subset(A, spl)$cust    # 21438
cid2 = subset(A, !spl)$cust   # 7146

cid1/cid2 are the customers ids in the training/testing data. But, …

【Q】 What are the Predicting (X) and Targeted Variables (Y)?









LS0tDQp0aXRsZTogIlRoZSBUYS1GZW5nIERhdGFzZXQiDQphdXRob3I6ICLljZPpm43nhLYsIOS4reWxseWkp+WtuCDnrqHnkIblrbjooZPnoJTnqbbkuK3lv4MiDQpkYXRlOiAiYHIgU3lzLnRpbWUoKWAiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQo8YnI+DQoNCiMjIyDos4fmlpnlvZnmlbTmtYHnqIsNCg0KPGNlbnRlcj4NCg0KIVtGaWctMTogUGF0YSBQcmVwYXJhdGlvbl0oZmlnL2FnZ3JlZ2F0aW9uLmpwZykNCg0KPC9jZW50ZXI+DQoNCjxocj4NCg0KIyMjIDEuIOS6pOaYk+mgheebruioiOmMhO+8mmBaYA0KDQpgYGB7ciBlY2hvPVQsIG1lc3NhZ2U9RiwgY2FjaGU9Riwgd2FybmluZz1GfQ0Kcm0obGlzdD1scyhhbGw9VCkpDQpTeXMuc2V0bG9jYWxlKCJMQ19BTEwiLCJDIikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGNhVG9vbHMpDQpgYGANCg0KIyMjIyMgMS4xIFRoZSBgZG8uY2FsbC1yYmluZC1sYXBwbHlgIENvbWJvDQpgYGB7cn0NClogPSBkby5jYWxsKHJiaW5kLCBsYXBwbHkoDQogICAgZGlyKCdkYXRhL1RhRmVuZ0RhdGFTZXQnLCcuKmNzdiQnLGZ1bGwubmFtZXM9VCksDQogICAgcmVhZC5jc3YsIGhlYWRlcj1GKSANCiAgKSAlPiUgDQogIHNldE5hbWVzKGMoImRhdGUiLCJjdXN0IiwiYWdlIiwiYXJlYSIsImNhdCIsInByb2QiLCJxdHkiLCJjb3N0IiwicHJpY2UiKSkNCm5yb3coWikNCmBgYA0KDQojIyMjIyBEYXRhIENvbnZyZXNpb24NCmBgYHtyfQ0KWiRkYXRlID0gYXMuRGF0ZShhcy5jaGFyYWN0ZXIoWiRkYXRlKSkNCnN1bW1hcnkoWikNCmBgYA0KDQojIyMjIyBRdWFudGlsZSBvZiBWYXJpYWJsZXMNCmBgYHtyfQ0Kc2FwcGx5KFpbLDc6OV0sIHF1YW50aWxlLCBwcm9iPWMoLjk5LCAuOTk5LCAuOTk5NSkpDQpgYGANCg0KIyMjIyMgR2V0IHJpZCBvZiBPdXRsaWVycw0KYGBge3J9DQpaID0gc3Vic2V0KFosIHF0eTw9MjQgJiBjb3N0PD0zODAwICYgcHJpY2U8PTQwMDApIA0KbnJvdyhaKSAgDQpgYGANCg0KIyMjIyMgQXNzaWduIFRyYW5zYWN0aW9uIElEDQpgYGB7cn0NClokdGlkID0gZ3JvdXBfaW5kaWNlcyhaLCBkYXRlLCBjdXN0KQ0KYGBgDQoNCiMjIyMjIE5vLiBDdXN0b21lcnMsIENhdGVnb3JpZXMsIFByb2R1Y3QgSXRlbXMgJiBUcmFuc2FjdGlvbnMNCmBgYHtyfQ0Kc2FwcGx5KFpbLGMoImN1c3QiLCJjYXQiLCJwcm9kIiwidGlkIildLCBuX2Rpc3RpbmN0KQ0KYGBgDQoNCiMjIyMjIFN1bW1hcnkgb2YgSXRlbSBSZWNvcmRzDQpgYGB7cn0NCnN1bW1hcnkoWikNCmBgYA0KPGJyPjxocj4NCg0KDQoNCiMjIyAyLiDkuqTmmJPoqIjpjITvvJpgWGANCg0KIyMjIyMg5Lqk5piT6LOH5paZ5b2Z5pW0DQpgYGB7cn0NClggPSBncm91cF9ieShaLCB0aWQpICU+JSBzdW1tYXJpc2UoDQogIGRhdGUgPSBmaXJzdChkYXRlKSwgICMg5Lqk5piT5pel5pyfDQogIGN1c3QgPSBmaXJzdChjdXN0KSwgICMg6aGn5a6iIElEDQogIGFnZSA9IGZpcnN0KGFnZSksICAgICMg6aGn5a6iIOW5tOm9oee0muWIpQ0KICBhcmVhID0gZmlyc3QoYXJlYSksICAjIOmhp+WuoiDlsYXkvY/ljYDliKUNCiAgaXRlbXMgPSBuKCksICAgICAgICAgICAgICAgICMg5Lqk5piT6aCF55uuKOe4vSnmlbgNCiAgcGllY2VzID0gc3VtKHF0eSksICAgICAgICAgICMg55Si5ZOBKOe4vSnku7bmlbgNCiAgdG90YWwgPSBzdW0ocHJpY2UpLCAgICAgICAgICMg5Lqk5piTKOe4vSnph5HpoY0NCiAgZ3Jvc3MgPSBzdW0ocHJpY2UgLSBjb3N0KSAgICMg5q+b5YipDQogICkgJT4lIGRhdGEuZnJhbWUgICMgMTE5NDIyDQpgYGANCg0KIyMjIyMg5Lqk5piT5pGY6KaBDQpgYGB7cn0NCnN1bW1hcnkoWCkgICAgDQpgYGANCg0KIyMjIyMgQ2hlY2sgUXVhbnRpbGUgJiBSZW1vdmUgT3V0bGllcnMNCmBgYHtyfQ0Kc2FwcGx5KFhbLDY6OV0sIHF1YW50aWxlLCBwcm9iPWMoLjk5OSwgLjk5OTUsIC45OTk5KSkNCmBgYA0KDQpgYGB7cn0NClggPSBzdWJzZXQoWCwgaXRlbXM8PTYyICYgcGllY2VzPDk1ICYgdG90YWw8MTYwMDApICMgMTE5MzI4DQpgYGANCg0KIyMjIyMgV2Vla2x5IFRyYW5zYWN0aW9ucw0KYGBge3IgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9N30NCnBhcihjZXg9MC44KQ0KaGlzdChYJGRhdGUsICJ3ZWVrcyIsIGZyZXE9VCwgYm9yZGVyPSdsaWdodGdyYXknLCBjb2w9J2RhcmtjeWFuJywgDQogICAgIGxhcz0yLCBtYWluPSJOby4gVHJhbnNhY3Rpb24gcGVyIFdlZWsiKQ0KYGBgDQo8YnI+PGhyPg0KDQoNCg0KIyMjIDMuIOmhp+Wuouizh+aWme+8mmBBYA0KDQojIyMjIyDpoaflrqLos4fmlpnlvZnmlbQNCmBgYHtyfQ0KZDAgPSBtYXgoWCRkYXRlKQ0KQSA9IGdyb3VwX2J5KFgsIGN1c3QpICU+JSBzdW1tYXJpc2UoDQogIHIgPSAxICsgYXMuaW50ZWdlcihkaWZmdGltZShkMCwgbWF4KGRhdGUpLCB1bml0cz0iZGF5cyIpKSwgIyByZWNlbmN5DQogIHMgPSAxICsgYXMuaW50ZWdlcihkaWZmdGltZShkMCwgbWluKGRhdGUpLCB1bml0cz0iZGF5cyIpKSwgIyBzZW5pb3JpdHkNCiAgZiA9IG4oKSwgICAgICAgICAgICAjIGZycXVlbmN5DQogIG0gPSBtZWFuKHRvdGFsKSwgICAgIyBtb25ldGFyeQ0KICByZXYgPSBzdW0odG90YWwpLCAgICMgdG90YWwgcmV2ZW51ZSBjb250cmlidXRpb24NCiAgcmF3ID0gc3VtKGdyb3NzKSwgICAjIHRvdGFsIGdyb3NzIHByb2ZpdCBjb250cmlidXRpb24NCiAgYWdlID0gZmlyc3QoYWdlKSwgICAjIGFnZSBncm91cA0KICBhcmVhID0gZmlyc3QoYXJlYSksICMgYXJlYSBjb2RlDQogICkgJT4lIGRhdGEuZnJhbWUgICAgIyAzMzI0MQ0KYGBgDQoNCiMjIyMjIOmhp+WuouaRmOimgQ0KYGBge3J9DQpzdW1tYXJ5KEEpIA0KYGBgDQoNCmBgYHtyIGZpZy5oZWlnaHQ9OH0NCnBhcihtZnJvdz1jKDMsMiksIG1hcj1jKDMsMyw0LDIpKQ0KZm9yKHggaW4gYygncicsJ3MnLCdmJywnbScpKSANCiAgaGlzdChBWyx4XSxmcmVxPVQsbWFpbj14LHhsYWI9IiIseWxhYj0iIixjZXgubWFpbj0yKQ0KaGlzdChwbWluKEEkZiwxMCksMDoxMCxmcmVxPVQseGxhYj0iIix5bGFiPSIiLGNleC5tYWluPTIpDQpoaXN0KGxvZyhBJG0sMTApLGZyZXE9VCx4bGFiPSIiLHlsYWI9IiIsY2V4Lm1haW49MikNCmBgYA0KDQojIyMjIyBEdXBsaWF0ZSAmIFNhdmUNCmBgYHtyfQ0KQTAgPSBBOyBYMCA9IFg7IFowID0gWg0Kc2F2ZShaMCwgWDAsIEEwLCBmaWxlPSJkYXRhL3RmMC5yZGF0YSIpDQpgYGANCjxicj48aHI+DQoNCg0KDQojIyMgNC4gT2JqZWN0aXZlIG9mIHRoZSBDb250ZXN0IA0KDQpgYGB7cn0NCnJhbmdlKFgkZGF0ZSkNCmBgYA0KDQoqKuS9v+eUqOS4gOaciOW6lSjlkKsyMDAxLTAxLTMxKeS7peWJjeeahOizh+aWme+8jOW7uueri+aooeWei+S+humgkOa4rOavj+S4gOS9jemhp+Wuou+8mioqDQoNCmEuICoq5aW55ZyoMuaciOS7vSgyMDAxLTAyLTAxIH4gMjAwMS0wMi0yOCnmnIPkuI3mnIPkvobosrfvvJ8qKg0KYi4gKirlpoLmnpzlpbnkvobosrfnmoToqbHvvIzmnIPosrflpJrlsJHpjKLvvJ8qKg0KDQo8YnI+DQoNCiMjIyMjIFRoZSBCYXNpYyBRdWVzdGlvbnMgb2YgQW5hbHlzaXMNCg0KKirjgJBR44CRKiogX1doYXQgYXJlIHRoZSBVbml0IG9mIEFuYWx5c2lzP18gDQoNCisNCisNCg0KKirjgJBR44CRKiogX1doYXQgYXJlIHRoZSBUYXJnZXQgb2YgQW5hbHlzaXM/XyANCl9TaG91bGQgd2UgbW9kZWwgZm9yIGV2ZXJ5IGN1c3RvbWVycyBpbiB0aGUgZGF0YXNldD9fIA0KX1doeSBub3Q/Xw0KDQorDQorDQoNCioq44CQUeOAkSoqIF9Ib3cgdG8gbWFrZSB0aGUgVHJhaW5pbmcvVGVzdGluZyBEYXRhIFNwbGl0P18NCg0KKw0KKw0KDQoqKuOAkFHjgJEqKiBfV2hhdCBhcmUgdGhlIFByZWRpY3RpbmcgYW5kIFRhcmdldGVkIFZhcmlhYmxlcz9fDQoNCisNCisNCg0KIyMjIyMgVGhlIFRhcmdldCBvZiBBbmFseXNpcw0KDQoNClNjcmVlbiBvdXQgdGhlIG5ldyBjdXN0b21lcnMgKHdobyBhcnJpdmUgYWZ0ZXIgMjAwMS0wMi0wMSkNCmBgYHtyfQ0KQSA9IGZpbHRlcihBMCwgcyA+IDI4KSAgIyAyODU4NA0KYGBgDQoNCiMjIyMjIFRoZSBCYXNlbGluZSBQcm9iYWJpbGl0eQ0KYGBge3J9DQptZWFuKEEkciA8PSAyOCkNCmBgYA0KDQojIyMjIyBTcGxpdGluZyBGYWN0b3IgYW5kIFNwbGl0aW5nIFJhdGlvDQpgYGB7cn0NCmxpYnJhcnkoY2FUb29scykNCnNldC5zZWVkKDEyMzQpOyBzcGwgPSBzYW1wbGUuc3BsaXQoQSRyIDw9IDI4LCBTcGxpdFJhdGlvPTAuNzUpDQpjaWQxID0gc3Vic2V0KEEsIHNwbCkkY3VzdCAgICAjIDIxNDM4DQpjaWQyID0gc3Vic2V0KEEsICFzcGwpJGN1c3QgICAjIDcxNDYNCmBgYA0KYGNpZDFgL2BjaWQyYCBhcmUgdGhlIGN1c3RvbWVycyBpZHMgaW4gdGhlIHRyYWluaW5nL3Rlc3RpbmcgZGF0YS4gQnV0LCAuLi4NCg0KKirjgJBR44CRKiogX1doYXQgYXJlIHRoZSBQcmVkaWN0aW5nIChYKSBhbmQgVGFyZ2V0ZWQgVmFyaWFibGVzIChZKT9fDQoNCisNCisNCg0KPGJyPjxicj48YnI+PGJyPjxocj48YnI+PGJyPjxicj4NCg0KPHN0eWxlPg0KDQouY2FwdGlvbiB7DQogIGNvbG9yOiAjNzc3Ow0KICBtYXJnaW4tdG9wOiAxMHB4Ow0KfQ0KcCBjb2RlIHsNCiAgd2hpdGUtc3BhY2U6IGluaGVyaXQ7DQp9DQpwcmUgew0KICB3b3JkLWJyZWFrOiBub3JtYWw7DQogIHdvcmQtd3JhcDogbm9ybWFsOw0KICBsaW5lLWhlaWdodDogMTsNCn0NCnByZSBjb2RlIHsNCiAgd2hpdGUtc3BhY2U6IGluaGVyaXQ7DQp9DQpwLGxpIHsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCi5yew0KICBsaW5lLWhlaWdodDogMS4yOw0KfQ0KDQoucWl6IHsNCiAgbGluZS1oZWlnaHQ6IDEuNzU7DQogIGJhY2tncm91bmQ6ICNmMGYwZjA7DQogIGJvcmRlci1sZWZ0OiAxMnB4IHNvbGlkICNjY2ZmY2M7DQogIHBhZGRpbmc6IDRweDsNCiAgcGFkZGluZy1sZWZ0OiAxMHB4Ow0KICBjb2xvcjogIzAwOTkwMDsNCn0NCg0KdGl0bGV7DQogIGNvbG9yOiAjY2MwMDAwOw0KICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsNCn0NCg0KYm9keXsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCmgxLGgyLGgzLGg0LGg1ew0KICBjb2xvcjogIzAwNjZmZjsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCg0KaDN7DQogIGNvbG9yOiAjMDA4ODAwOw0KICBiYWNrZ3JvdW5kOiAjZTZmZmU2Ow0KICBsaW5lLWhlaWdodDogMjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQp9DQoNCmg1ew0KICBjb2xvcjogIzAwNjAwMDsNCiAgYmFja2dyb3VuZDogI2Y4ZjhmODsNCiAgbGluZS1oZWlnaHQ6IDEuNTsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQp9DQoNCjwvc3R5bGU+DQoNCg==