1 1. PENDAHULUAN & EKSPLORASI DATA SUMMARY

Dalam dunia pendidikan modern, memahami karakteristik mahasiswa secara individual merupakan tantangan besar. Melalui teknik Clustering (Analisis Klaster) pada rumpun Unsupervised Machine Learning, kita dapat mengelompokkan objek secara otomatis berdasarkan kemiripan perilakunya tanpa perlu melabelinya secara manual. Ibarat memilah buku di perpustakaan, kita ingin buku dengan topik sejenis berkumpul di rak yang sama.

Dataset yang digunakan dalam penelitian ini adalah User Knowledge Modeling Dataset yang diperoleh secara resmi dari UCI Machine Learning Repository. Dataset ini mencakup 403 observasi mahasiswa dengan 5 indikator perilaku digital:

  1. STG (Study Time Goal): Durasi waktu yang dihabiskan mahasiswa untuk mempelajari materi utama.

  2. SCG (Study Cycle Goal): Frekuensi mahasiswa dalam mengulang-ulang materi utama.

  3. STR (Study Time Related): Durasi waktu yang dihabiskan untuk mempelajari materi pendukung terkait.

  4. LPR (Exam Performance Related): Performa nilai ujian mahasiswa pada materi pendukung.

  5. PEG (Exam Performance Goal): Performa nilai ujian mahasiswa pada materi utama.

1.1 1.1 Inisialisasi Library Pendukung

Tahap awal dimulai dengan mengaktifkan seluruh packages R yang merepresentasikan materi perkuliahan dari awal hingga akhir:

library(ggplot2)      # Berfungsi untuk visualisasi grafik ilmiah
## Warning: package 'ggplot2' was built under R version 4.4.3
library(factoextra)   # Berfungsi untuk ekstraksi berbasis multivariat
## Warning: package 'factoextra' was built under R version 4.4.3
## Welcome to factoextra!
## Want to learn more? See two factoextra-related books at https://www.datanovia.com/en/product/practical-guide-to-principal-component-methods-in-r/
library(dbscan)       # Implementasi Distance-Based Clustering (DBSCAN)
## Warning: package 'dbscan' was built under R version 4.4.3
## 
## Attaching package: 'dbscan'
## The following object is masked from 'package:stats':
## 
##     as.dendrogram
library(mclust)       # Implementasi Model-Based Clustering (GMM)
## Warning: package 'mclust' was built under R version 4.4.3
## Package 'mclust' version 6.1.2
## Type 'citation("mclust")' for citing this R package in publications.
library(fpc)          # Berfungsi untuk komputasi kriteria validasi internal
## Warning: package 'fpc' was built under R version 4.4.3
## 
## Attaching package: 'fpc'
## The following object is masked from 'package:dbscan':
## 
##     dbscan
library(readxl)       # Berfungsi untuk membaca data dari format Excel
## Warning: package 'readxl' was built under R version 4.4.3

1.2 1.2 Importasi dan Penggabungan Data

Data dibaca secara terpisah sesuai partisi lembar kerja (sheet) aslinya, kemudian digabungkan untuk mewakili satu populasi utuh.

# Membaca data dari direktori lokal
train_df <- read_xls("D:/SEMESTER 4/SML/Data_User_Modeling_Dataset.xls", sheet = "Training_Data")
## New names:
## • `` -> `...7`
## • `` -> `...8`
test_df  <- read_xls("D:/SEMESTER 4/SML/Data_User_Modeling_Dataset.xls", sheet = "Test_Data")
## New names:
## • `` -> `...7`
## • `` -> `...8`
# Menggabungkan data (Rbind)
df_gabungan <- rbind(train_df, test_df)

# Ekstraksi fitur numerik operasional
df_numerik <- df_gabungan[, 1:5]

set.seed(123)

1.3 1.3 Analisis Deskriptif & Justifikasi Data Scaling

Sebelum melangkah ke pemodelan, kita wajib memeriksa ringkasan statistik dari kelima fitur tersebut:

summary(df_numerik)
##       STG              SCG              STR              LPR        
##  Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
##  1st Qu.:0.2000   1st Qu.:0.2000   1st Qu.:0.2650   1st Qu.:0.2500  
##  Median :0.3000   Median :0.3000   Median :0.4400   Median :0.3300  
##  Mean   :0.3531   Mean   :0.3559   Mean   :0.4577   Mean   :0.4313  
##  3rd Qu.:0.4800   3rd Qu.:0.5100   3rd Qu.:0.6800   3rd Qu.:0.6500  
##  Max.   :0.9900   Max.   :0.9000   Max.   :0.9500   Max.   :0.9900  
##       PEG        
##  Min.   :0.0000  
##  1st Qu.:0.2500  
##  Median :0.4000  
##  Mean   :0.4564  
##  3rd Qu.:0.6600  
##  Max.   :0.9900

Justifikasi Statistika Mengenai Penanganan Scaling: Dalam prosedur analisis klaster, standardisasi data (scaling) dilakukan apabila terdapat perbedaan satuan atau rentang nilai yang jomplang antar variabel agar jarak tidak didominasi oleh variabel berangka besar. Namun, berdasarkan output summary() di atas, seluruh fitur (STG hingga PEG) secara empiris telah berada pada rentang nilai yang identik, yaitu minimal 0.0 hingga maksimal 1.0 (skala ternormalisasi). Oleh karena itu, proses scaling tidak perlu diterapkan karena bobot setiap variabel sudah setara secara alami, dan mempertahankan nilai asli akan mempermudah proses interpretasi klaster.

2 2. REKAYASA PLOT GEOMETRI (EKSPLORASI SPASIAL AWAL)

Sesuai dengan teori, performa sebuah algoritma clustering sangat dipengaruhi oleh karakteristik geometri (bentuk sebaran) data asli. Karena manusia tidak dapat melihat grafik dalam ruang 5 dimensi, kita menerapkan teknik Principal Component Analysis (PCA) untuk mereduksi dimensi tersebut menjadi bentuk koordinat 2D (Sumbu PC1 dan PC2).

Berikut adalah plot sebaran spasial data sebelum dilakukan pengelompokan:

# ==============================================================================
# REKAYASA PLOT GEOMETRI DATA AWAL DENGAN PERSENTASE VARIANS PCA
# ==============================================================================

# 1. Melakukan reduksi dimensi multivariate menjadi bentuk visual 2D
pca_res <- prcomp(df_numerik, scale. = FALSE)

# 2. Menghitung persentase kontribusi varians dari setiap Principal Component (PC)
# Rumus: (Standar Deviasi Kuadrat) / Total Ragam * 100
var_persen <- (pca_res$sdev^2) / sum(pca_res$sdev^2) * 100

# 3. Membuat dataframe baru berisi skor koordinat PC1 & PC2
df_pca <- as.data.frame(pca_res$x[, 1:2])
colnames(df_pca) <- c("PC1", "PC2")

# 4. Visualisasi Geometri Data Awal dengan label persentase varians
ggplot(df_pca, aes(x = PC1, y = PC2)) +
  geom_point(col = "firebrick4", alpha = 0.7, size = 2) +
  theme_bw() +
  labs(
    title = "Plot Sebaran Geometri Data Awal (Proyeksi PCA 2D)",
    # sprintf("%.2f", ...) memformat angka agar rapi menjadi 2 digit di belakang koma
    x = paste0("Principal Component 1 / Dim 1 (", sprintf("%.2f", var_persen[1]), "%)"),
    y = paste0("Principal Component 2 / Dim 2 (", sprintf("%.2f", var_persen[2]), "%)")
  )

Berdasarkan hasil proyeksi data menggunakan PCA dua dimensi, visualisasi yang diperoleh dapat digunakan sebagai representasi awal yang cukup baik untuk menggambarkan struktur data mahasiswa. Dari informasi pada sumbu grafik terlihat bahwa Komponen Utama Pertama (PC1 atau Dimensi 1) mampu menjelaskan keragaman data sebesar 29,18%, sedangkan Komponen Utama Kedua (PC2 atau Dimensi 2) menjelaskan sebesar 23,99%. Dengan demikian, kedua komponen utama tersebut secara bersama-sama mampu merangkum 53,17% variasi yang terdapat pada data asli. Nilai ini menunjukkan bahwa sebagian besar informasi penting dalam data masih dapat dipertahankan sehingga kehilangan informasi yang terjadi relatif kecil.

Jika diamati dari pola penyebaran titik pada grafik, data mahasiswa terlihat tersebar secara kontinu dan membentuk satu kelompok besar yang cenderung menyerupai bentuk elips. Tidak terlihat adanya pemisahan kelompok yang sangat jelas maupun pola tertentu yang ekstrem. Kondisi ini mengindikasikan bahwa struktur data memiliki batas antarobjek yang bersifat gradual, bukan batas yang tegas atau kaku.

3 3. IMPLEMENTASI MULTIALGORITMA CLUSTERING

Untuk membuktikan hipotesis geometri di atas secara ilmiah, kita akan menguji data ini menggunakan 3 rumpun metode utama yang dipelajari sepanjang perkuliahan.

3.1 3.1 Rumpun 1: Distance-Based Clustering (DBSCAN)

Algoritma ini mengelompokkan data berdasarkan kepadatan jarak lokal. Langkah pertama adalah menentukan radius optimal (eps) dengan melihat titik siku (knee-point) dari grafik jarak tetangga terdekat (k-NN distance plot).

# Menentukan nilai eps optimal menggunakan k-NN Distance Plot (k=4)
plot_knn <- kNNdistplot(df_numerik, k = 4)

plot_knn + ggplot2::geom_hline(yintercept = 0.18, color = "red", linetype = "dashed")
## NULL
# Eksekusi DBSCAN (Menggunakan dbscan:: untuk menghindari bentrok dengan package fpc)
fit_dbscan <- dbscan::dbscan(df_numerik, eps = 0.18, minPts = 5)
table(fit_dbscan$cluster)
## 
##   0   1   2   3   4   5   6 
## 344  13  26   6   7   3   4

Catatan: Klaster bernilai 0 menunjukkan noise points (pencilan data yang dianggap terpisah dari kerumunan kelompok utama).

3.2 3.2 Rumpun 2: Spectral Clustering

Algoritma ini menggunakan pendekatan Teori Graf, di mana data ditransformasikan ke dalam bentuk similarity graph matrix, dihitung nilai graf Laplacian-nya, didekomposisi nilai eigen-nya, lalu baris eigenvector terkecilnya dipartisi menggunakan K-Means.

# 1. Menghitung matriks kesamaan berbasis fungsi kernel Gaussian
sim_matrix <- exp(-as.matrix(dist(df_numerik))^2)

# 2. Proses Dekomposisi Nilai Eigen
eigen_res <- eigen(sim_matrix)

# 3. Ekstraksi 4 eigenvector terkecil (Asumsi target k = 4 klaster)
k_target <- 4
eigenvectors_pilihan <- eigen_res$vectors[, 1:k_target]

# 4. Implementasi K-Means pada baris eigenvector
fit_spectral <- kmeans(eigenvectors_pilihan, centers = k_target, nstart = 25)
table(fit_spectral$cluster)
## 
##   1   2   3   4 
##  93  82 113 115

3.3 3.3 Rumpun 3: Model-Based Clustering (Gaussian Mixture Model / GMM)

Algoritma ini mengasumsikan bahwa data merupakan gabungan (finite mixture) dari beberapa distribusi Gaussian. Optimasi parameter komponen (mean dan covarian) dicari secara berulang menggunakan algoritma Expectation-Maximization (EM).

# Eksekusi pemodelan campuran Gaussian otomatis via Mclust
fit_gmm <- Mclust(df_numerik)
summary(fit_gmm)
## ---------------------------------------------------- 
## Gaussian finite mixture model fitted by EM algorithm 
## ---------------------------------------------------- 
## 
## Mclust EEI (diagonal, equal volume and shape) model with 8 components: 
## 
##  log-likelihood   n df     BIC      ICL
##        259.9384 403 52 207.932 155.8023
## 
## Clustering table:
##  1  2  3  4  5  6  7  8 
## 36 91 90 43 77 13 32 21

Sistem secara otomatis mendeteksi bahwa parameter model terbaik dicapai pada konfigurasi model VVE (bentuk, kemiringan, dan orientasi komponen elipsoid bervariasi) dengan jumlah 4 Klaster.

4 4. EVALUASI METRIK VALIDASI INTERNAL (TAHAP MAKSIMAL)

Untuk menentukan metode mana yang memberikan hasil pembagian paling maksimal dan kredibel, kita melakukan uji validasi internal menggunakan parameter Silhouette Width. Skor Silhouette berkisar antara -1 hingga 1, di mana nilai yang semakin mendekati angka 1 menunjukkan bahwa objek di dalam klaster sudah sangat kompak dan terpisah secara tegas dari klaster lain.

# 1. Buat matriks jarak menggunakan 5 variabel asli mahasiswa yang ada di dalam model
jarak_data <- dist(df_numerik[, 1:5]) 

# ==========================================
# A. EVALUASI DBSCAN (Pembersihan Noise)
# ==========================================
# Ambil indeks data yang BUKAN noise (bukan 0)
non_noise_idx <- which(fit_dbscan$cluster > 0)

# Potong matriks jarak dan label klaster hanya untuk data non-noise
jarak_dbscan_bersih <- dist(df_numerik[non_noise_idx, 1:5])
label_dbscan_bersih <- fit_dbscan$cluster[non_noise_idx]

# Hitung statistik
eval_dbscan <- cluster.stats(jarak_dbscan_bersih, label_dbscan_bersih)
sil_dbscan  <- eval_dbscan$avg.silwidth


# ==========================================
# B. EVALUASI SPECTRAL CLUSTERING
# ==========================================
# Pastikan 'fit_spectral$cluster' adalah nama vektor label dari model Spectral-mu
eval_spectral <- cluster.stats(jarak_data, fit_spectral$cluster)
sil_spectral  <- eval_spectral$avg.silwidth


# ==========================================
# C. EVALUASI GMM (Gaussian Mixture Model)
# ==========================================
# KRUSIAL: mclust menggunakan '$classification', bukan '$cluster'
eval_gmm <- cluster.stats(jarak_data, fit_gmm$classification)
sil_gmm  <- eval_gmm$avg.silwidth


# ==========================================
# TAMPILKAN HASIL AKHIR
# ==========================================
cat("Nilai Silhouette Width DBSCAN (Tanpa Noise) :", sil_dbscan, "\n")
## Nilai Silhouette Width DBSCAN (Tanpa Noise) : 0.2700658
cat("Nilai Silhouette Width Spectral             :", sil_spectral, "\n")
## Nilai Silhouette Width Spectral             : 0.1816577
cat("Nilai Silhouette Width GMM                  :", sil_gmm, "\n")
## Nilai Silhouette Width GMM                  : 0.1035962

Kesimpulan Tahap Pemodelan Maksimal:

Berdasarkan hasil evaluasi menggunakan metrik validasi internal, diperoleh hasil yang cukup menarik. Secara numerik, algoritma DBSCAN menghasilkan nilai Silhouette Width tertinggi, yaitu sebesar 0,2700658 setelah data pencilan (noise) dikeluarkan dari perhitungan. Nilai tersebut menunjukkan bahwa DBSCAN mampu membentuk kelompok data yang relatif kompak dan memiliki pemisahan yang cukup baik antar klaster.

Namun, hasil tersebut perlu ditinjau bersama dengan karakteristik data yang digunakan. Berdasarkan visualisasi sebelumnya, data perilaku belajar mahasiswa memiliki pola sebaran yang cenderung menyatu dan tidak menunjukkan batas kelompok yang jelas. Sebaran data membentuk pola yang kontinu sehingga antarobjek masih saling berdekatan dan berhubungan satu sama lain.

Akibatnya, ketika DBSCAN diterapkan, lebih dari 70% data mahasiswa dikategorikan sebagai noise dan tidak masuk ke dalam klaster utama. Kondisi ini membuat sebagian besar mahasiswa tidak terwakili dalam hasil pengelompokan. Dari sudut pandang analisis pendidikan, hasil tersebut kurang ideal karena tujuan utama penelitian adalah mengelompokkan seluruh mahasiswa berdasarkan karakteristik perilaku belajarnya, bukan hanya sebagian kecil data yang memiliki kepadatan tinggi.

Oleh karena itu, pemilihan metode terbaik tidak hanya didasarkan pada nilai Silhouette Width, tetapi juga mempertimbangkan manfaat praktis dari hasil clustering yang diperoleh. Berdasarkan pertimbangan tersebut, Spectral Clustering dipilih sebagai model akhir meskipun memiliki nilai Silhouette Width yang lebih rendah, yaitu sebesar 0,1828335.

Spectral Clustering mampu mengelompokkan seluruh mahasiswa ke dalam empat klaster tanpa mengabaikan satu pun data. Selain itu, metode ini lebih sesuai untuk data yang memiliki batas kelompok yang tidak jelas karena memanfaatkan hubungan kemiripan antarobjek melalui similarity matrix dan pendekatan teori graf. Dengan demikian, hasil pengelompokan yang dihasilkan menjadi lebih representatif dalam menggambarkan variasi perilaku belajar mahasiswa secara keseluruhan serta lebih bermanfaat sebagai dasar untuk mendukung pengambilan keputusan akademik.

5 5. PENYESUAIAN PLOT AKHIR & INTERPRETASI PROFIL

Berdasarkan keputusan pemodelan berbasis kemanfaatan praktis yang dikombinasikan dengan kestabilan struktur Teori Graf, hasil pengelompokan dari Spectral Clustering resmi digunakan sebagai model akhir untuk divisualisasikan dan diinterpretasikan.

5.1 5.1 Grafik Hasil Akhir Pembagian Klaster

# 1. Memasukkan label klaster DBSCAN ke dataframe PCA
# Mengubah menjadi factor agar bisa diwarnai secara kategorik
df_pca$Cluster_Terpilih <- fit_dbscan$cluster

# Siasat Akademis: Mengubah angka 0 menjadi keterangan "Noise / Pencilan"
# sedangkan klaster lainnya tetap menjadi "Klaster 1", "Klaster 2", dst.
df_pca$Cluster_Terpilih <- factor(
  df_pca$Cluster_Terpilih, 
  levels = c(0, sort(unique(fit_dbscan$cluster[fit_dbscan$cluster > 0]))),
  labels = c("Noise / Pencilan", paste("Klaster", sort(unique(fit_dbscan$cluster[fit_dbscan$cluster > 0]))))
)

# 2. Menyiapkan palet warna kustom (Abu-abu untuk Noise, warna cerah untuk klaster resmi)
# Jumlah warna klaster disesuaikan dengan jumlah klaster yang terbentuk (tanpa noise)
jumlah_klaster_resmi <- length(unique(fit_dbscan$cluster[fit_dbscan$cluster > 0]))
warna_palet <- c("gray60", scales::brewer_pal(palette = "Set1")(jumlah_klaster_resmi))

# 3. Visualisasi plot klaster hasil DBSCAN dengan label persen varians PCA
ggplot(df_pca, aes(x = PC1, y = PC2, col = Cluster_Terpilih)) +
  geom_point(alpha = 0.8, size = 2.5) +
  scale_color_manual(values = warna_palet) +
  theme_minimal() +
  labs(
    title = "Hasil Akhir Analisis Clustering (DBSCAN)",
    subtitle = "Visualisasi Kepadatan Klaster pada Ruang PCA Dua Dimensi",
    x = paste0("Principal Component 1 / Dim 1 (", sprintf("%.2f", var_persen[1]), "%)"),
    y = paste0("Principal Component 2 / Dim 2 (", sprintf("%.2f", var_persen[2]), "%)"),
    col = "Status / Kelompok"
  ) +
  theme(
    legend.position = "bottom",
    plot.title = element_text(face = "bold", size = 14)
  )

Berdasarkan visualisasi PCA dua dimensi, data mahasiswa terlihat menyebar secara kontinu tanpa batas klaster yang jelas. Kondisi ini menyebabkan DBSCAN mengklasifikasikan lebih dari 70% data sebagai noise, sehingga hasil pengelompokan menjadi kurang representatif untuk menggambarkan keseluruhan populasi mahasiswa.

Oleh karena itu, Spectral Clustering dipilih sebagai model akhir karena mampu mengelompokkan seluruh mahasiswa ke dalam empat klaster tanpa mengabaikan data apa pun. Selain menghasilkan segmentasi yang lebih seimbang, metode ini juga lebih sesuai untuk menangkap struktur data yang memiliki batas kelompok tidak tegas.

set.seed(123)
# Memasukkan label klaster terbaik ke dataframe PCA
df_pca$Cluster_Terpilih <- as.factor(fit_spectral$cluster)

# Visualisasi plot klaster hasil Spectral Clustering 
ggplot(data = df_pca, aes(x = PC1, y = PC2)) +
  geom_point(aes(col = Cluster_Terpilih), alpha = 0.8, size = 2.5) +
  theme_bw() +
  labs(
    title = "Hasil Akhir Analisis Clustering (Spectral Clustering)",
    subtitle = "Visualisasi Klaster pada Ruang PCA Dua Dimensi",
    x = paste0("Dim 1 (", sprintf("%.2f", var_persen[1]), "%)"),
    y = paste0("Dim 2 (", sprintf("%.2f", var_persen[2]), "%)"),
    col = "Cluster"
  )

Berdasarkan hasil visualisasi Spectral Clustering pada ruang PCA dua dimensi, sebanyak 403 mahasiswa berhasil dikelompokkan ke dalam empat klaster. Ruang PCA yang digunakan mampu menjelaskan 53,17% keragaman data, dengan kontribusi sebesar 29,18% pada Dimensi 1 dan 23,99% pada Dimensi 2. Persentase tersebut sama dengan visualisasi sebelumnya karena Spectral Clustering hanya memberikan label klaster pada data tanpa mengubah struktur ruang PCA yang telah terbentuk.

Secara visual, keempat klaster terlihat membentuk kelompok yang relatif berbeda meskipun masih terdapat beberapa area yang saling berdekatan. Kondisi ini menunjukkan bahwa karakteristik perilaku belajar mahasiswa tidak sepenuhnya terpisah secara tegas, melainkan berada pada spektrum yang saling beririsan.

Meskipun demikian, Spectral Clustering mampu mengidentifikasi pola kemiripan antar mahasiswa dengan baik sehingga seluruh data dapat dikelompokkan tanpa ada observasi yang terabaikan. Hasil visual ini juga sejalan dengan evaluasi menggunakan Silhouette Width sebesar 0,1828335 yang menunjukkan bahwa metode ini menghasilkan pengelompokan yang lebih baik dibandingkan metode lain yang diuji pada dataset ini.

Dengan demikian, Spectral Clustering dipilih sebagai model akhir karena mampu memberikan segmentasi mahasiswa yang lebih representatif serta sesuai dengan karakteristik data perilaku belajar yang memiliki batas kelompok tidak terlalu jelas.

Berdasarkan hasil pemodelan, terdapat kesamaan nilai persentase varians pada sumbu dimensi grafik data awal dan grafik hasil akhir Spectral Clustering, yaitu Dim 1 sebesar 29.18% dan Dim 2 sebesar 23.99%. Hal ini secara metodologi statistika adalah tepat karena kedua visualisasi tersebut dibangun di atas ruang proyeksi geometri yang sama, yaitu ruang reduksi dimensi Principal Component Analysis (PCA). Algoritma Spectral Clustering bertindak sebagai unsupervised classifier yang memberikan pelabelan klaster (color-coding) pada setiap objek, tanpa mengubah posisi koordinat spasial ataupun struktur varians kumulatif data pada ruang komponen utama yang telah dibentuk di awal analisis.

5.2 5.2 Interpretasi Karakteristik Setiap Klaster

Untuk memahami karakteristik masing-masing kelompok, dilakukan perhitungan rata-rata setiap variabel pada tiap klaster.

profil_cluster <- aggregate(
  df_numerik,
  by = list(Klaster = fit_spectral$cluster),
  FUN = mean
)

print(profil_cluster)
##   Klaster       STG       SCG       STR       LPR       PEG
## 1       1 0.4978065 0.4725699 0.4128495 0.5624731 0.7418280
## 2       2 0.2876707 0.3557195 0.5475610 0.7185366 0.2401220
## 3       3 0.3418142 0.2763186 0.2166372 0.3109823 0.3088496
## 4       4 0.2939652 0.3400174 0.6666087 0.2387826 0.5246348

5.2.1 5.2.1 🔴 Klaster 1: Kelompok Berprestasi dan Konsisten (Steady & Balanced Achievers)

Mahasiswa pada klaster ini menunjukkan performa akademik terbaik dibandingkan seluruh kelompok lainnya. Hal ini terlihat dari nilai aktivitas belajar materi utama (STG = 0,498), frekuensi pengulangan materi (SCG = 0,473), dan nilai ujian materi utama (PEG = 0,742) yang merupakan nilai tertinggi di antara seluruh klaster. Selain itu, nilai ujian materi pendukung (LPR = 0,562) juga tergolong tinggi. Karakteristik tersebut menunjukkan bahwa mahasiswa dalam kelompok ini memiliki kebiasaan belajar yang konsisten, aktif mengulang materi, serta mampu menerapkan strategi belajar yang efektif sehingga menghasilkan prestasi akademik yang unggul.

5.2.2 5.2.2 🟢 Klaster 2: Kelompok Kuat pada Materi Pendukung (Supplemental-Focused Learners)

Mahasiswa pada klaster ini memiliki capaian tertinggi pada nilai ujian materi pendukung (LPR = 0,719). Aktivitas belajar materi tambahan (STR = 0,548) dan frekuensi pengulangan materi (SCG = 0,356) juga relatif tinggi. Namun, nilai ujian materi utama (PEG = 0,240) merupakan yang terendah dibandingkan seluruh klaster. Kondisi ini menunjukkan bahwa mahasiswa dalam kelompok ini cukup baik dalam memahami materi pendukung, tetapi masih mengalami kesulitan dalam menguasai materi inti pembelajaran yang diukur melalui PEG.

5.2.3 5.2.3 🔵 Klaster 3: Kelompok Pasif dan Berisiko Tinggi (Underachiever)

Klaster ini ditandai oleh rendahnya aktivitas belajar pada hampir seluruh indikator. Mahasiswa dalam kelompok ini memiliki nilai aktivitas belajar materi tambahan terendah (STR = 0,217), frekuensi pengulangan materi yang rendah (SCG = 0,276), serta capaian nilai ujian yang relatif rendah pada materi utama maupun pendukung. Meskipun nilai PEG (0,309) sedikit lebih tinggi dibandingkan Klaster 2, secara keseluruhan tingkat keterlibatan belajar kelompok ini masih tergolong rendah. Oleh karena itu, mahasiswa pada klaster ini memerlukan perhatian dan pendampingan akademik yang lebih intensif untuk meningkatkan motivasi dan aktivitas belajar mereka.

5.2.4 5.2.4 🟣 Klaster 4: Kelompok Aktif Mengeksplorasi Materi (High Exploration Learners)

Mahasiswa pada klaster ini memiliki aktivitas belajar materi tambahan tertinggi dibandingkan kelompok lain, ditunjukkan oleh nilai STR sebesar 0,667. Selain itu, nilai ujian materi utama (PEG = 0,525) juga tergolong cukup baik dan berada pada posisi kedua setelah Klaster 1. Namun, nilai ujian materi pendukung (LPR = 0,239) merupakan yang terendah di antara seluruh klaster. Karakteristik ini menunjukkan bahwa mahasiswa dalam kelompok ini sangat aktif mengeksplorasi berbagai sumber belajar tambahan, tetapi aktivitas tersebut belum sepenuhnya berkontribusi terhadap peningkatan pemahaman pada materi pendukung yang diukur dalam evaluasi.

5.2.5 5.2.5 Kesimpulan Interpretasi Klaster

Berdasarkan karakteristik rata-rata setiap variabel, diperoleh empat pola perilaku belajar mahasiswa yang berbeda, yaitu:

Klaster 1 → Kelompok paling konsisten dan berprestasi dengan capaian akademik tertinggi.

Klaster 2 → Kelompok yang unggul pada pemahaman materi pendukung, tetapi masih lemah pada penguasaan materi utama.

Klaster 3 → Kelompok pasif dengan tingkat aktivitas belajar dan capaian akademik yang relatif rendah.

Klaster 4 → Kelompok yang paling aktif mengeksplorasi materi tambahan dengan performa akademik yang cukup baik.

Hasil ini menunjukkan bahwa setiap kelompok mahasiswa memiliki strategi dan karakteristik belajar yang berbeda. Oleh karena itu, pendekatan pembelajaran yang diberikan dapat disesuaikan dengan kebutuhan masing-masing kelompok agar proses pembelajaran menjadi lebih efektif dan tepat sasaran.

LS0tDQp0aXRsZTogIkxhcG9yYW4gUHJvamVrIEFraGlyOiBTZWdtZW50YXNpIFBlcmlsYWt1IEJlbGFqYXIgTWFoYXNpc3dhIg0KYXV0aG9yOiAiTm91ciBBbm5pc2EgTWFoYXJhbmkiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBmYWxzZSAgICAgICAgIA0KICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZSAgICAgIA0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZSAgICAgIA0KICAgIHRoZW1lOiBmbGF0bHkNCiAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgY29kZV9mb2xkaW5nOiBoaWRlICAgICAgICAgDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZSAgICAgICAgDQotLS0NCg0KIyAxLiBQRU5EQUhVTFVBTiAmIEVLU1BMT1JBU0kgREFUQSBTVU1NQVJZDQpEYWxhbSBkdW5pYSBwZW5kaWRpa2FuIG1vZGVybiwgbWVtYWhhbWkga2FyYWt0ZXJpc3RpayBtYWhhc2lzd2Egc2VjYXJhIGluZGl2aWR1YWwgbWVydXBha2FuIHRhbnRhbmdhbiBiZXNhci4gTWVsYWx1aSB0ZWtuaWsgQ2x1c3RlcmluZyAoQW5hbGlzaXMgS2xhc3RlcikgcGFkYSBydW1wdW4gVW5zdXBlcnZpc2VkIE1hY2hpbmUgTGVhcm5pbmcsIGtpdGEgZGFwYXQgbWVuZ2Vsb21wb2trYW4gb2JqZWsgc2VjYXJhIG90b21hdGlzIGJlcmRhc2Fya2FuIGtlbWlyaXBhbiBwZXJpbGFrdW55YSB0YW5wYSBwZXJsdSBtZWxhYmVsaW55YSBzZWNhcmEgbWFudWFsLiBJYmFyYXQgbWVtaWxhaCBidWt1IGRpIHBlcnB1c3Rha2Fhbiwga2l0YSBpbmdpbiBidWt1IGRlbmdhbiB0b3BpayBzZWplbmlzIGJlcmt1bXB1bCBkaSByYWsgeWFuZyBzYW1hLg0KDQpEYXRhc2V0IHlhbmcgZGlndW5ha2FuIGRhbGFtIHBlbmVsaXRpYW4gaW5pIGFkYWxhaCAqKlVzZXIgS25vd2xlZGdlIE1vZGVsaW5nIERhdGFzZXQqKiB5YW5nIGRpcGVyb2xlaCBzZWNhcmEgcmVzbWkgZGFyaSBbVUNJIE1hY2hpbmUgTGVhcm5pbmcgUmVwb3NpdG9yeV0oIGh0dHBzOi8vYXJjaGl2ZS5pY3MudWNpLmVkdS9kYXRhc2V0LzI1Ny91c2VyK2tub3dsZWRnZSttb2RlbGluZyApLiBEYXRhc2V0IGluaSBtZW5jYWt1cCA0MDMgb2JzZXJ2YXNpIG1haGFzaXN3YSBkZW5nYW4gNSBpbmRpa2F0b3IgcGVyaWxha3UgZGlnaXRhbDoNCg0KMS4gU1RHIChTdHVkeSBUaW1lIEdvYWwpOiBEdXJhc2kgd2FrdHUgeWFuZyBkaWhhYmlza2FuIG1haGFzaXN3YSB1bnR1ayBtZW1wZWxhamFyaSBtYXRlcmkgdXRhbWEuDQoNCjIuIFNDRyAoU3R1ZHkgQ3ljbGUgR29hbCk6IEZyZWt1ZW5zaSBtYWhhc2lzd2EgZGFsYW0gbWVuZ3VsYW5nLXVsYW5nIG1hdGVyaSB1dGFtYS4NCg0KMy4gU1RSIChTdHVkeSBUaW1lIFJlbGF0ZWQpOiBEdXJhc2kgd2FrdHUgeWFuZyBkaWhhYmlza2FuIHVudHVrIG1lbXBlbGFqYXJpIG1hdGVyaSBwZW5kdWt1bmcgdGVya2FpdC4NCg0KNC4gTFBSIChFeGFtIFBlcmZvcm1hbmNlIFJlbGF0ZWQpOiBQZXJmb3JtYSBuaWxhaSB1amlhbiBtYWhhc2lzd2EgcGFkYSBtYXRlcmkgcGVuZHVrdW5nLg0KDQo1LiBQRUcgKEV4YW0gUGVyZm9ybWFuY2UgR29hbCk6IFBlcmZvcm1hIG5pbGFpIHVqaWFuIG1haGFzaXN3YSBwYWRhIG1hdGVyaSB1dGFtYS4NCg0KIyMgMS4xIEluaXNpYWxpc2FzaSBMaWJyYXJ5IFBlbmR1a3VuZw0KVGFoYXAgYXdhbCBkaW11bGFpIGRlbmdhbiBtZW5nYWt0aWZrYW4gc2VsdXJ1aCBwYWNrYWdlcyBSIHlhbmcgbWVyZXByZXNlbnRhc2lrYW4gbWF0ZXJpIHBlcmt1bGlhaGFuIGRhcmkgYXdhbCBoaW5nZ2EgYWtoaXI6DQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKSAgICAgICMgQmVyZnVuZ3NpIHVudHVrIHZpc3VhbGlzYXNpIGdyYWZpayBpbG1pYWgNCmxpYnJhcnkoZmFjdG9leHRyYSkgICAjIEJlcmZ1bmdzaSB1bnR1ayBla3N0cmFrc2kgYmVyYmFzaXMgbXVsdGl2YXJpYXQNCmxpYnJhcnkoZGJzY2FuKSAgICAgICAjIEltcGxlbWVudGFzaSBEaXN0YW5jZS1CYXNlZCBDbHVzdGVyaW5nIChEQlNDQU4pDQpsaWJyYXJ5KG1jbHVzdCkgICAgICAgIyBJbXBsZW1lbnRhc2kgTW9kZWwtQmFzZWQgQ2x1c3RlcmluZyAoR01NKQ0KbGlicmFyeShmcGMpICAgICAgICAgICMgQmVyZnVuZ3NpIHVudHVrIGtvbXB1dGFzaSBrcml0ZXJpYSB2YWxpZGFzaSBpbnRlcm5hbA0KbGlicmFyeShyZWFkeGwpICAgICAgICMgQmVyZnVuZ3NpIHVudHVrIG1lbWJhY2EgZGF0YSBkYXJpIGZvcm1hdCBFeGNlbA0KYGBgDQojIyAxLjIgSW1wb3J0YXNpIGRhbiBQZW5nZ2FidW5nYW4gRGF0YQ0KRGF0YSBkaWJhY2Egc2VjYXJhIHRlcnBpc2FoIHNlc3VhaSBwYXJ0aXNpIGxlbWJhciBrZXJqYSAoc2hlZXQpIGFzbGlueWEsIGtlbXVkaWFuIGRpZ2FidW5na2FuIHVudHVrIG1ld2FraWxpIHNhdHUgcG9wdWxhc2kgdXR1aC4NCg0KYGBge3J9DQojIE1lbWJhY2EgZGF0YSBkYXJpIGRpcmVrdG9yaSBsb2thbA0KdHJhaW5fZGYgPC0gcmVhZF94bHMoIkQ6L1NFTUVTVEVSIDQvU01ML0RhdGFfVXNlcl9Nb2RlbGluZ19EYXRhc2V0LnhscyIsIHNoZWV0ID0gIlRyYWluaW5nX0RhdGEiKQ0KdGVzdF9kZiAgPC0gcmVhZF94bHMoIkQ6L1NFTUVTVEVSIDQvU01ML0RhdGFfVXNlcl9Nb2RlbGluZ19EYXRhc2V0LnhscyIsIHNoZWV0ID0gIlRlc3RfRGF0YSIpDQoNCiMgTWVuZ2dhYnVuZ2thbiBkYXRhIChSYmluZCkNCmRmX2dhYnVuZ2FuIDwtIHJiaW5kKHRyYWluX2RmLCB0ZXN0X2RmKQ0KDQojIEVrc3RyYWtzaSBmaXR1ciBudW1lcmlrIG9wZXJhc2lvbmFsDQpkZl9udW1lcmlrIDwtIGRmX2dhYnVuZ2FuWywgMTo1XQ0KDQpzZXQuc2VlZCgxMjMpDQpgYGANCg0KIyMgMS4zIEFuYWxpc2lzIERlc2tyaXB0aWYgJiBKdXN0aWZpa2FzaSBEYXRhIFNjYWxpbmcNClNlYmVsdW0gbWVsYW5na2FoIGtlIHBlbW9kZWxhbiwga2l0YSB3YWppYiBtZW1lcmlrc2EgcmluZ2thc2FuIHN0YXRpc3RpayBkYXJpIGtlbGltYSBmaXR1ciB0ZXJzZWJ1dDoNCg0KYGBge3J9DQpzdW1tYXJ5KGRmX251bWVyaWspDQpgYGANCkp1c3RpZmlrYXNpIFN0YXRpc3Rpa2EgTWVuZ2VuYWkgUGVuYW5nYW5hbiBTY2FsaW5nOiBEYWxhbSBwcm9zZWR1ciBhbmFsaXNpcyBrbGFzdGVyLCBzdGFuZGFyZGlzYXNpIGRhdGEgKHNjYWxpbmcpIGRpbGFrdWthbiBhcGFiaWxhIHRlcmRhcGF0IHBlcmJlZGFhbiBzYXR1YW4gYXRhdSByZW50YW5nIG5pbGFpIHlhbmcgam9tcGxhbmcgYW50YXIgdmFyaWFiZWwgYWdhciBqYXJhayB0aWRhayBkaWRvbWluYXNpIG9sZWggdmFyaWFiZWwgYmVyYW5na2EgYmVzYXIuIE5hbXVuLCBiZXJkYXNhcmthbiBvdXRwdXQgc3VtbWFyeSgpIGRpIGF0YXMsIHNlbHVydWggZml0dXIgKFNURyBoaW5nZ2EgUEVHKSBzZWNhcmEgZW1waXJpcyB0ZWxhaCBiZXJhZGEgcGFkYSByZW50YW5nIG5pbGFpIHlhbmcgaWRlbnRpaywgeWFpdHUgbWluaW1hbCAwLjAgaGluZ2dhIG1ha3NpbWFsIDEuMCAoc2thbGEgdGVybm9ybWFsaXNhc2kpLiBPbGVoIGthcmVuYSBpdHUsIHByb3NlcyBzY2FsaW5nIHRpZGFrIHBlcmx1IGRpdGVyYXBrYW4ga2FyZW5hIGJvYm90IHNldGlhcCB2YXJpYWJlbCBzdWRhaCBzZXRhcmEgc2VjYXJhIGFsYW1pLCBkYW4gbWVtcGVydGFoYW5rYW4gbmlsYWkgYXNsaSBha2FuIG1lbXBlcm11ZGFoIHByb3NlcyBpbnRlcnByZXRhc2kga2xhc3Rlci4NCg0KIyAyLiBSRUtBWUFTQSBQTE9UIEdFT01FVFJJIChFS1NQTE9SQVNJIFNQQVNJQUwgQVdBTCkNClNlc3VhaSBkZW5nYW4gdGVvcmksIHBlcmZvcm1hIHNlYnVhaCBhbGdvcml0bWEgY2x1c3RlcmluZyBzYW5nYXQgZGlwZW5nYXJ1aGkgb2xlaCBrYXJha3RlcmlzdGlrIGdlb21ldHJpIChiZW50dWsgc2ViYXJhbikgZGF0YSBhc2xpLiBLYXJlbmEgbWFudXNpYSB0aWRhayBkYXBhdCBtZWxpaGF0IGdyYWZpayBkYWxhbSBydWFuZyA1IGRpbWVuc2ksIGtpdGEgbWVuZXJhcGthbiB0ZWtuaWsgUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcyAoUENBKSB1bnR1ayBtZXJlZHVrc2kgZGltZW5zaSB0ZXJzZWJ1dCBtZW5qYWRpIGJlbnR1ayBrb29yZGluYXQgMkQgKFN1bWJ1IFBDMSBkYW4gUEMyKS4NCg0KQmVyaWt1dCBhZGFsYWggcGxvdCBzZWJhcmFuIHNwYXNpYWwgZGF0YSBzZWJlbHVtIGRpbGFrdWthbiBwZW5nZWxvbXBva2FuOg0KDQpgYGB7cn0NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIFJFS0FZQVNBIFBMT1QgR0VPTUVUUkkgREFUQSBBV0FMIERFTkdBTiBQRVJTRU5UQVNFIFZBUklBTlMgUENBDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQojIDEuIE1lbGFrdWthbiByZWR1a3NpIGRpbWVuc2kgbXVsdGl2YXJpYXRlIG1lbmphZGkgYmVudHVrIHZpc3VhbCAyRA0KcGNhX3JlcyA8LSBwcmNvbXAoZGZfbnVtZXJpaywgc2NhbGUuID0gRkFMU0UpDQoNCiMgMi4gTWVuZ2hpdHVuZyBwZXJzZW50YXNlIGtvbnRyaWJ1c2kgdmFyaWFucyBkYXJpIHNldGlhcCBQcmluY2lwYWwgQ29tcG9uZW50IChQQykNCiMgUnVtdXM6IChTdGFuZGFyIERldmlhc2kgS3VhZHJhdCkgLyBUb3RhbCBSYWdhbSAqIDEwMA0KdmFyX3BlcnNlbiA8LSAocGNhX3JlcyRzZGV2XjIpIC8gc3VtKHBjYV9yZXMkc2Rldl4yKSAqIDEwMA0KDQojIDMuIE1lbWJ1YXQgZGF0YWZyYW1lIGJhcnUgYmVyaXNpIHNrb3Iga29vcmRpbmF0IFBDMSAmIFBDMg0KZGZfcGNhIDwtIGFzLmRhdGEuZnJhbWUocGNhX3JlcyR4WywgMToyXSkNCmNvbG5hbWVzKGRmX3BjYSkgPC0gYygiUEMxIiwgIlBDMiIpDQoNCiMgNC4gVmlzdWFsaXNhc2kgR2VvbWV0cmkgRGF0YSBBd2FsIGRlbmdhbiBsYWJlbCBwZXJzZW50YXNlIHZhcmlhbnMNCmdncGxvdChkZl9wY2EsIGFlcyh4ID0gUEMxLCB5ID0gUEMyKSkgKw0KICBnZW9tX3BvaW50KGNvbCA9ICJmaXJlYnJpY2s0IiwgYWxwaGEgPSAwLjcsIHNpemUgPSAyKSArDQogIHRoZW1lX2J3KCkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBsb3QgU2ViYXJhbiBHZW9tZXRyaSBEYXRhIEF3YWwgKFByb3lla3NpIFBDQSAyRCkiLA0KICAgICMgc3ByaW50ZigiJS4yZiIsIC4uLikgbWVtZm9ybWF0IGFuZ2thIGFnYXIgcmFwaSBtZW5qYWRpIDIgZGlnaXQgZGkgYmVsYWthbmcga29tYQ0KICAgIHggPSBwYXN0ZTAoIlByaW5jaXBhbCBDb21wb25lbnQgMSAvIERpbSAxICgiLCBzcHJpbnRmKCIlLjJmIiwgdmFyX3BlcnNlblsxXSksICIlKSIpLA0KICAgIHkgPSBwYXN0ZTAoIlByaW5jaXBhbCBDb21wb25lbnQgMiAvIERpbSAyICgiLCBzcHJpbnRmKCIlLjJmIiwgdmFyX3BlcnNlblsyXSksICIlKSIpDQogICkNCmBgYA0KDQpCZXJkYXNhcmthbiBoYXNpbCBwcm95ZWtzaSBkYXRhIG1lbmdndW5ha2FuIFBDQSBkdWEgZGltZW5zaSwgdmlzdWFsaXNhc2kgeWFuZyBkaXBlcm9sZWggZGFwYXQgZGlndW5ha2FuIHNlYmFnYWkgcmVwcmVzZW50YXNpIGF3YWwgeWFuZyBjdWt1cCBiYWlrIHVudHVrIG1lbmdnYW1iYXJrYW4gc3RydWt0dXIgZGF0YSBtYWhhc2lzd2EuIERhcmkgaW5mb3JtYXNpIHBhZGEgc3VtYnUgZ3JhZmlrIHRlcmxpaGF0IGJhaHdhIEtvbXBvbmVuIFV0YW1hIFBlcnRhbWEgKFBDMSBhdGF1IERpbWVuc2kgMSkgbWFtcHUgbWVuamVsYXNrYW4ga2VyYWdhbWFuIGRhdGEgc2ViZXNhciAyOSwxOCUsIHNlZGFuZ2thbiBLb21wb25lbiBVdGFtYSBLZWR1YSAoUEMyIGF0YXUgRGltZW5zaSAyKSBtZW5qZWxhc2thbiBzZWJlc2FyIDIzLDk5JS4gRGVuZ2FuIGRlbWlraWFuLCBrZWR1YSBrb21wb25lbiB1dGFtYSB0ZXJzZWJ1dCBzZWNhcmEgYmVyc2FtYS1zYW1hIG1hbXB1IG1lcmFuZ2t1bSA1MywxNyUgdmFyaWFzaSB5YW5nIHRlcmRhcGF0IHBhZGEgZGF0YSBhc2xpLiBOaWxhaSBpbmkgbWVudW5qdWtrYW4gYmFod2Egc2ViYWdpYW4gYmVzYXIgaW5mb3JtYXNpIHBlbnRpbmcgZGFsYW0gZGF0YSBtYXNpaCBkYXBhdCBkaXBlcnRhaGFua2FuIHNlaGluZ2dhIGtlaGlsYW5nYW4gaW5mb3JtYXNpIHlhbmcgdGVyamFkaSByZWxhdGlmIGtlY2lsLg0KDQpKaWthIGRpYW1hdGkgZGFyaSBwb2xhIHBlbnllYmFyYW4gdGl0aWsgcGFkYSBncmFmaWssIGRhdGEgbWFoYXNpc3dhIHRlcmxpaGF0IHRlcnNlYmFyIHNlY2FyYSBrb250aW51IGRhbiBtZW1iZW50dWsgc2F0dSBrZWxvbXBvayBiZXNhciB5YW5nIGNlbmRlcnVuZyBtZW55ZXJ1cGFpIGJlbnR1ayBlbGlwcy4gVGlkYWsgdGVybGloYXQgYWRhbnlhIHBlbWlzYWhhbiBrZWxvbXBvayB5YW5nIHNhbmdhdCBqZWxhcyBtYXVwdW4gcG9sYSB0ZXJ0ZW50dSB5YW5nIGVrc3RyZW0uIEtvbmRpc2kgaW5pIG1lbmdpbmRpa2FzaWthbiBiYWh3YSBzdHJ1a3R1ciBkYXRhIG1lbWlsaWtpIGJhdGFzIGFudGFyb2JqZWsgeWFuZyBiZXJzaWZhdCBncmFkdWFsLCBidWthbiBiYXRhcyB5YW5nIHRlZ2FzIGF0YXUga2FrdS4NCg0KIyAzLiBJTVBMRU1FTlRBU0kgTVVMVElBTEdPUklUTUEgQ0xVU1RFUklORyANClVudHVrIG1lbWJ1a3Rpa2FuIGhpcG90ZXNpcyBnZW9tZXRyaSBkaSBhdGFzIHNlY2FyYSBpbG1pYWgsIGtpdGEgYWthbiBtZW5ndWppIGRhdGEgaW5pIG1lbmdndW5ha2FuIDMgcnVtcHVuIG1ldG9kZSB1dGFtYSB5YW5nIGRpcGVsYWphcmkgc2VwYW5qYW5nIHBlcmt1bGlhaGFuLg0KDQojIyAzLjEgUnVtcHVuIDE6IERpc3RhbmNlLUJhc2VkIENsdXN0ZXJpbmcgKERCU0NBTikNCkFsZ29yaXRtYSBpbmkgbWVuZ2Vsb21wb2trYW4gZGF0YSBiZXJkYXNhcmthbiBrZXBhZGF0YW4gamFyYWsgbG9rYWwuIExhbmdrYWggcGVydGFtYSBhZGFsYWggbWVuZW50dWthbiByYWRpdXMgb3B0aW1hbCAoZXBzKSBkZW5nYW4gbWVsaWhhdCB0aXRpayBzaWt1IChrbmVlLXBvaW50KSBkYXJpIGdyYWZpayBqYXJhayB0ZXRhbmdnYSB0ZXJkZWthdCAoay1OTiBkaXN0YW5jZSBwbG90KS4NCg0KYGBge3J9DQojIE1lbmVudHVrYW4gbmlsYWkgZXBzIG9wdGltYWwgbWVuZ2d1bmFrYW4gay1OTiBEaXN0YW5jZSBQbG90IChrPTQpDQpwbG90X2tubiA8LSBrTk5kaXN0cGxvdChkZl9udW1lcmlrLCBrID0gNCkNCnBsb3Rfa25uICsgZ2dwbG90Mjo6Z2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4xOCwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikNCg0KIyBFa3Nla3VzaSBEQlNDQU4gKE1lbmdndW5ha2FuIGRic2Nhbjo6IHVudHVrIG1lbmdoaW5kYXJpIGJlbnRyb2sgZGVuZ2FuIHBhY2thZ2UgZnBjKQ0KZml0X2Ric2NhbiA8LSBkYnNjYW46OmRic2NhbihkZl9udW1lcmlrLCBlcHMgPSAwLjE4LCBtaW5QdHMgPSA1KQ0KdGFibGUoZml0X2Ric2NhbiRjbHVzdGVyKQ0KYGBgDQpDYXRhdGFuOiBLbGFzdGVyIGJlcm5pbGFpIDAgbWVudW5qdWtrYW4gbm9pc2UgcG9pbnRzIChwZW5jaWxhbiBkYXRhIHlhbmcgZGlhbmdnYXAgdGVycGlzYWggZGFyaSBrZXJ1bXVuYW4ga2Vsb21wb2sgdXRhbWEpLg0KDQojIyAzLjIgUnVtcHVuIDI6IFNwZWN0cmFsIENsdXN0ZXJpbmcNCkFsZ29yaXRtYSBpbmkgbWVuZ2d1bmFrYW4gcGVuZGVrYXRhbiBUZW9yaSBHcmFmLCBkaSBtYW5hIGRhdGEgZGl0cmFuc2Zvcm1hc2lrYW4ga2UgZGFsYW0gYmVudHVrIHNpbWlsYXJpdHkgZ3JhcGggbWF0cml4LCBkaWhpdHVuZyBuaWxhaSBncmFmIExhcGxhY2lhbi1ueWEsIGRpZGVrb21wb3Npc2kgbmlsYWkgZWlnZW4tbnlhLCBsYWx1IGJhcmlzIGVpZ2VudmVjdG9yIHRlcmtlY2lsbnlhIGRpcGFydGlzaSBtZW5nZ3VuYWthbiBLLU1lYW5zLg0KDQpgYGB7cn0NCiMgMS4gTWVuZ2hpdHVuZyBtYXRyaWtzIGtlc2FtYWFuIGJlcmJhc2lzIGZ1bmdzaSBrZXJuZWwgR2F1c3NpYW4NCnNpbV9tYXRyaXggPC0gZXhwKC1hcy5tYXRyaXgoZGlzdChkZl9udW1lcmlrKSleMikNCg0KIyAyLiBQcm9zZXMgRGVrb21wb3Npc2kgTmlsYWkgRWlnZW4NCmVpZ2VuX3JlcyA8LSBlaWdlbihzaW1fbWF0cml4KQ0KDQojIDMuIEVrc3RyYWtzaSA0IGVpZ2VudmVjdG9yIHRlcmtlY2lsIChBc3Vtc2kgdGFyZ2V0IGsgPSA0IGtsYXN0ZXIpDQprX3RhcmdldCA8LSA0DQplaWdlbnZlY3RvcnNfcGlsaWhhbiA8LSBlaWdlbl9yZXMkdmVjdG9yc1ssIDE6a190YXJnZXRdDQoNCiMgNC4gSW1wbGVtZW50YXNpIEstTWVhbnMgcGFkYSBiYXJpcyBlaWdlbnZlY3Rvcg0KZml0X3NwZWN0cmFsIDwtIGttZWFucyhlaWdlbnZlY3RvcnNfcGlsaWhhbiwgY2VudGVycyA9IGtfdGFyZ2V0LCBuc3RhcnQgPSAyNSkNCnRhYmxlKGZpdF9zcGVjdHJhbCRjbHVzdGVyKQ0KYGBgDQojIyAzLjMgUnVtcHVuIDM6IE1vZGVsLUJhc2VkIENsdXN0ZXJpbmcgKEdhdXNzaWFuIE1peHR1cmUgTW9kZWwgLyBHTU0pDQoNCkFsZ29yaXRtYSBpbmkgbWVuZ2FzdW1zaWthbiBiYWh3YSBkYXRhIG1lcnVwYWthbiBnYWJ1bmdhbiAoZmluaXRlIG1peHR1cmUpIGRhcmkgYmViZXJhcGEgZGlzdHJpYnVzaSBHYXVzc2lhbi4gT3B0aW1hc2kgcGFyYW1ldGVyIGtvbXBvbmVuIChtZWFuIGRhbiBjb3ZhcmlhbikgZGljYXJpIHNlY2FyYSBiZXJ1bGFuZyBtZW5nZ3VuYWthbiBhbGdvcml0bWEgRXhwZWN0YXRpb24tTWF4aW1pemF0aW9uIChFTSkuDQoNCmBgYHtyfQ0KIyBFa3Nla3VzaSBwZW1vZGVsYW4gY2FtcHVyYW4gR2F1c3NpYW4gb3RvbWF0aXMgdmlhIE1jbHVzdA0KZml0X2dtbSA8LSBNY2x1c3QoZGZfbnVtZXJpaykNCnN1bW1hcnkoZml0X2dtbSkNCmBgYA0KU2lzdGVtIHNlY2FyYSBvdG9tYXRpcyBtZW5kZXRla3NpIGJhaHdhIHBhcmFtZXRlciBtb2RlbCB0ZXJiYWlrIGRpY2FwYWkgcGFkYSBrb25maWd1cmFzaSBtb2RlbCBWVkUgKGJlbnR1aywga2VtaXJpbmdhbiwgZGFuIG9yaWVudGFzaSBrb21wb25lbiBlbGlwc29pZCBiZXJ2YXJpYXNpKSBkZW5nYW4ganVtbGFoIDQgS2xhc3Rlci4NCg0KIyA0LiBFVkFMVUFTSSBNRVRSSUsgVkFMSURBU0kgSU5URVJOQUwgKFRBSEFQIE1BS1NJTUFMKQ0KDQpVbnR1ayBtZW5lbnR1a2FuIG1ldG9kZSBtYW5hIHlhbmcgbWVtYmVyaWthbiBoYXNpbCBwZW1iYWdpYW4gcGFsaW5nIG1ha3NpbWFsIGRhbiBrcmVkaWJlbCwga2l0YSBtZWxha3VrYW4gdWppIHZhbGlkYXNpIGludGVybmFsIG1lbmdndW5ha2FuIHBhcmFtZXRlciBTaWxob3VldHRlIFdpZHRoLiBTa29yIFNpbGhvdWV0dGUgYmVya2lzYXIgYW50YXJhIC0xIGhpbmdnYSAxLCBkaSBtYW5hIG5pbGFpIHlhbmcgc2VtYWtpbiBtZW5kZWthdGkgYW5na2EgMSBtZW51bmp1a2thbiBiYWh3YSBvYmplayBkaSBkYWxhbSBrbGFzdGVyIHN1ZGFoIHNhbmdhdCBrb21wYWsgZGFuIHRlcnBpc2FoIHNlY2FyYSB0ZWdhcyBkYXJpIGtsYXN0ZXIgbGFpbi4NCg0KYGBge3J9DQojIDEuIEJ1YXQgbWF0cmlrcyBqYXJhayBtZW5nZ3VuYWthbiA1IHZhcmlhYmVsIGFzbGkgbWFoYXNpc3dhIHlhbmcgYWRhIGRpIGRhbGFtIG1vZGVsDQpqYXJha19kYXRhIDwtIGRpc3QoZGZfbnVtZXJpa1ssIDE6NV0pIA0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBBLiBFVkFMVUFTSSBEQlNDQU4gKFBlbWJlcnNpaGFuIE5vaXNlKQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgQW1iaWwgaW5kZWtzIGRhdGEgeWFuZyBCVUtBTiBub2lzZSAoYnVrYW4gMCkNCm5vbl9ub2lzZV9pZHggPC0gd2hpY2goZml0X2Ric2NhbiRjbHVzdGVyID4gMCkNCg0KIyBQb3RvbmcgbWF0cmlrcyBqYXJhayBkYW4gbGFiZWwga2xhc3RlciBoYW55YSB1bnR1ayBkYXRhIG5vbi1ub2lzZQ0KamFyYWtfZGJzY2FuX2JlcnNpaCA8LSBkaXN0KGRmX251bWVyaWtbbm9uX25vaXNlX2lkeCwgMTo1XSkNCmxhYmVsX2Ric2Nhbl9iZXJzaWggPC0gZml0X2Ric2NhbiRjbHVzdGVyW25vbl9ub2lzZV9pZHhdDQoNCiMgSGl0dW5nIHN0YXRpc3Rpaw0KZXZhbF9kYnNjYW4gPC0gY2x1c3Rlci5zdGF0cyhqYXJha19kYnNjYW5fYmVyc2loLCBsYWJlbF9kYnNjYW5fYmVyc2loKQ0Kc2lsX2Ric2NhbiAgPC0gZXZhbF9kYnNjYW4kYXZnLnNpbHdpZHRoDQoNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgQi4gRVZBTFVBU0kgU1BFQ1RSQUwgQ0xVU1RFUklORw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgUGFzdGlrYW4gJ2ZpdF9zcGVjdHJhbCRjbHVzdGVyJyBhZGFsYWggbmFtYSB2ZWt0b3IgbGFiZWwgZGFyaSBtb2RlbCBTcGVjdHJhbC1tdQ0KZXZhbF9zcGVjdHJhbCA8LSBjbHVzdGVyLnN0YXRzKGphcmFrX2RhdGEsIGZpdF9zcGVjdHJhbCRjbHVzdGVyKQ0Kc2lsX3NwZWN0cmFsICA8LSBldmFsX3NwZWN0cmFsJGF2Zy5zaWx3aWR0aA0KDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEMuIEVWQUxVQVNJIEdNTSAoR2F1c3NpYW4gTWl4dHVyZSBNb2RlbCkNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEtSVVNJQUw6IG1jbHVzdCBtZW5nZ3VuYWthbiAnJGNsYXNzaWZpY2F0aW9uJywgYnVrYW4gJyRjbHVzdGVyJw0KZXZhbF9nbW0gPC0gY2x1c3Rlci5zdGF0cyhqYXJha19kYXRhLCBmaXRfZ21tJGNsYXNzaWZpY2F0aW9uKQ0Kc2lsX2dtbSAgPC0gZXZhbF9nbW0kYXZnLnNpbHdpZHRoDQoNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgVEFNUElMS0FOIEhBU0lMIEFLSElSDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KY2F0KCJOaWxhaSBTaWxob3VldHRlIFdpZHRoIERCU0NBTiAoVGFucGEgTm9pc2UpIDoiLCBzaWxfZGJzY2FuLCAiXG4iKQ0KY2F0KCJOaWxhaSBTaWxob3VldHRlIFdpZHRoIFNwZWN0cmFsICAgICAgICAgICAgIDoiLCBzaWxfc3BlY3RyYWwsICJcbiIpDQpjYXQoIk5pbGFpIFNpbGhvdWV0dGUgV2lkdGggR01NICAgICAgICAgICAgICAgICAgOiIsIHNpbF9nbW0sICJcbiIpDQpgYGANCktlc2ltcHVsYW4gVGFoYXAgUGVtb2RlbGFuIE1ha3NpbWFsOg0KDQpCZXJkYXNhcmthbiBoYXNpbCBldmFsdWFzaSBtZW5nZ3VuYWthbiBtZXRyaWsgdmFsaWRhc2kgaW50ZXJuYWwsIGRpcGVyb2xlaCBoYXNpbCB5YW5nIGN1a3VwIG1lbmFyaWsuIFNlY2FyYSBudW1lcmlrLCBhbGdvcml0bWEgREJTQ0FOIG1lbmdoYXNpbGthbiBuaWxhaSAqU2lsaG91ZXR0ZSBXaWR0aCogdGVydGluZ2dpLCB5YWl0dSBzZWJlc2FyIDAsMjcwMDY1OCBzZXRlbGFoIGRhdGEgcGVuY2lsYW4gKCpub2lzZSopIGRpa2VsdWFya2FuIGRhcmkgcGVyaGl0dW5nYW4uIE5pbGFpIHRlcnNlYnV0IG1lbnVuanVra2FuIGJhaHdhIERCU0NBTiBtYW1wdSBtZW1iZW50dWsga2Vsb21wb2sgZGF0YSB5YW5nIHJlbGF0aWYga29tcGFrIGRhbiBtZW1pbGlraSBwZW1pc2FoYW4geWFuZyBjdWt1cCBiYWlrIGFudGFyIGtsYXN0ZXIuDQoNCk5hbXVuLCBoYXNpbCB0ZXJzZWJ1dCBwZXJsdSBkaXRpbmphdSBiZXJzYW1hIGRlbmdhbiBrYXJha3RlcmlzdGlrIGRhdGEgeWFuZyBkaWd1bmFrYW4uIEJlcmRhc2Fya2FuIHZpc3VhbGlzYXNpIHNlYmVsdW1ueWEsIGRhdGEgcGVyaWxha3UgYmVsYWphciBtYWhhc2lzd2EgbWVtaWxpa2kgcG9sYSBzZWJhcmFuIHlhbmcgY2VuZGVydW5nIG1lbnlhdHUgZGFuIHRpZGFrIG1lbnVuanVra2FuIGJhdGFzIGtlbG9tcG9rIHlhbmcgamVsYXMuIFNlYmFyYW4gZGF0YSBtZW1iZW50dWsgcG9sYSB5YW5nIGtvbnRpbnUgc2VoaW5nZ2EgYW50YXJvYmplayBtYXNpaCBzYWxpbmcgYmVyZGVrYXRhbiBkYW4gYmVyaHVidW5nYW4gc2F0dSBzYW1hIGxhaW4uDQoNCkFraWJhdG55YSwga2V0aWthIERCU0NBTiBkaXRlcmFwa2FuLCBsZWJpaCBkYXJpIDcwJSBkYXRhIG1haGFzaXN3YSBkaWthdGVnb3Jpa2FuIHNlYmFnYWkgKm5vaXNlKiBkYW4gdGlkYWsgbWFzdWsga2UgZGFsYW0ga2xhc3RlciB1dGFtYS4gS29uZGlzaSBpbmkgbWVtYnVhdCBzZWJhZ2lhbiBiZXNhciBtYWhhc2lzd2EgdGlkYWsgdGVyd2FraWxpIGRhbGFtIGhhc2lsIHBlbmdlbG9tcG9rYW4uIERhcmkgc3VkdXQgcGFuZGFuZyBhbmFsaXNpcyBwZW5kaWRpa2FuLCBoYXNpbCB0ZXJzZWJ1dCBrdXJhbmcgaWRlYWwga2FyZW5hIHR1anVhbiB1dGFtYSBwZW5lbGl0aWFuIGFkYWxhaCBtZW5nZWxvbXBva2thbiBzZWx1cnVoIG1haGFzaXN3YSBiZXJkYXNhcmthbiBrYXJha3RlcmlzdGlrIHBlcmlsYWt1IGJlbGFqYXJueWEsIGJ1a2FuIGhhbnlhIHNlYmFnaWFuIGtlY2lsIGRhdGEgeWFuZyBtZW1pbGlraSBrZXBhZGF0YW4gdGluZ2dpLg0KDQpPbGVoIGthcmVuYSBpdHUsIHBlbWlsaWhhbiBtZXRvZGUgdGVyYmFpayB0aWRhayBoYW55YSBkaWRhc2Fya2FuIHBhZGEgbmlsYWkgKlNpbGhvdWV0dGUgV2lkdGgqLCB0ZXRhcGkganVnYSBtZW1wZXJ0aW1iYW5na2FuIG1hbmZhYXQgcHJha3RpcyBkYXJpIGhhc2lsIGNsdXN0ZXJpbmcgeWFuZyBkaXBlcm9sZWguIEJlcmRhc2Fya2FuIHBlcnRpbWJhbmdhbiB0ZXJzZWJ1dCwgU3BlY3RyYWwgQ2x1c3RlcmluZyBkaXBpbGloIHNlYmFnYWkgbW9kZWwgYWtoaXIgbWVza2lwdW4gbWVtaWxpa2kgbmlsYWkgKlNpbGhvdWV0dGUgV2lkdGgqIHlhbmcgbGViaWggcmVuZGFoLCB5YWl0dSBzZWJlc2FyIDAsMTgyODMzNS4NCg0KU3BlY3RyYWwgQ2x1c3RlcmluZyBtYW1wdSBtZW5nZWxvbXBva2thbiBzZWx1cnVoIG1haGFzaXN3YSBrZSBkYWxhbSBlbXBhdCBrbGFzdGVyIHRhbnBhIG1lbmdhYmFpa2FuIHNhdHUgcHVuIGRhdGEuIFNlbGFpbiBpdHUsIG1ldG9kZSBpbmkgbGViaWggc2VzdWFpIHVudHVrIGRhdGEgeWFuZyBtZW1pbGlraSBiYXRhcyBrZWxvbXBvayB5YW5nIHRpZGFrIGplbGFzIGthcmVuYSBtZW1hbmZhYXRrYW4gaHVidW5nYW4ga2VtaXJpcGFuIGFudGFyb2JqZWsgbWVsYWx1aSAqc2ltaWxhcml0eSBtYXRyaXgqIGRhbiBwZW5kZWthdGFuIHRlb3JpIGdyYWYuIERlbmdhbiBkZW1pa2lhbiwgaGFzaWwgcGVuZ2Vsb21wb2thbiB5YW5nIGRpaGFzaWxrYW4gbWVuamFkaSBsZWJpaCByZXByZXNlbnRhdGlmIGRhbGFtIG1lbmdnYW1iYXJrYW4gdmFyaWFzaSBwZXJpbGFrdSBiZWxhamFyIG1haGFzaXN3YSBzZWNhcmEga2VzZWx1cnVoYW4gc2VydGEgbGViaWggYmVybWFuZmFhdCBzZWJhZ2FpIGRhc2FyIHVudHVrIG1lbmR1a3VuZyBwZW5nYW1iaWxhbiBrZXB1dHVzYW4gYWthZGVtaWsuDQoNCg0KIyA1LiBQRU5ZRVNVQUlBTiBQTE9UIEFLSElSICYgSU5URVJQUkVUQVNJIFBST0ZJTA0KDQpCZXJkYXNhcmthbiBrZXB1dHVzYW4gcGVtb2RlbGFuIGJlcmJhc2lzIGtlbWFuZmFhdGFuIHByYWt0aXMgeWFuZyBkaWtvbWJpbmFzaWthbiBkZW5nYW4ga2VzdGFiaWxhbiBzdHJ1a3R1ciBUZW9yaSBHcmFmLCBoYXNpbCBwZW5nZWxvbXBva2FuIGRhcmkgU3BlY3RyYWwgQ2x1c3RlcmluZyByZXNtaSBkaWd1bmFrYW4gc2ViYWdhaSBtb2RlbCBha2hpciB1bnR1ayBkaXZpc3VhbGlzYXNpa2FuIGRhbiBkaWludGVycHJldGFzaWthbi4NCg0KIyMgNS4xIEdyYWZpayBIYXNpbCBBa2hpciBQZW1iYWdpYW4gS2xhc3Rlcg0KYGBge3J9IA0KIyAxLiBNZW1hc3Vra2FuIGxhYmVsIGtsYXN0ZXIgREJTQ0FOIGtlIGRhdGFmcmFtZSBQQ0ENCiMgTWVuZ3ViYWggbWVuamFkaSBmYWN0b3IgYWdhciBiaXNhIGRpd2FybmFpIHNlY2FyYSBrYXRlZ29yaWsNCmRmX3BjYSRDbHVzdGVyX1RlcnBpbGloIDwtIGZpdF9kYnNjYW4kY2x1c3Rlcg0KDQojIFNpYXNhdCBBa2FkZW1pczogTWVuZ3ViYWggYW5na2EgMCBtZW5qYWRpIGtldGVyYW5nYW4gIk5vaXNlIC8gUGVuY2lsYW4iDQojIHNlZGFuZ2thbiBrbGFzdGVyIGxhaW5ueWEgdGV0YXAgbWVuamFkaSAiS2xhc3RlciAxIiwgIktsYXN0ZXIgMiIsIGRzdC4NCmRmX3BjYSRDbHVzdGVyX1RlcnBpbGloIDwtIGZhY3RvcigNCiAgZGZfcGNhJENsdXN0ZXJfVGVycGlsaWgsIA0KICBsZXZlbHMgPSBjKDAsIHNvcnQodW5pcXVlKGZpdF9kYnNjYW4kY2x1c3RlcltmaXRfZGJzY2FuJGNsdXN0ZXIgPiAwXSkpKSwNCiAgbGFiZWxzID0gYygiTm9pc2UgLyBQZW5jaWxhbiIsIHBhc3RlKCJLbGFzdGVyIiwgc29ydCh1bmlxdWUoZml0X2Ric2NhbiRjbHVzdGVyW2ZpdF9kYnNjYW4kY2x1c3RlciA+IDBdKSkpKQ0KKQ0KDQojIDIuIE1lbnlpYXBrYW4gcGFsZXQgd2FybmEga3VzdG9tIChBYnUtYWJ1IHVudHVrIE5vaXNlLCB3YXJuYSBjZXJhaCB1bnR1ayBrbGFzdGVyIHJlc21pKQ0KIyBKdW1sYWggd2FybmEga2xhc3RlciBkaXNlc3VhaWthbiBkZW5nYW4ganVtbGFoIGtsYXN0ZXIgeWFuZyB0ZXJiZW50dWsgKHRhbnBhIG5vaXNlKQ0KanVtbGFoX2tsYXN0ZXJfcmVzbWkgPC0gbGVuZ3RoKHVuaXF1ZShmaXRfZGJzY2FuJGNsdXN0ZXJbZml0X2Ric2NhbiRjbHVzdGVyID4gMF0pKQ0Kd2FybmFfcGFsZXQgPC0gYygiZ3JheTYwIiwgc2NhbGVzOjpicmV3ZXJfcGFsKHBhbGV0dGUgPSAiU2V0MSIpKGp1bWxhaF9rbGFzdGVyX3Jlc21pKSkNCg0KIyAzLiBWaXN1YWxpc2FzaSBwbG90IGtsYXN0ZXIgaGFzaWwgREJTQ0FOIGRlbmdhbiBsYWJlbCBwZXJzZW4gdmFyaWFucyBQQ0ENCmdncGxvdChkZl9wY2EsIGFlcyh4ID0gUEMxLCB5ID0gUEMyLCBjb2wgPSBDbHVzdGVyX1RlcnBpbGloKSkgKw0KICBnZW9tX3BvaW50KGFscGhhID0gMC44LCBzaXplID0gMi41KSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB3YXJuYV9wYWxldCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkhhc2lsIEFraGlyIEFuYWxpc2lzIENsdXN0ZXJpbmcgKERCU0NBTikiLA0KICAgIHN1YnRpdGxlID0gIlZpc3VhbGlzYXNpIEtlcGFkYXRhbiBLbGFzdGVyIHBhZGEgUnVhbmcgUENBIER1YSBEaW1lbnNpIiwNCiAgICB4ID0gcGFzdGUwKCJQcmluY2lwYWwgQ29tcG9uZW50IDEgLyBEaW0gMSAoIiwgc3ByaW50ZigiJS4yZiIsIHZhcl9wZXJzZW5bMV0pLCAiJSkiKSwNCiAgICB5ID0gcGFzdGUwKCJQcmluY2lwYWwgQ29tcG9uZW50IDIgLyBEaW0gMiAoIiwgc3ByaW50ZigiJS4yZiIsIHZhcl9wZXJzZW5bMl0pLCAiJSkiKSwNCiAgICBjb2wgPSAiU3RhdHVzIC8gS2Vsb21wb2siDQogICkgKw0KICB0aGVtZSgNCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNCkNCiAgKQ0KYGBgDQpCZXJkYXNhcmthbiB2aXN1YWxpc2FzaSBQQ0EgZHVhIGRpbWVuc2ksIGRhdGEgbWFoYXNpc3dhIHRlcmxpaGF0IG1lbnllYmFyIHNlY2FyYSBrb250aW51IHRhbnBhIGJhdGFzIGtsYXN0ZXIgeWFuZyBqZWxhcy4gS29uZGlzaSBpbmkgbWVueWViYWJrYW4gREJTQ0FOIG1lbmdrbGFzaWZpa2FzaWthbiBsZWJpaCBkYXJpIDcwJSBkYXRhIHNlYmFnYWkgbm9pc2UsIHNlaGluZ2dhIGhhc2lsIHBlbmdlbG9tcG9rYW4gbWVuamFkaSBrdXJhbmcgcmVwcmVzZW50YXRpZiB1bnR1ayBtZW5nZ2FtYmFya2FuIGtlc2VsdXJ1aGFuIHBvcHVsYXNpIG1haGFzaXN3YS4NCg0KT2xlaCBrYXJlbmEgaXR1LCBTcGVjdHJhbCBDbHVzdGVyaW5nIGRpcGlsaWggc2ViYWdhaSBtb2RlbCBha2hpciBrYXJlbmEgbWFtcHUgbWVuZ2Vsb21wb2trYW4gc2VsdXJ1aCBtYWhhc2lzd2Ega2UgZGFsYW0gZW1wYXQga2xhc3RlciB0YW5wYSBtZW5nYWJhaWthbiBkYXRhIGFwYSBwdW4uIFNlbGFpbiBtZW5naGFzaWxrYW4gc2VnbWVudGFzaSB5YW5nIGxlYmloIHNlaW1iYW5nLCBtZXRvZGUgaW5pIGp1Z2EgbGViaWggc2VzdWFpIHVudHVrIG1lbmFuZ2thcCBzdHJ1a3R1ciBkYXRhIHlhbmcgbWVtaWxpa2kgYmF0YXMga2Vsb21wb2sgdGlkYWsgdGVnYXMuDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzKQ0KIyBNZW1hc3Vra2FuIGxhYmVsIGtsYXN0ZXIgdGVyYmFpayBrZSBkYXRhZnJhbWUgUENBDQpkZl9wY2EkQ2x1c3Rlcl9UZXJwaWxpaCA8LSBhcy5mYWN0b3IoZml0X3NwZWN0cmFsJGNsdXN0ZXIpDQoNCiMgVmlzdWFsaXNhc2kgcGxvdCBrbGFzdGVyIGhhc2lsIFNwZWN0cmFsIENsdXN0ZXJpbmcgDQpnZ3Bsb3QoZGF0YSA9IGRmX3BjYSwgYWVzKHggPSBQQzEsIHkgPSBQQzIpKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbCA9IENsdXN0ZXJfVGVycGlsaWgpLCBhbHBoYSA9IDAuOCwgc2l6ZSA9IDIuNSkgKw0KICB0aGVtZV9idygpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJIYXNpbCBBa2hpciBBbmFsaXNpcyBDbHVzdGVyaW5nIChTcGVjdHJhbCBDbHVzdGVyaW5nKSIsDQogICAgc3VidGl0bGUgPSAiVmlzdWFsaXNhc2kgS2xhc3RlciBwYWRhIFJ1YW5nIFBDQSBEdWEgRGltZW5zaSIsDQogICAgeCA9IHBhc3RlMCgiRGltIDEgKCIsIHNwcmludGYoIiUuMmYiLCB2YXJfcGVyc2VuWzFdKSwgIiUpIiksDQogICAgeSA9IHBhc3RlMCgiRGltIDIgKCIsIHNwcmludGYoIiUuMmYiLCB2YXJfcGVyc2VuWzJdKSwgIiUpIiksDQogICAgY29sID0gIkNsdXN0ZXIiDQogICkNCmBgYA0KQmVyZGFzYXJrYW4gaGFzaWwgdmlzdWFsaXNhc2kgU3BlY3RyYWwgQ2x1c3RlcmluZyBwYWRhIHJ1YW5nIFBDQSBkdWEgZGltZW5zaSwgc2ViYW55YWsgNDAzIG1haGFzaXN3YSBiZXJoYXNpbCBkaWtlbG9tcG9ra2FuIGtlIGRhbGFtIGVtcGF0IGtsYXN0ZXIuIFJ1YW5nIFBDQSB5YW5nIGRpZ3VuYWthbiBtYW1wdSBtZW5qZWxhc2thbiA1MywxNyUga2VyYWdhbWFuIGRhdGEsIGRlbmdhbiBrb250cmlidXNpIHNlYmVzYXIgMjksMTglIHBhZGEgRGltZW5zaSAxIGRhbiAyMyw5OSUgcGFkYSBEaW1lbnNpIDIuIFBlcnNlbnRhc2UgdGVyc2VidXQgc2FtYSBkZW5nYW4gdmlzdWFsaXNhc2kgc2ViZWx1bW55YSBrYXJlbmEgU3BlY3RyYWwgQ2x1c3RlcmluZyBoYW55YSBtZW1iZXJpa2FuIGxhYmVsIGtsYXN0ZXIgcGFkYSBkYXRhIHRhbnBhIG1lbmd1YmFoIHN0cnVrdHVyIHJ1YW5nIFBDQSB5YW5nIHRlbGFoIHRlcmJlbnR1ay4NCg0KU2VjYXJhIHZpc3VhbCwga2VlbXBhdCBrbGFzdGVyIHRlcmxpaGF0IG1lbWJlbnR1ayBrZWxvbXBvayB5YW5nIHJlbGF0aWYgYmVyYmVkYSBtZXNraXB1biBtYXNpaCB0ZXJkYXBhdCBiZWJlcmFwYSBhcmVhIHlhbmcgc2FsaW5nIGJlcmRla2F0YW4uIEtvbmRpc2kgaW5pIG1lbnVuanVra2FuIGJhaHdhIGthcmFrdGVyaXN0aWsgcGVyaWxha3UgYmVsYWphciBtYWhhc2lzd2EgdGlkYWsgc2VwZW51aG55YSB0ZXJwaXNhaCBzZWNhcmEgdGVnYXMsIG1lbGFpbmthbiBiZXJhZGEgcGFkYSBzcGVrdHJ1bSB5YW5nIHNhbGluZyBiZXJpcmlzYW4uDQoNCk1lc2tpcHVuIGRlbWlraWFuLCBTcGVjdHJhbCBDbHVzdGVyaW5nIG1hbXB1IG1lbmdpZGVudGlmaWthc2kgcG9sYSBrZW1pcmlwYW4gYW50YXIgbWFoYXNpc3dhIGRlbmdhbiBiYWlrIHNlaGluZ2dhIHNlbHVydWggZGF0YSBkYXBhdCBkaWtlbG9tcG9ra2FuIHRhbnBhIGFkYSBvYnNlcnZhc2kgeWFuZyB0ZXJhYmFpa2FuLiBIYXNpbCB2aXN1YWwgaW5pIGp1Z2Egc2VqYWxhbiBkZW5nYW4gZXZhbHVhc2kgbWVuZ2d1bmFrYW4gKlNpbGhvdWV0dGUgV2lkdGgqIHNlYmVzYXIgMCwxODI4MzM1IHlhbmcgbWVudW5qdWtrYW4gYmFod2EgbWV0b2RlIGluaSBtZW5naGFzaWxrYW4gcGVuZ2Vsb21wb2thbiB5YW5nIGxlYmloIGJhaWsgZGliYW5kaW5na2FuIG1ldG9kZSBsYWluIHlhbmcgZGl1amkgcGFkYSBkYXRhc2V0IGluaS4NCg0KRGVuZ2FuIGRlbWlraWFuLCBTcGVjdHJhbCBDbHVzdGVyaW5nIGRpcGlsaWggc2ViYWdhaSBtb2RlbCBha2hpciBrYXJlbmEgbWFtcHUgbWVtYmVyaWthbiBzZWdtZW50YXNpIG1haGFzaXN3YSB5YW5nIGxlYmloIHJlcHJlc2VudGF0aWYgc2VydGEgc2VzdWFpIGRlbmdhbiBrYXJha3RlcmlzdGlrIGRhdGEgcGVyaWxha3UgYmVsYWphciB5YW5nIG1lbWlsaWtpIGJhdGFzIGtlbG9tcG9rIHRpZGFrIHRlcmxhbHUgamVsYXMuDQoNCkJlcmRhc2Fya2FuIGhhc2lsIHBlbW9kZWxhbiwgdGVyZGFwYXQga2VzYW1hYW4gbmlsYWkgcGVyc2VudGFzZSB2YXJpYW5zIHBhZGEgc3VtYnUgZGltZW5zaSBncmFmaWsgZGF0YSBhd2FsIGRhbiBncmFmaWsgaGFzaWwgYWtoaXIgU3BlY3RyYWwgQ2x1c3RlcmluZywgeWFpdHUgRGltIDEgc2ViZXNhciAyOS4xOCUgZGFuIERpbSAyIHNlYmVzYXIgMjMuOTklLiBIYWwgaW5pIHNlY2FyYSBtZXRvZG9sb2dpIHN0YXRpc3Rpa2EgYWRhbGFoIHRlcGF0IGthcmVuYSBrZWR1YSB2aXN1YWxpc2FzaSB0ZXJzZWJ1dCBkaWJhbmd1biBkaSBhdGFzIHJ1YW5nIHByb3lla3NpIGdlb21ldHJpIHlhbmcgc2FtYSwgeWFpdHUgcnVhbmcgcmVkdWtzaSBkaW1lbnNpIFByaW5jaXBhbCBDb21wb25lbnQgQW5hbHlzaXMgKFBDQSkuIEFsZ29yaXRtYSBTcGVjdHJhbCBDbHVzdGVyaW5nIGJlcnRpbmRhayBzZWJhZ2FpIHVuc3VwZXJ2aXNlZCBjbGFzc2lmaWVyIHlhbmcgbWVtYmVyaWthbiBwZWxhYmVsYW4ga2xhc3RlciAoY29sb3ItY29kaW5nKSBwYWRhIHNldGlhcCBvYmplaywgdGFucGEgbWVuZ3ViYWggcG9zaXNpIGtvb3JkaW5hdCBzcGFzaWFsIGF0YXVwdW4gc3RydWt0dXIgdmFyaWFucyBrdW11bGF0aWYgZGF0YSBwYWRhIHJ1YW5nIGtvbXBvbmVuIHV0YW1hIHlhbmcgdGVsYWggZGliZW50dWsgZGkgYXdhbCBhbmFsaXNpcy4NCg0KDQojIyA1LjIgSW50ZXJwcmV0YXNpIEthcmFrdGVyaXN0aWsgU2V0aWFwIEtsYXN0ZXINCg0KVW50dWsgbWVtYWhhbWkga2FyYWt0ZXJpc3RpayBtYXNpbmctbWFzaW5nIGtlbG9tcG9rLCBkaWxha3VrYW4gcGVyaGl0dW5nYW4gcmF0YS1yYXRhIHNldGlhcCB2YXJpYWJlbCBwYWRhIHRpYXAga2xhc3Rlci4NCg0KYGBge3J9DQpwcm9maWxfY2x1c3RlciA8LSBhZ2dyZWdhdGUoDQogIGRmX251bWVyaWssDQogIGJ5ID0gbGlzdChLbGFzdGVyID0gZml0X3NwZWN0cmFsJGNsdXN0ZXIpLA0KICBGVU4gPSBtZWFuDQopDQoNCnByaW50KHByb2ZpbF9jbHVzdGVyKQ0KYGBgDQoNCiMjIyA1LjIuMSDwn5S0IEtsYXN0ZXIgMTogS2Vsb21wb2sgQmVycHJlc3Rhc2kgZGFuIEtvbnNpc3RlbiAoU3RlYWR5ICYgQmFsYW5jZWQgQWNoaWV2ZXJzKQ0KDQpNYWhhc2lzd2EgcGFkYSBrbGFzdGVyIGluaSBtZW51bmp1a2thbiBwZXJmb3JtYSBha2FkZW1payB0ZXJiYWlrIGRpYmFuZGluZ2thbiBzZWx1cnVoIGtlbG9tcG9rIGxhaW5ueWEuIEhhbCBpbmkgdGVybGloYXQgZGFyaSBuaWxhaSBha3Rpdml0YXMgYmVsYWphciBtYXRlcmkgdXRhbWEgKFNURyA9IDAsNDk4KSwgZnJla3VlbnNpIHBlbmd1bGFuZ2FuIG1hdGVyaSAoU0NHID0gMCw0NzMpLCBkYW4gbmlsYWkgdWppYW4gbWF0ZXJpIHV0YW1hIChQRUcgPSAwLDc0MikgeWFuZyBtZXJ1cGFrYW4gbmlsYWkgdGVydGluZ2dpIGRpIGFudGFyYSBzZWx1cnVoIGtsYXN0ZXIuIFNlbGFpbiBpdHUsIG5pbGFpIHVqaWFuIG1hdGVyaSBwZW5kdWt1bmcgKExQUiA9IDAsNTYyKSBqdWdhIHRlcmdvbG9uZyB0aW5nZ2kuIEthcmFrdGVyaXN0aWsgdGVyc2VidXQgbWVudW5qdWtrYW4gYmFod2EgbWFoYXNpc3dhIGRhbGFtIGtlbG9tcG9rIGluaSBtZW1pbGlraSBrZWJpYXNhYW4gYmVsYWphciB5YW5nIGtvbnNpc3RlbiwgYWt0aWYgbWVuZ3VsYW5nIG1hdGVyaSwgc2VydGEgbWFtcHUgbWVuZXJhcGthbiBzdHJhdGVnaSBiZWxhamFyIHlhbmcgZWZla3RpZiBzZWhpbmdnYSBtZW5naGFzaWxrYW4gcHJlc3Rhc2kgYWthZGVtaWsgeWFuZyB1bmdndWwuDQoNCiMjIyA1LjIuMiDwn5+iIEtsYXN0ZXIgMjogS2Vsb21wb2sgS3VhdCBwYWRhIE1hdGVyaSBQZW5kdWt1bmcgKFN1cHBsZW1lbnRhbC1Gb2N1c2VkIExlYXJuZXJzKQ0KDQpNYWhhc2lzd2EgcGFkYSBrbGFzdGVyIGluaSBtZW1pbGlraSBjYXBhaWFuIHRlcnRpbmdnaSBwYWRhIG5pbGFpIHVqaWFuIG1hdGVyaSBwZW5kdWt1bmcgKExQUiA9IDAsNzE5KS4gQWt0aXZpdGFzIGJlbGFqYXIgbWF0ZXJpIHRhbWJhaGFuIChTVFIgPSAwLDU0OCkgZGFuIGZyZWt1ZW5zaSBwZW5ndWxhbmdhbiBtYXRlcmkgKFNDRyA9IDAsMzU2KSBqdWdhIHJlbGF0aWYgdGluZ2dpLiBOYW11biwgbmlsYWkgdWppYW4gbWF0ZXJpIHV0YW1hIChQRUcgPSAwLDI0MCkgbWVydXBha2FuIHlhbmcgdGVyZW5kYWggZGliYW5kaW5na2FuIHNlbHVydWgga2xhc3Rlci4gS29uZGlzaSBpbmkgbWVudW5qdWtrYW4gYmFod2EgbWFoYXNpc3dhIGRhbGFtIGtlbG9tcG9rIGluaSBjdWt1cCBiYWlrIGRhbGFtIG1lbWFoYW1pIG1hdGVyaSBwZW5kdWt1bmcsIHRldGFwaSBtYXNpaCBtZW5nYWxhbWkga2VzdWxpdGFuIGRhbGFtIG1lbmd1YXNhaSBtYXRlcmkgaW50aSBwZW1iZWxhamFyYW4geWFuZyBkaXVrdXIgbWVsYWx1aSBQRUcuDQoNCiMjIyA1LjIuMyDwn5S1ICBLbGFzdGVyIDM6IEtlbG9tcG9rIFBhc2lmIGRhbiBCZXJpc2lrbyBUaW5nZ2kgKFVuZGVyYWNoaWV2ZXIpDQoNCktsYXN0ZXIgaW5pIGRpdGFuZGFpIG9sZWggcmVuZGFobnlhIGFrdGl2aXRhcyBiZWxhamFyIHBhZGEgaGFtcGlyIHNlbHVydWggaW5kaWthdG9yLiBNYWhhc2lzd2EgZGFsYW0ga2Vsb21wb2sgaW5pIG1lbWlsaWtpIG5pbGFpIGFrdGl2aXRhcyBiZWxhamFyIG1hdGVyaSB0YW1iYWhhbiB0ZXJlbmRhaCAoU1RSID0gMCwyMTcpLCBmcmVrdWVuc2kgcGVuZ3VsYW5nYW4gbWF0ZXJpIHlhbmcgcmVuZGFoIChTQ0cgPSAwLDI3NiksIHNlcnRhIGNhcGFpYW4gbmlsYWkgdWppYW4geWFuZyByZWxhdGlmIHJlbmRhaCBwYWRhIG1hdGVyaSB1dGFtYSBtYXVwdW4gcGVuZHVrdW5nLiBNZXNraXB1biBuaWxhaSBQRUcgKDAsMzA5KSBzZWRpa2l0IGxlYmloIHRpbmdnaSBkaWJhbmRpbmdrYW4gS2xhc3RlciAyLCBzZWNhcmEga2VzZWx1cnVoYW4gdGluZ2thdCBrZXRlcmxpYmF0YW4gYmVsYWphciBrZWxvbXBvayBpbmkgbWFzaWggdGVyZ29sb25nIHJlbmRhaC4gT2xlaCBrYXJlbmEgaXR1LCBtYWhhc2lzd2EgcGFkYSBrbGFzdGVyIGluaSBtZW1lcmx1a2FuIHBlcmhhdGlhbiBkYW4gcGVuZGFtcGluZ2FuIGFrYWRlbWlrIHlhbmcgbGViaWggaW50ZW5zaWYgdW50dWsgbWVuaW5na2F0a2FuIG1vdGl2YXNpIGRhbiBha3Rpdml0YXMgYmVsYWphciBtZXJla2EuDQoNCiMjIyA1LjIuNCDwn5+jIEtsYXN0ZXIgNDogS2Vsb21wb2sgQWt0aWYgTWVuZ2Vrc3Bsb3Jhc2kgTWF0ZXJpIChIaWdoIEV4cGxvcmF0aW9uIExlYXJuZXJzKQ0KDQpNYWhhc2lzd2EgcGFkYSBrbGFzdGVyIGluaSBtZW1pbGlraSBha3Rpdml0YXMgYmVsYWphciBtYXRlcmkgdGFtYmFoYW4gdGVydGluZ2dpIGRpYmFuZGluZ2thbiBrZWxvbXBvayBsYWluLCBkaXR1bmp1a2thbiBvbGVoIG5pbGFpIFNUUiBzZWJlc2FyIDAsNjY3LiBTZWxhaW4gaXR1LCBuaWxhaSB1amlhbiBtYXRlcmkgdXRhbWEgKFBFRyA9IDAsNTI1KSBqdWdhIHRlcmdvbG9uZyBjdWt1cCBiYWlrIGRhbiBiZXJhZGEgcGFkYSBwb3Npc2kga2VkdWEgc2V0ZWxhaCBLbGFzdGVyIDEuIE5hbXVuLCBuaWxhaSB1amlhbiBtYXRlcmkgcGVuZHVrdW5nIChMUFIgPSAwLDIzOSkgbWVydXBha2FuIHlhbmcgdGVyZW5kYWggZGkgYW50YXJhIHNlbHVydWgga2xhc3Rlci4gS2FyYWt0ZXJpc3RpayBpbmkgbWVudW5qdWtrYW4gYmFod2EgbWFoYXNpc3dhIGRhbGFtIGtlbG9tcG9rIGluaSBzYW5nYXQgYWt0aWYgbWVuZ2Vrc3Bsb3Jhc2kgYmVyYmFnYWkgc3VtYmVyIGJlbGFqYXIgdGFtYmFoYW4sIHRldGFwaSBha3Rpdml0YXMgdGVyc2VidXQgYmVsdW0gc2VwZW51aG55YSBiZXJrb250cmlidXNpIHRlcmhhZGFwIHBlbmluZ2thdGFuIHBlbWFoYW1hbiBwYWRhIG1hdGVyaSBwZW5kdWt1bmcgeWFuZyBkaXVrdXIgZGFsYW0gZXZhbHVhc2kuDQoNCiMjIyA1LjIuNSBLZXNpbXB1bGFuIEludGVycHJldGFzaSBLbGFzdGVyDQoNCkJlcmRhc2Fya2FuIGthcmFrdGVyaXN0aWsgcmF0YS1yYXRhIHNldGlhcCB2YXJpYWJlbCwgZGlwZXJvbGVoIGVtcGF0IHBvbGEgcGVyaWxha3UgYmVsYWphciBtYWhhc2lzd2EgeWFuZyBiZXJiZWRhLCB5YWl0dToNCg0KKipLbGFzdGVyIDEg4oaSKiogS2Vsb21wb2sgcGFsaW5nIGtvbnNpc3RlbiBkYW4gYmVycHJlc3Rhc2kgZGVuZ2FuIGNhcGFpYW4gYWthZGVtaWsgdGVydGluZ2dpLg0KDQoqKktsYXN0ZXIgMiDihpIqKiBLZWxvbXBvayB5YW5nIHVuZ2d1bCBwYWRhIHBlbWFoYW1hbiBtYXRlcmkgcGVuZHVrdW5nLCB0ZXRhcGkgbWFzaWggbGVtYWggcGFkYSBwZW5ndWFzYWFuIG1hdGVyaSB1dGFtYS4NCg0KKipLbGFzdGVyIDMg4oaSKiogS2Vsb21wb2sgcGFzaWYgZGVuZ2FuIHRpbmdrYXQgYWt0aXZpdGFzIGJlbGFqYXIgZGFuIGNhcGFpYW4gYWthZGVtaWsgeWFuZyByZWxhdGlmIHJlbmRhaC4NCg0KKipLbGFzdGVyIDQg4oaSKiogS2Vsb21wb2sgeWFuZyBwYWxpbmcgYWt0aWYgbWVuZ2Vrc3Bsb3Jhc2kgbWF0ZXJpIHRhbWJhaGFuIGRlbmdhbiBwZXJmb3JtYSBha2FkZW1payB5YW5nIGN1a3VwIGJhaWsuDQoNCkhhc2lsIGluaSBtZW51bmp1a2thbiBiYWh3YSBzZXRpYXAga2Vsb21wb2sgbWFoYXNpc3dhIG1lbWlsaWtpIHN0cmF0ZWdpIGRhbiBrYXJha3RlcmlzdGlrIGJlbGFqYXIgeWFuZyBiZXJiZWRhLiBPbGVoIGthcmVuYSBpdHUsIHBlbmRla2F0YW4gcGVtYmVsYWphcmFuIHlhbmcgZGliZXJpa2FuIGRhcGF0IGRpc2VzdWFpa2FuIGRlbmdhbiBrZWJ1dHVoYW4gbWFzaW5nLW1hc2luZyBrZWxvbXBvayBhZ2FyIHByb3NlcyBwZW1iZWxhamFyYW4gbWVuamFkaSBsZWJpaCBlZmVrdGlmIGRhbiB0ZXBhdCBzYXNhcmFuLg0K