Author: Kayla Keyue Chen
Last updated: 2024.4.28
Objectives
In this exercise, we will be recapping data manipulation and
visualisation skills and check normality to prepare for inferential
tests. We’ll also learn more functions to manipulate your
dataset, which we don’t have time to cover in the lab:
select()
and mutate()
from the tidyverse
package.
Dataset
This exercise will use a R built in dataset called
USJudgeRatings.
The data contains average ratings of 43 different judges’ abilities
by lawyers in the US. Each row is a lawyer (i.e., the rater), and each
column is a measure. You can type “USJudgeRatings” into the Help pane
and read more about it. For example,
- The first column CONT gives the mean number of
contacts each judge has had with the lawyers doing the ratings.
- The following columns give mean ratings out of 10 by the lawyers of
the judge’s abilities in different areas of their job.
- The final column RTEN gives the lawyers’ judgement
about whether the judge is worthy of retention.
We will be recapping data manipulation and visualisation skills and
check normality to prepare for inferential tests.
1. Set-up
Q1. Set working directory to your folder containing the files. Load
in the tidyverse and USJudgeRatings
dataset, saving it as
data
HINT: setwd()
, library()
,
read.csv()
#setwd("...")
library(tidyverse)
data <- read.csv("USJudgeRatings.csv")
Q2. Is the dataframe in WIDE or LONG format?
# type your answer here: wide
2. Data manipulation
Q3. First remove the column reflecting ‘Worthy of retention’ (i.e.,
RTEN) as we are not interested in that variable (save the new object as
data
)
HINT: Use select(dataframe_name, <column names>)
to select the columns to keep. For exmaple,
select(data, c("CONT", "INTG", "DMNR"))
. Alternatively, you
can drop columns that you don’t need any more by using a minus symbol
-
. For example, to drop the INTG column, you can use
select(data, -INTG)
.
data <- select(data, -RTEN)
Q4. Next create a new column ID
so that we can identify
the judges anonymously. The first row has ID of 1, the second has ID of
2, etc (recall that a row is a lawyer who rated the judge so ID is the
participant ID).
HINT: Use mutate(column_name = ...)
to create a new
column or edit an existing column.
data <- data %>% mutate(ID=1:43)
Q5. Next we want to convert the table to a long format with three
columns: ID
, Variable
and Score
:
save this as object data2
HINT: Use gather()
data2 <- data %>% gather(key=Variable, value=Score, CONT:PHYS)
2. Descriptive Statistics
Q6. Now we can summarise the data. Make a table of mean, SD, SE and
95% confidence intervals for each variable and save it as
summary
.
HINT: Use group_by()
, summarise()
summary <- data2 %>% group_by(Variable) %>%
summarise(mean = mean(Score),
sd = sd(Score),
se = sd/sqrt(n()),
ci_lower = mean - 1.96*se,
ci_upper = mean + 1.96*se)
3. Further manipulation
Q7. Create a new dataframe (data3
) that comprises
ID
and Total
. Total is the sum
score of all variables except number of contacts with judge
(i.e., CONT).
HINT: Use filter()
, group_by()
and
summarise()
data3 <- data2 %>%
filter(Variable != 'CONT') %>%
group_by(ID) %>%
summarise(Total = sum(Score))
Q8. Now we will integrate the total (in data3
) with all
other measures (in data
) and save it as
data4
.
HINT: Use inner_join()
data4 <- data3 %>% inner_join(data, by='ID')
Now we have ID, Number of contacts of lawyer with judge (CONT), 10
measures of the judge (from INTG to PHYS), and a total score of all
measures. Take a look at first 6 rows of the dataframe.
HINT: Use head()
head(data4)
# A tibble: 6 × 13
ID Total CONT INTG DMNR DILG CFMG DECI PREP FAMI ORAL WRIT PHYS
<int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 74 5.7 7.9 7.7 7.3 7.1 7.4 7.1 7.1 7.1 7 8.3
2 2 82.3 6.8 8.9 8.8 8.5 7.8 8.1 8 8 7.8 7.9 8.5
3 3 76.4 7.2 8.1 7.8 7.8 7.5 7.6 7.5 7.5 7.3 7.4 7.9
4 4 86 6.8 8.8 8.5 8.8 8.3 8.5 8.7 8.7 8.4 8.5 8.8
5 5 56.7 7.3 6.4 4.3 6.5 6 6.2 5.7 5.7 5.1 5.3 5.5
6 6 82.6 6.2 8.8 8.7 8.5 7.9 8 8.1 8 8 8 8.6
PS: You can always name the dataframe data
instead of
data2
, data3
, data4
to avoid too
many (useless) objects in your environment. However, this would
overwrite your original data
dataframe, so you won’t be
able to come back to it. There is a balance between creating new objects
and keeping the environment tidy…
4. Data visualisation
Q9. Make a graph to help you decide whether the total ratings are
normally distributed, check the Q-Q plot, Skewness and Kurtosis values,
and test normality using Shapiro-Wilk test.
HINT: Histogram, qqnorm()
, qqline()
,
describe()
(from the psych package),
shapiro.test()
# histogram
ggplot(data4, aes(x = Total)) +
geom_histogram(binwidth = 5, fill = "white", color = "black")
# Q-Q plot
qqnorm(data4$Total)
qqline(data4$Total)
# skewness and kurtosis
library(psych)
describe(data4$Total)
vars n mean sd median trimmed mad min max range skew kurtosis se
X1 1 43 75.84 8.89 77.4 76.73 7.71 53.5 89.2 35.7 -0.76 -0.07 1.36
# skewness = -0.76, kurtosis = -0.07
# shapiro-wilk test
shapiro.test(data4$Total)
Shapiro-Wilk normality test
data: data4$Total
W = 0.93925, p-value = 0.02444
# p value = 0.024
Is the Shapiro-Wilk test significant? What does it mean?
# type your answer here: It is significant so the Total score is not normally distributed.
Q10. Next plot the relationship between number of contacts and total
rating (add an estimated regression line).
HINT: scatter plot
ggplot(data4, aes(x=CONT, y=Total)) +
geom_point() +
geom_smooth(method = "lm")
Q11. Create a bar plot of Judicial integrity (INTG), Demeanor (DMNR),
Diligence (DILG), including mean, SD, and CI.
HINT: Use the summary
dataframe, filter relevant
variables, use stat = "identity"
in the
geom_bar()
function, add CI with
geom_errorbar()
ggplot(filter(summary, Variable %in% c("INTG", "DMNR", "DILG")), aes(x = Variable, y = mean)) +
geom_bar(stat = "identity", fill = "white", color = "black") +
geom_errorbar(aes(ymin = ci_lower, ymax = ci_upper)) +
ylim(0, 10)
LS0tDQp0aXRsZTogIlBMSU5TVEFUIGxhYiAyIGV4ZXJjaXNlIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQpwYXJhbXM6DQogIGZsZXg6IFRSVUUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiNzdHVkZW50czogdGhpcyBpcyB0aGUgc2V0IHVwIGNodW5rLCBpdCBjYW4gYmUgaWdub3JlZA0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNvbW1lbnQgPSAiIikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkocHN5Y2gpDQpgYGANCg0KQXV0aG9yOiBLYXlsYSBLZXl1ZSBDaGVuDQoNCkxhc3QgdXBkYXRlZDogMjAyNC40LjI4DQoNCiMjIE9iamVjdGl2ZXMNCg0KSW4gdGhpcyBleGVyY2lzZSwgd2Ugd2lsbCBiZSByZWNhcHBpbmcgZGF0YSBtYW5pcHVsYXRpb24gYW5kIHZpc3VhbGlzYXRpb24gc2tpbGxzIGFuZCBjaGVjayBub3JtYWxpdHkgdG8gcHJlcGFyZSBmb3IgaW5mZXJlbnRpYWwgdGVzdHMuICoqV2UnbGwgYWxzbyBsZWFybiBtb3JlIGZ1bmN0aW9ucyB0byBtYW5pcHVsYXRlIHlvdXIgZGF0YXNldCwgd2hpY2ggd2UgZG9uJ3QgaGF2ZSB0aW1lIHRvIGNvdmVyIGluIHRoZSBsYWI6KiogYHNlbGVjdCgpYCBhbmQgYG11dGF0ZSgpYCBmcm9tIHRoZSB0aWR5dmVyc2UgcGFja2FnZS4gDQoNCiMjIERhdGFzZXQNCg0KVGhpcyBleGVyY2lzZSB3aWxsIHVzZSBhIFIgYnVpbHQgaW4gZGF0YXNldCBjYWxsZWQgVVNKdWRnZVJhdGluZ3MuDQoNClRoZSBkYXRhIGNvbnRhaW5zIGF2ZXJhZ2UgcmF0aW5ncyBvZiA0MyBkaWZmZXJlbnQganVkZ2VzJyBhYmlsaXRpZXMgYnkgbGF3eWVycyBpbiB0aGUgVVMuIEVhY2ggcm93IGlzIGEgbGF3eWVyIChpLmUuLCB0aGUgcmF0ZXIpLCBhbmQgZWFjaCBjb2x1bW4gaXMgYSBtZWFzdXJlLiBZb3UgY2FuIHR5cGUgIlVTSnVkZ2VSYXRpbmdzIiBpbnRvIHRoZSBIZWxwIHBhbmUgYW5kIHJlYWQgbW9yZSBhYm91dCBpdC4gRm9yIGV4YW1wbGUsIA0KDQoqIFRoZSBmaXJzdCBjb2x1bW4gKipDT05UKiogZ2l2ZXMgdGhlIG1lYW4gbnVtYmVyIG9mIGNvbnRhY3RzIGVhY2gganVkZ2UgaGFzIGhhZCB3aXRoIHRoZSBsYXd5ZXJzIGRvaW5nIHRoZSByYXRpbmdzLiANCiogVGhlIGZvbGxvd2luZyBjb2x1bW5zIGdpdmUgbWVhbiByYXRpbmdzIG91dCBvZiAxMCBieSB0aGUgbGF3eWVycyBvZiB0aGUganVkZ2XigJlzIGFiaWxpdGllcyBpbiBkaWZmZXJlbnQgYXJlYXMgb2YgdGhlaXIgam9iLiANCiogVGhlIGZpbmFsIGNvbHVtbiAqKlJURU4qKiBnaXZlcyB0aGUgbGF3eWVycycganVkZ2VtZW50IGFib3V0IHdoZXRoZXIgdGhlIGp1ZGdlIGlzIHdvcnRoeSBvZiByZXRlbnRpb24uDQoNCldlIHdpbGwgYmUgcmVjYXBwaW5nIGRhdGEgbWFuaXB1bGF0aW9uIGFuZCB2aXN1YWxpc2F0aW9uIHNraWxscyBhbmQgY2hlY2sgbm9ybWFsaXR5IHRvIHByZXBhcmUgZm9yIGluZmVyZW50aWFsIHRlc3RzLiANCg0KIyMgMS4gU2V0LXVwDQoNClExLiBTZXQgd29ya2luZyBkaXJlY3RvcnkgdG8geW91ciBmb2xkZXIgY29udGFpbmluZyB0aGUgZmlsZXMuIExvYWQgaW4gdGhlIHRpZHl2ZXJzZSBhbmQgYFVTSnVkZ2VSYXRpbmdzYCBkYXRhc2V0LCBzYXZpbmcgaXQgYXMgYGRhdGFgDQoNCkhJTlQ6IGBzZXR3ZCgpYCwgYGxpYnJhcnkoKWAsIGByZWFkLmNzdigpYA0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCiNzZXR3ZCgiLi4uIikNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQpkYXRhIDwtIHJlYWQuY3N2KCJVU0p1ZGdlUmF0aW5ncy5jc3YiKQ0KYGBgDQoNClEyLiBJcyB0aGUgZGF0YWZyYW1lIGluIFdJREUgb3IgTE9ORyBmb3JtYXQ/DQoNCmBgYHtyfQ0KIyB0eXBlIHlvdXIgYW5zd2VyIGhlcmU6IHdpZGUNCmBgYA0KDQojIyAyLiBEYXRhIG1hbmlwdWxhdGlvbg0KDQpRMy4gRmlyc3QgcmVtb3ZlIHRoZSBjb2x1bW4gcmVmbGVjdGluZyAnV29ydGh5IG9mIHJldGVudGlvbicgKGkuZS4sIFJURU4pIGFzIHdlIGFyZSBub3QgaW50ZXJlc3RlZCBpbiB0aGF0IHZhcmlhYmxlIChzYXZlIHRoZSBuZXcgb2JqZWN0IGFzIGBkYXRhYCkNCg0KSElOVDogVXNlIGBzZWxlY3QoZGF0YWZyYW1lX25hbWUsIDxjb2x1bW4gbmFtZXM+KWAgdG8gc2VsZWN0IHRoZSBjb2x1bW5zIHRvIGtlZXAuIEZvciBleG1hcGxlLCBgc2VsZWN0KGRhdGEsIGMoIkNPTlQiLCAiSU5URyIsICJETU5SIikpYC4gQWx0ZXJuYXRpdmVseSwgeW91IGNhbiBkcm9wIGNvbHVtbnMgdGhhdCB5b3UgZG9uJ3QgbmVlZCBhbnkgbW9yZSBieSB1c2luZyBhIG1pbnVzIHN5bWJvbCBgLWAuIEZvciBleGFtcGxlLCB0byBkcm9wIHRoZSBJTlRHIGNvbHVtbiwgeW91IGNhbiB1c2UgYHNlbGVjdChkYXRhLCAtSU5URylgLiANCg0KYGBge3J9DQpkYXRhIDwtIHNlbGVjdChkYXRhLCAtUlRFTikNCmBgYA0KDQpRNC4gTmV4dCBjcmVhdGUgYSBuZXcgY29sdW1uIGBJRGAgc28gdGhhdCB3ZSBjYW4gaWRlbnRpZnkgdGhlIGp1ZGdlcyBhbm9ueW1vdXNseS4gVGhlIGZpcnN0IHJvdyBoYXMgSUQgb2YgMSwgdGhlIHNlY29uZCBoYXMgSUQgb2YgMiwgZXRjIChyZWNhbGwgdGhhdCBhIHJvdyBpcyBhIGxhd3llciB3aG8gcmF0ZWQgdGhlIGp1ZGdlIHNvIElEIGlzIHRoZSBwYXJ0aWNpcGFudCBJRCkuIA0KDQpISU5UOiBVc2UgYG11dGF0ZShjb2x1bW5fbmFtZSA9IC4uLilgIHRvIGNyZWF0ZSBhIG5ldyBjb2x1bW4gb3IgZWRpdCBhbiBleGlzdGluZyBjb2x1bW4uIA0KDQpgYGB7cn0NCmRhdGEgPC0gZGF0YSAlPiUgbXV0YXRlKElEPTE6NDMpDQpgYGANCg0KUTUuIE5leHQgd2Ugd2FudCB0byBjb252ZXJ0IHRoZSB0YWJsZSB0byBhIGxvbmcgZm9ybWF0IHdpdGggdGhyZWUgY29sdW1uczogYElEYCwgYFZhcmlhYmxlYCBhbmQgYFNjb3JlYDogc2F2ZSB0aGlzIGFzIG9iamVjdCBkYXRhMg0KDQpISU5UOiBVc2UgYGdhdGhlcigpYA0KDQpgYGB7cn0NCmRhdGEyIDwtIGRhdGEgJT4lIGdhdGhlcihrZXk9VmFyaWFibGUsIHZhbHVlPVNjb3JlLCBDT05UOlBIWVMpDQpgYGANCg0KIyMgMi4gRGVzY3JpcHRpdmUgU3RhdGlzdGljcw0KDQpRNi4gTm93IHdlIGNhbiBzdW1tYXJpc2UgdGhlIGRhdGEuIE1ha2UgYSB0YWJsZSBvZiBtZWFuLCBTRCwgU0UgYW5kIDk1JSBjb25maWRlbmNlIGludGVydmFscyBmb3IgZWFjaCB2YXJpYWJsZSBhbmQgc2F2ZSBpdCBhcyBgc3VtbWFyeWAuDQoNCkhJTlQ6IFVzZSBgZ3JvdXBfYnkoKWAsIGBzdW1tYXJpc2UoKWANCg0KYGBge3J9DQpzdW1tYXJ5IDwtIGRhdGEyICU+JSBncm91cF9ieShWYXJpYWJsZSkgJT4lIA0KICBzdW1tYXJpc2UobWVhbiA9IG1lYW4oU2NvcmUpLCANCiAgICAgICAgICAgIHNkID0gc2QoU2NvcmUpLCANCiAgICAgICAgICAgIHNlID0gc2Qvc3FydChuKCkpLCANCiAgICAgICAgICAgIGNpX2xvd2VyID0gbWVhbiAtIDEuOTYqc2UsIA0KICAgICAgICAgICAgY2lfdXBwZXIgPSBtZWFuICsgMS45NipzZSkNCmBgYA0KDQojIyAzLiBGdXJ0aGVyIG1hbmlwdWxhdGlvbg0KDQpRNy4gQ3JlYXRlIGEgbmV3IGRhdGFmcmFtZSAoYGRhdGEzYCkgdGhhdCBjb21wcmlzZXMgYElEYCBhbmQgYFRvdGFsYC4gVG90YWwgaXMgdGhlICoqc3VtIHNjb3JlKiogb2YgYWxsIHZhcmlhYmxlcyBleGNlcHQgbnVtYmVyIG9mIGNvbnRhY3RzIHdpdGgganVkZ2UgKGkuZS4sIENPTlQpLg0KDQpISU5UOiBVc2UgYGZpbHRlcigpYCwgYGdyb3VwX2J5KClgIGFuZCBgc3VtbWFyaXNlKClgDQoNCmBgYHtyfQ0KZGF0YTMgPC0gZGF0YTIgJT4lIA0KICBmaWx0ZXIoVmFyaWFibGUgIT0gJ0NPTlQnKSAlPiUNCiAgZ3JvdXBfYnkoSUQpICU+JSANCiAgc3VtbWFyaXNlKFRvdGFsID0gc3VtKFNjb3JlKSkNCmBgYA0KDQpROC4gTm93IHdlIHdpbGwgaW50ZWdyYXRlIHRoZSB0b3RhbCAoaW4gYGRhdGEzYCkgd2l0aCBhbGwgb3RoZXIgbWVhc3VyZXMgKGluIGBkYXRhYCkgYW5kIHNhdmUgaXQgYXMgYGRhdGE0YC4NCg0KSElOVDogVXNlIGBpbm5lcl9qb2luKClgDQoNCmBgYHtyfQ0KZGF0YTQgPC0gZGF0YTMgJT4lIGlubmVyX2pvaW4oZGF0YSwgYnk9J0lEJykNCmBgYA0KDQpOb3cgd2UgaGF2ZSBJRCwgTnVtYmVyIG9mIGNvbnRhY3RzIG9mIGxhd3llciB3aXRoIGp1ZGdlIChDT05UKSwgMTAgbWVhc3VyZXMgb2YgdGhlIGp1ZGdlIChmcm9tIElOVEcgdG8gUEhZUyksIGFuZCBhIHRvdGFsIHNjb3JlIG9mIGFsbCBtZWFzdXJlcy4gVGFrZSBhIGxvb2sgYXQgZmlyc3QgNiByb3dzIG9mIHRoZSBkYXRhZnJhbWUuIA0KDQpISU5UOiBVc2UgYGhlYWQoKWANCg0KYGBge3J9DQpoZWFkKGRhdGE0KQ0KYGBgDQoNClBTOiBZb3UgY2FuIGFsd2F5cyBuYW1lIHRoZSBkYXRhZnJhbWUgYGRhdGFgIGluc3RlYWQgb2YgYGRhdGEyYCwgYGRhdGEzYCwgYGRhdGE0YCB0byBhdm9pZCB0b28gbWFueSAodXNlbGVzcykgb2JqZWN0cyBpbiB5b3VyIGVudmlyb25tZW50LiBIb3dldmVyLCB0aGlzIHdvdWxkIG92ZXJ3cml0ZSB5b3VyIG9yaWdpbmFsIGBkYXRhYCBkYXRhZnJhbWUsIHNvIHlvdSB3b24ndCBiZSBhYmxlIHRvIGNvbWUgYmFjayB0byBpdC4gVGhlcmUgaXMgYSBiYWxhbmNlIGJldHdlZW4gY3JlYXRpbmcgbmV3IG9iamVjdHMgYW5kIGtlZXBpbmcgdGhlIGVudmlyb25tZW50IHRpZHkuLi4gDQoNCiMjIDQuIERhdGEgdmlzdWFsaXNhdGlvbg0KDQpROS4gTWFrZSBhIGdyYXBoIHRvIGhlbHAgeW91IGRlY2lkZSB3aGV0aGVyIHRoZSB0b3RhbCByYXRpbmdzIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZCwgY2hlY2sgdGhlIFEtUSBwbG90LCBTa2V3bmVzcyBhbmQgS3VydG9zaXMgdmFsdWVzLCBhbmQgdGVzdCBub3JtYWxpdHkgdXNpbmcgU2hhcGlyby1XaWxrIHRlc3QuIA0KDQpISU5UOiBIaXN0b2dyYW0sIGBxcW5vcm0oKWAsIGBxcWxpbmUoKWAsIGBkZXNjcmliZSgpYCAoZnJvbSB0aGUgcHN5Y2ggcGFja2FnZSksIGBzaGFwaXJvLnRlc3QoKWANCg0KYGBge3J9DQojIGhpc3RvZ3JhbQ0KZ2dwbG90KGRhdGE0LCBhZXMoeCA9IFRvdGFsKSkgKyANCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1LCBmaWxsID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siKQ0KDQojIFEtUSBwbG90DQpxcW5vcm0oZGF0YTQkVG90YWwpDQpxcWxpbmUoZGF0YTQkVG90YWwpDQoNCiMgc2tld25lc3MgYW5kIGt1cnRvc2lzDQpsaWJyYXJ5KHBzeWNoKQ0KZGVzY3JpYmUoZGF0YTQkVG90YWwpDQojIHNrZXduZXNzID0gLTAuNzYsIGt1cnRvc2lzID0gLTAuMDcNCg0KIyBzaGFwaXJvLXdpbGsgdGVzdA0Kc2hhcGlyby50ZXN0KGRhdGE0JFRvdGFsKQ0KIyBwIHZhbHVlID0gMC4wMjQNCmBgYA0KDQpJcyB0aGUgU2hhcGlyby1XaWxrIHRlc3Qgc2lnbmlmaWNhbnQ/IFdoYXQgZG9lcyBpdCBtZWFuPyANCg0KYGBge3J9DQojIHR5cGUgeW91ciBhbnN3ZXIgaGVyZTogSXQgaXMgc2lnbmlmaWNhbnQgc28gdGhlIFRvdGFsIHNjb3JlIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZC4gDQpgYGANCg0KDQpRMTAuIE5leHQgcGxvdCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbnVtYmVyIG9mIGNvbnRhY3RzIGFuZCB0b3RhbCByYXRpbmcgKGFkZCBhbiBlc3RpbWF0ZWQgcmVncmVzc2lvbiBsaW5lKS4NCg0KSElOVDogc2NhdHRlciBwbG90DQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGE0LCBhZXMoeD1DT05ULCB5PVRvdGFsKSkgKyANCiAgZ2VvbV9wb2ludCgpICsgDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpDQpgYGANCg0KUTExLiBDcmVhdGUgYSBiYXIgcGxvdCBvZiBKdWRpY2lhbCBpbnRlZ3JpdHkgKElOVEcpLCBEZW1lYW5vciAoRE1OUiksIERpbGlnZW5jZSAoRElMRyksIGluY2x1ZGluZyBtZWFuLCBTRCwgYW5kIENJLiANCg0KSElOVDogVXNlIHRoZSBgc3VtbWFyeWAgZGF0YWZyYW1lLCBmaWx0ZXIgcmVsZXZhbnQgdmFyaWFibGVzLCB1c2UgYHN0YXQgPSAiaWRlbnRpdHkiYCBpbiB0aGUgYGdlb21fYmFyKClgIGZ1bmN0aW9uLCBhZGQgQ0kgd2l0aCBgZ2VvbV9lcnJvcmJhcigpYA0KDQpgYGB7ciwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NH0NCmdncGxvdChmaWx0ZXIoc3VtbWFyeSwgVmFyaWFibGUgJWluJSBjKCJJTlRHIiwgIkRNTlIiLCAiRElMRyIpKSwgYWVzKHggPSBWYXJpYWJsZSwgeSA9IG1lYW4pKSArIA0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIikgKyANCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGNpX2xvd2VyLCB5bWF4ID0gY2lfdXBwZXIpKSArIA0KICB5bGltKDAsIDEwKQ0KYGBgDQoNCg==