
Exercise 1
The following table shows sample information for three students. Each
observation represents a single student and includes details such as
their unique student ID, name, age, total credits completed, major field
of study, and year level.
This dataset demonstrates a mixture of variable types:
- Nominal: StudentID, Name, Major
- Numeric: Age (continuous), CreditsCompleted
(discrete)
- Ordinal: YearLevel (Freshman → Senior)
| S001 |
Alice |
20 |
45 |
Data Sains |
Sophomore |
| S002 |
Budi |
21 |
60 |
Mathematics |
Junior |
| S003 |
Citra |
19 |
30 |
Statistics |
Freshman |
# 1. Create vectors for each variable
StudentID <- c("S001", "S002", "S003") # Nominal / ID
Name <- c("Alice", "Budi", "Citra") # Nominal / Name
Age <- c(20, 21, 19) # Numeric / Continuous
CreditsCompleted <- c(45, 60, 30) # Numeric / Discrete
# Nominal
Major <- c("Data Sains", "Mathematics", "Statistics")
# Ordinal
YearLevel <- factor(c("Sophomore", "Junior", "Freshman"),
levels = c("Freshman","Sophomore","Junior","Senior"),
ordered = TRUE)
# 2. Combine all vectors into a data frame
students <- data.frame(
StudentID, Name, Age, CreditsCompleted, Major, YearLevel,
stringsAsFactors = FALSE
)
# 3. Display the data frame
print(students)
## StudentID Name Age CreditsCompleted Major YearLevel
## 1 S001 Alice 20 45 Data Sains Sophomore
## 2 S002 Budi 21 60 Mathematics Junior
## 3 S003 Citra 19 30 Statistics Freshman
Exercise 2
Identify Data Types: Determine the type of data for
each of the following variables:
# Install knitr package if not already installed
# install.packages("knitr")
library(knitr)
# Create a data frame for Data Types
variables_info <- data.frame(
No = 1:5,
Variable = c(
"Number of vehicles passing through the toll road each day",
"Student height in cm",
"Employee gender (Male / Female)",
"Customer satisfaction level: Low, Medium, High",
"Respondent's favorite color: Red, Blue, Green"
),
DataType = c(
"Quantitative",
"Quantitative",
"Quantitative",
"Qualitative",
"Qualitative"
),
Subtype = c(
"Diskrete",
"Continuous",
"Nominal",
"Ordinal",
"Nominal"
),
stringsAsFactors = FALSE
)
# Display the data frame as a neat table
kable(variables_info,
caption = "Table of Variables and Data Types")
Table of Variables and Data Types
| 1 |
Number of vehicles passing through the toll road each
day |
Quantitative |
Diskrete |
| 2 |
Student height in cm |
Quantitative |
Continuous |
| 3 |
Employee gender (Male / Female) |
Quantitative |
Nominal |
| 4 |
Customer satisfaction level: Low, Medium, High |
Qualitative |
Ordinal |
| 5 |
Respondent’s favorite color: Red, Blue, Green |
Qualitative |
Nominal |
Exercise 3
Classify Data Sources: Determine whether the
following data comes from internal or external
sources, and whether it is structured or
unstructured:
# Install DT package if not already installed
# install.packages("DT")
library(DT)
# Create a data frame for data sources
data_sources <- data.frame(
No = 1:4,
DataSource = c(
"Daily sales transaction data of the company",
"Weather reports from BMKG",
"Product reviews on social media",
"Warehouse inventory reports"
),
Internal_External = c(
"Internal",
"Eksternal",
"Eksternal",
"Internal"
),
Structured_Unstructured = c(
"Structured",
"Structured",
"Unstructured",
"Structured"
),
stringsAsFactors = FALSE
)
# Display the data frame as a neat table
datatable(data_sources,
caption = "Table of Data Sources",
rownames = FALSE) # hides the index column
Exercise 4
Dataset Structure: Consider the following
transaction table:
| 2025-10-01 |
2 |
1000 |
Laptop |
High |
| 2025-10-01 |
5 |
20 |
Mouse |
Medium |
| 2025-10-02 |
1 |
1000 |
Laptop |
Low |
| 2025-10-02 |
3 |
30 |
Keyboard |
Medium |
| 2025-10-03 |
4 |
50 |
Mouse |
Medium |
| 2025-10-03 |
2 |
1000 |
Laptop |
High |
| 2025-10-04 |
6 |
25 |
Keyboard |
Low |
| 2025-10-04 |
1 |
1000 |
Laptop |
High |
| 2025-10-05 |
3 |
40 |
Mouse |
Low |
| 2025-10-05 |
5 |
10 |
Keyboard |
Medium |
Your Assignment Instructions: Creating a
Transactions Table above in R
Create a data frame in R called
transactions containing the data above.
Identify which variables are numeric and which are
categorical
Calculate total revenue for each transaction by
multiplying Qty × Price and add it as a new column
Total.
Compute summary statistics:
- Total quantity sold for each product
- Total revenue per product
- Average price per product
Visualize the data:
- Create a barplot showing total quantity sold per
product.
- Create a pie chart showing the proportion of total
revenue per customer tier.
Optional Challenge:
- Find which date had the highest total revenue.
- Create a stacked bar chart showing quantity sold
per product by customer tier.
Hints: Use data.frame(),
aggregate(), barplot(), pie(),
and basic arithmetic operations in R.
Exercise 5
Create Your Own Data Frame:
Objective: Create a data frame in R with 30
rows containing a mix of data types: continuous, discrete,
nominal, and ordinal.
Instructions
Open RStudio or the R console.
Create a vector for each column in your data
frame:
- Date: 30 dates (can be sequential or random within
a month/year)
- Continuous: numeric values that can take decimal
values (e.g., height, weight, temperature)
- Discrete: numeric values that can only take whole
numbers (e.g., number of items, number of vehicles)
- Nominal: categorical values with no
order (e.g., color, gender, city)
- Ordinal: categorical values with a defined
order (e.g., Low, Medium, High; Beginner, Intermediate,
Expert)
Combine all vectors into a data frame called
my_data.
Check your data frame using head()
or View() to ensure it has 30 rows and the
columns are correct.
Optional tasks:
- Summarize each column using
summary()
- Count the frequency of each category for Nominal
and Ordinal columns using
table()
Hints
- Use
seq.Date() or as.Date() to generate
the Date column.
- Use
runif() or rnorm() for continuous
numeric data.
- Use
sample() for discrete, nominal, and ordinal
data.
- Ensure the ordinal vector is created with
factor(..., levels = c("Low","Medium","High"), ordered = TRUE)
(or similar).
LS0tDQp0aXRsZTogIkRhdGEgRXhwbG9yYXRpb24iICAgICAgICMgTWFpbiB0aXRsZSBvZiB0aGUgZG9jdW1lbnQNCnN1YnRpdGxlOiAiRXhlcmNpc2VzIH4gV2VlayAyIiAgIyBTdWJ0aXRsZSBvciB0b3BpYyBmb3Igd2VlayAyDQphdXRob3I6IA0KLSAiUGFza2FsaXMgRmFyZWxuYXRhIFphbWFzaSINCi0gIk0uIEZpdHJhaCBBaWRpbCBIYXJhaGFwIg0KLSAiSGFuYWZpIE1hbGlrIFJpZmEnaSINCi0gIkRlbiBZdWFuIEZyYXNzZWthIg0KLSAiWmlkaGFuIEFsZmFyZXppIEFmZGkiIyBSZXBsYWNlIHdpdGggeW91ciBmdWxsIG5hbWUNCmRhdGU6ICAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiICMgQXV0byBkaXNwbGF5cyB0aGUgY3VycmVudCBkYXRlDQpvdXRwdXQ6ICAgICAgICAgICAgICAgICAgICAgICAgICMgT3V0cHV0IHNlY3Rpb24gZGVmaW5lcyB0aGUgZm9ybWF0IGFuZCBsYXlvdXQgDQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOiAgICAgICMgaHR0cHM6Ly9naXRodWIuY29tL2p1YmEvcm1kZm9ybWF0cw0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlICAgICAgICAjIEVtYmVkcyBhbGwgcmVzb3VyY2VzIChDU1MsIEpTLCBpbWFnZXMpIA0KICAgIHRodW1ibmFpbHM6IHRydWUgICAgICAgICAgICAjIERpc3BsYXlzIGltYWdlIHRodW1ibmFpbHMgaW4gdGhlIGRvYw0KICAgIGxpZ2h0Ym94OiB0cnVlICAgICAgICAgICAgICAjIEVuYWJsZXMgY2xpY2sgdG8gZW5sYXJnZSBpbWFnZXMNCiAgICBnYWxsZXJ5OiB0cnVlICAgICAgICAgICAgICAgIyBHcm91cHMgaW1hZ2VzIGludG8gYW4gaW50ZXJhY3RpdmUgZ2FsbGVyeQ0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZSAgICAgICAjIEF1dG9tYXRpY2FsbHkgbnVtYmVycyBhbGwgc2VjdGlvbnMNCiAgICBsaWJfZGlyOiBsaWJzICAgICAgICAgICAgICAgIyBEaXJlY3Rvcnkgd2hlcmUgSmF2YVNjcmlwdC9DU1MgbGlicmFyaWVzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCIgICAgICAgICAgICMgRGlzcGxheXMgZGF0YSBmcmFtZXMgYXMgaW50ZXJhY3RpdmUgcGFnZWQgDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyIgICAgICAgICMgQWxsb3dzIGZvbGRpbmcvdW5mb2xkaW5nIFIgY29kZSBibG9ja3MgDQogICAgY29kZV9kb3dubG9hZDogeWVzICAgICAgICAgICMgQWRkcyBhIGJ1dHRvbiB0byBkb3dubG9hZCBhbGwgUiBjb2RlDQotLS0NCg0KDQo8aW1nIGlkPSJGb3RvIiBzcmM9Imh0dHBzOi8vZ2l0aHViLmNvbS9kc2NpZW5jZWxhYnMvaW1hZ2VzL2Jsb2IvbWFzdGVyL0xvZ29fRHNjaWVuY2VsYWJzX3YxLnBuZz9yYXc9dHJ1ZSIgYWx0PSJMb2dvIiBzdHlsZT0id2lkdGg6MjAwcHg7IGRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87Ij4NCg0KLS0tDQoNCiMjIEV4ZXJjaXNlIDENCg0KVGhlIGZvbGxvd2luZyB0YWJsZSBzaG93cyBzYW1wbGUgaW5mb3JtYXRpb24gZm9yIHRocmVlIHN0dWRlbnRzLiBFYWNoIG9ic2VydmF0aW9uIHJlcHJlc2VudHMgYSBzaW5nbGUgc3R1ZGVudCBhbmQgaW5jbHVkZXMgZGV0YWlscyBzdWNoIGFzIHRoZWlyIHVuaXF1ZSBzdHVkZW50IElELCBuYW1lLCBhZ2UsIHRvdGFsIGNyZWRpdHMgY29tcGxldGVkLCBtYWpvciBmaWVsZCBvZiBzdHVkeSwgYW5kIHllYXIgbGV2ZWwuICANCg0KVGhpcyBkYXRhc2V0IGRlbW9uc3RyYXRlcyBhIG1peHR1cmUgb2YgdmFyaWFibGUgdHlwZXM6ICANCg0KLSAqKk5vbWluYWw6KiogU3R1ZGVudElELCBOYW1lLCBNYWpvciAgDQotICoqTnVtZXJpYzoqKiBBZ2UgKGNvbnRpbnVvdXMpLCBDcmVkaXRzQ29tcGxldGVkIChkaXNjcmV0ZSkgIA0KLSAqKk9yZGluYWw6KiogWWVhckxldmVsIChGcmVzaG1hbiDihpIgU2VuaW9yKSAgDQoNCnwgU3R1ZGVudElEIHwgTmFtZSAgIHwgQWdlIHwgQ3JlZGl0c0NvbXBsZXRlZCB8IE1ham9yICAgICAgICAgICAgfCBZZWFyTGV2ZWwgfA0KfC0tLS0tLS0tLS0tfC0tLS0tLS0tfC0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tfA0KfCBTMDAxICAgICAgfCBBbGljZSAgfCAyMCAgfCA0NSAgICAgICAgICAgICAgfCBEYXRhIFNhaW5zICAgICAgfCBTb3Bob21vcmUgfA0KfCBTMDAyICAgICAgfCBCdWRpICAgfCAyMSAgfCA2MCAgICAgICAgICAgICAgfCBNYXRoZW1hdGljcyAgICAgfCBKdW5pb3IgICAgfA0KfCBTMDAzICAgICAgfCBDaXRyYSAgfCAxOSAgfCAzMCAgICAgICAgICAgICAgfCBTdGF0aXN0aWNzICAgICAgfCBGcmVzaG1hbiAgfA0KDQpgYGB7cn0NCiMgMS4gQ3JlYXRlIHZlY3RvcnMgZm9yIGVhY2ggdmFyaWFibGUNClN0dWRlbnRJRCA8LSBjKCJTMDAxIiwgIlMwMDIiLCAiUzAwMyIpICAgICAgICMgTm9taW5hbCAvIElEDQpOYW1lIDwtIGMoIkFsaWNlIiwgIkJ1ZGkiLCAiQ2l0cmEiKSAgICAgICAgICAjIE5vbWluYWwgLyBOYW1lDQpBZ2UgPC0gYygyMCwgMjEsIDE5KSAgICAgICAgICAgICAgICAgICAgICAgICAjIE51bWVyaWMgLyBDb250aW51b3VzDQpDcmVkaXRzQ29tcGxldGVkIDwtIGMoNDUsIDYwLCAzMCkgICAgICAgICAgICAjIE51bWVyaWMgLyBEaXNjcmV0ZQ0KDQojIE5vbWluYWwNCk1ham9yIDwtIGMoIkRhdGEgU2FpbnMiLCAiTWF0aGVtYXRpY3MiLCAiU3RhdGlzdGljcyIpICANCg0KIyBPcmRpbmFsDQpZZWFyTGV2ZWwgPC0gZmFjdG9yKGMoIlNvcGhvbW9yZSIsICJKdW5pb3IiLCAiRnJlc2htYW4iKSwNCiAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiRnJlc2htYW4iLCJTb3Bob21vcmUiLCJKdW5pb3IiLCJTZW5pb3IiKSwNCiAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpICAgICAgICAgIA0KDQojIDIuIENvbWJpbmUgYWxsIHZlY3RvcnMgaW50byBhIGRhdGEgZnJhbWUNCnN0dWRlbnRzIDwtIGRhdGEuZnJhbWUoDQogIFN0dWRlbnRJRCwgTmFtZSwgQWdlLCBDcmVkaXRzQ29tcGxldGVkLCBNYWpvciwgWWVhckxldmVsLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCikNCg0KIyAzLiBEaXNwbGF5IHRoZSBkYXRhIGZyYW1lDQpwcmludChzdHVkZW50cykNCmBgYA0KDQoNCiMjIEV4ZXJjaXNlIDINCg0KKipJZGVudGlmeSBEYXRhIFR5cGVzOioqIERldGVybWluZSB0aGUgdHlwZSBvZiBkYXRhIGZvciBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgdmFyaWFibGVzOg0KDQpgYGB7cn0NCiMgSW5zdGFsbCBrbml0ciBwYWNrYWdlIGlmIG5vdCBhbHJlYWR5IGluc3RhbGxlZA0KIyBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIENyZWF0ZSBhIGRhdGEgZnJhbWUgZm9yIERhdGEgVHlwZXMNCnZhcmlhYmxlc19pbmZvIDwtIGRhdGEuZnJhbWUoDQogIE5vID0gMTo1LA0KICBWYXJpYWJsZSA9IGMoDQogICAgIk51bWJlciBvZiB2ZWhpY2xlcyBwYXNzaW5nIHRocm91Z2ggdGhlIHRvbGwgcm9hZCBlYWNoIGRheSIsDQogICAgIlN0dWRlbnQgaGVpZ2h0IGluIGNtIiwNCiAgICAiRW1wbG95ZWUgZ2VuZGVyIChNYWxlIC8gRmVtYWxlKSIsDQogICAgIkN1c3RvbWVyIHNhdGlzZmFjdGlvbiBsZXZlbDogTG93LCBNZWRpdW0sIEhpZ2giLA0KICAgICJSZXNwb25kZW50J3MgZmF2b3JpdGUgY29sb3I6IFJlZCwgQmx1ZSwgR3JlZW4iDQogICksDQogIERhdGFUeXBlID0gYygNCiAgICAiUXVhbnRpdGF0aXZlIiwNCiAgICAiUXVhbnRpdGF0aXZlIiwNCiAgICAiUXVhbnRpdGF0aXZlIiwNCiAgICAiUXVhbGl0YXRpdmUiLA0KICAgICJRdWFsaXRhdGl2ZSINCiAgKSwNCiAgU3VidHlwZSA9IGMoDQogICAgIkRpc2tyZXRlIiwNCiAgICAiQ29udGludW91cyIsDQogICAgIk5vbWluYWwiLA0KICAgICJPcmRpbmFsIiwNCiAgICAiTm9taW5hbCINCiAgKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCiMgRGlzcGxheSB0aGUgZGF0YSBmcmFtZSBhcyBhIG5lYXQgdGFibGUNCmthYmxlKHZhcmlhYmxlc19pbmZvLCANCiAgICAgIGNhcHRpb24gPSAiVGFibGUgb2YgVmFyaWFibGVzIGFuZCBEYXRhIFR5cGVzIikNCmBgYA0KLS0tDQoNCiMjIEV4ZXJjaXNlIDMNCg0KKipDbGFzc2lmeSBEYXRhIFNvdXJjZXM6KiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhlIGZvbGxvd2luZyBkYXRhIGNvbWVzIGZyb20gKippbnRlcm5hbCoqIG9yICoqZXh0ZXJuYWwgc291cmNlcyoqLCBhbmQgd2hldGhlciBpdCBpcyAqKnN0cnVjdHVyZWQqKiBvciAqKnVuc3RydWN0dXJlZCoqOg0KDQpgYGB7cn0NCiMgSW5zdGFsbCBEVCBwYWNrYWdlIGlmIG5vdCBhbHJlYWR5IGluc3RhbGxlZA0KIyBpbnN0YWxsLnBhY2thZ2VzKCJEVCIpIA0KbGlicmFyeShEVCkNCg0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIGZvciBkYXRhIHNvdXJjZXMgDQpkYXRhX3NvdXJjZXMgPC0gZGF0YS5mcmFtZSgNCiAgTm8gPSAxOjQsDQogIERhdGFTb3VyY2UgPSBjKA0KICAgICJEYWlseSBzYWxlcyB0cmFuc2FjdGlvbiBkYXRhIG9mIHRoZSBjb21wYW55IiwNCiAgICAiV2VhdGhlciByZXBvcnRzIGZyb20gQk1LRyIsDQogICAgIlByb2R1Y3QgcmV2aWV3cyBvbiBzb2NpYWwgbWVkaWEiLA0KICAgICJXYXJlaG91c2UgaW52ZW50b3J5IHJlcG9ydHMiDQogICksDQogIEludGVybmFsX0V4dGVybmFsID0gYygNCiAgICAiSW50ZXJuYWwiLA0KICAgICJFa3N0ZXJuYWwiLA0KICAgICJFa3N0ZXJuYWwiLA0KICAgICJJbnRlcm5hbCINCiAgKSwNCiAgU3RydWN0dXJlZF9VbnN0cnVjdHVyZWQgPSBjKA0KICAgICJTdHJ1Y3R1cmVkIiwNCiAgICAiU3RydWN0dXJlZCIsDQogICAgIlVuc3RydWN0dXJlZCIsDQogICAgIlN0cnVjdHVyZWQiDQogICksDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KKQ0KDQojIERpc3BsYXkgdGhlIGRhdGEgZnJhbWUgYXMgYSBuZWF0IHRhYmxlDQpkYXRhdGFibGUoZGF0YV9zb3VyY2VzLCANCiAgICAgICAgICBjYXB0aW9uID0gIlRhYmxlIG9mIERhdGEgU291cmNlcyIsDQogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSkgIyBoaWRlcyB0aGUgaW5kZXggY29sdW1uDQpgYGANCg0KLS0tDQoNCiMjIEV4ZXJjaXNlIDQNCg0KKipEYXRhc2V0IFN0cnVjdHVyZToqKiBDb25zaWRlciB0aGUgZm9sbG93aW5nIHRyYW5zYWN0aW9uIHRhYmxlOg0KDQp8IERhdGUgICAgICAgfCBRdHkgfCBQcmljZSB8IFByb2R1Y3QgIHwgQ3VzdG9tZXJUaWVyIHwNCnwtLS0tLS0tLS0tLS18LS0tLS18LS0tLS0tLXwtLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tfA0KfCAyMDI1LTEwLTAxIHwgMiAgIHwgMTAwMCAgfCBMYXB0b3AgICB8IEhpZ2ggICAgICAgICB8DQp8IDIwMjUtMTAtMDEgfCA1ICAgfCAyMCAgICB8IE1vdXNlICAgIHwgTWVkaXVtICAgICAgIHwNCnwgMjAyNS0xMC0wMiB8IDEgICB8IDEwMDAgIHwgTGFwdG9wICAgfCBMb3cgICAgICAgICAgfA0KfCAyMDI1LTEwLTAyIHwgMyAgIHwgMzAgICAgfCBLZXlib2FyZCB8IE1lZGl1bSAgICAgICB8DQp8IDIwMjUtMTAtMDMgfCA0ICAgfCA1MCAgICB8IE1vdXNlICAgIHwgTWVkaXVtICAgICAgIHwNCnwgMjAyNS0xMC0wMyB8IDIgICB8IDEwMDAgIHwgTGFwdG9wICAgfCBIaWdoICAgICAgICAgfA0KfCAyMDI1LTEwLTA0IHwgNiAgIHwgMjUgICAgfCBLZXlib2FyZCB8IExvdyAgICAgICAgICB8DQp8IDIwMjUtMTAtMDQgfCAxICAgfCAxMDAwICB8IExhcHRvcCAgIHwgSGlnaCAgICAgICAgIHwNCnwgMjAyNS0xMC0wNSB8IDMgICB8IDQwICAgIHwgTW91c2UgICAgfCBMb3cgICAgICAgICAgfA0KfCAyMDI1LTEwLTA1IHwgNSAgIHwgMTAgICAgfCBLZXlib2FyZCB8IE1lZGl1bSAgICAgICB8DQoNCg0KKipZb3VyIEFzc2lnbm1lbnQgSW5zdHJ1Y3Rpb25zOioqIENyZWF0aW5nIGEgVHJhbnNhY3Rpb25zIFRhYmxlIGFib3ZlIGluIFINCg0KMS4gKipDcmVhdGUgYSBkYXRhIGZyYW1lKiogaW4gUiBjYWxsZWQgYHRyYW5zYWN0aW9uc2AgY29udGFpbmluZyB0aGUgZGF0YSBhYm92ZS4NCg0KMi4gSWRlbnRpZnkgd2hpY2ggdmFyaWFibGVzIGFyZSBudW1lcmljIGFuZCB3aGljaCBhcmUgY2F0ZWdvcmljYWwNCg0KMy4gKipDYWxjdWxhdGUgdG90YWwgcmV2ZW51ZSoqIGZvciBlYWNoIHRyYW5zYWN0aW9uIGJ5IG11bHRpcGx5aW5nIGBRdHkgw5cgUHJpY2VgIGFuZCBhZGQgaXQgYXMgYSBuZXcgY29sdW1uIGBUb3RhbGAuDQoNCjQuICoqQ29tcHV0ZSBzdW1tYXJ5IHN0YXRpc3RpY3MqKjoNCiAgIC0gVG90YWwgcXVhbnRpdHkgc29sZCBmb3IgZWFjaCBwcm9kdWN0DQogICAtIFRvdGFsIHJldmVudWUgcGVyIHByb2R1Y3QNCiAgIC0gQXZlcmFnZSBwcmljZSBwZXIgcHJvZHVjdA0KDQo1LiAqKlZpc3VhbGl6ZSB0aGUgZGF0YSoqOg0KICAgLSBDcmVhdGUgYSAqKmJhcnBsb3QqKiBzaG93aW5nIHRvdGFsIHF1YW50aXR5IHNvbGQgcGVyIHByb2R1Y3QuDQogICAtIENyZWF0ZSBhICoqcGllIGNoYXJ0Kiogc2hvd2luZyB0aGUgcHJvcG9ydGlvbiBvZiB0b3RhbCByZXZlbnVlIHBlciBjdXN0b21lciB0aWVyLg0KDQo2LiAqKk9wdGlvbmFsIENoYWxsZW5nZSoqOg0KICAgLSBGaW5kIHdoaWNoICoqZGF0ZSoqIGhhZCB0aGUgaGlnaGVzdCB0b3RhbCByZXZlbnVlLg0KICAgLSBDcmVhdGUgYSAqKnN0YWNrZWQgYmFyIGNoYXJ0Kiogc2hvd2luZyBxdWFudGl0eSBzb2xkIHBlciBwcm9kdWN0IGJ5IGN1c3RvbWVyIHRpZXIuDQoNCioqSGludHM6KiogVXNlIGBkYXRhLmZyYW1lKClgLCBgYWdncmVnYXRlKClgLCBgYmFycGxvdCgpYCwgYHBpZSgpYCwgYW5kIGJhc2ljIGFyaXRobWV0aWMgb3BlcmF0aW9ucyBpbiBSLg0KDQoNCiMjIEV4ZXJjaXNlIDUNCg0KKipDcmVhdGUgWW91ciBPd24gRGF0YSBGcmFtZToqKg0KDQoqKk9iamVjdGl2ZToqKiBDcmVhdGUgYSBkYXRhIGZyYW1lIGluIFIgd2l0aCAqKjMwIHJvd3MqKiBjb250YWluaW5nIGEgbWl4IG9mIGRhdGEgdHlwZXM6IGNvbnRpbnVvdXMsIGRpc2NyZXRlLCBub21pbmFsLCBhbmQgb3JkaW5hbC4gIA0KDQojIyMgSW5zdHJ1Y3Rpb25zDQoNCjEuICoqT3BlbiBSU3R1ZGlvKiogb3IgdGhlIFIgY29uc29sZS4gIA0KDQoyLiAqKkNyZWF0ZSBhIHZlY3RvciBmb3IgZWFjaCBjb2x1bW4qKiBpbiB5b3VyIGRhdGEgZnJhbWU6ICANCg0KICAgLSAqKkRhdGUqKjogMzAgZGF0ZXMgKGNhbiBiZSBzZXF1ZW50aWFsIG9yIHJhbmRvbSB3aXRoaW4gYSBtb250aC95ZWFyKSAgDQogICAtICoqQ29udGludW91cyoqOiBudW1lcmljIHZhbHVlcyB0aGF0IGNhbiB0YWtlIGRlY2ltYWwgdmFsdWVzIChlLmcuLCBoZWlnaHQsIHdlaWdodCwgdGVtcGVyYXR1cmUpICANCiAgIC0gKipEaXNjcmV0ZSoqOiBudW1lcmljIHZhbHVlcyB0aGF0IGNhbiBvbmx5IHRha2Ugd2hvbGUgbnVtYmVycyAoZS5nLiwgbnVtYmVyIG9mIGl0ZW1zLCBudW1iZXIgb2YgdmVoaWNsZXMpICANCiAgIC0gKipOb21pbmFsKio6IGNhdGVnb3JpY2FsIHZhbHVlcyB3aXRoICoqbm8gb3JkZXIqKiAoZS5nLiwgY29sb3IsIGdlbmRlciwgY2l0eSkgIA0KICAgLSAqKk9yZGluYWwqKjogY2F0ZWdvcmljYWwgdmFsdWVzIHdpdGggYSAqKmRlZmluZWQgb3JkZXIqKiAoZS5nLiwgTG93LCBNZWRpdW0sIEhpZ2g7IEJlZ2lubmVyLCBJbnRlcm1lZGlhdGUsIEV4cGVydCkgIA0KDQozLiAqKkNvbWJpbmUgYWxsIHZlY3RvcnMgaW50byBhIGRhdGEgZnJhbWUqKiBjYWxsZWQgYG15X2RhdGFgLiAgDQoNCjQuICoqQ2hlY2sgeW91ciBkYXRhIGZyYW1lKiogdXNpbmcgYGhlYWQoKWAgb3IgYFZpZXcoKWAgdG8gZW5zdXJlIGl0IGhhcyAqKjMwIHJvd3MqKiBhbmQgdGhlIGNvbHVtbnMgYXJlIGNvcnJlY3QuICANCg0KNS4gKipPcHRpb25hbCB0YXNrcyoqOiAgDQogICAtIFN1bW1hcml6ZSBlYWNoIGNvbHVtbiB1c2luZyBgc3VtbWFyeSgpYCAgDQogICAtIENvdW50IHRoZSBmcmVxdWVuY3kgb2YgZWFjaCBjYXRlZ29yeSBmb3IgKipOb21pbmFsKiogYW5kICoqT3JkaW5hbCoqIGNvbHVtbnMgdXNpbmcgYHRhYmxlKClgICANCg0KIyMjIEhpbnRzDQoNCi0gVXNlIGBzZXEuRGF0ZSgpYCBvciBgYXMuRGF0ZSgpYCB0byBnZW5lcmF0ZSB0aGUgRGF0ZSBjb2x1bW4uICANCi0gVXNlIGBydW5pZigpYCBvciBgcm5vcm0oKWAgZm9yIGNvbnRpbnVvdXMgbnVtZXJpYyBkYXRhLiAgDQotIFVzZSBgc2FtcGxlKClgIGZvciBkaXNjcmV0ZSwgbm9taW5hbCwgYW5kIG9yZGluYWwgZGF0YS4gIA0KLSBFbnN1cmUgdGhlICoqb3JkaW5hbCB2ZWN0b3IqKiBpcyBjcmVhdGVkIHdpdGggYGZhY3RvciguLi4sIGxldmVscyA9IGMoIkxvdyIsIk1lZGl1bSIsIkhpZ2giKSwgb3JkZXJlZCA9IFRSVUUpYCAob3Igc2ltaWxhcikuICANCg0KDQoNCg0KDQo=