Jennifer Ganeles
4/7/19

Airbnb Satisfaction: How Much Does Price Matter? (A Multilevel Analysis)

This week’s homework explores an AirBNB analysis Lisbon datset found on Kaggle. Airbnb is an online marketplace, which allows people to rent out their properties or spare rooms to guests. Its popularity has increased over the years as a financially-friendly way to stay overnight in prime locations while also getting an authentically local travel experience.


Airbnb is known for being a cheaper alternative to normal hotel accommodations, but what’s considered a good price can vary by location. For this reason, I will be using multilevel modelling to explore how price affects overall Airbnb satisfaction across individual listings as well as across neighborhoods. The dataset contains listing and rating information for 13,578 Airbnb accommodations spanning 24 neighborhoods in Lisbon, Portugal as of 2017.

Importing the Data and Examining Key Variables:

My dependent variable (overall satisfaction) was rated on a scale from 0 to 5. My independent variable (price) was simplified into two levels using median as a cuttoff point: Low ($70 or lower) and High (Greater than $70).
Low Price=0
High Price=1

library(readr)
airbnb<-read_csv("/Users/jenniferganeles/Downloads/airbnb_lisbon_1480_2017-07-27.csv")
airbnb$pricelev <- ifelse(airbnb$price > median(airbnb$price), 1, 0)
airbnb<-select(airbnb, room_id, neighborhood, overall_satisfaction, price, pricelev, accommodates, bedrooms, reviews)
airbnbs<-airbnb[order(-airbnb$overall_satisfaction),]
head(airbnbs)

Ecological Analysis (Neighborhood-Level Analysis)

First, I will be conducting an ecological regression, which is a neighborhood-level analysis. The below analysis shows that at the neighborhood-level, there is an insignificant positive relationship between price level and satisfaction rating. We may be tempted to say that high priced accommodations have higher ratings, but this would be an ecological fallacy since I am not using individual-level data here.

#First, grouping by neighborhood:
hood<-airbnbs %>% 
  group_by(neighborhood) %>% 
  summarise(mean_s = mean(overall_satisfaction, na.rm = TRUE), mean_p = mean(pricelev, na.rm = TRUE))
#Ecological model:
ecoreg <- lm(mean_s ~ mean_p, data = hood)
summary(ecoreg)

Call:
lm(formula = mean_s ~ mean_p, data = hood)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.5061 -0.4240  0.1378  0.4185  0.8816 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   2.5283     0.4159   6.079 4.06e-06 ***
mean_p        0.5188     0.9259   0.560    0.581    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.6483 on 22 degrees of freedom
Multiple R-squared:  0.01407,   Adjusted R-squared:  -0.03075 
F-statistic: 0.3139 on 1 and 22 DF,  p-value: 0.5809

Complete-Pooling Model (Individual-Level Analysis)

Using the complete pooling method, I can see that there is a significant negative relationship between price level and satisfaction rating. In other words, high prices decrease satisfaction by 0.19. However, here I am exploring the relationship between price level and satisfaction rating under the assumption that no difference exists between neighborhoods. Like my ecological regression, this model is also flawed since the type of neighborhood can be an important determinant of what is satisfactory and what it not.

cpooling <- lm(overall_satisfaction ~ pricelev, data = airbnbs)
summary(cpooling)

Call:
lm(formula = overall_satisfaction ~ pricelev, data = airbnbs)

Residuals:
   Min     1Q Median     3Q    Max 
-3.338 -3.144  1.162  1.662  1.856 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  3.33770    0.02594 128.680  < 2e-16 ***
pricelev    -0.19345    0.03689  -5.245 1.59e-07 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.149 on 13576 degrees of freedom
Multiple R-squared:  0.002022,  Adjusted R-squared:  0.001948 
F-statistic: 27.51 on 1 and 13576 DF,  p-value: 1.59e-07

No-Pooling Model (Intercept)

Here, I am running 24 different regression models (one per neighborhood) using the no-pooling model. Below are plots of the intercept of my regression for each neighborhood. The intercept represents the average satisfaction rating for listings that are low price (picelev=0). Here, the mode satisfaction rating for low-price listings is about 3, but variation exists with ratings as high as 4 and as low as about 1.3.

dcoefi <- airbnbs %>% 
    group_by(neighborhood) %>% 
    do(mod = lm(overall_satisfaction ~ pricelev, data = .))
coefi <- dcoef %>% do(data.frame(intc = coef(.$mod)[1]))
ggplot(coefi, aes(x = intc)) + geom_histogram()+xlab("Satisfaction Rating for Low Price Across 24 Neighborhoods")

ggplot(coefi, aes(x = intc)) + geom_density(fill="steelblue")+xlab("Satisfaction Rating for Low Price Level Across 24 Neighborhoods")

No Pooling Model (Slope)

Below are plots of the slope of my regression for each neighborhood (in other words, the difference in satisfaction between price levels across neighborhoods). The mode difference is about -0.5, which suggests that satifaction ratings are, on average, 0.5 lower for high-priced airbnb listings than for low-priced listings. However, there is variation in this distribution as well. Satisfaction rating for high-price listings can range from about 1.77 less than low-price listings to about 0.4 more than low-price listings. The issue with no-pooling is that it does not impose a structure on this between-neighborhood variation.

dcoefs <- airbnbs %>% 
    group_by(neighborhood) %>% 
    do(mod = lm(overall_satisfaction ~ pricelev, data = .))
coefs <- dcoef %>% do(data.frame(pricec = coef(.$mod)[2]))
ggplot(coefs, aes(x = pricec)) + geom_histogram()+xlab("Difference in Satisfaction Rating Between High and Low Price Levels Across 24 Neighborhoods")

ggplot(coefs, aes(x = pricec)) + geom_density(fill="steelblue")+xlab("Difference in Satisfaction Rating Between High and Low Price Levels Across 24 Neighborhoods")

Random Intercept Model

With a random effects model, I am now combining the complexity of variation from the no-pooling model with the simplicity of the complete-pooling model (using the parameters of a normal distribution). Here, I am using a random intercept model, which allows the intercept of my regression model to vary freely between neighborhoods, but does not allow the price difference in satisfaction to differ between neighborhoods.


Below we can see that the standard deviation between neighborhoods for low-price listings is about 0.59. Ratings for low-price listings are, on average, 2.93 while ratings for high-price listings are, on average, 0.35 lower.

library(nlme)
m1_lme <- lme(overall_satisfaction ~ pricelev, data = airbnbs, random = ~1|neighborhood, method = "ML")
summary(m1_lme)
Linear mixed-effects model fit by maximum likelihood
 Data: airbnbs 

Random effects:
 Formula: ~1 | neighborhood
        (Intercept) Residual
StdDev:   0.5936869 2.088129

Fixed effects: overall_satisfaction ~ pricelev 
 Correlation: 
         (Intr)
pricelev -0.124

Standardized Within-Group Residuals:
       Min         Q1        Med         Q3        Max 
-1.8772828 -1.2117618  0.4744175  0.7191426  1.7468961 

Number of Observations: 13578
Number of Groups: 24 

Random Slope Model

Using a random slope model, I am now allowing the price difference in satisfaction to vary between neighborhoods.


Below we can see that the satisfaction rating of low-price listings across neighborhoods is 3.02 with a standard deviation of 0.62. Satisfaction ratings for high-price listings across neighborhoods is 0.54 lower, with a standard deviation of 0.45. The intercept and slope has a negative correlation of 0.33 across neighborhoods, which suggests that in neighborhoods where low-price listings have high satisfaction ratings, the difference in ratings between price levels is low, and in neighborhoods where low-price listings have low satisfaction ratings, the difference in ratings between price levels is high.

m2_lme <- lme(overall_satisfaction ~ pricelev, data = airbnbs, random = ~ pricelev|neighborhood, method = "ML")
summary(m2_lme)
Linear mixed-effects model fit by maximum likelihood
 Data: airbnbs 

Random effects:
 Formula: ~pricelev | neighborhood
 Structure: General positive-definite, Log-Cholesky parametrization
            StdDev    Corr  
(Intercept) 0.6159586 (Intr)
pricelev    0.4476372 -0.286
Residual    2.0816310       

Fixed effects: overall_satisfaction ~ pricelev 
 Correlation: 
         (Intr)
pricelev -0.33 

Standardized Within-Group Residuals:
       Min         Q1        Med         Q3        Max 
-1.9273662 -1.1607159  0.4745965  0.7204646  1.7657156 

Number of Observations: 13578
Number of Groups: 24 

Comparing Models

Based on the below AIC results, the random slope model seems to fit the data best. As previously shown, this model suggests that, on average, low-price listings have a satisfaction rating of 3.02 with a standard deviation of .62 between neighborhoods, while high-price listings have a satisfaction rating that is .54 lower across neighborhoods with a standard deviation of .45.

AIC(cpooling, m1_lme, m2_lme)

Intra-Class Correlation:

Is overall satisfaction mainly an individual-level or neighborhood-level thing?

m0_lme <- lme(overall_satisfaction ~ 1, random = ~ 1|neighborhood, data = airbnbs, method = "ML")
summary(m0_lme)
Linear mixed-effects model fit by maximum likelihood
 Data: airbnbs 

Random effects:
 Formula: ~1 | neighborhood
        (Intercept) Residual
StdDev:   0.5817633 2.095359

Fixed effects: overall_satisfaction ~ 1 

Standardized Within-Group Residuals:
       Min         Q1        Med         Q3        Max 
-1.7710411 -1.1962397  0.4412431  0.6839926  1.6267148 

Number of Observations: 13578
Number of Groups: 24 

Intra-class correlation (ICC):
0.5817633/(0.5817633+2.095359)=0.21730919801
About 21.7% of the total variation in overall_satisfaction can be attributed to neighborhood-level influences. The other 78.3% can be attributed to the individual level.


Confidence Intervals:

intervals(m0_lme)
Approximate 95% confidence intervals

 Fixed effects:
               lower     est.    upper
(Intercept) 2.539996 2.782792 3.025588
attr(,"label")
[1] "Fixed effects:"

 Random Effects:
  Level: neighborhood 
                    lower      est.     upper
sd((Intercept)) 0.4242685 0.5817633 0.7977225

 Within-group standard error:
   lower     est.    upper 
2.070563 2.095359 2.120453 

Conclusion

After exploring the satisfaction ratings for Airbnb ratings across 24 neighorhoods, I can conclude that price level does, in fact, matter when it comes to overall satisfaction. Though my ecological analysis showed a positive relationship between price and rating, all other analysese showed a negative relationship, where satisfaction ratings decrease when price level is high. This held true for both complete and partial pooling models; however, partial pooling was shown to be the best model fit, suggesting that what is considered satisfactory does indeed vary by neighborhood. According to the intra-class correlation, about 21.7% of variation in satisfaction can be attributed to neighborhood influences, while the rest can be attributed to individual-level influences.

LS0tCnRpdGxlOiAiU29jIDcxMjogSG9tZXdvcmsgOCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoqSmVubmlmZXIgR2FuZWxlcyoKPGJyLz4qNC83LzE5KgoKI0FpcmJuYiBTYXRpc2ZhY3Rpb246IEhvdyBNdWNoIERvZXMgUHJpY2UgTWF0dGVyPyAoQSBNdWx0aWxldmVsIEFuYWx5c2lzKQoKVGhpcyB3ZWVrJ3MgaG9tZXdvcmsgZXhwbG9yZXMgYW4gW0FpckJOQiBhbmFseXNpcyBMaXNib25dKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vdmZvdWZpa29zL2FpcmJuYi1hbmFseXNpcy1saXNib24pIGRhdHNldCBmb3VuZCBvbiBLYWdnbGUuIEFpcmJuYiBpcyBhbiBvbmxpbmUgbWFya2V0cGxhY2UsIHdoaWNoIGFsbG93cyBwZW9wbGUgdG8gcmVudCBvdXQgdGhlaXIgcHJvcGVydGllcyBvciBzcGFyZSByb29tcyB0byBndWVzdHMuIEl0cyBwb3B1bGFyaXR5IGhhcyBpbmNyZWFzZWQgb3ZlciB0aGUgeWVhcnMgYXMgYSBmaW5hbmNpYWxseS1mcmllbmRseSB3YXkgdG8gc3RheSBvdmVybmlnaHQgaW4gcHJpbWUgbG9jYXRpb25zIHdoaWxlIGFsc28gZ2V0dGluZyBhbiBhdXRoZW50aWNhbGx5IGxvY2FsIHRyYXZlbCBleHBlcmllbmNlLiAKCjxici8+QWlyYm5iIGlzIGtub3duIGZvciBiZWluZyBhIGNoZWFwZXIgYWx0ZXJuYXRpdmUgdG8gbm9ybWFsIGhvdGVsIGFjY29tbW9kYXRpb25zLCBidXQgd2hhdCdzIGNvbnNpZGVyZWQgYSBnb29kIHByaWNlIGNhbiB2YXJ5IGJ5IGxvY2F0aW9uLiBGb3IgdGhpcyByZWFzb24sIEkgd2lsbCBiZSB1c2luZyBtdWx0aWxldmVsIG1vZGVsbGluZyB0byBleHBsb3JlIGhvdyBwcmljZSBhZmZlY3RzIG92ZXJhbGwgQWlyYm5iIHNhdGlzZmFjdGlvbiBhY3Jvc3MgaW5kaXZpZHVhbCBsaXN0aW5ncyBhcyB3ZWxsIGFzIGFjcm9zcyBuZWlnaGJvcmhvb2RzLiBUaGUgZGF0YXNldCBjb250YWlucyBsaXN0aW5nIGFuZCByYXRpbmcgaW5mb3JtYXRpb24gZm9yIDEzLDU3OCBBaXJibmIgYWNjb21tb2RhdGlvbnMgc3Bhbm5pbmcgMjQgbmVpZ2hib3Job29kcyBpbiBMaXNib24sIFBvcnR1Z2FsIGFzIG9mIDIwMTcuIAoKIyMjSW1wb3J0aW5nIHRoZSBEYXRhIGFuZCBFeGFtaW5pbmcgS2V5IFZhcmlhYmxlczoKTXkgZGVwZW5kZW50IHZhcmlhYmxlIChvdmVyYWxsIHNhdGlzZmFjdGlvbikgd2FzIHJhdGVkIG9uIGEgc2NhbGUgZnJvbSAwIHRvIDUuIE15IGluZGVwZW5kZW50IHZhcmlhYmxlIChwcmljZSkgd2FzIHNpbXBsaWZpZWQgaW50byB0d28gbGV2ZWxzIHVzaW5nIG1lZGlhbiBhcyBhIGN1dHRvZmYgcG9pbnQ6IExvdyAoJDcwIG9yIGxvd2VyKSBhbmQgSGlnaCAoR3JlYXRlciB0aGFuICQ3MCkuCjxici8+KipMb3cgUHJpY2UqKj0wCjxici8+KipIaWdoIFByaWNlKio9MQoKYGBge3IgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShyZWFkcikKYWlyYm5iPC1yZWFkX2NzdigiL1VzZXJzL2plbm5pZmVyZ2FuZWxlcy9Eb3dubG9hZHMvYWlyYm5iX2xpc2Jvbl8xNDgwXzIwMTctMDctMjcuY3N2IikKYWlyYm5iJHByaWNlbGV2IDwtIGlmZWxzZShhaXJibmIkcHJpY2UgPiBtZWRpYW4oYWlyYm5iJHByaWNlKSwgMSwgMCkKYWlyYm5iPC1zZWxlY3QoYWlyYm5iLCByb29tX2lkLCBuZWlnaGJvcmhvb2QsIG92ZXJhbGxfc2F0aXNmYWN0aW9uLCBwcmljZSwgcHJpY2VsZXYsIGFjY29tbW9kYXRlcywgYmVkcm9vbXMsIHJldmlld3MpCmFpcmJuYnM8LWFpcmJuYltvcmRlcigtYWlyYm5iJG92ZXJhbGxfc2F0aXNmYWN0aW9uKSxdCmhlYWQoYWlyYm5icykKYGBgCgojI0Vjb2xvZ2ljYWwgQW5hbHlzaXMgKE5laWdoYm9yaG9vZC1MZXZlbCBBbmFseXNpcykKRmlyc3QsIEkgd2lsbCBiZSBjb25kdWN0aW5nIGFuIGVjb2xvZ2ljYWwgcmVncmVzc2lvbiwgd2hpY2ggaXMgYSBuZWlnaGJvcmhvb2QtbGV2ZWwgYW5hbHlzaXMuIFRoZSBiZWxvdyBhbmFseXNpcyBzaG93cyB0aGF0IGF0IHRoZSBuZWlnaGJvcmhvb2QtbGV2ZWwsIHRoZXJlIGlzIGFuIGluc2lnbmlmaWNhbnQgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gcHJpY2UgbGV2ZWwgYW5kIHNhdGlzZmFjdGlvbiByYXRpbmcuIFdlIG1heSBiZSB0ZW1wdGVkIHRvIHNheSB0aGF0IGhpZ2ggcHJpY2VkIGFjY29tbW9kYXRpb25zIGhhdmUgaGlnaGVyIHJhdGluZ3MsIGJ1dCB0aGlzIHdvdWxkIGJlIGFuIGVjb2xvZ2ljYWwgZmFsbGFjeSBzaW5jZSBJIGFtIG5vdCB1c2luZyBpbmRpdmlkdWFsLWxldmVsIGRhdGEgaGVyZS4gCmBgYHtyfQojRmlyc3QsIGdyb3VwaW5nIGJ5IG5laWdoYm9yaG9vZDoKaG9vZDwtYWlyYm5icyAlPiUgCiAgZ3JvdXBfYnkobmVpZ2hib3Job29kKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fcyA9IG1lYW4ob3ZlcmFsbF9zYXRpc2ZhY3Rpb24sIG5hLnJtID0gVFJVRSksIG1lYW5fcCA9IG1lYW4ocHJpY2VsZXYsIG5hLnJtID0gVFJVRSkpCgojRWNvbG9naWNhbCBtb2RlbDoKZWNvcmVnIDwtIGxtKG1lYW5fcyB+IG1lYW5fcCwgZGF0YSA9IGhvb2QpCnN1bW1hcnkoZWNvcmVnKQpgYGAKIyNDb21wbGV0ZS1Qb29saW5nIE1vZGVsIChJbmRpdmlkdWFsLUxldmVsIEFuYWx5c2lzKSAKVXNpbmcgdGhlIGNvbXBsZXRlIHBvb2xpbmcgbWV0aG9kLCBJIGNhbiBzZWUgdGhhdCB0aGVyZSBpcyBhIHNpZ25pZmljYW50ICpuZWdhdGl2ZSogcmVsYXRpb25zaGlwIGJldHdlZW4gcHJpY2UgbGV2ZWwgYW5kIHNhdGlzZmFjdGlvbiByYXRpbmcuIEluIG90aGVyIHdvcmRzLCBoaWdoIHByaWNlcyBkZWNyZWFzZSBzYXRpc2ZhY3Rpb24gYnkgMC4xOS4gSG93ZXZlciwgaGVyZSBJIGFtIGV4cGxvcmluZyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcHJpY2UgbGV2ZWwgYW5kIHNhdGlzZmFjdGlvbiByYXRpbmcgdW5kZXIgdGhlIGFzc3VtcHRpb24gdGhhdCBubyBkaWZmZXJlbmNlIGV4aXN0cyBiZXR3ZWVuIG5laWdoYm9yaG9vZHMuIExpa2UgbXkgZWNvbG9naWNhbCByZWdyZXNzaW9uLCB0aGlzIG1vZGVsIGlzIGFsc28gZmxhd2VkIHNpbmNlIHRoZSB0eXBlIG9mIG5laWdoYm9yaG9vZCBjYW4gYmUgYW4gaW1wb3J0YW50IGRldGVybWluYW50IG9mIHdoYXQgaXMgc2F0aXNmYWN0b3J5IGFuZCB3aGF0IGl0IG5vdC4gCmBgYHtyfQpjcG9vbGluZyA8LSBsbShvdmVyYWxsX3NhdGlzZmFjdGlvbiB+IHByaWNlbGV2LCBkYXRhID0gYWlyYm5icykKc3VtbWFyeShjcG9vbGluZykKYGBgCgojI05vLVBvb2xpbmcgTW9kZWwgKEludGVyY2VwdCkKSGVyZSwgSSBhbSBydW5uaW5nIDI0IGRpZmZlcmVudCByZWdyZXNzaW9uIG1vZGVscyAob25lIHBlciBuZWlnaGJvcmhvb2QpIHVzaW5nIHRoZSBuby1wb29saW5nIG1vZGVsLiBCZWxvdyBhcmUgcGxvdHMgb2YgdGhlIGludGVyY2VwdCBvZiBteSByZWdyZXNzaW9uIGZvciBlYWNoIG5laWdoYm9yaG9vZC4gVGhlIGludGVyY2VwdCByZXByZXNlbnRzIHRoZSBhdmVyYWdlIHNhdGlzZmFjdGlvbiByYXRpbmcgZm9yIGxpc3RpbmdzIHRoYXQgYXJlIGxvdyBwcmljZSAocGljZWxldj0wKS4gSGVyZSwgdGhlIG1vZGUgc2F0aXNmYWN0aW9uIHJhdGluZyBmb3IgbG93LXByaWNlIGxpc3RpbmdzIGlzIGFib3V0IDMsIGJ1dCB2YXJpYXRpb24gZXhpc3RzIHdpdGggcmF0aW5ncyBhcyBoaWdoIGFzIDQgYW5kIGFzIGxvdyBhcyBhYm91dCAxLjMuCmBgYHtyfQpkY29lZmkgPC0gYWlyYm5icyAlPiUgCiAgICBncm91cF9ieShuZWlnaGJvcmhvb2QpICU+JSAKICAgIGRvKG1vZCA9IGxtKG92ZXJhbGxfc2F0aXNmYWN0aW9uIH4gcHJpY2VsZXYsIGRhdGEgPSAuKSkKY29lZmkgPC0gZGNvZWYgJT4lIGRvKGRhdGEuZnJhbWUoaW50YyA9IGNvZWYoLiRtb2QpWzFdKSkKZ2dwbG90KGNvZWZpLCBhZXMoeCA9IGludGMpKSArIGdlb21faGlzdG9ncmFtKCkreGxhYigiU2F0aXNmYWN0aW9uIFJhdGluZyBmb3IgTG93IFByaWNlIEFjcm9zcyAyNCBOZWlnaGJvcmhvb2RzIikKCmBgYAoKYGBge3J9CmdncGxvdChjb2VmaSwgYWVzKHggPSBpbnRjKSkgKyBnZW9tX2RlbnNpdHkoZmlsbD0ic3RlZWxibHVlIikreGxhYigiU2F0aXNmYWN0aW9uIFJhdGluZyBmb3IgTG93IFByaWNlIExldmVsIEFjcm9zcyAyNCBOZWlnaGJvcmhvb2RzIikKYGBgCiMjTm8gUG9vbGluZyBNb2RlbCAoU2xvcGUpCkJlbG93IGFyZSBwbG90cyBvZiB0aGUgc2xvcGUgb2YgbXkgcmVncmVzc2lvbiBmb3IgZWFjaCBuZWlnaGJvcmhvb2QgKGluIG90aGVyIHdvcmRzLCB0aGUgZGlmZmVyZW5jZSBpbiBzYXRpc2ZhY3Rpb24gYmV0d2VlbiBwcmljZSBsZXZlbHMgYWNyb3NzIG5laWdoYm9yaG9vZHMpLiBUaGUgbW9kZSBkaWZmZXJlbmNlIGlzIGFib3V0IC0wLjUsIHdoaWNoIHN1Z2dlc3RzIHRoYXQgc2F0aWZhY3Rpb24gcmF0aW5ncyBhcmUsIG9uIGF2ZXJhZ2UsIDAuNSBsb3dlciBmb3IgaGlnaC1wcmljZWQgYWlyYm5iIGxpc3RpbmdzIHRoYW4gZm9yIGxvdy1wcmljZWQgbGlzdGluZ3MuIEhvd2V2ZXIsIHRoZXJlIGlzIHZhcmlhdGlvbiBpbiB0aGlzIGRpc3RyaWJ1dGlvbiBhcyB3ZWxsLiBTYXRpc2ZhY3Rpb24gcmF0aW5nIGZvciBoaWdoLXByaWNlIGxpc3RpbmdzIGNhbiByYW5nZSBmcm9tIGFib3V0IDEuNzcgbGVzcyB0aGFuIGxvdy1wcmljZSBsaXN0aW5ncyB0byBhYm91dCAwLjQgbW9yZSB0aGFuIGxvdy1wcmljZSBsaXN0aW5ncy4gVGhlIGlzc3VlIHdpdGggbm8tcG9vbGluZyBpcyB0aGF0IGl0IGRvZXMgbm90IGltcG9zZSBhIHN0cnVjdHVyZSBvbiB0aGlzIGJldHdlZW4tbmVpZ2hib3Job29kIHZhcmlhdGlvbi4KYGBge3J9CmRjb2VmcyA8LSBhaXJibmJzICU+JSAKICAgIGdyb3VwX2J5KG5laWdoYm9yaG9vZCkgJT4lIAogICAgZG8obW9kID0gbG0ob3ZlcmFsbF9zYXRpc2ZhY3Rpb24gfiBwcmljZWxldiwgZGF0YSA9IC4pKQpjb2VmcyA8LSBkY29lZiAlPiUgZG8oZGF0YS5mcmFtZShwcmljZWMgPSBjb2VmKC4kbW9kKVsyXSkpCmdncGxvdChjb2VmcywgYWVzKHggPSBwcmljZWMpKSArIGdlb21faGlzdG9ncmFtKCkreGxhYigiRGlmZmVyZW5jZSBpbiBTYXRpc2ZhY3Rpb24gUmF0aW5nIEJldHdlZW4gSGlnaCBhbmQgTG93IFByaWNlIExldmVscyBBY3Jvc3MgMjQgTmVpZ2hib3Job29kcyIpCmBgYAoKYGBge3Igd2FybmluZz1GQUxTRX0KZ2dwbG90KGNvZWZzLCBhZXMoeCA9IHByaWNlYykpICsgZ2VvbV9kZW5zaXR5KGZpbGw9InN0ZWVsYmx1ZSIpK3hsYWIoIkRpZmZlcmVuY2UgaW4gU2F0aXNmYWN0aW9uIFJhdGluZyBCZXR3ZWVuIEhpZ2ggYW5kIExvdyBQcmljZSBMZXZlbHMgQWNyb3NzIDI0IE5laWdoYm9yaG9vZHMiKQpgYGAKIyNSYW5kb20gSW50ZXJjZXB0IE1vZGVsCldpdGggYSByYW5kb20gZWZmZWN0cyBtb2RlbCwgSSBhbSBub3cgY29tYmluaW5nIHRoZSBjb21wbGV4aXR5IG9mIHZhcmlhdGlvbiBmcm9tIHRoZSBuby1wb29saW5nIG1vZGVsIHdpdGggdGhlIHNpbXBsaWNpdHkgb2YgdGhlIGNvbXBsZXRlLXBvb2xpbmcgbW9kZWwgKHVzaW5nIHRoZSBwYXJhbWV0ZXJzIG9mIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbikuIEhlcmUsIEkgYW0gdXNpbmcgYSByYW5kb20gaW50ZXJjZXB0IG1vZGVsLCB3aGljaCBhbGxvd3MgdGhlIGludGVyY2VwdCBvZiBteSByZWdyZXNzaW9uIG1vZGVsIHRvIHZhcnkgZnJlZWx5IGJldHdlZW4gbmVpZ2hib3Job29kcywgYnV0IGRvZXMgbm90IGFsbG93IHRoZSBwcmljZSBkaWZmZXJlbmNlIGluIHNhdGlzZmFjdGlvbiB0byBkaWZmZXIgYmV0d2VlbiBuZWlnaGJvcmhvb2RzLgoKPGJyLz4gQmVsb3cgd2UgY2FuIHNlZSB0aGF0IHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gYmV0d2VlbiBuZWlnaGJvcmhvb2RzIGZvciBsb3ctcHJpY2UgbGlzdGluZ3MgaXMgYWJvdXQgMC41OS4gUmF0aW5ncyBmb3IgbG93LXByaWNlIGxpc3RpbmdzIGFyZSwgb24gYXZlcmFnZSwgMi45MyB3aGlsZSByYXRpbmdzIGZvciBoaWdoLXByaWNlIGxpc3RpbmdzIGFyZSwgb24gYXZlcmFnZSwgMC4zNSBsb3dlci4gCmBgYHtyfQpsaWJyYXJ5KG5sbWUpCm0xX2xtZSA8LSBsbWUob3ZlcmFsbF9zYXRpc2ZhY3Rpb24gfiBwcmljZWxldiwgZGF0YSA9IGFpcmJuYnMsIHJhbmRvbSA9IH4xfG5laWdoYm9yaG9vZCwgbWV0aG9kID0gIk1MIikKc3VtbWFyeShtMV9sbWUpCmBgYAojI1JhbmRvbSBTbG9wZSBNb2RlbApVc2luZyBhIHJhbmRvbSBzbG9wZSBtb2RlbCwgSSBhbSBub3cgYWxsb3dpbmcgdGhlIHByaWNlIGRpZmZlcmVuY2UgaW4gc2F0aXNmYWN0aW9uIHRvIHZhcnkgYmV0d2VlbiBuZWlnaGJvcmhvb2RzLiAKCjxici8+QmVsb3cgd2UgY2FuIHNlZSB0aGF0IHRoZSBzYXRpc2ZhY3Rpb24gcmF0aW5nIG9mIGxvdy1wcmljZSBsaXN0aW5ncyBhY3Jvc3MgbmVpZ2hib3Job29kcyBpcyAzLjAyIHdpdGggYSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgMC42Mi4gU2F0aXNmYWN0aW9uIHJhdGluZ3MgZm9yIGhpZ2gtcHJpY2UgbGlzdGluZ3MgYWNyb3NzIG5laWdoYm9yaG9vZHMgaXMgMC41NCBsb3dlciwgd2l0aCBhIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAwLjQ1LiBUaGUgaW50ZXJjZXB0IGFuZCBzbG9wZSBoYXMgYSBuZWdhdGl2ZSBjb3JyZWxhdGlvbiBvZiAwLjMzICBhY3Jvc3MgbmVpZ2hib3Job29kcywgd2hpY2ggc3VnZ2VzdHMgdGhhdCBpbiBuZWlnaGJvcmhvb2RzIHdoZXJlIGxvdy1wcmljZSBsaXN0aW5ncyBoYXZlIGhpZ2ggc2F0aXNmYWN0aW9uIHJhdGluZ3MsIHRoZSBkaWZmZXJlbmNlIGluIHJhdGluZ3MgYmV0d2VlbiBwcmljZSBsZXZlbHMgaXMgbG93LCBhbmQgaW4gbmVpZ2hib3Job29kcyB3aGVyZSBsb3ctcHJpY2UgbGlzdGluZ3MgaGF2ZSBsb3cgc2F0aXNmYWN0aW9uIHJhdGluZ3MsIHRoZSBkaWZmZXJlbmNlIGluIHJhdGluZ3MgYmV0d2VlbiBwcmljZSBsZXZlbHMgaXMgaGlnaC4KYGBge3J9Cm0yX2xtZSA8LSBsbWUob3ZlcmFsbF9zYXRpc2ZhY3Rpb24gfiBwcmljZWxldiwgZGF0YSA9IGFpcmJuYnMsIHJhbmRvbSA9IH4gcHJpY2VsZXZ8bmVpZ2hib3Job29kLCBtZXRob2QgPSAiTUwiKQpzdW1tYXJ5KG0yX2xtZSkKYGBgCiMjQ29tcGFyaW5nIE1vZGVscwpCYXNlZCBvbiB0aGUgYmVsb3cgQUlDIHJlc3VsdHMsIHRoZSByYW5kb20gc2xvcGUgbW9kZWwgc2VlbXMgdG8gZml0IHRoZSBkYXRhIGJlc3QuIEFzIHByZXZpb3VzbHkgc2hvd24sIHRoaXMgbW9kZWwgc3VnZ2VzdHMgdGhhdCwgb24gYXZlcmFnZSwgbG93LXByaWNlIGxpc3RpbmdzIGhhdmUgYSBzYXRpc2ZhY3Rpb24gcmF0aW5nIG9mIDMuMDIgd2l0aCBhIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAuNjIgYmV0d2VlbiBuZWlnaGJvcmhvb2RzLCB3aGlsZSBoaWdoLXByaWNlIGxpc3RpbmdzIGhhdmUgYSBzYXRpc2ZhY3Rpb24gcmF0aW5nIHRoYXQgaXMgLjU0IGxvd2VyIGFjcm9zcyBuZWlnaGJvcmhvb2RzIHdpdGggYSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgLjQ1LgpgYGB7cn0KQUlDKGNwb29saW5nLCBtMV9sbWUsIG0yX2xtZSkKYGBgCgojI0ludHJhLUNsYXNzIENvcnJlbGF0aW9uOiAKIyMjSXMgb3ZlcmFsbCBzYXRpc2ZhY3Rpb24gbWFpbmx5IGFuIGluZGl2aWR1YWwtbGV2ZWwgb3IgbmVpZ2hib3Job29kLWxldmVsIHRoaW5nPwpgYGB7cn0KbTBfbG1lIDwtIGxtZShvdmVyYWxsX3NhdGlzZmFjdGlvbiB+IDEsIHJhbmRvbSA9IH4gMXxuZWlnaGJvcmhvb2QsIGRhdGEgPSBhaXJibmJzLCBtZXRob2QgPSAiTUwiKQpzdW1tYXJ5KG0wX2xtZSkKYGBgCioqSW50cmEtY2xhc3MgY29ycmVsYXRpb24gKElDQyk6KioKPGJyLz4gMC41ODE3NjMzLygwLjU4MTc2MzMrMi4wOTUzNTkpPTAuMjE3MzA5MTk4MDEKPGJyLz5BYm91dCAyMS43JSBvZiB0aGUgdG90YWwgdmFyaWF0aW9uIGluIG92ZXJhbGxfc2F0aXNmYWN0aW9uIGNhbiBiZSBhdHRyaWJ1dGVkIHRvIG5laWdoYm9yaG9vZC1sZXZlbCBpbmZsdWVuY2VzLiBUaGUgb3RoZXIgNzguMyUgY2FuIGJlIGF0dHJpYnV0ZWQgdG8gdGhlIGluZGl2aWR1YWwgbGV2ZWwuIAoKPGJyLz4qKkNvbmZpZGVuY2UgSW50ZXJ2YWxzOioqCmBgYHtyfQppbnRlcnZhbHMobTBfbG1lKQpgYGAKI0NvbmNsdXNpb24KQWZ0ZXIgZXhwbG9yaW5nIHRoZSBzYXRpc2ZhY3Rpb24gcmF0aW5ncyBmb3IgQWlyYm5iIHJhdGluZ3MgYWNyb3NzIDI0IG5laWdob3Job29kcywgSSBjYW4gY29uY2x1ZGUgdGhhdCBwcmljZSBsZXZlbCBkb2VzLCBpbiBmYWN0LCBtYXR0ZXIgd2hlbiBpdCBjb21lcyB0byBvdmVyYWxsIHNhdGlzZmFjdGlvbi4gVGhvdWdoIG15IGVjb2xvZ2ljYWwgYW5hbHlzaXMgc2hvd2VkIGEgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gcHJpY2UgYW5kIHJhdGluZywgYWxsIG90aGVyIGFuYWx5c2VzZSBzaG93ZWQgYSBuZWdhdGl2ZSByZWxhdGlvbnNoaXAsIHdoZXJlIHNhdGlzZmFjdGlvbiByYXRpbmdzIGRlY3JlYXNlIHdoZW4gcHJpY2UgbGV2ZWwgaXMgaGlnaC4gVGhpcyBoZWxkIHRydWUgZm9yIGJvdGggY29tcGxldGUgYW5kIHBhcnRpYWwgcG9vbGluZyBtb2RlbHM7IGhvd2V2ZXIsIHBhcnRpYWwgcG9vbGluZyB3YXMgc2hvd24gdG8gYmUgdGhlIGJlc3QgbW9kZWwgZml0LCBzdWdnZXN0aW5nIHRoYXQgd2hhdCBpcyBjb25zaWRlcmVkIHNhdGlzZmFjdG9yeSBkb2VzIGluZGVlZCB2YXJ5IGJ5IG5laWdoYm9yaG9vZC4gQWNjb3JkaW5nIHRvIHRoZSBpbnRyYS1jbGFzcyBjb3JyZWxhdGlvbiwgYWJvdXQgMjEuNyUgb2YgdmFyaWF0aW9uIGluIHNhdGlzZmFjdGlvbiBjYW4gYmUgYXR0cmlidXRlZCB0byBuZWlnaGJvcmhvb2QgaW5mbHVlbmNlcywgd2hpbGUgdGhlIHJlc3QgY2FuIGJlIGF0dHJpYnV0ZWQgdG8gaW5kaXZpZHVhbC1sZXZlbCBpbmZsdWVuY2VzLiA=