Analisis Spasial-Temporal Determinan Banjir Pulau Sumatera Menggunakan Geographically Weighted Panel Regression Untuk Kebijakan Pembangunan Wilayah Dan Mitigasi Bencana Berkelanjutan

Penerapan Metode Geographically Weighted Panel Regression (GWPR) untuk mengindentifikasifaktor penyebab Kejadian Banjir di Pulau Sumatera pada tahun 2010-2024 berbasis data lingkungan

Ahmad Helmi Yasir

2026-02-01

Anggota Kelompok

  • Ahmad Helmi Yasir (Ketua)
  • Najla Khalisa
  • Gusti Luqman Nor Hafizh
  • Muhammad Ihsan
  • Nur Ridho Arif Billah

1. Pustaka (Library)

Tahap pertama memuat seluruh library yang diperlukan untuk analisis data panel, spasial, dan visualisasi.

# GWPR in Sumatra Island 2010-2024 =========================================
# 1. Library ===============================================================
libs <- c("gplots", "kableExtra", "tidyverse", "plm", "tinytex", "tseries", 
          "lmtest", "broom", "stargazer", "RColorBrewer", "corrplot", "car", 
          "readxl", "jsonlite", "GWmodel", "sf", "rnaturalearth", "patchwork",
          "viridis","plm","knitr","DescTools","tidyr", "ggplot2","spdep")
lapply(libs, library, character.only = TRUE)
## [[1]]
## [1] "gplots"    "stats"     "graphics"  "grDevices" "utils"     "datasets" 
## [7] "methods"   "base"     
## 
## [[2]]
## [1] "kableExtra" "gplots"     "stats"      "graphics"   "grDevices" 
## [6] "utils"      "datasets"   "methods"    "base"      
## 
## [[3]]
##  [1] "lubridate"  "forcats"    "stringr"    "dplyr"      "purrr"     
##  [6] "readr"      "tidyr"      "tibble"     "ggplot2"    "tidyverse" 
## [11] "kableExtra" "gplots"     "stats"      "graphics"   "grDevices" 
## [16] "utils"      "datasets"   "methods"    "base"      
## 
## [[4]]
##  [1] "plm"        "lubridate"  "forcats"    "stringr"    "dplyr"     
##  [6] "purrr"      "readr"      "tidyr"      "tibble"     "ggplot2"   
## [11] "tidyverse"  "kableExtra" "gplots"     "stats"      "graphics"  
## [16] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[5]]
##  [1] "tinytex"    "plm"        "lubridate"  "forcats"    "stringr"   
##  [6] "dplyr"      "purrr"      "readr"      "tidyr"      "tibble"    
## [11] "ggplot2"    "tidyverse"  "kableExtra" "gplots"     "stats"     
## [16] "graphics"   "grDevices"  "utils"      "datasets"   "methods"   
## [21] "base"      
## 
## [[6]]
##  [1] "tseries"    "tinytex"    "plm"        "lubridate"  "forcats"   
##  [6] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [11] "tibble"     "ggplot2"    "tidyverse"  "kableExtra" "gplots"    
## [16] "stats"      "graphics"   "grDevices"  "utils"      "datasets"  
## [21] "methods"    "base"      
## 
## [[7]]
##  [1] "lmtest"     "zoo"        "tseries"    "tinytex"    "plm"       
##  [6] "lubridate"  "forcats"    "stringr"    "dplyr"      "purrr"     
## [11] "readr"      "tidyr"      "tibble"     "ggplot2"    "tidyverse" 
## [16] "kableExtra" "gplots"     "stats"      "graphics"   "grDevices" 
## [21] "utils"      "datasets"   "methods"    "base"      
## 
## [[8]]
##  [1] "broom"      "lmtest"     "zoo"        "tseries"    "tinytex"   
##  [6] "plm"        "lubridate"  "forcats"    "stringr"    "dplyr"     
## [11] "purrr"      "readr"      "tidyr"      "tibble"     "ggplot2"   
## [16] "tidyverse"  "kableExtra" "gplots"     "stats"      "graphics"  
## [21] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[9]]
##  [1] "stargazer"  "broom"      "lmtest"     "zoo"        "tseries"   
##  [6] "tinytex"    "plm"        "lubridate"  "forcats"    "stringr"   
## [11] "dplyr"      "purrr"      "readr"      "tidyr"      "tibble"    
## [16] "ggplot2"    "tidyverse"  "kableExtra" "gplots"     "stats"     
## [21] "graphics"   "grDevices"  "utils"      "datasets"   "methods"   
## [26] "base"      
## 
## [[10]]
##  [1] "RColorBrewer" "stargazer"    "broom"        "lmtest"       "zoo"         
##  [6] "tseries"      "tinytex"      "plm"          "lubridate"    "forcats"     
## [11] "stringr"      "dplyr"        "purrr"        "readr"        "tidyr"       
## [16] "tibble"       "ggplot2"      "tidyverse"    "kableExtra"   "gplots"      
## [21] "stats"        "graphics"     "grDevices"    "utils"        "datasets"    
## [26] "methods"      "base"        
## 
## [[11]]
##  [1] "corrplot"     "RColorBrewer" "stargazer"    "broom"        "lmtest"      
##  [6] "zoo"          "tseries"      "tinytex"      "plm"          "lubridate"   
## [11] "forcats"      "stringr"      "dplyr"        "purrr"        "readr"       
## [16] "tidyr"        "tibble"       "ggplot2"      "tidyverse"    "kableExtra"  
## [21] "gplots"       "stats"        "graphics"     "grDevices"    "utils"       
## [26] "datasets"     "methods"      "base"        
## 
## [[12]]
##  [1] "car"          "carData"      "corrplot"     "RColorBrewer" "stargazer"   
##  [6] "broom"        "lmtest"       "zoo"          "tseries"      "tinytex"     
## [11] "plm"          "lubridate"    "forcats"      "stringr"      "dplyr"       
## [16] "purrr"        "readr"        "tidyr"        "tibble"       "ggplot2"     
## [21] "tidyverse"    "kableExtra"   "gplots"       "stats"        "graphics"    
## [26] "grDevices"    "utils"        "datasets"     "methods"      "base"        
## 
## [[13]]
##  [1] "readxl"       "car"          "carData"      "corrplot"     "RColorBrewer"
##  [6] "stargazer"    "broom"        "lmtest"       "zoo"          "tseries"     
## [11] "tinytex"      "plm"          "lubridate"    "forcats"      "stringr"     
## [16] "dplyr"        "purrr"        "readr"        "tidyr"        "tibble"      
## [21] "ggplot2"      "tidyverse"    "kableExtra"   "gplots"       "stats"       
## [26] "graphics"     "grDevices"    "utils"        "datasets"     "methods"     
## [31] "base"        
## 
## [[14]]
##  [1] "jsonlite"     "readxl"       "car"          "carData"      "corrplot"    
##  [6] "RColorBrewer" "stargazer"    "broom"        "lmtest"       "zoo"         
## [11] "tseries"      "tinytex"      "plm"          "lubridate"    "forcats"     
## [16] "stringr"      "dplyr"        "purrr"        "readr"        "tidyr"       
## [21] "tibble"       "ggplot2"      "tidyverse"    "kableExtra"   "gplots"      
## [26] "stats"        "graphics"     "grDevices"    "utils"        "datasets"    
## [31] "methods"      "base"        
## 
## [[15]]
##  [1] "GWmodel"      "Rcpp"         "sp"           "robustbase"   "jsonlite"    
##  [6] "readxl"       "car"          "carData"      "corrplot"     "RColorBrewer"
## [11] "stargazer"    "broom"        "lmtest"       "zoo"          "tseries"     
## [16] "tinytex"      "plm"          "lubridate"    "forcats"      "stringr"     
## [21] "dplyr"        "purrr"        "readr"        "tidyr"        "tibble"      
## [26] "ggplot2"      "tidyverse"    "kableExtra"   "gplots"       "stats"       
## [31] "graphics"     "grDevices"    "utils"        "datasets"     "methods"     
## [36] "base"        
## 
## [[16]]
##  [1] "sf"           "GWmodel"      "Rcpp"         "sp"           "robustbase"  
##  [6] "jsonlite"     "readxl"       "car"          "carData"      "corrplot"    
## [11] "RColorBrewer" "stargazer"    "broom"        "lmtest"       "zoo"         
## [16] "tseries"      "tinytex"      "plm"          "lubridate"    "forcats"     
## [21] "stringr"      "dplyr"        "purrr"        "readr"        "tidyr"       
## [26] "tibble"       "ggplot2"      "tidyverse"    "kableExtra"   "gplots"      
## [31] "stats"        "graphics"     "grDevices"    "utils"        "datasets"    
## [36] "methods"      "base"        
## 
## [[17]]
##  [1] "rnaturalearth" "sf"            "GWmodel"       "Rcpp"         
##  [5] "sp"            "robustbase"    "jsonlite"      "readxl"       
##  [9] "car"           "carData"       "corrplot"      "RColorBrewer" 
## [13] "stargazer"     "broom"         "lmtest"        "zoo"          
## [17] "tseries"       "tinytex"       "plm"           "lubridate"    
## [21] "forcats"       "stringr"       "dplyr"         "purrr"        
## [25] "readr"         "tidyr"         "tibble"        "ggplot2"      
## [29] "tidyverse"     "kableExtra"    "gplots"        "stats"        
## [33] "graphics"      "grDevices"     "utils"         "datasets"     
## [37] "methods"       "base"         
## 
## [[18]]
##  [1] "patchwork"     "rnaturalearth" "sf"            "GWmodel"      
##  [5] "Rcpp"          "sp"            "robustbase"    "jsonlite"     
##  [9] "readxl"        "car"           "carData"       "corrplot"     
## [13] "RColorBrewer"  "stargazer"     "broom"         "lmtest"       
## [17] "zoo"           "tseries"       "tinytex"       "plm"          
## [21] "lubridate"     "forcats"       "stringr"       "dplyr"        
## [25] "purrr"         "readr"         "tidyr"         "tibble"       
## [29] "ggplot2"       "tidyverse"     "kableExtra"    "gplots"       
## [33] "stats"         "graphics"      "grDevices"     "utils"        
## [37] "datasets"      "methods"       "base"         
## 
## [[19]]
##  [1] "viridis"       "viridisLite"   "patchwork"     "rnaturalearth"
##  [5] "sf"            "GWmodel"       "Rcpp"          "sp"           
##  [9] "robustbase"    "jsonlite"      "readxl"        "car"          
## [13] "carData"       "corrplot"      "RColorBrewer"  "stargazer"    
## [17] "broom"         "lmtest"        "zoo"           "tseries"      
## [21] "tinytex"       "plm"           "lubridate"     "forcats"      
## [25] "stringr"       "dplyr"         "purrr"         "readr"        
## [29] "tidyr"         "tibble"        "ggplot2"       "tidyverse"    
## [33] "kableExtra"    "gplots"        "stats"         "graphics"     
## [37] "grDevices"     "utils"         "datasets"      "methods"      
## [41] "base"         
## 
## [[20]]
##  [1] "viridis"       "viridisLite"   "patchwork"     "rnaturalearth"
##  [5] "sf"            "GWmodel"       "Rcpp"          "sp"           
##  [9] "robustbase"    "jsonlite"      "readxl"        "car"          
## [13] "carData"       "corrplot"      "RColorBrewer"  "stargazer"    
## [17] "broom"         "lmtest"        "zoo"           "tseries"      
## [21] "tinytex"       "plm"           "lubridate"     "forcats"      
## [25] "stringr"       "dplyr"         "purrr"         "readr"        
## [29] "tidyr"         "tibble"        "ggplot2"       "tidyverse"    
## [33] "kableExtra"    "gplots"        "stats"         "graphics"     
## [37] "grDevices"     "utils"         "datasets"      "methods"      
## [41] "base"         
## 
## [[21]]
##  [1] "knitr"         "viridis"       "viridisLite"   "patchwork"    
##  [5] "rnaturalearth" "sf"            "GWmodel"       "Rcpp"         
##  [9] "sp"            "robustbase"    "jsonlite"      "readxl"       
## [13] "car"           "carData"       "corrplot"      "RColorBrewer" 
## [17] "stargazer"     "broom"         "lmtest"        "zoo"          
## [21] "tseries"       "tinytex"       "plm"           "lubridate"    
## [25] "forcats"       "stringr"       "dplyr"         "purrr"        
## [29] "readr"         "tidyr"         "tibble"        "ggplot2"      
## [33] "tidyverse"     "kableExtra"    "gplots"        "stats"        
## [37] "graphics"      "grDevices"     "utils"         "datasets"     
## [41] "methods"       "base"         
## 
## [[22]]
##  [1] "DescTools"     "knitr"         "viridis"       "viridisLite"  
##  [5] "patchwork"     "rnaturalearth" "sf"            "GWmodel"      
##  [9] "Rcpp"          "sp"            "robustbase"    "jsonlite"     
## [13] "readxl"        "car"           "carData"       "corrplot"     
## [17] "RColorBrewer"  "stargazer"     "broom"         "lmtest"       
## [21] "zoo"           "tseries"       "tinytex"       "plm"          
## [25] "lubridate"     "forcats"       "stringr"       "dplyr"        
## [29] "purrr"         "readr"         "tidyr"         "tibble"       
## [33] "ggplot2"       "tidyverse"     "kableExtra"    "gplots"       
## [37] "stats"         "graphics"      "grDevices"     "utils"        
## [41] "datasets"      "methods"       "base"         
## 
## [[23]]
##  [1] "DescTools"     "knitr"         "viridis"       "viridisLite"  
##  [5] "patchwork"     "rnaturalearth" "sf"            "GWmodel"      
##  [9] "Rcpp"          "sp"            "robustbase"    "jsonlite"     
## [13] "readxl"        "car"           "carData"       "corrplot"     
## [17] "RColorBrewer"  "stargazer"     "broom"         "lmtest"       
## [21] "zoo"           "tseries"       "tinytex"       "plm"          
## [25] "lubridate"     "forcats"       "stringr"       "dplyr"        
## [29] "purrr"         "readr"         "tidyr"         "tibble"       
## [33] "ggplot2"       "tidyverse"     "kableExtra"    "gplots"       
## [37] "stats"         "graphics"      "grDevices"     "utils"        
## [41] "datasets"      "methods"       "base"         
## 
## [[24]]
##  [1] "DescTools"     "knitr"         "viridis"       "viridisLite"  
##  [5] "patchwork"     "rnaturalearth" "sf"            "GWmodel"      
##  [9] "Rcpp"          "sp"            "robustbase"    "jsonlite"     
## [13] "readxl"        "car"           "carData"       "corrplot"     
## [17] "RColorBrewer"  "stargazer"     "broom"         "lmtest"       
## [21] "zoo"           "tseries"       "tinytex"       "plm"          
## [25] "lubridate"     "forcats"       "stringr"       "dplyr"        
## [29] "purrr"         "readr"         "tidyr"         "tibble"       
## [33] "ggplot2"       "tidyverse"     "kableExtra"    "gplots"       
## [37] "stats"         "graphics"      "grDevices"     "utils"        
## [41] "datasets"      "methods"       "base"         
## 
## [[25]]
##  [1] "spdep"         "spData"        "DescTools"     "knitr"        
##  [5] "viridis"       "viridisLite"   "patchwork"     "rnaturalearth"
##  [9] "sf"            "GWmodel"       "Rcpp"          "sp"           
## [13] "robustbase"    "jsonlite"      "readxl"        "car"          
## [17] "carData"       "corrplot"      "RColorBrewer"  "stargazer"    
## [21] "broom"         "lmtest"        "zoo"           "tseries"      
## [25] "tinytex"       "plm"           "lubridate"     "forcats"      
## [29] "stringr"       "dplyr"         "purrr"         "readr"        
## [33] "tidyr"         "tibble"        "ggplot2"       "tidyverse"    
## [37] "kableExtra"    "gplots"        "stats"         "graphics"     
## [41] "grDevices"     "utils"         "datasets"      "methods"      
## [45] "base"

2. Persiapan Data

Memuat data kejadian banjir di Pulau Sumatera, melakukan penyesuaian nama kolom, pengaturan tipe data, dan pengecekan missing value, dan mencek outlier dan melakukan penanganan.

# 2. Data ==================================================================
setwd("D:/Kuliah/Lomba/PKM-AI 2026")
banjir <- read_excel("data_banjir_pulausumatera.xlsx", sheet = "2010")
# Penamaan kolom agar konsisten dengan analisis selanjutnya
colnames(banjir) <- c("PROV", "TAHUN", "Y", "X1", "X2", "X3", "X4", "X5")
banjir$PROV <- as.factor(toupper(banjir$PROV))
banjir$TAHUN <- as.factor(banjir$TAHUN)

# Pre-Processing Data
# Cek Missing Value
print(colSums(is.na(banjir)))
##  PROV TAHUN     Y    X1    X2    X3    X4    X5 
##     0     0     0     0     0     0     0     0
# Cek Duplikasi Data
# Menghitung jumlah total baris yang duplikat
jumlah_duplikasi <- sum(duplicated(banjir))
print(paste("Jumlah data duplikat:", jumlah_duplikasi))
## [1] "Jumlah data duplikat: 0"
# Menampilkan baris data yang duplikat (jika ada)
if (jumlah_duplikasi > 0) {
  print("Detail data yang terduplikasi:")
  print(banjir[duplicated(banjir), ])
} else {
  print("Tidak ditemukan data duplikat (bersih).")
}
## [1] "Tidak ditemukan data duplikat (bersih)."

3. Eksplorasi Data

Melakukan visualisasi untuk melihat pola keragaman kejadian banjir berdasarkan waktu dan antar provinsi, serta melihat korelasi antar variabel.

# 3. Eksplorasi Data ===========================================================
summary_stats <- banjir %>%
  dplyr::select("Y", "X1", "X2", "X3", "X4","X5") %>%
  summarise_all(list(
    Min = ~min(.),
    Q1 = ~quantile(., 0.25),
    Median = ~median(.),
    Mean = ~mean(.),
    Q3 = ~quantile(., 0.75),
    Max = ~max(.),
    SD = ~sd(.)
  )) %>%
  pivot_longer(everything(),
               names_to = c("Variable", "Statistic"),
               names_sep = "_") %>%
  pivot_wider(names_from = Statistic, values_from = value)

kable(summary_stats)
Variable Min Q1 Median Mean Q3 Max SD
Y 0.00 8.000 19.000 26.31333 36.0000 120.00 25.04094
X1 -9941.50 1826.150 5738.400 17635.24680 16856.1000 290777.00 38246.46864
X2 116.33 5324.225 11004.000 24739.22720 22428.2825 225316.06 44814.03000
X3 7.40 233.800 419.315 730.70507 1073.9500 3408.68 737.98993
X4 91.50 191.160 231.090 233.33880 274.5475 435.67 64.77882
X5 62.00 82.000 94.500 131.57333 194.5000 281.00 67.43273
# Keragaman Antar Waktu
ggplot(data = banjir, aes(x = TAHUN, y = Y)) +
  geom_line() +
  labs(x = "Tahun", y = "Jumlah Kejadian Banjir") +
  theme(legend.position = "none") +
  theme_bw()

# Keragaman Antar Individu
gplots::plotmeans(Y ~ `PROV`, main="Keragaman Antar Kejadian Banjir",
                  banjir, n.label = F)
## Warning in arrows(x, li, x, pmax(y - gap, li), col = barcol, lwd = lwd, :
## zero-length arrow is of indeterminate angle and so skipped
## Warning in arrows(x, ui, x, pmin(y + gap, ui), col = barcol, lwd = lwd, :
## zero-length arrow is of indeterminate angle and so skipped

# Di sini saya asumsikan continuous agar sumbu X rapi
banjir$TAHUN <- as.numeric(as.character(banjir$TAHUN))
# Plotting
p <- ggplot(data = banjir, aes(x = TAHUN, y = Y)) +
  # 1. DATA MENTAH (BACKGROUND)
  geom_point(position = position_jitter(width = 0.2), 
             alpha = 0.3, 
             color = "grey60", 
             size = 1.5) +
  # 2. GARIS RATA-RATA (CENTRAL TENDENCY)
  stat_summary(fun = mean, 
               geom = "line", 
               color = "black", 
               size = 0.8) +
  # 3. TITIK RATA-RATA
  stat_summary(fun = mean, 
               geom = "point", 
               shape = 18,        # Shape diamond (formal)
               size = 3, 
               color = "black") +
  # 4. ERROR BARS (VARIABILITAS) - Sangat disukai reviewer
  stat_summary(fun.data = mean_se, 
               geom = "errorbar", 
               width = 0.2, 
               size = 0.6) +
  # 5. PEMFORMATAN LABEL & SKALA
  scale_x_continuous(breaks = unique(banjir$TAHUN)) + 
  labs(x = "Tahun Pengamatan", 
       y = "Frekuensi Kejadian Banjir",
       caption = "Sumber: [Sebutkan Data Anda Disini]\nError bars menunjukkan Standard Error of Mean (SEM)") +
  
  # 6. TEMA ILMIAH (PUBLICATION READY THEME)
  theme_bw() + # Dasar hitam putih
  theme(
    text = element_text(family = "serif"),      
    axis.title = element_text(size = 12, face = "bold"),
    axis.text = element_text(size = 10, color = "black"),
    panel.grid.major.x = element_blank(),       
    panel.grid.minor = element_blank(),         # Hilangkan minor grid
    axis.line = element_line(colour = "black"), # Pertegas garis sumbu
    plot.caption = element_text(hjust = 0, face = "italic", size = 9)
  )
## 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.
print(p)

# Correlation Plot
corrplot(cor(banjir[-c(1:2)]), method="color", type = "upper", tl.pos = 'tp')
corrplot(cor(banjir[-c(1:2)]), method="number", diag=F, add=T, type = "lower",
         tl.pos = 'n', cl.pos = 'n')

4. Uji Multikolinearitas

Pengecekan masalah multikolinearitas antar variabel bebas menggunakan nilai VIF (Variance Inflation Factor).

# 4. Seleksi Peubah Multikolinearitas ==========================================
check_model <- lm(Y ~ X1 + X2 + X3 + X4 + X5, banjir)
data.frame(t(vif(check_model)))

5. Pemodelan Data Panel (CEM & FEM)

Estimasi parameter menggunakan pendekatan Common Effect Model (CEM) dan Fixed Effect Model (FEM) dengan berbagai efek (Individu, Waktu, Two-ways).

# 5. Common-Effect Model =======================================================
# Model CEM
cem <- plm(Y ~ X1 + X2 + X3 + X4 + X5, data = banjir, model = "pooling")
summary(cem)
## Pooling Model
## 
## Call:
## plm(formula = Y ~ X1 + X2 + X3 + X4 + X5, data = banjir, model = "pooling")
## 
## Balanced Panel: n = 10, T = 15, N = 150
## 
## Residuals:
##     Min.  1st Qu.   Median  3rd Qu.     Max. 
## -42.1958 -15.7700  -4.2596   7.6629  85.5516 
## 
## Coefficients:
##                Estimate  Std. Error t-value  Pr(>|t|)    
## (Intercept)  7.8701e+00  9.3212e+00  0.8443 0.3998899    
## X1          -5.3187e-05  5.8736e-05 -0.9055 0.3667030    
## X2          -1.3782e-04  4.6543e-05 -2.9611 0.0035862 ** 
## X3           1.1399e-02  2.9160e-03  3.9089 0.0001422 ***
## X4           5.3063e-02  3.0217e-02  1.7561 0.0812027 .  
## X5           1.5809e-02  3.1143e-02  0.5076 0.6124811    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    93430
## Residual Sum of Squares: 78850
## R-Squared:      0.15605
## Adj. R-Squared: 0.12675
## F-statistic: 5.32541 on 5 and 144 DF, p-value: 0.00016048
# 6. Fixed-Effect Model ========================================================
# Model FEM Individual
fem_ind <- plm(Y ~ X1 + X2 + X3 + X4 + X5, index = c("PROV", "TAHUN"),
               model = "within", effect= "individual", data = banjir)
summary(fem_ind)
## Oneway (individual) effect Within Model
## 
## Call:
## plm(formula = Y ~ X1 + X2 + X3 + X4 + X5, data = banjir, effect = "individual", 
##     model = "within", index = c("PROV", "TAHUN"))
## 
## Balanced Panel: n = 10, T = 15, N = 150
## 
## Residuals:
##      Min.   1st Qu.    Median   3rd Qu.      Max. 
## -33.67095  -8.84941   0.11677   7.40798  57.77951 
## 
## Coefficients:
##       Estimate  Std. Error t-value  Pr(>|t|)    
## X1 -1.8483e-05  4.0638e-05 -0.4548 0.6499626    
## X2  6.4756e-05  4.5498e-05  1.4233 0.1569622    
## X3  3.0755e-02  8.0666e-03  3.8127 0.0002082 ***
## X4  1.1405e-01  2.7293e-02  4.1786 5.237e-05 ***
## X5  5.9241e-01  1.3487e-01  4.3925 2.246e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    45751
## Residual Sum of Squares: 30330
## R-Squared:      0.33706
## Adj. R-Squared: 0.26831
## F-statistic: 13.7275 on 5 and 135 DF, p-value: 7.7981e-11
summary(fixef(fem_ind, effect="individual"))
##                           Estimate Std. Error t-value  Pr(>|t|)    
## ACEH                       -25.533     13.960 -1.8290    0.0696 .  
## BENGKULU                   -87.951     15.413 -5.7062 7.005e-08 ***
## JAMBI                      -71.540     13.824 -5.1752 8.060e-07 ***
## KEPULAUAN BANGKA BELITUNG  -78.137     13.470 -5.8008 4.468e-08 ***
## KEPULAUAN RIAU            -173.928     35.015 -4.9672 2.018e-06 ***
## LAMPUNG                   -152.341     33.351 -4.5678 1.099e-05 ***
## RIAU                      -126.550     26.082 -4.8520 3.321e-06 ***
## SUMATERA BARAT             -88.869     19.713 -4.5081 1.405e-05 ***
## SUMATERA SELATAN           -78.434     16.740 -4.6855 6.734e-06 ***
## SUMATERA UTARA            -136.649     29.708 -4.5997 9.634e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Model FEM Individual
fem_time <- plm(Y ~ X1 + X2 + X3 + X4 + X5, index = c("PROV", "TAHUN"),
               model = "within", effect= "time", data = banjir)
summary(fem_time)
## Oneway (time) effect Within Model
## 
## Call:
## plm(formula = Y ~ X1 + X2 + X3 + X4 + X5, data = banjir, effect = "time", 
##     model = "within", index = c("PROV", "TAHUN"))
## 
## Balanced Panel: n = 10, T = 15, N = 150
## 
## Residuals:
##     Min.  1st Qu.   Median  3rd Qu.     Max. 
## -37.0485 -14.0108  -2.8886   8.0758  77.7908 
## 
## Coefficients:
##       Estimate  Std. Error t-value Pr(>|t|)   
## X1 -1.4771e-05  6.1834e-05 -0.2389 0.811573   
## X2 -1.0326e-04  5.0451e-05 -2.0467 0.042702 * 
## X3  8.5406e-03  3.0264e-03  2.8221 0.005522 **
## X4  3.1019e-02  3.2625e-02  0.9508 0.343483   
## X5 -2.7843e-03  3.1279e-02 -0.0890 0.929209   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    74769
## Residual Sum of Squares: 67998
## R-Squared:      0.090566
## Adj. R-Squared: -0.042352
## F-statistic: 2.5892 on 5 and 130 DF, p-value: 0.02875
summary(fixef(fem_time, effect="time"))
##      Estimate Std. Error t-value Pr(>|t|)   
## 2010  13.1029    12.8241  1.0217 0.308803   
## 2011   4.9946    11.1656  0.4473 0.655389   
## 2012  15.8313    11.4312  1.3849 0.168450   
## 2013   9.8938    12.2266  0.8092 0.419877   
## 2014  10.2313    11.0018  0.9300 0.354113   
## 2015   9.8999    11.6416  0.8504 0.396675   
## 2016   9.3849    12.0641  0.7779 0.438028   
## 2017   7.8554    12.5719  0.6248 0.533174   
## 2018  14.6589    12.2677  1.1949 0.234295   
## 2019   9.8734    11.8697  0.8318 0.407039   
## 2020  14.9420    12.3343  1.2114 0.227935   
## 2021  32.8561    12.8340  2.5601 0.011608 * 
## 2022  22.8874    13.1786  1.7367 0.084806 . 
## 2023  33.8614    12.0868  2.8015 0.005864 **
## 2024  29.9688    13.1550  2.2781 0.024351 * 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Model FEM Individual
fem_twoways  <- plm(Y ~ X1 + X2 + X3 + X4 + X5, index = c("PROV", "TAHUN"),
               model = "within", effect= "twoways", data = banjir)
summary(fem_twoways )
## Twoways effects Within Model
## 
## Call:
## plm(formula = Y ~ X1 + X2 + X3 + X4 + X5, data = banjir, effect = "twoways", 
##     model = "within", index = c("PROV", "TAHUN"))
## 
## Balanced Panel: n = 10, T = 15, N = 150
## 
## Residuals:
##      Min.   1st Qu.    Median   3rd Qu.      Max. 
## -30.80961  -8.04997  -0.14031   8.21278  56.02914 
## 
## Coefficients:
##       Estimate  Std. Error t-value Pr(>|t|)   
## X1 -1.0900e-05  4.1367e-05 -0.2635 0.792621   
## X2  8.3139e-06  4.8060e-05  0.1730 0.862948   
## X3  1.1775e-02  1.0016e-02  1.1756 0.242050   
## X4  1.0268e-01  3.2307e-02  3.1783 0.001881 **
## X5  4.4507e-02  2.4062e-01  0.1850 0.853562   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    27090
## Residual Sum of Squares: 24399
## R-Squared:      0.099334
## Adj. R-Squared: -0.10908
## F-statistic: 2.669 on 5 and 121 DF, p-value: 0.025186
summary(fixef(fem_twoways , effect="twoways"))
##                                   Estimate
## ACEH-2010                       26.3305700
## ACEH-2011                       23.1910797
## ACEH-2012                       31.6055818
## ACEH-2013                       26.9148115
## ACEH-2014                       29.1415433
## ACEH-2015                       32.0064124
## ACEH-2016                       26.6575150
## ACEH-2017                       25.4243314
## ACEH-2018                       33.5629996
## ACEH-2019                       30.8098126
## ACEH-2020                       33.7741216
## ACEH-2021                       50.3042083
## ACEH-2022                       39.0737233
## ACEH-2023                       53.4086043
## ACEH-2024                       46.1518057
## BENGKULU-2010                  -32.9855767
## BENGKULU-2011                  -36.1250669
## BENGKULU-2012                  -27.7105648
## BENGKULU-2013                  -32.4013351
## BENGKULU-2014                  -30.1746033
## BENGKULU-2015                  -27.3097343
## BENGKULU-2016                  -32.6586317
## BENGKULU-2017                  -33.8918152
## BENGKULU-2018                  -25.7531471
## BENGKULU-2019                  -28.5063341
## BENGKULU-2020                  -25.5420250
## BENGKULU-2021                   -9.0119384
## BENGKULU-2022                  -20.2424234
## BENGKULU-2023                   -5.9075424
## BENGKULU-2024                  -13.1643410
## JAMBI-2010                     -21.7214970
## JAMBI-2011                     -24.8609872
## JAMBI-2012                     -16.4464851
## JAMBI-2013                     -21.1372554
## JAMBI-2014                     -18.9105236
## JAMBI-2015                     -16.0456546
## JAMBI-2016                     -21.3945520
## JAMBI-2017                     -22.6277355
## JAMBI-2018                     -14.4890673
## JAMBI-2019                     -17.2422544
## JAMBI-2020                     -14.2779453
## JAMBI-2021                       2.2521414
## JAMBI-2022                      -8.9783437
## JAMBI-2023                       5.3565374
## JAMBI-2024                      -1.9002613
## KEPULAUAN BANGKA BELITUNG-2010 -31.9175102
## KEPULAUAN BANGKA BELITUNG-2011 -35.0570004
## KEPULAUAN BANGKA BELITUNG-2012 -26.6424983
## KEPULAUAN BANGKA BELITUNG-2013 -31.3332686
## KEPULAUAN BANGKA BELITUNG-2014 -29.1065368
## KEPULAUAN BANGKA BELITUNG-2015 -26.2416678
## KEPULAUAN BANGKA BELITUNG-2016 -31.5905652
## KEPULAUAN BANGKA BELITUNG-2017 -32.8237487
## KEPULAUAN BANGKA BELITUNG-2018 -24.6850805
## KEPULAUAN BANGKA BELITUNG-2019 -27.4382676
## KEPULAUAN BANGKA BELITUNG-2020 -24.4739585
## KEPULAUAN BANGKA BELITUNG-2021  -7.9438718
## KEPULAUAN BANGKA BELITUNG-2022 -19.1743569
## KEPULAUAN BANGKA BELITUNG-2023  -4.8394758
## KEPULAUAN BANGKA BELITUNG-2024 -12.0962745
## KEPULAUAN RIAU-2010            -40.1239724
## KEPULAUAN RIAU-2011            -43.2634627
## KEPULAUAN RIAU-2012            -34.8489606
## KEPULAUAN RIAU-2013            -39.5397309
## KEPULAUAN RIAU-2014            -37.3129991
## KEPULAUAN RIAU-2015            -34.4481300
## KEPULAUAN RIAU-2016            -39.7970274
## KEPULAUAN RIAU-2017            -41.0302110
## KEPULAUAN RIAU-2018            -32.8915428
## KEPULAUAN RIAU-2019            -35.6447298
## KEPULAUAN RIAU-2020            -32.6804208
## KEPULAUAN RIAU-2021            -16.1503341
## KEPULAUAN RIAU-2022            -27.3808191
## KEPULAUAN RIAU-2023            -13.0459381
## KEPULAUAN RIAU-2024            -20.3027367
## LAMPUNG-2010                   -20.0714366
## LAMPUNG-2011                   -23.2109269
## LAMPUNG-2012                   -14.7964248
## LAMPUNG-2013                   -19.4871951
## LAMPUNG-2014                   -17.2604633
## LAMPUNG-2015                   -14.3955942
## LAMPUNG-2016                   -19.7444916
## LAMPUNG-2017                   -20.9776751
## LAMPUNG-2018                   -12.8390070
## LAMPUNG-2019                   -15.5921940
## LAMPUNG-2020                   -12.6278849
## LAMPUNG-2021                     3.9022017
## LAMPUNG-2022                    -7.3282833
## LAMPUNG-2023                     7.0065977
## LAMPUNG-2024                    -0.2502009
## RIAU-2010                      -40.0599813
## RIAU-2011                      -43.1994716
## RIAU-2012                      -34.7849695
## RIAU-2013                      -39.4757398
## RIAU-2014                      -37.2490080
## RIAU-2015                      -34.3841389
## RIAU-2016                      -39.7330363
## RIAU-2017                      -40.9662199
## RIAU-2018                      -32.8275517
## RIAU-2019                      -35.5807387
## RIAU-2020                      -32.6164297
## RIAU-2021                      -16.0863430
## RIAU-2022                      -27.3168280
## RIAU-2023                      -12.9819470
## RIAU-2024                      -20.2387456
## SUMATERA BARAT-2010            -14.9192267
## SUMATERA BARAT-2011            -18.0587169
## SUMATERA BARAT-2012             -9.6442148
## SUMATERA BARAT-2013            -14.3349851
## SUMATERA BARAT-2014            -12.1082533
## SUMATERA BARAT-2015             -9.2433843
## SUMATERA BARAT-2016            -14.5922817
## SUMATERA BARAT-2017            -15.8254652
## SUMATERA BARAT-2018             -7.6867970
## SUMATERA BARAT-2019            -10.4399841
## SUMATERA BARAT-2020             -7.4756750
## SUMATERA BARAT-2021              9.0544117
## SUMATERA BARAT-2022             -2.1760734
## SUMATERA BARAT-2023             12.1588077
## SUMATERA BARAT-2024              4.9020090
## SUMATERA SELATAN-2010          -13.5026882
## SUMATERA SELATAN-2011          -16.6421784
## SUMATERA SELATAN-2012           -8.2276763
## SUMATERA SELATAN-2013          -12.9184466
## SUMATERA SELATAN-2014          -10.6917148
## SUMATERA SELATAN-2015           -7.8268458
## SUMATERA SELATAN-2016          -13.1757432
## SUMATERA SELATAN-2017          -14.4089267
## SUMATERA SELATAN-2018           -6.2702585
## SUMATERA SELATAN-2019           -9.0234456
## SUMATERA SELATAN-2020           -6.0591365
## SUMATERA SELATAN-2021           10.4709502
## SUMATERA SELATAN-2022           -0.7595349
## SUMATERA SELATAN-2023           13.5753462
## SUMATERA SELATAN-2024            6.3185475
## SUMATERA UTARA-2010             -7.8306517
## SUMATERA UTARA-2011            -10.9701420
## SUMATERA UTARA-2012             -2.5556399
## SUMATERA UTARA-2013             -7.2464102
## SUMATERA UTARA-2014             -5.0196784
## SUMATERA UTARA-2015             -2.1548093
## SUMATERA UTARA-2016             -7.5037067
## SUMATERA UTARA-2017             -8.7368903
## SUMATERA UTARA-2018             -0.5982221
## SUMATERA UTARA-2019             -3.3514091
## SUMATERA UTARA-2020             -0.3871001
## SUMATERA UTARA-2021             16.1429866
## SUMATERA UTARA-2022              4.9125016
## SUMATERA UTARA-2023             19.2473826
## SUMATERA UTARA-2024             11.9905839

6. Evaluasi Model FEM

Melakukan uji spesifikasi untuk menentukan efek yang signifikan pada FEM serta membandingkan performa model berdasarkan kriteria kebaikan model (SSE, AIC, MAPE, R-Squared).

# 7. Uji Signifikasi Pengaruh FEM ==============================================
# Uji pengaruh individu
plmtest(fem_twoways, type = "bp", effect = "individual")
## 
##  Lagrange Multiplier Test - (Breusch-Pagan)
## 
## data:  Y ~ X1 + X2 + X3 + X4 + X5
## chisq = 238.01, df = 1, p-value < 2.2e-16
## alternative hypothesis: significant effects
plmtest(fem_twoways, type = "bp", effect = "time")
## 
##  Lagrange Multiplier Test - time effects (Breusch-Pagan)
## 
## data:  Y ~ X1 + X2 + X3 + X4 + X5
## chisq = 0.49453, df = 1, p-value = 0.4819
## alternative hypothesis: significant effects
plmtest(fem_twoways, type = "bp", effect = "twoways")
## 
##  Lagrange Multiplier Test - two-ways effects (Breusch-Pagan)
## 
## data:  Y ~ X1 + X2 + X3 + X4 + X5
## chisq = 238.5, df = 2, p-value < 2.2e-16
## alternative hypothesis: significant effects
# Nilai Kebaikan Model
# Sum Squared Error
dsse <- data.frame(Individu=sum(fem_ind$residuals^2),
                   Time=sum(fem_time$residuals^2),
                   Twoways=sum(fem_twoways$residuals^2))
# AIC
lsdv_ind <- lm(Y ~ X1 + X2 + X3 + X4 + X5 + PROV, banjir)
lsdv_time <- lm(Y ~ X1 + X2 + X3 + X4 + X5 + TAHUN, banjir)
lsdv_twoways <- lm(Y ~ X1 + X2 + X3 + X4 + X5 + PROV + TAHUN, banjir)
daic <- data.frame(Individu=AIC(lsdv_ind),Time=AIC(lsdv_time),
                   Twoways=AIC(lsdv_twoways))
# MAPE
mape <- function(actual, forecast) {
  mean(abs((actual - forecast) / actual)) * 100
}
dmape <- data.frame(Individu=mape(banjir$Y,predict(fem_ind)),
                    Time=mape(banjir$Y,predict(fem_time)),
                    Twoways=mape(banjir$Y,predict(fem_twoways)))
# BIC
dbic <- data.frame(Individu=BIC(lsdv_ind),Time=BIC(lsdv_time),
                   Twoways=BIC(lsdv_twoways))
# R-squared
ind <- summary(fem_ind)
time <- summary(fem_time)
tways <- summary(fem_twoways)
drsq <- data.frame(Individu=ind$r.squared,Time=time$r.squared,
                   Twoways=tways$r.squared)
# Perbandingan
compare <- t(rbind(dsse,daic,dbic,dmape,drsq))
colnames(compare) <- c("SSE","AIC","BIC", "MAPE","R-Squared","Adj R-Squared")
compare
##               SSE      AIC      BIC MAPE  R-Squared Adj R-Squared
## Individu 30329.96 1254.070 1302.240  Inf 0.33705789    0.26830834
## Time     67997.78 1370.530 1394.615  Inf 0.09056555   -0.04235179
## Twoways  24398.65 1247.023 1298.204  Inf 0.09933384   -0.10908478
# FEM vs CEM 
pooltest(cem, fem_ind)
## 
##  F statistic
## 
## data:  Y ~ X1 + X2 + X3 + X4 + X5
## F = 23.996, df1 = 9, df2 = 135, p-value < 2.2e-16
## alternative hypothesis: unstability

7. Random Effect Model (REM)

Estimasi model menggunakan pendekatan Random Effect dan melakukan uji Lagrange Multiplier serta uji Hausman untuk membandingkan FEM dan REM.

# 8. Random-Effect Model =======================================================
# Pendugaan Parameter
rem_gls <- plm(Y ~ X1 + X2 + X3 + X4 + X5, data = banjir, 
               index = c("PROV", "TAHUN"), 
               effect = "individual", model = "random",
               random.method = "nerlove")
summary(rem_gls)
## Oneway (individual) effect Random Effect Model 
##    (Nerlove's transformation)
## 
## Call:
## plm(formula = Y ~ X1 + X2 + X3 + X4 + X5, data = banjir, effect = "individual", 
##     model = "random", random.method = "nerlove", index = c("PROV", 
##         "TAHUN"))
## 
## Balanced Panel: n = 10, T = 15, N = 150
## 
## Effects:
##                   var std.dev share
## idiosyncratic  202.20   14.22 0.093
## individual    1975.64   44.45 0.907
## theta: 0.9177
## 
## Residuals:
##     Min.  1st Qu.   Median  3rd Qu.     Max. 
## -35.3964  -8.5495  -1.8589   7.3066  58.2127 
## 
## Coefficients:
##                Estimate  Std. Error z-value  Pr(>|z|)    
## (Intercept) -8.2025e+01  2.3087e+01 -3.5529  0.000381 ***
## X1          -1.9621e-05  3.9927e-05 -0.4914  0.623126    
## X2           3.7422e-05  4.3442e-05  0.8614  0.389008    
## X3           2.9209e-02  7.4117e-03  3.9409 8.117e-05 ***
## X4           1.1617e-01  2.6935e-02  4.3129 1.611e-05 ***
## X5           4.5077e-01  1.1459e-01  3.9337 8.363e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    46074
## Residual Sum of Squares: 31796
## R-Squared:      0.3099
## Adj. R-Squared: 0.28594
## Chisq: 64.6647 on 5 DF, p-value: 1.3153e-12
# Perbandingan Kebaikan REM
# Efek individu
plmtest(rem_gls,type = "bp", effect="individu")
## 
##  Lagrange Multiplier Test - (Breusch-Pagan)
## 
## data:  Y ~ X1 + X2 + X3 + X4 + X5
## chisq = 238.01, df = 1, p-value < 2.2e-16
## alternative hypothesis: significant effects
# Efek time
plmtest(rem_gls,type = "bp", effect="time")
## 
##  Lagrange Multiplier Test - time effects (Breusch-Pagan)
## 
## data:  Y ~ X1 + X2 + X3 + X4 + X5
## chisq = 0.49453, df = 1, p-value = 0.4819
## alternative hypothesis: significant effects
# Efek twoways
plmtest(rem_gls,type = "bp", effect="twoways")
## 
##  Lagrange Multiplier Test - two-ways effects (Breusch-Pagan)
## 
## data:  Y ~ X1 + X2 + X3 + X4 + X5
## chisq = 238.5, df = 2, p-value < 2.2e-16
## alternative hypothesis: significant effects
# FEM vs REM
#fem dengan rem gls
phtest(fem_ind, rem_gls)
## 
##  Hausman Test
## 
## data:  Y ~ X1 + X2 + X3 + X4 + X5
## chisq = 4.8307, df = 5, p-value = 0.4369
## alternative hypothesis: one model is inconsistent

8. Pemilihan Model Terbaik

Estimasi model menggunakan pendekatan Random Effect dan melakukan uji Lagrange Multiplier serta uji Hausman untuk membandingkan FEM dan REM.

# =========================================================================
# UJI PEMILIHAN MODEL (CHOW, HAUSMAN, LM) & TABEL REKAPITULASI
# =========================================================================

# A. Uji Chow (Likelihood Ratio Test): Membandingkan CEM vs FEM
# H0: Model CEM lebih baik
# H1: Model FEM lebih baik
chow_test <- pooltest(cem, fem_ind)

# B. Uji Hausman: Membandingkan FEM vs REM
# H0: Model REM lebih baik (Konsisten & Efisien)
# H1: Model FEM lebih baik (Konsisten)
hausman_test <- phtest(fem_ind, rem_gls)

# C. Uji LM (Lagrange Multiplier - Breusch-Pagan): Membandingkan CEM vs REM
# H0: Variansi error individual = 0 (Model CEM lebih baik)
# H1: Variansi error individual != 0 (Model REM lebih baik)
lm_test <- plmtest(cem, type = "bp", effect = "individual")

# --- FUNGSI UNTUK MENENTUKAN KESIMPULAN OTOMATIS ---
get_conclusion <- function(p_val, test_type) {
  alpha <- 0.05
  if (test_type == "Chow") {
    return(ifelse(p_val < alpha, "Model FEM lebih baik", "Model CEM lebih baik"))
  } else if (test_type == "Hausman") {
    return(ifelse(p_val < alpha, "Model FEM lebih baik", "Model REM lebih baik"))
  } else if (test_type == "LM") {
    return(ifelse(p_val < alpha, "Model REM lebih baik", "Model CEM lebih baik"))
  }
}

# --- MEMBUAT DATA FRAME HASIL ---
hasil_uji <- data.frame(
  Uji = c("Chow (F-Test)", "Hausman", "Lagrange Multiplier (LM)"),
  
  Statistik = c(
    as.numeric(chow_test$statistic), 
    as.numeric(hausman_test$statistic), 
    as.numeric(lm_test$statistic)
  ),
  
  P_Value = c(
    as.numeric(chow_test$p.value), 
    as.numeric(hausman_test$p.value), 
    as.numeric(lm_test$p.value)
  ),
  
  Kesimpulan = c(
    get_conclusion(as.numeric(chow_test$p.value), "Chow"),
    get_conclusion(as.numeric(hausman_test$p.value), "Hausman"),
    get_conclusion(as.numeric(lm_test$p.value), "LM")
  )
)

# --- FORMATTING TAMPILAN AGAR RAPI (OPSIONAL) ---
hasil_uji$Statistik <- round(hasil_uji$Statistik, 4)
# Mengubah P-value yang sangat kecil menjadi notasi ilmiah atau < 0.05
hasil_uji$P_Value_Str <- ifelse(hasil_uji$P_Value < 0.0001, 
                                format(hasil_uji$P_Value, scientific = TRUE, digits = 3), 
                                round(hasil_uji$P_Value, 4))

# Menampilkan Tabel Akhir (Bersih)
library(knitr) # Gunakan library ini jika ingin tampilan tabel cantik di console
tabel_final <- hasil_uji[, c("Uji", "Statistik", "P_Value_Str", "Kesimpulan")]
colnames(tabel_final)[3] <- "P-value" # Ubah nama kolom biar sesuai contoh

print("=== TABEL RINGKASAN PEMILIHAN MODEL PANEL ===")
## [1] "=== TABEL RINGKASAN PEMILIHAN MODEL PANEL ==="
kable(tabel_final, align = "c")
Uji Statistik P-value Kesimpulan
Chow (F-Test) 23.9962 4.52e-24 Model FEM lebih baik
Hausman 4.8307 0.4369 Model REM lebih baik
Lagrange Multiplier (LM) 238.0099 1.07e-53 Model REM lebih baik

9. Uji Diagnostik Asumsi & Spasial

Pemeriksaan asumsi klasik (Normalitas, Heteroskedastisitas, Autokorelasi) serta pengujian dependensi spasial (Cross-sectional Dependence) untuk melegitimasi penggunaan model spasial.

# 9. UJi Diagnostik Sisaan =====================================================
sum_rem <- summary(rem_gls)
# Menghitung VIF
vif_values <- tryCatch(vif(rem_gls), error = function(e) NULL)
if (!is.null(vif_values)) {
  if (length(coef(rem_gls)) > length(vif_values)) {
    vif_vec <- c(NA, vif_values) 
  } else {
    vif_vec <- vif_values
  }
} else {
  vif_vec <- rep(NA, length(coef(rem_gls)))
}
# --- 2. Membuat Tabel Estimasi (Koefisien & VIF) ---
tabel_estimasi <- data.frame(
  Variabel = rownames(sum_rem$coefficients),
  Koefisien = round(sum_rem$coefficients[,1], 4),
  Std_Error = round(sum_rem$coefficients[,2], 4),
  P_Value = round(sum_rem$coefficients[,4], 4),
  VIF = round(vif_vec, 2)
)
tabel_estimasi$Signifikansi <- ifelse(tabel_estimasi$P_Value < 0.05,
                                      "Signifikan (5%)", 
                                      ifelse(tabel_estimasi$P_Value < 0.1,
                                      "Signifikan (10%)", "Tidak Signifikan"))

tabel_estimasi$Status_VIF <- ifelse(is.na(tabel_estimasi$VIF), "-", 
                                    ifelse(tabel_estimasi$VIF < 10,
                                    "Aman", "Multikolinearitas"))
# --- 3. Melakukan Uji Diagnostik & Membuat Tabel ---
# A. Uji Normalitas (Kolmogorov-Smirnov)
uji_norm <- ks.test(residuals(rem_gls), "pnorm", 
                    mean=mean(residuals(rem_gls)), 
                    sd=sd(residuals(rem_gls)))
# B. Uji Heteroskedastisitas (Breusch-Pagan)
uji_hetero <- bptest(rem_gls, studentize = TRUE)
# C. Uji Autokorelasi Serial (Waktu - Breusch-Godfrey)
uji_auto_serial <- pbgtest(rem_gls)
# D. UJI BARU: Uji Dependensi Spasial / Cross-sectional Dependence (Pesaran CD)
# H0: Tidak ada dependensi antar wilayah (Cross-sectional independence)
# H1: Ada dependensi antar wilayah (Indikasi Spasial)->P < 0.05 BAGUS untuk GWPR
uji_spasial <- pcdtest(rem_gls, test = "cd")
# Mengambil R-Squared
r_sq <- sum_rem$r.squared[1] 
# Menyusun Tabel Diagnostik
tabel_diagnostik <- data.frame(
  Uji_Asumsi = c("Normalitas (KS)", 
                 "Heteroskedastisitas (BP)", 
                 "Autokorelasi Serial (Waktu)", 
                 "Dependensi Spasial (Pesaran CD)", # Baris Baru
                 "R-Squared Overall"),
  Nilai_P = c(round(uji_norm$p.value, 4), 
              round(uji_hetero$p.value, 4), 
              round(uji_auto_serial$p.value, 4), 
              round(uji_spasial$p.value, 4), # Nilai P Spasial
              NA),
  Statistik = c(round(uji_norm$statistic, 4), 
                round(uji_hetero$statistic, 4), 
                round(uji_auto_serial$statistic, 4), 
                round(uji_spasial$statistic, 4), # Statistik Spasial
                round(r_sq, 4)),
  Keputusan = c(ifelse(uji_norm$p.value > 0.05,
                       "Normal (Terpenuhi)", "Tidak Normal"),
                ifelse(uji_hetero$p.value > 0.05,
                       "Homoskedastis (Terpenuhi)",
                       "Heteroskedastis (Cek Spasial)"),
                ifelse(uji_auto_serial$p.value > 0.05,
                       "Bebas Autokorelasi Waktu", "Ada Autokorelasi Waktu"),
                ifelse(uji_spasial$p.value < 0.05,
                       "Ada Efek Spasial (Lanjut GWPR)",
                       "Tidak Ada Efek Spasial"),
                paste0(round(r_sq * 100, 2), "%"))
)
# --- 4. Cetak Output dengan Kable ---
cat("\n=== RINGKASAN ESTIMASI RANDOM EFFECT MODEL (REM) ===\n")
## 
## === RINGKASAN ESTIMASI RANDOM EFFECT MODEL (REM) ===
print(kable(tabel_estimasi, row.names=FALSE, align="c",
            caption = "Koefisien dan Uji Multikolinearitas"))
## 
## 
## Table: Koefisien dan Uji Multikolinearitas
## 
## |  Variabel   | Koefisien | Std_Error | P_Value | VIF  |   Signifikansi   | Status_VIF |
## |:-----------:|:---------:|:---------:|:-------:|:----:|:----------------:|:----------:|
## | (Intercept) | -82.0254  |  23.0869  | 0.0004  |  NA  | Signifikan (5%)  |     -      |
## |     X1      |  0.0000   |  0.0000   | 0.6231  | 1.20 | Tidak Signifikan |    Aman    |
## |     X2      |  0.0000   |  0.0000   | 0.3890  | 1.57 | Tidak Signifikan |    Aman    |
## |     X3      |  0.0292   |  0.0074   | 0.0001  | 1.35 | Signifikan (5%)  |    Aman    |
## |     X4      |  0.1162   |  0.0269   | 0.0000  | 1.05 | Signifikan (5%)  |    Aman    |
## |     X5      |  0.4508   |  0.1146   | 0.0001  | 1.24 | Signifikan (5%)  |    Aman    |
cat("\n=== DIAGNOSTIK ASUMSI KLASIK & SPASIAL ===\n")
## 
## === DIAGNOSTIK ASUMSI KLASIK & SPASIAL ===
print(kable(tabel_diagnostik, row.names=FALSE, align="l",
            caption = "Hasil Uji Diagnostik"))
## 
## 
## Table: Hasil Uji Diagnostik
## 
## |Uji_Asumsi                      |Nilai_P |Statistik |Keputusan                      |
## |:-------------------------------|:-------|:---------|:------------------------------|
## |Normalitas (KS)                 |0.3138  |0.0785    |Normal (Terpenuhi)             |
## |Heteroskedastisitas (BP)        |0.5460  |4.0239    |Homoskedastis (Terpenuhi)      |
## |Autokorelasi Serial (Waktu)     |0.0014  |36.6224   |Ada Autokorelasi Waktu         |
## |Dependensi Spasial (Pesaran CD) |0.0204  |2.3181    |Ada Efek Spasial (Lanjut GWPR) |
## |R-Squared Overall               |NA      |0.3099    |30.99%                         |
# Histogram 
ggplot(as.data.frame(rem_gls$residuals), aes(x = rem_gls$residuals)) +
  geom_histogram(aes(y = after_stat(density)), color = "white",
                 fill = "steelblue") +
  geom_density(color = "red", linewidth = 1) +
  theme_minimal()
## `stat_bin()` using `bins = 30`. Pick better value `binwidth`.

10. Pemodelan GWPR

Memuat data koordinat wilayah, menentukan bandwidth optimal (Adaptive/Fixed) dengan berbagai fungsi kernel (Bisquare, Gaussian, Exponential), dan membangun model GWPR.

# 10 Geographically Weighted Panel Regression ==================================
# Input Latitude Longitude
wilayah <- fromJSON("https://raw.githubusercontent.com/yusufsyaifudin/wilayah-indonesia/master/data/list_of_area/provinces.json")
wilayah$name <- toupper(wilayah$name)
data.sp.GWPR <- banjir %>%
  left_join(wilayah %>% select(name, latitude, longitude),
            by = c("PROV" = "name")) %>%
  rename(LAT = latitude, LONG = longitude) %>%
  select(PROV, TAHUN, LAT, LONG, everything())
# Modeling GWPR
coordinates(data.sp.GWPR)=3:4
class(data.sp.GWPR)
## [1] "SpatialPointsDataFrame"
## attr(,"package")
## [1] "sp"
# Menentukan Fungsi Pembobot Spasial Terbaik
# Fungsi kernel: ((gaussian, eksponensial, bisquare, Tricube) (adaptive dan fixed))
# --- KELOMPOK ADAPTIVE ---
# 1. Adaptive Bisquare
bwd.GWPR.bisquare.ad <- bw.gwr(Y ~ X1 + X2 + X3 + X4 + X5,
                               data = data.sp.GWPR, approach = "CV",
                               kernel = "bisquare", adaptive=T)
## Adaptive bandwidth: 100 CV score: 43636.5 
## Adaptive bandwidth: 70 CV score: 41819.79 
## Adaptive bandwidth: 50 CV score: 38156.24 
## Adaptive bandwidth: 39 CV score: 36535.15 
## Adaptive bandwidth: 31 CV score: 36535.15
hasil.GWPR.bisquare.ad <- gwr.basic(Y ~ X1 + X2 + X3 + X4 + X5,
                                    data = data.sp.GWPR,
                                    bw = bwd.GWPR.bisquare.ad,
                                    kernel = "bisquare", adaptive=T)
# 2. Adaptive Gaussian
bwd.GWPR.gaussian.ad <- bw.gwr(Y ~ X1 + X2 + X3 + X4 + X5,
                               data = data.sp.GWPR, approach = "CV",
                               kernel = "gaussian", adaptive=T)
## Adaptive bandwidth: 100 CV score: 70008.75 
## Adaptive bandwidth: 70 CV score: 65964.49 
## Adaptive bandwidth: 50 CV score: 58937.44 
## Adaptive bandwidth: 39 CV score: 55737.64 
## Adaptive bandwidth: 31 CV score: 55737.64
hasil.GWPR.gaussian.ad <- gwr.basic(Y ~ X1 + X2 + X3 + X4 + X5,
                                    data = data.sp.GWPR,
                                    bw = bwd.GWPR.gaussian.ad,
                                    kernel = "gaussian", adaptive=T)
# 3. Adaptive Exponential
bwd.GWPR.exponential.ad <- bw.gwr(Y ~ X1 + X2 + X3 + X4 + X5,
                                  data = data.sp.GWPR, approach = "CV",
                                  kernel = "exponential", adaptive=T)
## Adaptive bandwidth: 100 CV score: 62286.85 
## Adaptive bandwidth: 70 CV score: 59273.64 
## Adaptive bandwidth: 50 CV score: 55106.61 
## Adaptive bandwidth: 39 CV score: 53314.57 
## Adaptive bandwidth: 31 CV score: 53314.57
hasil.GWPR.exponential.ad <- gwr.basic(Y ~ X1 + X2 + X3 + X4 + X5,
                                       data = data.sp.GWPR,
                                       bw = bwd.GWPR.exponential.ad,
                                       kernel = "exponential", adaptive=T)
# 4. Adaptive Tricube (BARU)
bwd.GWPR.tricube.ad <- bw.gwr(Y ~ X1 + X2 + X3 + X4 + X5,
                              data = data.sp.GWPR, approach = "CV",
                              kernel = "tricube", adaptive=T)
## Adaptive bandwidth: 100 CV score: 44122.37 
## Adaptive bandwidth: 70 CV score: 41745.24 
## Adaptive bandwidth: 50 CV score: 37500.37 
## Adaptive bandwidth: 39 CV score: 36631.9 
## Adaptive bandwidth: 31 CV score: 36631.9
hasil.GWPR.tricube.ad <- gwr.basic(Y ~ X1 + X2 + X3 + X4 + X5,
                                   data = data.sp.GWPR,
                                   bw = bwd.GWPR.tricube.ad,
                                   kernel = "tricube", adaptive=T)
# --- KELOMPOK FIXED ---
# 5.  Bisquare
bwd.GWPR.bisquare.fix <- bw.gwr(Y ~ X1 + X2 + X3 + X4 + X5,
                                data = data.sp.GWPR, approach = "CV",
                                kernel = "bisquare", adaptive=F)
## Fixed bandwidth: 7.873791 CV score: 48073 
## Fixed bandwidth: 4.867243 CV score: 39069.78 
## Fixed bandwidth: 3.009095 CV score: 34268.34 
## Fixed bandwidth: 1.860696 CV score: 26792.34 
## Fixed bandwidth: 1.150947 CV score: 28458.12 
## Fixed bandwidth: 2.299345 CV score: 24711.74 
## Fixed bandwidth: 2.570446 CV score: 22971.01 
## Fixed bandwidth: 2.737995 CV score: 23261.04 
## Fixed bandwidth: 2.466895 CV score: 23288.38 
## Fixed bandwidth: 2.634444 CV score: 23020.68 
## Fixed bandwidth: 2.530893 CV score: 23055.61 
## Fixed bandwidth: 2.594891 CV score: 22968.27 
## Fixed bandwidth: 2.609999 CV score: 22981.67 
## Fixed bandwidth: 2.585554 CV score: 22965.36 
## Fixed bandwidth: 2.579783 CV score: 22965.93 
## Fixed bandwidth: 2.58912 CV score: 22965.94 
## Fixed bandwidth: 2.583349 CV score: 22965.36 
## Fixed bandwidth: 2.581987 CV score: 22965.49 
## Fixed bandwidth: 2.584191 CV score: 22965.33 
## Fixed bandwidth: 2.584712 CV score: 22965.33 
## Fixed bandwidth: 2.58387 CV score: 22965.33 
## Fixed bandwidth: 2.58439 CV score: 22965.33 
## Fixed bandwidth: 2.584513 CV score: 22965.33 
## Fixed bandwidth: 2.584314 CV score: 22965.33 
## Fixed bandwidth: 2.584437 CV score: 22965.33
hasil.GWPR.bisquare.fix <- gwr.basic(Y ~ X1 + X2 + X3 + X4 + X5,
                                     data = data.sp.GWPR,
                                     bw = bwd.GWPR.bisquare.fix,
                                     kernel = "bisquare", adaptive=F)
# 6. Fixed Gaussian
bwd.GWPR.gaussian.fix <- bw.gwr(Y ~ X1 + X2 + X3 + X4 + X5,
                                data = data.sp.GWPR, approach = "CV",
                                kernel = "gaussian", adaptive=F)
## Fixed bandwidth: 7.873791 CV score: 69333.52 
## Fixed bandwidth: 4.867243 CV score: 57038.7 
## Fixed bandwidth: 3.009095 CV score: 46845.79 
## Fixed bandwidth: 1.860696 CV score: 39337.6 
## Fixed bandwidth: 1.150947 CV score: 34167.23 
## Fixed bandwidth: 0.7122972 CV score: 24725.82 
## Fixed bandwidth: 0.441197 CV score: 27344.92 
## Fixed bandwidth: 0.8798464 CV score: 31464.35 
## Fixed bandwidth: 0.6087462 CV score: 24466.57 
## Fixed bandwidth: 0.5447481 CV score: 25102.2 
## Fixed bandwidth: 0.6482991 CV score: 24144.46 
## Fixed bandwidth: 0.6727442 CV score: 24113.23 
## Fixed bandwidth: 0.6878521 CV score: 24229.29 
## Fixed bandwidth: 0.663407 CV score: 24099.26 
## Fixed bandwidth: 0.6576363 CV score: 24108.04 
## Fixed bandwidth: 0.6669735 CV score: 24100.14 
## Fixed bandwidth: 0.6612028 CV score: 24101.21 
## Fixed bandwidth: 0.6647693 CV score: 24098.99 
## Fixed bandwidth: 0.6656113 CV score: 24099.19 
## Fixed bandwidth: 0.664249 CV score: 24099.01 
## Fixed bandwidth: 0.6650909 CV score: 24099.03 
## Fixed bandwidth: 0.6645706 CV score: 24098.98 
## Fixed bandwidth: 0.6644477 CV score: 24098.99 
## Fixed bandwidth: 0.6646465 CV score: 24098.98 
## Fixed bandwidth: 0.6645236 CV score: 24098.98 
## Fixed bandwidth: 0.6645996 CV score: 24098.98
hasil.GWPR.gaussian.fix <- gwr.basic(Y ~ X1 + X2 + X3 + X4 + X5,
                                     data = data.sp.GWPR,
                                     bw = bwd.GWPR.gaussian.fix,
                                     kernel = "gaussian", adaptive=F)
# 7. Fixed Exponential
bwd.GWPR.exponential.fix <- bw.gwr(Y ~ X1 + X2 + X3 + X4 + X5,
                                   data = data.sp.GWPR, approach = "CV",
                                   kernel = "exponential", adaptive=F)
## Fixed bandwidth: 7.873791 CV score: 62204.64 
## Fixed bandwidth: 4.867243 CV score: 54130.08 
## Fixed bandwidth: 3.009095 CV score: 47025.43 
## Fixed bandwidth: 1.860696 CV score: 41651.48 
## Fixed bandwidth: 1.150947 CV score: 37707.6 
## Fixed bandwidth: 0.7122972 CV score: 33565.85 
## Fixed bandwidth: 0.441197 CV score: 28431.57 
## Fixed bandwidth: 0.2736479 CV score: 25288.98 
## Fixed bandwidth: 0.1700968 CV score: 28185.32 
## Fixed bandwidth: 0.337646 CV score: 25118.05 
## Fixed bandwidth: 0.377199 CV score: 25936.37 
## Fixed bandwidth: 0.3132009 CV score: 25010.59 
## Fixed bandwidth: 0.298093 CV score: 25063.39 
## Fixed bandwidth: 0.3225381 CV score: 25020.24 
## Fixed bandwidth: 0.3074302 CV score: 25021.55 
## Fixed bandwidth: 0.3167674 CV score: 25010.09 
## Fixed bandwidth: 0.3189716 CV score: 25012.33 
## Fixed bandwidth: 0.3154051 CV score: 25009.69 
## Fixed bandwidth: 0.3145632 CV score: 25009.81 
## Fixed bandwidth: 0.3159254 CV score: 25009.76 
## Fixed bandwidth: 0.3150835 CV score: 25009.71 
## Fixed bandwidth: 0.3156038 CV score: 25009.71 
## Fixed bandwidth: 0.3152823 CV score: 25009.69
hasil.GWPR.exponential.fix <- gwr.basic(Y ~ X1 + X2 + X3 + X4 + X5,
                                        data = data.sp.GWPR,
                                        bw = bwd.GWPR.exponential.fix,
                                        kernel = "exponential", adaptive=F)
# 8. Fixed Tricube (BARU)
bwd.GWPR.tricube.fix <- bw.gwr(Y ~ X1 + X2 + X3 + X4 + X5,
                               data = data.sp.GWPR, approach = "CV",
                               kernel = "tricube", adaptive=F)
## Fixed bandwidth: 7.873791 CV score: 48442.01 
## Fixed bandwidth: 4.867243 CV score: 39172.72 
## Fixed bandwidth: 3.009095 CV score: 33207.67 
## Fixed bandwidth: 1.860696 CV score: 26894.05 
## Fixed bandwidth: 1.150947 CV score: 28458.12 
## Fixed bandwidth: 2.299345 CV score: 24840.73 
## Fixed bandwidth: 2.570446 CV score: 23057.9 
## Fixed bandwidth: 2.737995 CV score: 23004.35 
## Fixed bandwidth: 2.841546 CV score: 24976.5 
## Fixed bandwidth: 2.673997 CV score: 22903.65 
## Fixed bandwidth: 2.634444 CV score: 22912.8 
## Fixed bandwidth: 2.698442 CV score: 22929.27 
## Fixed bandwidth: 2.658889 CV score: 22899.05 
## Fixed bandwidth: 2.649552 CV score: 22901.11 
## Fixed bandwidth: 2.664659 CV score: 22899.69 
## Fixed bandwidth: 2.655322 CV score: 22899.38 
## Fixed bandwidth: 2.661093 CV score: 22899.13 
## Fixed bandwidth: 2.657526 CV score: 22899.11 
## Fixed bandwidth: 2.659731 CV score: 22899.06 
## Fixed bandwidth: 2.658368 CV score: 22899.07 
## Fixed bandwidth: 2.65921 CV score: 22899.05 
## Fixed bandwidth: 2.659409 CV score: 22899.05 
## Fixed bandwidth: 2.659088 CV score: 22899.05 
## Fixed bandwidth: 2.659286 CV score: 22899.05 
## Fixed bandwidth: 2.659163 CV score: 22899.05
hasil.GWPR.tricube.fix <- gwr.basic(Y ~ X1 + X2 + X3 + X4 + X5,
                                    data = data.sp.GWPR,
                                    bw = bwd.GWPR.tricube.fix,
                                    kernel = "tricube", adaptive=F)

11. Pemilihan Model Terbaik & Parameter Lokal

Membandingkan kebaikan model berdasarkan AIC/AICc, R-Squared, dan RSS, serta menampilkan parameter lokal dan signifikansinya per provinsi.

AIC <- c(hasil.GWPR.bisquare.ad$GW.diagnostic$AIC,
         hasil.GWPR.gaussian.ad$GW.diagnostic$AIC,
         hasil.GWPR.exponential.ad$GW.diagnostic$AIC,
         hasil.GWPR.tricube.ad$GW.diagnostic$AIC,   
         hasil.GWPR.bisquare.fix$GW.diagnostic$AIC,
         hasil.GWPR.gaussian.fix$GW.diagnostic$AIC,
         hasil.GWPR.exponential.fix$GW.diagnostic$AIC,
         hasil.GWPR.tricube.fix$GW.diagnostic$AIC)    

R2 <- c(hasil.GWPR.bisquare.ad$GW.diagnostic$gw.R2,
        hasil.GWPR.gaussian.ad$GW.diagnostic$gw.R2,
        hasil.GWPR.exponential.ad$GW.diagnostic$gw.R2,
        hasil.GWPR.tricube.ad$GW.diagnostic$gw.R2,    
        hasil.GWPR.bisquare.fix$GW.diagnostic$gw.R2,
        hasil.GWPR.gaussian.fix$GW.diagnostic$gw.R2,
        hasil.GWPR.exponential.fix$GW.diagnostic$gw.R2,
        hasil.GWPR.tricube.fix$GW.diagnostic$gw.R2)   

AICc <- c(hasil.GWPR.bisquare.ad$GW.diagnostic$AICc,
          hasil.GWPR.gaussian.ad$GW.diagnostic$AICc,
          hasil.GWPR.exponential.ad$GW.diagnostic$AICc,
          hasil.GWPR.tricube.ad$GW.diagnostic$AICc,   
          hasil.GWPR.bisquare.fix$GW.diagnostic$AICc,
          hasil.GWPR.gaussian.fix$GW.diagnostic$AICc,
          hasil.GWPR.exponential.fix$GW.diagnostic$AICc,
          hasil.GWPR.tricube.fix$GW.diagnostic$AICc)  

R2adj <- c(hasil.GWPR.bisquare.ad$GW.diagnostic$gwR2.adj,
           hasil.GWPR.gaussian.ad$GW.diagnostic$gwR2.adj,
           hasil.GWPR.exponential.ad$GW.diagnostic$gwR2.adj,
           hasil.GWPR.tricube.ad$GW.diagnostic$gwR2.adj,  
           hasil.GWPR.bisquare.fix$GW.diagnostic$gwR2.adj,
           hasil.GWPR.gaussian.fix$GW.diagnostic$gwR2.adj,
           hasil.GWPR.exponential.fix$GW.diagnostic$gwR2.adj,
           hasil.GWPR.tricube.fix$GW.diagnostic$gwR2.adj) 

RSS <- c(hasil.GWPR.bisquare.ad$GW.diagnostic$RSS.gw,
         hasil.GWPR.gaussian.ad$GW.diagnostic$RSS.gw,
         hasil.GWPR.exponential.ad$GW.diagnostic$RSS.gw,
         hasil.GWPR.tricube.ad$GW.diagnostic$RSS.gw,    
         hasil.GWPR.bisquare.fix$GW.diagnostic$RSS.gw,
         hasil.GWPR.gaussian.fix$GW.diagnostic$RSS.gw,
         hasil.GWPR.exponential.fix$GW.diagnostic$RSS.gw,
         hasil.GWPR.tricube.fix$GW.diagnostic$RSS.gw) 

tabel <- cbind(RSS,R2,R2adj,AIC,AICc)
rownames(tabel) <- c("Adaptive Bisquare", "Adaptive Gaussian",
                     "Adaptive Exponential", "Adaptive Tricube", "Fixed Bisquare",
                     "Fixed Gaussian", "Fixed Exponential", "Fixed Tricube")
data.frame(tabel)
# Pendugaan Parameter
parameter.GWPR <- as.data.frame(
  hasil.GWPR.tricube.fix$SDF[1:10,1:6])[-c(7,8)]
parameter.GWPR %>% 
  mutate(PROV=banjir$PROV[1:10]) %>% 
  select(PROV, everything())
parameter_R2 <- as.data.frame(
  hasil.GWPR.tricube.fix$SDF[1:10,c(1:6,24)])[-8:-19]
# R2 setiap provinsi
parameter_R2 %>% 
  mutate(PROV=banjir$PROV[1:10]) %>%
  select(PROV, Local_R2) %>% 
  arrange(-Local_R2)
# 11 Signifikasi parameter (p-value) ===========================================
p_value <- gwr.t.adjust(hasil.GWPR.tricube.fix)$results$p
p_value <- as.data.frame(ifelse(p_value<=0.05, "Signifikan", "Tidak"))[1:10,]
p_value %>% 
  mutate(PROV=banjir$PROV[1:10]) %>% 
  select(PROV, everything())
#Filter Provinsi yang mempunyai signifikansi pada peubah X1
p_value %>% 
  mutate(PROV=banjir$PROV[1:10]) %>% 
  select(PROV, X1_p) %>% 
  filter("Signifikan" == p_value$X1)
#Filter Provinsi yang mempunyai signifikansi pada peubah X2
p_value %>% 
  mutate(PROV=banjir$PROV[1:10]) %>% 
  select(PROV, X2_p) %>% 
  filter("Signifikan" == p_value$X2)
#Filter Provinsi yang mempunyai signifikansi pada peubah X3
p_value %>% 
  mutate(PROV=banjir$PROV[1:10]) %>% 
  select(PROV, X3_p) %>% 
  filter("Signifikan" == p_value$X3)
#Filter Provinsi yang mempunyai signifikansi pada peubah X4
p_value %>% 
  mutate(PROV=banjir$PROV[1:10]) %>% 
  select(PROV, X4_p) %>% 
  filter("Signifikan" == p_value$X4)
# Filter Provinsi yang mempunyai signifikansi pada peubah X5
p_value %>% 
  mutate(PROV=banjir$PROV[1:10]) %>% 
  select(PROV, X5_p) %>% 
  filter("Signifikan" == p_value$X5)
# Lihat koefisien untuk provinsi tertentu (misal baris ke-1 adalah Sumatera Utara)
hasil.GWPR.tricube.fix$SDF[1,] 
##          coordinates Intercept            X1           X2        X3        X4
## 1 (4.36855, 97.0253)  132.0107 -0.0005626677 -0.003256374 0.2081083 0.1654052
##          X5  y     yhat  residual CV_Score Stud_residual Intercept_SE
## 1 -1.533336 36 35.21741 0.7825929        0     0.1102028     84.45181
##          X1_SE        X2_SE     X3_SE      X4_SE    X5_SE Intercept_TV
## 1 0.0004214656 0.0009942214 0.1355392 0.07654525 1.120265     1.563148
##       X1_TV   X2_TV   X3_TV    X4_TV     X5_TV  Local_R2
## 1 -1.335027 -3.2753 1.53541 2.160882 -1.368726 0.9256041
# Atau jika ingin melihat signifikansi (t-hitung) untuk memberi tanda bintang (*)
gwr.t.adjust(hasil.GWPR.tricube.fix)$results$t[1,]
## Intercept_t        X1_t        X2_t        X3_t        X4_t        X5_t 
##    1.563148   -1.335027   -3.275300    1.535410    2.160882   -1.368726

12. Uji Kesesuaian Model (Global vs Lokal)

Melakukan uji F untuk membandingkan apakah model GWPR (lokal) secara signifikan lebih baik daripada model global (REM).

# 12.  Uji Kesesuaian Model ====================================================
# Uji F
rss_rem <- sum(rem_gls$residuals^2)
rss_gwpr <- hasil.GWPR.tricube.fix$GW.diagnostic$RSS.gw
df_rem <- rem_gls$df.residual
df_gwpr <- hasil.GWPR.tricube.fix$GW.diagnostic$edf
Fhit=(rss_gwpr/df_gwpr)/(rss_rem/df_rem)
Fhit
## [1] 0.5599753
pf(Fhit,df_gwpr,df_rem)
## [1] 0.0008418435
comparison <- data.frame(R2=c(hasil.GWPR.tricube.fix$GW.diagnostic$gw.R2,
                              summary(rem_gls)$r.squared[1]),
                         R2adj=c(hasil.GWPR.tricube.fix$GW.diagnostic$gwR2.adj,
                                 summary(rem_gls)$r.squared[2]),
                         RSS=c(hasil.GWPR.tricube.fix$GW.diagnostic$RSS.gw,
                               sum(summary(rem_gls)$residuals^2)))
rownames(comparison) <- c("GWPR", "REM Two Ways")
comparison
# ==============================================================================
# UJI ANOVA (UJI F) PERBANDINGAN MODEL GLOBAL VS GWPR
# ==============================================================================

# 1. Masukkan Nilai RSS dan DF (Gunakan Data dari Tabel 6 Anda agar Konsisten)
# ------------------------------------------------------------------------------
# Nilai ini diambil dari Tabel 6 yang Anda tunjukkan sebelumnya (yang R2-nya 78%)
RSS_Global <- sum(summary(rem_gls)$residuals^2)  # RSS dari REM Two Ways
RSS_GWPR   <- hasil.GWPR.tricube.fix$GW.diagnostic$RSS.gw   # RSS dari GWPR Bisquare Fixed

# Ambil Degrees of Freedom (DF)
# Ganti obj_global dan obj_gwpr dengan nama objek model asli Anda
DF_Global  <- rem_gls$df.residual               
DF_GWPR    <- hasil.GWPR.tricube.fix$GW.diagnostic$edf 

# 2. Perhitungan Statistik F
# ------------------------------------------------------------------------------
# Hitung Selisih (Improvement)
SS_Improvement <- RSS_Global - RSS_GWPR       # Seberapa banyak error berkurang
DF_Improvement <- DF_Global - DF_GWPR         # Selisih derajat bebas

# Hitung Mean Square (Rata-rata Kuadrat)
MS_Improvement <- SS_Improvement / DF_Improvement
MS_GWPR        <- RSS_GWPR / DF_GWPR

# Hitung F-Statistik
F_Hitung <- MS_Improvement / MS_GWPR

# Hitung P-Value
P_Value  <- pf(F_Hitung, df1 = DF_Improvement, df2 = DF_GWPR, lower.tail = FALSE)

# 3. Menyusun Tabel Sesuai Format yang Anda Inginkan (F di Bawah)
# ------------------------------------------------------------------------------
anova_table <- data.frame(
  Sumber_Variasi = c("Global Residuals (REM)", "GWPR Improvement", "GWPR Residuals"),
  DF = c(DF_Global, DF_Improvement, DF_GWPR),
  SS = c(RSS_Global, SS_Improvement, RSS_GWPR),
  MS = c(NA, MS_Improvement, MS_GWPR),
  F_Stat = c(NA, NA, F_Hitung),
  P_Value = c(NA, NA, P_Value)
)

# Merapikan Angka (Pembulatan)
anova_table$SS <- round(anova_table$SS, 2)
anova_table$MS <- round(anova_table$MS, 2)
anova_table$F_Stat <- round(anova_table$F_Stat, 4)
anova_table$P_Value <- format(anova_table$P_Value, scientific = TRUE, digits = 4)

# Ubah NA menjadi kosong agar rapi saat diprint
anova_table[is.na(anova_table)] <- "NA"

# Tampilkan Hasil
print(anova_table)
##           Sumber_Variasi        DF       SS     MS F_Stat   P_Value
## 1 Global Residuals (REM) 144.00000 31795.53     NA     NA        NA
## 2       GWPR Improvement  36.07932 18451.80 511.42     NA        NA
## 3         GWPR Residuals 107.92068 13343.73 123.64 4.1363 5.858e-09

13. Visualisasi Peta Signifikansi

Membuat peta tematik yang menunjukkan kombinasi variabel yang signifikan berpengaruh terhadap kejadian banjir di setiap provinsi.

# VISUALISASI PETA: KOMBINASI VARIABEL SIGNIFIKAN ==============================
# 1. Persiapan Data Signifikansi 
# Ambil hasil p-value yang sudah di-adjust. Pastikan urutan data sesuai.
# Karena data panel, kita ambil representasi unik provinsi (10 baris pertama)
# Asumsi: 10 baris pertama mewakili urutan provinsi di data 'banjir'
res_t_adj <- gwr.t.adjust(hasil.GWPR.tricube.fix) 
p_vals_matrix <- res_t_adj$results$p[1:10, ]
# Buat Data Frame Signifikansi
df_sig_map <- data.frame(
  PROV = banjir$PROV[1:10], # Mengambil nama provinsi
  p_vals_matrix
)
# Tentukan nama variabel X
# (sesuaikan dengan colnames dari p_vals_matrix selain Intercept)
# Biasanya: X1.1, X2.1 dst atau X1, X2. Kita bersihkan nama kolomnya.
vars_target <- c("X1", "X2", "X3", "X4", "X5")
# Cek kolom mana yang sesuai dengan vars_target di df_sig_map
# (Terkadang output gwr memberi suffix .1, .2 dst)
cols_idx <- grep(paste(vars_target, collapse="|"), colnames(df_sig_map))
# 2. Membuat Kolom Kombinasi "var_sig" 
df_sig_map$var_sig <- apply(df_sig_map[, cols_idx], 1, function(row) {
  # Cek variabel mana yang p-value <= 0.05
  is_sig <- row <= 0.05
  # Ambil nama variabel yang TRUE
  # Kita mapping index row ke nama vars_target agar rapi
  nama_sig <- vars_target[is_sig]
  if (length(nama_sig) == 0) {
    return("Tidak Signifikan")
  } else {
    return(paste(sort(nama_sig), collapse = ", "))
  }
})
# Cek tabel rekapitulasi sementara
print(table(df_sig_map$var_sig))
## 
## Tidak Signifikan           X1, X5       X2, X3, X5           X2, X4 
##                2                1                1                1 
##               X3       X3, X4, X5 
##                2                3
# 3. Persiapan Data Spasial (Shapefile) 
library(rnaturalearth)
library(sf)
# Ambil peta Indonesia level provinsi
indo_map <- ne_states(country = "indonesia", returnclass = "sf")
# Filter hanya Pulau Sumatera
# Daftar nama provinsi di rnaturalearth mungkin Title Case, data Anda UPPERCASE.
# Kita samakan dulu.
indo_map$name_upper <- toupper(indo_map$name)
list_sumatera <- c("ACEH", "SUMATERA UTARA", "SUMATERA BARAT", "RIAU", 
                   "KEPULAUAN RIAU", "JAMBI", "BENGKULU", "SUMATERA SELATAN", 
                   "KEPULAUAN BANGKA BELITUNG", "LAMPUNG")
sumatera_sf <- indo_map %>% 
  filter(name_upper %in% list_sumatera)
# Gabungkan (Join) Data Signifikansi ke Peta
# Pastikan nama kolom kunci sama (PROV vs name_upper)
map_final <- sumatera_sf %>%
  left_join(df_sig_map, by = c("name_upper" = "PROV"))
urutan_custom <- c("X2, X3, X5",
                   "X3, X4, X5",
                   "X1, X5",
                   "X2, X4",
                   "X3"
)
# Ubah var_sig menjadi factor agar legend rapi
map_final$var_sig <- factor(map_final$var_sig, levels = urutan_custom)
# 4. Visualisasi (Gaya Kustom) 
# Definisikan palet warna dinamis
# kita pakai palette RColorBrewer
library(RColorBrewer)
jml_kategori <- length(levels(map_final$var_sig))
# Jika kategori sedikit pakai manual, jika banyak pakai palette otomatis
# 3. Definisikan Warna Berdasarkan Logika Pencampuran
# Format: c("KATEGORI" = "KODE_HEX")
# Definisikan warna pilihan
# Menambahkan warna Merah Tua (#800026) di bagian akhir
my_colors_logic <- c(
  "#08519C", 
  "#3182BD", 
  "#9ECAE1", 
  "#31A354", 
  "#756BB1" 
)
# Plotting
ggplot(data = map_final) +
  geom_sf(aes(fill = var_sig), color = "black", size = 0.2) +
  scale_fill_manual(
    values = my_colors_logic,
    name = "Peubah Signifikan",
    na.value = "grey80", # Warna jika ada provinsi yang datanya NA
    guide = guide_legend(
      title.position = "top",
      title.hjust = 0.5,
      label.position = "right"
    )
  ) +
  labs(
    title = "Peta Sebaran Signifikansi Parsial GWPR",
    subtitle = "Wilayah Pulau Sumatera (2010-2024)",
    caption = "Sumber: Hasil Olah Data (2026)"
  ) +
  theme_void() + # Tema kosong (tanpa axis/grid)
  theme(
    legend.position = "right",
    legend.title = element_text(face = "bold", size = 10),
    legend.text = element_text(size = 9),
    legend.key.width = unit(1, "cm"),
    legend.key.height = unit(1, "cm"),
    plot.title = element_text(hjust = 0.5, face = "bold",
                              size = 16, margin = margin(b=10)),
    plot.subtitle = element_text(hjust = 0.5, size = 12, margin = margin(b=20))
  )

LS0tDQp0aXRsZTogIkFuYWxpc2lzIFNwYXNpYWwtVGVtcG9yYWwgRGV0ZXJtaW5hbiBCYW5qaXIgUHVsYXUgU3VtYXRlcmEgTWVuZ2d1bmFrYW4gR2VvZ3JhcGhpY2FsbHkgV2VpZ2h0ZWQgUGFuZWwgUmVncmVzc2lvbiBVbnR1ayBLZWJpamFrYW4gUGVtYmFuZ3VuYW4gV2lsYXlhaCBEYW4gTWl0aWdhc2kgQmVuY2FuYSBCZXJrZWxhbmp1dGFuIg0Kc3VidGl0bGU6ICJQZW5lcmFwYW4gTWV0b2RlIEdlb2dyYXBoaWNhbGx5IFdlaWdodGVkIFBhbmVsIFJlZ3Jlc3Npb24gKEdXUFIpIHVudHVrIG1lbmdpbmRlbnRpZmlrYXNpZmFrdG9yIHBlbnllYmFiIEtlamFkaWFuIEJhbmppciBkaSBQdWxhdSBTdW1hdGVyYSBwYWRhIHRhaHVuIDIwMTAtMjAyNCBiZXJiYXNpcyBkYXRhIGxpbmdrdW5nYW4iDQphdXRob3I6ICJBaG1hZCBIZWxtaSBZYXNpciINCmRhdGU6ICIyMDI2LTAyLTAxIg0Kb3V0cHV0OiANCiAgcm1kZm9ybWF0czo6ZG93bmN1dGU6DQogICAgZG93bmN1dGVfdGhlbWU6ICJjaGFvcyINCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICB0b2NfZGVwdGg6IDMNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgICB0aGVtZTogY2VydWxlYW4NCiAgICBoaWdobGlnaHQ6ICJrYXRlIg0KLS0tDQoNCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij4NCg0KKipBbmdnb3RhIEtlbG9tcG9rKioNCg0KPC9wPg0KDQotICAgQWhtYWQgSGVsbWkgWWFzaXIgKEtldHVhKQ0KLSAgIE5hamxhIEtoYWxpc2ENCi0gICBHdXN0aSBMdXFtYW4gTm9yIEhhZml6aA0KLSAgIE11aGFtbWFkIEloc2FuDQotICAgTnVyIFJpZGhvIEFyaWYgQmlsbGFoDQoNCiMgMS4gUHVzdGFrYSAoTGlicmFyeSkNCg0KVGFoYXAgcGVydGFtYSBtZW11YXQgc2VsdXJ1aCAqbGlicmFyeSogeWFuZyBkaXBlcmx1a2FuIHVudHVrIGFuYWxpc2lzIGRhdGEgcGFuZWwsIHNwYXNpYWwsIGRhbiB2aXN1YWxpc2FzaS4NCg0KYGBge3Igd2FybmluZz1GLCBtZXNzYWdlPUZ9DQojIEdXUFIgaW4gU3VtYXRyYSBJc2xhbmQgMjAxMC0yMDI0ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDEuIExpYnJhcnkgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpsaWJzIDwtIGMoImdwbG90cyIsICJrYWJsZUV4dHJhIiwgInRpZHl2ZXJzZSIsICJwbG0iLCAidGlueXRleCIsICJ0c2VyaWVzIiwgDQogICAgICAgICAgImxtdGVzdCIsICJicm9vbSIsICJzdGFyZ2F6ZXIiLCAiUkNvbG9yQnJld2VyIiwgImNvcnJwbG90IiwgImNhciIsIA0KICAgICAgICAgICJyZWFkeGwiLCAianNvbmxpdGUiLCAiR1dtb2RlbCIsICJzZiIsICJybmF0dXJhbGVhcnRoIiwgInBhdGNod29yayIsDQogICAgICAgICAgInZpcmlkaXMiLCJwbG0iLCJrbml0ciIsIkRlc2NUb29scyIsInRpZHlyIiwgImdncGxvdDIiLCJzcGRlcCIpDQpsYXBwbHkobGlicywgbGlicmFyeSwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKQ0KYGBgDQoNCiMgMi4gUGVyc2lhcGFuIERhdGENCg0KTWVtdWF0IGRhdGEga2VqYWRpYW4gYmFuamlyIGRpIFB1bGF1IFN1bWF0ZXJhLCBtZWxha3VrYW4gcGVueWVzdWFpYW4gbmFtYSBrb2xvbSwgcGVuZ2F0dXJhbiB0aXBlIGRhdGEsIGRhbiBwZW5nZWNla2FuICptaXNzaW5nIHZhbHVlLCBkYW4gbWVuY2VrIG91dGxpZXIgZGFuIG1lbGFrdWthbiBwZW5hbmdhbmFuKi4NCg0KYGBge3Igd2FybmluZz1GLCBtZXNzYWdlPUZ9DQojIDIuIERhdGEgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpzZXR3ZCgiRDovS3VsaWFoL0xvbWJhL1BLTS1BSSAyMDI2IikNCmJhbmppciA8LSByZWFkX2V4Y2VsKCJkYXRhX2Jhbmppcl9wdWxhdXN1bWF0ZXJhLnhsc3giLCBzaGVldCA9ICIyMDEwIikNCiMgUGVuYW1hYW4ga29sb20gYWdhciBrb25zaXN0ZW4gZGVuZ2FuIGFuYWxpc2lzIHNlbGFuanV0bnlhDQpjb2xuYW1lcyhiYW5qaXIpIDwtIGMoIlBST1YiLCAiVEFIVU4iLCAiWSIsICJYMSIsICJYMiIsICJYMyIsICJYNCIsICJYNSIpDQpiYW5qaXIkUFJPViA8LSBhcy5mYWN0b3IodG91cHBlcihiYW5qaXIkUFJPVikpDQpiYW5qaXIkVEFIVU4gPC0gYXMuZmFjdG9yKGJhbmppciRUQUhVTikNCg0KIyBQcmUtUHJvY2Vzc2luZyBEYXRhDQojIENlayBNaXNzaW5nIFZhbHVlDQpwcmludChjb2xTdW1zKGlzLm5hKGJhbmppcikpKQ0KDQojIENlayBEdXBsaWthc2kgRGF0YQ0KIyBNZW5naGl0dW5nIGp1bWxhaCB0b3RhbCBiYXJpcyB5YW5nIGR1cGxpa2F0DQpqdW1sYWhfZHVwbGlrYXNpIDwtIHN1bShkdXBsaWNhdGVkKGJhbmppcikpDQpwcmludChwYXN0ZSgiSnVtbGFoIGRhdGEgZHVwbGlrYXQ6IiwganVtbGFoX2R1cGxpa2FzaSkpDQojIE1lbmFtcGlsa2FuIGJhcmlzIGRhdGEgeWFuZyBkdXBsaWthdCAoamlrYSBhZGEpDQppZiAoanVtbGFoX2R1cGxpa2FzaSA+IDApIHsNCiAgcHJpbnQoIkRldGFpbCBkYXRhIHlhbmcgdGVyZHVwbGlrYXNpOiIpDQogIHByaW50KGJhbmppcltkdXBsaWNhdGVkKGJhbmppciksIF0pDQp9IGVsc2Ugew0KICBwcmludCgiVGlkYWsgZGl0ZW11a2FuIGRhdGEgZHVwbGlrYXQgKGJlcnNpaCkuIikNCn0NCg0KDQpgYGANCg0KIyAzLiBFa3NwbG9yYXNpIERhdGENCg0KTWVsYWt1a2FuIHZpc3VhbGlzYXNpIHVudHVrIG1lbGloYXQgcG9sYSBrZXJhZ2FtYW4ga2VqYWRpYW4gYmFuamlyIGJlcmRhc2Fya2FuIHdha3R1IGRhbiBhbnRhciBwcm92aW5zaSwgc2VydGEgbWVsaWhhdCBrb3JlbGFzaSBhbnRhciB2YXJpYWJlbC4NCg0KYGBge3IgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTZ9DQojIDMuIEVrc3Bsb3Jhc2kgRGF0YSA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0Kc3VtbWFyeV9zdGF0cyA8LSBiYW5qaXIgJT4lDQogIGRwbHlyOjpzZWxlY3QoIlkiLCAiWDEiLCAiWDIiLCAiWDMiLCAiWDQiLCJYNSIpICU+JQ0KICBzdW1tYXJpc2VfYWxsKGxpc3QoDQogICAgTWluID0gfm1pbiguKSwNCiAgICBRMSA9IH5xdWFudGlsZSguLCAwLjI1KSwNCiAgICBNZWRpYW4gPSB+bWVkaWFuKC4pLA0KICAgIE1lYW4gPSB+bWVhbiguKSwNCiAgICBRMyA9IH5xdWFudGlsZSguLCAwLjc1KSwNCiAgICBNYXggPSB+bWF4KC4pLA0KICAgIFNEID0gfnNkKC4pDQogICkpICU+JQ0KICBwaXZvdF9sb25nZXIoZXZlcnl0aGluZygpLA0KICAgICAgICAgICAgICAgbmFtZXNfdG8gPSBjKCJWYXJpYWJsZSIsICJTdGF0aXN0aWMiKSwNCiAgICAgICAgICAgICAgIG5hbWVzX3NlcCA9ICJfIikgJT4lDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBTdGF0aXN0aWMsIHZhbHVlc19mcm9tID0gdmFsdWUpDQoNCmthYmxlKHN1bW1hcnlfc3RhdHMpDQoNCiMgS2VyYWdhbWFuIEFudGFyIFdha3R1DQpnZ3Bsb3QoZGF0YSA9IGJhbmppciwgYWVzKHggPSBUQUhVTiwgeSA9IFkpKSArDQogIGdlb21fbGluZSgpICsNCiAgbGFicyh4ID0gIlRhaHVuIiwgeSA9ICJKdW1sYWggS2VqYWRpYW4gQmFuamlyIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgdGhlbWVfYncoKQ0KIyBLZXJhZ2FtYW4gQW50YXIgSW5kaXZpZHUNCmdwbG90czo6cGxvdG1lYW5zKFkgfiBgUFJPVmAsIG1haW49IktlcmFnYW1hbiBBbnRhciBLZWphZGlhbiBCYW5qaXIiLA0KICAgICAgICAgICAgICAgICAgYmFuamlyLCBuLmxhYmVsID0gRikNCg0KIyBEaSBzaW5pIHNheWEgYXN1bXNpa2FuIGNvbnRpbnVvdXMgYWdhciBzdW1idSBYIHJhcGkNCmJhbmppciRUQUhVTiA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihiYW5qaXIkVEFIVU4pKQ0KIyBQbG90dGluZw0KcCA8LSBnZ3Bsb3QoZGF0YSA9IGJhbmppciwgYWVzKHggPSBUQUhVTiwgeSA9IFkpKSArDQogICMgMS4gREFUQSBNRU5UQUggKEJBQ0tHUk9VTkQpDQogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjIpLCANCiAgICAgICAgICAgICBhbHBoYSA9IDAuMywgDQogICAgICAgICAgICAgY29sb3IgPSAiZ3JleTYwIiwgDQogICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKw0KICAjIDIuIEdBUklTIFJBVEEtUkFUQSAoQ0VOVFJBTCBURU5ERU5DWSkNCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sIA0KICAgICAgICAgICAgICAgZ2VvbSA9ICJsaW5lIiwgDQogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgc2l6ZSA9IDAuOCkgKw0KICAjIDMuIFRJVElLIFJBVEEtUkFUQQ0KICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgDQogICAgICAgICAgICAgICBnZW9tID0gInBvaW50IiwgDQogICAgICAgICAgICAgICBzaGFwZSA9IDE4LCAgICAgICAgIyBTaGFwZSBkaWFtb25kIChmb3JtYWwpDQogICAgICAgICAgICAgICBzaXplID0gMywgDQogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsNCiAgIyA0LiBFUlJPUiBCQVJTIChWQVJJQUJJTElUQVMpIC0gU2FuZ2F0IGRpc3VrYWkgcmV2aWV3ZXINCiAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9zZSwgDQogICAgICAgICAgICAgICBnZW9tID0gImVycm9yYmFyIiwgDQogICAgICAgICAgICAgICB3aWR0aCA9IDAuMiwgDQogICAgICAgICAgICAgICBzaXplID0gMC42KSArDQogICMgNS4gUEVNRk9STUFUQU4gTEFCRUwgJiBTS0FMQQ0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gdW5pcXVlKGJhbmppciRUQUhVTikpICsgDQogIGxhYnMoeCA9ICJUYWh1biBQZW5nYW1hdGFuIiwgDQogICAgICAgeSA9ICJGcmVrdWVuc2kgS2VqYWRpYW4gQmFuamlyIiwNCiAgICAgICBjYXB0aW9uID0gIlN1bWJlcjogW1NlYnV0a2FuIERhdGEgQW5kYSBEaXNpbmldXG5FcnJvciBiYXJzIG1lbnVuanVra2FuIFN0YW5kYXJkIEVycm9yIG9mIE1lYW4gKFNFTSkiKSArDQogIA0KICAjIDYuIFRFTUEgSUxNSUFIIChQVUJMSUNBVElPTiBSRUFEWSBUSEVNRSkNCiAgdGhlbWVfYncoKSArICMgRGFzYXIgaGl0YW0gcHV0aWgNCiAgdGhlbWUoDQogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAic2VyaWYiKSwgICAgICANCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3IgPSAiYmxhY2siKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksICAgICAgIA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksICAgICAgICAgIyBIaWxhbmdrYW4gbWlub3IgZ3JpZA0KICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwgIyBQZXJ0ZWdhcyBnYXJpcyBzdW1idQ0KICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAsIGZhY2UgPSAiaXRhbGljIiwgc2l6ZSA9IDkpDQogICkNCnByaW50KHApDQoNCiMgQ29ycmVsYXRpb24gUGxvdA0KY29ycnBsb3QoY29yKGJhbmppclstYygxOjIpXSksIG1ldGhvZD0iY29sb3IiLCB0eXBlID0gInVwcGVyIiwgdGwucG9zID0gJ3RwJykNCmNvcnJwbG90KGNvcihiYW5qaXJbLWMoMToyKV0pLCBtZXRob2Q9Im51bWJlciIsIGRpYWc9RiwgYWRkPVQsIHR5cGUgPSAibG93ZXIiLA0KICAgICAgICAgdGwucG9zID0gJ24nLCBjbC5wb3MgPSAnbicpDQpgYGANCg0KIyA0LiBVamkgTXVsdGlrb2xpbmVhcml0YXMNCg0KUGVuZ2VjZWthbiBtYXNhbGFoIG11bHRpa29saW5lYXJpdGFzIGFudGFyIHZhcmlhYmVsIGJlYmFzIG1lbmdndW5ha2FuIG5pbGFpIFZJRiAoKlZhcmlhbmNlIEluZmxhdGlvbiBGYWN0b3IqKS4NCg0KYGBge3J9DQojIDQuIFNlbGVrc2kgUGV1YmFoIE11bHRpa29saW5lYXJpdGFzID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KY2hlY2tfbW9kZWwgPC0gbG0oWSB+IFgxICsgWDIgKyBYMyArIFg0ICsgWDUsIGJhbmppcikNCmRhdGEuZnJhbWUodCh2aWYoY2hlY2tfbW9kZWwpKSkNCmBgYA0KDQojIDUuIFBlbW9kZWxhbiBEYXRhIFBhbmVsIChDRU0gJiBGRU0pDQoNCkVzdGltYXNpIHBhcmFtZXRlciBtZW5nZ3VuYWthbiBwZW5kZWthdGFuICpDb21tb24gRWZmZWN0IE1vZGVsKiAoQ0VNKSBkYW4gKkZpeGVkIEVmZmVjdCBNb2RlbCogKEZFTSkgZGVuZ2FuIGJlcmJhZ2FpIGVmZWsgKEluZGl2aWR1LCBXYWt0dSwgVHdvLXdheXMpLg0KDQpgYGB7cn0NCiMgNS4gQ29tbW9uLUVmZmVjdCBNb2RlbCA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIE1vZGVsIENFTQ0KY2VtIDwtIHBsbShZIH4gWDEgKyBYMiArIFgzICsgWDQgKyBYNSwgZGF0YSA9IGJhbmppciwgbW9kZWwgPSAicG9vbGluZyIpDQpzdW1tYXJ5KGNlbSkNCg0KIyA2LiBGaXhlZC1FZmZlY3QgTW9kZWwgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgTW9kZWwgRkVNIEluZGl2aWR1YWwNCmZlbV9pbmQgPC0gcGxtKFkgfiBYMSArIFgyICsgWDMgKyBYNCArIFg1LCBpbmRleCA9IGMoIlBST1YiLCAiVEFIVU4iKSwNCiAgICAgICAgICAgICAgIG1vZGVsID0gIndpdGhpbiIsIGVmZmVjdD0gImluZGl2aWR1YWwiLCBkYXRhID0gYmFuamlyKQ0Kc3VtbWFyeShmZW1faW5kKQ0Kc3VtbWFyeShmaXhlZihmZW1faW5kLCBlZmZlY3Q9ImluZGl2aWR1YWwiKSkNCiMgTW9kZWwgRkVNIEluZGl2aWR1YWwNCmZlbV90aW1lIDwtIHBsbShZIH4gWDEgKyBYMiArIFgzICsgWDQgKyBYNSwgaW5kZXggPSBjKCJQUk9WIiwgIlRBSFVOIiksDQogICAgICAgICAgICAgICBtb2RlbCA9ICJ3aXRoaW4iLCBlZmZlY3Q9ICJ0aW1lIiwgZGF0YSA9IGJhbmppcikNCnN1bW1hcnkoZmVtX3RpbWUpDQpzdW1tYXJ5KGZpeGVmKGZlbV90aW1lLCBlZmZlY3Q9InRpbWUiKSkNCiMgTW9kZWwgRkVNIEluZGl2aWR1YWwNCmZlbV90d293YXlzICA8LSBwbG0oWSB+IFgxICsgWDIgKyBYMyArIFg0ICsgWDUsIGluZGV4ID0gYygiUFJPViIsICJUQUhVTiIpLA0KICAgICAgICAgICAgICAgbW9kZWwgPSAid2l0aGluIiwgZWZmZWN0PSAidHdvd2F5cyIsIGRhdGEgPSBiYW5qaXIpDQpzdW1tYXJ5KGZlbV90d293YXlzICkNCnN1bW1hcnkoZml4ZWYoZmVtX3R3b3dheXMgLCBlZmZlY3Q9InR3b3dheXMiKSkNCmBgYA0KDQojIDYuIEV2YWx1YXNpIE1vZGVsIEZFTQ0KDQpNZWxha3VrYW4gdWppIHNwZXNpZmlrYXNpIHVudHVrIG1lbmVudHVrYW4gZWZlayB5YW5nIHNpZ25pZmlrYW4gcGFkYSBGRU0gc2VydGEgbWVtYmFuZGluZ2thbiBwZXJmb3JtYSBtb2RlbCBiZXJkYXNhcmthbiBrcml0ZXJpYSBrZWJhaWthbiBtb2RlbCAoU1NFLCBBSUMsIE1BUEUsIFItU3F1YXJlZCkuDQoNCmBgYHtyfQ0KIyA3LiBVamkgU2lnbmlmaWthc2kgUGVuZ2FydWggRkVNID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgVWppIHBlbmdhcnVoIGluZGl2aWR1DQpwbG10ZXN0KGZlbV90d293YXlzLCB0eXBlID0gImJwIiwgZWZmZWN0ID0gImluZGl2aWR1YWwiKQ0KcGxtdGVzdChmZW1fdHdvd2F5cywgdHlwZSA9ICJicCIsIGVmZmVjdCA9ICJ0aW1lIikNCnBsbXRlc3QoZmVtX3R3b3dheXMsIHR5cGUgPSAiYnAiLCBlZmZlY3QgPSAidHdvd2F5cyIpDQojIE5pbGFpIEtlYmFpa2FuIE1vZGVsDQojIFN1bSBTcXVhcmVkIEVycm9yDQpkc3NlIDwtIGRhdGEuZnJhbWUoSW5kaXZpZHU9c3VtKGZlbV9pbmQkcmVzaWR1YWxzXjIpLA0KICAgICAgICAgICAgICAgICAgIFRpbWU9c3VtKGZlbV90aW1lJHJlc2lkdWFsc14yKSwNCiAgICAgICAgICAgICAgICAgICBUd293YXlzPXN1bShmZW1fdHdvd2F5cyRyZXNpZHVhbHNeMikpDQojIEFJQw0KbHNkdl9pbmQgPC0gbG0oWSB+IFgxICsgWDIgKyBYMyArIFg0ICsgWDUgKyBQUk9WLCBiYW5qaXIpDQpsc2R2X3RpbWUgPC0gbG0oWSB+IFgxICsgWDIgKyBYMyArIFg0ICsgWDUgKyBUQUhVTiwgYmFuamlyKQ0KbHNkdl90d293YXlzIDwtIGxtKFkgfiBYMSArIFgyICsgWDMgKyBYNCArIFg1ICsgUFJPViArIFRBSFVOLCBiYW5qaXIpDQpkYWljIDwtIGRhdGEuZnJhbWUoSW5kaXZpZHU9QUlDKGxzZHZfaW5kKSxUaW1lPUFJQyhsc2R2X3RpbWUpLA0KICAgICAgICAgICAgICAgICAgIFR3b3dheXM9QUlDKGxzZHZfdHdvd2F5cykpDQojIE1BUEUNCm1hcGUgPC0gZnVuY3Rpb24oYWN0dWFsLCBmb3JlY2FzdCkgew0KICBtZWFuKGFicygoYWN0dWFsIC0gZm9yZWNhc3QpIC8gYWN0dWFsKSkgKiAxMDANCn0NCmRtYXBlIDwtIGRhdGEuZnJhbWUoSW5kaXZpZHU9bWFwZShiYW5qaXIkWSxwcmVkaWN0KGZlbV9pbmQpKSwNCiAgICAgICAgICAgICAgICAgICAgVGltZT1tYXBlKGJhbmppciRZLHByZWRpY3QoZmVtX3RpbWUpKSwNCiAgICAgICAgICAgICAgICAgICAgVHdvd2F5cz1tYXBlKGJhbmppciRZLHByZWRpY3QoZmVtX3R3b3dheXMpKSkNCiMgQklDDQpkYmljIDwtIGRhdGEuZnJhbWUoSW5kaXZpZHU9QklDKGxzZHZfaW5kKSxUaW1lPUJJQyhsc2R2X3RpbWUpLA0KICAgICAgICAgICAgICAgICAgIFR3b3dheXM9QklDKGxzZHZfdHdvd2F5cykpDQojIFItc3F1YXJlZA0KaW5kIDwtIHN1bW1hcnkoZmVtX2luZCkNCnRpbWUgPC0gc3VtbWFyeShmZW1fdGltZSkNCnR3YXlzIDwtIHN1bW1hcnkoZmVtX3R3b3dheXMpDQpkcnNxIDwtIGRhdGEuZnJhbWUoSW5kaXZpZHU9aW5kJHIuc3F1YXJlZCxUaW1lPXRpbWUkci5zcXVhcmVkLA0KICAgICAgICAgICAgICAgICAgIFR3b3dheXM9dHdheXMkci5zcXVhcmVkKQ0KIyBQZXJiYW5kaW5nYW4NCmNvbXBhcmUgPC0gdChyYmluZChkc3NlLGRhaWMsZGJpYyxkbWFwZSxkcnNxKSkNCmNvbG5hbWVzKGNvbXBhcmUpIDwtIGMoIlNTRSIsIkFJQyIsIkJJQyIsICJNQVBFIiwiUi1TcXVhcmVkIiwiQWRqIFItU3F1YXJlZCIpDQpjb21wYXJlDQojIEZFTSB2cyBDRU0gDQpwb29sdGVzdChjZW0sIGZlbV9pbmQpDQpgYGANCg0KIyA3LiBSYW5kb20gRWZmZWN0IE1vZGVsIChSRU0pDQoNCkVzdGltYXNpIG1vZGVsIG1lbmdndW5ha2FuIHBlbmRla2F0YW4gKlJhbmRvbSBFZmZlY3QqIGRhbiBtZWxha3VrYW4gdWppIExhZ3JhbmdlIE11bHRpcGxpZXIgc2VydGEgdWppIEhhdXNtYW4gdW50dWsgbWVtYmFuZGluZ2thbiBGRU0gZGFuIFJFTS4NCg0KYGBge3J9DQojIDguIFJhbmRvbS1FZmZlY3QgTW9kZWwgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBQZW5kdWdhYW4gUGFyYW1ldGVyDQpyZW1fZ2xzIDwtIHBsbShZIH4gWDEgKyBYMiArIFgzICsgWDQgKyBYNSwgZGF0YSA9IGJhbmppciwgDQogICAgICAgICAgICAgICBpbmRleCA9IGMoIlBST1YiLCAiVEFIVU4iKSwgDQogICAgICAgICAgICAgICBlZmZlY3QgPSAiaW5kaXZpZHVhbCIsIG1vZGVsID0gInJhbmRvbSIsDQogICAgICAgICAgICAgICByYW5kb20ubWV0aG9kID0gIm5lcmxvdmUiKQ0Kc3VtbWFyeShyZW1fZ2xzKQ0KIyBQZXJiYW5kaW5nYW4gS2ViYWlrYW4gUkVNDQojIEVmZWsgaW5kaXZpZHUNCnBsbXRlc3QocmVtX2dscyx0eXBlID0gImJwIiwgZWZmZWN0PSJpbmRpdmlkdSIpDQojIEVmZWsgdGltZQ0KcGxtdGVzdChyZW1fZ2xzLHR5cGUgPSAiYnAiLCBlZmZlY3Q9InRpbWUiKQ0KIyBFZmVrIHR3b3dheXMNCnBsbXRlc3QocmVtX2dscyx0eXBlID0gImJwIiwgZWZmZWN0PSJ0d293YXlzIikNCiMgRkVNIHZzIFJFTQ0KI2ZlbSBkZW5nYW4gcmVtIGdscw0KcGh0ZXN0KGZlbV9pbmQsIHJlbV9nbHMpDQpgYGANCg0KIyA4LiBQZW1pbGloYW4gTW9kZWwgVGVyYmFpaw0KDQpFc3RpbWFzaSBtb2RlbCBtZW5nZ3VuYWthbiBwZW5kZWthdGFuICpSYW5kb20gRWZmZWN0KiBkYW4gbWVsYWt1a2FuIHVqaSBMYWdyYW5nZSBNdWx0aXBsaWVyIHNlcnRhIHVqaSBIYXVzbWFuIHVudHVrIG1lbWJhbmRpbmdrYW4gRkVNIGRhbiBSRU0uDQoNCmBgYHtyfQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIFVKSSBQRU1JTElIQU4gTU9ERUwgKENIT1csIEhBVVNNQU4sIExNKSAmIFRBQkVMIFJFS0FQSVRVTEFTSQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgQS4gVWppIENob3cgKExpa2VsaWhvb2QgUmF0aW8gVGVzdCk6IE1lbWJhbmRpbmdrYW4gQ0VNIHZzIEZFTQ0KIyBIMDogTW9kZWwgQ0VNIGxlYmloIGJhaWsNCiMgSDE6IE1vZGVsIEZFTSBsZWJpaCBiYWlrDQpjaG93X3Rlc3QgPC0gcG9vbHRlc3QoY2VtLCBmZW1faW5kKQ0KDQojIEIuIFVqaSBIYXVzbWFuOiBNZW1iYW5kaW5na2FuIEZFTSB2cyBSRU0NCiMgSDA6IE1vZGVsIFJFTSBsZWJpaCBiYWlrIChLb25zaXN0ZW4gJiBFZmlzaWVuKQ0KIyBIMTogTW9kZWwgRkVNIGxlYmloIGJhaWsgKEtvbnNpc3RlbikNCmhhdXNtYW5fdGVzdCA8LSBwaHRlc3QoZmVtX2luZCwgcmVtX2dscykNCg0KIyBDLiBVamkgTE0gKExhZ3JhbmdlIE11bHRpcGxpZXIgLSBCcmV1c2NoLVBhZ2FuKTogTWVtYmFuZGluZ2thbiBDRU0gdnMgUkVNDQojIEgwOiBWYXJpYW5zaSBlcnJvciBpbmRpdmlkdWFsID0gMCAoTW9kZWwgQ0VNIGxlYmloIGJhaWspDQojIEgxOiBWYXJpYW5zaSBlcnJvciBpbmRpdmlkdWFsICE9IDAgKE1vZGVsIFJFTSBsZWJpaCBiYWlrKQ0KbG1fdGVzdCA8LSBwbG10ZXN0KGNlbSwgdHlwZSA9ICJicCIsIGVmZmVjdCA9ICJpbmRpdmlkdWFsIikNCg0KIyAtLS0gRlVOR1NJIFVOVFVLIE1FTkVOVFVLQU4gS0VTSU1QVUxBTiBPVE9NQVRJUyAtLS0NCmdldF9jb25jbHVzaW9uIDwtIGZ1bmN0aW9uKHBfdmFsLCB0ZXN0X3R5cGUpIHsNCiAgYWxwaGEgPC0gMC4wNQ0KICBpZiAodGVzdF90eXBlID09ICJDaG93Iikgew0KICAgIHJldHVybihpZmVsc2UocF92YWwgPCBhbHBoYSwgIk1vZGVsIEZFTSBsZWJpaCBiYWlrIiwgIk1vZGVsIENFTSBsZWJpaCBiYWlrIikpDQogIH0gZWxzZSBpZiAodGVzdF90eXBlID09ICJIYXVzbWFuIikgew0KICAgIHJldHVybihpZmVsc2UocF92YWwgPCBhbHBoYSwgIk1vZGVsIEZFTSBsZWJpaCBiYWlrIiwgIk1vZGVsIFJFTSBsZWJpaCBiYWlrIikpDQogIH0gZWxzZSBpZiAodGVzdF90eXBlID09ICJMTSIpIHsNCiAgICByZXR1cm4oaWZlbHNlKHBfdmFsIDwgYWxwaGEsICJNb2RlbCBSRU0gbGViaWggYmFpayIsICJNb2RlbCBDRU0gbGViaWggYmFpayIpKQ0KICB9DQp9DQoNCiMgLS0tIE1FTUJVQVQgREFUQSBGUkFNRSBIQVNJTCAtLS0NCmhhc2lsX3VqaSA8LSBkYXRhLmZyYW1lKA0KICBVamkgPSBjKCJDaG93IChGLVRlc3QpIiwgIkhhdXNtYW4iLCAiTGFncmFuZ2UgTXVsdGlwbGllciAoTE0pIiksDQogIA0KICBTdGF0aXN0aWsgPSBjKA0KICAgIGFzLm51bWVyaWMoY2hvd190ZXN0JHN0YXRpc3RpYyksIA0KICAgIGFzLm51bWVyaWMoaGF1c21hbl90ZXN0JHN0YXRpc3RpYyksIA0KICAgIGFzLm51bWVyaWMobG1fdGVzdCRzdGF0aXN0aWMpDQogICksDQogIA0KICBQX1ZhbHVlID0gYygNCiAgICBhcy5udW1lcmljKGNob3dfdGVzdCRwLnZhbHVlKSwgDQogICAgYXMubnVtZXJpYyhoYXVzbWFuX3Rlc3QkcC52YWx1ZSksIA0KICAgIGFzLm51bWVyaWMobG1fdGVzdCRwLnZhbHVlKQ0KICApLA0KICANCiAgS2VzaW1wdWxhbiA9IGMoDQogICAgZ2V0X2NvbmNsdXNpb24oYXMubnVtZXJpYyhjaG93X3Rlc3QkcC52YWx1ZSksICJDaG93IiksDQogICAgZ2V0X2NvbmNsdXNpb24oYXMubnVtZXJpYyhoYXVzbWFuX3Rlc3QkcC52YWx1ZSksICJIYXVzbWFuIiksDQogICAgZ2V0X2NvbmNsdXNpb24oYXMubnVtZXJpYyhsbV90ZXN0JHAudmFsdWUpLCAiTE0iKQ0KICApDQopDQoNCiMgLS0tIEZPUk1BVFRJTkcgVEFNUElMQU4gQUdBUiBSQVBJIChPUFNJT05BTCkgLS0tDQpoYXNpbF91amkkU3RhdGlzdGlrIDwtIHJvdW5kKGhhc2lsX3VqaSRTdGF0aXN0aWssIDQpDQojIE1lbmd1YmFoIFAtdmFsdWUgeWFuZyBzYW5nYXQga2VjaWwgbWVuamFkaSBub3Rhc2kgaWxtaWFoIGF0YXUgPCAwLjA1DQpoYXNpbF91amkkUF9WYWx1ZV9TdHIgPC0gaWZlbHNlKGhhc2lsX3VqaSRQX1ZhbHVlIDwgMC4wMDAxLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0KGhhc2lsX3VqaSRQX1ZhbHVlLCBzY2llbnRpZmljID0gVFJVRSwgZGlnaXRzID0gMyksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3VuZChoYXNpbF91amkkUF9WYWx1ZSwgNCkpDQoNCiMgTWVuYW1waWxrYW4gVGFiZWwgQWtoaXIgKEJlcnNpaCkNCmxpYnJhcnkoa25pdHIpICMgR3VuYWthbiBsaWJyYXJ5IGluaSBqaWthIGluZ2luIHRhbXBpbGFuIHRhYmVsIGNhbnRpayBkaSBjb25zb2xlDQp0YWJlbF9maW5hbCA8LSBoYXNpbF91amlbLCBjKCJVamkiLCAiU3RhdGlzdGlrIiwgIlBfVmFsdWVfU3RyIiwgIktlc2ltcHVsYW4iKV0NCmNvbG5hbWVzKHRhYmVsX2ZpbmFsKVszXSA8LSAiUC12YWx1ZSIgIyBVYmFoIG5hbWEga29sb20gYmlhciBzZXN1YWkgY29udG9oDQoNCnByaW50KCI9PT0gVEFCRUwgUklOR0tBU0FOIFBFTUlMSUhBTiBNT0RFTCBQQU5FTCA9PT0iKQ0Ka2FibGUodGFiZWxfZmluYWwsIGFsaWduID0gImMiKQ0KYGBgDQoNCiMgOS4gVWppIERpYWdub3N0aWsgQXN1bXNpICYgU3Bhc2lhbA0KDQpQZW1lcmlrc2FhbiBhc3Vtc2kga2xhc2lrIChOb3JtYWxpdGFzLCBIZXRlcm9za2VkYXN0aXNpdGFzLCBBdXRva29yZWxhc2kpIHNlcnRhIHBlbmd1amlhbiBkZXBlbmRlbnNpIHNwYXNpYWwgKCpDcm9zcy1zZWN0aW9uYWwgRGVwZW5kZW5jZSopIHVudHVrIG1lbGVnaXRpbWFzaSBwZW5nZ3VuYWFuIG1vZGVsIHNwYXNpYWwuDQoNCmBgYHtyIHdhcm5pbmc9Rn0NCiMgOS4gVUppIERpYWdub3N0aWsgU2lzYWFuID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpzdW1fcmVtIDwtIHN1bW1hcnkocmVtX2dscykNCiMgTWVuZ2hpdHVuZyBWSUYNCnZpZl92YWx1ZXMgPC0gdHJ5Q2F0Y2godmlmKHJlbV9nbHMpLCBlcnJvciA9IGZ1bmN0aW9uKGUpIE5VTEwpDQppZiAoIWlzLm51bGwodmlmX3ZhbHVlcykpIHsNCiAgaWYgKGxlbmd0aChjb2VmKHJlbV9nbHMpKSA+IGxlbmd0aCh2aWZfdmFsdWVzKSkgew0KICAgIHZpZl92ZWMgPC0gYyhOQSwgdmlmX3ZhbHVlcykgDQogIH0gZWxzZSB7DQogICAgdmlmX3ZlYyA8LSB2aWZfdmFsdWVzDQogIH0NCn0gZWxzZSB7DQogIHZpZl92ZWMgPC0gcmVwKE5BLCBsZW5ndGgoY29lZihyZW1fZ2xzKSkpDQp9DQojIC0tLSAyLiBNZW1idWF0IFRhYmVsIEVzdGltYXNpIChLb2VmaXNpZW4gJiBWSUYpIC0tLQ0KdGFiZWxfZXN0aW1hc2kgPC0gZGF0YS5mcmFtZSgNCiAgVmFyaWFiZWwgPSByb3duYW1lcyhzdW1fcmVtJGNvZWZmaWNpZW50cyksDQogIEtvZWZpc2llbiA9IHJvdW5kKHN1bV9yZW0kY29lZmZpY2llbnRzWywxXSwgNCksDQogIFN0ZF9FcnJvciA9IHJvdW5kKHN1bV9yZW0kY29lZmZpY2llbnRzWywyXSwgNCksDQogIFBfVmFsdWUgPSByb3VuZChzdW1fcmVtJGNvZWZmaWNpZW50c1ssNF0sIDQpLA0KICBWSUYgPSByb3VuZCh2aWZfdmVjLCAyKQ0KKQ0KdGFiZWxfZXN0aW1hc2kkU2lnbmlmaWthbnNpIDwtIGlmZWxzZSh0YWJlbF9lc3RpbWFzaSRQX1ZhbHVlIDwgMC4wNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNpZ25pZmlrYW4gKDUlKSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFiZWxfZXN0aW1hc2kkUF9WYWx1ZSA8IDAuMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNpZ25pZmlrYW4gKDEwJSkiLCAiVGlkYWsgU2lnbmlmaWthbiIpKQ0KDQp0YWJlbF9lc3RpbWFzaSRTdGF0dXNfVklGIDwtIGlmZWxzZShpcy5uYSh0YWJlbF9lc3RpbWFzaSRWSUYpLCAiLSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhYmVsX2VzdGltYXNpJFZJRiA8IDEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFtYW4iLCAiTXVsdGlrb2xpbmVhcml0YXMiKSkNCiMgLS0tIDMuIE1lbGFrdWthbiBVamkgRGlhZ25vc3RpayAmIE1lbWJ1YXQgVGFiZWwgLS0tDQojIEEuIFVqaSBOb3JtYWxpdGFzIChLb2xtb2dvcm92LVNtaXJub3YpDQp1amlfbm9ybSA8LSBrcy50ZXN0KHJlc2lkdWFscyhyZW1fZ2xzKSwgInBub3JtIiwgDQogICAgICAgICAgICAgICAgICAgIG1lYW49bWVhbihyZXNpZHVhbHMocmVtX2dscykpLCANCiAgICAgICAgICAgICAgICAgICAgc2Q9c2QocmVzaWR1YWxzKHJlbV9nbHMpKSkNCiMgQi4gVWppIEhldGVyb3NrZWRhc3Rpc2l0YXMgKEJyZXVzY2gtUGFnYW4pDQp1amlfaGV0ZXJvIDwtIGJwdGVzdChyZW1fZ2xzLCBzdHVkZW50aXplID0gVFJVRSkNCiMgQy4gVWppIEF1dG9rb3JlbGFzaSBTZXJpYWwgKFdha3R1IC0gQnJldXNjaC1Hb2RmcmV5KQ0KdWppX2F1dG9fc2VyaWFsIDwtIHBiZ3Rlc3QocmVtX2dscykNCiMgRC4gVUpJIEJBUlU6IFVqaSBEZXBlbmRlbnNpIFNwYXNpYWwgLyBDcm9zcy1zZWN0aW9uYWwgRGVwZW5kZW5jZSAoUGVzYXJhbiBDRCkNCiMgSDA6IFRpZGFrIGFkYSBkZXBlbmRlbnNpIGFudGFyIHdpbGF5YWggKENyb3NzLXNlY3Rpb25hbCBpbmRlcGVuZGVuY2UpDQojIEgxOiBBZGEgZGVwZW5kZW5zaSBhbnRhciB3aWxheWFoIChJbmRpa2FzaSBTcGFzaWFsKS0+UCA8IDAuMDUgQkFHVVMgdW50dWsgR1dQUg0KdWppX3NwYXNpYWwgPC0gcGNkdGVzdChyZW1fZ2xzLCB0ZXN0ID0gImNkIikNCiMgTWVuZ2FtYmlsIFItU3F1YXJlZA0Kcl9zcSA8LSBzdW1fcmVtJHIuc3F1YXJlZFsxXSANCiMgTWVueXVzdW4gVGFiZWwgRGlhZ25vc3Rpaw0KdGFiZWxfZGlhZ25vc3RpayA8LSBkYXRhLmZyYW1lKA0KICBVamlfQXN1bXNpID0gYygiTm9ybWFsaXRhcyAoS1MpIiwgDQogICAgICAgICAgICAgICAgICJIZXRlcm9za2VkYXN0aXNpdGFzIChCUCkiLCANCiAgICAgICAgICAgICAgICAgIkF1dG9rb3JlbGFzaSBTZXJpYWwgKFdha3R1KSIsIA0KICAgICAgICAgICAgICAgICAiRGVwZW5kZW5zaSBTcGFzaWFsIChQZXNhcmFuIENEKSIsICMgQmFyaXMgQmFydQ0KICAgICAgICAgICAgICAgICAiUi1TcXVhcmVkIE92ZXJhbGwiKSwNCiAgTmlsYWlfUCA9IGMocm91bmQodWppX25vcm0kcC52YWx1ZSwgNCksIA0KICAgICAgICAgICAgICByb3VuZCh1amlfaGV0ZXJvJHAudmFsdWUsIDQpLCANCiAgICAgICAgICAgICAgcm91bmQodWppX2F1dG9fc2VyaWFsJHAudmFsdWUsIDQpLCANCiAgICAgICAgICAgICAgcm91bmQodWppX3NwYXNpYWwkcC52YWx1ZSwgNCksICMgTmlsYWkgUCBTcGFzaWFsDQogICAgICAgICAgICAgIE5BKSwNCiAgU3RhdGlzdGlrID0gYyhyb3VuZCh1amlfbm9ybSRzdGF0aXN0aWMsIDQpLCANCiAgICAgICAgICAgICAgICByb3VuZCh1amlfaGV0ZXJvJHN0YXRpc3RpYywgNCksIA0KICAgICAgICAgICAgICAgIHJvdW5kKHVqaV9hdXRvX3NlcmlhbCRzdGF0aXN0aWMsIDQpLCANCiAgICAgICAgICAgICAgICByb3VuZCh1amlfc3Bhc2lhbCRzdGF0aXN0aWMsIDQpLCAjIFN0YXRpc3RpayBTcGFzaWFsDQogICAgICAgICAgICAgICAgcm91bmQocl9zcSwgNCkpLA0KICBLZXB1dHVzYW4gPSBjKGlmZWxzZSh1amlfbm9ybSRwLnZhbHVlID4gMC4wNSwNCiAgICAgICAgICAgICAgICAgICAgICAgIk5vcm1hbCAoVGVycGVudWhpKSIsICJUaWRhayBOb3JtYWwiKSwNCiAgICAgICAgICAgICAgICBpZmVsc2UodWppX2hldGVybyRwLnZhbHVlID4gMC4wNSwNCiAgICAgICAgICAgICAgICAgICAgICAgIkhvbW9za2VkYXN0aXMgKFRlcnBlbnVoaSkiLA0KICAgICAgICAgICAgICAgICAgICAgICAiSGV0ZXJvc2tlZGFzdGlzIChDZWsgU3Bhc2lhbCkiKSwNCiAgICAgICAgICAgICAgICBpZmVsc2UodWppX2F1dG9fc2VyaWFsJHAudmFsdWUgPiAwLjA1LA0KICAgICAgICAgICAgICAgICAgICAgICAiQmViYXMgQXV0b2tvcmVsYXNpIFdha3R1IiwgIkFkYSBBdXRva29yZWxhc2kgV2FrdHUiKSwNCiAgICAgICAgICAgICAgICBpZmVsc2UodWppX3NwYXNpYWwkcC52YWx1ZSA8IDAuMDUsDQogICAgICAgICAgICAgICAgICAgICAgICJBZGEgRWZlayBTcGFzaWFsIChMYW5qdXQgR1dQUikiLA0KICAgICAgICAgICAgICAgICAgICAgICAiVGlkYWsgQWRhIEVmZWsgU3Bhc2lhbCIpLA0KICAgICAgICAgICAgICAgIHBhc3RlMChyb3VuZChyX3NxICogMTAwLCAyKSwgIiUiKSkNCikNCiMgLS0tIDQuIENldGFrIE91dHB1dCBkZW5nYW4gS2FibGUgLS0tDQpjYXQoIlxuPT09IFJJTkdLQVNBTiBFU1RJTUFTSSBSQU5ET00gRUZGRUNUIE1PREVMIChSRU0pID09PVxuIikNCnByaW50KGthYmxlKHRhYmVsX2VzdGltYXNpLCByb3cubmFtZXM9RkFMU0UsIGFsaWduPSJjIiwNCiAgICAgICAgICAgIGNhcHRpb24gPSAiS29lZmlzaWVuIGRhbiBVamkgTXVsdGlrb2xpbmVhcml0YXMiKSkNCmNhdCgiXG49PT0gRElBR05PU1RJSyBBU1VNU0kgS0xBU0lLICYgU1BBU0lBTCA9PT1cbiIpDQpwcmludChrYWJsZSh0YWJlbF9kaWFnbm9zdGlrLCByb3cubmFtZXM9RkFMU0UsIGFsaWduPSJsIiwNCiAgICAgICAgICAgIGNhcHRpb24gPSAiSGFzaWwgVWppIERpYWdub3N0aWsiKSkNCiMgSGlzdG9ncmFtIA0KZ2dwbG90KGFzLmRhdGEuZnJhbWUocmVtX2dscyRyZXNpZHVhbHMpLCBhZXMoeCA9IHJlbV9nbHMkcmVzaWR1YWxzKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IGFmdGVyX3N0YXQoZGVuc2l0eSkpLCBjb2xvciA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICAgIGZpbGwgPSAic3RlZWxibHVlIikgKw0KICBnZW9tX2RlbnNpdHkoY29sb3IgPSAicmVkIiwgbGluZXdpZHRoID0gMSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQojIDEwLiBQZW1vZGVsYW4gR1dQUg0KDQpNZW11YXQgZGF0YSBrb29yZGluYXQgd2lsYXlhaCwgbWVuZW50dWthbiAqYmFuZHdpZHRoKiBvcHRpbWFsIChBZGFwdGl2ZS9GaXhlZCkgZGVuZ2FuIGJlcmJhZ2FpIGZ1bmdzaSBrZXJuZWwgKEJpc3F1YXJlLCBHYXVzc2lhbiwgRXhwb25lbnRpYWwpLCBkYW4gbWVtYmFuZ3VuIG1vZGVsIEdXUFIuDQoNCmBgYHtyIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQ0KIyAxMCBHZW9ncmFwaGljYWxseSBXZWlnaHRlZCBQYW5lbCBSZWdyZXNzaW9uID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgSW5wdXQgTGF0aXR1ZGUgTG9uZ2l0dWRlDQp3aWxheWFoIDwtIGZyb21KU09OKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20veXVzdWZzeWFpZnVkaW4vd2lsYXlhaC1pbmRvbmVzaWEvbWFzdGVyL2RhdGEvbGlzdF9vZl9hcmVhL3Byb3ZpbmNlcy5qc29uIikNCndpbGF5YWgkbmFtZSA8LSB0b3VwcGVyKHdpbGF5YWgkbmFtZSkNCmRhdGEuc3AuR1dQUiA8LSBiYW5qaXIgJT4lDQogIGxlZnRfam9pbih3aWxheWFoICU+JSBzZWxlY3QobmFtZSwgbGF0aXR1ZGUsIGxvbmdpdHVkZSksDQogICAgICAgICAgICBieSA9IGMoIlBST1YiID0gIm5hbWUiKSkgJT4lDQogIHJlbmFtZShMQVQgPSBsYXRpdHVkZSwgTE9ORyA9IGxvbmdpdHVkZSkgJT4lDQogIHNlbGVjdChQUk9WLCBUQUhVTiwgTEFULCBMT05HLCBldmVyeXRoaW5nKCkpDQojIE1vZGVsaW5nIEdXUFINCmNvb3JkaW5hdGVzKGRhdGEuc3AuR1dQUik9Mzo0DQpjbGFzcyhkYXRhLnNwLkdXUFIpDQojIE1lbmVudHVrYW4gRnVuZ3NpIFBlbWJvYm90IFNwYXNpYWwgVGVyYmFpaw0KIyBGdW5nc2kga2VybmVsOiAoKGdhdXNzaWFuLCBla3Nwb25lbnNpYWwsIGJpc3F1YXJlLCBUcmljdWJlKSAoYWRhcHRpdmUgZGFuIGZpeGVkKSkNCiMgLS0tIEtFTE9NUE9LIEFEQVBUSVZFIC0tLQ0KIyAxLiBBZGFwdGl2ZSBCaXNxdWFyZQ0KYndkLkdXUFIuYmlzcXVhcmUuYWQgPC0gYncuZ3dyKFkgfiBYMSArIFgyICsgWDMgKyBYNCArIFg1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLnNwLkdXUFIsIGFwcHJvYWNoID0gIkNWIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXJuZWwgPSAiYmlzcXVhcmUiLCBhZGFwdGl2ZT1UKQ0KaGFzaWwuR1dQUi5iaXNxdWFyZS5hZCA8LSBnd3IuYmFzaWMoWSB+IFgxICsgWDIgKyBYMyArIFg0ICsgWDUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5zcC5HV1BSLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYncgPSBid2QuR1dQUi5iaXNxdWFyZS5hZCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlcm5lbCA9ICJiaXNxdWFyZSIsIGFkYXB0aXZlPVQpDQojIDIuIEFkYXB0aXZlIEdhdXNzaWFuDQpid2QuR1dQUi5nYXVzc2lhbi5hZCA8LSBidy5nd3IoWSB+IFgxICsgWDIgKyBYMyArIFg0ICsgWDUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEuc3AuR1dQUiwgYXBwcm9hY2ggPSAiQ1YiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlcm5lbCA9ICJnYXVzc2lhbiIsIGFkYXB0aXZlPVQpDQpoYXNpbC5HV1BSLmdhdXNzaWFuLmFkIDwtIGd3ci5iYXNpYyhZIH4gWDEgKyBYMiArIFgzICsgWDQgKyBYNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLnNwLkdXUFIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidyA9IGJ3ZC5HV1BSLmdhdXNzaWFuLmFkLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VybmVsID0gImdhdXNzaWFuIiwgYWRhcHRpdmU9VCkNCiMgMy4gQWRhcHRpdmUgRXhwb25lbnRpYWwNCmJ3ZC5HV1BSLmV4cG9uZW50aWFsLmFkIDwtIGJ3Lmd3cihZIH4gWDEgKyBYMiArIFgzICsgWDQgKyBYNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5zcC5HV1BSLCBhcHByb2FjaCA9ICJDViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VybmVsID0gImV4cG9uZW50aWFsIiwgYWRhcHRpdmU9VCkNCmhhc2lsLkdXUFIuZXhwb25lbnRpYWwuYWQgPC0gZ3dyLmJhc2ljKFkgfiBYMSArIFgyICsgWDMgKyBYNCArIFg1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEuc3AuR1dQUiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ3ID0gYndkLkdXUFIuZXhwb25lbnRpYWwuYWQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXJuZWwgPSAiZXhwb25lbnRpYWwiLCBhZGFwdGl2ZT1UKQ0KIyA0LiBBZGFwdGl2ZSBUcmljdWJlIChCQVJVKQ0KYndkLkdXUFIudHJpY3ViZS5hZCA8LSBidy5nd3IoWSB+IFgxICsgWDIgKyBYMyArIFg0ICsgWDUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5zcC5HV1BSLCBhcHByb2FjaCA9ICJDViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXJuZWwgPSAidHJpY3ViZSIsIGFkYXB0aXZlPVQpDQpoYXNpbC5HV1BSLnRyaWN1YmUuYWQgPC0gZ3dyLmJhc2ljKFkgfiBYMSArIFgyICsgWDMgKyBYNCArIFg1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5zcC5HV1BSLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidyA9IGJ3ZC5HV1BSLnRyaWN1YmUuYWQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlcm5lbCA9ICJ0cmljdWJlIiwgYWRhcHRpdmU9VCkNCiMgLS0tIEtFTE9NUE9LIEZJWEVEIC0tLQ0KIyA1LiAgQmlzcXVhcmUNCmJ3ZC5HV1BSLmJpc3F1YXJlLmZpeCA8LSBidy5nd3IoWSB+IFgxICsgWDIgKyBYMyArIFg0ICsgWDUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLnNwLkdXUFIsIGFwcHJvYWNoID0gIkNWIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VybmVsID0gImJpc3F1YXJlIiwgYWRhcHRpdmU9RikNCmhhc2lsLkdXUFIuYmlzcXVhcmUuZml4IDwtIGd3ci5iYXNpYyhZIH4gWDEgKyBYMiArIFgzICsgWDQgKyBYNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5zcC5HV1BSLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ3ID0gYndkLkdXUFIuYmlzcXVhcmUuZml4LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlcm5lbCA9ICJiaXNxdWFyZSIsIGFkYXB0aXZlPUYpDQojIDYuIEZpeGVkIEdhdXNzaWFuDQpid2QuR1dQUi5nYXVzc2lhbi5maXggPC0gYncuZ3dyKFkgfiBYMSArIFgyICsgWDMgKyBYNCArIFg1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5zcC5HV1BSLCBhcHByb2FjaCA9ICJDViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlcm5lbCA9ICJnYXVzc2lhbiIsIGFkYXB0aXZlPUYpDQpoYXNpbC5HV1BSLmdhdXNzaWFuLmZpeCA8LSBnd3IuYmFzaWMoWSB+IFgxICsgWDIgKyBYMyArIFg0ICsgWDUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEuc3AuR1dQUiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidyA9IGJ3ZC5HV1BSLmdhdXNzaWFuLmZpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXJuZWwgPSAiZ2F1c3NpYW4iLCBhZGFwdGl2ZT1GKQ0KIyA3LiBGaXhlZCBFeHBvbmVudGlhbA0KYndkLkdXUFIuZXhwb25lbnRpYWwuZml4IDwtIGJ3Lmd3cihZIH4gWDEgKyBYMiArIFgzICsgWDQgKyBYNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEuc3AuR1dQUiwgYXBwcm9hY2ggPSAiQ1YiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXJuZWwgPSAiZXhwb25lbnRpYWwiLCBhZGFwdGl2ZT1GKQ0KaGFzaWwuR1dQUi5leHBvbmVudGlhbC5maXggPC0gZ3dyLmJhc2ljKFkgfiBYMSArIFgyICsgWDMgKyBYNCArIFg1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLnNwLkdXUFIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYncgPSBid2QuR1dQUi5leHBvbmVudGlhbC5maXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VybmVsID0gImV4cG9uZW50aWFsIiwgYWRhcHRpdmU9RikNCiMgOC4gRml4ZWQgVHJpY3ViZSAoQkFSVSkNCmJ3ZC5HV1BSLnRyaWN1YmUuZml4IDwtIGJ3Lmd3cihZIH4gWDEgKyBYMiArIFgzICsgWDQgKyBYNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5zcC5HV1BSLCBhcHByb2FjaCA9ICJDViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VybmVsID0gInRyaWN1YmUiLCBhZGFwdGl2ZT1GKQ0KaGFzaWwuR1dQUi50cmljdWJlLmZpeCA8LSBnd3IuYmFzaWMoWSB+IFgxICsgWDIgKyBYMyArIFg0ICsgWDUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5zcC5HV1BSLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYncgPSBid2QuR1dQUi50cmljdWJlLmZpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlcm5lbCA9ICJ0cmljdWJlIiwgYWRhcHRpdmU9RikNCmBgYA0KDQojIDExLiBQZW1pbGloYW4gTW9kZWwgVGVyYmFpayAmIFBhcmFtZXRlciBMb2thbA0KDQpNZW1iYW5kaW5na2FuIGtlYmFpa2FuIG1vZGVsIGJlcmRhc2Fya2FuIEFJQy9BSUNjLCBSLVNxdWFyZWQsIGRhbiBSU1MsIHNlcnRhIG1lbmFtcGlsa2FuIHBhcmFtZXRlciBsb2thbCBkYW4gc2lnbmlmaWthbnNpbnlhIHBlciBwcm92aW5zaS4NCg0KYGBge3J9DQpBSUMgPC0gYyhoYXNpbC5HV1BSLmJpc3F1YXJlLmFkJEdXLmRpYWdub3N0aWMkQUlDLA0KICAgICAgICAgaGFzaWwuR1dQUi5nYXVzc2lhbi5hZCRHVy5kaWFnbm9zdGljJEFJQywNCiAgICAgICAgIGhhc2lsLkdXUFIuZXhwb25lbnRpYWwuYWQkR1cuZGlhZ25vc3RpYyRBSUMsDQogICAgICAgICBoYXNpbC5HV1BSLnRyaWN1YmUuYWQkR1cuZGlhZ25vc3RpYyRBSUMsICAgDQogICAgICAgICBoYXNpbC5HV1BSLmJpc3F1YXJlLmZpeCRHVy5kaWFnbm9zdGljJEFJQywNCiAgICAgICAgIGhhc2lsLkdXUFIuZ2F1c3NpYW4uZml4JEdXLmRpYWdub3N0aWMkQUlDLA0KICAgICAgICAgaGFzaWwuR1dQUi5leHBvbmVudGlhbC5maXgkR1cuZGlhZ25vc3RpYyRBSUMsDQogICAgICAgICBoYXNpbC5HV1BSLnRyaWN1YmUuZml4JEdXLmRpYWdub3N0aWMkQUlDKSAgICANCg0KUjIgPC0gYyhoYXNpbC5HV1BSLmJpc3F1YXJlLmFkJEdXLmRpYWdub3N0aWMkZ3cuUjIsDQogICAgICAgIGhhc2lsLkdXUFIuZ2F1c3NpYW4uYWQkR1cuZGlhZ25vc3RpYyRndy5SMiwNCiAgICAgICAgaGFzaWwuR1dQUi5leHBvbmVudGlhbC5hZCRHVy5kaWFnbm9zdGljJGd3LlIyLA0KICAgICAgICBoYXNpbC5HV1BSLnRyaWN1YmUuYWQkR1cuZGlhZ25vc3RpYyRndy5SMiwgICAgDQogICAgICAgIGhhc2lsLkdXUFIuYmlzcXVhcmUuZml4JEdXLmRpYWdub3N0aWMkZ3cuUjIsDQogICAgICAgIGhhc2lsLkdXUFIuZ2F1c3NpYW4uZml4JEdXLmRpYWdub3N0aWMkZ3cuUjIsDQogICAgICAgIGhhc2lsLkdXUFIuZXhwb25lbnRpYWwuZml4JEdXLmRpYWdub3N0aWMkZ3cuUjIsDQogICAgICAgIGhhc2lsLkdXUFIudHJpY3ViZS5maXgkR1cuZGlhZ25vc3RpYyRndy5SMikgICANCg0KQUlDYyA8LSBjKGhhc2lsLkdXUFIuYmlzcXVhcmUuYWQkR1cuZGlhZ25vc3RpYyRBSUNjLA0KICAgICAgICAgIGhhc2lsLkdXUFIuZ2F1c3NpYW4uYWQkR1cuZGlhZ25vc3RpYyRBSUNjLA0KICAgICAgICAgIGhhc2lsLkdXUFIuZXhwb25lbnRpYWwuYWQkR1cuZGlhZ25vc3RpYyRBSUNjLA0KICAgICAgICAgIGhhc2lsLkdXUFIudHJpY3ViZS5hZCRHVy5kaWFnbm9zdGljJEFJQ2MsICAgDQogICAgICAgICAgaGFzaWwuR1dQUi5iaXNxdWFyZS5maXgkR1cuZGlhZ25vc3RpYyRBSUNjLA0KICAgICAgICAgIGhhc2lsLkdXUFIuZ2F1c3NpYW4uZml4JEdXLmRpYWdub3N0aWMkQUlDYywNCiAgICAgICAgICBoYXNpbC5HV1BSLmV4cG9uZW50aWFsLmZpeCRHVy5kaWFnbm9zdGljJEFJQ2MsDQogICAgICAgICAgaGFzaWwuR1dQUi50cmljdWJlLmZpeCRHVy5kaWFnbm9zdGljJEFJQ2MpICANCg0KUjJhZGogPC0gYyhoYXNpbC5HV1BSLmJpc3F1YXJlLmFkJEdXLmRpYWdub3N0aWMkZ3dSMi5hZGosDQogICAgICAgICAgIGhhc2lsLkdXUFIuZ2F1c3NpYW4uYWQkR1cuZGlhZ25vc3RpYyRnd1IyLmFkaiwNCiAgICAgICAgICAgaGFzaWwuR1dQUi5leHBvbmVudGlhbC5hZCRHVy5kaWFnbm9zdGljJGd3UjIuYWRqLA0KICAgICAgICAgICBoYXNpbC5HV1BSLnRyaWN1YmUuYWQkR1cuZGlhZ25vc3RpYyRnd1IyLmFkaiwgIA0KICAgICAgICAgICBoYXNpbC5HV1BSLmJpc3F1YXJlLmZpeCRHVy5kaWFnbm9zdGljJGd3UjIuYWRqLA0KICAgICAgICAgICBoYXNpbC5HV1BSLmdhdXNzaWFuLmZpeCRHVy5kaWFnbm9zdGljJGd3UjIuYWRqLA0KICAgICAgICAgICBoYXNpbC5HV1BSLmV4cG9uZW50aWFsLmZpeCRHVy5kaWFnbm9zdGljJGd3UjIuYWRqLA0KICAgICAgICAgICBoYXNpbC5HV1BSLnRyaWN1YmUuZml4JEdXLmRpYWdub3N0aWMkZ3dSMi5hZGopIA0KDQpSU1MgPC0gYyhoYXNpbC5HV1BSLmJpc3F1YXJlLmFkJEdXLmRpYWdub3N0aWMkUlNTLmd3LA0KICAgICAgICAgaGFzaWwuR1dQUi5nYXVzc2lhbi5hZCRHVy5kaWFnbm9zdGljJFJTUy5ndywNCiAgICAgICAgIGhhc2lsLkdXUFIuZXhwb25lbnRpYWwuYWQkR1cuZGlhZ25vc3RpYyRSU1MuZ3csDQogICAgICAgICBoYXNpbC5HV1BSLnRyaWN1YmUuYWQkR1cuZGlhZ25vc3RpYyRSU1MuZ3csICAgIA0KICAgICAgICAgaGFzaWwuR1dQUi5iaXNxdWFyZS5maXgkR1cuZGlhZ25vc3RpYyRSU1MuZ3csDQogICAgICAgICBoYXNpbC5HV1BSLmdhdXNzaWFuLmZpeCRHVy5kaWFnbm9zdGljJFJTUy5ndywNCiAgICAgICAgIGhhc2lsLkdXUFIuZXhwb25lbnRpYWwuZml4JEdXLmRpYWdub3N0aWMkUlNTLmd3LA0KICAgICAgICAgaGFzaWwuR1dQUi50cmljdWJlLmZpeCRHVy5kaWFnbm9zdGljJFJTUy5ndykgDQoNCnRhYmVsIDwtIGNiaW5kKFJTUyxSMixSMmFkaixBSUMsQUlDYykNCnJvd25hbWVzKHRhYmVsKSA8LSBjKCJBZGFwdGl2ZSBCaXNxdWFyZSIsICJBZGFwdGl2ZSBHYXVzc2lhbiIsDQogICAgICAgICAgICAgICAgICAgICAiQWRhcHRpdmUgRXhwb25lbnRpYWwiLCAiQWRhcHRpdmUgVHJpY3ViZSIsICJGaXhlZCBCaXNxdWFyZSIsDQogICAgICAgICAgICAgICAgICAgICAiRml4ZWQgR2F1c3NpYW4iLCAiRml4ZWQgRXhwb25lbnRpYWwiLCAiRml4ZWQgVHJpY3ViZSIpDQpkYXRhLmZyYW1lKHRhYmVsKQ0KDQojIFBlbmR1Z2FhbiBQYXJhbWV0ZXINCnBhcmFtZXRlci5HV1BSIDwtIGFzLmRhdGEuZnJhbWUoDQogIGhhc2lsLkdXUFIudHJpY3ViZS5maXgkU0RGWzE6MTAsMTo2XSlbLWMoNyw4KV0NCnBhcmFtZXRlci5HV1BSICU+JSANCiAgbXV0YXRlKFBST1Y9YmFuamlyJFBST1ZbMToxMF0pICU+JSANCiAgc2VsZWN0KFBST1YsIGV2ZXJ5dGhpbmcoKSkNCnBhcmFtZXRlcl9SMiA8LSBhcy5kYXRhLmZyYW1lKA0KICBoYXNpbC5HV1BSLnRyaWN1YmUuZml4JFNERlsxOjEwLGMoMTo2LDI0KV0pWy04Oi0xOV0NCiMgUjIgc2V0aWFwIHByb3ZpbnNpDQpwYXJhbWV0ZXJfUjIgJT4lIA0KICBtdXRhdGUoUFJPVj1iYW5qaXIkUFJPVlsxOjEwXSkgJT4lDQogIHNlbGVjdChQUk9WLCBMb2NhbF9SMikgJT4lIA0KICBhcnJhbmdlKC1Mb2NhbF9SMikNCiMgMTEgU2lnbmlmaWthc2kgcGFyYW1ldGVyIChwLXZhbHVlKSA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpwX3ZhbHVlIDwtIGd3ci50LmFkanVzdChoYXNpbC5HV1BSLnRyaWN1YmUuZml4KSRyZXN1bHRzJHANCnBfdmFsdWUgPC0gYXMuZGF0YS5mcmFtZShpZmVsc2UocF92YWx1ZTw9MC4wNSwgIlNpZ25pZmlrYW4iLCAiVGlkYWsiKSlbMToxMCxdDQpwX3ZhbHVlICU+JSANCiAgbXV0YXRlKFBST1Y9YmFuamlyJFBST1ZbMToxMF0pICU+JSANCiAgc2VsZWN0KFBST1YsIGV2ZXJ5dGhpbmcoKSkNCg0KI0ZpbHRlciBQcm92aW5zaSB5YW5nIG1lbXB1bnlhaSBzaWduaWZpa2Fuc2kgcGFkYSBwZXViYWggWDENCnBfdmFsdWUgJT4lIA0KICBtdXRhdGUoUFJPVj1iYW5qaXIkUFJPVlsxOjEwXSkgJT4lIA0KICBzZWxlY3QoUFJPViwgWDFfcCkgJT4lIA0KICBmaWx0ZXIoIlNpZ25pZmlrYW4iID09IHBfdmFsdWUkWDEpDQojRmlsdGVyIFByb3ZpbnNpIHlhbmcgbWVtcHVueWFpIHNpZ25pZmlrYW5zaSBwYWRhIHBldWJhaCBYMg0KcF92YWx1ZSAlPiUgDQogIG11dGF0ZShQUk9WPWJhbmppciRQUk9WWzE6MTBdKSAlPiUgDQogIHNlbGVjdChQUk9WLCBYMl9wKSAlPiUgDQogIGZpbHRlcigiU2lnbmlmaWthbiIgPT0gcF92YWx1ZSRYMikNCiNGaWx0ZXIgUHJvdmluc2kgeWFuZyBtZW1wdW55YWkgc2lnbmlmaWthbnNpIHBhZGEgcGV1YmFoIFgzDQpwX3ZhbHVlICU+JSANCiAgbXV0YXRlKFBST1Y9YmFuamlyJFBST1ZbMToxMF0pICU+JSANCiAgc2VsZWN0KFBST1YsIFgzX3ApICU+JSANCiAgZmlsdGVyKCJTaWduaWZpa2FuIiA9PSBwX3ZhbHVlJFgzKQ0KI0ZpbHRlciBQcm92aW5zaSB5YW5nIG1lbXB1bnlhaSBzaWduaWZpa2Fuc2kgcGFkYSBwZXViYWggWDQNCnBfdmFsdWUgJT4lIA0KICBtdXRhdGUoUFJPVj1iYW5qaXIkUFJPVlsxOjEwXSkgJT4lIA0KICBzZWxlY3QoUFJPViwgWDRfcCkgJT4lIA0KICBmaWx0ZXIoIlNpZ25pZmlrYW4iID09IHBfdmFsdWUkWDQpDQojIEZpbHRlciBQcm92aW5zaSB5YW5nIG1lbXB1bnlhaSBzaWduaWZpa2Fuc2kgcGFkYSBwZXViYWggWDUNCnBfdmFsdWUgJT4lIA0KICBtdXRhdGUoUFJPVj1iYW5qaXIkUFJPVlsxOjEwXSkgJT4lIA0KICBzZWxlY3QoUFJPViwgWDVfcCkgJT4lIA0KICBmaWx0ZXIoIlNpZ25pZmlrYW4iID09IHBfdmFsdWUkWDUpDQoNCiMgTGloYXQga29lZmlzaWVuIHVudHVrIHByb3ZpbnNpIHRlcnRlbnR1IChtaXNhbCBiYXJpcyBrZS0xIGFkYWxhaCBTdW1hdGVyYSBVdGFyYSkNCmhhc2lsLkdXUFIudHJpY3ViZS5maXgkU0RGWzEsXSANCg0KIyBBdGF1IGppa2EgaW5naW4gbWVsaWhhdCBzaWduaWZpa2Fuc2kgKHQtaGl0dW5nKSB1bnR1ayBtZW1iZXJpIHRhbmRhIGJpbnRhbmcgKCopDQpnd3IudC5hZGp1c3QoaGFzaWwuR1dQUi50cmljdWJlLmZpeCkkcmVzdWx0cyR0WzEsXQ0KYGBgDQoNCiMgMTIuIFVqaSBLZXNlc3VhaWFuIE1vZGVsIChHbG9iYWwgdnMgTG9rYWwpDQoNCk1lbGFrdWthbiB1amkgRiB1bnR1ayBtZW1iYW5kaW5na2FuIGFwYWthaCBtb2RlbCBHV1BSIChsb2thbCkgc2VjYXJhIHNpZ25pZmlrYW4gbGViaWggYmFpayBkYXJpcGFkYSBtb2RlbCBnbG9iYWwgKFJFTSkuDQoNCmBgYHtyfQ0KIyAxMi4gIFVqaSBLZXNlc3VhaWFuIE1vZGVsID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgVWppIEYNCnJzc19yZW0gPC0gc3VtKHJlbV9nbHMkcmVzaWR1YWxzXjIpDQpyc3NfZ3dwciA8LSBoYXNpbC5HV1BSLnRyaWN1YmUuZml4JEdXLmRpYWdub3N0aWMkUlNTLmd3DQpkZl9yZW0gPC0gcmVtX2dscyRkZi5yZXNpZHVhbA0KZGZfZ3dwciA8LSBoYXNpbC5HV1BSLnRyaWN1YmUuZml4JEdXLmRpYWdub3N0aWMkZWRmDQpGaGl0PShyc3NfZ3dwci9kZl9nd3ByKS8ocnNzX3JlbS9kZl9yZW0pDQpGaGl0DQpwZihGaGl0LGRmX2d3cHIsZGZfcmVtKQ0KY29tcGFyaXNvbiA8LSBkYXRhLmZyYW1lKFIyPWMoaGFzaWwuR1dQUi50cmljdWJlLmZpeCRHVy5kaWFnbm9zdGljJGd3LlIyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtbWFyeShyZW1fZ2xzKSRyLnNxdWFyZWRbMV0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgIFIyYWRqPWMoaGFzaWwuR1dQUi50cmljdWJlLmZpeCRHVy5kaWFnbm9zdGljJGd3UjIuYWRqLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtbWFyeShyZW1fZ2xzKSRyLnNxdWFyZWRbMl0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgIFJTUz1jKGhhc2lsLkdXUFIudHJpY3ViZS5maXgkR1cuZGlhZ25vc3RpYyRSU1MuZ3csDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtKHN1bW1hcnkocmVtX2dscykkcmVzaWR1YWxzXjIpKSkNCnJvd25hbWVzKGNvbXBhcmlzb24pIDwtIGMoIkdXUFIiLCAiUkVNIFR3byBXYXlzIikNCmNvbXBhcmlzb24NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgVUpJIEFOT1ZBIChVSkkgRikgUEVSQkFORElOR0FOIE1PREVMIEdMT0JBTCBWUyBHV1BSDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQojIDEuIE1hc3Vra2FuIE5pbGFpIFJTUyBkYW4gREYgKEd1bmFrYW4gRGF0YSBkYXJpIFRhYmVsIDYgQW5kYSBhZ2FyIEtvbnNpc3RlbikNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIE5pbGFpIGluaSBkaWFtYmlsIGRhcmkgVGFiZWwgNiB5YW5nIEFuZGEgdHVuanVra2FuIHNlYmVsdW1ueWEgKHlhbmcgUjItbnlhIDc4JSkNClJTU19HbG9iYWwgPC0gc3VtKHN1bW1hcnkocmVtX2dscykkcmVzaWR1YWxzXjIpICAjIFJTUyBkYXJpIFJFTSBUd28gV2F5cw0KUlNTX0dXUFIgICA8LSBoYXNpbC5HV1BSLnRyaWN1YmUuZml4JEdXLmRpYWdub3N0aWMkUlNTLmd3ICAgIyBSU1MgZGFyaSBHV1BSIEJpc3F1YXJlIEZpeGVkDQoNCiMgQW1iaWwgRGVncmVlcyBvZiBGcmVlZG9tIChERikNCiMgR2FudGkgb2JqX2dsb2JhbCBkYW4gb2JqX2d3cHIgZGVuZ2FuIG5hbWEgb2JqZWsgbW9kZWwgYXNsaSBBbmRhDQpERl9HbG9iYWwgIDwtIHJlbV9nbHMkZGYucmVzaWR1YWwgICAgICAgICAgICAgICANCkRGX0dXUFIgICAgPC0gaGFzaWwuR1dQUi50cmljdWJlLmZpeCRHVy5kaWFnbm9zdGljJGVkZiANCg0KIyAyLiBQZXJoaXR1bmdhbiBTdGF0aXN0aWsgRg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgSGl0dW5nIFNlbGlzaWggKEltcHJvdmVtZW50KQ0KU1NfSW1wcm92ZW1lbnQgPC0gUlNTX0dsb2JhbCAtIFJTU19HV1BSICAgICAgICMgU2ViZXJhcGEgYmFueWFrIGVycm9yIGJlcmt1cmFuZw0KREZfSW1wcm92ZW1lbnQgPC0gREZfR2xvYmFsIC0gREZfR1dQUiAgICAgICAgICMgU2VsaXNpaCBkZXJhamF0IGJlYmFzDQoNCiMgSGl0dW5nIE1lYW4gU3F1YXJlIChSYXRhLXJhdGEgS3VhZHJhdCkNCk1TX0ltcHJvdmVtZW50IDwtIFNTX0ltcHJvdmVtZW50IC8gREZfSW1wcm92ZW1lbnQNCk1TX0dXUFIgICAgICAgIDwtIFJTU19HV1BSIC8gREZfR1dQUg0KDQojIEhpdHVuZyBGLVN0YXRpc3Rpaw0KRl9IaXR1bmcgPC0gTVNfSW1wcm92ZW1lbnQgLyBNU19HV1BSDQoNCiMgSGl0dW5nIFAtVmFsdWUNClBfVmFsdWUgIDwtIHBmKEZfSGl0dW5nLCBkZjEgPSBERl9JbXByb3ZlbWVudCwgZGYyID0gREZfR1dQUiwgbG93ZXIudGFpbCA9IEZBTFNFKQ0KDQojIDMuIE1lbnl1c3VuIFRhYmVsIFNlc3VhaSBGb3JtYXQgeWFuZyBBbmRhIEluZ2lua2FuIChGIGRpIEJhd2FoKQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCmFub3ZhX3RhYmxlIDwtIGRhdGEuZnJhbWUoDQogIFN1bWJlcl9WYXJpYXNpID0gYygiR2xvYmFsIFJlc2lkdWFscyAoUkVNKSIsICJHV1BSIEltcHJvdmVtZW50IiwgIkdXUFIgUmVzaWR1YWxzIiksDQogIERGID0gYyhERl9HbG9iYWwsIERGX0ltcHJvdmVtZW50LCBERl9HV1BSKSwNCiAgU1MgPSBjKFJTU19HbG9iYWwsIFNTX0ltcHJvdmVtZW50LCBSU1NfR1dQUiksDQogIE1TID0gYyhOQSwgTVNfSW1wcm92ZW1lbnQsIE1TX0dXUFIpLA0KICBGX1N0YXQgPSBjKE5BLCBOQSwgRl9IaXR1bmcpLA0KICBQX1ZhbHVlID0gYyhOQSwgTkEsIFBfVmFsdWUpDQopDQoNCiMgTWVyYXBpa2FuIEFuZ2thIChQZW1idWxhdGFuKQ0KYW5vdmFfdGFibGUkU1MgPC0gcm91bmQoYW5vdmFfdGFibGUkU1MsIDIpDQphbm92YV90YWJsZSRNUyA8LSByb3VuZChhbm92YV90YWJsZSRNUywgMikNCmFub3ZhX3RhYmxlJEZfU3RhdCA8LSByb3VuZChhbm92YV90YWJsZSRGX1N0YXQsIDQpDQphbm92YV90YWJsZSRQX1ZhbHVlIDwtIGZvcm1hdChhbm92YV90YWJsZSRQX1ZhbHVlLCBzY2llbnRpZmljID0gVFJVRSwgZGlnaXRzID0gNCkNCg0KIyBVYmFoIE5BIG1lbmphZGkga29zb25nIGFnYXIgcmFwaSBzYWF0IGRpcHJpbnQNCmFub3ZhX3RhYmxlW2lzLm5hKGFub3ZhX3RhYmxlKV0gPC0gIk5BIg0KDQojIFRhbXBpbGthbiBIYXNpbA0KcHJpbnQoYW5vdmFfdGFibGUpDQpgYGANCg0KIyAxMy4gVmlzdWFsaXNhc2kgUGV0YSBTaWduaWZpa2Fuc2kNCg0KTWVtYnVhdCBwZXRhIHRlbWF0aWsgeWFuZyBtZW51bmp1a2thbiBrb21iaW5hc2kgdmFyaWFiZWwgeWFuZyBzaWduaWZpa2FuIGJlcnBlbmdhcnVoIHRlcmhhZGFwIGtlamFkaWFuIGJhbmppciBkaSBzZXRpYXAgcHJvdmluc2kuDQoNCmBgYHtyIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD04fQ0KIyBWSVNVQUxJU0FTSSBQRVRBOiBLT01CSU5BU0kgVkFSSUFCRUwgU0lHTklGSUtBTiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgMS4gUGVyc2lhcGFuIERhdGEgU2lnbmlmaWthbnNpIA0KIyBBbWJpbCBoYXNpbCBwLXZhbHVlIHlhbmcgc3VkYWggZGktYWRqdXN0LiBQYXN0aWthbiB1cnV0YW4gZGF0YSBzZXN1YWkuDQojIEthcmVuYSBkYXRhIHBhbmVsLCBraXRhIGFtYmlsIHJlcHJlc2VudGFzaSB1bmlrIHByb3ZpbnNpICgxMCBiYXJpcyBwZXJ0YW1hKQ0KIyBBc3Vtc2k6IDEwIGJhcmlzIHBlcnRhbWEgbWV3YWtpbGkgdXJ1dGFuIHByb3ZpbnNpIGRpIGRhdGEgJ2JhbmppcicNCnJlc190X2FkaiA8LSBnd3IudC5hZGp1c3QoaGFzaWwuR1dQUi50cmljdWJlLmZpeCkgDQpwX3ZhbHNfbWF0cml4IDwtIHJlc190X2FkaiRyZXN1bHRzJHBbMToxMCwgXQ0KIyBCdWF0IERhdGEgRnJhbWUgU2lnbmlmaWthbnNpDQpkZl9zaWdfbWFwIDwtIGRhdGEuZnJhbWUoDQogIFBST1YgPSBiYW5qaXIkUFJPVlsxOjEwXSwgIyBNZW5nYW1iaWwgbmFtYSBwcm92aW5zaQ0KICBwX3ZhbHNfbWF0cml4DQopDQojIFRlbnR1a2FuIG5hbWEgdmFyaWFiZWwgWA0KIyAoc2VzdWFpa2FuIGRlbmdhbiBjb2xuYW1lcyBkYXJpIHBfdmFsc19tYXRyaXggc2VsYWluIEludGVyY2VwdCkNCiMgQmlhc2FueWE6IFgxLjEsIFgyLjEgZHN0IGF0YXUgWDEsIFgyLiBLaXRhIGJlcnNpaGthbiBuYW1hIGtvbG9tbnlhLg0KdmFyc190YXJnZXQgPC0gYygiWDEiLCAiWDIiLCAiWDMiLCAiWDQiLCAiWDUiKQ0KIyBDZWsga29sb20gbWFuYSB5YW5nIHNlc3VhaSBkZW5nYW4gdmFyc190YXJnZXQgZGkgZGZfc2lnX21hcA0KIyAoVGVya2FkYW5nIG91dHB1dCBnd3IgbWVtYmVyaSBzdWZmaXggLjEsIC4yIGRzdCkNCmNvbHNfaWR4IDwtIGdyZXAocGFzdGUodmFyc190YXJnZXQsIGNvbGxhcHNlPSJ8IiksIGNvbG5hbWVzKGRmX3NpZ19tYXApKQ0KIyAyLiBNZW1idWF0IEtvbG9tIEtvbWJpbmFzaSAidmFyX3NpZyIgDQpkZl9zaWdfbWFwJHZhcl9zaWcgPC0gYXBwbHkoZGZfc2lnX21hcFssIGNvbHNfaWR4XSwgMSwgZnVuY3Rpb24ocm93KSB7DQogICMgQ2VrIHZhcmlhYmVsIG1hbmEgeWFuZyBwLXZhbHVlIDw9IDAuMDUNCiAgaXNfc2lnIDwtIHJvdyA8PSAwLjA1DQogICMgQW1iaWwgbmFtYSB2YXJpYWJlbCB5YW5nIFRSVUUNCiAgIyBLaXRhIG1hcHBpbmcgaW5kZXggcm93IGtlIG5hbWEgdmFyc190YXJnZXQgYWdhciByYXBpDQogIG5hbWFfc2lnIDwtIHZhcnNfdGFyZ2V0W2lzX3NpZ10NCiAgaWYgKGxlbmd0aChuYW1hX3NpZykgPT0gMCkgew0KICAgIHJldHVybigiVGlkYWsgU2lnbmlmaWthbiIpDQogIH0gZWxzZSB7DQogICAgcmV0dXJuKHBhc3RlKHNvcnQobmFtYV9zaWcpLCBjb2xsYXBzZSA9ICIsICIpKQ0KICB9DQp9KQ0KIyBDZWsgdGFiZWwgcmVrYXBpdHVsYXNpIHNlbWVudGFyYQ0KcHJpbnQodGFibGUoZGZfc2lnX21hcCR2YXJfc2lnKSkNCiMgMy4gUGVyc2lhcGFuIERhdGEgU3Bhc2lhbCAoU2hhcGVmaWxlKSANCmxpYnJhcnkocm5hdHVyYWxlYXJ0aCkNCmxpYnJhcnkoc2YpDQojIEFtYmlsIHBldGEgSW5kb25lc2lhIGxldmVsIHByb3ZpbnNpDQppbmRvX21hcCA8LSBuZV9zdGF0ZXMoY291bnRyeSA9ICJpbmRvbmVzaWEiLCByZXR1cm5jbGFzcyA9ICJzZiIpDQojIEZpbHRlciBoYW55YSBQdWxhdSBTdW1hdGVyYQ0KIyBEYWZ0YXIgbmFtYSBwcm92aW5zaSBkaSBybmF0dXJhbGVhcnRoIG11bmdraW4gVGl0bGUgQ2FzZSwgZGF0YSBBbmRhIFVQUEVSQ0FTRS4NCiMgS2l0YSBzYW1ha2FuIGR1bHUuDQppbmRvX21hcCRuYW1lX3VwcGVyIDwtIHRvdXBwZXIoaW5kb19tYXAkbmFtZSkNCmxpc3Rfc3VtYXRlcmEgPC0gYygiQUNFSCIsICJTVU1BVEVSQSBVVEFSQSIsICJTVU1BVEVSQSBCQVJBVCIsICJSSUFVIiwgDQogICAgICAgICAgICAgICAgICAgIktFUFVMQVVBTiBSSUFVIiwgIkpBTUJJIiwgIkJFTkdLVUxVIiwgIlNVTUFURVJBIFNFTEFUQU4iLCANCiAgICAgICAgICAgICAgICAgICAiS0VQVUxBVUFOIEJBTkdLQSBCRUxJVFVORyIsICJMQU1QVU5HIikNCnN1bWF0ZXJhX3NmIDwtIGluZG9fbWFwICU+JSANCiAgZmlsdGVyKG5hbWVfdXBwZXIgJWluJSBsaXN0X3N1bWF0ZXJhKQ0KIyBHYWJ1bmdrYW4gKEpvaW4pIERhdGEgU2lnbmlmaWthbnNpIGtlIFBldGENCiMgUGFzdGlrYW4gbmFtYSBrb2xvbSBrdW5jaSBzYW1hIChQUk9WIHZzIG5hbWVfdXBwZXIpDQptYXBfZmluYWwgPC0gc3VtYXRlcmFfc2YgJT4lDQogIGxlZnRfam9pbihkZl9zaWdfbWFwLCBieSA9IGMoIm5hbWVfdXBwZXIiID0gIlBST1YiKSkNCnVydXRhbl9jdXN0b20gPC0gYygiWDIsIFgzLCBYNSIsDQogICAgICAgICAgICAgICAgICAgIlgzLCBYNCwgWDUiLA0KICAgICAgICAgICAgICAgICAgICJYMSwgWDUiLA0KICAgICAgICAgICAgICAgICAgICJYMiwgWDQiLA0KICAgICAgICAgICAgICAgICAgICJYMyINCikNCiMgVWJhaCB2YXJfc2lnIG1lbmphZGkgZmFjdG9yIGFnYXIgbGVnZW5kIHJhcGkNCm1hcF9maW5hbCR2YXJfc2lnIDwtIGZhY3RvcihtYXBfZmluYWwkdmFyX3NpZywgbGV2ZWxzID0gdXJ1dGFuX2N1c3RvbSkNCiMgNC4gVmlzdWFsaXNhc2kgKEdheWEgS3VzdG9tKSANCiMgRGVmaW5pc2lrYW4gcGFsZXQgd2FybmEgZGluYW1pcw0KIyBraXRhIHBha2FpIHBhbGV0dGUgUkNvbG9yQnJld2VyDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmptbF9rYXRlZ29yaSA8LSBsZW5ndGgobGV2ZWxzKG1hcF9maW5hbCR2YXJfc2lnKSkNCiMgSmlrYSBrYXRlZ29yaSBzZWRpa2l0IHBha2FpIG1hbnVhbCwgamlrYSBiYW55YWsgcGFrYWkgcGFsZXR0ZSBvdG9tYXRpcw0KIyAzLiBEZWZpbmlzaWthbiBXYXJuYSBCZXJkYXNhcmthbiBMb2dpa2EgUGVuY2FtcHVyYW4NCiMgRm9ybWF0OiBjKCJLQVRFR09SSSIgPSAiS09ERV9IRVgiKQ0KIyBEZWZpbmlzaWthbiB3YXJuYSBwaWxpaGFuDQojIE1lbmFtYmFoa2FuIHdhcm5hIE1lcmFoIFR1YSAoIzgwMDAyNikgZGkgYmFnaWFuIGFraGlyDQpteV9jb2xvcnNfbG9naWMgPC0gYygNCiAgIiMwODUxOUMiLCANCiAgIiMzMTgyQkQiLCANCiAgIiM5RUNBRTEiLCANCiAgIiMzMUEzNTQiLCANCiAgIiM3NTZCQjEiIA0KKQ0KIyBQbG90dGluZw0KZ2dwbG90KGRhdGEgPSBtYXBfZmluYWwpICsNCiAgZ2VvbV9zZihhZXMoZmlsbCA9IHZhcl9zaWcpLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwoDQogICAgdmFsdWVzID0gbXlfY29sb3JzX2xvZ2ljLA0KICAgIG5hbWUgPSAiUGV1YmFoIFNpZ25pZmlrYW4iLA0KICAgIG5hLnZhbHVlID0gImdyZXk4MCIsICMgV2FybmEgamlrYSBhZGEgcHJvdmluc2kgeWFuZyBkYXRhbnlhIE5BDQogICAgZ3VpZGUgPSBndWlkZV9sZWdlbmQoDQogICAgICB0aXRsZS5wb3NpdGlvbiA9ICJ0b3AiLA0KICAgICAgdGl0bGUuaGp1c3QgPSAwLjUsDQogICAgICBsYWJlbC5wb3NpdGlvbiA9ICJyaWdodCINCiAgICApDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBldGEgU2ViYXJhbiBTaWduaWZpa2Fuc2kgUGFyc2lhbCBHV1BSIiwNCiAgICBzdWJ0aXRsZSA9ICJXaWxheWFoIFB1bGF1IFN1bWF0ZXJhICgyMDEwLTIwMjQpIiwNCiAgICBjYXB0aW9uID0gIlN1bWJlcjogSGFzaWwgT2xhaCBEYXRhICgyMDI2KSINCiAgKSArDQogIHRoZW1lX3ZvaWQoKSArICMgVGVtYSBrb3NvbmcgKHRhbnBhIGF4aXMvZ3JpZCkNCiAgdGhlbWUoDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEwKSwNCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksDQogICAgbGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMSwgImNtIiksDQogICAgbGVnZW5kLmtleS5oZWlnaHQgPSB1bml0KDEsICJjbSIpLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTYsIG1hcmdpbiA9IG1hcmdpbihiPTEwKSksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDEyLCBtYXJnaW4gPSBtYXJnaW4oYj0yMCkpDQogICkNCmBgYA0K