# LOAD PACKAGE
library(readxl)
## Warning: package 'readxl' was built under R version 4.3.3
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.3.3
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(tidyr)
## Warning: package 'tidyr' was built under R version 4.3.3
library(lubridate)
## Warning: package 'lubridate' was built under R version 4.3.3
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
library(RColorBrewer)
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.3.3
## corrplot 0.95 loaded
library(scales)
library(igraph)
## Warning: package 'igraph' was built under R version 4.3.3
## 
## Attaching package: 'igraph'
## The following objects are masked from 'package:lubridate':
## 
##     %--%, union
## The following object is masked from 'package:tidyr':
## 
##     crossing
## The following objects are masked from 'package:dplyr':
## 
##     as_data_frame, groups, union
## The following objects are masked from 'package:stats':
## 
##     decompose, spectrum
## The following object is masked from 'package:base':
## 
##     union
# IMPORT DATA
data <- read_excel(
  "C:/Users/ASUS/OneDrive/Documents/CRM_KELOMPOK 3/DATA PUAN COFEE GUNMAL_APRIL-SEPTEMBER 2025.xlsx",
  sheet = "PEMASUKAN"
)
# RENAME KOLOM
colnames(data) <- c(
  "Tanggal",
  "Cup_Dingin", "Cup_Panas", "Air_Mineral",
  "Espresso", "Kapiten",
  "Cookies", "Fudgy_Brownies", "Fudgy_Brownies_Aya",
  "Cireng", "Singkong", "Kentang", "Dimsum",
  "Pentol", "Tahu_Bakso",
  "Mie_Goreng", "Mie_Kuah", "Nasi_Goreng"
)
# CLEANING DATA
data$Tanggal <- as.Date(data$Tanggal)

produk_cols <- names(data)[-1]
for (col in produk_cols) {
  data[[col]] <- suppressWarnings(as.numeric(as.character(data[[col]])))
}

data <- data %>% filter(!is.na(Tanggal))
# STATISTIK DESKRIPTIF
summary(data)
##     Tanggal             Cup_Dingin      Cup_Panas       Air_Mineral    
##  Min.   :2025-03-29   Min.   : 83.0   Min.   : 0.000   Min.   : 0.000  
##  1st Qu.:2025-05-16   1st Qu.:131.0   1st Qu.: 1.000   1st Qu.: 4.000  
##  Median :2025-07-01   Median :147.0   Median : 2.000   Median : 6.000  
##  Mean   :2025-06-30   Mean   :149.6   Mean   : 2.623   Mean   : 6.956  
##  3rd Qu.:2025-08-15   3rd Qu.:168.5   3rd Qu.: 4.000   3rd Qu.:10.000  
##  Max.   :2025-09-30   Max.   :255.0   Max.   :13.000   Max.   :21.000  
##                                                                        
##     Espresso         Kapiten          Cookies       Fudgy_Brownies  
##  Min.   : 0.000   Min.   :0.0000   Min.   : 0.000   Min.   :0.0000  
##  1st Qu.: 0.000   1st Qu.:0.0000   1st Qu.: 1.000   1st Qu.:0.0000  
##  Median : 1.000   Median :0.0000   Median : 3.000   Median :0.0000  
##  Mean   : 1.527   Mean   :0.3661   Mean   : 4.098   Mean   :0.2131  
##  3rd Qu.: 2.000   3rd Qu.:1.0000   3rd Qu.: 7.000   3rd Qu.:0.0000  
##  Max.   :48.000   Max.   :4.0000   Max.   :30.000   Max.   :6.0000  
##  NA's   :1                                                          
##  Fudgy_Brownies_Aya     Cireng          Singkong        Kentang      
##  Min.   :0.0000     Min.   : 0.000   Min.   :0.000   Min.   : 0.000  
##  1st Qu.:0.0000     1st Qu.: 4.000   1st Qu.:1.000   1st Qu.: 2.000  
##  Median :0.0000     Median : 6.000   Median :2.000   Median : 4.000  
##  Mean   :0.9563     Mean   : 6.104   Mean   :1.869   Mean   : 4.087  
##  3rd Qu.:2.0000     3rd Qu.: 8.000   3rd Qu.:3.000   3rd Qu.: 6.000  
##  Max.   :6.0000     Max.   :18.000   Max.   :7.000   Max.   :11.000  
##                                                                      
##      Dimsum          Pentol         Tahu_Bakso     Mie_Goreng      Mie_Kuah    
##  Min.   :0.000   Min.   :0.0000   Min.   :0.00   Min.   :0.00   Min.   :0.000  
##  1st Qu.:1.000   1st Qu.:0.0000   1st Qu.:0.00   1st Qu.:0.00   1st Qu.:0.000  
##  Median :1.000   Median :1.0000   Median :1.00   Median :1.00   Median :1.000  
##  Mean   :1.486   Mean   :0.7486   Mean   :1.47   Mean   :1.23   Mean   :1.175  
##  3rd Qu.:2.000   3rd Qu.:1.0000   3rd Qu.:2.00   3rd Qu.:2.00   3rd Qu.:2.000  
##  Max.   :7.000   Max.   :5.0000   Max.   :8.00   Max.   :8.00   Max.   :9.000  
##                                                                                
##   Nasi_Goreng   
##  Min.   :0.000  
##  1st Qu.:1.000  
##  Median :2.000  
##  Mean   :1.743  
##  3rd Qu.:3.000  
##  Max.   :6.000  
## 
# VISUALISASI 1 - TOTAL PENJUALAN PER PRODUK
total_produk <- data %>%
  select(-Tanggal) %>%
  summarise(across(everything(), ~sum(., na.rm = TRUE))) %>%
  pivot_longer(everything(), names_to = "Produk", values_to = "Total") %>%
  mutate(
    Produk   = gsub("_", " ", Produk),
    Kategori = case_when(
      Produk %in% c("Cup Dingin", "Cup Panas",
                    "Espresso", "Kapiten", "Air Mineral") ~ "Minuman",
      Produk %in% c("Cookies", "Fudgy Brownies",
                    "Fudgy Brownies Aya")                 ~ "Kue & Snack",
      TRUE                                                ~ "Makanan"
    )
  ) %>%
  arrange(desc(Total))

ggplot(total_produk,
       aes(x = reorder(Produk, Total), y = Total, fill = Kategori)) +
  geom_col(width = 0.7) +
  geom_text(aes(label = comma(Total)), hjust = -0.1, size = 3.2) +
  coord_flip() +
  scale_fill_manual(values = c("Kue & Snack" = "#6F3811",
                               "Makanan"     = "#A0522D",
                               "Minuman"     = "#C68642")) +
  scale_y_continuous(labels = comma, expand = expansion(mult = c(0, 0.18))) +
  labs(title    = "Total Penjualan per Produk (April–September 2025)",
       subtitle = "Puan Kopi Gunung Malang",
       x = NULL, y = "Jumlah Terjual (Unit)", fill = "Kategori") +
  theme_minimal(base_size = 12) +
  theme(plot.title = element_text(face = "bold", color = "#3E1C00"))

# VISUALISASI 2 - TREN PENJUALAN BULANAN
tren_bulanan <- data %>%
  mutate(Bulan = floor_date(Tanggal, "month")) %>%
  group_by(Bulan) %>%
  summarise(across(Cup_Dingin:Kapiten, ~sum(., na.rm = TRUE)),
            .groups = "drop") %>%
  pivot_longer(-Bulan, names_to = "Produk", values_to = "Total") %>%
  mutate(Produk = gsub("_", " ", Produk))

ggplot(tren_bulanan,
       aes(x = Bulan, y = Total, color = Produk, group = Produk)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 2.5) +
  scale_color_manual(values = c("#3E1C00", "#7B3F00", "#C68642",
                                "#E8B97E", "#A0522D")) +
  scale_x_date(date_labels = "%b %Y", date_breaks = "1 month") +
  scale_y_continuous(labels = comma) +
  labs(title    = "Tren Penjualan Minuman per Bulan",
       subtitle = "Puan Kopi Gunung Malang | April–September 2025",
       x = NULL, y = "Jumlah Terjual", color = "Produk") +
  theme_minimal(base_size = 12) +
  theme(plot.title = element_text(face = "bold", color = "#3E1C00"))

# VISUALISASI 3 - HEATMAP PENJUALAN BULANAN
heatmap_data <- data %>%
  mutate(Bulan = format(Tanggal, "%b %Y")) %>%
  group_by(Bulan) %>%
  summarise(across(-Tanggal, ~sum(., na.rm = TRUE)), .groups = "drop") %>%
  pivot_longer(-Bulan, names_to = "Produk", values_to = "Total") %>%
  mutate(
    Produk = gsub("_", " ", Produk),
    Bulan  = factor(Bulan, levels = c("Mar 2025", "Apr 2025", "May 2025",
                                      "Jun 2025", "Jul 2025", "Aug 2025",
                                      "Sep 2025"))
  )

ggplot(heatmap_data, aes(x = Bulan, y = Produk, fill = Total)) +
  geom_tile(color = "white", linewidth = 0.5) +
  geom_text(aes(label = comma(Total)), size = 2.8, color = "white") +
  scale_fill_gradient(low = "#FBE9D0", high = "#3E1C00", labels = comma) +
  labs(title    = "Heatmap Penjualan Bulanan per Produk",
       subtitle = "Puan Kopi Gunung Malang | April–September 2025",
       x = NULL, y = NULL, fill = "Total\nTerjual") +
  theme_minimal(base_size = 11) +
  theme(plot.title  = element_text(face = "bold", color = "#3E1C00"),
        axis.text.x = element_text(angle = 30, hjust = 1))

# DATA BINER
data_biner <- data %>%
  select(-Tanggal) %>%
  mutate(across(everything(), ~ifelse(is.na(.) | . == 0, 0L, 1L)))

data_matrix <- as.matrix(data_biner)
n_trans     <- nrow(data_biner)
prod_names  <- gsub("_", " ", colnames(data_biner))
# PENENTUAN THRESHOLD
freq_item      <- colSums(data_biner)
support_produk <- freq_item / n_trans
names(support_produk) <- prod_names
print(round(sort(support_produk, decreasing = TRUE), 4))
##         Cup Dingin             Cireng        Air Mineral            Kentang 
##             1.0000             0.9836             0.9727             0.9508 
##          Cup Panas           Singkong        Nasi Goreng            Cookies 
##             0.8525             0.8142             0.7869             0.7650 
##             Dimsum         Tahu Bakso           Espresso         Mie Goreng 
##             0.7650             0.7268             0.6721             0.6120 
##           Mie Kuah             Pentol Fudgy Brownies Aya            Kapiten 
##             0.5355             0.5301             0.3497             0.2787 
##     Fudgy Brownies 
##             0.0874
MIN_SUPPORT    <- 0.50
MIN_CONFIDENCE <- 0.60
MIN_LIFT       <- 1.0
# VISUALISASI 4 - ITEM FREQUENCY PLOT
freq_df <- data.frame(
  Produk    = prod_names,
  Frekuensi = as.numeric(freq_item)
) %>% arrange(desc(Frekuensi)) %>% head(17)

ggplot(freq_df, aes(x = reorder(Produk, Frekuensi), y = Frekuensi)) +
  geom_col(fill = "#A0522D", width = 0.7) +
  geom_text(aes(label = Frekuensi), hjust = -0.2, size = 3.2, color = "#3E1C00") +
  coord_flip() +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(title = "Frekuensi Kemunculan Tiap Produk\nPuan Kopi Gunung Malang",
       x = NULL, y = "Frekuensi (Hari)") +
  theme_minimal(base_size = 11) +
  theme(plot.title = element_text(face = "bold", color = "#3E1C00"))

# FREQUENT ITEMSETS
freq_1 <- data.frame(
  Itemset = prod_names,
  Support = round(support_produk, 4),
  Count   = as.numeric(freq_item)
) %>%
  filter(Support >= MIN_SUPPORT) %>%
  arrange(desc(Support))

cat("\n=== FREQUENT 1-ITEMSETS ===\n")
## 
## === FREQUENT 1-ITEMSETS ===
print(freq_1)
##                 Itemset Support Count
## Cup Dingin   Cup Dingin  1.0000   183
## Cireng           Cireng  0.9836   180
## Air Mineral Air Mineral  0.9727   178
## Kentang         Kentang  0.9508   174
## Cup Panas     Cup Panas  0.8525   156
## Singkong       Singkong  0.8142   149
## Nasi Goreng Nasi Goreng  0.7869   144
## Cookies         Cookies  0.7650   140
## Dimsum           Dimsum  0.7650   140
## Tahu Bakso   Tahu Bakso  0.7268   133
## Espresso       Espresso  0.6721   123
## Mie Goreng   Mie Goreng  0.6120   112
## Mie Kuah       Mie Kuah  0.5355    98
## Pentol           Pentol  0.5301    97
# APRIORI MANUAL - ASSOCIATION RULES
cols      <- colnames(data_biner)
n_cols    <- length(cols)
rules_list <- list()

for (i in 1:(n_cols - 1)) {
  for (j in (i + 1):n_cols) {
    sup_ij <- sum(data_biner[[i]] == 1 & data_biner[[j]] == 1) / n_trans
    if (sup_ij < MIN_SUPPORT) next
    
    sup_i <- sum(data_biner[[i]]) / n_trans
    sup_j <- sum(data_biner[[j]]) / n_trans
    
    conf_ij <- sup_ij / sup_i
    lift_ij <- conf_ij / sup_j
    if (conf_ij >= MIN_CONFIDENCE && lift_ij > MIN_LIFT) {
      rules_list[[length(rules_list) + 1]] <- data.frame(
        Antecedent = gsub("_", " ", cols[i]),
        Consequent = gsub("_", " ", cols[j]),
        Support    = round(sup_ij,  3),
        Confidence = round(conf_ij, 3),
        Lift       = round(lift_ij, 3),
        Count      = round(sup_ij * n_trans)
      )
    }
    
    conf_ji <- sup_ij / sup_j
    lift_ji <- conf_ji / sup_i
    if (conf_ji >= MIN_CONFIDENCE && lift_ji > MIN_LIFT) {
      rules_list[[length(rules_list) + 1]] <- data.frame(
        Antecedent = gsub("_", " ", cols[j]),
        Consequent = gsub("_", " ", cols[i]),
        Support    = round(sup_ij,  3),
        Confidence = round(conf_ji, 3),
        Lift       = round(lift_ji, 3),
        Count      = round(sup_ij * n_trans)
      )
    }
  }
}

rules_df <- bind_rows(rules_list) %>%
  arrange(desc(Lift), desc(Confidence)) %>%
  mutate(No = row_number()) %>%
  select(No, everything())

cat("\n=== ASSOCIATION RULES (lift > 1) ===\n")
## 
## === ASSOCIATION RULES (lift > 1) ===
print(rules_df)
##    No  Antecedent  Consequent Support Confidence  Lift Count
## 1   1  Mie Goreng Nasi Goreng   0.514      0.839 1.067    94
## 2   2 Nasi Goreng  Mie Goreng   0.514      0.653 1.067    94
## 3   3    Espresso     Cookies   0.546      0.813 1.063   100
## 4   4    Espresso  Tahu Bakso   0.519      0.772 1.063    95
## 5   5     Cookies    Espresso   0.546      0.714 1.063   100
## 6   6  Tahu Bakso    Espresso   0.519      0.714 1.063    95
## 7   7  Tahu Bakso      Dimsum   0.579      0.797 1.042   106
## 8   8      Dimsum  Tahu Bakso   0.579      0.757 1.042   106
## 9   9    Espresso    Singkong   0.568      0.846 1.038   104
## 10 10    Singkong    Espresso   0.568      0.698 1.038   104
## 11 11  Mie Goreng   Cup Panas   0.541      0.884 1.037    99
## 12 12   Cup Panas  Mie Goreng   0.541      0.635 1.037    99
## 13 13  Tahu Bakso    Singkong   0.612      0.842 1.034   112
## 14 14    Singkong  Tahu Bakso   0.612      0.752 1.034   112
## 15 15    Espresso Nasi Goreng   0.546      0.813 1.033   100
## 16 16 Nasi Goreng    Espresso   0.546      0.694 1.033   100
## 17 17 Nasi Goreng    Singkong   0.661      0.840 1.032   121
## 18 18    Singkong Nasi Goreng   0.661      0.812 1.032   121
## 19 19      Pentol     Kentang   0.519      0.979 1.030    95
## 20 20 Nasi Goreng     Kentang   0.770      0.979 1.030   141
## 21 21     Kentang Nasi Goreng   0.770      0.810 1.030   141
## 22 22    Espresso     Kentang   0.656      0.976 1.026   120
## 23 23     Kentang    Espresso   0.656      0.690 1.026   120
## 24 24    Singkong     Kentang   0.792      0.973 1.023   145
## 25 25     Kentang    Singkong   0.792      0.833 1.023   145
## 26 26     Cookies   Cup Panas   0.667      0.871 1.022   122
## 27 27   Cup Panas     Cookies   0.667      0.782 1.022   122
## 28 28  Tahu Bakso     Cookies   0.568      0.782 1.022   104
## 29 29     Cookies  Tahu Bakso   0.568      0.743 1.022   104
## 30 30 Nasi Goreng   Cup Panas   0.683      0.868 1.018   125
## 31 31   Cup Panas Nasi Goreng   0.683      0.801 1.018   125
## 32 32      Pentol      Cireng   0.530      1.000 1.017    97
## 33 33  Tahu Bakso      Cireng   0.727      1.000 1.017   133
## 34 34  Mie Goreng      Cireng   0.612      1.000 1.017   112
## 35 35    Mie Kuah      Cireng   0.536      1.000 1.017    98
## 36 36      Cireng  Tahu Bakso   0.727      0.739 1.017   133
## 37 37      Cireng  Mie Goreng   0.612      0.622 1.017   112
## 38 38      Dimsum     Kentang   0.738      0.964 1.014   135
## 39 39  Mie Goreng     Kentang   0.590      0.964 1.014   108
## 40 40     Kentang      Dimsum   0.738      0.776 1.014   135
## 41 41     Kentang  Mie Goreng   0.590      0.621 1.014   108
## 42 42      Dimsum Air Mineral   0.754      0.986 1.013   138
## 43 43 Air Mineral      Dimsum   0.754      0.775 1.013   138
## 44 44  Tahu Bakso     Kentang   0.699      0.962 1.012   128
## 45 45     Kentang  Tahu Bakso   0.699      0.736 1.012   128
## 46 46 Nasi Goreng      Cireng   0.781      0.993 1.010   143
## 47 47      Cireng Nasi Goreng   0.781      0.794 1.010   143
## 48 48      Dimsum      Cireng   0.760      0.993 1.009   139
## 49 49    Mie Kuah     Kentang   0.514      0.959 1.009    94
## 50 50     Cookies    Singkong   0.628      0.821 1.009   115
## 51 51  Mie Goreng    Singkong   0.503      0.821 1.009    92
## 52 52    Singkong     Cookies   0.628      0.772 1.009   115
## 53 53      Cireng      Dimsum   0.760      0.772 1.009   139
## 54 54    Singkong  Mie Goreng   0.503      0.617 1.009    92
## 55 55    Espresso      Cireng   0.667      0.992 1.008   122
## 56 56     Cookies Nasi Goreng   0.607      0.793 1.008   111
## 57 57 Nasi Goreng     Cookies   0.607      0.771 1.008   111
## 58 58      Cireng    Espresso   0.667      0.678 1.008   122
## 59 59    Singkong Air Mineral   0.798      0.980 1.007   146
## 60 60 Nasi Goreng Air Mineral   0.770      0.979 1.007   141
## 61 61 Air Mineral    Singkong   0.798      0.820 1.007   146
## 62 62 Air Mineral Nasi Goreng   0.770      0.792 1.007   141
## 63 63     Cookies Air Mineral   0.749      0.979 1.006   137
## 64 64 Air Mineral     Cookies   0.749      0.770 1.006   137
## 65 65 Air Mineral      Cireng   0.962      0.989 1.005   176
## 66 66     Kentang      Cireng   0.940      0.989 1.005   172
## 67 67      Cireng Air Mineral   0.962      0.978 1.005   176
## 68 68      Cireng     Kentang   0.940      0.956 1.005   172
## 69 69  Tahu Bakso   Cup Panas   0.623      0.857 1.005   114
## 70 70   Cup Panas  Tahu Bakso   0.623      0.731 1.005   114
## 71 71     Kentang Air Mineral   0.929      0.977 1.004   170
## 72 72 Air Mineral     Kentang   0.929      0.955 1.004   170
## 73 73    Singkong      Cireng   0.803      0.987 1.003   147
## 74 74      Cireng    Singkong   0.803      0.817 1.003   147
## 75 75     Cookies      Cireng   0.754      0.986 1.002   138
## 76 76   Cup Panas Air Mineral   0.831      0.974 1.002   152
## 77 77 Air Mineral   Cup Panas   0.831      0.854 1.002   152
## 78 78      Cireng     Cookies   0.754      0.767 1.002   138
## 79 79      Dimsum    Singkong   0.623      0.814 1.000   114
## 80 80    Singkong      Dimsum   0.623      0.765 1.000   114
# VISUALISASI 5 - SCATTER PLOT RULES
ggplot(rules_df, aes(x = Support, y = Confidence, size = Lift, color = Lift)) +
  geom_point(alpha = 0.8) +
  scale_color_gradient(low = "#F2D0A4", high = "#3E1C00") +
  scale_size_continuous(range = c(3, 10)) +
  labs(title    = "Association Rules: Support vs Confidence (warna = Lift)",
       x = "Support", y = "Confidence",
       color = "Lift", size = "Lift") +
  theme_minimal(base_size = 11) +
  theme(plot.title = element_text(face = "bold", color = "#3E1C00"))

# VISUALISASI 6 - NETWORK GRAPH
g <- graph_from_data_frame(
  rules_df[, c("Antecedent", "Consequent", "Lift")],
  directed = TRUE
)
E(g)$width       <- E(g)$Lift * 0.8
E(g)$color       <- colorRampPalette(c("#E8B97E", "#3E1C00"))(ecount(g))
V(g)$color       <- "#C68642"
V(g)$frame.color <- "#6F3811"
V(g)$size        <- 20
V(g)$label.cex   <- 0.65
V(g)$label.color <- "white"

plot(g,
     layout          = layout_with_fr(g),
     edge.arrow.size = 0.4,
     main            = "Network Graph Association Rules — Puan Kopi Gunung Malang")

# VISUALISASI 7 - HEATMAP RULES
ggplot(rules_df, aes(x = Consequent, y = Antecedent, fill = Lift)) +
  geom_tile(color = "white") +
  geom_text(aes(label = round(Lift, 2)), size = 2.8, color = "white") +
  scale_fill_gradient(low = "#FBE9D0", high = "#3E1C00") +
  labs(title = "Heatmap Rules: Antecedent vs Consequent (nilai = Lift)",
       x = "Consequent", y = "Antecedent", fill = "Lift") +
  theme_minimal(base_size = 10) +
  theme(plot.title  = element_text(face = "bold", color = "#3E1C00"),
        axis.text.x = element_text(angle = 45, hjust = 1))

# KORELASI ANTAR PRODUK
data_biner_cor <- data_biner %>%
  select(where(~ sd(., na.rm = TRUE) > 0))

cor_matrix <- cor(data_biner_cor, use = "pairwise.complete.obs")
cor_matrix[is.nan(cor_matrix)] <- 0
cor_matrix[is.na(cor_matrix)]  <- 0
colnames(cor_matrix) <- gsub("_", " ", colnames(cor_matrix))
rownames(cor_matrix) <- gsub("_", " ", rownames(cor_matrix))

corrplot(cor_matrix,
         method      = "color",
         type        = "upper",
         order       = "hclust",
         addCoef.col = "#3E1C00",
         number.cex  = 0.65,
         tl.cex      = 0.8,
         tl.col      = "#3E1C00",
         col         = colorRampPalette(c("#FBE9D0", "#C68642", "#3E1C00"))(200),
         title       = "Korelasi Antar Produk — Puan Kopi Gunung Malang",
         mar         = c(0, 0, 2, 0))

# CO-OCCURRENCE MATRIX
co_matrix       <- t(data_matrix) %*% data_matrix
diag(co_matrix) <- 0
colnames(co_matrix) <- gsub("_", " ", colnames(co_matrix))
rownames(co_matrix) <- gsub("_", " ", rownames(co_matrix))

print(co_matrix)
##                    Cup Dingin Cup Panas Air Mineral Espresso Kapiten Cookies
## Cup Dingin                  0       156         178      123      51     140
## Cup Panas                 156         0         152      104      47     122
## Air Mineral               178       152           0      119      50     137
## Espresso                  123       104         119        0      34     100
## Kapiten                    51        47          50       34       0      41
## Cookies                   140       122         137      100      41       0
## Fudgy Brownies             16        13          16       10       5      14
## Fudgy Brownies Aya         64        54          62       38      16      44
## Cireng                    180       153         176      122      50     138
## Singkong                  149       125         146      104      39     115
## Kentang                   174       148         170      120      49     133
## Dimsum                    140       118         138       89      40     103
## Pentol                     97        86          94       70      25      73
## Tahu Bakso                133       114         129       95      38     104
## Mie Goreng                112        99         108       80      33      89
## Mie Kuah                   98        83          95       69      29      77
## Nasi Goreng               144       125         141      100      44     111
##                    Fudgy Brownies Fudgy Brownies Aya Cireng Singkong Kentang
## Cup Dingin                     16                 64    180      149     174
## Cup Panas                      13                 54    153      125     148
## Air Mineral                    16                 62    176      146     170
## Espresso                       10                 38    122      104     120
## Kapiten                         5                 16     50       39      49
## Cookies                        14                 44    138      115     133
## Fudgy Brownies                  0                  0     16       14      16
## Fudgy Brownies Aya              0                  0     64       56      60
## Cireng                         16                 64      0      147     172
## Singkong                       14                 56    147        0     145
## Kentang                        16                 60    172      145       0
## Dimsum                         14                 52    139      114     135
## Pentol                          8                 38     97       82      95
## Tahu Bakso                     15                 48    133      112     128
## Mie Goreng                     12                 41    112       92     108
## Mie Kuah                        9                 31     98       80      94
## Nasi Goreng                    13                 50    143      121     141
##                    Dimsum Pentol Tahu Bakso Mie Goreng Mie Kuah Nasi Goreng
## Cup Dingin            140     97        133        112       98         144
## Cup Panas             118     86        114         99       83         125
## Air Mineral           138     94        129        108       95         141
## Espresso               89     70         95         80       69         100
## Kapiten                40     25         38         33       29          44
## Cookies               103     73        104         89       77         111
## Fudgy Brownies         14      8         15         12        9          13
## Fudgy Brownies Aya     52     38         48         41       31          50
## Cireng                139     97        133        112       98         143
## Singkong              114     82        112         92       80         121
## Kentang               135     95        128        108       94         141
## Dimsum                  0     78        106         85       77         110
## Pentol                 78      0         73         70       58          83
## Tahu Bakso            106     73          0         80       74         103
## Mie Goreng             85     70         80          0       62          94
## Mie Kuah               77     58         74         62        0          86
## Nasi Goreng           110     83        103         94       86           0
# VISUALISASI 8 - TOP CO-OCCURRENCE
co_df <- as.data.frame(as.table(co_matrix)) %>%
  rename(Produk1 = Var1, Produk2 = Var2, CoOccurrence = Freq) %>%
  filter(as.character(Produk1) < as.character(Produk2), CoOccurrence > 0) %>%
  arrange(desc(CoOccurrence)) %>%
  head(20) %>%
  mutate(Pasangan = paste(Produk1, "–", Produk2))

ggplot(co_df, aes(x = reorder(Pasangan, CoOccurrence), y = CoOccurrence)) +
  geom_col(fill = "#A0522D", alpha = 0.9, width = 0.7) +
  geom_text(aes(label = CoOccurrence), hjust = -0.2, size = 3.2, color = "#3E1C00") +
  coord_flip() +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(title    = "Top 20 Pasangan Produk Co-occurrence Tertinggi",
       subtitle = "Puan Kopi Gunung Malang | April–September 2025",
       x = NULL, y = "Jumlah Hari Terjual Bersamaan") +
  theme_minimal(base_size = 11) +
  theme(plot.title = element_text(face = "bold", color = "#3E1C00"))

# ANALISIS WEEKDAY VS WEEKEND
data_hari <- data %>%
  mutate(
    Hari       = weekdays(Tanggal),
    Jenis_Hari = ifelse(Hari %in% c("Saturday", "Sunday",
                                    "Sabtu", "Minggu"),
                        "Weekend", "Weekday")
  ) %>%
  group_by(Jenis_Hari) %>%
  summarise(across(-c(Tanggal, Hari), ~round(mean(., na.rm = TRUE), 2)),
            .groups = "drop") %>%
  pivot_longer(-Jenis_Hari, names_to = "Produk", values_to = "Rata2") %>%
  mutate(Produk = gsub("_", " ", Produk))

ggplot(data_hari,
       aes(x = reorder(Produk, Rata2), y = Rata2, fill = Jenis_Hari)) +
  geom_col(position = "dodge", width = 0.7) +
  coord_flip() +
  scale_fill_manual(values = c("Weekday" = "#A0522D",
                               "Weekend" = "#E8B97E")) +
  scale_y_continuous(labels = comma) +
  labs(title    = "Rata-rata Penjualan Harian: Weekday vs Weekend",
       subtitle = "Puan Kopi Gunung Malang | April–September 2025",
       x = NULL, y = "Rata-rata Unit Terjual", fill = "Jenis Hari") +
  theme_minimal(base_size = 11) +
  theme(plot.title      = element_text(face = "bold", color = "#3E1C00"),
        legend.position = "bottom")

# REKOMENDASI PRODUCT BUNDLING
bundling <- data.frame(
  Bundle      = c("Bundle 1", "Bundle 2", "Bundle 3", "Bundle 4"),
  Nama_Bundle = c("Paket Kopi Favorit", "Paket Ngopi Santai",
                  "Paket Makan Siang",  "Paket Cemilan Grup"),
  Produk      = c(
    "Cup Dingin + Cireng / Kentang",
    "Cup Dingin + Cookies / Fudgy Brownies",
    "Nasi Goreng / Mie Goreng + Cup Dingin",
    "Cireng + Kentang + Dimsum + Air Mineral"
  ),
  Dasar_Rules = c(
    "Support & Lift tertinggi antara minuman + snack",
    "Asosiasi kuat minuman kopi + kue",
    "Co-occurrence tinggi makanan berat + minuman",
    "Produk snack sering terjual bersamaan"
  )
)

print(bundling)
##     Bundle        Nama_Bundle                                  Produk
## 1 Bundle 1 Paket Kopi Favorit           Cup Dingin + Cireng / Kentang
## 2 Bundle 2 Paket Ngopi Santai   Cup Dingin + Cookies / Fudgy Brownies
## 3 Bundle 3  Paket Makan Siang   Nasi Goreng / Mie Goreng + Cup Dingin
## 4 Bundle 4 Paket Cemilan Grup Cireng + Kentang + Dimsum + Air Mineral
##                                       Dasar_Rules
## 1 Support & Lift tertinggi antara minuman + snack
## 2                Asosiasi kuat minuman kopi + kue
## 3    Co-occurrence tinggi makanan berat + minuman
## 4           Produk snack sering terjual bersamaan
# STRATEGI CRM
strategi_crm <- data.frame(
  No        = 1:6,
  Strategi  = c("Diskon Bundle", "Stamp Card",
                "Promo Jam Makan Siang", "Weekend Special",
                "Cross-Selling", "Member Reward"),
  Deskripsi = c(
    "Diskon 10-15% untuk pembelian paket bundle",
    "Beli 5x bundle = 1 minuman gratis",
    "Harga spesial jam 11.00-14.00 untuk Paket Makan Siang",
    "Promo bundle eksklusif Sabtu-Minggu",
    "Kasir menawarkan produk pelengkap berdasarkan rules",
    "Pelanggan member poin 2x lipat saat beli bundle"
  ),
  Target_Bundle = c("Semua Bundle", "Bundle 1 & 2", "Bundle 3",
                    "Bundle 4", "Semua Bundle", "Semua Bundle")
)

print(strategi_crm)
##   No              Strategi
## 1  1         Diskon Bundle
## 2  2            Stamp Card
## 3  3 Promo Jam Makan Siang
## 4  4       Weekend Special
## 5  5         Cross-Selling
## 6  6         Member Reward
##                                               Deskripsi Target_Bundle
## 1            Diskon 10-15% untuk pembelian paket bundle  Semua Bundle
## 2                     Beli 5x bundle = 1 minuman gratis  Bundle 1 & 2
## 3 Harga spesial jam 11.00-14.00 untuk Paket Makan Siang      Bundle 3
## 4                   Promo bundle eksklusif Sabtu-Minggu      Bundle 4
## 5   Kasir menawarkan produk pelengkap berdasarkan rules  Semua Bundle
## 6       Pelanggan member poin 2x lipat saat beli bundle  Semua Bundle
# VISUALISASI 9 - PROPORSI KATEGORI PRODUK
total_kategori <- total_produk %>%
  group_by(Kategori) %>%
  summarise(Total = sum(Total), .groups = "drop") %>%
  mutate(Persen = round(Total / sum(Total) * 100, 1),
         Label  = paste0(Kategori, "\n", Persen, "%"))

ggplot(total_kategori, aes(x = "", y = Total, fill = Kategori)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  geom_text(aes(label = Label),
            position = position_stack(vjust = 0.5),
            size = 4, fontface = "bold", color = "white") +
  scale_fill_manual(values = c("Kue & Snack" = "#6F3811",
                               "Makanan"     = "#A0522D",
                               "Minuman"     = "#C68642")) +
  labs(title    = "Proporsi Penjualan per Kategori Produk",
       subtitle = "Puan Kopi Gunung Malang | April–September 2025") +
  theme_void() +
  theme(plot.title      = element_text(face = "bold", hjust = 0.5, color = "#3E1C00"),
        plot.subtitle   = element_text(hjust = 0.5, color = "#6F3811"),
        legend.position = "none")

# VISUALISASI 10 - SUPPORT VS CONFIDENCE + LABEL
ggplot(rules_df, aes(x = Support, y = Confidence, size = Lift, color = Lift)) +
  geom_point(alpha = 0.8) +
  scale_color_gradient(low = "#F2D0A4", high = "#3E1C00") +
  scale_size_continuous(range = c(3, 10)) +
  geom_text(aes(label = paste(Antecedent, "→", Consequent)),
            size = 2.5, vjust = -1, check_overlap = TRUE, color = "#3E1C00") +
  labs(title    = "Association Rules: Support vs Confidence",
       subtitle = "Ukuran & Warna Titik = Nilai Lift",
       x = "Support", y = "Confidence",
       color = "Lift", size = "Lift") +
  theme_minimal(base_size = 11) +
  theme(plot.title = element_text(face = "bold", color = "#3E1C00"))

# VISUALISASI 11 - PENJUALAN PER KATEGORI PER BULAN
bulanan_kategori <- data %>%
  mutate(Bulan = format(Tanggal, "%b %Y")) %>%
  group_by(Bulan) %>%
  summarise(
    Minuman   = sum(Cup_Dingin + Cup_Panas + Espresso +
                      Kapiten + Air_Mineral, na.rm = TRUE),
    Kue_Snack = sum(Cookies + Fudgy_Brownies +
                      Fudgy_Brownies_Aya, na.rm = TRUE),
    Makanan   = sum(Cireng + Singkong + Kentang + Dimsum +
                      Pentol + Tahu_Bakso + Mie_Goreng +
                      Mie_Kuah + Nasi_Goreng, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  pivot_longer(-Bulan, names_to = "Kategori", values_to = "Total") %>%
  mutate(Bulan = factor(Bulan, levels = c("Mar 2025", "Apr 2025",
                                          "May 2025", "Jun 2025",
                                          "Jul 2025", "Aug 2025",
                                          "Sep 2025")))

ggplot(bulanan_kategori,
       aes(x = Bulan, y = Total, fill = Kategori)) +
  geom_col(position = "dodge", width = 0.7) +
  scale_fill_manual(values = c("Kue_Snack" = "#6F3811",
                               "Makanan"   = "#A0522D",
                               "Minuman"   = "#C68642")) +
  scale_y_continuous(labels = comma) +
  labs(title    = "Total Penjualan per Kategori per Bulan",
       subtitle = "Puan Kopi Gunung Malang | April–September 2025",
       x = NULL, y = "Jumlah Terjual", fill = "Kategori") +
  theme_minimal(base_size = 11) +
  theme(plot.title  = element_text(face = "bold", color = "#3E1C00"),
        axis.text.x = element_text(angle = 30, hjust = 1))

# VISUALISASI 12 - TOP 10 PRODUK TERLARIS
top10 <- total_produk %>% head(10)

ggplot(top10,
       aes(x = reorder(Produk, Total), y = Total, fill = Kategori)) +
  geom_col(width = 0.7) +
  geom_text(aes(label = comma(Total)), hjust = -0.1, size = 3.5) +
  coord_flip() +
  scale_fill_manual(values = c("Kue & Snack" = "#6F3811",
                               "Makanan"     = "#A0522D",
                               "Minuman"     = "#C68642")) +
  scale_y_continuous(labels = comma,
                     expand = expansion(mult = c(0, 0.18))) +
  labs(title    = "Top 10 Produk Terlaris",
       subtitle = "Puan Kopi Gunung Malang | April–September 2025",
       x = NULL, y = "Total Terjual", fill = "Kategori") +
  theme_minimal(base_size = 11) +
  theme(plot.title = element_text(face = "bold", color = "#3E1C00"))

# RINGKASAN AKHIR
cat("================================================\n")
## ================================================
cat("  RINGKASAN MARKET BASKET ANALYSIS - CRM\n")
##   RINGKASAN MARKET BASKET ANALYSIS - CRM
cat("  Puan Kopi Gunung Malang\n")
##   Puan Kopi Gunung Malang
cat("================================================\n")
## ================================================
cat("Periode data      :", format(min(data$Tanggal)),
    "s.d.", format(max(data$Tanggal)), "\n")
## Periode data      : 2025-03-29 s.d. 2025-09-30
cat("Total hari data   :", nrow(data), "hari\n")
## Total hari data   : 183 hari
cat("Jumlah produk     : 17 produk\n")
## Jumlah produk     : 17 produk
cat("Frequent itemsets :", nrow(freq_1), "(1-itemset)\n")
## Frequent itemsets : 14 (1-itemset)
cat("Total rules       :", nrow(rules_df), "\n")
## Total rules       : 80
cat("Min Support       :", MIN_SUPPORT, "\n")
## Min Support       : 0.5
cat("Min Confidence    :", MIN_CONFIDENCE, "\n")
## Min Confidence    : 0.6
cat("Bundle diusulkan  : 4 bundle produk\n")
## Bundle diusulkan  : 4 bundle produk
cat("Strategi CRM      : 6 strategi\n")
## Strategi CRM      : 6 strategi
cat("================================================\n")
## ================================================