1. Research question

1.1 Research Question:

Is there a difference in the price of unfurnished, semi-furnished and furnished houses?

1.2 Variables that need to be collected

  • price
  • furnishing status

1.3 Research Hypothesis:

The better furnished a house is, the higher the price.

2. Data

2.1 Data Import

# Load the dataset
housing <- read.table("Housing.csv",
                      header = TRUE,
                      sep = ",")

# Convert character columns to factors
housing$mainroad <- factor(housing$mainroad,
                           levels = c("no", "yes"),
                           labels = c("no", "yes"))
housing$guestroom <- factor(housing$guestroom,
                           levels = c("no", "yes"),
                           labels = c("no", "yes"))
housing$basement <- factor(housing$basement,
                           levels = c("no", "yes"),
                           labels = c("no", "yes"))
housing$hotwaterheating <- factor(housing$hotwaterheating,
                           levels = c("no", "yes"),
                           labels = c("no", "yes"))
housing$airconditioning <- factor(housing$airconditioning,
                           levels = c("no", "yes"),
                           labels = c("no", "yes"))
housing$prefarea <- factor(housing$prefarea,
                           levels = c("no", "yes"),
                           labels = c("no", "yes"))
housing$furnishingstatus <- factor(housing$furnishingstatus,
                           levels = c("unfurnished", "semi-furnished", "furnished"),
                           labels = c("unfurnished", "semi-furnished", "furnished"))

# Explore the dataset
head(housing)
str(housing)
'data.frame':   545 obs. of  13 variables:
 $ price           : int  13300000 12250000 12250000 12215000 11410000 10850000 10150000 10150000 9870000 9800000 ...
 $ area            : int  7420 8960 9960 7500 7420 7500 8580 16200 8100 5750 ...
 $ bedrooms        : int  4 4 3 4 4 3 4 5 4 3 ...
 $ bathrooms       : int  2 4 2 2 1 3 3 3 1 2 ...
 $ stories         : int  3 4 2 2 2 1 4 2 2 4 ...
 $ mainroad        : Factor w/ 2 levels "no","yes": 2 2 2 2 2 2 2 2 2 2 ...
 $ guestroom       : Factor w/ 2 levels "no","yes": 1 1 1 1 2 1 1 1 2 2 ...
 $ basement        : Factor w/ 2 levels "no","yes": 1 1 2 2 2 2 1 1 2 1 ...
 $ hotwaterheating : Factor w/ 2 levels "no","yes": 1 1 1 1 1 1 1 1 1 1 ...
 $ airconditioning : Factor w/ 2 levels "no","yes": 2 2 1 2 2 2 2 1 2 2 ...
 $ parking         : int  2 3 2 3 2 2 2 0 2 1 ...
 $ prefarea        : Factor w/ 2 levels "no","yes": 2 1 2 2 1 2 2 1 2 2 ...
 $ furnishingstatus: Factor w/ 3 levels "unfurnished",..: 3 3 2 3 3 2 2 1 3 1 ...

13 variables (6 numerical, 7 categorical):

  1. price: price of the house in USD, numerical (ratio)
  2. area: are of the house in sqft, numerical (ratio)
  3. bedrooms: number of bedrooms, numerical (ratio)
  4. bathrooms: number of bathrooms, numerical (ratio)
  5. stories: number of stories, numerical (ratio)
  6. mainroad: indicator if the house is located at a mainroad or not, categorical (nominal) with categories “yes” and “no”
  7. guestroom: indicator if the house features a guestroom or not, categorical (nominal) with categories “yes” and “no”
  8. basement: indicator if the house has a basement or not, categorical (nominal) with categories “yes” and “no”
  9. hotwaterheating: indicator if the house comes with heating, categorical (nominal) with categories “yes” and “no”
  10. airconditioning: indicator if the house has airconditioning, categorical (nominal) with categories “yes” and “no”
  11. parking: number of parking spots that come iwth the house, numerical (ratio)
  12. prefarea: indicator if the house is located in a prefferable area, categorical (nominal) with categories “yes” and “no”
  13. furnishingstatus: indicator if the house is furnished, semi-furnished, or unfurnished, categorical (ordinal)

I will use the variables, “price” and “furnishingstatus” to see if the furnishing status of a house has a significant effect on its price.

2.2 Definition of the unit of observation and the sample size

  • Unit: 1 house
  • Unit of observation: furnishing status
  • Variable of observation: price
  • Sample size: 545 houses (178 unfurnished, 227 semi-furnished, 140 furnished)

2.3 Dataset Source:

“Housing Prices Dataset” dataset sourced from https://www.kaggle.com/datasets/yasserh/housing-prices-dataset

2.4 Basic descriptive statistics for the variables of interest:

# Explore the dataset
summary(housing)
     price               area          bedrooms       bathrooms        stories      mainroad  guestroom basement 
 Min.   : 1750000   Min.   : 1650   Min.   :1.000   Min.   :1.000   Min.   :1.000   no : 77   no :448   no :354  
 1st Qu.: 3430000   1st Qu.: 3600   1st Qu.:2.000   1st Qu.:1.000   1st Qu.:1.000   yes:468   yes: 97   yes:191  
 Median : 4340000   Median : 4600   Median :3.000   Median :1.000   Median :2.000                                
 Mean   : 4766729   Mean   : 5151   Mean   :2.965   Mean   :1.286   Mean   :1.806                                
 3rd Qu.: 5740000   3rd Qu.: 6360   3rd Qu.:3.000   3rd Qu.:2.000   3rd Qu.:2.000                                
 Max.   :13300000   Max.   :16200   Max.   :6.000   Max.   :4.000   Max.   :4.000                                
 hotwaterheating airconditioning    parking       prefarea        furnishingstatus
 no :520         no :373         Min.   :0.0000   no :417   unfurnished   :178    
 yes: 25         yes:172         1st Qu.:0.0000   yes:128   semi-furnished:227    
                                 Median :0.0000             furnished     :140    
                                 Mean   :0.6936                                   
                                 3rd Qu.:1.0000                                   
                                 Max.   :3.0000                                   
describe(housing)
describeBy(housing$price, housing$furnishingstatus)

 Descriptive statistics by group 
group: unfurnished
------------------------------------------------------------------------------------------ 
group: semi-furnished
------------------------------------------------------------------------------------------ 
group: furnished

General:

  • price: 545 values ranging from 1.75M USD to 13.30M USD and thus a range of 11.55M USD with a median of 4.34M USD and a mean of ~4.77M USD
  • furnishingstatus: 545 values split into 3 categories with 178 in unfurnished, 227 in semi-furnished, and 140 in furnished with a median of 2, i.e. semi-furnished

Price grouped by furnishing status:

  • unfurnished: 178 values ranging from 1.75M USD to 10.15M USD and thus a range of 8.40M USD with a median of 3.43M USD and a mean of ~4.01M USD
  • semi-furnished: 227 values ranging from ~1.77M USD to 12.25M USD and thus a range of ~10.48M USD with a median of ~4.59M USD and a mean of ~4.91M USD
  • furnished: 140 values ranging from 1.75M USD to 13.30M USD and thus a range of 11.55M USD with a median of ~5.08M USD and a mean of ~5.5M USD

Although the lowest price doesn’t really change with a better furnishing status, we can see that the highest price does which is also reflected in an increasing median and mean price.

# Plot prices by furnishing status
ggboxplot(housing,
          x = "furnishingstatus",
          y = "price",
          xlab = "Furnishing Status",
          ylab = "Price")

The boxplot again confirms the previous observation that the median price seems to go up with a better furnishing status.

3. Analysis

3.1 Statistical test choice:

I will need the One-way ANOVA or alternatively the Kruskal-Wallis Rank Sum Test since my hypothesis is concerned with the difference between the house prices from three populations from independent samples, i.e. the price of unfurnished, the price of semi-furnished and the price of furnished houses.

3.2 Evaluation of all assumptions for the One-way ANOVA:

Analyzed variable is numeric.

Yes, the variable “price” is numeric.

The data must come from independent populations:

Yes, the data for the different furnishing status are independent populations.

Normality:

# Test normality in both populations
housing %>%
  group_by(furnishingstatus) %>%
  shapiro_test(price)
NA

We reject H_0, i.e. that the distribution of the price is normal for every furnishing status at p < 0.001 and accept H_1, i.e. that the distribution of the price is NOT normal for every furnishing status.

Homoscedasticity:

# Test if the variance of the price is the same within all groups
leveneTest(housing$price, group = housing$furnishingstatus)
Levene's Test for Homogeneity of Variance (center = median)
       Df F value   Pr(>F)    
group   2  7.4278 0.000657 ***
      542                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

We reject H_0, i.e. that the population variances are the same and accept H_1 that the population variances are NOT the same.

3.3 Wilcoxon Rank Sum Test:

Since both the normality and the homoscedasticity assumptions needed for the One-way ANOVA do not hold, I will continue by using the alternative non-parametric statistical test, the Kruskal-Wallis Rank Sum Test.

  • H_0: All distribution locations of house prices are the same for every furnishing status.
  • H_1: At least one distribution location of house prices is NOT the same the other furnishing status.
# Test the hypothesis that there is no significant difference in the median price between the furnishing status
kruskal.test(price ~ furnishingstatus,
             data = housing)

    Kruskal-Wallis rank sum test

data:  price by furnishingstatus
Kruskal-Wallis chi-squared = 69.583, df = 2, p-value = 7.767e-16

We reject H_0 at p < 0.0001 and accept H_1 that at least one distribution location of house prices is NOT the same the other furnishing status.

# Determine the effect size
kruskal_effsize(price ~ furnishingstatus,
             data = housing)
NA

According to the effect size ranges from Field, 2013, the effect size is moderate.

4. Conclusion:

# Plot all results
pwc <- housing %>%
  wilcox_test(price ~ furnishingstatus,
              paired = FALSE,
              p.adjust.method = "bonferroni")

Kruskal_results <- kruskal_test(price ~ furnishingstatus,
                                data = housing)

pwc <- pwc %>%
       add_y_position(fun = "max", step.increase = 0.20)

ggboxplot(housing, x = "furnishingstatus", y = "price", add = "point") +
  stat_pvalue_manual(pwc, hide.ns = FALSE) +
  stat_summary(fun = median, geom = "point", shape = 16, size = 4,
               aes(group = furnishingstatus), color = "darkred",
               position = position_dodge(width = 0.8)) +
  stat_summary(fun = median, color = "darkred",
               position = position_dodge(width = 0.8),
               geom = "text", vjust = -0.5, hjust = -1,
               aes(label = round(after_stat(y), digits = 2), group = furnishingstatus)) +
  labs(subtitle = get_test_label(Kruskal_results, detailed = TRUE),
       caption = get_pwc_label(pwc))

We found that the distribution of house prices differs for at least one of the furnishing status (𝜒2 = 69.58, 𝑝 < 0.0001), the effect size was moderate (𝜂2 = 0.125). Post-Hoc tests revealed differences for two furnishing status (𝑝 < 0.0001), with the exception of semi-furnished vs. furnished houses.

LS0tDQp0aXRsZTogIjU5NDNfQXBwbGllZERhdGFBbmFseXNpc0luQnVzaW5lc3NXaXRoUl9IVzIiDQphdXRob3I6ICJNYXJrdXMgV2Vpc3MiDQpkYXRlOiAiMjAyNC0wNC0xNiINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQpgYGB7ciBlY2hvID0gRiwgbWVzc2FnZSA9IEYsIGluY2x1ZGUgPSBGfQ0Kb3B0aW9ucyh0aW55dGV4LnZlcmJvc2UgPSBUUlVFKQ0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpOyBsaWJyYXJ5KCJrbml0ciIpDQppZiAoIXJlcXVpcmUoInN0YXJnYXplciIpKSBpbnN0YWxsLnBhY2thZ2VzKCJzdGFyZ2F6ZXIiKTsgbGlicmFyeSgic3RhcmdhemVyIikNCmlmICghcmVxdWlyZSgic3RyaW5nciIpKSBpbnN0YWxsLnBhY2thZ2VzKCJzdHJpbmdyIik7IGxpYnJhcnkoInN0cmluZ3IiKQ0KaWYgKCFyZXF1aXJlKCJkcGx5ciIpKSBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpOyBsaWJyYXJ5KCJkcGx5ciIpDQppZiAoIXJlcXVpcmUoInJlYWR4bCIpKSBpbnN0YWxsLnBhY2thZ2VzKCJyZWFkeGwiKTsgbGlicmFyeSgicmVhZHhsIikNCmlmICghcmVxdWlyZSgibHVicmlkYXRlIikpIGluc3RhbGwucGFja2FnZXMoImx1YnJpZGF0ZSIpOyBsaWJyYXJ5KCJsdWJyaWRhdGUiKQ0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5Iik7IGxpYnJhcnkoInBsb3RseSIpDQppZiAoIXJlcXVpcmUoImdncGxvdDIiKSkgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpOyBsaWJyYXJ5KCJnZ3Bsb3QyIikNCmlmICghcmVxdWlyZSgiZ2dwdWJyIikpIGluc3RhbGwucGFja2FnZXMoImdncHViciIpOyBsaWJyYXJ5KCJnZ3B1YnIiKQ0KaWYgKCFyZXF1aXJlKCJyc3RhdGl4IikpIGluc3RhbGwucGFja2FnZXMoInJzdGF0aXgiKTsgbGlicmFyeSgicnN0YXRpeCIpDQppZiAoIXJlcXVpcmUoInBzeWNoIikpIGluc3RhbGwucGFja2FnZXMoInBzeWNoIik7IGxpYnJhcnkoInBzeWNoIikNCmlmICghcmVxdWlyZSgicGFzdGVjcyIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYXN0ZWNzIik7IGxpYnJhcnkoInBhc3RlY3MiKQ0KaWYgKCFyZXF1aXJlKCJlZmZlY3RzaXplIikpIGluc3RhbGwucGFja2FnZXMoImVmZmVjdHNpemUiKTsgbGlicmFyeSgiZWZmZWN0c2l6ZSIpDQppZiAoIXJlcXVpcmUoImNhciIpKSBpbnN0YWxsLnBhY2thZ2VzKCJjYXIiKTsgbGlicmFyeSgiY2FyIikNCg0KIyBjbGVhbmluZyB0aGUgd29ya2luZyBlbnZpcm9ubWVudA0Kcm0obGlzdCA9IGxzKCkpDQojIHNldHRpbmcgc2VlZCBmb3IgcmVwcm9kdWNpYmlsaXR5DQpzZXQuc2VlZCg2OSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlID0gRiwgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDQpDQoNCmBgYA0KDQoNCiMgMS4gUmVzZWFyY2ggcXVlc3Rpb24NCg0KIyMgMS4xIFJlc2VhcmNoIFF1ZXN0aW9uOg0KDQpJcyB0aGVyZSBhIGRpZmZlcmVuY2UgaW4gdGhlIHByaWNlIG9mIHVuZnVybmlzaGVkLCBzZW1pLWZ1cm5pc2hlZCBhbmQgZnVybmlzaGVkIGhvdXNlcz8NCg0KIyMgMS4yIFZhcmlhYmxlcyB0aGF0IG5lZWQgdG8gYmUgY29sbGVjdGVkDQoNCi0gcHJpY2UNCi0gZnVybmlzaGluZyBzdGF0dXMNCg0KIyMgMS4zIFJlc2VhcmNoIEh5cG90aGVzaXM6DQoNClRoZSBiZXR0ZXIgZnVybmlzaGVkIGEgaG91c2UgaXMsIHRoZSBoaWdoZXIgdGhlIHByaWNlLg0KDQojIDIuIERhdGENCg0KIyMgMi4xIERhdGEgSW1wb3J0DQoNCmBgYHtyIG1lc3NhZ2UgPSBGfQ0KIyBMb2FkIHRoZSBkYXRhc2V0DQpob3VzaW5nIDwtIHJlYWQudGFibGUoIkhvdXNpbmcuY3N2IiwNCiAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICIsIikNCg0KIyBDb252ZXJ0IGNoYXJhY3RlciBjb2x1bW5zIHRvIGZhY3RvcnMNCmhvdXNpbmckbWFpbnJvYWQgPC0gZmFjdG9yKGhvdXNpbmckbWFpbnJvYWQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJubyIsICJ5ZXMiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIm5vIiwgInllcyIpKQ0KaG91c2luZyRndWVzdHJvb20gPC0gZmFjdG9yKGhvdXNpbmckZ3Vlc3Ryb29tLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygibm8iLCAieWVzIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJubyIsICJ5ZXMiKSkNCmhvdXNpbmckYmFzZW1lbnQgPC0gZmFjdG9yKGhvdXNpbmckYmFzZW1lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJubyIsICJ5ZXMiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIm5vIiwgInllcyIpKQ0KaG91c2luZyRob3R3YXRlcmhlYXRpbmcgPC0gZmFjdG9yKGhvdXNpbmckaG90d2F0ZXJoZWF0aW5nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygibm8iLCAieWVzIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJubyIsICJ5ZXMiKSkNCmhvdXNpbmckYWlyY29uZGl0aW9uaW5nIDwtIGZhY3Rvcihob3VzaW5nJGFpcmNvbmRpdGlvbmluZywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIm5vIiwgInllcyIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygibm8iLCAieWVzIikpDQpob3VzaW5nJHByZWZhcmVhIDwtIGZhY3Rvcihob3VzaW5nJHByZWZhcmVhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygibm8iLCAieWVzIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJubyIsICJ5ZXMiKSkNCmhvdXNpbmckZnVybmlzaGluZ3N0YXR1cyA8LSBmYWN0b3IoaG91c2luZyRmdXJuaXNoaW5nc3RhdHVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygidW5mdXJuaXNoZWQiLCAic2VtaS1mdXJuaXNoZWQiLCAiZnVybmlzaGVkIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJ1bmZ1cm5pc2hlZCIsICJzZW1pLWZ1cm5pc2hlZCIsICJmdXJuaXNoZWQiKSkNCg0KIyBFeHBsb3JlIHRoZSBkYXRhc2V0DQpoZWFkKGhvdXNpbmcpDQpzdHIoaG91c2luZykNCg0KYGBgDQoNCiMjIyAxMyB2YXJpYWJsZXMgKDYgbnVtZXJpY2FsLCA3IGNhdGVnb3JpY2FsKToNCg0KICAxLiBwcmljZTogcHJpY2Ugb2YgdGhlIGhvdXNlIGluIFVTRCwgbnVtZXJpY2FsIChyYXRpbykNCiAgMi4gYXJlYTogYXJlIG9mIHRoZSBob3VzZSBpbiBzcWZ0LCBudW1lcmljYWwgKHJhdGlvKQ0KICAzLiBiZWRyb29tczogbnVtYmVyIG9mIGJlZHJvb21zLCBudW1lcmljYWwgKHJhdGlvKQ0KICA0LiBiYXRocm9vbXM6IG51bWJlciBvZiBiYXRocm9vbXMsIG51bWVyaWNhbCAocmF0aW8pDQogIDUuIHN0b3JpZXM6IG51bWJlciBvZiBzdG9yaWVzLCBudW1lcmljYWwgKHJhdGlvKQ0KICA2LiBtYWlucm9hZDogaW5kaWNhdG9yIGlmIHRoZSBob3VzZSBpcyBsb2NhdGVkIGF0IGEgbWFpbnJvYWQgb3Igbm90LCBjYXRlZ29yaWNhbCAobm9taW5hbCkgd2l0aCBjYXRlZ29yaWVzICJ5ZXMiIGFuZCAibm8iDQogIDcuIGd1ZXN0cm9vbTogaW5kaWNhdG9yIGlmIHRoZSBob3VzZSBmZWF0dXJlcyBhIGd1ZXN0cm9vbSBvciBub3QsIGNhdGVnb3JpY2FsIChub21pbmFsKSB3aXRoIGNhdGVnb3JpZXMgInllcyIgYW5kICJubyINCiAgOC4gYmFzZW1lbnQ6IGluZGljYXRvciBpZiB0aGUgaG91c2UgaGFzIGEgYmFzZW1lbnQgb3Igbm90LCBjYXRlZ29yaWNhbCAobm9taW5hbCkgd2l0aCBjYXRlZ29yaWVzICJ5ZXMiIGFuZCAibm8iDQogIDkuIGhvdHdhdGVyaGVhdGluZzogaW5kaWNhdG9yIGlmIHRoZSBob3VzZSBjb21lcyB3aXRoIGhlYXRpbmcsIGNhdGVnb3JpY2FsIChub21pbmFsKSB3aXRoIGNhdGVnb3JpZXMgInllcyIgYW5kICJubyINCiAgMTAuIGFpcmNvbmRpdGlvbmluZzogaW5kaWNhdG9yIGlmIHRoZSBob3VzZSBoYXMgYWlyY29uZGl0aW9uaW5nLCBjYXRlZ29yaWNhbCAobm9taW5hbCkgd2l0aCBjYXRlZ29yaWVzICJ5ZXMiIGFuZCAibm8iDQogIDExLiBwYXJraW5nOiBudW1iZXIgb2YgcGFya2luZyBzcG90cyB0aGF0IGNvbWUgaXd0aCB0aGUgaG91c2UsIG51bWVyaWNhbCAocmF0aW8pDQogIDEyLiBwcmVmYXJlYTogaW5kaWNhdG9yIGlmIHRoZSBob3VzZSBpcyBsb2NhdGVkIGluIGEgcHJlZmZlcmFibGUgYXJlYSwgY2F0ZWdvcmljYWwgKG5vbWluYWwpIHdpdGggY2F0ZWdvcmllcyAieWVzIiBhbmQgIm5vIg0KICAxMy4gZnVybmlzaGluZ3N0YXR1czogaW5kaWNhdG9yIGlmIHRoZSBob3VzZSBpcyBmdXJuaXNoZWQsIHNlbWktZnVybmlzaGVkLCBvciB1bmZ1cm5pc2hlZCwgY2F0ZWdvcmljYWwgKG9yZGluYWwpDQoNCkkgd2lsbCB1c2UgdGhlIHZhcmlhYmxlcywgInByaWNlIiBhbmQgImZ1cm5pc2hpbmdzdGF0dXMiIHRvIHNlZSBpZiB0aGUgZnVybmlzaGluZyBzdGF0dXMgb2YgYSBob3VzZSBoYXMgYSBzaWduaWZpY2FudCBlZmZlY3Qgb24gaXRzIHByaWNlLg0KDQojIyAyLjIgRGVmaW5pdGlvbiBvZiB0aGUgdW5pdCBvZiBvYnNlcnZhdGlvbiBhbmQgdGhlIHNhbXBsZSBzaXplDQoNCi0gVW5pdDogMSBob3VzZQ0KLSBVbml0IG9mIG9ic2VydmF0aW9uOiBmdXJuaXNoaW5nIHN0YXR1cw0KLSBWYXJpYWJsZSBvZiBvYnNlcnZhdGlvbjogcHJpY2UNCi0gU2FtcGxlIHNpemU6IDU0NSBob3VzZXMgKDE3OCB1bmZ1cm5pc2hlZCwgMjI3IHNlbWktZnVybmlzaGVkLCAxNDAgZnVybmlzaGVkKQ0KDQojIyAyLjMgRGF0YXNldCBTb3VyY2U6DQoNCiJIb3VzaW5nIFByaWNlcyBEYXRhc2V0IiBkYXRhc2V0IHNvdXJjZWQgZnJvbSBodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL3lhc3NlcmgvaG91c2luZy1wcmljZXMtZGF0YXNldA0KICANCiMjIDIuNCBCYXNpYyBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciB0aGUgdmFyaWFibGVzIG9mIGludGVyZXN0Og0KDQpgYGB7ciBtZXNzYWdlID0gRn0NCiMgRXhwbG9yZSB0aGUgZGF0YXNldA0Kc3VtbWFyeShob3VzaW5nKQ0KZGVzY3JpYmUoaG91c2luZykNCmRlc2NyaWJlQnkoaG91c2luZyRwcmljZSwgaG91c2luZyRmdXJuaXNoaW5nc3RhdHVzKQ0KDQpgYGANCg0KIyMjIEdlbmVyYWw6DQoNCi0gcHJpY2U6IDU0NSB2YWx1ZXMgcmFuZ2luZyBmcm9tIDEuNzVNIFVTRCB0byAxMy4zME0gVVNEIGFuZCB0aHVzIGEgcmFuZ2Ugb2YgMTEuNTVNIFVTRCB3aXRoIGEgbWVkaWFuIG9mIDQuMzRNIFVTRCBhbmQgYSBtZWFuIG9mIH40Ljc3TSBVU0QNCi0gZnVybmlzaGluZ3N0YXR1czogNTQ1IHZhbHVlcyBzcGxpdCBpbnRvIDMgY2F0ZWdvcmllcyB3aXRoIDE3OCBpbiB1bmZ1cm5pc2hlZCwgMjI3IGluIHNlbWktZnVybmlzaGVkLCBhbmQgMTQwIGluIGZ1cm5pc2hlZCB3aXRoIGEgbWVkaWFuIG9mIDIsIGkuZS4gc2VtaS1mdXJuaXNoZWQNCiAgDQojIyMgUHJpY2UgZ3JvdXBlZCBieSBmdXJuaXNoaW5nIHN0YXR1czoNCg0KLSB1bmZ1cm5pc2hlZDogMTc4IHZhbHVlcyByYW5naW5nIGZyb20gMS43NU0gVVNEIHRvIDEwLjE1TSBVU0QgYW5kIHRodXMgYSByYW5nZSBvZiA4LjQwTSBVU0Qgd2l0aCBhIG1lZGlhbiBvZiAzLjQzTSBVU0QgYW5kIGEgbWVhbiBvZiB+NC4wMU0gVVNEDQotIHNlbWktZnVybmlzaGVkOiAyMjcgdmFsdWVzIHJhbmdpbmcgZnJvbSB+MS43N00gVVNEIHRvIDEyLjI1TSBVU0QgYW5kIHRodXMgYSByYW5nZSBvZiB+MTAuNDhNIFVTRCB3aXRoIGEgbWVkaWFuIG9mIH40LjU5TSBVU0QgYW5kIGEgbWVhbiBvZiB+NC45MU0gVVNEDQotIGZ1cm5pc2hlZDogMTQwIHZhbHVlcyByYW5naW5nIGZyb20gMS43NU0gVVNEIHRvIDEzLjMwTSBVU0QgYW5kIHRodXMgYSByYW5nZSBvZiAxMS41NU0gVVNEIHdpdGggYSBtZWRpYW4gb2YgfjUuMDhNIFVTRCBhbmQgYSBtZWFuIG9mIH41LjVNIFVTRA0KDQpBbHRob3VnaCB0aGUgbG93ZXN0IHByaWNlIGRvZXNuJ3QgcmVhbGx5IGNoYW5nZSB3aXRoIGEgYmV0dGVyIGZ1cm5pc2hpbmcgc3RhdHVzLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGhpZ2hlc3QgcHJpY2UgZG9lcyB3aGljaCBpcyBhbHNvIHJlZmxlY3RlZCBpbiBhbiBpbmNyZWFzaW5nIG1lZGlhbiBhbmQgbWVhbiBwcmljZS4NCg0KYGBge3IgbWVzc2FnZSA9IEZ9DQojIFBsb3QgcHJpY2VzIGJ5IGZ1cm5pc2hpbmcgc3RhdHVzDQpnZ2JveHBsb3QoaG91c2luZywNCiAgICAgICAgICB4ID0gImZ1cm5pc2hpbmdzdGF0dXMiLA0KICAgICAgICAgIHkgPSAicHJpY2UiLA0KICAgICAgICAgIHhsYWIgPSAiRnVybmlzaGluZyBTdGF0dXMiLA0KICAgICAgICAgIHlsYWIgPSAiUHJpY2UiKQ0KDQpgYGANCg0KVGhlIGJveHBsb3QgYWdhaW4gY29uZmlybXMgdGhlIHByZXZpb3VzIG9ic2VydmF0aW9uIHRoYXQgdGhlIG1lZGlhbiBwcmljZSBzZWVtcyB0byBnbyB1cCB3aXRoIGEgYmV0dGVyIGZ1cm5pc2hpbmcgc3RhdHVzLg0KDQojIDMuIEFuYWx5c2lzDQoNCiMjIDMuMSBTdGF0aXN0aWNhbCB0ZXN0IGNob2ljZToNCg0KSSB3aWxsIG5lZWQgdGhlIE9uZS13YXkgQU5PVkEgb3IgYWx0ZXJuYXRpdmVseSB0aGUgS3J1c2thbC1XYWxsaXMgUmFuayBTdW0gVGVzdCBzaW5jZSBteSBoeXBvdGhlc2lzIGlzIGNvbmNlcm5lZCB3aXRoIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGhvdXNlIHByaWNlcyBmcm9tIHRocmVlIHBvcHVsYXRpb25zIGZyb20gaW5kZXBlbmRlbnQgc2FtcGxlcywgaS5lLiB0aGUgcHJpY2Ugb2YgdW5mdXJuaXNoZWQsIHRoZSBwcmljZSBvZiBzZW1pLWZ1cm5pc2hlZCBhbmQgdGhlIHByaWNlIG9mIGZ1cm5pc2hlZCBob3VzZXMuDQoNCiMjIDMuMiBFdmFsdWF0aW9uIG9mIGFsbCBhc3N1bXB0aW9ucyBmb3IgdGhlIE9uZS13YXkgQU5PVkE6DQoNCiMjIyBBbmFseXplZCB2YXJpYWJsZSBpcyBudW1lcmljLg0KDQpZZXMsIHRoZSB2YXJpYWJsZSAicHJpY2UiIGlzIG51bWVyaWMuDQoNCiMjIyBUaGUgZGF0YSBtdXN0IGNvbWUgZnJvbSBpbmRlcGVuZGVudCBwb3B1bGF0aW9uczoNCg0KWWVzLCB0aGUgZGF0YSBmb3IgdGhlIGRpZmZlcmVudCBmdXJuaXNoaW5nIHN0YXR1cyBhcmUgaW5kZXBlbmRlbnQgcG9wdWxhdGlvbnMuDQoNCiMjIyBOb3JtYWxpdHk6DQoNCmBgYHtyIG1lc3NhZ2UgPSBGfQ0KIyBUZXN0IG5vcm1hbGl0eSBpbiBib3RoIHBvcHVsYXRpb25zDQpob3VzaW5nICU+JQ0KICBncm91cF9ieShmdXJuaXNoaW5nc3RhdHVzKSAlPiUNCiAgc2hhcGlyb190ZXN0KHByaWNlKQ0KDQpgYGANCg0KV2UgcmVqZWN0IEhfMCwgaS5lLiB0aGF0IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHByaWNlIGlzIG5vcm1hbCBmb3IgZXZlcnkgZnVybmlzaGluZyBzdGF0dXMgYXQgcCA8IDAuMDAxIGFuZCBhY2NlcHQgSF8xLCBpLmUuIHRoYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcHJpY2UgaXMgTk9UIG5vcm1hbCBmb3IgZXZlcnkgZnVybmlzaGluZyBzdGF0dXMuDQoNCiMjIyBIb21vc2NlZGFzdGljaXR5Og0KYGBge3IgbWVzc2FnZSA9IEZ9DQojIFRlc3QgaWYgdGhlIHZhcmlhbmNlIG9mIHRoZSBwcmljZSBpcyB0aGUgc2FtZSB3aXRoaW4gYWxsIGdyb3Vwcw0KbGV2ZW5lVGVzdChob3VzaW5nJHByaWNlLCBncm91cCA9IGhvdXNpbmckZnVybmlzaGluZ3N0YXR1cykNCg0KYGBgDQoNCldlIHJlamVjdCBIXzAsIGkuZS4gdGhhdCB0aGUgcG9wdWxhdGlvbiB2YXJpYW5jZXMgYXJlIHRoZSBzYW1lIGFuZCBhY2NlcHQgSF8xIHRoYXQgdGhlIHBvcHVsYXRpb24gdmFyaWFuY2VzIGFyZSBOT1QgdGhlIHNhbWUuDQoNCiMjIDMuMyBXaWxjb3hvbiBSYW5rIFN1bSBUZXN0Og0KDQpTaW5jZSBib3RoIHRoZSBub3JtYWxpdHkgYW5kIHRoZSBob21vc2NlZGFzdGljaXR5IGFzc3VtcHRpb25zIG5lZWRlZCBmb3IgdGhlIE9uZS13YXkgQU5PVkEgZG8gbm90IGhvbGQsIEkgd2lsbCBjb250aW51ZSBieSB1c2luZyB0aGUgYWx0ZXJuYXRpdmUgbm9uLXBhcmFtZXRyaWMgc3RhdGlzdGljYWwgdGVzdCwgdGhlIEtydXNrYWwtV2FsbGlzIFJhbmsgU3VtIFRlc3QuDQoNCi0gSF8wOiBBbGwgZGlzdHJpYnV0aW9uIGxvY2F0aW9ucyBvZiBob3VzZSBwcmljZXMgYXJlIHRoZSBzYW1lIGZvciBldmVyeSBmdXJuaXNoaW5nIHN0YXR1cy4NCi0gSF8xOiBBdCBsZWFzdCBvbmUgZGlzdHJpYnV0aW9uIGxvY2F0aW9uIG9mIGhvdXNlIHByaWNlcyBpcyBOT1QgdGhlIHNhbWUgdGhlIG90aGVyIGZ1cm5pc2hpbmcgc3RhdHVzLg0KDQpgYGB7ciBtZXNzYWdlID0gRn0NCiMgVGVzdCB0aGUgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIG5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gdGhlIG1lZGlhbiBwcmljZSBiZXR3ZWVuIHRoZSBmdXJuaXNoaW5nIHN0YXR1cw0Ka3J1c2thbC50ZXN0KHByaWNlIH4gZnVybmlzaGluZ3N0YXR1cywNCiAgICAgICAgICAgICBkYXRhID0gaG91c2luZykNCg0KYGBgDQoNCldlIHJlamVjdCBIXzAgYXQgcCA8IDAuMDAwMSBhbmQgYWNjZXB0IEhfMSB0aGF0IGF0IGxlYXN0IG9uZSBkaXN0cmlidXRpb24gbG9jYXRpb24gb2YgaG91c2UgcHJpY2VzIGlzIE5PVCB0aGUgc2FtZSB0aGUgb3RoZXIgZnVybmlzaGluZyBzdGF0dXMuDQoNCmBgYHtyIG1lc3NhZ2UgPSBGfQ0KIyBEZXRlcm1pbmUgdGhlIGVmZmVjdCBzaXplDQprcnVza2FsX2VmZnNpemUocHJpY2UgfiBmdXJuaXNoaW5nc3RhdHVzLA0KICAgICAgICAgICAgIGRhdGEgPSBob3VzaW5nKQ0KDQpgYGANCg0KQWNjb3JkaW5nIHRvIHRoZSBlZmZlY3Qgc2l6ZSByYW5nZXMgZnJvbSBGaWVsZCwgMjAxMywgdGhlIGVmZmVjdCBzaXplIGlzIG1vZGVyYXRlLg0KDQojIyA0LiBDb25jbHVzaW9uOg0KDQpgYGB7ciBtZXNzYWdlID0gRn0NCiMgUGxvdCBhbGwgcmVzdWx0cw0KcHdjIDwtIGhvdXNpbmcgJT4lDQogIHdpbGNveF90ZXN0KHByaWNlIH4gZnVybmlzaGluZ3N0YXR1cywNCiAgICAgICAgICAgICAgcGFpcmVkID0gRkFMU0UsDQogICAgICAgICAgICAgIHAuYWRqdXN0Lm1ldGhvZCA9ICJib25mZXJyb25pIikNCg0KS3J1c2thbF9yZXN1bHRzIDwtIGtydXNrYWxfdGVzdChwcmljZSB+IGZ1cm5pc2hpbmdzdGF0dXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBob3VzaW5nKQ0KDQpwd2MgPC0gcHdjICU+JQ0KICAgICAgIGFkZF95X3Bvc2l0aW9uKGZ1biA9ICJtYXgiLCBzdGVwLmluY3JlYXNlID0gMC4yMCkNCg0KZ2dib3hwbG90KGhvdXNpbmcsIHggPSAiZnVybmlzaGluZ3N0YXR1cyIsIHkgPSAicHJpY2UiLCBhZGQgPSAicG9pbnQiKSArDQogIHN0YXRfcHZhbHVlX21hbnVhbChwd2MsIGhpZGUubnMgPSBGQUxTRSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuID0gbWVkaWFuLCBnZW9tID0gInBvaW50Iiwgc2hhcGUgPSAxNiwgc2l6ZSA9IDQsDQogICAgICAgICAgICAgICBhZXMoZ3JvdXAgPSBmdXJuaXNoaW5nc3RhdHVzKSwgY29sb3IgPSAiZGFya3JlZCIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuID0gbWVkaWFuLCBjb2xvciA9ICJkYXJrcmVkIiwNCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLA0KICAgICAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0Iiwgdmp1c3QgPSAtMC41LCBoanVzdCA9IC0xLA0KICAgICAgICAgICAgICAgYWVzKGxhYmVsID0gcm91bmQoYWZ0ZXJfc3RhdCh5KSwgZGlnaXRzID0gMiksIGdyb3VwID0gZnVybmlzaGluZ3N0YXR1cykpICsNCiAgbGFicyhzdWJ0aXRsZSA9IGdldF90ZXN0X2xhYmVsKEtydXNrYWxfcmVzdWx0cywgZGV0YWlsZWQgPSBUUlVFKSwNCiAgICAgICBjYXB0aW9uID0gZ2V0X3B3Y19sYWJlbChwd2MpKQ0KDQpgYGANCg0KV2UgZm91bmQgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGhvdXNlIHByaWNlcyBkaWZmZXJzIGZvciBhdCBsZWFzdCBvbmUgb2YgdGhlIGZ1cm5pc2hpbmcgc3RhdHVzICjwnZySMiA9IDY5LjU4LCDwnZGdIDwgMC4wMDAxKSwgdGhlIGVmZmVjdCBzaXplIHdhcyBtb2RlcmF0ZSAo8J2cgjIgPSAwLjEyNSkuIFBvc3QtSG9jIHRlc3RzIHJldmVhbGVkIGRpZmZlcmVuY2VzIGZvciB0d28gZnVybmlzaGluZyBzdGF0dXMgKPCdkZ0gPCAwLjAwMDEpLCB3aXRoIHRoZSBleGNlcHRpb24gb2Ygc2VtaS1mdXJuaXNoZWQgdnMuIGZ1cm5pc2hlZCBob3VzZXMuDQoNCg0K