Abstract

The Data pre-processing and visualization herein is done with the help of R Programming Language and Tableau. First, I will process non dummy variable in Section 1 and then process dummy variables in Section 2

Tableau Link to my Profile for interactive Visualization: https://public.tableau.com/app/profile/emmanuel.m.maseruka

Section 1: Non-Dummy Variable Preprocessing

distancefromhome - the distance from home where the transaction happened.

distancefromlast_transaction - the distance from last transaction happened.

ratiotomedianpurchaseprice - Ratio of purchased price transaction to median purchase price.

1) STEP 1

Pulling my Credit card Fraud Data set

data<-read.csv("C:\\Users\\Kevin Meng\\OneDrive\\Desktop\\1.Credit card Fraud.csv",header = TRUE)%>%as.data.frame() 

2) STEP 2

Normalization of Non Dummy Attributes




range<-max(data$distance_from_home)-min(data$distance_from_home)

dist.home.norm<-(data$distance_from_home-min(data$distance_from_home))/range   #normalized distance from home

range<-max(data$distance_from_last_transaction)-min(data$distance_from_last_transaction)

dist.transac.norm<-(data$distance_from_last_transaction-min(data$distance_from_last_transaction))/range  #normalized distance from last transaction

range<-max(data$ratio_to_median_purchase_price)-min(data$ratio_to_median_purchase_price)

median2purchase.ratio.norm<-(data$ratio_to_median_purchase_price-min(data$ratio_to_median_purchase_price))/range #normalized ratio_to_median_purchase_price

3) STEP 3

New Dataset with Normalized Attributes

new.data<-cbind(dist.home.norm,dist.transac.norm,median2purchase.ratio.norm,data$repeat_retailer,data$used_chip,data$used_pin_number,data$online_order,data$fraud) #Creating new dataset with normalised attributes

4) STEP 4

Visualizing the Relationship between the Normalized Attributes

The Visualization below was produced by Tableau

Tableau Link to my Profile for interactive Visualistion: https://public.tableau.com/app/profile/emmanuel.m.maseruka/viz/CreditCardFraud_16558266779080/Dashboard1

Section 2: Dummy Variable Preprocessing & Visualisation

repeat_retailer - Is the transaction happened from same retailer. (dummy)

used_chip - Is the transaction through chip (dummy)

used_pin_number - Is the transaction happened by using PIN number(dummy)

online_order - Is the transaction an online order (dummy)

1) STEP 1

Subdividing Attributes into different groups

repeat_retailer.fraud1<-subset(data,fraud==1, select = repeat_retailer)
repeat_retailer.1.fraud1<-subset(repeat_retailer.fraud1,repeat_retailer==1)       #Repeat Retailers that were a fraud
repeat_retailer.0.fraud1<-subset(repeat_retailer.fraud1,repeat_retailer==0)       #Non Repeat Retailers that were a fraud




repeat_retailer.fraud0<-subset(data,fraud==0, select = repeat_retailer)
repeat_retailer.1.fraud0<-subset(repeat_retailer.fraud0,repeat_retailer==1)        #Repeat Retailers that were not fraud
repeat_retailer.0.fraud0<-subset(repeat_retailer.fraud0,repeat_retailer==0)        #Non Repeat Retailers that were not fraud

fraud<-c(nrow(repeat_retailer.1.fraud1),nrow(repeat_retailer.0.fraud1),nrow(repeat_retailer.fraud1))
no.fraud<-c(nrow(repeat_retailer.1.fraud0),nrow(repeat_retailer.0.fraud0),nrow(repeat_retailer.fraud0))



totals<-c(nrow(repeat_retailer.1.fraud1)+nrow(repeat_retailer.1.fraud0),nrow(repeat_retailer.0.fraud1)+nrow(repeat_retailer.0.fraud0),nrow(repeat_retailer.fraud1)+nrow(repeat_retailer.fraud0))



x<-rbind(fraud,no.fraud,totals) 
x<-as.data.frame(x)
colnames(x)<-c("Repeat Retailers","Non Repeat Retailers", "Total")
row.names(x)<-c("Fraud","No Fraud","Total")
x %>%
  kbl() %>%
  kable_material(c("striped", "hover"))
Repeat Retailers Non Repeat Retailers Total
Fraud 76925 10478 87403
No Fraud 804611 107986 912597
Total 881536 118464 1000000
NA
used_chip.fraud1<-subset(data,fraud==1, select = used_chip)
used_chip.1.fraud1<-subset(used_chip.fraud1,used_chip==1)                         #Instances who Used_chip that were a fraud
used_chip.0.fraud1<-subset(used_chip.fraud1,used_chip==0)                         #Instances who did not Use_chip that were a fraud


used_chip.fraud0<-subset(data,fraud==0, select = used_chip)
used_chip.1.fraud0<-subset(used_chip.fraud0,used_chip==1)                         #Instances who Used_chip that were a fraud
used_chip.0.fraud0<-subset(used_chip.fraud0,used_chip==0)                         #Instances who Used_chip that were a fraud

fraud2<-c(nrow(used_chip.1.fraud1),nrow(used_chip.0.fraud1),nrow(used_chip.fraud1))
no.fraud2<-c(nrow(used_chip.1.fraud0),nrow(used_chip.0.fraud0),nrow(used_chip.fraud0))
y<-rbind(fraud2,no.fraud2)


totals1<-c(nrow(used_chip.1.fraud1)+nrow(used_chip.1.fraud0),nrow(used_chip.0.fraud1)+nrow(used_chip.0.fraud0),nrow(used_chip.fraud1)+nrow(used_chip.fraud0))



y<-rbind(fraud2,no.fraud2,totals1) 
y<-as.data.frame(y)
colnames(y)<-c("Used Chip","No Chip", "Total")
row.names(y)<-c("Fraud","No Fraud","Total")
y %>%
  kbl() %>%
  kable_material(c("striped", "hover"))
Used Chip No Chip Total
Fraud 22410 64993 87403
No Fraud 327989 584608 912597
Total 350399 649601 1000000
used_pin_number.fraud1<-subset(data,fraud==1, select = used_pin_number)
used_pin_number.1.fraud1<-subset(used_pin_number.fraud1,used_pin_number==1)        #Instances who Used_pin that were a fraud
used_pin_number.0.fraud1<-subset(used_pin_number.fraud1,used_pin_number==0)        #Instances who did not Use_chip that were a fraud


used_pin_number.fraud0<-subset(data,fraud==0, select = used_pin_number)
used_pin_number.1.fraud0<-subset(used_pin_number.fraud0,used_pin_number==1)        #Instances who Used_chip that were not a fraud
used_pin_number.0.fraud0<-subset(used_pin_number.fraud0,used_pin_number==0)        #Instances who did not Use_chip that were not a fraud

fraud3<-c(nrow(used_pin_number.1.fraud1),nrow(used_pin_number.0.fraud1),nrow(used_pin_number.fraud1))
no.fraud3<-c(nrow(used_pin_number.1.fraud0),nrow(used_pin_number.0.fraud0),nrow(used_pin_number.fraud0))
z<-rbind(fraud3,no.fraud3)



totals2<-c(nrow(used_pin_number.1.fraud1)+nrow(used_pin_number.1.fraud0),nrow(used_pin_number.0.fraud1)+nrow(used_pin_number.0.fraud0),nrow(used_pin_number.fraud1)+nrow(used_pin_number.fraud0))



z<-rbind(fraud3,no.fraud3,totals2) 
z<-as.data.frame(z)
colnames(z)<-c("Used Pin","No Pin", "Total")
row.names(z)<-c("Fraud","No Fraud","Total")
z %>%
  kbl() %>%
  kable_material(c("striped", "hover"))
Used Pin No Pin Total
Fraud 273 87130 87403
No Fraud 100335 812262 912597
Total 100608 899392 1000000

online_order.fraud1<-subset(data,fraud==1, select = online_order)
online_order.1.fraud1<-subset(online_order.fraud1,online_order==1)                 #Instances who Used_online purchases that were a fraud
online_order.0.fraud1<-subset(online_order.fraud1,online_order==0)                 #Instances who did not Use_online purchases that were a fraud

online_order.fraud0<-subset(data,fraud==0, select = online_order)
online_order.1.fraud0<-subset(online_order.fraud0,online_order==1)                 #Instances who Used_online purchases that were not a fraud
online_order.0.fraud0<-subset(online_order.fraud0,online_order==0)                #Instances who did not Use_online purchases that were not a fraud


fraud4<-c(nrow(online_order.1.fraud1),nrow(online_order.0.fraud1),nrow(online_order.fraud1))
no.fraud4<-c(nrow(online_order.1.fraud0),nrow(online_order.0.fraud0),nrow(online_order.fraud0))
a<-rbind(fraud4,no.fraud4)


totals3<-c(nrow(online_order.1.fraud1)+nrow(online_order.1.fraud0),nrow(online_order.0.fraud1)+nrow(online_order.0.fraud0),nrow(online_order.fraud1)+nrow(online_order.fraud0))



a<-rbind(fraud4,no.fraud4,totals3) 
a<-as.data.frame(a)
colnames(a)<-c("Online Order","Offline Order", "Total")
row.names(a)<-c("Fraud","No Fraud","Total")
a %>%
  kbl() %>%
  kable_material(c("striped", "hover"))
Online Order Offline Order Total
Fraud 82711 4692 87403
No Fraud 567841 344756 912597
Total 650552 349448 1000000

2) STEP 2

Visualizing the Dummy Variables

The Visualization below was produced by Tableau

Tableau Link to my Profile for interactive Visualistion: https://public.tableau.com/app/profile/emmanuel.m.maseruka/viz/CreditCardFraudDetectionVisualisationofDummyVariables2/Dashboard1

Tableau Link to my Profile for interactive Visualiztion: https://public.tableau.com/app/profile/emmanuel.m.maseruka/viz/CreditCardFraudDetectionVisualisationofDummyVariables1/Dashboard2

LS0tDQp0aXRsZTogIk1hY2hpbmUgTGVhcm5pbmcgJiBCaWcgRGF0YSBQcm9qZWN0Ig0Kc3VidGl0bGU6ICJDcmVkaXQgQ2FyZCBGcmF1ZCBEZXRlY3Rpb246IERhdGEgUHJlLXByb2Nlc3NpbmcgJiBWaXN1YWxpc2F0aW9uIg0KYXV0aG9yOiAiRW1tYW51ZWwgTWFzZXJ1a2EiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclYiAlZCwgJVknKWAiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIEFic3RyYWN0DQoNClRoZSBEYXRhIHByZS1wcm9jZXNzaW5nIGFuZCB2aXN1YWxpemF0aW9uIGhlcmVpbiBpcyBkb25lIHdpdGggdGhlIGhlbHAgb2YgUiBQcm9ncmFtbWluZyBMYW5ndWFnZSBhbmQgVGFibGVhdS4gRmlyc3QsIEkgd2lsbCBwcm9jZXNzIG5vbiBkdW1teSB2YXJpYWJsZSBpbiBTZWN0aW9uIDEgYW5kIHRoZW4gcHJvY2VzcyBkdW1teSB2YXJpYWJsZXMgaW4gU2VjdGlvbiAyDQoNCl9UYWJsZWF1IExpbmsgdG8gbXkgUHJvZmlsZSBmb3IgaW50ZXJhY3RpdmUgVmlzdWFsaXphdGlvbjpfIGh0dHBzOi8vcHVibGljLnRhYmxlYXUuY29tL2FwcC9wcm9maWxlL2VtbWFudWVsLm0ubWFzZXJ1a2ENCg0KIyBTZWN0aW9uIDE6IE5vbi1EdW1teSBWYXJpYWJsZSBQcmVwcm9jZXNzaW5nDQoNCiAgZGlzdGFuY2Vmcm9taG9tZSAtIHRoZSBkaXN0YW5jZSBmcm9tIGhvbWUgd2hlcmUgdGhlIHRyYW5zYWN0aW9uIGhhcHBlbmVkLg0KICANCiAgZGlzdGFuY2Vmcm9tbGFzdF90cmFuc2FjdGlvbiAtIHRoZSBkaXN0YW5jZSBmcm9tIGxhc3QgdHJhbnNhY3Rpb24gaGFwcGVuZWQuDQogIA0KICByYXRpb3RvbWVkaWFucHVyY2hhc2VwcmljZSAtIFJhdGlvIG9mIHB1cmNoYXNlZCBwcmljZSB0cmFuc2FjdGlvbiB0byBtZWRpYW4gcHVyY2hhc2UgcHJpY2UuDQogIA0KDQoqKjEpKiogX19TVEVQIDFfXw0KDQoNCiAgIFB1bGxpbmcgbXkgQ3JlZGl0IGNhcmQgRnJhdWQgRGF0YSBzZXQNCiAgIA0KYGBge3J9DQpkYXRhPC1yZWFkLmNzdigiQzpcXFVzZXJzXFxLZXZpbiBNZW5nXFxPbmVEcml2ZVxcRGVza3RvcFxcMS5DcmVkaXQgY2FyZCBGcmF1ZC5jc3YiLGhlYWRlciA9IFRSVUUpJT4lYXMuZGF0YS5mcmFtZSgpIA0KYGBgDQoNCg0KDQoqKjIpKiogX19TVEVQIDJfXw0KDQoNCiAgIE5vcm1hbGl6YXRpb24gb2YgTm9uIER1bW15IEF0dHJpYnV0ZXMNCg0KYGBge3J9DQoNCg0KDQpyYW5nZTwtbWF4KGRhdGEkZGlzdGFuY2VfZnJvbV9ob21lKS1taW4oZGF0YSRkaXN0YW5jZV9mcm9tX2hvbWUpDQoNCmRpc3QuaG9tZS5ub3JtPC0oZGF0YSRkaXN0YW5jZV9mcm9tX2hvbWUtbWluKGRhdGEkZGlzdGFuY2VfZnJvbV9ob21lKSkvcmFuZ2UgICAjbm9ybWFsaXplZCBkaXN0YW5jZSBmcm9tIGhvbWUNCg0KcmFuZ2U8LW1heChkYXRhJGRpc3RhbmNlX2Zyb21fbGFzdF90cmFuc2FjdGlvbiktbWluKGRhdGEkZGlzdGFuY2VfZnJvbV9sYXN0X3RyYW5zYWN0aW9uKQ0KDQpkaXN0LnRyYW5zYWMubm9ybTwtKGRhdGEkZGlzdGFuY2VfZnJvbV9sYXN0X3RyYW5zYWN0aW9uLW1pbihkYXRhJGRpc3RhbmNlX2Zyb21fbGFzdF90cmFuc2FjdGlvbikpL3JhbmdlICAjbm9ybWFsaXplZCBkaXN0YW5jZSBmcm9tIGxhc3QgdHJhbnNhY3Rpb24NCg0KcmFuZ2U8LW1heChkYXRhJHJhdGlvX3RvX21lZGlhbl9wdXJjaGFzZV9wcmljZSktbWluKGRhdGEkcmF0aW9fdG9fbWVkaWFuX3B1cmNoYXNlX3ByaWNlKQ0KDQptZWRpYW4ycHVyY2hhc2UucmF0aW8ubm9ybTwtKGRhdGEkcmF0aW9fdG9fbWVkaWFuX3B1cmNoYXNlX3ByaWNlLW1pbihkYXRhJHJhdGlvX3RvX21lZGlhbl9wdXJjaGFzZV9wcmljZSkpL3JhbmdlICNub3JtYWxpemVkIHJhdGlvX3RvX21lZGlhbl9wdXJjaGFzZV9wcmljZQ0KDQpgYGANCg0KDQoqKjMpKiogX19TVEVQIDNfXw0KDQoNCiAgIE5ldyBEYXRhc2V0IHdpdGggTm9ybWFsaXplZCBBdHRyaWJ1dGVzDQoNCmBgYHtyfQ0KbmV3LmRhdGE8LWNiaW5kKGRpc3QuaG9tZS5ub3JtLGRpc3QudHJhbnNhYy5ub3JtLG1lZGlhbjJwdXJjaGFzZS5yYXRpby5ub3JtLGRhdGEkcmVwZWF0X3JldGFpbGVyLGRhdGEkdXNlZF9jaGlwLGRhdGEkdXNlZF9waW5fbnVtYmVyLGRhdGEkb25saW5lX29yZGVyLGRhdGEkZnJhdWQpICNDcmVhdGluZyBuZXcgZGF0YXNldCB3aXRoIG5vcm1hbGlzZWQgYXR0cmlidXRlcw0KYGBgDQoNCg0KKio0KSoqIF9fU1RFUCA0X18NCg0KICAgVmlzdWFsaXppbmcgdGhlIFJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBOb3JtYWxpemVkIEF0dHJpYnV0ZXMNCiAgIA0KICAgVGhlIFZpc3VhbGl6YXRpb24gYmVsb3cgd2FzIHByb2R1Y2VkIGJ5IFRhYmxlYXUNCiAgIA0KICAgX1RhYmxlYXUgTGluayB0byBteSBQcm9maWxlIGZvciBpbnRlcmFjdGl2ZSBWaXN1YWxpc3Rpb246XyBodHRwczovL3B1YmxpYy50YWJsZWF1LmNvbS9hcHAvcHJvZmlsZS9lbW1hbnVlbC5tLm1hc2VydWthL3Zpei9DcmVkaXRDYXJkRnJhdWRfMTY1NTgyNjY3NzkwODAvRGFzaGJvYXJkMQ0KDQpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmNhcD0iUHJvZHVjZWQgd2l0aDogVGFibGVhdSIsIG91dC53aWR0aCA9ICcxMDAlJyxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9LZXZpbiBNZW5nL09uZURyaXZlL0Rlc2t0b3AvbWFjaGluZSBsZWFybmluZyBwcm9qZWN0L3ZpejEucG5nIikgIA0KDQpgYGANCg0KDQoNCg0KDQoNCg0KIyMgU2VjdGlvbiAyOiBEdW1teSBWYXJpYWJsZSBQcmVwcm9jZXNzaW5nICYgVmlzdWFsaXNhdGlvbg0KDQogIHJlcGVhdF9yZXRhaWxlciAtIElzIHRoZSB0cmFuc2FjdGlvbiBoYXBwZW5lZCBmcm9tIHNhbWUgcmV0YWlsZXIuIChkdW1teSkNCg0KICB1c2VkX2NoaXAgLSBJcyB0aGUgdHJhbnNhY3Rpb24gdGhyb3VnaCBjaGlwIChkdW1teSkNCg0KICB1c2VkX3Bpbl9udW1iZXIgLSBJcyB0aGUgdHJhbnNhY3Rpb24gaGFwcGVuZWQgYnkgdXNpbmcgUElOIG51bWJlcihkdW1teSkNCg0KICBvbmxpbmVfb3JkZXIgLSBJcyB0aGUgdHJhbnNhY3Rpb24gYW4gb25saW5lIG9yZGVyIChkdW1teSkNCiAgDQoqKjEpKiogX19TVEVQIDFfXw0KDQogIFN1YmRpdmlkaW5nIEF0dHJpYnV0ZXMgaW50byBkaWZmZXJlbnQgZ3JvdXBzDQoNCiAgDQpgYGB7cn0NCnJlcGVhdF9yZXRhaWxlci5mcmF1ZDE8LXN1YnNldChkYXRhLGZyYXVkPT0xLCBzZWxlY3QgPSByZXBlYXRfcmV0YWlsZXIpDQpyZXBlYXRfcmV0YWlsZXIuMS5mcmF1ZDE8LXN1YnNldChyZXBlYXRfcmV0YWlsZXIuZnJhdWQxLHJlcGVhdF9yZXRhaWxlcj09MSkgICAgICAgI1JlcGVhdCBSZXRhaWxlcnMgdGhhdCB3ZXJlIGEgZnJhdWQNCnJlcGVhdF9yZXRhaWxlci4wLmZyYXVkMTwtc3Vic2V0KHJlcGVhdF9yZXRhaWxlci5mcmF1ZDEscmVwZWF0X3JldGFpbGVyPT0wKSAgICAgICAjTm9uIFJlcGVhdCBSZXRhaWxlcnMgdGhhdCB3ZXJlIGEgZnJhdWQNCg0KDQoNCg0KcmVwZWF0X3JldGFpbGVyLmZyYXVkMDwtc3Vic2V0KGRhdGEsZnJhdWQ9PTAsIHNlbGVjdCA9IHJlcGVhdF9yZXRhaWxlcikNCnJlcGVhdF9yZXRhaWxlci4xLmZyYXVkMDwtc3Vic2V0KHJlcGVhdF9yZXRhaWxlci5mcmF1ZDAscmVwZWF0X3JldGFpbGVyPT0xKSAgICAgICAgI1JlcGVhdCBSZXRhaWxlcnMgdGhhdCB3ZXJlIG5vdCBmcmF1ZA0KcmVwZWF0X3JldGFpbGVyLjAuZnJhdWQwPC1zdWJzZXQocmVwZWF0X3JldGFpbGVyLmZyYXVkMCxyZXBlYXRfcmV0YWlsZXI9PTApICAgICAgICAjTm9uIFJlcGVhdCBSZXRhaWxlcnMgdGhhdCB3ZXJlIG5vdCBmcmF1ZA0KDQpmcmF1ZDwtYyhucm93KHJlcGVhdF9yZXRhaWxlci4xLmZyYXVkMSksbnJvdyhyZXBlYXRfcmV0YWlsZXIuMC5mcmF1ZDEpLG5yb3cocmVwZWF0X3JldGFpbGVyLmZyYXVkMSkpDQpuby5mcmF1ZDwtYyhucm93KHJlcGVhdF9yZXRhaWxlci4xLmZyYXVkMCksbnJvdyhyZXBlYXRfcmV0YWlsZXIuMC5mcmF1ZDApLG5yb3cocmVwZWF0X3JldGFpbGVyLmZyYXVkMCkpDQoNCg0KDQp0b3RhbHM8LWMobnJvdyhyZXBlYXRfcmV0YWlsZXIuMS5mcmF1ZDEpK25yb3cocmVwZWF0X3JldGFpbGVyLjEuZnJhdWQwKSxucm93KHJlcGVhdF9yZXRhaWxlci4wLmZyYXVkMSkrbnJvdyhyZXBlYXRfcmV0YWlsZXIuMC5mcmF1ZDApLG5yb3cocmVwZWF0X3JldGFpbGVyLmZyYXVkMSkrbnJvdyhyZXBlYXRfcmV0YWlsZXIuZnJhdWQwKSkNCg0KDQoNCng8LXJiaW5kKGZyYXVkLG5vLmZyYXVkLHRvdGFscykgDQp4PC1hcy5kYXRhLmZyYW1lKHgpDQpjb2xuYW1lcyh4KTwtYygiUmVwZWF0IFJldGFpbGVycyIsIk5vbiBSZXBlYXQgUmV0YWlsZXJzIiwgIlRvdGFsIikNCnJvdy5uYW1lcyh4KTwtYygiRnJhdWQiLCJObyBGcmF1ZCIsIlRvdGFsIikNCnggJT4lDQogIGtibCgpICU+JQ0KICBrYWJsZV9tYXRlcmlhbChjKCJzdHJpcGVkIiwgImhvdmVyIikpDQoNCmBgYA0KDQoNCg0KICANCiAgDQpgYGB7cn0NCnVzZWRfY2hpcC5mcmF1ZDE8LXN1YnNldChkYXRhLGZyYXVkPT0xLCBzZWxlY3QgPSB1c2VkX2NoaXApDQp1c2VkX2NoaXAuMS5mcmF1ZDE8LXN1YnNldCh1c2VkX2NoaXAuZnJhdWQxLHVzZWRfY2hpcD09MSkgICAgICAgICAgICAgICAgICAgICAgICAgI0luc3RhbmNlcyB3aG8gVXNlZF9jaGlwIHRoYXQgd2VyZSBhIGZyYXVkDQp1c2VkX2NoaXAuMC5mcmF1ZDE8LXN1YnNldCh1c2VkX2NoaXAuZnJhdWQxLHVzZWRfY2hpcD09MCkgICAgICAgICAgICAgICAgICAgICAgICAgI0luc3RhbmNlcyB3aG8gZGlkIG5vdCBVc2VfY2hpcCB0aGF0IHdlcmUgYSBmcmF1ZA0KDQoNCnVzZWRfY2hpcC5mcmF1ZDA8LXN1YnNldChkYXRhLGZyYXVkPT0wLCBzZWxlY3QgPSB1c2VkX2NoaXApDQp1c2VkX2NoaXAuMS5mcmF1ZDA8LXN1YnNldCh1c2VkX2NoaXAuZnJhdWQwLHVzZWRfY2hpcD09MSkgICAgICAgICAgICAgICAgICAgICAgICAgI0luc3RhbmNlcyB3aG8gVXNlZF9jaGlwIHRoYXQgd2VyZSBhIGZyYXVkDQp1c2VkX2NoaXAuMC5mcmF1ZDA8LXN1YnNldCh1c2VkX2NoaXAuZnJhdWQwLHVzZWRfY2hpcD09MCkgICAgICAgICAgICAgICAgICAgICAgICAgI0luc3RhbmNlcyB3aG8gVXNlZF9jaGlwIHRoYXQgd2VyZSBhIGZyYXVkDQoNCmZyYXVkMjwtYyhucm93KHVzZWRfY2hpcC4xLmZyYXVkMSksbnJvdyh1c2VkX2NoaXAuMC5mcmF1ZDEpLG5yb3codXNlZF9jaGlwLmZyYXVkMSkpDQpuby5mcmF1ZDI8LWMobnJvdyh1c2VkX2NoaXAuMS5mcmF1ZDApLG5yb3codXNlZF9jaGlwLjAuZnJhdWQwKSxucm93KHVzZWRfY2hpcC5mcmF1ZDApKQ0KeTwtcmJpbmQoZnJhdWQyLG5vLmZyYXVkMikNCg0KDQp0b3RhbHMxPC1jKG5yb3codXNlZF9jaGlwLjEuZnJhdWQxKStucm93KHVzZWRfY2hpcC4xLmZyYXVkMCksbnJvdyh1c2VkX2NoaXAuMC5mcmF1ZDEpK25yb3codXNlZF9jaGlwLjAuZnJhdWQwKSxucm93KHVzZWRfY2hpcC5mcmF1ZDEpK25yb3codXNlZF9jaGlwLmZyYXVkMCkpDQoNCg0KDQp5PC1yYmluZChmcmF1ZDIsbm8uZnJhdWQyLHRvdGFsczEpIA0KeTwtYXMuZGF0YS5mcmFtZSh5KQ0KY29sbmFtZXMoeSk8LWMoIlVzZWQgQ2hpcCIsIk5vIENoaXAiLCAiVG90YWwiKQ0Kcm93Lm5hbWVzKHkpPC1jKCJGcmF1ZCIsIk5vIEZyYXVkIiwiVG90YWwiKQ0KeSAlPiUNCiAga2JsKCkgJT4lDQogIGthYmxlX21hdGVyaWFsKGMoInN0cmlwZWQiLCAiaG92ZXIiKSkNCmBgYA0KDQogIA0KYGBge3J9DQp1c2VkX3Bpbl9udW1iZXIuZnJhdWQxPC1zdWJzZXQoZGF0YSxmcmF1ZD09MSwgc2VsZWN0ID0gdXNlZF9waW5fbnVtYmVyKQ0KdXNlZF9waW5fbnVtYmVyLjEuZnJhdWQxPC1zdWJzZXQodXNlZF9waW5fbnVtYmVyLmZyYXVkMSx1c2VkX3Bpbl9udW1iZXI9PTEpICAgICAgICAjSW5zdGFuY2VzIHdobyBVc2VkX3BpbiB0aGF0IHdlcmUgYSBmcmF1ZA0KdXNlZF9waW5fbnVtYmVyLjAuZnJhdWQxPC1zdWJzZXQodXNlZF9waW5fbnVtYmVyLmZyYXVkMSx1c2VkX3Bpbl9udW1iZXI9PTApICAgICAgICAjSW5zdGFuY2VzIHdobyBkaWQgbm90IFVzZV9jaGlwIHRoYXQgd2VyZSBhIGZyYXVkDQoNCg0KdXNlZF9waW5fbnVtYmVyLmZyYXVkMDwtc3Vic2V0KGRhdGEsZnJhdWQ9PTAsIHNlbGVjdCA9IHVzZWRfcGluX251bWJlcikNCnVzZWRfcGluX251bWJlci4xLmZyYXVkMDwtc3Vic2V0KHVzZWRfcGluX251bWJlci5mcmF1ZDAsdXNlZF9waW5fbnVtYmVyPT0xKSAgICAgICAgI0luc3RhbmNlcyB3aG8gVXNlZF9jaGlwIHRoYXQgd2VyZSBub3QgYSBmcmF1ZA0KdXNlZF9waW5fbnVtYmVyLjAuZnJhdWQwPC1zdWJzZXQodXNlZF9waW5fbnVtYmVyLmZyYXVkMCx1c2VkX3Bpbl9udW1iZXI9PTApICAgICAgICAjSW5zdGFuY2VzIHdobyBkaWQgbm90IFVzZV9jaGlwIHRoYXQgd2VyZSBub3QgYSBmcmF1ZA0KDQpmcmF1ZDM8LWMobnJvdyh1c2VkX3Bpbl9udW1iZXIuMS5mcmF1ZDEpLG5yb3codXNlZF9waW5fbnVtYmVyLjAuZnJhdWQxKSxucm93KHVzZWRfcGluX251bWJlci5mcmF1ZDEpKQ0Kbm8uZnJhdWQzPC1jKG5yb3codXNlZF9waW5fbnVtYmVyLjEuZnJhdWQwKSxucm93KHVzZWRfcGluX251bWJlci4wLmZyYXVkMCksbnJvdyh1c2VkX3Bpbl9udW1iZXIuZnJhdWQwKSkNCno8LXJiaW5kKGZyYXVkMyxuby5mcmF1ZDMpDQoNCg0KDQp0b3RhbHMyPC1jKG5yb3codXNlZF9waW5fbnVtYmVyLjEuZnJhdWQxKStucm93KHVzZWRfcGluX251bWJlci4xLmZyYXVkMCksbnJvdyh1c2VkX3Bpbl9udW1iZXIuMC5mcmF1ZDEpK25yb3codXNlZF9waW5fbnVtYmVyLjAuZnJhdWQwKSxucm93KHVzZWRfcGluX251bWJlci5mcmF1ZDEpK25yb3codXNlZF9waW5fbnVtYmVyLmZyYXVkMCkpDQoNCg0KDQp6PC1yYmluZChmcmF1ZDMsbm8uZnJhdWQzLHRvdGFsczIpIA0KejwtYXMuZGF0YS5mcmFtZSh6KQ0KY29sbmFtZXMoeik8LWMoIlVzZWQgUGluIiwiTm8gUGluIiwgIlRvdGFsIikNCnJvdy5uYW1lcyh6KTwtYygiRnJhdWQiLCJObyBGcmF1ZCIsIlRvdGFsIikNCnogJT4lDQogIGtibCgpICU+JQ0KICBrYWJsZV9tYXRlcmlhbChjKCJzdHJpcGVkIiwgImhvdmVyIikpDQpgYGANCg0KDQpgYGB7cn0NCg0Kb25saW5lX29yZGVyLmZyYXVkMTwtc3Vic2V0KGRhdGEsZnJhdWQ9PTEsIHNlbGVjdCA9IG9ubGluZV9vcmRlcikNCm9ubGluZV9vcmRlci4xLmZyYXVkMTwtc3Vic2V0KG9ubGluZV9vcmRlci5mcmF1ZDEsb25saW5lX29yZGVyPT0xKSAgICAgICAgICAgICAgICAgI0luc3RhbmNlcyB3aG8gVXNlZF9vbmxpbmUgcHVyY2hhc2VzIHRoYXQgd2VyZSBhIGZyYXVkDQpvbmxpbmVfb3JkZXIuMC5mcmF1ZDE8LXN1YnNldChvbmxpbmVfb3JkZXIuZnJhdWQxLG9ubGluZV9vcmRlcj09MCkgICAgICAgICAgICAgICAgICNJbnN0YW5jZXMgd2hvIGRpZCBub3QgVXNlX29ubGluZSBwdXJjaGFzZXMgdGhhdCB3ZXJlIGEgZnJhdWQNCg0Kb25saW5lX29yZGVyLmZyYXVkMDwtc3Vic2V0KGRhdGEsZnJhdWQ9PTAsIHNlbGVjdCA9IG9ubGluZV9vcmRlcikNCm9ubGluZV9vcmRlci4xLmZyYXVkMDwtc3Vic2V0KG9ubGluZV9vcmRlci5mcmF1ZDAsb25saW5lX29yZGVyPT0xKSAgICAgICAgICAgICAgICAgI0luc3RhbmNlcyB3aG8gVXNlZF9vbmxpbmUgcHVyY2hhc2VzIHRoYXQgd2VyZSBub3QgYSBmcmF1ZA0Kb25saW5lX29yZGVyLjAuZnJhdWQwPC1zdWJzZXQob25saW5lX29yZGVyLmZyYXVkMCxvbmxpbmVfb3JkZXI9PTApICAgICAgICAgICAgICAgICNJbnN0YW5jZXMgd2hvIGRpZCBub3QgVXNlX29ubGluZSBwdXJjaGFzZXMgdGhhdCB3ZXJlIG5vdCBhIGZyYXVkDQoNCg0KZnJhdWQ0PC1jKG5yb3cob25saW5lX29yZGVyLjEuZnJhdWQxKSxucm93KG9ubGluZV9vcmRlci4wLmZyYXVkMSksbnJvdyhvbmxpbmVfb3JkZXIuZnJhdWQxKSkNCm5vLmZyYXVkNDwtYyhucm93KG9ubGluZV9vcmRlci4xLmZyYXVkMCksbnJvdyhvbmxpbmVfb3JkZXIuMC5mcmF1ZDApLG5yb3cob25saW5lX29yZGVyLmZyYXVkMCkpDQphPC1yYmluZChmcmF1ZDQsbm8uZnJhdWQ0KQ0KDQoNCnRvdGFsczM8LWMobnJvdyhvbmxpbmVfb3JkZXIuMS5mcmF1ZDEpK25yb3cob25saW5lX29yZGVyLjEuZnJhdWQwKSxucm93KG9ubGluZV9vcmRlci4wLmZyYXVkMSkrbnJvdyhvbmxpbmVfb3JkZXIuMC5mcmF1ZDApLG5yb3cob25saW5lX29yZGVyLmZyYXVkMSkrbnJvdyhvbmxpbmVfb3JkZXIuZnJhdWQwKSkNCg0KDQoNCmE8LXJiaW5kKGZyYXVkNCxuby5mcmF1ZDQsdG90YWxzMykgDQphPC1hcy5kYXRhLmZyYW1lKGEpDQpjb2xuYW1lcyhhKTwtYygiT25saW5lIE9yZGVyIiwiT2ZmbGluZSBPcmRlciIsICJUb3RhbCIpDQpyb3cubmFtZXMoYSk8LWMoIkZyYXVkIiwiTm8gRnJhdWQiLCJUb3RhbCIpDQphICU+JQ0KICBrYmwoKSAlPiUNCiAga2FibGVfbWF0ZXJpYWwoYygic3RyaXBlZCIsICJob3ZlciIpKQ0KYGBgDQoNCg0KDQoNCioqMikqKiBfX1NURVAgMl9fDQoNCg0KICAgX19WaXN1YWxpemluZyB0aGUgRHVtbXkgVmFyaWFibGVzX18NCiAgIA0KICAgVGhlIFZpc3VhbGl6YXRpb24gYmVsb3cgd2FzIHByb2R1Y2VkIGJ5IFRhYmxlYXUNCiAgIA0KICAgX1RhYmxlYXUgTGluayB0byBteSBQcm9maWxlIGZvciBpbnRlcmFjdGl2ZSBWaXN1YWxpc3Rpb246XyBodHRwczovL3B1YmxpYy50YWJsZWF1LmNvbS9hcHAvcHJvZmlsZS9lbW1hbnVlbC5tLm1hc2VydWthL3Zpei9DcmVkaXRDYXJkRnJhdWREZXRlY3Rpb25WaXN1YWxpc2F0aW9ub2ZEdW1teVZhcmlhYmxlczIvRGFzaGJvYXJkMQ0KDQpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmNhcD0iUHJvZHVjZWQgd2l0aDogVGFibGVhdSIsIG91dC53aWR0aCA9ICcxMDAlJyxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9LZXZpbiBNZW5nL09uZURyaXZlL0Rlc2t0b3AvbWFjaGluZSBsZWFybmluZyBwcm9qZWN0L0NoaXAmb25saW5lLnBuZyIpICANCg0KYGBgDQoNCiAgIF9UYWJsZWF1IExpbmsgdG8gbXkgUHJvZmlsZSBmb3IgaW50ZXJhY3RpdmUgVmlzdWFsaXp0aW9uOl8gaHR0cHM6Ly9wdWJsaWMudGFibGVhdS5jb20vYXBwL3Byb2ZpbGUvZW1tYW51ZWwubS5tYXNlcnVrYS92aXovQ3JlZGl0Q2FyZEZyYXVkRGV0ZWN0aW9uVmlzdWFsaXNhdGlvbm9mRHVtbXlWYXJpYWJsZXMxL0Rhc2hib2FyZDINCg0KYGBge3IsIGVjaG89RkFMU0UsIGZpZy5jYXA9IlByb2R1Y2VkIHdpdGg6IFRhYmxlYXUiLCBvdXQud2lkdGggPSAnMTAwJScsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiQzovVXNlcnMvS2V2aW4gTWVuZy9PbmVEcml2ZS9EZXNrdG9wL21hY2hpbmUgbGVhcm5pbmcgcHJvamVjdC9waW4mcmV0YWlsZXIucG5nIikgIA0KDQpgYGANCg0KDQoNCg0KDQoNCg0K