Evaluating passing skill in hockey is hard, especially when most of the data that you have to work with is just box score stats. Sure, primary assists, secondary assists, and turnovers are a decent place to start, but that’s a specific subset of all passes that occur in a hockey game. What about the passes that take place over the rest of the game?

Well, the lack of data has stood in the way of that sort of analysis for women’s hockey in recent years. But earlier this year, for the Big Data Cup, Stathletes released a dataset for the 2021 NWHL season that contained detailed tracking data, including pass events and both passer/receiver locations. With this data now available for the NWHL, it was unsurprising that many people made evaluating passing and movements a focus of their Big Data Cup projects, a list of which you can find here.

There were quite a few projects that focused on evaluating pass types by pass cluster, but for this project I was interested in testing out a couple of methods for evaluating individual players and their passing skill. You can find the full results and leader board at the bottom of this article (though some of the columns may not make sense if you don’t read the full article!) and the code can be found on my GitHub page.

The first method I test is building a Completion Percentage Over Expected (CPOE) model for the NWHL data and then using a Bayesian estimation to look at uncertainty in CPOE. While CPOE is not a new idea, I was inspired to use the Bayesian process by the tweet/project that is linked below which looked at CPOE for NFL Draft Prospects.

The other method that I explored is using a linear mixed-effects model with a random effect term for each player to see how each player’s completion percentage varied. Much of this was inspired by Dani Treisman’s Big Data Cup project, which used mixed effects for measuring how skill impacts xG, as well as previous research surrounding fumbles in the NFL (Michael Lopez) and catcher framing in baseball (Jonathan Judge, Harry Pavlidis, and Dan Brooks).

Let’s jump into it!


Completion Percentage Over Expected (CPOE)

Every attempted pass will either be completed (1) or incomplete (0). However, every single pass has a different likelihood of being completed. CPOE looks to see who completes more (or fewer) passes than what they’re expected to based on how difficult the pass attempt was. If a player is routinely completing difficult passes, that’s a good indication that they are a very good passer.

I used a Generalized Additive Model (GAM) from the mgcv package in R to model Expected Completion Percentage (xCP) for this project, using the passer location, intended receiver location, length of the pass, and the direction of the pass as inputs. These inputs are mostly dependent on the offense, though xCP surely depends on the defensive alignment, we don’t have that data available, so it’s not considered.

One item of note: while I took a random half of all the direct passes in the dataset to train the model, I did run the model on the entire dataset in order to include as many players/passes as possible in my results. This approach does mean that over fitting is a potential concern with our model, given the limited sample of passes (about 8000 recorded passes). (I removed indirect passes from the NWHL dataset because rimming a pass along the board has a different goal than a pass directed at another player.)

Once we run our Completion Percentage model on the NWHL data, we can calculate the CPOE for each pass (and player). As discussed previously, every pass is either complete (1) or incomplete (0). Since the GAM that we ran uses a binomial distribution, the values returned from the model are probabilities, ranging from 0 to 1. To calculate CPOE, take the Completion Percentage (CP) of the pass (0 or 1) and subtract the Expected Completion Percentage (xCP) from it.

For example, take a complete pass from Kaleigh Fratkin to McKenna Brand, which has an xCP of 0.64. Since the pass was completed, it has a CP of 1.00. Given the xCP of 0.64, the CPOE of that pass is 0.36. Repeat this process (or rather, write the code for it) and you get CPOE for every player. (The full leaderboard for CPOE is at the bottom of this article.)

Great!

We’ve calculated which players have completed more (or less) passes than we would expect, but how can we account for the uncertainty that comes from working with small samples? That’s an important question because CPOE tends to converge to 0.00 in our sample (check out the CPOE by Pass Attempts graph at the end of the second section to see this trend).

It’s clear that we should be cautious in making sweeping claims about the passing skill of players with just a few passes (and I’d argue that all the players should be viewed with caution because even Kaleigh Fratkin’s 245 passes isn’t that many). Obviously we can mentally add that asterisk to these figures, but I’d be happier if we put a number (read: confidence interval) on these figures.

That’s where the linked tweet and Bayesian estimation comes in.

Taking each player individually, the model examines each player’s distribution of CPOE and returns their mean CPOE, as well as the figures for a 95% confidence interval of where that player’s “true” CPOE lies. This interval is represented on the graphic below for the 44 NWHL players who recorded at least 75 attempted passes in 2021.

We have a fairly even split of positive CPOE and negative CPOE here, with some on the much higher and much lower ends of the spectrum. What I want to draw attention to is how the length of the interval is varied for every single player. On one hand, you’ve got a player like Kaleigh Fratkin, who has a the smallest interval, and on the other there’s Kristin Lewicki with a giant interval.

The graph with all 44 names on it can be kind of tough to read, so we can visualize this on a smaller scale too. Here I’ve pulled four names: Kaleigh Fratkin, McKenna Brand, Mikyla Grant-Mentis, and Sarah-Eve Coutu Godbout to represent this.

While there is overlap between every single player’s distribution of CPOE, we see that Fratkin has the highest peak of CPOE, while Coutu Godbout’s distribution is flatter. This indicates that there’s less uncertainty in our estimation of Fratkin’s CPOE (0.036 per pass) while we don’t know as much about Coutu Godbout “true CPOE talent”, which is -0.095 per pass in our sample.

(I chose these four names because they had distributions that I was looking for, but can easily run this for really any combination players. If you want to see a different set of players, hit me up on Twitter @benhowell71!)

The discrepancies in those intervals and distributions is largely due to how many passes have been observed for each player. For instance, Fratkin’s 245 passes are the most in our dataset, while Coutu Godbout’s 75 passes are right at our arbitrary cutoff. However, it’s not a 1:1 relationship between passes and spread (check out the CI Lengths vs Pass Attempts graph at the end of the second section to see this trend). Another factor that plays a big part in determining that 95% confidence interval is a player’s consistency.

For instance, if one player oscillates between successfully converting low xCP passes and turning over high xCP passes, they’ll be more volatile (larger interval) than the player who completes everything above an xCP of 0.5 and fails to complete anything below 0.5.


Mixed Model to account for passer effects

The second model that I tested is a mixed effects model with a random effect intercept. The random effect in the formula (the (1 | Player) term) has the model evaluate each player against their own baseline average, rather than relative to the overall population.

The major components of my mixed effects model are the same as the GAM I used earlier, with the sole addition of the random effect parameter (1 | Player). The pass start and intended location, direction, and length all remain in the model.

Once the model has been run, we can pull out the intercepts for each unique player to see who increases the likelihood of a successful pass the most (a positive intercept = better passer by this measure). As with our CPOE measure, the mixed effects model allows us to create confidence intervals for the effect of each player.

Now that we’ve gone through the two methods that I used to try and measure passing skill in the NWHL, let’s compare them! (There’s going to be some words here, but you can scroll down to find the full results and leader board at the end of the article.)

There turned out to be a strong relationship (R of 0.83) between CPOE rank and Passer Effect rank. In most cases, being a good passer by either CPOE or by Passer Effect means that a player is probably a good passer in the other. However, there are some…interesting cases and discrepancies between the two, most notably with Jonna Curtis, a forward with the Minnesota Whitecaps who had 96 pass attempts. It’s an interesting discrepancy and one that may be worth exploring more in-depth (or it could be a small sample quirk).

In contrast to our CPOE metric, the Passer Effect intercept does not converge as drastically to zero. I did find it intriguing that everyone with more than 125 direct passes increased the chance of a successful pass; this could imply that the better a passer you are, the more passes that you make. However, this could also be a quirk of our small sample size.

As with CPOE, there is a strong relationship between attempting more passes and having a smaller confidence interval on a player’s intercept.


Leaderboard and Full Results

Below is a full table that compares CP, xCP, CPOE, and Passer Effect for the 2021 NWHL skaters who attempted at least 75 passes in the 2021 season + a rundown of some of the results I found interesting.

Kaleigh Fratkin (the 2021 Defender of the Year) who had 9 assists, fared much better in the Passer Effect metric (ranking 3rd) while ranking 11th in CPOE. Her xCP has on the higher side and, for how high her xCP is, her CPOE is really good! It’s just hard to improve on already high xCP passes. The high Passer Effect does indicate that her proclivity to have high xCP passes could be because she’s an excellent passer!

Mikyla Grant-Mentis (the 2021 MVP) was above average in both CPOE and Passer Effect, but didn’t pop at the top of either leader board. McKenna Brand ranked 2nd in both CPOE and Passer Effect, which meshes well with Treisman’s findings on Brand leading the NWHL in his play-making ability metric.

NWHL CPOE (Completion Percentage Over Expected) and Passer Effects

Minimum 75 passes in 2021 season

LS0tDQp0aXRsZTogIk1lYXN1cmluZyBQYXNzaW5nIFNraWxsIGluIHRoZSBOV0hMIg0KYXV0aG9yOiAiQmVuIEhvd2VsbCINCmRhdGU6ICI2LzUvMjAyMSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBoaWdobGlnaHRlcjogbnVsbA0KICAgIHRoZW1lOiAiZmxhdGx5Ig0KICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQ0KYGBgDQoNCmBgYHtyIERhdGEgTWFuaXB1bGF0aW9ufQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KG1nY3YpDQpsaWJyYXJ5KGxtZTQpDQpsaWJyYXJ5KHJlYWN0YWJsZSkNCmxpYnJhcnkoYmF5ZXNib290KQ0KbGlicmFyeShodG1sd2lkZ2V0cykNCmxpYnJhcnkoaHRtbHRvb2xzKQ0KbGlicmFyeSh0d2VldHJtZCkNCmxpYnJhcnkocGF0Y2h3b3JrKQ0KbGlicmFyeShSV29yZFByZXNzKQ0KbGlicmFyeShrbml0cikNCg0KI0knbSBub3QgcnVubmluZyB0aGlzIGFuYWx5c2lzIG9uIHRoZSBPbHltcGljIGRhdGEgZnJvbSB0aGUgQmlnIERhdGEgQ3VwIGJlY2F1c2UgSSB3YW50ZWQgdG8gZm9jdXMgb24gcnVubmluZyB0aGlzIGFuYWx5c2lzDQojZm9yIE5XSEwgcGxheWVycy9kYXRhDQoNCmRmIDwtIHJlYWQuY3N2KCJud2hsX2RhdGEuY3N2IikNCg0KZGYgPC0gZGYgJT4lDQogIG11dGF0ZShYLkNvb3JkaW5hdGUgPSBYLkNvb3JkaW5hdGUgLSAxMDAsDQogICAgICAgICBZLkNvb3JkaW5hdGUgPSBZLkNvb3JkaW5hdGUgLSA0Mi41LA0KICAgICAgICAgWC5Db29yZGluYXRlLjIgPSBYLkNvb3JkaW5hdGUuMiAtIDEwMCwNCiAgICAgICAgIFkuQ29vcmRpbmF0ZS4yID0gWS5Db29yZGluYXRlLjIgLSA0Mi41KSAlPiUNCiAgc2VwYXJhdGUoQ2xvY2ssIGludG8gPSBjKCJNaW51dGVzIiwgIlNlY29uZHMiKSwgc2VwID0gIjoiLCByZW1vdmUgPSBGQUxTRSkgJT4lDQogIG11dGF0ZShNaW51dGVzID0gYXMubnVtZXJpYyhNaW51dGVzKSwNCiAgICAgICAgIFNlY29uZHMgPSBhcy5udW1lcmljKFNlY29uZHMpLA0KICAgICAgICAgYWR2YW50YWdlID0gaWZlbHNlKFRlYW0gPT0gSG9tZS5UZWFtLCBIb21lLlRlYW0uU2thdGVycyAtIEF3YXkuVGVhbS5Ta2F0ZXJzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShUZWFtID09IEF3YXkuVGVhbSwgQXdheS5UZWFtLlNrYXRlcnMgLSBIb21lLlRlYW0uU2thdGVycywgTkEpKSwNCiAgICAgICAgIG9yZGVyID0gcm93X251bWJlcigpKQ0KDQpzdG9yZSA8LSBkZiAlPiUNCiAgZmlsdGVyKEV2ZW50ICVpbiUgYygiRmFjZW9mZiBXaW4iLCAiVGFrZWF3YXkiLCAiUHVjayBSZWNvdmVyeSIpKSAlPiUNCiAgbXV0YXRlKHBsYXlfZXZlbnQgPSByb3dfbnVtYmVyKCkpIA0KIyBiZWdpbiBvZiBhIHNlcXVlbmNlIG9mIGV2ZW50cyBmb3IgYSB0ZWFtDQojIGlnbm9yZXMgdGhlIHBvdGVudGlhbCBmb3IgZHVtcCBhbmQgY2hhc2Ugdy8gYSBQdWNrIFJlY292ZXJ5DQojIG1vc3RseSBiYyBJIGRpZG4ndCB3YW50IHRvIHRoaW5rIGFib3V0IHRoYXQNCiMgaXQgd29uJ3QgcmVhbGx5IGltcGFjdCB0aGlzIHBhc3NpbmcgYW5hbHlzaXMgYmMgd2Ugd291bGRuJ3QgY291bnQgYSBEdW1wIGFuZCBDaGFzZSBhcyBhbiBpbnRlbmRlZCBwYXNzDQoNCmRmIDwtIGxlZnRfam9pbihkZiwgc3RvcmUpDQoNCmRmIDwtIGRmICU+JQ0KICBmaWxsKHBsYXlfZXZlbnQpDQoNCnJtKHN0b3JlKQ0KYGBgDQoNCkV2YWx1YXRpbmcgcGFzc2luZyBza2lsbCBpbiBob2NrZXkgaXMgaGFyZCwgZXNwZWNpYWxseSB3aGVuIG1vc3Qgb2YgdGhlIGRhdGEgdGhhdCB5b3UgaGF2ZSB0byB3b3JrIHdpdGggaXMganVzdCBib3ggc2NvcmUgc3RhdHMuIFN1cmUsIHByaW1hcnkgYXNzaXN0cywgc2Vjb25kYXJ5IGFzc2lzdHMsIGFuZCB0dXJub3ZlcnMgYXJlIGEgZGVjZW50IHBsYWNlIHRvIHN0YXJ0LCBidXQgdGhhdCdzIGEgc3BlY2lmaWMgc3Vic2V0IG9mIGFsbCBwYXNzZXMgdGhhdCBvY2N1ciBpbiBhIGhvY2tleSBnYW1lLiBXaGF0IGFib3V0IHRoZSBwYXNzZXMgdGhhdCB0YWtlIHBsYWNlIG92ZXIgdGhlIHJlc3Qgb2YgdGhlIGdhbWU/ICAgICAgICAgICAgIA0KDQpXZWxsLCB0aGUgbGFjayBvZiBkYXRhIGhhcyBzdG9vZCBpbiB0aGUgd2F5IG9mIHRoYXQgc29ydCBvZiBhbmFseXNpcyBmb3Igd29tZW4ncyBob2NrZXkgaW4gcmVjZW50IHllYXJzLiBCdXQgZWFybGllciB0aGlzIHllYXIsIGZvciB0aGUgQmlnIERhdGEgQ3VwLCBTdGF0aGxldGVzIHJlbGVhc2VkIGEgZGF0YXNldCBmb3IgdGhlIDIwMjEgTldITCBzZWFzb24gdGhhdCBjb250YWluZWQgZGV0YWlsZWQgdHJhY2tpbmcgZGF0YSwgaW5jbHVkaW5nIHBhc3MgZXZlbnRzIGFuZCBib3RoIHBhc3Nlci9yZWNlaXZlciBsb2NhdGlvbnMuIFdpdGggdGhpcyBkYXRhIG5vdyBhdmFpbGFibGUgZm9yIHRoZSBOV0hMLCBpdCB3YXMgdW5zdXJwcmlzaW5nIHRoYXQgbWFueSBwZW9wbGUgbWFkZSBldmFsdWF0aW5nIHBhc3NpbmcgYW5kIG1vdmVtZW50cyBhIGZvY3VzIG9mIHRoZWlyIEJpZyBEYXRhIEN1cCBwcm9qZWN0cywgYSBsaXN0IG9mIHdoaWNoIHlvdSBjYW4gZmluZCBbaGVyZV0oaHR0cHM6Ly93d3cudGhlaWNlZ2FyZGVuLmNvbS8yMDIxLzQvMTUvMjIzNzQ5ODEvYS1kaXJlY3Rvcnktb2Ytd29tZW5zLWhvY2tleS1wcm9qZWN0cy1mcm9tLWJpZy1kYXRhLWN1cC0yMDIxLWFuYWx5dGljcy1vdHRoYWMtc3RhdGhsZXRlcykuICAgICAgICAgICAgICAgICAgICAgICAgDQoNClRoZXJlIHdlcmUgcXVpdGUgYSBmZXcgcHJvamVjdHMgdGhhdCBmb2N1c2VkIG9uIGV2YWx1YXRpbmcgcGFzcyB0eXBlcyBieSBwYXNzIGNsdXN0ZXIsIGJ1dCBmb3IgdGhpcyBwcm9qZWN0IEkgd2FzIGludGVyZXN0ZWQgaW4gdGVzdGluZyBvdXQgYSBjb3VwbGUgb2YgbWV0aG9kcyBmb3IgZXZhbHVhdGluZyBpbmRpdmlkdWFsIHBsYXllcnMgYW5kIHRoZWlyIHBhc3Npbmcgc2tpbGwuIFlvdSBjYW4gZmluZCB0aGUgZnVsbCByZXN1bHRzIGFuZCBsZWFkZXIgYm9hcmQgYXQgdGhlIGJvdHRvbSBvZiB0aGlzIGFydGljbGUgKHRob3VnaCBzb21lIG9mIHRoZSBjb2x1bW5zIG1heSBub3QgbWFrZSBzZW5zZSBpZiB5b3UgZG9uJ3QgcmVhZCB0aGUgZnVsbCBhcnRpY2xlISkgYW5kIHRoZSBjb2RlIGNhbiBiZSBmb3VuZCBvbiBbbXkgR2l0SHViIHBhZ2VdKGh0dHBzOi8vZ2l0aHViLmNvbS9iZW5ob3dlbGw3MS9OV0hMKS4gICAgICAgICAgICAgIA0KDQpUaGUgZmlyc3QgbWV0aG9kIEkgdGVzdCBpcyBidWlsZGluZyBhIENvbXBsZXRpb24gUGVyY2VudGFnZSBPdmVyIEV4cGVjdGVkIChDUE9FKSBtb2RlbCBmb3IgdGhlIE5XSEwgZGF0YSBhbmQgdGhlbiB1c2luZyBhIEJheWVzaWFuIGVzdGltYXRpb24gdG8gbG9vayBhdCB1bmNlcnRhaW50eSBpbiBDUE9FLiBXaGlsZSBDUE9FIGlzIG5vdCBhIG5ldyBpZGVhLCBJIHdhcyBpbnNwaXJlZCB0byB1c2UgdGhlIEJheWVzaWFuIHByb2Nlc3MgYnkgdGhlIHR3ZWV0L3Byb2plY3QgdGhhdCBpcyBsaW5rZWQgYmVsb3cgd2hpY2ggbG9va2VkIGF0IENQT0UgZm9yIE5GTCBEcmFmdCBQcm9zcGVjdHMuDQoNCmBgYHtyfQ0KdHdlZXRfZW1iZWQoImh0dHBzOi8vdHdpdHRlci5jb20vbWZiYW5hbHl0aWNzL3N0YXR1cy8xMzk4MzUyMjM0ODgzMDc2MDk3P3M9MjAiLCBhbGlnbiA9ICJjZW50ZXIiKQ0KYGBgDQoNClRoZSBvdGhlciBtZXRob2QgdGhhdCBJIGV4cGxvcmVkIGlzIHVzaW5nIGEgbGluZWFyIG1peGVkLWVmZmVjdHMgbW9kZWwgd2l0aCBhIHJhbmRvbSBlZmZlY3QgdGVybSBmb3IgZWFjaCBwbGF5ZXIgdG8gc2VlIGhvdyBlYWNoIHBsYXllcidzIGNvbXBsZXRpb24gcGVyY2VudGFnZSB2YXJpZWQuIE11Y2ggb2YgdGhpcyB3YXMgaW5zcGlyZWQgYnkgW0RhbmkgVHJlaXNtYW4ncyBCaWcgRGF0YSBDdXAgcHJvamVjdF0oaHR0cHM6Ly9naXRodWIuY29tL2R0cmVpc21hbi9CaWdEYXRhQ3VwMjAyMSksIHdoaWNoIHVzZWQgbWl4ZWQgZWZmZWN0cyBmb3IgbWVhc3VyaW5nIGhvdyBza2lsbCBpbXBhY3RzIHhHLCBhcyB3ZWxsIGFzIHByZXZpb3VzIHJlc2VhcmNoIHN1cnJvdW5kaW5nIFtmdW1ibGVzIGluIHRoZSBORkxdKGh0dHBzOi8vZ2l0aHViLmNvbS9zdGF0c2J5bG9wZXovTkZMX0Z1bWJsZXMpIChNaWNoYWVsIExvcGV6KSBhbmQgW2NhdGNoZXIgZnJhbWluZ10oaHR0cHM6Ly93d3cuYmFzZWJhbGxwcm9zcGVjdHVzLmNvbS9uZXdzL2FydGljbGUvMjU1MTQvbW92aW5nLWJleW9uZC13b3d5LWEtbWl4ZWQtYXBwcm9hY2gtdG8tbWVhc3VyaW5nLWNhdGNoZXItZnJhbWluZy8pIGluIGJhc2ViYWxsIChKb25hdGhhbiBKdWRnZSwgSGFycnkgUGF2bGlkaXMsIGFuZCBEYW4gQnJvb2tzKS4NCg0KTGV0J3MganVtcCBpbnRvIGl0IQ0KDQoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg0KDQojIENvbXBsZXRpb24gUGVyY2VudGFnZSBPdmVyIEV4cGVjdGVkIChDUE9FKQ0KDQpFdmVyeSBhdHRlbXB0ZWQgcGFzcyB3aWxsIGVpdGhlciBiZSBjb21wbGV0ZWQgKDEpIG9yIGluY29tcGxldGUgKDApLiBIb3dldmVyLCBldmVyeSBzaW5nbGUgcGFzcyBoYXMgYSBkaWZmZXJlbnQgbGlrZWxpaG9vZCBvZiBiZWluZyBjb21wbGV0ZWQuIENQT0UgbG9va3MgdG8gc2VlIHdobyBjb21wbGV0ZXMgbW9yZSAob3IgZmV3ZXIpIHBhc3NlcyB0aGFuIHdoYXQgdGhleSdyZSBleHBlY3RlZCB0byBiYXNlZCBvbiBob3cgZGlmZmljdWx0IHRoZSBwYXNzIGF0dGVtcHQgd2FzLiBJZiBhIHBsYXllciBpcyByb3V0aW5lbHkgY29tcGxldGluZyBkaWZmaWN1bHQgcGFzc2VzLCB0aGF0J3MgYSBnb29kIGluZGljYXRpb24gdGhhdCB0aGV5IGFyZSBhIHZlcnkgZ29vZCBwYXNzZXIuICAgICAgICAgICAgICANCg0KSSB1c2VkIGEgR2VuZXJhbGl6ZWQgQWRkaXRpdmUgTW9kZWwgKEdBTSkgZnJvbSB0aGUgYG1nY3ZgIHBhY2thZ2UgaW4gUiB0byBtb2RlbCBFeHBlY3RlZCBDb21wbGV0aW9uIFBlcmNlbnRhZ2UgKHhDUCkgZm9yIHRoaXMgcHJvamVjdCwgdXNpbmcgdGhlIHBhc3NlciBsb2NhdGlvbiwgaW50ZW5kZWQgcmVjZWl2ZXIgbG9jYXRpb24sIGxlbmd0aCBvZiB0aGUgcGFzcywgYW5kIHRoZSBkaXJlY3Rpb24gb2YgdGhlIHBhc3MgYXMgaW5wdXRzLiBUaGVzZSBpbnB1dHMgYXJlIG1vc3RseSBkZXBlbmRlbnQgb24gdGhlIG9mZmVuc2UsIHRob3VnaCB4Q1Agc3VyZWx5IGRlcGVuZHMgb24gdGhlIGRlZmVuc2l2ZSBhbGlnbm1lbnQsIHdlIGRvbid0IGhhdmUgdGhhdCBkYXRhIGF2YWlsYWJsZSwgc28gaXQncyBub3QgY29uc2lkZXJlZC4gICAgICAgICAgICAgICAgICANCg0KKk9uZSBpdGVtIG9mIG5vdGU6IHdoaWxlIEkgdG9vayBhIHJhbmRvbSBoYWxmIG9mIGFsbCB0aGUgZGlyZWN0IHBhc3NlcyBpbiB0aGUgZGF0YXNldCB0byB0cmFpbiB0aGUgbW9kZWwsIEkgZGlkIHJ1biB0aGUgbW9kZWwgb24gdGhlIGVudGlyZSBkYXRhc2V0IGluIG9yZGVyIHRvIGluY2x1ZGUgYXMgbWFueSBwbGF5ZXJzL3Bhc3NlcyBhcyBwb3NzaWJsZSBpbiBteSByZXN1bHRzLiBUaGlzIGFwcHJvYWNoIGRvZXMgbWVhbiB0aGF0IG92ZXIgZml0dGluZyBpcyBhIHBvdGVudGlhbCBjb25jZXJuIHdpdGggb3VyIG1vZGVsLCBnaXZlbiB0aGUgbGltaXRlZCBzYW1wbGUgb2YgcGFzc2VzIChhYm91dCA4MDAwIHJlY29yZGVkIHBhc3NlcykuIChJIHJlbW92ZWQgaW5kaXJlY3QgcGFzc2VzIGZyb20gdGhlIE5XSEwgZGF0YXNldCBiZWNhdXNlIHJpbW1pbmcgYSBwYXNzIGFsb25nIHRoZSBib2FyZCBoYXMgYSBkaWZmZXJlbnQgZ29hbCB0aGFuIGEgcGFzcyBkaXJlY3RlZCBhdCBhbm90aGVyIHBsYXllci4pKiAgICAgICAgICAgICAgICAgICAgIA0KDQpPbmNlIHdlIHJ1biBvdXIgQ29tcGxldGlvbiBQZXJjZW50YWdlIG1vZGVsIG9uIHRoZSBOV0hMIGRhdGEsIHdlIGNhbiBjYWxjdWxhdGUgdGhlIENQT0UgZm9yIGVhY2ggcGFzcyAoYW5kIHBsYXllcikuIEFzIGRpc2N1c3NlZCBwcmV2aW91c2x5LCBldmVyeSBwYXNzIGlzIGVpdGhlciBjb21wbGV0ZSAoMSkgb3IgaW5jb21wbGV0ZSAoMCkuIFNpbmNlIHRoZSBHQU0gdGhhdCB3ZSByYW4gdXNlcyBhIGJpbm9taWFsIGRpc3RyaWJ1dGlvbiwgdGhlIHZhbHVlcyByZXR1cm5lZCBmcm9tIHRoZSBtb2RlbCBhcmUgcHJvYmFiaWxpdGllcywgcmFuZ2luZyBmcm9tIDAgdG8gMS4gVG8gY2FsY3VsYXRlIENQT0UsIHRha2UgdGhlIENvbXBsZXRpb24gUGVyY2VudGFnZSAoQ1ApIG9mIHRoZSBwYXNzICgwIG9yIDEpIGFuZCBzdWJ0cmFjdCB0aGUgRXhwZWN0ZWQgQ29tcGxldGlvbiBQZXJjZW50YWdlICh4Q1ApIGZyb20gaXQuICAgICAgIA0KDQpGb3IgZXhhbXBsZSwgdGFrZSBhIGNvbXBsZXRlIHBhc3MgZnJvbSBLYWxlaWdoIEZyYXRraW4gdG8gTWNLZW5uYSBCcmFuZCwgd2hpY2ggaGFzIGFuIHhDUCBvZiAwLjY0LiBTaW5jZSB0aGUgcGFzcyB3YXMgY29tcGxldGVkLCBpdCBoYXMgYSBDUCBvZiAxLjAwLiBHaXZlbiB0aGUgeENQIG9mIDAuNjQsIHRoZSBDUE9FIG9mIHRoYXQgcGFzcyBpcyAwLjM2LiBSZXBlYXQgdGhpcyBwcm9jZXNzIChvciByYXRoZXIsIHdyaXRlIHRoZSBjb2RlIGZvciBpdCkgYW5kIHlvdSBnZXQgQ1BPRSBmb3IgZXZlcnkgcGxheWVyLiAoVGhlIGZ1bGwgbGVhZGVyYm9hcmQgZm9yIENQT0UgaXMgYXQgdGhlIGJvdHRvbSBvZiB0aGlzIGFydGljbGUuKQ0KDQpgYGB7cn0NCiMgTWludXRlIDwtIDA6MjANCiMgbWluX29mX2dhbWUgPC0gMjA6MA0KIyANCiMgdGltZSA8LSBkYXRhLmZyYW1lKE1pbnV0ZSwgbWluX29mX2dhbWUpDQojIGNvZGUgdGhhdCBJIHB1bGxlZCBmcm9tIG15IEJEQyBwcm9qZWN0IHdoZW4gSSBjb3BpZWQgc29tZSBjb2RlIG92ZXIgKGl0IHdhcyB1c2VkIGZvciB0aW1lIGxlZnQgaW4gZ2FtZSB0eXBlIHN0dWZmDQojIHdlJ3JlIG5vdCBwYXJ0aWN1bGFybHkgY29uY2VybmVkIHdpdGggaXQgdGhpcyB0aW1lIGFyb3VuZA0KDQpwYXNzZXMgPC0gZGYgJT4lDQogIGZpbHRlcihFdmVudCAlaW4lIGMoIlBsYXkiLCAiSW5jb21wbGV0ZSBQbGF5IikgJiBEZXRhaWwuMSA9PSAiRGlyZWN0IikgJT4lDQogICNmaWx0ZXIgb3V0IGFsbCBkaXJlY3QgcGFzcyBldmVudHMgYmMgd2UgY2FuIGNvbnNpZGVyIHRoZW0gYW4gaW50ZW5kZWQgcGFzcw0KICAjSSBoYXZlIGEgaGFyZCB0aW1lIGNvbWluZyB1cCB3LyBhIHJlYXNvbiB3aHkgaW5kaXJlY3QgcGFzc2VzIHNob3VsZCBiZSBpbmNsdWRlZCBhIENQT0UgbW9kZWwgc2luY2UgdGhleSdyZSBsZXNzIG9mIGFuIGludGVuZGVkIHBhc3MgDQogIG11dGF0ZShYLkNvb3JkaW5hdGUgPSBpZmVsc2UoWC5Db29yZGluYXRlID09IFguQ29vcmRpbmF0ZS4yLCBYLkNvb3JkaW5hdGUgKyAwLjAwMSwgWC5Db29yZGluYXRlKSwNCiAgICAgICAgICN0aGUgYWJvdmUgbGluZSBpcyBiYXNpY2FsbHkgc28gdGhhdCB3ZSBjYW4gY29tZSB1cCB3LyBhIGRpcmVjdGlvbi9sZW5ndGggb2YgYSBwYXNzIHRoYXQgZ29lcyBzaWRld2F5cw0KICAgICAgICAgRGlyZWN0aW9uID0gKFkuQ29vcmRpbmF0ZS4yIC0gWS5Db29yZGluYXRlKSAvIChYLkNvb3JkaW5hdGUuMiAtIFguQ29vcmRpbmF0ZSksDQogICAgICAgICANCiAgICAgICAgIExlbmd0aCA9IHNxcnQoKChYLkNvb3JkaW5hdGUuMiAtIFguQ29vcmRpbmF0ZSkgXiAyKSArICgoWS5Db29yZGluYXRlLjIgLSBZLkNvb3JkaW5hdGUpIF4gMikpLA0KICAgICAgICAgc3VjY2VzcyA9IGlmZWxzZShFdmVudCA9PSAiUGxheSIsIDEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRXZlbnQgID09ICJJbmNvbXBsZXRlIFBsYXkiLCAwLCBOQSkpKQ0KDQojbWVhbihwYXNzZXMkc3VjY2VzcykNCiNzaG91bGQgYmUgYWJvdXQgMC42OSAobmljZSEpDQpgYGANCg0KYGBge3J9DQojc2VwYXJhdGluZyB0aGUgZGF0YSBpbnRvIGEgdHJhaW4gYW5kIHRlc3Qgc2V0DQojYWx0aG91Z2gsIHNpbmNlIHRoZSBkYXRhc2V0IGlzIHNvIHNtYWxsLCBJIHRha2UgdGhpcyByYW5kb20gaGFsZiBvZiBkYXRhIHRvIHRyYWluIHRoZSBtb2RlbA0KI3RoZW4gd2UgcnVuIHRoZSBkYXRhIG9uIHRoZSBvdmVyYWxsIGRhdGEgc2V0LCB3aGljaCBpbmNsdWRlcyB0aGUgdHJhaW5pbmcgZGF0YXNldA0KI3RoZSBqb3lzIG9mIGxpbWl0ZWQgZGF0YSENCnNldC5zZWVkKDU2NSkNCmR0IDwtIHNvcnQoc2FtcGxlKG5yb3cocGFzc2VzKSwgbnJvdyhwYXNzZXMpKi41KSkNCg0KdHJhaW4gPC0gcGFzc2VzW2R0LCBdDQp0ZXN0IDwtIHBhc3Nlc1stZHQsIF0NCmBgYA0KDQpgYGB7cn0NCnBhc3NfbW9kZWwgPC0gZ2FtKHN1Y2Nlc3MgfiBzKFguQ29vcmRpbmF0ZSwgWS5Db29yZGluYXRlKSArIHMoWC5Db29yZGluYXRlLjIsIFkuQ29vcmRpbmF0ZS4yKSArIERpcmVjdGlvbiArIExlbmd0aCwNCiAgICAgICAgICAgICAgICAgIGRhdGEgPSB0cmFpbiwgZmFtaWx5ID0gImJpbm9taWFsIikNCiNydW5uaW5nIHRoZSBtb2RlbA0KI21ha2Ugc3VyZSB0aGF0ICdmYW1pbHkgPSBiaW5vbWlhbCcgc28gdGhhdCB3ZSByZXR1cm4gdmFsdWVzIGJldHdlZW4gMCBhbmQgMSBhcyBhIHBlcmNlbnRhZ2UNCiNzdW1tYXJ5KHBhc3NfbW9kZWwpDQoNCnBhc3NlcyR4Q09NUCA8LSBwcmVkaWN0LmdhbShwYXNzX21vZGVsLCBuZXdkYXRhID0gcGFzc2VzLCB0eXBlID0gInJlc3BvbnNlIikNCiNzdW1tYXJ5KHBhc3NlcyR4Q09NUCkNCiN0byBjaGVjayB3aGF0IHRoZSBzdW1tYXJ5IG9mIHRoZSByZXR1cm5lZCB2YWx1ZXMgYXJlDQpgYGANCg0KYGBge3J9DQpwYXNzZXMgPC0gcGFzc2VzICU+JQ0KICBtdXRhdGUoZGlmZmVyZW5jZSA9IHN1Y2Nlc3MgLSB4Q09NUCkNCg0KbGIgPC0gcGFzc2VzICU+JQ0KICBncm91cF9ieShQbGF5ZXIpICU+JQ0KICBzdW1tYXJpc2UobiA9IG4oKSwNCiAgICAgICAgICAgIENQID0gcm91bmQobWVhbihzdWNjZXNzLCBuYS5ybSA9IFRSVUUpLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIHhDUCA9IHJvdW5kKG1lYW4oeENPTVApLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIENQT0UgPSByb3VuZChtZWFuKGRpZmZlcmVuY2UpLCBkaWdpdHMgPSAzKSkNCg0KI21lYW4ocGFzc2VzJHhDT01QKQ0KI3RoZSBhdmVyYWdlIHhDUCBpcyAwLjY5NzENCiN3aGljaCBpcyB2IHYgY2xvc2UgdG8gdGhlIHJhdyBDUCUNCiN3aGljaCBpcyBhIGdvb2Qgc2lnbg0KYGBgDQoNCmBgYHtyfQ0KI3dlaWdodGVkLm1lYW4obGIkeENQLCB3ID0gbGIkbikNCmBgYA0KDQpgYGB7cn0NCnAxIDwtIGxiICU+JQ0KICBmaWx0ZXIobiA+PSAyNSkgJT4lDQogIGdncGxvdCgpICsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IG4sIHkgPSBDUE9FKSkgKw0KICBsYWJzKHggPSAiUGFzc2VzIiwgdGl0bGUgPSAiQ1BPRSBieSBQYXNzIEF0dGVtcHRzIikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIikpDQoNCiNoaXN0KGxiJENQT0UpDQoNCmdyYXBoaWMgPC0gbGIgJT4lDQogIGZpbHRlcihuID49IDc1KQ0KYGBgDQoNCmBgYHtyfQ0KbWluIDwtIG1pbihncmFwaGljJENQT0UpDQptYXggPC0gbWF4KGdyYXBoaWMkQ1BPRSkNCg0KbWFrZV9jb2xvcl9wYWwgPC0gZnVuY3Rpb24oY29sb3JzLCBiaWFzID0gMSkgew0KICBnZXRfY29sb3IgPC0gY29sb3JSYW1wKGNvbG9ycywgYmlhcyA9IGJpYXMpDQogIGZ1bmN0aW9uKHgpIHJnYihnZXRfY29sb3IoeCksIG1heENvbG9yVmFsdWUgPSAyNTUpDQp9DQoNCmdvb2RfY29sb3IgPC0gbWFrZV9jb2xvcl9wYWwoYygiIzM1YjBhYiIsICIjOTNkM2FiIiwgIiNjOWVjYjQiLCAiI2YyZmJkMiIsICIjZmZmZmZmIiksIGJpYXMgPSAyKQ0KdmVsb19jb2xvciA8LSBtYWtlX2NvbG9yX3BhbChjKCIjQjdFOUY3IiwgIiM3QUQ3RjAiLCAiI0ZGRkVGRSIsICIjREI3QTdCIiwgIiNCQjAxMDMiKSwgYmlhcyA9IDIpDQoNCmNvbG9yIDwtIG1ha2VfY29sb3JfcGFsKGMoIiNjNjJmMmQiLCAiI2NjN2E2NCIsICIjZjdjZWMzIiwgIiNmN2U0ZGYiLCAiI0ZGRkVGRSIsICIjNWJlMDRmIiwgIiMzODgyMjMiKSwgYmlhcyA9IDIpDQoNCnRibCA8LSBncmFwaGljICU+JSANCiAgZmlsdGVyKG4gPj0gNzUpICU+JSANCiAgYXJyYW5nZShkZXNjKENQT0UpKSAlPiUNCiAgcmVhY3RhYmxlKA0KICAgIHBhZ2luYXRpb24gPSBGQUxTRSwNCiAgICBoaWdobGlnaHQgPSBUUlVFLA0KICAgIHN0cmlwZWQgPSBUUlVFLA0KICAgIGRlZmF1bHRDb2xEZWYgPSBjb2xEZWYoDQogICAgYWxpZ24gPSAiY2VudGVyIiwgbWluV2lkdGggPSAyNSwgaGVhZGVyQ2xhc3MgPSAiaGVhZGVyIiwgaGVhZGVyU3R5bGUgPSBsaXN0KGZvbnRXZWlnaHQgPSA3MDApDQogICksDQogIGNvbHVtbkdyb3VwcyA9IGxpc3QoDQogICAgY29sR3JvdXAobmFtZSA9ICJSZXN1bHRzIiwgY29sdW1ucyA9IGMoIkNQIiwgInhDUCIsICJDUE9FIikpDQogICksDQogIHRoZW1lID0gcmVhY3RhYmxlVGhlbWUoDQogICAgaGVhZGVyU3R5bGUgPSBsaXN0KA0KICAgICAgIiY6aG92ZXJbYXJpYS1zb3J0XSIgPSBsaXN0KGJhY2tncm91bmQgPSAiaHNsKDAsIDAlLCA5NiUpIiksDQogICAgICAiJlthcmlhLXNvcnQ9J2FzY2VuZGluZyddLCAmW2FyaWEtc29ydD0nZGVzY2VuZGluZyddIiA9IGxpc3QoYmFja2dyb3VuZCA9ICJoc2woMCwgMCUsIDk2JSkiKSwNCiAgICAgIGJvcmRlckNvbG9yID0gIiM1NTUiDQogICAgKSksDQogIGNvbHVtbnMgPSBsaXN0KA0KICAgIG4gPSBjb2xEZWYoDQogICAgICBuYW1lID0gIlBhc3NlcyIsDQogICAgICBjbGFzcyA9ICJib3JkZXItbGVmdCINCiAgICApLA0KICAgIENQT0UgPSBjb2xEZWYoDQogICAgICBuYW1lID0gIkNQT0UiLA0KICAgICAgc3R5bGUgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICB2YWx1ZQ0KICAgICAgICBub3JtYWxpemVkIDwtICh2YWx1ZSAtIG1pbikgLyAobWF4IC0gbWluKQ0KICAgICAgICAjbm9ybWFsaXplZCA8LSAodmFsdWUgLSBtaW4ocGl0Y2hfdHlwZSRSVjEwMCkpIC8gKG1heChwaXRjaF90eXBlJFJWMTAwKSAtIG1pbihwaXRjaF90eXBlJFJWMTAwKSkNCiAgICAgICAgY29sb3IgPC0gY29sb3Iobm9ybWFsaXplZCkNCiAgICAgICAgbGlzdChiYWNrZ3JvdW5kID0gY29sb3IpDQogICAgICB9DQogICAgKSwNCiAgICBQbGF5ZXIgPSBjb2xEZWYoDQogICAgICBuYW1lID0gIlBsYXllciIsIHdpZHRoID0gMTc1LCByZXNpemFibGUgPSBGQUxTRQ0KICAgICkNCiAgKQ0KKQ0KIyANCiMgZGl2KGNsYXNzID0gInRpdGxlIiwNCiMgICBoMigiTldITCBDUE9FIChDb21wbGV0aW9uIFBlcmNlbnRhZ2UgT3ZlciBFeHBlY3RlZCkiKSwNCiMgICB0YmwpDQpgYGANCg0KYGBge2Nzc30NCi50aXRsZSB7DQogIG1hcmdpbjogMThweCAwcHg7DQogIGZvbnQtc2l6ZTogMTZweDsNCn0NCg0KLmJvcmRlci1sZWZ0IHsNCiAgYm9yZGVyLWxlZnQ6IDJweCBzb2xpZCAjNTU1Ow0KfQ0KDQoudGl0bGUgaDIgew0KICBmb250LXNpemU6IDIwcHg7DQogIGZvbnQtd2VpZ2h0OiA2MDA7DQp9DQoNCi5zdWJ0aXRsZSB7DQogIG1hcmdpbjogMThweCAwcHg7DQogIGZvbnQtc2l6ZTogM3B4Ow0KfQ0KDQouc3VidGl0bGUgaDIgew0KICBmb250LXNpemU6IDE0cHg7DQogICNmb250LXdlaWdodDogMTAwOw0KfQ0KDQovKiBBbGlnbiBoZWFkZXIgdGV4dCB0byB0aGUgYm90dG9tICovDQouaGVhZGVyLA0KLmdyb3VwLWhlYWRlciB7DQogIGRpc3BsYXk6IGZsZXg7DQogIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47DQogIGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7DQp9DQoNCi5oZWFkZXIgew0KICBib3JkZXItYm90dG9tLWNvbG9yOiAjNTU1Ow0KICBmb250LXNpemU6IDEzcHg7DQogIGZvbnQtd2VpZ2h0OiA0MDA7DQogICN0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlOw0KfQ0KDQovKiBIaWdobGlnaHQgaGVhZGVycyB3aGVuIHNvcnRpbmcgKi8NCi5oZWFkZXI6aG92ZXIsDQouaGVhZGVyW2FyaWEtc29ydD0iYXNjZW5kaW5nIl0sDQouaGVhZGVyW2FyaWEtc29ydD0iZGVzY2VuZGluZyJdIHsNCiAgYmFja2dyb3VuZC1jb2xvcjogI2VlZTsNCn0NCg0KLnN0YW5kaW5ncyB7DQogIGZvbnQtZmFtaWx5OiBLYXJsYSwgIkhlbHZldGljYSBOZXVlIiwgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZjsNCiAgZm9udC1zaXplOiAxNHB4Ow0KfQ0KYGBgDQoNCmBgYHtyfQ0KIyBkaXYoY2xhc3MgPSAidGl0bGUiLA0KIyAgIGgyKCJOV0hMIENQT0UgKENvbXBsZXRpb24gUGVyY2VudGFnZSBPdmVyIEV4cGVjdGVkKSIpLA0KIyAgICJNaW5pbXVtIDc1IHBhc3NlcyBpbiAyMDIxIHNlYXNvbiIsDQojICAgdGJsKQ0KDQojIGRpdigNCiMgICBjbGFzcyA9ICJzdGFuZGluZ3MiLA0KIyAgIGRpdihjbGFzcyA9ICJ0aXRsZSIsDQojICAgICBoMigiTldITCBDUE9FIChDb21wbGV0aW9uIFBlcmNlbnRhZ2UgT3ZlciBFeHBlY3RlZCkiKSksDQojICAgZGl2KGNsYXNzID0gInN1YnRpdGxlIiwNCiMgICAgIGg0KCJNaW5pbXVtIDc1IHBhc3NlcyBpbiAyMDIxIHNlYXNvbiIpDQojICAgKSwNCiMgICB0YmwNCiMgKQ0KYGBgDQoNCkdyZWF0ISAgICAgICAgICAgICAgICAgDQoNCldlJ3ZlIGNhbGN1bGF0ZWQgd2hpY2ggcGxheWVycyBoYXZlIGNvbXBsZXRlZCBtb3JlIChvciBsZXNzKSBwYXNzZXMgdGhhbiB3ZSB3b3VsZCBleHBlY3QsIGJ1dCBob3cgY2FuIHdlIGFjY291bnQgZm9yIHRoZSB1bmNlcnRhaW50eSB0aGF0IGNvbWVzIGZyb20gd29ya2luZyB3aXRoIHNtYWxsIHNhbXBsZXM/IFRoYXQncyBhbiBpbXBvcnRhbnQgcXVlc3Rpb24gYmVjYXVzZSBDUE9FIHRlbmRzIHRvIGNvbnZlcmdlIHRvIDAuMDAgaW4gb3VyIHNhbXBsZSAoY2hlY2sgb3V0IHRoZSAqQ1BPRSBieSBQYXNzIEF0dGVtcHRzKiBncmFwaCBhdCB0aGUgZW5kIG9mIHRoZSBzZWNvbmQgc2VjdGlvbiB0byBzZWUgdGhpcyB0cmVuZCkuICAgICAgICAgICAgICAgICANCg0KSXQncyBjbGVhciB0aGF0IHdlIHNob3VsZCBiZSBjYXV0aW91cyBpbiBtYWtpbmcgc3dlZXBpbmcgY2xhaW1zIGFib3V0IHRoZSBwYXNzaW5nIHNraWxsIG9mIHBsYXllcnMgd2l0aCBqdXN0IGEgZmV3IHBhc3NlcyAoYW5kIEknZCBhcmd1ZSB0aGF0IGFsbCB0aGUgcGxheWVycyBzaG91bGQgYmUgdmlld2VkIHdpdGggY2F1dGlvbiBiZWNhdXNlIGV2ZW4gS2FsZWlnaCBGcmF0a2luJ3MgMjQ1IHBhc3NlcyBpc24ndCAqdGhhdCogbWFueSkuIE9idmlvdXNseSB3ZSBjYW4gbWVudGFsbHkgYWRkIHRoYXQgYXN0ZXJpc2sgdG8gdGhlc2UgZmlndXJlcywgYnV0IEknZCBiZSBoYXBwaWVyIGlmIHdlIHB1dCBhIG51bWJlciAocmVhZDogY29uZmlkZW5jZSBpbnRlcnZhbCkgb24gdGhlc2UgZmlndXJlcy4gICAgICAgICAgICAgICAgIA0KDQpUaGF0J3Mgd2hlcmUgdGhlIGxpbmtlZCB0d2VldCBhbmQgQmF5ZXNpYW4gZXN0aW1hdGlvbiBjb21lcyBpbi4gICAgICAgICAgICAgICAgICAgDQoNClRha2luZyBlYWNoIHBsYXllciBpbmRpdmlkdWFsbHksIHRoZSBtb2RlbCBleGFtaW5lcyBlYWNoIHBsYXllcidzIGRpc3RyaWJ1dGlvbiBvZiBDUE9FIGFuZCByZXR1cm5zIHRoZWlyIG1lYW4gQ1BPRSwgYXMgd2VsbCBhcyB0aGUgZmlndXJlcyBmb3IgYSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBvZiB3aGVyZSB0aGF0IHBsYXllcidzICJ0cnVlIiBDUE9FIGxpZXMuIFRoaXMgaW50ZXJ2YWwgaXMgcmVwcmVzZW50ZWQgb24gdGhlIGdyYXBoaWMgYmVsb3cgZm9yIHRoZSA0NCBOV0hMIHBsYXllcnMgd2hvIHJlY29yZGVkIGF0IGxlYXN0IDc1IGF0dGVtcHRlZCBwYXNzZXMgaW4gMjAyMS4NCg0KYGBge3IsIGZpZy5oZWlnaHQ9OSwgZmlnLndpZHRoPTl9DQpuYW1lcyA8LSBncmFwaGljJFBsYXllcg0KDQpkYXRhIDwtIHBhc3NlcyAlPiUNCiAgZmlsdGVyKFBsYXllciAlaW4lIG5hbWVzKQ0KDQpsc3QgPC0gbGlzdCgpDQoNCmZvciAocWIgaW4gbmFtZXMpIHsNCiAgZGZfcGxheSA8LSBkYXRhICU+JQ0KICAgIGZpbHRlcihQbGF5ZXIgPT0gcWIpDQogIHggPC0gYmF5ZXNib290KGFzLnZlY3RvcihkZl9wbGF5JGRpZmZlcmVuY2UpLCBtZWFuKQ0KICBzIDwtIHN1bW1hcnkoeCkNCiAgbWVhbl9jcG9lIDwtIHMkdmFsdWVbMV0NCiAgbGNpIDwtIHMkdmFsdWVbNV0NCiAgdWNpIDwtIHMkdmFsdWVbOV0NCiAgZGZfYmF5ZXMgPC0gZGF0YS5mcmFtZSgibWVhbl9jcG9lIiA9IG1lYW5fY3BvZSwgIkxDSSIgPSBsY2ksICJVQ0kiID0gdWNpKQ0KICBsc3RbW3FiXV0gPC0gZGZfYmF5ZXMNCn0NCg0KZGZfYmF5ZXMgPC0gZHBseXI6OmJpbmRfcm93cyhsc3QpDQpkZl9iYXllcyRQbGF5ZXIgPC0gbmFtZXMNCmRmX2JheWVzIDwtIGRmX2JheWVzICU+JSANCiAgYXJyYW5nZShtZWFuX2Nwb2UpDQoNCmRmX2JheWVzICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3IoUGxheWVyLCBsZXZlbCA9IFBsYXllciksIHkgPSBtZWFuX2Nwb2UpKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgZ2VvbV9wb2ludHJhbmdlKGFlcyh5bWluID0gTENJLCB5bWF4ID0gVUNJLCBjb2xvciA9IG1lYW5fY3BvZSksIHNpemUgPSAxLjYpICsNCiAgbGFicyh4ID0gIlBsYXllciIsIHRpdGxlID0gIkJheWVzaWFuIEVzdGltYXRpb24gZm9yIDIwMjEgTldITCBQYXNzZXIgQ1BPRSIsDQogICAgICAgeSA9ICJNZWFuIENQT0UiLCBzdWJ0aXRsZSA9ICJDUE9FOiBDb21wbGV0aW9uIFBlcmNlbnRhZ2UgT3ZlciBFeHBlY3RlZCIsDQogICAgICAgY2FwdGlvbiA9ICJCZW4gSG93ZWxsIHwgQGJlbmhvd2VsbDcxIHwgYmVuaG93ZWxsNzEuY29tIiwNCiAgICAgICBsYWJlbCA9ICJNZWFuIENQT0UiKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAoImJsdWUiKSwgbWlkID0gImdyZXkiLCBtaWRwb2ludCA9IDAsIGhpZ2ggPSAoInJlZCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJNZWFuIENQT0UiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNSwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDEyKSwNCiAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gOSksDQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMykpDQpgYGANCg0KV2UgaGF2ZSBhIGZhaXJseSBldmVuIHNwbGl0IG9mIHBvc2l0aXZlIENQT0UgYW5kIG5lZ2F0aXZlIENQT0UgaGVyZSwgd2l0aCBzb21lIG9uIHRoZSBtdWNoIGhpZ2hlciBhbmQgbXVjaCBsb3dlciBlbmRzIG9mIHRoZSBzcGVjdHJ1bS4gV2hhdCBJIHdhbnQgdG8gZHJhdyBhdHRlbnRpb24gdG8gaXMgaG93IHRoZSBsZW5ndGggb2YgdGhlIGludGVydmFsIGlzIHZhcmllZCBmb3IgZXZlcnkgc2luZ2xlIHBsYXllci4gT24gb25lIGhhbmQsIHlvdSd2ZSBnb3QgYSBwbGF5ZXIgbGlrZSBLYWxlaWdoIEZyYXRraW4sIHdobyBoYXMgYSB0aGUgc21hbGxlc3QgaW50ZXJ2YWwsIGFuZCBvbiB0aGUgb3RoZXIgdGhlcmUncyBLcmlzdGluIExld2lja2kgd2l0aCBhIGdpYW50IGludGVydmFsLiAgICAgICAgICAgICAgICAgICAgICAgDQoNClRoZSBncmFwaCB3aXRoIGFsbCA0NCBuYW1lcyBvbiBpdCBjYW4gYmUga2luZCBvZiB0b3VnaCB0byByZWFkLCBzbyB3ZSBjYW4gdmlzdWFsaXplIHRoaXMgb24gYSBzbWFsbGVyIHNjYWxlIHRvby4gSGVyZSBJJ3ZlIHB1bGxlZCBmb3VyIG5hbWVzOiBLYWxlaWdoIEZyYXRraW4sIE1jS2VubmEgQnJhbmQsIE1pa3lsYSBHcmFudC1NZW50aXMsIGFuZCBTYXJhaC1FdmUgQ291dHUgR29kYm91dCB0byByZXByZXNlbnQgdGhpcy4gICAgICAgICAgICAgICAgICAgICANCg0KV2hpbGUgdGhlcmUgaXMgb3ZlcmxhcCBiZXR3ZWVuIGV2ZXJ5IHNpbmdsZSBwbGF5ZXIncyBkaXN0cmlidXRpb24gb2YgQ1BPRSwgd2Ugc2VlIHRoYXQgRnJhdGtpbiBoYXMgdGhlIGhpZ2hlc3QgcGVhayBvZiBDUE9FLCB3aGlsZSBDb3V0dSBHb2Rib3V0J3MgZGlzdHJpYnV0aW9uIGlzIGZsYXR0ZXIuIFRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlcmUncyBsZXNzIHVuY2VydGFpbnR5IGluIG91ciBlc3RpbWF0aW9uIG9mIEZyYXRraW4ncyBDUE9FICgwLjAzNiBwZXIgcGFzcykgd2hpbGUgd2UgZG9uJ3Qga25vdyBhcyBtdWNoIGFib3V0IENvdXR1IEdvZGJvdXQgInRydWUgQ1BPRSB0YWxlbnQiLCB3aGljaCBpcyAtMC4wOTUgcGVyIHBhc3MgaW4gb3VyIHNhbXBsZS4gDQoNCihJIGNob3NlIHRoZXNlIGZvdXIgbmFtZXMgYmVjYXVzZSB0aGV5IGhhZCBkaXN0cmlidXRpb25zIHRoYXQgSSB3YXMgbG9va2luZyBmb3IsIGJ1dCBjYW4gZWFzaWx5IHJ1biB0aGlzIGZvciByZWFsbHkgYW55IGNvbWJpbmF0aW9uIHBsYXllcnMuIElmIHlvdSB3YW50IHRvIHNlZSBhIGRpZmZlcmVudCBzZXQgb2YgcGxheWVycywgaGl0IG1lIHVwIG9uIFR3aXR0ZXIgQGJlbmhvd2VsbDcxISkNCg0KYGBge3J9DQpsc3QyIDwtIGxpc3QoKQ0KaG9ja2V5IDwtIGMoIkthbGVpZ2ggRnJhdGtpbiIsICJNY0tlbm5hIEJyYW5kIiwgIk1pa3lsYSBHcmFudC1NZW50aXMiLCAiU2FyYWgtRXZlIENvdXR1IEdvZGJvdXQiKQ0KI2NhbiBjaGFuZ2Ugb3V0IHRoZSBuYW1lcyBoZXJlIHRvIGxvb2sgYXQgdGhlIGRpc3RyaWJ1dGlvbnMgZm9yIGRpZmVyZW50IHBsYXllcnMNCg0KZm9yIChxYiBpbiBob2NrZXkpIHsNCiAgZGZfcGxheSA8LSBkYXRhICU+JSANCiAgICBmaWx0ZXIoUGxheWVyID09IHFiKQ0KICB4IDwtIGJheWVzYm9vdChhcy52ZWN0b3IoZGZfcGxheSRkaWZmZXJlbmNlKSwgbWVhbikNCiAgZGYyIDwtIGRhdGEuZnJhbWUoJ2VzdGltYXRlJyA9IHgkVjEsICdQbGF5ZXInID0gcWIpDQogIGxzdDJbW3FiXV0gPC0gZGYyDQp9DQoNCmRmMiA8LSBkcGx5cjo6YmluZF9yb3dzKGxzdDIpDQoNCmRmMiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gZXN0aW1hdGUpKSArDQogIGdlb21fZGVuc2l0eShhZXMoZmlsbCA9IFBsYXllciksIGFscGhhID0gMC42LCBvdXRsaW5lLnR5cGUgPSAiYm90aCIpICsNCiAgI2dlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKGVzdGltYXRlKSwgY29sb3IgPSBQaXRjaGVyKSkNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh4ID0gIkVzdGltYXRlZCBDUE9FIiwgdGl0bGUgPSAiQmF5ZXNpYW4gRXN0aW1hdGlvbiBvZiBOV0hMIENQT0UgKDIwMjEpIiwNCiAgICAgICBjYXB0aW9uID0gIkJlbiBIb3dlbGwgfCBAYmVuaG93ZWxsNzEgfCBiZW5ob3dlbGw3MS5jb20iLCB5ID0gIiIsDQogICAgICAgc3VidGl0bGUgPSAiQ1BPRTogQ29tcGxldGlvbiBQZXJjZW50YWdlIE92ZXIgRXhwZWN0ZWQiKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0KSwNCiAgICAgICAgI2F4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDgpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTApKQ0KI3dvcnRoIG5vdGluZyB0aGF0IFNFQ0cgaGFzIHRoZSB3aWRlc3Qgc3ByZWFkIGFtb25nIHRoZXNlIHBsYXllcnMNCiNpZiB3ZSBsb29rIGF0IHRoZSAnZ3JhcGhpYycgZGF0YS5mcmFtZSBzaGUgb25seSBoYXMgNzUgb2JzZXJ2YXRpb25zIHdoaWNoIGlzIHRpZWQgZm9yIHRoZSBmZXdlc3QgaW4gdGhpcyBzZXQNCiMoc2luY2Ugd2Ugc2V0IDc1IHBhc3NlcyBhcyB0aGUgbWluaW11bSkNCiNzbyBuYXR1cmFsbHkgc2hlIHNob3VsZCBoYXZlIHRoZSBtb3N0IHVuY2VydGFpbnR5IGluIGhlciBDUE9FIGJjIHdlcmUgZXN0aW1hdGluZyBpdCBmcm9tIHRoZSBzbWFsbGVzdCBzZXQNCiNLYWxlaWdoIEZyYXRraW4gb24gdGhlIG90aGVyIGhhbmQgZWFzaWx5IGhhcyB0aGUgbW9zdCBvYnNlcnZlZCBwYXNzZXMgc28gc2hlIGhhcyB0aGUgaGlnaGVzdCBwZWFrIGFuZCBzb21lIG9mIHRoZSBsZWFzdCB1bmNlcnRhaW50eQ0KI2luIGhlciBkaXN0cmlidXRpb24NCmBgYA0KDQpUaGUgZGlzY3JlcGFuY2llcyBpbiB0aG9zZSBpbnRlcnZhbHMgYW5kIGRpc3RyaWJ1dGlvbnMgaXMgbGFyZ2VseSBkdWUgdG8gaG93IG1hbnkgcGFzc2VzIGhhdmUgYmVlbiBvYnNlcnZlZCBmb3IgZWFjaCBwbGF5ZXIuIEZvciBpbnN0YW5jZSwgRnJhdGtpbidzIDI0NSBwYXNzZXMgYXJlIHRoZSBtb3N0IGluIG91ciBkYXRhc2V0LCB3aGlsZSBDb3V0dSBHb2Rib3V0J3MgNzUgcGFzc2VzIGFyZSByaWdodCBhdCBvdXIgYXJiaXRyYXJ5IGN1dG9mZi4gSG93ZXZlciwgaXQncyBub3QgYSAxOjEgcmVsYXRpb25zaGlwIGJldHdlZW4gcGFzc2VzIGFuZCBzcHJlYWQgKGNoZWNrIG91dCB0aGUgKkNJIExlbmd0aHMgdnMgUGFzcyBBdHRlbXB0cyogZ3JhcGggYXQgdGhlIGVuZCBvZiB0aGUgc2Vjb25kIHNlY3Rpb24gdG8gc2VlIHRoaXMgdHJlbmQpLiBBbm90aGVyIGZhY3RvciB0aGF0IHBsYXlzIGEgYmlnIHBhcnQgaW4gZGV0ZXJtaW5pbmcgdGhhdCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBpcyBhIHBsYXllcidzIGNvbnNpc3RlbmN5LiAgICAgICAgICAgICAgICAgIA0KDQpGb3IgaW5zdGFuY2UsIGlmIG9uZSBwbGF5ZXIgb3NjaWxsYXRlcyBiZXR3ZWVuIHN1Y2Nlc3NmdWxseSBjb252ZXJ0aW5nIGxvdyB4Q1AgcGFzc2VzIGFuZCB0dXJuaW5nIG92ZXIgaGlnaCB4Q1AgcGFzc2VzLCB0aGV5J2xsIGJlIG1vcmUgdm9sYXRpbGUgKGxhcmdlciBpbnRlcnZhbCkgdGhhbiB0aGUgcGxheWVyIHdobyBjb21wbGV0ZXMgZXZlcnl0aGluZyBhYm92ZSBhbiB4Q1Agb2YgMC41IGFuZCBmYWlscyB0byBjb21wbGV0ZSBhbnl0aGluZyBiZWxvdyAwLjUuDQoNCmBgYHtyfQ0KYWxsX2RhdGEgPC0gcmlnaHRfam9pbihncmFwaGljLCBkZl9iYXllcywgYnkgPSAiUGxheWVyIikNCmFsbF9kYXRhIDwtIGFsbF9kYXRhICU+JQ0KICBtdXRhdGUoc3ByZWFkID0gVUNJIC0gTENJKQ0KDQpwMiA8LSBhbGxfZGF0YSAlPiUNCiAgZ2dwbG90KCkgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gbiwgeSA9IHNwcmVhZCkpICsNCiAgbGFicyh4ID0gIlBhc3NlcyIsIHkgPSAiTGVuZ3RoIG9mIENJIiwgdGl0bGUgPSAiQ0kgTGVuZ3RoIHZzIFBhc3MgQXR0ZW1wdHMiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIikpDQoNCmxheW91dCA8LSAocDEgKyBwMikNCiNsYXlvdXQNCiN0aGVyZSBpcyBhIGNsZWFyIHJlbGF0aW9uc2hpcCBidCBoYXZpbmcgbW9yZSBwYXNzZXMgYW5kIGxlc3MgdW5jZXJ0YWludHkgaW4gdGhlIGVzdGltYXRlZCBDUE9FDQpgYGANCg0KKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioNCg0KIyBNaXhlZCBNb2RlbCB0byBhY2NvdW50IGZvciBwYXNzZXIgZWZmZWN0cw0KDQpUaGUgc2Vjb25kIG1vZGVsIHRoYXQgSSB0ZXN0ZWQgaXMgYSBtaXhlZCBlZmZlY3RzIG1vZGVsIHdpdGggYSByYW5kb20gZWZmZWN0IGludGVyY2VwdC4gVGhlIHJhbmRvbSBlZmZlY3QgaW4gdGhlIGZvcm11bGEgKHRoZSAoMSB8IFBsYXllcikgdGVybSkgaGFzIHRoZSBtb2RlbCBldmFsdWF0ZSBlYWNoIHBsYXllciBhZ2FpbnN0IHRoZWlyIG93biBiYXNlbGluZSBhdmVyYWdlLCByYXRoZXIgdGhhbiByZWxhdGl2ZSB0byB0aGUgb3ZlcmFsbCBwb3B1bGF0aW9uLiAgICAgICAgICAgICAgICAgICAgDQoNClRoZSBtYWpvciBjb21wb25lbnRzIG9mIG15IG1peGVkIGVmZmVjdHMgbW9kZWwgYXJlIHRoZSBzYW1lIGFzIHRoZSBHQU0gSSB1c2VkIGVhcmxpZXIsIHdpdGggdGhlIHNvbGUgYWRkaXRpb24gb2YgdGhlIHJhbmRvbSBlZmZlY3QgcGFyYW1ldGVyICgxIHwgUGxheWVyKS4gVGhlIHBhc3Mgc3RhcnQgYW5kIGludGVuZGVkIGxvY2F0aW9uLCBkaXJlY3Rpb24sIGFuZCBsZW5ndGggYWxsIHJlbWFpbiBpbiB0aGUgbW9kZWwuICAgICAgICAgICAgICAgICAgICAgIA0KDQpPbmNlIHRoZSBtb2RlbCBoYXMgYmVlbiBydW4sIHdlIGNhbiBwdWxsIG91dCB0aGUgaW50ZXJjZXB0cyBmb3IgZWFjaCB1bmlxdWUgcGxheWVyIHRvIHNlZSB3aG8gaW5jcmVhc2VzIHRoZSBsaWtlbGlob29kIG9mIGEgc3VjY2Vzc2Z1bCBwYXNzIHRoZSBtb3N0IChhIHBvc2l0aXZlIGludGVyY2VwdCA9IGJldHRlciBwYXNzZXIgYnkgdGhpcyBtZWFzdXJlKS4gQXMgd2l0aCBvdXIgQ1BPRSBtZWFzdXJlLCB0aGUgbWl4ZWQgZWZmZWN0cyBtb2RlbCBhbGxvd3MgdXMgdG8gY3JlYXRlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvciB0aGUgZWZmZWN0IG9mIGVhY2ggcGxheWVyLg0KDQpgYGB7cn0NCnNldC5zZWVkKDMzMykNCnBhc3NfZWZmZWN0IDwtIGdsbWVyKHN1Y2Nlc3MgfiAoMSB8IFBsYXllcikgKyBYLkNvb3JkaW5hdGUgKyBZLkNvb3JkaW5hdGUgKyBYLkNvb3JkaW5hdGUuMiArIFkuQ29vcmRpbmF0ZS4yICsNCiAgICAgICAgICAgICAgICAgICAgICBEaXJlY3Rpb24gKyBMZW5ndGgsIGRhdGEgPSBwYXNzZXMsIGZhbWlseSA9ICJiaW5vbWlhbCIpDQojc3VtbWFyeShwYXNzX2VmZmVjdCkNCmBgYA0KDQpgYGB7cn0NCnJhbmRvbXMgPC0gcmFuZWYocGFzc19lZmZlY3QsIGNvbmRWYXIgPSBUUlVFKSRQbGF5ZXINCnFxIDwtIGF0dHIocmFuZWYocGFzc19lZmZlY3QsIGNvbmRWYXIgPSBUUlVFKSRQbGF5ZXIsICJwb3N0VmFyIikgDQpyYW5kLmludGVyY2VwdCA8LSByYW5kb21zWywgMV0NCg0KcGFzc19yYW5kZWZzIDwtIGRhdGEuZnJhbWUocmVfSW50ZXJjZXB0cyA9IHJhbmRvbXNbLCAxXSwNCiAgICAgICAgICAgICAgICAgICAgIHJlX3NkLmludGVyYyA9IDIqc3FydChxcVssLCAxOmxlbmd0aChxcSldKSwNCiAgICAgICAgICAgICAgICAgICAgIE5hbWVzID0gcm93bmFtZXMocmFuZG9tcykpDQoNCnBhc3NfcmFuZGVmcyROYW1lcyA8LSBmYWN0b3IocGFzc19yYW5kZWZzJE5hbWVzLCBsZXZlbHMgPSBwYXNzX3JhbmRlZnMkTmFtZXNbb3JkZXIocGFzc19yYW5kZWZzJHJlX0ludGVyY2VwdHMpXSkNCnBhc3NfcmFuZGVmcyA8LSBwYXNzX3JhbmRlZnNbb3JkZXIocGFzc19yYW5kZWZzJHJlX0ludGVyY2VwdHMpLF0NCg0KcGFzc19yYW5kZWZzIDwtIHBhc3NfcmFuZGVmcyAlPiUNCiAgbXV0YXRlKHJlX21pbiA9IHJlX0ludGVyY2VwdHMgLSByZV9zZC5pbnRlcmMsDQogICAgICAgICByZV9tYXggPSByZV9JbnRlcmNlcHRzICsgcmVfc2QuaW50ZXJjKQ0KYGBgDQoNCmBgYHtyfQ0KbWluX3BlIDwtIHBhc3NfcmFuZGVmcyAlPiUNCiAgZmlsdGVyKE5hbWVzICVpbiUgbmFtZXMpDQoNCmFsbF9kYXRhIDwtIHJpZ2h0X2pvaW4oYWxsX2RhdGEsIG1pbl9wZSwgYnkgPSBjKCJQbGF5ZXIiID0gIk5hbWVzIikpDQoNCnAzIDwtIGFsbF9kYXRhICU+JQ0KICBnZ3Bsb3QoKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBuLCB5ID0gcmVfc2QuaW50ZXJjKSkgKw0KICBsYWJzKHggPSAiUGFzc2VzIiwgeSA9ICJJbnRlcmNlcHQgQ0kiLCB0aXRsZSA9ICJJbnRlcmNlcHQgQ0kgdnMgUGFzcyBBdHRlbXB0cyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSkNCiNhZ2Fpbiwgc3Ryb25nIHJlbGF0aW9uc2hpcCBidCBtb3JlIG9ic2VydmF0aW9ucyBhbmQgbG93ZXIgc3RhbmRhcmQgZGV2aWF0aW9ucyBmb3IgdGhlIGVmZmVjdCBvZiBhIHBhc3Nlcg0KDQpwNCA8LSBhbGxfZGF0YSAlPiUNCiAgZ2dwbG90KCkgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gbiwgeSA9IHJlX0ludGVyY2VwdHMpKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgbGFicyh4ID0gIlBhc3NlcyIsIHkgPSAiSW50ZXJjZXB0IiwgdGl0bGUgPSAiUGFzc2VyIEVmZmVjdCB2cyBQYXNzIEF0dGVtcHRzIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpKQ0KDQpsMiA8LSAocDQgKyBwMykNCmBgYA0KDQpgYGB7ciwgZmlnLmhlaWdodD05LCBmaWcud2lkdGg9OX0NCmFsbF9kYXRhICU+JQ0KICBhcnJhbmdlKHJlX0ludGVyY2VwdHMpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3IoUGxheWVyLCBsZXZlbCA9IFBsYXllciksIHkgPSByZV9JbnRlcmNlcHRzKSkgKw0KICBnZW9tX3BvaW50cmFuZ2UoYWVzKHltaW4gPSByZV9taW4sIHltYXggPSByZV9tYXgsIGNvbG9yID0gcmVfSW50ZXJjZXB0cyksIHNpemUgPSAxLjYpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICBsYWJzKHggPSAiUGxheWVyIiwgdGl0bGUgPSAiTWVhc3VyaW5nIHRoZSBFZmZlY3Qgb2YgTldITCBQYXNzZXJzIG9uIFBhc3MgU3VjY2VzcyIsDQogICAgICAgeSA9ICJSYW5kb20gRWZmZWN0IEludGVyY2VwdCIsIHN1YnRpdGxlID0gIlBvc2l0aXZlIEludGVyY2VwdCBtZWFucyBQYXNzZXIgSW5jcmVhc2VzIFN1Y2Nlc3MlIiwNCiAgICAgICBjYXB0aW9uID0gIkJlbiBIb3dlbGwgfCBAYmVuaG93ZWxsNzEgfCBiZW5ob3dlbGw3MS5jb20iLA0KICAgICAgIGxhYmVsID0gIkVmZmVjdCIpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdyA9ICgiYmx1ZSIpLCBtaWQgPSAiZ3JleSIsIG1pZHBvaW50ID0gMCwgaGlnaCA9ICgicmVkIiksDQogICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkVmZmVjdCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE1LCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTIpLA0KICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSA5KSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSkNCmBgYA0KDQpOb3cgdGhhdCB3ZSd2ZSBnb25lIHRocm91Z2ggdGhlIHR3byBtZXRob2RzIHRoYXQgSSB1c2VkIHRvIHRyeSBhbmQgbWVhc3VyZSBwYXNzaW5nIHNraWxsIGluIHRoZSBOV0hMLCBsZXQncyBjb21wYXJlIHRoZW0hIChUaGVyZSdzIGdvaW5nIHRvIGJlIHNvbWUgd29yZHMgaGVyZSwgYnV0IHlvdSBjYW4gc2Nyb2xsIGRvd24gdG8gZmluZCB0aGUgZnVsbCByZXN1bHRzIGFuZCBsZWFkZXIgYm9hcmQgYXQgdGhlIGVuZCBvZiB0aGUgYXJ0aWNsZS4pICAgICAgICAgICAgICAgICAgICAgDQoNClRoZXJlIHR1cm5lZCBvdXQgdG8gYmUgYSBzdHJvbmcgcmVsYXRpb25zaGlwIChSIG9mIDAuODMpIGJldHdlZW4gQ1BPRSByYW5rIGFuZCBQYXNzZXIgRWZmZWN0IHJhbmsuIEluIG1vc3QgY2FzZXMsIGJlaW5nIGEgZ29vZCBwYXNzZXIgYnkgZWl0aGVyIENQT0Ugb3IgYnkgUGFzc2VyIEVmZmVjdCBtZWFucyB0aGF0IGEgcGxheWVyIGlzIHByb2JhYmx5IGEgZ29vZCBwYXNzZXIgaW4gdGhlIG90aGVyLiBIb3dldmVyLCB0aGVyZSBhcmUgc29tZS4uLmludGVyZXN0aW5nIGNhc2VzIGFuZCBkaXNjcmVwYW5jaWVzIGJldHdlZW4gdGhlIHR3bywgbW9zdCBub3RhYmx5IHdpdGggSm9ubmEgQ3VydGlzLCBhIGZvcndhcmQgd2l0aCB0aGUgTWlubmVzb3RhIFdoaXRlY2FwcyB3aG8gaGFkIDk2IHBhc3MgYXR0ZW1wdHMuIEl0J3MgYW4gaW50ZXJlc3RpbmcgZGlzY3JlcGFuY3kgYW5kIG9uZSB0aGF0IG1heSBiZSB3b3J0aCBleHBsb3JpbmcgbW9yZSBpbi1kZXB0aCAob3IgaXQgY291bGQgYmUgYSBzbWFsbCBzYW1wbGUgcXVpcmspLiANCg0KYGBge3J9DQphbGxfZGF0YSA8LSBhbGxfZGF0YSAlPiUNCiAgYXJyYW5nZShkZXNjKG1lYW5fY3BvZSkpICU+JQ0KICBtdXRhdGUobWVhbl9jcG9lX3JhbmsgPSByb3dfbnVtYmVyKCkpICU+JQ0KICBhcnJhbmdlKGRlc2MocmVfSW50ZXJjZXB0cykpICU+JQ0KICBtdXRhdGUoaW50ZXJjZXB0X3JhbmsgPSByb3dfbnVtYmVyKCkpDQoNCnZhbCA8LSByb3VuZChjb3IoYWxsX2RhdGEkbWVhbl9jcG9lX3JhbmssIGFsbF9kYXRhJGludGVyY2VwdF9yYW5rKSwgZGlnaXRzID0gMikNCiNzdHJvbmcgcmVsYXRpb25zaGlwIGJldHdlZW4gbWVhbiBDUE9FIGFuZCB0aGUgcGFzc2VyIGVmZmVjdA0KDQphbGxfZGF0YSAlPiUNCiAgZ2dwbG90KCkgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gbWVhbl9jcG9lX3JhbmssIHkgPSBpbnRlcmNlcHRfcmFuaywgY29sb3IgPSBtZWFuX2Nwb2UpLCBzaXplID0gNCkgKw0KICBsYWJzKHggPSAiTWVhbiBDUE9FIFJhbmsiLCB0aXRsZSA9ICJDb21wYXJpbmcgTWVhbiBDUE9FIGFuZCBQYXNzZXIgRWZmZWN0IFJhbmtzIiwNCiAgICAgICB5ID0gIlJhbmRvbSBFZmZlY3QgSW50ZXJjZXB0IFJhbmsiLA0KICAgICAgIGNhcHRpb24gPSAiQmVuIEhvd2VsbCB8IEBiZW5ob3dlbGw3MSB8IGJlbmhvd2VsbDcxLmNvbSIpICsNCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIGdlb21fdGV4dChhZXMoeCA9IDYsIHkgPSAzNSwgbGFiZWwgPSBwYXN0ZTAoIkNvcjogIiwgdmFsKSksIHNpemUgPSA1LCBmb250ZmFjZSA9ICJpdGFsaWMiKSArDQogIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAoImJsdWUiKSwgbWlkID0gImdyZXkiLCBtaWRwb2ludCA9IDAsIGhpZ2ggPSAoInJlZCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJNZWFuIENQT0UiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNSwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxMiksDQogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDkpKQ0KYGBgDQoNCkluIGNvbnRyYXN0IHRvIG91ciBDUE9FIG1ldHJpYywgdGhlIFBhc3NlciBFZmZlY3QgaW50ZXJjZXB0IGRvZXMgbm90IGNvbnZlcmdlIGFzIGRyYXN0aWNhbGx5IHRvIHplcm8uIEkgZGlkIGZpbmQgaXQgaW50cmlndWluZyB0aGF0IGV2ZXJ5b25lIHdpdGggbW9yZSB0aGFuIDEyNSBkaXJlY3QgcGFzc2VzIGluY3JlYXNlZCB0aGUgY2hhbmNlIG9mIGEgc3VjY2Vzc2Z1bCBwYXNzOyB0aGlzIGNvdWxkIGltcGx5IHRoYXQgdGhlIGJldHRlciBhIHBhc3NlciB5b3UgYXJlLCB0aGUgbW9yZSBwYXNzZXMgdGhhdCB5b3UgbWFrZS4gSG93ZXZlciwgdGhpcyBjb3VsZCBhbHNvIGJlIGEgcXVpcmsgb2Ygb3VyIHNtYWxsIHNhbXBsZSBzaXplLiAgICAgICAgICAgICAgICAgIA0KDQpBcyB3aXRoIENQT0UsIHRoZXJlIGlzIGEgc3Ryb25nIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGF0dGVtcHRpbmcgbW9yZSBwYXNzZXMgYW5kIGhhdmluZyBhIHNtYWxsZXIgY29uZmlkZW5jZSBpbnRlcnZhbCBvbiBhIHBsYXllcidzIGludGVyY2VwdC4gICAgICAgICAgICAgIA0KDQpgYGB7cn0NCnRlc3QgPC0gYWxsX2RhdGEgJT4lIA0KICBmaWx0ZXIobiA+PSA3NSkNCg0KbWluMiA8LSBtaW4odGVzdCRyZV9JbnRlcmNlcHRzKQ0KbWF4MiA8LSBtYXgodGVzdCRyZV9JbnRlcmNlcHRzKQ0KDQp0YmwyIDwtIGFsbF9kYXRhICU+JSANCiAgZmlsdGVyKG4gPj0gNzUpICU+JSANCiAgYXJyYW5nZShkZXNjKENQT0UpKSAlPiUNCiAgbXV0YXRlKHJlX0ludGVyY2VwdHMgPSByb3VuZChyZV9JbnRlcmNlcHRzLCBkaWdpdHMgPSAzKSkgJT4lDQogIGRwbHlyOjpzZWxlY3QoUGxheWVyLCBuLCBDUCwgeENQLCBDUE9FLCByZV9JbnRlcmNlcHRzKSAlPiUNCiAgcmVhY3RhYmxlKA0KICAgIHBhZ2luYXRpb24gPSBGQUxTRSwNCiAgICBoaWdobGlnaHQgPSBUUlVFLA0KICAgIHN0cmlwZWQgPSBUUlVFLA0KICAgIGRlZmF1bHRDb2xEZWYgPSBjb2xEZWYoDQogICAgYWxpZ24gPSAiY2VudGVyIiwgbWluV2lkdGggPSAyNSwgaGVhZGVyQ2xhc3MgPSAiaGVhZGVyIiwgaGVhZGVyU3R5bGUgPSBsaXN0KGZvbnRXZWlnaHQgPSA3MDApDQogICksDQogIGNvbHVtbkdyb3VwcyA9IGxpc3QoDQogICAgY29sR3JvdXAobmFtZSA9ICJSZXN1bHRzIiwgY29sdW1ucyA9IGMoIkNQIiwgInhDUCIsICJDUE9FIiwgInJlX0ludGVyY2VwdHMiKSkNCiAgKSwNCiAgdGhlbWUgPSByZWFjdGFibGVUaGVtZSgNCiAgICBoZWFkZXJTdHlsZSA9IGxpc3QoDQogICAgICAiJjpob3ZlclthcmlhLXNvcnRdIiA9IGxpc3QoYmFja2dyb3VuZCA9ICJoc2woMCwgMCUsIDk2JSkiKSwNCiAgICAgICImW2FyaWEtc29ydD0nYXNjZW5kaW5nJ10sICZbYXJpYS1zb3J0PSdkZXNjZW5kaW5nJ10iID0gbGlzdChiYWNrZ3JvdW5kID0gImhzbCgwLCAwJSwgOTYlKSIpLA0KICAgICAgYm9yZGVyQ29sb3IgPSAiIzU1NSINCiAgICApKSwNCiAgY29sdW1ucyA9IGxpc3QoDQogICAgbiA9IGNvbERlZigNCiAgICAgIG5hbWUgPSAiUGFzc2VzIiwNCiAgICAgIGNsYXNzID0gImJvcmRlci1sZWZ0Ig0KICAgICksDQogICAgcmVfSW50ZXJjZXB0cyA9IGNvbERlZigNCiAgICAgIG5hbWUgPSAiUGFzc2VyIEVmZmVjdCIsDQogICAgICBzdHlsZSA9IGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgICAgIHZhbHVlDQogICAgICAgIG5vcm1hbGl6ZWQgPC0gKHZhbHVlIC0gbWluMikgLyAobWF4MiAtIG1pbjIpDQogICAgICAgICNub3JtYWxpemVkIDwtICh2YWx1ZSAtIG1pbihwaXRjaF90eXBlJFJWMTAwKSkgLyAobWF4KHBpdGNoX3R5cGUkUlYxMDApIC0gbWluKHBpdGNoX3R5cGUkUlYxMDApKQ0KICAgICAgICBjb2xvciA8LSBjb2xvcihub3JtYWxpemVkKQ0KICAgICAgICBsaXN0KGJhY2tncm91bmQgPSBjb2xvcikNCiAgICAgIH0NCiAgICApLA0KICAgIENQT0UgPSBjb2xEZWYoDQogICAgICBuYW1lID0gIkNQT0UiLA0KICAgICAgc3R5bGUgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICB2YWx1ZQ0KICAgICAgICBub3JtYWxpemVkIDwtICh2YWx1ZSAtIG1pbikgLyAobWF4IC0gbWluKQ0KICAgICAgICAjbm9ybWFsaXplZCA8LSAodmFsdWUgLSBtaW4ocGl0Y2hfdHlwZSRSVjEwMCkpIC8gKG1heChwaXRjaF90eXBlJFJWMTAwKSAtIG1pbihwaXRjaF90eXBlJFJWMTAwKSkNCiAgICAgICAgY29sb3IgPC0gY29sb3Iobm9ybWFsaXplZCkNCiAgICAgICAgbGlzdChiYWNrZ3JvdW5kID0gY29sb3IpDQogICAgICB9DQogICAgKSwNCiAgICBQbGF5ZXIgPSBjb2xEZWYoDQogICAgICBuYW1lID0gIlBsYXllciIsIHdpZHRoID0gMTc1LCByZXNpemFibGUgPSBGQUxTRQ0KICAgICkNCiAgKQ0KKQ0KYGBgDQoNCmBgYHtyfQ0KbGF5b3V0IC8gbDINCmBgYA0KDQoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqDQoNCiMgTGVhZGVyYm9hcmQgYW5kIEZ1bGwgUmVzdWx0cw0KDQpCZWxvdyBpcyBhIGZ1bGwgdGFibGUgdGhhdCBjb21wYXJlcyBDUCwgeENQLCBDUE9FLCBhbmQgUGFzc2VyIEVmZmVjdCBmb3IgdGhlIDIwMjEgTldITCBza2F0ZXJzIHdobyBhdHRlbXB0ZWQgYXQgbGVhc3QgNzUgcGFzc2VzIGluIHRoZSAyMDIxIHNlYXNvbiArIGEgcnVuZG93biBvZiBzb21lIG9mIHRoZSByZXN1bHRzIEkgZm91bmQgaW50ZXJlc3RpbmcuICAgICAgICAgICAgICANCg0KS2FsZWlnaCBGcmF0a2luICh0aGUgMjAyMSBEZWZlbmRlciBvZiB0aGUgWWVhcikgd2hvIGhhZCA5IGFzc2lzdHMsIGZhcmVkIG11Y2ggYmV0dGVyIGluIHRoZSBQYXNzZXIgRWZmZWN0IG1ldHJpYyAocmFua2luZyAzcmQpIHdoaWxlIHJhbmtpbmcgMTF0aCBpbiBDUE9FLiBIZXIgeENQIGhhcyBvbiB0aGUgaGlnaGVyIHNpZGUgYW5kLCBmb3IgaG93IGhpZ2ggaGVyIHhDUCBpcywgaGVyIENQT0UgaXMgcmVhbGx5IGdvb2QhIEl0J3MganVzdCBoYXJkIHRvIGltcHJvdmUgb24gYWxyZWFkeSBoaWdoIHhDUCBwYXNzZXMuIFRoZSBoaWdoIFBhc3NlciBFZmZlY3QgZG9lcyBpbmRpY2F0ZSB0aGF0IGhlciBwcm9jbGl2aXR5IHRvIGhhdmUgaGlnaCB4Q1AgcGFzc2VzIGNvdWxkIGJlIGJlY2F1c2Ugc2hlJ3MgYW4gZXhjZWxsZW50IHBhc3NlciEgICAgICAgICAgICAgICAgIA0KDQpNaWt5bGEgR3JhbnQtTWVudGlzICh0aGUgMjAyMSBNVlApIHdhcyBhYm92ZSBhdmVyYWdlIGluIGJvdGggQ1BPRSBhbmQgUGFzc2VyIEVmZmVjdCwgYnV0IGRpZG4ndCBwb3AgYXQgdGhlIHRvcCBvZiBlaXRoZXIgbGVhZGVyIGJvYXJkLiBNY0tlbm5hIEJyYW5kIHJhbmtlZCAybmQgaW4gYm90aCBDUE9FIGFuZCBQYXNzZXIgRWZmZWN0LCB3aGljaCBtZXNoZXMgd2VsbCB3aXRoIFRyZWlzbWFuJ3MgZmluZGluZ3Mgb24gQnJhbmQgbGVhZGluZyB0aGUgTldITCBpbiBoaXMgcGxheS1tYWtpbmcgYWJpbGl0eSBtZXRyaWMuDQoNCmBgYHtyfQ0KZGl2KA0KICBjbGFzcyA9ICJzdGFuZGluZ3MiLA0KICBkaXYoY2xhc3MgPSAidGl0bGUiLA0KICAgIGgyKCJOV0hMIENQT0UgKENvbXBsZXRpb24gUGVyY2VudGFnZSBPdmVyIEV4cGVjdGVkKSBhbmQgUGFzc2VyIEVmZmVjdHMiKSksDQogIGRpdihjbGFzcyA9ICJzdWJ0aXRsZSIsDQogICAgaDQoIk1pbmltdW0gNzUgcGFzc2VzIGluIDIwMjEgc2Vhc29uIikNCiAgKSwNCiAgdGJsMg0KKQ0KYGBgDQoNCmBgYHtyfQ0KIyBvcHRpb25zKFdvcmRwcmVzc0xvZ2luID0gYygiQmVuSG93ZWxsIiA9ICdOYW9taTEyMygpJyksDQojICAgICAgICAgV29yZHByZXNzVVJMID0gJ2h0dHA6Ly9iZW5ob3dlbGw3MS5jb20veG1scnBjLnBocCcpDQojIA0KIyBrbml0MndwKCdud2hsX2Nwb2UuUm1kJywgdGl0bGUgPSAnTWVhc3VyaW5nIFBhc3NpbmcgU2tpbGwgaW4gdGhlIE5XSEwnLCBwdWJsaXNoID0gRkFMU0UsDQojICAgICAgICAgYWN0aW9uID0gIm5ld1Bvc3QiKQ0KYGBgDQoNCg==