Outline


    01. Multiple linear regression

    02. Mediation

    03. Moderation


    Data and packages

    Hate Crimes




    • Packages:
    ipak <- function(pkg){
      new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
      if (length(new.pkg)) 
        install.packages(new.pkg, dependencies = TRUE)
      sapply(pkg, require, character.only = TRUE)
    }
    
    packages <- c("ggplot2", "dplyr")
    ipak(packages)
    • Create a dataset and its subset:
    Hate_Crimes <- read.csv("hate_crimes.csv")
    
    Hate_Crimes_selected <- read.csv("hate_crimes.csv") %>% 
      select(c(share_voters_voted_trump, share_white_poverty, share_non_citizen))


    Multiple Linear Regression

    Linear Regression


    • Lineární regrese
      • Nakolik lze z IQ skóru usuzovat o výkonu v matematice?
        • Predikce


    • Vícenásobná lineární regrese
      • Přispívá k výši platu kromě úrovně vzdělání také pohlaví?
        • Predikce
        • Inkrementální validita
        • Statistická kontrola


    Notace
    \(Y = Y' + e\)


    • Lineární regrese:

    \(Y' = a + bX\)

    \(Y' = b_{0} + b_{1}X_{1}\)


    • Vícenásobná lineární regrese:

    \(Y' = b_{0} + b_{n}X_{n}\)

    \(Y' = b_{0} + b_{1}X_{1} + b_{2}X_{2} + ... + b_{n}X_{n}+ e\)


    • \(Y\) = Outcome (= dependent) variable
    • \(Y'\) = Our model
    • \(e\) = Error
    • \(a\) or \(b_{0}\) = Intercept
    • \(b\) or \(b_{1...n}\) = Slope
    • \(X_{1...n}\) = Predictor (= independent variable)



    Přímka (model) je proložena daty tak, aby jim co nejlépe odpovídala.

    • Metoda odhadu nejmenších čtverců (Least Squares Estimation)
      • Suma (druhých mocnin) vzdáleností modelu od dat je nejmenší možná



    \(S_{T}\)\(^{2}\) = \(S_{M}\)\(^{2}\) + \(S_{R}\)\(^{2}\)

    • Neboli \(SS_{T} = SS_{res} + SS_{reg}\)


    \(R^{2}\) = \(SS_{M}\)\(^{2}\) + \(SS_{T}\)\(^{2}\)


    \(SS_{M}\)

    • Rozdíl mezi nulovým modelem (průměr \(Y\)) a námi stanoveným modeleme (přímkou).

    \(SS_{R}\)

    • Rozdíl mezi daty a námi stanoveným modelem (přímkou).

    \(SS_{T}\)

    • Rozdíl mezi daty a nulovým modelem (průměr \(Y\)).

    \(R^{2}\)

    • Podíl rozptylu závislé (outcome) proměnné vysvětlené modelem (= koeficient determinance).


    Metoda nejmenších čtverců graficky



    Model

    ModelHateCrime <- lm(formula = share_voters_voted_trump ~ share_white_poverty +
     share_non_citizen, data = Hate_Crimes_selected)


    • Compute the summary statistics for model:
    # Generic functions (summary) change their behaviour based on an object's class.
    
    summary(ModelHateCrime)
    
    Call:
    lm(formula = share_voters_voted_trump ~ share_white_poverty + 
        share_non_citizen, data = Hate_Crimes_selected)
    
    Residuals:
         Min       1Q   Median       3Q      Max 
    -0.25728 -0.03434 -0.00480  0.03619  0.16636 
    
    Coefficients:
                        Estimate Std. Error t value Pr(>|t|)    
    (Intercept)          0.40711    0.06397   6.364 8.99e-08 ***
    share_white_poverty  1.98561    0.55229   3.595 0.000801 ***
    share_non_citizen   -1.83930    0.42746  -4.303 8.98e-05 ***
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
    
    Residual standard error: 0.08387 on 45 degrees of freedom
      (3 observations deleted due to missingness)
    Multiple R-squared:  0.5326,    Adjusted R-squared:  0.5119 
    F-statistic: 25.64 on 2 and 45 DF,  p-value: 3.69e-08


    • Perform an analysis of variance on model:
    anova(ModelHateCrime)
    Analysis of Variance Table
    
    Response: share_voters_voted_trump
                        Df  Sum Sq  Mean Sq F value    Pr(>F)    
    share_white_poverty  1 0.23054 0.230537  32.773 7.987e-07 ***
    share_non_citizen    1 0.13024 0.130238  18.514 8.976e-05 ***
    Residuals           45 0.31655 0.007034                      
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1


    • Predict based on the fitted function:
    predict(ModelHateCrime)
            1         2         3         4         5         6         7         8         9        10 
    0.6085999 0.4526775 0.4018880 0.5718139 0.3467091 0.4357477 0.4158916 0.4739967 0.2842146 0.4599931 
           11        12        13        14        15        16        17        18        19        21 
    0.4386739 0.3989617 0.5519579 0.4173547 0.5902069 0.5306387 0.5519579 0.6894873 0.6085999 0.3791057 
           22        23        24        26        27        28        29        30        31        32 
    0.4004248 0.5122457 0.4144285 0.5093195 0.5872807 0.4541406 0.3820319 0.4710705 0.3437828 0.4953159 
           33        34        35        36        37        38        39        40        41        43 
    0.4217440 0.5137088 0.5306387 0.5504948 0.5321018 0.4769229 0.5306387 0.4188178 0.5306387 0.5916700 
           44        45        46        47        48        49        50        51 
    0.3636389 0.4923897 0.5872807 0.4357477 0.4386739 0.6667050 0.5306387 0.5490317 


    Coefficients


    \(b_{i}\)

    • Vyjadřuje nárůst \(Y’\) při nárůstu \(X_{i}\) o jednu jednotku v jednotkách Y, při kontrole všech ostatních prediktorů (tj. semiparciální korelace); jedinečný přínos
      • K porovnání síly prediktoru v různých skupinách, modelech, vzorcích

    \(β_{i}\)

    • Beta vyjadřuje nárůst \(Y’\) při nárůstu \(X_{i}\) o 1; pokud jsou \(X_{i}\) a \(Y\) standardizovány, při kontrole všech ostatních prediktorů (tj. semiparciální korelace), jedinečný přínos
      • K porovnání prediktorů mezi sebou v rámci jednoho modelu
      • K porovnání různě operacionalizovaného prediktoru v různých modelech
      • Ukazatel velikosti účinku

    \(b_{0}\)

    • Po vycentrování (odečtení průměru od všech hodnot \(X_{i}\)) odpovídá průměru \(Y\).
    QuantPsyc::lm.beta(ModelHateCrime)
    share_white_poverty   share_non_citizen 
              0.3978439          -0.4761472 

    Assumptions

    “To draw conclusions about a population based on a regression analysis done on a sample, several assumptions must be true.” (Field, 2009 , s. 220)

    Variables

    1. Povaha proměnných - spojité, kvantitativní a kardinální nebo dummy (jen v případě prediktorů).

    2. Nenulová variabilita prediktorů (tj. nejde o konstantu).

    Predictors

    1. Absence (dokonalé) multikolinearity - prediktory by spolu neměly vysoce korelovat.

    2. Prediktory nekorelují s vnějšími proměnnými - absence třetí (intervenující, vnější) proměnné.


    • Povaha proměnných a nenulová variabilita:
    Hate_Crimes_Select <- Hate_Crimes%>%
     select(c("share_voters_voted_trump", "share_white_poverty", "share_non_citizen"))
     
    lapply(Hate_Crimes_Select, class)
    $share_voters_voted_trump
    [1] "numeric"
    
    $share_white_poverty
    [1] "numeric"
    
    $share_non_citizen
    [1] "numeric"
    summary(Hate_Crimes_Select)
     share_voters_voted_trump share_white_poverty share_non_citizen
     Min.   :0.040            Min.   :0.04000     Min.   :0.01000  
     1st Qu.:0.415            1st Qu.:0.07500     1st Qu.:0.03000  
     Median :0.490            Median :0.09000     Median :0.04500  
     Mean   :0.490            Mean   :0.09176     Mean   :0.05458  
     3rd Qu.:0.575            3rd Qu.:0.10000     3rd Qu.:0.08000  
     Max.   :0.700            Max.   :0.17000     Max.   :0.13000  
                                                  NA's   :3        
    psych::describe(Hate_Crimes_Select) # install.packages("psych")


    • Multikolinearita:
    car::vif(ModelHateCrime) # variance inflation factors, install.packages("car")
    share_white_poverty   share_non_citizen 
               1.179078            1.179078 
    sqrt(car::vif(ModelHateCrime)) > 2 # problem?
    share_white_poverty   share_non_citizen 
                  FALSE               FALSE 
    Rcmdr::rcorr.adjust(Hate_Crimes_Select) # install.packages("Rcmdr"), library(Rcmdr)
    Error: 'rcorr.adjust' is not an exported object from 'namespace:Rcmdr'


    Rezidua

    1. Homoskedascita - rozptyl reziduí by měl být konstantní napříč různými úrovněmi prediktoru.

    2. Nezávislost reziduí - Reziduální hodnoty kterýchkoliv dvou případů by spolu neměly souviset.

    3. Normálně rozložená rezidua - jejich rozložení by mělo být náhodné.


    Outcome

    1. Nezávislost kterýchkoliv dvou hodnot závislé proměnné (každá hodnota v rámci ní pochází z unikátního zdroje).

    2. Linearita - přímka jako vhodný model popisu dat.


    • Homoskedascita a linearita (dle Field, 2009, s. 248)


    • Evaluate homoscedasticity:
    # non-constant error variance test
    car::ncvTest(ModelHateCrime)
    Non-constant Variance Score Test 
    Variance formula: ~ fitted.values 
    Chisquare = 3.022336, Df = 1, p = 0.082125
    # plot studentized residuals vs. fitted values
    car::spreadLevelPlot(ModelHateCrime)
    
    Suggested power transformation:  2.358004 


    • Nezávislost reziduí:
    # Test for Autocorrelated Errors
    car::durbinWatsonTest(ModelHateCrime)
     lag Autocorrelation D-W Statistic p-value
       1    -0.003840009      1.934234   0.786
     Alternative hypothesis: rho != 0


    • Normálně rozložená rezidua:
    # distribution of studentized residuals
    # library(MASS)
    sresid <- MASS::studres(ModelHateCrime)
    
    hist(sresid, freq=FALSE, main="Distribution of Studentized Residuals")


    • Linearita:
    # component + residual plot
    car::crPlots(ModelHateCrime)

    Model Diagnostics


    Outliers and Influential cases

    Nemají některé případy příliš velký vliv na výsledky regrese?

    • Outliers – mohou zvyšovat i snižovat b
      • Rezidua – případy s vysokými rezidui regrese predikuje nejhůř, standardizovaná, ± 3
      • Vlivné případy – případy, které nejvíc ovlivňují parametry modelu
        • Co se stane s parametry regrese, když případ odstraníme?
        • DFBeta – rozdíl mezi parametrem s a bez, standardizované > 1
        • DFFit – rozdíl mezi predikovanou hodnotou a predikovanou hodnotou bez případu (adjustovanou)
        • Cookova vzdálenost > 1
        • Leverage > 2( k+1)/ n , kde k = počet prediktorů, n = velikost výběrového souboru Případy s vysokými rezidui či vlivné případy NEODSTRAŇUJEME …leda by šlo o zjevnou chybu v datech či vzorku …leda by nám šlo výhradně o zpřesnění predikce (nikoli o testy hypotéz)


    • Outliers:
    # Bonferonni p-value for most extreme observations
    car::outlierTest(ModelHateCrime)
    
    #qq plot for studentized resid
    car::qqPlot(ModelHateCrime, main="QQ Plot")
    [1]  9 46


    • Influentials:
    # Cook's D plot
    # identify D values > 4/(n-k-1)
    cutoff <- 4/((nrow(Hate_Crimes)-length(ModelHateCrime$coefficients)-2))
    plot(ModelHateCrime, which=4, cook.levels=cutoff)

    
    # leverage plots
    car::leveragePlots(ModelHateCrime)


    Collinearity

    • Když dva prediktory vysvětlují tutéž část variability závislé proměnné, jeden z nich je téměř zbytečný
    • Komplikuje porovnávání síly prediktorů
    • Snižuje stabilitu odhadu parametrů
    • V extrému (když lze jeden prediktor přesně vypočítat z ostatních) regresi úplně znemožňuje
    • “Rules of Thumb”
      • Korelace nad 0,9
      • Tolerance (= 1/VIF) cca pod 0,1
      • VIF (= 1/tolerance) cca nad 10


    Dummy coding

    Introduction to dummy coding

    Dummy proměnné - kategorické proměnné upravené tak, aby mohly vstoupit do (vícenásobné) lineární regrese

    • Postup (dle Field, 2009, s. 254):


    Indikátorové kódování (Indicator coding)

    • Referenční kategorie = 0

    Efektové kódování (Effect coding)

    • Referenční kategorie = -1



    Coding

    \(Y = b_{0} + b_{A1}X_{A1} + b_{A2}X_{A2} + ... + b_{m}X_{m}+ e\)

    • Po dosazení do regresní rovnice predikujeme případu průměr jeho skupiny (pokud nejsou žádné další prediktory).

    • Indikátorové kódování
      • \(b_{Ai}\) udává rozdíl průměrných hodnot Y mezi indikovanou skupinou a referenční skupinou; signifikanci b Ai referenční skupinou; signifikance bAi znamená signifikanci rozdílu
      • \(b_{Ai}\) udává o kolik nám členství ve skupině zvyšuje/snižuje predikovanou hodnotu oproti referenční skupině
      • \(b_{0}\) udává (při absenci jiných prediktorů) průměr Y v referenční skupině
    • Efektové kódování
      • \(b_{Ai}\) udává rozdíl průměrných hodnot Y mezi indikovanou skupinou a celkovým průměrem
      • \(b_{0}\) udává (při absenci jiných prediktorů) celkový průměr


    Example

    Hate_Crimes$UrbanRural = cut(Hate_Crimes$share_population_in_metro_areas,
                                 breaks=c(-Inf,0.5, Inf), 
                                 labels=c("Rural","Urban"))
    
    # The factor function
    class(Hate_Crimes$UrbanRural)
    [1] "factor"
    contrasts(Hate_Crimes$UrbanRural)
          Urban
    Rural     0
    Urban     1
      
    summary(lm(share_voters_voted_trump ~ share_white_poverty +
     share_non_citizen + UrbanRural, data = Hate_Crimes))
    
    Call:
    lm(formula = share_voters_voted_trump ~ share_white_poverty + 
        share_non_citizen + UrbanRural, data = Hate_Crimes)
    
    Residuals:
          Min        1Q    Median        3Q       Max 
    -0.253819 -0.035001 -0.005224  0.035566  0.166835 
    
    Coefficients:
                         Estimate Std. Error t value Pr(>|t|)    
    (Intercept)          0.404332   0.071068   5.689 9.64e-07 ***
    share_white_poverty  1.980436   0.561149   3.529 0.000990 ***
    share_non_citizen   -1.855612   0.465441  -3.987 0.000249 ***
    UrbanRuralUrban      0.004516   0.047773   0.095 0.925123    
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
    
    Residual standard error: 0.08481 on 44 degrees of freedom
      (3 observations deleted due to missingness)
    Multiple R-squared:  0.5327,    Adjusted R-squared:  0.5009 
    F-statistic: 16.72 on 3 and 44 DF,  p-value: 2.151e-07


    Mediation

    Introduction

    A mediation analysis is typically conducted to better understand an observed effect of an IV on a DV or a correlation between \(X\) and \(Y\).

    • Why, and how, does \(X\) influence/correlates with \(Y\)?

    If \(X\) and \(Y\) are correlated BECAUSE of the mediator \(M\), then (\(X\) -> \(M\) -> \(Y\))


    \(Y = B_{0} + B_1M + e\)

    &

    \(M = B_0 + B_1X + e\)

    &

    \(Y = B_0 + B_1M + B_2X + e\)


    What will happen to the predictive value of \(X\)?

    • In other words, will \(B_2\) be significant?


    A mediator variable (M) accounts for some or all of the relationship between X and Y:

    • Some: Partial mediation
    • All: Full mediation


    Example

    • Run the three regression models:
    model_yx <- lm(Hate_Crimes$share_voters_voted_trump ~ Hate_Crimes$median_household_income)
    
    model_mx <- lm(Hate_Crimes$share_population_in_metro_areas ~ Hate_Crimes$median_household_income)
    
    model_yxm <- lm(Hate_Crimes$share_voters_voted_trump ~ Hate_Crimes$median_household_income + Hate_Crimes$share_population_in_metro_areas)


    • Make a summary of the three models:
    summary(model_yx)
    
    Call:
    lm(formula = Hate_Crimes$share_voters_voted_trump ~ Hate_Crimes$median_household_income)
    
    Residuals:
         Min       1Q   Median       3Q      Max 
    -0.34945 -0.06275  0.00718  0.04909  0.21359 
    
    Coefficients:
                                          Estimate Std. Error t value Pr(>|t|)    
    (Intercept)                          9.154e-01  8.265e-02  11.075 6.09e-15 ***
    Hate_Crimes$median_household_income -7.703e-06  1.477e-06  -5.216 3.67e-06 ***
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
    
    Residual standard error: 0.09615 on 49 degrees of freedom
    Multiple R-squared:  0.357, Adjusted R-squared:  0.3439 
    F-statistic: 27.21 on 1 and 49 DF,  p-value: 3.669e-06
    summary(model_mx)
    
    Call:
    lm(formula = Hate_Crimes$share_population_in_metro_areas ~ Hate_Crimes$median_household_income)
    
    Residuals:
         Min       1Q   Median       3Q      Max 
    -0.44283 -0.11326  0.03132  0.13582  0.26112 
    
    Coefficients:
                                         Estimate Std. Error t value Pr(>|t|)   
    (Intercept)                         4.382e-01  1.511e-01   2.901  0.00556 **
    Hate_Crimes$median_household_income 5.649e-06  2.699e-06   2.093  0.04154 * 
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
    
    Residual standard error: 0.1757 on 49 degrees of freedom
    Multiple R-squared:  0.08207,   Adjusted R-squared:  0.06334 
    F-statistic: 4.381 on 1 and 49 DF,  p-value: 0.04154
    summary(model_yxm)
    
    Call:
    lm(formula = Hate_Crimes$share_voters_voted_trump ~ Hate_Crimes$median_household_income + 
        Hate_Crimes$share_population_in_metro_areas)
    
    Residuals:
         Min       1Q   Median       3Q      Max 
    -0.29936 -0.02858  0.01007  0.05338  0.11238 
    
    Coefficients:
                                                  Estimate Std. Error t value Pr(>|t|)    
    (Intercept)                                  1.040e+00  7.721e-02  13.470  < 2e-16 ***
    Hate_Crimes$median_household_income         -6.096e-06  1.330e-06  -4.583 3.29e-05 ***
    Hate_Crimes$share_population_in_metro_areas -2.845e-01  6.745e-02  -4.218 0.000109 ***
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
    
    Residual standard error: 0.08298 on 48 degrees of freedom
    Multiple R-squared:  0.5309,    Adjusted R-squared:  0.5114 
    F-statistic: 27.16 on 2 and 48 DF,  p-value: 1.288e-08


    • Sobel test:
    # install.packages("multilevel")
    
    # Compare the previous results to the output of the sobel function
    model_all <- multilevel::sobel(Hate_Crimes$share_population_in_metro_areas,
                       Hate_Crimes$median_household_income,
                       Hate_Crimes$share_voters_voted_trump)
    
    # Print out model_all
    model_all
    $`Mod1: Y~X`
                  Estimate Std. Error   t value     Pr(>|t|)
    (Intercept)  0.7698849 0.05916087 13.013413 1.614296e-17
    pred        -0.3730823 0.07668876 -4.864888 1.227635e-05
    
    $`Mod2: Y~X+M`
                     Estimate   Std. Error   t value     Pr(>|t|)
    (Intercept)  1.040071e+00 7.721107e-02 13.470490 6.321824e-18
    pred        -2.845277e-01 6.745246e-02 -4.218195 1.085169e-04
    med         -6.095571e-06 1.330134e-06 -4.582673 3.285506e-05
    
    $`Mod3: M~X`
                Estimate Std. Error  t value     Pr(>|t|)
    (Intercept) 44324.99   5354.411 8.278219 7.196527e-11
    pred        14527.70   6940.789 2.093090 4.154055e-02
    
    $Indirect.Effect
    [1] -0.08855461
    
    $SE
    [1] 0.04651217
    
    $z.value
    [1] -1.903902
    
    $N
    [1] 51


    Moderation

    Introduction

    • Experimentální design
      • Manipulace s nezávislou proměnnou (\(X\)) vede ke změně v závislé proměnné (\(Y\))
      • Moderátor (\(Z\)) zavádíme z toho kvůli předpokladu, že vliv (účinek) \(X\) na \(Y\) NENÍ konzistentní napříč rozložením (různými úrovněmi) \(Z\)
    • Korelační design
      • Předpokládáme souvislost mezi proměnnými \(X\) a \(Y\)
      • Moderátor \((Z)\) zavádíme kvůli předpokladu, že korelace mezi \(X\) a \(Y\) NENÍ konzistentní napříč rozložením (různými úrovněmi) \(Z\)

    Pokud jsou oboje \(X\) a \(Z\) spojité (resp. intervalové úrovně měření):

    \(Y = B_0 + B_1X + B_2Z + B_3(X\)*\(Z) + e\)

    • Pokud je \(X\) kategorická a \(Z\) spojitá (3 úrovně \(X\)):

    \(Y = B_0 + B_1(X_1) + B_2(X_2) + B_3Z + B_4(X_1\)\(Z) + B_5(X_2\)\(Z) + e\)


    Example

    • Data
    mod <- Hate_Crimes %>%
            select(share_voters_voted_trump, median_household_income, UrbanRural)
    • Summary statistics
    psych::describeBy(mod, mod$UrbanRural)
    
     Descriptive statistics by group 
    group: Rural
    --------------------------------------------------------------------------------- 
    group: Urban
    • Create a boxplot of the data
    boxplot(formula = mod$share_voters_voted_trump ~ mod$UrbanRural, 
              main = "Boxplot", 
              xlab = "Group UrbanRural", 
              ylab = "share_voters_voted_trump")


    • Create subsets of the two groups:
    # Make the subset for the group UrbanRural = "Rural"
    mod_Rural <- subset(mod, mod$UrbanRural == "Rural")
    
    # Make the subset for the group UrbanRural = "Urban"
    mod_Urban <- subset(mod, mod$UrbanRural == "Urban")


    • Calculate the correlations:
    cor(mod_Rural$share_voters_voted_trump, mod_Rural$median_household_income)
    [1] -0.1942672
    cor(mod_Urban$share_voters_voted_trump, mod_Urban$median_household_income)
    [1] -0.6440223


    • Model without moderation (tests for “first-order effects”)
    model_1 <- lm(mod$share_voters_voted_trump ~ mod$median_household_income + mod$UrbanRural)


    • Make a summary of model_1
    summary(model_1)
    
    Call:
    lm(formula = mod$share_voters_voted_trump ~ mod$median_household_income + 
        mod$UrbanRural)
    
    Residuals:
         Min       1Q   Median       3Q      Max 
    -0.34577 -0.05937  0.00564  0.05396  0.15812 
    
    Coefficients:
                                  Estimate Std. Error t value Pr(>|t|)    
    (Intercept)                  9.609e-01  8.848e-02  10.860 1.59e-14 ***
    mod$median_household_income -7.524e-06  1.470e-06  -5.119 5.37e-06 ***
    mod$UrbanRuralUrban         -6.141e-02  4.507e-02  -1.363    0.179    
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
    
    Residual standard error: 0.09532 on 48 degrees of freedom
    Multiple R-squared:  0.381, Adjusted R-squared:  0.3552 
    F-statistic: 14.77 on 2 and 48 DF,  p-value: 1.002e-05


    • Create new predictor variables
    moderator <- mod$median_household_income * as.numeric(mod$UrbanRural)


    • Model with moderation
    model_2 <- lm(mod$share_voters_voted_trump ~ mod$median_household_income + mod$UrbanRural + moderator)


    • Make a summary of model_2
    summary(model_2)
    
    Call:
    lm(formula = mod$share_voters_voted_trump ~ mod$median_household_income + 
        mod$UrbanRural + moderator)
    
    Residuals:
         Min       1Q   Median       3Q      Max 
    -0.33854 -0.05012  0.00546  0.05554  0.14622 
    
    Coefficients:
                                  Estimate Std. Error t value Pr(>|t|)   
    (Intercept)                  7.023e-01  2.440e-01   2.878    0.006 **
    mod$median_household_income  2.844e-06  9.242e-06   0.308    0.760   
    mod$UrbanRuralUrban          2.285e-01  2.591e-01   0.882    0.382   
    moderator                   -5.467e-06  4.811e-06  -1.136    0.262   
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
    
    Residual standard error: 0.09504 on 47 degrees of freedom
    Multiple R-squared:  0.3975,    Adjusted R-squared:  0.3591 
    F-statistic: 10.34 on 3 and 47 DF,  p-value: 2.431e-05


    • Compare model_1 and model_2
    anova(model_1, model_2)
    Analysis of Variance Table
    
    Model 1: mod$share_voters_voted_trump ~ mod$median_household_income + 
        mod$UrbanRural
    Model 2: mod$share_voters_voted_trump ~ mod$median_household_income + 
        mod$UrbanRural + moderator
      Res.Df     RSS Df Sum of Sq      F Pr(>F)
    1     48 0.43616                           
    2     47 0.42450  1  0.011661 1.2911 0.2616


    • Choose colors to represent the points by group:
    color <- c("red","green","blue")


    • Illustration of the first-order effects of working memory on share_voters_voted_trump:
    ggplot(mod, aes(x = median_household_income, y = share_voters_voted_trump)) +
    geom_smooth(method = "lm", color = "black") +
     geom_point(aes(color = UrbanRural))


    • Illustration of the moderation effect of working memory on share_voters_voted_trump:
    ggplot(mod, aes(x = median_household_income, y = share_voters_voted_trump)) +
     geom_smooth(aes(group = UrbanRural), method = "lm", se = T, color = "black", fullrange = T) +
     geom_point(aes(color = UrbanRural))


    Moderation and Mediation


    A moderator has influence over other effects or relationships, whereas the mediator explains a relationship.

    Resources


    Field, A. (2009). Discovering statistics using SPSS, 3th Ed. Los Angeles: Sage.

    Fox, J. (2016). Applied Regression Analysis and Generalized Linear Models, 3th Ed. Los Angeles: Sage.

    Robotková, A., & Ježek, S. (2012). Vícenásobná lineární regrese. Prezentace ke kurzu PSY252.

     

    A work by Vit Gabrhel

    LS0tCnRpdGxlOiAiKioxMC4gTXVsdGlwbGUgTGluZWFyIFJlZ3Jlc3Npb24qKiIKc3VidGl0bGU6ICJSMTAxIgphdXRob3I6ICJWw610IEdhYnJoZWwiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0aGVtZTogeWV0aQogICAgY29kZV9mb2xkaW5nOiAic2hvdyIKICAgIAotLS0KCgojIyBPdXRsaW5lCjxicj4KCjx1bD4KIyMjIyAwMS4gKipNdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbioqCiMjIyMgMDIuICoqTWVkaWF0aW9uKioKIyMjIyAwMy4gKipNb2RlcmF0aW9uKioKPHVsLz4KCjxicj4KCiMjIERhdGEgYW5kIHBhY2thZ2VzCioqSGF0ZSBDcmltZXMqKgoKPGJyPgoKIVtdKDAxLnBuZykKCjxicj4KCiFbXSgwMi5wbmcpCgo8YnI+CgoqIFBhY2thZ2VzOgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZScsIHdhcm5pbmc9RkFMU0V9CmlwYWsgPC0gZnVuY3Rpb24ocGtnKXsKICBuZXcucGtnIDwtIHBrZ1shKHBrZyAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpWywgIlBhY2thZ2UiXSldCiAgaWYgKGxlbmd0aChuZXcucGtnKSkgCiAgICBpbnN0YWxsLnBhY2thZ2VzKG5ldy5wa2csIGRlcGVuZGVuY2llcyA9IFRSVUUpCiAgc2FwcGx5KHBrZywgcmVxdWlyZSwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKQp9CgpwYWNrYWdlcyA8LSBjKCJnZ3Bsb3QyIiwgImRwbHlyIikKaXBhayhwYWNrYWdlcykKYGBgCgoqIENyZWF0ZSBhIGRhdGFzZXQgYW5kIGl0cyBzdWJzZXQ6CmBgYHtyfQpIYXRlX0NyaW1lcyA8LSByZWFkLmNzdigiaGF0ZV9jcmltZXMuY3N2IikKCkhhdGVfQ3JpbWVzX3NlbGVjdGVkIDwtIHJlYWQuY3N2KCJoYXRlX2NyaW1lcy5jc3YiKSAlPiUgCiAgc2VsZWN0KGMoc2hhcmVfdm90ZXJzX3ZvdGVkX3RydW1wLCAKICAgICAgICAgICBzaGFyZV93aGl0ZV9wb3ZlcnR5LCAKICAgICAgICAgICBzaGFyZV9ub25fY2l0aXplbikpCmBgYAoKPGJyPgoKIyMgTXVsdGlwbGUgTGluZWFyIFJlZ3Jlc3Npb24KIyMjICpMaW5lYXIgUmVncmVzc2lvbioKCjxicj4KCiogKipMaW5lw6FybsOtIHJlZ3Jlc2UqKgogICsgTmFrb2xpayBsemUgeiBJUSBza8OzcnUgdXN1em92YXQgbyB2w71rb251IHYgbWF0ZW1hdGljZT8KICAgICsgKlByZWRpa2NlKgoKPGJyPgoKKiAqKlbDrWNlbsOhc29ibsOhIGxpbmXDoXJuw60gcmVncmVzZSoqCiAgKyBQxZlpc3DDrXbDoSBrIHbDvcWhaSBwbGF0dSBrcm9txJsgw7pyb3ZuxJsgdnpkxJtsw6Fuw60gdGFrw6kgcG9obGF2w60/CiAgICArICpQcmVkaWtjZSoKICAgICsgKklua3JlbWVudMOhbG7DrSB2YWxpZGl0YSoKICAgICsgKlN0YXRpc3RpY2vDoSBrb250cm9sYSoKCjxicj4KCiMjIyMjICoqTm90YWNlKioKCjxjZW50ZXI+CiRZID0gWScgKyBlJAo8L2NlbnRlcj4KCjxicj4KCiogKkxpbmXDoXJuw60gcmVncmVzZSo6Cgo8Y2VudGVyPgokWScgPSBhICsgYlgkCgokWScgPSBiX3swfSArIGJfezF9WF97MX0kCjwvY2VudGVyPgoKPGJyPgoKKiAqVsOtY2Vuw6Fzb2Juw6EgbGluZcOhcm7DrSByZWdyZXNlKjoKCjxjZW50ZXI+CiRZJyA9IGJfezB9ICsgYl97bn1YX3tufSQKCiRZJyA9IGJfezB9ICsgYl97MX1YX3sxfSArIGJfezJ9WF97Mn0gKyAuLi4gKyBiX3tufVhfe259KyBlJAo8L2NlbnRlcj4KCjxicj4KCiogJFkkICo9KiAqKk91dGNvbWUqKiAoPSBkZXBlbmRlbnQpICoqdmFyaWFibGUqKgoqICRZJyQgKj0qIE91ciAqKm1vZGVsKioKKiAkZSQgKj0qICoqRXJyb3IqKgoqICRhJCAqb3IqICRiX3swfSQgKj0qICoqSW50ZXJjZXB0KioKKiAkYiQgKm9yKiAkYl97MS4uLm59JCAqPSogKipTbG9wZSoqCiogJFhfezEuLi5ufSQgKj0qICoqUHJlZGljdG9yKiogKD0gaW5kZXBlbmRlbnQgdmFyaWFibGUpCgo8YnI+Cgo8Y2VudGVyPgoKIVtdKDA2LnBuZykKCjwvY2VudGVyPgoKPGJyPgoKKlDFmcOtbWthIChtb2RlbCkgamUgcHJvbG/FvmVuYSBkYXR5IHRhaywgYWJ5IGppbSBjbyBuZWpsw6lwZSBvZHBvdsOtZGFsYS4qCgoqIE1ldG9kYSBvZGhhZHUgbmVqbWVuxaHDrWNoIMSNdHZlcmPFryAoKipMZWFzdCBTcXVhcmVzIEVzdGltYXRpb24qKikKICArIFN1bWEgKGRydWjDvWNoIG1vY25pbikgdnpkw6FsZW5vc3TDrSBtb2RlbHUgb2QgZGF0IGplIG5lam1lbsWhw60gbW/Fvm7DoQogIAo8YnI+Cgo8Y2VudGVyPgoKIVtdKDA3LnBuZykKCjwvY2VudGVyPgoKPGJyPgoKJFNfe1R9JCReezJ9JCA9ICRTX3tNfSQkXnsyfSQgKyAkU197Un0kJF57Mn0kCgoqIE5lYm9saSAkU1Nfe1R9ID0gU1Nfe3Jlc30gKyBTU197cmVnfSQKCjxicj4KCiRSXnsyfSQgPSAkU1Nfe019JCReezJ9JCArICRTU197VH0kJF57Mn0kCgo8YnI+CgokU1Nfe019JAoKKiBSb3pkw61sIG1lemkgKipudWxvdsO9bSBtb2RlbGVtKiogKHByxa9txJtyICRZJCkgYSBuw6FtaSBzdGFub3ZlbsO9bSBtb2RlbGVtZSAocMWZw61ta291KS4KCiRTU197Un0kCgoqIFJvemTDrWwgbWV6aSAqKmRhdHkqKiBhICoqbsOhbWkgc3Rhbm92ZW7DvW0gbW9kZWxlbSoqIChwxZnDrW1rb3UpLgoKJFNTX3tUfSQKCiogUm96ZMOtbCBtZXppIGRhdHkgYSBudWxvdsO9bSBtb2RlbGVtIChwcsWvbcSbciAkWSQpLgoKJFJeezJ9JAoKKiBQb2TDrWwgcm96cHR5bHUgesOhdmlzbMOpIChvdXRjb21lKSBwcm9txJtubsOpICoqdnlzdsSbdGxlbsOpIG1vZGVsZW0qKiAoPSAqa29lZmljaWVudCBkZXRlcm1pbmFuY2UqKS4KCjxicj4KCipNZXRvZGEgbmVqbWVuxaHDrWNoIMSNdHZlcmPFryBncmFmaWNreSoKCjxjZW50ZXI+CgohW10oMDgucG5nKQoKPC9jZW50ZXI+Cgo8YnI+Cgo8Y2VudGVyPgoKIVtdKDA3LnBuZykKCjwvY2VudGVyPgoKPGJyPgoKIyMjIyAqKk1vZGVsKioKCgpgYGB7cn0KTW9kZWxIYXRlQ3JpbWUgPC0gbG0oZm9ybXVsYSA9IHNoYXJlX3ZvdGVyc192b3RlZF90cnVtcCB+IHNoYXJlX3doaXRlX3BvdmVydHkgKyBzaGFyZV9ub25fY2l0aXplbiwgCiAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBIYXRlX0NyaW1lc19zZWxlY3RlZCkKYGBgCgo8YnI+CgoqIENvbXB1dGUgdGhlIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgbW9kZWw6CmBgYHtyfQojIEdlbmVyaWMgZnVuY3Rpb25zIChzdW1tYXJ5KSBjaGFuZ2UgdGhlaXIgYmVoYXZpb3VyIGJhc2VkIG9uIGFuIG9iamVjdCdzIGNsYXNzLgpzdW1tYXJ5KE1vZGVsSGF0ZUNyaW1lKQpgYGAKCjxicj4KCiogUGVyZm9ybSBhbiBhbmFseXNpcyBvZiB2YXJpYW5jZSBvbiBtb2RlbDoKYGBge3J9CmFub3ZhKE1vZGVsSGF0ZUNyaW1lKQpgYGAKCjxicj4KCiogUHJlZGljdCBiYXNlZCBvbiB0aGUgZml0dGVkIGZ1bmN0aW9uOgpgYGB7cn0KcHJlZGljdChNb2RlbEhhdGVDcmltZSkKYGBgCgo8YnI+CgojIyMjICoqQ29lZmZpY2llbnRzKioKCjxicj4KCioqJGJfe2l9JCoqCgoqIFZ5amFkxZl1amUgbsOhcsWvc3QgJFnigJkkIHDFmWkgbsOhcsWvc3R1ICRYX3tpfSQgbyBqZWRudSBqZWRub3RrdSB2IGplZG5vdGvDoWNoIFksIHDFmWkga29udHJvbGUgdsWhZWNoIG9zdGF0bsOtY2ggcHJlZGlrdG9yxa8gKHRqLiBzZW1pcGFyY2nDoWxuw60ga29yZWxhY2UpOyBqZWRpbmXEjW7DvSBwxZnDrW5vcwogICsgSyBwb3Jvdm7DoW7DrSBzw61seSBwcmVkaWt0b3J1IHYgcsWvem7DvWNoIHNrdXBpbsOhY2gsIG1vZGVsZWNoLCB2em9yY8OtY2gKCioqJM6yX3tpfSQqKgoKKiBCZXRhIHZ5amFkxZl1amUgbsOhcsWvc3QgJFnigJkkIHDFmWkgbsOhcsWvc3R1ICRYX3tpfSQgbyAxOyBwb2t1ZCBqc291ICRYX3tpfSQgYSAkWSQgc3RhbmRhcmRpem92w6FueSwgcMWZaSBrb250cm9sZSB2xaFlY2ggb3N0YXRuw61jaCBwcmVkaWt0b3LFryAodGouIHNlbWlwYXJjacOhbG7DrSBrb3JlbGFjZSksIGplZGluZcSNbsO9IHDFmcOtbm9zCiAgKyBLIHBvcm92bsOhbsOtIHByZWRpa3RvcsWvIG1lemkgc2Vib3UgdiByw6FtY2kgamVkbm9obyBtb2RlbHUKICArIEsgcG9yb3Zuw6Fuw60gcsWvem7EmyBvcGVyYWNpb25hbGl6b3ZhbsOpaG8gcHJlZGlrdG9ydSB2IHLFr3puw71jaCBtb2RlbGVjaAogICsgVWthemF0ZWwgdmVsaWtvc3RpIMO6xI1pbmt1CgoqKiRiX3swfSQqKgoKKiBQbyB2eWNlbnRyb3bDoW7DrSAob2RlxI10ZW7DrSBwcsWvbcSbcnUgb2QgdsWhZWNoIGhvZG5vdCAkWF97aX0kKSBvZHBvdsOtZMOhIHByxa9txJtydSAkWSQuCgpgYGB7ciwgd2FybmluZz1GQUxTRSx9ClF1YW50UHN5Yzo6bG0uYmV0YShNb2RlbEhhdGVDcmltZSkKYGBgCgojIyMgKkFzc3VtcHRpb25zKgoKKiJUbyBkcmF3IGNvbmNsdXNpb25zIGFib3V0IGEgcG9wdWxhdGlvbiBiYXNlZCBvbiBhIHJlZ3Jlc3Npb24gYW5hbHlzaXMgZG9uZSBvbiBhIHNhbXBsZSwgc2V2ZXJhbAphc3N1bXB0aW9ucyBtdXN0IGJlIHRydWUuIiogKEZpZWxkLCAyMDA5ICwgcy4gMjIwKQoKIyMjIyBWYXJpYWJsZXMKMS4gUG92YWhhIHByb23Em25uw71jaCAtIHNwb2ppdMOpLCBrdmFudGl0YXRpdm7DrSBhIGthcmRpbsOhbG7DrSBuZWJvIGR1bW15IChqZW4gdiBwxZnDrXBhZMSbIHByZWRpa3RvcsWvKS4KCjIuIE5lbnVsb3bDoSB2YXJpYWJpbGl0YSBwcmVkaWt0b3LFryAodGouIG5lamRlIG8ga29uc3RhbnR1KS4KCiMjIyMgUHJlZGljdG9ycwozLiBBYnNlbmNlIChkb2tvbmFsw6kpIG11bHRpa29saW5lYXJpdHkgLSBwcmVkaWt0b3J5IGJ5IHNwb2x1IG5lbcSbbHkgdnlzb2NlIGtvcmVsb3ZhdC4KCjQuIFByZWRpa3RvcnkgbmVrb3JlbHVqw60gcyB2bsSbasWhw61taSBwcm9txJtubsO9bWkgLSBhYnNlbmNlIHTFmWV0w60gKGludGVydmVudWrDrWPDrSwgdm7Em2rFocOtKSBwcm9txJtubsOpLgoKPGJyPgoKKiAqKlBvdmFoYSBwcm9txJtubsO9Y2ggYSBuZW51bG92w6EgdmFyaWFiaWxpdGEqKjoKYGBge3J9CkhhdGVfQ3JpbWVzX1NlbGVjdCA8LSBIYXRlX0NyaW1lcyU+JQogc2VsZWN0KGMoInNoYXJlX3ZvdGVyc192b3RlZF90cnVtcCIsICJzaGFyZV93aGl0ZV9wb3ZlcnR5IiwgInNoYXJlX25vbl9jaXRpemVuIikpCiAKbGFwcGx5KEhhdGVfQ3JpbWVzX1NlbGVjdCwgY2xhc3MpCgpzdW1tYXJ5KEhhdGVfQ3JpbWVzX1NlbGVjdCkKCnBzeWNoOjpkZXNjcmliZShIYXRlX0NyaW1lc19TZWxlY3QpICMgaW5zdGFsbC5wYWNrYWdlcygicHN5Y2giKQpgYGAKCjxicj4KCiogKipNdWx0aWtvbGluZWFyaXRhKio6CmBgYHtyfQpjYXI6OnZpZihNb2RlbEhhdGVDcmltZSkgIyB2YXJpYW5jZSBpbmZsYXRpb24gZmFjdG9ycywgaW5zdGFsbC5wYWNrYWdlcygiY2FyIikKCnNxcnQoY2FyOjp2aWYoTW9kZWxIYXRlQ3JpbWUpKSA+IDIgIyBwcm9ibGVtPwoKUmNtZHI6OnJjb3JyLmFkanVzdChIYXRlX0NyaW1lc19TZWxlY3QpICMgaW5zdGFsbC5wYWNrYWdlcygiUmNtZHIiKSwgbGlicmFyeShSY21kcikKYGBgCgo8YnI+CgojIyMjIFJlemlkdWEKCjUuICoqSG9tb3NrZWRhc2NpdGEqKiAtIHJvenB0eWwgcmV6aWR1w60gYnkgbcSbbCBiw710IGtvbnN0YW50bsOtIG5hcMWZw63EjSByxa96bsO9bWkgw7pyb3ZuxJttaSBwcmVkaWt0b3J1LgoKNi4gKipOZXrDoXZpc2xvc3QgcmV6aWR1w60qKiAtIFJlemlkdcOhbG7DrSBob2Rub3R5IGt0ZXLDvWNoa29saXYgZHZvdSBwxZnDrXBhZMWvIGJ5IHNwb2x1IG5lbcSbbHkgc291dmlzZXQuCgo3LiAqKk5vcm3DoWxuxJsgcm96bG/FvmVuw6EgcmV6aWR1YSoqIC0gamVqaWNoIHJvemxvxb5lbsOtIGJ5IG3Em2xvIGLDvXQgbsOhaG9kbsOpLgoKPGJyPgoKIyMjIyBPdXRjb21lCgo4LiAqKk5lesOhdmlzbG9zdCoqIGt0ZXLDvWNoa29saXYgZHZvdSBob2Rub3QgesOhdmlzbMOpIHByb23Em25uw6kgKGthxb5kw6EgaG9kbm90YSB2IHLDoW1jaSBuw60gcG9jaMOhesOtIHogdW5pa8OhdG7DrWhvIHpkcm9qZSkuCgo5LiAqKkxpbmVhcml0YSoqIC0gcMWZw61ta2EgamFrbyB2aG9kbsO9IG1vZGVsIHBvcGlzdSBkYXQuCgo8YnI+CgoqICoqSG9tb3NrZWRhc2NpdGEqKiBhICoqbGluZWFyaXRhKiogKCpkbGUgRmllbGQsIDIwMDksIHMuIDI0OCopCgo8Y2VudGVyPgoKIVtdKDEwLnBuZykKCjwvY2VudGVyPgoKPGJyPgoKKiAqKkV2YWx1YXRlIGhvbW9zY2VkYXN0aWNpdHkqKjoKYGBge3J9CiMgbm9uLWNvbnN0YW50IGVycm9yIHZhcmlhbmNlIHRlc3QKY2FyOjpuY3ZUZXN0KE1vZGVsSGF0ZUNyaW1lKQoKIyBwbG90IHN0dWRlbnRpemVkIHJlc2lkdWFscyB2cy4gZml0dGVkIHZhbHVlcwpjYXI6OnNwcmVhZExldmVsUGxvdChNb2RlbEhhdGVDcmltZSkKYGBgCgo8YnI+CgoqICoqTmV6w6F2aXNsb3N0IHJlemlkdcOtKio6CmBgYHtyfQojIFRlc3QgZm9yIEF1dG9jb3JyZWxhdGVkIEVycm9ycwpjYXI6OmR1cmJpbldhdHNvblRlc3QoTW9kZWxIYXRlQ3JpbWUpCmBgYAoKPGJyPgoKKiAqKk5vcm3DoWxuxJsgcm96bG/FvmVuw6EgcmV6aWR1YSoqOgpgYGB7cn0KIyBkaXN0cmlidXRpb24gb2Ygc3R1ZGVudGl6ZWQgcmVzaWR1YWxzCiMgbGlicmFyeShNQVNTKQpzcmVzaWQgPC0gTUFTUzo6c3R1ZHJlcyhNb2RlbEhhdGVDcmltZSkKCmhpc3Qoc3Jlc2lkLCBmcmVxPUZBTFNFLCBtYWluPSJEaXN0cmlidXRpb24gb2YgU3R1ZGVudGl6ZWQgUmVzaWR1YWxzIikKYGBgCgo8YnI+CgoqICoqTGluZWFyaXRhKio6CmBgYHtyfQojIGNvbXBvbmVudCArIHJlc2lkdWFsIHBsb3QKY2FyOjpjclBsb3RzKE1vZGVsSGF0ZUNyaW1lKQpgYGAKCiMjIyAqTW9kZWwgRGlhZ25vc3RpY3MqCgo8YnI+CgojIyMjIE91dGxpZXJzIGFuZCBJbmZsdWVudGlhbCBjYXNlcwoKKk5lbWFqw60gbsSba3RlcsOpIHDFmcOtcGFkeSBwxZnDrWxpxaEgdmVsa8O9IHZsaXYgbmEgdsO9c2xlZGt5IHJlZ3Jlc2U/KgoKKiAqKk91dGxpZXJzKiog4oCTIG1vaG91IHp2ecWhb3ZhdCBpIHNuacW+b3ZhdCBiCiAgKyAqKlJlemlkdWEqKiDigJMgcMWZw61wYWR5IHMgdnlzb2vDvW1pIHJlemlkdWkgcmVncmVzZSBwcmVkaWt1amUgbmVqaMWvxZksIHN0YW5kYXJkaXpvdmFuw6EsIMKxIDMKICArICoqVmxpdm7DqSBwxZnDrXBhZHkqKiDigJMgcMWZw61wYWR5LCBrdGVyw6kgbmVqdsOtYyBvdmxpdsWIdWrDrSBwYXJhbWV0cnkgbW9kZWx1CiAgICArIENvIHNlIHN0YW5lIHMgcGFyYW1ldHJ5IHJlZ3Jlc2UsIGtkecW+IHDFmcOtcGFkIG9kc3RyYW7DrW1lPwogICAgKyBERkJldGEg4oCTIHJvemTDrWwgbWV6aSBwYXJhbWV0cmVtIHMgYSBiZXosIHN0YW5kYXJkaXpvdmFuw6kgPiAxCiAgICArIERGRml0IOKAkyByb3pkw61sIG1lemkgcHJlZGlrb3Zhbm91IGhvZG5vdG91IGEgcHJlZGlrb3Zhbm91IGhvZG5vdG91IGJleiBwxZnDrXBhZHUgKGFkanVzdG92YW5vdSkKICAgICsgQ29va292YSB2emTDoWxlbm9zdCA+IDEKICAgICsgTGV2ZXJhZ2UgPiAyKCBrKzEpLyBuICwga2RlIGsgPSBwb8SNZXQgcHJlZGlrdG9yxa8sIG4gPSB2ZWxpa29zdCB2w71ixJtyb3bDqWhvIHNvdWJvcnUKUMWZw61wYWR5IHMgdnlzb2vDvW1pIHJlemlkdWkgxI1pIHZsaXZuw6kgcMWZw61wYWR5IE5FT0RTVFJBxYdVSkVNRQouLi5sZWRhIGJ5IMWhbG8gbyB6amV2bm91IGNoeWJ1IHYgZGF0ZWNoIMSNaSB2em9ya3UKLi4ubGVkYSBieSBuw6FtIMWhbG8gdsO9aHJhZG7EmyBvIHpwxZllc27Em27DrSBwcmVkaWtjZSAobmlrb2xpIG8gdGVzdHkgaHlwb3TDqXopCgo8YnI+CgoqICoqT3V0bGllcnMqKjoKYGBge3J9CiMgQm9uZmVyb25uaSBwLXZhbHVlIGZvciBtb3N0IGV4dHJlbWUgb2JzZXJ2YXRpb25zCmNhcjo6b3V0bGllclRlc3QoTW9kZWxIYXRlQ3JpbWUpCgojcXEgcGxvdCBmb3Igc3R1ZGVudGl6ZWQgcmVzaWQKY2FyOjpxcVBsb3QoTW9kZWxIYXRlQ3JpbWUsIG1haW49IlFRIFBsb3QiKQpgYGAKCjxicj4KCiogKipJbmZsdWVudGlhbHMqKjoKYGBge3J9CiMgQ29vaydzIEQgcGxvdAojIGlkZW50aWZ5IEQgdmFsdWVzID4gNC8obi1rLTEpCmN1dG9mZiA8LSA0LygobnJvdyhIYXRlX0NyaW1lcyktbGVuZ3RoKE1vZGVsSGF0ZUNyaW1lJGNvZWZmaWNpZW50cyktMikpCnBsb3QoTW9kZWxIYXRlQ3JpbWUsIHdoaWNoPTQsIGNvb2subGV2ZWxzPWN1dG9mZikKCiMgbGV2ZXJhZ2UgcGxvdHMKY2FyOjpsZXZlcmFnZVBsb3RzKE1vZGVsSGF0ZUNyaW1lKQpgYGAKCjxicj4KCiMjIyMgQ29sbGluZWFyaXR5CgoqIEtkecW+IGR2YSBwcmVkaWt0b3J5IHZ5c3bEm3RsdWrDrSAqKnR1dMOpxb4gxI3DoXN0IHZhcmlhYmlsaXR5KiogesOhdmlzbMOpIHByb23Em25uw6ksIGplZGVuIHogbmljaCBqZSB0w6ltxJvFmQp6Ynl0ZcSNbsO9CiogKipLb21wbGlrdWplIHBvcm92bsOhdsOhbsOtKiogc8OtbHkgcHJlZGlrdG9yxa8KKiAqKlNuacW+dWplIHN0YWJpbGl0dSoqIG9kaGFkdSBwYXJhbWV0csWvCiogViBleHRyw6ltdSAoKmtkecW+IGx6ZSBqZWRlbiBwcmVkaWt0b3IgcMWZZXNuxJsgdnlwb8SNw610YXQgeiBvc3RhdG7DrWNoKikgcmVncmVzaSDDunBsbsSbICoqem5lbW/FvsWIdWplKioKKiAqKiJSdWxlcyBvZiBUaHVtYiIqKgogICsgS29yZWxhY2UgbmFkIDAsOQogICsgVG9sZXJhbmNlICg9IDEvVklGKSBjY2EgcG9kIDAsMQogICsgVklGICg9IDEvdG9sZXJhbmNlKSBjY2EgbmFkIDEwCgo8YnI+CgojIyMgKkR1bW15IGNvZGluZyoKCiMjIyMgSW50cm9kdWN0aW9uIHRvIGR1bW15IGNvZGluZwoKKipEdW1teSBwcm9txJtubsOpKiogLSBrYXRlZ29yaWNrw6kgcHJvbcSbbm7DqSB1cHJhdmVuw6kgdGFrLCBhYnkgbW9obHkgdnN0b3VwaXQgZG8gKHbDrWNlbsOhc29ibsOpKQpsaW5lw6FybsOtIHJlZ3Jlc2UKCiogUG9zdHVwIChkbGUgRmllbGQsIDIwMDksIHMuIDI1NCk6IAoKPGNlbnRlcj4KCiFbXSgxMS5wbmcpCgo8L2NlbnRlcj4KCjxicj4KCkluZGlrw6F0b3JvdsOpIGvDs2RvdsOhbsOtICgqKkluZGljYXRvciBjb2RpbmcqKikKCiogUmVmZXJlbsSNbsOtIGthdGVnb3JpZSA9IDAKCkVmZWt0b3bDqSBrw7Nkb3bDoW7DrSAoKipFZmZlY3QgY29kaW5nKiopCgoqIFJlZmVyZW7EjW7DrSBrYXRlZ29yaWUgPSAtMQoKPGJyPgoKPGNlbnRlcj4KCiFbXSgxMi5wbmcpCgo8L2NlbnRlcj4KCjxicj4KCiMjIyMgQ29kaW5nCgo8Y2VudGVyPgoKJFkgPSBiX3swfSArIGJfe0ExfVhfe0ExfSArIGJfe0EyfVhfe0EyfSArIC4uLiArIGJfe219WF97bX0rIGUkCgo8L2NlbnRlcj4KCiogUG8gZG9zYXplbsOtIGRvIHJlZ3Jlc27DrSByb3ZuaWNlIHByZWRpa3VqZW1lIHDFmcOtcGFkdSBwcsWvbcSbciBqZWhvIHNrdXBpbnkgKHBva3VkIG5lanNvdSDFvsOhZG7DqSBkYWzFocOtIHByZWRpa3RvcnkpLgoKKiAqKkluZGlrw6F0b3JvdsOpIGvDs2RvdsOhbsOtKioKICArICRiX3tBaX0kIHVkw6F2w6Egcm96ZMOtbCBwcsWvbcSbcm7DvWNoIGhvZG5vdCBZIG1lemkgaW5kaWtvdmFub3Ugc2t1cGlub3UgYSByZWZlcmVuxI1uw60gc2t1cGlub3U7IHNpZ25pZmlrYW5jaSBiIEFpIHJlZmVyZW7EjW7DrSBza3VwaW5vdTsgc2lnbmlmaWthbmNlIGJBaSB6bmFtZW7DoSBzaWduaWZpa2FuY2kgcm96ZMOtbHUKICArICRiX3tBaX0kIHVkw6F2w6EgbyBrb2xpayBuw6FtIMSNbGVuc3R2w60gdmUgc2t1cGluxJsgenZ5xaF1amUvc25pxb51amUgcHJlZGlrb3Zhbm91IGhvZG5vdHUgb3Byb3RpIHJlZmVyZW7EjW7DrSBza3VwaW7EmwogICsgJGJfezB9JCB1ZMOhdsOhIChwxZlpIGFic2VuY2kgamluw71jaCBwcmVkaWt0b3LFrykgcHLFr23Em3IgWSB2IHJlZmVyZW7EjW7DrSBza3VwaW7EmwoqICoqRWZla3RvdsOpIGvDs2RvdsOhbsOtKioKICArICRiX3tBaX0kIHVkw6F2w6Egcm96ZMOtbCBwcsWvbcSbcm7DvWNoIGhvZG5vdCBZIG1lemkgaW5kaWtvdmFub3Ugc2t1cGlub3UgYSBjZWxrb3bDvW0gcHLFr23Em3JlbQogICsgJGJfezB9JCB1ZMOhdsOhIChwxZlpIGFic2VuY2kgamluw71jaCBwcmVkaWt0b3LFrykgY2Vsa292w70gcHLFr23Em3IKCjxicj4KCiMjIyMgRXhhbXBsZQpgYGB7cn0KSGF0ZV9DcmltZXMkVXJiYW5SdXJhbCA9IGN1dChIYXRlX0NyaW1lcyRzaGFyZV9wb3B1bGF0aW9uX2luX21ldHJvX2FyZWFzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcz1jKC1JbmYsMC41LCBJbmYpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiUnVyYWwiLCJVcmJhbiIpKQoKIyBUaGUgZmFjdG9yIGZ1bmN0aW9uCmNsYXNzKEhhdGVfQ3JpbWVzJFVyYmFuUnVyYWwpCmNvbnRyYXN0cyhIYXRlX0NyaW1lcyRVcmJhblJ1cmFsKQogIApzdW1tYXJ5KGxtKHNoYXJlX3ZvdGVyc192b3RlZF90cnVtcCB+IHNoYXJlX3doaXRlX3BvdmVydHkgKwogc2hhcmVfbm9uX2NpdGl6ZW4gKyBVcmJhblJ1cmFsLCBkYXRhID0gSGF0ZV9DcmltZXMpKQpgYGAKCjxicj4KCiMjIE1lZGlhdGlvbgoKIyMjICpJbnRyb2R1Y3Rpb24qCgpBIG1lZGlhdGlvbiBhbmFseXNpcyBpcyB0eXBpY2FsbHkgY29uZHVjdGVkIHRvIGJldHRlciB1bmRlcnN0YW5kIGFuIG9ic2VydmVkIGVmZmVjdCBvZiBhbiBJViBvbiBhIERWIG9yIGEgY29ycmVsYXRpb24gYmV0d2VlbiAkWCQgYW5kICRZJC4KCiogV2h5LCBhbmQgaG93LCBkb2VzICRYJCBpbmZsdWVuY2UvY29ycmVsYXRlcyB3aXRoICRZJD8KCklmICRYJCBhbmQgJFkkIGFyZSBjb3JyZWxhdGVkIEJFQ0FVU0Ugb2YgdGhlIG1lZGlhdG9yICRNJCwgdGhlbiAoJFgkIC0+ICRNJCAtPiAkWSQpCgo8YnI+Cgo8Y2VudGVyPgoKJFkgPSBCX3swfSArIEJfMU0gKyBlJAoKJgoKJE0gPSBCXzAgKyBCXzFYICsgZSQKCiYKCiRZID0gQl8wICsgQl8xTSArIEJfMlggKyBlJAoKPC9jZW50ZXI+Cgo8YnI+CgpXaGF0IHdpbGwgaGFwcGVuIHRvIHRoZSBwcmVkaWN0aXZlIHZhbHVlIG9mICRYJD8KCiogSW4gb3RoZXIgd29yZHMsIHdpbGwgJEJfMiQgYmUgc2lnbmlmaWNhbnQ/Cgo8YnI+CgpBIG1lZGlhdG9yIHZhcmlhYmxlIChNKSBhY2NvdW50cyBmb3Igc29tZSBvciBhbGwgb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIFggYW5kIFk6CgoqIFNvbWU6ICoqUGFydGlhbCBtZWRpYXRpb24qKgoqIEFsbDogKipGdWxsIG1lZGlhdGlvbioqCgo8YnI+CgojIyMgKkV4YW1wbGUqCgoqIFJ1biB0aGUgdGhyZWUgcmVncmVzc2lvbiBtb2RlbHM6CmBgYHtyfQptb2RlbF95eCA8LSBsbShIYXRlX0NyaW1lcyRzaGFyZV92b3RlcnNfdm90ZWRfdHJ1bXAgfiBIYXRlX0NyaW1lcyRtZWRpYW5faG91c2Vob2xkX2luY29tZSkKCm1vZGVsX214IDwtIGxtKEhhdGVfQ3JpbWVzJHNoYXJlX3BvcHVsYXRpb25faW5fbWV0cm9fYXJlYXMgfiBIYXRlX0NyaW1lcyRtZWRpYW5faG91c2Vob2xkX2luY29tZSkKCm1vZGVsX3l4bSA8LSBsbShIYXRlX0NyaW1lcyRzaGFyZV92b3RlcnNfdm90ZWRfdHJ1bXAgfiBIYXRlX0NyaW1lcyRtZWRpYW5faG91c2Vob2xkX2luY29tZSArIEhhdGVfQ3JpbWVzJHNoYXJlX3BvcHVsYXRpb25faW5fbWV0cm9fYXJlYXMpCmBgYAoKPGJyPgoKKiBNYWtlIGEgc3VtbWFyeSBvZiB0aGUgdGhyZWUgbW9kZWxzOgpgYGB7cn0Kc3VtbWFyeShtb2RlbF95eCkKc3VtbWFyeShtb2RlbF9teCkKc3VtbWFyeShtb2RlbF95eG0pCmBgYAoKPGJyPgoKKiBTb2JlbCB0ZXN0OgpgYGB7cn0KIyBpbnN0YWxsLnBhY2thZ2VzKCJtdWx0aWxldmVsIikKCiMgQ29tcGFyZSB0aGUgcHJldmlvdXMgcmVzdWx0cyB0byB0aGUgb3V0cHV0IG9mIHRoZSBzb2JlbCBmdW5jdGlvbgptb2RlbF9hbGwgPC0gbXVsdGlsZXZlbDo6c29iZWwoSGF0ZV9DcmltZXMkc2hhcmVfcG9wdWxhdGlvbl9pbl9tZXRyb19hcmVhcywKICAgICAgICAgICAgICAgICAgIEhhdGVfQ3JpbWVzJG1lZGlhbl9ob3VzZWhvbGRfaW5jb21lLAogICAgICAgICAgICAgICAgICAgSGF0ZV9DcmltZXMkc2hhcmVfdm90ZXJzX3ZvdGVkX3RydW1wKQoKIyBQcmludCBvdXQgbW9kZWxfYWxsCm1vZGVsX2FsbApgYGAKCjxicj4KCiMjIE1vZGVyYXRpb24KCiMjIyAqSW50cm9kdWN0aW9uKgoKKiBFeHBlcmltZW50w6FsbsOtIGRlc2lnbgogICsgTWFuaXB1bGFjZSBzIG5lesOhdmlzbG91IHByb23Em25ub3UgKCRYJCkgdmVkZSBrZSB6bcSbbsSbIHYgesOhdmlzbMOpIHByb23Em25uw6kgKCRZJCkKICArIE1vZGVyw6F0b3IgKCRaJCkgemF2w6Fkw61tZSB6IHRvaG8ga3bFr2xpIHDFmWVkcG9rbGFkdSwgxb5lIHZsaXYgKMO6xI1pbmVrKSAkWCQgbmEgJFkkICoqTkVOw40qKiBrb256aXN0ZW50bsOtIG5hcMWZw63EjSByb3psb8W+ZW7DrW0gKHLFr3puw71taSDDunJvdm7Em21pKSAkWiQKCiogS29yZWxhxI1uw60gZGVzaWduCiAgKyBQxZllZHBva2zDoWTDoW1lIHNvdXZpc2xvc3QgbWV6aSBwcm9txJtubsO9bWkgJFgkIGEgJFkkCiAgKyBNb2RlcsOhdG9yICQoWikkIHphdsOhZMOtbWUga3bFr2xpIHDFmWVkcG9rbGFkdSwgxb5lIGtvcmVsYWNlIG1lemkgJFgkIGEgJFkkICoqTkVOw40qKiBrb256aXN0ZW50bsOtIG5hcMWZw63EjSByb3psb8W+ZW7DrW0gKHLFr3puw71taSDDunJvdm7Em21pKSAkWiQKICAKUG9rdWQganNvdSBvYm9qZSAkWCQgYSAkWiQgc3Bvaml0w6kgKHJlc3AuIGludGVydmFsb3bDqSDDunJvdm7EmyBtxJvFmWVuw60pOgoKPGNlbnRlcj4KCiRZID0gQl8wICsgQl8xWCArIEJfMlogKyBCXzMoWCQqJFopICsgZSQKCjwvY2VudGVyPgoKKiBQb2t1ZCBqZSAkWCQga2F0ZWdvcmlja8OhIGEgJFokIHNwb2ppdMOhICgzIMO6cm92bsSbICRYJCk6Cgo8Y2VudGVyPgoKJFkgPSBCXzAgKyBCXzEoWF8xKSArIEJfMihYXzIpICsgQl8zWiArIEJfNChYXzEkKiRaKSArIEJfNShYXzIkKiRaKSArIGUkCgo8L2NlbnRlcj4KCgo8YnI+CgojIyMgKkV4YW1wbGUqCgoqIERhdGEKYGBge3J9Cm1vZCA8LSBIYXRlX0NyaW1lcyAlPiUKICAgICAgICBzZWxlY3Qoc2hhcmVfdm90ZXJzX3ZvdGVkX3RydW1wLCBtZWRpYW5faG91c2Vob2xkX2luY29tZSwgVXJiYW5SdXJhbCkKYGBgCgoqIFN1bW1hcnkgc3RhdGlzdGljcwpgYGB7cn0KcHN5Y2g6OmRlc2NyaWJlQnkobW9kLCBtb2QkVXJiYW5SdXJhbCkKYGBgCgoKKiBDcmVhdGUgYSBib3hwbG90IG9mIHRoZSBkYXRhCmBgYHtyfQpib3hwbG90KGZvcm11bGEgPSBtb2Qkc2hhcmVfdm90ZXJzX3ZvdGVkX3RydW1wIH4gbW9kJFVyYmFuUnVyYWwsIAogICAgICAgICAgbWFpbiA9ICJCb3hwbG90IiwgCiAgICAgICAgICB4bGFiID0gIkdyb3VwIFVyYmFuUnVyYWwiLCAKICAgICAgICAgIHlsYWIgPSAic2hhcmVfdm90ZXJzX3ZvdGVkX3RydW1wIikKYGBgCgo8YnI+CgoqICBDcmVhdGUgc3Vic2V0cyBvZiB0aGUgdHdvIGdyb3VwczoKYGBge3J9CiMgTWFrZSB0aGUgc3Vic2V0IGZvciB0aGUgZ3JvdXAgVXJiYW5SdXJhbCA9ICJSdXJhbCIKbW9kX1J1cmFsIDwtIHN1YnNldChtb2QsIAogICAgICAgICAgICAgICAgICAgIG1vZCRVcmJhblJ1cmFsID09ICJSdXJhbCIpCgojIE1ha2UgdGhlIHN1YnNldCBmb3IgdGhlIGdyb3VwIFVyYmFuUnVyYWwgPSAiVXJiYW4iCm1vZF9VcmJhbiA8LSBzdWJzZXQobW9kLCAKICAgICAgICAgICAgICAgICAgICBtb2QkVXJiYW5SdXJhbCA9PSAiVXJiYW4iKQpgYGAKCjxicj4KCiogQ2FsY3VsYXRlIHRoZSBjb3JyZWxhdGlvbnM6CmBgYHtyfQpjb3IobW9kX1J1cmFsJHNoYXJlX3ZvdGVyc192b3RlZF90cnVtcCwgbW9kX1J1cmFsJG1lZGlhbl9ob3VzZWhvbGRfaW5jb21lKQpjb3IobW9kX1VyYmFuJHNoYXJlX3ZvdGVyc192b3RlZF90cnVtcCwgbW9kX1VyYmFuJG1lZGlhbl9ob3VzZWhvbGRfaW5jb21lKQpgYGAKCjxicj4KCiogIE1vZGVsIHdpdGhvdXQgbW9kZXJhdGlvbiAodGVzdHMgZm9yICJmaXJzdC1vcmRlciBlZmZlY3RzIikKYGBge3J9Cm1vZGVsXzEgPC0gbG0obW9kJHNoYXJlX3ZvdGVyc192b3RlZF90cnVtcCB+IG1vZCRtZWRpYW5faG91c2Vob2xkX2luY29tZSArIG1vZCRVcmJhblJ1cmFsKQpgYGAKCjxicj4KCiogIE1ha2UgYSBzdW1tYXJ5IG9mIG1vZGVsXzEKYGBge3J9CnN1bW1hcnkobW9kZWxfMSkKYGBgCgo8YnI+CgoqIENyZWF0ZSBuZXcgcHJlZGljdG9yIHZhcmlhYmxlcwpgYGB7cn0KbW9kZXJhdG9yIDwtIG1vZCRtZWRpYW5faG91c2Vob2xkX2luY29tZSAqIGFzLm51bWVyaWMobW9kJFVyYmFuUnVyYWwpCmBgYAoKPGJyPgoKKiBNb2RlbCB3aXRoIG1vZGVyYXRpb24KYGBge3J9Cm1vZGVsXzIgPC0gbG0obW9kJHNoYXJlX3ZvdGVyc192b3RlZF90cnVtcCB+IG1vZCRtZWRpYW5faG91c2Vob2xkX2luY29tZSArIG1vZCRVcmJhblJ1cmFsICsgbW9kZXJhdG9yKQpgYGAKCjxicj4KCiogTWFrZSBhIHN1bW1hcnkgb2YgbW9kZWxfMgpgYGB7cn0Kc3VtbWFyeShtb2RlbF8yKQpgYGAKCjxicj4KCiogQ29tcGFyZSBtb2RlbF8xIGFuZCBtb2RlbF8yCmBgYHtyfQphbm92YShtb2RlbF8xLCBtb2RlbF8yKQpgYGAKCjxicj4KCiogIENob29zZSBjb2xvcnMgdG8gcmVwcmVzZW50IHRoZSBwb2ludHMgYnkgZ3JvdXA6CmBgYHtyfQpjb2xvciA8LSBjKCJyZWQiLCJncmVlbiIsImJsdWUiKQpgYGAKCjxicj4KCiogSWxsdXN0cmF0aW9uIG9mIHRoZSBmaXJzdC1vcmRlciBlZmZlY3RzIG9mIHdvcmtpbmcgbWVtb3J5IG9uIHNoYXJlX3ZvdGVyc192b3RlZF90cnVtcDoKYGBge3J9CmdncGxvdChtb2QsIGFlcyh4ID0gbWVkaWFuX2hvdXNlaG9sZF9pbmNvbWUsIHkgPSBzaGFyZV92b3RlcnNfdm90ZWRfdHJ1bXApKSArCmdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIAogICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gVXJiYW5SdXJhbCkpCmBgYAoKPGJyPgoKKiBJbGx1c3RyYXRpb24gb2YgdGhlIG1vZGVyYXRpb24gZWZmZWN0IG9mIHdvcmtpbmcgbWVtb3J5IG9uIHNoYXJlX3ZvdGVyc192b3RlZF90cnVtcDoKYGBge3J9CmdncGxvdChtb2QsIGFlcyh4ID0gbWVkaWFuX2hvdXNlaG9sZF9pbmNvbWUsIHkgPSBzaGFyZV92b3RlcnNfdm90ZWRfdHJ1bXApKSArCiBnZW9tX3Ntb290aChhZXMoZ3JvdXAgPSBVcmJhblJ1cmFsKSwgCiAgICAgICAgICAgICBtZXRob2QgPSAibG0iLCAKICAgICAgICAgICAgIHNlID0gVCwgCiAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsIAogICAgICAgICAgICAgZnVsbHJhbmdlID0gVCkgKwogZ2VvbV9wb2ludChhZXMoY29sb3IgPSBVcmJhblJ1cmFsKSkKYGBgCgo8YnI+CgojIyBNb2RlcmF0aW9uIGFuZCBNZWRpYXRpb24KCjxicj4KCjxjZW50ZXI+Cgo8dT4gQSBtb2RlcmF0b3IgaGFzIGluZmx1ZW5jZSBvdmVyIG90aGVyIGVmZmVjdHMgb3IgcmVsYXRpb25zaGlwcywKd2hlcmVhcyB0aGUgbWVkaWF0b3IgZXhwbGFpbnMgYSByZWxhdGlvbnNoaXAuIDwvdT4KCjwvY2VudGVyPgoKIyMgUmVzb3VyY2VzCgo8YnI+CgpGaWVsZCwgQS4gKDIwMDkpLiBEaXNjb3ZlcmluZyBzdGF0aXN0aWNzIHVzaW5nIFNQU1MsIDN0aCBFZC4gTG9zIEFuZ2VsZXM6IFNhZ2UuCgpGb3gsIEouICgyMDE2KS4gQXBwbGllZCBSZWdyZXNzaW9uIEFuYWx5c2lzIGFuZCBHZW5lcmFsaXplZCBMaW5lYXIgTW9kZWxzLCAzdGggRWQuIExvcyBBbmdlbGVzOiBTYWdlLgoKUm9ib3Rrb3bDoSwgQS4sICYgSmXFvmVrLCBTLiAoMjAxMikuIFbDrWNlbsOhc29ibsOhIGxpbmXDoXJuw60gcmVncmVzZS4gUHJlemVudGFjZSBrZSBrdXJ6dSBQU1kyNTIuCgoKJm5ic3A7CjxociAvPgo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+QSB3b3JrIGJ5IDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9WR2FicmhlbCI+Vml0IEdhYnJoZWw8L2E+PC9wPgo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+PHNwYW4gc3R5bGU9ImNvbG9yOiAjODA4MDgwOyI+PGVtPnZpdC5nYWJyaGVsQGdtYWlsLmNvbTwvZW0+PC9zcGFuPjwvcD4KCjwhLS0gQWRkIGljb24gbGlicmFyeSAtLT4KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9mb250LWF3ZXNvbWUvNC43LjAvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIj4KCjwhLS0gQWRkIGZvbnQgYXdlc29tZSBpY29ucyAtLT4KPHAgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPgogICAgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL1ZHYWJyaGVsIiBjbGFzcz0iZmEgZmEtZ2l0aHViIj48L2E+CiAgICA8YSBocmVmPSJodHRwczovL2N6LmxpbmtlZGluLmNvbS9pbi92JUMzJUFEdC1nYWJyaGVsLTJiMGE4Yjk4IiBjbGFzcz0iZmEgZmEtbGlua2VkaW4iPjwvYT4KICAgIDxhIGhyZWY9Imh0dHBzOi8vc2Nob2xhci5nb29nbGUuY29tL2NpdGF0aW9ucz91c2VyPVktTkdKZWtBQUFBSiZobD1lbiZvaT1hbyIgY2xhc3M9ImZhIGZhLWJvb2siPjwvYT4KPC9wPgo=