Introduction

In Victoria there are in excess of 5,000,000 cars registered to VicRoads. Crash statistics are closely monitored by several government organisations. A reduction in the road toll is paramount in the saving lives of Victorian citizens.Crash data is information recorded by VicRoads and made publicly available at data.vic.gov.au. This dataset contains all crash data from 1st January 2006 up until 3rd August 2016. The Victorian Government in 2011 released a report into the road toll and the effect that road safety cameras (red light and speed cameras) has had on reducing the number of deaths on the road. It was found that many variables contributed to deaths on the road including: speed, fatigue, road design etc. The report also found that there were several factors that lend themselves to higher road toll numbers. Accident/crash dataset is merged with ACCIDENT_NO, identified missing values, excluded the outliers, applied data transformation for following reasons: i) to change the scale for better understanding of the variable, ii) to convert a non-linear relation into linear one, or iii) to decrease the skewness and convert the distribution into a normal distribution

Required packages

library(readr)
library(dplyr)
library(plyr)
library(tidyr)
library(knitr)
library(MVN)
library(lubridate)
library(stringr)
library(outliers)
library(forecast)
setwd("F:/RMIT/sem2/Data Preprocessing/assignment 3/")
accident <- read.csv("ACCIDENT.csv",stringsAsFactors = FALSE)
acc_chinage <- read.csv("ACCIDENT_CHAINAGE.csv")
acc_event <- read.csv("ACCIDENT_EVENT.csv")
acc_location <- read.csv("ACCIDENT_LOCATION.csv")
acc_atmosCond <- read.csv("ATMOSPHERIC_COND.csv")
acc_node <- read.csv("NODE.csv")
acc_nodeId <- read.csv("NODE_ID_COMPLEX_INT_ID.csv",stringsAsFactors = FALSE)
acc_person <- read.csv("PERSON.csv")
acc_rdSurfaceCond <- read.csv("ROAD_SURFACE_COND.csv")
acc_subdca <- read.csv("SUBDCA.csv")
acc_vehicle <- read.csv("VEHICLE.csv" )
#merging all csv file by ACCIDENT_NO as ID
accident_df <- join_all(list(accident,acc_event,acc_location,acc_atmosCond,acc_node,acc_nodeId,acc_person,acc_rdSurfaceCond,acc_subdca,acc_vehicle), by='ACCIDENT_NO', type='left')
sapply(accident_df,class)
           ACCIDENT_NO           ACCIDENTDATE           ACCIDENTTIME          ACCIDENT_TYPE     Accident.Type.Desc            DAY_OF_WEEK 
           "character"            "character"            "character"              "integer"            "character"              "integer" 
  Day.Week.Description               DCA_CODE        DCA.Description              DIRECTORY                EDITION                   PAGE 
           "character"              "integer"            "character"            "character"            "character"            "character" 
      GRID_REFERENCE_X       GRID_REFERENCE_Y        LIGHT_CONDITION   Light.Condition.Desc                NODE_ID         NO_OF_VEHICLES 
           "character"              "integer"              "integer"            "character"              "integer"              "integer" 
            NO_PERSONS       NO_PERSONS_INJ_2       NO_PERSONS_INJ_3      NO_PERSONS_KILLED     NO_PERSONS_NOT_INJ          POLICE_ATTEND 
             "integer"              "integer"              "integer"              "integer"              "integer"              "integer" 
         ROAD_GEOMETRY     Road.Geometry.Desc               SEVERITY             SPEED_ZONE           EVENT_SEQ_NO             EVENT_TYPE 
             "integer"            "character"              "integer"              "integer"              "integer"               "factor" 
       Event.Type.Desc           VEHICLE_1_ID      VEHICLE_1_COLL_PT Vehicle.1.Coll.Pt.Desc           VEHICLE_2_ID      VEHICLE_2_COLL_PT 
              "factor"               "factor"               "factor"               "factor"               "factor"               "factor" 
Vehicle.2.Coll.Pt.Desc              PERSON_ID            OBJECT_TYPE       Object.Type.Desc                NODE_ID           ROAD_ROUTE_1 
              "factor"               "factor"              "integer"               "factor"              "integer"              "integer" 
             ROAD_NAME              ROAD_TYPE          ROAD_NAME_INT          ROAD_TYPE_INT      DISTANCE_LOCATION     DIRECTION_LOCATION 
              "factor"               "factor"               "factor"               "factor"              "integer"               "factor" 
       NEAREST_KM_POST      OFF_ROAD_LOCATION           ATMOSPH_COND       ATMOSPH_COND_SEQ      Atmosph.Cond.Desc                NODE_ID 
             "integer"               "factor"              "integer"              "integer"               "factor"              "integer" 
             NODE_TYPE                  AMG_X                  AMG_Y               LGA_NAME           Lga.Name.All            Region.Name 
              "factor"              "numeric"              "numeric"               "factor"               "factor"               "factor" 
        Deg.Urban.Name                    Lat                   Long            Postcode.No                NODE_ID         COMPLEX_INT_NO 
              "factor"              "numeric"              "numeric"              "integer"              "integer"              "integer" 
             PERSON_ID             VEHICLE_ID                    SEX                    AGE              Age.Group              INJ_LEVEL 
              "factor"               "factor"               "factor"              "integer"               "factor"              "integer" 
        Inj.Level.Desc       SEATING_POSITION       HELMET_BELT_WORN         ROAD_USER_TYPE    Road.User.Type.Desc          LICENCE_STATE 
              "factor"               "factor"              "integer"              "numeric"               "factor"               "factor" 
       PEDEST_MOVEMENT               POSTCODE         TAKEN_HOSPITAL           EJECTED_CODE           SURFACE_COND      Surface.Cond.Desc 
             "integer"              "integer"               "factor"              "integer"              "integer"               "factor" 
      SURFACE_COND_SEQ           SUB_DCA_CODE            SUB_DCA_SEQ      Sub.Dca.Code.Desc             VEHICLE_ID     VEHICLE_YEAR_MANUF 
             "integer"               "factor"              "integer"               "factor"               "factor"              "integer" 
      VEHICLE_DCA_CODE      INITIAL_DIRECTION      ROAD_SURFACE_TYPE Road.Surface.Type.Desc              REG_STATE     VEHICLE_BODY_STYLE 
             "integer"               "factor"              "integer"               "factor"               "factor"               "factor" 
          VEHICLE_MAKE          VEHICLE_MODEL          VEHICLE_POWER           VEHICLE_TYPE      Vehicle.Type.Desc         VEHICLE_WEIGHT 
              "factor"               "factor"              "integer"              "integer"               "factor"              "integer" 
     CONSTRUCTION_TYPE              FUEL_TYPE           NO_OF_WHEELS        NO_OF_CYLINDERS       SEATING_CAPACITY            TARE_WEIGHT 
              "factor"               "factor"              "integer"              "integer"              "integer"              "integer" 
    TOTAL_NO_OCCUPANTS         CARRY_CAPACITY         CUBIC_CAPACITY        FINAL_DIRECTION          DRIVER_INTENT       VEHICLE_MOVEMENT 
             "integer"              "integer"               "factor"               "factor"              "integer"              "integer" 
          TRAILER_TYPE       VEHICLE_COLOUR_1       VEHICLE_COLOUR_2            CAUGHT_FIRE         INITIAL_IMPACT                  LAMPS 
              "factor"               "factor"               "factor"              "integer"               "factor"              "integer" 
       LEVEL_OF_DAMAGE         OWNER_POSTCODE        TOWED_AWAY_FLAG        TRAFFIC_CONTROL   Traffic.Control.Desc 
             "integer"              "integer"              "integer"              "integer"               "factor" 

Identifying missing values

#COncentrating on number of people killed in accidents
acc_severity <- accident_df[(accident_df$NO_PERSONS_KILLED > 0),]
#change to datetime
acc_severity$ACCIDENTDATE <- as.POSIXct(strptime(acc_severity$ACCIDENTDATE, "%d/%m/%Y"))
#changing character to hms
acc_severity$ACCIDENTTIME <- hms(acc_severity$ACCIDENTTIME)
sapply(acc_severity, function(x) sum(is.na(x)))
           ACCIDENT_NO           ACCIDENTDATE           ACCIDENTTIME          ACCIDENT_TYPE     Accident.Type.Desc            DAY_OF_WEEK 
                     0                      0                      0                      0                      0                      0 
  Day.Week.Description               DCA_CODE        DCA.Description              DIRECTORY                EDITION                   PAGE 
                     0                      0                      0                      0                      0                      0 
      GRID_REFERENCE_X       GRID_REFERENCE_Y        LIGHT_CONDITION   Light.Condition.Desc                NODE_ID         NO_OF_VEHICLES 
                     0                   4982                      0                      0                      0                      0 
            NO_PERSONS       NO_PERSONS_INJ_2       NO_PERSONS_INJ_3      NO_PERSONS_KILLED     NO_PERSONS_NOT_INJ          POLICE_ATTEND 
                     0                      0                      0                      0                      0                      0 
         ROAD_GEOMETRY     Road.Geometry.Desc               SEVERITY             SPEED_ZONE           EVENT_SEQ_NO             EVENT_TYPE 
                     0                      0                      0                      0                      0                      0 
       Event.Type.Desc           VEHICLE_1_ID      VEHICLE_1_COLL_PT Vehicle.1.Coll.Pt.Desc           VEHICLE_2_ID      VEHICLE_2_COLL_PT 
                     0                      0                      0                      0                      0                      0 
Vehicle.2.Coll.Pt.Desc              PERSON_ID            OBJECT_TYPE       Object.Type.Desc                NODE_ID           ROAD_ROUTE_1 
                     0                      0                      0                      0                      0                      0 
             ROAD_NAME              ROAD_TYPE          ROAD_NAME_INT          ROAD_TYPE_INT      DISTANCE_LOCATION     DIRECTION_LOCATION 
                     0                      0                      0                      0                      0                      0 
       NEAREST_KM_POST      OFF_ROAD_LOCATION           ATMOSPH_COND       ATMOSPH_COND_SEQ      Atmosph.Cond.Desc                NODE_ID 
                 49283                      0                      0                      0                      0                      0 
             NODE_TYPE                  AMG_X                  AMG_Y               LGA_NAME           Lga.Name.All            Region.Name 
                     0                      0                      0                      0                      0                      0 
        Deg.Urban.Name                    Lat                   Long            Postcode.No                NODE_ID         COMPLEX_INT_NO 
                     0                      0                      0                      0                  51167                  51167 
             PERSON_ID             VEHICLE_ID                    SEX                    AGE              Age.Group              INJ_LEVEL 
                     0                      0                      0                   1069                      0                      0 
        Inj.Level.Desc       SEATING_POSITION       HELMET_BELT_WORN         ROAD_USER_TYPE    Road.User.Type.Desc          LICENCE_STATE 
                     0                   2591                      0                      0                      0                      0 
       PEDEST_MOVEMENT               POSTCODE         TAKEN_HOSPITAL           EJECTED_CODE           SURFACE_COND      Surface.Cond.Desc 
                     0                   7532                      0                     56                      0                      0 
      SURFACE_COND_SEQ           SUB_DCA_CODE            SUB_DCA_SEQ      Sub.Dca.Code.Desc             VEHICLE_ID     VEHICLE_YEAR_MANUF 
                     0                    502                    502                    502                      0                   2396 
      VEHICLE_DCA_CODE      INITIAL_DIRECTION      ROAD_SURFACE_TYPE Road.Surface.Type.Desc              REG_STATE     VEHICLE_BODY_STYLE 
                    44                      0                      0                      0                      0                      0 
          VEHICLE_MAKE          VEHICLE_MODEL          VEHICLE_POWER           VEHICLE_TYPE      Vehicle.Type.Desc         VEHICLE_WEIGHT 
                     0                      0                  54265                      0                      0                  45115 
     CONSTRUCTION_TYPE              FUEL_TYPE           NO_OF_WHEELS        NO_OF_CYLINDERS       SEATING_CAPACITY            TARE_WEIGHT 
                     0                      0                  10251                   7833                  11643                   5429 
    TOTAL_NO_OCCUPANTS         CARRY_CAPACITY         CUBIC_CAPACITY        FINAL_DIRECTION          DRIVER_INTENT       VEHICLE_MOVEMENT 
                     0                  40147                      0                      0                      0                      0 
          TRAILER_TYPE       VEHICLE_COLOUR_1       VEHICLE_COLOUR_2            CAUGHT_FIRE         INITIAL_IMPACT                  LAMPS 
                     0                      0                      0                      0                      0                      0 
       LEVEL_OF_DAMAGE         OWNER_POSTCODE        TOWED_AWAY_FLAG        TRAFFIC_CONTROL   Traffic.Control.Desc 
                     0                   2030                      0                      0                      0 

Ignorning the variables consisting null values because further analysis dosen’t require those variables with null values.

Subsetting the data

list1 <- c("ACCIDENT_NO","ACCIDENTDATE","ACCIDENTTIME","Accident.Type.Desc","DAY_OF_WEEK","Day.Week.Description","DCA.Description","DIRECTORY","Light.Condition.Desc","NO_OF_VEHICLES","NO_PERSONS","NO_PERSONS_KILLED","SPEED_ZONE","Event.Type.Desc","Lat","Long","Vehicle.Type.Desc","SEX","Age.Group")
accident <- acc_severity[list1]
sapply(accident, function(x) sum(is.na(x)))
         ACCIDENT_NO         ACCIDENTDATE         ACCIDENTTIME   Accident.Type.Desc          DAY_OF_WEEK Day.Week.Description      DCA.Description 
                   0                    0                    0                    0                    0                    0                    0 
           DIRECTORY Light.Condition.Desc       NO_OF_VEHICLES           NO_PERSONS    NO_PERSONS_KILLED           SPEED_ZONE      Event.Type.Desc 
                   0                    0                    0                    0                    0                    0                    0 
                 Lat                 Long    Vehicle.Type.Desc                  SEX            Age.Group 
                   0                    0                    0                    0                    0 

Data set source and description

The data in this study was sourced from VicRoads and stored on data.vic.gov.au, which has a compilation of data from a wide range of government sources. The data set contains a collection of 145,156 accidents for the past decade and records basic accident details such as: day of the week, light conditions, speed limit, type of accidents. . ACCIDENT_NO: The identification number given to each accident where the 2nd to 5th chararachters make up the year that the accident occured. . ACCIDENTDATE: The date that each accident occured - recorded as DD/MM/YYY. . ACCIDENTTIME: The time that the accident occured recorded in 24 Hour time . ACCIDENTTYPE & Accident Type Desc: Variables describing the nature of the accident. ACCIDENTTYPE is a categorical variable with values 1-9 describing the type of accident respective to the Accident Type Description (1=Collision with vehicle 2=Struck pedestrian 3=Struck animal 4=Collision with a fixed object 5=Collision with some other object 6=Vehicle overturned (no collision) 7=Fall from or in moving vehicle 8=No collision and no object struck 9=Other accident). . DAY OF THE WEEK: The day of each week that the accident took place (1=Sunday,2= Monday, 3=Tuesday,4=Wednesday,5= Thursday,6=Friday and 7=Saturday) 1 . LIGHT CONDITION: The level of light available at the time of the accident (1=Day,2=Dusk/dawn,3=Dark street lights on,4=Dark street lights off,5=Dark no street lights,6=Dark street lights unknown, 9=Unknown) . SPEED ZONE: The speed limit that is enforced at the site of the accident (040=40 km/hr, 050=50 km/hr, 060=60 km/hr, 075=75 km/hr, 080=80 km/hr, 090=90 km/hr, 100=100 km/hr, 110=110 km/hr, 777=Other speed limit, 888=Camping grounds/off road, 999=Not known). 2

accident$time_category <- ifelse(hour(accident$ACCIDENTTIME) >= 05 & hour(accident$ACCIDENTTIME) <= 11, "Morning",
                           ifelse(hour(accident$ACCIDENTTIME) > 11 & hour(accident$ACCIDENTTIME) <= 16, "Afternoon",
                                  ifelse(hour(accident$ACCIDENTTIME) > 16 & hour(accident$ACCIDENTTIME) <= 19, "Evening", "Night")))
accident$SEASON <- ifelse(month(accident$ACCIDENTDATE) >= 12 & month(accident$ACCIDENTDATE) <= 2, "Summer",
                           ifelse(month(accident$ACCIDENTDATE) >= 3 & month(accident$ACCIDENTDATE) <= 5, "Autumn",
                                  ifelse(month(accident$ACCIDENTDATE) >= 6 & month(accident$ACCIDENTDATE) <= 8, "Winter",
                                          ifelse(month(accident$ACCIDENTDATE) >= 9 & month(accident$ACCIDENTDATE) <= 11, "Spring","Summer"))))
accident$hourly <- hour(accident$ACCIDENTTIME)
accident_freq <- accident %>% 
  dplyr::group_by(hourly,Vehicle.Type.Desc,SPEED_ZONE) %>% 
  dplyr::summarise(freq = sum(NO_PERSONS_KILLED))

Multivariate Outlier Detection

boxplot(accident_freq$freq ~ accident_freq$SPEED_ZONE, main="NO PERSONS KILLED vs SPEED ZONE", ylab = "NO. PERSONS KILLED freq", xlab = "Speed Zone")

The above figure illustrates the bivariate box plot, we are interested in Speed_zone variable and a “No.of people killed” variable in the accident data set. According to the plot, there are few outliers with respect to the speed zones. The mvn() function is used to discover possible multivariate outliers

# Multivariate outlier detection using Mahalanobis distance with QQ plots
accident_freq_sub <- accident_freq %>% dplyr::select(hourly,SPEED_ZONE,freq)
Adding missing grouping variables: `Vehicle.Type.Desc`
accident_freq_sub$Vehicle.Type.Desc <- NULL
results <- mvn(data = accident_freq_sub, multivariateOutlierMethod = "quan", showOutliers = TRUE)

As we can see on the QQ plot, the Mahalonobis distance suggests existence of few outliers for this subset of the accident data. The list of possible multivariate outliers can be displayed by using result$multivariateOutliers to select only the results related to outliers as follows:

results$multivariateOutliers

This output is providing the locations of outliers in the data set. In this project there are 365 observations that are suggested outliers for this subset of accident data. Argument showNewData = TRUE is used to exclude the outliers. One can simply detect and remove outliers using the following argument:

accident_clean <- mvn(data = accident_freq_sub, multivariateOutlierMethod = "quan", showOutliers = TRUE, showNewData = TRUE)

# Prints the data without outliers
dim(accident_clean$newData)
[1] 741   3
head(accident_clean$newData)

Data Transformation

Mathematical transformation

To achive the data normality, we are applying data transformations through mathematical operations like logarithmic (i.e., ln and log), square root, power transformations etc. and finally we will select the best transformation.

hist(accident_clean$newData$freq)

From the histogram, we observe that frequency count have a right-skewed distribution. By applying a logarithmic transformation, the salary distribution would be more symmetrical.

Log10 transformation
ln_fliter_acc_filt <- log10(accident_clean$newData$freq)
hist(ln_fliter_acc_filt)

Log transformation
ln_accident <- log(accident_clean$newData$freq)
hist(ln_accident)

As seen from the histograms, the log10 transformation worked slightly better than the ln transformation for this dataset.

Another transformation is the square root transformation. It is also used for reducing right skewness, and also has the advantage that it can be applied to zero values.

Square root transformation
sqrt_accident <- sqrt(accident_clean$newData$freq)
hist(sqrt_accident)

The square root transformation has reduced the skewness in the accident frequency count distribution. But still we can see for more transformations to confirm the better one.

reciprocal transformation
recip_fliter_acc_filt <- 1/(accident_clean$newData$freq)
hist(recip_fliter_acc_filt)

Box-Cox Transformation
boxcox_acc_filt<- BoxCox(accident_clean$newData$freq,lambda = "auto")
hist(boxcox_acc_filt)

After trying out many transformations, square root transformation has reduced the skewness in the accident frequency count distribution

Data Normalisation

z score standardisation
center_x <-scale(sqrt_accident, center = TRUE, scale = TRUE)
hist(center_x)

The resulting transformed data values would have a zero mean and one standard deviation.

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQphdXRob3I6ICJNYW5qdXNocmVlIFNvbWFzaGVrYXIoIHMzNzEyMjM3ICkiDQpkYXRlOiAiTUFUSDIzNDkgRGF0YSBQcmVwcm9jZXNzaW5nIG9uIFZpY3RvcmlhbiBhY2NpZGVudCBkYXRhIC0gQXNzaWdubWVudCAzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCiMjIyBJbnRyb2R1Y3Rpb24NCkluIFZpY3RvcmlhIHRoZXJlIGFyZSBpbiBleGNlc3Mgb2YgNSwwMDAsMDAwIGNhcnMgcmVnaXN0ZXJlZCB0byBWaWNSb2Fkcy4gQ3Jhc2ggc3RhdGlzdGljcyBhcmUgY2xvc2VseSBtb25pdG9yZWQgYnkgc2V2ZXJhbCBnb3Zlcm5tZW50IG9yZ2FuaXNhdGlvbnMuIEEgcmVkdWN0aW9uIGluIHRoZSByb2FkIHRvbGwgaXMgcGFyYW1vdW50IGluIHRoZSBzYXZpbmcgbGl2ZXMgb2YgVmljdG9yaWFuIGNpdGl6ZW5zLkNyYXNoIGRhdGEgaXMgaW5mb3JtYXRpb24gcmVjb3JkZWQgYnkgVmljUm9hZHMgYW5kIG1hZGUgcHVibGljbHkgYXZhaWxhYmxlIGF0IGRhdGEudmljLmdvdi5hdS4gVGhpcyBkYXRhc2V0IGNvbnRhaW5zIGFsbCBjcmFzaCBkYXRhIGZyb20gMXN0IEphbnVhcnkgMjAwNiB1cCB1bnRpbCAzcmQgQXVndXN0IDIwMTYuICBUaGUgVmljdG9yaWFuIEdvdmVybm1lbnQgaW4gMjAxMSByZWxlYXNlZCBhIHJlcG9ydCBpbnRvIHRoZSByb2FkIHRvbGwgYW5kIHRoZSBlZmZlY3QgdGhhdCByb2FkIHNhZmV0eSBjYW1lcmFzIChyZWQgbGlnaHQgYW5kIHNwZWVkIGNhbWVyYXMpIGhhcyBoYWQgb24gcmVkdWNpbmcgdGhlIG51bWJlciBvZiBkZWF0aHMgb24gdGhlIHJvYWQuIEl0IHdhcyBmb3VuZCB0aGF0IG1hbnkgdmFyaWFibGVzIGNvbnRyaWJ1dGVkIHRvIGRlYXRocyBvbiB0aGUgcm9hZCBpbmNsdWRpbmc6IHNwZWVkLCBmYXRpZ3VlLCByb2FkIGRlc2lnbiBldGMuIFRoZSByZXBvcnQgYWxzbyBmb3VuZCB0aGF0IHRoZXJlIHdlcmUgc2V2ZXJhbCBmYWN0b3JzIHRoYXQgbGVuZCB0aGVtc2VsdmVzIHRvIGhpZ2hlciByb2FkIHRvbGwgbnVtYmVycy4gDQpBY2NpZGVudC9jcmFzaCBkYXRhc2V0IGlzIG1lcmdlZCB3aXRoIEFDQ0lERU5UX05PLCBpZGVudGlmaWVkIG1pc3NpbmcgdmFsdWVzLCBleGNsdWRlZCB0aGUgb3V0bGllcnMsIGFwcGxpZWQgZGF0YSB0cmFuc2Zvcm1hdGlvbiBmb3IgZm9sbG93aW5nIHJlYXNvbnM6IGkpIHRvIGNoYW5nZSB0aGUgc2NhbGUgZm9yIGJldHRlciB1bmRlcnN0YW5kaW5nIG9mIHRoZSB2YXJpYWJsZSwgaWkpIHRvIGNvbnZlcnQgYSBub24tbGluZWFyIHJlbGF0aW9uIGludG8gbGluZWFyIG9uZSwgb3IgaWlpKSB0byBkZWNyZWFzZSB0aGUgc2tld25lc3MgYW5kIGNvbnZlcnQgdGhlIGRpc3RyaWJ1dGlvbiBpbnRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiANCg0KIyMjIFJlcXVpcmVkIHBhY2thZ2VzDQpgYGB7cn0NCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwbHlyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KE1WTikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeShvdXRsaWVycykNCmxpYnJhcnkoZm9yZWNhc3QpDQoNCnNldHdkKCJGOi9STUlUL3NlbTIvRGF0YSBQcmVwcm9jZXNzaW5nL2Fzc2lnbm1lbnQgMy8iKQ0KYWNjaWRlbnQgPC0gcmVhZC5jc3YoIkFDQ0lERU5ULmNzdiIsc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KYWNjX2NoaW5hZ2UgPC0gcmVhZC5jc3YoIkFDQ0lERU5UX0NIQUlOQUdFLmNzdiIpDQphY2NfZXZlbnQgPC0gcmVhZC5jc3YoIkFDQ0lERU5UX0VWRU5ULmNzdiIpDQphY2NfbG9jYXRpb24gPC0gcmVhZC5jc3YoIkFDQ0lERU5UX0xPQ0FUSU9OLmNzdiIpDQphY2NfYXRtb3NDb25kIDwtIHJlYWQuY3N2KCJBVE1PU1BIRVJJQ19DT05ELmNzdiIpDQphY2Nfbm9kZSA8LSByZWFkLmNzdigiTk9ERS5jc3YiKQ0KYWNjX25vZGVJZCA8LSByZWFkLmNzdigiTk9ERV9JRF9DT01QTEVYX0lOVF9JRC5jc3YiLHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCmFjY19wZXJzb24gPC0gcmVhZC5jc3YoIlBFUlNPTi5jc3YiKQ0KYWNjX3JkU3VyZmFjZUNvbmQgPC0gcmVhZC5jc3YoIlJPQURfU1VSRkFDRV9DT05ELmNzdiIpDQphY2Nfc3ViZGNhIDwtIHJlYWQuY3N2KCJTVUJEQ0EuY3N2IikNCmFjY192ZWhpY2xlIDwtIHJlYWQuY3N2KCJWRUhJQ0xFLmNzdiIgKQ0KDQojbWVyZ2luZyBhbGwgY3N2IGZpbGUgYnkgQUNDSURFTlRfTk8gYXMgSUQNCmFjY2lkZW50X2RmIDwtIGpvaW5fYWxsKGxpc3QoYWNjaWRlbnQsYWNjX2V2ZW50LGFjY19sb2NhdGlvbixhY2NfYXRtb3NDb25kLGFjY19ub2RlLGFjY19ub2RlSWQsYWNjX3BlcnNvbixhY2NfcmRTdXJmYWNlQ29uZCxhY2Nfc3ViZGNhLGFjY192ZWhpY2xlKSwgYnk9J0FDQ0lERU5UX05PJywgdHlwZT0nbGVmdCcpDQoNCnNhcHBseShhY2NpZGVudF9kZixjbGFzcykNCg0KDQpgYGANCg0KIyMjIElkZW50aWZ5aW5nIG1pc3NpbmcgdmFsdWVzDQoNCmBgYHtyfQ0KI0NPbmNlbnRyYXRpbmcgb24gbnVtYmVyIG9mIHBlb3BsZSBraWxsZWQgaW4gYWNjaWRlbnRzDQphY2Nfc2V2ZXJpdHkgPC0gYWNjaWRlbnRfZGZbKGFjY2lkZW50X2RmJE5PX1BFUlNPTlNfS0lMTEVEID4gMCksXQ0KDQojY2hhbmdlIHRvIGRhdGV0aW1lDQphY2Nfc2V2ZXJpdHkkQUNDSURFTlREQVRFIDwtIGFzLlBPU0lYY3Qoc3RycHRpbWUoYWNjX3NldmVyaXR5JEFDQ0lERU5UREFURSwgIiVkLyVtLyVZIikpDQojY2hhbmdpbmcgY2hhcmFjdGVyIHRvIGhtcw0KYWNjX3NldmVyaXR5JEFDQ0lERU5UVElNRSA8LSBobXMoYWNjX3NldmVyaXR5JEFDQ0lERU5UVElNRSkNCg0Kc2FwcGx5KGFjY19zZXZlcml0eSwgZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkNCg0KYGBgDQoNCklnbm9ybmluZyB0aGUgdmFyaWFibGVzIGNvbnNpc3RpbmcgbnVsbCB2YWx1ZXMgYmVjYXVzZSBmdXJ0aGVyIGFuYWx5c2lzIGRvc2VuJ3QgcmVxdWlyZSB0aG9zZSB2YXJpYWJsZXMgd2l0aCBudWxsIHZhbHVlcy4NCg0KIyMjIyBTdWJzZXR0aW5nIHRoZSBkYXRhDQpgYGB7cn0NCg0KbGlzdDEgPC0gYygiQUNDSURFTlRfTk8iLCJBQ0NJREVOVERBVEUiLCJBQ0NJREVOVFRJTUUiLCJBY2NpZGVudC5UeXBlLkRlc2MiLCJEQVlfT0ZfV0VFSyIsIkRheS5XZWVrLkRlc2NyaXB0aW9uIiwiRENBLkRlc2NyaXB0aW9uIiwiRElSRUNUT1JZIiwiTGlnaHQuQ29uZGl0aW9uLkRlc2MiLCJOT19PRl9WRUhJQ0xFUyIsIk5PX1BFUlNPTlMiLCJOT19QRVJTT05TX0tJTExFRCIsIlNQRUVEX1pPTkUiLCJFdmVudC5UeXBlLkRlc2MiLCJMYXQiLCJMb25nIiwiVmVoaWNsZS5UeXBlLkRlc2MiLCJTRVgiLCJBZ2UuR3JvdXAiKQ0KDQphY2NpZGVudCA8LSBhY2Nfc2V2ZXJpdHlbbGlzdDFdDQoNCnNhcHBseShhY2NpZGVudCwgZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkNCg0KYGBgDQoNCiMjIyBEYXRhIHNldCBzb3VyY2UgYW5kIGRlc2NyaXB0aW9uDQpUaGUgZGF0YSBpbiB0aGlzIHN0dWR5IHdhcyBzb3VyY2VkIGZyb20gVmljUm9hZHMgYW5kIHN0b3JlZCBvbiBkYXRhLnZpYy5nb3YuYXUsIHdoaWNoIGhhcyBhIGNvbXBpbGF0aW9uIG9mIGRhdGEgZnJvbSBhIHdpZGUgcmFuZ2Ugb2YgZ292ZXJubWVudCBzb3VyY2VzLiBUaGUgZGF0YSBzZXQgY29udGFpbnMgYSBjb2xsZWN0aW9uIG9mIDE0NSwxNTYgYWNjaWRlbnRzIGZvciB0aGUgcGFzdCBkZWNhZGUgYW5kIHJlY29yZHMgYmFzaWMgYWNjaWRlbnQgZGV0YWlscyBzdWNoIGFzOiBkYXkgb2YgdGhlIHdlZWssIGxpZ2h0IGNvbmRpdGlvbnMsIHNwZWVkIGxpbWl0LCB0eXBlIG9mDQphY2NpZGVudHMuDQouIEFDQ0lERU5UX05POiBUaGUgaWRlbnRpZmljYXRpb24gbnVtYmVyIGdpdmVuIHRvIGVhY2ggYWNjaWRlbnQgd2hlcmUgdGhlIDJuZCB0byA1dGggY2hhcmFyYWNodGVycw0KbWFrZSB1cCB0aGUgeWVhciB0aGF0IHRoZSBhY2NpZGVudCBvY2N1cmVkLg0KLiBBQ0NJREVOVERBVEU6IFRoZSBkYXRlIHRoYXQgZWFjaCBhY2NpZGVudCBvY2N1cmVkIC0gcmVjb3JkZWQgYXMgREQvTU0vWVlZLg0KLiBBQ0NJREVOVFRJTUU6IFRoZSB0aW1lIHRoYXQgdGhlIGFjY2lkZW50IG9jY3VyZWQgcmVjb3JkZWQgaW4gMjQgSG91ciB0aW1lDQouIEFDQ0lERU5UVFlQRSAmIEFjY2lkZW50IFR5cGUgRGVzYzogVmFyaWFibGVzIGRlc2NyaWJpbmcgdGhlIG5hdHVyZSBvZiB0aGUgYWNjaWRlbnQuIEFDQ0lERU5UVFlQRQ0KaXMgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSB3aXRoIHZhbHVlcyAxLTkgZGVzY3JpYmluZyB0aGUgdHlwZSBvZiBhY2NpZGVudCByZXNwZWN0aXZlIHRvIHRoZQ0KQWNjaWRlbnQgVHlwZSBEZXNjcmlwdGlvbiAoMT1Db2xsaXNpb24gd2l0aCB2ZWhpY2xlIDI9U3RydWNrIHBlZGVzdHJpYW4gMz1TdHJ1Y2sgYW5pbWFsIDQ9Q29sbGlzaW9uDQp3aXRoIGEgZml4ZWQgb2JqZWN0IDU9Q29sbGlzaW9uIHdpdGggc29tZSBvdGhlciBvYmplY3QgNj1WZWhpY2xlIG92ZXJ0dXJuZWQgKG5vIGNvbGxpc2lvbikgNz1GYWxsIGZyb20NCm9yIGluIG1vdmluZyB2ZWhpY2xlIDg9Tm8gY29sbGlzaW9uIGFuZCBubyBvYmplY3Qgc3RydWNrIDk9T3RoZXIgYWNjaWRlbnQpLg0KLiBEQVkgT0YgVEhFIFdFRUs6IFRoZSBkYXkgb2YgZWFjaCB3ZWVrIHRoYXQgdGhlIGFjY2lkZW50IHRvb2sgcGxhY2UgKDE9U3VuZGF5LDI9IE1vbmRheSwNCjM9VHVlc2RheSw0PVdlZG5lc2RheSw1PSBUaHVyc2RheSw2PUZyaWRheSBhbmQgNz1TYXR1cmRheSkNCjENCi4gTElHSFQgQ09ORElUSU9OOiBUaGUgbGV2ZWwgb2YgbGlnaHQgYXZhaWxhYmxlIGF0IHRoZSB0aW1lIG9mIHRoZSBhY2NpZGVudCAoMT1EYXksMj1EdXNrL2Rhd24sMz1EYXJrDQpzdHJlZXQgbGlnaHRzIG9uLDQ9RGFyayBzdHJlZXQgbGlnaHRzIG9mZiw1PURhcmsgbm8gc3RyZWV0IGxpZ2h0cyw2PURhcmsgc3RyZWV0IGxpZ2h0cyB1bmtub3duLA0KOT1Vbmtub3duKQ0KLiBTUEVFRCBaT05FOiBUaGUgc3BlZWQgbGltaXQgdGhhdCBpcyBlbmZvcmNlZCBhdCB0aGUgc2l0ZSBvZiB0aGUgYWNjaWRlbnQgKDA0MD00MCBrbS9ociwgMDUwPTUwDQprbS9ociwgMDYwPTYwIGttL2hyLCAwNzU9NzUga20vaHIsIDA4MD04MCBrbS9ociwgMDkwPTkwIGttL2hyLCAxMDA9MTAwIGttL2hyLCAxMTA9MTEwDQprbS9ociwgNzc3PU90aGVyIHNwZWVkIGxpbWl0LCA4ODg9Q2FtcGluZyBncm91bmRzL29mZiByb2FkLCA5OTk9Tm90IGtub3duKS4NCjINCg0KYGBge3J9DQphY2NpZGVudCR0aW1lX2NhdGVnb3J5IDwtIGlmZWxzZShob3VyKGFjY2lkZW50JEFDQ0lERU5UVElNRSkgPj0gMDUgJiBob3VyKGFjY2lkZW50JEFDQ0lERU5UVElNRSkgPD0gMTEsICJNb3JuaW5nIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShob3VyKGFjY2lkZW50JEFDQ0lERU5UVElNRSkgPiAxMSAmIGhvdXIoYWNjaWRlbnQkQUNDSURFTlRUSU1FKSA8PSAxNiwgIkFmdGVybm9vbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGhvdXIoYWNjaWRlbnQkQUNDSURFTlRUSU1FKSA+IDE2ICYgaG91cihhY2NpZGVudCRBQ0NJREVOVFRJTUUpIDw9IDE5LCAiRXZlbmluZyIsICJOaWdodCIpKSkNCg0KDQoNCmFjY2lkZW50JFNFQVNPTiA8LSBpZmVsc2UobW9udGgoYWNjaWRlbnQkQUNDSURFTlREQVRFKSA+PSAxMiAmIG1vbnRoKGFjY2lkZW50JEFDQ0lERU5UREFURSkgPD0gMiwgIlN1bW1lciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UobW9udGgoYWNjaWRlbnQkQUNDSURFTlREQVRFKSA+PSAzICYgbW9udGgoYWNjaWRlbnQkQUNDSURFTlREQVRFKSA8PSA1LCAiQXV0dW1uIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UobW9udGgoYWNjaWRlbnQkQUNDSURFTlREQVRFKSA+PSA2ICYgbW9udGgoYWNjaWRlbnQkQUNDSURFTlREQVRFKSA8PSA4LCAiV2ludGVyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShtb250aChhY2NpZGVudCRBQ0NJREVOVERBVEUpID49IDkgJiBtb250aChhY2NpZGVudCRBQ0NJREVOVERBVEUpIDw9IDExLCAiU3ByaW5nIiwiU3VtbWVyIikpKSkNCg0KYWNjaWRlbnQkaG91cmx5IDwtIGhvdXIoYWNjaWRlbnQkQUNDSURFTlRUSU1FKQ0KYWNjaWRlbnRfZnJlcSA8LSBhY2NpZGVudCAlPiUgDQogIGRwbHlyOjpncm91cF9ieShob3VybHksVmVoaWNsZS5UeXBlLkRlc2MsU1BFRURfWk9ORSkgJT4lIA0KICBkcGx5cjo6c3VtbWFyaXNlKGZyZXEgPSBzdW0oTk9fUEVSU09OU19LSUxMRUQpKQ0KDQpgYGANCg0KIyMjIE11bHRpdmFyaWF0ZSBPdXRsaWVyIERldGVjdGlvbg0KDQpgYGB7cn0NCmJveHBsb3QoYWNjaWRlbnRfZnJlcSRmcmVxIH4gYWNjaWRlbnRfZnJlcSRTUEVFRF9aT05FLCBtYWluPSJOTyBQRVJTT05TIEtJTExFRCB2cyBTUEVFRCBaT05FIiwgeWxhYiA9ICJOTy4gUEVSU09OUyBLSUxMRUQgZnJlcSIsIHhsYWIgPSAiU3BlZWQgWm9uZSIpDQpgYGANClRoZSBhYm92ZSBmaWd1cmUgaWxsdXN0cmF0ZXMgdGhlIGJpdmFyaWF0ZSBib3ggcGxvdCwgd2UgYXJlIGludGVyZXN0ZWQgaW4gU3BlZWRfem9uZSB2YXJpYWJsZSBhbmQgYSAiTm8ub2YgcGVvcGxlIGtpbGxlZCIgdmFyaWFibGUgaW4gdGhlIGFjY2lkZW50IGRhdGEgc2V0Lg0KQWNjb3JkaW5nIHRvIHRoZSBwbG90LCB0aGVyZSBhcmUgZmV3IG91dGxpZXJzIHdpdGggcmVzcGVjdCB0byB0aGUgc3BlZWQgem9uZXMuDQpUaGUgbXZuKCkgZnVuY3Rpb24gaXMgdXNlZCB0byBkaXNjb3ZlciBwb3NzaWJsZSBtdWx0aXZhcmlhdGUgb3V0bGllcnMNCmBgYHtyfQ0KIyBNdWx0aXZhcmlhdGUgb3V0bGllciBkZXRlY3Rpb24gdXNpbmcgTWFoYWxhbm9iaXMgZGlzdGFuY2Ugd2l0aCBRUSBwbG90cw0KYWNjaWRlbnRfZnJlcV9zdWIgPC0gYWNjaWRlbnRfZnJlcSAlPiUgZHBseXI6OnNlbGVjdChob3VybHksU1BFRURfWk9ORSxmcmVxKQ0KYWNjaWRlbnRfZnJlcV9zdWIkVmVoaWNsZS5UeXBlLkRlc2MgPC0gTlVMTA0KcmVzdWx0cyA8LSBtdm4oZGF0YSA9IGFjY2lkZW50X2ZyZXFfc3ViLCBtdWx0aXZhcmlhdGVPdXRsaWVyTWV0aG9kID0gInF1YW4iLCBzaG93T3V0bGllcnMgPSBUUlVFKQ0KYGBgDQoNCkFzIHdlIGNhbiBzZWUgb24gdGhlIFFRIHBsb3QsIHRoZSBNYWhhbG9ub2JpcyBkaXN0YW5jZSBzdWdnZXN0cyBleGlzdGVuY2Ugb2YgZmV3IG91dGxpZXJzIGZvciB0aGlzIHN1YnNldCBvZiB0aGUgYWNjaWRlbnQgZGF0YS4gDQpUaGUgbGlzdCBvZiBwb3NzaWJsZSBtdWx0aXZhcmlhdGUgb3V0bGllcnMgY2FuIGJlIGRpc3BsYXllZCBieSB1c2luZyByZXN1bHQkbXVsdGl2YXJpYXRlT3V0bGllcnMgdG8gc2VsZWN0IG9ubHkgdGhlIHJlc3VsdHMgcmVsYXRlZCB0byBvdXRsaWVycyBhcyBmb2xsb3dzOg0KDQpgYGB7cn0NCg0KcmVzdWx0cyRtdWx0aXZhcmlhdGVPdXRsaWVycw0KYGBgDQoNClRoaXMgb3V0cHV0IGlzIHByb3ZpZGluZyB0aGUgbG9jYXRpb25zIG9mIG91dGxpZXJzIGluIHRoZSBkYXRhIHNldC4gSW4gdGhpcyBwcm9qZWN0IHRoZXJlIGFyZSAzNjUgb2JzZXJ2YXRpb25zIHRoYXQgYXJlIHN1Z2dlc3RlZCBvdXRsaWVycyBmb3IgdGhpcyBzdWJzZXQgb2YgYWNjaWRlbnQgZGF0YS4NCkFyZ3VtZW50IHNob3dOZXdEYXRhID0gVFJVRSBpcyB1c2VkIHRvIGV4Y2x1ZGUgdGhlIG91dGxpZXJzLiBPbmUgY2FuIHNpbXBseSBkZXRlY3QgYW5kIHJlbW92ZSBvdXRsaWVycyB1c2luZyB0aGUgZm9sbG93aW5nIGFyZ3VtZW50Og0KDQpgYGB7cn0NCmFjY2lkZW50X2NsZWFuIDwtIG12bihkYXRhID0gYWNjaWRlbnRfZnJlcV9zdWIsIG11bHRpdmFyaWF0ZU91dGxpZXJNZXRob2QgPSAicXVhbiIsIHNob3dPdXRsaWVycyA9IFRSVUUsIHNob3dOZXdEYXRhID0gVFJVRSkNCmBgYA0KDQpgYGB7cn0NCiMgUHJpbnRzIHRoZSBkYXRhIHdpdGhvdXQgb3V0bGllcnMNCg0KZGltKGFjY2lkZW50X2NsZWFuJG5ld0RhdGEpDQoNCmBgYA0KDQpgYGB7cn0NCmhlYWQoYWNjaWRlbnRfY2xlYW4kbmV3RGF0YSkNCmBgYA0KDQojIyMgRGF0YSBUcmFuc2Zvcm1hdGlvbg0KDQojIyMjIE1hdGhlbWF0aWNhbCB0cmFuc2Zvcm1hdGlvbg0KVG8gYWNoaXZlIHRoZSBkYXRhIG5vcm1hbGl0eSwgd2UgYXJlIGFwcGx5aW5nIGRhdGEgdHJhbnNmb3JtYXRpb25zIHRocm91Z2ggbWF0aGVtYXRpY2FsIG9wZXJhdGlvbnMgbGlrZSBsb2dhcml0aG1pYyAoaS5lLiwgbG4gYW5kIGxvZyksIHNxdWFyZSByb290LCBwb3dlciB0cmFuc2Zvcm1hdGlvbnMgZXRjLiBhbmQgZmluYWxseSB3ZSB3aWxsIHNlbGVjdCB0aGUgYmVzdCB0cmFuc2Zvcm1hdGlvbi4NCg0KYGBge3J9DQpoaXN0KGFjY2lkZW50X2NsZWFuJG5ld0RhdGEkZnJlcSkNCmBgYA0KRnJvbSB0aGUgaGlzdG9ncmFtLCB3ZSBvYnNlcnZlIHRoYXQgZnJlcXVlbmN5IGNvdW50IGhhdmUgYSByaWdodC1za2V3ZWQgZGlzdHJpYnV0aW9uLiBCeSBhcHBseWluZyBhIGxvZ2FyaXRobWljIHRyYW5zZm9ybWF0aW9uLCB0aGUgc2FsYXJ5IGRpc3RyaWJ1dGlvbiB3b3VsZCBiZSBtb3JlIHN5bW1ldHJpY2FsLg0KDQojIyMjIyBMb2cxMCB0cmFuc2Zvcm1hdGlvbg0KDQpgYGB7cn0NCmxuX2ZsaXRlcl9hY2NfZmlsdCA8LSBsb2cxMChhY2NpZGVudF9jbGVhbiRuZXdEYXRhJGZyZXEpDQpoaXN0KGxuX2ZsaXRlcl9hY2NfZmlsdCkNCmBgYA0KIyMjIyMgTG9nIHRyYW5zZm9ybWF0aW9uDQoNCmBgYHtyfQ0KbG5fYWNjaWRlbnQgPC0gbG9nKGFjY2lkZW50X2NsZWFuJG5ld0RhdGEkZnJlcSkNCg0KaGlzdChsbl9hY2NpZGVudCkNCmBgYA0KDQoNCkFzIHNlZW4gZnJvbSB0aGUgaGlzdG9ncmFtcywgdGhlIGxvZzEwIHRyYW5zZm9ybWF0aW9uIHdvcmtlZCBzbGlnaHRseSBiZXR0ZXIgdGhhbiB0aGUgbG4gdHJhbnNmb3JtYXRpb24gZm9yIHRoaXMgZGF0YXNldC4gDQoNCkFub3RoZXIgdHJhbnNmb3JtYXRpb24gaXMgdGhlIHNxdWFyZSByb290IHRyYW5zZm9ybWF0aW9uLiBJdCBpcyBhbHNvIHVzZWQgZm9yIHJlZHVjaW5nIHJpZ2h0IHNrZXduZXNzLCBhbmQgYWxzbyBoYXMgdGhlIGFkdmFudGFnZSB0aGF0IGl0IGNhbiBiZSBhcHBsaWVkIHRvIHplcm8gdmFsdWVzLg0KDQojIyMjIyBTcXVhcmUgcm9vdCB0cmFuc2Zvcm1hdGlvbg0KYGBge3J9DQpzcXJ0X2FjY2lkZW50IDwtIHNxcnQoYWNjaWRlbnRfY2xlYW4kbmV3RGF0YSRmcmVxKQ0KaGlzdChzcXJ0X2FjY2lkZW50KQ0KYGBgDQpUaGUgc3F1YXJlIHJvb3QgdHJhbnNmb3JtYXRpb24gaGFzIHJlZHVjZWQgdGhlIHNrZXduZXNzIGluIHRoZSBhY2NpZGVudCBmcmVxdWVuY3kgY291bnQgZGlzdHJpYnV0aW9uLiBCdXQgc3RpbGwgd2UgY2FuIHNlZSBmb3IgbW9yZSB0cmFuc2Zvcm1hdGlvbnMgdG8gY29uZmlybSB0aGUgYmV0dGVyIG9uZS4NCg0KIyMjIyMgcmVjaXByb2NhbCB0cmFuc2Zvcm1hdGlvbg0KYGBge3J9DQpyZWNpcF9mbGl0ZXJfYWNjX2ZpbHQgPC0gMS8oYWNjaWRlbnRfY2xlYW4kbmV3RGF0YSRmcmVxKQ0KaGlzdChyZWNpcF9mbGl0ZXJfYWNjX2ZpbHQpDQpgYGANCg0KIyMjIyMgQm94LUNveCBUcmFuc2Zvcm1hdGlvbg0KDQpgYGB7cn0NCg0KYm94Y294X2FjY19maWx0PC0gQm94Q294KGFjY2lkZW50X2NsZWFuJG5ld0RhdGEkZnJlcSxsYW1iZGEgPSAiYXV0byIpDQoNCmhpc3QoYm94Y294X2FjY19maWx0KQ0KYGBgDQpBZnRlciB0cnlpbmcgb3V0IG1hbnkgdHJhbnNmb3JtYXRpb25zLCBzcXVhcmUgcm9vdCB0cmFuc2Zvcm1hdGlvbiBoYXMgcmVkdWNlZCB0aGUgc2tld25lc3MgaW4gdGhlIGFjY2lkZW50IGZyZXF1ZW5jeSBjb3VudCBkaXN0cmlidXRpb24NCg0KDQojIyMgRGF0YSBOb3JtYWxpc2F0aW9uDQoNCiMjIyMjIHogc2NvcmUgc3RhbmRhcmRpc2F0aW9uDQpgYGB7cn0NCmNlbnRlcl94IDwtc2NhbGUoc3FydF9hY2NpZGVudCwgY2VudGVyID0gVFJVRSwgc2NhbGUgPSBUUlVFKQ0KDQpoaXN0KGNlbnRlcl94KQ0KDQpgYGANCg0KVGhlIHJlc3VsdGluZyB0cmFuc2Zvcm1lZCBkYXRhIHZhbHVlcyB3b3VsZCBoYXZlIGEgemVybyBtZWFuIGFuZCBvbmUgc3RhbmRhcmQgZGV2aWF0aW9uLg0KDQoNCg0KDQoNCg0K