Hi all–

Great lab! A wide variety of approaches were observed. I hope your groups’ semi-futile efforts banging away at dlpyr syntax was at least somewhat pedagogically constructive.

I promise, we’ll spend more time in a future lab on the relevant verbs of dplyr.

The Lab

Q1

The first questions asks us about this weird ANES survey device, the “feeling thermometer”, which measures a respondent’s affection for different social groups. We want the estimates of warmth by respondents’ ideology (ie, how did liberals evaluate big business? how did moderates? etc…)

Ok–we’ll start by loading the data

library(plyr)
library(tidyverse)
library(magrittr)

d1 <- "https://github.com/thomasjwood/ps4160/raw/master/anes_timeseries_2020.rds" %>%
  url %>%
  gzcon %>%
  readRDS 

We can check the feeling thermometers, whose range is given by the question (V202159:V202187).

d1 %>% 
  select(V202159:V202187)

An initial complication is that our feeling thermometers are factors, not numeric (ie, they’re categorical, and we can’t do math with them.) They also have a set of non substantive answers–indicators that a respondent refused to answer a question.


We could do something quite laborious, recoding each variable one at a time

d1$V202159 <- d1$V202159 %>% 
  mapvalues(
    c("-9. Refused",
      "-7. No post-election data, deleted due to incomplete interview",
      "-6. No post-election interview",
      "-5. Interview breakoff (sufficient partial IW)", 
      "-4. Technical error",
       "998. Don't know",
      "999. Don't recognize"),
    c(NA) %>% 
      rep(7)
    ) %>%
    as.character %>%
    as.numeric

This is saying

  1. Take the first feeling thermometer
  2. Take the seven values which are non substantive (ie, reflecting different reasons that a subject didn’t give a substantive answer).
  3. Replace them with an NA.
  4. Make this into a numeric variable that we can do math on.

Now, all I do below is to take that process and wrap it with a map, which applies the same function to each variable.

d1[
  ,
   (d1 %>% 
    names %>% 
    equals("V202159") %>% 
    which):
    (d1 %>% 
    names %>% 
    equals("V202187") %>% 
    which)
  ] %<>% 
  map(
    function(i)
      i %>% 
      mapvalues(
        c("-9. Refused",
          "-7. No post-election data, deleted due to incomplete interview",
          "-6. No post-election interview",
          "-5. Interview breakoff (sufficient partial IW)", 
          "-4. Technical error",
           "998. Don't know",
          "999. Don't recognize"),
        c(NA) %>% 
          rep(7)
        ) %>%
        as.character %>% 
        as.numeric
    )
  

Almost ready for our table. But we need a nice three party ideology measure:

d1$ideo_3 <- d1$V201200 %>%
  plyr::mapvalues(
    d1$V201200 %>% 
      levels,
    c(NA,
      "liberal",
      "moderate",
      "conservative",
      NA) %>% 
      rep(c(2, 2, 3, 2, 1))
  ) %>% 
  factor(
    c("liberal",
      "moderate",
      "conservative")
  )

Now we can do the calculation with dplyr

d1 %>% 
  select(
    V200010a, ideo_3, V202159:V202187
  ) %>% 
  gather(
    group, eval, -c(V200010a, ideo_3)
  ) %>% 
  na.omit %>% 
  group_by(ideo_3, group) %>% 
  summarize(
    mu = eval %>% weighted.mean(V200010a)
  ) %>% 
  slice(
    c(
      mu %>% 
        which.max,
      mu %>% 
        which.min
    )
  )

Would return

    ideo_3       group         mu
    <fct>        <chr>      <dbl>
  1 liberal      Scientists  90.0
  2 liberal      NRA         15.8
  3 moderate     Scientists  80.8
  4 moderate     Socialists  39.7
  5 conservative Christians  85.7
  6 conservative Socialists  12.7
  

(with some modest adjustments for labelling the groups…).

Q2

Now we want to test the level of retrospective economic impressions among mid to high education Democrats, during 2020 (that is, when their partisan impulse was in conflict with their receptivity to objective evidence).

First, some demographics–party and education

d1$partyid_3 <- d1$V201231x %>% 
  mapvalues(
    d1$V201231x %>% 
      levels,
    c(NA,
      "democrat",
      "independent",
      "republican"
      ) %>% 
      rep(
        c(2, 2, 3, 2)
      )
  )
  
d1$educ_3 <- d1$V201511x %>% 
  mapvalues(
    d1$V201511x %>% 
      levels,
    c(NA, 
      "hsd or less",
      "some college",
      "ba or more"
      ) %>% 
      rep(
        c(3, 2, 1, 2)
      )
  )

Now, let’s clean up the economic impression variables

d1$econ_natl <- d1$V201327x %>% 
  mapvalues(
    d1$V201327x %>% 
      levels,
    c(NA,
      "better",
      "same",
      "worse") %>% 
      rep(
        c(1, 2, 1, 2)
        )
    ) %>% 
    factor(
    c("better",
      "same",
      "worse")
      )

d1$econ <- d1$V201330x %>% 
  mapvalues(
    d1$V201330x %>% 
      levels,
    c(NA,
      "better",
      "same",
      "worse") %>% 
      rep(
        c(1, 2, 1, 2)
      )
    ) %>% 
    factor(
      c("better",
        "same",
        "worse")
        )
    
d1$econ_unemp <- d1$V201333x %>% 
  mapvalues(
    d1$V201333x %>% 
      levels,
    c(NA,
      "better",
      "same",
      "worse") %>% 
      rep(
        c(1, 2, 1, 2)
      )
  )

Then it’s all the dplyr verbs

d1 %>% 
  select(
    V200010b,
    partyid_3,
    educ_3,
    starts_with("econ")
  ) %>% 
  filter(
    partyid_3 %>% 
      equals("democrat") &
    educ_3 %>% 
      equals("hsd or less") %>% 
      not
    ) %>% 
  gather(
    econ, ans, starts_with("econ")
  ) %>% 
  na.omit %>% 
  group_by(
    partyid_3, econ, ans
  ) %>% 
  tally(
    V200010b
    ) %>% 
  mutate(
    perc = n %>% 
      divide_by(
        n %>% sum
        ) %>% 
      multiply_by(100)
    ) %>% 
  select(-n) %>% 
  spread(ans, perc) %>% 
  arrange(desc(better))

should return

    partyid_3 econ       better  same worse
    <fct>     <chr>       <dbl> <dbl> <dbl>
  1 democrat  econ        30.1  36.9   33.0
  2 democrat  econ_natl    5.00 14.5   80.5
  3 democrat  econ_unemp   3.12  9.10  87.8

hey good job, moderate to high education Democrats–you balanced your economic expectations for the coming year against the expectation that your copartisan president would be elected!

LS0tDQp0aXRsZTogIlBTIDQxNjAgTGFiIEFzc2lnbm1lbnQgMiINCmF1dGhvcjogIlRob21hcyBXb29kLCBQb2xpdGljYWwgU2NpZW5jZS0tT2hpbyBTdGF0ZSwgd29vZC4xMDgwQG9zdS5lZHUiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgdGhlbWU6IGNlcnVsZWFuDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCg0KSGkgYWxsLS0NCg0KR3JlYXQgbGFiISBBIHdpZGUgdmFyaWV0eSBvZiBhcHByb2FjaGVzIHdlcmUgb2JzZXJ2ZWQuIEkgaG9wZSB5b3VyIGdyb3Vwcycgc2VtaS1mdXRpbGUgZWZmb3J0cyBiYW5naW5nIGF3YXkgYXQgYGRscHlyYCBzeW50YXggd2FzIGF0IGxlYXN0IHNvbWV3aGF0IHBlZGFnb2dpY2FsbHkgY29uc3RydWN0aXZlLg0KDQpJIHByb21pc2UsIHdlJ2xsIHNwZW5kIG1vcmUgdGltZSBpbiBhIGZ1dHVyZSBsYWIgb24gdGhlIHJlbGV2YW50IHZlcmJzIG9mIGBkcGx5cmAuDQoNCiMjIFRoZSBMYWINCg0KIyMjIFExDQoNClRoZSBmaXJzdCBxdWVzdGlvbnMgYXNrcyB1cyBhYm91dCB0aGlzIHdlaXJkIEFORVMgc3VydmV5IGRldmljZSwgdGhlICJmZWVsaW5nIHRoZXJtb21ldGVyIiwgd2hpY2ggbWVhc3VyZXMgYSByZXNwb25kZW50J3MgYWZmZWN0aW9uIGZvciBkaWZmZXJlbnQgc29jaWFsIGdyb3Vwcy4gV2Ugd2FudCB0aGUgZXN0aW1hdGVzIG9mIHdhcm10aCBieSByZXNwb25kZW50cycgaWRlb2xvZ3kgKGllLCBob3cgZGlkIGxpYmVyYWxzIGV2YWx1YXRlIGJpZyBidXNpbmVzcz8gaG93IGRpZCBtb2RlcmF0ZXM/IGV0Yy4uLikNCg0KT2stLXdlJ2xsIHN0YXJ0IGJ5IGxvYWRpbmcgdGhlIGRhdGENCg0KYGBgIHsjbG9hZF9kYXRhIC5yIC5SfQ0KbGlicmFyeShwbHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KDQpkMSA8LSAiaHR0cHM6Ly9naXRodWIuY29tL3Rob21hc2p3b29kL3BzNDE2MC9yYXcvbWFzdGVyL2FuZXNfdGltZXNlcmllc18yMDIwLnJkcyIgJT4lDQogIHVybCAlPiUNCiAgZ3pjb24gJT4lDQogIHJlYWRSRFMgDQpgYGANCg0KV2UgY2FuIGNoZWNrIHRoZSBmZWVsaW5nIHRoZXJtb21ldGVycywgd2hvc2UgcmFuZ2UgaXMgZ2l2ZW4gYnkgdGhlIHF1ZXN0aW9uIChgVjIwMjE1OTpWMjAyMTg3YCkuXA0KDQpgYGAgcg0KZDEgJT4lIA0KICBzZWxlY3QoVjIwMjE1OTpWMjAyMTg3KQ0KYGBgDQoNCmBgYHtyIGMxLCBlY2hvPUZBTFNFfQ0KZDEgJT4lIA0KICBzZWxlY3QoVjIwMjE1OTpWMjAyMTg3KQ0KDQpgYGANCg0KQW4gaW5pdGlhbCBjb21wbGljYXRpb24gaXMgdGhhdCBvdXIgZmVlbGluZyB0aGVybW9tZXRlcnMgYXJlIGBmYWN0b3JzYCwgbm90IGBudW1lcmljYCAoaWUsIHRoZXkncmUgY2F0ZWdvcmljYWwsIGFuZCB3ZSBjYW4ndCBkbyBtYXRoIHdpdGggdGhlbS4pIFRoZXkgYWxzbyBoYXZlIGEgc2V0IG9mIG5vbiBzdWJzdGFudGl2ZSBhbnN3ZXJzLS1pbmRpY2F0b3JzIHRoYXQgYSByZXNwb25kZW50IHJlZnVzZWQgdG8gYW5zd2VyIGEgcXVlc3Rpb24uDQoNClwNCldlIGNvdWxkIGRvIHNvbWV0aGluZyBxdWl0ZSBsYWJvcmlvdXMsIHJlY29kaW5nIGVhY2ggdmFyaWFibGUgb25lIGF0IGEgdGltZQ0KDQpgYGAgcg0KZDEkVjIwMjE1OSA8LSBkMSRWMjAyMTU5ICU+JSANCiAgbWFwdmFsdWVzKA0KICAgIGMoIi05LiBSZWZ1c2VkIiwNCiAgICAgICItNy4gTm8gcG9zdC1lbGVjdGlvbiBkYXRhLCBkZWxldGVkIGR1ZSB0byBpbmNvbXBsZXRlIGludGVydmlldyIsDQogICAgICAiLTYuIE5vIHBvc3QtZWxlY3Rpb24gaW50ZXJ2aWV3IiwNCiAgICAgICItNS4gSW50ZXJ2aWV3IGJyZWFrb2ZmIChzdWZmaWNpZW50IHBhcnRpYWwgSVcpIiwgDQogICAgICAiLTQuIFRlY2huaWNhbCBlcnJvciIsDQogICAgICAgIjk5OC4gRG9uJ3Qga25vdyIsDQogICAgICAiOTk5LiBEb24ndCByZWNvZ25pemUiKSwNCiAgICBjKE5BKSAlPiUgDQogICAgICByZXAoNykNCiAgICApICU+JQ0KICAgIGFzLmNoYXJhY3RlciAlPiUNCiAgICBhcy5udW1lcmljDQpgYGANCg0KVGhpcyBpcyBzYXlpbmcNCg0KMS4gIFRha2UgdGhlIGZpcnN0IGZlZWxpbmcgdGhlcm1vbWV0ZXINCjIuICBUYWtlIHRoZSBzZXZlbiB2YWx1ZXMgd2hpY2ggYXJlIG5vbiBzdWJzdGFudGl2ZSAoaWUsIHJlZmxlY3RpbmcgZGlmZmVyZW50IHJlYXNvbnMgdGhhdCBhIHN1YmplY3QgZGlkbid0IGdpdmUgYSBzdWJzdGFudGl2ZSBhbnN3ZXIpLg0KMy4gIFJlcGxhY2UgdGhlbSB3aXRoIGFuIGBOQWAuDQo0LiAgTWFrZSB0aGlzIGludG8gYSBgbnVtZXJpY2AgdmFyaWFibGUgdGhhdCB3ZSBjYW4gZG8gbWF0aCBvbi4NCg0KTm93LCBhbGwgSSBkbyBiZWxvdyBpcyB0byB0YWtlIHRoYXQgcHJvY2VzcyBhbmQgd3JhcCBpdCB3aXRoIGEgYG1hcGAsIHdoaWNoIGFwcGxpZXMgdGhlIHNhbWUgZnVuY3Rpb24gdG8gZWFjaCB2YXJpYWJsZS4NCg0KICAgIGQxWw0KICAgICAgLA0KICAgICAgIChkMSAlPiUgDQogICAgICAgIG5hbWVzICU+JSANCiAgICAgICAgZXF1YWxzKCJWMjAyMTU5IikgJT4lIA0KICAgICAgICB3aGljaCk6DQogICAgICAgIChkMSAlPiUgDQogICAgICAgIG5hbWVzICU+JSANCiAgICAgICAgZXF1YWxzKCJWMjAyMTg3IikgJT4lIA0KICAgICAgICB3aGljaCkNCiAgICAgIF0gJTw+JSANCiAgICAgIG1hcCgNCiAgICAgICAgZnVuY3Rpb24oaSkNCiAgICAgICAgICBpICU+JSANCiAgICAgICAgICBtYXB2YWx1ZXMoDQogICAgICAgICAgICBjKCItOS4gUmVmdXNlZCIsDQogICAgICAgICAgICAgICItNy4gTm8gcG9zdC1lbGVjdGlvbiBkYXRhLCBkZWxldGVkIGR1ZSB0byBpbmNvbXBsZXRlIGludGVydmlldyIsDQogICAgICAgICAgICAgICItNi4gTm8gcG9zdC1lbGVjdGlvbiBpbnRlcnZpZXciLA0KICAgICAgICAgICAgICAiLTUuIEludGVydmlldyBicmVha29mZiAoc3VmZmljaWVudCBwYXJ0aWFsIElXKSIsIA0KICAgICAgICAgICAgICAiLTQuIFRlY2huaWNhbCBlcnJvciIsDQogICAgICAgICAgICAgICAiOTk4LiBEb24ndCBrbm93IiwNCiAgICAgICAgICAgICAgIjk5OS4gRG9uJ3QgcmVjb2duaXplIiksDQogICAgICAgICAgICBjKE5BKSAlPiUgDQogICAgICAgICAgICAgIHJlcCg3KQ0KICAgICAgICAgICAgKSAlPiUNCiAgICAgICAgICAgIGFzLmNoYXJhY3RlciAlPiUgDQogICAgICAgICAgICBhcy5udW1lcmljDQogICAgICAgICkNCiAgICAgIA0KDQoNCkFsbW9zdCByZWFkeSBmb3Igb3VyIHRhYmxlLiBCdXQgd2UgbmVlZCBhIG5pY2UgdGhyZWUgcGFydHkgaWRlb2xvZ3kgbWVhc3VyZToNCg0KICAgIGQxJGlkZW9fMyA8LSBkMSRWMjAxMjAwICU+JQ0KICAgICAgcGx5cjo6bWFwdmFsdWVzKA0KICAgICAgICBkMSRWMjAxMjAwICU+JSANCiAgICAgICAgICBsZXZlbHMsDQogICAgICAgIGMoTkEsDQogICAgICAgICAgImxpYmVyYWwiLA0KICAgICAgICAgICJtb2RlcmF0ZSIsDQogICAgICAgICAgImNvbnNlcnZhdGl2ZSIsDQogICAgICAgICAgTkEpICU+JSANCiAgICAgICAgICByZXAoYygyLCAyLCAzLCAyLCAxKSkNCiAgICAgICkgJT4lIA0KICAgICAgZmFjdG9yKA0KICAgICAgICBjKCJsaWJlcmFsIiwNCiAgICAgICAgICAibW9kZXJhdGUiLA0KICAgICAgICAgICJjb25zZXJ2YXRpdmUiKQ0KICAgICAgKQ0KDQpOb3cgd2UgY2FuIGRvIHRoZSBjYWxjdWxhdGlvbiB3aXRoIGBkcGx5cmANCg0KICAgIGQxICU+JSANCiAgICAgIHNlbGVjdCgNCiAgICAgICAgVjIwMDAxMGEsIGlkZW9fMywgVjIwMjE1OTpWMjAyMTg3DQogICAgICApICU+JSANCiAgICAgIGdhdGhlcigNCiAgICAgICAgZ3JvdXAsIGV2YWwsIC1jKFYyMDAwMTBhLCBpZGVvXzMpDQogICAgICApICU+JSANCiAgICAgIG5hLm9taXQgJT4lIA0KICAgICAgZ3JvdXBfYnkoaWRlb18zLCBncm91cCkgJT4lIA0KICAgICAgc3VtbWFyaXplKA0KICAgICAgICBtdSA9IGV2YWwgJT4lIHdlaWdodGVkLm1lYW4oVjIwMDAxMGEpDQogICAgICApICU+JSANCiAgICAgIHNsaWNlKA0KICAgICAgICBjKA0KICAgICAgICAgIG11ICU+JSANCiAgICAgICAgICAgIHdoaWNoLm1heCwNCiAgICAgICAgICBtdSAlPiUgDQogICAgICAgICAgICB3aGljaC5taW4NCiAgICAgICAgKQ0KICAgICAgKQ0KDQpXb3VsZCByZXR1cm4NCg0KICAgICAgICBpZGVvXzMgICAgICAgZ3JvdXAgICAgICAgICBtdQ0KICAgICAgICA8ZmN0PiAgICAgICAgPGNocj4gICAgICA8ZGJsPg0KICAgICAgMSBsaWJlcmFsICAgICAgU2NpZW50aXN0cyAgOTAuMA0KICAgICAgMiBsaWJlcmFsICAgICAgTlJBICAgICAgICAgMTUuOA0KICAgICAgMyBtb2RlcmF0ZSAgICAgU2NpZW50aXN0cyAgODAuOA0KICAgICAgNCBtb2RlcmF0ZSAgICAgU29jaWFsaXN0cyAgMzkuNw0KICAgICAgNSBjb25zZXJ2YXRpdmUgQ2hyaXN0aWFucyAgODUuNw0KICAgICAgNiBjb25zZXJ2YXRpdmUgU29jaWFsaXN0cyAgMTIuNw0KICAgICAgDQood2l0aCBzb21lIG1vZGVzdCBhZGp1c3RtZW50cyBmb3IgbGFiZWxsaW5nIHRoZSBncm91cHMuLi4pLg0KDQojIyMgUTINCg0KTm93IHdlIHdhbnQgdG8gdGVzdCB0aGUgbGV2ZWwgb2YgcmV0cm9zcGVjdGl2ZSBlY29ub21pYyBpbXByZXNzaW9ucyBhbW9uZyBtaWQgdG8gaGlnaCBlZHVjYXRpb24gRGVtb2NyYXRzLCBkdXJpbmcgMjAyMCAodGhhdCBpcywgd2hlbiB0aGVpciBwYXJ0aXNhbiBpbXB1bHNlIHdhcyBpbiBjb25mbGljdCB3aXRoIHRoZWlyIHJlY2VwdGl2aXR5IHRvIG9iamVjdGl2ZSBldmlkZW5jZSkuDQoNCkZpcnN0LCBzb21lIGRlbW9ncmFwaGljcy0tcGFydHkgYW5kIGVkdWNhdGlvbg0KDQogICAgZDEkcGFydHlpZF8zIDwtIGQxJFYyMDEyMzF4ICU+JSANCiAgICAgIG1hcHZhbHVlcygNCiAgICAgICAgZDEkVjIwMTIzMXggJT4lIA0KICAgICAgICAgIGxldmVscywNCiAgICAgICAgYyhOQSwNCiAgICAgICAgICAiZGVtb2NyYXQiLA0KICAgICAgICAgICJpbmRlcGVuZGVudCIsDQogICAgICAgICAgInJlcHVibGljYW4iDQogICAgICAgICAgKSAlPiUgDQogICAgICAgICAgcmVwKA0KICAgICAgICAgICAgYygyLCAyLCAzLCAyKQ0KICAgICAgICAgICkNCiAgICAgICkNCiAgICAgIA0KICAgIGQxJGVkdWNfMyA8LSBkMSRWMjAxNTExeCAlPiUgDQogICAgICBtYXB2YWx1ZXMoDQogICAgICAgIGQxJFYyMDE1MTF4ICU+JSANCiAgICAgICAgICBsZXZlbHMsDQogICAgICAgIGMoTkEsIA0KICAgICAgICAgICJoc2Qgb3IgbGVzcyIsDQogICAgICAgICAgInNvbWUgY29sbGVnZSIsDQogICAgICAgICAgImJhIG9yIG1vcmUiDQogICAgICAgICAgKSAlPiUgDQogICAgICAgICAgcmVwKA0KICAgICAgICAgICAgYygzLCAyLCAxLCAyKQ0KICAgICAgICAgICkNCiAgICAgICkNCg0KTm93LCBsZXQncyBjbGVhbiB1cCB0aGUgZWNvbm9taWMgaW1wcmVzc2lvbiB2YXJpYWJsZXMNCg0KICAgIGQxJGVjb25fbmF0bCA8LSBkMSRWMjAxMzI3eCAlPiUgDQogICAgICBtYXB2YWx1ZXMoDQogICAgICAgIGQxJFYyMDEzMjd4ICU+JSANCiAgICAgICAgICBsZXZlbHMsDQogICAgICAgIGMoTkEsDQogICAgICAgICAgImJldHRlciIsDQogICAgICAgICAgInNhbWUiLA0KICAgICAgICAgICJ3b3JzZSIpICU+JSANCiAgICAgICAgICByZXAoDQogICAgICAgICAgICBjKDEsIDIsIDEsIDIpDQogICAgICAgICAgICApDQogICAgICAgICkgJT4lIA0KICAgICAgICBmYWN0b3IoDQogICAgICAgIGMoImJldHRlciIsDQogICAgICAgICAgInNhbWUiLA0KICAgICAgICAgICJ3b3JzZSIpDQogICAgICAgICAgKQ0KDQogICAgZDEkZWNvbiA8LSBkMSRWMjAxMzMweCAlPiUgDQogICAgICBtYXB2YWx1ZXMoDQogICAgICAgIGQxJFYyMDEzMzB4ICU+JSANCiAgICAgICAgICBsZXZlbHMsDQogICAgICAgIGMoTkEsDQogICAgICAgICAgImJldHRlciIsDQogICAgICAgICAgInNhbWUiLA0KICAgICAgICAgICJ3b3JzZSIpICU+JSANCiAgICAgICAgICByZXAoDQogICAgICAgICAgICBjKDEsIDIsIDEsIDIpDQogICAgICAgICAgKQ0KICAgICAgICApICU+JSANCiAgICAgICAgZmFjdG9yKA0KICAgICAgICAgIGMoImJldHRlciIsDQogICAgICAgICAgICAic2FtZSIsDQogICAgICAgICAgICAid29yc2UiKQ0KICAgICAgICAgICAgKQ0KICAgICAgICANCiAgICBkMSRlY29uX3VuZW1wIDwtIGQxJFYyMDEzMzN4ICU+JSANCiAgICAgIG1hcHZhbHVlcygNCiAgICAgICAgZDEkVjIwMTMzM3ggJT4lIA0KICAgICAgICAgIGxldmVscywNCiAgICAgICAgYyhOQSwNCiAgICAgICAgICAiYmV0dGVyIiwNCiAgICAgICAgICAic2FtZSIsDQogICAgICAgICAgIndvcnNlIikgJT4lIA0KICAgICAgICAgIHJlcCgNCiAgICAgICAgICAgIGMoMSwgMiwgMSwgMikNCiAgICAgICAgICApDQogICAgICApDQoNClRoZW4gaXQncyBhbGwgdGhlIGBkcGx5cmAgdmVyYnMNCg0KICAgIGQxICU+JSANCiAgICAgIHNlbGVjdCgNCiAgICAgICAgVjIwMDAxMGIsDQogICAgICAgIHBhcnR5aWRfMywNCiAgICAgICAgZWR1Y18zLA0KICAgICAgICBzdGFydHNfd2l0aCgiZWNvbiIpDQogICAgICApICU+JSANCiAgICAgIGZpbHRlcigNCiAgICAgICAgcGFydHlpZF8zICU+JSANCiAgICAgICAgICBlcXVhbHMoImRlbW9jcmF0IikgJg0KICAgICAgICBlZHVjXzMgJT4lIA0KICAgICAgICAgIGVxdWFscygiaHNkIG9yIGxlc3MiKSAlPiUgDQogICAgICAgICAgbm90DQogICAgICAgICkgJT4lIA0KICAgICAgZ2F0aGVyKA0KICAgICAgICBlY29uLCBhbnMsIHN0YXJ0c193aXRoKCJlY29uIikNCiAgICAgICkgJT4lIA0KICAgICAgbmEub21pdCAlPiUgDQogICAgICBncm91cF9ieSgNCiAgICAgICAgcGFydHlpZF8zLCBlY29uLCBhbnMNCiAgICAgICkgJT4lIA0KICAgICAgdGFsbHkoDQogICAgICAgIFYyMDAwMTBiDQogICAgICAgICkgJT4lIA0KICAgICAgbXV0YXRlKA0KICAgICAgICBwZXJjID0gbiAlPiUgDQogICAgICAgICAgZGl2aWRlX2J5KA0KICAgICAgICAgICAgbiAlPiUgc3VtDQogICAgICAgICAgICApICU+JSANCiAgICAgICAgICBtdWx0aXBseV9ieSgxMDApDQogICAgICAgICkgJT4lIA0KICAgICAgc2VsZWN0KC1uKSAlPiUgDQogICAgICBzcHJlYWQoYW5zLCBwZXJjKSAlPiUgDQogICAgICBhcnJhbmdlKGRlc2MoYmV0dGVyKSkNCg0Kc2hvdWxkIHJldHVybg0KDQoNCiAgICAgICAgcGFydHlpZF8zIGVjb24gICAgICAgYmV0dGVyICBzYW1lIHdvcnNlDQogICAgICAgIDxmY3Q+ICAgICA8Y2hyPiAgICAgICA8ZGJsPiA8ZGJsPiA8ZGJsPg0KICAgICAgMSBkZW1vY3JhdCAgZWNvbiAgICAgICAgMzAuMSAgMzYuOSAgIDMzLjANCiAgICAgIDIgZGVtb2NyYXQgIGVjb25fbmF0bCAgICA1LjAwIDE0LjUgICA4MC41DQogICAgICAzIGRlbW9jcmF0ICBlY29uX3VuZW1wICAgMy4xMiAgOS4xMCAgODcuOA0KDQpoZXkgZ29vZCBqb2IsIG1vZGVyYXRlIHRvIGhpZ2ggZWR1Y2F0aW9uIERlbW9jcmF0cy0teW91IGJhbGFuY2VkIHlvdXIgZWNvbm9taWMgZXhwZWN0YXRpb25zIGZvciB0aGUgY29taW5nIHllYXIgYWdhaW5zdCB0aGUgZXhwZWN0YXRpb24gdGhhdCB5b3VyIGNvcGFydGlzYW4gcHJlc2lkZW50IHdvdWxkIGJlIGVsZWN0ZWQhDQo=