1 Introduction

This RMarkdown document is part of the Generic Skills Component (GSK) of the Course of the Foundation Studies Programme at Srishti Manipal Institute of Art, Design, and Technology, Bangalore India. The material is based on A Layered Grammar of Graphics by Hadley Wickham. The course is meant for First Year students pursuing a Degree in Art and Design.

The intent of this GSK part is to build Skill in coding in R, and also appreciate R as a way to metaphorically visualize information of various kinds, using predominantly geometric figures and structures.

All RMarkdown files combine code, text, web-images, and figures developed using code. Everything is text; code chunks are enclosed in fences (```)

2 Goals for Lab 03

  • Understand the idea of “tidy” data
  • Using “tidy data” and the “tidyverse” way of programming in R allows to translate our thoughts readily into code.
  • Understand dplyr VERB functions to get to know and manipulate a dataset

3 Pedagogical Note

The method followed will be based on PRIMM:

  • PREDICT Inspect the code and guess at what the code might do, write predictions
  • RUN the code provided and check what happens
  • INFER what the parameters of the code do and write comments to explain. What bells and whistles can you see?
  • MODIFY the parameters code provided to understand the options available. Write comments to show what you have aimed for and achieved.
  • MAKE : take an idea/concept of your own, and graph it. # Inspiration + data

We’ll use data from the Museum of Modern Art (MoMA)

4 Packages needed

library(tidyverse) # readr, ggplot2, dplyr

5 Read in the data

This dataset has been created by Alison Hill(@apreshill on Twitter). Download the dataset, save it into your data folder and then import it into R:

moma <- read_csv("data/artworks-cleaned.csv")

6 Getting to Know your data: Make up some Questions

Challenge #1:

Try to answer all of these questions using dplyr. Answers are below but try them on your own first!

  1. How many paintings (rows) are in moma?
  2. How many variables (columns) are in moma?
  3. What is the first painting acquired by MoMA? Which year? Which artist? What title?
  4. What is the oldest painting in the collection? Which year? Which artist? What title?
  5. How many distinct artists are there?
  6. Which artist has the most paintings in the collection? How many paintings are by this artist?
  7. How many paintings by male vs female artists?
  8. How many paintings acquired by year, and by gender of artist, over time?

If you want more:

  1. How many artists of each gender are there?
  2. In what year were the most paintings acquired? Created?
  3. In what year was the first painting by a (solo) female artist acquired? When was that painting created? Which artist? What title?

6.1 How many paintings?

  • How many rows/observations are in moma?
  • How many variables are in moma?

Hint: These questions can be answered using the dplyr function glimpse.

library(dplyr)
moma
# A tibble: 2,253 × 23
   title             artist artist_bio artist_birth_ye… artist_death_ye… num_artists n_female_artists n_male_artists artist_gender
   <chr>             <chr>  <chr>                 <dbl>            <dbl>       <dbl>            <dbl>          <dbl> <chr>        
 1 "Rope and People… Joan … (Spanish,…             1893             1983           1                0              1 Male         
 2 "Fire in the Eve… Paul … (German, …             1879             1940           1                0              1 Male         
 3 "Portrait of an … Paul … (German, …             1879             1940           1                0              1 Male         
 4 "Guitar"          Pablo… (Spanish,…             1881             1973           1                0              1 Male         
 5 "Grandmother"     Arthu… (American…             1880             1946           1                0              1 Male         
 6 "\"M'Amenez-y\""  Franc… (French, …             1879             1953           1                0              1 Male         
 7 "Untitled"        Blink… (German, …             1943             1977           1                0              1 Male         
 8 "Daylight Saving… Pierr… (French, …             1880             1950           1                0              1 Male         
 9 "The Bather"      Paul … (French, …             1839             1906           1                0              1 Male         
10 "Syntheses of Na… Enric… (Italian,…             1894             1956           1                0              1 Male         
# … with 2,243 more rows, and 14 more variables: year_acquired <dbl>, year_created <dbl>, circumference_cm <lgl>, depth_cm <dbl>,
#   diameter_cm <lgl>, height_cm <dbl>, length_cm <lgl>, width_cm <dbl>, seat_height_cm <lgl>, purchase <lgl>, gift <lgl>,
#   exchange <lgl>, classification <chr>, department <chr>
glimpse(moma)
Rows: 2,253
Columns: 23
$ title             <chr> "Rope and People, I", "Fire in the Evening", "Portrait of an Equilibrist", "Guitar", "Grandmother", "\…
$ artist            <chr> "Joan Miró", "Paul Klee", "Paul Klee", "Pablo Picasso", "Arthur Dove", "Francis Picabia", "Blinky Pale…
$ artist_bio        <chr> "(Spanish, 1893–1983)", "(German, born Switzerland. 1879–1940)", "(German, born Switzerland. 1879–1940…
$ artist_birth_year <dbl> 1893, 1879, 1879, 1881, 1880, 1879, 1943, 1880, 1839, 1894, 1895, 1904, 1916, 1924, 1905, 1889, 1872, …
$ artist_death_year <dbl> 1983, 1940, 1940, 1973, 1946, 1953, 1977, 1950, 1906, 1956, 1949, 2001, 1991, 2001, 1970, 1930, 1944, …
$ num_artists       <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ n_female_artists  <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ n_male_artists    <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ artist_gender     <chr> "Male", "Male", "Male", "Male", "Male", "Male", "Male", "Male", "Male", "Male", "Male", "Male", "Male"…
$ year_acquired     <dbl> 1936, 1970, 1966, 1955, 1939, 1968, 1997, 1931, 1934, 1941, 1949, 1957, 1960, 1963, 1968, 1931, 1937, …
$ year_created      <dbl> 1935, 1929, 1927, 1919, 1925, 1919, 1970, 1929, 1885, 1930, 1942, 1953, 1959, 1962, 1950, 1926, 1936, …
$ circumference_cm  <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ depth_cm          <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ diameter_cm       <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ height_cm         <dbl> 104.8, 33.8, 60.3, 215.9, 50.8, 129.2, 200.0, 54.6, 127.0, 100.0, 86.0, 194.9, 209.8, 101.6, 244.1, 35…
$ length_cm         <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ width_cm          <dbl> 74.6000, 33.3000, 36.8000, 78.7000, 54.0000, 89.9000, 200.0000, 38.1000, 96.8000, 100.3000, 112.1000, …
$ seat_height_cm    <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ purchase          <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALS…
$ gift              <lgl> TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE,…
$ exchange          <lgl> FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
$ classification    <chr> "Painting", "Painting", "Painting", "Painting", "Painting", "Painting", "Painting", "Painting", "Paint…
$ department        <chr> "Painting & Sculpture", "Painting & Sculpture", "Painting & Sculpture", "Painting & Sculpture", "Paint…

6.2 What is the first painting acquired?

  • What is the first painting acquired by MoMA (since they started tracking)?
  • What year was it acquired?
  • Which artist?
  • What title?

Hint: These questions can be answered by combining two dplyr functions: select and arrange.

moma %>% 
  select(artist, title, year_acquired) %>% 
  arrange(year_acquired)
# A tibble: 2,253 × 3
   artist            title                                               year_acquired
   <chr>             <chr>                                                       <dbl>
 1 Edward Hopper     House by the Railroad                                        1930
 2 Bernard Karfiol   Seated Nude                                                  1930
 3 Pierre Roy        Daylight Savings Time                                        1931
 4 Preston Dickinson Plums on a Plate                                             1931
 5 Otto Dix          Dr. Mayer-Hermann                                            1932
 6 Paul Cézanne      The Bather                                                   1934
 7 Paul Cézanne      Pines and Rocks (Fontainebleau?)                             1934
 8 Paul Cézanne      Still Life with Ginger Jar, Sugar Bowl, and Oranges          1934
 9 Paul Cézanne      Still Life with Apples                                       1934
10 Arthur B. Davies  Italian Landscape                                            1934
# … with 2,243 more rows

6.3 What is the oldest painting in the MoMA collection?

  • What is the oldest painting in the MoMA collection historically (since they started tracking)?
  • What year was it created?
  • Which artist?
  • What title?

Hint: These questions can be answered by combining two dplyr functions: select and arrange.

moma %>% 
  select(artist, title, year_created) %>% 
  arrange(year_created)
# A tibble: 2,253 × 3
   artist       title                                    year_created
   <chr>        <chr>                                           <dbl>
 1 Odilon Redon Landscape at Daybreak                            1872
 2 Odilon Redon Apache (Man on Horseback)                        1875
 3 Odilon Redon Apache (Man on Horseback II)                     1875
 4 Odilon Redon Fishing Boat                                     1875
 5 Odilon Redon Rocky Peak                                       1875
 6 Odilon Redon The Rocky Slope                                  1875
 7 Odilon Redon Landscape with Rocks, near Royan                 1875
 8 Paul Cézanne Still Life with Fruit Dish                       1879
 9 Paul Cézanne L'Estaque                                        1879
10 Claude Monet On the Cliff at Pourville, Clear Weather         1882
# … with 2,243 more rows
oldest <- moma %>% 
  select(artist, title, year_created) %>% 
  arrange(year_created) %>% 
  slice(1)
oldest
# A tibble: 1 × 3
  artist       title                 year_created
  <chr>        <chr>                        <dbl>
1 Odilon Redon Landscape at Daybreak         1872

To do inline comments, I could say that the oldest painting is Landscape at Daybreak, painted by Odilon Redon in 1872.

6.4 How many artists?

  • How many distinct artists are there?

Hint: Try dplyr::distinct.

moma %>% 
  distinct(artist)
# A tibble: 989 × 1
   artist           
   <chr>            
 1 Joan Miró        
 2 Paul Klee        
 3 Pablo Picasso    
 4 Arthur Dove      
 5 Francis Picabia  
 6 Blinky Palermo   
 7 Pierre Roy       
 8 Paul Cézanne     
 9 Enrico Prampolini
10 Jankel Adler     
# … with 979 more rows

You could add a tally() too to get just the number of rows. You can also then use pull() to get that single number out of the tibble:

num_artists <- moma %>% 
  distinct(artist) %>% 
  tally() %>% 
  pull()
num_artists
[1] 989

Then I can refer to this number in inline comments like: there are 989 total.

6.5 Which artist has the most paintings?

  • Which artist has the most paintings ever owned by moma?
  • How many paintings in the MoMA collection by that artist?

Hint: Try dplyr::count. Use ?count to figure out how to sort the output.

moma %>% 
  count(artist, sort = TRUE)
# A tibble: 989 × 2
   artist               n
   <chr>            <int>
 1 Pablo Picasso       55
 2 Henri Matisse       32
 3 On Kawara           32
 4 Jacob Lawrence      30
 5 Batiste Madalena    25
 6 Jean Dubuffet       25
 7 Odilon Redon        25
 8 Ben Vautier         24
 9 Frank Stella        23
10 Philip Guston       23
# … with 979 more rows

In the ?count documentation, it says: “count and tally are designed so that you can call them repeatedly, each time rolling up a level of detail.” Try running count() again (leave parentheses empty) on your last code chunk. ( before the slice())

moma %>% 
  count(artist, sort = TRUE) %>% 
  count()
# A tibble: 1 × 1
      n
  <int>
1   989

6.6 How many paintings by male vs female artists?

moma %>% 
  count(artist_gender)
# A tibble: 3 × 2
  artist_gender     n
  <chr>         <int>
1 Female          252
2 Male           1991
3 <NA>             10

Now together we’ll count the number of artists by gender. You’ll need to give count two variable names in the parentheses: artist_gender and artist.

moma %>% 
  count(artist_gender, artist, sort = TRUE) 
# A tibble: 989 × 3
   artist_gender artist               n
   <chr>         <chr>            <int>
 1 Male          Pablo Picasso       55
 2 Male          Henri Matisse       32
 3 Male          On Kawara           32
 4 Male          Jacob Lawrence      30
 5 Male          Batiste Madalena    25
 6 Male          Jean Dubuffet       25
 7 Male          Odilon Redon        25
 8 Male          Ben Vautier         24
 9 Male          Frank Stella        23
10 Male          Philip Guston       23
# … with 979 more rows

This output is not super helpful as we already know that Pablo Picasso has 55 paintings in the MoMA collection. But how can we find out which female artist has the most paintings? We have a few options. Let’s first add a filter for females.

moma %>% 
  count(artist_gender, artist, sort = TRUE) %>% 
  filter(artist_gender == "Female")
# A tibble: 143 × 3
   artist_gender artist                    n
   <chr>         <chr>                 <int>
 1 Female        Sherrie Levine           12
 2 Female        Agnes Martin              9
 3 Female        Elizabeth Murray          8
 4 Female        Susan Rothenberg          8
 5 Female        Joan Mitchell             6
 6 Female        Loren MacIver             6
 7 Female        R. H. Quaytman            6
 8 Female        Helen Frankenthaler       5
 9 Female        Georgia O'Keeffe          4
10 Female        Lynette Yiadom-Boakye     4
# … with 133 more rows

Another option is to use another dplyr function called top_n(). Use ?top_n to see how it works. How it won’t work in this context:

moma %>% 
  count(artist_gender, artist, sort = TRUE) %>% 
  top_n(2)
# A tibble: 3 × 3
  artist_gender artist            n
  <chr>         <chr>         <int>
1 Male          Pablo Picasso    55
2 Male          Henri Matisse    32
3 Male          On Kawara        32

How it will work better is following a group_by(artist_gender):

moma %>% 
  count(artist_gender, artist, sort = TRUE) %>% 
  group_by(artist_gender) %>% 
  top_n(1)
# A tibble: 3 × 3
# Groups:   artist_gender [3]
  artist_gender artist                                                 n
  <chr>         <chr>                                              <int>
1 Male          Pablo Picasso                                         55
2 Female        Sherrie Levine                                        12
3 <NA>          Gilbert & George, Gilbert Proesch, George Passmore     2

Now we can see that Sherrie Levine has 12 paintings. This is a pretty far cry from the 55 paintings by Pablo Picasso.

6.7 How many artists of each gender are there?

This is a harder question to answer than you think! This is because the level of observation in our current moma dataset is unique paintings. We have multiple paintings done by the same artists though, so counting just the number of unique paintings is different than counting the number of unique artists.

Remember how count can be used back-to-back to roll up a level of detail? Try running count(artist_gender) again on your last code chunk.

moma %>% 
  count(artist_gender, artist) %>% 
  count(artist_gender)
# A tibble: 3 × 2
  artist_gender     n
  <chr>         <int>
1 Female          143
2 Male            837
3 <NA>              9

This output takes the previous table (made with count(artist_gender, artist)), and essentially ignores the n column. So we no longer care about how many paintings each individual artist created. Instead, we want to count the rows in this new table where each row is a unique artist. By counting by artist_gender in the last line, we are grouping by levels of that variable (so Female/Male/NA) and nn is the number of unique artists for each gender category recorded.

6.8 When were the most paintings in the collection acquired?

Hint: Try dplyr::count. Use ?count to figure out how to sort the output.

moma %>% 
  count(year_acquired, sort = TRUE)
# A tibble: 88 × 2
   year_acquired     n
           <dbl> <int>
 1          1985    86
 2          1942    71
 3          1979    71
 4          1991    67
 5          2005    67
 6          1967    65
 7          2008    55
 8          1961    45
 9          1969    45
10          1956    42
# … with 78 more rows

6.9 When were the most paintings in the collection created?

Hint: Try dplyr::count. Use ?count to figure out how to sort the output.

moma %>% 
  count(year_created, sort = TRUE)
# A tibble: 139 × 2
   year_created     n
          <dbl> <int>
 1         1977    57
 2         1940    56
 3         1964    56
 4         1961    50
 5         1962    49
 6         1963    44
 7         1959    42
 8         1968    40
 9         1960    39
10         1914    37
# … with 129 more rows

6.10 What about the first painting by a solo female artist?

Hint: Try combining three dplyr functions: filter, select, and arrange.

When was the first painting by a solo female artist acquired?

moma %>% 
  filter(num_artists == 1 & n_female_artists == 1) %>% 
  select(title, artist, year_acquired, year_created) %>% 
  arrange(year_acquired)
# A tibble: 252 × 4
   title                           artist                  year_acquired year_created
   <chr>                           <chr>                           <dbl>        <dbl>
 1 Landscape, 47                   Natalia Goncharova               1937         1912
 2 Shack                           Loren MacIver                    1938         1934
 3 Hopscotch                       Loren MacIver                    1940         1940
 4 Shadows with Painting           Irene Rice Pereira               1941         1940
 5 Figure                          Varvara Stepanova                1941         1921
 6 Still Life in Red               Amelia Peláez Del Casal          1942         1938
 7 White Lines                     Irene Rice Pereira               1942         1942
 8 Musical Squash                  Maud Morgan                      1942         1942
 9 Desolation                      Raquel Forner                    1942         1942
10 Self-Portrait with Cropped Hair Frida Kahlo                      1943         1940
# … with 242 more rows

What is the oldest painting by a solo female artist, and when was it created?

moma %>% 
  filter(num_artists == 1 & n_female_artists == 1) %>% 
  select(title, artist, year_acquired, year_created) %>% 
  arrange(year_created)
# A tibble: 252 × 4
   title                                                  artist                 year_acquired year_created
   <chr>                                                  <chr>                          <dbl>        <dbl>
 1 Self-Portrait with Two Flowers in Her Raised Left Hand Paula Modersohn-Becker          2017         1907
 2 Girl with Bare Shoulders                               Gwen John                       1958         1909
 3 Girl Reading at a Window                               Gwen John                       1971         1911
 4 Landscape, 47                                          Natalia Goncharova              1937         1912
 5 Cubist Nude                                            Alexandra Exter                 1991         1912
 6 Rayonism, Blue-Green Forest                            Natalia Goncharova              1985         1913
 7 The Factory and the Bridge                             Olga Rozanova                   1985         1913
 8 Subject from a Dyer's Shop                             Lyubov Popova                   1985         1914
 9 Portuguese Market                                      Sonia Delaunay-Terk             1955         1915
10 Girl with a Blue Scarf                                 Gwen John                       1963         1915
# … with 242 more rows
# or, because artist_gender is missing when num_artists > 1
moma %>% 
  filter(artist_gender == "Female") %>% 
  select(title, artist, year_acquired, year_created) %>% 
  arrange(year_acquired)
  1. How many paintings acquired by year, and by gender of artist, over time?

Hint: Try dplyr::count. Use ?count to figure out how to sort the output.

LS0tDQp0aXRsZTogIkxhYiAwMzogV2hhdCB1c2UgaXMgYSBCb29rIHdpdGhvdXQgYW55IFBpY3R1cmVzPyINCmF1dGhvcjogIkFydmluZCBWZW5rYXRhZHJpIg0KZGF0ZTogMDYvSnVseS8yMDIxDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdGhlbWU6IGZsYXRseQ0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KICAgIHRvY19kZXB0aDogMg0KICAgIG51bWJlcl9zZWN0aW9uczogVFJVRQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCg0KYWJzdHJhY3Q6IFBhcnQgb2YgdGhlIGBSIGZvciBBcnRpc3RzIGFuZCBEZXNpZ25lcnNgIGNvdXJzZSBhdCB0aGUgU2Nob29sIG9mIEZvdW5kYXRpb24gU3R1ZGllcywgU3Jpc2h0aSBNYW5pcGFsIEluc3RpdHV0ZSBvZiBBcnQsIERlc2lnbiwgYW5kIFRlY2hub2xvZ3ksIEJhbmdhbG9yZS4NCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFLCBjYWNoZSA9IEZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVycm9yID0gVFJVRSwgY29tbWVudCA9IE5BLCB3YXJuaW5nID0gRkFMU0UsIGVycm9ycyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHRpZHkgPSBGQUxTRSwgY2FjaGUgPSBGQUxTRSwgZmlnLnBhdGg9ICIwMi1maWdzLyIpDQpsaWJyYXJ5KGRvd25sb2FkdGhpcykNCmxpYnJhcnkoc2FzcykNCmBgYA0KDQoNCiMgSW50cm9kdWN0aW9uDQoNClRoaXMgUk1hcmtkb3duIGRvY3VtZW50IGlzIHBhcnQgb2YgdGhlIEdlbmVyaWMgU2tpbGxzIENvbXBvbmVudCAgKEdTSykgb2YgdGhlIENvdXJzZSBvZiB0aGUgIEZvdW5kYXRpb24gU3R1ZGllcyBQcm9ncmFtbWUgYXQgU3Jpc2h0aSBNYW5pcGFsIEluc3RpdHV0ZSBvZiBBcnQsIERlc2lnbiwgYW5kIFRlY2hub2xvZ3ksIEJhbmdhbG9yZSBJbmRpYS4gVGhlIG1hdGVyaWFsIGlzIGJhc2VkIG9uICpBIExheWVyZWQgR3JhbW1hciBvZiBHcmFwaGljcyogYnkgSGFkbGV5IFdpY2toYW0uIFRoZSBjb3Vyc2UgaXMgbWVhbnQgZm9yIEZpcnN0IFllYXIgc3R1ZGVudHMgcHVyc3VpbmcgYSBEZWdyZWUgaW4gQXJ0IGFuZCBEZXNpZ24uIA0KDQpUaGUgaW50ZW50IG9mIHRoaXMgR1NLIHBhcnQgaXMgdG8gYnVpbGQgU2tpbGwgaW4gY29kaW5nIGluIFIsIGFuZCBhbHNvIGFwcHJlY2lhdGUgUiBhcyBhIHdheSB0byBtZXRhcGhvcmljYWxseSB2aXN1YWxpemUgaW5mb3JtYXRpb24gb2YgdmFyaW91cyBraW5kcywgdXNpbmcgcHJlZG9taW5hbnRseSBnZW9tZXRyaWMgZmlndXJlcyBhbmQgc3RydWN0dXJlcy4NCg0KQWxsIFJNYXJrZG93biBmaWxlcyBjb21iaW5lIGNvZGUsIHRleHQsIHdlYi1pbWFnZXMsIGFuZCBmaWd1cmVzIGRldmVsb3BlZCB1c2luZyBjb2RlLiBFdmVyeXRoaW5nIGlzIHRleHQ7IGNvZGUgY2h1bmtzIGFyZSBlbmNsb3NlZCBpbiAqKmZlbmNlcyoqIChgYGApDQoNCiMgR29hbHMgZm9yIExhYiAwMw0KDQotIFVuZGVyc3RhbmQgdGhlIGlkZWEgb2YgInRpZHkiIGRhdGENCi0gVXNpbmcgInRpZHkgZGF0YSIgYW5kIHRoZSAidGlkeXZlcnNlIiB3YXkgb2YgcHJvZ3JhbW1pbmcgaW4gUiBhbGxvd3MgdG8gdHJhbnNsYXRlIG91ciB0aG91Z2h0cyByZWFkaWx5IGludG8gY29kZS4gDQotIFVuZGVyc3RhbmQgYGRwbHlyYCBWRVJCIGZ1bmN0aW9ucyB0byBnZXQgdG8ga25vdyBhbmQgbWFuaXB1bGF0ZSBhIGRhdGFzZXQNCg0KDQojIFBlZGFnb2dpY2FsIE5vdGUNCg0KVGhlIG1ldGhvZCBmb2xsb3dlZCB3aWxsIGJlIGJhc2VkIG9uDQpbUFJJTU1dKGh0dHBzOi8vYmxvZ3Mua2NsLmFjLnVrL2NzZXIvMjAxNy8wOS8wMS9wcmltbS1hLXN0cnVjdHVyZWQtYXBwcm9hY2gtdG8tdGVhY2hpbmctcHJvZ3JhbW1pbmcvKToNCg0KLSAgICoqUFJFRElDVCoqIEluc3BlY3QgdGhlIGNvZGUgYW5kIGd1ZXNzIGF0IHdoYXQgdGhlIGNvZGUgbWlnaHQgZG8sDQogICAgKip3cml0ZSBwcmVkaWN0aW9ucyoqDQotICAgKipSVU4qKiB0aGUgY29kZSBwcm92aWRlZCBhbmQgY2hlY2sgd2hhdCBoYXBwZW5zDQotICAgKipJTkZFUioqIHdoYXQgdGhlIGBwYXJhbWV0ZXJzYCBvZiB0aGUgY29kZSBkbyBhbmQgKip3cml0ZSBjb21tZW50cyB0byBleHBsYWluKiouIFdoYXQgYmVsbHMgYW5kIHdoaXN0bGVzIGNhbiB5b3Ugc2VlPw0KLSAgICoqTU9ESUZZKiogdGhlIGBwYXJhbWV0ZXJzYCBjb2RlIHByb3ZpZGVkIHRvIHVuZGVyc3RhbmQgdGhlDQogICAgYG9wdGlvbnNgIGF2YWlsYWJsZS4gKipXcml0ZSBjb21tZW50cyoqIHRvIHNob3cgd2hhdCB5b3UgaGF2ZSBhaW1lZCBmb3IgYW5kIGFjaGlldmVkLg0KLSAgICoqTUFLRSoqIDogdGFrZSBhbiBpZGVhL2NvbmNlcHQgb2YgeW91ciBvd24sIGFuZCBncmFwaCBpdC4NCiMgSW5zcGlyYXRpb24gKyBkYXRhDQoNCldlJ2xsIHVzZSBkYXRhIGZyb20gdGhlIE11c2V1bSBvZiBNb2Rlcm4gQXJ0IChNb01BKQ0KDQotIFB1YmxpY2x5IGF2YWlsYWJsZSBvbiBbR2l0SHViXShodHRwczovL2dpdGh1Yi5jb20vTXVzZXVtb2ZNb2Rlcm5BcnQvY29sbGVjdGlvbikNCi0gQXMgYW5hbHl6ZWQgYnkgW2ZpdmV0aGlydHllaWdodC5jb21dKGh0dHBzOi8vZml2ZXRoaXJ0eWVpZ2h0LmNvbS9mZWF0dXJlcy9hLW5lcmRzLWd1aWRlLXRvLXRoZS0yMjI5LXBhaW50aW5ncy1hdC1tb21hLykNCi0gQW5kIGJ5IFtvdGhlcnNdKGh0dHBzOi8vbWVkaXVtLmNvbS9AZm9lL2hlcmUtcy1hLXJvdW5kdXAtb2YtaG93LXBlb3BsZS1oYXZlLXVzZWQtb3VyLWRhdGEtc28tZmFyLTgwODYyZTRjZTIyMCkNCg0KIyBQYWNrYWdlcyBuZWVkZWQNCg0KYGBge3J9DQoNCmxpYnJhcnkodGlkeXZlcnNlKSAjIHJlYWRyLCBnZ3Bsb3QyLCBkcGx5cg0KDQpgYGANCg0KDQojIFJlYWQgaW4gdGhlIGRhdGENCg0KVGhpcyBkYXRhc2V0IGhhcyBiZWVuIGNyZWF0ZWQgYnkgQWxpc29uIEhpbGwoQGFwcmVzaGlsbCBvbiBUd2l0dGVyKS4gRG93bmxvYWQgdGhlIGRhdGFzZXQsIHNhdmUgaXQgaW50byB5b3VyICoqZGF0YSoqIGZvbGRlciBhbmQgdGhlbiBpbXBvcnQgaXQgaW50byBSOg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCm1vbWEgPC0gcmVhZF9jc3YoImRhdGEvYXJ0d29ya3MtY2xlYW5lZC5jc3YiKQ0KbW9tYSAlPiUgDQogIGRvd25sb2FkX3RoaXMoDQogICAgb3V0cHV0X25hbWUgPSAiYXJ0d29ya3MtY2xlYW5lZCIsDQogICAgb3V0cHV0X2V4dGVuc2lvbiA9ICIuY3N2IiwNCiAgICBidXR0b25fbGFiZWwgPSAiRG93bmxvYWQgZGF0YSBhcyBjc3YiLA0KICAgIGJ1dHRvbl90eXBlID0gImRlZmF1bHQiLA0KICAgIGhhc19pY29uID0gVFJVRSwNCiAgICBpY29uID0gImZhIGZhLXNhdmUiLA0KICAgIGNsYXNzID0gImh2ci1zd2VlcC10by1sZWZ0Ig0KICApDQpgYGANCg0KYGBge2NzcywgZWNobz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCi8qIGZyb20gaHR0cHM6Ly9pYW5sdW5uLmdpdGh1Yi5pby9Ib3Zlci8gKi8NCi5odnItc3dlZXAtdG8tbGVmdCB7DQogIGRpc3BsYXk6IGlubGluZS1ibG9jazsNCiAgdmVydGljYWwtYWxpZ246IG1pZGRsZTsNCiAgLXdlYmtpdC10cmFuc2Zvcm06IHBlcnNwZWN0aXZlKDFweCkgdHJhbnNsYXRlWigwKTsNCiAgdHJhbnNmb3JtOiBwZXJzcGVjdGl2ZSgxcHgpIHRyYW5zbGF0ZVooMCk7DQogIGJveC1zaGFkb3c6IDAgMCAxcHggcmdiYSgwLCAwLCAwLCAwKTsNCiAgcG9zaXRpb246IHJlbGF0aXZlOw0KICAtd2Via2l0LXRyYW5zaXRpb24tcHJvcGVydHk6IGNvbG9yOw0KICB0cmFuc2l0aW9uLXByb3BlcnR5OiBjb2xvcjsNCiAgLXdlYmtpdC10cmFuc2l0aW9uLWR1cmF0aW9uOiAwLjNzOw0KICB0cmFuc2l0aW9uLWR1cmF0aW9uOiAwLjNzOw0KfQ0KLmh2ci1zd2VlcC10by1sZWZ0OmJlZm9yZSB7DQogIGNvbnRlbnQ6ICIiOw0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIHotaW5kZXg6IC0xOw0KICB0b3A6IDA7DQogIGxlZnQ6IDA7DQogIHJpZ2h0OiAwOw0KICBib3R0b206IDA7DQogIGJhY2tncm91bmQ6ICMyMDk4RDE7DQogIC13ZWJraXQtdHJhbnNmb3JtOiBzY2FsZVgoMCk7DQogIHRyYW5zZm9ybTogc2NhbGVYKDApOw0KICAtd2Via2l0LXRyYW5zZm9ybS1vcmlnaW46IDEwMCUgNTAlOw0KICB0cmFuc2Zvcm0tb3JpZ2luOiAxMDAlIDUwJTsNCiAgLXdlYmtpdC10cmFuc2l0aW9uLXByb3BlcnR5OiB0cmFuc2Zvcm07DQogIHRyYW5zaXRpb24tcHJvcGVydHk6IHRyYW5zZm9ybTsNCiAgLXdlYmtpdC10cmFuc2l0aW9uLWR1cmF0aW9uOiAwLjNzOw0KICB0cmFuc2l0aW9uLWR1cmF0aW9uOiAwLjNzOw0KICAtd2Via2l0LXRyYW5zaXRpb24tdGltaW5nLWZ1bmN0aW9uOiBlYXNlLW91dDsNCiAgdHJhbnNpdGlvbi10aW1pbmctZnVuY3Rpb246IGVhc2Utb3V0Ow0KfQ0KLmh2ci1zd2VlcC10by1sZWZ0OmhvdmVyLCAuaHZyLXN3ZWVwLXRvLWxlZnQ6Zm9jdXMsIC5odnItc3dlZXAtdG8tbGVmdDphY3RpdmUgew0KICBjb2xvcjogd2hpdGU7DQp9DQouaHZyLXN3ZWVwLXRvLWxlZnQ6aG92ZXI6YmVmb3JlLCAuaHZyLXN3ZWVwLXRvLWxlZnQ6Zm9jdXM6YmVmb3JlLCAuaHZyLXN3ZWVwLXRvLWxlZnQ6YWN0aXZlOmJlZm9yZSB7DQogIC13ZWJraXQtdHJhbnNmb3JtOiBzY2FsZVgoMSk7DQogIHRyYW5zZm9ybTogc2NhbGVYKDEpOw0KfQ0KDQpgYGANCg0KYGBge3J9DQptb21hIDwtIHJlYWRfY3N2KCJkYXRhL2FydHdvcmtzLWNsZWFuZWQuY3N2IikNCmBgYA0KDQojIEdldHRpbmcgdG8gS25vdyB5b3VyIGRhdGE6IE1ha2UgdXAgc29tZSBRdWVzdGlvbnMNCg0KPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtc3VjY2VzcyI+DQogIDxkaXYgY2xhc3M9InBhbmVsLWhlYWRpbmciPkNoYWxsZW5nZSAjMTo8L2Rpdj4NCiAgPGRpdiBjbGFzcz0icGFuZWwtYm9keSI+DQpUcnkgdG8gYW5zd2VyIGFsbCBvZiB0aGVzZSBxdWVzdGlvbnMgdXNpbmcgYGRwbHlyYC4gQW5zd2VycyBhcmUgYmVsb3cgYnV0IHRyeSB0aGVtIG9uIHlvdXIgb3duIGZpcnN0IQ0KDQoxLiBIb3cgbWFueSBwYWludGluZ3MgKHJvd3MpIGFyZSBpbiBgbW9tYWA/IA0KMi4gSG93IG1hbnkgdmFyaWFibGVzIChjb2x1bW5zKSBhcmUgaW4gYG1vbWFgPw0KMy4gV2hhdCBpcyB0aGUgZmlyc3QgcGFpbnRpbmcgYWNxdWlyZWQgYnkgTW9NQT8gV2hpY2ggeWVhcj8gV2hpY2ggYXJ0aXN0PyBXaGF0IHRpdGxlPw0KNC4gV2hhdCBpcyB0aGUgb2xkZXN0IHBhaW50aW5nIGluIHRoZSBjb2xsZWN0aW9uPyBXaGljaCB5ZWFyPyBXaGljaCBhcnRpc3Q/IFdoYXQgdGl0bGU/DQo1LiBIb3cgbWFueSBkaXN0aW5jdCBhcnRpc3RzIGFyZSB0aGVyZT8NCjYuIFdoaWNoIGFydGlzdCBoYXMgdGhlIG1vc3QgcGFpbnRpbmdzIGluIHRoZSBjb2xsZWN0aW9uPyBIb3cgbWFueSBwYWludGluZ3MgYXJlIGJ5IHRoaXMgYXJ0aXN0Pw0KNy4gSG93IG1hbnkgcGFpbnRpbmdzIGJ5IG1hbGUgdnMgZmVtYWxlIGFydGlzdHM/DQo4LiBIb3cgbWFueSBwYWludGluZ3MgYWNxdWlyZWQgYnkgeWVhciwgYW5kIGJ5IGdlbmRlciBvZiBhcnRpc3QsIG92ZXIgdGltZT8NCg0KDQpJZiB5b3Ugd2FudCBtb3JlOg0KDQoxLiBIb3cgbWFueSBhcnRpc3RzIG9mIGVhY2ggZ2VuZGVyIGFyZSB0aGVyZT8NCjIuIEluIHdoYXQgeWVhciB3ZXJlIHRoZSBtb3N0IHBhaW50aW5ncyBhY3F1aXJlZD8gQ3JlYXRlZD8NCjMuIEluIHdoYXQgeWVhciB3YXMgdGhlIGZpcnN0IHBhaW50aW5nIGJ5IGEgKHNvbG8pIGZlbWFsZSBhcnRpc3QgYWNxdWlyZWQ/IFdoZW4gd2FzIHRoYXQgcGFpbnRpbmcgY3JlYXRlZD8gV2hpY2ggYXJ0aXN0PyBXaGF0IHRpdGxlPw0KICA8L2Rpdj4NCjwvZGl2Pg0KDQojIyBIb3cgbWFueSBwYWludGluZ3M/DQoNCi0gSG93IG1hbnkgcm93cy9vYnNlcnZhdGlvbnMgYXJlIGluIGBtb21hYD8NCi0gSG93IG1hbnkgdmFyaWFibGVzIGFyZSBpbiBgbW9tYWA/DQoNCjxwIGNsYXNzPSJ0ZXh0LWluZm8iPiBfX0hpbnQ6X18gVGhlc2UgcXVlc3Rpb25zIGNhbiBiZSBhbnN3ZXJlZCB1c2luZyB0aGUgYGRwbHlyYCBmdW5jdGlvbiBgZ2xpbXBzZWAuPC9wPg0KDQoNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCm1vbWENCmdsaW1wc2UobW9tYSkNCmBgYA0KDQoNCiMjIFdoYXQgaXMgdGhlIGZpcnN0IHBhaW50aW5nIGFjcXVpcmVkPw0KDQoNCi0gV2hhdCBpcyB0aGUgZmlyc3QgcGFpbnRpbmcgYWNxdWlyZWQgYnkgTW9NQSAoc2luY2UgdGhleSBzdGFydGVkIHRyYWNraW5nKT8gDQotIFdoYXQgeWVhciB3YXMgaXQgYWNxdWlyZWQ/DQotIFdoaWNoIGFydGlzdD8NCi0gV2hhdCB0aXRsZT8NCg0KPHAgY2xhc3M9InRleHQtaW5mbyI+IF9fSGludDpfXyBUaGVzZSBxdWVzdGlvbnMgY2FuIGJlIGFuc3dlcmVkIGJ5IGNvbWJpbmluZyB0d28gYGRwbHlyYCBmdW5jdGlvbnM6IGBzZWxlY3RgIGFuZCBgYXJyYW5nZWAuPC9wPg0KDQoNCmBgYHtyfQ0KbW9tYSAlPiUgDQogIHNlbGVjdChhcnRpc3QsIHRpdGxlLCB5ZWFyX2FjcXVpcmVkKSAlPiUgDQogIGFycmFuZ2UoeWVhcl9hY3F1aXJlZCkNCmBgYA0KDQojIyBXaGF0IGlzIHRoZSBvbGRlc3QgcGFpbnRpbmcgaW4gdGhlIE1vTUEgY29sbGVjdGlvbj8NCg0KDQotIFdoYXQgaXMgdGhlIG9sZGVzdCBwYWludGluZyBpbiB0aGUgTW9NQSBjb2xsZWN0aW9uIGhpc3RvcmljYWxseSAoc2luY2UgdGhleSBzdGFydGVkIHRyYWNraW5nKT8gDQotIFdoYXQgeWVhciB3YXMgaXQgY3JlYXRlZD8NCi0gV2hpY2ggYXJ0aXN0Pw0KLSBXaGF0IHRpdGxlPw0KDQo8cCBjbGFzcz0idGV4dC1pbmZvIj4gX19IaW50Ol9fIFRoZXNlIHF1ZXN0aW9ucyBjYW4gYmUgYW5zd2VyZWQgYnkgY29tYmluaW5nIHR3byBgZHBseXJgIGZ1bmN0aW9uczogYHNlbGVjdGAgYW5kIGBhcnJhbmdlYC48L3A+DQoNCg0KDQpgYGB7cn0NCm1vbWEgJT4lIA0KICBzZWxlY3QoYXJ0aXN0LCB0aXRsZSwgeWVhcl9jcmVhdGVkKSAlPiUgDQogIGFycmFuZ2UoeWVhcl9jcmVhdGVkKQ0KYGBgDQoNCmBgYHtyfQ0Kb2xkZXN0IDwtIG1vbWEgJT4lIA0KICBzZWxlY3QoYXJ0aXN0LCB0aXRsZSwgeWVhcl9jcmVhdGVkKSAlPiUgDQogIGFycmFuZ2UoeWVhcl9jcmVhdGVkKSAlPiUgDQogIHNsaWNlKDEpDQpvbGRlc3QNCmBgYA0KDQpUbyBkbyBpbmxpbmUgY29tbWVudHMsIEkgY291bGQgc2F5IHRoYXQgdGhlIG9sZGVzdCBwYWludGluZyBpcyBgciBvbGRlc3QgJT4lIHB1bGwodGl0bGUpYCwgcGFpbnRlZCBieSBgciBvbGRlc3QgJT4lIHB1bGwoYXJ0aXN0KWAgaW4gYHIgb2xkZXN0ICU+JSBwdWxsKHllYXJfY3JlYXRlZClgLg0KDQojIyBIb3cgbWFueSBhcnRpc3RzPw0KDQotIEhvdyBtYW55IGRpc3RpbmN0IGFydGlzdHMgYXJlIHRoZXJlPw0KDQo8cCBjbGFzcz0idGV4dC1pbmZvIj4gX19IaW50Ol9fIFRyeSBgZHBseXI6OmRpc3RpbmN0YC48L3A+DQogDQoNCmBgYHtyfQ0KbW9tYSAlPiUgDQogIGRpc3RpbmN0KGFydGlzdCkNCmBgYA0KDQpZb3UgY291bGQgYWRkIGEgYHRhbGx5KClgIHRvbyB0byBnZXQganVzdCB0aGUgbnVtYmVyIG9mIHJvd3MuIFlvdSBjYW4gYWxzbyB0aGVuIHVzZSBgcHVsbCgpYCB0byBnZXQgdGhhdCBzaW5nbGUgbnVtYmVyIG91dCBvZiB0aGUgdGliYmxlOg0KDQpgYGB7cn0NCm51bV9hcnRpc3RzIDwtIG1vbWEgJT4lIA0KICBkaXN0aW5jdChhcnRpc3QpICU+JSANCiAgdGFsbHkoKSAlPiUgDQogIHB1bGwoKQ0KbnVtX2FydGlzdHMNCmBgYA0KDQpUaGVuIEkgY2FuIHJlZmVyIHRvIHRoaXMgbnVtYmVyIGluIGlubGluZSBjb21tZW50cyBsaWtlOiB0aGVyZSBhcmUgYHIgbnVtX2FydGlzdHNgIHRvdGFsLg0KDQojIyBXaGljaCBhcnRpc3QgaGFzIHRoZSBtb3N0IHBhaW50aW5ncz8NCg0KLSBXaGljaCBhcnRpc3QgaGFzIHRoZSBtb3N0IHBhaW50aW5ncyBldmVyIG93bmVkIGJ5IGBtb21hYD8gDQotIEhvdyBtYW55IHBhaW50aW5ncyBpbiB0aGUgTW9NQSBjb2xsZWN0aW9uIGJ5IHRoYXQgYXJ0aXN0Pw0KDQo8cCBjbGFzcz0idGV4dC1pbmZvIj4gX19IaW50Ol9fIFRyeSBgZHBseXI6OmNvdW50YC4gVXNlIGA/Y291bnRgIHRvIGZpZ3VyZSBvdXQgaG93IHRvIHNvcnQgdGhlIG91dHB1dC48L3A+DQoNCg0KYGBge3J9DQptb21hICU+JSANCiAgY291bnQoYXJ0aXN0LCBzb3J0ID0gVFJVRSkNCmBgYA0KDQpgYGB7ciBpbmNsdWRlID0gRkFMU0V9DQpwYWJsbyA8LSBtb21hICU+JSANCiAgY291bnQoYXJ0aXN0LCBzb3J0ID0gVFJVRSkgJT4lIA0KICBzbGljZSgxKQ0KYGBgDQoNCkluIHRoZSBgP2NvdW50YCBkb2N1bWVudGF0aW9uLCBpdCBzYXlzOiAiYGNvdW50YCBhbmQgYHRhbGx5YCBhcmUgZGVzaWduZWQgc28gdGhhdCB5b3UgY2FuIGNhbGwgdGhlbSByZXBlYXRlZGx5LCBlYWNoIHRpbWUgcm9sbGluZyB1cCBhIGxldmVsIG9mIGRldGFpbC4iIFRyeSBydW5uaW5nIGBjb3VudCgpYCBhZ2FpbiAobGVhdmUgcGFyZW50aGVzZXMgZW1wdHkpIG9uIHlvdXIgbGFzdCBjb2RlIGNodW5rLiAoIGJlZm9yZSB0aGUgYHNsaWNlKClgKQ0KDQpgYGB7cn0NCm1vbWEgJT4lIA0KICBjb3VudChhcnRpc3QsIHNvcnQgPSBUUlVFKSAlPiUgDQogIGNvdW50KCkNCmBgYA0KDQojIyBIb3cgbWFueSBwYWludGluZ3MgYnkgbWFsZSB2cyBmZW1hbGUgYXJ0aXN0cz8NCg0KDQpgYGB7cn0NCm1vbWEgJT4lIA0KICBjb3VudChhcnRpc3RfZ2VuZGVyKQ0KYGBgDQoNCg0KTm93IHRvZ2V0aGVyIHdlJ2xsIGNvdW50IHRoZSBudW1iZXIgb2YgYXJ0aXN0cyBieSBnZW5kZXIuIFlvdSdsbCBuZWVkIHRvIGdpdmUgYGNvdW50YCB0d28gdmFyaWFibGUgbmFtZXMgaW4gdGhlIHBhcmVudGhlc2VzOiBgYXJ0aXN0X2dlbmRlcmAgYW5kIGBhcnRpc3RgLg0KDQpgYGB7cn0NCm1vbWEgJT4lIA0KICBjb3VudChhcnRpc3RfZ2VuZGVyLCBhcnRpc3QsIHNvcnQgPSBUUlVFKSANCmBgYA0KDQpUaGlzIG91dHB1dCBpcyBub3Qgc3VwZXIgaGVscGZ1bCBhcyB3ZSBhbHJlYWR5IGtub3cgdGhhdCBgciBwYWJsbyAlPiUgcHVsbChhcnRpc3QpYCBoYXMgYHIgcGFibG8gJT4lIHB1bGwobilgIHBhaW50aW5ncyBpbiB0aGUgTW9NQSBjb2xsZWN0aW9uLiBCdXQgaG93IGNhbiB3ZSBmaW5kIG91dCB3aGljaCBmZW1hbGUgYXJ0aXN0IGhhcyB0aGUgbW9zdCBwYWludGluZ3M/IFdlIGhhdmUgYSBmZXcgb3B0aW9ucy4gTGV0J3MgZmlyc3QgYWRkIGEgYGZpbHRlcmAgZm9yIGZlbWFsZXMuDQoNCmBgYHtyfQ0KbW9tYSAlPiUgDQogIGNvdW50KGFydGlzdF9nZW5kZXIsIGFydGlzdCwgc29ydCA9IFRSVUUpICU+JSANCiAgZmlsdGVyKGFydGlzdF9nZW5kZXIgPT0gIkZlbWFsZSIpDQpgYGANCg0KQW5vdGhlciBvcHRpb24gaXMgdG8gdXNlIGFub3RoZXIgYGRwbHlyYCBmdW5jdGlvbiBjYWxsZWQgYHRvcF9uKClgLiBVc2UgYD90b3BfbmAgdG8gc2VlIGhvdyBpdCB3b3Jrcy4gSG93IGl0IHdvbid0IHdvcmsgaW4gdGhpcyBjb250ZXh0Og0KDQpgYGB7cn0NCm1vbWEgJT4lIA0KICBjb3VudChhcnRpc3RfZ2VuZGVyLCBhcnRpc3QsIHNvcnQgPSBUUlVFKSAlPiUgDQogIHRvcF9uKDIpDQpgYGANCg0KSG93IGl0IHdpbGwgd29yayBiZXR0ZXIgaXMgZm9sbG93aW5nIGEgYGdyb3VwX2J5KGFydGlzdF9nZW5kZXIpYDoNCg0KYGBge3J9DQptb21hICU+JSANCiAgY291bnQoYXJ0aXN0X2dlbmRlciwgYXJ0aXN0LCBzb3J0ID0gVFJVRSkgJT4lIA0KICBncm91cF9ieShhcnRpc3RfZ2VuZGVyKSAlPiUgDQogIHRvcF9uKDEpDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlID0gRkFMU0V9DQpzaGVycmllIDwtIG1vbWEgJT4lIA0KICBjb3VudChhcnRpc3RfZ2VuZGVyLCBhcnRpc3QsIHNvcnQgPSBUUlVFKSAlPiUgDQogIGZpbHRlcihhcnRpc3RfZ2VuZGVyID09ICJGZW1hbGUiKSAlPiUgDQogIHNsaWNlKDEpDQpgYGANCg0KTm93IHdlIGNhbiBzZWUgdGhhdCBgciBzaGVycmllICU+JSBwdWxsKGFydGlzdClgIGhhcyBgciBzaGVycmllICU+JSBwdWxsKG4pYCBwYWludGluZ3MuIFRoaXMgaXMgYSBwcmV0dHkgZmFyIGNyeSBmcm9tIHRoZSBgciBwYWJsbyAlPiUgcHVsbChuKWAgcGFpbnRpbmdzIGJ5IGByIHBhYmxvICU+JSBwdWxsKGFydGlzdClgLg0KDQojIyBIb3cgbWFueSBhcnRpc3RzIG9mIGVhY2ggZ2VuZGVyIGFyZSB0aGVyZT8NCg0KVGhpcyBpcyBhIGhhcmRlciBxdWVzdGlvbiB0byBhbnN3ZXIgdGhhbiB5b3UgdGhpbmshIFRoaXMgaXMgYmVjYXVzZSB0aGUgbGV2ZWwgb2Ygb2JzZXJ2YXRpb24gaW4gb3VyIGN1cnJlbnQgYG1vbWFgIGRhdGFzZXQgaXMgKnVuaXF1ZSBwYWludGluZ3MqLiBXZSBoYXZlIG11bHRpcGxlIHBhaW50aW5ncyBkb25lIGJ5IHRoZSBzYW1lIGFydGlzdHMgdGhvdWdoLCBzbyBjb3VudGluZyBqdXN0IHRoZSBudW1iZXIgb2YgdW5pcXVlIHBhaW50aW5ncyBpcyBkaWZmZXJlbnQgdGhhbiBjb3VudGluZyB0aGUgbnVtYmVyIG9mIHVuaXF1ZSBhcnRpc3RzLiANCg0KUmVtZW1iZXIgaG93IGBjb3VudGAgY2FuIGJlIHVzZWQgYmFjay10by1iYWNrIHRvIHJvbGwgdXAgYSBsZXZlbCBvZiBkZXRhaWw/IFRyeSBydW5uaW5nIGBjb3VudChhcnRpc3RfZ2VuZGVyKWAgYWdhaW4gb24geW91ciBsYXN0IGNvZGUgY2h1bmsuDQoNCmBgYHtyfQ0KbW9tYSAlPiUgDQogIGNvdW50KGFydGlzdF9nZW5kZXIsIGFydGlzdCkgJT4lIA0KICBjb3VudChhcnRpc3RfZ2VuZGVyKQ0KYGBgDQoNCg0KVGhpcyBvdXRwdXQgdGFrZXMgdGhlIHByZXZpb3VzIHRhYmxlIChtYWRlIHdpdGggYGNvdW50KGFydGlzdF9nZW5kZXIsIGFydGlzdClgKSwgYW5kIGVzc2VudGlhbGx5IGlnbm9yZXMgdGhlIGBuYCBjb2x1bW4uIFNvIHdlIG5vIGxvbmdlciBjYXJlIGFib3V0IGhvdyAqbWFueSogcGFpbnRpbmdzIGVhY2ggaW5kaXZpZHVhbCBhcnRpc3QgY3JlYXRlZC4gSW5zdGVhZCwgd2Ugd2FudCB0byBgY291bnRgIHRoZSByb3dzIGluIHRoaXMgKm5ldyogdGFibGUgd2hlcmUgZWFjaCByb3cgaXMgYSB1bmlxdWUgYXJ0aXN0LiBCeSBjb3VudGluZyBieSBgYXJ0aXN0X2dlbmRlcmAgaW4gdGhlIGxhc3QgbGluZSwgd2UgYXJlIGdyb3VwaW5nIGJ5IGxldmVscyBvZiB0aGF0IHZhcmlhYmxlIChzbyBGZW1hbGUvTWFsZS9gTkFgKSBhbmQgYG5uYCBpcyB0aGUgbnVtYmVyIG9mIHVuaXF1ZSBhcnRpc3RzIGZvciBlYWNoIGdlbmRlciBjYXRlZ29yeSByZWNvcmRlZC4NCg0KIyMgV2hlbiB3ZXJlIHRoZSBtb3N0IHBhaW50aW5ncyBpbiB0aGUgY29sbGVjdGlvbiBhY3F1aXJlZD8NCg0KDQo8cCBjbGFzcz0idGV4dC1pbmZvIj4gX19IaW50Ol9fIFRyeSBgZHBseXI6OmNvdW50YC4gVXNlIGA/Y291bnRgIHRvIGZpZ3VyZSBvdXQgaG93IHRvIHNvcnQgdGhlIG91dHB1dC48L3A+DQoNCmBgYHtyfQ0KbW9tYSAlPiUgDQogIGNvdW50KHllYXJfYWNxdWlyZWQsIHNvcnQgPSBUUlVFKQ0KYGBgDQoNCiMjIFdoZW4gd2VyZSB0aGUgbW9zdCBwYWludGluZ3MgaW4gdGhlIGNvbGxlY3Rpb24gY3JlYXRlZD8NCg0KDQo8cCBjbGFzcz0idGV4dC1pbmZvIj4gX19IaW50Ol9fIFRyeSBgZHBseXI6OmNvdW50YC4gVXNlIGA/Y291bnRgIHRvIGZpZ3VyZSBvdXQgaG93IHRvIHNvcnQgdGhlIG91dHB1dC48L3A+DQoNCmBgYHtyfQ0KbW9tYSAlPiUgDQogIGNvdW50KHllYXJfY3JlYXRlZCwgc29ydCA9IFRSVUUpDQpgYGANCg0KDQojIyBXaGF0IGFib3V0IHRoZSBmaXJzdCBwYWludGluZyBieSBhIHNvbG8gZmVtYWxlIGFydGlzdD8NCg0KPHAgY2xhc3M9InRleHQtaW5mbyI+IF9fSGludDpfXyBUcnkgY29tYmluaW5nIHRocmVlIGBkcGx5cmAgZnVuY3Rpb25zOiBgZmlsdGVyYCwgYHNlbGVjdGAsIGFuZCBgYXJyYW5nZWAuPC9wPg0KDQpXaGVuIHdhcyB0aGUgZmlyc3QgcGFpbnRpbmcgYnkgYSBzb2xvIGZlbWFsZSBhcnRpc3QgYWNxdWlyZWQ/DQoNCmBgYHtyfQ0KbW9tYSAlPiUgDQogIGZpbHRlcihudW1fYXJ0aXN0cyA9PSAxICYgbl9mZW1hbGVfYXJ0aXN0cyA9PSAxKSAlPiUgDQogIHNlbGVjdCh0aXRsZSwgYXJ0aXN0LCB5ZWFyX2FjcXVpcmVkLCB5ZWFyX2NyZWF0ZWQpICU+JSANCiAgYXJyYW5nZSh5ZWFyX2FjcXVpcmVkKQ0KYGBgDQoNCldoYXQgaXMgdGhlIG9sZGVzdCBwYWludGluZyBieSBhIHNvbG8gZmVtYWxlIGFydGlzdCwgYW5kIHdoZW4gd2FzIGl0IGNyZWF0ZWQ/DQoNCmBgYHtyfQ0KbW9tYSAlPiUgDQogIGZpbHRlcihudW1fYXJ0aXN0cyA9PSAxICYgbl9mZW1hbGVfYXJ0aXN0cyA9PSAxKSAlPiUgDQogIHNlbGVjdCh0aXRsZSwgYXJ0aXN0LCB5ZWFyX2FjcXVpcmVkLCB5ZWFyX2NyZWF0ZWQpICU+JSANCiAgYXJyYW5nZSh5ZWFyX2NyZWF0ZWQpDQpgYGANCg0KYGBge3IgZXZhbCA9IEZBTFNFfQ0KIyBvciwgYmVjYXVzZSBhcnRpc3RfZ2VuZGVyIGlzIG1pc3Npbmcgd2hlbiBudW1fYXJ0aXN0cyA+IDENCm1vbWEgJT4lIA0KICBmaWx0ZXIoYXJ0aXN0X2dlbmRlciA9PSAiRmVtYWxlIikgJT4lIA0KICBzZWxlY3QodGl0bGUsIGFydGlzdCwgeWVhcl9hY3F1aXJlZCwgeWVhcl9jcmVhdGVkKSAlPiUgDQogIGFycmFuZ2UoeWVhcl9hY3F1aXJlZCkNCmBgYA0KDQoNCjguIEhvdyBtYW55IHBhaW50aW5ncyBhY3F1aXJlZCBieSB5ZWFyLCBhbmQgYnkgZ2VuZGVyIG9mIGFydGlzdCwgb3ZlciB0aW1lPw0KDQo8cCBjbGFzcz0idGV4dC1pbmZvIj4gX19IaW50Ol9fIFRyeSBgZHBseXI6OmNvdW50YC4gVXNlIGA/Y291bnRgIHRvIGZpZ3VyZSBvdXQgaG93IHRvIHNvcnQgdGhlIG91dHB1dC48L3A+DQoNCmBgYHtyfQ0KDQpgYGANCg0K