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

Correspondence: Jarosław Kotowicz <>

1 Wstęp

  1. Ręczne ściąganie danych z bazy danych bdl GUS vs. zautomatyzowane ściąganie danych
  2. Instalowanie biblioteki bdl
  3. Podczytanie biblioteki bdl i tidyverse
  4. Omówienie podstawowych funkcji bdl
library(bdl)
library(tidyverse)

Czyszczenie środowiska

rm(list = ls())

2 Praca z bibioteką bdl

2.1 Grupa 2

2.1.1 Funkcja get_levels - poziomy jednostej statystycznych

Jednostki statystycznych vs. jednostki administracyjne

poziomy <- get_levels()
Błąd w poleceniu 'curl::curl_fetch_memory(url, handle = handle)':
  Send failure: Connection was aborted

2.1.2 Funkcja get_units - drzewo jednostek statystycznych

#tree <- get_units()
load("bdlTree.RData")
tree %>% colnames
[1] "id"             "name"           "level"          "unitHasChanged" "parentId"       "kind"          

2.1.2.1 Poziomy województwa, powiatu i gminy

tree %>% DT::datatable()
tree %>% filter(level == 2)
wojewodztwa <- tree %>% filter(level == 2)
powiaty <- tree %>% filter(level == 5)
gminy <- tree %>% filter(level == 6)

2.1.3 Funkcja unit_info - informacje dotyczące jednostki statytycznej

unit_info("062000000000")
$id
[1] "062000000000"

$name
[1] "PODLASKIE"

$parentId
[1] "060000000000"

$level
[1] 2

$hasDescription
[1] FALSE

$years
 [1] 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
[23] 2017 2018 2019 2020

2.1.3.1 Zapisywanie identyfikatorów jednostek stytystycznych wybranego poziomu

wojewodztwa.id <- wojewodztwa %>% pull(id)
powiaty.id <- powiaty %>% pull(id)
gminy.id <- gminy %>% pull(id)

2.1.4 Funkcja get_subjects - informacje dotyczące zakresu danych - tematyki

2.1.4.1 Poziom kategorii danych statystycznych

subject <- get_subjects()

2.1.5 Funkcja subject_info - informacje dotyczące kategorii

subject_info("K3")
$id
[1] "K3"

$name
[1] "LUDNOŚĆ"

$hasVariables
[1] FALSE

$children
[1] "G7"   "G8"   "G10"  "G534" "G535" "G557" "G564"

$years
 [1] 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
[23] 2017 2018 2019 2020

$availability

$dimensions
list()

$lastUpdate
[1] "2020-05-07T08:37:43.133"

$description
[1] "Bilanse liczby i struktury ludności w gminach imiennie opracowane w oparciu o wyniki Narodowych Spisów Powszechnych z uwzględnieniem zmian spowodowanych ruchem naturalnym (urodzenia i zgony), migracjami ludności (na pobyt stały i czasowy) oraz przemieszczeniami związanymi ze zmianami administracyjnymi. Dane o ludności w miejscowościach na podstawie rejestru PESEL. Dane o zarejestrowanych małżeństwach, urodzeniach i zgonach pochodzące ze sprawozdawczości urzędów stanu cywilnego. Dane o orzeczonych rozwodach i separacjach pochodzące ze sprawozdawczości sądów. Dane o migracjach wewnętrznych i zagranicznych na pobyt stały pochodzą z Ministerstwa Spraw Wewnętrznych i Administracji. Prognoza ludności na podstawie badania GUS."
subject_info("K3", lang = "en")
$id
[1] "K3"

$name
[1] "POPULATION"

$hasVariables
[1] FALSE

$children
[1] "G7"   "G8"   "G10"  "G534" "G535" "G557" "G564"

$years
 [1] 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
[23] 2017 2018 2019 2020

$availability

$dimensions
list()

$lastUpdate
[1] "2020-05-07T08:37:43.133"

$description
[1] "Balance of size and structure of the population in gminas was prepared on the basis of the National Population Censuses including changes connected with vital statistics (births and deaths) and migration of the population (for permanent residence and for temporary stay) and changes caused by administrative changes. The data on population in localities based on PESEL register. The data on registered marriages, births and deaths based on the reports of civil status offices. The data on divorces and separations based on the reports of courts. The data on internal and international migration for permanent residence are obtained from the Ministry of the Interior and Administration. Population projection based the results of survey conducted by the Statistics Poland."

2.1.6 Funkcje get_subjects i subject_info c.d.

2.1.6.1 Poziom grup statystycznych dla wybranej kategorii danych

subject.K4 <- get_subjects(parentId = "K4")

2.1.6.2 Poziom podgrup statystycznych dla wybranej grupy danych

subject.K4.G13 <- get_subjects(parentId = "G13")
subject_info("P1960")
$id
[1] "P1960"

$parentId
[1] "G13"

$name
[1] "Stwierdzone choroby zawodowe"

$hasVariables
[1] TRUE

$children
list()

$years
 [1] 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019

$availability

$dimensions
[1] "Rodzaje chorób"

$lastUpdate
[1] "2019-06-18T15:10:17.22"

$description
[1] "Liczba na Polskę ogółem może być wyższa niż suma z poszczególnych województw, jeśli wystąpią przypadki chorób zawodowych, które powstały w zakładach pracy poza granicami Polski."

Polecenie:
Wybrać dowolną podgrupę i ją zapisać

subject.K18.G559 <- get_subjects(parentId = "G559")
subject_info("P3186")
$id
[1] "P3186"

$parentId
[1] "G559"

$name
[1] "Turystyczne obiekty noclegowe w lipcu"

$hasVariables
[1] TRUE

$children
list()

$years
[1] 2012 2013 2014 2015 2016 2017 2018 2019 2020

$availability

$dimensions
[1] "Obiekty"           "Obiekty"           " miejsca i pokoje"

$lastUpdate
[1] "2019-09-30T10:06:23.68"

2.1.7 Funkcja get_varaible - pobieranie zmiennych

dane <- get_variables("P3186")

2.1.8 Funkcja variable_info - informacje o zmiennych

variable_info("289443")
$id
[1] 289443

$subjectId
[1] "P3186"

$n1
[1] "pensjonaty"

$n2
[1] "pokoje z własną łazienką i WC"

$level
[1] 6

$measureUnitId
[1] 1

$measureUnitName
[1] "-"

$years
[1] 2012 2013 2014 2015 2016 2017 2018 2019 2020

2.1.9 Funkcja get_data_by_unit - pobieranie zmiennych dla danej jednostki

dane_289443 <- get_data_by_unit(unitId = "042800000000", varId = "289443")
dane_289443

2.2 Grupa 1

Przypomnienie dotyczące przetwarzania potokowego

  • a %>% f oznacza f(a)
  • a %>% f(b) oznacza f(a, b)
  • b %>% f(a, .) oznacza f(a,b)
rm(list = ls())

2.2.1 Funkcja get_levels

poziomy <- get_levels()
poziomy

2.2.1.1 Drzewo jednostek statystycznych

load("bdlTree.RData")
tree %>% colnames
[1] "id"             "name"           "level"          "unitHasChanged" "parentId"       "kind"          

2.2.1.2 Wybór województw, powiatów i gmin

tree %>% filter(level == 2)
wojewodztwa <- tree %>% filter(level == 2)
powiaty <- tree %>% filter(level == 5)
gminy <- tree %>% filter(level == 6)

2.2.2 Funkcja unit_info

unit_info("062000000000")
$id
[1] "062000000000"

$name
[1] "PODLASKIE"

$parentId
[1] "060000000000"

$level
[1] 2

$hasDescription
[1] FALSE

$years
 [1] 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
[23] 2017 2018 2019 2020
wojewodztwa.id <- wojewodztwa %>% pull(id)
powiaty.id <- powiaty %>% pull(id)
gminy.id <- gminy %>% pull(id)

2.2.3 Funkcja get_subjects

subject <- get_subjects()

2.2.4 Funkcja subjects_info

subject_info("K3")
$id
[1] "K3"

$name
[1] "LUDNOŚĆ"

$hasVariables
[1] FALSE

$children
[1] "G7"   "G8"   "G10"  "G534" "G535" "G557" "G564"

$years
 [1] 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
[23] 2017 2018 2019 2020

$availability

$dimensions
list()

$lastUpdate
[1] "2020-05-07T08:37:43.133"

$description
[1] "Bilanse liczby i struktury ludności w gminach imiennie opracowane w oparciu o wyniki Narodowych Spisów Powszechnych z uwzględnieniem zmian spowodowanych ruchem naturalnym (urodzenia i zgony), migracjami ludności (na pobyt stały i czasowy) oraz przemieszczeniami związanymi ze zmianami administracyjnymi. Dane o ludności w miejscowościach na podstawie rejestru PESEL. Dane o zarejestrowanych małżeństwach, urodzeniach i zgonach pochodzące ze sprawozdawczości urzędów stanu cywilnego. Dane o orzeczonych rozwodach i separacjach pochodzące ze sprawozdawczości sądów. Dane o migracjach wewnętrznych i zagranicznych na pobyt stały pochodzą z Ministerstwa Spraw Wewnętrznych i Administracji. Prognoza ludności na podstawie badania GUS."
subject_info("K3", lang = "en")
$id
[1] "K3"

$name
[1] "POPULATION"

$hasVariables
[1] FALSE

$children
[1] "G7"   "G8"   "G10"  "G534" "G535" "G557" "G564"

$years
 [1] 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
[23] 2017 2018 2019 2020

$availability

$dimensions
list()

$lastUpdate
[1] "2020-05-07T08:37:43.133"

$description
[1] "Balance of size and structure of the population in gminas was prepared on the basis of the National Population Censuses including changes connected with vital statistics (births and deaths) and migration of the population (for permanent residence and for temporary stay) and changes caused by administrative changes. The data on population in localities based on PESEL register. The data on registered marriages, births and deaths based on the reports of civil status offices. The data on divorces and separations based on the reports of courts. The data on internal and international migration for permanent residence are obtained from the Ministry of the Interior and Administration. Population projection based the results of survey conducted by the Statistics Poland."
subject.ludosc <- get_subjects(parentId = "K3")
subject.ludosc.G7 <- get_subjects(parentId = "G7")
subject_info("P2137")
$id
[1] "P2137"

$parentId
[1] "G7"

$name
[1] "Ludność wg grup wieku i płci"

$hasVariables
[1] TRUE

$children
list()

$years
 [1] 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
[23] 2017 2018 2019

$availability

$dimensions
[1] "Wiek" "Płeć"

$lastUpdate
[1] "2019-05-22T15:25:01.16"

$description
[1] "Dane wg podziału administracyjnego na dzień 31 XII."

2.2.5 Funkcja get_variables

dane <- get_variables("P2137")

2.2.6 Funkcja variables_info

variable_info("47693")
$id
[1] 47693

$subjectId
[1] "P2137"

$n1
[1] "60-64"

$n2
[1] "kobiety"

$level
[1] 6

$measureUnitId
[1] 26

$measureUnitName
[1] "osoba"

$years
 [1] 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
[23] 2017 2018 2019

2.2.7 Funkcja get_data_by_unit dla jednej zmiennej

dane.id.47693 <- get_data_by_unit(unitId = "062000000000", varId = "47693")

2.2.7.1 Wybór identyfikatorów zmiennych

dane.id <- dane %>% pull(id)
dane.id.zmienne <- get_data_by_unit(unitId = "062000000000", varId = dane.id)

2.2.7.2 Próba połączenia wartości zmiennych z ich opisem (funkcja left_join)

wynik <- dane.id.zmienne %>%
  left_join(dane)
Joining, by = c("id", "measureUnitId")
BŁĄD: Can't join on 'id' x 'id' because of incompatible types (integer / character)
2.2.7.2.1 Przekształcenie, aby można było wykonać łączenie (funkcja mutate)
dane <- dane %>%
  mutate(id = as.character(id))
wynik <- dane.id.zmienne %>%
  left_join(dane)
Joining, by = c("id", "measureUnitId")
2.2.7.2.2 Łączenie wartości zmiennych z ich opisem z ustawianiem kolejności zmiennych (funkcja select)

Różnice między funkcją pull, a select

wynik <- dane.id.zmienne %>%
  left_join(dane) %>%
  select(subjectId, id, n1, n2, level, measureUnitId, measureUnitName, year, val)
Joining, by = c("id", "measureUnitId")
wynik %>% DT::datatable()

3 Praca domowa

Grupa 2: Wybrać kategorię, grupę, podgrupę i ją podczytać.

Grupa 1: Wybrać kategorię, grupę, podgrupę i zbudować tabelę zawierającą wartości zmiennych z ich opisem z ustawianiem kolejności zmiennych.

LS0tDQp0aXRsZTogIkluZm9ybWF0eWthIGVrb25vbWljem5hIChraWVydW5layBpbmZvcm1hdHlrYSBpIGVrb25vbWV0cmlhKSAtIGxhYm9yYXRvcml1bSAxMSINCnN1YnRpdGxlOiAiUHJhY2EgeiBiaWJsaW90ZWvEhSAqKmJkbCoqIg0KYXV0aG9yOg0KLSBKYXJvc8WCYXcgS290b3dpY3o6DQogICAgY29ycmVzcG9uZGVuY2U6IG5vDQogICAgZW1haWw6IGoua290b3dpY3pAdXdiLmVkdS5wbA0KICAgIGluc3RpdHV0ZTogSUlVd0INCmRhdGU6ICIxMiBtYWphIDIwMjByLiINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgaGlnaGxpZ2h0OiBoYWRkb2NrDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBwYW5kb2NfYXJnczoNCiAgICAtIC0tbHVhLWZpbHRlcj1zY2hvbGFybHktbWV0YWRhdGEubHVhDQogICAgLSAtLWx1YS1maWx0ZXI9YXV0aG9yLWluZm8tYmxvY2tzLmx1YQ0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KICAgIHRvYzogeWVzDQppbnN0aXR1dGU6DQotIElJVXdCOiBaYWvFgmFkIEJpb2luZm9ybWF0eWtpLCBJbnN0eXR1dCBJbmZvcm1hdHlraSwgVW5pd2Vyc3l0ZXQgdyBCaWHFgnltc3Rva3UNCmNzbDogYmlnLWRhdGEtYW5kLWluZm9ybWF0aW9uLWFuYWx5dGljcy5jc2wNCmFsd2F5c19hbGxvd19odG1sOiB5ZXMNCi0tLQ0KDQojIFdzdMSZcA0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KMS4gUsSZY3puZSDFm2NpxIVnYW5pZSBkYW55Y2ggeiBiYXp5IGRhbnljaCAqKmJkbCoqICpHVVMqIHZzLiB6YXV0b21hdHl6b3dhbmUgxZtjacSFZ2FuaWUgZGFueWNoIA0KMi4gSW5zdGFsb3dhbmllIGJpYmxpb3Rla2kgKipiZGwqKg0KMy4gUG9kY3p5dGFuaWUgYmlibGlvdGVraSAqKmJkbCoqIGkgKip0aWR5dmVyc2UqKg0KNC4gT23Ds3dpZW5pZSBwb2RzdGF3b3d5Y2ggZnVua2NqaSAqYmRsKg0KDQpgYGB7cn0NCmxpYnJhcnkoYmRsKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpgYGANCg0KKkN6eXN6Y3plbmllIMWbcm9kb3dpc2thKg0KYGBge3J9DQpybShsaXN0ID0gbHMoKSkNCmBgYA0KDQojIFByYWNhIHogYmliaW90ZWvEhSAqKmJkbCoqDQoNCiMjIEdydXBhIDINCg0KIyMjIEZ1bmtjamEgKmdldF9sZXZlbHMqIC0gcG96aW9teSBqZWRub3N0ZWogc3RhdHlzdHljem55Y2ggIA0KDQoqSmVkbm9zdGtpIHN0YXR5c3R5Y3pueWNoKiB2cy4gKmplZG5vc3RraSBhZG1pbmlzdHJhY3lqbmUqDQpgYGB7cn0NCnBvemlvbXkgPC0gZ2V0X2xldmVscygpDQpwb3ppb215DQpgYGANCg0KIyMjIEZ1bmtjamEgKmdldF91bml0cyogLSBkcnpld28gamVkbm9zdGVrIHN0YXR5c3R5Y3pueWNoDQpgYGB7cn0NCiN0cmVlIDwtIGdldF91bml0cygpDQpsb2FkKCJiZGxUcmVlLlJEYXRhIikNCmBgYA0KDQpgYGB7cn0NCnRyZWUgJT4lIGNvbG5hbWVzDQpgYGANCg0KIyMjIyBQb3ppb215IHdvamV3w7NkenR3YSwgcG93aWF0dSBpIGdtaW55DQpgYGB7cn0NCnRyZWUgJT4lIERUOjpkYXRhdGFibGUoKQ0KYGBgDQoNCmBgYHtyfQ0KdHJlZSAlPiUgZmlsdGVyKGxldmVsID09IDIpDQpgYGANCg0KYGBge3J9DQp3b2pld29kenR3YSA8LSB0cmVlICU+JSBmaWx0ZXIobGV2ZWwgPT0gMikNCnBvd2lhdHkgPC0gdHJlZSAlPiUgZmlsdGVyKGxldmVsID09IDUpDQpnbWlueSA8LSB0cmVlICU+JSBmaWx0ZXIobGV2ZWwgPT0gNikNCmBgYA0KDQojIyMgRnVua2NqYSAqdW5pdF9pbmZvKiAtIGluZm9ybWFjamUgZG90eWN6xIVjZSBqZWRub3N0a2kgc3RhdHl0eWN6bmVqDQpgYGB7cn0NCnVuaXRfaW5mbygiMDYyMDAwMDAwMDAwIikNCmBgYA0KDQojIyMjIFphcGlzeXdhbmllIGlkZW50eWZpa2F0b3LDs3cgamVkbm9zdGVrIHN0eXR5c3R5Y3pueWNoIHd5YnJhbmVnbyBwb3ppb211DQpgYGB7cn0NCndvamV3b2R6dHdhLmlkIDwtIHdvamV3b2R6dHdhICU+JSBwdWxsKGlkKQ0KcG93aWF0eS5pZCA8LSBwb3dpYXR5ICU+JSBwdWxsKGlkKQ0KZ21pbnkuaWQgPC0gZ21pbnkgJT4lIHB1bGwoaWQpDQpgYGANCg0KIyMjIEZ1bmtjamEgKmdldF9zdWJqZWN0cyogLSBpbmZvcm1hY2plIGRvdHljesSFY2UgemFrcmVzdSBkYW55Y2ggLSB0ZW1hdHlraQ0KDQojIyMjIFBvemlvbSBrYXRlZ29yaWkgZGFueWNoIHN0YXR5c3R5Y3pueWNoDQpgYGB7cn0NCnN1YmplY3QgPC0gZ2V0X3N1YmplY3RzKCkNCmBgYA0KDQojIyMgRnVua2NqYSAqc3ViamVjdF9pbmZvKiAtIGluZm9ybWFjamUgZG90eWN6xIVjZSBrYXRlZ29yaWkNCmBgYHtyfQ0Kc3ViamVjdF9pbmZvKCJLMyIpDQpzdWJqZWN0X2luZm8oIkszIiwgbGFuZyA9ICJlbiIpDQpgYGANCg0KIyMjIEZ1bmtjamUgKmdldF9zdWJqZWN0cyogaSAqc3ViamVjdF9pbmZvKiBjLmQuDQoNCiMjIyMgUG96aW9tIGdydXAgc3RhdHlzdHljem55Y2ggZGxhIHd5YnJhbmVqIGthdGVnb3JpaSBkYW55Y2gNCmBgYHtyfQ0Kc3ViamVjdC5LNCA8LSBnZXRfc3ViamVjdHMocGFyZW50SWQgPSAiSzQiKQ0KYGBgDQoNCiMjIyMgUG96aW9tIHBvZGdydXAgc3RhdHlzdHljem55Y2ggZGxhIHd5YnJhbmVqIGdydXB5IGRhbnljaA0KYGBge3J9DQpzdWJqZWN0Lks0LkcxMyA8LSBnZXRfc3ViamVjdHMocGFyZW50SWQgPSAiRzEzIikNCmBgYA0KDQpgYGB7cn0NCnN1YmplY3RfaW5mbygiUDE5NjAiKQ0KYGBgDQoNCjxzcGFuIHN0eWxlPSJjb2xvcjogcmVkIj4gUG9sZWNlbmllOiA8YnI+IFd5YnJhxIcgZG93b2xuxIUgcG9kZ3J1cMSZIGkgasSFIHphcGlzYcSHPC9zcGFuPg0KDQpgYGB7cn0NCnN1YmplY3QuSzE4Lkc1NTkgPC0gZ2V0X3N1YmplY3RzKHBhcmVudElkID0gIkc1NTkiKQ0Kc3ViamVjdF9pbmZvKCJQMzE4NiIpDQpgYGANCg0KIyMjIEZ1bmtjamEgKmdldF92YXJhaWJsZSogLSAgcG9iaWVyYW5pZSB6bWllbm55Y2gNCmBgYHtyfQ0KZGFuZSA8LSBnZXRfdmFyaWFibGVzKCJQMzE4NiIpDQpgYGANCg0KIyMjIEZ1bmtjamEgKnZhcmlhYmxlX2luZm8qIC0gaW5mb3JtYWNqZSBvIHptaWVubnljaA0KYGBge3J9DQp2YXJpYWJsZV9pbmZvKCIyODk0NDMiKQ0KYGBgDQoNCiMjIyBGdW5rY2phICpnZXRfZGF0YV9ieV91bml0KiAtIHBvYmllcmFuaWUgem1pZW5ueWNoIGRsYSBkYW5laiBqZWRub3N0a2kNCmBgYHtyfQ0KZGFuZV8yODk0NDMgPC0gZ2V0X2RhdGFfYnlfdW5pdCh1bml0SWQgPSAiMDQyODAwMDAwMDAwIiwgdmFySWQgPSAiMjg5NDQzIikNCmBgYA0KDQpgYGB7cn0NCmRhbmVfMjg5NDQzDQpgYGANCg0KIyMgR3J1cGEgMQ0KDQpQcnp5cG9tbmllbmllIGRvdHljesSFY2UgcHJ6ZXR3YXJ6YW5pYSBwb3Rva293ZWdvDQoNCiAgLSBhICU+JSBmICAgICAgICBvem5hY3phICAgZihhKQ0KICAtIGEgJT4lIGYoYikgICAgIG96bmFjemEgICBmKGEsIGIpDQogIC0gYiAlPiUgZihhLCAuKSAgb3puYWN6YSAgIGYoYSxiKQ0KDQoNCmBgYHtyfQ0Kcm0obGlzdCA9IGxzKCkpDQpgYGANCg0KIyMjIEZ1bmtjamEgKmdldF9sZXZlbHMqDQpgYGB7cn0NCnBvemlvbXkgPC0gZ2V0X2xldmVscygpDQpwb3ppb215DQpgYGANCiMjIyMgRHJ6ZXdvIGplZG5vc3RlayBzdGF0eXN0eWN6bnljaA0KYGBge3J9DQpsb2FkKCJiZGxUcmVlLlJEYXRhIikNCmBgYA0KDQpgYGB7cn0NCnRyZWUgJT4lIGNvbG5hbWVzDQpgYGANCg0KIyMjIyBXeWLDs3Igd29qZXfDs2R6dHcsIHBvd2lhdMOzdyBpIGdtaW4NCmBgYHtyfQ0KdHJlZSAlPiUgZmlsdGVyKGxldmVsID09IDIpDQpgYGANCg0KYGBge3J9DQp3b2pld29kenR3YSA8LSB0cmVlICU+JSBmaWx0ZXIobGV2ZWwgPT0gMikNCnBvd2lhdHkgPC0gdHJlZSAlPiUgZmlsdGVyKGxldmVsID09IDUpDQpnbWlueSA8LSB0cmVlICU+JSBmaWx0ZXIobGV2ZWwgPT0gNikNCmBgYA0KDQojIyMgRnVua2NqYSAqdW5pdF9pbmZvKg0KYGBge3J9DQp1bml0X2luZm8oIjA2MjAwMDAwMDAwMCIpDQpgYGANCg0KDQpgYGB7cn0NCndvamV3b2R6dHdhLmlkIDwtIHdvamV3b2R6dHdhICU+JSBwdWxsKGlkKQ0KcG93aWF0eS5pZCA8LSBwb3dpYXR5ICU+JSBwdWxsKGlkKQ0KZ21pbnkuaWQgPC0gZ21pbnkgJT4lIHB1bGwoaWQpDQpgYGANCg0KIyMjIEZ1bmtjamEgKmdldF9zdWJqZWN0cyoNCmBgYHtyfQ0Kc3ViamVjdCA8LSBnZXRfc3ViamVjdHMoKQ0KYGBgDQoNCiMjIyBGdW5rY2phICpzdWJqZWN0c19pbmZvKg0KYGBge3J9DQpzdWJqZWN0X2luZm8oIkszIikNCmBgYA0KDQpgYGB7cn0NCnN1YmplY3RfaW5mbygiSzMiLCBsYW5nID0gImVuIikNCmBgYA0KDQpgYGB7cn0NCnN1YmplY3QubHVkb3NjIDwtIGdldF9zdWJqZWN0cyhwYXJlbnRJZCA9ICJLMyIpDQpgYGANCg0KYGBge3J9DQpzdWJqZWN0Lmx1ZG9zYy5HNyA8LSBnZXRfc3ViamVjdHMocGFyZW50SWQgPSAiRzciKQ0KYGBgDQoNCmBgYHtyfQ0Kc3ViamVjdF9pbmZvKCJQMjEzNyIpDQpgYGANCg0KIyMjIEZ1bmtjamEgKmdldF92YXJpYWJsZXMqDQpgYGB7cn0NCmRhbmUgPC0gZ2V0X3ZhcmlhYmxlcygiUDIxMzciKQ0KYGBgDQoNCiMjIyBGdW5rY2phICp2YXJpYWJsZXNfaW5mbyoNCmBgYHtyfQ0KdmFyaWFibGVfaW5mbygiNDc2OTMiKQ0KYGBgDQoNCiMjIyBGdW5rY2phICpnZXRfZGF0YV9ieV91bml0KiBkbGEgamVkbmVqIHptaWVubmVqDQpgYGB7cn0NCmRhbmUuaWQuNDc2OTMgPC0gZ2V0X2RhdGFfYnlfdW5pdCh1bml0SWQgPSAiMDYyMDAwMDAwMDAwIiwgdmFySWQgPSAiNDc2OTMiKQ0KYGBgDQoNCiMjIyMgV3liw7NyIGlkZW50eWZpa2F0b3LDs3cgem1pZW5ueWNoIA0KYGBge3J9DQpkYW5lLmlkIDwtIGRhbmUgJT4lIHB1bGwoaWQpDQpgYGANCg0KYGBge3J9DQpkYW5lLmlkLnptaWVubmUgPC0gZ2V0X2RhdGFfYnlfdW5pdCh1bml0SWQgPSAiMDYyMDAwMDAwMDAwIiwgdmFySWQgPSBkYW5lLmlkKQ0KYGBgDQoNCiMjIyMgUHLDs2JhIHBvxYLEhWN6ZW5pYSB3YXJ0b8WbY2kgem1pZW5ueWNoIHogaWNoIG9waXNlbSAoZnVua2NqYSAqbGVmdF9qb2luKikNCmBgYHtyfQ0Kd3luaWsgPC0gZGFuZS5pZC56bWllbm5lICU+JQ0KICBsZWZ0X2pvaW4oZGFuZSkNCmBgYA0KDQojIyMjIyBQcnpla3N6dGHFgmNlbmllLCBhYnkgbW/FvG5hIGJ5xYJvIHd5a29uYcSHIMWCxIVjemVuaWUgKGZ1bmtjamEgKm11dGF0ZSopDQpgYGB7cn0NCmRhbmUgPC0gZGFuZSAlPiUNCiAgbXV0YXRlKGlkID0gYXMuY2hhcmFjdGVyKGlkKSkNCmBgYA0KDQpgYGB7cn0NCnd5bmlrIDwtIGRhbmUuaWQuem1pZW5uZSAlPiUNCiAgbGVmdF9qb2luKGRhbmUpDQpgYGANCg0KIyMjIyMgxYHEhWN6ZW5pZSB3YXJ0b8WbY2kgem1pZW5ueWNoIHogaWNoIG9waXNlbSB6IHVzdGF3aWFuaWVtIGtvbGVqbm/Fm2NpIHptaWVubnljaCAoZnVua2NqYSAqc2VsZWN0KikNClLDs8W8bmljZSBtacSZZHp5IGZ1bmtjasSFICpwdWxsKiwgYSAqc2VsZWN0Kg0KYGBge3J9DQp3eW5payA8LSBkYW5lLmlkLnptaWVubmUgJT4lDQogIGxlZnRfam9pbihkYW5lKSAlPiUNCiAgc2VsZWN0KHN1YmplY3RJZCwgaWQsIG4xLCBuMiwgbGV2ZWwsIG1lYXN1cmVVbml0SWQsIG1lYXN1cmVVbml0TmFtZSwgeWVhciwgdmFsKQ0KYGBgDQpgYGB7cn0NCnd5bmlrICU+JSBEVDo6ZGF0YXRhYmxlKCkNCmBgYA0KDQojIFByYWNhIGRvbW93YQ0KDQpHcnVwYSAyOiBXeWJyYcSHIGthdGVnb3JpxJksIGdydXDEmSwgcG9kZ3J1cMSZIGkgasSFIHBvZGN6eXRhxIcuDQoNCkdydXBhIDE6IFd5YnJhxIcga2F0ZWdvcmnEmSwgZ3J1cMSZLCBwb2RncnVwxJkgaSB6YnVkb3dhxIcgdGFiZWzEmSB6YXdpZXJhasSFY8SFICp3YXJ0b8WbY2kgem1pZW5ueWNoIHogaWNoIG9waXNlbSB6IHVzdGF3aWFuaWVtIGtvbGVqbm/Fm2NpIHptaWVubnljaCou