Your Exercise
In this section, your expected to get familiar with confidential intervals exercise:
Exercise 1
Find a point estimate of average university student Age with the sample data from survey!
## [1] 20.37451
we calculate the point estimate of average university student Age using mean() function and probably add the na.rm = TRUE if there are missing values.
Exercise 2
Assume the population standard deviation \(\sigma\) of the student Age in data survey is 7. Find the margin of error and interval estimate at 95% confidence level.
## [1] 0.8911934
## [1] 20.37451
## [1] 19.48332 21.26571
Assuming the population standard deviation $σ$ being 7, the margin of error for the student height survey at 95% confidence level is 0.8911. The confidence interval is between 19.48332 and 21.26571.
Exercise 3
Without assuming the population standard deviation \(\sigma\) of the student Age in survey, find the margin of error and interval estimate at 95% confidence level.
## [1] 0.8957872
## [1] 20.37451
## [1] 19.47873 21.27030
Without assumption on the population standard deviation, the margin of error for the student height survey at 95% confidence level is 0.8957. The confidence interval is between 19.47 and 21.27
Exercise 4
Improve the quality of a sample survey by increasing the sample size with unknown standard deviation \(\sigma\)!.
## [1] 130.7163
Based on the assumption of population standard deviation being 9.48, it needs a sample size of 2.53 to achieve a 1.2 centimeters margin of error at 95% confidence level.
Exercise 5
Assume you don’t have planned proportion estimate, find the sample size needed to achieve 5% margin of error for the male student survey at 95% confidence level!
## [1] 1460.715
Based on the assumption of population standard deviation being 9.48, it needs a sample size of 1460.715 to achieve a 5% margin of error at 95% confidence level.
Exercise 6
Perform confidence intervals analysis on this data set from 2004 that includes data on average hourly earnings, marital status, gender, and age for thousands of people.
## 'data.frame': 7986 obs. of 4 variables:
## $ ahe : num 34.6 19.2 13.7 19.2 19.2 ...
## $ bachelor: num 1 1 0 1 1 1 1 0 0 0 ...
## $ female : num 0 1 1 1 0 1 0 0 1 0 ...
## $ age : num 30 30 30 30 25 32 33 32 30 30 ...
## Warning: package 'rcompanion' was built under R version 4.0.2
## age bachelor n Mean Conf.level Trad.lower Trad.upper
## 1 25 0 388 13 0.95 12 13
## 2 25 1 337 16 0.95 16 17
## 3 26 0 386 12 0.95 12 13
## 4 26 1 301 18 0.95 17 19
## 5 27 0 416 13 0.95 12 14
## 6 27 1 342 18 0.95 17 19
## 7 28 0 408 13 0.95 13 14
## 8 28 1 342 19 0.95 18 20
## 9 29 0 418 14 0.95 13 15
## 10 29 1 375 20 0.95 19 21
## 11 30 0 434 14 0.95 14 15
## 12 30 1 366 21 0.95 20 22
## 13 31 0 409 14 0.95 14 15
## 14 31 1 370 21 0.95 20 22
## 15 32 0 470 15 0.95 14 15
## 16 32 1 351 22 0.95 21 23
## 17 33 0 506 14 0.95 14 15
## 18 33 1 428 23 0.95 22 24
## 19 34 0 511 15 0.95 14 15
## 20 34 1 428 23 0.95 22 24
##
## One Sample t-test
##
## data: cps$age
## t = 919.71, df = 7985, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
## 29.69103 29.81786
## sample estimates:
## mean of x
## 29.75445
alternative hypothesis : true mean is not equal to 0 95% confidence interval : 29.69103 mean of x 29.75445.
Case Study
Assume you have access to data on an entire population, say the size of every house in all residential home sales in Ames, Iowa between 2006 and 2010 it’s straight forward to answer questions like,
- How big is the typical house in Ames?
- How much variation is there in sizes of houses?.
- How much is the average price of house in Ames?
- How much is the confidence interval price of house in Ames?
But, If you have access to only a sample of the population, as is often the case, the task becomes more complicated. What is your best guess for the typical size if you only know the sizes of several dozen houses? This sort of situation requires that you use your sample to make inference on what your population looks like.
Collect Data
To access the data in R, type the following code:
## chr [1:3] "ames" "plot_ci" "contains"
In this case study we’ll start with a simple random sample of size 60 from the population. Specifically, this is a simple random sample of size 60. Note that the data set has information on many housing variables, but for the first portion of the lab we’ll focus on the size of the house, represented by the variable Gr.Liv.Area.
## [1] 2200 2093 1040 2233 1523 1660 1555 1102 848 1136 2061 1122 960 1092 2610
## [16] 2217 1959 2334 1660 1576 848 2004 988 1500 874 1340 1800 1069 1456 784
## [31] 985 1928 882 1124 1639 1214 1434 1150 1544 1812 1511 1949 1077 1248 1480
## [46] 1320 1717 1367 928 2552 1953 693 2690 2276 1173 1258 2582 1558 672 1488
Visualization
As usual, before you begin to analyze more about your data. It’s important to visualize the data in advance. Here, we use a random sample of size 60 from the population.

# Make a histogram of your sample
hist(samp, main ="Distribution fo Samp",
col = "deeppink3",
xlim = c(200, 3500),
freq = F,
xlab = "Samp")
# ...and add a density curve
curve(dnorm(x,
mean=mean(samp),
sd=sd(samp)), add=T,
col="blue", lwd=2)

Your Challenge:
- Describe the distribution of your sample. What would you say is the “typical” size within your sample? Also state precisely what you interpreted “typical” to mean.
##Answer This distribution is multimodal, and not normal. It’s kind of every where. * Would you expect another student’s distribution to be identical to yours? Would you expect it to be similar? Why or why not?
Answer
I would expect the shape to me similar to mine, in that it will not be normal and it will be multimodal.
Confidence Intervals
One of the most common ways to describe the typical or central value of a distribution is to use the mean. In this case we can calculate the mean of the sample using,
## [1] 1514.133
Return for a moment to the question that first motivated this lab: based on this sample, what can we infer about the population? Based only on this single sample, the best estimate of the average living area of houses sold in Ames would be the sample mean, usually denoted as \(\bar{x}\) (here we’re calling it sample_mean). That serves as a good point estimate but it would be useful to also communicate how uncertain we are of that estimate. This can be captured by using a confidence interval.
We can calculate a 95% confidence interval for a sample mean by adding and subtracting 1.96 standard errors to the point estimate (I assume that you have been familiar with this formula).
## [1] 1381.351 1646.915
This is an important inference that we’ve just made: even though we don’t know what the full population looks like, we’re 95% confident that the true average size of houses in Ames lies between the values lower and upper. There are a few conditions that must be met for this interval to be valid.
Your Challenge:
- For the confidence interval to be valid, the sample mean must be normally distributed and have standard error $ s/$. What conditions must be met for this to be true?
Answer
The sample has to be random and independent. It must be a simple random sample with less than 10% of the population. * What does “95% confidence” mean?
Answer
The 95% confidence interval is a range of values that can be 95% certain contains the true mean of the population. As the sample size increases, the range of interval values will narrow, meaning that know mean with much more accuracy compared with a smaller sample. 95% confidence describes the level of confidence we have that the parameter lies in the confidence interval.
- Does your confidence interval capture the true average size of houses in
Ames? If you are working on this case study, does your classmate’s interval capture this value?
Answer
Yes, my confidence interval does capture the actual mean.
Simulation
let’s simulate a scenario of confidence interval in classroom to capture the true average size of houses in Ames. Suppose we have 100 students in the classroom.
## [1] 97
Using R, we’re going to recreate many samples to learn more about how sample means and confidence intervals vary from one sample to another. Loops come in handy here (If you are unfamiliar with loops, review the Sampling Distribution Lab).
Here is the rough outline:
- Obtain a random sample.
- Calculate and store the sample’s mean and standard deviation.
- Repeat steps (1) and (2) 50 times.
- Use these stored statistics to calculate many confidence intervals.
But before we do all of this, we need to first create empty vectors where we can save the means and standard deviations that will be calculated from each sample. And while we’re at it, let’s also store the desired sample size as \(n\).
## [1] 60
Now we’re ready for the loop where we calculate the means and standard deviations of 50 random samples.
## [1] 2206 3672 2270 1786 1041 2614 1655 1378 1250 1884 1358 764 1176 1595 1419
## [16] 1620 1299 1097 1073 1647 1220 1086 1928 1412 1091 2263 1968 1261 1538 793
## [31] 1337 1768 1604 1609 1479 980 480 816 951 1069 1709 1742 2237 1458 864
## [46] 1665 1778 1949 1040 1414 954 1142 1614 1368 5642 1383 1242 816 2082 1728
Lastly, we construct the confidence intervals.
Lower bounds of these 50 confidence intervals are stored in lower_vector, and the upper bounds are in upper_vector. Let’s view the first interval.
## [1] 1400.415 1718.352

## [1] -1.959964
## [1] 1.959964
Your Challenge:
- What proportion of your confidence intervals include the true population mean? Is this proportion exactly equal to the confidence level? If not, explain why.
Answer
96% of my confidence intervals include the true population mean. It is not exactly equal. We only
tooK 50 samples of size 60. This could be where our discrepancy comes from.
- Pick a confidence level of your choosing, provided it is 99%. What is the appropriate critical value?
Answer
## [1] 0.995
We will use the table to complete the rest by looking up the z score that correlates to .995
- Calculate 50 confidence intervals at the confidence level you chose in the previous question. You do not need to obtain new samples, simply calculate new intervals based on the sample means and standard deviations you have already collected. Using the plot_ci function, plot all intervals and calculate the proportion of intervals that include the true population mean. How does this percentage compare to the confidence level selected for the intervals?
Answer
## [1] 1350.94 1762.15
Visually, I can see that 100% of intervals include the true population mean. It is very close to the confidence level selected.
LS0tDQp0aXRsZTogIkNvbmZpZGVuY2UgSW50ZXJ2YWxzIg0KYXV0aG9yOiAiV2lkaSB5YW50aWgiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgaGlnaGxpZ2h0OiBweWdtZW50cw0KICAgIHRoZW1lOiBzcGFjZWxhYg0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KLS0tDQoNCmBgYHtyIExvZ28sIGVjaG89RkFMU0UsZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnNDAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL2dpdGh1Yi5jb20vQmFrdGktU2lyZWdhci9pbWFnZXMvYmxvYi9tYXN0ZXIvbG9nby5wbmc/cmF3PXRydWUiKQ0KYGBgDQoNCiMgQnJpZWYgSW50cm9kdWN0aW9uIA0KDQpQbGVhc2Ugd2F0Y2hpbmcgdGhpcyB2aWRlbywgdG8gZ2V0IHNvbWUgaWRlYXMgYWJvdXQgQ29uZmlkZW5jZSBJbnRlcnZhbHMgKENJKQ0KDQo8Y2VudGVyPg0KPGlmcmFtZSB3aWR0aD0iODAwIiBoZWlnaHQ9IjQ1MCIgc3JjPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC9NYlhUaGJUU3JWSSIgZnJhbWVib3JkZXI9IjAiIGFsbG93PSJhY2NlbGVyb21ldGVyOyBhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhOyBneXJvc2NvcGU7IHBpY3R1cmUtaW4tcGljdHVyZSIgYWxsb3dmdWxsc2NyZWVuPjwvaWZyYW1lPg0KPC9jZW50ZXI+DQoNCg0KIyBDSSBpbiBCdXNpbmVzcyANCg0KVGhpcyB2aWRlbyBndWlkZSB5b3UsIGhvdyBjYW4geW91IGFwcGx5IENvbmZpZGVuY2UgSW50ZXJ2YWxzIGluIEJ1c2luZXNzLg0KDQo8Y2VudGVyPg0KPGlmcmFtZSB3aWR0aD0iODAwIiBoZWlnaHQ9IjQ1MCIgc3JjPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC9fSkdBTGV0TWNqbyIgZnJhbWVib3JkZXI9IjAiIGFsbG93PSJhY2NlbGVyb21ldGVyOyBhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhOyBneXJvc2NvcGU7IHBpY3R1cmUtaW4tcGljdHVyZSIgYWxsb3dmdWxsc2NyZWVuPjwvaWZyYW1lPg0KPC9jZW50ZXI+DQoNCg0KIyBZb3VyIEV4ZXJjaXNlIA0KDQpJbiB0aGlzIHNlY3Rpb24sIHlvdXIgZXhwZWN0ZWQgdG8gZ2V0IGZhbWlsaWFyIHdpdGggY29uZmlkZW50aWFsIGludGVydmFscyBleGVyY2lzZTogDQoNCiMjIEV4ZXJjaXNlIDENCg0KRmluZCBhIHBvaW50IGVzdGltYXRlIG9mIGF2ZXJhZ2UgdW5pdmVyc2l0eSBzdHVkZW50IGBBZ2VgIHdpdGggdGhlIHNhbXBsZSBkYXRhIGZyb20gYHN1cnZleWAhDQoNCmBgYHtyfQ0KbGlicmFyeShNQVNTKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpBZ2Uuc3VydmV5ID0gc3VydmV5JEFnZSAgICAgICAgICAgICAgICAgDQptZWFuKEFnZS5zdXJ2ZXksIG5hLnJtPVRSVUUpICAgDQpgYGANCg0KYHdlIGNhbGN1bGF0ZSB0aGUgcG9pbnQgZXN0aW1hdGUgb2YgYXZlcmFnZSB1bml2ZXJzaXR5IHN0dWRlbnQgQWdlIHVzaW5nIG1lYW4oKSBmdW5jdGlvbiBhbmQgcHJvYmFibHkgYWRkIHRoZSBuYS5ybSA9IFRSVUUgaWYgdGhlcmUgYXJlIG1pc3NpbmcgdmFsdWVzLmANCg0KIyMgRXhlcmNpc2UgMg0KDQpBc3N1bWUgdGhlIHBvcHVsYXRpb24gc3RhbmRhcmQgZGV2aWF0aW9uICRcc2lnbWEkIG9mIHRoZSBzdHVkZW50IGBBZ2VgIGluIGRhdGEgYHN1cnZleWAgaXMgNy4gRmluZCB0aGUgbWFyZ2luIG9mIGVycm9yIGFuZCBpbnRlcnZhbCBlc3RpbWF0ZSBhdCA5NSUgY29uZmlkZW5jZSBsZXZlbC4NCg0KYGBge3J9DQpsaWJyYXJ5KE1BU1MpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCkFnZS5yZXNwb25zZSA9IG5hLm9taXQoc3VydmV5JEFnZSkgICAgICAgICAgICAgDQpuID0gbGVuZ3RoKEFnZS5yZXNwb25zZSkgICAgICAgICAgICAgICAgICAgICAgICAgICANCnNpZ21hID0gNyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpzZW0gPSBzaWdtYS9zcXJ0KG4pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCkUgPSBxbm9ybSguOTc1KSpzZW0gO0UgICAgDQoNCnhiYXIgPSBtZWFuKEFnZS5yZXNwb25zZSk7IHhiYXIgDQp4YmFyICsgYygtRSwgRSkNCmBgYA0KDQpgQXNzdW1pbmcgdGhlIHBvcHVsYXRpb24gc3RhbmRhcmQgZGV2aWF0aW9uICTPgyQgYmVpbmcgNywgdGhlIG1hcmdpbiBvZiBlcnJvciBmb3IgdGhlIHN0dWRlbnQgaGVpZ2h0IHN1cnZleSBhdCA5NSUgY29uZmlkZW5jZSBsZXZlbCBpcyAwLjg5MTEuIFRoZSBjb25maWRlbmNlIGludGVydmFsIGlzIGJldHdlZW4gMTkuNDgzMzIgYW5kIDIxLjI2NTcxLmANCg0KIyMgRXhlcmNpc2UgMw0KDQpXaXRob3V0IGFzc3VtaW5nIHRoZSBwb3B1bGF0aW9uIHN0YW5kYXJkIGRldmlhdGlvbiAkXHNpZ21hJCBvZiB0aGUgc3R1ZGVudCBgQWdlYCBpbiBzdXJ2ZXksIGZpbmQgdGhlIG1hcmdpbiBvZiBlcnJvciBhbmQgaW50ZXJ2YWwgZXN0aW1hdGUgYXQgOTUlIGNvbmZpZGVuY2UgbGV2ZWwuDQoNCmBgYHtyfQ0KbGlicmFyeShNQVNTKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCkFnZS5yZXNwb25zZSA9IG5hLm9taXQoc3VydmV5JEFnZSkgICAgICAgDQpuID0gbGVuZ3RoKEFnZS5yZXNwb25zZSkgICAgICAgICAgICAgICAgICAgIA0KcyA9IDcNClNFID0gcy9zcXJ0KG4pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCkUgPSBxdCguOTc1LCBkZj1uLTEpKlNFOyBFICAgIA0KeGJhciA9IG1lYW4oQWdlLnJlc3BvbnNlKTsgeGJhcg0KeGJhciArIGMoLUUsIEUpICANCmBgYA0KDQpgV2l0aG91dCBhc3N1bXB0aW9uIG9uIHRoZSBwb3B1bGF0aW9uIHN0YW5kYXJkIGRldmlhdGlvbiwgdGhlIG1hcmdpbiBvZiBlcnJvciBmb3IgdGhlIHN0dWRlbnQgaGVpZ2h0IHN1cnZleSBhdCA5NSUgY29uZmlkZW5jZSBsZXZlbCBpcyAwLjg5NTcuIFRoZSBjb25maWRlbmNlIGludGVydmFsIGlzIGJldHdlZW4gMTkuNDcgYW5kIDIxLjI3IGANCg0KIyMgRXhlcmNpc2UgNA0KDQpJbXByb3ZlIHRoZSBxdWFsaXR5IG9mIGEgc2FtcGxlIGBzdXJ2ZXlgIGJ5IGluY3JlYXNpbmcgdGhlIHNhbXBsZSBzaXplIHdpdGggdW5rbm93biBzdGFuZGFyZCBkZXZpYXRpb24gJFxzaWdtYSQhLg0KDQpgYGB7cn0NCnpzdGFyID0gcW5vcm0oLjk3NSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpFID0gMS4yICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQp6c3Rhcl4yKnNpZ21hXjIvIEVeMiAgICANCmBgYA0KYEJhc2VkIG9uIHRoZSBhc3N1bXB0aW9uIG9mIHBvcHVsYXRpb24gc3RhbmRhcmQgZGV2aWF0aW9uIGJlaW5nIDkuNDgsIGl0IG5lZWRzIGEgc2FtcGxlIHNpemUgb2YgMi41MyB0byBhY2hpZXZlIGEgMS4yIGNlbnRpbWV0ZXJzIG1hcmdpbiBvZiBlcnJvciBhdCA5NSUgY29uZmlkZW5jZSBsZXZlbC5gDQoNCiMjIEV4ZXJjaXNlIDUNCg0KQXNzdW1lIHlvdSBkb27igJl0IGhhdmUgcGxhbm5lZCBwcm9wb3J0aW9uIGVzdGltYXRlLCBmaW5kIHRoZSBzYW1wbGUgc2l6ZSBuZWVkZWQgdG8gYWNoaWV2ZSA1JSBtYXJnaW4gb2YgZXJyb3IgZm9yIHRoZSBtYWxlIHN0dWRlbnQgYHN1cnZleWAgYXQgOTUlIGNvbmZpZGVuY2UgbGV2ZWwhDQoNCmBgYHtyfQ0KenN0YXIgPSBxbm9ybSguOTc1KSANCnNpZ21hID0gLjk3NSANCkUgPSAwLjA1IA0KenN0YXJeMiDiiJcgc2lnbWFeMi8gRV4yDQpgYGANCg0KYEJhc2VkIG9uIHRoZSBhc3N1bXB0aW9uIG9mIHBvcHVsYXRpb24gc3RhbmRhcmQgZGV2aWF0aW9uIGJlaW5nIDkuNDgsIGl0IG5lZWRzIGEgc2FtcGxlIHNpemUgb2YgMTQ2MC43MTUgdG8gYWNoaWV2ZSBhIDUlIG1hcmdpbiBvZiBlcnJvciBhdCA5NSUgY29uZmlkZW5jZSBsZXZlbC5gDQoNCiMjIEV4ZXJjaXNlIDYNCg0KUGVyZm9ybSBjb25maWRlbmNlIGludGVydmFscyBhbmFseXNpcyBvbiB0aGlzIFtkYXRhIHNldF0oaHR0cDovL211cnJheWxheC5vcmcvZGF0YXNldHMvY3BzMDQuY3N2KSBmcm9tIDIwMDQgdGhhdCBpbmNsdWRlcyBkYXRhIG9uIGF2ZXJhZ2UgaG91cmx5IGVhcm5pbmdzLCBtYXJpdGFsIHN0YXR1cywgZ2VuZGVyLCBhbmQgYWdlIGZvciB0aG91c2FuZHMgb2YgcGVvcGxlLg0KDQpgYGB7cn0NCmNwcyA9IHJlYWQuY3N2KCdjcHMwNC5jc3YnLGhlYWRlcj1UUlVFKQ0Kc3RyKGNwcykNCmxpYnJhcnkocmNvbXBhbmlvbikNCg0KZ3JvdXB3aXNlTWVhbihhaGUgfiBhZ2UgKyBiYWNoZWxvciwNCiAgICAgICAgICAgICAgZGF0YSAgID0gY3BzLA0KICAgICAgICAgICAgICBjb25mICAgPSAwLjk1LA0KICAgICAgICAgICAgICBkaWdpdHMgPSAyKQ0KdC50ZXN0KGNwcyRhZ2UsDQogICAgICAgY29uZi5sZXZlbD0wLjk1KQ0KYGBgDQoNCmBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIDogdHJ1ZSBtZWFuIGlzIG5vdCBlcXVhbCB0byAwIDk1JSBjb25maWRlbmNlIGludGVydmFsIDogMjkuNjkxMDMgbWVhbiBvZiB4IDI5Ljc1NDQ1LmANCg0KDQojIENhc2UgU3R1ZHkgDQoNCkFzc3VtZSB5b3UgaGF2ZSBhY2Nlc3MgdG8gZGF0YSBvbiBhbiBlbnRpcmUgcG9wdWxhdGlvbiwgc2F5IHRoZSBzaXplIG9mIGV2ZXJ5IGhvdXNlIGluIFthbGwgcmVzaWRlbnRpYWwgaG9tZSBzYWxlcyBpbiBBbWVzLCBJb3dhIGJldHdlZW4gMjAwNiBhbmQgMjAxMF0oaHR0cHM6Ly93d3cub3BlbmludHJvLm9yZy9ib29rL3N0YXRkYXRhLz9kYXRhPWFtZXMpIGl04oCZcyBzdHJhaWdodCBmb3J3YXJkIHRvIGFuc3dlciBxdWVzdGlvbnMgbGlrZSwgDQoNCiogSG93IGJpZyBpcyB0aGUgdHlwaWNhbCBob3VzZSBpbiBBbWVzPyANCiogSG93IG11Y2ggdmFyaWF0aW9uIGlzIHRoZXJlIGluIHNpemVzIG9mIGhvdXNlcz8uIA0KKiBIb3cgbXVjaCBpcyB0aGUgYXZlcmFnZSBwcmljZSBvZiBob3VzZSBpbiBBbWVzPw0KKiBIb3cgbXVjaCBpcyB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBwcmljZSBvZiBob3VzZSBpbiBBbWVzPw0KDQpCdXQsIElmIHlvdSBoYXZlIGFjY2VzcyB0byBvbmx5IGEgc2FtcGxlIG9mIHRoZSBwb3B1bGF0aW9uLCBhcyBpcyBvZnRlbiB0aGUgY2FzZSwgdGhlIHRhc2sgYmVjb21lcyBtb3JlIGNvbXBsaWNhdGVkLiBXaGF0IGlzIHlvdXIgYmVzdCBndWVzcyBmb3IgdGhlIHR5cGljYWwgc2l6ZSBpZiB5b3Ugb25seSBrbm93IHRoZSBzaXplcyBvZiBzZXZlcmFsIGRvemVuIGhvdXNlcz8gVGhpcyBzb3J0IG9mIHNpdHVhdGlvbiByZXF1aXJlcyB0aGF0IHlvdSB1c2UgeW91ciBzYW1wbGUgdG8gbWFrZSBpbmZlcmVuY2Ugb24gd2hhdCB5b3VyIHBvcHVsYXRpb24gbG9va3MgbGlrZS4NCg0KYGBge3J9DQpkYXRhMjwtIGxvYWQodXJsKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vR2FyY2lhUmlvcy9nb3Z0XzM5OTAvZ2gtcGFnZXMvTGFicy9sYWI0L2RhdGEvYW1lcy5SRGF0YSIpKQ0KDQpgYGANCg0KDQojIyBDb2xsZWN0IERhdGENCg0KVG8gYWNjZXNzIHRoZSBkYXRhIGluIFIsIHR5cGUgdGhlIGZvbGxvd2luZyBjb2RlOg0KDQpgYGB7cn0NCmRhdGEyIDwtIGxvYWQodXJsKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vR2FyY2lhUmlvcy9nb3Z0XzM5OTAvZ2gtcGFnZXMvTGFicy9sYWI0L2RhdGEvYW1lcy5SRGF0YSIpKQ0Kc3RyKGRhdGEyKQ0KDQoNCmBgYA0KDQpJbiB0aGlzIGNhc2Ugc3R1ZHkgd2XigJlsbCBzdGFydCB3aXRoIGEgc2ltcGxlIHJhbmRvbSBzYW1wbGUgb2Ygc2l6ZSA2MCBmcm9tIHRoZSBwb3B1bGF0aW9uLiBTcGVjaWZpY2FsbHksIHRoaXMgaXMgYSBzaW1wbGUgcmFuZG9tIHNhbXBsZSBvZiBzaXplIDYwLiBOb3RlIHRoYXQgdGhlIGRhdGEgc2V0IGhhcyBpbmZvcm1hdGlvbiBvbiBtYW55IGhvdXNpbmcgdmFyaWFibGVzLCBidXQgZm9yIHRoZSBmaXJzdCBwb3J0aW9uIG9mIHRoZSBsYWIgd2XigJlsbCBmb2N1cyBvbiB0aGUgc2l6ZSBvZiB0aGUgaG91c2UsIHJlcHJlc2VudGVkIGJ5IHRoZSB2YXJpYWJsZSBgR3IuTGl2LkFyZWFgLg0KDQpgYGB7cn0NCiNyYW5kb21seSBzZXQgc2VlZCB0byBmaXggb3V0cHV0cyBpbiB0aGlzIGFzc2lnbm1lbnQNCnNldC5zZWVkKDApDQpwb3B1bGF0aW9uIDwtIGFtZXMkR3IuTGl2LkFyZWENCnNhbXAgPC0gc2FtcGxlKHBvcHVsYXRpb24sIDYwKQ0Kc2FtcA0KYGBgDQoNCg0KIyMgVmlzdWFsaXphdGlvbg0KDQpBcyB1c3VhbCwgYmVmb3JlIHlvdSBiZWdpbiB0byBhbmFseXplIG1vcmUgYWJvdXQgeW91ciBkYXRhLiBJdCdzIGltcG9ydGFudCB0byB2aXN1YWxpemUgdGhlIGRhdGEgaW4gYWR2YW5jZS4gSGVyZSwgd2UgdXNlIGEgcmFuZG9tIHNhbXBsZSBvZiBzaXplIDYwIGZyb20gdGhlIHBvcHVsYXRpb24uDQoNCmBgYHtyfQ0KIyBIaXN0b2dyYW0NCmxpYnJhcnkobW9tZW50cykNCmhpc3Qoc2FtcCwgYnJlYWtzID0gMjAsIGNvbCA9ICdwaW5rJykNCmBgYA0KDQpgYGB7cn0NCiMgTWFrZSBhIGhpc3RvZ3JhbSBvZiB5b3VyIHNhbXBsZQ0KaGlzdChzYW1wLCBtYWluID0iRGlzdHJpYnV0aW9uIGZvIFNhbXAiLCANCiAgICAgY29sID0gImRlZXBwaW5rMyIsIA0KICAgICB4bGltID0gYygyMDAsIDM1MDApLCANCiAgICAgZnJlcSA9IEYsDQogICAgIHhsYWIgPSAiU2FtcCIpDQojIC4uLmFuZCBhZGQgYSBkZW5zaXR5IGN1cnZlDQpjdXJ2ZShkbm9ybSh4LCANCiAgICAgICAgICAgIG1lYW49bWVhbihzYW1wKSwgDQogICAgICAgICAgICBzZD1zZChzYW1wKSksIGFkZD1ULCANCiAgICAgICAgICAgIGNvbD0iYmx1ZSIsIGx3ZD0yKQ0KYGBgDQoNCioqWW91ciBDaGFsbGVuZ2U6KiogDQoNCiogRGVzY3JpYmUgdGhlIGRpc3RyaWJ1dGlvbiBvZiB5b3VyIHNhbXBsZS4gV2hhdCB3b3VsZCB5b3Ugc2F5IGlzIHRoZSDigJx0eXBpY2Fs4oCdIHNpemUgd2l0aGluIHlvdXIgc2FtcGxlPyBBbHNvIHN0YXRlIHByZWNpc2VseSB3aGF0IHlvdSBpbnRlcnByZXRlZCDigJx0eXBpY2Fs4oCdIHRvIG1lYW4uDQoNCiMjQW5zd2VyDQpUaGlzIGRpc3RyaWJ1dGlvbiBpcyBtdWx0aW1vZGFsLCBhbmQgbm90IG5vcm1hbC4gSXTigJlzIGtpbmQgb2YgZXZlcnkgd2hlcmUuDQoqIFdvdWxkIHlvdSBleHBlY3QgYW5vdGhlciBzdHVkZW504oCZcyBkaXN0cmlidXRpb24gdG8gYmUgaWRlbnRpY2FsIHRvIHlvdXJzPyBXb3VsZCB5b3UgZXhwZWN0IGl0IHRvIGJlIHNpbWlsYXI/IFdoeSBvciB3aHkgbm90Pw0KDQojIyBBbnN3ZXINCkkgd291bGQgZXhwZWN0IHRoZSBzaGFwZSB0byBtZSBzaW1pbGFyIHRvIG1pbmUsIGluIHRoYXQgaXQgd2lsbCBub3QgYmUgbm9ybWFsIGFuZCBpdCB3aWxsIGJlIG11bHRpbW9kYWwuDQoNCiMjIENvbmZpZGVuY2UgSW50ZXJ2YWxzDQoNCk9uZSBvZiB0aGUgbW9zdCBjb21tb24gd2F5cyB0byBkZXNjcmliZSB0aGUgdHlwaWNhbCBvciBjZW50cmFsIHZhbHVlIG9mIGEgZGlzdHJpYnV0aW9uIGlzIHRvIHVzZSB0aGUgbWVhbi4gSW4gdGhpcyBjYXNlIHdlIGNhbiBjYWxjdWxhdGUgdGhlIG1lYW4gb2YgdGhlIHNhbXBsZSB1c2luZywNCg0KYGBge3J9DQpzYW1wbGVfbWVhbiA8LSBtZWFuKHNhbXApDQpzYW1wbGVfbWVhbg0KYGBgDQpSZXR1cm4gZm9yIGEgbW9tZW50IHRvIHRoZSBxdWVzdGlvbiB0aGF0IGZpcnN0IG1vdGl2YXRlZCB0aGlzIGxhYjogYmFzZWQgb24gdGhpcyBzYW1wbGUsIHdoYXQgY2FuIHdlIGluZmVyIGFib3V0IHRoZSBwb3B1bGF0aW9uPyBCYXNlZCBvbmx5IG9uIHRoaXMgc2luZ2xlIHNhbXBsZSwgdGhlIGJlc3QgZXN0aW1hdGUgb2YgdGhlIGF2ZXJhZ2UgbGl2aW5nIGFyZWEgb2YgaG91c2VzIHNvbGQgaW4gQW1lcyB3b3VsZCBiZSB0aGUgc2FtcGxlIG1lYW4sIHVzdWFsbHkgZGVub3RlZCBhcyAkXGJhcnt4fSQgKGhlcmUgd2XigJlyZSBjYWxsaW5nIGl0IGBzYW1wbGVfbWVhbmApLiBUaGF0IHNlcnZlcyBhcyBhIGdvb2QgcG9pbnQgZXN0aW1hdGUgYnV0IGl0IHdvdWxkIGJlIHVzZWZ1bCB0byBhbHNvIGNvbW11bmljYXRlIGhvdyB1bmNlcnRhaW4gd2UgYXJlIG9mIHRoYXQgZXN0aW1hdGUuIFRoaXMgY2FuIGJlIGNhcHR1cmVkIGJ5IHVzaW5nIGEgY29uZmlkZW5jZSBpbnRlcnZhbC4NCg0KV2UgY2FuIGNhbGN1bGF0ZSBhIDk1JSBjb25maWRlbmNlIGludGVydmFsIGZvciBhIHNhbXBsZSBtZWFuIGJ5IGFkZGluZyBhbmQgc3VidHJhY3RpbmcgMS45NiBzdGFuZGFyZCBlcnJvcnMgdG8gdGhlIHBvaW50IGVzdGltYXRlIChJIGFzc3VtZSB0aGF0IHlvdSBoYXZlIGJlZW4gZmFtaWxpYXIgd2l0aCB0aGlzIGZvcm11bGEpLg0KDQpgYGB7cn0NCnNlIDwtIHNkKHNhbXApIC8gc3FydCg2MCkNCmxvd2VyIDwtIHNhbXBsZV9tZWFuIC0gMS45NiAqIHNlDQp1cHBlciA8LSBzYW1wbGVfbWVhbiArIDEuOTYgKiBzZQ0KYyhsb3dlciwgdXBwZXIpDQpgYGANClRoaXMgaXMgYW4gaW1wb3J0YW50IGluZmVyZW5jZSB0aGF0IHdl4oCZdmUganVzdCBtYWRlOiBldmVuIHRob3VnaCB3ZSBkb27igJl0IGtub3cgd2hhdCB0aGUgZnVsbCBwb3B1bGF0aW9uIGxvb2tzIGxpa2UsIHdl4oCZcmUgOTUlIGNvbmZpZGVudCB0aGF0IHRoZSB0cnVlIGF2ZXJhZ2Ugc2l6ZSBvZiBob3VzZXMgaW4gYEFtZXNgIGxpZXMgYmV0d2VlbiB0aGUgdmFsdWVzIGxvd2VyIGFuZCB1cHBlci4gVGhlcmUgYXJlIGEgZmV3IGNvbmRpdGlvbnMgdGhhdCBtdXN0IGJlIG1ldCBmb3IgdGhpcyBpbnRlcnZhbCB0byBiZSB2YWxpZC4NCg0KKipZb3VyIENoYWxsZW5nZToqKiANCg0KKiBGb3IgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgdG8gYmUgdmFsaWQsIHRoZSBzYW1wbGUgbWVhbiBtdXN0IGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGFuZCBoYXZlIHN0YW5kYXJkIGVycm9yICQgcy9cc3FydHtufSQuIFdoYXQgY29uZGl0aW9ucyBtdXN0IGJlIG1ldCBmb3IgdGhpcyB0byBiZSB0cnVlPw0KDQojIyBBbnN3ZXINClRoZSBzYW1wbGUgaGFzIHRvIGJlIHJhbmRvbSBhbmQgaW5kZXBlbmRlbnQuIEl0IG11c3QgYmUgYSBzaW1wbGUgcmFuZG9tIHNhbXBsZSB3aXRoIGxlc3MgdGhhbiAxMCUgb2YgdGhlIHBvcHVsYXRpb24uDQoqIFdoYXQgZG9lcyDigJw5NSUgY29uZmlkZW5jZeKAnSBtZWFuPw0KDQojIyBBbnN3ZXIgDQpUaGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgaXMgYSByYW5nZSBvZiB2YWx1ZXMgdGhhdCBjYW4gYmUgOTUlIGNlcnRhaW4gY29udGFpbnMgdGhlIHRydWUgbWVhbiBvZiB0aGUgcG9wdWxhdGlvbi4gQXMgdGhlIHNhbXBsZSBzaXplIGluY3JlYXNlcywgdGhlIHJhbmdlIG9mIGludGVydmFsIHZhbHVlcyB3aWxsIG5hcnJvdywgbWVhbmluZyB0aGF0IGtub3cgbWVhbiB3aXRoIG11Y2ggbW9yZSBhY2N1cmFjeSBjb21wYXJlZCB3aXRoIGEgc21hbGxlciBzYW1wbGUuDQo5NSUgY29uZmlkZW5jZSBkZXNjcmliZXMgdGhlIGxldmVsIG9mIGNvbmZpZGVuY2Ugd2UgaGF2ZSB0aGF0IHRoZSBwYXJhbWV0ZXIgbGllcyBpbiB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbC4NCg0KKiBEb2VzIHlvdXIgY29uZmlkZW5jZSBpbnRlcnZhbCBjYXB0dXJlIHRoZSB0cnVlIGF2ZXJhZ2Ugc2l6ZSBvZiBob3VzZXMgaW4gYEFtZXNgPyBJZiB5b3UgYXJlIHdvcmtpbmcgb24gdGhpcyBjYXNlIHN0dWR5LCBkb2VzIHlvdXIgY2xhc3NtYXRl4oCZcyBpbnRlcnZhbCBjYXB0dXJlIHRoaXMgdmFsdWU/DQoNCiMjIEFuc3dlciANClllcywgbXkgY29uZmlkZW5jZSBpbnRlcnZhbCBkb2VzIGNhcHR1cmUgdGhlIGFjdHVhbCBtZWFuLg0KDQoNCiMjIFNpbXVsYXRpb24gDQoNCmxldOKAmXMgc2ltdWxhdGUgYSBzY2VuYXJpbyBvZiBjb25maWRlbmNlIGludGVydmFsIGluIGNsYXNzcm9vbSB0byBjYXB0dXJlIHRoZSB0cnVlIGF2ZXJhZ2Ugc2l6ZSBvZiBob3VzZXMgaW4gYEFtZXNgLiBTdXBwb3NlIHdlIGhhdmUgMTAwIHN0dWRlbnRzIGluIHRoZSBjbGFzc3Jvb20uIA0KDQpgYGB7cn0NCmNvdW50ID0gMA0KZm9yIChpIGluIDE6MTAwKSB7DQogIHNhbXAgPC0gc2FtcGxlKHBvcHVsYXRpb24sNjApDQogIHNhbXBfbWVhbjwtIG1lYW4oc2FtcCkNCiAgc2UgPC0gc2Qoc2FtcCkvc3FydCg2MCkNCiAgbG93ZXIgPC0gc2FtcF9tZWFuLTEuOTYqc2UNCiAgdXBwZXIgPC0gc2FtcF9tZWFuKzEuOTYqc2UNCiAgaWYgKChsb3dlciA8PSAxNDk5LjY5KSAmICh1cHBlciA+PSAxNDk5LjY5KSkgew0KICAgIGNvdW50ID0gY291bnQrMQ0KICB9ICANCn0NCmNvdW50DQpgYGANClVzaW5nIFIsIHdl4oCZcmUgZ29pbmcgdG8gcmVjcmVhdGUgbWFueSBzYW1wbGVzIHRvIGxlYXJuIG1vcmUgYWJvdXQgaG93IHNhbXBsZSBtZWFucyBhbmQgY29uZmlkZW5jZSBpbnRlcnZhbHMgdmFyeSBmcm9tIG9uZSBzYW1wbGUgdG8gYW5vdGhlci4gTG9vcHMgY29tZSBpbiBoYW5keSBoZXJlIChJZiB5b3UgYXJlIHVuZmFtaWxpYXIgd2l0aCBsb29wcywgcmV2aWV3IHRoZSBTYW1wbGluZyBEaXN0cmlidXRpb24gTGFiKS4NCg0KSGVyZSBpcyB0aGUgcm91Z2ggb3V0bGluZToNCg0KKiBPYnRhaW4gYSByYW5kb20gc2FtcGxlLg0KKiBDYWxjdWxhdGUgYW5kIHN0b3JlIHRoZSBzYW1wbGXigJlzIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbi4NCiogUmVwZWF0IHN0ZXBzICgxKSBhbmQgKDIpIDUwIHRpbWVzLg0KKiBVc2UgdGhlc2Ugc3RvcmVkIHN0YXRpc3RpY3MgdG8gY2FsY3VsYXRlIG1hbnkgY29uZmlkZW5jZSBpbnRlcnZhbHMuDQoNCkJ1dCBiZWZvcmUgd2UgZG8gYWxsIG9mIHRoaXMsIHdlIG5lZWQgdG8gZmlyc3QgY3JlYXRlIGVtcHR5IHZlY3RvcnMgd2hlcmUgd2UgY2FuIHNhdmUgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIHRoYXQgd2lsbCBiZSBjYWxjdWxhdGVkIGZyb20gZWFjaCBzYW1wbGUuIEFuZCB3aGlsZSB3ZeKAmXJlIGF0IGl0LCBsZXTigJlzIGFsc28gc3RvcmUgdGhlIGRlc2lyZWQgc2FtcGxlIHNpemUgYXMgJG4kLg0KDQoNCmBgYHtyfQ0Kc2FtcF9tZWFuIDwtIHJlcChOQSwgNTApDQpzYW1wX3NkIDwtIHJlcChOQSwgNTApDQpuIDwtIDYwDQpuDQpgYGANCg0KTm93IHdl4oCZcmUgcmVhZHkgZm9yIHRoZSBsb29wIHdoZXJlIHdlIGNhbGN1bGF0ZSB0aGUgbWVhbnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbnMgb2YgNTAgcmFuZG9tIHNhbXBsZXMuDQoNCmBgYHtyfQ0KZm9yKGkgaW4gMTo1MCl7DQogIHNhbXAgPC0gc2FtcGxlKHBvcHVsYXRpb24sIG4pICMgb2J0YWluIGEgc2FtcGxlIG9mIHNpemUgbiA9IDYwIGZyb20gdGhlIHBvcHVsYXRpb24NCiAgc2FtcF9tZWFuW2ldIDwtIG1lYW4oc2FtcCkgICAgIyBzYXZlIHNhbXBsZSBtZWFuIGluIGl0aCBlbGVtZW50IG9mIHNhbXBfbWVhbg0KICBzYW1wX3NkW2ldIDwtIHNkKHNhbXApICAgICAgICAjIHNhdmUgc2FtcGxlIHNkIGluIGl0aCBlbGVtZW50IG9mIHNhbXBfc2QNCn0NCnNhbXANCmBgYA0KDQpMYXN0bHksIHdlIGNvbnN0cnVjdCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMuDQoNCmBgYHtyfQ0KbG93ZXJfdmVjdG9yIDwtIHNhbXBfbWVhbiAtIDEuOTYgKiBzYW1wX3NkIC8gc3FydChuKSANCnVwcGVyX3ZlY3RvciA8LSBzYW1wX21lYW4gKyAxLjk2ICogc2FtcF9zZCAvIHNxcnQobikNCmBgYA0KDQoNCkxvd2VyIGJvdW5kcyBvZiB0aGVzZSA1MCBjb25maWRlbmNlIGludGVydmFscyBhcmUgc3RvcmVkIGluIGBsb3dlcl92ZWN0b3JgLCBhbmQgdGhlIHVwcGVyIGJvdW5kcyBhcmUgaW4gYHVwcGVyX3ZlY3RvcmAuIExldOKAmXMgdmlldyB0aGUgZmlyc3QgaW50ZXJ2YWwuDQoNCmBgYHtyfQ0KYyhsb3dlcl92ZWN0b3JbMV0sIHVwcGVyX3ZlY3RvclsxXSkNCmBgYA0KYGBge3J9DQojIGNvbmZpZGVudGlhbCBpbnRlcnZhbCB2aXN1YWxpemF0aW9uDQpwbG90X2NpKGxvd2VyX3ZlY3RvciwgdXBwZXJfdmVjdG9yLCBtZWFuKHBvcHVsYXRpb24pKQ0KIyBGb3IgYSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCwgdGhlIGNyaXRpY2FsIHZhbHVlIGlzIC0xLjk1OTk2NCBhbmQgMS45NTk5NjQuDQpxbm9ybSgoMS0wLjk1KS8yKQ0KcW5vcm0oKDErMC45NSkvMikNCmBgYA0KDQoqKllvdXIgQ2hhbGxlbmdlOioqIA0KDQoqIFdoYXQgcHJvcG9ydGlvbiBvZiB5b3VyIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGluY2x1ZGUgdGhlIHRydWUgcG9wdWxhdGlvbiBtZWFuPyBJcyB0aGlzIHByb3BvcnRpb24gZXhhY3RseSBlcXVhbCB0byB0aGUgY29uZmlkZW5jZSBsZXZlbD8gSWYgbm90LCBleHBsYWluIHdoeS4NCg0KIyMgQW5zd2VyDQo5NiUgb2YgbXkgY29uZmlkZW5jZSBpbnRlcnZhbHMgaW5jbHVkZSB0aGUgdHJ1ZSBwb3B1bGF0aW9uIG1lYW4uIEl0IGlzIG5vdCBleGFjdGx5IGVxdWFsLiBXZSBvbmx5ICANCnRvb0sgNTAgc2FtcGxlcyBvZiBzaXplIDYwLiBUaGlzIGNvdWxkIGJlIHdoZXJlIG91ciBkaXNjcmVwYW5jeSBjb21lcyBmcm9tLg0KDQoqIFBpY2sgYSBjb25maWRlbmNlIGxldmVsIG9mIHlvdXIgY2hvb3NpbmcsIHByb3ZpZGVkIGl0IGlzIDk5JS4gV2hhdCBpcyB0aGUgYXBwcm9wcmlhdGUgY3JpdGljYWwgdmFsdWU/DQoNCiMjIEFuc3dlcg0KYGBge3J9DQpjbCA8LSA5OQ0KYWxwaGEgPC0gMS0oY2wvMTAwKQ0KY3AgPC0gMS0oYWxwaGEvMikgDQpjcA0KYGBgDQpXZSB3aWxsIHVzZSB0aGUgIHRhYmxlIHRvIGNvbXBsZXRlIHRoZSByZXN0IGJ5IGxvb2tpbmcgdXAgdGhlIHogc2NvcmUgdGhhdCBjb3JyZWxhdGVzIHRvIC45OTUNCg0KKiBDYWxjdWxhdGUgNTAgY29uZmlkZW5jZSBpbnRlcnZhbHMgYXQgdGhlIGNvbmZpZGVuY2UgbGV2ZWwgeW91IGNob3NlIGluIHRoZSBwcmV2aW91cyBxdWVzdGlvbi4gWW91IGRvIG5vdCBuZWVkIHRvIG9idGFpbiBuZXcgc2FtcGxlcywgc2ltcGx5IGNhbGN1bGF0ZSBuZXcgaW50ZXJ2YWxzIGJhc2VkIG9uIHRoZSBzYW1wbGUgbWVhbnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbnMgeW91IGhhdmUgYWxyZWFkeSBjb2xsZWN0ZWQuIFVzaW5nIHRoZSBwbG90X2NpIGZ1bmN0aW9uLCBwbG90IGFsbCBpbnRlcnZhbHMgYW5kIGNhbGN1bGF0ZSB0aGUgcHJvcG9ydGlvbiBvZiBpbnRlcnZhbHMgdGhhdCBpbmNsdWRlIHRoZSB0cnVlIHBvcHVsYXRpb24gbWVhbi4gSG93IGRvZXMgdGhpcyBwZXJjZW50YWdlIGNvbXBhcmUgdG8gdGhlIGNvbmZpZGVuY2UgbGV2ZWwgc2VsZWN0ZWQgZm9yIHRoZSBpbnRlcnZhbHM/DQoNCiMjIEFuc3dlcg0KYGBge3J9DQpsb3dlcl92ZWN0b3IgPC0gc2FtcF9tZWFuIC0gMi41NyAqIHNhbXBfc2Qvc3FydChuKQ0KdXBwZXJfdmVjdG9yIDwtIHNhbXBfbWVhbiArIDIuNSAqIHNhbXBfc2Qvc3FydChuKQ0KYyhsb3dlcl92ZWN0b3JbMV0sIHVwcGVyX3ZlY3RvclsxXSkNCnBsb3RfY2kobG93ZXJfdmVjdG9yLCB1cHBlcl92ZWN0b3IsIG1lYW4ocG9wdWxhdGlvbikpDQoNCmBgYA0KVmlzdWFsbHksIEkgY2FuIHNlZSB0aGF0IDEwMCUgb2YgaW50ZXJ2YWxzIGluY2x1ZGUgdGhlIHRydWUgcG9wdWxhdGlvbiBtZWFuLiBJdCBpcyB2ZXJ5IGNsb3NlIHRvIHRoZSBjb25maWRlbmNlIGxldmVsIHNlbGVjdGVkLg0KDQoNCg0KDQoNCg0KDQo=