Results

  1. 3 models were used: xgboost, lasso regression and emsabling (stacked generalization)

  2. The xgboost model had the best performance with an RMSE score of 0.2223.

  3. It seems that the most important variables to predict the price are: the district in which the house is built and the inside and total area of a property (square meters).

  4. In the case of the inside area, there is a strong linear relationship with the price of the house. For total meters, the relationship with the outcome is quadratic (concave).

  5. The number of rooms, bathrooms and parking spaces also have an effect on the price.

  6. Although not as important as the previous variables, the words in the description of the house also have an impact. Among the most important are places (streets, neighborhoods), adjectives (fine, spectacular) and the characteristics of the house (well, parquet, mediterranean, irrigation).

Intro

I know this has been done many times, but I wanted to try to predict the price of houses in the city where I live. With that objective I did webscrapping on the page Portal Inmobiliario, which is a website where people list properties for sale or rent. The database was collected in May 2021. Only houses in the urban districts of the Metropolitan Region of Chile were considered.

Variables

We are going to start by describing our outcome variable. This is PrecioPesos which is the price of the houses in Chilean pesos.

The distribution of the variable is quite interesting, it has 3 peaks. This is because people who post prices prefer to put “pretty” numbers instead “ugly” numbers. For example, it is more common for people to list a property with a price of 100,000,000 or 50,000,000 rather than numbers like 127,699,322. This is what causes the data to have these peaks. The data is left skewed; there are more not that expensives houses than really expensives ones.

A next variable is metrosUtiles which is the inside area of the house (meters). It seems that there is a fairly strong linear relationship between it and the outcome variable.

Another important variable is the total meters of the houses, Total meters3 on the database. The total meters is the sum of the meters that are inside and outside the house. In this case there seems to be a strong quadratic relationship. The values are marginally positive up to a point where one more square meter happens to have a negative effect on the price of the house. This is possibly due to the fact that houses with many total meters tend to be in rural areas, where the price of land is lower compared to urban areas.

Let’s analyze the rest of the variables, first the bathrooms. As the number of bathrooms increases, the price of houses also increases, as can be seen in the graph.

In the case of bedrooms, it seems that houses with 1 bedroom are more expensive than those with two. But then the value seems to be increasing, until it flattens out around 6 or 7 rooms.

Regarding the number of parking spaces, it is clear that houses with only 1 parking lot have much lower prices. Then the price, as with the other variables, increases as parking spaces increase. The price seems to flatten around the 6 parking spaces. It is important to mention that there are few houses with more than 10 parking spaces in the sample.

Another important variable is the ditrict. In the graph you can see the clear differences that exist between the different districts. The red dashed line represents the median price in our sample. Most of the houses in our sample come from the 4 most exclusive districts of Santiago (Lo Barnechea, Vitacura, Las Condes, Chicureo). Looking at the graph it is clear that there are huge differences between the districts. The eight poorest districts have a median price that is not even one-eighth of the median of the richest district.

In the following 3D map we can see the median price (In millions of Chilean pesos) of the houses by district. The price is represented by the color and height of each district on the map. wealthy districts are to the northeast of the map. While the poorest districts are to the south and northwest of the map. These are the districts where, preferably, people who lived in illegal settlements in the 80’s were relocated. Finally, we have Chicureo and Colina to the north separated from the rest of the metropolitan region. The chart is interactive so it can be rotated and zoomed.

There is also a short description which was tokenized in order to find the words that have the greatest effect on house prices. In the 2 charts below, I only selected words that appeared in at least 200 house descriptions. Among the words with a higher median price there are some that are characteristics of the house such as: wine storage room cava, cinema cine,marble mármol, sauna sauna, basement subterráneo. Others represent neighborhoods (La Dehesa, El Golf) or adjectives: fine finas, spectacular espectacular, wonderful maravilloso, beautiful precioso. One word that stands out is architect, arquitecto. This word probably has a positive effect, since the architect will only be mentioned, by name, when he or she is a recognized, award winning architect. It is possible to think that these types of architects build very expensive houses. The word Mediterranean mediterránea also attracts our attention, it has a positive effect because it is in vogue, in upper-middle-class neighborhoods, to build houses in this style.

On the other hand, there are also words that are associated with low prices. Some are related to places, specifically districts and streets: Vespucio, Tobalaba, Maipú, Puente. There are 5 words that caught my attention. The first is villa, which is what a middle-class neighborhood in Chile is called. The second are the words associated with real estate such as brokerage corretaje, broker corredora. The third is pareado which means semi-detached, this is because in Chile it is very common to build semi-detached houses in middle-class neighborhoods. The fourth is pasaje alleyway, which is probably associated with the way middle-class neighborhoods are built. Fifth, locomocion, which means public transportation, it is obvious that this word is going to be linked to houses in neighborhoods where people cannot afford a car.

We have a large number of dummy variables. One that I found interesting is the variable pool. The graph has the price of the house on one axis and the inner area of the house on the other axis. The color of the hexagons represents the percentage of houses with a swimming pool. It is possible to see that the proportion of houses with a swimming pool tends to increase as the price of houses increases. Now, it is important to note that this variable also seems to have a relationship with the square meters of the inner area of the house.

Treatment of Variables

Some outliers were removed, mainly houses that belonged to rural areas (which were not of our interest), some typing errors and duplicate observations. The numerical observations were transformed to logarithms and normalized. In addition, the district variable was transformed to a numerical variable taking as a reference the median price of houses by district.

Results

We ran 3 models, one using xgboost, the second a lasso regression and an ensabled of both models. The best model was the xgboost one. These were the results:

If we look at the most important variables we have the district (comuna2), this is explained because this variable contains many components within it, mainly access to services and public goods such as: hospitals, parks, schools; and other very important features such as security.

The second most important variable is total meters (metrosTotales3_poly_1 and metrosTotales3_poly_2) and the meters of the inner area of the house metrosUtiles. Which makes sense because one would expect that the bigger the house, the higher the price. The interesting thing is that the total meters have a concave quadratic relationship, which may be due to the fact that houses that have a very large area of land are located in more rural areas where the price of land is lower, which causes this relationship.

After these variables, the most important are the number of bathrooms baños2, the existence of a pool piscina, the number of bedrooms dormitorios2 and the number of parking spaces parking20

Although text on the description was not an important variable in the xgboost model, it was important in the lasso model. Here are a list of the words that were the most important:

Among the words with a positive effect we have places such as: the districts of Quilicura, Providencia, condes (Las Condes) and neighborhoods such as damián (San Damián) and golf (El Golf). The fact that Quilicura has a positive effect takes us by surprise since it is not a wealthy district. Verbo is there because of the Verbo Divino school, which is one of the most exclusive educational establishments in Santiago. Other words with a positive effect are: the adjectives spectacular espectacular and fine fina, the presence of parquet in the houses, when the houses are built in a mediterranean mediterránea style and, finally, the word easybroker which is probably a real state company.

Among the words with a negative effect we have Chicureo, which is curious because it is one of the richest districts in Santiago. The explanation is that since most of the sample comes from the four richest districts (Lo Barnechea, Vitacura, Las Condes and Chicureo), Chicureo having the lowest median price in this group has a negative effect on the total sample. Chamisero is a street in Chicureo therefore that is the reason why this word also has a negative effect.

Other words like irrigation, well and wood stove are signs of rurality so may explain the effect they have. The last words are schools colegios and cash contado. About these, it is a bit difficult to find a clear reason for the negative effect. It may be that when prices are not expensive, sellers ask for cash payment. schools, may have a negative effect because when the schools around a property are not well known, people only mention the word “school” instead of the name of the school, as happens with the well known private school, such Verbo Divino.

Here are the results for all models:

Final Thoughts

First of all, I think it is important to point out that important considerations must be taken when analyzing these results, since the bulk of the houses in our sample come from well-to-do neighborhoods. If we had a more balanced sample, perhaps the results would be different. Here is a chart with the number of houses by district.

Considering what I just mentioned, the district is the variable that helps to better predict the price of the house. It is interesting to note how those districts that received the most relocated families in the 80’s are those with the lowest prices. The importance of the inner and total meters does not surprise us, what we do consider surprising is the quadratic relationship between the price of the house and the total meters of the home.

I think it is still pending to run a model with pairs of words, binomials, instead of just using single words. I think that despite the good results of the models, there is room to improve performance, it would be helpful to have servers to better train the data.

LS0tDQp0aXRsZTogIlByZWRpY3RpbmcgdGhlIFByaWNlIG9mIEhvdXNlcyBpbiBTYW50aWFnbyBkZSBDaGlsZSINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgdGhlbWU6IHVuaXRlZA0KICAgIHRvYzogeWVzDQotLS0NCjxzdHlsZT4NCg0KYm9keXsNCiB0ZXh0LWFsaWduOiBqdXN0aWZ5Ow0KfQ0KDQo8L3N0eWxlPg0KDQojIyBSZXN1bHRzDQoNCjEpIDMgbW9kZWxzIHdlcmUgdXNlZDogeGdib29zdCwgbGFzc28gcmVncmVzc2lvbiBhbmQgZW1zYWJsaW5nICgqc3RhY2tlZCBnZW5lcmFsaXphdGlvbiopDQoNCjIpIFRoZSB4Z2Jvb3N0IG1vZGVsIGhhZCB0aGUgYmVzdCBwZXJmb3JtYW5jZSB3aXRoIGFuIFJNU0Ugc2NvcmUgb2YgMC4yMjIzLg0KDQozKSBJdCBzZWVtcyB0aGF0IHRoZSBtb3N0IGltcG9ydGFudCB2YXJpYWJsZXMgdG8gcHJlZGljdCB0aGUgcHJpY2UgYXJlOiB0aGUgZGlzdHJpY3QgaW4gd2hpY2ggdGhlIGhvdXNlIGlzIGJ1aWx0IGFuZCB0aGUgaW5zaWRlIGFuZCB0b3RhbCBhcmVhIG9mIGEgcHJvcGVydHkgKHNxdWFyZSBtZXRlcnMpLg0KDQo0KSBJbiB0aGUgY2FzZSBvZiB0aGUgaW5zaWRlIGFyZWEsIHRoZXJlIGlzIGEgc3Ryb25nIGxpbmVhciByZWxhdGlvbnNoaXAgd2l0aCB0aGUgcHJpY2Ugb2YgdGhlIGhvdXNlLiBGb3IgdG90YWwgbWV0ZXJzLCB0aGUgcmVsYXRpb25zaGlwIHdpdGggdGhlICpvdXRjb21lKiBpcyBxdWFkcmF0aWMgKGNvbmNhdmUpLg0KDQo1KSBUaGUgbnVtYmVyIG9mIHJvb21zLCBiYXRocm9vbXMgYW5kIHBhcmtpbmcgc3BhY2VzIGFsc28gaGF2ZSBhbiBlZmZlY3Qgb24gdGhlIHByaWNlLg0KDQo2KSBBbHRob3VnaCBub3QgYXMgaW1wb3J0YW50IGFzIHRoZSBwcmV2aW91cyB2YXJpYWJsZXMsIHRoZSB3b3JkcyBpbiB0aGUgZGVzY3JpcHRpb24gb2YgdGhlIGhvdXNlIGFsc28gaGF2ZSBhbiBpbXBhY3QuIEFtb25nIHRoZSBtb3N0IGltcG9ydGFudCBhcmUgcGxhY2VzIChzdHJlZXRzLCBuZWlnaGJvcmhvb2RzKSwgYWRqZWN0aXZlcyAoZmluZSwgc3BlY3RhY3VsYXIpIGFuZCB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBob3VzZSAod2VsbCwgcGFycXVldCwgbWVkaXRlcnJhbmVhbiwgaXJyaWdhdGlvbikuIA0KDQoNCg0KIyMgSW50cm8NCg0KIVtdKGh0dHBzOi8vY2dwYXJvZGkuY2wvd3AtY29udGVudC91cGxvYWRzLzIwMTgvMDUvcG9ydGFsLWNvbXByZXNzb3IucG5nKQ0KDQpJIGtub3cgdGhpcyBoYXMgYmVlbiBkb25lIG1hbnkgdGltZXMsIGJ1dCBJIHdhbnRlZCB0byB0cnkgdG8gcHJlZGljdCB0aGUgcHJpY2Ugb2YgaG91c2VzIGluIHRoZSBjaXR5IHdoZXJlIEkgbGl2ZS4gV2l0aCB0aGF0IG9iamVjdGl2ZSBJIGRpZCB3ZWJzY3JhcHBpbmcgb24gdGhlIHBhZ2UgW1BvcnRhbCBJbm1vYmlsaWFyaW9dKGh0dHBzOi8vd3d3LnBvcnRhbGlubW9iaWxpYXJpby5jb20vKSwNCndoaWNoIGlzIGEgd2Vic2l0ZSB3aGVyZSBwZW9wbGUgbGlzdCAgcHJvcGVydGllcyBmb3Igc2FsZSBvciByZW50LiBUaGUgZGF0YWJhc2Ugd2FzIGNvbGxlY3RlZCBpbiBNYXkgMjAyMS4gT25seSBob3VzZXMgaW4gdGhlIHVyYmFuIGRpc3RyaWN0cyBvZiB0aGUgTWV0cm9wb2xpdGFuIFJlZ2lvbiBvZiBDaGlsZSB3ZXJlIGNvbnNpZGVyZWQuDQoNCiMjIFZhcmlhYmxlcw0KDQpXZSBhcmUgZ29pbmcgdG8gc3RhcnQgYnkgZGVzY3JpYmluZyBvdXIgb3V0Y29tZSB2YXJpYWJsZS4gVGhpcyBpcyAqKlByZWNpb1Blc29zKiogd2hpY2ggaXMgdGhlIHByaWNlIG9mIHRoZSBob3VzZXMgaW4gQ2hpbGVhbiBwZXNvcy4NCg0KDQpgYGB7cixlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRSxmaWcud2lkdGg9Ny41LCBmaWcuaGVpZ2h0PTQuMn0NCg0KZGVuc2l0eSA8LSBkZW5zaXR5KHBvcnRhbDQkcHJlY2lvUGVzb3MpDQoNCnBsb3RfbHkob3BhY2l0eT0wLjUpICU+JSANCiAgYWRkX2xpbmVzKHg9fmRlbnNpdHkkeCx5PX5kZW5zaXR5JHkpICU+JSANCmxheW91dCh0aXRsZSA9ICdEZW5zaXR5IERpc3RyaWJ1dGlvbicsDQogICAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJIb3VzZSBQcmljZSAoQ2hpbGVhbiBQZXNvcykiKSwNCiAgICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gImRlbnNpdHkiKSkNCmBgYA0KDQoNClRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHZhcmlhYmxlIGlzIHF1aXRlIGludGVyZXN0aW5nLCBpdCBoYXMgMyBwZWFrcy4gVGhpcyBpcyBiZWNhdXNlIHBlb3BsZSB3aG8gcG9zdCBwcmljZXMgcHJlZmVyIHRvIHB1dCAqInByZXR0eSIqIG51bWJlcnMgaW5zdGVhZCAqInVnbHkiKiBudW1iZXJzLiBGb3IgZXhhbXBsZSwgaXQgaXMgbW9yZSBjb21tb24gZm9yIHBlb3BsZSB0byBsaXN0IGEgcHJvcGVydHkgd2l0aCBhIHByaWNlIG9mIDEwMCwwMDAsMDAwIG9yIDUwLDAwMCwwMDAgcmF0aGVyIHRoYW4gbnVtYmVycyBsaWtlIDEyNyw2OTksMzIyLiBUaGlzIGlzIHdoYXQgY2F1c2VzIHRoZSBkYXRhIHRvIGhhdmUgdGhlc2UgcGVha3MuIFRoZSBkYXRhIGlzIGxlZnQgc2tld2VkOyB0aGVyZSBhcmUgbW9yZSAqbm90IHRoYXQgZXhwZW5zaXZlcyogaG91c2VzIHRoYW4gKnJlYWxseSBleHBlbnNpdmVzKiBvbmVzLiANCg0KQSBuZXh0IHZhcmlhYmxlIGlzICoqbWV0cm9zVXRpbGVzKiogd2hpY2ggaXMgdGhlIGluc2lkZSBhcmVhIG9mIHRoZSBob3VzZSAobWV0ZXJzKS4gSXQgc2VlbXMgdGhhdCB0aGVyZSBpcyBhIGZhaXJseSBzdHJvbmcgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGl0IGFuZCB0aGUgb3V0Y29tZSB2YXJpYWJsZS4NCg0KDQpgYGB7cixlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRSxmaWcud2lkdGg9Ny41LCBmaWcuaGVpZ2h0PTQuMn0NCg0KbTE8LWxtKGxvZyhwcmVjaW9QZXNvcykgfiBsb2cobWV0cm9zVXRpbGVzKSxkYXRhPSBwb3J0YWwzKQ0KDQoNCmZpZyA8LXBsb3RfbHkoZGF0YSA9IHBvcnRhbDMsIHggPSB+bG9nKG1ldHJvc1V0aWxlcyksIHkgPSB+bG9nKHByZWNpb1Blc29zKSkNCg0KZmlnICU+JSBsYXlvdXQodGl0bGUgPSAnU3F1YXJlIEZlZXQgdnMgSG91c2UgUHJpY2UnLA0KICAgICAgICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkxvZyhIb3VzZSBQcmljZSkiKSwNCiAgICAgICAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJMb2coU3F1YXJlIEZlZXQpIikpICU+JQ0KICBhZGRfbWFya2VycyhzaG93bGVnZW5kID0gRkFMU0UpJT4lDQogIGFkZF9saW5lcyh5ID0gfmZpdHRlZChtMSksbmFtZSA9IlBvbHlub21pYWwiKQ0KDQpgYGANCg0KQW5vdGhlciBpbXBvcnRhbnQgdmFyaWFibGUgaXMgdGhlIHRvdGFsIG1ldGVycyBvZiB0aGUgaG91c2VzLCAqKlRvdGFsIG1ldGVyczMqKiBvbiB0aGUgZGF0YWJhc2UuIFRoZSB0b3RhbCBtZXRlcnMgaXMgdGhlIHN1bSBvZiB0aGUgbWV0ZXJzIHRoYXQgYXJlIGluc2lkZSBhbmQgb3V0c2lkZSB0aGUgaG91c2UuIEluIHRoaXMgY2FzZSB0aGVyZSBzZWVtcyB0byBiZSBhIHN0cm9uZyBxdWFkcmF0aWMgcmVsYXRpb25zaGlwLiBUaGUgdmFsdWVzIGFyZSBtYXJnaW5hbGx5IHBvc2l0aXZlIHVwIHRvIGEgcG9pbnQgd2hlcmUgb25lIG1vcmUgc3F1YXJlIG1ldGVyIGhhcHBlbnMgdG8gaGF2ZSBhIG5lZ2F0aXZlIGVmZmVjdCBvbiB0aGUgcHJpY2Ugb2YgdGhlIGhvdXNlLiBUaGlzIGlzIHBvc3NpYmx5IGR1ZSB0byB0aGUgZmFjdCB0aGF0IGhvdXNlcyB3aXRoIG1hbnkgdG90YWwgbWV0ZXJzIHRlbmQgdG8gYmUgaW4gcnVyYWwgYXJlYXMsIHdoZXJlIHRoZSBwcmljZSBvZiBsYW5kIGlzIGxvd2VyIGNvbXBhcmVkIHRvIHVyYmFuIGFyZWFzLiANCg0KYGBge3IsZWNobz1GQUxTRSx3YXJuaW5nPUZBTFNFLGZpZy53aWR0aD03LjUsIGZpZy5oZWlnaHQ9NC4yfQ0KDQptMTwtbG0obG9nKHByZWNpb1Blc29zKSB+IHBvbHkobG9nKG1ldHJvc1RvdGFsZXMzKSwyKSxkYXRhPSBwb3J0YWwzKQ0KDQoNCmZpZyA8LXBsb3RfbHkoZGF0YSA9IHBvcnRhbDMsIHggPSB+bG9nKG1ldHJvc1RvdGFsZXMzKSwgeSA9IH5sb2cocHJlY2lvUGVzb3MpKQ0KDQpmaWcgJT4lIGxheW91dCh0aXRsZSA9ICdUb3RhbCBTcXVhcmUgRmVldCB2cyBIb3VzZSBQcmljZScsDQogICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiTG9nKEhvdXNlIFByaWNlKSIpLA0KICAgICAgICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIiBMb2coVG90YWwgU3F1YXJlIEZlZXQpIikpICU+JQ0KICBhZGRfbWFya2VycyhzaG93bGVnZW5kID0gRkFMU0UpJT4lDQogIGFkZF9saW5lcyh5ID0gfmZpdHRlZChtMSksbmFtZSA9IlBvbHlub21pYWwiKQ0KYGBgICAgICAgICAgICANCg0KTGV0J3MgYW5hbHl6ZSB0aGUgcmVzdCBvZiB0aGUgdmFyaWFibGVzLCBmaXJzdCB0aGUgYmF0aHJvb21zLiBBcyB0aGUgbnVtYmVyIG9mIGJhdGhyb29tcyBpbmNyZWFzZXMsIHRoZSBwcmljZSBvZiBob3VzZXMgYWxzbyBpbmNyZWFzZXMsIGFzIGNhbiBiZSBzZWVuIGluIHRoZSBncmFwaC4NCg0KYGBge3IsZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFfQ0KDQpwb3J0YWwzICU+JSANCiAgZ2dwbG90KGFlcyh4PShmY3RfcmVsZXZlbChhcy5jaGFyYWN0ZXIoYmHDsW9zMiksIjEwIiwgYWZ0ZXIgPSBJbmYpKSx5PWxvZyhwcmVjaW9QZXNvcyksIGZpbGw9YXMuZmFjdG9yKGJhw7FvczIpKSkrZ2VvbV9ib3hwbG90KCkrDQogICAgc2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVFJVRSwgYWxwaGE9MC42KSArDQpsYWJzKHg9Ik51bWJlciBvZiBCYXRocm9vbXMiLCB5PSJMb2coSG91c2UgUHJpY2UpIiwNCiAgICAgdGl0bGU9Ik51bWJlciBvZiBCYXRocm9vbXMgVnMuIEhvdXNlIFByaWNlIikrIA0KICB0aGVtZV9pcHN1bV9yYygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCg0KDQpgYGANCg0KDQpJbiB0aGUgY2FzZSBvZiBiZWRyb29tcywgaXQgc2VlbXMgdGhhdCBob3VzZXMgd2l0aCAxIGJlZHJvb20gYXJlIG1vcmUgZXhwZW5zaXZlIHRoYW4gdGhvc2Ugd2l0aCB0d28uIEJ1dCB0aGVuIHRoZSB2YWx1ZSBzZWVtcyB0byBiZSBpbmNyZWFzaW5nLCB1bnRpbCBpdCBmbGF0dGVucyBvdXQgYXJvdW5kIDYgb3IgNyByb29tcy4NCg0KYGBge3IsZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFfQ0KDQpwb3J0YWwzICU+JSANCiAgZ2dwbG90KGFlcyh4PShmY3RfcmVsZXZlbChhcy5jaGFyYWN0ZXIoZG9ybWl0b3Jpb3MyKSwiMTAiLCIxMSIsIjEyIixhZnRlciA9IEluZikpLHk9bG9nKHByZWNpb1Blc29zKSxmaWxsPWFzLmZhY3Rvcihkb3JtaXRvcmlvczIpKSkrZ2VvbV9ib3hwbG90KCkrDQogICAgICBzY2FsZV9maWxsX3ZpcmlkaXMoZGlzY3JldGUgPSBUUlVFLCBhbHBoYT0wLjYpICsNCmxhYnMoeD0iTnVtYmVyIG9mIEJlZHJvb21zIiwgeT0iTG9nIChIb3VzZSBQcmljZSkiLA0KICAgICB0aXRsZT0iTnVtYmVyIG9mIEJlZHJvb21zIFZzLiBIb3VzZSBQcmljZSIpKyANCiAgdGhlbWVfaXBzdW1fcmMoKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQoNCmBgYA0KDQpSZWdhcmRpbmcgdGhlIG51bWJlciBvZiBwYXJraW5nIHNwYWNlcywgaXQgaXMgY2xlYXIgdGhhdCBob3VzZXMgd2l0aCBvbmx5IDEgcGFya2luZyBsb3QgaGF2ZSBtdWNoIGxvd2VyIHByaWNlcy4gVGhlbiB0aGUgcHJpY2UsIGFzIHdpdGggdGhlIG90aGVyIHZhcmlhYmxlcywgaW5jcmVhc2VzIGFzIHBhcmtpbmcgc3BhY2VzIGluY3JlYXNlLiBUaGUgcHJpY2Ugc2VlbXMgdG8gZmxhdHRlbiBhcm91bmQgdGhlIDYgcGFya2luZyBzcGFjZXMuIEl0IGlzIGltcG9ydGFudCB0byBtZW50aW9uIHRoYXQgdGhlcmUgYXJlIGZldyBob3VzZXMgd2l0aCBtb3JlIHRoYW4gMTAgcGFya2luZyBzcGFjZXMgaW4gdGhlIHNhbXBsZS4NCg0KDQpgYGB7cixlY2hvPUZBTFNFLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRX0NCg0KcG9ydGFsMyAlPiUgDQogIGdncGxvdChhZXMoeD0oZmN0X3JlbGV2ZWwoYXMuY2hhcmFjdGVyKHBhcmtpbmcyMCksIjEwIiwiMTEiLCIxMiIsIjEzIiwiMTQiLCIxNSIsIjE2IiwiMTciLCIxOCIsIjE5IiwiMjAiLCIyMiIsIjI1IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMzAiLCIzOSIsYWZ0ZXIgPSBJbmYpKSx5PWxvZyhwcmVjaW9QZXNvcyksZmlsbD1hcy5mYWN0b3IocGFya2luZzIwKSkpK2dlb21fYm94cGxvdCgpKw0KICBzY2FsZV9maWxsX3ZpcmlkaXMoZGlzY3JldGUgPSBUUlVFLCBhbHBoYT0wLjYpICsNCiAgbGFicyh4PSJOdW1iZXIgb2YgUGFya2luZyBQbGFjZXMiLCB5PSJMb2coSG91c2UgUHJpY2UpIiwNCiAgICAgICB0aXRsZT0iTnVtYmVyIG9mIFBhcmtpbmcgUGxhY2VzIFZzLiBIb3VzZSBQcmljZSIpKyANCiAgdGhlbWVfaXBzdW1fcmMoKSsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQpgYGANCg0KDQoNCkFub3RoZXIgaW1wb3J0YW50IHZhcmlhYmxlIGlzIHRoZSBkaXRyaWN0LiBJbiB0aGUgZ3JhcGggeW91IGNhbiBzZWUgdGhlIGNsZWFyIGRpZmZlcmVuY2VzIHRoYXQgZXhpc3QgYmV0d2VlbiB0aGUgZGlmZmVyZW50IGRpc3RyaWN0cy4gVGhlIHJlZCBkYXNoZWQgbGluZSByZXByZXNlbnRzIHRoZSBtZWRpYW4gcHJpY2UgaW4gb3VyIHNhbXBsZS4gTW9zdCBvZiB0aGUgaG91c2VzIGluIG91ciBzYW1wbGUgY29tZSBmcm9tIHRoZSA0IG1vc3QgZXhjbHVzaXZlIGRpc3RyaWN0cyBvZiBTYW50aWFnbyAoTG8gQmFybmVjaGVhLCBWaXRhY3VyYSwgTGFzIENvbmRlcywgQ2hpY3VyZW8pLiBMb29raW5nIGF0IHRoZSBncmFwaCBpdCBpcyBjbGVhciB0aGF0IHRoZXJlIGFyZSBodWdlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGRpc3RyaWN0cy4gVGhlIGVpZ2h0IHBvb3Jlc3QgZGlzdHJpY3RzIGhhdmUgYSBtZWRpYW4gcHJpY2UgdGhhdCBpcyBub3QgZXZlbiBvbmUtZWlnaHRoIG9mIHRoZSBtZWRpYW4gb2YgdGhlIHJpY2hlc3QgZGlzdHJpY3QuDQoNCg0KDQpgYGB7cixlY2hvPUZBTFNFLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1UUlVFfQ0KDQoNCnBvcnRhbDMlPiUgZ3JvdXBfYnkoY29tdW5hKSAlPiUgc3VtbWFyaXNlKHByZWNpb1Blc29zPW1lZGlhbihwcmVjaW9QZXNvcykpICU+JSANCiAgZ2dwbG90KGFlcyh4PWZjdF9yZW9yZGVyKGNvbXVuYSxwcmVjaW9QZXNvcyksIHk9cHJlY2lvUGVzb3MpKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgZmlsbD0iI2Y2ODA2MCIsIGFscGhhPS42KSArDQogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPSBzZXEoMCw4MDAwMDAwMDAwICwgYnk9MTAwMDAwMDAwKSwgbGFiZWxzID0gY29tbWEpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PSA0ODQ3MDU4ODIsIGxpbmV0eXBlPSJkYXNoZWQiLCBjb2xvciA9ICJyZWQiKSsNCmxhYnMoeD0iRGlzdHJpY3QiLCB5PSIgTWVkaWFuIEhvdXNlIFByaWNlIiwNCiAgICAgdGl0bGU9IkhvdXNlIFByaWNlIE1lZGlhbiBCeSBEaXN0cmljdCIpK3RoZW1lX2xpZ2h0KCkrDQogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KYGBgDQoNCkluIHRoZSBmb2xsb3dpbmcgM0QgbWFwIHdlIGNhbiBzZWUgdGhlIG1lZGlhbiBwcmljZSAoSW4gbWlsbGlvbnMgb2YgQ2hpbGVhbiBwZXNvcykgb2YgdGhlIGhvdXNlcyBieSBkaXN0cmljdC4gVGhlIHByaWNlIGlzIHJlcHJlc2VudGVkIGJ5IHRoZSBjb2xvciBhbmQgaGVpZ2h0IG9mIGVhY2ggZGlzdHJpY3Qgb24gdGhlIG1hcC4gd2VhbHRoeSBkaXN0cmljdHMgYXJlIHRvIHRoZSBub3J0aGVhc3Qgb2YgdGhlIG1hcC4gV2hpbGUgdGhlIHBvb3Jlc3QgZGlzdHJpY3RzIGFyZSB0byB0aGUgc291dGggYW5kIG5vcnRod2VzdCBvZiB0aGUgbWFwLiBUaGVzZSBhcmUgdGhlIGRpc3RyaWN0cyB3aGVyZSwgcHJlZmVyYWJseSwgcGVvcGxlIHdobyBsaXZlZCBpbiBpbGxlZ2FsIHNldHRsZW1lbnRzIGluIHRoZSA4MCdzIHdlcmUgcmVsb2NhdGVkLiBGaW5hbGx5LCB3ZSBoYXZlIENoaWN1cmVvIGFuZCBDb2xpbmEgdG8gdGhlIG5vcnRoIHNlcGFyYXRlZCBmcm9tIHRoZSByZXN0IG9mIHRoZSBtZXRyb3BvbGl0YW4gcmVnaW9uLiBUaGUgY2hhcnQgaXMgaW50ZXJhY3RpdmUgc28gaXQgY2FuIGJlIHJvdGF0ZWQgYW5kIHpvb21lZC4NCg0KDQoNCmBgYHtyLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSxmaWcud2lkdGg9Ny41LCBmaWcuaGVpZ2h0PTQuMix3YXJuaW5nPUZBTFNFfQ0KDQpwbG90X2dnKGdyYWZpY28sem9vbSA9IDAuNSx3aWR0aD03LGhlaWdodD01KQ0KDQpyZ2w6OnJnbHdpZGdldCgpDQoNCmBgYA0KDQoNClRoZXJlIGlzIGFsc28gYSBzaG9ydCBkZXNjcmlwdGlvbiB3aGljaCB3YXMgKnRva2VuaXplZCogaW4gb3JkZXIgdG8gZmluZCB0aGUgd29yZHMgdGhhdCBoYXZlIHRoZSBncmVhdGVzdCBlZmZlY3Qgb24gaG91c2UgcHJpY2VzLiBJbiB0aGUgMiBjaGFydHMgYmVsb3csIEkgb25seSBzZWxlY3RlZCB3b3JkcyB0aGF0IGFwcGVhcmVkIGluIGF0IGxlYXN0IDIwMCBob3VzZSBkZXNjcmlwdGlvbnMuIEFtb25nIHRoZSB3b3JkcyB3aXRoIGEgaGlnaGVyIG1lZGlhbiBwcmljZSB0aGVyZSBhcmUgc29tZSB0aGF0IGFyZSBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIGhvdXNlIHN1Y2ggYXM6IHdpbmUgc3RvcmFnZSByb29tICoqY2F2YSoqLCBjaW5lbWEgKipjaW5lKiosbWFyYmxlICoqbcOhcm1vbCoqLCBzYXVuYSAqKnNhdW5hKiosIGJhc2VtZW50ICoqc3VidGVycsOhbmVvKiouIE90aGVycyByZXByZXNlbnQgbmVpZ2hib3Job29kcyAoTGEgRGVoZXNhLCBFbCBHb2xmKSBvciBhZGplY3RpdmVzOiBmaW5lICoqZmluYXMqKiwgc3BlY3RhY3VsYXIgKiplc3BlY3RhY3VsYXIqKiwgd29uZGVyZnVsICoqbWFyYXZpbGxvc28qKiwgYmVhdXRpZnVsICoqcHJlY2lvc28qKi4gT25lIHdvcmQgdGhhdCBzdGFuZHMgb3V0IGlzIGFyY2hpdGVjdCwgKiphcnF1aXRlY3RvKiouIFRoaXMgd29yZCBwcm9iYWJseSBoYXMgYSBwb3NpdGl2ZSBlZmZlY3QsIHNpbmNlIHRoZSBhcmNoaXRlY3Qgd2lsbCBvbmx5IGJlIG1lbnRpb25lZCwgYnkgbmFtZSwgd2hlbiBoZSBvciBzaGUgaXMgYSByZWNvZ25pemVkLCBhd2FyZCB3aW5uaW5nIGFyY2hpdGVjdC4gSXQgaXMgcG9zc2libGUgdG8gdGhpbmsgdGhhdCB0aGVzZSB0eXBlcyBvZiBhcmNoaXRlY3RzIGJ1aWxkIHZlcnkgZXhwZW5zaXZlIGhvdXNlcy4gVGhlIHdvcmQgTWVkaXRlcnJhbmVhbiAqKm1lZGl0ZXJyw6FuZWEqKiBhbHNvIGF0dHJhY3RzIG91ciBhdHRlbnRpb24sIGl0IGhhcyBhIHBvc2l0aXZlIGVmZmVjdCBiZWNhdXNlIGl0IGlzIGluIHZvZ3VlLCBpbiB1cHBlci1taWRkbGUtY2xhc3MgbmVpZ2hib3Job29kcywgdG8gYnVpbGQgaG91c2VzIGluIHRoaXMgc3R5bGUuDQoNCg0KYGBge3IsZWNobz1GQUxTRX0NCg0KcG9ydGFsMyAlPiUNCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCBkYXRvczQpICU+JQ0KICBncm91cF9ieSh3b3JkKSAlPiUNCiAgc3VtbWFyaXplKGF2Z19wcmljZT1sb2cobWVkaWFuKHByZWNpb1Blc29zKSksbj1uKCkpICU+JSBmaWx0ZXIobj4yMDApJT4lIGFycmFuZ2UoZGVzYyhhdmdfcHJpY2UpKSAlPiUgDQogIGhlYWQoMjUpICU+JQ0KICBtdXRhdGUod29yZCA9IGZjdF9yZW9yZGVyKHdvcmQsIGF2Z19wcmljZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKGF2Z19wcmljZSwgd29yZCxzaXplID0gbikpICsNCiAgZ2VvbV9wb2ludChjb2xvcj0ib3JhbmdlIixhbHBoYT0wLjcpKw0KICB0aGVtZV9idygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpK2dndGl0bGUoIldvcmRzIEFzc29jaWF0ZWQgd2l0aCB0aGUgSGlnaGVzdCBNZWFuIFByaWNlcyIpDQogIA0KYGBgDQoNCg0KDQpPbiB0aGUgb3RoZXIgaGFuZCwgdGhlcmUgYXJlIGFsc28gd29yZHMgdGhhdCBhcmUgYXNzb2NpYXRlZCB3aXRoIGxvdyBwcmljZXMuIFNvbWUgYXJlIHJlbGF0ZWQgdG8gcGxhY2VzLCBzcGVjaWZpY2FsbHkgZGlzdHJpY3RzIGFuZCBzdHJlZXRzOiBWZXNwdWNpbywgVG9iYWxhYmEsIE1haXDDuiwgUHVlbnRlLiBUaGVyZSBhcmUgNSB3b3JkcyB0aGF0IGNhdWdodCBteSBhdHRlbnRpb24uIFRoZSBmaXJzdCBpcyAqKnZpbGxhKiosIHdoaWNoIGlzIHdoYXQgYSBtaWRkbGUtY2xhc3MgbmVpZ2hib3Job29kIGluIENoaWxlIGlzIGNhbGxlZC4gVGhlIHNlY29uZCBhcmUgdGhlIHdvcmRzIGFzc29jaWF0ZWQgd2l0aCByZWFsIGVzdGF0ZSBzdWNoIGFzIGJyb2tlcmFnZSAqKmNvcnJldGFqZSoqLCBicm9rZXIgKipjb3JyZWRvcmEqKi4gVGhlIHRoaXJkIGlzICoqcGFyZWFkbyoqIHdoaWNoIG1lYW5zIHNlbWktZGV0YWNoZWQsIHRoaXMgaXMgYmVjYXVzZSBpbiBDaGlsZSBpdCBpcyB2ZXJ5IGNvbW1vbiB0byBidWlsZCBzZW1pLWRldGFjaGVkIGhvdXNlcyBpbiBtaWRkbGUtY2xhc3MgbmVpZ2hib3Job29kcy4gVGhlIGZvdXJ0aCBpcyAqKnBhc2FqZSoqIGFsbGV5d2F5LCB3aGljaCBpcyBwcm9iYWJseSBhc3NvY2lhdGVkIHdpdGggdGhlIHdheSBtaWRkbGUtY2xhc3MgbmVpZ2hib3Job29kcyBhcmUgYnVpbHQuIEZpZnRoLCAqKmxvY29tb2Npb24qKiwgd2hpY2ggbWVhbnMgcHVibGljIHRyYW5zcG9ydGF0aW9uLCBpdCBpcyBvYnZpb3VzIHRoYXQgdGhpcyB3b3JkIGlzIGdvaW5nIHRvIGJlIGxpbmtlZCB0byBob3VzZXMgaW4gbmVpZ2hib3Job29kcyB3aGVyZSBwZW9wbGUgY2Fubm90IGFmZm9yZCBhIGNhci4NCg0KYGBge3IsZWNobz1GQUxTRX0NCg0KcG9ydGFsMyAlPiUNCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCBkYXRvczQpICU+JQ0KICBncm91cF9ieSh3b3JkKSAlPiUNCiAgc3VtbWFyaXplKGF2Z19wcmljZT1sb2cobWVkaWFuKHByZWNpb1Blc29zKSksbj1uKCkpICU+JSBmaWx0ZXIobj4yMDApJT4lIGFycmFuZ2UoZGVzYyhhdmdfcHJpY2UpKSAlPiUgDQogIHRhaWwoMjUpICU+JQ0KICBtdXRhdGUod29yZCA9IGZjdF9yZW9yZGVyKHdvcmQsIGF2Z19wcmljZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKGF2Z19wcmljZSwgd29yZCxzaXplID0gbikpICsNCiAgZ2VvbV9wb2ludChjb2xvcj0ib3JhbmdlIixhbHBoYT0wLjcpKw0KICB0aGVtZV9idygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpK2dndGl0bGUoIldvcmRzIEFzc29jaWF0ZWQgd2l0aCB0aGUgTG93ZXN0IE1lYW4gUHJpY2VzIikNCiAgDQpgYGANCg0KV2UgaGF2ZSBhIGxhcmdlIG51bWJlciBvZiBkdW1teSB2YXJpYWJsZXMuIE9uZSB0aGF0IEkgZm91bmQgaW50ZXJlc3RpbmcgaXMgdGhlIHZhcmlhYmxlIHBvb2wuIFRoZSBncmFwaCBoYXMgdGhlIHByaWNlIG9mIHRoZSBob3VzZSBvbiBvbmUgYXhpcyBhbmQgdGhlIGlubmVyIGFyZWEgb2YgdGhlIGhvdXNlIG9uIHRoZSBvdGhlciBheGlzLiBUaGUgY29sb3Igb2YgdGhlIGhleGFnb25zIHJlcHJlc2VudHMgdGhlIHBlcmNlbnRhZ2Ugb2YgaG91c2VzIHdpdGggYSBzd2ltbWluZyBwb29sLiBJdCBpcyBwb3NzaWJsZSB0byBzZWUgdGhhdCB0aGUgcHJvcG9ydGlvbiBvZiBob3VzZXMgd2l0aCBhIHN3aW1taW5nIHBvb2wgdGVuZHMgdG8gaW5jcmVhc2UgYXMgdGhlIHByaWNlIG9mIGhvdXNlcyBpbmNyZWFzZXMuIE5vdywgaXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCB0aGlzIHZhcmlhYmxlIGFsc28gc2VlbXMgdG8gaGF2ZSBhIHJlbGF0aW9uc2hpcCB3aXRoIHRoZSBzcXVhcmUgbWV0ZXJzIG9mIHRoZSBpbm5lciBhcmVhIG9mIHRoZSBob3VzZS4NCg0KYGBge3IsZWNobz1GQUxTRSx3YXJuaW5nPUZBTFNFfQ0KcG9ydGFsMyAlPiUNCiAgZ2dwbG90KGFlcyhsb2cobWV0cm9zVXRpbGVzKSwgbG9nKHByZWNpb1Blc29zKSwgeiA9IHBpc2NpbmEpKSArDQogIHN0YXRfc3VtbWFyeV9oZXgoYWxwaGEgPSAwLjgsIGJpbnMgPSAyMCkgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXNfYyhsYWJlbHMgPSBwZXJjZW50KSArDQpsYWJzKHg9IkxvZyhTcXVhcmUgRmVldHMpIiwgeT0iTG9nKEhvdXNlIFByaWNlKSIsDQogICAgIHRpdGxlPSIlIE9mIEhvdXNlcyB3aXRoIFBvb2wgYnkgU3F1YXJlIEZlZXQgYW5kIFByaWNlIikrDQogIGxhYnMoZmlsbCA9ICIlIHBvb2wiKSsNCiAgdGhlbWVfYncoKQ0KYGBgDQoNCg0KIyMgVHJlYXRtZW50IG9mIFZhcmlhYmxlcw0KICAgICAgICAgICANClNvbWUgb3V0bGllcnMgd2VyZSByZW1vdmVkLCBtYWlubHkgaG91c2VzIHRoYXQgYmVsb25nZWQgdG8gcnVyYWwgYXJlYXMgKHdoaWNoIHdlcmUgbm90IG9mIG91ciBpbnRlcmVzdCksIHNvbWUgdHlwaW5nIGVycm9ycyBhbmQgZHVwbGljYXRlIG9ic2VydmF0aW9ucy4gVGhlIG51bWVyaWNhbCBvYnNlcnZhdGlvbnMgd2VyZSB0cmFuc2Zvcm1lZCB0byBsb2dhcml0aG1zIGFuZCBub3JtYWxpemVkLiBJbiBhZGRpdGlvbiwgdGhlIGRpc3RyaWN0IHZhcmlhYmxlIHdhcyB0cmFuc2Zvcm1lZCB0byBhIG51bWVyaWNhbCB2YXJpYWJsZSB0YWtpbmcgYXMgYSByZWZlcmVuY2UgdGhlIG1lZGlhbiBwcmljZSBvZiBob3VzZXMgYnkgZGlzdHJpY3QuDQoNCiMjIFJlc3VsdHMNCg0KV2UgcmFuIDMgbW9kZWxzLCBvbmUgdXNpbmcgeGdib29zdCwgdGhlIHNlY29uZCBhIGxhc3NvIHJlZ3Jlc3Npb24gYW5kIGFuIGVuc2FibGVkIG9mIGJvdGggbW9kZWxzLiBUaGUgYmVzdCBtb2RlbCB3YXMgdGhlIHhnYm9vc3Qgb25lLiBUaGVzZSB3ZXJlIHRoZSByZXN1bHRzOg0KDQpgYGB7cixlY2hvPUZBTFNFLHdhcm5pbmc9RkFMU0V9DQpmaW5hbF9yZXMgPC0gbGFzdF9maXQoZmluYWxfeGdiLCBzcGwpDQoNCmNvbGxlY3RfbWV0cmljcyhmaW5hbF9yZXMpDQpgYGANCg0KSWYgd2UgbG9vayBhdCB0aGUgbW9zdCBpbXBvcnRhbnQgdmFyaWFibGVzIHdlIGhhdmUgdGhlIGRpc3RyaWN0ICgqKmNvbXVuYTIqKiksIHRoaXMgaXMgZXhwbGFpbmVkIGJlY2F1c2UgdGhpcyB2YXJpYWJsZSBjb250YWlucyBtYW55IGNvbXBvbmVudHMgd2l0aGluIGl0LCBtYWlubHkgYWNjZXNzIHRvIHNlcnZpY2VzIGFuZCBwdWJsaWMgZ29vZHMgc3VjaCBhczogaG9zcGl0YWxzLCBwYXJrcywgc2Nob29sczsgYW5kIG90aGVyIHZlcnkgaW1wb3J0YW50IGZlYXR1cmVzIHN1Y2ggYXMgc2VjdXJpdHkuDQoNClRoZSBzZWNvbmQgbW9zdCBpbXBvcnRhbnQgdmFyaWFibGUgaXMgdG90YWwgbWV0ZXJzICgqKm1ldHJvc1RvdGFsZXMzX3BvbHlfMSoqIGFuZCAqKm1ldHJvc1RvdGFsZXMzX3BvbHlfMioqKSBhbmQgdGhlIG1ldGVycyBvZiB0aGUgaW5uZXIgYXJlYSBvZiB0aGUgaG91c2UgKiptZXRyb3NVdGlsZXMqKi4gV2hpY2ggbWFrZXMgc2Vuc2UgYmVjYXVzZSBvbmUgd291bGQgZXhwZWN0IHRoYXQgdGhlIGJpZ2dlciB0aGUgaG91c2UsIHRoZSBoaWdoZXIgdGhlIHByaWNlLiBUaGUgaW50ZXJlc3RpbmcgdGhpbmcgaXMgdGhhdCB0aGUgdG90YWwgbWV0ZXJzIGhhdmUgYSBjb25jYXZlIHF1YWRyYXRpYyByZWxhdGlvbnNoaXAsIHdoaWNoIG1heSBiZSBkdWUgdG8gdGhlIGZhY3QgdGhhdCBob3VzZXMgdGhhdCBoYXZlIGEgdmVyeSBsYXJnZSBhcmVhIG9mIGxhbmQgYXJlIGxvY2F0ZWQgaW4gbW9yZSBydXJhbCBhcmVhcyB3aGVyZSB0aGUgcHJpY2Ugb2YgbGFuZCBpcyBsb3dlciwgd2hpY2ggY2F1c2VzIHRoaXMgcmVsYXRpb25zaGlwLg0KDQpBZnRlciB0aGVzZSB2YXJpYWJsZXMsIHRoZSBtb3N0IGltcG9ydGFudCBhcmUgdGhlIG51bWJlciBvZiBiYXRocm9vbXMgKipiYcOxb3MyKiosIHRoZSBleGlzdGVuY2Ugb2YgYSBwb29sICoqcGlzY2luYSoqLCB0aGUgbnVtYmVyIG9mIGJlZHJvb21zICoqZG9ybWl0b3Jpb3MyKiogYW5kIHRoZSBudW1iZXIgb2YgcGFya2luZyBzcGFjZXMgKipwYXJraW5nMjAqKg0KDQoNCmBgYHtyLGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQoNCmZpbmFsX3hnYiAlPiUNCiAgZml0KGRhdGEgPSB0cmFpbikgJT4lDQogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lDQogIHZpcChnZW9tID0gInBvaW50IiwgbnVtX2ZlYXR1cmVzID0gOCkNCmBgYA0KDQpBbHRob3VnaCB0ZXh0IG9uIHRoZSBkZXNjcmlwdGlvbiB3YXMgbm90IGFuIGltcG9ydGFudCB2YXJpYWJsZSBpbiB0aGUgeGdib29zdCBtb2RlbCwgaXQgd2FzIGltcG9ydGFudCBpbiB0aGUgbGFzc28gbW9kZWwuIEhlcmUgYXJlIGEgbGlzdCBvZiB0aGUgd29yZHMgdGhhdCB3ZXJlIHRoZSBtb3N0IGltcG9ydGFudDogDQoNCmBgYHtyLGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQpncmFwaDwtZmluYWxfbGFzc28gJT4lDQogIGZpdCh0cmFpbikgJT4lDQogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lDQogIHZpKGxhbWJkYSA9IGxvd2VzdF9ybXNlJHBlbmFsdHkpICU+JQ0KICBtdXRhdGUoDQogICAgSW1wb3J0YW5jZSA9IGFicyhJbXBvcnRhbmNlKSwNCiAgICBWYXJpYWJsZSA9IGZjdF9yZW9yZGVyKFZhcmlhYmxlLCBJbXBvcnRhbmNlKSklPiVmaWx0ZXIoc3RyX2RldGVjdChWYXJpYWJsZSwidGZfZGF0b3M0IikpDQoNCmdyYXBoJT4lbXV0YXRlKFZhcmlhYmxlMj1zdHJfcmVwbGFjZShncmFwaCRWYXJpYWJsZSwidGZfZGF0b3M0XyIsIiIpLA0KICAgICAgICAgICAgICAgVmFyaWFibGUgPSBmY3RfcmVvcmRlcihWYXJpYWJsZTIsIEltcG9ydGFuY2UpKSAlPiUgDQogICAgICAgICBoZWFkKDIwKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IEltcG9ydGFuY2UsIHkgPSBWYXJpYWJsZSwgZmlsbCA9IFNpZ24pKSArDQogIGdlb21fY29sKCkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKw0KICBsYWJzKHkgPSBOVUxMKSt0aGVtZV9saWdodCgpDQpgYGANCg0KQW1vbmcgdGhlIHdvcmRzIHdpdGggYSBwb3NpdGl2ZSBlZmZlY3Qgd2UgaGF2ZSBwbGFjZXMgc3VjaCBhczogdGhlIGRpc3RyaWN0cyBvZiBRdWlsaWN1cmEsIFByb3ZpZGVuY2lhLCBjb25kZXMgKExhcyBDb25kZXMpIGFuZCBuZWlnaGJvcmhvb2RzIHN1Y2ggYXMgZGFtacOhbiAoU2FuIERhbWnDoW4pIGFuZCBnb2xmIChFbCBHb2xmKS4gVGhlIGZhY3QgdGhhdCBRdWlsaWN1cmEgaGFzIGEgcG9zaXRpdmUgZWZmZWN0IHRha2VzIHVzIGJ5IHN1cnByaXNlIHNpbmNlIGl0IGlzIG5vdCBhIHdlYWx0aHkgZGlzdHJpY3QuIFZlcmJvIGlzIHRoZXJlIGJlY2F1c2Ugb2YgdGhlICpWZXJibyBEaXZpbm8qIHNjaG9vbCwgd2hpY2ggaXMgb25lIG9mIHRoZSBtb3N0IGV4Y2x1c2l2ZSBlZHVjYXRpb25hbCBlc3RhYmxpc2htZW50cyBpbiBTYW50aWFnby4gT3RoZXIgd29yZHMgd2l0aCBhIHBvc2l0aXZlIGVmZmVjdCBhcmU6IHRoZSBhZGplY3RpdmVzIHNwZWN0YWN1bGFyICoqZXNwZWN0YWN1bGFyKiogYW5kIGZpbmUgKipmaW5hKiosIHRoZSBwcmVzZW5jZSBvZiAqKnBhcnF1ZXQqKiBpbiB0aGUgaG91c2VzLCB3aGVuIHRoZSBob3VzZXMgYXJlIGJ1aWx0IGluIGEgbWVkaXRlcnJhbmVhbiAqKm1lZGl0ZXJyw6FuZWEqKiBzdHlsZSBhbmQsIGZpbmFsbHksIHRoZSB3b3JkIGVhc3licm9rZXIgd2hpY2ggaXMgKnByb2JhYmx5KiBhIHJlYWwgc3RhdGUgY29tcGFueS4NCg0KQW1vbmcgdGhlIHdvcmRzIHdpdGggYSBuZWdhdGl2ZSBlZmZlY3Qgd2UgaGF2ZSBDaGljdXJlbywgd2hpY2ggaXMgY3VyaW91cyBiZWNhdXNlIGl0IGlzIG9uZSBvZiB0aGUgcmljaGVzdCBkaXN0cmljdHMgaW4gU2FudGlhZ28uIFRoZSBleHBsYW5hdGlvbiBpcyB0aGF0IHNpbmNlIG1vc3Qgb2YgdGhlIHNhbXBsZSBjb21lcyBmcm9tIHRoZSBmb3VyIHJpY2hlc3QgZGlzdHJpY3RzIChMbyBCYXJuZWNoZWEsIFZpdGFjdXJhLCBMYXMgQ29uZGVzIGFuZCBDaGljdXJlbyksIENoaWN1cmVvIGhhdmluZyB0aGUgbG93ZXN0IG1lZGlhbiBwcmljZSBpbiB0aGlzIGdyb3VwIGhhcyBhIG5lZ2F0aXZlIGVmZmVjdCBvbiB0aGUgdG90YWwgc2FtcGxlLiBDaGFtaXNlcm8gaXMgYSBzdHJlZXQgaW4gQ2hpY3VyZW8gdGhlcmVmb3JlIHRoYXQgaXMgdGhlIHJlYXNvbiB3aHkgdGhpcyB3b3JkIGFsc28gaGFzIGEgbmVnYXRpdmUgZWZmZWN0LiANCg0KT3RoZXIgd29yZHMgbGlrZSBpcnJpZ2F0aW9uLCB3ZWxsIGFuZCB3b29kIHN0b3ZlIGFyZSBzaWducyBvZiBydXJhbGl0eSBzbyBtYXkgZXhwbGFpbiB0aGUgZWZmZWN0IHRoZXkgaGF2ZS4gVGhlIGxhc3Qgd29yZHMgYXJlIHNjaG9vbHMgKipjb2xlZ2lvcyoqIGFuZCBjYXNoICoqY29udGFkbyoqLiBBYm91dCB0aGVzZSwgaXQgaXMgYSBiaXQgZGlmZmljdWx0IHRvIGZpbmQgYSBjbGVhciByZWFzb24gZm9yIHRoZSBuZWdhdGl2ZSBlZmZlY3QuIEl0IG1heSBiZSB0aGF0IHdoZW4gcHJpY2VzIGFyZSBub3QgZXhwZW5zaXZlLCBzZWxsZXJzIGFzayBmb3IgY2FzaCBwYXltZW50LiBzY2hvb2xzLCBtYXkgaGF2ZSBhIG5lZ2F0aXZlIGVmZmVjdCBiZWNhdXNlIHdoZW4gdGhlIHNjaG9vbHMgYXJvdW5kIGEgcHJvcGVydHkgYXJlIG5vdCB3ZWxsIGtub3duLCBwZW9wbGUgb25seSBtZW50aW9uIHRoZSB3b3JkICJzY2hvb2wiIGluc3RlYWQgb2YgdGhlIG5hbWUgb2YgdGhlIHNjaG9vbCwgYXMgaGFwcGVucyB3aXRoIHRoZSB3ZWxsIGtub3duIHByaXZhdGUgc2Nob29sLCBzdWNoIFZlcmJvIERpdmluby4NCg0KSGVyZSBhcmUgdGhlIHJlc3VsdHMgZm9yIGFsbCBtb2RlbHM6DQpgYGB7cixlY2hvPUZBTFNFfQ0KcHJlZGljdChzdGFja19tb2RlbCwgc3RhY2tfZmluYWxfZGYpICU+JSANCiAgYmluZF9jb2xzKHN0YWNrX2ZpbmFsX2RmKSAlPiUgDQogIHJlbmFtZSgic3RhY2siID0gLnByZWQpICU+JSANCiAgcGl2b3RfbG9uZ2VyKC1wcmVjaW9QZXNvcykgJT4lIA0KICBncm91cF9ieShuYW1lKSAlPiUgDQogIG1zZXQodHJ1dGggPSBwcmVjaW9QZXNvcywgZXN0aW1hdGUgPSB2YWx1ZSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gLm1ldHJpYywgdmFsdWVzX2Zyb20gPSAuZXN0aW1hdGUpICU+JSANCiAgYXJyYW5nZShybXNlKQ0KYGBgDQoNCiMjIEZpbmFsIFRob3VnaHRzDQoNCkZpcnN0IG9mIGFsbCwgSSB0aGluayBpdCBpcyBpbXBvcnRhbnQgdG8gcG9pbnQgb3V0IHRoYXQgaW1wb3J0YW50IGNvbnNpZGVyYXRpb25zIG11c3QgYmUgdGFrZW4gd2hlbiBhbmFseXppbmcgdGhlc2UgcmVzdWx0cywgc2luY2UgdGhlIGJ1bGsgb2YgdGhlIGhvdXNlcyBpbiBvdXIgc2FtcGxlIGNvbWUgZnJvbSB3ZWxsLXRvLWRvIG5laWdoYm9yaG9vZHMuIElmIHdlIGhhZCBhIG1vcmUgYmFsYW5jZWQgc2FtcGxlLCBwZXJoYXBzIHRoZSByZXN1bHRzIHdvdWxkIGJlIGRpZmZlcmVudC4gSGVyZSBpcyBhIGNoYXJ0IHdpdGggdGhlIG51bWJlciBvZiBob3VzZXMgYnkgZGlzdHJpY3QuDQoNCg0KYGBge3IsZWNobz1GQUxTRSx3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0V9DQoNCnBvcnRhbDMgJT4lIGdyb3VwX2J5KGNvbXVuYSkgJT4lIHN1bW1hcmlzZShuPW4oKSklPiUgDQogIGdncGxvdChhZXMoeD1mY3RfcmVvcmRlcihjb211bmEsbiksbikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oc3RhdD0iaWRlbnRpdHkiLCBmaWxsPSIjZjY4MDYwIiwgYWxwaGE9LjYpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSsNCiAgbGFicyh4PSJEaXN0cmljdCIsIHk9Ik4iLA0KICAgICAgIHRpdGxlPSJOdW1iZXIgb2YgSG91c2VzIEJ5IERpc3RyaWN0IikrdGhlbWVfbGlnaHQoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KDQoNCkNvbnNpZGVyaW5nIHdoYXQgSSBqdXN0IG1lbnRpb25lZCwgdGhlIGRpc3RyaWN0IGlzIHRoZSB2YXJpYWJsZSB0aGF0IGhlbHBzIHRvIGJldHRlciBwcmVkaWN0IHRoZSBwcmljZSBvZiB0aGUgaG91c2UuIEl0IGlzIGludGVyZXN0aW5nIHRvIG5vdGUgaG93IHRob3NlIGRpc3RyaWN0cyB0aGF0IHJlY2VpdmVkIHRoZSBtb3N0IHJlbG9jYXRlZCBmYW1pbGllcyBpbiB0aGUgODAncyBhcmUgdGhvc2Ugd2l0aCB0aGUgbG93ZXN0IHByaWNlcy4gVGhlIGltcG9ydGFuY2Ugb2YgdGhlIGlubmVyIGFuZCB0b3RhbCBtZXRlcnMgZG9lcyBub3Qgc3VycHJpc2UgdXMsIHdoYXQgd2UgZG8gY29uc2lkZXIgc3VycHJpc2luZyBpcyB0aGUgcXVhZHJhdGljIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBwcmljZSBvZiB0aGUgaG91c2UgYW5kIHRoZSB0b3RhbCBtZXRlcnMgb2YgdGhlIGhvbWUuDQoNCkkgdGhpbmsgaXQgaXMgc3RpbGwgcGVuZGluZyB0byBydW4gYSBtb2RlbCB3aXRoIHBhaXJzIG9mIHdvcmRzLCBiaW5vbWlhbHMsIGluc3RlYWQgb2YganVzdCB1c2luZyBzaW5nbGUgd29yZHMuIEkgdGhpbmsgdGhhdCBkZXNwaXRlIHRoZSBnb29kIHJlc3VsdHMgb2YgdGhlIG1vZGVscywgdGhlcmUgaXMgcm9vbSB0byBpbXByb3ZlIHBlcmZvcm1hbmNlLCBpdCB3b3VsZCBiZSBoZWxwZnVsIHRvIGhhdmUgc2VydmVycyB0byBiZXR0ZXIgdHJhaW4gdGhlIGRhdGEuDQoNCg0KDQoNCg0KDQoNCg==