1 Zakład Bioinformatyki, Instytut Informatyki, Uniwersytet w Białymstoku

Correspondence: Jarosław Kotowicz <>

1 Bazy danych ekonomicznych i korzystanie z nich w środowisku R

  1. Unia Europejska
  1. OECD
  2. World Bank
  3. NArodowy Bank Polski - API
  4. Serwisy internetowe (dane finansowe)
  5. Inne bazy danych

2 Wybrane biblioteki w środowisku R

Wybrałem kilka bibiolotek dostępnych w środowisku R

load("Packages.RData")

Chwila na obejrzenie

packages %>% datatable()

2.1 Komisja Europejska

download.file(url = "http://ec.europa.eu/economy_finance/db_indicators/ameco/documents/ameco0.zip",
              destfile = "ameco0.zip" )
unzip("ameco0.zip")

Przeanalizujemy jedną z tabel z AMECO.

load("AMECO1.RData")
AMECO1.pl <- AMECO1 %>% filter(COUNTRY == "Poland") %>% select(-68)
AMECO1.pl
AMECO1.pl.pop <- AMECO1.pl %>% 
  slice(2:5) %>% 
  pivot_longer(
    -c(CODE, COUNTRY, `SUB-CHAPTER`, TITLE, UNIT),
    names_to = "Year",
    values_to = "Population"
  ) %>%
  select(-c(1:3, 5))
AMECO1.pl.pop %>% datatable()

Ilustracja graficzna

AMECO1.pl.pop %>% ggplot(aes(x = Year, y = Population)) +
  geom_point(aes(color = TITLE)) +
  geom_line(aes(x = Year, y = Population, group = TITLE, color = TITLE), stat="identity") +
  scale_x_discrete(breaks = seq(1960, 2022, 5)) +
  scale_y_continuous(breaks = seq(0, 40000, 5000), labels = c(0,paste(seq(5, 40, 5), "mln."))) +
  labs(title = "Populacja Polski w latach 1960 - 2020",
       colour = "Grupy wiekowe",
       x = "Rok",
       y = "Populacja Polski",
       caption = "Opracowanie własne na podstawie danych KE.") +
  theme(plot.title = element_text(hjust=0.5))

2.2 Eurostat

library(eurostat)

Podczytanie struktur magazynu danych

tabela.danych <- get_eurostat_toc()
tabela.danych %>% head(12)

Przeszukiwanie magazynu danych w poszukiwaniu danych związanych ze słowem kluczowym

wynik.education <- search_eurostat("education")
wynik.education %>% head(8)
wynik.population <- search_eurostat("Population")
wynik.population %>% head(8)

Importowanie konkretnego zbioru danych z magazynu danych Eurosatu

wynik.population[6,]
wynik.population.06 <- get_eurostat(wynik.population[6,2])
trying URL 'https://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing?sort=1&file=data%2Fdemo_r_pjanind2.tsv.gz'
Content type 'application/octet-stream;charset=UTF-8' length 604613 bytes (590 KB)
downloaded 590 KB

Table demo_r_pjanind2 cached at C:\Users\user\AppData\Local\Temp\RtmpsnjNfc/eurostat/demo_r_pjanind2_date_code_TF.rds
wynik.population.06 %>% 
  filter(str_detect(geo, "PL"))

2.3 OECD

library(OECD)
# -------->> Get a data frame with information on all available datasets.
oecd_datasets <- get_datasets()
oecd_datasets %>% dim
[1] 1366    2
# -------->> Search codes and descriptions of available OECD series
oecd_employment <- search_dataset("employment", oecd_datasets)
oecd_employment %>% datatable()
# -------->> Get the data structure of a dataset.
oecd_employment_DUR_D <- get_data_structure("DUR_D")
oecd_employment_DUR_D %>% class
[1] "list"
oecd_employment_DUR_D %>% length()
[1] 12
oecd_employment_DUR_D %>% names
 [1] "VAR_DESC"        "COUNTRY"         "TIME"            "SEX"             "AGE"             "DURATION"       
 [7] "FREQUENCY"       "OBS_STATUS"      "UNIT"            "POWERCODE"       "REFERENCEPERIOD" "TIME_FORMAT"    
oecd_employment_DUR_D$POWERCODE
oecd_employment_DUR_D$DURATION
oecd_employment_DUR_D$AGE
oecd_employment_DUR_D$COUNTRY
oecd_employment_DUR_D$UNIT %>% datatable()

Można odnaleźć na stronie OECD metadane zbioru danych.

# -------->> Download OECD data sets
oecd_employment_DUR_D_df <- get_dataset("DUR_D",
                                        filter = list(c("POL"), c("MEN")),
                                        start_time = 2000, end_time = 2018)
oecd_employment_DUR_D_df_f <- oecd_employment_DUR_D_df %>%
  filter(DURATION == "UN", AGE != "1524", AGE !="6599", AGE != "900000")
oecd_employment_DUR_D_df_f %>% head(12)

Wykres

oecd_employment_DUR_D_df_f %>% 
  ggplot(aes(x = obsTime, y = obsValue)) +
  geom_point(aes(color = AGE)) +
  geom_line(aes(x = obsTime, y = obsValue, group = AGE, color = AGE), stat="identity") +
  scale_x_discrete(breaks = seq(2000, 2018, 3)) +
 scale_y_continuous(breaks = seq(0, 1250, 250), labels = c(0,paste(seq(250, 1250, 250), "tyś."))) +
  labs(title = "Bezrobotni meżczyźni w Polsce wg grup wiekowych",
       colour = "Grupy wiekowe",
       x = "Rok",
       y = "Liczba bezrobotnych",
       caption = "Opracowanie własne na podstawie danych OECD.") +
  theme(plot.title = element_text(hjust=0.5))

2.4 Dane finansowe (biblioteki quantmod i tidyquant)

load("WebUrls.RData")
web_urls %>% datatable

Strona quantmod

library(quantmod)
library(tidyquant)
== Need to Learn tidyquant? ====================================================
Business Science offers a 1-hour course - Learning Lab #9: Performance Analysis & Portfolio Optimization with tidyquant!
</> Learn more at: https://university.business-science.io/p/learning-labs-pro </>

2.4.1 Skąd można pobrać dane

  1. Strona Yahoo Finance
  2. Strona Google Finance
  3. St. Louis Federal Reserve Bank’s FRED system
  4. Currency and Metals Data from Oanda.com

Użycie

getSymbols("USD/EUR",src="oanda")
[1] "USD/EUR"
USDEUR %>% class
[1] "xts" "zoo"
USDEUR %>% dim
[1] 179   1
USDEUR %>% colnames()
[1] "USD.EUR"

2.4.2 Microsoft

getSymbols('MSFT')
[1] "MSFT"
MSFT %>% class
[1] "xts" "zoo"
MSFT %>% dim
[1] 3333    6
MSFT %>% colnames()
[1] "MSFT.Open"     "MSFT.High"     "MSFT.Low"      "MSFT.Close"    "MSFT.Volume"   "MSFT.Adjusted"
barChart(MSFT)

candleChart(MSFT, multi.col = TRUE, theme="white")

MSFT.20 <- MSFT[3313:3333,]
barChart(MSFT.20)

candleChart(MSFT.20, multi.col = TRUE, theme="white")

library(TTR)
MSFT.my <- tq_get("MSFT", from = "2017-01-01", to = "2019-12-31")
# Bar Chart
MSFT.my %>%
    ggplot(aes(x = date, y = close)) +
    geom_barchart(aes(open = open, high = high, low = low, close = close)) +
    geom_ma(color = "darkgreen") +
    coord_x_date(xlim = c("2019-10-01", "2019-12-31"),
                 ylim = c(130, 165)) +
    labs(title = "Wykres słupkowy kursu akcji Microsoft od 01.10 do 31.12 w roku 2019",
       x = "Data",
       y = "Cena zamknięcia",
       caption = "Opracowanie własne na podstawie danych Yahoo Finance.") +
  theme(plot.title = element_text(hjust=0.5))

MSFT.my %>%
    ggplot(aes(x = date, y = close)) +
    geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
    geom_ma(color = "darkgreen") +
    coord_x_date(xlim = c("2019-10-01", "2019-12-31"),
                 ylim = c(130, 165)) +
  labs(title = "Wykres świecowy kursu akcji Microsoft od 01.10 do 31.12 w roku 2019",
       x = "Data",
       y = "Cena zamknięcia",
       caption = "Opracowanie własne na podstawie danych Yahoo Finance.") +
  theme(plot.title = element_text(hjust=0.5))

2.5 Narodowy Bank Polski i biblioteka rnbp

library(rnbp)

2.5.1 Kursy walut

waluta_EUR_A <- get_current_exchangerate("A", "EUR")
waluta_EUR_A %>% class
[1] "nbp_api_response"
waluta_EUR_A$content
$table
[1] "A"

$currency
[1] "euro"

$code
[1] "EUR"

$rates
NA
waluta_EUR_A <- get_exchangerate_from("A", "EUR", Sys.Date() - 180)
waluta_EUR_A$content
$table
[1] "A"

$currency
[1] "euro"

$code
[1] "EUR"

$rates
NA
waluta_EUR_A <- get_exchangerate_tables_from_interval(table = "A", from = Sys.Date() - 93, to = Sys.Date())
waluta_EUR_A$content
waluta_EUR_A <- get_exchangerate_from_interval(table = "A", currency_code = "EUR", 
                                                      from = Sys.Date() - 93, to = Sys.Date())
waluta_EUR_A$content
$table
[1] "A"

$currency
[1] "euro"

$code
[1] "EUR"

$rates
NA
waluta_EUR_A <- get_last_n_exchangerates("A", "EUR", 93)
waluta_EUR_A$content[[4]] %>% datatable

2.5.2 Ceny złota w NBP

2.5.2.1 Z ostatnich n dni

gold_93 <- get_last_n_goldprices(93)
gold_93$content
gold_93 <- get_goldprice_from_interval(Sys.Date() - 93, Sys.Date())
gold_93$content
LS0tDQp0aXRsZTogIkluZm9ybWF0eWthIGVrb25vbWljem5hIChraWVydW5layBpbmZvcm1hdHlrYSBpIGVrb25vbWV0cmlhKSAtIHd5a8WCYWQgNCINCmF1dGhvcjoNCi0gSmFyb3PFgmF3IEtvdG93aWN6Og0KICAgIGNvcnJlc3BvbmRlbmNlOiBubw0KICAgIGVtYWlsOiBqLmtvdG93aWN6QHV3Yi5lZHUucGwNCiAgICBpbnN0aXR1dGU6IElJVXdCDQpkYXRlOiAiMzEgbWFyY2EgMjAyMCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgaGlnaGxpZ2h0OiBoYWRkb2NrDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBwYW5kb2NfYXJnczoNCiAgICAtIC0tbHVhLWZpbHRlcj1zY2hvbGFybHktbWV0YWRhdGEubHVhDQogICAgLSAtLWx1YS1maWx0ZXI9YXV0aG9yLWluZm8tYmxvY2tzLmx1YQ0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KICAgIHRvYzogeWVzDQppbnN0aXR1dGU6DQotIElJVXdCOiBaYWvFgmFkIEJpb2luZm9ybWF0eWtpLCBJbnN0eXR1dCBJbmZvcm1hdHlraSwgVW5pd2Vyc3l0ZXQgdyBCaWHFgnltc3Rva3UNCmNzbDogYmlnLWRhdGEtYW5kLWluZm9ybWF0aW9uLWFuYWx5dGljcy5jc2wNCmFsd2F5c19hbGxvd19odG1sOiB5ZXMNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIEJhenkgZGFueWNoIGVrb25vbWljem55Y2ggaSBrb3J6eXN0YW5pZSB6IG5pY2ggdyDFm3JvZG93aXNrdSBSDQoNCjEuIFVuaWEgRXVyb3BlanNrYSANCiAgLSBbS29taXNqYSBFdXJvcGVqc2thXShodHRwczovL2VjLmV1cm9wYS5ldS9pbmZvL2J1c2luZXNzLWVjb25vbXktZXVyby9pbmRpY2F0b3JzLXN0YXRpc3RpY3MvZWNvbm9taWMtZGF0YWJhc2VzX2VuKQ0KICAgIC0gW01hY3JvLWVjb25vbWljIGRhdGFiYXNlIEFNRUNPXShodHRwczovL2VjLmV1cm9wYS5ldS9pbmZvL2J1c2luZXNzLWVjb25vbXktZXVyby9pbmRpY2F0b3JzLXN0YXRpc3RpY3MvZWNvbm9taWMtZGF0YWJhc2VzL21hY3JvLWVjb25vbWljLWRhdGFiYXNlLWFtZWNvX2VuKQ0KICAgIC0gW0J1c2luZXNzIGFuZCBjb25zdW1lciBzdXJ2ZXlzXShodHRwczovL2VjLmV1cm9wYS5ldS9pbmZvL2J1c2luZXNzLWVjb25vbXktZXVyby9pbmRpY2F0b3JzLXN0YXRpc3RpY3MvZWNvbm9taWMtZGF0YWJhc2VzL2J1c2luZXNzLWFuZC1jb25zdW1lci1zdXJ2ZXlzX2VuKQ0KICAgIC0gW1ByaWNlIGFuZCBDb3N0IENvbXBldGl0aXZlbmVzc10oaHR0cHM6Ly9lYy5ldXJvcGEuZXUvaW5mby9idXNpbmVzcy1lY29ub215LWV1cm8vaW5kaWNhdG9ycy1zdGF0aXN0aWNzL2Vjb25vbWljLWRhdGFiYXNlcy9wcmljZS1hbmQtY29zdC1jb21wZXRpdGl2ZW5lc3NfZW4pDQogICAgLSBbS0xFTVMgZGF0YV0oaHR0cHM6Ly9ldWtsZW1zLmV1LykNCiAgLSBbRUJDXShodHRwOi8vc2R3LmVjYi5ldXJvcGEuZXUvYnJvd3NlLmRvP25vZGU9OTY4OTcyNykNCiAgLSBbRXVyb3N0YXRdKGh0dHBzOi8vZWMuZXVyb3BhLmV1L2V1cm9zdGF0L2RhdGEvZGF0YWJhc2UpDQoyLiBbT0VDRF0oaHR0cHM6Ly9kYXRhLm9lY2Qub3JnLykNCjMuIFtXb3JsZCBCYW5rXShodHRwczovL2RhdGEud29ybGRiYW5rLm9yZy8pDQo0LiBbTkFyb2Rvd3kgQmFuayBQb2xza2kgLSBBUEldKGh0dHA6Ly9hcGkubmJwLnBsLyNrdXJzeVdhbHV0KQ0KNS4gU2Vyd2lzeSBpbnRlcm5ldG93ZSAoZGFuZSBmaW5hbnNvd2UpDQo2LiBJbm5lIGJhenkgZGFueWNoDQogICAgDQojIFd5YnJhbmUgYmlibGlvdGVraSB3IMWbcm9kb3dpc2t1ICoqUioqDQoNCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1UUlVFLCBpbmNsdWRlPUZBTFNFfQ0Kcm0obGlzdCA9IGxzKCkpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoRFQpDQpgYGANCg0KV3licmHFgmVtIGtpbGthIGJpYmlvbG90ZWsgZG9zdMSZcG55Y2ggdyDFm3JvZG93aXNrdSAqKlIqKg0KYGBge3J9DQpsb2FkKCJQYWNrYWdlcy5SRGF0YSIpDQpgYGANCg0KQ2h3aWxhIG5hIG9iZWpyemVuaWUNCmBgYHtyfQ0KcGFja2FnZXMgJT4lIGRhdGF0YWJsZSgpDQpgYGANCiMjIEtvbWlzamEgRXVyb3BlanNrYQ0KDQpgYGB7ciBldmFsPUZBTFNFLCBwdXJsID0gVFJVRX0NCmRvd25sb2FkLmZpbGUodXJsID0gImh0dHA6Ly9lYy5ldXJvcGEuZXUvZWNvbm9teV9maW5hbmNlL2RiX2luZGljYXRvcnMvYW1lY28vZG9jdW1lbnRzL2FtZWNvMC56aXAiLA0KICAgICAgICAgICAgICBkZXN0ZmlsZSA9ICJhbWVjbzAuemlwIiApDQp1bnppcCgiYW1lY28wLnppcCIpDQpgYGANCg0KUHJ6ZWFuYWxpenVqZW15IGplZG7EhSB6IHRhYmVsIHogKkFNRUNPKi4NCmBgYHtyfQ0KbG9hZCgiQU1FQ08xLlJEYXRhIikNCmBgYA0KDQpgYGB7cn0NCkFNRUNPMS5wbCA8LSBBTUVDTzEgJT4lIGZpbHRlcihDT1VOVFJZID09ICJQb2xhbmQiKSAlPiUgc2VsZWN0KC02OCkNCkFNRUNPMS5wbA0KYGBgDQoNCmBgYHtyfQ0KQU1FQ08xLnBsLnBvcCA8LSBBTUVDTzEucGwgJT4lIA0KICBzbGljZSgyOjUpICU+JSANCiAgcGl2b3RfbG9uZ2VyKA0KICAgIC1jKENPREUsIENPVU5UUlksIGBTVUItQ0hBUFRFUmAsIFRJVExFLCBVTklUKSwNCiAgICBuYW1lc190byA9ICJZZWFyIiwNCiAgICB2YWx1ZXNfdG8gPSAiUG9wdWxhdGlvbiINCiAgKSAlPiUNCiAgc2VsZWN0KC1jKDE6MywgNSkpDQpBTUVDTzEucGwucG9wICU+JSBkYXRhdGFibGUoKQ0KYGBgDQoNCklsdXN0cmFjamEgZ3JhZmljem5hDQpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0NCkFNRUNPMS5wbC5wb3AgJT4lIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBQb3B1bGF0aW9uKSkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFRJVExFKSkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBZZWFyLCB5ID0gUG9wdWxhdGlvbiwgZ3JvdXAgPSBUSVRMRSwgY29sb3IgPSBUSVRMRSksIHN0YXQ9ImlkZW50aXR5IikgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGJyZWFrcyA9IHNlcSgxOTYwLCAyMDIyLCA1KSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDQwMDAwLCA1MDAwKSwgbGFiZWxzID0gYygwLHBhc3RlKHNlcSg1LCA0MCwgNSksICJtbG4uIikpKSArDQogIGxhYnModGl0bGUgPSAiUG9wdWxhY2phIFBvbHNraSB3IGxhdGFjaCAxOTYwIC0gMjAyMCIsDQogICAgICAgY29sb3VyID0gIkdydXB5IHdpZWtvd2UiLA0KICAgICAgIHggPSAiUm9rIiwNCiAgICAgICB5ID0gIlBvcHVsYWNqYSBQb2xza2kiLA0KICAgICAgIGNhcHRpb24gPSAiT3ByYWNvd2FuaWUgd8WCYXNuZSBuYSBwb2RzdGF3aWUgZGFueWNoIEtFLiIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdD0wLjUpKQ0KYGBgDQoNCiMjIEV1cm9zdGF0DQoNCmBgYHtyfQ0KbGlicmFyeShldXJvc3RhdCkNCmBgYA0KDQpQb2Rjenl0YW5pZSBzdHJ1a3R1ciBtYWdhenludSBkYW55Y2gNCmBgYHtyfQ0KdGFiZWxhLmRhbnljaCA8LSBnZXRfZXVyb3N0YXRfdG9jKCkNCnRhYmVsYS5kYW55Y2ggJT4lIGhlYWQoMTIpDQpgYGANCg0KUHJ6ZXN6dWtpd2FuaWUgbWFnYXp5bnUgZGFueWNoIHcgcG9zenVraXdhbml1IGRhbnljaCB6d2nEhXphbnljaCB6ZSBzxYJvd2VtIGtsdWN6b3d5bQ0KYGBge3J9DQp3eW5pay5lZHVjYXRpb24gPC0gc2VhcmNoX2V1cm9zdGF0KCJlZHVjYXRpb24iKQ0Kd3luaWsuZWR1Y2F0aW9uICU+JSBoZWFkKDgpDQpgYGANCg0KYGBge3J9DQp3eW5pay5wb3B1bGF0aW9uIDwtIHNlYXJjaF9ldXJvc3RhdCgiUG9wdWxhdGlvbiIpDQp3eW5pay5wb3B1bGF0aW9uICU+JSBoZWFkKDgpDQpgYGANCg0KSW1wb3J0b3dhbmllIGtvbmtyZXRuZWdvIHpiaW9ydSBkYW55Y2ggeiBtYWdhenludSBkYW55Y2ggRXVyb3NhdHUNCmBgYHtyfQ0Kd3luaWsucG9wdWxhdGlvbls2LF0NCnd5bmlrLnBvcHVsYXRpb24uMDYgPC0gZ2V0X2V1cm9zdGF0KHd5bmlrLnBvcHVsYXRpb25bNiwyXSkNCmBgYA0KDQpgYGB7cn0NCnd5bmlrLnBvcHVsYXRpb24uMDYgJT4lIA0KICBmaWx0ZXIoc3RyX2RldGVjdChnZW8sICJQTCIpKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQpkZXRhY2gocGFja2FnZTpldXJvc3RhdCkNCmBgYA0KDQoNCiMjIE9FQ0QNCg0KYGBge3J9DQpsaWJyYXJ5KE9FQ0QpDQpgYGANCg0KYGBge3J9DQojIC0tLS0tLS0tPj4gR2V0IGEgZGF0YSBmcmFtZSB3aXRoIGluZm9ybWF0aW9uIG9uIGFsbCBhdmFpbGFibGUgZGF0YXNldHMuDQpvZWNkX2RhdGFzZXRzIDwtIGdldF9kYXRhc2V0cygpDQpgYGANCg0KYGBge3J9DQpvZWNkX2RhdGFzZXRzICU+JSBkaW0NCmBgYA0KDQpgYGB7cn0NCiMgLS0tLS0tLS0+PiBTZWFyY2ggY29kZXMgYW5kIGRlc2NyaXB0aW9ucyBvZiBhdmFpbGFibGUgT0VDRCBzZXJpZXMNCm9lY2RfZW1wbG95bWVudCA8LSBzZWFyY2hfZGF0YXNldCgiZW1wbG95bWVudCIsIG9lY2RfZGF0YXNldHMpDQpgYGANCg0KYGBge3J9DQpvZWNkX2VtcGxveW1lbnQgJT4lIGRhdGF0YWJsZSgpDQpgYGANCg0KYGBge3J9DQojIC0tLS0tLS0tPj4gR2V0IHRoZSBkYXRhIHN0cnVjdHVyZSBvZiBhIGRhdGFzZXQuDQpvZWNkX2VtcGxveW1lbnRfRFVSX0QgPC0gZ2V0X2RhdGFfc3RydWN0dXJlKCJEVVJfRCIpDQpgYGANCg0KYGBge3J9DQpvZWNkX2VtcGxveW1lbnRfRFVSX0QgJT4lIGNsYXNzDQpvZWNkX2VtcGxveW1lbnRfRFVSX0QgJT4lIGxlbmd0aCgpDQpvZWNkX2VtcGxveW1lbnRfRFVSX0QgJT4lIG5hbWVzDQoNCmBgYA0KDQpgYGB7cn0NCm9lY2RfZW1wbG95bWVudF9EVVJfRCRQT1dFUkNPREUNCmBgYA0KDQpgYGB7cn0NCm9lY2RfZW1wbG95bWVudF9EVVJfRCREVVJBVElPTg0KYGBgDQoNCmBgYHtyfQ0Kb2VjZF9lbXBsb3ltZW50X0RVUl9EJEFHRQ0KYGBgDQoNCmBgYHtyfQ0Kb2VjZF9lbXBsb3ltZW50X0RVUl9EJENPVU5UUlkNCmBgYA0KDQpgYGB7cn0NCm9lY2RfZW1wbG95bWVudF9EVVJfRCRVTklUICU+JSBkYXRhdGFibGUoKQ0KYGBgDQpNb8W8bmEgb2RuYWxlxbrEhyBuYSBzdHJvbmllIE9FQ0QgKm1ldGFkYW5lKiB6YmlvcnUgZGFueWNoLg0KYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRSwgcHVybD1UUlVFfQ0KIyAtLS0tLS0tLT4+ICBCcm93c2UgdGhlIG1ldGFkYXRhIHJlbGF0ZWQgdG8gYSBzZXJpZXMuDQpicm93c2VfbWV0YWRhdGEoIkRVUl9EIikNCmBgYA0KDQpgYGB7cn0NCiMgLS0tLS0tLS0+PiBEb3dubG9hZCBPRUNEIGRhdGEgc2V0cw0Kb2VjZF9lbXBsb3ltZW50X0RVUl9EX2RmIDwtIGdldF9kYXRhc2V0KCJEVVJfRCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyID0gbGlzdChjKCJQT0wiKSwgYygiTUVOIikpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0X3RpbWUgPSAyMDAwLCBlbmRfdGltZSA9IDIwMTgpDQpgYGANCg0KYGBge3J9DQpvZWNkX2VtcGxveW1lbnRfRFVSX0RfZGZfZiA8LSBvZWNkX2VtcGxveW1lbnRfRFVSX0RfZGYgJT4lDQogIGZpbHRlcihEVVJBVElPTiA9PSAiVU4iLCBBR0UgIT0gIjE1MjQiLCBBR0UgIT0iNjU5OSIsIEFHRSAhPSAiOTAwMDAwIikNCmBgYA0KDQpgYGB7cn0NCm9lY2RfZW1wbG95bWVudF9EVVJfRF9kZl9mICU+JSBoZWFkKDEyKQ0KYGBgDQpXeWtyZXMNCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwfQ0Kb2VjZF9lbXBsb3ltZW50X0RVUl9EX2RmX2YgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBvYnNUaW1lLCB5ID0gb2JzVmFsdWUpKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gQUdFKSkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBvYnNUaW1lLCB5ID0gb2JzVmFsdWUsIGdyb3VwID0gQUdFLCBjb2xvciA9IEFHRSksIHN0YXQ9ImlkZW50aXR5IikgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGJyZWFrcyA9IHNlcSgyMDAwLCAyMDE4LCAzKSkgKw0KIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMTI1MCwgMjUwKSwgbGFiZWxzID0gYygwLHBhc3RlKHNlcSgyNTAsIDEyNTAsIDI1MCksICJ0ecWbLiIpKSkgKw0KICBsYWJzKHRpdGxlID0gIkJlenJvYm90bmkgbWXFvGN6ecW6bmkgdyBQb2xzY2Ugd2cgZ3J1cCB3aWVrb3d5Y2giLA0KICAgICAgIGNvbG91ciA9ICJHcnVweSB3aWVrb3dlIiwNCiAgICAgICB4ID0gIlJvayIsDQogICAgICAgeSA9ICJMaWN6YmEgYmV6cm9ib3RueWNoIiwNCiAgICAgICBjYXB0aW9uID0gIk9wcmFjb3dhbmllIHfFgmFzbmUgbmEgcG9kc3Rhd2llIGRhbnljaCBPRUNELiIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdD0wLjUpKQ0KYGBgDQoNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCmRldGFjaChwYWNrYWdlOk9FQ0QpDQpgYGANCg0KIyMgRGFuZSBmaW5hbnNvd2UgKGJpYmxpb3Rla2kgKipxdWFudG1vZCoqIGkgKip0aWR5cXVhbnQqKikNCg0KYGBge3J9DQpsb2FkKCJXZWJVcmxzLlJEYXRhIikNCndlYl91cmxzICU+JSBkYXRhdGFibGUNCmBgYA0KW1N0cm9uYSBxdWFudG1vZF0oaHR0cDovL3d3dy5xdWFudG1vZC5jb20vKQ0KDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHF1YW50bW9kKQ0KbGlicmFyeSh0aWR5cXVhbnQpDQpgYGANCg0KIyMjIFNrxIVkIG1vxbxuYSBwb2JyYcSHIGRhbmUNCg0KMS4gW1N0cm9uYSBZYWhvbyBGaW5hbmNlXShodHRwczovL2ZpbmFuY2UueWFob28uY29tLykNCjIuIFtTdHJvbmEgR29vZ2xlIEZpbmFuY2VdKGh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vZmluYW5jZS8pDQozLiBbU3QuIExvdWlzIEZlZGVyYWwgUmVzZXJ2ZSBCYW5rJ3MgRlJFRCBzeXN0ZW1dKGh0dHBzOi8vZnJlZC5zdGxvdWlzZmVkLm9yZy8pDQo0LiBbQ3VycmVuY3kgYW5kIE1ldGFscyBEYXRhIGZyb20gT2FuZGEuY29tXShodHRwczovL3d3dy5vYW5kYS5jb20vKQ0KDQpVxbx5Y2llDQpgYGB7cn0NCmdldFN5bWJvbHMoIlVTRC9FVVIiLHNyYz0ib2FuZGEiKQ0KYGBgDQpgYGB7cn0NClVTREVVUiAlPiUgY2xhc3MNClVTREVVUiAlPiUgZGltDQpVU0RFVVIgJT4lIGNvbG5hbWVzKCkNCmBgYA0KDQoNCiMjIyBNaWNyb3NvZnQNCiANCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpnZXRTeW1ib2xzKCdNU0ZUJykNCmBgYA0KDQpgYGB7cn0NCk1TRlQgJT4lIGNsYXNzDQpNU0ZUICU+JSBkaW0NCk1TRlQgJT4lIGNvbG5hbWVzKCkNCmBgYA0KDQpgYGB7cn0NCmJhckNoYXJ0KE1TRlQpDQpgYGANCmBgYHtyfQ0KY2FuZGxlQ2hhcnQoTVNGVCwgbXVsdGkuY29sID0gVFJVRSwgdGhlbWU9IndoaXRlIikNCmBgYA0KDQpgYGB7cn0NCk1TRlQuMjAgPC0gTVNGVFszMzEzOjMzMzMsXQ0KYGBgDQoNCmBgYHtyfQ0KYmFyQ2hhcnQoTVNGVC4yMCkNCmBgYA0KDQpgYGB7cn0NCmNhbmRsZUNoYXJ0KE1TRlQuMjAsIG11bHRpLmNvbCA9IFRSVUUsIHRoZW1lPSJ3aGl0ZSIpDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KFRUUikNCmBgYA0KDQpgYGB7cn0NCk1TRlQubXkgPC0gdHFfZ2V0KCJNU0ZUIiwgZnJvbSA9ICIyMDE3LTAxLTAxIiwgdG8gPSAiMjAxOS0xMi0zMSIpDQpgYGANCg0KYGBge3IgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9MTB9DQojIEJhciBDaGFydA0KTVNGVC5teSAlPiUNCiAgICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gY2xvc2UpKSArDQogICAgZ2VvbV9iYXJjaGFydChhZXMob3BlbiA9IG9wZW4sIGhpZ2ggPSBoaWdoLCBsb3cgPSBsb3csIGNsb3NlID0gY2xvc2UpKSArDQogICAgZ2VvbV9tYShjb2xvciA9ICJkYXJrZ3JlZW4iKSArDQogICAgY29vcmRfeF9kYXRlKHhsaW0gPSBjKCIyMDE5LTEwLTAxIiwgIjIwMTktMTItMzEiKSwNCiAgICAgICAgICAgICAgICAgeWxpbSA9IGMoMTMwLCAxNjUpKSArDQogICAgbGFicyh0aXRsZSA9ICJXeWtyZXMgc8WCdXBrb3d5IGt1cnN1IGFrY2ppIE1pY3Jvc29mdCBvZCAwMS4xMCBkbyAzMS4xMiB3IHJva3UgMjAxOSIsDQogICAgICAgeCA9ICJEYXRhIiwNCiAgICAgICB5ID0gIkNlbmEgemFta25pxJljaWEiLA0KICAgICAgIGNhcHRpb24gPSAiT3ByYWNvd2FuaWUgd8WCYXNuZSBuYSBwb2RzdGF3aWUgZGFueWNoIFlhaG9vIEZpbmFuY2UuIikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0PTAuNSkpDQoNCmBgYA0KDQpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0NCk1TRlQubXkgJT4lDQogICAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IGNsb3NlKSkgKw0KICAgIGdlb21fY2FuZGxlc3RpY2soYWVzKG9wZW4gPSBvcGVuLCBoaWdoID0gaGlnaCwgbG93ID0gbG93LCBjbG9zZSA9IGNsb3NlKSkgKw0KICAgIGdlb21fbWEoY29sb3IgPSAiZGFya2dyZWVuIikgKw0KICAgIGNvb3JkX3hfZGF0ZSh4bGltID0gYygiMjAxOS0xMC0wMSIsICIyMDE5LTEyLTMxIiksDQogICAgICAgICAgICAgICAgIHlsaW0gPSBjKDEzMCwgMTY1KSkgKw0KICBsYWJzKHRpdGxlID0gIld5a3JlcyDFm3dpZWNvd3kga3Vyc3UgYWtjamkgTWljcm9zb2Z0IG9kIDAxLjEwIGRvIDMxLjEyIHcgcm9rdSAyMDE5IiwNCiAgICAgICB4ID0gIkRhdGEiLA0KICAgICAgIHkgPSAiQ2VuYSB6YW1rbmnEmWNpYSIsDQogICAgICAgY2FwdGlvbiA9ICJPcHJhY293YW5pZSB3xYJhc25lIG5hIHBvZHN0YXdpZSBkYW55Y2ggWWFob28gRmluYW5jZS4iKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3Q9MC41KSkNCmBgYA0KIyMgTmFyb2Rvd3kgQmFuayBQb2xza2kgaSBiaWJsaW90ZWthICoqcm5icCoqDQoNCmBgYHtyfQ0KbGlicmFyeShybmJwKQ0KYGBgDQoNCiMjIyBbS3Vyc3kgd2FsdXRdKGh0dHA6Ly9hcGkubmJwLnBsLyNrdXJzeVdhbHV0KQ0KYGBge3J9DQp3YWx1dGFfRVVSX0EgPC0gZ2V0X2N1cnJlbnRfZXhjaGFuZ2VyYXRlKCJBIiwgIkVVUiIpDQp3YWx1dGFfRVVSX0EgJT4lIGNsYXNzDQp3YWx1dGFfRVVSX0EkY29udGVudA0KYGBgDQpgYGB7cn0NCndhbHV0YV9FVVJfQSA8LSBnZXRfZXhjaGFuZ2VyYXRlX2Zyb20oIkEiLCAiRVVSIiwgU3lzLkRhdGUoKSAtIDE4MCkNCndhbHV0YV9FVVJfQSRjb250ZW50DQpgYGANCg0KYGBge3J9DQp3YWx1dGFfRVVSX0EgPC0gZ2V0X2V4Y2hhbmdlcmF0ZV90YWJsZXNfZnJvbV9pbnRlcnZhbCh0YWJsZSA9ICJBIiwgZnJvbSA9IFN5cy5EYXRlKCkgLSA5MywgdG8gPSBTeXMuRGF0ZSgpKQ0Kd2FsdXRhX0VVUl9BJGNvbnRlbnQNCmBgYA0KDQoNCmBgYHtyfQ0Kd2FsdXRhX0VVUl9BIDwtIGdldF9leGNoYW5nZXJhdGVfZnJvbV9pbnRlcnZhbCh0YWJsZSA9ICJBIiwgY3VycmVuY3lfY29kZSA9ICJFVVIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb20gPSBTeXMuRGF0ZSgpIC0gOTMsIHRvID0gU3lzLkRhdGUoKSkNCndhbHV0YV9FVVJfQSRjb250ZW50DQpgYGANCg0KYGBge3J9DQp3YWx1dGFfRVVSX0EgPC0gZ2V0X2xhc3Rfbl9leGNoYW5nZXJhdGVzKCJBIiwgIkVVUiIsIDkzKQ0Kd2FsdXRhX0VVUl9BJGNvbnRlbnRbWzRdXSAlPiUgZGF0YXRhYmxlDQpgYGANCiMjIyBbQ2VueSB6xYJvdGEgdyBOQlBdKGh0dHA6Ly9hcGkubmJwLnBsLyNjZW55WmxvdGEpDQoNCiMjIyMgWiBvc3RhdG5pY2ggKm4qIGRuaQ0KYGBge3J9DQpnb2xkXzkzIDwtIGdldF9sYXN0X25fZ29sZHByaWNlcyg5MykNCmdvbGRfOTMkY29udGVudA0KYGBgDQoNCmBgYHtyfQ0KZ29sZF85MyA8LSBnZXRfZ29sZHByaWNlX2Zyb21faW50ZXJ2YWwoU3lzLkRhdGUoKSAtIDkzLCBTeXMuRGF0ZSgpKQ0KZ29sZF85MyRjb250ZW50DQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCmRldGFjaChwYWNrYWdlOnJuYnApDQpkZXRhY2gocGFja2FnZTp0aWR5cXVhbnQpDQpkZXRhY2gocGFja2FnZTpCYXRjaEdldFN5bWJvbHMpDQpkZXRhY2gocGFja2FnZTpxdWFudG1vZCkNCmRldGFjaChwYWNrYWdlOlRUUikNCmRldGFjaChwYWNrYWdlOnRpZHl2ZXJzZSkNCmRldGFjaChwYWNrYWdlOmdncGxvdDIpDQpkZXRhY2gocGFja2FnZTp0aWJibGUpDQpkZXRhY2gocGFja2FnZTp0aWR5cikNCmRldGFjaChwYWNrYWdlOnJlYWRyKQ0KZGV0YWNoKHBhY2thZ2U6cHVycnIpDQpkZXRhY2gocGFja2FnZTpkcGx5cikNCmRldGFjaChwYWNrYWdlOnN0cmluZ3IpDQpkZXRhY2gocGFja2FnZTpmb3JjYXRzKQ0KDQpgYGANCg0K