Identifying Consumer Segments

Loading required packages and dataset…

Loading required package: grid

examine the structure of the bank data frame

'data.frame':   4521 obs. of  17 variables:
 $ age      : int  30 33 35 30 59 35 36 39 41 43 ...
 $ job      : chr  "unemployed" "services" "management" "management" ...
 $ marital  : chr  "married" "married" "single" "married" ...
 $ education: chr  "primary" "secondary" "tertiary" "tertiary" ...
 $ default  : chr  "no" "no" "no" "no" ...
 $ balance  : int  1787 4789 1350 1476 0 747 307 147 221 -88 ...
 $ housing  : chr  "no" "yes" "yes" "yes" ...
 $ loan     : chr  "no" "yes" "no" "yes" ...
 $ contact  : chr  "cellular" "cellular" "cellular" "unknown" ...
 $ day      : int  19 11 16 3 5 23 14 6 14 17 ...
 $ month    : chr  "oct" "may" "apr" "jun" ...
 $ duration : int  79 220 185 199 226 141 341 151 57 313 ...
 $ campaign : int  1 1 1 4 1 2 1 2 2 1 ...
 $ pdays    : int  -1 339 330 -1 -1 176 330 -1 -1 147 ...
 $ previous : int  0 4 1 0 0 3 2 0 0 2 ...
 $ poutcome : chr  "unknown" "failure" "failure" "unknown" ...
 $ response : chr  "no" "no" "no" "no" ...
NULL

Printing first few rows


       admin.   blue-collar  entrepreneur     housemaid    management       retired 
          478           946           168           112           969           230 
self-employed      services       student    technician    unemployed       unknown 
          183           417            84           768           128            38 
         <NA> 
            0 

divorced  married   single     <NA> 
     528     2797     1196        0 

  primary secondary  tertiary   unknown      <NA> 
      678      2306      1350       187         0 

  no  yes <NA> 
4445   76    0 

  no  yes <NA> 
1962 2559    0 

  no  yes <NA> 
3830  691    0 
               jobtype
job             White Collar Blue Collar Other/Unknown <NA>
  admin.                 478           0             0    0
  blue-collar              0         946             0    0
  entrepreneur           168           0             0    0
  housemaid                0           0           112    0
  management             969           0             0    0
  retired                  0           0           230    0
  self-employed          183           0             0    0
  services                 0         417             0    0
  student                  0           0            84    0
  technician               0         768             0    0
  unemployed               0           0           128    0
  unknown                  0           0            38    0
  <NA>                     0           0             0    0
           bluecollar
whitecollar    0    1
          0  592 2131
          1 1798    0
jobtype
 White Collar   Blue Collar Other/Unknown 
         1798          2131           592 
        married
divorced    0    1
       0 1196 2797
       1  528    0
marital
Divorced  Married   Single 
     528     2797     1196 
, , tertiary = 0

       secondary
primary    0    1
      0  187 2306
      1  678    0

, , tertiary = 1

       secondary
primary    0    1
      0 1350    0
      1    0    0
education
  Primary Secondary  Tertiary   Unknown 
      678      2306      1350       187 
'data.frame':   3705 obs. of  16 variables:
 $ response   : chr  "no" "no" "no" "no" ...
 $ age        : int  30 30 59 39 41 39 43 36 20 40 ...
 $ jobtype    : Factor w/ 3 levels "White Collar",..: 3 1 2 2 1 2 1 2 3 1 ...
 $ marital    : Factor w/ 3 levels "Divorced","Married",..: 2 2 2 2 2 2 2 2 3 2 ...
 $ education  : Factor w/ 4 levels "Primary","Secondary",..: 1 3 2 2 3 2 2 3 2 3 ...
 $ default    : chr  "no" "no" "no" "no" ...
 $ balance    : int  1787 1476 0 147 221 9374 264 1109 502 194 ...
 $ housing    : chr  "no" "yes" "yes" "yes" ...
 $ loan       : chr  "no" "yes" "no" "no" ...
 $ whitecollar: num  0 1 0 0 1 0 1 0 0 1 ...
 $ bluecollar : num  0 0 1 1 0 1 0 1 0 0 ...
 $ divorced   : num  0 0 0 0 0 0 0 0 0 0 ...
 $ married    : num  1 1 1 1 1 1 1 1 0 1 ...
 $ primary    : num  1 0 0 0 0 0 0 0 0 0 ...
 $ secondary  : num  0 0 1 1 0 1 1 0 1 0 ...
 $ tertiary   : num  0 1 0 0 1 0 0 1 0 1 ...
NULL

null device 
          1 

Examine the cluster solution results, look for average silhouette width > 0.5 and look for last big jump in average silhoutte width

provide a single summary plot for the clustering solutions

select clustering solution and examine it

From the silhouette plot, the first five of the seven clusters appear to be large and well-defined

look at demographics across the clusters/segments (age Age in years). Examine relationship between age and response to promotion

cluster: A
[1] 45.9057
---------------------------------------------------------------------- 
cluster: B
[1] 41.6633
---------------------------------------------------------------------- 
cluster: C
[1] 43.04649
---------------------------------------------------------------------- 
cluster: D
[1] 40.03083
---------------------------------------------------------------------- 
cluster: E
[1] 32.29765

Plot lattice. responders tend to be older

Level of education (unknown, secondary, primary, tertiary)

       education
cluster Primary Secondary Tertiary Unknown
      A     509         0        0       0
      B       0         0      594       0
      C       0       826        0      56
      D       0       485        0      34
      E       0       354        0      29

Table of job status using jobtype

       jobtype
cluster White Collar Blue Collar Other/Unknown
      A           70         313           126
      B          470          81            43
      C            0         768           114
      D          488           0            31
      E            0         314            69
       marital
cluster Divorced Married Single
      A        0     449     60
      B        0     594      0
      C        0     882      0
      D        0     380    139
      E        0       0    383

look at bank client history across the clusters/segments. default Has credit in default? (yes, no)

       default
cluster  no yes
      A 502   7
      B 590   4
      C 868  14
      D 508  11
      E 372  11

balance Average yearly balance (in Euros)

cluster: A
[1] 1446.106
---------------------------------------------------------------------- 
cluster: B
[1] 1882.47
---------------------------------------------------------------------- 
cluster: C
[1] 1273.861
---------------------------------------------------------------------- 
cluster: D
[1] 1331.609
---------------------------------------------------------------------- 
cluster: E
[1] 1018.661

Plot lattice. responders tend to be older

null device 
          1 

housing Has housing loan? (yes, no)

       housing
cluster  no yes
      A 225 284
      B 310 284
      C 322 560
      D 208 311
      E 194 189

loan Has personal loan? (yes, no)

response Response to term deposit offer (yes, no)

       response
cluster  no yes
      A 473  36
      B 535  59
      C 824  58
      D 489  30
      E 333  50

Plot mosaic Response to Term Deposit Offer

Computation percentage of yes responses to term deposit offer


Percentage Responses

 A 7.1
 B 9.9
 C 6.6
 D 5.8
 E 13.1

Note the percentage of the customers receiving offers for the first time falling into each of the clusters/segments


   1    2    3    4    5    6    7    8 
13.7 16.0 23.8 14.0 10.3  3.9  8.1 10.1 
LS0tDQp0aXRsZTogIkZpbmRpbmcgTmV3IEN1c3RvbWVycyAtIFRhcmdldCBNYXJrZXRpbmciDQphdXRob3I6IEhvYSBRdWFjaA0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyBJZGVudGlmeWluZyBDb25zdW1lciBTZWdtZW50cw0KDQpMb2FkaW5nIHJlcXVpcmVkIHBhY2thZ2VzIGFuZCBkYXRhc2V0Li4uDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgY2FsbCBpbiBSIHBhY2thZ2VzIGZvciB1c2UgaW4gdGhpcyBzdHVkeQ0KbGlicmFyeShsYXR0aWNlKSAgIyBtdWx0aXZhcmlhdGUgZGF0YSB2aXN1YWxpemF0aW9uDQpsaWJyYXJ5KHZjZCkgICMgZGF0YSB2aXN1YWxpemF0aW9uIGZvciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMNCmxpYnJhcnkoY2x1c3RlcikgICMgY2x1c3RlciBhbmFseXNpcyBtZXRob2RzDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyByZWFkIGJhbmsgZGF0YSBpbnRvIFIsIGNyZWF0aW5nIGRhdGEgZnJhbWUgYmFuaw0KIyBub3RlIHRoYXQgdGhpcyBpcyBhIHNlbWljb2xvbi1kZWxpbWl0ZWQgZmlsZQ0KYmFuayA8LSByZWFkLmNzdigiYmFuay5jc3YiLCBzZXAgPSAiOyIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCmBgYA0KDQpleGFtaW5lIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGJhbmsgZGF0YSBmcmFtZQ0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIGV4YW1pbmUgdGhlIHN0cnVjdHVyZSBvZiB0aGUgYmFuayBkYXRhIGZyYW1lDQpwcmludChzdHIoYmFuaykpDQpgYGANCg0KUHJpbnRpbmcgZmlyc3QgZmV3IHJvd3MNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KcHJpbnQoaGVhZChiYW5rKSkNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQpwcmludCh0YWJsZShiYW5rJGpvYiAsIHVzZU5BID0gYygiYWx3YXlzIikpKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCnByaW50KHRhYmxlKGJhbmskbWFyaXRhbCAsIHVzZU5BID0gYygiYWx3YXlzIikpKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCnByaW50KHRhYmxlKGJhbmskZWR1Y2F0aW9uICwgdXNlTkEgPSBjKCJhbHdheXMiKSkpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KcHJpbnQodGFibGUoYmFuayRkZWZhdWx0ICwgdXNlTkEgPSBjKCJhbHdheXMiKSkpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KcHJpbnQodGFibGUoYmFuayRob3VzaW5nICwgdXNlTkEgPSBjKCJhbHdheXMiKSkpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KcHJpbnQodGFibGUoYmFuayRsb2FuICwgdXNlTkEgPSBjKCJhbHdheXMiKSkpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyBUeXBlIG9mIGpvYiAoYWRtaW4uLCB1bmtub3duLCB1bmVtcGxveWVkLCBtYW5hZ2VtZW50LA0KIyBob3VzZW1haWQsIGVudHJlcHJlbmV1ciwgc3R1ZGVudCwgYmx1ZS1jb2xsYXIsIHNlbGYtZW1wbG95ZWQsDQojIHJldGlyZWQsIHRlY2huaWNpYW4sIHNlcnZpY2VzKQ0KIyBwdXQgam9iIGludG8gdGhyZWUgbWFqb3IgY2F0ZWdvcmllcyBkZWZpbmluZyB0aGUgZmFjdG9yIHZhcmlhYmxlIGpvYnR5cGUNCiMgdGhlICJ1bmtub3duIiBjYXRlZ29yeSBpcyBob3cgbWlzc2luZyBkYXRhIHdlcmUgY29kZWQgZm9yIGpvYi4uLiANCiMgaW5jbHVkZSB0aGVzZSBpbiAiT3RoZXIvVW5rbm93biIgY2F0ZWdvcnkvbGV2ZWwNCndoaXRlX2NvbGxhcl9saXN0IDwtIGMoImFkbWluLiIsImVudHJlcHJlbmV1ciIsIm1hbmFnZW1lbnQiLCJzZWxmLWVtcGxveWVkIikgIA0KYmx1ZV9jb2xsYXJfbGlzdCA8LSBjKCJibHVlLWNvbGxhciIsInNlcnZpY2VzIiwidGVjaG5pY2lhbiIpDQpiYW5rJGpvYnR5cGUgPC0gcmVwKDMsIGxlbmd0aCA9IG5yb3coYmFuaykpDQpiYW5rJGpvYnR5cGUgPC0gaWZlbHNlKChiYW5rJGpvYiAlaW4lIHdoaXRlX2NvbGxhcl9saXN0KSwgMSwgYmFuayRqb2J0eXBlKSANCmJhbmskam9idHlwZSA8LSBpZmVsc2UoKGJhbmskam9iICVpbiUgYmx1ZV9jb2xsYXJfbGlzdCksIDIsIGJhbmskam9idHlwZSkgDQpiYW5rJGpvYnR5cGUgPC0gZmFjdG9yKGJhbmskam9idHlwZSwgbGV2ZWxzID0gYygxLCAyLCAzKSwgDQogICAgbGFiZWxzID0gYygiV2hpdGUgQ29sbGFyIiwgIkJsdWUgQ29sbGFyIiwgIk90aGVyL1Vua25vd24iKSkNCndpdGgoYmFuaywgdGFibGUoam9iLCBqb2J0eXBlLCB1c2VOQSA9IGMoImFsd2F5cyIpKSkgICMgY2hlY2sgZGVmaW5pdGlvbiAgIA0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgZGVmaW5lIGJpbmFyeSBpbmRpY2F0b3IgdmFyaWFibGVzIGFzIG51bWVyaWMgMC8xIHZhcmlhYmxlcw0KYmFuayR3aGl0ZWNvbGxhciA8LSBpZmVsc2UoKGJhbmskam9idHlwZSA9PSAiV2hpdGUgQ29sbGFyIiksIDEsIDApDQpiYW5rJGJsdWVjb2xsYXIgPC0gaWZlbHNlKChiYW5rJGpvYnR5cGUgPT0gIkJsdWUgQ29sbGFyIiksIDEsIDApDQp3aXRoKGJhbmssIHByaW50KHRhYmxlKHdoaXRlY29sbGFyLCBibHVlY29sbGFyKSkpICAjIGNoZWNrIGRlZmluaXRpb24NCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQp3aXRoKGJhbmssIHByaW50KHRhYmxlKGpvYnR5cGUpKSkgICMgY2hlY2sgZGVmaW5pdGlvbg0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgZGVmaW5lIGZhY3RvciB2YXJpYWJsZXMgd2l0aCBsYWJlbHMgZm9yIHBsb3R0aW5nIGFuZCBiaW5hcnkgZmFjdG9ycw0KYmFuayRtYXJpdGFsIDwtIGZhY3RvcihiYW5rJG1hcml0YWwsIA0KICAgIGxhYmVscyA9IGMoIkRpdm9yY2VkIiwgIk1hcnJpZWQiLCAiU2luZ2xlIikpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyBkZWZpbmUgYmluYXJ5IGluZGljYXRvciB2YXJpYWJsZXMgYXMgbnVtZXJpYyAwLzEgdmFyaWFibGVzDQpiYW5rJGRpdm9yY2VkIDwtIGlmZWxzZSgoYmFuayRtYXJpdGFsID09ICJEaXZvcmNlZCIpLCAxLCAwKQ0KYmFuayRtYXJyaWVkIDwtIGlmZWxzZSgoYmFuayRtYXJpdGFsID09ICJNYXJyaWVkIiksIDEsIDApICAgIA0Kd2l0aChiYW5rLCBwcmludCh0YWJsZShkaXZvcmNlZCwgbWFycmllZCkpKSAgIyBjaGVjayBkZWZpbml0aW9uDQoNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQp3aXRoKGJhbmssIHByaW50KHRhYmxlKG1hcml0YWwpKSkgICMgY2hlY2sgZGVmaW5pdGlvbiAgICANCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQpiYW5rJGVkdWNhdGlvbiA8LSBmYWN0b3IoYmFuayRlZHVjYXRpb24sIA0KICAgIGxhYmVscyA9IGMoIlByaW1hcnkiLCAiU2Vjb25kYXJ5IiwgIlRlcnRpYXJ5IiwgIlVua25vd24iKSkNCg0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgZGVmaW5lIGJpbmFyeSBpbmRpY2F0b3IgdmFyaWFibGVzIGFzIG51bWVyaWMgMC8xIHZhcmlhYmxlcw0KYmFuayRwcmltYXJ5IDwtIGlmZWxzZSgoYmFuayRlZHVjYXRpb24gPT0gIlByaW1hcnkiKSwgMSwgMCkNCmJhbmskc2Vjb25kYXJ5IDwtIGlmZWxzZSgoYmFuayRlZHVjYXRpb24gPT0gIlNlY29uZGFyeSIpLCAxLCAwKSAgICAgICAgDQpiYW5rJHRlcnRpYXJ5IDwtIGlmZWxzZSgoYmFuayRlZHVjYXRpb24gPT0gIlRlcnRpYXJ5IiksIDEsIDApICAgICANCndpdGgoYmFuaywgcHJpbnQodGFibGUocHJpbWFyeSwgc2Vjb25kYXJ5LCB0ZXJ0aWFyeSkpKSAgIyBjaGVjayBkZWZpbml0aW9uDQoNCmBgYA0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0Kd2l0aChiYW5rLCBwcmludCh0YWJsZShlZHVjYXRpb24pKSkgICMgY2hlY2sgZGVmaW5pdGlvbiAgICANCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIGNsaWVudCBleHBlcmllbmNlIHZhcmlhYmxlcyB3aWxsIG5vdCBiZSB1c2VmdWwgZm9yIHNlZ21lbnRhdGlvbiANCiMgYnV0IGNhbiBiZSByZWZlcnJlZCB0byBhZnRlciBzZWdtZW50cyBoYXZlIGJlZW4gZGVmaW5lZA0KYmFuayRkZWZhdWx0IDwtIGZhY3RvcihiYW5rJGRlZmF1bHQsIGxhYmVscyA9IGMoIk5vIiwgIlllcyIpKQ0KYmFuayRob3VzaW5nIDwtIGZhY3RvcihiYW5rJGhvdXNpbmcsIGxhYmVscyA9IGMoIk5vIiwgIlllcyIpKQ0KYmFuayRsb2FuIDwtIGZhY3RvcihiYW5rJGxvYW4sIGxhYmVscyA9IGMoIk5vIiwgIlllcyIpKQ0KYmFuayRyZXNwb25zZSA8LSBmYWN0b3IoYmFuayRyZXNwb25zZSwgbGFiZWxzID0gYygiTm8iLCAiWWVzIikpDQoNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIHNlbGVjdCBzdWJzZXQgb2YgY2FzZXMgbmV2ZXIgcGVydmlvdXNseSBjb250YWN0ZWQgYnkgc2FsZXMNCiMga2VlcGluZyB2YXJpYWJsZXMgbmVlZGVkIGZvciBjbHVzdGVyIGFuYWx5c2lzIGFuZCBwb3N0LWFuYWx5c2lzDQpiYW5rZnVsbCA8LSBzdWJzZXQoYmFuaywgc3Vic2V0ID0gKHByZXZpb3VzID09IDApLA0KICAgIHNlbGVjdCA9IGMoInJlc3BvbnNlIiwgImFnZSIsICJqb2J0eXBlIiwgIm1hcml0YWwiLCAiZWR1Y2F0aW9uIiwgDQogICAgICAgICAgICAgICAiZGVmYXVsdCIsICJiYWxhbmNlIiwgImhvdXNpbmciLCAibG9hbiIsIA0KICAgICAgICAgICAgICAgIndoaXRlY29sbGFyIiwgImJsdWVjb2xsYXIiLCAiZGl2b3JjZWQiLCAibWFycmllZCIsDQogICAgICAgICAgICAgICAicHJpbWFyeSIsICJzZWNvbmRhcnkiLCAidGVydGlhcnkiKSkNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIGV4YW1pbmUgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZnVsbCBiYW5rIGRhdGEgZnJhbWUNCnByaW50KHN0cihiYW5rZnVsbCkpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KcHJpbnQoaGVhZChiYW5rZnVsbCkpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyBzZWxlY3Qgc3Vic2V0IG9mIHZhcmlhYmxlcyBmb3IgaW5wdXQgdG8gY2x1c3RlciBhbmFseXNpcw0KZGF0YV9mb3JfY2x1c3RlcmluZyA8LSBzdWJzZXQoYmFua2Z1bGwsDQogICAgc2VsZWN0ID0gYygiYWdlIiwgDQogICAgICAgICAgICAgICAid2hpdGVjb2xsYXIiLCAiYmx1ZWNvbGxhciIsIA0KICAgICAgICAgICAgICAgImRpdm9yY2VkIiwgIm1hcnJpZWQiLA0KICAgICAgICAgICAgICAgInByaW1hcnkiLCAic2Vjb25kYXJ5IiwgInRlcnRpYXJ5IikpICAgIA0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgY2x1c3RlcmluZyBzb2x1dGlvbnMgKG1pbl9jbHVzdGVycyB0byBtYXhfY2x1c3RlcnMpDQojIHRoaXMgc3RlcCBtYXkgdGFrZSAxMCBtaW51dGVzIG9yIG1vcmUgdG8gY29tcGxldGUNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgc2V0IGZpbGUgZm9yIGdyYXBoaWNhbCBvdXRwdXQgZnJvbSB0aGUgY2x1c3RlcmluZyBzb2x1dGlvbnMNCnBkZihmaWxlID0gImZpZ19maW5kaW5nX25ld19jdXN0b21lcnNfY2x1c3Rlcl9zZWFyY2gucGRmIiwNCiAgICAgICAgd2lkdGggPSA4LjUsIGhlaWdodCA9IDExKQ0KbWluX2NsdXN0ZXJzIDwtIDINCm1heF9jbHVzdGVycyA8LSAyMA0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgZXZhbHVhdGUgYWx0ZXJuYXRpdmUgbnVtYmVycyBvZiBjbHVzdGVycy9zZWdtZW50cw0KIyB3ZSB1c2UgdGhlIGF2ZXJhZ2Ugc2lsaG91ZXR0ZSB3aWR0aCBhcyBhIHN0YXRpc3RpY2FsIGNyaXRlcmlvbg0KZXZhbHVhdGlvbl92ZWN0b3IgPC0gTlVMTCAgIyBpbml0aWFsaXplIGV2YWx1YXRpb24gdmVjdG9yIA0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgc2VsZWN0ZWQgYWxnb3JpdGhtIGlzIHBhbSAocGFydGl0aW9uaW5nIGFyb3VuZCBtZWRvaWRzKQ0KIyB3aXRoIHNvIG1hbnkgYmluYXJ5IHZhcmlhYmxlcywgbWFuaGF0dGFuIGRpc3RhbmNlcyBzZWVtZWQgDQojIHRvIHdvcmsgYmV0dGVyIHRoYW4gRXVjbGlkZWFuIGRpc3RhbmNlcw0KZm9yIChudW1iZXJfb2ZfY2x1c3RlcnMgaW4gbWluX2NsdXN0ZXJzOm1heF9jbHVzdGVycykgew0KICAgIHRyeV9jbHVzdGVyaW5nIDwtIHBhbShkYXRhX2Zvcl9jbHVzdGVyaW5nLCBrID0gbnVtYmVyX29mX2NsdXN0ZXJzLA0KICAgICAgICBtZXRyaWMgPSAibWFuaGF0dGFuIiwgc3RhbmQgPSBUUlVFKQ0KICAgIGV2YWx1YXRpb25fdmVjdG9yIDwtIHJiaW5kKGV2YWx1YXRpb25fdmVjdG9yLA0KICAgICAgICBkYXRhLmZyYW1lKG51bWJlcl9vZl9jbHVzdGVycywgDQogICAgICAgICAgICBhdmVyYWdlX3NpbGhvdWV0dGVfd2lkdGggPSANCiAgICAgICAgICAgICAgICB0cnlfY2x1c3RlcmluZyRzaWxpbmZvJGF2Zy53aWR0aCkpDQogICAgIyBzaG93IHBsb3QgZm9yIHRoaXMgY2x1c3RlcmluZyBzb2x1dGlvbg0KICAgIHBsb3QodHJ5X2NsdXN0ZXJpbmcpICAjIGFkZCB0aGlzIGNsdXN0ZXJpbmcgc29sdXRpb24gdG8gcmVzdWx0cyBmaWxlICAgICAgICAgDQogICAgfSAgICAgICAgDQpkZXYub2ZmKCkgICMgY2xvc2UgdGhlIHBkZiByZXN1bHRzIGZpbGUgZm9yIHRoZSBjbHVzdGVyaW5nIHNvbHV0aW9uICAgIA0KYGBgDQoNCkV4YW1pbmUgdGhlIGNsdXN0ZXIgc29sdXRpb24gcmVzdWx0cywgbG9vayBmb3IgYXZlcmFnZSBzaWxob3VldHRlIHdpZHRoID4gMC41IGFuZCBsb29rIGZvciBsYXN0IGJpZyBqdW1wIGluIGF2ZXJhZ2Ugc2lsaG91dHRlIHdpZHRoDQogICAgDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIGV4YW1pbmUgdGhlIGNsdXN0ZXIgc29sdXRpb24gcmVzdWx0cywgDQojIGxvb2sgZm9yIGF2ZXJhZ2Ugc2lsaG91ZXR0ZSB3aWR0aCA+IDAuNQ0KIyBsb29rIGZvciBsYXN0IGJpZyBqdW1wIGluIGF2ZXJhZ2Ugc2lsaG91dHRlIHdpZHRoDQpwcmludChldmFsdWF0aW9uX3ZlY3RvcikNCmBgYA0KDQpwcm92aWRlIGEgc2luZ2xlIHN1bW1hcnkgcGxvdCBmb3IgdGhlIGNsdXN0ZXJpbmcgc29sdXRpb25zDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgcHJvdmlkZSBhIHNpbmdsZSBzdW1tYXJ5IHBsb3QgZm9yIHRoZSBjbHVzdGVyaW5nIHNvbHV0aW9ucw0KcGRmKGZpbGUgPSAiZmlnX2ZpbmRpbmdfbmV3X2N1c3RvbWVyc19jbHVzdGVyX3N1bW1hcnkucGRmIiwNCiAgICAgICAgd2lkdGggPSA4LjUsIGhlaWdodCA9IDguNSkNCg0Kd2l0aChldmFsdWF0aW9uX3ZlY3RvciwgcGxvdChudW1iZXJfb2ZfY2x1c3RlcnMsIA0KICAgIGF2ZXJhZ2Vfc2lsaG91ZXR0ZV93aWR0aCkpDQoNCmRldi5vZmYoKSAgIyBjbG9zZSBzdW1tYXJ5IHJlc3VsdHMgZmlsZQ0KYGBgDQoNCnNlbGVjdCBjbHVzdGVyaW5nIHNvbHV0aW9uIGFuZCBleGFtaW5lIGl0DQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgc2VsZWN0IGNsdXN0ZXJpbmcgc29sdXRpb24gYW5kIGV4YW1pbmUgaXQNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgZXhhbWluZSB0aGUgc2V2ZW4tY2x1c3RlciBzb2x1dGlvbiBpbiBtb3JlIGRldGFpbA0Kc2V2ZW5fY2x1c3Rlcl9zb2x1dGlvbiA8LSBwYW0oZGF0YV9mb3JfY2x1c3RlcmluZywgayA9IDgsDQogICAgICAgIG1ldHJpYyA9ICJtYW5oYXR0YW4iLCBzdGFuZCA9IFRSVUUpDQoNCnBkZihmaWxlID0gImZpZ19maW5kaW5nX25ld19jdXN0b21lcnNfc2V2ZW5fY2x1c3Rlcl9zb2x1dGlvbi5wZGYiLA0KICAgIHdpZHRoID0gOC41LCBoZWlnaHQgPSA4LjUpDQoNCnBsb3Qoc2V2ZW5fY2x1c3Rlcl9zb2x1dGlvbikNCg0KZGV2Lm9mZigpDQpgYGANCg0KRnJvbSB0aGUgc2lsaG91ZXR0ZSBwbG90LCB0aGUgZmlyc3QgZml2ZSBvZiB0aGUgc2V2ZW4gY2x1c3RlcnMgYXBwZWFyIHRvIGJlIGxhcmdlIGFuZCB3ZWxsLWRlZmluZWQNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyBmcm9tIHRoZSBzaWxob3VldHRlIHBsb3QsIHRoZSBmaXJzdCBmaXZlIG9mIHRoZSBzZXZlbg0KIyBjbHVzdGVycyBhcHBlYXIgdG8gYmUgbGFyZ2UgYW5kIHdlbGwtZGVmaW5lZA0KDQojIGFkZCB0aGUgY2x1c3RlciBtZW1iZXJzaGlwIGluZm9ybWF0aW9uIGFuZCBzZWxlY3QgZmlyc3QgZml2ZQ0KYmFua2Z1bGwkY2x1c3RlciA8LSBzZXZlbl9jbHVzdGVyX3NvbHV0aW9uJGNsdXN0ZXJpbmcNCmJhbmtwYXJ0IDwtIHN1YnNldChiYW5rZnVsbCwgc3Vic2V0ID0gKGNsdXN0ZXIgPCA2KSkNCmJhbmtwYXJ0JGNsdXN0ZXIgPC0gZmFjdG9yKGJhbmtwYXJ0JGNsdXN0ZXIsDQogICAgbGFiZWxzID0gYygiQSIsICJCIiwgIkMiLCAiRCIsICJFIikpDQpgYGANCg0KbG9vayBhdCBkZW1vZ3JhcGhpY3MgYWNyb3NzIHRoZSBjbHVzdGVycy9zZWdtZW50cyAoYWdlICBBZ2UgaW4geWVhcnMpLiBFeGFtaW5lIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGFnZSBhbmQgcmVzcG9uc2UgdG8gcHJvbW90aW9uDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgbG9vayBhdCBkZW1vZ3JhcGhpY3MgYWNyb3NzIHRoZSBjbHVzdGVycy9zZWdtZW50cw0KIyAtLS0tLS0tLS0tLS0tLS0tLQ0KIyBhZ2UgIEFnZSBpbiB5ZWFycw0KIyAtLS0tLS0tLS0tLS0tLS0tLQ0KIyBleGFtaW5lIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGFnZSBhbmQgcmVzcG9uc2UgdG8gcHJvbW90aW9uDQp3aXRoKGJhbmtwYXJ0LCBwcmludChieShhZ2UsIGNsdXN0ZXIsIG1lYW4pKSkNCmBgYA0KDQpQbG90IGxhdHRpY2UuIHJlc3BvbmRlcnMgdGVuZCB0byBiZSBvbGRlcg0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQpwZGYoZmlsZSA9ICJmaWdfZmluZGluZ19uZXdfY3VzdG9tZXJzX2FnZV9sYXR0aWNlLnBkZiIsICAgICANCiAgICB3aWR0aCA9IDguNSwgaGVpZ2h0ID0gMTEpDQoNCmxhdHRpY2VfcGxvdF9vYmplY3QgPC0gaGlzdG9ncmFtKH5hZ2UgfCBjbHVzdGVyLCBkYXRhID0gYmFua3BhcnQsDQogICAgdHlwZSA9ICJkZW5zaXR5IiwgDQogICAgeGxhYiA9ICJBZ2Ugb2YgQmFuayBDbGllbnQiLCBsYXlvdXQgPSBjKDEsNSkpDQoNCnByaW50KGxhdHRpY2VfcGxvdF9vYmplY3QpICAjIHJlc3BvbmRlcnMgdGVuZCB0byBiZSBvbGRlcg0KDQpkZXYub2ZmKCkNCmBgYA0KDQpMZXZlbCBvZiBlZHVjYXRpb24gKHVua25vd24sIHNlY29uZGFyeSwgcHJpbWFyeSwgdGVydGlhcnkpDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgZWR1Y2F0aW9uDQojIExldmVsIG9mIGVkdWNhdGlvbiAodW5rbm93biwgc2Vjb25kYXJ5LCBwcmltYXJ5LCB0ZXJ0aWFyeSkNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCndpdGgoYmFua3BhcnQsIHByaW50KHRhYmxlKGNsdXN0ZXIsIGVkdWNhdGlvbikpKQ0KYGBgDQoNClRhYmxlIG9mIGpvYiBzdGF0dXMgdXNpbmcgam9idHlwZQ0KICAgICAgICAgICAgICAgDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIGpvYiBzdGF0dXMgdXNpbmcgam9idHlwZQ0KIyBXaGl0ZSBDb2xsYXI6IGFkbWluLiwgZW50cmVwcmVuZXVyLCBtYW5hZ2VtZW50LCBzZWxmLWVtcGxveWVkICANCiMgQmx1ZSBDb2xsYXI6IGJsdWUtY29sbGFyLCBzZXJ2aWNlcywgdGVjaG5pY2lhbg0KIyBPdGhlci9Vbmtub3duDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0Kd2l0aChiYW5rcGFydCwgcHJpbnQodGFibGUoY2x1c3Rlciwgam9idHlwZSkpKQ0KDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIG1hcml0YWwgc3RhdHVzDQojIE1hcml0YWwgc3RhdHVzIChtYXJyaWVkLCBkaXZvcmNlZCwgc2luZ2xlKQ0KIyBbTm90ZTogYGBkaXZvcmNlZCcnIG1lYW5zIGRpdm9yY2VkIG9yIHdpZG93ZWRdDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCndpdGgoYmFua3BhcnQsIHByaW50KHRhYmxlKGNsdXN0ZXIsIG1hcml0YWwpKSkNCg0KYGBgDQoNCmxvb2sgYXQgYmFuayBjbGllbnQgaGlzdG9yeSBhY3Jvc3MgdGhlIGNsdXN0ZXJzL3NlZ21lbnRzLiBkZWZhdWx0ICBIYXMgY3JlZGl0IGluIGRlZmF1bHQ/ICh5ZXMsIG5vKQ0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIGxvb2sgYXQgYmFuayBjbGllbnQgaGlzdG9yeSBhY3Jvc3MgdGhlIGNsdXN0ZXJzL3NlZ21lbnRzDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgZGVmYXVsdCAgSGFzIGNyZWRpdCBpbiBkZWZhdWx0PyAoeWVzLCBubykNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCndpdGgoYmFua3BhcnQsIHByaW50KHRhYmxlKGNsdXN0ZXIsIGRlZmF1bHQpKSkNCg0KYGBgDQoNCmJhbGFuY2UgIEF2ZXJhZ2UgeWVhcmx5IGJhbGFuY2UgKGluIEV1cm9zKQ0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBiYWxhbmNlICBBdmVyYWdlIHllYXJseSBiYWxhbmNlIChpbiBFdXJvcykNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQp3aXRoKGJhbmtwYXJ0LCBwcmludChieShiYWxhbmNlLCBjbHVzdGVyLCBtZWFuKSkpDQpgYGANCg0KUGxvdCBsYXR0aWNlLiByZXNwb25kZXJzIHRlbmQgdG8gYmUgb2xkZXINCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KcGRmKGZpbGUgPSAiZmlnX2ZpbmRpbmdfbmV3X2N1c3RvbWVyc19ibGFuY2VfbGF0dGljZS5wZGYiLCAgICAgDQogICAgd2lkdGggPSA4LjUsIGhlaWdodCA9IDExKQ0KDQpsYXR0aWNlX3Bsb3Rfb2JqZWN0IDwtIGhpc3RvZ3JhbSh+YmFsYW5jZSB8IGNsdXN0ZXIsIGRhdGEgPSBiYW5rcGFydCwNCiAgICB0eXBlID0gImRlbnNpdHkiLCB4bGFiID0gIkFnZSBvZiBCYW5rIENsaWVudCIsIA0KICAgIGxheW91dCA9IGMoMSw1KSkNCg0KcHJpbnQobGF0dGljZV9wbG90X29iamVjdCkgICMgcmVzcG9uZGVycyB0ZW5kIHRvIGJlIG9sZGVyDQoNCmRldi5vZmYoKQ0KDQpgYGANCg0KaG91c2luZyAgSGFzIGhvdXNpbmcgbG9hbj8gKHllcywgbm8pDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIGhvdXNpbmcgIEhhcyBob3VzaW5nIGxvYW4/ICh5ZXMsIG5vKQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCndpdGgoYmFua3BhcnQsIHByaW50KHRhYmxlKGNsdXN0ZXIsIGhvdXNpbmcpKSkNCg0KYGBgDQoNCmxvYW4gIEhhcyBwZXJzb25hbCBsb2FuPyAoeWVzLCBubykNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIGxvYW4gIEhhcyBwZXJzb25hbCBsb2FuPyAoeWVzLCBubykNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0Kd2l0aChiYW5rcGFydCwgcHJpbnQodGFibGUoY2x1c3RlciwgbG9hbikpKQ0KDQpgYGANCg0KIHJlc3BvbnNlICBSZXNwb25zZSB0byB0ZXJtIGRlcG9zaXQgb2ZmZXIgKHllcywgbm8pDQogDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyByZXNwb25zZSAgUmVzcG9uc2UgdG8gdGVybSBkZXBvc2l0IG9mZmVyICh5ZXMsIG5vKQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQp3aXRoKGJhbmtwYXJ0LCBwcmludCh0YWJsZShjbHVzdGVyLCByZXNwb25zZSkpKQ0KDQpgYGANCg0KUGxvdCBtb3NhaWMgUmVzcG9uc2UgdG8gVGVybSBEZXBvc2l0IE9mZmVyDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCnBkZihmaWxlID0gImZpZ19maW5kaW5nX25ld19jdXN0b21lcnNfcmVzcG9uc2VfbW9zYWljLnBkZiIsIA0KICAgIHdpZHRoID0gOC41LCBoZWlnaHQgPSA4LjUpDQoNCm1vc2FpYyggfiByZXNwb25zZSArIGNsdXN0ZXIsIGRhdGEgPSBiYW5rcGFydCwNCiAgbGFiZWxpbmdfYXJncyA9IGxpc3Qoc2V0X3Zhcm5hbWVzID0gYyhyZXNwb25zZSA9ICJSZXNwb25zZSB0byBUZXJtIERlcG9zaXQgT2ZmZXIiLCANCiAgY2x1c3RlciA9ICJTZWdtZW50IE1lbWJlcnNoaXAiKSksDQogIGhpZ2hsaWdodGluZyA9ICJyZXNwb25zZSIsDQogIGhpZ2hsaWdodGluZ19maWxsID0gYygiY29ybnNpbGsiLCJ2aW9sZXQiKSwNCiAgcm90X2xhYmVscyA9IGMobGVmdCA9IDAsIHRvcCA9IDApLA0KICBwb3NfbGFiZWxzID0gYygiY2VudGVyIiwiY2VudGVyIiksDQogIG9mZnNldF9sYWJlbHMgPSBjKDAuMCwwLjYpKQ0KDQpkZXYub2ZmKCkNCg0KDQpgYGANCg0KQ29tcHV0YXRpb24gcGVyY2VudGFnZSBvZiB5ZXMgcmVzcG9uc2VzIHRvIHRlcm0gZGVwb3NpdCBvZmZlcg0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIGNvbXB1dGUgcGVyY2VudGFnZSBvZiB5ZXMgcmVzcG9uc2VzIHRvIHRlcm0gZGVwb3NpdCBvZmZlcg0KcmVzcG9uc2VfdGFibGUgPC0gdGFibGUoYmFua3BhcnQkY2x1c3RlciwgYmFua3BhcnQkcmVzcG9uc2UpDQpjYXQoIlxuUGVyY2VudGFnZSBSZXNwb25zZXNcbiIpDQpmb3IgKGkgaW4gMTo1KSANCiAgICAgY2F0KCJcbiIsIHRvdXBwZXIobGV0dGVyc1tpXSksIA0KICAgICAgICAgcm91bmQoMTAwICogcmVzcG9uc2VfdGFibGVbaSwyXSAvIA0KICAgICAgICAgICAgIHN1bShyZXNwb25zZV90YWJsZVtpLF0pLCBkaWdpdHMgPSAxKSkNCg0KYGBgDQoNCk5vdGUgdGhlIHBlcmNlbnRhZ2Ugb2YgdGhlIGN1c3RvbWVycyByZWNlaXZpbmcgb2ZmZXJzIGZvciB0aGUgZmlyc3QgdGltZSBmYWxsaW5nIGludG8gZWFjaCBvZiB0aGUgY2x1c3RlcnMvc2VnbWVudHMNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyBub3RlIHRoZSBwZXJjZW50YWdlIG9mIHRoZSBjdXN0b21lcnMgcmVjZWl2aW5nIG9mZmVycw0KIyBmb3IgdGhlIGZpcnN0IHRpbWUgZmFsbGluZyBpbnRvIGVhY2ggb2YgdGhlIGNsdXN0ZXJzL3NlZ21lbnRzDQojIEEgPSAxIC4uLiBFID0gNSAuLi4NCnByaW50KHJvdW5kKDEwMCAqIHRhYmxlKGJhbmtmdWxsJGNsdXN0ZXIpIC8gbnJvdyhiYW5rZnVsbCksIGRpZ2l0cyA9IDEpKQ0KYGBgDQo=