1. Đọc file dữ liệu

d <- read.csv("D:/PTDLDT/Supermarket Transactions.csv")

2. Chọn các biến định tính

dldt <- c("Gender", "MaritalStatus", "Homeowner","City", "StateorProvince", "Country", "ProductFamily", "ProductDepartment", "ProductCategory")
dldt
## [1] "Gender"            "MaritalStatus"     "Homeowner"        
## [4] "City"              "StateorProvince"   "Country"          
## [7] "ProductFamily"     "ProductDepartment" "ProductCategory"

3. Tạo bộ dữ liệu mới chỉ chứa các biến định tính

dt <- d[, dldt]

4. Xem trước dữ liệu

head(dt)
##   Gender MaritalStatus Homeowner          City StateorProvince Country
## 1      F             S         Y   Los Angeles              CA     USA
## 2      M             M         Y   Los Angeles              CA     USA
## 3      F             M         N     Bremerton              WA     USA
## 4      M             M         Y      Portland              OR     USA
## 5      F             S         Y Beverly Hills              CA     USA
## 6      F             M         Y Beverly Hills              CA     USA
##   ProductFamily ProductDepartment      ProductCategory
## 1          Food       Snack Foods          Snack Foods
## 2          Food           Produce           Vegetables
## 3          Food       Snack Foods          Snack Foods
## 4          Food            Snacks                Candy
## 5         Drink         Beverages Carbonated Beverages
## 6          Food              Deli          Side Dishes

5. Biến Gender

#Lập bảng tần suất của biến Gender
table(dt$Gender)/sum(nrow(dt))
## 
##         F         M 
## 0.5099936 0.4900064
#Lập bảng tần số biến Gender
table(dt$Gender)
## 
##    F    M 
## 7170 6889

Nhận xét: Vậy trong bộ dữ liệu này có 50.9993598 % nữ và 49.0006402% nam.

Biểu đồ

# Bảng tần suất và tỷ lệ %
gender_freq  <- table(dt$Gender)
gender_pct   <- gender_freq / nrow(dt)   # hoặc prop.table(gender_freq)

# Xem nhanh
gender_pct
## 
##         F         M 
## 0.5099936 0.4900064
# Vẽ biểu đồ tròn
pie(gender_freq,
    main   = "Phân bố giới tính (Gender)",
    labels = paste0(names(gender_freq),
                    " (", round(gender_pct*100, 1), "%)"),
    col    = c("lightpink", "lightblue"))   # đổi màu tuỳ thích

6. Biến Homeowner

#Lập bảng tần suất của biến Homeowner
table(dt$Homeowner)/sum(nrow(dt))
## 
##         N         Y 
## 0.3993883 0.6006117
#Lập bảng tần số biến Homeowner
table(dt$Homeowner)
## 
##    N    Y 
## 5615 8444

Nhận xét: Vậy trong bộ dữ liệu này có 39.9388292 % không có nhà và 60.0611708% có nhà.

Biểu đồ

# Bảng tần suất và tỷ lệ %
home_freq <- table(dt$Homeowner)
home_pct  <- home_freq / nrow(dt)   # hoặc prop.table(home_freq)

# Vẽ biểu đồ tròn
pie(home_freq,
    main   = "Tỷ lệ sở hữu nhà (Homeowner)",
    labels = paste0(names(home_freq),
                    " (", round(home_pct*100, 1), "%)"),
    col    = c("lightcoral", "lightgreen"))   # thay màu tùy ý

7. Biến MaritalStatus

#Lập bảng tần suất của biến MaritalStatus
table(dt$MaritalStatus)/sum(nrow(dt))
## 
##         M         S 
## 0.4883704 0.5116296
#Lập bảng tần số của biến MaritalStatus
table(dt$MaritalStatus)
## 
##    M    S 
## 6866 7193

Nhận xét: Vậy trong bộ dữ liệu này có 48.8370439 % đã kết hôn và 51.1629561% độc thân.

Biểu đồ

# Bảng tần số và tỷ lệ %
mar_freq <- table(dt$MaritalStatus)      # đếm từng nhóm
mar_pct  <- mar_freq / nrow(dt)          # tỷ lệ phần trăm

# Xem nhanh
mar_freq
## 
##    M    S 
## 6866 7193
mar_pct
## 
##         M         S 
## 0.4883704 0.5116296
# Vẽ biểu đồ tròn
pie(mar_freq,
    main   = "Phân bố tình trạng hôn nhân (MaritalStatus)",
    labels = paste0(names(mar_freq),
                    " (", round(mar_pct*100, 1), "%)"))

8. Biến City

#Lập bảng tần suất của biến City
table(dt$City)/sum(nrow(dt))
## 
##      Acapulco    Bellingham Beverly Hills     Bremerton       Camacho 
##   0.027242336   0.010171420   0.057685468   0.059321431   0.032150224 
##   Guadalajara       Hidalgo   Los Angeles        Merida   Mexico City 
##   0.005334661   0.060103848   0.065865282   0.046518245   0.013798990 
##       Orizaba      Portland         Salem    San Andres     San Diego 
##   0.033003770   0.062308841   0.098584537   0.044170994   0.061597553 
## San Francisco       Seattle       Spokane        Tacoma     Vancouver 
##   0.009246746   0.065580767   0.062237712   0.089408920   0.045024539 
##      Victoria   Walla Walla        Yakima 
##   0.012518671   0.011380610   0.026744434
#Lập bảng tần số của biến City
table(dt$City)
## 
##      Acapulco    Bellingham Beverly Hills     Bremerton       Camacho 
##           383           143           811           834           452 
##   Guadalajara       Hidalgo   Los Angeles        Merida   Mexico City 
##            75           845           926           654           194 
##       Orizaba      Portland         Salem    San Andres     San Diego 
##           464           876          1386           621           866 
## San Francisco       Seattle       Spokane        Tacoma     Vancouver 
##           130           922           875          1257           633 
##      Victoria   Walla Walla        Yakima 
##           176           160           376

Nhận xét:
- Trong bộ dữ liệu này, thành phố có tỷ lệ giao dịch cao nhất là Salem với khoảng 9.86%, tiếp theo là Tacoma (8.94%), Los Angeles (6.59%) và Seattle (6.56%).

  • Các thành phố nhỏ hơn như Hidalgo (6.01%) hoặc Guadalajara (0.53%) có tỷ lệ thấp hơn nhiều.

  • Điều này cho thấy giao dịch chủ yếu tập trung ở một số thành phố lớn với dân số hoặc hoạt động kinh tế cao hơn. Các thành phố nhỏ hơn đóng góp ít hơn vào tổng số giao dịch, có thể do quy mô thị trường nhỏ hoặc mức độ phổ biến của sản phẩm thấp.

  • Ngoài ra, việc phân bố này cũng có thể phản ánh chiến lược tiếp thị hoặc kênh phân phối mà siêu thị đang tập trung vào các khu vực đô thị lớn.

Biểu đồ

library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
ggplot(dt, aes(x = City)) +
  geom_bar() +
  coord_flip() +                             # xoay ngang cho gọn
  labs(title = "Tần suất giao dịch theo City",
       x = "City", y = "Số giao dịch")

9. Biến StateorProvince

#Lập bảng tần suất của biến StateorProvince
table(dt$StateorProvince)/sum(nrow(dt))
## 
##          BC          CA          DF    Guerrero     Jalisco          OR 
## 0.057543211 0.194395049 0.057969984 0.027242336 0.005334661 0.160893378 
##    Veracruz          WA     Yucatan   Zacatecas 
## 0.033003770 0.324845295 0.046518245 0.092254072
#Lập bảng tần số của biến StateorProvince
table(dt$StateorProvince)
## 
##        BC        CA        DF  Guerrero   Jalisco        OR  Veracruz        WA 
##       809      2733       815       383        75      2262       464      4567 
##   Yucatan Zacatecas 
##       654      1297

Nhận xét: Trong bộ dữ liệu này, bang hoặc tỉnh có tỷ lệ giao dịch lớn nhất là WA với khoảng 32.48%, tiếp theo là CA (19.44%) và OR (16.09%). Các bang như Jalisco (0.53%) và Guerrero (2.72%) chiếm tỷ lệ thấp hơn. Như vậy, dữ liệu cho thấy sự tập trung giao dịch cao ở một số bang chính.

Biểu đồ

ggplot(dt, aes(x = StateorProvince)) +
  geom_bar() +
  coord_flip() +                                # xoay trục cho gọn
  labs(title = "Tần suất giao dịch theo State / Province",
       x = "State / Province",
       y = "Số giao dịch")

10. Biến Country

#Lập bảng tần suất của biến Country
table(dt$Country)/sum(nrow(dt))
## 
##     Canada     Mexico        USA 
## 0.05754321 0.26232307 0.68013372
#Lập bảng tần suất của biến Country
table(dt$Country)
## 
## Canada Mexico    USA 
##    809   3688   9562

Nhận xét: Vậy trong bộ dữ liệu này có 5.7543211 % ở Canada, 26.2323067% ở Mexico và 68.0133722% ở USA.

Biểu đồ

# Bảng tần suất và tỷ lệ %
country_freq <- table(dt$Country)
country_pct  <- country_freq / nrow(dt)      # tỷ lệ phần trăm

# Xem nhanh
country_freq
## 
## Canada Mexico    USA 
##    809   3688   9562
country_pct
## 
##     Canada     Mexico        USA 
## 0.05754321 0.26232307 0.68013372
# ----- Biểu đồ tròn -----
pie(country_freq,
    main   = "Phân bố giao dịch theo Country",
    labels = paste0(names(country_freq),
                    " (", round(country_pct * 100, 1), "%)"))

11. Biến ProductFamily

#Lập bảng tần suất của biến ProductFamily
table(dt$ProductFamily)/sum(nrow(dt))
## 
##          Drink           Food Non-Consumable 
##     0.08891102     0.72217085     0.18891813
#Lập bảng tần suất của biến ProductFamily
table(dt$ProductFamily)
## 
##          Drink           Food Non-Consumable 
##           1250          10153           2656

Nhận xét: Vậy trong bộ dữ liệu này có 8.8911018 % đồ uống, 72.2170851% thức ăn và 18.8918131% không tiêu thụ được.

Biểu đồ

# Bảng tần suất và tỷ lệ %
pfreq <- sort(table(dt$ProductFamily), decreasing = TRUE)   # sắp xếp giảm dần
ppct  <- pfreq / nrow(dt)                                   # tỷ lệ %

pie(pfreq,
    main   = "Phân bố giao dịch theo Product Family",
    labels = paste0(names(pfreq),
                    " (", round(ppct*100, 1), "%)"))

12. Biến ProductDepartment

#Lập bảng tần suất của biến ProductDepartment
table(dt$ProductDepartment)/sum(nrow(dt))
## 
## Alcoholic Beverages         Baked Goods        Baking Goods           Beverages 
##         0.025321858         0.030229746         0.076250089         0.048367594 
##     Breakfast Foods        Canned Foods     Canned Products            Carousel 
##         0.013372217         0.069492852         0.007753041         0.004196600 
##            Checkout               Dairy                Deli                Eggs 
##         0.005832563         0.064229319         0.049719041         0.014083505 
##        Frozen Foods  Health and Hygiene           Household                Meat 
##         0.098300021         0.063518031         0.101002916         0.006330464 
##         Periodicals             Produce             Seafood         Snack Foods 
##         0.014368020         0.141830856         0.007255139         0.113806103 
##              Snacks       Starchy Foods 
##         0.025037343         0.019702682
#Lập bảng tần suất của biến ProductDepartment
table(dt$ProductDepartment)
## 
## Alcoholic Beverages         Baked Goods        Baking Goods           Beverages 
##                 356                 425                1072                 680 
##     Breakfast Foods        Canned Foods     Canned Products            Carousel 
##                 188                 977                 109                  59 
##            Checkout               Dairy                Deli                Eggs 
##                  82                 903                 699                 198 
##        Frozen Foods  Health and Hygiene           Household                Meat 
##                1382                 893                1420                  89 
##         Periodicals             Produce             Seafood         Snack Foods 
##                 202                1994                 102                1600 
##              Snacks       Starchy Foods 
##                 352                 277

Nhận xét: Trong bộ dữ liệu, nhóm sản phẩm có tỷ lệ giao dịch cao nhất là Produce với 14.18%, tiếp theo là Snack Foods (11.38%) và Household (10.1%). Nhóm Frozen Foods cũng chiếm tỷ lệ đáng kể là 9.83%. Các nhóm như Carousel (0.42%) và Checkout (0.58%) có tỷ lệ thấp hơn nhiều.

Biểu đồ

ggplot(dt, aes(x = ProductDepartment)) +
  geom_bar() +
  coord_flip() +  # xoay ngang nhãn cho dễ đọc
  labs(title = "Tần suất giao dịch theo Product Department",
       x = "Product Department",
       y = "Số giao dịch")

13. Biến ProductCategory

#Lập bảng tần suất của biến ProductCategory
table(dt$ProductCategory)/sum(nrow(dt))
## 
##         Baking Goods    Bathroom Products        Beer and Wine 
##          0.034426346          0.025962017          0.025321858 
##                Bread      Breakfast Foods              Candles 
##          0.030229746          0.029660716          0.003200797 
##                Candy     Canned Anchovies         Canned Clams 
##          0.025037343          0.003129668          0.003769827 
##       Canned Oysters      Canned Sardines        Canned Shrimp 
##          0.002489508          0.002845153          0.002702895 
##          Canned Soup          Canned Tuna Carbonated Beverages 
##          0.028736041          0.006188207          0.010953837 
##    Cleaning Supplies        Cold Remedies                Dairy 
##          0.013443346          0.006614980          0.064229319 
##        Decongestants               Drinks                 Eggs 
##          0.006045949          0.009602390          0.014083505 
##           Electrical      Frozen Desserts       Frozen Entrees 
##          0.025250729          0.022974607          0.008393200 
##                Fruit             Hardware        Hot Beverages 
##          0.054413543          0.009175617          0.016075112 
##              Hygiene     Jams and Jellies     Kitchen Products 
##          0.014012376          0.041823743          0.015434953 
##            Magazines                 Meat        Miscellaneous 
##          0.014368020          0.054129028          0.002987410 
##  Packaged Vegetables       Pain Relievers       Paper Products 
##          0.003414183          0.013656732          0.024539441 
##                Pizza     Plastic Products Pure Juice Beverages 
##          0.013798990          0.010029163          0.011736254 
##              Seafood          Side Dishes          Snack Foods 
##          0.007255139          0.010882709          0.113806103 
##            Specialty        Starchy Foods           Vegetables 
##          0.020556227          0.019702682          0.122910591
#Lập bảng tần suất của biến ProductCategory
table(dt$ProductCategory)
## 
##         Baking Goods    Bathroom Products        Beer and Wine 
##                  484                  365                  356 
##                Bread      Breakfast Foods              Candles 
##                  425                  417                   45 
##                Candy     Canned Anchovies         Canned Clams 
##                  352                   44                   53 
##       Canned Oysters      Canned Sardines        Canned Shrimp 
##                   35                   40                   38 
##          Canned Soup          Canned Tuna Carbonated Beverages 
##                  404                   87                  154 
##    Cleaning Supplies        Cold Remedies                Dairy 
##                  189                   93                  903 
##        Decongestants               Drinks                 Eggs 
##                   85                  135                  198 
##           Electrical      Frozen Desserts       Frozen Entrees 
##                  355                  323                  118 
##                Fruit             Hardware        Hot Beverages 
##                  765                  129                  226 
##              Hygiene     Jams and Jellies     Kitchen Products 
##                  197                  588                  217 
##            Magazines                 Meat        Miscellaneous 
##                  202                  761                   42 
##  Packaged Vegetables       Pain Relievers       Paper Products 
##                   48                  192                  345 
##                Pizza     Plastic Products Pure Juice Beverages 
##                  194                  141                  165 
##              Seafood          Side Dishes          Snack Foods 
##                  102                  153                 1600 
##            Specialty        Starchy Foods           Vegetables 
##                  289                  277                 1728

Nhận xét: Trong bộ dữ liệu, nhóm sản phẩm có tỷ lệ giao dịch cao nhất là Vegetables với 12.29%, tiếp theo là Snack Foods (11.38%) và Dairy (6.42%). Các nhóm đóng hộp như Canned Oysters (0.25%) và Canned Clams (0.38%) chiếm tỷ lệ rất nhỏ, cho thấy sự ưu tiên mua hàng tươi và đồ ăn nhẹ.

Biểu đồ

# Vẽ biểu đồ cột tần suất ProductCategory
ggplot(dt, aes(x = reorder(ProductCategory, ProductCategory, function(x) -length(x)))) +
  geom_bar(fill = "steelblue") +
  coord_flip() +  # Xoay trục để nhãn dễ đọc hơn
  labs(title = "Tần suất giao dịch theo Product Category",
       x = "Product Category",
       y = "Số giao dịch") +
  theme_minimal()

LS0tDQp0aXRsZTogIkJUMSINCmF1dGhvcjogIkzDqiBUaOG7iyBOZ+G7jWMgw4FuaCINCmRhdGU6ICIyMDI1LTA1LTE5Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdG9jOiB0cnVlDQogIHBkZl9kb2N1bWVudDoNCiAgICBsYXRleF9lbmdpbmU6IHhlbGF0ZXgNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQo8c3R5bGU+DQpib2R5IHsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBzYW5zLXNlcmlmOw0KICBmb250LXNpemU6IDE2cHg7DQogIHRleHQtYWxpZ246IGp1c3RpZnk7DQogIGxpbmUtaGVpZ2h0OiAxLjU7DQp9DQpoMiB7DQogIGNvbG9yOiByZWQ7DQp9DQpoMyB7DQogIGNvbG9yOiBkYXJrYmx1ZTsNCn0NCjwvc3R5bGU+DQoNCiMgMS4gxJDhu41jIGZpbGUgZOG7ryBsaeG7h3UNCg0KYGBge3J9DQpkIDwtIHJlYWQuY3N2KCJEOi9QVERMRFQvU3VwZXJtYXJrZXQgVHJhbnNhY3Rpb25zLmNzdiIpDQpgYGANCg0KIyAyLiBDaOG7jW4gY8OhYyBiaeG6v24gxJHhu4tuaCB0w61uaA0KDQpgYGB7cn0NCmRsZHQgPC0gYygiR2VuZGVyIiwgIk1hcml0YWxTdGF0dXMiLCAiSG9tZW93bmVyIiwiQ2l0eSIsICJTdGF0ZW9yUHJvdmluY2UiLCAiQ291bnRyeSIsICJQcm9kdWN0RmFtaWx5IiwgIlByb2R1Y3REZXBhcnRtZW50IiwgIlByb2R1Y3RDYXRlZ29yeSIpDQpkbGR0DQpgYGANCiANCiMgMy4gVOG6oW8gYuG7mSBk4buvIGxp4buHdSBt4bubaSBjaOG7iSBjaOG7qWEgY8OhYyBiaeG6v24gxJHhu4tuaCB0w61uaA0KDQpgYGB7cn0NCmR0IDwtIGRbLCBkbGR0XQ0KYGBgDQoNCiMgNC4gWGVtIHRyxrDhu5tjIGThu68gbGnhu4d1DQoNCmBgYHtyfQ0KaGVhZChkdCkNCmBgYA0KIyA1LiBCaeG6v24gR2VuZGVyDQoNCmBgYHtyfQ0KI0zhuq1wIGLhuqNuZyB04bqnbiBzdeG6pXQgY+G7p2EgYmnhur9uIEdlbmRlcg0KdGFibGUoZHQkR2VuZGVyKS9zdW0obnJvdyhkdCkpDQpgYGANCmBgYHtyfQ0KI0zhuq1wIGLhuqNuZyB04bqnbiBz4buRIGJp4bq/biBHZW5kZXINCnRhYmxlKGR0JEdlbmRlcikNCmBgYA0KKipOaOG6rW4geMOpdDoqKiBW4bqteSB0cm9uZyBi4buZIGThu68gbGnhu4d1IG7DoHkgY8OzIGByIHRhYmxlKGR0JEdlbmRlcilbMV0vc3VtKG5yb3coZHQpKSoxMDBgIFwlIG7hu68gdsOgICBgciB0YWJsZShkdCRHZW5kZXIpWzJdL3N1bShucm93KGR0KSkqMTAwYFwlIG5hbS4NCg0KKipCaeG7g3UgxJHhu5MqKg0KDQpgYGB7cn0NCiMgQuG6o25nIHThuqduIHN14bqldCB2w6AgdOG7tyBs4buHICUNCmdlbmRlcl9mcmVxICA8LSB0YWJsZShkdCRHZW5kZXIpDQpnZW5kZXJfcGN0ICAgPC0gZ2VuZGVyX2ZyZXEgLyBucm93KGR0KSAgICMgaG/hurdjIHByb3AudGFibGUoZ2VuZGVyX2ZyZXEpDQoNCiMgWGVtIG5oYW5oDQpnZW5kZXJfcGN0DQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgdHLDsm4NCnBpZShnZW5kZXJfZnJlcSwNCiAgICBtYWluICAgPSAiUGjDom4gYuG7kSBnaeG7m2kgdMOtbmggKEdlbmRlcikiLA0KICAgIGxhYmVscyA9IHBhc3RlMChuYW1lcyhnZW5kZXJfZnJlcSksDQogICAgICAgICAgICAgICAgICAgICIgKCIsIHJvdW5kKGdlbmRlcl9wY3QqMTAwLCAxKSwgIiUpIiksDQogICAgY29sICAgID0gYygibGlnaHRwaW5rIiwgImxpZ2h0Ymx1ZSIpKSAgICMgxJHhu5VpIG3DoHUgdHXhu7MgdGjDrWNoDQpgYGANCg0KDQojIDYuIEJp4bq/biBIb21lb3duZXINCmBgYHtyfQ0KI0zhuq1wIGLhuqNuZyB04bqnbiBzdeG6pXQgY+G7p2EgYmnhur9uIEhvbWVvd25lcg0KdGFibGUoZHQkSG9tZW93bmVyKS9zdW0obnJvdyhkdCkpDQpgYGANCmBgYHtyfQ0KI0zhuq1wIGLhuqNuZyB04bqnbiBz4buRIGJp4bq/biBIb21lb3duZXINCnRhYmxlKGR0JEhvbWVvd25lcikNCmBgYA0KKipOaOG6rW4geMOpdDoqKiBW4bqteSB0cm9uZyBi4buZIGThu68gbGnhu4d1IG7DoHkgY8OzIGByIHRhYmxlKGR0JEhvbWVvd25lcilbMV0vc3VtKG5yb3coZHQpKSoxMDBgIFwlIGtow7RuZyBjw7MgbmjDoCB2w6AgIGByIHRhYmxlKGR0JEhvbWVvd25lcilbMl0vc3VtKG5yb3coZHQpKSoxMDBgXCUgY8OzIG5ow6AuDQoNCioqQmnhu4N1IMSR4buTKioNCg0KYGBge3J9DQojIELhuqNuZyB04bqnbiBzdeG6pXQgdsOgIHThu7cgbOG7hyAlDQpob21lX2ZyZXEgPC0gdGFibGUoZHQkSG9tZW93bmVyKQ0KaG9tZV9wY3QgIDwtIGhvbWVfZnJlcSAvIG5yb3coZHQpICAgIyBob+G6t2MgcHJvcC50YWJsZShob21lX2ZyZXEpDQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgdHLDsm4NCnBpZShob21lX2ZyZXEsDQogICAgbWFpbiAgID0gIlThu7cgbOG7hyBz4bufIGjhu691IG5ow6AgKEhvbWVvd25lcikiLA0KICAgIGxhYmVscyA9IHBhc3RlMChuYW1lcyhob21lX2ZyZXEpLA0KICAgICAgICAgICAgICAgICAgICAiICgiLCByb3VuZChob21lX3BjdCoxMDAsIDEpLCAiJSkiKSwNCiAgICBjb2wgICAgPSBjKCJsaWdodGNvcmFsIiwgImxpZ2h0Z3JlZW4iKSkgICAjIHRoYXkgbcOgdSB0w7l5IMO9DQoNCmBgYA0KDQoNCiMgNy4gQmnhur9uIE1hcml0YWxTdGF0dXMNCmBgYHtyfQ0KI0zhuq1wIGLhuqNuZyB04bqnbiBzdeG6pXQgY+G7p2EgYmnhur9uIE1hcml0YWxTdGF0dXMNCnRhYmxlKGR0JE1hcml0YWxTdGF0dXMpL3N1bShucm93KGR0KSkNCmBgYA0KYGBge3J9DQojTOG6rXAgYuG6o25nIHThuqduIHPhu5EgY+G7p2EgYmnhur9uIE1hcml0YWxTdGF0dXMNCnRhYmxlKGR0JE1hcml0YWxTdGF0dXMpDQpgYGANCioqTmjhuq1uIHjDqXQ6KiogIFbhuq15IHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgbsOgeSBjw7MgYHIgdGFibGUoZHQkTWFyaXRhbFN0YXR1cylbMV0vc3VtKG5yb3coZHQpKSoxMDBgIFwlIMSRw6Mga+G6v3QgaMO0biB2w6AgIGByIHRhYmxlKGR0JE1hcml0YWxTdGF0dXMpWzJdL3N1bShucm93KGR0KSkqMTAwYFwlIMSR4buZYyB0aMOibi4NCg0KKipCaeG7g3UgxJHhu5MqKg0KYGBge3J9DQojIELhuqNuZyB04bqnbiBz4buRIHbDoCB04bu3IGzhu4cgJQ0KbWFyX2ZyZXEgPC0gdGFibGUoZHQkTWFyaXRhbFN0YXR1cykgICAgICAjIMSR4bq/bSB04burbmcgbmjDs20NCm1hcl9wY3QgIDwtIG1hcl9mcmVxIC8gbnJvdyhkdCkgICAgICAgICAgIyB04bu3IGzhu4cgcGjhuqduIHRyxINtDQoNCiMgWGVtIG5oYW5oDQptYXJfZnJlcQ0KbWFyX3BjdA0KDQojIFbhur0gYmnhu4N1IMSR4buTIHRyw7JuDQpwaWUobWFyX2ZyZXEsDQogICAgbWFpbiAgID0gIlBow6JuIGLhu5EgdMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIChNYXJpdGFsU3RhdHVzKSIsDQogICAgbGFiZWxzID0gcGFzdGUwKG5hbWVzKG1hcl9mcmVxKSwNCiAgICAgICAgICAgICAgICAgICAgIiAoIiwgcm91bmQobWFyX3BjdCoxMDAsIDEpLCAiJSkiKSkNCmBgYA0KDQoNCiMgOC4gQmnhur9uIENpdHkNCmBgYHtyfQ0KI0zhuq1wIGLhuqNuZyB04bqnbiBzdeG6pXQgY+G7p2EgYmnhur9uIENpdHkNCnRhYmxlKGR0JENpdHkpL3N1bShucm93KGR0KSkNCmBgYA0KDQoNCmBgYHtyfQ0KI0zhuq1wIGLhuqNuZyB04bqnbiBz4buRIGPhu6dhIGJp4bq/biBDaXR5DQp0YWJsZShkdCRDaXR5KQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQ6KiogIA0KLSBUcm9uZyBi4buZIGThu68gbGnhu4d1IG7DoHksIHRow6BuaCBwaOG7kSBjw7MgdOG7tyBs4buHIGdpYW8gZOG7i2NoIGNhbyBuaOG6pXQgbMOgIFNhbGVtIHbhu5tpIGtob+G6o25nIGByIHJvdW5kKHRhYmxlKGR0JENpdHkpWyJTYWxlbSJdL25yb3coZHQpKjEwMCwgMilgJSwgdGnhur9wIHRoZW8gbMOgIFRhY29tYSAoYHIgcm91bmQodGFibGUoZHQkQ2l0eSlbIlRhY29tYSJdL25yb3coZHQpKjEwMCwgMilgJSksIExvcyBBbmdlbGVzIChgciByb3VuZCh0YWJsZShkdCRDaXR5KVsiTG9zIEFuZ2VsZXMiXS9ucm93KGR0KSoxMDAsIDIpYCUpIHbDoCBTZWF0dGxlIChgciByb3VuZCh0YWJsZShkdCRDaXR5KVsiU2VhdHRsZSJdL25yb3coZHQpKjEwMCwgMilgJSkuICANCg0KLSBDw6FjIHRow6BuaCBwaOG7kSBuaOG7jyBoxqFuIG5oxrAgSGlkYWxnbyAoYHIgcm91bmQodGFibGUoZHQkQ2l0eSlbIkhpZGFsZ28iXS9ucm93KGR0KSoxMDAsIDIpYCUpIGhv4bq3YyBHdWFkYWxhamFyYSAoYHIgcm91bmQodGFibGUoZHQkQ2l0eSlbIkd1YWRhbGFqYXJhIl0vbnJvdyhkdCkqMTAwLCAyKWAlKSBjw7MgdOG7tyBs4buHIHRo4bqlcCBoxqFuIG5oaeG7gXUuICANCg0KLSDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSBnaWFvIGThu4tjaCBjaOG7pyB54bq/dSB04bqtcCB0cnVuZyDhu58gbeG7mXQgc+G7kSB0aMOgbmggcGjhu5EgbOG7m24gduG7m2kgZMOibiBz4buRIGhv4bq3YyBob+G6oXQgxJHhu5luZyBraW5oIHThur8gY2FvIGjGoW4uIEPDoWMgdGjDoG5oIHBo4buRIG5o4buPIGjGoW4gxJHDs25nIGfDs3Agw610IGjGoW4gdsOgbyB04buVbmcgc+G7kSBnaWFvIGThu4tjaCwgY8OzIHRo4buDIGRvIHF1eSBtw7QgdGjhu4sgdHLGsOG7nW5nIG5o4buPIGhv4bq3YyBt4bupYyDEkeG7mSBwaOG7lSBiaeG6v24gY+G7p2Egc+G6o24gcGjhuqltIHRo4bqlcC4gIA0KDQotIE5nb8OgaSByYSwgdmnhu4djIHBow6JuIGLhu5EgbsOgeSBjxaluZyBjw7MgdGjhu4MgcGjhuqNuIMOhbmggY2hp4bq/biBsxrDhu6NjIHRp4bq/cCB0aOG7iyBob+G6t2Mga8OqbmggcGjDom4gcGjhu5FpIG3DoCBzacOqdSB0aOG7iyDEkWFuZyB04bqtcCB0cnVuZyB2w6BvIGPDoWMga2h1IHbhu7FjIMSRw7QgdGjhu4sgbOG7m24uDQoNCioqQmnhu4N1IMSR4buTKioNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQpnZ3Bsb3QoZHQsIGFlcyh4ID0gQ2l0eSkpICsNCiAgZ2VvbV9iYXIoKSArDQogIGNvb3JkX2ZsaXAoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHhvYXkgbmdhbmcgY2hvIGfhu41uDQogIGxhYnModGl0bGUgPSAiVOG6p24gc3XhuqV0IGdpYW8gZOG7i2NoIHRoZW8gQ2l0eSIsDQogICAgICAgeCA9ICJDaXR5IiwgeSA9ICJT4buRIGdpYW8gZOG7i2NoIikNCmBgYA0KDQojIDkuIEJp4bq/biBTdGF0ZW9yUHJvdmluY2UNCmBgYHtyfQ0KI0zhuq1wIGLhuqNuZyB04bqnbiBzdeG6pXQgY+G7p2EgYmnhur9uIFN0YXRlb3JQcm92aW5jZQ0KdGFibGUoZHQkU3RhdGVvclByb3ZpbmNlKS9zdW0obnJvdyhkdCkpDQpgYGANCmBgYHtyfQ0KI0zhuq1wIGLhuqNuZyB04bqnbiBz4buRIGPhu6dhIGJp4bq/biBTdGF0ZW9yUHJvdmluY2UNCnRhYmxlKGR0JFN0YXRlb3JQcm92aW5jZSkNCmBgYA0KDQoqKk5o4bqtbiB4w6l0OioqIFRyb25nIGLhu5kgZOG7ryBsaeG7h3UgbsOgeSwgYmFuZyBob+G6t2MgdOG7iW5oIGPDsyB04bu3IGzhu4cgZ2lhbyBk4buLY2ggbOG7m24gbmjhuqV0IGzDoCBXQSB24bubaSBraG/huqNuZyBgciByb3VuZCh0YWJsZShkdCRTdGF0ZW9yUHJvdmluY2UpWyJXQSJdL25yb3coZHQpKjEwMCwgMilgJSwgdGnhur9wIHRoZW8gbMOgIENBIChgciByb3VuZCh0YWJsZShkdCRTdGF0ZW9yUHJvdmluY2UpWyJDQSJdL25yb3coZHQpKjEwMCwgMilgJSkgdsOgIE9SIChgciByb3VuZCh0YWJsZShkdCRTdGF0ZW9yUHJvdmluY2UpWyJPUiJdL25yb3coZHQpKjEwMCwgMilgJSkuIEPDoWMgYmFuZyBuaMawIEphbGlzY28gKGByIHJvdW5kKHRhYmxlKGR0JFN0YXRlb3JQcm92aW5jZSlbIkphbGlzY28iXS9ucm93KGR0KSoxMDAsIDIpYCUpIHbDoCBHdWVycmVybyAoYHIgcm91bmQodGFibGUoZHQkU3RhdGVvclByb3ZpbmNlKVsiR3VlcnJlcm8iXS9ucm93KGR0KSoxMDAsIDIpYCUpIGNoaeG6v20gdOG7tyBs4buHIHRo4bqlcCBoxqFuLiBOaMawIHbhuq15LCBk4buvIGxp4buHdSBjaG8gdGjhuqV5IHPhu7EgdOG6rXAgdHJ1bmcgZ2lhbyBk4buLY2ggY2FvIOG7nyBt4buZdCBz4buRIGJhbmcgY2jDrW5oLg0KDQoqKkJp4buDdSDEkeG7kyoqDQoNCmBgYHtyfQ0KZ2dwbG90KGR0LCBhZXMoeCA9IFN0YXRlb3JQcm92aW5jZSkpICsNCiAgZ2VvbV9iYXIoKSArDQogIGNvb3JkX2ZsaXAoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHhvYXkgdHLhu6VjIGNobyBn4buNbg0KICBsYWJzKHRpdGxlID0gIlThuqduIHN14bqldCBnaWFvIGThu4tjaCB0aGVvIFN0YXRlIC8gUHJvdmluY2UiLA0KICAgICAgIHggPSAiU3RhdGUgLyBQcm92aW5jZSIsDQogICAgICAgeSA9ICJT4buRIGdpYW8gZOG7i2NoIikNCmBgYA0KDQojIDEwLiBCaeG6v24gQ291bnRyeQ0KYGBge3J9DQojTOG6rXAgYuG6o25nIHThuqduIHN14bqldCBj4bunYSBiaeG6v24gQ291bnRyeQ0KdGFibGUoZHQkQ291bnRyeSkvc3VtKG5yb3coZHQpKQ0KYGBgDQpgYGB7cn0NCiNM4bqtcCBi4bqjbmcgdOG6p24gc3XhuqV0IGPhu6dhIGJp4bq/biBDb3VudHJ5DQp0YWJsZShkdCRDb3VudHJ5KQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIFbhuq15IHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgbsOgeSBjw7MgYHIgdGFibGUoZHQkQ291bnRyeSlbMV0vc3VtKG5yb3coZHQpKSoxMDBgIFwlIOG7nyBDYW5hZGEsIGByIHRhYmxlKGR0JENvdW50cnkpWzJdL3N1bShucm93KGR0KSkqMTAwYFwlIOG7nyBNZXhpY28gdsOgIGByIHRhYmxlKGR0JENvdW50cnkpWzNdL3N1bShucm93KGR0KSkqMTAwYFwlIOG7nyBVU0EuDQoNCioqQmnhu4N1IMSR4buTKioNCg0KYGBge3J9DQojIELhuqNuZyB04bqnbiBzdeG6pXQgdsOgIHThu7cgbOG7hyAlDQpjb3VudHJ5X2ZyZXEgPC0gdGFibGUoZHQkQ291bnRyeSkNCmNvdW50cnlfcGN0ICA8LSBjb3VudHJ5X2ZyZXEgLyBucm93KGR0KSAgICAgICMgdOG7tyBs4buHIHBo4bqnbiB0csSDbQ0KDQojIFhlbSBuaGFuaA0KY291bnRyeV9mcmVxDQpjb3VudHJ5X3BjdA0KDQojIC0tLS0tIEJp4buDdSDEkeG7kyB0csOybiAtLS0tLQ0KcGllKGNvdW50cnlfZnJlcSwNCiAgICBtYWluICAgPSAiUGjDom4gYuG7kSBnaWFvIGThu4tjaCB0aGVvIENvdW50cnkiLA0KICAgIGxhYmVscyA9IHBhc3RlMChuYW1lcyhjb3VudHJ5X2ZyZXEpLA0KICAgICAgICAgICAgICAgICAgICAiICgiLCByb3VuZChjb3VudHJ5X3BjdCAqIDEwMCwgMSksICIlKSIpKQ0KYGBgDQoNCg0KIyAxMS4gQmnhur9uIFByb2R1Y3RGYW1pbHkNCmBgYHtyfQ0KI0zhuq1wIGLhuqNuZyB04bqnbiBzdeG6pXQgY+G7p2EgYmnhur9uIFByb2R1Y3RGYW1pbHkNCnRhYmxlKGR0JFByb2R1Y3RGYW1pbHkpL3N1bShucm93KGR0KSkNCmBgYA0KDQpgYGB7cn0NCiNM4bqtcCBi4bqjbmcgdOG6p24gc3XhuqV0IGPhu6dhIGJp4bq/biBQcm9kdWN0RmFtaWx5DQp0YWJsZShkdCRQcm9kdWN0RmFtaWx5KQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIFbhuq15IHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgbsOgeSBjw7MgYHIgdGFibGUoZHQkUHJvZHVjdEZhbWlseSlbMV0vc3VtKG5yb3coZHQpKSoxMDBgIFwlIMSR4buTIHXhu5FuZywgYHIgdGFibGUoZHQkUHJvZHVjdEZhbWlseSlbMl0vc3VtKG5yb3coZHQpKSoxMDBgXCUgdGjhu6ljIMSDbiB2w6AgYHIgdGFibGUoZHQkUHJvZHVjdEZhbWlseSlbM10vc3VtKG5yb3coZHQpKSoxMDBgXCUga2jDtG5nIHRpw6p1IHRo4bulIMSRxrDhu6NjLg0KDQoqKkJp4buDdSDEkeG7kyoqDQoNCmBgYHtyfQ0KIyBC4bqjbmcgdOG6p24gc3XhuqV0IHbDoCB04bu3IGzhu4cgJQ0KcGZyZXEgPC0gc29ydCh0YWJsZShkdCRQcm9kdWN0RmFtaWx5KSwgZGVjcmVhc2luZyA9IFRSVUUpICAgIyBz4bqvcCB44bq/cCBnaeG6o20gZOG6p24NCnBwY3QgIDwtIHBmcmVxIC8gbnJvdyhkdCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdOG7tyBs4buHICUNCg0KcGllKHBmcmVxLA0KICAgIG1haW4gICA9ICJQaMOibiBi4buRIGdpYW8gZOG7i2NoIHRoZW8gUHJvZHVjdCBGYW1pbHkiLA0KICAgIGxhYmVscyA9IHBhc3RlMChuYW1lcyhwZnJlcSksDQogICAgICAgICAgICAgICAgICAgICIgKCIsIHJvdW5kKHBwY3QqMTAwLCAxKSwgIiUpIikpDQoNCmBgYA0KDQoNCiMgMTIuIEJp4bq/biBQcm9kdWN0RGVwYXJ0bWVudA0KYGBge3J9DQojTOG6rXAgYuG6o25nIHThuqduIHN14bqldCBj4bunYSBiaeG6v24gUHJvZHVjdERlcGFydG1lbnQNCnRhYmxlKGR0JFByb2R1Y3REZXBhcnRtZW50KS9zdW0obnJvdyhkdCkpDQpgYGANCg0KDQpgYGB7cn0NCiNM4bqtcCBi4bqjbmcgdOG6p24gc3XhuqV0IGPhu6dhIGJp4bq/biBQcm9kdWN0RGVwYXJ0bWVudA0KdGFibGUoZHQkUHJvZHVjdERlcGFydG1lbnQpDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKiBUcm9uZyBi4buZIGThu68gbGnhu4d1LCBuaMOzbSBz4bqjbiBwaOG6qW0gY8OzIHThu7cgbOG7hyBnaWFvIGThu4tjaCBjYW8gbmjhuqV0IGzDoCBQcm9kdWNlIHbhu5tpIGByIHJvdW5kKHRhYmxlKGR0JFByb2R1Y3REZXBhcnRtZW50KVsiUHJvZHVjZSJdL25yb3coZHQpKjEwMCwgMilgJSwgdGnhur9wIHRoZW8gbMOgIFNuYWNrIEZvb2RzIChgciByb3VuZCh0YWJsZShkdCRQcm9kdWN0RGVwYXJ0bWVudClbIlNuYWNrIEZvb2RzIl0vbnJvdyhkdCkqMTAwLCAyKWAlKSB2w6AgSG91c2Vob2xkIChgciByb3VuZCh0YWJsZShkdCRQcm9kdWN0RGVwYXJ0bWVudClbIkhvdXNlaG9sZCJdL25yb3coZHQpKjEwMCwgMilgJSkuIE5ow7NtIEZyb3plbiBGb29kcyBjxaluZyBjaGnhur9tIHThu7cgbOG7hyDEkcOhbmcga+G7gyBsw6AgYHIgcm91bmQodGFibGUoZHQkUHJvZHVjdERlcGFydG1lbnQpWyJGcm96ZW4gRm9vZHMiXS9ucm93KGR0KSoxMDAsIDIpYCUuIEPDoWMgbmjDs20gbmjGsCBDYXJvdXNlbCAoYHIgcm91bmQodGFibGUoZHQkUHJvZHVjdERlcGFydG1lbnQpWyJDYXJvdXNlbCJdL25yb3coZHQpKjEwMCwgMilgJSkgdsOgIENoZWNrb3V0IChgciByb3VuZCh0YWJsZShkdCRQcm9kdWN0RGVwYXJ0bWVudClbIkNoZWNrb3V0Il0vbnJvdyhkdCkqMTAwLCAyKWAlKSBjw7MgdOG7tyBs4buHIHRo4bqlcCBoxqFuIG5oaeG7gXUuDQoNCioqQmnhu4N1IMSR4buTKioNCg0KYGBge3J9DQpnZ3Bsb3QoZHQsIGFlcyh4ID0gUHJvZHVjdERlcGFydG1lbnQpKSArDQogIGdlb21fYmFyKCkgKw0KICBjb29yZF9mbGlwKCkgKyAgIyB4b2F5IG5nYW5nIG5ow6NuIGNobyBk4buFIMSR4buNYw0KICBsYWJzKHRpdGxlID0gIlThuqduIHN14bqldCBnaWFvIGThu4tjaCB0aGVvIFByb2R1Y3QgRGVwYXJ0bWVudCIsDQogICAgICAgeCA9ICJQcm9kdWN0IERlcGFydG1lbnQiLA0KICAgICAgIHkgPSAiU+G7kSBnaWFvIGThu4tjaCIpDQpgYGANCg0KDQojIDEzLiBCaeG6v24gUHJvZHVjdENhdGVnb3J5DQpgYGB7cn0NCiNM4bqtcCBi4bqjbmcgdOG6p24gc3XhuqV0IGPhu6dhIGJp4bq/biBQcm9kdWN0Q2F0ZWdvcnkNCnRhYmxlKGR0JFByb2R1Y3RDYXRlZ29yeSkvc3VtKG5yb3coZHQpKQ0KYGBgDQoNCg0KYGBge3J9DQojTOG6rXAgYuG6o25nIHThuqduIHN14bqldCBj4bunYSBiaeG6v24gUHJvZHVjdENhdGVnb3J5DQp0YWJsZShkdCRQcm9kdWN0Q2F0ZWdvcnkpDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKiBUcm9uZyBi4buZIGThu68gbGnhu4d1LCBuaMOzbSBz4bqjbiBwaOG6qW0gY8OzIHThu7cgbOG7hyBnaWFvIGThu4tjaCBjYW8gbmjhuqV0IGzDoCBWZWdldGFibGVzIHbhu5tpIGByIHJvdW5kKHRhYmxlKGR0JFByb2R1Y3RDYXRlZ29yeSlbIlZlZ2V0YWJsZXMiXS9ucm93KGR0KSoxMDAsIDIpYCUsIHRp4bq/cCB0aGVvIGzDoCBTbmFjayBGb29kcyAoYHIgcm91bmQodGFibGUoZHQkUHJvZHVjdENhdGVnb3J5KVsiU25hY2sgRm9vZHMiXS9ucm93KGR0KSoxMDAsIDIpYCUpIHbDoCBEYWlyeSAoYHIgcm91bmQodGFibGUoZHQkUHJvZHVjdENhdGVnb3J5KVsiRGFpcnkiXS9ucm93KGR0KSoxMDAsIDIpYCUpLiBDw6FjIG5ow7NtIMSRw7NuZyBo4buZcCBuaMawIENhbm5lZCBPeXN0ZXJzIChgciByb3VuZCh0YWJsZShkdCRQcm9kdWN0Q2F0ZWdvcnkpWyJDYW5uZWQgT3lzdGVycyJdL25yb3coZHQpKjEwMCwgMilgJSkgdsOgIENhbm5lZCBDbGFtcyAoYHIgcm91bmQodGFibGUoZHQkUHJvZHVjdENhdGVnb3J5KVsiQ2FubmVkIENsYW1zIl0vbnJvdyhkdCkqMTAwLCAyKWAlKSBjaGnhur9tIHThu7cgbOG7hyBy4bqldCBuaOG7jywgY2hvIHRo4bqleSBz4buxIMawdSB0acOqbiBtdWEgaMOgbmcgdMawxqFpIHbDoCDEkeG7kyDEg24gbmjhurkuDQoNCioqQmnhu4N1IMSR4buTKioNCg0KYGBge3J9DQojIFbhur0gYmnhu4N1IMSR4buTIGPhu5l0IHThuqduIHN14bqldCBQcm9kdWN0Q2F0ZWdvcnkNCmdncGxvdChkdCwgYWVzKHggPSByZW9yZGVyKFByb2R1Y3RDYXRlZ29yeSwgUHJvZHVjdENhdGVnb3J5LCBmdW5jdGlvbih4KSAtbGVuZ3RoKHgpKSkpICsNCiAgZ2VvbV9iYXIoZmlsbCA9ICJzdGVlbGJsdWUiKSArDQogIGNvb3JkX2ZsaXAoKSArICAjIFhvYXkgdHLhu6VjIMSR4buDIG5ow6NuIGThu4UgxJHhu41jIGjGoW4NCiAgbGFicyh0aXRsZSA9ICJU4bqnbiBzdeG6pXQgZ2lhbyBk4buLY2ggdGhlbyBQcm9kdWN0IENhdGVnb3J5IiwNCiAgICAgICB4ID0gIlByb2R1Y3QgQ2F0ZWdvcnkiLA0KICAgICAgIHkgPSAiU+G7kSBnaWFvIGThu4tjaCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0K