Using ms via GSImulator

We are using ms this way because it is fairly easy to distribute the binaries in an R package.

library(tidyverse)
library(GSImulator)

ms is a coalescent simulator written in C by Dick Hudson at U Chicago. It has been around for a long time, but a paper describing it came out long after it had been in routine use (Hudson 2002)

It can be downloaded from here. However, I have wrapped up compiled versions in an R package, so you needn’t worry about that.

It is quite fast for simulating small segments of DNA without much recombination. It is worth noting, however, that a more recent program that implements the whole process more efficiently is available and much better for whole-genome-scale simulation (Kelleher, Etheridge, and McVean 2016).

Running ms within R with the system2 command

ms is a program that runs in the shell. Here we use R’s system2() command to run it from within R.

If we invoke ms with no arguments it gives us a message about what kinds of arguments one can use:

# ms_binary() gives the path to ms on your system
system2(command = ms_binary(), args = "")
/Users/eriq/Library/R/4.3/library/GSImulator/bin/ms-Darwin 
Too few command line arguments
usage: ms nsam howmany 
  Options: 
     -t theta   (this option and/or the next must be used. Theta = 4*N0*u )
     -s segsites   ( fixed number of segregating sites)
     -T          (Output gene tree.)
     -F minfreq     Output only sites with freq of minor allele >= minfreq.
     -r rho nsites     (rho here is 4Nc)
         -c f track_len   (f = ratio of conversion rate to rec rate. tracklen is mean length.) 
             if rho = 0.,  f = 4*N0*g, with g the gene conversion rate.
     -G alpha  ( N(t) = N0*exp(-alpha*t) .  alpha = -log(Np/Nr)/t
     -I npop n1 n2 ... [mig_rate] (all elements of mig matrix set to mig_rate/(npop-1) 
         -m i j m_ij    (i,j-th element of mig matrix set to m_ij.)
         -ma m_11 m_12 m_13 m_21 m_22 m_23 ...(Assign values to elements of migration matrix.)
         -n i size_i   (popi has size set to size_i*N0 
         -g i alpha_i  (If used must appear after -M option.)
       The following options modify parameters at the time 't' specified as the first argument:
     -eG t alpha  (Modify growth rate of all pop's.)
     -eg t i alpha_i  (Modify growth rate of pop i.) 
     -eM t mig_rate   (Modify the mig matrix so all elements are mig_rate/(npop-1)
     -em t i j m_ij    (i,j-th element of mig matrix set to m_ij at time t )
     -ema t npop  m_11 m_12 m_13 m_21 m_22 m_23 ...(Assign values to elements of migration matrix.)
     -eN t size  (Modify pop sizes. New sizes = size*N0 ) 
     -en t i size_i  (Modify pop size of pop i.  New size of popi = size_i*N0 .)
     -es t i proportion  (Split: pop i -> pop-i + pop-npop, npop increases by 1.
         proportion is probability that each lineage stays in pop-i. (p, 1-p are admixt. proport.
         Size of pop npop is set to N0 and alpha = 0.0 , size and alpha of pop i are unchanged.
     -ej t i j   ( Join lineages in pop i and pop j into pop j
          size, alpha and M are unchanged.
      -f filename     ( Read command line arguments from file filename.)
 See msdoc.pdf for explanation of these parameters.

That shows a lot of fun things to do. Let’s start by just simulating coalescent trees and looking at them. In order to do that, you will need to install another couple packages if you don’t already have them. See the instructions at: https://eriqande.github.io/coalescent-hands-on/000-prep-for-coalescent.nb.html.

Load the other packages we will use:

library(ape)
library(ggtree)

A basic vanilla tree

Here we simulate a single tree with 10 tips and tell ms to just print the tree out in Newick format:

system2(command = ms_binary(), args = "10 1 -T")
/Users/eriq/Library/R/4.3/library/GSImulator/bin/ms-Darwin 10 1 -T 
17591 45577 21597

//
(((4:0.070,8:0.070):0.057,(5:0.079,(3:0.029,(1:0.023,(6:0.006,9:0.006):0.018):0.006):0.050):0.048):0.822,(7:0.771,(2:0.029,10:0.029):0.742):0.179);

The resulting coalescent tree is written out above in “Newick” format, which is named after a restaurant (“Newick’s”) in New Hampshire where a group of phylogeneticist’s sketched it out on a napkin.

It shows the branch tip numbers and the patterns in which branches in a tree join one another. It also shows the branch lengths in units of time.

In trees made by ms, the branch lengths are coalescence times are in units of \(4N\) generations. So an ms time of 0.5 is the expected coalescence time of a single pair of lineages.

Cool. Now, we can redirect that sort of output into a file, read it in and plot a tree.

system2(command = ms_binary(), args = "10 1 -T", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree") 
ggtree(ctree, layout = "rectangular") +
  geom_tiplab(size = 3) + coord_flip() + scale_x_reverse() 

Note that from here on out, we are going to flip our trees sideways, since it is a little easier to plot them that way with ggtree. Like this:

p <- ggtree(ctree, layout = "rectangular") +
  geom_tiplab(size = 3) +
  theme_tree2()
revts(p)

We also put a “timeline” on that one so that the units of time can be visualized. In this case, time going backwards is depicted as negative.

Multiple trees

One characteristic of the coalescent process is its variability. Here we simulate 12 different trees (each with 10 tips) and plot them to appreciate how variable trees can be, even if simulated from the same neutral process.

system2(command = ms_binary(), args = "10 12 -T", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:12
ggtree(ctree, layout = "rectangular") +
  facet_wrap(~.id, ncol  = 3) +
  geom_tiplab(size = 2)

Population structure

The standard coalescent can easily be updated to include population structure. Basically, at the time of sampling (i.e., “the present”), you specify that your samples are from \(K\) different populations. This is done with the -I flag. For example, -I 2 20 30 means that there are 2 subpopulations with the first 20 (haploid) samples from the first subpopulation, and the next 30 from the second subpopulation. Note that the nsam parameter (number of samples) must be 50 = 20 + 30 in that case.

After the -I 2 20 30 you then give a number which is the population scaled migration rate, \(4Nm\), where \(m\) in the per-generation probability that a parent in the population is an immigrant from a different population. (You can actually specify a whole migration matrix if you want, but we won’t worry about that now.) You can specify an arbitrary number of populations, but we will only focus on two of them in this notebook.

What does the coalescent with migration look like? When everyone gets down to this point, ask Eric, and he will show you with a small example.

Think about this: what does \(4Nm\) mean in terms of how many migrational events you would expect to see in the history of a pair of gene copies? And why? (Once again, think of each branch as a bead-string of generations…)

Let’s do two populations, each of 10 chromosomes (\(2N = 10\)), and let the migration rate be quite low. Like \(4Nm = 0.01\), to see what we get. Let’s do 6 reps:

system2(command = ms_binary(), args = "20 6 -T -I 2 10 10 0.01", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:6
ggtree(ctree, layout = "rectangular") +
  facet_wrap(~.id, ncol  = 3) +
  geom_tiplab(size = 2)

OK, at such low migration rates, we see that all 10 gene copies in each population have, almost without exception, coalesced with one another before coalescing with any genes from the other population.

That is not the always the case when migration rate gets higher, for example \(4Nm = 0.2\).

system2(command = ms_binary(), args = "20 6 -T -I 2 10 10 0.2", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:6
ggtree(ctree, layout = "rectangular") +
  facet_wrap(~.id, ncol  = 3) +
  geom_tiplab(size = 2)

By taking the limit as the mutation rate goes to zero, Monty Slatkin, showed that the parameter \(F_\mathrm{ST}\) can be defined in terms of the expected coalescent times between pairs of genes drawn within and between different populations. \[ F_\mathrm{ST} = \frac{\bar{t} - \bar{t}_0}{\bar{t}} \] where \(\bar{t}_0\) is the expected coalescence time between two genes drawn at random from within subpopulations and \(\bar{t}\) is the expected coalescence time for two gene copies drawn at random from amongst all those in either subpopulation (Slatkin 2007).

Population growth

As the manual for ms notes, “The switch -G [used like ms nsam nreps -t 4 -G a] is used to specify that the population has been growing (or shrinking) exponentially. That is, the population size at time \(t\) in the past is given by: \(N(t) = N_0 \exp^{-at}\), where \(t\) is the time before the present, measured in units of \(4N_0\) generations.” Note that \(N_0\) is the size of the population at the time of sampling. So, if \(a>0\) it means the population was smaller further back in time.

Let’s make some plots to grok out what this means. First, let’s pretend that we are thinking about a population that, at the time of sampling is of size \(N_0 = 10,000\). And so, if we were interested in what its population size was, say 34,000 generations ago, then that would mean that time, measured in units of \(4N_0\) generations would be: \[ t = \frac{34,000}{4N_0} = \frac{34,000}{40,0000} \approx 0.85 \]

So, let’s make a picture of what the population size looks like at different times going back in the past. You can play with the values of N_0 and a below to see what you get

# define parameter values
N_0 <- 10000
a = 5

# make a tibble of different values at different times
ptib <- tibble(
  generations = seq(0, 5 * N_0, by = N_0 / 100)
) %>% 
  mutate(t = generations / (4 * N_0),
         Nt = N_0 * exp(-t * a)
         )

# make a plot
ggplot(ptib, aes(x = generations, y = Nt)) +
  geom_line() +
  scale_x_continuous("Time in generations", sec.axis = sec_axis(~ . / (4 * N_0), name = "Time in 4N_0 generations" ))

Population growth can stretch trees out. If a population is growing exponentially then the terminal branches tend to be longer. Let’s experiment with that.

system2(command = ms_binary(), args = "10 6 -T -G 5", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:6
ggtree(ctree, layout = "rectangular") +
  facet_wrap(~.id, ncol  = 3) +
  geom_tiplab(size = 2)

Yep, longer terminal branches. Play around with different settings and check out the results.

Instantaneous population size changes

Past changes in the populations are controlled by values of -eSomething options. Where the e stands for event. The simplest of these are instantaneous changes in population size. The simplest is:

  • -en t i x which means “Set subpop \(i\) size to \(x \times N_0\) at time \(t\) and growth rate to zero.

So, for example, in our migration model above we could make the two populations very different sizes and see what the results are. Let’s make population 2 ten times bigger than population 1 from the present all the way back into the past…

system2(command = ms_binary(), args = "20 6 -T -I 2 10 10 0.01 -en 0 2 10", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:6
ggtree(ctree, layout = "rectangular") +
  facet_wrap(~.id, ncol  = 3) +
  geom_tiplab(size = 2)

Aha! That is interesting. It is hard to tell, because the coalescence times are so short in population 1, but if you squint, you can convince yourself that, on average, the trees in population 2 reach a MRCA in about 10 times the amount of time as the trees in population 1.

The results also show that there is a lot of variability in the coalescent process.

Population Splitting/Merging

My goodness, there are a lot of options in ms. To see the full rundown on all the options, you can read the full documentation: msdoc.pdf. But for now, we will just discuss one more, used to join or split two populations going back in time.

  • -ej t i j which means move all lineages in subpopulation \(i\) into subpopulation \(j\) at time \(t\) in units of \(4N_0\). The j means “join”. It corresponds to populations “joining” while going backward in time. But, forward in time this corresponds to population splitting.

  • -es t i p which means split subpopulation \(i\) into two subpopulations \(i\) and \(npop + 1\) \(t\) (in units of \(4N_0\)). Lineages currently in \(i\) remain in \(i\) with probability \(p\) and with probability \(1-p\) they get placed into subpopulation \(npop + 1\). The s means split.
    It corresponds to populations “joining” while going forward in time.

Discuss with your partner: What are some conservation-genetic scenarios that these last two demographic scenarios might correspond to?

Here is an example of a population join going back in time. We have 10 samples from each population with no migration between them, and the populations join at time \(2N_0\) in the past (at which point most will have coalesced within subpopulations):

system2(command = ms_binary(), args = "20 6 -T -I 2 10 10 0.00 -ej 0.5 1 2", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:6
ggtree(ctree, layout = "rectangular") +
  facet_wrap(~.id, ncol  = 3) +
  geom_tiplab(size = 2)

Your Mission/Homework!

All right, after playing around with all the above, look at the tree below and, with your group:

  1. think about and discuss what the demography might have looked like to produce the tree. Think about how different population sizes must have been and at which time periods population size changes might have happened.

  2. Check your hypotheses by generating some trees with ms.

Here is a hint. To make the trees below, I didn’t bother with exponential growth, I just used (quite unrealistic) instantaneous population size changes.

References

Hudson, Richard R. 2002. “Generating Samples Under a Wright Neutral Model of Genetic Variation.” Bioinformatics 18 (2): 337–38. https://doi.org/10.1093/bioinformatics/18.2.337.
Kelleher, Jerome, Alison M. Etheridge, and Gilean McVean. 2016. “Efficient Coalescent Simulation and Genealogical Analysis for Large Sample Sizes.” PLOS Computational Biology 12 (5): e1004842. https://doi.org/10.1371/journal.pcbi.1004842.
Slatkin, Montgomery. 2007. “Inbreeding Coefficients and Coalescence Times.” Genetical Research 89 (5-6): 479. https://doi.org/10.1017/S0016672308009671.
LS0tCnRpdGxlOiAiVGhlIENvYWxlc2NlbnQgd2l0aCBQb3B1bGF0aW9uIFN0cnVjdHVyZSBhbmQgRGVtb2dyYXBoeSwgZXRjLiIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKYXV0aG9yOiAiRXJpYyBDLiBBbmRlcnNvbiIKYmlibGlvZ3JhcGh5OiByZWZlcmVuY2VzLmJpYgotLS0KCgoKCgojIyBVc2luZyBgbXNgIHZpYSBHU0ltdWxhdG9yCgpXZSBhcmUgdXNpbmcgYG1zYCB0aGlzIHdheSBiZWNhdXNlIGl0IGlzIGZhaXJseSBlYXN5IHRvIGRpc3RyaWJ1dGUgdGhlIGJpbmFyaWVzCmluIGFuIFIgcGFja2FnZS4KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KEdTSW11bGF0b3IpCmBgYAoKYG1zYCBpcyBhIGNvYWxlc2NlbnQgc2ltdWxhdG9yIHdyaXR0ZW4gaW4gQyBieSBEaWNrIEh1ZHNvbiBhdCBVIENoaWNhZ28uICBJdCBoYXMKYmVlbiBhcm91bmQgZm9yIGEgbG9uZyB0aW1lLCBidXQgYSBwYXBlciBkZXNjcmliaW5nIGl0IGNhbWUgb3V0IGxvbmcgYWZ0ZXIgaXQgaGFkIApiZWVuIGluIHJvdXRpbmUgdXNlIFtAaHVkc29uR2VuZXJhdGluZ1NhbXBsZXNXcmlnaHQyMDAyXQoKCkl0IGNhbiBiZSBkb3dubG9hZGVkIGZyb20gW2hlcmVdKGh0dHA6Ly9ob21lLnVjaGljYWdvLmVkdS9yaHVkc29uMS9zb3VyY2UvbWtzYW1wbGVzLmh0bWwpLgpIb3dldmVyLCBJIGhhdmUKd3JhcHBlZCB1cCBjb21waWxlZCB2ZXJzaW9ucyBpbiBhbiBSIHBhY2thZ2UsIHNvIHlvdSBuZWVkbid0IHdvcnJ5IGFib3V0IHRoYXQuCgoKSXQgaXMgcXVpdGUgZmFzdCBmb3Igc2ltdWxhdGluZyBzbWFsbCBzZWdtZW50cyBvZiAKRE5BIHdpdGhvdXQgbXVjaCByZWNvbWJpbmF0aW9uLiAgSXQgaXMgd29ydGggbm90aW5nLCBob3dldmVyLCB0aGF0IAphIG1vcmUgcmVjZW50IHByb2dyYW0gdGhhdCBpbXBsZW1lbnRzIHRoZSB3aG9sZSBwcm9jZXNzIG1vcmUgZWZmaWNpZW50bHkKaXMgYXZhaWxhYmxlIGFuZCBtdWNoIGJldHRlciBmb3Igd2hvbGUtZ2Vub21lLXNjYWxlIHNpbXVsYXRpb24gW0BrZWxsZWhlckVmZmljaWVudENvYWxlc2NlbnRTaW11bGF0aW9uMjAxNl0uCgojIyMgUnVubmluZyBgbXNgIHdpdGhpbiBSIHdpdGggdGhlIHN5c3RlbTIgY29tbWFuZAoKYG1zYCBpcyBhIHByb2dyYW0gdGhhdCBydW5zIGluIHRoZSBzaGVsbC4gIEhlcmUgd2UgdXNlIFIncyBgc3lzdGVtMigpYCBjb21tYW5kIHRvIHJ1biBpdApmcm9tIHdpdGhpbiBSLgoKSWYgd2UgaW52b2tlIGBtc2Agd2l0aCBubyBhcmd1bWVudHMgaXQgZ2l2ZXMgdXMgYSBtZXNzYWdlIGFib3V0IHdoYXQga2luZHMKb2YgYXJndW1lbnRzIG9uZSBjYW4gdXNlOgpgYGB7cn0KIyBtc19iaW5hcnkoKSBnaXZlcyB0aGUgcGF0aCB0byBtcyBvbiB5b3VyIHN5c3RlbQpzeXN0ZW0yKGNvbW1hbmQgPSBtc19iaW5hcnkoKSwgYXJncyA9ICIiKQpgYGAKClRoYXQgc2hvd3MgYSBsb3Qgb2YgZnVuIHRoaW5ncyB0byBkby4gIExldCdzIHN0YXJ0IGJ5IGp1c3Qgc2ltdWxhdGluZyBjb2FsZXNjZW50IAp0cmVlcyBhbmQgbG9va2luZyBhdCB0aGVtLiAgSW4gb3JkZXIgdG8gZG8gdGhhdCwgeW91IHdpbGwgbmVlZCB0byBpbnN0YWxsIGFub3RoZXIKY291cGxlIHBhY2thZ2VzIGlmIHlvdSBkb24ndCBhbHJlYWR5IGhhdmUgdGhlbS4gIFNlZSB0aGUgaW5zdHJ1Y3Rpb25zIGF0OiBbaHR0cHM6Ly9lcmlxYW5kZS5naXRodWIuaW8vY29hbGVzY2VudC1oYW5kcy1vbi8wMDAtcHJlcC1mb3ItY29hbGVzY2VudC5uYi5odG1sXShodHRwczovL2VyaXFhbmRlLmdpdGh1Yi5pby9jb2FsZXNjZW50LWhhbmRzLW9uLzAwMC1wcmVwLWZvci1jb2FsZXNjZW50Lm5iLmh0bWwpLgoKTG9hZCB0aGUgb3RoZXIgcGFja2FnZXMgd2Ugd2lsbCB1c2U6CmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGFwZSkKbGlicmFyeShnZ3RyZWUpCmBgYAoKCiMjIyBBIGJhc2ljIHZhbmlsbGEgdHJlZQoKSGVyZSB3ZSBzaW11bGF0ZSBhIHNpbmdsZSB0cmVlIHdpdGggMTAgdGlwcyBhbmQgdGVsbCBgbXNgIHRvIGp1c3QgcHJpbnQgdGhlIHRyZWUgb3V0CmluIE5ld2ljayBmb3JtYXQ6CmBgYHtyfQpzeXN0ZW0yKGNvbW1hbmQgPSBtc19iaW5hcnkoKSwgYXJncyA9ICIxMCAxIC1UIikKYGBgCgpUaGUgcmVzdWx0aW5nIGNvYWxlc2NlbnQgdHJlZSBpcyB3cml0dGVuIG91dCBhYm92ZSBpbiAiTmV3aWNrIiBmb3JtYXQsIHdoaWNoIGlzCm5hbWVkIGFmdGVyIGEgcmVzdGF1cmFudCAoIk5ld2ljaydzIikgaW4gTmV3IEhhbXBzaGlyZSB3aGVyZSBhIGdyb3VwIG9mIHBoeWxvZ2VuZXRpY2lzdCdzCnNrZXRjaGVkIGl0IG91dCBvbiBhIG5hcGtpbi4KCkl0IHNob3dzIHRoZSBicmFuY2ggdGlwIG51bWJlcnMgYW5kIHRoZSBwYXR0ZXJucyBpbiB3aGljaApicmFuY2hlcyBpbiBhIHRyZWUgam9pbiBvbmUgYW5vdGhlci4gIEl0IGFsc28gc2hvd3MgdGhlIGJyYW5jaApsZW5ndGhzIGluIHVuaXRzIG9mIHRpbWUuCgpJbiB0cmVlcyBtYWRlIGJ5IGBtc2AsIHRoZSBicmFuY2ggbGVuZ3RocyBhcmUgY29hbGVzY2VuY2UgdGltZXMgYXJlCmluIHVuaXRzIG9mICQ0TiQgZ2VuZXJhdGlvbnMuICBTbyBhbiBgbXNgIHRpbWUgb2YgMC41IGlzIHRoZSBleHBlY3RlZApjb2FsZXNjZW5jZSB0aW1lIG9mIGEgc2luZ2xlIHBhaXIgb2YgbGluZWFnZXMuCgoKCkNvb2wuICBOb3csIHdlIGNhbiByZWRpcmVjdCB0aGF0IHNvcnQgb2Ygb3V0cHV0IGludG8gYSBmaWxlLCByZWFkIGl0IGluIGFuZCBwbG90CmEgdHJlZS4KYGBge3J9CnN5c3RlbTIoY29tbWFuZCA9IG1zX2JpbmFyeSgpLCBhcmdzID0gIjEwIDEgLVQiLCBzdGRvdXQgPSAib3V0LnRyZWUiLCBzdGRlcnIgPSBGQUxTRSkKY3RyZWUgPC0gcmVhZC50cmVlKCJvdXQudHJlZSIpIApnZ3RyZWUoY3RyZWUsIGxheW91dCA9ICJyZWN0YW5ndWxhciIpICsKICBnZW9tX3RpcGxhYihzaXplID0gMykgKyBjb29yZF9mbGlwKCkgKyBzY2FsZV94X3JldmVyc2UoKSAKYGBgCgpOb3RlIHRoYXQgZnJvbSBoZXJlIG9uIG91dCwgd2UgYXJlIGdvaW5nIHRvIGZsaXAgb3VyIHRyZWVzIHNpZGV3YXlzLCBzaW5jZSBpdCBpcyBhIGxpdHRsZQplYXNpZXIgdG8gcGxvdCB0aGVtIHRoYXQgd2F5IHdpdGggZ2d0cmVlLiAgTGlrZSB0aGlzOgpgYGB7cn0KcCA8LSBnZ3RyZWUoY3RyZWUsIGxheW91dCA9ICJyZWN0YW5ndWxhciIpICsKICBnZW9tX3RpcGxhYihzaXplID0gMykgKwogIHRoZW1lX3RyZWUyKCkKcmV2dHMocCkKYGBgCgpXZSBhbHNvIHB1dCBhICJ0aW1lbGluZSIgb24gdGhhdCBvbmUgc28gdGhhdCB0aGUgdW5pdHMgb2YgdGltZSBjYW4gYmUgdmlzdWFsaXplZC4KSW4gdGhpcyBjYXNlLCB0aW1lIGdvaW5nIGJhY2t3YXJkcyBpcyBkZXBpY3RlZCBhcyBuZWdhdGl2ZS4KCgojIyMgTXVsdGlwbGUgdHJlZXMKCk9uZSBjaGFyYWN0ZXJpc3RpYyBvZiB0aGUgY29hbGVzY2VudCBwcm9jZXNzIGlzIGl0cyB2YXJpYWJpbGl0eS4gIEhlcmUKd2Ugc2ltdWxhdGUgMTIgZGlmZmVyZW50IHRyZWVzIChlYWNoIHdpdGggMTAgdGlwcykgYW5kIHBsb3QKdGhlbSB0byBhcHByZWNpYXRlIGhvdyB2YXJpYWJsZQp0cmVlcyBjYW4gYmUsIGV2ZW4gaWYgc2ltdWxhdGVkIGZyb20gdGhlIHNhbWUgbmV1dHJhbCBwcm9jZXNzLgoKYGBge3J9CnN5c3RlbTIoY29tbWFuZCA9IG1zX2JpbmFyeSgpLCBhcmdzID0gIjEwIDEyIC1UIiwgc3Rkb3V0ID0gIm91dC50cmVlIiwgc3RkZXJyID0gRkFMU0UpCmN0cmVlIDwtIHJlYWQudHJlZSgib3V0LnRyZWUiKQpuYW1lcyhjdHJlZSkgPC0gMToxMgpnZ3RyZWUoY3RyZWUsIGxheW91dCA9ICJyZWN0YW5ndWxhciIpICsKICBmYWNldF93cmFwKH4uaWQsIG5jb2wgID0gMykgKwogIGdlb21fdGlwbGFiKHNpemUgPSAyKQoKYGBgCgojIyMgUG9wdWxhdGlvbiBzdHJ1Y3R1cmUgCgpUaGUgc3RhbmRhcmQgY29hbGVzY2VudCBjYW4gZWFzaWx5IGJlIHVwZGF0ZWQgdG8gaW5jbHVkZSBwb3B1bGF0aW9uIHN0cnVjdHVyZS4gIEJhc2ljYWxseSwKYXQgdGhlIHRpbWUgb2Ygc2FtcGxpbmcgKGkuZS4sICJ0aGUgcHJlc2VudCIpLCB5b3Ugc3BlY2lmeSB0aGF0IHlvdXIgc2FtcGxlcyBhcmUgZnJvbSAkSyQKZGlmZmVyZW50IHBvcHVsYXRpb25zLiAgVGhpcyBpcyBkb25lIHdpdGggdGhlIGAtSWAgZmxhZy4gIEZvciBleGFtcGxlLCBgLUkgMiAyMCAzMGAgbWVhbnMgdGhhdAp0aGVyZSBhcmUgMiBzdWJwb3B1bGF0aW9ucyB3aXRoCnRoZSBmaXJzdCAyMCAoaGFwbG9pZCkgc2FtcGxlcyBmcm9tIHRoZSBmaXJzdCBzdWJwb3B1bGF0aW9uLCBhbmQgdGhlIG5leHQgMzAgZnJvbSB0aGUgc2Vjb25kCnN1YnBvcHVsYXRpb24uICBOb3RlIHRoYXQgdGhlIG5zYW0gcGFyYW1ldGVyIChudW1iZXIgb2Ygc2FtcGxlcykgbXVzdCBiZSA1MCA9IDIwICsgMzAgaW4gdGhhdCBjYXNlLgoKQWZ0ZXIgdGhlIGAtSSAyIDIwIDMwYCB5b3UgdGhlbiBnaXZlIGEgbnVtYmVyIHdoaWNoIGlzIHRoZSBfcG9wdWxhdGlvbiBzY2FsZWQgbWlncmF0aW9uIHJhdGVfLCAkNE5tJCwgCndoZXJlICRtJCBpbiB0aGUgcGVyLWdlbmVyYXRpb24gcHJvYmFiaWxpdHkgdGhhdCBhIHBhcmVudCBpbiB0aGUgcG9wdWxhdGlvbiBpcyBhbgppbW1pZ3JhbnQgZnJvbSBhIGRpZmZlcmVudCBwb3B1bGF0aW9uLiAgKFlvdSBjYW4gYWN0dWFsbHkgc3BlY2lmeSBhIHdob2xlIG1pZ3JhdGlvbiBtYXRyaXggaWYgeW91CndhbnQsIGJ1dCB3ZSB3b24ndCB3b3JyeSBhYm91dCB0aGF0IG5vdy4pICBZb3UgY2FuIHNwZWNpZnkgYW4gYXJiaXRyYXJ5IG51bWJlciBvZiBwb3B1bGF0aW9ucywKYnV0IHdlIHdpbGwgb25seSBmb2N1cyBvbiB0d28gb2YgdGhlbSBpbiB0aGlzIG5vdGVib29rLiAgCgpXaGF0IGRvZXMgdGhlIGNvYWxlc2NlbnQgd2l0aCBtaWdyYXRpb24gbG9vayBsaWtlPyBXaGVuIGV2ZXJ5b25lIGdldHMgZG93biB0byB0aGlzCnBvaW50LCBhc2sgRXJpYywgYW5kIGhlIHdpbGwgc2hvdyB5b3Ugd2l0aCBhIHNtYWxsIGV4YW1wbGUuICAKClRoaW5rIGFib3V0IHRoaXM6IHdoYXQgZG9lcyAkNE5tJCBtZWFuIGluIHRlcm1zIG9mIGhvdyBtYW55IG1pZ3JhdGlvbmFsIGV2ZW50cyB5b3Ugd291bGQKZXhwZWN0IHRvIHNlZSBpbiB0aGUgaGlzdG9yeSBvZiBhIHBhaXIgb2YgZ2VuZSBjb3BpZXM/IEFuZCB3aHk/IChPbmNlIGFnYWluLCB0aGluayBvZiAKZWFjaCBicmFuY2ggYXMgYSBiZWFkLXN0cmluZyBvZiBnZW5lcmF0aW9ucy4uLikKCkxldCdzIGRvIHR3byBwb3B1bGF0aW9ucywgZWFjaCBvZiAxMCBjaHJvbW9zb21lcyAoJDJOID0gMTAkKSwgYW5kIGxldCB0aGUgbWlncmF0aW9uCnJhdGUgYmUgcXVpdGUgbG93LiAgTGlrZSAkNE5tID0gMC4wMSQsIHRvIHNlZSB3aGF0IHdlIGdldC4gIExldCdzIGRvIDYgcmVwczoKYGBge3J9CnN5c3RlbTIoY29tbWFuZCA9IG1zX2JpbmFyeSgpLCBhcmdzID0gIjIwIDYgLVQgLUkgMiAxMCAxMCAwLjAxIiwgc3Rkb3V0ID0gIm91dC50cmVlIiwgc3RkZXJyID0gRkFMU0UpCmN0cmVlIDwtIHJlYWQudHJlZSgib3V0LnRyZWUiKQpuYW1lcyhjdHJlZSkgPC0gMTo2CmdndHJlZShjdHJlZSwgbGF5b3V0ID0gInJlY3Rhbmd1bGFyIikgKwogIGZhY2V0X3dyYXAofi5pZCwgbmNvbCAgPSAzKSArCiAgZ2VvbV90aXBsYWIoc2l6ZSA9IDIpCmBgYAoKT0ssIGF0IHN1Y2ggbG93IG1pZ3JhdGlvbiByYXRlcywgd2Ugc2VlIHRoYXQgYWxsIDEwIGdlbmUgY29waWVzIGluIGVhY2ggcG9wdWxhdGlvbiBoYXZlLAphbG1vc3Qgd2l0aG91dCBleGNlcHRpb24sIGNvYWxlc2NlZCB3aXRoIG9uZSBhbm90aGVyIGJlZm9yZSBjb2FsZXNjaW5nIHdpdGggYW55IGdlbmVzIGZyb20KdGhlIG90aGVyIHBvcHVsYXRpb24uICAKClRoYXQgaXMgbm90IHRoZSBhbHdheXMgdGhlIGNhc2Ugd2hlbiBtaWdyYXRpb24gcmF0ZSBnZXRzIGhpZ2hlciwgZm9yIGV4YW1wbGUgJDRObSA9IDAuMiQuICAKYGBge3J9CnN5c3RlbTIoY29tbWFuZCA9IG1zX2JpbmFyeSgpLCBhcmdzID0gIjIwIDYgLVQgLUkgMiAxMCAxMCAwLjIiLCBzdGRvdXQgPSAib3V0LnRyZWUiLCBzdGRlcnIgPSBGQUxTRSkKY3RyZWUgPC0gcmVhZC50cmVlKCJvdXQudHJlZSIpCm5hbWVzKGN0cmVlKSA8LSAxOjYKZ2d0cmVlKGN0cmVlLCBsYXlvdXQgPSAicmVjdGFuZ3VsYXIiKSArCiAgZmFjZXRfd3JhcCh+LmlkLCBuY29sICA9IDMpICsKICBnZW9tX3RpcGxhYihzaXplID0gMikKYGBgCgpCeSB0YWtpbmcgdGhlIGxpbWl0IGFzIHRoZSBtdXRhdGlvbiByYXRlIGdvZXMgdG8gemVybywgTW9udHkgU2xhdGtpbiwgc2hvd2VkCnRoYXQgdGhlIHBhcmFtZXRlciAkRl9cbWF0aHJte1NUfSQgY2FuIGJlIGRlZmluZWQgaW4gdGVybXMgb2YgdGhlIGV4cGVjdGVkIGNvYWxlc2NlbnQgCnRpbWVzIGJldHdlZW4gcGFpcnMgb2YgZ2VuZXMgZHJhd24gd2l0aGluIGFuZCBiZXR3ZWVuIGRpZmZlcmVudCBwb3B1bGF0aW9ucy4gCiQkCkZfXG1hdGhybXtTVH0gPSBcZnJhY3tcYmFye3R9IC0gXGJhcnt0fV8wfXtcYmFye3R9fQokJAp3aGVyZSAkXGJhcnt0fV8wJCBpcyB0aGUgZXhwZWN0ZWQgY29hbGVzY2VuY2UgdGltZSBiZXR3ZWVuIHR3byBnZW5lcyBkcmF3biBhdCByYW5kb20KZnJvbSB3aXRoaW4gc3VicG9wdWxhdGlvbnMgYW5kICRcYmFye3R9JCBpcyB0aGUgZXhwZWN0ZWQgY29hbGVzY2VuY2UgdGltZSBmb3IgdHdvIGdlbmUKY29waWVzIGRyYXduIGF0IHJhbmRvbSBmcm9tIGFtb25nc3QgYWxsIHRob3NlIGluIGVpdGhlciBzdWJwb3B1bGF0aW9uIFtAc2xhdGtpbkluYnJlZWRpbmdDb2VmZmljaWVudHNDb2FsZXNjZW5jZTIwMDddLgoKIyMjIFBvcHVsYXRpb24gZ3Jvd3RoCgpBcyB0aGUgbWFudWFsIGZvciBgbXNgIG5vdGVzLCAiVGhlIHN3aXRjaCBgLUdgIFt1c2VkIGxpa2UgYG1zIG5zYW0gbnJlcHMgLXQgNCAtRyBhYF0gaXMgdXNlZCB0byBzcGVjaWZ5IHRoYXQgdGhlIHBvcHVsYXRpb24gaGFzIGJlZW4gZ3Jvd2luZyAob3Igc2hyaW5raW5nKSBleHBvbmVudGlhbGx5LiBUaGF0IGlzLCB0aGUgcG9wdWxhdGlvbiBzaXplIGF0IHRpbWUgJHQkIGluIHRoZSBwYXN0IGlzIGdpdmVuIGJ5OiAkTih0KSA9IE5fMCBcZXhwXnstYXR9JCwgd2hlcmUgJHQkIGlzIHRoZSB0aW1lIGJlZm9yZSB0aGUgcHJlc2VudCwgbWVhc3VyZWQgaW4gdW5pdHMgb2YgJDROXzAkIGdlbmVyYXRpb25zLiIgTm90ZSB0aGF0ICROXzAkIGlzIHRoZSBzaXplIG9mIHRoZSBwb3B1bGF0aW9uIGF0IHRoZSB0aW1lIG9mIHNhbXBsaW5nLiBTbywgaWYgJGE+MCQgaXQgbWVhbnMgdGhlIHBvcHVsYXRpb24gd2FzIHNtYWxsZXIgZnVydGhlciBiYWNrIGluIHRpbWUuCgpMZXQncyBtYWtlIHNvbWUgcGxvdHMgdG8gZ3JvayBvdXQgd2hhdCB0aGlzIG1lYW5zLiBGaXJzdCwgbGV0J3MgcHJldGVuZCB0aGF0IHdlIGFyZSB0aGlua2luZyBhYm91dCBhCnBvcHVsYXRpb24gdGhhdCwgYXQgdGhlIHRpbWUgb2Ygc2FtcGxpbmcgaXMgb2Ygc2l6ZSAkTl8wID0gMTAsMDAwJC4gIEFuZCBzbywgaWYgd2Ugd2VyZSBpbnRlcmVzdGVkIGluCndoYXQgaXRzIHBvcHVsYXRpb24gc2l6ZSB3YXMsIHNheSAzNCwwMDAgZ2VuZXJhdGlvbnMgYWdvLCB0aGVuIHRoYXQgd291bGQgbWVhbiB0aGF0IHRpbWUsIG1lYXN1cmVkIGluIHVuaXRzCm9mICQ0Tl8wJCBnZW5lcmF0aW9ucyB3b3VsZCBiZToKJCQKdCA9IFxmcmFjezM0LDAwMH17NE5fMH0gPSBcZnJhY3szNCwwMDB9ezQwLDAwMDB9IFxhcHByb3ggMC44NQokJAoKU28sIGxldCdzIG1ha2UgYSBwaWN0dXJlIG9mIHdoYXQgdGhlIHBvcHVsYXRpb24gc2l6ZSBsb29rcyBsaWtlIGF0IGRpZmZlcmVudCB0aW1lcyBnb2luZyBiYWNrIGluIHRoZSBwYXN0LgpZb3UgY2FuIHBsYXkgd2l0aCB0aGUgdmFsdWVzIG9mIGBOXzBgIGFuZCBgYWAgYmVsb3cgdG8gc2VlIHdoYXQgeW91IGdldCAKYGBge3J9CiMgZGVmaW5lIHBhcmFtZXRlciB2YWx1ZXMKTl8wIDwtIDEwMDAwCmEgPSA1CgojIG1ha2UgYSB0aWJibGUgb2YgZGlmZmVyZW50IHZhbHVlcyBhdCBkaWZmZXJlbnQgdGltZXMKcHRpYiA8LSB0aWJibGUoCiAgZ2VuZXJhdGlvbnMgPSBzZXEoMCwgNSAqIE5fMCwgYnkgPSBOXzAgLyAxMDApCikgJT4lIAogIG11dGF0ZSh0ID0gZ2VuZXJhdGlvbnMgLyAoNCAqIE5fMCksCiAgICAgICAgIE50ID0gTl8wICogZXhwKC10ICogYSkKICAgICAgICAgKQoKIyBtYWtlIGEgcGxvdApnZ3Bsb3QocHRpYiwgYWVzKHggPSBnZW5lcmF0aW9ucywgeSA9IE50KSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoIlRpbWUgaW4gZ2VuZXJhdGlvbnMiLCBzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAvICg0ICogTl8wKSwgbmFtZSA9ICJUaW1lIGluIDROXzAgZ2VuZXJhdGlvbnMiICkpCgpgYGAKClBvcHVsYXRpb24gZ3Jvd3RoIGNhbiBzdHJldGNoIHRyZWVzIG91dC4gIElmIGEgcG9wdWxhdGlvbiBpcyBncm93aW5nIGV4cG9uZW50aWFsbHkKdGhlbiB0aGUgdGVybWluYWwgYnJhbmNoZXMgdGVuZCB0byBiZSBsb25nZXIuICBMZXQncyBleHBlcmltZW50IHdpdGggdGhhdC4KYGBge3J9CnN5c3RlbTIoY29tbWFuZCA9IG1zX2JpbmFyeSgpLCBhcmdzID0gIjEwIDYgLVQgLUcgNSIsIHN0ZG91dCA9ICJvdXQudHJlZSIsIHN0ZGVyciA9IEZBTFNFKQpjdHJlZSA8LSByZWFkLnRyZWUoIm91dC50cmVlIikKbmFtZXMoY3RyZWUpIDwtIDE6NgpnZ3RyZWUoY3RyZWUsIGxheW91dCA9ICJyZWN0YW5ndWxhciIpICsKICBmYWNldF93cmFwKH4uaWQsIG5jb2wgID0gMykgKwogIGdlb21fdGlwbGFiKHNpemUgPSAyKQpgYGAKWWVwLCBsb25nZXIgdGVybWluYWwgYnJhbmNoZXMuIFBsYXkgYXJvdW5kIHdpdGggZGlmZmVyZW50IHNldHRpbmdzIGFuZCBjaGVjayBvdXQgdGhlCnJlc3VsdHMuCgojIyMgSW5zdGFudGFuZW91cyBwb3B1bGF0aW9uIHNpemUgY2hhbmdlcwoKUGFzdCBjaGFuZ2VzIGluIHRoZSBwb3B1bGF0aW9ucyBhcmUgY29udHJvbGxlZCBieSB2YWx1ZXMgb2YgYC1lU29tZXRoaW5nYCBvcHRpb25zLiAgV2hlcmUKdGhlIGUgc3RhbmRzIGZvciBldmVudC4gIFRoZSBzaW1wbGVzdCBvZiB0aGVzZSBhcmUgaW5zdGFudGFuZW91cyBjaGFuZ2VzIGluIHBvcHVsYXRpb24Kc2l6ZS4gIFRoZSBzaW1wbGVzdCBpczoKCiogYC1lbiB0IGkgeGAgd2hpY2ggbWVhbnMgIlNldCBzdWJwb3AgJGkkIHNpemUgdG8gJHggXHRpbWVzIE5fMCQgYXQgdGltZSAkdCQgYW5kIGdyb3d0aCByYXRlIHRvIHplcm8uCgpTbywgZm9yIGV4YW1wbGUsIGluIG91ciBtaWdyYXRpb24gbW9kZWwgYWJvdmUgd2UgY291bGQgbWFrZSB0aGUgdHdvIHBvcHVsYXRpb25zIHZlcnkgZGlmZmVyZW50IHNpemVzCmFuZCBzZWUgd2hhdCB0aGUgcmVzdWx0cyBhcmUuICBMZXQncyBtYWtlIHBvcHVsYXRpb24gMiB0ZW4gdGltZXMgYmlnZ2VyIHRoYW4gcG9wdWxhdGlvbiAxIGZyb20KdGhlIHByZXNlbnQgYWxsIHRoZSB3YXkgYmFjayBpbnRvIHRoZSBwYXN0Li4uCmBgYHtyfQpzeXN0ZW0yKGNvbW1hbmQgPSBtc19iaW5hcnkoKSwgYXJncyA9ICIyMCA2IC1UIC1JIDIgMTAgMTAgMC4wMSAtZW4gMCAyIDEwIiwgc3Rkb3V0ID0gIm91dC50cmVlIiwgc3RkZXJyID0gRkFMU0UpCmN0cmVlIDwtIHJlYWQudHJlZSgib3V0LnRyZWUiKQpuYW1lcyhjdHJlZSkgPC0gMTo2CmdndHJlZShjdHJlZSwgbGF5b3V0ID0gInJlY3Rhbmd1bGFyIikgKwogIGZhY2V0X3dyYXAofi5pZCwgbmNvbCAgPSAzKSArCiAgZ2VvbV90aXBsYWIoc2l6ZSA9IDIpCmBgYAoKQWhhISBUaGF0IGlzIGludGVyZXN0aW5nLiAgSXQgaXMgaGFyZCB0byB0ZWxsLCBiZWNhdXNlIHRoZSBjb2FsZXNjZW5jZSB0aW1lcyBhcmUgc28gc2hvcnQgaW4gcG9wdWxhdGlvbgoxLCBidXQgaWYgeW91IHNxdWludCwgeW91IGNhbiBjb252aW5jZSB5b3Vyc2VsZiB0aGF0LCBvbiBhdmVyYWdlLCB0aGUgdHJlZXMgaW4gcG9wdWxhdGlvbiAyIHJlYWNoIAphIE1SQ0EgaW4gYWJvdXQgMTAgdGltZXMgdGhlIGFtb3VudCBvZiB0aW1lIGFzIHRoZSB0cmVlcyBpbiBwb3B1bGF0aW9uIDEuCgpUaGUgcmVzdWx0cyBhbHNvIHNob3cgdGhhdCB0aGVyZSBpcyBhIGxvdCBvZiB2YXJpYWJpbGl0eSBpbiB0aGUgY29hbGVzY2VudCBwcm9jZXNzLgoKCgoKIyMjIFBvcHVsYXRpb24gU3BsaXR0aW5nL01lcmdpbmcKCk15IGdvb2RuZXNzLCB0aGVyZSBhcmUgYSBsb3Qgb2Ygb3B0aW9ucyBpbiBgbXNgLiAgVG8gc2VlIHRoZSBmdWxsIHJ1bmRvd24gb24gYWxsIHRoZSBvcHRpb25zLAp5b3UgY2FuIHJlYWQgdGhlIGZ1bGwgZG9jdW1lbnRhdGlvbjogW21zZG9jLnBkZl0oaHR0cHM6Ly9lcmlxYW5kZS5naXRodWIuaW8vY29hbGVzY2VudC1oYW5kcy1vbi9tc2RvYy5wZGYpLiAgQnV0IGZvciBub3csIHdlIHdpbGwKanVzdCBkaXNjdXNzIG9uZSBtb3JlLCB1c2VkIHRvIGpvaW4gb3Igc3BsaXQgdHdvIHBvcHVsYXRpb25zIGdvaW5nIGJhY2sgaW4gdGltZS4KCiogYC1laiB0IGkgamAgd2hpY2ggbWVhbnMgbW92ZSBhbGwgbGluZWFnZXMgaW4gc3VicG9wdWxhdGlvbiAkaSQgaW50byBzdWJwb3B1bGF0aW9uICRqJCBhdCB0aW1lICR0JAppbiB1bml0cyBvZiAkNE5fMCQuICBUaGUgYGpgIG1lYW5zICJqb2luIi4gIEl0IGNvcnJlc3BvbmRzIHRvIHBvcHVsYXRpb25zICJqb2luaW5nIiB3aGlsZSBnb2luZwpiYWNrd2FyZCBpbiB0aW1lLiAgQnV0LCBfZm9yd2FyZCBpbiB0aW1lXyB0aGlzIGNvcnJlc3BvbmRzIHRvIHBvcHVsYXRpb24gX3NwbGl0dGluZ18uXAoKKiBgLWVzIHQgaSBwYCB3aGljaCBtZWFucyBzcGxpdCBzdWJwb3B1bGF0aW9uICRpJCBpbnRvIHR3byBzdWJwb3B1bGF0aW9ucyAkaSQgYW5kICRucG9wICsgMSQgJHQkCihpbiB1bml0cyBvZiAkNE5fMCQpLiBMaW5lYWdlcyBjdXJyZW50bHkgaW4gJGkkIHJlbWFpbiBpbiAkaSQgd2l0aCBwcm9iYWJpbGl0eSAkcCQgYW5kCndpdGggcHJvYmFiaWxpdHkgJDEtcCQgdGhleSBnZXQgcGxhY2VkIGludG8gc3VicG9wdWxhdGlvbiAkbnBvcCArIDEkLiBUaGUgYHNgIG1lYW5zIHNwbGl0LiAgCkl0IGNvcnJlc3BvbmRzIHRvIHBvcHVsYXRpb25zICJqb2luaW5nIiB3aGlsZSBnb2luZyBmb3J3YXJkIGluIHRpbWUuCgoqKkRpc2N1c3Mgd2l0aCB5b3VyIHBhcnRuZXIqKjogV2hhdCBhcmUgc29tZSBjb25zZXJ2YXRpb24tZ2VuZXRpYyBzY2VuYXJpb3MgdGhhdAp0aGVzZSBsYXN0IHR3byBkZW1vZ3JhcGhpYyBzY2VuYXJpb3MgbWlnaHQgY29ycmVzcG9uZCB0bz8KCkhlcmUgaXMgYW4gZXhhbXBsZSBvZiBhIHBvcHVsYXRpb24gam9pbiBnb2luZyBiYWNrIGluIHRpbWUuICBXZSBoYXZlIDEwIHNhbXBsZXMgZnJvbQplYWNoIHBvcHVsYXRpb24gd2l0aCBubyBtaWdyYXRpb24gYmV0d2VlbiB0aGVtLCBhbmQgdGhlIHBvcHVsYXRpb25zIGpvaW4gYXQgdGltZSAkMk5fMCQgaW4gdGhlIApwYXN0IChhdCB3aGljaCBwb2ludCBtb3N0IHdpbGwgaGF2ZSBjb2FsZXNjZWQgd2l0aGluIHN1YnBvcHVsYXRpb25zKToKCmBgYHtyfQpzeXN0ZW0yKGNvbW1hbmQgPSBtc19iaW5hcnkoKSwgYXJncyA9ICIyMCA2IC1UIC1JIDIgMTAgMTAgMC4wMCAtZWogMC41IDEgMiIsIHN0ZG91dCA9ICJvdXQudHJlZSIsIHN0ZGVyciA9IEZBTFNFKQpjdHJlZSA8LSByZWFkLnRyZWUoIm91dC50cmVlIikKbmFtZXMoY3RyZWUpIDwtIDE6NgpnZ3RyZWUoY3RyZWUsIGxheW91dCA9ICJyZWN0YW5ndWxhciIpICsKICBmYWNldF93cmFwKH4uaWQsIG5jb2wgID0gMykgKwogIGdlb21fdGlwbGFiKHNpemUgPSAyKQpgYGAKCiMjIFlvdXIgTWlzc2lvbi9Ib21ld29yayEKCkFsbCByaWdodCwgYWZ0ZXIgcGxheWluZyBhcm91bmQgd2l0aCBhbGwgdGhlIGFib3ZlLCBsb29rIGF0IHRoZSB0cmVlIGJlbG93IGFuZCwgd2l0aCB5b3VyCmdyb3VwOgoKMS4gdGhpbmsgYWJvdXQgYW5kIGRpc2N1c3Mgd2hhdCB0aGUgZGVtb2dyYXBoeSBtaWdodCBoYXZlIGxvb2tlZCBsaWtlIHRvIHByb2R1Y2UgdGhlIHRyZWUuClRoaW5rIGFib3V0IGhvdyBkaWZmZXJlbnQgcG9wdWxhdGlvbiBzaXplcyBtdXN0IGhhdmUgYmVlbiBhbmQgYXQgd2hpY2ggdGltZSBwZXJpb2RzIHBvcHVsYXRpb24Kc2l6ZSBjaGFuZ2VzIG1pZ2h0IGhhdmUgaGFwcGVuZWQuICAKCjIuIENoZWNrIHlvdXIgaHlwb3RoZXNlcyBieSBnZW5lcmF0aW5nIHNvbWUgdHJlZXMgd2l0aCBgbXNgLgoKCkhlcmUgaXMgYSBoaW50LiAgVG8gbWFrZSB0aGUgdHJlZXMgYmVsb3csIEkgZGlkbid0IGJvdGhlciB3aXRoIGV4cG9uZW50aWFsCmdyb3d0aCwgSSBqdXN0IHVzZWQgKHF1aXRlIHVucmVhbGlzdGljKSBpbnN0YW50YW5lb3VzIHBvcHVsYXRpb24gc2l6ZSBjaGFuZ2VzLgoKYGBge3IsIGVjaG89RkFMU0V9CiMgVHdvIHN1YnBvcHVsYXRpb25zLiAgVGhlIGZpcnN0IG9uZSBvZiBzaXplIE4wLiAgV2Ugd2FudCB0byBleHBlY3QKIyBUTVJDQSBmb3IgdGhhdCBvbmUgdG8gYmUgWCA9IDROMC4gIEZvciBzdWJwb3AgMiB3ZSB3YW50IHRvIGV4cGVjdCBvbmx5CiMgb25lIGNvYWxlc2NlbmNlIGJ5IDVYLiAgMTAgbGluZWFnZXMgaW4gZWFjaCBzdWJwb3B1bGF0aW9uLCBzbyBuKG4tMSkgaXMKIyA5MC4gIFRoYXQgbWVhbnMgc3VicG9wIDIgbXVzdCBiZSA0NTAgdGltZXMgYmlnZ2VyIHRoYW4gc3VicG9wIDEuICBBdCB0aW1lCiMgNVggd2Ugam9pbiBzdWJwb3BzIDEgYW5kIDIsIGFuZCBzZXQgdGhlIHNpemUgb2YgdGhlIG1lcmdlZCBwb3B1bGF0aW9uIHRvCiMgTjAgc28gd2UgaGF2ZSB0aGUgc2FtZSBleHBlY3RlZCB0aW1lIHRvIE1SQ0EgYXMgd2UgZGlkIHdpdGggc3VicG9wIDEgaW4gdGhlCiMgYmVnaW5uaW5nLgpzeXN0ZW0yKGNvbW1hbmQgPSBtc19iaW5hcnkoKSwgYXJncyA9ICIyMCA2IC1UIC1JIDIgMTAgMTAgMC4wMCAtZW4gMCAyIDQ1MCAtZWogMjAgMiAxIC1lbiAyMC4wMDEgMSAxICAiLCBzdGRvdXQgPSAib3V0LnRyZWUiLCBzdGRlcnIgPSBGQUxTRSkKY3RyZWUgPC0gcmVhZC50cmVlKCJvdXQudHJlZSIpCm5hbWVzKGN0cmVlKSA8LSAxOjYKZ2d0cmVlKGN0cmVlLCBsYXlvdXQgPSAicmVjdGFuZ3VsYXIiKSArCiAgZmFjZXRfd3JhcCh+LmlkLCBuY29sICA9IDMpICsKICBnZW9tX3RpcGxhYihzaXplID0gMikKYGBgCgoKCgojIyBSZWZlcmVuY2VzCgoK