This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.
Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.
Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.
When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).
List of R colours at: http://www.stat.columbia.edu/~tzheng/files/Rcolor.pdf
Required Libraries
The library we need for this work book is ggplot2 which is required for plotting clustered and stacked bar-plots. This library must be first installed as follows:
- Go to the Tools tab and select Install Packages
- In the Packages box type ggplot2 and press install
- Once installed, call the ggplot2 library as follows
library(ggplot2)
Clustered Bar Charts
In the case of clustered bar-charts it is often helpful to create a separate data file for our table. In the example from lectures we drew a clustered bar chart to represent the results of a customer survey carried out by a mobile phone company regarding five areas of customer experience:
| Support |
551 |
449 |
| Pricing |
684 |
316 |
| Contracts |
329 |
671 |
| Coverage |
848 |
152 |
| Rewards |
215 |
785 |
We create this table in a standard database system and save the file with a .csv (comma separated values) extension. The file for this particular example, CustomerSurvey.csv, is available on Moodle in the section Data Files. Download this file into the same directory as this R workbook.
We now import the data in the .csv file, which we call Survey, as follows: Run the chunk below as usual, and when the pop-up menu appears select the file CustomerSurvey.csv and press Open
Survey <- read.csv(file.choose())
We display this data frame by running the following chunk
Survey
We now plot this data frame using the functions ggplot(), geom_bar() and scale_fill_manual():
We use ggplot() to plot the data structure CustData. The argument aes() (for aesthetics) informs ggplot to use the Experience column as the x-axis data of the plot and to use the Frequency column as the y-axis data of the plot.
We use geom_bar() to indicate we want the geometry of the plot to be bars. The argument aes(fill=Satisfacion) indicates that the bars should be filled according to the Satisfaction values from the data frame. The argument position = “dodge” ensures the clustered bars do not overlap. The argument stat=“identity” ensures the y-data is taken from the data set.
The scale_fill_manual() function allows us to choose the colours of the bars
ggplot(data=Survey, aes(x=Experience, y=Frequency)) +
geom_bar(aes(fill = Satisfaction), position = "dodge", stat = "identity")+
scale_fill_manual(values=c("blue", "red"))

Ordering the data
We saw during lectures that rearranging the order of the clusters may improve the overall appearance of the bar chart, and in particular it may make the content of data more apparent.
We will organise our clusters so they are arranged from highest to lowest levels of customer satisfaction. This means the clusters should be arranged as
- Coverage
- Pricing
- Support
- Contracts
- Rewards
This is done in R in the cell below:
Survey$Experience <- factor(Survey$Experience, levels = c('Coverage', 'Pricing', 'Support', 'Contracts', 'Rewards'))
Survey
ggplot(data=Survey, aes(x=Experience,y=Frequency)) +
geom_bar(aes(fill = Satisfaction), position = "dodge", stat = "identity")+
scale_fill_manual(values=c("blue", "red"))

- It is clear, at least in this particular example, that re-ordering the clusters has improved the presentation of the data, and in particular it should be more apparent that levels of customer satisfaction are slightly higher than levels of customer dissatisfaction.
Colouring
So far, the bars representing satisfaction/dissatisfaction are coloured in a similar way. This can make it difficult to discern which bar represents which sub-category.
A list of colours in R can be found at http://www.stat.columbia.edu/~tzheng/files/Rcolor.pdf
To highlight the difference between satisfaction/dissatisfaction we could choose different colours that bear no resemblance to one another.
In addition, colours that are occur in nature are found to be more appealing to the viewer. With this in mind, we make the same plot with alternative colors
ggplot(data=Survey, aes(x=Experience,y=Frequency)) +
geom_bar(aes(fill = Satisfaction), position = "dodge", stat = "identity")+
scale_fill_manual(values=c("cadetblue4", "goldenrod"))

Exercise 1
A computer retailer collected data on laptop sales and organise it according to make and chip type, with the following data obtained
| Apple |
5 |
25 |
31 |
| Dell |
15 |
21 |
16 |
| HP |
21 |
28 |
26 |
| Lenovo |
18 |
32 |
31 |
Given this data answer the following
Identify the data type given.
Create a .csv file to tabulate this data.
Create two clustered bar plot from this data file, using different colours in each plot.
Reorder these plots in order of decreasing Intel i3 sales.
Which of these plots conveys the data in the clearest way?
Exercise 2
A company survey asked a sample of 500 employees a series of satisfied/dissatisfied questions in relation to their work in the following areas
- Work/Life Balance 2. Remuneration 3. Career Opportunities 4. Job Satisfaction 5. Vacation Time 6. Up-skilling Opportunities
with the following data obtained
| Work/Life Balance |
398 |
102 |
| Remuneration |
302 |
198 |
| Career Opportunities |
274 |
226 |
| Job Satisfaction |
405 |
95 |
| Vacation Time |
277 |
233 |
| Up-skilling Opportunities |
321 |
179 |
Using this data answer the following
Create a .csv file for this data an import it into this work book
Create a clustered bar-plot for this data
Identify the datatype given
Is there any trend obvious from the chart?
Stacked Bar Charts
A stacked bar-chart is another type of bar-chart where we compare data within a given class, and in particular it illustrates how the overall frequency in a given class is decomposed into further sub-categories.
Example 2
A Toyota dealership is taking an inventory of all models present on the lot, and organises its data according to make and age. The ages of the cars are categorised according to pre-2008 and post-2008, with the data given as follows
| Auris |
8 |
15 |
| Avensis |
11 |
21 |
| Camry |
4 |
2 |
| Corolla |
23 |
18 |
| Prius |
1 |
4 |
| Yaris |
4 |
12 |
- Import the data from CarInventory.csv available in Workbook Files on Moodle and display the data.
Cars <- read.csv(file.choose())
We display the data frame Cars to ensure all is correct
Cars
- Plot the data with high-contrast colours using ggplot.
ggplot(Cars, aes(x=Model,y=Inventory, fill=Year))+
geom_bar(stat="identity")+
scale_fill_manual(values=c("dodgerblue","goldenrod1"))

- Reorder the plots in order of decreaing Pre-2008 inventory.
Cars$Model <- factor(Cars$Model, levels = c('Corolla', 'Avensis', 'Auris', 'Camry', 'Yaris', 'Prius'))
Cars
- Plot the reordered data using the same colouring.
ggplot(Cars, aes(x=Model,y=Inventory, fill=Year))+
geom_bar(stat="identity")+
scale_fill_manual(values=c("dodgerblue","goldenrod1"))

- Re-plot the ordered bar-chart using different colours. Which of the bar-charts is easier to interpret?
ggplot(Cars, aes(x=Model,y=Inventory, fill=Year))+
geom_bar(stat="identity")+
scale_fill_manual(values=c("slategrey","skyblue"))

Exercise 3
A computer retailer sumarises its quarterly sales by computer make and sales point, with the following data collected
| Apple |
210 |
155 |
53 |
| Asus |
335 |
278 |
55 |
| Fujitsu |
188 |
205 |
75 |
| HP |
336 |
451 |
125 |
| Lenovo |
225 |
321 |
144 |
Using this data answer the following:
- Identify the data type given
- Construct a .csv file to store this data
- Generate a stacked bar chart to represent this data
- Re-plot the data in order of decreasing Online Sales
- Use a different set of colours to re-plot the ordered bar-chart
Exercise 4
Using the data given in Exercise 1, generate ordered and unordered stacked bar charts to represent this data set.
Exercise 5
Using the data given in Exercise 2, generate ordered and unordered clustered bar chart to represent this data.
Exercise 6
A food producer collects data on its global revenue from one year of sales. It categorises the regions of sales activity as
- North America 2. Central & South America 3. Europe, Middle East and Africa (EMEA) 4. Asia 5. Australasia
It categorises its food products according to
- Wheat and Dairy 2. Beverages 3. Confectionery 4. Weight Reduction
with the following sales data in millions of euro
| North America |
51 |
152 |
95 |
125 |
| South & Central America |
71 |
32 |
122 |
75 |
| EMEA |
241 |
111 |
84 |
119 |
| Asia |
188 |
94 |
88 |
92 |
| Australasia |
44 |
29 |
74 |
57 |
Using this data set answer the following:
Identify the data types given
Generate a .csv file to store this data
Generate a clustered barplot to represent this data
Generate a stacked barplot to represent this data
Which of the bar charts represents this data better?
Re-plot these charts with a different ordering and with different colouring, of your own choice?
LS0tCnRpdGxlOiAiRGF0YSBWaXN1YWxpc2F0aW9uIDIwMTkgLSBBc3NpZ25tZW50IDIiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuIAoKVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLiAKCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDdHJsK0FsdCtJKi4KCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ3RybCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLgoKTGlzdCBvZiBfX1JfXyBjb2xvdXJzIGF0OgogaHR0cDovL3d3dy5zdGF0LmNvbHVtYmlhLmVkdS9+dHpoZW5nL2ZpbGVzL1Jjb2xvci5wZGYKIAojIyBSZXF1aXJlZCBMaWJyYXJpZXMKVGhlIGxpYnJhcnkgd2UgbmVlZCBmb3IgdGhpcyB3b3JrIGJvb2sgaXMgX19nZ3Bsb3QyX18gd2hpY2ggaXMgcmVxdWlyZWQgZm9yIHBsb3R0aW5nIGNsdXN0ZXJlZCBhbmQgc3RhY2tlZCBiYXItcGxvdHMuIFRoaXMgbGlicmFyeSBtdXN0IGJlIGZpcnN0IGluc3RhbGxlZCBhcyBmb2xsb3dzOgoKMS4gR28gdG8gdGhlIF9fVG9vbHNfXyB0YWIgYW5kIHNlbGVjdCBfSW5zdGFsbCBQYWNrYWdlc18KMi4gSW4gdGhlIF9QYWNrYWdlc18gYm94IHR5cGUgX19nZ3Bsb3QyX18gYW5kIHByZXNzIGluc3RhbGwKMy4gT25jZSBpbnN0YWxsZWQsIGNhbGwgdGhlIF9fZ2dwbG90Ml9fIGxpYnJhcnkgYXMgZm9sbG93cwogCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmBgYAoKIyBDbHVzdGVyZWQgQmFyIENoYXJ0cwpJbiB0aGUgY2FzZSBvZiBjbHVzdGVyZWQgYmFyLWNoYXJ0cyBpdCBpcyBvZnRlbiBoZWxwZnVsIHRvIGNyZWF0ZSBhIHNlcGFyYXRlIGRhdGEgZmlsZSBmb3Igb3VyIHRhYmxlLiBJbiB0aGUgZXhhbXBsZSBmcm9tIGxlY3R1cmVzIHdlIGRyZXcgYSBjbHVzdGVyZWQgYmFyIGNoYXJ0IHRvIHJlcHJlc2VudCB0aGUgcmVzdWx0cyBvZiBhIGN1c3RvbWVyIHN1cnZleSBjYXJyaWVkIG91dCBieSBhIG1vYmlsZSBwaG9uZSBjb21wYW55IHJlZ2FyZGluZyBmaXZlIGFyZWFzIG9mIGN1c3RvbWVyIGV4cGVyaWVuY2U6CgogIHwgX19FeHBlcmllbmNlX18gfCBfX1NhdGlzZmllZF9fIHwgX19EaXNzYXRpc2ZpZWRfXyB8CiAgfC0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLXwKICB8ICAgICBTdXBwb3J0ICAgIHwgICAgNTUxICAgICAgICB8ICAgICAgNDQ5ICAgICAgICAgfAogIHwgICAgIFByaWNpbmcgICAgfCAgICA2ODQgICAgICAgIHwgICAgICAzMTYgICAgICAgICB8CiAgfCAgICAgQ29udHJhY3RzICB8ICAgIDMyOSAgICAgICAgfCAgICAgIDY3MSAgICAgICAgIHwKICB8ICAgICBDb3ZlcmFnZSAgIHwgICAgODQ4ICAgICAgICB8ICAgICAgMTUyICAgICAgICAgfAogIHwgICAgIFJld2FyZHMgICAgfCAgICAyMTUgICAgICAgIHwgICAgICA3ODUgICAgICAgICB8CiAgCldlIGNyZWF0ZSB0aGlzIHRhYmxlIGluIGEgc3RhbmRhcmQgZGF0YWJhc2Ugc3lzdGVtIGFuZCBzYXZlIHRoZSBmaWxlIHdpdGggYSBfXy5jc3ZfXyAoY29tbWEgc2VwYXJhdGVkIHZhbHVlcykgZXh0ZW5zaW9uLiBUaGUgZmlsZSBmb3IgdGhpcyBwYXJ0aWN1bGFyIGV4YW1wbGUsIF9fQ3VzdG9tZXJTdXJ2ZXkuY3N2X18sIGlzIGF2YWlsYWJsZSBvbiBNb29kbGUgaW4gdGhlIHNlY3Rpb24gX0RhdGEgRmlsZXNfLiBEb3dubG9hZCB0aGlzIGZpbGUgaW50byB0aGUgc2FtZSBkaXJlY3RvcnkgYXMgdGhpcyBfX1JfXyB3b3JrYm9vay4gIAogIAoKV2Ugbm93IGltcG9ydCB0aGUgZGF0YSBpbiB0aGUgX18uY3N2X18gZmlsZSwgd2hpY2ggd2UgY2FsbCBfX1N1cnZleV9fLCBhcyBmb2xsb3dzOiBSdW4gdGhlIGNodW5rIGJlbG93IGFzIHVzdWFsLCBhbmQgd2hlbiB0aGUgcG9wLXVwIG1lbnUgYXBwZWFycyBzZWxlY3QgdGhlIGZpbGUgX19DdXN0b21lclN1cnZleS5jc3ZfXyBhbmQgcHJlc3MgX19PcGVuX18KYGBge3J9ClN1cnZleSA8LSByZWFkLmNzdihmaWxlLmNob29zZSgpKQpgYGAKV2UgZGlzcGxheSB0aGlzIGRhdGEgZnJhbWUgYnkgcnVubmluZyB0aGUgZm9sbG93aW5nIGNodW5rCmBgYHtyfQpTdXJ2ZXkKYGBgCldlIG5vdyBwbG90IHRoaXMgZGF0YSBmcmFtZSB1c2luZyB0aGUgZnVuY3Rpb25zIF9fZ2dwbG90KClfXywgX19nZW9tX2JhcigpX18gYW5kIF9fc2NhbGVfZmlsbF9tYW51YWwoKV9fOgoKCgoqIFdlIHVzZSBfX2dncGxvdCgpX18gdG8gcGxvdCB0aGUgZGF0YSBzdHJ1Y3R1cmUgX19DdXN0RGF0YV9fLiBUaGUgYXJndW1lbnQgX19hZXMoKV9fIChmb3IgYWVzdGhldGljcykgaW5mb3JtcyBfX2dncGxvdF9fIHRvIHVzZSB0aGUgX19FeHBlcmllbmNlX18gY29sdW1uIGFzIHRoZSB4LWF4aXMgZGF0YSBvZiB0aGUgcGxvdCBhbmQgdG8gdXNlIHRoZSBfX0ZyZXF1ZW5jeV9fIGNvbHVtbiBhcyB0aGUgeS1heGlzIGRhdGEgb2YgdGhlIHBsb3QuCgoKKiBXZSB1c2UgX19nZW9tX2JhcigpX18gdG8gaW5kaWNhdGUgd2Ugd2FudCB0aGUgZ2VvbWV0cnkgb2YgdGhlIHBsb3QgdG8gYmUgYmFycy4gVGhlIGFyZ3VtZW50IF9fYWVzKGZpbGw9U2F0aXNmYWNpb24pX18gaW5kaWNhdGVzIHRoYXQgdGhlIGJhcnMgc2hvdWxkIGJlIGZpbGxlZCBhY2NvcmRpbmcgdG8gdGhlIF9fU2F0aXNmYWN0aW9uX18gdmFsdWVzIGZyb20gdGhlIGRhdGEgZnJhbWUuIFRoZSBhcmd1bWVudCBfX3Bvc2l0aW9uID0gImRvZGdlIl9fIGVuc3VyZXMgdGhlIGNsdXN0ZXJlZCBiYXJzIGRvIG5vdCBvdmVybGFwLiBUaGUgYXJndW1lbnQgX19zdGF0PSJpZGVudGl0eSJfXyBlbnN1cmVzIHRoZSB5LWRhdGEgaXMgdGFrZW4gZnJvbSB0aGUgZGF0YSBzZXQuCgoqIFRoZSBfX3NjYWxlX2ZpbGxfbWFudWFsKClfXyBmdW5jdGlvbiBhbGxvd3MgdXMgdG8gY2hvb3NlIHRoZSBjb2xvdXJzIG9mIHRoZSBiYXJzCgpgYGB7cn0KZ2dwbG90KGRhdGE9U3VydmV5LCBhZXMoeD1FeHBlcmllbmNlLCB5PUZyZXF1ZW5jeSkpICsgICAKICBnZW9tX2JhcihhZXMoZmlsbCA9IFNhdGlzZmFjdGlvbiksIHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJibHVlIiwgInJlZCIpKQpgYGAKCiMjIE9yZGVyaW5nIHRoZSBkYXRhCgoqIFdlIHNhdyBkdXJpbmcgbGVjdHVyZXMgdGhhdCByZWFycmFuZ2luZyB0aGUgb3JkZXIgb2YgdGhlIGNsdXN0ZXJzIG1heSBpbXByb3ZlIHRoZSBvdmVyYWxsIGFwcGVhcmFuY2Ugb2YgdGhlIGJhciBjaGFydCwgYW5kIGluIHBhcnRpY3VsYXIgaXQgbWF5IG1ha2UgdGhlIGNvbnRlbnQgb2YgZGF0YSBtb3JlIGFwcGFyZW50LgoKKiBXZSB3aWxsIG9yZ2FuaXNlIG91ciBjbHVzdGVycyBzbyB0aGV5IGFyZSBhcnJhbmdlZCBmcm9tIGhpZ2hlc3QgdG8gbG93ZXN0IGxldmVscyBvZiBjdXN0b21lciBzYXRpc2ZhY3Rpb24uIFRoaXMgbWVhbnMgdGhlIGNsdXN0ZXJzIHNob3VsZCBiZSBhcnJhbmdlZCBhcwoKICAgIDEuIENvdmVyYWdlCiAgICAyLiBQcmljaW5nCiAgICAzLiBTdXBwb3J0CiAgICA0LiBDb250cmFjdHMKICAgIDUuIFJld2FyZHMKClRoaXMgaXMgZG9uZSBpbiBfX1JfXyBpbiB0aGUgY2VsbCBiZWxvdzoKYGBge3J9ClN1cnZleSRFeHBlcmllbmNlIDwtIGZhY3RvcihTdXJ2ZXkkRXhwZXJpZW5jZSwgbGV2ZWxzID0gYygnQ292ZXJhZ2UnLCAnUHJpY2luZycsICdTdXBwb3J0JywgJ0NvbnRyYWN0cycsICdSZXdhcmRzJykpClN1cnZleQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YT1TdXJ2ZXksIGFlcyh4PUV4cGVyaWVuY2UseT1GcmVxdWVuY3kpKSArICAgCiAgZ2VvbV9iYXIoYWVzKGZpbGwgPSBTYXRpc2ZhY3Rpb24pLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiYmx1ZSIsICJyZWQiKSkKYGBgCiogSXQgaXMgY2xlYXIsIGF0IGxlYXN0IGluIHRoaXMgcGFydGljdWxhciBleGFtcGxlLCB0aGF0IHJlLW9yZGVyaW5nIHRoZSBjbHVzdGVycyBoYXMgaW1wcm92ZWQgdGhlIHByZXNlbnRhdGlvbiBvZiB0aGUgZGF0YSwgYW5kIGluIHBhcnRpY3VsYXIgaXQgc2hvdWxkIGJlIG1vcmUgYXBwYXJlbnQgdGhhdCBsZXZlbHMgb2YgY3VzdG9tZXIgc2F0aXNmYWN0aW9uIGFyZSBzbGlnaHRseSBoaWdoZXIgdGhhbiBsZXZlbHMgb2YgY3VzdG9tZXIgZGlzc2F0aXNmYWN0aW9uLgoKCgojIyMgQ29sb3VyaW5nCgoqIFNvIGZhciwgdGhlIGJhcnMgcmVwcmVzZW50aW5nIF9fc2F0aXNmYWN0aW9uL2Rpc3NhdGlzZmFjdGlvbl9fIGFyZSBjb2xvdXJlZCBpbiBhIHNpbWlsYXIgd2F5LiBUaGlzIGNhbiBtYWtlIGl0IGRpZmZpY3VsdCB0byBkaXNjZXJuIHdoaWNoIGJhciByZXByZXNlbnRzIHdoaWNoIHN1Yi1jYXRlZ29yeS4KCiogQSBsaXN0IG9mIGNvbG91cnMgaW4gX19SX18gY2FuIGJlIGZvdW5kIGF0ICBodHRwOi8vd3d3LnN0YXQuY29sdW1iaWEuZWR1L350emhlbmcvZmlsZXMvUmNvbG9yLnBkZgoKKiBUbyBoaWdobGlnaHQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBfX3NhdGlzZmFjdGlvbi9kaXNzYXRpc2ZhY3Rpb25fXyB3ZSBjb3VsZCBjaG9vc2UgZGlmZmVyZW50IGNvbG91cnMgdGhhdCBiZWFyIG5vIHJlc2VtYmxhbmNlIHRvIG9uZSBhbm90aGVyLgoKKiBJbiBhZGRpdGlvbiwgY29sb3VycyAgdGhhdCBhcmUgb2NjdXIgaW4gbmF0dXJlIGFyZSBmb3VuZCB0byBiZSBtb3JlIGFwcGVhbGluZyB0byB0aGUgdmlld2VyLiBXaXRoIHRoaXMgaW4gbWluZCwgd2UgbWFrZSB0aGUgc2FtZSBwbG90IHdpdGggYWx0ZXJuYXRpdmUgY29sb3JzCgpgYGB7cn0KZ2dwbG90KGRhdGE9U3VydmV5LCBhZXMoeD1FeHBlcmllbmNlLHk9RnJlcXVlbmN5KSkgKyAgIAogIGdlb21fYmFyKGFlcyhmaWxsID0gU2F0aXNmYWN0aW9uKSwgcG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoImNhZGV0Ymx1ZTQiLCAiZ29sZGVucm9kIikpCmBgYAoKIyMgRXhlcmNpc2UgMSAKCkEgY29tcHV0ZXIgcmV0YWlsZXIgY29sbGVjdGVkIGRhdGEgb24gbGFwdG9wIHNhbGVzIGFuZCBvcmdhbmlzZSBpdCBhY2NvcmRpbmcgdG8gbWFrZSBhbmQgY2hpcCB0eXBlLCB3aXRoIHRoZSBmb2xsb3dpbmcgZGF0YSBvYnRhaW5lZAoKfCBfX01ha2VfXyB8IF9fSW50ZWwgaTNfXyB8IF9fSW50ZWwgaTVfXyB8IF9fSW50ZWwgaTdfXyB8CnwtLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tfAp8ICBBcHBsZSAgIHwgICAgICA1ICAgICAgIHwgICAgICAyNSAgICAgIHwgICAgICAgMzEgICAgIHwKfCAgRGVsbCAgICB8ICAgICAgMTUgICAgICB8ICAgICAgMjEgICAgICB8ICAgICAgIDE2ICAgICB8CnwgIEhQICAgICAgfCAgICAgIDIxICAgICAgfCAgICAgIDI4ICAgICAgfCAgICAgICAyNiAgICAgfAp8ICBMZW5vdm8gIHwgICAgICAxOCAgICAgIHwgICAgICAzMiAgICAgIHwgICAgICAgMzEgICAgIHwKCkdpdmVuIHRoaXMgZGF0YSBhbnN3ZXIgdGhlIGZvbGxvd2luZwoKMS4gSWRlbnRpZnkgdGhlIGRhdGEgdHlwZSBnaXZlbi4KCjIuIENyZWF0ZSBhIF9fLmNzdl9fIGZpbGUgdG8gdGFidWxhdGUgdGhpcyBkYXRhLgoKMy4gQ3JlYXRlIF9fdHdvX18gY2x1c3RlcmVkIGJhciBwbG90IGZyb20gdGhpcyBkYXRhIGZpbGUsIHVzaW5nIGRpZmZlcmVudCBjb2xvdXJzIGluIGVhY2ggcGxvdC4KCjQuIFJlb3JkZXIgdGhlc2UgcGxvdHMgaW4gb3JkZXIgb2YgX19kZWNyZWFzaW5nIEludGVsIGkzX18gc2FsZXMuCgo0LiBXaGljaCBvZiB0aGVzZSBwbG90cyBjb252ZXlzIHRoZSBkYXRhIGluIHRoZSBjbGVhcmVzdCB3YXk/CgojIyBFeGVyY2lzZSAyCgpBIGNvbXBhbnkgc3VydmV5IGFza2VkIGEgc2FtcGxlIG9mIDUwMCBlbXBsb3llZXMgYSBzZXJpZXMgb2Ygc2F0aXNmaWVkL2Rpc3NhdGlzZmllZCBxdWVzdGlvbnMgaW4gcmVsYXRpb24gdG8gdGhlaXIgd29yayBpbiB0aGUgZm9sbG93aW5nIGFyZWFzCgoxLiBXb3JrL0xpZmUgQmFsYW5jZSAgMi4gUmVtdW5lcmF0aW9uICAzLiBDYXJlZXIgT3Bwb3J0dW5pdGllcyAgIDQuIEpvYiBTYXRpc2ZhY3Rpb24gICA1LiBWYWNhdGlvbiBUaW1lICA2LiBVcC1za2lsbGluZyBPcHBvcnR1bml0aWVzCgp3aXRoIHRoZSBmb2xsb3dpbmcgZGF0YSBvYnRhaW5lZAoKfCBfX1dvcmsgRmVhdHVyZV9fICAgICAgICB8IFNhdGlzZmllZCB8IERpc3NhdGlzZmllZCB8CnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tfAp8V29yay9MaWZlIEJhbGFuY2UgICAgICAgIHwgICAgMzk4ICAgIHwgICAgIDEwMiAgICAgIHwKfCAgUmVtdW5lcmF0aW9uICAgICAgICAgICB8ICAgIDMwMiAgICB8ICAgICAxOTggICAgICB8CnxDYXJlZXIgT3Bwb3J0dW5pdGllcyAgICAgfCAgICAyNzQgICAgfCAgICAgMjI2ICAgICAgfAp8IEpvYiBTYXRpc2ZhY3Rpb24gICAgICAgIHwgICAgNDA1ICAgIHwgICAgICA5NSAgICAgIHwKfCBWYWNhdGlvbiBUaW1lICAgICAgICAgICB8ICAgIDI3NyAgICB8ICAgICAyMzMgICAgICB8CnwgVXAtc2tpbGxpbmcgT3Bwb3J0dW5pdGllc3wgICAgMzIxICAgIHwgICAgIDE3OSAgICAgIHwKClVzaW5nIHRoaXMgZGF0YSBhbnN3ZXIgdGhlIGZvbGxvd2luZwoKMS4gQ3JlYXRlIGEgX18uY3N2X18gZmlsZSBmb3IgdGhpcyBkYXRhIGFuIGltcG9ydCBpdCBpbnRvIHRoaXMgd29yayBib29rCgoyLiBDcmVhdGUgYSBjbHVzdGVyZWQgYmFyLXBsb3QgZm9yIHRoaXMgZGF0YQoKMy4gSWRlbnRpZnkgdGhlIGRhdGF0eXBlIGdpdmVuIAoKNC4gSXMgdGhlcmUgYW55IHRyZW5kIG9idmlvdXMgZnJvbSB0aGUgY2hhcnQ/CgojIFN0YWNrZWQgQmFyIENoYXJ0cwoKQSBzdGFja2VkIGJhci1jaGFydCBpcyBhbm90aGVyIHR5cGUgb2YgYmFyLWNoYXJ0IHdoZXJlIHdlIGNvbXBhcmUgZGF0YSB3aXRoaW4gYSBnaXZlbiBjbGFzcywgYW5kIGluIHBhcnRpY3VsYXIgaXQgaWxsdXN0cmF0ZXMgaG93IHRoZSBvdmVyYWxsIGZyZXF1ZW5jeSBpbiBhIGdpdmVuIGNsYXNzIGlzIGRlY29tcG9zZWQgaW50byBmdXJ0aGVyIHN1Yi1jYXRlZ29yaWVzLgoKIyMgRXhhbXBsZSAyCgpBIFRveW90YSBkZWFsZXJzaGlwIGlzIHRha2luZyBhbiBpbnZlbnRvcnkgb2YgYWxsIG1vZGVscyBwcmVzZW50IG9uIHRoZSBsb3QsIGFuZCBvcmdhbmlzZXMgaXRzIGRhdGEgYWNjb3JkaW5nIHRvIG1ha2UgYW5kIGFnZS4gVGhlIGFnZXMgb2YgdGhlIGNhcnMgYXJlIGNhdGVnb3Jpc2VkIGFjY29yZGluZyB0byBwcmUtMjAwOCBhbmQgcG9zdC0yMDA4LCB3aXRoIHRoZSBkYXRhIGdpdmVuIGFzIGZvbGxvd3MKCgp8IF9fTW9kZWxfXyB8IFByZS0yMDA4IHwgUG9zdC0yMDA4ICB8CnwtLS0tLS0tLS0tLXwtLS0tLS0tLS0tfC0tLS0tLS0tLS0tLXwKfCAgIEF1cmlzICAgfCAgICA4ICAgICB8ICAgICAxNSAgICAgfAp8ICAgQXZlbnNpcyB8ICAgIDExICAgIHwgICAgIDIxICAgICB8CnwgICBDYW1yeSAgIHwgICAgNCAgICAgfCAgICAgIDIgICAgIHwKfCAgIENvcm9sbGEgfCAgICAyMyAgICB8ICAgICAxOCAgICAgfAp8ICAgUHJpdXMgICB8ICAgIDEgICAgIHwgICAgICA0ICAgICB8CnwgICBZYXJpcyAgIHwgICAgNCAgICAgfCAgICAgMTIgICAgIHwKCgoxLiBJbXBvcnQgdGhlIGRhdGEgZnJvbSAgX19DYXJJbnZlbnRvcnkuY3N2X18gYXZhaWxhYmxlIGluIF9Xb3JrYm9vayBGaWxlc18gb24gTW9vZGxlIGFuZCBkaXNwbGF5IHRoZSBkYXRhLgpgYGB7cn0KQ2FycyA8LSByZWFkLmNzdihmaWxlLmNob29zZSgpKQpgYGAKV2UgZGlzcGxheSB0aGUgZGF0YSBmcmFtZSBfX0NhcnNfXyB0byBlbnN1cmUgYWxsIGlzIGNvcnJlY3QKYGBge3J9CkNhcnMKYGBgCgoyLiBQbG90IHRoZSBkYXRhIHdpdGggaGlnaC1jb250cmFzdCBjb2xvdXJzIHVzaW5nIF9fZ2dwbG90X18uCgpgYGB7cn0KZ2dwbG90KENhcnMsIGFlcyh4PU1vZGVsLHk9SW52ZW50b3J5LCBmaWxsPVllYXIpKSsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJkb2RnZXJibHVlIiwiZ29sZGVucm9kMSIpKQpgYGAgCjMuIFJlb3JkZXIgdGhlIHBsb3RzIGluIG9yZGVyIG9mIF9fZGVjcmVhaW5nIFByZS0yMDA4X18gaW52ZW50b3J5LgpgYGB7cn0KQ2FycyRNb2RlbCA8LSBmYWN0b3IoQ2FycyRNb2RlbCwgbGV2ZWxzID0gYygnQ29yb2xsYScsICdBdmVuc2lzJywgJ0F1cmlzJywgJ0NhbXJ5JywgJ1lhcmlzJywgJ1ByaXVzJykpCkNhcnMKYGBgCjQuIFBsb3QgdGhlIHJlb3JkZXJlZCBkYXRhIHVzaW5nIHRoZSBzYW1lIGNvbG91cmluZy4KYGBge3J9CmdncGxvdChDYXJzLCBhZXMoeD1Nb2RlbCx5PUludmVudG9yeSwgZmlsbD1ZZWFyKSkrCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiZG9kZ2VyYmx1ZSIsImdvbGRlbnJvZDEiKSkKYGBgIAo1LiBSZS1wbG90IHRoZSBvcmRlcmVkIGJhci1jaGFydCB1c2luZyBkaWZmZXJlbnQgY29sb3Vycy4gV2hpY2ggb2YgdGhlIGJhci1jaGFydHMgaXMgZWFzaWVyIHRvIGludGVycHJldD8KYGBge3J9CmdncGxvdChDYXJzLCBhZXMoeD1Nb2RlbCx5PUludmVudG9yeSwgZmlsbD1ZZWFyKSkrCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Yygic2xhdGVncmV5Iiwic2t5Ymx1ZSIpKQpgYGAgCgoKIyMgRXhlcmNpc2UgMyAKQSBjb21wdXRlciByZXRhaWxlciBzdW1hcmlzZXMgaXRzIHF1YXJ0ZXJseSBzYWxlcyBieSBjb21wdXRlciBtYWtlIGFuZCBzYWxlcyBwb2ludCwgd2l0aCB0aGUgZm9sbG93aW5nIGRhdGEgY29sbGVjdGVkCgp8IF9fTWFrZV9fIHwgX19PbmxpbmUgU2FsZXNfXyB8IF9fU3RvcmUgU2FsZXNfXyB8IF9fQ29ycG9yYXRlIFNhbGVzX18gfAp8LS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tfAp8IEFwcGxlICAgIHwgICAgICAgICAyMTAgICAgICB8ICAgICAgICAxNTUgICAgICB8ICAgICAgICAgIDUzICAgICAgICAgfAp8IEFzdXMgICAgIHwgICAgICAgICAzMzUgICAgICB8ICAgICAgICAyNzggICAgICB8ICAgICAgICAgIDU1ICAgICAgICAgfAp8IEZ1aml0c3UgIHwgICAgICAgICAxODggICAgICB8ICAgICAgICAyMDUgICAgICB8ICAgICAgICAgIDc1ICAgICAgICAgfAp8IEhQICAgICAgIHwgICAgICAgICAzMzYgICAgICB8ICAgICAgICA0NTEgICAgICB8ICAgICAgICAgMTI1ICAgICAgICAgfAp8IExlbm92byAgIHwgICAgICAgICAyMjUgICAgICB8ICAgICAgICAzMjEgICAgICB8ICAgICAgICAgMTQ0ICAgICAgICAgfAoKVXNpbmcgdGhpcyBkYXRhIGFuc3dlciB0aGUgZm9sbG93aW5nOgoKMS4gSWRlbnRpZnkgdGhlIGRhdGEgdHlwZSBnaXZlbgoyLiBDb25zdHJ1Y3QgYSBfXy5jc3ZfXyBmaWxlIHRvIHN0b3JlIHRoaXMgZGF0YQozLiBHZW5lcmF0ZSBhIHN0YWNrZWQgYmFyIGNoYXJ0IHRvIHJlcHJlc2VudCB0aGlzIGRhdGEKNC4gUmUtcGxvdCB0aGUgZGF0YSBpbiBvcmRlciBvZiBfX2RlY3JlYXNpbmcgT25saW5lIFNhbGVzX18KNS4gVXNlIGEgZGlmZmVyZW50IHNldCBvZiBjb2xvdXJzIHRvIHJlLXBsb3QgdGhlIG9yZGVyZWQgYmFyLWNoYXJ0CgoKIyMgRXhlcmNpc2UgNAoKVXNpbmcgdGhlIGRhdGEgZ2l2ZW4gaW4gX19FeGVyY2lzZSAxX18sIGdlbmVyYXRlIG9yZGVyZWQgYW5kIHVub3JkZXJlZCBfKipzdGFja2VkIGJhciBjaGFydHMqKl8gdG8gcmVwcmVzZW50IHRoaXMgZGF0YSBzZXQuCgoKIyMgRXhlcmNpc2UgNQoKVXNpbmcgdGhlIGRhdGEgZ2l2ZW4gaW4gX19FeGVyY2lzZSAyX18sIGdlbmVyYXRlIG9yZGVyZWQgYW5kIHVub3JkZXJlZCBfKipjbHVzdGVyZWQgYmFyIGNoYXJ0KipfIHRvIHJlcHJlc2VudCB0aGlzIGRhdGEuCgoKCiMjIEV4ZXJjaXNlIDYKCkEgZm9vZCBwcm9kdWNlciBjb2xsZWN0cyBkYXRhIG9uIGl0cyBnbG9iYWwgcmV2ZW51ZSBmcm9tIG9uZSB5ZWFyIG9mIHNhbGVzLiBJdCBjYXRlZ29yaXNlcyB0aGUgcmVnaW9ucyBvZiBzYWxlcyBhY3Rpdml0eSBhcwoKMS4gTm9ydGggQW1lcmljYSAgMi4gQ2VudHJhbCAmIFNvdXRoIEFtZXJpY2EgIDMuIEV1cm9wZSwgTWlkZGxlIEVhc3QgYW5kIEFmcmljYSAoRU1FQSkgICA0LiBBc2lhICA1LiBBdXN0cmFsYXNpYQoKSXQgY2F0ZWdvcmlzZXMgaXRzIGZvb2QgcHJvZHVjdHMgYWNjb3JkaW5nIHRvCgoxLiBXaGVhdCBhbmQgRGFpcnkgIDIuIEJldmVyYWdlcyAgMy4gQ29uZmVjdGlvbmVyeSAgNC4gV2VpZ2h0IFJlZHVjdGlvbgoKd2l0aCB0aGUgZm9sbG93aW5nIHNhbGVzIGRhdGEgaW4gbWlsbGlvbnMgb2YgZXVybyAKCnwgX19SZWdpb25fXyAgICAgICAgICAgICB8IF9fV2hlYXQgYW5kIERhaXJ5X18gfCBfX0JldmVyYWdlc19fIHwgX19Db25mZWN0aW9uYXJ5X18gfCBfX1dlaWdodCBSZWR1Y3Rpb25fXyB8CnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS18CnwgTm9ydGggQW1lcmljYSAgICAgICAgICB8ICAgICAgIDUxICAgICAgICAgICAgfCAgICAgICAxNTIgICAgIHwgICAgICAgOTUgICAgICAgICAgfCAgICAgICAgMTI1ICAgICAgICAgICB8CnwgU291dGggJiBDZW50cmFsIEFtZXJpY2F8ICAgICAgIDcxICAgICAgICAgICAgfCAgICAgICAgMzIgICAgIHwgICAgICAgMTIyICAgICAgICAgfCAgICAgICAgIDc1ICAgICAgICAgICB8CnwgRU1FQSAgICAgICAgICAgICAgICAgICB8ICAgICAgIDI0MSAgICAgICAgICAgfCAgICAgICAxMTEgICAgIHwgICAgICAgODQgICAgICAgICAgfCAgICAgICAgMTE5ICAgICAgICAgICB8CnwgQXNpYSAgICAgICAgICAgICAgICAgICB8ICAgICAgIDE4OCAgICAgICAgICAgfCAgICAgICAgOTQgICAgIHwgICAgICAgODggICAgICAgICAgfCAgICAgICAgIDkyICAgICAgICAgICB8CnwgQXVzdHJhbGFzaWEgICAgICAgICAgICB8ICAgICAgIDQ0ICAgICAgICAgICAgfCAgICAgICAgMjkgICAgIHwgICAgICAgNzQgICAgICAgICAgfCAgICAgICAgIDU3ICAgICAgICAgICB8CgoKVXNpbmcgdGhpcyBkYXRhIHNldCBhbnN3ZXIgdGhlIGZvbGxvd2luZzoKCjEuIElkZW50aWZ5IHRoZSBkYXRhIHR5cGVzIGdpdmVuCgoyLiBHZW5lcmF0ZSBhIF9fLmNzdl9fIGZpbGUgdG8gc3RvcmUgdGhpcyBkYXRhCgozLiBHZW5lcmF0ZSBhIF9fY2x1c3RlcmVkIGJhcnBsb3RfXyB0byByZXByZXNlbnQgdGhpcyBkYXRhCgo0LiBHZW5lcmF0ZSBhIF9fc3RhY2tlZCBiYXJwbG90X18gdG8gcmVwcmVzZW50IHRoaXMgZGF0YQoKNS4gV2hpY2ggb2YgdGhlIGJhciBjaGFydHMgcmVwcmVzZW50cyB0aGlzIGRhdGEgYmV0dGVyPwoKNi4gUmUtcGxvdCB0aGVzZSBjaGFydHMgd2l0aCBhIGRpZmZlcmVudCBvcmRlcmluZyBhbmQgd2l0aCBkaWZmZXJlbnQgY29sb3VyaW5nLCBvZiB5b3VyIG93biBjaG9pY2U/CgoKCgoKCgoKCgoKCgoK