#Install Packages

#install.packages("dplyr")
#install.packages("tidyr")
#install.packages("readr")
#install.packages("lubridate")
#install.packages("ggplot2")
#install.packages("tidyverse")
#install.packages("psych")
#install.packages("reshape2")
#install.packages("corrplot")
#install.packages("caret")
#install.packages("scales")

#Libraries

library(tidyverse)
library(psych)
library(ggplot2)
library(reshape2)
library(corrplot)
library(scales)

##Uploading the dataset

rental_income <- read.csv("XYZ LLC 2021 PL.csv")

#EPA

##Head

head(rental_income)

##Structure

str(rental_income)
'data.frame':   28 obs. of  17 variables:
 $ X         : chr  "Ordinary Income/Expense" "Income" "Rental Income" "Unit 1115" ...
 $ X1.1.2022 : num  NA NA NA 16663 15500 ...
 $ X2.1.2022 : num  NA NA NA 0 15500 ...
 $ X3.1.2022 : num  NA NA NA 16663 15500 ...
 $ X4.1.2022 : num  NA NA NA 16663 15500 ...
 $ X5.1.2022 : num  NA NA NA 16663 15500 ...
 $ X6.1.2022 : num  NA NA NA 16663 15500 ...
 $ X7.1.2022 : num  NA NA NA 16663 15500 ...
 $ X8.1.2022 : num  NA NA NA 16663 15500 ...
 $ X9.1.2022 : num  NA NA NA 0 15500 ...
 $ X10.1.2022: num  NA NA NA 16663 15500 ...
 $ X11.1.2022: num  NA NA NA 16663 15500 ...
 $ X12.1.2022: num  NA NA NA 0 15500 ...
 $ X1.1.2023 : num  NA NA NA 16663 15500 ...
 $ X1.2.2023 : num  NA NA NA 16663 15500 ...
 $ X3.1.2023 : num  NA NA NA 16663 15500 ...
 $ X4.1.2023 : num  NA NA NA 0 15500 ...

#Summary

summary(rental_income)
      X               X1.1.2022          X2.1.2022          X3.1.2022       
 Length:28          Min.   :   63.78   Min.   :    0.00   Min.   :    0.00  
 Class :character   1st Qu.:  307.01   1st Qu.:   63.78   1st Qu.:   63.78  
 Mode  :character   Median : 8880.50   Median :  307.01   Median :  307.01  
                    Mean   :16403.14   Mean   :12960.68   Mean   :12879.38  
                    3rd Qu.:16805.15   3rd Qu.:16300.00   3rd Qu.:16300.00  
                    Max.   :99680.87   Max.   :83018.00   Max.   :82448.87  
                    NA's   :8          NA's   :7          NA's   :7         
   X4.1.2022       X5.1.2022         X6.1.2022         X7.1.2022      
 Min.   :    0   Min.   :    0.0   Min.   :    0.0   Min.   :    0.0  
 1st Qu.:  219   1st Qu.:  138.8   1st Qu.:  138.8   1st Qu.:  138.8  
 Median : 1500   Median : 3000.0   Median : 3000.0   Median : 3000.0  
 Mean   :13375   Mean   :15341.1   Mean   :15341.1   Mean   :15341.1  
 3rd Qu.:16663   3rd Qu.:16662.9   3rd Qu.:16662.9   3rd Qu.:16662.9  
 Max.   :84920   Max.   :99680.9   Max.   :99680.9   Max.   :99680.9  
 NA's   :7       NA's   :7         NA's   :7         NA's   :7        
   X8.1.2022          X9.1.2022          X10.1.2022        X11.1.2022     
 Min.   :    0.00   Min.   :    0.00   Min.   :    0.0   Min.   :    0.0  
 1st Qu.:   63.78   1st Qu.:   63.78   1st Qu.:  138.8   1st Qu.:  138.8  
 Median :  307.01   Median :  307.01   Median : 3000.0   Median : 3000.0  
 Mean   :13232.38   Mean   :12960.68   Mean   :15341.1   Mean   :15341.1  
 3rd Qu.:16662.87   3rd Qu.:16300.00   3rd Qu.:16662.9   3rd Qu.:16662.9  
 Max.   :84919.87   Max.   :83018.00   Max.   :99680.9   Max.   :99680.9  
 NA's   :7          NA's   :7          NA's   :7         NA's   :7        
   X12.1.2022         X1.1.2023         X1.2.2023         X3.1.2023       
 Min.   :    0.00   Min.   :    0.0   Min.   :    0.0   Min.   :    0.00  
 1st Qu.:   63.78   1st Qu.:  282.8   1st Qu.:  138.8   1st Qu.:   63.78  
 Median :  307.01   Median : 2950.0   Median : 3000.0   Median :  307.01  
 Mean   :12960.68   Mean   :13293.5   Mean   :15341.1   Mean   :13232.38  
 3rd Qu.:16300.00   3rd Qu.:16662.9   3rd Qu.:16662.9   3rd Qu.:16662.87  
 Max.   :83018.00   Max.   :83380.9   Max.   :99680.9   Max.   :84919.87  
 NA's   :7          NA's   :7         NA's   :7         NA's   :7         
   X4.1.2023    
 Min.   :    0  
 1st Qu.:  219  
 Median : 1500  
 Mean   :13104  
 3rd Qu.:16300  
 Max.   :83018  
 NA's   :7      

##Omit NA values

clean_rental_income <- na.omit(rental_income)
#view(clean_rental_income)

#check the current column names

print(colnames(clean_rental_income))
 [1] "X"          "X1.1.2022"  "X2.1.2022"  "X3.1.2022"  "X4.1.2022"  "X5.1.2022" 
 [7] "X6.1.2022"  "X7.1.2022"  "X8.1.2022"  "X9.1.2022"  "X10.1.2022" "X11.1.2022"
[13] "X12.1.2022" "X1.1.2023"  "X1.2.2023"  "X3.1.2023"  "X4.1.2023" 

Change The headers into a date structure

Col_headers <- seq(as.Date("2022-01-01"), as.Date("2023-04-01"), by = "month")

# Assign dates as column names from the second column onwards
names(clean_rental_income)[-1] <- format(Col_headers, "%B %Y")
print(colnames(clean_rental_income))
 [1] "X"              "January 2022"   "February 2022"  "March 2022"    
 [5] "April 2022"     "May 2022"       "June 2022"      "July 2022"     
 [9] "August 2022"    "September 2022" "October 2022"   "November 2022" 
[13] "December 2022"  "January 2023"   "February 2023"  "March 2023"    
[17] "April 2023"    
total_rental_income_monthly <- clean_rental_income %>%
  filter(grepl("Total Rental Income", clean_rental_income[[1]])) %>% # Adjust the column index if necessary
  select(-1)  # Remove the category column to focus on numerical data
# Transpose for better readability
monthly_totals <- colSums(total_rental_income_monthly, na.rm = TRUE)
monthly_totals_df <- data.frame(Month = names(monthly_totals), Total = as.numeric(monthly_totals), row.names = NULL)
print(monthly_totals_df)

#Bar Chart with the Total Rental Income per month

ggplot(monthly_totals_df, aes(x = Month, y = Total)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  theme_minimal() +
  labs(title = "Monthly Total Rental Income",
       x = "Month",
       y = "Total Income ($)") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  # Rotate x-axis labels for better readability

# Define the specific order of the months
months_order <- c("January 2022", "February 2022", "March 2022", "April 2022", 
                  "May 2022", "June 2022", "July 2022", "August 2022", "September 2022", 
                  "October 2022", "November 2022", "December 2022", "January 2023", 
                  "February 2023", "March 2023", "April 2023")
# Ensure that 'Month' is converted to a factor and ordered correctly
monthly_totals_df$Month <- factor(monthly_totals_df$Month, levels = months_order)

# Plotting the bar chart with the months in the specified order
ggplot(monthly_totals_df, aes(x = Month, y = Total)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  geom_text(aes(label = paste0("$", format(Total, big.mark=","))), # Format numbers with commas
            position = position_stack(vjust = 0.5),  # Adjust vertical position to be inside the bars
            color = "white", size = 3.5, angle = 90) +  # Set text color and size, rotate text vertically
  theme_minimal() +
  labs(title = "Monthly Total Rental Income",
       x = "Month",
       y = "Total Income ($)") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  # Rotate x-axis labels for better readability

# Filter the data for 'Net Income'
net_income_data <- clean_rental_income %>%
  filter(grepl("Net Income", clean_rental_income[[1]])) %>% # Adjust the column index if necessary
  select(-1)  # Remove the category column to focus on numerical data
print(net_income_data)
# Prepare data for plotting
net_income_data <- tibble(
  Month = months_order,
  Net_Income = as.numeric(net_income_data[1, ])
)
print(net_income_data)
# Convert 'Month' into an ordered factor based on the months_order
net_income_data$Month <- factor(net_income_data$Month, levels = months_order)
# Plotting the line graph
plot <- ggplot(net_income_data, aes(x = Month, y = Net_Income)) +
  geom_line(color = "dodgerblue", size = 1.5) +  # Ensure line connects the points
  geom_point(color = "darkblue", size = 3.5) +  # Points on the line
  geom_smooth(method = "lm", color = "red", se = FALSE, aes(group = 1)) +  # Add a linear trendline
  theme_minimal() +
  scale_y_continuous(labels = dollar_format(prefix = "$", suffix = ""), 
                     breaks = pretty_breaks(n = 10)) +
  labs(title = "Monthly Net Income",
       x = "Month",
       y = "Net Income ($)") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
# Print the plot
print(plot)

# Extract column names (months), which are the levels of the 'Month' factor
month_names <- levels(net_income_data$Month)  # This assumes 'Month' is a factor

# Extract values for Net Income
total_income <- net_income_data$Net_Income

# Create the line plot with nicer aesthetics but without the y-axis
plot(1:length(month_names), total_income, type = "o", 
     xlab = "Months", ylab = "",  # Remove ylab here
     main = "Net Income per Month",
     col = "blue",            # Line color
     pch = 16,                # Point shape
     lwd = 2,                 # Line width
     ylim = c(0, max(total_income) * 1.1),  # Adjust y-axis limits
     xaxt = "n",              # Disable x-axis labels
     yaxt = "n")              # Disable y-axis to customize later

# Add month labels on the x-axis with rotated labels
axis(1, at = 1:length(month_names), labels = month_names, las = 2, cex.axis = 0.8)

# Customize y-axis with dollar sign
y_at <- pretty(range(c(0, max(total_income) * 1.1)))  # Get pretty breaks for y-axis
axis(2, at = y_at, labels = paste("$", format(y_at, big.mark = ",", scientific = FALSE), sep = ""), las = 1, cex.axis = 0.8)

# Add gridlines
grid(nx = NULL, ny = NULL)  # Add horizontal and vertical grid lines

# Add a legend
legend("topright", 
       legend = c("Net Income"), 
       col = "blue", 
       lty = 1, 
       pch = 16, 
       cex = 0.8,
       bg = "white")

#Analysis of Expense Lines

transposed_data <- t(clean_rental_income)
#view(transposed_data)
colnames(transposed_data) <- transposed_data[1, ]
transposed_data <- transposed_data[-1, ]
#view(transposed_data)
# Select only the rows corresponding to expenses
rental_expenses <- transposed_data[, c("Bright Star Credit Union", "Bank Charges - Other", "Total Commission", "Filing Fees","Total Electricity", "Total Utilities")]

# Convert the selected columns to numeric
rental_expenses <- apply(rental_expenses, 2, as.numeric)

# Calculate the sum of each expense column
total_expenses <- colSums(rental_expenses)

# Create a dataframe with the expense names and their totals
expenses_df <- data.frame(expense = names(total_expenses), total = total_expenses)

##Bar Chart Expenses

# Create the bar plot with enhancements
ggplot(expenses_df, aes(x = expense, y = total)) +
  geom_bar(stat = "identity", fill = "skyblue") +
  geom_text(aes(label = format(total, big.mark = ",")),   # Adding formatted labels inside bars
            position = position_stack(vjust = 0.5),       # Center labels vertically in bars
            color = "black", size = 3.5) +                # Set text color and size
  
  labs(title = "Total Expenses", x = "Expense", y = "Total") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),  # Rotate x-axis labels for better readability
        axis.text.y = element_text(color = "gray20"))  # Enhance y-axis labels readability

##Pie Chart Distribution of Expenses

# Calculate the percentages for the pie chart labels
expenses_df$percentage <- expenses_df$total / sum(expenses_df$total) * 100

# Create the pie chart
ggplot(expenses_df, aes(x = "", y = total, fill = expense)) +
  geom_bar(width = 1, stat = "identity") +  # Use geom_bar and set width to 1 for pie chart
  coord_polar(theta = "y") +                # Convert bar chart to pie chart using polar coordinates
  geom_text(aes(label = paste0(round(percentage, 1), "%")), position = position_stack(vjust = 0.5),
            color = "white", size = 4) +     # Add percentage labels inside each slice
  labs(title = "Distribution of Expenses", x = NULL, y = NULL, fill = "Expense Type") +
  theme_void() +                            # Remove axis and grid lines
  theme(legend.position = "right",          # Adjust legend position
        legend.title = element_text(size = 10),  # Legend title size
        legend.text = element_text(size = 8))    # Legend text size

#install.packages("randomForest")
# Fit multiple linear regression model
multiple_lm <- lm(`Net Income` ~ `Total Rental Income` + `Bright Star Credit Union` + `Bank Charges - Other` + `Total Commission` + `Filing Fees` + `Total Electricity` + `Total Utilities` + `Depreciation Expense`, data = model_data)

# Print summary of the model
summary(multiple_lm)
Warning: essentially perfect fit: summary may be unreliable

Call:
lm(formula = `Net Income` ~ `Total Rental Income` + `Bright Star Credit Union` + 
    `Bank Charges - Other` + `Total Commission` + `Filing Fees` + 
    `Total Electricity` + `Total Utilities` + `Depreciation Expense`, 
    data = model_data)

Residuals:
       Min         1Q     Median         3Q        Max 
-5.109e-12 -1.523e-12  0.000e+00  5.740e-14  7.002e-12 

Coefficients: (6 not defined because of singularities)
                                Estimate Std. Error    t value Pr(>|t|)    
(Intercept)                    5.961e+04  3.731e-12  1.598e+16   <2e-16 ***
`Total Rental Income`83018.00  5.691e+02  4.193e-12  1.357e+14   <2e-16 ***
`Total Rental Income`83380.87  9.320e+02  6.262e-12  1.488e+14   <2e-16 ***
`Total Rental Income`84919.87  2.471e+03  4.345e-12  5.686e+14   <2e-16 ***
`Total Rental Income`99680.87  1.723e+04  4.017e-12  4.290e+15   <2e-16 ***
`Bright Star Credit Union`            NA         NA         NA       NA    
`Bank Charges - Other`                NA         NA         NA       NA    
`Total Commission`            -1.000e+00  1.143e-15 -8.746e+14   <2e-16 ***
`Filing Fees`                         NA         NA         NA       NA    
`Total Electricity`                   NA         NA         NA       NA    
`Total Utilities`                     NA         NA         NA       NA    
`Depreciation Expense`                NA         NA         NA       NA    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.731e-12 on 10 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 1.536e+31 on 5 and 10 DF,  p-value: < 2.2e-16

##Multiple Linear Regression

# Fit multiple linear regression model
multiple_lm <- lm(`Net Income` ~ ., data = model_data)
# Print summary of the model
summary(multiple_lm)
Warning: essentially perfect fit: summary may be unreliable

Call:
lm(formula = `Net Income` ~ ., data = model_data)

Residuals:
       Min         1Q     Median         3Q        Max 
-5.109e-12 -1.523e-12  0.000e+00  5.740e-14  7.002e-12 

Coefficients: (6 not defined because of singularities)
                                Estimate Std. Error    t value Pr(>|t|)    
(Intercept)                    5.961e+04  3.731e-12  1.598e+16   <2e-16 ***
`Total Rental Income`83018.00  5.691e+02  4.193e-12  1.357e+14   <2e-16 ***
`Total Rental Income`83380.87  9.320e+02  6.262e-12  1.488e+14   <2e-16 ***
`Total Rental Income`84919.87  2.471e+03  4.345e-12  5.686e+14   <2e-16 ***
`Total Rental Income`99680.87  1.723e+04  4.017e-12  4.290e+15   <2e-16 ***
`Bright Star Credit Union`            NA         NA         NA       NA    
`Bank Charges - Other`                NA         NA         NA       NA    
`Total Commission`            -1.000e+00  1.143e-15 -8.746e+14   <2e-16 ***
`Filing Fees`                         NA         NA         NA       NA    
`Total Electricity`                   NA         NA         NA       NA    
`Total Utilities`                     NA         NA         NA       NA    
`Depreciation Expense`                NA         NA         NA       NA    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.731e-12 on 10 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 1.536e+31 on 5 and 10 DF,  p-value: < 2.2e-16
# Remove rows with missing values
numeric_data <- na.omit(numeric_data)

# Calculate the correlation matrix
correlation_matrix <- cor(numeric_data)
Warning: the standard deviation is zero
# Print the correlation matrix
#print(correlation_matrix)
#Check for missing values in the relevant columns
missing_values <- sapply(correlation_data, function(x) sum(is.na(x)))

# Print the number of missing values for each column
print(missing_values)
     Total Rental Income Bright Star Credit Union     Bank Charges - Other 
                       0                        0                        0 
        Total Commission              Filing Fees        Total Electricity 
                       0                        0                        0 
         Total Utilities     Depreciation Expense               Net Income 
                       0                        0                        0 

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKI0luc3RhbGwgUGFja2FnZXMKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCiNpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5ciIpCiNpbnN0YWxsLnBhY2thZ2VzKCJyZWFkciIpCiNpbnN0YWxsLnBhY2thZ2VzKCJsdWJyaWRhdGUiKQojaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpCiNpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQojaW5zdGFsbC5wYWNrYWdlcygicHN5Y2giKQojaW5zdGFsbC5wYWNrYWdlcygicmVzaGFwZTIiKQojaW5zdGFsbC5wYWNrYWdlcygiY29ycnBsb3QiKQojaW5zdGFsbC5wYWNrYWdlcygiY2FyZXQiKQojaW5zdGFsbC5wYWNrYWdlcygic2NhbGVzIikKYGBgCgojTGlicmFyaWVzCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShwc3ljaCkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KGNvcnJwbG90KQpsaWJyYXJ5KHNjYWxlcykKYGBgCgojI1VwbG9hZGluZyB0aGUgZGF0YXNldApgYGB7cn0KcmVudGFsX2luY29tZSA8LSByZWFkLmNzdigiWFlaIExMQyAyMDIxIFBMLmNzdiIpCmBgYAoKI0VQQQoKIyNIZWFkCmBgYHtyfQpoZWFkKHJlbnRhbF9pbmNvbWUpCmBgYAojI1N0cnVjdHVyZSAKYGBge3J9CnN0cihyZW50YWxfaW5jb21lKQpgYGAKCiNTdW1tYXJ5CmBgYHtyfQpzdW1tYXJ5KHJlbnRhbF9pbmNvbWUpCmBgYAojI09taXQgTkEgdmFsdWVzCmBgYHtyfQpjbGVhbl9yZW50YWxfaW5jb21lIDwtIG5hLm9taXQocmVudGFsX2luY29tZSkKYGBgCgoKYGBge3J9CiN2aWV3KGNsZWFuX3JlbnRhbF9pbmNvbWUpCmBgYAoKI2NoZWNrIHRoZSBjdXJyZW50IGNvbHVtbiBuYW1lcwpgYGB7cn0KcHJpbnQoY29sbmFtZXMoY2xlYW5fcmVudGFsX2luY29tZSkpCmBgYAojIENoYW5nZSBUaGUgaGVhZGVycyBpbnRvIGEgZGF0ZSBzdHJ1Y3R1cmUKYGBge3J9CkNvbF9oZWFkZXJzIDwtIHNlcShhcy5EYXRlKCIyMDIyLTAxLTAxIiksIGFzLkRhdGUoIjIwMjMtMDQtMDEiKSwgYnkgPSAibW9udGgiKQoKIyBBc3NpZ24gZGF0ZXMgYXMgY29sdW1uIG5hbWVzIGZyb20gdGhlIHNlY29uZCBjb2x1bW4gb253YXJkcwpuYW1lcyhjbGVhbl9yZW50YWxfaW5jb21lKVstMV0gPC0gZm9ybWF0KENvbF9oZWFkZXJzLCAiJUIgJVkiKQpgYGAKCmBgYHtyfQpwcmludChjb2xuYW1lcyhjbGVhbl9yZW50YWxfaW5jb21lKSkKYGBgCgpgYGB7cn0KdG90YWxfcmVudGFsX2luY29tZV9tb250aGx5IDwtIGNsZWFuX3JlbnRhbF9pbmNvbWUgJT4lCiAgZmlsdGVyKGdyZXBsKCJUb3RhbCBSZW50YWwgSW5jb21lIiwgY2xlYW5fcmVudGFsX2luY29tZVtbMV1dKSkgJT4lICMgQWRqdXN0IHRoZSBjb2x1bW4gaW5kZXggaWYgbmVjZXNzYXJ5CiAgc2VsZWN0KC0xKSAgIyBSZW1vdmUgdGhlIGNhdGVnb3J5IGNvbHVtbiB0byBmb2N1cyBvbiBudW1lcmljYWwgZGF0YQpgYGAKCgpgYGB7cn0KIyBUcmFuc3Bvc2UgZm9yIGJldHRlciByZWFkYWJpbGl0eQptb250aGx5X3RvdGFscyA8LSBjb2xTdW1zKHRvdGFsX3JlbnRhbF9pbmNvbWVfbW9udGhseSwgbmEucm0gPSBUUlVFKQptb250aGx5X3RvdGFsc19kZiA8LSBkYXRhLmZyYW1lKE1vbnRoID0gbmFtZXMobW9udGhseV90b3RhbHMpLCBUb3RhbCA9IGFzLm51bWVyaWMobW9udGhseV90b3RhbHMpLCByb3cubmFtZXMgPSBOVUxMKQoKYGBgCgoKYGBge3J9CnByaW50KG1vbnRobHlfdG90YWxzX2RmKQpgYGAKCiNCYXIgQ2hhcnQgd2l0aCB0aGUgVG90YWwgUmVudGFsIEluY29tZSBwZXIgbW9udGgKYGBge3J9CmdncGxvdChtb250aGx5X3RvdGFsc19kZiwgYWVzKHggPSBNb250aCwgeSA9IFRvdGFsKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInN0ZWVsYmx1ZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiTW9udGhseSBUb3RhbCBSZW50YWwgSW5jb21lIiwKICAgICAgIHggPSAiTW9udGgiLAogICAgICAgeSA9ICJUb3RhbCBJbmNvbWUgKCQpIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciBiZXR0ZXIgcmVhZGFiaWxpdHkKYGBgCgoKYGBge3J9CiMgRGVmaW5lIHRoZSBzcGVjaWZpYyBvcmRlciBvZiB0aGUgbW9udGhzCm1vbnRoc19vcmRlciA8LSBjKCJKYW51YXJ5IDIwMjIiLCAiRmVicnVhcnkgMjAyMiIsICJNYXJjaCAyMDIyIiwgIkFwcmlsIDIwMjIiLCAKICAgICAgICAgICAgICAgICAgIk1heSAyMDIyIiwgIkp1bmUgMjAyMiIsICJKdWx5IDIwMjIiLCAiQXVndXN0IDIwMjIiLCAiU2VwdGVtYmVyIDIwMjIiLCAKICAgICAgICAgICAgICAgICAgIk9jdG9iZXIgMjAyMiIsICJOb3ZlbWJlciAyMDIyIiwgIkRlY2VtYmVyIDIwMjIiLCAiSmFudWFyeSAyMDIzIiwgCiAgICAgICAgICAgICAgICAgICJGZWJydWFyeSAyMDIzIiwgIk1hcmNoIDIwMjMiLCAiQXByaWwgMjAyMyIpCgpgYGAKCgpgYGB7cn0KIyBFbnN1cmUgdGhhdCAnTW9udGgnIGlzIGNvbnZlcnRlZCB0byBhIGZhY3RvciBhbmQgb3JkZXJlZCBjb3JyZWN0bHkKbW9udGhseV90b3RhbHNfZGYkTW9udGggPC0gZmFjdG9yKG1vbnRobHlfdG90YWxzX2RmJE1vbnRoLCBsZXZlbHMgPSBtb250aHNfb3JkZXIpCgojIFBsb3R0aW5nIHRoZSBiYXIgY2hhcnQgd2l0aCB0aGUgbW9udGhzIGluIHRoZSBzcGVjaWZpZWQgb3JkZXIKZ2dwbG90KG1vbnRobHlfdG90YWxzX2RmLCBhZXMoeCA9IE1vbnRoLCB5ID0gVG90YWwpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic3RlZWxibHVlIikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoIiQiLCBmb3JtYXQoVG90YWwsIGJpZy5tYXJrPSIsIikpKSwgIyBGb3JtYXQgbnVtYmVycyB3aXRoIGNvbW1hcwogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwgICMgQWRqdXN0IHZlcnRpY2FsIHBvc2l0aW9uIHRvIGJlIGluc2lkZSB0aGUgYmFycwogICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAzLjUsIGFuZ2xlID0gOTApICsgICMgU2V0IHRleHQgY29sb3IgYW5kIHNpemUsIHJvdGF0ZSB0ZXh0IHZlcnRpY2FsbHkKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiTW9udGhseSBUb3RhbCBSZW50YWwgSW5jb21lIiwKICAgICAgIHggPSAiTW9udGgiLAogICAgICAgeSA9ICJUb3RhbCBJbmNvbWUgKCQpIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciBiZXR0ZXIgcmVhZGFiaWxpdHkKYGBgCgpgYGB7cn0KIyBGaWx0ZXIgdGhlIGRhdGEgZm9yICdOZXQgSW5jb21lJwpuZXRfaW5jb21lX2RhdGEgPC0gY2xlYW5fcmVudGFsX2luY29tZSAlPiUKICBmaWx0ZXIoZ3JlcGwoIk5ldCBJbmNvbWUiLCBjbGVhbl9yZW50YWxfaW5jb21lW1sxXV0pKSAlPiUgIyBBZGp1c3QgdGhlIGNvbHVtbiBpbmRleCBpZiBuZWNlc3NhcnkKICBzZWxlY3QoLTEpICAjIFJlbW92ZSB0aGUgY2F0ZWdvcnkgY29sdW1uIHRvIGZvY3VzIG9uIG51bWVyaWNhbCBkYXRhCmBgYAoKYGBge3J9CnByaW50KG5ldF9pbmNvbWVfZGF0YSkKYGBgCgpgYGB7cn0KIyBQcmVwYXJlIGRhdGEgZm9yIHBsb3R0aW5nCm5ldF9pbmNvbWVfZGF0YSA8LSB0aWJibGUoCiAgTW9udGggPSBtb250aHNfb3JkZXIsCiAgTmV0X0luY29tZSA9IGFzLm51bWVyaWMobmV0X2luY29tZV9kYXRhWzEsIF0pCikKYGBgCgpgYGB7cn0KcHJpbnQobmV0X2luY29tZV9kYXRhKQpgYGAKCmBgYHtyfQojIENvbnZlcnQgJ01vbnRoJyBpbnRvIGFuIG9yZGVyZWQgZmFjdG9yIGJhc2VkIG9uIHRoZSBtb250aHNfb3JkZXIKbmV0X2luY29tZV9kYXRhJE1vbnRoIDwtIGZhY3RvcihuZXRfaW5jb21lX2RhdGEkTW9udGgsIGxldmVscyA9IG1vbnRoc19vcmRlcikKYGBgCgoKYGBge3J9CiMgUGxvdHRpbmcgdGhlIGxpbmUgZ3JhcGgKcGxvdCA8LSBnZ3Bsb3QobmV0X2luY29tZV9kYXRhLCBhZXMoeCA9IE1vbnRoLCB5ID0gTmV0X0luY29tZSkpICsKICBnZW9tX2xpbmUoY29sb3IgPSAiZG9kZ2VyYmx1ZSIsIHNpemUgPSAxLjUpICsgICMgRW5zdXJlIGxpbmUgY29ubmVjdHMgdGhlIHBvaW50cwogIGdlb21fcG9pbnQoY29sb3IgPSAiZGFya2JsdWUiLCBzaXplID0gMy41KSArICAjIFBvaW50cyBvbiB0aGUgbGluZQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gInJlZCIsIHNlID0gRkFMU0UsIGFlcyhncm91cCA9IDEpKSArICAjIEFkZCBhIGxpbmVhciB0cmVuZGxpbmUKICB0aGVtZV9taW5pbWFsKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBkb2xsYXJfZm9ybWF0KHByZWZpeCA9ICIkIiwgc3VmZml4ID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gcHJldHR5X2JyZWFrcyhuID0gMTApKSArCiAgbGFicyh0aXRsZSA9ICJNb250aGx5IE5ldCBJbmNvbWUiLAogICAgICAgeCA9ICJNb250aCIsCiAgICAgICB5ID0gIk5ldCBJbmNvbWUgKCQpIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCmBgYAoKCmBgYHtyfQojIFByaW50IHRoZSBwbG90CnByaW50KHBsb3QpCmBgYAoKYGBge3J9CiMgRXh0cmFjdCBjb2x1bW4gbmFtZXMgKG1vbnRocyksIHdoaWNoIGFyZSB0aGUgbGV2ZWxzIG9mIHRoZSAnTW9udGgnIGZhY3Rvcgptb250aF9uYW1lcyA8LSBsZXZlbHMobmV0X2luY29tZV9kYXRhJE1vbnRoKSAgIyBUaGlzIGFzc3VtZXMgJ01vbnRoJyBpcyBhIGZhY3RvcgoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgTmV0IEluY29tZQp0b3RhbF9pbmNvbWUgPC0gbmV0X2luY29tZV9kYXRhJE5ldF9JbmNvbWUKCiMgQ3JlYXRlIHRoZSBsaW5lIHBsb3Qgd2l0aCBuaWNlciBhZXN0aGV0aWNzIGJ1dCB3aXRob3V0IHRoZSB5LWF4aXMKcGxvdCgxOmxlbmd0aChtb250aF9uYW1lcyksIHRvdGFsX2luY29tZSwgdHlwZSA9ICJvIiwgCiAgICAgeGxhYiA9ICJNb250aHMiLCB5bGFiID0gIiIsICAjIFJlbW92ZSB5bGFiIGhlcmUKICAgICBtYWluID0gIk5ldCBJbmNvbWUgcGVyIE1vbnRoIiwKICAgICBjb2wgPSAiYmx1ZSIsICAgICAgICAgICAgIyBMaW5lIGNvbG9yCiAgICAgcGNoID0gMTYsICAgICAgICAgICAgICAgICMgUG9pbnQgc2hhcGUKICAgICBsd2QgPSAyLCAgICAgICAgICAgICAgICAgIyBMaW5lIHdpZHRoCiAgICAgeWxpbSA9IGMoMCwgbWF4KHRvdGFsX2luY29tZSkgKiAxLjEpLCAgIyBBZGp1c3QgeS1heGlzIGxpbWl0cwogICAgIHhheHQgPSAibiIsICAgICAgICAgICAgICAjIERpc2FibGUgeC1heGlzIGxhYmVscwogICAgIHlheHQgPSAibiIpICAgICAgICAgICAgICAjIERpc2FibGUgeS1heGlzIHRvIGN1c3RvbWl6ZSBsYXRlcgoKIyBBZGQgbW9udGggbGFiZWxzIG9uIHRoZSB4LWF4aXMgd2l0aCByb3RhdGVkIGxhYmVscwpheGlzKDEsIGF0ID0gMTpsZW5ndGgobW9udGhfbmFtZXMpLCBsYWJlbHMgPSBtb250aF9uYW1lcywgbGFzID0gMiwgY2V4LmF4aXMgPSAwLjgpCgojIEN1c3RvbWl6ZSB5LWF4aXMgd2l0aCBkb2xsYXIgc2lnbgp5X2F0IDwtIHByZXR0eShyYW5nZShjKDAsIG1heCh0b3RhbF9pbmNvbWUpICogMS4xKSkpICAjIEdldCBwcmV0dHkgYnJlYWtzIGZvciB5LWF4aXMKYXhpcygyLCBhdCA9IHlfYXQsIGxhYmVscyA9IHBhc3RlKCIkIiwgZm9ybWF0KHlfYXQsIGJpZy5tYXJrID0gIiwiLCBzY2llbnRpZmljID0gRkFMU0UpLCBzZXAgPSAiIiksIGxhcyA9IDEsIGNleC5heGlzID0gMC44KQoKIyBBZGQgZ3JpZGxpbmVzCmdyaWQobnggPSBOVUxMLCBueSA9IE5VTEwpICAjIEFkZCBob3Jpem9udGFsIGFuZCB2ZXJ0aWNhbCBncmlkIGxpbmVzCgojIEFkZCBhIGxlZ2VuZApsZWdlbmQoInRvcHJpZ2h0IiwgCiAgICAgICBsZWdlbmQgPSBjKCJOZXQgSW5jb21lIiksIAogICAgICAgY29sID0gImJsdWUiLCAKICAgICAgIGx0eSA9IDEsIAogICAgICAgcGNoID0gMTYsIAogICAgICAgY2V4ID0gMC44LAogICAgICAgYmcgPSAid2hpdGUiKQoKYGBgCgojQW5hbHlzaXMgb2YgRXhwZW5zZSBMaW5lcwpgYGB7cn0KdHJhbnNwb3NlZF9kYXRhIDwtIHQoY2xlYW5fcmVudGFsX2luY29tZSkKYGBgCgoKYGBge3J9CiN2aWV3KHRyYW5zcG9zZWRfZGF0YSkKYGBgCgoKYGBge3J9CmNvbG5hbWVzKHRyYW5zcG9zZWRfZGF0YSkgPC0gdHJhbnNwb3NlZF9kYXRhWzEsIF0KdHJhbnNwb3NlZF9kYXRhIDwtIHRyYW5zcG9zZWRfZGF0YVstMSwgXQpgYGAKCmBgYHtyfQojdmlldyh0cmFuc3Bvc2VkX2RhdGEpCmBgYAoKYGBge3J9CiMgU2VsZWN0IG9ubHkgdGhlIHJvd3MgY29ycmVzcG9uZGluZyB0byBleHBlbnNlcwpyZW50YWxfZXhwZW5zZXMgPC0gdHJhbnNwb3NlZF9kYXRhWywgYygiQnJpZ2h0IFN0YXIgQ3JlZGl0IFVuaW9uIiwgIkJhbmsgQ2hhcmdlcyAtIE90aGVyIiwgIlRvdGFsIENvbW1pc3Npb24iLCAiRmlsaW5nIEZlZXMiLCJUb3RhbCBFbGVjdHJpY2l0eSIsICJUb3RhbCBVdGlsaXRpZXMiKV0KCiMgQ29udmVydCB0aGUgc2VsZWN0ZWQgY29sdW1ucyB0byBudW1lcmljCnJlbnRhbF9leHBlbnNlcyA8LSBhcHBseShyZW50YWxfZXhwZW5zZXMsIDIsIGFzLm51bWVyaWMpCgojIENhbGN1bGF0ZSB0aGUgc3VtIG9mIGVhY2ggZXhwZW5zZSBjb2x1bW4KdG90YWxfZXhwZW5zZXMgPC0gY29sU3VtcyhyZW50YWxfZXhwZW5zZXMpCgojIENyZWF0ZSBhIGRhdGFmcmFtZSB3aXRoIHRoZSBleHBlbnNlIG5hbWVzIGFuZCB0aGVpciB0b3RhbHMKZXhwZW5zZXNfZGYgPC0gZGF0YS5mcmFtZShleHBlbnNlID0gbmFtZXModG90YWxfZXhwZW5zZXMpLCB0b3RhbCA9IHRvdGFsX2V4cGVuc2VzKQoKYGBgCgojI0JhciBDaGFydCBFeHBlbnNlcwpgYGB7cn0KIyBDcmVhdGUgdGhlIGJhciBwbG90IHdpdGggZW5oYW5jZW1lbnRzCmdncGxvdChleHBlbnNlc19kZiwgYWVzKHggPSBleHBlbnNlLCB5ID0gdG90YWwpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic2t5Ymx1ZSIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gZm9ybWF0KHRvdGFsLCBiaWcubWFyayA9ICIsIikpLCAgICMgQWRkaW5nIGZvcm1hdHRlZCBsYWJlbHMgaW5zaWRlIGJhcnMKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksICAgICAgICMgQ2VudGVyIGxhYmVscyB2ZXJ0aWNhbGx5IGluIGJhcnMKICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMy41KSArICAgICAgICAgICAgICAgICMgU2V0IHRleHQgY29sb3IgYW5kIHNpemUKICAKICBsYWJzKHRpdGxlID0gIlRvdGFsIEV4cGVuc2VzIiwgeCA9ICJFeHBlbnNlIiwgeSA9ICJUb3RhbCIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciBiZXR0ZXIgcmVhZGFiaWxpdHkKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmF5MjAiKSkgICMgRW5oYW5jZSB5LWF4aXMgbGFiZWxzIHJlYWRhYmlsaXR5CmBgYAoKIyNQaWUgQ2hhcnQgRGlzdHJpYnV0aW9uIG9mIEV4cGVuc2VzCmBgYHtyfQojIENhbGN1bGF0ZSB0aGUgcGVyY2VudGFnZXMgZm9yIHRoZSBwaWUgY2hhcnQgbGFiZWxzCmV4cGVuc2VzX2RmJHBlcmNlbnRhZ2UgPC0gZXhwZW5zZXNfZGYkdG90YWwgLyBzdW0oZXhwZW5zZXNfZGYkdG90YWwpICogMTAwCgojIENyZWF0ZSB0aGUgcGllIGNoYXJ0CmdncGxvdChleHBlbnNlc19kZiwgYWVzKHggPSAiIiwgeSA9IHRvdGFsLCBmaWxsID0gZXhwZW5zZSkpICsKICBnZW9tX2Jhcih3aWR0aCA9IDEsIHN0YXQgPSAiaWRlbnRpdHkiKSArICAjIFVzZSBnZW9tX2JhciBhbmQgc2V0IHdpZHRoIHRvIDEgZm9yIHBpZSBjaGFydAogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArICAgICAgICAgICAgICAgICMgQ29udmVydCBiYXIgY2hhcnQgdG8gcGllIGNoYXJ0IHVzaW5nIHBvbGFyIGNvb3JkaW5hdGVzCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChyb3VuZChwZXJjZW50YWdlLCAxKSwgIiUiKSksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLAogICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSA0KSArICAgICAjIEFkZCBwZXJjZW50YWdlIGxhYmVscyBpbnNpZGUgZWFjaCBzbGljZQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEV4cGVuc2VzIiwgeCA9IE5VTEwsIHkgPSBOVUxMLCBmaWxsID0gIkV4cGVuc2UgVHlwZSIpICsKICB0aGVtZV92b2lkKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFJlbW92ZSBheGlzIGFuZCBncmlkIGxpbmVzCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwgICAgICAgICAgIyBBZGp1c3QgbGVnZW5kIHBvc2l0aW9uCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksICAjIExlZ2VuZCB0aXRsZSBzaXplCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSAgICAjIExlZ2VuZCB0ZXh0IHNpemUKYGBgCgpgYGB7cn0KI2luc3RhbGwucGFja2FnZXMoInJhbmRvbUZvcmVzdCIpCmBgYAoKYGBge3J9CiMgRml0IG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsCm11bHRpcGxlX2xtIDwtIGxtKGBOZXQgSW5jb21lYCB+IGBUb3RhbCBSZW50YWwgSW5jb21lYCArIGBCcmlnaHQgU3RhciBDcmVkaXQgVW5pb25gICsgYEJhbmsgQ2hhcmdlcyAtIE90aGVyYCArIGBUb3RhbCBDb21taXNzaW9uYCArIGBGaWxpbmcgRmVlc2AgKyBgVG90YWwgRWxlY3RyaWNpdHlgICsgYFRvdGFsIFV0aWxpdGllc2AgKyBgRGVwcmVjaWF0aW9uIEV4cGVuc2VgLCBkYXRhID0gbW9kZWxfZGF0YSkKCiMgUHJpbnQgc3VtbWFyeSBvZiB0aGUgbW9kZWwKc3VtbWFyeShtdWx0aXBsZV9sbSkKYGBgCgojI011bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uCgpgYGB7cn0KIyBGaXQgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwKbXVsdGlwbGVfbG0gPC0gbG0oYE5ldCBJbmNvbWVgIH4gLiwgZGF0YSA9IG1vZGVsX2RhdGEpCmBgYAoKCmBgYHtyfQojIFByaW50IHN1bW1hcnkgb2YgdGhlIG1vZGVsCnN1bW1hcnkobXVsdGlwbGVfbG0pCmBgYAoKCgpgYGB7cn0KIyBSZW1vdmUgcm93cyB3aXRoIG1pc3NpbmcgdmFsdWVzCm51bWVyaWNfZGF0YSA8LSBuYS5vbWl0KG51bWVyaWNfZGF0YSkKCiMgQ2FsY3VsYXRlIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXgKY29ycmVsYXRpb25fbWF0cml4IDwtIGNvcihudW1lcmljX2RhdGEpCgojIFByaW50IHRoZSBjb3JyZWxhdGlvbiBtYXRyaXgKI3ByaW50KGNvcnJlbGF0aW9uX21hdHJpeCkKYGBgCgpgYGB7cn0KI0NoZWNrIGZvciBtaXNzaW5nIHZhbHVlcyBpbiB0aGUgcmVsZXZhbnQgY29sdW1ucwptaXNzaW5nX3ZhbHVlcyA8LSBzYXBwbHkoY29ycmVsYXRpb25fZGF0YSwgZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkKCiMgUHJpbnQgdGhlIG51bWJlciBvZiBtaXNzaW5nIHZhbHVlcyBmb3IgZWFjaCBjb2x1bW4KcHJpbnQobWlzc2luZ192YWx1ZXMpCmBgYAoKCgpgYGAKCgpgYGA=