Aim: to explore effect heterogeneity in social influence between actors within clubs, according to running level and gender.

Our model already considers rather many parameters given the information available in the data-set. We have limited power to detect behavior evolution effects, as the number of data points is at the order \(n\). If we consider network evolution, we have data points of the order \(n^2\). Therefore, our data does now allow for backward elimination (i.e., estimating the ‘full model’, including all interactions simultaneously, and stepwisely removing effects that are not significant according to some criterion).

Instead, we estimate our main model and assess the interactions by testing their parameters \((H_0:\theta=0)\) without estimating them, using score-type tests, a procedure proposed by Schweinberger (2012). Score-type tests indicate whether and which of the tested effects will improve a model, when included. We will consider the results of the (one-sided) one-parameter test. Its test statistic is standard normally distributed.

If we find interaction effects that would improve the model, we will estimate these effects simultaneously with the other model effects. Thus, we use a two-step exploratory procedure.


Getting started

clean up

rm (list = ls( ))
#gc()


general custom functions

  • fpackage.check: Check if packages are installed (and install if not) in R (source)
  • fload.R: function to load R-objects under new names.
fpackage.check <- function(packages) {
    lapply(packages, FUN = function(x) {
        if (!require(x, character.only = TRUE)) {
            install.packages(x, dependencies = TRUE)
            library(x, character.only = TRUE)
        }
    })
}

fload.R  <- function(fileName){
  load(fileName)
  get(ls()[ls() != "fileName"])
}

colorize <- function(x, color) {sprintf("<span style='color: %s;'>%s</span>", color, x) }

necessary packages

  • RSiena
  • parallel: utilize more cores
packages = c("RSiena", "parallel")

fpackage.check(packages)


Down below, we focus on running frequency; but the scripts can be modified to model running volume.

read in RSiena data objects

load("clubdata_rsiena_freq.Rdata")
#load("clubdata_rsiena_vol.Rdata")



Approach

We probe for moderational effects of:

  • gender: to see whether receiving kudos or the activities of alters have differential effects for males and females;
  • running level: to see whether runners with different running experience are more/less s usceptible to influence. We interact the influence effects with the linear shape effect (which represents ego’s current running) and a time-constant actor-covariate representing the number of years that actors were active on Strava (labeled novice).

We discuss here why we use the linear shape effect, and why we use avSim rather than avAttLower in the interaction models.

We focus on 2 influence effects, and 3 interactions; thus a total of 6 models for each club.

Step 1: score-type test

#detectCores()


# make a list to store our final results in.
results.list <- vector("list", length(clubdata_rsiena_freq)) #"pre-allocate" empty list of length 5

for (i in 1:5) { # for club i
  
  print(paste0("next up: club ", i))
  
  #get rsiena object
  mydata <- clubdata_rsiena_freq[[i]]
  
  #and the list containing myeff objects
  load(file=paste0("test/myeff/myeff_club",i,".RData"))
  #load(file=paste0("test/myeff/duration/myeff_club",i,".RData"))

  #take 6th element, which is the model with avSim
  myeff <- myeff[[6]]
  
  #include interaction effects, fixed to 0 and test=TRUE
  #here, it is important that in the `getEffects` command, the `behNintn` argument is set to a high enough value...
  
  #current behavior (linear shape)
  beh <- "freq_run"
  #beh <- "time_run"
  myeff1 <- includeInteraction(myeff, linear, indeg, name=beh, interaction1=c("","kudonet"), fix=TRUE, test=TRUE)
  myeff2 <- includeInteraction(myeff, linear, avSim, name=beh, interaction1=c("","kudonet"), fix=TRUE, test=TRUE)

  #novice
  myeff3 <- includeInteraction(myeff, effFrom, indeg, name = beh, interaction1 = c("novice", "kudonet"), fix=TRUE, test=TRUE)
  myeff4 <- includeInteraction(myeff, effFrom, avSim, name = beh, interaction1 = c("novice", "kudonet"), fix=TRUE, test=TRUE)
  
  #gender:
  myeff5 <- includeInteraction(myeff, effFrom, indeg, name = beh, interaction1 = c("gender", "kudonet"), fix=TRUE, test=TRUE)
  myeff6 <- includeInteraction(myeff, effFrom, avSim, name = beh, interaction1 = c("gender", "kudonet"), fix=TRUE, test=TRUE)
  
  myeffL<-list(myeff1,myeff2, myeff3,myeff4,myeff5,myeff6)
  
  # specify algorithm
  myalgorithm <- sienaAlgorithmCreate(projname = "test", nsub=5, n3=5000 )
 # myalgorithm <- sienaAlgorithmCreate(projname = "test", nsub=3, n3=50 ) #test
  
  ansL <- vector("list", length(myeffL)) #"pre-allocate" empty list of length 6 to store models j in, for club i

  #estimate
  for (j in 1:length(ansL)) {
    
    print(paste0("club ", i, ": estimating model ", j, "/6"))
    
    ans <- siena07(myalgorithm, data=mydata, effects=myeffL[[j]], nbrNodes=10, initC=TRUE, useCluster = TRUE, batch=TRUE)
    ansL[[j]] <- ans
  }
  
  results.list[[i]] <- ansL
}

#takes a long time, so save the results...
save(results.list, file="test/sienaFit/interactions_frequency.RData")

#save(results.list, file="test/sienaFit/interactions_volume.RData")


  • indeg x novice appears to improve the model in club 5;
  • avSim x novice appears to improve the model in clubs 2 and 4.



Step 2: estimate interaction effects

We found some indication that the effects of receiving kudos and the running of friends worked differently for club members who are newer to Strava (at least, in some clubs). These dynamics were no different for the genders, nor for athletes that differed in their current running. In step 2, we include these (missing) predictors of change in running behavior in our model. Thus, we not only test the effect, but we also estimate it simultaneously with the other effects.


indeg x novice

load("clubdata_rsiena_freq.Rdata")

mydata <- clubdata_rsiena_freq[[5]]

#load effects object
load(file=paste0("test/myeff/myeff_club","5",".RData"))
myeff <- myeff[[6]] 

# include interaction, and estimate the parameter
beh <- "freq_run"
myeff <- includeInteraction(myeff, effFrom, indeg, name = beh, interaction1 = c("novice", "kudonet"), fix=FALSE, test=FALSE)

# specify algorithm
myalgorithm <- sienaAlgorithmCreate(projname = "test", nsub=5, n3=5000 )

# estimate
ans <- siena07(myalgorithm, data=mydata, effects=myeff, nbrNodes=10, initC=TRUE, useCluster = TRUE, batch=TRUE)

# save output
save(ans, file="test/sienaFit/indeg_novice_club5.RData")


The interaction effect indeg x novice is negative and significant, suggesting that club members who joined Strava relatively recently, are less susceptible to the positive motivational effect of receiving kudos from clubmates on Strava.


avSim x novice

rm(list=setdiff(ls(), "clubdata_rsiena_freq"))

# make a list to store our results in.
results.list <- vector("list", length(clubdata_rsiena_freq)) #"pre-allocate" empty list of length 5

#club we need to do the estimation for
clubs <- c("2","4")

for (i in unique(clubs)) { # for club i
   #get rsiena object
   mydata <- clubdata_rsiena_freq[[2]]
   
  #and the list containing myeff objects
  load(file=paste0("test/myeff/myeff_club",i,".RData"))

  #take 6th element, which is the model with avSim
  myeff <- myeff[[6]]
  
  #include interaction, estimate parameter
  beh <- "freq_run"
  myeff <- includeInteraction(myeff, effFrom, avSim, name = beh, interaction1 = c("novice", "kudonet"), fix=FALSE, test=FALSE)
  
  # specify algorithm
  myalgorithm <- sienaAlgorithmCreate(projname = "test", nsub=5, n3=5000 )
  
  #estimate saom
  ans <- siena07(myalgorithm, data=mydata, effects=myeff, nbrNodes=10, initC=TRUE, useCluster = TRUE, batch=TRUE)
  
  #store in results.list
  results.list[[i]] <- ans
}

# save output
save(results.list, file="test/sienaFit/avsim_novice_club2_4.RData")


In both clubs, avSim x novice is positive and significant, suggesting that the tendency to minimize the dissimilarity in running behaviors compared to friends is greater for athletes that are relatively new to Strava…

All in all, we do not find consistent findings for these moderations.



References

Schweinberger, Michael. 2012. “Statistical Modelling of Network Panel Data: Goodness of Fit.” British Journal of Mathematical and Statistical Psychology 65 (2): 263–81. https://doi.org/10.1111/j.2044-8317.2011.02022.x.
LS0tDQp0aXRsZTogIlBvc3QtaG9jIHByb2Jpbmcgb2YgbW9kZXJhdGlvbmFsIGVmZmVjdHMiDQpkYXRlOiAiTGFzdCBjb21waWxlZCBvbiBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVCLCAlWScpYCINCmJpYmxpb2dyYXBoeTogcmVmZXJlbmNlcy5iaWINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjc3M6IHR3ZWFrcy5jc3MNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2xsYXBzZWQ6IGZhbHNlDQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQ0KICAgIHRvY19kZXB0aDogMQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KLS0tDQogIA0KYGBge3IsIGdsb2JhbHNldHRpbmdzLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30NCg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0Kb3B0c19jaHVuayRzZXQodGlkeS5vcHRzPWxpc3Qod2lkdGguY3V0b2ZmPTEwMCksdGlkeT1UUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSxjb21tZW50ID0gIiM+IiwgY2FjaGU9VFJVRSwgY2xhc3Muc291cmNlPWMoInRlc3QiKSwgY2xhc3Mub3V0cHV0PWMoInRlc3QyIikpDQpvcHRpb25zKHdpZHRoID0gMTAwKQ0KcmdsOjpzZXR1cEtuaXRyKCkNCg0KDQoNCmBgYA0KDQpgYGB7ciBrbGlwcHksIGVjaG89RkFMU0UsIGluY2x1ZGU9VFJVRX0NCmtsaXBweTo6a2xpcHB5KHBvc2l0aW9uID0gYygndG9wJywgJ3JpZ2h0JykpDQoja2xpcHB5OjprbGlwcHkoY29sb3IgPSAnZGFya3JlZCcpDQoja2xpcHB5OjprbGlwcHkodG9vbHRpcF9tZXNzYWdlID0gJ0NsaWNrIHRvIGNvcHknLCB0b29sdGlwX3N1Y2Nlc3MgPSAnRG9uZScpDQpgYGANCg0KDQoNCi0tLQ0KICANCkFpbTogdG8gZXhwbG9yZSBlZmZlY3QgaGV0ZXJvZ2VuZWl0eSBpbiBzb2NpYWwgaW5mbHVlbmNlIGJldHdlZW4gYWN0b3JzIHdpdGhpbiBjbHVicywgYWNjb3JkaW5nIHRvIHJ1bm5pbmcgbGV2ZWwgYW5kIGdlbmRlci4NCg0KDQpPdXIgbW9kZWwgYWxyZWFkeSBjb25zaWRlcnMgcmF0aGVyIG1hbnkgcGFyYW1ldGVycyBnaXZlbiB0aGUgaW5mb3JtYXRpb24gYXZhaWxhYmxlIGluIHRoZSBkYXRhLXNldC4gV2UgaGF2ZSBsaW1pdGVkIHBvd2VyIHRvIGRldGVjdCBiZWhhdmlvciBldm9sdXRpb24gZWZmZWN0cywgYXMgdGhlIG51bWJlciBvZiBkYXRhIHBvaW50cyBpcyBhdCB0aGUgb3JkZXIgJG4kLiBJZiB3ZSBjb25zaWRlciBuZXR3b3JrIGV2b2x1dGlvbiwgd2UgaGF2ZSBkYXRhIHBvaW50cyBvZiB0aGUgb3JkZXIgJG5eMiQuIFRoZXJlZm9yZSwgb3VyIGRhdGEgZG9lcyBub3cgYWxsb3cgZm9yIGJhY2t3YXJkIGVsaW1pbmF0aW9uIChpLmUuLCBlc3RpbWF0aW5nIHRoZSAnZnVsbCBtb2RlbCcsIGluY2x1ZGluZyBhbGwgaW50ZXJhY3Rpb25zIHNpbXVsdGFuZW91c2x5LCBhbmQgc3RlcHdpc2VseSByZW1vdmluZyBlZmZlY3RzIHRoYXQgYXJlIG5vdCBzaWduaWZpY2FudCBhY2NvcmRpbmcgdG8gc29tZSBjcml0ZXJpb24pLiANCg0KSW5zdGVhZCwgd2UgZXN0aW1hdGUgb3VyIG1haW4gbW9kZWwgYW5kIGFzc2VzcyB0aGUgaW50ZXJhY3Rpb25zIGJ5IHRlc3RpbmcgdGhlaXIgcGFyYW1ldGVycyAkKEhfMDpcdGhldGE9MCkkICp3aXRob3V0KiBlc3RpbWF0aW5nIHRoZW0sIHVzaW5nIHNjb3JlLXR5cGUgdGVzdHMsIGEgcHJvY2VkdXJlIHByb3Bvc2VkIGJ5IEBzY2h3ZWluYmVyZ2VyLiBTY29yZS10eXBlIHRlc3RzIGluZGljYXRlIHdoZXRoZXIgYW5kIHdoaWNoIG9mIHRoZSB0ZXN0ZWQgZWZmZWN0cyB3aWxsIGltcHJvdmUgYSBtb2RlbCwgd2hlbiBpbmNsdWRlZC4gV2Ugd2lsbCBjb25zaWRlciB0aGUgcmVzdWx0cyBvZiB0aGUgKG9uZS1zaWRlZCkgb25lLXBhcmFtZXRlciB0ZXN0LiBJdHMgdGVzdCBzdGF0aXN0aWMgaXMgc3RhbmRhcmQgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIA0KDQpJZiB3ZSBmaW5kIGludGVyYWN0aW9uIGVmZmVjdHMgdGhhdCB3b3VsZCBpbXByb3ZlIHRoZSBtb2RlbCwgd2Ugd2lsbCBlc3RpbWF0ZSB0aGVzZSBlZmZlY3RzIHNpbXVsdGFuZW91c2x5IHdpdGggdGhlIG90aGVyIG1vZGVsIGVmZmVjdHMuIFRodXMsIHdlIHVzZSBhIHR3by1zdGVwIGV4cGxvcmF0b3J5IHByb2NlZHVyZS4NCg0KDQotLS0tDQoNCiMgR2V0dGluZyBzdGFydGVkDQoNCiMjIGNsZWFuIHVwDQoNCmBgYHtyLCBhdHRyLm91dHB1dD0nc3R5bGU9Im1heC1oZWlnaHQ6IDIwMHB4OyInfQ0Kcm0gKGxpc3QgPSBscyggKSkNCiNnYygpDQpgYGANCg0KPGJyPg0KDQojIyBnZW5lcmFsIGN1c3RvbSBmdW5jdGlvbnMNCg0KLSBgZnBhY2thZ2UuY2hlY2tgOiBDaGVjayBpZiBwYWNrYWdlcyBhcmUgaW5zdGFsbGVkIChhbmQgaW5zdGFsbCBpZiBub3QpIGluIFIgKFtzb3VyY2VdKGh0dHBzOi8vdmJhbGlnYS5naXRodWIuaW8vdmVyaWZ5LXRoYXQtci1wYWNrYWdlcy1hcmUtaW5zdGFsbGVkLWFuZC1sb2FkZWQvKSkNCi0gYGZsb2FkLlJgOiBmdW5jdGlvbiB0byBsb2FkIFItb2JqZWN0cyB1bmRlciBuZXcgbmFtZXMuDQoNCmBgYHtyLCBldmFsPUZ9DQoNCmZwYWNrYWdlLmNoZWNrIDwtIGZ1bmN0aW9uKHBhY2thZ2VzKSB7DQogICAgbGFwcGx5KHBhY2thZ2VzLCBGVU4gPSBmdW5jdGlvbih4KSB7DQogICAgICAgIGlmICghcmVxdWlyZSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKSB7DQogICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKHgsIGRlcGVuZGVuY2llcyA9IFRSVUUpDQogICAgICAgICAgICBsaWJyYXJ5KHgsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkNCiAgICAgICAgfQ0KICAgIH0pDQp9DQoNCmZsb2FkLlIgIDwtIGZ1bmN0aW9uKGZpbGVOYW1lKXsNCiAgbG9hZChmaWxlTmFtZSkNCiAgZ2V0KGxzKClbbHMoKSAhPSAiZmlsZU5hbWUiXSkNCn0NCg0KY29sb3JpemUgPC0gZnVuY3Rpb24oeCwgY29sb3IpIHtzcHJpbnRmKCI8c3BhbiBzdHlsZT0nY29sb3I6ICVzOyc+JXM8L3NwYW4+IiwgY29sb3IsIHgpIH0NCg0KYGBgDQoNCg0KIyMgbmVjZXNzYXJ5IHBhY2thZ2VzDQoNCi0gYFJTaWVuYWANCi0gYHBhcmFsbGVsYDogdXRpbGl6ZSBtb3JlIGNvcmVzDQoNCmBgYHtyIHBhY2thZ2VzLCBldmFsPUZ9DQoNCnBhY2thZ2VzID0gYygiUlNpZW5hIiwgInBhcmFsbGVsIikNCg0KZnBhY2thZ2UuY2hlY2socGFja2FnZXMpDQpgYGANCg0KPGJyPg0KDQpEb3duIGJlbG93LCB3ZSBmb2N1cyBvbiBydW5uaW5nIGZyZXF1ZW5jeTsgYnV0IHRoZSBzY3JpcHRzIGNhbiBiZSBtb2RpZmllZCB0byBtb2RlbCBydW5uaW5nIHZvbHVtZS4NCg0KDQojIyByZWFkIGluIFJTaWVuYSBkYXRhIG9iamVjdHMNCmBgYHtyLCBldmFsPUZ9DQpsb2FkKCJjbHViZGF0YV9yc2llbmFfZnJlcS5SZGF0YSIpDQojbG9hZCgiY2x1YmRhdGFfcnNpZW5hX3ZvbC5SZGF0YSIpDQpgYGANCg0KPGJyPg0KDQotLS0tDQoNCiMgQXBwcm9hY2gNCg0KV2UgcHJvYmUgZm9yIG1vZGVyYXRpb25hbCBlZmZlY3RzIG9mOg0KDQotICpnZW5kZXIqOiB0byBzZWUgd2hldGhlciByZWNlaXZpbmcga3Vkb3Mgb3IgdGhlIGFjdGl2aXRpZXMgb2YgYWx0ZXJzIGhhdmUgZGlmZmVyZW50aWFsIGVmZmVjdHMgZm9yIG1hbGVzIGFuZCBmZW1hbGVzOw0KLSAqcnVubmluZyBsZXZlbCo6IHRvIHNlZSB3aGV0aGVyIHJ1bm5lcnMgd2l0aCBkaWZmZXJlbnQgcnVubmluZyBleHBlcmllbmNlIGFyZSBtb3JlL2xlc3MgcyAgdXNjZXB0aWJsZSB0byBpbmZsdWVuY2UuIFdlIGludGVyYWN0IHRoZSBpbmZsdWVuY2UgZWZmZWN0cyB3aXRoIHRoZSBgbGluZWFyYCBzaGFwZSBlZmZlY3QgKHdoaWNoIHJlcHJlc2VudHMgZWdvJ3MgY3VycmVudCBydW5uaW5nKSBhbmQgYSB0aW1lLWNvbnN0YW50IGFjdG9yLWNvdmFyaWF0ZSByZXByZXNlbnRpbmcgdGhlIG51bWJlciBvZiB5ZWFycyB0aGF0IGFjdG9ycyB3ZXJlIGFjdGl2ZSBvbiBTdHJhdmEgKGxhYmVsZWQgYG5vdmljZWApLiANCg0KV2UgZGlzY3VzcyBbaGVyZV0oaHR0cHM6Ly9yb2JmcmFua2VuLmdpdGh1Yi5pby9TdHJhdmEvaW50ZXJhY3Rpb24pIHdoeSB3ZSB1c2UgdGhlIGBsaW5lYXJgIHNoYXBlIGVmZmVjdCwgYW5kIHdoeSB3ZSB1c2UgYGF2U2ltYCByYXRoZXIgdGhhbiBgYXZBdHRMb3dlcmAgaW4gdGhlIGludGVyYWN0aW9uIG1vZGVscy4gDQogDQpXZSBmb2N1cyBvbiAyIGluZmx1ZW5jZSBlZmZlY3RzLCBhbmQgMyBpbnRlcmFjdGlvbnM7IHRodXMgYSB0b3RhbCBvZiA2IG1vZGVscyBmb3IgZWFjaCBjbHViLg0KDQoNCg0KIyBTdGVwIDE6IHNjb3JlLXR5cGUgdGVzdA0KDQpgYGB7ciwgZXZhbD1GfQ0KI2RldGVjdENvcmVzKCkNCg0KDQojIG1ha2UgYSBsaXN0IHRvIHN0b3JlIG91ciBmaW5hbCByZXN1bHRzIGluLg0KcmVzdWx0cy5saXN0IDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aChjbHViZGF0YV9yc2llbmFfZnJlcSkpICMicHJlLWFsbG9jYXRlIiBlbXB0eSBsaXN0IG9mIGxlbmd0aCA1DQoNCmZvciAoaSBpbiAxOjUpIHsgIyBmb3IgY2x1YiBpDQogIA0KICBwcmludChwYXN0ZTAoIm5leHQgdXA6IGNsdWIgIiwgaSkpDQogIA0KICAjZ2V0IHJzaWVuYSBvYmplY3QNCiAgbXlkYXRhIDwtIGNsdWJkYXRhX3JzaWVuYV9mcmVxW1tpXV0NCiAgDQogICNhbmQgdGhlIGxpc3QgY29udGFpbmluZyBteWVmZiBvYmplY3RzDQogIGxvYWQoZmlsZT1wYXN0ZTAoInRlc3QvbXllZmYvbXllZmZfY2x1YiIsaSwiLlJEYXRhIikpDQogICNsb2FkKGZpbGU9cGFzdGUwKCJ0ZXN0L215ZWZmL2R1cmF0aW9uL215ZWZmX2NsdWIiLGksIi5SRGF0YSIpKQ0KDQogICN0YWtlIDZ0aCBlbGVtZW50LCB3aGljaCBpcyB0aGUgbW9kZWwgd2l0aCBhdlNpbQ0KICBteWVmZiA8LSBteWVmZltbNl1dDQogIA0KICAjaW5jbHVkZSBpbnRlcmFjdGlvbiBlZmZlY3RzLCBmaXhlZCB0byAwIGFuZCB0ZXN0PVRSVUUNCiAgI2hlcmUsIGl0IGlzIGltcG9ydGFudCB0aGF0IGluIHRoZSBgZ2V0RWZmZWN0c2AgY29tbWFuZCwgdGhlIGBiZWhOaW50bmAgYXJndW1lbnQgaXMgc2V0IHRvIGEgaGlnaCBlbm91Z2ggdmFsdWUuLi4NCiAgDQogICNjdXJyZW50IGJlaGF2aW9yIChsaW5lYXIgc2hhcGUpDQogIGJlaCA8LSAiZnJlcV9ydW4iDQogICNiZWggPC0gInRpbWVfcnVuIg0KICBteWVmZjEgPC0gaW5jbHVkZUludGVyYWN0aW9uKG15ZWZmLCBsaW5lYXIsIGluZGVnLCBuYW1lPWJlaCwgaW50ZXJhY3Rpb24xPWMoIiIsImt1ZG9uZXQiKSwgZml4PVRSVUUsIHRlc3Q9VFJVRSkNCiAgbXllZmYyIDwtIGluY2x1ZGVJbnRlcmFjdGlvbihteWVmZiwgbGluZWFyLCBhdlNpbSwgbmFtZT1iZWgsIGludGVyYWN0aW9uMT1jKCIiLCJrdWRvbmV0IiksIGZpeD1UUlVFLCB0ZXN0PVRSVUUpDQoNCiAgI25vdmljZQ0KICBteWVmZjMgPC0gaW5jbHVkZUludGVyYWN0aW9uKG15ZWZmLCBlZmZGcm9tLCBpbmRlZywgbmFtZSA9IGJlaCwgaW50ZXJhY3Rpb24xID0gYygibm92aWNlIiwgImt1ZG9uZXQiKSwgZml4PVRSVUUsIHRlc3Q9VFJVRSkNCiAgbXllZmY0IDwtIGluY2x1ZGVJbnRlcmFjdGlvbihteWVmZiwgZWZmRnJvbSwgYXZTaW0sIG5hbWUgPSBiZWgsIGludGVyYWN0aW9uMSA9IGMoIm5vdmljZSIsICJrdWRvbmV0IiksIGZpeD1UUlVFLCB0ZXN0PVRSVUUpDQogIA0KICAjZ2VuZGVyOg0KICBteWVmZjUgPC0gaW5jbHVkZUludGVyYWN0aW9uKG15ZWZmLCBlZmZGcm9tLCBpbmRlZywgbmFtZSA9IGJlaCwgaW50ZXJhY3Rpb24xID0gYygiZ2VuZGVyIiwgImt1ZG9uZXQiKSwgZml4PVRSVUUsIHRlc3Q9VFJVRSkNCiAgbXllZmY2IDwtIGluY2x1ZGVJbnRlcmFjdGlvbihteWVmZiwgZWZmRnJvbSwgYXZTaW0sIG5hbWUgPSBiZWgsIGludGVyYWN0aW9uMSA9IGMoImdlbmRlciIsICJrdWRvbmV0IiksIGZpeD1UUlVFLCB0ZXN0PVRSVUUpDQogIA0KICBteWVmZkw8LWxpc3QobXllZmYxLG15ZWZmMiwgbXllZmYzLG15ZWZmNCxteWVmZjUsbXllZmY2KQ0KICANCiAgIyBzcGVjaWZ5IGFsZ29yaXRobQ0KICBteWFsZ29yaXRobSA8LSBzaWVuYUFsZ29yaXRobUNyZWF0ZShwcm9qbmFtZSA9ICJ0ZXN0IiwgbnN1Yj01LCBuMz01MDAwICkNCiAjIG15YWxnb3JpdGhtIDwtIHNpZW5hQWxnb3JpdGhtQ3JlYXRlKHByb2puYW1lID0gInRlc3QiLCBuc3ViPTMsIG4zPTUwICkgI3Rlc3QNCiAgDQogIGFuc0wgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoKG15ZWZmTCkpICMicHJlLWFsbG9jYXRlIiBlbXB0eSBsaXN0IG9mIGxlbmd0aCA2IHRvIHN0b3JlIG1vZGVscyBqIGluLCBmb3IgY2x1YiBpDQoNCiAgI2VzdGltYXRlDQogIGZvciAoaiBpbiAxOmxlbmd0aChhbnNMKSkgew0KICAgIA0KICAgIHByaW50KHBhc3RlMCgiY2x1YiAiLCBpLCAiOiBlc3RpbWF0aW5nIG1vZGVsICIsIGosICIvNiIpKQ0KICAgIA0KICAgIGFucyA8LSBzaWVuYTA3KG15YWxnb3JpdGhtLCBkYXRhPW15ZGF0YSwgZWZmZWN0cz1teWVmZkxbW2pdXSwgbmJyTm9kZXM9MTAsIGluaXRDPVRSVUUsIHVzZUNsdXN0ZXIgPSBUUlVFLCBiYXRjaD1UUlVFKQ0KICAgIGFuc0xbW2pdXSA8LSBhbnMNCiAgfQ0KICANCiAgcmVzdWx0cy5saXN0W1tpXV0gPC0gYW5zTA0KfQ0KDQojdGFrZXMgYSBsb25nIHRpbWUsIHNvIHNhdmUgdGhlIHJlc3VsdHMuLi4NCnNhdmUocmVzdWx0cy5saXN0LCBmaWxlPSJ0ZXN0L3NpZW5hRml0L2ludGVyYWN0aW9uc19mcmVxdWVuY3kuUkRhdGEiKQ0KDQojc2F2ZShyZXN1bHRzLmxpc3QsIGZpbGU9InRlc3Qvc2llbmFGaXQvaW50ZXJhY3Rpb25zX3ZvbHVtZS5SRGF0YSIpDQoNCmBgYA0KDQotLS0NCg0KPGJyPg0KDQotIGBpbmRlZyB4IG5vdmljZWAgYXBwZWFycyB0byBpbXByb3ZlIHRoZSBtb2RlbCBpbiBjbHViIDU7DQotIGBhdlNpbSB4IG5vdmljZWAgYXBwZWFycyB0byBpbXByb3ZlIHRoZSBtb2RlbCBpbiBjbHVicyAyIGFuZCA0Lg0KDQo8YnI+DQoNCi0tLQ0KDQojIFN0ZXAgMjogZXN0aW1hdGUgaW50ZXJhY3Rpb24gZWZmZWN0cw0KDQpXZSBmb3VuZCBzb21lIGluZGljYXRpb24gdGhhdCB0aGUgZWZmZWN0cyBvZiByZWNlaXZpbmcga3Vkb3MgYW5kIHRoZSBydW5uaW5nIG9mIGZyaWVuZHMgd29ya2VkIGRpZmZlcmVudGx5IGZvciBjbHViIG1lbWJlcnMgd2hvIGFyZSBuZXdlciB0byBTdHJhdmEgKGF0IGxlYXN0LCBpbiBzb21lIGNsdWJzKS4gVGhlc2UgZHluYW1pY3Mgd2VyZSBubyBkaWZmZXJlbnQgZm9yIHRoZSBnZW5kZXJzLCBub3IgZm9yIGF0aGxldGVzIHRoYXQgZGlmZmVyZWQgaW4gdGhlaXIgY3VycmVudCBydW5uaW5nLiBJbiBzdGVwIDIsIHdlIGluY2x1ZGUgdGhlc2UgKG1pc3NpbmcpIHByZWRpY3RvcnMgb2YgY2hhbmdlIGluIHJ1bm5pbmcgYmVoYXZpb3IgaW4gb3VyIG1vZGVsLiBgciBjb2xvcml6ZSgiVGh1cywgd2Ugbm90IG9ubHkgdGVzdCB0aGUgZWZmZWN0LCBidXQgd2UgYWxzbyBlc3RpbWF0ZSBpdCBzaW11bHRhbmVvdXNseSB3aXRoIHRoZSBvdGhlciBlZmZlY3RzLiIsICJyZWQiKWANCg0KDQoNCjxicj4NCg0KIyMgYGluZGVnIHggbm92aWNlYA0KYGBge3IsIGV2YWw9Rn0NCmxvYWQoImNsdWJkYXRhX3JzaWVuYV9mcmVxLlJkYXRhIikNCg0KbXlkYXRhIDwtIGNsdWJkYXRhX3JzaWVuYV9mcmVxW1s1XV0NCg0KI2xvYWQgZWZmZWN0cyBvYmplY3QNCmxvYWQoZmlsZT1wYXN0ZTAoInRlc3QvbXllZmYvbXllZmZfY2x1YiIsIjUiLCIuUkRhdGEiKSkNCm15ZWZmIDwtIG15ZWZmW1s2XV0gDQoNCiMgaW5jbHVkZSBpbnRlcmFjdGlvbiwgYW5kIGVzdGltYXRlIHRoZSBwYXJhbWV0ZXINCmJlaCA8LSAiZnJlcV9ydW4iDQpteWVmZiA8LSBpbmNsdWRlSW50ZXJhY3Rpb24obXllZmYsIGVmZkZyb20sIGluZGVnLCBuYW1lID0gYmVoLCBpbnRlcmFjdGlvbjEgPSBjKCJub3ZpY2UiLCAia3Vkb25ldCIpLCBmaXg9RkFMU0UsIHRlc3Q9RkFMU0UpDQoNCiMgc3BlY2lmeSBhbGdvcml0aG0NCm15YWxnb3JpdGhtIDwtIHNpZW5hQWxnb3JpdGhtQ3JlYXRlKHByb2puYW1lID0gInRlc3QiLCBuc3ViPTUsIG4zPTUwMDAgKQ0KDQojIGVzdGltYXRlDQphbnMgPC0gc2llbmEwNyhteWFsZ29yaXRobSwgZGF0YT1teWRhdGEsIGVmZmVjdHM9bXllZmYsIG5ick5vZGVzPTEwLCBpbml0Qz1UUlVFLCB1c2VDbHVzdGVyID0gVFJVRSwgYmF0Y2g9VFJVRSkNCg0KIyBzYXZlIG91dHB1dA0Kc2F2ZShhbnMsIGZpbGU9InRlc3Qvc2llbmFGaXQvaW5kZWdfbm92aWNlX2NsdWI1LlJEYXRhIikNCmBgYA0KDQo8YnI+DQoNClRoZSBpbnRlcmFjdGlvbiBlZmZlY3QgYGluZGVnIHggbm92aWNlYCBpcyAqKm5lZ2F0aXZlKiogYW5kIHNpZ25pZmljYW50LCBzdWdnZXN0aW5nIHRoYXQgY2x1YiBtZW1iZXJzIHdobyBqb2luZWQgU3RyYXZhIHJlbGF0aXZlbHkgcmVjZW50bHksIGFyZSAqbGVzcyogc3VzY2VwdGlibGUgdG8gdGhlIHBvc2l0aXZlIG1vdGl2YXRpb25hbCBlZmZlY3Qgb2YgcmVjZWl2aW5nIGt1ZG9zIGZyb20gY2x1Ym1hdGVzIG9uIFN0cmF2YS4NCg0KPGJyPg0KDQojIyBgYXZTaW0geCBub3ZpY2VgDQpgYGB7ciwgZXZhbD1GfQ0Kcm0obGlzdD1zZXRkaWZmKGxzKCksICJjbHViZGF0YV9yc2llbmFfZnJlcSIpKQ0KDQojIG1ha2UgYSBsaXN0IHRvIHN0b3JlIG91ciByZXN1bHRzIGluLg0KcmVzdWx0cy5saXN0IDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aChjbHViZGF0YV9yc2llbmFfZnJlcSkpICMicHJlLWFsbG9jYXRlIiBlbXB0eSBsaXN0IG9mIGxlbmd0aCA1DQoNCiNjbHViIHdlIG5lZWQgdG8gZG8gdGhlIGVzdGltYXRpb24gZm9yDQpjbHVicyA8LSBjKCIyIiwiNCIpDQoNCmZvciAoaSBpbiB1bmlxdWUoY2x1YnMpKSB7ICMgZm9yIGNsdWIgaQ0KICAgI2dldCByc2llbmEgb2JqZWN0DQogICBteWRhdGEgPC0gY2x1YmRhdGFfcnNpZW5hX2ZyZXFbWzJdXQ0KICAgDQogICNhbmQgdGhlIGxpc3QgY29udGFpbmluZyBteWVmZiBvYmplY3RzDQogIGxvYWQoZmlsZT1wYXN0ZTAoInRlc3QvbXllZmYvbXllZmZfY2x1YiIsaSwiLlJEYXRhIikpDQoNCiAgI3Rha2UgNnRoIGVsZW1lbnQsIHdoaWNoIGlzIHRoZSBtb2RlbCB3aXRoIGF2U2ltDQogIG15ZWZmIDwtIG15ZWZmW1s2XV0NCiAgDQogICNpbmNsdWRlIGludGVyYWN0aW9uLCBlc3RpbWF0ZSBwYXJhbWV0ZXINCiAgYmVoIDwtICJmcmVxX3J1biINCiAgbXllZmYgPC0gaW5jbHVkZUludGVyYWN0aW9uKG15ZWZmLCBlZmZGcm9tLCBhdlNpbSwgbmFtZSA9IGJlaCwgaW50ZXJhY3Rpb24xID0gYygibm92aWNlIiwgImt1ZG9uZXQiKSwgZml4PUZBTFNFLCB0ZXN0PUZBTFNFKQ0KICANCiAgIyBzcGVjaWZ5IGFsZ29yaXRobQ0KICBteWFsZ29yaXRobSA8LSBzaWVuYUFsZ29yaXRobUNyZWF0ZShwcm9qbmFtZSA9ICJ0ZXN0IiwgbnN1Yj01LCBuMz01MDAwICkNCiAgDQogICNlc3RpbWF0ZSBzYW9tDQogIGFucyA8LSBzaWVuYTA3KG15YWxnb3JpdGhtLCBkYXRhPW15ZGF0YSwgZWZmZWN0cz1teWVmZiwgbmJyTm9kZXM9MTAsIGluaXRDPVRSVUUsIHVzZUNsdXN0ZXIgPSBUUlVFLCBiYXRjaD1UUlVFKQ0KICANCiAgI3N0b3JlIGluIHJlc3VsdHMubGlzdA0KICByZXN1bHRzLmxpc3RbW2ldXSA8LSBhbnMNCn0NCg0KIyBzYXZlIG91dHB1dA0Kc2F2ZShyZXN1bHRzLmxpc3QsIGZpbGU9InRlc3Qvc2llbmFGaXQvYXZzaW1fbm92aWNlX2NsdWIyXzQuUkRhdGEiKQ0KYGBgDQoNCjxicj4NCg0KSW4gYm90aCBjbHVicywgYGF2U2ltIHggbm92aWNlYCBpcyAqKnBvc2l0aXZlKiogYW5kIHNpZ25pZmljYW50LCBzdWdnZXN0aW5nIHRoYXQgdGhlIHRlbmRlbmN5IHRvIG1pbmltaXplIHRoZSBkaXNzaW1pbGFyaXR5IGluIHJ1bm5pbmcgYmVoYXZpb3JzIGNvbXBhcmVkIHRvIGZyaWVuZHMgaXMgZ3JlYXRlciBmb3IgYXRobGV0ZXMgdGhhdCBhcmUgcmVsYXRpdmVseSBuZXcgdG8gU3RyYXZhLi4uDQoNCg0KQWxsIGluIGFsbCwgd2UgZG8gbm90IGZpbmQgY29uc2lzdGVudCBmaW5kaW5ncyBmb3IgdGhlc2UgbW9kZXJhdGlvbnMuDQoNCjxicj4gDQoNCi0tLS0NCg0KIyMgUmVmZXJlbmNlcw0KDQo=


Copyright © 2021 Rob Franken