0908 all
if("rJava" %in% installed.packages("rJava") == FALSE)install.packages("rJava")
library(rJava)
if("DBI" %in% installed.packages("DBI") == FALSE)install.packages("DBI")
library(DBI)
if("RJDBC" %in% installed.packages("RJDBC") == FALSE)install.packages("RJDBC")
library(RJDBC)
if("dplyr" %in% installed.packages("dplyr") == FALSE)install.packages("dplyr")
library(dplyr)
if("data.table" %in% installed.packages("data.table") == FALSE)install.packages("data.table")
library(data.table)
#oracle 데이터를 Rstudio로 가져오는 방법
myJDBC <- JDBC("oracle.jdbc.driver.OracleDriver",
"C:\\oraclexeapp\\oracle\\product\\11.2.0\\server\\jdbc\\lib\\ojdbc6.jar")
conn <- dbConnect(myJDBC,
"jdbc:oracle:thin:@localhost:1521:xe",
"hr",
"oracle"
)
tab <- dbGetQuery(conn, "SELECT * FROM TAB")
head(tab)
tab
#dplyr
#filterm select, arrange, mutate,
#summarise, group_by, left_join, bind_rows
tab <- data.frame(tab)
View(tab)
tname <- tab$TNAME
tname <- as.vector(tname)
tname
# [1] "COUNTRIES" cnt "DEPARTMENTS" dep
# [2] "EMPLOYEES" emp "EMP_DETAILS_VIEW" empd
# [3] "JOBS" job "JOB_HISTORY" jobh
# [4] "LOCATIONS" loc "REGIONS" reg
cnt <- data.frame(dbGetQuery(conn, "SELECT * FROM COUNTRIES"))
dep <- data.frame(dbGetQuery(conn, "SELECT * FROM DEPARTMENTS"))
emp <- data.frame(dbGetQuery(conn, "SELECT * FROM EMPLOYEES"))
empd <- data.frame(dbGetQuery(conn, "SELECT * FROM EMP_DETAILS_VIEW"))
job <- data.frame(dbGetQuery(conn, "SELECT * FROM JOBS"))
jobh <- data.frame(dbGetQuery(conn, "SELECT * FROM JOB_HISTORY"))
loc <- data.frame(dbGetQuery(conn, "SELECT * FROM LOCATIONS"))
reg <- data.frame(dbGetQuery(conn, "SELECT * FROM REGIONS"))
head(cnt)
# cnt 의 컬럼명을 한글로 전환하시오. (3.5.1)
str(cnt)
# COUNTRY_ID 국가아이디,
# COUNTRY_NAME 국가명,
# REGION_ID 지역아이디
cnt <- cnt %>%
dplyr::rename(국가아이디 = COUNTRY_ID,
국가명 = COUNTRY_NAME,
지역아이디 = REGION_ID)
str(cnt)
# dep 의 컬럼명 전환
str(dep)
# DEPARTMENT_ID 부서아이디,
# DEPARTMENT_NAME 부서명,
# MANAGER_ID 매니저아이디,
# LOCATION_ID 위치아이디
dep <- dep %>%
dplyr::rename(부서아이디 = DEPARTMENT_ID,
부서명 = DEPARTMENT_NAME,
매니저아이디 = MANAGER_ID,
위치아이디 = LOCATION_ID)
str(dep)
## emp 의 컬럼명을 한글로 전환하시오.
## 그리고 First Name 과 Last Name 을
## 붙여서 이름 으로 된 컬럼을 추가하시오
## 단, 이름 간격은 띄울것. ex) James Dean
## 직원아이디 = EMPLOYEE_ID
## 이메일 = EMAIL
## 전화번호 = PHONE_NUMBER
## 채용일 = HIRE_DATE
## 업무아이디 = JOB_ID
## 연봉 = SALARY
## 커미션비율 = COMMISSION_PCT
## 매니저아이디 = MANAGER_ID
## 부서아이디 = DEPARTMENT_ID
str(emp)
emp <- emp %>%
dplyr::rename(직원아이디 = EMPLOYEE_ID,
이메일 = EMAIL,
전화번호 = PHONE_NUMBER,
채용일 = HIRE_DATE,
업무아이디 = JOB_ID,
연봉 = SALARY,
커미션비율 = COMMISSION_PCT,
매니저아이디 = MANAGER_ID,
부서아이디 = DEPARTMENT_ID) %>%
mutate(이름 = paste(FIRST_NAME, LAST_NAME))
View(head(emp))
# 필요없는 변수 삭제하기
emp <- subset(emp,select = -c(FIRST_NAME, LAST_NAME))
View(head(emp))
# 매달 지급하는 월급여 (연봉/12)를 보여주는 월급이라는 컬럼(변수)를 추가시키시오.
# 0단위 이하는 절삭
emp <- emp %>%
dplyr::mutate(월급 = 연봉 %/% 12)
emp %>% head
# 연봉이 10000불 이상인 사원(emp)의 목록을 이름, 직원아이디, 연봉만 구하되,
# 연봉 내림차순으로 보여주시오.
emp %>%
left_join(dep,by="부서아이디") %>%
filter(연봉 >= 10000) %>%
select(이름, 직원아이디, 연봉, 부서명) %>%
arrange(desc(연봉))
# 연봉이 3000 미만인 사원에게 보너스로 급여를 1%를 지급하겠다고 합니다.
# 대상자의 목록을 이름, 직원아이디, 연봉, 보너스를 기재하고
# 아이디 오름차순으로 보여주시오.
# 단, 보너스는 이번 달만 주는 것이므로
# emp DF에 저장하지 않고 1회용 임시 DF를 따로 생성해서 저장하고, 기한이 지나면 폐기하시오.
보너스지급명세서<- emp %>%
filter(연봉 < 3000) %>%
dplyr::mutate(보너스 = 연봉 * 0.01) %>%
select(이름, 직원아이디, 연봉, 보너스) %>%
arrange(직원아이디)
View(보너스지급명세서)
rm(보너스지급명세서)
View(dep)
# 연봉이 10000 이 넘는 직원의 부서명, 이름, 연봉을 출력(get)하시오.
emp %>%
left_join(dep,by="부서아이디") %>%
filter(연봉 >= 10000) %>%
select(부서명, 이름, 연봉)
# 부서별로 연봉 평균을 구하시오.
dep %>%
left_join(emp,by="부서아이디") %>%
group_by(부서명, 부서아이디) %>%
dplyr::summarise(연봉평균=mean(연봉,na.rm=T)) %>%
arrange(desc(연봉평균)) %>%
View
# 이 회사의 부서의 수를 구하시오.
dep %>%
dplyr::distinct(부서명) %>%#distinct는 중복을 제거함.
count
# 연봉이 12000 이 넘는 직원의 부서명, 이름, 연봉, 직책 을 기재하시오.
job <- job %>%
rename(업무아이디 = JOB_ID,
직책 = JOB_TITLE,
최소연봉 = MIN_SALARY,
최대연봉 = MAX_SALARY
)
job %>% View
dep %>%
left_join(emp,by="부서아이디") %>%
left_join(job,by="업무아이디") %>%
filter(연봉 > 12000) %>%
select(부서명, 이름, 연봉, 직책)
emp %>%
left_join(dep,by="부서아이디") %>%
left_join(job,by="업무아이디") %>%
filter(연봉 > 12000) %>%
select(부서명, 이름, 연봉, 직책)
# 부서별로 가장 높은 연봉을 받는 부서아이디, 부서명, 최대연봉을 구하시오.
emp %>%
left_join(dep,by="부서아이디") %>%
left_join(job,by="업무아이디") %>%
group_by(부서아이디, 부서명) %>%
summarise(max(연봉))
# 부서아이디를 발급 받지 않으면 신입입니다.
# 신입의 이름과 연봉을 구하시오.
emp %>%
filter(is.na(emp %>% select(부서아이디))) %>%
select(이름, 연봉, 부서아이디)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KIyMjIyMwOTA4IGFsbA0KDQpgYGB7cn0NCmlmKCJySmF2YSIgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoInJKYXZhIikgPT0gRkFMU0UpaW5zdGFsbC5wYWNrYWdlcygickphdmEiKQ0KbGlicmFyeShySmF2YSkNCmlmKCJEQkkiICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCJEQkkiKSA9PSBGQUxTRSlpbnN0YWxsLnBhY2thZ2VzKCJEQkkiKQ0KbGlicmFyeShEQkkpDQppZigiUkpEQkMiICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCJSSkRCQyIpID09IEZBTFNFKWluc3RhbGwucGFja2FnZXMoIlJKREJDIikNCmxpYnJhcnkoUkpEQkMpDQppZigiZHBseXIiICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCJkcGx5ciIpID09IEZBTFNFKWluc3RhbGwucGFja2FnZXMoImRwbHlyIikNCmxpYnJhcnkoZHBseXIpDQppZigiZGF0YS50YWJsZSIgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoImRhdGEudGFibGUiKSA9PSBGQUxTRSlpbnN0YWxsLnBhY2thZ2VzKCJkYXRhLnRhYmxlIikNCmxpYnJhcnkoZGF0YS50YWJsZSkNCiNvcmFjbGUg642w7J207YSw66W8IFJzdHVkaW/roZwg6rCA7KC47Jik64qUIOuwqeuylQ0KbXlKREJDIDwtIEpEQkMoIm9yYWNsZS5qZGJjLmRyaXZlci5PcmFjbGVEcml2ZXIiLA0KICAgICAgICAgICAgICAgIkM6XFxvcmFjbGV4ZWFwcFxcb3JhY2xlXFxwcm9kdWN0XFwxMS4yLjBcXHNlcnZlclxcamRiY1xcbGliXFxvamRiYzYuamFyIikNCmNvbm4gPC0gZGJDb25uZWN0KG15SkRCQywNCiAgICAgICAgICAgICAgICAgICJqZGJjOm9yYWNsZTp0aGluOkBsb2NhbGhvc3Q6MTUyMTp4ZSIsDQogICAgICAgICAgICAgICAgICAiaHIiLA0KICAgICAgICAgICAgICAgICAgIm9yYWNsZSINCikNCnRhYiA8LSBkYkdldFF1ZXJ5KGNvbm4sICJTRUxFQ1QgKiBGUk9NIFRBQiIpDQpoZWFkKHRhYikNCnRhYg0KI2RwbHlyDQojZmlsdGVybSBzZWxlY3QsIGFycmFuZ2UsIG11dGF0ZSwNCiNzdW1tYXJpc2UsIGdyb3VwX2J5LCBsZWZ0X2pvaW4sIGJpbmRfcm93cw0KdGFiIDwtIGRhdGEuZnJhbWUodGFiKQ0KVmlldyh0YWIpDQp0bmFtZSA8LSB0YWIkVE5BTUUNCnRuYW1lIDwtIGFzLnZlY3Rvcih0bmFtZSkNCnRuYW1lDQoNCiMgWzFdICJDT1VOVFJJRVMiIGNudCAgIkRFUEFSVE1FTlRTIiAgZGVwDQojIFsyXSAiRU1QTE9ZRUVTIiAgZW1wICAiRU1QX0RFVEFJTFNfVklFVyIgIGVtcGQNCiMgWzNdICJKT0JTIiAgICAgIGpvYiAgIkpPQl9ISVNUT1JZIiAgam9iaA0KIyBbNF0gIkxPQ0FUSU9OUyIgIGxvYyAgIlJFR0lPTlMiICByZWcNCg0KY250IDwtIGRhdGEuZnJhbWUoZGJHZXRRdWVyeShjb25uLCAiU0VMRUNUICogRlJPTSBDT1VOVFJJRVMiKSkNCmRlcCA8LSBkYXRhLmZyYW1lKGRiR2V0UXVlcnkoY29ubiwgIlNFTEVDVCAqIEZST00gREVQQVJUTUVOVFMiKSkNCmVtcCA8LSBkYXRhLmZyYW1lKGRiR2V0UXVlcnkoY29ubiwgIlNFTEVDVCAqIEZST00gRU1QTE9ZRUVTIikpDQplbXBkIDwtIGRhdGEuZnJhbWUoZGJHZXRRdWVyeShjb25uLCAiU0VMRUNUICogRlJPTSBFTVBfREVUQUlMU19WSUVXIikpDQpqb2IgPC0gZGF0YS5mcmFtZShkYkdldFF1ZXJ5KGNvbm4sICJTRUxFQ1QgKiBGUk9NIEpPQlMiKSkNCmpvYmggPC0gZGF0YS5mcmFtZShkYkdldFF1ZXJ5KGNvbm4sICJTRUxFQ1QgKiBGUk9NIEpPQl9ISVNUT1JZIikpDQpsb2MgPC0gZGF0YS5mcmFtZShkYkdldFF1ZXJ5KGNvbm4sICJTRUxFQ1QgKiBGUk9NIExPQ0FUSU9OUyIpKQ0KcmVnIDwtIGRhdGEuZnJhbWUoZGJHZXRRdWVyeShjb25uLCAiU0VMRUNUICogRlJPTSBSRUdJT05TIikpDQpoZWFkKGNudCkNCg0KDQojIGNudCDsnZgg7Lus65+866qF7J2EIO2VnOq4gOuhnCDsoITtmZjtlZjsi5zsmKQuICgzLjUuMSkNCg0Kc3RyKGNudCkNCiMgQ09VTlRSWV9JRCDqta3qsIDslYTsnbTrlJQsDQojIENPVU5UUllfTkFNRSDqta3qsIDrqoUsDQojIFJFR0lPTl9JRCDsp4Dsl63slYTsnbTrlJQNCmNudCA8LSBjbnQgJT4lDQogIGRwbHlyOjpyZW5hbWUo6rWt6rCA7JWE7J2065SUID0gQ09VTlRSWV9JRCwNCiAgICAgICAgICAgICAgICAgICAgIOq1reqwgOuqhSA9IENPVU5UUllfTkFNRSwNCiAgICAgICAgICAgICAgICAgICAgIOyngOyXreyVhOydtOuUlCA9IFJFR0lPTl9JRCkNCnN0cihjbnQpDQoNCg0KIyBkZXAg7J2YIOy7rOufvOuqhSDsoITtmZgNCnN0cihkZXApDQojIERFUEFSVE1FTlRfSUQg67aA7ISc7JWE7J2065SULA0KIyBERVBBUlRNRU5UX05BTUUg67aA7ISc66qFLA0KIyBNQU5BR0VSX0lEIOunpOuLiOyggOyVhOydtOuUlCwNCiMgTE9DQVRJT05fSUQg7JyE7LmY7JWE7J2065SUDQpkZXAgPC0gZGVwICU+JSANCiAgZHBseXI6OnJlbmFtZSjrtoDshJzslYTsnbTrlJQgPSBERVBBUlRNRU5UX0lELA0KICAgICAgICAgICAgICAgICAgICAg67aA7ISc66qFID0gREVQQVJUTUVOVF9OQU1FLA0KICAgICAgICAgICAgICAgICAgICAg66ek64uI7KCA7JWE7J2065SUID0gTUFOQUdFUl9JRCwNCiAgICAgICAgICAgICAgICAgICAgIOychOy5mOyVhOydtOuUlCA9IExPQ0FUSU9OX0lEKQ0Kc3RyKGRlcCkNCg0KDQojIyBlbXAg7J2YIOy7rOufvOuqheydhCDtlZzquIDroZwg7KCE7ZmY7ZWY7Iuc7JikLg0KIyMg6re466as6rOgIEZpcnN0IE5hbWUg6rO8IExhc3QgTmFtZSDsnYQNCiMjIOu2meyXrOyEnCDsnbTrpoQg7Jy866GcIOuQnCDsu6zrn7zsnYQg7LaU6rCA7ZWY7Iuc7JikDQojIyDri6gsIOydtOumhCDqsITqsqnsnYAg652E7Jq46rKDLiBleCkgSmFtZXMgRGVhbg0KIyMg7KeB7JuQ7JWE7J2065SUID0gRU1QTE9ZRUVfSUQNCiMjIOydtOuplOydvCA9IEVNQUlMDQojIyDsoITtmZTrsojtmLggPSBQSE9ORV9OVU1CRVINCiMjIOyxhOyaqeydvCA9IEhJUkVfREFURQ0KIyMg7JeF66y07JWE7J2065SUID0gSk9CX0lEDQojIyDsl7DrtIkgPSBTQUxBUlkNCiMjIOy7pOuvuOyFmOu5hOycqCA9IENPTU1JU1NJT05fUENUDQojIyDrp6Tri4jsoIDslYTsnbTrlJQgPSBNQU5BR0VSX0lEDQojIyDrtoDshJzslYTsnbTrlJQgPSBERVBBUlRNRU5UX0lEDQoNCnN0cihlbXApDQplbXAgPC0gZW1wICU+JQ0KICBkcGx5cjo6cmVuYW1lKOyngeybkOyVhOydtOuUlCA9IEVNUExPWUVFX0lELA0KICAgICAgICAgICAgICAgICAgICAg7J2066mU7J28ID0gRU1BSUwsDQogICAgICAgICAgICAgICAgICAgICDsoITtmZTrsojtmLggPSBQSE9ORV9OVU1CRVIsDQogICAgICAgICAgICAgICAgICAgICDssYTsmqnsnbwgPSBISVJFX0RBVEUsDQogICAgICAgICAgICAgICAgICAgICDsl4XrrLTslYTsnbTrlJQgPSBKT0JfSUQsDQogICAgICAgICAgICAgICAgICAgICDsl7DrtIkgPSBTQUxBUlksDQogICAgICAgICAgICAgICAgICAgICDsu6Trr7jshZjruYTsnKggPSBDT01NSVNTSU9OX1BDVCwNCiAgICAgICAgICAgICAgICAgICAgIOunpOuLiOyggOyVhOydtOuUlCA9IE1BTkFHRVJfSUQsDQogICAgICAgICAgICAgICAgICAgICDrtoDshJzslYTsnbTrlJQgPSBERVBBUlRNRU5UX0lEKSAlPiUNCiAgbXV0YXRlKOydtOumhCA9IHBhc3RlKEZJUlNUX05BTUUsIExBU1RfTkFNRSkpDQpWaWV3KGhlYWQoZW1wKSkNCg0KIyDtlYTsmpTsl4bripQg67OA7IiYIOyCreygnO2VmOq4sA0KZW1wIDwtIHN1YnNldChlbXAsc2VsZWN0ID0gLWMoRklSU1RfTkFNRSwgTEFTVF9OQU1FKSkNClZpZXcoaGVhZChlbXApKSANCg0KIyDrp6Tri6wg7KeA6riJ7ZWY64qUIOyblOq4ieyXrCAo7Jew67SJLzEyKeulvCDrs7Tsl6zso7zripQg7JuU6riJ7J20652864qUIOy7rOufvCjrs4DsiJgp66W8IOy2lOqwgOyLnO2CpOyLnOyYpC4NCiMgMOuLqOychCDsnbTtlZjripQg7KCI7IKtDQoNCmVtcCA8LSBlbXAgJT4lIA0KICBkcGx5cjo6bXV0YXRlKOyblOq4iSA9IOyXsOu0iSAlLyUgMTIpDQplbXAgJT4lIGhlYWQNCg0KDQojIOyXsOu0ieydtCAxMDAwMOu2iCDsnbTsg4Hsnbgg7IKs7JuQKGVtcCnsnZgg66qp66Gd7J2EIOydtOumhCwg7KeB7JuQ7JWE7J2065SULCDsl7DrtInrp4wg6rWs7ZWY65CYLA0KIyDsl7DrtIkg64K066a87LCo7Iic7Jy866GcIOuztOyXrOyjvOyLnOyYpC4NCg0KZW1wICU+JSANCiAgbGVmdF9qb2luKGRlcCxieT0i67aA7ISc7JWE7J2065SUIikgJT4lIA0KICBmaWx0ZXIo7Jew67SJID49IDEwMDAwKSAlPiUgDQogIHNlbGVjdCjsnbTrpoQsIOyngeybkOyVhOydtOuUlCwg7Jew67SJLCDrtoDshJzrqoUpICU+JSANCiAgYXJyYW5nZShkZXNjKOyXsOu0iSkpDQoNCiMg7Jew67SJ7J20IDMwMDAg66+466eM7J24IOyCrOybkOyXkOqyjCDrs7TrhIjsiqTroZwg6riJ7Jes66W8IDEl66W8IOyngOq4ie2VmOqyoOuLpOqzoCDtlanri4jri6QuDQojIOuMgOyDgeyekOydmCDrqqnroZ3snYQg7J2066aELCDsp4Hsm5DslYTsnbTrlJQsIOyXsOu0iSwg67O064SI7Iqk66W8IOq4sOyerO2VmOqzoA0KIyDslYTsnbTrlJQg7Jik66aE7LCo7Iic7Jy866GcIOuztOyXrOyjvOyLnOyYpC4NCiMg64uoLCDrs7TrhIjsiqTripQg7J2067KIIOuLrOunjCDso7zripQg6rKD7J2066+A66GcDQojIGVtcCBERuyXkCDsoIDsnqXtlZjsp4Ag7JWK6rOgIDHtmozsmqkg7J6E7IucIERG66W8IOuUsOuhnCDsg53shLHtlbTshJwg7KCA7J6l7ZWY6rOgLCDquLDtlZzsnbQg7KeA64KY66m0IO2PkOq4sO2VmOyLnOyYpC4NCg0K67O064SI7Iqk7KeA6riJ66qF7IS47IScPC0gZW1wICU+JSANCiAgZmlsdGVyKOyXsOu0iSA8IDMwMDApICU+JSANCiAgZHBseXI6Om11dGF0ZSjrs7TrhIjsiqQgPSDsl7DrtIkgKiAwLjAxKSAlPiUgDQogIHNlbGVjdCjsnbTrpoQsIOyngeybkOyVhOydtOuUlCwg7Jew67SJLCDrs7TrhIjsiqQpICU+JSANCiAgYXJyYW5nZSjsp4Hsm5DslYTsnbTrlJQpDQpWaWV3KOuztOuEiOyKpOyngOq4ieuqheyEuOyEnCkNCnJtKOuztOuEiOyKpOyngOq4ieuqheyEuOyEnCkNCg0KVmlldyhkZXApDQojIOyXsOu0ieydtCAxMDAwMCDsnbQg64SY64qUIOyngeybkOydmCDrtoDshJzrqoUsIOydtOumhCwg7Jew67SJ7J2EIOy2nOugpShnZXQp7ZWY7Iuc7JikLg0KDQplbXAgJT4lDQogIGxlZnRfam9pbihkZXAsYnk9Iuu2gOyEnOyVhOydtOuUlCIpICU+JSANCiAgZmlsdGVyKOyXsOu0iSA+PSAxMDAwMCkgJT4lDQogIHNlbGVjdCjrtoDshJzrqoUsIOydtOumhCwg7Jew67SJKQ0KDQoNCiMg67aA7ISc67OE66GcIOyXsOu0iSDtj4nqt6DsnYQg6rWs7ZWY7Iuc7JikLg0KZGVwICU+JQ0KICBsZWZ0X2pvaW4oZW1wLGJ5PSLrtoDshJzslYTsnbTrlJQiKSAlPiUNCiAgZ3JvdXBfYnko67aA7ISc66qFLCDrtoDshJzslYTsnbTrlJQpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXNlKOyXsOu0ie2Pieq3oD1tZWFuKOyXsOu0iSxuYS5ybT1UKSkgJT4lIA0KICBhcnJhbmdlKGRlc2Mo7Jew67SJ7Y+J6regKSkgJT4lIA0KICBWaWV3DQoNCiMg7J20IO2ajOyCrOydmCDrtoDshJzsnZgg7IiY66W8IOq1rO2VmOyLnOyYpC4NCmRlcCAlPiUNCiAgZHBseXI6OmRpc3RpbmN0KOu2gOyEnOuqhSkgJT4lI2Rpc3RpbmN064qUIOykkeuzteydhCDsoJzqsbDtlaguDQogIGNvdW50DQoNCiMg7Jew67SJ7J20IDEyMDAwIOydtCDrhJjripQg7KeB7JuQ7J2YIOu2gOyEnOuqhSwg7J2066aELCDsl7DrtIksIOyngeyxhSDsnYQg6riw7J6s7ZWY7Iuc7JikLg0Kam9iIDwtIGpvYiAlPiUgDQogIHJlbmFtZSjsl4XrrLTslYTsnbTrlJQgPSBKT0JfSUQsDQogICAgICAgICAgICAgIOyngeyxhSA9IEpPQl9USVRMRSwNCiAgICAgICAgICAgICAg7LWc7IaM7Jew67SJID0gTUlOX1NBTEFSWSwNCiAgICAgICAgICAgICAg7LWc64yA7Jew67SJID0gTUFYX1NBTEFSWQ0KICApDQpqb2IgJT4lIFZpZXcNCg0KZGVwICU+JSANCiAgbGVmdF9qb2luKGVtcCxieT0i67aA7ISc7JWE7J2065SUIikgJT4lIA0KICBsZWZ0X2pvaW4oam9iLGJ5PSLsl4XrrLTslYTsnbTrlJQiKSAlPiUgDQogIGZpbHRlcijsl7DrtIkgPiAxMjAwMCkgJT4lIA0KICBzZWxlY3Qo67aA7ISc66qFLCDsnbTrpoQsIOyXsOu0iSwg7KeB7LGFKQ0KDQplbXAgJT4lDQogIGxlZnRfam9pbihkZXAsYnk9Iuu2gOyEnOyVhOydtOuUlCIpICU+JQ0KICBsZWZ0X2pvaW4oam9iLGJ5PSLsl4XrrLTslYTsnbTrlJQiKSAlPiUNCiAgZmlsdGVyKOyXsOu0iSA+IDEyMDAwKSAlPiUgDQogIHNlbGVjdCjrtoDshJzrqoUsIOydtOumhCwg7Jew67SJLCDsp4HssYUpDQoNCiMg67aA7ISc67OE66GcIOqwgOyepSDrhpLsnYAg7Jew67SJ7J2EIOuwm+uKlCDrtoDshJzslYTsnbTrlJQsIOu2gOyEnOuqhSwg7LWc64yA7Jew67SJ7J2EIOq1rO2VmOyLnOyYpC4NCg0KZW1wICU+JQ0KICBsZWZ0X2pvaW4oZGVwLGJ5PSLrtoDshJzslYTsnbTrlJQiKSAlPiUNCiAgbGVmdF9qb2luKGpvYixieT0i7JeF66y07JWE7J2065SUIikgJT4lDQogIGdyb3VwX2J5KOu2gOyEnOyVhOydtOuUlCwg67aA7ISc66qFKSAlPiUgDQogIHN1bW1hcmlzZShtYXgo7Jew67SJKSkNCg0KIyDrtoDshJzslYTsnbTrlJTrpbwg67Cc6riJIOuwm+yngCDslYrsnLzrqbQg7Iug7J6F7J6F64uI64ukLg0KIyDsi6DsnoXsnZgg7J2066aE6rO8IOyXsOu0ieydhCDqtaztlZjsi5zsmKQuDQplbXAgJT4lIA0KICBmaWx0ZXIoaXMubmEoZW1wICU+JSBzZWxlY3Qo67aA7ISc7JWE7J2065SUKSkpICU+JSANCiAgc2VsZWN0KOydtOumhCwg7Jew67SJLCDrtoDshJzslYTsnbTrlJQpDQoNCmBgYA0K