Rats HW OIDD 2450

Install Packages

install.packages(“TeachingDemos”) install.packages(“readr”) install.packages(“tidyverse”) install.packages(“lubridate”) install.packages(“readr”) install.packages(“ggplot2”) install.packages(“rlang”) install.packages(“htmltools”) install.packages(“htmlwidgets”) install.packages(“shiny”)

library(TeachingDemos)
library(lubridate)
library(readr)
library(dplyr)
library(tidyverse)
library(ggplot2)
library(rlang)
library(htmltools)
library(htmlwidgets)
library(shiny)

rod.inspection = read_csv("rodent_inspection.csv")
Rows: 939924 Columns: 20── Column specification ───────────────────────────────
Delimiter: ","
chr (11): INSPECTION_TYPE, JOB_ID, BLOCK, LOT, HOUS...
dbl  (9): JOB_TICKET_OR_WORK_ORDER_ID, JOB_PROGRESS...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
myname = "Mattison Boveri"

# Then run the following lines
set.seed(char2seed(myname))
rod.inspection = sample_frac(rod.inspection, .8)
rod.inspection = rod.inspection[, sample(1:ncol(rod.inspection))]

# Part 1, A

# Fix the date format
rod.inspection$INSPECTION_DATE <- as.POSIXct(rod.inspection$INSPECTION_DATE, format = "%m/%d/%Y %I:%M:%S %p")

# Make RESULTS column numeric
rod.inspection$RESULT <- ifelse(rod.inspection$RESULT == "Active Rat Signs", 1, 0)

# Collect data from 2011 - 2016
rod.inspection <- rod.inspection %>%
  mutate(INSPECTION_DATE = if_else(INSPECTION_DATE >= as.Date("2011-01-01"), INSPECTION_DATE, NA))

# Delete data from before 2011
rod.inspection <- rod.inspection[complete.cases(rod.inspection$INSPECTION_DATE), ]

# Format data
rod.inspection <- rod.inspection %>%
  mutate(month_year = format(ymd_hms(INSPECTION_DATE), "%Y-%m"),
         year = year(ymd_hms(INSPECTION_DATE)),
         month = month(ymd_hms(INSPECTION_DATE), label = TRUE))

# Aggregate data by month and year for each borough
rod.agg <- rod.inspection %>%
  group_by(BOROUGH, month_year, year, month) %>%
  summarise(active_rat_signs = sum(RESULT))
`summarise()` has grouped output by 'BOROUGH', 'month_year', 'year'. You can override using the `.groups` argument.
# Create line chart
graph = ggplot(data = rod.agg, aes(x = month_year, y = active_rat_signs, color = BOROUGH, group = BOROUGH)) +
  theme(axis.text.x = element_text(angle = -90, hjust = 0)) +
  theme(plot.margin = unit(c(1, 0.5, 1, 1), "cm")) + 
  geom_line() +
  labs(x = "Month and Year", 
       y = "Number of Active Rate Signs", 
       title = "Monthly Trend of Rat Sightings by Borough",
       color = "Borough")
 
graph

Rat sightings over the past 5 years have remained the same.

Rat sightings normally decrease during the winter months from December until February and the rat sightings increase again starting in March until June.

# Part 1, D
# Find the Efficiency
efficiency <- rod.inspection %>% 
  group_by(BOROUGH, month_year) %>% 
  summarize(rod.inspection = n(),
            active_rat_signs = sum(RESULT),
            Efficiency = active_rat_signs / rod.inspection)
`summarise()` has grouped output by 'BOROUGH'. You can override using the `.groups` argument.
# Graph the Efficiency of rat inspections
graph2 = ggplot(data = efficiency, aes(x = month_year, y = Efficiency, color = BOROUGH, group = BOROUGH)) +
  theme(axis.text.x = element_text(angle = -90, hjust = 0)) +
  theme(plot.margin = unit(c(1, 0.5, 1, 1), "cm")) + 
  geom_line() +
  labs(x = "Month and Year", 
       y = "Efficiency", 
       title = "Efficiency of Rat Inspections by Borough",
       color = "Borough")

graph2



# Part 1, E

# Find the top 10 zipcodes
efficiency_zipcode <- rod.inspection %>% 
  group_by(BOROUGH, month_year, ZIP_CODE) %>% 
  summarize(rod.inspection = n(),
            active_rat_signs = sum(RESULT),
            Efficiency = active_rat_signs / rod.inspection)
`summarise()` has grouped output by 'BOROUGH', 'month_year'. You can override using the `.groups` argument.
top_10_zipcodes <- efficiency_zipcode %>%
  arrange(desc(Efficiency)) %>%
  head(10) %>%
  select(ZIP_CODE)
Adding missing grouping variables: `BOROUGH`, `month_year`
# View the top 10 zip codes in descending order by efficiency
print(top_10_zipcodes)


# Part 2, A

complaints <- read.csv("sandyrelated.csv")

# Filter to find all Rodent complaints
rodent_complaints <- complaints %>%
  filter(Complaint.Type == "Rodent")

# Create a new column to differentiate between complaints before and after sandy
rodent_complaints <- rodent_complaints %>%
  mutate(before_sandy = if_else(Created.Date < "10/29/12", 1, 0))

# Find a numeric value for before and after sandy
complaints_before <- sum(rodent_complaints$before_sandy)
complaints_after <- nrow(rodent_complaints) - complaints_before

# Create a vector with the two variables
complaints <- c(complaints_before, complaints_after)

# Create a barplot with the vector as input
barplot(complaints, 
        names.arg = c("Before Sandy", "After Sandy"), 
        xlab = "Time Period", 
        ylab = "Number of Complaints", 
        main = "Rodent Complaints Before and After Hurricane Sandy")

The data suggests that Hurricane Sandy led to an increase in rodent sightings on the island because there were more rodent complaints in the weeks following the hurricane.

# Part 2, B

complaints <- read.csv("sandyrelated.csv")

# Find all non-rodent complaints
non_rodent_complaints <- complaints %>%
  filter(Complaint.Type != "Rodent")

# Group by complaint type and count number of complaints
complaint_counts <- non_rodent_complaints %>%
  group_by(Complaint.Type) %>%
  summarize(Count = n()) %>%
  ungroup()

# Sort by count and select top 15 complaint types
top_complaint_types <- complaint_counts %>%
  arrange(desc(Count)) %>%
  head(15)

# View the top 15 complaint types and their counts
top_complaint_types



# Create a new data frame with the top 15 non-rodent complaints and rodent complaints
top_complaints <- c(top_complaint_types$Complaint.Type, "Rodent")
complaints_subset <- complaints %>%
  filter(Complaint.Type %in% top_complaints)

# Group by complaint type and zip code and count number of complaints
complaint_counts <- complaints_subset %>%
  group_by(Incident.Zip, Complaint.Type) %>%
  summarize(Count = n()) %>%
  ungroup()
`summarise()` has grouped output by 'Incident.Zip'. You can override using the `.groups` argument.
# Get rid of rows without zipcodes
complaint_counts <- complaint_counts %>%
  filter(as.numeric(Incident.Zip) >= 1000)
Warning: There was 1 warning in `filter()`.
ℹ In argument: `as.numeric(Incident.Zip) >= 1000`.
Caused by warning:
! NAs introduced by coercion
# View the resulting data frame
head(complaint_counts)

complaint_counts_wide <- complaint_counts %>%
  pivot_wider(names_from = Complaint.Type, values_from = Count, values_fill = 0)

# Get rid of the Incident Zip column
complaint_counts_wide_nozip <- complaint_counts_wide %>%
  select(-Incident.Zip) 

# Find the correlations
complaint_correlations <- cor(complaint_counts_wide_nozip)
rodent_correlations <- complaint_correlations["Rodent", ]

rodent_correlations
           Consumer Complaint 
                   0.11494767 
                 Damaged Tree 
                  -0.10293178 
                     ELECTRIC 
                   0.40108714 
         GENERAL CONSTRUCTION 
                   0.59992869 
General Construction/Plumbing 
                   0.26319429 
                      HEATING 
                   0.60705494 
                     NONCONST 
                   0.68215526 
              PAINT - PLASTER 
                   0.56843051 
                     PLUMBING 
                   0.62028448 
                       Rodent 
                   1.00000000 
                        Sewer 
                   0.10801506 
             Street Condition 
                   0.25272826 
                 Water System 
                   0.04584400 
             Blocked Driveway 
                   0.20435230 
       Street Light Condition 
                   0.08343904 
     Traffic Signal Condition 
                   0.15980346 

The two complaint types most highly correlated with rodent sightings were NONCONST and PLUMBING.

# PART 3

inspections <- read.csv("dohmh.csv", stringsAsFactors = FALSE)

# Convert INSPECTION.DATE to a Date object
inspections$INSPECTION.DATE <- as.Date(inspections$INSPECTION.DATE, format = "%m/%d/%Y")

# Extract month and year as a string
inspections$MonthYear <- format(inspections$INSPECTION.DATE, "%m-%Y")

# Find all rodent violations from the violation codes
rodent_violations <- inspections %>%
  filter(VIOLATION.CODE %in% c("04L", "04K", "08A")) %>%
  select(MonthYear, ZIPCODE)

# Count rodent violations by month, year, and zipcode
rodent_counts <- rodent_violations %>%
  group_by(MonthYear, ZIPCODE) %>%
  summarize(RestaurantRatViolations = n())
`summarise()` has grouped output by 'MonthYear'. You can override using the `.groups` argument.
rodent_inspections = read_csv("rodent_inspection.csv")
Rows: 939924 Columns: 20── Column specification ───────────────────────────────
Delimiter: ","
chr (11): INSPECTION_TYPE, JOB_ID, BLOCK, LOT, HOUS...
dbl  (9): JOB_TICKET_OR_WORK_ORDER_ID, JOB_PROGRESS...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Convert INSPECTION DATE column to Date format
rodent_inspections$INSPECTION_DATE <- as.Date(rodent_inspections$INSPECTION_DATE, format = "%m/%d/%Y")

# Create MonthYear column from INSPECTION DATE
rodent_inspections$MonthYear <- format(rodent_inspections$INSPECTION_DATE, "%m-%Y")

names(rodent_inspections)[names(rodent_inspections) == "ZIP_CODE"] <- "ZIPCODE"

# Merge with rodent violation data
merged_data <- merge(rodent_inspections, rodent_counts, by = c("ZIPCODE", "MonthYear"))

merged_data$RESULT <- ifelse(merged_data$RESULT == "Active Rat Signs", 1, 0)

# Create separate month and year columns
merged_data$month <- as.numeric(substr(merged_data$MonthYear, 1, 2))
merged_data$year <- as.numeric(substr(merged_data$MonthYear, 4, 7))

# Create train and test cases
train = merged_data[1:(0.8*nrow(merged_data)),]
test = merged_data[-(1:(0.8*nrow(merged_data))),]

# Run the model
model <- glm(RESULT ~ log(RestaurantRatViolations + 1) + month + year, data = merged_data, family = binomial())
summary(model)

Call:
glm(formula = RESULT ~ log(RestaurantRatViolations + 1) + month + 
    year, family = binomial(), data = merged_data)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-0.5806  -0.5266  -0.5061  -0.4808   2.1726  

Coefficients:
                                   Estimate Std. Error
(Intercept)                      -1.141e+02  7.809e+00
log(RestaurantRatViolations + 1)  7.206e-02  5.653e-03
month                            -3.379e-03  1.296e-03
year                              5.559e-02  3.879e-03
                                 z value Pr(>|z|)    
(Intercept)                      -14.607  < 2e-16 ***
log(RestaurantRatViolations + 1)  12.747  < 2e-16 ***
month                             -2.607  0.00914 ** 
year                              14.331  < 2e-16 ***
---
Signif. codes:  
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 392274  on 527643  degrees of freedom
Residual deviance: 391624  on 527640  degrees of freedom
  (2 observations deleted due to missingness)
AIC: 391632

Number of Fisher Scoring iterations: 4

The coefficient for log(RestaurantRatViolations + 1) is positive and statistically significant, indicating that higher values of Restaurant Rat Violations are associated with higher log adds of the outcome variable (Active Rat Signs). The coefficient for month is negative and statistically significant, indicating that later months (higher values of month) are associated with lower log odds of the outcome variable (Active Rat Signs). The coefficient for year is positive and statistically significant, indicating that later years (higher values of year) are associated with higher log odds of the outcome variable (Active Rat Signs). This evidence indicates that Restaurant Rat Violations, month, and year are all important predictors of the outcome variable (Active Rat Signs).

# PART 4, A

Another area to explore in conjunction with the NYC rat data would be DSNY Litter Basket data. This data set contains information about litter baskets located around NYC. https://data.cityofnewyork.us/dataset/DSNY-Litter-Basket-Map-/d6m8-cwh9 I would like to use this data to see if litter basket location correlates with active rat sightings around the city. I would download the data from the NYC Open Data website and merge the data with the Rodent Inspection data set based on location using GPS coordinates. I would like to do some analysis on correlation between litter basket location and active rat sightings. I would also like to create a chart based on the different boroughs and see how number of litter baskets and active rat sightings vary by borough.

LS0tDQp0aXRsZTogIlJhdHMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KUmF0cyBIVyBPSUREIDI0NTANCg0KDQpJbnN0YWxsIFBhY2thZ2VzIA0KDQppbnN0YWxsLnBhY2thZ2VzKCJUZWFjaGluZ0RlbW9zIikNCmluc3RhbGwucGFja2FnZXMoInJlYWRyIikNCmluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQppbnN0YWxsLnBhY2thZ2VzKCJsdWJyaWRhdGUiKQ0KaW5zdGFsbC5wYWNrYWdlcygicmVhZHIiKQ0KaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQppbnN0YWxsLnBhY2thZ2VzKCJybGFuZyIpDQppbnN0YWxsLnBhY2thZ2VzKCJodG1sdG9vbHMiKQ0KaW5zdGFsbC5wYWNrYWdlcygiaHRtbHdpZGdldHMiKQ0KaW5zdGFsbC5wYWNrYWdlcygic2hpbnkiKQ0KYGBge3J9DQpsaWJyYXJ5KFRlYWNoaW5nRGVtb3MpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJsYW5nKQ0KbGlicmFyeShodG1sdG9vbHMpDQpsaWJyYXJ5KGh0bWx3aWRnZXRzKQ0KbGlicmFyeShzaGlueSkNCg0Kcm9kLmluc3BlY3Rpb24gPSByZWFkX2Nzdigicm9kZW50X2luc3BlY3Rpb24uY3N2IikNCg0KbXluYW1lID0gIk1hdHRpc29uIEJvdmVyaSINCg0KIyBUaGVuIHJ1biB0aGUgZm9sbG93aW5nIGxpbmVzDQpzZXQuc2VlZChjaGFyMnNlZWQobXluYW1lKSkNCnJvZC5pbnNwZWN0aW9uID0gc2FtcGxlX2ZyYWMocm9kLmluc3BlY3Rpb24sIC44KQ0Kcm9kLmluc3BlY3Rpb24gPSByb2QuaW5zcGVjdGlvblssIHNhbXBsZSgxOm5jb2wocm9kLmluc3BlY3Rpb24pKV0NCg0KIyBQYXJ0IDEsIEENCg0KIyBGaXggdGhlIGRhdGUgZm9ybWF0DQpyb2QuaW5zcGVjdGlvbiRJTlNQRUNUSU9OX0RBVEUgPC0gYXMuUE9TSVhjdChyb2QuaW5zcGVjdGlvbiRJTlNQRUNUSU9OX0RBVEUsIGZvcm1hdCA9ICIlbS8lZC8lWSAlSTolTTolUyAlcCIpDQoNCiMgTWFrZSBSRVNVTFRTIGNvbHVtbiBudW1lcmljDQpyb2QuaW5zcGVjdGlvbiRSRVNVTFQgPC0gaWZlbHNlKHJvZC5pbnNwZWN0aW9uJFJFU1VMVCA9PSAiQWN0aXZlIFJhdCBTaWducyIsIDEsIDApDQoNCiMgQ29sbGVjdCBkYXRhIGZyb20gMjAxMSAtIDIwMTYNCnJvZC5pbnNwZWN0aW9uIDwtIHJvZC5pbnNwZWN0aW9uICU+JQ0KICBtdXRhdGUoSU5TUEVDVElPTl9EQVRFID0gaWZfZWxzZShJTlNQRUNUSU9OX0RBVEUgPj0gYXMuRGF0ZSgiMjAxMS0wMS0wMSIpLCBJTlNQRUNUSU9OX0RBVEUsIE5BKSkNCg0KIyBEZWxldGUgZGF0YSBmcm9tIGJlZm9yZSAyMDExDQpyb2QuaW5zcGVjdGlvbiA8LSByb2QuaW5zcGVjdGlvbltjb21wbGV0ZS5jYXNlcyhyb2QuaW5zcGVjdGlvbiRJTlNQRUNUSU9OX0RBVEUpLCBdDQoNCiMgRm9ybWF0IGRhdGENCnJvZC5pbnNwZWN0aW9uIDwtIHJvZC5pbnNwZWN0aW9uICU+JQ0KICBtdXRhdGUobW9udGhfeWVhciA9IGZvcm1hdCh5bWRfaG1zKElOU1BFQ1RJT05fREFURSksICIlWS0lbSIpLA0KICAgICAgICAgeWVhciA9IHllYXIoeW1kX2htcyhJTlNQRUNUSU9OX0RBVEUpKSwNCiAgICAgICAgIG1vbnRoID0gbW9udGgoeW1kX2htcyhJTlNQRUNUSU9OX0RBVEUpLCBsYWJlbCA9IFRSVUUpKQ0KDQojIEFnZ3JlZ2F0ZSBkYXRhIGJ5IG1vbnRoIGFuZCB5ZWFyIGZvciBlYWNoIGJvcm91Z2gNCnJvZC5hZ2cgPC0gcm9kLmluc3BlY3Rpb24gJT4lDQogIGdyb3VwX2J5KEJPUk9VR0gsIG1vbnRoX3llYXIsIHllYXIsIG1vbnRoKSAlPiUNCiAgc3VtbWFyaXNlKGFjdGl2ZV9yYXRfc2lnbnMgPSBzdW0oUkVTVUxUKSkNCg0KIyBDcmVhdGUgbGluZSBjaGFydA0KZ3JhcGggPSBnZ3Bsb3QoZGF0YSA9IHJvZC5hZ2csIGFlcyh4ID0gbW9udGhfeWVhciwgeSA9IGFjdGl2ZV9yYXRfc2lnbnMsIGNvbG9yID0gQk9ST1VHSCwgZ3JvdXAgPSBCT1JPVUdIKSkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IC05MCwgaGp1c3QgPSAwKSkgKw0KICB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygxLCAwLjUsIDEsIDEpLCAiY20iKSkgKyANCiAgZ2VvbV9saW5lKCkgKw0KICBsYWJzKHggPSAiTW9udGggYW5kIFllYXIiLCANCiAgICAgICB5ID0gIk51bWJlciBvZiBBY3RpdmUgUmF0ZSBTaWducyIsIA0KICAgICAgIHRpdGxlID0gIk1vbnRobHkgVHJlbmQgb2YgUmF0IFNpZ2h0aW5ncyBieSBCb3JvdWdoIiwNCiAgICAgICBjb2xvciA9ICJCb3JvdWdoIikNCiANCmdyYXBoDQpgYGANClJhdCBzaWdodGluZ3Mgb3ZlciB0aGUgcGFzdCA1IHllYXJzIGhhdmUgcmVtYWluZWQgdGhlIHNhbWUuDQoNClJhdCBzaWdodGluZ3Mgbm9ybWFsbHkgZGVjcmVhc2UgZHVyaW5nIHRoZSB3aW50ZXIgbW9udGhzIGZyb20gRGVjZW1iZXIgdW50aWwgRmVicnVhcnkgYW5kIHRoZSByYXQgc2lnaHRpbmdzIGluY3JlYXNlIGFnYWluIHN0YXJ0aW5nIGluIE1hcmNoIHVudGlsIEp1bmUuDQpgYGB7cn0NCiMgUGFydCAxLCBEDQojIEZpbmQgdGhlIEVmZmljaWVuY3kNCmVmZmljaWVuY3kgPC0gcm9kLmluc3BlY3Rpb24gJT4lIA0KICBncm91cF9ieShCT1JPVUdILCBtb250aF95ZWFyKSAlPiUgDQogIHN1bW1hcml6ZShyb2QuaW5zcGVjdGlvbiA9IG4oKSwNCiAgICAgICAgICAgIGFjdGl2ZV9yYXRfc2lnbnMgPSBzdW0oUkVTVUxUKSwNCiAgICAgICAgICAgIEVmZmljaWVuY3kgPSBhY3RpdmVfcmF0X3NpZ25zIC8gcm9kLmluc3BlY3Rpb24pDQoNCiMgR3JhcGggdGhlIEVmZmljaWVuY3kgb2YgcmF0IGluc3BlY3Rpb25zDQpncmFwaDIgPSBnZ3Bsb3QoZGF0YSA9IGVmZmljaWVuY3ksIGFlcyh4ID0gbW9udGhfeWVhciwgeSA9IEVmZmljaWVuY3ksIGNvbG9yID0gQk9ST1VHSCwgZ3JvdXAgPSBCT1JPVUdIKSkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IC05MCwgaGp1c3QgPSAwKSkgKw0KICB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygxLCAwLjUsIDEsIDEpLCAiY20iKSkgKyANCiAgZ2VvbV9saW5lKCkgKw0KICBsYWJzKHggPSAiTW9udGggYW5kIFllYXIiLCANCiAgICAgICB5ID0gIkVmZmljaWVuY3kiLCANCiAgICAgICB0aXRsZSA9ICJFZmZpY2llbmN5IG9mIFJhdCBJbnNwZWN0aW9ucyBieSBCb3JvdWdoIiwNCiAgICAgICBjb2xvciA9ICJCb3JvdWdoIikNCg0KZ3JhcGgyDQoNCg0KIyBQYXJ0IDEsIEUNCg0KIyBGaW5kIHRoZSB0b3AgMTAgemlwY29kZXMNCmVmZmljaWVuY3lfemlwY29kZSA8LSByb2QuaW5zcGVjdGlvbiAlPiUgDQogIGdyb3VwX2J5KEJPUk9VR0gsIG1vbnRoX3llYXIsIFpJUF9DT0RFKSAlPiUgDQogIHN1bW1hcml6ZShyb2QuaW5zcGVjdGlvbiA9IG4oKSwNCiAgICAgICAgICAgIGFjdGl2ZV9yYXRfc2lnbnMgPSBzdW0oUkVTVUxUKSwNCiAgICAgICAgICAgIEVmZmljaWVuY3kgPSBhY3RpdmVfcmF0X3NpZ25zIC8gcm9kLmluc3BlY3Rpb24pDQoNCg0KdG9wXzEwX3ppcGNvZGVzIDwtIGVmZmljaWVuY3lfemlwY29kZSAlPiUNCiAgYXJyYW5nZShkZXNjKEVmZmljaWVuY3kpKSAlPiUNCiAgaGVhZCgxMCkgJT4lDQogIHNlbGVjdChaSVBfQ09ERSkNCg0KIyBWaWV3IHRoZSB0b3AgMTAgemlwIGNvZGVzIGluIGRlc2NlbmRpbmcgb3JkZXIgYnkgZWZmaWNpZW5jeQ0KcHJpbnQodG9wXzEwX3ppcGNvZGVzKQ0KDQoNCiMgUGFydCAyLCBBDQoNCmNvbXBsYWludHMgPC0gcmVhZC5jc3YoInNhbmR5cmVsYXRlZC5jc3YiKQ0KDQojIEZpbHRlciB0byBmaW5kIGFsbCBSb2RlbnQgY29tcGxhaW50cw0Kcm9kZW50X2NvbXBsYWludHMgPC0gY29tcGxhaW50cyAlPiUNCiAgZmlsdGVyKENvbXBsYWludC5UeXBlID09ICJSb2RlbnQiKQ0KDQojIENyZWF0ZSBhIG5ldyBjb2x1bW4gdG8gZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIGNvbXBsYWludHMgYmVmb3JlIGFuZCBhZnRlciBzYW5keQ0Kcm9kZW50X2NvbXBsYWludHMgPC0gcm9kZW50X2NvbXBsYWludHMgJT4lDQogIG11dGF0ZShiZWZvcmVfc2FuZHkgPSBpZl9lbHNlKENyZWF0ZWQuRGF0ZSA8ICIxMC8yOS8xMiIsIDEsIDApKQ0KDQojIEZpbmQgYSBudW1lcmljIHZhbHVlIGZvciBiZWZvcmUgYW5kIGFmdGVyIHNhbmR5DQpjb21wbGFpbnRzX2JlZm9yZSA8LSBzdW0ocm9kZW50X2NvbXBsYWludHMkYmVmb3JlX3NhbmR5KQ0KY29tcGxhaW50c19hZnRlciA8LSBucm93KHJvZGVudF9jb21wbGFpbnRzKSAtIGNvbXBsYWludHNfYmVmb3JlDQoNCiMgQ3JlYXRlIGEgdmVjdG9yIHdpdGggdGhlIHR3byB2YXJpYWJsZXMNCmNvbXBsYWludHMgPC0gYyhjb21wbGFpbnRzX2JlZm9yZSwgY29tcGxhaW50c19hZnRlcikNCg0KIyBDcmVhdGUgYSBiYXJwbG90IHdpdGggdGhlIHZlY3RvciBhcyBpbnB1dA0KYmFycGxvdChjb21wbGFpbnRzLCANCiAgICAgICAgbmFtZXMuYXJnID0gYygiQmVmb3JlIFNhbmR5IiwgIkFmdGVyIFNhbmR5IiksIA0KICAgICAgICB4bGFiID0gIlRpbWUgUGVyaW9kIiwgDQogICAgICAgIHlsYWIgPSAiTnVtYmVyIG9mIENvbXBsYWludHMiLCANCiAgICAgICAgbWFpbiA9ICJSb2RlbnQgQ29tcGxhaW50cyBCZWZvcmUgYW5kIEFmdGVyIEh1cnJpY2FuZSBTYW5keSIpDQoNCmBgYA0KVGhlIGRhdGEgc3VnZ2VzdHMgdGhhdCBIdXJyaWNhbmUgU2FuZHkgbGVkIHRvIGFuIGluY3JlYXNlIGluIHJvZGVudCBzaWdodGluZ3Mgb24gdGhlIGlzbGFuZCBiZWNhdXNlIHRoZXJlIHdlcmUgbW9yZSByb2RlbnQgY29tcGxhaW50cyBpbiB0aGUgd2Vla3MgZm9sbG93aW5nIHRoZSBodXJyaWNhbmUuDQoNCmBgYHtyfQ0KIyBQYXJ0IDIsIEINCg0KY29tcGxhaW50cyA8LSByZWFkLmNzdigic2FuZHlyZWxhdGVkLmNzdiIpDQoNCiMgRmluZCBhbGwgbm9uLXJvZGVudCBjb21wbGFpbnRzDQpub25fcm9kZW50X2NvbXBsYWludHMgPC0gY29tcGxhaW50cyAlPiUNCiAgZmlsdGVyKENvbXBsYWludC5UeXBlICE9ICJSb2RlbnQiKQ0KDQojIEdyb3VwIGJ5IGNvbXBsYWludCB0eXBlIGFuZCBjb3VudCBudW1iZXIgb2YgY29tcGxhaW50cw0KY29tcGxhaW50X2NvdW50cyA8LSBub25fcm9kZW50X2NvbXBsYWludHMgJT4lDQogIGdyb3VwX2J5KENvbXBsYWludC5UeXBlKSAlPiUNCiAgc3VtbWFyaXplKENvdW50ID0gbigpKSAlPiUNCiAgdW5ncm91cCgpDQoNCiMgU29ydCBieSBjb3VudCBhbmQgc2VsZWN0IHRvcCAxNSBjb21wbGFpbnQgdHlwZXMNCnRvcF9jb21wbGFpbnRfdHlwZXMgPC0gY29tcGxhaW50X2NvdW50cyAlPiUNCiAgYXJyYW5nZShkZXNjKENvdW50KSkgJT4lDQogIGhlYWQoMTUpDQoNCiMgVmlldyB0aGUgdG9wIDE1IGNvbXBsYWludCB0eXBlcyBhbmQgdGhlaXIgY291bnRzDQp0b3BfY29tcGxhaW50X3R5cGVzDQoNCg0KDQojIENyZWF0ZSBhIG5ldyBkYXRhIGZyYW1lIHdpdGggdGhlIHRvcCAxNSBub24tcm9kZW50IGNvbXBsYWludHMgYW5kIHJvZGVudCBjb21wbGFpbnRzDQp0b3BfY29tcGxhaW50cyA8LSBjKHRvcF9jb21wbGFpbnRfdHlwZXMkQ29tcGxhaW50LlR5cGUsICJSb2RlbnQiKQ0KY29tcGxhaW50c19zdWJzZXQgPC0gY29tcGxhaW50cyAlPiUNCiAgZmlsdGVyKENvbXBsYWludC5UeXBlICVpbiUgdG9wX2NvbXBsYWludHMpDQoNCiMgR3JvdXAgYnkgY29tcGxhaW50IHR5cGUgYW5kIHppcCBjb2RlIGFuZCBjb3VudCBudW1iZXIgb2YgY29tcGxhaW50cw0KY29tcGxhaW50X2NvdW50cyA8LSBjb21wbGFpbnRzX3N1YnNldCAlPiUNCiAgZ3JvdXBfYnkoSW5jaWRlbnQuWmlwLCBDb21wbGFpbnQuVHlwZSkgJT4lDQogIHN1bW1hcml6ZShDb3VudCA9IG4oKSkgJT4lDQogIHVuZ3JvdXAoKQ0KDQojIEdldCByaWQgb2Ygcm93cyB3aXRob3V0IHppcGNvZGVzDQpjb21wbGFpbnRfY291bnRzIDwtIGNvbXBsYWludF9jb3VudHMgJT4lDQogIGZpbHRlcihhcy5udW1lcmljKEluY2lkZW50LlppcCkgPj0gMTAwMCkNCg0KIyBWaWV3IHRoZSByZXN1bHRpbmcgZGF0YSBmcmFtZQ0KaGVhZChjb21wbGFpbnRfY291bnRzKQ0KDQpjb21wbGFpbnRfY291bnRzX3dpZGUgPC0gY29tcGxhaW50X2NvdW50cyAlPiUNCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IENvbXBsYWludC5UeXBlLCB2YWx1ZXNfZnJvbSA9IENvdW50LCB2YWx1ZXNfZmlsbCA9IDApDQoNCiMgR2V0IHJpZCBvZiB0aGUgSW5jaWRlbnQgWmlwIGNvbHVtbg0KY29tcGxhaW50X2NvdW50c193aWRlX25vemlwIDwtIGNvbXBsYWludF9jb3VudHNfd2lkZSAlPiUNCiAgc2VsZWN0KC1JbmNpZGVudC5aaXApIA0KDQojIEZpbmQgdGhlIGNvcnJlbGF0aW9ucw0KY29tcGxhaW50X2NvcnJlbGF0aW9ucyA8LSBjb3IoY29tcGxhaW50X2NvdW50c193aWRlX25vemlwKQ0Kcm9kZW50X2NvcnJlbGF0aW9ucyA8LSBjb21wbGFpbnRfY29ycmVsYXRpb25zWyJSb2RlbnQiLCBdDQoNCnJvZGVudF9jb3JyZWxhdGlvbnMNCmBgYA0KVGhlIHR3byBjb21wbGFpbnQgdHlwZXMgbW9zdCBoaWdobHkgY29ycmVsYXRlZCB3aXRoIHJvZGVudCBzaWdodGluZ3Mgd2VyZSBOT05DT05TVCBhbmQgUExVTUJJTkcuDQoNCmBgYHtyfQ0KIyBQQVJUIDMNCg0KaW5zcGVjdGlvbnMgPC0gcmVhZC5jc3YoImRvaG1oLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCg0KIyBDb252ZXJ0IElOU1BFQ1RJT04uREFURSB0byBhIERhdGUgb2JqZWN0DQppbnNwZWN0aW9ucyRJTlNQRUNUSU9OLkRBVEUgPC0gYXMuRGF0ZShpbnNwZWN0aW9ucyRJTlNQRUNUSU9OLkRBVEUsIGZvcm1hdCA9ICIlbS8lZC8lWSIpDQoNCiMgRXh0cmFjdCBtb250aCBhbmQgeWVhciBhcyBhIHN0cmluZw0KaW5zcGVjdGlvbnMkTW9udGhZZWFyIDwtIGZvcm1hdChpbnNwZWN0aW9ucyRJTlNQRUNUSU9OLkRBVEUsICIlbS0lWSIpDQoNCiMgRmluZCBhbGwgcm9kZW50IHZpb2xhdGlvbnMgZnJvbSB0aGUgdmlvbGF0aW9uIGNvZGVzDQpyb2RlbnRfdmlvbGF0aW9ucyA8LSBpbnNwZWN0aW9ucyAlPiUNCiAgZmlsdGVyKFZJT0xBVElPTi5DT0RFICVpbiUgYygiMDRMIiwgIjA0SyIsICIwOEEiKSkgJT4lDQogIHNlbGVjdChNb250aFllYXIsIFpJUENPREUpDQoNCiMgQ291bnQgcm9kZW50IHZpb2xhdGlvbnMgYnkgbW9udGgsIHllYXIsIGFuZCB6aXBjb2RlDQpyb2RlbnRfY291bnRzIDwtIHJvZGVudF92aW9sYXRpb25zICU+JQ0KICBncm91cF9ieShNb250aFllYXIsIFpJUENPREUpICU+JQ0KICBzdW1tYXJpemUoUmVzdGF1cmFudFJhdFZpb2xhdGlvbnMgPSBuKCkpDQoNCg0Kcm9kZW50X2luc3BlY3Rpb25zID0gcmVhZF9jc3YoInJvZGVudF9pbnNwZWN0aW9uLmNzdiIpDQoNCiMgQ29udmVydCBJTlNQRUNUSU9OIERBVEUgY29sdW1uIHRvIERhdGUgZm9ybWF0DQpyb2RlbnRfaW5zcGVjdGlvbnMkSU5TUEVDVElPTl9EQVRFIDwtIGFzLkRhdGUocm9kZW50X2luc3BlY3Rpb25zJElOU1BFQ1RJT05fREFURSwgZm9ybWF0ID0gIiVtLyVkLyVZIikNCg0KIyBDcmVhdGUgTW9udGhZZWFyIGNvbHVtbiBmcm9tIElOU1BFQ1RJT04gREFURQ0Kcm9kZW50X2luc3BlY3Rpb25zJE1vbnRoWWVhciA8LSBmb3JtYXQocm9kZW50X2luc3BlY3Rpb25zJElOU1BFQ1RJT05fREFURSwgIiVtLSVZIikNCg0KbmFtZXMocm9kZW50X2luc3BlY3Rpb25zKVtuYW1lcyhyb2RlbnRfaW5zcGVjdGlvbnMpID09ICJaSVBfQ09ERSJdIDwtICJaSVBDT0RFIg0KDQojIE1lcmdlIHdpdGggcm9kZW50IHZpb2xhdGlvbiBkYXRhDQptZXJnZWRfZGF0YSA8LSBtZXJnZShyb2RlbnRfaW5zcGVjdGlvbnMsIHJvZGVudF9jb3VudHMsIGJ5ID0gYygiWklQQ09ERSIsICJNb250aFllYXIiKSkNCg0KbWVyZ2VkX2RhdGEkUkVTVUxUIDwtIGlmZWxzZShtZXJnZWRfZGF0YSRSRVNVTFQgPT0gIkFjdGl2ZSBSYXQgU2lnbnMiLCAxLCAwKQ0KDQojIENyZWF0ZSBzZXBhcmF0ZSBtb250aCBhbmQgeWVhciBjb2x1bW5zDQptZXJnZWRfZGF0YSRtb250aCA8LSBhcy5udW1lcmljKHN1YnN0cihtZXJnZWRfZGF0YSRNb250aFllYXIsIDEsIDIpKQ0KbWVyZ2VkX2RhdGEkeWVhciA8LSBhcy5udW1lcmljKHN1YnN0cihtZXJnZWRfZGF0YSRNb250aFllYXIsIDQsIDcpKQ0KDQojIENyZWF0ZSB0cmFpbiBhbmQgdGVzdCBjYXNlcw0KdHJhaW4gPSBtZXJnZWRfZGF0YVsxOigwLjgqbnJvdyhtZXJnZWRfZGF0YSkpLF0NCnRlc3QgPSBtZXJnZWRfZGF0YVstKDE6KDAuOCpucm93KG1lcmdlZF9kYXRhKSkpLF0NCg0KIyBSdW4gdGhlIG1vZGVsDQptb2RlbCA8LSBnbG0oUkVTVUxUIH4gbG9nKFJlc3RhdXJhbnRSYXRWaW9sYXRpb25zICsgMSkgKyBtb250aCArIHllYXIsIGRhdGEgPSBtZXJnZWRfZGF0YSwgZmFtaWx5ID0gYmlub21pYWwoKSkNCnN1bW1hcnkobW9kZWwpDQpgYGANClRoZSBjb2VmZmljaWVudCBmb3IgbG9nKFJlc3RhdXJhbnRSYXRWaW9sYXRpb25zICsgMSkgaXMgcG9zaXRpdmUgYW5kIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQsIGluZGljYXRpbmcgdGhhdCBoaWdoZXIgdmFsdWVzIG9mIFJlc3RhdXJhbnQgUmF0IFZpb2xhdGlvbnMgYXJlIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgbG9nIGFkZHMgb2YgdGhlIG91dGNvbWUgdmFyaWFibGUgKEFjdGl2ZSBSYXQgU2lnbnMpLiBUaGUgY29lZmZpY2llbnQgZm9yIG1vbnRoIGlzIG5lZ2F0aXZlIGFuZCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LCBpbmRpY2F0aW5nIHRoYXQgbGF0ZXIgbW9udGhzIChoaWdoZXIgdmFsdWVzIG9mIG1vbnRoKSBhcmUgYXNzb2NpYXRlZCB3aXRoIGxvd2VyIGxvZyBvZGRzIG9mIHRoZSBvdXRjb21lIHZhcmlhYmxlIChBY3RpdmUgUmF0IFNpZ25zKS4gVGhlIGNvZWZmaWNpZW50IGZvciB5ZWFyIGlzIHBvc2l0aXZlIGFuZCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LCBpbmRpY2F0aW5nIHRoYXQgbGF0ZXIgeWVhcnMgKGhpZ2hlciB2YWx1ZXMgb2YgeWVhcikgYXJlIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgbG9nIG9kZHMgb2YgdGhlIG91dGNvbWUgdmFyaWFibGUgKEFjdGl2ZSBSYXQgU2lnbnMpLiANClRoaXMgZXZpZGVuY2UgaW5kaWNhdGVzIHRoYXQgUmVzdGF1cmFudCBSYXQgVmlvbGF0aW9ucywgbW9udGgsIGFuZCB5ZWFyIGFyZSBhbGwgaW1wb3J0YW50IHByZWRpY3RvcnMgb2YgdGhlIG91dGNvbWUgdmFyaWFibGUgKEFjdGl2ZSBSYXQgU2lnbnMpLiANCg0KYGBge3J9DQojIFBBUlQgNCwgQQ0KYGBgDQpBbm90aGVyIGFyZWEgdG8gZXhwbG9yZSBpbiBjb25qdW5jdGlvbiB3aXRoIHRoZSBOWUMgcmF0IGRhdGEgd291bGQgYmUgRFNOWSBMaXR0ZXIgQmFza2V0IGRhdGEuIFRoaXMgZGF0YSBzZXQgY29udGFpbnMgaW5mb3JtYXRpb24gYWJvdXQgbGl0dGVyIGJhc2tldHMgbG9jYXRlZCBhcm91bmQgTllDLiBodHRwczovL2RhdGEuY2l0eW9mbmV3eW9yay51cy9kYXRhc2V0L0RTTlktTGl0dGVyLUJhc2tldC1NYXAtL2Q2bTgtY3doOSBJIHdvdWxkIGxpa2UgdG8gdXNlIHRoaXMgZGF0YSB0byBzZWUgaWYgbGl0dGVyIGJhc2tldCBsb2NhdGlvbiBjb3JyZWxhdGVzIHdpdGggYWN0aXZlIHJhdCBzaWdodGluZ3MgYXJvdW5kIHRoZSBjaXR5LiBJIHdvdWxkIGRvd25sb2FkIHRoZSBkYXRhIGZyb20gdGhlIE5ZQyBPcGVuIERhdGEgd2Vic2l0ZSBhbmQgbWVyZ2UgdGhlIGRhdGEgd2l0aCB0aGUgUm9kZW50IEluc3BlY3Rpb24gZGF0YSBzZXQgYmFzZWQgb24gbG9jYXRpb24gdXNpbmcgR1BTIGNvb3JkaW5hdGVzLiBJIHdvdWxkIGxpa2UgdG8gZG8gc29tZSBhbmFseXNpcyBvbiBjb3JyZWxhdGlvbiBiZXR3ZWVuIGxpdHRlciBiYXNrZXQgbG9jYXRpb24gYW5kIGFjdGl2ZSByYXQgc2lnaHRpbmdzLiBJIHdvdWxkIGFsc28gbGlrZSB0byBjcmVhdGUgYSBjaGFydCBiYXNlZCBvbiB0aGUgZGlmZmVyZW50IGJvcm91Z2hzIGFuZCBzZWUgaG93IG51bWJlciBvZiBsaXR0ZXIgYmFza2V0cyBhbmQgYWN0aXZlIHJhdCBzaWdodGluZ3MgdmFyeSBieSBib3JvdWdoLiANCg0KYGBge3J9DQoNCg0KDQpgYGANCg==