library(ggplot2)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggrepel)
## Warning: package 'ggrepel' was built under R version 4.3.3
#COSTS
current_rent <- 675.0
july1_rent <- 520.0

avg_food <- 300.0
target_food <- 200.0

insure_cost_semester <- 700.0

tuition_fee_semester <- 1600

#defining a function
cumulative_cost <- function(months) {
  # Fixed values
  current_rent <- 675.0
  july1_rent <- 520.0
  avg_food <- 300.0
  target_food <- 200.0
  insure_cost_semester <- 700.0
  tuition_fee_semester <- 1600.0

  # Choose appropriate rent based on month count
  if (months < 2) {
    rent_per_month <- current_rent
  } else {
    rent_per_month <- july1_rent
  }

  # Total rent and food
  total_rent <- rent_per_month * months
  total_food <- target_food * months

  # Semester-based costs (assume 1 semester = 5 months)
  semester_counter = -5 + months
  semesters <- ceiling(semester_counter / 5)
  total_insurance <- semesters * insure_cost_semester
  total_tuition <- semesters * tuition_fee_semester

  # Total cost
  total_cost <- total_rent + total_food + total_insurance + total_tuition
  return(total_cost)
}


#better functions which allows flexible cost changes and projections


initial_money <- 10000  # Example starting money

# Function to generate monthly cumulative cost
generate_projection <- function(name, months, rent, food, insure_cost, tuition_cost, transit, gym, income, initial_money) {
  cumulative_costs <- numeric(months)
  remaining_money <- numeric(months)  # Initialize remaining_money vector
  total_insurance <- 0
  total_tuition <- 0
  
  for (m in 1:months) {
    total_rent <- rent * m
    total_food <- food * m
    total_gym <- gym * m
    total_transit <- transit * m
    total_income <- -income * m
    #canadian government money
    total_income =  total_income - (200 * m)
    
     if (m %% 5 == 0) {
      total_insurance <- total_insurance + insure_cost
      total_tuition <- total_tuition + tuition_cost
    }
    
    cumulative_costs[m] <- total_rent + total_food + total_insurance + total_tuition + total_gym + total_transit + total_income
    
    remaining_money[m] <- initial_money - cumulative_costs[m]
  }
  
  # Return data frame with all projections
  data.frame(
    Month = 1:months,
    CumulativeCost = cumulative_costs,
    RemainingMoney = remaining_money,
    Projection = name
  )
}


# Define different projections (scenarios)
months <- 12

# Scenario 1: Baseline
proj1 <- generate_projection(
  name = "Current Living Expenses",
  months = months,
  rent = 675,             # Post-July rent
  food = 300,
  insure_cost = 700,
  tuition_cost = 1600,
  transit =40,
  gym = 50,
  income = 0,
  initial_money = initial_money
)


# Scenario 2: Reduced Food Budget
proj2 <- generate_projection(
  name = "Current Living Expenses + Income (400euros/month)",
  months = months,
  rent = 675,
  food = 300,             # Lower food cost
  insure_cost = 700,
  tuition_cost = 1600,
  transit =40,
  gym = 50,
  income = 400,
  initial_money = initial_money
)

#Gym, tight food budgeting, income
proj3 <- generate_projection(
  name = "Reduced Rent and Income (400euros/month)",
  months = months,
  rent = 520,             # Hypothetical rent hike
  food = 300,
  insure_cost = 700,
  tuition_cost = 1600,
  transit = 40,
  gym = 50,
  income = 400,
  initial_money = initial_money
)

#Scenario 4: Bare minimum
proj4 <- generate_projection(
  name = "Reduced Rent, Reduced Food (120euros/month)\nIncome (400euros/month), No Gym, No Transit ",
  months = months,
  rent = 520,
  food = 120,
  insure_cost = 700,
  tuition_cost = 1600,
  transit =0,
  gym = 0,
  income = 400,
  initial_money = initial_money
)

proj5 <- generate_projection(
  name = "Bare Minimum; Increased Income (850euros/month)",
  months = months,
  rent = 520,
  food = 120,
  insure_cost = 700,
  tuition_cost = 1600,
  transit =0,
  gym = 0,
  income = 850,
  initial_money = initial_money
)

proj6 <- generate_projection(
  name = "Realistic Projection: Low Food (200euros/month)\nNo Transit, Cheap Gym, Income (650euros/month)",
  months = months,
  rent = 520,
  food = 200,
  insure_cost = 700,
  tuition_cost = 1600,
  transit =0,
  gym = 20,
  income = 650,
  initial_money = initial_money
)

proj7 <- generate_projection(
  name = "Realistic Projection: Low Food (200euros/month)\nNo Transit, Cheap Gym, High Income (850euros/month)",
  months = months,
  rent = 520,
  food = 200,
  insure_cost = 700,
  tuition_cost = 1600,
  transit =0,
  gym = 20,
  income = 850,
  initial_money = initial_money
)

# Combine all scenarios
all_proj <- bind_rows(proj1, proj2, proj3, proj4, proj5, proj6, proj7)

# Plot
label_data <- all_proj %>%
  group_by(Projection) %>%
  filter(Month == max(Month))

plot_colors <- RColorBrewer::brewer.pal(15, "Set2")
## Warning in RColorBrewer::brewer.pal(15, "Set2"): n too large, allowed maximum for palette Set2 is 8
## Returning the palette you asked for with that many colors
# Plot with direct labels
ggplot(all_proj, aes(x = Month)) +
  # Remaining money line
  geom_line(aes(y = RemainingMoney, color = Projection), linetype = "dashed", size = 0.5) +
  # Cumulative cost line
  geom_line(aes(y = CumulativeCost, color = Projection), size = 1.2) +
  # Labels for each projection at the end
  geom_text_repel(
    data = label_data,
    aes(label = Projection, y = CumulativeCost, color = Projection),
    hjust = 0,
    nudge_x = 0.5,
    direction = "y",
    show.legend = FALSE,
    segment.color = "grey50"
  ) +
  # Horizontal dotted line at y = 0 (baseline for remaining money)
  geom_hline(yintercept = 0, linetype = "dotted", color = "black") +
  scale_color_manual(values = plot_colors) +  # Color the lines using fcolors vector
  labs(
    title = "Cumulative Cost and Remaining Money Projections (Semester Costs Start at Month 5)",
    x = "Month",
    y = "Amount (Euros)",
    color = "Scenario"
  ) +
  theme_classic() +
  theme(legend.position = "none") +  # Remove legend
  xlim(1, max(all_proj$Month) + 10)   # Add space for labels to the right
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

#calculating the regression

#first create a lookup table
income_lookup <- tibble::tibble(
  Projection = c(unique(all_proj$Projection)),
  MonthlyIncome = c(0, 400, 400, 400, 850, 650, 850)  # Add corresponding income for each projection
)

all_proj_avgs <- all_proj %>%
  left_join(income_lookup, by = "Projection") %>%
  mutate(
    TotalIncome = Month * (MonthlyIncome + 200),   # Include Canadian gov. support
    NetCost = CumulativeCost - TotalIncome         # Net cost after income
  )

library(broom)

average_net_costs <- all_proj_avgs %>%
  group_by(Projection) %>%
  do(tidy(lm(NetCost ~ Month, data = .))) %>%
  filter(term == "Month") %>%
  rename(AverageMonthlyNetCost = estimate) %>%
  select(Projection, AverageMonthlyNetCost)
#Integration with shiny app.
library(shiny)
library(shinyjs)
## 
## Attaching package: 'shinyjs'
## The following object is masked from 'package:shiny':
## 
##     runExample
## The following objects are masked from 'package:methods':
## 
##     removeClass, show
library(ggplot2)
library(dplyr)

# UI part of the Shiny app
ui <- fluidPage(
  useShinyjs(),  # Enable shinyjs functionality
  titlePanel("Resizable Sidebar Panel"),
  
  # Layout
  sidebarLayout(
    sidebarPanel(
      # Button to toggle visibility of numeric inputs
      actionButton("toggle_btn", "Toggle Inputs"),
      
      # Create a container div to wrap the numeric inputs (only these will be toggled)
      div(id = "numeric-inputs-container", 
          fluidRow(
            column(4,  # First column (left side)
                   numericInput("months", "Number of Months", 12, min = 1),
                   numericInput("initial_money", "Starting Money (€)", 10000),
                   numericInput("rent", "Monthly Rent (€)", 520),
                   numericInput("food", "Monthly Food (€)", 200)
            ),
            
            column(4,  # Second column (middle)
                   numericInput("gym", "Monthly Gym (€)", 20),
                   numericInput("transit", "Monthly Transit (€)", 0)
            ),
            
            column(4,  # Third column (right side)
                   numericInput("income", "Monthly Income (€)", 850),
                   numericInput("insure", "Insurance per Semester (€)", 700),
                   numericInput("tuition", "Tuition per Semester (€)", 1600)
            )
          )
      ),
      
      # Keep sliders outside the toggle container so they are always visible
      sliderInput("rent_slider", "Rent Slider", min = 0, max = 2000, value = 520, step = 10),
      sliderInput("food_slider", "Food Slider", min = 0, max = 2000, value = 200, step = 10),
      sliderInput("income_slider", "Income Slider", min = 0, max = 2000, value = 850, step = 10)
    ),
    
    # Main panel for displaying the plot
    mainPanel(
      plotOutput("costPlot", height = "90vh")  # Full height of the viewport
    )
  )
)

# Server part of the Shiny app
server <- function(input, output, session) {
  
  # Toggle the visibility of numeric inputs
  observeEvent(input$toggle_btn, {
    # Hide or show the numeric inputs container using shinyjs::toggle
    toggle("numeric-inputs-container")  # Toggle visibility of the numeric inputs container
  })
  
  # Create a reactive expression for projection data that automatically updates when inputs change
  projection_data <- reactive({
    # Use the slider values directly for calculation
    months <- input$months
    cumulative_costs <- numeric(months)
    remaining_money <- numeric(months)
    total_insurance <- 0
    total_tuition <- 0
    
    for (m in 1:months) {
      # Use slider values in the calculations
      total_rent <- input$rent_slider * m
      total_food <- input$food_slider * m
      total_gym <- input$gym * m
      total_transit <- input$transit * m
      
      if (m %% 5 == 0) {
        total_insurance <- total_insurance + input$insure
        total_tuition <- total_tuition + input$tuition
      }
      
      # Expense only (without income)
      cumulative_costs[m] <- total_rent + total_food + total_gym + total_transit + total_insurance + total_tuition
      
      # Now subtract income directly from cumulative cost
      income <- input$income_slider * m + 200 * m  # Use the income slider
      cumulative_costs[m] <- cumulative_costs[m] - income
      
      # Calculate remaining money (starting with initial money)
      remaining_money[m] <- input$initial_money - cumulative_costs[m]
    }
    
    tibble(
      Month = 1:months,
      CumulativeCost = cumulative_costs,
      RemainingMoney = remaining_money
    )
  })
  
  # Render the plot based on the reactive data
  output$costPlot <- renderPlot({
    df <- projection_data()
    
    ggplot(df, aes(x = Month)) +
      geom_line(aes(y = CumulativeCost, color = "Cumulative Cost"), size = 1.2) +
      geom_line(aes(y = RemainingMoney, color = "Remaining Money"), linetype = "dashed", size = 1.2) +
      geom_hline(yintercept = 0, linetype = "dotted") +
      labs(
        title = "Cumulative Cost and Remaining Money Over Time",
        y = "€ Amount",
        x = "Month"
      ) +
      scale_color_manual(values = c("Cumulative Cost" = "red", "Remaining Money" = "blue")) +
      theme_minimal()  # Static plot
  })
  
}

# Run the app
shinyApp(ui, server)
Shiny applications not supported in static R Markdown documents