1 Motivation

Experiment 3 was designed to eliminate the potential confounds of Experiment 2’s design by comparing extraction from RCs in three different environments: the pivot of an existential, within a predicate nominal, and within a transitive object.

2 Design

This experiment returns to the length by complexity design utilized by Sprouse, Wagers, and Phillips (2012) and adds an additional environment factor with three levels, shown below. This resulted in a 3×2×2 design, with 12 conditions per item. A sample item is shown in 2.

  1. Factors
    1. Environment
      1. object
      2. predicate
      3. existential
    2. Structure
      1. island (RC)
      2. non-island (embedded that-clause)
    3. Length
      1. long (embedded object)
      2. short (matrix subject)
  2. Sample item
    1. Who said that Michael remembered that only one journalist read this article?
      (object|non-island|short)
    2. Which article did you say that Michael remembered that only one journalist read?
      (object|non-island|long)
    3. Who said that Michael remembered the only journalist who read this article?
      (object|island|short)
    4. Which article did you say that Michael remembered the only journalist who read?
      (object|island|long)
    5. Who said that Michael thinks that only one journalist read this article?
      (predicate|non-island|short)
    6. Which article did you say that Michael thinks that only one journalist read?
      (predicate|non-island|long)
    7. Who said that Michael thinks that he is the only journalist who read this article?
      (predicate|island|short)
    8. Which article did you say that Michael thinks that he is the only journalist who read?
      (predicate|island|long)
    9. Who said that there was only one senator reading this article?
      (existential|non-island|short)
    10. Which article did you say that there was only one senator reading?
      (existential|non-island|long)
    11. Who said that there is only one journalist who read this article?
      (existential|island|short)
    12. Which article did you say that there is only one journalist who read?
      (existential|island|long)

3 Analysis

# Pull in formatted results
raw_results_mt <- read.csv("results_mturk/20180704/20180704_results_formatted_fixed.csv")

# Rename 1st column header b/c of excel issue
colnames(raw_results_mt)[1] <- "date_received"

# Make subject a factor
raw_results_mt$subject %<>% as.factor

# Separate experiment and filler data
raw_results_mt %>% subset(item_type == "experimental") %>% droplevels -> experiment_data_mt
raw_results_mt %>% subset(item_type == "filler") %>% droplevels -> filler_data_mt

3.1 Participant information (based on filler ratings)

The following table summarizes the ratings data for each participant (based on filler sentences only), including the mean ratings they gave to expected grammatical fillers and expected ungrammatical fillers.

# Look at the results by participant, get means for both grammatical and ungrammatical fillers
filler_data_mt %>% group_by(subject) %>%
  summarize(mean_rating = mean(rating),
            sd_rating = sd(rating),
            n = n(),
            se_rating = sd_rating/sqrt(n),
            mean_gramm = mean(rating[expected_gramm == "gramm"]),
            mean_ungramm = mean(rating[expected_gramm == "ungramm"])) -> worker_summary
print(worker_summary)

Participants will be excluded whose average rating for ungrammatical fillers is greater than or equal to their average rating for grammatical fillers. The following code chunk identifies these participants.

worker_summary %>% subset(mean_ungramm >= mean_gramm) -> excluded_1
print(excluded_1)

Here’s a visual representation of the participants’ average filler ratings. Each point represents the average z-scores for a participant’s grammatical/ungrammatical filler ratings. Participants 377 and 387 stand out since the red point (average z-scored rating for grammatical fillers) is below the blue point (for ungrammatical fillers).

filler_data_mt %>%
  group_by(subject) %>%
  mutate(z_score = scale(rating)) %>%
  group_by(subject, expected_gramm) %>%
  summarize(mean_z_score = mean(z_score)) %>%
  ggplot(aes(y = mean_z_score,
             x = subject)) +
  geom_point(aes(col = expected_gramm)) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

The following table summarizes the average ratings for each condition.

# Remove data from subjects 377, 387 in the raw data
raw_results_mt %>% subset(subject != "377") %>% subset(subject != "387") %>% droplevels -> raw_results_mt_cln

# ...then separate fillers and experimental sentences
raw_results_mt_cln %>% subset(item_type == "experimental") %>% droplevels -> experiment_data_mt_cln
raw_results_mt_cln %>% subset(item_type == "filler") %>% droplevels -> filler_data_mt_cln

# Reorder context factor levels to mirror discussion (object, predicate, existential)
experiment_data_mt_cln$context <- relevel(experiment_data_mt_cln$context, "predicate")
experiment_data_mt_cln$context <- relevel(experiment_data_mt_cln$context, "object")
# Reorder dep_length factor levels to standard (baseline first)
experiment_data_mt_cln$dep_length <- relevel(experiment_data_mt_cln$dep_length, "short")
# Reorder ec_type factor levels to standard (baseline first)
experiment_data_mt_cln$ec_type <- relevel(experiment_data_mt_cln$ec_type, "non-island")

# Make sure ratings data is numeric so it can be averaged
experiment_data_mt_cln$rating %<>% as.numeric

# Group together by conditions to get averages for each condition
experiment_data_mt_cln %>% group_by(context, ec_type, dep_length) %>%
  summarize(mean_rating = mean(rating),
            sd_rating = sd(rating),
            n = n(),
            se_rating = sd_rating/sqrt(n)) -> descriptive_summary_mt

# Save this summary for use in external scripts
# saveRDS(descriptive_summary_mt, file="expt3_descriptive_summary.rds")
print(descriptive_summary_mt)

The following table visualizes the ratings data. Error bars represent standard errors.

descriptive_summary_mt %>%
  ggplot(aes(x = dep_length,
             y = mean_rating,
             ymin = 1,
             ymax = 6,
             colour = ec_type,
             group = ec_type)) -> descriptive_plot_mt

descriptive_plot_mt + facet_grid(.~context) +
  labs(title = "Ratings by context (MTurk)",
       x = "Dependency length",
       y = "Mean rating",
       colour = "Dependency length") +
  scale_color_discrete("Embedded clause type", labels = c("island", "non-island")) +
  geom_errorbar(aes(ymin = mean_rating - se_rating,
                    ymax = mean_rating + se_rating),
                    width = 0.15) +
  geom_point(aes(col = ec_type),
             size = 2) +
  scale_y_continuous(breaks = seq(1:6)) +
  theme(panel.grid.minor = element_blank()) -> descriptive_plot_mt
print(descriptive_plot_mt)

3.2 Calculating the DD scores (island strength)

The following code z-scores the ratings so that they are comparable across experiments. To do this, we start with both experimental and filler data, and group by subject. Each subject’s rating is then z-scored, and the z-scores for each condition are averaged after ungrouping by subject.

# Copy the data to a new data frame for safe-keeping of the original
raw_results_mt_cln -> raw_results_mt_cln_shrt
# Paste the ec_type and dep_length columns together so that conditions (ignoring context) are represented by a single cell in the data frame
raw_results_mt_cln_shrt$ec_typeXdep_length <- paste(raw_results_mt_cln_shrt$ec_type, "x", raw_results_mt_cln_shrt$dep_length)

# Get z-scores
raw_results_mt_cln_shrt %>%
  group_by(subject) %>% # Group raw results by subject
  mutate(z_rating = scale(rating)) %>% # Get z-scores for each subject's ratings
  ungroup %>% # Bring subjects back together
  subset(item_type == "experimental") %>% droplevels %>% # Remove fillers
  group_by(context, ec_typeXdep_length, item_set) %>% # Group by condition and item set
  summarize(mean_z_rating = mean(z_rating)) %>% # Get the mean z-score for each condition per item set
  group_by(context, ec_typeXdep_length) %>% # Group this summary by condition
  summarize(mean_z_ratings = mean(mean_z_rating)) -> summary_zscores # Get the mean of the mean z-scores
print(summary_zscores)

Now, we’ll calculate the DDs using the summary table from above. Subtracting the island|long average from the non-island|long average yields the combined cost of complexity and extracting out of an island. This difference is called D1. Subtracting the island|short average from the non-island|short average yields D2, which represents the isolated cost of complexity. D1-D2 then yields the isolated cost of extracting out of the island. Each difference is given for each environment considered in this experiment.

# Make table for DDs by making the conditions into columns & filling in the cells with the avg'd z-scores
z_DDs <- summary_zscores %>% spread(ec_typeXdep_length, mean_z_ratings)

# Calculate differences
z_DDs$D1 <- z_DDs$`non-island x long` - z_DDs$`island x long`
z_DDs$D2 <- z_DDs$`non-island x short` - z_DDs$`island x short`
z_DDs$DD <- z_DDs$D1 - z_DDs$D2

# Make the column names shorter so they'll all fit in the same table
colnames(z_DDs)[colnames(z_DDs) == "island x long"] <- "isl x long"
colnames(z_DDs)[colnames(z_DDs) == "island x short"] <- "isl x shrt"
colnames(z_DDs)[colnames(z_DDs) == "non-island x long"] <- "nonisl x long"
colnames(z_DDs)[colnames(z_DDs) == "non-island x short"] <- "nonisl x shrt"

options(digits = 3)
print(z_DDs)

3.3 Ordinal regression analysis

3.3.1 Predictions

  • General island effect (would show up as an interaction between ec_type and dep_length)
  • Effect of contrast on transparency
    • Would show up as a three-way interaction between ec_type, dep_length, and different context factors

3.3.2 Contrasts

Set the contrasts appropriately for each factor

# Helmert contrast for three-level factor
contrasts(experiment_data_mt_cln$context) <- "contr.helmert"
# Assigning contrasts in above way doesn't group the factors appropriately (it would be more appropriate to group existential and predicate factors together, and to compare the two of these to the object factor)
# Assign contrasts manually (the first row is fine; I want to switch the second and third rows' values)
contrasts(experiment_data_mt_cln$context)[1,] <- c(0, 2)
contrasts(experiment_data_mt_cln$context)[2,] <- c(1, -1)
contrasts(experiment_data_mt_cln$context)[3,] <- c(-1, -1)

# Relabel contrast column names for context factor
dimnames(contrasts(experiment_data_mt_cln$context))[[2]] <- c("BE", "TRANSITIVITY")

# Check again
contrasts(experiment_data_mt_cln$context)
          BE TRANSITIVITY
object     0            2
predicate  1           -1
exist     -1           -1
# Fix contrasts for dep_length factor
contrasts(experiment_data_mt_cln$dep_length) <- c(-0.5, 0.5)
# Check
contrasts(experiment_data_mt_cln$dep_length)
      [,1]
short -0.5
long   0.5
# Fix contrasts for ec_type factor
contrasts(experiment_data_mt_cln$ec_type) <- c(-0.5, 0.5)
# Check
contrasts(experiment_data_mt_cln$ec_type)
           [,1]
non-island -0.5
island      0.5

3.3.3 Simple effects analysis

# Make ratings a factor
experiment_data_mt_cln$rating %<>% as.factor
experiment_data_mt_cln$subject %<>% as.factor

# Save data for use elsewhere
saveRDS(experiment_data_mt_cln, "expt3_data_cln.rds")

# Simple effects analysis
timeinit <- Sys.time()
clm(rating ~ context * dep_length * ec_type, data = experiment_data_mt_cln) -> clm_analysis_expt3_mt
timeend <- Sys.time()
timeend - timeinit
Time difference of 1.07 secs
summary(clm_analysis_expt3_mt)
formula: rating ~ context * dep_length * ec_type
data:    experiment_data_mt_cln

Coefficients:
                                         Estimate Std. Error z value Pr(>|z|)    
contextBE                                 -0.4029     0.0544   -7.41  1.3e-13 ***
contextTRANSITIVITY                       -0.2428     0.0312   -7.78  7.4e-15 ***
dep_length1                               -0.9581     0.0895  -10.70  < 2e-16 ***
ec_type1                                  -0.4736     0.0882   -5.37  7.9e-08 ***
contextBE:dep_length1                      0.2519     0.1078    2.34    0.019 *  
contextTRANSITIVITY:dep_length1            0.0465     0.0618    0.75    0.452    
contextBE:ec_type1                         0.2143     0.1077    1.99    0.047 *  
contextTRANSITIVITY:ec_type1              -0.0786     0.0618   -1.27    0.203    
dep_length1:ec_type1                      -0.7264     0.1760   -4.13  3.7e-05 ***
contextBE:dep_length1:ec_type1             0.0554     0.2153    0.26    0.797    
contextTRANSITIVITY:dep_length1:ec_type1  -0.2808     0.1236   -2.27    0.023 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Threshold coefficients:
    Estimate Std. Error z value
1|2  -2.6015     0.0922  -28.23
2|3  -1.2755     0.0606  -21.06
3|4  -0.4613     0.0527   -8.75
4|5   0.3668     0.0523    7.02
5|6   1.3992     0.0626   22.37

3.3.4 Some notes

  • context1 is the exist-predicate comparison
  • context2 is the object-[exist-predicate] comparison

3.3.5 Observations/interpretations

  • Main effects
    • context1 (exist-object comparison)
    • context2 ([exist-object]-predicate comparison)
    • dependency length (dep_length)
    • embedded clause type (ec_type)
  • Two-way interactions
    • Significant interaction (p = 5.8*10-6) between dep_length and ec_type (island effect)
    • Significant interaction (p = 0.005) between context1 (exist-predicate) and dep_length (regardless of ec_type)
      • (Suggests that either the existential or the predicate context increases transparency whether the embedded clause is an island or not(?))
    • No significant interaction between context2 ([exist-predicate]-object) and dep_length
    • Significant interaction (p = 0.026) between context1 (exist-predicate) and ec_type
      • Suggests that either the existential or the predicate context affects the impact of ec_type, regardless of dep_length
  • Three-way interactions
    • Significant interaction (p = 0.038) between context2 ([exist-predicate]-object), dep_length, and ec_type
      • Suggests that existential and predicate contexts are more transparent to extraction than the object context (coefficient is negative)
    • No interaction (p = 0.921) between context1 (exist-predicate), dep_length, and ec_type
      • Suggests that existential and predicate contexts do not differ in transparency to extraction (compared to each other)

3.3.6 Mixed effects analysis

The following code chunk was run on the UCSC hummingbird cluster using the data saved above.

# Read in the data saved from personal computer
readRDS("expt3_data_cln.rds") -> expt3_data_cln
# Perform a mixed effects analysis by subjects and by items
clmm(data = expt3_data_cln,
     formula = rating ~ context * ec_type * dep_length +
       (1 + context * ec_type * dep_length | subject) +
       (1 + context * ec_type * dep_length | item_set)
     ) -> expt3_clmm_full
# Save clmm analysis
saveRDS(object = expt3_clmm_full, file = "expt3_clmm_full.rds")

The following code chunk summarizes the results of the clmm analysis run on the cluster.

# Pull in full clmm that was run on the hummingbird cluster
readRDS("expt3_clmm_full.rds") -> clmm_3_analysis_expt3
summary(clmm_3_analysis_expt3)
Cumulative Link Mixed Model fitted with the Laplace approximation

formula: rating ~ context * ec_type * dep_length + (1 + context * ec_type *  
    dep_length | subject) + (1 + context * ec_type * dep_length |      item_set)
data:    expt3_data_cln

Random effects:
 Groups   Name                                               Variance Std.Dev. Corr                
 subject  (Intercept)                                        5.602    2.367                        
          contextobject                                      2.709    1.646    -0.497              
          contextpredicate                                   2.793    1.671    -0.274  0.504       
          ec_typenon-island                                  2.555    1.598    -0.365  0.069  0.564
          dep_lengthshort                                    4.942    2.223    -0.491 -0.253  0.242
          contextobject:ec_typenon-island                    3.833    1.958     0.487 -0.640 -0.406
          contextpredicate:ec_typenon-island                 3.794    1.948     0.218 -0.363 -0.838
          contextobject:dep_lengthshort                      2.531    1.591     0.578 -0.519 -0.350
          contextpredicate:dep_lengthshort                   3.390    1.841     0.179 -0.056 -0.684
          ec_typenon-island:dep_lengthshort                  3.949    1.987    -0.209  0.192 -0.387
          contextobject:ec_typenon-island:dep_lengthshort    5.251    2.291     0.121  0.129  0.046
          contextpredicate:ec_typenon-island:dep_lengthshort 8.124    2.850     0.432 -0.107  0.359
 item_set (Intercept)                                        0.587    0.766                        
          contextobject                                      0.262    0.512     0.202              
          contextpredicate                                   0.392    0.626    -0.648  0.279       
          ec_typenon-island                                  0.406    0.637     0.742  0.290 -0.084
          dep_lengthshort                                    0.465    0.682    -0.589  0.347  0.798
          contextobject:ec_typenon-island                    1.234    1.111    -0.861 -0.305  0.614
          contextpredicate:ec_typenon-island                 0.269    0.519    -0.712 -0.249  0.620
          contextobject:dep_lengthshort                      0.786    0.887     0.070 -0.821 -0.616
          contextpredicate:dep_lengthshort                   0.619    0.787     0.688 -0.397 -0.620
          ec_typenon-island:dep_lengthshort                  0.758    0.871    -0.018 -0.441  0.342
          contextobject:ec_typenon-island:dep_lengthshort    5.579    2.362    -0.008  0.278 -0.259
          contextpredicate:ec_typenon-island:dep_lengthshort 4.078    2.019    -0.163  0.186 -0.374
                                                         
                                                         
                                                         
                                                         
                                                         
  0.855                                                  
 -0.620 -0.324                                           
 -0.855 -0.512  0.654                                    
 -0.387 -0.277  0.751  0.473                             
 -0.837 -0.633  0.540  0.824  0.490                      
 -0.791 -0.547  0.473  0.723  0.171  0.817               
  0.158 -0.035 -0.557 -0.295 -0.695 -0.397 -0.430        
  0.544  0.204 -0.371 -0.578 -0.014 -0.709 -0.904  0.399 
                                                         
                                                         
                                                         
                                                         
 -0.184                                                  
 -0.700  0.650                                           
 -0.480  0.175  0.644                                    
 -0.362 -0.590  0.111  0.046                             
  0.621 -0.764 -0.704 -0.371  0.353                      
  0.299  0.036  0.275  0.422  0.186  0.266               
 -0.158 -0.380 -0.441 -0.019 -0.186  0.069 -0.723        
 -0.662 -0.052  0.061 -0.199  0.182 -0.448 -0.853  0.493 
Number of groups:  subject 46,  item_set 36 

Coefficients:
                                         Estimate Std. Error z value Pr(>|z|)    
contextBE                                 -0.7346     0.1046   -7.03  2.1e-12 ***
contextTRANSITIVITY                       -0.4327     0.0626   -6.92  4.7e-12 ***
ec_type1                                   0.7973     0.1411    5.65  1.6e-08 ***
dep_length1                                1.7243     0.2470    6.98  2.9e-12 ***
contextBE:ec_type1                        -0.3824     0.1967   -1.94    0.052 .  
contextTRANSITIVITY:ec_type1               0.0966     0.1080    0.89    0.371    
contextBE:dep_length1                     -0.4487     0.1806   -2.49    0.013 *  
contextTRANSITIVITY:dep_length1           -0.0781     0.0959   -0.81    0.415    
ec_type1:dep_length1                      -1.2935     0.2872   -4.50  6.7e-06 ***
contextBE:ec_type1:dep_length1             0.2203     0.3764    0.59    0.558    
contextTRANSITIVITY:ec_type1:dep_length1  -0.4544     0.2109   -2.15    0.031 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Threshold coefficients:
    Estimate Std. Error z value
1|2   -4.432      0.329  -13.47
2|3   -2.369      0.308   -7.69
3|4   -0.976      0.302   -3.23
4|5    0.552      0.301    1.83
5|6    2.467      0.309    7.99

4 Simulation

4.1 Actual response distributions

# Subset the island extraction cases from the data
experiment_data_mt_cln %>%
  subset(dep_length == "long" & ec_type == "island") %>%
  droplevels %>%
  ggplot(aes(rating)) +
  geom_histogram(stat = "count") + 
  facet_grid(.~context) -> resp_dist_hist
Ignoring unknown parameters: binwidth, bins, pad
print(resp_dist_hist)

if('package:dplyr' %in% search()) {
  detach(package:dplyr, unload = TRUE)
  } else {}
library(plyr)
library(mixtools)
mixtools package, version 1.1.0, Released 2017-03-10
This package is based upon work supported by the National Science Foundation under Grant No. SES-0518772.
library(gridExtra)

filler_data_mt_cln$rating %<>% as.numeric

filler_data_ungramm <- subset(filler_data_mt_cln, expected_gramm == "ungramm")$rating
filler_data_gramm <- subset(filler_data_mt_cln, expected_gramm == "gramm")$rating

experiment_data_mt_cln$rating %<>% as.numeric

data_object <- subset(experiment_data_mt_cln, context == "object" & dep_length == "long" & ec_type == "island")$rating
data_predicate <- subset(experiment_data_mt_cln, context == "predicate" & dep_length == "long" & ec_type == "island")$rating
data_existential <- subset(experiment_data_mt_cln, context == "exist" & dep_length == "long" & ec_type == "island")$rating
## These functions and those defined in following chunks are due to Brian Dillon, via Jed Pizarro-Guevara. ##

# Define functions to create discrete and gradient models.

# create.discrete/gradient returns the parameters of a multinomial distribution over responses.
# It takes grammatical and ungrammatical reference sets (actual data), pi (relative weight of ungrammatical distribution), and N (number of data points to be sampled in estimating the distribution)
# These functions have been modified to work for data on a 6-point Likert scale, instead of 7-point.

create.discrete = function(gram.ref, ungram.ref, pi, num = length(gram.ref), smooth = T) {
  
        samples.discrete = c(
            sample(gram.ref, round((1-pi)*num), replace = T), 
            sample(ungram.ref, round(pi*num), replace = T)
        )
        if (smooth) {
            prob.discrete = (tabulate(samples.discrete, nbins = 6)+1)/(length(samples.discrete)+6)
        } else {
            prob.discrete = (tabulate(samples.discrete, nbins = 6))/(length(samples.discrete))  
        }
        return(prob.discrete)
}

create.gradient = function(gram.ref, ungram.ref, pi, num = length(gram.ref), smooth = T) {
  
        samples.gradient = round(
            (1-pi)*sample(gram.ref, num, replace = T)+pi*sample(ungram.ref, num, replace = T)
        )
        if (smooth) {
            prob.gradient = (tabulate(samples.gradient, nbins = 6)+1)/(length(samples.gradient)+6)
        } else {    
            prob.gradient = (tabulate(samples.gradient, nbins = 6))/(length(samples.gradient))  
        }
        return(prob.gradient)
}
# Define functions to determine the fit of a given value of pi for the dataset

# fit.gradient/discrete.pi is a function used to maximize pi parameter given a dataset. It takes the same parameters as the mixture creating functions, plus a test parameter. Test is the test distribution to be modeled.
# fit.gradient/discrete.pi returns the RMSD (root-mean-square deviation) between the mean of the mixture and admixture model and the empirical mean of the test distribution.

fit.gradient.pi = function(pi, gram.ref, ungram.ref, test) {
        gradient.model = create.gradient(gram.ref, ungram.ref, pi, smooth = F)
        gradient.mean = sum(gradient.model*c(1:6))
        test.mean = mean(test)
        rmsd = (gradient.mean-test.mean)^2
        return(rmsd)
}

fit.discrete.pi = function(pi, gram.ref, ungram.ref, test) {
        discrete.model = create.discrete(gram.ref, ungram.ref, pi)
        discrete.mean = sum(discrete.model*c(1:6))
        test.mean = mean(test)
        rmsd = (discrete.mean-test.mean)^2
        return(rmsd)
}
# Define the main simulation function

compare.models = function(gram.dist, ungram.dist, test.dist, chisquare = T) {
  
  optim.discrete.pi = optimize(fit.discrete.pi, interval = c(0, 1), gram.ref = gram.dist, ungram.ref = ungram.dist, test = test.dist)
        for (i in c(1:5)) {
            cur.discrete.pi = optimize(fit.discrete.pi, interval = c(0, 1), gram.ref = gram.dist, ungram.ref = ungram.dist, test = test.dist)
            if (cur.discrete.pi$objective < optim.discrete.pi$objective) {
                optim.discrete.pi = cur.discrete.pi
            }
        }
        discrete.pi = optim.discrete.pi$minimum

        optim.gradient.pi = optimize(fit.gradient.pi, interval = c(0, 1), gram.ref = gram.dist, ungram.ref = ungram.dist, test = test.dist)
        for (i in c(1:5)) {
            cur.gradient.pi = optimize(fit.gradient.pi, interval = c(0, 1), gram.ref = gram.dist, ungram.ref = ungram.dist, test = test.dist)
            if (cur.gradient.pi$objective < optim.gradient.pi$objective) {
                optim.gradient.pi = cur.gradient.pi
            }
        }
        gradient.pi = optim.gradient.pi$minimum
        discrete.model = create.discrete(gram.dist, ungram.dist, discrete.pi)
        gradient.model = create.gradient(gram.dist, ungram.dist, gradient.pi)
        discrete.mean = sum(discrete.model*c(1:6))
      gradient.mean = sum(gradient.model*c(1:6))
      
      # Next step, calculate BIC of test data under each model.

    K = length(discrete.model)-1    ### # of free params in multinomial model... doesn't really matter for BIC difference score, is constant across models.
    
    discrete.bic = -2*sum(dmultinom(tabulate(test.dist, nbins = 6), prob = discrete.model, log = T))+K*log(length(test.dist))
    gradient.bic = -2*sum(dmultinom(tabulate(test.dist, nbins = 6), prob = gradient.model, log = T))+K*log(length(test.dist))
    
    # Next step, convert BIC to BF

    bf = exp(-.5*(discrete.bic-gradient.bic))
    
    # Wrap it up
    
    my.fit = {}
    my.fit[["Discrete"]] = discrete.model
    my.fit[["Gradient"]] = gradient.model
    my.fit[["Test"]] = (tabulate(test.dist, nbins = 6))/(length(test.dist)) 
    my.fit[["Data mean"]] = mean(test.dist)
    my.fit[["Discrete predicted mean"]] = discrete.mean
    my.fit[["Gradient predicted mean"]] = gradient.mean
    my.fit[["Discrete BIC"]] = discrete.bic
    my.fit[["Gradient BIC"]] = gradient.bic
    my.fit[["BF"]] = bf
    my.fit[["Stats"]] = c(discrete.mean, gradient.mean, discrete.pi, gradient.pi, discrete.bic-gradient.bic, bf, discrete.mean, gradient.mean)
    
    if (chisquare) {
        # Calculate X2 values under two models
        # simulate.p.value set to T because of very low expected counts on some models
        chisq.discrete = chisq.test(tabulate(test.dist, nbins = 6), p = discrete.model, simulate.p.value = T)
        chisq.gradient = chisq.test(tabulate(test.dist, nbins = 6), p = gradient.model, simulate.p.value = T)
        my.fit[["Discrete Chisq"]] = chisq.discrete
        my.fit[["Gradient Chisq"]] = chisq.gradient
    }
    
    my.fit[["pi"]] = c(discrete.pi, gradient.pi)
    
    return(my.fit)
    
}

summary.figure = function(my.fit) {
    par(mfrow = c(3, 1))
    max = max(c(my.fit$Test, my.fit$Discrete, my.fit$Discrete))
    max = ceiling(max*10)/10
    barplot(my.fit$Test, main = "Test Distribution", ylim = c(0, max))
    barplot(my.fit$Discrete, main = "Discrete Distribution", ylim = c(0, max))
    barplot(my.fit$Gradient, main = "Gradient Distribution", ylim = c(0, max))
}
# Run the simulation on the transitive object cases
# Use ungrammatical fillers as ungram.ref, and grammatical fillers as gram.ref
# Use transitive object condition as test

# gram.ref, ungram.ref, test
#sim_object <- compare.models(filler_data_gramm, filler_data_ungramm, data_object)
#sim_object
#summary.figure(sim_object)

outcomes_object <- {}
sim_object.discrete <- {}
sim_object.gradient <- {}

for (i in c(1:500)) {
    sim_object = compare.models(filler_data_gramm, filler_data_ungramm, data_object)
    outcomes_object <- cbind(outcomes_object, sim_object$Stats)
    sim_object.discrete <- cbind(sim_object.discrete, sim_object$Discrete)
    sim_object.gradient <- cbind(sim_object.gradient, sim_object$Gradient)
}

paste(round(c(mean(outcomes_object[2,]), # mean predicted means under gradient
              mean(outcomes_object[4,]), # mean gradient pi
              mean(outcomes_object[1,]), # mean predicted means under discrete
              mean(outcomes_object[3,]), # mean discrete pi
              mean(outcomes_object[5,]), # mean BIC difference
              range(outcomes_object[5,]), # range of BIC difference
              mean(outcomes_object[6,])), # mean Bayes factor
            digits=2)) -> results.sim_object

results.sim_object %>% t %>% data.frame -> results.sim_object
colnames(results.sim_object) <- c("Gradient_mean", "Gradient_pi", "Discrete_mean", "Discrete_pi", "BIC_mean", "BIC_min" ,"BIC_max", "BF")

print(results.sim_object)

### See how many have BIC > 0 ###
outcomes_object[5,] %>% data.frame -> outcomes.sim_object
outcomes.sim_object %>% subset(. > 0) %>% nrow
[1] 374
# Run the simulation on the predicate cases
# Use ungrammatical fillers as ungram.ref, and grammatical fillers as gram.ref
# Use predicate condition as test

# gram.ref, ungram.ref, test
#sim_predicate <- compare.models(filler_data_gramm, filler_data_ungramm, data_object)
#sim_predicate
#summary.figure(sim_predicate)

outcomes_predicate <- {}
sim_predicate.discrete <- {}
sim_predicate.gradient <- {}

for (i in c(1:500)) {
    sim_predicate = compare.models(filler_data_gramm, filler_data_ungramm, data_predicate)
    outcomes_predicate <- cbind(outcomes_predicate, sim_predicate$Stats)
    sim_predicate.discrete <- cbind(sim_predicate.discrete, sim_predicate$Discrete)
    sim_predicate.gradient <- cbind(sim_predicate.gradient, sim_predicate$Gradient)
}

paste(round(c(mean(outcomes_predicate[2,]), # mean predicted means under gradient
              mean(outcomes_predicate[4,]), # mean gradient pi
              mean(outcomes_predicate[1,]), # mean predicted means under discrete
              mean(outcomes_predicate[3,]), # mean discrete pi
              mean(outcomes_predicate[5,]), # mean BIC difference
              range(outcomes_predicate[5,]), # range of BIC difference
              mean(outcomes_predicate[6,])), # mean Bayes factor
            digits=2)) -> results.sim_predicate

results.sim_predicate %>% t %>% data.frame -> results.sim_predicate
colnames(results.sim_predicate) <- c("Gradient_mean", "Gradient_pi", "Discrete_mean", "Discrete_pi", "BIC_mean", "BIC_min" ,"BIC_max", "BF")

print(results.sim_predicate)

### See how many have BIC > 0 ###
outcomes_predicate[5,] %>% data.frame -> outcomes.sim_predicate
outcomes.sim_predicate %>% subset(. > 0) %>% nrow
[1] 0
# Run the simulation on the existential cases
# Use ungrammatical fillers as ungram.ref, and grammatical fillers as gram.ref
# Use existential condition as test

# gram.ref, ungram.ref, test
#sim_existential <- compare.models(filler_data_gramm, filler_data_ungramm, data_object)
#sim_existential
#summary.figure(sim_existential)

outcomes_existential <- {}
sim_existential.discrete <- {}
sim_existential.gradient <- {}

for (i in c(1:500)) {
    sim_existential = compare.models(filler_data_gramm, filler_data_ungramm, data_existential)
    outcomes_existential <- cbind(outcomes_existential, sim_existential$Stats)
    sim_existential.discrete <- cbind(sim_existential.discrete, sim_existential$Discrete)
    sim_existential.gradient <- cbind(sim_existential.gradient, sim_existential$Gradient)
}

paste(round(c(mean(outcomes_existential[2,]), # mean predicted means under gradient
              mean(outcomes_existential[4,]), # mean gradient pi
              mean(outcomes_existential[1,]), # mean predicted means under discrete
              mean(outcomes_existential[3,]), # mean discrete pi
              mean(outcomes_existential[5,]), # mean BIC difference
              range(outcomes_existential[5,]), # range of BIC difference
              mean(outcomes_existential[6,])), # mean Bayes factor
            digits=2)) -> results.sim_existential

results.sim_existential %>% t %>% data.frame -> results.sim_existential
colnames(results.sim_existential) <- c("Gradient_mean", "Gradient_pi", "Discrete_mean", "Discrete_pi", "BIC_mean", "BIC_min" ,"BIC_max", "BF")

print(results.sim_existential)

### See how many have BIC > 0 ###
outcomes_existential[5,] %>% data.frame -> outcomes.sim_existential
outcomes.sim_existential %>% subset(. > 0) %>% nrow
[1] 0

Sprouse, Jon, Matthew W. Wagers, and Colin Phillips. 2012. “A test of the relation between working memory capacity and syntactic island effects.” Language 88 (1): 82–123.

LS0tDQp0aXRsZTogIlJDIHN1YmV4dHJhY3Rpb24gaW4gRW5nbGlzaDogRXhwZXJpbWVudCAzIG5vdGVib29rIg0KYXV0aG9yOiAiSmFrZSBXLiBWaW5jZW50ICgmIzEwNjsmIzExOTsmIzExODsmIzEwNTsmIzExMDsmIzk5OyYjMTAxO24mIzY0OyYjMTE3O2MmIzExNTtjLmUmIzEwMDt1KSINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogDQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IGZsYXRseQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNzczogc3R5bGUuY3NzDQogIHBkZl9kb2N1bWVudDogDQogICAga2VlcF90ZXg6IHllcw0KYmlibGlvZ3JhcGh5OiAuLi8uLi8uLi8uLi8uLi8uLi9Eb2N1bWVudHMvbGlicmFyeS5iaWINCi0tLQ0KDQpgYGB7ciBsaWJyYXJpZXMsIGVjaG8gPSBGQUxTRSwgaW5jbHVkZSA9IEZBTFNFfQ0KIyBHZXQgbGlicmFyaWVzDQojIE5vdGU6IGNzdiBmaWxlcyBpbiBDOi9Vc2Vycy9qYWtldy9PbmVEcml2ZS9Eb2N1bWVudHMvU2Nob29sL1VDU0MgR3JhZCBzY2hvb2wvUVAyL0V4cGVyaW1lbnQgMy9yZXN1bHRzDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KG9yZGluYWwpDQpyZXF1aXJlKGtuaXRyKQ0KZ2V0d2QoKQ0KYGBgDQoNCiMgTW90aXZhdGlvbg0KDQpFeHBlcmltZW50IDMgd2FzIGRlc2lnbmVkIHRvIGVsaW1pbmF0ZSB0aGUgcG90ZW50aWFsIGNvbmZvdW5kcyBvZiBFeHBlcmltZW50IDIncyBkZXNpZ24gYnkgY29tcGFyaW5nIGV4dHJhY3Rpb24gZnJvbSBSQ3MgaW4gdGhyZWUgZGlmZmVyZW50IGVudmlyb25tZW50czogdGhlIHBpdm90IG9mIGFuIGV4aXN0ZW50aWFsLCB3aXRoaW4gYSBwcmVkaWNhdGUgbm9taW5hbCwgYW5kIHdpdGhpbiBhIHRyYW5zaXRpdmUgb2JqZWN0Lg0KDQojIERlc2lnbg0KDQpUaGlzIGV4cGVyaW1lbnQgcmV0dXJucyB0byB0aGUgbGVuZ3RoIGJ5IGNvbXBsZXhpdHkgZGVzaWduIHV0aWxpemVkIGJ5IEBTcHJvdXNlMjAxMiBhbmQgYWRkcyBhbiBhZGRpdGlvbmFsIDxzcGFuIGNsYXNzPSJzbWFsbGNhcHMiPmVudmlyb25tZW50PC9zcGFuPiBmYWN0b3Igd2l0aCB0aHJlZSBsZXZlbHMsIHNob3duIGJlbG93LiBUaGlzIHJlc3VsdGVkIGluIGEgM8OXMsOXMiBkZXNpZ24sIHdpdGggMTIgY29uZGl0aW9ucyBwZXIgaXRlbS4gQSBzYW1wbGUgaXRlbSBpcyBzaG93biBpbiAyLg0KDQoxLiAqKkZhY3RvcnMqKg0KICAgIGEuIDxzcGFuIGNsYXNzPSJzbWFsbGNhcHMiPkVudmlyb25tZW50PC9zcGFuPg0KICAgICAgICBpLiA8c3BhbiBjbGFzcz0ic21hbGxjYXBzIj5vYmplY3Q8L3NwYW4+DQogICAgICAgIGlpLiA8c3BhbiBjbGFzcz0ic21hbGxjYXBzIj5wcmVkaWNhdGU8L3NwYW4+DQogICAgICAgIGlpaS4gPHNwYW4gY2xhc3M9InNtYWxsY2FwcyI+ZXhpc3RlbnRpYWw8L3NwYW4+DQogICAgYi4gU3RydWN0dXJlDQogICAgICAgIGkuIDxzcGFuIGNsYXNzPSJzbWFsbGNhcHMiPmlzbGFuZDwvc3Bhbj4gKFJDKQ0KICAgICAgICBpaS4gPHNwYW4gY2xhc3M9InNtYWxsY2FwcyI+bm9uLWlzbGFuZDwvc3Bhbj4gKGVtYmVkZGVkICp0aGF0Ki1jbGF1c2UpDQogICAgYy4gTGVuZ3RoDQogICAgICAgIGkuIDxzcGFuIGNsYXNzPSJzbWFsbGNhcHMiPmxvbmc8L3NwYW4+IChlbWJlZGRlZCBvYmplY3QpDQogICAgICAgIGlpLiA8c3BhbiBjbGFzcz0ic21hbGxjYXBzIj5zaG9ydDwvc3Bhbj4gKG1hdHJpeCBzdWJqZWN0KQ0KDQoyLiAqKlNhbXBsZSBpdGVtKioNCiAgICBhLiBXaG8gc2FpZCB0aGF0IE1pY2hhZWwgcmVtZW1iZXJlZCB0aGF0IG9ubHkgb25lIGpvdXJuYWxpc3QgcmVhZCB0aGlzIGFydGljbGU/PGRpdiBjbGFzcz0iYWxpZ25yaWdodCI+KDxzcGFuIGNsYXNzPSJzbWFsbGNhcHMiPm9iamVjdHxub24taXNsYW5kfHNob3J0PC9zcGFuPik8L2Rpdj4NCiAgICBiLiBXaGljaCBhcnRpY2xlIGRpZCB5b3Ugc2F5IHRoYXQgTWljaGFlbCByZW1lbWJlcmVkIHRoYXQgb25seSBvbmUgam91cm5hbGlzdCByZWFkPzxkaXYgY2xhc3M9ImFsaWducmlnaHQiPig8c3BhbiBjbGFzcz0ic21hbGxjYXBzIj5vYmplY3R8bm9uLWlzbGFuZHxsb25nPC9zcGFuPik8L2Rpdj4NCiAgICBjLiBXaG8gc2FpZCB0aGF0IE1pY2hhZWwgcmVtZW1iZXJlZCB0aGUgb25seSBqb3VybmFsaXN0IHdobyByZWFkIHRoaXMgYXJ0aWNsZT88ZGl2IGNsYXNzPSJhbGlnbnJpZ2h0Ij4oPHNwYW4gY2xhc3M9InNtYWxsY2FwcyI+b2JqZWN0fGlzbGFuZHxzaG9ydDwvc3Bhbj4pPC9kaXY+DQogICAgZC4gV2hpY2ggYXJ0aWNsZSBkaWQgeW91IHNheSB0aGF0IE1pY2hhZWwgcmVtZW1iZXJlZCB0aGUgb25seSBqb3VybmFsaXN0IHdobyByZWFkPzxkaXYgY2xhc3M9ImFsaWducmlnaHQiPig8c3BhbiBjbGFzcz0ic21hbGxjYXBzIj5vYmplY3R8aXNsYW5kfGxvbmc8L3NwYW4+KTwvZGl2Pg0KICAgIGUuIFdobyBzYWlkIHRoYXQgTWljaGFlbCB0aGlua3MgdGhhdCBvbmx5IG9uZSBqb3VybmFsaXN0IHJlYWQgdGhpcyBhcnRpY2xlPzxkaXYgY2xhc3M9ImFsaWducmlnaHQiPig8c3BhbiBjbGFzcz0ic21hbGxjYXBzIj5wcmVkaWNhdGV8bm9uLWlzbGFuZHxzaG9ydDwvc3Bhbj4pPC9kaXY+DQogICAgZi4gV2hpY2ggYXJ0aWNsZSBkaWQgeW91IHNheSB0aGF0IE1pY2hhZWwgdGhpbmtzIHRoYXQgb25seSBvbmUgam91cm5hbGlzdCByZWFkPzxkaXYgY2xhc3M9ImFsaWducmlnaHQiPig8c3BhbiBjbGFzcz0ic21hbGxjYXBzIj5wcmVkaWNhdGV8bm9uLWlzbGFuZHxsb25nPC9zcGFuPik8L2Rpdj4NCiAgICBnLiBXaG8gc2FpZCB0aGF0IE1pY2hhZWwgdGhpbmtzIHRoYXQgaGUgaXMgdGhlIG9ubHkgam91cm5hbGlzdCB3aG8gcmVhZCB0aGlzIGFydGljbGU/PGRpdiBjbGFzcz0iYWxpZ25yaWdodCI+KDxzcGFuIGNsYXNzPSJzbWFsbGNhcHMiPnByZWRpY2F0ZXxpc2xhbmR8c2hvcnQ8L3NwYW4+KTwvZGl2Pg0KICAgIGguIFdoaWNoIGFydGljbGUgZGlkIHlvdSBzYXkgdGhhdCBNaWNoYWVsIHRoaW5rcyB0aGF0IGhlIGlzIHRoZSBvbmx5IGpvdXJuYWxpc3Qgd2hvIHJlYWQ/PGRpdiBjbGFzcz0iYWxpZ25yaWdodCI+KDxzcGFuIGNsYXNzPSJzbWFsbGNhcHMiPnByZWRpY2F0ZXxpc2xhbmR8bG9uZzwvc3Bhbj4pPC9kaXY+DQogICAgaS4gV2hvIHNhaWQgdGhhdCB0aGVyZSB3YXMgb25seSBvbmUgc2VuYXRvciByZWFkaW5nIHRoaXMgYXJ0aWNsZT88ZGl2IGNsYXNzPSJhbGlnbnJpZ2h0Ij4oPHNwYW4gY2xhc3M9InNtYWxsY2FwcyI+ZXhpc3RlbnRpYWx8bm9uLWlzbGFuZHxzaG9ydDwvc3Bhbj4pPC9kaXY+DQogICAgai4gV2hpY2ggYXJ0aWNsZSBkaWQgeW91IHNheSB0aGF0IHRoZXJlIHdhcyBvbmx5IG9uZSBzZW5hdG9yIHJlYWRpbmc/PGRpdiBjbGFzcz0iYWxpZ25yaWdodCI+KDxzcGFuIGNsYXNzPSJzbWFsbGNhcHMiPmV4aXN0ZW50aWFsfG5vbi1pc2xhbmR8bG9uZzwvc3Bhbj4pPC9kaXY+DQogICAgay4gV2hvIHNhaWQgdGhhdCB0aGVyZSBpcyBvbmx5IG9uZSBqb3VybmFsaXN0IHdobyByZWFkIHRoaXMgYXJ0aWNsZT88ZGl2IGNsYXNzPSJhbGlnbnJpZ2h0Ij4oPHNwYW4gY2xhc3M9InNtYWxsY2FwcyI+ZXhpc3RlbnRpYWx8aXNsYW5kfHNob3J0PC9zcGFuPik8L2Rpdj4NCiAgICBsLiBXaGljaCBhcnRpY2xlIGRpZCB5b3Ugc2F5IHRoYXQgdGhlcmUgaXMgb25seSBvbmUgam91cm5hbGlzdCB3aG8gcmVhZD88ZGl2IGNsYXNzPSJhbGlnbnJpZ2h0Ij4oPHNwYW4gY2xhc3M9InNtYWxsY2FwcyI+ZXhpc3RlbnRpYWx8aXNsYW5kfGxvbmc8L3NwYW4+KTwvZGl2Pg0KDQojIEFuYWx5c2lzDQpgYGB7ciBzZXR1cH0NCiMgUHVsbCBpbiBmb3JtYXR0ZWQgcmVzdWx0cw0KcmF3X3Jlc3VsdHNfbXQgPC0gcmVhZC5jc3YoInJlc3VsdHNfbXR1cmsvMjAxODA3MDQvMjAxODA3MDRfcmVzdWx0c19mb3JtYXR0ZWRfZml4ZWQuY3N2IikNCg0KIyBSZW5hbWUgMXN0IGNvbHVtbiBoZWFkZXIgYi9jIG9mIGV4Y2VsIGlzc3VlDQpjb2xuYW1lcyhyYXdfcmVzdWx0c19tdClbMV0gPC0gImRhdGVfcmVjZWl2ZWQiDQoNCiMgTWFrZSBzdWJqZWN0IGEgZmFjdG9yDQpyYXdfcmVzdWx0c19tdCRzdWJqZWN0ICU8PiUgYXMuZmFjdG9yDQoNCiMgU2VwYXJhdGUgZXhwZXJpbWVudCBhbmQgZmlsbGVyIGRhdGENCnJhd19yZXN1bHRzX210ICU+JSBzdWJzZXQoaXRlbV90eXBlID09ICJleHBlcmltZW50YWwiKSAlPiUgZHJvcGxldmVscyAtPiBleHBlcmltZW50X2RhdGFfbXQNCnJhd19yZXN1bHRzX210ICU+JSBzdWJzZXQoaXRlbV90eXBlID09ICJmaWxsZXIiKSAlPiUgZHJvcGxldmVscyAtPiBmaWxsZXJfZGF0YV9tdA0KYGBgDQoNCiMjIFBhcnRpY2lwYW50IGluZm9ybWF0aW9uIChiYXNlZCBvbiBmaWxsZXIgcmF0aW5ncykNCg0KVGhlIGZvbGxvd2luZyB0YWJsZSBzdW1tYXJpemVzIHRoZSByYXRpbmdzIGRhdGEgZm9yIGVhY2ggcGFydGljaXBhbnQgKGJhc2VkIG9uIGZpbGxlciBzZW50ZW5jZXMgb25seSksIGluY2x1ZGluZyB0aGUgbWVhbiByYXRpbmdzIHRoZXkgZ2F2ZSB0byBleHBlY3RlZCBncmFtbWF0aWNhbCBmaWxsZXJzIGFuZCBleHBlY3RlZCB1bmdyYW1tYXRpY2FsIGZpbGxlcnMuDQoNCmBgYHtyIGJ5X3BhcnRpY2lwYW50fQ0KIyBMb29rIGF0IHRoZSByZXN1bHRzIGJ5IHBhcnRpY2lwYW50LCBnZXQgbWVhbnMgZm9yIGJvdGggZ3JhbW1hdGljYWwgYW5kIHVuZ3JhbW1hdGljYWwgZmlsbGVycw0KZmlsbGVyX2RhdGFfbXQgJT4lIGdyb3VwX2J5KHN1YmplY3QpICU+JQ0KICBzdW1tYXJpemUobWVhbl9yYXRpbmcgPSBtZWFuKHJhdGluZyksDQogICAgICAgICAgICBzZF9yYXRpbmcgPSBzZChyYXRpbmcpLA0KICAgICAgICAgICAgbiA9IG4oKSwNCiAgICAgICAgICAgIHNlX3JhdGluZyA9IHNkX3JhdGluZy9zcXJ0KG4pLA0KICAgICAgICAgICAgbWVhbl9ncmFtbSA9IG1lYW4ocmF0aW5nW2V4cGVjdGVkX2dyYW1tID09ICJncmFtbSJdKSwNCiAgICAgICAgICAgIG1lYW5fdW5ncmFtbSA9IG1lYW4ocmF0aW5nW2V4cGVjdGVkX2dyYW1tID09ICJ1bmdyYW1tIl0pKSAtPiB3b3JrZXJfc3VtbWFyeQ0KcHJpbnQod29ya2VyX3N1bW1hcnkpDQpgYGANCg0KUGFydGljaXBhbnRzIHdpbGwgYmUgZXhjbHVkZWQgd2hvc2UgYXZlcmFnZSByYXRpbmcgZm9yIHVuZ3JhbW1hdGljYWwgZmlsbGVycyBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gdGhlaXIgYXZlcmFnZSByYXRpbmcgZm9yIGdyYW1tYXRpY2FsIGZpbGxlcnMuIFRoZSBmb2xsb3dpbmcgY29kZSBjaHVuayBpZGVudGlmaWVzIHRoZXNlIHBhcnRpY2lwYW50cy4NCg0KYGBge3IgZ3JhbW1fdW5kZXJfdW5ncmFtbX0NCndvcmtlcl9zdW1tYXJ5ICU+JSBzdWJzZXQobWVhbl91bmdyYW1tID49IG1lYW5fZ3JhbW0pIC0+IGV4Y2x1ZGVkXzENCnByaW50KGV4Y2x1ZGVkXzEpDQpgYGANCg0KSGVyZSdzIGEgdmlzdWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwYXJ0aWNpcGFudHMnIGF2ZXJhZ2UgZmlsbGVyIHJhdGluZ3MuIEVhY2ggcG9pbnQgcmVwcmVzZW50cyB0aGUgYXZlcmFnZSB6LXNjb3JlcyBmb3IgYSBwYXJ0aWNpcGFudCdzIGdyYW1tYXRpY2FsL3VuZ3JhbW1hdGljYWwgZmlsbGVyIHJhdGluZ3MuIFBhcnRpY2lwYW50cyAzNzcgYW5kIDM4NyBzdGFuZCBvdXQgc2luY2UgdGhlIHJlZCBwb2ludCAoYXZlcmFnZSB6LXNjb3JlZCByYXRpbmcgZm9yIGdyYW1tYXRpY2FsIGZpbGxlcnMpIGlzIGJlbG93IHRoZSBibHVlIHBvaW50IChmb3IgdW5ncmFtbWF0aWNhbCBmaWxsZXJzKS4NCg0KYGBge3IgcG90ZW50aWFsX2V4Y2x1c2lvbnN9DQpmaWxsZXJfZGF0YV9tdCAlPiUNCiAgZ3JvdXBfYnkoc3ViamVjdCkgJT4lDQogIG11dGF0ZSh6X3Njb3JlID0gc2NhbGUocmF0aW5nKSkgJT4lDQogIGdyb3VwX2J5KHN1YmplY3QsIGV4cGVjdGVkX2dyYW1tKSAlPiUNCiAgc3VtbWFyaXplKG1lYW5fel9zY29yZSA9IG1lYW4oel9zY29yZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHkgPSBtZWFuX3pfc2NvcmUsDQogICAgICAgICAgICAgeCA9IHN1YmplY3QpKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbCA9IGV4cGVjdGVkX2dyYW1tKSkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSkpDQpgYGANCg0KVGhlIGZvbGxvd2luZyB0YWJsZSBzdW1tYXJpemVzIHRoZSBhdmVyYWdlIHJhdGluZ3MgZm9yIGVhY2ggY29uZGl0aW9uLg0KDQpgYGB7ciBkYXRhX3N1bW1hcnl9DQojIFJlbW92ZSBkYXRhIGZyb20gc3ViamVjdHMgMzc3LCAzODcgaW4gdGhlIHJhdyBkYXRhDQpyYXdfcmVzdWx0c19tdCAlPiUgc3Vic2V0KHN1YmplY3QgIT0gIjM3NyIpICU+JSBzdWJzZXQoc3ViamVjdCAhPSAiMzg3IikgJT4lIGRyb3BsZXZlbHMgLT4gcmF3X3Jlc3VsdHNfbXRfY2xuDQoNCiMgLi4udGhlbiBzZXBhcmF0ZSBmaWxsZXJzIGFuZCBleHBlcmltZW50YWwgc2VudGVuY2VzDQpyYXdfcmVzdWx0c19tdF9jbG4gJT4lIHN1YnNldChpdGVtX3R5cGUgPT0gImV4cGVyaW1lbnRhbCIpICU+JSBkcm9wbGV2ZWxzIC0+IGV4cGVyaW1lbnRfZGF0YV9tdF9jbG4NCnJhd19yZXN1bHRzX210X2NsbiAlPiUgc3Vic2V0KGl0ZW1fdHlwZSA9PSAiZmlsbGVyIikgJT4lIGRyb3BsZXZlbHMgLT4gZmlsbGVyX2RhdGFfbXRfY2xuDQoNCiMgUmVvcmRlciBjb250ZXh0IGZhY3RvciBsZXZlbHMgdG8gbWlycm9yIGRpc2N1c3Npb24gKG9iamVjdCwgcHJlZGljYXRlLCBleGlzdGVudGlhbCkNCmV4cGVyaW1lbnRfZGF0YV9tdF9jbG4kY29udGV4dCA8LSByZWxldmVsKGV4cGVyaW1lbnRfZGF0YV9tdF9jbG4kY29udGV4dCwgInByZWRpY2F0ZSIpDQpleHBlcmltZW50X2RhdGFfbXRfY2xuJGNvbnRleHQgPC0gcmVsZXZlbChleHBlcmltZW50X2RhdGFfbXRfY2xuJGNvbnRleHQsICJvYmplY3QiKQ0KIyBSZW9yZGVyIGRlcF9sZW5ndGggZmFjdG9yIGxldmVscyB0byBzdGFuZGFyZCAoYmFzZWxpbmUgZmlyc3QpDQpleHBlcmltZW50X2RhdGFfbXRfY2xuJGRlcF9sZW5ndGggPC0gcmVsZXZlbChleHBlcmltZW50X2RhdGFfbXRfY2xuJGRlcF9sZW5ndGgsICJzaG9ydCIpDQojIFJlb3JkZXIgZWNfdHlwZSBmYWN0b3IgbGV2ZWxzIHRvIHN0YW5kYXJkIChiYXNlbGluZSBmaXJzdCkNCmV4cGVyaW1lbnRfZGF0YV9tdF9jbG4kZWNfdHlwZSA8LSByZWxldmVsKGV4cGVyaW1lbnRfZGF0YV9tdF9jbG4kZWNfdHlwZSwgIm5vbi1pc2xhbmQiKQ0KDQojIE1ha2Ugc3VyZSByYXRpbmdzIGRhdGEgaXMgbnVtZXJpYyBzbyBpdCBjYW4gYmUgYXZlcmFnZWQNCmV4cGVyaW1lbnRfZGF0YV9tdF9jbG4kcmF0aW5nICU8PiUgYXMubnVtZXJpYw0KDQojIEdyb3VwIHRvZ2V0aGVyIGJ5IGNvbmRpdGlvbnMgdG8gZ2V0IGF2ZXJhZ2VzIGZvciBlYWNoIGNvbmRpdGlvbg0KZXhwZXJpbWVudF9kYXRhX210X2NsbiAlPiUgZ3JvdXBfYnkoY29udGV4dCwgZWNfdHlwZSwgZGVwX2xlbmd0aCkgJT4lDQogIHN1bW1hcml6ZShtZWFuX3JhdGluZyA9IG1lYW4ocmF0aW5nKSwNCiAgICAgICAgICAgIHNkX3JhdGluZyA9IHNkKHJhdGluZyksDQogICAgICAgICAgICBuID0gbigpLA0KICAgICAgICAgICAgc2VfcmF0aW5nID0gc2RfcmF0aW5nL3NxcnQobikpIC0+IGRlc2NyaXB0aXZlX3N1bW1hcnlfbXQNCg0KIyBTYXZlIHRoaXMgc3VtbWFyeSBmb3IgdXNlIGluIGV4dGVybmFsIHNjcmlwdHMNCiMgc2F2ZVJEUyhkZXNjcmlwdGl2ZV9zdW1tYXJ5X210LCBmaWxlPSJleHB0M19kZXNjcmlwdGl2ZV9zdW1tYXJ5LnJkcyIpDQpwcmludChkZXNjcmlwdGl2ZV9zdW1tYXJ5X210KQ0KYGBgDQoNClRoZSBmb2xsb3dpbmcgdGFibGUgdmlzdWFsaXplcyB0aGUgcmF0aW5ncyBkYXRhLiBFcnJvciBiYXJzIHJlcHJlc2VudCBzdGFuZGFyZCBlcnJvcnMuDQoNCmBgYHtyIGRlc2NyaXB0aXZlX3Bsb3R9DQpkZXNjcmlwdGl2ZV9zdW1tYXJ5X210ICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBkZXBfbGVuZ3RoLA0KICAgICAgICAgICAgIHkgPSBtZWFuX3JhdGluZywNCiAgICAgICAgICAgICB5bWluID0gMSwNCiAgICAgICAgICAgICB5bWF4ID0gNiwNCiAgICAgICAgICAgICBjb2xvdXIgPSBlY190eXBlLA0KICAgICAgICAgICAgIGdyb3VwID0gZWNfdHlwZSkpIC0+IGRlc2NyaXB0aXZlX3Bsb3RfbXQNCg0KZGVzY3JpcHRpdmVfcGxvdF9tdCArIGZhY2V0X2dyaWQoLn5jb250ZXh0KSArDQogIGxhYnModGl0bGUgPSAiUmF0aW5ncyBieSBjb250ZXh0IChNVHVyaykiLA0KICAgICAgIHggPSAiRGVwZW5kZW5jeSBsZW5ndGgiLA0KICAgICAgIHkgPSAiTWVhbiByYXRpbmciLA0KICAgICAgIGNvbG91ciA9ICJEZXBlbmRlbmN5IGxlbmd0aCIpICsNCiAgc2NhbGVfY29sb3JfZGlzY3JldGUoIkVtYmVkZGVkIGNsYXVzZSB0eXBlIiwgbGFiZWxzID0gYygiaXNsYW5kIiwgIm5vbi1pc2xhbmQiKSkgKw0KICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbl9yYXRpbmcgLSBzZV9yYXRpbmcsDQogICAgICAgICAgICAgICAgICAgIHltYXggPSBtZWFuX3JhdGluZyArIHNlX3JhdGluZyksDQogICAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4xNSkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2wgPSBlY190eXBlKSwNCiAgICAgICAgICAgICBzaXplID0gMikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDE6NikpICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSkgLT4gZGVzY3JpcHRpdmVfcGxvdF9tdA0KcHJpbnQoZGVzY3JpcHRpdmVfcGxvdF9tdCkNCmBgYA0KDQojIyBDYWxjdWxhdGluZyB0aGUgREQgc2NvcmVzIChpc2xhbmQgc3RyZW5ndGgpDQoNClRoZSBmb2xsb3dpbmcgY29kZSB6LXNjb3JlcyB0aGUgcmF0aW5ncyBzbyB0aGF0IHRoZXkgYXJlIGNvbXBhcmFibGUgYWNyb3NzIGV4cGVyaW1lbnRzLiBUbyBkbyB0aGlzLCB3ZSBzdGFydCB3aXRoIGJvdGggZXhwZXJpbWVudGFsIGFuZCBmaWxsZXIgZGF0YSwgYW5kIGdyb3VwIGJ5IHN1YmplY3QuIEVhY2ggc3ViamVjdCdzIHJhdGluZyBpcyB0aGVuIHotc2NvcmVkLCBhbmQgdGhlIHotc2NvcmVzIGZvciBlYWNoIGNvbmRpdGlvbiBhcmUgYXZlcmFnZWQgYWZ0ZXIgdW5ncm91cGluZyBieSBzdWJqZWN0Lg0KDQpgYGB7ciB6c2NvcmVzX2Zvcl9kZHN9DQojIENvcHkgdGhlIGRhdGEgdG8gYSBuZXcgZGF0YSBmcmFtZSBmb3Igc2FmZS1rZWVwaW5nIG9mIHRoZSBvcmlnaW5hbA0KcmF3X3Jlc3VsdHNfbXRfY2xuIC0+IHJhd19yZXN1bHRzX210X2Nsbl9zaHJ0DQojIFBhc3RlIHRoZSBlY190eXBlIGFuZCBkZXBfbGVuZ3RoIGNvbHVtbnMgdG9nZXRoZXIgc28gdGhhdCBjb25kaXRpb25zIChpZ25vcmluZyBjb250ZXh0KSBhcmUgcmVwcmVzZW50ZWQgYnkgYSBzaW5nbGUgY2VsbCBpbiB0aGUgZGF0YSBmcmFtZQ0KcmF3X3Jlc3VsdHNfbXRfY2xuX3NocnQkZWNfdHlwZVhkZXBfbGVuZ3RoIDwtIHBhc3RlKHJhd19yZXN1bHRzX210X2Nsbl9zaHJ0JGVjX3R5cGUsICJ4IiwgcmF3X3Jlc3VsdHNfbXRfY2xuX3NocnQkZGVwX2xlbmd0aCkNCg0KIyBHZXQgei1zY29yZXMNCnJhd19yZXN1bHRzX210X2Nsbl9zaHJ0ICU+JQ0KICBncm91cF9ieShzdWJqZWN0KSAlPiUgIyBHcm91cCByYXcgcmVzdWx0cyBieSBzdWJqZWN0DQogIG11dGF0ZSh6X3JhdGluZyA9IHNjYWxlKHJhdGluZykpICU+JSAjIEdldCB6LXNjb3JlcyBmb3IgZWFjaCBzdWJqZWN0J3MgcmF0aW5ncw0KICB1bmdyb3VwICU+JSAjIEJyaW5nIHN1YmplY3RzIGJhY2sgdG9nZXRoZXINCiAgc3Vic2V0KGl0ZW1fdHlwZSA9PSAiZXhwZXJpbWVudGFsIikgJT4lIGRyb3BsZXZlbHMgJT4lICMgUmVtb3ZlIGZpbGxlcnMNCiAgZ3JvdXBfYnkoY29udGV4dCwgZWNfdHlwZVhkZXBfbGVuZ3RoLCBpdGVtX3NldCkgJT4lICMgR3JvdXAgYnkgY29uZGl0aW9uIGFuZCBpdGVtIHNldA0KICBzdW1tYXJpemUobWVhbl96X3JhdGluZyA9IG1lYW4oel9yYXRpbmcpKSAlPiUgIyBHZXQgdGhlIG1lYW4gei1zY29yZSBmb3IgZWFjaCBjb25kaXRpb24gcGVyIGl0ZW0gc2V0DQogIGdyb3VwX2J5KGNvbnRleHQsIGVjX3R5cGVYZGVwX2xlbmd0aCkgJT4lICMgR3JvdXAgdGhpcyBzdW1tYXJ5IGJ5IGNvbmRpdGlvbg0KICBzdW1tYXJpemUobWVhbl96X3JhdGluZ3MgPSBtZWFuKG1lYW5fel9yYXRpbmcpKSAtPiBzdW1tYXJ5X3pzY29yZXMgIyBHZXQgdGhlIG1lYW4gb2YgdGhlIG1lYW4gei1zY29yZXMNCnByaW50KHN1bW1hcnlfenNjb3JlcykNCmBgYA0KDQpOb3csIHdlJ2xsIGNhbGN1bGF0ZSB0aGUgRERzIHVzaW5nIHRoZSBzdW1tYXJ5IHRhYmxlIGZyb20gYWJvdmUuIFN1YnRyYWN0aW5nIHRoZSBpc2xhbmR8bG9uZyBhdmVyYWdlIGZyb20gdGhlIG5vbi1pc2xhbmR8bG9uZyBhdmVyYWdlIHlpZWxkcyB0aGUgY29tYmluZWQgY29zdCBvZiBjb21wbGV4aXR5IGFuZCBleHRyYWN0aW5nIG91dCBvZiBhbiBpc2xhbmQuIFRoaXMgZGlmZmVyZW5jZSBpcyBjYWxsZWQgRDEuIFN1YnRyYWN0aW5nIHRoZSBpc2xhbmR8c2hvcnQgYXZlcmFnZSBmcm9tIHRoZSBub24taXNsYW5kfHNob3J0IGF2ZXJhZ2UgeWllbGRzIEQyLCB3aGljaCByZXByZXNlbnRzIHRoZSBpc29sYXRlZCBjb3N0IG9mIGNvbXBsZXhpdHkuIEQxLUQyIHRoZW4geWllbGRzIHRoZSBpc29sYXRlZCBjb3N0IG9mIGV4dHJhY3Rpbmcgb3V0IG9mIHRoZSBpc2xhbmQuIEVhY2ggZGlmZmVyZW5jZSBpcyBnaXZlbiBmb3IgZWFjaCBlbnZpcm9ubWVudCBjb25zaWRlcmVkIGluIHRoaXMgZXhwZXJpbWVudC4NCg0KYGBge3IgRERzfQ0KIyBNYWtlIHRhYmxlIGZvciBERHMgYnkgbWFraW5nIHRoZSBjb25kaXRpb25zIGludG8gY29sdW1ucyAmIGZpbGxpbmcgaW4gdGhlIGNlbGxzIHdpdGggdGhlIGF2ZydkIHotc2NvcmVzDQp6X0REcyA8LSBzdW1tYXJ5X3pzY29yZXMgJT4lIHNwcmVhZChlY190eXBlWGRlcF9sZW5ndGgsIG1lYW5fel9yYXRpbmdzKQ0KDQojIENhbGN1bGF0ZSBkaWZmZXJlbmNlcw0Kel9ERHMkRDEgPC0gel9ERHMkYG5vbi1pc2xhbmQgeCBsb25nYCAtIHpfRERzJGBpc2xhbmQgeCBsb25nYA0Kel9ERHMkRDIgPC0gel9ERHMkYG5vbi1pc2xhbmQgeCBzaG9ydGAgLSB6X0REcyRgaXNsYW5kIHggc2hvcnRgDQp6X0REcyRERCA8LSB6X0REcyREMSAtIHpfRERzJEQyDQoNCiMgTWFrZSB0aGUgY29sdW1uIG5hbWVzIHNob3J0ZXIgc28gdGhleSdsbCBhbGwgZml0IGluIHRoZSBzYW1lIHRhYmxlDQpjb2xuYW1lcyh6X0REcylbY29sbmFtZXMoel9ERHMpID09ICJpc2xhbmQgeCBsb25nIl0gPC0gImlzbCB4IGxvbmciDQpjb2xuYW1lcyh6X0REcylbY29sbmFtZXMoel9ERHMpID09ICJpc2xhbmQgeCBzaG9ydCJdIDwtICJpc2wgeCBzaHJ0Ig0KY29sbmFtZXMoel9ERHMpW2NvbG5hbWVzKHpfRERzKSA9PSAibm9uLWlzbGFuZCB4IGxvbmciXSA8LSAibm9uaXNsIHggbG9uZyINCmNvbG5hbWVzKHpfRERzKVtjb2xuYW1lcyh6X0REcykgPT0gIm5vbi1pc2xhbmQgeCBzaG9ydCJdIDwtICJub25pc2wgeCBzaHJ0Ig0KDQpvcHRpb25zKGRpZ2l0cyA9IDMpDQpwcmludCh6X0REcykNCmBgYA0KDQojIyBPcmRpbmFsIHJlZ3Jlc3Npb24gYW5hbHlzaXMNCg0KIyMjIFByZWRpY3Rpb25zDQoNCiAgLSBHZW5lcmFsIGlzbGFuZCBlZmZlY3QgKHdvdWxkIHNob3cgdXAgYXMgYW4gaW50ZXJhY3Rpb24gYmV0d2VlbiBlY190eXBlIGFuZCBkZXBfbGVuZ3RoKQ0KICAtIEVmZmVjdCBvZiBjb250cmFzdCBvbiB0cmFuc3BhcmVuY3kNCiAgICAgIC0gV291bGQgc2hvdyB1cCBhcyBhIHRocmVlLXdheSBpbnRlcmFjdGlvbiBiZXR3ZWVuIGVjX3R5cGUsIGRlcF9sZW5ndGgsIGFuZCBkaWZmZXJlbnQgY29udGV4dCBmYWN0b3JzDQoNCiMjIyBDb250cmFzdHMNCg0KU2V0IHRoZSBjb250cmFzdHMgYXBwcm9wcmlhdGVseSBmb3IgZWFjaCBmYWN0b3INCg0KYGBge3IgY29udHJhc3RzX2NvbnRleHR9DQojIEhlbG1lcnQgY29udHJhc3QgZm9yIHRocmVlLWxldmVsIGZhY3Rvcg0KY29udHJhc3RzKGV4cGVyaW1lbnRfZGF0YV9tdF9jbG4kY29udGV4dCkgPC0gImNvbnRyLmhlbG1lcnQiDQojIEFzc2lnbmluZyBjb250cmFzdHMgaW4gYWJvdmUgd2F5IGRvZXNuJ3QgZ3JvdXAgdGhlIGZhY3RvcnMgYXBwcm9wcmlhdGVseSAoaXQgd291bGQgYmUgbW9yZSBhcHByb3ByaWF0ZSB0byBncm91cCBleGlzdGVudGlhbCBhbmQgcHJlZGljYXRlIGZhY3RvcnMgdG9nZXRoZXIsIGFuZCB0byBjb21wYXJlIHRoZSB0d28gb2YgdGhlc2UgdG8gdGhlIG9iamVjdCBmYWN0b3IpDQojIEFzc2lnbiBjb250cmFzdHMgbWFudWFsbHkgKHRoZSBmaXJzdCByb3cgaXMgZmluZTsgSSB3YW50IHRvIHN3aXRjaCB0aGUgc2Vjb25kIGFuZCB0aGlyZCByb3dzJyB2YWx1ZXMpDQpjb250cmFzdHMoZXhwZXJpbWVudF9kYXRhX210X2NsbiRjb250ZXh0KVsxLF0gPC0gYygwLCAyKQ0KY29udHJhc3RzKGV4cGVyaW1lbnRfZGF0YV9tdF9jbG4kY29udGV4dClbMixdIDwtIGMoMSwgLTEpDQpjb250cmFzdHMoZXhwZXJpbWVudF9kYXRhX210X2NsbiRjb250ZXh0KVszLF0gPC0gYygtMSwgLTEpDQoNCiMgUmVsYWJlbCBjb250cmFzdCBjb2x1bW4gbmFtZXMgZm9yIGNvbnRleHQgZmFjdG9yDQpkaW1uYW1lcyhjb250cmFzdHMoZXhwZXJpbWVudF9kYXRhX210X2NsbiRjb250ZXh0KSlbWzJdXSA8LSBjKCJCRSIsICJUUkFOU0lUSVZJVFkiKQ0KDQojIENoZWNrIGFnYWluDQpjb250cmFzdHMoZXhwZXJpbWVudF9kYXRhX210X2NsbiRjb250ZXh0KQ0KYGBgDQoNCmBgYHtyIGNvbnRyYXN0c19kZXBfbGVuZ3RofQ0KIyBGaXggY29udHJhc3RzIGZvciBkZXBfbGVuZ3RoIGZhY3Rvcg0KY29udHJhc3RzKGV4cGVyaW1lbnRfZGF0YV9tdF9jbG4kZGVwX2xlbmd0aCkgPC0gYygtMC41LCAwLjUpDQojIENoZWNrDQpjb250cmFzdHMoZXhwZXJpbWVudF9kYXRhX210X2NsbiRkZXBfbGVuZ3RoKQ0KYGBgDQoNCmBgYHtyIGNvbnRyYXN0c19lY190eXBlfQ0KIyBGaXggY29udHJhc3RzIGZvciBlY190eXBlIGZhY3Rvcg0KY29udHJhc3RzKGV4cGVyaW1lbnRfZGF0YV9tdF9jbG4kZWNfdHlwZSkgPC0gYygtMC41LCAwLjUpDQojIENoZWNrDQpjb250cmFzdHMoZXhwZXJpbWVudF9kYXRhX210X2NsbiRlY190eXBlKQ0KYGBgDQoNCiMjIyBTaW1wbGUgZWZmZWN0cyBhbmFseXNpcw0KYGBge3IgYW5hbHlzaXN9DQojIE1ha2UgcmF0aW5ncyBhIGZhY3Rvcg0KZXhwZXJpbWVudF9kYXRhX210X2NsbiRyYXRpbmcgJTw+JSBhcy5mYWN0b3INCmV4cGVyaW1lbnRfZGF0YV9tdF9jbG4kc3ViamVjdCAlPD4lIGFzLmZhY3Rvcg0KDQojIFNhdmUgZGF0YSBmb3IgdXNlIGVsc2V3aGVyZQ0Kc2F2ZVJEUyhleHBlcmltZW50X2RhdGFfbXRfY2xuLCAiZXhwdDNfZGF0YV9jbG4ucmRzIikNCg0KIyBTaW1wbGUgZWZmZWN0cyBhbmFseXNpcw0KdGltZWluaXQgPC0gU3lzLnRpbWUoKQ0KY2xtKHJhdGluZyB+IGNvbnRleHQgKiBkZXBfbGVuZ3RoICogZWNfdHlwZSwgZGF0YSA9IGV4cGVyaW1lbnRfZGF0YV9tdF9jbG4pIC0+IGNsbV9hbmFseXNpc19leHB0M19tdA0KdGltZWVuZCA8LSBTeXMudGltZSgpDQp0aW1lZW5kIC0gdGltZWluaXQNCnN1bW1hcnkoY2xtX2FuYWx5c2lzX2V4cHQzX210KQ0KYGBgDQoNCiMjIyBTb21lIG5vdGVzDQoNCiAgLSBjb250ZXh0MSBpcyB0aGUgZXhpc3QtcHJlZGljYXRlIGNvbXBhcmlzb24NCiAgLSBjb250ZXh0MiBpcyB0aGUgb2JqZWN0LVtleGlzdC1wcmVkaWNhdGVdIGNvbXBhcmlzb24NCg0KIyMjIE9ic2VydmF0aW9ucy9pbnRlcnByZXRhdGlvbnMNCg0KICAtIE1haW4gZWZmZWN0cw0KICAgICAgLSBjb250ZXh0MSAoZXhpc3Qtb2JqZWN0IGNvbXBhcmlzb24pDQogICAgICAtIGNvbnRleHQyIChbZXhpc3Qtb2JqZWN0XS1wcmVkaWNhdGUgY29tcGFyaXNvbikNCiAgICAgIC0gZGVwZW5kZW5jeSBsZW5ndGggKGRlcF9sZW5ndGgpDQogICAgICAtIGVtYmVkZGVkIGNsYXVzZSB0eXBlIChlY190eXBlKQ0KICAtIFR3by13YXkgaW50ZXJhY3Rpb25zDQogICAgICAtIFNpZ25pZmljYW50IGludGVyYWN0aW9uIChwID0gNS44KjEwXi02XikgYmV0d2VlbiBkZXBfbGVuZ3RoIGFuZCBlY190eXBlICgqKmlzbGFuZCBlZmZlY3QqKikNCiAgICAgIC0gU2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gKHAgPSAwLjAwNSkgYmV0d2VlbiBjb250ZXh0MSAoZXhpc3QtcHJlZGljYXRlKSBhbmQgZGVwX2xlbmd0aCAocmVnYXJkbGVzcyBvZiBlY190eXBlKQ0KICAgICAgICAgIC0gKFN1Z2dlc3RzIHRoYXQgZWl0aGVyIHRoZSBleGlzdGVudGlhbCBvciB0aGUgcHJlZGljYXRlIGNvbnRleHQgaW5jcmVhc2VzIHRyYW5zcGFyZW5jeSB3aGV0aGVyIHRoZSBlbWJlZGRlZCBjbGF1c2UgaXMgYW4gaXNsYW5kIG9yIG5vdCg/KSkNCiAgICAgIC0gTm8gc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gYmV0d2VlbiBjb250ZXh0MiAoW2V4aXN0LXByZWRpY2F0ZV0tb2JqZWN0KSBhbmQgZGVwX2xlbmd0aA0KICAgICAgLSBTaWduaWZpY2FudCBpbnRlcmFjdGlvbiAocCA9IDAuMDI2KSBiZXR3ZWVuIGNvbnRleHQxIChleGlzdC1wcmVkaWNhdGUpIGFuZCBlY190eXBlDQogICAgICAgICAgLSBTdWdnZXN0cyB0aGF0IGVpdGhlciB0aGUgZXhpc3RlbnRpYWwgb3IgdGhlIHByZWRpY2F0ZSBjb250ZXh0IGFmZmVjdHMgdGhlIGltcGFjdCBvZiBlY190eXBlLCByZWdhcmRsZXNzIG9mIGRlcF9sZW5ndGgNCiAgLSBUaHJlZS13YXkgaW50ZXJhY3Rpb25zDQogICAgICAtIFNpZ25pZmljYW50IGludGVyYWN0aW9uIChwID0gMC4wMzgpIGJldHdlZW4gY29udGV4dDIgKFtleGlzdC1wcmVkaWNhdGVdLW9iamVjdCksIGRlcF9sZW5ndGgsIGFuZCBlY190eXBlDQogICAgICAgICAgLSBTdWdnZXN0cyB0aGF0IGV4aXN0ZW50aWFsIGFuZCBwcmVkaWNhdGUgY29udGV4dHMgYXJlIG1vcmUgdHJhbnNwYXJlbnQgdG8gZXh0cmFjdGlvbiB0aGFuIHRoZSBvYmplY3QgY29udGV4dCAoY29lZmZpY2llbnQgaXMgbmVnYXRpdmUpDQogICAgICAtIE5vIGludGVyYWN0aW9uIChwID0gMC45MjEpIGJldHdlZW4gY29udGV4dDEgKGV4aXN0LXByZWRpY2F0ZSksIGRlcF9sZW5ndGgsIGFuZCBlY190eXBlDQogICAgICAgICAgLSBTdWdnZXN0cyB0aGF0IGV4aXN0ZW50aWFsIGFuZCBwcmVkaWNhdGUgY29udGV4dHMgZG8gbm90IGRpZmZlciBpbiB0cmFuc3BhcmVuY3kgdG8gZXh0cmFjdGlvbiAoY29tcGFyZWQgdG8gZWFjaCBvdGhlcikNCiAgICAgICAgICANCiMjIyBNaXhlZCBlZmZlY3RzIGFuYWx5c2lzDQoNClRoZSBmb2xsb3dpbmcgY29kZSBjaHVuayB3YXMgcnVuIG9uIHRoZSBbVUNTQyBodW1taW5nYmlyZCBjbHVzdGVyXShodHRwczovL3d3dy5oYi51Y3NjLmVkdSkgdXNpbmcgdGhlIGRhdGEgc2F2ZWQgYWJvdmUuDQoNCmBgYHtyIG1peGVkX2VmZmVjdHNfbWF4aW1hbCwgZXZhbD1GQUxTRX0NCiMgUmVhZCBpbiB0aGUgZGF0YSBzYXZlZCBmcm9tIHBlcnNvbmFsIGNvbXB1dGVyDQpyZWFkUkRTKCJleHB0M19kYXRhX2Nsbi5yZHMiKSAtPiBleHB0M19kYXRhX2Nsbg0KIyBQZXJmb3JtIGEgbWl4ZWQgZWZmZWN0cyBhbmFseXNpcyBieSBzdWJqZWN0cyBhbmQgYnkgaXRlbXMNCmNsbW0oZGF0YSA9IGV4cHQzX2RhdGFfY2xuLA0KICAgICBmb3JtdWxhID0gcmF0aW5nIH4gY29udGV4dCAqIGVjX3R5cGUgKiBkZXBfbGVuZ3RoICsNCiAgICAgICAoMSArIGNvbnRleHQgKiBlY190eXBlICogZGVwX2xlbmd0aCB8IHN1YmplY3QpICsNCiAgICAgICAoMSArIGNvbnRleHQgKiBlY190eXBlICogZGVwX2xlbmd0aCB8IGl0ZW1fc2V0KQ0KICAgICApIC0+IGV4cHQzX2NsbW1fZnVsbA0KIyBTYXZlIGNsbW0gYW5hbHlzaXMNCnNhdmVSRFMob2JqZWN0ID0gZXhwdDNfY2xtbV9mdWxsLCBmaWxlID0gImV4cHQzX2NsbW1fZnVsbC5yZHMiKQ0KYGBgDQoNClRoZSBmb2xsb3dpbmcgY29kZSBjaHVuayBzdW1tYXJpemVzIHRoZSByZXN1bHRzIG9mIHRoZSBjbG1tIGFuYWx5c2lzIHJ1biBvbiB0aGUgY2x1c3Rlci4NCg0KYGBge3IgY2xtbV9hbmFseXNpc30NCiMgUHVsbCBpbiBmdWxsIGNsbW0gdGhhdCB3YXMgcnVuIG9uIHRoZSBodW1taW5nYmlyZCBjbHVzdGVyDQpyZWFkUkRTKCJleHB0M19jbG1tX2Z1bGwucmRzIikgLT4gY2xtbV8zX2FuYWx5c2lzX2V4cHQzDQpzdW1tYXJ5KGNsbW1fM19hbmFseXNpc19leHB0MykNCmBgYA0KDQojIFNpbXVsYXRpb24NCg0KIyMgQWN0dWFsIHJlc3BvbnNlIGRpc3RyaWJ1dGlvbnMNCg0KYGBge3IgcmVzcF9kaXN0fQ0KIyBTdWJzZXQgdGhlIGlzbGFuZCBleHRyYWN0aW9uIGNhc2VzIGZyb20gdGhlIGRhdGENCmV4cGVyaW1lbnRfZGF0YV9tdF9jbG4gJT4lDQogIHN1YnNldChkZXBfbGVuZ3RoID09ICJsb25nIiAmIGVjX3R5cGUgPT0gImlzbGFuZCIpICU+JQ0KICBkcm9wbGV2ZWxzICU+JQ0KICBnZ3Bsb3QoYWVzKHJhdGluZykpICsNCiAgZ2VvbV9oaXN0b2dyYW0oc3RhdCA9ICJjb3VudCIpICsgDQogIGZhY2V0X2dyaWQoLn5jb250ZXh0KSAtPiByZXNwX2Rpc3RfaGlzdA0KDQpwcmludChyZXNwX2Rpc3RfaGlzdCkNCmBgYA0KDQpgYGB7ciBzaW1fc2V0dXB9DQppZigncGFja2FnZTpkcGx5cicgJWluJSBzZWFyY2goKSkgew0KICBkZXRhY2gocGFja2FnZTpkcGx5ciwgdW5sb2FkID0gVFJVRSkNCiAgfSBlbHNlIHt9DQpsaWJyYXJ5KHBseXIpDQpsaWJyYXJ5KG1peHRvb2xzKQ0KbGlicmFyeShncmlkRXh0cmEpDQoNCmZpbGxlcl9kYXRhX210X2NsbiRyYXRpbmcgJTw+JSBhcy5udW1lcmljDQoNCmZpbGxlcl9kYXRhX3VuZ3JhbW0gPC0gc3Vic2V0KGZpbGxlcl9kYXRhX210X2NsbiwgZXhwZWN0ZWRfZ3JhbW0gPT0gInVuZ3JhbW0iKSRyYXRpbmcNCmZpbGxlcl9kYXRhX2dyYW1tIDwtIHN1YnNldChmaWxsZXJfZGF0YV9tdF9jbG4sIGV4cGVjdGVkX2dyYW1tID09ICJncmFtbSIpJHJhdGluZw0KDQpleHBlcmltZW50X2RhdGFfbXRfY2xuJHJhdGluZyAlPD4lIGFzLm51bWVyaWMNCg0KZGF0YV9vYmplY3QgPC0gc3Vic2V0KGV4cGVyaW1lbnRfZGF0YV9tdF9jbG4sIGNvbnRleHQgPT0gIm9iamVjdCIgJiBkZXBfbGVuZ3RoID09ICJsb25nIiAmIGVjX3R5cGUgPT0gImlzbGFuZCIpJHJhdGluZw0KZGF0YV9wcmVkaWNhdGUgPC0gc3Vic2V0KGV4cGVyaW1lbnRfZGF0YV9tdF9jbG4sIGNvbnRleHQgPT0gInByZWRpY2F0ZSIgJiBkZXBfbGVuZ3RoID09ICJsb25nIiAmIGVjX3R5cGUgPT0gImlzbGFuZCIpJHJhdGluZw0KZGF0YV9leGlzdGVudGlhbCA8LSBzdWJzZXQoZXhwZXJpbWVudF9kYXRhX210X2NsbiwgY29udGV4dCA9PSAiZXhpc3QiICYgZGVwX2xlbmd0aCA9PSAibG9uZyIgJiBlY190eXBlID09ICJpc2xhbmQiKSRyYXRpbmcNCmBgYA0KDQpgYGB7ciBkZWZpbmVfbXVsdGlub21pYWxfZnVuY3Rpb25zfQ0KIyMgVGhlc2UgZnVuY3Rpb25zIGFuZCB0aG9zZSBkZWZpbmVkIGluIGZvbGxvd2luZyBjaHVua3MgYXJlIGR1ZSB0byBCcmlhbiBEaWxsb24sIHZpYSBKZWQgUGl6YXJyby1HdWV2YXJhLiAjIw0KDQojIERlZmluZSBmdW5jdGlvbnMgdG8gY3JlYXRlIGRpc2NyZXRlIGFuZCBncmFkaWVudCBtb2RlbHMuDQoNCiMgY3JlYXRlLmRpc2NyZXRlL2dyYWRpZW50IHJldHVybnMgdGhlIHBhcmFtZXRlcnMgb2YgYSBtdWx0aW5vbWlhbCBkaXN0cmlidXRpb24gb3ZlciByZXNwb25zZXMuDQojIEl0IHRha2VzIGdyYW1tYXRpY2FsIGFuZCB1bmdyYW1tYXRpY2FsIHJlZmVyZW5jZSBzZXRzIChhY3R1YWwgZGF0YSksIHBpIChyZWxhdGl2ZSB3ZWlnaHQgb2YgdW5ncmFtbWF0aWNhbCBkaXN0cmlidXRpb24pLCBhbmQgTiAobnVtYmVyIG9mIGRhdGEgcG9pbnRzIHRvIGJlIHNhbXBsZWQgaW4gZXN0aW1hdGluZyB0aGUgZGlzdHJpYnV0aW9uKQ0KIyBUaGVzZSBmdW5jdGlvbnMgaGF2ZSBiZWVuIG1vZGlmaWVkIHRvIHdvcmsgZm9yIGRhdGEgb24gYSA2LXBvaW50IExpa2VydCBzY2FsZSwgaW5zdGVhZCBvZiA3LXBvaW50Lg0KDQpjcmVhdGUuZGlzY3JldGUgPSBmdW5jdGlvbihncmFtLnJlZiwgdW5ncmFtLnJlZiwgcGksIG51bSA9IGxlbmd0aChncmFtLnJlZiksIHNtb290aCA9IFQpIHsNCiAgDQoJCXNhbXBsZXMuZGlzY3JldGUgPSBjKA0KCQkJc2FtcGxlKGdyYW0ucmVmLCByb3VuZCgoMS1waSkqbnVtKSwgcmVwbGFjZSA9IFQpLCANCgkJCXNhbXBsZSh1bmdyYW0ucmVmLCByb3VuZChwaSpudW0pLCByZXBsYWNlID0gVCkNCgkJKQ0KCQlpZiAoc21vb3RoKSB7DQoJCQlwcm9iLmRpc2NyZXRlID0gKHRhYnVsYXRlKHNhbXBsZXMuZGlzY3JldGUsIG5iaW5zID0gNikrMSkvKGxlbmd0aChzYW1wbGVzLmRpc2NyZXRlKSs2KQ0KCQl9IGVsc2Ugew0KCQkJcHJvYi5kaXNjcmV0ZSA9ICh0YWJ1bGF0ZShzYW1wbGVzLmRpc2NyZXRlLCBuYmlucyA9IDYpKS8obGVuZ3RoKHNhbXBsZXMuZGlzY3JldGUpKQkNCgkJfQ0KCQlyZXR1cm4ocHJvYi5kaXNjcmV0ZSkNCn0NCg0KY3JlYXRlLmdyYWRpZW50ID0gZnVuY3Rpb24oZ3JhbS5yZWYsIHVuZ3JhbS5yZWYsIHBpLCBudW0gPSBsZW5ndGgoZ3JhbS5yZWYpLCBzbW9vdGggPSBUKSB7DQogIA0KCQlzYW1wbGVzLmdyYWRpZW50ID0gcm91bmQoDQoJCQkoMS1waSkqc2FtcGxlKGdyYW0ucmVmLCBudW0sIHJlcGxhY2UgPSBUKStwaSpzYW1wbGUodW5ncmFtLnJlZiwgbnVtLCByZXBsYWNlID0gVCkNCgkJKQ0KCQlpZiAoc21vb3RoKSB7DQoJCQlwcm9iLmdyYWRpZW50ID0gKHRhYnVsYXRlKHNhbXBsZXMuZ3JhZGllbnQsIG5iaW5zID0gNikrMSkvKGxlbmd0aChzYW1wbGVzLmdyYWRpZW50KSs2KQ0KCQl9IGVsc2UgewkNCgkJCXByb2IuZ3JhZGllbnQgPSAodGFidWxhdGUoc2FtcGxlcy5ncmFkaWVudCwgbmJpbnMgPSA2KSkvKGxlbmd0aChzYW1wbGVzLmdyYWRpZW50KSkJDQoJCX0NCgkJcmV0dXJuKHByb2IuZ3JhZGllbnQpDQp9DQpgYGANCg0KYGBge3IgZGVmaW5lX2ZpdF9waV9mdW5jdGlvbnN9DQojIERlZmluZSBmdW5jdGlvbnMgdG8gZGV0ZXJtaW5lIHRoZSBmaXQgb2YgYSBnaXZlbiB2YWx1ZSBvZiBwaSBmb3IgdGhlIGRhdGFzZXQNCg0KIyBmaXQuZ3JhZGllbnQvZGlzY3JldGUucGkgaXMgYSBmdW5jdGlvbiB1c2VkIHRvIG1heGltaXplIHBpIHBhcmFtZXRlciBnaXZlbiBhIGRhdGFzZXQuIEl0IHRha2VzIHRoZSBzYW1lIHBhcmFtZXRlcnMgYXMgdGhlIG1peHR1cmUgY3JlYXRpbmcgZnVuY3Rpb25zLCBwbHVzIGEgdGVzdCBwYXJhbWV0ZXIuIFRlc3QgaXMgdGhlIHRlc3QgZGlzdHJpYnV0aW9uIHRvIGJlIG1vZGVsZWQuDQojIGZpdC5ncmFkaWVudC9kaXNjcmV0ZS5waSByZXR1cm5zIHRoZSBSTVNEIChyb290LW1lYW4tc3F1YXJlIGRldmlhdGlvbikgYmV0d2VlbiB0aGUgbWVhbiBvZiB0aGUgbWl4dHVyZSBhbmQgYWRtaXh0dXJlIG1vZGVsIGFuZCB0aGUgZW1waXJpY2FsIG1lYW4gb2YgdGhlIHRlc3QgZGlzdHJpYnV0aW9uLg0KDQpmaXQuZ3JhZGllbnQucGkgPSBmdW5jdGlvbihwaSwgZ3JhbS5yZWYsIHVuZ3JhbS5yZWYsIHRlc3QpIHsNCgkJZ3JhZGllbnQubW9kZWwgPSBjcmVhdGUuZ3JhZGllbnQoZ3JhbS5yZWYsIHVuZ3JhbS5yZWYsIHBpLCBzbW9vdGggPSBGKQ0KCQlncmFkaWVudC5tZWFuID0gc3VtKGdyYWRpZW50Lm1vZGVsKmMoMTo2KSkNCgkJdGVzdC5tZWFuID0gbWVhbih0ZXN0KQ0KCQlybXNkID0gKGdyYWRpZW50Lm1lYW4tdGVzdC5tZWFuKV4yDQoJCXJldHVybihybXNkKQ0KfQ0KDQpmaXQuZGlzY3JldGUucGkgPSBmdW5jdGlvbihwaSwgZ3JhbS5yZWYsIHVuZ3JhbS5yZWYsIHRlc3QpIHsNCgkJZGlzY3JldGUubW9kZWwgPSBjcmVhdGUuZGlzY3JldGUoZ3JhbS5yZWYsIHVuZ3JhbS5yZWYsIHBpKQ0KCQlkaXNjcmV0ZS5tZWFuID0gc3VtKGRpc2NyZXRlLm1vZGVsKmMoMTo2KSkNCgkJdGVzdC5tZWFuID0gbWVhbih0ZXN0KQ0KCQlybXNkID0gKGRpc2NyZXRlLm1lYW4tdGVzdC5tZWFuKV4yDQoJCXJldHVybihybXNkKQ0KfQ0KYGBgDQoNCmBgYHtyIGRlZmluZV9zaW11bGF0aW9uX2Z1bmN0aW9ufQ0KIyBEZWZpbmUgdGhlIG1haW4gc2ltdWxhdGlvbiBmdW5jdGlvbg0KDQpjb21wYXJlLm1vZGVscyA9IGZ1bmN0aW9uKGdyYW0uZGlzdCwgdW5ncmFtLmRpc3QsIHRlc3QuZGlzdCwgY2hpc3F1YXJlID0gVCkgew0KICANCiAgb3B0aW0uZGlzY3JldGUucGkgPSBvcHRpbWl6ZShmaXQuZGlzY3JldGUucGksIGludGVydmFsID0gYygwLCAxKSwgZ3JhbS5yZWYgPSBncmFtLmRpc3QsIHVuZ3JhbS5yZWYgPSB1bmdyYW0uZGlzdCwgdGVzdCA9IHRlc3QuZGlzdCkNCgkJZm9yIChpIGluIGMoMTo1KSkgew0KCQkJY3VyLmRpc2NyZXRlLnBpID0gb3B0aW1pemUoZml0LmRpc2NyZXRlLnBpLCBpbnRlcnZhbCA9IGMoMCwgMSksIGdyYW0ucmVmID0gZ3JhbS5kaXN0LCB1bmdyYW0ucmVmID0gdW5ncmFtLmRpc3QsIHRlc3QgPSB0ZXN0LmRpc3QpDQoJCQlpZiAoY3VyLmRpc2NyZXRlLnBpJG9iamVjdGl2ZSA8IG9wdGltLmRpc2NyZXRlLnBpJG9iamVjdGl2ZSkgew0KCQkJCW9wdGltLmRpc2NyZXRlLnBpID0gY3VyLmRpc2NyZXRlLnBpDQoJCQl9DQoJCX0NCgkJZGlzY3JldGUucGkgPSBvcHRpbS5kaXNjcmV0ZS5waSRtaW5pbXVtDQoNCgkJb3B0aW0uZ3JhZGllbnQucGkgPSBvcHRpbWl6ZShmaXQuZ3JhZGllbnQucGksIGludGVydmFsID0gYygwLCAxKSwgZ3JhbS5yZWYgPSBncmFtLmRpc3QsIHVuZ3JhbS5yZWYgPSB1bmdyYW0uZGlzdCwgdGVzdCA9IHRlc3QuZGlzdCkNCgkJZm9yIChpIGluIGMoMTo1KSkgew0KCQkJY3VyLmdyYWRpZW50LnBpID0gb3B0aW1pemUoZml0LmdyYWRpZW50LnBpLCBpbnRlcnZhbCA9IGMoMCwgMSksIGdyYW0ucmVmID0gZ3JhbS5kaXN0LCB1bmdyYW0ucmVmID0gdW5ncmFtLmRpc3QsIHRlc3QgPSB0ZXN0LmRpc3QpDQoJCQlpZiAoY3VyLmdyYWRpZW50LnBpJG9iamVjdGl2ZSA8IG9wdGltLmdyYWRpZW50LnBpJG9iamVjdGl2ZSkgew0KCQkJCW9wdGltLmdyYWRpZW50LnBpID0gY3VyLmdyYWRpZW50LnBpDQoJCQl9DQoJCX0NCgkJZ3JhZGllbnQucGkgPSBvcHRpbS5ncmFkaWVudC5waSRtaW5pbXVtDQoJCWRpc2NyZXRlLm1vZGVsID0gY3JlYXRlLmRpc2NyZXRlKGdyYW0uZGlzdCwgdW5ncmFtLmRpc3QsIGRpc2NyZXRlLnBpKQ0KCQlncmFkaWVudC5tb2RlbCA9IGNyZWF0ZS5ncmFkaWVudChncmFtLmRpc3QsIHVuZ3JhbS5kaXN0LCBncmFkaWVudC5waSkNCgkJZGlzY3JldGUubWVhbiA9IHN1bShkaXNjcmV0ZS5tb2RlbCpjKDE6NikpDQoJICBncmFkaWVudC5tZWFuID0gc3VtKGdyYWRpZW50Lm1vZGVsKmMoMTo2KSkNCgkgIA0KCSAgIyBOZXh0IHN0ZXAsIGNhbGN1bGF0ZSBCSUMgb2YgdGVzdCBkYXRhIHVuZGVyIGVhY2ggbW9kZWwuDQoNCiAgICBLID0gbGVuZ3RoKGRpc2NyZXRlLm1vZGVsKS0xCSMjIyAjIG9mIGZyZWUgcGFyYW1zIGluIG11bHRpbm9taWFsIG1vZGVsLi4uIGRvZXNuJ3QgcmVhbGx5IG1hdHRlciBmb3IgQklDIGRpZmZlcmVuY2Ugc2NvcmUsIGlzIGNvbnN0YW50IGFjcm9zcyBtb2RlbHMuDQogICAgDQogICAgZGlzY3JldGUuYmljID0gLTIqc3VtKGRtdWx0aW5vbSh0YWJ1bGF0ZSh0ZXN0LmRpc3QsIG5iaW5zID0gNiksIHByb2IgPSBkaXNjcmV0ZS5tb2RlbCwgbG9nID0gVCkpK0sqbG9nKGxlbmd0aCh0ZXN0LmRpc3QpKQ0KICAgIGdyYWRpZW50LmJpYyA9IC0yKnN1bShkbXVsdGlub20odGFidWxhdGUodGVzdC5kaXN0LCBuYmlucyA9IDYpLCBwcm9iID0gZ3JhZGllbnQubW9kZWwsIGxvZyA9IFQpKStLKmxvZyhsZW5ndGgodGVzdC5kaXN0KSkNCiAgICANCiAgICAjIE5leHQgc3RlcCwgY29udmVydCBCSUMgdG8gQkYNCg0KICAJYmYgPSBleHAoLS41KihkaXNjcmV0ZS5iaWMtZ3JhZGllbnQuYmljKSkNCiAgCQ0KICAJIyBXcmFwIGl0IHVwDQogIAkNCiAgCW15LmZpdCA9IHt9DQogIAlteS5maXRbWyJEaXNjcmV0ZSJdXSA9IGRpc2NyZXRlLm1vZGVsDQogIAlteS5maXRbWyJHcmFkaWVudCJdXSA9IGdyYWRpZW50Lm1vZGVsDQogIAlteS5maXRbWyJUZXN0Il1dID0gKHRhYnVsYXRlKHRlc3QuZGlzdCwgbmJpbnMgPSA2KSkvKGxlbmd0aCh0ZXN0LmRpc3QpKQkNCiAgCW15LmZpdFtbIkRhdGEgbWVhbiJdXSA9IG1lYW4odGVzdC5kaXN0KQ0KICAJbXkuZml0W1siRGlzY3JldGUgcHJlZGljdGVkIG1lYW4iXV0gPSBkaXNjcmV0ZS5tZWFuDQogIAlteS5maXRbWyJHcmFkaWVudCBwcmVkaWN0ZWQgbWVhbiJdXSA9IGdyYWRpZW50Lm1lYW4NCiAgCW15LmZpdFtbIkRpc2NyZXRlIEJJQyJdXSA9IGRpc2NyZXRlLmJpYw0KICAJbXkuZml0W1siR3JhZGllbnQgQklDIl1dID0gZ3JhZGllbnQuYmljDQogIAlteS5maXRbWyJCRiJdXSA9IGJmDQogIAlteS5maXRbWyJTdGF0cyJdXSA9IGMoZGlzY3JldGUubWVhbiwgZ3JhZGllbnQubWVhbiwgZGlzY3JldGUucGksIGdyYWRpZW50LnBpLCBkaXNjcmV0ZS5iaWMtZ3JhZGllbnQuYmljLCBiZiwgZGlzY3JldGUubWVhbiwgZ3JhZGllbnQubWVhbikNCiAgCQ0KICAJaWYgKGNoaXNxdWFyZSkgew0KICAJCSMgQ2FsY3VsYXRlIFgyIHZhbHVlcyB1bmRlciB0d28gbW9kZWxzDQogIAkJIyBzaW11bGF0ZS5wLnZhbHVlIHNldCB0byBUIGJlY2F1c2Ugb2YgdmVyeSBsb3cgZXhwZWN0ZWQgY291bnRzIG9uIHNvbWUgbW9kZWxzDQogIAkJY2hpc3EuZGlzY3JldGUgPSBjaGlzcS50ZXN0KHRhYnVsYXRlKHRlc3QuZGlzdCwgbmJpbnMgPSA2KSwgcCA9IGRpc2NyZXRlLm1vZGVsLCBzaW11bGF0ZS5wLnZhbHVlID0gVCkNCiAgCQljaGlzcS5ncmFkaWVudCA9IGNoaXNxLnRlc3QodGFidWxhdGUodGVzdC5kaXN0LCBuYmlucyA9IDYpLCBwID0gZ3JhZGllbnQubW9kZWwsIHNpbXVsYXRlLnAudmFsdWUgPSBUKQ0KICAJCW15LmZpdFtbIkRpc2NyZXRlIENoaXNxIl1dID0gY2hpc3EuZGlzY3JldGUNCiAgCQlteS5maXRbWyJHcmFkaWVudCBDaGlzcSJdXSA9IGNoaXNxLmdyYWRpZW50DQogIAl9DQogIAkNCiAgCW15LmZpdFtbInBpIl1dID0gYyhkaXNjcmV0ZS5waSwgZ3JhZGllbnQucGkpDQogIAkNCiAgCXJldHVybihteS5maXQpDQoJDQp9DQoNCnN1bW1hcnkuZmlndXJlID0gZnVuY3Rpb24obXkuZml0KSB7DQoJcGFyKG1mcm93ID0gYygzLCAxKSkNCgltYXggPSBtYXgoYyhteS5maXQkVGVzdCwgbXkuZml0JERpc2NyZXRlLCBteS5maXQkRGlzY3JldGUpKQ0KCW1heCA9IGNlaWxpbmcobWF4KjEwKS8xMA0KCWJhcnBsb3QobXkuZml0JFRlc3QsIG1haW4gPSAiVGVzdCBEaXN0cmlidXRpb24iLCB5bGltID0gYygwLCBtYXgpKQ0KCWJhcnBsb3QobXkuZml0JERpc2NyZXRlLCBtYWluID0gIkRpc2NyZXRlIERpc3RyaWJ1dGlvbiIsIHlsaW0gPSBjKDAsIG1heCkpDQoJYmFycGxvdChteS5maXQkR3JhZGllbnQsIG1haW4gPSAiR3JhZGllbnQgRGlzdHJpYnV0aW9uIiwgeWxpbSA9IGMoMCwgbWF4KSkNCn0NCmBgYA0KDQpgYGB7ciBydW5fc2ltdWxhdGlvbl9vYmplY3R9DQojIFJ1biB0aGUgc2ltdWxhdGlvbiBvbiB0aGUgdHJhbnNpdGl2ZSBvYmplY3QgY2FzZXMNCiMgVXNlIHVuZ3JhbW1hdGljYWwgZmlsbGVycyBhcyB1bmdyYW0ucmVmLCBhbmQgZ3JhbW1hdGljYWwgZmlsbGVycyBhcyBncmFtLnJlZg0KIyBVc2UgdHJhbnNpdGl2ZSBvYmplY3QgY29uZGl0aW9uIGFzIHRlc3QNCg0KIyBncmFtLnJlZiwgdW5ncmFtLnJlZiwgdGVzdA0KI3NpbV9vYmplY3QgPC0gY29tcGFyZS5tb2RlbHMoZmlsbGVyX2RhdGFfZ3JhbW0sIGZpbGxlcl9kYXRhX3VuZ3JhbW0sIGRhdGFfb2JqZWN0KQ0KI3NpbV9vYmplY3QNCiNzdW1tYXJ5LmZpZ3VyZShzaW1fb2JqZWN0KQ0KDQpvdXRjb21lc19vYmplY3QgPC0ge30NCnNpbV9vYmplY3QuZGlzY3JldGUgPC0ge30NCnNpbV9vYmplY3QuZ3JhZGllbnQgPC0ge30NCg0KZm9yIChpIGluIGMoMTo1MDApKSB7DQoJc2ltX29iamVjdCA9IGNvbXBhcmUubW9kZWxzKGZpbGxlcl9kYXRhX2dyYW1tLCBmaWxsZXJfZGF0YV91bmdyYW1tLCBkYXRhX29iamVjdCkNCglvdXRjb21lc19vYmplY3QgPC0gY2JpbmQob3V0Y29tZXNfb2JqZWN0LCBzaW1fb2JqZWN0JFN0YXRzKQ0KCXNpbV9vYmplY3QuZGlzY3JldGUgPC0gY2JpbmQoc2ltX29iamVjdC5kaXNjcmV0ZSwgc2ltX29iamVjdCREaXNjcmV0ZSkNCglzaW1fb2JqZWN0LmdyYWRpZW50IDwtIGNiaW5kKHNpbV9vYmplY3QuZ3JhZGllbnQsIHNpbV9vYmplY3QkR3JhZGllbnQpDQp9DQoNCnBhc3RlKHJvdW5kKGMobWVhbihvdXRjb21lc19vYmplY3RbMixdKSwgIyBtZWFuIHByZWRpY3RlZCBtZWFucyB1bmRlciBncmFkaWVudA0KICAgICAgICAgICAgICBtZWFuKG91dGNvbWVzX29iamVjdFs0LF0pLCAjIG1lYW4gZ3JhZGllbnQgcGkNCiAgICAgICAgICAgICAgbWVhbihvdXRjb21lc19vYmplY3RbMSxdKSwgIyBtZWFuIHByZWRpY3RlZCBtZWFucyB1bmRlciBkaXNjcmV0ZQ0KICAgICAgICAgICAgICBtZWFuKG91dGNvbWVzX29iamVjdFszLF0pLCAjIG1lYW4gZGlzY3JldGUgcGkNCiAgICAgICAgICAgICAgbWVhbihvdXRjb21lc19vYmplY3RbNSxdKSwgIyBtZWFuIEJJQyBkaWZmZXJlbmNlDQogICAgICAgICAgICAgIHJhbmdlKG91dGNvbWVzX29iamVjdFs1LF0pLCAjIHJhbmdlIG9mIEJJQyBkaWZmZXJlbmNlDQogICAgICAgICAgICAgIG1lYW4ob3V0Y29tZXNfb2JqZWN0WzYsXSkpLCAjIG1lYW4gQmF5ZXMgZmFjdG9yDQogICAgICAgICAgICBkaWdpdHM9MikpIC0+IHJlc3VsdHMuc2ltX29iamVjdA0KDQpyZXN1bHRzLnNpbV9vYmplY3QgJT4lIHQgJT4lIGRhdGEuZnJhbWUgLT4gcmVzdWx0cy5zaW1fb2JqZWN0DQpjb2xuYW1lcyhyZXN1bHRzLnNpbV9vYmplY3QpIDwtIGMoIkdyYWRpZW50X21lYW4iLCAiR3JhZGllbnRfcGkiLCAiRGlzY3JldGVfbWVhbiIsICJEaXNjcmV0ZV9waSIsICJCSUNfbWVhbiIsICJCSUNfbWluIiAsIkJJQ19tYXgiLCAiQkYiKQ0KDQpwcmludChyZXN1bHRzLnNpbV9vYmplY3QpDQoNCiMjIyBTZWUgaG93IG1hbnkgaGF2ZSBCSUMgPiAwICMjIw0Kb3V0Y29tZXNfb2JqZWN0WzUsXSAlPiUgZGF0YS5mcmFtZSAtPiBvdXRjb21lcy5zaW1fb2JqZWN0DQpvdXRjb21lcy5zaW1fb2JqZWN0ICU+JSBzdWJzZXQoLiA+IDApICU+JSBucm93DQoNCmBgYA0KDQpgYGB7ciBydW5fc2ltdWxhdGlvbl9wcmVkaWNhdGV9DQojIFJ1biB0aGUgc2ltdWxhdGlvbiBvbiB0aGUgcHJlZGljYXRlIGNhc2VzDQojIFVzZSB1bmdyYW1tYXRpY2FsIGZpbGxlcnMgYXMgdW5ncmFtLnJlZiwgYW5kIGdyYW1tYXRpY2FsIGZpbGxlcnMgYXMgZ3JhbS5yZWYNCiMgVXNlIHByZWRpY2F0ZSBjb25kaXRpb24gYXMgdGVzdA0KDQojIGdyYW0ucmVmLCB1bmdyYW0ucmVmLCB0ZXN0DQojc2ltX3ByZWRpY2F0ZSA8LSBjb21wYXJlLm1vZGVscyhmaWxsZXJfZGF0YV9ncmFtbSwgZmlsbGVyX2RhdGFfdW5ncmFtbSwgZGF0YV9vYmplY3QpDQojc2ltX3ByZWRpY2F0ZQ0KI3N1bW1hcnkuZmlndXJlKHNpbV9wcmVkaWNhdGUpDQoNCm91dGNvbWVzX3ByZWRpY2F0ZSA8LSB7fQ0Kc2ltX3ByZWRpY2F0ZS5kaXNjcmV0ZSA8LSB7fQ0Kc2ltX3ByZWRpY2F0ZS5ncmFkaWVudCA8LSB7fQ0KDQpmb3IgKGkgaW4gYygxOjUwMCkpIHsNCglzaW1fcHJlZGljYXRlID0gY29tcGFyZS5tb2RlbHMoZmlsbGVyX2RhdGFfZ3JhbW0sIGZpbGxlcl9kYXRhX3VuZ3JhbW0sIGRhdGFfcHJlZGljYXRlKQ0KCW91dGNvbWVzX3ByZWRpY2F0ZSA8LSBjYmluZChvdXRjb21lc19wcmVkaWNhdGUsIHNpbV9wcmVkaWNhdGUkU3RhdHMpDQoJc2ltX3ByZWRpY2F0ZS5kaXNjcmV0ZSA8LSBjYmluZChzaW1fcHJlZGljYXRlLmRpc2NyZXRlLCBzaW1fcHJlZGljYXRlJERpc2NyZXRlKQ0KCXNpbV9wcmVkaWNhdGUuZ3JhZGllbnQgPC0gY2JpbmQoc2ltX3ByZWRpY2F0ZS5ncmFkaWVudCwgc2ltX3ByZWRpY2F0ZSRHcmFkaWVudCkNCn0NCg0KcGFzdGUocm91bmQoYyhtZWFuKG91dGNvbWVzX3ByZWRpY2F0ZVsyLF0pLCAjIG1lYW4gcHJlZGljdGVkIG1lYW5zIHVuZGVyIGdyYWRpZW50DQogICAgICAgICAgICAgIG1lYW4ob3V0Y29tZXNfcHJlZGljYXRlWzQsXSksICMgbWVhbiBncmFkaWVudCBwaQ0KICAgICAgICAgICAgICBtZWFuKG91dGNvbWVzX3ByZWRpY2F0ZVsxLF0pLCAjIG1lYW4gcHJlZGljdGVkIG1lYW5zIHVuZGVyIGRpc2NyZXRlDQogICAgICAgICAgICAgIG1lYW4ob3V0Y29tZXNfcHJlZGljYXRlWzMsXSksICMgbWVhbiBkaXNjcmV0ZSBwaQ0KICAgICAgICAgICAgICBtZWFuKG91dGNvbWVzX3ByZWRpY2F0ZVs1LF0pLCAjIG1lYW4gQklDIGRpZmZlcmVuY2UNCiAgICAgICAgICAgICAgcmFuZ2Uob3V0Y29tZXNfcHJlZGljYXRlWzUsXSksICMgcmFuZ2Ugb2YgQklDIGRpZmZlcmVuY2UNCiAgICAgICAgICAgICAgbWVhbihvdXRjb21lc19wcmVkaWNhdGVbNixdKSksICMgbWVhbiBCYXllcyBmYWN0b3INCiAgICAgICAgICAgIGRpZ2l0cz0yKSkgLT4gcmVzdWx0cy5zaW1fcHJlZGljYXRlDQoNCnJlc3VsdHMuc2ltX3ByZWRpY2F0ZSAlPiUgdCAlPiUgZGF0YS5mcmFtZSAtPiByZXN1bHRzLnNpbV9wcmVkaWNhdGUNCmNvbG5hbWVzKHJlc3VsdHMuc2ltX3ByZWRpY2F0ZSkgPC0gYygiR3JhZGllbnRfbWVhbiIsICJHcmFkaWVudF9waSIsICJEaXNjcmV0ZV9tZWFuIiwgIkRpc2NyZXRlX3BpIiwgIkJJQ19tZWFuIiwgIkJJQ19taW4iICwiQklDX21heCIsICJCRiIpDQoNCnByaW50KHJlc3VsdHMuc2ltX3ByZWRpY2F0ZSkNCg0KIyMjIFNlZSBob3cgbWFueSBoYXZlIEJJQyA+IDAgIyMjDQpvdXRjb21lc19wcmVkaWNhdGVbNSxdICU+JSBkYXRhLmZyYW1lIC0+IG91dGNvbWVzLnNpbV9wcmVkaWNhdGUNCm91dGNvbWVzLnNpbV9wcmVkaWNhdGUgJT4lIHN1YnNldCguID4gMCkgJT4lIG5yb3cNCmBgYA0KDQpgYGB7ciBydW5fc2ltdWxhdGlvbl9leGlzdGVudGlhbH0NCiMgUnVuIHRoZSBzaW11bGF0aW9uIG9uIHRoZSBleGlzdGVudGlhbCBjYXNlcw0KIyBVc2UgdW5ncmFtbWF0aWNhbCBmaWxsZXJzIGFzIHVuZ3JhbS5yZWYsIGFuZCBncmFtbWF0aWNhbCBmaWxsZXJzIGFzIGdyYW0ucmVmDQojIFVzZSBleGlzdGVudGlhbCBjb25kaXRpb24gYXMgdGVzdA0KDQojIGdyYW0ucmVmLCB1bmdyYW0ucmVmLCB0ZXN0DQojc2ltX2V4aXN0ZW50aWFsIDwtIGNvbXBhcmUubW9kZWxzKGZpbGxlcl9kYXRhX2dyYW1tLCBmaWxsZXJfZGF0YV91bmdyYW1tLCBkYXRhX29iamVjdCkNCiNzaW1fZXhpc3RlbnRpYWwNCiNzdW1tYXJ5LmZpZ3VyZShzaW1fZXhpc3RlbnRpYWwpDQoNCm91dGNvbWVzX2V4aXN0ZW50aWFsIDwtIHt9DQpzaW1fZXhpc3RlbnRpYWwuZGlzY3JldGUgPC0ge30NCnNpbV9leGlzdGVudGlhbC5ncmFkaWVudCA8LSB7fQ0KDQpmb3IgKGkgaW4gYygxOjUwMCkpIHsNCglzaW1fZXhpc3RlbnRpYWwgPSBjb21wYXJlLm1vZGVscyhmaWxsZXJfZGF0YV9ncmFtbSwgZmlsbGVyX2RhdGFfdW5ncmFtbSwgZGF0YV9leGlzdGVudGlhbCkNCglvdXRjb21lc19leGlzdGVudGlhbCA8LSBjYmluZChvdXRjb21lc19leGlzdGVudGlhbCwgc2ltX2V4aXN0ZW50aWFsJFN0YXRzKQ0KCXNpbV9leGlzdGVudGlhbC5kaXNjcmV0ZSA8LSBjYmluZChzaW1fZXhpc3RlbnRpYWwuZGlzY3JldGUsIHNpbV9leGlzdGVudGlhbCREaXNjcmV0ZSkNCglzaW1fZXhpc3RlbnRpYWwuZ3JhZGllbnQgPC0gY2JpbmQoc2ltX2V4aXN0ZW50aWFsLmdyYWRpZW50LCBzaW1fZXhpc3RlbnRpYWwkR3JhZGllbnQpDQp9DQoNCnBhc3RlKHJvdW5kKGMobWVhbihvdXRjb21lc19leGlzdGVudGlhbFsyLF0pLCAjIG1lYW4gcHJlZGljdGVkIG1lYW5zIHVuZGVyIGdyYWRpZW50DQogICAgICAgICAgICAgIG1lYW4ob3V0Y29tZXNfZXhpc3RlbnRpYWxbNCxdKSwgIyBtZWFuIGdyYWRpZW50IHBpDQogICAgICAgICAgICAgIG1lYW4ob3V0Y29tZXNfZXhpc3RlbnRpYWxbMSxdKSwgIyBtZWFuIHByZWRpY3RlZCBtZWFucyB1bmRlciBkaXNjcmV0ZQ0KICAgICAgICAgICAgICBtZWFuKG91dGNvbWVzX2V4aXN0ZW50aWFsWzMsXSksICMgbWVhbiBkaXNjcmV0ZSBwaQ0KICAgICAgICAgICAgICBtZWFuKG91dGNvbWVzX2V4aXN0ZW50aWFsWzUsXSksICMgbWVhbiBCSUMgZGlmZmVyZW5jZQ0KICAgICAgICAgICAgICByYW5nZShvdXRjb21lc19leGlzdGVudGlhbFs1LF0pLCAjIHJhbmdlIG9mIEJJQyBkaWZmZXJlbmNlDQogICAgICAgICAgICAgIG1lYW4ob3V0Y29tZXNfZXhpc3RlbnRpYWxbNixdKSksICMgbWVhbiBCYXllcyBmYWN0b3INCiAgICAgICAgICAgIGRpZ2l0cz0yKSkgLT4gcmVzdWx0cy5zaW1fZXhpc3RlbnRpYWwNCg0KcmVzdWx0cy5zaW1fZXhpc3RlbnRpYWwgJT4lIHQgJT4lIGRhdGEuZnJhbWUgLT4gcmVzdWx0cy5zaW1fZXhpc3RlbnRpYWwNCmNvbG5hbWVzKHJlc3VsdHMuc2ltX2V4aXN0ZW50aWFsKSA8LSBjKCJHcmFkaWVudF9tZWFuIiwgIkdyYWRpZW50X3BpIiwgIkRpc2NyZXRlX21lYW4iLCAiRGlzY3JldGVfcGkiLCAiQklDX21lYW4iLCAiQklDX21pbiIgLCJCSUNfbWF4IiwgIkJGIikNCg0KcHJpbnQocmVzdWx0cy5zaW1fZXhpc3RlbnRpYWwpDQoNCiMjIyBTZWUgaG93IG1hbnkgaGF2ZSBCSUMgPiAwICMjIw0Kb3V0Y29tZXNfZXhpc3RlbnRpYWxbNSxdICU+JSBkYXRhLmZyYW1lIC0+IG91dGNvbWVzLnNpbV9leGlzdGVudGlhbA0Kb3V0Y29tZXMuc2ltX2V4aXN0ZW50aWFsICU+JSBzdWJzZXQoLiA+IDApICU+JSBucm93DQpgYGA=