Importing and Inspecting Data

path    <- "/Users/frenandezlawrence/Downloads/Fall_2022-2024_Firsttime_Fulltime_Cohort_data_with_Unmet_Need.xlsx"
sheets  <- excel_sheets(path)
sheets
[1] "Variables"                      "Fall 2022 Financial Aid"        "Fall 2022 Enrollment"           "Fall 2023 Financial Aid"        "Fall 2023 Enrollment"           "Fall 2024 Financial Aid Prelim"
[7] "Fall 2024 Enrollment Prelim"    "Data Dictionary"               

Standardizing Columns Header and Values

df_example <- read_xlsx(path, sheet = sheets[2]) %>%
  clean_names()
head(df_example)

#The below is used to standardize Dependency Status column to ensure that all three years represented using the same format.
dep_lookup <- c(
  "0" = "Unkn",
  "1" = "Dependent",
  "2" = "Independent",
  "3" = "Unkn"
)

#The below is used to standardize Race column to ensure that all three years represented using the same format.
race_text_to_code <- c(
  "African-American"= 1,
  "Native-American" = 2,
  "Asian"           = 3,
  "Hispanic"        = 4,
  "White"           = 5,
  "Native-Hawaiian" = 6,
  "Mulitracial"     = 7,
  "International"   = 8
)

Reading and Type Casting Cohort 2022 to ustilize as the standard for the additional cohorts

## Enrollment 2022 Data

enr22_raw <- read_xlsx(path, sheet = "Fall 2022 Enrollment")
print(names(enr22))
 [1] "collection_term"                       "collection_year"                       "study_id"                              "gender"                                "zip_code"                             
 [6] "tuition_status"                        "high_school_gpa"                       "distance_education_enrollment"         "sat_2016_math_score"                   "sat_2016_ebrw_score"                  
[11] "act_math_score"                        "act_english_score"                     "act_reading_score"                     "act_science_score"                     "act_composite_score"                  
[16] "admission_test_flag"                   "admission_exemption"                   "math_remedial_assessment"              "english_remedial_assessment"           "reading_remedial_assessment"          
[21] "military_status"                       "majors"                                "cip_code"                              "age"                                   "newrace"                              
[26] "term_credit_hours_attempted2022fall"   "semesterhoursearned2022fall"           "cumulativegpa2022fall"                 "retained_fall2023"                     "casa_student"                         
[31] "returned_spring2023"                   "term_credit_hours_attempted2023spring" "semesterhoursearned2023spring"         "semestergpa2023spring"                 "cumulativehoursearned2023spring"      
[36] "cumulativegpa2023spring"               "college"                              
enr22     <- enr22_raw %>%
clean_names() %>%
{ if (!"cip_code" %in% names(.)) mutate(., cip_code = NA_character_) else . } %>%
  mutate(
    study_id                              = as.character(study_id),
    zip_code                              = str_pad(as.character(zip_code), 5, "left", "0"),
    retained_fall2023                     = case_when(retained_fall2023  %in% c("Yes","Y","TRUE")   ~ TRUE,
                                            retained_fall2023  %in% c("No","N","FALSE")             ~ FALSE,
                                            TRUE                                                    ~ NA),
    casa_student                          = case_when(casa_student   %in% c("Yes","Y","TRUE")       ~ TRUE,
                                            casa_student   %in% c("No","N","FALSE")                 ~ FALSE,
                                            TRUE                                                    ~ NA),
    returned_spring2023                   = case_when(returned_spring2023 %in% c("Yes","Y","TRUE")  ~ TRUE,
                                            returned_spring2023 %in% c("No","N","FALSE")            ~ FALSE,
                                            TRUE                                                    ~ NA),
    gender                                = factor(gender, levels = c("F","M")),
    tuition_status                        = as.factor(tuition_status),
    newrace                               = case_when(
    newrace %in% names(race_text_to_code) ~ race_text_to_code[newrace],
            TRUE                          ~ as.numeric(newrace)),
  
    high_school_gpa                       = as.numeric(high_school_gpa),
    sat_2016_math_score                   = as.numeric(sat_2016_math_score),
    sat_2016_ebrw_score                   = as.numeric(sat_2016_ebrw_score),
    age                                   = as.integer(age),
    cip_code                              = as.character(cip_code),
    admission_test_flag                   = as.integer(admission_test_flag),,
    distance_education_enrollment         = as.integer(distance_education_enrollment),
    act_math_score                        = as.integer(act_math_score),
    act_english_score                     = as.integer(act_english_score),
    act_reading_score                     = as.integer(act_reading_score),
    act_science_score                     = as.integer(act_science_score),
    act_composite_score                   = as.integer(act_composite_score),
    admission_exemption                   = as.integer(admission_exemption),
    math_remedial_assessment              = as.integer(math_remedial_assessment),
    english_remedial_assessment           = as.integer(english_remedial_assessment),
    reading_remedial_assessment           = as.integer(reading_remedial_assessment),
    military_status                       = as.integer(military_status),
    majors                                = as.character(majors),
    term_credit_hours_attempted2022fall   = as.integer(term_credit_hours_attempted2022fall),
    semesterhoursearned2022fall           = as.integer(semesterhoursearned2022fall),
    cumulativegpa2022fall                 = as.numeric(cumulativegpa2022fall),
    term_credit_hours_attempted2023spring = as.integer(term_credit_hours_attempted2023spring),
    semesterhoursearned2023spring         = as.integer(semesterhoursearned2023spring),
    semestergpa2023spring                 = as.numeric(semestergpa2023spring),
    cumulativehoursearned2023spring       = as.integer(cumulativehoursearned2023spring),
    cumulativegpa2023spring               = as.numeric(cumulativegpa2023spring),
    college                               = as.character(college),
    collection_term                       = "Fall",
    collection_year                       = 2022
  )

## Financial Aid 2022 Data
fa22_raw <- read_xlsx(path, sheet = "Fall 2022 Financial Aid")
fa22     <- fa22_raw %>%
  clean_names() %>%
    transmute(
    study_id                              = as.character(study_id),
    family_size                           = as.integer(family_size),
    dependency_status                     = factor(dependency_status, levels = c("Dependent","Independent","Unkn")),
    expected_family_contribution          = as.numeric(expected_family_contribution),
    cost_of_attendance                    = as.numeric(cost_of_attendance),
    financial_aid_disbursement_amount     = as.numeric(financial_aid_disbursement_amount),
    pell_recipient                        = case_when(pell_recipient  %in% c("Yes","Y","TRUE")  ~ TRUE,
                                            pell_recipient  %in% c("No","N","FALSE")            ~ FALSE,
                                            TRUE                                                ~ NA),
    unmetneed_amount                      = as.numeric(unmetneed_amount),
    unmetneed_category                    = as.integer(unmetneed_category),
    family_income_category                = as.integer(family_income_category),
    first_generation                      = factor(first_generation, levels = c("Yes","No","Unkn"))
  )

cohort22 <- left_join(enr22, fa22, by = "study_id")

##Looping and Data Cleansing of All Three Cohorts

year_sheets <- tribble(
  ~year, ~fa_sheet,                         ~enr_sheet,
  2022,  "Fall 2022 Financial Aid",         "Fall 2022 Enrollment",
  2023,  "Fall 2023 Financial Aid",         "Fall 2023 Enrollment",
  2024,  "Fall 2024 Financial Aid Prelim",  "Fall 2024 Enrollment Prelim"
)

vars_raw      <- read_xlsx(path, sheet = "Variables", col_names = FALSE)
New names:
• `` -> `...1`
• `` -> `...2`
all_cohorts   <- purrr::pmap_dfr(
  .l = list(
    year      = year_sheets$year,
    fa_sheet  = year_sheets$fa_sheet,
    enr_sheet = year_sheets$enr_sheet),
  
  .f = function(year, fa_sheet, enr_sheet) {
    next_retained                    <- paste0("retained_fall", year + 1)
    next_returned                    <- paste0("returned_spring", year + 1)
    next_termcreditattemptedfall     <- paste0("term_credit_hours_attempted", year,"fall")
    next_semesterhoursearnedfall     <- paste0("semesterhoursearned", year,"fall")
    next_cumulativegpafall           <- paste0("cumulativegpa", year,"fall")
    next_termcreditattemptedspring   <- paste0("term_credit_hours_attempted", year + 1,"spring")
    next_semesterhoursearnedspring   <- paste0("semesterhoursearned", year + 1,"spring")
    next_semestergpaspring           <- paste0("semestergpa", year + 1,"spring")
    next_cumulativehoursearnedspring <- paste0("cumulativehoursearned", year + 1,"spring")
    next_cumulativegpaspring         <- paste0("cumulativegpa", year + 1,"spring")
    
#Enrollment Fields Cleaning 
    
    enr_raw <- read_xlsx(path, sheet = enr_sheet)
    enr     <- enr_raw %>%
    clean_names() %>%
{ if (!"cip_code" %in% names(.)) mutate(., cip_code = NA_character_) else . } %>%
  mutate(
    across(
      any_of(next_retained),
        ~ case_when(
          .x %in% c("Yes","Y","TRUE")  ~ TRUE,
          .x %in% c("No","N","FALSE")  ~ FALSE,
          TRUE                         ~ NA)),
    
    study_id                     = as.character(study_id),
    zip_code                     = str_pad(as.character(zip_code), 5, "left", "0"),
    casa_student                 = (casa_student      == "Yes"),
    across(
      any_of(next_retained),
        ~ case_when(
        .x %in% c("Yes","Y","TRUE")  ~ TRUE,
        .x %in% c("No","N","FALSE")  ~ FALSE,
        TRUE                         ~ NA)),
    gender                       = factor(gender, levels = c("F","M")),
    tuition_status               = factor(tolower(as.character(tuition_status))),
    newrace_str                  = as.character(newrace),
    newrace                      = if_else(
                                    newrace_str %in% names(race_text_to_code),
                                    race_text_to_code[newrace_str],
                                    as.numeric(newrace_str)),
    
    high_school_gpa               = as.numeric(high_school_gpa),
    sat_2016_math_score           = as.numeric(sat_2016_math_score),
    sat_2016_ebrw_score           = as.numeric(sat_2016_ebrw_score),
    age                           = as.integer(age),
    cip_code                      = as.character(cip_code),
    admission_test_flag           = as.integer(admission_test_flag),
    admission_exemption           = as.character(admission_exemption),
    distance_education_enrollment = as.integer(distance_education_enrollment),
    act_math_score                = as.integer(act_math_score),
    act_english_score             = as.integer(act_english_score),
    act_reading_score             = as.integer(act_reading_score),
    act_science_score             = as.integer(act_science_score),
    act_composite_score           = as.integer(act_composite_score),
    admission_exemption           = as.integer(admission_exemption),
    math_remedial_assessment      = as.integer(math_remedial_assessment),
    english_remedial_assessment   = as.integer(english_remedial_assessment),
    reading_remedial_assessment   = as.integer(reading_remedial_assessment),
    military_status               = as.integer(military_status),
    majors                        = as.character(majors),
    
#Handling of Dynamic Column Term Credit Attempted Fall 2022-2024
    across(any_of(next_termcreditattemptedfall),
          as.integer),

#Handling of Dynamic Column Semester Hours Earned Fall 2022-2024
    across(any_of(next_semesterhoursearnedfall),
          as.integer),
       
#Handling of Dynamic Column Cumulative GPA Fall 2022-2024
    across(any_of(next_cumulativegpafall ),
          ~ round(as.numeric(.x), 2)),
       
#Handling of Dynamic Column Term Credit Attempted Spring 2023-2025
    across(any_of(next_termcreditattemptedspring),
          as.integer),
       
#Handling of Dynamic Column Semester Hours Earned Spring 2023-2025
    across(any_of( next_semesterhoursearnedspring),
          as.integer),
       
#Handling of Dynamic Column GPA Spring 2023-2025
    across(any_of(next_semestergpaspring),
          ~ round(as.numeric(.x), 2)),
       
#Handling of Dynamic Column Cumulative Hours Earned Spring 2023-2025
    across(any_of(next_cumulativehoursearnedspring),
          as.integer),
       
#Handling of Dynamic Column Cumulative GPA Spring 2023-2025
    across(any_of(next_cumulativegpaspring ),
          ~ round(as.numeric(.x), 2)),
       
    college = as.character(college),
    collection_term     = "Fall",
    collection_year     = year)


#Enrollment Data Cleaning 
    fa_raw <- read_xlsx(path, sheet = fa_sheet)
    fa     <- fa_raw %>%
    clean_names() %>%
    transmute(
      study_id                          = as.character(study_id),
      family_size                       = as.integer(family_size),
      dependency_status                 = as.character(dependency_status),
        
#Mapping any numeric values using dep_lookup, Otherwise we will keep text
      dependency_status                 = if_else(
                                           dependency_status %in% names(dep_lookup),
                                           dep_lookup[dependency_status],
                                           dependency_status), 
      dependency_status                 = factor(
                                           dependency_status,
                                           levels = c("Dependent","Independent","Unkn")),
      expected_family_contribution      = as.numeric(expected_family_contribution),
      cost_of_attendance                = as.numeric(cost_of_attendance),
      financial_aid_disbursement_amount = as.numeric(financial_aid_disbursement_amount),
      pell_recipient                    = case_when(pell_recipient  %in% c("Yes","Y","TRUE")  ~ TRUE,
                                        pell_recipient  %in% c("No","N","FALSE")  ~ FALSE,
                                        TRUE                                             ~ NA),
      unmetneed_amount                  = as.numeric(unmetneed_amount),
      unmetneed_category                = as.integer(unmetneed_category),
      family_income_category            = as.integer(family_income_category),
      first_generation                  = factor(first_generation, levels = c("Yes","No","Unkn")))

#Joining and Returning the data
    df_year <- left_join(enr, fa, by = "study_id")%>%

#Filtering Out the Columns that have over 70% of data missing 
    select(
      -sat_2016_math_score,
      -sat_2016_ebrw_score,
      -act_math_score,
      -act_english_score,
      -act_reading_score,
      -act_science_score,
      -act_composite_score,
      -newrace_str) %>%  

    mutate(
      admission_exemption = as.character(admission_exemption),
      admission_exemption = coalesce(na_if(admission_exemption, ""), "1"),
      admission_exemption = as.integer(admission_exemption)) %>%
    
#Replacing blanks with 9 which represents race as unknown   
    mutate(
      newrace = as.character(newrace),
      newrace = coalesce(na_if(newrace, ""), "9"),
      newrace = as.integer(newrace)) %>%
  
  
#Handling Dependency Status Blanks
    mutate(
      dependency_status = as.character(dependency_status),
      dependency_status = coalesce(na_if(dependency_status, ""), "Unkn"),
      dependency_status = factor(dependency_status,levels = c("Dependent","Independent","Unkn"))) %>%

#Identifying, Replacing Outliers and Imputing Missing Values with Mean   
      mutate(
        across(
          c(expected_family_contribution, unmetneed_amount, cost_of_attendance, financial_aid_disbursement_amount, high_school_gpa,family_size),
          ~ {

#Computing the mean for each column on a yearly basis
            med    <- median(.x, na.rm = TRUE)
            
#Imputing Missing Values
            x0   <- if_else(is.na(.x), med, .x)
            
#Computing IQR Boundaries
            q    <- quantile(x0, c(0.25, 0.75), na.rm = TRUE)
            iqr  <- diff(q)
            lower <- q[1] - 1.5 * iqr
            upper <- q[2] + 1.5 * iqr
            
#Replacing outliers with the year’s mean
            ifelse(x0 < lower | x0 > upper, med, x0)
            }
            )
            ) %>%

#Dropping Records which are NA since it is less than 5% of data set
    filter(
      if_all(
        any_of(c(
          paste0("term_credit_hours_attempted",  year + 1, "spring"),
          paste0("semestergpa",                  year + 1, "spring"),
          paste0("cumulativehoursearned",        year + 1, "spring"),
          paste0("cumulativegpa",                year + 1, "spring")
          )),
          ~ !is.na(.x)
            )
          )
    
    
##The Below Lines of Codes represents lookup tables for varibales.
##For Numeric Variables a label has been created
##For Text Fields a Code has been created to used for modelling 
    
  family_inc_lookup             <- tibble(
  family_income_category        = 1:10,
  family_income_label           = c("Lowest Thru 25,000", "25,001 Thru 50,000", "50,001 Thru 75,000",
                                    "75,001 Thru 100,000", "100,001 Thru 125,000", "125,001 Thru 150,000",
                                    "150,001 Thru 175,000", "175,001 Thru 200,000", "200,001 Thru 225,000",
                                    "225,001+"))

  unmetneed_cat_lookup          <- tibble(
  unmetneed_category            = 1:7,
  unmetneed_category_label      = c("$1 Thru $5000", "$5001 Thru $7500", "$7501 Thru $10000",
                                    "$10001 Thru $15000", "$15001 Thru Highest", "No Unmet Need",
                                    "Unknown Unmet Need"))
  
  distance_edu_lookup           <- tibble(
  distance_education_enrollment = 1:3,
  distance_education_label      = c("Enrolled Exclusively in Distance Education", "Enrolled in Some but Not All Distance Education", "Not Enrolled in Any Distance Education"))
  
  admission_test_lookup         <- tibble(
  admission_test_flag           = 0:5,
  admission_test_flag_label     = c("No Test Required for Admission", "SAT Test Required", "ACT Test Required",
                                    "Either ACT or SAT Required", "Institution Test Required", "Because of Admission Exemption"))
  
  military_status_lookup        <- tibble(
  military_status               = 1:5,
  military_status_label         = c("Active Duty Member of Any of the US Uniform Forces", "Veteran or Former Active Duty Member of Any of The US Uniformed Forces", "Reserve Duty Member of Any of The US                                                Armed Forces, Including The National Guard", "Spouse or Dependent Child of an Active, Reserve, or Former Member of The US Uniformed Forces", "None of the above"))
  
  frace_lookup                  <- tibble(
  newrace                       = 1:9,
  race_label                    = c("African-Americans", "Native-Americans", "Asian",
                                    "Hispanic", "White", "Native-Hawaiians",
                                    "MultiRacials", "International","Unknown"))
    
  dependency_status_lookup      <- tibble(
  dependency_status             = c("Unkn", "Dependent","Independent"),
  dependency_code               = 0:2)
   
  gender_lookup                 <- tibble(
  gender                        = c("M","F"),
  gender_code                   = 1:2)
    
  
  tuition_status_lookup         <- tibble(
  tuition_status                = c("in-state", "out-of-state"),
  tuition_status_code           = 2:3)
   
   
  first_generation_lookup       <- tibble(
  first_generation             = c("No", "Yes", "Unkn"),
  first_generation_code         = c(0,1,9))

#Adding the Additional Columns to dataset   
  df_year <- df_year %>%
  left_join(family_inc_lookup,        by = "family_income_category") %>%
  left_join(unmetneed_cat_lookup,     by = "unmetneed_category") %>%
  left_join(distance_edu_lookup,      by = "distance_education_enrollment") %>%
  left_join(admission_test_lookup,    by = "admission_test_flag") %>%
  left_join(military_status_lookup,   by = "military_status") %>%
  left_join(frace_lookup,             by = "newrace") %>%
  left_join(dependency_status_lookup, by = "dependency_status")  %>%
  left_join(gender_lookup,            by = "gender")  %>%
  left_join(tuition_status_lookup,    by = "tuition_status")  %>%
  left_join(first_generation_lookup,  by = "first_generation") 



# Identify dynamic column names directly 
  fall_credit_col   <- next_termcreditattemptedfall
  fall_earned_col   <- next_semesterhoursearnedfall
  spring_credit_col <- next_termcreditattemptedspring
  spring_earned_col <- next_semesterhoursearnedspring
  spring_cumearned_col <- next_cumulativehoursearnedspring

# Ensuring Columns are Found
  if(length(fall_credit_col)!=1 || length(fall_earned_col)!=1 || length(spring_credit_col)!=1 || length(spring_earned_col)!=1) {
    stop(glue::glue(
      "[{year}] Unable to find exactly one match for dynamic columns:
",
      "fall_credit: {fall_credit_col}; fall_earned: {fall_earned_col};
",
      "spring_credit: {spring_credit_col}; spring_earned: {spring_earned_col}"
    ))
  }

# Feature engineering using resolved column names
  df_year <- df_year %>%
    mutate(
      cc_rate_fall      = round(.data[[fall_earned_col]] / .data[[fall_credit_col]],2),
      cc_rate_spring    = round(.data[[spring_earned_col]] / .data[[spring_credit_col]],2),
      on_track_fall     = cc_rate_fall >= 1.0,
      full_time_spring  = .data[[spring_credit_col]] >= 12,
      unmet_need_ratio  = round(unmetneed_amount / cost_of_attendance,2),
      aid_coverage_ratio= round(financial_aid_disbursement_amount / cost_of_attendance,2),
      pell_coverage_ratio = round(if_else(pell_recipient, aid_coverage_ratio, 0),2),
      gpa_delta         = .data[[paste0("cumulativegpa", year+1, "spring")]] -
                            .data[[paste0("cumulativegpa", year, "fall")]],
      gpa_trend         = case_when(
                             gpa_delta >  0.2 ~ "Upward",
                             gpa_delta < -0.2 ~ "Downward",
                             TRUE             ~ "Stable"),
      credits_growth    = .data[[spring_cumearned_col]] - .data[[fall_earned_col]],
      high_unmet_need   = unmetneed_amount > 0.5 * cost_of_attendance,
      age_group         = case_when(
                             age < 20           ~ "Less Than 20",
                             age < 25           ~ "20 To 24",
                             age < 30           ~ "25 To 29",
                             TRUE               ~ "30+" )
    ) %>%
    rowwise() %>%
    mutate(
      risk_score = sum(
        !on_track_fall,
        gpa_delta < 0,
        high_unmet_need,
        na.rm = TRUE
      )
    ) %>%
    ungroup() %>%
    mutate(
      race_financial_stress = paste0(race_label, "_", if_else(high_unmet_need, "Stress", "NoStress")),
      pct_distance_ed       = round(distance_education_enrollment / max(distance_education_enrollment, na.rm = TRUE),2)
    )
  
#Writing Each Year Data to A separate CSV to Upload to Tableau        
  file_name <- paste0("/Users/frenandezlawrence/Downloads/Team_B",year,"Cleaned_DataFinal.csv")
  write.csv(df_year, file      = file_name, row.names = FALSE)

  df_year
  }
)

Performing Final Quality Checks on Merged Dataset

#Performing Uniqueness Check
  all_cohorts %>%
    count(collection_year, study_id) %>%
    filter(n > 1)

# Performing Missingness Check
  all_cohorts %>%
    summarise_all(~ mean(is.na(.))) %>%
    pivot_longer(everything(), names_to = "var", values_to = "pct_missing")

# Perfoming a final look at dataset
#The NAs displaying in the glimpse is for the dynamic columns which are not not applicable for all years. 
glimpse(all_cohorts)
Rows: 5,957
Columns: 85
$ collection_term                       <chr> "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fal…
$ collection_year                       <dbl> 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, …
$ study_id                              <chr> "20227000000002", "20227000000004", "20227000000005", "20227000000006", "20227000000007", "20227000000008", "20227000000010", "20227000000012", "20227000000…
$ gender                                <chr> "F", "F", "F", "M", "F", "M", "F", "M", "F", "M", "F", "M", "M", "F", "F", "M", "F", "M", "M", "M", "F", "M", "M", "F", "F", "M", "F", "F", "F", "F", "M", "…
$ zip_code                              <chr> "21220", "10500", "21045", "21085", "21217", "21244", "21212", "21043", "21206", "08000", "20708", "21040", "20695", "21117", "21218", "21500", "21213", "19…
$ tuition_status                        <chr> "out-of-state", "out-of-state", "in-state", "in-state", "in-state", "in-state", "in-state", "in-state", "in-state", "out-of-state", "in-state", "in-state", …
$ high_school_gpa                       <dbl> 2.29, 3.00, 3.10, 1.97, 4.00, 2.71, 2.80, 2.76, 2.72, 3.30, 2.35, 2.45, 3.04, 3.88, 3.00, 3.50, 2.84, 2.96, 3.19, 2.67, 3.65, 2.81, 3.10, 3.08, 3.65, 3.20, …
$ distance_education_enrollment         <int> 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 3, 3, 3, 3, 2, 2, 1, 3, 2, 3, 3, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 3, 2, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 2, 3, 3, 3, 2, 2, 3, 2, 3, …
$ admission_test_flag                   <int> 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5, 5, 5, 3, 5, 3, 5, …
$ admission_exemption                   <int> 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ math_remedial_assessment              <int> 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, …
$ english_remedial_assessment           <int> 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ reading_remedial_assessment           <int> 1, 1, 1, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, …
$ military_status                       <int> 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, …
$ majors                                <chr> "NURS", "PSYC", "SOWK", "AREN", "SWAN", "MKTG", "SWAN", "COSC", "SOCI", "ACCT", "NURS", "ACCT", "HLTH", "SOWK", "PSYC", "BUAD", "SWAN", "AREN", "EEGR", "PHE…
$ cip_code                              <chr> "51.3801", "42.0101", "44.0701", "4.0902", "10.0304", "52.1401", "10.0304", "11.0101", "45.1101", "52.0301", "51.3801", "52.0301", "51.2207", "44.0701", "42…
$ age                                   <int> 29, 18, 23, 19, 18, 19, 22, 20, 20, 20, 20, 20, 20, 21, 23, 19, 19, 19, 19, 19, 18, 19, 19, 20, 18, 19, 18, 19, 17, 18, 19, 18, 19, 18, 18, 19, 18, 18, 18, …
$ newrace                               <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 5, 7, 1, 1, 1, 1, 1, 1, 4, 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, 4, 1, …
$ term_credit_hours_attempted2022fall   <int> 15, 14, 12, 16, 14, 13, 14, 15, 14, 15, 18, 16, 15, 14, 17, 15, 17, 17, 12, 15, 16, 16, 13, 16, 15, 16, 15, 14, 16, 16, 13, 13, 14, 16, 16, 16, 16, 16, 14, …
$ semesterhoursearned2022fall           <int> 15, 14, 12, 10, 14, 13, 14, 14, 13, 0, 18, 16, 15, 14, 17, 15, 17, 14, 12, 11, 16, 10, 13, 13, 15, 3, 11, 7, 12, 10, 13, 10, 14, 16, 10, 16, 16, 1, 14, 17, …
$ cumulativegpa2022fall                 <dbl> 3.36, 3.43, 3.67, 1.15, 3.40, 1.92, 4.00, 3.20, 2.70, 0.00, 2.64, 2.44, 2.20, 3.10, 4.00, 2.50, 4.00, 2.18, 3.67, 1.45, 3.58, 1.90, 1.92, 2.46, 2.73, 0.69, …
$ retained_fall2023                     <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TR…
$ casa_student                          <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FAL…
$ returned_spring2023                   <chr> "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Y…
$ term_credit_hours_attempted2023spring <int> 16, 16, 15, 12, 15, 15, 13, 14, 13, 12, 14, 12, 17, 13, 18, 17, 13, 12, 16, 12, 13, 13, 14, 16, 15, 13, 14, 13, 8, 15, 16, 9, 14, 16, 13, 20, 15, 13, 16, 13…
$ semesterhoursearned2023spring         <int> 16, 16, 9, 6, 14, 9, 13, 0, 7, 0, 14, 12, 6, 13, 18, 14, 13, 8, 16, 3, 13, 13, 10, 3, 15, 3, 14, 7, 0, 6, 16, 6, 10, 16, 7, 20, 15, 3, 16, 13, 12, 3, 8, 16,…
$ semestergpa2023spring                 <dbl> 3.12, 2.81, 2.75, 1.00, 2.73, 1.80, 3.60, 0.00, 1.23, 0.00, 1.93, 2.50, 0.46, 3.08, 4.00, 2.79, 3.77, 3.00, 3.19, 0.00, 3.77, 2.77, 3.20, 0.60, 2.67, 0.46, …
$ cumulativehoursearned2023spring       <int> 31, 30, 21, 16, 30, 16, 27, 14, 20, 0, 32, 28, 21, 27, 35, 32, 30, 22, 53, 14, 29, 23, 23, 16, 30, 6, 22, 11, 12, 19, 29, 16, 24, 32, 20, 36, 31, 4, 33, 33,…
$ cumulativegpa2023spring               <dbl> 3.22, 3.10, 3.21, 1.23, 3.08, 2.09, 3.83, 3.43, 1.87, 0.00, 2.29, 2.46, 1.39, 3.09, 4.00, 2.62, 3.90, 2.53, 3.39, 0.94, 3.68, 2.39, 2.48, 1.65, 2.70, 0.75, …
$ college                               <chr> "SCHP", "CLA", "SOWK", "SAP", "CLA", "SBM", "CLA", "SCMNS", "CLA", "SBM", "SCHP", "SBM", "SCHP", "SOWK", "CLA", "SBM", "CLA", "SAP", "SOE", "SEUS", "SCHP", …
$ family_size                           <dbl> 2, 3, 3, 3, 6, 2, 2, 4, 3, 2, 3, 3, 4, 3, 1, 3, 5, 5, 2, 2, 3, 4, 4, 3, 3, 1, 3, 6, 4, 3, 4, 2, 4, 3, 4, 2, 2, 4, 3, 6, 4, 2, 3, 2, 6, 3, 2, 3, 2, 3, 6, 4, …
$ dependency_status                     <chr> "Independent", "Dependent", "Unkn", "Independent", "Dependent", "Dependent", "Independent", "Dependent", "Dependent", "Dependent", "Dependent", "Dependent",…
$ expected_family_contribution          <dbl> 0, 6451, 2469, 2789, 15651, 0, 0, 26802, 0, 6443, 448, 0, 709, 12127, 0, 2469, 928, 2469, 1350, 10447, 10490, 0, 24413, 0, 0, 0, 9900, 0, 5483, 2469, 2469, …
$ cost_of_attendance                    <dbl> 39589, 39533, 38249, 39552, 29061, 39589, 39552, 29061, 21229, 39533, 27777, 27777, 38249, 29061, 29117, 24802, 21229, 39533, 29080, 39533, 39533, 38249, 29…
$ financial_aid_disbursement_amount     <dbl> 19797.0, 10444.0, 17910.5, 6845.0, 19872.0, 9695.0, 9409.0, 3000.0, 11359.0, 37021.0, 18447.0, 20297.0, 10145.0, 7444.0, 6895.0, 19623.0, 13289.0, 30358.0, …
$ pell_recipient                        <lgl> TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, T…
$ unmetneed_amount                      <dbl> 19792.0, 22638.0, 8394.5, 29918.0, -6462.0, 29894.0, 30143.0, -741.0, 9870.0, -3931.0, 8882.0, 7480.0, 27395.0, 9490.0, 22222.0, 8394.5, 7012.0, 8394.5, 191…
$ unmetneed_category                    <int> 5, 5, 7, 5, 6, 5, 5, 6, 3, 6, 3, 2, 5, 3, 5, 7, 2, 6, 5, 1, 6, 1, 6, 5, 4, 4, 6, 6, 5, 6, 6, 6, 5, 4, 6, 6, 1, 6, 6, 6, 6, 1, 6, 3, 5, 4, 6, 6, 5, 4, 3, 5, …
$ family_income_category                <int> 2, 3, 10, 2, 7, 1, 1, 8, 2, 3, 3, 1, 1, 4, 10, 10, 3, 9, 2, 3, 3, 2, 5, 1, 2, 10, 3, 2, 3, 9, 9, 2, 1, 3, 9, 6, 1, 1, 5, 9, 8, 2, 2, 2, 3, 3, 6, 7, 4, 2, 3,…
$ first_generation                      <chr> "Yes", "Yes", "Yes", "No", "No", "Yes", "Yes", "No", "No", "No", "No", "Yes", "Yes", "No", "No", "Yes", "No", "No", "No", "No", "No", "Yes", "No", "Yes", "Y…
$ family_income_label                   <chr> "25,001 Thru 50,000", "50,001 Thru 75,000", "225,001+", "25,001 Thru 50,000", "150,001 Thru 175,000", "Lowest Thru 25,000", "Lowest Thru 25,000", "175,001 T…
$ unmetneed_category_label              <chr> "$15001 Thru Highest", "$15001 Thru Highest", "Unknown Unmet Need", "$15001 Thru Highest", "No Unmet Need", "$15001 Thru Highest", "$15001 Thru Highest", "N…
$ distance_education_label              <chr> "Enrolled in Some but Not All Distance Education", "Enrolled in Some but Not All Distance Education", "Enrolled in Some but Not All Distance Education", "En…
$ admission_test_flag_label             <chr> "Because of Admission Exemption", "Because of Admission Exemption", "Because of Admission Exemption", "Either ACT or SAT Required", "Because of Admission Ex…
$ military_status_label                 <chr> "None of the above", "None of the above", "None of the above", "None of the above", "None of the above", "None of the above", "None of the above", "None of …
$ race_label                            <chr> "African-Americans", "African-Americans", "African-Americans", "African-Americans", "African-Americans", "African-Americans", "African-Americans", "African-…
$ dependency_code                       <int> 2, 1, 0, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, …
$ gender_code                           <int> 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 2, 1, 2, 1, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, …
$ tuition_status_code                   <int> 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3, 3, 3, 2, 3, 2, 2, 3, 2, 3, 3, 2, 3, 2, 3, 2, 2, 3, 2, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, …
$ first_generation_code                 <dbl> 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, …
$ cc_rate_fall                          <dbl> 1.00, 1.00, 1.00, 0.62, 1.00, 1.00, 1.00, 0.93, 0.93, 0.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.82, 1.00, 0.73, 1.00, 0.62, 1.00, 0.81, 1.00, 0.19, …
$ cc_rate_spring                        <dbl> 1.00, 1.00, 0.60, 0.50, 0.93, 0.60, 1.00, 0.00, 0.54, 0.00, 1.00, 1.00, 0.35, 1.00, 1.00, 0.82, 1.00, 0.67, 1.00, 0.25, 1.00, 1.00, 0.71, 0.19, 1.00, 0.23, …
$ on_track_fall                         <lgl> TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE…
$ full_time_spring                      <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, …
$ unmet_need_ratio                      <dbl> 0.50, 0.57, 0.22, 0.76, -0.22, 0.76, 0.76, -0.03, 0.46, -0.10, 0.32, 0.27, 0.72, 0.33, 0.76, 0.34, 0.33, 0.21, 0.66, 0.12, -0.23, 0.02, -0.13, 0.44, 0.37, 0…
$ aid_coverage_ratio                    <dbl> 0.50, 0.26, 0.47, 0.17, 0.68, 0.24, 0.24, 0.10, 0.54, 0.94, 0.66, 0.73, 0.27, 0.26, 0.24, 0.79, 0.63, 0.77, 0.29, 0.62, 0.97, 0.98, 0.29, 0.56, 0.63, 0.62, …
$ pell_coverage_ratio                   <dbl> 0.50, 0.00, 0.00, 0.17, 0.00, 0.24, 0.24, 0.00, 0.54, 0.00, 0.66, 0.73, 0.27, 0.00, 0.24, 0.00, 0.63, 0.00, 0.29, 0.00, 0.00, 0.98, 0.00, 0.56, 0.63, 0.62, …
$ gpa_delta                             <dbl> -0.14, -0.33, -0.46, 0.08, -0.32, 0.17, -0.17, 0.23, -0.83, 0.00, -0.35, 0.02, -0.81, -0.01, 0.00, 0.12, -0.10, 0.35, -0.28, -0.51, 0.10, 0.49, 0.56, -0.81,…
$ gpa_trend                             <chr> "Stable", "Downward", "Downward", "Stable", "Downward", "Stable", "Stable", "Upward", "Downward", "Stable", "Downward", "Stable", "Downward", "Stable", "Sta…
$ credits_growth                        <int> 16, 16, 9, 6, 16, 3, 13, 0, 7, 0, 14, 12, 6, 13, 18, 17, 13, 8, 41, 3, 13, 13, 10, 3, 15, 3, 11, 4, 0, 9, 16, 6, 10, 16, 10, 20, 15, 3, 19, 16, 12, 3, 8, 16…
$ high_unmet_need                       <lgl> FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FA…
$ age_group                             <chr> "25 To 29", "Less Than 20", "20 To 24", "Less Than 20", "Less Than 20", "Less Than 20", "20 To 24", "20 To 24", "20 To 24", "20 To 24", "20 To 24", "20 To 2…
$ risk_score                            <int> 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 0, 2, 1, 1, 0, 1, 1, 2, 2, 0, 1, 0, 2, 1, 1, 1, 1, 2, 2, 0, 2, 2, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 3, 2, 1, 0, 1, 1, 2, 2, …
$ race_financial_stress                 <chr> "African-Americans_NoStress", "African-Americans_Stress", "African-Americans_NoStress", "African-Americans_Stress", "African-Americans_NoStress", "African-A…
$ pct_distance_ed                       <dbl> 0.67, 0.67, 0.67, 0.67, 1.00, 0.67, 0.67, 1.00, 0.67, 0.67, 1.00, 1.00, 1.00, 1.00, 0.67, 0.67, 0.33, 1.00, 0.67, 1.00, 1.00, 1.00, 1.00, 0.67, 0.67, 1.00, …
$ term_credit_hours_attempted2023fall   <int> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ semesterhoursearned2023fall           <int> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ cumulativegpa2023fall                 <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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ retained_fall2024                     <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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ returned_in_2024spring                <chr> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ term_credit_hours_attempted2024spring <int> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ semesterhoursearned2024spring         <int> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ semestergpa2024spring                 <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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ cumulativehoursearned2024spring       <int> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ cumulativegpa2024spring               <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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ term_credit_hours_attempted2024fall   <int> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ semesterhoursearned2024fall           <int> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ cumulativegpa2024fall                 <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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ retained_fall2025                     <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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ returned_spring2025                   <chr> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ term_credit_hours_attempted2025spring <int> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ semesterhoursearned2025spring         <int> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ semestergpa2025spring                 <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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ cumulativehoursearned2025spring       <int> 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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ cumulativegpa2025spring               <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, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …

Exporting Clean and Merge Data for Internal Analysis

write.csv(all_cohorts,
           file      = "/Users/frenandezlawrence/Downloads/Team_B_Cleaned_Cohort_Data_2022_2024Final.csv",
        row.names = FALSE)
LS0tCnRpdGxlOiAiVGVhbSBCIENsZWFuaW5nIFNjcmlwdCBmb3IgRmFsbCAyMDIy4oCTMjAyNCBDb2hvcnQgRGF0YSBGaW5hbCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShwdXJycikKbGlicmFyeSh0aWJibGUpCmxpYnJhcnkobmFuaWFyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHdyaXRleGwpCmBgYAoKIyMgSW1wb3J0aW5nIGFuZCBJbnNwZWN0aW5nIERhdGEKCmBgYHtyfQpwYXRoICAgIDwtICIvVXNlcnMvZnJlbmFuZGV6bGF3cmVuY2UvRG93bmxvYWRzL0ZhbGxfMjAyMi0yMDI0X0ZpcnN0dGltZV9GdWxsdGltZV9Db2hvcnRfZGF0YV93aXRoX1VubWV0X05lZWQueGxzeCIKc2hlZXRzICA8LSBleGNlbF9zaGVldHMocGF0aCkKc2hlZXRzCmBgYAoKIyMgU3RhbmRhcmRpemluZyBDb2x1bW5zIEhlYWRlciBhbmQgVmFsdWVzIAoKYGBge3J9CmRmX2V4YW1wbGUgPC0gcmVhZF94bHN4KHBhdGgsIHNoZWV0ID0gc2hlZXRzWzJdKSAlPiUKICBjbGVhbl9uYW1lcygpCmhlYWQoZGZfZXhhbXBsZSkKCiNUaGUgYmVsb3cgaXMgdXNlZCB0byBzdGFuZGFyZGl6ZSBEZXBlbmRlbmN5IFN0YXR1cyBjb2x1bW4gdG8gZW5zdXJlIHRoYXQgYWxsIHRocmVlIHllYXJzIHJlcHJlc2VudGVkIHVzaW5nIHRoZSBzYW1lIGZvcm1hdC4KZGVwX2xvb2t1cCA8LSBjKAogICIwIiA9ICJVbmtuIiwKICAiMSIgPSAiRGVwZW5kZW50IiwKICAiMiIgPSAiSW5kZXBlbmRlbnQiLAogICIzIiA9ICJVbmtuIgopCgojVGhlIGJlbG93IGlzIHVzZWQgdG8gc3RhbmRhcmRpemUgUmFjZSBjb2x1bW4gdG8gZW5zdXJlIHRoYXQgYWxsIHRocmVlIHllYXJzIHJlcHJlc2VudGVkIHVzaW5nIHRoZSBzYW1lIGZvcm1hdC4KcmFjZV90ZXh0X3RvX2NvZGUgPC0gYygKICAiQWZyaWNhbi1BbWVyaWNhbiI9IDEsCiAgIk5hdGl2ZS1BbWVyaWNhbiIgPSAyLAogICJBc2lhbiIgICAgICAgICAgID0gMywKICAiSGlzcGFuaWMiICAgICAgICA9IDQsCiAgIldoaXRlIiAgICAgICAgICAgPSA1LAogICJOYXRpdmUtSGF3YWlpYW4iID0gNiwKICAiTXVsaXRyYWNpYWwiICAgICA9IDcsCiAgIkludGVybmF0aW9uYWwiICAgPSA4CikKYGBgCgojIyBSZWFkaW5nIGFuZCBUeXBlIENhc3RpbmcgQ29ob3J0IDIwMjIgdG8gdXN0aWxpemUgYXMgdGhlIHN0YW5kYXJkIGZvciB0aGUgYWRkaXRpb25hbCBjb2hvcnRzCgpgYGB7cn0KIyMgRW5yb2xsbWVudCAyMDIyIERhdGEKCmVucjIyX3JhdyA8LSByZWFkX3hsc3gocGF0aCwgc2hlZXQgPSAiRmFsbCAyMDIyIEVucm9sbG1lbnQiKQpwcmludChuYW1lcyhlbnIyMikpCmVucjIyICAgICA8LSBlbnIyMl9yYXcgJT4lCmNsZWFuX25hbWVzKCkgJT4lCnsgaWYgKCEiY2lwX2NvZGUiICVpbiUgbmFtZXMoLikpIG11dGF0ZSguLCBjaXBfY29kZSA9IE5BX2NoYXJhY3Rlcl8pIGVsc2UgLiB9ICU+JQogIG11dGF0ZSgKICAgIHN0dWR5X2lkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBhcy5jaGFyYWN0ZXIoc3R1ZHlfaWQpLAogICAgemlwX2NvZGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IHN0cl9wYWQoYXMuY2hhcmFjdGVyKHppcF9jb2RlKSwgNSwgImxlZnQiLCAiMCIpLAogICAgcmV0YWluZWRfZmFsbDIwMjMgICAgICAgICAgICAgICAgICAgICA9IGNhc2Vfd2hlbihyZXRhaW5lZF9mYWxsMjAyMyAgJWluJSBjKCJZZXMiLCJZIiwiVFJVRSIpICAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldGFpbmVkX2ZhbGwyMDIzICAlaW4lIGMoIk5vIiwiTiIsIkZBTFNFIikgICAgICAgICAgICAgfiBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH4gTkEpLAogICAgY2FzYV9zdHVkZW50ICAgICAgICAgICAgICAgICAgICAgICAgICA9IGNhc2Vfd2hlbihjYXNhX3N0dWRlbnQgICAlaW4lIGMoIlllcyIsIlkiLCJUUlVFIikgICAgICAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2Ffc3R1ZGVudCAgICVpbiUgYygiTm8iLCJOIiwiRkFMU0UiKSAgICAgICAgICAgICAgICAgfiBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH4gTkEpLAogICAgcmV0dXJuZWRfc3ByaW5nMjAyMyAgICAgICAgICAgICAgICAgICA9IGNhc2Vfd2hlbihyZXR1cm5lZF9zcHJpbmcyMDIzICVpbiUgYygiWWVzIiwiWSIsIlRSVUUiKSAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybmVkX3NwcmluZzIwMjMgJWluJSBjKCJObyIsIk4iLCJGQUxTRSIpICAgICAgICAgICAgfiBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH4gTkEpLAogICAgZ2VuZGVyICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IGZhY3RvcihnZW5kZXIsIGxldmVscyA9IGMoIkYiLCJNIikpLAogICAgdHVpdGlvbl9zdGF0dXMgICAgICAgICAgICAgICAgICAgICAgICA9IGFzLmZhY3Rvcih0dWl0aW9uX3N0YXR1cyksCiAgICBuZXdyYWNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gY2FzZV93aGVuKAogICAgbmV3cmFjZSAlaW4lIG5hbWVzKHJhY2VfdGV4dF90b19jb2RlKSB+IHJhY2VfdGV4dF90b19jb2RlW25ld3JhY2VdLAogICAgICAgICAgICBUUlVFICAgICAgICAgICAgICAgICAgICAgICAgICB+IGFzLm51bWVyaWMobmV3cmFjZSkpLAogIAogICAgaGlnaF9zY2hvb2xfZ3BhICAgICAgICAgICAgICAgICAgICAgICA9IGFzLm51bWVyaWMoaGlnaF9zY2hvb2xfZ3BhKSwKICAgIHNhdF8yMDE2X21hdGhfc2NvcmUgICAgICAgICAgICAgICAgICAgPSBhcy5udW1lcmljKHNhdF8yMDE2X21hdGhfc2NvcmUpLAogICAgc2F0XzIwMTZfZWJyd19zY29yZSAgICAgICAgICAgICAgICAgICA9IGFzLm51bWVyaWMoc2F0XzIwMTZfZWJyd19zY29yZSksCiAgICBhZ2UgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gYXMuaW50ZWdlcihhZ2UpLAogICAgY2lwX2NvZGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IGFzLmNoYXJhY3RlcihjaXBfY29kZSksCiAgICBhZG1pc3Npb25fdGVzdF9mbGFnICAgICAgICAgICAgICAgICAgID0gYXMuaW50ZWdlcihhZG1pc3Npb25fdGVzdF9mbGFnKSwsCiAgICBkaXN0YW5jZV9lZHVjYXRpb25fZW5yb2xsbWVudCAgICAgICAgID0gYXMuaW50ZWdlcihkaXN0YW5jZV9lZHVjYXRpb25fZW5yb2xsbWVudCksCiAgICBhY3RfbWF0aF9zY29yZSAgICAgICAgICAgICAgICAgICAgICAgID0gYXMuaW50ZWdlcihhY3RfbWF0aF9zY29yZSksCiAgICBhY3RfZW5nbGlzaF9zY29yZSAgICAgICAgICAgICAgICAgICAgID0gYXMuaW50ZWdlcihhY3RfZW5nbGlzaF9zY29yZSksCiAgICBhY3RfcmVhZGluZ19zY29yZSAgICAgICAgICAgICAgICAgICAgID0gYXMuaW50ZWdlcihhY3RfcmVhZGluZ19zY29yZSksCiAgICBhY3Rfc2NpZW5jZV9zY29yZSAgICAgICAgICAgICAgICAgICAgID0gYXMuaW50ZWdlcihhY3Rfc2NpZW5jZV9zY29yZSksCiAgICBhY3RfY29tcG9zaXRlX3Njb3JlICAgICAgICAgICAgICAgICAgID0gYXMuaW50ZWdlcihhY3RfY29tcG9zaXRlX3Njb3JlKSwKICAgIGFkbWlzc2lvbl9leGVtcHRpb24gICAgICAgICAgICAgICAgICAgPSBhcy5pbnRlZ2VyKGFkbWlzc2lvbl9leGVtcHRpb24pLAogICAgbWF0aF9yZW1lZGlhbF9hc3Nlc3NtZW50ICAgICAgICAgICAgICA9IGFzLmludGVnZXIobWF0aF9yZW1lZGlhbF9hc3Nlc3NtZW50KSwKICAgIGVuZ2xpc2hfcmVtZWRpYWxfYXNzZXNzbWVudCAgICAgICAgICAgPSBhcy5pbnRlZ2VyKGVuZ2xpc2hfcmVtZWRpYWxfYXNzZXNzbWVudCksCiAgICByZWFkaW5nX3JlbWVkaWFsX2Fzc2Vzc21lbnQgICAgICAgICAgID0gYXMuaW50ZWdlcihyZWFkaW5nX3JlbWVkaWFsX2Fzc2Vzc21lbnQpLAogICAgbWlsaXRhcnlfc3RhdHVzICAgICAgICAgICAgICAgICAgICAgICA9IGFzLmludGVnZXIobWlsaXRhcnlfc3RhdHVzKSwKICAgIG1ham9ycyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBhcy5jaGFyYWN0ZXIobWFqb3JzKSwKICAgIHRlcm1fY3JlZGl0X2hvdXJzX2F0dGVtcHRlZDIwMjJmYWxsICAgPSBhcy5pbnRlZ2VyKHRlcm1fY3JlZGl0X2hvdXJzX2F0dGVtcHRlZDIwMjJmYWxsKSwKICAgIHNlbWVzdGVyaG91cnNlYXJuZWQyMDIyZmFsbCAgICAgICAgICAgPSBhcy5pbnRlZ2VyKHNlbWVzdGVyaG91cnNlYXJuZWQyMDIyZmFsbCksCiAgICBjdW11bGF0aXZlZ3BhMjAyMmZhbGwgICAgICAgICAgICAgICAgID0gYXMubnVtZXJpYyhjdW11bGF0aXZlZ3BhMjAyMmZhbGwpLAogICAgdGVybV9jcmVkaXRfaG91cnNfYXR0ZW1wdGVkMjAyM3NwcmluZyA9IGFzLmludGVnZXIodGVybV9jcmVkaXRfaG91cnNfYXR0ZW1wdGVkMjAyM3NwcmluZyksCiAgICBzZW1lc3RlcmhvdXJzZWFybmVkMjAyM3NwcmluZyAgICAgICAgID0gYXMuaW50ZWdlcihzZW1lc3RlcmhvdXJzZWFybmVkMjAyM3NwcmluZyksCiAgICBzZW1lc3RlcmdwYTIwMjNzcHJpbmcgICAgICAgICAgICAgICAgID0gYXMubnVtZXJpYyhzZW1lc3RlcmdwYTIwMjNzcHJpbmcpLAogICAgY3VtdWxhdGl2ZWhvdXJzZWFybmVkMjAyM3NwcmluZyAgICAgICA9IGFzLmludGVnZXIoY3VtdWxhdGl2ZWhvdXJzZWFybmVkMjAyM3NwcmluZyksCiAgICBjdW11bGF0aXZlZ3BhMjAyM3NwcmluZyAgICAgICAgICAgICAgID0gYXMubnVtZXJpYyhjdW11bGF0aXZlZ3BhMjAyM3NwcmluZyksCiAgICBjb2xsZWdlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gYXMuY2hhcmFjdGVyKGNvbGxlZ2UpLAogICAgY29sbGVjdGlvbl90ZXJtICAgICAgICAgICAgICAgICAgICAgICA9ICJGYWxsIiwKICAgIGNvbGxlY3Rpb25feWVhciAgICAgICAgICAgICAgICAgICAgICAgPSAyMDIyCiAgKQoKIyMgRmluYW5jaWFsIEFpZCAyMDIyIERhdGEKZmEyMl9yYXcgPC0gcmVhZF94bHN4KHBhdGgsIHNoZWV0ID0gIkZhbGwgMjAyMiBGaW5hbmNpYWwgQWlkIikKZmEyMiAgICAgPC0gZmEyMl9yYXcgJT4lCiAgY2xlYW5fbmFtZXMoKSAlPiUKICAgIHRyYW5zbXV0ZSgKICAgIHN0dWR5X2lkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBhcy5jaGFyYWN0ZXIoc3R1ZHlfaWQpLAogICAgZmFtaWx5X3NpemUgICAgICAgICAgICAgICAgICAgICAgICAgICA9IGFzLmludGVnZXIoZmFtaWx5X3NpemUpLAogICAgZGVwZW5kZW5jeV9zdGF0dXMgICAgICAgICAgICAgICAgICAgICA9IGZhY3RvcihkZXBlbmRlbmN5X3N0YXR1cywgbGV2ZWxzID0gYygiRGVwZW5kZW50IiwiSW5kZXBlbmRlbnQiLCJVbmtuIikpLAogICAgZXhwZWN0ZWRfZmFtaWx5X2NvbnRyaWJ1dGlvbiAgICAgICAgICA9IGFzLm51bWVyaWMoZXhwZWN0ZWRfZmFtaWx5X2NvbnRyaWJ1dGlvbiksCiAgICBjb3N0X29mX2F0dGVuZGFuY2UgICAgICAgICAgICAgICAgICAgID0gYXMubnVtZXJpYyhjb3N0X29mX2F0dGVuZGFuY2UpLAogICAgZmluYW5jaWFsX2FpZF9kaXNidXJzZW1lbnRfYW1vdW50ICAgICA9IGFzLm51bWVyaWMoZmluYW5jaWFsX2FpZF9kaXNidXJzZW1lbnRfYW1vdW50KSwKICAgIHBlbGxfcmVjaXBpZW50ICAgICAgICAgICAgICAgICAgICAgICAgPSBjYXNlX3doZW4ocGVsbF9yZWNpcGllbnQgICVpbiUgYygiWWVzIiwiWSIsIlRSVUUiKSAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlbGxfcmVjaXBpZW50ICAlaW4lIGMoIk5vIiwiTiIsIkZBTFNFIikgICAgICAgICAgICB+IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB+IE5BKSwKICAgIHVubWV0bmVlZF9hbW91bnQgICAgICAgICAgICAgICAgICAgICAgPSBhcy5udW1lcmljKHVubWV0bmVlZF9hbW91bnQpLAogICAgdW5tZXRuZWVkX2NhdGVnb3J5ICAgICAgICAgICAgICAgICAgICA9IGFzLmludGVnZXIodW5tZXRuZWVkX2NhdGVnb3J5KSwKICAgIGZhbWlseV9pbmNvbWVfY2F0ZWdvcnkgICAgICAgICAgICAgICAgPSBhcy5pbnRlZ2VyKGZhbWlseV9pbmNvbWVfY2F0ZWdvcnkpLAogICAgZmlyc3RfZ2VuZXJhdGlvbiAgICAgICAgICAgICAgICAgICAgICA9IGZhY3RvcihmaXJzdF9nZW5lcmF0aW9uLCBsZXZlbHMgPSBjKCJZZXMiLCJObyIsIlVua24iKSkKICApCgpjb2hvcnQyMiA8LSBsZWZ0X2pvaW4oZW5yMjIsIGZhMjIsIGJ5ID0gInN0dWR5X2lkIikKYGBgCgojI0xvb3BpbmcgYW5kIERhdGEgQ2xlYW5zaW5nIG9mIEFsbCBUaHJlZSBDb2hvcnRzIAoKYGBge3J9CnllYXJfc2hlZXRzIDwtIHRyaWJibGUoCiAgfnllYXIsIH5mYV9zaGVldCwgICAgICAgICAgICAgICAgICAgICAgICAgfmVucl9zaGVldCwKICAyMDIyLCAgIkZhbGwgMjAyMiBGaW5hbmNpYWwgQWlkIiwgICAgICAgICAiRmFsbCAyMDIyIEVucm9sbG1lbnQiLAogIDIwMjMsICAiRmFsbCAyMDIzIEZpbmFuY2lhbCBBaWQiLCAgICAgICAgICJGYWxsIDIwMjMgRW5yb2xsbWVudCIsCiAgMjAyNCwgICJGYWxsIDIwMjQgRmluYW5jaWFsIEFpZCBQcmVsaW0iLCAgIkZhbGwgMjAyNCBFbnJvbGxtZW50IFByZWxpbSIKKQoKdmFyc19yYXcgICAgICA8LSByZWFkX3hsc3gocGF0aCwgc2hlZXQgPSAiVmFyaWFibGVzIiwgY29sX25hbWVzID0gRkFMU0UpCgphbGxfY29ob3J0cyAgIDwtIHB1cnJyOjpwbWFwX2RmcigKICAubCA9IGxpc3QoCiAgICB5ZWFyICAgICAgPSB5ZWFyX3NoZWV0cyR5ZWFyLAogICAgZmFfc2hlZXQgID0geWVhcl9zaGVldHMkZmFfc2hlZXQsCiAgICBlbnJfc2hlZXQgPSB5ZWFyX3NoZWV0cyRlbnJfc2hlZXQpLAogIAogIC5mID0gZnVuY3Rpb24oeWVhciwgZmFfc2hlZXQsIGVucl9zaGVldCkgewogICAgbmV4dF9yZXRhaW5lZCAgICAgICAgICAgICAgICAgICAgPC0gcGFzdGUwKCJyZXRhaW5lZF9mYWxsIiwgeWVhciArIDEpCiAgICBuZXh0X3JldHVybmVkICAgICAgICAgICAgICAgICAgICA8LSBwYXN0ZTAoInJldHVybmVkX3NwcmluZyIsIHllYXIgKyAxKQogICAgbmV4dF90ZXJtY3JlZGl0YXR0ZW1wdGVkZmFsbCAgICAgPC0gcGFzdGUwKCJ0ZXJtX2NyZWRpdF9ob3Vyc19hdHRlbXB0ZWQiLCB5ZWFyLCJmYWxsIikKICAgIG5leHRfc2VtZXN0ZXJob3Vyc2Vhcm5lZGZhbGwgICAgIDwtIHBhc3RlMCgic2VtZXN0ZXJob3Vyc2Vhcm5lZCIsIHllYXIsImZhbGwiKQogICAgbmV4dF9jdW11bGF0aXZlZ3BhZmFsbCAgICAgICAgICAgPC0gcGFzdGUwKCJjdW11bGF0aXZlZ3BhIiwgeWVhciwiZmFsbCIpCiAgICBuZXh0X3Rlcm1jcmVkaXRhdHRlbXB0ZWRzcHJpbmcgICA8LSBwYXN0ZTAoInRlcm1fY3JlZGl0X2hvdXJzX2F0dGVtcHRlZCIsIHllYXIgKyAxLCJzcHJpbmciKQogICAgbmV4dF9zZW1lc3RlcmhvdXJzZWFybmVkc3ByaW5nICAgPC0gcGFzdGUwKCJzZW1lc3RlcmhvdXJzZWFybmVkIiwgeWVhciArIDEsInNwcmluZyIpCiAgICBuZXh0X3NlbWVzdGVyZ3Bhc3ByaW5nICAgICAgICAgICA8LSBwYXN0ZTAoInNlbWVzdGVyZ3BhIiwgeWVhciArIDEsInNwcmluZyIpCiAgICBuZXh0X2N1bXVsYXRpdmVob3Vyc2Vhcm5lZHNwcmluZyA8LSBwYXN0ZTAoImN1bXVsYXRpdmVob3Vyc2Vhcm5lZCIsIHllYXIgKyAxLCJzcHJpbmciKQogICAgbmV4dF9jdW11bGF0aXZlZ3Bhc3ByaW5nICAgICAgICAgPC0gcGFzdGUwKCJjdW11bGF0aXZlZ3BhIiwgeWVhciArIDEsInNwcmluZyIpCiAgICAKI0Vucm9sbG1lbnQgRmllbGRzIENsZWFuaW5nIAogICAgCiAgICBlbnJfcmF3IDwtIHJlYWRfeGxzeChwYXRoLCBzaGVldCA9IGVucl9zaGVldCkKICAgIGVuciAgICAgPC0gZW5yX3JhdyAlPiUKICAgIGNsZWFuX25hbWVzKCkgJT4lCnsgaWYgKCEiY2lwX2NvZGUiICVpbiUgbmFtZXMoLikpIG11dGF0ZSguLCBjaXBfY29kZSA9IE5BX2NoYXJhY3Rlcl8pIGVsc2UgLiB9ICU+JQogIG11dGF0ZSgKICAgIGFjcm9zcygKICAgICAgYW55X29mKG5leHRfcmV0YWluZWQpLAogICAgICAgIH4gY2FzZV93aGVuKAogICAgICAgICAgLnggJWluJSBjKCJZZXMiLCJZIiwiVFJVRSIpICB+IFRSVUUsCiAgICAgICAgICAueCAlaW4lIGMoIk5vIiwiTiIsIkZBTFNFIikgIH4gRkFMU0UsCiAgICAgICAgICBUUlVFICAgICAgICAgICAgICAgICAgICAgICAgIH4gTkEpKSwKICAgIAogICAgc3R1ZHlfaWQgICAgICAgICAgICAgICAgICAgICA9IGFzLmNoYXJhY3RlcihzdHVkeV9pZCksCiAgICB6aXBfY29kZSAgICAgICAgICAgICAgICAgICAgID0gc3RyX3BhZChhcy5jaGFyYWN0ZXIoemlwX2NvZGUpLCA1LCAibGVmdCIsICIwIiksCiAgICBjYXNhX3N0dWRlbnQgICAgICAgICAgICAgICAgID0gKGNhc2Ffc3R1ZGVudCAgICAgID09ICJZZXMiKSwKICAgIGFjcm9zcygKICAgICAgYW55X29mKG5leHRfcmV0YWluZWQpLAogICAgICAgIH4gY2FzZV93aGVuKAogICAgICAgIC54ICVpbiUgYygiWWVzIiwiWSIsIlRSVUUiKSAgfiBUUlVFLAogICAgICAgIC54ICVpbiUgYygiTm8iLCJOIiwiRkFMU0UiKSAgfiBGQUxTRSwKICAgICAgICBUUlVFICAgICAgICAgICAgICAgICAgICAgICAgIH4gTkEpKSwKICAgIGdlbmRlciAgICAgICAgICAgICAgICAgICAgICAgPSBmYWN0b3IoZ2VuZGVyLCBsZXZlbHMgPSBjKCJGIiwiTSIpKSwKICAgIHR1aXRpb25fc3RhdHVzICAgICAgICAgICAgICAgPSBmYWN0b3IodG9sb3dlcihhcy5jaGFyYWN0ZXIodHVpdGlvbl9zdGF0dXMpKSksCiAgICBuZXdyYWNlX3N0ciAgICAgICAgICAgICAgICAgID0gYXMuY2hhcmFjdGVyKG5ld3JhY2UpLAogICAgbmV3cmFjZSAgICAgICAgICAgICAgICAgICAgICA9IGlmX2Vsc2UoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld3JhY2Vfc3RyICVpbiUgbmFtZXMocmFjZV90ZXh0X3RvX2NvZGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYWNlX3RleHRfdG9fY29kZVtuZXdyYWNlX3N0cl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm51bWVyaWMobmV3cmFjZV9zdHIpKSwKICAgIAogICAgaGlnaF9zY2hvb2xfZ3BhICAgICAgICAgICAgICAgPSBhcy5udW1lcmljKGhpZ2hfc2Nob29sX2dwYSksCiAgICBzYXRfMjAxNl9tYXRoX3Njb3JlICAgICAgICAgICA9IGFzLm51bWVyaWMoc2F0XzIwMTZfbWF0aF9zY29yZSksCiAgICBzYXRfMjAxNl9lYnJ3X3Njb3JlICAgICAgICAgICA9IGFzLm51bWVyaWMoc2F0XzIwMTZfZWJyd19zY29yZSksCiAgICBhZ2UgICAgICAgICAgICAgICAgICAgICAgICAgICA9IGFzLmludGVnZXIoYWdlKSwKICAgIGNpcF9jb2RlICAgICAgICAgICAgICAgICAgICAgID0gYXMuY2hhcmFjdGVyKGNpcF9jb2RlKSwKICAgIGFkbWlzc2lvbl90ZXN0X2ZsYWcgICAgICAgICAgID0gYXMuaW50ZWdlcihhZG1pc3Npb25fdGVzdF9mbGFnKSwKICAgIGFkbWlzc2lvbl9leGVtcHRpb24gICAgICAgICAgID0gYXMuY2hhcmFjdGVyKGFkbWlzc2lvbl9leGVtcHRpb24pLAogICAgZGlzdGFuY2VfZWR1Y2F0aW9uX2Vucm9sbG1lbnQgPSBhcy5pbnRlZ2VyKGRpc3RhbmNlX2VkdWNhdGlvbl9lbnJvbGxtZW50KSwKICAgIGFjdF9tYXRoX3Njb3JlICAgICAgICAgICAgICAgID0gYXMuaW50ZWdlcihhY3RfbWF0aF9zY29yZSksCiAgICBhY3RfZW5nbGlzaF9zY29yZSAgICAgICAgICAgICA9IGFzLmludGVnZXIoYWN0X2VuZ2xpc2hfc2NvcmUpLAogICAgYWN0X3JlYWRpbmdfc2NvcmUgICAgICAgICAgICAgPSBhcy5pbnRlZ2VyKGFjdF9yZWFkaW5nX3Njb3JlKSwKICAgIGFjdF9zY2llbmNlX3Njb3JlICAgICAgICAgICAgID0gYXMuaW50ZWdlcihhY3Rfc2NpZW5jZV9zY29yZSksCiAgICBhY3RfY29tcG9zaXRlX3Njb3JlICAgICAgICAgICA9IGFzLmludGVnZXIoYWN0X2NvbXBvc2l0ZV9zY29yZSksCiAgICBhZG1pc3Npb25fZXhlbXB0aW9uICAgICAgICAgICA9IGFzLmludGVnZXIoYWRtaXNzaW9uX2V4ZW1wdGlvbiksCiAgICBtYXRoX3JlbWVkaWFsX2Fzc2Vzc21lbnQgICAgICA9IGFzLmludGVnZXIobWF0aF9yZW1lZGlhbF9hc3Nlc3NtZW50KSwKICAgIGVuZ2xpc2hfcmVtZWRpYWxfYXNzZXNzbWVudCAgID0gYXMuaW50ZWdlcihlbmdsaXNoX3JlbWVkaWFsX2Fzc2Vzc21lbnQpLAogICAgcmVhZGluZ19yZW1lZGlhbF9hc3Nlc3NtZW50ICAgPSBhcy5pbnRlZ2VyKHJlYWRpbmdfcmVtZWRpYWxfYXNzZXNzbWVudCksCiAgICBtaWxpdGFyeV9zdGF0dXMgICAgICAgICAgICAgICA9IGFzLmludGVnZXIobWlsaXRhcnlfc3RhdHVzKSwKICAgIG1ham9ycyAgICAgICAgICAgICAgICAgICAgICAgID0gYXMuY2hhcmFjdGVyKG1ham9ycyksCiAgICAKI0hhbmRsaW5nIG9mIER5bmFtaWMgQ29sdW1uIFRlcm0gQ3JlZGl0IEF0dGVtcHRlZCBGYWxsIDIwMjItMjAyNAogICAgYWNyb3NzKGFueV9vZihuZXh0X3Rlcm1jcmVkaXRhdHRlbXB0ZWRmYWxsKSwKICAgICAgICAgIGFzLmludGVnZXIpLAoKI0hhbmRsaW5nIG9mIER5bmFtaWMgQ29sdW1uIFNlbWVzdGVyIEhvdXJzIEVhcm5lZCBGYWxsIDIwMjItMjAyNAogICAgYWNyb3NzKGFueV9vZihuZXh0X3NlbWVzdGVyaG91cnNlYXJuZWRmYWxsKSwKICAgICAgICAgIGFzLmludGVnZXIpLAogICAgICAgCiNIYW5kbGluZyBvZiBEeW5hbWljIENvbHVtbiBDdW11bGF0aXZlIEdQQSBGYWxsIDIwMjItMjAyNAogICAgYWNyb3NzKGFueV9vZihuZXh0X2N1bXVsYXRpdmVncGFmYWxsICksCiAgICAgICAgICB+IHJvdW5kKGFzLm51bWVyaWMoLngpLCAyKSksCiAgICAgICAKI0hhbmRsaW5nIG9mIER5bmFtaWMgQ29sdW1uIFRlcm0gQ3JlZGl0IEF0dGVtcHRlZCBTcHJpbmcgMjAyMy0yMDI1CiAgICBhY3Jvc3MoYW55X29mKG5leHRfdGVybWNyZWRpdGF0dGVtcHRlZHNwcmluZyksCiAgICAgICAgICBhcy5pbnRlZ2VyKSwKICAgICAgIAojSGFuZGxpbmcgb2YgRHluYW1pYyBDb2x1bW4gU2VtZXN0ZXIgSG91cnMgRWFybmVkIFNwcmluZyAyMDIzLTIwMjUKICAgIGFjcm9zcyhhbnlfb2YoIG5leHRfc2VtZXN0ZXJob3Vyc2Vhcm5lZHNwcmluZyksCiAgICAgICAgICBhcy5pbnRlZ2VyKSwKICAgICAgIAojSGFuZGxpbmcgb2YgRHluYW1pYyBDb2x1bW4gR1BBIFNwcmluZyAyMDIzLTIwMjUKICAgIGFjcm9zcyhhbnlfb2YobmV4dF9zZW1lc3RlcmdwYXNwcmluZyksCiAgICAgICAgICB+IHJvdW5kKGFzLm51bWVyaWMoLngpLCAyKSksCiAgICAgICAKI0hhbmRsaW5nIG9mIER5bmFtaWMgQ29sdW1uIEN1bXVsYXRpdmUgSG91cnMgRWFybmVkIFNwcmluZyAyMDIzLTIwMjUKICAgIGFjcm9zcyhhbnlfb2YobmV4dF9jdW11bGF0aXZlaG91cnNlYXJuZWRzcHJpbmcpLAogICAgICAgICAgYXMuaW50ZWdlciksCiAgICAgICAKI0hhbmRsaW5nIG9mIER5bmFtaWMgQ29sdW1uIEN1bXVsYXRpdmUgR1BBIFNwcmluZyAyMDIzLTIwMjUKICAgIGFjcm9zcyhhbnlfb2YobmV4dF9jdW11bGF0aXZlZ3Bhc3ByaW5nICksCiAgICAgICAgICB+IHJvdW5kKGFzLm51bWVyaWMoLngpLCAyKSksCiAgICAgICAKICAgIGNvbGxlZ2UgPSBhcy5jaGFyYWN0ZXIoY29sbGVnZSksCiAgICBjb2xsZWN0aW9uX3Rlcm0gICAgID0gIkZhbGwiLAogICAgY29sbGVjdGlvbl95ZWFyICAgICA9IHllYXIpCgoKI0Vucm9sbG1lbnQgRGF0YSBDbGVhbmluZyAKICAgIGZhX3JhdyA8LSByZWFkX3hsc3gocGF0aCwgc2hlZXQgPSBmYV9zaGVldCkKICAgIGZhICAgICA8LSBmYV9yYXcgJT4lCiAgICBjbGVhbl9uYW1lcygpICU+JQogICAgdHJhbnNtdXRlKAogICAgICBzdHVkeV9pZCAgICAgICAgICAgICAgICAgICAgICAgICAgPSBhcy5jaGFyYWN0ZXIoc3R1ZHlfaWQpLAogICAgICBmYW1pbHlfc2l6ZSAgICAgICAgICAgICAgICAgICAgICAgPSBhcy5pbnRlZ2VyKGZhbWlseV9zaXplKSwKICAgICAgZGVwZW5kZW5jeV9zdGF0dXMgICAgICAgICAgICAgICAgID0gYXMuY2hhcmFjdGVyKGRlcGVuZGVuY3lfc3RhdHVzKSwKICAgICAgICAKI01hcHBpbmcgYW55IG51bWVyaWMgdmFsdWVzIHVzaW5nIGRlcF9sb29rdXAsIE90aGVyd2lzZSB3ZSB3aWxsIGtlZXAgdGV4dAogICAgICBkZXBlbmRlbmN5X3N0YXR1cyAgICAgICAgICAgICAgICAgPSBpZl9lbHNlKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwZW5kZW5jeV9zdGF0dXMgJWluJSBuYW1lcyhkZXBfbG9va3VwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcF9sb29rdXBbZGVwZW5kZW5jeV9zdGF0dXNdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwZW5kZW5jeV9zdGF0dXMpLCAKICAgICAgZGVwZW5kZW5jeV9zdGF0dXMgICAgICAgICAgICAgICAgID0gZmFjdG9yKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwZW5kZW5jeV9zdGF0dXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJEZXBlbmRlbnQiLCJJbmRlcGVuZGVudCIsIlVua24iKSksCiAgICAgIGV4cGVjdGVkX2ZhbWlseV9jb250cmlidXRpb24gICAgICA9IGFzLm51bWVyaWMoZXhwZWN0ZWRfZmFtaWx5X2NvbnRyaWJ1dGlvbiksCiAgICAgIGNvc3Rfb2ZfYXR0ZW5kYW5jZSAgICAgICAgICAgICAgICA9IGFzLm51bWVyaWMoY29zdF9vZl9hdHRlbmRhbmNlKSwKICAgICAgZmluYW5jaWFsX2FpZF9kaXNidXJzZW1lbnRfYW1vdW50ID0gYXMubnVtZXJpYyhmaW5hbmNpYWxfYWlkX2Rpc2J1cnNlbWVudF9hbW91bnQpLAogICAgICBwZWxsX3JlY2lwaWVudCAgICAgICAgICAgICAgICAgICAgPSBjYXNlX3doZW4ocGVsbF9yZWNpcGllbnQgICVpbiUgYygiWWVzIiwiWSIsIlRSVUUiKSAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVsbF9yZWNpcGllbnQgICVpbiUgYygiTm8iLCJOIiwiRkFMU0UiKSAgfiBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB+IE5BKSwKICAgICAgdW5tZXRuZWVkX2Ftb3VudCAgICAgICAgICAgICAgICAgID0gYXMubnVtZXJpYyh1bm1ldG5lZWRfYW1vdW50KSwKICAgICAgdW5tZXRuZWVkX2NhdGVnb3J5ICAgICAgICAgICAgICAgID0gYXMuaW50ZWdlcih1bm1ldG5lZWRfY2F0ZWdvcnkpLAogICAgICBmYW1pbHlfaW5jb21lX2NhdGVnb3J5ICAgICAgICAgICAgPSBhcy5pbnRlZ2VyKGZhbWlseV9pbmNvbWVfY2F0ZWdvcnkpLAogICAgICBmaXJzdF9nZW5lcmF0aW9uICAgICAgICAgICAgICAgICAgPSBmYWN0b3IoZmlyc3RfZ2VuZXJhdGlvbiwgbGV2ZWxzID0gYygiWWVzIiwiTm8iLCJVbmtuIikpKQoKI0pvaW5pbmcgYW5kIFJldHVybmluZyB0aGUgZGF0YQogICAgZGZfeWVhciA8LSBsZWZ0X2pvaW4oZW5yLCBmYSwgYnkgPSAic3R1ZHlfaWQiKSU+JQoKI0ZpbHRlcmluZyBPdXQgdGhlIENvbHVtbnMgdGhhdCBoYXZlIG92ZXIgNzAlIG9mIGRhdGEgbWlzc2luZyAKICAgIHNlbGVjdCgKICAgICAgLXNhdF8yMDE2X21hdGhfc2NvcmUsCiAgICAgIC1zYXRfMjAxNl9lYnJ3X3Njb3JlLAogICAgICAtYWN0X21hdGhfc2NvcmUsCiAgICAgIC1hY3RfZW5nbGlzaF9zY29yZSwKICAgICAgLWFjdF9yZWFkaW5nX3Njb3JlLAogICAgICAtYWN0X3NjaWVuY2Vfc2NvcmUsCiAgICAgIC1hY3RfY29tcG9zaXRlX3Njb3JlLAogICAgICAtbmV3cmFjZV9zdHIpICU+JSAgCgogICAgbXV0YXRlKAogICAgICBhZG1pc3Npb25fZXhlbXB0aW9uID0gYXMuY2hhcmFjdGVyKGFkbWlzc2lvbl9leGVtcHRpb24pLAogICAgICBhZG1pc3Npb25fZXhlbXB0aW9uID0gY29hbGVzY2UobmFfaWYoYWRtaXNzaW9uX2V4ZW1wdGlvbiwgIiIpLCAiMSIpLAogICAgICBhZG1pc3Npb25fZXhlbXB0aW9uID0gYXMuaW50ZWdlcihhZG1pc3Npb25fZXhlbXB0aW9uKSkgJT4lCiAgICAKI1JlcGxhY2luZyBibGFua3Mgd2l0aCA5IHdoaWNoIHJlcHJlc2VudHMgcmFjZSBhcyB1bmtub3duICAgCiAgICBtdXRhdGUoCiAgICAgIG5ld3JhY2UgPSBhcy5jaGFyYWN0ZXIobmV3cmFjZSksCiAgICAgIG5ld3JhY2UgPSBjb2FsZXNjZShuYV9pZihuZXdyYWNlLCAiIiksICI5IiksCiAgICAgIG5ld3JhY2UgPSBhcy5pbnRlZ2VyKG5ld3JhY2UpKSAlPiUKICAKICAKI0hhbmRsaW5nIERlcGVuZGVuY3kgU3RhdHVzIEJsYW5rcwogICAgbXV0YXRlKAogICAgICBkZXBlbmRlbmN5X3N0YXR1cyA9IGFzLmNoYXJhY3RlcihkZXBlbmRlbmN5X3N0YXR1cyksCiAgICAgIGRlcGVuZGVuY3lfc3RhdHVzID0gY29hbGVzY2UobmFfaWYoZGVwZW5kZW5jeV9zdGF0dXMsICIiKSwgIlVua24iKSwKICAgICAgZGVwZW5kZW5jeV9zdGF0dXMgPSBmYWN0b3IoZGVwZW5kZW5jeV9zdGF0dXMsbGV2ZWxzID0gYygiRGVwZW5kZW50IiwiSW5kZXBlbmRlbnQiLCJVbmtuIikpKSAlPiUKCiNJZGVudGlmeWluZywgUmVwbGFjaW5nIE91dGxpZXJzIGFuZCBJbXB1dGluZyBNaXNzaW5nIFZhbHVlcyB3aXRoIE1lYW4gICAKICAgICAgbXV0YXRlKAogICAgICAgIGFjcm9zcygKICAgICAgICAgIGMoZXhwZWN0ZWRfZmFtaWx5X2NvbnRyaWJ1dGlvbiwgdW5tZXRuZWVkX2Ftb3VudCwgY29zdF9vZl9hdHRlbmRhbmNlLCBmaW5hbmNpYWxfYWlkX2Rpc2J1cnNlbWVudF9hbW91bnQsIGhpZ2hfc2Nob29sX2dwYSxmYW1pbHlfc2l6ZSksCiAgICAgICAgICB+IHsKCiNDb21wdXRpbmcgdGhlIG1lYW4gZm9yIGVhY2ggY29sdW1uIG9uIGEgeWVhcmx5IGJhc2lzCiAgICAgICAgICAgIG1lZCAgICA8LSBtZWRpYW4oLngsIG5hLnJtID0gVFJVRSkKICAgICAgICAgICAgCiNJbXB1dGluZyBNaXNzaW5nIFZhbHVlcwogICAgICAgICAgICB4MCAgIDwtIGlmX2Vsc2UoaXMubmEoLngpLCBtZWQsIC54KQogICAgICAgICAgICAKI0NvbXB1dGluZyBJUVIgQm91bmRhcmllcwogICAgICAgICAgICBxICAgIDwtIHF1YW50aWxlKHgwLCBjKDAuMjUsIDAuNzUpLCBuYS5ybSA9IFRSVUUpCiAgICAgICAgICAgIGlxciAgPC0gZGlmZihxKQogICAgICAgICAgICBsb3dlciA8LSBxWzFdIC0gMS41ICogaXFyCiAgICAgICAgICAgIHVwcGVyIDwtIHFbMl0gKyAxLjUgKiBpcXIKICAgICAgICAgICAgCiNSZXBsYWNpbmcgb3V0bGllcnMgd2l0aCB0aGUgeWVhcuKAmXMgbWVhbgogICAgICAgICAgICBpZmVsc2UoeDAgPCBsb3dlciB8IHgwID4gdXBwZXIsIG1lZCwgeDApCiAgICAgICAgICAgIH0KICAgICAgICAgICAgKQogICAgICAgICAgICApICU+JQoKI0Ryb3BwaW5nIFJlY29yZHMgd2hpY2ggYXJlIE5BIHNpbmNlIGl0IGlzIGxlc3MgdGhhbiA1JSBvZiBkYXRhIHNldAogICAgZmlsdGVyKAogICAgICBpZl9hbGwoCiAgICAgICAgYW55X29mKGMoCiAgICAgICAgICBwYXN0ZTAoInRlcm1fY3JlZGl0X2hvdXJzX2F0dGVtcHRlZCIsICB5ZWFyICsgMSwgInNwcmluZyIpLAogICAgICAgICAgcGFzdGUwKCJzZW1lc3RlcmdwYSIsICAgICAgICAgICAgICAgICAgeWVhciArIDEsICJzcHJpbmciKSwKICAgICAgICAgIHBhc3RlMCgiY3VtdWxhdGl2ZWhvdXJzZWFybmVkIiwgICAgICAgIHllYXIgKyAxLCAic3ByaW5nIiksCiAgICAgICAgICBwYXN0ZTAoImN1bXVsYXRpdmVncGEiLCAgICAgICAgICAgICAgICB5ZWFyICsgMSwgInNwcmluZyIpCiAgICAgICAgICApKSwKICAgICAgICAgIH4gIWlzLm5hKC54KQogICAgICAgICAgICApCiAgICAgICAgICApCiAgICAKICAgIAojI1RoZSBCZWxvdyBMaW5lcyBvZiBDb2RlcyByZXByZXNlbnRzIGxvb2t1cCB0YWJsZXMgZm9yIHZhcmliYWxlcy4KIyNGb3IgTnVtZXJpYyBWYXJpYWJsZXMgYSBsYWJlbCBoYXMgYmVlbiBjcmVhdGVkCiMjRm9yIFRleHQgRmllbGRzIGEgQ29kZSBoYXMgYmVlbiBjcmVhdGVkIHRvIHVzZWQgZm9yIG1vZGVsbGluZyAKICAgIAogIGZhbWlseV9pbmNfbG9va3VwICAgICAgICAgICAgIDwtIHRpYmJsZSgKICBmYW1pbHlfaW5jb21lX2NhdGVnb3J5ICAgICAgICA9IDE6MTAsCiAgZmFtaWx5X2luY29tZV9sYWJlbCAgICAgICAgICAgPSBjKCJMb3dlc3QgVGhydSAyNSwwMDAiLCAiMjUsMDAxIFRocnUgNTAsMDAwIiwgIjUwLDAwMSBUaHJ1IDc1LDAwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI3NSwwMDEgVGhydSAxMDAsMDAwIiwgIjEwMCwwMDEgVGhydSAxMjUsMDAwIiwgIjEyNSwwMDEgVGhydSAxNTAsMDAwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjE1MCwwMDEgVGhydSAxNzUsMDAwIiwgIjE3NSwwMDEgVGhydSAyMDAsMDAwIiwgIjIwMCwwMDEgVGhydSAyMjUsMDAwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIyNSwwMDErIikpCgogIHVubWV0bmVlZF9jYXRfbG9va3VwICAgICAgICAgIDwtIHRpYmJsZSgKICB1bm1ldG5lZWRfY2F0ZWdvcnkgICAgICAgICAgICA9IDE6NywKICB1bm1ldG5lZWRfY2F0ZWdvcnlfbGFiZWwgICAgICA9IGMoIiQxIFRocnUgJDUwMDAiLCAiJDUwMDEgVGhydSAkNzUwMCIsICIkNzUwMSBUaHJ1ICQxMDAwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIkMTAwMDEgVGhydSAkMTUwMDAiLCAiJDE1MDAxIFRocnUgSGlnaGVzdCIsICJObyBVbm1ldCBOZWVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVua25vd24gVW5tZXQgTmVlZCIpKQogIAogIGRpc3RhbmNlX2VkdV9sb29rdXAgICAgICAgICAgIDwtIHRpYmJsZSgKICBkaXN0YW5jZV9lZHVjYXRpb25fZW5yb2xsbWVudCA9IDE6MywKICBkaXN0YW5jZV9lZHVjYXRpb25fbGFiZWwgICAgICA9IGMoIkVucm9sbGVkIEV4Y2x1c2l2ZWx5IGluIERpc3RhbmNlIEVkdWNhdGlvbiIsICJFbnJvbGxlZCBpbiBTb21lIGJ1dCBOb3QgQWxsIERpc3RhbmNlIEVkdWNhdGlvbiIsICJOb3QgRW5yb2xsZWQgaW4gQW55IERpc3RhbmNlIEVkdWNhdGlvbiIpKQogIAogIGFkbWlzc2lvbl90ZXN0X2xvb2t1cCAgICAgICAgIDwtIHRpYmJsZSgKICBhZG1pc3Npb25fdGVzdF9mbGFnICAgICAgICAgICA9IDA6NSwKICBhZG1pc3Npb25fdGVzdF9mbGFnX2xhYmVsICAgICA9IGMoIk5vIFRlc3QgUmVxdWlyZWQgZm9yIEFkbWlzc2lvbiIsICJTQVQgVGVzdCBSZXF1aXJlZCIsICJBQ1QgVGVzdCBSZXF1aXJlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFaXRoZXIgQUNUIG9yIFNBVCBSZXF1aXJlZCIsICJJbnN0aXR1dGlvbiBUZXN0IFJlcXVpcmVkIiwgIkJlY2F1c2Ugb2YgQWRtaXNzaW9uIEV4ZW1wdGlvbiIpKQogIAogIG1pbGl0YXJ5X3N0YXR1c19sb29rdXAgICAgICAgIDwtIHRpYmJsZSgKICBtaWxpdGFyeV9zdGF0dXMgICAgICAgICAgICAgICA9IDE6NSwKICBtaWxpdGFyeV9zdGF0dXNfbGFiZWwgICAgICAgICA9IGMoIkFjdGl2ZSBEdXR5IE1lbWJlciBvZiBBbnkgb2YgdGhlIFVTIFVuaWZvcm0gRm9yY2VzIiwgIlZldGVyYW4gb3IgRm9ybWVyIEFjdGl2ZSBEdXR5IE1lbWJlciBvZiBBbnkgb2YgVGhlIFVTIFVuaWZvcm1lZCBGb3JjZXMiLCAiUmVzZXJ2ZSBEdXR5IE1lbWJlciBvZiBBbnkgb2YgVGhlIFVTICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJtZWQgRm9yY2VzLCBJbmNsdWRpbmcgVGhlIE5hdGlvbmFsIEd1YXJkIiwgIlNwb3VzZSBvciBEZXBlbmRlbnQgQ2hpbGQgb2YgYW4gQWN0aXZlLCBSZXNlcnZlLCBvciBGb3JtZXIgTWVtYmVyIG9mIFRoZSBVUyBVbmlmb3JtZWQgRm9yY2VzIiwgIk5vbmUgb2YgdGhlIGFib3ZlIikpCiAgCiAgZnJhY2VfbG9va3VwICAgICAgICAgICAgICAgICAgPC0gdGliYmxlKAogIG5ld3JhY2UgICAgICAgICAgICAgICAgICAgICAgID0gMTo5LAogIHJhY2VfbGFiZWwgICAgICAgICAgICAgICAgICAgID0gYygiQWZyaWNhbi1BbWVyaWNhbnMiLCAiTmF0aXZlLUFtZXJpY2FucyIsICJBc2lhbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIaXNwYW5pYyIsICJXaGl0ZSIsICJOYXRpdmUtSGF3YWlpYW5zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk11bHRpUmFjaWFscyIsICJJbnRlcm5hdGlvbmFsIiwiVW5rbm93biIpKQogICAgCiAgZGVwZW5kZW5jeV9zdGF0dXNfbG9va3VwICAgICAgPC0gdGliYmxlKAogIGRlcGVuZGVuY3lfc3RhdHVzICAgICAgICAgICAgID0gYygiVW5rbiIsICJEZXBlbmRlbnQiLCJJbmRlcGVuZGVudCIpLAogIGRlcGVuZGVuY3lfY29kZSAgICAgICAgICAgICAgID0gMDoyKQogICAKICBnZW5kZXJfbG9va3VwICAgICAgICAgICAgICAgICA8LSB0aWJibGUoCiAgZ2VuZGVyICAgICAgICAgICAgICAgICAgICAgICAgPSBjKCJNIiwiRiIpLAogIGdlbmRlcl9jb2RlICAgICAgICAgICAgICAgICAgID0gMToyKQogICAgCiAgCiAgdHVpdGlvbl9zdGF0dXNfbG9va3VwICAgICAgICAgPC0gdGliYmxlKAogIHR1aXRpb25fc3RhdHVzICAgICAgICAgICAgICAgID0gYygiaW4tc3RhdGUiLCAib3V0LW9mLXN0YXRlIiksCiAgdHVpdGlvbl9zdGF0dXNfY29kZSAgICAgICAgICAgPSAyOjMpCiAgIAogICAKICBmaXJzdF9nZW5lcmF0aW9uX2xvb2t1cCAgICAgICA8LSB0aWJibGUoCiAgZmlyc3RfZ2VuZXJhdGlvbiAgICAgICAgICAgICA9IGMoIk5vIiwgIlllcyIsICJVbmtuIiksCiAgZmlyc3RfZ2VuZXJhdGlvbl9jb2RlICAgICAgICAgPSBjKDAsMSw5KSkKCiNBZGRpbmcgdGhlIEFkZGl0aW9uYWwgQ29sdW1ucyB0byBkYXRhc2V0ICAgCiAgZGZfeWVhciA8LSBkZl95ZWFyICU+JQogIGxlZnRfam9pbihmYW1pbHlfaW5jX2xvb2t1cCwgICAgICAgIGJ5ID0gImZhbWlseV9pbmNvbWVfY2F0ZWdvcnkiKSAlPiUKICBsZWZ0X2pvaW4odW5tZXRuZWVkX2NhdF9sb29rdXAsICAgICBieSA9ICJ1bm1ldG5lZWRfY2F0ZWdvcnkiKSAlPiUKICBsZWZ0X2pvaW4oZGlzdGFuY2VfZWR1X2xvb2t1cCwgICAgICBieSA9ICJkaXN0YW5jZV9lZHVjYXRpb25fZW5yb2xsbWVudCIpICU+JQogIGxlZnRfam9pbihhZG1pc3Npb25fdGVzdF9sb29rdXAsICAgIGJ5ID0gImFkbWlzc2lvbl90ZXN0X2ZsYWciKSAlPiUKICBsZWZ0X2pvaW4obWlsaXRhcnlfc3RhdHVzX2xvb2t1cCwgICBieSA9ICJtaWxpdGFyeV9zdGF0dXMiKSAlPiUKICBsZWZ0X2pvaW4oZnJhY2VfbG9va3VwLCAgICAgICAgICAgICBieSA9ICJuZXdyYWNlIikgJT4lCiAgbGVmdF9qb2luKGRlcGVuZGVuY3lfc3RhdHVzX2xvb2t1cCwgYnkgPSAiZGVwZW5kZW5jeV9zdGF0dXMiKSAgJT4lCiAgbGVmdF9qb2luKGdlbmRlcl9sb29rdXAsICAgICAgICAgICAgYnkgPSAiZ2VuZGVyIikgICU+JQogIGxlZnRfam9pbih0dWl0aW9uX3N0YXR1c19sb29rdXAsICAgIGJ5ID0gInR1aXRpb25fc3RhdHVzIikgICU+JQogIGxlZnRfam9pbihmaXJzdF9nZW5lcmF0aW9uX2xvb2t1cCwgIGJ5ID0gImZpcnN0X2dlbmVyYXRpb24iKSAKCgoKIyBJZGVudGlmeSBkeW5hbWljIGNvbHVtbiBuYW1lcyBkaXJlY3RseSAKICBmYWxsX2NyZWRpdF9jb2wgICA8LSBuZXh0X3Rlcm1jcmVkaXRhdHRlbXB0ZWRmYWxsCiAgZmFsbF9lYXJuZWRfY29sICAgPC0gbmV4dF9zZW1lc3RlcmhvdXJzZWFybmVkZmFsbAogIHNwcmluZ19jcmVkaXRfY29sIDwtIG5leHRfdGVybWNyZWRpdGF0dGVtcHRlZHNwcmluZwogIHNwcmluZ19lYXJuZWRfY29sIDwtIG5leHRfc2VtZXN0ZXJob3Vyc2Vhcm5lZHNwcmluZwogIHNwcmluZ19jdW1lYXJuZWRfY29sIDwtIG5leHRfY3VtdWxhdGl2ZWhvdXJzZWFybmVkc3ByaW5nCgojIEVuc3VyaW5nIENvbHVtbnMgYXJlIEZvdW5kCiAgaWYobGVuZ3RoKGZhbGxfY3JlZGl0X2NvbCkhPTEgfHwgbGVuZ3RoKGZhbGxfZWFybmVkX2NvbCkhPTEgfHwgbGVuZ3RoKHNwcmluZ19jcmVkaXRfY29sKSE9MSB8fCBsZW5ndGgoc3ByaW5nX2Vhcm5lZF9jb2wpIT0xKSB7CiAgICBzdG9wKGdsdWU6OmdsdWUoCiAgICAgICJbe3llYXJ9XSBVbmFibGUgdG8gZmluZCBleGFjdGx5IG9uZSBtYXRjaCBmb3IgZHluYW1pYyBjb2x1bW5zOgoiLAogICAgICAiZmFsbF9jcmVkaXQ6IHtmYWxsX2NyZWRpdF9jb2x9OyBmYWxsX2Vhcm5lZDoge2ZhbGxfZWFybmVkX2NvbH07CiIsCiAgICAgICJzcHJpbmdfY3JlZGl0OiB7c3ByaW5nX2NyZWRpdF9jb2x9OyBzcHJpbmdfZWFybmVkOiB7c3ByaW5nX2Vhcm5lZF9jb2x9IgogICAgKSkKICB9CgojIEZlYXR1cmUgZW5naW5lZXJpbmcgdXNpbmcgcmVzb2x2ZWQgY29sdW1uIG5hbWVzCiAgZGZfeWVhciA8LSBkZl95ZWFyICU+JQogICAgbXV0YXRlKAogICAgICBjY19yYXRlX2ZhbGwgICAgICA9IHJvdW5kKC5kYXRhW1tmYWxsX2Vhcm5lZF9jb2xdXSAvIC5kYXRhW1tmYWxsX2NyZWRpdF9jb2xdXSwyKSwKICAgICAgY2NfcmF0ZV9zcHJpbmcgICAgPSByb3VuZCguZGF0YVtbc3ByaW5nX2Vhcm5lZF9jb2xdXSAvIC5kYXRhW1tzcHJpbmdfY3JlZGl0X2NvbF1dLDIpLAogICAgICBvbl90cmFja19mYWxsICAgICA9IGNjX3JhdGVfZmFsbCA+PSAxLjAsCiAgICAgIGZ1bGxfdGltZV9zcHJpbmcgID0gLmRhdGFbW3NwcmluZ19jcmVkaXRfY29sXV0gPj0gMTIsCiAgICAgIHVubWV0X25lZWRfcmF0aW8gID0gcm91bmQodW5tZXRuZWVkX2Ftb3VudCAvIGNvc3Rfb2ZfYXR0ZW5kYW5jZSwyKSwKICAgICAgYWlkX2NvdmVyYWdlX3JhdGlvPSByb3VuZChmaW5hbmNpYWxfYWlkX2Rpc2J1cnNlbWVudF9hbW91bnQgLyBjb3N0X29mX2F0dGVuZGFuY2UsMiksCiAgICAgIHBlbGxfY292ZXJhZ2VfcmF0aW8gPSByb3VuZChpZl9lbHNlKHBlbGxfcmVjaXBpZW50LCBhaWRfY292ZXJhZ2VfcmF0aW8sIDApLDIpLAogICAgICBncGFfZGVsdGEgICAgICAgICA9IC5kYXRhW1twYXN0ZTAoImN1bXVsYXRpdmVncGEiLCB5ZWFyKzEsICJzcHJpbmciKV1dIC0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kYXRhW1twYXN0ZTAoImN1bXVsYXRpdmVncGEiLCB5ZWFyLCAiZmFsbCIpXV0sCiAgICAgIGdwYV90cmVuZCAgICAgICAgID0gY2FzZV93aGVuKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdwYV9kZWx0YSA+ICAwLjIgfiAiVXB3YXJkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncGFfZGVsdGEgPCAtMC4yIH4gIkRvd253YXJkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFICAgICAgICAgICAgIH4gIlN0YWJsZSIpLAogICAgICBjcmVkaXRzX2dyb3d0aCAgICA9IC5kYXRhW1tzcHJpbmdfY3VtZWFybmVkX2NvbF1dIC0gLmRhdGFbW2ZhbGxfZWFybmVkX2NvbF1dLAogICAgICBoaWdoX3VubWV0X25lZWQgICA9IHVubWV0bmVlZF9hbW91bnQgPiAwLjUgKiBjb3N0X29mX2F0dGVuZGFuY2UsCiAgICAgIGFnZV9ncm91cCAgICAgICAgID0gY2FzZV93aGVuKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZSA8IDIwICAgICAgICAgICB+ICJMZXNzIFRoYW4gMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZSA8IDI1ICAgICAgICAgICB+ICIyMCBUbyAyNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdlIDwgMzAgICAgICAgICAgIH4gIjI1IFRvIDI5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFICAgICAgICAgICAgICAgfiAiMzArIiApCiAgICApICU+JQogICAgcm93d2lzZSgpICU+JQogICAgbXV0YXRlKAogICAgICByaXNrX3Njb3JlID0gc3VtKAogICAgICAgICFvbl90cmFja19mYWxsLAogICAgICAgIGdwYV9kZWx0YSA8IDAsCiAgICAgICAgaGlnaF91bm1ldF9uZWVkLAogICAgICAgIG5hLnJtID0gVFJVRQogICAgICApCiAgICApICU+JQogICAgdW5ncm91cCgpICU+JQogICAgbXV0YXRlKAogICAgICByYWNlX2ZpbmFuY2lhbF9zdHJlc3MgPSBwYXN0ZTAocmFjZV9sYWJlbCwgIl8iLCBpZl9lbHNlKGhpZ2hfdW5tZXRfbmVlZCwgIlN0cmVzcyIsICJOb1N0cmVzcyIpKSwKICAgICAgcGN0X2Rpc3RhbmNlX2VkICAgICAgID0gcm91bmQoZGlzdGFuY2VfZWR1Y2F0aW9uX2Vucm9sbG1lbnQgLyBtYXgoZGlzdGFuY2VfZWR1Y2F0aW9uX2Vucm9sbG1lbnQsIG5hLnJtID0gVFJVRSksMikKICAgICkKICAKI1dyaXRpbmcgRWFjaCBZZWFyIERhdGEgdG8gQSBzZXBhcmF0ZSBDU1YgdG8gVXBsb2FkIHRvIFRhYmxlYXUgICAgICAgIAogIGZpbGVfbmFtZSA8LSBwYXN0ZTAoIi9Vc2Vycy9mcmVuYW5kZXpsYXdyZW5jZS9Eb3dubG9hZHMvVGVhbV9CIix5ZWFyLCJDbGVhbmVkX0RhdGFGaW5hbC5jc3YiKQogIHdyaXRlLmNzdihkZl95ZWFyLCBmaWxlICAgICAgPSBmaWxlX25hbWUsIHJvdy5uYW1lcyA9IEZBTFNFKQoKICBkZl95ZWFyCiAgfQopCmBgYAoKCiMjIFBlcmZvcm1pbmcgRmluYWwgUXVhbGl0eSBDaGVja3Mgb24gTWVyZ2VkIERhdGFzZXQKCmBgYHtyfQojUGVyZm9ybWluZyBVbmlxdWVuZXNzIENoZWNrCiAgYWxsX2NvaG9ydHMgJT4lCiAgICBjb3VudChjb2xsZWN0aW9uX3llYXIsIHN0dWR5X2lkKSAlPiUKICAgIGZpbHRlcihuID4gMSkKCiMgUGVyZm9ybWluZyBNaXNzaW5nbmVzcyBDaGVjawogIGFsbF9jb2hvcnRzICU+JQogICAgc3VtbWFyaXNlX2FsbCh+IG1lYW4oaXMubmEoLikpKSAlPiUKICAgIHBpdm90X2xvbmdlcihldmVyeXRoaW5nKCksIG5hbWVzX3RvID0gInZhciIsIHZhbHVlc190byA9ICJwY3RfbWlzc2luZyIpCgojIFBlcmZvbWluZyBhIGZpbmFsIGxvb2sgYXQgZGF0YXNldAojVGhlIE5BcyBkaXNwbGF5aW5nIGluIHRoZSBnbGltcHNlIGlzIGZvciB0aGUgZHluYW1pYyBjb2x1bW5zIHdoaWNoIGFyZSBub3Qgbm90IGFwcGxpY2FibGUgZm9yIGFsbCB5ZWFycy4gCmdsaW1wc2UoYWxsX2NvaG9ydHMpCmBgYAoKIyMgRXhwb3J0aW5nIENsZWFuIGFuZCBNZXJnZSBEYXRhIGZvciBJbnRlcm5hbCBBbmFseXNpcwoKYGBge3J9CndyaXRlLmNzdihhbGxfY29ob3J0cywKICAgICAgICAgICBmaWxlICAgICAgPSAiL1VzZXJzL2ZyZW5hbmRlemxhd3JlbmNlL0Rvd25sb2Fkcy9UZWFtX0JfQ2xlYW5lZF9Db2hvcnRfRGF0YV8yMDIyXzIwMjRGaW5hbC5jc3YiLAogICAgICAgIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAK