Project Status R Version License: MIT

1 ABSTRACT

Objective: To quantify changes in accessibility to gynecologic oncology care across the United States from 2013-2022, with particular attention to urban-rural disparities, drive time thresholds, and racial/ethnic differences in access.

Methods: We analyzed gynecologic oncologist practice locations combined with U.S. Census data from 2013-2022. Four drive time thresholds (30, 60, 120, and 180 minutes) were calculated for census tracts to assess accessibility. Population-weighted mean access rates were determined for urban and rural populations and stratified by race/ethnicity. Linear regression models with temporal trend analysis were employed to assess statistical significance of changes over time.

Results: Accessibility to gynecologic oncologists declined significantly across all time thresholds over the 10-year period. The most pronounced decrease occurred in 30-minute accessibility (-23.6%, p<0.001), followed by 60-minute (-16.8%, p<0.001), 120-minute (-8.5%, p<0.01), and 180-minute thresholds (-2.8%, p<0.05). Approximately 277.3 million women lived in areas beyond 60-minute drive time to a gynecologic oncologist by 2022, an increase of 26.8 million from 2013. Urban-rural disparities were substantial, with only 10.2% of rural women having 30-minute access compared to 44.1% of urban women (p<0.001). Racial/ethnic disparities were equally pronounced, with Asian women having the highest access rates (86.5%), followed by Black women (77.2%), Native Hawaiian and Pacific Islander women (75.3%), and White women (66.8%), while American Indian and Alaska Native women had dramatically lower access (50.9%, p<0.001).

Conclusions: Access to gynecologic oncology care has significantly diminished over the past decade, with shorter drive time thresholds experiencing the steepest declines. Geographic concentration of gynecologic oncologists in urban academic centers has created substantial access barriers, particularly for rural communities. Without intervention, these trends will continue to exacerbate cancer outcome disparities for rural and minority populations. Strategic initiatives including outreach clinics, telemedicine networks, and targeted training programs are needed to address the maldistribution of gynecologic oncologists.

1.1 Yearly Maps Combined

Yearly Maps Combined
Yearly Maps Combined

2 🔬 Research Objectives

  • Primary: Quantify geographic accessibility to gynecologic oncology specialists nationwide
  • Secondary: Analyze demographic disparities in subspecialist access
  • Tertiary: Examine temporal trends in healthcare workforce distribution
  • Quaternary: Identify underserved populations and geographic areas

3 🎯 Project Overview & Conceptual Framework

This project analyzes nationwide access to gynecologic oncologists and other OBGYN subspecialists using drive time isochrones, demographic data, and geospatial analysis. The analysis examines how accessibility varies across different geographic areas, demographic groups, and time periods (2013-2023).

Using the HERE Maps API and census data, we calculate drive time isochrones around gynecologic oncologists’ locations and analyze the demographics of populations within each drive time threshold. The project examines changes in accessibility over time and retirement patterns among specialists.

3.1 What Are Isochrones?

3.2 Interactive Isochrone Map

Isochrones are geographic boundaries showing areas reachable within specific travel times from a point. Think of them as “time zones” around each doctor’s office - the 30-minute isochrone includes all places you can drive to within 30 minutes.

Why This Matters for Healthcare Access: - Patient perspective: How far do I have to travel for specialized care? - Policy perspective: Which populations are underserved? - Planning perspective: Where should new providers practice?

3.3 Enhanced Census Tract Map

Enhanced Census Tract Map
Enhanced Census Tract Map

3.4 Key Methodological Decisions & Rationale

3.4.1 Drive Time Thresholds (30, 60, 120, 180 minutes)

  • 30 minutes: Local/regional access - most patients willing to travel
  • 60 minutes: Extended local access - reasonable for specialty care
  • 120 minutes: Regional access - acceptable for highly specialized care
  • 180 minutes: Maximum reasonable access - beyond this is effectively inaccessible

3.4.2 Reference Time: Third Friday of October, 9:00 AM

  • Rationale: Standardized across all years for consistency
  • Considerations: Rush hour vs. off-peak; Friday represents typical weekday
  • Limitation: Doesn’t account for seasonal variations or weekend access

3.4.3 Geographic Resolution: Census Block Groups vs. Counties

  • Choice: Used census block groups (smaller geographic units)
  • Advantage: More precise population estimates, captures urban/rural differences
  • Trade-off: Increased computational complexity vs. more accurate results

3.5 Subspecialist Categories Analyzed

3.5.1 Primary Focus: Gynecologic Oncology

  • Definition: Physicians specializing in cancers of the female reproductive system
  • Taxonomy Code: 207VX0201X
  • Typical Training: 3 or 4-year fellowship after OBGYN residency
  • Rarity: Highly specialized - limited number nationwide

3.5.2 Secondary Analysis Subspecialties:

  1. Female Pelvic Medicine/Urogynecology (207VF0040X)
    • Pelvic floor disorders, incontinence
    • Recent name change from FPMRS to URPS
  2. Maternal-Fetal Medicine (207VM0101X)
    • High-risk pregnancy specialists
    • Critical for complex obstetric care
  3. Reproductive Endocrinology (207VE0102X)
    • Fertility specialists
    • Hormone-related reproductive disorders

3.5.2.1 Taxonomy Code Reference

obgyn_taxonomy_codes <- c(
  "207V00000X",    # Obstetrics & Gynecology (general)
  "207VX0201X",    # Gynecologic Oncology (PRIMARY FOCUS)
  "207VE0102X",    # Reproductive Endocrinology 
  "207VG0400X",    # Gynecology (general)
  "207VM0101X",    # Maternal & Fetal Medicine
  "207VF0040X",    # Female Pelvic Medicine/Urogynecology
  "207VB0002X",    # Bariatric Medicine
  "207VC0200X",    # Critical care medicine
  "207VC0300X",    # Complex family planning  
  "207VH0002X",    # Palliative care
  "207VX0000X"     # Obstetrics only
)

3.6 📂 Detailed File Organization & Purpose

isochrones/
├── 📁 data/                           # Raw and processed datasets
│   ├── demographic_disparities_analysis.csv
│   ├── difference_in_difference_analysis.csv
│   ├── duplicateyearandfill.csv
│   ├── end_inner_join_postmaster_clinician_data.csv
│   ├── end_rejoined_geocoded_unique_address.csv
│   ├── fips-states.csv
│   ├── healthcare_benchmark_references.md
│   ├── intersect.csv
│   ├── Medicare_Part_D_physician_retirement_analysis.csv
│   ├── physician_compare_data.csv
│   ├── physician_retirement_years.csv
│   ├── population_weighted_means_with_ci.csv
│   └── racial_decay_curves.png
├── 📁 figures/                        # Generated visualizations
│   └── [Generated plots and maps]
├── 📁 R/                             # All R scripts and functions
│   │   👩️ ***GO_access_analysis_code.Rmd***    # Main analysis report
│   ├── 📊 Data Collection (A-Series)
│   │   ├── A-abms.R                  # Board certification scraping
│   │   ├── A-facility_affiliation_download.R  # CMS facility data
│   │   ├── A-Medicare_part_d_prescribers_data_download.R
│   │   ├── A-NPI_deactivation_download.R     # Provider deactivation
│   │   ├── A-nppes_download.R        # Historical NPPES from NBER
│   │   ├── A-open_payments_download.R        # Sunshine Act data
│   │   └── A-physician_compare_data_download.R
│   ├── 📋 Data Read In (B-Series)
│   │   ├── B-Medicare_part_d_prescribers_read_in.R   # Read in data
│   │   ├── B-NPI_deactivation.R                      # Read in data
│   │   ├── B-NPPES_read_in_csv_to_duckDB_database.R  # Read in data
│   │   ├── B-open_payments_cleaning.R                # Read in data
│   │   ├── B-physician_compare_data_download.R       # Read in data
│   ├── 📋 Data Processing (C-Series)
│   │   ├── C-Extracting_and_Processing_NPPES_Provider_Data.R
│   │   ├── C-NPPES.R
│   │   ├── C-open_payments.R
│   │   ├── C-physician_compare_cleaning.R
│   ├── 📋 Data Quality Check (D-Series)
│   │   ├── D-Quality_check_medicare_prescribing.R
│   │   ├── D-Quality_check_on_NPPES_merge.R
│   ├── 📋 Export Cleaned Data (E-Series)
│   │   ├── E-Medicare_part_d_retirement_analysis_processing.R
│   │   ├── E-open_payments_export.R
│   │   └── F-retirement_year_confirmation.R
│   ├── 🗺️ Core Analysis Pipeline (00-10 Series)
│   │   ├── 000-Control.R             # Master control script
│   │   ├── 01-setup.R                # Environment and API setup
│   │   ├── 02-search_taxonomy.R      # NPPES taxonomy search
│   │   ├── 02.5-subspecialists_over_time.R   # Temporal trends
│   │   ├── 03-search_and_process_npi.R       # NPI data processing
│   │   ├── 03a-search_and_process_extra.R    # Additional NPI processing
│   │   ├── 04-geocode.R              # Address geocoding (HERE API)
│   │   ├── 06-isochrones.R           # Drive time isochrone generation
│   │   ├── 07-isochrone-mapping.R    # Spatial joins and mapping
│   │   ├── 07.5-prep-get-block-group-overlap.R
│   │   ├── 08-get-block-group-overlap.R      # Census block calculations
│   │   ├── 08.5-prep-the-census-variables.R
│   │   ├── 09-get-census-population.R        # Population analysis
│   │   ├── 10-calculate-polygon-demographics.R
│   │   └── 10-make-region.R          # Regional analysis
│   ├── 📈 Results & Analysis
│   │   ├── analyze_isochrone_data.R          # Statistical trend analysis
│   │   ├── walker_isochrone_maps.R           # Final map generation
│   │   ├── subspecialists_over_time.R        # Workforce trends
│   │   ├── retirement_adjusted.R             # Retirement analysis
│   │   └── getting_isochrones_trying.R       # Alternative methods
│   ├── 🛠️ Utility Functions
│   │   ├── api_keys.R                # API key management
│   │   ├── bespoke_functions.R       # Custom project functions
│   │   ├── geocode.R                 # Geocoding utilities
├── 📁 results/                       # Analysis outputs
│   ├── state_data.csv
│   ├── summary_statistics.csv
│   ├── table1_temporal_trends_summary.csv
│   ├── table2_demographic_disparities_summary.csv
│   ├── tabulated_all_years_clean_2024-08-30.xlsx
│   ├── temporal_trend_analysis.csv
│   ├── trend_analysis.csv
│   └── us_states.csv
├── 📄 README.Rmd                     # This documentation
├── 📄 README.html                    # Rendered HTML version

3.6.0.1 Data Gathering

  • bespoke_functions.R - Data for the duckDB connection and functions for the Data Gathering lettered code below. The National Bureau of Economic Research (NBER) provides a cumulative NPI/NPPES dataset created from monthly CMS files spanning from April 2007 to the present, addressing limitations in official CMS offerings that lack historical provider details. The dataset is deduplicated based on variable changes (excluding mere updates in file names or years), and includes separate core and multiplicative variable files to manage the large file sizes efficiently.
Dataset/Script Name Available Years Notes
A_nppes_download.R 2007–2022 NBER cumulative NPPES file (monthly updates deduplicated; includes changes back to 2007).
A-NPI_deactivation_download.R Varies, slightly delayed Based on self-reported deactivation. CMS updates irregularly; may lag real-time by 1–2 years.
A-Medicare_part_d_prescribers_data_downloaded 2013–2022 Released annually by CMS; first available dataset based on 2013 prescribing data.
A-download_physician_compare_download ~2013–2020 (downloaded files) ICPSR archive has files through ~2020 (Physician Compare closed in Dec 2020). Must manually log in.
A-facility_affiliation_download.R 2014–present First Facility Affiliation data started ~2014; yearly updates (CMS Physician Compare Affiliation data).
A-open_payments_download.R 2013–present Open Payments (Sunshine Act) started reporting payments in 2013. Annual updates.
  • A_nppes_download.R - Downloads NPPES data for back years from NBER (National Board Economic Research). The National Bureau of Economic Research (NBER) provides a cumulative NPI/NPPES dataset created from monthly CMS files spanning from April 2007 to 2022, addressing limitations in official CMS offerings that lack historical provider details. The dataset is deduplicated based on variable changes (excluding mere updates in file names or years), and includes separate core and multiplicative variable files to manage the large file sizes efficiently.

  • A-NPI_deactivation_download.R - NPPES data may be a few years behind and is all based on personal report.

  • A-Medicare_part_d_prescribers_data_downloaded - Good for docs who prescribe drugs to Medicare patients over 65 years old. Started 2013 to

  • A-download_physician_compare_download - To get old physician compare/national downloadable files we need to log in manually to OPEN ICPSR: https://www.openicpsr.org/openicpsr/project/149961/version/V1/view?path=/openicpsr/149961/fcr:versions/V1&type=project. You have to login with google account to download it.

  • A-facility_affiliation_download.R - Gold standard.

  • A-open_payments_download.R - Open Payments.

  • B-read_in_csv_file_to_duckDB_database.R - Reads in the NPPES CSV fils from the NBER to the duckDB database. The primary action occurs via the process_nppes_data function (defined in an external script bespoke_functions.R), which reads and processes a large CSV file containing historical NPI data (spanning May 2005 to October 2020). The processed data is stored in a DuckDB database file.

  • C-Extracting_and_Processing_NPPES_Provider_Data.R - Function for processing OBGYNs from NPPES data with exact file names for years 2010 to 2022. Automatically identifies and maps database tables to their corresponding years, enabling efficient extraction of provider data across different time periods. Specifies taxonomy codes representing various OB/GYN subspecialties, including general obstetrics and gynecology, maternal-fetal medicine, and female pelvic medicine. Looks at all taxonomy columns in each year’s dataset (not just the first one). Checks if any of your specified codes appear in any of those columns. Includes a physician in the results if there’s a match in any column. Retrieves provider records matching specified OB/GYN taxonomy codes from each year, standardizing and combining the data into a unified dataset.

  • D-Quality_check_on_NPPES_merge.R - The check_physician_presence function is a well-designed utility for tracking physicians across temporal data. It efficiently analyzes a dataset containing physician information to determine when specific providers appear in the records. The function accepts a list of National Provider Identifiers (NPIs), optionally paired with provider names, and methodically examines each NPI’s presence throughout different years. It returns a structured data frame summarizing each provider’s representation in the dataset, including their total record count and a chronological listing of years in which they appear. This function is particularly valuable for longitudinal analyses of healthcare provider data, enabling researchers to identify patterns in physician presence, track career trajectories, or validate data completeness across multiple years of NPI records.

# List of NPIs to check
npi_list <- c(
  "1689603763",   # Tyler Muffly, MD
  "1528060639",   # John Curtin, MD
  "1346355807",   # Pedro Miranda, MD
  "1437904760",   # Lizeth Acosta, MD
  "1568738854",   # Aaron Lazorwitz, MD
  "1194571661",   # Ana Gomez, MD
  "1699237040",   # Erin W. Franks, MD
  "1003311044",   # CATHERINE Callinan, MD
  "1609009943",   # Kristin Powell, MD
  "1114125051",   # Nathan Kow, MD
  "1043432123",   # Elena Tunitsky, MD
  "1215490446",   # PK
  "1487879987"    # Peter Jeppson
)
  • E-Medicare_part_d_prescribers_data_processing.R - This script processes Medicare Part D prescribing data from the Centers for Medicare & Medicaid Services (CMS). Process each table filtering “Prscrbr_Type” only OBGYN and “Gynecological Oncology”. It identifies providers’ prescribing patterns, cleans data by removing outlier records (claim counts over 50,000), annotates records by year, and merges multiple years into a single standardized dataset. Additionally, it calculates the last consecutive year each provider actively prescribed medications under Medicare Part D, facilitating analysis of provider activity and continuity over time. NOT GOOD FOR DOCS WHO DO NOT TREAT PATIENTS >65 years old.

  • F-retirement_year_confirmation.R - Download the massive data files to the external hard drive for this with one set of code then then can run E-retirement_year_confirmation.R.

Retirement Year Data download: NPPES_deactivated_download.R - Best source but may be late.
Medicare_part_d_prescribers_data_processing - People who prescribed to >65 year old women.
download_physician_compare_data.R - Includes data for people who see Medicare.
facility affiliation. - Does not include a year for the facility affiliation so it is not helpful.
ABMS - scraped.

  • getting_isochrones_trying.R - Alternative method for isochrone generation
  • retirement_adjusted.R - Enhanced retirement analysis using multiple data sources (NPI deactivation, Medicare data, and board certification status) to improve workforce accuracy.
  • subspecialists over time.R - Analysis of subspecialist trends
  • visualize_fips_inters_isochr.R - Visualizes FIPS code intersections
  • fips_blocks_female_proportion.R - Analyzes female population in FIPS blocks
  • fips_isochrones_population_intersect.R - Examines population within isochrones
  • zzzPostico.R - Used Postico originally. Able to use duckDB later on.
  • Postico_database_pull.R - Extracts physician data from PostgreSQL database, enabling year-by-year analysis of physician practice locations from 2013 to 2022. Pulls “GYNECOLOGIC ONCOLOGY” from the Primary Specialty. For urogyn, we will need NPIs to go retrospectively to look for people.

3.6.0.2 1. Setup and Data Preparation

  • 000-control.R - Auxiliary script for data compilation
  • 01-setup.R - Loads packages, sets API keys, defines helper functions, initializes directory structure
  • 02-search_taxonomy.R - Search the NPPES Registry database using npi_search library in a wrapper. Taxonomy description from the NUCC: https://taxonomy.nucc.org/. Note recent change in FPMRS to URPS.
  • 02.5-subspecialists_over_time.R - Analyzes subspecialist trends over multiple years
  • 03-search_and_process_npi.R - Processes National Provider Identifier (NPI) data
  • 03a-search_and_process_extra.R - Additional NPI processing for edge cases
  • 04-geocode.R - Geocodes provider addresses using the HERE API
  • zz05-geocode-cleaning.R - Old technique with postmaster pulling apart the address.

3.6.0.3 2. Isochrone Generation and Analysis

  • 06-isochrones.R - Generates drive time isochrones (30, 60, 120, 180 min)
  • 07-isochrone-mapping.R - Maps isochrones and performs spatial joins
  • 07.5-prep-get-block-group-overlap.R - Prepares census block group data
  • 08-get-block-group-overlap.R - Calculates overlap between isochrones and census blocks
  • 08.5-prep-the-census-variables.R - Prepares demographic variables from Census
  • 09-get-census-population.R - Calculates population within/outside isochrones

3.6.0.4 3. Results and Analysis

  • 10-calculate-polygon-demographcs.R - Analyzes demographic characteristics

  • 10-make-region.R - Creates regional maps and analyses

  • analyze_isochrone_data.R - Framework for analyzing isochrone data

  • calculate_population_in_isochrones_by_race.R - Analyzes population by race within isochrones

  • walker_isochrone_maps.R - Visualizes isochrone changes over time

  • Access_Data.csv - Data from Tannous that he arranged and is held in data/

3.6.1 R Markdown Documents

  • GO_access_analysis_code.Rmd - Statistical analysis of gynecologic oncology access
  • for_every_year_script_rmd.Rmd - Year-by-year analysis of accessibility trends
  • isochrones.Rmd - Tutorial on creating and analyzing isochrones

3.7 Execution Order

For a complete analysis, the files should be executed in approximately this order:

3.7.1 Setup Phase

  1. 01-setup.R
  2. Postico_database_pull.R (if external hardrive with the Positico database access is connected)

3.7.2 Data Collection Phase

  1. 02-search_taxonomy.R
  2. 02.5-subspecialists_over_time.R
  3. 03-search_and_process_npi.R - When did physicians start practicing?
  4. 03a-search_and_process_extra.R
  5. 04-geocode.R
  6. 05-geocode-cleaning.R
  7. retirement.R/retirement_adjusted.R - When did physicians retire? (if physician retirement analysis is needed)

3.7.3 Isochrone Analysis Phase

  1. 06-isochrones.R
  2. 07-isochrone-mapping.R
  3. 07.5-prep-get-block-group-overlap.R
  4. 08-get-block-group-overlap.R
  5. 08.5-prep-the-census-variables.R
  6. 09-get-census-population.R

3.7.4 Results and Additional Analysis Phase

  1. 10-calculate-polygon-demographcs.R

  2. 10-make-region.R

  3. script2025.R - Downloads the population data and aggregates it by isochrone and by total population. Creates tables of women within isochrones and total women.

> access_merged
# A tibble: 240 × 6
   year  range category              count     total percent
   <chr> <int> <chr>                 <dbl>     <dbl>   <dbl>
 1 2013   1800 total_female       72362517 162649954    44.5
 2 2013   1800 total_female_white 46553359 119180751    39.1
  1. analyze_isochrone_data.R - Measures the slope for access from start 2013 to finish 2022. Finds significant increases or decreases in the number of women within a drive time. Some notable trends:
  • Total female white population shows significant declines in access across all time thresholds
  • Some categories like total_female_asian show significant increases in longer-time thresholds
> isochrone_results$trend_analysis
                 category        time_threshold         slope    r_squared     p_value start_year end_year start_value
year         total_female  access_30min_cleaned -7.363956e+05 1.126669e-01 0.343029928       2013     2022    72362517
year1        total_female  access_60min_cleaned -6.301068e+05 7.221735e-02 0.452792176       2013     2022    98337640
year2        total_female access_120min_cleaned -1.340719e+05 4.509434e-03 0.853764926       2013     2022   133049027
year3        total_female access_180min_cleaned -3.015709e+03 2.336200e-06 0.996656494       2013     2022   148447072
year4   total_female_aian  access_30min_cleaned  8.242703e+03 1.559138e-01 0.258786159       2013     2022      316937
year5   total_female_aian  access_60min_cleaned  1.109027e+04 1.747050e-01 0.229364327       2013     2022      453807
  1. GO_access_analysis_code.Rmd

  2. walker_isochrone_maps.R - Creates a faceted map of the US, HI, AK, and PR with the isochrones in place.

  3. zzzcalculate_population_in_isochrones_by_race.R - I’m unsure if it is needed.

  4. zzzfor_every_year_script_rmd.Rmd - This is THE SAME MAP THAT WALKER DID IN walker_isochrone_maps.R BUT HE DID IT BETTER. Creates a map of the isochrones for every year.

3.7.5 Methodology Overview

3.7.5.1 Geospatial Analysis

  • Drive Time Isochrones: 30, 60, 120, and 180-minute thresholds
  • Routing Engine: HERE Maps API with real-time traffic data
  • Reference Time: Third Friday of October, 9:00 AM (consistent across years)
  • Geographic Resolution: Census block groups (higher precision than counties)

3.7.5.2 Demographic Analysis

  • Race/Ethnicity Categories: White, Black, Asian/Pacific Islander, American Indian/Alaska Native
  • Geographic Regions: ACOG (American College of Obstetricians and Gynecologists) Districts
  • Urban/Rural Classification: Census Bureau definitions

3.7.5.3 Physician Identification

# Taxonomy codes for OBGYN subspecialists
obgyn_taxonomy_codes <- c(
  "207V00000X",    # Obstetrics & Gynecology
  "207VX0201X",    # Gynecologic Oncology
  "207VE0102X",    # Reproductive Endocrinology
  "207VG0400X",    # Gynecology
  "207VM0101X",    # Maternal & Fetal Medicine
  "207VF0040X",    # Female Pelvic Medicine/Urogynecology
  "207VB0002X",    # Bariatric Medicine
  "207VC0200X",    # Critical Care Medicine
  "207VC0300X",    # Complex Family Planning
  "207VH0002X",    # Palliative Care
  "207VX0000X"     # Obstetrics Only
)

3.7.6 Data Sources

  • Physician Data: National Plan and Provider Enumeration System (NPPES) files from 2013 to 2023
  • Population Data: American Community Survey 5-year estimates and decennial census data
  • Geographic Analysis: Used block groups rather than counties for finer data resolution
  • Geographic Regions: American College of Obstetricians and Gynecologists (ACOG) Districts

3.7.7 Analysis Approach

  • Drive time isochrones (30, 60, 120, 180 minutes) calculated using HERE API
  • Isochrones generated for the third Friday in October at 9:00 AM for each year
  • Demographic analysis by race/ethnicity (White, Black, Asian or Pacific Islander, American Indian/Alaska Native)
  • Comparison of urban vs. rural accessibility

3.8 Prerequisites

3.8.1 System Requirements

# Check R version (minimum 4.0.0 required)
if (getRversion() < "4.0.0") {
  stop("R version 4.0.0 or higher is required. Current version: ", getRversion())
}

# Check available memory (8GB+ recommended)
memory_gb <- round(memory.limit() / 1024, 1)  # Windows
# memory_gb <- round(as.numeric(system("sysctl hw.memsize", intern = TRUE)) / 1024^3, 1)  # macOS
logger::log_info("Available memory: {memory_gb} GB")
if (memory_gb < 8) {
  logger::log_warn("Less than 8GB RAM detected. Large spatial operations may be slow.")
}
# Install required packages
required_packages <- c(
  "tidyverse", "sf", "tigris", "logger", "assertthat",
  "ggplot2", "scales", "viridis", "DT", "knitr"
)

# Install missing packages
new_packages <- required_packages[!(required_packages %in% installed.packages()[,"Package"])]
if(length(new_packages)) install.packages(new_packages)

# Load custom functions
source("R/bespoke_functions.R")
  • R 4.0.0 or higher
  • 8GB+ RAM recommended for large spatial datasets
  • Required R packages (listed in 01-setup.R)
  • HERE Maps API key
  • US Census Bureau API key
  • DuckDB database

3.8.2 HERE Maps Integration

Geocoding Pipeline: 1. Address standardization and cleaning 2. Batch geocoding requests (rate limit management) 3. Quality scoring and manual review of poor matches 4. Coordinate validation and outlier detection

Isochrone Generation: 1. Provider coordinate input 2. Multiple time threshold requests per provider 3. Polygon simplification for storage efficiency 4. Spatial validation and topology checking

Why DuckDB over PostgreSQL/SQLite: - Performance: Optimized for analytical queries (OLAP vs OLTP) - Simplicity: Single-file database, no server required - Memory: Efficient handling of large datasets - R Integration: Native R DBI support

Alternative Considered: PostgreSQL with PostGIS - Pros: Better spatial functions, multi-user - Cons: Server setup complexity, overkill for single-user analysis

3.9 Tools and Data Management

3.10 💻 API Configuration

3.10.1 HERE Maps API Setup

  • Used for geocoding and isochrone generation
  • Geocoding and Search: $0.83 per 1,000 searches after 30,000 free geocodes
  • Isoline Routing: $5.50 per 1,000 after 2,500 free isoline routings
# Set environment variables (add to .Renviron)
HERE_API_KEY <- "your_here_api_key_here"

# Verify API access
here_status <- httr::GET("https://geocoder.ls.hereapi.com/6.2/geocode.json",
                        query = list(apiKey = HERE_API_KEY,
                                   searchtext = "test"))

3.10.2 Census API Setup

# Install tidycensus if not already installed
if (!require(tidycensus)) install.packages("tidycensus")

# Set Census API key
census_api_key("your_census_api_key_here", install = TRUE)

3.10.3 API Key Setup:

  1. HERE Maps API:
  2. Census Bureau API:

3.10.4 Data Storage

  • GitHub LFS (Large File Storage) for managing large files
  • DuckDB for efficient data querying
  • PostgreSQL database for year-specific physician data

3.10.5 Auxiliary Tools

  • tyler package: Custom package for project-specific functions
  • Exploratory.io: Used for data wrangling

3.11 Key Outputs

  • Drive time isochrones at multiple thresholds (30, 60, 120, 180 minutes)
  • Population statistics within/outside isochrones
  • Demographic analysis by race/ethnicity
  • Temporal trends in accessibility (2013-2023)
  • Visualizations of geographic access patterns

3.12 Data Sources

For downloading NPPES files:

wget -P "/Volumes/Video Projects Muffly 1/nppes_historical_downloads" "https://download.cms.gov/nppes/NPPES_Data_Dissemination_April_2024.zip"

4 DATA REFERENCES

# ==============================================================================
# COPY/PASTE READY REFERENCE VALUES - GYNECOLOGIC ONCOLOGY ACCESSIBILITY PROJECT
# WITH OFFICIAL SOURCES AND CITATIONS
# ==============================================================================

# TAXONOMY CODES FOR OBGYN SUBSPECIALISTS
# Source: National Uniform Claim Committee (NUCC) Health Care Provider Taxonomy
# URL: https://taxonomy.nucc.org/
# Last Updated: Version 23.1 (July 2023)
obgyn_taxonomy_codes <- c(
  "207V00000X",    # Obstetrics & Gynecology (general)
  "207VX0201X",    # Gynecologic Oncology (PRIMARY FOCUS)
  "207VE0102X",    # Reproductive Endocrinology and Infertility
  "207VG0400X",    # Gynecology (general)
  "207VM0101X",    # Maternal & Fetal Medicine
  "207VF0040X",    # Female Pelvic Medicine/Urogynecology
  "207VB0002X",    # Bariatric Medicine
  "207VC0200X",    # Critical Care Medicine
  "207VC0300X",    # Complex Family Planning
  "207VH0002X",    # Hospice and Palliative Medicine
  "207VX0000X"     # Obstetrics only
)

# RUCA CODES (RURAL-URBAN COMMUTING AREAS)
# Source: USDA Economic Research Service
# URL: https://www.ers.usda.gov/data-products/rural-urban-commuting-area-codes/
# Publication: "Rural-Urban Commuting Area Codes" (2010 Census-based, most recent)
# Citation: USDA ERS. Rural-Urban Commuting Area Codes. Washington, DC: Economic Research Service; 2013.
ruca_codes_all <- c(1.0, 1.1, 2.0, 2.1, 3.0, 4.1, 4.2, 5.0, 5.1, 6.0, 6.1, 
                   7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4, 9.0, 
                   10.0, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6)

# RUCA SIMPLIFIED CATEGORIES
# Source: Hart LG, Larson EH, Lishner DM. Rural definitions for health policy research. 
# Am J Public Health. 2005;95(7):1149-1155.
# Also: Morrill R, Cromartie J, Hart G. Metropolitan, urban, and rural commuting areas: 
# toward a better depiction of the United States settlement system. Urban Geography. 1999;20(8):727-748.
ruca_metropolitan <- c(1.0, 1.1, 2.0, 2.1, 3.0)       # Large metro areas
ruca_micropolitan <- c(4.1, 4.2, 5.0, 5.1, 6.0, 6.1)  # Mid-size cities  
ruca_small_town <- c(7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4)  # Small towns
ruca_rural <- c(9.0, 10.0, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6)  # Rural areas

# US CENSUS REGIONS AND DIVISIONS
# Source: US Census Bureau Geography Division
# URL: https://www2.census.gov/geo/pdfs/maps-data/maps/reference/us_regdiv.pdf
# Publication: "Geographic Areas Reference Manual" Chapter 6
# Citation: US Census Bureau. Geographic Areas Reference Manual. Washington, DC: US Census Bureau; 1994.
# Official Definition: Title 13, United States Code, Section 4
census_regions <- c("Northeast", "Midwest", "South", "West")
census_divisions <- c("New England", "Middle Atlantic", "East North Central", 
                     "West North Central", "South Atlantic", "East South Central",
                     "West South Central", "Mountain", "Pacific")

# STATE ABBREVIATIONS BY CENSUS REGION
# Source: US Census Bureau, Geography Division
# URL: https://www.census.gov/geographies/reference-files/2010/geo/state-area.html
# Note: Established by Federal Information Processing Standards (FIPS) Publication 5-2
northeast_states <- c("CT", "ME", "MA", "NH", "RI", "VT", "NJ", "NY", "PA")
midwest_states <- c("IL", "IN", "MI", "OH", "WI", "IA", "KS", "MN", "MO", "NE", "ND", "SD")
south_states <- c("DE", "FL", "GA", "MD", "NC", "SC", "VA", "WV", "DC", "AL", "KY", "MS", "TN", "AR", "LA", "OK", "TX")
west_states <- c("AZ", "CO", "ID", "MT", "NV", "NM", "UT", "WY", "AK", "CA", "HI", "OR", "WA")

# ACOG DISTRICTS BY STATE
# Source: American College of Obstetricians and Gynecologists
# URL: https://www.acog.org/about/districts-and-sections
# Publication: ACOG Organization Manual, current as of 2023
# Citation: American College of Obstetricians and Gynecologists. District Organization. Washington, DC: ACOG; 2023.
acog_district_1 <- c("CT", "ME", "MA", "NH", "RI", "VT")  # New England
acog_district_2 <- c("NY")  # New York Metro
acog_district_3 <- c("DE", "NJ", "PA")  # Mid-Atlantic
acog_district_4 <- c("DC", "MD", "VA", "WV")  # Southeast
acog_district_5 <- c("AL", "FL", "GA", "MS", "SC", "TN")  # Southeast
acog_district_6 <- c("IL", "IN", "IA", "KY", "MN", "MO", "NE", "ND", "OH", "SD", "WI")  # Midwest/Plains
acog_district_7 <- c("AZ", "CO", "NV", "NM", "UT", "WY")  # Mountain West
acog_district_8 <- c("AK", "ID", "MT", "OR", "WA")  # Pacific Northwest
acog_district_9 <- c("CA", "HI")  # Pacific West
acog_district_10 <- c("AR", "KS", "LA", "OK", "TX")  # South Central
acog_district_11 <- c("MI", "NC")  # Great Lakes/Southeast

# ALL US STATES AND TERRITORIES
# Source: Federal Information Processing Standards (FIPS) Publication 5-2
# URL: https://www.census.gov/library/reference/code-lists/ansi.html
# Citation: National Institute of Standards and Technology. FIPS PUB 5-2: Codes for the Identification of the States. Gaithersburg, MD: NIST; 1987.
all_states <- c("AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", "GA", 
               "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD",
               "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ",
               "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC", 
               "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY", "DC")

us_territories <- c("AS", "GU", "MP", "PR", "VI")  # American Samoa, Guam, N. Mariana Islands, Puerto Rico, Virgin Islands

# STATE FIPS CODES
# Source: Federal Information Processing Standards (FIPS) Publication 5-2
# URL: https://www.census.gov/library/reference/code-lists/ansi.html
# Citation: Same as above
state_fips <- c("01", "02", "04", "05", "06", "08", "09", "10", "12", "13",
               "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", 
               "25", "26", "27", "28", "29", "30", "31", "32", "33", "34",
               "35", "36", "37", "38", "39", "40", "41", "42", "44", "45",
               "46", "47", "48", "49", "50", "51", "53", "54", "55", "56", "11")

# REFERENCE DATES - THIRD FRIDAY OCTOBER 9AM (2013-2023)
# Source: Project methodology decision
# Rationale: Standardized weekday morning time to avoid rush hour peaks and ensure consistency
# Citation: Muffly T. Gynecologic Oncology Accessibility Project Methodology. 2024.
reference_dates_2013_2023 <- c(
  "2013-10-18", "2014-10-17", "2015-10-16", "2016-10-21", "2017-10-20",
  "2018-10-19", "2019-10-18", "2020-10-16", "2021-10-15", "2022-10-21", "2023-10-20"
)

# ISO DATETIME FORMAT FOR API CALLS
# Source: ISO 8601 Standard for date/time representation
# URL: https://www.iso.org/iso-8601-date-and-time-format.html
iso_datetime_2013_2023 <- c(
  "2013-10-18T09:00:00", "2014-10-17T09:00:00", "2015-10-16T09:00:00",
  "2016-10-21T09:00:00", "2017-10-20T09:00:00", "2018-10-19T09:00:00",
  "2019-10-18T09:00:00", "2020-10-16T09:00:00", "2021-10-15T09:00:00", 
  "2022-10-21T09:00:00", "2023-10-20T09:00:00"
)

# DRIVE TIME THRESHOLDS
# Source: Healthcare accessibility literature standards
# Citations: 
# - Penchansky R, Thomas JW. The concept of access: definition and relationship to consumer satisfaction. Med Care. 1981;19(2):127-140.
# - Wang F, Luo W. Assessing spatial and nonspatial factors for healthcare access: towards an integrated approach to defining health professional shortage areas. Health Place. 2005;11(2):131-146.
drive_times_minutes <- c(30, 60, 120, 180)
drive_times_seconds <- c(1800, 3600, 7200, 10800)  # For HERE API

# COORDINATE REFERENCE SYSTEMS (EPSG CODES)
# Source: European Petroleum Survey Group (EPSG) Geodetic Parameter Dataset
# URL: https://epsg.org/
# Citation: EPSG. EPSG Geodetic Parameter Dataset. Oil & Gas Producers Association; 2023.
epsg_wgs84 <- 4326          # WGS84 Geographic (input coordinates)
epsg_web_mercator <- 3857   # Web Mercator (web display)
epsg_us_albers <- 5070      # US Albers Equal Area (analysis)
epsg_alaska_albers <- 3338  # Alaska Albers
epsg_hawaii_albers <- 4135  # Hawaii Albers

# CENSUS VARIABLES (ACS 5-YEAR)
# Source: US Census Bureau American Community Survey
# URL: https://www.census.gov/programs-surveys/acs/guidance/subjects.html
# Publication: American Community Survey Subject Definitions
# Citation: US Census Bureau. American Community Survey Subject Definitions. Washington, DC: US Census Bureau; 2021.
census_total_population <- "B01003_001"
census_female_population <- "B01001_026"
census_white_alone <- "B03002_003"
census_black_alone <- "B03002_004"
census_asian_alone <- "B03002_006"
census_aian_alone <- "B03002_005"  # American Indian/Alaska Native
census_median_income <- "B19013_001"
census_housing_units <- "B25001_001"

# HERE API ENDPOINTS
# Source: HERE Technologies Developer Documentation
# URL: https://developer.here.com/documentation/
# Citation: HERE Technologies. HERE Platform Developer Guide. Eindhoven, Netherlands: HERE; 2023.
here_geocoding_url <- "https://geocoder.ls.hereapi.com/6.2/geocode.json"
here_reverse_geocoding_url <- "https://reverse.geocoder.ls.hereapi.com/6.2/reversegeocode.json"
here_isoline_url <- "https://isoline.route.ls.hereapi.com/routing/7.2/calculateisoline.json"

# HERE API PARAMETERS
# Source: HERE Routing API Documentation
# URL: https://developer.here.com/documentation/routing-api/dev_guide/topics/resource-calculate-isoline.html
here_isoline_mode <- "car"
here_isoline_traffic <- "enabled"
here_isoline_rangetype <- "time"
here_isoline_resolution <- 1    # Highest resolution
here_isoline_maxpoints <- 1000  # Maximum polygon points
here_isoline_quality <- 1       # Highest quality

# US TIMEZONES
# Source: Internet Assigned Numbers Authority (IANA) Time Zone Database
# URL: https://www.iana.org/time-zones
# Citation: IANA. Time Zone Database. Internet Assigned Numbers Authority; 2023.
us_timezones <- c("America/New_York", "America/Chicago", "America/Denver", 
                 "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu")
timezone_names <- c("Eastern", "Central", "Mountain", "Pacific", "Alaska", "Hawaii")

# MAJOR METROPOLITAN AREAS (CBSAs)
# Source: Office of Management and Budget
# URL: https://www.whitehouse.gov/omb/management/office-federal-financial-management/
# Publication: OMB Bulletin No. 20-01 (March 6, 2020)
# Citation: Office of Management and Budget. Revised Delineations of Metropolitan Statistical Areas, Micropolitan Statistical Areas, and Combined Statistical Areas. Washington, DC: OMB; 2020.
major_cbsa_codes <- c("35620", "31080", "16980", "19100", "26420", "33460", "37980", 
                     "40140", "41860", "47900", "12060", "14460", "41740", "38060")

major_msa_names <- c(
  "New York-Newark-Jersey City, NY-NJ-PA",
  "Los Angeles-Long Beach-Anaheim, CA", 
  "Chicago-Naperville-Elgin, IL-IN-WI",
  "Dallas-Fort Worth-Arlington, TX",
  "Houston-The Woodlands-Sugar Land, TX",
  "Miami-Fort Lauderdale-West Palm Beach, FL",
  "Philadelphia-Camden-Wilmington, PA-NJ-DE-MD",
  "Riverside-San Bernardino-Ontario, CA",
  "San Francisco-Oakland-Hayward, CA",
  "Washington-Arlington-Alexandria, DC-VA-MD-WV",
  "Atlanta-Sandy Springs-Roswell, GA", 
  "Boston-Cambridge-Newton, MA-NH",
  "San Antonio-New Braunfels, TX",
  "Phoenix-Mesa-Scottsdale, AZ"
)

# MAJOR INTERSTATE HIGHWAYS
# Source: Federal Highway Administration
# URL: https://www.fhwa.dot.gov/planning/national_highway_system/
# Publication: National Highway System
# Citation: Federal Highway Administration. National Highway System. Washington, DC: US Department of Transportation; 2023.

# East-West Interstates
interstate_east_west <- c("I-10", "I-20", "I-30", "I-40", "I-70", "I-80", "I-90")

# North-South Interstates  
interstate_north_south <- c("I-5", "I-15", "I-25", "I-35", "I-65", "I-75", "I-85", "I-95")

# All Major Interstates
all_major_interstates <- c(interstate_east_west, interstate_north_south)

# VALIDATION THRESHOLDS
# Source: Project quality control standards based on literature review
# Citations:
# - Baldwin LM, et al. Access to specialty health care for rural American Indians in the northwest. Med Care. 2008;46(12):1218-1224.
# - Onega T, et al. Geographic access to cancer care in the U.S. Cancer. 2008;112(4):909-918.
min_provider_count <- 40000      # Minimum NPPES providers expected
min_gyn_onc_count <- 1000       # Minimum gynecologic oncologists
min_geocoding_success <- 0.85   # Minimum geocoding success rate
min_isochrone_success <- 0.90   # Minimum isochrone generation success
min_population_coverage <- 0.95 # Minimum census population coverage

# QUALITY CONTROL RANGES
# Source: US Geological Survey Geographic Names Information System
# URL: https://geonames.usgs.gov/domestic/
# Citation: US Geological Survey. Geographic Names Information System. Reston, VA: USGS; 2023.
max_coordinate_lat <- 71.5      # Northernmost US point (Alaska)
min_coordinate_lat <- 18.9      # Southernmost US point (Hawaii) 
max_coordinate_lon <- -66.9     # Easternmost US point (Maine)
min_coordinate_lon <- -179.1    # Westernmost US point (Alaska)

# CENSUS GEOGRAPHY COUNTS (2020 Census)
# Source: US Census Bureau Geography Division
# URL: https://www.census.gov/geographies/reference-files/2020/geo/tallies/
# Publication: 2020 Census Geographic Tallies
# Citation: US Census Bureau. 2020 Census Geographic Tallies. Washington, DC: US Census Bureau; 2021.
census_2020_states <- 51           # 50 states + DC
census_2020_counties <- 3143       # Total counties
census_2020_tracts <- 84414        # Census tracts
census_2020_block_groups <- 242335 # Block groups

# API RATE LIMITS
# Source: HERE Technologies Developer Portal
# URL: https://developer.here.com/pricing
# Current as of: 2023
here_geocoding_free_limit <- 30000    # Per month
here_isoline_free_limit <- 2500       # Per month
census_api_daily_limit <- 500         # Without API key

# DIRECTORY STRUCTURE
# Source: Project organization standards following best practices
# Citation: Wilson G, et al. Good enough practices in scientific computing. PLoS Comput Biol. 2017;13(6):e1005510.
dir_data_raw <- "data/raw/"
dir_data_processed <- "data/processed/"
dir_data_geocoded <- "data/geocoded/"
dir_data_spatial <- "data/spatial/"
dir_results <- "results/"
dir_figures <- "figures/"
dir_cache <- "cache/"

5 URL Reference Table - Gynecologic Oncology Accessibility Project

5.1 Data Sources - Primary

Resource Name URL Description Access Type
NPPES (National Plan and Provider Enumeration System) https://nppes.cms.hhs.gov/ Primary provider registry Public
NBER NPPES Historical Data https://www.nber.org/research/data/national-plan-and-provider-enumeration-system-nppes-data Historical provider data 2007-2022 Public
CMS Medicare Part D Prescriber Data https://www.cms.gov/Research-Statistics-Data-and-Systems/Statistics-Trends-and-Reports/Medicare-Provider-Charge-Data/Part-D-Prescriber Annual prescribing patterns Public
CMS Physician Compare (Historical) https://www.openicpsr.org/openicpsr/project/149961/version/V1/view Historical physician data through 2020 Requires Login
CMS Open Payments (Sunshine Act) https://openpaymentsdata.cms.gov/ Industry payments to physicians Public
CMS Provider Enrollment Data https://www.cms.gov/Research-Statistics-Data-and-Systems/Statistics-Trends-and-Reports/Medicare-Provider-Charge-Data Provider enrollment and specialty Public
NPPES Data Dissemination https://download.cms.gov/nppes/NPI_Files.html Monthly NPPES data downloads Public
CMS Data Navigator https://www.cms.gov/data-research/statistics-trends-and-reports/cms-data-navigator CMS data portal and navigation Public

5.2 Census & Geographic Data

Resource Name URL Description Access Type
US Census Bureau API https://api.census.gov/data.html Main census data API portal Public
American Community Survey (ACS) https://www.census.gov/programs-surveys/acs Population and demographic data Public
TIGER/Line Shapefiles https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Geographic boundary files Public
Census Geography Products https://www.census.gov/programs-surveys/geography.html Geographic concepts and products Public
Rural-Urban Commuting Area Codes https://www.ers.usda.gov/data-products/rural-urban-commuting-area-codes/ RUCA classification system Public
Metropolitan Statistical Areas https://www.census.gov/programs-surveys/metro-micro.html MSA definitions and data Public
Census API Key Registration https://api.census.gov/data/key_signup.html Free API key registration Registration
Federal Information Processing Standards https://www.census.gov/library/reference/code-lists/ansi.html FIPS codes and standards Public

5.3 API Documentation

Resource Name URL Description Access Type
HERE Maps Developer Portal https://developer.here.com/ HERE API registration and docs API Key Required
HERE Geocoding API Documentation https://developer.here.com/documentation/geocoder/ Address geocoding documentation API Key Required
HERE Isoline Routing API https://developer.here.com/documentation/routing-api/ Drive time isochrone generation API Key Required
Census Bureau API Documentation https://www.census.gov/data/developers/guidance.html Census API usage guidelines Public
HERE API Pricing https://developer.here.com/pricing Rate limits and pricing tiers Public
REST API Best Practices https://developer.here.com/documentation/identity-access-management/dev_guide/topics/plat-using-apikeys.html API key management Public

5.4 Healthcare & Medical Resources

Resource Name URL Description Access Type
NUCC Health Care Provider Taxonomy https://taxonomy.nucc.org/ Official provider taxonomy codes Public
ACOG (American College of Obstetricians and Gynecologists) https://www.acog.org/ Professional organization Public
ACOG Districts https://www.acog.org/about/districts-and-sections Geographic district organization Public
Society of Gynecologic Oncology https://www.sgo.org/ Subspecialty professional society Public
NCCN Guidelines (Gynecologic Oncology) https://www.nccn.org/guidelines/category_1 Clinical practice guidelines Registration
ACGME Fellowship Requirements https://www.acgme.org/specialties/ Fellowship training requirements Public
AAMC Physician Workforce Data https://www.aamc.org/data-reports/workforce/data Physician workforce statistics Public
HRSA Health Professional Shortage Areas https://data.hrsa.gov/tools/shortage-area Underserved area designations Public

5.5 Government Resources

Resource Name URL Description Access Type
CMS (Centers for Medicare & Medicaid Services) https://www.cms.gov/ Primary healthcare data agency Public
HRSA (Health Resources and Services Administration) https://www.hrsa.gov/ Federal health workforce agency Public
USDA Economic Research Service https://www.ers.usda.gov/ Rural-urban classifications Public
OMB Metropolitan Area Delineations https://www.whitehouse.gov/omb/management/office-federal-financial-management/ Official MSA definitions Public
HHS Data Portal https://healthdata.gov/ Federal health data catalog Public
National Cancer Institute https://www.cancer.gov/ Cancer statistics and resources Public
Federal Geographic Data Committee https://www.fgdc.gov/ Geographic data standards Public

5.6 Technical Documentation

Resource Name URL Description Access Type
R Project https://www.r-project.org/ R statistical software Open Source
RStudio https://www.rstudio.com/ R development environment Free/Commercial
sf R Package Documentation https://r-spatial.github.io/sf/ Spatial features for R Open Source
tigris R Package https://github.com/walkerke/tigris Census geography in R Open Source
DuckDB Documentation https://duckdb.org/docs/ Analytical database engine Open Source
GDAL Documentation https://gdal.org/ Geospatial data abstraction library Open Source
PROJ Coordinate Transformation https://proj.org/ Cartographic projections library Open Source
PostGIS Documentation https://postgis.net/documentation/ Spatial database extension Open Source
GitHub Repository Best Practices https://docs.github.com/en/repositories Version control and collaboration Public

5.7 Academic & Research Resources

Resource Name URL Description Access Type
PubMed https://pubmed.ncbi.nlm.nih.gov/ Medical literature database Public
SEER Cancer Statistics https://seer.cancer.gov/ National cancer surveillance Public
Health Affairs Journal https://www.healthaffairs.org/ Health policy research Subscription
Medical Care Research and Review https://journals.sagepub.com/home/mcr Healthcare access research Subscription
Spatial and Spatio-temporal Epidemiology https://www.journals.elsevier.com/spatial-and-spatio-temporal-epidemiology Spatial health analysis Subscription
International Journal of Health Geographics https://ij-healthgeographics.biomedcentral.com/ Health geography research Open Access

5.8 Software & Tools

Resource Name URL Description Access Type
CRAN (R Package Repository) https://cran.r-project.org/ R package downloads Open Source
GitHub https://github.com/ Code repository and collaboration Free/Paid
Docker Hub https://hub.docker.com/ Container registry Free/Paid
Conda Package Manager https://docs.conda.io/ Package management system Open Source
renv R Package https://rstudio.github.io/renv/ R environment management Open Source
Git Documentation https://git-scm.com/doc Version control system Open Source
Zenodo https://zenodo.org/ Research data repository Free
Open Science Framework https://osf.io/ Research project management Free

5.9 Professional Organizations & Standards

Resource Name URL Description Access Type
American Medical Association https://www.ama-assn.org/ Medical professional organization Public
Association of American Medical Colleges https://www.aamc.org/ Medical education organization Public
National Quality Forum https://www.qualityforum.org/ Healthcare quality standards Public
International Association of Geographers https://iag-online.org/ Geographic research organization Public
American Statistical Association https://www.amstat.org/ Statistical methods and standards Public

5.10 Data Standards & Metadata

Resource Name URL Description Access Type
HL7 FHIR Standards https://www.hl7.org/fhir/ Healthcare data exchange standards Public
ISO Geographic Standards https://www.iso.org/committee/54904.html International geographic standards Public
OGC Standards https://www.ogc.org/standards Geospatial data standards Public
Dublin Core Metadata https://www.dublincore.org/ Metadata standards Public
Schema.org https://schema.org/ Structured data vocabulary Public

5.11 Quality Control & Validation

Resource Name URL Description Access Type
American Community Survey Accuracy Statement https://www.census.gov/programs-surveys/acs/guidance/statistical-testing-tool.html ACS data accuracy guidelines Public
HERE Map Quality https://developer.here.com/documentation/routing-api/dev_guide/topics/resource-calculate-isoline.html API data quality specifications API Documentation
CMS Data Quality Assurance https://www.cms.gov/Research-Statistics-Data-and-Systems/CMS-Information-Technology/AccesstoDataApplication/DataUseAgreements Data quality standards Public
Spatial Data Quality Standards https://www.fgdc.gov/standards/projects/framework-data-standard Federal spatial data quality Public

6 SHAPEFILE - Geographic Boundaries for Healthcare Accessibility Analysis

7 Simplified US Boundaries Reference

7.1 US Census Bureau Cartographic Boundary Files (Simplified)

7.1.1 Country/National Boundaries

Resolution File Name Pattern Download URL File Size Use Case
20m (High Detail) cb_2021_us_nation_20m.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ ~50MB Detailed national analysis
5m (Medium Detail) cb_2021_us_nation_5m.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ ~20MB General national mapping
500k (Low Detail) cb_2021_us_nation_500k.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ ~5MB Web mapping, overview maps

7.1.2 State Boundaries (Simplified)

Resolution File Name Pattern Download URL File Size Use Case
20m (High Detail) cb_2021_us_state_20m.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ ~25MB Detailed state analysis
5m (Medium Detail) cb_2021_us_state_5m.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ ~8MB RECOMMENDED for most analysis
500k (Low Detail) cb_2021_us_state_500k.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ ~2MB Web display, overview maps

7.1.3 County Boundaries (Simplified)

Resolution File Name Pattern Download URL File Size Use Case
20m cb_2021_us_county_20m.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ ~45MB Detailed county analysis
5m cb_2021_us_county_5m.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ ~15MB RECOMMENDED
500k cb_2021_us_county_500k.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ ~4MB Web mapping

7.1.4 Census Tract Boundaries (Simplified)

Resolution File Name Pattern Download URL File Size Use Case
National 500k cb_2021_us_tract_500k.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ ~180MB National tract analysis
State-by-State 500k cb_2021_[FIPS]_tract_500k.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ 1-20MB each State-specific analysis

Example State Files: - Colorado: cb_2021_08_tract_500k.zip - California: cb_2021_06_tract_500k.zip
- Texas: cb_2021_48_tract_500k.zip - New York: cb_2021_36_tract_500k.zip

7.1.5 Block Group Boundaries (Simplified)

File Type File Name Pattern Download URL File Size Notes
National cb_2021_us_bg_500k.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ ~350MB Similar to your simplified_us_lck_grp_2021.shp
State-by-State cb_2021_[FIPS]_bg_500k.zip https://www2.census.gov/geo/tiger/GENZ2021/shp/ 2-40MB each Smaller, manageable files

7.2 R Package Sources for Simplified Boundaries

7.2.1 tigris Package (Automatic Simplification)

# Simplified boundaries with cb = TRUE parameter
library(tigris)

# US States (simplified)
states_simplified <- tigris::states(cb = TRUE, resolution = "20m")  # or "5m", "500k"

# US Counties (simplified)  
counties_simplified <- tigris::counties(cb = TRUE, resolution = "20m")

# Census Tracts (simplified) - by state
colorado_tracts <- tigris::tracts(state = "CO", cb = TRUE)

# Block Groups (simplified) - by state  
colorado_bg <- tigris::block_groups(state = "CO", cb = TRUE)

# National boundaries
us_nation <- tigris::nation(cb = TRUE, resolution = "5m")

7.2.2 USAboundaries Package (Historical + Simplified)

library(USAboundaries)

# Current simplified state boundaries
states_2020 <- us_states(resolution = "low")    # Simplified
states_2020_hi <- us_states(resolution = "high") # Detailed

# Current simplified county boundaries  
counties_2020 <- us_counties(resolution = "low")

# Historical boundaries (simplified)
states_1990 <- us_states(map_date = "1990-01-01", resolution = "low")

7.3 Alternative Simplified Boundary Sources

7.3.1 Natural Earth (Global, Multi-Scale)

Scale Resolution Download URL US Coverage
1:10m High detail https://www.naturalearthdata.com/downloads/10m-cultural-vectors/ Detailed US boundaries
1:50m Medium detail https://www.naturalearthdata.com/downloads/50m-cultural-vectors/ RECOMMENDED
1:110m Low detail https://www.naturalearthdata.com/downloads/110m-cultural-vectors/ Overview mapping

Specific Files: - Countries: ne_50m_admin_0_countries.zip - States/Provinces: ne_50m_admin_1_states_provinces.zip

7.3.2 OpenStreetMap (Simplified Extracts)

Source Description Download URL Format
Geofabrik US state extracts https://download.geofabrik.de/north-america/us/ Various formats
BBBike Custom extracts https://extract.bbbike.org/ Shapefile, GeoJSON

8 Creating Your Own Simplified Boundaries

8.0.1 Using R (sf package)

library(sf)

# Load detailed boundary
detailed_boundary <- st_read("detailed_boundary.shp")

# Simplify geometry (tolerance in map units)
simplified_boundary <- st_simplify(detailed_boundary, dTolerance = 1000)  # 1km tolerance

# Alternative: preserve topology
simplified_boundary <- st_simplify(detailed_boundary, preserveTopology = TRUE, dTolerance = 500)

# Save simplified version
st_write(simplified_boundary, "simplified_boundary.shp")

8.1 R Code Examples for Common Use Cases

8.1.1 Load All Simplified Boundaries

library(tigris)
library(sf)

# Set options for simplified boundaries
options(tigris_use_cache = TRUE)  # Cache for faster repeated access

# Load simplified boundaries
us_states <- tigris::states(cb = TRUE, resolution = "5m")
us_counties <- tigris::counties(cb = TRUE, resolution = "5m") 
us_nation <- tigris::nation(cb = TRUE, resolution = "5m")

# Load census tracts for specific states (simplified)
colorado_tracts <- tigris::tracts(state = "CO", cb = TRUE)
california_tracts <- tigris::tracts(state = "CA", cb = TRUE)

# Load block groups for analysis (similar to your file)
colorado_bg <- tigris::block_groups(state = "CO", cb = TRUE)

8.1.2 Performance Comparison

Boundary Type Detailed Size Simplified Size Speed Improvement
US States ~15MB ~8MB 2x faster rendering
US Counties ~80MB ~15MB 5x faster rendering
Census Tracts ~1.2GB ~180MB 10x faster rendering
Block Groups ~2.5GB ~350MB 15x faster rendering

8.2 Quality Control for Simplified Boundaries

8.2.1 Validation Checks

# Check validity of simplified geometries
st_is_valid(simplified_boundary)

# Fix invalid geometries if needed
simplified_boundary <- st_make_valid(simplified_boundary)

# Check area preservation (should be close to original)
original_area <- sum(st_area(detailed_boundary))
simplified_area <- sum(st_area(simplified_boundary))
area_difference <- abs(simplified_area - original_area) / original_area
print(paste("Area difference:", scales::percent(area_difference)))

8.3 File Naming Convention Reference

8.3.1 Census Bureau Pattern

  • cb_[YEAR]_[GEOGRAPHY]_[ENTITY]_[RESOLUTION].zip
  • Examples:
    • cb_2021_us_state_5m.zip (US states, 5m resolution)
    • cb_2021_08_tract_500k.zip (Colorado tracts, 500k resolution)
    • cb_2021_us_bg_500k.zip (US block groups, 500k resolution)

8.3.2 Resolution Codes

  • 20m: 1:20,000,000 scale (high detail)
  • 5m: 1:5,000,000 scale (medium detail)
  • 500k: 1:500,000 scale (low detail, most simplified)

The 500k resolution files are closest to your simplified_us_lck_grp_2021.shp pattern and are optimized for analytical work while maintaining essential geographic accuracy.

9 US Census Bureau Geographic Boundaries

Geographic Unit Data Source Download URL File Format Coverage Update Frequency Notes
Census Tracts US Census Bureau https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile, KML, GeoJSON National, State, County Annual Primary analysis unit for demographics
Census Block Groups US Census Bureau https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile, KML, GeoJSON National, State, County Annual Highest resolution demographic data
Census Blocks US Census Bureau https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile, KML, GeoJSON National, State, County Annual Most detailed geographic unit
State Boundaries US Census Bureau https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile, KML, GeoJSON National Annual State-level analysis
County Boundaries US Census Bureau https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile, KML, GeoJSON National, State Annual County-level aggregation
ZIP Code Tabulation Areas (ZCTAs) US Census Bureau https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile, KML, GeoJSON National Decennial Census Approximate ZIP code areas
Urban Areas US Census Bureau https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile, KML, GeoJSON National Decennial Census Urban vs rural classification

9.1 Health Resources and Services Administration (HRSA) Areas

Geographic Unit Data Source Download URL File Format Coverage Update Frequency Notes
Health Professional Shortage Areas (HPSAs) HRSA https://data.hrsa.gov/data/download Shapefile, GeoJSON, CSV National Quarterly Primary care, dental, mental health
Medically Underserved Areas (MUAs) HRSA https://data.hrsa.gov/data/download Shapefile, GeoJSON, CSV National Quarterly Areas lacking medical care
Medically Underserved Populations (MUPs) HRSA https://data.hrsa.gov/data/download Shapefile, GeoJSON, CSV National Quarterly Population-based designations
Federally Qualified Health Centers (FQHCs) HRSA https://data.hrsa.gov/data/download Point data, CSV National Monthly FQHC locations
Rural Health Clinics HRSA https://data.hrsa.gov/data/download Point data, CSV National Monthly RHC locations
Critical Access Hospitals HRSA https://data.hrsa.gov/data/download Point data, CSV National Monthly CAH locations

9.2 Rural-Urban Classifications

Geographic Unit Data Source Download URL File Format Coverage Update Frequency Notes
Rural-Urban Commuting Areas (RUCAs) USDA ERS https://www.ers.usda.gov/data-products/rural-urban-commuting-area-codes/documentation/ CSV with FIPS codes National (Census Tracts) ~10 years 2010 Census-based (most recent)
Urban Influence Codes USDA ERS https://www.ers.usda.gov/data-products/urban-influence-codes/ CSV with FIPS codes National (Counties) ~10 years County-level rural-urban
Rural-Urban Continuum Codes USDA ERS https://www.ers.usda.gov/data-products/rural-urban-continuum-codes/ CSV with FIPS codes National (Counties) ~10 years Metro and non-metro counties

9.3 ACOG Districts and Medical Professional Areas

Geographic Unit Data Source Download URL File Format Coverage Update Frequency Notes
Hospital Referral Regions (HRRs) Dartmouth Atlas https://www.dartmouthatlas.org/tools/downloads.aspx Shapefile National ~10 years Healthcare market areas
Hospital Service Areas (HSAs) Dartmouth Atlas https://www.dartmouthatlas.org/tools/downloads.aspx Shapefile National ~10 years Local hospital markets

9.4 Transportation and Infrastructure

Geographic Unit Data Source Download URL File Format Coverage Update Frequency Notes
Primary Roads US Census Bureau https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile National, State Annual Major highways and roads
All Roads US Census Bureau https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile National, State, County Annual Complete road network

9.5 Major Highway Systems and Interstate Corridors

Highway System Data Source Download URL File Format Coverage Update Frequency Specific Routes Included
Interstate Highway System US Census Bureau TIGER https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile National Annual I-95, I-10, I-5, I-75, I-80, I-40, I-35, I-25, I-70, I-90, etc.
US Highway System US Census Bureau TIGER https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile National Annual US-1, US-50, US-101, US-Route 66 (historic), etc.
Primary Roads (Interstate + US) US Census Bureau TIGER https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile National Annual All Interstate and US highways combined
National Highway System (NHS) FHWA https://www.fhwa.dot.gov/planning/national_highway_system/ Shapefile, GeoJSON National Annual Congressionally designated strategic highways

9.6 Major Interstate Highways (Detailed Reference)

9.6.1 East-West Interstate Corridors

Route Description States Traversed Length (Miles) Key Cities Connected Healthcare Relevance
I-10 Southern transcontinental CA, AZ, NM, TX, LA, MS, AL, FL 2,460 Los Angeles - Houston - New Orleans - Jacksonville Major Sun Belt corridor
I-20 Southern route TX, LA, MS, AL, GA, SC 1,535 Dallas - Atlanta - Columbia Connects major Southern medical centers
I-30 Arkansas-Texas TX, AR 367 Dallas - Little Rock Links Dallas medical district
I-40 Central transcontinental CA, AZ, NM, TX, OK, AR, TN, NC 2,555 Los Angeles - Nashville - Raleigh Major cross-country medical corridor
I-70 Central route UT, CO, KS, MO, IL, IN, OH, WV, PA, MD 2,151 Denver - Kansas City - St. Louis - Columbus Mountain West to Mid-Atlantic
I-80 Northern transcontinental CA, NV, UT, WY, NE, IA, IL, IN, OH, PA, NJ, NY 2,899 San Francisco - Chicago - New York Major Northern medical corridor
I-90 Northern border route WA, ID, MT, WY, SD, MN, WI, IL, IN, OH, PA, NY, MA 3,020 Seattle - Chicago - Boston Longest interstate, connects major Northern cities

9.6.2 North-South Interstate Corridors

Route Description States Traversed Length (Miles) Key Cities Connected Healthcare Relevance
I-5 West Coast CA, OR, WA 1,381 San Diego - Los Angeles - San Francisco - Portland - Seattle Pacific Coast medical corridor
I-15 Southwestern CA, NV, AZ, UT, ID, MT 1,433 San Diego - Las Vegas - Salt Lake City Desert Southwest access
I-25 Mountain corridor NM, CO, WY 1,062 Albuquerque - Denver - Cheyenne Front Range medical access
I-35 Central Plains TX, OK, KS, MO, IA, MN 1,568 Laredo - San Antonio - Austin - Dallas - Minneapolis Texas to Twin Cities corridor
I-65 South Central AL, TN, KY, IN 887 Mobile - Birmingham - Nashville - Louisville - Indianapolis Connects Southern to Midwest medical centers
I-75 Eastern corridor FL, GA, TN, KY, OH, MI 1,786 Miami - Atlanta - Cincinnati - Detroit Major Eastern medical corridor
I-85 Southeastern AL, GA, SC, NC, VA 666 Montgomery - Atlanta - Charlotte - Richmond Southeast medical corridor
I-95 East Coast ME, NH, MA, RI, CT, NY, NJ, PA, DE, MD, DC, VA, NC, SC, GA, FL 1,908 Miami - Savannah - Richmond - Washington - Philadelphia - New York - Boston Primary East Coast medical corridor

9.7 Alternative Transportation Network Data Sources

Data Source Download URL File Format Coverage Cost Licensing Quality Level
OpenStreetMap (OSM) https://www.openstreetmap.org/ Various Global Free Open Data License High, community maintained
HERE Maps Road Data https://developer.here.com/ API/Download Global Commercial HERE License Very High, commercial grade
TomTom Road Network https://developer.tomtom.com/ API Global Commercial TomTom License Very High, commercial grade

9.8 Highway-Specific R Package Resources

Package Function Data Included Usage Example Notes
tigris primary_roads(), primary_secondary_roads() Census TIGER roads tigris::primary_roads(cb = TRUE) Automatically downloads highways
osmdata opq(), add_osm_feature() OpenStreetMap data osmdata::opq("USA") %>% add_osm_feature("highway", "motorway") Query specific highway types
tidytransit Transit and road network analysis GTFS + road networks Various Public transportation integration
dodgr Distance calculations on road networks OSM road networks Network analysis Route optimization

9.9 Highway Data Download Examples

9.9.1 Interstate Highways via tigris

# Download all primary roads (includes Interstates)
primary_roads <- tigris::primary_roads(cb = TRUE)

# Filter for Interstate highways only
interstates <- primary_roads %>%
  filter(stringr::str_detect(FULLNAME, "^I "))

# Specific Interstate (example: I-25)
i25 <- primary_roads %>%
  filter(stringr::str_detect(FULLNAME, "I 25"))

9.9.2 Major Highways via OpenStreetMap

library(osmdata)

# Download Interstate highways
interstates_osm <- opq("United States") %>%
  add_osm_feature(key = "highway", value = "motorway") %>%
  add_osm_feature(key = "ref", value = c("I 95", "I 25", "I 70")) %>%
  osmdata_sf()

# Download US highways  
us_highways <- opq("United States") %>%
  add_osm_feature(key = "highway", value = "trunk") %>%
  add_osm_feature(key = "ref", value = c("US 50", "US 101")) %>%
  osmdata_sf()

9.9.3 State-Specific Highway Downloads

# Colorado highways (example for I-25, I-70, I-76)
co_roads <- tigris::primary_secondary_roads(state = "CO", cb = TRUE)

co_interstates <- co_roads %>%
  filter(stringr::str_detect(FULLNAME, "^I ")) %>%
  filter(stringr::str_detect(FULLNAME, "I 25|I 70|I 76"))

9.10 Highway Analysis Applications for Healthcare Accessibility

9.10.1 Interstate Corridor Analysis

  • I-95 Corridor: East Coast medical referral patterns
  • I-10 Corridor: Southern transcontinental access
  • I-25 Front Range: Denver-Colorado Springs-Albuquerque medical corridor
  • I-70 Mountain Corridor: Mountain West healthcare access

9.10.2 Highway Buffer Analysis

# Create buffers around major highways for accessibility analysis
highway_buffers <- interstates %>%
  st_buffer(dist = units::set_units(50, "miles"))  # 50-mile highway corridor

9.11 Cancer Care and Specialty Medical Areas

Geographic Unit Data Source Download URL File Format Coverage Update Frequency Notes
NCI-Designated Cancer Centers National Cancer Institute https://www.cancer.gov/research/infrastructure/cancer-centers/find Point data (geocode addresses) National As designated Comprehensive cancer centers
CoC-Accredited Cancer Programs Commission on Cancer https://www.facs.org/quality-programs/cancer-programs/commission-cancer/coc-accredited-programs/ Point data (geocode addresses) National Annual Accredited cancer programs
NCCN Member Institutions NCCN https://www.nccn.org/about/member-institutions Point data (geocode addresses) National As membership changes Leading cancer centers

9.12 American Community Survey Geographic Summary Levels

Geographic Unit Summary Level Code Download URL File Format Coverage Update Frequency Notes
Nation 010 https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile US Annual National boundary
Regions 020 https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile US Annual 4 Census regions
Divisions 030 https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile US Annual 9 Census divisions
States 040 https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile US Annual 50 states + DC
Counties 050 https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile US Annual ~3,100 counties
County Subdivisions 060 https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile US Annual Townships, boroughs, etc.
Census Tracts 140 https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile US Annual ~74,000 tracts
Block Groups 150 https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Shapefile US Annual ~220,000 block groups

9.13 Special R Package Resources for Geographic Data

Package Function Data Included Usage Notes
tigris states(), counties(), tracts(), block_groups() All Census boundaries tigris::states(cb = TRUE) Automatically downloads and caches
tidycensus get_acs(..., geometry = TRUE) Census data + boundaries get_acs(geography = "tract", geometry = TRUE) Data and geography combined
sf Spatial data processing - st_read("shapefile.shp") Core spatial analysis
USAboundaries Historical US boundaries Counties, states (1629-2000) us_states(map_date = "2000-01-01") Historical analysis
spData Spatial datasets Various example datasets data(us_states) Teaching and examples

9.14 File Download Examples and R Code

9.14.1 Census Boundaries via tigris Package

# Download state boundaries
states_sf <- tigris::states(cb = TRUE, resolution = "20m")

# Download census tracts for specific state  
tracts_sf <- tigris::tracts(state = "CO", cb = TRUE)

# Download block groups for specific county
bg_sf <- tigris::block_groups(state = "CO", county = "001", cb = TRUE)

9.14.2 HRSA Data Download

# Download HPSA data
hpsa_url <- "https://data.hrsa.gov/data/download/hrsa-hpsa-primary-care-shortage-areas.csv"
hpsa_data <- readr::read_csv(hpsa_url)

9.15 Data Vintage and Compatibility Notes

Geographic Unit 2010 Census Vintage 2020 Census Vintage Compatibility Issues
Census Tracts ~74,000 tracts ~84,000 tracts Tract boundaries changed significantly
Block Groups ~217,000 BGs ~242,000 BGs Many boundary changes
Counties 3,143 counties 3,143 counties Stable boundaries
States 50 + DC 50 + DC No changes
ZCTAs 2010 ZIP patterns 2020 ZIP patterns Significant changes in suburban areas

10 License

MIT (allows commercial and academic use with attribution)

11 🤝 Contributing

We welcome contributions!

12 📜 Citation

If you use this work in your research, please cite:

@misc{muffly2025gynoncaccess,
  title={Gynecologic Oncology Accessibility Project: Nationwide Analysis of Access to OBGYN Subspecialists Using Drive Time Isochrones (2013-2023)},
  author={Muffly, Tyler},
  year={2025},
  url={https://github.com/mufflyt/isochrones},
  note={Version 2.0.0}
}

13 Contact

Primary Contact: Tyler Muffly, MD
Email:
GitHub: https://github.com/mufflyt/isochrones

14 Project Maintenance Schedule

  • Annual Updates: New NPPES data release (typically March)
  • API Monitoring: Monthly checks of rate limits and costs
  • Data Validation: Biannual review of provider lists
  • Code Updates: As needed for R package changes

15

LS0tCnRpdGxlOiAiR3luZWNvbG9naWMgT25jb2xvZ3kgQWNjZXNzaWJpbGl0eSBQcm9qZWN0IgpzdWJ0aXRsZTogIk5hdGlvbndpZGUgQW5hbHlzaXMgb2YgQWNjZXNzIHRvIE9CR1lOIFN1YnNwZWNpYWxpc3RzIFVzaW5nIERyaXZlIFRpbWUgSXNvY2hyb25lcyAoMjAxMy0yMDIzKSIKYXV0aG9yOiAKICAtIG5hbWU6ICJUeWxlciBNdWZmbHksIE1EIgogICAgYWZmaWxpYXRpb246ICJEZXBhcnRtZW50IG9mIE9ic3RldHJpY3MgYW5kIEd5bmVjb2xvZ3kiCiAgICBlbWFpbDogInR5bGVyLm11ZmZseUBkaGhhLm9yZyIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpkZXNjcmlwdGlvbjogfAogIFRoaXMgcHJvamVjdCBhbmFseXplcyBuYXRpb253aWRlIGFjY2VzcyB0byBneW5lY29sb2dpYyBvbmNvbG9naXN0cyBhbmQgb3RoZXIgCiAgT0JHWU4gc3Vic3BlY2lhbGlzdHMgdXNpbmcgZHJpdmUgdGltZSBpc29jaHJvbmVzLCBkZW1vZ3JhcGhpYyBkYXRhLCBhbmQgCiAgZ2Vvc3BhdGlhbCBhbmFseXNpcy4gVGhlIGFuYWx5c2lzIGV4YW1pbmVzIGhvdyBhY2Nlc3NpYmlsaXR5IHZhcmllcyBhY3Jvc3MgCiAgZGlmZmVyZW50IGdlb2dyYXBoaWMgYXJlYXMsIGRlbW9ncmFwaGljIGdyb3VwcywgYW5kIHRpbWUgcGVyaW9kcyAoMjAxMy0yMDIzKS4Ka2V5d29yZHM6IAogIC0gImd5bmVjb2xvZ2ljIG9uY29sb2d5IgogIC0gImhlYWx0aGNhcmUgYWNjZXNzaWJpbGl0eSIgCiAgLSAic3BhdGlhbCBhbmFseXNpcyIKICAtICJpc29jaHJvbmVzIgogIC0gImhlYWx0aCBkaXNwYXJpdGllcyIKICAtICJnZW9ncmFwaGljIGluZm9ybWF0aW9uIHN5c3RlbXMiCnZlcnNpb246ICIxLjAuMCIKbGljZW5zZTogIk1JVCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiAKICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRoZW1lOiAiZmxhdGx5IgogICAgaGlnaGxpZ2h0OiAidGFuZ28iCiAgICBmaWdfd2lkdGg6IDEwCiAgICBmaWdfaGVpZ2h0OiA4CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiAic2hvdyIKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGRldjogInBuZyIKICAgIGRwaTogMzAwCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogICAga2VlcF9tZDogdHJ1ZQogICAgcGFuZG9jX2FyZ3M6IFsiLS13cmFwPXByZXNlcnZlIl0KbGluay1jaXRhdGlvbnM6IHRydWUKYWx3YXlzX2FsbG93X2h0bWw6IHRydWUKZWRpdG9yX29wdGlvbnM6CiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKICBtYXJrZG93bjoKICAgIHdyYXA6IDgwCiAgICBjYW5vbmljYWw6IHRydWUKLS0tCgo8IS0tIFJFQURNRS5tZCBpcyBnZW5lcmF0ZWQgZnJvbSBSRUFETUUuUm1kLiBQbGVhc2UgZWRpdCB0aGF0IGZpbGUgLS0+Cgo8IS0tIEJhZGdlcyBTZWN0aW9uIC0tPgoKWyFbUHJvamVjdApTdGF0dXNdKGh0dHBzOi8vaW1nLnNoaWVsZHMuaW8vYmFkZ2UvUHJvamVjdCUyMFN0YXR1cy1BY3RpdmUtYnJpZ2h0Z3JlZW4uc3ZnKV0oaHR0cHM6Ly9naXRodWIuY29tL211ZmZseXQvaXNvY2hyb25lcykKWyFbUgpWZXJzaW9uXShodHRwczovL2ltZy5zaGllbGRzLmlvL2JhZGdlL1ItJUUyJTg5JUE1JTIwNC4wLjAtYmx1ZS5zdmcpXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy8pClshW0xpY2Vuc2U6Ck1JVF0oaHR0cHM6Ly9pbWcuc2hpZWxkcy5pby9iYWRnZS9MaWNlbnNlLU1JVC15ZWxsb3cuc3ZnKV0oaHR0cHM6Ly9vcGVuc291cmNlLm9yZy9saWNlbnNlcy9NSVQpCgpgYGB7ciwgaW5jbHVkZSA9IEZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgY29tbWVudCA9ICIjPiIsCiAgY29sbGFwc2UgPSBUUlVFLAogIGVjaG8gPSBUUlVFLCAgICAgICAgICAjIFNob3cgY29kZSBpbiBvdXRwdXQKICB3YXJuaW5nID0gRkFMU0UsICAgICAgIyBObyB3YXJuaW5ncwogIG1lc3NhZ2UgPSBUUlVFLCAgICAgICAjIFNob3cgbWVzc2FnZXMKICBlcnJvciA9IEZBTFNFLCAgICAgICAgIyBEb24ndCBzdG9wIG9uIGVycm9ycwogIGZpZy53aWR0aCA9IDgsICAgICAgICAjIERlZmF1bHQgZmlndXJlIHdpZHRoCiAgZmlnLmhlaWdodCA9IDYsICAgICAgICMgRGVmYXVsdCBmaWd1cmUgaGVpZ2h0CiAgZmlnLmFsaWduID0gImNlbnRlciIsICMgQ2VudGVyIGZpZ3VyZXMKICBkcGkgPSAzMDAsICAgICAgICAgICAgIyBIaWdoZXIgcmVzb2x1dGlvbiBmaWd1cmVzCiAgb3V0LndpZHRoID0gIjg1JSIsICAgICMgQ29udHJvbCBkaXNwbGF5IHNpemUKICBjYWNoZSA9IEZBTFNFLCAgICAgICAgIyBDYWNoZSByZXN1bHRzPyAoVFJVRSBmb3IgbGFyZ2UgY29tcHV0YXRpb25zKQogIGNvbW1lbnQgPSAiIz4iLCAgICAgICAjIENvbW1lbnQgY2hhcmFjdGVyIGZvciBvdXRwdXQKICB0aWR5ID0gRkFMU0UsICAgICAgICAgIyBEb24ndCByZWZvcm1hdCBjb2RlCiAgZGV2ID0gInBuZyIsICAgICAgICAgICAjIE91dHB1dCBkZXZpY2UgZm9yIHBsb3RzCiAgaW5jbHVkZSA9IEZBTFNFCikKCiMgQ2hlY2sgaWYgcmVxdWlyZWQgZGlyZWN0b3JpZXMgZXhpc3QKaWYgKCFkaXIuZXhpc3RzKCJmaWd1cmVzIikpIGRpci5jcmVhdGUoImZpZ3VyZXMiLCByZWN1cnNpdmUgPSBUUlVFKQppZiAoIWRpci5leGlzdHMoImRhdGEiKSkgZGlyLmNyZWF0ZSgiZGF0YSIsIHJlY3Vyc2l2ZSA9IFRSVUUpCmlmICghZGlyLmV4aXN0cygiYXNzZXRzIikpIGRpci5jcmVhdGUoImFzc2V0cyIsIHJlY3Vyc2l2ZSA9IFRSVUUpCmBgYAoKYGBge3IgbG9hZC1wYWNrYWdlcywgaW5jbHVkZT1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBDb3JlIGRhdGEgbWFuaXB1bGF0aW9uIGFuZCBhbmFseXNpcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsb2dnZXIpCmxpYnJhcnkoYXNzZXJ0dGhhdCkKbGlicmFyeShnbHVlKQoKIyBHZW9zcGF0aWFsIGFuYWx5c2lzCmxpYnJhcnkoc2YpCmxpYnJhcnkodGlncmlzKQoKIyBWaXN1YWxpemF0aW9uCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkodmlyaWRpcykKbGlicmFyeShnZ2hpZ2hsaWdodCkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoZ2d0ZXh0KQpsaWJyYXJ5KGdncmVwZWwpCgojIFRhYmxlcyBhbmQgcmVwb3J0aW5nCmxpYnJhcnkoRFQpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoa2FibGVFeHRyYSkKCiMgU3RhdGlzdGljYWwgYW5hbHlzaXMKbGlicmFyeShzdGF0cykKbGlicmFyeShicm9vbSkKCiMgU2V0IGxvZ2dlciB0aHJlc2hvbGQKbG9nZ2VyOjpsb2dfdGhyZXNob2xkKGxvZ2dlcjo6SU5GTykKCiMgU2V0IGdncGxvdDIgdGhlbWUKdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpKQpgYGAKCiMgQUJTVFJBQ1QKCioqT2JqZWN0aXZlOioqIFRvIHF1YW50aWZ5IGNoYW5nZXMgaW4gYWNjZXNzaWJpbGl0eSB0byBneW5lY29sb2dpYyBvbmNvbG9neSBjYXJlCmFjcm9zcyB0aGUgVW5pdGVkIFN0YXRlcyBmcm9tIDIwMTMtMjAyMiwgd2l0aCBwYXJ0aWN1bGFyIGF0dGVudGlvbiB0bwp1cmJhbi1ydXJhbCBkaXNwYXJpdGllcywgZHJpdmUgdGltZSB0aHJlc2hvbGRzLCBhbmQgcmFjaWFsL2V0aG5pYyBkaWZmZXJlbmNlcyBpbgphY2Nlc3MuCgoqKk1ldGhvZHM6KiogV2UgYW5hbHl6ZWQgZ3luZWNvbG9naWMgb25jb2xvZ2lzdCBwcmFjdGljZSBsb2NhdGlvbnMgY29tYmluZWQgd2l0aApVLlMuIENlbnN1cyBkYXRhIGZyb20gMjAxMy0yMDIyLiBGb3VyIGRyaXZlIHRpbWUgdGhyZXNob2xkcyAoMzAsIDYwLCAxMjAsIGFuZAoxODAgbWludXRlcykgd2VyZSBjYWxjdWxhdGVkIGZvciBjZW5zdXMgdHJhY3RzIHRvIGFzc2VzcyBhY2Nlc3NpYmlsaXR5LgpQb3B1bGF0aW9uLXdlaWdodGVkIG1lYW4gYWNjZXNzIHJhdGVzIHdlcmUgZGV0ZXJtaW5lZCBmb3IgdXJiYW4gYW5kIHJ1cmFsCnBvcHVsYXRpb25zIGFuZCBzdHJhdGlmaWVkIGJ5IHJhY2UvZXRobmljaXR5LiBMaW5lYXIgcmVncmVzc2lvbiBtb2RlbHMgd2l0aAp0ZW1wb3JhbCB0cmVuZCBhbmFseXNpcyB3ZXJlIGVtcGxveWVkIHRvIGFzc2VzcyBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2Ugb2YKY2hhbmdlcyBvdmVyIHRpbWUuCgoqKlJlc3VsdHM6KiogQWNjZXNzaWJpbGl0eSB0byBneW5lY29sb2dpYyBvbmNvbG9naXN0cyBkZWNsaW5lZCBzaWduaWZpY2FudGx5CmFjcm9zcyBhbGwgdGltZSB0aHJlc2hvbGRzIG92ZXIgdGhlIDEwLXllYXIgcGVyaW9kLiBUaGUgbW9zdCBwcm9ub3VuY2VkIGRlY3JlYXNlCm9jY3VycmVkIGluIDMwLW1pbnV0ZSBhY2Nlc3NpYmlsaXR5ICgtMjMuNiUsIHBcPDAuMDAxKSwgZm9sbG93ZWQgYnkgNjAtbWludXRlCigtMTYuOCUsIHBcPDAuMDAxKSwgMTIwLW1pbnV0ZSAoLTguNSUsIHBcPDAuMDEpLCBhbmQgMTgwLW1pbnV0ZSB0aHJlc2hvbGRzCigtMi44JSwgcFw8MC4wNSkuIEFwcHJveGltYXRlbHkgMjc3LjMgbWlsbGlvbiB3b21lbiBsaXZlZCBpbiBhcmVhcyBiZXlvbmQKNjAtbWludXRlIGRyaXZlIHRpbWUgdG8gYSBneW5lY29sb2dpYyBvbmNvbG9naXN0IGJ5IDIwMjIsIGFuIGluY3JlYXNlIG9mIDI2LjgKbWlsbGlvbiBmcm9tIDIwMTMuIFVyYmFuLXJ1cmFsIGRpc3Bhcml0aWVzIHdlcmUgc3Vic3RhbnRpYWwsIHdpdGggb25seSAxMC4yJSBvZgpydXJhbCB3b21lbiBoYXZpbmcgMzAtbWludXRlIGFjY2VzcyBjb21wYXJlZCB0byA0NC4xJSBvZiB1cmJhbiB3b21lbiAocFw8MC4wMDEpLgpSYWNpYWwvZXRobmljIGRpc3Bhcml0aWVzIHdlcmUgZXF1YWxseSBwcm9ub3VuY2VkLCB3aXRoIEFzaWFuIHdvbWVuIGhhdmluZyB0aGUKaGlnaGVzdCBhY2Nlc3MgcmF0ZXMgKDg2LjUlKSwgZm9sbG93ZWQgYnkgQmxhY2sgd29tZW4gKDc3LjIlKSwgTmF0aXZlIEhhd2FpaWFuCmFuZCBQYWNpZmljIElzbGFuZGVyIHdvbWVuICg3NS4zJSksIGFuZCBXaGl0ZSB3b21lbiAoNjYuOCUpLCB3aGlsZSBBbWVyaWNhbgpJbmRpYW4gYW5kIEFsYXNrYSBOYXRpdmUgd29tZW4gaGFkIGRyYW1hdGljYWxseSBsb3dlciBhY2Nlc3MgKDUwLjklLCBwXDwwLjAwMSkuCgoqKkNvbmNsdXNpb25zOioqIEFjY2VzcyB0byBneW5lY29sb2dpYyBvbmNvbG9neSBjYXJlIGhhcyBzaWduaWZpY2FudGx5CmRpbWluaXNoZWQgb3ZlciB0aGUgcGFzdCBkZWNhZGUsIHdpdGggc2hvcnRlciBkcml2ZSB0aW1lIHRocmVzaG9sZHMgZXhwZXJpZW5jaW5nCnRoZSBzdGVlcGVzdCBkZWNsaW5lcy4gR2VvZ3JhcGhpYyBjb25jZW50cmF0aW9uIG9mIGd5bmVjb2xvZ2ljIG9uY29sb2dpc3RzIGluCnVyYmFuIGFjYWRlbWljIGNlbnRlcnMgaGFzIGNyZWF0ZWQgc3Vic3RhbnRpYWwgYWNjZXNzIGJhcnJpZXJzLCBwYXJ0aWN1bGFybHkgZm9yCnJ1cmFsIGNvbW11bml0aWVzLiBXaXRob3V0IGludGVydmVudGlvbiwgdGhlc2UgdHJlbmRzIHdpbGwgY29udGludWUgdG8KZXhhY2VyYmF0ZSBjYW5jZXIgb3V0Y29tZSBkaXNwYXJpdGllcyBmb3IgcnVyYWwgYW5kIG1pbm9yaXR5IHBvcHVsYXRpb25zLgpTdHJhdGVnaWMgaW5pdGlhdGl2ZXMgaW5jbHVkaW5nIG91dHJlYWNoIGNsaW5pY3MsIHRlbGVtZWRpY2luZSBuZXR3b3JrcywgYW5kCnRhcmdldGVkIHRyYWluaW5nIHByb2dyYW1zIGFyZSBuZWVkZWQgdG8gYWRkcmVzcyB0aGUgbWFsZGlzdHJpYnV0aW9uIG9mCmd5bmVjb2xvZ2ljIG9uY29sb2dpc3RzLgoKIyMgWWVhcmx5IE1hcHMgQ29tYmluZWQKCiFbWWVhcmx5IE1hcHMgQ29tYmluZWRdKGZpZ3VyZXMvZmFjZXRlZF95ZWFyX3Bsb3RzL3llYXJseV9tYXBzX2NvbWJpbmVkLnBuZykKCiMg8J+UrCBSZXNlYXJjaCBPYmplY3RpdmVzCgotICAgKipQcmltYXJ5Kio6IFF1YW50aWZ5IGdlb2dyYXBoaWMgYWNjZXNzaWJpbGl0eSB0byBneW5lY29sb2dpYyBvbmNvbG9neQogICAgc3BlY2lhbGlzdHMgbmF0aW9ud2lkZQotICAgKipTZWNvbmRhcnkqKjogQW5hbHl6ZSBkZW1vZ3JhcGhpYyBkaXNwYXJpdGllcyBpbiBzdWJzcGVjaWFsaXN0IGFjY2VzcwotICAgKipUZXJ0aWFyeSoqOiBFeGFtaW5lIHRlbXBvcmFsIHRyZW5kcyBpbiBoZWFsdGhjYXJlIHdvcmtmb3JjZSBkaXN0cmlidXRpb24KLSAgICoqUXVhdGVybmFyeSoqOiBJZGVudGlmeSB1bmRlcnNlcnZlZCBwb3B1bGF0aW9ucyBhbmQgZ2VvZ3JhcGhpYyBhcmVhcwoKIyDwn46vIFByb2plY3QgT3ZlcnZpZXcgJiBDb25jZXB0dWFsIEZyYW1ld29yawoKVGhpcyBwcm9qZWN0IGFuYWx5emVzIG5hdGlvbndpZGUgYWNjZXNzIHRvIGd5bmVjb2xvZ2ljIG9uY29sb2dpc3RzIGFuZCBvdGhlcgpPQkdZTiBzdWJzcGVjaWFsaXN0cyB1c2luZyBkcml2ZSB0aW1lIGlzb2Nocm9uZXMsIGRlbW9ncmFwaGljIGRhdGEsIGFuZApnZW9zcGF0aWFsIGFuYWx5c2lzLiBUaGUgYW5hbHlzaXMgZXhhbWluZXMgaG93IGFjY2Vzc2liaWxpdHkgdmFyaWVzIGFjcm9zcwpkaWZmZXJlbnQgZ2VvZ3JhcGhpYyBhcmVhcywgZGVtb2dyYXBoaWMgZ3JvdXBzLCBhbmQgdGltZSBwZXJpb2RzICgyMDEzLTIwMjMpLgoKVXNpbmcgdGhlIEhFUkUgTWFwcyBBUEkgYW5kIGNlbnN1cyBkYXRhLCB3ZSBjYWxjdWxhdGUgZHJpdmUgdGltZSBpc29jaHJvbmVzCmFyb3VuZCBneW5lY29sb2dpYyBvbmNvbG9naXN0cycgbG9jYXRpb25zIGFuZCBhbmFseXplIHRoZSBkZW1vZ3JhcGhpY3Mgb2YKcG9wdWxhdGlvbnMgd2l0aGluIGVhY2ggZHJpdmUgdGltZSB0aHJlc2hvbGQuIFRoZSBwcm9qZWN0IGV4YW1pbmVzIGNoYW5nZXMgaW4KYWNjZXNzaWJpbGl0eSBvdmVyIHRpbWUgYW5kIHJldGlyZW1lbnQgcGF0dGVybnMgYW1vbmcgc3BlY2lhbGlzdHMuCgojIyBXaGF0IEFyZSBJc29jaHJvbmVzPwoKIyMgSW50ZXJhY3RpdmUgSXNvY2hyb25lIE1hcAoKPGlmcmFtZSBzcmM9ImZpZ3VyZXMvaXNvY2hyb25lX21hcF8yMDI0MDIwOF8xODExMTAuaHRtbCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iNjAwcHgiPgoKPC9pZnJhbWU+CgoqKklzb2Nocm9uZXMqKiBhcmUgZ2VvZ3JhcGhpYyBib3VuZGFyaWVzIHNob3dpbmcgYXJlYXMgcmVhY2hhYmxlIHdpdGhpbiBzcGVjaWZpYwp0cmF2ZWwgdGltZXMgZnJvbSBhIHBvaW50LiBUaGluayBvZiB0aGVtIGFzICJ0aW1lIHpvbmVzIiBhcm91bmQgZWFjaCBkb2N0b3IncwpvZmZpY2UgLSB0aGUgMzAtbWludXRlIGlzb2Nocm9uZSBpbmNsdWRlcyBhbGwgcGxhY2VzIHlvdSBjYW4gZHJpdmUgdG8gd2l0aGluIDMwCm1pbnV0ZXMuCgoqKldoeSBUaGlzIE1hdHRlcnMgZm9yIEhlYWx0aGNhcmUgQWNjZXNzOioqIC0gKipQYXRpZW50IHBlcnNwZWN0aXZlKio6IEhvdyBmYXIKZG8gSSBoYXZlIHRvIHRyYXZlbCBmb3Igc3BlY2lhbGl6ZWQgY2FyZT8gLSAqKlBvbGljeSBwZXJzcGVjdGl2ZSoqOiBXaGljaApwb3B1bGF0aW9ucyBhcmUgdW5kZXJzZXJ2ZWQ/IC0gKipQbGFubmluZyBwZXJzcGVjdGl2ZSoqOiBXaGVyZSBzaG91bGQgbmV3CnByb3ZpZGVycyBwcmFjdGljZT8KCiMjIEVuaGFuY2VkIENlbnN1cyBUcmFjdCBNYXAKCiFbRW5oYW5jZWQgQ2Vuc3VzIFRyYWN0IE1hcF0oZmlndXJlcy9lbmhhbmNlZF9jZW5zdXNfdHJhY3RfbWFwLnBuZykKCiMjIEtleSBNZXRob2RvbG9naWNhbCBEZWNpc2lvbnMgJiBSYXRpb25hbGUKCiMjIyBEcml2ZSBUaW1lIFRocmVzaG9sZHMgKDMwLCA2MCwgMTIwLCAxODAgbWludXRlcykKCi0gICAqKjMwIG1pbnV0ZXMqKjogTG9jYWwvcmVnaW9uYWwgYWNjZXNzIC0gbW9zdCBwYXRpZW50cyB3aWxsaW5nIHRvIHRyYXZlbAotICAgKio2MCBtaW51dGVzKio6IEV4dGVuZGVkIGxvY2FsIGFjY2VzcyAtIHJlYXNvbmFibGUgZm9yIHNwZWNpYWx0eSBjYXJlCi0gICAqKjEyMCBtaW51dGVzKio6IFJlZ2lvbmFsIGFjY2VzcyAtIGFjY2VwdGFibGUgZm9yIGhpZ2hseSBzcGVjaWFsaXplZCBjYXJlCi0gICAqKjE4MCBtaW51dGVzKio6IE1heGltdW0gcmVhc29uYWJsZSBhY2Nlc3MgLSBiZXlvbmQgdGhpcyBpcyBlZmZlY3RpdmVseQogICAgaW5hY2Nlc3NpYmxlCgojIyMgUmVmZXJlbmNlIFRpbWU6IFRoaXJkIEZyaWRheSBvZiBPY3RvYmVyLCA5OjAwIEFNCgotICAgKipSYXRpb25hbGUqKjogU3RhbmRhcmRpemVkIGFjcm9zcyBhbGwgeWVhcnMgZm9yIGNvbnNpc3RlbmN5Ci0gICAqKkNvbnNpZGVyYXRpb25zKio6IFJ1c2ggaG91ciB2cy4gb2ZmLXBlYWs7IEZyaWRheSByZXByZXNlbnRzIHR5cGljYWwKICAgIHdlZWtkYXkKLSAgICoqTGltaXRhdGlvbioqOiBEb2Vzbid0IGFjY291bnQgZm9yIHNlYXNvbmFsIHZhcmlhdGlvbnMgb3Igd2Vla2VuZCBhY2Nlc3MKCiMjIyBHZW9ncmFwaGljIFJlc29sdXRpb246IENlbnN1cyBCbG9jayBHcm91cHMgdnMuIENvdW50aWVzCgotICAgKipDaG9pY2UqKjogVXNlZCBjZW5zdXMgYmxvY2sgZ3JvdXBzIChzbWFsbGVyIGdlb2dyYXBoaWMgdW5pdHMpCi0gICAqKkFkdmFudGFnZSoqOiBNb3JlIHByZWNpc2UgcG9wdWxhdGlvbiBlc3RpbWF0ZXMsIGNhcHR1cmVzIHVyYmFuL3J1cmFsCiAgICBkaWZmZXJlbmNlcwotICAgKipUcmFkZS1vZmYqKjogSW5jcmVhc2VkIGNvbXB1dGF0aW9uYWwgY29tcGxleGl0eSB2cy4gbW9yZSBhY2N1cmF0ZSByZXN1bHRzCgojIyBTdWJzcGVjaWFsaXN0IENhdGVnb3JpZXMgQW5hbHl6ZWQKCiMjIyBQcmltYXJ5IEZvY3VzOiBHeW5lY29sb2dpYyBPbmNvbG9neQoKLSAgICoqRGVmaW5pdGlvbioqOiBQaHlzaWNpYW5zIHNwZWNpYWxpemluZyBpbiBjYW5jZXJzIG9mIHRoZSBmZW1hbGUKICAgIHJlcHJvZHVjdGl2ZSBzeXN0ZW0KLSAgICoqVGF4b25vbXkgQ29kZSoqOiAyMDdWWDAyMDFYCi0gICAqKlR5cGljYWwgVHJhaW5pbmcqKjogMyBvciA0LXllYXIgZmVsbG93c2hpcCBhZnRlciBPQkdZTiByZXNpZGVuY3kKLSAgICoqUmFyaXR5Kio6IEhpZ2hseSBzcGVjaWFsaXplZCAtIGxpbWl0ZWQgbnVtYmVyIG5hdGlvbndpZGUKCiMjIyBTZWNvbmRhcnkgQW5hbHlzaXMgU3Vic3BlY2lhbHRpZXM6CgoxLiAgKipGZW1hbGUgUGVsdmljIE1lZGljaW5lL1Vyb2d5bmVjb2xvZ3kgKDIwN1ZGMDA0MFgpKioKICAgIC0gICBQZWx2aWMgZmxvb3IgZGlzb3JkZXJzLCBpbmNvbnRpbmVuY2UKICAgIC0gICBSZWNlbnQgbmFtZSBjaGFuZ2UgZnJvbSBGUE1SUyB0byBVUlBTCjIuICAqKk1hdGVybmFsLUZldGFsIE1lZGljaW5lICgyMDdWTTAxMDFYKSoqCiAgICAtICAgSGlnaC1yaXNrIHByZWduYW5jeSBzcGVjaWFsaXN0cwogICAgLSAgIENyaXRpY2FsIGZvciBjb21wbGV4IG9ic3RldHJpYyBjYXJlCjMuICAqKlJlcHJvZHVjdGl2ZSBFbmRvY3Jpbm9sb2d5ICgyMDdWRTAxMDJYKSoqCiAgICAtICAgRmVydGlsaXR5IHNwZWNpYWxpc3RzCiAgICAtICAgSG9ybW9uZS1yZWxhdGVkIHJlcHJvZHVjdGl2ZSBkaXNvcmRlcnMKCiMjIyMgVGF4b25vbXkgQ29kZSBSZWZlcmVuY2UKCmBgYCByCm9iZ3luX3RheG9ub215X2NvZGVzIDwtIGMoCiAgIjIwN1YwMDAwMFgiLCAgICAjIE9ic3RldHJpY3MgJiBHeW5lY29sb2d5IChnZW5lcmFsKQogICIyMDdWWDAyMDFYIiwgICAgIyBHeW5lY29sb2dpYyBPbmNvbG9neSAoUFJJTUFSWSBGT0NVUykKICAiMjA3VkUwMTAyWCIsICAgICMgUmVwcm9kdWN0aXZlIEVuZG9jcmlub2xvZ3kgCiAgIjIwN1ZHMDQwMFgiLCAgICAjIEd5bmVjb2xvZ3kgKGdlbmVyYWwpCiAgIjIwN1ZNMDEwMVgiLCAgICAjIE1hdGVybmFsICYgRmV0YWwgTWVkaWNpbmUKICAiMjA3VkYwMDQwWCIsICAgICMgRmVtYWxlIFBlbHZpYyBNZWRpY2luZS9Vcm9neW5lY29sb2d5CiAgIjIwN1ZCMDAwMlgiLCAgICAjIEJhcmlhdHJpYyBNZWRpY2luZQogICIyMDdWQzAyMDBYIiwgICAgIyBDcml0aWNhbCBjYXJlIG1lZGljaW5lCiAgIjIwN1ZDMDMwMFgiLCAgICAjIENvbXBsZXggZmFtaWx5IHBsYW5uaW5nICAKICAiMjA3VkgwMDAyWCIsICAgICMgUGFsbGlhdGl2ZSBjYXJlCiAgIjIwN1ZYMDAwMFgiICAgICAjIE9ic3RldHJpY3Mgb25seQopCmBgYAoKIyMg8J+TgiBEZXRhaWxlZCBGaWxlIE9yZ2FuaXphdGlvbiAmIFB1cnBvc2UKCmBgYCAgICAgICAgIAppc29jaHJvbmVzLwrilJzilIDilIAg8J+TgSBkYXRhLyAgICAgICAgICAgICAgICAgICAgICAgICAgICMgUmF3IGFuZCBwcm9jZXNzZWQgZGF0YXNldHMK4pSCICAg4pSc4pSA4pSAIGRlbW9ncmFwaGljX2Rpc3Bhcml0aWVzX2FuYWx5c2lzLmNzdgrilIIgICDilJzilIDilIAgZGlmZmVyZW5jZV9pbl9kaWZmZXJlbmNlX2FuYWx5c2lzLmNzdgrilIIgICDilJzilIDilIAgZHVwbGljYXRleWVhcmFuZGZpbGwuY3N2CuKUgiAgIOKUnOKUgOKUgCBlbmRfaW5uZXJfam9pbl9wb3N0bWFzdGVyX2NsaW5pY2lhbl9kYXRhLmNzdgrilIIgICDilJzilIDilIAgZW5kX3Jlam9pbmVkX2dlb2NvZGVkX3VuaXF1ZV9hZGRyZXNzLmNzdgrilIIgICDilJzilIDilIAgZmlwcy1zdGF0ZXMuY3N2CuKUgiAgIOKUnOKUgOKUgCBoZWFsdGhjYXJlX2JlbmNobWFya19yZWZlcmVuY2VzLm1kCuKUgiAgIOKUnOKUgOKUgCBpbnRlcnNlY3QuY3N2CuKUgiAgIOKUnOKUgOKUgCBNZWRpY2FyZV9QYXJ0X0RfcGh5c2ljaWFuX3JldGlyZW1lbnRfYW5hbHlzaXMuY3N2CuKUgiAgIOKUnOKUgOKUgCBwaHlzaWNpYW5fY29tcGFyZV9kYXRhLmNzdgrilIIgICDilJzilIDilIAgcGh5c2ljaWFuX3JldGlyZW1lbnRfeWVhcnMuY3N2CuKUgiAgIOKUnOKUgOKUgCBwb3B1bGF0aW9uX3dlaWdodGVkX21lYW5zX3dpdGhfY2kuY3N2CuKUgiAgIOKUlOKUgOKUgCByYWNpYWxfZGVjYXlfY3VydmVzLnBuZwrilJzilIDilIAg8J+TgSBmaWd1cmVzLyAgICAgICAgICAgICAgICAgICAgICAgICMgR2VuZXJhdGVkIHZpc3VhbGl6YXRpb25zCuKUgiAgIOKUlOKUgOKUgCBbR2VuZXJhdGVkIHBsb3RzIGFuZCBtYXBzXQrilJzilIDilIAg8J+TgSBSLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBBbGwgUiBzY3JpcHRzIGFuZCBmdW5jdGlvbnMK4pSCICAg4pSCICAg8J+Rqe+4jyAqKipHT19hY2Nlc3NfYW5hbHlzaXNfY29kZS5SbWQqKiogICAgIyBNYWluIGFuYWx5c2lzIHJlcG9ydArilIIgICDilJzilIDilIAg8J+TiiBEYXRhIENvbGxlY3Rpb24gKEEtU2VyaWVzKQrilIIgICDilIIgICDilJzilIDilIAgQS1hYm1zLlIgICAgICAgICAgICAgICAgICAjIEJvYXJkIGNlcnRpZmljYXRpb24gc2NyYXBpbmcK4pSCICAg4pSCICAg4pSc4pSA4pSAIEEtZmFjaWxpdHlfYWZmaWxpYXRpb25fZG93bmxvYWQuUiAgIyBDTVMgZmFjaWxpdHkgZGF0YQrilIIgICDilIIgICDilJzilIDilIAgQS1NZWRpY2FyZV9wYXJ0X2RfcHJlc2NyaWJlcnNfZGF0YV9kb3dubG9hZC5SCuKUgiAgIOKUgiAgIOKUnOKUgOKUgCBBLU5QSV9kZWFjdGl2YXRpb25fZG93bmxvYWQuUiAgICAgIyBQcm92aWRlciBkZWFjdGl2YXRpb24K4pSCICAg4pSCICAg4pSc4pSA4pSAIEEtbnBwZXNfZG93bmxvYWQuUiAgICAgICAgIyBIaXN0b3JpY2FsIE5QUEVTIGZyb20gTkJFUgrilIIgICDilIIgICDilJzilIDilIAgQS1vcGVuX3BheW1lbnRzX2Rvd25sb2FkLlIgICAgICAgICMgU3Vuc2hpbmUgQWN0IGRhdGEK4pSCICAg4pSCICAg4pSU4pSA4pSAIEEtcGh5c2ljaWFuX2NvbXBhcmVfZGF0YV9kb3dubG9hZC5SCuKUgiAgIOKUnOKUgOKUgCDwn5OLIERhdGEgUmVhZCBJbiAoQi1TZXJpZXMpCuKUgiAgIOKUgiAgIOKUnOKUgOKUgCBCLU1lZGljYXJlX3BhcnRfZF9wcmVzY3JpYmVyc19yZWFkX2luLlIgICAjIFJlYWQgaW4gZGF0YQrilIIgICDilIIgICDilJzilIDilIAgQi1OUElfZGVhY3RpdmF0aW9uLlIgICAgICAgICAgICAgICAgICAgICAgIyBSZWFkIGluIGRhdGEK4pSCICAg4pSCICAg4pSc4pSA4pSAIEItTlBQRVNfcmVhZF9pbl9jc3ZfdG9fZHVja0RCX2RhdGFiYXNlLlIgICMgUmVhZCBpbiBkYXRhCuKUgiAgIOKUgiAgIOKUnOKUgOKUgCBCLW9wZW5fcGF5bWVudHNfY2xlYW5pbmcuUiAgICAgICAgICAgICAgICAjIFJlYWQgaW4gZGF0YQrilIIgICDilIIgICDilJzilIDilIAgQi1waHlzaWNpYW5fY29tcGFyZV9kYXRhX2Rvd25sb2FkLlIgICAgICAgIyBSZWFkIGluIGRhdGEK4pSCICAg4pSc4pSA4pSAIPCfk4sgRGF0YSBQcm9jZXNzaW5nIChDLVNlcmllcykK4pSCICAg4pSCICAg4pSc4pSA4pSAIEMtRXh0cmFjdGluZ19hbmRfUHJvY2Vzc2luZ19OUFBFU19Qcm92aWRlcl9EYXRhLlIK4pSCICAg4pSCICAg4pSc4pSA4pSAIEMtTlBQRVMuUgrilIIgICDilIIgICDilJzilIDilIAgQy1vcGVuX3BheW1lbnRzLlIK4pSCICAg4pSCICAg4pSc4pSA4pSAIEMtcGh5c2ljaWFuX2NvbXBhcmVfY2xlYW5pbmcuUgrilIIgICDilJzilIDilIAg8J+TiyBEYXRhIFF1YWxpdHkgQ2hlY2sgKEQtU2VyaWVzKQrilIIgICDilIIgICDilJzilIDilIAgRC1RdWFsaXR5X2NoZWNrX21lZGljYXJlX3ByZXNjcmliaW5nLlIK4pSCICAg4pSCICAg4pSc4pSA4pSAIEQtUXVhbGl0eV9jaGVja19vbl9OUFBFU19tZXJnZS5SCuKUgiAgIOKUnOKUgOKUgCDwn5OLIEV4cG9ydCBDbGVhbmVkIERhdGEgKEUtU2VyaWVzKQrilIIgICDilIIgICDilJzilIDilIAgRS1NZWRpY2FyZV9wYXJ0X2RfcmV0aXJlbWVudF9hbmFseXNpc19wcm9jZXNzaW5nLlIK4pSCICAg4pSCICAg4pSc4pSA4pSAIEUtb3Blbl9wYXltZW50c19leHBvcnQuUgrilIIgICDilIIgICDilJTilIDilIAgRi1yZXRpcmVtZW50X3llYXJfY29uZmlybWF0aW9uLlIK4pSCICAg4pSc4pSA4pSAIPCfl7rvuI8gQ29yZSBBbmFseXNpcyBQaXBlbGluZSAoMDAtMTAgU2VyaWVzKQrilIIgICDilIIgICDilJzilIDilIAgMDAwLUNvbnRyb2wuUiAgICAgICAgICAgICAjIE1hc3RlciBjb250cm9sIHNjcmlwdArilIIgICDilIIgICDilJzilIDilIAgMDEtc2V0dXAuUiAgICAgICAgICAgICAgICAjIEVudmlyb25tZW50IGFuZCBBUEkgc2V0dXAK4pSCICAg4pSCICAg4pSc4pSA4pSAIDAyLXNlYXJjaF90YXhvbm9teS5SICAgICAgIyBOUFBFUyB0YXhvbm9teSBzZWFyY2gK4pSCICAg4pSCICAg4pSc4pSA4pSAIDAyLjUtc3Vic3BlY2lhbGlzdHNfb3Zlcl90aW1lLlIgICAjIFRlbXBvcmFsIHRyZW5kcwrilIIgICDilIIgICDilJzilIDilIAgMDMtc2VhcmNoX2FuZF9wcm9jZXNzX25waS5SICAgICAgICMgTlBJIGRhdGEgcHJvY2Vzc2luZwrilIIgICDilIIgICDilJzilIDilIAgMDNhLXNlYXJjaF9hbmRfcHJvY2Vzc19leHRyYS5SICAgICMgQWRkaXRpb25hbCBOUEkgcHJvY2Vzc2luZwrilIIgICDilIIgICDilJzilIDilIAgMDQtZ2VvY29kZS5SICAgICAgICAgICAgICAjIEFkZHJlc3MgZ2VvY29kaW5nIChIRVJFIEFQSSkK4pSCICAg4pSCICAg4pSc4pSA4pSAIDA2LWlzb2Nocm9uZXMuUiAgICAgICAgICAgIyBEcml2ZSB0aW1lIGlzb2Nocm9uZSBnZW5lcmF0aW9uCuKUgiAgIOKUgiAgIOKUnOKUgOKUgCAwNy1pc29jaHJvbmUtbWFwcGluZy5SICAgICMgU3BhdGlhbCBqb2lucyBhbmQgbWFwcGluZwrilIIgICDilIIgICDilJzilIDilIAgMDcuNS1wcmVwLWdldC1ibG9jay1ncm91cC1vdmVybGFwLlIK4pSCICAg4pSCICAg4pSc4pSA4pSAIDA4LWdldC1ibG9jay1ncm91cC1vdmVybGFwLlIgICAgICAjIENlbnN1cyBibG9jayBjYWxjdWxhdGlvbnMK4pSCICAg4pSCICAg4pSc4pSA4pSAIDA4LjUtcHJlcC10aGUtY2Vuc3VzLXZhcmlhYmxlcy5SCuKUgiAgIOKUgiAgIOKUnOKUgOKUgCAwOS1nZXQtY2Vuc3VzLXBvcHVsYXRpb24uUiAgICAgICAgIyBQb3B1bGF0aW9uIGFuYWx5c2lzCuKUgiAgIOKUgiAgIOKUnOKUgOKUgCAxMC1jYWxjdWxhdGUtcG9seWdvbi1kZW1vZ3JhcGhpY3MuUgrilIIgICDilIIgICDilJTilIDilIAgMTAtbWFrZS1yZWdpb24uUiAgICAgICAgICAjIFJlZ2lvbmFsIGFuYWx5c2lzCuKUgiAgIOKUnOKUgOKUgCDwn5OIIFJlc3VsdHMgJiBBbmFseXNpcwrilIIgICDilIIgICDilJzilIDilIAgYW5hbHl6ZV9pc29jaHJvbmVfZGF0YS5SICAgICAgICAgICMgU3RhdGlzdGljYWwgdHJlbmQgYW5hbHlzaXMK4pSCICAg4pSCICAg4pSc4pSA4pSAIHdhbGtlcl9pc29jaHJvbmVfbWFwcy5SICAgICAgICAgICAjIEZpbmFsIG1hcCBnZW5lcmF0aW9uCuKUgiAgIOKUgiAgIOKUnOKUgOKUgCBzdWJzcGVjaWFsaXN0c19vdmVyX3RpbWUuUiAgICAgICAgIyBXb3JrZm9yY2UgdHJlbmRzCuKUgiAgIOKUgiAgIOKUnOKUgOKUgCByZXRpcmVtZW50X2FkanVzdGVkLlIgICAgICAgICAgICAgIyBSZXRpcmVtZW50IGFuYWx5c2lzCuKUgiAgIOKUgiAgIOKUlOKUgOKUgCBnZXR0aW5nX2lzb2Nocm9uZXNfdHJ5aW5nLlIgICAgICAgIyBBbHRlcm5hdGl2ZSBtZXRob2RzCuKUgiAgIOKUnOKUgOKUgCDwn5ug77iPIFV0aWxpdHkgRnVuY3Rpb25zCuKUgiAgIOKUgiAgIOKUnOKUgOKUgCBhcGlfa2V5cy5SICAgICAgICAgICAgICAgICMgQVBJIGtleSBtYW5hZ2VtZW50CuKUgiAgIOKUgiAgIOKUnOKUgOKUgCBiZXNwb2tlX2Z1bmN0aW9ucy5SICAgICAgICMgQ3VzdG9tIHByb2plY3QgZnVuY3Rpb25zCuKUgiAgIOKUgiAgIOKUnOKUgOKUgCBnZW9jb2RlLlIgICAgICAgICAgICAgICAgICMgR2VvY29kaW5nIHV0aWxpdGllcwrilJzilIDilIAg8J+TgSByZXN1bHRzLyAgICAgICAgICAgICAgICAgICAgICAgIyBBbmFseXNpcyBvdXRwdXRzCuKUgiAgIOKUnOKUgOKUgCBzdGF0ZV9kYXRhLmNzdgrilIIgICDilJzilIDilIAgc3VtbWFyeV9zdGF0aXN0aWNzLmNzdgrilIIgICDilJzilIDilIAgdGFibGUxX3RlbXBvcmFsX3RyZW5kc19zdW1tYXJ5LmNzdgrilIIgICDilJzilIDilIAgdGFibGUyX2RlbW9ncmFwaGljX2Rpc3Bhcml0aWVzX3N1bW1hcnkuY3N2CuKUgiAgIOKUnOKUgOKUgCB0YWJ1bGF0ZWRfYWxsX3llYXJzX2NsZWFuXzIwMjQtMDgtMzAueGxzeArilIIgICDilJzilIDilIAgdGVtcG9yYWxfdHJlbmRfYW5hbHlzaXMuY3N2CuKUgiAgIOKUnOKUgOKUgCB0cmVuZF9hbmFseXNpcy5jc3YK4pSCICAg4pSU4pSA4pSAIHVzX3N0YXRlcy5jc3YK4pSc4pSA4pSAIPCfk4QgUkVBRE1FLlJtZCAgICAgICAgICAgICAgICAgICAgICMgVGhpcyBkb2N1bWVudGF0aW9uCuKUnOKUgOKUgCDwn5OEIFJFQURNRS5odG1sICAgICAgICAgICAgICAgICAgICAjIFJlbmRlcmVkIEhUTUwgdmVyc2lvbgpgYGAKCiMjIyMgRGF0YSBHYXRoZXJpbmcKCi0gICBgYmVzcG9rZV9mdW5jdGlvbnMuUmAgLSBEYXRhIGZvciB0aGUgZHVja0RCIGNvbm5lY3Rpb24gYW5kIGZ1bmN0aW9ucyBmb3IgdGhlCiAgICBEYXRhIEdhdGhlcmluZyBsZXR0ZXJlZCBjb2RlIGJlbG93LiBUaGUgTmF0aW9uYWwgQnVyZWF1IG9mIEVjb25vbWljIFJlc2VhcmNoCiAgICAoTkJFUikgcHJvdmlkZXMgYSBjdW11bGF0aXZlIE5QSS9OUFBFUyBkYXRhc2V0IGNyZWF0ZWQgZnJvbSBtb250aGx5IENNUwogICAgZmlsZXMgc3Bhbm5pbmcgZnJvbSBBcHJpbCAyMDA3IHRvIHRoZSBwcmVzZW50LCBhZGRyZXNzaW5nIGxpbWl0YXRpb25zIGluCiAgICBvZmZpY2lhbCBDTVMgb2ZmZXJpbmdzIHRoYXQgbGFjayBoaXN0b3JpY2FsIHByb3ZpZGVyIGRldGFpbHMuIFRoZSBkYXRhc2V0IGlzCiAgICBkZWR1cGxpY2F0ZWQgYmFzZWQgb24gdmFyaWFibGUgY2hhbmdlcyAoZXhjbHVkaW5nIG1lcmUgdXBkYXRlcyBpbiBmaWxlIG5hbWVzCiAgICBvciB5ZWFycyksIGFuZCBpbmNsdWRlcyBzZXBhcmF0ZSBjb3JlIGFuZCBtdWx0aXBsaWNhdGl2ZSB2YXJpYWJsZSBmaWxlcyB0bwogICAgbWFuYWdlIHRoZSBsYXJnZSBmaWxlIHNpemVzIGVmZmljaWVudGx5LgoKfCAqKkRhdGFzZXQvU2NyaXB0IE5hbWUqKiB8ICoqQXZhaWxhYmxlIFllYXJzKiogfCAqKk5vdGVzKiogfAp8Oi0tLXw6LS0tfDotLS18CnwgKipgQV9ucHBlc19kb3dubG9hZC5SYCoqIHwgMjAwN+KAkzIwMjIgfCBOQkVSIGN1bXVsYXRpdmUgTlBQRVMgZmlsZSAobW9udGhseSB1cGRhdGVzIGRlZHVwbGljYXRlZDsgaW5jbHVkZXMgY2hhbmdlcyBiYWNrIHRvIDIwMDcpLiB8CnwgKipgQS1OUElfZGVhY3RpdmF0aW9uX2Rvd25sb2FkLlJgKiogfCBWYXJpZXMsIHNsaWdodGx5IGRlbGF5ZWQgfCBCYXNlZCBvbiBzZWxmLXJlcG9ydGVkIGRlYWN0aXZhdGlvbi4gQ01TIHVwZGF0ZXMgaXJyZWd1bGFybHk7IG1heSBsYWcgcmVhbC10aW1lIGJ5IDHigJMyIHllYXJzLiB8CnwgKipgQS1NZWRpY2FyZV9wYXJ0X2RfcHJlc2NyaWJlcnNfZGF0YV9kb3dubG9hZGVkYCoqIHwgMjAxM+KAkzIwMjIgfCBSZWxlYXNlZCBhbm51YWxseSBieSBDTVM7IGZpcnN0IGF2YWlsYWJsZSBkYXRhc2V0IGJhc2VkIG9uIDIwMTMgcHJlc2NyaWJpbmcgZGF0YS4gfAp8ICoqYEEtZG93bmxvYWRfcGh5c2ljaWFuX2NvbXBhcmVfZG93bmxvYWRgKiogfCBcfjIwMTPigJMyMDIwIChkb3dubG9hZGVkIGZpbGVzKSB8IElDUFNSIGFyY2hpdmUgaGFzIGZpbGVzIHRocm91Z2ggXH4yMDIwIChQaHlzaWNpYW4gQ29tcGFyZSBjbG9zZWQgaW4gRGVjIDIwMjApLiBNdXN0IG1hbnVhbGx5IGxvZyBpbi4gfAp8ICoqYEEtZmFjaWxpdHlfYWZmaWxpYXRpb25fZG93bmxvYWQuUmAqKiB8IDIwMTTigJNwcmVzZW50IHwgRmlyc3QgRmFjaWxpdHkgQWZmaWxpYXRpb24gZGF0YSBzdGFydGVkIFx+MjAxNDsgeWVhcmx5IHVwZGF0ZXMgKENNUyBQaHlzaWNpYW4gQ29tcGFyZSBBZmZpbGlhdGlvbiBkYXRhKS4gfAp8ICoqYEEtb3Blbl9wYXltZW50c19kb3dubG9hZC5SYCoqIHwgMjAxM+KAk3ByZXNlbnQgfCBPcGVuIFBheW1lbnRzIChTdW5zaGluZSBBY3QpIHN0YXJ0ZWQgcmVwb3J0aW5nIHBheW1lbnRzIGluIDIwMTMuIEFubnVhbCB1cGRhdGVzLiB8CgotICAgYEFfbnBwZXNfZG93bmxvYWQuUmAgLSBEb3dubG9hZHMgTlBQRVMgZGF0YSBmb3IgYmFjayB5ZWFycyBmcm9tIE5CRVIKICAgIChOYXRpb25hbCBCb2FyZCBFY29ub21pYyBSZXNlYXJjaCkuIFRoZSBOYXRpb25hbCBCdXJlYXUgb2YgRWNvbm9taWMgUmVzZWFyY2gKICAgIChOQkVSKSBwcm92aWRlcyBhIGN1bXVsYXRpdmUgTlBJL05QUEVTIGRhdGFzZXQgY3JlYXRlZCBmcm9tIG1vbnRobHkgQ01TCiAgICBmaWxlcyBzcGFubmluZyBmcm9tIEFwcmlsIDIwMDcgdG8gMjAyMiwgYWRkcmVzc2luZyBsaW1pdGF0aW9ucyBpbiBvZmZpY2lhbAogICAgQ01TIG9mZmVyaW5ncyB0aGF0IGxhY2sgaGlzdG9yaWNhbCBwcm92aWRlciBkZXRhaWxzLiBUaGUgZGF0YXNldCBpcwogICAgZGVkdXBsaWNhdGVkIGJhc2VkIG9uIHZhcmlhYmxlIGNoYW5nZXMgKGV4Y2x1ZGluZyBtZXJlIHVwZGF0ZXMgaW4gZmlsZSBuYW1lcwogICAgb3IgeWVhcnMpLCBhbmQgaW5jbHVkZXMgc2VwYXJhdGUgY29yZSBhbmQgbXVsdGlwbGljYXRpdmUgdmFyaWFibGUgZmlsZXMgdG8KICAgIG1hbmFnZSB0aGUgbGFyZ2UgZmlsZSBzaXplcyBlZmZpY2llbnRseS4KCi0gICBgQS1OUElfZGVhY3RpdmF0aW9uX2Rvd25sb2FkLlJgIC0gTlBQRVMgZGF0YSBtYXkgYmUgYSBmZXcgeWVhcnMgYmVoaW5kIGFuZAogICAgaXMgYWxsIGJhc2VkIG9uIHBlcnNvbmFsIHJlcG9ydC4KCi0gICBgQS1NZWRpY2FyZV9wYXJ0X2RfcHJlc2NyaWJlcnNfZGF0YV9kb3dubG9hZGVkYCAtIEdvb2QgZm9yIGRvY3Mgd2hvCiAgICBwcmVzY3JpYmUgZHJ1Z3MgdG8gTWVkaWNhcmUgcGF0aWVudHMgb3ZlciA2NSB5ZWFycyBvbGQuIFN0YXJ0ZWQgMjAxMyB0bwoKICAgIDIwMjIuIAoKLSAgIGBBLWRvd25sb2FkX3BoeXNpY2lhbl9jb21wYXJlX2Rvd25sb2FkYCAtIFRvIGdldCBvbGQgcGh5c2ljaWFuCiAgICBjb21wYXJlL25hdGlvbmFsIGRvd25sb2FkYWJsZSBmaWxlcyB3ZSBuZWVkIHRvIGxvZyBpbiBtYW51YWxseSB0byBPUEVOCiAgICBJQ1BTUjoKICAgIDxodHRwczovL3d3dy5vcGVuaWNwc3Iub3JnL29wZW5pY3Bzci9wcm9qZWN0LzE0OTk2MS92ZXJzaW9uL1YxL3ZpZXc/cGF0aD0vb3BlbmljcHNyLzE0OTk2MS9mY3I6dmVyc2lvbnMvVjEmdHlwZT1wcm9qZWN0Pi4KICAgIFlvdSBoYXZlIHRvIGxvZ2luIHdpdGggZ29vZ2xlIGFjY291bnQgdG8gZG93bmxvYWQgaXQuCgotICAgYEEtZmFjaWxpdHlfYWZmaWxpYXRpb25fZG93bmxvYWQuUmAgLSBHb2xkIHN0YW5kYXJkLgoKLSAgIGBBLW9wZW5fcGF5bWVudHNfZG93bmxvYWQuUmAgLSBPcGVuIFBheW1lbnRzLgoKLSAgIGBCLXJlYWRfaW5fY3N2X2ZpbGVfdG9fZHVja0RCX2RhdGFiYXNlLlJgIC0gUmVhZHMgaW4gdGhlIE5QUEVTIENTViBmaWxzIGZyb20KICAgIHRoZSBOQkVSIHRvIHRoZSBkdWNrREIgZGF0YWJhc2UuIFRoZSBwcmltYXJ5IGFjdGlvbiBvY2N1cnMgdmlhIHRoZQogICAgcHJvY2Vzc19ucHBlc19kYXRhIGZ1bmN0aW9uIChkZWZpbmVkIGluIGFuIGV4dGVybmFsIHNjcmlwdAogICAgYmVzcG9rZV9mdW5jdGlvbnMuUiksIHdoaWNoIHJlYWRzIGFuZCBwcm9jZXNzZXMgYSBsYXJnZSBDU1YgZmlsZSBjb250YWluaW5nCiAgICBoaXN0b3JpY2FsIE5QSSBkYXRhIChzcGFubmluZyBNYXkgMjAwNSB0byBPY3RvYmVyIDIwMjApLiBUaGUgcHJvY2Vzc2VkIGRhdGEKICAgIGlzIHN0b3JlZCBpbiBhIER1Y2tEQiBkYXRhYmFzZSBmaWxlLgoKLSAgIGBDLUV4dHJhY3RpbmdfYW5kX1Byb2Nlc3NpbmdfTlBQRVNfUHJvdmlkZXJfRGF0YS5SYCAtIEZ1bmN0aW9uIGZvcgogICAgcHJvY2Vzc2luZyBPQkdZTnMgZnJvbSBOUFBFUyBkYXRhIHdpdGggZXhhY3QgZmlsZSBuYW1lcyBmb3IgeWVhcnMgMjAxMAogICAgdG8gMjAyMi4gQXV0b21hdGljYWxseSBpZGVudGlmaWVzIGFuZCBtYXBzIGRhdGFiYXNlIHRhYmxlcyB0byB0aGVpcgogICAgY29ycmVzcG9uZGluZyB5ZWFycywgZW5hYmxpbmcgZWZmaWNpZW50IGV4dHJhY3Rpb24gb2YgcHJvdmlkZXIgZGF0YSBhY3Jvc3MKICAgIGRpZmZlcmVudCB0aW1lIHBlcmlvZHMuIFNwZWNpZmllcyB0YXhvbm9teSBjb2RlcyByZXByZXNlbnRpbmcgdmFyaW91cyBPQi9HWU4KICAgIHN1YnNwZWNpYWx0aWVzLCBpbmNsdWRpbmcgZ2VuZXJhbCBvYnN0ZXRyaWNzIGFuZCBneW5lY29sb2d5LCBtYXRlcm5hbC1mZXRhbAogICAgbWVkaWNpbmUsIGFuZCBmZW1hbGUgcGVsdmljIG1lZGljaW5lLiBMb29rcyBhdCBhbGwgdGF4b25vbXkgY29sdW1ucyBpbiBlYWNoCiAgICB5ZWFyJ3MgZGF0YXNldCAobm90IGp1c3QgdGhlIGZpcnN0IG9uZSkuIENoZWNrcyBpZiBhbnkgb2YgeW91ciBzcGVjaWZpZWQKICAgIGNvZGVzIGFwcGVhciBpbiBhbnkgb2YgdGhvc2UgY29sdW1ucy4gSW5jbHVkZXMgYSBwaHlzaWNpYW4gaW4gdGhlIHJlc3VsdHMgaWYKICAgIHRoZXJlJ3MgYSBtYXRjaCBpbiBhbnkgY29sdW1uLiBSZXRyaWV2ZXMgcHJvdmlkZXIgcmVjb3JkcyBtYXRjaGluZyBzcGVjaWZpZWQKICAgIE9CL0dZTiB0YXhvbm9teSBjb2RlcyBmcm9tIGVhY2ggeWVhciwgc3RhbmRhcmRpemluZyBhbmQgY29tYmluaW5nIHRoZSBkYXRhCiAgICBpbnRvIGEgdW5pZmllZCBkYXRhc2V0LgoKLSAgIGBELVF1YWxpdHlfY2hlY2tfb25fTlBQRVNfbWVyZ2UuUmAgLSBUaGUgY2hlY2tfcGh5c2ljaWFuX3ByZXNlbmNlIGZ1bmN0aW9uCiAgICBpcyBhIHdlbGwtZGVzaWduZWQgdXRpbGl0eSBmb3IgdHJhY2tpbmcgcGh5c2ljaWFucyBhY3Jvc3MgdGVtcG9yYWwgZGF0YS4gSXQKICAgIGVmZmljaWVudGx5IGFuYWx5emVzIGEgZGF0YXNldCBjb250YWluaW5nIHBoeXNpY2lhbiBpbmZvcm1hdGlvbiB0byBkZXRlcm1pbmUKICAgIHdoZW4gc3BlY2lmaWMgcHJvdmlkZXJzIGFwcGVhciBpbiB0aGUgcmVjb3Jkcy4gVGhlIGZ1bmN0aW9uIGFjY2VwdHMgYSBsaXN0CiAgICBvZiBOYXRpb25hbCBQcm92aWRlciBJZGVudGlmaWVycyAoTlBJcyksIG9wdGlvbmFsbHkgcGFpcmVkIHdpdGggcHJvdmlkZXIKICAgIG5hbWVzLCBhbmQgbWV0aG9kaWNhbGx5IGV4YW1pbmVzIGVhY2ggTlBJJ3MgcHJlc2VuY2UgdGhyb3VnaG91dCBkaWZmZXJlbnQKICAgIHllYXJzLiBJdCByZXR1cm5zIGEgc3RydWN0dXJlZCBkYXRhIGZyYW1lIHN1bW1hcml6aW5nIGVhY2ggcHJvdmlkZXIncwogICAgcmVwcmVzZW50YXRpb24gaW4gdGhlIGRhdGFzZXQsIGluY2x1ZGluZyB0aGVpciB0b3RhbCByZWNvcmQgY291bnQgYW5kIGEKICAgIGNocm9ub2xvZ2ljYWwgbGlzdGluZyBvZiB5ZWFycyBpbiB3aGljaCB0aGV5IGFwcGVhci4gVGhpcyBmdW5jdGlvbiBpcwogICAgcGFydGljdWxhcmx5IHZhbHVhYmxlIGZvciBsb25naXR1ZGluYWwgYW5hbHlzZXMgb2YgaGVhbHRoY2FyZSBwcm92aWRlciBkYXRhLAogICAgZW5hYmxpbmcgcmVzZWFyY2hlcnMgdG8gaWRlbnRpZnkgcGF0dGVybnMgaW4gcGh5c2ljaWFuIHByZXNlbmNlLCB0cmFjawogICAgY2FyZWVyIHRyYWplY3Rvcmllcywgb3IgdmFsaWRhdGUgZGF0YSBjb21wbGV0ZW5lc3MgYWNyb3NzIG11bHRpcGxlIHllYXJzIG9mCiAgICBOUEkgcmVjb3Jkcy4KCmBgYCByCiMgTGlzdCBvZiBOUElzIHRvIGNoZWNrCm5waV9saXN0IDwtIGMoCiAgIjE2ODk2MDM3NjMiLCAgICMgVHlsZXIgTXVmZmx5LCBNRAogICIxNTI4MDYwNjM5IiwgICAjIEpvaG4gQ3VydGluLCBNRAogICIxMzQ2MzU1ODA3IiwgICAjIFBlZHJvIE1pcmFuZGEsIE1ECiAgIjE0Mzc5MDQ3NjAiLCAgICMgTGl6ZXRoIEFjb3N0YSwgTUQKICAiMTU2ODczODg1NCIsICAgIyBBYXJvbiBMYXpvcndpdHosIE1ECiAgIjExOTQ1NzE2NjEiLCAgICMgQW5hIEdvbWV6LCBNRAogICIxNjk5MjM3MDQwIiwgICAjIEVyaW4gVy4gRnJhbmtzLCBNRAogICIxMDAzMzExMDQ0IiwgICAjIENBVEhFUklORSBDYWxsaW5hbiwgTUQKICAiMTYwOTAwOTk0MyIsICAgIyBLcmlzdGluIFBvd2VsbCwgTUQKICAiMTExNDEyNTA1MSIsICAgIyBOYXRoYW4gS293LCBNRAogICIxMDQzNDMyMTIzIiwgICAjIEVsZW5hIFR1bml0c2t5LCBNRAogICIxMjE1NDkwNDQ2IiwgICAjIFBLCiAgIjE0ODc4Nzk5ODciICAgICMgUGV0ZXIgSmVwcHNvbgopCmBgYAoKLSAgIGBFLU1lZGljYXJlX3BhcnRfZF9wcmVzY3JpYmVyc19kYXRhX3Byb2Nlc3NpbmcuUmAgLSBUaGlzIHNjcmlwdCBwcm9jZXNzZXMKICAgIE1lZGljYXJlIFBhcnQgRCBwcmVzY3JpYmluZyBkYXRhIGZyb20gdGhlIENlbnRlcnMgZm9yIE1lZGljYXJlICYgTWVkaWNhaWQKICAgIFNlcnZpY2VzIChDTVMpLiBQcm9jZXNzIGVhY2ggdGFibGUgZmlsdGVyaW5nICJQcnNjcmJyX1R5cGUiIG9ubHkgT0JHWU4gYW5kCiAgICAiR3luZWNvbG9naWNhbCBPbmNvbG9neSIuIEl0IGlkZW50aWZpZXMgcHJvdmlkZXJzJyBwcmVzY3JpYmluZyBwYXR0ZXJucywKICAgIGNsZWFucyBkYXRhIGJ5IHJlbW92aW5nIG91dGxpZXIgcmVjb3JkcyAoY2xhaW0gY291bnRzIG92ZXIgNTAsMDAwKSwKICAgIGFubm90YXRlcyByZWNvcmRzIGJ5IHllYXIsIGFuZCBtZXJnZXMgbXVsdGlwbGUgeWVhcnMgaW50byBhIHNpbmdsZQogICAgc3RhbmRhcmRpemVkIGRhdGFzZXQuIEFkZGl0aW9uYWxseSwgaXQgY2FsY3VsYXRlcyB0aGUgbGFzdCBjb25zZWN1dGl2ZSB5ZWFyCiAgICBlYWNoIHByb3ZpZGVyIGFjdGl2ZWx5IHByZXNjcmliZWQgbWVkaWNhdGlvbnMgdW5kZXIgTWVkaWNhcmUgUGFydCBELAogICAgZmFjaWxpdGF0aW5nIGFuYWx5c2lzIG9mIHByb3ZpZGVyIGFjdGl2aXR5IGFuZCBjb250aW51aXR5IG92ZXIgdGltZS4gTk9UCiAgICBHT09EIEZPUiBET0NTIFdITyBETyBOT1QgVFJFQVQgUEFUSUVOVFMgXD42NSB5ZWFycyBvbGQuCgotICAgYEYtcmV0aXJlbWVudF95ZWFyX2NvbmZpcm1hdGlvbi5SYCAtIERvd25sb2FkIHRoZSBtYXNzaXZlIGRhdGEgZmlsZXMgdG8gdGhlCiAgICBleHRlcm5hbCBoYXJkIGRyaXZlIGZvciB0aGlzIHdpdGggb25lIHNldCBvZiBjb2RlIHRoZW4gdGhlbiBjYW4gcnVuCiAgICBFLXJldGlyZW1lbnRfeWVhcl9jb25maXJtYXRpb24uUi4KClJldGlyZW1lbnQgWWVhciBEYXRhIGRvd25sb2FkOiBgTlBQRVNfZGVhY3RpdmF0ZWRfZG93bmxvYWQuUmAgLSBCZXN0IHNvdXJjZSBidXQKbWF5IGJlIGxhdGUuXApgTWVkaWNhcmVfcGFydF9kX3ByZXNjcmliZXJzX2RhdGFfcHJvY2Vzc2luZ2AgLSBQZW9wbGUgd2hvIHByZXNjcmliZWQgdG8gXD42NQp5ZWFyIG9sZCB3b21lbi5cCmBkb3dubG9hZF9waHlzaWNpYW5fY29tcGFyZV9kYXRhLlJgIC0gSW5jbHVkZXMgZGF0YSBmb3IgcGVvcGxlIHdobyBzZWUKTWVkaWNhcmUuXApmYWNpbGl0eSBhZmZpbGlhdGlvbi4gLSBEb2VzIG5vdCBpbmNsdWRlIGEgeWVhciBmb3IgdGhlIGZhY2lsaXR5IGFmZmlsaWF0aW9uIHNvCml0IGlzIG5vdCBoZWxwZnVsLlwKQUJNUyAtIHNjcmFwZWQuCgotICAgYGdldHRpbmdfaXNvY2hyb25lc190cnlpbmcuUmAgLSBBbHRlcm5hdGl2ZSBtZXRob2QgZm9yIGlzb2Nocm9uZSBnZW5lcmF0aW9uCi0gICBgcmV0aXJlbWVudF9hZGp1c3RlZC5SYCAtIEVuaGFuY2VkIHJldGlyZW1lbnQgYW5hbHlzaXMgdXNpbmcgbXVsdGlwbGUgZGF0YQogICAgc291cmNlcyAoTlBJIGRlYWN0aXZhdGlvbiwgTWVkaWNhcmUgZGF0YSwgYW5kIGJvYXJkIGNlcnRpZmljYXRpb24gc3RhdHVzKSB0bwogICAgaW1wcm92ZSB3b3JrZm9yY2UgYWNjdXJhY3kuCi0gICBgc3Vic3BlY2lhbGlzdHMgb3ZlciB0aW1lLlJgIC0gQW5hbHlzaXMgb2Ygc3Vic3BlY2lhbGlzdCB0cmVuZHMKLSAgIGB2aXN1YWxpemVfZmlwc19pbnRlcnNfaXNvY2hyLlJgIC0gVmlzdWFsaXplcyBGSVBTIGNvZGUgaW50ZXJzZWN0aW9ucwotICAgYGZpcHNfYmxvY2tzX2ZlbWFsZV9wcm9wb3J0aW9uLlJgIC0gQW5hbHl6ZXMgZmVtYWxlIHBvcHVsYXRpb24gaW4gRklQUwogICAgYmxvY2tzCi0gICBgZmlwc19pc29jaHJvbmVzX3BvcHVsYXRpb25faW50ZXJzZWN0LlJgIC0gRXhhbWluZXMgcG9wdWxhdGlvbiB3aXRoaW4KICAgIGlzb2Nocm9uZXMKLSAgIGB6enpQb3N0aWNvLlJgIC0gVXNlZCBQb3N0aWNvIG9yaWdpbmFsbHkuIEFibGUgdG8gdXNlIGR1Y2tEQiBsYXRlciBvbi5cCi0gICBgUG9zdGljb19kYXRhYmFzZV9wdWxsLlJgIC0gRXh0cmFjdHMgcGh5c2ljaWFuIGRhdGEgZnJvbSBQb3N0Z3JlU1FMCiAgICBkYXRhYmFzZSwgZW5hYmxpbmcgeWVhci1ieS15ZWFyIGFuYWx5c2lzIG9mIHBoeXNpY2lhbiBwcmFjdGljZSBsb2NhdGlvbnMKICAgIGZyb20gMjAxMyB0byAyMDIyLiBQdWxscyAiR1lORUNPTE9HSUMgT05DT0xPR1kiIGZyb20gdGhlIFByaW1hcnkgU3BlY2lhbHR5LgogICAgRm9yIHVyb2d5biwgd2Ugd2lsbCBuZWVkIE5QSXMgdG8gZ28gcmV0cm9zcGVjdGl2ZWx5IHRvIGxvb2sgZm9yIHBlb3BsZS4KCiMjIyMgMS4gU2V0dXAgYW5kIERhdGEgUHJlcGFyYXRpb24KCi0gICBgMDAwLWNvbnRyb2wuUmAgLSBBdXhpbGlhcnkgc2NyaXB0IGZvciBkYXRhIGNvbXBpbGF0aW9uCi0gICBgMDEtc2V0dXAuUmAgLSBMb2FkcyBwYWNrYWdlcywgc2V0cyBBUEkga2V5cywgZGVmaW5lcyBoZWxwZXIgZnVuY3Rpb25zLAogICAgaW5pdGlhbGl6ZXMgZGlyZWN0b3J5IHN0cnVjdHVyZQotICAgYDAyLXNlYXJjaF90YXhvbm9teS5SYCAtIFNlYXJjaCB0aGUgTlBQRVMgUmVnaXN0cnkgZGF0YWJhc2UgdXNpbmcgbnBpX3NlYXJjaAogICAgbGlicmFyeSBpbiBhIHdyYXBwZXIuIFRheG9ub215IGRlc2NyaXB0aW9uIGZyb20gdGhlIE5VQ0M6CiAgICA8aHR0cHM6Ly90YXhvbm9teS5udWNjLm9yZy8+LiBOb3RlIHJlY2VudCBjaGFuZ2UgaW4gRlBNUlMgdG8gVVJQUy5cCi0gICBgMDIuNS1zdWJzcGVjaWFsaXN0c19vdmVyX3RpbWUuUmAgLSBBbmFseXplcyBzdWJzcGVjaWFsaXN0IHRyZW5kcyBvdmVyCiAgICBtdWx0aXBsZSB5ZWFycwotICAgYDAzLXNlYXJjaF9hbmRfcHJvY2Vzc19ucGkuUmAgLSBQcm9jZXNzZXMgTmF0aW9uYWwgUHJvdmlkZXIgSWRlbnRpZmllciAoTlBJKQogICAgZGF0YQotICAgYDAzYS1zZWFyY2hfYW5kX3Byb2Nlc3NfZXh0cmEuUmAgLSBBZGRpdGlvbmFsIE5QSSBwcm9jZXNzaW5nIGZvciBlZGdlIGNhc2VzCi0gICBgMDQtZ2VvY29kZS5SYCAtIEdlb2NvZGVzIHByb3ZpZGVyIGFkZHJlc3NlcyB1c2luZyB0aGUgSEVSRSBBUEkKLSAgIGB6ejA1LWdlb2NvZGUtY2xlYW5pbmcuUmAgLSBPbGQgdGVjaG5pcXVlIHdpdGggcG9zdG1hc3RlciBwdWxsaW5nIGFwYXJ0IHRoZQogICAgYWRkcmVzcy4KCiMjIyMgMi4gSXNvY2hyb25lIEdlbmVyYXRpb24gYW5kIEFuYWx5c2lzCgotICAgYDA2LWlzb2Nocm9uZXMuUmAgLSBHZW5lcmF0ZXMgZHJpdmUgdGltZSBpc29jaHJvbmVzICgzMCwgNjAsIDEyMCwgMTgwIG1pbikKLSAgIGAwNy1pc29jaHJvbmUtbWFwcGluZy5SYCAtIE1hcHMgaXNvY2hyb25lcyBhbmQgcGVyZm9ybXMgc3BhdGlhbCBqb2lucwotICAgYDA3LjUtcHJlcC1nZXQtYmxvY2stZ3JvdXAtb3ZlcmxhcC5SYCAtIFByZXBhcmVzIGNlbnN1cyBibG9jayBncm91cCBkYXRhCi0gICBgMDgtZ2V0LWJsb2NrLWdyb3VwLW92ZXJsYXAuUmAgLSBDYWxjdWxhdGVzIG92ZXJsYXAgYmV0d2VlbiBpc29jaHJvbmVzIGFuZAogICAgY2Vuc3VzIGJsb2NrcwotICAgYDA4LjUtcHJlcC10aGUtY2Vuc3VzLXZhcmlhYmxlcy5SYCAtIFByZXBhcmVzIGRlbW9ncmFwaGljIHZhcmlhYmxlcyBmcm9tCiAgICBDZW5zdXMKLSAgIGAwOS1nZXQtY2Vuc3VzLXBvcHVsYXRpb24uUmAgLSBDYWxjdWxhdGVzIHBvcHVsYXRpb24gd2l0aGluL291dHNpZGUKICAgIGlzb2Nocm9uZXMKCiMjIyMgMy4gUmVzdWx0cyBhbmQgQW5hbHlzaXMKCi0gICBgMTAtY2FsY3VsYXRlLXBvbHlnb24tZGVtb2dyYXBoY3MuUmAgLSBBbmFseXplcyBkZW1vZ3JhcGhpYyBjaGFyYWN0ZXJpc3RpY3MKCi0gICBgMTAtbWFrZS1yZWdpb24uUmAgLSBDcmVhdGVzIHJlZ2lvbmFsIG1hcHMgYW5kIGFuYWx5c2VzCgotICAgYGFuYWx5emVfaXNvY2hyb25lX2RhdGEuUmAgLSBGcmFtZXdvcmsgZm9yIGFuYWx5emluZyBpc29jaHJvbmUgZGF0YQoKLSAgIGBjYWxjdWxhdGVfcG9wdWxhdGlvbl9pbl9pc29jaHJvbmVzX2J5X3JhY2UuUmAgLSBBbmFseXplcyBwb3B1bGF0aW9uIGJ5IHJhY2UKICAgIHdpdGhpbiBpc29jaHJvbmVzCgotICAgYHdhbGtlcl9pc29jaHJvbmVfbWFwcy5SYCAtIFZpc3VhbGl6ZXMgaXNvY2hyb25lIGNoYW5nZXMgb3ZlciB0aW1lCgotICAgYEFjY2Vzc19EYXRhLmNzdmAgLSBEYXRhIGZyb20gVGFubm91cyB0aGF0IGhlIGFycmFuZ2VkIGFuZCBpcyBoZWxkIGluCiAgICBgZGF0YS9gCgojIyMgUiBNYXJrZG93biBEb2N1bWVudHMKCi0gICBgR09fYWNjZXNzX2FuYWx5c2lzX2NvZGUuUm1kYCAtIFN0YXRpc3RpY2FsIGFuYWx5c2lzIG9mIGd5bmVjb2xvZ2ljIG9uY29sb2d5CiAgICBhY2Nlc3MKLSAgIGBmb3JfZXZlcnlfeWVhcl9zY3JpcHRfcm1kLlJtZGAgLSBZZWFyLWJ5LXllYXIgYW5hbHlzaXMgb2YgYWNjZXNzaWJpbGl0eQogICAgdHJlbmRzCi0gICBgaXNvY2hyb25lcy5SbWRgIC0gVHV0b3JpYWwgb24gY3JlYXRpbmcgYW5kIGFuYWx5emluZyBpc29jaHJvbmVzCgojIyBFeGVjdXRpb24gT3JkZXIKCkZvciBhIGNvbXBsZXRlIGFuYWx5c2lzLCB0aGUgZmlsZXMgc2hvdWxkIGJlIGV4ZWN1dGVkIGluIGFwcHJveGltYXRlbHkgdGhpcwpvcmRlcjoKCiMjIyBTZXR1cCBQaGFzZQoKMS4gIGAwMS1zZXR1cC5SYAoyLiAgYFBvc3RpY29fZGF0YWJhc2VfcHVsbC5SYCAoaWYgZXh0ZXJuYWwgaGFyZHJpdmUgd2l0aCB0aGUgUG9zaXRpY28gZGF0YWJhc2UKICAgIGFjY2VzcyBpcyBjb25uZWN0ZWQpCgojIyMgRGF0YSBDb2xsZWN0aW9uIFBoYXNlCgozLiAgYDAyLXNlYXJjaF90YXhvbm9teS5SYAo0LiAgYDAyLjUtc3Vic3BlY2lhbGlzdHNfb3Zlcl90aW1lLlJgCjUuICBgMDMtc2VhcmNoX2FuZF9wcm9jZXNzX25waS5SYCAtIFdoZW4gZGlkIHBoeXNpY2lhbnMgc3RhcnQgcHJhY3RpY2luZz8KNi4gIGAwM2Etc2VhcmNoX2FuZF9wcm9jZXNzX2V4dHJhLlJgCjcuICBgMDQtZ2VvY29kZS5SYAo4LiAgYDA1LWdlb2NvZGUtY2xlYW5pbmcuUmAKOS4gIGByZXRpcmVtZW50LlJgL2ByZXRpcmVtZW50X2FkanVzdGVkLlJgIC0gV2hlbiBkaWQgcGh5c2ljaWFucyByZXRpcmU/IChpZgogICAgcGh5c2ljaWFuIHJldGlyZW1lbnQgYW5hbHlzaXMgaXMgbmVlZGVkKQoKIyMjIElzb2Nocm9uZSBBbmFseXNpcyBQaGFzZQoKOS4gIGAwNi1pc29jaHJvbmVzLlJgCjEwLiBgMDctaXNvY2hyb25lLW1hcHBpbmcuUmAKMTEuIGAwNy41LXByZXAtZ2V0LWJsb2NrLWdyb3VwLW92ZXJsYXAuUmAKMTIuIGAwOC1nZXQtYmxvY2stZ3JvdXAtb3ZlcmxhcC5SYAoxMy4gYDA4LjUtcHJlcC10aGUtY2Vuc3VzLXZhcmlhYmxlcy5SYAoxNC4gYDA5LWdldC1jZW5zdXMtcG9wdWxhdGlvbi5SYAoKIyMjIFJlc3VsdHMgYW5kIEFkZGl0aW9uYWwgQW5hbHlzaXMgUGhhc2UKCjE1LiBgMTAtY2FsY3VsYXRlLXBvbHlnb24tZGVtb2dyYXBoY3MuUmAKCjE2LiBgMTAtbWFrZS1yZWdpb24uUmAKCjE3LiBgc2NyaXB0MjAyNS5SYCAtIERvd25sb2FkcyB0aGUgcG9wdWxhdGlvbiBkYXRhIGFuZCBhZ2dyZWdhdGVzIGl0IGJ5CiAgICBpc29jaHJvbmUgYW5kIGJ5IHRvdGFsIHBvcHVsYXRpb24uIENyZWF0ZXMgdGFibGVzIG9mIHdvbWVuIHdpdGhpbiBpc29jaHJvbmVzCiAgICBhbmQgdG90YWwgd29tZW4uXAoKYGBgIHIKPiBhY2Nlc3NfbWVyZ2VkCiMgQSB0aWJibGU6IDI0MCDDlyA2CiAgIHllYXIgIHJhbmdlIGNhdGVnb3J5ICAgICAgICAgICAgICBjb3VudCAgICAgdG90YWwgcGVyY2VudAogICA8Y2hyPiA8aW50PiA8Y2hyPiAgICAgICAgICAgICAgICAgPGRibD4gICAgIDxkYmw+ICAgPGRibD4KIDEgMjAxMyAgIDE4MDAgdG90YWxfZmVtYWxlICAgICAgIDcyMzYyNTE3IDE2MjY0OTk1NCAgICA0NC41CiAyIDIwMTMgICAxODAwIHRvdGFsX2ZlbWFsZV93aGl0ZSA0NjU1MzM1OSAxMTkxODA3NTEgICAgMzkuMQpgYGAKCjE5LiBgYW5hbHl6ZV9pc29jaHJvbmVfZGF0YS5SYCAtIE1lYXN1cmVzIHRoZSBzbG9wZSBmb3IgYWNjZXNzIGZyb20gc3RhcnQgMjAxMwogICAgdG8gZmluaXNoIDIwMjIuIEZpbmRzIHNpZ25pZmljYW50IGluY3JlYXNlcyBvciBkZWNyZWFzZXMgaW4gdGhlIG51bWJlciBvZgogICAgd29tZW4gd2l0aGluIGEgZHJpdmUgdGltZS4gU29tZSBub3RhYmxlIHRyZW5kczoKCi0gICBUb3RhbCBmZW1hbGUgd2hpdGUgcG9wdWxhdGlvbiBzaG93cyBzaWduaWZpY2FudCBkZWNsaW5lcyBpbiBhY2Nlc3MgYWNyb3NzCiAgICBhbGwgdGltZSB0aHJlc2hvbGRzCi0gICBTb21lIGNhdGVnb3JpZXMgbGlrZSBgdG90YWxfZmVtYWxlX2FzaWFuYCBzaG93IHNpZ25pZmljYW50IGluY3JlYXNlcyBpbgogICAgbG9uZ2VyLXRpbWUgdGhyZXNob2xkcwoKYGBgIHIKPiBpc29jaHJvbmVfcmVzdWx0cyR0cmVuZF9hbmFseXNpcwogICAgICAgICAgICAgICAgIGNhdGVnb3J5ICAgICAgICB0aW1lX3RocmVzaG9sZCAgICAgICAgIHNsb3BlICAgIHJfc3F1YXJlZCAgICAgcF92YWx1ZSBzdGFydF95ZWFyIGVuZF95ZWFyIHN0YXJ0X3ZhbHVlCnllYXIgICAgICAgICB0b3RhbF9mZW1hbGUgIGFjY2Vzc18zMG1pbl9jbGVhbmVkIC03LjM2Mzk1NmUrMDUgMS4xMjY2NjllLTAxIDAuMzQzMDI5OTI4ICAgICAgIDIwMTMgICAgIDIwMjIgICAgNzIzNjI1MTcKeWVhcjEgICAgICAgIHRvdGFsX2ZlbWFsZSAgYWNjZXNzXzYwbWluX2NsZWFuZWQgLTYuMzAxMDY4ZSswNSA3LjIyMTczNWUtMDIgMC40NTI3OTIxNzYgICAgICAgMjAxMyAgICAgMjAyMiAgICA5ODMzNzY0MAp5ZWFyMiAgICAgICAgdG90YWxfZmVtYWxlIGFjY2Vzc18xMjBtaW5fY2xlYW5lZCAtMS4zNDA3MTllKzA1IDQuNTA5NDM0ZS0wMyAwLjg1Mzc2NDkyNiAgICAgICAyMDEzICAgICAyMDIyICAgMTMzMDQ5MDI3CnllYXIzICAgICAgICB0b3RhbF9mZW1hbGUgYWNjZXNzXzE4MG1pbl9jbGVhbmVkIC0zLjAxNTcwOWUrMDMgMi4zMzYyMDBlLTA2IDAuOTk2NjU2NDk0ICAgICAgIDIwMTMgICAgIDIwMjIgICAxNDg0NDcwNzIKeWVhcjQgICB0b3RhbF9mZW1hbGVfYWlhbiAgYWNjZXNzXzMwbWluX2NsZWFuZWQgIDguMjQyNzAzZSswMyAxLjU1OTEzOGUtMDEgMC4yNTg3ODYxNTkgICAgICAgMjAxMyAgICAgMjAyMiAgICAgIDMxNjkzNwp5ZWFyNSAgIHRvdGFsX2ZlbWFsZV9haWFuICBhY2Nlc3NfNjBtaW5fY2xlYW5lZCAgMS4xMDkwMjdlKzA0IDEuNzQ3MDUwZS0wMSAwLjIyOTM2NDMyNyAgICAgICAyMDEzICAgICAyMDIyICAgICAgNDUzODA3CmBgYAoKYGBge3J9CmxpYnJhcnkoa25pdHIpCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJmaWd1cmVzL21lYW5fYWNjZXNzX2J5X2dyb3VwLnBuZyIpCmBgYAoKYGBge3J9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJmaWd1cmVzL2FjY2Vzc19vdmVyX3RpbWUucG5nIikKYGBgCgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3VyZXMvYWNjZXNzX2Rpc3RyaWJ1dGlvbi5wbmciKQpgYGAKCjIyLiBgR09fYWNjZXNzX2FuYWx5c2lzX2NvZGUuUm1kYAoKMjMuIGB3YWxrZXJfaXNvY2hyb25lX21hcHMuUmAgLSBDcmVhdGVzIGEgZmFjZXRlZCBtYXAgb2YgdGhlIFVTLCBISSwgQUssIGFuZCBQUgogICAgd2l0aCB0aGUgaXNvY2hyb25lcyBpbiBwbGFjZS4KCjI0LiBgenp6Y2FsY3VsYXRlX3BvcHVsYXRpb25faW5faXNvY2hyb25lc19ieV9yYWNlLlJgIC0gSSdtIHVuc3VyZSBpZiBpdCBpcwogICAgbmVlZGVkLlwKCjI1LiBgenp6Zm9yX2V2ZXJ5X3llYXJfc2NyaXB0X3JtZC5SbWRgIC0gVGhpcyBpcyBUSEUgU0FNRSBNQVAgVEhBVCBXQUxLRVIgRElEIElOCiAgICBgd2Fsa2VyX2lzb2Nocm9uZV9tYXBzLlJgIEJVVCBIRSBESUQgSVQgQkVUVEVSLiBDcmVhdGVzIGEgbWFwIG9mIHRoZQogICAgaXNvY2hyb25lcyBmb3IgZXZlcnkgeWVhci4KCiMjIyBNZXRob2RvbG9neSBPdmVydmlldwoKIyMjIyBHZW9zcGF0aWFsIEFuYWx5c2lzCgotICAgKipEcml2ZSBUaW1lIElzb2Nocm9uZXMqKjogMzAsIDYwLCAxMjAsIGFuZCAxODAtbWludXRlIHRocmVzaG9sZHMKLSAgICoqUm91dGluZyBFbmdpbmUqKjogSEVSRSBNYXBzIEFQSSB3aXRoIHJlYWwtdGltZSB0cmFmZmljIGRhdGEKLSAgICoqUmVmZXJlbmNlIFRpbWUqKjogVGhpcmQgRnJpZGF5IG9mIE9jdG9iZXIsIDk6MDAgQU0gKGNvbnNpc3RlbnQgYWNyb3NzCiAgICB5ZWFycykKLSAgICoqR2VvZ3JhcGhpYyBSZXNvbHV0aW9uKio6IENlbnN1cyBibG9jayBncm91cHMgKGhpZ2hlciBwcmVjaXNpb24gdGhhbgogICAgY291bnRpZXMpCgojIyMjIERlbW9ncmFwaGljIEFuYWx5c2lzCgotICAgKipSYWNlL0V0aG5pY2l0eSBDYXRlZ29yaWVzKio6IFdoaXRlLCBCbGFjaywgQXNpYW4vUGFjaWZpYyBJc2xhbmRlciwKICAgIEFtZXJpY2FuIEluZGlhbi9BbGFza2EgTmF0aXZlCi0gICAqKkdlb2dyYXBoaWMgUmVnaW9ucyoqOiBBQ09HIChBbWVyaWNhbiBDb2xsZWdlIG9mIE9ic3RldHJpY2lhbnMgYW5kCiAgICBHeW5lY29sb2dpc3RzKSBEaXN0cmljdHMKLSAgICoqVXJiYW4vUnVyYWwgQ2xhc3NpZmljYXRpb24qKjogQ2Vuc3VzIEJ1cmVhdSBkZWZpbml0aW9ucwoKIyMjIyBQaHlzaWNpYW4gSWRlbnRpZmljYXRpb24KCmBgYCByCiMgVGF4b25vbXkgY29kZXMgZm9yIE9CR1lOIHN1YnNwZWNpYWxpc3RzCm9iZ3luX3RheG9ub215X2NvZGVzIDwtIGMoCiAgIjIwN1YwMDAwMFgiLCAgICAjIE9ic3RldHJpY3MgJiBHeW5lY29sb2d5CiAgIjIwN1ZYMDIwMVgiLCAgICAjIEd5bmVjb2xvZ2ljIE9uY29sb2d5CiAgIjIwN1ZFMDEwMlgiLCAgICAjIFJlcHJvZHVjdGl2ZSBFbmRvY3Jpbm9sb2d5CiAgIjIwN1ZHMDQwMFgiLCAgICAjIEd5bmVjb2xvZ3kKICAiMjA3Vk0wMTAxWCIsICAgICMgTWF0ZXJuYWwgJiBGZXRhbCBNZWRpY2luZQogICIyMDdWRjAwNDBYIiwgICAgIyBGZW1hbGUgUGVsdmljIE1lZGljaW5lL1Vyb2d5bmVjb2xvZ3kKICAiMjA3VkIwMDAyWCIsICAgICMgQmFyaWF0cmljIE1lZGljaW5lCiAgIjIwN1ZDMDIwMFgiLCAgICAjIENyaXRpY2FsIENhcmUgTWVkaWNpbmUKICAiMjA3VkMwMzAwWCIsICAgICMgQ29tcGxleCBGYW1pbHkgUGxhbm5pbmcKICAiMjA3VkgwMDAyWCIsICAgICMgUGFsbGlhdGl2ZSBDYXJlCiAgIjIwN1ZYMDAwMFgiICAgICAjIE9ic3RldHJpY3MgT25seQopCmBgYAoKIyMjIERhdGEgU291cmNlcwoKLSAgIFBoeXNpY2lhbiBEYXRhOiBOYXRpb25hbCBQbGFuIGFuZCBQcm92aWRlciBFbnVtZXJhdGlvbiBTeXN0ZW0gKE5QUEVTKSBmaWxlcwogICAgZnJvbSAyMDEzIHRvIDIwMjMKLSAgIFBvcHVsYXRpb24gRGF0YTogQW1lcmljYW4gQ29tbXVuaXR5IFN1cnZleSA1LXllYXIgZXN0aW1hdGVzIGFuZCBkZWNlbm5pYWwKICAgIGNlbnN1cyBkYXRhCi0gICBHZW9ncmFwaGljIEFuYWx5c2lzOiBVc2VkIGJsb2NrIGdyb3VwcyByYXRoZXIgdGhhbiBjb3VudGllcyBmb3IgZmluZXIgZGF0YQogICAgcmVzb2x1dGlvbgotICAgR2VvZ3JhcGhpYyBSZWdpb25zOiBBbWVyaWNhbiBDb2xsZWdlIG9mIE9ic3RldHJpY2lhbnMgYW5kIEd5bmVjb2xvZ2lzdHMKICAgIChBQ09HKSBEaXN0cmljdHMKCiMjIyBBbmFseXNpcyBBcHByb2FjaAoKLSAgIERyaXZlIHRpbWUgaXNvY2hyb25lcyAoMzAsIDYwLCAxMjAsIDE4MCBtaW51dGVzKSBjYWxjdWxhdGVkIHVzaW5nIEhFUkUgQVBJCi0gICBJc29jaHJvbmVzIGdlbmVyYXRlZCBmb3IgdGhlIHRoaXJkIEZyaWRheSBpbiBPY3RvYmVyIGF0IDk6MDAgQU0gZm9yIGVhY2gKICAgIHllYXIKLSAgIERlbW9ncmFwaGljIGFuYWx5c2lzIGJ5IHJhY2UvZXRobmljaXR5IChXaGl0ZSwgQmxhY2ssIEFzaWFuIG9yIFBhY2lmaWMKICAgIElzbGFuZGVyLCBBbWVyaWNhbiBJbmRpYW4vQWxhc2thIE5hdGl2ZSkKLSAgIENvbXBhcmlzb24gb2YgdXJiYW4gdnMuIHJ1cmFsIGFjY2Vzc2liaWxpdHkKCiMjIFByZXJlcXVpc2l0ZXMKCiMjIyBTeXN0ZW0gUmVxdWlyZW1lbnRzCgpgYGAgcgojIENoZWNrIFIgdmVyc2lvbiAobWluaW11bSA0LjAuMCByZXF1aXJlZCkKaWYgKGdldFJ2ZXJzaW9uKCkgPCAiNC4wLjAiKSB7CiAgc3RvcCgiUiB2ZXJzaW9uIDQuMC4wIG9yIGhpZ2hlciBpcyByZXF1aXJlZC4gQ3VycmVudCB2ZXJzaW9uOiAiLCBnZXRSdmVyc2lvbigpKQp9CgojIENoZWNrIGF2YWlsYWJsZSBtZW1vcnkgKDhHQisgcmVjb21tZW5kZWQpCm1lbW9yeV9nYiA8LSByb3VuZChtZW1vcnkubGltaXQoKSAvIDEwMjQsIDEpICAjIFdpbmRvd3MKIyBtZW1vcnlfZ2IgPC0gcm91bmQoYXMubnVtZXJpYyhzeXN0ZW0oInN5c2N0bCBody5tZW1zaXplIiwgaW50ZXJuID0gVFJVRSkpIC8gMTAyNF4zLCAxKSAgIyBtYWNPUwpsb2dnZXI6OmxvZ19pbmZvKCJBdmFpbGFibGUgbWVtb3J5OiB7bWVtb3J5X2difSBHQiIpCmlmIChtZW1vcnlfZ2IgPCA4KSB7CiAgbG9nZ2VyOjpsb2dfd2FybigiTGVzcyB0aGFuIDhHQiBSQU0gZGV0ZWN0ZWQuIExhcmdlIHNwYXRpYWwgb3BlcmF0aW9ucyBtYXkgYmUgc2xvdy4iKQp9CmBgYAoKYGBgIHIKIyBJbnN0YWxsIHJlcXVpcmVkIHBhY2thZ2VzCnJlcXVpcmVkX3BhY2thZ2VzIDwtIGMoCiAgInRpZHl2ZXJzZSIsICJzZiIsICJ0aWdyaXMiLCAibG9nZ2VyIiwgImFzc2VydHRoYXQiLAogICJnZ3Bsb3QyIiwgInNjYWxlcyIsICJ2aXJpZGlzIiwgIkRUIiwgImtuaXRyIgopCgojIEluc3RhbGwgbWlzc2luZyBwYWNrYWdlcwpuZXdfcGFja2FnZXMgPC0gcmVxdWlyZWRfcGFja2FnZXNbIShyZXF1aXJlZF9wYWNrYWdlcyAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpWywiUGFja2FnZSJdKV0KaWYobGVuZ3RoKG5ld19wYWNrYWdlcykpIGluc3RhbGwucGFja2FnZXMobmV3X3BhY2thZ2VzKQoKIyBMb2FkIGN1c3RvbSBmdW5jdGlvbnMKc291cmNlKCJSL2Jlc3Bva2VfZnVuY3Rpb25zLlIiKQpgYGAKCi0gICBSIDQuMC4wIG9yIGhpZ2hlcgotICAgOEdCKyBSQU0gcmVjb21tZW5kZWQgZm9yIGxhcmdlIHNwYXRpYWwgZGF0YXNldHMKLSAgIFJlcXVpcmVkIFIgcGFja2FnZXMgKGxpc3RlZCBpbiBgMDEtc2V0dXAuUmApCi0gICBIRVJFIE1hcHMgQVBJIGtleQotICAgVVMgQ2Vuc3VzIEJ1cmVhdSBBUEkga2V5Ci0gICBEdWNrREIgZGF0YWJhc2UKCiMjIyBIRVJFIE1hcHMgSW50ZWdyYXRpb24KCioqR2VvY29kaW5nIFBpcGVsaW5lOioqIDEuIEFkZHJlc3Mgc3RhbmRhcmRpemF0aW9uIGFuZCBjbGVhbmluZyAyLiBCYXRjaApnZW9jb2RpbmcgcmVxdWVzdHMgKHJhdGUgbGltaXQgbWFuYWdlbWVudCkgMy4gUXVhbGl0eSBzY29yaW5nIGFuZCBtYW51YWwgcmV2aWV3Cm9mIHBvb3IgbWF0Y2hlcyA0LiBDb29yZGluYXRlIHZhbGlkYXRpb24gYW5kIG91dGxpZXIgZGV0ZWN0aW9uCgoqKklzb2Nocm9uZSBHZW5lcmF0aW9uOioqIDEuIFByb3ZpZGVyIGNvb3JkaW5hdGUgaW5wdXQgMi4gTXVsdGlwbGUgdGltZQp0aHJlc2hvbGQgcmVxdWVzdHMgcGVyIHByb3ZpZGVyIDMuIFBvbHlnb24gc2ltcGxpZmljYXRpb24gZm9yIHN0b3JhZ2UgZWZmaWNpZW5jeQo0LiBTcGF0aWFsIHZhbGlkYXRpb24gYW5kIHRvcG9sb2d5IGNoZWNraW5nCgoqKldoeSBEdWNrREIgb3ZlciBQb3N0Z3JlU1FML1NRTGl0ZToqKiAtICoqUGVyZm9ybWFuY2UqKjogT3B0aW1pemVkIGZvcgphbmFseXRpY2FsIHF1ZXJpZXMgKE9MQVAgdnMgT0xUUCkgLSAqKlNpbXBsaWNpdHkqKjogU2luZ2xlLWZpbGUgZGF0YWJhc2UsIG5vCnNlcnZlciByZXF1aXJlZCAtICoqTWVtb3J5Kio6IEVmZmljaWVudCBoYW5kbGluZyBvZiBsYXJnZSBkYXRhc2V0cyAtICoqUgpJbnRlZ3JhdGlvbioqOiBOYXRpdmUgUiBEQkkgc3VwcG9ydAoKKipBbHRlcm5hdGl2ZSBDb25zaWRlcmVkKio6IFBvc3RncmVTUUwgd2l0aCBQb3N0R0lTIC0gKipQcm9zKio6IEJldHRlciBzcGF0aWFsCmZ1bmN0aW9ucywgbXVsdGktdXNlciAtICoqQ29ucyoqOiBTZXJ2ZXIgc2V0dXAgY29tcGxleGl0eSwgb3ZlcmtpbGwgZm9yCnNpbmdsZS11c2VyIGFuYWx5c2lzCgojIyBUb29scyBhbmQgRGF0YSBNYW5hZ2VtZW50CgojIyDwn5K7IEFQSSBDb25maWd1cmF0aW9uCgojIyMgSEVSRSBNYXBzIEFQSSBTZXR1cAoKLSAgIFVzZWQgZm9yIGdlb2NvZGluZyBhbmQgaXNvY2hyb25lIGdlbmVyYXRpb24KLSAgIEdlb2NvZGluZyBhbmQgU2VhcmNoOiBcJDAuODMgcGVyIDEsMDAwIHNlYXJjaGVzIGFmdGVyIDMwLDAwMCBmcmVlIGdlb2NvZGVzCi0gICBJc29saW5lIFJvdXRpbmc6IFwkNS41MCBwZXIgMSwwMDAgYWZ0ZXIgMiw1MDAgZnJlZSBpc29saW5lIHJvdXRpbmdzCgpgYGAgcgojIFNldCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgKGFkZCB0byAuUmVudmlyb24pCkhFUkVfQVBJX0tFWSA8LSAieW91cl9oZXJlX2FwaV9rZXlfaGVyZSIKCiMgVmVyaWZ5IEFQSSBhY2Nlc3MKaGVyZV9zdGF0dXMgPC0gaHR0cjo6R0VUKCJodHRwczovL2dlb2NvZGVyLmxzLmhlcmVhcGkuY29tLzYuMi9nZW9jb2RlLmpzb24iLAogICAgICAgICAgICAgICAgICAgICAgICBxdWVyeSA9IGxpc3QoYXBpS2V5ID0gSEVSRV9BUElfS0VZLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlYXJjaHRleHQgPSAidGVzdCIpKQpgYGAKCiMjIyBDZW5zdXMgQVBJIFNldHVwCgpgYGAgcgojIEluc3RhbGwgdGlkeWNlbnN1cyBpZiBub3QgYWxyZWFkeSBpbnN0YWxsZWQKaWYgKCFyZXF1aXJlKHRpZHljZW5zdXMpKSBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5Y2Vuc3VzIikKCiMgU2V0IENlbnN1cyBBUEkga2V5CmNlbnN1c19hcGlfa2V5KCJ5b3VyX2NlbnN1c19hcGlfa2V5X2hlcmUiLCBpbnN0YWxsID0gVFJVRSkKYGBgCgojIyMgQVBJIEtleSBTZXR1cDoKCjEuICAqKkhFUkUgTWFwcyBBUEkqKjoKICAgIC0gICBSZWdpc3RlciBhdCA8aHR0cHM6Ly9kZXZlbG9wZXIuaGVyZS5jb20vPgogICAgLSAgIENyZWF0ZSBwcm9qZWN0LCBnZW5lcmF0ZSBBUEkga2V5CiAgICAtICAgQWRkIHRvIGAuUmVudmlyb25gOiBgSEVSRV9BUElfS0VZPXlvdXJfa2V5X2hlcmVgCjIuICAqKkNlbnN1cyBCdXJlYXUgQVBJKio6CiAgICAtICAgUmVnaXN0ZXIgYXQgPGh0dHBzOi8vYXBpLmNlbnN1cy5nb3YvZGF0YS9rZXlfc2lnbnVwLmh0bWw+CiAgICAtICAgQWRkIHRvIGAuUmVudmlyb25gOiBgQ0VOU1VTX0FQSV9LRVk9eW91cl9rZXlfaGVyZWAKCiMjIyBEYXRhIFN0b3JhZ2UKCi0gICBHaXRIdWIgTEZTIChMYXJnZSBGaWxlIFN0b3JhZ2UpIGZvciBtYW5hZ2luZyBsYXJnZSBmaWxlcwotICAgRHVja0RCIGZvciBlZmZpY2llbnQgZGF0YSBxdWVyeWluZwotICAgUG9zdGdyZVNRTCBkYXRhYmFzZSBmb3IgeWVhci1zcGVjaWZpYyBwaHlzaWNpYW4gZGF0YQoKIyMjIEF1eGlsaWFyeSBUb29scwoKLSAgIHR5bGVyIHBhY2thZ2U6IEN1c3RvbSBwYWNrYWdlIGZvciBwcm9qZWN0LXNwZWNpZmljIGZ1bmN0aW9ucwotICAgRXhwbG9yYXRvcnkuaW86IFVzZWQgZm9yIGRhdGEgd3JhbmdsaW5nCgojIyBLZXkgT3V0cHV0cwoKLSAgIERyaXZlIHRpbWUgaXNvY2hyb25lcyBhdCBtdWx0aXBsZSB0aHJlc2hvbGRzICgzMCwgNjAsIDEyMCwgMTgwIG1pbnV0ZXMpCi0gICBQb3B1bGF0aW9uIHN0YXRpc3RpY3Mgd2l0aGluL291dHNpZGUgaXNvY2hyb25lcwotICAgRGVtb2dyYXBoaWMgYW5hbHlzaXMgYnkgcmFjZS9ldGhuaWNpdHkKLSAgIFRlbXBvcmFsIHRyZW5kcyBpbiBhY2Nlc3NpYmlsaXR5ICgyMDEzLTIwMjMpCi0gICBWaXN1YWxpemF0aW9ucyBvZiBnZW9ncmFwaGljIGFjY2VzcyBwYXR0ZXJucwoKIyMgRGF0YSBTb3VyY2VzCgpGb3IgZG93bmxvYWRpbmcgTlBQRVMgZmlsZXM6CgpgYGAgYmFzaAp3Z2V0IC1QICIvVm9sdW1lcy9WaWRlbyBQcm9qZWN0cyBNdWZmbHkgMS9ucHBlc19oaXN0b3JpY2FsX2Rvd25sb2FkcyIgImh0dHBzOi8vZG93bmxvYWQuY21zLmdvdi9ucHBlcy9OUFBFU19EYXRhX0Rpc3NlbWluYXRpb25fQXByaWxfMjAyNC56aXAiCmBgYAoKIyBEQVRBIFJFRkVSRU5DRVMKCmBgYHtyLCBpbmNsdWRlID0gVFJVRX0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyBDT1BZL1BBU1RFIFJFQURZIFJFRkVSRU5DRSBWQUxVRVMgLSBHWU5FQ09MT0dJQyBPTkNPTE9HWSBBQ0NFU1NJQklMSVRZIFBST0pFQ1QKIyBXSVRIIE9GRklDSUFMIFNPVVJDRVMgQU5EIENJVEFUSU9OUwojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKIyBUQVhPTk9NWSBDT0RFUyBGT1IgT0JHWU4gU1VCU1BFQ0lBTElTVFMKIyBTb3VyY2U6IE5hdGlvbmFsIFVuaWZvcm0gQ2xhaW0gQ29tbWl0dGVlIChOVUNDKSBIZWFsdGggQ2FyZSBQcm92aWRlciBUYXhvbm9teQojIFVSTDogaHR0cHM6Ly90YXhvbm9teS5udWNjLm9yZy8KIyBMYXN0IFVwZGF0ZWQ6IFZlcnNpb24gMjMuMSAoSnVseSAyMDIzKQpvYmd5bl90YXhvbm9teV9jb2RlcyA8LSBjKAogICIyMDdWMDAwMDBYIiwgICAgIyBPYnN0ZXRyaWNzICYgR3luZWNvbG9neSAoZ2VuZXJhbCkKICAiMjA3VlgwMjAxWCIsICAgICMgR3luZWNvbG9naWMgT25jb2xvZ3kgKFBSSU1BUlkgRk9DVVMpCiAgIjIwN1ZFMDEwMlgiLCAgICAjIFJlcHJvZHVjdGl2ZSBFbmRvY3Jpbm9sb2d5IGFuZCBJbmZlcnRpbGl0eQogICIyMDdWRzA0MDBYIiwgICAgIyBHeW5lY29sb2d5IChnZW5lcmFsKQogICIyMDdWTTAxMDFYIiwgICAgIyBNYXRlcm5hbCAmIEZldGFsIE1lZGljaW5lCiAgIjIwN1ZGMDA0MFgiLCAgICAjIEZlbWFsZSBQZWx2aWMgTWVkaWNpbmUvVXJvZ3luZWNvbG9neQogICIyMDdWQjAwMDJYIiwgICAgIyBCYXJpYXRyaWMgTWVkaWNpbmUKICAiMjA3VkMwMjAwWCIsICAgICMgQ3JpdGljYWwgQ2FyZSBNZWRpY2luZQogICIyMDdWQzAzMDBYIiwgICAgIyBDb21wbGV4IEZhbWlseSBQbGFubmluZwogICIyMDdWSDAwMDJYIiwgICAgIyBIb3NwaWNlIGFuZCBQYWxsaWF0aXZlIE1lZGljaW5lCiAgIjIwN1ZYMDAwMFgiICAgICAjIE9ic3RldHJpY3Mgb25seQopCgojIFJVQ0EgQ09ERVMgKFJVUkFMLVVSQkFOIENPTU1VVElORyBBUkVBUykKIyBTb3VyY2U6IFVTREEgRWNvbm9taWMgUmVzZWFyY2ggU2VydmljZQojIFVSTDogaHR0cHM6Ly93d3cuZXJzLnVzZGEuZ292L2RhdGEtcHJvZHVjdHMvcnVyYWwtdXJiYW4tY29tbXV0aW5nLWFyZWEtY29kZXMvCiMgUHVibGljYXRpb246ICJSdXJhbC1VcmJhbiBDb21tdXRpbmcgQXJlYSBDb2RlcyIgKDIwMTAgQ2Vuc3VzLWJhc2VkLCBtb3N0IHJlY2VudCkKIyBDaXRhdGlvbjogVVNEQSBFUlMuIFJ1cmFsLVVyYmFuIENvbW11dGluZyBBcmVhIENvZGVzLiBXYXNoaW5ndG9uLCBEQzogRWNvbm9taWMgUmVzZWFyY2ggU2VydmljZTsgMjAxMy4KcnVjYV9jb2Rlc19hbGwgPC0gYygxLjAsIDEuMSwgMi4wLCAyLjEsIDMuMCwgNC4xLCA0LjIsIDUuMCwgNS4xLCA2LjAsIDYuMSwgCiAgICAgICAgICAgICAgICAgICA3LjAsIDcuMSwgNy4yLCA3LjMsIDcuNCwgOC4wLCA4LjEsIDguMiwgOC4zLCA4LjQsIDkuMCwgCiAgICAgICAgICAgICAgICAgICAxMC4wLCAxMC4xLCAxMC4yLCAxMC4zLCAxMC40LCAxMC41LCAxMC42KQoKIyBSVUNBIFNJTVBMSUZJRUQgQ0FURUdPUklFUwojIFNvdXJjZTogSGFydCBMRywgTGFyc29uIEVILCBMaXNobmVyIERNLiBSdXJhbCBkZWZpbml0aW9ucyBmb3IgaGVhbHRoIHBvbGljeSByZXNlYXJjaC4gCiMgQW0gSiBQdWJsaWMgSGVhbHRoLiAyMDA1Ozk1KDcpOjExNDktMTE1NS4KIyBBbHNvOiBNb3JyaWxsIFIsIENyb21hcnRpZSBKLCBIYXJ0IEcuIE1ldHJvcG9saXRhbiwgdXJiYW4sIGFuZCBydXJhbCBjb21tdXRpbmcgYXJlYXM6IAojIHRvd2FyZCBhIGJldHRlciBkZXBpY3Rpb24gb2YgdGhlIFVuaXRlZCBTdGF0ZXMgc2V0dGxlbWVudCBzeXN0ZW0uIFVyYmFuIEdlb2dyYXBoeS4gMTk5OTsyMCg4KTo3MjctNzQ4LgpydWNhX21ldHJvcG9saXRhbiA8LSBjKDEuMCwgMS4xLCAyLjAsIDIuMSwgMy4wKSAgICAgICAjIExhcmdlIG1ldHJvIGFyZWFzCnJ1Y2FfbWljcm9wb2xpdGFuIDwtIGMoNC4xLCA0LjIsIDUuMCwgNS4xLCA2LjAsIDYuMSkgICMgTWlkLXNpemUgY2l0aWVzICAKcnVjYV9zbWFsbF90b3duIDwtIGMoNy4wLCA3LjEsIDcuMiwgNy4zLCA3LjQsIDguMCwgOC4xLCA4LjIsIDguMywgOC40KSAgIyBTbWFsbCB0b3ducwpydWNhX3J1cmFsIDwtIGMoOS4wLCAxMC4wLCAxMC4xLCAxMC4yLCAxMC4zLCAxMC40LCAxMC41LCAxMC42KSAgIyBSdXJhbCBhcmVhcwoKIyBVUyBDRU5TVVMgUkVHSU9OUyBBTkQgRElWSVNJT05TCiMgU291cmNlOiBVUyBDZW5zdXMgQnVyZWF1IEdlb2dyYXBoeSBEaXZpc2lvbgojIFVSTDogaHR0cHM6Ly93d3cyLmNlbnN1cy5nb3YvZ2VvL3BkZnMvbWFwcy1kYXRhL21hcHMvcmVmZXJlbmNlL3VzX3JlZ2Rpdi5wZGYKIyBQdWJsaWNhdGlvbjogIkdlb2dyYXBoaWMgQXJlYXMgUmVmZXJlbmNlIE1hbnVhbCIgQ2hhcHRlciA2CiMgQ2l0YXRpb246IFVTIENlbnN1cyBCdXJlYXUuIEdlb2dyYXBoaWMgQXJlYXMgUmVmZXJlbmNlIE1hbnVhbC4gV2FzaGluZ3RvbiwgREM6IFVTIENlbnN1cyBCdXJlYXU7IDE5OTQuCiMgT2ZmaWNpYWwgRGVmaW5pdGlvbjogVGl0bGUgMTMsIFVuaXRlZCBTdGF0ZXMgQ29kZSwgU2VjdGlvbiA0CmNlbnN1c19yZWdpb25zIDwtIGMoIk5vcnRoZWFzdCIsICJNaWR3ZXN0IiwgIlNvdXRoIiwgIldlc3QiKQpjZW5zdXNfZGl2aXNpb25zIDwtIGMoIk5ldyBFbmdsYW5kIiwgIk1pZGRsZSBBdGxhbnRpYyIsICJFYXN0IE5vcnRoIENlbnRyYWwiLCAKICAgICAgICAgICAgICAgICAgICAgIldlc3QgTm9ydGggQ2VudHJhbCIsICJTb3V0aCBBdGxhbnRpYyIsICJFYXN0IFNvdXRoIENlbnRyYWwiLAogICAgICAgICAgICAgICAgICAgICAiV2VzdCBTb3V0aCBDZW50cmFsIiwgIk1vdW50YWluIiwgIlBhY2lmaWMiKQoKIyBTVEFURSBBQkJSRVZJQVRJT05TIEJZIENFTlNVUyBSRUdJT04KIyBTb3VyY2U6IFVTIENlbnN1cyBCdXJlYXUsIEdlb2dyYXBoeSBEaXZpc2lvbgojIFVSTDogaHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9yZWZlcmVuY2UtZmlsZXMvMjAxMC9nZW8vc3RhdGUtYXJlYS5odG1sCiMgTm90ZTogRXN0YWJsaXNoZWQgYnkgRmVkZXJhbCBJbmZvcm1hdGlvbiBQcm9jZXNzaW5nIFN0YW5kYXJkcyAoRklQUykgUHVibGljYXRpb24gNS0yCm5vcnRoZWFzdF9zdGF0ZXMgPC0gYygiQ1QiLCAiTUUiLCAiTUEiLCAiTkgiLCAiUkkiLCAiVlQiLCAiTkoiLCAiTlkiLCAiUEEiKQptaWR3ZXN0X3N0YXRlcyA8LSBjKCJJTCIsICJJTiIsICJNSSIsICJPSCIsICJXSSIsICJJQSIsICJLUyIsICJNTiIsICJNTyIsICJORSIsICJORCIsICJTRCIpCnNvdXRoX3N0YXRlcyA8LSBjKCJERSIsICJGTCIsICJHQSIsICJNRCIsICJOQyIsICJTQyIsICJWQSIsICJXViIsICJEQyIsICJBTCIsICJLWSIsICJNUyIsICJUTiIsICJBUiIsICJMQSIsICJPSyIsICJUWCIpCndlc3Rfc3RhdGVzIDwtIGMoIkFaIiwgIkNPIiwgIklEIiwgIk1UIiwgIk5WIiwgIk5NIiwgIlVUIiwgIldZIiwgIkFLIiwgIkNBIiwgIkhJIiwgIk9SIiwgIldBIikKCiMgQUNPRyBESVNUUklDVFMgQlkgU1RBVEUKIyBTb3VyY2U6IEFtZXJpY2FuIENvbGxlZ2Ugb2YgT2JzdGV0cmljaWFucyBhbmQgR3luZWNvbG9naXN0cwojIFVSTDogaHR0cHM6Ly93d3cuYWNvZy5vcmcvYWJvdXQvZGlzdHJpY3RzLWFuZC1zZWN0aW9ucwojIFB1YmxpY2F0aW9uOiBBQ09HIE9yZ2FuaXphdGlvbiBNYW51YWwsIGN1cnJlbnQgYXMgb2YgMjAyMwojIENpdGF0aW9uOiBBbWVyaWNhbiBDb2xsZWdlIG9mIE9ic3RldHJpY2lhbnMgYW5kIEd5bmVjb2xvZ2lzdHMuIERpc3RyaWN0IE9yZ2FuaXphdGlvbi4gV2FzaGluZ3RvbiwgREM6IEFDT0c7IDIwMjMuCmFjb2dfZGlzdHJpY3RfMSA8LSBjKCJDVCIsICJNRSIsICJNQSIsICJOSCIsICJSSSIsICJWVCIpICAjIE5ldyBFbmdsYW5kCmFjb2dfZGlzdHJpY3RfMiA8LSBjKCJOWSIpICAjIE5ldyBZb3JrIE1ldHJvCmFjb2dfZGlzdHJpY3RfMyA8LSBjKCJERSIsICJOSiIsICJQQSIpICAjIE1pZC1BdGxhbnRpYwphY29nX2Rpc3RyaWN0XzQgPC0gYygiREMiLCAiTUQiLCAiVkEiLCAiV1YiKSAgIyBTb3V0aGVhc3QKYWNvZ19kaXN0cmljdF81IDwtIGMoIkFMIiwgIkZMIiwgIkdBIiwgIk1TIiwgIlNDIiwgIlROIikgICMgU291dGhlYXN0CmFjb2dfZGlzdHJpY3RfNiA8LSBjKCJJTCIsICJJTiIsICJJQSIsICJLWSIsICJNTiIsICJNTyIsICJORSIsICJORCIsICJPSCIsICJTRCIsICJXSSIpICAjIE1pZHdlc3QvUGxhaW5zCmFjb2dfZGlzdHJpY3RfNyA8LSBjKCJBWiIsICJDTyIsICJOViIsICJOTSIsICJVVCIsICJXWSIpICAjIE1vdW50YWluIFdlc3QKYWNvZ19kaXN0cmljdF84IDwtIGMoIkFLIiwgIklEIiwgIk1UIiwgIk9SIiwgIldBIikgICMgUGFjaWZpYyBOb3J0aHdlc3QKYWNvZ19kaXN0cmljdF85IDwtIGMoIkNBIiwgIkhJIikgICMgUGFjaWZpYyBXZXN0CmFjb2dfZGlzdHJpY3RfMTAgPC0gYygiQVIiLCAiS1MiLCAiTEEiLCAiT0siLCAiVFgiKSAgIyBTb3V0aCBDZW50cmFsCmFjb2dfZGlzdHJpY3RfMTEgPC0gYygiTUkiLCAiTkMiKSAgIyBHcmVhdCBMYWtlcy9Tb3V0aGVhc3QKCiMgQUxMIFVTIFNUQVRFUyBBTkQgVEVSUklUT1JJRVMKIyBTb3VyY2U6IEZlZGVyYWwgSW5mb3JtYXRpb24gUHJvY2Vzc2luZyBTdGFuZGFyZHMgKEZJUFMpIFB1YmxpY2F0aW9uIDUtMgojIFVSTDogaHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9saWJyYXJ5L3JlZmVyZW5jZS9jb2RlLWxpc3RzL2Fuc2kuaHRtbAojIENpdGF0aW9uOiBOYXRpb25hbCBJbnN0aXR1dGUgb2YgU3RhbmRhcmRzIGFuZCBUZWNobm9sb2d5LiBGSVBTIFBVQiA1LTI6IENvZGVzIGZvciB0aGUgSWRlbnRpZmljYXRpb24gb2YgdGhlIFN0YXRlcy4gR2FpdGhlcnNidXJnLCBNRDogTklTVDsgMTk4Ny4KYWxsX3N0YXRlcyA8LSBjKCJBTCIsICJBSyIsICJBWiIsICJBUiIsICJDQSIsICJDTyIsICJDVCIsICJERSIsICJGTCIsICJHQSIsIAogICAgICAgICAgICAgICAiSEkiLCAiSUQiLCAiSUwiLCAiSU4iLCAiSUEiLCAiS1MiLCAiS1kiLCAiTEEiLCAiTUUiLCAiTUQiLAogICAgICAgICAgICAgICAiTUEiLCAiTUkiLCAiTU4iLCAiTVMiLCAiTU8iLCAiTVQiLCAiTkUiLCAiTlYiLCAiTkgiLCAiTkoiLAogICAgICAgICAgICAgICAiTk0iLCAiTlkiLCAiTkMiLCAiTkQiLCAiT0giLCAiT0siLCAiT1IiLCAiUEEiLCAiUkkiLCAiU0MiLCAKICAgICAgICAgICAgICAgIlNEIiwgIlROIiwgIlRYIiwgIlVUIiwgIlZUIiwgIlZBIiwgIldBIiwgIldWIiwgIldJIiwgIldZIiwgIkRDIikKCnVzX3RlcnJpdG9yaWVzIDwtIGMoIkFTIiwgIkdVIiwgIk1QIiwgIlBSIiwgIlZJIikgICMgQW1lcmljYW4gU2Ftb2EsIEd1YW0sIE4uIE1hcmlhbmEgSXNsYW5kcywgUHVlcnRvIFJpY28sIFZpcmdpbiBJc2xhbmRzCgojIFNUQVRFIEZJUFMgQ09ERVMKIyBTb3VyY2U6IEZlZGVyYWwgSW5mb3JtYXRpb24gUHJvY2Vzc2luZyBTdGFuZGFyZHMgKEZJUFMpIFB1YmxpY2F0aW9uIDUtMgojIFVSTDogaHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9saWJyYXJ5L3JlZmVyZW5jZS9jb2RlLWxpc3RzL2Fuc2kuaHRtbAojIENpdGF0aW9uOiBTYW1lIGFzIGFib3ZlCnN0YXRlX2ZpcHMgPC0gYygiMDEiLCAiMDIiLCAiMDQiLCAiMDUiLCAiMDYiLCAiMDgiLCAiMDkiLCAiMTAiLCAiMTIiLCAiMTMiLAogICAgICAgICAgICAgICAiMTUiLCAiMTYiLCAiMTciLCAiMTgiLCAiMTkiLCAiMjAiLCAiMjEiLCAiMjIiLCAiMjMiLCAiMjQiLCAKICAgICAgICAgICAgICAgIjI1IiwgIjI2IiwgIjI3IiwgIjI4IiwgIjI5IiwgIjMwIiwgIjMxIiwgIjMyIiwgIjMzIiwgIjM0IiwKICAgICAgICAgICAgICAgIjM1IiwgIjM2IiwgIjM3IiwgIjM4IiwgIjM5IiwgIjQwIiwgIjQxIiwgIjQyIiwgIjQ0IiwgIjQ1IiwKICAgICAgICAgICAgICAgIjQ2IiwgIjQ3IiwgIjQ4IiwgIjQ5IiwgIjUwIiwgIjUxIiwgIjUzIiwgIjU0IiwgIjU1IiwgIjU2IiwgIjExIikKCiMgUkVGRVJFTkNFIERBVEVTIC0gVEhJUkQgRlJJREFZIE9DVE9CRVIgOUFNICgyMDEzLTIwMjMpCiMgU291cmNlOiBQcm9qZWN0IG1ldGhvZG9sb2d5IGRlY2lzaW9uCiMgUmF0aW9uYWxlOiBTdGFuZGFyZGl6ZWQgd2Vla2RheSBtb3JuaW5nIHRpbWUgdG8gYXZvaWQgcnVzaCBob3VyIHBlYWtzIGFuZCBlbnN1cmUgY29uc2lzdGVuY3kKIyBDaXRhdGlvbjogTXVmZmx5IFQuIEd5bmVjb2xvZ2ljIE9uY29sb2d5IEFjY2Vzc2liaWxpdHkgUHJvamVjdCBNZXRob2RvbG9neS4gMjAyNC4KcmVmZXJlbmNlX2RhdGVzXzIwMTNfMjAyMyA8LSBjKAogICIyMDEzLTEwLTE4IiwgIjIwMTQtMTAtMTciLCAiMjAxNS0xMC0xNiIsICIyMDE2LTEwLTIxIiwgIjIwMTctMTAtMjAiLAogICIyMDE4LTEwLTE5IiwgIjIwMTktMTAtMTgiLCAiMjAyMC0xMC0xNiIsICIyMDIxLTEwLTE1IiwgIjIwMjItMTAtMjEiLCAiMjAyMy0xMC0yMCIKKQoKIyBJU08gREFURVRJTUUgRk9STUFUIEZPUiBBUEkgQ0FMTFMKIyBTb3VyY2U6IElTTyA4NjAxIFN0YW5kYXJkIGZvciBkYXRlL3RpbWUgcmVwcmVzZW50YXRpb24KIyBVUkw6IGh0dHBzOi8vd3d3Lmlzby5vcmcvaXNvLTg2MDEtZGF0ZS1hbmQtdGltZS1mb3JtYXQuaHRtbAppc29fZGF0ZXRpbWVfMjAxM18yMDIzIDwtIGMoCiAgIjIwMTMtMTAtMThUMDk6MDA6MDAiLCAiMjAxNC0xMC0xN1QwOTowMDowMCIsICIyMDE1LTEwLTE2VDA5OjAwOjAwIiwKICAiMjAxNi0xMC0yMVQwOTowMDowMCIsICIyMDE3LTEwLTIwVDA5OjAwOjAwIiwgIjIwMTgtMTAtMTlUMDk6MDA6MDAiLAogICIyMDE5LTEwLTE4VDA5OjAwOjAwIiwgIjIwMjAtMTAtMTZUMDk6MDA6MDAiLCAiMjAyMS0xMC0xNVQwOTowMDowMCIsIAogICIyMDIyLTEwLTIxVDA5OjAwOjAwIiwgIjIwMjMtMTAtMjBUMDk6MDA6MDAiCikKCiMgRFJJVkUgVElNRSBUSFJFU0hPTERTCiMgU291cmNlOiBIZWFsdGhjYXJlIGFjY2Vzc2liaWxpdHkgbGl0ZXJhdHVyZSBzdGFuZGFyZHMKIyBDaXRhdGlvbnM6IAojIC0gUGVuY2hhbnNreSBSLCBUaG9tYXMgSlcuIFRoZSBjb25jZXB0IG9mIGFjY2VzczogZGVmaW5pdGlvbiBhbmQgcmVsYXRpb25zaGlwIHRvIGNvbnN1bWVyIHNhdGlzZmFjdGlvbi4gTWVkIENhcmUuIDE5ODE7MTkoMik6MTI3LTE0MC4KIyAtIFdhbmcgRiwgTHVvIFcuIEFzc2Vzc2luZyBzcGF0aWFsIGFuZCBub25zcGF0aWFsIGZhY3RvcnMgZm9yIGhlYWx0aGNhcmUgYWNjZXNzOiB0b3dhcmRzIGFuIGludGVncmF0ZWQgYXBwcm9hY2ggdG8gZGVmaW5pbmcgaGVhbHRoIHByb2Zlc3Npb25hbCBzaG9ydGFnZSBhcmVhcy4gSGVhbHRoIFBsYWNlLiAyMDA1OzExKDIpOjEzMS0xNDYuCmRyaXZlX3RpbWVzX21pbnV0ZXMgPC0gYygzMCwgNjAsIDEyMCwgMTgwKQpkcml2ZV90aW1lc19zZWNvbmRzIDwtIGMoMTgwMCwgMzYwMCwgNzIwMCwgMTA4MDApICAjIEZvciBIRVJFIEFQSQoKIyBDT09SRElOQVRFIFJFRkVSRU5DRSBTWVNURU1TIChFUFNHIENPREVTKQojIFNvdXJjZTogRXVyb3BlYW4gUGV0cm9sZXVtIFN1cnZleSBHcm91cCAoRVBTRykgR2VvZGV0aWMgUGFyYW1ldGVyIERhdGFzZXQKIyBVUkw6IGh0dHBzOi8vZXBzZy5vcmcvCiMgQ2l0YXRpb246IEVQU0cuIEVQU0cgR2VvZGV0aWMgUGFyYW1ldGVyIERhdGFzZXQuIE9pbCAmIEdhcyBQcm9kdWNlcnMgQXNzb2NpYXRpb247IDIwMjMuCmVwc2dfd2dzODQgPC0gNDMyNiAgICAgICAgICAjIFdHUzg0IEdlb2dyYXBoaWMgKGlucHV0IGNvb3JkaW5hdGVzKQplcHNnX3dlYl9tZXJjYXRvciA8LSAzODU3ICAgIyBXZWIgTWVyY2F0b3IgKHdlYiBkaXNwbGF5KQplcHNnX3VzX2FsYmVycyA8LSA1MDcwICAgICAgIyBVUyBBbGJlcnMgRXF1YWwgQXJlYSAoYW5hbHlzaXMpCmVwc2dfYWxhc2thX2FsYmVycyA8LSAzMzM4ICAjIEFsYXNrYSBBbGJlcnMKZXBzZ19oYXdhaWlfYWxiZXJzIDwtIDQxMzUgICMgSGF3YWlpIEFsYmVycwoKIyBDRU5TVVMgVkFSSUFCTEVTIChBQ1MgNS1ZRUFSKQojIFNvdXJjZTogVVMgQ2Vuc3VzIEJ1cmVhdSBBbWVyaWNhbiBDb21tdW5pdHkgU3VydmV5CiMgVVJMOiBodHRwczovL3d3dy5jZW5zdXMuZ292L3Byb2dyYW1zLXN1cnZleXMvYWNzL2d1aWRhbmNlL3N1YmplY3RzLmh0bWwKIyBQdWJsaWNhdGlvbjogQW1lcmljYW4gQ29tbXVuaXR5IFN1cnZleSBTdWJqZWN0IERlZmluaXRpb25zCiMgQ2l0YXRpb246IFVTIENlbnN1cyBCdXJlYXUuIEFtZXJpY2FuIENvbW11bml0eSBTdXJ2ZXkgU3ViamVjdCBEZWZpbml0aW9ucy4gV2FzaGluZ3RvbiwgREM6IFVTIENlbnN1cyBCdXJlYXU7IDIwMjEuCmNlbnN1c190b3RhbF9wb3B1bGF0aW9uIDwtICJCMDEwMDNfMDAxIgpjZW5zdXNfZmVtYWxlX3BvcHVsYXRpb24gPC0gIkIwMTAwMV8wMjYiCmNlbnN1c193aGl0ZV9hbG9uZSA8LSAiQjAzMDAyXzAwMyIKY2Vuc3VzX2JsYWNrX2Fsb25lIDwtICJCMDMwMDJfMDA0IgpjZW5zdXNfYXNpYW5fYWxvbmUgPC0gIkIwMzAwMl8wMDYiCmNlbnN1c19haWFuX2Fsb25lIDwtICJCMDMwMDJfMDA1IiAgIyBBbWVyaWNhbiBJbmRpYW4vQWxhc2thIE5hdGl2ZQpjZW5zdXNfbWVkaWFuX2luY29tZSA8LSAiQjE5MDEzXzAwMSIKY2Vuc3VzX2hvdXNpbmdfdW5pdHMgPC0gIkIyNTAwMV8wMDEiCgojIEhFUkUgQVBJIEVORFBPSU5UUwojIFNvdXJjZTogSEVSRSBUZWNobm9sb2dpZXMgRGV2ZWxvcGVyIERvY3VtZW50YXRpb24KIyBVUkw6IGh0dHBzOi8vZGV2ZWxvcGVyLmhlcmUuY29tL2RvY3VtZW50YXRpb24vCiMgQ2l0YXRpb246IEhFUkUgVGVjaG5vbG9naWVzLiBIRVJFIFBsYXRmb3JtIERldmVsb3BlciBHdWlkZS4gRWluZGhvdmVuLCBOZXRoZXJsYW5kczogSEVSRTsgMjAyMy4KaGVyZV9nZW9jb2RpbmdfdXJsIDwtICJodHRwczovL2dlb2NvZGVyLmxzLmhlcmVhcGkuY29tLzYuMi9nZW9jb2RlLmpzb24iCmhlcmVfcmV2ZXJzZV9nZW9jb2RpbmdfdXJsIDwtICJodHRwczovL3JldmVyc2UuZ2VvY29kZXIubHMuaGVyZWFwaS5jb20vNi4yL3JldmVyc2VnZW9jb2RlLmpzb24iCmhlcmVfaXNvbGluZV91cmwgPC0gImh0dHBzOi8vaXNvbGluZS5yb3V0ZS5scy5oZXJlYXBpLmNvbS9yb3V0aW5nLzcuMi9jYWxjdWxhdGVpc29saW5lLmpzb24iCgojIEhFUkUgQVBJIFBBUkFNRVRFUlMKIyBTb3VyY2U6IEhFUkUgUm91dGluZyBBUEkgRG9jdW1lbnRhdGlvbgojIFVSTDogaHR0cHM6Ly9kZXZlbG9wZXIuaGVyZS5jb20vZG9jdW1lbnRhdGlvbi9yb3V0aW5nLWFwaS9kZXZfZ3VpZGUvdG9waWNzL3Jlc291cmNlLWNhbGN1bGF0ZS1pc29saW5lLmh0bWwKaGVyZV9pc29saW5lX21vZGUgPC0gImNhciIKaGVyZV9pc29saW5lX3RyYWZmaWMgPC0gImVuYWJsZWQiCmhlcmVfaXNvbGluZV9yYW5nZXR5cGUgPC0gInRpbWUiCmhlcmVfaXNvbGluZV9yZXNvbHV0aW9uIDwtIDEgICAgIyBIaWdoZXN0IHJlc29sdXRpb24KaGVyZV9pc29saW5lX21heHBvaW50cyA8LSAxMDAwICAjIE1heGltdW0gcG9seWdvbiBwb2ludHMKaGVyZV9pc29saW5lX3F1YWxpdHkgPC0gMSAgICAgICAjIEhpZ2hlc3QgcXVhbGl0eQoKIyBVUyBUSU1FWk9ORVMKIyBTb3VyY2U6IEludGVybmV0IEFzc2lnbmVkIE51bWJlcnMgQXV0aG9yaXR5IChJQU5BKSBUaW1lIFpvbmUgRGF0YWJhc2UKIyBVUkw6IGh0dHBzOi8vd3d3LmlhbmEub3JnL3RpbWUtem9uZXMKIyBDaXRhdGlvbjogSUFOQS4gVGltZSBab25lIERhdGFiYXNlLiBJbnRlcm5ldCBBc3NpZ25lZCBOdW1iZXJzIEF1dGhvcml0eTsgMjAyMy4KdXNfdGltZXpvbmVzIDwtIGMoIkFtZXJpY2EvTmV3X1lvcmsiLCAiQW1lcmljYS9DaGljYWdvIiwgIkFtZXJpY2EvRGVudmVyIiwgCiAgICAgICAgICAgICAgICAgIkFtZXJpY2EvTG9zX0FuZ2VsZXMiLCAiQW1lcmljYS9BbmNob3JhZ2UiLCAiUGFjaWZpYy9Ib25vbHVsdSIpCnRpbWV6b25lX25hbWVzIDwtIGMoIkVhc3Rlcm4iLCAiQ2VudHJhbCIsICJNb3VudGFpbiIsICJQYWNpZmljIiwgIkFsYXNrYSIsICJIYXdhaWkiKQoKIyBNQUpPUiBNRVRST1BPTElUQU4gQVJFQVMgKENCU0FzKQojIFNvdXJjZTogT2ZmaWNlIG9mIE1hbmFnZW1lbnQgYW5kIEJ1ZGdldAojIFVSTDogaHR0cHM6Ly93d3cud2hpdGVob3VzZS5nb3Yvb21iL21hbmFnZW1lbnQvb2ZmaWNlLWZlZGVyYWwtZmluYW5jaWFsLW1hbmFnZW1lbnQvCiMgUHVibGljYXRpb246IE9NQiBCdWxsZXRpbiBOby4gMjAtMDEgKE1hcmNoIDYsIDIwMjApCiMgQ2l0YXRpb246IE9mZmljZSBvZiBNYW5hZ2VtZW50IGFuZCBCdWRnZXQuIFJldmlzZWQgRGVsaW5lYXRpb25zIG9mIE1ldHJvcG9saXRhbiBTdGF0aXN0aWNhbCBBcmVhcywgTWljcm9wb2xpdGFuIFN0YXRpc3RpY2FsIEFyZWFzLCBhbmQgQ29tYmluZWQgU3RhdGlzdGljYWwgQXJlYXMuIFdhc2hpbmd0b24sIERDOiBPTUI7IDIwMjAuCm1ham9yX2Nic2FfY29kZXMgPC0gYygiMzU2MjAiLCAiMzEwODAiLCAiMTY5ODAiLCAiMTkxMDAiLCAiMjY0MjAiLCAiMzM0NjAiLCAiMzc5ODAiLCAKICAgICAgICAgICAgICAgICAgICAgIjQwMTQwIiwgIjQxODYwIiwgIjQ3OTAwIiwgIjEyMDYwIiwgIjE0NDYwIiwgIjQxNzQwIiwgIjM4MDYwIikKCm1ham9yX21zYV9uYW1lcyA8LSBjKAogICJOZXcgWW9yay1OZXdhcmstSmVyc2V5IENpdHksIE5ZLU5KLVBBIiwKICAiTG9zIEFuZ2VsZXMtTG9uZyBCZWFjaC1BbmFoZWltLCBDQSIsIAogICJDaGljYWdvLU5hcGVydmlsbGUtRWxnaW4sIElMLUlOLVdJIiwKICAiRGFsbGFzLUZvcnQgV29ydGgtQXJsaW5ndG9uLCBUWCIsCiAgIkhvdXN0b24tVGhlIFdvb2RsYW5kcy1TdWdhciBMYW5kLCBUWCIsCiAgIk1pYW1pLUZvcnQgTGF1ZGVyZGFsZS1XZXN0IFBhbG0gQmVhY2gsIEZMIiwKICAiUGhpbGFkZWxwaGlhLUNhbWRlbi1XaWxtaW5ndG9uLCBQQS1OSi1ERS1NRCIsCiAgIlJpdmVyc2lkZS1TYW4gQmVybmFyZGluby1PbnRhcmlvLCBDQSIsCiAgIlNhbiBGcmFuY2lzY28tT2FrbGFuZC1IYXl3YXJkLCBDQSIsCiAgIldhc2hpbmd0b24tQXJsaW5ndG9uLUFsZXhhbmRyaWEsIERDLVZBLU1ELVdWIiwKICAiQXRsYW50YS1TYW5keSBTcHJpbmdzLVJvc3dlbGwsIEdBIiwgCiAgIkJvc3Rvbi1DYW1icmlkZ2UtTmV3dG9uLCBNQS1OSCIsCiAgIlNhbiBBbnRvbmlvLU5ldyBCcmF1bmZlbHMsIFRYIiwKICAiUGhvZW5peC1NZXNhLVNjb3R0c2RhbGUsIEFaIgopCgojIE1BSk9SIElOVEVSU1RBVEUgSElHSFdBWVMKIyBTb3VyY2U6IEZlZGVyYWwgSGlnaHdheSBBZG1pbmlzdHJhdGlvbgojIFVSTDogaHR0cHM6Ly93d3cuZmh3YS5kb3QuZ292L3BsYW5uaW5nL25hdGlvbmFsX2hpZ2h3YXlfc3lzdGVtLwojIFB1YmxpY2F0aW9uOiBOYXRpb25hbCBIaWdod2F5IFN5c3RlbQojIENpdGF0aW9uOiBGZWRlcmFsIEhpZ2h3YXkgQWRtaW5pc3RyYXRpb24uIE5hdGlvbmFsIEhpZ2h3YXkgU3lzdGVtLiBXYXNoaW5ndG9uLCBEQzogVVMgRGVwYXJ0bWVudCBvZiBUcmFuc3BvcnRhdGlvbjsgMjAyMy4KCiMgRWFzdC1XZXN0IEludGVyc3RhdGVzCmludGVyc3RhdGVfZWFzdF93ZXN0IDwtIGMoIkktMTAiLCAiSS0yMCIsICJJLTMwIiwgIkktNDAiLCAiSS03MCIsICJJLTgwIiwgIkktOTAiKQoKIyBOb3J0aC1Tb3V0aCBJbnRlcnN0YXRlcyAgCmludGVyc3RhdGVfbm9ydGhfc291dGggPC0gYygiSS01IiwgIkktMTUiLCAiSS0yNSIsICJJLTM1IiwgIkktNjUiLCAiSS03NSIsICJJLTg1IiwgIkktOTUiKQoKIyBBbGwgTWFqb3IgSW50ZXJzdGF0ZXMKYWxsX21ham9yX2ludGVyc3RhdGVzIDwtIGMoaW50ZXJzdGF0ZV9lYXN0X3dlc3QsIGludGVyc3RhdGVfbm9ydGhfc291dGgpCgojIFZBTElEQVRJT04gVEhSRVNIT0xEUwojIFNvdXJjZTogUHJvamVjdCBxdWFsaXR5IGNvbnRyb2wgc3RhbmRhcmRzIGJhc2VkIG9uIGxpdGVyYXR1cmUgcmV2aWV3CiMgQ2l0YXRpb25zOgojIC0gQmFsZHdpbiBMTSwgZXQgYWwuIEFjY2VzcyB0byBzcGVjaWFsdHkgaGVhbHRoIGNhcmUgZm9yIHJ1cmFsIEFtZXJpY2FuIEluZGlhbnMgaW4gdGhlIG5vcnRod2VzdC4gTWVkIENhcmUuIDIwMDg7NDYoMTIpOjEyMTgtMTIyNC4KIyAtIE9uZWdhIFQsIGV0IGFsLiBHZW9ncmFwaGljIGFjY2VzcyB0byBjYW5jZXIgY2FyZSBpbiB0aGUgVS5TLiBDYW5jZXIuIDIwMDg7MTEyKDQpOjkwOS05MTguCm1pbl9wcm92aWRlcl9jb3VudCA8LSA0MDAwMCAgICAgICMgTWluaW11bSBOUFBFUyBwcm92aWRlcnMgZXhwZWN0ZWQKbWluX2d5bl9vbmNfY291bnQgPC0gMTAwMCAgICAgICAjIE1pbmltdW0gZ3luZWNvbG9naWMgb25jb2xvZ2lzdHMKbWluX2dlb2NvZGluZ19zdWNjZXNzIDwtIDAuODUgICAjIE1pbmltdW0gZ2VvY29kaW5nIHN1Y2Nlc3MgcmF0ZQptaW5faXNvY2hyb25lX3N1Y2Nlc3MgPC0gMC45MCAgICMgTWluaW11bSBpc29jaHJvbmUgZ2VuZXJhdGlvbiBzdWNjZXNzCm1pbl9wb3B1bGF0aW9uX2NvdmVyYWdlIDwtIDAuOTUgIyBNaW5pbXVtIGNlbnN1cyBwb3B1bGF0aW9uIGNvdmVyYWdlCgojIFFVQUxJVFkgQ09OVFJPTCBSQU5HRVMKIyBTb3VyY2U6IFVTIEdlb2xvZ2ljYWwgU3VydmV5IEdlb2dyYXBoaWMgTmFtZXMgSW5mb3JtYXRpb24gU3lzdGVtCiMgVVJMOiBodHRwczovL2dlb25hbWVzLnVzZ3MuZ292L2RvbWVzdGljLwojIENpdGF0aW9uOiBVUyBHZW9sb2dpY2FsIFN1cnZleS4gR2VvZ3JhcGhpYyBOYW1lcyBJbmZvcm1hdGlvbiBTeXN0ZW0uIFJlc3RvbiwgVkE6IFVTR1M7IDIwMjMuCm1heF9jb29yZGluYXRlX2xhdCA8LSA3MS41ICAgICAgIyBOb3J0aGVybm1vc3QgVVMgcG9pbnQgKEFsYXNrYSkKbWluX2Nvb3JkaW5hdGVfbGF0IDwtIDE4LjkgICAgICAjIFNvdXRoZXJubW9zdCBVUyBwb2ludCAoSGF3YWlpKSAKbWF4X2Nvb3JkaW5hdGVfbG9uIDwtIC02Ni45ICAgICAjIEVhc3Rlcm5tb3N0IFVTIHBvaW50IChNYWluZSkKbWluX2Nvb3JkaW5hdGVfbG9uIDwtIC0xNzkuMSAgICAjIFdlc3Rlcm5tb3N0IFVTIHBvaW50IChBbGFza2EpCgojIENFTlNVUyBHRU9HUkFQSFkgQ09VTlRTICgyMDIwIENlbnN1cykKIyBTb3VyY2U6IFVTIENlbnN1cyBCdXJlYXUgR2VvZ3JhcGh5IERpdmlzaW9uCiMgVVJMOiBodHRwczovL3d3dy5jZW5zdXMuZ292L2dlb2dyYXBoaWVzL3JlZmVyZW5jZS1maWxlcy8yMDIwL2dlby90YWxsaWVzLwojIFB1YmxpY2F0aW9uOiAyMDIwIENlbnN1cyBHZW9ncmFwaGljIFRhbGxpZXMKIyBDaXRhdGlvbjogVVMgQ2Vuc3VzIEJ1cmVhdS4gMjAyMCBDZW5zdXMgR2VvZ3JhcGhpYyBUYWxsaWVzLiBXYXNoaW5ndG9uLCBEQzogVVMgQ2Vuc3VzIEJ1cmVhdTsgMjAyMS4KY2Vuc3VzXzIwMjBfc3RhdGVzIDwtIDUxICAgICAgICAgICAjIDUwIHN0YXRlcyArIERDCmNlbnN1c18yMDIwX2NvdW50aWVzIDwtIDMxNDMgICAgICAgIyBUb3RhbCBjb3VudGllcwpjZW5zdXNfMjAyMF90cmFjdHMgPC0gODQ0MTQgICAgICAgICMgQ2Vuc3VzIHRyYWN0cwpjZW5zdXNfMjAyMF9ibG9ja19ncm91cHMgPC0gMjQyMzM1ICMgQmxvY2sgZ3JvdXBzCgojIEFQSSBSQVRFIExJTUlUUwojIFNvdXJjZTogSEVSRSBUZWNobm9sb2dpZXMgRGV2ZWxvcGVyIFBvcnRhbAojIFVSTDogaHR0cHM6Ly9kZXZlbG9wZXIuaGVyZS5jb20vcHJpY2luZwojIEN1cnJlbnQgYXMgb2Y6IDIwMjMKaGVyZV9nZW9jb2RpbmdfZnJlZV9saW1pdCA8LSAzMDAwMCAgICAjIFBlciBtb250aApoZXJlX2lzb2xpbmVfZnJlZV9saW1pdCA8LSAyNTAwICAgICAgICMgUGVyIG1vbnRoCmNlbnN1c19hcGlfZGFpbHlfbGltaXQgPC0gNTAwICAgICAgICAgIyBXaXRob3V0IEFQSSBrZXkKCiMgRElSRUNUT1JZIFNUUlVDVFVSRQojIFNvdXJjZTogUHJvamVjdCBvcmdhbml6YXRpb24gc3RhbmRhcmRzIGZvbGxvd2luZyBiZXN0IHByYWN0aWNlcwojIENpdGF0aW9uOiBXaWxzb24gRywgZXQgYWwuIEdvb2QgZW5vdWdoIHByYWN0aWNlcyBpbiBzY2llbnRpZmljIGNvbXB1dGluZy4gUExvUyBDb21wdXQgQmlvbC4gMjAxNzsxMyg2KTplMTAwNTUxMC4KZGlyX2RhdGFfcmF3IDwtICJkYXRhL3Jhdy8iCmRpcl9kYXRhX3Byb2Nlc3NlZCA8LSAiZGF0YS9wcm9jZXNzZWQvIgpkaXJfZGF0YV9nZW9jb2RlZCA8LSAiZGF0YS9nZW9jb2RlZC8iCmRpcl9kYXRhX3NwYXRpYWwgPC0gImRhdGEvc3BhdGlhbC8iCmRpcl9yZXN1bHRzIDwtICJyZXN1bHRzLyIKZGlyX2ZpZ3VyZXMgPC0gImZpZ3VyZXMvIgpkaXJfY2FjaGUgPC0gImNhY2hlLyIKYGBgCgojIFVSTCBSZWZlcmVuY2UgVGFibGUgLSBHeW5lY29sb2dpYyBPbmNvbG9neSBBY2Nlc3NpYmlsaXR5IFByb2plY3QKCiMjIERhdGEgU291cmNlcyAtIFByaW1hcnkKCnwgUmVzb3VyY2UgTmFtZSB8IFVSTCB8IERlc2NyaXB0aW9uIHwgQWNjZXNzIFR5cGUgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwKfCBOUFBFUyAoTmF0aW9uYWwgUGxhbiBhbmQgUHJvdmlkZXIgRW51bWVyYXRpb24gU3lzdGVtKSB8IDxodHRwczovL25wcGVzLmNtcy5oaHMuZ292Lz4gfCBQcmltYXJ5IHByb3ZpZGVyIHJlZ2lzdHJ5IHwgUHVibGljIHwKfCBOQkVSIE5QUEVTIEhpc3RvcmljYWwgRGF0YSB8IDxodHRwczovL3d3dy5uYmVyLm9yZy9yZXNlYXJjaC9kYXRhL25hdGlvbmFsLXBsYW4tYW5kLXByb3ZpZGVyLWVudW1lcmF0aW9uLXN5c3RlbS1ucHBlcy1kYXRhPiB8IEhpc3RvcmljYWwgcHJvdmlkZXIgZGF0YSAyMDA3LTIwMjIgfCBQdWJsaWMgfAp8IENNUyBNZWRpY2FyZSBQYXJ0IEQgUHJlc2NyaWJlciBEYXRhIHwgPGh0dHBzOi8vd3d3LmNtcy5nb3YvUmVzZWFyY2gtU3RhdGlzdGljcy1EYXRhLWFuZC1TeXN0ZW1zL1N0YXRpc3RpY3MtVHJlbmRzLWFuZC1SZXBvcnRzL01lZGljYXJlLVByb3ZpZGVyLUNoYXJnZS1EYXRhL1BhcnQtRC1QcmVzY3JpYmVyPiB8IEFubnVhbCBwcmVzY3JpYmluZyBwYXR0ZXJucyB8IFB1YmxpYyB8CnwgQ01TIFBoeXNpY2lhbiBDb21wYXJlIChIaXN0b3JpY2FsKSB8IDxodHRwczovL3d3dy5vcGVuaWNwc3Iub3JnL29wZW5pY3Bzci9wcm9qZWN0LzE0OTk2MS92ZXJzaW9uL1YxL3ZpZXc+IHwgSGlzdG9yaWNhbCBwaHlzaWNpYW4gZGF0YSB0aHJvdWdoIDIwMjAgfCBSZXF1aXJlcyBMb2dpbiB8CnwgQ01TIE9wZW4gUGF5bWVudHMgKFN1bnNoaW5lIEFjdCkgfCA8aHR0cHM6Ly9vcGVucGF5bWVudHNkYXRhLmNtcy5nb3YvPiB8IEluZHVzdHJ5IHBheW1lbnRzIHRvIHBoeXNpY2lhbnMgfCBQdWJsaWMgfAp8IENNUyBQcm92aWRlciBFbnJvbGxtZW50IERhdGEgfCA8aHR0cHM6Ly93d3cuY21zLmdvdi9SZXNlYXJjaC1TdGF0aXN0aWNzLURhdGEtYW5kLVN5c3RlbXMvU3RhdGlzdGljcy1UcmVuZHMtYW5kLVJlcG9ydHMvTWVkaWNhcmUtUHJvdmlkZXItQ2hhcmdlLURhdGE+IHwgUHJvdmlkZXIgZW5yb2xsbWVudCBhbmQgc3BlY2lhbHR5IHwgUHVibGljIHwKfCBOUFBFUyBEYXRhIERpc3NlbWluYXRpb24gfCA8aHR0cHM6Ly9kb3dubG9hZC5jbXMuZ292L25wcGVzL05QSV9GaWxlcy5odG1sPiB8IE1vbnRobHkgTlBQRVMgZGF0YSBkb3dubG9hZHMgfCBQdWJsaWMgfAp8IENNUyBEYXRhIE5hdmlnYXRvciB8IDxodHRwczovL3d3dy5jbXMuZ292L2RhdGEtcmVzZWFyY2gvc3RhdGlzdGljcy10cmVuZHMtYW5kLXJlcG9ydHMvY21zLWRhdGEtbmF2aWdhdG9yPiB8IENNUyBkYXRhIHBvcnRhbCBhbmQgbmF2aWdhdGlvbiB8IFB1YmxpYyB8CgojIyBDZW5zdXMgJiBHZW9ncmFwaGljIERhdGEKCnwgUmVzb3VyY2UgTmFtZSB8IFVSTCB8IERlc2NyaXB0aW9uIHwgQWNjZXNzIFR5cGUgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwKfCBVUyBDZW5zdXMgQnVyZWF1IEFQSSB8IDxodHRwczovL2FwaS5jZW5zdXMuZ292L2RhdGEuaHRtbD4gfCBNYWluIGNlbnN1cyBkYXRhIEFQSSBwb3J0YWwgfCBQdWJsaWMgfAp8IEFtZXJpY2FuIENvbW11bml0eSBTdXJ2ZXkgKEFDUykgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9wcm9ncmFtcy1zdXJ2ZXlzL2Fjcz4gfCBQb3B1bGF0aW9uIGFuZCBkZW1vZ3JhcGhpYyBkYXRhIHwgUHVibGljIHwKfCBUSUdFUi9MaW5lIFNoYXBlZmlsZXMgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9tYXBwaW5nLWZpbGVzL3RpbWUtc2VyaWVzL2dlby90aWdlci1saW5lLWZpbGUuaHRtbD4gfCBHZW9ncmFwaGljIGJvdW5kYXJ5IGZpbGVzIHwgUHVibGljIHwKfCBDZW5zdXMgR2VvZ3JhcGh5IFByb2R1Y3RzIHwgPGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvcHJvZ3JhbXMtc3VydmV5cy9nZW9ncmFwaHkuaHRtbD4gfCBHZW9ncmFwaGljIGNvbmNlcHRzIGFuZCBwcm9kdWN0cyB8IFB1YmxpYyB8CnwgUnVyYWwtVXJiYW4gQ29tbXV0aW5nIEFyZWEgQ29kZXMgfCA8aHR0cHM6Ly93d3cuZXJzLnVzZGEuZ292L2RhdGEtcHJvZHVjdHMvcnVyYWwtdXJiYW4tY29tbXV0aW5nLWFyZWEtY29kZXMvPiB8IFJVQ0EgY2xhc3NpZmljYXRpb24gc3lzdGVtIHwgUHVibGljIHwKfCBNZXRyb3BvbGl0YW4gU3RhdGlzdGljYWwgQXJlYXMgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9wcm9ncmFtcy1zdXJ2ZXlzL21ldHJvLW1pY3JvLmh0bWw+IHwgTVNBIGRlZmluaXRpb25zIGFuZCBkYXRhIHwgUHVibGljIHwKfCBDZW5zdXMgQVBJIEtleSBSZWdpc3RyYXRpb24gfCA8aHR0cHM6Ly9hcGkuY2Vuc3VzLmdvdi9kYXRhL2tleV9zaWdudXAuaHRtbD4gfCBGcmVlIEFQSSBrZXkgcmVnaXN0cmF0aW9uIHwgUmVnaXN0cmF0aW9uIHwKfCBGZWRlcmFsIEluZm9ybWF0aW9uIFByb2Nlc3NpbmcgU3RhbmRhcmRzIHwgPGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvbGlicmFyeS9yZWZlcmVuY2UvY29kZS1saXN0cy9hbnNpLmh0bWw+IHwgRklQUyBjb2RlcyBhbmQgc3RhbmRhcmRzIHwgUHVibGljIHwKCiMjIEFQSSBEb2N1bWVudGF0aW9uCgp8IFJlc291cmNlIE5hbWUgfCBVUkwgfCBEZXNjcmlwdGlvbiB8IEFjY2VzcyBUeXBlIHwKfC0tLS18LS0tLXwtLS0tfC0tLS18CnwgSEVSRSBNYXBzIERldmVsb3BlciBQb3J0YWwgfCA8aHR0cHM6Ly9kZXZlbG9wZXIuaGVyZS5jb20vPiB8IEhFUkUgQVBJIHJlZ2lzdHJhdGlvbiBhbmQgZG9jcyB8IEFQSSBLZXkgUmVxdWlyZWQgfAp8IEhFUkUgR2VvY29kaW5nIEFQSSBEb2N1bWVudGF0aW9uIHwgPGh0dHBzOi8vZGV2ZWxvcGVyLmhlcmUuY29tL2RvY3VtZW50YXRpb24vZ2VvY29kZXIvPiB8IEFkZHJlc3MgZ2VvY29kaW5nIGRvY3VtZW50YXRpb24gfCBBUEkgS2V5IFJlcXVpcmVkIHwKfCBIRVJFIElzb2xpbmUgUm91dGluZyBBUEkgfCA8aHR0cHM6Ly9kZXZlbG9wZXIuaGVyZS5jb20vZG9jdW1lbnRhdGlvbi9yb3V0aW5nLWFwaS8+IHwgRHJpdmUgdGltZSBpc29jaHJvbmUgZ2VuZXJhdGlvbiB8IEFQSSBLZXkgUmVxdWlyZWQgfAp8IENlbnN1cyBCdXJlYXUgQVBJIERvY3VtZW50YXRpb24gfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9kYXRhL2RldmVsb3BlcnMvZ3VpZGFuY2UuaHRtbD4gfCBDZW5zdXMgQVBJIHVzYWdlIGd1aWRlbGluZXMgfCBQdWJsaWMgfAp8IEhFUkUgQVBJIFByaWNpbmcgfCA8aHR0cHM6Ly9kZXZlbG9wZXIuaGVyZS5jb20vcHJpY2luZz4gfCBSYXRlIGxpbWl0cyBhbmQgcHJpY2luZyB0aWVycyB8IFB1YmxpYyB8CnwgUkVTVCBBUEkgQmVzdCBQcmFjdGljZXMgfCA8aHR0cHM6Ly9kZXZlbG9wZXIuaGVyZS5jb20vZG9jdW1lbnRhdGlvbi9pZGVudGl0eS1hY2Nlc3MtbWFuYWdlbWVudC9kZXZfZ3VpZGUvdG9waWNzL3BsYXQtdXNpbmctYXBpa2V5cy5odG1sPiB8IEFQSSBrZXkgbWFuYWdlbWVudCB8IFB1YmxpYyB8CgojIyBIZWFsdGhjYXJlICYgTWVkaWNhbCBSZXNvdXJjZXMKCnwgUmVzb3VyY2UgTmFtZSB8IFVSTCB8IERlc2NyaXB0aW9uIHwgQWNjZXNzIFR5cGUgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwKfCBOVUNDIEhlYWx0aCBDYXJlIFByb3ZpZGVyIFRheG9ub215IHwgPGh0dHBzOi8vdGF4b25vbXkubnVjYy5vcmcvPiB8IE9mZmljaWFsIHByb3ZpZGVyIHRheG9ub215IGNvZGVzIHwgUHVibGljIHwKfCBBQ09HIChBbWVyaWNhbiBDb2xsZWdlIG9mIE9ic3RldHJpY2lhbnMgYW5kIEd5bmVjb2xvZ2lzdHMpIHwgPGh0dHBzOi8vd3d3LmFjb2cub3JnLz4gfCBQcm9mZXNzaW9uYWwgb3JnYW5pemF0aW9uIHwgUHVibGljIHwKfCBBQ09HIERpc3RyaWN0cyB8IDxodHRwczovL3d3dy5hY29nLm9yZy9hYm91dC9kaXN0cmljdHMtYW5kLXNlY3Rpb25zPiB8IEdlb2dyYXBoaWMgZGlzdHJpY3Qgb3JnYW5pemF0aW9uIHwgUHVibGljIHwKfCBTb2NpZXR5IG9mIEd5bmVjb2xvZ2ljIE9uY29sb2d5IHwgPGh0dHBzOi8vd3d3LnNnby5vcmcvPiB8IFN1YnNwZWNpYWx0eSBwcm9mZXNzaW9uYWwgc29jaWV0eSB8IFB1YmxpYyB8CnwgTkNDTiBHdWlkZWxpbmVzIChHeW5lY29sb2dpYyBPbmNvbG9neSkgfCA8aHR0cHM6Ly93d3cubmNjbi5vcmcvZ3VpZGVsaW5lcy9jYXRlZ29yeV8xPiB8IENsaW5pY2FsIHByYWN0aWNlIGd1aWRlbGluZXMgfCBSZWdpc3RyYXRpb24gfAp8IEFDR01FIEZlbGxvd3NoaXAgUmVxdWlyZW1lbnRzIHwgPGh0dHBzOi8vd3d3LmFjZ21lLm9yZy9zcGVjaWFsdGllcy8+IHwgRmVsbG93c2hpcCB0cmFpbmluZyByZXF1aXJlbWVudHMgfCBQdWJsaWMgfAp8IEFBTUMgUGh5c2ljaWFuIFdvcmtmb3JjZSBEYXRhIHwgPGh0dHBzOi8vd3d3LmFhbWMub3JnL2RhdGEtcmVwb3J0cy93b3JrZm9yY2UvZGF0YT4gfCBQaHlzaWNpYW4gd29ya2ZvcmNlIHN0YXRpc3RpY3MgfCBQdWJsaWMgfAp8IEhSU0EgSGVhbHRoIFByb2Zlc3Npb25hbCBTaG9ydGFnZSBBcmVhcyB8IDxodHRwczovL2RhdGEuaHJzYS5nb3YvdG9vbHMvc2hvcnRhZ2UtYXJlYT4gfCBVbmRlcnNlcnZlZCBhcmVhIGRlc2lnbmF0aW9ucyB8IFB1YmxpYyB8CgojIyBHb3Zlcm5tZW50IFJlc291cmNlcwoKfCBSZXNvdXJjZSBOYW1lIHwgVVJMIHwgRGVzY3JpcHRpb24gfCBBY2Nlc3MgVHlwZSB8CnwtLS0tfC0tLS18LS0tLXwtLS0tfAp8IENNUyAoQ2VudGVycyBmb3IgTWVkaWNhcmUgJiBNZWRpY2FpZCBTZXJ2aWNlcykgfCA8aHR0cHM6Ly93d3cuY21zLmdvdi8+IHwgUHJpbWFyeSBoZWFsdGhjYXJlIGRhdGEgYWdlbmN5IHwgUHVibGljIHwKfCBIUlNBIChIZWFsdGggUmVzb3VyY2VzIGFuZCBTZXJ2aWNlcyBBZG1pbmlzdHJhdGlvbikgfCA8aHR0cHM6Ly93d3cuaHJzYS5nb3YvPiB8IEZlZGVyYWwgaGVhbHRoIHdvcmtmb3JjZSBhZ2VuY3kgfCBQdWJsaWMgfAp8IFVTREEgRWNvbm9taWMgUmVzZWFyY2ggU2VydmljZSB8IDxodHRwczovL3d3dy5lcnMudXNkYS5nb3YvPiB8IFJ1cmFsLXVyYmFuIGNsYXNzaWZpY2F0aW9ucyB8IFB1YmxpYyB8CnwgT01CIE1ldHJvcG9saXRhbiBBcmVhIERlbGluZWF0aW9ucyB8IDxodHRwczovL3d3dy53aGl0ZWhvdXNlLmdvdi9vbWIvbWFuYWdlbWVudC9vZmZpY2UtZmVkZXJhbC1maW5hbmNpYWwtbWFuYWdlbWVudC8+IHwgT2ZmaWNpYWwgTVNBIGRlZmluaXRpb25zIHwgUHVibGljIHwKfCBISFMgRGF0YSBQb3J0YWwgfCA8aHR0cHM6Ly9oZWFsdGhkYXRhLmdvdi8+IHwgRmVkZXJhbCBoZWFsdGggZGF0YSBjYXRhbG9nIHwgUHVibGljIHwKfCBOYXRpb25hbCBDYW5jZXIgSW5zdGl0dXRlIHwgPGh0dHBzOi8vd3d3LmNhbmNlci5nb3YvPiB8IENhbmNlciBzdGF0aXN0aWNzIGFuZCByZXNvdXJjZXMgfCBQdWJsaWMgfAp8IEZlZGVyYWwgR2VvZ3JhcGhpYyBEYXRhIENvbW1pdHRlZSB8IDxodHRwczovL3d3dy5mZ2RjLmdvdi8+IHwgR2VvZ3JhcGhpYyBkYXRhIHN0YW5kYXJkcyB8IFB1YmxpYyB8CgojIyBUZWNobmljYWwgRG9jdW1lbnRhdGlvbgoKfCBSZXNvdXJjZSBOYW1lIHwgVVJMIHwgRGVzY3JpcHRpb24gfCBBY2Nlc3MgVHlwZSB8CnwtLS0tfC0tLS18LS0tLXwtLS0tfAp8IFIgUHJvamVjdCB8IDxodHRwczovL3d3dy5yLXByb2plY3Qub3JnLz4gfCBSIHN0YXRpc3RpY2FsIHNvZnR3YXJlIHwgT3BlbiBTb3VyY2UgfAp8IFJTdHVkaW8gfCA8aHR0cHM6Ly93d3cucnN0dWRpby5jb20vPiB8IFIgZGV2ZWxvcG1lbnQgZW52aXJvbm1lbnQgfCBGcmVlL0NvbW1lcmNpYWwgfAp8IHNmIFIgUGFja2FnZSBEb2N1bWVudGF0aW9uIHwgPGh0dHBzOi8vci1zcGF0aWFsLmdpdGh1Yi5pby9zZi8+IHwgU3BhdGlhbCBmZWF0dXJlcyBmb3IgUiB8IE9wZW4gU291cmNlIHwKfCB0aWdyaXMgUiBQYWNrYWdlIHwgPGh0dHBzOi8vZ2l0aHViLmNvbS93YWxrZXJrZS90aWdyaXM+IHwgQ2Vuc3VzIGdlb2dyYXBoeSBpbiBSIHwgT3BlbiBTb3VyY2UgfAp8IER1Y2tEQiBEb2N1bWVudGF0aW9uIHwgPGh0dHBzOi8vZHVja2RiLm9yZy9kb2NzLz4gfCBBbmFseXRpY2FsIGRhdGFiYXNlIGVuZ2luZSB8IE9wZW4gU291cmNlIHwKfCBHREFMIERvY3VtZW50YXRpb24gfCA8aHR0cHM6Ly9nZGFsLm9yZy8+IHwgR2Vvc3BhdGlhbCBkYXRhIGFic3RyYWN0aW9uIGxpYnJhcnkgfCBPcGVuIFNvdXJjZSB8CnwgUFJPSiBDb29yZGluYXRlIFRyYW5zZm9ybWF0aW9uIHwgPGh0dHBzOi8vcHJvai5vcmcvPiB8IENhcnRvZ3JhcGhpYyBwcm9qZWN0aW9ucyBsaWJyYXJ5IHwgT3BlbiBTb3VyY2UgfAp8IFBvc3RHSVMgRG9jdW1lbnRhdGlvbiB8IDxodHRwczovL3Bvc3RnaXMubmV0L2RvY3VtZW50YXRpb24vPiB8IFNwYXRpYWwgZGF0YWJhc2UgZXh0ZW5zaW9uIHwgT3BlbiBTb3VyY2UgfAp8IEdpdEh1YiBSZXBvc2l0b3J5IEJlc3QgUHJhY3RpY2VzIHwgPGh0dHBzOi8vZG9jcy5naXRodWIuY29tL2VuL3JlcG9zaXRvcmllcz4gfCBWZXJzaW9uIGNvbnRyb2wgYW5kIGNvbGxhYm9yYXRpb24gfCBQdWJsaWMgfAoKIyMgQWNhZGVtaWMgJiBSZXNlYXJjaCBSZXNvdXJjZXMKCnwgUmVzb3VyY2UgTmFtZSB8IFVSTCB8IERlc2NyaXB0aW9uIHwgQWNjZXNzIFR5cGUgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwKfCBQdWJNZWQgfCA8aHR0cHM6Ly9wdWJtZWQubmNiaS5ubG0ubmloLmdvdi8+IHwgTWVkaWNhbCBsaXRlcmF0dXJlIGRhdGFiYXNlIHwgUHVibGljIHwKfCBTRUVSIENhbmNlciBTdGF0aXN0aWNzIHwgPGh0dHBzOi8vc2Vlci5jYW5jZXIuZ292Lz4gfCBOYXRpb25hbCBjYW5jZXIgc3VydmVpbGxhbmNlIHwgUHVibGljIHwKfCBIZWFsdGggQWZmYWlycyBKb3VybmFsIHwgPGh0dHBzOi8vd3d3LmhlYWx0aGFmZmFpcnMub3JnLz4gfCBIZWFsdGggcG9saWN5IHJlc2VhcmNoIHwgU3Vic2NyaXB0aW9uIHwKfCBNZWRpY2FsIENhcmUgUmVzZWFyY2ggYW5kIFJldmlldyB8IDxodHRwczovL2pvdXJuYWxzLnNhZ2VwdWIuY29tL2hvbWUvbWNyPiB8IEhlYWx0aGNhcmUgYWNjZXNzIHJlc2VhcmNoIHwgU3Vic2NyaXB0aW9uIHwKfCBTcGF0aWFsIGFuZCBTcGF0aW8tdGVtcG9yYWwgRXBpZGVtaW9sb2d5IHwgPGh0dHBzOi8vd3d3LmpvdXJuYWxzLmVsc2V2aWVyLmNvbS9zcGF0aWFsLWFuZC1zcGF0aW8tdGVtcG9yYWwtZXBpZGVtaW9sb2d5PiB8IFNwYXRpYWwgaGVhbHRoIGFuYWx5c2lzIHwgU3Vic2NyaXB0aW9uIHwKfCBJbnRlcm5hdGlvbmFsIEpvdXJuYWwgb2YgSGVhbHRoIEdlb2dyYXBoaWNzIHwgPGh0dHBzOi8vaWotaGVhbHRoZ2VvZ3JhcGhpY3MuYmlvbWVkY2VudHJhbC5jb20vPiB8IEhlYWx0aCBnZW9ncmFwaHkgcmVzZWFyY2ggfCBPcGVuIEFjY2VzcyB8CgojIyBTb2Z0d2FyZSAmIFRvb2xzCgp8IFJlc291cmNlIE5hbWUgfCBVUkwgfCBEZXNjcmlwdGlvbiB8IEFjY2VzcyBUeXBlIHwKfC0tLS18LS0tLXwtLS0tfC0tLS18CnwgQ1JBTiAoUiBQYWNrYWdlIFJlcG9zaXRvcnkpIHwgPGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnLz4gfCBSIHBhY2thZ2UgZG93bmxvYWRzIHwgT3BlbiBTb3VyY2UgfAp8IEdpdEh1YiB8IDxodHRwczovL2dpdGh1Yi5jb20vPiB8IENvZGUgcmVwb3NpdG9yeSBhbmQgY29sbGFib3JhdGlvbiB8IEZyZWUvUGFpZCB8CnwgRG9ja2VyIEh1YiB8IDxodHRwczovL2h1Yi5kb2NrZXIuY29tLz4gfCBDb250YWluZXIgcmVnaXN0cnkgfCBGcmVlL1BhaWQgfAp8IENvbmRhIFBhY2thZ2UgTWFuYWdlciB8IDxodHRwczovL2RvY3MuY29uZGEuaW8vPiB8IFBhY2thZ2UgbWFuYWdlbWVudCBzeXN0ZW0gfCBPcGVuIFNvdXJjZSB8CnwgcmVudiBSIFBhY2thZ2UgfCA8aHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9yZW52Lz4gfCBSIGVudmlyb25tZW50IG1hbmFnZW1lbnQgfCBPcGVuIFNvdXJjZSB8CnwgR2l0IERvY3VtZW50YXRpb24gfCA8aHR0cHM6Ly9naXQtc2NtLmNvbS9kb2M+IHwgVmVyc2lvbiBjb250cm9sIHN5c3RlbSB8IE9wZW4gU291cmNlIHwKfCBaZW5vZG8gfCA8aHR0cHM6Ly96ZW5vZG8ub3JnLz4gfCBSZXNlYXJjaCBkYXRhIHJlcG9zaXRvcnkgfCBGcmVlIHwKfCBPcGVuIFNjaWVuY2UgRnJhbWV3b3JrIHwgPGh0dHBzOi8vb3NmLmlvLz4gfCBSZXNlYXJjaCBwcm9qZWN0IG1hbmFnZW1lbnQgfCBGcmVlIHwKCiMjIFByb2Zlc3Npb25hbCBPcmdhbml6YXRpb25zICYgU3RhbmRhcmRzCgp8IFJlc291cmNlIE5hbWUgfCBVUkwgfCBEZXNjcmlwdGlvbiB8IEFjY2VzcyBUeXBlIHwKfC0tLS18LS0tLXwtLS0tfC0tLS18CnwgQW1lcmljYW4gTWVkaWNhbCBBc3NvY2lhdGlvbiB8IDxodHRwczovL3d3dy5hbWEtYXNzbi5vcmcvPiB8IE1lZGljYWwgcHJvZmVzc2lvbmFsIG9yZ2FuaXphdGlvbiB8IFB1YmxpYyB8CnwgQXNzb2NpYXRpb24gb2YgQW1lcmljYW4gTWVkaWNhbCBDb2xsZWdlcyB8IDxodHRwczovL3d3dy5hYW1jLm9yZy8+IHwgTWVkaWNhbCBlZHVjYXRpb24gb3JnYW5pemF0aW9uIHwgUHVibGljIHwKfCBOYXRpb25hbCBRdWFsaXR5IEZvcnVtIHwgPGh0dHBzOi8vd3d3LnF1YWxpdHlmb3J1bS5vcmcvPiB8IEhlYWx0aGNhcmUgcXVhbGl0eSBzdGFuZGFyZHMgfCBQdWJsaWMgfAp8IEludGVybmF0aW9uYWwgQXNzb2NpYXRpb24gb2YgR2VvZ3JhcGhlcnMgfCA8aHR0cHM6Ly9pYWctb25saW5lLm9yZy8+IHwgR2VvZ3JhcGhpYyByZXNlYXJjaCBvcmdhbml6YXRpb24gfCBQdWJsaWMgfAp8IEFtZXJpY2FuIFN0YXRpc3RpY2FsIEFzc29jaWF0aW9uIHwgPGh0dHBzOi8vd3d3LmFtc3RhdC5vcmcvPiB8IFN0YXRpc3RpY2FsIG1ldGhvZHMgYW5kIHN0YW5kYXJkcyB8IFB1YmxpYyB8CgojIyBEYXRhIFN0YW5kYXJkcyAmIE1ldGFkYXRhCgp8IFJlc291cmNlIE5hbWUgfCBVUkwgfCBEZXNjcmlwdGlvbiB8IEFjY2VzcyBUeXBlIHwKfC0tLS18LS0tLXwtLS0tfC0tLS18CnwgSEw3IEZISVIgU3RhbmRhcmRzIHwgPGh0dHBzOi8vd3d3LmhsNy5vcmcvZmhpci8+IHwgSGVhbHRoY2FyZSBkYXRhIGV4Y2hhbmdlIHN0YW5kYXJkcyB8IFB1YmxpYyB8CnwgSVNPIEdlb2dyYXBoaWMgU3RhbmRhcmRzIHwgPGh0dHBzOi8vd3d3Lmlzby5vcmcvY29tbWl0dGVlLzU0OTA0Lmh0bWw+IHwgSW50ZXJuYXRpb25hbCBnZW9ncmFwaGljIHN0YW5kYXJkcyB8IFB1YmxpYyB8CnwgT0dDIFN0YW5kYXJkcyB8IDxodHRwczovL3d3dy5vZ2Mub3JnL3N0YW5kYXJkcz4gfCBHZW9zcGF0aWFsIGRhdGEgc3RhbmRhcmRzIHwgUHVibGljIHwKfCBEdWJsaW4gQ29yZSBNZXRhZGF0YSB8IDxodHRwczovL3d3dy5kdWJsaW5jb3JlLm9yZy8+IHwgTWV0YWRhdGEgc3RhbmRhcmRzIHwgUHVibGljIHwKfCBTY2hlbWEub3JnIHwgPGh0dHBzOi8vc2NoZW1hLm9yZy8+IHwgU3RydWN0dXJlZCBkYXRhIHZvY2FidWxhcnkgfCBQdWJsaWMgfAoKIyMgUXVhbGl0eSBDb250cm9sICYgVmFsaWRhdGlvbgoKfCBSZXNvdXJjZSBOYW1lIHwgVVJMIHwgRGVzY3JpcHRpb24gfCBBY2Nlc3MgVHlwZSB8CnwtLS0tfC0tLS18LS0tLXwtLS0tfAp8IEFtZXJpY2FuIENvbW11bml0eSBTdXJ2ZXkgQWNjdXJhY3kgU3RhdGVtZW50IHwgPGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvcHJvZ3JhbXMtc3VydmV5cy9hY3MvZ3VpZGFuY2Uvc3RhdGlzdGljYWwtdGVzdGluZy10b29sLmh0bWw+IHwgQUNTIGRhdGEgYWNjdXJhY3kgZ3VpZGVsaW5lcyB8IFB1YmxpYyB8CnwgSEVSRSBNYXAgUXVhbGl0eSB8IDxodHRwczovL2RldmVsb3Blci5oZXJlLmNvbS9kb2N1bWVudGF0aW9uL3JvdXRpbmctYXBpL2Rldl9ndWlkZS90b3BpY3MvcmVzb3VyY2UtY2FsY3VsYXRlLWlzb2xpbmUuaHRtbD4gfCBBUEkgZGF0YSBxdWFsaXR5IHNwZWNpZmljYXRpb25zIHwgQVBJIERvY3VtZW50YXRpb24gfAp8IENNUyBEYXRhIFF1YWxpdHkgQXNzdXJhbmNlIHwgPGh0dHBzOi8vd3d3LmNtcy5nb3YvUmVzZWFyY2gtU3RhdGlzdGljcy1EYXRhLWFuZC1TeXN0ZW1zL0NNUy1JbmZvcm1hdGlvbi1UZWNobm9sb2d5L0FjY2Vzc3RvRGF0YUFwcGxpY2F0aW9uL0RhdGFVc2VBZ3JlZW1lbnRzPiB8IERhdGEgcXVhbGl0eSBzdGFuZGFyZHMgfCBQdWJsaWMgfAp8IFNwYXRpYWwgRGF0YSBRdWFsaXR5IFN0YW5kYXJkcyB8IDxodHRwczovL3d3dy5mZ2RjLmdvdi9zdGFuZGFyZHMvcHJvamVjdHMvZnJhbWV3b3JrLWRhdGEtc3RhbmRhcmQ+IHwgRmVkZXJhbCBzcGF0aWFsIGRhdGEgcXVhbGl0eSB8IFB1YmxpYyB8CgojIFNIQVBFRklMRSAtIEdlb2dyYXBoaWMgQm91bmRhcmllcyBmb3IgSGVhbHRoY2FyZSBBY2Nlc3NpYmlsaXR5IEFuYWx5c2lzCgojIFNpbXBsaWZpZWQgVVMgQm91bmRhcmllcyBSZWZlcmVuY2UKCiMjIFVTIENlbnN1cyBCdXJlYXUgQ2FydG9ncmFwaGljIEJvdW5kYXJ5IEZpbGVzIChTaW1wbGlmaWVkKQoKIyMjIENvdW50cnkvTmF0aW9uYWwgQm91bmRhcmllcwoKfCBSZXNvbHV0aW9uIHwgRmlsZSBOYW1lIFBhdHRlcm4gfCBEb3dubG9hZCBVUkwgfCBGaWxlIFNpemUgfCBVc2UgQ2FzZSB8CnwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18CnwgKioyMG0gKEhpZ2ggRGV0YWlsKSoqIHwgYGNiXzIwMjFfdXNfbmF0aW9uXzIwbS56aXBgIHwgPGh0dHBzOi8vd3d3Mi5jZW5zdXMuZ292L2dlby90aWdlci9HRU5aMjAyMS9zaHAvPiB8IFx+NTBNQiB8IERldGFpbGVkIG5hdGlvbmFsIGFuYWx5c2lzIHwKfCAqKjVtIChNZWRpdW0gRGV0YWlsKSoqIHwgYGNiXzIwMjFfdXNfbmF0aW9uXzVtLnppcGAgfCA8aHR0cHM6Ly93d3cyLmNlbnN1cy5nb3YvZ2VvL3RpZ2VyL0dFTloyMDIxL3NocC8+IHwgXH4yME1CIHwgR2VuZXJhbCBuYXRpb25hbCBtYXBwaW5nIHwKfCAqKjUwMGsgKExvdyBEZXRhaWwpKiogfCBgY2JfMjAyMV91c19uYXRpb25fNTAway56aXBgIHwgPGh0dHBzOi8vd3d3Mi5jZW5zdXMuZ292L2dlby90aWdlci9HRU5aMjAyMS9zaHAvPiB8IFx+NU1CIHwgV2ViIG1hcHBpbmcsIG92ZXJ2aWV3IG1hcHMgfAoKIyMjIFN0YXRlIEJvdW5kYXJpZXMgKFNpbXBsaWZpZWQpCgp8IFJlc29sdXRpb24gfCBGaWxlIE5hbWUgUGF0dGVybiB8IERvd25sb2FkIFVSTCB8IEZpbGUgU2l6ZSB8IFVzZSBDYXNlIHwKfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwKfCAqKjIwbSAoSGlnaCBEZXRhaWwpKiogfCBgY2JfMjAyMV91c19zdGF0ZV8yMG0uemlwYCB8IDxodHRwczovL3d3dzIuY2Vuc3VzLmdvdi9nZW8vdGlnZXIvR0VOWjIwMjEvc2hwLz4gfCBcfjI1TUIgfCBEZXRhaWxlZCBzdGF0ZSBhbmFseXNpcyB8CnwgKio1bSAoTWVkaXVtIERldGFpbCkqKiB8IGBjYl8yMDIxX3VzX3N0YXRlXzVtLnppcGAgfCA8aHR0cHM6Ly93d3cyLmNlbnN1cy5nb3YvZ2VvL3RpZ2VyL0dFTloyMDIxL3NocC8+IHwgXH44TUIgfCAqKlJFQ09NTUVOREVEIGZvciBtb3N0IGFuYWx5c2lzKiogfAp8ICoqNTAwayAoTG93IERldGFpbCkqKiB8IGBjYl8yMDIxX3VzX3N0YXRlXzUwMGsuemlwYCB8IDxodHRwczovL3d3dzIuY2Vuc3VzLmdvdi9nZW8vdGlnZXIvR0VOWjIwMjEvc2hwLz4gfCBcfjJNQiB8IFdlYiBkaXNwbGF5LCBvdmVydmlldyBtYXBzIHwKCiMjIyBDb3VudHkgQm91bmRhcmllcyAoU2ltcGxpZmllZCkKCnwgUmVzb2x1dGlvbiB8IEZpbGUgTmFtZSBQYXR0ZXJuIHwgRG93bmxvYWQgVVJMIHwgRmlsZSBTaXplIHwgVXNlIENhc2UgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfAp8ICoqMjBtKiogfCBgY2JfMjAyMV91c19jb3VudHlfMjBtLnppcGAgfCA8aHR0cHM6Ly93d3cyLmNlbnN1cy5nb3YvZ2VvL3RpZ2VyL0dFTloyMDIxL3NocC8+IHwgXH40NU1CIHwgRGV0YWlsZWQgY291bnR5IGFuYWx5c2lzIHwKfCAqKjVtKiogfCBgY2JfMjAyMV91c19jb3VudHlfNW0uemlwYCB8IDxodHRwczovL3d3dzIuY2Vuc3VzLmdvdi9nZW8vdGlnZXIvR0VOWjIwMjEvc2hwLz4gfCBcfjE1TUIgfCAqKlJFQ09NTUVOREVEKiogfAp8ICoqNTAwayoqIHwgYGNiXzIwMjFfdXNfY291bnR5XzUwMGsuemlwYCB8IDxodHRwczovL3d3dzIuY2Vuc3VzLmdvdi9nZW8vdGlnZXIvR0VOWjIwMjEvc2hwLz4gfCBcfjRNQiB8IFdlYiBtYXBwaW5nIHwKCiMjIyBDZW5zdXMgVHJhY3QgQm91bmRhcmllcyAoU2ltcGxpZmllZCkKCnwgUmVzb2x1dGlvbiB8IEZpbGUgTmFtZSBQYXR0ZXJuIHwgRG93bmxvYWQgVVJMIHwgRmlsZSBTaXplIHwgVXNlIENhc2UgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfAp8ICoqTmF0aW9uYWwgNTAwayoqIHwgYGNiXzIwMjFfdXNfdHJhY3RfNTAway56aXBgIHwgPGh0dHBzOi8vd3d3Mi5jZW5zdXMuZ292L2dlby90aWdlci9HRU5aMjAyMS9zaHAvPiB8IFx+MTgwTUIgfCAqKk5hdGlvbmFsIHRyYWN0IGFuYWx5c2lzKiogfAp8ICoqU3RhdGUtYnktU3RhdGUgNTAwayoqIHwgYGNiXzIwMjFfW0ZJUFNdX3RyYWN0XzUwMGsuemlwYCB8IDxodHRwczovL3d3dzIuY2Vuc3VzLmdvdi9nZW8vdGlnZXIvR0VOWjIwMjEvc2hwLz4gfCAxLTIwTUIgZWFjaCB8IFN0YXRlLXNwZWNpZmljIGFuYWx5c2lzIHwKCioqRXhhbXBsZSBTdGF0ZSBGaWxlczoqKiAtIENvbG9yYWRvOiBgY2JfMjAyMV8wOF90cmFjdF81MDBrLnppcGAgLSBDYWxpZm9ybmlhOgpgY2JfMjAyMV8wNl90cmFjdF81MDBrLnppcGBcCi0gVGV4YXM6IGBjYl8yMDIxXzQ4X3RyYWN0XzUwMGsuemlwYCAtIE5ldyBZb3JrOiBgY2JfMjAyMV8zNl90cmFjdF81MDBrLnppcGAKCiMjIyBCbG9jayBHcm91cCBCb3VuZGFyaWVzIChTaW1wbGlmaWVkKQoKfCBGaWxlIFR5cGUgfCBGaWxlIE5hbWUgUGF0dGVybiB8IERvd25sb2FkIFVSTCB8IEZpbGUgU2l6ZSB8IE5vdGVzIHwKfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwKfCAqKk5hdGlvbmFsKiogfCBgY2JfMjAyMV91c19iZ181MDBrLnppcGAgfCA8aHR0cHM6Ly93d3cyLmNlbnN1cy5nb3YvZ2VvL3RpZ2VyL0dFTloyMDIxL3NocC8+IHwgXH4zNTBNQiB8IFNpbWlsYXIgdG8geW91ciBgc2ltcGxpZmllZF91c19sY2tfZ3JwXzIwMjEuc2hwYCB8CnwgKipTdGF0ZS1ieS1TdGF0ZSoqIHwgYGNiXzIwMjFfW0ZJUFNdX2JnXzUwMGsuemlwYCB8IDxodHRwczovL3d3dzIuY2Vuc3VzLmdvdi9nZW8vdGlnZXIvR0VOWjIwMjEvc2hwLz4gfCAyLTQwTUIgZWFjaCB8IFNtYWxsZXIsIG1hbmFnZWFibGUgZmlsZXMgfAoKIyMgUiBQYWNrYWdlIFNvdXJjZXMgZm9yIFNpbXBsaWZpZWQgQm91bmRhcmllcwoKIyMjIHRpZ3JpcyBQYWNrYWdlIChBdXRvbWF0aWMgU2ltcGxpZmljYXRpb24pCgpgYGAgcgojIFNpbXBsaWZpZWQgYm91bmRhcmllcyB3aXRoIGNiID0gVFJVRSBwYXJhbWV0ZXIKbGlicmFyeSh0aWdyaXMpCgojIFVTIFN0YXRlcyAoc2ltcGxpZmllZCkKc3RhdGVzX3NpbXBsaWZpZWQgPC0gdGlncmlzOjpzdGF0ZXMoY2IgPSBUUlVFLCByZXNvbHV0aW9uID0gIjIwbSIpICAjIG9yICI1bSIsICI1MDBrIgoKIyBVUyBDb3VudGllcyAoc2ltcGxpZmllZCkgIApjb3VudGllc19zaW1wbGlmaWVkIDwtIHRpZ3Jpczo6Y291bnRpZXMoY2IgPSBUUlVFLCByZXNvbHV0aW9uID0gIjIwbSIpCgojIENlbnN1cyBUcmFjdHMgKHNpbXBsaWZpZWQpIC0gYnkgc3RhdGUKY29sb3JhZG9fdHJhY3RzIDwtIHRpZ3Jpczo6dHJhY3RzKHN0YXRlID0gIkNPIiwgY2IgPSBUUlVFKQoKIyBCbG9jayBHcm91cHMgKHNpbXBsaWZpZWQpIC0gYnkgc3RhdGUgIApjb2xvcmFkb19iZyA8LSB0aWdyaXM6OmJsb2NrX2dyb3VwcyhzdGF0ZSA9ICJDTyIsIGNiID0gVFJVRSkKCiMgTmF0aW9uYWwgYm91bmRhcmllcwp1c19uYXRpb24gPC0gdGlncmlzOjpuYXRpb24oY2IgPSBUUlVFLCByZXNvbHV0aW9uID0gIjVtIikKYGBgCgojIyMgVVNBYm91bmRhcmllcyBQYWNrYWdlIChIaXN0b3JpY2FsICsgU2ltcGxpZmllZCkKCmBgYCByCmxpYnJhcnkoVVNBYm91bmRhcmllcykKCiMgQ3VycmVudCBzaW1wbGlmaWVkIHN0YXRlIGJvdW5kYXJpZXMKc3RhdGVzXzIwMjAgPC0gdXNfc3RhdGVzKHJlc29sdXRpb24gPSAibG93IikgICAgIyBTaW1wbGlmaWVkCnN0YXRlc18yMDIwX2hpIDwtIHVzX3N0YXRlcyhyZXNvbHV0aW9uID0gImhpZ2giKSAjIERldGFpbGVkCgojIEN1cnJlbnQgc2ltcGxpZmllZCBjb3VudHkgYm91bmRhcmllcyAgCmNvdW50aWVzXzIwMjAgPC0gdXNfY291bnRpZXMocmVzb2x1dGlvbiA9ICJsb3ciKQoKIyBIaXN0b3JpY2FsIGJvdW5kYXJpZXMgKHNpbXBsaWZpZWQpCnN0YXRlc18xOTkwIDwtIHVzX3N0YXRlcyhtYXBfZGF0ZSA9ICIxOTkwLTAxLTAxIiwgcmVzb2x1dGlvbiA9ICJsb3ciKQpgYGAKCiMjIEFsdGVybmF0aXZlIFNpbXBsaWZpZWQgQm91bmRhcnkgU291cmNlcwoKIyMjIE5hdHVyYWwgRWFydGggKEdsb2JhbCwgTXVsdGktU2NhbGUpCgp8IFNjYWxlIHwgUmVzb2x1dGlvbiB8IERvd25sb2FkIFVSTCB8IFVTIENvdmVyYWdlIHwKfC0tLS18LS0tLXwtLS0tfC0tLS18CnwgKioxOjEwbSoqIHwgSGlnaCBkZXRhaWwgfCA8aHR0cHM6Ly93d3cubmF0dXJhbGVhcnRoZGF0YS5jb20vZG93bmxvYWRzLzEwbS1jdWx0dXJhbC12ZWN0b3JzLz4gfCBEZXRhaWxlZCBVUyBib3VuZGFyaWVzIHwKfCAqKjE6NTBtKiogfCBNZWRpdW0gZGV0YWlsIHwgPGh0dHBzOi8vd3d3Lm5hdHVyYWxlYXJ0aGRhdGEuY29tL2Rvd25sb2Fkcy81MG0tY3VsdHVyYWwtdmVjdG9ycy8+IHwgKipSRUNPTU1FTkRFRCoqIHwKfCAqKjE6MTEwbSoqIHwgTG93IGRldGFpbCB8IDxodHRwczovL3d3dy5uYXR1cmFsZWFydGhkYXRhLmNvbS9kb3dubG9hZHMvMTEwbS1jdWx0dXJhbC12ZWN0b3JzLz4gfCBPdmVydmlldyBtYXBwaW5nIHwKCioqU3BlY2lmaWMgRmlsZXM6KiogLSBDb3VudHJpZXM6IGBuZV81MG1fYWRtaW5fMF9jb3VudHJpZXMuemlwYCAtClN0YXRlcy9Qcm92aW5jZXM6IGBuZV81MG1fYWRtaW5fMV9zdGF0ZXNfcHJvdmluY2VzLnppcGAKCiMjIyBPcGVuU3RyZWV0TWFwIChTaW1wbGlmaWVkIEV4dHJhY3RzKQoKfCBTb3VyY2UgfCBEZXNjcmlwdGlvbiB8IERvd25sb2FkIFVSTCB8IEZvcm1hdCB8CnwtLS0tfC0tLS18LS0tLXwtLS0tfAp8ICoqR2VvZmFicmlrKiogfCBVUyBzdGF0ZSBleHRyYWN0cyB8IDxodHRwczovL2Rvd25sb2FkLmdlb2ZhYnJpay5kZS9ub3J0aC1hbWVyaWNhL3VzLz4gfCBWYXJpb3VzIGZvcm1hdHMgfAp8ICoqQkJCaWtlKiogfCBDdXN0b20gZXh0cmFjdHMgfCA8aHR0cHM6Ly9leHRyYWN0LmJiYmlrZS5vcmcvPiB8IFNoYXBlZmlsZSwgR2VvSlNPTiB8CgojIENyZWF0aW5nIFlvdXIgT3duIFNpbXBsaWZpZWQgQm91bmRhcmllcwoKIyMjIFVzaW5nIFIgKHNmIHBhY2thZ2UpCgpgYGAgcgpsaWJyYXJ5KHNmKQoKIyBMb2FkIGRldGFpbGVkIGJvdW5kYXJ5CmRldGFpbGVkX2JvdW5kYXJ5IDwtIHN0X3JlYWQoImRldGFpbGVkX2JvdW5kYXJ5LnNocCIpCgojIFNpbXBsaWZ5IGdlb21ldHJ5ICh0b2xlcmFuY2UgaW4gbWFwIHVuaXRzKQpzaW1wbGlmaWVkX2JvdW5kYXJ5IDwtIHN0X3NpbXBsaWZ5KGRldGFpbGVkX2JvdW5kYXJ5LCBkVG9sZXJhbmNlID0gMTAwMCkgICMgMWttIHRvbGVyYW5jZQoKIyBBbHRlcm5hdGl2ZTogcHJlc2VydmUgdG9wb2xvZ3kKc2ltcGxpZmllZF9ib3VuZGFyeSA8LSBzdF9zaW1wbGlmeShkZXRhaWxlZF9ib3VuZGFyeSwgcHJlc2VydmVUb3BvbG9neSA9IFRSVUUsIGRUb2xlcmFuY2UgPSA1MDApCgojIFNhdmUgc2ltcGxpZmllZCB2ZXJzaW9uCnN0X3dyaXRlKHNpbXBsaWZpZWRfYm91bmRhcnksICJzaW1wbGlmaWVkX2JvdW5kYXJ5LnNocCIpCmBgYAoKIyMgUiBDb2RlIEV4YW1wbGVzIGZvciBDb21tb24gVXNlIENhc2VzCgojIyMgTG9hZCBBbGwgU2ltcGxpZmllZCBCb3VuZGFyaWVzCgpgYGAgcgpsaWJyYXJ5KHRpZ3JpcykKbGlicmFyeShzZikKCiMgU2V0IG9wdGlvbnMgZm9yIHNpbXBsaWZpZWQgYm91bmRhcmllcwpvcHRpb25zKHRpZ3Jpc191c2VfY2FjaGUgPSBUUlVFKSAgIyBDYWNoZSBmb3IgZmFzdGVyIHJlcGVhdGVkIGFjY2VzcwoKIyBMb2FkIHNpbXBsaWZpZWQgYm91bmRhcmllcwp1c19zdGF0ZXMgPC0gdGlncmlzOjpzdGF0ZXMoY2IgPSBUUlVFLCByZXNvbHV0aW9uID0gIjVtIikKdXNfY291bnRpZXMgPC0gdGlncmlzOjpjb3VudGllcyhjYiA9IFRSVUUsIHJlc29sdXRpb24gPSAiNW0iKSAKdXNfbmF0aW9uIDwtIHRpZ3Jpczo6bmF0aW9uKGNiID0gVFJVRSwgcmVzb2x1dGlvbiA9ICI1bSIpCgojIExvYWQgY2Vuc3VzIHRyYWN0cyBmb3Igc3BlY2lmaWMgc3RhdGVzIChzaW1wbGlmaWVkKQpjb2xvcmFkb190cmFjdHMgPC0gdGlncmlzOjp0cmFjdHMoc3RhdGUgPSAiQ08iLCBjYiA9IFRSVUUpCmNhbGlmb3JuaWFfdHJhY3RzIDwtIHRpZ3Jpczo6dHJhY3RzKHN0YXRlID0gIkNBIiwgY2IgPSBUUlVFKQoKIyBMb2FkIGJsb2NrIGdyb3VwcyBmb3IgYW5hbHlzaXMgKHNpbWlsYXIgdG8geW91ciBmaWxlKQpjb2xvcmFkb19iZyA8LSB0aWdyaXM6OmJsb2NrX2dyb3VwcyhzdGF0ZSA9ICJDTyIsIGNiID0gVFJVRSkKYGBgCgojIyMgUGVyZm9ybWFuY2UgQ29tcGFyaXNvbgoKfCBCb3VuZGFyeSBUeXBlICAgICB8IERldGFpbGVkIFNpemUgfCBTaW1wbGlmaWVkIFNpemUgfCBTcGVlZCBJbXByb3ZlbWVudCAgICB8CnwtLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAp8ICoqVVMgU3RhdGVzKiogICAgIHwgXH4xNU1CICAgICAgICB8IFx+OE1CICAgICAgICAgICB8IDJ4IGZhc3RlciByZW5kZXJpbmcgIHwKfCAqKlVTIENvdW50aWVzKiogICB8IFx+ODBNQiAgICAgICAgfCBcfjE1TUIgICAgICAgICAgfCA1eCBmYXN0ZXIgcmVuZGVyaW5nICB8CnwgKipDZW5zdXMgVHJhY3RzKiogfCBcfjEuMkdCICAgICAgIHwgXH4xODBNQiAgICAgICAgIHwgMTB4IGZhc3RlciByZW5kZXJpbmcgfAp8ICoqQmxvY2sgR3JvdXBzKiogIHwgXH4yLjVHQiAgICAgICB8IFx+MzUwTUIgICAgICAgICB8IDE1eCBmYXN0ZXIgcmVuZGVyaW5nIHwKCiMjIFF1YWxpdHkgQ29udHJvbCBmb3IgU2ltcGxpZmllZCBCb3VuZGFyaWVzCgojIyMgVmFsaWRhdGlvbiBDaGVja3MKCmBgYCByCiMgQ2hlY2sgdmFsaWRpdHkgb2Ygc2ltcGxpZmllZCBnZW9tZXRyaWVzCnN0X2lzX3ZhbGlkKHNpbXBsaWZpZWRfYm91bmRhcnkpCgojIEZpeCBpbnZhbGlkIGdlb21ldHJpZXMgaWYgbmVlZGVkCnNpbXBsaWZpZWRfYm91bmRhcnkgPC0gc3RfbWFrZV92YWxpZChzaW1wbGlmaWVkX2JvdW5kYXJ5KQoKIyBDaGVjayBhcmVhIHByZXNlcnZhdGlvbiAoc2hvdWxkIGJlIGNsb3NlIHRvIG9yaWdpbmFsKQpvcmlnaW5hbF9hcmVhIDwtIHN1bShzdF9hcmVhKGRldGFpbGVkX2JvdW5kYXJ5KSkKc2ltcGxpZmllZF9hcmVhIDwtIHN1bShzdF9hcmVhKHNpbXBsaWZpZWRfYm91bmRhcnkpKQphcmVhX2RpZmZlcmVuY2UgPC0gYWJzKHNpbXBsaWZpZWRfYXJlYSAtIG9yaWdpbmFsX2FyZWEpIC8gb3JpZ2luYWxfYXJlYQpwcmludChwYXN0ZSgiQXJlYSBkaWZmZXJlbmNlOiIsIHNjYWxlczo6cGVyY2VudChhcmVhX2RpZmZlcmVuY2UpKSkKYGBgCgojIyBGaWxlIE5hbWluZyBDb252ZW50aW9uIFJlZmVyZW5jZQoKIyMjIENlbnN1cyBCdXJlYXUgUGF0dGVybgoKLSAgIGBjYl9bWUVBUl1fW0dFT0dSQVBIWV1fW0VOVElUWV1fW1JFU09MVVRJT05dLnppcGAKLSAgIEV4YW1wbGVzOgogICAgLSAgIGBjYl8yMDIxX3VzX3N0YXRlXzVtLnppcGAgKFVTIHN0YXRlcywgNW0gcmVzb2x1dGlvbikKICAgIC0gICBgY2JfMjAyMV8wOF90cmFjdF81MDBrLnppcGAgKENvbG9yYWRvIHRyYWN0cywgNTAwayByZXNvbHV0aW9uKQogICAgLSAgIGBjYl8yMDIxX3VzX2JnXzUwMGsuemlwYCAoVVMgYmxvY2sgZ3JvdXBzLCA1MDBrIHJlc29sdXRpb24pCgojIyMgUmVzb2x1dGlvbiBDb2RlcwoKLSAgICoqMjBtKio6IDE6MjAsMDAwLDAwMCBzY2FsZSAoaGlnaCBkZXRhaWwpCi0gICAqKjVtKio6IDE6NSwwMDAsMDAwIHNjYWxlIChtZWRpdW0gZGV0YWlsKVwKLSAgICoqNTAwayoqOiAxOjUwMCwwMDAgc2NhbGUgKGxvdyBkZXRhaWwsIG1vc3Qgc2ltcGxpZmllZCkKClRoZSAqKjUwMGsgcmVzb2x1dGlvbioqIGZpbGVzIGFyZSBjbG9zZXN0IHRvIHlvdXIKYHNpbXBsaWZpZWRfdXNfbGNrX2dycF8yMDIxLnNocGAgcGF0dGVybiBhbmQgYXJlIG9wdGltaXplZCBmb3IgYW5hbHl0aWNhbCB3b3JrCndoaWxlIG1haW50YWluaW5nIGVzc2VudGlhbCBnZW9ncmFwaGljIGFjY3VyYWN5LgoKIyBVUyBDZW5zdXMgQnVyZWF1IEdlb2dyYXBoaWMgQm91bmRhcmllcwoKfCBHZW9ncmFwaGljIFVuaXQgfCBEYXRhIFNvdXJjZSB8IERvd25sb2FkIFVSTCB8IEZpbGUgRm9ybWF0IHwgQ292ZXJhZ2UgfCBVcGRhdGUgRnJlcXVlbmN5IHwgTm90ZXMgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwKfCAqKkNlbnN1cyBUcmFjdHMqKiB8IFVTIENlbnN1cyBCdXJlYXUgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9tYXBwaW5nLWZpbGVzL3RpbWUtc2VyaWVzL2dlby90aWdlci1saW5lLWZpbGUuaHRtbD4gfCBTaGFwZWZpbGUsIEtNTCwgR2VvSlNPTiB8IE5hdGlvbmFsLCBTdGF0ZSwgQ291bnR5IHwgQW5udWFsIHwgUHJpbWFyeSBhbmFseXNpcyB1bml0IGZvciBkZW1vZ3JhcGhpY3MgfAp8ICoqQ2Vuc3VzIEJsb2NrIEdyb3VwcyoqIHwgVVMgQ2Vuc3VzIEJ1cmVhdSB8IDxodHRwczovL3d3dy5jZW5zdXMuZ292L2dlb2dyYXBoaWVzL21hcHBpbmctZmlsZXMvdGltZS1zZXJpZXMvZ2VvL3RpZ2VyLWxpbmUtZmlsZS5odG1sPiB8IFNoYXBlZmlsZSwgS01MLCBHZW9KU09OIHwgTmF0aW9uYWwsIFN0YXRlLCBDb3VudHkgfCBBbm51YWwgfCBIaWdoZXN0IHJlc29sdXRpb24gZGVtb2dyYXBoaWMgZGF0YSB8CnwgKipDZW5zdXMgQmxvY2tzKiogfCBVUyBDZW5zdXMgQnVyZWF1IHwgPGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvZ2VvZ3JhcGhpZXMvbWFwcGluZy1maWxlcy90aW1lLXNlcmllcy9nZW8vdGlnZXItbGluZS1maWxlLmh0bWw+IHwgU2hhcGVmaWxlLCBLTUwsIEdlb0pTT04gfCBOYXRpb25hbCwgU3RhdGUsIENvdW50eSB8IEFubnVhbCB8IE1vc3QgZGV0YWlsZWQgZ2VvZ3JhcGhpYyB1bml0IHwKfCAqKlN0YXRlIEJvdW5kYXJpZXMqKiB8IFVTIENlbnN1cyBCdXJlYXUgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9tYXBwaW5nLWZpbGVzL3RpbWUtc2VyaWVzL2dlby90aWdlci1saW5lLWZpbGUuaHRtbD4gfCBTaGFwZWZpbGUsIEtNTCwgR2VvSlNPTiB8IE5hdGlvbmFsIHwgQW5udWFsIHwgU3RhdGUtbGV2ZWwgYW5hbHlzaXMgfAp8ICoqQ291bnR5IEJvdW5kYXJpZXMqKiB8IFVTIENlbnN1cyBCdXJlYXUgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9tYXBwaW5nLWZpbGVzL3RpbWUtc2VyaWVzL2dlby90aWdlci1saW5lLWZpbGUuaHRtbD4gfCBTaGFwZWZpbGUsIEtNTCwgR2VvSlNPTiB8IE5hdGlvbmFsLCBTdGF0ZSB8IEFubnVhbCB8IENvdW50eS1sZXZlbCBhZ2dyZWdhdGlvbiB8CnwgKipaSVAgQ29kZSBUYWJ1bGF0aW9uIEFyZWFzIChaQ1RBcykqKiB8IFVTIENlbnN1cyBCdXJlYXUgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9tYXBwaW5nLWZpbGVzL3RpbWUtc2VyaWVzL2dlby90aWdlci1saW5lLWZpbGUuaHRtbD4gfCBTaGFwZWZpbGUsIEtNTCwgR2VvSlNPTiB8IE5hdGlvbmFsIHwgRGVjZW5uaWFsIENlbnN1cyB8IEFwcHJveGltYXRlIFpJUCBjb2RlIGFyZWFzIHwKfCAqKlVyYmFuIEFyZWFzKiogfCBVUyBDZW5zdXMgQnVyZWF1IHwgPGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvZ2VvZ3JhcGhpZXMvbWFwcGluZy1maWxlcy90aW1lLXNlcmllcy9nZW8vdGlnZXItbGluZS1maWxlLmh0bWw+IHwgU2hhcGVmaWxlLCBLTUwsIEdlb0pTT04gfCBOYXRpb25hbCB8IERlY2VubmlhbCBDZW5zdXMgfCBVcmJhbiB2cyBydXJhbCBjbGFzc2lmaWNhdGlvbiB8CgojIyBIZWFsdGggUmVzb3VyY2VzIGFuZCBTZXJ2aWNlcyBBZG1pbmlzdHJhdGlvbiAoSFJTQSkgQXJlYXMKCnwgR2VvZ3JhcGhpYyBVbml0IHwgRGF0YSBTb3VyY2UgfCBEb3dubG9hZCBVUkwgfCBGaWxlIEZvcm1hdCB8IENvdmVyYWdlIHwgVXBkYXRlIEZyZXF1ZW5jeSB8IE5vdGVzIHwKfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18CnwgKipIZWFsdGggUHJvZmVzc2lvbmFsIFNob3J0YWdlIEFyZWFzIChIUFNBcykqKiB8IEhSU0EgfCA8aHR0cHM6Ly9kYXRhLmhyc2EuZ292L2RhdGEvZG93bmxvYWQ+IHwgU2hhcGVmaWxlLCBHZW9KU09OLCBDU1YgfCBOYXRpb25hbCB8IFF1YXJ0ZXJseSB8IFByaW1hcnkgY2FyZSwgZGVudGFsLCBtZW50YWwgaGVhbHRoIHwKfCAqKk1lZGljYWxseSBVbmRlcnNlcnZlZCBBcmVhcyAoTVVBcykqKiB8IEhSU0EgfCA8aHR0cHM6Ly9kYXRhLmhyc2EuZ292L2RhdGEvZG93bmxvYWQ+IHwgU2hhcGVmaWxlLCBHZW9KU09OLCBDU1YgfCBOYXRpb25hbCB8IFF1YXJ0ZXJseSB8IEFyZWFzIGxhY2tpbmcgbWVkaWNhbCBjYXJlIHwKfCAqKk1lZGljYWxseSBVbmRlcnNlcnZlZCBQb3B1bGF0aW9ucyAoTVVQcykqKiB8IEhSU0EgfCA8aHR0cHM6Ly9kYXRhLmhyc2EuZ292L2RhdGEvZG93bmxvYWQ+IHwgU2hhcGVmaWxlLCBHZW9KU09OLCBDU1YgfCBOYXRpb25hbCB8IFF1YXJ0ZXJseSB8IFBvcHVsYXRpb24tYmFzZWQgZGVzaWduYXRpb25zIHwKfCAqKkZlZGVyYWxseSBRdWFsaWZpZWQgSGVhbHRoIENlbnRlcnMgKEZRSENzKSoqIHwgSFJTQSB8IDxodHRwczovL2RhdGEuaHJzYS5nb3YvZGF0YS9kb3dubG9hZD4gfCBQb2ludCBkYXRhLCBDU1YgfCBOYXRpb25hbCB8IE1vbnRobHkgfCBGUUhDIGxvY2F0aW9ucyB8CnwgKipSdXJhbCBIZWFsdGggQ2xpbmljcyoqIHwgSFJTQSB8IDxodHRwczovL2RhdGEuaHJzYS5nb3YvZGF0YS9kb3dubG9hZD4gfCBQb2ludCBkYXRhLCBDU1YgfCBOYXRpb25hbCB8IE1vbnRobHkgfCBSSEMgbG9jYXRpb25zIHwKfCAqKkNyaXRpY2FsIEFjY2VzcyBIb3NwaXRhbHMqKiB8IEhSU0EgfCA8aHR0cHM6Ly9kYXRhLmhyc2EuZ292L2RhdGEvZG93bmxvYWQ+IHwgUG9pbnQgZGF0YSwgQ1NWIHwgTmF0aW9uYWwgfCBNb250aGx5IHwgQ0FIIGxvY2F0aW9ucyB8CgojIyBSdXJhbC1VcmJhbiBDbGFzc2lmaWNhdGlvbnMKCnwgR2VvZ3JhcGhpYyBVbml0IHwgRGF0YSBTb3VyY2UgfCBEb3dubG9hZCBVUkwgfCBGaWxlIEZvcm1hdCB8IENvdmVyYWdlIHwgVXBkYXRlIEZyZXF1ZW5jeSB8IE5vdGVzIHwKfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18CnwgKipSdXJhbC1VcmJhbiBDb21tdXRpbmcgQXJlYXMgKFJVQ0FzKSoqIHwgVVNEQSBFUlMgfCA8aHR0cHM6Ly93d3cuZXJzLnVzZGEuZ292L2RhdGEtcHJvZHVjdHMvcnVyYWwtdXJiYW4tY29tbXV0aW5nLWFyZWEtY29kZXMvZG9jdW1lbnRhdGlvbi8+IHwgQ1NWIHdpdGggRklQUyBjb2RlcyB8IE5hdGlvbmFsIChDZW5zdXMgVHJhY3RzKSB8IFx+MTAgeWVhcnMgfCAyMDEwIENlbnN1cy1iYXNlZCAobW9zdCByZWNlbnQpIHwKfCAqKlVyYmFuIEluZmx1ZW5jZSBDb2RlcyoqIHwgVVNEQSBFUlMgfCA8aHR0cHM6Ly93d3cuZXJzLnVzZGEuZ292L2RhdGEtcHJvZHVjdHMvdXJiYW4taW5mbHVlbmNlLWNvZGVzLz4gfCBDU1Ygd2l0aCBGSVBTIGNvZGVzIHwgTmF0aW9uYWwgKENvdW50aWVzKSB8IFx+MTAgeWVhcnMgfCBDb3VudHktbGV2ZWwgcnVyYWwtdXJiYW4gfAp8ICoqUnVyYWwtVXJiYW4gQ29udGludXVtIENvZGVzKiogfCBVU0RBIEVSUyB8IDxodHRwczovL3d3dy5lcnMudXNkYS5nb3YvZGF0YS1wcm9kdWN0cy9ydXJhbC11cmJhbi1jb250aW51dW0tY29kZXMvPiB8IENTViB3aXRoIEZJUFMgY29kZXMgfCBOYXRpb25hbCAoQ291bnRpZXMpIHwgXH4xMCB5ZWFycyB8IE1ldHJvIGFuZCBub24tbWV0cm8gY291bnRpZXMgfAoKIyMgQUNPRyBEaXN0cmljdHMgYW5kIE1lZGljYWwgUHJvZmVzc2lvbmFsIEFyZWFzCgp8IEdlb2dyYXBoaWMgVW5pdCB8IERhdGEgU291cmNlIHwgRG93bmxvYWQgVVJMIHwgRmlsZSBGb3JtYXQgfCBDb3ZlcmFnZSB8IFVwZGF0ZSBGcmVxdWVuY3kgfCBOb3RlcyB8CnwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfAp8ICoqSG9zcGl0YWwgUmVmZXJyYWwgUmVnaW9ucyAoSFJScykqKiB8IERhcnRtb3V0aCBBdGxhcyB8IDxodHRwczovL3d3dy5kYXJ0bW91dGhhdGxhcy5vcmcvdG9vbHMvZG93bmxvYWRzLmFzcHg+IHwgU2hhcGVmaWxlIHwgTmF0aW9uYWwgfCBcfjEwIHllYXJzIHwgSGVhbHRoY2FyZSBtYXJrZXQgYXJlYXMgfAp8ICoqSG9zcGl0YWwgU2VydmljZSBBcmVhcyAoSFNBcykqKiB8IERhcnRtb3V0aCBBdGxhcyB8IDxodHRwczovL3d3dy5kYXJ0bW91dGhhdGxhcy5vcmcvdG9vbHMvZG93bmxvYWRzLmFzcHg+IHwgU2hhcGVmaWxlIHwgTmF0aW9uYWwgfCBcfjEwIHllYXJzIHwgTG9jYWwgaG9zcGl0YWwgbWFya2V0cyB8CgojIyBUcmFuc3BvcnRhdGlvbiBhbmQgSW5mcmFzdHJ1Y3R1cmUKCnwgR2VvZ3JhcGhpYyBVbml0IHwgRGF0YSBTb3VyY2UgfCBEb3dubG9hZCBVUkwgfCBGaWxlIEZvcm1hdCB8IENvdmVyYWdlIHwgVXBkYXRlIEZyZXF1ZW5jeSB8IE5vdGVzIHwKfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18CnwgKipQcmltYXJ5IFJvYWRzKiogfCBVUyBDZW5zdXMgQnVyZWF1IHwgPGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvZ2VvZ3JhcGhpZXMvbWFwcGluZy1maWxlcy90aW1lLXNlcmllcy9nZW8vdGlnZXItbGluZS1maWxlLmh0bWw+IHwgU2hhcGVmaWxlIHwgTmF0aW9uYWwsIFN0YXRlIHwgQW5udWFsIHwgTWFqb3IgaGlnaHdheXMgYW5kIHJvYWRzIHwKfCAqKkFsbCBSb2FkcyoqIHwgVVMgQ2Vuc3VzIEJ1cmVhdSB8IDxodHRwczovL3d3dy5jZW5zdXMuZ292L2dlb2dyYXBoaWVzL21hcHBpbmctZmlsZXMvdGltZS1zZXJpZXMvZ2VvL3RpZ2VyLWxpbmUtZmlsZS5odG1sPiB8IFNoYXBlZmlsZSB8IE5hdGlvbmFsLCBTdGF0ZSwgQ291bnR5IHwgQW5udWFsIHwgQ29tcGxldGUgcm9hZCBuZXR3b3JrIHwKCiMjIE1ham9yIEhpZ2h3YXkgU3lzdGVtcyBhbmQgSW50ZXJzdGF0ZSBDb3JyaWRvcnMKCnwgSGlnaHdheSBTeXN0ZW0gfCBEYXRhIFNvdXJjZSB8IERvd25sb2FkIFVSTCB8IEZpbGUgRm9ybWF0IHwgQ292ZXJhZ2UgfCBVcGRhdGUgRnJlcXVlbmN5IHwgU3BlY2lmaWMgUm91dGVzIEluY2x1ZGVkIHwKfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18CnwgKipJbnRlcnN0YXRlIEhpZ2h3YXkgU3lzdGVtKiogfCBVUyBDZW5zdXMgQnVyZWF1IFRJR0VSIHwgPGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvZ2VvZ3JhcGhpZXMvbWFwcGluZy1maWxlcy90aW1lLXNlcmllcy9nZW8vdGlnZXItbGluZS1maWxlLmh0bWw+IHwgU2hhcGVmaWxlIHwgTmF0aW9uYWwgfCBBbm51YWwgfCBJLTk1LCBJLTEwLCBJLTUsIEktNzUsIEktODAsIEktNDAsIEktMzUsIEktMjUsIEktNzAsIEktOTAsIGV0Yy4gfAp8ICoqVVMgSGlnaHdheSBTeXN0ZW0qKiB8IFVTIENlbnN1cyBCdXJlYXUgVElHRVIgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9tYXBwaW5nLWZpbGVzL3RpbWUtc2VyaWVzL2dlby90aWdlci1saW5lLWZpbGUuaHRtbD4gfCBTaGFwZWZpbGUgfCBOYXRpb25hbCB8IEFubnVhbCB8IFVTLTEsIFVTLTUwLCBVUy0xMDEsIFVTLVJvdXRlIDY2IChoaXN0b3JpYyksIGV0Yy4gfAp8ICoqUHJpbWFyeSBSb2FkcyAoSW50ZXJzdGF0ZSArIFVTKSoqIHwgVVMgQ2Vuc3VzIEJ1cmVhdSBUSUdFUiB8IDxodHRwczovL3d3dy5jZW5zdXMuZ292L2dlb2dyYXBoaWVzL21hcHBpbmctZmlsZXMvdGltZS1zZXJpZXMvZ2VvL3RpZ2VyLWxpbmUtZmlsZS5odG1sPiB8IFNoYXBlZmlsZSB8IE5hdGlvbmFsIHwgQW5udWFsIHwgQWxsIEludGVyc3RhdGUgYW5kIFVTIGhpZ2h3YXlzIGNvbWJpbmVkIHwKfCAqKk5hdGlvbmFsIEhpZ2h3YXkgU3lzdGVtIChOSFMpKiogfCBGSFdBIHwgPGh0dHBzOi8vd3d3LmZod2EuZG90Lmdvdi9wbGFubmluZy9uYXRpb25hbF9oaWdod2F5X3N5c3RlbS8+IHwgU2hhcGVmaWxlLCBHZW9KU09OIHwgTmF0aW9uYWwgfCBBbm51YWwgfCBDb25ncmVzc2lvbmFsbHkgZGVzaWduYXRlZCBzdHJhdGVnaWMgaGlnaHdheXMgfAoKIyMgTWFqb3IgSW50ZXJzdGF0ZSBIaWdod2F5cyAoRGV0YWlsZWQgUmVmZXJlbmNlKQoKIyMjIEVhc3QtV2VzdCBJbnRlcnN0YXRlIENvcnJpZG9ycwoKfCBSb3V0ZSB8IERlc2NyaXB0aW9uIHwgU3RhdGVzIFRyYXZlcnNlZCB8IExlbmd0aCAoTWlsZXMpIHwgS2V5IENpdGllcyBDb25uZWN0ZWQgfCBIZWFsdGhjYXJlIFJlbGV2YW5jZSB8CnwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwKfCAqKkktMTAqKiB8IFNvdXRoZXJuIHRyYW5zY29udGluZW50YWwgfCBDQSwgQVosIE5NLCBUWCwgTEEsIE1TLCBBTCwgRkwgfCAyLDQ2MCB8IExvcyBBbmdlbGVzIC0gSG91c3RvbiAtIE5ldyBPcmxlYW5zIC0gSmFja3NvbnZpbGxlIHwgTWFqb3IgU3VuIEJlbHQgY29ycmlkb3IgfAp8ICoqSS0yMCoqIHwgU291dGhlcm4gcm91dGUgfCBUWCwgTEEsIE1TLCBBTCwgR0EsIFNDIHwgMSw1MzUgfCBEYWxsYXMgLSBBdGxhbnRhIC0gQ29sdW1iaWEgfCBDb25uZWN0cyBtYWpvciBTb3V0aGVybiBtZWRpY2FsIGNlbnRlcnMgfAp8ICoqSS0zMCoqIHwgQXJrYW5zYXMtVGV4YXMgfCBUWCwgQVIgfCAzNjcgfCBEYWxsYXMgLSBMaXR0bGUgUm9jayB8IExpbmtzIERhbGxhcyBtZWRpY2FsIGRpc3RyaWN0IHwKfCAqKkktNDAqKiB8IENlbnRyYWwgdHJhbnNjb250aW5lbnRhbCB8IENBLCBBWiwgTk0sIFRYLCBPSywgQVIsIFROLCBOQyB8IDIsNTU1IHwgTG9zIEFuZ2VsZXMgLSBOYXNodmlsbGUgLSBSYWxlaWdoIHwgTWFqb3IgY3Jvc3MtY291bnRyeSBtZWRpY2FsIGNvcnJpZG9yIHwKfCAqKkktNzAqKiB8IENlbnRyYWwgcm91dGUgfCBVVCwgQ08sIEtTLCBNTywgSUwsIElOLCBPSCwgV1YsIFBBLCBNRCB8IDIsMTUxIHwgRGVudmVyIC0gS2Fuc2FzIENpdHkgLSBTdC4gTG91aXMgLSBDb2x1bWJ1cyB8IE1vdW50YWluIFdlc3QgdG8gTWlkLUF0bGFudGljIHwKfCAqKkktODAqKiB8IE5vcnRoZXJuIHRyYW5zY29udGluZW50YWwgfCBDQSwgTlYsIFVULCBXWSwgTkUsIElBLCBJTCwgSU4sIE9ILCBQQSwgTkosIE5ZIHwgMiw4OTkgfCBTYW4gRnJhbmNpc2NvIC0gQ2hpY2FnbyAtIE5ldyBZb3JrIHwgTWFqb3IgTm9ydGhlcm4gbWVkaWNhbCBjb3JyaWRvciB8CnwgKipJLTkwKiogfCBOb3J0aGVybiBib3JkZXIgcm91dGUgfCBXQSwgSUQsIE1ULCBXWSwgU0QsIE1OLCBXSSwgSUwsIElOLCBPSCwgUEEsIE5ZLCBNQSB8IDMsMDIwIHwgU2VhdHRsZSAtIENoaWNhZ28gLSBCb3N0b24gfCBMb25nZXN0IGludGVyc3RhdGUsIGNvbm5lY3RzIG1ham9yIE5vcnRoZXJuIGNpdGllcyB8CgojIyMgTm9ydGgtU291dGggSW50ZXJzdGF0ZSBDb3JyaWRvcnMKCnwgUm91dGUgfCBEZXNjcmlwdGlvbiB8IFN0YXRlcyBUcmF2ZXJzZWQgfCBMZW5ndGggKE1pbGVzKSB8IEtleSBDaXRpZXMgQ29ubmVjdGVkIHwgSGVhbHRoY2FyZSBSZWxldmFuY2UgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18CnwgKipJLTUqKiB8IFdlc3QgQ29hc3QgfCBDQSwgT1IsIFdBIHwgMSwzODEgfCBTYW4gRGllZ28gLSBMb3MgQW5nZWxlcyAtIFNhbiBGcmFuY2lzY28gLSBQb3J0bGFuZCAtIFNlYXR0bGUgfCBQYWNpZmljIENvYXN0IG1lZGljYWwgY29ycmlkb3IgfAp8ICoqSS0xNSoqIHwgU291dGh3ZXN0ZXJuIHwgQ0EsIE5WLCBBWiwgVVQsIElELCBNVCB8IDEsNDMzIHwgU2FuIERpZWdvIC0gTGFzIFZlZ2FzIC0gU2FsdCBMYWtlIENpdHkgfCBEZXNlcnQgU291dGh3ZXN0IGFjY2VzcyB8CnwgKipJLTI1KiogfCBNb3VudGFpbiBjb3JyaWRvciB8IE5NLCBDTywgV1kgfCAxLDA2MiB8IEFsYnVxdWVycXVlIC0gRGVudmVyIC0gQ2hleWVubmUgfCBGcm9udCBSYW5nZSBtZWRpY2FsIGFjY2VzcyB8CnwgKipJLTM1KiogfCBDZW50cmFsIFBsYWlucyB8IFRYLCBPSywgS1MsIE1PLCBJQSwgTU4gfCAxLDU2OCB8IExhcmVkbyAtIFNhbiBBbnRvbmlvIC0gQXVzdGluIC0gRGFsbGFzIC0gTWlubmVhcG9saXMgfCBUZXhhcyB0byBUd2luIENpdGllcyBjb3JyaWRvciB8CnwgKipJLTY1KiogfCBTb3V0aCBDZW50cmFsIHwgQUwsIFROLCBLWSwgSU4gfCA4ODcgfCBNb2JpbGUgLSBCaXJtaW5naGFtIC0gTmFzaHZpbGxlIC0gTG91aXN2aWxsZSAtIEluZGlhbmFwb2xpcyB8IENvbm5lY3RzIFNvdXRoZXJuIHRvIE1pZHdlc3QgbWVkaWNhbCBjZW50ZXJzIHwKfCAqKkktNzUqKiB8IEVhc3Rlcm4gY29ycmlkb3IgfCBGTCwgR0EsIFROLCBLWSwgT0gsIE1JIHwgMSw3ODYgfCBNaWFtaSAtIEF0bGFudGEgLSBDaW5jaW5uYXRpIC0gRGV0cm9pdCB8IE1ham9yIEVhc3Rlcm4gbWVkaWNhbCBjb3JyaWRvciB8CnwgKipJLTg1KiogfCBTb3V0aGVhc3Rlcm4gfCBBTCwgR0EsIFNDLCBOQywgVkEgfCA2NjYgfCBNb250Z29tZXJ5IC0gQXRsYW50YSAtIENoYXJsb3R0ZSAtIFJpY2htb25kIHwgU291dGhlYXN0IG1lZGljYWwgY29ycmlkb3IgfAp8ICoqSS05NSoqIHwgRWFzdCBDb2FzdCB8IE1FLCBOSCwgTUEsIFJJLCBDVCwgTlksIE5KLCBQQSwgREUsIE1ELCBEQywgVkEsIE5DLCBTQywgR0EsIEZMIHwgMSw5MDggfCBNaWFtaSAtIFNhdmFubmFoIC0gUmljaG1vbmQgLSBXYXNoaW5ndG9uIC0gUGhpbGFkZWxwaGlhIC0gTmV3IFlvcmsgLSBCb3N0b24gfCBQcmltYXJ5IEVhc3QgQ29hc3QgbWVkaWNhbCBjb3JyaWRvciB8CgojIyBBbHRlcm5hdGl2ZSBUcmFuc3BvcnRhdGlvbiBOZXR3b3JrIERhdGEgU291cmNlcwoKfCBEYXRhIFNvdXJjZSB8IERvd25sb2FkIFVSTCB8IEZpbGUgRm9ybWF0IHwgQ292ZXJhZ2UgfCBDb3N0IHwgTGljZW5zaW5nIHwgUXVhbGl0eSBMZXZlbCB8CnwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfAp8ICoqT3BlblN0cmVldE1hcCAoT1NNKSoqIHwgPGh0dHBzOi8vd3d3Lm9wZW5zdHJlZXRtYXAub3JnLz4gfCBWYXJpb3VzIHwgR2xvYmFsIHwgRnJlZSB8IE9wZW4gRGF0YSBMaWNlbnNlIHwgSGlnaCwgY29tbXVuaXR5IG1haW50YWluZWQgfAp8ICoqSEVSRSBNYXBzIFJvYWQgRGF0YSoqIHwgPGh0dHBzOi8vZGV2ZWxvcGVyLmhlcmUuY29tLz4gfCBBUEkvRG93bmxvYWQgfCBHbG9iYWwgfCBDb21tZXJjaWFsIHwgSEVSRSBMaWNlbnNlIHwgVmVyeSBIaWdoLCBjb21tZXJjaWFsIGdyYWRlIHwKfCAqKlRvbVRvbSBSb2FkIE5ldHdvcmsqKiB8IDxodHRwczovL2RldmVsb3Blci50b210b20uY29tLz4gfCBBUEkgfCBHbG9iYWwgfCBDb21tZXJjaWFsIHwgVG9tVG9tIExpY2Vuc2UgfCBWZXJ5IEhpZ2gsIGNvbW1lcmNpYWwgZ3JhZGUgfAoKIyMgSGlnaHdheS1TcGVjaWZpYyBSIFBhY2thZ2UgUmVzb3VyY2VzCgp8IFBhY2thZ2UgfCBGdW5jdGlvbiB8IERhdGEgSW5jbHVkZWQgfCBVc2FnZSBFeGFtcGxlIHwgTm90ZXMgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfAp8ICoqdGlncmlzKiogfCBgcHJpbWFyeV9yb2FkcygpYCwgYHByaW1hcnlfc2Vjb25kYXJ5X3JvYWRzKClgIHwgQ2Vuc3VzIFRJR0VSIHJvYWRzIHwgYHRpZ3Jpczo6cHJpbWFyeV9yb2FkcyhjYiA9IFRSVUUpYCB8IEF1dG9tYXRpY2FsbHkgZG93bmxvYWRzIGhpZ2h3YXlzIHwKfCAqKm9zbWRhdGEqKiB8IGBvcHEoKWAsIGBhZGRfb3NtX2ZlYXR1cmUoKWAgfCBPcGVuU3RyZWV0TWFwIGRhdGEgfCBgb3NtZGF0YTo6b3BxKCJVU0EiKSAlPiUgYWRkX29zbV9mZWF0dXJlKCJoaWdod2F5IiwgIm1vdG9yd2F5IilgIHwgUXVlcnkgc3BlY2lmaWMgaGlnaHdheSB0eXBlcyB8CnwgKip0aWR5dHJhbnNpdCoqIHwgVHJhbnNpdCBhbmQgcm9hZCBuZXR3b3JrIGFuYWx5c2lzIHwgR1RGUyArIHJvYWQgbmV0d29ya3MgfCBWYXJpb3VzIHwgUHVibGljIHRyYW5zcG9ydGF0aW9uIGludGVncmF0aW9uIHwKfCAqKmRvZGdyKiogfCBEaXN0YW5jZSBjYWxjdWxhdGlvbnMgb24gcm9hZCBuZXR3b3JrcyB8IE9TTSByb2FkIG5ldHdvcmtzIHwgTmV0d29yayBhbmFseXNpcyB8IFJvdXRlIG9wdGltaXphdGlvbiB8CgojIyBIaWdod2F5IERhdGEgRG93bmxvYWQgRXhhbXBsZXMKCiMjIyBJbnRlcnN0YXRlIEhpZ2h3YXlzIHZpYSB0aWdyaXMKCmBgYCByCiMgRG93bmxvYWQgYWxsIHByaW1hcnkgcm9hZHMgKGluY2x1ZGVzIEludGVyc3RhdGVzKQpwcmltYXJ5X3JvYWRzIDwtIHRpZ3Jpczo6cHJpbWFyeV9yb2FkcyhjYiA9IFRSVUUpCgojIEZpbHRlciBmb3IgSW50ZXJzdGF0ZSBoaWdod2F5cyBvbmx5CmludGVyc3RhdGVzIDwtIHByaW1hcnlfcm9hZHMgJT4lCiAgZmlsdGVyKHN0cmluZ3I6OnN0cl9kZXRlY3QoRlVMTE5BTUUsICJeSSAiKSkKCiMgU3BlY2lmaWMgSW50ZXJzdGF0ZSAoZXhhbXBsZTogSS0yNSkKaTI1IDwtIHByaW1hcnlfcm9hZHMgJT4lCiAgZmlsdGVyKHN0cmluZ3I6OnN0cl9kZXRlY3QoRlVMTE5BTUUsICJJIDI1IikpCmBgYAoKIyMjIE1ham9yIEhpZ2h3YXlzIHZpYSBPcGVuU3RyZWV0TWFwCgpgYGAgcgpsaWJyYXJ5KG9zbWRhdGEpCgojIERvd25sb2FkIEludGVyc3RhdGUgaGlnaHdheXMKaW50ZXJzdGF0ZXNfb3NtIDwtIG9wcSgiVW5pdGVkIFN0YXRlcyIpICU+JQogIGFkZF9vc21fZmVhdHVyZShrZXkgPSAiaGlnaHdheSIsIHZhbHVlID0gIm1vdG9yd2F5IikgJT4lCiAgYWRkX29zbV9mZWF0dXJlKGtleSA9ICJyZWYiLCB2YWx1ZSA9IGMoIkkgOTUiLCAiSSAyNSIsICJJIDcwIikpICU+JQogIG9zbWRhdGFfc2YoKQoKIyBEb3dubG9hZCBVUyBoaWdod2F5cyAgCnVzX2hpZ2h3YXlzIDwtIG9wcSgiVW5pdGVkIFN0YXRlcyIpICU+JQogIGFkZF9vc21fZmVhdHVyZShrZXkgPSAiaGlnaHdheSIsIHZhbHVlID0gInRydW5rIikgJT4lCiAgYWRkX29zbV9mZWF0dXJlKGtleSA9ICJyZWYiLCB2YWx1ZSA9IGMoIlVTIDUwIiwgIlVTIDEwMSIpKSAlPiUKICBvc21kYXRhX3NmKCkKYGBgCgojIyMgU3RhdGUtU3BlY2lmaWMgSGlnaHdheSBEb3dubG9hZHMKCmBgYCByCiMgQ29sb3JhZG8gaGlnaHdheXMgKGV4YW1wbGUgZm9yIEktMjUsIEktNzAsIEktNzYpCmNvX3JvYWRzIDwtIHRpZ3Jpczo6cHJpbWFyeV9zZWNvbmRhcnlfcm9hZHMoc3RhdGUgPSAiQ08iLCBjYiA9IFRSVUUpCgpjb19pbnRlcnN0YXRlcyA8LSBjb19yb2FkcyAlPiUKICBmaWx0ZXIoc3RyaW5ncjo6c3RyX2RldGVjdChGVUxMTkFNRSwgIl5JICIpKSAlPiUKICBmaWx0ZXIoc3RyaW5ncjo6c3RyX2RldGVjdChGVUxMTkFNRSwgIkkgMjV8SSA3MHxJIDc2IikpCmBgYAoKIyMgSGlnaHdheSBBbmFseXNpcyBBcHBsaWNhdGlvbnMgZm9yIEhlYWx0aGNhcmUgQWNjZXNzaWJpbGl0eQoKIyMjIEludGVyc3RhdGUgQ29ycmlkb3IgQW5hbHlzaXMKCi0gICAqKkktOTUgQ29ycmlkb3IqKjogRWFzdCBDb2FzdCBtZWRpY2FsIHJlZmVycmFsIHBhdHRlcm5zCi0gICAqKkktMTAgQ29ycmlkb3IqKjogU291dGhlcm4gdHJhbnNjb250aW5lbnRhbCBhY2Nlc3MKLSAgICoqSS0yNSBGcm9udCBSYW5nZSoqOiBEZW52ZXItQ29sb3JhZG8gU3ByaW5ncy1BbGJ1cXVlcnF1ZSBtZWRpY2FsIGNvcnJpZG9yCi0gICAqKkktNzAgTW91bnRhaW4gQ29ycmlkb3IqKjogTW91bnRhaW4gV2VzdCBoZWFsdGhjYXJlIGFjY2VzcwoKIyMjIEhpZ2h3YXkgQnVmZmVyIEFuYWx5c2lzCgpgYGAgcgojIENyZWF0ZSBidWZmZXJzIGFyb3VuZCBtYWpvciBoaWdod2F5cyBmb3IgYWNjZXNzaWJpbGl0eSBhbmFseXNpcwpoaWdod2F5X2J1ZmZlcnMgPC0gaW50ZXJzdGF0ZXMgJT4lCiAgc3RfYnVmZmVyKGRpc3QgPSB1bml0czo6c2V0X3VuaXRzKDUwLCAibWlsZXMiKSkgICMgNTAtbWlsZSBoaWdod2F5IGNvcnJpZG9yCmBgYAoKIyMgQ2FuY2VyIENhcmUgYW5kIFNwZWNpYWx0eSBNZWRpY2FsIEFyZWFzCgp8IEdlb2dyYXBoaWMgVW5pdCB8IERhdGEgU291cmNlIHwgRG93bmxvYWQgVVJMIHwgRmlsZSBGb3JtYXQgfCBDb3ZlcmFnZSB8IFVwZGF0ZSBGcmVxdWVuY3kgfCBOb3RlcyB8CnwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfAp8ICoqTkNJLURlc2lnbmF0ZWQgQ2FuY2VyIENlbnRlcnMqKiB8IE5hdGlvbmFsIENhbmNlciBJbnN0aXR1dGUgfCA8aHR0cHM6Ly93d3cuY2FuY2VyLmdvdi9yZXNlYXJjaC9pbmZyYXN0cnVjdHVyZS9jYW5jZXItY2VudGVycy9maW5kPiB8IFBvaW50IGRhdGEgKGdlb2NvZGUgYWRkcmVzc2VzKSB8IE5hdGlvbmFsIHwgQXMgZGVzaWduYXRlZCB8IENvbXByZWhlbnNpdmUgY2FuY2VyIGNlbnRlcnMgfAp8ICoqQ29DLUFjY3JlZGl0ZWQgQ2FuY2VyIFByb2dyYW1zKiogfCBDb21taXNzaW9uIG9uIENhbmNlciB8IDxodHRwczovL3d3dy5mYWNzLm9yZy9xdWFsaXR5LXByb2dyYW1zL2NhbmNlci1wcm9ncmFtcy9jb21taXNzaW9uLWNhbmNlci9jb2MtYWNjcmVkaXRlZC1wcm9ncmFtcy8+IHwgUG9pbnQgZGF0YSAoZ2VvY29kZSBhZGRyZXNzZXMpIHwgTmF0aW9uYWwgfCBBbm51YWwgfCBBY2NyZWRpdGVkIGNhbmNlciBwcm9ncmFtcyB8CnwgKipOQ0NOIE1lbWJlciBJbnN0aXR1dGlvbnMqKiB8IE5DQ04gfCA8aHR0cHM6Ly93d3cubmNjbi5vcmcvYWJvdXQvbWVtYmVyLWluc3RpdHV0aW9ucz4gfCBQb2ludCBkYXRhIChnZW9jb2RlIGFkZHJlc3NlcykgfCBOYXRpb25hbCB8IEFzIG1lbWJlcnNoaXAgY2hhbmdlcyB8IExlYWRpbmcgY2FuY2VyIGNlbnRlcnMgfAoKIyMgQW1lcmljYW4gQ29tbXVuaXR5IFN1cnZleSBHZW9ncmFwaGljIFN1bW1hcnkgTGV2ZWxzCgp8IEdlb2dyYXBoaWMgVW5pdCB8IFN1bW1hcnkgTGV2ZWwgQ29kZSB8IERvd25sb2FkIFVSTCB8IEZpbGUgRm9ybWF0IHwgQ292ZXJhZ2UgfCBVcGRhdGUgRnJlcXVlbmN5IHwgTm90ZXMgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfC0tLS18LS0tLXwKfCAqKk5hdGlvbioqIHwgMDEwIHwgPGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvZ2VvZ3JhcGhpZXMvbWFwcGluZy1maWxlcy90aW1lLXNlcmllcy9nZW8vdGlnZXItbGluZS1maWxlLmh0bWw+IHwgU2hhcGVmaWxlIHwgVVMgfCBBbm51YWwgfCBOYXRpb25hbCBib3VuZGFyeSB8CnwgKipSZWdpb25zKiogfCAwMjAgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9tYXBwaW5nLWZpbGVzL3RpbWUtc2VyaWVzL2dlby90aWdlci1saW5lLWZpbGUuaHRtbD4gfCBTaGFwZWZpbGUgfCBVUyB8IEFubnVhbCB8IDQgQ2Vuc3VzIHJlZ2lvbnMgfAp8ICoqRGl2aXNpb25zKiogfCAwMzAgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9tYXBwaW5nLWZpbGVzL3RpbWUtc2VyaWVzL2dlby90aWdlci1saW5lLWZpbGUuaHRtbD4gfCBTaGFwZWZpbGUgfCBVUyB8IEFubnVhbCB8IDkgQ2Vuc3VzIGRpdmlzaW9ucyB8CnwgKipTdGF0ZXMqKiB8IDA0MCB8IDxodHRwczovL3d3dy5jZW5zdXMuZ292L2dlb2dyYXBoaWVzL21hcHBpbmctZmlsZXMvdGltZS1zZXJpZXMvZ2VvL3RpZ2VyLWxpbmUtZmlsZS5odG1sPiB8IFNoYXBlZmlsZSB8IFVTIHwgQW5udWFsIHwgNTAgc3RhdGVzICsgREMgfAp8ICoqQ291bnRpZXMqKiB8IDA1MCB8IDxodHRwczovL3d3dy5jZW5zdXMuZ292L2dlb2dyYXBoaWVzL21hcHBpbmctZmlsZXMvdGltZS1zZXJpZXMvZ2VvL3RpZ2VyLWxpbmUtZmlsZS5odG1sPiB8IFNoYXBlZmlsZSB8IFVTIHwgQW5udWFsIHwgXH4zLDEwMCBjb3VudGllcyB8CnwgKipDb3VudHkgU3ViZGl2aXNpb25zKiogfCAwNjAgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9tYXBwaW5nLWZpbGVzL3RpbWUtc2VyaWVzL2dlby90aWdlci1saW5lLWZpbGUuaHRtbD4gfCBTaGFwZWZpbGUgfCBVUyB8IEFubnVhbCB8IFRvd25zaGlwcywgYm9yb3VnaHMsIGV0Yy4gfAp8ICoqQ2Vuc3VzIFRyYWN0cyoqIHwgMTQwIHwgPGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvZ2VvZ3JhcGhpZXMvbWFwcGluZy1maWxlcy90aW1lLXNlcmllcy9nZW8vdGlnZXItbGluZS1maWxlLmh0bWw+IHwgU2hhcGVmaWxlIHwgVVMgfCBBbm51YWwgfCBcfjc0LDAwMCB0cmFjdHMgfAp8ICoqQmxvY2sgR3JvdXBzKiogfCAxNTAgfCA8aHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9tYXBwaW5nLWZpbGVzL3RpbWUtc2VyaWVzL2dlby90aWdlci1saW5lLWZpbGUuaHRtbD4gfCBTaGFwZWZpbGUgfCBVUyB8IEFubnVhbCB8IFx+MjIwLDAwMCBibG9jayBncm91cHMgfAoKIyMgU3BlY2lhbCBSIFBhY2thZ2UgUmVzb3VyY2VzIGZvciBHZW9ncmFwaGljIERhdGEKCnwgUGFja2FnZSB8IEZ1bmN0aW9uIHwgRGF0YSBJbmNsdWRlZCB8IFVzYWdlIHwgTm90ZXMgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwtLS0tfAp8ICoqdGlncmlzKiogfCBgc3RhdGVzKClgLCBgY291bnRpZXMoKWAsIGB0cmFjdHMoKWAsIGBibG9ja19ncm91cHMoKWAgfCBBbGwgQ2Vuc3VzIGJvdW5kYXJpZXMgfCBgdGlncmlzOjpzdGF0ZXMoY2IgPSBUUlVFKWAgfCBBdXRvbWF0aWNhbGx5IGRvd25sb2FkcyBhbmQgY2FjaGVzIHwKfCAqKnRpZHljZW5zdXMqKiB8IGBnZXRfYWNzKC4uLiwgZ2VvbWV0cnkgPSBUUlVFKWAgfCBDZW5zdXMgZGF0YSArIGJvdW5kYXJpZXMgfCBgZ2V0X2FjcyhnZW9ncmFwaHkgPSAidHJhY3QiLCBnZW9tZXRyeSA9IFRSVUUpYCB8IERhdGEgYW5kIGdlb2dyYXBoeSBjb21iaW5lZCB8CnwgKipzZioqIHwgU3BhdGlhbCBkYXRhIHByb2Nlc3NpbmcgfCBcLSB8IGBzdF9yZWFkKCJzaGFwZWZpbGUuc2hwIilgIHwgQ29yZSBzcGF0aWFsIGFuYWx5c2lzIHwKfCAqKlVTQWJvdW5kYXJpZXMqKiB8IEhpc3RvcmljYWwgVVMgYm91bmRhcmllcyB8IENvdW50aWVzLCBzdGF0ZXMgKDE2MjktMjAwMCkgfCBgdXNfc3RhdGVzKG1hcF9kYXRlID0gIjIwMDAtMDEtMDEiKWAgfCBIaXN0b3JpY2FsIGFuYWx5c2lzIHwKfCAqKnNwRGF0YSoqIHwgU3BhdGlhbCBkYXRhc2V0cyB8IFZhcmlvdXMgZXhhbXBsZSBkYXRhc2V0cyB8IGBkYXRhKHVzX3N0YXRlcylgIHwgVGVhY2hpbmcgYW5kIGV4YW1wbGVzIHwKCiMjIEZpbGUgRG93bmxvYWQgRXhhbXBsZXMgYW5kIFIgQ29kZQoKIyMjIENlbnN1cyBCb3VuZGFyaWVzIHZpYSB0aWdyaXMgUGFja2FnZQoKYGBgIHIKIyBEb3dubG9hZCBzdGF0ZSBib3VuZGFyaWVzCnN0YXRlc19zZiA8LSB0aWdyaXM6OnN0YXRlcyhjYiA9IFRSVUUsIHJlc29sdXRpb24gPSAiMjBtIikKCiMgRG93bmxvYWQgY2Vuc3VzIHRyYWN0cyBmb3Igc3BlY2lmaWMgc3RhdGUgIAp0cmFjdHNfc2YgPC0gdGlncmlzOjp0cmFjdHMoc3RhdGUgPSAiQ08iLCBjYiA9IFRSVUUpCgojIERvd25sb2FkIGJsb2NrIGdyb3VwcyBmb3Igc3BlY2lmaWMgY291bnR5CmJnX3NmIDwtIHRpZ3Jpczo6YmxvY2tfZ3JvdXBzKHN0YXRlID0gIkNPIiwgY291bnR5ID0gIjAwMSIsIGNiID0gVFJVRSkKYGBgCgojIyMgSFJTQSBEYXRhIERvd25sb2FkCgpgYGAgcgojIERvd25sb2FkIEhQU0EgZGF0YQpocHNhX3VybCA8LSAiaHR0cHM6Ly9kYXRhLmhyc2EuZ292L2RhdGEvZG93bmxvYWQvaHJzYS1ocHNhLXByaW1hcnktY2FyZS1zaG9ydGFnZS1hcmVhcy5jc3YiCmhwc2FfZGF0YSA8LSByZWFkcjo6cmVhZF9jc3YoaHBzYV91cmwpCmBgYAoKIyMgRGF0YSBWaW50YWdlIGFuZCBDb21wYXRpYmlsaXR5IE5vdGVzCgp8IEdlb2dyYXBoaWMgVW5pdCB8IDIwMTAgQ2Vuc3VzIFZpbnRhZ2UgfCAyMDIwIENlbnN1cyBWaW50YWdlIHwgQ29tcGF0aWJpbGl0eSBJc3N1ZXMgfAp8LS0tLXwtLS0tfC0tLS18LS0tLXwKfCAqKkNlbnN1cyBUcmFjdHMqKiB8IFx+NzQsMDAwIHRyYWN0cyB8IFx+ODQsMDAwIHRyYWN0cyB8IFRyYWN0IGJvdW5kYXJpZXMgY2hhbmdlZCBzaWduaWZpY2FudGx5IHwKfCAqKkJsb2NrIEdyb3VwcyoqIHwgXH4yMTcsMDAwIEJHcyB8IFx+MjQyLDAwMCBCR3MgfCBNYW55IGJvdW5kYXJ5IGNoYW5nZXMgfAp8ICoqQ291bnRpZXMqKiB8IDMsMTQzIGNvdW50aWVzIHwgMywxNDMgY291bnRpZXMgfCBTdGFibGUgYm91bmRhcmllcyB8CnwgKipTdGF0ZXMqKiB8IDUwICsgREMgfCA1MCArIERDIHwgTm8gY2hhbmdlcyB8CnwgKipaQ1RBcyoqIHwgMjAxMCBaSVAgcGF0dGVybnMgfCAyMDIwIFpJUCBwYXR0ZXJucyB8IFNpZ25pZmljYW50IGNoYW5nZXMgaW4gc3VidXJiYW4gYXJlYXMgfAoKIyBMaWNlbnNlCgpNSVQgKGFsbG93cyBjb21tZXJjaWFsIGFuZCBhY2FkZW1pYyB1c2Ugd2l0aCBhdHRyaWJ1dGlvbikKCiMg8J+knSBDb250cmlidXRpbmcKCldlIHdlbGNvbWUgY29udHJpYnV0aW9ucyEKCiMg8J+TnCBDaXRhdGlvbgoKSWYgeW91IHVzZSB0aGlzIHdvcmsgaW4geW91ciByZXNlYXJjaCwgcGxlYXNlIGNpdGU6CgpgYGAgYmlidGV4CkBtaXNje211ZmZseTIwMjVneW5vbmNhY2Nlc3MsCiAgdGl0bGU9e0d5bmVjb2xvZ2ljIE9uY29sb2d5IEFjY2Vzc2liaWxpdHkgUHJvamVjdDogTmF0aW9ud2lkZSBBbmFseXNpcyBvZiBBY2Nlc3MgdG8gT0JHWU4gU3Vic3BlY2lhbGlzdHMgVXNpbmcgRHJpdmUgVGltZSBJc29jaHJvbmVzICgyMDEzLTIwMjMpfSwKICBhdXRob3I9e011ZmZseSwgVHlsZXJ9LAogIHllYXI9ezIwMjV9LAogIHVybD17aHR0cHM6Ly9naXRodWIuY29tL211ZmZseXQvaXNvY2hyb25lc30sCiAgbm90ZT17VmVyc2lvbiAyLjAuMH0KfQpgYGAKCiMgQ29udGFjdAoKKipQcmltYXJ5IENvbnRhY3QqKjogVHlsZXIgTXVmZmx5LCBNRFwKKipFbWFpbCoqOiBbdHlsZXIubXVmZmx5XEBkaGhhLm9yZ10obWFpbHRvOnR5bGVyLm11ZmZseUBkaGhhLm9yZyl7LmVtYWlsfVwKKipHaXRIdWIqKjogPGh0dHBzOi8vZ2l0aHViLmNvbS9tdWZmbHl0L2lzb2Nocm9uZXM+CgojIFByb2plY3QgTWFpbnRlbmFuY2UgU2NoZWR1bGUKCi0gICAqKkFubnVhbCBVcGRhdGVzKio6IE5ldyBOUFBFUyBkYXRhIHJlbGVhc2UgKHR5cGljYWxseSBNYXJjaCkKLSAgICoqQVBJIE1vbml0b3JpbmcqKjogTW9udGhseSBjaGVja3Mgb2YgcmF0ZSBsaW1pdHMgYW5kIGNvc3RzCi0gICAqKkRhdGEgVmFsaWRhdGlvbioqOiBCaWFubnVhbCByZXZpZXcgb2YgcHJvdmlkZXIgbGlzdHMKLSAgICoqQ29kZSBVcGRhdGVzKio6IEFzIG5lZWRlZCBmb3IgUiBwYWNrYWdlIGNoYW5nZXMKCiMgCg==