Using Datasets Available Here: https://www.kaggle.com/dansbecker/nba-shot-logs (shot_log.csv)

And Here: https://www.basketball-reference.com/leagues/NBA_2015_totals.html (BBREF_players.csv)

This project attempts to identify patterns and create a framework for evaluating the performance value of basketball players by focusing on their scoring efficiency (ability to generate the most points in the least time).

Load in all required packages

This dataset was posted on Kaggle.com, and contains a record of every shot by every player in every game of the 2014-15 season (as far as I can tell, there was too much data to check). This section simply loads the data and does some basic cleaning. The dataset included the point value of shots that were missed as well, so in cleaning the data I tested the implications of both penalizing missed shots (making them behave as the negative of their point value), and nuetralizing missed shots (making all missed point values equal to zero). For the purposes of this project it makes more sense to treat missed shots as zero point values, because the implications of misses to player performance can already be accounted for in the ratio of points per shot.

The data on in-game performance and shooting tendencies contains a lot of very specific information on player performance that could be used to get a high-resolution look at exactly how individuals performed in different situations. Instead of looking for a fine grained means of quantifying player performance in different situations, this analysis will pull out aggregate results to create a generalized means of ranking players on their ability to generate points, given the limited amount of time they have to handle the ball. Since Basketball games are short and high scoring, there is reason to believe that the best (offensive) players should have the highest ratio of points per shot to minutes of ball time. This study will look at the implications of using only this low resolution artificial ranking system, and maybe compare it to ranking systems that account for more features. As can be seen from the ggplot2 graphic, more ball time and low point per shot ratio result in a lower ranking value. Since taking more shots requires more ball-time, the players that tend to have the most ball time and publicity arent ranked very highly with respect to this metric (Kobe Bryant, and Lebron James are pretty low). The plotly graphic is far more useful and interactive in showing the same information, but unfortunately it doesn’t live in the notebook.

In order to get a few more metrics on player performance, the first dataset was joined with data from basketball-reference.com. This dataset contained player specific information on seasonal performance, including position, age, games played etc., many of which were completely unattainable from the dataset on in-game shooting. Using both datasets allows for a fuller picture of the individual player’s performance, and offers a means to check the implications of the rankings and the consistency of the data.

This tangent looks at how player performance stacks up when grouping by position. This will show if the ranking system is dramatically biased towards the skills required for any given position. Looking at the ggplot graphic generated by averaging all the metrics after aggregating by position, it is clear that centers are ranked much higher than other positions when looking at how often they score given the amount of time they handle the ball. The surprise is that the centers had a much higher points-per-shot ratio but also less ball time, which contributed to the higher average score and lower ranking.

This ggplot graphic shows how this ranking system plays out with respect to a player’s point total, accounting for position and ball time as well. As one would expect players with high point totals have the highest rankings, and this generally corresponds to more ball time. Looking at the graphic it is also clear that different positions have defined clustering within the data, something that could be explored further.

The positional rankings exist in clusters, which means that the rankings for players of the same position are grouped around an expected value (average) with some standard deviation within the grouping. By modeling the probabilities of players in each position having a certain ranking as a normal distribution, a set of boundaries for identifying a player’s position by their ranking within this system begins to appear. For example, the most confident estimate that a player with a certain ranking plays a certain position will map directly to the positional distribution with the highest value for that ranking (e.g. if a player’s ranking is less than 1.00, then ‘center’ would be the best estimate for their position.)

LS0tDQp0aXRsZTogIk5CQSBQbGF5ZXIgUGVyZm9ybWFuY2UgMjAxNC0yMDE1Ig0KYXV0aG9yOiAicGxvdGx5Ig0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KI1VzaW5nIERhdGFzZXRzIEF2YWlsYWJsZSBIZXJlOiBodHRwczovL3d3dy5rYWdnbGUuY29tL2RhbnNiZWNrZXIvbmJhLXNob3QtbG9ncyAoc2hvdF9sb2cuY3N2KQ0KI0FuZCBIZXJlOiBodHRwczovL3d3dy5iYXNrZXRiYWxsLXJlZmVyZW5jZS5jb20vbGVhZ3Vlcy9OQkFfMjAxNV90b3RhbHMuaHRtbCAoQkJSRUZfcGxheWVycy5jc3YpDQoNClRoaXMgcHJvamVjdCBhdHRlbXB0cyB0byBpZGVudGlmeSBwYXR0ZXJucyBhbmQgY3JlYXRlIGEgZnJhbWV3b3JrIGZvciBldmFsdWF0aW5nIHRoZSBwZXJmb3JtYW5jZSB2YWx1ZSBvZiBiYXNrZXRiYWxsIHBsYXllcnMgYnkgZm9jdXNpbmcgb24gdGhlaXIgc2NvcmluZyBlZmZpY2llbmN5IChhYmlsaXR5IHRvIGdlbmVyYXRlIHRoZSBtb3N0IHBvaW50cyBpbiB0aGUgbGVhc3QgdGltZSkuDQoNCkxvYWQgaW4gYWxsIHJlcXVpcmVkIHBhY2thZ2VzDQpgYGB7ciBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKA0KICB7DQogICAgcGFja2FnZV9saXN0IDwtIGMoJ3Bsb3RseScsICdzdHJpbmdyJywgJ2RwbHlyJywgJ3NxbGRmJywgJ21hZ3JpdHRyJywnUkNvbG9yQnJld2VyJywnd2Vic2hvdCcpDQogICAgbm9uX2luc3RhbGxlZCA8LSBwYWNrYWdlX2xpc3RbIShwYWNrYWdlX2xpc3QgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKVssIlBhY2thZ2UiXSldDQogICAgaWYobGVuZ3RoKG5vbl9pbnN0YWxsZWQpKSBpbnN0YWxsLnBhY2thZ2VzKG5vbl9pbnN0YWxsZWQpDQogICAgbGlicmFyeSgncGxvdGx5JykNCiAgICBsaWJyYXJ5KCdSQ29sb3JCcmV3ZXInKQ0KICAgIGxpYnJhcnkoJ2RwbHlyJykNCiAgICBsaWJyYXJ5KCdzdHJpbmdyJykNCiAgICBsaWJyYXJ5KCdzcWxkZicpDQogICAgbGlicmFyeSgnbWFncml0dHInKQ0KICAgIGxpYnJhcnkoJ3dlYnNob3QnKQ0KICB9DQopDQpgYGANCg0KDQpUaGlzIGRhdGFzZXQgd2FzIHBvc3RlZCBvbiBLYWdnbGUuY29tLCBhbmQgY29udGFpbnMgYSByZWNvcmQgb2YgZXZlcnkgc2hvdCBieSBldmVyeSBwbGF5ZXIgaW4gZXZlcnkgZ2FtZSBvZiB0aGUgMjAxNC0xNSBzZWFzb24gKGFzIGZhciBhcyBJIGNhbiB0ZWxsLCB0aGVyZSB3YXMgdG9vIG11Y2ggZGF0YSB0byBjaGVjaykuICBUaGlzIHNlY3Rpb24gc2ltcGx5IGxvYWRzIHRoZSBkYXRhIGFuZCBkb2VzIHNvbWUgYmFzaWMgY2xlYW5pbmcuICBUaGUgZGF0YXNldCBpbmNsdWRlZCB0aGUgcG9pbnQgdmFsdWUgb2Ygc2hvdHMgdGhhdCB3ZXJlIG1pc3NlZCBhcyB3ZWxsLCBzbyBpbiBjbGVhbmluZyB0aGUgZGF0YSBJIHRlc3RlZCB0aGUgaW1wbGljYXRpb25zIG9mIGJvdGggcGVuYWxpemluZyBtaXNzZWQgc2hvdHMgKG1ha2luZyB0aGVtIGJlaGF2ZSBhcyB0aGUgbmVnYXRpdmUgb2YgdGhlaXIgcG9pbnQgdmFsdWUpLCBhbmQgbnVldHJhbGl6aW5nIG1pc3NlZCBzaG90cyAobWFraW5nIGFsbCBtaXNzZWQgcG9pbnQgdmFsdWVzIGVxdWFsIHRvIHplcm8pLiAgRm9yIHRoZSBwdXJwb3NlcyBvZiB0aGlzIHByb2plY3QgaXQgbWFrZXMgbW9yZSBzZW5zZSB0byB0cmVhdCBtaXNzZWQgc2hvdHMgYXMgemVybyBwb2ludCB2YWx1ZXMsIGJlY2F1c2UgdGhlIGltcGxpY2F0aW9ucyBvZiBtaXNzZXMgdG8gcGxheWVyIHBlcmZvcm1hbmNlIGNhbiBhbHJlYWR5IGJlIGFjY291bnRlZCBmb3IgaW4gdGhlIHJhdGlvIG9mIHBvaW50cyBwZXIgc2hvdC4NCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBlY2hvID0gRkFMU0V9DQoNCnNob3RzX0RGIDwtIGRwbHlyOjp0YmxfZGYocmVhZC5jc3YoInNob3RfbG9ncy5jc3YiKSkNCg0KI1BlcmZvcm0gQ2xlYW5pbmcNCiAgI1BlbmFsaXplIG1pc3NlZCBzaG90cz8NCiAgI3Nob3RzX0RGJFBUU19UWVBFIDwtIGlmZWxzZShzaG90c19ERiRTSE9UX1JFU1VMVCA9PSAibWFkZSIsIHNob3RzX0RGJFBUU19UWVBFLCAtc2hvdHNfREYkUFRTX1RZUEUpDQoNCg0KICAjTnVldHJhbGl6ZSBtaXNzZWQgc2hvdHMNCnNob3RzX0RGJFBUU19UWVBFIDwtIGlmZWxzZShzaG90c19ERiRTSE9UX1JFU1VMVCA9PSAibWFkZSIsIHNob3RzX0RGJFBUU19UWVBFLCAwKQ0KDQpwbGF5ZXJzIDwtIHNxbGRmKCJTRUxFQ1QgRElTVElOQ1QocGxheWVyX2lkKSBBUyBcIklEXCIsIHBsYXllcl9uYW1lIEFTIFwiUExBWUVSXCINCiAgICAgICAgICAgICAgICAgICAgICAgICAgRlJPTSBzaG90c19ERg0KICAgICAgICAgICAgICAgICAgICAgICAgICBPUkRFUiBCWSBJRCIpDQpwbGF5ZXJzDQoNCmBgYA0KDQoNCg0KVGhlIGRhdGEgb24gaW4tZ2FtZSBwZXJmb3JtYW5jZSBhbmQgc2hvb3RpbmcgdGVuZGVuY2llcyBjb250YWlucyBhIGxvdCBvZiB2ZXJ5IHNwZWNpZmljIGluZm9ybWF0aW9uIG9uIHBsYXllciBwZXJmb3JtYW5jZSB0aGF0IGNvdWxkIGJlIHVzZWQgdG8gZ2V0IGEgaGlnaC1yZXNvbHV0aW9uIGxvb2sgYXQgZXhhY3RseSBob3cgaW5kaXZpZHVhbHMgcGVyZm9ybWVkIGluIGRpZmZlcmVudCBzaXR1YXRpb25zLiAgSW5zdGVhZCBvZiBsb29raW5nIGZvciBhIGZpbmUgZ3JhaW5lZCBtZWFucyBvZiBxdWFudGlmeWluZyBwbGF5ZXIgcGVyZm9ybWFuY2UgaW4gZGlmZmVyZW50IHNpdHVhdGlvbnMsIHRoaXMgYW5hbHlzaXMgd2lsbCBwdWxsIG91dCBhZ2dyZWdhdGUgcmVzdWx0cyB0byBjcmVhdGUgYSBnZW5lcmFsaXplZCBtZWFucyBvZiByYW5raW5nIHBsYXllcnMgb24gdGhlaXIgYWJpbGl0eSB0byBnZW5lcmF0ZSBwb2ludHMsIGdpdmVuIHRoZSBsaW1pdGVkIGFtb3VudCBvZiB0aW1lIHRoZXkgaGF2ZSB0byBoYW5kbGUgdGhlIGJhbGwuICBTaW5jZSBCYXNrZXRiYWxsIGdhbWVzIGFyZSBzaG9ydCBhbmQgaGlnaCBzY29yaW5nLCB0aGVyZSBpcyByZWFzb24gdG8gYmVsaWV2ZSB0aGF0IHRoZSBiZXN0IChvZmZlbnNpdmUpIHBsYXllcnMgc2hvdWxkIGhhdmUgdGhlIGhpZ2hlc3QgcmF0aW8gb2YgcG9pbnRzIHBlciBzaG90IHRvIG1pbnV0ZXMgb2YgYmFsbCB0aW1lLiBUaGlzIHN0dWR5IHdpbGwgbG9vayBhdCB0aGUgaW1wbGljYXRpb25zIG9mIHVzaW5nIG9ubHkgdGhpcyBsb3cgcmVzb2x1dGlvbiBhcnRpZmljaWFsIHJhbmtpbmcgc3lzdGVtLCBhbmQgbWF5YmUgY29tcGFyZSBpdCB0byByYW5raW5nIHN5c3RlbXMgdGhhdCBhY2NvdW50IGZvciBtb3JlIGZlYXR1cmVzLg0KQXMgY2FuIGJlIHNlZW4gZnJvbSB0aGUgZ2dwbG90MiBncmFwaGljLCBtb3JlIGJhbGwgdGltZSBhbmQgbG93IHBvaW50IHBlciBzaG90IHJhdGlvIHJlc3VsdCBpbiBhIGxvd2VyIHJhbmtpbmcgdmFsdWUuICBTaW5jZSB0YWtpbmcgbW9yZSBzaG90cyByZXF1aXJlcyBtb3JlIGJhbGwtdGltZSwgdGhlIHBsYXllcnMgdGhhdCB0ZW5kIHRvIGhhdmUgdGhlIG1vc3QgYmFsbCB0aW1lIGFuZCBwdWJsaWNpdHkgYXJlbnQgcmFua2VkIHZlcnkgaGlnaGx5IHdpdGggcmVzcGVjdCB0byB0aGlzIG1ldHJpYyAoS29iZSBCcnlhbnQsIGFuZCBMZWJyb24gSmFtZXMgYXJlIHByZXR0eSBsb3cpLiAgVGhlIHBsb3RseSBncmFwaGljIGlzIGZhciBtb3JlIHVzZWZ1bCBhbmQgaW50ZXJhY3RpdmUgaW4gc2hvd2luZyB0aGUgc2FtZSBpbmZvcm1hdGlvbiwgYnV0IHVuZm9ydHVuYXRlbHkgaXQgZG9lc24ndCBsaXZlIGluIHRoZSBub3RlYm9vay4NCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBlY2hvID0gRkFMU0V9DQpwbGF5ZXJzX3N0YXRzX2RhdGEgPC0gc3FsZGYoIlNFTEVDVCBwbGF5ZXJzLklELCBwbGF5ZXJzLlBMQVlFUiBBUyBcIlBsYXllclwiLCANCiAgICAgICAgICAgICAgICAgICBTVU0oRFJJQkJMRVMpIEFTIFwiRHJpYmJsZXNcIiwgQ09VTlQoU0hPVF9OVU1CRVIpIEFTIFwiVG90YWxfU2hvdHNcIiwNCiAgICAgICAgICAgICAgICAgICBTVU0oUFRTX1RZUEUpIEFTIFwiUG9pbnRfVG90YWxcIiwNCiAgICAgICAgICAgICAgICAgICBTVU0oUFRTX1RZUEUpL0NPVU5UKFNIT1RfTlVNQkVSKSBBUyBcIlBvaW50c19QZXJfU2hvdFwiLA0KICAgICAgICAgICAgICAgICAgIFNVTShUT1VDSF9USU1FKSBBUyBcIkJhbGxfVGltZVwiDQogICAgICAgICAgICAgICAgICAgRlJPTSBwbGF5ZXJzIElOTkVSIEpPSU4gc2hvdHNfREYNCiAgICAgICAgICAgICAgICAgICBPTiBwbGF5ZXJzLklEID0gc2hvdHNfREYucGxheWVyX2lkDQogICAgICAgICAgICAgICAgICAgR1JPVVAgQlkgcGxheWVycy5JRA0KICAgICAgICAgICAgICAgICAgIE9SREVSIEJZIFBvaW50c19QZXJfU2hvdCBERVNDIikNCg0KDQojUmFua2luZyBGdW5jdGlvbiBGb3IgSWRlbnRpZnlpbmcgVG9wIFBsYXllciBQZXJmb3JtYW5jZQ0KcGxheWVyX3N0YXRzX3JhbmtmdW4gPC0gZnVuY3Rpb24oeCkNCnsNCiAgdmFscyA8LSBjKCkNCiAgZm9yKGkgaW4gMTpkaW0oeClbMV0pDQogIHsNCiAgICBwb3MgPC0geFtpLF0NCiAgICB2YWwgPC0gcG9zJEJhbGxfVGltZSAvIHBvcyRQb2ludF9Ub3RhbA0KICAgIHZhbHMgPC0gYyh2YWxzLCB2YWwpDQogIH0NCiAgcmV0dXJuKGRhdGEuZnJhbWUoUmFua2luZyA9IHZhbHMsIFJhbmsgPSByYW5rKHZhbHMpKSkNCn0NCg0KcmFua2luZ3MgPC0gcGxheWVyX3N0YXRzX3JhbmtmdW4ocGxheWVyc19zdGF0c19kYXRhKQ0KDQpwbGF5ZXJzX3N0YXRzX2RhdGFfcmFua3MgPC0gY2JpbmQocGxheWVyX3N0YXRzX3JhbmtmdW4ocGxheWVyc19zdGF0c19kYXRhKSwgcGxheWVyc19zdGF0c19kYXRhKQ0KDQoNCnBsYXllcnNfc3RhdHNfcGxvdF9wbG90bHkgPC0gcGxvdF9seShwbGF5ZXJzX3N0YXRzX2RhdGFfcmFua3MpICU+JQ0KICAgICAgICAgICAgICAgICBhZGRfbWFya2Vycyh4ID0gflRvdGFsX1Nob3RzLCB5ID0gflBvaW50c19QZXJfU2hvdCwgY29sb3IgPSB+UmFua2luZywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IH5CYWxsX1RpbWUsIGNvbG9ycyA9ICJTcGVjdHJhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSB+cGFzdGUoIlBsYXllcjogIiwgUGxheWVyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8L2JyPlJhbms6ICIsIFJhbmssICIsIFZhbHVlOiAiLCByb3VuZChSYW5raW5nLCBkaWdpdHMgPSAzKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPC9icj5Qb2ludHMgcGVyIFNob3Q6ICIsIHJvdW5kKFBvaW50c19QZXJfU2hvdCwgZGlnaXRzID0gMyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjwvYnI+QmFsbCBUaW1lOiAiLCByb3VuZChCYWxsX1RpbWUsIGRpZ2l0cyA9IDMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8L2JyPkRyaWJibGVzOiAiLCBEcmliYmxlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPC9icj5Ub3RhbCBQb2ludHM6ICIsIFBvaW50X1RvdGFsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8L2JyPlRvdGFsIFNob3RzOiAiLCBUb3RhbF9TaG90cykpICU+JQ0KICAgICAgICAgICAgICAgICBsYXlvdXQodGl0bGUgPSBwYXN0ZTAoIlBsYXllciBSYW5raW5ncyIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlRvdGFsIFNob3RzIiksDQogICAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiUG9pbnRzIFBlciBTaG90IikpDQoNCg0KcGxheWVyc19zdGF0c19wbG90X2dnIDwtIGdncGxvdCgpICsgDQogICAgICAgICAgICAgICAgICAgICAgZ2VvbV9wb2ludChkYXRhID0gcGxheWVyc19zdGF0c19kYXRhX3JhbmtzLCBhZXMoeCA9IFRvdGFsX1Nob3RzLCB5ID0gUG9pbnRzX1Blcl9TaG90LCBjb2xvdXIgPSBSYW5raW5nLCBzaXplID0gQmFsbF9UaW1lKSkNCiAgICAgICAgICAgICAgICAgICAgICANCg0KI2dncGxvdDIgR3JhcGhpYw0KcGxheWVyc19zdGF0c19wbG90X2dnDQoNCiNQbG90bHkgR3JhcGhpYw0KI3BsYXllcnNfc3RhdHNfcGxvdF9wbG90bHkNCmBgYA0KDQoNCg0KSW4gb3JkZXIgdG8gZ2V0IGEgZmV3IG1vcmUgbWV0cmljcyBvbiBwbGF5ZXIgcGVyZm9ybWFuY2UsIHRoZSBmaXJzdCBkYXRhc2V0IHdhcyBqb2luZWQgd2l0aCBkYXRhIGZyb20gYmFza2V0YmFsbC1yZWZlcmVuY2UuY29tLiAgVGhpcyBkYXRhc2V0IGNvbnRhaW5lZCBwbGF5ZXIgc3BlY2lmaWMgaW5mb3JtYXRpb24gb24gc2Vhc29uYWwgcGVyZm9ybWFuY2UsIGluY2x1ZGluZyBwb3NpdGlvbiwgYWdlLCBnYW1lcyBwbGF5ZWQgZXRjLiwgbWFueSBvZiB3aGljaCB3ZXJlIGNvbXBsZXRlbHkgdW5hdHRhaW5hYmxlIGZyb20gdGhlIGRhdGFzZXQgb24gaW4tZ2FtZSBzaG9vdGluZy4gVXNpbmcgYm90aCBkYXRhc2V0cyBhbGxvd3MgZm9yIGEgZnVsbGVyIHBpY3R1cmUgb2YgdGhlIGluZGl2aWR1YWwgcGxheWVyJ3MgcGVyZm9ybWFuY2UsIGFuZCBvZmZlcnMgYSBtZWFucyB0byBjaGVjayB0aGUgaW1wbGljYXRpb25zIG9mIHRoZSByYW5raW5ncyBhbmQgdGhlIGNvbnNpc3RlbmN5IG9mIHRoZSBkYXRhLg0KYGBge3IgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0NCkJSRUZfZGF0YSA8LSBkcGx5cjo6dGJsX2RmKHJlYWQuY3N2KCJCQlJFRl9wbGF5ZXJzLmNzdiIpKQ0KcGxheWVyc19yYW5rIDwtIEJSRUZfZGF0YQ0KDQojUGVyZm9ybSBDbGVhbmluZw0KcGxheWVyc19yYW5rJFBsYXllciA8LSBzdHJfZXh0cmFjdChwbGF5ZXJzX3JhbmskUGxheWVyLCAiXFx3KyBcXHcrXFxiIikNCnBsYXllcnNfcmFuayA8LSBwbGF5ZXJzX3JhbmtbIWlzLm5hKHBsYXllcnNfcmFuayRQbGF5ZXIpLF0NCnBsYXllcnNfcmFuayA8LSBkaXN0aW5jdChwbGF5ZXJzX3JhbmssIFBsYXllciwgLmtlZXBfYWxsID0gVFJVRSkNCg0KcGxheWVyX3N0YXRzX3JhbmtpbmdfZGF0YSA8LSBzcWxkZigiU2VsZWN0IHBsYXllcnNfc3RhdHNfZGF0YV9yYW5rcy5SYW5rLCBSYW5raW5nLCBwbGF5ZXJzX3JhbmsuUGxheWVyLCBQb3MgQXMgUG9zaXRpb24sIEFnZSwgVG0gQVMgVGVhbSwgRyBBcyBHYW1lcywgTVAgQVMgTWludXRlc19Ub3RhbCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCYWxsX1RpbWUsIERyaWJibGVzLCBUb3RhbF9TaG90cywgUG9pbnRfVG90YWwsIFBvaW50c19QZXJfU2hvdCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGRyBBUyBGaWVsZF9Hb2FscywgRkdBIEFTIEZpZWxkX0dvYWxfQXR0DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGUk9NIHBsYXllcnNfcmFuayBJTk5FUiBKT0lOIHBsYXllcnNfc3RhdHNfZGF0YV9yYW5rcw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT04gTE9XRVIocGxheWVyc19yYW5rLlBsYXllcikgPSBwbGF5ZXJzX3N0YXRzX2RhdGFfcmFua3MuUGxheWVyDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPUkRFUiBCWSBQb3NpdGlvbiwgUmFuayIpDQoNCg0KI1BlcmZvcm0gQ2xlYW5pbmcNCnBsYXllcl9zdGF0c19yYW5raW5nX2RhdGEgPC0gcGxheWVyX3N0YXRzX3JhbmtpbmdfZGF0YVtwbGF5ZXJfc3RhdHNfcmFua2luZ19kYXRhJFBvc2l0aW9uICVpbiUgYygiQyIsIlBGIiwiUEciLCJTRiIsICJTRyIpLF0NCnBsYXllcl9zdGF0c19yYW5raW5nX2RhdGEgPC0gYXMuZGF0YS5mcmFtZShsYXBwbHkocGxheWVyX3N0YXRzX3JhbmtpbmdfZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9IGZ1bmN0aW9uKFgpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZighaXMubnVtZXJpYyhYKSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4oYXMuY2hhcmFjdGVyKFgpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuKHJvdW5kKFgsIGRpZ2l0cyA9IDMpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KcGxheWVyX3N0YXRzX3JhbmtpbmdfZGF0YQ0KDQpgYGANCg0KDQoNClRoaXMgdGFuZ2VudCBsb29rcyBhdCBob3cgcGxheWVyIHBlcmZvcm1hbmNlIHN0YWNrcyB1cCB3aGVuIGdyb3VwaW5nIGJ5IHBvc2l0aW9uLiAgVGhpcyB3aWxsIHNob3cgaWYgdGhlIHJhbmtpbmcgc3lzdGVtIGlzIGRyYW1hdGljYWxseSBiaWFzZWQgdG93YXJkcyB0aGUgc2tpbGxzIHJlcXVpcmVkIGZvciBhbnkgZ2l2ZW4gcG9zaXRpb24uICBMb29raW5nIGF0IHRoZSBnZ3Bsb3QgZ3JhcGhpYyBnZW5lcmF0ZWQgYnkgYXZlcmFnaW5nIGFsbCB0aGUgbWV0cmljcyBhZnRlciBhZ2dyZWdhdGluZyBieSBwb3NpdGlvbiwgaXQgaXMgY2xlYXIgdGhhdCBjZW50ZXJzIGFyZSByYW5rZWQgbXVjaCBoaWdoZXIgdGhhbiBvdGhlciBwb3NpdGlvbnMgd2hlbiBsb29raW5nIGF0IGhvdyBvZnRlbiB0aGV5IHNjb3JlIGdpdmVuIHRoZSBhbW91bnQgb2YgdGltZSB0aGV5IGhhbmRsZSB0aGUgYmFsbC4gIFRoZSBzdXJwcmlzZSBpcyB0aGF0IHRoZSBjZW50ZXJzIGhhZCBhIG11Y2ggaGlnaGVyIHBvaW50cy1wZXItc2hvdCByYXRpbyBidXQgYWxzbyBsZXNzIGJhbGwgdGltZSwgd2hpY2ggY29udHJpYnV0ZWQgdG8gdGhlIGhpZ2hlciBhdmVyYWdlIHNjb3JlIGFuZCBsb3dlciByYW5raW5nLg0KYGBge3IgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0NCmF2Z19wb3NpdGlvbl9yYW5rcyA8LSBzcWxkZigiU0VMRUNUIFBvc2l0aW9uLCBDT1VOVChQb3NpdGlvbikgQVMgTnVtYmVyLCBBVkcoUmFuaykgQVMgUmFuaywgQVZHKEFnZSkgQXMgQWdlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBVkcoUG9pbnRzX1Blcl9TaG90KSBBUyBQb2ludHNfUGVyX1Nob3QsIEFWRyhCYWxsX1RpbWUpIEFTIEJhbGxfVGltZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQVZHKFBvaW50X1RvdGFsKSBBUyBQb2ludF9Ub3RhbCwgQVZHKFRvdGFsX1Nob3RzKSBBcyBUb3RhbF9TaG90cw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGUk9NIHBsYXllcl9zdGF0c19yYW5raW5nX2RhdGENCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR1JPVVAgQlkgUG9zaXRpb24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT1JERVIgQlkgUmFuaywgTnVtYmVyIikNCg0KI1BlcmZvcm0gQ2xlYW5pbmcNCmF2Z19wb3NpdGlvbl9yYW5rcyA8LSBhcy5kYXRhLmZyYW1lKGxhcHBseShhdmdfcG9zaXRpb25fcmFua3MsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSBmdW5jdGlvbihYLCBuID0gMikNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKCFpcy5udW1lcmljKFgpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybihhcy5jaGFyYWN0ZXIoWCkpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ocm91bmQoWCwgZGlnaXRzID0gbikpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQoNCmF2Z19wb3NpdGlvbl9yYW5rc19wbG90bHkgPC0gcGxvdF9seShhdmdfcG9zaXRpb25fcmFua3MpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkX2JhcnMoeCA9IH5Qb3NpdGlvbiwgeSA9IH5SYW5rLCBjb2xvciA9IH5Qb2ludHNfUGVyX1Nob3QsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSB+TnVtYmVyLCBjb2xvcnMgPSAiUmRCdSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSB+cGFzdGUoIjwvYnI+TnVtYmVyOiAiLCBOdW1iZXIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjwvYnI+UG9pbnRzIFBlciBTaG90OiAiLCBQb2ludHNfUGVyX1Nob3QsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjwvYnI+UG9pbnQgVG90YWw6ICIsIFBvaW50X1RvdGFsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8L2JyPlNob3QgVG90YWw6ICIsIFRvdGFsX1Nob3RzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8L2JyPkJhbGwgVGltZTogIiwgQmFsbF9UaW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8L2JyPkFnZTogIiwgQWdlKSApICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYXlvdXQodGl0bGUgPSAiUG9zaXRpb25hbCBSYW5raW5ncyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiUG9zaXRpb24iKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJBdmVyYWdlIFJhbmtpbmciKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhcmdhcCA9IH5OdW1iZXIpDQoNCmF2Z19wb3NpdGlvbl9yYW5rc19nZyA8LSBnZ3Bsb3QoKSArDQogICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9jb2woZGF0YSA9IGF2Z19wb3NpdGlvbl9yYW5rcywgYWVzKHggPSBQb3NpdGlvbiwgeSA9IFJhbmssIGZpbGwgPSBQb2ludHNfUGVyX1Nob3QpKQ0KDQojZ2dwbG90MiBHcmFwaGljcw0KYXZnX3Bvc2l0aW9uX3JhbmtzX2dnDQoNCiNQbG90bHkgR3JhcGhpYw0KI2F2Z19wb3NpdGlvbl9yYW5rc19wbG90bHkNCmBgYA0KDQpUaGlzIGdncGxvdCBncmFwaGljIHNob3dzIGhvdyB0aGlzIHJhbmtpbmcgc3lzdGVtIHBsYXlzIG91dCB3aXRoIHJlc3BlY3QgdG8gYSBwbGF5ZXIncyBwb2ludCB0b3RhbCwgYWNjb3VudGluZyBmb3IgcG9zaXRpb24gYW5kIGJhbGwgdGltZSBhcyB3ZWxsLiAgQXMgb25lIHdvdWxkIGV4cGVjdCBwbGF5ZXJzIHdpdGggaGlnaCBwb2ludCB0b3RhbHMgaGF2ZSB0aGUgaGlnaGVzdCByYW5raW5ncywgYW5kIHRoaXMgZ2VuZXJhbGx5IGNvcnJlc3BvbmRzIHRvIG1vcmUgYmFsbCB0aW1lLiBMb29raW5nIGF0IHRoZSBncmFwaGljIGl0IGlzIGFsc28gY2xlYXIgdGhhdCBkaWZmZXJlbnQgcG9zaXRpb25zIGhhdmUgZGVmaW5lZCBjbHVzdGVyaW5nIHdpdGhpbiB0aGUgZGF0YSwgc29tZXRoaW5nIHRoYXQgY291bGQgYmUgZXhwbG9yZWQgZnVydGhlci4NCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBlY2hvID0gRkFMU0V9DQogICAgICAgICAgICAgICAgICAgICAgICAgIA0KcGxheWVyX3Bvc2l0aW9uX3JhbmtzX3Bsb3RseSA8LSAgcGxvdF9seSgpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRfZGF0YShwbGF5ZXJfc3RhdHNfcmFua2luZ19kYXRhKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkX21hcmtlcnMoeCA9IH5SYW5raW5nLCB5ID0gflBvaW50X1RvdGFsLCB6ID0gflBvaW50c19QZXJfU2hvdCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IH5CYWxsX1RpbWUsIGNvbG9yID0gflBvc2l0aW9uLCBjb2xvcnMgPSAiU3BlY3RyYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gfnBhc3RlKCI8L2JyPlBsYXllcjogIiwgUGxheWVyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8L2JyPlJhbms6ICIsIFJhbmssICIsIFZhbHVlOiAiLCBSYW5raW5nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8L2JyPlBvc2l0aW9uOiAiLCBQb3NpdGlvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPC9icj5Qb2ludHMgUGVyIFNob3Q6ICIsIFBvaW50c19QZXJfU2hvdCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPC9icj5Qb2ludCBUb3RhbDogIiwgUG9pbnRfVG90YWwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjwvYnI+U2hvdCBUb3RhbDogIiwgVG90YWxfU2hvdHMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjwvYnI+QmFsbCBUaW1lOiAiLCBCYWxsX1RpbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjwvYnI+QWdlOiAiLCBBZ2UpICkgJT4lDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxheW91dCh0aXRsZSA9ICJQbGF5ZXIgUG9zaXRpb25hbCBSYW5raW5ncyIpDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQpwbGF5ZXJfcG9zaXRpb25fcmFua3NfZ2cgPC0gZ2dwbG90KCkgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KGRhdGEgPSBwbGF5ZXJfc3RhdHNfcmFua2luZ19kYXRhLCBhZXMoeCA9IFJhbmtpbmcsIHkgPSBQb2ludF9Ub3RhbCwgc2l6ZSA9IEJhbGxfVGltZSwgY29sb3IgPSBQb3NpdGlvbikpDQoNCiNnZ3Bsb3QyIEdyYXBoaWMNCnBsYXllcl9wb3NpdGlvbl9yYW5rc19nZw0KDQojUGxvdGx5IEdyYXBoaWMNCiNwbGF5ZXJfcG9zaXRpb25fcmFua3NfcGxvdGx5DQoNCmBgYA0KDQoNClRoZSBwb3NpdGlvbmFsIHJhbmtpbmdzIGV4aXN0IGluIGNsdXN0ZXJzLCB3aGljaCBtZWFucyB0aGF0IHRoZSByYW5raW5ncyBmb3IgcGxheWVycyBvZiB0aGUgc2FtZSBwb3NpdGlvbiBhcmUgZ3JvdXBlZCBhcm91bmQgYW4gZXhwZWN0ZWQgdmFsdWUgKGF2ZXJhZ2UpIHdpdGggc29tZSBzdGFuZGFyZCBkZXZpYXRpb24gd2l0aGluIHRoZSBncm91cGluZy4gIEJ5IG1vZGVsaW5nIHRoZSBwcm9iYWJpbGl0aWVzIG9mIHBsYXllcnMgaW4gZWFjaCBwb3NpdGlvbiBoYXZpbmcgYSBjZXJ0YWluIHJhbmtpbmcgYXMgYSBub3JtYWwgZGlzdHJpYnV0aW9uLCBhIHNldCBvZiBib3VuZGFyaWVzIGZvciBpZGVudGlmeWluZyBhIHBsYXllcidzIHBvc2l0aW9uIGJ5IHRoZWlyIHJhbmtpbmcgd2l0aGluIHRoaXMgc3lzdGVtIGJlZ2lucyB0byBhcHBlYXIuIEZvciBleGFtcGxlLCB0aGUgbW9zdCBjb25maWRlbnQgZXN0aW1hdGUgdGhhdCBhIHBsYXllciB3aXRoIGEgY2VydGFpbiByYW5raW5nIHBsYXlzIGEgY2VydGFpbiBwb3NpdGlvbiB3aWxsIG1hcCBkaXJlY3RseSB0byB0aGUgcG9zaXRpb25hbCBkaXN0cmlidXRpb24gd2l0aCB0aGUgaGlnaGVzdCB2YWx1ZSBmb3IgdGhhdCByYW5raW5nIA0KKGUuZy4gaWYgYSBwbGF5ZXIncyByYW5raW5nIGlzIGxlc3MgdGhhbiAxLjAwLCB0aGVuICdjZW50ZXInIHdvdWxkIGJlIHRoZSBiZXN0IGVzdGltYXRlIGZvciB0aGVpciBwb3NpdGlvbi4pDQpgYGB7ciBtZXNzYWdlID0gRkFMU0UsICB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0NCg0KcG9zaXRpb25zIDwtIHVubGlzdChzcWxkZigiU0VMRUNUIERJU1RJTkNUKCBwb3NpdGlvbiApIEZST00gcGxheWVyX3N0YXRzX3JhbmtpbmdfZGF0YSIpKQ0KcG9zaXRpb25fcmFua3Nfc3RhdHMgPC0gYXMuZGF0YS5mcmFtZShtYXRyaXgoMCwgbmNvbCA9IGxlbmd0aChwb3NpdGlvbnMpLCBucm93ICA9IDIpKQ0KY29sbmFtZXMocG9zaXRpb25fcmFua3Nfc3RhdHMpIDwtIHBvc2l0aW9ucw0Kcm93bmFtZXMocG9zaXRpb25fcmFua3Nfc3RhdHMpIDwtIGMoIm1lYW4iLCAic3RkRGlzdCIpDQpjb2xvcnMgPC0gYygicmVkIiwgImdyZWVuIiwgImJsdWUiLCAieWVsbG93IiwgInB1cnBsZSIpDQpuIDwtIDENCnBvc2l0aW9uX3JhbmtzX2Rpc3RfcGxvdGx5IDwtIHBsb3RfbHkoKQ0KDQpmb3IocG9zIGluIHBvc2l0aW9ucykNCnsNCiAgZGF0YSA8LSBwbGF5ZXJfc3RhdHNfcmFua2luZ19kYXRhW3BsYXllcl9zdGF0c19yYW5raW5nX2RhdGEkUG9zaXRpb24gPT0gcG9zLCAiUmFua2luZyJdDQogIHBvc2l0aW9uX3JhbmtzX3N0YXRzWyxwb3NdID0gYyhtZWFuKGRhdGEpLCBzZChkYXRhKSkgIA0KICB5dmFsIDwtIGRub3JtKGRhdGEsIHBvc2l0aW9uX3JhbmtzX3N0YXRzWzEscG9zXSwgcG9zaXRpb25fcmFua3Nfc3RhdHNbMixwb3NdKQ0KICANCiAgcG9zaXRpb25fcmFua3NfZGlzdF9wbG90bHkgPC0gcG9zaXRpb25fcmFua3NfZGlzdF9wbG90bHkgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRfbWFya2Vycyh4ID0gZGF0YSwgeSA9IHl2YWwsIGNvbG9ycyA9ICJTcGVjdHJhbCIsIG5hbWUgPSBwb3MpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRfbGluZXMoeCA9IGRhdGEsIHkgPSB5dmFsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSBwb3MsIHRleHQgPSBwYXN0ZSgiTWVhbiBSYW5raW5nOiAiLCBwb3NpdGlvbl9yYW5rc19zdGF0c1sxLHBvc10sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjwvYnI+IFN0ZCBEZXZpYXRpb246ICIsIHBvc2l0aW9uX3JhbmtzX3N0YXRzWzIsIHBvc10pLCBjb2xvcnMgPSAiU3BlY3RyYWwiKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCn0NCg0KcG9zaXRpb25fcmFua3NfZGlzdF9wbG90bHkgPC0gcG9zaXRpb25fcmFua3NfZGlzdF9wbG90bHkgJT4lDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXlvdXQodGl0bGUgPSAiUG9zaXRpb24gUmFua2luZyBEaXN0cmlidXRpb25zIiwgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlJhbmtpbmcgVmFsdWUiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiUHJvYmFiaWxpdHkgJSIpKQ0KDQoNCmRhdGFmdWxsIDwtIGRhdGEuZnJhbWUoIlJhbmtpbmciID0gcGxheWVyX3N0YXRzX3JhbmtpbmdfZGF0YVtwbGF5ZXJfc3RhdHNfcmFua2luZ19kYXRhJFBvc2l0aW9uID09ICJDIiwgIlJhbmtpbmciXVsxOjQ3XSwNCiAgICAgICAgICAgICAgICAgICAgIlBGIiA9IHBsYXllcl9zdGF0c19yYW5raW5nX2RhdGFbcGxheWVyX3N0YXRzX3JhbmtpbmdfZGF0YSRQb3NpdGlvbiA9PSAiUEYiLCAiUmFua2luZyJdWzE6NDddLA0KICAgICAgICAgICAgICAgICAgICAiUEciID0gcGxheWVyX3N0YXRzX3JhbmtpbmdfZGF0YVtwbGF5ZXJfc3RhdHNfcmFua2luZ19kYXRhJFBvc2l0aW9uID09ICJQRyIsICJSYW5raW5nIl1bMTo0N10sDQogICAgICAgICAgICAgICAgICAgICJTRiIgPSBwbGF5ZXJfc3RhdHNfcmFua2luZ19kYXRhW3BsYXllcl9zdGF0c19yYW5raW5nX2RhdGEkUG9zaXRpb24gPT0gIlNGIiwgIlJhbmtpbmciXVsxOjQ3XSwNCiAgICAgICAgICAgICAgICAgICAgIlNHIiA9IHBsYXllcl9zdGF0c19yYW5raW5nX2RhdGFbcGxheWVyX3N0YXRzX3JhbmtpbmdfZGF0YSRQb3NpdGlvbiA9PSAiU0ciLCAiUmFua2luZyJdWzE6NDddKQ0KDQpkYXRhZnVsbCRQZXJjZW50YWdlIDwtIGRub3JtKGRhdGFmdWxsJFJhbmtpbmcsIHBvc2l0aW9uX3JhbmtzX3N0YXRzWzEsMV0sIHBvc2l0aW9uX3JhbmtzX3N0YXRzWzIsMV0pDQpkYXRhZnVsbCR2YWxQRiA8LSBkbm9ybShkYXRhZnVsbCRQRiwgcG9zaXRpb25fcmFua3Nfc3RhdHNbMSwyXSwgcG9zaXRpb25fcmFua3Nfc3RhdHNbMiwyXSkNCmRhdGFmdWxsJHZhbFBHPC0gZG5vcm0oZGF0YWZ1bGwkUEcsIHBvc2l0aW9uX3JhbmtzX3N0YXRzWzEsM10sIHBvc2l0aW9uX3JhbmtzX3N0YXRzWzIsM10pDQpkYXRhZnVsbCR2YWxTRiA8LSBkbm9ybShkYXRhZnVsbCRTRiwgcG9zaXRpb25fcmFua3Nfc3RhdHNbMSw0XSwgcG9zaXRpb25fcmFua3Nfc3RhdHNbMiw0XSkNCmRhdGFmdWxsJHZhbFNHIDwtIGRub3JtKGRhdGFmdWxsJFNHLCBwb3NpdGlvbl9yYW5rc19zdGF0c1sxLDVdLCBwb3NpdGlvbl9yYW5rc19zdGF0c1syLDVdKQ0KDQoNCnBvc2l0aW9uX3JhbmtzX2Rpc3RfZ2cgPC0gZ2dwbG90KGRhdGFmdWxsKSArDQogICAgICAgICAgICAgICAgICAgICAgICAgIGdlb21fbGluZShhZXMoeCA9IFJhbmtpbmcsIHkgPSBQZXJjZW50YWdlLCBjb2xvciA9ICJDIiwgbmFtZSA9ICJDIikpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9wYXRoKGFlcyh4ID0gUEYsIHkgPSB2YWxQRiwgY29sb3IgPSAiUEYiLCBuYW1lID0gIlBGIikpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9wYXRoKGFlcyh4ID0gUEcsIHkgPSB2YWxQRywgY29sb3IgPSAiUEciLCBuYW1lID0gIlBHIikpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9wYXRoKGFlcyh4ID0gU0YsIHkgPSB2YWxTRiwgY29sb3IgPSAiU0YiLCBuYW1lID0gIlNGIikpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9wYXRoKGFlcyh4ID0gU0csIHkgPSB2YWxTRywgY29sb3IgPSAiU0ciLCBuYW1lID0gIlNHIikpDQojZ2dwbG90IEdyYXBoaWMNCnBvc2l0aW9uX3JhbmtzX2Rpc3RfZ2cNCg0KI3Bsb3RseSBHcmFwaGljDQojcG9zaXRpb25fcmFua3NfZGlzdF9wbG90bHkNCg0KYGBgDQoNCg0KDQoNCg0K