This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

plot(cars)
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages --------------------------------------- tidyverse 1.3.0 --
v ggplot2 3.3.2     v purrr   0.3.4
v tibble  3.0.3     v dplyr   1.0.2
v tidyr   1.1.1     v stringr 1.4.0
v readr   1.3.1     v forcats 0.5.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(lme4)
Loading required package: Matrix

Attaching package: 㤼㸱Matrix㤼㸲

The following objects are masked from 㤼㸱package:tidyr㤼㸲:

    expand, pack, unpack
library(Hmisc)
Loading required package: lattice
Loading required package: survival
Loading required package: Formula
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     

Attaching package: 㤼㸱Hmisc㤼㸲

The following objects are masked from 㤼㸱package:dplyr㤼㸲:

    src, summarize

The following objects are masked from 㤼㸱package:base㤼㸲:

    format.pval, units
projectSTAR_1_ <- read_dta("EDUS 651/projectSTAR (1).dta")
glimpse(projectSTAR_1_)
Rows: 6,325
Columns: 27
$ stdntid       <dbl> 10001, 10133, 10246, 10263, 10266, 10275, ...
$ race          <dbl+lbl> 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2,...
$ gender        <dbl+lbl> 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1,...
$ FLAGSGK       <dbl+lbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
$ flaggk        <dbl+lbl> 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
$ gkclasstype   <dbl+lbl> 3, 3, 3, 1, 2, 3, 1, 3, 1, 2, 3, 3, 2,...
$ gkschid       <dbl> 169229, 169280, 218562, 205492, 257899, 16...
$ gksurban      <dbl+lbl> 2, 2, 4, 2, 3, 3, 2, 2, 3, 3, 3, 2, 2,...
$ gktchid       <dbl> 16922904, 16928003, 21856202, 20549204, 25...
$ gktgen        <dbl+lbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
$ gktrace       <dbl+lbl> 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
$ gkthighdegree <dbl+lbl> 2, 2, 3, 2, 3, 2, 3, 3, 3, 3, 2, 2, 3,...
$ gktcareer     <dbl+lbl>  4,  4,  4,  4,  4, NA,  4,  4,  4,  4...
$ gktyears      <dbl> 5, 7, 8, 3, 12, 2, 7, 14, 4, 6, 11, 16, 12...
$ gkclasssize   <dbl> 24, 22, 17, 17, 24, 24, 13, 24, 14, 23, 23...
$ gkfreelunch   <dbl+lbl> 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2,...
$ gkrepeat      <dbl+lbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
$ gkspeced      <dbl+lbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
$ gkspecin      <dbl+lbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,...
$ gkpresent     <dbl> 161, 175, 132, 178, 170, 94, 160, 154, 172...
$ gkabsent      <dbl> 19, 5, 28, 2, 10, 3, 2, 7, 8, 2, 17, 8, 0,...
$ gktreadss     <dbl> NA, 427, 450, 483, 456, 411, 443, 448, 463...
$ gktmathss     <dbl> NA, 478, 494, 513, 513, 468, 473, 449, 520...
$ gktlistss     <dbl> NA, 509, 549, 554, 520, 571, 595, 540, 565...
$ gkwordskillss <dbl> NA, 418, 444, 431, 468, 396, 444, 444, 480...
$ gkmotivraw    <dbl> 23, 24, 28, 27, 25, 24, NA, NA, 26, 27, 24...
$ gkselfconcraw <dbl> 52, 53, 56, 61, 54, 55, NA, NA, 52, 61, 55...
clean.projectSTAR_1 <- projectSTAR_1_ %>%
  mutate(., 
         gkclasstype.fac = as_factor(gkclasstype),
         gkthighdegree.fac = as_factor(gkthighdegree),
         classid = gktchid)
glimpse(clean.projectSTAR_1)
Rows: 6,325
Columns: 30
$ stdntid           <dbl> 10001, 10133, 10246, 10263, 10266, 102...
$ race              <dbl+lbl> 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1...
$ gender            <dbl+lbl> 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1...
$ FLAGSGK           <dbl+lbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
$ flaggk            <dbl+lbl> 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
$ gkclasstype       <dbl+lbl> 3, 3, 3, 1, 2, 3, 1, 3, 1, 2, 3, 3...
$ gkschid           <dbl> 169229, 169280, 218562, 205492, 257899...
$ gksurban          <dbl+lbl> 2, 2, 4, 2, 3, 3, 2, 2, 3, 3, 3, 2...
$ gktchid           <dbl> 16922904, 16928003, 21856202, 20549204...
$ gktgen            <dbl+lbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2...
$ gktrace           <dbl+lbl> 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
$ gkthighdegree     <dbl+lbl> 2, 2, 3, 2, 3, 2, 3, 3, 3, 3, 2, 2...
$ gktcareer         <dbl+lbl>  4,  4,  4,  4,  4, NA,  4,  4,  4...
$ gktyears          <dbl> 5, 7, 8, 3, 12, 2, 7, 14, 4, 6, 11, 16...
$ gkclasssize       <dbl> 24, 22, 17, 17, 24, 24, 13, 24, 14, 23...
$ gkfreelunch       <dbl+lbl> 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2...
$ gkrepeat          <dbl+lbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
$ gkspeced          <dbl+lbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2...
$ gkspecin          <dbl+lbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2...
$ gkpresent         <dbl> 161, 175, 132, 178, 170, 94, 160, 154,...
$ gkabsent          <dbl> 19, 5, 28, 2, 10, 3, 2, 7, 8, 2, 17, 8...
$ gktreadss         <dbl> NA, 427, 450, 483, 456, 411, 443, 448,...
$ gktmathss         <dbl> NA, 478, 494, 513, 513, 468, 473, 449,...
$ gktlistss         <dbl> NA, 509, 549, 554, 520, 571, 595, 540,...
$ gkwordskillss     <dbl> NA, 418, 444, 431, 468, 396, 444, 444,...
$ gkmotivraw        <dbl> 23, 24, 28, 27, 25, 24, NA, NA, 26, 27...
$ gkselfconcraw     <dbl> 52, 53, 56, 61, 54, 55, NA, NA, 52, 61...
$ gkclasstype.fac   <fct> REGULAR + AIDE CLASS, REGULAR + AIDE C...
$ gkthighdegree.fac <fct> BACHELORS, BACHELORS, MASTERS, BACHELO...
$ classid           <dbl> 16922904, 16928003, 21856202, 20549204...

1.Run a conditional random intercept model with math scores (gktmathss) as the DV, and self-concept (gkselfconcraw) as a student-level IV, and classroom type (gkclasstype) and teacher highest degree (gkthighdegree) as teacher/classroom-level IVs. Save these model results for later.

model.1 <- lmer(gktmathss ~  gkselfconcraw + gkclasstype.fac + gkthighdegree.fac +(1|classid), REML = FALSE, data = clean.projectSTAR_1)
summary(model.1)
Linear mixed model fit by maximum likelihood  ['lmerMod']
Formula: 
gktmathss ~ gkselfconcraw + gkclasstype.fac + gkthighdegree.fac +  
    (1 | classid)
   Data: clean.projectSTAR_1

     AIC      BIC   logLik deviance df.resid 
 49060.3  49118.5 -24521.1  49042.3     4747 

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.8420 -0.6386 -0.0638  0.5808  3.8959 

Random effects:
 Groups   Name        Variance Std.Dev.
 classid  (Intercept)  659.1   25.67   
 Residual             1550.2   39.37   
Number of obs: 4756, groups:  classid, 301

Fixed effects:
                                    Estimate Std. Error t value
(Intercept)                         466.5310     7.2874  64.019
gkselfconcraw                         0.4449     0.1196   3.719
gkclasstype.facREGULAR CLASS         -6.8528     3.8833  -1.765
gkclasstype.facREGULAR + AIDE CLASS  -8.6284     3.8933  -2.216
gkthighdegree.facMASTERS              1.7043     3.5020   0.487
gkthighdegree.facMASTERS +            1.9140     9.9387   0.193
gkthighdegree.facSPECIALIST          23.2069    16.7318   1.387

Correlation of Fixed Effects:
            (Intr) gkslfc g.REGC g.R+AC g.MAST g.MAS+
gkselfcncrw -0.924                                   
g.REGULARCL -0.249  0.018                            
g.REGULA+AC -0.249  0.017  0.458                     
gkt.MASTERS -0.122 -0.008 -0.072 -0.066              
gk.MASTERS+ -0.045 -0.005 -0.023  0.002  0.112       
g.SPECIALIS -0.060 -0.005  0.101  0.101  0.056  0.022
  1. Create a variable for your conditional standardized residuals using the predict command in Stata or the augment function in R. Then, check for normality of residuals using a histogram, as well as sktest in Stata or shapiro.test in R.
library(broom.mixed)
Registered S3 method overwritten by 'broom.mixed':
  method      from 
  tidy.gamlss broom
diagnostics <- augment(model.1)
ggplot(data = diagnostics, mapping = aes(x = .resid)) +
  geom_histogram(binwidth = .25) + theme_classic() + 
  labs(title = "Histogram of Residuals for Math Scores Model",
                      x = "Residual Value") 

shapiro.test(diagnostics$.resid)

    Shapiro-Wilk normality test

data:  diagnostics$.resid
W = 0.99119, p-value < 2.2e-16

The residuals do not meet the assumptions of normalcy. The histogram is bimodal and the Sapiro-wilk normality test was significant meaning the null hypothesis that the residuals are normally distributed can be rejected.

  1. Create a variable for your predicted values (fitted values) using the predict command with the fitted option. R folks - this should already be created by running the previous augment function. Then, check for linearity and heteroskedasticity using an RVF plot.
ggplot(data = diagnostics, mapping = aes(x = .fitted, y = .resid)) +
  geom_point() + labs(title = "RVF Plot for Math Scores Model",
                      x = "Predicted Value, Math Scores",
                      y = "Residual Value") + theme_classic()

There is funnenling which shows that there is heteroskedasticity. I also think there is a curve which is a sign of non-linearity.

  1. Use Cook’s Distance values to look for potential regression outliers. In Stata, this will require the mlt package and mltcooksd command. Create a plot of fitted values vs. Cook’s distances and interpret.
ggplot(data = diagnostics, mapping = aes(x = .fitted, y = .cooksd, label = classid)) +
  geom_point() + geom_text(nudge_x = .25) + theme_classic() + 
  labs(title = "Cook's Distance Plot for Classroom Math Scores Model",
                      x = "Predicted Value, Math Scores",
                      y = "Cook's Distance") + 
  geom_hline(yintercept = 4/6325, linetype = "dotted")

I can’t see the dotted line and there is only one part where the observations go from one side to the other. The cutoff of 4/6325 does not seem reasonable because it would exclude a large amount of data. There are a few outliers though perhaps a cutoff of a cook’s distance of 0.10 would be good. It is hard to tell becaue they are clumped together.

  1. Conduct a robustness check for your model by comparing your original model to 1) a model with robust standard errors, and 2) a model with all Cook’s Distance outliers removed. Create a summary table to summarize the estimates of all three models together. Are your results robust to mild to moderate violations of the assumptions? Focus on the estimate of the class type variable (gkclasstype)
library(robustlmm)
package 㤼㸱robustlmm㤼㸲 was built under R version 4.0.3
model.robust <- rlmer(gktmathss ~  gkselfconcraw + gkclasstype.fac + gkthighdegree.fac + (1|classid), REML = FALSE, data = clean.projectSTAR_1)
summary(model.robust)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLiANCg0KYGBge3J9DQpwbG90KGNhcnMpDQpgYGANCg0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShsbWU0KQ0KbGlicmFyeShIbWlzYykNCmBgYA0KYGBge3J9DQpwcm9qZWN0U1RBUl8xXyA8LSByZWFkX2R0YSgiRURVUyA2NTEvcHJvamVjdFNUQVIgKDEpLmR0YSIpDQpnbGltcHNlKHByb2plY3RTVEFSXzFfKQ0KYGBgDQoNCmBgYHtyfQ0KY2xlYW4ucHJvamVjdFNUQVJfMSA8LSBwcm9qZWN0U1RBUl8xXyAlPiUNCiAgbXV0YXRlKC4sIA0KICAgICAgICAgZ2tjbGFzc3R5cGUuZmFjID0gYXNfZmFjdG9yKGdrY2xhc3N0eXBlKSwNCiAgICAgICAgIGdrdGhpZ2hkZWdyZWUuZmFjID0gYXNfZmFjdG9yKGdrdGhpZ2hkZWdyZWUpLA0KICAgICAgICAgY2xhc3NpZCA9IGdrdGNoaWQpDQpnbGltcHNlKGNsZWFuLnByb2plY3RTVEFSXzEpDQpgYGANCjEuUnVuIGEgY29uZGl0aW9uYWwgcmFuZG9tIGludGVyY2VwdCBtb2RlbCB3aXRoIG1hdGggc2NvcmVzIChna3RtYXRoc3MpIGFzIHRoZSBEViwgYW5kIHNlbGYtY29uY2VwdCAoZ2tzZWxmY29uY3JhdykgYXMgYSBzdHVkZW50LWxldmVsIElWLCBhbmQgY2xhc3Nyb29tIHR5cGUgKGdrY2xhc3N0eXBlKSBhbmQgdGVhY2hlciBoaWdoZXN0IGRlZ3JlZSAoZ2t0aGlnaGRlZ3JlZSkgYXMgdGVhY2hlci9jbGFzc3Jvb20tbGV2ZWwgSVZzLiBTYXZlIHRoZXNlIG1vZGVsIHJlc3VsdHMgZm9yIGxhdGVyLg0KDQpgYGB7cn0NCm1vZGVsLjEgPC0gbG1lcihna3RtYXRoc3MgfiAgZ2tzZWxmY29uY3JhdyArIGdrY2xhc3N0eXBlLmZhYyArIGdrdGhpZ2hkZWdyZWUuZmFjICsoMXxjbGFzc2lkKSwgUkVNTCA9IEZBTFNFLCBkYXRhID0gY2xlYW4ucHJvamVjdFNUQVJfMSkNCnN1bW1hcnkobW9kZWwuMSkNCmBgYA0KMi4gQ3JlYXRlIGEgdmFyaWFibGUgZm9yIHlvdXIgY29uZGl0aW9uYWwgc3RhbmRhcmRpemVkIHJlc2lkdWFscyB1c2luZyB0aGUgcHJlZGljdCBjb21tYW5kIGluIFN0YXRhIG9yIHRoZSBhdWdtZW50IGZ1bmN0aW9uIGluIFIuIFRoZW4sIGNoZWNrIGZvciBub3JtYWxpdHkgb2YgcmVzaWR1YWxzIHVzaW5nIGEgaGlzdG9ncmFtLCBhcyB3ZWxsIGFzIHNrdGVzdCBpbiBTdGF0YSBvciBzaGFwaXJvLnRlc3QgaW4gUi4NCmBgYHtyfQ0KbGlicmFyeShicm9vbS5taXhlZCkNCmBgYA0KDQpgYGB7cn0NCmRpYWdub3N0aWNzIDwtIGF1Z21lbnQobW9kZWwuMSkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gZGlhZ25vc3RpY3MsIG1hcHBpbmcgPSBhZXMoeCA9IC5yZXNpZCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAuMjUpICsgdGhlbWVfY2xhc3NpYygpICsgDQogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtIG9mIFJlc2lkdWFscyBmb3IgTWF0aCBTY29yZXMgTW9kZWwiLA0KICAgICAgICAgICAgICAgICAgICAgIHggPSAiUmVzaWR1YWwgVmFsdWUiKSANCmBgYA0KDQpgYGB7cn0NCnNoYXBpcm8udGVzdChkaWFnbm9zdGljcyQucmVzaWQpDQpgYGANClRoZSByZXNpZHVhbHMgZG8gbm90IG1lZXQgdGhlIGFzc3VtcHRpb25zIG9mIG5vcm1hbGN5LiBUaGUgaGlzdG9ncmFtIGlzIGJpbW9kYWwgYW5kIHRoZSBTYXBpcm8td2lsayBub3JtYWxpdHkgdGVzdCB3YXMgc2lnbmlmaWNhbnQgbWVhbmluZyB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIHJlc2lkdWFscyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgY2FuIGJlIHJlamVjdGVkLiANCg0KMy4gIENyZWF0ZSBhIHZhcmlhYmxlIGZvciB5b3VyIHByZWRpY3RlZCB2YWx1ZXMgKGZpdHRlZCB2YWx1ZXMpIHVzaW5nIHRoZSBwcmVkaWN0IGNvbW1hbmQgd2l0aCB0aGUgZml0dGVkIG9wdGlvbi4gUiBmb2xrcyAtIHRoaXMgc2hvdWxkIGFscmVhZHkgYmUgY3JlYXRlZCBieSBydW5uaW5nIHRoZSBwcmV2aW91cyBhdWdtZW50IGZ1bmN0aW9uLiBUaGVuLCBjaGVjayBmb3IgbGluZWFyaXR5IGFuZCBoZXRlcm9za2VkYXN0aWNpdHkgdXNpbmcgYW4gUlZGIHBsb3QuDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBkaWFnbm9zdGljcywgbWFwcGluZyA9IGFlcyh4ID0gLmZpdHRlZCwgeSA9IC5yZXNpZCkpICsNCiAgZ2VvbV9wb2ludCgpICsgbGFicyh0aXRsZSA9ICJSVkYgUGxvdCBmb3IgTWF0aCBTY29yZXMgTW9kZWwiLA0KICAgICAgICAgICAgICAgICAgICAgIHggPSAiUHJlZGljdGVkIFZhbHVlLCBNYXRoIFNjb3JlcyIsDQogICAgICAgICAgICAgICAgICAgICAgeSA9ICJSZXNpZHVhbCBWYWx1ZSIpICsgdGhlbWVfY2xhc3NpYygpDQpgYGANClRoZXJlIGlzIGZ1bm5lbmxpbmcgd2hpY2ggc2hvd3MgdGhhdCB0aGVyZSBpcyBoZXRlcm9za2VkYXN0aWNpdHkuIEkgYWxzbyB0aGluayB0aGVyZSBpcyBhIGN1cnZlIHdoaWNoIGlzIGEgc2lnbiBvZiBub24tbGluZWFyaXR5LiANCg0KDQo0LiAgVXNlIENvb2vigJlzIERpc3RhbmNlIHZhbHVlcyB0byBsb29rIGZvciBwb3RlbnRpYWwgcmVncmVzc2lvbiBvdXRsaWVycy4gSW4gU3RhdGEsIHRoaXMgd2lsbCByZXF1aXJlIHRoZSBtbHQgcGFja2FnZSBhbmQgbWx0Y29va3NkIGNvbW1hbmQuIENyZWF0ZSBhIHBsb3Qgb2YgZml0dGVkIHZhbHVlcyB2cy4gQ29va+KAmXMgZGlzdGFuY2VzIGFuZCBpbnRlcnByZXQuDQpgYGB7cn0NCmdncGxvdChkYXRhID0gZGlhZ25vc3RpY3MsIG1hcHBpbmcgPSBhZXMoeCA9IC5maXR0ZWQsIHkgPSAuY29va3NkLCBsYWJlbCA9IGNsYXNzaWQpKSArDQogIGdlb21fcG9pbnQoKSArIGdlb21fdGV4dChudWRnZV94ID0gLjI1KSArIHRoZW1lX2NsYXNzaWMoKSArIA0KICBsYWJzKHRpdGxlID0gIkNvb2sncyBEaXN0YW5jZSBQbG90IGZvciBDbGFzc3Jvb20gTWF0aCBTY29yZXMgTW9kZWwiLA0KICAgICAgICAgICAgICAgICAgICAgIHggPSAiUHJlZGljdGVkIFZhbHVlLCBNYXRoIFNjb3JlcyIsDQogICAgICAgICAgICAgICAgICAgICAgeSA9ICJDb29rJ3MgRGlzdGFuY2UiKSArIA0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA0LzYzMjUsIGxpbmV0eXBlID0gImRvdHRlZCIpDQpgYGANCg0KSSBjYW4ndCBzZWUgdGhlIGRvdHRlZCBsaW5lIGFuZCB0aGVyZSBpcyBvbmx5IG9uZSBwYXJ0IHdoZXJlIHRoZSBvYnNlcnZhdGlvbnMgZ28gZnJvbSBvbmUgc2lkZSB0byB0aGUgb3RoZXIuIFRoZSBjdXRvZmYgb2YgNC82MzI1IGRvZXMgbm90IHNlZW0gcmVhc29uYWJsZSBiZWNhdXNlIGl0IHdvdWxkIGV4Y2x1ZGUgYSBsYXJnZSBhbW91bnQgb2YgZGF0YS4gVGhlcmUgYXJlIGEgZmV3IG91dGxpZXJzIHRob3VnaCBwZXJoYXBzIGEgY3V0b2ZmIG9mIGEgY29vaydzIGRpc3RhbmNlIG9mIDAuMTAgd291bGQgYmUgZ29vZC4gSXQgaXMgaGFyZCB0byB0ZWxsIGJlY2F1ZSB0aGV5IGFyZSBjbHVtcGVkIHRvZ2V0aGVyLiANCg0KNS4gQ29uZHVjdCBhIHJvYnVzdG5lc3MgY2hlY2sgZm9yIHlvdXIgbW9kZWwgYnkgY29tcGFyaW5nIHlvdXIgb3JpZ2luYWwgbW9kZWwgdG8gMSkgYSBtb2RlbCB3aXRoIHJvYnVzdCBzdGFuZGFyZCBlcnJvcnMsIGFuZCAyKSBhIG1vZGVsIHdpdGggYWxsIENvb2vigJlzIERpc3RhbmNlIG91dGxpZXJzIHJlbW92ZWQuIENyZWF0ZSBhIHN1bW1hcnkgdGFibGUgdG8gc3VtbWFyaXplIHRoZSBlc3RpbWF0ZXMgb2YgYWxsIHRocmVlIG1vZGVscyB0b2dldGhlci4gQXJlIHlvdXIgcmVzdWx0cyByb2J1c3QgdG8gbWlsZCB0byBtb2RlcmF0ZSB2aW9sYXRpb25zIG9mIHRoZSBhc3N1bXB0aW9ucz8gRm9jdXMgb24gdGhlIGVzdGltYXRlIG9mIHRoZSBjbGFzcyB0eXBlIHZhcmlhYmxlIChna2NsYXNzdHlwZSkNCg0KYGBge3J9DQpsaWJyYXJ5KHJvYnVzdGxtbSkNCmBgYA0KYGBge3J9DQptb2RlbC5yb2J1c3QgPC0gcmxtZXIoZ2t0bWF0aHNzIH4gIGdrc2VsZmNvbmNyYXcgKyBna2NsYXNzdHlwZS5mYWMgKyBna3RoaWdoZGVncmVlLmZhYyArICgxfGNsYXNzaWQpLCBSRU1MID0gRkFMU0UsIGRhdGEgPSBjbGVhbi5wcm9qZWN0U1RBUl8xKQ0KDQpgYGANCg0KYGBge3J9DQpzdW1tYXJ5KG1vZGVsLnJvYnVzdCkNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==