Jennifer Ganeles
4/14/19

Gender Diveristy in Comic Books:

Revisiting Female Under-Representation in the Marvel and DC Universes

This week’s homework explores gender representation in both the Marvel and DC universes using the FiveThirtyEight Comic Characters Dataset found on Kaggle. The data is split into two files for Marvel and DC respectively: marvel-wikia-data.csv and dc-wikia-data.csv.


Using data visualization, I will be exploring the following variables:


Gender: Male or female
APPEARANCES: Number of appearances
Year: Year that character was first introduced
YEARS: Number of years since character first appeared
ALIGN: Whether a character is bad, good, or neutral
ALIVE: Whether a character is living or deceased


Given my previous homework on gender differences in Marvel comics (Homework 7), I hypothesize that males will severely outnumber females in both universes, but females will appear in the comics, on average, more times than males when controlling for alignment, alive status, and years since character was introduced.

Importing and Tidying the Data:

library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)
library(ggthemes)
library(magrittr)
library(gridExtra)
#MARVEL
Marvel<-read_csv("/Users/jenniferganeles/Downloads/marvel-wikia-data.csv")
marvel_comics<-
  mutate (Marvel, Gender=
            recode(SEX, "Agender Characters"="Other", "Genderfluid Characters"="Other", 
                   "Male Characters"="Male", "Female Characters"="Female"),
          ALIVE=
            recode(ALIVE, "Deceased Characters"="Deceased", "Living Characters"="Living"),
          YEARS=
            2014-Year,
          Gender=as.factor(Gender),
          ALIGN=as.factor(ALIGN),
          ALIVE=as.factor(ALIVE),
          Universe="Marvel")%>%
  filter(Gender!="Other", !is.na(Gender), !is.na(APPEARANCES))
#DC
DC<-read_csv("/Users/jenniferganeles/Downloads/dc-wikia-data.csv")
dc_comics<-
  mutate (DC, Gender=
            recode(SEX, "Genderless Characters"="Other", "Transgender Characters"="Other",
                   "Male Characters"="Male", "Female Characters"="Female"),
          ALIVE=
            recode(ALIVE, "Deceased Characters"="Deceased", "Living Characters"="Living"),
          Gender=as.factor(Gender),
          ALIGN=as.factor(ALIGN),
          ALIVE=as.factor(ALIVE),
          YEARS=
            2014-YEAR,
          Universe="DC")%>%
  filter(Gender!="Other", !is.na(Gender), !is.na(APPEARANCES))

Total Characters by Universe:

The following bar graph represents the frequency of male and female characters in both the Marvel and DC universes:

marvel_gender<-marvel_comics%>%
  group_by(Gender)%>%
  tally
dc_gender<-dc_comics%>%
  group_by(Gender)%>%
  tally
total<-rbind(marvel_gender, dc_gender)%>%
  mutate(Universe=
           recode(n, "3599"="Marvel", "10899"="Marvel", "1880"="DC", "4527"="DC"))
ggplot(data=total)+
 geom_col(aes(x=Universe,y=n, fill=Gender), position="dodge")+
  labs(title="Total Characters: DC vs. Marvel", y="Number of Characters")+
  theme_tufte()+
  theme(plot.title = element_text(hjust = 0.5))

New Characters Introduced by Year:

The following line graphs depict how many characters have been introduced each year (from around 1940 to 2014). It shows the temporal trend of new male and female characters.

#MARVEL
new_marvel <- marvel_comics%>%
    group_by(Year, Gender) %>%
  tally
nm<-ggplot(new_marvel, aes(x=Year, y=n)) +
  geom_line(aes(color = Gender), size = 2)+
  theme_tufte()+
  theme(plot.title = element_text(hjust = 0.5))+
  labs(y="New Characters (Marvel)")
#DC
new_dc <- dc_comics%>%
    group_by(YEAR, Gender) %>%
  tally
nd<-ggplot(new_dc, aes(x=YEAR, y=n)) +
  geom_line(aes(color = Gender), size = 2)+
  theme_tufte()+
  theme(plot.title = element_text(hjust = 0.5))+
  labs(x="Year", y="New Characters (DC)")
grid.arrange(nm,nd, nrow=2)

Top Ten Characters: Who Appears Most in the Comics?

Below, one can see the characters with highest number of appearances in the comics.

#MARVEL
marvel_top<-marvel_comics%>%
  group_by(APPEARANCES, name)%>%
  arrange(-APPEARANCES)
mpop<-ggplot(data=marvel_top[1:10,], aes(x=reorder(name,APPEARANCES), y=APPEARANCES))+
  geom_bar(stat = "identity", aes(fill=Gender)) +
  scale_fill_manual(values = c("turquoise3"))+
  coord_flip()+
  labs(x="", y="Appearances", title="Top Ten Marvel Characters")+
  theme_tufte()
#DC
dc_top<-dc_comics%>%
  group_by(APPEARANCES, name)%>%
  arrange(-APPEARANCES)
dcpop<-ggplot(data=dc_top[1:10,], aes(x=reorder(name,APPEARANCES), y=APPEARANCES))+
  geom_bar(stat = "identity", aes(fill=Gender)) +
  coord_flip()+
  labs(x="", y="Appearances", title="Top Ten DC Characters")+
  theme_tufte()
grid.arrange(mpop, dcpop, nrow=2)

Distribution of Appearances by Gender:

The following boxplots represent the distribution of appearances for male and female characters. However, it is important to note that only recurring characters were included in this distribution (where appearances equal 150 or greater).

library(Hmisc)
#MARVEL
pop<-marvel_comics%>%
  filter(APPEARANCES>=150)
mbx<-ggplot(data=pop, aes(x=Gender,y=APPEARANCES, fill=Gender))+
  geom_boxplot() + stat_summary(fun.data = "mean_cl_boot", colour = "red")+
  labs(title="Marvel")+
  theme_tufte()+
  theme(plot.title = element_text(hjust = 0.5))
#DC
pop2<-dc_comics%>%
  filter(APPEARANCES>=150)
dcbx<-ggplot(data=pop2, aes(x=Gender,y=APPEARANCES, fill=Gender))+
  geom_boxplot() + stat_summary(fun.data = "mean_cl_boot", colour = "blue")+
  labs(title="DC")+
  theme_tufte()+
  theme(plot.title = element_text(hjust = 0.5))
grid.arrange(mbx, dcbx, nrow=1)

Relationship Between Years as Comic Character and Number of Appearances:

The following regressions represent the relationship between how many years a character has appeared in the comics and how many times they have appeared in the comics. However, once again, only frequently recurring characters were included in this model (where appearances equal 150 or greater).

#MARVEL
mlm<-ggplot(data=pop, aes(x=YEARS,y=APPEARANCES, fill=Gender))+
  geom_point()+stat_smooth(method="lm", color='red')+
  labs(title="Marvel", y= "Appearances", x="Years")+
  theme_tufte()+
  theme(plot.title = element_text(hjust = 0.5))
#DC
dclm<-ggplot(data=pop2, aes(x=YEARS,y=APPEARANCES, fill=Gender))+
  geom_point()+stat_smooth(method="lm")+
  labs(title="DC", y="Appearances", x="Years")+
  theme_tufte()+
  theme(plot.title = element_text(hjust = 0.5))
grid.arrange(mlm, dclm, nrow=1)

Median Appearance for Male and Female Characters by Alignment and Alive Status:

The below plots explore the median gender difference in appearances, taking into account whether a character is living or deceased, as well as whether a character is bad, good, or neutral.

#MARVEL
marvel_comics2<-marvel_comics%>%
  filter(!is.na(ALIGN))
int<-ggplot(data=marvel_comics2) +
  aes(x = Gender, color = ALIGN, group=ALIGN, y = APPEARANCES) +  
  stat_summary(fun.y = median, geom ="point")+
  stat_summary(fun.y = median, geom = "line")+
   facet_wrap( ~ ALIVE)+
  labs(title="Marvel", y="Appearances (Median)")+theme(plot.title = element_text(hjust = 0.5))
 
#DC
dc_comics2<-dc_comics%>%
  filter(!is.na(ALIVE), !is.na(ALIGN), ALIGN!="Reformed Criminals")
int2<-ggplot(data=dc_comics2) +
  aes(x = Gender, color = ALIGN, group=ALIGN, y = APPEARANCES) +  
  stat_summary(fun.y = median, geom ="point")+
  stat_summary(fun.y = median, geom = "line")+
   facet_wrap( ~ ALIVE)+
  labs(title="DC", y="Appearances (Median)")+theme(plot.title = element_text(hjust = 0.5))
  
grid.arrange(int, int2, nrow=2) 

Gender Difference in MARVEL Appearances

Using a poisson model, the below plots represent the mean gender difference in MARVEL appearances while controlling for alignment, alive status, and number of years since introduced.

library(Zelig)
MPoisson <- zelig(APPEARANCES ~ Gender+ALIGN+ALIVE+YEARS, model = "poisson", data = marvel_comics, cite = F)
xm<-setx(MPoisson,Gender="Male")
xf<-setx(MPoisson,Gender="Female")
s<-sim(MPoisson,x=xm,x1=xf)
evm <- s$get_qi(xvalue="x", qi="ev")
evf<-s$get_qi(xvalue="x1",qi="ev")
df <- as.data.frame(cbind(evf,evm))%>%
  rename("Female"=V1, "Male"=V2)
tidd <- df %>% 
  gather(Gender, APPEARANCES, 1:2)
appear<-tidd%>%
  group_by(Gender)%>% 
  summarise(mean = mean(APPEARANCES), sd = sd(APPEARANCES))
mdiff<-
  ggplot(data=tidd, aes(x=APPEARANCES))+
  geom_density(fill="red")+
  facet_wrap(~Gender)+
  geom_vline(data=appear,aes(xintercept=mean),color="black") + 
  xlab("Average Number of Appearances (Expected Value)")+ 
  ggtitle("Gender Difference in Marvel Comic Appearances")+
  theme_bw()+theme(plot.title = element_text(hjust = 0.5))
x <- setx(MPoisson, Gender = "Male")
x1 <- setx(MPoisson, Gender = "Female")
s <- sim(MPoisson, x = x, x1 = x1)
fdm <- s$get_qi(xvalue="x1", qi="fd")
genderdiff <- as.data.frame(cbind(fdm))%>%
rename("Gender Difference"=V1)
gender_diff<- genderdiff %>% 
  gather(class, simv)
gf<-gender_diff %>% 
  group_by(class) %>% 
  summarise(mean = mean(simv), sd = sd(simv))
 m_diff<-
  ggplot(data=gender_diff, aes(simv)) + 
  geom_density(fill="red") + 
  facet_grid(~class) + 
  geom_vline(data=gf,aes(xintercept=mean))+
  labs(x = "Simulated First Difference (Mean)")+
  theme_bw()
grid.arrange(mdiff, m_diff, nrow=2)

Gender Difference in DC Appearances:

Using a poisson model, the below plots represent the mean gender difference in DC appearances while controlling for alignment, alive status, and number of years since introduced.

DCPoisson <- zelig(APPEARANCES ~ Gender+ALIGN+ALIVE+YEARS, model = "poisson", data = dc_comics, cite = F)
xm<-setx(DCPoisson, Gender="Male")
xf<-setx(DCPoisson, Gender="Female")
s<-sim(DCPoisson, x=xm, x1=xf)
evm <- s$get_qi(xvalue="x", qi="ev")
evf<-s$get_qi(xvalue="x1",qi="ev")
df2 <- as.data.frame(cbind(evf,evm))%>%
  rename("Female"=V1,
        "Male"=V2)
tidd2 <- df2 %>% 
  gather(Gender, APPEARANCES, 1:2)
appear2<-tidd2%>%
  group_by(Gender)%>% 
  summarise(mean = mean(APPEARANCES), sd = sd(APPEARANCES))
mdiff2<-
  ggplot(data=tidd2, aes(x=APPEARANCES))+
  geom_density(fill="blue")+
  facet_wrap(~Gender)+
  geom_vline(data=appear2,aes(xintercept=mean),color="black") + 
  xlab("Average Number of Appearances (Expected Value)")+ 
  ggtitle("Gender Difference in DC Comic Appearances")+
  theme_bw()+theme(plot.title = element_text(hjust = 0.5))
x <- setx(DCPoisson, Gender = "Male")
x1 <- setx(DCPoisson, Gender = "Female")
s <- sim(DCPoisson, x = x, x1 = x1)
fd <- s$get_qi(xvalue="x1", qi="fd")
genderdiff2 <- as.data.frame(cbind(fd))%>%
rename("Gender Difference"=V1)
 gender_diff2<- genderdiff2 %>% 
  gather(class, simv)
gf2<-gender_diff2 %>% 
  group_by(class) %>% 
  summarise(mean = mean(simv), sd = sd(simv))
m_diff2<-
  ggplot(data=gender_diff2, aes(simv)) + 
  geom_density(fill="blue") + 
  facet_grid(~class) + 
  geom_vline(data=gf2,aes(xintercept=mean))+
  labs(x = "Simulated First Difference (Mean)")+
  theme_bw()
grid.arrange(mdiff2, m_diff2, nrow=2)

LS0tCnRpdGxlOiAiU29jIDcxMjogSG9tZXdvcmsgOSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoqSmVubmlmZXIgR2FuZWxlcyoKPGJyLz4qNC8xNC8xOSoKCiFbXSgvVXNlcnMvamVubmlmZXJnYW5lbGVzL0Rvd25sb2Fkcy9NYXJ2ZWwuREMuanBnKQoKI0dlbmRlciBEaXZlcmlzdHkgaW4gQ29taWMgQm9va3M6CiMjUmV2aXNpdGluZyBGZW1hbGUgVW5kZXItUmVwcmVzZW50YXRpb24gaW4gdGhlIE1hcnZlbCBhbmQgREMgVW5pdmVyc2VzIAoKVGhpcyB3ZWVrJ3MgaG9tZXdvcmsgZXhwbG9yZXMgZ2VuZGVyIHJlcHJlc2VudGF0aW9uIGluIGJvdGggdGhlIE1hcnZlbCBhbmQgREMgdW5pdmVyc2VzIHVzaW5nIHRoZSBGaXZlVGhpcnR5RWlnaHQgQ29taWMgQ2hhcmFjdGVycyBEYXRhc2V0IGZvdW5kIG9uIEthZ2dsZS4gVGhlIGRhdGEgaXMgc3BsaXQgaW50byB0d28gZmlsZXMgZm9yIE1hcnZlbCBhbmQgREMgcmVzcGVjdGl2ZWx5OiAqKm1hcnZlbC13aWtpYS1kYXRhLmNzdioqIGFuZCAqKmRjLXdpa2lhLWRhdGEuY3N2KiouIAoKPGJyLz5Vc2luZyBkYXRhIHZpc3VhbGl6YXRpb24sIEkgd2lsbCBiZSBleHBsb3JpbmcgdGhlIGZvbGxvd2luZyB2YXJpYWJsZXM6IAoKPGJyLz4qKkdlbmRlcjoqKiBNYWxlIG9yIGZlbWFsZSAKPGJyLz4gKipBUFBFQVJBTkNFUzoqKiBOdW1iZXIgb2YgYXBwZWFyYW5jZXMgCjxici8+ICoqWWVhcjoqKiBZZWFyIHRoYXQgY2hhcmFjdGVyIHdhcyBmaXJzdCBpbnRyb2R1Y2VkIAo8YnIvPiAqKllFQVJTOioqIE51bWJlciBvZiB5ZWFycyBzaW5jZSBjaGFyYWN0ZXIgZmlyc3QgYXBwZWFyZWQKPGJyLz4gKipBTElHTjoqKiBXaGV0aGVyIGEgY2hhcmFjdGVyIGlzIGJhZCwgZ29vZCwgb3IgbmV1dHJhbAo8YnIvPiAqKkFMSVZFOioqIFdoZXRoZXIgYSBjaGFyYWN0ZXIgaXMgbGl2aW5nIG9yIGRlY2Vhc2VkCgoKPGJyLz4gR2l2ZW4gbXkgcHJldmlvdXMgaG9tZXdvcmsgb24gZ2VuZGVyIGRpZmZlcmVuY2VzIGluIE1hcnZlbCBjb21pY3MgKEhvbWV3b3JrIDcpLCBJIGh5cG90aGVzaXplIHRoYXQgbWFsZXMgd2lsbCBzZXZlcmVseSBvdXRudW1iZXIgZmVtYWxlcyBpbiBib3RoIHVuaXZlcnNlcywgYnV0IGZlbWFsZXMgd2lsbCBhcHBlYXIgaW4gdGhlIGNvbWljcywgb24gYXZlcmFnZSwgbW9yZSB0aW1lcyB0aGFuIG1hbGVzIHdoZW4gY29udHJvbGxpbmcgZm9yIGFsaWdubWVudCwgYWxpdmUgc3RhdHVzLCBhbmQgeWVhcnMgc2luY2UgY2hhcmFjdGVyIHdhcyBpbnRyb2R1Y2VkLiAKCiMjI0ltcG9ydGluZyBhbmQgVGlkeWluZyB0aGUgRGF0YToKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdndGhlbWVzKQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KGdyaWRFeHRyYSkKCiNNQVJWRUwKTWFydmVsPC1yZWFkX2NzdigiL1VzZXJzL2plbm5pZmVyZ2FuZWxlcy9Eb3dubG9hZHMvbWFydmVsLXdpa2lhLWRhdGEuY3N2IikKbWFydmVsX2NvbWljczwtCiAgbXV0YXRlIChNYXJ2ZWwsIEdlbmRlcj0KICAgICAgICAgICAgcmVjb2RlKFNFWCwgIkFnZW5kZXIgQ2hhcmFjdGVycyI9Ik90aGVyIiwgIkdlbmRlcmZsdWlkIENoYXJhY3RlcnMiPSJPdGhlciIsIAogICAgICAgICAgICAgICAgICAgIk1hbGUgQ2hhcmFjdGVycyI9Ik1hbGUiLCAiRmVtYWxlIENoYXJhY3RlcnMiPSJGZW1hbGUiKSwKICAgICAgICAgIEFMSVZFPQogICAgICAgICAgICByZWNvZGUoQUxJVkUsICJEZWNlYXNlZCBDaGFyYWN0ZXJzIj0iRGVjZWFzZWQiLCAiTGl2aW5nIENoYXJhY3RlcnMiPSJMaXZpbmciKSwKICAgICAgICAgIFlFQVJTPQogICAgICAgICAgICAyMDE0LVllYXIsCiAgICAgICAgICBHZW5kZXI9YXMuZmFjdG9yKEdlbmRlciksCiAgICAgICAgICBBTElHTj1hcy5mYWN0b3IoQUxJR04pLAogICAgICAgICAgQUxJVkU9YXMuZmFjdG9yKEFMSVZFKSwKICAgICAgICAgIFVuaXZlcnNlPSJNYXJ2ZWwiKSU+JQogIGZpbHRlcihHZW5kZXIhPSJPdGhlciIsICFpcy5uYShHZW5kZXIpLCAhaXMubmEoQVBQRUFSQU5DRVMpKQoKI0RDCkRDPC1yZWFkX2NzdigiL1VzZXJzL2plbm5pZmVyZ2FuZWxlcy9Eb3dubG9hZHMvZGMtd2lraWEtZGF0YS5jc3YiKQpkY19jb21pY3M8LQogIG11dGF0ZSAoREMsIEdlbmRlcj0KICAgICAgICAgICAgcmVjb2RlKFNFWCwgIkdlbmRlcmxlc3MgQ2hhcmFjdGVycyI9Ik90aGVyIiwgIlRyYW5zZ2VuZGVyIENoYXJhY3RlcnMiPSJPdGhlciIsCiAgICAgICAgICAgICAgICAgICAiTWFsZSBDaGFyYWN0ZXJzIj0iTWFsZSIsICJGZW1hbGUgQ2hhcmFjdGVycyI9IkZlbWFsZSIpLAogICAgICAgICAgQUxJVkU9CiAgICAgICAgICAgIHJlY29kZShBTElWRSwgIkRlY2Vhc2VkIENoYXJhY3RlcnMiPSJEZWNlYXNlZCIsICJMaXZpbmcgQ2hhcmFjdGVycyI9IkxpdmluZyIpLAogICAgICAgICAgR2VuZGVyPWFzLmZhY3RvcihHZW5kZXIpLAogICAgICAgICAgQUxJR049YXMuZmFjdG9yKEFMSUdOKSwKICAgICAgICAgIEFMSVZFPWFzLmZhY3RvcihBTElWRSksCiAgICAgICAgICBZRUFSUz0KICAgICAgICAgICAgMjAxNC1ZRUFSLAogICAgICAgICAgVW5pdmVyc2U9IkRDIiklPiUKICBmaWx0ZXIoR2VuZGVyIT0iT3RoZXIiLCAhaXMubmEoR2VuZGVyKSwgIWlzLm5hKEFQUEVBUkFOQ0VTKSkKYGBgCgojIyNUb3RhbCBDaGFyYWN0ZXJzIGJ5IFVuaXZlcnNlOgpUaGUgZm9sbG93aW5nIGJhciBncmFwaCByZXByZXNlbnRzIHRoZSBmcmVxdWVuY3kgb2YgbWFsZSBhbmQgZmVtYWxlIGNoYXJhY3RlcnMgaW4gYm90aCB0aGUgTWFydmVsIGFuZCBEQyB1bml2ZXJzZXM6CmBgYHtyfQptYXJ2ZWxfZ2VuZGVyPC1tYXJ2ZWxfY29taWNzJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSU+JQogIHRhbGx5CmRjX2dlbmRlcjwtZGNfY29taWNzJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSU+JQogIHRhbGx5Cgp0b3RhbDwtcmJpbmQobWFydmVsX2dlbmRlciwgZGNfZ2VuZGVyKSU+JQogIG11dGF0ZShVbml2ZXJzZT0KICAgICAgICAgICByZWNvZGUobiwgIjM1OTkiPSJNYXJ2ZWwiLCAiMTA4OTkiPSJNYXJ2ZWwiLCAiMTg4MCI9IkRDIiwgIjQ1MjciPSJEQyIpKQoKZ2dwbG90KGRhdGE9dG90YWwpKwogZ2VvbV9jb2woYWVzKHg9VW5pdmVyc2UseT1uLCBmaWxsPUdlbmRlciksIHBvc2l0aW9uPSJkb2RnZSIpKwogIGxhYnModGl0bGU9IlRvdGFsIENoYXJhY3RlcnM6IERDIHZzLiBNYXJ2ZWwiLCB5PSJOdW1iZXIgb2YgQ2hhcmFjdGVycyIpKwogIHRoZW1lX3R1ZnRlKCkrCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKIyMjTmV3IENoYXJhY3RlcnMgSW50cm9kdWNlZCBieSBZZWFyOgpUaGUgZm9sbG93aW5nIGxpbmUgZ3JhcGhzIGRlcGljdCBob3cgbWFueSBjaGFyYWN0ZXJzIGhhdmUgYmVlbiBpbnRyb2R1Y2VkIGVhY2ggeWVhciAoZnJvbSBhcm91bmQgMTk0MCB0byAyMDE0KS4gSXQgc2hvd3MgdGhlIHRlbXBvcmFsIHRyZW5kIG9mIG5ldyBtYWxlIGFuZCBmZW1hbGUgY2hhcmFjdGVycy4gCmBgYHtyIHdhcm5pbmc9RkFMU0V9CiNNQVJWRUwKbmV3X21hcnZlbCA8LSBtYXJ2ZWxfY29taWNzJT4lCiAgICBncm91cF9ieShZZWFyLCBHZW5kZXIpICU+JQogIHRhbGx5Cm5tPC1nZ3Bsb3QobmV3X21hcnZlbCwgYWVzKHg9WWVhciwgeT1uKSkgKwogIGdlb21fbGluZShhZXMoY29sb3IgPSBHZW5kZXIpLCBzaXplID0gMikrCiAgdGhlbWVfdHVmdGUoKSsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkrCiAgbGFicyh5PSJOZXcgQ2hhcmFjdGVycyAoTWFydmVsKSIpCgojREMKbmV3X2RjIDwtIGRjX2NvbWljcyU+JQogICAgZ3JvdXBfYnkoWUVBUiwgR2VuZGVyKSAlPiUKICB0YWxseQpuZDwtZ2dwbG90KG5ld19kYywgYWVzKHg9WUVBUiwgeT1uKSkgKwogIGdlb21fbGluZShhZXMoY29sb3IgPSBHZW5kZXIpLCBzaXplID0gMikrCiAgdGhlbWVfdHVmdGUoKSsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkrCiAgbGFicyh4PSJZZWFyIiwgeT0iTmV3IENoYXJhY3RlcnMgKERDKSIpCgpncmlkLmFycmFuZ2Uobm0sbmQsIG5yb3c9MikKYGBgCgojIyNUb3AgVGVuIENoYXJhY3RlcnM6IFdobyBBcHBlYXJzIE1vc3QgaW4gdGhlIENvbWljcz8KQmVsb3csIG9uZSBjYW4gc2VlIHRoZSBjaGFyYWN0ZXJzIHdpdGggaGlnaGVzdCBudW1iZXIgb2YgYXBwZWFyYW5jZXMgaW4gdGhlIGNvbWljcy4gCmBgYHtyfQojTUFSVkVMCm1hcnZlbF90b3A8LW1hcnZlbF9jb21pY3MlPiUKICBncm91cF9ieShBUFBFQVJBTkNFUywgbmFtZSklPiUKICBhcnJhbmdlKC1BUFBFQVJBTkNFUykKbXBvcDwtZ2dwbG90KGRhdGE9bWFydmVsX3RvcFsxOjEwLF0sIGFlcyh4PXJlb3JkZXIobmFtZSxBUFBFQVJBTkNFUyksIHk9QVBQRUFSQU5DRVMpKSsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgYWVzKGZpbGw9R2VuZGVyKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoInR1cnF1b2lzZTMiKSkrCiAgY29vcmRfZmxpcCgpKwogIGxhYnMoeD0iIiwgeT0iQXBwZWFyYW5jZXMiLCB0aXRsZT0iVG9wIFRlbiBNYXJ2ZWwgQ2hhcmFjdGVycyIpKwogIHRoZW1lX3R1ZnRlKCkKCiNEQwpkY190b3A8LWRjX2NvbWljcyU+JQogIGdyb3VwX2J5KEFQUEVBUkFOQ0VTLCBuYW1lKSU+JQogIGFycmFuZ2UoLUFQUEVBUkFOQ0VTKQpkY3BvcDwtZ2dwbG90KGRhdGE9ZGNfdG9wWzE6MTAsXSwgYWVzKHg9cmVvcmRlcihuYW1lLEFQUEVBUkFOQ0VTKSwgeT1BUFBFQVJBTkNFUykpKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBhZXMoZmlsbD1HZW5kZXIpKSArCiAgY29vcmRfZmxpcCgpKwogIGxhYnMoeD0iIiwgeT0iQXBwZWFyYW5jZXMiLCB0aXRsZT0iVG9wIFRlbiBEQyBDaGFyYWN0ZXJzIikrCiAgdGhlbWVfdHVmdGUoKQoKZ3JpZC5hcnJhbmdlKG1wb3AsIGRjcG9wLCBucm93PTIpCmBgYAojIyNEaXN0cmlidXRpb24gb2YgQXBwZWFyYW5jZXMgYnkgR2VuZGVyOgpUaGUgZm9sbG93aW5nIGJveHBsb3RzIHJlcHJlc2VudCB0aGUgZGlzdHJpYnV0aW9uIG9mIGFwcGVhcmFuY2VzIGZvciBtYWxlIGFuZCBmZW1hbGUgY2hhcmFjdGVycy4gSG93ZXZlciwgaXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCBvbmx5IHJlY3VycmluZyBjaGFyYWN0ZXJzIHdlcmUgaW5jbHVkZWQgaW4gdGhpcyBkaXN0cmlidXRpb24gKHdoZXJlIGFwcGVhcmFuY2VzIGVxdWFsIDE1MCBvciBncmVhdGVyKS4gCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KEhtaXNjKQojTUFSVkVMCnBvcDwtbWFydmVsX2NvbWljcyU+JQogIGZpbHRlcihBUFBFQVJBTkNFUz49MTUwKQptYng8LWdncGxvdChkYXRhPXBvcCwgYWVzKHg9R2VuZGVyLHk9QVBQRUFSQU5DRVMsIGZpbGw9R2VuZGVyKSkrCiAgZ2VvbV9ib3hwbG90KCkgKyBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSAibWVhbl9jbF9ib290IiwgY29sb3VyID0gInJlZCIpKwogIGxhYnModGl0bGU9Ik1hcnZlbCIpKwogIHRoZW1lX3R1ZnRlKCkrCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgojREMKcG9wMjwtZGNfY29taWNzJT4lCiAgZmlsdGVyKEFQUEVBUkFOQ0VTPj0xNTApCmRjYng8LWdncGxvdChkYXRhPXBvcDIsIGFlcyh4PUdlbmRlcix5PUFQUEVBUkFOQ0VTLCBmaWxsPUdlbmRlcikpKwogIGdlb21fYm94cGxvdCgpICsgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gIm1lYW5fY2xfYm9vdCIsIGNvbG91ciA9ICJibHVlIikrCiAgbGFicyh0aXRsZT0iREMiKSsKICB0aGVtZV90dWZ0ZSgpKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQoKZ3JpZC5hcnJhbmdlKG1ieCwgZGNieCwgbnJvdz0xKQpgYGAKIyMjUmVsYXRpb25zaGlwIEJldHdlZW4gWWVhcnMgYXMgQ29taWMgQ2hhcmFjdGVyIGFuZCBOdW1iZXIgb2YgQXBwZWFyYW5jZXM6ClRoZSBmb2xsb3dpbmcgcmVncmVzc2lvbnMgcmVwcmVzZW50IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBob3cgbWFueSB5ZWFycyBhIGNoYXJhY3RlciBoYXMgYXBwZWFyZWQgaW4gdGhlIGNvbWljcyBhbmQgaG93IG1hbnkgdGltZXMgdGhleSBoYXZlIGFwcGVhcmVkIGluIHRoZSBjb21pY3MuIEhvd2V2ZXIsIG9uY2UgYWdhaW4sIG9ubHkgZnJlcXVlbnRseSByZWN1cnJpbmcgY2hhcmFjdGVycyB3ZXJlIGluY2x1ZGVkIGluIHRoaXMgbW9kZWwgKHdoZXJlIGFwcGVhcmFuY2VzIGVxdWFsIDE1MCBvciBncmVhdGVyKS4gCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiNNQVJWRUwKCm1sbTwtZ2dwbG90KGRhdGE9cG9wLCBhZXMoeD1ZRUFSUyx5PUFQUEVBUkFOQ0VTLCBmaWxsPUdlbmRlcikpKwogIGdlb21fcG9pbnQoKStzdGF0X3Ntb290aChtZXRob2Q9ImxtIiwgY29sb3I9J3JlZCcpKwogIGxhYnModGl0bGU9Ik1hcnZlbCIsIHk9ICJBcHBlYXJhbmNlcyIsIHg9IlllYXJzIikrCiAgdGhlbWVfdHVmdGUoKSsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCiNEQwpkY2xtPC1nZ3Bsb3QoZGF0YT1wb3AyLCBhZXMoeD1ZRUFSUyx5PUFQUEVBUkFOQ0VTLCBmaWxsPUdlbmRlcikpKwogIGdlb21fcG9pbnQoKStzdGF0X3Ntb290aChtZXRob2Q9ImxtIikrCiAgbGFicyh0aXRsZT0iREMiLCB5PSJBcHBlYXJhbmNlcyIsIHg9IlllYXJzIikrCiAgdGhlbWVfdHVmdGUoKSsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCmdyaWQuYXJyYW5nZShtbG0sIGRjbG0sIG5yb3c9MSkKYGBgCgoKIyMjTWVkaWFuIEFwcGVhcmFuY2UgZm9yIE1hbGUgYW5kIEZlbWFsZSBDaGFyYWN0ZXJzIGJ5IEFsaWdubWVudCBhbmQgQWxpdmUgU3RhdHVzOgpUaGUgYmVsb3cgcGxvdHMgZXhwbG9yZSB0aGUgbWVkaWFuIGdlbmRlciBkaWZmZXJlbmNlIGluIGFwcGVhcmFuY2VzLCB0YWtpbmcgaW50byBhY2NvdW50IHdoZXRoZXIgYSBjaGFyYWN0ZXIgaXMgbGl2aW5nIG9yIGRlY2Vhc2VkLCBhcyB3ZWxsIGFzIHdoZXRoZXIgYSBjaGFyYWN0ZXIgaXMgYmFkLCBnb29kLCBvciBuZXV0cmFsLgpgYGB7ciB3YXJuaW5nPUZBTFNFfQojTUFSVkVMCm1hcnZlbF9jb21pY3MyPC1tYXJ2ZWxfY29taWNzJT4lCiAgZmlsdGVyKCFpcy5uYShBTElHTikpCmludDwtZ2dwbG90KGRhdGE9bWFydmVsX2NvbWljczIpICsKICBhZXMoeCA9IEdlbmRlciwgY29sb3IgPSBBTElHTiwgZ3JvdXA9QUxJR04sIHkgPSBBUFBFQVJBTkNFUykgKyAgCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVkaWFuLCBnZW9tID0icG9pbnQiKSsKICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWRpYW4sIGdlb20gPSAibGluZSIpKwogICBmYWNldF93cmFwKCB+IEFMSVZFKSsKICBsYWJzKHRpdGxlPSJNYXJ2ZWwiLCB5PSJBcHBlYXJhbmNlcyAoTWVkaWFuKSIpK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQogCiNEQwpkY19jb21pY3MyPC1kY19jb21pY3MlPiUKICBmaWx0ZXIoIWlzLm5hKEFMSVZFKSwgIWlzLm5hKEFMSUdOKSwgQUxJR04hPSJSZWZvcm1lZCBDcmltaW5hbHMiKQppbnQyPC1nZ3Bsb3QoZGF0YT1kY19jb21pY3MyKSArCiAgYWVzKHggPSBHZW5kZXIsIGNvbG9yID0gQUxJR04sIGdyb3VwPUFMSUdOLCB5ID0gQVBQRUFSQU5DRVMpICsgIAogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lZGlhbiwgZ2VvbSA9InBvaW50IikrCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVkaWFuLCBnZW9tID0gImxpbmUiKSsKICAgZmFjZXRfd3JhcCggfiBBTElWRSkrCiAgbGFicyh0aXRsZT0iREMiLCB5PSJBcHBlYXJhbmNlcyAoTWVkaWFuKSIpK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQogIApncmlkLmFycmFuZ2UoaW50LCBpbnQyLCBucm93PTIpIApgYGAKCgojIyNHZW5kZXIgRGlmZmVyZW5jZSBpbiBNQVJWRUwgQXBwZWFyYW5jZXMgClVzaW5nIGEgcG9pc3NvbiBtb2RlbCwgdGhlIGJlbG93IHBsb3RzIHJlcHJlc2VudCB0aGUgbWVhbiBnZW5kZXIgZGlmZmVyZW5jZSBpbiBNQVJWRUwgYXBwZWFyYW5jZXMgd2hpbGUgY29udHJvbGxpbmcgZm9yIGFsaWdubWVudCwgYWxpdmUgc3RhdHVzLCBhbmQgbnVtYmVyIG9mIHllYXJzIHNpbmNlIGludHJvZHVjZWQuCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoWmVsaWcpCk1Qb2lzc29uIDwtIHplbGlnKEFQUEVBUkFOQ0VTIH4gR2VuZGVyK0FMSUdOK0FMSVZFK1lFQVJTLCBtb2RlbCA9ICJwb2lzc29uIiwgZGF0YSA9IG1hcnZlbF9jb21pY3MsIGNpdGUgPSBGKQoKeG08LXNldHgoTVBvaXNzb24sR2VuZGVyPSJNYWxlIikKeGY8LXNldHgoTVBvaXNzb24sR2VuZGVyPSJGZW1hbGUiKQpzPC1zaW0oTVBvaXNzb24seD14bSx4MT14ZikKZXZtIDwtIHMkZ2V0X3FpKHh2YWx1ZT0ieCIsIHFpPSJldiIpCmV2ZjwtcyRnZXRfcWkoeHZhbHVlPSJ4MSIscWk9ImV2IikKZGYgPC0gYXMuZGF0YS5mcmFtZShjYmluZChldmYsZXZtKSklPiUKICByZW5hbWUoIkZlbWFsZSI9VjEsICJNYWxlIj1WMikKdGlkZCA8LSBkZiAlPiUgCiAgZ2F0aGVyKEdlbmRlciwgQVBQRUFSQU5DRVMsIDE6MikKYXBwZWFyPC10aWRkJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSU+JSAKICBzdW1tYXJpc2UobWVhbiA9IG1lYW4oQVBQRUFSQU5DRVMpLCBzZCA9IHNkKEFQUEVBUkFOQ0VTKSkKCgptZGlmZjwtCiAgZ2dwbG90KGRhdGE9dGlkZCwgYWVzKHg9QVBQRUFSQU5DRVMpKSsKICBnZW9tX2RlbnNpdHkoZmlsbD0icmVkIikrCiAgZmFjZXRfd3JhcCh+R2VuZGVyKSsKICBnZW9tX3ZsaW5lKGRhdGE9YXBwZWFyLGFlcyh4aW50ZXJjZXB0PW1lYW4pLGNvbG9yPSJibGFjayIpICsgCiAgeGxhYigiQXZlcmFnZSBOdW1iZXIgb2YgQXBwZWFyYW5jZXMgKEV4cGVjdGVkIFZhbHVlKSIpKyAKICBnZ3RpdGxlKCJHZW5kZXIgRGlmZmVyZW5jZSBpbiBNYXJ2ZWwgQ29taWMgQXBwZWFyYW5jZXMiKSsKICB0aGVtZV9idygpK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQoKeCA8LSBzZXR4KE1Qb2lzc29uLCBHZW5kZXIgPSAiTWFsZSIpCngxIDwtIHNldHgoTVBvaXNzb24sIEdlbmRlciA9ICJGZW1hbGUiKQpzIDwtIHNpbShNUG9pc3NvbiwgeCA9IHgsIHgxID0geDEpCmZkbSA8LSBzJGdldF9xaSh4dmFsdWU9IngxIiwgcWk9ImZkIikKZ2VuZGVyZGlmZiA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKGZkbSkpJT4lCnJlbmFtZSgiR2VuZGVyIERpZmZlcmVuY2UiPVYxKQpnZW5kZXJfZGlmZjwtIGdlbmRlcmRpZmYgJT4lIAogIGdhdGhlcihjbGFzcywgc2ltdikKZ2Y8LWdlbmRlcl9kaWZmICU+JSAKICBncm91cF9ieShjbGFzcykgJT4lIAogIHN1bW1hcmlzZShtZWFuID0gbWVhbihzaW12KSwgc2QgPSBzZChzaW12KSkKCiBtX2RpZmY8LQogIGdncGxvdChkYXRhPWdlbmRlcl9kaWZmLCBhZXMoc2ltdikpICsgCiAgZ2VvbV9kZW5zaXR5KGZpbGw9InJlZCIpICsgCiAgZmFjZXRfZ3JpZCh+Y2xhc3MpICsgCiAgZ2VvbV92bGluZShkYXRhPWdmLGFlcyh4aW50ZXJjZXB0PW1lYW4pKSsKICBsYWJzKHggPSAiU2ltdWxhdGVkIEZpcnN0IERpZmZlcmVuY2UgKE1lYW4pIikrCiAgdGhlbWVfYncoKQoKZ3JpZC5hcnJhbmdlKG1kaWZmLCBtX2RpZmYsIG5yb3c9MikKCmBgYAoKIyMjR2VuZGVyIERpZmZlcmVuY2UgaW4gREMgQXBwZWFyYW5jZXM6IApVc2luZyBhIHBvaXNzb24gbW9kZWwsIHRoZSBiZWxvdyBwbG90cyByZXByZXNlbnQgdGhlIG1lYW4gZ2VuZGVyIGRpZmZlcmVuY2UgaW4gREMgYXBwZWFyYW5jZXMgd2hpbGUgY29udHJvbGxpbmcgZm9yIGFsaWdubWVudCwgYWxpdmUgc3RhdHVzLCBhbmQgbnVtYmVyIG9mIHllYXJzIHNpbmNlIGludHJvZHVjZWQuCmBgYHtyIHdhcm5pbmc9RkFMU0V9CkRDUG9pc3NvbiA8LSB6ZWxpZyhBUFBFQVJBTkNFUyB+IEdlbmRlcitBTElHTitBTElWRStZRUFSUywgbW9kZWwgPSAicG9pc3NvbiIsIGRhdGEgPSBkY19jb21pY3MsIGNpdGUgPSBGKQoKeG08LXNldHgoRENQb2lzc29uLCBHZW5kZXI9Ik1hbGUiKQp4Zjwtc2V0eChEQ1BvaXNzb24sIEdlbmRlcj0iRmVtYWxlIikKczwtc2ltKERDUG9pc3NvbiwgeD14bSwgeDE9eGYpCmV2bSA8LSBzJGdldF9xaSh4dmFsdWU9IngiLCBxaT0iZXYiKQpldmY8LXMkZ2V0X3FpKHh2YWx1ZT0ieDEiLHFpPSJldiIpCmRmMiA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKGV2Zixldm0pKSU+JQogIHJlbmFtZSgiRmVtYWxlIj1WMSwKICAgICAgICAiTWFsZSI9VjIpCnRpZGQyIDwtIGRmMiAlPiUgCiAgZ2F0aGVyKEdlbmRlciwgQVBQRUFSQU5DRVMsIDE6MikKYXBwZWFyMjwtdGlkZDIlPiUKICBncm91cF9ieShHZW5kZXIpJT4lIAogIHN1bW1hcmlzZShtZWFuID0gbWVhbihBUFBFQVJBTkNFUyksIHNkID0gc2QoQVBQRUFSQU5DRVMpKQoKbWRpZmYyPC0KICBnZ3Bsb3QoZGF0YT10aWRkMiwgYWVzKHg9QVBQRUFSQU5DRVMpKSsKICBnZW9tX2RlbnNpdHkoZmlsbD0iYmx1ZSIpKwogIGZhY2V0X3dyYXAofkdlbmRlcikrCiAgZ2VvbV92bGluZShkYXRhPWFwcGVhcjIsYWVzKHhpbnRlcmNlcHQ9bWVhbiksY29sb3I9ImJsYWNrIikgKyAKICB4bGFiKCJBdmVyYWdlIE51bWJlciBvZiBBcHBlYXJhbmNlcyAoRXhwZWN0ZWQgVmFsdWUpIikrIAogIGdndGl0bGUoIkdlbmRlciBEaWZmZXJlbmNlIGluIERDIENvbWljIEFwcGVhcmFuY2VzIikrCiAgdGhlbWVfYncoKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCnggPC0gc2V0eChEQ1BvaXNzb24sIEdlbmRlciA9ICJNYWxlIikKeDEgPC0gc2V0eChEQ1BvaXNzb24sIEdlbmRlciA9ICJGZW1hbGUiKQpzIDwtIHNpbShEQ1BvaXNzb24sIHggPSB4LCB4MSA9IHgxKQpmZCA8LSBzJGdldF9xaSh4dmFsdWU9IngxIiwgcWk9ImZkIikKZ2VuZGVyZGlmZjIgPC0gYXMuZGF0YS5mcmFtZShjYmluZChmZCkpJT4lCnJlbmFtZSgiR2VuZGVyIERpZmZlcmVuY2UiPVYxKQogZ2VuZGVyX2RpZmYyPC0gZ2VuZGVyZGlmZjIgJT4lIAogIGdhdGhlcihjbGFzcywgc2ltdikKZ2YyPC1nZW5kZXJfZGlmZjIgJT4lIAogIGdyb3VwX2J5KGNsYXNzKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKHNpbXYpLCBzZCA9IHNkKHNpbXYpKQoKbV9kaWZmMjwtCiAgZ2dwbG90KGRhdGE9Z2VuZGVyX2RpZmYyLCBhZXMoc2ltdikpICsgCiAgZ2VvbV9kZW5zaXR5KGZpbGw9ImJsdWUiKSArIAogIGZhY2V0X2dyaWQofmNsYXNzKSArIAogIGdlb21fdmxpbmUoZGF0YT1nZjIsYWVzKHhpbnRlcmNlcHQ9bWVhbikpKwogIGxhYnMoeCA9ICJTaW11bGF0ZWQgRmlyc3QgRGlmZmVyZW5jZSAoTWVhbikiKSsKICB0aGVtZV9idygpCgpncmlkLmFycmFuZ2UobWRpZmYyLCBtX2RpZmYyLCBucm93PTIpCgpgYGAKCgo=