# Load required libraries
library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)
library(plotly)
library(tidyverse)
library(scales)
library(ggrepel)
library(stringr)
library(GGally)

theme_set(theme_minimal())

Data Preprocessing

lpi <- read.csv(
  "living-planet-index.csv",
  sep = ";"
)

colnames(lpi) <- c(
  "Region",
  "Year",
  "AverageIndex",
  "UpperIndex",
  "LowerIndex"
)

lpi$Year <- as.numeric(lpi$Year)
lpi$AverageIndex <- as.numeric(lpi$AverageIndex)
lpi$UpperIndex <- as.numeric(lpi$UpperIndex)
lpi$LowerIndex <- as.numeric(lpi$LowerIndex)
species <- read.csv(
  "Species.csv",
  check.names = FALSE
)
species$Threatened <- as.numeric(
  gsub(",", "", species$`Subtotal (threatened spp.)`)
)

species$Total <- as.numeric(
  gsub(",", "", species$Total)
)

species$ThreatenedPercent <-
  (species$Threatened / species$Total) * 100

species$EN <- as.numeric(
  gsub(",", "", species$EN)
)

species$VU <- as.numeric(
  gsub(",", "", species$VU)
)

species$CR <- as.numeric(gsub(",", "", species$CR))

species_clean <- species %>%
  arrange(desc(ThreatenedPercent)) %>%
  slice(1:20)

top15 <- species %>%
  arrange(desc(Threatened)) %>%
  slice(1:15)

species_long <- top15 %>%
  select(Name, VU, EN, CR) %>%
  pivot_longer(
    cols = c(VU, EN, CR),
    names_to = "ThreatLevel",
    values_to = "Count"
  )
protected <- read.csv(
  "161a1ce8-f2e3-46c2-b830-1f9149c4f66d_Data.csv"
)

protected <- protected %>%
  select(
    Country.Name,
    X2024..YR2024.
  ) %>%
  rename(
    Country = Country.Name,
    ProtectedArea = X2024..YR2024.
  )

protected <- protected %>%
  filter(ProtectedArea != "..")

protected$ProtectedArea <- as.numeric(
  protected$ProtectedArea
)

top_protected <- protected %>%
  arrange(desc(ProtectedArea)) %>%
  slice(1:20)
df <- read_csv("Biodiversity habitat loss (Williams et al. 2021).csv")

aggregates <- c("Europe", "Latin America", "North Africa", "North America", 
                "South and East Asia", "Sub-Saharan Africa", "World")
clean_story <- df %>%
  filter(!Entity %in% aggregates) %>%
  summarise(
    Amphibians_BAU = mean(bau_habitat_loss_amphibians, na.rm = TRUE),
    Amphibians_Waste = mean(waste_habitat_loss_amphibians, na.rm = TRUE),
    Amphibians_Diets = mean(diets_habitat_loss_amphibians, na.rm = TRUE),
    Amphibians_Yields = mean(yields_habitat_loss_amphibians, na.rm = TRUE),
    Amphibians_Combined = mean(combined_habitat_loss_amphibians, na.rm = TRUE),
    
    Birds_BAU = mean(bau_habitat_loss_birds, na.rm = TRUE),
    Birds_Waste = mean(waste_habitat_loss_birds, na.rm = TRUE),
    Birds_Diets = mean(diets_habitat_loss_birds, na.rm = TRUE),
    Birds_Yields = mean(yields_habitat_loss_birds, na.rm = TRUE),
    Birds_Combined = mean(combined_habitat_loss_birds, na.rm = TRUE),
    
    Mammals_BAU = mean(bau_habitat_loss_mammals, na.rm = TRUE),
    Mammals_Waste = mean(waste_habitat_loss_mammals, na.rm = TRUE),
    Mammals_Diets = mean(diets_habitat_loss_mammals, na.rm = TRUE),
    Mammals_Yields = mean(yields_habitat_loss_mammals, na.rm = TRUE),
    Mammals_Combined = mean(combined_habitat_loss_mammals, na.rm = TRUE)
  ) %>%
  pivot_longer(
    cols = everything(),
    names_to = c("Species", "Scenario"),
    names_sep = "_"
  ) %>%
  mutate(
    Scenario = recode(Scenario, 
                      "BAU" = "Business As Usual", 
                      "Waste" = "Reduce Food Waste", 
                      "Diets" = "Dietary Shifts", 
                      "Yields" = "Improve Crop Yields", 
                      "Combined" = "All Interventions Combined"),
    Scenario = factor(Scenario, levels = c(
      "Business As Usual", 
      "Reduce Food Waste", 
      "Dietary Shifts", 
      "Improve Crop Yields", 
      "All Interventions Combined"
    ))
  )

Chart 1: Wildlife Populations Over Time (2025)

global_lpi <- lpi %>%
  group_by(Year) %>%
  summarise(
    AvgIndex = mean(
      AverageIndex,
      na.rm = TRUE
    )
  )

p1 <- ggplot(
  global_lpi,
  aes(
    x = Year,
    y = AvgIndex,
    text = paste(
      "Year:", Year,
      "<br>Index:", round(AvgIndex,1)
    )
  )
) +
  geom_line(
    linewidth = 1.3,
    colour = "darkgreen"
  ) +
  geom_point(size = 2) +
  labs(
    title = "Wildlife Populations Over Time",
    x = "Year",
    y = "Living Planet Index"
  )

ggplotly(
  p1,
  tooltip = "text"
)

Chart 2: Biodiversity Loss Across Regions

latest <- lpi %>%
  filter(
    Year == max(Year)
  )

p2 <- ggplot(
  latest,
  aes(
    reorder(
      Region,
      AverageIndex
    ),
    AverageIndex,
    text = paste(
      Region,
      "<br>Index:",
      round(AverageIndex,1)
    )
  )
) +
  geom_col(
    fill = "steelblue"
  ) +
  coord_flip() +
  labs(
    title = "Biodiversity By Region",
    x = "",
    y = "Index"
  )

ggplotly(
  p2,
  tooltip = "text"
)

Chart 3: Threat Composition Across Species Groups

species_heat <- species %>%
  select(Name, CR, EN, VU)

species_heat$CR <- as.numeric(gsub(",", "", species_heat$CR))
species_heat$EN <- as.numeric(gsub(",", "", species_heat$EN))
species_heat$VU <- as.numeric(gsub(",", "", species_heat$VU))

species_heat <- species_heat %>%
  pivot_longer(
    cols = c(CR, EN, VU),
    names_to = "ThreatLevel",
    values_to = "Count"
  )

top_species <- species %>%
  mutate(
    Threatened = as.numeric(
      gsub(",", "", `Subtotal (threatened spp.)`)
    )
  ) %>%
  arrange(desc(Threatened)) %>%
  slice(1:15)

species_heat <- species_heat %>%
  filter(Name %in% top_species$Name)

p3 <- ggplot(
  species_heat,
  aes(
    x = ThreatLevel,
    y = reorder(Name, Count),
    fill = Count
  )
) +
  geom_tile() +
  scale_fill_gradient(
    low = "#fee8c8",
    high = "#e34a33"
  ) +
  labs(
    title = "Threat Composition Across Species Groups"
  )+
  theme(
    strip.text = element_text(size = 9),
    plot.title = element_text(size = 11),
    plot.subtitle = element_text(size = 7),
    panel.spacing = unit(2, "lines"),
    panel.grid.minor = element_blank()
  )

ggplotly(
  p3,
  tooltip = c("x", "y")
)

Chart 4: Countries Most In Need Of Conservation Action

priority_countries <- protected %>%
  filter(!is.na(ProtectedArea)) %>%
  arrange(ProtectedArea) %>%
  slice(1:20)
p4 <- ggplot(
  priority_countries,
  aes(
    x = reorder(Country, ProtectedArea),
    y = ProtectedArea
  )
) +

  geom_segment(
    aes(
      xend = Country,
      y = 0,
      yend = ProtectedArea
    ),
    colour = "grey70"
  ) +

  geom_point(
    aes(
      colour = ProtectedArea,
      size = ProtectedArea
    )
  ) +

  coord_flip() +

  labs(
    title = "Countries Most In Need Of Conservation Action",
    subtitle = "Countries with the smallest share of protected land",
    x = "",
    y = "Protected Area (%)"
  ) +

  theme_minimal()+
  theme(
    strip.text = element_text(size = 9),
    plot.title = element_text(size = 11),
    plot.subtitle = element_text(size = 7)
  )

ggplotly(
  p4,
  tooltip = c("x", "y")
)

Chart 5: What Could Save Wildlife by 2050?

# Split data by animal class
data_amphibians <- clean_story %>% filter(Species == "Amphibians")
data_birds      <- clean_story %>% filter(Species == "Birds")
data_mammals    <- clean_story %>% filter(Species == "Mammals")

# Color mapping matching performance hierarchy (Red to Green)
scenario_colors <- c(
  "Business As Usual" = "#d73027", 
  "Reduce Food Waste" = "#f46d43", 
  "Dietary Shifts" = "#fdae61", 
  "Improve Crop Yields" = "#a6d96a", 
  "All Interventions Combined" = "#1a9850"
)

# 2. Build individual subplots
create_subplot <- function(sub_data, title_text) {
  plot_ly(
    data = sub_data,
    y = ~Scenario,
    x = ~value,
    type = 'bar',
    orientation = 'h',
    color = ~Scenario,
    colors = scenario_colors,
    text = ~paste0(round(value, 2), "%"),
    textposition = 'outside',
    textfont = list(size = 10), 
    hovertemplate = paste0("<b>%{y}</b><br>Habitat Change: %{x:.2f}%<extra></extra>"),
    showlegend = FALSE
  ) %>%
    layout(
      # FIX: Changed xref and yref to "paper" and adjusted coordinates
      # This explicitly locks the heading right in the middle top of the column grid
      annotations = list(
        list(
          x = 0.5, y = 1.05, 
          text = paste0("<b>", title_text, "</b>"),
          xref = "paper", yref = "paper", 
          xanchor = "center", yanchor = "bottom",
          showarrow = FALSE, 
          font = list(size = 13, color = "black")
        )
      ),
      xaxis = list(
        title = list(text = "Habitat Change (%)", standoff = 15), 
        ticksuffix = "%"
      ),
      yaxis = list(title = "", categoryorder = "array", categoryarray = levels(sub_data$Scenario)),
      shapes = list(
        list(type = "line", x0 = 0, x1 = 0, y0 = -0.5, y1 = 4.5, 
             line = list(color = "grey40", width = 1.5, dash = "dash"))
      )
    )
}

p1 <- create_subplot(data_amphibians, "Amphibians")
p2 <- create_subplot(data_birds, "Birds")
p3 <- create_subplot(data_mammals, "Mammals")

# 3. Combine subplots and set structural spacing layout
interactive_chart <- subplot(p1, p2, p3, nrows = 1, shareY = TRUE, titleX = TRUE, margin = 0.06) %>%
  layout(
    title = list(
      text = "<b>Which Action Actually Saves Wildlife Habitats by 2050?</b><br><span style='font-size:11px;color:gray;'>Global average projected habitat change. Negative values indicate habitat destruction.</span>",
      font = list(size = 14),
      x = 0.02
    ),
    margin = list(t = 120, b = 70, l = 180, r = 30), # Expanded top margin slightly for the headings
    barmode = 'group'
  )

# View chart
interactive_chart
LS0tCnRpdGxlOiAiTUFUSDIyNzAgQXNzaWdubWVudCAzIC0gU3Rvcnl0ZWxsaW5nIHdpdGggT3BlbiBEYXRhIgphdXRob3I6ICJTd2FwbmlrYSBHYWRpZGFzdSAoUzQxNDU1NzkpIgpkYXRlOiAiMjAyNi0wNi0wOSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CiMgTG9hZCByZXF1aXJlZCBsaWJyYXJpZXMKbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShHR2FsbHkpCgp0aGVtZV9zZXQodGhlbWVfbWluaW1hbCgpKQpgYGAKIyMgRGF0YSBQcmVwcm9jZXNzaW5nCgpgYGB7cn0KbHBpIDwtIHJlYWQuY3N2KAogICJsaXZpbmctcGxhbmV0LWluZGV4LmNzdiIsCiAgc2VwID0gIjsiCikKCmNvbG5hbWVzKGxwaSkgPC0gYygKICAiUmVnaW9uIiwKICAiWWVhciIsCiAgIkF2ZXJhZ2VJbmRleCIsCiAgIlVwcGVySW5kZXgiLAogICJMb3dlckluZGV4IgopCgpscGkkWWVhciA8LSBhcy5udW1lcmljKGxwaSRZZWFyKQpscGkkQXZlcmFnZUluZGV4IDwtIGFzLm51bWVyaWMobHBpJEF2ZXJhZ2VJbmRleCkKbHBpJFVwcGVySW5kZXggPC0gYXMubnVtZXJpYyhscGkkVXBwZXJJbmRleCkKbHBpJExvd2VySW5kZXggPC0gYXMubnVtZXJpYyhscGkkTG93ZXJJbmRleCkKYGBgCgpgYGB7cn0Kc3BlY2llcyA8LSByZWFkLmNzdigKICAiU3BlY2llcy5jc3YiLAogIGNoZWNrLm5hbWVzID0gRkFMU0UKKQpzcGVjaWVzJFRocmVhdGVuZWQgPC0gYXMubnVtZXJpYygKICBnc3ViKCIsIiwgIiIsIHNwZWNpZXMkYFN1YnRvdGFsICh0aHJlYXRlbmVkIHNwcC4pYCkKKQoKc3BlY2llcyRUb3RhbCA8LSBhcy5udW1lcmljKAogIGdzdWIoIiwiLCAiIiwgc3BlY2llcyRUb3RhbCkKKQoKc3BlY2llcyRUaHJlYXRlbmVkUGVyY2VudCA8LQogIChzcGVjaWVzJFRocmVhdGVuZWQgLyBzcGVjaWVzJFRvdGFsKSAqIDEwMAoKc3BlY2llcyRFTiA8LSBhcy5udW1lcmljKAogIGdzdWIoIiwiLCAiIiwgc3BlY2llcyRFTikKKQoKc3BlY2llcyRWVSA8LSBhcy5udW1lcmljKAogIGdzdWIoIiwiLCAiIiwgc3BlY2llcyRWVSkKKQoKc3BlY2llcyRDUiA8LSBhcy5udW1lcmljKGdzdWIoIiwiLCAiIiwgc3BlY2llcyRDUikpCgpzcGVjaWVzX2NsZWFuIDwtIHNwZWNpZXMgJT4lCiAgYXJyYW5nZShkZXNjKFRocmVhdGVuZWRQZXJjZW50KSkgJT4lCiAgc2xpY2UoMToyMCkKCnRvcDE1IDwtIHNwZWNpZXMgJT4lCiAgYXJyYW5nZShkZXNjKFRocmVhdGVuZWQpKSAlPiUKICBzbGljZSgxOjE1KQoKc3BlY2llc19sb25nIDwtIHRvcDE1ICU+JQogIHNlbGVjdChOYW1lLCBWVSwgRU4sIENSKSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gYyhWVSwgRU4sIENSKSwKICAgIG5hbWVzX3RvID0gIlRocmVhdExldmVsIiwKICAgIHZhbHVlc190byA9ICJDb3VudCIKICApCmBgYAoKYGBge3J9CnByb3RlY3RlZCA8LSByZWFkLmNzdigKICAiMTYxYTFjZTgtZjJlMy00NmMyLWI4MzAtMWY5MTQ5YzRmNjZkX0RhdGEuY3N2IgopCgpwcm90ZWN0ZWQgPC0gcHJvdGVjdGVkICU+JQogIHNlbGVjdCgKICAgIENvdW50cnkuTmFtZSwKICAgIFgyMDI0Li5ZUjIwMjQuCiAgKSAlPiUKICByZW5hbWUoCiAgICBDb3VudHJ5ID0gQ291bnRyeS5OYW1lLAogICAgUHJvdGVjdGVkQXJlYSA9IFgyMDI0Li5ZUjIwMjQuCiAgKQoKcHJvdGVjdGVkIDwtIHByb3RlY3RlZCAlPiUKICBmaWx0ZXIoUHJvdGVjdGVkQXJlYSAhPSAiLi4iKQoKcHJvdGVjdGVkJFByb3RlY3RlZEFyZWEgPC0gYXMubnVtZXJpYygKICBwcm90ZWN0ZWQkUHJvdGVjdGVkQXJlYQopCgp0b3BfcHJvdGVjdGVkIDwtIHByb3RlY3RlZCAlPiUKICBhcnJhbmdlKGRlc2MoUHJvdGVjdGVkQXJlYSkpICU+JQogIHNsaWNlKDE6MjApCmBgYAoKYGBge3J9CmRmIDwtIHJlYWRfY3N2KCJCaW9kaXZlcnNpdHkgaGFiaXRhdCBsb3NzIChXaWxsaWFtcyBldCBhbC4gMjAyMSkuY3N2IikKCmFnZ3JlZ2F0ZXMgPC0gYygiRXVyb3BlIiwgIkxhdGluIEFtZXJpY2EiLCAiTm9ydGggQWZyaWNhIiwgIk5vcnRoIEFtZXJpY2EiLCAKICAgICAgICAgICAgICAgICJTb3V0aCBhbmQgRWFzdCBBc2lhIiwgIlN1Yi1TYWhhcmFuIEFmcmljYSIsICJXb3JsZCIpCmNsZWFuX3N0b3J5IDwtIGRmICU+JQogIGZpbHRlcighRW50aXR5ICVpbiUgYWdncmVnYXRlcykgJT4lCiAgc3VtbWFyaXNlKAogICAgQW1waGliaWFuc19CQVUgPSBtZWFuKGJhdV9oYWJpdGF0X2xvc3NfYW1waGliaWFucywgbmEucm0gPSBUUlVFKSwKICAgIEFtcGhpYmlhbnNfV2FzdGUgPSBtZWFuKHdhc3RlX2hhYml0YXRfbG9zc19hbXBoaWJpYW5zLCBuYS5ybSA9IFRSVUUpLAogICAgQW1waGliaWFuc19EaWV0cyA9IG1lYW4oZGlldHNfaGFiaXRhdF9sb3NzX2FtcGhpYmlhbnMsIG5hLnJtID0gVFJVRSksCiAgICBBbXBoaWJpYW5zX1lpZWxkcyA9IG1lYW4oeWllbGRzX2hhYml0YXRfbG9zc19hbXBoaWJpYW5zLCBuYS5ybSA9IFRSVUUpLAogICAgQW1waGliaWFuc19Db21iaW5lZCA9IG1lYW4oY29tYmluZWRfaGFiaXRhdF9sb3NzX2FtcGhpYmlhbnMsIG5hLnJtID0gVFJVRSksCiAgICAKICAgIEJpcmRzX0JBVSA9IG1lYW4oYmF1X2hhYml0YXRfbG9zc19iaXJkcywgbmEucm0gPSBUUlVFKSwKICAgIEJpcmRzX1dhc3RlID0gbWVhbih3YXN0ZV9oYWJpdGF0X2xvc3NfYmlyZHMsIG5hLnJtID0gVFJVRSksCiAgICBCaXJkc19EaWV0cyA9IG1lYW4oZGlldHNfaGFiaXRhdF9sb3NzX2JpcmRzLCBuYS5ybSA9IFRSVUUpLAogICAgQmlyZHNfWWllbGRzID0gbWVhbih5aWVsZHNfaGFiaXRhdF9sb3NzX2JpcmRzLCBuYS5ybSA9IFRSVUUpLAogICAgQmlyZHNfQ29tYmluZWQgPSBtZWFuKGNvbWJpbmVkX2hhYml0YXRfbG9zc19iaXJkcywgbmEucm0gPSBUUlVFKSwKICAgIAogICAgTWFtbWFsc19CQVUgPSBtZWFuKGJhdV9oYWJpdGF0X2xvc3NfbWFtbWFscywgbmEucm0gPSBUUlVFKSwKICAgIE1hbW1hbHNfV2FzdGUgPSBtZWFuKHdhc3RlX2hhYml0YXRfbG9zc19tYW1tYWxzLCBuYS5ybSA9IFRSVUUpLAogICAgTWFtbWFsc19EaWV0cyA9IG1lYW4oZGlldHNfaGFiaXRhdF9sb3NzX21hbW1hbHMsIG5hLnJtID0gVFJVRSksCiAgICBNYW1tYWxzX1lpZWxkcyA9IG1lYW4oeWllbGRzX2hhYml0YXRfbG9zc19tYW1tYWxzLCBuYS5ybSA9IFRSVUUpLAogICAgTWFtbWFsc19Db21iaW5lZCA9IG1lYW4oY29tYmluZWRfaGFiaXRhdF9sb3NzX21hbW1hbHMsIG5hLnJtID0gVFJVRSkKICApICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSBldmVyeXRoaW5nKCksCiAgICBuYW1lc190byA9IGMoIlNwZWNpZXMiLCAiU2NlbmFyaW8iKSwKICAgIG5hbWVzX3NlcCA9ICJfIgogICkgJT4lCiAgbXV0YXRlKAogICAgU2NlbmFyaW8gPSByZWNvZGUoU2NlbmFyaW8sIAogICAgICAgICAgICAgICAgICAgICAgIkJBVSIgPSAiQnVzaW5lc3MgQXMgVXN1YWwiLCAKICAgICAgICAgICAgICAgICAgICAgICJXYXN0ZSIgPSAiUmVkdWNlIEZvb2QgV2FzdGUiLCAKICAgICAgICAgICAgICAgICAgICAgICJEaWV0cyIgPSAiRGlldGFyeSBTaGlmdHMiLCAKICAgICAgICAgICAgICAgICAgICAgICJZaWVsZHMiID0gIkltcHJvdmUgQ3JvcCBZaWVsZHMiLCAKICAgICAgICAgICAgICAgICAgICAgICJDb21iaW5lZCIgPSAiQWxsIEludGVydmVudGlvbnMgQ29tYmluZWQiKSwKICAgIFNjZW5hcmlvID0gZmFjdG9yKFNjZW5hcmlvLCBsZXZlbHMgPSBjKAogICAgICAiQnVzaW5lc3MgQXMgVXN1YWwiLCAKICAgICAgIlJlZHVjZSBGb29kIFdhc3RlIiwgCiAgICAgICJEaWV0YXJ5IFNoaWZ0cyIsIAogICAgICAiSW1wcm92ZSBDcm9wIFlpZWxkcyIsIAogICAgICAiQWxsIEludGVydmVudGlvbnMgQ29tYmluZWQiCiAgICApKQogICkKYGBgCiMjIENoYXJ0IDE6IFdpbGRsaWZlIFBvcHVsYXRpb25zIE92ZXIgVGltZSAoMjAyNSkKYGBge3J9Cmdsb2JhbF9scGkgPC0gbHBpICU+JQogIGdyb3VwX2J5KFllYXIpICU+JQogIHN1bW1hcmlzZSgKICAgIEF2Z0luZGV4ID0gbWVhbigKICAgICAgQXZlcmFnZUluZGV4LAogICAgICBuYS5ybSA9IFRSVUUKICAgICkKICApCgpwMSA8LSBnZ3Bsb3QoCiAgZ2xvYmFsX2xwaSwKICBhZXMoCiAgICB4ID0gWWVhciwKICAgIHkgPSBBdmdJbmRleCwKICAgIHRleHQgPSBwYXN0ZSgKICAgICAgIlllYXI6IiwgWWVhciwKICAgICAgIjxicj5JbmRleDoiLCByb3VuZChBdmdJbmRleCwxKQogICAgKQogICkKKSArCiAgZ2VvbV9saW5lKAogICAgbGluZXdpZHRoID0gMS4zLAogICAgY29sb3VyID0gImRhcmtncmVlbiIKICApICsKICBnZW9tX3BvaW50KHNpemUgPSAyKSArCiAgbGFicygKICAgIHRpdGxlID0gIldpbGRsaWZlIFBvcHVsYXRpb25zIE92ZXIgVGltZSIsCiAgICB4ID0gIlllYXIiLAogICAgeSA9ICJMaXZpbmcgUGxhbmV0IEluZGV4IgogICkKCmdncGxvdGx5KAogIHAxLAogIHRvb2x0aXAgPSAidGV4dCIKKQpgYGAKCiMjIENoYXJ0IDI6IEJpb2RpdmVyc2l0eSBMb3NzIEFjcm9zcyBSZWdpb25zCmBgYHtyfQpsYXRlc3QgPC0gbHBpICU+JQogIGZpbHRlcigKICAgIFllYXIgPT0gbWF4KFllYXIpCiAgKQoKcDIgPC0gZ2dwbG90KAogIGxhdGVzdCwKICBhZXMoCiAgICByZW9yZGVyKAogICAgICBSZWdpb24sCiAgICAgIEF2ZXJhZ2VJbmRleAogICAgKSwKICAgIEF2ZXJhZ2VJbmRleCwKICAgIHRleHQgPSBwYXN0ZSgKICAgICAgUmVnaW9uLAogICAgICAiPGJyPkluZGV4OiIsCiAgICAgIHJvdW5kKEF2ZXJhZ2VJbmRleCwxKQogICAgKQogICkKKSArCiAgZ2VvbV9jb2woCiAgICBmaWxsID0gInN0ZWVsYmx1ZSIKICApICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJCaW9kaXZlcnNpdHkgQnkgUmVnaW9uIiwKICAgIHggPSAiIiwKICAgIHkgPSAiSW5kZXgiCiAgKQoKZ2dwbG90bHkoCiAgcDIsCiAgdG9vbHRpcCA9ICJ0ZXh0IgopCmBgYAoKIyMgQ2hhcnQgMzogVGhyZWF0IENvbXBvc2l0aW9uIEFjcm9zcyBTcGVjaWVzIEdyb3VwcwpgYGB7cn0Kc3BlY2llc19oZWF0IDwtIHNwZWNpZXMgJT4lCiAgc2VsZWN0KE5hbWUsIENSLCBFTiwgVlUpCgpzcGVjaWVzX2hlYXQkQ1IgPC0gYXMubnVtZXJpYyhnc3ViKCIsIiwgIiIsIHNwZWNpZXNfaGVhdCRDUikpCnNwZWNpZXNfaGVhdCRFTiA8LSBhcy5udW1lcmljKGdzdWIoIiwiLCAiIiwgc3BlY2llc19oZWF0JEVOKSkKc3BlY2llc19oZWF0JFZVIDwtIGFzLm51bWVyaWMoZ3N1YigiLCIsICIiLCBzcGVjaWVzX2hlYXQkVlUpKQoKc3BlY2llc19oZWF0IDwtIHNwZWNpZXNfaGVhdCAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gYyhDUiwgRU4sIFZVKSwKICAgIG5hbWVzX3RvID0gIlRocmVhdExldmVsIiwKICAgIHZhbHVlc190byA9ICJDb3VudCIKICApCgp0b3Bfc3BlY2llcyA8LSBzcGVjaWVzICU+JQogIG11dGF0ZSgKICAgIFRocmVhdGVuZWQgPSBhcy5udW1lcmljKAogICAgICBnc3ViKCIsIiwgIiIsIGBTdWJ0b3RhbCAodGhyZWF0ZW5lZCBzcHAuKWApCiAgICApCiAgKSAlPiUKICBhcnJhbmdlKGRlc2MoVGhyZWF0ZW5lZCkpICU+JQogIHNsaWNlKDE6MTUpCgpzcGVjaWVzX2hlYXQgPC0gc3BlY2llc19oZWF0ICU+JQogIGZpbHRlcihOYW1lICVpbiUgdG9wX3NwZWNpZXMkTmFtZSkKCnAzIDwtIGdncGxvdCgKICBzcGVjaWVzX2hlYXQsCiAgYWVzKAogICAgeCA9IFRocmVhdExldmVsLAogICAgeSA9IHJlb3JkZXIoTmFtZSwgQ291bnQpLAogICAgZmlsbCA9IENvdW50CiAgKQopICsKICBnZW9tX3RpbGUoKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudCgKICAgIGxvdyA9ICIjZmVlOGM4IiwKICAgIGhpZ2ggPSAiI2UzNGEzMyIKICApICsKICBsYWJzKAogICAgdGl0bGUgPSAiVGhyZWF0IENvbXBvc2l0aW9uIEFjcm9zcyBTcGVjaWVzIEdyb3VwcyIKICApKwogIHRoZW1lKAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSwKICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDIsICJsaW5lcyIpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCmdncGxvdGx5KAogIHAzLAogIHRvb2x0aXAgPSBjKCJ4IiwgInkiKQopCmBgYAoKIyMgQ2hhcnQgNDogQ291bnRyaWVzIE1vc3QgSW4gTmVlZCBPZiBDb25zZXJ2YXRpb24gQWN0aW9uCmBgYHtyfQpwcmlvcml0eV9jb3VudHJpZXMgPC0gcHJvdGVjdGVkICU+JQogIGZpbHRlcighaXMubmEoUHJvdGVjdGVkQXJlYSkpICU+JQogIGFycmFuZ2UoUHJvdGVjdGVkQXJlYSkgJT4lCiAgc2xpY2UoMToyMCkKcDQgPC0gZ2dwbG90KAogIHByaW9yaXR5X2NvdW50cmllcywKICBhZXMoCiAgICB4ID0gcmVvcmRlcihDb3VudHJ5LCBQcm90ZWN0ZWRBcmVhKSwKICAgIHkgPSBQcm90ZWN0ZWRBcmVhCiAgKQopICsKCiAgZ2VvbV9zZWdtZW50KAogICAgYWVzKAogICAgICB4ZW5kID0gQ291bnRyeSwKICAgICAgeSA9IDAsCiAgICAgIHllbmQgPSBQcm90ZWN0ZWRBcmVhCiAgICApLAogICAgY29sb3VyID0gImdyZXk3MCIKICApICsKCiAgZ2VvbV9wb2ludCgKICAgIGFlcygKICAgICAgY29sb3VyID0gUHJvdGVjdGVkQXJlYSwKICAgICAgc2l6ZSA9IFByb3RlY3RlZEFyZWEKICAgICkKICApICsKCiAgY29vcmRfZmxpcCgpICsKCiAgbGFicygKICAgIHRpdGxlID0gIkNvdW50cmllcyBNb3N0IEluIE5lZWQgT2YgQ29uc2VydmF0aW9uIEFjdGlvbiIsCiAgICBzdWJ0aXRsZSA9ICJDb3VudHJpZXMgd2l0aCB0aGUgc21hbGxlc3Qgc2hhcmUgb2YgcHJvdGVjdGVkIGxhbmQiLAogICAgeCA9ICIiLAogICAgeSA9ICJQcm90ZWN0ZWQgQXJlYSAoJSkiCiAgKSArCgogIHRoZW1lX21pbmltYWwoKSsKICB0aGVtZSgKICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gNykKICApCgpnZ3Bsb3RseSgKICBwNCwKICB0b29sdGlwID0gYygieCIsICJ5IikKKQpgYGAKCiMjIENoYXJ0IDU6IFdoYXQgQ291bGQgU2F2ZSBXaWxkbGlmZSBieSAyMDUwPwpgYGB7cn0KIyBTcGxpdCBkYXRhIGJ5IGFuaW1hbCBjbGFzcwpkYXRhX2FtcGhpYmlhbnMgPC0gY2xlYW5fc3RvcnkgJT4lIGZpbHRlcihTcGVjaWVzID09ICJBbXBoaWJpYW5zIikKZGF0YV9iaXJkcyAgICAgIDwtIGNsZWFuX3N0b3J5ICU+JSBmaWx0ZXIoU3BlY2llcyA9PSAiQmlyZHMiKQpkYXRhX21hbW1hbHMgICAgPC0gY2xlYW5fc3RvcnkgJT4lIGZpbHRlcihTcGVjaWVzID09ICJNYW1tYWxzIikKCiMgQ29sb3IgbWFwcGluZyBtYXRjaGluZyBwZXJmb3JtYW5jZSBoaWVyYXJjaHkgKFJlZCB0byBHcmVlbikKc2NlbmFyaW9fY29sb3JzIDwtIGMoCiAgIkJ1c2luZXNzIEFzIFVzdWFsIiA9ICIjZDczMDI3IiwgCiAgIlJlZHVjZSBGb29kIFdhc3RlIiA9ICIjZjQ2ZDQzIiwgCiAgIkRpZXRhcnkgU2hpZnRzIiA9ICIjZmRhZTYxIiwgCiAgIkltcHJvdmUgQ3JvcCBZaWVsZHMiID0gIiNhNmQ5NmEiLCAKICAiQWxsIEludGVydmVudGlvbnMgQ29tYmluZWQiID0gIiMxYTk4NTAiCikKCiMgMi4gQnVpbGQgaW5kaXZpZHVhbCBzdWJwbG90cwpjcmVhdGVfc3VicGxvdCA8LSBmdW5jdGlvbihzdWJfZGF0YSwgdGl0bGVfdGV4dCkgewogIHBsb3RfbHkoCiAgICBkYXRhID0gc3ViX2RhdGEsCiAgICB5ID0gflNjZW5hcmlvLAogICAgeCA9IH52YWx1ZSwKICAgIHR5cGUgPSAnYmFyJywKICAgIG9yaWVudGF0aW9uID0gJ2gnLAogICAgY29sb3IgPSB+U2NlbmFyaW8sCiAgICBjb2xvcnMgPSBzY2VuYXJpb19jb2xvcnMsCiAgICB0ZXh0ID0gfnBhc3RlMChyb3VuZCh2YWx1ZSwgMiksICIlIiksCiAgICB0ZXh0cG9zaXRpb24gPSAnb3V0c2lkZScsCiAgICB0ZXh0Zm9udCA9IGxpc3Qoc2l6ZSA9IDEwKSwgCiAgICBob3ZlcnRlbXBsYXRlID0gcGFzdGUwKCI8Yj4le3l9PC9iPjxicj5IYWJpdGF0IENoYW5nZTogJXt4Oi4yZn0lPGV4dHJhPjwvZXh0cmE+IiksCiAgICBzaG93bGVnZW5kID0gRkFMU0UKICApICU+JQogICAgbGF5b3V0KAogICAgICAjIEZJWDogQ2hhbmdlZCB4cmVmIGFuZCB5cmVmIHRvICJwYXBlciIgYW5kIGFkanVzdGVkIGNvb3JkaW5hdGVzCiAgICAgICMgVGhpcyBleHBsaWNpdGx5IGxvY2tzIHRoZSBoZWFkaW5nIHJpZ2h0IGluIHRoZSBtaWRkbGUgdG9wIG9mIHRoZSBjb2x1bW4gZ3JpZAogICAgICBhbm5vdGF0aW9ucyA9IGxpc3QoCiAgICAgICAgbGlzdCgKICAgICAgICAgIHggPSAwLjUsIHkgPSAxLjA1LCAKICAgICAgICAgIHRleHQgPSBwYXN0ZTAoIjxiPiIsIHRpdGxlX3RleHQsICI8L2I+IiksCiAgICAgICAgICB4cmVmID0gInBhcGVyIiwgeXJlZiA9ICJwYXBlciIsIAogICAgICAgICAgeGFuY2hvciA9ICJjZW50ZXIiLCB5YW5jaG9yID0gImJvdHRvbSIsCiAgICAgICAgICBzaG93YXJyb3cgPSBGQUxTRSwgCiAgICAgICAgICBmb250ID0gbGlzdChzaXplID0gMTMsIGNvbG9yID0gImJsYWNrIikKICAgICAgICApCiAgICAgICksCiAgICAgIHhheGlzID0gbGlzdCgKICAgICAgICB0aXRsZSA9IGxpc3QodGV4dCA9ICJIYWJpdGF0IENoYW5nZSAoJSkiLCBzdGFuZG9mZiA9IDE1KSwgCiAgICAgICAgdGlja3N1ZmZpeCA9ICIlIgogICAgICApLAogICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiIiwgY2F0ZWdvcnlvcmRlciA9ICJhcnJheSIsIGNhdGVnb3J5YXJyYXkgPSBsZXZlbHMoc3ViX2RhdGEkU2NlbmFyaW8pKSwKICAgICAgc2hhcGVzID0gbGlzdCgKICAgICAgICBsaXN0KHR5cGUgPSAibGluZSIsIHgwID0gMCwgeDEgPSAwLCB5MCA9IC0wLjUsIHkxID0gNC41LCAKICAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gImdyZXk0MCIsIHdpZHRoID0gMS41LCBkYXNoID0gImRhc2giKSkKICAgICAgKQogICAgKQp9CgpwMSA8LSBjcmVhdGVfc3VicGxvdChkYXRhX2FtcGhpYmlhbnMsICJBbXBoaWJpYW5zIikKcDIgPC0gY3JlYXRlX3N1YnBsb3QoZGF0YV9iaXJkcywgIkJpcmRzIikKcDMgPC0gY3JlYXRlX3N1YnBsb3QoZGF0YV9tYW1tYWxzLCAiTWFtbWFscyIpCgojIDMuIENvbWJpbmUgc3VicGxvdHMgYW5kIHNldCBzdHJ1Y3R1cmFsIHNwYWNpbmcgbGF5b3V0CmludGVyYWN0aXZlX2NoYXJ0IDwtIHN1YnBsb3QocDEsIHAyLCBwMywgbnJvd3MgPSAxLCBzaGFyZVkgPSBUUlVFLCB0aXRsZVggPSBUUlVFLCBtYXJnaW4gPSAwLjA2KSAlPiUKICBsYXlvdXQoCiAgICB0aXRsZSA9IGxpc3QoCiAgICAgIHRleHQgPSAiPGI+V2hpY2ggQWN0aW9uIEFjdHVhbGx5IFNhdmVzIFdpbGRsaWZlIEhhYml0YXRzIGJ5IDIwNTA/PC9iPjxicj48c3BhbiBzdHlsZT0nZm9udC1zaXplOjExcHg7Y29sb3I6Z3JheTsnPkdsb2JhbCBhdmVyYWdlIHByb2plY3RlZCBoYWJpdGF0IGNoYW5nZS4gTmVnYXRpdmUgdmFsdWVzIGluZGljYXRlIGhhYml0YXQgZGVzdHJ1Y3Rpb24uPC9zcGFuPiIsCiAgICAgIGZvbnQgPSBsaXN0KHNpemUgPSAxNCksCiAgICAgIHggPSAwLjAyCiAgICApLAogICAgbWFyZ2luID0gbGlzdCh0ID0gMTIwLCBiID0gNzAsIGwgPSAxODAsIHIgPSAzMCksICMgRXhwYW5kZWQgdG9wIG1hcmdpbiBzbGlnaHRseSBmb3IgdGhlIGhlYWRpbmdzCiAgICBiYXJtb2RlID0gJ2dyb3VwJwogICkKCiMgVmlldyBjaGFydAppbnRlcmFjdGl2ZV9jaGFydApgYGAK