# my_folder <- 'P:/Nhansu/Du lieu cham cong - Theo doi ngay nghi/Du lieu cham cong/Hoi so/'
# files <- list.files(my_folder, pattern = "\\.xls$", full.names = T, recursive = T) # change here
# map_df(files, read_excel)->> cham_cong
cham_cong <- read_excel("D:/R/Rmarkdown/chamcong/chamcong.xlsx")
cham_cong <- cham_cong %>%
set_names(c("day_name", "date", "time", "emp_code")) %>%
mutate(date_time = paste(date, time) %>% dmy_hms(),
date = date_time %>% as_date()) %>%
group_by(emp_code, date) %>%
summarise(max_time = max(date_time, na.rm = T),
min_time = min(date_time, na.rm = T)) %>%
mutate(working_time = difftime(max_time, min_time, units = "hours") %>% as.numeric()) %>%
ungroup()
#==============================================================================
# Tao bang calendar
#==============================================================================
df_date <- data.frame(date = ymd(20180101) %m+% days(1:303))
df_date %<>% mutate(day = day(date),
week_name = weekdays(date, abbreviate = T),
week_name = factor(week_name,
levels = rev(c("Mon","Tue","Wed","Thu","Fri","Sat","Sun")),
labels = rev(c("Mon","Tue","Wed","Thu","Fri","Sat","Sun"))),
week = week(date),
month = month(date),
month_name = month.abb[month],
month_name = factor(month_name,
levels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"),
labels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))) %>%
group_by(month_name) %>%
mutate(month_week = week - min(week) + 1) %>%
ungroup()
nnb_plot <- function(sb = 'SB11341'){
df <- working_time %>%
filter(emp_code == sb) %>%
right_join(df_date, by = "date") %>%
mutate(pass_min_time = ymd_hms(paste(date, "08:15:00")),
pass_max_time = case_when(week_name == "Sat" ~ ymd_hms(paste(date, "12:00:00")),
TRUE ~ ymd_hms(paste(date, "17:00:00"))),
pass_day = case_when(is.na(min_time) ~ "Absent",
min_time <= pass_min_time & max_time >= pass_max_time ~ "Ok",
TRUE ~ "Fail") %>% as.factor()) %>%
filter(week_name != "Sun")
# df %>% mutate(pass_day = case_when(is.na(working_time) ~ "Absent",
# week_name %in% "Sat" & working_time >= 4 ~ "Ok",
# week_name != "Sat" & working_time >= 8 ~ "Ok",
# TRUE ~ "Fail") %>% as.factor()) %>%
df %>%
ggplot(aes(x = month_week, y = week_name, fill = pass_day))+
geom_tile() +
scale_fill_manual(values = c("snow2", "brown3", "springgreen"))+
facet_wrap(~month_name)+
geom_text(aes(label = day))+
labs(title = paste("Working hour by date of", sb),
y = NULL,
x = NULL)->> p
p
}
Tổng số giờ làm việc theo ngày của tất cả cán bộ nhân viên hội sở
hoi_so %>%
ggplot(aes(x = month_week, y = week_name, fill = working_time))+
geom_tile() +
scale_fill_gradient(low = "white", high = "red") +
facet_wrap(~month_name)+
geom_text(aes(label = day))+
labs(title = "Total working time of staff",
y = NULL,
x = NULL,
caption = "Source: HR-SeABank",
fill = "Working time")

Một số SB
SB11341

SB10205

SB10973

SB10292

SB10356

SB10059

SB11397

SB11658

SB11819

BI
bi %>%
mutate(pass_min_time = ymd_hms(paste(date, "08:15:00")),
pass_max_time = case_when(week_name == "Sat" ~ ymd_hms(paste(date, "12:00:00")),
TRUE ~ ymd_hms(paste(date, "17:00:00"))),
pass_day = case_when(is.na(min_time) ~ "Absent",
min_time <= pass_min_time & max_time >= pass_max_time ~ "Ok",
TRUE ~ "Fail") %>% as.factor()) %>%
filter(week_name != "Sun")%>%
filter(!is.na(emp_code)) %>%
ggplot(aes(x = month_week, y = week_name, fill = pass_day))+
geom_tile() +
scale_fill_manual(values = c("brown3", "springgreen"))+
facet_wrap(~emp_name)+
geom_text(aes(label = day))+
labs(title = paste("Working hour by date of BI in", month.abb[month(first_date)]),
y = NULL,
x = NULL,
fill = "Pass day")

LS0tDQp0aXRsZTogIkNo4bqlbSBjw7RuZyBjYWxlbmRhciINCmF1dGhvcjogIk5ndXnhu4VuIE5n4buNYyBCw6xuaCINCmRhdGU6ICIxMC8zMC8yMDE4Ig0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzDQogICAgdGhlbWU6ICJkZWZhdWx0Ig0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KICAgICAgc21vb3RoX3Njcm9sbDogbm8NCg0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFICkgIyBmaWcuY2FwID0gIlNvdXJjZTogQkkgLSBTZUFiYW5rIiwgIGZpZy5oZWlnaHQgPSA2LCBmaWcud2lkdGggPSA5DQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShsdWJyaWRhdGUpDQoNCnRoZW1lX25uYiA8LSB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAnc25vdzInLCBjb2xvdXIgPSAnc25vdzQnKSkNCg0KdGhlbWVfc2V0KHRoZW1lX25uYikNCmBgYA0KDQpgYGB7cn0NCiMgbXlfZm9sZGVyIDwtICdQOi9OaGFuc3UvRHUgbGlldSBjaGFtIGNvbmcgLSBUaGVvIGRvaSBuZ2F5IG5naGkvRHUgbGlldSBjaGFtIGNvbmcvSG9pIHNvLycNCiMgZmlsZXMgPC0gbGlzdC5maWxlcyhteV9mb2xkZXIsIHBhdHRlcm4gPSAiXFwueGxzJCIsIGZ1bGwubmFtZXMgPSBULCByZWN1cnNpdmUgPSBUKSAjIGNoYW5nZSBoZXJlDQojIG1hcF9kZihmaWxlcywgcmVhZF9leGNlbCktPj4gY2hhbV9jb25nDQpjaGFtX2NvbmcgPC0gcmVhZF9leGNlbCgiRDovUi9SbWFya2Rvd24vY2hhbWNvbmcvY2hhbWNvbmcueGxzeCIpDQoNCmNoYW1fY29uZyA8LSBjaGFtX2NvbmcgJT4lDQogIHNldF9uYW1lcyhjKCJkYXlfbmFtZSIsICJkYXRlIiwgInRpbWUiLCAiZW1wX2NvZGUiKSkgJT4lDQogIG11dGF0ZShkYXRlX3RpbWUgPSBwYXN0ZShkYXRlLCB0aW1lKSAlPiUgZG15X2htcygpLA0KICAgICAgICAgZGF0ZSA9IGRhdGVfdGltZSAlPiUgYXNfZGF0ZSgpKSAgJT4lDQogIGdyb3VwX2J5KGVtcF9jb2RlLCBkYXRlKSAlPiUNCiAgc3VtbWFyaXNlKG1heF90aW1lID0gbWF4KGRhdGVfdGltZSwgbmEucm0gPSBUKSwNCiAgICAgICAgIG1pbl90aW1lID0gbWluKGRhdGVfdGltZSwgbmEucm0gPSBUKSkgJT4lIA0KICBtdXRhdGUod29ya2luZ190aW1lID0gZGlmZnRpbWUobWF4X3RpbWUsIG1pbl90aW1lLCB1bml0cyA9ICJob3VycyIpICU+JSBhcy5udW1lcmljKCkpICU+JQ0KICB1bmdyb3VwKCkNCmBgYA0KDQpgYGB7cn0NCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgVGFvIGJhbmcgY2FsZW5kYXINCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCmRmX2RhdGUgPC0gZGF0YS5mcmFtZShkYXRlID0geW1kKDIwMTgwMTAxKSAlbSslIGRheXMoMTozMDMpKQ0KDQpkZl9kYXRlICU8PiUgbXV0YXRlKGRheSA9IGRheShkYXRlKSwNCiAgICAgICAgICAgICAgICAgICB3ZWVrX25hbWUgPSB3ZWVrZGF5cyhkYXRlLCBhYmJyZXZpYXRlID0gVCksDQogICAgICAgICAgICAgICAgICAgd2Vla19uYW1lID0gZmFjdG9yKHdlZWtfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gcmV2KGMoIk1vbiIsIlR1ZSIsIldlZCIsIlRodSIsIkZyaSIsIlNhdCIsIlN1biIpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gcmV2KGMoIk1vbiIsIlR1ZSIsIldlZCIsIlRodSIsIkZyaSIsIlNhdCIsIlN1biIpKSksDQogICAgICAgICAgICAgICAgICAgd2VlayA9IHdlZWsoZGF0ZSksDQogICAgICAgICAgICAgICAgICAgbW9udGggPSBtb250aChkYXRlKSwNCiAgICAgICAgICAgICAgICAgICBtb250aF9uYW1lID0gbW9udGguYWJiW21vbnRoXSwNCiAgICAgICAgICAgICAgICAgICBtb250aF9uYW1lID0gZmFjdG9yKG1vbnRoX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJKYW4iLCAiRmViIiwgIk1hciIsICJBcHIiLCAiTWF5IiwgIkp1biIsICJKdWwiLCAiQXVnIiwgIlNlcCIsICJPY3QiLCAiTm92IiwgIkRlYyIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiSmFuIiwgIkZlYiIsICJNYXIiLCAiQXByIiwgIk1heSIsICJKdW4iLCAiSnVsIiwgIkF1ZyIsICJTZXAiLCAiT2N0IiwgIk5vdiIsICJEZWMiKSkpICU+JSANCiAgZ3JvdXBfYnkobW9udGhfbmFtZSkgJT4lIA0KICBtdXRhdGUobW9udGhfd2VlayA9IHdlZWsgLSBtaW4od2VlaykgKyAxKSAlPiUgDQogIHVuZ3JvdXAoKQ0KDQpgYGANCg0KYGBge3IsaW5jbHVkZT1GQUxTRX0NCndvcmtpbmdfdGltZSA8LSBjaGFtX2NvbmcgJT4lIA0KICBtdXRhdGUoZW1wX25hbWUgPSBjYXNlX3doZW4oZW1wX2NvZGUgPT0gJ1NCMTEzNDEnIH4gJ0JpbmgnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW1wX2NvZGUgPT0gJ1NCMTAyMDUnIH4gJ1RyYW5nJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVtcF9jb2RlID09ICdTQjEwOTczJyB+ICdLaWVtJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVtcF9jb2RlID09ICdTQjEwMzU2JyB+ICdUaGFuaCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbXBfY29kZSA9PSAnU0IxMDI5MicgfiAnR2lhbmcnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW1wX2NvZGUgPT0gJ1NCMTAwNTknIH4gJ1F1eW5oJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVtcF9jb2RlID09ICdTQjExNjU4JyB+ICdBbicsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbXBfY29kZSA9PSAnU0IxMTM5NycgfiAnRHVuZycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbXBfY29kZSA9PSAnU0IxMTgxOScgfiAnRHV5JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiT3RoZXIiDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSANCg0KDQoNCmhvaV9zbyA8LSB3b3JraW5nX3RpbWUgJT4lIA0KICBncm91cF9ieShkYXRlKSAlPiUgDQogIHN1bW1hcmlzZSh3b3JraW5nX3RpbWUgPSBzdW0od29ya2luZ190aW1lKSkgJT4lIA0KICB1bmdyb3VwKCklPiUgDQogIHJpZ2h0X2pvaW4oZGZfZGF0ZSkgJT4lIA0KICBmaWx0ZXIod2Vla19uYW1lICE9ICJTdW4iKQ0KDQojIEZpcnN0IGRhdGUgdGhpcyBtb250aA0KZmlyc3RfZGF0ZSA8LSByb2xsYmFjayhTeXMuRGF0ZSgpJW0tJSBkYXlzKDEwKSkgJW0rJSBkYXlzKDEpDQojZmlyc3RfZGF0ZSA8LSByb2xsYmFjayhTeXMuRGF0ZSgpKSAlbSslIGRheXMoMSkNCg0KYmkgPC0gd29ya2luZ190aW1lICU+JSANCiAgZmlsdGVyKGVtcF9jb2RlICAlaW4lIGMoJ1NCMTEzNDEnLCAnU0IxMDIwNScsICdTQjEwOTczJywgJ1NCMTAzNTYnLCAnU0IxMDI5MicsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAnU0IxMDA1OScsICdTQjExNjU4JywgJ1NCMTEzOTcnLCAnU0IxMTgxOScpKSAlPiUgDQogIHJpZ2h0X2pvaW4oZGZfZGF0ZSkgJT4lIA0KICBmaWx0ZXIod2Vla19uYW1lICE9ICJTdW4iLCBkYXRlID49IGZpcnN0X2RhdGUpDQogIA0KYGBgDQoNCmBgYHtyfQ0Kbm5iX3Bsb3QgPC0gZnVuY3Rpb24oc2IgPSAnU0IxMTM0MScpew0KICBkZiA8LSB3b3JraW5nX3RpbWUgJT4lIA0KICAgIGZpbHRlcihlbXBfY29kZSA9PSBzYikgJT4lIA0KICAgIHJpZ2h0X2pvaW4oZGZfZGF0ZSwgYnkgPSAiZGF0ZSIpICU+JSANCiAgICBtdXRhdGUocGFzc19taW5fdGltZSA9IHltZF9obXMocGFzdGUoZGF0ZSwgIjA4OjE1OjAwIikpLA0KICAgICAgICAgICBwYXNzX21heF90aW1lID0gY2FzZV93aGVuKHdlZWtfbmFtZSA9PSAiU2F0IiB+IHltZF9obXMocGFzdGUoZGF0ZSwgIjEyOjAwOjAwIikpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiB5bWRfaG1zKHBhc3RlKGRhdGUsICIxNzowMDowMCIpKSksDQogICAgICAgICAgIHBhc3NfZGF5ID0gY2FzZV93aGVuKGlzLm5hKG1pbl90aW1lKSB+ICJBYnNlbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5fdGltZSA8PSBwYXNzX21pbl90aW1lICYgbWF4X3RpbWUgPj0gcGFzc19tYXhfdGltZSB+ICJPayIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRmFpbCIpICU+JSBhcy5mYWN0b3IoKSkgJT4lIA0KICAgIGZpbHRlcih3ZWVrX25hbWUgIT0gIlN1biIpDQogIA0KICAjIGRmICU+JSBtdXRhdGUocGFzc19kYXkgPSBjYXNlX3doZW4oaXMubmEod29ya2luZ190aW1lKSB+ICJBYnNlbnQiLA0KICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3ZWVrX25hbWUgJWluJSAiU2F0IiAmIHdvcmtpbmdfdGltZSA+PSA0IH4gIk9rIiwNCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2Vla19uYW1lICE9ICJTYXQiICYgd29ya2luZ190aW1lID49IDggfiAiT2siLA0KICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIkZhaWwiKSAlPiUgYXMuZmFjdG9yKCkpICU+JSANCiAgZGYgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBtb250aF93ZWVrLCB5ID0gd2Vla19uYW1lLCBmaWxsID0gcGFzc19kYXkpKSsNCiAgZ2VvbV90aWxlKCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJzbm93MiIsICJicm93bjMiLCAic3ByaW5nZ3JlZW4iKSkrDQogIGZhY2V0X3dyYXAofm1vbnRoX25hbWUpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gZGF5KSkrDQogIGxhYnModGl0bGUgPSBwYXN0ZSgiV29ya2luZyBob3VyIGJ5IGRhdGUgb2YiLCBzYiksDQogICAgICAgeSA9IE5VTEwsDQogICAgICAgeCA9IE5VTEwpLT4+IHANCiAgDQogIHANCiAgDQp9DQpgYGANCg0KDQojIFThu5VuZyBz4buRIGdp4budIGzDoG0gdmnhu4djIHRoZW8gbmfDoHkgY+G7p2EgdOG6pXQgY+G6oyBjw6FuIGLhu5kgbmjDom4gdmnDqm4gaOG7mWkgc+G7nw0KYGBge3J9DQpob2lfc28gJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBtb250aF93ZWVrLCB5ID0gd2Vla19uYW1lLCBmaWxsID0gd29ya2luZ190aW1lKSkrDQogIGdlb21fdGlsZSgpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAid2hpdGUiLCBoaWdoID0gInJlZCIpICsNCiAgZmFjZXRfd3JhcCh+bW9udGhfbmFtZSkrDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBkYXkpKSsNCiAgbGFicyh0aXRsZSA9ICJUb3RhbCB3b3JraW5nIHRpbWUgb2Ygc3RhZmYiLA0KICAgICAgICB5ID0gTlVMTCwNCiAgICAgICAgeCA9IE5VTEwsDQogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEhSLVNlQUJhbmsiLA0KICAgICAgIGZpbGwgPSAiV29ya2luZyB0aW1lIikNCg0KYGBgDQoNCiMgTeG7mXQgc+G7kSBTQiANCiMjIFNCMTEzNDENCmBgYHtyfQ0Kbm5iX3Bsb3Qoc2IgPSAiU0IxMTM0MSIpDQpgYGANCg0KIyMgU0IxMDIwNQ0KDQpgYGB7cn0NCm5uYl9wbG90KHNiID0gIlNCMTAyMDUiKQ0KYGBgDQoNCiMjIFNCMTA5NzMNCg0KYGBge3J9DQpubmJfcGxvdChzYiA9ICJTQjEwOTczIikNCmBgYA0KDQojIyBTQjEwMjkyDQpgYGB7cn0NCm5uYl9wbG90KHNiID0gIlNCMTAyOTIiKQ0KYGBgDQoNCiMjIFNCMTAzNTYNCmBgYHtyfQ0Kbm5iX3Bsb3Qoc2IgPSAiU0IxMDM1NiIpDQpgYGANCg0KIyMgU0IxMDA1OQ0KYGBge3J9DQpubmJfcGxvdChzYiA9ICJTQjEwMDU5IikNCmBgYA0KDQojIyBTQjExMzk3DQpgYGB7cn0NCm5uYl9wbG90KHNiID0gIlNCMTEzOTciKQ0KYGBgDQoNCiMjIFNCMTE2NTgNCg0KYGBge3J9DQpubmJfcGxvdChzYiA9ICJTQjExNjU4IikNCmBgYA0KDQojIyBTQjExODE5DQpgYGB7cn0NCm5uYl9wbG90KHNiID0gIlNCMTE4MTkiKQ0KYGBgDQoNCiMjIEJJDQpgYGB7cn0NCmJpICU+JSANCiAgbXV0YXRlKHBhc3NfbWluX3RpbWUgPSB5bWRfaG1zKHBhc3RlKGRhdGUsICIwODoxNTowMCIpKSwNCiAgICAgICAgIHBhc3NfbWF4X3RpbWUgPSBjYXNlX3doZW4od2Vla19uYW1lID09ICJTYXQiIH4geW1kX2htcyhwYXN0ZShkYXRlLCAiMTI6MDA6MDAiKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiB5bWRfaG1zKHBhc3RlKGRhdGUsICIxNzowMDowMCIpKSksDQogICAgICAgICBwYXNzX2RheSA9IGNhc2Vfd2hlbihpcy5uYShtaW5fdGltZSkgfiAiQWJzZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbl90aW1lIDw9IHBhc3NfbWluX3RpbWUgJiBtYXhfdGltZSA+PSBwYXNzX21heF90aW1lIH4gIk9rIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRmFpbCIpICU+JSBhcy5mYWN0b3IoKSkgJT4lIA0KICBmaWx0ZXIod2Vla19uYW1lICE9ICJTdW4iKSU+JSANCiAgZmlsdGVyKCFpcy5uYShlbXBfY29kZSkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gbW9udGhfd2VlaywgeSA9IHdlZWtfbmFtZSwgZmlsbCA9IHBhc3NfZGF5KSkrDQogIGdlb21fdGlsZSgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiYnJvd24zIiwgInNwcmluZ2dyZWVuIikpKw0KICBmYWNldF93cmFwKH5lbXBfbmFtZSkrDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBkYXkpKSsNCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJXb3JraW5nIGhvdXIgYnkgZGF0ZSBvZiBCSSBpbiIsIG1vbnRoLmFiYlttb250aChmaXJzdF9kYXRlKV0pLA0KICAgICAgIHkgPSBOVUxMLA0KICAgICAgIHggPSBOVUxMLA0KICAgICAgIGZpbGwgPSAiUGFzcyBkYXkiKQ0KYGBgDQoNCjxzY3JpcHQ+DQokKCAiaW5wdXQuaGlkZXNob3ciICkuZWFjaCggZnVuY3Rpb24gKCBpbmRleCwgYnV0dG9uICkgew0KICBidXR0b24udmFsdWUgPSAnSGlkZSBPdXRwdXQnOw0KICAkKCBidXR0b24gKS5jbGljayggZnVuY3Rpb24gKCkgew0KICAgIHZhciB0YXJnZXQgPSB0aGlzLm5leHRTaWJsaW5nID8gdGhpcyA6IHRoaXMucGFyZW50Tm9kZTsNCiAgICB0YXJnZXQgPSB0YXJnZXQubmV4dFNpYmxpbmcubmV4dFNpYmxpbmcubmV4dFNpYmxpbmcubmV4dFNpYmxpbmc7DQogICAgaWYgKCB0YXJnZXQuc3R5bGUuZGlzcGxheSA9PSAnYmxvY2snIHx8IHRhcmdldC5zdHlsZS5kaXNwbGF5ID09ICcnICkgew0KICAgICAgdGFyZ2V0LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7DQogICAgICB0aGlzLnZhbHVlID0gJ1Nob3cgT3V0cHV0JzsNCiAgICB9IGVsc2Ugew0KICAgICAgdGFyZ2V0LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snOw0KICAgICAgdGhpcy52YWx1ZSA9ICdIaWRlIE91dHB1dCc7DQogICAgfQ0KICB9ICk7DQp9ICk7DQo8L3NjcmlwdD4=