knitr::opts_chunk$set(echo = TRUE, warning=FALSE)

This is the final analysis. All the datasets have been pre-processing into the df_filtered.rds file

Packages

pacman::p_load(tidyverse, # data science tools
               janitor, # data cleaning and tabyl
               sf,  # for maps
               gtsummary,  # for tables and regression summary
               ggpubr, # for ggplot themes
               scales, # for ggplot scales
               here) # files paths
theme_set(theme_minimal())

2. START FROM HERE Load the RDS file

# df <- readRDS(here("datasets", "df.rds"))
# test with new dataset
# df <- readRDS(here("datasets", "df_with_all_2021.rds"))
df_filtered <- readRDS(here("datasets", "df_filtered.rds"))

Filter dates to avoid dates from the second semester 2019

df_filtered <- df_filtered %>%
  filter(ep_beig_dat > "2018-12-31") %>% 
  filter(!between(ep_beig_dat, as.Date('2019-06-30'), as.Date('2019-12-31')))

Codification

EDA

Hoy many patients?

n_distinct(df_filtered$pid) %>% 
  knitr::kable()
x
60932

How many interventions?


df_filtered %>%
  select(ep_beig_dat, manipulation_type, periods) %>%
  # remove first semester 2020
  filter(!between(ep_beig_dat, as.Date('2020-06-30'), as.Date('2020-12-31'))) %>%
  # remove first semester 2021
  filter(!between(ep_beig_dat, as.Date('2021-06-30'), as.Date('2021-12-31'))) %>%
  # count
  select(-ep_beig_dat) %>%
  mutate(manipulation_type = fct_drop(manipulation_type)) %>%
  group_by(manipulation_type, periods) %>%
  count() %>%
  pivot_wider(
    names_from = periods,
    ,
    names_prefix = "y",
    values_from = n
  ) %>%
  mutate("Variation 2020" = (y2020 - y2019) / y2019 * 100) %>% 
  mutate("Variation 2021" = (y2021 - y2019) / y2019 * 100) %>% 
  knitr::kable()
manipulation_type y2019 y2020 y2021 Variation 2020 Variation 2021
Dental hygiene 88729 62588 80901 -29.46162 -8.822369
Examination 52853 38395 51622 -27.35512 -2.329102
Fluoride applications 61618 45085 58352 -26.83145 -5.300399
Hygiene instructions 62224 45382 58933 -27.06673 -5.288956
NA

df_filtered %>% 
    # remove first semester 2020
  filter(!between(ep_beig_dat, as.Date('2020-06-30'), as.Date('2020-12-31'))) %>%
  # remove first semester 2021
  filter(!between(ep_beig_dat, as.Date('2021-06-30'), as.Date('2021-12-31'))) %>%
  # mutate(manipulation_type = fct_lump_prop(manipulation_type, prop = .001)) %>% 
  # mutate(manipulation_type = replace_na(manipulation_type, "Other")) %>% 
  filter(!is.na(manipulation_type)) %>% 
  group_by(manipulation_type, periods) %>% 
  count() %>% 
  ggplot(aes(x = as.factor(periods), 
             y = n, 
             color = manipulation_type, 
             group = manipulation_type)) +
  geom_line() +
  scale_y_log10(labels = scales::label_number(scale_cut = scales::cut_short_scale())) +
  labs(title = "Manipulations per year (first semester)", 
       x = "Year", 
       y = "N (x1000)", 
       color = "Manipulation")

How many specialties per year

Filter according to https://docs.google.com/document/d/17c5QXkbnCI9aEFDIblwdOLP-zfS5e9NFxVn5TjOTXEE/edit#heading=h.nmf14n

Codes Explication
P25 General dentist
P26 Maxillofacial surgeon
P32 radiologist
A253 Paediatric dentist
A251 orthodontist
n11 Dental hygienist
df_filtered %>% 
  filter(spec_kods %in% c("P25", "P26", "P32", "A253", "A251", "n11")) %>% 
  group_by(periods, spec_kods) %>% 
  count() %>% 
  pivot_wider(names_from = periods, 
              values_from = n) %>% 
  knitr::kable()
spec_kods 2019 2020 2021
n11 264889 465554 507680
P26 534 59 NA
P32 1 NA NA

Manipulation per date

Check the dates

df_filtered %>%
  # remove first semester 2020
  filter(!between(ep_beig_dat, as.Date('2020-06-30'), as.Date('2020-12-31'))) %>%
  # remove first semester 2021
  filter(!between(ep_beig_dat, as.Date('2021-06-30'), as.Date('2021-12-31'))) %>%
  # group_by(year, month, day, day_week) %>%
  # count() %>%
  group_by(month = lubridate::floor_date(ep_beig_dat, unit = "month")) %>%
  count() %>%
  mutate(month = lubridate::ymd(month)) %>%
  
  ggplot(aes(x = month,
             y = n,
             group = 1)) +
  geom_point() +
  geom_line() +
  scale_y_log10(labels = scales::label_number(scale_cut = scales::cut_short_scale())) +
  scale_x_date(NULL, date_labels = "%b %y", breaks = "month", 
               ) +
  # scale_x_date(limits = as.Date(c("2019-01-01", "2021-12-31"))) +
  theme(axis.text.x  = element_text(size = 8, angle = 45, colour = "black",
      vjust = 1, hjust = 1)) + 
  labs(title = "Manipulations per day, 2019-2021",
       y = "Manipulations (log 10)",
       x = "Date")

ggsave(here("Figs2019_2021", "fig1.tif"), width = 6, height = 4, device='tiff', dpi=300)

Manipulations

df_filtered %>%
  select(ep_beig_dat, manipulation_type, periods) %>% 
  # remove first semester 2020
  filter(!between(ep_beig_dat, as.Date('2020-06-30'), as.Date('2020-12-31'))) %>% 
  # remove first semester 2021
 filter(!between(ep_beig_dat, as.Date('2021-06-30'), as.Date('2021-12-31'))) %>% 
  # count
  group_by(manipulation_type, periods) %>% 
  count() %>%
  mutate(error_estimate = sqrt(n)) %>% 
  # create the graph
  ggplot(aes(
    x = as.factor(periods), 
    y = n, 
    fill = manipulation_type
    )) +
   geom_col(position="dodge") + # the position="dodge" allow to have the bars by side
  # scale_fill_manual(values = c("#C2C1C1", "#89272F")) +
  scale_fill_viridis_d() +
  # scale_fill_manual(values = c("grey90", "grey60", "grey30", "grey10")) +
  # scale_y_log10(labels = scales::label_number()) +
    labs(
      # title = "Total of manipulations during the first semester", 
      x = "Year (First Semester)", 
      y = "Manipulations", 
      fill = ""
    )  +
  theme(legend.position="top") + 
  geom_errorbar(
    aes(
      ymin = n - error_estimate * 4,
      ymax = n + error_estimate * 4
    ),
    width = .2,
    position = position_dodge(.9)
  ) 

ggsave(here("Figs2019_2021", "fig2.tif"), width = 7, height = 4, device='tiff', dpi=300)

Manipulations per day

df_filtered %>%
  mutate(ep_beig_dat = lubridate::ymd(ep_beig_dat)) %>%
  group_by(ep_beig_dat, manipulation_type) %>% # add kodes_grouped to see the kodes
  count() %>%
  # so far, here are the manipulations per day
  # count() %>%   # here is the number of manipulacijas per day
  # add the name of the day
  mutate(day = lubridate::wday(
    lubridate::ymd(ep_beig_dat),
    label = TRUE,
    abbr = TRUE
  )) %>%
  ggplot(aes(x = ep_beig_dat,
             y = n,
             color = day)) +
  geom_point() +
  labs(
    title = "Manipulations per day of the week",
    y = "Manipulations (n)",
    x = "Date",
    color = "Day of the week"
  ) +
  scale_fill_viridis_b() +
  theme(legend.position="top")

ggsave(here("Figs2019_2021", "fig3.tif"), width = 7, height = 4, device='tiff', dpi=300)

Manipulations per type

df_filtered %>%
  mutate(ep_beig_dat = lubridate::ymd(ep_beig_dat)) %>%
  group_by(ep_beig_dat, manipulation_type) %>% # add kodes_grouped to see the kodes
  count() %>%
  # so far, here are the manipulations per day
  # count() %>%   # here is the number of manipulacijas per day
  # add the name of the day
  mutate(day = lubridate::wday(
    lubridate::ymd(ep_beig_dat),
    label = TRUE,
    abbr = TRUE
  )) %>%
  ggplot(aes(x = ep_beig_dat,
             y = n,
             color = day)) +
  geom_point() +
  labs(
    title = "Manipulations per day of the week",
    y = "Manipulations n",
    x = "Date",
    color = "Day of the week"
  ) +
  # scale_y_log10() + 
  scale_fill_viridis_b() + 
  facet_grid(manipulation_type ~ . ) + 
  theme(legend.position = "top") +
  theme(strip.text.y = element_text(size = 8))

ggsave(here("Figs2019_2021", "fig4.tif"), width = 8, height = 6, device='tiff', dpi=300)
LS0tCnRpdGxlOiAiQ09WSUQgTGF0dmlhIDIwMTkgdGlsIDIwMjAiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazogCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCi0tLQoKYGBge3J9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZz1GQUxTRSkKYGBgCgpUaGlzIGlzIHRoZSBmaW5hbCBhbmFseXNpcy4gQWxsIHRoZSBkYXRhc2V0cyBoYXZlIGJlZW4gcHJlLXByb2Nlc3NpbmcgaW50byB0aGUgZGZfZmlsdGVyZWQucmRzIGZpbGUKCiMgUGFja2FnZXMKCmBgYHtyfQpwYWNtYW46OnBfbG9hZCh0aWR5dmVyc2UsICMgZGF0YSBzY2llbmNlIHRvb2xzCiAgICAgICAgICAgICAgIGphbml0b3IsICMgZGF0YSBjbGVhbmluZyBhbmQgdGFieWwKICAgICAgICAgICAgICAgc2YsICAjIGZvciBtYXBzCiAgICAgICAgICAgICAgIGd0c3VtbWFyeSwgICMgZm9yIHRhYmxlcyBhbmQgcmVncmVzc2lvbiBzdW1tYXJ5CiAgICAgICAgICAgICAgIGdncHViciwgIyBmb3IgZ2dwbG90IHRoZW1lcwogICAgICAgICAgICAgICBzY2FsZXMsICMgZm9yIGdncGxvdCBzY2FsZXMKICAgICAgICAgICAgICAgaGVyZSkgIyBmaWxlcyBwYXRocwpgYGAKCmBgYHtyfQp0aGVtZV9zZXQodGhlbWVfbWluaW1hbCgpKQpgYGAKCiMgMi4gU1RBUlQgRlJPTSBIRVJFIExvYWQgdGhlIFJEUyBmaWxlCgpgYGB7cn0KIyBkZiA8LSByZWFkUkRTKGhlcmUoImRhdGFzZXRzIiwgImRmLnJkcyIpKQojIHRlc3Qgd2l0aCBuZXcgZGF0YXNldAojIGRmIDwtIHJlYWRSRFMoaGVyZSgiZGF0YXNldHMiLCAiZGZfd2l0aF9hbGxfMjAyMS5yZHMiKSkKZGZfZmlsdGVyZWQgPC0gcmVhZFJEUyhoZXJlKCJkYXRhc2V0cyIsICJkZl9maWx0ZXJlZC5yZHMiKSkKCmBgYAoKIyMgRmlsdGVyIGRhdGVzIHRvIGF2b2lkIGRhdGVzIGZyb20gdGhlIHNlY29uZCBzZW1lc3RlciAyMDE5CgpgYGB7cn0KZGZfZmlsdGVyZWQgPC0gZGZfZmlsdGVyZWQgJT4lCiAgZmlsdGVyKGVwX2JlaWdfZGF0ID4gIjIwMTgtMTItMzEiKSAlPiUgCiAgZmlsdGVyKCFiZXR3ZWVuKGVwX2JlaWdfZGF0LCBhcy5EYXRlKCcyMDE5LTA2LTMwJyksIGFzLkRhdGUoJzIwMTktMTItMzEnKSkpCgpgYGAKCiMjIyMgQ29kaWZpY2F0aW9uCgojIEVEQQoKSG95IG1hbnkgcGF0aWVudHM/CgpgYGB7cn0Kbl9kaXN0aW5jdChkZl9maWx0ZXJlZCRwaWQpICU+JSAKICBrbml0cjo6a2FibGUoKQpgYGAKCkhvdyBtYW55IGludGVydmVudGlvbnM/CgpgYGB7cn0KCmRmX2ZpbHRlcmVkICU+JQogIHNlbGVjdChlcF9iZWlnX2RhdCwgbWFuaXB1bGF0aW9uX3R5cGUsIHBlcmlvZHMpICU+JQogICMgcmVtb3ZlIGZpcnN0IHNlbWVzdGVyIDIwMjAKICBmaWx0ZXIoIWJldHdlZW4oZXBfYmVpZ19kYXQsIGFzLkRhdGUoJzIwMjAtMDYtMzAnKSwgYXMuRGF0ZSgnMjAyMC0xMi0zMScpKSkgJT4lCiAgIyByZW1vdmUgZmlyc3Qgc2VtZXN0ZXIgMjAyMQogIGZpbHRlcighYmV0d2VlbihlcF9iZWlnX2RhdCwgYXMuRGF0ZSgnMjAyMS0wNi0zMCcpLCBhcy5EYXRlKCcyMDIxLTEyLTMxJykpKSAlPiUKICAjIGNvdW50CiAgc2VsZWN0KC1lcF9iZWlnX2RhdCkgJT4lCiAgbXV0YXRlKG1hbmlwdWxhdGlvbl90eXBlID0gZmN0X2Ryb3AobWFuaXB1bGF0aW9uX3R5cGUpKSAlPiUKICBncm91cF9ieShtYW5pcHVsYXRpb25fdHlwZSwgcGVyaW9kcykgJT4lCiAgY291bnQoKSAlPiUKICBwaXZvdF93aWRlcigKICAgIG5hbWVzX2Zyb20gPSBwZXJpb2RzLAogICAgLAogICAgbmFtZXNfcHJlZml4ID0gInkiLAogICAgdmFsdWVzX2Zyb20gPSBuCiAgKSAlPiUKICBtdXRhdGUoIlZhcmlhdGlvbiAyMDIwIiA9ICh5MjAyMCAtIHkyMDE5KSAvIHkyMDE5ICogMTAwKSAlPiUgCiAgbXV0YXRlKCJWYXJpYXRpb24gMjAyMSIgPSAoeTIwMjEgLSB5MjAxOSkgLyB5MjAxOSAqIDEwMCkgJT4lIAogIGtuaXRyOjprYWJsZSgpCgpgYGAKCmBgYHtyfQpkZl9maWx0ZXJlZCAlPiUKICBzZWxlY3QoZXBfYmVpZ19kYXQsIG1hbmlwdWxhdGlvbl90eXBlLCBwZXJpb2RzKSAlPiUKICAjIHJlbW92ZSBmaXJzdCBzZW1lc3RlciAyMDIwCiAgZmlsdGVyKCFiZXR3ZWVuKGVwX2JlaWdfZGF0LCBhcy5EYXRlKCcyMDIwLTA2LTMwJyksIGFzLkRhdGUoJzIwMjAtMTItMzEnKSkpICU+JQogICMgcmVtb3ZlIGZpcnN0IHNlbWVzdGVyIDIwMjEKICBmaWx0ZXIoIWJldHdlZW4oZXBfYmVpZ19kYXQsIGFzLkRhdGUoJzIwMjEtMDYtMzAnKSwgYXMuRGF0ZSgnMjAyMS0xMi0zMScpKSkgJT4lCiAgIyBjb3VudAogIHNlbGVjdCgtZXBfYmVpZ19kYXQpICU+JQogIG11dGF0ZShtYW5pcHVsYXRpb25fdHlwZSA9IGZjdF9kcm9wKG1hbmlwdWxhdGlvbl90eXBlKSkgJT4lCiAgZ3JvdXBfYnkobWFuaXB1bGF0aW9uX3R5cGUsIHBlcmlvZHMpICU+JQogIGNvdW50KCkgJT4lCiAgcGl2b3Rfd2lkZXIoCiAgICBuYW1lc19mcm9tID0gcGVyaW9kcywKICAgICwKICAgIG5hbWVzX3ByZWZpeCA9ICJ5IiwKICAgIHZhbHVlc19mcm9tID0gbgogICkgJT4lCiAgbXV0YXRlKCJWYXJpYXRpb25fMjAyMCIgPSAoeTIwMjAgLSB5MjAxOSkgLyB5MjAxOSAqIDEwMCkgJT4lIAogIG11dGF0ZSgiVmFyaWF0aW9uXzIwMjEiID0gKHkyMDIxIC0geTIwMTkpIC8geTIwMTkgKiAxMDApICU+JSAKICBzZWxlY3QobWFuaXB1bGF0aW9uX3R5cGUsIFZhcmlhdGlvbl8yMDIwLCBWYXJpYXRpb25fMjAyMSApICU+JSAKICBwaXZvdF9sb25nZXIoVmFyaWF0aW9uXzIwMjA6VmFyaWF0aW9uXzIwMjEsIAogICAgICAgICAgICAgICBuYW1lc190byA9ICJQZXJpb2QiLCAKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIm4iKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gUGVyaW9kLCAKICAgICAgICAgICAgIHkgPSBuLCAKICAgICAgICAgICAgIGZpbGwgPSBtYW5pcHVsYXRpb25fdHlwZSkpICsgCiAgIGdlb21fY29sKHBvc2l0aW9uPSJkb2RnZSIpICsgIyB0aGUgcG9zaXRpb249ImRvZGdlIiBhbGxvdyB0byBoYXZlIHRoZSBiYXJzIGJ5IHNpZGUKICAjIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNDMkMxQzEiLCAiIzg5MjcyRiIpKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSAgKyAKICBsYWJzKHRpdGxlID0gIkNvbXBhcmlzb24gdG8gMjAxOSIsIAogICAgICAgZmlsbCA9ICJNYW5pcHVsYXRpb25zIiwgCiAgICAgICB5ID0gIlBlcmNlbnRhZ2UgQ2hhbmdlIikrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpCiAgCmBgYAoKYGBge3J9CmRmX2ZpbHRlcmVkICU+JSAKICAgICMgcmVtb3ZlIGZpcnN0IHNlbWVzdGVyIDIwMjAKICBmaWx0ZXIoIWJldHdlZW4oZXBfYmVpZ19kYXQsIGFzLkRhdGUoJzIwMjAtMDYtMzAnKSwgYXMuRGF0ZSgnMjAyMC0xMi0zMScpKSkgJT4lCiAgIyByZW1vdmUgZmlyc3Qgc2VtZXN0ZXIgMjAyMQogIGZpbHRlcighYmV0d2VlbihlcF9iZWlnX2RhdCwgYXMuRGF0ZSgnMjAyMS0wNi0zMCcpLCBhcy5EYXRlKCcyMDIxLTEyLTMxJykpKSAlPiUKICAjIG11dGF0ZShtYW5pcHVsYXRpb25fdHlwZSA9IGZjdF9sdW1wX3Byb3AobWFuaXB1bGF0aW9uX3R5cGUsIHByb3AgPSAuMDAxKSkgJT4lIAogICMgbXV0YXRlKG1hbmlwdWxhdGlvbl90eXBlID0gcmVwbGFjZV9uYShtYW5pcHVsYXRpb25fdHlwZSwgIk90aGVyIikpICU+JSAKICBmaWx0ZXIoIWlzLm5hKG1hbmlwdWxhdGlvbl90eXBlKSkgJT4lIAogIGdyb3VwX2J5KG1hbmlwdWxhdGlvbl90eXBlLCBwZXJpb2RzKSAlPiUgCiAgY291bnQoKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gYXMuZmFjdG9yKHBlcmlvZHMpLCAKICAgICAgICAgICAgIHkgPSBuLCAKICAgICAgICAgICAgIGNvbG9yID0gbWFuaXB1bGF0aW9uX3R5cGUsIAogICAgICAgICAgICAgZ3JvdXAgPSBtYW5pcHVsYXRpb25fdHlwZSkpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfeV9sb2cxMChsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX251bWJlcihzY2FsZV9jdXQgPSBzY2FsZXM6OmN1dF9zaG9ydF9zY2FsZSgpKSkgKwogIGxhYnModGl0bGUgPSAiTWFuaXB1bGF0aW9ucyBwZXIgeWVhciAoZmlyc3Qgc2VtZXN0ZXIpIiwgCiAgICAgICB4ID0gIlllYXIiLCAKICAgICAgIHkgPSAiTiAoeDEwMDApIiwgCiAgICAgICBjb2xvciA9ICJNYW5pcHVsYXRpb24iKQpgYGAKCkhvdyBtYW55IHNwZWNpYWx0aWVzIHBlciB5ZWFyCgpGaWx0ZXIgYWNjb3JkaW5nIHRvIDxodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9kb2N1bWVudC9kLzE3YzVRWGtibkNJOWFFRkRJYmx3ZE9MUC16ZlM1ZTlORnhWbjVUak9UWEVFL2VkaXQjaGVhZGluZz1oLm5tZjE0bj4KCnwgQ29kZXMgfCBFeHBsaWNhdGlvbiAgICAgICAgICAgfAp8LS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwKfCBQMjUgICB8IEdlbmVyYWwgZGVudGlzdCAgICAgICB8CnwgUDI2ICAgfCBNYXhpbGxvZmFjaWFsIHN1cmdlb24gfAp8ICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgIHwKfCBQMzIgICB8IHJhZGlvbG9naXN0ICAgICAgICAgICB8CnwgQTI1MyAgfCBQYWVkaWF0cmljIGRlbnRpc3QgICAgfAp8IEEyNTEgIHwgb3J0aG9kb250aXN0ICAgICAgICAgIHwKfCBuMTEgICB8IERlbnRhbCBoeWdpZW5pc3QgICAgICB8CgpgYGB7cn0KZGZfZmlsdGVyZWQgJT4lIAogIGZpbHRlcihzcGVjX2tvZHMgJWluJSBjKCJQMjUiLCAiUDI2IiwgIlAzMiIsICJBMjUzIiwgIkEyNTEiLCAibjExIikpICU+JSAKICBncm91cF9ieShwZXJpb2RzLCBzcGVjX2tvZHMpICU+JSAKICBjb3VudCgpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcGVyaW9kcywgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBuKSAlPiUgCiAga25pdHI6OmthYmxlKCkKYGBgCgojIyBNYW5pcHVsYXRpb24gcGVyIGRhdGUKCkNoZWNrIHRoZSBkYXRlcwoKYGBge3J9CmRmX2ZpbHRlcmVkICU+JQogICMgcmVtb3ZlIGZpcnN0IHNlbWVzdGVyIDIwMjAKICBmaWx0ZXIoIWJldHdlZW4oZXBfYmVpZ19kYXQsIGFzLkRhdGUoJzIwMjAtMDYtMzAnKSwgYXMuRGF0ZSgnMjAyMC0xMi0zMScpKSkgJT4lCiAgIyByZW1vdmUgZmlyc3Qgc2VtZXN0ZXIgMjAyMQogIGZpbHRlcighYmV0d2VlbihlcF9iZWlnX2RhdCwgYXMuRGF0ZSgnMjAyMS0wNi0zMCcpLCBhcy5EYXRlKCcyMDIxLTEyLTMxJykpKSAlPiUKICAjIGdyb3VwX2J5KHllYXIsIG1vbnRoLCBkYXksIGRheV93ZWVrKSAlPiUKICAjIGNvdW50KCkgJT4lCiAgZ3JvdXBfYnkobW9udGggPSBsdWJyaWRhdGU6OmZsb29yX2RhdGUoZXBfYmVpZ19kYXQsIHVuaXQgPSAibW9udGgiKSkgJT4lCiAgY291bnQoKSAlPiUKICBtdXRhdGUobW9udGggPSBsdWJyaWRhdGU6OnltZChtb250aCkpICU+JQogIAogIGdncGxvdChhZXMoeCA9IG1vbnRoLAogICAgICAgICAgICAgeSA9IG4sCiAgICAgICAgICAgICBncm91cCA9IDEpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfeV9sb2cxMChsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX251bWJlcihzY2FsZV9jdXQgPSBzY2FsZXM6OmN1dF9zaG9ydF9zY2FsZSgpKSkgKwogIHNjYWxlX3hfZGF0ZShOVUxMLCBkYXRlX2xhYmVscyA9ICIlYiAleSIsIGJyZWFrcyA9ICJtb250aCIsIAogICAgICAgICAgICAgICApICsKICAjIHNjYWxlX3hfZGF0ZShsaW1pdHMgPSBhcy5EYXRlKGMoIjIwMTktMDEtMDEiLCAiMjAyMS0xMi0zMSIpKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ICA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgYW5nbGUgPSA0NSwgY29sb3VyID0gImJsYWNrIiwKICAgICAgdmp1c3QgPSAxLCBoanVzdCA9IDEpKSArIAogIGxhYnModGl0bGUgPSAiTWFuaXB1bGF0aW9ucyBwZXIgZGF5LCAyMDE5LTIwMjEiLAogICAgICAgeSA9ICJNYW5pcHVsYXRpb25zIChsb2cgMTApIiwKICAgICAgIHggPSAiRGF0ZSIpCmBgYAoKYGBge3J9Cmdnc2F2ZShoZXJlKCJGaWdzMjAxOV8yMDIxIiwgImZpZzEudGlmIiksIHdpZHRoID0gNiwgaGVpZ2h0ID0gNCwgZGV2aWNlPSd0aWZmJywgZHBpPTMwMCkKYGBgCgojIyBNYW5pcHVsYXRpb25zCgpgYGB7cn0KZGZfZmlsdGVyZWQgJT4lCiAgc2VsZWN0KGVwX2JlaWdfZGF0LCBtYW5pcHVsYXRpb25fdHlwZSwgcGVyaW9kcykgJT4lIAogICMgcmVtb3ZlIGZpcnN0IHNlbWVzdGVyIDIwMjAKICBmaWx0ZXIoIWJldHdlZW4oZXBfYmVpZ19kYXQsIGFzLkRhdGUoJzIwMjAtMDYtMzAnKSwgYXMuRGF0ZSgnMjAyMC0xMi0zMScpKSkgJT4lIAogICMgcmVtb3ZlIGZpcnN0IHNlbWVzdGVyIDIwMjEKIGZpbHRlcighYmV0d2VlbihlcF9iZWlnX2RhdCwgYXMuRGF0ZSgnMjAyMS0wNi0zMCcpLCBhcy5EYXRlKCcyMDIxLTEyLTMxJykpKSAlPiUgCiAgIyBjb3VudAogIGdyb3VwX2J5KG1hbmlwdWxhdGlvbl90eXBlLCBwZXJpb2RzKSAlPiUgCiAgY291bnQoKSAlPiUKICBtdXRhdGUoZXJyb3JfZXN0aW1hdGUgPSBzcXJ0KG4pKSAlPiUgCiAgIyBjcmVhdGUgdGhlIGdyYXBoCiAgZ2dwbG90KGFlcygKICAgIHggPSBhcy5mYWN0b3IocGVyaW9kcyksIAogICAgeSA9IG4sIAogICAgZmlsbCA9IG1hbmlwdWxhdGlvbl90eXBlCiAgICApKSArCiAgIGdlb21fY29sKHBvc2l0aW9uPSJkb2RnZSIpICsgIyB0aGUgcG9zaXRpb249ImRvZGdlIiBhbGxvdyB0byBoYXZlIHRoZSBiYXJzIGJ5IHNpZGUKICAjIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNDMkMxQzEiLCAiIzg5MjcyRiIpKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSArCiAgIyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJncmV5OTAiLCAiZ3JleTYwIiwgImdyZXkzMCIsICJncmV5MTAiKSkgKwogICMgc2NhbGVfeV9sb2cxMChsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX251bWJlcigpKSArCiAgICBsYWJzKAogICAgICAjIHRpdGxlID0gIlRvdGFsIG9mIG1hbmlwdWxhdGlvbnMgZHVyaW5nIHRoZSBmaXJzdCBzZW1lc3RlciIsIAogICAgICB4ID0gIlllYXIgKEZpcnN0IFNlbWVzdGVyKSIsIAogICAgICB5ID0gIk1hbmlwdWxhdGlvbnMiLCAKICAgICAgZmlsbCA9ICIiCiAgICApICArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJ0b3AiKSArIAogIGdlb21fZXJyb3JiYXIoCiAgICBhZXMoCiAgICAgIHltaW4gPSBuIC0gZXJyb3JfZXN0aW1hdGUgKiA0LAogICAgICB5bWF4ID0gbiArIGVycm9yX2VzdGltYXRlICogNAogICAgKSwKICAgIHdpZHRoID0gLjIsCiAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKC45KQogICkgCmBgYAoKYGBge3J9Cmdnc2F2ZShoZXJlKCJGaWdzMjAxOV8yMDIxIiwgImZpZzIudGlmIiksIHdpZHRoID0gNywgaGVpZ2h0ID0gNCwgZGV2aWNlPSd0aWZmJywgZHBpPTMwMCkKYGBgCgojIyBNYW5pcHVsYXRpb25zIHBlciBkYXkKCmBgYHtyfQpkZl9maWx0ZXJlZCAlPiUKICBtdXRhdGUoZXBfYmVpZ19kYXQgPSBsdWJyaWRhdGU6OnltZChlcF9iZWlnX2RhdCkpICU+JQogIGdyb3VwX2J5KGVwX2JlaWdfZGF0LCBtYW5pcHVsYXRpb25fdHlwZSkgJT4lICMgYWRkIGtvZGVzX2dyb3VwZWQgdG8gc2VlIHRoZSBrb2RlcwogIGNvdW50KCkgJT4lCiAgIyBzbyBmYXIsIGhlcmUgYXJlIHRoZSBtYW5pcHVsYXRpb25zIHBlciBkYXkKICAjIGNvdW50KCkgJT4lICAgIyBoZXJlIGlzIHRoZSBudW1iZXIgb2YgbWFuaXB1bGFjaWphcyBwZXIgZGF5CiAgIyBhZGQgdGhlIG5hbWUgb2YgdGhlIGRheQogIG11dGF0ZShkYXkgPSBsdWJyaWRhdGU6OndkYXkoCiAgICBsdWJyaWRhdGU6OnltZChlcF9iZWlnX2RhdCksCiAgICBsYWJlbCA9IFRSVUUsCiAgICBhYmJyID0gVFJVRQogICkpICU+JQogIGdncGxvdChhZXMoeCA9IGVwX2JlaWdfZGF0LAogICAgICAgICAgICAgeSA9IG4sCiAgICAgICAgICAgICBjb2xvciA9IGRheSkpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJNYW5pcHVsYXRpb25zIHBlciBkYXkgb2YgdGhlIHdlZWsiLAogICAgeSA9ICJNYW5pcHVsYXRpb25zIChuKSIsCiAgICB4ID0gIkRhdGUiLAogICAgY29sb3IgPSAiRGF5IG9mIHRoZSB3ZWVrIgogICkgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19iKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIikKYGBgCgpgYGB7cn0KZ2dzYXZlKGhlcmUoIkZpZ3MyMDE5XzIwMjEiLCAiZmlnMy50aWYiKSwgd2lkdGggPSA3LCBoZWlnaHQgPSA0LCBkZXZpY2U9J3RpZmYnLCBkcGk9MzAwKQpgYGAKCiMjIE1hbmlwdWxhdGlvbnMgcGVyIHR5cGUKCmBgYHtyfQpkZl9maWx0ZXJlZCAlPiUKICBtdXRhdGUoZXBfYmVpZ19kYXQgPSBsdWJyaWRhdGU6OnltZChlcF9iZWlnX2RhdCkpICU+JQogIGdyb3VwX2J5KGVwX2JlaWdfZGF0LCBtYW5pcHVsYXRpb25fdHlwZSkgJT4lICMgYWRkIGtvZGVzX2dyb3VwZWQgdG8gc2VlIHRoZSBrb2RlcwogIGNvdW50KCkgJT4lCiAgIyBzbyBmYXIsIGhlcmUgYXJlIHRoZSBtYW5pcHVsYXRpb25zIHBlciBkYXkKICAjIGNvdW50KCkgJT4lICAgIyBoZXJlIGlzIHRoZSBudW1iZXIgb2YgbWFuaXB1bGFjaWphcyBwZXIgZGF5CiAgIyBhZGQgdGhlIG5hbWUgb2YgdGhlIGRheQogIG11dGF0ZShkYXkgPSBsdWJyaWRhdGU6OndkYXkoCiAgICBsdWJyaWRhdGU6OnltZChlcF9iZWlnX2RhdCksCiAgICBsYWJlbCA9IFRSVUUsCiAgICBhYmJyID0gVFJVRQogICkpICU+JQogIGdncGxvdChhZXMoeCA9IGVwX2JlaWdfZGF0LAogICAgICAgICAgICAgeSA9IG4sCiAgICAgICAgICAgICBjb2xvciA9IGRheSkpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJNYW5pcHVsYXRpb25zIHBlciBkYXkgb2YgdGhlIHdlZWsiLAogICAgeSA9ICJNYW5pcHVsYXRpb25zIG4iLAogICAgeCA9ICJEYXRlIiwKICAgIGNvbG9yID0gIkRheSBvZiB0aGUgd2VlayIKICApICsKICAjIHNjYWxlX3lfbG9nMTAoKSArIAogIHNjYWxlX2ZpbGxfdmlyaWRpc19iKCkgKyAKICBmYWNldF9ncmlkKG1hbmlwdWxhdGlvbl90eXBlIH4gLiApICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsKICB0aGVtZShzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKQpgYGAKCmBgYHtyfQpnZ3NhdmUoaGVyZSgiRmlnczIwMTlfMjAyMSIsICJmaWc0LnRpZiIpLCB3aWR0aCA9IDgsIGhlaWdodCA9IDYsIGRldmljZT0ndGlmZicsIGRwaT0zMDApCmBgYAo=