This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Cmd+Shift+Enter.

Accidents in the year 2017

Ask:

Define the problem or question you want to answer with the data. Gather information about the context and existing knowledge related to the problem. Formulate specific, measurable, achievable, relevant, and time-bound (SMART) questions for analysis.

Objective:

Traffic accidents remain a persistent threat on American roads. In 2020, an estimated 38824 people lost their lives in motor vehicle crashes, and millions more were injured. This analysis seeks to understand the underlying causes of these incidents to develop effective preventative measures. By examining traffic accident data, we aim to identify contributing factors and patterns, ultimately reducing the devastating impact of these tragedies.

Which states have the 10 most fatalities?

Top 10 states for the year 2017?

Top 10 states for the year 2017 per population?

Which times of days (which hour) are their more occurances?

#install packages
install.packages('ggplot2')
Error in install.packages : Updating loaded packages
install.packages('tidyr')
Installing package into ‘/Users/charles/Library/R/arm64/4.4/library’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.4/tidyr_1.3.1.tgz'
Content type 'application/x-gzip' length 1324134 bytes (1.3 MB)
==================================================
downloaded 1.3 MB

The downloaded binary packages are in
    /var/folders/nk/f2nsf9xx7xj3sy9f7qtz_d6m0000gp/T//RtmpFw8yuq/downloaded_packages
install.packages('purrr')
Error in install.packages : Updating loaded packages
install.packages('dplyr')
Error in install.packages : Updating loaded packages
install.packages('tidyverse')
Error in install.packages : Updating loaded packages
install.packages('shiny')
Error in install.packages : Updating loaded packages
install.packages('psych')
Installing package into ‘/Users/charles/Library/R/arm64/4.4/library’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.4/psych_2.4.6.26.tgz'
Content type 'application/x-gzip' length 3734319 bytes (3.6 MB)
==================================================
downloaded 3.6 MB

The downloaded binary packages are in
    /var/folders/nk/f2nsf9xx7xj3sy9f7qtz_d6m0000gp/T//RtmpFw8yuq/downloaded_packages
# getting packages to show on a map
install.packages('maps')
Installing package into ‘/Users/charles/Library/R/arm64/4.4/library’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.4/maps_3.4.2.1.tgz'
Content type 'application/x-gzip' length 3113848 bytes (3.0 MB)
==================================================
downloaded 3.0 MB

The downloaded binary packages are in
    /var/folders/nk/f2nsf9xx7xj3sy9f7qtz_d6m0000gp/T//RtmpFw8yuq/downloaded_packages
install.packages('readr')
Installing package into ‘/Users/charles/Library/R/arm64/4.4/library’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.4/readr_2.1.5.tgz'
Content type 'application/x-gzip' length 1970418 bytes (1.9 MB)
==================================================
downloaded 1.9 MB

The downloaded binary packages are in
    /var/folders/nk/f2nsf9xx7xj3sy9f7qtz_d6m0000gp/T//RtmpFw8yuq/downloaded_packages

Loading in required packages

library(tidyverse)
── Attaching core tidyverse packages ────────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     ── Conflicts ──────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
install.packages("purrr")
Installing package into ‘/Users/charles/Library/R/arm64/4.4/library’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.4/purrr_1.0.2.tgz'
Content type 'application/x-gzip' length 524757 bytes (512 KB)
==================================================
downloaded 512 KB

The downloaded binary packages are in
    /var/folders/nk/f2nsf9xx7xj3sy9f7qtz_d6m0000gp/T//RtmpFw8yuq/downloaded_packages
install.packages("dplyr")
Installing package into ‘/Users/charles/Library/R/arm64/4.4/library’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.4/dplyr_1.1.4.tgz'
Content type 'application/x-gzip' length 1599250 bytes (1.5 MB)
==================================================
downloaded 1.5 MB

The downloaded binary packages are in
    /var/folders/nk/f2nsf9xx7xj3sy9f7qtz_d6m0000gp/T//RtmpFw8yuq/downloaded_packages
install.packages("tidyverse")
Error in install.packages : Updating loaded packages
install.packages("shiny")
Error in install.packages : Updating loaded packages
install.packages("ggplot2")
Error in install.packages : Updating loaded packages
library(tidyr)
library(purrr)
library(dplyr)
library(ggplot2)
library(psych)

Attaching package: ‘psych’

The following objects are masked from ‘package:ggplot2’:

    %+%, alpha
library(readr)
# 'https://www.dropbox.com/scl/fi/galo8nwup3jwwbdwb37t1/accidents.csv?rlkey=9iya5poo86931spy7h0ipm833&dl=0'
accidents <- read.csv('https://www.dropbox.com/scl/fi/galo8nwup3jwwbdwb37t1/accidents.csv?rlkey=9iya5poo86931spy7h0ipm833&dl=0')
function (pkgs, lib, repos = getOption("repos"), contriburl = contrib.url(repos, 
  type), method, available = NULL, destdir = NULL, dependencies = NA, 
  type = getOption("pkgType"), configure.args = getOption("configure.args"), 
  configure.vars = getOption("configure.vars"), clean = FALSE, 
  Ncpus = getOption("Ncpus", 1L), verbose = getOption("verbose"), 
  libs_only = FALSE, INSTALL_opts, quiet = FALSE, keep_outputs = FALSE, 
  ...) 
# 'https://www.dropbox.com/scl/fi/galo8nwup3jwwbdwb37t1/accidents.csv?rlkey=9iya5poo86931spy7h0ipm833&dl=0'
accidents <- read.csv('https://www.dropbox.com/scl/fi/galo8nwup3jwwbdwb37t1/accidents.csv?rlkey=9iya5poo86931spy7h0ipm833&dl=0')
# Identify the latest year
latest_year <- max(accidents$YEAR)

# Print the latest year
print(latest_year)
[1] 2018
print(summary(accidents))
     L_YEAR        STATE              COUNTY              CITY                DAY           MONTH                YEAR        WEEK_DAY        
 Min.   :1990   Length:1027008     Length:1027008     Length:1027008     Min.   : 1.00   Length:1027008     Min.   :1990   Length:1027008    
 1st Qu.:1997   Class :character   Class :character   Class :character   1st Qu.: 8.00   Class :character   1st Qu.:1997   Class :character  
 Median :2003   Mode  :character   Mode  :character   Mode  :character   Median :16.00   Mode  :character   Median :2003   Mode  :character  
 Mean   :2004                                                            Mean   :15.65                      Mean   :2004                     
 3rd Qu.:2010                                                            3rd Qu.:23.00                      3rd Qu.:2010                     
 Max.   :2018                                                            Max.   :31.00                      Max.   :2018                     
                                                                                                                                             
      HOUR           MINUTE       RUR_URB            FUNC_SYS            LATITUDE           LONGITUD           WRK_ZONE        
 Min.   : 0.00   Min.   : 0.0   Length:1027008     Length:1027008     Min.   :      18   Min.   :    -1001   Length:1027008    
 1st Qu.: 7.00   1st Qu.:13.0   Class :character   Class :character   1st Qu.:      34   1st Qu.:      -97   Class :character  
 Median :14.00   Median :29.0   Mode  :character   Mode  :character   Median :      38   Median :      -86   Mode  :character  
 Mean   :12.64   Mean   :27.9                                         Mean   :10296065   Mean   :102803615                     
 3rd Qu.:19.00   3rd Qu.:44.0                                         3rd Qu.:      42   3rd Qu.:      -78                     
 Max.   :24.00   Max.   :59.0                                         Max.   :99999999   Max.   :999999999                     
                                                                      NA's   :350102     NA's   :350096                        
   WEATHER1           WEATHER2           WEATHER            SCH_BUS              FATALS      
 Length:1027008     Length:1027008     Length:1027008     Length:1027008     Min.   : 1.000  
 Class :character   Class :character   Class :character   Class :character   1st Qu.: 1.000  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character   Median : 1.000  
                                                                             Mean   : 1.108  
                                                                             3rd Qu.: 1.000  
                                                                             Max.   :23.000  
                                                                                             

Lets use the psych package to get a more comprehensive descriptive statistics with the describe funtion:

describe(accidents)
colSums(is.na(accidents))

Check for any outliers.

# Create list for boxplots
# na.rm = TRUE: ensure that the summary statistics are not affected by the missing values
summary(accidents, na.rm = TRUE)

Prepare:

Collect or access the relevant data sources. Clean and pre-process the data to handle missing values, inconsistencies, and errors. Explore the data through descriptive statistics and visualizations to understand its distribution and characteristics.

# Select only numeric columns from the accidents DataFrame

outlierremoval <- function(accidents){
 accidents %>%
      # Select only numeric columns from the accidents DataFrame
      select_if(is.numeric) %>% 
      map(~ .x[!.x %in% boxplot.stats(.)$out]) 
 }

options(max.print = 200)
print(outlierremoval(accidents))
# options(max.print = 1000)
list_plots <- lapply(names(accidents), function(col) {
  # Increase plot area size
  ggplot(accidents, aes(x = .data[[col]], y = ..count..)) +
    geom_bar(aes(fill = .data[[col]]), position = "dodge") +
    # Center x-axis labels and adjust spacing
    theme(
      axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5),
      axis.ticks.x = element_line(linewidth = 0.5)  # Fix size issue
    ) +
    guides(
      legend = TRUE,
      legend.title = element_text(angle = 90),
      legend.text = element_text(angle = 90)
    ) +
    facet_grid(~ .)
})
# fix misspelling / spelling errors
print('FUNC_SYS')
print(unique(accidents$FUNC_SYS))
# fix spelling error
accidents$FUNC_SYS[accidents$FUNC_SYS == 'ncipal arterial, other'] <- 'Principal arterial, other'
# double check
print(unique(accidents$FUNC_SYS))
accidents <- accidents %>%
 filter(HOUR <= 24,
        MINUTE <= 59,
        DAY <= 31,
        YEAR >= 1990)
Now to double check for any visible outliers on the graphs:
lapply(names(accidents), function(col=group) {
  ggplot(accidents, aes(x = .data[[col]], y = ..count..)) + 
    geom_bar(aes(fill = .data[[col]]), position = "dodge") +
    # Display the legend with title and text slanted at 45 degrees
    guides(
      legend = TRUE,
      legend.title = element_text(angle = 45, size = 12),
      legend.text = element_text(angle = 45, size = 10)
    ) + 
      # Rotate the x-axis labels to 90 degrees and adjust horizontal alignment
      theme(axis.text.x = element_text(angle=90, hjust=3))
}) -> list_plots
print(list_plots)

Which states have the 10 most fatalities?

# Check for missing values
print(which(is.na(accidents$STATE)))
print(which(is.na(accidents$FATALS)))

# Calculate total fatalities per state
fatals_per_state <- aggregate(FATALS ~ STATE, data = accidents, sum)

# Sort by fatalities and select the top 10 states
fatals_per_state <- arrange(fatals_per_state, desc(FATALS))[1:10,]

# print results
print(fatals_per_state)

Moving on from the national perspective, let’s zoom in and examine the states with the highest number of accident fatalities in 2017.

Top 10 states with most accident fatals for the year 2017?

# Check for missing values
print(which(is.na(accidents$STATE)))
print(which(is.na(accidents$FATALS)))

# Filter data for the year 2017
accidents_2017 <- accidents[accidents$YEAR == 2017,]

# Calculate total fatalities per state for 2017
fatals_per_state_2017 <- aggregate(FATALS ~ STATE, data = accidents_2017, sum)

# Sort by fatalities and select the top 10 states
top_10_fatals_2017 <- arrange(fatals_per_state_2017, desc(FATALS))[1:10,]

# print results
print(top_10_fatals_2017)

To understand the impact of fatal accidents more comprehensively, we must consider population density. The following will rank the top 10 states with the highest fatal accident rates per capita in 2017.

Top 10 states for the year 2017 per population?

state_pop = read.csv('/Users/charles/Documents/50_states_pop.csv')

# Change the column titles to uppercase
colnames(state_pop) <- toupper(colnames(state_pop))

print(head(state_pop))

top_10_fatals_2017_per_state <- top_10_fatals_2017 %>%
  merge(state_pop, by = "STATE")

print(top_10_fatals_2017_per_state)

Calculating traffic accident fatalities per capita allows for fair comparisons between states with varying population sizes, providing a clearer picture of their relative risk on the road. To facilitate this analysis, we will express fatalities per million population for each state.

# Create a new column named "fatality_rate" by dividing FATALS by POPULATION
top_10_fatals_2017_per_state$fatality_rate_per_million <- top_10_fatals_2017_per_state$FATALS / top_10_fatals_2017_per_state$POPULATION * 1000000
top_10_fatals_2017_per_state <- arrange(top_10_fatals_2017_per_state, desc(fatality_rate_per_million))
print(top_10_fatals_2017_per_state)
library(ggplot2)
library(maps)
library(dplyr)


# Load US state data
all_states <- map_data("state")

# Assuming you have "top_10_fatals_2017_per_state" data with state and fatality rate

# Join data with map data (modify based on your data structure)
merged_data <- inner_join(
  transform(all_states, region = tolower(region)),
  transform(top_10_fatals_2017_per_state, STATE = tolower(STATE)),
  by = c("region" = "STATE")
)

# Fill missing fatality rates (if needed)
merged_data$fatality_rate_per_million[is.na(merged_data$fatality_rate_per_million)] <- 0

# Create the map
ggplot(merged_data, aes(x = long, y = lat, group = group, fill = fatality_rate_per_million)) +
  # State boundaries (thinner line)
  geom_polygon(color = "gray80", size = 0.2) +
  # US outline (thicker black line)
  geom_polygon(data = all_states, aes(x = long, y = lat, group = group), color = "black", fill = NA, size = 0.5) +
  # Color gradient for fatality rate
  scale_fill_gradient(low = "lightblue", high = "red", name = "Fatality Rate\nper Million") +
  # Map title
  ggtitle("Fatality Rates per Million by State (2017)") +
  # Remove extra plot elements
  theme_void() +
  # Use map projection for accurate positioning
  coord_map()

# Order the data frame by fatality rate per million
top_10_fatals_2017_per_state <- arrange(top_10_fatals_2017_per_state)
print(top_10_fatals_2017_per_state)
# Create the bar chart to show the fatality rate per million by State
ggplot(data = top_10_fatals_2017_per_state,
       aes(x = fatality_rate_per_million,
           y = reorder(STATE, fatality_rate_per_million),
           fill = -fatality_rate_per_million)) +
  geom_bar(stat = "identity", width = .9) +
  geom_text(aes(label = round(fatality_rate_per_million, 1)), # Round to 1 decimal point
            stat = "identity",
            vjust = 0.5, # Adjust label position above bars
            hjust = 1.5,
            color = "#E36414",
            fontweight = "bold") + # Set text color and weight
  labs(title = "Fatality Rate Per Million by State in 2017",
       y = "State",
       x = "Fatality Rate per Million") +
  theme_bw() +
  scale_color_gradientn(colors = rainbow(2))

The bar chart paints a vivid picture of fatality rates per million across various states, revealing a stark disparity in the toll of preventable accidents. While some states boast remarkably low rates, others struggle with alarmingly high figures. This discrepancy underscores the urgent need for targeted interventions and safety initiatives tailored to individual states’ specific challenges.

On the one hand, several states showcase exemplary fatality rates, demonstrating the effectiveness of their safety measures. These states can serve as beacons of success, inspiring others to emulate their strategies and prioritize public safety.

However, the somber reality for states with significantly higher fatalities demands immediate attention. The graph acts as a powerful call to action, urging policymakers and stakeholders to implement comprehensive plans to address the root causes of these tragic occurrences.

Which times of days (which hour) are their more occurances?

# Count occurrences of accidents for each hour
# Sort data by count in descending order
hour_counts_sorted <- accidents_2017 %>%
  group_by(HOUR) %>%
  summarise(count = n()) %>%
  arrange(desc(count))
print(hour_counts_sorted)
# Calculate medians for count within each hour range
median_count_0_11 <- median(hour_counts_sorted[hour_counts_sorted$HOUR <= 11,]$count)
median_count_12_23 <- median(hour_counts_sorted[hour_counts_sorted$HOUR >= 12,]$count)

# Print the results
cat("Median count for hours 0-11:", median_count_0_11, "\n")
cat("Median count for hours 12-23:", median_count_12_23)

So, Accidents median is higher in the afternoon and night i.e. 12-23:59vs from midnight to noon.

# Create the horizontal bar chart:

ggplot(hour_counts_sorted, aes(x = HOUR, y = count), fill(hour_counts_sorted)) +
  geom_bar(stat = "identity", fill = "#96EFFF", alpha = 0.5, width = 0.8) +
  labs(title = "Number of Accidents by Hour in 2017",
       x = "Hour of the Day (0-23)",
       y = "Number of Accidents") +
  # Add annotations for each median
  geom_label(aes(label = paste0("Median: ", median_count_0_11)), x = 5.5, y = 80, hjust = "left", color = "#FFB534", size = 6) +
  geom_label(aes(label = paste0("Median: ", median_count_12_23)), x = 18.5, y = 80, hjust = "left", color = "#5C8374", size = 6) +
  geom_text(aes(label = count),
            stat = "identity",
            vjust = .4,
            hjust = 3.5,
            color = "#1B4242",
            fontweight = "bold") +
  theme_bw() +
  coord_flip() +
  # for vline used vs hline
  geom_vline(xintercept = 12.0, linetype = "dashed", color = "#A9A9A9", size = 0.5)

Data indicates a substantial increase in median accidents counts during the nighttime hours and looks like a major difference in road safety. Comparing nighttime median accidents to overall median or the morning’s median further emphasizes the magnitude of this risk.

Several factors may contribute to the nighttime peak. These include reduced visibility, driver fatigue, increased instances of drunk driving, and potentially altered risk perception.

hour_counts_sorted$half_of_day <- cut(hour_counts_sorted$HOUR, breaks = c(0, 12, 24), labels = c("AM", "PM"), include.lowest = TRUE)

ggplot(hour_counts_sorted, aes(x = HOUR, y = count), fill(hour_counts_sorted)) +
  geom_bar(stat = "identity", aes(fill = half_of_day), width = 0.8) +
  scale_fill_manual(values = c("AM" = "#96EFFF", "PM" = "#FFB534")) +
  labs(title = "Number of Accidents by Hour in 2017",
       x = "Hour of the Day (0-23)",
       y = "Number of Accidents") +
  # Add annotations for each median
  geom_label(aes(label = paste0("Median: ", median_count_0_11)), x = 5.5, y = 10, hjust = "left", color = "#FFB534", size = 6) +
  geom_label(aes(label = paste0("Median: ", median_count_12_23)), x = 18.5, y = 680, hjust = "left", color = "#5C8374", size = 6) +
  geom_text(aes(label = count),
            stat = "identity",
            vjust = .4,
            hjust = 3.5,
            color = "#1B4242",
            fontweight = "bold") +
  theme_bw() +
  coord_flip() +
  # for vline used vs hline
  geom_vline(xintercept = 12.0, linetype = "dashed", color = "#A9A9A9", size = 0.5)
print(merged_data)
print(colnames(accidents_2017))
# Check if WEATHER1 has any NA values
has_na <- sum(!is.na(accidents_2017$WEATHER1)) > 0

# Count rows based on WEATHER1 excluding NA values
if (has_na) {
  weather1_counts <- accidents_2017[!is.na(accidents_2017$WEATHER1),]$WEATHER1 %>%
    table()
} else {
  weather1_counts <- accidents_2017$WEATHER1 %>%
    table()
}

# Print the results
print("Number of accidents by WEATHER1 (excluding NA):")
print(weather1_counts)

The raw numbers tell a surface story, but the proportions can unearth the hidden dimensions of risk, tracing the invisible threads that bind certain weather types to a disproportionate share of accidents.

# Calculate total number of accidents (excluding NA)
total_accidents <- sum(weather1_counts)

# Calculate proportions for each WEATHER1 value
proportions <- weather1_counts / total_accidents

# Print the proportions
# print("Proportions of accidents by WEATHER1 (excluding NA):")
# print(proportions)

# Sort proportions in descending order
proportions_sorted <- sort(proportions, decreasing = TRUE)

# Print sorted proportions
print("Proportions of accidents by WEATHER1 (excluding NA) in descending order:")
print(proportions_sorted)
# bar chart
ggplot(data = data.frame(WEATHER1 = names(proportions_sorted), proportion = proportions_sorted),
       aes(x = reorder(WEATHER1, proportions), y = proportions)) +
  geom_bar(stat = 'identity', fill = 'skyblue') +
  geom_text(aes(label = round(proportions, 2)), vjust = 0.4, hjust = 1.1) +
  labs(title = 'Proportions of Accidents by WEATHER1 (excluding NA)', x = 'WEATHER1', y = "Proportion") +
  theme_minimal() +
  coord_flip()

When looking at different conditions we can see that Rain is the most common accidents occurring condition. This analysis of traffic accidents in 2017 has shed light on some key aspects of road safety concerns in the United States. Here’s a summary of key points: * High-Fatality States: Highest total number of fatalities per capita were identified. This information can help prioritize resources for states facing the most significant challenges. * Fatality Rates: By calculating fatality rates per million population, a relative risk across multiple states was calculated. * Time of Day: The analysis showed a significant increase in the median for accidents during nighttime hours compared to daytime. Reduced visibility , driver fatigue, and potentially altered risk perception could be contributing factors. * Weather Conditions: While raw data provided insights into the frequency of accidents under different weather conditions, further analysis exploring proportions under different weather condition at the same locations can better reveal which weather types pose the greater risk for accidents.

Overall, this study clarifies data-driven approaches to tackling traffic safety issues. By identifying high-risk factors and vulnerable populations, we can develop more effective strategies to prevent accidents, save lives, and prevent traffic jams.

Further Considerations: * This analysis focused on data from 2017. Examing data from additional years could reveal trends and track progress in road safety efforts. * We could explore other factors like road type, driver demographics, and accident severity to gain a more comprehensive risk analysis. * Also, one could investigate the specific causes of accidents (e.g., speeding, distracted driving) and infroms development of targeted safety campaigns. By continuing to analyze traffic accident data and implementing data-driven solutions, we can create safer roads for everyone.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCmVkaXRvcl9vcHRpb25zOiAKICBtYXJrZG93bjogCiAgICB3cmFwOiBzZW50ZW5jZQotLS0KClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLgpXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuCgoqQ21kK1NoaWZ0K0VudGVyKi4KCiMgQWNjaWRlbnRzIGluIHRoZSB5ZWFyIDIwMTcKCiMgQXNrOgoKRGVmaW5lIHRoZSBwcm9ibGVtIG9yIHF1ZXN0aW9uIHlvdSB3YW50IHRvIGFuc3dlciB3aXRoIHRoZSBkYXRhLgpHYXRoZXIgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGNvbnRleHQgYW5kIGV4aXN0aW5nIGtub3dsZWRnZSByZWxhdGVkIHRvIHRoZSBwcm9ibGVtLgpGb3JtdWxhdGUgc3BlY2lmaWMsIG1lYXN1cmFibGUsIGFjaGlldmFibGUsIHJlbGV2YW50LCBhbmQgdGltZS1ib3VuZCAoU01BUlQpIHF1ZXN0aW9ucyBmb3IgYW5hbHlzaXMuCgpPYmplY3RpdmU6CgpUcmFmZmljIGFjY2lkZW50cyByZW1haW4gYSBwZXJzaXN0ZW50IHRocmVhdCBvbiBBbWVyaWNhbiByb2Fkcy4KSW4gMjAyMCwgYW4gZXN0aW1hdGVkIDM4ODI0IHBlb3BsZSBsb3N0IHRoZWlyIGxpdmVzIGluIG1vdG9yIHZlaGljbGUgY3Jhc2hlcywgYW5kIG1pbGxpb25zIG1vcmUgd2VyZSBpbmp1cmVkLgpUaGlzIGFuYWx5c2lzIHNlZWtzIHRvIHVuZGVyc3RhbmQgdGhlIHVuZGVybHlpbmcgY2F1c2VzIG9mIHRoZXNlIGluY2lkZW50cyB0byBkZXZlbG9wIGVmZmVjdGl2ZSBwcmV2ZW50YXRpdmUgbWVhc3VyZXMuCkJ5IGV4YW1pbmluZyB0cmFmZmljIGFjY2lkZW50IGRhdGEsIHdlIGFpbSB0byBpZGVudGlmeSBjb250cmlidXRpbmcgZmFjdG9ycyBhbmQgcGF0dGVybnMsIHVsdGltYXRlbHkgcmVkdWNpbmcgdGhlIGRldmFzdGF0aW5nIGltcGFjdCBvZiB0aGVzZSB0cmFnZWRpZXMuCgojIyMjIFdoaWNoIHN0YXRlcyBoYXZlIHRoZSAxMCBtb3N0IGZhdGFsaXRpZXM/CgojIyMjIFRvcCAxMCBzdGF0ZXMgZm9yIHRoZSB5ZWFyIDIwMTc/CgojIyMjIFRvcCAxMCBzdGF0ZXMgZm9yIHRoZSB5ZWFyIDIwMTcgcGVyIHBvcHVsYXRpb24/CgojIyMjIFdoaWNoIHRpbWVzIG9mIGRheXMgKHdoaWNoIGhvdXIpIGFyZSB0aGVpciBtb3JlIG9jY3VyYW5jZXM/CgpgYGB7cn0KI2luc3RhbGwgcGFja2FnZXMKaW5zdGFsbC5wYWNrYWdlcygnZ2dwbG90MicpCmluc3RhbGwucGFja2FnZXMoJ3RpZHlyJykKaW5zdGFsbC5wYWNrYWdlcygncHVycnInKQppbnN0YWxsLnBhY2thZ2VzKCdkcGx5cicpCmluc3RhbGwucGFja2FnZXMoJ3RpZHl2ZXJzZScpCmluc3RhbGwucGFja2FnZXMoJ3NoaW55JykKaW5zdGFsbC5wYWNrYWdlcygncHN5Y2gnKQojIGdldHRpbmcgcGFja2FnZXMgdG8gc2hvdyBvbiBhIG1hcAppbnN0YWxsLnBhY2thZ2VzKCdtYXBzJykKaW5zdGFsbC5wYWNrYWdlcygncmVhZHInKQpgYGAKCkxvYWRpbmcgaW4gcmVxdWlyZWQgcGFja2FnZXMKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeSh0aWR5cikKbGlicmFyeShwdXJycikKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KHJlYWRyKQpgYGAKCmBgYHtyfQojICdodHRwczovL3d3dy5kcm9wYm94LmNvbS9zY2wvZmkvZ2Fsbzhud3VwM2p3d2Jkd2IzN3QxL2FjY2lkZW50cy5jc3Y/cmxrZXk9OWl5YTVwb284NjkzMXNweTdoMGlwbTgzMyZkbD0wJwphY2NpZGVudHMgPC0gcmVhZC5jc3YoJ2h0dHBzOi8vd3d3LmRyb3Bib3guY29tL3NjbC9maS9nYWxvOG53dXAzand3YmR3YjM3dDEvYWNjaWRlbnRzLmNzdj9ybGtleT05aXlhNXBvbzg2OTMxc3B5N2gwaXBtODMzJmRsPTAnKQoKIyBJZGVudGlmeSB0aGUgbGF0ZXN0IHllYXIKbGF0ZXN0X3llYXIgPC0gbWF4KGFjY2lkZW50cyRZRUFSKQoKIyBQcmludCB0aGUgbGF0ZXN0IHllYXIKcHJpbnQobGF0ZXN0X3llYXIpCnByaW50KHN1bW1hcnkoYWNjaWRlbnRzKSkKYGBgCkxldHMgdXNlIHRoZSBwc3ljaCBwYWNrYWdlIHRvIGdldCBhIG1vcmUgY29tcHJlaGVuc2l2ZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIHdpdGggdGhlIGRlc2NyaWJlIGZ1bnRpb246CgpgYGB7cn0KZGVzY3JpYmUoYWNjaWRlbnRzKQpgYGAKCmBgYHtyfQpjb2xTdW1zKGlzLm5hKGFjY2lkZW50cykpCgpgYGAKCkNoZWNrIGZvciBhbnkgb3V0bGllcnMuCgpgYGB7cn0KIyBDcmVhdGUgbGlzdCBmb3IgYm94cGxvdHMKIyBuYS5ybSA9IFRSVUU6IGVuc3VyZSB0aGF0IHRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MgYXJlIG5vdCBhZmZlY3RlZCBieSB0aGUgbWlzc2luZyB2YWx1ZXMKc3VtbWFyeShhY2NpZGVudHMsIG5hLnJtID0gVFJVRSkKYGBgCgojIFByZXBhcmU6CgpDb2xsZWN0IG9yIGFjY2VzcyB0aGUgcmVsZXZhbnQgZGF0YSBzb3VyY2VzLgpDbGVhbiBhbmQgcHJlLXByb2Nlc3MgdGhlIGRhdGEgdG8gaGFuZGxlIG1pc3NpbmcgdmFsdWVzLCBpbmNvbnNpc3RlbmNpZXMsIGFuZCBlcnJvcnMuCkV4cGxvcmUgdGhlIGRhdGEgdGhyb3VnaCBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGFuZCB2aXN1YWxpemF0aW9ucyB0byB1bmRlcnN0YW5kIGl0cyBkaXN0cmlidXRpb24gYW5kIGNoYXJhY3RlcmlzdGljcy4KCmBgYHtyfQojIFNlbGVjdCBvbmx5IG51bWVyaWMgY29sdW1ucyBmcm9tIHRoZSBhY2NpZGVudHMgRGF0YUZyYW1lCgpvdXRsaWVycmVtb3ZhbCA8LSBmdW5jdGlvbihhY2NpZGVudHMpewogYWNjaWRlbnRzICU+JQogICAgICAjIFNlbGVjdCBvbmx5IG51bWVyaWMgY29sdW1ucyBmcm9tIHRoZSBhY2NpZGVudHMgRGF0YUZyYW1lCiAgICAgIHNlbGVjdF9pZihpcy5udW1lcmljKSAlPiUgCiAgICAgIG1hcCh+IC54WyEueCAlaW4lIGJveHBsb3Quc3RhdHMoLikkb3V0XSkgCiB9CgpvcHRpb25zKG1heC5wcmludCA9IDIwMCkKcHJpbnQob3V0bGllcnJlbW92YWwoYWNjaWRlbnRzKSkKIyBvcHRpb25zKG1heC5wcmludCA9IDEwMDApCmBgYAoKYGBge3J9Cmxpc3RfcGxvdHMgPC0gbGFwcGx5KG5hbWVzKGFjY2lkZW50cyksIGZ1bmN0aW9uKGNvbCkgewogICMgSW5jcmVhc2UgcGxvdCBhcmVhIHNpemUKICBnZ3Bsb3QoYWNjaWRlbnRzLCBhZXMoeCA9IC5kYXRhW1tjb2xdXSwgeSA9IC4uY291bnQuLikpICsKICAgIGdlb21fYmFyKGFlcyhmaWxsID0gLmRhdGFbW2NvbF1dKSwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgICAjIENlbnRlciB4LWF4aXMgbGFiZWxzIGFuZCBhZGp1c3Qgc3BhY2luZwogICAgdGhlbWUoCiAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgdmp1c3QgPSAwLjUpLAogICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2xpbmUobGluZXdpZHRoID0gMC41KSAgIyBGaXggc2l6ZSBpc3N1ZQogICAgKSArCiAgICBndWlkZXMoCiAgICAgIGxlZ2VuZCA9IFRSVUUsCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkKICAgICkgKwogICAgZmFjZXRfZ3JpZCh+IC4pCn0pCgpgYGAKCmBgYHtyfQojIGZpeCBtaXNzcGVsbGluZyAvIHNwZWxsaW5nIGVycm9ycwpwcmludCgnRlVOQ19TWVMnKQpwcmludCh1bmlxdWUoYWNjaWRlbnRzJEZVTkNfU1lTKSkKYGBgCgpgYGB7cn0KIyBmaXggc3BlbGxpbmcgZXJyb3IKYWNjaWRlbnRzJEZVTkNfU1lTW2FjY2lkZW50cyRGVU5DX1NZUyA9PSAnbmNpcGFsIGFydGVyaWFsLCBvdGhlciddIDwtICdQcmluY2lwYWwgYXJ0ZXJpYWwsIG90aGVyJwojIGRvdWJsZSBjaGVjawpwcmludCh1bmlxdWUoYWNjaWRlbnRzJEZVTkNfU1lTKSkKYGBgCgpgYGB7cn0KYWNjaWRlbnRzIDwtIGFjY2lkZW50cyAlPiUKIGZpbHRlcihIT1VSIDw9IDI0LAogICAgICAgIE1JTlVURSA8PSA1OSwKICAgICAgICBEQVkgPD0gMzEsCiAgICAgICAgWUVBUiA+PSAxOTkwKQpgYGAKCiMjIyMjIE5vdyB0byBkb3VibGUgY2hlY2sgZm9yIGFueSB2aXNpYmxlIG91dGxpZXJzIG9uIHRoZSBncmFwaHM6CgpgYGB7cn0KbGFwcGx5KG5hbWVzKGFjY2lkZW50cyksIGZ1bmN0aW9uKGNvbD1ncm91cCkgewogIGdncGxvdChhY2NpZGVudHMsIGFlcyh4ID0gLmRhdGFbW2NvbF1dLCB5ID0gLi5jb3VudC4uKSkgKyAKICAgIGdlb21fYmFyKGFlcyhmaWxsID0gLmRhdGFbW2NvbF1dKSwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgICAjIERpc3BsYXkgdGhlIGxlZ2VuZCB3aXRoIHRpdGxlIGFuZCB0ZXh0IHNsYW50ZWQgYXQgNDUgZGVncmVlcwogICAgZ3VpZGVzKAogICAgICBsZWdlbmQgPSBUUlVFLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgc2l6ZSA9IDEyKSwKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgc2l6ZSA9IDEwKQogICAgKSArIAogICAgICAjIFJvdGF0ZSB0aGUgeC1heGlzIGxhYmVscyB0byA5MCBkZWdyZWVzIGFuZCBhZGp1c3QgaG9yaXpvbnRhbCBhbGlnbm1lbnQKICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTMpKQp9KSAtPiBsaXN0X3Bsb3RzCmBgYAoKYGBge3J9CnByaW50KGxpc3RfcGxvdHMpCmBgYAoKIyMjIFdoaWNoIHN0YXRlcyBoYXZlIHRoZSAxMCBtb3N0IGZhdGFsaXRpZXM/CgpgYGB7cn0KIyBDaGVjayBmb3IgbWlzc2luZyB2YWx1ZXMKcHJpbnQod2hpY2goaXMubmEoYWNjaWRlbnRzJFNUQVRFKSkpCnByaW50KHdoaWNoKGlzLm5hKGFjY2lkZW50cyRGQVRBTFMpKSkKCiMgQ2FsY3VsYXRlIHRvdGFsIGZhdGFsaXRpZXMgcGVyIHN0YXRlCmZhdGFsc19wZXJfc3RhdGUgPC0gYWdncmVnYXRlKEZBVEFMUyB+IFNUQVRFLCBkYXRhID0gYWNjaWRlbnRzLCBzdW0pCgojIFNvcnQgYnkgZmF0YWxpdGllcyBhbmQgc2VsZWN0IHRoZSB0b3AgMTAgc3RhdGVzCmZhdGFsc19wZXJfc3RhdGUgPC0gYXJyYW5nZShmYXRhbHNfcGVyX3N0YXRlLCBkZXNjKEZBVEFMUykpWzE6MTAsXQoKIyBwcmludCByZXN1bHRzCnByaW50KGZhdGFsc19wZXJfc3RhdGUpCmBgYAoKTW92aW5nIG9uIGZyb20gdGhlIG5hdGlvbmFsIHBlcnNwZWN0aXZlLCBsZXQncyB6b29tIGluIGFuZCBleGFtaW5lIHRoZSBzdGF0ZXMgd2l0aCB0aGUgaGlnaGVzdCBudW1iZXIgb2YgYWNjaWRlbnQgZmF0YWxpdGllcyBpbiAyMDE3LgoKIyMjIFRvcCAxMCBzdGF0ZXMgd2l0aCBtb3N0IGFjY2lkZW50IGZhdGFscyBmb3IgdGhlIHllYXIgMjAxNz8KCmBgYHtyfQojIENoZWNrIGZvciBtaXNzaW5nIHZhbHVlcwpwcmludCh3aGljaChpcy5uYShhY2NpZGVudHMkU1RBVEUpKSkKcHJpbnQod2hpY2goaXMubmEoYWNjaWRlbnRzJEZBVEFMUykpKQoKIyBGaWx0ZXIgZGF0YSBmb3IgdGhlIHllYXIgMjAxNwphY2NpZGVudHNfMjAxNyA8LSBhY2NpZGVudHNbYWNjaWRlbnRzJFlFQVIgPT0gMjAxNyxdCgojIENhbGN1bGF0ZSB0b3RhbCBmYXRhbGl0aWVzIHBlciBzdGF0ZSBmb3IgMjAxNwpmYXRhbHNfcGVyX3N0YXRlXzIwMTcgPC0gYWdncmVnYXRlKEZBVEFMUyB+IFNUQVRFLCBkYXRhID0gYWNjaWRlbnRzXzIwMTcsIHN1bSkKCiMgU29ydCBieSBmYXRhbGl0aWVzIGFuZCBzZWxlY3QgdGhlIHRvcCAxMCBzdGF0ZXMKdG9wXzEwX2ZhdGFsc18yMDE3IDwtIGFycmFuZ2UoZmF0YWxzX3Blcl9zdGF0ZV8yMDE3LCBkZXNjKEZBVEFMUykpWzE6MTAsXQoKIyBwcmludCByZXN1bHRzCnByaW50KHRvcF8xMF9mYXRhbHNfMjAxNykKYGBgCgpUbyB1bmRlcnN0YW5kIHRoZSBpbXBhY3Qgb2YgZmF0YWwgYWNjaWRlbnRzIG1vcmUgY29tcHJlaGVuc2l2ZWx5LCB3ZSBtdXN0IGNvbnNpZGVyIHBvcHVsYXRpb24gZGVuc2l0eS4KVGhlIGZvbGxvd2luZyB3aWxsIHJhbmsgdGhlIHRvcCAxMCBzdGF0ZXMgd2l0aCB0aGUgaGlnaGVzdCBmYXRhbCBhY2NpZGVudCByYXRlcyBwZXIgY2FwaXRhIGluIDIwMTcuCgojIyMgVG9wIDEwIHN0YXRlcyBmb3IgdGhlIHllYXIgMjAxNyBwZXIgcG9wdWxhdGlvbj8KCmBgYHtyfQpzdGF0ZV9wb3AgPSByZWFkLmNzdignL1VzZXJzL2NoYXJsZXMvRG9jdW1lbnRzLzUwX3N0YXRlc19wb3AuY3N2JykKCiMgQ2hhbmdlIHRoZSBjb2x1bW4gdGl0bGVzIHRvIHVwcGVyY2FzZQpjb2xuYW1lcyhzdGF0ZV9wb3ApIDwtIHRvdXBwZXIoY29sbmFtZXMoc3RhdGVfcG9wKSkKCnByaW50KGhlYWQoc3RhdGVfcG9wKSkKCnRvcF8xMF9mYXRhbHNfMjAxN19wZXJfc3RhdGUgPC0gdG9wXzEwX2ZhdGFsc18yMDE3ICU+JQogIG1lcmdlKHN0YXRlX3BvcCwgYnkgPSAiU1RBVEUiKQoKcHJpbnQodG9wXzEwX2ZhdGFsc18yMDE3X3Blcl9zdGF0ZSkKYGBgCgpDYWxjdWxhdGluZyB0cmFmZmljIGFjY2lkZW50IGZhdGFsaXRpZXMgcGVyIGNhcGl0YSBhbGxvd3MgZm9yIGZhaXIgY29tcGFyaXNvbnMgYmV0d2VlbiBzdGF0ZXMgd2l0aCB2YXJ5aW5nIHBvcHVsYXRpb24gc2l6ZXMsIHByb3ZpZGluZyBhIGNsZWFyZXIgcGljdHVyZSBvZiB0aGVpciByZWxhdGl2ZSByaXNrIG9uIHRoZSByb2FkLgpUbyBmYWNpbGl0YXRlIHRoaXMgYW5hbHlzaXMsIHdlIHdpbGwgZXhwcmVzcyBmYXRhbGl0aWVzIHBlciBtaWxsaW9uIHBvcHVsYXRpb24gZm9yIGVhY2ggc3RhdGUuCgpgYGB7cn0KIyBDcmVhdGUgYSBuZXcgY29sdW1uIG5hbWVkICJmYXRhbGl0eV9yYXRlIiBieSBkaXZpZGluZyBGQVRBTFMgYnkgUE9QVUxBVElPTgp0b3BfMTBfZmF0YWxzXzIwMTdfcGVyX3N0YXRlJGZhdGFsaXR5X3JhdGVfcGVyX21pbGxpb24gPC0gdG9wXzEwX2ZhdGFsc18yMDE3X3Blcl9zdGF0ZSRGQVRBTFMgLyB0b3BfMTBfZmF0YWxzXzIwMTdfcGVyX3N0YXRlJFBPUFVMQVRJT04gKiAxMDAwMDAwCnRvcF8xMF9mYXRhbHNfMjAxN19wZXJfc3RhdGUgPC0gYXJyYW5nZSh0b3BfMTBfZmF0YWxzXzIwMTdfcGVyX3N0YXRlLCBkZXNjKGZhdGFsaXR5X3JhdGVfcGVyX21pbGxpb24pKQpwcmludCh0b3BfMTBfZmF0YWxzXzIwMTdfcGVyX3N0YXRlKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkobWFwcykKbGlicmFyeShkcGx5cikKCgojIExvYWQgVVMgc3RhdGUgZGF0YQphbGxfc3RhdGVzIDwtIG1hcF9kYXRhKCJzdGF0ZSIpCgojIEFzc3VtaW5nIHlvdSBoYXZlICJ0b3BfMTBfZmF0YWxzXzIwMTdfcGVyX3N0YXRlIiBkYXRhIHdpdGggc3RhdGUgYW5kIGZhdGFsaXR5IHJhdGUKCiMgSm9pbiBkYXRhIHdpdGggbWFwIGRhdGEgKG1vZGlmeSBiYXNlZCBvbiB5b3VyIGRhdGEgc3RydWN0dXJlKQptZXJnZWRfZGF0YSA8LSBpbm5lcl9qb2luKAogIHRyYW5zZm9ybShhbGxfc3RhdGVzLCByZWdpb24gPSB0b2xvd2VyKHJlZ2lvbikpLAogIHRyYW5zZm9ybSh0b3BfMTBfZmF0YWxzXzIwMTdfcGVyX3N0YXRlLCBTVEFURSA9IHRvbG93ZXIoU1RBVEUpKSwKICBieSA9IGMoInJlZ2lvbiIgPSAiU1RBVEUiKQopCgojIEZpbGwgbWlzc2luZyBmYXRhbGl0eSByYXRlcyAoaWYgbmVlZGVkKQptZXJnZWRfZGF0YSRmYXRhbGl0eV9yYXRlX3Blcl9taWxsaW9uW2lzLm5hKG1lcmdlZF9kYXRhJGZhdGFsaXR5X3JhdGVfcGVyX21pbGxpb24pXSA8LSAwCgojIENyZWF0ZSB0aGUgbWFwCmdncGxvdChtZXJnZWRfZGF0YSwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZmF0YWxpdHlfcmF0ZV9wZXJfbWlsbGlvbikpICsKICAjIFN0YXRlIGJvdW5kYXJpZXMgKHRoaW5uZXIgbGluZSkKICBnZW9tX3BvbHlnb24oY29sb3IgPSAiZ3JheTgwIiwgc2l6ZSA9IDAuMikgKwogICMgVVMgb3V0bGluZSAodGhpY2tlciBibGFjayBsaW5lKQogIGdlb21fcG9seWdvbihkYXRhID0gYWxsX3N0YXRlcywgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gTkEsIHNpemUgPSAwLjUpICsKICAjIENvbG9yIGdyYWRpZW50IGZvciBmYXRhbGl0eSByYXRlCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAibGlnaHRibHVlIiwgaGlnaCA9ICJyZWQiLCBuYW1lID0gIkZhdGFsaXR5IFJhdGVcbnBlciBNaWxsaW9uIikgKwogICMgTWFwIHRpdGxlCiAgZ2d0aXRsZSgiRmF0YWxpdHkgUmF0ZXMgcGVyIE1pbGxpb24gYnkgU3RhdGUgKDIwMTcpIikgKwogICMgUmVtb3ZlIGV4dHJhIHBsb3QgZWxlbWVudHMKICB0aGVtZV92b2lkKCkgKwogICMgVXNlIG1hcCBwcm9qZWN0aW9uIGZvciBhY2N1cmF0ZSBwb3NpdGlvbmluZwogIGNvb3JkX21hcCgpCgpgYGAKCmBgYHtyfQoKIyBPcmRlciB0aGUgZGF0YSBmcmFtZSBieSBmYXRhbGl0eSByYXRlIHBlciBtaWxsaW9uCnRvcF8xMF9mYXRhbHNfMjAxN19wZXJfc3RhdGUgPC0gYXJyYW5nZSh0b3BfMTBfZmF0YWxzXzIwMTdfcGVyX3N0YXRlKQpwcmludCh0b3BfMTBfZmF0YWxzXzIwMTdfcGVyX3N0YXRlKQojIENyZWF0ZSB0aGUgYmFyIGNoYXJ0IHRvIHNob3cgdGhlIGZhdGFsaXR5IHJhdGUgcGVyIG1pbGxpb24gYnkgU3RhdGUKZ2dwbG90KGRhdGEgPSB0b3BfMTBfZmF0YWxzXzIwMTdfcGVyX3N0YXRlLAogICAgICAgYWVzKHggPSBmYXRhbGl0eV9yYXRlX3Blcl9taWxsaW9uLAogICAgICAgICAgIHkgPSByZW9yZGVyKFNUQVRFLCBmYXRhbGl0eV9yYXRlX3Blcl9taWxsaW9uKSwKICAgICAgICAgICBmaWxsID0gLWZhdGFsaXR5X3JhdGVfcGVyX21pbGxpb24pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gLjkpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoZmF0YWxpdHlfcmF0ZV9wZXJfbWlsbGlvbiwgMSkpLCAjIFJvdW5kIHRvIDEgZGVjaW1hbCBwb2ludAogICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICAgdmp1c3QgPSAwLjUsICMgQWRqdXN0IGxhYmVsIHBvc2l0aW9uIGFib3ZlIGJhcnMKICAgICAgICAgICAgaGp1c3QgPSAxLjUsCiAgICAgICAgICAgIGNvbG9yID0gIiNFMzY0MTQiLAogICAgICAgICAgICBmb250d2VpZ2h0ID0gImJvbGQiKSArICMgU2V0IHRleHQgY29sb3IgYW5kIHdlaWdodAogIGxhYnModGl0bGUgPSAiRmF0YWxpdHkgUmF0ZSBQZXIgTWlsbGlvbiBieSBTdGF0ZSBpbiAyMDE3IiwKICAgICAgIHkgPSAiU3RhdGUiLAogICAgICAgeCA9ICJGYXRhbGl0eSBSYXRlIHBlciBNaWxsaW9uIikgKwogIHRoZW1lX2J3KCkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvcnMgPSByYWluYm93KDIpKQpgYGAKClRoZSBiYXIgY2hhcnQgcGFpbnRzIGEgdml2aWQgcGljdHVyZSBvZiBmYXRhbGl0eSByYXRlcyBwZXIgbWlsbGlvbiBhY3Jvc3MgdmFyaW91cyBzdGF0ZXMsIHJldmVhbGluZyBhIHN0YXJrIGRpc3Bhcml0eSBpbiB0aGUgdG9sbCBvZiBwcmV2ZW50YWJsZSBhY2NpZGVudHMuCldoaWxlIHNvbWUgc3RhdGVzIGJvYXN0IHJlbWFya2FibHkgbG93IHJhdGVzLCBvdGhlcnMgc3RydWdnbGUgd2l0aCBhbGFybWluZ2x5IGhpZ2ggZmlndXJlcy4KVGhpcyBkaXNjcmVwYW5jeSB1bmRlcnNjb3JlcyB0aGUgdXJnZW50IG5lZWQgZm9yIHRhcmdldGVkIGludGVydmVudGlvbnMgYW5kIHNhZmV0eSBpbml0aWF0aXZlcyB0YWlsb3JlZCB0byBpbmRpdmlkdWFsIHN0YXRlcycgc3BlY2lmaWMgY2hhbGxlbmdlcy4KCk9uIHRoZSBvbmUgaGFuZCwgc2V2ZXJhbCBzdGF0ZXMgc2hvd2Nhc2UgZXhlbXBsYXJ5IGZhdGFsaXR5IHJhdGVzLCBkZW1vbnN0cmF0aW5nIHRoZSBlZmZlY3RpdmVuZXNzIG9mIHRoZWlyIHNhZmV0eSBtZWFzdXJlcy4KVGhlc2Ugc3RhdGVzIGNhbiBzZXJ2ZSBhcyBiZWFjb25zIG9mIHN1Y2Nlc3MsIGluc3BpcmluZyBvdGhlcnMgdG8gZW11bGF0ZSB0aGVpciBzdHJhdGVnaWVzIGFuZCBwcmlvcml0aXplIHB1YmxpYyBzYWZldHkuCgpIb3dldmVyLCB0aGUgc29tYmVyIHJlYWxpdHkgZm9yIHN0YXRlcyB3aXRoIHNpZ25pZmljYW50bHkgaGlnaGVyIGZhdGFsaXRpZXMgZGVtYW5kcyBpbW1lZGlhdGUgYXR0ZW50aW9uLgpUaGUgZ3JhcGggYWN0cyBhcyBhIHBvd2VyZnVsIGNhbGwgdG8gYWN0aW9uLCB1cmdpbmcgcG9saWN5bWFrZXJzIGFuZCBzdGFrZWhvbGRlcnMgdG8gaW1wbGVtZW50IGNvbXByZWhlbnNpdmUgcGxhbnMgdG8gYWRkcmVzcyB0aGUgcm9vdCBjYXVzZXMgb2YgdGhlc2UgdHJhZ2ljIG9jY3VycmVuY2VzLgoKIyMjIFdoaWNoIHRpbWVzIG9mIGRheXMgKHdoaWNoIGhvdXIpIGFyZSB0aGVpciBtb3JlIG9jY3VyYW5jZXM/CgpgYGB7cn0KIyBDb3VudCBvY2N1cnJlbmNlcyBvZiBhY2NpZGVudHMgZm9yIGVhY2ggaG91cgojIFNvcnQgZGF0YSBieSBjb3VudCBpbiBkZXNjZW5kaW5nIG9yZGVyCmhvdXJfY291bnRzX3NvcnRlZCA8LSBhY2NpZGVudHNfMjAxNyAlPiUKICBncm91cF9ieShIT1VSKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JQogIGFycmFuZ2UoZGVzYyhjb3VudCkpCnByaW50KGhvdXJfY291bnRzX3NvcnRlZCkKYGBgCgpgYGB7cn0KIyBDYWxjdWxhdGUgbWVkaWFucyBmb3IgY291bnQgd2l0aGluIGVhY2ggaG91ciByYW5nZQptZWRpYW5fY291bnRfMF8xMSA8LSBtZWRpYW4oaG91cl9jb3VudHNfc29ydGVkW2hvdXJfY291bnRzX3NvcnRlZCRIT1VSIDw9IDExLF0kY291bnQpCm1lZGlhbl9jb3VudF8xMl8yMyA8LSBtZWRpYW4oaG91cl9jb3VudHNfc29ydGVkW2hvdXJfY291bnRzX3NvcnRlZCRIT1VSID49IDEyLF0kY291bnQpCgojIFByaW50IHRoZSByZXN1bHRzCmNhdCgiTWVkaWFuIGNvdW50IGZvciBob3VycyAwLTExOiIsIG1lZGlhbl9jb3VudF8wXzExLCAiXG4iKQpjYXQoIk1lZGlhbiBjb3VudCBmb3IgaG91cnMgMTItMjM6IiwgbWVkaWFuX2NvdW50XzEyXzIzKQpgYGAKClNvLCBBY2NpZGVudHMgbWVkaWFuIGlzIGhpZ2hlciBpbiB0aGUgYWZ0ZXJub29uIGFuZCBuaWdodCBpLmUuIDEyLTIzOjU5dnMgZnJvbSBtaWRuaWdodCB0byBub29uLgoKYGBge3J9CiMgQ3JlYXRlIHRoZSBob3Jpem9udGFsIGJhciBjaGFydDoKCmdncGxvdChob3VyX2NvdW50c19zb3J0ZWQsIGFlcyh4ID0gSE9VUiwgeSA9IGNvdW50KSwgZmlsbChob3VyX2NvdW50c19zb3J0ZWQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiIzk2RUZGRiIsIGFscGhhID0gMC41LCB3aWR0aCA9IDAuOCkgKwogIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIEFjY2lkZW50cyBieSBIb3VyIGluIDIwMTciLAogICAgICAgeCA9ICJIb3VyIG9mIHRoZSBEYXkgKDAtMjMpIiwKICAgICAgIHkgPSAiTnVtYmVyIG9mIEFjY2lkZW50cyIpICsKICAjIEFkZCBhbm5vdGF0aW9ucyBmb3IgZWFjaCBtZWRpYW4KICBnZW9tX2xhYmVsKGFlcyhsYWJlbCA9IHBhc3RlMCgiTWVkaWFuOiAiLCBtZWRpYW5fY291bnRfMF8xMSkpLCB4ID0gNS41LCB5ID0gODAsIGhqdXN0ID0gImxlZnQiLCBjb2xvciA9ICIjRkZCNTM0Iiwgc2l6ZSA9IDYpICsKICBnZW9tX2xhYmVsKGFlcyhsYWJlbCA9IHBhc3RlMCgiTWVkaWFuOiAiLCBtZWRpYW5fY291bnRfMTJfMjMpKSwgeCA9IDE4LjUsIHkgPSA4MCwgaGp1c3QgPSAibGVmdCIsIGNvbG9yID0gIiM1QzgzNzQiLCBzaXplID0gNikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBjb3VudCksCiAgICAgICAgICAgIHN0YXQgPSAiaWRlbnRpdHkiLAogICAgICAgICAgICB2anVzdCA9IC40LAogICAgICAgICAgICBoanVzdCA9IDMuNSwKICAgICAgICAgICAgY29sb3IgPSAiIzFCNDI0MiIsCiAgICAgICAgICAgIGZvbnR3ZWlnaHQgPSAiYm9sZCIpICsKICB0aGVtZV9idygpICsKICBjb29yZF9mbGlwKCkgKwogICMgZm9yIHZsaW5lIHVzZWQgdnMgaGxpbmUKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxMi4wLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICIjQTlBOUE5Iiwgc2l6ZSA9IDAuNSkKYGBgCgpEYXRhIGluZGljYXRlcyBhIHN1YnN0YW50aWFsIGluY3JlYXNlIGluIG1lZGlhbiBhY2NpZGVudHMgY291bnRzIGR1cmluZyB0aGUgbmlnaHR0aW1lIGhvdXJzIGFuZCBsb29rcyBsaWtlIGEgbWFqb3IgZGlmZmVyZW5jZSBpbiByb2FkIHNhZmV0eS4KQ29tcGFyaW5nIG5pZ2h0dGltZSBtZWRpYW4gYWNjaWRlbnRzIHRvIG92ZXJhbGwgbWVkaWFuIG9yIHRoZSBtb3JuaW5nJ3MgbWVkaWFuIGZ1cnRoZXIgZW1waGFzaXplcyB0aGUgbWFnbml0dWRlIG9mIHRoaXMgcmlzay4KClNldmVyYWwgZmFjdG9ycyBtYXkgY29udHJpYnV0ZSB0byB0aGUgbmlnaHR0aW1lIHBlYWsuClRoZXNlIGluY2x1ZGUgcmVkdWNlZCB2aXNpYmlsaXR5LCBkcml2ZXIgZmF0aWd1ZSwgaW5jcmVhc2VkIGluc3RhbmNlcyBvZiBkcnVuayBkcml2aW5nLCBhbmQgcG90ZW50aWFsbHkgYWx0ZXJlZCByaXNrIHBlcmNlcHRpb24uCgpgYGB7cn0KaG91cl9jb3VudHNfc29ydGVkJGhhbGZfb2ZfZGF5IDwtIGN1dChob3VyX2NvdW50c19zb3J0ZWQkSE9VUiwgYnJlYWtzID0gYygwLCAxMiwgMjQpLCBsYWJlbHMgPSBjKCJBTSIsICJQTSIpLCBpbmNsdWRlLmxvd2VzdCA9IFRSVUUpCgpnZ3Bsb3QoaG91cl9jb3VudHNfc29ydGVkLCBhZXMoeCA9IEhPVVIsIHkgPSBjb3VudCksIGZpbGwoaG91cl9jb3VudHNfc29ydGVkKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBhZXMoZmlsbCA9IGhhbGZfb2ZfZGF5KSwgd2lkdGggPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJBTSIgPSAiIzk2RUZGRiIsICJQTSIgPSAiI0ZGQjUzNCIpKSArCiAgbGFicyh0aXRsZSA9ICJOdW1iZXIgb2YgQWNjaWRlbnRzIGJ5IEhvdXIgaW4gMjAxNyIsCiAgICAgICB4ID0gIkhvdXIgb2YgdGhlIERheSAoMC0yMykiLAogICAgICAgeSA9ICJOdW1iZXIgb2YgQWNjaWRlbnRzIikgKwogICMgQWRkIGFubm90YXRpb25zIGZvciBlYWNoIG1lZGlhbgogIGdlb21fbGFiZWwoYWVzKGxhYmVsID0gcGFzdGUwKCJNZWRpYW46ICIsIG1lZGlhbl9jb3VudF8wXzExKSksIHggPSA1LjUsIHkgPSAxMCwgaGp1c3QgPSAibGVmdCIsIGNvbG9yID0gIiNGRkI1MzQiLCBzaXplID0gNikgKwogIGdlb21fbGFiZWwoYWVzKGxhYmVsID0gcGFzdGUwKCJNZWRpYW46ICIsIG1lZGlhbl9jb3VudF8xMl8yMykpLCB4ID0gMTguNSwgeSA9IDY4MCwgaGp1c3QgPSAibGVmdCIsIGNvbG9yID0gIiM1QzgzNzQiLCBzaXplID0gNikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBjb3VudCksCiAgICAgICAgICAgIHN0YXQgPSAiaWRlbnRpdHkiLAogICAgICAgICAgICB2anVzdCA9IC40LAogICAgICAgICAgICBoanVzdCA9IDMuNSwKICAgICAgICAgICAgY29sb3IgPSAiIzFCNDI0MiIsCiAgICAgICAgICAgIGZvbnR3ZWlnaHQgPSAiYm9sZCIpICsKICB0aGVtZV9idygpICsKICBjb29yZF9mbGlwKCkgKwogICMgZm9yIHZsaW5lIHVzZWQgdnMgaGxpbmUKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxMi4wLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICIjQTlBOUE5Iiwgc2l6ZSA9IDAuNSkKYGBgCgpgYGB7cn0KcHJpbnQobWVyZ2VkX2RhdGEpCnByaW50KGNvbG5hbWVzKGFjY2lkZW50c18yMDE3KSkKYGBgCgpgYGB7cn0KIyBDaGVjayBpZiBXRUFUSEVSMSBoYXMgYW55IE5BIHZhbHVlcwpoYXNfbmEgPC0gc3VtKCFpcy5uYShhY2NpZGVudHNfMjAxNyRXRUFUSEVSMSkpID4gMAoKIyBDb3VudCByb3dzIGJhc2VkIG9uIFdFQVRIRVIxIGV4Y2x1ZGluZyBOQSB2YWx1ZXMKaWYgKGhhc19uYSkgewogIHdlYXRoZXIxX2NvdW50cyA8LSBhY2NpZGVudHNfMjAxN1shaXMubmEoYWNjaWRlbnRzXzIwMTckV0VBVEhFUjEpLF0kV0VBVEhFUjEgJT4lCiAgICB0YWJsZSgpCn0gZWxzZSB7CiAgd2VhdGhlcjFfY291bnRzIDwtIGFjY2lkZW50c18yMDE3JFdFQVRIRVIxICU+JQogICAgdGFibGUoKQp9CgojIFByaW50IHRoZSByZXN1bHRzCnByaW50KCJOdW1iZXIgb2YgYWNjaWRlbnRzIGJ5IFdFQVRIRVIxIChleGNsdWRpbmcgTkEpOiIpCnByaW50KHdlYXRoZXIxX2NvdW50cykKYGBgCgpUaGUgcmF3IG51bWJlcnMgdGVsbCBhIHN1cmZhY2Ugc3RvcnksIGJ1dCB0aGUgcHJvcG9ydGlvbnMgY2FuIHVuZWFydGggdGhlIGhpZGRlbiBkaW1lbnNpb25zIG9mIHJpc2ssIHRyYWNpbmcgdGhlIGludmlzaWJsZSB0aHJlYWRzIHRoYXQgYmluZCBjZXJ0YWluIHdlYXRoZXIgdHlwZXMgdG8gYSBkaXNwcm9wb3J0aW9uYXRlIHNoYXJlIG9mIGFjY2lkZW50cy4KCmBgYHtyfQojIENhbGN1bGF0ZSB0b3RhbCBudW1iZXIgb2YgYWNjaWRlbnRzIChleGNsdWRpbmcgTkEpCnRvdGFsX2FjY2lkZW50cyA8LSBzdW0od2VhdGhlcjFfY291bnRzKQoKIyBDYWxjdWxhdGUgcHJvcG9ydGlvbnMgZm9yIGVhY2ggV0VBVEhFUjEgdmFsdWUKcHJvcG9ydGlvbnMgPC0gd2VhdGhlcjFfY291bnRzIC8gdG90YWxfYWNjaWRlbnRzCgojIFByaW50IHRoZSBwcm9wb3J0aW9ucwojIHByaW50KCJQcm9wb3J0aW9ucyBvZiBhY2NpZGVudHMgYnkgV0VBVEhFUjEgKGV4Y2x1ZGluZyBOQSk6IikKIyBwcmludChwcm9wb3J0aW9ucykKCiMgU29ydCBwcm9wb3J0aW9ucyBpbiBkZXNjZW5kaW5nIG9yZGVyCnByb3BvcnRpb25zX3NvcnRlZCA8LSBzb3J0KHByb3BvcnRpb25zLCBkZWNyZWFzaW5nID0gVFJVRSkKCiMgUHJpbnQgc29ydGVkIHByb3BvcnRpb25zCnByaW50KCJQcm9wb3J0aW9ucyBvZiBhY2NpZGVudHMgYnkgV0VBVEhFUjEgKGV4Y2x1ZGluZyBOQSkgaW4gZGVzY2VuZGluZyBvcmRlcjoiKQpwcmludChwcm9wb3J0aW9uc19zb3J0ZWQpCmBgYAoKYGBge3J9CiMgYmFyIGNoYXJ0CmdncGxvdChkYXRhID0gZGF0YS5mcmFtZShXRUFUSEVSMSA9IG5hbWVzKHByb3BvcnRpb25zX3NvcnRlZCksIHByb3BvcnRpb24gPSBwcm9wb3J0aW9uc19zb3J0ZWQpLAogICAgICAgYWVzKHggPSByZW9yZGVyKFdFQVRIRVIxLCBwcm9wb3J0aW9ucyksIHkgPSBwcm9wb3J0aW9ucykpICsKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JywgZmlsbCA9ICdza3libHVlJykgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChwcm9wb3J0aW9ucywgMikpLCB2anVzdCA9IDAuNCwgaGp1c3QgPSAxLjEpICsKICBsYWJzKHRpdGxlID0gJ1Byb3BvcnRpb25zIG9mIEFjY2lkZW50cyBieSBXRUFUSEVSMSAoZXhjbHVkaW5nIE5BKScsIHggPSAnV0VBVEhFUjEnLCB5ID0gIlByb3BvcnRpb24iKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBjb29yZF9mbGlwKCkKYGBgCgpXaGVuIGxvb2tpbmcgYXQgZGlmZmVyZW50IGNvbmRpdGlvbnMgd2UgY2FuIHNlZSB0aGF0IFJhaW4gaXMgdGhlIG1vc3QgY29tbW9uIGFjY2lkZW50cyBvY2N1cnJpbmcgY29uZGl0aW9uLgpUaGlzIGFuYWx5c2lzIG9mIHRyYWZmaWMgYWNjaWRlbnRzIGluIDIwMTcgaGFzIHNoZWQgbGlnaHQgb24gc29tZSBrZXkgYXNwZWN0cyBvZiByb2FkIHNhZmV0eSBjb25jZXJucyBpbiB0aGUgVW5pdGVkIFN0YXRlcy4gCkhlcmUncyBhIHN1bW1hcnkgb2Yga2V5IHBvaW50czoKKiAqKkhpZ2gtRmF0YWxpdHkgU3RhdGVzKio6IEhpZ2hlc3QgdG90YWwgbnVtYmVyIG9mIGZhdGFsaXRpZXMgcGVyIGNhcGl0YSB3ZXJlIGlkZW50aWZpZWQuIFRoaXMgaW5mb3JtYXRpb24gY2FuIGhlbHAgcHJpb3JpdGl6ZSByZXNvdXJjZXMgZm9yIHN0YXRlcyBmYWNpbmcgdGhlIG1vc3Qgc2lnbmlmaWNhbnQgY2hhbGxlbmdlcy4KKiAqKkZhdGFsaXR5IFJhdGVzKio6IEJ5IGNhbGN1bGF0aW5nIGZhdGFsaXR5IHJhdGVzIHBlciBtaWxsaW9uIHBvcHVsYXRpb24sIGEgcmVsYXRpdmUgcmlzayBhY3Jvc3MgbXVsdGlwbGUgc3RhdGVzIHdhcyBjYWxjdWxhdGVkLiAKKiAqKlRpbWUgb2YgRGF5Kio6IFRoZSBhbmFseXNpcyBzaG93ZWQgYSBzaWduaWZpY2FudCBpbmNyZWFzZSBpbiB0aGUgbWVkaWFuIGZvciBhY2NpZGVudHMgZHVyaW5nIG5pZ2h0dGltZSBob3VycyBjb21wYXJlZCB0byBkYXl0aW1lLiBSZWR1Y2VkIHZpc2liaWxpdHkgLCBkcml2ZXIgZmF0aWd1ZSwgYW5kIHBvdGVudGlhbGx5IGFsdGVyZWQgcmlzayBwZXJjZXB0aW9uIGNvdWxkIGJlIGNvbnRyaWJ1dGluZyBmYWN0b3JzLgoqICoqV2VhdGhlciBDb25kaXRpb25zKio6IFdoaWxlIHJhdyBkYXRhIHByb3ZpZGVkIGluc2lnaHRzIGludG8gdGhlIGZyZXF1ZW5jeSBvZiBhY2NpZGVudHMgdW5kZXIgZGlmZmVyZW50IHdlYXRoZXIgY29uZGl0aW9ucywgZnVydGhlciBhbmFseXNpcyBleHBsb3JpbmcgcHJvcG9ydGlvbnMgdW5kZXIgZGlmZmVyZW50IHdlYXRoZXIgY29uZGl0aW9uIGF0IHRoZSBzYW1lIGxvY2F0aW9ucyBjYW4gYmV0dGVyIHJldmVhbCB3aGljaCB3ZWF0aGVyIHR5cGVzIHBvc2UgdGhlIGdyZWF0ZXIgcmlzayBmb3IgYWNjaWRlbnRzLgoKT3ZlcmFsbCwgdGhpcyBzdHVkeSBjbGFyaWZpZXMgZGF0YS1kcml2ZW4gYXBwcm9hY2hlcyB0byB0YWNrbGluZyB0cmFmZmljIHNhZmV0eSBpc3N1ZXMuIEJ5IGlkZW50aWZ5aW5nIGhpZ2gtcmlzayBmYWN0b3JzIGFuZCB2dWxuZXJhYmxlIHBvcHVsYXRpb25zLCB3ZSBjYW4gZGV2ZWxvcCBtb3JlIGVmZmVjdGl2ZSBzdHJhdGVnaWVzIHRvIHByZXZlbnQgYWNjaWRlbnRzLCBzYXZlIGxpdmVzLCBhbmQgcHJldmVudCB0cmFmZmljIGphbXMuCgoqKkZ1cnRoZXIgQ29uc2lkZXJhdGlvbnM6KioKKiBUaGlzIGFuYWx5c2lzIGZvY3VzZWQgb24gZGF0YSBmcm9tIDIwMTcuIEV4YW1pbmcgZGF0YSBmcm9tIGFkZGl0aW9uYWwgeWVhcnMgY291bGQgcmV2ZWFsIHRyZW5kcyBhbmQgdHJhY2sgcHJvZ3Jlc3MgaW4gcm9hZCBzYWZldHkgZWZmb3J0cy4KKiBXZSBjb3VsZCBleHBsb3JlIG90aGVyIGZhY3RvcnMgbGlrZSByb2FkIHR5cGUsIGRyaXZlciBkZW1vZ3JhcGhpY3MsIGFuZCBhY2NpZGVudCBzZXZlcml0eSB0byBnYWluIGEgbW9yZSBjb21wcmVoZW5zaXZlIHJpc2sgYW5hbHlzaXMuCiogQWxzbywgb25lIGNvdWxkIGludmVzdGlnYXRlIHRoZSBzcGVjaWZpYyBjYXVzZXMgb2YgYWNjaWRlbnRzIChlLmcuLCBzcGVlZGluZywgZGlzdHJhY3RlZCBkcml2aW5nKSBhbmQgaW5mcm9tcyBkZXZlbG9wbWVudCBvZiB0YXJnZXRlZCBzYWZldHkgY2FtcGFpZ25zLgpCeSBjb250aW51aW5nIHRvIGFuYWx5emUgdHJhZmZpYyBhY2NpZGVudCBkYXRhIGFuZCBpbXBsZW1lbnRpbmcgZGF0YS1kcml2ZW4gc29sdXRpb25zLCB3ZSBjYW4gY3JlYXRlIHNhZmVyIHJvYWRzIGZvciBldmVyeW9uZS4=