Algoritma & Struktur Data

~ UAS ~


Kontak : \(\downarrow\)
Email
Instagram https://www.instagram.com/novia_labola/
RPubs https://rpubs.com/noviaanita/

Berikut ini saya lampirkan data perumahan di kota Melbourne Australia, dengan struktur data sebagai berikut:

Type: yang dibagi menjadi 3 bagian

• TipeA.csv

• TipeB.xlsx

• TipeC.rds

Dimana setiap tipe rumah (A,B,C) tersebut terdiri dari beberapa variabel sebagai berikut:

• Suburb: Suburb

• Rooms: Number of rooms

• Price: Price in dollars

• Method: Status of property sale -

  • S - property sold;

  • SP - property sold prior;

  • PI - property passed in;

  • PN - sold prior not disclosed;

  • SN - sold not disclosed;

  • VB - vendor bid;

  • W - withdrawn prior to auction;

  • SA - sold after auction;

  • SS - sold after auction price not disclosed.

• SellerG: Real Estate Agent

• Date: Date sold

• Distance: Distance from CBD

• Bedroom2: Number of Bedrooms

• Bathroom: Number of Bathrooms

• Car: Number of car spots

• Landsize: Land Size

• YearBuilt: Year the house was built

• Regionname: General Region (West, North West, North, North east …etc)

Tugas :

Soal 1

Gabungkan data tipe A,B, C kedalam satu dataframe sehingga membentuk struktur data (Type,Subur, Price, Method, SellerG, Date, Distance,Bedroom2, Bathroom, Car, Landsize, YearBuilt, Regionname)

Pertama saya memastikan direktori kerja dengan menggunakan fungsi getwd() dan untuk mengatur direktori kerja baru dengan menggunakan fungsi setwd().

print(getwd())
## [1] "C:/Users/MASTER/Documents/TugasUASALGO"
getwd()
## [1] "C:/Users/MASTER/Documents/TugasUASALGO"
setwd(getwd())

Saya juga menggunakan packages readxl untuk membaca langsung filenya. Kemudian saya menggunakan fungsi rbind untuk mengabungkan 3 data yang berbeda dalam satu data frame.

# install.packages(c("readxl","writexl")) # install packages readxl and writexl
pacman::p_load(readxl, writexl)         # install pacman
# impor data
df1 <-read.csv("File1/TipeA.csv",sep = ",") 
df2 <-read_excel("File1/TipeB.xlsx") 
df3 <-readRDS("File1/TipeC.rds")

df1$type="A"
df2$type="B"
df3$type="C"

df4 <- rbind(df1,df2,df3)
df4

Setelah mengabungkan data, saya menambahkan variabel type di dataset.

baru = data.frame("type" =df4$type,
               "Subur" =df4$Suburb,
               "Price"= df4$Price,
               "Method" = df4$Method,
               "SellerG" = df4$SellerG,
               "Date" = df4$Date,
               "Distance" = df4$Distance,
               "Bedroom2" = df4$Bedroom2,
               "Bathroom" = df4$Bathroom,
               "Car" = df4$Car,
               "Landsize" = df4$Landsize,
               "YearBuilt" = df4$YearBuilt,
               "Regionname" = df4$Regionname)
baru

Soal 2

Rename setiap variabel diatas kedalam bahasa Indonesia.

Pada soal nomor 2 ini saya menggunakan fungsi names untuk mengubah nama variabel dari bahasa Inggris ke bahasa Indonesia. Setelah itu,masukan list nama variabel yang baru kemudian print data frame rename_1

rename_1<-baru
names(rename_1)<-c("Tipe",
                   "pinggiran kota", 
                   "Harga",
                   "Metode",
                   "Penjual",
                   "Tanggal",
                   "Jarak",
                   "Kamar_tidur",
                   "Kamar.mandi",
                   "Mobil",
                   "Ukuran_tanah",
                   "Dibangun.tahun",
                   "Wilayah")
rename_1

Soal 3

Rename kategori variabel “Regionname” kedalam bahasa Indonesia.

Pada soal nomor 3 ini saya menggunakan fungsi unique untuk mengevaluasi variabel unik pada kolom Wilayah

unique(rename_1$Wilayah)
## [1] "Northern Metropolitan"      "Western Metropolitan"      
## [3] "Southern Metropolitan"      "Eastern Metropolitan"      
## [5] "South-Eastern Metropolitan" "Eastern Victoria"          
## [7] "Northern Victoria"          "Western Victoria"          
## [9] NA

Setelah semua variabel unik diketahui, kemudian saya mengubah variabelnya dari bahasa Inggris menjadi bahasa Indonesia.

rename_1
rename_1$Wilayah[rename_1$Wilayah=="Southern Metropolitan"] <- "Metropolitan Selatan"
rename_1$Wilayah[rename_1$Wilayah=="Northern Metropolitan"] <- "Metropolitan Utara"
rename_1$Wilayah[rename_1$Wilayah=="Western Metropolitan"] <- "Metropolitan Barat"
rename_1$Wilayah[rename_1$Wilayah=="Eastern Metropolitan"] <- "Metropolitan Timur"
rename_1$Wilayah[rename_1$Wilayah=="South-Eastern Metropolitan"] <- "Metropolitan Tenggara"
rename_1$Wilayah[rename_1$Wilayah=="Eastern Victoria"] <- "Victoria Timur"
rename_1$Wilayah[rename_1$Wilayah=="Western Victoria"] <- "Victoria Barat"

rename_1

Soal 4

Lakukan pengecekan Missing Value dan pengendalian

Pada soal nomor 4 ini saya melakukan pengecekan missing value dengan menggunakan fungsi na.omit untuk menghilangkan data NA pada data frame rename_1. Setelah semua data bersih dari NA, saya memanggil data tersebut. Kemudian data bersih akan muncul.Data bersih tersebut saya beri nama nov_NA.

nov_NA = na.omit(rename_1)
nov_NA

Kemudian, saya menggunakan fungsi setdiff untuk menunjukkan variabel NA-nya saja. Atau saya ingin memunculkan data rename_1 tanpa data nov_NA.Data nov_NA merupakan data bersih yang tidak ada NA-nya. Data yang berisi NA saja saya beri nama via_NA

via.NA = setdiff(rename_1, nov_NA)
via.NA
summary(rename_1)
##      Tipe           pinggiran kota         Harga             Metode         
##  Length:34857       Length:34857       Min.   :   85000   Length:34857      
##  Class :character   Class :character   1st Qu.:  635000   Class :character  
##  Mode  :character   Mode  :character   Median :  870000   Mode  :character  
##                                        Mean   : 1050173                     
##                                        3rd Qu.: 1295000                     
##                                        Max.   :11200000                     
##                                        NA's   :7610                         
##    Penjual            Tanggal              Jarak        Kamar_tidur    
##  Length:34857       Length:34857       Min.   : 0.00   Min.   : 0.000  
##  Class :character   Class :character   1st Qu.: 6.40   1st Qu.: 2.000  
##  Mode  :character   Mode  :character   Median :10.30   Median : 3.000  
##                                        Mean   :11.18   Mean   : 3.085  
##                                        3rd Qu.:14.00   3rd Qu.: 4.000  
##                                        Max.   :48.10   Max.   :30.000  
##                                        NA's   :1       NA's   :8217    
##   Kamar.mandi         Mobil         Ukuran_tanah      Dibangun.tahun 
##  Min.   : 0.000   Min.   : 0.000   Min.   :     0.0   Min.   :1196   
##  1st Qu.: 1.000   1st Qu.: 1.000   1st Qu.:   224.0   1st Qu.:1940   
##  Median : 2.000   Median : 2.000   Median :   521.0   Median :1970   
##  Mean   : 1.625   Mean   : 1.729   Mean   :   593.6   Mean   :1965   
##  3rd Qu.: 2.000   3rd Qu.: 2.000   3rd Qu.:   670.0   3rd Qu.:2000   
##  Max.   :12.000   Max.   :26.000   Max.   :433014.0   Max.   :2106   
##  NA's   :8226     NA's   :8728     NA's   :11810      NA's   :19306  
##    Wilayah         
##  Length:34857      
##  Class :character  
##  Mode  :character  
##                    
##                    
##                    
## 

Soal 5

Buatlah Visualisasi Data secara lengkap untuk mendapatkan informasi penting yang terkandung dalam Data_Perumahan_Melbourne.xlsx.

# Diagram Boxplot

library(ggplot2)
ggplot(nov_NA, aes(Tipe, Harga)) +
  geom_boxplot(outlier.colour = "magenta") + 
  scale_x_discrete(labels = c('A','B','C')) +
  scale_y_continuous(breaks=seq(0,10000000,1500000)) +
  xlab("Tipe") +
  ylab("Harga") +
  ggtitle("Distribusi Harga Tipe Rumah")

Berdasarkan diagram diatas dapat disimpulkan bahwa distribusi harga tipe rumah yang memiliki harga tertinggi adalah tipe A. Dibandingkan dengan tipe B dan C.

# Diagram Pai

library(scales)
library(dplyr)
## 
## 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
plotdata <- nov_NA %>%
  count(Wilayah) %>%
  arrange(desc(Wilayah)) %>%
  mutate(prop = round(n*100/sum(n),1),
         lab.ypos = cumsum(prop) - 0.5*prop)


ggplot(plotdata,
       aes(x = "",
           y = prop,
           fill = Wilayah)) +
  geom_bar(width = 1, stat = "identity", color = "white") +
  coord_polar("y", start = 0) +
  geom_text(aes(y = lab.ypos, label = prop), color = ("black")) +
  scale_fill_brewer(palette="Paired", direction=-1) +
  theme_void() +
  labs(title = "Wilayah banyak penduduk ")

Berdasarkan kesimpulan diagram diatas dapat disimpulkan, bahwa wilayah yang padat penduduk terdapat di Metropolitan Selatan dengan 31.9% penduduk.

# Diagram Histogram

ggplot(nov_NA, aes(x = Dibangun.tahun)) +
  geom_histogram(fill = "Magenta",
                 color = "white", bins = 30) +
  scale_y_continuous(breaks=seq(0,1700,1800))+
  theme_minimal() +
  labs(title = "Pembangunan Tahun",
       x = "Tahun bangunan")

Kesimpulan dari diagram diatas adalah pembangunan yang banyak dilakukan pada tahun sekitar 2000-an.

# Plot Sebaran Menyesuaikan Garis

library(ggplot2)                                     # untuk visualisasi
ggplot(nov_NA,
       aes(x = Ukuran_tanah, 
           y = Harga)) +
  geom_point(color= "yellow") +
  geom_smooth(method = "lm", color = "red")+
  scale_y_continuous(label = scales::dollar, 
                     limits = c(50000, 5000000)) +
  scale_x_continuous(breaks = seq(0, 2500, 200), 
                     limits=c(0, 2500)) +
  theme_minimal() +                                  # menggunakan tema minimal
  labs(x = "Luas Bangunan",
       y = "Harga",
       title = "Luas Bangunan Vs. Harga",
       subtitle = "Harga dan Luas")+
  theme(axis.text.x = element_text(angle = 60, hjust = 1))
## `geom_smooth()` using formula 'y ~ x'
## Warning: Removed 144 rows containing non-finite values (stat_smooth).
## Warning: Removed 144 rows containing missing values (geom_point).

Kesimpulannya adalah rumah yang memiliki luas kecil dan harga yang rendah banyak diminati oleh penduduk. Sedangkan rumah yang memiliki luas yang besar dengan harga yang tinggi jarang diminati oleh penduduk.

# Plot Sebaran Menyesuaikan Garis

library(ggplot2)                                     # untuk visualisasi
ggplot(nov_NA,
       aes(x = Ukuran_tanah, 
           y = Harga)) +
  geom_point(color= "orange") +
  geom_smooth(method = "lm",
              formula = y ~ poly(x, 2),
              color = "red")+
  scale_y_continuous(label = scales::dollar, 
                     limits = c(50000, 5000000)) +
  scale_x_continuous(breaks = seq(0, 2500, 200), 
                     limits=c(0, 2500)) +
  theme_minimal() +                                  # menggunakan tema minimal
  labs(x = "Luas Bangunan",
       y = "Harga",
       title = "Luas Bangunan Vs. Harga",
       subtitle = "Harga dan Luas")+
  theme(axis.text.x = element_text(angle = 60, hjust = 1))
## Warning: Removed 144 rows containing non-finite values (stat_smooth).
## Warning: Removed 144 rows containing missing values (geom_point).

# Diagram Batang

library(dplyr)                                       # untuk manipulasi data
library(ggplot2)                                     # untuk visualisasi
library(scales)                                      # menentukan jeda atau label secara otomatis

# menghitung gaji rata-rata untuk setiap jabatan
plotdata <- nov_NA %>%
  group_by(Wilayah) %>%
  dplyr::summarize(mean_Harga = mean(Harga))
# plot gaji rata-rata dengan cara yang lebih menarik
mycols <- c("#CD534CFF", "#EFC000FF", "#2FDD92","#FFAB4C", "#116530", "#7267CB","#CD534CFF", "#EBE645")
ggplot(plotdata, 
       aes(x = factor(Wilayah,
                      labels = c("Selatan",
                                 "Utara",
                                 "Barat",
                                 "Timur",
                                 "Tenggara.Metropolitan",
                                 "Utara.Victoria",
                                 "Barat.Victoria",
                                 "Timur.Victoria")), 
                      y = mean_Harga)) +
  geom_bar(stat = "identity", 
           fill = mycols) +
  geom_text(aes(label = dollar(mean_Harga)), 
            vjust = -0.5) +
  scale_y_continuous(breaks = seq(0, 40000000, 500000), 
                     label = dollar) +
  theme_minimal() +                                  # menggunakan tema minimal
  labs(title = "Rata-rata harga rumah di beberapa wilayah", 
       x = "",
       y = "") +
  theme(axis.text.x = element_text(angle = 45, vjust = 0.5))

Dari diagram diatas dapat disimpulkan bahwa rata-rata harga rumah di beberapa wilayah yang memiliki harga tertinggi adalah wilayah Utara dengan $1,449,759. Sedangkan harga yang rendah terdapat di wilayah Barat Victoria dengan harga $441,087.

LS0tDQp0aXRsZTogIkFsZ29yaXRtYSAmIFN0cnVrdHVyIERhdGEiDQpzdWJ0aXRsZTogIn4gVUFTIH4iDQphdXRob3I6ICJOb3ZpYSBBbml0YSAoMjAyMTQ1MjAwMDgpIg0KZGF0ZTogICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDoNCiAgcm1kZm9ybWF0czo6cm9ib2Jvb2s6ICAgIyBodHRwczovL2dpdGh1Yi5jb20vanViYS9ybWRmb3JtYXRzDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICB0aHVtYm5haWxzOiB0cnVlDQogICAgbGlnaHRib3g6IHRydWUNCiAgICBnYWxsZXJ5OiB0cnVlDQogICAgbGliX2RpcjogbGlicw0KICAgIGRmX3ByaW50OiAicGFnZWQiDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyINCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBjc3M6ICJzdHlsZS5jc3MiDQoNCi0tLQ0KDQo8YnI+DQoNCjxpbWcgc3R5bGU9ImZsb2F0OiByaWdodDsgbWFyZ2luOiAtNTBweCA1MHB4IDBweCA1MHB4OyB3aWR0aDozMCUiIHNyYz0ibm92aWEuSlBHIi8+IA0KDQp8DQo6LS0tLSB8Oi0tLS0NCioqS29udGFrKip8ICoqOiAkXGRvd25hcnJvdyQqKg0KRW1haWx8IG5vdmlhYWxibDAyQGdtYWlsLmNvbQ0KSW5zdGFncmFtIHwgaHR0cHM6Ly93d3cuaW5zdGFncmFtLmNvbS9ub3ZpYV9sYWJvbGEvIA0KUlB1YnMgIHwgaHR0cHM6Ly9ycHVicy5jb20vbm92aWFhbml0YS8gDQoNCioqKg0KDQoNCg0KDQpCZXJpa3V0IGluaSBzYXlhIGxhbXBpcmthbiBkYXRhIHBlcnVtYWhhbiBkaSBrb3RhIE1lbGJvdXJuZSBBdXN0cmFsaWEsIGRlbmdhbiBzdHJ1a3R1ciBkYXRhIHNlYmFnYWkgYmVyaWt1dDoNCg0KVHlwZTogeWFuZyBkaWJhZ2kgbWVuamFkaSAzIGJhZ2lhbg0KDQrigKIJVGlwZUEuY3N2DQoNCuKAoglUaXBlQi54bHN4DQoNCuKAoglUaXBlQy5yZHMNCg0KRGltYW5hIHNldGlhcCB0aXBlIHJ1bWFoIChBLEIsQykgdGVyc2VidXQgdGVyZGlyaSBkYXJpIGJlYmVyYXBhIHZhcmlhYmVsIHNlYmFnYWkgYmVyaWt1dDoNCg0K4oCiCVN1YnVyYjogU3VidXJiDQoNCuKAoglSb29tczogTnVtYmVyIG9mIHJvb21zDQoNCuKAoglQcmljZTogUHJpY2UgaW4gZG9sbGFycw0KDQrigKIJTWV0aG9kOiBTdGF0dXMgb2YgcHJvcGVydHkgc2FsZSAtDQoNCiAgIC0JUyAtIHByb3BlcnR5IHNvbGQ7DQogICANCiAgIC0JU1AgLSBwcm9wZXJ0eSBzb2xkIHByaW9yOw0KICAgDQogICAtCVBJIC0gcHJvcGVydHkgcGFzc2VkIGluOw0KICAgDQogICAtCVBOIC0gc29sZCBwcmlvciBub3QgZGlzY2xvc2VkOw0KICAgDQogICAtCVNOIC0gc29sZCBub3QgZGlzY2xvc2VkOw0KICAgDQogICAtCVZCIC0gdmVuZG9yIGJpZDsNCiAgIA0KICAgLQlXIC0gd2l0aGRyYXduIHByaW9yIHRvIGF1Y3Rpb247DQogICANCiAgIC0JU0EgLSBzb2xkIGFmdGVyIGF1Y3Rpb247DQogICANCiAgIC0JU1MgLSBzb2xkIGFmdGVyIGF1Y3Rpb24gcHJpY2Ugbm90IGRpc2Nsb3NlZC4NCiAgIA0K4oCiCVNlbGxlckc6IFJlYWwgRXN0YXRlIEFnZW50DQoNCuKAoglEYXRlOiBEYXRlIHNvbGQNCg0K4oCiCURpc3RhbmNlOiBEaXN0YW5jZSBmcm9tIENCRA0KDQrigKIJQmVkcm9vbTI6IE51bWJlciBvZiBCZWRyb29tcw0KDQrigKIJQmF0aHJvb206IE51bWJlciBvZiBCYXRocm9vbXMNCg0K4oCiCUNhcjogTnVtYmVyIG9mIGNhciBzcG90cw0KDQrigKIJTGFuZHNpemU6IExhbmQgU2l6ZQ0KDQrigKIJWWVhckJ1aWx0OiBZZWFyIHRoZSBob3VzZSB3YXMgYnVpbHQNCg0K4oCiCVJlZ2lvbm5hbWU6IEdlbmVyYWwgUmVnaW9uIChXZXN0LCBOb3J0aCBXZXN0LCBOb3J0aCwgTm9ydGggZWFzdCDigKZldGMpDQoNClR1Z2FzIDoNCg0KIyBTb2FsIDEgDQpHYWJ1bmdrYW4gZGF0YSB0aXBlIEEsQiwgQyBrZWRhbGFtIHNhdHUgZGF0YWZyYW1lIHNlaGluZ2dhIG1lbWJlbnR1ayBzdHJ1a3R1ciBkYXRhIChUeXBlLFN1YnVyLCBQcmljZSwgTWV0aG9kLCBTZWxsZXJHLCAgRGF0ZSwgRGlzdGFuY2UsQmVkcm9vbTIsIEJhdGhyb29tLCBDYXIsIExhbmRzaXplLCBZZWFyQnVpbHQsIFJlZ2lvbm5hbWUpDQoNCg0KUGVydGFtYSBzYXlhIG1lbWFzdGlrYW4gZGlyZWt0b3JpIGtlcmphIGRlbmdhbiBtZW5nZ3VuYWthbiBmdW5nc2kgKipnZXR3ZCgpKiogZGFuIHVudHVrIG1lbmdhdHVyIGRpcmVrdG9yaSBrZXJqYSBiYXJ1IGRlbmdhbiBtZW5nZ3VuYWthbiBmdW5nc2kgKipzZXR3ZCgpKiouDQpgYGB7cn0NCnByaW50KGdldHdkKCkpDQpnZXR3ZCgpDQpgYGANCg0KYGBge3J9DQpzZXR3ZChnZXR3ZCgpKQ0KYGBgDQoNClNheWEganVnYSBtZW5nZ3VuYWthbiBwYWNrYWdlcyAqKnJlYWR4bCoqIHVudHVrIG1lbWJhY2EgbGFuZ3N1bmcgZmlsZW55YS4gS2VtdWRpYW4gc2F5YSBtZW5nZ3VuYWthbiBmdW5nc2kgKipyYmluZCoqIHVudHVrIG1lbmdhYnVuZ2thbiAzIGRhdGEgeWFuZyBiZXJiZWRhIGRhbGFtIHNhdHUgZGF0YSBmcmFtZS4NCmBgYHtyfQ0KIyBpbnN0YWxsLnBhY2thZ2VzKGMoInJlYWR4bCIsIndyaXRleGwiKSkgIyBpbnN0YWxsIHBhY2thZ2VzIHJlYWR4bCBhbmQgd3JpdGV4bA0KcGFjbWFuOjpwX2xvYWQocmVhZHhsLCB3cml0ZXhsKSAgICAgICAgICMgaW5zdGFsbCBwYWNtYW4NCmBgYA0KDQoNCmBgYHtyfQ0KIyBpbXBvciBkYXRhDQpkZjEgPC1yZWFkLmNzdigiRmlsZTEvVGlwZUEuY3N2IixzZXAgPSAiLCIpIA0KZGYyIDwtcmVhZF9leGNlbCgiRmlsZTEvVGlwZUIueGxzeCIpIA0KZGYzIDwtcmVhZFJEUygiRmlsZTEvVGlwZUMucmRzIikNCg0KZGYxJHR5cGU9IkEiDQpkZjIkdHlwZT0iQiINCmRmMyR0eXBlPSJDIg0KDQpkZjQgPC0gcmJpbmQoZGYxLGRmMixkZjMpDQpkZjQNCmBgYA0KU2V0ZWxhaCBtZW5nYWJ1bmdrYW4gZGF0YSwgc2F5YSBtZW5hbWJhaGthbiB2YXJpYWJlbCAqKnR5cGUqKiBkaSBkYXRhc2V0LiANCmBgYHtyfQ0KYmFydSA9IGRhdGEuZnJhbWUoInR5cGUiID1kZjQkdHlwZSwNCiAgICAgICAgICAgICAgICJTdWJ1ciIgPWRmNCRTdWJ1cmIsDQogICAgICAgICAgICAgICAiUHJpY2UiPSBkZjQkUHJpY2UsDQogICAgICAgICAgICAgICAiTWV0aG9kIiA9IGRmNCRNZXRob2QsDQogICAgICAgICAgICAgICAiU2VsbGVyRyIgPSBkZjQkU2VsbGVyRywNCiAgICAgICAgICAgICAgICJEYXRlIiA9IGRmNCREYXRlLA0KICAgICAgICAgICAgICAgIkRpc3RhbmNlIiA9IGRmNCREaXN0YW5jZSwNCiAgICAgICAgICAgICAgICJCZWRyb29tMiIgPSBkZjQkQmVkcm9vbTIsDQogICAgICAgICAgICAgICAiQmF0aHJvb20iID0gZGY0JEJhdGhyb29tLA0KICAgICAgICAgICAgICAgIkNhciIgPSBkZjQkQ2FyLA0KICAgICAgICAgICAgICAgIkxhbmRzaXplIiA9IGRmNCRMYW5kc2l6ZSwNCiAgICAgICAgICAgICAgICJZZWFyQnVpbHQiID0gZGY0JFllYXJCdWlsdCwNCiAgICAgICAgICAgICAgICJSZWdpb25uYW1lIiA9IGRmNCRSZWdpb25uYW1lKQ0KYmFydQ0KYGBgDQoNCiMgU29hbCAyDQpSZW5hbWUgc2V0aWFwIHZhcmlhYmVsIGRpYXRhcyBrZWRhbGFtIGJhaGFzYSBJbmRvbmVzaWEuDQoNClBhZGEgc29hbCBub21vciAyIGluaSBzYXlhIG1lbmdndW5ha2FuIGZ1bmdzaSAqKm5hbWVzKiogdW50dWsgbWVuZ3ViYWggbmFtYSB2YXJpYWJlbCBkYXJpIGJhaGFzYSBJbmdncmlzIGtlIGJhaGFzYSBJbmRvbmVzaWEuIFNldGVsYWggaXR1LG1hc3VrYW4gbGlzdCBuYW1hIHZhcmlhYmVsIHlhbmcgYmFydSBrZW11ZGlhbiBwcmludCBkYXRhIGZyYW1lICoqcmVuYW1lXzEqKg0KYGBge3J9DQpyZW5hbWVfMTwtYmFydQ0KbmFtZXMocmVuYW1lXzEpPC1jKCJUaXBlIiwNCiAgICAgICAgICAgICAgICAgICAicGluZ2dpcmFuIGtvdGEiLCANCiAgICAgICAgICAgICAgICAgICAiSGFyZ2EiLA0KICAgICAgICAgICAgICAgICAgICJNZXRvZGUiLA0KICAgICAgICAgICAgICAgICAgICJQZW5qdWFsIiwNCiAgICAgICAgICAgICAgICAgICAiVGFuZ2dhbCIsDQogICAgICAgICAgICAgICAgICAgIkphcmFrIiwNCiAgICAgICAgICAgICAgICAgICAiS2FtYXJfdGlkdXIiLA0KICAgICAgICAgICAgICAgICAgICJLYW1hci5tYW5kaSIsDQogICAgICAgICAgICAgICAgICAgIk1vYmlsIiwNCiAgICAgICAgICAgICAgICAgICAiVWt1cmFuX3RhbmFoIiwNCiAgICAgICAgICAgICAgICAgICAiRGliYW5ndW4udGFodW4iLA0KICAgICAgICAgICAgICAgICAgICJXaWxheWFoIikNCnJlbmFtZV8xDQpgYGANCg0KDQojIFNvYWwgMw0KUmVuYW1lIGthdGVnb3JpIHZhcmlhYmVsICJSZWdpb25uYW1lIiBrZWRhbGFtIGJhaGFzYSBJbmRvbmVzaWEuDQoNClBhZGEgc29hbCBub21vciAzIGluaSBzYXlhIG1lbmdndW5ha2FuIGZ1bmdzaSAqKnVuaXF1ZSoqIHVudHVrIG1lbmdldmFsdWFzaSB2YXJpYWJlbCB1bmlrIHBhZGEga29sb20gKipXaWxheWFoKioNCmBgYHtyfQ0KdW5pcXVlKHJlbmFtZV8xJFdpbGF5YWgpDQpgYGANClNldGVsYWggc2VtdWEgdmFyaWFiZWwgdW5payBkaWtldGFodWksIGtlbXVkaWFuIHNheWEgbWVuZ3ViYWggdmFyaWFiZWxueWEgZGFyaSBiYWhhc2EgSW5nZ3JpcyBtZW5qYWRpIGJhaGFzYSBJbmRvbmVzaWEuDQpgYGB7cn0NCnJlbmFtZV8xDQpyZW5hbWVfMSRXaWxheWFoW3JlbmFtZV8xJFdpbGF5YWg9PSJTb3V0aGVybiBNZXRyb3BvbGl0YW4iXSA8LSAiTWV0cm9wb2xpdGFuIFNlbGF0YW4iDQpyZW5hbWVfMSRXaWxheWFoW3JlbmFtZV8xJFdpbGF5YWg9PSJOb3J0aGVybiBNZXRyb3BvbGl0YW4iXSA8LSAiTWV0cm9wb2xpdGFuIFV0YXJhIg0KcmVuYW1lXzEkV2lsYXlhaFtyZW5hbWVfMSRXaWxheWFoPT0iV2VzdGVybiBNZXRyb3BvbGl0YW4iXSA8LSAiTWV0cm9wb2xpdGFuIEJhcmF0Ig0KcmVuYW1lXzEkV2lsYXlhaFtyZW5hbWVfMSRXaWxheWFoPT0iRWFzdGVybiBNZXRyb3BvbGl0YW4iXSA8LSAiTWV0cm9wb2xpdGFuIFRpbXVyIg0KcmVuYW1lXzEkV2lsYXlhaFtyZW5hbWVfMSRXaWxheWFoPT0iU291dGgtRWFzdGVybiBNZXRyb3BvbGl0YW4iXSA8LSAiTWV0cm9wb2xpdGFuIFRlbmdnYXJhIg0KcmVuYW1lXzEkV2lsYXlhaFtyZW5hbWVfMSRXaWxheWFoPT0iRWFzdGVybiBWaWN0b3JpYSJdIDwtICJWaWN0b3JpYSBUaW11ciINCnJlbmFtZV8xJFdpbGF5YWhbcmVuYW1lXzEkV2lsYXlhaD09Ildlc3Rlcm4gVmljdG9yaWEiXSA8LSAiVmljdG9yaWEgQmFyYXQiDQoNCnJlbmFtZV8xDQpgYGANCg0KDQojIFNvYWwgNA0KTGFrdWthbiBwZW5nZWNla2FuIE1pc3NpbmcgVmFsdWUgZGFuIHBlbmdlbmRhbGlhbg0KDQpQYWRhIHNvYWwgbm9tb3IgNCBpbmkgc2F5YSBtZWxha3VrYW4gcGVuZ2VjZWthbiBtaXNzaW5nIHZhbHVlIGRlbmdhbiBtZW5nZ3VuYWthbiBmdW5nc2kgKipuYS5vbWl0KiogdW50dWsgbWVuZ2hpbGFuZ2thbiBkYXRhICoqTkEqKiBwYWRhIGRhdGEgZnJhbWUgKipyZW5hbWVfMSoqLiBTZXRlbGFoIHNlbXVhIGRhdGEgYmVyc2loIGRhcmkgKipOQSoqLCBzYXlhIG1lbWFuZ2dpbCBkYXRhIHRlcnNlYnV0LiBLZW11ZGlhbiBkYXRhIGJlcnNpaCBha2FuIG11bmN1bC5EYXRhIGJlcnNpaCB0ZXJzZWJ1dCBzYXlhIGJlcmkgbmFtYSAqKm5vdl9OQSoqLg0KYGBge3J9DQpub3ZfTkEgPSBuYS5vbWl0KHJlbmFtZV8xKQ0Kbm92X05BDQpgYGANCktlbXVkaWFuLCBzYXlhIG1lbmdndW5ha2FuIGZ1bmdzaSAqKnNldGRpZmYqKiB1bnR1ayBtZW51bmp1a2thbiB2YXJpYWJlbCAqKk5BKiotbnlhIHNhamEuIEF0YXUgc2F5YSBpbmdpbiBtZW11bmN1bGthbiBkYXRhICoqcmVuYW1lXzEqKiB0YW5wYSBkYXRhICoqbm92X05BKiouRGF0YSAqKm5vdl9OQSoqIG1lcnVwYWthbiBkYXRhIGJlcnNpaCB5YW5nIHRpZGFrIGFkYSAqTkEqLW55YS4gRGF0YSB5YW5nIGJlcmlzaSAqKk5BKiogc2FqYSBzYXlhIGJlcmkgbmFtYSAqKnZpYV9OQSoqDQpgYGB7cn0NCnZpYS5OQSA9IHNldGRpZmYocmVuYW1lXzEsIG5vdl9OQSkNCnZpYS5OQQ0KYGBgDQoNCg0KYGBge3J9DQpzdW1tYXJ5KHJlbmFtZV8xKQ0KYGBgDQoNCg0KIyBTb2FsIDUNCkJ1YXRsYWggVmlzdWFsaXNhc2kgRGF0YSBzZWNhcmEgbGVuZ2thcCB1bnR1ayBtZW5kYXBhdGthbiBpbmZvcm1hc2kgcGVudGluZyB5YW5nIHRlcmthbmR1bmcgZGFsYW0gRGF0YV9QZXJ1bWFoYW5fTWVsYm91cm5lLnhsc3guDQoNCg0KYGBge3J9DQojIERpYWdyYW0gQm94cGxvdA0KDQpsaWJyYXJ5KGdncGxvdDIpDQpnZ3Bsb3Qobm92X05BLCBhZXMoVGlwZSwgSGFyZ2EpKSArDQogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91ciA9ICJtYWdlbnRhIikgKyANCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKCdBJywnQicsJ0MnKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDEwMDAwMDAwLDE1MDAwMDApKSArDQogIHhsYWIoIlRpcGUiKSArDQogIHlsYWIoIkhhcmdhIikgKw0KICBnZ3RpdGxlKCJEaXN0cmlidXNpIEhhcmdhIFRpcGUgUnVtYWgiKQ0KYGBgDQpCZXJkYXNhcmthbiBkaWFncmFtIGRpYXRhcyBkYXBhdCBkaXNpbXB1bGthbiBiYWh3YSBkaXN0cmlidXNpIGhhcmdhIHRpcGUgcnVtYWggeWFuZyBtZW1pbGlraSBoYXJnYSB0ZXJ0aW5nZ2kgYWRhbGFoIHRpcGUgQS4gRGliYW5kaW5na2FuIGRlbmdhbiB0aXBlIEIgZGFuIEMuDQoNCmBgYHtyfQ0KIyBEaWFncmFtIFBhaQ0KDQpsaWJyYXJ5KHNjYWxlcykNCmxpYnJhcnkoZHBseXIpDQpwbG90ZGF0YSA8LSBub3ZfTkEgJT4lDQogIGNvdW50KFdpbGF5YWgpICU+JQ0KICBhcnJhbmdlKGRlc2MoV2lsYXlhaCkpICU+JQ0KICBtdXRhdGUocHJvcCA9IHJvdW5kKG4qMTAwL3N1bShuKSwxKSwNCiAgICAgICAgIGxhYi55cG9zID0gY3Vtc3VtKHByb3ApIC0gMC41KnByb3ApDQoNCg0KZ2dwbG90KHBsb3RkYXRhLA0KICAgICAgIGFlcyh4ID0gIiIsDQogICAgICAgICAgIHkgPSBwcm9wLA0KICAgICAgICAgICBmaWxsID0gV2lsYXlhaCkpICsNCiAgZ2VvbV9iYXIod2lkdGggPSAxLCBzdGF0ID0gImlkZW50aXR5IiwgY29sb3IgPSAid2hpdGUiKSArDQogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQgPSAwKSArDQogIGdlb21fdGV4dChhZXMoeSA9IGxhYi55cG9zLCBsYWJlbCA9IHByb3ApLCBjb2xvciA9ICgiYmxhY2siKSkgKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJQYWlyZWQiLCBkaXJlY3Rpb249LTEpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgbGFicyh0aXRsZSA9ICJXaWxheWFoIGJhbnlhayBwZW5kdWR1ayAiKQ0KYGBgDQpCZXJkYXNhcmthbiBrZXNpbXB1bGFuIGRpYWdyYW0gZGlhdGFzIGRhcGF0IGRpc2ltcHVsa2FuLCBiYWh3YSB3aWxheWFoIHlhbmcgcGFkYXQgcGVuZHVkdWsgdGVyZGFwYXQgZGkgTWV0cm9wb2xpdGFuIFNlbGF0YW4gZGVuZ2FuIDMxLjklIHBlbmR1ZHVrLg0KDQogDQpgYGB7cn0NCiMgRGlhZ3JhbSBIaXN0b2dyYW0NCg0KZ2dwbG90KG5vdl9OQSwgYWVzKHggPSBEaWJhbmd1bi50YWh1bikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oZmlsbCA9ICJNYWdlbnRhIiwNCiAgICAgICAgICAgICAgICAgY29sb3IgPSAid2hpdGUiLCBiaW5zID0gMzApICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1zZXEoMCwxNzAwLDE4MDApKSsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJQZW1iYW5ndW5hbiBUYWh1biIsDQogICAgICAgeCA9ICJUYWh1biBiYW5ndW5hbiIpDQpgYGANCktlc2ltcHVsYW4gZGFyaSBkaWFncmFtIGRpYXRhcyBhZGFsYWggcGVtYmFuZ3VuYW4geWFuZyBiYW55YWsgZGlsYWt1a2FuIHBhZGEgdGFodW4gc2VraXRhciAyMDAwLWFuLg0KDQoNCmBgYHtyfQ0KIyBQbG90IFNlYmFyYW4gTWVueWVzdWFpa2FuIEdhcmlzDQoNCmxpYnJhcnkoZ2dwbG90MikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB1bnR1ayB2aXN1YWxpc2FzaQ0KZ2dwbG90KG5vdl9OQSwNCiAgICAgICBhZXMoeCA9IFVrdXJhbl90YW5haCwgDQogICAgICAgICAgIHkgPSBIYXJnYSkpICsNCiAgZ2VvbV9wb2ludChjb2xvcj0gInllbGxvdyIpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3IgPSAicmVkIikrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbCA9IHNjYWxlczo6ZG9sbGFyLCANCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoNTAwMDAsIDUwMDAwMDApKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMjUwMCwgMjAwKSwgDQogICAgICAgICAgICAgICAgICAgICBsaW1pdHM9YygwLCAyNTAwKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG1lbmdndW5ha2FuIHRlbWEgbWluaW1hbA0KICBsYWJzKHggPSAiTHVhcyBCYW5ndW5hbiIsDQogICAgICAgeSA9ICJIYXJnYSIsDQogICAgICAgdGl0bGUgPSAiTHVhcyBCYW5ndW5hbiBWcy4gSGFyZ2EiLA0KICAgICAgIHN1YnRpdGxlID0gIkhhcmdhIGRhbiBMdWFzIikrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0ID0gMSkpDQpgYGANCktlc2ltcHVsYW5ueWEgYWRhbGFoIHJ1bWFoIHlhbmcgbWVtaWxpa2kgbHVhcyBrZWNpbCBkYW4gaGFyZ2EgeWFuZyByZW5kYWggYmFueWFrIGRpbWluYXRpIG9sZWggcGVuZHVkdWsuIFNlZGFuZ2thbiBydW1haCB5YW5nIG1lbWlsaWtpIGx1YXMgeWFuZyBiZXNhciBkZW5nYW4gaGFyZ2EgeWFuZyB0aW5nZ2kgamFyYW5nIGRpbWluYXRpIG9sZWggcGVuZHVkdWsuDQoNCmBgYHtyfQ0KIyBQbG90IFNlYmFyYW4gTWVueWVzdWFpa2FuIEdhcmlzDQoNCmxpYnJhcnkoZ2dwbG90MikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB1bnR1ayB2aXN1YWxpc2FzaQ0KZ2dwbG90KG5vdl9OQSwNCiAgICAgICBhZXMoeCA9IFVrdXJhbl90YW5haCwgDQogICAgICAgICAgIHkgPSBIYXJnYSkpICsNCiAgZ2VvbV9wb2ludChjb2xvcj0gIm9yYW5nZSIpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwNCiAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBwb2x5KHgsIDIpLA0KICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVsID0gc2NhbGVzOjpkb2xsYXIsIA0KICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYyg1MDAwMCwgNTAwMDAwMCkpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAyNTAwLCAyMDApLCANCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cz1jKDAsIDI1MDApKSArDQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbWVuZ2d1bmFrYW4gdGVtYSBtaW5pbWFsDQogIGxhYnMoeCA9ICJMdWFzIEJhbmd1bmFuIiwNCiAgICAgICB5ID0gIkhhcmdhIiwNCiAgICAgICB0aXRsZSA9ICJMdWFzIEJhbmd1bmFuIFZzLiBIYXJnYSIsDQogICAgICAgc3VidGl0bGUgPSAiSGFyZ2EgZGFuIEx1YXMiKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3QgPSAxKSkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBEaWFncmFtIEJhdGFuZw0KDQpsaWJyYXJ5KGRwbHlyKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdW50dWsgbWFuaXB1bGFzaSBkYXRhDQpsaWJyYXJ5KGdncGxvdDIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdW50dWsgdmlzdWFsaXNhc2kNCmxpYnJhcnkoc2NhbGVzKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBtZW5lbnR1a2FuIGplZGEgYXRhdSBsYWJlbCBzZWNhcmEgb3RvbWF0aXMNCg0KIyBtZW5naGl0dW5nIGdhamkgcmF0YS1yYXRhIHVudHVrIHNldGlhcCBqYWJhdGFuDQpwbG90ZGF0YSA8LSBub3ZfTkEgJT4lDQogIGdyb3VwX2J5KFdpbGF5YWgpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKG1lYW5fSGFyZ2EgPSBtZWFuKEhhcmdhKSkNCiMgcGxvdCBnYWppIHJhdGEtcmF0YSBkZW5nYW4gY2FyYSB5YW5nIGxlYmloIG1lbmFyaWsNCm15Y29scyA8LSBjKCIjQ0Q1MzRDRkYiLCAiI0VGQzAwMEZGIiwgIiMyRkREOTIiLCIjRkZBQjRDIiwgIiMxMTY1MzAiLCAiIzcyNjdDQiIsIiNDRDUzNENGRiIsICIjRUJFNjQ1IikNCmdncGxvdChwbG90ZGF0YSwgDQogICAgICAgYWVzKHggPSBmYWN0b3IoV2lsYXlhaCwNCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJTZWxhdGFuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVdGFyYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmFyYXQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRpbXVyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUZW5nZ2FyYS5NZXRyb3BvbGl0YW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlV0YXJhLlZpY3RvcmlhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCYXJhdC5WaWN0b3JpYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGltdXIuVmljdG9yaWEiKSksIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuX0hhcmdhKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgDQogICAgICAgICAgIGZpbGwgPSBteWNvbHMpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGRvbGxhcihtZWFuX0hhcmdhKSksIA0KICAgICAgICAgICAgdmp1c3QgPSAtMC41KSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNDAwMDAwMDAsIDUwMDAwMCksIA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBkb2xsYXIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBtZW5nZ3VuYWthbiB0ZW1hIG1pbmltYWwNCiAgbGFicyh0aXRsZSA9ICJSYXRhLXJhdGEgaGFyZ2EgcnVtYWggZGkgYmViZXJhcGEgd2lsYXlhaCIsIA0KICAgICAgIHggPSAiIiwNCiAgICAgICB5ID0gIiIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAwLjUpKQ0KYGBgDQpEYXJpIGRpYWdyYW0gZGlhdGFzIGRhcGF0IGRpc2ltcHVsa2FuIGJhaHdhIHJhdGEtcmF0YSBoYXJnYSBydW1haCBkaSBiZWJlcmFwYSB3aWxheWFoIHlhbmcgbWVtaWxpa2kgaGFyZ2EgdGVydGluZ2dpIGFkYWxhaCB3aWxheWFoIFV0YXJhIGRlbmdhbiAkMSw0NDksNzU5LiBTZWRhbmdrYW4gaGFyZ2EgeWFuZyByZW5kYWggdGVyZGFwYXQgZGkgd2lsYXlhaCBCYXJhdCBWaWN0b3JpYSBkZW5nYW4gaGFyZ2EgJDQ0MSwwODcuDQo=