Overview
In todays workshop we will be looking to:
- Use some MSA programs to analyze sequence similarity
- Determine the accuracy of certain alignment programs using BAliBASE data
We will also see how to:
- Use R to perform MSA on a dataset
Multiple Sequence Alignment
Multiple sequence alignment (MSA) is tool used in a variety of downstream bioinformatics applications. We have already seen MSA used in aligning RNA molecules to constrain RNA folding and we will see MSA be used again in the coming weeks.
MSA is a heuristic approach to compare sequences. The dynamic programming algorithm that works well for pairwise comparisons between sequences fails for a variety of theoretical and practical reasons when applied to more than a few sequences. As a result, most MSA algorithms rely on a variety approaches to assemble pairwise alignments into larger MSAs.
There are a wide variety of MSA algorithms and many more programs available to view MSA output. Each software is well-suited for a variety of tasks. Today, we will focus on some widely-used web-based applications to perform MSA and view the output in meaningful ways.
MSA algorithms
There are dozens of different programs available to perform MSA. Baxevanis et al. provide a nice overview of many popular programs used by a wide variety of researchers. Today, we will focus on using a few popular programs - CLUSTAL Omega, MUSCLE, and COBALT. CLUSTAL and MUSCLE are accessible via EMBL-EBI and have easy to use interfaces. COBALT is available through NCBI and uses the BLAST alighment system as its backbone.
Let’s get started by navigating to: https://www.ebi.ac.uk/Tools/msa/
CLUSTAL Omega
One of the most commonly used programs is CLUSTAL Omega. This program is the current iteration of CLUSTAL, a program continuously under development for over 30 years. CLUSTAL Omega is a tree-based progressive aligner that uses iterative tree building and hidden Markov models to refine alignments.
Let’s get a feel for how this aligner works and how accurate it is.
Enter the following sequences into the CLUSTAL Omega interface and execute using default settings except that the output will be MSF. Note that there are a variety of settings we can change regarding the degree of iteration that CLUSTAL will use.
>O24646
MQEQATSSLAASSLPSSSERSSSSAPHLEIKEGIESDEEIRRVPEFGGEAVGKETSGRES
GSATGQERTQATVGESQRKRGRTPAEKENKRLKRLLRNRVSAQQARERKKAYLSELENRV
KDLENKNSELEERLSTLQNENQMLRHILKNTTGNKRGGGGGSNADASL
>Q9SM50
MQEQATSSIAASSLPSSSERSSSSALHHELKEGMESDDEIRRVPEMGGEATGTTSASGRD
GVSAAGQAQPSAGTQRKRGRSPADKENKRLKRLLRNRVSAQQARERKKAYLIDLEARVKE
LETKNAELEERLSTLQNENQMLRHILKNTTAGAQEGRK
>Q0JQA4
MAAQEQEQEKQQVKTSTTSSLPSSSERSSSSAPNNLKEGGGVESDEEIRRVPEMGGGGGS
ASSGAGADERQGKEDGKQQGGGGGGAAAAGGGQEQAPPARKRGRSAGDKEQNRLKRLLRN
RVSAQQARERKKAYMTELEAKAKDLELRNAELEQRVSTLQNENNTLRQILKNTTAHAGKR
GGGGGGKGGDGGGGGKKHHFTKS
>Q69XK6
MTIKRKDDGQVVKQSVKAVGGGLLERVDSDDEEIVGRVPEFGLALPGTSTSGRGSVRVAG
DAAATAAGTSSSSPAAQAGVAGSSSSGRRRGRSPADKEHRRLKRLLRNRVSAQQARERKK
AYMSELEARVKDLERSNSELEERLSTLQNENQMLRQVLKNTTANRRGPDSSAGGDS
>Q6ZHT8
MQEQATSSRPSSSERSSSSGGHHMEIKEGKEAPLRSLLLPFLDFHFTVPLSGMESDEEIG
RVPELGLEPGGASTSGRAAGGGGGGAERAQSSTAQASARRRGRSPADKEHKRLKRLLRNR
VSAQQARERKKAYLNDLEVKVKDLEKKNSELEERFSTLQNENQMLRQILKNTTVSRRGPG
STASGEGQ
Let’s take a look at the output. There are several tabs at the top of the alignment window, click Results Summary. There you will find downloadable files for all information related to your alignment, given your input parameters.
Now, let’s view our alignment. Alignment viewing is a critical part of interpreting an alignment.
MSA viewers
Here are a few popular viewers.
MSA Viewer: https://www.ncbi.nlm.nih.gov/projects/msaviewer/ Mview: https://www.ebi.ac.uk/Tools/msa/mview/ Jalview: https://www.jalview.org/
If using the EBI interface, we can pipe our alignment data straight into Mview in the web browser. If we wanted to use other stand-alone software, we would download our alignment file and open per the software’s instructions.
Go ahead and click Results Viewer. Scroll down and click View in Mview. Your submission link will now be entered into the Mview input window. Click Submit and we will walk through some of the output.
Determining the quality of an alignment program
We may need to learn how good a MSA program is at dealing with our particular scenario. This is a great place to employ the BAliBASE (http://www.lbgi.fr/balibase/). BAliBASE has a number of benchmark scenarios to test your chosen MSA programs. BAliBASE contains different sequence data types in FASTA format along with corresponding validated alignments to compare your MSA program output against.
Let’s test our output - which is actually a BAliBASE test dataset! A number of tests exist for MSA comparison. VerAlign (https://www.ibi.vu.nl/programs/veralignwww/) is a fairly conventional program to make such comparisons. Using our MSF alignment output above, and the MSF output below, let’s compare and see how CLUSTAL did with our reference dataset.
PileUp
MSF: 227 Type: P Check: 4174 ..
Name: O24646 oo Len: 227 Check: 5110 Weight: 10.0
Name: Q9SM50 oo Len: 227 Check: 9784 Weight: 10.0
Name: Q0JQA4 oo Len: 227 Check: 3471 Weight: 10.0
Name: Q69XK6 oo Len: 227 Check: 9317 Weight: 10.0
Name: Q6ZHT8 oo Len: 227 Check: 6492 Weight: 10.0
//
O24646 .......MQE QATSSLAASS LPSSSERSSS SAP.HLEIKE G.........
Q9SM50 .......MQE QATSSIAASS LPSSSERSSS SAL.HHELKE G.........
Q0JQA4 MAAQEQEQEK QQVKTSTTSS LPSSSERSSS SAPNNLKEGG G.........
Q69XK6 .......... ..MTIKRKDD GQVVKQSVKA VGGGLLERVD S.........
Q6ZHT8 .......... ..MQEQATSS RPSSSERSSS SGGHHMEIKE GKEAPLRSLL
O24646 .......... ....IESDEE IRRVPEFGGE AVG....... .KETSGRESG
Q9SM50 .......... ....MESDDE IRRVPEMGGE ATG....... TTSASGRDGV
Q0JQA4 .......... ....VESDEE IRRVPEMGGG GGSAS.SGAG ADERQGKEDG
Q69XK6 .......... .....DDEEI VGRVPEFGLA LPGTSTSGRG SVRVAGDAAA
Q6ZHT8 LPFLDFHFTV PLSGMESDEE IGRVPELGLE PGG....... ASTSGRAAGG
O24646 SATGQERTQA TVGE...... .SQRKRGRTP AEKENKRLKR LLRNRVSAQQ
Q9SM50 SAAGQ..AQP SAG....... .TQRKRGRSP ADKENKRLKR LLRNRVSAQQ
Q0JQA4 KQQGGGGGGA AAAGGGQEQA PPARKRGRSA GDKEQNRLKR LLRNRVSAQQ
Q69XK6 TAAGTSSSSP AAQAGVAGSS SSGRRRGRSP ADKEHRRLKR LLRNRVSAQQ
Q6ZHT8 GGGGAERAQS STAQ...... ASARRRGRSP ADKEHKRLKR LLRNRVSAQQ
O24646 ARERKKAYLS ELENRVKDLE NKNSELEERL STLQNENQML RHILKNTTGN
Q9SM50 ARERKKAYLI DLEARVKELE TKNAELEERL STLQNENQML RHILKNTTAG
Q0JQA4 ARERKKAYMT ELEAKAKDLE LRNAELEQRV STLQNENNTL RQILKNTTAH
Q69XK6 ARERKKAYMS ELEARVKDLE RSNSELEERL STLQNENQML RQVLKNTTAN
Q6ZHT8 ARERKKAYLN DLEVKVKDLE KKNSELEERF STLQNENQML RQILKNTTVS
O24646 K..RGGGGGS NADASL.... .......
Q9SM50 A..QEGRK.. .......... .......
Q0JQA4 AGKRGGGGGG KGGDGGGGGK KHHFTKS
Q69XK6 RRGPDSSAGG DS........ .......
Q6ZHT8 RRGPGSTASG EGQ....... .......
You will see two numbers that are important. SP and CS. SP is a metric that accounts of variable positioning of similarly aligned regions between the test and reference, while CS is a column score for each alignment. SP is a softer metric, while CS is a more stringent metric. Both scale from 0 to 1 (or can be described as percent) where 0 is complete incongruence and 1 is a perfect match. Here, we see our alignment is about 65% successful based on column scoring…
Question
How much do you think exactness of an MSA program matters?
MUSCLE
MUSCLE is another program available through EBI and is widely used in protein sequence alignment. There are some structural differences in how MUSCLE performs MSA compared to CLUSTAL. These differences are described in the textbook, if you are interested.
Let’s input the same dataset as we did for CLUSTAL Omega. You will note we cannot have MSF as an output. In the event you want to use VerAlign, choose FASTA.
Using default settings, let’s see what we get for output.
COBALT
The last aligner we will explore is COBALT. While less popular compared to the global aligners CLUSTAL and MUSCLE, COBALT is a good option as well. COBALT uses the local alignment method behind BLAST to perform alignment. In fact, it is the MSA output provided when you use BLAST to search the NCBI database!
Let’s take a look: https://www.ncbi.nlm.nih.gov/tools/cobalt/re_cobalt.cgi
Paste in the dataset above, as before. Note the advanced parameters available for COBALT. Go ahead and click Align.
Examining the output, we can see there is a graphical depiction of our alignment and several options to allow for realignment, etc. These features make COBALT a powerful web environment for sequence analysis.
Take a second to examine the output compared to the reference, above. Note that COBALT was able to capture some of the early alignment missed by CLUSTAL, much like MUSCLE. However, it does fail with some of the internal gaps in these sequences. This underlies a key point… no MSA aligner is perfect. You often need to make choices on the aligner used based on the circumstances you are working with. That said, most aligners should be giving you relatively similar output if they are well-established platforms.
Real life example
MSA is a powerful tool for identifying highly conserved regions in DNA, RNA, and AA sequences.So far, we’ve been covering this in a fairly abstract way. The power of MSA is really best observed through example. That said, let’s align something interesting and see what we can learn.
One place MSA has been life-changing in the last few years is the development of vaccines targeting the spike protein of SARS-CoV-2. You may have found yourself asking the following question: “How did we know what part of the spike protein to target?” Great question!
The answer to this question is an excellent use of MSA and underlying knowledge of protein structural biology. It turns out, researchers have been looking for vaccine epitopes to coronaviruses for some time. In 2017, Jesper Pallesen and coworkers developed a successful antigenic epitope of the MERS spike protein. We’re lucky they were successful then because epitope used in all vaccines used in the USA and Europe use the principles from Pallesen’s work to great effect against the SARS-CoV-2 spike protein!
Let’s take a look at how we can think about starting an inquiry like Pallesen and coworkers. We first need a series of coronavirus spike protein sequences to compare. Specifically, we need sequences from Betacoronaviruses (i.e. the family causing respiratory disorders in various mammalian hosts). You can get those here. DOWNLOAD
Enter these sequences into COBALT and align.
Now, let’s examine the alignment. Question for us to ponder: If you had to choose a region to design an epitope, which would you choose? Why?
Using the first sequence as a guide (it is SARS-CoV-2 spike), navigate to the 986/987 residue pair. These two residues, in the vaccine S-2P epitope, have been mutated to prolines. These mutations lock the spike protein into its active conformation found in the virion surface. This simple change was directed by MSA, structural comparison, and hypothesis testing in lab experiments. Without our ability to compare… we’d be far behind in our development of vaccines.
MSA in R
library(msa)
We have seen the use of the seqinr subroutines for reading in FASTA data (namely read.fasta()). Here, we can use a function in the Biostrings package to load in FASTA sequences. This package will also read in other formats, too. Like Module 5, we are creating a StringSet variable (box17). This is the standard input for most Bioconductor sequence analysis packages.
box17 <- readAAStringSet("https://drive.google.com/uc?export=download&id=1hMqmCS9ae2-Rvk2oOyiOMUZ_MWKCOeh6")
trying URL 'https://drive.google.com/uc?export=download&id=1hMqmCS9ae2-Rvk2oOyiOMUZ_MWKCOeh6'
Content type 'application/octet-stream' length 13532 bytes (13 KB)
==================================================
downloaded 13 KB
The msa package contains three subroutines for performing CLUSTALW (progressive only), CLUSTAL Omega (with iteration), and MUSCLE alignments. These will meet most needs and allow sending output data to a variety of analysis packages - some we will see next week!
# using the old CLUSTALW2 algorithm
ClustalW = msaClustalW(box17)
use default substitution matrix
# using the iterative Omega algorithm
ClustalO = msaClustalOmega(box17,
maxiters = 5)
using Gonnet
# using MUSCLE
Muscle = msaMuscle(box17)
The msa package also has some alignment analysis tools. One useful one is the msaConsensusSequence() subroutine. This will allow you to extract highly conserved motifs (i.e. 100% conservation).
msaConsensusSequence(ClustalW)
[1] "------------------------------------------------------------???????----?????????-?????---------------------??????????????????????????????????????????????????????????????????????????????????????????????????-----------------------???????????????????--??-------------------------------------------------------------------???????????????????????????????????????????????????------------------------------------------------------------------------------------------??????????--------??????????????????????????????????-???KR?RR??RNR?SAQ??R?RKK?Y???LE?RV??L???N?EL??????L???N??L?Q?L?????????????????????-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"
# let's use a loop and create some output we can compare
alignments <- c(ClustalW, ClustalO, Muscle)
alignmentConsensus = c()
for (i in 1:length(alignments)) {
alignmentConsensus[i] = msaConsensusSequence(alignments[[i]])
}
print(alignmentConsensus)
[1] "------------------------------------------------------------???????----?????????-?????---------------------??????????????????????????????????????????????????????????????????????????????????????????????????-----------------------???????????????????--??-------------------------------------------------------------------???????????????????????????????????????????????????------------------------------------------------------------------------------------------??????????--------??????????????????????????????????-???KR?RR??RNR?SAQ??R?RKK?Y???LE?RV??L???N?EL??????L???N??L?Q?L?????????????????????-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"
[2] "---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------???????????-?--------------------------------------------------------------????????????--??-----------???????---?????-------??????????????----------------------?????????????????-------------------------------------------------------------?-????????????????????------------------------------------------------???------???--------??????-----??-?--???---------???????--??----------????????--????????????????-----------------????????-----??????????????????????P?????????KR?RR??RNR?SAQ??R?RKK?Y???LE?RV??L???N?EL??????L???N??L?Q?L????????????-----?--??????-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"
[3] "-------------------------------------------?????????????????????????---------------------??????????????????---------------------------------??????????????????????????P------------???------------------------??????????-------????????-?????---------------------??????????-------------------?????????????????????????????????????????????????---------------------------------------??????????????????????????????????-------????-----------------------????????????????-???????P?DK??????-KR?RR??RNR?SAQ??R?RKK?Y???LE?RV??L???N?EL?????-?L???N??L?Q?L????????-----------??????????--??????---?-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"
Question
Comparing these consensus alignments, do they seem to capture similar motifs?
We can also use msa to output more visually accessible outputs using the msaPrettyPrint subroutine. There are several more options in this subroutine than shown here, but the basic output is reasonably informative, as is.
msaPrettyPrint(ClustalO, output="pdf")
LS0tCnRpdGxlOiAiTW9kdWxlIDYgV29ya3Nob3AgRXhlcmNpc2VzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKIyBPdmVydmlldwoKSW4gdG9kYXlzIHdvcmtzaG9wIHdlIHdpbGwgYmUgbG9va2luZyB0bzoKCi0gVXNlIHNvbWUgTVNBIHByb2dyYW1zIHRvIGFuYWx5emUgc2VxdWVuY2Ugc2ltaWxhcml0eQotIERldGVybWluZSB0aGUgYWNjdXJhY3kgb2YgY2VydGFpbiBhbGlnbm1lbnQgcHJvZ3JhbXMgdXNpbmcgQkFsaUJBU0UgZGF0YQoKV2Ugd2lsbCBhbHNvIHNlZSBob3cgdG86CgotIFVzZSBSIHRvIHBlcmZvcm0gTVNBIG9uIGEgZGF0YXNldAoKCiMgTXVsdGlwbGUgU2VxdWVuY2UgQWxpZ25tZW50CgpNdWx0aXBsZSBzZXF1ZW5jZSBhbGlnbm1lbnQgKE1TQSkgaXMgdG9vbCB1c2VkIGluIGEgdmFyaWV0eSBvZiBkb3duc3RyZWFtIGJpb2luZm9ybWF0aWNzIGFwcGxpY2F0aW9ucy4gV2UgaGF2ZSBhbHJlYWR5IHNlZW4gTVNBIHVzZWQgaW4gYWxpZ25pbmcgUk5BIG1vbGVjdWxlcyB0byBjb25zdHJhaW4gUk5BIGZvbGRpbmcgYW5kIHdlIHdpbGwgc2VlIE1TQSBiZSB1c2VkIGFnYWluIGluIHRoZSBjb21pbmcgd2Vla3MuCgpNU0EgaXMgYSBoZXVyaXN0aWMgYXBwcm9hY2ggdG8gY29tcGFyZSBzZXF1ZW5jZXMuIFRoZSBkeW5hbWljIHByb2dyYW1taW5nIGFsZ29yaXRobSB0aGF0IHdvcmtzIHdlbGwgZm9yIHBhaXJ3aXNlIGNvbXBhcmlzb25zIGJldHdlZW4gc2VxdWVuY2VzIGZhaWxzIGZvciBhIHZhcmlldHkgb2YgdGhlb3JldGljYWwgYW5kIHByYWN0aWNhbCByZWFzb25zIHdoZW4gYXBwbGllZCB0byBtb3JlIHRoYW4gYSBmZXcgc2VxdWVuY2VzLiBBcyBhIHJlc3VsdCwgbW9zdCBNU0EgYWxnb3JpdGhtcyByZWx5IG9uIGEgdmFyaWV0eSBhcHByb2FjaGVzIHRvIGFzc2VtYmxlIHBhaXJ3aXNlIGFsaWdubWVudHMgaW50byBsYXJnZXIgTVNBcy4KClRoZXJlIGFyZSBhIHdpZGUgdmFyaWV0eSBvZiBNU0EgYWxnb3JpdGhtcyBhbmQgbWFueSBtb3JlIHByb2dyYW1zIGF2YWlsYWJsZSB0byB2aWV3IE1TQSBvdXRwdXQuIEVhY2ggc29mdHdhcmUgaXMgd2VsbC1zdWl0ZWQgZm9yIGEgdmFyaWV0eSBvZiB0YXNrcy4gVG9kYXksIHdlIHdpbGwgZm9jdXMgb24gc29tZSB3aWRlbHktdXNlZCB3ZWItYmFzZWQgYXBwbGljYXRpb25zIHRvIHBlcmZvcm0gTVNBIGFuZCB2aWV3IHRoZSBvdXRwdXQgaW4gbWVhbmluZ2Z1bCB3YXlzLgoKIyBNU0EgYWxnb3JpdGhtcwoKVGhlcmUgYXJlIGRvemVucyBvZiBkaWZmZXJlbnQgcHJvZ3JhbXMgYXZhaWxhYmxlIHRvIHBlcmZvcm0gTVNBLiBCYXhldmFuaXMgZXQgYWwuIHByb3ZpZGUgYSBuaWNlIG92ZXJ2aWV3IG9mIG1hbnkgcG9wdWxhciBwcm9ncmFtcyB1c2VkIGJ5IGEgd2lkZSB2YXJpZXR5IG9mIHJlc2VhcmNoZXJzLiBUb2RheSwgd2Ugd2lsbCBmb2N1cyBvbiB1c2luZyBhIGZldyBwb3B1bGFyIHByb2dyYW1zIC0gQ0xVU1RBTCBPbWVnYSwgTVVTQ0xFLCBhbmQgQ09CQUxULiBDTFVTVEFMIGFuZCBNVVNDTEUgYXJlIGFjY2Vzc2libGUgdmlhIEVNQkwtRUJJIGFuZCBoYXZlIGVhc3kgdG8gdXNlIGludGVyZmFjZXMuIENPQkFMVCBpcyBhdmFpbGFibGUgdGhyb3VnaCBOQ0JJIGFuZCB1c2VzIHRoZSBCTEFTVCBhbGlnaG1lbnQgc3lzdGVtIGFzIGl0cyBiYWNrYm9uZS4KCkxldCdzIGdldCBzdGFydGVkIGJ5IG5hdmlnYXRpbmcgdG86IGh0dHBzOi8vd3d3LmViaS5hYy51ay9Ub29scy9tc2EvCgojIyBDTFVTVEFMIE9tZWdhCgpPbmUgb2YgdGhlIG1vc3QgY29tbW9ubHkgdXNlZCBwcm9ncmFtcyBpcyBDTFVTVEFMIE9tZWdhLiBUaGlzIHByb2dyYW0gaXMgdGhlIGN1cnJlbnQgaXRlcmF0aW9uIG9mIENMVVNUQUwsIGEgcHJvZ3JhbSBjb250aW51b3VzbHkgdW5kZXIgZGV2ZWxvcG1lbnQgZm9yIG92ZXIgMzAgeWVhcnMuIENMVVNUQUwgT21lZ2EgaXMgYSB0cmVlLWJhc2VkIHByb2dyZXNzaXZlIGFsaWduZXIgdGhhdCB1c2VzIGl0ZXJhdGl2ZSB0cmVlIGJ1aWxkaW5nIGFuZCBoaWRkZW4gTWFya292IG1vZGVscyB0byByZWZpbmUgYWxpZ25tZW50cy4KCkxldCdzIGdldCBhIGZlZWwgZm9yIGhvdyB0aGlzIGFsaWduZXIgd29ya3MgYW5kIGhvdyBhY2N1cmF0ZSBpdCBpcy4KCkVudGVyIHRoZSBmb2xsb3dpbmcgc2VxdWVuY2VzIGludG8gdGhlIENMVVNUQUwgT21lZ2EgaW50ZXJmYWNlIGFuZCBleGVjdXRlIHVzaW5nIGRlZmF1bHQgc2V0dGluZ3MgZXhjZXB0IHRoYXQgdGhlIG91dHB1dCB3aWxsIGJlIE1TRi4gTm90ZSB0aGF0IHRoZXJlIGFyZSBhIHZhcmlldHkgb2Ygc2V0dGluZ3Mgd2UgY2FuIGNoYW5nZSByZWdhcmRpbmcgdGhlIGRlZ3JlZSBvZiBpdGVyYXRpb24gdGhhdCBDTFVTVEFMIHdpbGwgdXNlLgoKICAgID5PMjQ2NDYKICAgIE1RRVFBVFNTTEFBU1NMUFNTU0VSU1NTU0FQSExFSUtFR0lFU0RFRUlSUlZQRUZHR0VBVkdLRVRTR1JFUwogICAgR1NBVEdRRVJUUUFUVkdFU1FSS1JHUlRQQUVLRU5LUkxLUkxMUk5SVlNBUVFBUkVSS0tBWUxTRUxFTlJWCiAgICBLRExFTktOU0VMRUVSTFNUTFFORU5RTUxSSElMS05UVEdOS1JHR0dHR1NOQURBU0wKICAgID5ROVNNNTAKICAgIE1RRVFBVFNTSUFBU1NMUFNTU0VSU1NTU0FMSEhFTEtFR01FU0RERUlSUlZQRU1HR0VBVEdUVFNBU0dSRAogICAgR1ZTQUFHUUFRUFNBR1RRUktSR1JTUEFES0VOS1JMS1JMTFJOUlZTQVFRQVJFUktLQVlMSURMRUFSVktFCiAgICBMRVRLTkFFTEVFUkxTVExRTkVOUU1MUkhJTEtOVFRBR0FRRUdSSwogICAgPlEwSlFBNAogICAgTUFBUUVRRVFFS1FRVktUU1RUU1NMUFNTU0VSU1NTU0FQTk5MS0VHR0dWRVNERUVJUlJWUEVNR0dHR0dTCiAgICBBU1NHQUdBREVSUUdLRURHS1FRR0dHR0dHQUFBQUdHR1FFUUFQUEFSS1JHUlNBR0RLRVFOUkxLUkxMUk4KICAgIFJWU0FRUUFSRVJLS0FZTVRFTEVBS0FLRExFTFJOQUVMRVFSVlNUTFFORU5OVExSUUlMS05UVEFIQUdLUgogICAgR0dHR0dHS0dHREdHR0dHS0tISEZUS1MKICAgID5RNjlYSzYKICAgIE1USUtSS0RER1FWVktRU1ZLQVZHR0dMTEVSVkRTRERFRUlWR1JWUEVGR0xBTFBHVFNUU0dSR1NWUlZBRwogICAgREFBQVRBQUdUU1NTU1BBQVFBR1ZBR1NTU1NHUlJSR1JTUEFES0VIUlJMS1JMTFJOUlZTQVFRQVJFUktLCiAgICBBWU1TRUxFQVJWS0RMRVJTTlNFTEVFUkxTVExRTkVOUU1MUlFWTEtOVFRBTlJSR1BEU1NBR0dEUwogICAgPlE2WkhUOAogICAgTVFFUUFUU1NSUFNTU0VSU1NTU0dHSEhNRUlLRUdLRUFQTFJTTExMUEZMREZIRlRWUExTR01FU0RFRUlHCiAgICBSVlBFTEdMRVBHR0FTVFNHUkFBR0dHR0dHQUVSQVFTU1RBUUFTQVJSUkdSU1BBREtFSEtSTEtSTExSTlIKICAgIFZTQVFRQVJFUktLQVlMTkRMRVZLVktETEVLS05TRUxFRVJGU1RMUU5FTlFNTFJRSUxLTlRUVlNSUkdQRwogICAgU1RBU0dFR1EKCkxldCdzIHRha2UgYSBsb29rIGF0IHRoZSBvdXRwdXQuIFRoZXJlIGFyZSBzZXZlcmFsIHRhYnMgYXQgdGhlIHRvcCBvZiB0aGUgYWxpZ25tZW50IHdpbmRvdywgY2xpY2sgYFJlc3VsdHMgU3VtbWFyeWAuIFRoZXJlIHlvdSB3aWxsIGZpbmQgZG93bmxvYWRhYmxlIGZpbGVzIGZvciBhbGwgaW5mb3JtYXRpb24gcmVsYXRlZCB0byB5b3VyIGFsaWdubWVudCwgZ2l2ZW4geW91ciBpbnB1dCBwYXJhbWV0ZXJzLgoKTm93LCBsZXQncyB2aWV3IG91ciBhbGlnbm1lbnQuIEFsaWdubWVudCB2aWV3aW5nIGlzIGEgY3JpdGljYWwgcGFydCBvZiBpbnRlcnByZXRpbmcgYW4gYWxpZ25tZW50LgoKIyMjIE1TQSB2aWV3ZXJzCgpIZXJlIGFyZSBhIGZldyBwb3B1bGFyIHZpZXdlcnMuCgpNU0EgVmlld2VyOiBodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3Byb2plY3RzL21zYXZpZXdlci8KTXZpZXc6IGh0dHBzOi8vd3d3LmViaS5hYy51ay9Ub29scy9tc2EvbXZpZXcvCkphbHZpZXc6IGh0dHBzOi8vd3d3LmphbHZpZXcub3JnLwoKSWYgdXNpbmcgdGhlIEVCSSBpbnRlcmZhY2UsIHdlIGNhbiBwaXBlIG91ciBhbGlnbm1lbnQgZGF0YSBzdHJhaWdodCBpbnRvIE12aWV3IGluIHRoZSB3ZWIgYnJvd3Nlci4gSWYgd2Ugd2FudGVkIHRvIHVzZSBvdGhlciBzdGFuZC1hbG9uZSBzb2Z0d2FyZSwgd2Ugd291bGQgZG93bmxvYWQgb3VyIGFsaWdubWVudCBmaWxlIGFuZCBvcGVuIHBlciB0aGUgc29mdHdhcmUncyBpbnN0cnVjdGlvbnMuCgpHbyBhaGVhZCBhbmQgY2xpY2sgYFJlc3VsdHMgVmlld2VyYC4gU2Nyb2xsIGRvd24gYW5kIGNsaWNrIGBWaWV3IGluIE12aWV3YC4gWW91ciBzdWJtaXNzaW9uIGxpbmsgd2lsbCBub3cgYmUgZW50ZXJlZCBpbnRvIHRoZSBNdmlldyBpbnB1dCB3aW5kb3cuIENsaWNrIGBTdWJtaXRgIGFuZCB3ZSB3aWxsIHdhbGsgdGhyb3VnaCBzb21lIG9mIHRoZSBvdXRwdXQuCgojIyMgRGV0ZXJtaW5pbmcgdGhlIHF1YWxpdHkgb2YgYW4gYWxpZ25tZW50IHByb2dyYW0KCldlIG1heSBuZWVkIHRvIGxlYXJuIGhvdyBnb29kIGEgTVNBIHByb2dyYW0gaXMgYXQgZGVhbGluZyB3aXRoIG91ciBwYXJ0aWN1bGFyIHNjZW5hcmlvLiBUaGlzIGlzIGEgZ3JlYXQgcGxhY2UgdG8gZW1wbG95IHRoZSBCQWxpQkFTRSAoaHR0cDovL3d3dy5sYmdpLmZyL2JhbGliYXNlLykuIEJBbGlCQVNFIGhhcyBhIG51bWJlciBvZiBiZW5jaG1hcmsgc2NlbmFyaW9zIHRvIHRlc3QgeW91ciBjaG9zZW4gTVNBIHByb2dyYW1zLiBCQWxpQkFTRSBjb250YWlucyBkaWZmZXJlbnQgc2VxdWVuY2UgZGF0YSB0eXBlcyBpbiBGQVNUQSBmb3JtYXQgYWxvbmcgd2l0aCBjb3JyZXNwb25kaW5nIHZhbGlkYXRlZCBhbGlnbm1lbnRzIHRvIGNvbXBhcmUgeW91ciBNU0EgcHJvZ3JhbSBvdXRwdXQgYWdhaW5zdC4KCkxldCdzIHRlc3Qgb3VyIG91dHB1dCAtIHdoaWNoIGlzIGFjdHVhbGx5IGEgQkFsaUJBU0UgdGVzdCBkYXRhc2V0ISBBIG51bWJlciBvZiB0ZXN0cyBleGlzdCBmb3IgTVNBIGNvbXBhcmlzb24uIFZlckFsaWduIChodHRwczovL3d3dy5pYmkudnUubmwvcHJvZ3JhbXMvdmVyYWxpZ253d3cvKSBpcyBhIGZhaXJseSBjb252ZW50aW9uYWwgcHJvZ3JhbSB0byBtYWtlIHN1Y2ggY29tcGFyaXNvbnMuIFVzaW5nIG91ciBNU0YgYWxpZ25tZW50IG91dHB1dCBhYm92ZSwgYW5kIHRoZSBNU0Ygb3V0cHV0IGJlbG93LCBsZXQncyBjb21wYXJlIGFuZCBzZWUgaG93IENMVVNUQUwgZGlkIHdpdGggb3VyIHJlZmVyZW5jZSBkYXRhc2V0LgoKCiAgICBQaWxlVXAKICAgIAogICAgCiAgICAKICAgICAgIE1TRjogIDIyNyAgVHlwZTogUCAgICBDaGVjazogIDQxNzQgICAuLiAKICAgIAogICAgIE5hbWU6IE8yNDY0NiBvbyAgTGVuOiAgMjI3ICBDaGVjazogIDUxMTAgIFdlaWdodDogIDEwLjAKICAgICBOYW1lOiBROVNNNTAgb28gIExlbjogIDIyNyAgQ2hlY2s6ICA5Nzg0ICBXZWlnaHQ6ICAxMC4wCiAgICAgTmFtZTogUTBKUUE0IG9vICBMZW46ICAyMjcgIENoZWNrOiAgMzQ3MSAgV2VpZ2h0OiAgMTAuMAogICAgIE5hbWU6IFE2OVhLNiBvbyAgTGVuOiAgMjI3ICBDaGVjazogIDkzMTcgIFdlaWdodDogIDEwLjAKICAgICBOYW1lOiBRNlpIVDggb28gIExlbjogIDIyNyAgQ2hlY2s6ICA2NDkyICBXZWlnaHQ6ICAxMC4wCiAgICAKICAgIC8vCiAgICAKICAgIAogICAgCiAgICBPMjQ2NDYgICAgICAuLi4uLi4uTVFFIFFBVFNTTEFBU1MgTFBTU1NFUlNTUyBTQVAuSExFSUtFIEcuLi4uLi4uLi4gCiAgICBROVNNNTAgICAgICAuLi4uLi4uTVFFIFFBVFNTSUFBU1MgTFBTU1NFUlNTUyBTQUwuSEhFTEtFIEcuLi4uLi4uLi4gCiAgICBRMEpRQTQgICAgICBNQUFRRVFFUUVLIFFRVktUU1RUU1MgTFBTU1NFUlNTUyBTQVBOTkxLRUdHIEcuLi4uLi4uLi4gCiAgICBRNjlYSzYgICAgICAuLi4uLi4uLi4uIC4uTVRJS1JLREQgR1FWVktRU1ZLQSBWR0dHTExFUlZEIFMuLi4uLi4uLi4gCiAgICBRNlpIVDggICAgICAuLi4uLi4uLi4uIC4uTVFFUUFUU1MgUlBTU1NFUlNTUyBTR0dISE1FSUtFIEdLRUFQTFJTTEwgCiAgICAKICAgIAogICAgTzI0NjQ2ICAgICAgLi4uLi4uLi4uLiAuLi4uSUVTREVFIElSUlZQRUZHR0UgQVZHLi4uLi4uLiAuS0VUU0dSRVNHIAogICAgUTlTTTUwICAgICAgLi4uLi4uLi4uLiAuLi4uTUVTRERFIElSUlZQRU1HR0UgQVRHLi4uLi4uLiBUVFNBU0dSREdWIAogICAgUTBKUUE0ICAgICAgLi4uLi4uLi4uLiAuLi4uVkVTREVFIElSUlZQRU1HR0cgR0dTQVMuU0dBRyBBREVSUUdLRURHIAogICAgUTY5WEs2ICAgICAgLi4uLi4uLi4uLiAuLi4uLkRERUVJIFZHUlZQRUZHTEEgTFBHVFNUU0dSRyBTVlJWQUdEQUFBIAogICAgUTZaSFQ4ICAgICAgTFBGTERGSEZUViBQTFNHTUVTREVFIElHUlZQRUxHTEUgUEdHLi4uLi4uLiBBU1RTR1JBQUdHIAogICAgCiAgICAKICAgIE8yNDY0NiAgICAgIFNBVEdRRVJUUUEgVFZHRS4uLi4uLiAuU1FSS1JHUlRQIEFFS0VOS1JMS1IgTExSTlJWU0FRUSAKICAgIFE5U001MCAgICAgIFNBQUdRLi5BUVAgU0FHLi4uLi4uLiAuVFFSS1JHUlNQIEFES0VOS1JMS1IgTExSTlJWU0FRUSAKICAgIFEwSlFBNCAgICAgIEtRUUdHR0dHR0EgQUFBR0dHUUVRQSBQUEFSS1JHUlNBIEdES0VRTlJMS1IgTExSTlJWU0FRUSAKICAgIFE2OVhLNiAgICAgIFRBQUdUU1NTU1AgQUFRQUdWQUdTUyBTU0dSUlJHUlNQIEFES0VIUlJMS1IgTExSTlJWU0FRUSAKICAgIFE2WkhUOCAgICAgIEdHR0dBRVJBUVMgU1RBUS4uLi4uLiBBU0FSUlJHUlNQIEFES0VIS1JMS1IgTExSTlJWU0FRUSAKICAgIAogICAgCiAgICBPMjQ2NDYgICAgICBBUkVSS0tBWUxTIEVMRU5SVktETEUgTktOU0VMRUVSTCBTVExRTkVOUU1MIFJISUxLTlRUR04gCiAgICBROVNNNTAgICAgICBBUkVSS0tBWUxJIERMRUFSVktFTEUgVEtOQUVMRUVSTCBTVExRTkVOUU1MIFJISUxLTlRUQUcgCiAgICBRMEpRQTQgICAgICBBUkVSS0tBWU1UIEVMRUFLQUtETEUgTFJOQUVMRVFSViBTVExRTkVOTlRMIFJRSUxLTlRUQUggCiAgICBRNjlYSzYgICAgICBBUkVSS0tBWU1TIEVMRUFSVktETEUgUlNOU0VMRUVSTCBTVExRTkVOUU1MIFJRVkxLTlRUQU4gCiAgICBRNlpIVDggICAgICBBUkVSS0tBWUxOIERMRVZLVktETEUgS0tOU0VMRUVSRiBTVExRTkVOUU1MIFJRSUxLTlRUVlMgCiAgICAKICAgIAogICAgTzI0NjQ2ICAgICAgSy4uUkdHR0dHUyBOQURBU0wuLi4uIC4uLi4uLi4KICAgIFE5U001MCAgICAgIEEuLlFFR1JLLi4gLi4uLi4uLi4uLiAuLi4uLi4uCiAgICBRMEpRQTQgICAgICBBR0tSR0dHR0dHIEtHR0RHR0dHR0sgS0hIRlRLUwogICAgUTY5WEs2ICAgICAgUlJHUERTU0FHRyBEUy4uLi4uLi4uIC4uLi4uLi4KICAgIFE2WkhUOCAgICAgIFJSR1BHU1RBU0cgRUdRLi4uLi4uLiAuLi4uLi4uCgpZb3Ugd2lsbCBzZWUgdHdvIG51bWJlcnMgdGhhdCBhcmUgaW1wb3J0YW50LiBTUCBhbmQgQ1MuIFNQIGlzIGEgbWV0cmljIHRoYXQgYWNjb3VudHMgb2YgdmFyaWFibGUgcG9zaXRpb25pbmcgb2Ygc2ltaWxhcmx5IGFsaWduZWQgcmVnaW9ucyBiZXR3ZWVuIHRoZSB0ZXN0IGFuZCByZWZlcmVuY2UsIHdoaWxlIENTIGlzIGEgY29sdW1uIHNjb3JlIGZvciBlYWNoIGFsaWdubWVudC4gU1AgaXMgYSBzb2Z0ZXIgbWV0cmljLCB3aGlsZSBDUyBpcyBhIG1vcmUgc3RyaW5nZW50IG1ldHJpYy4gQm90aCBzY2FsZSBmcm9tIDAgdG8gMSAob3IgY2FuIGJlIGRlc2NyaWJlZCBhcyBwZXJjZW50KSB3aGVyZSAwIGlzIGNvbXBsZXRlIGluY29uZ3J1ZW5jZSBhbmQgMSBpcyBhIHBlcmZlY3QgbWF0Y2guIEhlcmUsIHdlIHNlZSBvdXIgYWxpZ25tZW50IGlzIGFib3V0IDY1JSBzdWNjZXNzZnVsIGJhc2VkIG9uIGNvbHVtbiBzY29yaW5nLi4uCgotLS0KCioqUXVlc3Rpb24qKgoKSG93IG11Y2ggZG8geW91IHRoaW5rIGV4YWN0bmVzcyBvZiBhbiBNU0EgcHJvZ3JhbSBtYXR0ZXJzPwoKLS0tCgojIyBNVVNDTEUKCk1VU0NMRSBpcyBhbm90aGVyIHByb2dyYW0gYXZhaWxhYmxlIHRocm91Z2ggRUJJIGFuZCBpcyB3aWRlbHkgdXNlZCBpbiBwcm90ZWluIHNlcXVlbmNlIGFsaWdubWVudC4gVGhlcmUgYXJlIHNvbWUgc3RydWN0dXJhbCBkaWZmZXJlbmNlcyBpbiBob3cgTVVTQ0xFIHBlcmZvcm1zIE1TQSBjb21wYXJlZCB0byBDTFVTVEFMLiBUaGVzZSBkaWZmZXJlbmNlcyBhcmUgZGVzY3JpYmVkIGluIHRoZSB0ZXh0Ym9vaywgaWYgeW91IGFyZSBpbnRlcmVzdGVkLgoKTGV0J3MgaW5wdXQgdGhlIHNhbWUgZGF0YXNldCBhcyB3ZSBkaWQgZm9yIENMVVNUQUwgT21lZ2EuIFlvdSB3aWxsIG5vdGUgd2UgY2Fubm90IGhhdmUgTVNGIGFzIGFuIG91dHB1dC4gSW4gdGhlIGV2ZW50IHlvdSB3YW50IHRvIHVzZSBWZXJBbGlnbiwgY2hvb3NlIEZBU1RBLgoKVXNpbmcgZGVmYXVsdCBzZXR0aW5ncywgbGV0J3Mgc2VlIHdoYXQgd2UgZ2V0IGZvciBvdXRwdXQuIAoKIyMgQ09CQUxUCgpUaGUgbGFzdCBhbGlnbmVyIHdlIHdpbGwgZXhwbG9yZSBpcyBDT0JBTFQuIFdoaWxlIGxlc3MgcG9wdWxhciBjb21wYXJlZCB0byB0aGUgZ2xvYmFsIGFsaWduZXJzIENMVVNUQUwgYW5kIE1VU0NMRSwgQ09CQUxUIGlzIGEgZ29vZCBvcHRpb24gYXMgd2VsbC4gQ09CQUxUIHVzZXMgdGhlIGxvY2FsIGFsaWdubWVudCBtZXRob2QgYmVoaW5kIEJMQVNUIHRvIHBlcmZvcm0gYWxpZ25tZW50LiBJbiBmYWN0LCBpdCBpcyB0aGUgTVNBIG91dHB1dCBwcm92aWRlZCB3aGVuIHlvdSB1c2UgQkxBU1QgdG8gc2VhcmNoIHRoZSBOQ0JJIGRhdGFiYXNlIQoKTGV0J3MgdGFrZSBhIGxvb2s6IGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvdG9vbHMvY29iYWx0L3JlX2NvYmFsdC5jZ2kKClBhc3RlIGluIHRoZSBkYXRhc2V0IGFib3ZlLCBhcyBiZWZvcmUuIE5vdGUgdGhlIGFkdmFuY2VkIHBhcmFtZXRlcnMgYXZhaWxhYmxlIGZvciBDT0JBTFQuIEdvIGFoZWFkIGFuZCBjbGljayBgQWxpZ25gLgoKRXhhbWluaW5nIHRoZSBvdXRwdXQsIHdlIGNhbiBzZWUgdGhlcmUgaXMgYSBncmFwaGljYWwgZGVwaWN0aW9uIG9mIG91ciBhbGlnbm1lbnQgYW5kIHNldmVyYWwgb3B0aW9ucyB0byBhbGxvdyBmb3IgcmVhbGlnbm1lbnQsIGV0Yy4gVGhlc2UgZmVhdHVyZXMgbWFrZSBDT0JBTFQgYSBwb3dlcmZ1bCB3ZWIgZW52aXJvbm1lbnQgZm9yIHNlcXVlbmNlIGFuYWx5c2lzLgoKVGFrZSBhIHNlY29uZCB0byBleGFtaW5lIHRoZSBvdXRwdXQgY29tcGFyZWQgdG8gdGhlIHJlZmVyZW5jZSwgYWJvdmUuIE5vdGUgdGhhdCBDT0JBTFQgd2FzIGFibGUgdG8gY2FwdHVyZSBzb21lIG9mIHRoZSBlYXJseSBhbGlnbm1lbnQgbWlzc2VkIGJ5IENMVVNUQUwsIG11Y2ggbGlrZSBNVVNDTEUuIEhvd2V2ZXIsIGl0IGRvZXMgZmFpbCB3aXRoIHNvbWUgb2YgdGhlIGludGVybmFsIGdhcHMgaW4gdGhlc2Ugc2VxdWVuY2VzLiBUaGlzIHVuZGVybGllcyBhIGtleSBwb2ludC4uLiBubyBNU0EgYWxpZ25lciBpcyBwZXJmZWN0LiBZb3Ugb2Z0ZW4gbmVlZCB0byBtYWtlIGNob2ljZXMgb24gdGhlIGFsaWduZXIgdXNlZCBiYXNlZCBvbiB0aGUgY2lyY3Vtc3RhbmNlcyB5b3UgYXJlIHdvcmtpbmcgd2l0aC4gVGhhdCBzYWlkLCBtb3N0IGFsaWduZXJzIHNob3VsZCBiZSBnaXZpbmcgeW91IHJlbGF0aXZlbHkgc2ltaWxhciBvdXRwdXQgaWYgdGhleSBhcmUgd2VsbC1lc3RhYmxpc2hlZCBwbGF0Zm9ybXMuCgojIFJlYWwgbGlmZSBleGFtcGxlCgpNU0EgaXMgYSBwb3dlcmZ1bCB0b29sIGZvciBpZGVudGlmeWluZyBoaWdobHkgY29uc2VydmVkIHJlZ2lvbnMgaW4gRE5BLCBSTkEsIGFuZCBBQSBzZXF1ZW5jZXMuU28gZmFyLCB3ZSd2ZSBiZWVuIGNvdmVyaW5nIHRoaXMgaW4gYSBmYWlybHkgYWJzdHJhY3Qgd2F5LiBUaGUgcG93ZXIgb2YgTVNBIGlzIHJlYWxseSBiZXN0IG9ic2VydmVkIHRocm91Z2ggZXhhbXBsZS4gVGhhdCBzYWlkLCBsZXQncyBhbGlnbiBzb21ldGhpbmcgaW50ZXJlc3RpbmcgYW5kIHNlZSB3aGF0IHdlIGNhbiBsZWFybi4KCk9uZSBwbGFjZSBNU0EgaGFzIGJlZW4gbGlmZS1jaGFuZ2luZyBpbiB0aGUgbGFzdCBmZXcgeWVhcnMgaXMgdGhlIGRldmVsb3BtZW50IG9mIHZhY2NpbmVzIHRhcmdldGluZyB0aGUgc3Bpa2UgcHJvdGVpbiBvZiBTQVJTLUNvVi0yLiBZb3UgbWF5IGhhdmUgZm91bmQgeW91cnNlbGYgYXNraW5nIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb246ICJIb3cgZGlkIHdlIGtub3cgd2hhdCBwYXJ0IG9mIHRoZSBzcGlrZSBwcm90ZWluIHRvIHRhcmdldD8iIEdyZWF0IHF1ZXN0aW9uIQoKVGhlIGFuc3dlciB0byB0aGlzIHF1ZXN0aW9uIGlzIGFuIGV4Y2VsbGVudCB1c2Ugb2YgTVNBIGFuZCB1bmRlcmx5aW5nIGtub3dsZWRnZSBvZiBwcm90ZWluIHN0cnVjdHVyYWwgYmlvbG9neS4gSXQgdHVybnMgb3V0LCByZXNlYXJjaGVycyBoYXZlIGJlZW4gbG9va2luZyBmb3IgdmFjY2luZSBlcGl0b3BlcyB0byBjb3JvbmF2aXJ1c2VzIGZvciBzb21lIHRpbWUuIEluIDIwMTcsIEplc3BlciBQYWxsZXNlbiBhbmQgY293b3JrZXJzXltodHRwczovL3d3dy5wbmFzLm9yZy9jb250ZW50LzExNC8zNS9FNzM0OF0gZGV2ZWxvcGVkIGEgc3VjY2Vzc2Z1bCBhbnRpZ2VuaWMgZXBpdG9wZSBvZiB0aGUgTUVSUyBzcGlrZSBwcm90ZWluLiBXZSdyZSBsdWNreSB0aGV5IHdlcmUgc3VjY2Vzc2Z1bCB0aGVuIGJlY2F1c2UgZXBpdG9wZSB1c2VkIGluIGFsbCB2YWNjaW5lcyB1c2VkIGluIHRoZSBVU0EgYW5kIEV1cm9wZSB1c2UgdGhlIHByaW5jaXBsZXMgZnJvbSBQYWxsZXNlbidzIHdvcmsgdG8gZ3JlYXQgZWZmZWN0IGFnYWluc3QgdGhlIFNBUlMtQ29WLTIgc3Bpa2UgcHJvdGVpbiEKCkxldCdzIHRha2UgYSBsb29rIGF0IGhvdyB3ZSBjYW4gdGhpbmsgYWJvdXQgc3RhcnRpbmcgYW4gaW5xdWlyeSBsaWtlIFBhbGxlc2VuIGFuZCBjb3dvcmtlcnMuIFdlIGZpcnN0IG5lZWQgYSBzZXJpZXMgb2YgY29yb25hdmlydXMgc3Bpa2UgcHJvdGVpbiBzZXF1ZW5jZXMgdG8gY29tcGFyZS4gU3BlY2lmaWNhbGx5LCB3ZSBuZWVkIHNlcXVlbmNlcyBmcm9tIEJldGFjb3JvbmF2aXJ1c2VzIChpLmUuIHRoZSBmYW1pbHkgY2F1c2luZyByZXNwaXJhdG9yeSBkaXNvcmRlcnMgaW4gdmFyaW91cyBtYW1tYWxpYW4gaG9zdHMpLiBZb3UgY2FuIGdldCB0aG9zZSBoZXJlLiBbRE9XTkxPQURdKGh0dHBzOi8vZHJpdmUuZ29vZ2xlLmNvbS91Yz9leHBvcnQ9ZG93bmxvYWQmaWQ9MTBHVGdGMmoxZXlkamY5RTlJcHg3MzJ6MDBXQkJIUmlDKQoKRW50ZXIgdGhlc2Ugc2VxdWVuY2VzIGludG8gQ09CQUxUIGFuZCBhbGlnbi4KCk5vdywgbGV0J3MgZXhhbWluZSB0aGUgYWxpZ25tZW50LiBRdWVzdGlvbiBmb3IgdXMgdG8gcG9uZGVyOiAqKklmIHlvdSBoYWQgdG8gY2hvb3NlIGEgcmVnaW9uIHRvIGRlc2lnbiBhbiBlcGl0b3BlLCB3aGljaCB3b3VsZCB5b3UgY2hvb3NlPyBXaHk/KioKClVzaW5nIHRoZSBmaXJzdCBzZXF1ZW5jZSBhcyBhIGd1aWRlIChpdCBpcyBTQVJTLUNvVi0yIHNwaWtlKSwgbmF2aWdhdGUgdG8gdGhlIDk4Ni85ODcgcmVzaWR1ZSBwYWlyLiBUaGVzZSB0d28gcmVzaWR1ZXMsIGluIHRoZSB2YWNjaW5lIFMtMlAgZXBpdG9wZSwgaGF2ZSBiZWVuIG11dGF0ZWQgdG8gcHJvbGluZXMuIFRoZXNlIG11dGF0aW9ucyBsb2NrIHRoZSBzcGlrZSBwcm90ZWluIGludG8gaXRzIGFjdGl2ZSBjb25mb3JtYXRpb24gZm91bmQgaW4gdGhlIHZpcmlvbiBzdXJmYWNlLiBUaGlzIHNpbXBsZSBjaGFuZ2Ugd2FzIGRpcmVjdGVkIGJ5IE1TQSwgc3RydWN0dXJhbCBjb21wYXJpc29uLCBhbmQgaHlwb3RoZXNpcyB0ZXN0aW5nIGluIGxhYiBleHBlcmltZW50cy4gV2l0aG91dCBvdXIgYWJpbGl0eSB0byBjb21wYXJlLi4uIHdlJ2QgYmUgZmFyIGJlaGluZCBpbiBvdXIgZGV2ZWxvcG1lbnQgb2YgdmFjY2luZXMuCgojIE1TQSBpbiBSCgpgYGB7cn0KbGlicmFyeShtc2EpCmBgYAoKV2UgaGF2ZSBzZWVuIHRoZSB1c2Ugb2YgdGhlIGBzZXFpbnJgIHN1YnJvdXRpbmVzIGZvciByZWFkaW5nIGluIEZBU1RBIGRhdGEgKG5hbWVseSBgcmVhZC5mYXN0YSgpYCkuIEhlcmUsIHdlIGNhbiB1c2UgYSBmdW5jdGlvbiBpbiB0aGUgYEJpb3N0cmluZ3NgIHBhY2thZ2UgdG8gbG9hZCBpbiBGQVNUQSBzZXF1ZW5jZXMuIFRoaXMgcGFja2FnZSB3aWxsIGFsc28gcmVhZCBpbiBvdGhlciBmb3JtYXRzLCB0b28uIExpa2UgTW9kdWxlIDUsIHdlIGFyZSBjcmVhdGluZyBhIFN0cmluZ1NldCB2YXJpYWJsZSAoYm94MTcpLiBUaGlzIGlzIHRoZSBzdGFuZGFyZCBpbnB1dCBmb3IgbW9zdCBCaW9jb25kdWN0b3Igc2VxdWVuY2UgYW5hbHlzaXMgcGFja2FnZXMuCgpgYGB7cn0KCmJveDE3IDwtIHJlYWRBQVN0cmluZ1NldCgiaHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL3VjP2V4cG9ydD1kb3dubG9hZCZpZD0xaE1xbUNTOWFlMi1Sdmsyb095aU9NVVpfTVdLQ09laDYiKQoKYGBgCgpUaGUgYG1zYWAgcGFja2FnZSBjb250YWlucyB0aHJlZSBzdWJyb3V0aW5lcyBmb3IgcGVyZm9ybWluZyBDTFVTVEFMVyAocHJvZ3Jlc3NpdmUgb25seSksIENMVVNUQUwgT21lZ2EgKHdpdGggaXRlcmF0aW9uKSwgYW5kIE1VU0NMRSBhbGlnbm1lbnRzLiBUaGVzZSB3aWxsIG1lZXQgbW9zdCBuZWVkcyBhbmQgYWxsb3cgc2VuZGluZyBvdXRwdXQgZGF0YSB0byBhIHZhcmlldHkgb2YgYW5hbHlzaXMgcGFja2FnZXMgLSBzb21lIHdlIHdpbGwgc2VlIG5leHQgd2VlayEKCmBgYHtyfQoKIyB1c2luZyB0aGUgb2xkIENMVVNUQUxXMiBhbGdvcml0aG0KQ2x1c3RhbFcgPSBtc2FDbHVzdGFsVyhib3gxNykKCiMgdXNpbmcgdGhlIGl0ZXJhdGl2ZSBPbWVnYSBhbGdvcml0aG0KQ2x1c3RhbE8gPSBtc2FDbHVzdGFsT21lZ2EoYm94MTcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heGl0ZXJzID0gNSAjIHdlIGNhbiBjaGFuZ2UgdGhlIG51bWJlciBvZiBpdGVyYXRpb25zIG1hbnVhbGx5LCBkZWZhdWx0IGlzIDEtMi4KICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKIyB1c2luZyBNVVNDTEUKTXVzY2xlID0gbXNhTXVzY2xlKGJveDE3KQpgYGAKClRoZSBgbXNhYCBwYWNrYWdlIGFsc28gaGFzIHNvbWUgYWxpZ25tZW50IGFuYWx5c2lzIHRvb2xzLiBPbmUgdXNlZnVsIG9uZSBpcyB0aGUgYG1zYUNvbnNlbnN1c1NlcXVlbmNlKClgIHN1YnJvdXRpbmUuIFRoaXMgd2lsbCBhbGxvdyB5b3UgdG8gZXh0cmFjdCBoaWdobHkgY29uc2VydmVkIG1vdGlmcyAoaS5lLiAxMDAlIGNvbnNlcnZhdGlvbikuCgpgYGB7cn0KCm1zYUNvbnNlbnN1c1NlcXVlbmNlKENsdXN0YWxXKQoKIyBsZXQncyB1c2UgYSBsb29wIGFuZCBjcmVhdGUgc29tZSBvdXRwdXQgd2UgY2FuIGNvbXBhcmUKCmFsaWdubWVudHMgPC0gYyhDbHVzdGFsVywgQ2x1c3RhbE8sIE11c2NsZSkKCmFsaWdubWVudENvbnNlbnN1cyA9IGMoKQoKZm9yIChpIGluIDE6bGVuZ3RoKGFsaWdubWVudHMpKSB7CiAgCiAgYWxpZ25tZW50Q29uc2Vuc3VzW2ldID0gbXNhQ29uc2Vuc3VzU2VxdWVuY2UoYWxpZ25tZW50c1tbaV1dKQogIAp9CgpwcmludChhbGlnbm1lbnRDb25zZW5zdXMpCgpgYGAKCi0tLQoKKipRdWVzdGlvbioqCgpDb21wYXJpbmcgdGhlc2UgY29uc2Vuc3VzIGFsaWdubWVudHMsIGRvIHRoZXkgc2VlbSB0byBjYXB0dXJlIHNpbWlsYXIgbW90aWZzPwoKLS0tCgoKV2UgY2FuIGFsc28gdXNlIGBtc2FgIHRvIG91dHB1dCBtb3JlIHZpc3VhbGx5IGFjY2Vzc2libGUgb3V0cHV0cyB1c2luZyB0aGUgYG1zYVByZXR0eVByaW50YCBzdWJyb3V0aW5lLiBUaGVyZSBhcmUgc2V2ZXJhbCBtb3JlIG9wdGlvbnMgaW4gdGhpcyBzdWJyb3V0aW5lIHRoYW4gc2hvd24gaGVyZSwgYnV0IHRoZSBiYXNpYyBvdXRwdXQgaXMgcmVhc29uYWJseSBpbmZvcm1hdGl2ZSwgYXMgaXMuCgpgYGB7cn0KCm1zYVByZXR0eVByaW50KENsdXN0YWxPLCBvdXRwdXQ9InBkZiIpCgpgYGAKCg==