Wongupparaj et al. (2017) released a study that found that backward digit span/corsi span scores declined, while forward digit span/corsi scores increased. The idea is that backward memory is more g-loaded than forward memory, so this supports the view that the Flynn Effect is an artefact and that true IQ is lowering.

This wrong. Let me quickly pull up their dataset.

head(savy)

Recreating the first regression:

qwe <- lm(data=savy, Mean ~ Year, weights=Size)
summary(qwe)

Call:
lm(formula = Mean ~ Year, data = savy, weights = Size)

Weighted Residuals:
    Min      1Q  Median      3Q     Max 
-58.915  -4.623   0.428   4.564  51.829 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept) 16.109773   8.273144   1.947    0.052 .
Year        -0.005778   0.004121  -1.402    0.161  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 9.877 on 592 degrees of freedom
Multiple R-squared:  0.003309,  Adjusted R-squared:  0.001626 
F-statistic: 1.966 on 1 and 592 DF,  p-value: 0.1614

Alright. Replicated. What about their second regression?

qwe <- lm(data=savy, Mean ~ Year + Age + Male + Type_C + Platform, weights=Size)
summary(qwe)

Call:
lm(formula = Mean ~ Year + Age + Male + Type_C + Platform, data = savy, 
    weights = Size)

Weighted Residuals:
    Min      1Q  Median      3Q     Max 
-49.643  -4.525   0.440   4.506  51.708 

Coefficients:
              Estimate Std. Error t value        Pr(>|t|)    
(Intercept)  7.7411426  8.0485412   0.962           0.337    
Year        -0.0020717  0.0039988  -0.518           0.605    
Age          0.0058195  0.0014088   4.131 0.0000414092464 ***
Male        -0.0008939  0.0021264  -0.420           0.674    
Type_C       0.8781821  0.1312821   6.689 0.0000000000523 ***
Platform    -0.0862458  0.1244160  -0.693           0.488    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 9.418 on 588 degrees of freedom
Multiple R-squared:  0.09989,   Adjusted R-squared:  0.09223 
F-statistic: 13.05 on 5 and 588 DF,  p-value: 0.000000000004612

Different from their 2A table. Not sure what’s going on. Year is not statistically signfiicant anymore.


So, that aside, I labelled all 598 effect sizes by country of origin (22 cases could not be identified) and socioeconomic status (factor with levels 0, 1, 2) to test for omitted variable biases. I also corrected a few clerical errors, and added a few studies (6?) I randomly found when searching for the publications for each effect size.

subset <- testtempyarfwefe %>% filter(type=='backward' & ((!Country==1 & !Country==0 & !Country=='') | is.na(Country)))
subset$Country[is.na(subset$Country)] <- 'Unknown'
subset$SES[is.na(subset$SES)] <- 1
subset$SE <- subset$SD/sqrt(subset$Size)

Then, I noticed that the mean and the standard deviation of backward digit span was non-linearly related to age, even after controlling for specific country and SES, so I normed scores using splines instead of a linear method.

p <- splinechart(datos=subset, var1='Age', var2='Mean', knots=5, breakn=10, metastyle=F, label='Age', labely='Mean Backward Digit Span',
                 covariatefunc=' + as.factor(SES) + Country', ws='Size', burndata=data.frame(SES=1, Country='UK'), outputyes=F)
p

#Yes, this does pass significance testing
p <- splinechart(datos=subset, var1='Age', var2='SD', knots=5, breakn=10, metastyle=F, label='Age', labely='SD Backward Digit Span',
                 covariatefunc=' + as.factor(SES) + Country', ws='Size', burndata=data.frame(SES=1, Country='UK'), outputyes=F)
p

Onto the hard calculations. Now I have scores normed for age, both in terms of variance and mean.

lr <- lm(data=subset, Mean ~ rcs(Age, 5) + as.factor(SES), weights=sqrt(Size))
summary(lr)

Call:
lm(formula = Mean ~ rcs(Age, 5) + as.factor(SES), data = subset, 
    weights = sqrt(Size))

Weighted Residuals:
     Min       1Q   Median       3Q      Max 
-10.2619  -1.2523  -0.2109   1.0086   7.9391 

Coefficients:
                  Estimate Std. Error t value             Pr(>|t|)    
(Intercept)        0.59841    0.24813   2.412             0.016181 *  
rcs(Age, 5)Age     0.31503    0.02041  15.436 < 0.0000000000000002 ***
rcs(Age, 5)Age'   -5.34306    0.47150 -11.332 < 0.0000000000000002 ***
rcs(Age, 5)Age''   7.45751    0.69468  10.735 < 0.0000000000000002 ***
rcs(Age, 5)Age''' -2.20123    0.26302  -8.369 0.000000000000000419 ***
as.factor(SES)1    0.54224    0.15892   3.412             0.000689 ***
as.factor(SES)2    0.52464    0.18372   2.856             0.004446 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.214 on 592 degrees of freedom
Multiple R-squared:  0.4285,    Adjusted R-squared:  0.4228 
F-statistic: 73.99 on 6 and 592 DF,  p-value: < 0.00000000000000022
metaobj2 <- metafor::rma(yi=Mean, sei=SE, data=subset, mods = ~ rcs(Age, 5) + as.factor(SES))
summary(metaobj2)

Mixed-Effects Model (k = 599; tau^2 estimator: REML)

   logLik   deviance        AIC        BIC       AICc   
-681.8482  1363.6963  1379.6963  1414.7644  1379.9433   

tau^2 (estimated amount of residual heterogeneity):     0.5408 (SE = 0.0339)
tau (square root of estimated tau^2 value):             0.7354
I^2 (residual heterogeneity / unaccounted variability): 98.06%
H^2 (unaccounted variability / sampling variability):   51.42
R^2 (amount of heterogeneity accounted for):            48.41%

Test for Residual Heterogeneity:
QE(df = 592) = 35716.9755, p-val < .0001

Test of Moderators (coefficients 2:7):
QM(df = 6) = 525.5336, p-val < .0001

Model Results:

---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
lr$coefficients <- metaobj2$b

metaobj32 <- metafor::rma(yi=SD, sei=SE, data=subset, mods = ~ rcs(Age, 5) + as.factor(SES))
summary(metaobj2)

Mixed-Effects Model (k = 599; tau^2 estimator: REML)

   logLik   deviance        AIC        BIC       AICc   
-681.8482  1363.6963  1379.6963  1414.7644  1379.9433   

tau^2 (estimated amount of residual heterogeneity):     0.5408 (SE = 0.0339)
tau (square root of estimated tau^2 value):             0.7354
I^2 (residual heterogeneity / unaccounted variability): 98.06%
H^2 (unaccounted variability / sampling variability):   51.42
R^2 (amount of heterogeneity accounted for):            48.41%

Test for Residual Heterogeneity:
QE(df = 592) = 35716.9755, p-val < .0001

Test of Moderators (coefficients 2:7):
QM(df = 6) = 525.5336, p-val < .0001

Model Results:

---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
lr3 <- lm(data=subset, SD ~ rcs(Age, 5) + as.factor(SES), weights=sqrt(Size))
summary(lr)

Call:
lm(formula = Mean ~ rcs(Age, 5) + as.factor(SES), data = subset, 
    weights = sqrt(Size))

Weighted Residuals:
     Min       1Q   Median       3Q      Max 
-10.2619  -1.2523  -0.2109   1.0086   7.9391 

Coefficients:
     Estimate Std. Error t value             Pr(>|t|)    
[1,]  0.57151    0.24813   2.303              0.02161 *  
[2,]  0.30312    0.02041  14.852 < 0.0000000000000002 ***
[3,] -4.99721    0.47150 -10.599 < 0.0000000000000002 ***
[4,]  6.95332    0.69468  10.009 < 0.0000000000000002 ***
[5,] -2.03386    0.26302  -7.733   0.0000000000000455 ***
[6,]  0.62281    0.15892   3.919   0.0000992599476217 ***
[7,]  0.57459    0.18372   3.128              0.00185 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.214 on 592 degrees of freedom
Multiple R-squared:  0.4285,    Adjusted R-squared:  0.4228 
F-statistic: 73.99 on 6 and 592 DF,  p-value: < 0.00000000000000022
lr3$coefficients <- metaobj32$b

uzi <- seq(from=4, to=92.5, by=.1)
uzi2 <- data.frame(Age=uzi, SES=1)
uzi2$SD_age = predict(lr3, uzi2)

subset$residualscore <- lr$residuals
subset$roundage <- format(round(subset$Age, 1), nsmall = 1)
uzi2$Age_formatted <- format(uzi2$Age, nsmall = 1)

subset2 <- left_join(
  subset,
  uzi2 %>% select(Age_formatted, SD_age),
  by = c('roundage' = 'Age_formatted')
)

subset2$IQ <- subset2$residualscore/subset2$SD_age*15+100

Do these scores normed for age/SES have a Flynn Effect? Yes. See the regression table – increase of 0.14 (SE = 0.05) points every year.


p <- splinechart(datos=subset2, var1='Year', var2='IQ', knots=5, breakn=5, metastyle=F, label='Year', labely='IQ',
                 covariatefunc='+ Country', ws='Size', burndata=data.frame(SES=1, Country='UK'), outputyes = T)

Call:
lm(formula = paste0("var22", modell), data = datos, weights = sqrt(defaultweights))

Weighted Residuals:
    Min      1Q  Median      3Q     Max 
-133.79  -14.29   -1.38   11.05  121.40 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)   
(Intercept)         -183.98760   98.45329  -1.869  0.06218 . 
var11                  0.13720    0.04884   2.809  0.00514 **
CountryAustralia      15.13592    5.55526   2.725  0.00664 **
CountryAustria        27.19053   13.96176   1.948  0.05197 . 
CountryBelgium         5.27791    5.73316   0.921  0.35766   
CountryBrazil          3.67153    5.89434   0.623  0.53361   
CountryCanada         15.09410    5.61930   2.686  0.00744 **
CountryChina          11.66256    6.24306   1.868  0.06227 . 
CountryColombia       13.18377   12.80726   1.029  0.30374   
CountryCroatia         5.77719    7.12118   0.811  0.41756   
CountryDenmark        -1.42541    8.03405  -0.177  0.85924   
CountryFinland        12.67420    6.06690   2.089  0.03715 * 
CountryFrance         14.56088    6.94555   2.096  0.03649 * 
CountryGermany         8.75160    5.44791   1.606  0.10875   
CountryHong Kong      17.75716    7.34317   2.418  0.01592 * 
CountryHungary        14.17243   10.14527   1.397  0.16298   
CountryIndia          -7.70436    8.91570  -0.864  0.38788   
CountryIran            1.48125    9.76069   0.152  0.87943   
CountryIsrael          8.57904    7.87656   1.089  0.27654   
CountryItaly           3.84550    5.33187   0.721  0.47107   
CountryJamaica         2.43182    9.47772   0.257  0.79759   
CountryJapan           9.85085    6.90302   1.427  0.15413   
CountryMexico         -4.90161    5.95809  -0.823  0.41104   
CountryNetherlands    10.68805    5.54619   1.927  0.05447 . 
CountryNew Zealand     2.77731    5.75294   0.483  0.62945   
CountryNorway          8.04522    6.86588   1.172  0.24179   
CountryPortugal        2.14251    6.50921   0.329  0.74217   
CountrySingapore       4.85551    6.45849   0.752  0.45249   
CountrySlovenia       24.07165   11.62842   2.070  0.03890 * 
CountrySouth Africa   -9.97060    8.28712  -1.203  0.22943   
CountrySouth Korea     2.88260    6.19272   0.465  0.64177   
CountrySpain          11.49762    5.57165   2.064  0.03952 * 
CountrySweden          7.43187    5.53835   1.342  0.18017   
CountryTaiwan         -1.40316    6.98551  -0.201  0.84088   
CountryTunisia        10.32997    6.80912   1.517  0.12981   
CountryTurkey          9.78593    9.74573   1.004  0.31575   
CountryUK              8.98739    5.51222   1.630  0.10357   
CountryUnknown        10.78941    5.41159   1.994  0.04666 * 
CountryUSA            10.15682    5.20103   1.953  0.05134 . 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 27.44 on 560 degrees of freedom
Multiple R-squared:  0.1803,    Adjusted R-squared:  0.1247 
F-statistic: 3.241 on 38 and 560 DF,  p-value: 0.000000001205

[1] "Non-linear vs linear:"
Analysis of Variance Table

Model 1: var22 ~ rcs(var11, 5) + Country
Model 2: var22 ~ var11 + Country
  Res.Df    RSS Df Sum of Sq      F Pr(>F)
1    557 420168                           
2    560 421776 -3   -1607.9 0.7105  0.546
p

Same attempt, but with cohort effects instead. No increase or decrease.

subset2$cohort <- subset2$Year - subset2$Age

p <- splinechart(datos=subset2, var1='cohort', var2='IQ', knots=5, breakn=10, metastyle=F, label='Cohort', labely='IQ',
                 covariatefunc='+ Country', ws='Size', burndata=data.frame(SES=1, Country='UK'), outputyes = F)
p

Calculation of international differences (resetting data, controlling for year). Obviously, these means don’t have a reference population, and I’m sure that a dozen criticisms could be hauled at them, but I figured people would be curious anyway, so why not plot them.

subset <- testtempyarfwefe %>% filter(type=='backward' & ((!Country==1 & !Country==0 & !Country=='') | is.na(Country)))
subset$Country[is.na(subset$Country)] <- 'Unknown'
subset$SES[is.na(subset$SES)] <- 1
subset$SE <- subset$SD/sqrt(subset$Size)


########
lr <- lm(data=subset, Mean ~ rcs(Age, 5) + as.factor(SES) + Year, weights=sqrt(Size))
metaobj2 <- metafor::rma(yi=Mean, sei=SE, data=subset, mods = ~ rcs(Age, 5) + as.factor(SES) + Year)
lr$coefficients <- metaobj2$b

metaobj32 <- metafor::rma(yi=SD, sei=SE, data=subset, mods = ~ rcs(Age, 5) + as.factor(SES) + Year)
lr3 <- lm(data=subset, SD ~ rcs(Age, 5) + as.factor(SES) + Year, weights=sqrt(Size))
lr3$coefficients <- metaobj32$b

uzi <- seq(from=4, to=92.5, by=.1)
uzi2 <- data.frame(Age=uzi, SES=1, Year=2008)
uzi2$SD_age = predict(lr3, uzi2)

subset$residualscore <- lr$residuals
subset$roundage <- format(round(subset$Age, 1), nsmall = 1)
uzi2$Age_formatted <- format(uzi2$Age, nsmall = 1)

subset2 <- left_join(
  subset,
  uzi2 %>% select(Age_formatted, SD_age),
  by = c('roundage' = 'Age_formatted')
)

subset2$IQ <- subset2$residualscore/subset2$SD_age*15+100
subset2$pasteID <- paste0(subset2$Authors, subset2$Year)

zxc <- unique(subset2 %>% group_by(pasteID) %>% summarise(IQ2 = mean(IQ), n = sum(Size), Country = Country))
Warning: Returning more (or less) than 1 row per `summarise()` group was deprecated in dplyr 1.1.0.
Please use `reframe()` instead.
When switching from `summarise()` to `reframe()`, remember that `reframe()` always returns an ungrouped data frame and adjust accordingly.`summarise()` has grouped output by 'pasteID'. You can override using the `.groups` argument.
zxc$SE <- 1/sqrt(zxc$n)

zxcv <- unique(zxc %>% group_by(Country) %>% summarise(unwtdIQ = mean(IQ2), wtdIQ = wtd.mean(IQ2, n), medianIQ = median(IQ2), n2 = sum(n), k = n()))
zxcv  %>% arrange(-medianIQ)
LS0tCnRpdGxlOiAiRGlkIFdvbmd1cHBhcmFqIGV0IGFsLiBkZWJ1bmsgdGhlIEZseW5uIEVmZmVjdD8iCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCldvbmd1cHBhcmFqIGV0IGFsLiAoMjAxNykgcmVsZWFzZWQgYSBzdHVkeSB0aGF0IGZvdW5kIHRoYXQgYmFja3dhcmQgZGlnaXQgc3Bhbi9jb3JzaSBzcGFuIHNjb3JlcyBkZWNsaW5lZCwgd2hpbGUgZm9yd2FyZCBkaWdpdCBzcGFuL2NvcnNpIHNjb3JlcyBpbmNyZWFzZWQuIFRoZSBpZGVhIGlzIHRoYXQgYmFja3dhcmQgbWVtb3J5IGlzIG1vcmUgZy1sb2FkZWQgdGhhbiBmb3J3YXJkIG1lbW9yeSwgc28gdGhpcyBzdXBwb3J0cyB0aGUgdmlldyB0aGF0IHRoZSBGbHlubiBFZmZlY3QgaXMgYW4gYXJ0ZWZhY3QgYW5kIHRoYXQgdHJ1ZSBJUSBpcyBsb3dlcmluZy4gCgpUaGlzIHdyb25nLiBMZXQgbWUgcXVpY2tseSBwdWxsIHVwIHRoZWlyIGRhdGFzZXQuCgoKYGBge3J9CmhlYWQoc2F2eSkKYGBgCgpSZWNyZWF0aW5nIHRoZSBmaXJzdCByZWdyZXNzaW9uOgoKYGBge3J9CnF3ZSA8LSBsbShkYXRhPXNhdnksIE1lYW4gfiBZZWFyLCB3ZWlnaHRzPVNpemUpCnN1bW1hcnkocXdlKQpgYGAKCkFscmlnaHQuIFJlcGxpY2F0ZWQuIFdoYXQgYWJvdXQgdGhlaXIgc2Vjb25kIHJlZ3Jlc3Npb24/CgpgYGB7cn0KcXdlIDwtIGxtKGRhdGE9c2F2eSwgTWVhbiB+IFllYXIgKyBBZ2UgKyBNYWxlICsgVHlwZV9DICsgUGxhdGZvcm0sIHdlaWdodHM9U2l6ZSkKc3VtbWFyeShxd2UpCmBgYAoKRGlmZmVyZW50IGZyb20gdGhlaXIgMkEgdGFibGUuIE5vdCBzdXJlIHdoYXQncyBnb2luZyBvbi4gWWVhciBpcyBub3Qgc3RhdGlzdGljYWxseSBzaWduZmlpY2FudCBhbnltb3JlLgoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwoKCgpTbywgdGhhdCBhc2lkZSwgSSBsYWJlbGxlZCBhbGwgNTk4IGVmZmVjdCBzaXplcyBieSBjb3VudHJ5IG9mIG9yaWdpbiAoMjIgY2FzZXMgY291bGQgbm90IGJlIGlkZW50aWZpZWQpIGFuZCBzb2Npb2Vjb25vbWljIHN0YXR1cyAoZmFjdG9yIHdpdGggbGV2ZWxzIDAsIDEsIDIpIHRvIHRlc3QgZm9yIG9taXR0ZWQgdmFyaWFibGUgYmlhc2VzLiBJIGFsc28gY29ycmVjdGVkIGEgZmV3IGNsZXJpY2FsIGVycm9ycywgYW5kIGFkZGVkIGEgZmV3IHN0dWRpZXMgKDY/KSBJIHJhbmRvbWx5IGZvdW5kIHdoZW4gc2VhcmNoaW5nIGZvciB0aGUgcHVibGljYXRpb25zIGZvciBlYWNoIGVmZmVjdCBzaXplLiAKCmBgYHtyfQpzdWJzZXQgPC0gdGVzdHRlbXB5YXJmd2VmZSAlPiUgZmlsdGVyKHR5cGU9PSdiYWNrd2FyZCcgJiAoKCFDb3VudHJ5PT0xICYgIUNvdW50cnk9PTAgJiAhQ291bnRyeT09JycpIHwgaXMubmEoQ291bnRyeSkpKQpzdWJzZXQkQ291bnRyeVtpcy5uYShzdWJzZXQkQ291bnRyeSldIDwtICdVbmtub3duJwpzdWJzZXQkU0VTW2lzLm5hKHN1YnNldCRTRVMpXSA8LSAxCnN1YnNldCRTRSA8LSBzdWJzZXQkU0Qvc3FydChzdWJzZXQkU2l6ZSkKYGBgCgoKVGhlbiwgSSBub3RpY2VkIHRoYXQgdGhlIG1lYW4gYW5kIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgYmFja3dhcmQgZGlnaXQgc3BhbiAKd2FzIG5vbi1saW5lYXJseSByZWxhdGVkIHRvIGFnZSwgZXZlbiBhZnRlciBjb250cm9sbGluZyBmb3Igc3BlY2lmaWMgY291bnRyeSBhbmQgU0VTLCBzbyBJIG5vcm1lZApzY29yZXMgdXNpbmcgc3BsaW5lcyBpbnN0ZWFkIG9mIGEgbGluZWFyIG1ldGhvZC4KCmBgYHtyfQpwIDwtIHNwbGluZWNoYXJ0KGRhdG9zPXN1YnNldCwgdmFyMT0nQWdlJywgdmFyMj0nTWVhbicsIGtub3RzPTUsIGJyZWFrbj0xMCwgbWV0YXN0eWxlPUYsIGxhYmVsPSdBZ2UnLCBsYWJlbHk9J01lYW4gQmFja3dhcmQgRGlnaXQgU3BhbicsCiAgICAgICAgICAgICAgICAgY292YXJpYXRlZnVuYz0nICsgYXMuZmFjdG9yKFNFUykgKyBDb3VudHJ5Jywgd3M9J1NpemUnLCBidXJuZGF0YT1kYXRhLmZyYW1lKFNFUz0xLCBDb3VudHJ5PSdVSycpLCBvdXRwdXR5ZXM9RikKcApgYGAKYGBge3J9CiNZZXMsIHRoaXMgZG9lcyBwYXNzIHNpZ25pZmljYW5jZSB0ZXN0aW5nCnAgPC0gc3BsaW5lY2hhcnQoZGF0b3M9c3Vic2V0LCB2YXIxPSdBZ2UnLCB2YXIyPSdTRCcsIGtub3RzPTUsIGJyZWFrbj0xMCwgbWV0YXN0eWxlPUYsIGxhYmVsPSdBZ2UnLCBsYWJlbHk9J1NEIEJhY2t3YXJkIERpZ2l0IFNwYW4nLAogICAgICAgICAgICAgICAgIGNvdmFyaWF0ZWZ1bmM9JyArIGFzLmZhY3RvcihTRVMpICsgQ291bnRyeScsIHdzPSdTaXplJywgYnVybmRhdGE9ZGF0YS5mcmFtZShTRVM9MSwgQ291bnRyeT0nVUsnKSwgb3V0cHV0eWVzPUYpCnAKYGBgCk9udG8gdGhlIGhhcmQgY2FsY3VsYXRpb25zLiBOb3cgSSBoYXZlIHNjb3JlcyBub3JtZWQgZm9yIGFnZSwgYm90aCBpbiB0ZXJtcyBvZiB2YXJpYW5jZSBhbmQgbWVhbi4KCmBgYHtyfQpsciA8LSBsbShkYXRhPXN1YnNldCwgTWVhbiB+IHJjcyhBZ2UsIDUpICsgYXMuZmFjdG9yKFNFUyksIHdlaWdodHM9c3FydChTaXplKSkKc3VtbWFyeShscikKbWV0YW9iajIgPC0gbWV0YWZvcjo6cm1hKHlpPU1lYW4sIHNlaT1TRSwgZGF0YT1zdWJzZXQsIG1vZHMgPSB+IHJjcyhBZ2UsIDUpICsgYXMuZmFjdG9yKFNFUykpCnN1bW1hcnkobWV0YW9iajIpCmxyJGNvZWZmaWNpZW50cyA8LSBtZXRhb2JqMiRiCgptZXRhb2JqMzIgPC0gbWV0YWZvcjo6cm1hKHlpPVNELCBzZWk9U0UsIGRhdGE9c3Vic2V0LCBtb2RzID0gfiByY3MoQWdlLCA1KSArIGFzLmZhY3RvcihTRVMpKQpzdW1tYXJ5KG1ldGFvYmoyKQpscjMgPC0gbG0oZGF0YT1zdWJzZXQsIFNEIH4gcmNzKEFnZSwgNSkgKyBhcy5mYWN0b3IoU0VTKSwgd2VpZ2h0cz1zcXJ0KFNpemUpKQpzdW1tYXJ5KGxyKQpscjMkY29lZmZpY2llbnRzIDwtIG1ldGFvYmozMiRiCgp1emkgPC0gc2VxKGZyb209NCwgdG89OTIuNSwgYnk9LjEpCnV6aTIgPC0gZGF0YS5mcmFtZShBZ2U9dXppLCBTRVM9MSkKdXppMiRTRF9hZ2UgPSBwcmVkaWN0KGxyMywgdXppMikKCnN1YnNldCRyZXNpZHVhbHNjb3JlIDwtIGxyJHJlc2lkdWFscwpzdWJzZXQkcm91bmRhZ2UgPC0gZm9ybWF0KHJvdW5kKHN1YnNldCRBZ2UsIDEpLCBuc21hbGwgPSAxKQp1emkyJEFnZV9mb3JtYXR0ZWQgPC0gZm9ybWF0KHV6aTIkQWdlLCBuc21hbGwgPSAxKQoKc3Vic2V0MiA8LSBsZWZ0X2pvaW4oCiAgc3Vic2V0LAogIHV6aTIgJT4lIHNlbGVjdChBZ2VfZm9ybWF0dGVkLCBTRF9hZ2UpLAogIGJ5ID0gYygncm91bmRhZ2UnID0gJ0FnZV9mb3JtYXR0ZWQnKQopCgpzdWJzZXQyJElRIDwtIHN1YnNldDIkcmVzaWR1YWxzY29yZS9zdWJzZXQyJFNEX2FnZSoxNSsxMDAKYGBgCkRvIHRoZXNlIHNjb3JlcyBub3JtZWQgZm9yIGFnZS9TRVMgaGF2ZSBhIEZseW5uIEVmZmVjdD8KWWVzLiBTZWUgdGhlIHJlZ3Jlc3Npb24gdGFibGUgLS0gaW5jcmVhc2Ugb2YgMC4xNCAoU0UgPSAwLjA1KSBwb2ludHMgZXZlcnkgeWVhci4KCmBgYHtyfQoKcCA8LSBzcGxpbmVjaGFydChkYXRvcz1zdWJzZXQyLCB2YXIxPSdZZWFyJywgdmFyMj0nSVEnLCBrbm90cz01LCBicmVha249NSwgbWV0YXN0eWxlPUYsIGxhYmVsPSdZZWFyJywgbGFiZWx5PSdJUScsCiAgICAgICAgICAgICAgICAgY292YXJpYXRlZnVuYz0nKyBDb3VudHJ5Jywgd3M9J1NpemUnLCBidXJuZGF0YT1kYXRhLmZyYW1lKFNFUz0xLCBDb3VudHJ5PSdVSycpLCBvdXRwdXR5ZXMgPSBUKQpwCmBgYApTYW1lIGF0dGVtcHQsIGJ1dCB3aXRoIGNvaG9ydCBlZmZlY3RzIGluc3RlYWQuIE5vIGluY3JlYXNlIG9yIGRlY3JlYXNlLgpgYGB7cn0Kc3Vic2V0MiRjb2hvcnQgPC0gc3Vic2V0MiRZZWFyIC0gc3Vic2V0MiRBZ2UKCnAgPC0gc3BsaW5lY2hhcnQoZGF0b3M9c3Vic2V0MiwgdmFyMT0nY29ob3J0JywgdmFyMj0nSVEnLCBrbm90cz01LCBicmVha249MTAsIG1ldGFzdHlsZT1GLCBsYWJlbD0nQ29ob3J0JywgbGFiZWx5PSdJUScsCiAgICAgICAgICAgICAgICAgY292YXJpYXRlZnVuYz0nKyBDb3VudHJ5Jywgd3M9J1NpemUnLCBidXJuZGF0YT1kYXRhLmZyYW1lKFNFUz0xLCBDb3VudHJ5PSdVSycpLCBvdXRwdXR5ZXMgPSBGKQpwCmBgYApDYWxjdWxhdGlvbiBvZiBpbnRlcm5hdGlvbmFsIGRpZmZlcmVuY2VzIChyZXNldHRpbmcgZGF0YSwgY29udHJvbGxpbmcgZm9yIHllYXIpLiBPYnZpb3VzbHksCnRoZXNlIG1lYW5zIGRvbid0IGhhdmUgYSByZWZlcmVuY2UgcG9wdWxhdGlvbiwgYW5kIEknbSBzdXJlIHRoYXQgYSBkb3plbiBjcml0aWNpc21zIGNvdWxkIGJlCmhhdWxlZCBhdCB0aGVtLCBidXQgSSBmaWd1cmVkIHBlb3BsZSB3b3VsZCBiZSBjdXJpb3VzIGFueXdheSwgc28gd2h5IG5vdCBwbG90IHRoZW0uCgpgYGB7cn0Kc3Vic2V0IDwtIHRlc3R0ZW1weWFyZndlZmUgJT4lIGZpbHRlcih0eXBlPT0nYmFja3dhcmQnICYgKCghQ291bnRyeT09MSAmICFDb3VudHJ5PT0wICYgIUNvdW50cnk9PScnKSB8IGlzLm5hKENvdW50cnkpKSkKc3Vic2V0JENvdW50cnlbaXMubmEoc3Vic2V0JENvdW50cnkpXSA8LSAnVW5rbm93bicKc3Vic2V0JFNFU1tpcy5uYShzdWJzZXQkU0VTKV0gPC0gMQpzdWJzZXQkU0UgPC0gc3Vic2V0JFNEL3NxcnQoc3Vic2V0JFNpemUpCgoKIyMjIyMjIyMKbHIgPC0gbG0oZGF0YT1zdWJzZXQsIE1lYW4gfiByY3MoQWdlLCA1KSArIGFzLmZhY3RvcihTRVMpICsgWWVhciwgd2VpZ2h0cz1zcXJ0KFNpemUpKQptZXRhb2JqMiA8LSBtZXRhZm9yOjpybWEoeWk9TWVhbiwgc2VpPVNFLCBkYXRhPXN1YnNldCwgbW9kcyA9IH4gcmNzKEFnZSwgNSkgKyBhcy5mYWN0b3IoU0VTKSArIFllYXIpCmxyJGNvZWZmaWNpZW50cyA8LSBtZXRhb2JqMiRiCgptZXRhb2JqMzIgPC0gbWV0YWZvcjo6cm1hKHlpPVNELCBzZWk9U0UsIGRhdGE9c3Vic2V0LCBtb2RzID0gfiByY3MoQWdlLCA1KSArIGFzLmZhY3RvcihTRVMpICsgWWVhcikKbHIzIDwtIGxtKGRhdGE9c3Vic2V0LCBTRCB+IHJjcyhBZ2UsIDUpICsgYXMuZmFjdG9yKFNFUykgKyBZZWFyLCB3ZWlnaHRzPXNxcnQoU2l6ZSkpCmxyMyRjb2VmZmljaWVudHMgPC0gbWV0YW9iajMyJGIKCnV6aSA8LSBzZXEoZnJvbT00LCB0bz05Mi41LCBieT0uMSkKdXppMiA8LSBkYXRhLmZyYW1lKEFnZT11emksIFNFUz0xLCBZZWFyPTIwMDgpCnV6aTIkU0RfYWdlID0gcHJlZGljdChscjMsIHV6aTIpCgpzdWJzZXQkcmVzaWR1YWxzY29yZSA8LSBsciRyZXNpZHVhbHMKc3Vic2V0JHJvdW5kYWdlIDwtIGZvcm1hdChyb3VuZChzdWJzZXQkQWdlLCAxKSwgbnNtYWxsID0gMSkKdXppMiRBZ2VfZm9ybWF0dGVkIDwtIGZvcm1hdCh1emkyJEFnZSwgbnNtYWxsID0gMSkKCnN1YnNldDIgPC0gbGVmdF9qb2luKAogIHN1YnNldCwKICB1emkyICU+JSBzZWxlY3QoQWdlX2Zvcm1hdHRlZCwgU0RfYWdlKSwKICBieSA9IGMoJ3JvdW5kYWdlJyA9ICdBZ2VfZm9ybWF0dGVkJykKKQoKc3Vic2V0MiRJUSA8LSBzdWJzZXQyJHJlc2lkdWFsc2NvcmUvc3Vic2V0MiRTRF9hZ2UqMTUrMTAwCnN1YnNldDIkcGFzdGVJRCA8LSBwYXN0ZTAoc3Vic2V0MiRBdXRob3JzLCBzdWJzZXQyJFllYXIpCgp6eGMgPC0gdW5pcXVlKHN1YnNldDIgJT4lIGdyb3VwX2J5KHBhc3RlSUQpICU+JSBzdW1tYXJpc2UoSVEyID0gbWVhbihJUSksIG4gPSBzdW0oU2l6ZSksIENvdW50cnkgPSBDb3VudHJ5KSkKenhjJFNFIDwtIDEvc3FydCh6eGMkbikKCnp4Y3YgPC0gdW5pcXVlKHp4YyAlPiUgZ3JvdXBfYnkoQ291bnRyeSkgJT4lIHN1bW1hcmlzZSh1bnd0ZElRID0gbWVhbihJUTIpLCB3dGRJUSA9IHd0ZC5tZWFuKElRMiwgbiksIG1lZGlhbklRID0gbWVkaWFuKElRMiksIG4yID0gc3VtKG4pLCBrID0gbigpKSkKenhjdiAgJT4lIGFycmFuZ2UoLW1lZGlhbklRKQpgYGA=