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)
#Exercise 4: Create Transactions Data Frame
# transactions
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")
# Combine all colums into a data frame
transactions <- data.frame(Date, Qty ,Price ,Product ,CustomerTier)
#Show data frame
#Add a new column for total
transactions <- transform (transactions, Total = Qty * Price)
View (transactions)

str (transactions)
## 'data.frame':    10 obs. of  6 variables:
##  $ Date        : chr  "2025-10-01" "2025-10-01" "2025-10-02" "2025-10-02" ...
##  $ Qty         : num  2 5 1 3 4 2 6 1 3 5
##  $ Price       : num  1000 20 1000 30 50 1000 25 1000 40 10
##  $ Product     : chr  "Laptop" "Mouse" "Laptop" "Keyboard" ...
##  $ CustomerTier: chr  "High" "Medium" "Low" "Medium" ...
##  $ Total       : num  2000 100 1000 90 200 2000 150 1000 120 50
# Total quantity per product
aggregate (Qty ~ Product, data = 
             transactions, FUN = sum)
# Total revenue per product
aggregate (Total ~ Product, data = 
             transactions, FUN = sum)
# Total price per product
aggregate (Price ~ Product, data = 
             transactions, FUN = mean)
# Total quantity per product
qty_per_product <- aggregate (Qty ~ Product, transactions, sum)

# Bar chart of quantity sold
barplot (qty_per_product$Qty, 
         names.arg = qty_per_product$Product,
         main = "Quantity Sold by Product",
         xlab = "Product",
         ylab = "Quantity",
         col = "red")

# Revenue per custom tier
revenue_per_tier <- aggregate (Total ~ CustomerTier, transactions, sum)

# Pie chart of revenue share 
pie (revenue_per_tier$Total,
     labels = revenue_per_tier$CustomerTier,
     main = "Revenue Share by Customer Tier",
     col = rainbow(3))

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).
# create data frame about purchasing drinks at cafe statis

#Dates from September 1 to September 30 
date = seq.Date (from = as.Date ("2030-09-01"), to =
              as.Date ("2030-09-30"), by = "day")

#Number of drinks ordered each day
set.seed(123)
Number_of_Drinks <- sample (1:15, 30,
                            replace = TRUE)

#Total purchase amount 
Total_Purchase <- round (Number_of_Drinks * runif (30, min = 15000, max = 25000), 0)

#Type of drinks
Drink_Type = sample (c("Matcha", "Coffe", 
                  "Chocolate","Tea", 
                  "Milkshake", "Latte"),
                30, replace = TRUE)

# Customer satisfaction level
satisfaction <- ifelse (Total_Purchase < 50000, "Not satisfied",
                ifelse (Total_Purchase < 100000,"Satisfied", 
                "Very satisfied"))

#
q <- quantile(Total_Purchase, probs = c(0, 1/3, 2/3, 1))
satisfaction <- cut(Total_Purchase,
                    breaks = q,
                    labels = c("Not satisfied", "Satisfied", "Very satisfied"),
                    include.lowest = TRUE)


#combine all columns into on data frame named my_data
my_data <- data.frame(date, 
                      Total_Purchase, Number_of_Drinks, 
                      Drink_Type, satisfaction)

# 7. Show first few rows
head(my_data)
# 8. Print full data frame
print(my_data)
##          date Total_Purchase Number_of_Drinks Drink_Type   satisfaction
## 1  2030-09-01         360345               15        Tea Very satisfied
## 2  2030-09-02         328606               15  Milkshake Very satisfied
## 3  2030-09-03          68864                3      Coffe  Not satisfied
## 4  2030-09-04         213446               14     Matcha Very satisfied
## 5  2030-09-05          59334                3     Matcha  Not satisfied
## 6  2030-09-06         225846               10  Chocolate Very satisfied
## 7  2030-09-07          34328                2     Matcha  Not satisfied
## 8  2030-09-08         109091                6      Latte  Not satisfied
## 9  2030-09-09         190479               11  Milkshake      Satisfied
## 10 2030-09-10          82140                5     Matcha  Not satisfied
## 11 2030-09-11          76582                4      Coffe  Not satisfied
## 12 2030-09-12         267921               14        Tea Very satisfied
## 13 2030-09-13         112131                6        Tea  Not satisfied
## 14 2030-09-14         148720                9      Latte      Satisfied
## 15 2030-09-15         163881               10      Latte      Satisfied
## 16 2030-09-16         190634               11  Chocolate      Satisfied
## 17 2030-09-17          98298                5      Latte  Not satisfied
## 18 2030-09-18          52979                3      Latte  Not satisfied
## 19 2030-09-19         259361               11     Matcha Very satisfied
## 20 2030-09-20         139125                9      Latte      Satisfied
## 21 2030-09-21         233064               12      Coffe Very satisfied
## 22 2030-09-22         206903                9     Matcha Very satisfied
## 23 2030-09-23         145971                9      Coffe      Satisfied
## 24 2030-09-24         267923               13        Tea Very satisfied
## 25 2030-09-25          51196                3  Milkshake  Not satisfied
## 26 2030-09-26         130203                8  Milkshake      Satisfied
## 27 2030-09-27         225331               10      Latte Very satisfied
## 28 2030-09-28         167653                7  Chocolate      Satisfied
## 29 2030-09-29         187446               10     Matcha      Satisfied
## 30 2030-09-30         194860                9        Tea      Satisfied
# 9. Check number of rows
nrow(my_data)
## [1] 30
# 10. Display summary of each column
summary(my_data)
##       date            Total_Purchase   Number_of_Drinks  Drink_Type       
##  Min.   :2030-09-01   Min.   : 34328   Min.   : 2.000   Length:30         
##  1st Qu.:2030-09-08   1st Qu.:100996   1st Qu.: 5.250   Class :character  
##  Median :2030-09-15   Median :165767   Median : 9.000   Mode  :character  
##  Mean   :2030-09-15   Mean   :166422   Mean   : 8.533                     
##  3rd Qu.:2030-09-22   3rd Qu.:222360   3rd Qu.:11.000                     
##  Max.   :2030-09-30   Max.   :360345   Max.   :15.000                     
##          satisfaction
##  Not satisfied :10   
##  Satisfied     :10   
##  Very satisfied:10   
##                      
##                      
## 
# 11. Make a formatted table using knitr
library(knitr)
kable(my_data, caption = "Table: Drink Purchase Data (30 Days)")
Table: Drink Purchase Data (30 Days)
date Total_Purchase Number_of_Drinks Drink_Type satisfaction
2030-09-01 360345 15 Tea Very satisfied
2030-09-02 328606 15 Milkshake Very satisfied
2030-09-03 68864 3 Coffe Not satisfied
2030-09-04 213446 14 Matcha Very satisfied
2030-09-05 59334 3 Matcha Not satisfied
2030-09-06 225846 10 Chocolate Very satisfied
2030-09-07 34328 2 Matcha Not satisfied
2030-09-08 109091 6 Latte Not satisfied
2030-09-09 190479 11 Milkshake Satisfied
2030-09-10 82140 5 Matcha Not satisfied
2030-09-11 76582 4 Coffe Not satisfied
2030-09-12 267921 14 Tea Very satisfied
2030-09-13 112131 6 Tea Not satisfied
2030-09-14 148720 9 Latte Satisfied
2030-09-15 163881 10 Latte Satisfied
2030-09-16 190634 11 Chocolate Satisfied
2030-09-17 98298 5 Latte Not satisfied
2030-09-18 52979 3 Latte Not satisfied
2030-09-19 259361 11 Matcha Very satisfied
2030-09-20 139125 9 Latte Satisfied
2030-09-21 233064 12 Coffe Very satisfied
2030-09-22 206903 9 Matcha Very satisfied
2030-09-23 145971 9 Coffe Satisfied
2030-09-24 267923 13 Tea Very satisfied
2030-09-25 51196 3 Milkshake Not satisfied
2030-09-26 130203 8 Milkshake Satisfied
2030-09-27 225331 10 Latte Very satisfied
2030-09-28 167653 7 Chocolate Satisfied
2030-09-29 187446 10 Matcha Satisfied
2030-09-30 194860 9 Tea Satisfied
library(knitr)

# Count how many times each drink type appears

drink_table <- as.data.frame(table(my_data$Drink_Type))
colnames(drink_table) <- c("Drink Type", "Frequency")

# Count satisfaction levels

satisfaction_table <- as.data.frame(table(my_data$satisfaction))
colnames(satisfaction_table) <- c("Satisfaction Level", "Frequency")

# show table
knitr::kable(drink_table, caption = "Table: Frequency of Each Drink Type")
Table: Frequency of Each Drink Type
Drink Type Frequency
Chocolate 3
Coffe 4
Latte 7
Matcha 7
Milkshake 4
Tea 5
knitr::kable(satisfaction_table, caption = "Table: Frequency of Each Satisfaction Level")
Table: Frequency of Each Satisfaction Level
Satisfaction Level Frequency
Not satisfied 10
Satisfied 10
Very satisfied 10
LS0tDQp0aXRsZTogIkRhdGEgRXhwbG9yYXRpb24iICAgICAgICMgTWFpbiB0aXRsZSBvZiB0aGUgZG9jdW1lbnQNCnN1YnRpdGxlOiAiRXhlcmNpc2VzIH4gV2VlayAyIiAgIyBTdWJ0aXRsZSBvciB0b3BpYyBmb3Igd2VlayAyDQphdXRob3I6IA0KLSAiTXVoYW1tYWQgTmFiaWwgS2hhaXJpbCBBbmFtIg0KLSAiQ2Fyb2wgRHVwaW5vIHBlcmVpcmEiDQotICJJZ25hc2l1cyBSYWJpIEJsb2xvbmciDQotICJSYWloYW5pYSBTeWFoIFB1dHJpIg0KLSAiRGFtZXJpYSBBZGVsaW5hIE1pbmkgU2ltYXJtYXRhIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFJlcGxhY2Ugd2l0aCB5b3VyIGZ1bGwgbmFtZQ0KZGF0ZTogICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVkLCAlWScpYCIgIyBBdXRvIGRpc3BsYXlzIHRoZSBjdXJyZW50IGRhdGUNCm91dHB1dDogICAgICAgICAgICAgICAgICAgICAgICAgIyBPdXRwdXQgc2VjdGlvbiBkZWZpbmVzIHRoZSBmb3JtYXQgYW5kIGxheW91dCANCiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246ICAgICAgIyBodHRwczovL2dpdGh1Yi5jb20vanViYS9ybWRmb3JtYXRzDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUgICAgICAgICMgRW1iZWRzIGFsbCByZXNvdXJjZXMgKENTUywgSlMsIGltYWdlcykgDQogICAgdGh1bWJuYWlsczogdHJ1ZSAgICAgICAgICAgICMgRGlzcGxheXMgaW1hZ2UgdGh1bWJuYWlscyBpbiB0aGUgZG9jDQogICAgbGlnaHRib3g6IHRydWUgICAgICAgICAgICAgICMgRW5hYmxlcyBjbGljayB0byBlbmxhcmdlIGltYWdlcw0KICAgIGdhbGxlcnk6IHRydWUgICAgICAgICAgICAgICAjIEdyb3VwcyBpbWFnZXMgaW50byBhbiBpbnRlcmFjdGl2ZSBnYWxsZXJ5DQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlICAgICAgICMgQXV0b21hdGljYWxseSBudW1iZXJzIGFsbCBzZWN0aW9ucw0KICAgIGxpYl9kaXI6IGxpYnMgICAgICAgICAgICAgICAjIERpcmVjdG9yeSB3aGVyZSBKYXZhU2NyaXB0L0NTUyBsaWJyYXJpZXMNCiAgICBkZl9wcmludDogInBhZ2VkIiAgICAgICAgICAgIyBEaXNwbGF5cyBkYXRhIGZyYW1lcyBhcyBpbnRlcmFjdGl2ZSBwYWdlZCANCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93IiAgICAgICAgIyBBbGxvd3MgZm9sZGluZy91bmZvbGRpbmcgUiBjb2RlIGJsb2NrcyANCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMgICAgICAgICAgIyBBZGRzIGEgYnV0dG9uIHRvIGRvd25sb2FkIGFsbCBSIGNvZGUNCi0tLQ0KDQo8aW1nIHNyYz0iaHR0cHM6Ly9naXRodWIuY29tL2RzY2llbmNlbGFicy9pbWFnZXMvYmxvYi9tYXN0ZXIvTG9nb19Ec2NpZW5jZWxhYnNfdjEucG5nP3Jhdz10cnVlIiBhbHQ9IkxvZ28iIGlkPSJGb3RvIiBzdHlsZT0id2lkdGg6MjAwcHg7IGRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87Ii8+DQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBFeGVyY2lzZSAxDQoNClRoZSBmb2xsb3dpbmcgdGFibGUgc2hvd3Mgc2FtcGxlIGluZm9ybWF0aW9uIGZvciB0aHJlZSBzdHVkZW50cy4gRWFjaCBvYnNlcnZhdGlvbiByZXByZXNlbnRzIGEgc2luZ2xlIHN0dWRlbnQgYW5kIGluY2x1ZGVzIGRldGFpbHMgc3VjaCBhcyB0aGVpciB1bmlxdWUgc3R1ZGVudCBJRCwgbmFtZSwgYWdlLCB0b3RhbCBjcmVkaXRzIGNvbXBsZXRlZCwgbWFqb3IgZmllbGQgb2Ygc3R1ZHksIGFuZCB5ZWFyIGxldmVsLg0KDQpUaGlzIGRhdGFzZXQgZGVtb25zdHJhdGVzIGEgbWl4dHVyZSBvZiB2YXJpYWJsZSB0eXBlczoNCg0KLSAgICoqTm9taW5hbDoqKiBTdHVkZW50SUQsIE5hbWUsIE1ham9yXA0KLSAgICoqTnVtZXJpYzoqKiBBZ2UgKGNvbnRpbnVvdXMpLCBDcmVkaXRzQ29tcGxldGVkIChkaXNjcmV0ZSlcDQotICAgKipPcmRpbmFsOioqIFllYXJMZXZlbCAoRnJlc2htYW4g4oaSIFNlbmlvcikNCg0KfCBTdHVkZW50SUQgfCBOYW1lICB8IEFnZSB8IENyZWRpdHNDb21wbGV0ZWQgfCBNYWpvciAgICAgICB8IFllYXJMZXZlbCB8DQp8LS0tLS0tLS0tLS18LS0tLS0tLXwtLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLXwNCnwgUzAwMSAgICAgIHwgQWxpY2UgfCAyMCAgfCA0NSAgICAgICAgICAgICAgIHwgRGF0YSBTYWlucyAgfCBTb3Bob21vcmUgfA0KfCBTMDAyICAgICAgfCBCdWRpICB8IDIxICB8IDYwICAgICAgICAgICAgICAgfCBNYXRoZW1hdGljcyB8IEp1bmlvciAgICB8DQp8IFMwMDMgICAgICB8IENpdHJhIHwgMTkgIHwgMzAgICAgICAgICAgICAgICB8IFN0YXRpc3RpY3MgIHwgRnJlc2htYW4gIHwNCg0KYGBge3J9DQojIDEuIENyZWF0ZSB2ZWN0b3JzIGZvciBlYWNoIHZhcmlhYmxlDQpTdHVkZW50SUQgPC0gYygiUzAwMSIsICJTMDAyIiwgIlMwMDMiKSAgICAgICAjIE5vbWluYWwgLyBJRA0KTmFtZSA8LSBjKCJBbGljZSIsICJCdWRpIiwgIkNpdHJhIikgICAgICAgICAgIyBOb21pbmFsIC8gTmFtZQ0KQWdlIDwtIGMoMjAsIDIxLCAxOSkgICAgICAgICAgICAgICAgICAgICAgICAgIyBOdW1lcmljIC8gQ29udGludW91cw0KQ3JlZGl0c0NvbXBsZXRlZCA8LSBjKDQ1LCA2MCwgMzApICAgICAgICAgICAgIyBOdW1lcmljIC8gRGlzY3JldGUNCg0KIyBOb21pbmFsDQpNYWpvciA8LSBjKCJEYXRhIFNhaW5zIiwgIk1hdGhlbWF0aWNzIiwgIlN0YXRpc3RpY3MiKSAgDQoNCiMgT3JkaW5hbA0KWWVhckxldmVsIDwtIGZhY3RvcihjKCJTb3Bob21vcmUiLCAiSnVuaW9yIiwgIkZyZXNobWFuIiksDQogICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkZyZXNobWFuIiwiU29waG9tb3JlIiwiSnVuaW9yIiwiU2VuaW9yIiksDQogICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSAgICAgICAgICANCg0KIyAyLiBDb21iaW5lIGFsbCB2ZWN0b3JzIGludG8gYSBkYXRhIGZyYW1lDQpzdHVkZW50cyA8LSBkYXRhLmZyYW1lKA0KICBTdHVkZW50SUQsIE5hbWUsIEFnZSwgQ3JlZGl0c0NvbXBsZXRlZCwgTWFqb3IsIFllYXJMZXZlbCwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCiMgMy4gRGlzcGxheSB0aGUgZGF0YSBmcmFtZQ0KcHJpbnQoc3R1ZGVudHMpDQpgYGANCg0KIyMgRXhlcmNpc2UgMg0KDQoqKklkZW50aWZ5IERhdGEgVHlwZXM6KiogRGV0ZXJtaW5lIHRoZSB0eXBlIG9mIGRhdGEgZm9yIGVhY2ggb2YgdGhlIGZvbGxvd2luZyB2YXJpYWJsZXM6DQoNCmBgYHtyfQ0KIyBJbnN0YWxsIGtuaXRyIHBhY2thZ2UgaWYgbm90IGFscmVhZHkgaW5zdGFsbGVkDQojIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCmxpYnJhcnkoa25pdHIpDQoNCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSBmb3IgRGF0YSBUeXBlcw0KdmFyaWFibGVzX2luZm8gPC0gZGF0YS5mcmFtZSgNCiAgTm8gPSAxOjUsDQogIFZhcmlhYmxlID0gYygNCiAgICAiTnVtYmVyIG9mIHZlaGljbGVzIHBhc3NpbmcgdGhyb3VnaCB0aGUgdG9sbCByb2FkIGVhY2ggZGF5IiwNCiAgICAiU3R1ZGVudCBoZWlnaHQgaW4gY20iLA0KICAgICJFbXBsb3llZSBnZW5kZXIgKE1hbGUgLyBGZW1hbGUpIiwNCiAgICAiQ3VzdG9tZXIgc2F0aXNmYWN0aW9uIGxldmVsOiBMb3csIE1lZGl1bSwgSGlnaCIsDQogICAgIlJlc3BvbmRlbnQncyBmYXZvcml0ZSBjb2xvcjogUmVkLCBCbHVlLCBHcmVlbiINCiAgKSwNCiAgRGF0YVR5cGUgPSBjKA0KICAgICJOdW1lcmljIiwNCiAgICAiTnVtZXJpYyIsDQogICAgIkNhdGVnb3JpY2FsIiwNCiAgICAiQ2F0ZWdvcmljYWwiLA0KICAgICJDYXRlZ29yaWNhbCINCiAgKSwNCiAgU3VidHlwZSA9IGMoDQogICAgIkRpc2NyZXRlIiwNCiAgICAiQ29udGludW91cyIsDQogICAgIk5vbWluYWwiLA0KICAgICJPcmRpbmFsIiwNCiAgICAiTm9taW5hbCINCiAgKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCiMgRGlzcGxheSB0aGUgZGF0YSBmcmFtZSBhcyBhIG5lYXQgdGFibGUNCmthYmxlKHZhcmlhYmxlc19pbmZvLCANCiAgICAgIGNhcHRpb24gPSAiVGFibGUgb2YgVmFyaWFibGVzIGFuZCBEYXRhIFR5cGVzIikNCmBgYA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgRXhlcmNpc2UgMw0KDQoqKkNsYXNzaWZ5IERhdGEgU291cmNlczoqKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZm9sbG93aW5nIGRhdGEgY29tZXMgZnJvbSAqKmludGVybmFsKiogb3IgKipleHRlcm5hbCBzb3VyY2VzKiosIGFuZCB3aGV0aGVyIGl0IGlzICoqc3RydWN0dXJlZCoqIG9yICoqdW5zdHJ1Y3R1cmVkKio6DQoNCmBgYHtyfQ0KIyBJbnN0YWxsIERUIHBhY2thZ2UgaWYgbm90IGFscmVhZHkgaW5zdGFsbGVkDQojIGluc3RhbGwucGFja2FnZXMoIkRUIikNCmxpYnJhcnkoRFQpDQoNCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSBmb3IgZGF0YSBzb3VyY2VzIA0KZGF0YV9zb3VyY2VzIDwtIGRhdGEuZnJhbWUoDQogIE5vID0gMTo0LA0KICBEYXRhU291cmNlID0gYygNCiAgICAiRGFpbHkgc2FsZXMgdHJhbnNhY3Rpb24gZGF0YSBvZiB0aGUgY29tcGFueSIsDQogICAgIldlYXRoZXIgcmVwb3J0cyBmcm9tIEJNS0ciLA0KICAgICJQcm9kdWN0IHJldmlld3Mgb24gc29jaWFsIG1lZGlhIiwNCiAgICAiV2FyZWhvdXNlIGludmVudG9yeSByZXBvcnRzIg0KICApLA0KICBJbnRlcm5hbF9FeHRlcm5hbCA9IGMoDQogICAgIkludGVybmFsIiwNCiAgICAiRXh0ZXJuYWwiLA0KICAgICJFeHRlcm5hbCIsDQogICAgIkludGVybmFsIg0KICApLA0KICBTdHJ1Y3R1cmVkX1Vuc3RydWN0dXJlZCA9IGMoDQogICAgIlN0cnVjdHVyZWQiLA0KICAgICJTdHJ1Y3R1cmVkIiwNCiAgICAiVW5TdHJ1Y3R1cmVkIiwNCiAgICAiU3RydWN0dXJlZCINCiAgKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCiMgRGlzcGxheSB0aGUgZGF0YSBmcmFtZSBhcyBhIG5lYXQgdGFibGUNCmRhdGF0YWJsZShkYXRhX3NvdXJjZXMsIA0KICAgICAgICAgIGNhcHRpb24gPSAiVGFibGUgb2YgRGF0YSBTb3VyY2VzIiwNCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFKSAjIGhpZGVzIHRoZSBpbmRleCBjb2x1bW4NCmBgYA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgRXhlcmNpc2UgNA0KDQoqKkRhdGFzZXQgU3RydWN0dXJlOioqIENvbnNpZGVyIHRoZSBmb2xsb3dpbmcgdHJhbnNhY3Rpb24gdGFibGU6DQoNCnwgRGF0ZSAgICAgICB8IFF0eSB8IFByaWNlIHwgUHJvZHVjdCAgfCBDdXN0b21lclRpZXIgfA0KfC0tLS0tLS0tLS0tLXwtLS0tLXwtLS0tLS0tfC0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS18DQp8IDIwMjUtMTAtMDEgfCAyICAgfCAxMDAwICB8IExhcHRvcCAgIHwgSGlnaCAgICAgICAgIHwNCnwgMjAyNS0xMC0wMSB8IDUgICB8IDIwICAgIHwgTW91c2UgICAgfCBNZWRpdW0gICAgICAgfA0KfCAyMDI1LTEwLTAyIHwgMSAgIHwgMTAwMCAgfCBMYXB0b3AgICB8IExvdyAgICAgICAgICB8DQp8IDIwMjUtMTAtMDIgfCAzICAgfCAzMCAgICB8IEtleWJvYXJkIHwgTWVkaXVtICAgICAgIHwNCnwgMjAyNS0xMC0wMyB8IDQgICB8IDUwICAgIHwgTW91c2UgICAgfCBNZWRpdW0gICAgICAgfA0KfCAyMDI1LTEwLTAzIHwgMiAgIHwgMTAwMCAgfCBMYXB0b3AgICB8IEhpZ2ggICAgICAgICB8DQp8IDIwMjUtMTAtMDQgfCA2ICAgfCAyNSAgICB8IEtleWJvYXJkIHwgTG93ICAgICAgICAgIHwNCnwgMjAyNS0xMC0wNCB8IDEgICB8IDEwMDAgIHwgTGFwdG9wICAgfCBIaWdoICAgICAgICAgfA0KfCAyMDI1LTEwLTA1IHwgMyAgIHwgNDAgICAgfCBNb3VzZSAgICB8IExvdyAgICAgICAgICB8DQp8IDIwMjUtMTAtMDUgfCA1ICAgfCAxMCAgICB8IEtleWJvYXJkIHwgTWVkaXVtICAgICAgIHwNCg0KKipZb3VyIEFzc2lnbm1lbnQgSW5zdHJ1Y3Rpb25zOioqIENyZWF0aW5nIGEgVHJhbnNhY3Rpb25zIFRhYmxlIGFib3ZlIGluIFINCg0KMS4gICoqQ3JlYXRlIGEgZGF0YSBmcmFtZSoqIGluIFIgY2FsbGVkIGB0cmFuc2FjdGlvbnNgIGNvbnRhaW5pbmcgdGhlIGRhdGEgYWJvdmUuDQoNCjIuICBJZGVudGlmeSB3aGljaCB2YXJpYWJsZXMgYXJlIG51bWVyaWMgYW5kIHdoaWNoIGFyZSBjYXRlZ29yaWNhbA0KDQozLiAgKipDYWxjdWxhdGUgdG90YWwgcmV2ZW51ZSoqIGZvciBlYWNoIHRyYW5zYWN0aW9uIGJ5IG11bHRpcGx5aW5nIGBRdHkgw5cgUHJpY2VgIGFuZCBhZGQgaXQgYXMgYSBuZXcgY29sdW1uIGBUb3RhbGAuDQoNCjQuICAqKkNvbXB1dGUgc3VtbWFyeSBzdGF0aXN0aWNzKio6DQoNCiAgICAtICAgVG90YWwgcXVhbnRpdHkgc29sZCBmb3IgZWFjaCBwcm9kdWN0DQogICAgLSAgIFRvdGFsIHJldmVudWUgcGVyIHByb2R1Y3QNCiAgICAtICAgQXZlcmFnZSBwcmljZSBwZXIgcHJvZHVjdA0KDQo1LiAgKipWaXN1YWxpemUgdGhlIGRhdGEqKjoNCg0KICAgIC0gICBDcmVhdGUgYSAqKmJhcnBsb3QqKiBzaG93aW5nIHRvdGFsIHF1YW50aXR5IHNvbGQgcGVyIHByb2R1Y3QuDQogICAgLSAgIENyZWF0ZSBhICoqcGllIGNoYXJ0Kiogc2hvd2luZyB0aGUgcHJvcG9ydGlvbiBvZiB0b3RhbCByZXZlbnVlIHBlciBjdXN0b21lciB0aWVyLg0KDQo2LiAgKipPcHRpb25hbCBDaGFsbGVuZ2UqKjoNCg0KICAgIC0gICBGaW5kIHdoaWNoICoqZGF0ZSoqIGhhZCB0aGUgaGlnaGVzdCB0b3RhbCByZXZlbnVlLg0KICAgIC0gICBDcmVhdGUgYSAqKnN0YWNrZWQgYmFyIGNoYXJ0Kiogc2hvd2luZyBxdWFudGl0eSBzb2xkIHBlciBwcm9kdWN0IGJ5IGN1c3RvbWVyIHRpZXIuDQoNCioqSGludHM6KiogVXNlIGBkYXRhLmZyYW1lKClgLCBgYWdncmVnYXRlKClgLCBgYmFycGxvdCgpYCwgYHBpZSgpYCwgYW5kIGJhc2ljIGFyaXRobWV0aWMgb3BlcmF0aW9ucyBpbiBSLg0KDQpgYGB7cn0NCmxpYnJhcnkoRFQpDQojRXhlcmNpc2UgNDogQ3JlYXRlIFRyYW5zYWN0aW9ucyBEYXRhIEZyYW1lDQojIHRyYW5zYWN0aW9ucw0KRGF0ZSA9IGMoIjIwMjUtMTAtMDEiLCAiMjAyNS0xMC0wMSIsICIyMDI1LTEwLTAyIiwgIjIwMjUtMTAtMDIiLCAiMjAyNS0xMC0wMyIsDQogICAgICAgICAiMjAyNS0xMC0wMyIsICIyMDI1LTEwLTA0IiwgIjIwMjUtMTAtMDQiLCAiMjAyNS0xMC0wNSIsICIyMDI1LTEwLTA1IikNClF0eSA9IGMoMiw1LDEsMyw0LDIsNiwxLDMsNSkNClByaWNlID0gYygxMDAwLDIwLDEwMDAsMzAsNTAsMTAwMCwyNSwxMDAwLDQwLDEwKQ0KUHJvZHVjdCA9IGMoIkxhcHRvcCIsICJNb3VzZSIsICJMYXB0b3AiLCAiS2V5Ym9hcmQiLCAiTW91c2UiLCANCiAgICAgICAgICAgICAiTGFwdG9wIiwgIktleWJvYXJkIiwgIkxhcHRvcCIsICJNb3VzZSIsICJLZXlib2FyZCIpDQpDdXN0b21lclRpZXIgPSBjKCJIaWdoIiwgIk1lZGl1bSIsICJMb3ciLCAiTWVkaXVtIiwgIk1lZGl1bSIsIA0KICAgICAgICAgICAgICAgICAgIkhpZ2giLCAiTG93IiwgIkhpZ2giLCAiTG93IiwgIk1lZGl1bSIpDQojIENvbWJpbmUgYWxsIGNvbHVtcyBpbnRvIGEgZGF0YSBmcmFtZQ0KdHJhbnNhY3Rpb25zIDwtIGRhdGEuZnJhbWUoRGF0ZSwgUXR5ICxQcmljZSAsUHJvZHVjdCAsQ3VzdG9tZXJUaWVyKQ0KI1Nob3cgZGF0YSBmcmFtZQ0KI0FkZCBhIG5ldyBjb2x1bW4gZm9yIHRvdGFsDQp0cmFuc2FjdGlvbnMgPC0gdHJhbnNmb3JtICh0cmFuc2FjdGlvbnMsIFRvdGFsID0gUXR5ICogUHJpY2UpDQpWaWV3ICh0cmFuc2FjdGlvbnMpDQoNCnN0ciAodHJhbnNhY3Rpb25zKQ0KDQojIFRvdGFsIHF1YW50aXR5IHBlciBwcm9kdWN0DQphZ2dyZWdhdGUgKFF0eSB+IFByb2R1Y3QsIGRhdGEgPSANCiAgICAgICAgICAgICB0cmFuc2FjdGlvbnMsIEZVTiA9IHN1bSkNCg0KIyBUb3RhbCByZXZlbnVlIHBlciBwcm9kdWN0DQphZ2dyZWdhdGUgKFRvdGFsIH4gUHJvZHVjdCwgZGF0YSA9IA0KICAgICAgICAgICAgIHRyYW5zYWN0aW9ucywgRlVOID0gc3VtKQ0KDQojIFRvdGFsIHByaWNlIHBlciBwcm9kdWN0DQphZ2dyZWdhdGUgKFByaWNlIH4gUHJvZHVjdCwgZGF0YSA9IA0KICAgICAgICAgICAgIHRyYW5zYWN0aW9ucywgRlVOID0gbWVhbikNCg0KIyBUb3RhbCBxdWFudGl0eSBwZXIgcHJvZHVjdA0KcXR5X3Blcl9wcm9kdWN0IDwtIGFnZ3JlZ2F0ZSAoUXR5IH4gUHJvZHVjdCwgdHJhbnNhY3Rpb25zLCBzdW0pDQoNCiMgQmFyIGNoYXJ0IG9mIHF1YW50aXR5IHNvbGQNCmJhcnBsb3QgKHF0eV9wZXJfcHJvZHVjdCRRdHksIA0KICAgICAgICAgbmFtZXMuYXJnID0gcXR5X3Blcl9wcm9kdWN0JFByb2R1Y3QsDQogICAgICAgICBtYWluID0gIlF1YW50aXR5IFNvbGQgYnkgUHJvZHVjdCIsDQogICAgICAgICB4bGFiID0gIlByb2R1Y3QiLA0KICAgICAgICAgeWxhYiA9ICJRdWFudGl0eSIsDQogICAgICAgICBjb2wgPSAicmVkIikNCg0KDQojIFJldmVudWUgcGVyIGN1c3RvbSB0aWVyDQpyZXZlbnVlX3Blcl90aWVyIDwtIGFnZ3JlZ2F0ZSAoVG90YWwgfiBDdXN0b21lclRpZXIsIHRyYW5zYWN0aW9ucywgc3VtKQ0KDQojIFBpZSBjaGFydCBvZiByZXZlbnVlIHNoYXJlIA0KcGllIChyZXZlbnVlX3Blcl90aWVyJFRvdGFsLA0KICAgICBsYWJlbHMgPSByZXZlbnVlX3Blcl90aWVyJEN1c3RvbWVyVGllciwNCiAgICAgbWFpbiA9ICJSZXZlbnVlIFNoYXJlIGJ5IEN1c3RvbWVyIFRpZXIiLA0KICAgICBjb2wgPSByYWluYm93KDMpKQ0KDQpgYGANCg0KIyMgRXhlcmNpc2UgNQ0KDQoqKkNyZWF0ZSBZb3VyIE93biBEYXRhIEZyYW1lOioqDQoNCioqT2JqZWN0aXZlOioqIENyZWF0ZSBhIGRhdGEgZnJhbWUgaW4gUiB3aXRoICoqMzAgcm93cyoqIGNvbnRhaW5pbmcgYSBtaXggb2YgZGF0YSB0eXBlczogY29udGludW91cywgZGlzY3JldGUsIG5vbWluYWwsIGFuZCBvcmRpbmFsLg0KDQojIyMgSW5zdHJ1Y3Rpb25zDQoNCjEuICAqKk9wZW4gUlN0dWRpbyoqIG9yIHRoZSBSIGNvbnNvbGUuDQoNCjIuICAqKkNyZWF0ZSBhIHZlY3RvciBmb3IgZWFjaCBjb2x1bW4qKiBpbiB5b3VyIGRhdGEgZnJhbWU6DQoNCiAgICAtICAgKipEYXRlKio6IDMwIGRhdGVzIChjYW4gYmUgc2VxdWVudGlhbCBvciByYW5kb20gd2l0aGluIGEgbW9udGgveWVhcilcDQogICAgLSAgICoqQ29udGludW91cyoqOiBudW1lcmljIHZhbHVlcyB0aGF0IGNhbiB0YWtlIGRlY2ltYWwgdmFsdWVzIChlLmcuLCBoZWlnaHQsIHdlaWdodCwgdGVtcGVyYXR1cmUpXA0KICAgIC0gICAqKkRpc2NyZXRlKio6IG51bWVyaWMgdmFsdWVzIHRoYXQgY2FuIG9ubHkgdGFrZSB3aG9sZSBudW1iZXJzIChlLmcuLCBudW1iZXIgb2YgaXRlbXMsIG51bWJlciBvZiB2ZWhpY2xlcylcDQogICAgLSAgICoqTm9taW5hbCoqOiBjYXRlZ29yaWNhbCB2YWx1ZXMgd2l0aCAqKm5vIG9yZGVyKiogKGUuZy4sIGNvbG9yLCBnZW5kZXIsIGNpdHkpXA0KICAgIC0gICAqKk9yZGluYWwqKjogY2F0ZWdvcmljYWwgdmFsdWVzIHdpdGggYSAqKmRlZmluZWQgb3JkZXIqKiAoZS5nLiwgTG93LCBNZWRpdW0sIEhpZ2g7IEJlZ2lubmVyLCBJbnRlcm1lZGlhdGUsIEV4cGVydCkNCg0KMy4gICoqQ29tYmluZSBhbGwgdmVjdG9ycyBpbnRvIGEgZGF0YSBmcmFtZSoqIGNhbGxlZCBgbXlfZGF0YWAuDQoNCjQuICAqKkNoZWNrIHlvdXIgZGF0YSBmcmFtZSoqIHVzaW5nIGBoZWFkKClgIG9yIGBWaWV3KClgIHRvIGVuc3VyZSBpdCBoYXMgKiozMCByb3dzKiogYW5kIHRoZSBjb2x1bW5zIGFyZSBjb3JyZWN0Lg0KDQo1LiAgKipPcHRpb25hbCB0YXNrcyoqOg0KDQogICAgLSAgIFN1bW1hcml6ZSBlYWNoIGNvbHVtbiB1c2luZyBgc3VtbWFyeSgpYFwNCiAgICAtICAgQ291bnQgdGhlIGZyZXF1ZW5jeSBvZiBlYWNoIGNhdGVnb3J5IGZvciAqKk5vbWluYWwqKiBhbmQgKipPcmRpbmFsKiogY29sdW1ucyB1c2luZyBgdGFibGUoKWANCg0KIyMjIEhpbnRzDQoNCi0gICBVc2UgYHNlcS5EYXRlKClgIG9yIGBhcy5EYXRlKClgIHRvIGdlbmVyYXRlIHRoZSBEYXRlIGNvbHVtbi5cDQotICAgVXNlIGBydW5pZigpYCBvciBgcm5vcm0oKWAgZm9yIGNvbnRpbnVvdXMgbnVtZXJpYyBkYXRhLlwNCi0gICBVc2UgYHNhbXBsZSgpYCBmb3IgZGlzY3JldGUsIG5vbWluYWwsIGFuZCBvcmRpbmFsIGRhdGEuXA0KLSAgIEVuc3VyZSB0aGUgKipvcmRpbmFsIHZlY3RvcioqIGlzIGNyZWF0ZWQgd2l0aCBgZmFjdG9yKC4uLiwgbGV2ZWxzID0gYygiTG93IiwiTWVkaXVtIiwiSGlnaCIpLCBvcmRlcmVkID0gVFJVRSlgIChvciBzaW1pbGFyKS4NCg0KDQpgYGB7ciwgZWNobyA9IFRSVUUsIGluY2x1ZGUgPSBUUlVFLCB3YXJuaW5nID0gRkFMU0V9DQoNCiMgY3JlYXRlIGRhdGEgZnJhbWUgYWJvdXQgcHVyY2hhc2luZyBkcmlua3MgYXQgY2FmZSBzdGF0aXMNCg0KI0RhdGVzIGZyb20gU2VwdGVtYmVyIDEgdG8gU2VwdGVtYmVyIDMwIA0KZGF0ZSA9IHNlcS5EYXRlIChmcm9tID0gYXMuRGF0ZSAoIjIwMzAtMDktMDEiKSwgdG8gPQ0KICAgICAgICAgICAgICBhcy5EYXRlICgiMjAzMC0wOS0zMCIpLCBieSA9ICJkYXkiKQ0KDQojTnVtYmVyIG9mIGRyaW5rcyBvcmRlcmVkIGVhY2ggZGF5DQpzZXQuc2VlZCgxMjMpDQpOdW1iZXJfb2ZfRHJpbmtzIDwtIHNhbXBsZSAoMToxNSwgMzAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZSA9IFRSVUUpDQoNCiNUb3RhbCBwdXJjaGFzZSBhbW91bnQgDQpUb3RhbF9QdXJjaGFzZSA8LSByb3VuZCAoTnVtYmVyX29mX0RyaW5rcyAqIHJ1bmlmICgzMCwgbWluID0gMTUwMDAsIG1heCA9IDI1MDAwKSwgMCkNCg0KI1R5cGUgb2YgZHJpbmtzDQpEcmlua19UeXBlID0gc2FtcGxlIChjKCJNYXRjaGEiLCAiQ29mZmUiLCANCiAgICAgICAgICAgICAgICAgICJDaG9jb2xhdGUiLCJUZWEiLCANCiAgICAgICAgICAgICAgICAgICJNaWxrc2hha2UiLCAiTGF0dGUiKSwNCiAgICAgICAgICAgICAgICAzMCwgcmVwbGFjZSA9IFRSVUUpDQoNCiMgQ3VzdG9tZXIgc2F0aXNmYWN0aW9uIGxldmVsDQpzYXRpc2ZhY3Rpb24gPC0gaWZlbHNlIChUb3RhbF9QdXJjaGFzZSA8IDUwMDAwLCAiTm90IHNhdGlzZmllZCIsDQogICAgICAgICAgICAgICAgaWZlbHNlIChUb3RhbF9QdXJjaGFzZSA8IDEwMDAwMCwiU2F0aXNmaWVkIiwgDQogICAgICAgICAgICAgICAgIlZlcnkgc2F0aXNmaWVkIikpDQoNCiMNCnEgPC0gcXVhbnRpbGUoVG90YWxfUHVyY2hhc2UsIHByb2JzID0gYygwLCAxLzMsIDIvMywgMSkpDQpzYXRpc2ZhY3Rpb24gPC0gY3V0KFRvdGFsX1B1cmNoYXNlLA0KICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBxLA0KICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJOb3Qgc2F0aXNmaWVkIiwgIlNhdGlzZmllZCIsICJWZXJ5IHNhdGlzZmllZCIpLA0KICAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUpDQoNCg0KI2NvbWJpbmUgYWxsIGNvbHVtbnMgaW50byBvbiBkYXRhIGZyYW1lIG5hbWVkIG15X2RhdGENCm15X2RhdGEgPC0gZGF0YS5mcmFtZShkYXRlLCANCiAgICAgICAgICAgICAgICAgICAgICBUb3RhbF9QdXJjaGFzZSwgTnVtYmVyX29mX0RyaW5rcywgDQogICAgICAgICAgICAgICAgICAgICAgRHJpbmtfVHlwZSwgc2F0aXNmYWN0aW9uKQ0KDQojIDcuIFNob3cgZmlyc3QgZmV3IHJvd3MNCmhlYWQobXlfZGF0YSkNCg0KIyA4LiBQcmludCBmdWxsIGRhdGEgZnJhbWUNCnByaW50KG15X2RhdGEpDQoNCiMgOS4gQ2hlY2sgbnVtYmVyIG9mIHJvd3MNCm5yb3cobXlfZGF0YSkNCg0KIyAxMC4gRGlzcGxheSBzdW1tYXJ5IG9mIGVhY2ggY29sdW1uDQpzdW1tYXJ5KG15X2RhdGEpDQoNCiMgMTEuIE1ha2UgYSBmb3JtYXR0ZWQgdGFibGUgdXNpbmcga25pdHINCmxpYnJhcnkoa25pdHIpDQprYWJsZShteV9kYXRhLCBjYXB0aW9uID0gIlRhYmxlOiBEcmluayBQdXJjaGFzZSBEYXRhICgzMCBEYXlzKSIpDQoNCmxpYnJhcnkoa25pdHIpDQoNCiMgQ291bnQgaG93IG1hbnkgdGltZXMgZWFjaCBkcmluayB0eXBlIGFwcGVhcnMNCg0KZHJpbmtfdGFibGUgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShteV9kYXRhJERyaW5rX1R5cGUpKQ0KY29sbmFtZXMoZHJpbmtfdGFibGUpIDwtIGMoIkRyaW5rIFR5cGUiLCAiRnJlcXVlbmN5IikNCg0KIyBDb3VudCBzYXRpc2ZhY3Rpb24gbGV2ZWxzDQoNCnNhdGlzZmFjdGlvbl90YWJsZSA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKG15X2RhdGEkc2F0aXNmYWN0aW9uKSkNCmNvbG5hbWVzKHNhdGlzZmFjdGlvbl90YWJsZSkgPC0gYygiU2F0aXNmYWN0aW9uIExldmVsIiwgIkZyZXF1ZW5jeSIpDQoNCiMgc2hvdyB0YWJsZQ0Ka25pdHI6OmthYmxlKGRyaW5rX3RhYmxlLCBjYXB0aW9uID0gIlRhYmxlOiBGcmVxdWVuY3kgb2YgRWFjaCBEcmluayBUeXBlIikNCmtuaXRyOjprYWJsZShzYXRpc2ZhY3Rpb25fdGFibGUsIGNhcHRpb24gPSAiVGFibGU6IEZyZXF1ZW5jeSBvZiBFYWNoIFNhdGlzZmFjdGlvbiBMZXZlbCIp