library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.0     ✔ readr     2.1.5
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.0     ✔ tibble    3.3.0
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.2.0     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(plotly)
## 
## Attaching package: 'plotly'
## 
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## 
## The following object is masked from 'package:stats':
## 
##     filter
## 
## The following object is masked from 'package:graphics':
## 
##     layout
library(readr)
library(janitor)
## 
## Attaching package: 'janitor'
## 
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
library(htmlwidgets)

# -----------------------------
# DATA
# -----------------------------
ev <- read_csv("bmw_ev_transition.csv", show_col_types = FALSE) %>%
  clean_names() %>%
  mutate(series = str_to_title(series))

actual <- ev %>% filter(series == "Actual")

last_actual_year  <- max(actual$year, na.rm = TRUE)
last_actual_value <- actual %>% filter(year == last_actual_year) %>% pull(ev_share_pct)

forecast_2035 <- 80

required_path <- tibble(
  year = seq(last_actual_year, 2035, by = 1),
  ev_share_pct = seq(last_actual_value, forecast_2035,
                     length.out = length(seq(last_actual_year, 2035, by = 1)))
)

# -----------------------------
# POLICY MILESTONES
# -----------------------------
policy <- tibble(
  year = c(2025, 2030, 2035),
  y    = c(28, 52, 78),
  label = c(
    "EU CO₂ Fleet Targets (Fit for 55) – tightening",
    "EU 2030 CO₂ Reduction Target (~55%)",
    "EU 2035 ICE Ban (Zero-emission mandate)"
  ),
  short = c("2025", "2030", "2035")
)

# -----------------------------
# PLOTLY INTERACTIVE CHART
# -----------------------------
p <- plot_ly()

# Actual BMW EV share
p <- p %>%
  add_lines(
    data = actual,
    x = ~year, y = ~ev_share_pct,
    name = "BMW actual EV share",
    line = list(color = "#0072B2", width = 4),
    marker = list(color = "#0072B2", size = 7),
    hovertemplate = paste(
      "<b>BMW actual EV share</b><br>",
      "Year: %{x}<br>",
      "EV share: %{y:.1f}%<extra></extra>"
    )
  ) %>%
  add_markers(
    data = actual,
    x = ~year, y = ~ev_share_pct,
    name = "BMW actual EV share",
    marker = list(color = "#0072B2", size = 8),
    showlegend = FALSE,
    hovertemplate = paste(
      "<b>BMW actual EV share</b><br>",
      "Year: %{x}<br>",
      "EV share: %{y:.1f}%<extra></extra>"
    )
  )

# Required path
p <- p %>%
  add_lines(
    data = required_path,
    x = ~year, y = ~ev_share_pct,
    name = "Required path to 2035",
    line = list(color = "#5C5C5C", width = 3, dash = "dash"),
    hovertemplate = paste(
      "<b>Required path to 2035</b><br>",
      "Year: %{x}<br>",
      "Implied EV share: %{y:.1f}%<extra></extra>"
    )
  )

# Policy milestone markers
p <- p %>%
  add_markers(
    data = policy,
    x = ~year, y = ~y,
    name = "Policy milestones",
    marker = list(
      color = "#D55E00",
      size = 12,
      symbol = "diamond"
    ),
    text = ~label,
    customdata = ~short,
    hovertemplate = paste(
      "<b>%{customdata}</b><br>",
      "%{text}<extra></extra>"
    )
  )

# Endpoint label
p <- p %>%
  add_text(
    x = 2035.25, y = forecast_2035,
    text = "~80%",
    textposition = "middle right",
    showlegend = FALSE,
    textfont = list(size = 18, color = "#5C5C5C", family = "Arial Black")
  )

# Layout
p <- p %>%
  layout(
    title = list(
      text = paste0(
        "<b>BMW Is Electrifying — But Policy Requires ~80% EV by 2035</b>",
        "<br><sup>Click or hover on the orange markers to inspect major policy pressure points.</sup>"
      ),
      x = 0.01,
      xanchor = "left"
    ),
    xaxis = list(
      title = "",
      range = c(2009.5, 2036),
      tickvals = c(2010, 2015, 2020, 2025, 2030, 2035),
      showgrid = FALSE,
      zeroline = FALSE
    ),
    yaxis = list(
      title = list(text = "<b>EV share of BMW global deliveries</b>"),
      range = c(0, 90),
      tickvals = c(0, 20, 40, 60, 80),
      ticksuffix = "%",
      gridcolor = "#E6E6E6",
      zeroline = FALSE
    ),
    legend = list(
      orientation = "h",
      x = 0.02,
      y = 1.08
    ),
    shapes = list(
      list(
        type = "rect",
        x0 = 2030, x1 = 2035.5,
        y0 = 0, y1 = 90,
        fillcolor = "rgba(217,217,217,0.20)",
        line = list(width = 0),
        layer = "below"
      )
    ),
    annotations = list(
      list(
        x = 2032.7, y = 86,
        text = "<b>Policy target zone</b>",
        showarrow = FALSE,
        font = list(size = 16, color = "#5C5C5C")
      )
    ),
    plot_bgcolor = "white",
    paper_bgcolor = "white",
    margin = list(l = 90, r = 90, t = 100, b = 70)
  )

# Show in Viewer
p
## A marker object has been specified, but markers is not in the mode
## Adding markers to the mode...
# Save interactive html file
saveWidget(p, "plot_1_bmw_ev_transition_interactive.html", selfcontained = TRUE)
## A marker object has been specified, but markers is not in the mode
## Adding markers to the mode...