Overview

The US Geological Survey publishes a list of Strategic Minerals ( https://www.usgs.gov/news/national-news-release/us-geological-survey-releases-2022-list-critical-minerals ). Having a secure supply of these minerals is essential to our security and economic prosperity. However many of these minerals are sourced from outside of the US. This assignment is to develop a reference catalog of the source or sources of each of these minerals and a judgement on the reliability of each source under stressed circumstance (e.g. war, economic crisis, etc.) Notes:

You will need to identify a source or sources for each of the minerals in the 2022 List of Critical Minerals

You will need to categorize each source country as an ally, a competitor or a neutral party.

You will need to develop data visualizations that tell the story of source dependency and shortfall impact.

Demand in the US for Key minerals

#Installing and loading the readxl package

library(readxl)

#Specifying the file path
file_path <- "C:/Users/aleja/Desktop/Total demand key minerals.xlsx"

#Reading the Excel file into a dataframe
minerals_data <- read_excel(file_path)
## New names:
## • `` -> `...2`
## • `` -> `...3`
## • `` -> `...4`
## • `` -> `...5`
## • `` -> `...6`
## • `` -> `...7`
## • `` -> `...8`
## • `` -> `...9`
## • `` -> `...10`
## • `` -> `...11`
## • `` -> `...12`
## • `` -> `...13`
## • `` -> `...14`
## • `` -> `...15`
## • `` -> `...16`
## • `` -> `...17`
## • `` -> `...18`
## • `` -> `...19`
## • `` -> `...20`
## • `` -> `...21`
## • `` -> `...22`
## • `` -> `...23`
#View the structure of the dataframe
str(minerals_data)
## tibble [58 × 23] (S3: tbl_df/tbl/data.frame)
##  $ Total demand for lithium, copper, cobalt, nickel and neodymium (kt): chr [1:58] NA NA NA NA ...
##  $ ...2                                                               : num [1:58] NA NA 2022 NA NA ...
##  $ ...3                                                               : logi [1:58] NA NA NA NA NA NA ...
##  $ ...4                                                               : chr [1:58] NA "Stated policies scenario" "2025" NA ...
##  $ ...5                                                               : num [1:58] NA NA 2030 NA NA ...
##  $ ...6                                                               : num [1:58] NA NA 2035 NA NA ...
##  $ ...7                                                               : num [1:58] NA NA 2040 NA NA ...
##  $ ...8                                                               : num [1:58] NA NA 2045 NA NA ...
##  $ ...9                                                               : num [1:58] NA NA 2050 NA NA ...
##  $ ...10                                                              : logi [1:58] NA NA NA NA NA NA ...
##  $ ...11                                                              : chr [1:58] NA "Announced pledges scenario" "2025" NA ...
##  $ ...12                                                              : num [1:58] NA NA 2030 NA NA ...
##  $ ...13                                                              : num [1:58] NA NA 2035 NA NA ...
##  $ ...14                                                              : num [1:58] NA NA 2040 NA NA ...
##  $ ...15                                                              : num [1:58] NA NA 2045 NA NA ...
##  $ ...16                                                              : num [1:58] NA NA 2050 NA NA ...
##  $ ...17                                                              : logi [1:58] NA NA NA NA NA NA ...
##  $ ...18                                                              : chr [1:58] NA "Net Zero Emissions by 2050 scenario" "2025" NA ...
##  $ ...19                                                              : num [1:58] NA NA 2030 NA NA ...
##  $ ...20                                                              : num [1:58] NA NA 2035 NA NA ...
##  $ ...21                                                              : num [1:58] NA NA 2040 NA NA ...
##  $ ...22                                                              : num [1:58] NA NA 2045 NA NA ...
##  $ ...23                                                              : num [1:58] NA NA 2050 NA NA ...
#View the first few rows of the dataframe
head(minerals_data)
## # A tibble: 6 × 23
##   Total demand for lithi…¹  ...2 ...3  ...4   ...5  ...6  ...7  ...8  ...9 ...10
##   <chr>                    <dbl> <lgl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <lgl>
## 1 <NA>                       NA  NA    <NA>    NA    NA    NA    NA    NA  NA   
## 2 <NA>                       NA  NA    Stat…   NA    NA    NA    NA    NA  NA   
## 3 <NA>                     2022  NA    2025  2030  2035  2040  2045  2050  NA   
## 4 <NA>                       NA  NA    <NA>    NA    NA    NA    NA    NA  NA   
## 5 Copper                     NA  NA    <NA>    NA    NA    NA    NA    NA  NA   
## 6 Solar PV                  682. NA    778.…  907.  925.  959. 1122. 1262. NA   
## # ℹ abbreviated name:
## #   ¹​`Total demand for lithium, copper, cobalt, nickel and neodymium (kt)`
## # ℹ 13 more variables: ...11 <chr>, ...12 <dbl>, ...13 <dbl>, ...14 <dbl>,
## #   ...15 <dbl>, ...16 <dbl>, ...17 <lgl>, ...18 <chr>, ...19 <dbl>,
## #   ...20 <dbl>, ...21 <dbl>, ...22 <dbl>, ...23 <dbl>
#Creating dataframes for each mineral
copper_data <- data.frame(
  Mineral = "Copper",
  Category = c("Solar PV", "Wind", "Other low emissions power generation", "Electric vehicles", "Grid battery storage", "Electricity networks", "Hydrogen technologies", "Total clean technologies", "Other uses", "Total demand", "Share of clean technologies in total demand"),
  Total_Demand = c(682, 394, 85, 373, 20, 4182, 0, 5736, NA, NA, 22)
)

cobalt_data <- data.frame(
  Mineral = "Cobalt",
  Category = c("Low emissions power generation", "Electric vehicles", "Grid battery storage", "Hydrogen technologies", "Total clean technologies", "Other uses", "Total demand", "Share of clean technologies in total demand"),
  Total_Demand = c(0, 65, 4, 0, 68, 103, 171, 40)
)

lithium_data <- data.frame(
  Mineral = "Lithium",
  Category = c("Electric vehicles", "Grid battery storage", "Total clean technologies", "Other uses", "Total demand", "Share of clean technologies in total demand"),
  Total_Demand = c(70, 3, 73, 57, 130, 56)
)

nickel_data <- data.frame(
  Mineral = "Nickel",
  Category = c("Solar PV", "Wind", "Other low emissions power generation", "Electric vehicles", "Grid battery storage", "Hydrogen technologies", "Total clean technologies", "Other uses", "Total demand", "Share of clean technologies in total demand"),
  Total_Demand = c(0, 37, 83, 326, 9, 2, 457, 2477, 2934, 16)
)

neodymium_data <- data.frame(
  Mineral = "Neodymium",
  Category = c("Wind", "Electric vehicles", "Total clean technologies", "Other uses", "Total demand", "Share of clean technologies in total demand"),
  Total_Demand = c(6, 4, 10, 40, 50, 20)
)

# Combine dataframes into a single dataframe
mineral_data <- rbind(copper_data, cobalt_data, lithium_data, nickel_data, neodymium_data)

# Print the dataframe
print(mineral_data)
##      Mineral                                    Category Total_Demand
## 1     Copper                                    Solar PV          682
## 2     Copper                                        Wind          394
## 3     Copper        Other low emissions power generation           85
## 4     Copper                           Electric vehicles          373
## 5     Copper                        Grid battery storage           20
## 6     Copper                        Electricity networks         4182
## 7     Copper                       Hydrogen technologies            0
## 8     Copper                    Total clean technologies         5736
## 9     Copper                                  Other uses           NA
## 10    Copper                                Total demand           NA
## 11    Copper Share of clean technologies in total demand           22
## 12    Cobalt              Low emissions power generation            0
## 13    Cobalt                           Electric vehicles           65
## 14    Cobalt                        Grid battery storage            4
## 15    Cobalt                       Hydrogen technologies            0
## 16    Cobalt                    Total clean technologies           68
## 17    Cobalt                                  Other uses          103
## 18    Cobalt                                Total demand          171
## 19    Cobalt Share of clean technologies in total demand           40
## 20   Lithium                           Electric vehicles           70
## 21   Lithium                        Grid battery storage            3
## 22   Lithium                    Total clean technologies           73
## 23   Lithium                                  Other uses           57
## 24   Lithium                                Total demand          130
## 25   Lithium Share of clean technologies in total demand           56
## 26    Nickel                                    Solar PV            0
## 27    Nickel                                        Wind           37
## 28    Nickel        Other low emissions power generation           83
## 29    Nickel                           Electric vehicles          326
## 30    Nickel                        Grid battery storage            9
## 31    Nickel                       Hydrogen technologies            2
## 32    Nickel                    Total clean technologies          457
## 33    Nickel                                  Other uses         2477
## 34    Nickel                                Total demand         2934
## 35    Nickel Share of clean technologies in total demand           16
## 36 Neodymium                                        Wind            6
## 37 Neodymium                           Electric vehicles            4
## 38 Neodymium                    Total clean technologies           10
## 39 Neodymium                                  Other uses           40
## 40 Neodymium                                Total demand           50
## 41 Neodymium Share of clean technologies in total demand           20
#Extracting the first two columns (Mineral and Category) from the combined dataframe
mineral_category <- mineral_data[, c("Mineral", "Category")]

#Printing the extracted dataframe
print(mineral_category)
##      Mineral                                    Category
## 1     Copper                                    Solar PV
## 2     Copper                                        Wind
## 3     Copper        Other low emissions power generation
## 4     Copper                           Electric vehicles
## 5     Copper                        Grid battery storage
## 6     Copper                        Electricity networks
## 7     Copper                       Hydrogen technologies
## 8     Copper                    Total clean technologies
## 9     Copper                                  Other uses
## 10    Copper                                Total demand
## 11    Copper Share of clean technologies in total demand
## 12    Cobalt              Low emissions power generation
## 13    Cobalt                           Electric vehicles
## 14    Cobalt                        Grid battery storage
## 15    Cobalt                       Hydrogen technologies
## 16    Cobalt                    Total clean technologies
## 17    Cobalt                                  Other uses
## 18    Cobalt                                Total demand
## 19    Cobalt Share of clean technologies in total demand
## 20   Lithium                           Electric vehicles
## 21   Lithium                        Grid battery storage
## 22   Lithium                    Total clean technologies
## 23   Lithium                                  Other uses
## 24   Lithium                                Total demand
## 25   Lithium Share of clean technologies in total demand
## 26    Nickel                                    Solar PV
## 27    Nickel                                        Wind
## 28    Nickel        Other low emissions power generation
## 29    Nickel                           Electric vehicles
## 30    Nickel                        Grid battery storage
## 31    Nickel                       Hydrogen technologies
## 32    Nickel                    Total clean technologies
## 33    Nickel                                  Other uses
## 34    Nickel                                Total demand
## 35    Nickel Share of clean technologies in total demand
## 36 Neodymium                                        Wind
## 37 Neodymium                           Electric vehicles
## 38 Neodymium                    Total clean technologies
## 39 Neodymium                                  Other uses
## 40 Neodymium                                Total demand
## 41 Neodymium Share of clean technologies in total demand
#Loading the required packages
library(kableExtra)

#Creating a table with the Mineral, Category, and Total Demand columns
table <- mineral_data[, c("Mineral", "Category", "Total_Demand")]

#Displaying the table with kable
kable(table, format = "html", caption = "Mineral Category Table") %>%
  kable_styling(full_width = FALSE)
Mineral Category Table
Mineral Category Total_Demand
Copper Solar PV 682
Copper Wind 394
Copper Other low emissions power generation 85
Copper Electric vehicles 373
Copper Grid battery storage 20
Copper Electricity networks 4182
Copper Hydrogen technologies 0
Copper Total clean technologies 5736
Copper Other uses NA
Copper Total demand NA
Copper Share of clean technologies in total demand 22
Cobalt Low emissions power generation 0
Cobalt Electric vehicles 65
Cobalt Grid battery storage 4
Cobalt Hydrogen technologies 0
Cobalt Total clean technologies 68
Cobalt Other uses 103
Cobalt Total demand 171
Cobalt Share of clean technologies in total demand 40
Lithium Electric vehicles 70
Lithium Grid battery storage 3
Lithium Total clean technologies 73
Lithium Other uses 57
Lithium Total demand 130
Lithium Share of clean technologies in total demand 56
Nickel Solar PV 0
Nickel Wind 37
Nickel Other low emissions power generation 83
Nickel Electric vehicles 326
Nickel Grid battery storage 9
Nickel Hydrogen technologies 2
Nickel Total clean technologies 457
Nickel Other uses 2477
Nickel Total demand 2934
Nickel Share of clean technologies in total demand 16
Neodymium Wind 6
Neodymium Electric vehicles 4
Neodymium Total clean technologies 10
Neodymium Other uses 40
Neodymium Total demand 50
Neodymium Share of clean technologies in total demand 20
#Loading the required packages
library(kableExtra)

#Removing rows with NA values
mineral_data_clean <- mineral_data[complete.cases(mineral_data), ]

#Creating a table with the Mineral, Category, and Total Demand columns
table <- mineral_data_clean[, c("Mineral", "Category", "Total_Demand")]

#Displaying the table with kable
kable(table, format = "html", caption = "Mineral Category Table") %>%
  kable_styling(full_width = FALSE)
Mineral Category Table
Mineral Category Total_Demand
1 Copper Solar PV 682
2 Copper Wind 394
3 Copper Other low emissions power generation 85
4 Copper Electric vehicles 373
5 Copper Grid battery storage 20
6 Copper Electricity networks 4182
7 Copper Hydrogen technologies 0
8 Copper Total clean technologies 5736
11 Copper Share of clean technologies in total demand 22
12 Cobalt Low emissions power generation 0
13 Cobalt Electric vehicles 65
14 Cobalt Grid battery storage 4
15 Cobalt Hydrogen technologies 0
16 Cobalt Total clean technologies 68
17 Cobalt Other uses 103
18 Cobalt Total demand 171
19 Cobalt Share of clean technologies in total demand 40
20 Lithium Electric vehicles 70
21 Lithium Grid battery storage 3
22 Lithium Total clean technologies 73
23 Lithium Other uses 57
24 Lithium Total demand 130
25 Lithium Share of clean technologies in total demand 56
26 Nickel Solar PV 0
27 Nickel Wind 37
28 Nickel Other low emissions power generation 83
29 Nickel Electric vehicles 326
30 Nickel Grid battery storage 9
31 Nickel Hydrogen technologies 2
32 Nickel Total clean technologies 457
33 Nickel Other uses 2477
34 Nickel Total demand 2934
35 Nickel Share of clean technologies in total demand 16
36 Neodymium Wind 6
37 Neodymium Electric vehicles 4
38 Neodymium Total clean technologies 10
39 Neodymium Other uses 40
40 Neodymium Total demand 50
41 Neodymium Share of clean technologies in total demand 20

Total demand minerals 2022 in US

library(ggplot2) 
#Aggregate total demand for each mineral
total_demand <- aggregate(Total_Demand ~ Mineral, data = mineral_data_clean, sum)

#Creating a bar chart
ggplot(total_demand, aes(x = Mineral, y = Total_Demand, fill = Mineral)) +
  geom_bar(stat = "identity") +
  labs(title = "Total Demand of Each Mineral 2022",
       x = "Mineral",
       y = "Total Demand") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Usage in Clean Technologies: The data highlights the significant demand for minerals like copper, cobalt, lithium, nickel, and neodymium in clean technologies such as solar PV, wind power, electric vehicles, and grid battery storage. This indicates the importance of these minerals in supporting the transition towards renewable energy and low-emission technologies.

Diverse Applications: Each mineral serves multiple applications beyond clean technologies. For example, copper is also used in electricity networks, while nickel finds applications in other low emissions power generation methods. Understanding the diverse applications of these minerals helps assess their overall importance in various industries.

Strategic Importance of Clean Technologies: The share of clean technologies in total demand for each mineral provides insights into the strategic importance of these minerals in driving the clean energy transition. Minerals like cobalt and lithium, which have a higher share of demand from clean technologies, are crucial for accelerating the adoption of electric vehicles and energy storage solutions.

Supply Chain Risks: The concentration of demand for certain minerals in specific applications, such as electric vehicles and grid battery storage, highlights potential supply chain risks. Dependency on a limited number of applications or industries can make the supply chain vulnerable to disruptions, emphasizing the need for diversification and resilience strategies.

Policy Implications: Policymakers can use this data to formulate policies that promote sustainable sourcing, recycling, and domestic production of these critical minerals. Ensuring a stable and diversified supply of these minerals is essential for achieving long-term energy security and environmental sustainability goals.

Mineral imports in US

#Loading the dataset
wits_partner <- read.csv("C:/Users/aleja/Desktop/WITS-Partner.csv", stringsAsFactors = FALSE)

#Displaying the structure of the dataset
str(wits_partner)
## 'data.frame':    126 obs. of  31 variables:
##  $ Reporter.Name                          : chr  "United States" "United States" "United States" "United States" ...
##  $ Partner.Name                           : chr  "Albania" "United Arab Emirates" "Argentina" "Armenia" ...
##  $ Year                                   : int  2021 2021 2021 2021 2021 2021 2021 2021 2021 2021 ...
##  $ Trade.Flow                             : chr  "Import" "Import" "Import" "Import" ...
##  $ Product.Group                          : chr  "Minerals" "Minerals" "Minerals" "Minerals" ...
##  $ Import..US..Thousand.                  : num  6 103303 3429 50 256116 ...
##  $ Import.Product.Share....               : num  0.01 1.66 0.06 0.06 2.16 0.03 0 6.35 0.11 0.01 ...
##  $ AHS.Simple.Average....                 : num  0 0.14 0 NA 0 0.07 0 0 0.34 1.13 ...
##  $ AHS.Weighted.Average....               : num  0 0 0 NA 0 0.3 0 0 0.04 1.65 ...
##  $ AHS.Total.Tariff.Lines                 : int  2 12 9 NA 30 18 1 2 37 8 ...
##  $ AHS.Dutiable.Tariff.Lines.Share....    : num  0 8.33 0 NA 0 ...
##  $ AHS.Duty.Free.Tariff.Lines.Share....   : num  100 91.7 100 NA 100 ...
##  $ AHS.Specific.Tariff.Lines.Share....    : num  0 0 0 NA 0 0 0 0 2.7 0 ...
##  $ AHS.AVE.Tariff.Lines.Share....         : num  0 0 0 NA 0 0 0 0 0 0 ...
##  $ AHS.MaxRate....                        : num  0 2.9 0 NA 0 2.9 0 0 3 3 ...
##  $ AHS.MinRate....                        : int  0 0 0 NA 0 0 0 0 0 0 ...
##  $ AHS.SpecificDuty.Imports..US..Thousand.: num  0 0 0 NA 0 ...
##  $ AHS.Dutiable.Imports..US..Thousand.    : num  0 25.7 0 NA 0 ...
##  $ AHS.Duty.Free.Imports..US..Thousand.   : num  6 9330 3332 NA 235201 ...
##  $ MFN.Simple.Average....                 : num  1.5 0.14 0.14 NA 0.23 0.07 0 1.28 0.34 1.13 ...
##  $ MFN.Weighted.Average....               : num  1.5 0 0.04 NA 0.06 0.3 0 1.28 0.04 1.65 ...
##  $ MFN.Total.Tariff.Lines                 : int  2 12 9 NA 30 18 1 2 37 8 ...
##  $ MFN.Dutiable.Tariff.Lines.Share....    : num  50 8.33 11.11 NA 6.67 ...
##  $ MFN.Duty.Free.Tariff.Lines.Share....   : num  50 91.7 88.9 NA 90 ...
##  $ MFN.Specific.Tariff.Lines.Share....    : num  0 0 0 NA 0 0 0 0 2.7 0 ...
##  $ MFN.AVE.Tariff.Lines.Share....         : num  0 0 0 NA 3.33 0 0 50 0 0 ...
##  $ MFN.MaxRate....                        : num  3 2.9 2.9 NA 3 2.9 0 2.55 3 3 ...
##  $ MFN.MinRate....                        : int  0 0 0 NA 0 0 0 0 0 0 ...
##  $ MFN.SpecificDuty.Imports..US..Thousand.: num  0 0 0 NA 0 ...
##  $ MFN.Dutiable.Imports..US..Thousand.    : num  6 25.7 149.1 NA 13465.2 ...
##  $ MFN.Duty.Free.Imports..US..Thousand.   : num  0 9330 3183 NA 221735 ...
#Displaying the first few rows of the dataset
head(wits_partner)
##   Reporter.Name         Partner.Name Year Trade.Flow Product.Group
## 1 United States              Albania 2021     Import      Minerals
## 2 United States United Arab Emirates 2021     Import      Minerals
## 3 United States            Argentina 2021     Import      Minerals
## 4 United States              Armenia 2021     Import      Minerals
## 5 United States            Australia 2021     Import      Minerals
## 6 United States              Austria 2021     Import      Minerals
##   Import..US..Thousand. Import.Product.Share.... AHS.Simple.Average....
## 1                  6.00                     0.01                   0.00
## 2             103302.98                     1.66                   0.14
## 3               3428.89                     0.06                   0.00
## 4                 49.98                     0.06                     NA
## 5             256115.59                     2.16                   0.00
## 6               4209.11                     0.03                   0.07
##   AHS.Weighted.Average.... AHS.Total.Tariff.Lines
## 1                      0.0                      2
## 2                      0.0                     12
## 3                      0.0                      9
## 4                       NA                     NA
## 5                      0.0                     30
## 6                      0.3                     18
##   AHS.Dutiable.Tariff.Lines.Share.... AHS.Duty.Free.Tariff.Lines.Share....
## 1                                0.00                               100.00
## 2                                8.33                                91.67
## 3                                0.00                               100.00
## 4                                  NA                                   NA
## 5                                0.00                               100.00
## 6                                5.56                                94.44
##   AHS.Specific.Tariff.Lines.Share.... AHS.AVE.Tariff.Lines.Share....
## 1                                   0                              0
## 2                                   0                              0
## 3                                   0                              0
## 4                                  NA                             NA
## 5                                   0                              0
## 6                                   0                              0
##   AHS.MaxRate.... AHS.MinRate.... AHS.SpecificDuty.Imports..US..Thousand.
## 1             0.0               0                                       0
## 2             2.9               0                                       0
## 3             0.0               0                                       0
## 4              NA              NA                                      NA
## 5             0.0               0                                       0
## 6             2.9               0                                       0
##   AHS.Dutiable.Imports..US..Thousand. AHS.Duty.Free.Imports..US..Thousand.
## 1                                0.00                                 6.00
## 2                               25.74                              9329.78
## 3                                0.00                              3332.13
## 4                                  NA                                   NA
## 5                                0.00                            235200.66
## 6                             1171.06                              2600.56
##   MFN.Simple.Average.... MFN.Weighted.Average.... MFN.Total.Tariff.Lines
## 1                   1.50                     1.50                      2
## 2                   0.14                     0.00                     12
## 3                   0.14                     0.04                      9
## 4                     NA                       NA                     NA
## 5                   0.23                     0.06                     30
## 6                   0.07                     0.30                     18
##   MFN.Dutiable.Tariff.Lines.Share.... MFN.Duty.Free.Tariff.Lines.Share....
## 1                               50.00                                50.00
## 2                                8.33                                91.67
## 3                               11.11                                88.89
## 4                                  NA                                   NA
## 5                                6.67                                90.00
## 6                                5.56                                94.44
##   MFN.Specific.Tariff.Lines.Share.... MFN.AVE.Tariff.Lines.Share....
## 1                                   0                           0.00
## 2                                   0                           0.00
## 3                                   0                           0.00
## 4                                  NA                             NA
## 5                                   0                           3.33
## 6                                   0                           0.00
##   MFN.MaxRate.... MFN.MinRate.... MFN.SpecificDuty.Imports..US..Thousand.
## 1             3.0               0                                       0
## 2             2.9               0                                       0
## 3             2.9               0                                       0
## 4              NA              NA                                      NA
## 5             3.0               0                                       0
## 6             2.9               0                                       0
##   MFN.Dutiable.Imports..US..Thousand. MFN.Duty.Free.Imports..US..Thousand.
## 1                                6.00                                 0.00
## 2                               25.74                              9329.78
## 3                              149.07                              3183.06
## 4                                  NA                                   NA
## 5                            13465.25                            221735.41
## 6                             1171.06                              2600.56

Top 15 importing countries

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:kableExtra':
## 
##     group_rows
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
library(scales)

#Aggregating total imports from each partner country
top_countries <- wits_partner %>%
  filter(Trade.Flow == "Import") %>%
  group_by(Partner.Name) %>%
  summarise(Total_Import = sum(Import..US..Thousand.))

#Sorting the top countries by total import value
top_countries <- top_countries %>%
  arrange(desc(Total_Import)) %>%
  head(15) # Select the top 15 countries

#Creating a horizontal bar chart
ggplot(top_countries, aes(x = reorder(Partner.Name, Total_Import), y = Total_Import)) +
  geom_bar(stat = "identity", fill = "skyblue") +
  labs(title = "Top 15 Countries Importing to the US",
       y = "Total Import (US$ Thousand)",
       x = "Partner Country") +
  scale_y_continuous(labels = comma) +  # Format y-axis labels with commas
  theme(axis.text.y = element_text(hjust = 1),
        plot.title = element_text(hjust = 0.5)) +
  coord_flip()

Total imports

library(dplyr)
library(ggplot2)
library(maps)

#Filtering the data for import flows
import_data <- wits_partner %>%
  filter(Trade.Flow == "Import")

#Aggregating total imports from each partner country
import_sum <- import_data %>%
  group_by(Partner.Name) %>%
  summarise(Total_Import = sum(`Import..US..Thousand.`))

#Loading world map data
world_map <- map_data("world")

#Merging import data with world map data
import_map <- merge(world_map, import_sum, by.x = "region", by.y = "Partner.Name", all.x = TRUE)

#Creating a map plot
ggplot(import_map, aes(x = long, y = lat, group = group, fill = Total_Import)) +
  geom_polygon(color = "transparent", size = 0.2) +
  scale_fill_gradient(low = "lightblue", high = "darkblue", na.value = "grey", name = "Total Import (US$ Thousand)") +
  labs(title = "Import Values from Countries Partnering with the US") +
  theme_minimal() +
  coord_fixed()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

#Defining the alliance mapping
#Adding Brazil as a competitor
alliance_mapping <- list(
    'Chile' = "Neutral",
    'South Africa' = "Ally",
    'Finland' = "Ally", 
    'Mexico' = "Neutral",
    'Indonesia' = "Ally", 
    'Norway' = "Ally", 
    'Canada' = "Ally",
    'Russia' = "Strained Relations", 
    'Japan' = "Ally", 
    'Philippines' = "Neutral",
    'Peru' = "Neutral", 
    'Cuba' = "Strained Relations",
    'Australia' = "Ally", 
    'Burma' = "Neutral", 
    'Portugal' = "Ally", 
    'Sweden' = "Ally",
    'China' = "Strained Relations",
    'Mauritania' = "Neutral",
    'Brazil' = "Strained Relations",
    'Argentina' = "Neutral", 
    'Germany' = "Ally",
    'Namibia' = "Neutral",
    'Zambia' = "Neutral",
    'India' = "Neutral",
    'Poland' = "Ally",
    'Democratic Republic of Congo' = "Neutral",
    'Vietnam' = "Neutral",
    'Papua New Guinea' = "Neutral",
    'Honduras' = "Neutral"
)

#Adding the 'status' column to wits_partner dataset
wits_partner$status <- unlist(lapply(wits_partner$Partner.Name, function(country) {
  if (country %in% names(alliance_mapping)) {
    return(alliance_mapping[[country]])
  } else {
    return("Neutral")
  }
}))

#Checking the first few rows of the updated dataset
head(wits_partner)
##   Reporter.Name         Partner.Name Year Trade.Flow Product.Group
## 1 United States              Albania 2021     Import      Minerals
## 2 United States United Arab Emirates 2021     Import      Minerals
## 3 United States            Argentina 2021     Import      Minerals
## 4 United States              Armenia 2021     Import      Minerals
## 5 United States            Australia 2021     Import      Minerals
## 6 United States              Austria 2021     Import      Minerals
##   Import..US..Thousand. Import.Product.Share.... AHS.Simple.Average....
## 1                  6.00                     0.01                   0.00
## 2             103302.98                     1.66                   0.14
## 3               3428.89                     0.06                   0.00
## 4                 49.98                     0.06                     NA
## 5             256115.59                     2.16                   0.00
## 6               4209.11                     0.03                   0.07
##   AHS.Weighted.Average.... AHS.Total.Tariff.Lines
## 1                      0.0                      2
## 2                      0.0                     12
## 3                      0.0                      9
## 4                       NA                     NA
## 5                      0.0                     30
## 6                      0.3                     18
##   AHS.Dutiable.Tariff.Lines.Share.... AHS.Duty.Free.Tariff.Lines.Share....
## 1                                0.00                               100.00
## 2                                8.33                                91.67
## 3                                0.00                               100.00
## 4                                  NA                                   NA
## 5                                0.00                               100.00
## 6                                5.56                                94.44
##   AHS.Specific.Tariff.Lines.Share.... AHS.AVE.Tariff.Lines.Share....
## 1                                   0                              0
## 2                                   0                              0
## 3                                   0                              0
## 4                                  NA                             NA
## 5                                   0                              0
## 6                                   0                              0
##   AHS.MaxRate.... AHS.MinRate.... AHS.SpecificDuty.Imports..US..Thousand.
## 1             0.0               0                                       0
## 2             2.9               0                                       0
## 3             0.0               0                                       0
## 4              NA              NA                                      NA
## 5             0.0               0                                       0
## 6             2.9               0                                       0
##   AHS.Dutiable.Imports..US..Thousand. AHS.Duty.Free.Imports..US..Thousand.
## 1                                0.00                                 6.00
## 2                               25.74                              9329.78
## 3                                0.00                              3332.13
## 4                                  NA                                   NA
## 5                                0.00                            235200.66
## 6                             1171.06                              2600.56
##   MFN.Simple.Average.... MFN.Weighted.Average.... MFN.Total.Tariff.Lines
## 1                   1.50                     1.50                      2
## 2                   0.14                     0.00                     12
## 3                   0.14                     0.04                      9
## 4                     NA                       NA                     NA
## 5                   0.23                     0.06                     30
## 6                   0.07                     0.30                     18
##   MFN.Dutiable.Tariff.Lines.Share.... MFN.Duty.Free.Tariff.Lines.Share....
## 1                               50.00                                50.00
## 2                                8.33                                91.67
## 3                               11.11                                88.89
## 4                                  NA                                   NA
## 5                                6.67                                90.00
## 6                                5.56                                94.44
##   MFN.Specific.Tariff.Lines.Share.... MFN.AVE.Tariff.Lines.Share....
## 1                                   0                           0.00
## 2                                   0                           0.00
## 3                                   0                           0.00
## 4                                  NA                             NA
## 5                                   0                           3.33
## 6                                   0                           0.00
##   MFN.MaxRate.... MFN.MinRate.... MFN.SpecificDuty.Imports..US..Thousand.
## 1             3.0               0                                       0
## 2             2.9               0                                       0
## 3             2.9               0                                       0
## 4              NA              NA                                      NA
## 5             3.0               0                                       0
## 6             2.9               0                                       0
##   MFN.Dutiable.Imports..US..Thousand. MFN.Duty.Free.Imports..US..Thousand.
## 1                                6.00                                 0.00
## 2                               25.74                              9329.78
## 3                              149.07                              3183.06
## 4                                  NA                                   NA
## 5                            13465.25                            221735.41
## 6                             1171.06                              2600.56
##    status
## 1 Neutral
## 2 Neutral
## 3 Neutral
## 4 Neutral
## 5    Ally
## 6 Neutral
library(ggplot2)
library(maps)

#Loading world map data
world_map <- map_data("world")

#Merging world map data with wits_partner dataset
map_data <- merge(world_map, wits_partner, by.x = "region", by.y = "Partner.Name", all.x = TRUE)

#Creating a map plot with color-coded alliance status
ggplot(map_data, aes(x = long, y = lat, group = group, fill = status)) +
  geom_polygon(color = "transparent", size = 0.2) +
  scale_fill_manual(values = c("Ally" = "blue", "Competitor" = "red", "Neutral" = "green"),
                    na.value = "grey", name = "Status",
                    labels = c("Ally", "Competitor", "Neutral")) +
  labs(title = "Alliance Status of Countries",
       fill = "Status") +
  theme_minimal() +
  coord_fixed() +
  theme(legend.position = "bottom")  # Move legend to the bottom of the plot

library(ggplot2)
library(maps)

#Loading world map data
world_map <- map_data("world")

#Merging world map data with wits_partner dataset
map_data <- merge(world_map, wits_partner, by.x = "region", by.y = "Partner.Name", all.x = TRUE)

#Creating a map plot with color-coded alliance status
ggplot(map_data, aes(x = long, y = lat, group = group, fill = status)) +
  geom_polygon(color = "transparent", size = 0.2) +
  scale_fill_manual(values = c("Ally" = "blue", "Strained Relations" = "red", "Neutral" = "green"),
                    na.value = "grey", name = "Status",
                    labels = c("Ally", "Competitors", "Neutral")) +
  labs(title = "Alliance Status of Countries",
       fill = "Status") +
  theme_minimal() +
  coord_fixed() +
  theme(legend.position = "bottom")  # Move legend to the bottom of the plot

library(dplyr)
library(ggplot2)

#Filtering the data by status and aggregate total imports
status_imports <- wits_partner %>%
  group_by(status, Partner.Name) %>%
  summarise(Total_Import = sum(`Import..US..Thousand.`)) %>%
  arrange(desc(Total_Import)) %>%
  group_by(status) %>%
  top_n(10)
## `summarise()` has grouped output by 'status'. You can override using the
## `.groups` argument.
## Selecting by Total_Import
#Creating separate plots for each status
ally_plot <- ggplot(filter(status_imports, status == "Ally"), aes(x = reorder(Partner.Name, Total_Import), y = Total_Import)) +
  geom_bar(stat = "identity", fill = "blue") +
  labs(title = "Top 5 Ally Countries Importing to the US",
       y = "Total Import (US$ Thousand)",
       x = "Partner Country") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

competitor_plot <- ggplot(filter(status_imports, status == "Strained Relations"), aes(x = reorder(Partner.Name, Total_Import), y = Total_Import)) +
  geom_bar(stat = "identity", fill = "red") +
  labs(title = "Top 5 Competitor Countries Importing to the US",
       y = "Total Import (US$ Thousand)",
       x = "Partner Country") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

neutral_plot <- ggplot(filter(status_imports, status == "Neutral"), aes(x = reorder(Partner.Name, Total_Import), y = Total_Import)) +
  geom_bar(stat = "identity", fill = "green") +
  labs(title = "Top 5 Neutral Countries Importing to the US",
       y = "Total Import (US$ Thousand)",
       x = "Partner Country") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

#Displaying the plots
ally_plot

competitor_plot

neutral_plot

Conclusions

In conclusion, the analysis of mineral demand and import data provides valuable insights into the strategic importance of critical minerals for the United States. Key findings:

Importance of Critical Minerals: The US Geological Survey identifies certain minerals as critical due to their essential role in national security and economic prosperity. These minerals are crucial for various industries, including clean energy technologies like solar PV, wind power, electric vehicles, and grid battery storage.

Dependency on Foreign Sources: Despite their importance, many critical minerals are sourced from outside the US. This dependency raises concerns about supply chain vulnerabilities, especially during times of geopolitical tension, economic crises, or trade disruptions.

Categorization of Source Countries: As part of the assignment, each source country for critical minerals needs to be categorized as an ally, competitor, or neutral party. Understanding the geopolitical dynamics of mineral sourcing is essential for assessing reliability under stressed circumstances.

References

Mineral Commodity Summaries 2023: https://pubs.usgs.gov/publication/mcs2023

LS0tDQp0aXRsZTogIkRhdGEgNjA4IFN0b3J5IDciDQphdXRob3I6ICJMYXVyYSBCIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0OiBvcGVuaW50cm86OmxhYl9yZXBvcnQNCi0tLQ0KDQojIyBPdmVydmlldw0KDQpUaGUgVVMgR2VvbG9naWNhbCBTdXJ2ZXkgcHVibGlzaGVzIGEgbGlzdCBvZiBTdHJhdGVnaWMgTWluZXJhbHMgKCBodHRwczovL3d3dy51c2dzLmdvdi9uZXdzL25hdGlvbmFsLW5ld3MtcmVsZWFzZS91cy1nZW9sb2dpY2FsLXN1cnZleS1yZWxlYXNlcy0yMDIyLWxpc3QtY3JpdGljYWwtbWluZXJhbHMgKS4gSGF2aW5nIGEgc2VjdXJlIHN1cHBseSBvZiB0aGVzZSBtaW5lcmFscyBpcyBlc3NlbnRpYWwgdG8gb3VyIHNlY3VyaXR5IGFuZCBlY29ub21pYyBwcm9zcGVyaXR5LiBIb3dldmVyIG1hbnkgb2YgdGhlc2UgbWluZXJhbHMgYXJlIHNvdXJjZWQgZnJvbSBvdXRzaWRlIG9mIHRoZSBVUy4gVGhpcyBhc3NpZ25tZW50IGlzIHRvIGRldmVsb3AgYSByZWZlcmVuY2UgY2F0YWxvZyBvZiB0aGUgc291cmNlIG9yIHNvdXJjZXMgb2YgZWFjaCBvZiB0aGVzZSBtaW5lcmFscyBhbmQgYSBqdWRnZW1lbnQgb24gdGhlIHJlbGlhYmlsaXR5IG9mIGVhY2ggc291cmNlIHVuZGVyIHN0cmVzc2VkIGNpcmN1bXN0YW5jZSAoZS5nLiB3YXIsIGVjb25vbWljIGNyaXNpcywgZXRjLikNCk5vdGVzOg0KDQpZb3Ugd2lsbCBuZWVkIHRvIGlkZW50aWZ5IGEgc291cmNlIG9yIHNvdXJjZXMgZm9yIGVhY2ggb2YgdGhlIG1pbmVyYWxzIGluIHRoZSAyMDIyIExpc3Qgb2YgQ3JpdGljYWwgTWluZXJhbHMNCg0KWW91IHdpbGwgbmVlZCB0byBjYXRlZ29yaXplIGVhY2ggc291cmNlIGNvdW50cnkgYXMgYW4gYWxseSwgYSBjb21wZXRpdG9yIG9yIGEgbmV1dHJhbCBwYXJ0eS4NCg0KWW91IHdpbGwgbmVlZCB0byBkZXZlbG9wIGRhdGEgdmlzdWFsaXphdGlvbnMgdGhhdCB0ZWxsIHRoZSBzdG9yeSBvZiBzb3VyY2UgZGVwZW5kZW5jeSBhbmQgc2hvcnRmYWxsIGltcGFjdC4NCg0KDQoNCiMjIERlbWFuZCBpbiB0aGUgVVMgZm9yIEtleSBtaW5lcmFscw0KDQpgYGB7cn0NCiNJbnN0YWxsaW5nIGFuZCBsb2FkaW5nIHRoZSByZWFkeGwgcGFja2FnZQ0KDQpsaWJyYXJ5KHJlYWR4bCkNCg0KI1NwZWNpZnlpbmcgdGhlIGZpbGUgcGF0aA0KZmlsZV9wYXRoIDwtICJDOi9Vc2Vycy9hbGVqYS9EZXNrdG9wL1RvdGFsIGRlbWFuZCBrZXkgbWluZXJhbHMueGxzeCINCg0KI1JlYWRpbmcgdGhlIEV4Y2VsIGZpbGUgaW50byBhIGRhdGFmcmFtZQ0KbWluZXJhbHNfZGF0YSA8LSByZWFkX2V4Y2VsKGZpbGVfcGF0aCkNCg0KI1ZpZXcgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YWZyYW1lDQpzdHIobWluZXJhbHNfZGF0YSkNCg0KI1ZpZXcgdGhlIGZpcnN0IGZldyByb3dzIG9mIHRoZSBkYXRhZnJhbWUNCmhlYWQobWluZXJhbHNfZGF0YSkNCg0KYGBgDQoNCmBgYHtyfQ0KI0NyZWF0aW5nIGRhdGFmcmFtZXMgZm9yIGVhY2ggbWluZXJhbA0KY29wcGVyX2RhdGEgPC0gZGF0YS5mcmFtZSgNCiAgTWluZXJhbCA9ICJDb3BwZXIiLA0KICBDYXRlZ29yeSA9IGMoIlNvbGFyIFBWIiwgIldpbmQiLCAiT3RoZXIgbG93IGVtaXNzaW9ucyBwb3dlciBnZW5lcmF0aW9uIiwgIkVsZWN0cmljIHZlaGljbGVzIiwgIkdyaWQgYmF0dGVyeSBzdG9yYWdlIiwgIkVsZWN0cmljaXR5IG5ldHdvcmtzIiwgIkh5ZHJvZ2VuIHRlY2hub2xvZ2llcyIsICJUb3RhbCBjbGVhbiB0ZWNobm9sb2dpZXMiLCAiT3RoZXIgdXNlcyIsICJUb3RhbCBkZW1hbmQiLCAiU2hhcmUgb2YgY2xlYW4gdGVjaG5vbG9naWVzIGluIHRvdGFsIGRlbWFuZCIpLA0KICBUb3RhbF9EZW1hbmQgPSBjKDY4MiwgMzk0LCA4NSwgMzczLCAyMCwgNDE4MiwgMCwgNTczNiwgTkEsIE5BLCAyMikNCikNCg0KY29iYWx0X2RhdGEgPC0gZGF0YS5mcmFtZSgNCiAgTWluZXJhbCA9ICJDb2JhbHQiLA0KICBDYXRlZ29yeSA9IGMoIkxvdyBlbWlzc2lvbnMgcG93ZXIgZ2VuZXJhdGlvbiIsICJFbGVjdHJpYyB2ZWhpY2xlcyIsICJHcmlkIGJhdHRlcnkgc3RvcmFnZSIsICJIeWRyb2dlbiB0ZWNobm9sb2dpZXMiLCAiVG90YWwgY2xlYW4gdGVjaG5vbG9naWVzIiwgIk90aGVyIHVzZXMiLCAiVG90YWwgZGVtYW5kIiwgIlNoYXJlIG9mIGNsZWFuIHRlY2hub2xvZ2llcyBpbiB0b3RhbCBkZW1hbmQiKSwNCiAgVG90YWxfRGVtYW5kID0gYygwLCA2NSwgNCwgMCwgNjgsIDEwMywgMTcxLCA0MCkNCikNCg0KbGl0aGl1bV9kYXRhIDwtIGRhdGEuZnJhbWUoDQogIE1pbmVyYWwgPSAiTGl0aGl1bSIsDQogIENhdGVnb3J5ID0gYygiRWxlY3RyaWMgdmVoaWNsZXMiLCAiR3JpZCBiYXR0ZXJ5IHN0b3JhZ2UiLCAiVG90YWwgY2xlYW4gdGVjaG5vbG9naWVzIiwgIk90aGVyIHVzZXMiLCAiVG90YWwgZGVtYW5kIiwgIlNoYXJlIG9mIGNsZWFuIHRlY2hub2xvZ2llcyBpbiB0b3RhbCBkZW1hbmQiKSwNCiAgVG90YWxfRGVtYW5kID0gYyg3MCwgMywgNzMsIDU3LCAxMzAsIDU2KQ0KKQ0KDQpuaWNrZWxfZGF0YSA8LSBkYXRhLmZyYW1lKA0KICBNaW5lcmFsID0gIk5pY2tlbCIsDQogIENhdGVnb3J5ID0gYygiU29sYXIgUFYiLCAiV2luZCIsICJPdGhlciBsb3cgZW1pc3Npb25zIHBvd2VyIGdlbmVyYXRpb24iLCAiRWxlY3RyaWMgdmVoaWNsZXMiLCAiR3JpZCBiYXR0ZXJ5IHN0b3JhZ2UiLCAiSHlkcm9nZW4gdGVjaG5vbG9naWVzIiwgIlRvdGFsIGNsZWFuIHRlY2hub2xvZ2llcyIsICJPdGhlciB1c2VzIiwgIlRvdGFsIGRlbWFuZCIsICJTaGFyZSBvZiBjbGVhbiB0ZWNobm9sb2dpZXMgaW4gdG90YWwgZGVtYW5kIiksDQogIFRvdGFsX0RlbWFuZCA9IGMoMCwgMzcsIDgzLCAzMjYsIDksIDIsIDQ1NywgMjQ3NywgMjkzNCwgMTYpDQopDQoNCm5lb2R5bWl1bV9kYXRhIDwtIGRhdGEuZnJhbWUoDQogIE1pbmVyYWwgPSAiTmVvZHltaXVtIiwNCiAgQ2F0ZWdvcnkgPSBjKCJXaW5kIiwgIkVsZWN0cmljIHZlaGljbGVzIiwgIlRvdGFsIGNsZWFuIHRlY2hub2xvZ2llcyIsICJPdGhlciB1c2VzIiwgIlRvdGFsIGRlbWFuZCIsICJTaGFyZSBvZiBjbGVhbiB0ZWNobm9sb2dpZXMgaW4gdG90YWwgZGVtYW5kIiksDQogIFRvdGFsX0RlbWFuZCA9IGMoNiwgNCwgMTAsIDQwLCA1MCwgMjApDQopDQoNCiMgQ29tYmluZSBkYXRhZnJhbWVzIGludG8gYSBzaW5nbGUgZGF0YWZyYW1lDQptaW5lcmFsX2RhdGEgPC0gcmJpbmQoY29wcGVyX2RhdGEsIGNvYmFsdF9kYXRhLCBsaXRoaXVtX2RhdGEsIG5pY2tlbF9kYXRhLCBuZW9keW1pdW1fZGF0YSkNCg0KIyBQcmludCB0aGUgZGF0YWZyYW1lDQpwcmludChtaW5lcmFsX2RhdGEpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KI0V4dHJhY3RpbmcgdGhlIGZpcnN0IHR3byBjb2x1bW5zIChNaW5lcmFsIGFuZCBDYXRlZ29yeSkgZnJvbSB0aGUgY29tYmluZWQgZGF0YWZyYW1lDQptaW5lcmFsX2NhdGVnb3J5IDwtIG1pbmVyYWxfZGF0YVssIGMoIk1pbmVyYWwiLCAiQ2F0ZWdvcnkiKV0NCg0KI1ByaW50aW5nIHRoZSBleHRyYWN0ZWQgZGF0YWZyYW1lDQpwcmludChtaW5lcmFsX2NhdGVnb3J5KQ0KDQoNCmBgYA0KDQpgYGB7cn0NCiNMb2FkaW5nIHRoZSByZXF1aXJlZCBwYWNrYWdlcw0KbGlicmFyeShrYWJsZUV4dHJhKQ0KDQojQ3JlYXRpbmcgYSB0YWJsZSB3aXRoIHRoZSBNaW5lcmFsLCBDYXRlZ29yeSwgYW5kIFRvdGFsIERlbWFuZCBjb2x1bW5zDQp0YWJsZSA8LSBtaW5lcmFsX2RhdGFbLCBjKCJNaW5lcmFsIiwgIkNhdGVnb3J5IiwgIlRvdGFsX0RlbWFuZCIpXQ0KDQojRGlzcGxheWluZyB0aGUgdGFibGUgd2l0aCBrYWJsZQ0Ka2FibGUodGFibGUsIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJNaW5lcmFsIENhdGVnb3J5IFRhYmxlIikgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFKQ0KDQoNCmBgYA0KDQoNCmBgYHtyfQ0KI0xvYWRpbmcgdGhlIHJlcXVpcmVkIHBhY2thZ2VzDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQoNCiNSZW1vdmluZyByb3dzIHdpdGggTkEgdmFsdWVzDQptaW5lcmFsX2RhdGFfY2xlYW4gPC0gbWluZXJhbF9kYXRhW2NvbXBsZXRlLmNhc2VzKG1pbmVyYWxfZGF0YSksIF0NCg0KI0NyZWF0aW5nIGEgdGFibGUgd2l0aCB0aGUgTWluZXJhbCwgQ2F0ZWdvcnksIGFuZCBUb3RhbCBEZW1hbmQgY29sdW1ucw0KdGFibGUgPC0gbWluZXJhbF9kYXRhX2NsZWFuWywgYygiTWluZXJhbCIsICJDYXRlZ29yeSIsICJUb3RhbF9EZW1hbmQiKV0NCg0KI0Rpc3BsYXlpbmcgdGhlIHRhYmxlIHdpdGgga2FibGUNCmthYmxlKHRhYmxlLCBmb3JtYXQgPSAiaHRtbCIsIGNhcHRpb24gPSAiTWluZXJhbCBDYXRlZ29yeSBUYWJsZSIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSkNCg0KYGBgDQoNCiMjIyBUb3RhbCBkZW1hbmQgbWluZXJhbHMgMjAyMiBpbiBVUw0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikgDQojQWdncmVnYXRlIHRvdGFsIGRlbWFuZCBmb3IgZWFjaCBtaW5lcmFsDQp0b3RhbF9kZW1hbmQgPC0gYWdncmVnYXRlKFRvdGFsX0RlbWFuZCB+IE1pbmVyYWwsIGRhdGEgPSBtaW5lcmFsX2RhdGFfY2xlYW4sIHN1bSkNCg0KI0NyZWF0aW5nIGEgYmFyIGNoYXJ0DQpnZ3Bsb3QodG90YWxfZGVtYW5kLCBhZXMoeCA9IE1pbmVyYWwsIHkgPSBUb3RhbF9EZW1hbmQsIGZpbGwgPSBNaW5lcmFsKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBsYWJzKHRpdGxlID0gIlRvdGFsIERlbWFuZCBvZiBFYWNoIE1pbmVyYWwgMjAyMiIsDQogICAgICAgeCA9ICJNaW5lcmFsIiwNCiAgICAgICB5ID0gIlRvdGFsIERlbWFuZCIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KYGBgDQoNClVzYWdlIGluIENsZWFuIFRlY2hub2xvZ2llczogVGhlIGRhdGEgaGlnaGxpZ2h0cyB0aGUgc2lnbmlmaWNhbnQgZGVtYW5kIGZvciBtaW5lcmFscyBsaWtlIGNvcHBlciwgY29iYWx0LCBsaXRoaXVtLCBuaWNrZWwsIGFuZCBuZW9keW1pdW0gaW4gY2xlYW4gdGVjaG5vbG9naWVzIHN1Y2ggYXMgc29sYXIgUFYsIHdpbmQgcG93ZXIsIGVsZWN0cmljIHZlaGljbGVzLCBhbmQgZ3JpZCBiYXR0ZXJ5IHN0b3JhZ2UuIFRoaXMgaW5kaWNhdGVzIHRoZSBpbXBvcnRhbmNlIG9mIHRoZXNlIG1pbmVyYWxzIGluIHN1cHBvcnRpbmcgdGhlIHRyYW5zaXRpb24gdG93YXJkcyByZW5ld2FibGUgZW5lcmd5IGFuZCBsb3ctZW1pc3Npb24gdGVjaG5vbG9naWVzLg0KDQpEaXZlcnNlIEFwcGxpY2F0aW9uczogRWFjaCBtaW5lcmFsIHNlcnZlcyBtdWx0aXBsZSBhcHBsaWNhdGlvbnMgYmV5b25kIGNsZWFuIHRlY2hub2xvZ2llcy4gRm9yIGV4YW1wbGUsIGNvcHBlciBpcyBhbHNvIHVzZWQgaW4gZWxlY3RyaWNpdHkgbmV0d29ya3MsIHdoaWxlIG5pY2tlbCBmaW5kcyBhcHBsaWNhdGlvbnMgaW4gb3RoZXIgbG93IGVtaXNzaW9ucyBwb3dlciBnZW5lcmF0aW9uIG1ldGhvZHMuIFVuZGVyc3RhbmRpbmcgdGhlIGRpdmVyc2UgYXBwbGljYXRpb25zIG9mIHRoZXNlIG1pbmVyYWxzIGhlbHBzIGFzc2VzcyB0aGVpciBvdmVyYWxsIGltcG9ydGFuY2UgaW4gdmFyaW91cyBpbmR1c3RyaWVzLg0KDQpTdHJhdGVnaWMgSW1wb3J0YW5jZSBvZiBDbGVhbiBUZWNobm9sb2dpZXM6IFRoZSBzaGFyZSBvZiBjbGVhbiB0ZWNobm9sb2dpZXMgaW4gdG90YWwgZGVtYW5kIGZvciBlYWNoIG1pbmVyYWwgcHJvdmlkZXMgaW5zaWdodHMgaW50byB0aGUgc3RyYXRlZ2ljIGltcG9ydGFuY2Ugb2YgdGhlc2UgbWluZXJhbHMgaW4gZHJpdmluZyB0aGUgY2xlYW4gZW5lcmd5IHRyYW5zaXRpb24uIE1pbmVyYWxzIGxpa2UgY29iYWx0IGFuZCBsaXRoaXVtLCB3aGljaCBoYXZlIGEgaGlnaGVyIHNoYXJlIG9mIGRlbWFuZCBmcm9tIGNsZWFuIHRlY2hub2xvZ2llcywgYXJlIGNydWNpYWwgZm9yIGFjY2VsZXJhdGluZyB0aGUgYWRvcHRpb24gb2YgZWxlY3RyaWMgdmVoaWNsZXMgYW5kIGVuZXJneSBzdG9yYWdlIHNvbHV0aW9ucy4NCg0KU3VwcGx5IENoYWluIFJpc2tzOiBUaGUgY29uY2VudHJhdGlvbiBvZiBkZW1hbmQgZm9yIGNlcnRhaW4gbWluZXJhbHMgaW4gc3BlY2lmaWMgYXBwbGljYXRpb25zLCBzdWNoIGFzIGVsZWN0cmljIHZlaGljbGVzIGFuZCBncmlkIGJhdHRlcnkgc3RvcmFnZSwgaGlnaGxpZ2h0cyBwb3RlbnRpYWwgc3VwcGx5IGNoYWluIHJpc2tzLiBEZXBlbmRlbmN5IG9uIGEgbGltaXRlZCBudW1iZXIgb2YgYXBwbGljYXRpb25zIG9yIGluZHVzdHJpZXMgY2FuIG1ha2UgdGhlIHN1cHBseSBjaGFpbiB2dWxuZXJhYmxlIHRvIGRpc3J1cHRpb25zLCBlbXBoYXNpemluZyB0aGUgbmVlZCBmb3IgZGl2ZXJzaWZpY2F0aW9uIGFuZCByZXNpbGllbmNlIHN0cmF0ZWdpZXMuDQoNClBvbGljeSBJbXBsaWNhdGlvbnM6IFBvbGljeW1ha2VycyBjYW4gdXNlIHRoaXMgZGF0YSB0byBmb3JtdWxhdGUgcG9saWNpZXMgdGhhdCBwcm9tb3RlIHN1c3RhaW5hYmxlIHNvdXJjaW5nLCByZWN5Y2xpbmcsIGFuZCBkb21lc3RpYyBwcm9kdWN0aW9uIG9mIHRoZXNlIGNyaXRpY2FsIG1pbmVyYWxzLiBFbnN1cmluZyBhIHN0YWJsZSBhbmQgZGl2ZXJzaWZpZWQgc3VwcGx5IG9mIHRoZXNlIG1pbmVyYWxzIGlzIGVzc2VudGlhbCBmb3IgYWNoaWV2aW5nIGxvbmctdGVybSBlbmVyZ3kgc2VjdXJpdHkgYW5kIGVudmlyb25tZW50YWwgc3VzdGFpbmFiaWxpdHkgZ29hbHMuDQoNCg0KDQojIyBNaW5lcmFsIGltcG9ydHMgaW4gVVMNCg0KYGBge3J9DQojTG9hZGluZyB0aGUgZGF0YXNldA0Kd2l0c19wYXJ0bmVyIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9hbGVqYS9EZXNrdG9wL1dJVFMtUGFydG5lci5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQoNCiNEaXNwbGF5aW5nIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGFzZXQNCnN0cih3aXRzX3BhcnRuZXIpDQoNCiNEaXNwbGF5aW5nIHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgZGF0YXNldA0KaGVhZCh3aXRzX3BhcnRuZXIpDQoNCmBgYA0KDQojIyBUb3AgMTUgaW1wb3J0aW5nIGNvdW50cmllcw0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShzY2FsZXMpDQoNCiNBZ2dyZWdhdGluZyB0b3RhbCBpbXBvcnRzIGZyb20gZWFjaCBwYXJ0bmVyIGNvdW50cnkNCnRvcF9jb3VudHJpZXMgPC0gd2l0c19wYXJ0bmVyICU+JQ0KICBmaWx0ZXIoVHJhZGUuRmxvdyA9PSAiSW1wb3J0IikgJT4lDQogIGdyb3VwX2J5KFBhcnRuZXIuTmFtZSkgJT4lDQogIHN1bW1hcmlzZShUb3RhbF9JbXBvcnQgPSBzdW0oSW1wb3J0Li5VUy4uVGhvdXNhbmQuKSkNCg0KI1NvcnRpbmcgdGhlIHRvcCBjb3VudHJpZXMgYnkgdG90YWwgaW1wb3J0IHZhbHVlDQp0b3BfY291bnRyaWVzIDwtIHRvcF9jb3VudHJpZXMgJT4lDQogIGFycmFuZ2UoZGVzYyhUb3RhbF9JbXBvcnQpKSAlPiUNCiAgaGVhZCgxNSkgIyBTZWxlY3QgdGhlIHRvcCAxNSBjb3VudHJpZXMNCg0KI0NyZWF0aW5nIGEgaG9yaXpvbnRhbCBiYXIgY2hhcnQNCmdncGxvdCh0b3BfY291bnRyaWVzLCBhZXMoeCA9IHJlb3JkZXIoUGFydG5lci5OYW1lLCBUb3RhbF9JbXBvcnQpLCB5ID0gVG90YWxfSW1wb3J0KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJza3libHVlIikgKw0KICBsYWJzKHRpdGxlID0gIlRvcCAxNSBDb3VudHJpZXMgSW1wb3J0aW5nIHRvIHRoZSBVUyIsDQogICAgICAgeSA9ICJUb3RhbCBJbXBvcnQgKFVTJCBUaG91c2FuZCkiLA0KICAgICAgIHggPSAiUGFydG5lciBDb3VudHJ5IikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWEpICsgICMgRm9ybWF0IHktYXhpcyBsYWJlbHMgd2l0aCBjb21tYXMNCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAxKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsNCiAgY29vcmRfZmxpcCgpDQoNCg0KDQpgYGANCg0KIyMgVG90YWwgaW1wb3J0cw0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShtYXBzKQ0KDQojRmlsdGVyaW5nIHRoZSBkYXRhIGZvciBpbXBvcnQgZmxvd3MNCmltcG9ydF9kYXRhIDwtIHdpdHNfcGFydG5lciAlPiUNCiAgZmlsdGVyKFRyYWRlLkZsb3cgPT0gIkltcG9ydCIpDQoNCiNBZ2dyZWdhdGluZyB0b3RhbCBpbXBvcnRzIGZyb20gZWFjaCBwYXJ0bmVyIGNvdW50cnkNCmltcG9ydF9zdW0gPC0gaW1wb3J0X2RhdGEgJT4lDQogIGdyb3VwX2J5KFBhcnRuZXIuTmFtZSkgJT4lDQogIHN1bW1hcmlzZShUb3RhbF9JbXBvcnQgPSBzdW0oYEltcG9ydC4uVVMuLlRob3VzYW5kLmApKQ0KDQojTG9hZGluZyB3b3JsZCBtYXAgZGF0YQ0Kd29ybGRfbWFwIDwtIG1hcF9kYXRhKCJ3b3JsZCIpDQoNCiNNZXJnaW5nIGltcG9ydCBkYXRhIHdpdGggd29ybGQgbWFwIGRhdGENCmltcG9ydF9tYXAgPC0gbWVyZ2Uod29ybGRfbWFwLCBpbXBvcnRfc3VtLCBieS54ID0gInJlZ2lvbiIsIGJ5LnkgPSAiUGFydG5lci5OYW1lIiwgYWxsLnggPSBUUlVFKQ0KDQojQ3JlYXRpbmcgYSBtYXAgcGxvdA0KZ2dwbG90KGltcG9ydF9tYXAsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IFRvdGFsX0ltcG9ydCkpICsNCiAgZ2VvbV9wb2x5Z29uKGNvbG9yID0gInRyYW5zcGFyZW50Iiwgc2l6ZSA9IDAuMikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJsaWdodGJsdWUiLCBoaWdoID0gImRhcmtibHVlIiwgbmEudmFsdWUgPSAiZ3JleSIsIG5hbWUgPSAiVG90YWwgSW1wb3J0IChVUyQgVGhvdXNhbmQpIikgKw0KICBsYWJzKHRpdGxlID0gIkltcG9ydCBWYWx1ZXMgZnJvbSBDb3VudHJpZXMgUGFydG5lcmluZyB3aXRoIHRoZSBVUyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgY29vcmRfZml4ZWQoKQ0KDQpgYGANCg0KDQpgYGB7cn0NCiNEZWZpbmluZyB0aGUgYWxsaWFuY2UgbWFwcGluZw0KI0FkZGluZyBCcmF6aWwgYXMgYSBjb21wZXRpdG9yDQphbGxpYW5jZV9tYXBwaW5nIDwtIGxpc3QoDQogICAgJ0NoaWxlJyA9ICJOZXV0cmFsIiwNCiAgICAnU291dGggQWZyaWNhJyA9ICJBbGx5IiwNCiAgICAnRmlubGFuZCcgPSAiQWxseSIsIA0KICAgICdNZXhpY28nID0gIk5ldXRyYWwiLA0KICAgICdJbmRvbmVzaWEnID0gIkFsbHkiLCANCiAgICAnTm9yd2F5JyA9ICJBbGx5IiwgDQogICAgJ0NhbmFkYScgPSAiQWxseSIsDQogICAgJ1J1c3NpYScgPSAiU3RyYWluZWQgUmVsYXRpb25zIiwgDQogICAgJ0phcGFuJyA9ICJBbGx5IiwgDQogICAgJ1BoaWxpcHBpbmVzJyA9ICJOZXV0cmFsIiwNCiAgICAnUGVydScgPSAiTmV1dHJhbCIsIA0KICAgICdDdWJhJyA9ICJTdHJhaW5lZCBSZWxhdGlvbnMiLA0KICAgICdBdXN0cmFsaWEnID0gIkFsbHkiLCANCiAgICAnQnVybWEnID0gIk5ldXRyYWwiLCANCiAgICAnUG9ydHVnYWwnID0gIkFsbHkiLCANCiAgICAnU3dlZGVuJyA9ICJBbGx5IiwNCiAgICAnQ2hpbmEnID0gIlN0cmFpbmVkIFJlbGF0aW9ucyIsDQogICAgJ01hdXJpdGFuaWEnID0gIk5ldXRyYWwiLA0KICAgICdCcmF6aWwnID0gIlN0cmFpbmVkIFJlbGF0aW9ucyIsDQogICAgJ0FyZ2VudGluYScgPSAiTmV1dHJhbCIsIA0KICAgICdHZXJtYW55JyA9ICJBbGx5IiwNCiAgICAnTmFtaWJpYScgPSAiTmV1dHJhbCIsDQogICAgJ1phbWJpYScgPSAiTmV1dHJhbCIsDQogICAgJ0luZGlhJyA9ICJOZXV0cmFsIiwNCiAgICAnUG9sYW5kJyA9ICJBbGx5IiwNCiAgICAnRGVtb2NyYXRpYyBSZXB1YmxpYyBvZiBDb25nbycgPSAiTmV1dHJhbCIsDQogICAgJ1ZpZXRuYW0nID0gIk5ldXRyYWwiLA0KICAgICdQYXB1YSBOZXcgR3VpbmVhJyA9ICJOZXV0cmFsIiwNCiAgICAnSG9uZHVyYXMnID0gIk5ldXRyYWwiDQopDQoNCiNBZGRpbmcgdGhlICdzdGF0dXMnIGNvbHVtbiB0byB3aXRzX3BhcnRuZXIgZGF0YXNldA0Kd2l0c19wYXJ0bmVyJHN0YXR1cyA8LSB1bmxpc3QobGFwcGx5KHdpdHNfcGFydG5lciRQYXJ0bmVyLk5hbWUsIGZ1bmN0aW9uKGNvdW50cnkpIHsNCiAgaWYgKGNvdW50cnkgJWluJSBuYW1lcyhhbGxpYW5jZV9tYXBwaW5nKSkgew0KICAgIHJldHVybihhbGxpYW5jZV9tYXBwaW5nW1tjb3VudHJ5XV0pDQogIH0gZWxzZSB7DQogICAgcmV0dXJuKCJOZXV0cmFsIikNCiAgfQ0KfSkpDQoNCiNDaGVja2luZyB0aGUgZmlyc3QgZmV3IHJvd3Mgb2YgdGhlIHVwZGF0ZWQgZGF0YXNldA0KaGVhZCh3aXRzX3BhcnRuZXIpDQoNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobWFwcykNCg0KI0xvYWRpbmcgd29ybGQgbWFwIGRhdGENCndvcmxkX21hcCA8LSBtYXBfZGF0YSgid29ybGQiKQ0KDQojTWVyZ2luZyB3b3JsZCBtYXAgZGF0YSB3aXRoIHdpdHNfcGFydG5lciBkYXRhc2V0DQptYXBfZGF0YSA8LSBtZXJnZSh3b3JsZF9tYXAsIHdpdHNfcGFydG5lciwgYnkueCA9ICJyZWdpb24iLCBieS55ID0gIlBhcnRuZXIuTmFtZSIsIGFsbC54ID0gVFJVRSkNCg0KI0NyZWF0aW5nIGEgbWFwIHBsb3Qgd2l0aCBjb2xvci1jb2RlZCBhbGxpYW5jZSBzdGF0dXMNCmdncGxvdChtYXBfZGF0YSwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gc3RhdHVzKSkgKw0KICBnZW9tX3BvbHlnb24oY29sb3IgPSAidHJhbnNwYXJlbnQiLCBzaXplID0gMC4yKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkFsbHkiID0gImJsdWUiLCAiQ29tcGV0aXRvciIgPSAicmVkIiwgIk5ldXRyYWwiID0gImdyZWVuIiksDQogICAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gImdyZXkiLCBuYW1lID0gIlN0YXR1cyIsDQogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkFsbHkiLCAiQ29tcGV0aXRvciIsICJOZXV0cmFsIikpICsNCiAgbGFicyh0aXRsZSA9ICJBbGxpYW5jZSBTdGF0dXMgb2YgQ291bnRyaWVzIiwNCiAgICAgICBmaWxsID0gIlN0YXR1cyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgY29vcmRfZml4ZWQoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSAgIyBNb3ZlIGxlZ2VuZCB0byB0aGUgYm90dG9tIG9mIHRoZSBwbG90DQoNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobWFwcykNCg0KI0xvYWRpbmcgd29ybGQgbWFwIGRhdGENCndvcmxkX21hcCA8LSBtYXBfZGF0YSgid29ybGQiKQ0KDQojTWVyZ2luZyB3b3JsZCBtYXAgZGF0YSB3aXRoIHdpdHNfcGFydG5lciBkYXRhc2V0DQptYXBfZGF0YSA8LSBtZXJnZSh3b3JsZF9tYXAsIHdpdHNfcGFydG5lciwgYnkueCA9ICJyZWdpb24iLCBieS55ID0gIlBhcnRuZXIuTmFtZSIsIGFsbC54ID0gVFJVRSkNCg0KI0NyZWF0aW5nIGEgbWFwIHBsb3Qgd2l0aCBjb2xvci1jb2RlZCBhbGxpYW5jZSBzdGF0dXMNCmdncGxvdChtYXBfZGF0YSwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gc3RhdHVzKSkgKw0KICBnZW9tX3BvbHlnb24oY29sb3IgPSAidHJhbnNwYXJlbnQiLCBzaXplID0gMC4yKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkFsbHkiID0gImJsdWUiLCAiU3RyYWluZWQgUmVsYXRpb25zIiA9ICJyZWQiLCAiTmV1dHJhbCIgPSAiZ3JlZW4iKSwNCiAgICAgICAgICAgICAgICAgICAgbmEudmFsdWUgPSAiZ3JleSIsIG5hbWUgPSAiU3RhdHVzIiwNCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQWxseSIsICJDb21wZXRpdG9ycyIsICJOZXV0cmFsIikpICsNCiAgbGFicyh0aXRsZSA9ICJBbGxpYW5jZSBTdGF0dXMgb2YgQ291bnRyaWVzIiwNCiAgICAgICBmaWxsID0gIlN0YXR1cyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgY29vcmRfZml4ZWQoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSAgIyBNb3ZlIGxlZ2VuZCB0byB0aGUgYm90dG9tIG9mIHRoZSBwbG90DQpgYGANCg0KDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojRmlsdGVyaW5nIHRoZSBkYXRhIGJ5IHN0YXR1cyBhbmQgYWdncmVnYXRlIHRvdGFsIGltcG9ydHMNCnN0YXR1c19pbXBvcnRzIDwtIHdpdHNfcGFydG5lciAlPiUNCiAgZ3JvdXBfYnkoc3RhdHVzLCBQYXJ0bmVyLk5hbWUpICU+JQ0KICBzdW1tYXJpc2UoVG90YWxfSW1wb3J0ID0gc3VtKGBJbXBvcnQuLlVTLi5UaG91c2FuZC5gKSkgJT4lDQogIGFycmFuZ2UoZGVzYyhUb3RhbF9JbXBvcnQpKSAlPiUNCiAgZ3JvdXBfYnkoc3RhdHVzKSAlPiUNCiAgdG9wX24oMTApDQoNCiNDcmVhdGluZyBzZXBhcmF0ZSBwbG90cyBmb3IgZWFjaCBzdGF0dXMNCmFsbHlfcGxvdCA8LSBnZ3Bsb3QoZmlsdGVyKHN0YXR1c19pbXBvcnRzLCBzdGF0dXMgPT0gIkFsbHkiKSwgYWVzKHggPSByZW9yZGVyKFBhcnRuZXIuTmFtZSwgVG90YWxfSW1wb3J0KSwgeSA9IFRvdGFsX0ltcG9ydCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiYmx1ZSIpICsNCiAgbGFicyh0aXRsZSA9ICJUb3AgNSBBbGx5IENvdW50cmllcyBJbXBvcnRpbmcgdG8gdGhlIFVTIiwNCiAgICAgICB5ID0gIlRvdGFsIEltcG9ydCAoVVMkIFRob3VzYW5kKSIsDQogICAgICAgeCA9ICJQYXJ0bmVyIENvdW50cnkiKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQoNCmNvbXBldGl0b3JfcGxvdCA8LSBnZ3Bsb3QoZmlsdGVyKHN0YXR1c19pbXBvcnRzLCBzdGF0dXMgPT0gIlN0cmFpbmVkIFJlbGF0aW9ucyIpLCBhZXMoeCA9IHJlb3JkZXIoUGFydG5lci5OYW1lLCBUb3RhbF9JbXBvcnQpLCB5ID0gVG90YWxfSW1wb3J0KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJyZWQiKSArDQogIGxhYnModGl0bGUgPSAiVG9wIDUgQ29tcGV0aXRvciBDb3VudHJpZXMgSW1wb3J0aW5nIHRvIHRoZSBVUyIsDQogICAgICAgeSA9ICJUb3RhbCBJbXBvcnQgKFVTJCBUaG91c2FuZCkiLA0KICAgICAgIHggPSAiUGFydG5lciBDb3VudHJ5IikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KDQpuZXV0cmFsX3Bsb3QgPC0gZ2dwbG90KGZpbHRlcihzdGF0dXNfaW1wb3J0cywgc3RhdHVzID09ICJOZXV0cmFsIiksIGFlcyh4ID0gcmVvcmRlcihQYXJ0bmVyLk5hbWUsIFRvdGFsX0ltcG9ydCksIHkgPSBUb3RhbF9JbXBvcnQpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gImdyZWVuIikgKw0KICBsYWJzKHRpdGxlID0gIlRvcCA1IE5ldXRyYWwgQ291bnRyaWVzIEltcG9ydGluZyB0byB0aGUgVVMiLA0KICAgICAgIHkgPSAiVG90YWwgSW1wb3J0IChVUyQgVGhvdXNhbmQpIiwNCiAgICAgICB4ID0gIlBhcnRuZXIgQ291bnRyeSIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KI0Rpc3BsYXlpbmcgdGhlIHBsb3RzDQphbGx5X3Bsb3QNCmNvbXBldGl0b3JfcGxvdA0KbmV1dHJhbF9wbG90DQoNCg0KYGBgDQoNCg0KDQoNCg0KIyMgQ29uY2x1c2lvbnMNCg0KSW4gY29uY2x1c2lvbiwgdGhlIGFuYWx5c2lzIG9mIG1pbmVyYWwgZGVtYW5kIGFuZCBpbXBvcnQgZGF0YSBwcm92aWRlcyB2YWx1YWJsZSBpbnNpZ2h0cyBpbnRvIHRoZSBzdHJhdGVnaWMgaW1wb3J0YW5jZSBvZiBjcml0aWNhbCBtaW5lcmFscyBmb3IgdGhlIFVuaXRlZCBTdGF0ZXMuIEtleSBmaW5kaW5nczoNCg0KSW1wb3J0YW5jZSBvZiBDcml0aWNhbCBNaW5lcmFsczogVGhlIFVTIEdlb2xvZ2ljYWwgU3VydmV5IGlkZW50aWZpZXMgY2VydGFpbiBtaW5lcmFscyBhcyBjcml0aWNhbCBkdWUgdG8gdGhlaXIgZXNzZW50aWFsIHJvbGUgaW4gbmF0aW9uYWwgc2VjdXJpdHkgYW5kIGVjb25vbWljIHByb3NwZXJpdHkuIFRoZXNlIG1pbmVyYWxzIGFyZSBjcnVjaWFsIGZvciB2YXJpb3VzIGluZHVzdHJpZXMsIGluY2x1ZGluZyBjbGVhbiBlbmVyZ3kgdGVjaG5vbG9naWVzIGxpa2Ugc29sYXIgUFYsIHdpbmQgcG93ZXIsIGVsZWN0cmljIHZlaGljbGVzLCBhbmQgZ3JpZCBiYXR0ZXJ5IHN0b3JhZ2UuDQoNCkRlcGVuZGVuY3kgb24gRm9yZWlnbiBTb3VyY2VzOiBEZXNwaXRlIHRoZWlyIGltcG9ydGFuY2UsIG1hbnkgY3JpdGljYWwgbWluZXJhbHMgYXJlIHNvdXJjZWQgZnJvbSBvdXRzaWRlIHRoZSBVUy4gVGhpcyBkZXBlbmRlbmN5IHJhaXNlcyBjb25jZXJucyBhYm91dCBzdXBwbHkgY2hhaW4gdnVsbmVyYWJpbGl0aWVzLCBlc3BlY2lhbGx5IGR1cmluZyB0aW1lcyBvZiBnZW9wb2xpdGljYWwgdGVuc2lvbiwgZWNvbm9taWMgY3Jpc2VzLCBvciB0cmFkZSBkaXNydXB0aW9ucy4NCg0KQ2F0ZWdvcml6YXRpb24gb2YgU291cmNlIENvdW50cmllczogQXMgcGFydCBvZiB0aGUgYXNzaWdubWVudCwgZWFjaCBzb3VyY2UgY291bnRyeSBmb3IgY3JpdGljYWwgbWluZXJhbHMgbmVlZHMgdG8gYmUgY2F0ZWdvcml6ZWQgYXMgYW4gYWxseSwgY29tcGV0aXRvciwgb3IgbmV1dHJhbCBwYXJ0eS4gVW5kZXJzdGFuZGluZyB0aGUgZ2VvcG9saXRpY2FsIGR5bmFtaWNzIG9mIG1pbmVyYWwgc291cmNpbmcgaXMgZXNzZW50aWFsIGZvciBhc3Nlc3NpbmcgcmVsaWFiaWxpdHkgdW5kZXIgc3RyZXNzZWQgY2lyY3Vtc3RhbmNlcy4NCg0KDQoNCiMjIFJlZmVyZW5jZXMNCg0KTWluZXJhbCBDb21tb2RpdHkgU3VtbWFyaWVzIDIwMjM6DQpodHRwczovL3B1YnMudXNncy5nb3YvcHVibGljYXRpb24vbWNzMjAyMw0KDQoNCg0KDQoNCg0KDQo=