library(tidyverse)
library(stringr)
states <- map_data("state")

Attaching package: ‘maps’

The following object is masked from ‘package:purrr’:

    map

Create percent a and b

states<-as.tibble(states) %>%
  mutate(state=region) %>%
  #group_by(state) %>% 
  mutate(percent_a = sample(1:15537)) %>% 
  mutate(percent_a = (percent_a/15537) * 100)
`as.tibble()` is deprecated, use `as_tibble()` (but mind the new semantics).
This warning is displayed once per session.
#dat<-states

Round percent_a

states<-states %>% 
  mutate(percent_a = round(percent_a, 2))

Create percent_b

states<-states %>% 
  mutate(percent_b = 100-round(percent_a, 2))

Map percentages

states %>% 
  ggplot() +
  geom_polygon(aes(x = long, y = lat, fill = percent_a, group = group), color = "white") + 
  coord_fixed(1.3) +
  guides(fill=FALSE) +
  theme_bw()# do this to leave off the color legend

Map binary outcomes variable + map

states %>% 
  mutate(winner = ifelse(percent_a > percent_b, "a", "b")) %>% 
  ggplot() +
  geom_polygon(aes(x = long, y = lat, fill = winner, group = group), color = "white") + 
  coord_fixed(1.3) +
  guides(fill=FALSE) +
  theme_bw()# do this to leave off the color legend

Now make a function to create the variables we want

create_map_vars<-function(x){x %>%
                  as.tibble(.) %>%
  mutate(state=region) %>%
  mutate(percent_a = sample(1:15537)) %>% #this creates the percentage for each row
  mutate(percent_a = (percent_a/15537) * 100)  %>% 
    mutate(percent_a=round(percent_a, 2)) %>% 
  mutate(percent_b = 100-(percent_a)) %>% 
  mutate(winner = ifelse(percent_a > percent_b, "a", "b")) %>% 
    mutate(margin_a = percent_a - percent_b)
  }

Apply this function to the data and Save it as ‘dat’

dat<-create_map_vars(map_data("state"))

Map binary winner outcome

  dat %>% 
  ggplot() +
  geom_polygon(aes(x = long, y = lat, fill = winner, group = group), color = "white") + 
  coord_fixed(1.3) +
  guides(fill=FALSE) +
  theme_bw()# do this to leave off the color legend

Make function to plot percentage

plot_percent<-function(x){x %>% 
  ggplot() +
  geom_polygon(aes(x = long, y = lat, fill = margin_a, group = group), color = "white") + #x = longitude 
  coord_fixed(1.3) +
  theme_bw()+
    scale_fill_gradient2(low="red", high="blue")+
    theme(legend.position = "false")}

This is basically a “random” result of a US federal election

plot_percent(dat)


With real data


Thankfully, a lot of people have taken the time to carefully document election results and make that data available to the public

Here I am importing data from the MIT xxxx project (website)

pres_dat<-read_csv("1976-2016-president.csv")

Create 2008 Winners dat

map_2008_dat<-pres_dat %>% select(year, state,candidate, party, state_votes=candidatevotes) %>% 
  filter(year==2008) %>% 
  unique() %>% 
  na.omit() %>% 
  group_by(state) %>% 
  mutate(state_total=sum(state_votes)) %>% 
  mutate(percent = round((state_votes / state_total) * 100, 2)) %>% 
  mutate(winner=ifelse(percent == max(percent), 1, 0)) %>% 
  filter(winner==1) %>% select(-winner)

Create 2012 Winners dat

map_2012_dat<-pres_dat %>% select(year, state,candidate, party, state_votes=candidatevotes) %>% 
  filter(year==2012) %>% 
  unique() %>% 
  na.omit() %>% 
  group_by(state) %>% 
  mutate(state_total=sum(state_votes)) %>% 
  mutate(percent = round((state_votes / state_total) * 100, 2)) %>% 
  mutate(winner=ifelse(percent == max(percent), 1, 0)) %>% 
  filter(winner==1) %>% select(-winner)

Create 2016 Winners dat

map_2016_dat<-pres_dat %>% select(year, state,candidate, party, state_votes=candidatevotes) %>% 
  filter(year==2016) %>% 
  unique() %>% 
  na.omit() %>% 
  group_by(state) %>% 
  mutate(state_total=sum(state_votes)) %>% 
  mutate(percent = round((state_votes / state_total) * 100, 2)) %>% 
  mutate(winner=ifelse(percent == max(percent), 1, 0)) %>% 
  filter(winner==1) %>% select(-winner)
winners_2008_dat<-map_2008_dat %>% arrange(year, state) %>% ungroup() %>%  mutate(state=tolower(state))
winners_2012_dat<-map_2012_dat %>% arrange(year, state) %>% ungroup() %>%  mutate(state=tolower(state))
winners_2016_dat<-map_2016_dat %>% arrange(year, state) %>% ungroup() %>%  mutate(state=tolower(state))

map_dat_2008<-merge(dat, winners_2008_dat, by="state")
map_dat_2012<-merge(dat, winners_2012_dat, by="state")
map_dat_2016<-merge(dat, winners_2016_dat, by="state")

For some reason, 2012 isn’t working correctly;

Fix 2012

map_dat_2012<-map_dat_2012 %>% mutate(party=ifelse(party=="democratic-farmer-labor", "democrat", party))

Make function to plot percentage

plot_percent<-function(x){x %>% 
  ggplot() +
  geom_polygon(aes(x = long, y = lat, fill = factor(party), group = group), color="white", alpha=0.75) + 
  coord_fixed(1.3) +
  theme_void()+
  scale_fill_manual(values=c("blue", "red"))+
  theme(legend.position = "false")}

Here we can plot each election seperately

plot_percent(map_dat_2008) + 
  ggtitle(2008) +
  theme(plot.title = element_text(size = 28, face = "bold", hjust=0.5))

#
plot_percent(map_dat_2012)+ 
  ggtitle(2012) +
  theme(plot.title = element_text(size = 28, face = "bold", hjust=0.5))

#
plot_percent(map_dat_2016)+ 
  ggtitle(2016) +
  theme(plot.title = element_text(size = 28, face = "bold", hjust=0.5))

n

dat_2008_2016<-bind_rows(map_dat_2008, map_dat_2012, map_dat_2016)

plot_percent(dat_2008_2016)+ 
  ggtitle("Presidential Elections: 2008 - 2016") +
  theme(plot.title = element_text(size = 28, face = "bold", hjust=0.5))+
  facet_wrap(~year, nrow = 3)+
  theme(strip.text.x = element_text(size = 20, colour = "black", face="bold"))


dat_2008_2016 %>% 
  arrange(percent) %>% 
  select(year, state, candidate, percent) %>%
  unique()

Look at margins

dat_2008_2016 %>% 
  filter(percent<90) %>% #This excludes DC (sorry, DC)
  arrange(percent) %>% 
  select(year, state, candidate, percent) %>%
  unique() %>% 
  ggplot(aes(x=year, y=percent))+
  geom_hline(yintercept = 50, alpha=0.2)+
  geom_jitter(size=3, alpha=0.5)+
  theme_bw()

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc3RyaW5ncikKYGBgCgpgYGB7cn0Kc3RhdGVzIDwtIG1hcF9kYXRhKCJzdGF0ZSIpCmBgYAoKQ3JlYXRlIHBlcmNlbnQgYSBhbmQgYgpgYGB7cn0Kc3RhdGVzPC1hcy50aWJibGUoc3RhdGVzKSAlPiUKICBtdXRhdGUoc3RhdGU9cmVnaW9uKSAlPiUKICAjZ3JvdXBfYnkoc3RhdGUpICU+JSAKICBtdXRhdGUocGVyY2VudF9hID0gc2FtcGxlKDE6MTU1MzcpKSAlPiUgCiAgbXV0YXRlKHBlcmNlbnRfYSA9IChwZXJjZW50X2EvMTU1MzcpICogMTAwKQoKYGBgCgpgYGB7cn0KI2RhdDwtc3RhdGVzCmBgYAoKKioqCgpSb3VuZCBwZXJjZW50X2EKYGBge3J9CnN0YXRlczwtc3RhdGVzICU+JSAKICBtdXRhdGUocGVyY2VudF9hID0gcm91bmQocGVyY2VudF9hLCAyKSkKYGBgCgpDcmVhdGUgcGVyY2VudF9iCmBgYHtyfQpzdGF0ZXM8LXN0YXRlcyAlPiUgCiAgbXV0YXRlKHBlcmNlbnRfYiA9IDEwMC1yb3VuZChwZXJjZW50X2EsIDIpKQpgYGAKCgpNYXAgcGVyY2VudGFnZXMKYGBge3J9CnN0YXRlcyAlPiUgCiAgZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGZpbGwgPSBwZXJjZW50X2EsIGdyb3VwID0gZ3JvdXApLCBjb2xvciA9ICJ3aGl0ZSIpICsgCiAgY29vcmRfZml4ZWQoMS4zKSArCiAgZ3VpZGVzKGZpbGw9RkFMU0UpICsKICB0aGVtZV9idygpIyBkbyB0aGlzIHRvIGxlYXZlIG9mZiB0aGUgY29sb3IgbGVnZW5kCmBgYAoKTWFwIGJpbmFyeSBvdXRjb21lcyB2YXJpYWJsZSArIG1hcApgYGB7cn0Kc3RhdGVzICU+JSAKICBtdXRhdGUod2lubmVyID0gaWZlbHNlKHBlcmNlbnRfYSA+IHBlcmNlbnRfYiwgImEiLCAiYiIpKSAlPiUgCiAgZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGZpbGwgPSB3aW5uZXIsIGdyb3VwID0gZ3JvdXApLCBjb2xvciA9ICJ3aGl0ZSIpICsgCiAgY29vcmRfZml4ZWQoMS4zKSArCiAgZ3VpZGVzKGZpbGw9RkFMU0UpICsKICB0aGVtZV9idygpIyBkbyB0aGlzIHRvIGxlYXZlIG9mZiB0aGUgY29sb3IgbGVnZW5kCmBgYAoKTm93IG1ha2UgYSBmdW5jdGlvbiB0byBjcmVhdGUgdGhlIHZhcmlhYmxlcyB3ZSB3YW50IApgYGB7cn0KY3JlYXRlX21hcF92YXJzPC1mdW5jdGlvbih4KXt4ICU+JQogICAgICAgICAgICAgICAgICBhcy50aWJibGUoLikgJT4lCiAgbXV0YXRlKHN0YXRlPXJlZ2lvbikgJT4lCiAgbXV0YXRlKHBlcmNlbnRfYSA9IHNhbXBsZSgxOjE1NTM3KSkgJT4lICN0aGlzIGNyZWF0ZXMgdGhlIHBlcmNlbnRhZ2UgZm9yIGVhY2ggcm93CiAgbXV0YXRlKHBlcmNlbnRfYSA9IChwZXJjZW50X2EvMTU1MzcpICogMTAwKSAgJT4lIAogICAgbXV0YXRlKHBlcmNlbnRfYT1yb3VuZChwZXJjZW50X2EsIDIpKSAlPiUgCiAgbXV0YXRlKHBlcmNlbnRfYiA9IDEwMC0ocGVyY2VudF9hKSkgJT4lIAogIG11dGF0ZSh3aW5uZXIgPSBpZmVsc2UocGVyY2VudF9hID4gcGVyY2VudF9iLCAiYSIsICJiIikpICU+JSAKICAgIG11dGF0ZShtYXJnaW5fYSA9IHBlcmNlbnRfYSAtIHBlcmNlbnRfYikKCiAgfQpgYGAKCgpBcHBseSB0aGlzIGZ1bmN0aW9uIHRvIHRoZSBkYXRhIGFuZCBTYXZlIGl0IGFzICdkYXQnCmBgYHtyfQpkYXQ8LWNyZWF0ZV9tYXBfdmFycyhtYXBfZGF0YSgic3RhdGUiKSkKYGBgCgpNYXAgYmluYXJ5IHdpbm5lciBvdXRjb21lIApgYGB7cn0KICBkYXQgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3BvbHlnb24oYWVzKHggPSBsb25nLCB5ID0gbGF0LCBmaWxsID0gd2lubmVyLCBncm91cCA9IGdyb3VwKSwgY29sb3IgPSAid2hpdGUiKSArIAogIGNvb3JkX2ZpeGVkKDEuMykgKwogIGd1aWRlcyhmaWxsPUZBTFNFKSArCiAgdGhlbWVfYncoKSMgZG8gdGhpcyB0byBsZWF2ZSBvZmYgdGhlIGNvbG9yIGxlZ2VuZApgYGAKCk1ha2UgZnVuY3Rpb24gdG8gcGxvdCBwZXJjZW50YWdlIApgYGB7cn0KcGxvdF9wZXJjZW50PC1mdW5jdGlvbih4KXt4ICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV9wb2x5Z29uKGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZmlsbCA9IG1hcmdpbl9hLCBncm91cCA9IGdyb3VwKSwgY29sb3IgPSAid2hpdGUiKSArICN4ID0gbG9uZ2l0dWRlIAogIGNvb3JkX2ZpeGVkKDEuMykgKwogIHRoZW1lX2J3KCkrCiAgICBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3c9InJlZCIsIGhpZ2g9ImJsdWUiKSsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJmYWxzZSIpfQpgYGAKClRoaXMgaXMgYmFzaWNhbGx5IGEgInJhbmRvbSIgcmVzdWx0IG9mIGEgVVMgZmVkZXJhbCBlbGVjdGlvbgpgYGB7cn0KcGxvdF9wZXJjZW50KGRhdCkKYGBgCgoqKioKCldpdGggcmVhbCBkYXRhCgoqKioKClRoYW5rZnVsbHksIGEgbG90IG9mIHBlb3BsZSBoYXZlIHRha2VuIHRoZSB0aW1lIHRvIGNhcmVmdWxseSBkb2N1bWVudCBlbGVjdGlvbiByZXN1bHRzIGFuZCBtYWtlIHRoYXQgZGF0YSBhdmFpbGFibGUgdG8gdGhlIHB1YmxpYwoKCkhlcmUgSSBhbSBpbXBvcnRpbmcgZGF0YSBmcm9tIHRoZSBNSVQgeHh4eCBwcm9qZWN0ICh3ZWJzaXRlKQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwcmVzX2RhdDwtcmVhZF9jc3YoIjE5NzYtMjAxNi1wcmVzaWRlbnQuY3N2IikKYGBgCgoKQ3JlYXRlIDIwMDggV2lubmVycyBkYXQKYGBge3J9Cm1hcF8yMDA4X2RhdDwtcHJlc19kYXQgJT4lIHNlbGVjdCh5ZWFyLCBzdGF0ZSxjYW5kaWRhdGUsIHBhcnR5LCBzdGF0ZV92b3Rlcz1jYW5kaWRhdGV2b3RlcykgJT4lIAogIGZpbHRlcih5ZWFyPT0yMDA4KSAlPiUgCiAgdW5pcXVlKCkgJT4lIAogIG5hLm9taXQoKSAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUpICU+JSAKICBtdXRhdGUoc3RhdGVfdG90YWw9c3VtKHN0YXRlX3ZvdGVzKSkgJT4lIAogIG11dGF0ZShwZXJjZW50ID0gcm91bmQoKHN0YXRlX3ZvdGVzIC8gc3RhdGVfdG90YWwpICogMTAwLCAyKSkgJT4lIAogIG11dGF0ZSh3aW5uZXI9aWZlbHNlKHBlcmNlbnQgPT0gbWF4KHBlcmNlbnQpLCAxLCAwKSkgJT4lIAogIGZpbHRlcih3aW5uZXI9PTEpICU+JSBzZWxlY3QoLXdpbm5lcikKYGBgCgpDcmVhdGUgMjAxMiBXaW5uZXJzIGRhdApgYGB7cn0KbWFwXzIwMTJfZGF0PC1wcmVzX2RhdCAlPiUgc2VsZWN0KHllYXIsIHN0YXRlLGNhbmRpZGF0ZSwgcGFydHksIHN0YXRlX3ZvdGVzPWNhbmRpZGF0ZXZvdGVzKSAlPiUgCiAgZmlsdGVyKHllYXI9PTIwMTIpICU+JSAKICB1bmlxdWUoKSAlPiUgCiAgbmEub21pdCgpICU+JSAKICBncm91cF9ieShzdGF0ZSkgJT4lIAogIG11dGF0ZShzdGF0ZV90b3RhbD1zdW0oc3RhdGVfdm90ZXMpKSAlPiUgCiAgbXV0YXRlKHBlcmNlbnQgPSByb3VuZCgoc3RhdGVfdm90ZXMgLyBzdGF0ZV90b3RhbCkgKiAxMDAsIDIpKSAlPiUgCiAgbXV0YXRlKHdpbm5lcj1pZmVsc2UocGVyY2VudCA9PSBtYXgocGVyY2VudCksIDEsIDApKSAlPiUgCiAgZmlsdGVyKHdpbm5lcj09MSkgJT4lIHNlbGVjdCgtd2lubmVyKQpgYGAKCkNyZWF0ZSAyMDE2IFdpbm5lcnMgZGF0CmBgYHtyfQptYXBfMjAxNl9kYXQ8LXByZXNfZGF0ICU+JSBzZWxlY3QoeWVhciwgc3RhdGUsY2FuZGlkYXRlLCBwYXJ0eSwgc3RhdGVfdm90ZXM9Y2FuZGlkYXRldm90ZXMpICU+JSAKICBmaWx0ZXIoeWVhcj09MjAxNikgJT4lIAogIHVuaXF1ZSgpICU+JSAKICBuYS5vbWl0KCkgJT4lIAogIGdyb3VwX2J5KHN0YXRlKSAlPiUgCiAgbXV0YXRlKHN0YXRlX3RvdGFsPXN1bShzdGF0ZV92b3RlcykpICU+JSAKICBtdXRhdGUocGVyY2VudCA9IHJvdW5kKChzdGF0ZV92b3RlcyAvIHN0YXRlX3RvdGFsKSAqIDEwMCwgMikpICU+JSAKICBtdXRhdGUod2lubmVyPWlmZWxzZShwZXJjZW50ID09IG1heChwZXJjZW50KSwgMSwgMCkpICU+JSAKICBmaWx0ZXIod2lubmVyPT0xKSAlPiUgc2VsZWN0KC13aW5uZXIpCmBgYAoKCmBgYHtyfQp3aW5uZXJzXzIwMDhfZGF0PC1tYXBfMjAwOF9kYXQgJT4lIGFycmFuZ2UoeWVhciwgc3RhdGUpICU+JSB1bmdyb3VwKCkgJT4lICBtdXRhdGUoc3RhdGU9dG9sb3dlcihzdGF0ZSkpCmBgYAoKYGBge3J9Cndpbm5lcnNfMjAxMl9kYXQ8LW1hcF8yMDEyX2RhdCAlPiUgYXJyYW5nZSh5ZWFyLCBzdGF0ZSkgJT4lIHVuZ3JvdXAoKSAlPiUgIG11dGF0ZShzdGF0ZT10b2xvd2VyKHN0YXRlKSkKYGBgCgpgYGB7cn0Kd2lubmVyc18yMDE2X2RhdDwtbWFwXzIwMTZfZGF0ICU+JSBhcnJhbmdlKHllYXIsIHN0YXRlKSAlPiUgdW5ncm91cCgpICU+JSAgbXV0YXRlKHN0YXRlPXRvbG93ZXIoc3RhdGUpKQpgYGAKCgoqKioKCmBgYHtyfQptYXBfZGF0XzIwMDg8LW1lcmdlKGRhdCwgd2lubmVyc18yMDA4X2RhdCwgYnk9InN0YXRlIikKbWFwX2RhdF8yMDEyPC1tZXJnZShkYXQsIHdpbm5lcnNfMjAxMl9kYXQsIGJ5PSJzdGF0ZSIpCm1hcF9kYXRfMjAxNjwtbWVyZ2UoZGF0LCB3aW5uZXJzXzIwMTZfZGF0LCBieT0ic3RhdGUiKQpgYGAKCioqKgoKRm9yIHNvbWUgcmVhc29uLCAyMDEyIGlzbid0IHdvcmtpbmcgY29ycmVjdGx5OwoKRml4IDIwMTIKYGBge3J9Cm1hcF9kYXRfMjAxMjwtbWFwX2RhdF8yMDEyICU+JSBtdXRhdGUocGFydHk9aWZlbHNlKHBhcnR5PT0iZGVtb2NyYXRpYy1mYXJtZXItbGFib3IiLCAiZGVtb2NyYXQiLCBwYXJ0eSkpCmBgYAoKCk1ha2UgZnVuY3Rpb24gdG8gcGxvdCBwZXJjZW50YWdlIApgYGB7cn0KcGxvdF9wZXJjZW50PC1mdW5jdGlvbih4KXt4ICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV9wb2x5Z29uKGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZmlsbCA9IGZhY3RvcihwYXJ0eSksIGdyb3VwID0gZ3JvdXApLCBjb2xvcj0id2hpdGUiLCBhbHBoYT0wLjc1KSArIAogIGNvb3JkX2ZpeGVkKDEuMykgKwogIHRoZW1lX3ZvaWQoKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiYmx1ZSIsICJyZWQiKSkrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImZhbHNlIil9CmBgYAoKSGVyZSB3ZSBjYW4gcGxvdCBlYWNoIGVsZWN0aW9uIHNlcGVyYXRlbHkgCmBgYHtyfQpwbG90X3BlcmNlbnQobWFwX2RhdF8yMDA4KSArIAogIGdndGl0bGUoMjAwOCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI4LCBmYWNlID0gImJvbGQiLCBoanVzdD0wLjUpKQoKIwoKcGxvdF9wZXJjZW50KG1hcF9kYXRfMjAxMikrIAogIGdndGl0bGUoMjAxMikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI4LCBmYWNlID0gImJvbGQiLCBoanVzdD0wLjUpKQoKIwoKcGxvdF9wZXJjZW50KG1hcF9kYXRfMjAxNikrIAogIGdndGl0bGUoMjAxNikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI4LCBmYWNlID0gImJvbGQiLCBoanVzdD0wLjUpKQpgYGAKCm4KYGBge3J9CmRhdF8yMDA4XzIwMTY8LWJpbmRfcm93cyhtYXBfZGF0XzIwMDgsIG1hcF9kYXRfMjAxMiwgbWFwX2RhdF8yMDE2KQpgYGAKCgoKCioqKgoKYGBge3IgZmlnLmhlaWdodD0xOCwgZmlnLndpZHRoPTEyfQpwbG90X3BlcmNlbnQoZGF0XzIwMDhfMjAxNikrIAogIGdndGl0bGUoIlByZXNpZGVudGlhbCBFbGVjdGlvbnM6IDIwMDggLSAyMDE2IikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI4LCBmYWNlID0gImJvbGQiLCBoanVzdD0wLjUpKSsKICBmYWNldF93cmFwKH55ZWFyLCBucm93ID0gMykrCiAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgY29sb3VyID0gImJsYWNrIiwgZmFjZT0iYm9sZCIpKQpgYGAKCioqKgoKCmBgYHtyfQpkYXRfMjAwOF8yMDE2ICU+JSAKICBhcnJhbmdlKHBlcmNlbnQpICU+JSAKICBzZWxlY3QoeWVhciwgc3RhdGUsIGNhbmRpZGF0ZSwgcGVyY2VudCkgJT4lCiAgdW5pcXVlKCkKYGBgCgpMb29rIGF0IG1hcmdpbnMKYGBge3J9CmRhdF8yMDA4XzIwMTYgJT4lIAogIGZpbHRlcihwZXJjZW50PDkwKSAlPiUgI1RoaXMgZXhjbHVkZXMgREMgKHNvcnJ5LCBEQykKICBhcnJhbmdlKHBlcmNlbnQpICU+JSAKICBzZWxlY3QoeWVhciwgc3RhdGUsIGNhbmRpZGF0ZSwgcGVyY2VudCkgJT4lCiAgdW5pcXVlKCkgJT4lIAogIGdncGxvdChhZXMoeD15ZWFyLCB5PXBlcmNlbnQpKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA1MCwgYWxwaGE9MC4yKSsKICBnZW9tX2ppdHRlcihzaXplPTMsIGFscGhhPTAuNSkrCiAgdGhlbWVfYncoKQpgYGAKCg==