Introduction

This is going to be a bit of a of an attempt to talk you through and train you at the same time on how to create a markdown report.

You run a markdown by ‘knit’ ing it. There is literally an icon with a ball of wool with a knitting needle in it. That is the button we need and it knits together all the markdown stuff and r code into one super snazzy output.

Will get you to knit the report and see the results and then we will pick apart the code and see how it is done behind the scenes.

If you have 2 screens try to have the code on one side and the report on the other and you can look side by side at what is happening.

I will also be presenting and you can look at me to follow as well.

How many times have you wanted to create a report that has the beauty and readability of a word document but want to add interactive graphs and functionality of a excel filtered table or even a pivot table?

If only there was a way you could pull your data, wrangle it and then finally get it to produce a beautiful report, all in one process.

If only…

If only…

Hang on! Sounds really complicated and difficult and need lots of tricky code. Have we not been telling you how brilliant R is?

Introducing

MarkdownIcon

You can import images, either from the web or from a local directory - this one is from the web and it is massive! You can see above you can also insert animated gifs.
(I fear what I have done to the NHS by releasing that knowledge into the wild - I take no responsibility for any repercussions of animated nyan cat reports.)

R Markdown

This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.

Word and PDF reports are fine and you can do some very pretty but flat reports in these outputs. Thats fine but the cool kats and kitties want interactive and flashy.

When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document.

You may notice the nice floating contents page to the left. This is created in the YAML header at the very start of the document. YAML stands for YAML Ain’t Markup Language. It sets some global parameters and can do some cool stuff. You set the headings as per the next section and the document automatically picks up those with a single ‘#’.

So what can you do?

Markdown formatting

You can play with headers that get smaller

You can play with headers - and smaller

You can play with headers - and smaller

You can play with headers - and smallest

You can make a line make a line break


You can do all the normal italics and bold and superscript and strike-though

Things like block quotes look funky
especially if you put a few together
make sure you end your sentences with 2
spaces to start a new paragraph

Other things that are easy

  • lists
  • putting stuff in lists
    • putting stuff in sub lists
    • such as this
  • did I say lists?

You can also do numbered lists

  1. Like this
  2. Fine example of a list
    • and do sub lists in a numbered list
      1. and do sub sub lists
        A. and sub sub sub list

Write some stuff in the middle of your list

  1. and then go back to the list
  2. NOTE: the numbers in the list are not specified, they are dynamic and if you go and edit one out it will adjust them automatically

You can colour in a block to assist with highlighting an area.

  • This is my first conclusion
  • This is my second conclusion

You can add footnotes1

You can also do basic dynamic tables just in markdown - looks messy in the code, pretty in the markdown and thanks to the power of HTML, they re-size according to the screen, all of these tables and charts are mobile friendly.

Column heading one Second column heading
Stuff Column 2 stuff
Another row of stuff More column 2 stuff

You can align the stuff in these tables but they don’t work well with numbers

Right Left Default Centre
blurb right aligned blurb left aligned blurb default blurb in da centre
1234 56788 4545644 43535
34.2 3442.1 3421.1 4512.45

You can also play with HTML tags to change font to comic sans

Just because you can does not mean you should!

Tabsets

Tabsets are great for creating nice interactive documents and reducing the length of your document but still cramming in loads of extra data without your reader realising it.

If you look at the code you can see that you can add a little fade to give your report a little extra sparkle or you can leave it for extra zip. I am using a bit of fade sparkle for this example

Results by provider

Provider code RXQ

Blah blah blah super important commentary about the blue line going up.

Provider code RJ1

Oh my - the red line is going up, no one wants to see a red line going up. Must remember to RAG rate this later and add a sad smiley face, pretty sure there will be a lesson on how to do that later.

Provider code RYJ

-insert witty commentary here-

That is the basic text formatting stuff, but we want to do clever things and incorporate our data

Adding some data

We are going to use the NHR-R sample data set and use the AE attendances data. This has a date, a organisation code, a type, number for attendances, admissions and breaches.

You can include data within the markdown specifically within the text by doing a back tick r and entering a variable or formula (you can also format it into a nice readable number).

For example the total number of attendances from the data set is 8,295,237

The date of 07 October 2022 is when you pressed the knit button report.

You can also add ‘code chunks’, these are chunks of code that sit within your markdown document.

So here is a the base way to include some data you simple do triple back ticks to tell R studio that now you want to do some R stuff.

This will print the summary of the AE attendnace* data set in a not very pretty table

* just noticed a typo in ‘attendance’ - R studio does have a spell check feature - remember to use it as not automatic, no wavy red lines like word!**
** you also have to do backslash asterisk when you actually want to use an asterisk

## # A tibble: 9 × 6
##   period     org_code type  attendances breaches admissions
##   <date>     <fct>    <fct>       <dbl>    <dbl>      <dbl>
## 1 2019-03-01 RF4      other       10289       90          0
## 2 2019-02-01 RF4      other        9643       87          0
## 3 2019-01-01 RF4      other       10424       77          0
## 4 2018-12-01 RF4      other        9460       95          0
## 5 2018-11-01 RF4      other        8264       30          0
## 6 2018-10-01 RF4      other        7900       14          0
## 7 2018-09-01 RF4      other        7604       39          0
## 8 2018-08-01 RF4      other        7184       73          0
## 9 2018-07-01 RF4      other        5072       10          0

Library - Kable

Basic but by no means pretty, we can use the kable package to make a prettier table, in just 2 lines of code you can produce this, which has better readability and a nice reading hover over.

period org_code type attendances breaches admissions
2019-03-01 RF4 other 10289 90 0
2019-02-01 RF4 other 9643 87 0
2019-01-01 RF4 other 10424 77 0
2018-12-01 RF4 other 9460 95 0
2018-11-01 RF4 other 8264 30 0
2018-10-01 RF4 other 7900 14 0
2018-09-01 RF4 other 7604 39 0
2018-08-01 RF4 other 7184 73 0
2018-07-01 RF4 other 5072 10 0

The kable package to make a prettier table, indent rows and colour it in and change formats, add sub headings and is quite simple to use.

period org_code type attendances breaches admissions
sub heading and indent first 3 rows
2019-03-01 RF4 other 10289 90 0
2019-02-01 RF4 other 9643 87 0
2019-01-01 RF4 other 10424 77 0
2018-12-01 RF4 other 9460 95 0
2018-11-01 RF4 other 8264 30 0
2018-10-01 RF4 other 7900 14 0
2018-09-01 RF4 other 7604 39 0
2018-08-01 RF4 other 7184 73 0
2018-07-01 RF4 other 5072 10 0

Kable is really good for a static and pretty, but we want interactive.

Library - DT (short for data table)

This is a DT datatable - has lovely filters on the periods and different columns. You can re order the data and show as much or as little as you like. The export buttons export what you have selected. There is also a search function for the data.

You can mess around with the defaults so that it shows a larger table.

DT Datatable is pretty good and quick, even the base default comes up with a pretty good table. It is very nice at presenting a flat table, but if you want calculations and totals , you have to hard code them into your table.

That is one format or if you want more summary type reports you can use reactable.

Library - Reactable

This is reactable, and it works a little more like a filtered and sub grouped table. It is a bit trickier to use, but seems to be able to all the stuff of data table and a bit more.

Reactable is really good at creating summaries and drill down datasets. It creates all the groupings of data itself and so you do not have to wrangle the data into groups before you make the table. You can also create high level aggregate functions on a group and have the ability to drill down to see the underlying data.

Reactable has many more functions than a DT datatable but as I said, is a little more tricky to use.

You can use it to do funky stuff like this, I see your spark lines excel and raise you spark box plots! (and conditional formatting)

(Want to be super impressed? Hover over the spark box)


Lets get plotting…


Of course we can add a plot, you can change the size, alignment and all of that stuff. You can wrap your text around a plot and potentially have plots side by size.

You need to switch to the code here for a little funky plotting short cut.

Library - esquisse

So that’s a plot, does what it says on the tin, but what is better than a static plot?

Interactive plots…

Library - plotly

  • You can click on the legend to add or remove line
  • You can click and drag an area to zoom in on
  • You can hover over line to see data points
  • You can export as an image

All is far more customisable within the plotly function, you can have multiple select-able data sets and all manner of other stuff.

Animated graphs

Pretty cool but lets show off and animate

Obviously pretty pointless in this example, but may be good as a way to be more visual to get a point across.

If it gets people actually looking at the data and wanting their little wiggly lines going up that has to be good for patient care.

Library - dygraphs

So how about we take the admissions data for the providers above and create a nice time series graph. This DY graph is nice for playing with time series as it allows you to zoom in on certain areas.

There is also a nice little box on the bottom left of the graph. This allows you to smooth your data with a rolling average on the fly. Really useful for things such as length of stay or things with lots of variablity and trying to pull out an overall trend.

Other good functions for visualising data sets.

Library - Treemap

One is treemap, it is like a posh pie chart for looking at proportions of a variable.

Obviously R can do pie charts, but I whereas I am willing to show you how add animated gifs into your reports, even I would not sink that low.

This is a nice overview of a large amount of data, gets a bit messy when you have a lot of factors

Library - collapsibleTree

Another really cool thing to play with is a dendrogram which you can make with collapsibleTree.

This is really good at showing flow through pathways and systems. You can make them horizontal or vertical and play with all manner of bits on the nodes.

Click on the nodes and you can also zoom in and out and scroll around.

I also find it really relaxing for some reason.

Library - Leaflet

Leaflet is a great mapping library and works with open street map so you don’t have to worry about google API tokens and the like. There are some fantastic things you can do with the google service which allows you to access travel times and route finding, however for simple mapping leaflet is great. You can do heatmaps and areas, draw lines across points and also add layers that you can select on and off.

This example has 3 teams that are set up as layers and youcan turn each one on and off.

The maps can be scrolled and zoomed, what is nice is the icons remain to scale.

Library - Wordcloud2

Wordcloud2 is the sequel to wordcloud, much like Evil Dead 2 to the original, it is a far superior product, it has some really nice easy to use features and can make all manner of different wordclouds types.

However before you get to a word cloud you need some data which is basically a list of words and their frequency. You can do this manually on your fingers or you can get R to do this for you. I definately recommend the latter.

To get to that you read in some data, strip out all the gubbins such as punctuation, remove all the ‘stop words’ such as ‘the’ and ‘and’ etc and then remove white space and there you have a bunch of words fit for a cloud.

This is an example that pulls the text from a popular childrens novel and creates a cloud. Hopefully you can guess the book from the cloud.

You can hover over the words in the cloud and it will tell you the word and give you the number of the frequency.

Library - Rpivottable

Saving perhaps my favorite until last, is the super awesome Rpivottable.

This has full click and drag functionality as well the option to set up defaults in the report and also you can click through, create charts and heat maps, filter your data, calculate a pivot table with a median and just do all sorts of magic.

You can click and drag the variables around. You can click on the arrows to the side of the variables to filter them. You can click on the count to select a different metric and finally you can click on the table to change the results to a graph or heatmap or loads of things.

It doesn’t like super huge data sets if you are running it locally but if you get clever with shiny, you can do big things.

It also has a habbit of overlapping with stuff below it. I am working on a HTNL solution to this and I think this is a ‘feature’ that is being worked on by the developers. I usually just add it at the end of a report or on a seperate tab to get around this issue.

This whole functionality is done with one line of code. (!!!)

Thats all folks

Please feel free to hack and steal share best practice from this report.

Some really nice visualisation tips can be found at

https://www.data-to-viz.com/caveats.html

and some more markdown tips at

https://holtzy.github.io/Pimp-my-rmd/

Other that I wish you well on your R journey and please do not hesiatte to contact me if you have found any interesting things to share

Merry markdowning

Contact


  1. This is the footnote from the footnote added way way up above↩︎

LS0tDQp0aXRsZTogIlIgTWFya2Rvd24gVHJhaW5pbmciDQphdXRob3I6ICJTaW1vbiBXZWxsZXNsZXktTWlsbGVyIg0KZGF0ZTogIjA5LzA3LzIwMjAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobyA9IEZBTFNFKQ0KDQojIyBjaGFuZ2UgdGhlIGVjaG8gdG8gVFJVRSB0byBzaG93IHRoZSBSIGNvZGUgaW4gdGhlIGRvY3VtZW50DQojIyBoYXZpbmcgaXQgc2hvd2luZyBpcyByZWFsbHkgdXNlZnVsIHdoZW4gYnVpbGRpbmcgYSByZXBvcnQgYXMgaXQgaGVscHMgd29ya2luZyBvdXQgd2hhdCBiaXQgaXMgZG9pbmcgd2hhdA0KIyMgeW91IGNhbiByZWFsbHkgZ2V0IGluIHRvIGEgcmFiaXQgaG9sZSBvZiB0aGUgUiAgLyBNYXJrZG93biBjb2RlIGxvb2tpbmcgbm90aGluZyBsaWtlIHRoZSBvdXRwdXQNCg0KDQojI3VzdWFsbHkgZ2dvZCBwcmFjdGljZSB0byBsb2FkIGFsbCB5b3VyIGxpYnJhcnlzIGF0IHRoZSBzdGFydA0KDQpsaWJyYXJ5KE5IU1JkYXRhc2V0cykNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShrYWJsZUV4dHJhKQ0KbGlicmFyeShyZWFjdGFibGUpDQpsaWJyYXJ5KGVzcXVpc3NlKQ0KbGlicmFyeShycGl2b3RUYWJsZSkNCmxpYnJhcnkobGVhZmxldCkNCmxpYnJhcnkoRFQpDQpsaWJyYXJ5KHNwYXJrbGluZSkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KHRyZWVtYXApDQpsaWJyYXJ5KGNvbGxhcHNpYmxlVHJlZSkNCmxpYnJhcnkodGlkeWdlb2NvZGVyKQ0KbGlicmFyeShsZWFmbGV0KQ0KbGlicmFyeSh3aWRnZXRmcmFtZSkNCmxpYnJhcnkoInRtIikNCmxpYnJhcnkoIlNub3diYWxsQyIpDQpsaWJyYXJ5KCJ3b3JkY2xvdWQyIikNCmxpYnJhcnkoIlJDb2xvckJyZXdlciIpDQpsaWJyYXJ5KGR5Z3JhcGhzKQ0KbGlicmFyeSh4dHMpICAgDQoNCg0KDQoNCiMjIHB1bGwgc29tZSBkYXRhIGZyb20gdGhlIE5IUyBSIGRhdGFzZXQNCmRhdGEgPC0gYWVfYXR0ZW5kYW5jZXMNCg0KZGF0YTQgPC0gZGF0YSAlPiUgZmlsdGVyIChvcmdfY29kZSA9PSJSWFEiKQ0KDQojI0p1c3Qgc2V0dGluZyB1cCBhIGNvdXBsZSBvZiBwbG90cyB0byB1c2UgbGF0ZXIgaW4gdGhlIGV4YW1wbGUNCiMjdGhpcyB3aWxsIGJlIGV4cGxhaW5lZCBhIGxpdHRsZSBsYXRlcg0KIyNzbyBub3RoaW5nIHRvIHNlZSBoZXJlLCBtb3ZlIGFsb25nIA0KDQpwMSA8LWdncGxvdCggZmlsdGVyKGRhdGEsb3JnX2NvZGUgPT0iUlhRIiksIGFlcyh4ID0gcGVyaW9kLCB5ID0gYXR0ZW5kYW5jZXMsIGdyb3VwID0gdHlwZSwgY29sb3VyID0gdHlwZSkpICsNCiBnZW9tX2xpbmUoc2l6ZSA9IDEuMzIpICsNCiBsYWJzKHRpdGxlID0gIlJYUSBOdW1iZXIgb2YgYXR0ZW5kYW5jZXMgYnkgdHlwZSIpICsNCiB0aGVtZV9taW5pbWFsKCkNCnAyIDwtZ2dwbG90KCBmaWx0ZXIoZGF0YSxvcmdfY29kZSA9PSJSSjEiKSwgYWVzKHggPSBwZXJpb2QsIHkgPSBhdHRlbmRhbmNlcywgZ3JvdXAgPSB0eXBlLCBjb2xvdXIgPSB0eXBlKSkgKw0KIGdlb21fbGluZShzaXplID0gMS4zMikgKw0KIGxhYnModGl0bGUgPSAiUkoxIE51bWJlciBvZiBhdHRlbmRhbmNlcyBieSB0eXBlIikgKw0KIHRoZW1lX21pbmltYWwoKQ0KcDMgPC1nZ3Bsb3QoIGZpbHRlcihkYXRhLG9yZ19jb2RlID09IlJZSiIpLCBhZXMoeCA9IHBlcmlvZCwgeSA9IGF0dGVuZGFuY2VzLCBncm91cCA9IHR5cGUsIGNvbG91ciA9IHR5cGUpKSArDQogZ2VvbV9saW5lKHNpemUgPSAxLjMyKSArDQogbGFicyh0aXRsZSA9ICJSSDEgTnVtYmVyIG9mIGF0dGVuZGFuY2VzIGJ5IHR5cGUiKSArDQogdGhlbWVfbWluaW1hbCgpDQoNCiMjIEkgZmluZCBpdCBpcyB1c3VhbGx5IGdvb2QgcHJhY3RpY2UgdG8gd3JpdGUgYWxsIHlvdXIgUiBjb2RlIGF0IHRoZSBzdGFydCBhbmQgY3JlYXRlIGFsbCB5b3VyIGNoYXJ0cyBhbmQgdGFibGVzIGFuZCBzdHVmZiBhdCBzdGFydCBhbmQgbWFrZSB0aGVtIG9iamVjdHMuICBZb3UgY2FuIHRoZW4gaW5zZXJ0IHRoZW0gaW50byB0aGUgbWFya2Rvd24gZG9jdW1lbnQuICANCg0KIyMgVGhpcyBzcGxpdHMgdGhlIHR3byB0aGluZ3MgYW5kIG1ha2VzIGl0IGVhc2llciB0byByZWFkIHRoZSBtYXJrZG93biBhbmQgYWxsIHRoZSBjb2RlIGlzIHRvZ2V0aGVyLg0KDQojIyBIb3dldmVyIGZvciB0aGlzIGV4YW1wbGUgSSBhbSBicmVha2luZyB0aGlzIHJ1bGUgYW5kIHdyaXR0aW5nIG1vc3Qgb2YgdGhlIGNvZGUgYmVmb3JlIGEgY2h1bmsgb2YgbWFya2Rvd24gc28gdGhhdCB5b3UgY2FuIGRpcmVjdGx5IHNlZSB3aGljaCBlYWNoIGJpdCBpcyBkb2luZy4NCg0KIyMgVGhpcyBpcyBxdWl0ZSBhIGNvYmJsZWQgdG9ndGhlciBwaWVjZSBvZiBjb2RlIGZyb20gbWFueSBwcm9qZWN0cywgc28gSSBoYXZlIG5vdCBiZWVuIHZlcnkgY29uc2lzdGVudCB3aXRoIG15IG5hbWluZyBjb252ZW50aW9ucyBhbmQgSSBhbSByZXVzaW5nIGFuZCBkdXBsaWNhdGluZyBhIGZhciBiaXQgb2YgZGF0YSB3aGljaCBpcyBieSBubyBtZWFucyB0aGUgbW9zdCBlZmZpY2llbnQgd2F5IG9mIGRvaW5nIHRoaW5ncyBhbmQgaGFzIG92ZXIgaW5mbGF0ZWQgdGhlIGZpbmFsIGZpbGUgc2l6ZSBvZiB0aGUgb3V0cHV0LiAgT2ggd2VsbC4NCg0KDQoNCmBgYA0KDQojIEludHJvZHVjdGlvbg0KDQpUaGlzIGlzIGdvaW5nIHRvIGJlIGEgYml0IG9mIGEgb2YgYW4gYXR0ZW1wdCB0byB0YWxrIHlvdSB0aHJvdWdoIGFuZCB0cmFpbiB5b3UgYXQgdGhlIHNhbWUgdGltZSBvbiBob3cgdG8gY3JlYXRlIGEgbWFya2Rvd24gcmVwb3J0Lg0KDQpZb3UgcnVuIGEgbWFya2Rvd24gYnkgJ2tuaXQnIGluZyBpdC4gIFRoZXJlIGlzIGxpdGVyYWxseSBhbiBpY29uIHdpdGggYSBiYWxsIG9mIHdvb2wgd2l0aCBhIGtuaXR0aW5nIG5lZWRsZSBpbiBpdC4gIFRoYXQgaXMgdGhlIGJ1dHRvbiB3ZSBuZWVkIGFuZCBpdCBrbml0cyB0b2dldGhlciBhbGwgdGhlIG1hcmtkb3duIHN0dWZmIGFuZCByIGNvZGUgaW50byBvbmUgc3VwZXIgc25henp5IG91dHB1dC4NCg0KV2lsbCBnZXQgeW91IHRvIGtuaXQgdGhlIHJlcG9ydCBhbmQgc2VlIHRoZSByZXN1bHRzIGFuZCB0aGVuIHdlIHdpbGwgcGljayBhcGFydCB0aGUgY29kZSBhbmQgc2VlIGhvdyBpdCBpcyBkb25lIGJlaGluZCB0aGUgc2NlbmVzLg0KDQpJZiB5b3UgaGF2ZSAyIHNjcmVlbnMgdHJ5IHRvIGhhdmUgdGhlIGNvZGUgb24gb25lIHNpZGUgYW5kIHRoZSByZXBvcnQgb24gdGhlIG90aGVyIGFuZCB5b3UgY2FuIGxvb2sgc2lkZSBieSBzaWRlIGF0IHdoYXQgaXMgaGFwcGVuaW5nLg0KDQpJIHdpbGwgYWxzbyBiZSBwcmVzZW50aW5nIGFuZCB5b3UgY2FuIGxvb2sgYXQgbWUgdG8gZm9sbG93IGFzIHdlbGwuDQoNCj4gSG93IG1hbnkgdGltZXMgaGF2ZSB5b3Ugd2FudGVkIHRvIGNyZWF0ZSBhIHJlcG9ydCB0aGF0IGhhcyB0aGUgYmVhdXR5IGFuZCByZWFkYWJpbGl0eSBvZiBhIHdvcmQgZG9jdW1lbnQgYnV0IHdhbnQgdG8gYWRkIGludGVyYWN0aXZlIGdyYXBocyBhbmQgZnVuY3Rpb25hbGl0eSBvZiBhIGV4Y2VsIGZpbHRlcmVkIHRhYmxlIG9yIGV2ZW4gYSBwaXZvdCB0YWJsZT8gIA0KDQpJZiBvbmx5IHRoZXJlIHdhcyBhIHdheSB5b3UgY291bGQgcHVsbCB5b3VyIGRhdGEsIHdyYW5nbGUgaXQgYW5kIHRoZW4gZmluYWxseSBnZXQgaXQgdG8gcHJvZHVjZSBhIGJlYXV0aWZ1bCByZXBvcnQsIGFsbCBpbiBvbmUgcHJvY2Vzcy4NCg0KSWYgb25seS4uLg0KDQpJZiBvbmx5Li4uDQoNCkhhbmcgb24hICBTb3VuZHMgcmVhbGx5IGNvbXBsaWNhdGVkIGFuZCBkaWZmaWN1bHQgYW5kIG5lZWQgbG90cyBvZiB0cmlja3kgY29kZS4gIEhhdmUgd2Ugbm90IGJlZW4gdGVsbGluZyB5b3UgaG93IGJyaWxsaWFudCBSIGlzPyAgDQoNCiFbXShodHRwczovL21lZGlhLmdpcGh5LmNvbS9tZWRpYS9iNHpsSnRyUk0xNXE4L2dpcGh5LmdpZikNCg0KDQoNCkludHJvZHVjaW5nDQoNCg0KIVtNYXJrZG93bkljb25dKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi9pbWFnZXMvaGV4LXJtYXJrZG93bi5wbmcpDQoNCllvdSBjYW4gaW1wb3J0IGltYWdlcywgZWl0aGVyIGZyb20gdGhlIHdlYiBvciBmcm9tIGEgbG9jYWwgZGlyZWN0b3J5IC0gdGhpcyBvbmUgaXMgZnJvbSB0aGUgd2ViIGFuZCBpdCBpcyBtYXNzaXZlISBZb3UgY2FuIHNlZSBhYm92ZSB5b3UgY2FuIGFsc28gaW5zZXJ0IGFuaW1hdGVkIGdpZnMuICANCihJIGZlYXIgd2hhdCBJIGhhdmUgZG9uZSB0byB0aGUgTkhTIGJ5IHJlbGVhc2luZyB0aGF0IGtub3dsZWRnZSBpbnRvIHRoZSB3aWxkIC0gSSB0YWtlIG5vIHJlc3BvbnNpYmlsaXR5IGZvciBhbnkgcmVwZXJjdXNzaW9ucyBvZiBhbmltYXRlZCBueWFuIGNhdCByZXBvcnRzLikNCg0KIyMgUiBNYXJrZG93bg0KDQpUaGlzIGlzIGFuIFIgTWFya2Rvd24gZG9jdW1lbnQuIE1hcmtkb3duIGlzIGEgc2ltcGxlIGZvcm1hdHRpbmcgc3ludGF4IGZvciBhdXRob3JpbmcgSFRNTCwgUERGLCBhbmQgTVMgV29yZCBkb2N1bWVudHMuIEZvciBtb3JlIGRldGFpbHMgb24gdXNpbmcgUiBNYXJrZG93biBzZWUgPGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20+Lg0KDQpXb3JkIGFuZCBQREYgcmVwb3J0cyBhcmUgZmluZSBhbmQgeW91IGNhbiBkbyBzb21lIHZlcnkgcHJldHR5IGJ1dCBmbGF0IHJlcG9ydHMgaW4gdGhlc2Ugb3V0cHV0cy4gIFRoYXRzIGZpbmUgYnV0IHRoZSBjb29sIGthdHMgYW5kIGtpdHRpZXMgd2FudCBpbnRlcmFjdGl2ZSBhbmQgZmxhc2h5LiANCg0KV2hlbiB5b3UgY2xpY2sgdGhlICoqS25pdCoqIGJ1dHRvbiBhIGRvY3VtZW50IHdpbGwgYmUgZ2VuZXJhdGVkIHRoYXQgaW5jbHVkZXMgYm90aCBjb250ZW50IGFzIHdlbGwgYXMgdGhlIG91dHB1dCBvZiBhbnkgZW1iZWRkZWQgUiBjb2RlIGNodW5rcyB3aXRoaW4gdGhlIGRvY3VtZW50LiANCg0KWW91IG1heSBub3RpY2UgdGhlIG5pY2UgZmxvYXRpbmcgY29udGVudHMgcGFnZSB0byB0aGUgbGVmdC4gIFRoaXMgaXMgY3JlYXRlZCBpbiB0aGUgWUFNTCBoZWFkZXIgYXQgdGhlIHZlcnkgc3RhcnQgb2YgdGhlIGRvY3VtZW50LiAgWUFNTCBzdGFuZHMgZm9yIFlBTUwgQWluJ3QgTWFya3VwIExhbmd1YWdlLiAgSXQgc2V0cyBzb21lIGdsb2JhbCBwYXJhbWV0ZXJzIGFuZCBjYW4gZG8gc29tZSBjb29sIHN0dWZmLiAgWW91IHNldCB0aGUgaGVhZGluZ3MgYXMgcGVyIHRoZSBuZXh0IHNlY3Rpb24gYW5kIHRoZSBkb2N1bWVudCBhdXRvbWF0aWNhbGx5IHBpY2tzIHVwIHRob3NlIHdpdGggYSBzaW5nbGUgJyMnLg0KDQoqU28gd2hhdCBjYW4geW91IGRvPyoNCg0KIyBNYXJrZG93biBmb3JtYXR0aW5nDQoNCiMjIFlvdSBjYW4gcGxheSB3aXRoIGhlYWRlcnMgdGhhdCBnZXQgc21hbGxlcg0KDQojIyMgWW91IGNhbiBwbGF5IHdpdGggaGVhZGVycyAtIGFuZCBzbWFsbGVyDQoNCiMjIyMgWW91IGNhbiBwbGF5IHdpdGggaGVhZGVycyAgLSBhbmQgc21hbGxlcg0KDQojIyMjIyBZb3UgY2FuIHBsYXkgd2l0aCBoZWFkZXJzICAtIGFuZCBzbWFsbGVzdA0KDQpZb3UgY2FuIG1ha2UgYSBsaW5lIG1ha2UgYSBsaW5lIGJyZWFrDQoNCioqKg0KDQpZb3UgY2FuIGRvIGFsbCB0aGUgbm9ybWFsICppdGFsaWNzKiBhbmQgKipib2xkKiogYW5kIF5zdXBlcnNjcmlwdF4gYW5kIH5+c3RyaWtlLXRob3VnaH5+DQoNCj4gVGhpbmdzIGxpa2UgYmxvY2sgcXVvdGVzIGxvb2sgZnVua3kgIA0KPiBlc3BlY2lhbGx5IGlmIHlvdSBwdXQgYSBmZXcgdG9nZXRoZXIgIA0KPiBtYWtlIHN1cmUgeW91IGVuZCB5b3VyIHNlbnRlbmNlcyB3aXRoIDIgIA0KPiBzcGFjZXMgdG8gc3RhcnQgYSBuZXcgcGFyYWdyYXBoICANCg0KDQpPdGhlciB0aGluZ3MgdGhhdCBhcmUgZWFzeQ0KDQoqIGxpc3RzDQoqIHB1dHRpbmcgc3R1ZmYgaW4gbGlzdHMNCiAgKyBwdXR0aW5nIHN0dWZmIGluIHN1YiBsaXN0cw0KICArIHN1Y2ggYXMgdGhpcw0KKiBkaWQgSSBzYXkgbGlzdHM/DQoNCllvdSBjYW4gYWxzbyBkbyBudW1iZXJlZCBsaXN0cw0KDQooQCkgTGlrZSB0aGlzDQooQCkgRmluZSBleGFtcGxlIG9mIGEgbGlzdA0KICAgICsgYW5kIGRvIHN1YiBsaXN0cyBpbiBhIG51bWJlcmVkIGxpc3QNCiAgICAgIGkpIGFuZCBkbyBzdWIgc3ViIGxpc3RzICANCiAgICAgICAgQS4gYW5kIHN1YiBzdWIgc3ViIGxpc3QNCg0KV3JpdGUgc29tZSBzdHVmZiBpbiB0aGUgbWlkZGxlIG9mIHlvdXIgbGlzdCAgICAgICAgDQogICAgICAgIA0KKEApIGFuZCB0aGVuIGdvIGJhY2sgdG8gdGhlIGxpc3QNCihAKSBOT1RFOiB0aGUgbnVtYmVycyBpbiB0aGUgbGlzdCBhcmUgbm90IHNwZWNpZmllZCwgdGhleSBhcmUgZHluYW1pYyBhbmQgaWYgeW91IGdvIGFuZCBlZGl0IG9uZSBvdXQgaXQgd2lsbCBhZGp1c3QgdGhlbSBhdXRvbWF0aWNhbGx5DQoNCjxzdHlsZT4NCmRpdi5ibHVlIHsgYmFja2dyb3VuZC1jb2xvcjojZTZmMGZmOyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQ0KPC9zdHlsZT4NCjxkaXYgY2xhc3MgPSAiYmx1ZSI+DQoNCllvdSBjYW4gY29sb3VyIGluIGEgYmxvY2sgdG8gYXNzaXN0IHdpdGggaGlnaGxpZ2h0aW5nIGFuIGFyZWEuDQoNCi0gVGhpcyBpcyBteSBmaXJzdCBjb25jbHVzaW9uDQotIFRoaXMgaXMgbXkgc2Vjb25kIGNvbmNsdXNpb24gIA0KDQo8L2Rpdj4NCg0KWW91IGNhbiBhZGQgZm9vdG5vdGVzW14xXQ0KDQpbXjFdOlRoaXMgaXMgdGhlIGZvb3Rub3RlIGZyb20gdGhlIGZvb3Rub3RlIGFkZGVkIHdheSB3YXkgdXAgYWJvdmUNCg0KWW91IGNhbiBhbHNvIGRvIGJhc2ljIGR5bmFtaWMgdGFibGVzIGp1c3QgaW4gbWFya2Rvd24gLSBsb29rcyBtZXNzeSBpbiB0aGUgY29kZSwgcHJldHR5IGluIHRoZSBtYXJrZG93biBhbmQgdGhhbmtzIHRvIHRoZSBwb3dlciBvZiBIVE1MLCB0aGV5IHJlLXNpemUgYWNjb3JkaW5nIHRvIHRoZSBzY3JlZW4sIGFsbCBvZiB0aGVzZSB0YWJsZXMgYW5kIGNoYXJ0cyBhcmUgbW9iaWxlIGZyaWVuZGx5Lg0KDQpDb2x1bW4gaGVhZGluZyBvbmUgfCBTZWNvbmQgY29sdW1uIGhlYWRpbmcNCi0tLXwtLS0NClN0dWZmIHwgQ29sdW1uIDIgc3R1ZmYNCkFub3RoZXIgcm93IG9mIHN0dWZmIHwgTW9yZSBjb2x1bW4gMiBzdHVmZiAgDQoNCllvdSBjYW4gYWxpZ24gdGhlIHN0dWZmIGluIHRoZXNlIHRhYmxlcyBidXQgdGhleSBkb24ndCB3b3JrIHdlbGwgd2l0aCBudW1iZXJzDQoNCnwgUmlnaHQgfCBMZWZ0ICB8IERlZmF1bHQgfCBDZW50cmUgfA0KfC0tLTp8Oi0tLXwtLS0tfDotLS0tOnwNCnwgYmx1cmIgcmlnaHQgYWxpZ25lZCB8IGJsdXJiIGxlZnQgYWxpZ25lZCB8IGJsdXJiIGRlZmF1bHQgfCBibHVyYiBpbiBkYSBjZW50cmUgfA0KfCAxMjM0IHwgNTY3ODggfCA0NTQ1NjQ0IHwgNDM1MzUgfA0KfCAgMzQuMiB8IDM0NDIuMSB8IDM0MjEuMSB8IDQ1MTIuNDUgfA0KDQoNCjxwIHN0eWxlPSJmb250LWZhbWlseTogY29taWMgc2FucyBNUzsgZm9udC1zaXplOjIwcHQiPg0KICAgIFlvdSBjYW4gYWxzbyBwbGF5IHdpdGggSFRNTCB0YWdzIHRvIGNoYW5nZSBmb250IHRvIGNvbWljIHNhbnMNCjwvcD4NCg0KPHAgc3R5bGU9ImZvbnQtZmFtaWx5OiBJbXBhY3QsIENoYXJjb2FsLCBzYW5zLXNlcmlmOyBmb250LXNpemU6MTBwdDsgZm9udC1zdHlsZTppdGFsaWMiPg0KICAgIEp1c3QgYmVjYXVzZSB5b3UgY2FuIGRvZXMgbm90IG1lYW4geW91IHNob3VsZCENCjwvcD4NCg0KDQojIFRhYnNldHMNCg0KVGFic2V0cyBhcmUgZ3JlYXQgZm9yIGNyZWF0aW5nIG5pY2UgaW50ZXJhY3RpdmUgZG9jdW1lbnRzIGFuZCByZWR1Y2luZyB0aGUgbGVuZ3RoIG9mIHlvdXIgZG9jdW1lbnQgYnV0IHN0aWxsIGNyYW1taW5nIGluIGxvYWRzIG9mIGV4dHJhIGRhdGEgd2l0aG91dCB5b3VyIHJlYWRlciByZWFsaXNpbmcgaXQuDQoNCklmIHlvdSBsb29rIGF0IHRoZSBjb2RlIHlvdSBjYW4gc2VlIHRoYXQgeW91IGNhbiBhZGQgYSBsaXR0bGUgZmFkZSB0byBnaXZlIHlvdXIgcmVwb3J0IGEgbGl0dGxlIGV4dHJhIHNwYXJrbGUgb3IgeW91IGNhbiBsZWF2ZSBpdCBmb3IgZXh0cmEgemlwLiBJIGFtIHVzaW5nIGEgYml0IG9mIGZhZGUgc3BhcmtsZSBmb3IgdGhpcyBleGFtcGxlDQoNCiMjIFJlc3VsdHMgYnkgcHJvdmlkZXIgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9DQoNCg0KDQojIyMgUHJvdmlkZXIgY29kZSBSWFENCg0KYGBge3IgcDF9DQpwMQ0KYGBgDQoNCkJsYWggYmxhaCBibGFoIHN1cGVyIGltcG9ydGFudCBjb21tZW50YXJ5IGFib3V0IHRoZSBibHVlIGxpbmUgZ29pbmcgdXAuDQoNCiMjIyBQcm92aWRlciBjb2RlIFJKMQ0KYGBge3IgcDJ9DQpwMg0KYGBgDQoNCk9oIG15IC0gdGhlIHJlZCBsaW5lIGlzIGdvaW5nIHVwLCBubyBvbmUgd2FudHMgdG8gc2VlIGEgcmVkIGxpbmUgZ29pbmcgdXAuICBNdXN0IHJlbWVtYmVyIHRvIFJBRyByYXRlIHRoaXMgbGF0ZXIgYW5kIGFkZCBhIHNhZCBzbWlsZXkgZmFjZSwgcHJldHR5IHN1cmUgdGhlcmUgd2lsbCBiZSBhIGxlc3NvbiBvbiBob3cgdG8gZG8gdGhhdCBsYXRlci4NCg0KIyMjIFByb3ZpZGVyIGNvZGUgUllKDQpgYGB7ciBwM30NCnAzDQpgYGANCg0KLWluc2VydCB3aXR0eSBjb21tZW50YXJ5IGhlcmUtDQoNCiMjIHsudW5saXN0ZWQgLnVubnVtYmVyZWR9DQoNClRoYXQgaXMgdGhlIGJhc2ljIHRleHQgZm9ybWF0dGluZyBzdHVmZiwgYnV0IHdlIHdhbnQgdG8gZG8gY2xldmVyIHRoaW5ncyBhbmQgaW5jb3Jwb3JhdGUgb3VyIGRhdGENCg0KIyBBZGRpbmcgc29tZSBkYXRhDQoNCldlIGFyZSBnb2luZyB0byB1c2UgdGhlIE5IUi1SIHNhbXBsZSBkYXRhIHNldCBhbmQgdXNlIHRoZSBBRSBhdHRlbmRhbmNlcyBkYXRhLiAgVGhpcyBoYXMgYSBkYXRlLCBhIG9yZ2FuaXNhdGlvbiBjb2RlLCBhIHR5cGUsICBudW1iZXIgZm9yIGF0dGVuZGFuY2VzLCBhZG1pc3Npb25zIGFuZCBicmVhY2hlcy4gDQoNCllvdSBjYW4gaW5jbHVkZSBkYXRhIHdpdGhpbiB0aGUgbWFya2Rvd24gc3BlY2lmaWNhbGx5IHdpdGhpbiB0aGUgdGV4dCBieSBkb2luZyBhIGJhY2sgdGljayByIGFuZCBlbnRlcmluZyBhIHZhcmlhYmxlIG9yIGZvcm11bGEgKHlvdSBjYW4gYWxzbyBmb3JtYXQgaXQgaW50byBhIG5pY2UgcmVhZGFibGUgbnVtYmVyKS4NCg0KRm9yIGV4YW1wbGUgdGhlIHRvdGFsIG51bWJlciBvZiBhdHRlbmRhbmNlcyBmcm9tIHRoZSBkYXRhIHNldCBpcyBgciBmb3JtYXQoc3VtKGRhdGEkYnJlYWNoZXMpLGZvcm1hdD0iZiIsIGJpZy5tYXJrPSIsIilgDQoNClRoZSBkYXRlIG9mIGByIGFzLmNoYXJhY3Rlcih0b2RheSgpLGZvcm1hdD0iJWQgJUIgJVkiKWAgaXMgd2hlbiB5b3UgcHJlc3NlZCB0aGUga25pdCBidXR0b24gcmVwb3J0Lg0KDQpZb3UgY2FuIGFsc28gYWRkIConY29kZSBjaHVua3MnKiwgdGhlc2UgYXJlIGNodW5rcyBvZiBjb2RlIHRoYXQgc2l0IHdpdGhpbiB5b3VyIG1hcmtkb3duIGRvY3VtZW50LiANCg0KU28gaGVyZSBpcyBhIHRoZSBiYXNlIHdheSB0byBpbmNsdWRlIHNvbWUgZGF0YSB5b3Ugc2ltcGxlIGRvIHRyaXBsZSBiYWNrIHRpY2tzIHRvIHRlbGwgUiBzdHVkaW8gdGhhdCBub3cgeW91IHdhbnQgdG8gZG8gc29tZSBSIHN0dWZmLg0KDQpUaGlzIHdpbGwgcHJpbnQgdGhlIHN1bW1hcnkgb2YgdGhlIEFFIGF0dGVuZG5hY2UqIGRhdGEgc2V0IGluIGEgbm90IHZlcnkgcHJldHR5IHRhYmxlDQoNCj4gXCoganVzdCBub3RpY2VkIGEgdHlwbyBpbiAnYXR0ZW5kYW5jZScgLSBSIHN0dWRpbyBkb2VzIGhhdmUgYSBzcGVsbCBjaGVjayBmZWF0dXJlIC0gcmVtZW1iZXIgdG8gdXNlIGl0IGFzIG5vdCBhdXRvbWF0aWMsIG5vIHdhdnkgcmVkIGxpbmVzIGxpa2Ugd29yZCFcKiogIA0KPiBcKiogeW91IGFsc28gaGF2ZSB0byBkbyBiYWNrc2xhc2ggYXN0ZXJpc2sgd2hlbiB5b3UgYWN0dWFsbHkgd2FudCB0byB1c2UgYW4gYXN0ZXJpc2sNCg0KYGBge3IgYXR0ZW5kfQ0KIyBUaGUgYml0IHRoZSB0aGUgY3VybHkgYnJhY2tldHMgYWZ0ZXIgdGhlIFIgaXMgc2ltcGx5IHRoZSBuYW1lIG9mIHRoZSBjb2RlIGNodW5rDQojIGhlbHBzIHRvIGZpbmQgeW91ciB3YXkgYXJvdW5kIHdoZW4geW91IGhhdmUgbG90cyBvZiBiaXRzIG9mIGNvZGUNCiMgYXMgeW91IGNhbiBzZWUgJyMncyBoYXZlIGdvbmUgYmFjayB0byBiZWluZyBjb21tZW50cyBpbiB0aGUgUiBjb2RlIGFuZCBub3QgaGVhZGluZ3MNCiMgeW91IGNhbiB1c2UgdGhpcyBjaHVuayBoZWFkZXIgdG8gc2V0IHNldmVyYWwgcGVyYW1ldGVycyBzdWNocyBhcyB3aGV0aGVyIHRvIGRpc3BsYXkgDQojIHRoaXMgY29kZSBhbmQgc2V0IHNpemUgb2YgYW55IGNoYXJ0cyB5b3UgY2FsbCB1cCBhbmQgc3R1ZmYgbGlrZSB0aGF0Lg0KDQoNCiMjIGp1c3QgY3JlYXRlIGEgbGl0dGxlIHN1YnNldCBzbyBpdCB3aWxsIGZpdCBpbiBhIHNpbXBsZSB0YWJsZQ0KZGF0YTIgPC0gZGF0YSAlPiUgZmlsdGVyKG9yZ19jb2RlPT0iUkY0IiwgdHlwZSA9PSAib3RoZXIiLCBhdHRlbmRhbmNlcyA+PSA1MDAwKQ0KDQojIFlvdSBjYW4gcHJpbnQgdGhlIGRhdGEgZnJhbWUgc2ltcGx5IGJ5IHByaW50aW5nIGl0IChwcmludCBjb21tYW5kIG5vdCByZXF1aXJlZCkNCmRhdGEyDQoNCiMgZW5kIHRoZSBSIGNvZGUgY2h1bmsgd2l0aCBhbm90aGVyIDMgYmFja3RpY2tzDQpgYGANCg0KIyBMaWJyYXJ5IC0gS2FibGUNCg0KQmFzaWMgYnV0IGJ5IG5vIG1lYW5zIHByZXR0eSwgd2UgY2FuIHVzZSB0aGUga2FibGUgcGFja2FnZSB0byBtYWtlIGEgcHJldHRpZXIgdGFibGUsIGluIGp1c3QgMiBsaW5lcyBvZiBjb2RlIHlvdSBjYW4gcHJvZHVjZSB0aGlzLCB3aGljaCBoYXMgYmV0dGVyIHJlYWRhYmlsaXR5IGFuZCBhIG5pY2UgcmVhZGluZyBob3ZlciBvdmVyLiANCg0KYGBge3Iga2FibGVhdHRlbmR9DQoNCmthYmxlKGRhdGEyKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiKSkNCg0KYGBgDQoNClRoZSBrYWJsZSBwYWNrYWdlIHRvIG1ha2UgYSBwcmV0dGllciB0YWJsZSwgaW5kZW50IHJvd3MgYW5kIGNvbG91ciBpdCBpbiBhbmQgY2hhbmdlIGZvcm1hdHMsIGFkZCBzdWIgaGVhZGluZ3MgYW5kIGlzIHF1aXRlIHNpbXBsZSB0byB1c2UuDQoNCmBgYHtyIGthYmxlYXR0ZW5kZnVua3l9DQoNCmthYmxlKGRhdGEyKSAlPiUNCiAgIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiKSAlPiUNCiAgcGFja19yb3dzKCJzdWIgaGVhZGluZyBhbmQgaW5kZW50IGZpcnN0IDMgcm93cyIsIDEsIDMpICU+JQ0KICByb3dfc3BlYyg0LCBib2xkID0gVCwgYmFja2dyb3VuZCA9ICJ5ZWxsb3ciKSAlPiUNCiAgcm93X3NwZWMoNywgYm9sZCA9IFQsIGNvbG9yID0gIndoaXRlIiwgYmFja2dyb3VuZCA9ICIjRDcyNjFFIikNCmBgYA0KDQpLYWJsZSBpcyByZWFsbHkgZ29vZCBmb3IgYSBzdGF0aWMgYW5kIHByZXR0eSwgYnV0IHdlIHdhbnQgaW50ZXJhY3RpdmUuDQoNCiMgTGlicmFyeSAtIERUIChzaG9ydCBmb3IgZGF0YSB0YWJsZSkNCg0KVGhpcyBpcyBhIERUIGRhdGF0YWJsZSAtIGhhcyBsb3ZlbHkgZmlsdGVycyBvbiB0aGUgcGVyaW9kcyBhbmQgZGlmZmVyZW50IGNvbHVtbnMuICBZb3UgY2FuIHJlIG9yZGVyIHRoZSBkYXRhIGFuZCBzaG93IGFzIG11Y2ggb3IgYXMgbGl0dGxlIGFzIHlvdSBsaWtlLiAgIFRoZSBleHBvcnQgYnV0dG9ucyBleHBvcnQgd2hhdCB5b3UgaGF2ZSBzZWxlY3RlZC4gIFRoZXJlIGlzIGFsc28gYSBzZWFyY2ggZnVuY3Rpb24gZm9yIHRoZSBkYXRhLg0KDQpZb3UgY2FuIG1lc3MgYXJvdW5kIHdpdGggdGhlIGRlZmF1bHRzIHNvIHRoYXQgaXQgc2hvd3MgYSBsYXJnZXIgdGFibGUuDQoNCg0KYGBge3IgZGF0YXRhYmxlfQ0KDQpkYXRhdGFibGUoZGF0YSwgZmlsdGVyID0gJ3RvcCcsIA0KICAgICAgICAgIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycsDQogICAgICAgICAgb3B0aW9ucyA9IGxpc3QoZG9tID0gJ0JsZnJ0aXAnLA0KICAgICAgICAgIGJ1dHRvbnMgPSBjKCdjb3B5JywgJ2NzdicsICdwZGYnLCAncHJpbnQnKSwNCiAgICAgICAgICBsZW5ndGhNZW51ID0gbGlzdChjKDEwLDI1LDUwLC0xKSwNCiAgICAgICAgICBjKDEwLDI1LDUwLCJBbGwiKSkpKQ0KYGBgDQoNCkRUIERhdGF0YWJsZSBpcyBwcmV0dHkgZ29vZCBhbmQgcXVpY2ssIGV2ZW4gdGhlIGJhc2UgZGVmYXVsdCBjb21lcyB1cCB3aXRoIGEgcHJldHR5IGdvb2QgdGFibGUuICBJdCBpcyB2ZXJ5IG5pY2UgYXQgcHJlc2VudGluZyBhIGZsYXQgdGFibGUsIGJ1dCBpZiB5b3Ugd2FudCBjYWxjdWxhdGlvbnMgYW5kIHRvdGFscyAsIHlvdSBoYXZlIHRvIGhhcmQgY29kZSB0aGVtIGludG8geW91ciB0YWJsZS4NCg0KVGhhdCBpcyBvbmUgZm9ybWF0IG9yIGlmIHlvdSB3YW50IG1vcmUgc3VtbWFyeSB0eXBlIHJlcG9ydHMgeW91IGNhbiB1c2UgcmVhY3RhYmxlLg0KDQojIExpYnJhcnkgLSBSZWFjdGFibGUNCg0KVGhpcyBpcyByZWFjdGFibGUsIGFuZCBpdCB3b3JrcyBhIGxpdHRsZSBtb3JlIGxpa2UgYSBmaWx0ZXJlZCBhbmQgc3ViIGdyb3VwZWQgdGFibGUuICBJdCBpcyBhIGJpdCB0cmlja2llciB0byB1c2UsIGJ1dCBzZWVtcyB0byBiZSBhYmxlIHRvIGFsbCB0aGUgc3R1ZmYgb2YgZGF0YSB0YWJsZSBhbmQgYSBiaXQgbW9yZS4NCg0KYGBge3IgcmVhY3RhYmxlfQ0KDQpyZWFjdGFibGUoZGF0YSwgZ3JvdXBCeSA9ICJvcmdfY29kZSIsICBtaW5Sb3dzID0gMTApDQoNCmBgYA0KDQoNClJlYWN0YWJsZSBpcyByZWFsbHkgZ29vZCBhdCBjcmVhdGluZyBzdW1tYXJpZXMgYW5kIGRyaWxsIGRvd24gZGF0YXNldHMuICBJdCBjcmVhdGVzIGFsbCB0aGUgZ3JvdXBpbmdzIG9mIGRhdGEgaXRzZWxmIGFuZCBzbyB5b3UgZG8gbm90IGhhdmUgdG8gd3JhbmdsZSB0aGUgZGF0YSBpbnRvIGdyb3VwcyBiZWZvcmUgeW91IG1ha2UgdGhlIHRhYmxlLiAgWW91IGNhbiBhbHNvIGNyZWF0ZSBoaWdoIGxldmVsIGFnZ3JlZ2F0ZSBmdW5jdGlvbnMgb24gYSBncm91cCBhbmQgaGF2ZSB0aGUgYWJpbGl0eSB0byBkcmlsbCBkb3duIHRvIHNlZSB0aGUgdW5kZXJseWluZyBkYXRhLg0KDQpgYGB7ciByZWFjdGFibGVzdW1tYXJ5fQ0KDQojI2RhdGEyIDwtIGRhdGEgJT4lIGZpbHRlciAodHlwZSA9PSAyKQ0KDQpyZWFjdGFibGUoZGF0YSwgZ3JvdXBCeSA9IGMoInBlcmlvZCIsICJ0eXBlIiksICANCiAgICAgICAgICBtaW5Sb3dzID0gMTAsDQogICAgICAgICAgY29sdW1ucyA9IGxpc3QgKA0KICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRlbmRhbmNlcyA9Y29sRGVmKGFnZ3JlZ2F0ZSA9ICJtZWRpYW4iLCBuYW1lID0gIk1lZGlhbiBhdHRlbmRhbmNlcyIsIGFsaWduID0gImxlZnQiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFjaGVzID0gY29sRGVmKGFnZ3JlZ2F0ZSA9ICAibWF4IiwgbmFtZSA9ICJNYXggYnJlYWNoZXMiLCBhbGlnbiA9ICJsZWZ0IikgICwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYWRtaXNzaW9ucyA9IGNvbERlZihhZ2dyZWdhdGUgPSAibWVhbiIsIGZvcm1hdCA9IGNvbEZvcm1hdChkaWdpdHMgPSAxKSwgbmFtZSA9ICJNZWFuIGFkbWlzc2lvbnMiLCBhbGlnbiA9ICJsZWZ0IikgKSkNCg0KYGBgDQoNClJlYWN0YWJsZSBoYXMgbWFueSBtb3JlIGZ1bmN0aW9ucyB0aGFuIGEgRFQgZGF0YXRhYmxlIGJ1dCBhcyBJIHNhaWQsIGlzIGEgbGl0dGxlIG1vcmUgdHJpY2t5IHRvIHVzZS4gIA0KDQpZb3UgY2FuIHVzZSBpdCB0byBkbyBmdW5reSBzdHVmZiBsaWtlIHRoaXMsIEkgc2VlIHlvdXIgc3BhcmsgbGluZXMgZXhjZWwgYW5kIHJhaXNlIHlvdSBzcGFyayBib3ggcGxvdHMhICAoYW5kIGNvbmRpdGlvbmFsIGZvcm1hdHRpbmcpDQoNCmBgYHtyIHNwYXJreXRhYmxlfQ0KDQpkYXRhMyA8LSBkYXRhICU+JSBmaWx0ZXIgKG9yZ19jb2RlID09ICdSSjInLCB0eXBlID09ICIxIiApDQoNCnJlYWN0YWJsZSAoZGF0YTMsDQogIGRlZmF1bHRQYWdlU2l6ZSA9IDE1LA0KICBib3JkZXJlZCA9IFRSVUUsDQogIGNvbHVtbnMgPSBsaXN0IChicmVhY2hlcyA9IGNvbERlZihzdHlsZSA9IGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgaWYgKHZhbHVlIDwgMzAwMCkge2NvbG9yIDwtICIjMDA4MDAwIg0KICAgIH0gZWxzZSBpZiAodmFsdWUgPiAzMDAxKSB7Y29sb3IgPC0gIiNlMDAwMDAiDQogICAgfSBlbHNlIHtjb2xvciA8LSAiIzc3NyJ9DQogICAgbGlzdChjb2xvciA9IGNvbG9yLCBmb250V2VpZ2h0ID0gImJvbGQiKQ0KICB9KQ0KICApLA0KICBkZWZhdWx0Q29sRGVmID0gY29sRGVmKGZvb3RlciA9IGZ1bmN0aW9uKHZhbHVlcykgew0KICAgIGlmICghaXMubnVtZXJpYyh2YWx1ZXMpKSByZXR1cm4oKQ0KICAgIHNwYXJrbGluZSh2YWx1ZXMsIHR5cGUgPSAiYm94Iiwgd2lkdGggPSAxMDAsIGhlaWdodCA9IDMwKQ0KICB9KQ0KKQ0KYGBgDQoNCihXYW50IHRvIGJlIHN1cGVyIGltcHJlc3NlZD8gIEhvdmVyIG92ZXIgdGhlIHNwYXJrIGJveCkNCg0KKioqDQojIyMgTGV0cyBnZXQgcGxvdHRpbmcuLi4NCioqKg0KDQpPZiBjb3Vyc2Ugd2UgY2FuIGFkZCBhIHBsb3QsIHlvdSBjYW4gY2hhbmdlIHRoZSBzaXplLCBhbGlnbm1lbnQgYW5kIGFsbCBvZiB0aGF0IHN0dWZmLiAgWW91IGNhbiB3cmFwIHlvdXIgdGV4dCBhcm91bmQgYSBwbG90IGFuZCBwb3RlbnRpYWxseSBoYXZlIHBsb3RzIHNpZGUgYnkgc2l6ZS4NCg0KWW91IG5lZWQgdG8gc3dpdGNoIHRvIHRoZSBjb2RlIGhlcmUgZm9yIGEgbGl0dGxlIGZ1bmt5IHBsb3R0aW5nIHNob3J0IGN1dC4NCg0KIyBMaWJyYXJ5IC0gZXNxdWlzc2UNCg0KYGBge3IgcGxvdHR5bWNwbG90ZmFjZX0NCg0KIyMgc28gd2Ugd2FudCB0byBpbmNsdWRlIGEgcGxvdCAtIGJ1dCB3aGF0IHBsb3Qgc2hhbGwgd2UgbWFrZT8NCiMjIGhvcGVmdWxseSB3ZSBoYXZlIGEgYml0IG9mIGtub3dsZWRnZSBvZiBnZ3Bsb3QgYnV0IHNvbWV0aW1lcyBhIGxpdHRsZSB0cmlja3kgdG8gcGxheSB3aXRoIA0KIyNvciB5b3UgbWF5IHdhbnQgdG8gcXVpY2tseSBoYXZlIGEgbG9vayBhdCBhIG51bWJlciBvZiBwbG90cyB0byBzZWUgd2hpY2ggb25lIGlzIGJlc3QgZm9yIHlvdS4NCg0KIyNpbnRyb2R1Y2luZyB0aGUgZXNxdWlzc2UgcGFja2FnZSAoZnJlbmNoIHdvcmQgdGhhdCBtZWFucyAnYSByb3VnaCBvciBwcmVsaW1pbmFyeSBza2V0Y2gnKSANCg0KIyMgbGV0cyBqdXN0IG1ha2UgYSBxdWljayBjdXQgZG93biBkYXRhc2V0DQpkYXRhNCA8LSBkYXRhICU+JSBmaWx0ZXIgKG9yZ19jb2RlID09IlJYUSIpDQoNCg0KDQojIyBjbGljayBpbiB0aGUgY29kZSB3aGVyZSB5b3Ugd291bGQgbGlrZSB0byBhZGQgc29tZSBwbG90IGNvZGUNCg0KIyMgIGVzcXVpc3NlcihkYXRhKSAgICMjcnVuIHRoaXMgaW4gdGhlIGNvbnNvbGUNCg0KIyMgIGRyYWcgcGVyaW9kIHRvIHgNCiMjICBkcmFnIGF0dGVuZGFuY2VzIHRvIHkNCiMjICBkcmFnIHR5cGUgdG8gZ3JvdXANCiMjICBjYW4gYWxzbyBwbGF5ICB3aXRoIGZvcm1hdHMgYW5kIHRoZW1lcyBhbmQgZmlsdGVyIHRoZSBkYXRhIHRvIGEgc21hbGwgYW1vdW50DQojIyAgY2FuIHRoZW4gcGxhY2UgY29kZSBpbnRvIHlvdXIgc2NyaXB0DQoNCiMjIHRhIGRhIQ0KDQpnZ3Bsb3QoZGF0YTQsIGFlcyh4ID0gcGVyaW9kLCB5ID0gYXR0ZW5kYW5jZXMsIGdyb3VwID0gdHlwZSwgY29sb3VyID0gdHlwZSkpICsNCiBnZW9tX2xpbmUoc2l6ZSA9IDEuMzIpICsNCiBsYWJzKHRpdGxlID0gIlJYUSBOdW1iZXIgb2YgYXR0ZW5kYW5jZXMgYnkgdHlwZSIpICsNCiB0aGVtZV9taW5pbWFsKCkNCg0KDQpgYGANCg0KU28gdGhhdCdzIGEgcGxvdCwgZG9lcyB3aGF0IGl0IHNheXMgb24gdGhlIHRpbiwgYnV0IHdoYXQgaXMgYmV0dGVyIHRoYW4gYSBzdGF0aWMgcGxvdD8NCg0KSW50ZXJhY3RpdmUgcGxvdHMuLi4NCg0KDQojIExpYnJhcnkgLSBwbG90bHkNCg0KYGBge3IgaW50ZXJhY3RpdmVwbG90dHltY3Bsb3RmYWNlfQ0KDQojI3Rha2Ugb3VyIG5vcm1hbCBncmFwaCB3ZSBqdXN0IG1hZGUgYW5kIG1ha2UgaXQgYW4gb2JqZWN0DQoNCnAxIDwtIGdncGxvdChkYXRhNCwgYWVzKHggPSBwZXJpb2QsIHkgPSBhdHRlbmRhbmNlcywgZ3JvdXAgPSB0eXBlLCBjb2xvdXIgPSB0eXBlKSkgKw0KIGdlb21fbGluZShzaXplID0gMS4zMikgKw0KIGxhYnModGl0bGUgPSAiUlhRIE51bWJlciBvZiBhdHRlbmRhbmNlcyBieSB0eXBlIikgKw0KIHRoZW1lX21pbmltYWwoKQ0KDQojIyB0aGVuIHNpbXBseSAoZ2cpcGxvdGx5IGl0Li4NCg0KZ2dwbG90bHkocDEpDQoNCmBgYA0KDQoNCiogWW91IGNhbiBjbGljayBvbiB0aGUgbGVnZW5kIHRvIGFkZCBvciByZW1vdmUgbGluZQ0KKiBZb3UgY2FuIGNsaWNrIGFuZCBkcmFnIGFuIGFyZWEgdG8gem9vbSBpbiBvbg0KKiBZb3UgY2FuIGhvdmVyIG92ZXIgbGluZSB0byBzZWUgZGF0YSBwb2ludHMNCiogWW91IGNhbiBleHBvcnQgYXMgYW4gaW1hZ2UNCg0KQWxsIGlzIGZhciBtb3JlIGN1c3RvbWlzYWJsZSB3aXRoaW4gdGhlIHBsb3RseSBmdW5jdGlvbiwgeW91IGNhbiBoYXZlIG11bHRpcGxlIHNlbGVjdC1hYmxlIGRhdGEgc2V0cyBhbmQgYWxsIG1hbm5lciBvZiBvdGhlciBzdHVmZi4NCg0KIyMgQW5pbWF0ZWQgZ3JhcGhzDQoNClByZXR0eSBjb29sIGJ1dCBsZXRzIHNob3cgb2ZmIGFuZCBhbmltYXRlDQoNCg0KYGBge3IgYW5pbWF0ZWRwbG90dHltY3Bsb3RmYWNlfQ0KDQpkYXRhNSA8LSBkYXRhNA0KDQphY2N1bXVsYXRlX2J5IDwtIGZ1bmN0aW9uKGRhdCwgdmFyKSB7DQogIHZhciA8LSBsYXp5ZXZhbDo6Zl9ldmFsKHZhciwgZGF0KQ0KICBsdmxzIDwtIHBsb3RseTo6OmdldExldmVscyh2YXIpDQogIGRhdHMgPC0gbGFwcGx5KHNlcV9hbG9uZyhsdmxzKSwgZnVuY3Rpb24oeCkgew0KICAgIGNiaW5kKGRhdFt2YXIgJWluJSBsdmxzW3NlcSgxLCB4KV0sIF0sIGZyYW1lID0gbHZsc1tbeF1dKQ0KICB9KQ0KICBkcGx5cjo6YmluZF9yb3dzKGRhdHMpDQp9DQoNCmRhdGE1JHllYXIgPC0geWVhcihkYXRhNSRwZXJpb2QpDQpkYXRhNSRkYXRlIDwtIGRlY2ltYWxfZGF0ZShkYXRhNSRwZXJpb2QpDQpmaWcgPC0gZGF0YTUgJT4lIGFjY3VtdWxhdGVfYnkofnBlcmlvZCkNCg0KZmlnIDwtIGZpZyAlPiUNCiAgcGxvdF9seSgNCiAgICB4ID0gfmRhdGUsIA0KICAgIHkgPSB+YXR0ZW5kYW5jZXMsDQogICAgc3BsaXQgPSB+dHlwZSwNCiAgICBmcmFtZSA9IH5mcmFtZSwgDQogICAgI3R5cGUgPSAnc2NhdHRlcicsDQogICAgbW9kZSA9ICdsaW5lcycgDQogICAjIG1vZGUgPSAnbGluZXMrbWFya2VycycsDQogICAjIHR5cGUgPSAnc2NhdHRlcicsIA0KICAjICBtb2RlID0gJ25vbmUnLCANCiAgIyAgZmlsbCA9ICd0b3plcm95JywNCiAgIyAgbGluZSA9IGxpc3Qoc2ltcGx5ZnkgPSBUKQ0KICApDQpmaWcgPC0gZmlnICU+JSBsYXlvdXQoDQogIHhheGlzID0gbGlzdCgNCiAgICB0aXRsZSA9ICJEYXRlIiwNCiAgICB6ZXJvbGluZSA9IEYNCiAgKSwNCiAgeWF4aXMgPSBsaXN0KA0KICAgIHRpdGxlID0gIkFkbWlzc2lvbnMiLA0KICAgIHplcm9saW5lID0gVA0KICApDQopIA0KZmlnIDwtIGZpZyAlPiUgYW5pbWF0aW9uX29wdHMoDQogIGZyYW1lID0gMTAwLCANCiAgdHJhbnNpdGlvbiA9IDAsIA0KICByZWRyYXcgPSBUUlVFDQopDQpmaWcgPC0gZmlnICU+JSBhbmltYXRpb25fc2xpZGVyKA0KICBoaWRlID0gRg0KKQ0KZmlnIDwtIGZpZyAlPiUgYW5pbWF0aW9uX2J1dHRvbigNCiAgeCA9IDEsIHhhbmNob3IgPSAicmlnaHQiLCB5ID0gMCwgeWFuY2hvciA9ICJib3R0b20iDQopDQoNCmZpZw0KDQpgYGANCg0KT2J2aW91c2x5IHByZXR0eSBwb2ludGxlc3MgaW4gdGhpcyBleGFtcGxlLCBidXQgbWF5IGJlIGdvb2QgYXMgYSB3YXkgdG8gYmUgbW9yZSB2aXN1YWwgdG8gZ2V0IGEgcG9pbnQgYWNyb3NzLiAgDQoNCklmIGl0IGdldHMgcGVvcGxlIGFjdHVhbGx5IGxvb2tpbmcgYXQgdGhlIGRhdGEgYW5kIHdhbnRpbmcgdGhlaXIgbGl0dGxlIHdpZ2dseSBsaW5lcyBnb2luZyB1cCB0aGF0IGhhcyB0byBiZSBnb29kIGZvciBwYXRpZW50IGNhcmUuDQoNCiMgTGlicmFyeSAtIGR5Z3JhcGhzDQoNClNvIGhvdyBhYm91dCB3ZSB0YWtlIHRoZSBhZG1pc3Npb25zIGRhdGEgZm9yIHRoZSBwcm92aWRlcnMgYWJvdmUgYW5kIGNyZWF0ZSBhIG5pY2UgdGltZSBzZXJpZXMgZ3JhcGguICBUaGlzIERZIGdyYXBoIGlzIG5pY2UgZm9yIHBsYXlpbmcgd2l0aCB0aW1lIHNlcmllcyBhcyBpdCBhbGxvd3MgeW91IHRvIHpvb20gaW4gb24gY2VydGFpbiBhcmVhcy4NCg0KVGhlcmUgaXMgYWxzbyBhIG5pY2UgbGl0dGxlIGJveCBvbiB0aGUgYm90dG9tIGxlZnQgb2YgdGhlIGdyYXBoLiAgVGhpcyBhbGxvd3MgeW91IHRvIHNtb290aCB5b3VyIGRhdGEgd2l0aCBhIHJvbGxpbmcgYXZlcmFnZSBvbiB0aGUgZmx5LiAgUmVhbGx5IHVzZWZ1bCBmb3IgdGhpbmdzIHN1Y2ggYXMgbGVuZ3RoIG9mIHN0YXkgb3IgdGhpbmdzIHdpdGggbG90cyBvZiB2YXJpYWJsaXR5IGFuZCB0cnlpbmcgdG8gcHVsbCBvdXQgYW4gb3ZlcmFsbCB0cmVuZC4NCg0KDQpgYGB7ciBpbnRlcmFjdGl2ZXRpbWVzZXJpZXNwbG90dHltY3Bsb3RmYWNlfQ0KDQpkYXRhMTQgPC0gZGF0YTQgJT4lIGZpbHRlcih0eXBlPT0nMScpICU+JSBzZWxlY3QoJ3BlcmlvZCcsICdhdHRlbmRhbmNlcycpIA0KDQojIFRoZW4geW91IGNhbiBjcmVhdGUgdGhlIHh0cyBuZWNlc3NhcnkgdG8gdXNlIGR5Z3JhcGgNCmRvbiA8LSB4dHMoeCA9IGRhdGExNCRhdHRlbmRhbmNlcywgb3JkZXIuYnkgPSBkYXRhMTQkcGVyaW9kKQ0KDQoNCg0KIyBGaW5hbGx5IHRoZSBwbG90DQpwIDwtIGR5Z3JhcGgoZG9uLCBtYWluID0gIkFkbWlzc2lvbnMgb3ZlciB0aW1lIikgJT4lDQogIGR5T3B0aW9ucyhsYWJlbHNVVEMgPSBUUlVFLCBmaWxsR3JhcGg9VFJVRSwgZmlsbEFscGhhPTAuMSwgZHJhd0dyaWQgPSBGQUxTRSwgY29sb3JzPSIjRDhBRTVBIiwpICU+JQ0KICBkeVJhbmdlU2VsZWN0b3IoKSAlPiUNCiAgZHlDcm9zc2hhaXIoZGlyZWN0aW9uID0gInZlcnRpY2FsIikgJT4lDQogIGR5SGlnaGxpZ2h0KGhpZ2hsaWdodENpcmNsZVNpemUgPSA1LCBoaWdobGlnaHRTZXJpZXNCYWNrZ3JvdW5kQWxwaGEgPSAwLjIsIGhpZGVPbk1vdXNlT3V0ID0gRkFMU0UpICU+JQ0KICBkeVJvbGxlcihyb2xsUGVyaW9kID0gMCkgJT4lDQogIGR5QXhpcygieSIsIGxhYmVsID0gIk51bWJlciBvZiBhZG1pc3Npb25zIikNCg0KcA0KDQpgYGANCg0KT3RoZXIgZ29vZCBmdW5jdGlvbnMgZm9yIHZpc3VhbGlzaW5nIGRhdGEgc2V0cy4NCg0KIyBMaWJyYXJ5IC0gVHJlZW1hcA0KDQpPbmUgaXMgdHJlZW1hcCwgaXQgaXMgbGlrZSBhIHBvc2ggcGllIGNoYXJ0IGZvciBsb29raW5nIGF0IHByb3BvcnRpb25zIG9mIGEgdmFyaWFibGUuDQoNCk9idmlvdXNseSBSICoqY2FuKiogZG8gcGllIGNoYXJ0cywgYnV0IEkgd2hlcmVhcyBJIGFtIHdpbGxpbmcgdG8gc2hvdyB5b3UgaG93IGFkZCBhbmltYXRlZCBnaWZzIGludG8geW91ciByZXBvcnRzLCBldmVuIEkgd291bGQgbm90IHNpbmsgdGhhdCBsb3cuIA0KDQpgYGB7ciB0cmVlbWFwfQ0KDQpkYXRhOCA8LSBkYXRhICU+JSBmaWx0ZXIgKHR5cGUgPT0gJzInLCBwZXJpb2QgPT0gJzIwMTgtMDQtMDEnKQ0KDQoNCnRyZWVtYXAoZGF0YTgsIGluZGV4PWMoIm9yZ19jb2RlIiwgInR5cGUiKSx2U2l6ZT0iYXR0ZW5kYW5jZXMiKQ0KDQoNCmBgYA0KDQpUaGlzIGlzIGEgbmljZSBvdmVydmlldyBvZiBhIGxhcmdlIGFtb3VudCBvZiBkYXRhLCBnZXRzIGEgYml0IG1lc3N5IHdoZW4geW91IGhhdmUgYSBsb3Qgb2YgZmFjdG9ycw0KDQojIExpYnJhcnkgLSBjb2xsYXBzaWJsZVRyZWUNCg0KQW5vdGhlciByZWFsbHkgY29vbCB0aGluZyB0byBwbGF5IHdpdGggaXMgYSBkZW5kcm9ncmFtIHdoaWNoIHlvdSBjYW4gbWFrZSB3aXRoIGNvbGxhcHNpYmxlVHJlZS4gDQoNClRoaXMgaXMgcmVhbGx5IGdvb2QgYXQgc2hvd2luZyBmbG93IHRocm91Z2ggcGF0aHdheXMgYW5kIHN5c3RlbXMuICBZb3UgY2FuIG1ha2UgdGhlbSBob3Jpem9udGFsIG9yIHZlcnRpY2FsIGFuZCBwbGF5IHdpdGggYWxsIG1hbm5lciBvZiBiaXRzIG9uIHRoZSBub2Rlcy4NCg0KQ2xpY2sgb24gdGhlIG5vZGVzIGFuZCB5b3UgY2FuIGFsc28gem9vbSBpbiBhbmQgb3V0IGFuZCBzY3JvbGwgYXJvdW5kLg0KDQpJIGFsc28gZmluZCBpdCByZWFsbHkgcmVsYXhpbmcgZm9yIHNvbWUgcmVhc29uLg0KDQoNCmBgYHtyIGNvbGxhcHNlYWJsZXRyZWV9DQoNCmRhdGE2IDwtIGRhdGEgJT4lIGZpbHRlciAob3JnX2NvZGUgJWluJSBjKCJSSzkiLCAiUldKIiwgIkFEOTEzIikpDQoNCg0KDQpjb2xsYXBzaWJsZVRyZWUoIGRhdGE2LCBjKCJvcmdfY29kZSIsICJ0eXBlIiwicGVyaW9kIiwgImF0dGVuZGFuY2VzIiksIG5vZGVTaXplID0gJ2xlYWZDb3VudCcsIHJvb3QgPSAnQmFzZSBkYXRhJywgdG9vbHRpcCA9IFRSVUUpDQoNCmBgYA0KDQojIExpYnJhcnkgLSBMZWFmbGV0DQoNCkxlYWZsZXQgaXMgYSBncmVhdCBtYXBwaW5nIGxpYnJhcnkgYW5kIHdvcmtzIHdpdGggb3BlbiBzdHJlZXQgbWFwIHNvIHlvdSBkb24ndCBoYXZlIHRvIHdvcnJ5IGFib3V0IGdvb2dsZSBBUEkgdG9rZW5zIGFuZCB0aGUgbGlrZS4gIFRoZXJlIGFyZSBzb21lIGZhbnRhc3RpYyB0aGluZ3MgeW91IGNhbiBkbyB3aXRoIHRoZSBnb29nbGUgc2VydmljZSB3aGljaCBhbGxvd3MgeW91IHRvIGFjY2VzcyB0cmF2ZWwgdGltZXMgYW5kIHJvdXRlIGZpbmRpbmcsIGhvd2V2ZXIgZm9yIHNpbXBsZSBtYXBwaW5nIGxlYWZsZXQgaXMgZ3JlYXQuICBZb3UgY2FuIGRvIGhlYXRtYXBzIGFuZCBhcmVhcywgZHJhdyBsaW5lcyBhY3Jvc3MgcG9pbnRzIGFuZCBhbHNvIGFkZCBsYXllcnMgdGhhdCB5b3UgY2FuIHNlbGVjdCBvbiBhbmQgb2ZmLiAgDQoNClRoaXMgZXhhbXBsZSBoYXMgMyB0ZWFtcyB0aGF0IGFyZSBzZXQgdXAgYXMgbGF5ZXJzIGFuZCB5b3VjYW4gdHVybiBlYWNoIG9uZSBvbiBhbmQgb2ZmLiAgDQoNClRoZSBtYXBzIGNhbiBiZSBzY3JvbGxlZCBhbmQgem9vbWVkLCB3aGF0IGlzIG5pY2UgaXMgdGhlIGljb25zIHJlbWFpbiB0byBzY2FsZS4NCg0KDQpgYGB7ciBtYXBweW1jbWFwZmFjZX0NCg0KIyMgY3JlYXRlcyBhIGJhc2ljIGRhdGFmcmFtZSB3aXRoIHNvbWUgdGVhbXMgYW5kIHBvc3Rjb2Rlcw0KbGFiZWwgPC0gYygnVGVhbSBBJywgJ1RlYW0gQScsICdUZWFtIEInLCAnVGVhbSBCJywgJ1RlYW0gQycpDQpwb3N0Y29kZSA8LSBjKCdFWDE2IDdGTCcsICdFWDM5IDVFTicsICdQTDEzIDJXUCcsICdQTDE1IDhSWicsICdQTDMwIDRQWCcpDQpkZiA8LSBkYXRhLmZyYW1lKGxhYmVsLHBvc3Rjb2RlKQ0KDQojIyBUaGlzIGlzIHRoZSBtYWdpYyBiaXQgdGhhdCB1c2VzIHRoZSB0aWR5Z2VvY29kZXIgcGFja2FnZSB0byBmaW5kIGxvbmdhdHVkZXMgYW5kIGxhdGl0dWRlcw0KZGYgPC0gZGYgJT4lIG11dGF0ZSggZ2VvKGFkZHJlc3MgPSBkZiRwb3N0Y29kZSwgbWV0aG9kID0gJ29zbScpKQ0KDQojIyBGaWx0ZXJzIGNvaG9ydCBpbnRvIHRocmVlIGxpc3RzLCBvbmUgZm9yIGVhY2ggaWNvbnNldA0KY29ob3J0X2ZpbHRlcjEgPC0gZGYgJT4lDQogIGZpbHRlcihkZiRsYWJlbCA9PSAiVGVhbSBBIikNCmNvaG9ydF9maWx0ZXIyIDwtIGRmICU+JQ0KICBmaWx0ZXIoZGYkbGFiZWwgPT0gIlRlYW0gQiIpDQpjb2hvcnRfZmlsdGVyMyA8LSBkZiAlPiUNCiAgZmlsdGVyKGRmJGxhYmVsID09ICJUZWFtIEMiKQ0KDQojIyAgQ3JlYXRlIGF3ZXNvbWUgaWNvbiBzZXRzIGZvciBjb2xvdXJzDQppY29uU2V0IDwtIGF3ZXNvbWVJY29uTGlzdCgNCiAgIlRlYW0gQSIgID0gbWFrZUF3ZXNvbWVJY29uKCBpY29uID0gJ21hbGUnLCBsaWIgPSAnZmEnLCBpY29uQ29sb3IgPSAiYmxhY2siLCBtYXJrZXJDb2xvciA9ICJyZWQiICAgLCBzcGluID0gRkFMU0UgKSAsDQogICJUZWFtIEIiICAgICAgICAgICAgID0gbWFrZUF3ZXNvbWVJY29uKCBpY29uID0gJ21hbGUnLCBsaWIgPSAnZmEnLCBpY29uQ29sb3IgPSAiYmxhY2siLCBtYXJrZXJDb2xvciA9ICJvcmFuZ2UiLCBzcGluID0gRkFMU0UgKSAsDQogICJUZWFtIEMiICAgICAgID0gbWFrZUF3ZXNvbWVJY29uKCBpY29uID0gJ21hbGUnLCBsaWIgPSAnZmEnLCBpY29uQ29sb3IgPSAiYmxhY2siLCBtYXJrZXJDb2xvciA9ICJiZWlnZSIgLCBzcGluID0gRkFMU0UgKSApDQoNCiMjIENyZWF0ZXMgbGF5b3JzIGZvciBtYXAsIGVhY2ggZm9yIHRoZSB0aHJlZSBpY29uc2V0ICdUZWFtcycNCm1hcCA8LSBsZWFmbGV0KGRmKSAlPiUgIA0KICBhZGRUaWxlcygpICU+JQ0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRPcGVuU3RyZWV0TWFwKSAlPiUgDQogIGFkZEF3ZXNvbWVNYXJrZXJzKCBsbmcgPSBjb2hvcnRfZmlsdGVyMSRsb25nLA0KICAgICAgICAgICAgICAgICAgICAgbGF0ID0gY29ob3J0X2ZpbHRlcjEkbGF0LA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAiVGVhbSBBIiwNCiAgICAgICAgICAgICAgICAgICAgIGljb24gPSBpY29uU2V0W2NvaG9ydF9maWx0ZXIxJGxhYmVsXSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUoc2VwID0gIiAtICIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvaG9ydF9maWx0ZXIxJGxhYmVsICkgKSAlPiUNCiAgYWRkQXdlc29tZU1hcmtlcnMoIGxuZyA9IGNvaG9ydF9maWx0ZXIyJGxvbmcsDQogICAgICAgICAgICAgICAgICAgICBsYXQgPSBjb2hvcnRfZmlsdGVyMiRsYXQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9ICJUZWFtIEIiLA0KICAgICAgICAgICAgICAgICAgICAgaWNvbiA9IGljb25TZXRbY29ob3J0X2ZpbHRlcjIkbGFiZWxdLA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZShzZXAgPSAiIC0gIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ob3J0X2ZpbHRlcjIkbGFiZWwgKSApICU+JQ0KICBhZGRBd2Vzb21lTWFya2VycyggbG5nID0gY29ob3J0X2ZpbHRlcjMkbG9uZywNCiAgICAgICAgICAgICAgICAgICAgIGxhdCA9IGNvaG9ydF9maWx0ZXIzJGxhdCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gIlRlYW0gQyIsDQogICAgICAgICAgICAgICAgICAgICBpY29uID0gaWNvblNldFtjb2hvcnRfZmlsdGVyMyRsYWJlbF0sDQogICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlKHNlcCA9ICIgLSAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2hvcnRfZmlsdGVyMyRsYWJlbCApICkgJT4lIA0KICBhZGRMYXllcnNDb250cm9sKG92ZXJsYXlHcm91cHMgPSBjKCJUZWFtIEEiLCAiVGVhbSBCIiwgIlRlYW0gQyIpLCAgICAjI3RoaXMgYml0IGFkZHMgdGhlIGNvbnRyb2xzDQogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IEZBTFNFKSApIA0KDQptYXANCg0KYGBgDQoNCiMgTGlicmFyeSAtIFdvcmRjbG91ZDINCg0KV29yZGNsb3VkMiBpcyB0aGUgc2VxdWVsIHRvIHdvcmRjbG91ZCwgbXVjaCBsaWtlIEV2aWwgRGVhZCAyIHRvIHRoZSBvcmlnaW5hbCwgaXQgaXMgYSBmYXIgc3VwZXJpb3IgcHJvZHVjdCwgaXQgaGFzIHNvbWUgcmVhbGx5IG5pY2UgZWFzeSB0byB1c2UgZmVhdHVyZXMgYW5kIGNhbiBtYWtlIGFsbCBtYW5uZXIgb2YgZGlmZmVyZW50IHdvcmRjbG91ZHMgdHlwZXMuICANCg0KSG93ZXZlciBiZWZvcmUgeW91IGdldCB0byBhIHdvcmQgY2xvdWQgeW91IG5lZWQgc29tZSBkYXRhIHdoaWNoIGlzIGJhc2ljYWxseSBhIGxpc3Qgb2Ygd29yZHMgYW5kIHRoZWlyIGZyZXF1ZW5jeS4gIFlvdSBjYW4gZG8gdGhpcyBtYW51YWxseSBvbiB5b3VyIGZpbmdlcnMgb3IgeW91IGNhbiBnZXQgUiB0byBkbyB0aGlzIGZvciB5b3UuICBJIGRlZmluYXRlbHkgcmVjb21tZW5kIHRoZSBsYXR0ZXIuDQoNClRvIGdldCB0byB0aGF0IHlvdSByZWFkIGluIHNvbWUgZGF0YSwgc3RyaXAgb3V0IGFsbCB0aGUgZ3ViYmlucyBzdWNoIGFzIHB1bmN0dWF0aW9uLCByZW1vdmUgYWxsIHRoZSAnc3RvcCB3b3Jkcycgc3VjaCBhcyAndGhlJyBhbmQgJ2FuZCcgZXRjIGFuZCB0aGVuIHJlbW92ZSB3aGl0ZSBzcGFjZSBhbmQgdGhlcmUgeW91IGhhdmUgYSBidW5jaCBvZiB3b3JkcyBmaXQgZm9yIGEgY2xvdWQuDQoNClRoaXMgaXMgYW4gZXhhbXBsZSB0aGF0IHB1bGxzIHRoZSB0ZXh0IGZyb20gYSBwb3B1bGFyIGNoaWxkcmVucyBub3ZlbCBhbmQgY3JlYXRlcyBhIGNsb3VkLiAgSG9wZWZ1bGx5IHlvdSBjYW4gZ3Vlc3MgdGhlIGJvb2sgZnJvbSB0aGUgY2xvdWQuDQoNCllvdSBjYW4gaG92ZXIgb3ZlciB0aGUgd29yZHMgaW4gdGhlIGNsb3VkIGFuZCBpdCB3aWxsIHRlbGwgeW91IHRoZSB3b3JkIGFuZCBnaXZlIHlvdSB0aGUgbnVtYmVyIG9mIHRoZSBmcmVxdWVuY3kuDQoNCg0KYGBge3IgY2xvdWR5d2l0aGFjaGFuY2VvZndvcmRzfQ0KDQojIyMjIyBOb3RlIHRoYXQgdGhpcyBzZWN0aW9uIG1heSBub3QgcnVuIGlmIHlvdXIgVlBOIGhhcyBoaWdoIHNlY3VyaXR5ICMjIyMjIA0KIyMgcmVhZHMgaW4gdGV4dCBmaWxlIGZyb20gdGhlIGludGVyd2Vieg0KZmlsZVBhdGggPC0gImh0dHBzOi8vd3d3Lmd1dGVuYmVyZy5vcmcvZmlsZXMvMTEvMTEtMC50eHQiDQp0ZXh0IDwtIHJlYWRMaW5lcyhmaWxlUGF0aCkNCg0KIyNjb252ZXJ0cyB0aGUgZmlsZSBpbnRvIGEgY29ycHVzICh2ZWN0b3IgZmlsZSBmb3IgdGV4dCBtaW5pbmcpDQpkb2NzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodGV4dCkpDQoNCiMjIHJlbW92ZXMgc3BhY2VzIGFzIGFuZCBvZGQgY2hhcmFjdGVycw0KdG9TcGFjZSA8LSBjb250ZW50X3RyYW5zZm9ybWVyKGZ1bmN0aW9uICh4ICwgcGF0dGVybiApIGdzdWIocGF0dGVybiwgIiAiLCB4KSkNCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHRvU3BhY2UsICIvIikNCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHRvU3BhY2UsICJAIikNCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHRvU3BhY2UsICJcXHwiKQ0KZG9jcyA8LSB0bV9tYXAoZG9jcywgdG9TcGFjZSwgIiciKQ0KZG9jcyA8LSB0bV9tYXAoZG9jcywgdG9TcGFjZSwgImAiKQ0KIyBSZW1vdmUgcHVuY3R1YXRpb25zDQpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVQdW5jdHVhdGlvbikNCiMgQ29udmVydCB0aGUgdGV4dCB0byBsb3dlciBjYXNlDQpkb2NzIDwtIHRtX21hcChkb2NzLCBjb250ZW50X3RyYW5zZm9ybWVyKHRvbG93ZXIpKQ0KIyBSZW1vdmUgbnVtYmVycw0KZG9jcyA8LSB0bV9tYXAoZG9jcywgcmVtb3ZlTnVtYmVycykNCiMgUmVtb3ZlIGVuZ2xpc2ggY29tbW9uIHN0b3B3b3Jkcw0KZG9jcyA8LSB0bV9tYXAoZG9jcywgcmVtb3ZlV29yZHMsIHN0b3B3b3JkcygiZW5nbGlzaCIpKQ0KIyBzcGVjaWZ5IHlvdXIgc3RvcHdvcmRzIGFzIGEgY2hhcmFjdGVyIHZlY3RvciAtIGluIHRoaXMgaW5zdGFuY2UgaXQgd2FzIHBpY2tpbmcgdXAgc29tZSBvZiB0aGUgY29weXJpZ2h0IG5vdGljZQ0KZG9jcyA8LSB0bV9tYXAoZG9jcywgcmVtb3ZlV29yZHMsIGMoInByb2plY3QiLCAibGljZW5zZSIsICJjb3B5cmlnaHQiLCJndXRlbmJlcmciLCJlbGVjdHJvbmljIiwiYWdyZWVtZW50IiwiZ3V0ZW5iZXJndG0iKSkgDQojIEVsaW1pbmF0ZSBleHRyYSB3aGl0ZSBzcGFjZXMNCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHN0cmlwV2hpdGVzcGFjZSkNCiNpdCB3YXMgc3RpbGwgYnJpbmdpbmcgYmFjayBzb21lIHF1b3RhdGlvbiBtYXJrcyBhbmQgc28gdGhpcyBmaW5hbGx5IHJlbW92ZXMgd2hhdCBpcyBsZWZ0DQpyZW1vdmVTcGVjaWFsQ2hhcnMgPC0gZnVuY3Rpb24oeCkgZ3N1YigiW15hLXpBLVowLTkgXSIsIiIseCkNCmRvY3MgPC0gdG1fbWFwKGRvY3MsIGNvbnRlbnRfdHJhbnNmb3JtZXIocmVtb3ZlU3BlY2lhbENoYXJzKSkNCg0KIyB0aGlzIGJpdCBzb3J0cyBhbmQgcmFua3MgdGhlIHdvcmQgZnJlcXVlbmNpZXMgYW5kIHBsb25rcyBpbnRvIHRoZSBkYXRhZnJhbWUgJ2QnDQpkdG0gPC0gVGVybURvY3VtZW50TWF0cml4KGRvY3MpDQptIDwtIGFzLm1hdHJpeChkdG0pDQp2IDwtIHNvcnQocm93U3VtcyhtKSxkZWNyZWFzaW5nPVRSVUUpDQpkIDwtIGRhdGEuZnJhbWUod29yZCA9IG5hbWVzKHYpLGZyZXE9dikNCg0KIyB0aGlzIGlzIHRoZSBsaW5lIHRoYXQgY3JlYXRlcyB0aGUgd29yZCBjbG91ZA0Kd29yZGNsb3VkMihkLCBjb2xvciA9ICJyYW5kb20tbGlnaHQiLCBiYWNrZ3JvdW5kQ29sb3IgPSAid2hpdGUiKQ0KYGBgDQoNCiMgTGlicmFyeSAtIFJwaXZvdHRhYmxlDQoNClNhdmluZyBwZXJoYXBzIG15IGZhdm9yaXRlIHVudGlsIGxhc3QsIGlzIHRoZSBzdXBlciBhd2Vzb21lIFJwaXZvdHRhYmxlLg0KDQpUaGlzIGhhcyBmdWxsIGNsaWNrIGFuZCBkcmFnIGZ1bmN0aW9uYWxpdHkgYXMgd2VsbCB0aGUgb3B0aW9uIHRvIHNldCB1cCBkZWZhdWx0cyBpbiB0aGUgcmVwb3J0IGFuZCBhbHNvIHlvdSBjYW4gY2xpY2sgdGhyb3VnaCwgY3JlYXRlIGNoYXJ0cyBhbmQgaGVhdCBtYXBzLCBmaWx0ZXIgeW91ciBkYXRhLCBjYWxjdWxhdGUgYSBwaXZvdCB0YWJsZSB3aXRoIGEgbWVkaWFuIGFuZCBqdXN0IGRvIGFsbCBzb3J0cyBvZiBtYWdpYy4NCg0KWW91IGNhbiBjbGljayBhbmQgZHJhZyB0aGUgdmFyaWFibGVzIGFyb3VuZC4gIFlvdSBjYW4gY2xpY2sgb24gdGhlIGFycm93cyB0byB0aGUgc2lkZSBvZiB0aGUgdmFyaWFibGVzIHRvIGZpbHRlciB0aGVtLiAgWW91IGNhbiBjbGljayBvbiB0aGUgY291bnQgdG8gc2VsZWN0IGEgZGlmZmVyZW50IG1ldHJpYyBhbmQgZmluYWxseSB5b3UgY2FuIGNsaWNrIG9uIHRoZSB0YWJsZSB0byBjaGFuZ2UgdGhlIHJlc3VsdHMgdG8gYSBncmFwaCBvciBoZWF0bWFwIG9yIGxvYWRzIG9mIHRoaW5ncy4gDQoNCkl0IGRvZXNuJ3QgbGlrZSBzdXBlciBodWdlIGRhdGEgc2V0cyBpZiB5b3UgYXJlIHJ1bm5pbmcgaXQgbG9jYWxseSBidXQgaWYgeW91IGdldCBjbGV2ZXIgd2l0aCBzaGlueSwgeW91IGNhbiBkbyBiaWcgdGhpbmdzLg0KDQpJdCBhbHNvIGhhcyBhIGhhYmJpdCBvZiBvdmVybGFwcGluZyB3aXRoIHN0dWZmIGJlbG93IGl0LiAgSSBhbSB3b3JraW5nIG9uIGEgSFROTCBzb2x1dGlvbiB0byB0aGlzIGFuZCBJIHRoaW5rIHRoaXMgaXMgYSAnZmVhdHVyZScgdGhhdCBpcyBiZWluZyB3b3JrZWQgb24gYnkgdGhlIGRldmVsb3BlcnMuICBJIHVzdWFsbHkganVzdCBhZGQgaXQgYXQgdGhlIGVuZCBvZiBhIHJlcG9ydCBvciBvbiBhIHNlcGVyYXRlIHRhYiB0byBnZXQgYXJvdW5kIHRoaXMgaXNzdWUuDQoNClRoaXMgd2hvbGUgZnVuY3Rpb25hbGl0eSBpcyBkb25lIHdpdGggb25lIGxpbmUgb2YgY29kZS4gICghISEpDQoNCmBgYHtyIHBpdm90dGFibGV9DQoNCg0KcnBpdm90VGFibGUoZGF0YTYscm93cz1jKCJvcmdfY29kZSIpLCBjb2xzPWMoInR5cGUiKSwgdmFscz1jKCJhZG1pc3Npb25zIiksd2lkdGg9IjEwMCUiLCBoZWlnaHQ9IjEyMDBweCIpDQpgYGANCg0KDQojIFRoYXRzIGFsbCBmb2xrcw0KDQpQbGVhc2UgZmVlbCBmcmVlIHRvIGhhY2sgYW5kIH5+c3RlYWx+fiBzaGFyZSBiZXN0IHByYWN0aWNlIGZyb20gdGhpcyByZXBvcnQuICANCg0KU29tZSByZWFsbHkgbmljZSB2aXN1YWxpc2F0aW9uIHRpcHMgY2FuIGJlIGZvdW5kIGF0DQoNCmh0dHBzOi8vd3d3LmRhdGEtdG8tdml6LmNvbS9jYXZlYXRzLmh0bWwNCg0KYW5kIHNvbWUgbW9yZSBtYXJrZG93biB0aXBzIGF0DQoNCmh0dHBzOi8vaG9sdHp5LmdpdGh1Yi5pby9QaW1wLW15LXJtZC8NCg0KT3RoZXIgdGhhdCBJIHdpc2ggeW91IHdlbGwgb24geW91ciBSIGpvdXJuZXkgYW5kIHBsZWFzZSBkbyBub3QgaGVzaWF0dGUgdG8gY29udGFjdCBtZSBpZiB5b3UgaGF2ZSBmb3VuZCBhbnkgaW50ZXJlc3RpbmcgdGhpbmdzIHRvIHNoYXJlIA0KDQpNZXJyeSBtYXJrZG93bmluZw0KDQo+IENvbnRhY3QNClNpbW9uLldlbGxlc2xleS1NaWxsZXJAbmhzLm5ldCANCg0K