Data Description
Please load the MSR package and the data
camera from the package. The baseline levels for the
attributes are already set for you. To see a detailed description of the
data, run ?camera or help(camera) in your
command line prompt.
# load the package MSR
library(MSR)
# load the data `camera`
data(camera)
# get a sneak peak of the data
head(camera)
## id memory_format lens price ratings
## 1 1 SD Card Plastic Lens 8x Zoom 300 euro 51.05633
## 2 1 Compact Flash Card Glass Lens 8x Zoom 100 euro 89.76444
## 3 1 SD Card Plastic Lens 4x Zoom 100 euro 20.50488
## 4 1 Compact Flash Card Plastic Lens 8x Zoom 200 euro 61.27721
## 5 1 Memory Stick Plastic Lens 8x Zoom 100 euro 62.21202
## 6 1 SD Card Glass Lens 8x Zoom 200 euro 33.26009
The data has 3 product attributes for a camera and 3 levels for each
attribute. The levels of these attributes are as below. Note that the
baseline levels are already set for all the attributes
(Memory Stick, Glass Lens 8x Zoom,
300 euro).
## $memory_format
## [1] "Memory Stick" "SD Card" "Compact Flash Card"
##
## $lens
## [1] "Glass Lens 8x Zoom" "Plastic Lens 8x Zoom" "Plastic Lens 4x Zoom"
##
## $price
## [1] "300 euro" "100 euro" "200 euro"
Estimating the
Coefficients
We first estimate a linear regression of ratings on the three
attributes (memory_format, lens,
price) to obtain the coefficients of levels. The baseline
levels are already set for you. In your own practices, you may use
relevel() function to choose your own baselines. In theory,
you can use any level as the baseline for an attribute.
# running the linear regression
mdl <- lm(ratings ~ memory_format + lens + price, camera)
# get a summary of the model results
summary(mdl)
##
## Call:
## lm(formula = ratings ~ memory_format + lens + price, data = camera)
##
## Residuals:
## Min 1Q Median 3Q Max
## -45.959 -9.616 0.387 9.410 54.870
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 46.6175 1.5757 29.585 < 2e-16 ***
## memory_formatSD Card -0.1962 1.4588 -0.134 0.89307
## memory_formatCompact Flash Card 0.5834 1.4588 0.400 0.68938
## lensPlastic Lens 8x Zoom -3.7992 1.4588 -2.604 0.00943 **
## lensPlastic Lens 4x Zoom -9.9566 1.4588 -6.825 2.14e-11 ***
## price100 euro 16.5377 1.4588 11.336 < 2e-16 ***
## price200 euro 6.2857 1.4588 4.309 1.92e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 14.73 on 605 degrees of freedom
## Multiple R-squared: 0.2281, Adjusted R-squared: 0.2204
## F-statistic: 29.79 on 6 and 605 DF, p-value: < 2.2e-16
From the estimation results, we see that the overall model is
significant with F-stat 29.79 and
p-value < 0.05. Therefore, we reject the null hypothesis
that all coefficients are zero. Note that it is unnecessary to check the
R-squared as we are not doing prediction here.
Moreover, a closer look at the coefficients show that the two levels
of memory_format are insignificant, with
p-values of 0.89 and 0.69 respectively. Therefore, we
cannot reject the null hypothesis that the coefficients are zeros. We
will use this observation in the next step.
Obtaining the
Partworths
In class, we have discussed three rules to transform the coefficients
to partworths:
- Baseline levels partworths = 0
- Insignificant levels partworths = 0
- Significant levels partworths = coefficients
Here, we presenting two options. For those of you who are not
familiar with R, we will create a table in word/excel/ppt to record the
results. For those of you R lovers, pleas see the final section for the
R code.
First, we create a coefficients table to record the coefficients and
p-values of all levels. In your own practice, please follow a similar
procedure. I will show you the table here, but you can create your table
in word or excel. Note that in the table, the coefficients of baselines
are zeros, and p-values of the baselines are empty. This is because we
must set the coefficients of baselines to zeros.
|
Attributes
|
Levels
|
Coefficients
|
P-values
|
|
Memory Format
|
SD card
|
-0.196
|
0.893
|
|
|
Compact flash card
|
0.583
|
0.689
|
|
|
Memory stick
|
0.000
|
|
|
Lens
|
Plastic 8x Zoom
|
-3.799
|
0.009
|
|
|
Plastic 4x Zoom
|
-9.957
|
2.14E-11
|
|
|
Glass 8x Zoom
|
0.000
|
|
|
Price
|
100 euro
|
16.538
|
2.00E-16
|
|
|
200 euro
|
6.286
|
1.92E-05
|
|
|
300 euro
|
0.000
|
|
Based on the coefficients table, we then follow the three rules to
obtain the partworths of all levels. The partworths of all baselines
(Memory Stick, Glass 8x Zoom and
300 euro) are zeros. The partworths for insignificant
levels are also zeros, including SD Card and
Compact Flash Card. For all the other levels, the
partworths are the coefficients.
|
Attributes
|
Levels
|
Coefficients
|
P-values
|
Partworths
|
|
Memory Format
|
SD card
|
-0.196
|
0.893
|
0.000
|
|
|
Compact flash card
|
0.583
|
0.689
|
0.000
|
|
|
Memory stick
|
0.000
|
|
0.000
|
|
Lens
|
Plastic 8x Zoom
|
-3.799
|
0.009
|
-3.799
|
|
|
Plastic 4x Zoom
|
-9.957
|
2.14E-11
|
-9.957
|
|
|
Glass 8x Zoom
|
0.000
|
|
0.000
|
|
Price
|
100 euro
|
16.538
|
2.00E-16
|
16.538
|
|
|
200 euro
|
6.286
|
1.92E-05
|
6.286
|
|
|
300 euro
|
0.000
|
|
0.000
|
Making Use of the
Results
Given the partworths, we can use them to generate some insights into
consumers. Here, we focus on three applications:
- Calculating the importance of attributes;
- Checking the most preferred products;
- Comparing product ideas;
Calculating the
importance of attributes
To calculate the importance of an attribute, we first look at the
partworths of all the levels of the attribute. Then, we find the highest
and lowest levels and difference them. \[
importance = max(partworth) - min(partworth) \] Following the
equation, we have:
- Importance of Memory Format = 0 - 0 = 0
- Importance of Lens = 0 - (-9.957) = 9.957
- Importance of Price = 16.538 - 0 = 16.538
We can also normalize the importance for reporting purposes. With the
relative importance, our clients can read results much more easily. To
do the normalization, we divide each importance by the sum of all
importance.
\[
Memory\,\,Format=\frac{0}{\left( 0+9.957+16.538 \right)}=0
\\
Lens=\frac{9.957}{\left( 0+9.957+16.538 \right)}=0.376
\\
Price=\frac{16.538}{\left( 0+9.957+16.538 \right)}=0.624
\]
Obtaining the most
preferred product profile
To see which product profile consumers like the most, we just combine
all the highest levels. For Lens, it’s
Glass 8x Zoom. For Price, it’s
100 euro. For Memory Format, all the levels
have the same partworth (all zeros). This means consumers do not care
about which memory format to include, and the company can decide
whichever memory format without influencing consumers’ preferences.
Comparing product
ideas
In real research projects, you are often asked by your clients to
compare some product profiles. These profiles are probably “good
candidates” from within the company. For example, suppose your client
asks you to compare the following two product ideas:
- Camera A: SD card, Plastic 4x Zoom and priced at 100 euro.
- Camera B: Memory Stick, Plastic 8x Zoom and priced at 200 euro.
To compare the two products, you just need to add up the partworths
of the levels of the products.
- For Camera A, we have \(0 − 9.957 +16.538
= 6.581\).
- For Camera B, we have \(0 − 3.799 + 6.286
= 2.487\).
From the calculation, Camera A is more preferred by consumers.
For R Lovers: R Codes
to Obtain Partworths and Make Use of Results (ignore this if you are not
familiar with R)
First, we create three vectors for three attributes with names.
Memory_Format <- setNames(rep(0,3),
levels(camera$memory_format))
Lens <- setNames(rep(0,3),
levels(camera$lens))
Price <- setNames(rep(0,3),
levels(camera$price))
We next obtain the coefficients from the estimation results and
transform insignificant coefficients to zeros by checking if p-values
are larger than 0.05.
# getting the coefficients table
results <- summary(mdl)$coefficients
coefficients <- results[-1,1]*(results[-1,4]<0.05)
# reshape into a matrix
coefficients <- matrix(coefficients, nrow = 2, ncol = 3)
We next pack the coefficients into the three partworth vectors and
create a list called partworths to store all partworths values.
Memory_Format[2:3] <- coefficients[,1]
Lens[2:3] <- coefficients[,2]
Price[2:3] <- coefficients[,3]
partworths <- list(Memory_Format = Memory_Format,
Lens = Lens,
Price = Price)
partworths
## $Memory_Format
## Memory Stick SD Card Compact Flash Card
## 0 0 0
##
## $Lens
## Glass Lens 8x Zoom Plastic Lens 8x Zoom Plastic Lens 4x Zoom
## 0.000000 -3.799195 -9.956553
##
## $Price
## 300 euro 100 euro 200 euro
## 0.000000 16.537702 6.285731
Given the partworths table, we then calculate the importance of
different attributes and the relative importance.
importance <- unlist(lapply(partworths,
function(x){max(x)-min(x)}))
importance
## Memory_Format Lens Price
## 0.000000 9.956553 16.537702
relative_importance <- importance/sum(importance)
relative_importance
## Memory_Format Lens Price
## 0.0000000 0.3758005 0.6241995
The most preferred products are the combination of all highest
levels.
most_preferred <- lapply(partworths,
function(x){which(x==max(x),arr.ind = T)})
most_preferred
## $Memory_Format
## Memory Stick SD Card Compact Flash Card
## 1 2 3
##
## $Lens
## Glass Lens 8x Zoom
## 1
##
## $Price
## 100 euro
## 2
Lastly, we compare the two hypothetical product profiles: A
vs. B.
- Camera A: SD card, Plastic 4x Zoom and priced at 100 euro.
- Camera B: Memory Stick, Plastic 8x Zoom and priced at 200 euro.
Utility_A <- partworths$Memory_Format[2] +
partworths$Lens[3] +
partworths$Price[2]
setNames(Utility_A,"Utility_A")
## Utility_A
## 6.581148
Utility_B <- partworths$Memory_Format[1] +
partworths$Lens[2] +
partworths$Price[3]
setNames(Utility_B,"Utility_B")
## Utility_B
## 2.486536
LS0tDQp0aXRsZTogJ1IgVHV0b3JpYWw6IENvbmpvaW50IEFuYWx5c2lzJw0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBkZWZhdWx0DQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgdGhlbWU6IHJlYWRhYmxlDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IA0KICAgICAgY29sbGFwc2VkOiBubw0KICAgICAgc21vb3RoX3Njcm9sbDogbm8NCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCi0tLQ0KDQojIERhdGEgRGVzY3JpcHRpb24gDQoNClBsZWFzZSBsb2FkIHRoZSBgTVNSYCBwYWNrYWdlIGFuZCB0aGUgZGF0YSBgY2FtZXJhYCBmcm9tIHRoZSBwYWNrYWdlLiBUaGUgYmFzZWxpbmUgbGV2ZWxzIGZvciB0aGUgYXR0cmlidXRlcyBhcmUgYWxyZWFkeSBzZXQgZm9yIHlvdS4gVG8gc2VlIGEgZGV0YWlsZWQgZGVzY3JpcHRpb24gb2YgdGhlIGRhdGEsIHJ1biBgP2NhbWVyYWAgb3IgYGhlbHAoY2FtZXJhKWAgaW4geW91ciBjb21tYW5kIGxpbmUgcHJvbXB0LiANCg0KYGBge3J9DQojIGxvYWQgdGhlIHBhY2thZ2UgTVNSDQpsaWJyYXJ5KE1TUikNCg0KIyBsb2FkIHRoZSBkYXRhIGBjYW1lcmFgDQpkYXRhKGNhbWVyYSkNCg0KIyBnZXQgYSBzbmVhayBwZWFrIG9mIHRoZSBkYXRhIA0KaGVhZChjYW1lcmEpDQpgYGANCg0KVGhlIGRhdGEgaGFzIDMgcHJvZHVjdCBhdHRyaWJ1dGVzIGZvciBhIGNhbWVyYSBhbmQgMyBsZXZlbHMgZm9yIGVhY2ggYXR0cmlidXRlLiBUaGUgbGV2ZWxzIG9mIHRoZXNlIGF0dHJpYnV0ZXMgYXJlIGFzIGJlbG93LiBOb3RlIHRoYXQgdGhlIGJhc2VsaW5lIGxldmVscyBhcmUgYWxyZWFkeSBzZXQgZm9yIGFsbCB0aGUgYXR0cmlidXRlcyAoYE1lbW9yeSBTdGlja2AsIGBHbGFzcyBMZW5zIDh4IFpvb21gLCBgMzAwIGV1cm9gKS4NCg0KYGBge3IsIGVjaG89RkFMU0V9DQojIGNoZWNrIHRoZSBsZXZlbHMgb2YgYWxsIGF0dHJpYnV0ZXMNCmxhcHBseShjYW1lcmFbLDI6NF0sbGV2ZWxzKQ0KYGBgDQoNCiMgRXN0aW1hdGluZyB0aGUgQ29lZmZpY2llbnRzDQoNCldlIGZpcnN0IGVzdGltYXRlIGEgbGluZWFyIHJlZ3Jlc3Npb24gb2YgcmF0aW5ncyBvbiB0aGUgdGhyZWUgYXR0cmlidXRlcyAoYG1lbW9yeV9mb3JtYXRgLCBgbGVuc2AsIGBwcmljZWApIHRvIG9idGFpbiB0aGUgY29lZmZpY2llbnRzIG9mIGxldmVscy4gVGhlIGJhc2VsaW5lIGxldmVscyBhcmUgYWxyZWFkeSBzZXQgZm9yIHlvdS4gSW4geW91ciBvd24gcHJhY3RpY2VzLCB5b3UgbWF5IHVzZSBgcmVsZXZlbCgpYCBmdW5jdGlvbiB0byBjaG9vc2UgeW91ciBvd24gYmFzZWxpbmVzLiBJbiB0aGVvcnksIHlvdSBjYW4gdXNlIGFueSBsZXZlbCBhcyB0aGUgYmFzZWxpbmUgZm9yIGFuIGF0dHJpYnV0ZS4gDQoNCmBgYHtyfQ0KIyBydW5uaW5nIHRoZSBsaW5lYXIgcmVncmVzc2lvbiANCm1kbCA8LSBsbShyYXRpbmdzIH4gbWVtb3J5X2Zvcm1hdCArIGxlbnMgKyBwcmljZSwgY2FtZXJhKQ0KDQojIGdldCBhIHN1bW1hcnkgb2YgdGhlIG1vZGVsIHJlc3VsdHMNCnN1bW1hcnkobWRsKQ0KDQpgYGANCg0KRnJvbSB0aGUgZXN0aW1hdGlvbiByZXN1bHRzLCB3ZSBzZWUgdGhhdCB0aGUgb3ZlcmFsbCBtb2RlbCBpcyBzaWduaWZpY2FudCB3aXRoIGBGLXN0YXRgIDI5Ljc5IGFuZCBgcC12YWx1ZSA8IDAuMDVgLiBUaGVyZWZvcmUsIHdlIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgYWxsIGNvZWZmaWNpZW50cyBhcmUgemVyby4gTm90ZSB0aGF0IGl0IGlzIHVubmVjZXNzYXJ5IHRvIGNoZWNrIHRoZSBSLXNxdWFyZWQgYXMgd2UgYXJlIG5vdCBkb2luZyBwcmVkaWN0aW9uIGhlcmUuIA0KDQpNb3Jlb3ZlciwgYSBjbG9zZXIgbG9vayBhdCB0aGUgY29lZmZpY2llbnRzIHNob3cgdGhhdCB0aGUgdHdvIGxldmVscyBvZiBgbWVtb3J5X2Zvcm1hdGAgYXJlIGluc2lnbmlmaWNhbnQsIHdpdGggYHAtdmFsdWVzYCBvZiAwLjg5IGFuZCAwLjY5IHJlc3BlY3RpdmVseS4gVGhlcmVmb3JlLCB3ZSBjYW5ub3QgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgY29lZmZpY2llbnRzIGFyZSB6ZXJvcy4gV2Ugd2lsbCB1c2UgdGhpcyBvYnNlcnZhdGlvbiBpbiB0aGUgbmV4dCBzdGVwLiANCg0KIyBPYnRhaW5pbmcgdGhlIFBhcnR3b3J0aHMNCg0KSW4gY2xhc3MsIHdlIGhhdmUgZGlzY3Vzc2VkIHRocmVlIHJ1bGVzIHRvIHRyYW5zZm9ybSB0aGUgY29lZmZpY2llbnRzIHRvIHBhcnR3b3J0aHM6DQoNCiAgMS4gQmFzZWxpbmUgbGV2ZWxzIHBhcnR3b3J0aHMgPSAwDQogIDIuIEluc2lnbmlmaWNhbnQgbGV2ZWxzIHBhcnR3b3J0aHMgPSAwDQogIDMuIFNpZ25pZmljYW50IGxldmVscyBwYXJ0d29ydGhzID0gY29lZmZpY2llbnRzICANCg0KSGVyZSwgd2UgcHJlc2VudGluZyB0d28gb3B0aW9ucy4gRm9yIHRob3NlIG9mIHlvdSB3aG8gYXJlIG5vdCBmYW1pbGlhciB3aXRoIFIsIHdlIHdpbGwgY3JlYXRlIGEgdGFibGUgaW4gd29yZC9leGNlbC9wcHQgdG8gcmVjb3JkIHRoZSByZXN1bHRzLiBGb3IgdGhvc2Ugb2YgeW91IFIgbG92ZXJzLCBwbGVhcyBzZWUgdGhlIGZpbmFsIHNlY3Rpb24gZm9yIHRoZSBSIGNvZGUuIA0KDQpGaXJzdCwgd2UgY3JlYXRlIGEgY29lZmZpY2llbnRzIHRhYmxlIHRvIHJlY29yZCB0aGUgY29lZmZpY2llbnRzIGFuZCBwLXZhbHVlcyBvZiBhbGwgbGV2ZWxzLiBJbiB5b3VyIG93biBwcmFjdGljZSwgcGxlYXNlIGZvbGxvdyBhIHNpbWlsYXIgcHJvY2VkdXJlLiBJIHdpbGwgc2hvdyB5b3UgdGhlIHRhYmxlIGhlcmUsIGJ1dCB5b3UgY2FuIGNyZWF0ZSB5b3VyIHRhYmxlIGluIHdvcmQgb3IgZXhjZWwuIE5vdGUgdGhhdCBpbiB0aGUgdGFibGUsIHRoZSBjb2VmZmljaWVudHMgb2YgYmFzZWxpbmVzIGFyZSB6ZXJvcywgYW5kIHAtdmFsdWVzIG9mIHRoZSBiYXNlbGluZXMgYXJlIGVtcHR5LiBUaGlzIGlzIGJlY2F1c2Ugd2UgbXVzdCBzZXQgdGhlIGNvZWZmaWNpZW50cyBvZiBiYXNlbGluZXMgdG8gemVyb3MuICAgDQoNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoudGcgIHtib3JkZXItY29sbGFwc2U6Y29sbGFwc2U7Ym9yZGVyLXNwYWNpbmc6MDt9DQoudGcgdGR7Ym9yZGVyLWNvbG9yOmJsYWNrO2JvcmRlci1zdHlsZTpzb2xpZDtib3JkZXItd2lkdGg6MXB4O2ZvbnQtZmFtaWx5OkFyaWFsLCBzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNHB4Ow0KICBvdmVyZmxvdzpoaWRkZW47cGFkZGluZzoxMHB4IDVweDt3b3JkLWJyZWFrOm5vcm1hbDt9DQoudGcgdGh7Ym9yZGVyLWNvbG9yOmJsYWNrO2JvcmRlci1zdHlsZTpzb2xpZDtib3JkZXItd2lkdGg6MXB4O2ZvbnQtZmFtaWx5OkFyaWFsLCBzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNHB4Ow0KICBmb250LXdlaWdodDpub3JtYWw7b3ZlcmZsb3c6aGlkZGVuO3BhZGRpbmc6MTBweCA1cHg7d29yZC1icmVhazpub3JtYWw7fQ0KLnRnIC50Zy1meW1ye2JvcmRlci1jb2xvcjppbmhlcml0O2ZvbnQtd2VpZ2h0OmJvbGQ7dGV4dC1hbGlnbjpsZWZ0O3ZlcnRpY2FsLWFsaWduOnRvcH0NCi50ZyAudGctMHBreXtib3JkZXItY29sb3I6aW5oZXJpdDt0ZXh0LWFsaWduOmxlZnQ7dmVydGljYWwtYWxpZ246dG9wfQ0KPC9zdHlsZT4NCjx0YWJsZSBjbGFzcz0idGciPg0KPHRoZWFkPg0KICA8dHI+DQogICAgPHRoIGNsYXNzPSJ0Zy1meW1yIj5BdHRyaWJ1dGVzPC90aD4NCiAgICA8dGggY2xhc3M9InRnLWZ5bXIiPkxldmVsczwvdGg+DQogICAgPHRoIGNsYXNzPSJ0Zy1meW1yIj5Db2VmZmljaWVudHM8L3RoPg0KICAgIDx0aCBjbGFzcz0idGctZnltciI+UC12YWx1ZXM8L3RoPg0KICA8L3RyPg0KPC90aGVhZD4NCjx0Ym9keT4NCiAgPHRyPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+TWVtb3J5IEZvcm1hdDwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij5TRCBjYXJkPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPi0wLjE5NjwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4wLjg5MzwvdGQ+DQogIDwvdHI+DQogIDx0cj4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij5Db21wYWN0IGZsYXNoIGNhcmQ8L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+MC41ODM8L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+MC42ODk8L3RkPg0KICA8L3RyPg0KICA8dHI+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij48L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+TWVtb3J5IHN0aWNrPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjAuMDAwPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjwvdGQ+DQogIDwvdHI+DQogIDx0cj4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPkxlbnM8L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+UGxhc3RpYyA4eCBab29tPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPi0zLjc5OTwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4wLjAwOTwvdGQ+DQogIDwvdHI+DQogIDx0cj4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij5QbGFzdGljIDR4IFpvb208L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+LTkuOTU3PC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjIuMTRFLTExPC90ZD4NCiAgPC90cj4NCiAgPHRyPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+PC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPkdsYXNzIDh4IFpvb208L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+MC4wMDA8L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+PC90ZD4NCiAgPC90cj4NCiAgPHRyPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+UHJpY2U8L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+MTAwIGV1cm88L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+MTYuNTM4PC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjIuMDBFLTE2PC90ZD4NCiAgPC90cj4NCiAgPHRyPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+PC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjIwMCBldXJvPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjYuMjg2PC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjEuOTJFLTA1PC90ZD4NCiAgPC90cj4NCiAgPHRyPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+PC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjMwMCBldXJvPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjAuMDAwPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjwvdGQ+DQogIDwvdHI+DQo8L3Rib2R5Pg0KPC90YWJsZT48YnI+DQoNCkJhc2VkIG9uIHRoZSBjb2VmZmljaWVudHMgdGFibGUsIHdlIHRoZW4gZm9sbG93IHRoZSB0aHJlZSBydWxlcyB0byBvYnRhaW4gdGhlIHBhcnR3b3J0aHMgb2YgYWxsIGxldmVscy4gVGhlIHBhcnR3b3J0aHMgb2YgYWxsIGJhc2VsaW5lcyAoYE1lbW9yeSBTdGlja2AsIGBHbGFzcyA4eCBab29tYCBhbmQgYDMwMCBldXJvYCkgYXJlIHplcm9zLiBUaGUgcGFydHdvcnRocyBmb3IgaW5zaWduaWZpY2FudCBsZXZlbHMgYXJlIGFsc28gemVyb3MsIGluY2x1ZGluZyBgU0QgQ2FyZGAgYW5kIGBDb21wYWN0IEZsYXNoIENhcmRgLiBGb3IgYWxsIHRoZSBvdGhlciBsZXZlbHMsIHRoZSBwYXJ0d29ydGhzIGFyZSB0aGUgY29lZmZpY2llbnRzLiANCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCi50ZyAge2JvcmRlci1jb2xsYXBzZTpjb2xsYXBzZTtib3JkZXItc3BhY2luZzowO30NCi50ZyB0ZHtib3JkZXItY29sb3I6YmxhY2s7Ym9yZGVyLXN0eWxlOnNvbGlkO2JvcmRlci13aWR0aDoxcHg7Zm9udC1mYW1pbHk6QXJpYWwsIHNhbnMtc2VyaWY7Zm9udC1zaXplOjE0cHg7DQogIG92ZXJmbG93OmhpZGRlbjtwYWRkaW5nOjEwcHggNXB4O3dvcmQtYnJlYWs6bm9ybWFsO30NCi50ZyB0aHtib3JkZXItY29sb3I6YmxhY2s7Ym9yZGVyLXN0eWxlOnNvbGlkO2JvcmRlci13aWR0aDoxcHg7Zm9udC1mYW1pbHk6QXJpYWwsIHNhbnMtc2VyaWY7Zm9udC1zaXplOjE0cHg7DQogIGZvbnQtd2VpZ2h0Om5vcm1hbDtvdmVyZmxvdzpoaWRkZW47cGFkZGluZzoxMHB4IDVweDt3b3JkLWJyZWFrOm5vcm1hbDt9DQoudGcgLnRnLWZ5bXJ7Ym9yZGVyLWNvbG9yOmluaGVyaXQ7Zm9udC13ZWlnaHQ6Ym9sZDt0ZXh0LWFsaWduOmxlZnQ7dmVydGljYWwtYWxpZ246dG9wfQ0KLnRnIC50Zy0wcGt5e2JvcmRlci1jb2xvcjppbmhlcml0O3RleHQtYWxpZ246bGVmdDt2ZXJ0aWNhbC1hbGlnbjp0b3B9DQo8L3N0eWxlPg0KPHRhYmxlIGNsYXNzPSJ0ZyI+DQo8dGhlYWQ+DQogIDx0cj4NCiAgICA8dGggY2xhc3M9InRnLWZ5bXIiPkF0dHJpYnV0ZXM8L3RoPg0KICAgIDx0aCBjbGFzcz0idGctZnltciI+TGV2ZWxzPC90aD4NCiAgICA8dGggY2xhc3M9InRnLWZ5bXIiPkNvZWZmaWNpZW50czwvdGg+DQogICAgPHRoIGNsYXNzPSJ0Zy1meW1yIj5QLXZhbHVlczwvdGg+DQogICAgPHRoIGNsYXNzPSJ0Zy0wcGt5Ij48c3BhbiBzdHlsZT0iZm9udC13ZWlnaHQ6Ym9sZCI+UGFydHdvcnRoczwvc3Bhbj48L3RoPg0KICA8L3RyPg0KPC90aGVhZD4NCjx0Ym9keT4NCiAgPHRyPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+TWVtb3J5IEZvcm1hdDwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij5TRCBjYXJkPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPi0wLjE5NjwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4wLjg5MzwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4wLjAwMDwvdGQ+DQogIDwvdHI+DQogIDx0cj4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij5Db21wYWN0IGZsYXNoIGNhcmQ8L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+MC41ODM8L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+MC42ODk8L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+MC4wMDA8L3RkPg0KICA8L3RyPg0KICA8dHI+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij48L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+TWVtb3J5IHN0aWNrPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjAuMDAwPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4wLjAwMDwvdGQ+DQogIDwvdHI+DQogIDx0cj4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPkxlbnM8L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+UGxhc3RpYyA4eCBab29tPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPi0zLjc5OTwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4wLjAwOTwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4tMy43OTk8L3RkPg0KICA8L3RyPg0KICA8dHI+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij48L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+UGxhc3RpYyA0eCBab29tPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPi05Ljk1NzwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4yLjE0RS0xMTwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4tOS45NTc8L3RkPg0KICA8L3RyPg0KICA8dHI+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij48L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+R2xhc3MgOHggWm9vbTwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4wLjAwMDwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij48L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+MC4wMDA8L3RkPg0KICA8L3RyPg0KICA8dHI+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij5QcmljZTwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4xMDAgZXVybzwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4xNi41Mzg8L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+Mi4wMEUtMTY8L3RkPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+MTYuNTM4PC90ZD4NCiAgPC90cj4NCiAgPHRyPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+PC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjIwMCBldXJvPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjYuMjg2PC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjEuOTJFLTA1PC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjYuMjg2PC90ZD4NCiAgPC90cj4NCiAgPHRyPg0KICAgIDx0ZCBjbGFzcz0idGctMHBreSI+PC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjMwMCBldXJvPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjAuMDAwPC90ZD4NCiAgICA8dGQgY2xhc3M9InRnLTBwa3kiPjwvdGQ+DQogICAgPHRkIGNsYXNzPSJ0Zy0wcGt5Ij4wLjAwMDwvdGQ+DQogIDwvdHI+DQo8L3Rib2R5Pg0KPC90YWJsZT4NCg0KIyBNYWtpbmcgVXNlIG9mIHRoZSBSZXN1bHRzDQoNCkdpdmVuIHRoZSBwYXJ0d29ydGhzLCB3ZSBjYW4gdXNlIHRoZW0gdG8gZ2VuZXJhdGUgc29tZSBpbnNpZ2h0cyBpbnRvIGNvbnN1bWVycy4gSGVyZSwgd2UgZm9jdXMgb24gdGhyZWUgYXBwbGljYXRpb25zOiANCg0KKiBDYWxjdWxhdGluZyB0aGUgaW1wb3J0YW5jZSBvZiBhdHRyaWJ1dGVzOyANCiogQ2hlY2tpbmcgdGhlIG1vc3QgcHJlZmVycmVkIHByb2R1Y3RzOyANCiogQ29tcGFyaW5nIHByb2R1Y3QgaWRlYXM7IA0KDQojIyBDYWxjdWxhdGluZyB0aGUgaW1wb3J0YW5jZSBvZiBhdHRyaWJ1dGVzDQoNClRvIGNhbGN1bGF0ZSB0aGUgaW1wb3J0YW5jZSBvZiBhbiBhdHRyaWJ1dGUsIHdlIGZpcnN0IGxvb2sgYXQgdGhlIHBhcnR3b3J0aHMgb2YgYWxsIHRoZSBsZXZlbHMgb2YgdGhlIGF0dHJpYnV0ZS4gVGhlbiwgd2UgZmluZCB0aGUgaGlnaGVzdCBhbmQgbG93ZXN0IGxldmVscyBhbmQgZGlmZmVyZW5jZSB0aGVtLiANCiQkIGltcG9ydGFuY2UgPSBtYXgocGFydHdvcnRoKSAtIG1pbihwYXJ0d29ydGgpICQkDQpGb2xsb3dpbmcgdGhlIGVxdWF0aW9uLCB3ZSBoYXZlOiANCg0KKiBJbXBvcnRhbmNlIG9mIE1lbW9yeSBGb3JtYXQgPSAwIC0gMCA9IDANCiogSW1wb3J0YW5jZSBvZiBMZW5zID0gMCAtICgtOS45NTcpID0gOS45NTcNCiogSW1wb3J0YW5jZSBvZiBQcmljZSA9IDE2LjUzOCAtIDAgPSAxNi41MzgNCg0KV2UgY2FuIGFsc28gbm9ybWFsaXplIHRoZSBpbXBvcnRhbmNlIGZvciByZXBvcnRpbmcgcHVycG9zZXMuIFdpdGggdGhlIHJlbGF0aXZlIGltcG9ydGFuY2UsIG91ciBjbGllbnRzIGNhbiByZWFkIHJlc3VsdHMgbXVjaCBtb3JlIGVhc2lseS4gVG8gZG8gdGhlIG5vcm1hbGl6YXRpb24sIHdlIGRpdmlkZSBlYWNoIGltcG9ydGFuY2UgYnkgdGhlIHN1bSBvZiBhbGwgaW1wb3J0YW5jZS4gDQoNCiQkDQpNZW1vcnlcLFwsRm9ybWF0PVxmcmFjezB9e1xsZWZ0KCAwKzkuOTU3KzE2LjUzOCBccmlnaHQpfT0wDQpcXA0KTGVucz1cZnJhY3s5Ljk1N317XGxlZnQoIDArOS45NTcrMTYuNTM4IFxyaWdodCl9PTAuMzc2DQpcXA0KUHJpY2U9XGZyYWN7MTYuNTM4fXtcbGVmdCggMCs5Ljk1NysxNi41MzggXHJpZ2h0KX09MC42MjQNCiQkDQoNCiMjIE9idGFpbmluZyB0aGUgbW9zdCBwcmVmZXJyZWQgcHJvZHVjdCBwcm9maWxlDQoNClRvIHNlZSB3aGljaCBwcm9kdWN0IHByb2ZpbGUgY29uc3VtZXJzIGxpa2UgdGhlIG1vc3QsIHdlIGp1c3QgY29tYmluZSBhbGwgdGhlIGhpZ2hlc3QgbGV2ZWxzLiBGb3IgYExlbnNgLCBpdCdzIGBHbGFzcyA4eCBab29tYC4gRm9yIGBQcmljZWAsIGl0J3MgYDEwMCBldXJvYC4gRm9yIGBNZW1vcnkgRm9ybWF0YCwgYWxsIHRoZSBsZXZlbHMgaGF2ZSB0aGUgc2FtZSBwYXJ0d29ydGggKGFsbCB6ZXJvcykuIFRoaXMgbWVhbnMgY29uc3VtZXJzIGRvIG5vdCBjYXJlIGFib3V0IHdoaWNoIG1lbW9yeSBmb3JtYXQgdG8gaW5jbHVkZSwgYW5kIHRoZSBjb21wYW55IGNhbiBkZWNpZGUgd2hpY2hldmVyIG1lbW9yeSBmb3JtYXQgd2l0aG91dCBpbmZsdWVuY2luZyBjb25zdW1lcnMnIHByZWZlcmVuY2VzLiANCg0KIyMgQ29tcGFyaW5nIHByb2R1Y3QgaWRlYXMNCg0KSW4gcmVhbCByZXNlYXJjaCBwcm9qZWN0cywgeW91IGFyZSBvZnRlbiBhc2tlZCBieSB5b3VyIGNsaWVudHMgdG8gY29tcGFyZSBzb21lIHByb2R1Y3QgcHJvZmlsZXMuIFRoZXNlIHByb2ZpbGVzIGFyZSBwcm9iYWJseSAiZ29vZCBjYW5kaWRhdGVzIiBmcm9tIHdpdGhpbiB0aGUgY29tcGFueS4gRm9yIGV4YW1wbGUsIHN1cHBvc2UgeW91ciBjbGllbnQgYXNrcyB5b3UgdG8gY29tcGFyZSB0aGUgZm9sbG93aW5nIHR3byBwcm9kdWN0IGlkZWFzOiANCg0KKiBDYW1lcmEgQTogU0QgY2FyZCwgUGxhc3RpYyA0eCBab29tIGFuZCBwcmljZWQgYXQgMTAwIGV1cm8uIA0KKiBDYW1lcmEgQjogTWVtb3J5IFN0aWNrLCBQbGFzdGljIDh4IFpvb20gYW5kIHByaWNlZCBhdCAyMDAgZXVyby4gDQoNClRvIGNvbXBhcmUgdGhlIHR3byBwcm9kdWN0cywgeW91IGp1c3QgbmVlZCB0byBhZGQgdXAgdGhlIHBhcnR3b3J0aHMgb2YgdGhlIGxldmVscyBvZiB0aGUgcHJvZHVjdHMuIA0KDQoqIEZvciBDYW1lcmEgQSwgd2UgaGF2ZSAkMCDiiJIgOS45NTcgKzE2LjUzOCA9IDYuNTgxJC4NCiogRm9yIENhbWVyYSBCLCB3ZSBoYXZlICQwIOKIkiAzLjc5OSArIDYuMjg2ID0gMi40ODckLiANCg0KRnJvbSB0aGUgY2FsY3VsYXRpb24sIENhbWVyYSBBIGlzIG1vcmUgcHJlZmVycmVkIGJ5IGNvbnN1bWVycy4gDQoNCiMgRm9yIFIgTG92ZXJzOiBSIENvZGVzIHRvIE9idGFpbiBQYXJ0d29ydGhzIGFuZCBNYWtlIFVzZSBvZiBSZXN1bHRzIChpZ25vcmUgdGhpcyBpZiB5b3UgYXJlIG5vdCBmYW1pbGlhciB3aXRoIFIpDQoNCkZpcnN0LCB3ZSBjcmVhdGUgdGhyZWUgdmVjdG9ycyBmb3IgdGhyZWUgYXR0cmlidXRlcyB3aXRoIG5hbWVzLiANCg0KYGBge3J9DQpNZW1vcnlfRm9ybWF0IDwtIHNldE5hbWVzKHJlcCgwLDMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMoY2FtZXJhJG1lbW9yeV9mb3JtYXQpKQ0KTGVucyA8LSBzZXROYW1lcyhyZXAoMCwzKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzKGNhbWVyYSRsZW5zKSkNClByaWNlIDwtIHNldE5hbWVzKHJlcCgwLDMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMoY2FtZXJhJHByaWNlKSkNCmBgYA0KDQpXZSBuZXh0IG9idGFpbiB0aGUgY29lZmZpY2llbnRzIGZyb20gdGhlIGVzdGltYXRpb24gcmVzdWx0cyBhbmQgdHJhbnNmb3JtIGluc2lnbmlmaWNhbnQgY29lZmZpY2llbnRzIHRvIHplcm9zIGJ5IGNoZWNraW5nIGlmIHAtdmFsdWVzIGFyZSBsYXJnZXIgdGhhbiAwLjA1LiANCg0KYGBge3J9DQojIGdldHRpbmcgdGhlIGNvZWZmaWNpZW50cyB0YWJsZQ0KcmVzdWx0cyA8LSBzdW1tYXJ5KG1kbCkkY29lZmZpY2llbnRzDQpjb2VmZmljaWVudHMgPC0gcmVzdWx0c1stMSwxXSoocmVzdWx0c1stMSw0XTwwLjA1KQ0KDQojIHJlc2hhcGUgaW50byBhIG1hdHJpeA0KY29lZmZpY2llbnRzIDwtIG1hdHJpeChjb2VmZmljaWVudHMsIG5yb3cgPSAyLCBuY29sID0gMykNCmBgYA0KDQpXZSBuZXh0IHBhY2sgdGhlIGNvZWZmaWNpZW50cyBpbnRvIHRoZSB0aHJlZSBwYXJ0d29ydGggdmVjdG9ycyBhbmQgY3JlYXRlIGEgbGlzdCBjYWxsZWQgcGFydHdvcnRocyB0byBzdG9yZSBhbGwgcGFydHdvcnRocyB2YWx1ZXMuICANCg0KYGBge3J9DQpNZW1vcnlfRm9ybWF0WzI6M10gPC0gY29lZmZpY2llbnRzWywxXQ0KTGVuc1syOjNdIDwtIGNvZWZmaWNpZW50c1ssMl0NClByaWNlWzI6M10gPC0gY29lZmZpY2llbnRzWywzXQ0KDQpwYXJ0d29ydGhzIDwtIGxpc3QoTWVtb3J5X0Zvcm1hdCA9IE1lbW9yeV9Gb3JtYXQsDQogICAgICAgICAgICAgICAgICAgTGVucyA9IExlbnMsDQogICAgICAgICAgICAgICAgICAgUHJpY2UgPSBQcmljZSkNCnBhcnR3b3J0aHMNCmBgYA0KDQpHaXZlbiB0aGUgcGFydHdvcnRocyB0YWJsZSwgd2UgdGhlbiBjYWxjdWxhdGUgdGhlIGltcG9ydGFuY2Ugb2YgZGlmZmVyZW50IGF0dHJpYnV0ZXMgYW5kIHRoZSByZWxhdGl2ZSBpbXBvcnRhbmNlLiANCg0KYGBge3J9DQppbXBvcnRhbmNlIDwtIHVubGlzdChsYXBwbHkocGFydHdvcnRocywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KXttYXgoeCktbWluKHgpfSkpDQppbXBvcnRhbmNlDQoNCnJlbGF0aXZlX2ltcG9ydGFuY2UgPC0gaW1wb3J0YW5jZS9zdW0oaW1wb3J0YW5jZSkNCnJlbGF0aXZlX2ltcG9ydGFuY2UNCmBgYA0KDQpUaGUgbW9zdCBwcmVmZXJyZWQgcHJvZHVjdHMgYXJlIHRoZSBjb21iaW5hdGlvbiBvZiBhbGwgaGlnaGVzdCBsZXZlbHMuIA0KDQpgYGB7cn0NCm1vc3RfcHJlZmVycmVkIDwtIGxhcHBseShwYXJ0d29ydGhzLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpe3doaWNoKHg9PW1heCh4KSxhcnIuaW5kID0gVCl9KQ0KbW9zdF9wcmVmZXJyZWQNCmBgYA0KDQpMYXN0bHksIHdlIGNvbXBhcmUgdGhlIHR3byBoeXBvdGhldGljYWwgcHJvZHVjdCBwcm9maWxlczogQSB2cy4gQi4gDQoNCiogQ2FtZXJhIEE6IFNEIGNhcmQsIFBsYXN0aWMgNHggWm9vbSBhbmQgcHJpY2VkIGF0IDEwMCBldXJvLiANCiogQ2FtZXJhIEI6IE1lbW9yeSBTdGljaywgUGxhc3RpYyA4eCBab29tIGFuZCBwcmljZWQgYXQgMjAwIGV1cm8uIA0KDQpgYGB7cn0NClV0aWxpdHlfQSA8LSBwYXJ0d29ydGhzJE1lbW9yeV9Gb3JtYXRbMl0gKw0KICBwYXJ0d29ydGhzJExlbnNbM10gKyANCiAgcGFydHdvcnRocyRQcmljZVsyXQ0Kc2V0TmFtZXMoVXRpbGl0eV9BLCJVdGlsaXR5X0EiKQ0KDQpVdGlsaXR5X0IgPC0gcGFydHdvcnRocyRNZW1vcnlfRm9ybWF0WzFdICsNCiAgcGFydHdvcnRocyRMZW5zWzJdICsgDQogIHBhcnR3b3J0aHMkUHJpY2VbM10NCnNldE5hbWVzKFV0aWxpdHlfQiwiVXRpbGl0eV9CIikNCmBgYA0KDQoNCg0KDQoNCg==