Data Exploration

Exercises ~ Week 2

Logo


1 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)
StudentID Name Age CreditsCompleted Major YearLevel
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

2 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(
    "Numeric",
    "Numeric",
    "Categorical",
    "Categorical",
    "Categorical"
  ),
  Subtype = c(
    "Discrete",
    "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
No Variable DataType Subtype
1 Number of vehicles passing through the toll road each day Numeric Discrete
2 Student height in cm Numeric Continuous
3 Employee gender (Male / Female) Categorical Nominal
4 Customer satisfaction level: Low, Medium, High Categorical Ordinal
5 Respondent’s favorite color: Red, Blue, Green Categorical Nominal

3 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",
    "External",
    "External",
    "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

4 Exercise 4

Dataset Structure: Consider the following transaction table:

Date Qty Price Product CustomerTier
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

  1. Create a data frame in R called transactions containing the data above.

  2. Identify which variables are numeric and which are categorical

  3. Calculate total revenue for each transaction by multiplying Qty × Price and add it as a new column Total.

  4. Compute summary statistics:

    • Total quantity sold for each product
    • Total revenue per product
    • Average price per product
  5. 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.
  6. 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.

library(DT)

#transaction
Date <- c("2025-10-01", "2025-10-01", "2025-10-02", "2025-10-02", "2025-10-03", 
          "2025-10-03", "2025-10-04", "2025-10-04", "2025-10-05", "2025-10-05")
Qty <- c(2, 5, 1, 3, 4, 2, 6, 1, 3, 5)
Price <- c(1000, 20, 1000, 30, 50, 1000, 25, 1000, 40, 10)
Product <- c("Laptop", "Mouse", "Laptop", "Keyboard", "Mouse", "Laptop", 
             "Keyboard", "Laptop", "Mouse", "Keyboard")
CustomerTier <- c("High", "Medium", "Low", "Medium", "Medium", "High", 
                  "Low", "High", "Low", "Medium")

# data frame 
transactions <- data.frame(Date, Qty, Price, Product, CustomerTier)

# Display the data frame 
print(transactions)
##          Date Qty Price  Product CustomerTier
## 1  2025-10-01   2  1000   Laptop         High
## 2  2025-10-01   5    20    Mouse       Medium
## 3  2025-10-02   1  1000   Laptop          Low
## 4  2025-10-02   3    30 Keyboard       Medium
## 5  2025-10-03   4    50    Mouse       Medium
## 6  2025-10-03   2  1000   Laptop         High
## 7  2025-10-04   6    25 Keyboard          Low
## 8  2025-10-04   1  1000   Laptop         High
## 9  2025-10-05   3    40    Mouse          Low
## 10 2025-10-05   5    10 Keyboard       Medium
# Create a data frame for data types
variables_info <- data.frame(
  Variable = c(
    "Qty",
    "Price",
    "Product",
    "CustomerTier"
  ),
  DataType = c(
    "Numeric",
    "Numeric",
    "Categorical",
    "Categorical"
  ),
  stringsAsFactors = FALSE
)

print(variables_info)
##       Variable    DataType
## 1          Qty     Numeric
## 2        Price     Numeric
## 3      Product Categorical
## 4 CustomerTier Categorical
# 3 Total Reveneu
transactions$total <- transactions$Qty * transactions$Price

# view the data frame 
print(transactions)
##          Date Qty Price  Product CustomerTier total
## 1  2025-10-01   2  1000   Laptop         High  2000
## 2  2025-10-01   5    20    Mouse       Medium   100
## 3  2025-10-02   1  1000   Laptop          Low  1000
## 4  2025-10-02   3    30 Keyboard       Medium    90
## 5  2025-10-03   4    50    Mouse       Medium   200
## 6  2025-10-03   2  1000   Laptop         High  2000
## 7  2025-10-04   6    25 Keyboard          Low   150
## 8  2025-10-04   1  1000   Laptop         High  1000
## 9  2025-10-05   3    40    Mouse          Low   120
## 10 2025-10-05   5    10 Keyboard       Medium    50
qty_summary <- aggregate(Qty ~ Product, data = transactions, sum) 
print(qty_summary)
##    Product Qty
## 1 Keyboard  14
## 2   Laptop   6
## 3    Mouse  12
total_summary <- aggregate(total ~ Product, data = transactions, sum) 
print(total_summary)
##    Product total
## 1 Keyboard   290
## 2   Laptop  6000
## 3    Mouse   420
Price_summary <- aggregate(Price ~ Product, data = transactions, mean)
print(Price_summary)
##    Product      Price
## 1 Keyboard   21.66667
## 2   Laptop 1000.00000
## 3    Mouse   36.66667
# Calculate total quantity per product
qty_per_product <- aggregate(Qty ~ Product, data = transactions, sum)

# Create a bar plot 
barplot (qty_per_product$Qty,
         names.arg = qty_per_product$Product, 
         col = "orange", 
         main = "Total Quantity Sold per Product",
         xlab = "Product", ylab = "Quantity Sold")

# Calculate total revenue per CustomerTier
revenue_tier <- aggregate(total ~ CustomerTier, data = transactions, sum) 

# create pie chart 
pie(revenue_tier$tota, 
    labels = revenue_tier$CustomerTier, 
    main = "Proportion of Total Revenue per Customer Tier",
    col = c("red", "orange", "pink"))

# Hitung total revenue per tanggal
revenue_per_date <- aggregate(total ~ Date, data = transactions, sum)

# Lihat hasilnya
print(revenue_per_date)
##         Date total
## 1 2025-10-01  2100
## 2 2025-10-02  1090
## 3 2025-10-03  2200
## 4 2025-10-04  1150
## 5 2025-10-05   170
# Cari tanggal dengan total revenue paling tingi menggunakan max
max_date <- revenue_per_date[which.max(revenue_per_date$total), ]

#lihat hasilnya
print(max_date)
##         Date total
## 3 2025-10-03  2200
library(ggplot2)

# Bikin stacked bar chart
ggplot(transactions, aes(x = reorder(Product, Qty), y = Qty, fill = CustomerTier)) +
  geom_bar(stat = "identity") +
  labs(title = "Quantity Sold per Product by Customer Tier",
       x = "Product",
       y = "Quantity Sold") +
  theme_minimal()


5 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.

5.1 Instructions

  1. Open RStudio or the R console.

  2. 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)
  3. Combine all vectors into a data frame called my_data.

  4. Check your data frame using head() or View() to ensure it has 30 rows and the columns are correct.

  5. Optional tasks:

    • Summarize each column using summary()
    • Count the frequency of each category for Nominal and Ordinal columns using table()

5.2 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).
library(DT)

# Data Financial Frame

# column 1: Transaction Date
Date <- seq.Date(from = as.Date("2025-10-01"), by = "day", length.out = 30)

# Column 2: Transaction value (Continuous) — In rupiah
TransactionValue <- c(
  1250000, 980000, 1500000, 2100000, 1850000, 750000, 2400000, 1300000, 1780000, 2220000,
  1950000, 1650000, 1420000, 2550000, 3100000, 2750000, 1980000, 880000, 1750000, 2200000,
  1900000, 2600000, 2450000, 1350000, 1500000, 900000, 1200000, 2750000, 3200000, 2100000
)

# Column 3: Number of items purchased (Discrete)
Items <- c(
  2, 1, 3, 5, 4, 2, 6, 3, 5, 4,
  2, 3, 1, 7, 8, 5, 3, 2, 4, 6,
  5, 7, 8, 3, 4, 1, 2, 7, 9, 5
)

# Column 4: Transaction type (Nominal)
TransactionType <- c(
  "Pembelian Tunai", "Transfer Bank", "Kartu Kredit", "Pembelian Tunai", "E-Wallet",
  "Transfer Bank", "Kartu Kredit", "E-Wallet", "Pembelian Tunai", "E-Wallet",
  "Kartu Kredit", "Pembelian Tunai", "Transfer Bank", "E-Wallet", "Kartu Kredit",
  "Pembelian Tunai", "E-Wallet", "Transfer Bank", "Kartu Kredit", "Pembelian Tunai",
  "E-Wallet", "Transfer Bank", "Kartu Kredit", "Pembelian Tunai", "E-Wallet",
  "Kartu Kredit", "Transfer Bank", "Pembelian Tunai", "E-Wallet", "Transfer Bank"
)

# Kolom 5: Customer Tier (Ordinal)
CustomerTier <- factor(
  c(
    "Sedang", "Rendah", "Sedang", "Tinggi", "Sedang", "Rendah", "Tinggi", "Sedang", "Tinggi", "Sedang",
    "Rendah", "Tinggi", "Sedang", "Tinggi", "Tinggi", "Sedang", "Rendah", "Sedang", "Tinggi", "Sedang",
    "Rendah", "Tinggi", "Tinggi", "Rendah", "Sedang", "Rendah", "Sedang", "Tinggi", "Tinggi", "Sedang"
  ),
  levels = c("Rendah", "Sedang", "Tinggi"),
  ordered = TRUE
)

# Combine into a data frame
data_financial <- data.frame(Date, TransactionValue, Items, TransactionType, CustomerTier)

# Display the data frame as a table
print(data_financial)
##          Date TransactionValue Items TransactionType CustomerTier
## 1  2025-10-01          1250000     2 Pembelian Tunai       Sedang
## 2  2025-10-02           980000     1   Transfer Bank       Rendah
## 3  2025-10-03          1500000     3    Kartu Kredit       Sedang
## 4  2025-10-04          2100000     5 Pembelian Tunai       Tinggi
## 5  2025-10-05          1850000     4        E-Wallet       Sedang
## 6  2025-10-06           750000     2   Transfer Bank       Rendah
## 7  2025-10-07          2400000     6    Kartu Kredit       Tinggi
## 8  2025-10-08          1300000     3        E-Wallet       Sedang
## 9  2025-10-09          1780000     5 Pembelian Tunai       Tinggi
## 10 2025-10-10          2220000     4        E-Wallet       Sedang
## 11 2025-10-11          1950000     2    Kartu Kredit       Rendah
## 12 2025-10-12          1650000     3 Pembelian Tunai       Tinggi
## 13 2025-10-13          1420000     1   Transfer Bank       Sedang
## 14 2025-10-14          2550000     7        E-Wallet       Tinggi
## 15 2025-10-15          3100000     8    Kartu Kredit       Tinggi
## 16 2025-10-16          2750000     5 Pembelian Tunai       Sedang
## 17 2025-10-17          1980000     3        E-Wallet       Rendah
## 18 2025-10-18           880000     2   Transfer Bank       Sedang
## 19 2025-10-19          1750000     4    Kartu Kredit       Tinggi
## 20 2025-10-20          2200000     6 Pembelian Tunai       Sedang
## 21 2025-10-21          1900000     5        E-Wallet       Rendah
## 22 2025-10-22          2600000     7   Transfer Bank       Tinggi
## 23 2025-10-23          2450000     8    Kartu Kredit       Tinggi
## 24 2025-10-24          1350000     3 Pembelian Tunai       Rendah
## 25 2025-10-25          1500000     4        E-Wallet       Sedang
## 26 2025-10-26           900000     1    Kartu Kredit       Rendah
## 27 2025-10-27          1200000     2   Transfer Bank       Sedang
## 28 2025-10-28          2750000     7 Pembelian Tunai       Tinggi
## 29 2025-10-29          3200000     9        E-Wallet       Tinggi
## 30 2025-10-30          2100000     5   Transfer Bank       Sedang
# Create a second table for variable type
variables_info <- data.frame(
  No = 1:4,
  variable = c(
    "Transaction Value",
    "Items",
    "Transaction Type",
    "Customer Tier"
),
  DataType = c(
      "Continuous",
      "Discrete",
      "Nominal",
      "Ordinal"
    ),
    stringsAsFactors = FALSE
  )

library(knitr)

kable(
  variables_info,
  caption = "Table of Variables and Data Types"
)
Table of Variables and Data Types
No variable DataType
1 Transaction Value Continuous
2 Items Discrete
3 Transaction Type Nominal
4 Customer Tier Ordinal
LS0tDQp0aXRsZTogIkRhdGEgRXhwbG9yYXRpb24iICAgICAgICMgTWFpbiB0aXRsZSBvZiB0aGUgZG9jdW1lbnQNCnN1YnRpdGxlOiAiRXhlcmNpc2VzIH4gV2VlayAyIiAgIyBTdWJ0aXRsZSBvciB0b3BpYyBmb3Igd2VlayAyDQphdXRob3I6ICJrZWxvbXBvayAzIA0KLSBOYWlmYWggRWRyaWEgQXJ0YSAoIDUyMjUwMDU2KSANCi0gRnJpenp5IExpdGhtZW5zeWFoICg1MjI1MDA2MikgDQotIEx1bHUgTmFqbGEgU2Fsc2FiaWxhICggNTIyNTAwNjkpIA0KLSBOYWlsYSBTeWFocmFuaSBQdXRyaSAoNTIyNTAwNzApIA0KLSBOaS5NRCBBdXJvcmEgU2VrYXJuaW5ncnVtICg1MjI1MDA3MikiICAgIyBSZXBsYWNlIHdpdGggeW91ciBmdWxsIG5hbWUNCmRhdGU6ICAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiICMgQXV0byBkaXNwbGF5cyB0aGUgY3VycmVudCBkYXRlDQpvdXRwdXQ6ICAgICAgICAgICAgICAgICAgICAgICAgICMgT3V0cHV0IHNlY3Rpb24gZGVmaW5lcyB0aGUgZm9ybWF0IGFuZCBsYXlvdXQgDQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOiAgICAgICMgaHR0cHM6Ly9naXRodWIuY29tL2p1YmEvcm1kZm9ybWF0cw0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlICAgICAgICAjIEVtYmVkcyBhbGwgcmVzb3VyY2VzIChDU1MsIEpTLCBpbWFnZXMpIA0KICAgIHRodW1ibmFpbHM6IHRydWUgICAgICAgICAgICAjIERpc3BsYXlzIGltYWdlIHRodW1ibmFpbHMgaW4gdGhlIGRvYw0KICAgIGxpZ2h0Ym94OiB0cnVlICAgICAgICAgICAgICAjIEVuYWJsZXMgY2xpY2sgdG8gZW5sYXJnZSBpbWFnZXMNCiAgICBnYWxsZXJ5OiB0cnVlICAgICAgICAgICAgICAgIyBHcm91cHMgaW1hZ2VzIGludG8gYW4gaW50ZXJhY3RpdmUgZ2FsbGVyeQ0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZSAgICAgICAjIEF1dG9tYXRpY2FsbHkgbnVtYmVycyBhbGwgc2VjdGlvbnMNCiAgICBsaWJfZGlyOiBsaWJzICAgICAgICAgICAgICAgIyBEaXJlY3Rvcnkgd2hlcmUgSmF2YVNjcmlwdC9DU1MgbGlicmFyaWVzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCIgICAgICAgICAgICMgRGlzcGxheXMgZGF0YSBmcmFtZXMgYXMgaW50ZXJhY3RpdmUgcGFnZWQgDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyIgICAgICAgICMgQWxsb3dzIGZvbGRpbmcvdW5mb2xkaW5nIFIgY29kZSBibG9ja3MgDQogICAgY29kZV9kb3dubG9hZDogeWVzICAgICAgICAgICMgQWRkcyBhIGJ1dHRvbiB0byBkb3dubG9hZCBhbGwgUiBjb2RlDQotLS0NCg0KDQo8aW1nIGlkPSJGb3RvIiBzcmM9Imh0dHBzOi8vZ2l0aHViLmNvbS9kc2NpZW5jZWxhYnMvaW1hZ2VzL2Jsb2IvbWFzdGVyL0xvZ29fRHNjaWVuY2VsYWJzX3YxLnBuZz9yYXc9dHJ1ZSIgYWx0PSJMb2dvIiBzdHlsZT0id2lkdGg6MjAwcHg7IGRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87Ij4NCg0KLS0tDQoNCiMjIEV4ZXJjaXNlIDENCg0KVGhlIGZvbGxvd2luZyB0YWJsZSBzaG93cyBzYW1wbGUgaW5mb3JtYXRpb24gZm9yIHRocmVlIHN0dWRlbnRzLiBFYWNoIG9ic2VydmF0aW9uIHJlcHJlc2VudHMgYSBzaW5nbGUgc3R1ZGVudCBhbmQgaW5jbHVkZXMgZGV0YWlscyBzdWNoIGFzIHRoZWlyIHVuaXF1ZSBzdHVkZW50IElELCBuYW1lLCBhZ2UsIHRvdGFsIGNyZWRpdHMgY29tcGxldGVkLCBtYWpvciBmaWVsZCBvZiBzdHVkeSwgYW5kIHllYXIgbGV2ZWwuICANCg0KVGhpcyBkYXRhc2V0IGRlbW9uc3RyYXRlcyBhIG1peHR1cmUgb2YgdmFyaWFibGUgdHlwZXM6ICANCg0KLSAqKk5vbWluYWw6KiogU3R1ZGVudElELCBOYW1lLCBNYWpvciAgDQotICoqTnVtZXJpYzoqKiBBZ2UgKGNvbnRpbnVvdXMpLCBDcmVkaXRzQ29tcGxldGVkIChkaXNjcmV0ZSkgIA0KLSAqKk9yZGluYWw6KiogWWVhckxldmVsIChGcmVzaG1hbiDihpIgU2VuaW9yKSAgDQoNCnwgU3R1ZGVudElEIHwgTmFtZSAgIHwgQWdlIHwgQ3JlZGl0c0NvbXBsZXRlZCB8IE1ham9yICAgICAgICAgICAgfCBZZWFyTGV2ZWwgfA0KfC0tLS0tLS0tLS0tfC0tLS0tLS0tfC0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tfA0KfCBTMDAxICAgICAgfCBBbGljZSAgfCAyMCAgfCA0NSAgICAgICAgICAgICAgfCBEYXRhIFNhaW5zICAgICAgfCBTb3Bob21vcmUgfA0KfCBTMDAyICAgICAgfCBCdWRpICAgfCAyMSAgfCA2MCAgICAgICAgICAgICAgfCBNYXRoZW1hdGljcyAgICAgfCBKdW5pb3IgICAgfA0KfCBTMDAzICAgICAgfCBDaXRyYSAgfCAxOSAgfCAzMCAgICAgICAgICAgICAgfCBTdGF0aXN0aWNzICAgICAgfCBGcmVzaG1hbiAgfA0KDQpgYGB7cn0NCiMgMS4gQ3JlYXRlIHZlY3RvcnMgZm9yIGVhY2ggdmFyaWFibGUNClN0dWRlbnRJRCA8LSBjKCJTMDAxIiwgIlMwMDIiLCAiUzAwMyIpICAgICAgICMgTm9taW5hbCAvIElEDQpOYW1lIDwtIGMoIkFsaWNlIiwgIkJ1ZGkiLCAiQ2l0cmEiKSAgICAgICAgICAjIE5vbWluYWwgLyBOYW1lDQpBZ2UgPC0gYygyMCwgMjEsIDE5KSAgICAgICAgICAgICAgICAgICAgICAgICAjIE51bWVyaWMgLyBDb250aW51b3VzDQpDcmVkaXRzQ29tcGxldGVkIDwtIGMoNDUsIDYwLCAzMCkgICAgICAgICAgICAjIE51bWVyaWMgLyBEaXNjcmV0ZQ0KDQojIE5vbWluYWwNCk1ham9yIDwtIGMoIkRhdGEgU2FpbnMiLCAiTWF0aGVtYXRpY3MiLCAiU3RhdGlzdGljcyIpICANCg0KIyBPcmRpbmFsDQpZZWFyTGV2ZWwgPC0gZmFjdG9yKGMoIlNvcGhvbW9yZSIsICJKdW5pb3IiLCAiRnJlc2htYW4iKSwNCiAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiRnJlc2htYW4iLCJTb3Bob21vcmUiLCJKdW5pb3IiLCJTZW5pb3IiKSwNCiAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpICAgICAgICAgIA0KDQojIDIuIENvbWJpbmUgYWxsIHZlY3RvcnMgaW50byBhIGRhdGEgZnJhbWUNCnN0dWRlbnRzIDwtIGRhdGEuZnJhbWUoDQogIFN0dWRlbnRJRCwgTmFtZSwgQWdlLCBDcmVkaXRzQ29tcGxldGVkLCBNYWpvciwgWWVhckxldmVsLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCikNCg0KIyAzLiBEaXNwbGF5IHRoZSBkYXRhIGZyYW1lDQpwcmludChzdHVkZW50cykNCmBgYA0KDQoNCiMjIEV4ZXJjaXNlIDINCg0KKipJZGVudGlmeSBEYXRhIFR5cGVzOioqIERldGVybWluZSB0aGUgdHlwZSBvZiBkYXRhIGZvciBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgdmFyaWFibGVzOg0KDQpgYGB7cn0NCiMgSW5zdGFsbCBrbml0ciBwYWNrYWdlIGlmIG5vdCBhbHJlYWR5IGluc3RhbGxlZA0KIyBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIENyZWF0ZSBhIGRhdGEgZnJhbWUgZm9yIERhdGEgVHlwZXMNCnZhcmlhYmxlc19pbmZvIDwtIGRhdGEuZnJhbWUoDQogIE5vID0gMTo1LA0KICBWYXJpYWJsZSA9IGMoDQogICAgIk51bWJlciBvZiB2ZWhpY2xlcyBwYXNzaW5nIHRocm91Z2ggdGhlIHRvbGwgcm9hZCBlYWNoIGRheSIsDQogICAgIlN0dWRlbnQgaGVpZ2h0IGluIGNtIiwNCiAgICAiRW1wbG95ZWUgZ2VuZGVyIChNYWxlIC8gRmVtYWxlKSIsDQogICAgIkN1c3RvbWVyIHNhdGlzZmFjdGlvbiBsZXZlbDogTG93LCBNZWRpdW0sIEhpZ2giLA0KICAgICJSZXNwb25kZW50J3MgZmF2b3JpdGUgY29sb3I6IFJlZCwgQmx1ZSwgR3JlZW4iDQogICksDQogIERhdGFUeXBlID0gYygNCiAgICAiTnVtZXJpYyIsDQogICAgIk51bWVyaWMiLA0KICAgICJDYXRlZ29yaWNhbCIsDQogICAgIkNhdGVnb3JpY2FsIiwNCiAgICAiQ2F0ZWdvcmljYWwiDQogICksDQogIFN1YnR5cGUgPSBjKA0KICAgICJEaXNjcmV0ZSIsDQogICAgIkNvbnRpbnVvdXMiLA0KICAgICJOb21pbmFsIiwNCiAgICAiT3JkaW5hbCIsDQogICAgIk5vbWluYWwiDQogICksDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KKQ0KDQojIERpc3BsYXkgdGhlIGRhdGEgZnJhbWUgYXMgYSBuZWF0IHRhYmxlDQprYWJsZSh2YXJpYWJsZXNfaW5mbywgDQogICAgICBjYXB0aW9uID0gIlRhYmxlIG9mIFZhcmlhYmxlcyBhbmQgRGF0YSBUeXBlcyIpDQpgYGANCi0tLQ0KDQojIyBFeGVyY2lzZSAzDQoNCioqQ2xhc3NpZnkgRGF0YSBTb3VyY2VzOioqIERldGVybWluZSB3aGV0aGVyIHRoZSBmb2xsb3dpbmcgZGF0YSBjb21lcyBmcm9tICoqaW50ZXJuYWwqKiBvciAqKmV4dGVybmFsIHNvdXJjZXMqKiwgYW5kIHdoZXRoZXIgaXQgaXMgKipzdHJ1Y3R1cmVkKiogb3IgKip1bnN0cnVjdHVyZWQqKjoNCg0KYGBge3J9DQojIEluc3RhbGwgRFQgcGFja2FnZSBpZiBub3QgYWxyZWFkeSBpbnN0YWxsZWQNCiMgaW5zdGFsbC5wYWNrYWdlcygiRFQiKQ0KbGlicmFyeShEVCkNCg0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIGZvciBkYXRhIHNvdXJjZXMgDQpkYXRhX3NvdXJjZXMgPC0gZGF0YS5mcmFtZSgNCiAgTm8gPSAxOjQsDQogIERhdGFTb3VyY2UgPSBjKA0KICAgICJEYWlseSBzYWxlcyB0cmFuc2FjdGlvbiBkYXRhIG9mIHRoZSBjb21wYW55IiwNCiAgICAiV2VhdGhlciByZXBvcnRzIGZyb20gQk1LRyIsDQogICAgIlByb2R1Y3QgcmV2aWV3cyBvbiBzb2NpYWwgbWVkaWEiLA0KICAgICJXYXJlaG91c2UgaW52ZW50b3J5IHJlcG9ydHMiDQogICksDQogIEludGVybmFsX0V4dGVybmFsID0gYygNCiAgICAiSW50ZXJuYWwiLA0KICAgICJFeHRlcm5hbCIsDQogICAgIkV4dGVybmFsIiwNCiAgICAiSW50ZXJuYWwiDQogICksDQogIFN0cnVjdHVyZWRfVW5zdHJ1Y3R1cmVkID0gYygNCiAgICAiU3RydWN0dXJlZCIsDQogICAgIlN0cnVjdHVyZWQiLA0KICAgICJVbnN0cnVjdHVyZWQiLA0KICAgICJTdHJ1Y3R1cmVkIg0KICApLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCikNCg0KIyBEaXNwbGF5IHRoZSBkYXRhIGZyYW1lIGFzIGEgbmVhdCB0YWJsZQ0KZGF0YXRhYmxlKGRhdGFfc291cmNlcywgDQogICAgICAgICAgY2FwdGlvbiA9ICJUYWJsZSBvZiBEYXRhIFNvdXJjZXMiLA0KICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UpICMgaGlkZXMgdGhlIGluZGV4IGNvbHVtbg0KYGBgDQoNCi0tLQ0KDQojIyBFeGVyY2lzZSA0DQoNCioqRGF0YXNldCBTdHJ1Y3R1cmU6KiogQ29uc2lkZXIgdGhlIGZvbGxvd2luZyB0cmFuc2FjdGlvbiB0YWJsZToNCg0KfCBEYXRlICAgICAgIHwgUXR5IHwgUHJpY2UgfCBQcm9kdWN0ICB8IEN1c3RvbWVyVGllciB8DQp8LS0tLS0tLS0tLS0tfC0tLS0tfC0tLS0tLS18LS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLXwNCnwgMjAyNS0xMC0wMSB8IDIgICB8IDEwMDAgIHwgTGFwdG9wICAgfCBIaWdoICAgICAgICAgfA0KfCAyMDI1LTEwLTAxIHwgNSAgIHwgMjAgICAgfCBNb3VzZSAgICB8IE1lZGl1bSAgICAgICB8DQp8IDIwMjUtMTAtMDIgfCAxICAgfCAxMDAwICB8IExhcHRvcCAgIHwgTG93ICAgICAgICAgIHwNCnwgMjAyNS0xMC0wMiB8IDMgICB8IDMwICAgIHwgS2V5Ym9hcmQgfCBNZWRpdW0gICAgICAgfA0KfCAyMDI1LTEwLTAzIHwgNCAgIHwgNTAgICAgfCBNb3VzZSAgICB8IE1lZGl1bSAgICAgICB8DQp8IDIwMjUtMTAtMDMgfCAyICAgfCAxMDAwICB8IExhcHRvcCAgIHwgSGlnaCAgICAgICAgIHwNCnwgMjAyNS0xMC0wNCB8IDYgICB8IDI1ICAgIHwgS2V5Ym9hcmQgfCBMb3cgICAgICAgICAgfA0KfCAyMDI1LTEwLTA0IHwgMSAgIHwgMTAwMCAgfCBMYXB0b3AgICB8IEhpZ2ggICAgICAgICB8DQp8IDIwMjUtMTAtMDUgfCAzICAgfCA0MCAgICB8IE1vdXNlICAgIHwgTG93ICAgICAgICAgIHwNCnwgMjAyNS0xMC0wNSB8IDUgICB8IDEwICAgIHwgS2V5Ym9hcmQgfCBNZWRpdW0gICAgICAgfA0KDQoNCioqWW91ciBBc3NpZ25tZW50IEluc3RydWN0aW9uczoqKiBDcmVhdGluZyBhIFRyYW5zYWN0aW9ucyBUYWJsZSBhYm92ZSBpbiBSDQoNCjEuICoqQ3JlYXRlIGEgZGF0YSBmcmFtZSoqIGluIFIgY2FsbGVkIGB0cmFuc2FjdGlvbnNgIGNvbnRhaW5pbmcgdGhlIGRhdGEgYWJvdmUuDQoNCjIuIElkZW50aWZ5IHdoaWNoIHZhcmlhYmxlcyBhcmUgbnVtZXJpYyBhbmQgd2hpY2ggYXJlIGNhdGVnb3JpY2FsDQoNCjMuICoqQ2FsY3VsYXRlIHRvdGFsIHJldmVudWUqKiBmb3IgZWFjaCB0cmFuc2FjdGlvbiBieSBtdWx0aXBseWluZyBgUXR5IMOXIFByaWNlYCBhbmQgYWRkIGl0IGFzIGEgbmV3IGNvbHVtbiBgVG90YWxgLg0KDQo0LiAqKkNvbXB1dGUgc3VtbWFyeSBzdGF0aXN0aWNzKio6DQogICAtIFRvdGFsIHF1YW50aXR5IHNvbGQgZm9yIGVhY2ggcHJvZHVjdA0KICAgLSBUb3RhbCByZXZlbnVlIHBlciBwcm9kdWN0DQogICAtIEF2ZXJhZ2UgcHJpY2UgcGVyIHByb2R1Y3QNCg0KNS4gKipWaXN1YWxpemUgdGhlIGRhdGEqKjoNCiAgIC0gQ3JlYXRlIGEgKipiYXJwbG90Kiogc2hvd2luZyB0b3RhbCBxdWFudGl0eSBzb2xkIHBlciBwcm9kdWN0Lg0KICAgLSBDcmVhdGUgYSAqKnBpZSBjaGFydCoqIHNob3dpbmcgdGhlIHByb3BvcnRpb24gb2YgdG90YWwgcmV2ZW51ZSBwZXIgY3VzdG9tZXIgdGllci4NCg0KNi4gKipPcHRpb25hbCBDaGFsbGVuZ2UqKjoNCiAgIC0gRmluZCB3aGljaCAqKmRhdGUqKiBoYWQgdGhlIGhpZ2hlc3QgdG90YWwgcmV2ZW51ZS4NCiAgIC0gQ3JlYXRlIGEgKipzdGFja2VkIGJhciBjaGFydCoqIHNob3dpbmcgcXVhbnRpdHkgc29sZCBwZXIgcHJvZHVjdCBieSBjdXN0b21lciB0aWVyLg0KDQoqKkhpbnRzOioqIFVzZSBgZGF0YS5mcmFtZSgpYCwgYGFnZ3JlZ2F0ZSgpYCwgYGJhcnBsb3QoKWAsIGBwaWUoKWAsIGFuZCBiYXNpYyBhcml0aG1ldGljIG9wZXJhdGlvbnMgaW4gUi4NCg0KYGBge3J9DQpsaWJyYXJ5KERUKQ0KDQojdHJhbnNhY3Rpb24NCkRhdGUgPC0gYygiMjAyNS0xMC0wMSIsICIyMDI1LTEwLTAxIiwgIjIwMjUtMTAtMDIiLCAiMjAyNS0xMC0wMiIsICIyMDI1LTEwLTAzIiwgDQogICAgICAgICAgIjIwMjUtMTAtMDMiLCAiMjAyNS0xMC0wNCIsICIyMDI1LTEwLTA0IiwgIjIwMjUtMTAtMDUiLCAiMjAyNS0xMC0wNSIpDQpRdHkgPC0gYygyLCA1LCAxLCAzLCA0LCAyLCA2LCAxLCAzLCA1KQ0KUHJpY2UgPC0gYygxMDAwLCAyMCwgMTAwMCwgMzAsIDUwLCAxMDAwLCAyNSwgMTAwMCwgNDAsIDEwKQ0KUHJvZHVjdCA8LSBjKCJMYXB0b3AiLCAiTW91c2UiLCAiTGFwdG9wIiwgIktleWJvYXJkIiwgIk1vdXNlIiwgIkxhcHRvcCIsIA0KICAgICAgICAgICAgICJLZXlib2FyZCIsICJMYXB0b3AiLCAiTW91c2UiLCAiS2V5Ym9hcmQiKQ0KQ3VzdG9tZXJUaWVyIDwtIGMoIkhpZ2giLCAiTWVkaXVtIiwgIkxvdyIsICJNZWRpdW0iLCAiTWVkaXVtIiwgIkhpZ2giLCANCiAgICAgICAgICAgICAgICAgICJMb3ciLCAiSGlnaCIsICJMb3ciLCAiTWVkaXVtIikNCg0KIyBkYXRhIGZyYW1lIA0KdHJhbnNhY3Rpb25zIDwtIGRhdGEuZnJhbWUoRGF0ZSwgUXR5LCBQcmljZSwgUHJvZHVjdCwgQ3VzdG9tZXJUaWVyKQ0KDQojIERpc3BsYXkgdGhlIGRhdGEgZnJhbWUgDQpwcmludCh0cmFuc2FjdGlvbnMpDQoNCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSBmb3IgZGF0YSB0eXBlcw0KdmFyaWFibGVzX2luZm8gPC0gZGF0YS5mcmFtZSgNCiAgVmFyaWFibGUgPSBjKA0KICAgICJRdHkiLA0KICAgICJQcmljZSIsDQogICAgIlByb2R1Y3QiLA0KICAgICJDdXN0b21lclRpZXIiDQogICksDQogIERhdGFUeXBlID0gYygNCiAgICAiTnVtZXJpYyIsDQogICAgIk51bWVyaWMiLA0KICAgICJDYXRlZ29yaWNhbCIsDQogICAgIkNhdGVnb3JpY2FsIg0KICApLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCikNCg0KcHJpbnQodmFyaWFibGVzX2luZm8pDQoNCiMgMyBUb3RhbCBSZXZlbmV1DQp0cmFuc2FjdGlvbnMkdG90YWwgPC0gdHJhbnNhY3Rpb25zJFF0eSAqIHRyYW5zYWN0aW9ucyRQcmljZQ0KDQojIHZpZXcgdGhlIGRhdGEgZnJhbWUgDQpwcmludCh0cmFuc2FjdGlvbnMpDQoNCnF0eV9zdW1tYXJ5IDwtIGFnZ3JlZ2F0ZShRdHkgfiBQcm9kdWN0LCBkYXRhID0gdHJhbnNhY3Rpb25zLCBzdW0pIA0KcHJpbnQocXR5X3N1bW1hcnkpDQp0b3RhbF9zdW1tYXJ5IDwtIGFnZ3JlZ2F0ZSh0b3RhbCB+IFByb2R1Y3QsIGRhdGEgPSB0cmFuc2FjdGlvbnMsIHN1bSkgDQpwcmludCh0b3RhbF9zdW1tYXJ5KQ0KUHJpY2Vfc3VtbWFyeSA8LSBhZ2dyZWdhdGUoUHJpY2UgfiBQcm9kdWN0LCBkYXRhID0gdHJhbnNhY3Rpb25zLCBtZWFuKQ0KcHJpbnQoUHJpY2Vfc3VtbWFyeSkNCg0KIyBDYWxjdWxhdGUgdG90YWwgcXVhbnRpdHkgcGVyIHByb2R1Y3QNCnF0eV9wZXJfcHJvZHVjdCA8LSBhZ2dyZWdhdGUoUXR5IH4gUHJvZHVjdCwgZGF0YSA9IHRyYW5zYWN0aW9ucywgc3VtKQ0KDQojIENyZWF0ZSBhIGJhciBwbG90IA0KYmFycGxvdCAocXR5X3Blcl9wcm9kdWN0JFF0eSwNCiAgICAgICAgIG5hbWVzLmFyZyA9IHF0eV9wZXJfcHJvZHVjdCRQcm9kdWN0LCANCiAgICAgICAgIGNvbCA9ICJvcmFuZ2UiLCANCiAgICAgICAgIG1haW4gPSAiVG90YWwgUXVhbnRpdHkgU29sZCBwZXIgUHJvZHVjdCIsDQogICAgICAgICB4bGFiID0gIlByb2R1Y3QiLCB5bGFiID0gIlF1YW50aXR5IFNvbGQiKQ0KICAgICAgICAgDQojIENhbGN1bGF0ZSB0b3RhbCByZXZlbnVlIHBlciBDdXN0b21lclRpZXINCnJldmVudWVfdGllciA8LSBhZ2dyZWdhdGUodG90YWwgfiBDdXN0b21lclRpZXIsIGRhdGEgPSB0cmFuc2FjdGlvbnMsIHN1bSkgDQoNCiMgY3JlYXRlIHBpZSBjaGFydCANCnBpZShyZXZlbnVlX3RpZXIkdG90YSwgDQogICAgbGFiZWxzID0gcmV2ZW51ZV90aWVyJEN1c3RvbWVyVGllciwgDQogICAgbWFpbiA9ICJQcm9wb3J0aW9uIG9mIFRvdGFsIFJldmVudWUgcGVyIEN1c3RvbWVyIFRpZXIiLA0KICAgIGNvbCA9IGMoInJlZCIsICJvcmFuZ2UiLCAicGluayIpKQ0KICAgIA0KIyBIaXR1bmcgdG90YWwgcmV2ZW51ZSBwZXIgdGFuZ2dhbA0KcmV2ZW51ZV9wZXJfZGF0ZSA8LSBhZ2dyZWdhdGUodG90YWwgfiBEYXRlLCBkYXRhID0gdHJhbnNhY3Rpb25zLCBzdW0pDQoNCiMgTGloYXQgaGFzaWxueWENCnByaW50KHJldmVudWVfcGVyX2RhdGUpDQoNCiMgQ2FyaSB0YW5nZ2FsIGRlbmdhbiB0b3RhbCByZXZlbnVlIHBhbGluZyB0aW5naSBtZW5nZ3VuYWthbiBtYXgNCm1heF9kYXRlIDwtIHJldmVudWVfcGVyX2RhdGVbd2hpY2gubWF4KHJldmVudWVfcGVyX2RhdGUkdG90YWwpLCBdDQoNCiNsaWhhdCBoYXNpbG55YQ0KcHJpbnQobWF4X2RhdGUpDQoNCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBCaWtpbiBzdGFja2VkIGJhciBjaGFydA0KZ2dwbG90KHRyYW5zYWN0aW9ucywgYWVzKHggPSByZW9yZGVyKFByb2R1Y3QsIFF0eSksIHkgPSBRdHksIGZpbGwgPSBDdXN0b21lclRpZXIpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogIGxhYnModGl0bGUgPSAiUXVhbnRpdHkgU29sZCBwZXIgUHJvZHVjdCBieSBDdXN0b21lciBUaWVyIiwNCiAgICAgICB4ID0gIlByb2R1Y3QiLA0KICAgICAgIHkgPSAiUXVhbnRpdHkgU29sZCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCiAgDQotLS0NCg0KIyMgRXhlcmNpc2UgNQ0KDQoqKkNyZWF0ZSBZb3VyIE93biBEYXRhIEZyYW1lOioqDQoNCioqT2JqZWN0aXZlOioqIENyZWF0ZSBhIGRhdGEgZnJhbWUgaW4gUiB3aXRoICoqMzAgcm93cyoqIGNvbnRhaW5pbmcgYSBtaXggb2YgZGF0YSB0eXBlczogY29udGludW91cywgZGlzY3JldGUsIG5vbWluYWwsIGFuZCBvcmRpbmFsLiAgDQoNCiMjIyBJbnN0cnVjdGlvbnMNCg0KMS4gKipPcGVuIFJTdHVkaW8qKiBvciB0aGUgUiBjb25zb2xlLiAgDQoNCjIuICoqQ3JlYXRlIGEgdmVjdG9yIGZvciBlYWNoIGNvbHVtbioqIGluIHlvdXIgZGF0YSBmcmFtZTogIA0KDQogICAtICoqRGF0ZSoqOiAzMCBkYXRlcyAoY2FuIGJlIHNlcXVlbnRpYWwgb3IgcmFuZG9tIHdpdGhpbiBhIG1vbnRoL3llYXIpICANCiAgIC0gKipDb250aW51b3VzKio6IG51bWVyaWMgdmFsdWVzIHRoYXQgY2FuIHRha2UgZGVjaW1hbCB2YWx1ZXMgKGUuZy4sIGhlaWdodCwgd2VpZ2h0LCB0ZW1wZXJhdHVyZSkgIA0KICAgLSAqKkRpc2NyZXRlKio6IG51bWVyaWMgdmFsdWVzIHRoYXQgY2FuIG9ubHkgdGFrZSB3aG9sZSBudW1iZXJzIChlLmcuLCBudW1iZXIgb2YgaXRlbXMsIG51bWJlciBvZiB2ZWhpY2xlcykgIA0KICAgLSAqKk5vbWluYWwqKjogY2F0ZWdvcmljYWwgdmFsdWVzIHdpdGggKipubyBvcmRlcioqIChlLmcuLCBjb2xvciwgZ2VuZGVyLCBjaXR5KSAgDQogICAtICoqT3JkaW5hbCoqOiBjYXRlZ29yaWNhbCB2YWx1ZXMgd2l0aCBhICoqZGVmaW5lZCBvcmRlcioqIChlLmcuLCBMb3csIE1lZGl1bSwgSGlnaDsgQmVnaW5uZXIsIEludGVybWVkaWF0ZSwgRXhwZXJ0KSAgDQoNCjMuICoqQ29tYmluZSBhbGwgdmVjdG9ycyBpbnRvIGEgZGF0YSBmcmFtZSoqIGNhbGxlZCBgbXlfZGF0YWAuICANCg0KNC4gKipDaGVjayB5b3VyIGRhdGEgZnJhbWUqKiB1c2luZyBgaGVhZCgpYCBvciBgVmlldygpYCB0byBlbnN1cmUgaXQgaGFzICoqMzAgcm93cyoqIGFuZCB0aGUgY29sdW1ucyBhcmUgY29ycmVjdC4gIA0KDQo1LiAqKk9wdGlvbmFsIHRhc2tzKio6ICANCiAgIC0gU3VtbWFyaXplIGVhY2ggY29sdW1uIHVzaW5nIGBzdW1tYXJ5KClgICANCiAgIC0gQ291bnQgdGhlIGZyZXF1ZW5jeSBvZiBlYWNoIGNhdGVnb3J5IGZvciAqKk5vbWluYWwqKiBhbmQgKipPcmRpbmFsKiogY29sdW1ucyB1c2luZyBgdGFibGUoKWAgIA0KDQojIyMgSGludHMNCg0KLSBVc2UgYHNlcS5EYXRlKClgIG9yIGBhcy5EYXRlKClgIHRvIGdlbmVyYXRlIHRoZSBEYXRlIGNvbHVtbi4gIA0KLSBVc2UgYHJ1bmlmKClgIG9yIGBybm9ybSgpYCBmb3IgY29udGludW91cyBudW1lcmljIGRhdGEuICANCi0gVXNlIGBzYW1wbGUoKWAgZm9yIGRpc2NyZXRlLCBub21pbmFsLCBhbmQgb3JkaW5hbCBkYXRhLiAgDQotIEVuc3VyZSB0aGUgKipvcmRpbmFsIHZlY3RvcioqIGlzIGNyZWF0ZWQgd2l0aCBgZmFjdG9yKC4uLiwgbGV2ZWxzID0gYygiTG93IiwiTWVkaXVtIiwiSGlnaCIpLCBvcmRlcmVkID0gVFJVRSlgIChvciBzaW1pbGFyKS4gIA0KDQpgYGB7cn0NCmxpYnJhcnkoRFQpDQoNCiMgRGF0YSBGaW5hbmNpYWwgRnJhbWUNCg0KIyBjb2x1bW4gMTogVHJhbnNhY3Rpb24gRGF0ZQ0KRGF0ZSA8LSBzZXEuRGF0ZShmcm9tID0gYXMuRGF0ZSgiMjAyNS0xMC0wMSIpLCBieSA9ICJkYXkiLCBsZW5ndGgub3V0ID0gMzApDQoNCiMgQ29sdW1uIDI6IFRyYW5zYWN0aW9uIHZhbHVlIChDb250aW51b3VzKSDigJQgSW4gcnVwaWFoDQpUcmFuc2FjdGlvblZhbHVlIDwtIGMoDQogIDEyNTAwMDAsIDk4MDAwMCwgMTUwMDAwMCwgMjEwMDAwMCwgMTg1MDAwMCwgNzUwMDAwLCAyNDAwMDAwLCAxMzAwMDAwLCAxNzgwMDAwLCAyMjIwMDAwLA0KICAxOTUwMDAwLCAxNjUwMDAwLCAxNDIwMDAwLCAyNTUwMDAwLCAzMTAwMDAwLCAyNzUwMDAwLCAxOTgwMDAwLCA4ODAwMDAsIDE3NTAwMDAsIDIyMDAwMDAsDQogIDE5MDAwMDAsIDI2MDAwMDAsIDI0NTAwMDAsIDEzNTAwMDAsIDE1MDAwMDAsIDkwMDAwMCwgMTIwMDAwMCwgMjc1MDAwMCwgMzIwMDAwMCwgMjEwMDAwMA0KKQ0KDQojIENvbHVtbiAzOiBOdW1iZXIgb2YgaXRlbXMgcHVyY2hhc2VkIChEaXNjcmV0ZSkNCkl0ZW1zIDwtIGMoDQogIDIsIDEsIDMsIDUsIDQsIDIsIDYsIDMsIDUsIDQsDQogIDIsIDMsIDEsIDcsIDgsIDUsIDMsIDIsIDQsIDYsDQogIDUsIDcsIDgsIDMsIDQsIDEsIDIsIDcsIDksIDUNCikNCg0KIyBDb2x1bW4gNDogVHJhbnNhY3Rpb24gdHlwZSAoTm9taW5hbCkNClRyYW5zYWN0aW9uVHlwZSA8LSBjKA0KICAiUGVtYmVsaWFuIFR1bmFpIiwgIlRyYW5zZmVyIEJhbmsiLCAiS2FydHUgS3JlZGl0IiwgIlBlbWJlbGlhbiBUdW5haSIsICJFLVdhbGxldCIsDQogICJUcmFuc2ZlciBCYW5rIiwgIkthcnR1IEtyZWRpdCIsICJFLVdhbGxldCIsICJQZW1iZWxpYW4gVHVuYWkiLCAiRS1XYWxsZXQiLA0KICAiS2FydHUgS3JlZGl0IiwgIlBlbWJlbGlhbiBUdW5haSIsICJUcmFuc2ZlciBCYW5rIiwgIkUtV2FsbGV0IiwgIkthcnR1IEtyZWRpdCIsDQogICJQZW1iZWxpYW4gVHVuYWkiLCAiRS1XYWxsZXQiLCAiVHJhbnNmZXIgQmFuayIsICJLYXJ0dSBLcmVkaXQiLCAiUGVtYmVsaWFuIFR1bmFpIiwNCiAgIkUtV2FsbGV0IiwgIlRyYW5zZmVyIEJhbmsiLCAiS2FydHUgS3JlZGl0IiwgIlBlbWJlbGlhbiBUdW5haSIsICJFLVdhbGxldCIsDQogICJLYXJ0dSBLcmVkaXQiLCAiVHJhbnNmZXIgQmFuayIsICJQZW1iZWxpYW4gVHVuYWkiLCAiRS1XYWxsZXQiLCAiVHJhbnNmZXIgQmFuayINCikNCg0KIyBLb2xvbSA1OiBDdXN0b21lciBUaWVyIChPcmRpbmFsKQ0KQ3VzdG9tZXJUaWVyIDwtIGZhY3RvcigNCiAgYygNCiAgICAiU2VkYW5nIiwgIlJlbmRhaCIsICJTZWRhbmciLCAiVGluZ2dpIiwgIlNlZGFuZyIsICJSZW5kYWgiLCAiVGluZ2dpIiwgIlNlZGFuZyIsICJUaW5nZ2kiLCAiU2VkYW5nIiwNCiAgICAiUmVuZGFoIiwgIlRpbmdnaSIsICJTZWRhbmciLCAiVGluZ2dpIiwgIlRpbmdnaSIsICJTZWRhbmciLCAiUmVuZGFoIiwgIlNlZGFuZyIsICJUaW5nZ2kiLCAiU2VkYW5nIiwNCiAgICAiUmVuZGFoIiwgIlRpbmdnaSIsICJUaW5nZ2kiLCAiUmVuZGFoIiwgIlNlZGFuZyIsICJSZW5kYWgiLCAiU2VkYW5nIiwgIlRpbmdnaSIsICJUaW5nZ2kiLCAiU2VkYW5nIg0KICApLA0KICBsZXZlbHMgPSBjKCJSZW5kYWgiLCAiU2VkYW5nIiwgIlRpbmdnaSIpLA0KICBvcmRlcmVkID0gVFJVRQ0KKQ0KDQojIENvbWJpbmUgaW50byBhIGRhdGEgZnJhbWUNCmRhdGFfZmluYW5jaWFsIDwtIGRhdGEuZnJhbWUoRGF0ZSwgVHJhbnNhY3Rpb25WYWx1ZSwgSXRlbXMsIFRyYW5zYWN0aW9uVHlwZSwgQ3VzdG9tZXJUaWVyKQ0KDQojIERpc3BsYXkgdGhlIGRhdGEgZnJhbWUgYXMgYSB0YWJsZQ0KcHJpbnQoZGF0YV9maW5hbmNpYWwpDQoNCiMgQ3JlYXRlIGEgc2Vjb25kIHRhYmxlIGZvciB2YXJpYWJsZSB0eXBlDQp2YXJpYWJsZXNfaW5mbyA8LSBkYXRhLmZyYW1lKA0KICBObyA9IDE6NCwNCiAgdmFyaWFibGUgPSBjKA0KICAgICJUcmFuc2FjdGlvbiBWYWx1ZSIsDQogICAgIkl0ZW1zIiwNCiAgICAiVHJhbnNhY3Rpb24gVHlwZSIsDQogICAgIkN1c3RvbWVyIFRpZXIiDQopLA0KICBEYXRhVHlwZSA9IGMoDQogICAgICAiQ29udGludW91cyIsDQogICAgICAiRGlzY3JldGUiLA0KICAgICAgIk5vbWluYWwiLA0KICAgICAgIk9yZGluYWwiDQogICAgKSwNCiAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCiAgKQ0KDQpsaWJyYXJ5KGtuaXRyKQ0KDQprYWJsZSgNCiAgdmFyaWFibGVzX2luZm8sDQogIGNhcHRpb24gPSAiVGFibGUgb2YgVmFyaWFibGVzIGFuZCBEYXRhIFR5cGVzIg0KKQ0KYGBgDQoNCg0KDQoNCg==