This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.
Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.
plot(cars)
필요한 패키지
---
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("XML" %in% installed.packages("XML") == FALSE)install.packages("XML")
if("data.table" %in% installed.packages("data.table") == FALSE)install.packages("data.table")
library(data.table)
install.packages("dplyr")
library(dplyr)
Oracle 데이터를 Rstudio 로 가져오는 방법
myJDBC <- JDBC("oracle.jdbc.driver.OracleDriver",
"C:\\Users\\jiwon\\ojdbc6.jar")
conn <- dbConnect(myJDBC,
"jdbc:oracle:thin:@localhost:1521:xe",
"hr",
"oracle"
)
tab <- dbGetQuery(conn,"SELECT * FROM TAB")
tab
dplyr
filter, 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
[3] “EMPLOYEES” emp “EMP_DETAILS_VIEW” empd
[5] “JOBS” job “JOB_HISTORY” jobh
[7] “LOCATIONS” loc “REGIONS” reg
cnt <- data.frame(dbGetQuery(conn,"SELECT * FROM COUNTRIES"))
#마찬가지로 해보기
head(cnt)
str(cnt)
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"))
cnt의 컬럼명을 한글로 전환하시오
str(cnt)
#COUNRTY_ID 국가아이디,
#COUNTRNAME 국가명,
#REGION_ID 지역아이디,
#MANAGER_ID 매니저아이디
#LOCATION_ID 위치아이디
install.packages("dplyr")
library(dplyr)
cnt<- cnt %>%
dplyr::rename(국가아이디=COUNTRY_ID,
국가명=COUNTRY_NAME,
지역아이디=REGION_ID)
cnt
#dep의 칼럼명 전환
str(dep)
head(dep)
emp 의 컬럼명을 한글로 전환하시오.
그리고 First Name 과 Last Name 을
붙여서 이름 으로 된 컬럼을 추가하시오
단, 이름 간격은 띄울것. ex) James Dean
install.packages("dplyr")
library(dplyr)
str(emp)
emp<- emp %>%
dplyr::rename(전화번호=PHONE_NUMBER
) %>% mutate(이름=paste(FIRST_NAME,LAST_NAME)) # 두 변수 붙이기
View(head(emp))
필요없는 변수 삭제하기 부분함수를 구해서 마이너스 하면 제거된것처럼 된다
emp<-subset(empd,select=-c(FIRST_NAME,LAST_NAME))
View(head(empd))
매달 지급하는 월급여(연봉/12)를 보여주는
월급이라는 컬럼(변수)를 추가하시오. 0단위 이하는 절삭
emp <- emp %>% #emp에 뒤에 연산 부분을 추가하는것
dplyr::mutate(월급=연봉%/%12)
emp %>% head
View(emp)
연봉이 10000불 이상인 사원(emp)의 목록을 이름, 직원아이디, 연봉만 구하되,
연봉 내림차순으로 보여주시오(Get)
emp %>%
filter(연봉>=10000) %>% #파이트라인 뒤에는 왠만하면 줄바꿈
select(이름,EMPLOYEE_ID,연봉) %>%
arrange(desc(연봉))
연봉이 3000미만인 사원에게 보너스로 급여의 15%를 지급하겠다 한다.
보너스 컬럼을 추가하고,대상자의 목록을 이름 직원아이디 연봉을 기재하고 오름차순으으로 보여주시오.
install.packages("dplyr")
library(dplyr)
emp<-emp %>%
filter(연봉<3000) %>%
dplyr::mutate(보너스=연봉 * 0.15)
emp %>% select(이름, EMPLOYEE_ID, 연봉, 보너스) %>%
arrange(EMPLOYEE_ID)
+단, 보너스는 이번 달만 주는 것이므로, emp dataframe에 저장하지는 말고, 1회용 임시 df를 따로
생성해서 저장하고, 기한이 지나서는 폐기하라.
install.packages("dplyr")
library(dplyr)
emp<-emp %>%
filter(연봉<3000) %>%
dplyr::mutate(보너스=연봉 * 0.15)
emp %>% select(이름, EMPLOYEE_ID, 연봉, 보너스) %>%
arrange(EMPLOYEE_ID)
보너스지급명세서<- emp %>%
filter(연봉<3000) %>%
dplyr::mutate(보너스=연봉 * 0.15) %>%
select(이름, EMPLOYEE_ID, 연봉, 보너스) %>%
arrange(EMPLOYEE_ID)
View(보너스지급명세서)
rm(보너스지급명세서)
연봉이 10000이 넘는 직원의 부서명, 이름, 연봉을 출력(get.화살표 노)하시오.—<틀ㄹ #부서명은 dp안에 안나와있고 아이디만 나와있음. dp df안에 부서명 나와있으니 두개 join
install.packages("dplyr")
library(dplyr)
dep<- dep %>%
dplyr::rename(DEPARTMENT_ID=부서아이디)
emp<- emp %>%
dplyr::rename(DEPARTMENT_ID=부서아이디)
View(emp)
View(dep)
emp %>% #왼쪽에있는 emp기준.오른쪽에 있는것을 합쳐라
left_join(dep,by="DEPARTMENT_ID") %>% #두 df가 공통으로 가지고 있는것을by뒤에 둔다.
filter(연봉>=1000) %>%
select(DEPARTMENT_NAME,이름,연봉)
부서별로 연봉 평균을 구하시오–<틀ㄹ #(일대일 대응되는 두 요소-부서아이디와 부서명.그루핑 하기)
install.packages("dplyr")
library(dplyr)
emp %>%
left_join(dep,by="DEPARTMENT_ID") %>%
group_by(DEPARTMENT_NAME,DEPARTMENT_ID)
dplyr::summarise(연봉평균=mean(연봉,na.rm=T)) %>% #지운다rm=T--->
arrange(desc(연봉평균)) %>% View
이 회사의 부서의 수를 구하시오거<–
dep %>%
dplyr::distinct(DEPARTMENT_NAME) %>% #distinct:중복제ㄱ
count
연봉이 12000이 넘는 직원의 부서명, 이름, 연봉, 직책을 기재하시오
job. emp. dep 합쳐야함
install.packages("dplyr")
library(dplyr)
job %>% viwe
dep %>%
left_join(emp,by="DEPARTMENT_ID") %>%
left_join(job,by="JOB_ID")
filter(연봉>1200) %>%
select(DEPARTMENT_NAME,이름,연봉,JOB_NAME)
문제풀때는 항상 공통되는값을 기준으로!
부서별로 가장 높은 최대 연봉을 받는 부서아이디, 부서명, 최대연봉을 구하시오.max(연봉)
emp %>%
left_join(deb,by="DEPARTMENT_ID") %>%
left_join(job,by"JOB_ID") %>%
group_by(DEPARTMENT_ID,DEPARTMENT_NAME) %>%
summarise(max(연봉))
부서아이디를 발급받지 않으면 신입입니다.
신입의 이름과 연봉을 구하시오
install.packages("dplyr")
library(dplyr)
View(emp)
emp %>%
filter(is.na(emp %>% select(DEPARTMENT_ID))) ##이줄이핵심
selcect(이름,연봉,DEPARTMENT_NAME)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLiANCg0KYGBge3J9DQpwbG90KGNhcnMpDQpgYGANCuyXiOyKteuLiOuLpA0KLS0tDQojIyPrjbDsnbTthLDrsqDsnbTsiqQg67aE7ISd7ZWY6riwDQojI+2VhOyalO2VnCDtjKjtgqTsp4ANCg0KDQoNCmBgYHtyfQ0KLS0tDQppZigickphdmEiICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCJySmF2YSIpID09IEZBTFNFKWluc3RhbGwucGFja2FnZXMoInJKYXZhIikNCmxpYnJhcnkockphdmEpDQppZigiREJJIiAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygiREJJIikgPT0gRkFMU0UpaW5zdGFsbC5wYWNrYWdlcygiREJJIikNCmxpYnJhcnkoREJJKQ0KaWYoIlJKREJDIiAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygiUkpEQkMiKSA9PSBGQUxTRSlpbnN0YWxsLnBhY2thZ2VzKCJSSkRCQyIpDQpsaWJyYXJ5KFJKREJDKQ0KaWYoIlhNTCIgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoIlhNTCIpID09IEZBTFNFKWluc3RhbGwucGFja2FnZXMoIlhNTCIpDQppZigiZGF0YS50YWJsZSIgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoImRhdGEudGFibGUiKSA9PSBGQUxTRSlpbnN0YWxsLnBhY2thZ2VzKCJkYXRhLnRhYmxlIikNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmluc3RhbGwucGFja2FnZXMoImRwbHlyIikNCmxpYnJhcnkoZHBseXIpDQpgYGANCiMjIyBPcmFjbGUg642w7J207YSw66W8IFJzdHVkaW8g66GcIOqwgOyguOyYpOuKlCDrsKnrspUNCmBgYHtyfQ0KbXlKREJDIDwtIEpEQkMoIm9yYWNsZS5qZGJjLmRyaXZlci5PcmFjbGVEcml2ZXIiLA0KICAgICAgICAgICAgICAgIkM6XFxVc2Vyc1xcaml3b25cXG9qZGJjNi5qYXIiKQ0KY29ubiA8LSBkYkNvbm5lY3QobXlKREJDLA0KICAgICAgICAgICAgICAgICAgImpkYmM6b3JhY2xlOnRoaW46QGxvY2FsaG9zdDoxNTIxOnhlIiwNCiAgICAgICAgICAgICAgICAgICJociIsDQogICAgICAgICAgICAgICAgICAib3JhY2xlIg0KKQ0KdGFiIDwtIGRiR2V0UXVlcnkoY29ubiwiU0VMRUNUICogRlJPTSBUQUIiKQ0KdGFiDQpgYGANCg0KDQojI2RwbHlyDQojIyBmaWx0ZXIsIHNlbGVjdCwgYXJyYW5nZSwgbXV0YXRlLCANCiMjc3VtbWFyaXNlLCBncm91cF9ieSwgbGVmdF9qb2luLCBiaW5kX3Jvd3MNCmBgYHtyfQ0KdGFiIDwtIGRhdGEuZnJhbWUodGFiKQ0KVmlldyh0YWIpDQp0bmFtZSA8LSB0YWIkVE5BTUUNCnRuYW1lIDwtIGFzLnZlY3Rvcih0bmFtZSkNCnRuYW1lDQpgYGANCg0KIyBbMV0gIkNPVU5UUklFUyIgY250ICAgICAgICJERVBBUlRNRU5UUyIgZGVwICAgICANCiMgWzNdICJFTVBMT1lFRVMiIGVtcCAgICAgICAgIkVNUF9ERVRBSUxTX1ZJRVciIGVtcGQNCiMgWzVdICJKT0JTIiBqb2IgICAgICAgICAgICAgIkpPQl9ISVNUT1JZIiBqb2JoICAgICANCiMgWzddICJMT0NBVElPTlMiIGxvYyAgICAgICAiUkVHSU9OUyIgcmVnDQoNCmBgYHtyfQ0KDQpjbnQgPC0gZGF0YS5mcmFtZShkYkdldFF1ZXJ5KGNvbm4sIlNFTEVDVCAqIEZST00gQ09VTlRSSUVTIikpDQoj66eI7LCs6rCA7KeA66GcIO2VtOuztOq4sA0KaGVhZChjbnQpDQpzdHIoY250KQ0KZGVwPC0gZGF0YS5mcmFtZShkYkdldFF1ZXJ5KGNvbm4sIlNFTEVDVCAqIEZST00gREVQQVJUTUVOVFMiKSkNCmVtcDwtIGRhdGEuZnJhbWUoZGJHZXRRdWVyeShjb25uLCJTRUxFQ1QgKiBGUk9NIEVNUExPWUVFUyIpKQ0KZW1wZDwtIGRhdGEuZnJhbWUoZGJHZXRRdWVyeShjb25uLCJTRUxFQ1QgKiBGUk9NIEVNUF9ERVRBSUxTX1ZJRVciKSkNCmpvYjwtIGRhdGEuZnJhbWUoZGJHZXRRdWVyeShjb25uLCJTRUxFQ1QgKiBGUk9NIEpPQlMiKSkNCmpvYmg8LSBkYXRhLmZyYW1lKGRiR2V0UXVlcnkoY29ubiwiU0VMRUNUICogRlJPTSBKT0JfSElTVE9SWSIpKQ0KbG9jPC0gZGF0YS5mcmFtZShkYkdldFF1ZXJ5KGNvbm4sIlNFTEVDVCAqIEZST00gTE9DQVRJT05TIikpDQpyZWc8LSBkYXRhLmZyYW1lKGRiR2V0UXVlcnkoY29ubiwiU0VMRUNUICogRlJPTSBSRUdJT05TIikpDQpgYGANCg0KI2NudOydmCDsu6zrn7zrqoXsnYQg7ZWc6riA66GcIOyghO2ZmO2VmOyLnOyYpA0KYGBge3J9DQpzdHIoY250KQ0KI0NPVU5SVFlfSUQg6rWt6rCA7JWE7J2065SULA0KI0NPVU5UUk5BTUUg6rWt6rCA66qFLA0KI1JFR0lPTl9JRCDsp4Dsl63slYTsnbTrlJQsDQojTUFOQUdFUl9JRCDrp6Tri4jsoIDslYTsnbTrlJQNCiNMT0NBVElPTl9JRCDsnITsuZjslYTsnbTrlJQNCmluc3RhbGwucGFja2FnZXMoImRwbHlyIikNCmxpYnJhcnkoZHBseXIpDQpjbnQ8LSBjbnQgJT4lDQpkcGx5cjo6cmVuYW1lKOq1reqwgOyVhOydtOuUlD1DT1VOVFJZX0lELA0KICAgICAgICAgICAgICAgICAgIOq1reqwgOuqhT1DT1VOVFJZX05BTUUsDQogICAgICAgICAgICAgICAgICAg7KeA7Jet7JWE7J2065SUPVJFR0lPTl9JRCkNCmNudA0KI2RlcOydmCDsubzrn7zrqoUg7KCE7ZmYDQpzdHIoZGVwKQ0KaGVhZChkZXApDQoNCmBgYA0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyBlbXAg7J2YIOy7rOufvOuqheydhCDtlZzquIDroZwg7KCE7ZmY7ZWY7Iuc7JikLg0KIyMg6re466as6rOgIEZpcnN0IE5hbWUg6rO8IExhc3QgTmFtZSDsnYQNCiMjIOu2meyXrOyEnCDsnbTrpoQg7Jy866GcIOuQnCDsu6zrn7zsnYQg7LaU6rCA7ZWY7Iuc7JikDQojIyDri6gsIOydtOumhCDqsITqsqnsnYAg652E7Jq46rKDLiBleCkgSmFtZXMgRGVhbg0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpDQpsaWJyYXJ5KGRwbHlyKQ0Kc3RyKGVtcCkNCmVtcDwtIGVtcCAlPiUNCmRwbHlyOjpyZW5hbWUo7KCE7ZmU67KI7Zi4PVBIT05FX05VTUJFUg0KICAgICAgICAgICAgICAgICApICU+JSAgbXV0YXRlKOydtOumhD1wYXN0ZShGSVJTVF9OQU1FLExBU1RfTkFNRSkpICMg65GQIOuzgOyImCDrtpnsnbTquLANClZpZXcoaGVhZChlbXApKQ0KYGBgDQoNCiPtlYTsmpTsl4bripQg67OA7IiYIOyCreygnO2VmOq4sCDrtoDrtoTtlajsiJjrpbwg6rWs7ZW07IScIOuniOydtOuEiOyKpCDtlZjrqbQg7KCc6rGw65Cc6rKD7LKY65+8IOuQnOuLpA0KYGBge3J9DQplbXA8LXN1YnNldChlbXBkLHNlbGVjdD0tYyhGSVJTVF9OQU1FLExBU1RfTkFNRSkpDQpWaWV3KGhlYWQoZW1wZCkpDQoNCmBgYA0KDQoj66ek64usIOyngOq4ie2VmOuKlCDsm5TquInsl6wo7Jew67SJLzEyKeulvCDrs7Tsl6zso7zripQNCiPsm5TquInsnbTrnbzripQg7Lus65+8KOuzgOyImCnrpbwg7LaU6rCA7ZWY7Iuc7JikLiAw64uo7JyEIOydtO2VmOuKlCDsoIjsgq0NCmBgYHtyfQ0KZW1wIDwtIGVtcCAlPiUgICAjZW1w7JeQIOuSpOyXkCDsl7DsgrAg67aA67aE7J2EIOy2lOqwgO2VmOuKlOqygw0KICBkcGx5cjo6bXV0YXRlKOyblOq4iT3sl7DrtIklLyUxMikgIA0KZW1wICU+JSBoZWFkDQpWaWV3KGVtcCkNCg0KYGBgDQoNCiPsl7DrtInsnbQgMTAwMDDrtogg7J207IOB7J24IOyCrOybkChlbXAp7J2YIOuqqeuhneydhCDsnbTrpoQsIOyngeybkOyVhOydtOuUlCwg7Jew67SJ66eMIOq1rO2VmOuQmCwgDQoj7Jew67SJIOuCtOumvOywqOyInOycvOuhnCDrs7Tsl6zso7zsi5zsmKQoR2V0KQ0KYGBge3J9DQplbXAgJT4lIA0KICBmaWx0ZXIo7Jew67SJPj0xMDAwMCkgJT4lICPtjIzsnbTtirjrnbzsnbgg65Kk7JeQ64qUIOyZoOunjO2VmOuptCDspITrsJTqv4ggDQpzZWxlY3Qo7J2066aELEVNUExPWUVFX0lELOyXsOu0iSkgJT4lIA0KICBhcnJhbmdlKGRlc2Mo7Jew67SJKSkNCg0KYGBgDQoNCg0KI+yXsOu0ieydtCAzMDAw66+466eM7J24IOyCrOybkOyXkOqyjCDrs7TrhIjsiqTroZwg6riJ7Jes7J2YIDE1JeulvCDsp4DquIntlZjqsqDri6Qg7ZWc64ukLg0KI+uztOuEiOyKpCDsu6zrn7zsnYQg7LaU6rCA7ZWY6rOgLOuMgOyDgeyekOydmCDrqqnroZ3snYQg7J2066aEIOyngeybkOyVhOydtOuUlCDsl7DrtInsnYQg6riw7J6s7ZWY6rOgIOyYpOumhOywqOyInOycvOycvOuhnCDrs7Tsl6zso7zsi5zsmKQuDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoImRwbHlyIikNCmxpYnJhcnkoZHBseXIpDQoNCmVtcDwtZW1wICU+JQ0KZmlsdGVyKOyXsOu0iTwzMDAwKSAlPiUgDQogIGRwbHlyOjptdXRhdGUo67O064SI7IqkPeyXsOu0iSAqIDAuMTUpDQoNCmVtcCAlPiUgc2VsZWN0KOydtOumhCwgRU1QTE9ZRUVfSUQsIOyXsOu0iSwg67O064SI7IqkKSAlPiUgDQogIGFycmFuZ2UoRU1QTE9ZRUVfSUQpDQoNCmBgYA0KDQojK+uLqCwg67O064SI7Iqk64qUIOydtOuyiCDri6zrp4wg7KO864qUIOqyg+ydtOuvgOuhnCwgZW1wIGRhdGFmcmFtZeyXkCDsoIDsnqXtlZjsp4DripQg66eQ6rOgLCAx7ZqM7JqpIOyehOyLnCBkZuulvCDrlLDroZwNCiPsg53shLHtlbTshJwg7KCA7J6l7ZWY6rOgLCDquLDtlZzsnbQg7KeA64KY7ISc64qUIO2PkOq4sO2VmOudvC4NCmBgYHtyfQ0KaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQ0KbGlicmFyeShkcGx5cikNCg0KZW1wPC1lbXAgJT4lDQpmaWx0ZXIo7Jew67SJPDMwMDApICU+JSANCiAgZHBseXI6Om11dGF0ZSjrs7TrhIjsiqQ97Jew67SJICogMC4xNSkNCg0KZW1wICU+JSBzZWxlY3Qo7J2066aELCBFTVBMT1lFRV9JRCwg7Jew67SJLCDrs7TrhIjsiqQpICU+JSANCiAgYXJyYW5nZShFTVBMT1lFRV9JRCkNCuuztOuEiOyKpOyngOq4ieuqheyEuOyEnDwtIGVtcCAlPiUgDQogIGZpbHRlcijsl7DrtIk8MzAwMCkgJT4lIA0KICBkcGx5cjo6bXV0YXRlKOuztOuEiOyKpD3sl7DrtIkgKiAwLjE1KSAlPiUgDQogIHNlbGVjdCjsnbTrpoQsIEVNUExPWUVFX0lELCDsl7DrtIksIOuztOuEiOyKpCkgJT4lIA0KICBhcnJhbmdlKEVNUExPWUVFX0lEKQ0KIFZpZXco67O064SI7Iqk7KeA6riJ66qF7IS47IScKQ0KIHJtKOuztOuEiOyKpOyngOq4ieuqheyEuOyEnCkNCg0KYGBgDQoNCiANCiANCiANCg0KI+yXsOu0ieydtCAxMDAwMOydtCDrhJjripQg7KeB7JuQ7J2YIOu2gOyEnOuqhSwg7J2066aELCDsl7DrtInsnYQg7Lac66ClKGdldC7tmZTsgrTtkZwg64W4Ke2VmOyLnOyYpC4tLS087YuA44S5DQoj67aA7ISc66qF7J2AIGRw7JWI7JeQIOyViOuCmOyZgOyeiOqzoCDslYTsnbTrlJTrp4wg64KY7JmA7J6I7J2MLiBkcCBkZuyViOyXkCDrtoDshJzrqoUg64KY7JmA7J6I7Jy864uIIOuRkOqwnCBqb2luDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoImRwbHlyIikNCmxpYnJhcnkoZHBseXIpDQoNCmRlcDwtIGRlcCAlPiUNCiAgZHBseXI6OnJlbmFtZShERVBBUlRNRU5UX0lEPeu2gOyEnOyVhOydtOuUlCkNCmVtcDwtIGVtcCAlPiUNCiAgZHBseXI6OnJlbmFtZShERVBBUlRNRU5UX0lEPeu2gOyEnOyVhOydtOuUlCkNClZpZXcoZW1wKQ0KVmlldyhkZXApDQplbXAgJT4lICAj7Jm87Kq97JeQ7J6I64qUIGVtcOq4sOykgC7smKTrpbjsqr3sl5Ag7J6I64qU6rKD7J2EIO2VqeyzkOudvA0KICBsZWZ0X2pvaW4oZGVwLGJ5PSJERVBBUlRNRU5UX0lEIikgJT4lICAgI+uRkCBkZuqwgCDqs7XthrXsnLzroZwg6rCA7KeA6rOgIOyeiOuKlOqyg+ydhGJ565Kk7JeQIOuRlOuLpC4gDQogIGZpbHRlcijsl7DrtIk+PTEwMDApICU+JSANCiAgc2VsZWN0KERFUEFSVE1FTlRfTkFNRSzsnbTrpoQs7Jew67SJKQ0KDQoNCmBgYA0KDQojIOu2gOyEnOuzhOuhnCDsl7DrtIkg7Y+J6reg7J2EIOq1rO2VmOyLnOyYpC0tPO2LgOOEuQ0KIyjsnbzrjIDsnbwg64yA7J2R65CY64qUIOuRkCDsmpTshowt67aA7ISc7JWE7J2065SU7JmAIOu2gOyEnOuqhS7qt7jro6jtlZEg7ZWY6riwKQ0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpDQpsaWJyYXJ5KGRwbHlyKQ0KZW1wICU+JSANCiAgbGVmdF9qb2luKGRlcCxieT0iREVQQVJUTUVOVF9JRCIpICU+JSANCiAgZ3JvdXBfYnkoREVQQVJUTUVOVF9OQU1FLERFUEFSVE1FTlRfSUQpDQpkcGx5cjo6c3VtbWFyaXNlKOyXsOu0ie2Pieq3oD1tZWFuKOyXsOu0iSxuYS5ybT1UKSkgJT4lICAj7KeA7Jq064ukcm09VC0tLT4NCiAgYXJyYW5nZShkZXNjKOyXsOu0ie2Pieq3oCkpICU+JSBWaWV3DQoNCmBgYA0KDQoNCiMg7J20IO2ajOyCrOydmCDrtoDshJzsnZgg7IiY66W8IOq1rO2VmOyLnOyYpOqxsDwtLQ0KYGBge3J9DQpkZXAgJT4lIA0KICBkcGx5cjo6ZGlzdGluY3QoREVQQVJUTUVOVF9OQU1FKSAlPiUgICNkaXN0aW5jdDrspJHrs7XsoJzjhLENCiAgY291bnQNCg0KYGBgDQoNCiPsl7DrtInsnbQgMTIwMDDsnbQg64SY64qUIOyngeybkOydmCDrtoDshJzrqoUsIOydtOumhCwg7Jew67SJLCDsp4HssYXsnYQg6riw7J6s7ZWY7Iuc7JikDQojam9iLiBlbXAuIGRlcCDtlanss5DslbztlagNCmBgYHtyfQ0KDQppbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpDQpsaWJyYXJ5KGRwbHlyKQ0Kam9iICU+JSB2aXdlDQpkZXAgJT4lIA0KICBsZWZ0X2pvaW4oZW1wLGJ5PSJERVBBUlRNRU5UX0lEIikgJT4lIA0KICBsZWZ0X2pvaW4oam9iLGJ5PSJKT0JfSUQiKQ0KZmlsdGVyKOyXsOu0iT4xMjAwKSAlPiUgDQogIHNlbGVjdChERVBBUlRNRU5UX05BTUUs7J2066aELOyXsOu0iSxKT0JfTkFNRSkNCg0KYGBgDQoNCiMj66y47KCc7ZKA65WM64qUIO2VreyDgSDqs7XthrXrkJjripTqsJLsnYQg6riw7KSA7Jy866GcIQ0KIyPrtoDshJzrs4TroZwg6rCA7J6lIOuGkuydgCDstZzrjIAg7Jew67SJ7J2EIOuwm+uKlCDrtoDshJzslYTsnbTrlJQsIOu2gOyEnOuqhSwg7LWc64yA7Jew67SJ7J2EIOq1rO2VmOyLnOyYpC5tYXgo7Jew67SJKQ0KYGBge3J9DQplbXAgJT4lIA0KICBsZWZ0X2pvaW4oZGViLGJ5PSJERVBBUlRNRU5UX0lEIikgJT4lIA0KbGVmdF9qb2luKGpvYixieSJKT0JfSUQiKSAlPiUgDQogIGdyb3VwX2J5KERFUEFSVE1FTlRfSUQsREVQQVJUTUVOVF9OQU1FKSAlPiUgDQogIHN1bW1hcmlzZShtYXgo7Jew67SJKSkNCg0KYGBgDQoNCiPrtoDshJzslYTsnbTrlJTrpbwg67Cc6riJ67Cb7KeAIOyViuycvOuptCDsi6DsnoXsnoXri4jri6QuDQoj7Iug7J6F7J2YIOydtOumhOqzvCDsl7DrtInsnYQg6rWs7ZWY7Iuc7JikDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoImRwbHlyIikNCmxpYnJhcnkoZHBseXIpDQpWaWV3KGVtcCkNCmVtcCAlPiUgDQpmaWx0ZXIoaXMubmEoZW1wICU+JSBzZWxlY3QoREVQQVJUTUVOVF9JRCkpKSAjI+ydtOykhOydtO2VteyLrA0Kc2VsY2VjdCjsnbTrpoQs7Jew67SJLERFUEFSVE1FTlRfTkFNRSkNCmBgYA==