Import Library/Packages

library(tidyverse)
package 㤼㸱tidyverse㤼㸲 was built under R version 4.0.5Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages --------------------------------------------------- tidyverse 1.3.1 --
v ggplot2 3.3.5     v purrr   0.3.4
v tibble  3.1.3     v dplyr   1.0.7
v tidyr   1.1.3     v stringr 1.4.0
v readr   2.0.0     v forcats 0.5.1
package 㤼㸱ggplot2㤼㸲 was built under R version 4.0.5package 㤼㸱readr㤼㸲 was built under R version 4.0.5package 㤼㸱dplyr㤼㸲 was built under R version 4.0.5-- Conflicts ------------------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()

Load the processed public school file from Part 2 https://rpubs.com/caryjim/nces-ps-data-processing

public_school <- read.csv("./Datasets/public_school_processed.csv", header = T, stringsAsFactors = T)
# This time, stringsAsFactors is applied to ensure all characters are converted

View columns

colnames(public_school)
 [1] "State.Name"            "ST"                    "School.Name"          
 [4] "NCES.SchID"            "Agency_Name"           "County_Name"          
 [7] "COUNTY.ID"             "Urban.centric.Locale"  "Latitude"             
[10] "Longitude"             "Title.I.School.Status" "Updated.Status"       
[13] "Agency.Type"           "School.Type"           "Members"              
[16] "Male"                  "Female"                "FTE.Equivalent"       
[19] "Pupil.Teacher.Ratio"  

View data type

str(public_school)
'data.frame':   94619 obs. of  19 variables:
 $ State.Name           : Factor w/ 102 levels "Alabama","ALABAMA",..: 43 95 47 47 45 55 29 77 88 99 ...
 $ ST                   : Factor w/ 51 levels "AK","AL","AR",..: 20 48 24 24 23 30 16 39 44 49 ...
 $ School.Name          : Factor w/ 82716 levels "1 LT Charles W. Whitcomb School",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ NCES.SchID           : num  2.51e+11 5.30e+11 2.71e+11 2.71e+11 2.63e+11 ...
 $ Agency_Name          : Factor w/ 16253 levels "21st Century Charter Sch of Gary",..: 8707 8775 4196 4196 11576 10432 1 2 15484 9138 ...
 $ County_Name          : Factor w/ 1874 levels "Abbeville County",..: 1105 1552 278 278 863 712 934 323 765 447 ...
 $ COUNTY.ID            : int  25017 53061 27019 27019 26077 31079 18089 42029 48215 55025 ...
 $ Urban.centric.Locale : Factor w/ 4 levels "City","Rural",..: 3 3 3 3 1 2 1 3 3 3 ...
 $ Latitude             : num  42.4 48.1 44.8 44.8 42.2 ...
 $ Longitude            : num  -71.5 -122.2 -93.6 -93.6 -85.6 ...
 $ Title.I.School.Status: Factor w/ 7 levels "1-Title I targeted assistance eligible school-No program",..: 5 6 2 2 6 6 5 6 4 1 ...
 $ Updated.Status       : Factor w/ 5 levels "1-Open","3-New",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Agency.Type          : Factor w/ 6 levels "1-Regular local school district that is NOT a component of a supervisory union",..: 1 1 1 1 1 1 4 4 1 1 ...
 $ School.Type          : Factor w/ 4 levels "1-Regular school",..: 1 1 4 4 1 1 1 1 1 1 ...
 $ Members              : int  1308 178 37 366 530 182 934 1039 331 38 ...
 $ Male                 : int  681 77 20 198 269 96 481 383 159 20 ...
 $ Female               : int  627 101 17 168 261 86 453 656 172 18 ...
 $ FTE.Equivalent       : num  118.8 7.3 NA NA 29.3 ...
 $ Pupil.Teacher.Ratio  : num  11 24.4 NA NA 18.1 ...

State Level

In the original public school dataset, state names entries are inconsistent. There are some state names as ALL CAPS and some as lower cases. Therefore, using state abbreviation is a better varaible unless we parse the chartacters in the full state names.

# A quick count of schools by each state in the processed data
table(public_school$ST)

   AK    AL    AR    AZ    CA    CO    CT    DC    DE    FL    GA    HI    IA    ID    IL 
  506  1342  1060  2055 10026  1891  1001   224   219  4004  2300   292  1322   730  3983 
   IN    KS    KY    LA    MA    MD    ME    MI    MN    MO    MS    MT    NC    ND    NE 
 1874  1315  1392  1370  1845  1395   571  3329  2112  2282   900   817  2639   478  1005 
   NH    NJ    NM    NV    NY    OH    OK    OR    PA    RI    SC    SD    TN    TX    UT 
  488  2566   865   687  4757  3500  1798  1243  2903   290  1213   683  1782  8774  1028 
   VA    VT    WA    WI    WV    WY 
 1858   296  2334  2240   669   366 

Order the number of school per state

sort(table(public_school$ST))

   DE    DC    RI    HI    VT    WY    ND    NH    AK    ME    WV    SD    NV    ID    MT 
  219   224   290   292   296   366   478   488   506   571   669   683   687   730   817 
   NM    MS    CT    NE    UT    AR    SC    OR    KS    IA    AL    LA    KY    MD    TN 
  865   900  1001  1005  1028  1060  1213  1243  1315  1322  1342  1370  1392  1395  1782 
   OK    MA    VA    IN    CO    AZ    MN    WI    MO    GA    WA    NJ    NC    PA    MI 
 1798  1845  1858  1874  1891  2055  2112  2240  2282  2300  2334  2566  2639  2903  3329 
   OH    IL    FL    NY    TX    CA 
 3500  3983  4004  4757  8774 10026 

Note. It would be interesting to see the number of public school per state and compare it to the current digital opportunity status of these regions.

Locale Information

table(public_school$Urban.centric.Locale)

  City  Rural Suburb   Town 
 25897  26370  30087  12265 
table(public_school$Title.I.School.Status)

         1-Title I targeted assistance eligible school-No program 
                                                             5271 
                             2-Title I targeted assistance school 
                                                             9311 
3-Title I schoolwide eligible-Title I targeted assistance program 
                                                             2508 
                  4-Title I schoolwide eligible school-No program 
                                                             6155 
                                      5-Title I schoolwide school 
                                                            46136 
                                           6-Not a Title I school 
                                                            24429 
                                                          Unknown 
                                                              809 

Aggregate the types of Locale by State and Provide a Count

# Collapse the data by State and their locale 
public_school %>% 
  group_by(ST, Urban.centric.Locale) %>%
  summarize(locale = n())
`summarise()` has grouped output by 'ST'. You can override using the `.groups` argument.

Review the Title 1 information by state

public_school %>% 
  group_by(ST, Title.I.School.Status) %>%
  summarize(each_count = n())
`summarise()` has grouped output by 'ST'. You can override using the `.groups` argument.

We can see that some states have more reported categories of Title I status

public_school %>% 
  group_by(ST) %>%
  summarize(total_enrollment = sum(Members))

Task 1. Create a new dataframe for state level information

Group selected variables by state level and calculate a percentage of that information or a total count

Total student enrollment and gender

# Create a new dataframe with state level information 
schools_state <-
  public_school %>% 
  group_by(ST) %>%
  summarise(Num_of_school = n(), Total_enrollment = sum(Members), 
            male = sum(Male, na.rm = TRUE), Female = sum(Female, na.rm = TRUE))

Beware that some schools have missing values for one of the gender and the use of sum() of those return a NA value. So we have to use a different method by adding na.rm = True.

head(schools_state) #There are 51 rows

Locale

public_school %>% 
  group_by(ST) %>%
  summarise(Urbanicity = n_distinct(Urban.centric.Locale))
# This method gives me the count of categories, but not how many within the category 
t1 <- public_school %>% 
  group_by(ST, Urban.centric.Locale) %>%
  summarise(Locale_count = n())
`summarise()` has grouped output by 'ST'. You can override using the `.groups` argument.
t1
t1<- spread(t1, Urban.centric.Locale, Locale_count)
t1
#Row number 8 and row 40 in the t1 dataframe 
t1[8, 4] <- 0   
t1[8, 5] <- 0
t1[40, 5] <- 0

t1
#Create a total column
t1$total <- t1$City + t1$Suburb + t1$Town + t1$Rural
#Replace each locale by its own percentage 
#Create a list first to check if calculation are done correctly
t1$City <- t1$City/t1$total
#Replace each locale by its own percentage 
t1$Suburb <- t1$Suburb/t1$total
t1$Town <- t1$Town/t1$total
t1$Rural <- t1$Rural/t1$total
t1

Note. The percentage of each locale by school types can also be used as a comparison to digital opportunity.

Task 2 Title I status

t2 <- public_school %>% 
  group_by(ST, Title.I.School.Status) %>%
  summarise(count = n())
`summarise()` has grouped output by 'ST'. You can override using the `.groups` argument.
head(t2)
levels(t2$Title.I.School.Status)
[1] "1-Title I targeted assistance eligible school-No program"         
[2] "2-Title I targeted assistance school"                             
[3] "3-Title I schoolwide eligible-Title I targeted assistance program"
[4] "4-Title I schoolwide eligible school-No program"                  
[5] "5-Title I schoolwide school"                                      
[6] "6-Not a Title I school"                                           
[7] "Unknown"                                                          
levels(t2$Title.I.School.Status) <- c("TAE_No", "TAE", "SW_TAE", "SW_No", "SW", "NOT_TitleI", "Unknown")
head(t2)
t2 <- spread(t2, Title.I.School.Status, count)
t2

Since we have to perform calculation, we will impute all NA as zero

t2[is.na(t2)] = 0
t2$total <- rowSums(t2[,2:8])
t2
t2$Unknown <- t2$Unknown/t2$total
t2$TAE_No <- t2$TAE_No/t2$total
t2$TAE <- t2$TAE/t2$total
t2$SW_TAE <- t2$SW_TAE/t2$total
t2$SW_No <-t2$SW_No/t2$total
t2$SW <- t2$SW/t2$total
t2$NOT_TitleI <- t2$NOT_TitleI/t2$total

Verify the calculation

#Confirming the percentages are calculated correctly
public_school %>% 
  group_by(ST, Title.I.School.Status) %>%
  summarise(each_count = n()) %>%
  mutate(Title1_percent = each_count/sum(each_count))
`summarise()` has grouped output by 'ST'. You can override using the `.groups` argument.

Task 3. Combine dataframes

Merge schools_state with urbanciity/rurality table

schools_state <- left_join(schools_state, t1, by = "ST")
head(schools_state)
#We can drop the total count for urbanicity/rurality -column index 10
schools_state <- schools_state[-c(10)]

head(schools_state)

Merge schools_state with Title 1 info

#Append the title 1 information by each state 
schools_state <- left_join(schools_state, t2, by = "ST")
head(schools_state)
#Again, drop the total count column , index 17
schools_state <- schools_state[-c(17)]
head(schools_state)
LS0tDQp0aXRsZTogIkFnZ3JlZ2F0ZSBMb2NhbGUgYW5kIFRpdGxlIEkgU3RhdHVzIGJ5IFN0YXRlIg0KYXV0aG9yOiBDYXJ5IEsuIEppbQ0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KSW1wb3J0IExpYnJhcnkvUGFja2FnZXMNCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmBgYA0KDQpMb2FkIHRoZSBwcm9jZXNzZWQgcHVibGljIHNjaG9vbCBmaWxlIGZyb20gUGFydCAyIDxodHRwczovL3JwdWJzLmNvbS9jYXJ5amltL25jZXMtcHMtZGF0YS1wcm9jZXNzaW5nPg0KDQpgYGB7ciBMb2FkIGRhdGFzZXR9DQpwdWJsaWNfc2Nob29sIDwtIHJlYWQuY3N2KCIuL0RhdGFzZXRzL3B1YmxpY19zY2hvb2xfcHJvY2Vzc2VkLmNzdiIsIGhlYWRlciA9IFQsIHN0cmluZ3NBc0ZhY3RvcnMgPSBUKQ0KIyBUaGlzIHRpbWUsIHN0cmluZ3NBc0ZhY3RvcnMgaXMgYXBwbGllZCB0byBlbnN1cmUgYWxsIGNoYXJhY3RlcnMgYXJlIGNvbnZlcnRlZA0KYGBgDQoNClZpZXcgY29sdW1ucw0KDQpgYGB7ciBjb2x1bW4gbmFtZXN9DQpjb2xuYW1lcyhwdWJsaWNfc2Nob29sKQ0KYGBgDQoNClZpZXcgZGF0YSB0eXBlDQoNCmBgYHtyIGRhdGEgdHlwZX0NCnN0cihwdWJsaWNfc2Nob29sKQ0KYGBgDQoNCiMjIFN0YXRlIExldmVsDQoNCkluIHRoZSBvcmlnaW5hbCBwdWJsaWMgc2Nob29sIGRhdGFzZXQsIHN0YXRlIG5hbWVzIGVudHJpZXMgYXJlIGluY29uc2lzdGVudC4gVGhlcmUgYXJlIHNvbWUgc3RhdGUgbmFtZXMgYXMgQUxMIENBUFMgYW5kIHNvbWUgYXMgbG93ZXIgY2FzZXMuIFRoZXJlZm9yZSwgdXNpbmcgc3RhdGUgYWJicmV2aWF0aW9uIGlzIGEgYmV0dGVyIHZhcmFpYmxlIHVubGVzcyB3ZSBwYXJzZSB0aGUgY2hhcnRhY3RlcnMgaW4gdGhlIGZ1bGwgc3RhdGUgbmFtZXMuDQoNCmBgYHtyIE51bWJlciBvZiBzY2hvb2wgYnkgU1R9DQojIEEgcXVpY2sgY291bnQgb2Ygc2Nob29scyBieSBlYWNoIHN0YXRlIGluIHRoZSBwcm9jZXNzZWQgZGF0YQ0KdGFibGUocHVibGljX3NjaG9vbCRTVCkNCmBgYA0KDQpPcmRlciB0aGUgbnVtYmVyIG9mIHNjaG9vbCBwZXIgc3RhdGUNCg0KYGBge3Igc29ydCB0aGUgdGFibGUgYnkgU1R9DQpzb3J0KHRhYmxlKHB1YmxpY19zY2hvb2wkU1QpKQ0KYGBgDQoNCk5vdGUuIEl0IHdvdWxkIGJlIGludGVyZXN0aW5nIHRvIHNlZSB0aGUgbnVtYmVyIG9mIHB1YmxpYyBzY2hvb2wgcGVyIHN0YXRlIGFuZCBjb21wYXJlIGl0IHRvIHRoZSBjdXJyZW50IGRpZ2l0YWwgb3Bwb3J0dW5pdHkgc3RhdHVzIG9mIHRoZXNlIHJlZ2lvbnMuDQoNCiMjIyBMb2NhbGUgSW5mb3JtYXRpb24NCmBgYHtyIE51bWJlciBvZiBTY2hvb2wgYnkgVXJiYW5pY2l0eS9SdXJhbGl0eX0NCnRhYmxlKHB1YmxpY19zY2hvb2wkVXJiYW4uY2VudHJpYy5Mb2NhbGUpDQpgYGANCg0KYGBge3IgTnVtYmVyIG9mIFNjaG9vbCBieSBUaXRpbGUgSSBTdGF0dXN9DQp0YWJsZShwdWJsaWNfc2Nob29sJFRpdGxlLkkuU2Nob29sLlN0YXR1cykNCmBgYA0KQWdncmVnYXRlIHRoZSB0eXBlcyBvZiBMb2NhbGUgYnkgU3RhdGUgYW5kIFByb3ZpZGUgYSBDb3VudCANCmBgYHtyIFVyYmFuaWNpdHkvUnVyYWxpdHkgYnkgU3RhdGV9DQojIENvbGxhcHNlIHRoZSBkYXRhIGJ5IFN0YXRlIGFuZCB0aGVpciBsb2NhbGUgDQpwdWJsaWNfc2Nob29sICU+JSANCiAgZ3JvdXBfYnkoU1QsIFVyYmFuLmNlbnRyaWMuTG9jYWxlKSAlPiUNCiAgc3VtbWFyaXplKGxvY2FsZSA9IG4oKSkNCmBgYA0KDQpSZXZpZXcgdGhlIFRpdGxlIDEgaW5mb3JtYXRpb24gYnkgc3RhdGUNCg0KYGBge3IgVGl0bGUgSSBTY2hvb2wgU3RhdHVzIGJ5IFN0YXRlfQ0KcHVibGljX3NjaG9vbCAlPiUgDQogIGdyb3VwX2J5KFNULCBUaXRsZS5JLlNjaG9vbC5TdGF0dXMpICU+JQ0KICBzdW1tYXJpemUoZWFjaF9jb3VudCA9IG4oKSkNCmBgYA0KV2UgY2FuIHNlZSB0aGF0IHNvbWUgc3RhdGVzIGhhdmUgbW9yZSByZXBvcnRlZCBjYXRlZ29yaWVzIG9mIFRpdGxlIEkgc3RhdHVzIA0KYGBge3IgVG90YWwgZW5yb2xsbWVudCBvZiBLLTEyIHN0dWRlbnQgYnkgc3RhdGV9DQpwdWJsaWNfc2Nob29sICU+JSANCiAgZ3JvdXBfYnkoU1QpICU+JQ0KICBzdW1tYXJpemUodG90YWxfZW5yb2xsbWVudCA9IHN1bShNZW1iZXJzKSkNCmBgYA0KDQojIyBUYXNrIDEuIENyZWF0ZSBhIG5ldyBkYXRhZnJhbWUgZm9yIHN0YXRlIGxldmVsIGluZm9ybWF0aW9uDQoNCkdyb3VwIHNlbGVjdGVkIHZhcmlhYmxlcyBieSBzdGF0ZSBsZXZlbCBhbmQgY2FsY3VsYXRlIGEgcGVyY2VudGFnZSBvZiB0aGF0IGluZm9ybWF0aW9uIG9yIGEgdG90YWwgY291bnQNCg0KIyMjIFRvdGFsIHN0dWRlbnQgZW5yb2xsbWVudCBhbmQgZ2VuZGVyDQoNCmBgYHtyIEFnZ3JlZ2F0ZSBlbnJvbGxtZW50IGluZm8gYnkgU3RhdGV9DQojIENyZWF0ZSBhIG5ldyBkYXRhZnJhbWUgd2l0aCBzdGF0ZSBsZXZlbCBpbmZvcm1hdGlvbiANCnNjaG9vbHNfc3RhdGUgPC0NCiAgcHVibGljX3NjaG9vbCAlPiUgDQogIGdyb3VwX2J5KFNUKSAlPiUNCiAgc3VtbWFyaXNlKE51bV9vZl9zY2hvb2wgPSBuKCksIFRvdGFsX2Vucm9sbG1lbnQgPSBzdW0oTWVtYmVycyksIA0KICAgICAgICAgICAgbWFsZSA9IHN1bShNYWxlLCBuYS5ybSA9IFRSVUUpLCBGZW1hbGUgPSBzdW0oRmVtYWxlLCBuYS5ybSA9IFRSVUUpKQ0KYGBgDQoNCkJld2FyZSB0aGF0IHNvbWUgc2Nob29scyBoYXZlIG1pc3NpbmcgdmFsdWVzIGZvciBvbmUgb2YgdGhlIGdlbmRlciBhbmQgdGhlIHVzZSBvZiBzdW0oKSBvZiB0aG9zZSByZXR1cm4gYSBOQSB2YWx1ZS4gU28gd2UgaGF2ZSB0byB1c2UgYSBkaWZmZXJlbnQgbWV0aG9kIGJ5IGFkZGluZyBuYS5ybSA9IFRydWUuDQoNCmBgYHtyIHZpZXcgZGF0YWZyYW1lfQ0KaGVhZChzY2hvb2xzX3N0YXRlKSAjVGhlcmUgYXJlIDUxIHJvd3MNCmBgYA0KDQojIyMgTG9jYWxlDQoNCmBgYHtyIExvY2FsZSBjb3VudCBieSBTdGF0ZX0NCnB1YmxpY19zY2hvb2wgJT4lIA0KICBncm91cF9ieShTVCkgJT4lDQogIHN1bW1hcmlzZShVcmJhbmljaXR5ID0gbl9kaXN0aW5jdChVcmJhbi5jZW50cmljLkxvY2FsZSkpDQojIFRoaXMgbWV0aG9kIGdpdmVzIG1lIHRoZSBjb3VudCBvZiBjYXRlZ29yaWVzLCBidXQgbm90IGhvdyBtYW55IHdpdGhpbiB0aGUgY2F0ZWdvcnkgDQpgYGANCg0KYGBge3IgQ3JlYXRlIGEgZGF0YWZyYW1lIGZvciBsb2NhbGUgaW5mb30NCnQxIDwtIHB1YmxpY19zY2hvb2wgJT4lIA0KICBncm91cF9ieShTVCwgVXJiYW4uY2VudHJpYy5Mb2NhbGUpICU+JQ0KICBzdW1tYXJpc2UoTG9jYWxlX2NvdW50ID0gbigpKQ0KdDENCmBgYA0KDQpgYGB7ciBSZXNoYXBlIGRhdGFmcmFtZSB0byBzcHJlYWQgbGV2ZWxzIGFzIGNvbHVtbiBoZWFkaW5nc30NCnQxPC0gc3ByZWFkKHQxLCBVcmJhbi5jZW50cmljLkxvY2FsZSwgTG9jYWxlX2NvdW50KQ0KdDENCmBgYA0KDQpgYGB7ciBGaWxsLWluIG1pc3NpbmcgdmFsdWVzIHdpdGggMH0NCiNSb3cgbnVtYmVyIDggYW5kIHJvdyA0MCBpbiB0aGUgdDEgZGF0YWZyYW1lIA0KdDFbOCwgNF0gPC0gMAkNCnQxWzgsIDVdIDwtIDANCnQxWzQwLCA1XSA8LSAwDQoNCnQxDQpgYGANCg0KYGBge3IgVG90YWwgYWNvcnNzIGxvY2FsZSBsZXZlbHN9DQojQ3JlYXRlIGEgdG90YWwgY29sdW1uDQp0MSR0b3RhbCA8LSB0MSRDaXR5ICsgdDEkU3VidXJiICsgdDEkVG93biArIHQxJFJ1cmFsDQojUmVwbGFjZSBlYWNoIGxvY2FsZSBieSBpdHMgb3duIHBlcmNlbnRhZ2UgDQojQ3JlYXRlIGEgbGlzdCBmaXJzdCB0byBjaGVjayBpZiBjYWxjdWxhdGlvbiBhcmUgZG9uZSBjb3JyZWN0bHkNCnQxJENpdHkgPC0gdDEkQ2l0eS90MSR0b3RhbA0KYGBgDQoNCmBgYHtyIFJlcGxhY2UgZWFjaCBsZXZlbCB2YWx1ZXMgYXMgcGVyY2VudGFnZXN9DQojUmVwbGFjZSBlYWNoIGxvY2FsZSBieSBpdHMgb3duIHBlcmNlbnRhZ2UgDQp0MSRTdWJ1cmIgPC0gdDEkU3VidXJiL3QxJHRvdGFsDQp0MSRUb3duIDwtIHQxJFRvd24vdDEkdG90YWwNCnQxJFJ1cmFsIDwtIHQxJFJ1cmFsL3QxJHRvdGFsDQp0MQ0KYGBgDQpOb3RlLiBUaGUgcGVyY2VudGFnZSBvZiBlYWNoIGxvY2FsZSBieSBzY2hvb2wgdHlwZXMgY2FuIGFsc28gYmUgdXNlZCBhcyBhIGNvbXBhcmlzb24gdG8gZGlnaXRhbCBvcHBvcnR1bml0eS4gDQoNCiMjIFRhc2sgMiBUaXRsZSBJIHN0YXR1cw0KDQpgYGB7ciBDcmVhdGUgYSBkYXRhZnJhbWUgZm9yIFRpdGxlIEkgc3RhdHVzIGxldmVsc30NCnQyIDwtIHB1YmxpY19zY2hvb2wgJT4lIA0KICBncm91cF9ieShTVCwgVGl0bGUuSS5TY2hvb2wuU3RhdHVzKSAlPiUNCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKQ0KYGBgDQoNCmBgYHtyfQ0KaGVhZCh0MikNCmBgYA0KDQoNCmBgYHtyfQ0KbGV2ZWxzKHQyJFRpdGxlLkkuU2Nob29sLlN0YXR1cykNCmBgYA0KDQoNCmBgYHtyIHJlbmFtZSBmYWN0b3JzIGxldmVsfQ0KbGV2ZWxzKHQyJFRpdGxlLkkuU2Nob29sLlN0YXR1cykgPC0gYygiVEFFX05vIiwgIlRBRSIsICJTV19UQUUiLCAiU1dfTm8iLCAiU1ciLCAiTk9UX1RpdGxlSSIsICJVbmtub3duIikNCmBgYA0KDQpgYGB7cn0NCmhlYWQodDIpDQpgYGANCg0KYGBge3J9DQp0MiA8LSBzcHJlYWQodDIsIFRpdGxlLkkuU2Nob29sLlN0YXR1cywgY291bnQpDQp0Mg0KYGBgDQpTaW5jZSB3ZSBoYXZlIHRvIHBlcmZvcm0gY2FsY3VsYXRpb24sIHdlIHdpbGwgaW1wdXRlIGFsbCBOQSBhcyB6ZXJvIA0KYGBge3IgRmlsbC1pbiBtaXNzaW5nIGNvdW50cyBhcyAwfQ0KdDJbaXMubmEodDIpXSA9IDANCmBgYA0KDQpgYGB7ciBDcmVhdGUgdG90YWwgY29sdW1ufQ0KdDIkdG90YWwgPC0gcm93U3Vtcyh0MlssMjo4XSkNCnQyDQpgYGANCg0KDQpgYGB7ciBDYWxjdWxhdGUgcGVyY2VudGFnZSBvZiBlYWNoIGxldmVscyBieSB0b3RhbH0NCnQyJFVua25vd24gPC0gdDIkVW5rbm93bi90MiR0b3RhbA0KdDIkVEFFX05vIDwtIHQyJFRBRV9Oby90MiR0b3RhbA0KdDIkVEFFIDwtIHQyJFRBRS90MiR0b3RhbA0KdDIkU1dfVEFFIDwtIHQyJFNXX1RBRS90MiR0b3RhbA0KdDIkU1dfTm8gPC10MiRTV19Oby90MiR0b3RhbA0KdDIkU1cgPC0gdDIkU1cvdDIkdG90YWwNCnQyJE5PVF9UaXRsZUkgPC0gdDIkTk9UX1RpdGxlSS90MiR0b3RhbA0KYGBgDQoNClZlcmlmeSB0aGUgY2FsY3VsYXRpb24NCg0KYGBge3IgVmVyaWZ5IHRoZSBjYWxjdWxhdGlvbn0NCiNDb25maXJtaW5nIHRoZSBwZXJjZW50YWdlcyBhcmUgY2FsY3VsYXRlZCBjb3JyZWN0bHkNCnB1YmxpY19zY2hvb2wgJT4lIA0KICBncm91cF9ieShTVCwgVGl0bGUuSS5TY2hvb2wuU3RhdHVzKSAlPiUNCiAgc3VtbWFyaXNlKGVhY2hfY291bnQgPSBuKCkpICU+JQ0KICBtdXRhdGUoVGl0bGUxX3BlcmNlbnQgPSBlYWNoX2NvdW50L3N1bShlYWNoX2NvdW50KSkNCmBgYA0KDQojIyBUYXNrIDMuIENvbWJpbmUgZGF0YWZyYW1lcyANCg0KTWVyZ2Ugc2Nob29sc19zdGF0ZSB3aXRoIHVyYmFuY2lpdHkvcnVyYWxpdHkgdGFibGUNCg0KYGBge3J9DQpzY2hvb2xzX3N0YXRlIDwtIGxlZnRfam9pbihzY2hvb2xzX3N0YXRlLCB0MSwgYnkgPSAiU1QiKQ0KYGBgDQoNCmBgYHtyfQ0KaGVhZChzY2hvb2xzX3N0YXRlKQ0KYGBgDQoNCmBgYHtyfQ0KI1dlIGNhbiBkcm9wIHRoZSB0b3RhbCBjb3VudCBmb3IgdXJiYW5pY2l0eS9ydXJhbGl0eSAtY29sdW1uIGluZGV4IDEwDQpzY2hvb2xzX3N0YXRlIDwtIHNjaG9vbHNfc3RhdGVbLWMoMTApXQ0KDQpoZWFkKHNjaG9vbHNfc3RhdGUpDQpgYGANCg0KTWVyZ2Ugc2Nob29sc19zdGF0ZSB3aXRoIFRpdGxlIDEgaW5mbw0KDQpgYGB7cn0NCiNBcHBlbmQgdGhlIHRpdGxlIDEgaW5mb3JtYXRpb24gYnkgZWFjaCBzdGF0ZSANCnNjaG9vbHNfc3RhdGUgPC0gbGVmdF9qb2luKHNjaG9vbHNfc3RhdGUsIHQyLCBieSA9ICJTVCIpDQpgYGANCg0KYGBge3J9DQpoZWFkKHNjaG9vbHNfc3RhdGUpDQpgYGANCg0KYGBge3IgZHJvcCB0b3RhbCBjb2x1bW4gKGR1cGxpY2F0ZWQgY291bnQpfQ0KI0FnYWluLCBkcm9wIHRoZSB0b3RhbCBjb3VudCBjb2x1bW4gLCBpbmRleCAxNw0Kc2Nob29sc19zdGF0ZSA8LSBzY2hvb2xzX3N0YXRlWy1jKDE3KV0NCmBgYA0KDQpgYGB7cn0NCmhlYWQoc2Nob29sc19zdGF0ZSkNCmBgYA0KDQpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KI0V4cG9ydCB0aGUgZGF0YWZyYW1lIGZvciByZWNvcmQNCiN3cml0ZS5jc3Yoc2Nob29sc19zdGF0ZSwiRDovRG9jdW1lbnRzL1IvRGlnaXRhbCBEaXZpZGUvT3Blbl9EYXRhX0NoYWxsZW5nZS9BbmFseXNpcy9zY2hvb2xzX2J5X3N0YXRlLmNzdiIpDQpgYGANCg0K