General Instructions

Aims of the Lab

All the previous labs introduce you to R and how preprocessing stage of a data mining application works. In this lab you will learn and practice how to evaluate a model for a given problem. In particular we will cover the following objectives:

Preliminaries

spamCols <- c('word.freq.make', 'word.freq.address', 'word.freq.all',
   'word.freq.3d', 'word.freq.our', 'word.freq.over', 'word.freq.remove',
   'word.freq.internet', 'word.freq.order', 'word.freq.mail',
   'word.freq.receive', 'word.freq.will', 'word.freq.people',
   'word.freq.report', 'word.freq.addresses', 'word.freq.free',
   'word.freq.business', 'word.freq.email', 'word.freq.you',
   'word.freq.credit', 'word.freq.your', 'word.freq.font',
   'word.freq.000', 'word.freq.money', 'word.freq.hp', 'word.freq.hpl',
   'word.freq.george', 'word.freq.650', 'word.freq.lab',
   'word.freq.labs', 'word.freq.telnet', 'word.freq.857',
   'word.freq.data', 'word.freq.415', 'word.freq.85',
   'word.freq.technology', 'word.freq.1999', 'word.freq.parts',
   'word.freq.pm', 'word.freq.direct', 'word.freq.cs',
   'word.freq.meeting', 'word.freq.original', 'word.freq.project',
   'word.freq.re', 'word.freq.edu', 'word.freq.table',
   'word.freq.conference', 'char.freq.semi', 'char.freq.lparen',
   'char.freq.lbrack', 'char.freq.bang', 'char.freq.dollar',
   'char.freq.hash', 'capital.run.length.average',
   'capital.run.length.longest', 'capital.run.length.total',
   'spam')

The following code uses Unform distribution to assing a number to between 0-100 to the rgroup variable.

set.seed(2350290)
spamD$rgroup <- floor(100*runif(dim(spamD)[[1]]))

Now you have training and testing data for modelling. Before going into modelling, we will learn to implement functions according to evaluate a model. One way of evaluating accuracy of a classification problem (where we have labelled data of the final outcome) is to use a confusion matrix. A confusion matrix comapres the predicted values with the observed values.

obs<-c('spam','non-spam','non-spam','spam','non-spam','non-spam','non-spam','non-spam','non-spam','spam')
pred<-c(0.3,0.2,0.1,0.8,0.1,0.1,0.4,0.2,0.3,0.2)
threshold<-0.5
confdata<-c(obs,pred)
validateconf<-c('TP'=1,'TN'=7,'FP'=0,'FN'=2)

Mapping business problem to machine learning tasks

5.2 Evaluating models

It woul be easier to interprete the results if we know how many emails classified as spam are actually spam out the all spam labels. Such evaluation messures give more insight about the model. Read this wiki (https://en.wikipedia.org/wiki/Precision_and_recall) about precision, recall and accuracy.

Although labelling model (e.gl ‘spam’ or ‘non-spam’) can be evaluated using accuracy measures, the models that provide a score can not be just count and calculate the confusion matrix. Hence we need other measures such as root-mean-square-error or absolute error.

Culstering models do not use labelled data. Instead, often they use some distance information for the calculations.

LS0tDQp0aXRsZTogIkNJVFMgNDAwOSBMYWIgNSAtIENob29zaW5nIGFuZCBFdmFsdWF0aW5nIE1vZGVscyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjIyBHZW5lcmFsIEluc3RydWN0aW9ucw0KKiBZb3VyIGxhYnNoZWV0cyB3aWxsIGJlIHN0cnVjdHVyZWQgd2l0aCBjb21wbGVtZW50b3J5IGluZm9ybWF0aW9uLiBUaGUgbGFicyB3aWxsIGNsb3NlbHkgZm9sbG93IHRoZSBzdHJ1Y3R1cmUgb2YgIlByYWN0aWNhbCBEYXRhIFNjaWVuY2Ugd2l0aCBSIiBib29rIGJ5IE5pbmEgWnVtZWwgYW5kIEpvaG4gTW91bnQgDQoqIEZyb20gZWFjaCBsYWIgeW91IGFyZSBleHBlY3RlZCB0byBhbnN3ZXIgYWxsIHRoZSBxdWVzdGlvbnMgcHJlc2VudGVkIHdpdGggYSBxdWVzdGlvbiBudW1iZXIuIA0KDQojIyMgQWltcyBvZiB0aGUgTGFiDQpBbGwgdGhlIHByZXZpb3VzIGxhYnMgaW50cm9kdWNlIHlvdSB0byBSIGFuZCBob3cgcHJlcHJvY2Vzc2luZyBzdGFnZSBvZiBhIGRhdGEgbWluaW5nIGFwcGxpY2F0aW9uIHdvcmtzLiBJbiB0aGlzIGxhYiB5b3Ugd2lsbCBsZWFybiBhbmQgcHJhY3RpY2UgaG93IHRvIGV2YWx1YXRlIGEgbW9kZWwgZm9yIGEgZ2l2ZW4gcHJvYmxlbS4gSW4gcGFydGljdWxhcg0Kd2Ugd2lsbCBjb3ZlciB0aGUgZm9sbG93aW5nIG9iamVjdGl2ZXM6DQoNCiogV3JpdGluZyBmdW5jdGlvbnMgDQoqIFNwbGl0aW5nIGRhdGEgZnJvbSB0cmFpbmluZyBhbmQgZXZhbHVhdGluZyBtb2RlbHMNCiogRXZhbHVhdGluZyBtb2RlbCBxdWFsaXR5DQoNCg0KDQoNCiMjIyMgV2Ugd2lsbCB1c2UgdGhlIGRhdGFzZXQgYXQgKGh0dHA6Ly9hcmNoaXZlLmljcy51Y2kuZWR1L21sL21hY2hpbmUtbGVhcm5pbmctZGF0YWJhc2VzL3NwYW1iYXNlL3NwYW1iYXNlLmRhdGEpLiANCg0KIyBQcmVsaW1pbmFyaWVzDQoqICoqUTEqKiBMb2FkIHRoZSBhYm92ZSBkYXRhc2V0IGludG8gYXZhcmlhYmxlIG5hbWVkICdzcGFtRCcgdXNpbmcgcmVhZC50YWJsZSgpIGZ1bmN0aW9uLiBUaGUgZGF0YSBpcyBjb21tYSBzZXBhcmF0ZWQgYW5kIHRoZXJlIGlzIG5vIGhlYWRlci4gQ2hhbmdlIHRoZSBjb2x1bW4gbmFtZXMgb2YgdGhlIGRhdGEgdXNpbmcgc3BhbUNvbHMgdmVjdG9yLiBOb3RlOiBmb3IgdGhpcyBsYWIsIGxhYjUtZXguUiBpcyBub3QgZ2l2ZW4uIFNvIHlvdSBoYXZlIHRvIGNyZWF0ZSBhIG5ldyBSIHNjcmlwdCB0byBkbyB0aGlzIGxhYi4NCg0KKiAqKlEyKiogJ3NwYW0nIGNvbHVtbiBsYWJlbHMgd2hldGhlciB0aGUgZW1haWwgaXMgc3BhbSBvciBub3QuIEhvd2V2ZXIsIHRoaXMgaXMgZW5jb2RlZCBhcyBhIHNjb3JlIChlLmcgMC43KS4gQ2hhbmdlIHRoZSB2YWx1ZXMgaW4gdGhlIHNwYW0gY29sdW1uIHRvIGZhY3RvcnMvdGV4dCAnc3BhbScgb3IgJ25vbi1zcGFtJyB1c2luZyAwLjUgdGhyZXNob2xkLiAgRS5nLiBpZiB0aGUgZWFybGllciBvcmlnaW5hbCBkYXRhc2V0IGhhcyAwLjQgdmFsdWUgZm9yIGEgcmVjb3JkIGluIHRoZSBzcGFtIGNvbHVtbiwgdGhlbiB0aGUgbmV3IHZhbHVlIHNob3VsZCBiZSAnbm9uLXNwYW0nDQoNCg0KDQpgYGB7cn0NCnNwYW1Db2xzIDwtIGMoJ3dvcmQuZnJlcS5tYWtlJywgJ3dvcmQuZnJlcS5hZGRyZXNzJywgJ3dvcmQuZnJlcS5hbGwnLA0KICAgJ3dvcmQuZnJlcS4zZCcsICd3b3JkLmZyZXEub3VyJywgJ3dvcmQuZnJlcS5vdmVyJywgJ3dvcmQuZnJlcS5yZW1vdmUnLA0KICAgJ3dvcmQuZnJlcS5pbnRlcm5ldCcsICd3b3JkLmZyZXEub3JkZXInLCAnd29yZC5mcmVxLm1haWwnLA0KICAgJ3dvcmQuZnJlcS5yZWNlaXZlJywgJ3dvcmQuZnJlcS53aWxsJywgJ3dvcmQuZnJlcS5wZW9wbGUnLA0KICAgJ3dvcmQuZnJlcS5yZXBvcnQnLCAnd29yZC5mcmVxLmFkZHJlc3NlcycsICd3b3JkLmZyZXEuZnJlZScsDQogICAnd29yZC5mcmVxLmJ1c2luZXNzJywgJ3dvcmQuZnJlcS5lbWFpbCcsICd3b3JkLmZyZXEueW91JywNCiAgICd3b3JkLmZyZXEuY3JlZGl0JywgJ3dvcmQuZnJlcS55b3VyJywgJ3dvcmQuZnJlcS5mb250JywNCiAgICd3b3JkLmZyZXEuMDAwJywgJ3dvcmQuZnJlcS5tb25leScsICd3b3JkLmZyZXEuaHAnLCAnd29yZC5mcmVxLmhwbCcsDQogICAnd29yZC5mcmVxLmdlb3JnZScsICd3b3JkLmZyZXEuNjUwJywgJ3dvcmQuZnJlcS5sYWInLA0KICAgJ3dvcmQuZnJlcS5sYWJzJywgJ3dvcmQuZnJlcS50ZWxuZXQnLCAnd29yZC5mcmVxLjg1NycsDQogICAnd29yZC5mcmVxLmRhdGEnLCAnd29yZC5mcmVxLjQxNScsICd3b3JkLmZyZXEuODUnLA0KICAgJ3dvcmQuZnJlcS50ZWNobm9sb2d5JywgJ3dvcmQuZnJlcS4xOTk5JywgJ3dvcmQuZnJlcS5wYXJ0cycsDQogICAnd29yZC5mcmVxLnBtJywgJ3dvcmQuZnJlcS5kaXJlY3QnLCAnd29yZC5mcmVxLmNzJywNCiAgICd3b3JkLmZyZXEubWVldGluZycsICd3b3JkLmZyZXEub3JpZ2luYWwnLCAnd29yZC5mcmVxLnByb2plY3QnLA0KICAgJ3dvcmQuZnJlcS5yZScsICd3b3JkLmZyZXEuZWR1JywgJ3dvcmQuZnJlcS50YWJsZScsDQogICAnd29yZC5mcmVxLmNvbmZlcmVuY2UnLCAnY2hhci5mcmVxLnNlbWknLCAnY2hhci5mcmVxLmxwYXJlbicsDQogICAnY2hhci5mcmVxLmxicmFjaycsICdjaGFyLmZyZXEuYmFuZycsICdjaGFyLmZyZXEuZG9sbGFyJywNCiAgICdjaGFyLmZyZXEuaGFzaCcsICdjYXBpdGFsLnJ1bi5sZW5ndGguYXZlcmFnZScsDQogICAnY2FwaXRhbC5ydW4ubGVuZ3RoLmxvbmdlc3QnLCAnY2FwaXRhbC5ydW4ubGVuZ3RoLnRvdGFsJywNCiAgICdzcGFtJykNCg0KYGBgDQoNClRoZSBmb2xsb3dpbmcgY29kZSB1c2VzIFVuZm9ybSBkaXN0cmlidXRpb24gdG8gYXNzaW5nIGEgbnVtYmVyIHRvIGJldHdlZW4gMC0xMDAgdG8gdGhlIHJncm91cCB2YXJpYWJsZS4gDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMjM1MDI5MCkNCnNwYW1EJHJncm91cCA8LSBmbG9vcigxMDAqcnVuaWYoZGltKHNwYW1EKVtbMV1dKSkNCg0KYGBgDQoNCg0KDQoqICoqUTMqKiBSZWFkIHRoZSBkb2N1bWVudGF0aW9uIG9mIHRoZSBzZXQuc2VlZCgpIGZ1bmN0aW9uLiBXaGF0IGlzIHRoZSB1c2Ugb2YgdGhlIG51bWJlcigyMzUwMjkwKSBwYXNzZWQgdG8gdGhlIGZ1bmN0aW9uLiBXaHkgdGhlIHNlZWQgZnVuY3Rpb24gaXMgdXNlZCBiZWZvcmUgY3JlYXRpbmcgdGhlIHJncm91cCB2YXJpYWJsZS4NCg0KKiAqKlE0KiogWW91IG5lZWQgdG8gc3BsaXQgdGhlIHNwYW1EIGVtYWlscyBpbnRvIHR3byBzdWJzZXRzOmEgdHJhaW5pbmcgc2V0IChzcGFtVHJhaW4pIGFuZCBhIHRlc3Rpbmcgc2V0IChzcGFtVGVzdCkuIFRoZSByZ3JvdXAgdmFsdWVzIGxlc3MgdGhhbiAxMCBhcmUgdXNlZCBmb3IgdGVzdGluZyBhbmQgcmVzdCBhcmUgdXNlZCBmb3IgdHJhaW5pbmcuIA0KDQpOb3cgeW91IGhhdmUgdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YSBmb3IgbW9kZWxsaW5nLiBCZWZvcmUgZ29pbmcgaW50byBtb2RlbGxpbmcsIHdlIHdpbGwgbGVhcm4gdG8gaW1wbGVtZW50IGZ1bmN0aW9ucyBhY2NvcmRpbmcgdG8gZXZhbHVhdGUgYSBtb2RlbC4gT25lIHdheSBvZiBldmFsdWF0aW5nIGFjY3VyYWN5IG9mIGEgY2xhc3NpZmljYXRpb24gcHJvYmxlbSAod2hlcmUgd2UgaGF2ZSBsYWJlbGxlZCBkYXRhIG9mIHRoZSBmaW5hbCBvdXRjb21lKSBpcyB0byB1c2UgYSBjb25mdXNpb24gbWF0cml4LiBBIGNvbmZ1c2lvbiBtYXRyaXggY29tYXByZXMgdGhlIHByZWRpY3RlZCB2YWx1ZXMgd2l0aCB0aGUgb2JzZXJ2ZWQgdmFsdWVzLiAgDQoNCiogKipRNSoqIFJlYWQgdGhlIGxpbmsoJ2h0dHA6Ly93d3cuc3RhdG1ldGhvZHMubmV0L21hbmFnZW1lbnQvdXNlcmZ1bmN0aW9ucy5odG1sJykgYW5kIGhvdyB0aGUgZnVuY3Rpb25zIGFyZSBpbXBsZW1lbnRlZCBpbiBSLiBOb3cgd3JpdGUgYSBmdW5jdGlvbiBuYW1lZCAnY3JlYXRlQ29uZk1hdHJpeChvYnMscHJlZCx0aHJlc2hvbGQpJyB3aGVyZSB0aGUgJ29icycgYW5kICdwcmVkJyBhcmUgdmVjdG9ycyBvZiBlcXVhbCBsZW5ndGguIHRocmVzaG9sZCBpcyBhIHZhbHVlIGluIHRoZSByYW5nZSBbMCwxXS4gV2l0aGluIHRoZSBmdW5jdGlvbiB5b3Ugc2hvdWxkIGltcGxlbWVudCB0aGUgZm9sbG93aW5nIHN0ZXBzLg0KDQogICAgNS4xIENvbXBhcmUgdGhlIHByZWQgdmFsdWVzIHdpdGggdGhlIHRocmVzaG9sZC4gVGhpcyByZXN1bHRzIGluIGEgdmVjdG9yIG9mIHRydWUgYW5kIGZhbHNlIHZhbHVlcy4gIFRydWUgbWVhbnMgd2UgcHJlZGljdGVkIHRoZSBlbWFpbCBhcyBhIHNwYW0gZW1haWwgYW5kIGZhbHNlIG1lYW5zIHRoZSBlbWFpbCBpcyBub24tc3BhbS4NCiAgICANCiAgICA1LjIgTm93IGNvdW50IGhvdyBtYW55IHJvd3MgcHJlZGljdGVkIGFzIHNwYW0gYXJlIGFjdHVhbGx5IHNwYW0gZW1haWxzLiBUaGlzIGNhbiBiZSBkb25lIGJ5IGNvbXBhcmluZyB0aGUgcmVzdWx0YW50IHZlY3RvciBpbiA1LjEgd2l0aCB0aGUgb2JzIHZlY3RvciAoYXNzdW1lIHlvdSBnZXQgb2JzIGFzIHNwYW0vbm9uLXNwYW0pLiBJbiBvdGhlciB3b3JkcyB5b3UgaGF2ZSBjb3VudGVkIHRoZSBUcnVlIFBvc2l0aXZlcyAoVFApIG9mIHRoZSBjb25mdXNpb24gbWF0cml4IG9mIHRoZSBkYXRhLg0KICAgIA0KICAgIDUuMyBBcyB5b3UgZGlkIGluIDUuMywgY291bnQgaG93IG1hbnkgVHJ1ZSBOZWdhdGl2ZXMsIEZhbHNlIFBvc2l0aXZlcyBhbmQgRmFsc2UgTmVnYXRpdmVzIGFyZSBpbiBvdXIgcHJlZGljdGlvbi4gDQogICAgDQogICAgNS40IFJldHVyZW4gdGhlIHJlc3VsdHMgYSB2ZWN0b3Igb2YgYyhUUCxUTixGUCxGTikgZm91ciB2YWx1ZXMNCiAgICANCiAgICAoSGludDogeW91IGNhbiBwZXJmb3JtIHRoZSBzdGVwcyA1LjEgdG8gNS40IGluIHNpbmdsZSBzdGVwIHVzaW5nIHRhYmxlKCkgY29tbWFuZC4pDQogICAgDQogICAgDQoqICoqUTYqKiBOb3cgYXBwbHkgdGhlIGNyZWF0ZUNvbmZNYXRyaXggb24gY29uZmRhdGEgYW5kIGNoZWNrIHdoZXRoZXIgdGhlIGltcGxtZW5ldGF0aW9uIGlzIGNvcnJlY3QgdXNpbmcgdmFsaWRhdGVjb25mLg0KYGBge3J9DQpvYnM8LWMoJ3NwYW0nLCdub24tc3BhbScsJ25vbi1zcGFtJywnc3BhbScsJ25vbi1zcGFtJywnbm9uLXNwYW0nLCdub24tc3BhbScsJ25vbi1zcGFtJywnbm9uLXNwYW0nLCdzcGFtJykNCnByZWQ8LWMoMC4zLDAuMiwwLjEsMC44LDAuMSwwLjEsMC40LDAuMiwwLjMsMC4yKQ0KdGhyZXNob2xkPC0wLjUNCmNvbmZkYXRhPC1jKG9icyxwcmVkKQ0KdmFsaWRhdGVjb25mPC1jKCdUUCc9MSwnVE4nPTcsJ0ZQJz0wLCdGTic9MikNCmBgYA0KDQoNCg0KDQojIE1hcHBpbmcgYnVzaW5lc3MgcHJvYmxlbSB0byBtYWNoaW5lIGxlYXJuaW5nIHRhc2tzDQoqICoqUTcqKiBDcmVhdGUgYSBzcGFtIGNsYXNzaWZpY2F0aW9uIG1vZGVsIGNhbGxlZCAnc3BhbU1vZGVsJyB1c2luZyB0aGUgdHJhaW5kaW5nIGRhdGEgKHNwYW1UcmFpbikuIFRvIGRvIHRoaXMNCg0KICAgIDcuMSBTZXBhcmF0ZSBhbGwgdGhlIHZhcmlhYmxlcyAoY29sdW1ucyBvZiBzcGFtRCkgZXhjZXB0IHNwYW0gYW5kIHJncm91cC4gSGludDogVXNlIHRoZSBzZXRkaWZmIG1ldGhvZC4gU2F2ZSB0aGUgc2VsZWN0ZWQgZGF0YSBhcyBzcGFtVmFycy4NCiAgICAgICAgDQogICAgNy4yIFVzZSBnZW5lcmFsaXNlZCBsaW5lYXIgbW9kZWwgKGdsbSgpKSB0byBjcmVhdGUgYSBtb2RlbCAobmFtZSBpdCBzcGFtTW9kZWwgKSBmcm9tIHRoZSBzcGFtVmFycy4gZ2xtKCkgbmVlZHMgYSBmb3JtdWxhIHRvIHNwZWNpZnkgdGhlIHZhcmlhYmxlcyBhbmQgdGhlIGxpbmtpbmcgZnVuY3Rpb24uIA0KICAgICAgICAgICAgDQogICAgICAgIDcuMi4xIFVzZSBhcy5Gb3JtdWxhKCkgdG8gc3BlY2lmeSB0aGUgdmFyaWFibGVzIChzcGFtVmFycykuDQogICAgICAgICAgICANCiAgICAgICAgNy4yLjIgVXNlIHRoZSBmYW1pbHkvbGlua2luZyBmdW5jdGlvbiBhcyBiaW5vbWlhbChsaW5raW5nPSdsb2dpdCcpLiANCiAgICAgICAgICAgIA0KICAgIDcuMyBBcHBseSB0aGUgc3BhbU1vZGVsIG9uIHRoZSBzcGFtVHJhaW4gdG8gZ2V0IHByZWRpY3Rpb25zIG9uIHRoZSB0cmFpbmluZyBkYXRhLiBZb3UgY2FuIHVzZSBwcmVkaWN0KCkgZnVuY3Rpb24uIFNhdmUgdGhlIHJlc3VsdHMgdG8gc3BhbVRyYWluJHByZWQNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoqICoqUTgqKiBBcHBseSB0aGUgc3BhbU1vZGVsIG9uIHRoZSB0ZXN0aW5nIGRhdGEgKHNwYW1UZXN0KSBhcyB5b3UgZGlkIGluIDcuMy4gDQoNCiAgICAgICAgDQoNCiMgNS4yIEV2YWx1YXRpbmcgbW9kZWxzDQoNCg0KKiAqKlE5KiogQ2FsY3VsYXRlIHRoZSBjb25mdXNpb24gbWF0cml4IG9mIHRoZSB0ZXN0IGRhdGEgdXNpbmcgY3JlYXRlQ29uZk1hdHJpeCgpIGZ1bmN0aW9uIHlvdSBpbXBsZW1lbnRlZCBpbiBRNi4NCg0KSXQgd291bCBiZSBlYXNpZXIgdG8gaW50ZXJwcmV0ZSB0aGUgcmVzdWx0cyBpZiB3ZSBrbm93IGhvdyBtYW55IGVtYWlscyBjbGFzc2lmaWVkIGFzIHNwYW0gYXJlIGFjdHVhbGx5IHNwYW0gb3V0IHRoZSBhbGwgc3BhbSBsYWJlbHMuIFN1Y2ggZXZhbHVhdGlvbiBtZXNzdXJlcyBnaXZlIG1vcmUgaW5zaWdodCBhYm91dCB0aGUgbW9kZWwuIFJlYWQgdGhpcyB3aWtpIChodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9QcmVjaXNpb25fYW5kX3JlY2FsbCkgYWJvdXQgcHJlY2lzaW9uLCByZWNhbGwgYW5kIGFjY3VyYWN5Lg0KDQoqICoqUTEwKiogSW1wbGVtZW50IGZ1bmN0aW9ucyB0aGF0IGNhbGN1bGF0ZSBhY2N1cmFjeSxwcmVjaXNpb24gYW5kIHJlY2FsbC4gWW91IGNhbiB1c2UgdGhlIHNhbWUgcGFyYW1ldGVyICdvYnMnLCdwcmVkJyBhbmQgJ3RocmVzaG9sZCcgYXMgaW5wdXQgcGFyYW1ldGVycyBmb3IgdGhlc2UgZnVuY3Rpb25zLiANCg0KKiAqKlExMSoqIENhbGN1bGF0ZSBhY2N1cmFjeSxwcmVjaXNpb24gYW5kIHJlY2FsbCBvZiB0aGUgcHJlZGljdGlvbnMgb2YgdGhlIHNwYW1UZXN0IGRhdGEgdXNpbmcgdGhlIGZ1bmN0aW9ucyB5b3UgaW1wbGVtZW50IGluIFExMC4gSW50ZXJwcmV0IGVhY2ggcmVzdWx0IGluIHRlcm1zIG9mIHRoZSANCg0KDQoNCkFsdGhvdWdoIGxhYmVsbGluZyBtb2RlbCAoZS5nbCAnc3BhbScgb3IgJ25vbi1zcGFtJykgY2FuIGJlIGV2YWx1YXRlZCB1c2luZyBhY2N1cmFjeSBtZWFzdXJlcywgdGhlIG1vZGVscyB0aGF0IHByb3ZpZGUgYSBzY29yZSBjYW4gbm90IGJlIGp1c3QgY291bnQgYW5kIGNhbGN1bGF0ZSB0aGUgY29uZnVzaW9uIG1hdHJpeC4gSGVuY2Ugd2UgbmVlZCBvdGhlciBtZWFzdXJlcyBzdWNoIGFzIHJvb3QtbWVhbi1zcXVhcmUtZXJyb3Igb3IgYWJzb2x1dGUgZXJyb3IuDQoNCkN1bHN0ZXJpbmcgbW9kZWxzIGRvIG5vdCB1c2UgbGFiZWxsZWQgZGF0YS4gSW5zdGVhZCwgb2Z0ZW4gdGhleSB1c2Ugc29tZSBkaXN0YW5jZSBpbmZvcm1hdGlvbiBmb3IgdGhlIGNhbGN1bGF0aW9ucy4NCg0KKiAqKlExMioqIENyZWF0ZSBhIDEwMCoyIG1hdHJpeCAoZCkgd2hlcmUgZWFjaCBjb2x1bW4gaXMgY3JlYXRlZCBmcm9tIGEgdW5pZm9ybSBkaXN0cmlidXRpb24uIE5vdGU6IHlvdSBzaG91bGQgYmUgYWJsZSB0byByZXByb2R1Y2UgZCBleGFjdGx5IHRoZSBzYW1lIGVhY2ggdGltZSB5b3UgcnVuIHRoZSBwcm9ncmFtLg0KDQoqICoqUTEzKiogQ2x1c3RlciB0aGUgbWF0cml4IGQgdXNpbmcgay1tZWFucyBhbGdvcml0aG0uIChVc2Uga21lYW5zKCkgZnVuY3Rpb24pLiBZb3UgY2FuIHNwZWNpZnkgdGhlIG51bWJlciBvZiBjZW50cmVzIGFzIDUuIFNhdmUgdGhlIHJlc3VsdHMgKHh4XCRjbHVzdGVyKSB0byBkJGNsdXMuDQoNCiogKipRMTQqKiBWaXN1YWxpc2UgdGhlIGNsdXN0ZXJpbmcgcmVzdWx0cyBhbmQgc2VlIGhvdyB0aGUgY3Vsc3RlcnMgYXJlIHNlcGFyYXRlZCBhbmQgaG93IHRoZWlyIHNpemVzIHZhcnkuIA0KDQoqICoqUTE1KiogQ2FsY3VsYXRlIHRoZSBkaXN0YW5jZXMgYmV0d2VlbiBldmVyeSBwYWlyIG9mIGNlbnRyZXMgb2YgZC4NCg0KDQoNCg0KDQoNCg0KDQoNCg0K