For this practical, we will use data from a sample of the Teaching dataset of The Longitudinal Study of Young People in England, 2004-2006 available here.

We will be fitting a series of school value-added models, which are one of the most prominent examples of multilevel models applied in education research.

A traditional school value-added model is a model that attempts to isolate the “school effects” from the inherent variability/heterogeneity of the pupils. It attempts to ascertain what schools add to the progress of their pupils beyond what is expected of them, given their circumstances.



1. Typical workflow setup and data preparation

1.1. Define a working directory

You can use any directory in your computer. As in the example below:

setwd("C:/myfolder")

Remember to download the data to the folder you will define as working directory, as this makes matters easier.

1.2. Load packages

You can always load packages later on, but it is a good practice to load packages at the beginning of the session on the top of your script or R markdown file.

In this practical, we will use the packages haven, lme4 and ggplot2. Remember that if you haven’t installed them before, you need to do so before you call the library function:

install.packages("haven")
install.packages("lme4")
install.packages("ggplot2")
install.packages("dplyr")

Then you load them as such:

library(haven)
library(lme4)
library(ggplot2)
library(dplyr)

1.3. Read in data

You can download the data from the UKDS website. There are two SPSS datasets and we will be using the one named “lsype_15000_final_2011_05_04.sav”.

To read this dataset into R, we need to use the package haven:

ype<-read_sav("lsype_15000_final_2011_05_04.sav")



2. Select variables to use

In England and Wales, the Department for Education (DfE) publishes periodically the so-called performance tables, in which schools are assessed (and classified) according to the progress that their pupils make from one stage to another. Secondary schools are judged on the GCSE results of their pupils and the progress they made since the end of primary, when they sat the KS2 tests.

We will select the variables: pupilid, schoolID, ks2stand (KS2 scores), ks4stand (GCSE scores), gender, fsm and indschool.

For this, we need to use the function select of the dplyr package:

valueadded <- select(ype, pupilid, schoolID, 
                     ks2stand, ks4stand, gender, 
                     fsm) 



3. Analysis

Task 1: Relationship between KS2 and GCSE

Plot the relationship between KS2 and GCSE scores

plot1 <- ggplot(valueadded, aes(x=ks2stand, y=ks4stand)) +
geom_point() + geom_smooth(aes(x=ks2stand, y=ks4stand), method = "lm")

plot1

Question time 1

1.1 What can you observe in the plot?

1.2 How correlated are KS2 and GCSE scores?

cor(valueadded$ks2stand, valueadded$ks4stand, use="comp")
## [1] 0.6714863



Task 2: Empty model

Fit an empty multilevel model of pupils within schools

library(lme4)

We will use the lmer functions, which stands for “linear mixed effects regression”. The basic syntax follows the conventions of most R packages running regression. You specify an outcome regressed ~ on variables. Each variable you add needs to be preceded by a + sign. You specify the data.

Note that we will use ML, not REML. REML is the default in lmer.

Random effects are added within brackets after the fixed effects. 1 indicates that the constant is allowed to vary freely. The random effects are specified like this: (1|level2id). If you want to want random slopes, you specify (1+variable|level2id)

m0<-lmer(ks4stand~1+(1|schoolID), data=valueadded, REML=F)

summary(m0)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: ks4stand ~ 1 + (1 | schoolID)
##    Data: valueadded
## 
##      AIC      BIC   logLik deviance df.resid 
## 111792.8 111815.7 -55893.4 111786.8    15401 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.7751 -0.6241  0.0163  0.6378  4.0338 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  schoolID (Intercept) 24.33    4.932   
##  Residual             75.85    8.709   
## Number of obs: 15404, groups:  schoolID, 657
## 
## Fixed effects:
##             Estimate Std. Error t value
## (Intercept)  -0.1125     0.2057  -0.547

This model is called “type 0” value-added model in the literature

Question time 2

2.1. What is the proportion of variation that lies between schools in the empty model?

2.2. What does that value mean?



Task 3: Value-added model

Fit a model with “prior attainment” as the only covariate. According to the literature this is a “type AA” value-added model. According to the DfE, this is a school value-added model or “VA”

m1<-lmer(ks4stand~ks2stand+(1|schoolID), data=valueadded, REML=F)
summary(m1)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: ks4stand ~ ks2stand + (1 | schoolID)
##    Data: valueadded
## 
##      AIC      BIC   logLik deviance df.resid 
##  94184.3  94214.5 -47088.2  94176.3    14048 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -4.8324 -0.5431  0.0227  0.5858  4.6552 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  schoolID (Intercept)  8.884   2.981   
##  Residual             44.207   6.649   
## Number of obs: 14052, groups:  schoolID, 628
## 
## Fixed effects:
##              Estimate Std. Error t value
## (Intercept) -0.110626   0.132210  -0.837
## ks2stand     0.644306   0.006298 102.298
## 
## Correlation of Fixed Effects:
##          (Intr)
## ks2stand 0.006

Question time 3

3.1. How much variance is “explained” by prior attainment?



Task 4: Contextualised value-added model

Fit a model with all the available level 1 variables. In the literature, this model is called “type AA” value-added. The DfE would this model a “contextualised value-added model” or “CVA”.

m2<-lmer(ks4stand~ks2stand+factor(gender)+factor(fsm)+(1|schoolID), data=valueadded, REML=F)
summary(m2)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: 
## ks4stand ~ ks2stand + factor(gender) + factor(fsm) + (1 | schoolID)
##    Data: valueadded
## 
##      AIC      BIC   logLik deviance df.resid 
##  91571.5  91616.7 -45779.8  91559.5    13740 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -5.0675 -0.5341  0.0103  0.5770  4.8736 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  schoolID (Intercept)  8.984   2.997   
##  Residual             42.304   6.504   
## Number of obs: 13746, groups:  schoolID, 628
## 
## Fixed effects:
##                  Estimate Std. Error t value
## (Intercept)     -0.547500   0.148461  -3.688
## ks2stand         0.622985   0.006357  98.005
## factor(gender)1  1.911990   0.118926  16.077
## factor(fsm)1    -2.271849   0.157245 -14.448
## 
## Correlation of Fixed Effects:
##             (Intr) ks2stn fctr(g)1
## ks2stand    -0.023                
## fctr(gndr)1 -0.394 -0.033         
## factr(fsm)1 -0.215  0.183 -0.005

Question time 4

4.1. How much have the variances (at both levels) reduced?

4.2. What does this mean for the concept of value-added?



Task 5: Differential progress

Question time 5:

5.1. Do male and female pupils have different levels of progress?

m3<-lmer(ks4stand~ks2stand+ks2stand*factor(gender)+factor(gender)+
           factor(fsm)+(1|schoolID), data=valueadded, REML=F)

summary(m3)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: 
## ks4stand ~ ks2stand + ks2stand * factor(gender) + factor(gender) +  
##     factor(fsm) + (1 | schoolID)
##    Data: valueadded
## 
##      AIC      BIC   logLik deviance df.resid 
##  91571.8  91624.5 -45778.9  91557.8    13739 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -5.0469 -0.5340  0.0103  0.5770  4.8719 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  schoolID (Intercept)  8.976   2.996   
##  Residual             42.300   6.504   
## Number of obs: 13746, groups:  schoolID, 628
## 
## Fixed effects:
##                           Estimate Std. Error t value
## (Intercept)              -0.544662   0.148432  -3.669
## ks2stand                  0.630388   0.008533  73.874
## factor(gender)1           1.911635   0.118920  16.075
## factor(fsm)1             -2.272931   0.157238 -14.455
## ks2stand:factor(gender)1 -0.015305   0.011776  -1.300
## 
## Correlation of Fixed Effects:
##             (Intr) ks2stn fctr(g)1 fctr(f)1
## ks2stand    -0.008                         
## fctr(gndr)1 -0.394 -0.026                  
## factr(fsm)1 -0.215  0.133 -0.005           
## ks2stnd:()1 -0.015 -0.667  0.002    0.005

5.2. Do FSM eligible pupils make more or less progress?

m4<-lmer(ks4stand~ks2stand+ks2stand*factor(fsm)+factor(gender)+
           factor(fsm)+(1|schoolID), data=valueadded, REML=F)

summary(m4)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: ks4stand ~ ks2stand + ks2stand * factor(fsm) + factor(gender) +  
##     factor(fsm) + (1 | schoolID)
##    Data: valueadded
## 
##      AIC      BIC   logLik deviance df.resid 
##  91556.1  91608.8 -45771.0  91542.1    13739 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -5.0963 -0.5351  0.0088  0.5752  4.8744 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  schoolID (Intercept)  8.962   2.994   
##  Residual             42.253   6.500   
## Number of obs: 13746, groups:  schoolID, 628
## 
## Fixed effects:
##                       Estimate Std. Error t value
## (Intercept)           -0.56386    0.14836  -3.801
## ks2stand               0.63557    0.00703  90.410
## factor(fsm)1          -2.51428    0.16752 -15.009
## factor(gender)1        1.91338    0.11885  16.099
## ks2stand:factor(fsm)1 -0.06332    0.01516  -4.178
## 
## Correlation of Fixed Effects:
##             (Intr) ks2stn fctr(f)1 fctr(g)1
## ks2stand    -0.033                         
## factr(fsm)1 -0.193  0.007                  
## fctr(gndr)1 -0.394 -0.028 -0.005           
## ks2stnd:()1  0.026 -0.428  0.346   -0.003



Task 6: School-level variables

One of the strengths of MLM is that we can evaluate the effect of multiple variables at different levels on the outcome of interest. Adding higher-level variables is done in the same way as any other individual-level variable.

We can easily create a new school-level variable from the dataset we have if we aggregate pupil-level data. The code below uses the function mutate of the dplyr package to create a new variable that represents the percentage of pupils eligible for free school meals in each school:

valueadded <- valueadded %>%
  group_by(schoolID) %>%
  mutate(schoolfsm=mean(fsm, na.rm=T)*100)

You can inspect the results by clicking on the object valueadded that is in your Environment tab.

After that, we’re ready to fit the model with schoolfsm.

m5<-lmer(ks4stand ~ ks2stand + schoolfsm + (1|schoolID), data=valueadded, REML=F)

summary(m5)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: ks4stand ~ ks2stand + schoolfsm + (1 | schoolID)
##    Data: valueadded
## 
##      AIC      BIC   logLik deviance df.resid 
##  94182.1  94219.8 -47086.0  94172.1    14047 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -4.8302 -0.5454  0.0223  0.5870  4.6542 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  schoolID (Intercept)  8.832   2.972   
##  Residual             44.203   6.649   
## Number of obs: 14052, groups:  schoolID, 628
## 
## Fixed effects:
##              Estimate Std. Error t value
## (Intercept)  0.191653   0.196889   0.973
## ks2stand     0.642585   0.006354 101.130
## schoolfsm   -0.014478   0.007003  -2.067
## 
## Correlation of Fixed Effects:
##           (Intr) ks2stn
## ks2stand  -0.095       
## schoolfsm -0.742  0.133

Question time 6:

6.1. What is the effect of the percentage of FSM eligible pupils on GCSE scores?



Task 7: School-specific VA estimates

Plotting the higher-level residuals can be helpful to identify groups that have higher or lower than average effect on the individual-level outcome. In the case of school performance, the residuals can be thought of as the effect uniquely attributable to the school on the progress of their pupils.

To plot the residuals with this purpose, we can use a “caterpillar plot”.

u0 <- ranef(m1, condVar = TRUE) # These are the residuals from model "m1"

u0se <- sqrt(attr(u0[[1]], "postVar")[1,,]) # These are the standard errors of the residuals

schoolid <- as.numeric(rownames(u0[[1]])) # This is to create school identifiers

You will there are three additional objects in your environment. To put them together in one dataset, we do the following:

school_resid <- cbind(schoolid, u0[[1]], u0se)

colnames(school_resid) <- c("schoolid","u0","u0se")

# Then we sort the residuals in ascending order:

school_resid <- school_resid[order(school_resid$u0), ] 

# And we create a new column (variable) containing the ranks:

school_resid <- cbind(school_resid, c(1:dim(school_resid)[1]))

colnames(school_resid)[4] <- "u0rank" # This is to give a name to the new column containing the ranks

After all this, we end up with a new dataset school_resid containing the school value-added estimates. We can plot with ggplot2 as such:

school_VA_plot <- ggplot(school_resid, aes(x=u0rank, y=u0)) + 
  geom_point(stat="identity") +
  geom_errorbar(aes(ymin=u0-1.96*u0se, ymax=u0+1.96*u0se)) +
  geom_hline(yintercept=0,size=1.2, alpha=0.7,colour="#EF3B2C", linetype="twodash") +
  xlab("Rank of residuals") +
  ylab("School VA estimates") +
  theme_bw()

school_VA_plot

In the plot above, the red line at y=0 represents the overall national average. Each school is represented by a point and a vertical segment, which represent the average school-specific effect and its 95% confidence interval (respectively). Schools on the left-hand side of the distribution that do not overlap with the national average line are said to be “significantly underperforming”; whereas those on the right-hand side that do not overlap the red line are “significantly overperforming”. All schools that do overlap are those that can be thought of as “performing as expected”.

NB: This is not the only tool to make such judgements about school performance; a comprehensive accountability system would involve also school inspections and qualitative judgements.



Bonus track

You could plot predictions for each school:

valueadded2<-filter(valueadded, !is.na(ks4stand) & !is.na(ks2stand)) # this filter is necessary to avoid issues with missing values

valueadded2$pred<-fitted(m1)

school_plot<-ggplot(valueadded2, aes(x=ks2stand, y=pred, group=factor(schoolID))) + 
  geom_smooth(method="lm", colour="black") +
  xlab("Standardised KS2 score") +
  ylab("Predicted KS4 score") +
  theme_bw()

school_plot

In the plot above, each line represents a school. As you can see, there is a lot of variability across schools.In this plot, school predicted lines are parallel because we haven’t allowed the effect of KS2 scores to vary across schools; this is a random intercepts model. You can compare this plot with the first plot we did above, where the single-level regression line was clearly not enough to represent the extreme variability in scores. The multilevel model can account for that variability across schools and hence the multiple regression lines seen here are a much better representation of the observed data.

To visualise non-parallel school predicted lines, i.e. varying slopes, we need to fit a model that allows the effect of KS2 to vary across schools. To fit a random slopes model, we run the following code:

m1_rs<-lmer(ks4stand~as.vector(scale(ks2stand))+
              (1+as.vector(scale(ks2stand))|schoolID), data=valueadded, REML=F)

# Note that KS2 have been added like this "as.vector(scale(ks2stand))". This is done to prevent a convergence error. The function "scale" rescales KS2 scores to units of standard deviation.

summary(m1_rs)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: 
## ks4stand ~ as.vector(scale(ks2stand)) + (1 + as.vector(scale(ks2stand)) |  
##     schoolID)
##    Data: valueadded
## 
##      AIC      BIC   logLik deviance df.resid 
##  94083.5  94128.8 -47035.7  94071.5    14046 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -4.9474 -0.5315  0.0255  0.5764  4.5486 
## 
## Random effects:
##  Groups   Name                       Variance Std.Dev. Corr
##  schoolID (Intercept)                 8.964   2.994        
##           as.vector(scale(ks2stand))  1.295   1.138    0.50
##  Residual                            43.160   6.570        
## Number of obs: 14052, groups:  schoolID, 628
## 
## Fixed effects:
##                            Estimate Std. Error t value
## (Intercept)                -0.11737    0.13375  -0.877
## as.vector(scale(ks2stand))  6.42098    0.07797  82.353
## 
## Correlation of Fixed Effects:
##             (Intr)
## as.vct((2)) 0.282

To compare the random intercepts models with the random slopes model, we can run the following code:

anova(m1, m1_rs)
## Data: valueadded
## Models:
## m1: ks4stand ~ ks2stand + (1 | schoolID)
## m1_rs: ks4stand ~ as.vector(scale(ks2stand)) + (1 + as.vector(scale(ks2stand)) | 
## m1_rs:     schoolID)
##       Df   AIC   BIC logLik deviance  Chisq Chi Df Pr(>Chisq)    
## m1     4 94184 94215 -47088    94176                             
## m1_rs  6 94083 94129 -47036    94071 104.87      2  < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

The results indicate that, even though more complex (2 extra parameters), the random slopes model has a significantly better fit than the random intercepts model.

To plot the school predicted lines, we can retrieve the fitted values from the model m1_rs, as such:

valueadded2$pred_rs<-fitted(m1_rs)

Then we can simply copy the code from the previous plot, replacing m1 for m1_rs:

school_plot_rs<-ggplot(valueadded2, aes(x=ks2stand, y=pred_rs, group=factor(schoolID))) + 
  geom_smooth(method="lm", colour="black") +
  xlab("Standardised KS2 score") +
  ylab("Predicted KS4 score") +
  theme_bw()

school_plot_rs

Voilà! School predicted scores have varying slopes for the relationship between KS2 and GCSE scores. You can see that pupils in some schools make more progress than others on average and some make less.


You can also plot the higher-level (school) residuals to check for normality

hist(school_resid$u0)

You can also plot individual-level to check for normality

valueadded2$ind_resid <- residuals(m1)

hist(valueadded2$ind_resid)

And finally, you can plot individual-level residuals against the predicted values (previously retrieved):

homoscedasticity <- ggplot(valueadded2, aes(y = ind_resid, x = pred)) + geom_point()

homoscedasticity



Final comments

Multilevel modelling can be used for so much more than modelling educational outcomes of pupils nested within schools. It can also be used to understand variation across time within individuals; variation between prisoners nested within prisons; variation in income for individuals nested within geographical areas; variation in health outcomes of patients nested within GP practices and hospitals; and so many other examples.

Here are some applications that you may want to explore:

a) About school value-added models:

b) About prison effects:

c) General multilevel modelling books:

  • Goldstein, H. (2011). Multilevel statistical models (4th ed.). John Wiley and Sons

  • Hox, J., Moerbeek, M., van de Schoot, R. (2017). Multilevel Analysis: Techniques and Applications (3rd Ed). Routledge

  • Snijders, T., Bosker, R. (2012). Multilevel Analysis: An Introduction to Basic and Advanced Multilevel Modeling (2nd ed.). Sage


HIGHLY RECOMMENDED: For a more complete (and free) course on Multilevel Modelling, visit the LEMMA website of the University of Bristol.



Once you see multilevel structures in your data, you cannot unsee them…

 -'I see MLMs!' (via Giphy)

-‘I see MLMs!’ (via Giphy)

LS0tDQp0aXRsZTogIk1MTSBpbiBwcmFjdGljZTogU2Nob29sIHZhbHVlLWFkZGVkIG1vZGVscyINCmF1dGhvcjogIlBhdHJpY2lvIFRyb25jb3NvIg0KZGF0ZTogIkxhdGVzdCB1cGRhdGU6IE1hcmNoIDIwMjAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGhpZ2hsaWdodGVyOiBudWxsDQogICAgdGhlbWU6IGNvc21vDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIGZvbnRzaXplOiAxMnB0DQogICAgaW5jbHVkZXM6IA0KICAgICAgaW5faGVhZGVyOiBoZWFkZXIuaHRtbA0KICAgICAgYWZ0ZXJfYm9keTogZm9vdGVyLmh0bWwNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQoNCkZvciB0aGlzIHByYWN0aWNhbCwgd2Ugd2lsbCB1c2UgZGF0YSBmcm9tIGEgc2FtcGxlIG9mIHRoZSBUZWFjaGluZyBkYXRhc2V0IG9mIFRoZSBMb25naXR1ZGluYWwgU3R1ZHkgb2YgWW91bmcgUGVvcGxlIGluIEVuZ2xhbmQsIDIwMDQtMjAwNg0KYXZhaWxhYmxlIFsqKmhlcmUqKl0oaHR0cHM6Ly9iZXRhLnVrZGF0YXNlcnZpY2UuYWMudWsvZGF0YWNhdGFsb2d1ZS9zdHVkaWVzL3N0dWR5P2lkPTY2NjApLg0KDQpXZSB3aWxsIGJlIGZpdHRpbmcgYSBzZXJpZXMgb2Ygc2Nob29sIHZhbHVlLWFkZGVkIG1vZGVscywgd2hpY2ggYXJlIG9uZSBvZiB0aGUgbW9zdCBwcm9taW5lbnQgZXhhbXBsZXMgb2YgbXVsdGlsZXZlbCBtb2RlbHMgYXBwbGllZCBpbiBlZHVjYXRpb24gcmVzZWFyY2guDQoNCkEgdHJhZGl0aW9uYWwgc2Nob29sIHZhbHVlLWFkZGVkIG1vZGVsIGlzIGEgbW9kZWwgdGhhdCBhdHRlbXB0cyB0byBpc29sYXRlIHRoZSAic2Nob29sIGVmZmVjdHMiIGZyb20gdGhlIGluaGVyZW50IHZhcmlhYmlsaXR5L2hldGVyb2dlbmVpdHkgb2YgdGhlIHB1cGlscy4gSXQgYXR0ZW1wdHMgdG8gYXNjZXJ0YWluIHdoYXQgc2Nob29scyBhZGQgdG8gdGhlIHByb2dyZXNzIG9mIHRoZWlyIHB1cGlscyBiZXlvbmQgd2hhdCBpcyBleHBlY3RlZCBvZiB0aGVtLCBnaXZlbiB0aGVpciBjaXJjdW1zdGFuY2VzLg0KDQo8YnI+DQoNCioqKg0KDQojIDEuIFR5cGljYWwgd29ya2Zsb3cgc2V0dXAgYW5kIGRhdGEgcHJlcGFyYXRpb24NCg0KIyMgMS4xLiBEZWZpbmUgYSB3b3JraW5nIGRpcmVjdG9yeQ0KDQpZb3UgY2FuIHVzZSBhbnkgZGlyZWN0b3J5IGluIHlvdXIgY29tcHV0ZXIuIEFzIGluIHRoZSBleGFtcGxlIGJlbG93Og0KDQpgYGB7ciwgZXZhbD1GfQ0Kc2V0d2QoIkM6L215Zm9sZGVyIikNCmBgYA0KDQpSZW1lbWJlciB0byBkb3dubG9hZCB0aGUgZGF0YSB0byB0aGUgZm9sZGVyIHlvdSB3aWxsIGRlZmluZSBhcyB3b3JraW5nIGRpcmVjdG9yeSwgYXMgdGhpcyBtYWtlcyBtYXR0ZXJzIGVhc2llci4NCg0KIyMgMS4yLiBMb2FkIHBhY2thZ2VzDQoNCllvdSBjYW4gYWx3YXlzIGxvYWQgcGFja2FnZXMgbGF0ZXIgb24sIGJ1dCBpdCBpcyBhIGdvb2QgcHJhY3RpY2UgdG8gbG9hZCBwYWNrYWdlcyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzZXNzaW9uIG9uIHRoZSB0b3Agb2YgeW91ciBzY3JpcHQgb3IgUiBtYXJrZG93biBmaWxlLg0KDQpJbiB0aGlzIHByYWN0aWNhbCwgd2Ugd2lsbCB1c2UgdGhlIHBhY2thZ2VzIGBoYXZlbmAsIGBsbWU0YCBhbmQgYGdncGxvdDJgLiBSZW1lbWJlciB0aGF0IGlmIHlvdSBoYXZlbid0IGluc3RhbGxlZCB0aGVtIGJlZm9yZSwgeW91IG5lZWQgdG8gZG8gc28gYmVmb3JlIHlvdSBjYWxsIHRoZSBgbGlicmFyeWAgZnVuY3Rpb246DQoNCmBgYHt9DQppbnN0YWxsLnBhY2thZ2VzKCJoYXZlbiIpDQppbnN0YWxsLnBhY2thZ2VzKCJsbWU0IikNCmluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQ0KYGBgDQoNClRoZW4geW91IGxvYWQgdGhlbSBhcyBzdWNoOg0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQpsaWJyYXJ5KGhhdmVuKQ0KbGlicmFyeShsbWU0KQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShkcGx5cikNCmBgYA0KDQojIyAxLjMuIFJlYWQgaW4gZGF0YSANCg0KWW91IGNhbiBkb3dubG9hZCB0aGUgZGF0YSBmcm9tIHRoZSBbKipVS0RTIHdlYnNpdGUqKl0oaHR0cHM6Ly9iZXRhLnVrZGF0YXNlcnZpY2UuYWMudWsvZGF0YWNhdGFsb2d1ZS9zdHVkaWVzL3N0dWR5P2lkPTY2NjApLiBUaGVyZSBhcmUgdHdvIFNQU1MgZGF0YXNldHMgYW5kIHdlIHdpbGwgYmUgdXNpbmcgdGhlIG9uZSBuYW1lZCAibHN5cGVfMTUwMDBfZmluYWxfMjAxMV8wNV8wNC5zYXYiLg0KDQpUbyByZWFkIHRoaXMgZGF0YXNldCBpbnRvIFIsIHdlIG5lZWQgdG8gdXNlIHRoZSBwYWNrYWdlIGBoYXZlbmA6DQoNCg0KYGBge3IsIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQ0KeXBlPC1yZWFkX3NhdigibHN5cGVfMTUwMDBfZmluYWxfMjAxMV8wNV8wNC5zYXYiKQ0KYGBgDQoNCjxicj4NCg0KKioqDQoNCiMgMi4gU2VsZWN0IHZhcmlhYmxlcyB0byB1c2UNCg0KSW4gRW5nbGFuZCBhbmQgV2FsZXMsIHRoZSBEZXBhcnRtZW50IGZvciBFZHVjYXRpb24gKERmRSkgcHVibGlzaGVzIHBlcmlvZGljYWxseSB0aGUgc28tY2FsbGVkIHBlcmZvcm1hbmNlIHRhYmxlcywgaW4gd2hpY2ggc2Nob29scyBhcmUgYXNzZXNzZWQgKGFuZCBjbGFzc2lmaWVkKSBhY2NvcmRpbmcgdG8gdGhlIHByb2dyZXNzIHRoYXQgdGhlaXIgcHVwaWxzIG1ha2UgZnJvbSBvbmUgc3RhZ2UgdG8gYW5vdGhlci4gU2Vjb25kYXJ5IHNjaG9vbHMgYXJlIGp1ZGdlZCBvbiB0aGUgR0NTRSByZXN1bHRzIG9mIHRoZWlyIHB1cGlscyBhbmQgdGhlIHByb2dyZXNzIHRoZXkgbWFkZSBzaW5jZSB0aGUgZW5kIG9mIHByaW1hcnksIHdoZW4gdGhleSBzYXQgdGhlIEtTMiB0ZXN0cy4NCg0KV2Ugd2lsbCBzZWxlY3QgdGhlIHZhcmlhYmxlczogcHVwaWxpZCwgc2Nob29sSUQsIGtzMnN0YW5kIChLUzIgc2NvcmVzKSwga3M0c3RhbmQgKEdDU0Ugc2NvcmVzKSwgZ2VuZGVyLCBmc20gYW5kIGluZHNjaG9vbC4NCg0KRm9yIHRoaXMsIHdlIG5lZWQgdG8gdXNlIHRoZSBmdW5jdGlvbiBgc2VsZWN0YCBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlOg0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQoNCnZhbHVlYWRkZWQgPC0gc2VsZWN0KHlwZSwgcHVwaWxpZCwgc2Nob29sSUQsIA0KICAgICAgICAgICAgICAgICAgICAga3Myc3RhbmQsIGtzNHN0YW5kLCBnZW5kZXIsIA0KICAgICAgICAgICAgICAgICAgICAgZnNtKSANCg0KYGBgDQoNCjxicj4NCg0KKioqDQoNCiMgMy4gQW5hbHlzaXMNCg0KIyMgVGFzayAxOiBSZWxhdGlvbnNoaXAgYmV0d2VlbiBLUzIgYW5kIEdDU0UNCg0KUGxvdCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gS1MyIGFuZCBHQ1NFIHNjb3Jlcw0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQoNCnBsb3QxIDwtIGdncGxvdCh2YWx1ZWFkZGVkLCBhZXMoeD1rczJzdGFuZCwgeT1rczRzdGFuZCkpICsNCmdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKGFlcyh4PWtzMnN0YW5kLCB5PWtzNHN0YW5kKSwgbWV0aG9kID0gImxtIikNCg0KcGxvdDENCg0KYGBgDQoNCiMjIyBRdWVzdGlvbiB0aW1lIDENCg0KMS4xIFdoYXQgY2FuIHlvdSBvYnNlcnZlIGluIHRoZSBwbG90Pw0KDQoxLjIgSG93IGNvcnJlbGF0ZWQgYXJlIEtTMiBhbmQgR0NTRSBzY29yZXM/DQoNCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0NCmNvcih2YWx1ZWFkZGVkJGtzMnN0YW5kLCB2YWx1ZWFkZGVkJGtzNHN0YW5kLCB1c2U9ImNvbXAiKQ0KYGBgDQoNCjxicj4NCg0KKioqDQoNCiMjIFRhc2sgMjogRW1wdHkgbW9kZWwNCg0KRml0IGFuIGVtcHR5IG11bHRpbGV2ZWwgbW9kZWwgb2YgcHVwaWxzIHdpdGhpbiBzY2hvb2xzDQoNCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0NCmxpYnJhcnkobG1lNCkNCmBgYA0KDQpXZSB3aWxsIHVzZSB0aGUgYGxtZXJgIGZ1bmN0aW9ucywgd2hpY2ggc3RhbmRzIGZvciAibGluZWFyIG1peGVkIGVmZmVjdHMgcmVncmVzc2lvbiIuDQpUaGUgYmFzaWMgc3ludGF4IGZvbGxvd3MgdGhlIGNvbnZlbnRpb25zIG9mIG1vc3QgUiBwYWNrYWdlcyBydW5uaW5nIHJlZ3Jlc3Npb24uIFlvdSBzcGVjaWZ5IGFuIG91dGNvbWUgcmVncmVzc2VkIGB+YCBvbiB2YXJpYWJsZXMuIEVhY2ggdmFyaWFibGUgeW91IGFkZCBuZWVkcyB0byBiZSBwcmVjZWRlZCBieSBhIGArYCBzaWduLiBZb3Ugc3BlY2lmeSB0aGUgZGF0YS4NCg0KTm90ZSB0aGF0IHdlIHdpbGwgdXNlIE1MLCBub3QgUkVNTC4gUkVNTCBpcyB0aGUgZGVmYXVsdCBpbiBsbWVyLg0KDQpSYW5kb20gZWZmZWN0cyBhcmUgYWRkZWQgd2l0aGluIGJyYWNrZXRzIGFmdGVyIHRoZSBmaXhlZCBlZmZlY3RzLiBgMWAgaW5kaWNhdGVzIHRoYXQgdGhlIGNvbnN0YW50IGlzIGFsbG93ZWQgdG8gdmFyeSBmcmVlbHkuIFRoZSByYW5kb20gZWZmZWN0cyBhcmUgc3BlY2lmaWVkIGxpa2UgdGhpczogYCgxfGxldmVsMmlkKWAuIElmIHlvdSB3YW50IHRvIHdhbnQgcmFuZG9tIHNsb3BlcywgeW91IHNwZWNpZnkgYCgxK3ZhcmlhYmxlfGxldmVsMmlkKWANCg0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQoNCm0wPC1sbWVyKGtzNHN0YW5kfjErKDF8c2Nob29sSUQpLCBkYXRhPXZhbHVlYWRkZWQsIFJFTUw9RikNCg0Kc3VtbWFyeShtMCkNCg0KYGBgDQoNClRoaXMgbW9kZWwgaXMgY2FsbGVkICJ0eXBlIDAiIHZhbHVlLWFkZGVkIG1vZGVsIGluIHRoZSBsaXRlcmF0dXJlDQoNCiMjIyBRdWVzdGlvbiB0aW1lIDINCg0KMi4xLiBXaGF0IGlzIHRoZSBwcm9wb3J0aW9uIG9mIHZhcmlhdGlvbiB0aGF0IGxpZXMgYmV0d2VlbiBzY2hvb2xzIGluIHRoZSBlbXB0eSBtb2RlbD8NCg0KMi4yLiBXaGF0IGRvZXMgdGhhdCB2YWx1ZSBtZWFuPw0KDQo8YnI+DQoNCioqKg0KDQojIyBUYXNrIDM6IFZhbHVlLWFkZGVkIG1vZGVsDQoNCkZpdCBhIG1vZGVsIHdpdGggInByaW9yIGF0dGFpbm1lbnQiIGFzIHRoZSBvbmx5IGNvdmFyaWF0ZS4gQWNjb3JkaW5nIHRvIHRoZSBsaXRlcmF0dXJlIHRoaXMgaXMgYSAidHlwZSBBQSIgdmFsdWUtYWRkZWQgbW9kZWwuIEFjY29yZGluZyB0byB0aGUgRGZFLCB0aGlzIGlzIGEgc2Nob29sIHZhbHVlLWFkZGVkIG1vZGVsIG9yICJWQSINCg0KYGBge3IsIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQ0KDQptMTwtbG1lcihrczRzdGFuZH5rczJzdGFuZCsoMXxzY2hvb2xJRCksIGRhdGE9dmFsdWVhZGRlZCwgUkVNTD1GKQ0Kc3VtbWFyeShtMSkNCmBgYA0KDQojIyMgUXVlc3Rpb24gdGltZSAzDQoNCjMuMS4gSG93IG11Y2ggdmFyaWFuY2UgaXMgImV4cGxhaW5lZCIgYnkgcHJpb3IgYXR0YWlubWVudD8NCg0KPGJyPg0KDQoqKioNCg0KIyMgVGFzayA0OiBDb250ZXh0dWFsaXNlZCB2YWx1ZS1hZGRlZCBtb2RlbA0KDQpGaXQgYSBtb2RlbCB3aXRoIGFsbCB0aGUgYXZhaWxhYmxlIGxldmVsIDEgdmFyaWFibGVzLiBJbiB0aGUgbGl0ZXJhdHVyZSwgdGhpcyBtb2RlbCBpcyBjYWxsZWQgInR5cGUgQUEiIHZhbHVlLWFkZGVkLiBUaGUgRGZFIHdvdWxkIHRoaXMgbW9kZWwgYSAiY29udGV4dHVhbGlzZWQgdmFsdWUtYWRkZWQgbW9kZWwiIG9yICJDVkEiLg0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQoNCm0yPC1sbWVyKGtzNHN0YW5kfmtzMnN0YW5kK2ZhY3RvcihnZW5kZXIpK2ZhY3Rvcihmc20pKygxfHNjaG9vbElEKSwgZGF0YT12YWx1ZWFkZGVkLCBSRU1MPUYpDQpzdW1tYXJ5KG0yKQ0KYGBgDQoNCiMjIyBRdWVzdGlvbiB0aW1lIDQNCg0KNC4xLiBIb3cgbXVjaCBoYXZlIHRoZSB2YXJpYW5jZXMgKGF0IGJvdGggbGV2ZWxzKSByZWR1Y2VkPw0KDQo0LjIuIFdoYXQgZG9lcyB0aGlzIG1lYW4gZm9yIHRoZSBjb25jZXB0IG9mIHZhbHVlLWFkZGVkPw0KDQo8YnI+DQoNCioqKg0KDQojIyBUYXNrIDU6IERpZmZlcmVudGlhbCBwcm9ncmVzcw0KDQojIyMgUXVlc3Rpb24gdGltZSA1Og0KDQo1LjEuIERvIG1hbGUgYW5kIGZlbWFsZSBwdXBpbHMgaGF2ZSBkaWZmZXJlbnQgbGV2ZWxzIG9mIHByb2dyZXNzPw0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQptMzwtbG1lcihrczRzdGFuZH5rczJzdGFuZCtrczJzdGFuZCpmYWN0b3IoZ2VuZGVyKStmYWN0b3IoZ2VuZGVyKSsNCiAgICAgICAgICAgZmFjdG9yKGZzbSkrKDF8c2Nob29sSUQpLCBkYXRhPXZhbHVlYWRkZWQsIFJFTUw9RikNCg0Kc3VtbWFyeShtMykNCmBgYA0KDQo1LjIuIERvIEZTTSBlbGlnaWJsZSBwdXBpbHMgbWFrZSBtb3JlIG9yIGxlc3MgcHJvZ3Jlc3M/DQoNCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0NCm00PC1sbWVyKGtzNHN0YW5kfmtzMnN0YW5kK2tzMnN0YW5kKmZhY3Rvcihmc20pK2ZhY3RvcihnZW5kZXIpKw0KICAgICAgICAgICBmYWN0b3IoZnNtKSsoMXxzY2hvb2xJRCksIGRhdGE9dmFsdWVhZGRlZCwgUkVNTD1GKQ0KDQpzdW1tYXJ5KG00KQ0KYGBgDQoNCjxicj4NCg0KKioqDQoNCiMjIFRhc2sgNjogU2Nob29sLWxldmVsIHZhcmlhYmxlcw0KDQpPbmUgb2YgdGhlIHN0cmVuZ3RocyBvZiBNTE0gaXMgdGhhdCB3ZSBjYW4gZXZhbHVhdGUgdGhlIGVmZmVjdCBvZiBtdWx0aXBsZSB2YXJpYWJsZXMgYXQgZGlmZmVyZW50IGxldmVscyBvbiB0aGUgb3V0Y29tZSBvZiBpbnRlcmVzdC4gQWRkaW5nIGhpZ2hlci1sZXZlbCB2YXJpYWJsZXMgaXMgZG9uZSBpbiB0aGUgc2FtZSB3YXkgYXMgYW55IG90aGVyIGluZGl2aWR1YWwtbGV2ZWwgdmFyaWFibGUuDQoNCldlIGNhbiBlYXNpbHkgY3JlYXRlIGEgbmV3IHNjaG9vbC1sZXZlbCB2YXJpYWJsZSBmcm9tIHRoZSBkYXRhc2V0IHdlIGhhdmUgaWYgd2UgYWdncmVnYXRlIHB1cGlsLWxldmVsIGRhdGEuIFRoZSBjb2RlIGJlbG93IHVzZXMgdGhlIGZ1bmN0aW9uIGBtdXRhdGVgIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gY3JlYXRlIGEgbmV3IHZhcmlhYmxlIHRoYXQgcmVwcmVzZW50cyB0aGUgcGVyY2VudGFnZSBvZiBwdXBpbHMgZWxpZ2libGUgZm9yIGZyZWUgc2Nob29sIG1lYWxzIGluIGVhY2ggc2Nob29sOg0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQp2YWx1ZWFkZGVkIDwtIHZhbHVlYWRkZWQgJT4lDQogIGdyb3VwX2J5KHNjaG9vbElEKSAlPiUNCiAgbXV0YXRlKHNjaG9vbGZzbT1tZWFuKGZzbSwgbmEucm09VCkqMTAwKQ0KYGBgDQoNCllvdSBjYW4gaW5zcGVjdCB0aGUgcmVzdWx0cyBieSBjbGlja2luZyBvbiB0aGUgb2JqZWN0IGB2YWx1ZWFkZGVkYCB0aGF0IGlzIGluIHlvdXIgRW52aXJvbm1lbnQgdGFiLg0KDQpBZnRlciB0aGF0LCB3ZSdyZSByZWFkeSB0byBmaXQgdGhlIG1vZGVsIHdpdGggYHNjaG9vbGZzbWAuDQoNCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0NCm01PC1sbWVyKGtzNHN0YW5kIH4ga3Myc3RhbmQgKyBzY2hvb2xmc20gKyAoMXxzY2hvb2xJRCksIGRhdGE9dmFsdWVhZGRlZCwgUkVNTD1GKQ0KDQpzdW1tYXJ5KG01KQ0KYGBgDQoNCiMjIyBRdWVzdGlvbiB0aW1lIDY6DQoNCjYuMS4gV2hhdCBpcyB0aGUgZWZmZWN0IG9mIHRoZSBwZXJjZW50YWdlIG9mIEZTTSBlbGlnaWJsZSBwdXBpbHMgb24gR0NTRSBzY29yZXM/DQoNCjxicj4NCg0KKioqDQoNCiMjIFRhc2sgNzogU2Nob29sLXNwZWNpZmljIFZBIGVzdGltYXRlcw0KDQpQbG90dGluZyB0aGUgaGlnaGVyLWxldmVsIHJlc2lkdWFscyBjYW4gYmUgaGVscGZ1bCB0byBpZGVudGlmeSBncm91cHMgdGhhdCBoYXZlIGhpZ2hlciBvciBsb3dlciB0aGFuIGF2ZXJhZ2UgZWZmZWN0IG9uIHRoZSBpbmRpdmlkdWFsLWxldmVsIG91dGNvbWUuIEluIHRoZSBjYXNlIG9mIHNjaG9vbCBwZXJmb3JtYW5jZSwgdGhlIHJlc2lkdWFscyBjYW4gYmUgdGhvdWdodCBvZiBhcyB0aGUgZWZmZWN0IHVuaXF1ZWx5IGF0dHJpYnV0YWJsZSB0byB0aGUgc2Nob29sIG9uIHRoZSBwcm9ncmVzcyBvZiB0aGVpciBwdXBpbHMuDQoNClRvIHBsb3QgdGhlIHJlc2lkdWFscyB3aXRoIHRoaXMgcHVycG9zZSwgd2UgY2FuIHVzZSBhICJjYXRlcnBpbGxhciBwbG90Ii4NCg0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQoNCnUwIDwtIHJhbmVmKG0xLCBjb25kVmFyID0gVFJVRSkgIyBUaGVzZSBhcmUgdGhlIHJlc2lkdWFscyBmcm9tIG1vZGVsICJtMSINCg0KdTBzZSA8LSBzcXJ0KGF0dHIodTBbWzFdXSwgInBvc3RWYXIiKVsxLCxdKSAjIFRoZXNlIGFyZSB0aGUgc3RhbmRhcmQgZXJyb3JzIG9mIHRoZSByZXNpZHVhbHMNCg0Kc2Nob29saWQgPC0gYXMubnVtZXJpYyhyb3duYW1lcyh1MFtbMV1dKSkgIyBUaGlzIGlzIHRvIGNyZWF0ZSBzY2hvb2wgaWRlbnRpZmllcnMNCmBgYA0KDQpZb3Ugd2lsbCB0aGVyZSBhcmUgdGhyZWUgYWRkaXRpb25hbCBvYmplY3RzIGluIHlvdXIgZW52aXJvbm1lbnQuIFRvIHB1dCB0aGVtIHRvZ2V0aGVyIGluIG9uZSBkYXRhc2V0LCB3ZSBkbyB0aGUgZm9sbG93aW5nOg0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQoNCnNjaG9vbF9yZXNpZCA8LSBjYmluZChzY2hvb2xpZCwgdTBbWzFdXSwgdTBzZSkNCg0KY29sbmFtZXMoc2Nob29sX3Jlc2lkKSA8LSBjKCJzY2hvb2xpZCIsInUwIiwidTBzZSIpDQoNCiMgVGhlbiB3ZSBzb3J0IHRoZSByZXNpZHVhbHMgaW4gYXNjZW5kaW5nIG9yZGVyOg0KDQpzY2hvb2xfcmVzaWQgPC0gc2Nob29sX3Jlc2lkW29yZGVyKHNjaG9vbF9yZXNpZCR1MCksIF0gDQoNCiMgQW5kIHdlIGNyZWF0ZSBhIG5ldyBjb2x1bW4gKHZhcmlhYmxlKSBjb250YWluaW5nIHRoZSByYW5rczoNCg0Kc2Nob29sX3Jlc2lkIDwtIGNiaW5kKHNjaG9vbF9yZXNpZCwgYygxOmRpbShzY2hvb2xfcmVzaWQpWzFdKSkNCg0KY29sbmFtZXMoc2Nob29sX3Jlc2lkKVs0XSA8LSAidTByYW5rIiAjIFRoaXMgaXMgdG8gZ2l2ZSBhIG5hbWUgdG8gdGhlIG5ldyBjb2x1bW4gY29udGFpbmluZyB0aGUgcmFua3MNCmBgYA0KDQpBZnRlciBhbGwgdGhpcywgd2UgZW5kIHVwIHdpdGggYSBuZXcgZGF0YXNldCBgc2Nob29sX3Jlc2lkYCBjb250YWluaW5nIHRoZSBzY2hvb2wgdmFsdWUtYWRkZWQgZXN0aW1hdGVzLiBXZSBjYW4gcGxvdCB3aXRoIGBnZ3Bsb3QyYCBhcyBzdWNoOg0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQpzY2hvb2xfVkFfcGxvdCA8LSBnZ3Bsb3Qoc2Nob29sX3Jlc2lkLCBhZXMoeD11MHJhbmssIHk9dTApKSArIA0KICBnZW9tX3BvaW50KHN0YXQ9ImlkZW50aXR5IikgKw0KICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPXUwLTEuOTYqdTBzZSwgeW1heD11MCsxLjk2KnUwc2UpKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdD0wLHNpemU9MS4yLCBhbHBoYT0wLjcsY29sb3VyPSIjRUYzQjJDIiwgbGluZXR5cGU9InR3b2Rhc2giKSArDQogIHhsYWIoIlJhbmsgb2YgcmVzaWR1YWxzIikgKw0KICB5bGFiKCJTY2hvb2wgVkEgZXN0aW1hdGVzIikgKw0KICB0aGVtZV9idygpDQoNCnNjaG9vbF9WQV9wbG90DQoNCmBgYA0KDQpJbiB0aGUgcGxvdCBhYm92ZSwgdGhlIHJlZCBsaW5lIGF0IGB5PTBgIHJlcHJlc2VudHMgdGhlIG92ZXJhbGwgbmF0aW9uYWwgYXZlcmFnZS4gRWFjaCBzY2hvb2wgaXMgcmVwcmVzZW50ZWQgYnkgYSBwb2ludCBhbmQgYSB2ZXJ0aWNhbCBzZWdtZW50LCB3aGljaCByZXByZXNlbnQgdGhlIGF2ZXJhZ2Ugc2Nob29sLXNwZWNpZmljIGVmZmVjdCBhbmQgaXRzIDk1JSBjb25maWRlbmNlIGludGVydmFsIChyZXNwZWN0aXZlbHkpLiBTY2hvb2xzIG9uIHRoZSBsZWZ0LWhhbmQgc2lkZSBvZiB0aGUgZGlzdHJpYnV0aW9uIHRoYXQgZG8gbm90IG92ZXJsYXAgd2l0aCB0aGUgbmF0aW9uYWwgYXZlcmFnZSBsaW5lIGFyZSBzYWlkIHRvIGJlICJzaWduaWZpY2FudGx5IHVuZGVycGVyZm9ybWluZyI7IHdoZXJlYXMgdGhvc2Ugb24gdGhlIHJpZ2h0LWhhbmQgc2lkZSB0aGF0IGRvIG5vdCBvdmVybGFwIHRoZSByZWQgbGluZSBhcmUgInNpZ25pZmljYW50bHkgb3ZlcnBlcmZvcm1pbmciLiBBbGwgc2Nob29scyB0aGF0IGRvIG92ZXJsYXAgYXJlIHRob3NlIHRoYXQgY2FuIGJlIHRob3VnaHQgb2YgYXMgInBlcmZvcm1pbmcgYXMgZXhwZWN0ZWQiLiANCg0KKipOQjoqKiBUaGlzIGlzIG5vdCB0aGUgb25seSB0b29sIHRvIG1ha2Ugc3VjaCBqdWRnZW1lbnRzIGFib3V0IHNjaG9vbCBwZXJmb3JtYW5jZTsgYSBjb21wcmVoZW5zaXZlIGFjY291bnRhYmlsaXR5IHN5c3RlbSB3b3VsZCBpbnZvbHZlIGFsc28gc2Nob29sIGluc3BlY3Rpb25zIGFuZCBxdWFsaXRhdGl2ZSBqdWRnZW1lbnRzLg0KDQoNCjxicj4NCg0KKioqDQoNCiMgQm9udXMgdHJhY2sNCg0KWW91IGNvdWxkIHBsb3QgcHJlZGljdGlvbnMgZm9yIGVhY2ggc2Nob29sOg0KYGBge3IsIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQ0KDQp2YWx1ZWFkZGVkMjwtZmlsdGVyKHZhbHVlYWRkZWQsICFpcy5uYShrczRzdGFuZCkgJiAhaXMubmEoa3Myc3RhbmQpKSAjIHRoaXMgZmlsdGVyIGlzIG5lY2Vzc2FyeSB0byBhdm9pZCBpc3N1ZXMgd2l0aCBtaXNzaW5nIHZhbHVlcw0KDQp2YWx1ZWFkZGVkMiRwcmVkPC1maXR0ZWQobTEpDQoNCnNjaG9vbF9wbG90PC1nZ3Bsb3QodmFsdWVhZGRlZDIsIGFlcyh4PWtzMnN0YW5kLCB5PXByZWQsIGdyb3VwPWZhY3RvcihzY2hvb2xJRCkpKSArIA0KICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgY29sb3VyPSJibGFjayIpICsNCiAgeGxhYigiU3RhbmRhcmRpc2VkIEtTMiBzY29yZSIpICsNCiAgeWxhYigiUHJlZGljdGVkIEtTNCBzY29yZSIpICsNCiAgdGhlbWVfYncoKQ0KDQpzY2hvb2xfcGxvdA0KDQpgYGANCg0KSW4gdGhlIHBsb3QgYWJvdmUsIGVhY2ggbGluZSByZXByZXNlbnRzIGEgc2Nob29sLiBBcyB5b3UgY2FuIHNlZSwgdGhlcmUgaXMgYSBsb3Qgb2YgdmFyaWFiaWxpdHkgYWNyb3NzIHNjaG9vbHMuSW4gdGhpcyBwbG90LCBzY2hvb2wgcHJlZGljdGVkIGxpbmVzIGFyZSBwYXJhbGxlbCBiZWNhdXNlIHdlIGhhdmVuJ3QgYWxsb3dlZCB0aGUgZWZmZWN0IG9mIEtTMiBzY29yZXMgdG8gdmFyeSBhY3Jvc3Mgc2Nob29sczsgdGhpcyBpcyBhIGByYW5kb20gaW50ZXJjZXB0cyBtb2RlbGAuIFlvdSBjYW4gY29tcGFyZSB0aGlzIHBsb3Qgd2l0aCB0aGUgZmlyc3QgcGxvdCB3ZSBkaWQgYWJvdmUsIHdoZXJlIHRoZSBzaW5nbGUtbGV2ZWwgcmVncmVzc2lvbiBsaW5lIHdhcyBjbGVhcmx5IG5vdCBlbm91Z2ggdG8gcmVwcmVzZW50IHRoZSBleHRyZW1lIHZhcmlhYmlsaXR5IGluIHNjb3Jlcy4gVGhlIG11bHRpbGV2ZWwgbW9kZWwgY2FuIGFjY291bnQgZm9yIHRoYXQgdmFyaWFiaWxpdHkgYWNyb3NzIHNjaG9vbHMgYW5kIGhlbmNlIHRoZSBtdWx0aXBsZSByZWdyZXNzaW9uIGxpbmVzIHNlZW4gaGVyZSBhcmUgYSBtdWNoIGJldHRlciByZXByZXNlbnRhdGlvbiBvZiB0aGUgb2JzZXJ2ZWQgZGF0YS4NCg0KVG8gdmlzdWFsaXNlIG5vbi1wYXJhbGxlbCBzY2hvb2wgcHJlZGljdGVkIGxpbmVzLCBpLmUuIHZhcnlpbmcgc2xvcGVzLCB3ZSBuZWVkIHRvIGZpdCBhIG1vZGVsIHRoYXQgYWxsb3dzIHRoZSBlZmZlY3Qgb2YgS1MyIHRvIHZhcnkgYWNyb3NzIHNjaG9vbHMuIFRvIGZpdCBhIGByYW5kb20gc2xvcGVzIG1vZGVsYCwgd2UgcnVuIHRoZSBmb2xsb3dpbmcgY29kZTogDQoNCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0NCg0KbTFfcnM8LWxtZXIoa3M0c3RhbmR+YXMudmVjdG9yKHNjYWxlKGtzMnN0YW5kKSkrDQogICAgICAgICAgICAgICgxK2FzLnZlY3RvcihzY2FsZShrczJzdGFuZCkpfHNjaG9vbElEKSwgZGF0YT12YWx1ZWFkZGVkLCBSRU1MPUYpDQoNCiMgTm90ZSB0aGF0IEtTMiBoYXZlIGJlZW4gYWRkZWQgbGlrZSB0aGlzICJhcy52ZWN0b3Ioc2NhbGUoa3Myc3RhbmQpKSIuIFRoaXMgaXMgZG9uZSB0byBwcmV2ZW50IGEgY29udmVyZ2VuY2UgZXJyb3IuIFRoZSBmdW5jdGlvbiAic2NhbGUiIHJlc2NhbGVzIEtTMiBzY29yZXMgdG8gdW5pdHMgb2Ygc3RhbmRhcmQgZGV2aWF0aW9uLg0KDQpzdW1tYXJ5KG0xX3JzKQ0KYGBgDQoNClRvIGNvbXBhcmUgdGhlIGByYW5kb20gaW50ZXJjZXB0cyBtb2RlbHNgIHdpdGggdGhlIGByYW5kb20gc2xvcGVzIG1vZGVsYCwgd2UgY2FuIHJ1biB0aGUgZm9sbG93aW5nIGNvZGU6DQoNCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0NCmFub3ZhKG0xLCBtMV9ycykNCmBgYA0KDQpUaGUgcmVzdWx0cyBpbmRpY2F0ZSB0aGF0LCBldmVuIHRob3VnaCBtb3JlIGNvbXBsZXggKDIgZXh0cmEgcGFyYW1ldGVycyksIHRoZSBgcmFuZG9tIHNsb3BlcyBtb2RlbGAgaGFzIGEgc2lnbmlmaWNhbnRseSBiZXR0ZXIgZml0IHRoYW4gdGhlIGByYW5kb20gaW50ZXJjZXB0cyBtb2RlbGAuDQoNClRvIHBsb3QgdGhlIHNjaG9vbCBwcmVkaWN0ZWQgbGluZXMsIHdlIGNhbiByZXRyaWV2ZSB0aGUgZml0dGVkIHZhbHVlcyBmcm9tIHRoZSBtb2RlbCBgbTFfcnNgLCBhcyBzdWNoOg0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQp2YWx1ZWFkZGVkMiRwcmVkX3JzPC1maXR0ZWQobTFfcnMpDQpgYGANCg0KVGhlbiB3ZSBjYW4gc2ltcGx5IGNvcHkgdGhlIGNvZGUgZnJvbSB0aGUgcHJldmlvdXMgcGxvdCwgcmVwbGFjaW5nIGBtMWAgZm9yIGBtMV9yc2A6DQoNCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0NCnNjaG9vbF9wbG90X3JzPC1nZ3Bsb3QodmFsdWVhZGRlZDIsIGFlcyh4PWtzMnN0YW5kLCB5PXByZWRfcnMsIGdyb3VwPWZhY3RvcihzY2hvb2xJRCkpKSArIA0KICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgY29sb3VyPSJibGFjayIpICsNCiAgeGxhYigiU3RhbmRhcmRpc2VkIEtTMiBzY29yZSIpICsNCiAgeWxhYigiUHJlZGljdGVkIEtTNCBzY29yZSIpICsNCiAgdGhlbWVfYncoKQ0KDQpzY2hvb2xfcGxvdF9ycw0KYGBgDQoNClZvaWzDoCEgU2Nob29sIHByZWRpY3RlZCBzY29yZXMgaGF2ZSB2YXJ5aW5nIHNsb3BlcyBmb3IgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIEtTMiBhbmQgR0NTRSBzY29yZXMuIFlvdSBjYW4gc2VlIHRoYXQgcHVwaWxzIGluIHNvbWUgc2Nob29scyBtYWtlIG1vcmUgcHJvZ3Jlc3MgdGhhbiBvdGhlcnMgb24gYXZlcmFnZSBhbmQgc29tZSBtYWtlIGxlc3MuIA0KDQo8YnI+DQoNCllvdSBjYW4gYWxzbyBwbG90IHRoZSBoaWdoZXItbGV2ZWwgKHNjaG9vbCkgcmVzaWR1YWxzIHRvIGNoZWNrIGZvciBub3JtYWxpdHkNCg0KYGBge3IsIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQ0KDQpoaXN0KHNjaG9vbF9yZXNpZCR1MCkNCmBgYA0KDQoNCllvdSBjYW4gYWxzbyBwbG90IGluZGl2aWR1YWwtbGV2ZWwgdG8gY2hlY2sgZm9yIG5vcm1hbGl0eQ0KDQpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9DQoNCnZhbHVlYWRkZWQyJGluZF9yZXNpZCA8LSByZXNpZHVhbHMobTEpDQoNCmhpc3QodmFsdWVhZGRlZDIkaW5kX3Jlc2lkKQ0KDQpgYGANCg0KQW5kIGZpbmFsbHksIHlvdSBjYW4gcGxvdCBpbmRpdmlkdWFsLWxldmVsIHJlc2lkdWFscyBhZ2FpbnN0IHRoZSBwcmVkaWN0ZWQgdmFsdWVzIChwcmV2aW91c2x5IHJldHJpZXZlZCk6DQoNCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0NCg0KaG9tb3NjZWRhc3RpY2l0eSA8LSBnZ3Bsb3QodmFsdWVhZGRlZDIsIGFlcyh5ID0gaW5kX3Jlc2lkLCB4ID0gcHJlZCkpICsgZ2VvbV9wb2ludCgpDQoNCmhvbW9zY2VkYXN0aWNpdHkNCg0KYGBgDQoNCg0KDQo8YnI+DQoNCioqKg0KDQojIEZpbmFsIGNvbW1lbnRzDQoNCk11bHRpbGV2ZWwgbW9kZWxsaW5nIGNhbiBiZSB1c2VkIGZvciBzbyBtdWNoIG1vcmUgdGhhbiBtb2RlbGxpbmcgZWR1Y2F0aW9uYWwgb3V0Y29tZXMgb2YgcHVwaWxzIG5lc3RlZCB3aXRoaW4gc2Nob29scy4gSXQgY2FuIGFsc28gYmUgdXNlZCB0byB1bmRlcnN0YW5kIHZhcmlhdGlvbiBhY3Jvc3MgdGltZSB3aXRoaW4gaW5kaXZpZHVhbHM7IHZhcmlhdGlvbiBiZXR3ZWVuIHByaXNvbmVycyBuZXN0ZWQgd2l0aGluIHByaXNvbnM7IHZhcmlhdGlvbiBpbiBpbmNvbWUgZm9yIGluZGl2aWR1YWxzIG5lc3RlZCB3aXRoaW4gZ2VvZ3JhcGhpY2FsIGFyZWFzOyB2YXJpYXRpb24gaW4gaGVhbHRoIG91dGNvbWVzIG9mIHBhdGllbnRzIG5lc3RlZCB3aXRoaW4gR1AgcHJhY3RpY2VzIGFuZCBob3NwaXRhbHM7IGFuZCBzbyBtYW55IG90aGVyIGV4YW1wbGVzLiANCg0KSGVyZSBhcmUgc29tZSBhcHBsaWNhdGlvbnMgdGhhdCB5b3UgbWF5IHdhbnQgdG8gZXhwbG9yZToNCg0KKiphKSBBYm91dCBzY2hvb2wgdmFsdWUtYWRkZWQgbW9kZWxzOioqDQoNCiAgKyAqKkxlY2tpZSwgRy4qKiAoMjAwOSkuIFtUaGUgY29tcGxleGl0eSBvZiBzY2hvb2wgYW5kIG5laWdoYm91cmhvb2QgZWZmZWN0cyBhbmQgbW92ZW1lbnRzIG9mIHB1cGlscyBvbiBzY2hvb2wgZGlmZmVyZW5jZXMgaW4gbW9kZWxzIG9mIGVkdWNhdGlvbmFsIGFjaGlldmVtZW50XShodHRwczovL3Jzcy5vbmxpbmVsaWJyYXJ5LndpbGV5LmNvbS9kb2kvZnVsbC8xMC4xMTExL2ouMTQ2Ny05ODVYLjIwMDguMDA1NzcueCkNCiAgDQogICsgKipSYXNiYXNoLCBKLiwgTGVja2llLCBHLiwgUGlsbGluZ2VyLCBSLiwgSmVua2lucywgSi4qKiAoMjAxMCkuIFtDaGlsZHJlbidzIGVkdWNhdGlvbmFsIHByb2dyZXNzOiBwYXJ0aXRpb25pbmcgZmFtaWx5LCBzY2hvb2wgYW5kIGFyZWEgZWZmZWN0c10oaHR0cHM6Ly9yc3Mub25saW5lbGlicmFyeS53aWxleS5jb20vZG9pL2Z1bGwvMTAuMTExMS9qLjE0NjctOTg1WC4yMDEwLjAwNjQyLngpDQoNCiAgKyAqKlRyb25jb3NvLCBQLiwgUGFtcGFrYSwgTS4sIE9sc2VuLCBXLioqICgyMDE2KS4gW0JleW9uZCB0cmFkaXRpb25hbCBzY2hvb2wgdmFsdWUtYWRkZWQgbW9kZWxzOiBhIG11bHRpbGV2ZWwgYW5hbHlzaXMgb2YgY29tcGxleCBzY2hvb2wgZWZmZWN0cyBpbiBDaGlsZV0oaHR0cHM6Ly93d3cudGFuZGZvbmxpbmUuY29tL2RvaS9mdWxsLzEwLjEwODAvMDkyNDM0NTMuMjAxNS4xMDg0MDEwKQ0KDQogICsgKipUcm9uY29zbywgUC4qKiAoMjAxOSkuIFtBIHR3by1mb2xkIGluZGljYXRvciBvZiBzY2hvb2wgcGVyZm9ybWFuY2UgYW5kIHRoZSBjb3N0IG9mIGlnbm9yaW5nIGl0XShodHRwczovL3d3dy5zY2llbmNlZGlyZWN0LmNvbS9zY2llbmNlL2FydGljbGUvcGlpL1MwODgzMDM1NTE4MzEzMTIwKQ0KDQoqKmIpIEFib3V0IHByaXNvbiBlZmZlY3RzOioqDQoNCiArICoqTW9yYWxlcy1Hb21leiwgQS4qKiAoMjAxOCkuIFtJbmRpdmlkdWFsIGFuZCBTdHJ1Y3R1cmFsIEZhY3RvcnMgQWZmZWN0aW5nIFJlY2lkaXZpc206IFRoZSBSb2xlIG9mIFByaXNvbmVycywgUHJpc29ucyBhbmQgUGxhY2VzIGluIHRoZSBDaGlsZWFuIENvbnRleHRdKGh0dHBzOi8vd3d3LnJlc2VhcmNoLm1hbmNoZXN0ZXIuYWMudWsvcG9ydGFsL2ZpbGVzLzc3NTY3NjIzL0ZVTExfVEVYVC5QREYpLiAoUHJpc29uIGVmZmVjdHM6IHBwLiAxMDYtMTU3KS4gKEFyZWEgZWZmZWN0czogcHAuIDE1OC0yMDEpDQoNCioqYykgR2VuZXJhbCBtdWx0aWxldmVsIG1vZGVsbGluZyBib29rczoqKg0KDQogICsgKipHb2xkc3RlaW4sIEguKiogKDIwMTEpLiBNdWx0aWxldmVsIHN0YXRpc3RpY2FsIG1vZGVscyAoNHRoIGVkLikuIEpvaG4gV2lsZXkgYW5kIFNvbnMNCg0KICArICoqSG94LCBKLiwgTW9lcmJlZWssIE0uLCB2YW4gZGUgU2Nob290LCBSLioqICgyMDE3KS4gTXVsdGlsZXZlbCBBbmFseXNpczogVGVjaG5pcXVlcyBhbmQgQXBwbGljYXRpb25zICgzcmQgRWQpLiBSb3V0bGVkZ2UNCiANCiAgKyAqKlNuaWpkZXJzLCBULiwgQm9za2VyLCBSLioqICgyMDEyKS4gTXVsdGlsZXZlbCBBbmFseXNpczogQW4gSW50cm9kdWN0aW9uIHRvIEJhc2ljIGFuZCBBZHZhbmNlZCBNdWx0aWxldmVsIE1vZGVsaW5nICgybmQgZWQuKS4gU2FnZQ0KICANCjxicj4NCioqSElHSExZIFJFQ09NTUVOREVEOioqIA0KRm9yIGEgbW9yZSBjb21wbGV0ZSAoYW5kIGZyZWUpIGNvdXJzZSBvbiBNdWx0aWxldmVsIE1vZGVsbGluZywgdmlzaXQgdGhlIFtMRU1NQSB3ZWJzaXRlXShodHRwczovL3d3dy5jbW0uYnJpcy5hYy51ay9sZW1tYS8pIG9mIHRoZSBVbml2ZXJzaXR5IG9mIEJyaXN0b2wuDQoNCjxicj4NCg0KKioqDQoNCk9uY2UgeW91IHNlZSBtdWx0aWxldmVsIHN0cnVjdHVyZXMgaW4geW91ciBkYXRhLCB5b3UgY2Fubm90IHVuc2VlIHRoZW0uLi4NCg0KYGBge3IsIGVjaG89RkFMU0UsIGZpZy5hbGlnbj0gImNlbnRlciIsIG91dC53aWR0aD0iMzAwcHgiLCBmaWcuY2FwPSIgLSdJIHNlZSBNTE1zIScgKHZpYSBHaXBoeSkiLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL21lZGlhLmdpcGh5LmNvbS9tZWRpYS93YzdSSjBRSXJJWHUwL2dpcGh5LmdpZiIpDQpgYGA=
 

Patricio Troncoso

patricio.troncoso@manchester.ac.uk