Este cuaderno lo realicé para preparar mi ponencia en la Jornada Data Feminismo organizada por DataLab La Ciba el 8 de junio de 2021

Jornada Data Feminismo

Estás gráficas están están inspiradas en este estupendo tutorial sobre la evolución de un boxplot

Fuente de datos

Para la jornada analicé a los perfiles de un conjunto de mujeres tecnológicas de España seleccionadas por:

En total 389 perfiles únicos

Conexiones entre las mujeres seleccionadas

Estás mujeres están conectadas entre sí formando tres grupos: desarrolladoras, datos y divulgación

Caracterización de perfiles

Se caracterizaron según su actividad e impacto

Role

Representa su actividad e impacto.

Los altavoces consiguen llamar la atención y lo que dicen se propaga. Los networkers, retuiteadores y replicadores mueven los contenidos. Los monologuistas, aislados, automáticos y comunes aportan, pero tienen poca interacción.

T-index

Es una medida de impacto objetiva y fácil de realizar.

Número de seguidores

Indica su alcance. Como es un dato con valores muy dispersos de 1 a millones de seguidores se va a representar en logaritmo en base 10.

Relación de seguidores y seguidos

El coeficiente entre seguidores y seguidos muestra la simetría de la atención. Si es mayor que 1 indica que recibe más atención de los demás de la que muestra por otros.

Frecuencia de publicación

Muestra la actividad de los perfiles mediante la media de tweets diarios. Se calcula con el número total de tweets dividido entre los días transcurridos de su alta en Twitter.

Difusión

Refleja si los perfiles comparten o no información mediante RTs. El ratio se calcula como el número total de RT realizados dividido entre el número total de tweets originales. Cuanto más cerca está de 1 más comparte información.

Comentarios

Indica si los perfiles conversan mediante respuestas. El ratio se calcula como el número total de comentarios realizados dividido entre el número total de tweets originales. Cuanto más cerca está de 1 más conversa.

Conclusiones

Gráficas

Librerías necesarias

library(readr)
library(dplyr)
library(ggplot2)
library(scales)
library(reshape)
library(lubridate)
library(RColorBrewer)
locale(date_names = "es", date_format = "%AD", time_format = "%AT",
  decimal_mark = ".", grouping_mark = ",", tz = "Europe/Berlin",
  encoding = "UTF-8", asciify = FALSE)
<locale>
Numbers:  123,456.78
Formats:  %AD / %AT
Timezone: Europe/Berlin
Encoding: UTF-8
<date_names>
Days:   domingo (dom.), lunes (lun.), martes (mar.), miércoles (mié.), jueves (jue.), viernes (vie.), sábado (sáb.)
Months: enero (ene.), febrero (feb.), marzo (mar.), abril (abr.), mayo (may.), junio (jun.), julio (jul.), agosto
        (ago.), septiembre (sept.), octubre (oct.), noviembre (nov.), diciembre (dic.)
AM/PM:  a. m./p. m.
theme_set(theme_light(base_size = 12))

Leemos los datos

file= "https://raw.githubusercontent.com/congosto/congosto.github.io/master/mujerestech_plus_role.csv"

roles <- read_csv2 (file)
roles <- roles %>%
         filter(Role != "no tweets" &
                !is.na(Role)) %>%
         filter(!is.na (User))

print (roles)
roles_order <- c("Altavoz alto", "Altavoz medio", "Altavoz bajo", "Networker" , "Replicador", "Retuiteador", "Monologista", "Normal")
roles$Role <- factor (roles$Role, levels = roles_order)

Gráfica de distribución de roles

 roles %>%
  ggplot (aes(x =  Role, y= ..count../sum(..count..), fill= Role)) +
  geom_bar(show.legend = F, alpha = 0.5)+
  scale_fill_brewer( palette ='Dark2') + # Paleta divergente) +
  coord_flip() + 
  geom_text(aes(label = paste0(round(..count../sum(..count..)*100,1),"%"), 
                y= ..count../sum(..count..)), stat="count", vjust = -0.5, hjust = -0.25) +
  scale_x_discrete (limit = rev , expand = c(0,0))+
  scale_y_continuous (expand = c(0,0,0.5,0))+
  labs(x = "", y = "",
       title = "Roles",
       fill = "Tipo tweet")+
  theme (plot.title=element_text( vjust=1.25,hjust = 0.5),
       axis.title.y=element_blank(),
       axis.title.x=element_blank(),
       axis.text.x=element_blank(),
       panel.border = element_blank(),
       panel.grid.major=element_blank(),
       panel.grid.minor=element_blank()) 

Función para generar las gráficas de distribución

distribucion <- function (df,indicator,text_indicator, title, offset) {
  
df <- df %>%
      mutate (indicator=df[[`indicator`]])
  
df_indicator <- df %>%
                group_by(Role) %>%
                summarise(mean_indicator  =  mean (indicator),
                           indicator = indicator)  
role_avg <- 
  df %>%
  summarize(avg = mean(indicator, na.rm = T)) %>%
  pull(avg)

arrows <-
  tibble(
    y1 = c(1.1, 4.62),
    y2 = c(0.6, 5),
    x1 = c(role_avg + offset, role_avg + offset),
    x2 = c(role_avg + 0, role_avg + offset)
  )


  ggplot(df_indicator, aes(x = indicator, y = Role, color = Role)) +
    geom_vline(aes(xintercept = role_avg), color = "gray70", size = 0.6) +
    geom_jitter(size = 2, alpha = 0.25, width = 0.2) +
    stat_summary(fun = mean, geom = "point", size = 5) +
    stat_summary(fun = mean, geom = "text", 
                 aes(label=sprintf("%1.1f", ..x..)), 
                 position=position_nudge(y=0.3), 
                 color = "gray20", size=3.5) +
    geom_text(data = df_indicator %>% filter (Role == "Altavoz medio")
                    %>% select (Role,mean_indicator) %>%
                    distinct(Role,mean_indicator),
                 aes(x=mean_indicator,y=Role,label=paste("media")), 
                 position=position_nudge(y = -0.3, ), 
                 color = "gray20", size=3.5) +
    geom_segment(aes(y = Role, yend = Role,
                     x = role_avg, xend = mean_indicator),
                 size = 0.8) +
    annotate("text", x = role_avg+offset, y = 1.3, size = 3.5, color = "gray20", lineheight = .9,
             label = glue::glue("Media {text_indicator}:{round(role_avg, 1)}")) +
    annotate("text", x = role_avg+offset, y = 4.5,  size = 3.5, color = "gray20",
             label = glue::glue("{text_indicator} por perfil")) +
    geom_curve(data = arrows, aes(x = x1, y = y1, xend = x2, yend = y2),
             arrow = arrow(length = unit(0.08, "inch")), size = 0.5,
             color = "gray20", curvature = -0.3) +
    scale_y_discrete(limits = rev) +
    #scale_y_continuous( expand = c(0.005, 0.005)) +
    scale_colour_brewer( palette ='Dark2') + # Paleta divergente) +
    labs(title = title,
         y = NULL, x = text_indicator) +
    theme(plot.title=element_text( vjust=1.25,hjust = 0.5),
      legend.position = "none",
      panel.grid = element_blank()
    )

}

Distribución de T-Index

    p <- distribucion (roles,"h-index","T-index", "T-index por tipo de role",10)
    plot (p)

Distribución de Followers (escala logarítmica de 10)

    p <- distribucion (roles,"log_followers","log(Followers)", "Followers por tipo de role (escala logarítmica en base 10)",0.8)
    plot (p)

Distribución de Followers/Following

    p <- distribucion (roles,"Followers/Following","F/F", "Followers/Following por tipo de role",7)
    plot (p)

Distribución de la frecuencia de publicación

Media diaria

    p <- distribucion (roles,"Frequency","Tweets/día", "Tweets diarios de media por tipo de role",8)
    plot (p)

Distribución de los retweets realizados

    p <- distribucion (roles,"Ratio_RT_out","Ratio RT-out", "Ratio de retweets realizados por tipo de role",0.3)
    plot (p)

Distribución de las respuestas realizadas

    p <- distribucion (roles,"Ratio Reply_out","Ratio reply-out", "Ratio de respuestas realizadas por tipo de role",0.25)
    plot (p)

    
    x <- 10^2.4
  
LS0tDQp0aXRsZTogIk11amVyZXMgVGVjbm9sw7NnaWNhcyBlbiBFc3Bhw7FhIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KDQpFc3RlIGN1YWRlcm5vIGxvIHJlYWxpY8OpIHBhcmEgcHJlcGFyYXIgbWkgcG9uZW5jaWEgZW4gbGEgSm9ybmFkYSBEYXRhIEZlbWluaXNtbyBvcmdhbml6YWRhIHBvciBbRGF0YUxhYiBMYSBDaWJhXShodHRwczovL2xhY2liYS5ncmFtZW5ldC5jYXQvZXMvbXVsdGltZWRpYS9ub3RpY2lhcy1sYS1jaWJhL2RldGFsbGUtaW5mby9uZXdzL2RhdGEtZmVtaW5pc20tdHJhbnNmb3JtYWNpby1kaWdpdGFsLWRlcy1kZS1sYS1wZXJzcGVjdGl2YS1mZW1pbmlzdGEvKSBlbCA4IGRlIGp1bmlvIGRlIDIwMjENCg0KIVtKb3JuYWRhIERhdGEgRmVtaW5pc21vXShwb3J0YWRhLmpwZykNCg0KRXN0w6FzIGdyw6FmaWNhcyBlc3TDoW4gZXN0w6FuIGluc3BpcmFkYXMgZW4gW2VzdGUgZXN0dXBlbmRvIHR1dG9yaWFsIHNvYnJlIGxhIGV2b2x1Y2nDs24gZGUgdW4gYm94cGxvdF0oaHR0cHM6Ly93d3cuY2Vkcmljc2NoZXJlci5jb20vMjAxOS8wNS8xNy90aGUtZXZvbHV0aW9uLW9mLWEtZ2dwbG90LWVwLi0xLykgIVtdKA0KaHR0cHM6Ly9kMzN3dWJyZmtpMGw2OC5jbG91ZGZyb250Lm5ldC8xZTcwMzMzOTNhMmM3MGRjMTI1NWM1ZDBmMWM1NjNlOTQ1NTE5MjUxLzYxMDM1L2ltZy9ldm9sLWdncGxvdC9ldm9sLWdncGxvdC0xLmdpZikNCg0KIyMgRnVlbnRlIGRlIGRhdG9zDQoNClBhcmEgbGEgam9ybmFkYSBhbmFsaWPDqSBhIGxvcyBwZXJmaWxlcyBkZSAgdW4gY29uanVudG8gZGUgbXVqZXJlcyB0ZWNub2zDs2dpY2FzIGRlIEVzcGHDsWEgc2VsZWNjaW9uYWRhcyBwb3I6DQoNCi0gMTIyIHBlcmZpbGVzIG9idGVuaWRvcyBkZSBbTGEgbGlzdGEgZGUgbXVqZXJlcyB0ZWNub2zDs2dpY2FzXShodHRwczovL3R3aXR0ZXIuY29tL3ZpY3Rvcmlhbm9pL3N0YXR1cy85NTUxMzkxNDYxMzc0NTY2NDApIGdlbmVyYWRhIHBvciBbVmljdG9yaWFub2ldKGh0dHBzOi8vdHdpdHRlci5jb20vdmljdG9yaWFub2kpDQoNCi0gQcOxYWRpZW5kbyBtw6FzIHBlcmZpbGVzIGRlc2RlIGxhcyBsaXN0YXMNCg0KICAtIEF1ZGllbnNlQ28gLSB0M2NoZmVzdDIwMTkNCiAgLSBBbGljaWFwb21hcmVzIC0gdGVjaC1kYXRhDQogIC0gQXNzYXJhc3VhIC0gZGF0YS1hbmFseXRpY3MNCiAgLSBQaW5nbXVqZXJlcyDigJMgZGVzYXJyb2xsYWRvcmFzDQogIC0gVmljdG9yaWFub2kg4oCTIGNvbXBsZXhpdHkNCiAgLSBWaWN0b3JpYW5vaSAtIERhdGEtU3BhaW4NCi0gU2VsZWNjaW9uYW5kbyBsb3MgcGVyZmlsZXMgbcOhcyBkZXN0YWNhZG9zIHF1ZSBzb24gc2VndWlkb3MgcG9yIGxvcyBldmVudG9zIHRlY25vbMOzZ2ljb3MgZGUgbXVqZXJlcw0KDQpFbiB0b3RhbCAzODkgcGVyZmlsZXMgw7puaWNvcw0KDQojIyBDb25leGlvbmVzIGVudHJlIGxhcyBtdWplcmVzIHNlbGVjY2lvbmFkYXMNCg0KRXN0w6FzIG11amVyZXMgZXN0w6FuIGNvbmVjdGFkYXMgZW50cmUgc8OtIGZvcm1hbmRvIHRyZXMgZ3J1cG9zOiBkZXNhcnJvbGxhZG9yYXMsIGRhdG9zIHkgZGl2dWxnYWNpw7NuDQoNCiFbXShtdWplcmVzX3RlY2hfY29uZXhpb25lcy5qcGcpDQoNCiMjIENhcmFjdGVyaXphY2nDs24gZGUgcGVyZmlsZXMNCg0KU2UgY2FyYWN0ZXJpemFyb24gc2Vnw7puIHN1IGFjdGl2aWRhZCBlIGltcGFjdG8NCg0KIyMjIFJvbGUNCg0KUmVwcmVzZW50YSBzdSBhY3RpdmlkYWQgZSBpbXBhY3RvLiANCg0KIVtdKHJvbGVzLlBORykNCg0KTG9zIGFsdGF2b2NlcyBjb25zaWd1ZW4gbGxhbWFyIGxhIGF0ZW5jacOzbiB5IGxvIHF1ZSBkaWNlbiBzZSBwcm9wYWdhLiBMb3MgbmV0d29ya2VycywgcmV0dWl0ZWFkb3JlcyB5IHJlcGxpY2Fkb3JlcyAgbXVldmVuIGxvcyBjb250ZW5pZG9zLiBMb3MgbW9ub2xvZ3Vpc3RhcywgYWlzbGFkb3MsIGF1dG9tw6F0aWNvcyB5IGNvbXVuZXMgYXBvcnRhbiwgcGVybyB0aWVuZW4gcG9jYSBpbnRlcmFjY2nDs24uDQoNCiMjIyBULWluZGV4DQoNCkVzIHVuYSBtZWRpZGEgZGUgaW1wYWN0byBvYmpldGl2YSB5IGbDoWNpbCBkZSByZWFsaXphci4gDQoNCiFbXSh0LWluZGV4LlBORykNCg0KDQojIyMgTsO6bWVybyBkZSBzZWd1aWRvcmVzDQoNCkluZGljYSBzdSBhbGNhbmNlLiBDb21vIGVzIHVuIGRhdG8gY29uIHZhbG9yZXMgbXV5IGRpc3BlcnNvcyBkZSAxIGEgbWlsbG9uZXMgZGUgc2VndWlkb3JlcyBzZSB2YSBhIHJlcHJlc2VudGFyIGVuIGxvZ2FyaXRtbyBlbiBiYXNlIDEwLg0KDQoNCiMjIyBSZWxhY2nDs24gZGUgc2VndWlkb3JlcyB5IHNlZ3VpZG9zIA0KDQpFbCBjb2VmaWNpZW50ZSBlbnRyZSBzZWd1aWRvcmVzIHkgc2VndWlkb3MgbXVlc3RyYSBsYSBzaW1ldHLDrWEgZGUgbGEgYXRlbmNpw7NuLiBTaSBlcyBtYXlvciBxdWUgMSBpbmRpY2EgcXVlIHJlY2liZSBtw6FzIGF0ZW5jacOzbiBkZSBsb3MgZGVtw6FzIGRlIGxhIHF1ZSBtdWVzdHJhIHBvciBvdHJvcy4NCg0KDQoNCiMjIyBGcmVjdWVuY2lhIGRlIHB1YmxpY2FjacOzbg0KDQpNdWVzdHJhIGxhIGFjdGl2aWRhZCBkZSBsb3MgcGVyZmlsZXMgbWVkaWFudGUgbGEgbWVkaWEgZGUgdHdlZXRzIGRpYXJpb3MuIFNlIGNhbGN1bGEgY29uIGVsIG7Dum1lcm8gdG90YWwgZGUgdHdlZXRzIGRpdmlkaWRvIGVudHJlIGxvcyBkw61hcyB0cmFuc2N1cnJpZG9zIGRlIHN1IGFsdGEgZW4gVHdpdHRlci4NCg0KIyMjIERpZnVzacOzbg0KDQpSZWZsZWphIHNpIGxvcyBwZXJmaWxlcyBjb21wYXJ0ZW4gbyBubyBpbmZvcm1hY2nDs24gbWVkaWFudGUgUlRzLiBFbCByYXRpbyBzZSBjYWxjdWxhIGNvbW8gZWwgbsO6bWVybyB0b3RhbCBkZSBSVCByZWFsaXphZG9zIGRpdmlkaWRvIGVudHJlIGVsIG7Dum1lcm8gdG90YWwgZGUgdHdlZXRzIG9yaWdpbmFsZXMuIEN1YW50byBtw6FzIGNlcmNhIGVzdMOhIGRlIDEgbcOhcyBjb21wYXJ0ZSBpbmZvcm1hY2nDs24uDQoNCiMjIyBDb21lbnRhcmlvcw0KDQpJbmRpY2Egc2kgbG9zIHBlcmZpbGVzIGNvbnZlcnNhbiBtZWRpYW50ZSByZXNwdWVzdGFzLiBFbCByYXRpbyBzZSBjYWxjdWxhIGNvbW8gZWwgbsO6bWVybyB0b3RhbCBkZSBjb21lbnRhcmlvcyByZWFsaXphZG9zIGRpdmlkaWRvIGVudHJlIGVsIG7Dum1lcm8gdG90YWwgZGUgdHdlZXRzIG9yaWdpbmFsZXMuIEN1YW50byBtw6FzIGNlcmNhIGVzdMOhIGRlIDEgbcOhcyBjb252ZXJzYS4NCg0KIyMgQ29uY2x1c2lvbmVzDQoNCi0gTGFzIGNvbmV4aW9uZXMgc2UgaGFuIHZlcnRlYnJhZG8gcG9yIGV2ZW50b3MgcHJlc2VuY2lhbGVzDQotIExvcyBwZXJmaWxlcyBtw6FzIGRlc3RhY2Fkb3Mgc29uIGxvcyBxdWUgaGFuIHBhcnRpY2lwYWRvIGVuIGxhIG9yZ2FuaXphY2nDs24gbyBjw7NtbyBwb25lbnRlcw0KLSBFbCByZXN1bHRhZG8gZXMgdW5hIHJlZCBjb25leGlvbmFkYSBwb3IgdGVtw6F0aWNhcyAoZGF0b3MsIGRlc2Fycm9sbG8geSBkaXZ1bGdhY2nDs24pDQotIEhheSB1biAyMSw1JSBkZSBtb25vbG9ndWlzdGFzIChwdWJsaWNhbiBzaW4gcmVwZXJjdXNpw7NuKS4gRXMgdW5hIGRlYmlsaWRhZCBkZSBsYSByZWQsIHVuIGVzZnVlcnpvIHF1ZSBubyBzZSB2YWxvcmEuDQotIE3DoXMgZGUgdW4gdGVyY2lvIGRlIGxhIHJlZCBlcyBuZXR3b3JrZXIsIGVzIHVuYSBmb3J0YWxlemEgcG9ycXVlIG11ZXZlbiBjb250ZW5pZG9zIHkgcGFydGljaXBhbiBlbiBjb252ZXJzYWNpb25lcw0KLSBFbCBpbXBhY3RvIG1lZGlvIChULWluZGV4ID0gOSkgZXN0w6EgcG9yIGVuY2ltYSBkZWwgaW1wYWN0byBtZWRpbyBnbG9iYWwNCi0gRGVzcGllcnRhbiBhdGVuY2nDs24uIFN1IG1lZGlhIHNlZ3VpZG9yZXMvc2VndWlkb3MgZXMgZGUgMywxLiBFcyBkZWNpciwgdGllbmUgdHJlcyB2ZWNlcyBtw6FzIHNlZ3VpZG9yZXMgcXVlIHNlZ3VpZG9zDQotIFNvbiBhY3RpdmFzLiBQdWJsaWNhbiB1bmEgbWVkaWEgZGUgNSB0d2VldHMgZGlhcmlvcw0KLSBDb21wYXJ0ZW4gaW5mb3JtYWNpw7NuLCBFbCA0MCUgZGUgc3VzIHR3ZWV0cyBzb24gUlRzDQotIENvbnZlcnNhbiwgZWwgMzAlIGRlIHN1cyB0d2VldHMgc29uIGNvbWVudGFyaW9zDQoNCg0KDQoNCmBgYHtyIHNldHVwLCAJZWNobyA9IFRSVUUsbWVzc2FnZSA9IEZBTFNFLAl3YXJuaW5nID0gRkFMU0UsaW5jbHVkZT1GQUxTRSwgY2FjaGUgPSBGQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldCh3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkNCnJlcXVpcmUoImtuaXRyIikNCiMjIHNldHRpbmcgd29ya2luZyBkaXJlY3RvcnkNCg0KIw0KYGBgDQoNCiMjIEdyw6FmaWNhcw0KDQojIyMgTGlicmVyw61hcyBuZWNlc2FyaWFzDQoNCg0KYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHNjYWxlcykNCmxpYnJhcnkocmVzaGFwZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpsb2NhbGUoZGF0ZV9uYW1lcyA9ICJlcyIsIGRhdGVfZm9ybWF0ID0gIiVBRCIsIHRpbWVfZm9ybWF0ID0gIiVBVCIsDQogIGRlY2ltYWxfbWFyayA9ICIuIiwgZ3JvdXBpbmdfbWFyayA9ICIsIiwgdHogPSAiRXVyb3BlL0JlcmxpbiIsDQogIGVuY29kaW5nID0gIlVURi04IiwgYXNjaWlmeSA9IEZBTFNFKQ0KdGhlbWVfc2V0KHRoZW1lX2xpZ2h0KGJhc2Vfc2l6ZSA9IDEyKSkNCg0KYGBgDQoNCiMjIyBMZWVtb3MgbG9zIGRhdG9zDQoNCmBgYHtyIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmZpbGU9ICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vY29uZ29zdG8vY29uZ29zdG8uZ2l0aHViLmlvL21hc3Rlci9tdWplcmVzdGVjaF9wbHVzX3JvbGUuY3N2Ig0KDQpyb2xlcyA8LSByZWFkX2NzdjIgKGZpbGUpDQpyb2xlcyA8LSByb2xlcyAlPiUNCiAgICAgICAgIGZpbHRlcihSb2xlICE9ICJubyB0d2VldHMiICYNCiAgICAgICAgICAgICAgICAhaXMubmEoUm9sZSkpICU+JQ0KICAgICAgICAgZmlsdGVyKCFpcy5uYSAoVXNlcikpDQoNCnByaW50IChyb2xlcykNCnJvbGVzX29yZGVyIDwtIGMoIkFsdGF2b3ogYWx0byIsICJBbHRhdm96IG1lZGlvIiwgIkFsdGF2b3ogYmFqbyIsICJOZXR3b3JrZXIiICwgIlJlcGxpY2Fkb3IiLCAiUmV0dWl0ZWFkb3IiLCAiTW9ub2xvZ2lzdGEiLCAiTm9ybWFsIikNCnJvbGVzJFJvbGUgPC0gZmFjdG9yIChyb2xlcyRSb2xlLCBsZXZlbHMgPSByb2xlc19vcmRlcikNCmBgYA0KDQojIyMgR3LDoWZpY2EgZGUgZGlzdHJpYnVjacOzbiBkZSByb2xlcw0KDQoNCg0KYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIHJvbGVzICU+JQ0KICBnZ3Bsb3QgKGFlcyh4ID0gIFJvbGUsIHk9IC4uY291bnQuLi9zdW0oLi5jb3VudC4uKSwgZmlsbD0gUm9sZSkpICsNCiAgZ2VvbV9iYXIoc2hvdy5sZWdlbmQgPSBGLCBhbHBoYSA9IDAuNSkrDQogIHNjYWxlX2ZpbGxfYnJld2VyKCBwYWxldHRlID0nRGFyazInKSArICMgUGFsZXRhIGRpdmVyZ2VudGUpICsNCiAgY29vcmRfZmxpcCgpICsgDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAocm91bmQoLi5jb3VudC4uL3N1bSguLmNvdW50Li4pKjEwMCwxKSwiJSIpLCANCiAgICAgICAgICAgICAgICB5PSAuLmNvdW50Li4vc3VtKC4uY291bnQuLikpLCBzdGF0PSJjb3VudCIsIHZqdXN0ID0gLTAuNSwgaGp1c3QgPSAtMC4yNSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlIChsaW1pdCA9IHJldiAsIGV4cGFuZCA9IGMoMCwwKSkrDQogIHNjYWxlX3lfY29udGludW91cyAoZXhwYW5kID0gYygwLDAsMC41LDApKSsNCiAgbGFicyh4ID0gIiIsIHkgPSAiIiwNCiAgICAgICB0aXRsZSA9ICJSb2xlcyIsDQogICAgICAgZmlsbCA9ICJUaXBvIHR3ZWV0IikrDQogIHRoZW1lIChwbG90LnRpdGxlPWVsZW1lbnRfdGV4dCggdmp1c3Q9MS4yNSxoanVzdCA9IDAuNSksDQogICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgcGFuZWwuZ3JpZC5tYWpvcj1lbGVtZW50X2JsYW5rKCksDQogICAgICAgcGFuZWwuZ3JpZC5taW5vcj1lbGVtZW50X2JsYW5rKCkpIA0KYGBgDQoNCg0KIyMjIEZ1bmNpw7NuIHBhcmEgZ2VuZXJhciBsYXMgZ3LDoWZpY2FzIGRlIGRpc3RyaWJ1Y2nDs24NCg0KYGBge3IgZWNobz1UUlVFLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KZGlzdHJpYnVjaW9uIDwtIGZ1bmN0aW9uIChkZixpbmRpY2F0b3IsdGV4dF9pbmRpY2F0b3IsIHRpdGxlLCBvZmZzZXQpIHsNCiAgDQpkZiA8LSBkZiAlPiUNCiAgICAgIG11dGF0ZSAoaW5kaWNhdG9yPWRmW1tgaW5kaWNhdG9yYF1dKQ0KICANCmRmX2luZGljYXRvciA8LSBkZiAlPiUNCiAgICAgICAgICAgICAgICBncm91cF9ieShSb2xlKSAlPiUNCiAgICAgICAgICAgICAgICBzdW1tYXJpc2UobWVhbl9pbmRpY2F0b3IgID0gIG1lYW4gKGluZGljYXRvciksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2F0b3IgPSBpbmRpY2F0b3IpICANCnJvbGVfYXZnIDwtIA0KICBkZiAlPiUNCiAgc3VtbWFyaXplKGF2ZyA9IG1lYW4oaW5kaWNhdG9yLCBuYS5ybSA9IFQpKSAlPiUNCiAgcHVsbChhdmcpDQoNCmFycm93cyA8LQ0KICB0aWJibGUoDQogICAgeTEgPSBjKDEuMSwgNC42MiksDQogICAgeTIgPSBjKDAuNiwgNSksDQogICAgeDEgPSBjKHJvbGVfYXZnICsgb2Zmc2V0LCByb2xlX2F2ZyArIG9mZnNldCksDQogICAgeDIgPSBjKHJvbGVfYXZnICsgMCwgcm9sZV9hdmcgKyBvZmZzZXQpDQogICkNCg0KDQogIGdncGxvdChkZl9pbmRpY2F0b3IsIGFlcyh4ID0gaW5kaWNhdG9yLCB5ID0gUm9sZSwgY29sb3IgPSBSb2xlKSkgKw0KICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSByb2xlX2F2ZyksIGNvbG9yID0gImdyYXk3MCIsIHNpemUgPSAwLjYpICsNCiAgICBnZW9tX2ppdHRlcihzaXplID0gMiwgYWxwaGEgPSAwLjI1LCB3aWR0aCA9IDAuMikgKw0KICAgIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLCBnZW9tID0gInBvaW50Iiwgc2l6ZSA9IDUpICsNCiAgICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgZ2VvbSA9ICJ0ZXh0IiwgDQogICAgICAgICAgICAgICAgIGFlcyhsYWJlbD1zcHJpbnRmKCIlMS4xZiIsIC4ueC4uKSksIA0KICAgICAgICAgICAgICAgICBwb3NpdGlvbj1wb3NpdGlvbl9udWRnZSh5PTAuMyksIA0KICAgICAgICAgICAgICAgICBjb2xvciA9ICJncmF5MjAiLCBzaXplPTMuNSkgKw0KICAgIGdlb21fdGV4dChkYXRhID0gZGZfaW5kaWNhdG9yICU+JSBmaWx0ZXIgKFJvbGUgPT0gIkFsdGF2b3ogbWVkaW8iKQ0KICAgICAgICAgICAgICAgICAgICAlPiUgc2VsZWN0IChSb2xlLG1lYW5faW5kaWNhdG9yKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgZGlzdGluY3QoUm9sZSxtZWFuX2luZGljYXRvciksDQogICAgICAgICAgICAgICAgIGFlcyh4PW1lYW5faW5kaWNhdG9yLHk9Um9sZSxsYWJlbD1wYXN0ZSgibWVkaWEiKSksIA0KICAgICAgICAgICAgICAgICBwb3NpdGlvbj1wb3NpdGlvbl9udWRnZSh5ID0gLTAuMywgKSwgDQogICAgICAgICAgICAgICAgIGNvbG9yID0gImdyYXkyMCIsIHNpemU9My41KSArDQogICAgZ2VvbV9zZWdtZW50KGFlcyh5ID0gUm9sZSwgeWVuZCA9IFJvbGUsDQogICAgICAgICAgICAgICAgICAgICB4ID0gcm9sZV9hdmcsIHhlbmQgPSBtZWFuX2luZGljYXRvciksDQogICAgICAgICAgICAgICAgIHNpemUgPSAwLjgpICsNCiAgICBhbm5vdGF0ZSgidGV4dCIsIHggPSByb2xlX2F2ZytvZmZzZXQsIHkgPSAxLjMsIHNpemUgPSAzLjUsIGNvbG9yID0gImdyYXkyMCIsIGxpbmVoZWlnaHQgPSAuOSwNCiAgICAgICAgICAgICBsYWJlbCA9IGdsdWU6OmdsdWUoIk1lZGlhIHt0ZXh0X2luZGljYXRvcn06e3JvdW5kKHJvbGVfYXZnLCAxKX0iKSkgKw0KICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IHJvbGVfYXZnK29mZnNldCwgeSA9IDQuNSwgIHNpemUgPSAzLjUsIGNvbG9yID0gImdyYXkyMCIsDQogICAgICAgICAgICAgbGFiZWwgPSBnbHVlOjpnbHVlKCJ7dGV4dF9pbmRpY2F0b3J9IHBvciBwZXJmaWwiKSkgKw0KICAgIGdlb21fY3VydmUoZGF0YSA9IGFycm93cywgYWVzKHggPSB4MSwgeSA9IHkxLCB4ZW5kID0geDIsIHllbmQgPSB5MiksDQogICAgICAgICAgICAgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDAuMDgsICJpbmNoIikpLCBzaXplID0gMC41LA0KICAgICAgICAgICAgIGNvbG9yID0gImdyYXkyMCIsIGN1cnZhdHVyZSA9IC0wLjMpICsNCiAgICBzY2FsZV95X2Rpc2NyZXRlKGxpbWl0cyA9IHJldikgKw0KICAgICNzY2FsZV95X2NvbnRpbnVvdXMoIGV4cGFuZCA9IGMoMC4wMDUsIDAuMDA1KSkgKw0KICAgIHNjYWxlX2NvbG91cl9icmV3ZXIoIHBhbGV0dGUgPSdEYXJrMicpICsgIyBQYWxldGEgZGl2ZXJnZW50ZSkgKw0KICAgIGxhYnModGl0bGUgPSB0aXRsZSwNCiAgICAgICAgIHkgPSBOVUxMLCB4ID0gdGV4dF9pbmRpY2F0b3IpICsNCiAgICB0aGVtZShwbG90LnRpdGxlPWVsZW1lbnRfdGV4dCggdmp1c3Q9MS4yNSxoanVzdCA9IDAuNSksDQogICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpDQogICAgKQ0KDQp9DQpgYGANCg0KDQojIyMgRGlzdHJpYnVjacOzbiBkZSBULUluZGV4DQoNCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OCwgd2FybmluZz1GQUxTRX0NCiAgICBwIDwtIGRpc3RyaWJ1Y2lvbiAocm9sZXMsImgtaW5kZXgiLCJULWluZGV4IiwgIlQtaW5kZXggcG9yIHRpcG8gZGUgcm9sZSIsMTApDQogICAgcGxvdCAocCkNCmBgYA0KDQojIyMgRGlzdHJpYnVjacOzbiBkZSBGb2xsb3dlcnMgKGVzY2FsYSBsb2dhcsOtdG1pY2EgZGUgMTApDQoNCmBgYHtyICBlY2hvPVRSVUUsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTYsIHdhcm5pbmc9RkFMU0V9DQogICAgcCA8LSBkaXN0cmlidWNpb24gKHJvbGVzLCJsb2dfZm9sbG93ZXJzIiwibG9nKEZvbGxvd2VycykiLCAiRm9sbG93ZXJzIHBvciB0aXBvIGRlIHJvbGUgKGVzY2FsYSBsb2dhcsOtdG1pY2EgZW4gYmFzZSAxMCkiLDAuOCkNCiAgICBwbG90IChwKQ0KDQpgYGANCg0KDQoNCiMjIyBEaXN0cmlidWNpw7NuIGRlIEZvbGxvd2Vycy9Gb2xsb3dpbmcNCg0KYGBge3IgIGVjaG89VFJVRSxmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02LCB3YXJuaW5nPUZBTFNFfQ0KICAgIHAgPC0gZGlzdHJpYnVjaW9uIChyb2xlcywiRm9sbG93ZXJzL0ZvbGxvd2luZyIsIkYvRiIsICJGb2xsb3dlcnMvRm9sbG93aW5nIHBvciB0aXBvIGRlIHJvbGUiLDcpDQogICAgcGxvdCAocCkNCmBgYA0KDQoNCg0KIyMjIERpc3RyaWJ1Y2nDs24gZGUgbGEgZnJlY3VlbmNpYSBkZSBwdWJsaWNhY2nDs24NCg0KTWVkaWEgZGlhcmlhDQoNCmBgYHtyICBlY2hvPVRSVUUsZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Niwgd2FybmluZz1GQUxTRX0NCiAgICBwIDwtIGRpc3RyaWJ1Y2lvbiAocm9sZXMsIkZyZXF1ZW5jeSIsIlR3ZWV0cy9kw61hIiwgIlR3ZWV0cyBkaWFyaW9zIGRlIG1lZGlhIHBvciB0aXBvIGRlIHJvbGUiLDgpDQogICAgcGxvdCAocCkNCmBgYA0KDQojIyMgRGlzdHJpYnVjacOzbiBkZSBsb3MgcmV0d2VldHMgcmVhbGl6YWRvcw0KDQpgYGB7ciAgZWNobz1UUlVFLGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTYsIHdhcm5pbmc9RkFMU0V9DQogICAgcCA8LSBkaXN0cmlidWNpb24gKHJvbGVzLCJSYXRpb19SVF9vdXQiLCJSYXRpbyBSVC1vdXQiLCAiUmF0aW8gZGUgcmV0d2VldHMgcmVhbGl6YWRvcyBwb3IgdGlwbyBkZSByb2xlIiwwLjMpDQogICAgcGxvdCAocCkNCmBgYA0KDQojIyMgRGlzdHJpYnVjacOzbiBkZSBsYXMgcmVzcHVlc3RhcyByZWFsaXphZGFzDQoNCmBgYHtyICBlY2hvPVRSVUUsZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Niwgd2FybmluZz1GQUxTRX0NCiAgICBwIDwtIGRpc3RyaWJ1Y2lvbiAocm9sZXMsIlJhdGlvIFJlcGx5X291dCIsIlJhdGlvIHJlcGx5LW91dCIsICJSYXRpbyBkZSByZXNwdWVzdGFzIHJlYWxpemFkYXMgcG9yIHRpcG8gZGUgcm9sZSIsMC4yNSkNCiAgICBwbG90IChwKQ0KYGBg