Setup and Libraries

knitr::opts_chunk$set(echo = TRUE, error = TRUE, cache=TRUE, autodep = TRUE, message = FALSE, progress_bar = FALSE)

library(readr)
library(tidyverse) 
library(dplyr) 
library(ggplot2) 
library(knitr) 
library(psych)
library(lme4)
library(boot)
library(ggeffects) 
library(DescTools)
library(tidycensus)
library(xml2)
library(tmap)
library(tmaptools)
library(leaflet)
library(sf)
library(leaflet.extras)
library(raster)
library(tigris)
library(sp)
library(scales)
library(stringi)
library(leaflegend)
library(readxl)
library(readr)
library(stringr)
library(janitor)
library(ggrepel)
setwd("/Users/eleanorprickettmorgan/Desktop/DeportationData/")

Importing Data

I’m skipping 6 because the first 6 rows of the excel file have summary information, but the data itself doesn’t actually start. Then I’m using Summary to check what my time range is, looking specifically at the Apprehension column.

AdminArrest <- read_excel("/Users/eleanorprickettmorgan/Desktop/DeportationData/ERO Admin Arrests_LESA-STU-FINAL Release_raw.xlsx", skip = 6)
View(AdminArrest)
summary(AdminArrest)
 Apprehension Date             Apprehension State Apprehension County Apprehension AOR   Final Program      Final Program Group Apprehension Method
 Min.   :2023-09-01 00:00:00   Length:377067      Mode:logical        Length:377067      Length:377067      Length:377067       Length:377067      
 1st Qu.:2024-06-19 12:29:00   Class :character   NA's:377067         Class :character   Class :character   Class :character    Class :character   
 Median :2025-03-12 13:50:00   Mode  :character                       Mode  :character   Mode  :character   Mode  :character    Mode  :character   
 Mean   :2024-12-31 02:24:47                                                                                                                       
 3rd Qu.:2025-07-14 11:13:21                                                                                                                       
 Max.   :2025-10-16 00:31:07                                                                                                                       
                                                                                                                                                   
 Apprehension Criminality Case Status        Case Category      Departed Date                 Departure Country  Final Order Yes No
 Length:377067            Length:377067      Length:377067      Min.   :1923-09-14 00:00:00   Length:377067      Length:377067     
 Class :character         Class :character   Class :character   1st Qu.:2024-10-02 00:00:00   Class :character   Class :character  
 Mode  :character         Mode  :character   Mode  :character   Median :2025-05-04 00:00:00   Mode  :character   Mode  :character  
                                                                Mean   :2025-02-18 23:21:58                                        
                                                                3rd Qu.:2025-08-04 00:00:00                                        
                                                                Max.   :2025-10-15 00:00:00                                        
                                                                NA's   :140929                                                     
 Final Order Date               Birth Date          Birth Year   Citizenship Country    Gender          Apprehension Site Landmark Alien File Number 
 Min.   :1967-01-06 00:00:00   Length:377067      Min.   :1932   Length:377067       Length:377067      Length:377067              Length:377067     
 1st Qu.:2019-09-26 00:00:00   Class :character   1st Qu.:1983   Class :character    Class :character   Class :character           Class :character  
 Median :2024-06-20 00:00:00   Mode  :character   Median :1991   Mode  :character    Mode  :character   Mode  :character           Mode  :character  
 Mean   :2021-06-04 17:40:28                      Mean   :1990                                                                                       
 3rd Qu.:2025-05-09 00:00:00                      3rd Qu.:1998                                                                                       
 Max.   :2025-10-16 00:00:00                      Max.   :2025                                                                                       
 NA's   :147872                                   NA's   :1                                                                                          
 EID Case ID        EID Subject ID     Unique Identifier 
 Length:377067      Length:377067      Length:377067     
 Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character   Mode  :character  
                                                         
                                                         
                                                         
                                                         

Cleaning the Data

Checking for Duplicates

To check for duplicates I’m going to look at the unique identifier column.

AdminArrest %>%
  group_by(`Unique Identifier`) %>%
  filter(n()==2)
NA

I get back 27,214 rows where the Unique identifier repeated itself. But I can tell that there are certain instances where the same identifier appears twice with a different apprehension date. So I’m going to try again looking at Apprehension Date in addition to the Unique Identifier column.

AdminArrest %>%
  group_by(`Unique Identifier`, `Apprehension Date`) %>%
  filter(n()==2)

When I filter by both of these things I get 3,304 rows. That suggests that maybe certain individuals were arrested twice, or have been in the system multiple times over the course of many years, this is closer to the true number of duplicates. So now I’m going to remove those potential duplicates using the distinct function.

cleaned_AdminArrest <- AdminArrest %>%
  distinct(`Unique Identifier`,`Apprehension Date`, .keep_all = TRUE)
View(cleaned_AdminArrest)

When I run this I now have 289,927 entries instead of the original 291722. I would probably still ask an expert who works with this data if there are other ways I might not be catching duplicates but this makes the most sense to me.

For later on I’m going to make a version of this national admin arrest data that I can merge with a shapefile for mapping.

Filtered_AdminArrest <- cleaned_AdminArrest %>%
  drop_na(`Apprehension AOR`)

View(Filtered_AdminArrest)
Mutate_AdminArrest <- Filtered_AdminArrest %>%
  filter(`Apprehension AOR`!= "HQ Area of Responsibility")  %>%
  mutate(ApprehensionAORcleaned1 = str_remove(`Apprehension AOR`,"Area of Responsibility")) %>%
  mutate(ApprehensionAORcleaned2 = str_remove(`ApprehensionAORcleaned1`,"HQ")) %>%
  mutate(ApprehensionAORcleaned3 = str_replace_all(`ApprehensionAORcleaned2`,"St. Paul", "St Paul"))
  

Mutate_AdminArrest %>%
  group_by(ApprehensionAORcleaned3) %>%
  tally()
NA

I’m going to use this for QGIS mapping, so this is me exporting this dataframe as a csv

write_csv(Mutate_AdminArrest, "/Users/eleanorprickettmorgan/Desktop/DeportationData/AdminArrestMapping.csv")

Checking for Consistency Issues

Apprehension State

To check for consistency issues, I’m going to look at the column names dealing primarily with characters. So for example for states I know that I want 50 ideally, and I would check by doing the following:

cleaned_AdminArrest %>%
  group_by(`Apprehension State`) %>%
  tally()

Here there are a couple consistency issues, some of the things included in States are three locations labeled “ARMED FORCES - EUROPE, ARMED FORCES - THE AMERICAS, ARMED SERVICES - THE PACIFIC.” I have no idea what differentiates armed forces vs. services, nor am I clear if these are arrests that took place on military bases or as a part of Military operations. Worth noting that we have 62 rows, instead of 50, which is partially because of territories under US control (i.e. Puerto Rico, Federated States of Micronesia, Guam, etc.) District of Columbia is also it’s own entry, and it’s not a state. There are also two lone entries in areas outside of US control, one just labeled “MEXICO,” the other labeled “TAMAULIPAS,” which is a territory in Mexico. Those seem like individual data entry issues or miscategorizations. Aside from that, the states themselves are spelled in consistent ways.

AOR (Area of Responsibility)

Now I’m going to perform a similar test on the AOR column for consistency. From the ICE.gov website I’m expecting 25 AOR’s.

cleaned_AdminArrest %>%
  group_by(`Apprehension AOR`) %>%
  tally()
NA

Here I got 27 rows back, one corresponded to N/A, with 5223 entries not assigned to a specific geography. There’s also a mysterious HQ Area of Responsibility, which is not listed online with only 50 entries. I would again have to ask someone who works with this data regularly what this means.

Final Program

Now I’ll do the same with the final program column:

cleaned_AdminArrest %>%
  group_by(`Final Program`) %>%
  tally()

Here the most obvious issue which populates first is what’s the difference between “287G Program” and “287g Task Force.” Because my project is in California which is (allegedly) not participating in 287g, I’m not worried about that. I would want to double check with an expert that some of these things do not refer to the same practical categories. I am concerned about the 487 Juveniles listed here.

Final Program Group

Because this is ICE data, I would assume everything in the final program group column is ICE, but I’m just double checking.

cleaned_AdminArrest %>%
  group_by(`Final Program Group`) %>%
  tally()

That produced just one row, so that’s consistent.

Apprehension Method

Now I’m checking for apprehension method:

cleaned_AdminArrest %>%
  group_by(`Apprehension Method`) %>%
  tally()

In terms of how things are literally spelled yes there is consistency. In terms of what the data is saying here, I do have a lot of questions. For example only one person is listed as arrested in the “Presented During Inspection” category, which feels like a contradiction with the courthouse and field office check-ins having so many individuals grabbed by ICE. However, those might be a different category of enforcement that’s included in another data set (i.e. detentions). This is probably my flawed understanding of the legal system here, but still something I want to note.

Apprehension Criminality

Now I’m going to check for apprehension criminality:

cleaned_AdminArrest %>%
  group_by(`Apprehension Criminality`) %>%
  tally()

Here I get back only three rows, which is consistent with my understanding of folks are categorized in these situations.

Case Status

Now I’ll check for case status:

cleaned_AdminArrest %>%
  group_by(`Case Status`) %>%
  tally()

Here I get back 14 rows with categories listed. The first chunk are numbered starting at 0, but notably missing 1 and 2. I don’t know what those categories could be. There are 4462 who are not in a category at all, which is confusing because one category is literally just for active cases. There are also some acronyms I don’t understand, “9-VR Witnessed” I assume is voluntary removal witnessed, how is that different than voluntary departure? I’m concerned also about the 41 deaths listed. I’d also like to understand the difference between “L-Legalization - Permanent Residence Granted” and “Z-SAW - Permanent Residence Granted.”

Case Category

Now I’ll look at Case Category:

cleaned_AdminArrest %>%
  group_by(`Case Category`) %>%
  tally()

Here there are no glaring consistency issues except the 4412 uncategorized cases.

Departure Country

Now I’ll check for Departure Country:

cleaned_AdminArrest %>%
  group_by(`Departure Country`) %>%
  tally()

I got back 193 rows which is in line with the number of countries in the world (depending on who you ask, but at least in line with the number of countries the US recognizes). Clicking through I didn’t see any super weird duplicates. One row is N/A but from looking at the other columns in conjunction, I think a departure country is only entered when the departure happens. So the active cases don’t have a departure country listed.

Final Order Yes or No

Now I’ll check final order Yes or No (hopefully 2 rows).

cleaned_AdminArrest %>%
  group_by(`Final Order Yes No`) %>%
  tally()

Here we get back Yes, No, or Blank (4412 rows).

Citizenship Country

Now I’ll look at citizenship country

cleaned_AdminArrest %>%
  group_by(`Citizenship Country`) %>%
  tally()

My citizenship countries outnumber my departure countries by 3, I would want to compare those and see where I have additional citizenship but not departure. Notably no one here is uncategorized.

Gender

Now I’m checking for gender which I’m expecting 2 rows for:

cleaned_AdminArrest %>%
  group_by(Gender) %>%
  tally()

We get back three rows: Female, Male, and Unknown. Important to note that unknown is written in, and isn’t just a blank.

Apprehension Site Landmark

Now I’m checking for Apprehension Site Landmark. This is where I’m expecting the most inconsistencies.

cleaned_AdminArrest %>%
  group_by(`Apprehension Site Landmark`) %>%
  tally()

Here I get back 500 rows, and there are major differences in capitalization and usage of Dashes. Some include the state they were in, others do not. Some also includde the program they were in (297(g), CAP, etc.). For the purposes of my project I’d probably take the California subset and clean that, but this would likely be the most onerous part of working with this data.

Checking for Missing Data

Now to check for missing data, I’m going to use/refer to the original unclean data “AdminArrest”:

MissingData <-colSums(is.na(AdminArrest))
print(MissingData)
         Apprehension Date         Apprehension State        Apprehension County           Apprehension AOR              Final Program 
                         0                      60154                     377067                       5887                          0 
       Final Program Group        Apprehension Method   Apprehension Criminality                Case Status              Case Category 
                         0                          0                          0                       9372                       9373 
             Departed Date          Departure Country         Final Order Yes No           Final Order Date                 Birth Date 
                    140929                     140983                       9372                     147872                          1 
                Birth Year        Citizenship Country                     Gender Apprehension Site Landmark          Alien File Number 
                         1                          0                          0                       8767                       5410 
               EID Case ID             EID Subject ID          Unique Identifier 
                      9372                          0                       5410 

Additional Altering

Creating a New Column to Look at Time of Arrest

I want to mutate the apprehension date column so that I can filter later by year and month, and even potentially the time of day an administrative arrest took place.

new_AdminArrest <-cleaned_AdminArrest%>% 
  mutate(ApprehensionYear = year(`Apprehension Date`))%>% 
  mutate(ApprehensionMonth = month(`Apprehension Date`))%>% 
  mutate(ApprehensionDay = day(`Apprehension Date`))%>% 
  mutate(ApprehensionHour = hour(`Apprehension Date`))

View(new_AdminArrest)

Breaking out California and San Francisco Area of Responsibility Data.

Now I want to look at just administrative arrests in California, so I’m going to filter by the apprehension state column.

CA_AdminArrest <- new_AdminArrest %>%
  filter(`Apprehension State` == "CALIFORNIA")
View(CA_AdminArrest)

I want to filter that further to just the Administrative arrests in the SF Area of Responsibility, because even though that’s actually a lot larger than the geographic scope my project is looking at, it at least includes my area the Bay Area.

SFAOR_AdminArrest <- CA_AdminArrest %>% 
  filter(`Apprehension AOR` == "San Francisco Area of Responsibility")
View(SFAOR_AdminArrest)

Analysis

Adminsitrative Arrests Over Time

A really basic comparison I might make to start is comparing the number of Administrative Arrests by year.

SFAOR_AdminArrest %>% 
  group_by(ApprehensionYear) %>% 
  tally()

But the table I get here actually isn’t that informative given that I only have data from three years. But maybe I just want to see the change in time by month of just this new administration (2025), So I’d likely do the following:

SFAOR_AdminArrestbyMonth <-SFAOR_AdminArrest %>% 
  filter(ApprehensionYear == "2025") %>% 
  group_by(ApprehensionMonth) %>% 
  tally()
View(SFAOR_AdminArrestbyMonth)

Just looking at the table I see there’s an increase in June which held in July, but it might be helpful to visualize it, so I’m going to look at plot it out:

ggplot(data=SFAOR_AdminArrestbyMonth) +
  geom_line(aes(x=ApprehensionMonth, y=n)) +
  xlim(1,11) +
  scale_x_continuous(breaks = scales::breaks_extended(n = 11))+
  scale_y_continuous(limits = c(0,800), breaks = c(0,100,200,300,400,500,600,700,800))+
  labs( x = "Month", y = "Number of Arrests") +
  ggtitle("Administrative Arrests by Month") +
  theme(plot.title = element_text(hjust = 0.5))

NA

Administrative Arrests by Hour

Anecdotally, I’ve also heard this thing from a number of advocates that ICE actions (arrests) tend to happen in the early morning. I want to check if that’s true, so I’m going to look at the ApprehensionHour column that I mutated out of the original Apprehension Date column. It’s on a 24 hour clock (no am/pm). I’m going to use the CA_AdminArrest data because according to advocates this represents ICE policy so it should be true across the state.

CA_AdminArrest_byHour <- CA_AdminArrest %>%
  group_by(ApprehensionHour) %>%
  tally()

View(CA_AdminArrest_byHour)

To see that visually I’m going to chart it.

ggplot(data=CA_AdminArrest_byHour, aes(x = ApprehensionHour, y = n)) +
  geom_bar(stat="identity", width=0.5, fill= "steelblue") +
  labs( x = "Hour of the Day", y = "Number of Arrests") +
  ggtitle("Administrative Arrests by Hour of the Day from Sept 2023 through Oct 2025") +
  scale_x_continuous(n.breaks=23)

This shows that the number of arrests peaks betwen 9 and 10 am, and if the actual arrests are taking place at that hour we can infer that ICE/DHS had to be active before then. The majority of the activity seems to happen between 7am and 1pm.

Countries of Origin

Another thing I’m interested in is under the current administration, what are the top countries of origin for folks being arrested. I’m interested both statewide and for just the San Francisco AOR, but I’ll start with just California

CaliforniaCitizenshipCountry2025 <- CA_AdminArrest %>%
  filter(ApprehensionYear == "2025") %>%
  group_by(`Citizenship Country`) %>%
  tally() 

View(CaliforniaCitizenshipCountry2025)

When I do this and sort by values my top 10 citizenship countries are Mexico, Guatemala, El Salvador, Colombia, Honduras, India, Venezuela, China, Nicaragua and Peru. To compare this to the SFAOR I’m doing a similar analysis

SFAORCitizenshipCountry2025 <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025") %>%
  group_by(`Citizenship Country`) %>%
  tally() 

View(SFAORCitizenshipCountry2025)

When I sort this table by the count, I get slightly different results, but there is a lot of overlap. In the San Francisco Area of Responsibility the top 10 citizenship countries for arrested folks are Mexico, India, Guatemala, El Salvador, Colombia, Honduras, Peru, Nicaragua, Venezuela, and China. Mexico notably outpaces the rest of these places in number of arrests.

Criminality

Something else I’m interested in is the “criminality” of those arrested in the San Francisco Area of responsibility. Again I want to look just in the context of the current administration. Those who are arrested are assigned to one of three categories of criminality, but I’m interested in the proportion that those categories show up in arrests.

SFAORArrestCriminality2025 <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(SFAORArrestCriminality2025)

I want to see this visually, so even though I’m not a fan of pie charsts I’m going to look at it in a pie chart.

ggplot(SFAORArrestCriminality2025, aes(x="Apprehension Criminality", y=n, fill=`Apprehension Criminality`)) +
  geom_bar(stat="identity", width=1, color="white") +
  coord_polar("y", start=0) +
  ggtitle("Apprehension Criminality SFAOR 2025") +
  theme_void()

For those arrested the majority are convicted criminals, according to the data, but it’s notable that a sizable chunk are categorized under “other immigration violation.” Arrests are supposed to represent individuals have a real case against them, so the convicted criminal category should represented the majority. And these arrests are not the totality of deportations, if you look at the deportation data set in addition to this arrests data, you would find the majority of folks coming in to contact with ICE/DHS do not have any criminal convictions. It’s also worth noting that the convicted criminal category doesn’t break down further into what crimes folks were convicted of. Other reporting has confirmed that there are many folks who end up arrested where the basis of their conviction is a traffic violation. I talked to one lawyer in the Bay Area who confirmed they had a client where a prior conviction came in the form of a citation for failing to pay for BART. Are those crimes the same as murder? No, but under this categorization they’re flattened into one category together.

Just to make sure my analysis isn’t off I’m going to compare SF in 2025 to all of California.

CA_ArrestCriminality2025 <- CA_AdminArrest %>%
  filter(ApprehensionYear == "2025") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(CA_ArrestCriminality2025)

Here is that information visualized:

ggplot(CA_ArrestCriminality2025, aes(x="Apprehension Criminality", y=n, fill=`Apprehension Criminality`)) +
  geom_bar(stat="identity", width=1, color="white") +
  coord_polar("y", start=0) +
  ggtitle("Apprehension Criminality All of California 2025") +
  theme_void()

The proportions I get here are very different. Other Immigration Violator is nearly the same value as Convicted Criminal. I’m curious as to what’s at the root of this discrepancy in San Francisco. I do wonder if this has something to do with the lack of indiscriminate raids in the Bay Area, which means that in places like LA there is a much higher proportion of people who are being swept up by this system.

I want to do a visualization showing how arrest criminality changes by month under this administration so I’m going to filter to make multiple tables:

SFAORJan25Crim <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025", ApprehensionMonth == "1") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(SFAORJan25Crim)
SFAORFeb25Crim <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025", ApprehensionMonth == "2") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(SFAORFeb25Crim)
SFAORMar25Crim <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025", ApprehensionMonth == "3") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(SFAORMar25Crim)
SFAORApr25Crim <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025", ApprehensionMonth == "4") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(SFAORApr25Crim)
SFAORMay25Crim <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025", ApprehensionMonth == "5") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(SFAORMay25Crim)
SFAORJun25Crim <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025", ApprehensionMonth == "6") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(SFAORJun25Crim)
SFAORJul25Crim <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025", ApprehensionMonth == "7") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(SFAORJul25Crim)
SFAORAug25Crim <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025", ApprehensionMonth == "8") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(SFAORAug25Crim)
SFAORSept25Crim <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025", ApprehensionMonth == "9") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(SFAORSept25Crim)
SFAOROct25Crim <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025", ApprehensionMonth == "10") %>%
  group_by(`Apprehension Criminality`) %>%
  tally() 

View(SFAOROct25Crim)

Arrest Pickup Location and Apprehension Method

SFAOR_AdminArrest2025 <-SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025") %>%
  group_by(`Apprehension Method`,`Apprehension Site Landmark`)

view(SFAOR_AdminArrest2025)

I want to look at where the apprehension method is 287g.

SFAOR_AdminArrest2025_287g <-SFAOR_AdminArrest2025 %>%
  filter(`Apprehension Method`== "287(g) Program")

view(SFAOR_AdminArrest2025_287g)

I want to look at apprehension method involving local incarceration

SFAOR_AdminArrest2025_local <- SFAOR_AdminArrest2025 %>%
  filter(`Apprehension Method`== "CAP Local Incarceration")

View (SFAOR_AdminArrest2025_local)

Now I want a tally of apprehension site landmarks.

SFAPLandmarks <- SFAOR_AdminArrest2025 %>%
  group_by(`Apprehension Site Landmark`)%>%
  tally()

view(SFAPLandmarks)

These are unfortunately vague, and they’re worth looking at for me personally, but they do not make for a great visualization.

Mapping Arrest AOR against detention facilities

I’m going to start by taking a shape file of the AOR facilities and reading it in.

ICE_AOR <- st_read("/Users/eleanorprickettmorgan/Desktop/DeportationData/ERO files/ice-aor-shp/ice-aor-shp.shp")
Reading layer `ice-aor-shp' from data source `/Users/eleanorprickettmorgan/Desktop/DeportationData/ERO files/ice-aor-shp/ice-aor-shp.shp' using driver `ESRI Shapefile'
Simple feature collection with 26 features and 2 fields (with 1 geometry empty)
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -179.1467 ymin: 13.23419 xmax: 179.7785 ymax: 71.38782
Geodetic CRS:  NAD83
View(ICE_AOR)
ICE_AOR_CLEAN <- ICE_AOR %>%
  drop_na(offc_nm)

View(ICE_AOR_CLEAN)

This I’m going to use to Map in QGIS

st_write(ICE_AOR_CLEAN, "ICE_AOR_CLEAN.shp")
Layer ICE_AOR_CLEAN in dataset ICE_AOR_CLEAN.shp already exists:
use either append=TRUE to append to layer or append=FALSE to overwrite layer
Error: Dataset already exists.

Demographics in SFAOR

Gender Breakdown.

SFAORArrestGender2025 <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025") %>%
  group_by(`Gender`) %>%
  tally() 

View(SFAORArrestGender2025)
ggplot(SFAORArrestGender2025, aes(x="Gender", y=n, fill=`Gender`)) +
  geom_bar(stat="identity", width=1, color="white") +
  coord_polar("y", start=0) +
  ggtitle("Arrest Gender SFAOR 2025") +
  theme_void()

Age Breakdown.

SFAOR_AdminArrest_Age2025 <- SFAOR_AdminArrest %>%
  mutate(Age = 2025 - `Birth Year`) %>%
  filter(ApprehensionYear == "2025") %>%
  group_by(Age)  %>%
  tally()

View(SFAOR_AdminArrest_Age2025)

This table is not so useful, I think I’d like to see it visually.

ggplot(data=SFAOR_AdminArrest_Age2025, aes(x = Age, y =n)) +
  geom_bar(stat="identity", width=0.5, fill= "steelblue") +
  labs( x = "Age Range", y = "Number of Arrests") +
  ggtitle("Arrests by Age SFAOR") +
  scale_x_continuous(n.breaks=20)

summary(SFAOR_AdminArrest_Age2025$Age)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   3.00   22.25   40.50   40.59   58.75   84.00 

How Many Arrests result in Deportation

SFAORDepartureCountry <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025") %>%
  group_by(`Departure Country`) %>%
  tally()
ggplot(data=SFAORDepartureCountry, aes(x = `Departure Country`, y =n)) +
  geom_bar(stat="identity", width=0.5, fill= "steelblue") +
  labs( x = "Country", y = "Number of Arrests") +
  ggtitle("Departure Country SFAOR 2025") 

SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025") %>%
  group_by(`Case Status`) %>%
  tally()
LS0tCnRpdGxlOiAiSjIyMSBFUE0gRmluYWwgUHJvamVjdCDigJQgQWRtaW5pc3RyYXRpdmUgQXJyZXN0cyIKYXV0aG9yOiAiRWxsaWUgUHJpY2tldHQtTW9yZ2FuIgpkYXRlOiAiMjAyNS0xMi0xMCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgU2V0dXAgYW5kIExpYnJhcmllcwoKYGBge3J9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZXJyb3IgPSBUUlVFLCBjYWNoZT1UUlVFLCBhdXRvZGVwID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCBwcm9ncmVzc19iYXIgPSBGQUxTRSkKCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkodGlkeXZlcnNlKSAKbGlicmFyeShkcGx5cikgCmxpYnJhcnkoZ2dwbG90MikgCmxpYnJhcnkoa25pdHIpIApsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KGxtZTQpCmxpYnJhcnkoYm9vdCkKbGlicmFyeShnZ2VmZmVjdHMpIApsaWJyYXJ5KERlc2NUb29scykKbGlicmFyeSh0aWR5Y2Vuc3VzKQpsaWJyYXJ5KHhtbDIpCmxpYnJhcnkodG1hcCkKbGlicmFyeSh0bWFwdG9vbHMpCmxpYnJhcnkobGVhZmxldCkKbGlicmFyeShzZikKbGlicmFyeShsZWFmbGV0LmV4dHJhcykKbGlicmFyeShyYXN0ZXIpCmxpYnJhcnkodGlncmlzKQpsaWJyYXJ5KHNwKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShzdHJpbmdpKQpsaWJyYXJ5KGxlYWZsZWdlbmQpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoamFuaXRvcikKbGlicmFyeShnZ3JlcGVsKQpgYGAKCmBgYHtyfQpzZXR3ZCgiL1VzZXJzL2VsZWFub3Jwcmlja2V0dG1vcmdhbi9EZXNrdG9wL0RlcG9ydGF0aW9uRGF0YS8iKQpgYGAKCiMjIEltcG9ydGluZyBEYXRhCgpJJ20gc2tpcHBpbmcgNiBiZWNhdXNlIHRoZSBmaXJzdCA2IHJvd3Mgb2YgdGhlIGV4Y2VsIGZpbGUgaGF2ZSBzdW1tYXJ5IGluZm9ybWF0aW9uLCBidXQgdGhlIGRhdGEgaXRzZWxmIGRvZXNuJ3QgYWN0dWFsbHkgc3RhcnQuIFRoZW4gSSdtIHVzaW5nIFN1bW1hcnkgdG8gY2hlY2sgd2hhdCBteSB0aW1lIHJhbmdlIGlzLCBsb29raW5nIHNwZWNpZmljYWxseSBhdCB0aGUgQXBwcmVoZW5zaW9uIGNvbHVtbi4gCgpgYGB7cn0KQWRtaW5BcnJlc3QgPC0gcmVhZF9leGNlbCgiL1VzZXJzL2VsZWFub3Jwcmlja2V0dG1vcmdhbi9EZXNrdG9wL0RlcG9ydGF0aW9uRGF0YS9FUk8gQWRtaW4gQXJyZXN0c19MRVNBLVNUVS1GSU5BTCBSZWxlYXNlX3Jhdy54bHN4Iiwgc2tpcCA9IDYpClZpZXcoQWRtaW5BcnJlc3QpCnN1bW1hcnkoQWRtaW5BcnJlc3QpCmBgYAoKIyMgQ2xlYW5pbmcgdGhlIERhdGEKCiMjIyBDaGVja2luZyBmb3IgRHVwbGljYXRlcwoKVG8gY2hlY2sgZm9yIGR1cGxpY2F0ZXMgSSdtIGdvaW5nIHRvIGxvb2sgYXQgdGhlIHVuaXF1ZSBpZGVudGlmaWVyIGNvbHVtbi4gCgpgYGB7cn0KQWRtaW5BcnJlc3QgJT4lCiAgZ3JvdXBfYnkoYFVuaXF1ZSBJZGVudGlmaWVyYCkgJT4lCiAgZmlsdGVyKG4oKT09MikKCmBgYAoKSSBnZXQgYmFjayAyNywyMTQgcm93cyB3aGVyZSB0aGUgVW5pcXVlIGlkZW50aWZpZXIgcmVwZWF0ZWQgaXRzZWxmLiBCdXQgSSBjYW4gdGVsbCB0aGF0IHRoZXJlIGFyZSBjZXJ0YWluIGluc3RhbmNlcyB3aGVyZSB0aGUgc2FtZSBpZGVudGlmaWVyIGFwcGVhcnMgdHdpY2Ugd2l0aCBhIGRpZmZlcmVudCBhcHByZWhlbnNpb24gZGF0ZS4gU28gSSdtIGdvaW5nIHRvIHRyeSBhZ2FpbiBsb29raW5nIGF0IEFwcHJlaGVuc2lvbiBEYXRlIGluIGFkZGl0aW9uIHRvIHRoZSBVbmlxdWUgSWRlbnRpZmllciBjb2x1bW4uIAoKYGBge3J9CkFkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KGBVbmlxdWUgSWRlbnRpZmllcmAsIGBBcHByZWhlbnNpb24gRGF0ZWApICU+JQogIGZpbHRlcihuKCk9PTIpCmBgYAoKV2hlbiBJIGZpbHRlciBieSBib3RoIG9mIHRoZXNlIHRoaW5ncyBJIGdldCAzLDMwNCByb3dzLiBUaGF0IHN1Z2dlc3RzIHRoYXQgbWF5YmUgY2VydGFpbiBpbmRpdmlkdWFscyB3ZXJlIGFycmVzdGVkIHR3aWNlLCBvciBoYXZlIGJlZW4gaW4gdGhlIHN5c3RlbSBtdWx0aXBsZSB0aW1lcyBvdmVyIHRoZSBjb3Vyc2Ugb2YgbWFueSB5ZWFycywgdGhpcyBpcyBjbG9zZXIgdG8gdGhlIHRydWUgbnVtYmVyIG9mIGR1cGxpY2F0ZXMuIFNvIG5vdyBJJ20gZ29pbmcgdG8gcmVtb3ZlIHRob3NlIHBvdGVudGlhbCBkdXBsaWNhdGVzIHVzaW5nIHRoZSBkaXN0aW5jdCBmdW5jdGlvbi4gCgpgYGB7cn0KY2xlYW5lZF9BZG1pbkFycmVzdCA8LSBBZG1pbkFycmVzdCAlPiUKICBkaXN0aW5jdChgVW5pcXVlIElkZW50aWZpZXJgLGBBcHByZWhlbnNpb24gRGF0ZWAsIC5rZWVwX2FsbCA9IFRSVUUpClZpZXcoY2xlYW5lZF9BZG1pbkFycmVzdCkKYGBgCgpXaGVuIEkgcnVuIHRoaXMgSSBub3cgaGF2ZSAyODksOTI3IGVudHJpZXMgaW5zdGVhZCBvZiB0aGUgb3JpZ2luYWwgMjkxNzIyLiBJIHdvdWxkIHByb2JhYmx5IHN0aWxsIGFzayBhbiBleHBlcnQgd2hvIHdvcmtzIHdpdGggdGhpcyBkYXRhIGlmIHRoZXJlIGFyZSBvdGhlciB3YXlzIEkgbWlnaHQgbm90IGJlIGNhdGNoaW5nIGR1cGxpY2F0ZXMgYnV0IHRoaXMgbWFrZXMgdGhlIG1vc3Qgc2Vuc2UgdG8gbWUuCgpGb3IgbGF0ZXIgb24gSSdtIGdvaW5nIHRvIG1ha2UgYSB2ZXJzaW9uIG9mIHRoaXMgbmF0aW9uYWwgYWRtaW4gYXJyZXN0IGRhdGEgdGhhdCBJIGNhbiBtZXJnZSB3aXRoIGEgc2hhcGVmaWxlIGZvciBtYXBwaW5nLiAKCmBgYHtyfQpGaWx0ZXJlZF9BZG1pbkFycmVzdCA8LSBjbGVhbmVkX0FkbWluQXJyZXN0ICU+JQogIGRyb3BfbmEoYEFwcHJlaGVuc2lvbiBBT1JgKQoKVmlldyhGaWx0ZXJlZF9BZG1pbkFycmVzdCkKYGBgCgpgYGB7cn0KTXV0YXRlX0FkbWluQXJyZXN0IDwtIEZpbHRlcmVkX0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihgQXBwcmVoZW5zaW9uIEFPUmAhPSAiSFEgQXJlYSBvZiBSZXNwb25zaWJpbGl0eSIpICAlPiUKICBtdXRhdGUoQXBwcmVoZW5zaW9uQU9SY2xlYW5lZDEgPSBzdHJfcmVtb3ZlKGBBcHByZWhlbnNpb24gQU9SYCwiQXJlYSBvZiBSZXNwb25zaWJpbGl0eSIpKSAlPiUKICBtdXRhdGUoQXBwcmVoZW5zaW9uQU9SY2xlYW5lZDIgPSBzdHJfcmVtb3ZlKGBBcHByZWhlbnNpb25BT1JjbGVhbmVkMWAsIkhRIikpICU+JQogIG11dGF0ZShBcHByZWhlbnNpb25BT1JjbGVhbmVkMyA9IHN0cl9yZXBsYWNlX2FsbChgQXBwcmVoZW5zaW9uQU9SY2xlYW5lZDJgLCJTdC4gUGF1bCIsICJTdCBQYXVsIikpCiAgCgpNdXRhdGVfQWRtaW5BcnJlc3QgJT4lCiAgZ3JvdXBfYnkoQXBwcmVoZW5zaW9uQU9SY2xlYW5lZDMpICU+JQogIHRhbGx5KCkKCmBgYAoKSSdtIGdvaW5nIHRvIHVzZSB0aGlzIGZvciBRR0lTIG1hcHBpbmcsIHNvIHRoaXMgaXMgbWUgZXhwb3J0aW5nIHRoaXMgZGF0YWZyYW1lIGFzIGEgY3N2CgpgYGB7cn0Kd3JpdGVfY3N2KE11dGF0ZV9BZG1pbkFycmVzdCwgIi9Vc2Vycy9lbGVhbm9ycHJpY2tldHRtb3JnYW4vRGVza3RvcC9EZXBvcnRhdGlvbkRhdGEvQWRtaW5BcnJlc3RNYXBwaW5nLmNzdiIpCmBgYAoKCiMjIyBDaGVja2luZyBmb3IgQ29uc2lzdGVuY3kgSXNzdWVzCgojIyMjIEFwcHJlaGVuc2lvbiBTdGF0ZQoKVG8gY2hlY2sgZm9yIGNvbnNpc3RlbmN5IGlzc3VlcywgSSdtIGdvaW5nIHRvIGxvb2sgYXQgdGhlIGNvbHVtbiBuYW1lcyBkZWFsaW5nIHByaW1hcmlseSB3aXRoIGNoYXJhY3RlcnMuIFNvIGZvciBleGFtcGxlIGZvciBzdGF0ZXMgSSBrbm93IHRoYXQgSSB3YW50IDUwIGlkZWFsbHksIGFuZCBJIHdvdWxkIGNoZWNrIGJ5IGRvaW5nIHRoZSBmb2xsb3dpbmc6CgpgYGB7cn0KY2xlYW5lZF9BZG1pbkFycmVzdCAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIFN0YXRlYCkgJT4lCiAgdGFsbHkoKQpgYGAKCkhlcmUgdGhlcmUgYXJlIGEgY291cGxlIGNvbnNpc3RlbmN5IGlzc3Vlcywgc29tZSBvZiB0aGUgdGhpbmdzIGluY2x1ZGVkIGluIFN0YXRlcyBhcmUgdGhyZWUgbG9jYXRpb25zIGxhYmVsZWQgIkFSTUVEIEZPUkNFUyAtIEVVUk9QRSwgQVJNRUQgRk9SQ0VTIC0gVEhFIEFNRVJJQ0FTLCBBUk1FRCBTRVJWSUNFUyAtIFRIRSBQQUNJRklDLiIgSSBoYXZlIG5vIGlkZWEgd2hhdCBkaWZmZXJlbnRpYXRlcyBhcm1lZCBmb3JjZXMgdnMuIHNlcnZpY2VzLCBub3IgYW0gSSBjbGVhciBpZiB0aGVzZSBhcmUgYXJyZXN0cyB0aGF0IHRvb2sgcGxhY2Ugb24gbWlsaXRhcnkgYmFzZXMgb3IgYXMgYSBwYXJ0IG9mIE1pbGl0YXJ5IG9wZXJhdGlvbnMuIFdvcnRoIG5vdGluZyB0aGF0IHdlIGhhdmUgNjIgcm93cywgaW5zdGVhZCBvZiA1MCwgd2hpY2ggaXMgcGFydGlhbGx5IGJlY2F1c2Ugb2YgdGVycml0b3JpZXMgdW5kZXIgVVMgY29udHJvbCAoaS5lLiBQdWVydG8gUmljbywgRmVkZXJhdGVkIFN0YXRlcyBvZiBNaWNyb25lc2lhLCBHdWFtLCBldGMuKSBEaXN0cmljdCBvZiBDb2x1bWJpYSBpcyBhbHNvIGl0J3Mgb3duIGVudHJ5LCBhbmQgaXQncyBub3QgYSBzdGF0ZS4gVGhlcmUgYXJlIGFsc28gdHdvIGxvbmUgZW50cmllcyBpbiBhcmVhcyBvdXRzaWRlIG9mIFVTIGNvbnRyb2wsIG9uZSBqdXN0IGxhYmVsZWQgIk1FWElDTywiIHRoZSBvdGhlciBsYWJlbGVkICJUQU1BVUxJUEFTLCIgd2hpY2ggaXMgYSB0ZXJyaXRvcnkgaW4gTWV4aWNvLiBUaG9zZSBzZWVtIGxpa2UgaW5kaXZpZHVhbCBkYXRhIGVudHJ5IGlzc3VlcyBvciBtaXNjYXRlZ29yaXphdGlvbnMuIEFzaWRlIGZyb20gdGhhdCwgdGhlIHN0YXRlcyB0aGVtc2VsdmVzIGFyZSBzcGVsbGVkIGluIGNvbnNpc3RlbnQgd2F5cy4gCgojIyMjIEFPUiAoQXJlYSBvZiBSZXNwb25zaWJpbGl0eSkKCk5vdyBJJ20gZ29pbmcgdG8gcGVyZm9ybSBhIHNpbWlsYXIgdGVzdCBvbiB0aGUgQU9SIGNvbHVtbiBmb3IgY29uc2lzdGVuY3kuIEZyb20gdGhlIElDRS5nb3Ygd2Vic2l0ZSBJJ20gZXhwZWN0aW5nIDI1IEFPUidzLgoKYGBge3J9CmNsZWFuZWRfQWRtaW5BcnJlc3QgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBBT1JgKSAlPiUKICB0YWxseSgpCgpgYGAKCkhlcmUgSSBnb3QgMjcgcm93cyBiYWNrLCBvbmUgY29ycmVzcG9uZGVkIHRvIE4vQSwgd2l0aCA1MjIzIGVudHJpZXMgbm90IGFzc2lnbmVkIHRvIGEgc3BlY2lmaWMgZ2VvZ3JhcGh5LiBUaGVyZSdzIGFsc28gYSBteXN0ZXJpb3VzIEhRIEFyZWEgb2YgUmVzcG9uc2liaWxpdHksIHdoaWNoIGlzIG5vdCBsaXN0ZWQgb25saW5lIHdpdGggb25seSA1MCBlbnRyaWVzLiBJIHdvdWxkIGFnYWluIGhhdmUgdG8gYXNrIHNvbWVvbmUgd2hvIHdvcmtzIHdpdGggdGhpcyBkYXRhIHJlZ3VsYXJseSB3aGF0IHRoaXMgbWVhbnMuIAoKIyMjIyBGaW5hbCBQcm9ncmFtCgpOb3cgSSdsbCBkbyB0aGUgc2FtZSB3aXRoIHRoZSBmaW5hbCBwcm9ncmFtIGNvbHVtbjogCgpgYGB7cn0KY2xlYW5lZF9BZG1pbkFycmVzdCAlPiUKICBncm91cF9ieShgRmluYWwgUHJvZ3JhbWApICU+JQogIHRhbGx5KCkKYGBgCgpIZXJlIHRoZSBtb3N0IG9idmlvdXMgaXNzdWUgd2hpY2ggcG9wdWxhdGVzIGZpcnN0IGlzIHdoYXQncyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuICIyODdHIFByb2dyYW0iIGFuZCAiMjg3ZyBUYXNrIEZvcmNlLiIgQmVjYXVzZSBteSBwcm9qZWN0IGlzIGluIENhbGlmb3JuaWEgd2hpY2ggaXMgKGFsbGVnZWRseSkgbm90IHBhcnRpY2lwYXRpbmcgaW4gMjg3ZywgSSdtIG5vdCB3b3JyaWVkIGFib3V0IHRoYXQuIEkgd291bGQgd2FudCB0byBkb3VibGUgY2hlY2sgd2l0aCBhbiBleHBlcnQgdGhhdCBzb21lIG9mIHRoZXNlIHRoaW5ncyBkbyBub3QgcmVmZXIgdG8gdGhlIHNhbWUgcHJhY3RpY2FsIGNhdGVnb3JpZXMuIEkgYW0gY29uY2VybmVkIGFib3V0IHRoZSA0ODcgSnV2ZW5pbGVzIGxpc3RlZCBoZXJlLgoKIyMjIyBGaW5hbCBQcm9ncmFtIEdyb3VwCgpCZWNhdXNlIHRoaXMgaXMgSUNFIGRhdGEsIEkgd291bGQgYXNzdW1lIGV2ZXJ5dGhpbmcgaW4gdGhlIGZpbmFsIHByb2dyYW0gZ3JvdXAgY29sdW1uIGlzIElDRSwgYnV0IEknbSBqdXN0IGRvdWJsZSBjaGVja2luZy4gCgpgYGB7cn0KY2xlYW5lZF9BZG1pbkFycmVzdCAlPiUKICBncm91cF9ieShgRmluYWwgUHJvZ3JhbSBHcm91cGApICU+JQogIHRhbGx5KCkKYGBgClRoYXQgcHJvZHVjZWQganVzdCBvbmUgcm93LCBzbyB0aGF0J3MgY29uc2lzdGVudC4gCgojIyMjIEFwcHJlaGVuc2lvbiBNZXRob2QKCk5vdyBJJ20gY2hlY2tpbmcgZm9yIGFwcHJlaGVuc2lvbiBtZXRob2Q6CgpgYGB7cn0KY2xlYW5lZF9BZG1pbkFycmVzdCAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIE1ldGhvZGApICU+JQogIHRhbGx5KCkKYGBgCgpJbiB0ZXJtcyBvZiBob3cgdGhpbmdzIGFyZSBsaXRlcmFsbHkgc3BlbGxlZCB5ZXMgdGhlcmUgaXMgY29uc2lzdGVuY3kuIEluIHRlcm1zIG9mIHdoYXQgdGhlIGRhdGEgaXMgc2F5aW5nIGhlcmUsIEkgZG8gaGF2ZSBhIGxvdCBvZiBxdWVzdGlvbnMuIEZvciBleGFtcGxlIG9ubHkgb25lIHBlcnNvbiBpcyBsaXN0ZWQgYXMgYXJyZXN0ZWQgaW4gdGhlICJQcmVzZW50ZWQgRHVyaW5nIEluc3BlY3Rpb24iIGNhdGVnb3J5LCB3aGljaCBmZWVscyBsaWtlIGEgY29udHJhZGljdGlvbiB3aXRoIHRoZSBjb3VydGhvdXNlIGFuZCBmaWVsZCBvZmZpY2UgY2hlY2staW5zIGhhdmluZyBzbyBtYW55IGluZGl2aWR1YWxzIGdyYWJiZWQgYnkgSUNFLiBIb3dldmVyLCB0aG9zZSBtaWdodCBiZSBhIGRpZmZlcmVudCBjYXRlZ29yeSBvZiBlbmZvcmNlbWVudCB0aGF0J3MgaW5jbHVkZWQgaW4gYW5vdGhlciBkYXRhIHNldCAoaS5lLiBkZXRlbnRpb25zKS4gVGhpcyBpcyBwcm9iYWJseSBteSBmbGF3ZWQgdW5kZXJzdGFuZGluZyBvZiB0aGUgbGVnYWwgc3lzdGVtIGhlcmUsIGJ1dCBzdGlsbCBzb21ldGhpbmcgSSB3YW50IHRvIG5vdGUuIAoKIyMjIyBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHkKCk5vdyBJJ20gZ29pbmcgdG8gY2hlY2sgZm9yIGFwcHJlaGVuc2lvbiBjcmltaW5hbGl0eTogCgpgYGB7cn0KY2xlYW5lZF9BZG1pbkFycmVzdCAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5YCkgJT4lCiAgdGFsbHkoKQpgYGAKCkhlcmUgSSBnZXQgYmFjayBvbmx5IHRocmVlIHJvd3MsIHdoaWNoIGlzIGNvbnNpc3RlbnQgd2l0aCBteSB1bmRlcnN0YW5kaW5nIG9mIGZvbGtzIGFyZSBjYXRlZ29yaXplZCBpbiB0aGVzZSBzaXR1YXRpb25zLiAKCiMjIyMgQ2FzZSBTdGF0dXMKCk5vdyBJJ2xsIGNoZWNrIGZvciBjYXNlIHN0YXR1czoKCmBgYHtyfQpjbGVhbmVkX0FkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KGBDYXNlIFN0YXR1c2ApICU+JQogIHRhbGx5KCkKYGBgCgpIZXJlIEkgZ2V0IGJhY2sgMTQgcm93cyB3aXRoIGNhdGVnb3JpZXMgbGlzdGVkLiBUaGUgZmlyc3QgY2h1bmsgYXJlIG51bWJlcmVkIHN0YXJ0aW5nIGF0IDAsIGJ1dCBub3RhYmx5IG1pc3NpbmcgMSBhbmQgMi4gSSBkb24ndCBrbm93IHdoYXQgdGhvc2UgY2F0ZWdvcmllcyBjb3VsZCBiZS4gVGhlcmUgYXJlIDQ0NjIgd2hvIGFyZSBub3QgaW4gYSBjYXRlZ29yeSBhdCBhbGwsIHdoaWNoIGlzIGNvbmZ1c2luZyBiZWNhdXNlIG9uZSBjYXRlZ29yeSBpcyBsaXRlcmFsbHkganVzdCBmb3IgYWN0aXZlIGNhc2VzLiBUaGVyZSBhcmUgYWxzbyBzb21lIGFjcm9ueW1zIEkgZG9uJ3QgdW5kZXJzdGFuZCwgIjktVlIgV2l0bmVzc2VkIiBJIGFzc3VtZSBpcyB2b2x1bnRhcnkgcmVtb3ZhbCB3aXRuZXNzZWQsIGhvdyBpcyB0aGF0IGRpZmZlcmVudCB0aGFuIHZvbHVudGFyeSBkZXBhcnR1cmU/IEknbSBjb25jZXJuZWQgYWxzbyBhYm91dCB0aGUgNDEgZGVhdGhzIGxpc3RlZC4gSSdkIGFsc28gbGlrZSB0byB1bmRlcnN0YW5kIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gIkwtTGVnYWxpemF0aW9uIC0gUGVybWFuZW50IFJlc2lkZW5jZSBHcmFudGVkIiBhbmQJIlotU0FXIC0gUGVybWFuZW50IFJlc2lkZW5jZSBHcmFudGVkLiIKCiMjIyMgQ2FzZSBDYXRlZ29yeQoKTm93IEknbGwgbG9vayBhdCBDYXNlIENhdGVnb3J5OiAKCmBgYHtyfQpjbGVhbmVkX0FkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KGBDYXNlIENhdGVnb3J5YCkgJT4lCiAgdGFsbHkoKQpgYGAKSGVyZSB0aGVyZSBhcmUgbm8gZ2xhcmluZyBjb25zaXN0ZW5jeSBpc3N1ZXMgZXhjZXB0IHRoZSA0NDEyIHVuY2F0ZWdvcml6ZWQgY2FzZXMuIAoKIyMjIyBEZXBhcnR1cmUgQ291bnRyeQoKTm93IEknbGwgY2hlY2sgZm9yIERlcGFydHVyZSBDb3VudHJ5OgoKYGBge3J9CmNsZWFuZWRfQWRtaW5BcnJlc3QgJT4lCiAgZ3JvdXBfYnkoYERlcGFydHVyZSBDb3VudHJ5YCkgJT4lCiAgdGFsbHkoKQpgYGAKCkkgZ290IGJhY2sgMTkzIHJvd3Mgd2hpY2ggaXMgaW4gbGluZSB3aXRoIHRoZSBudW1iZXIgb2YgY291bnRyaWVzIGluIHRoZSB3b3JsZCAoZGVwZW5kaW5nIG9uIHdobyB5b3UgYXNrLCBidXQgYXQgbGVhc3QgaW4gbGluZSB3aXRoIHRoZSBudW1iZXIgb2YgY291bnRyaWVzIHRoZSBVUyByZWNvZ25pemVzKS4gQ2xpY2tpbmcgdGhyb3VnaCBJIGRpZG4ndCBzZWUgYW55IHN1cGVyIHdlaXJkIGR1cGxpY2F0ZXMuIE9uZSByb3cgaXMgTi9BIGJ1dCBmcm9tIGxvb2tpbmcgYXQgdGhlIG90aGVyIGNvbHVtbnMgaW4gY29uanVuY3Rpb24sIEkgdGhpbmsgYSBkZXBhcnR1cmUgY291bnRyeSBpcyBvbmx5IGVudGVyZWQgd2hlbiB0aGUgZGVwYXJ0dXJlIGhhcHBlbnMuIFNvIHRoZSBhY3RpdmUgY2FzZXMgZG9uJ3QgaGF2ZSBhIGRlcGFydHVyZSBjb3VudHJ5IGxpc3RlZC4gCgojIyMjIEZpbmFsIE9yZGVyIFllcyBvciBObwoKTm93IEknbGwgY2hlY2sgZmluYWwgb3JkZXIgWWVzIG9yIE5vIChob3BlZnVsbHkgMiByb3dzKS4KCmBgYHtyfQpjbGVhbmVkX0FkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KGBGaW5hbCBPcmRlciBZZXMgTm9gKSAlPiUKICB0YWxseSgpCmBgYApIZXJlIHdlIGdldCBiYWNrIFllcywgTm8sIG9yIEJsYW5rICg0NDEyIHJvd3MpLgoKIyMjIyBDaXRpemVuc2hpcCBDb3VudHJ5CgpOb3cgSSdsbCBsb29rIGF0IGNpdGl6ZW5zaGlwIGNvdW50cnkKCmBgYHtyfQpjbGVhbmVkX0FkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KGBDaXRpemVuc2hpcCBDb3VudHJ5YCkgJT4lCiAgdGFsbHkoKQpgYGAKCk15IGNpdGl6ZW5zaGlwIGNvdW50cmllcyBvdXRudW1iZXIgbXkgZGVwYXJ0dXJlIGNvdW50cmllcyBieSAzLCBJIHdvdWxkIHdhbnQgdG8gY29tcGFyZSB0aG9zZSBhbmQgc2VlIHdoZXJlIEkgaGF2ZSBhZGRpdGlvbmFsIGNpdGl6ZW5zaGlwIGJ1dCBub3QgZGVwYXJ0dXJlLiBOb3RhYmx5IG5vIG9uZSBoZXJlIGlzIHVuY2F0ZWdvcml6ZWQuIAoKIyMjIyBHZW5kZXIKCk5vdyBJJ20gY2hlY2tpbmcgZm9yIGdlbmRlciB3aGljaCBJJ20gZXhwZWN0aW5nIDIgcm93cyBmb3I6CmBgYHtyfQpjbGVhbmVkX0FkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgdGFsbHkoKQpgYGAKCldlIGdldCBiYWNrIHRocmVlIHJvd3M6IEZlbWFsZSwgTWFsZSwgYW5kIFVua25vd24uIEltcG9ydGFudCB0byBub3RlIHRoYXQgdW5rbm93biBpcyB3cml0dGVuIGluLCBhbmQgaXNuJ3QganVzdCBhIGJsYW5rLiAKCiMjIyMgQXBwcmVoZW5zaW9uIFNpdGUgTGFuZG1hcmsKCk5vdyBJJ20gY2hlY2tpbmcgZm9yIEFwcHJlaGVuc2lvbiBTaXRlIExhbmRtYXJrLiBUaGlzIGlzIHdoZXJlIEknbSBleHBlY3RpbmcgdGhlIG1vc3QgaW5jb25zaXN0ZW5jaWVzLgoKYGBge3J9CmNsZWFuZWRfQWRtaW5BcnJlc3QgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBTaXRlIExhbmRtYXJrYCkgJT4lCiAgdGFsbHkoKQpgYGAKCkhlcmUgSSBnZXQgYmFjayA1MDAgcm93cywgYW5kIHRoZXJlIGFyZSBtYWpvciBkaWZmZXJlbmNlcyBpbiBjYXBpdGFsaXphdGlvbiBhbmQgdXNhZ2Ugb2YgRGFzaGVzLiBTb21lIGluY2x1ZGUgdGhlIHN0YXRlIHRoZXkgd2VyZSBpbiwgb3RoZXJzIGRvIG5vdC4gU29tZSBhbHNvIGluY2x1ZGRlIHRoZSBwcm9ncmFtIHRoZXkgd2VyZSBpbiAoMjk3KGcpLCBDQVAsIGV0Yy4pLiBGb3IgdGhlIHB1cnBvc2VzIG9mIG15IHByb2plY3QgSSdkIHByb2JhYmx5IHRha2UgdGhlIENhbGlmb3JuaWEgc3Vic2V0IGFuZCBjbGVhbiB0aGF0LCBidXQgdGhpcyB3b3VsZCBsaWtlbHkgYmUgdGhlIG1vc3Qgb25lcm91cyBwYXJ0IG9mIHdvcmtpbmcgd2l0aCB0aGlzIGRhdGEuIAoKIyMjIENoZWNraW5nIGZvciBNaXNzaW5nIERhdGEKCk5vdyB0byBjaGVjayBmb3IgbWlzc2luZyBkYXRhLCBJJ20gZ29pbmcgdG8gdXNlL3JlZmVyIHRvIHRoZSBvcmlnaW5hbCB1bmNsZWFuIGRhdGEgIkFkbWluQXJyZXN0IjoKCmBgYHtyfQpNaXNzaW5nRGF0YSA8LWNvbFN1bXMoaXMubmEoQWRtaW5BcnJlc3QpKQpwcmludChNaXNzaW5nRGF0YSkKYGBgCgojIyMgQWRkaXRpb25hbCBBbHRlcmluZwoKIyMjIyBDcmVhdGluZyBhIE5ldyBDb2x1bW4gdG8gTG9vayBhdCBUaW1lIG9mIEFycmVzdAoKSSB3YW50IHRvIG11dGF0ZSB0aGUgYXBwcmVoZW5zaW9uIGRhdGUgY29sdW1uIHNvIHRoYXQgSSBjYW4gZmlsdGVyIGxhdGVyIGJ5IHllYXIgYW5kIG1vbnRoLCBhbmQgZXZlbiBwb3RlbnRpYWxseSB0aGUgdGltZSBvZiBkYXkgYW4gYWRtaW5pc3RyYXRpdmUgYXJyZXN0IHRvb2sgcGxhY2UuCgpgYGB7cn0KbmV3X0FkbWluQXJyZXN0IDwtY2xlYW5lZF9BZG1pbkFycmVzdCU+JSAKICBtdXRhdGUoQXBwcmVoZW5zaW9uWWVhciA9IHllYXIoYEFwcHJlaGVuc2lvbiBEYXRlYCkpJT4lIAogIG11dGF0ZShBcHByZWhlbnNpb25Nb250aCA9IG1vbnRoKGBBcHByZWhlbnNpb24gRGF0ZWApKSU+JSAKICBtdXRhdGUoQXBwcmVoZW5zaW9uRGF5ID0gZGF5KGBBcHByZWhlbnNpb24gRGF0ZWApKSU+JSAKICBtdXRhdGUoQXBwcmVoZW5zaW9uSG91ciA9IGhvdXIoYEFwcHJlaGVuc2lvbiBEYXRlYCkpCgpWaWV3KG5ld19BZG1pbkFycmVzdCkKCmBgYAoKIyMjIyBCcmVha2luZyBvdXQgQ2FsaWZvcm5pYSBhbmQgU2FuIEZyYW5jaXNjbyBBcmVhIG9mIFJlc3BvbnNpYmlsaXR5IERhdGEuCgpOb3cgSSB3YW50IHRvIGxvb2sgYXQganVzdCBhZG1pbmlzdHJhdGl2ZSBhcnJlc3RzIGluIENhbGlmb3JuaWEsIHNvIEknbSBnb2luZyB0byBmaWx0ZXIgYnkgdGhlIGFwcHJlaGVuc2lvbiBzdGF0ZSBjb2x1bW4uCgpgYGB7cn0KQ0FfQWRtaW5BcnJlc3QgPC0gbmV3X0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihgQXBwcmVoZW5zaW9uIFN0YXRlYCA9PSAiQ0FMSUZPUk5JQSIpClZpZXcoQ0FfQWRtaW5BcnJlc3QpCgpgYGAKCkkgd2FudCB0byBmaWx0ZXIgdGhhdCBmdXJ0aGVyIHRvIGp1c3QgdGhlIEFkbWluaXN0cmF0aXZlIGFycmVzdHMgaW4gdGhlIFNGIEFyZWEgb2YgUmVzcG9uc2liaWxpdHksIGJlY2F1c2UgZXZlbiB0aG91Z2ggdGhhdCdzIGFjdHVhbGx5IGEgbG90IGxhcmdlciB0aGFuIHRoZSBnZW9ncmFwaGljIHNjb3BlIG15IHByb2plY3QgaXMgbG9va2luZyBhdCwgaXQgYXQgbGVhc3QgaW5jbHVkZXMgbXkgYXJlYSB0aGUgQmF5IEFyZWEuIAoKYGBge3J9ClNGQU9SX0FkbWluQXJyZXN0IDwtIENBX0FkbWluQXJyZXN0ICU+JSAKICBmaWx0ZXIoYEFwcHJlaGVuc2lvbiBBT1JgID09ICJTYW4gRnJhbmNpc2NvIEFyZWEgb2YgUmVzcG9uc2liaWxpdHkiKQpWaWV3KFNGQU9SX0FkbWluQXJyZXN0KQpgYGAKCiMjIEFuYWx5c2lzCgojIyMgQWRtaW5zaXRyYXRpdmUgQXJyZXN0cyBPdmVyIFRpbWUKCkEgcmVhbGx5IGJhc2ljIGNvbXBhcmlzb24gSSBtaWdodCBtYWtlIHRvIHN0YXJ0IGlzIGNvbXBhcmluZyB0aGUgbnVtYmVyIG9mIEFkbWluaXN0cmF0aXZlIEFycmVzdHMgYnkgeWVhci4KCmBgYHtyfQpTRkFPUl9BZG1pbkFycmVzdCAlPiUgCiAgZ3JvdXBfYnkoQXBwcmVoZW5zaW9uWWVhcikgJT4lIAogIHRhbGx5KCkKYGBgCgpCdXQgdGhlIHRhYmxlIEkgZ2V0IGhlcmUgYWN0dWFsbHkgaXNuJ3QgdGhhdCBpbmZvcm1hdGl2ZSBnaXZlbiB0aGF0IEkgb25seSBoYXZlIGRhdGEgZnJvbSB0aHJlZSB5ZWFycy4gQnV0IG1heWJlIEkganVzdCB3YW50IHRvIHNlZSB0aGUgY2hhbmdlIGluIHRpbWUgYnkgbW9udGggb2YganVzdCB0aGlzIG5ldyBhZG1pbmlzdHJhdGlvbiAoMjAyNSksIFNvIEknZCBsaWtlbHkgZG8gdGhlIGZvbGxvd2luZzoKCmBgYHtyfQpTRkFPUl9BZG1pbkFycmVzdGJ5TW9udGggPC1TRkFPUl9BZG1pbkFycmVzdCAlPiUgCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiKSAlPiUgCiAgZ3JvdXBfYnkoQXBwcmVoZW5zaW9uTW9udGgpICU+JSAKICB0YWxseSgpClZpZXcoU0ZBT1JfQWRtaW5BcnJlc3RieU1vbnRoKQoKYGBgCgpKdXN0IGxvb2tpbmcgYXQgdGhlIHRhYmxlIEkgc2VlIHRoZXJlJ3MgYW4gaW5jcmVhc2UgaW4gSnVuZSB3aGljaCBoZWxkIGluIEp1bHksIGJ1dCBpdCBtaWdodCBiZSBoZWxwZnVsIHRvIHZpc3VhbGl6ZSBpdCwgc28gSSdtIGdvaW5nIHRvIGxvb2sgYXQgcGxvdCBpdCBvdXQ6IAoKYGBge3J9CmdncGxvdChkYXRhPVNGQU9SX0FkbWluQXJyZXN0YnlNb250aCkgKwogIGdlb21fbGluZShhZXMoeD1BcHByZWhlbnNpb25Nb250aCwgeT1uKSkgKwogIHhsaW0oMSwxMSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzY2FsZXM6OmJyZWFrc19leHRlbmRlZChuID0gMTEpKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDgwMCksIGJyZWFrcyA9IGMoMCwxMDAsMjAwLDMwMCw0MDAsNTAwLDYwMCw3MDAsODAwKSkrCiAgbGFicyggeCA9ICJNb250aCIsIHkgPSAiTnVtYmVyIG9mIEFycmVzdHMiKSArCiAgZ2d0aXRsZSgiQWRtaW5pc3RyYXRpdmUgQXJyZXN0cyBieSBNb250aCIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKICAKYGBgCgoKIyMjIyBBZG1pbmlzdHJhdGl2ZSBBcnJlc3RzIGJ5IEhvdXIKCkFuZWNkb3RhbGx5LCBJJ3ZlIGFsc28gaGVhcmQgdGhpcyB0aGluZyBmcm9tIGEgbnVtYmVyIG9mIGFkdm9jYXRlcyB0aGF0IElDRSBhY3Rpb25zIChhcnJlc3RzKSB0ZW5kIHRvIGhhcHBlbiBpbiB0aGUgZWFybHkgbW9ybmluZy4gSSB3YW50IHRvIGNoZWNrIGlmIHRoYXQncyB0cnVlLCBzbyBJJ20gZ29pbmcgdG8gbG9vayBhdCB0aGUgQXBwcmVoZW5zaW9uSG91ciBjb2x1bW4gdGhhdCBJIG11dGF0ZWQgb3V0IG9mIHRoZSBvcmlnaW5hbCBBcHByZWhlbnNpb24gRGF0ZSBjb2x1bW4uIEl0J3Mgb24gYSAyNCBob3VyIGNsb2NrIChubyBhbS9wbSkuIEknbSBnb2luZyB0byB1c2UgdGhlIENBX0FkbWluQXJyZXN0IGRhdGEgYmVjYXVzZSBhY2NvcmRpbmcgdG8gYWR2b2NhdGVzIHRoaXMgcmVwcmVzZW50cyBJQ0UgcG9saWN5IHNvIGl0IHNob3VsZCBiZSB0cnVlIGFjcm9zcyB0aGUgc3RhdGUuIAoKYGBge3J9CkNBX0FkbWluQXJyZXN0X2J5SG91ciA8LSBDQV9BZG1pbkFycmVzdCAlPiUKICBncm91cF9ieShBcHByZWhlbnNpb25Ib3VyKSAlPiUKICB0YWxseSgpCgpWaWV3KENBX0FkbWluQXJyZXN0X2J5SG91cikKCmBgYAoKVG8gc2VlIHRoYXQgdmlzdWFsbHkgSSdtIGdvaW5nIHRvIGNoYXJ0IGl0LiAKCmBgYHtyfQpnZ3Bsb3QoZGF0YT1DQV9BZG1pbkFycmVzdF9ieUhvdXIsIGFlcyh4ID0gQXBwcmVoZW5zaW9uSG91ciwgeSA9IG4pKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCB3aWR0aD0wLjUsIGZpbGw9ICJzdGVlbGJsdWUiKSArCiAgbGFicyggeCA9ICJIb3VyIG9mIHRoZSBEYXkiLCB5ID0gIk51bWJlciBvZiBBcnJlc3RzIikgKwogIGdndGl0bGUoIkFkbWluaXN0cmF0aXZlIEFycmVzdHMgYnkgSG91ciBvZiB0aGUgRGF5IGZyb20gU2VwdCAyMDIzIHRocm91Z2ggT2N0IDIwMjUiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKG4uYnJlYWtzPTIzKQpgYGAKVGhpcyBzaG93cyB0aGF0IHRoZSBudW1iZXIgb2YgYXJyZXN0cyBwZWFrcyBiZXR3ZW4gOSBhbmQgMTAgYW0sIGFuZCBpZiB0aGUgYWN0dWFsIGFycmVzdHMgYXJlIHRha2luZyBwbGFjZSBhdCB0aGF0IGhvdXIgd2UgY2FuIGluZmVyIHRoYXQgSUNFL0RIUyBoYWQgdG8gYmUgYWN0aXZlIGJlZm9yZSB0aGVuLiBUaGUgbWFqb3JpdHkgb2YgdGhlIGFjdGl2aXR5IHNlZW1zIHRvIGhhcHBlbiBiZXR3ZWVuIDdhbSBhbmQgMXBtLgoKIyMjIyBDb3VudHJpZXMgb2YgT3JpZ2luCgpBbm90aGVyIHRoaW5nIEknbSBpbnRlcmVzdGVkIGluIGlzIHVuZGVyIHRoZSBjdXJyZW50IGFkbWluaXN0cmF0aW9uLCB3aGF0IGFyZSB0aGUgdG9wIGNvdW50cmllcyBvZiBvcmlnaW4gZm9yIGZvbGtzIGJlaW5nIGFycmVzdGVkLiBJJ20gaW50ZXJlc3RlZCBib3RoIHN0YXRld2lkZSBhbmQgZm9yIGp1c3QgdGhlIFNhbiBGcmFuY2lzY28gQU9SLCBidXQgSSdsbCBzdGFydCB3aXRoIGp1c3QgQ2FsaWZvcm5pYQoKYGBge3J9CkNhbGlmb3JuaWFDaXRpemVuc2hpcENvdW50cnkyMDI1IDwtIENBX0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihBcHByZWhlbnNpb25ZZWFyID09ICIyMDI1IikgJT4lCiAgZ3JvdXBfYnkoYENpdGl6ZW5zaGlwIENvdW50cnlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhDYWxpZm9ybmlhQ2l0aXplbnNoaXBDb3VudHJ5MjAyNSkKYGBgCgpXaGVuIEkgZG8gdGhpcyBhbmQgc29ydCBieSB2YWx1ZXMgbXkgdG9wIDEwIGNpdGl6ZW5zaGlwIGNvdW50cmllcyBhcmUgTWV4aWNvLCBHdWF0ZW1hbGEsIEVsIFNhbHZhZG9yLCBDb2xvbWJpYSwgSG9uZHVyYXMsIEluZGlhLCBWZW5lenVlbGEsIENoaW5hLCBOaWNhcmFndWEgYW5kIFBlcnUuIFRvIGNvbXBhcmUgdGhpcyB0byB0aGUgU0ZBT1IgSSdtIGRvaW5nIGEgc2ltaWxhciBhbmFseXNpcwoKCmBgYHtyfQpTRkFPUkNpdGl6ZW5zaGlwQ291bnRyeTIwMjUgPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiKSAlPiUKICBncm91cF9ieShgQ2l0aXplbnNoaXAgQ291bnRyeWApICU+JQogIHRhbGx5KCkgCgpWaWV3KFNGQU9SQ2l0aXplbnNoaXBDb3VudHJ5MjAyNSkKYGBgCgpXaGVuIEkgc29ydCB0aGlzIHRhYmxlIGJ5IHRoZSBjb3VudCwgSSBnZXQgc2xpZ2h0bHkgZGlmZmVyZW50IHJlc3VsdHMsIGJ1dCB0aGVyZSBpcyBhIGxvdCBvZiBvdmVybGFwLiBJbiB0aGUgU2FuIEZyYW5jaXNjbyBBcmVhIG9mIFJlc3BvbnNpYmlsaXR5IHRoZSB0b3AgMTAgY2l0aXplbnNoaXAgY291bnRyaWVzIGZvciBhcnJlc3RlZCBmb2xrcyBhcmUgTWV4aWNvLCBJbmRpYSwgR3VhdGVtYWxhLCBFbCBTYWx2YWRvciwgQ29sb21iaWEsIEhvbmR1cmFzLCBQZXJ1LCBOaWNhcmFndWEsIFZlbmV6dWVsYSwgYW5kIENoaW5hLiBNZXhpY28gbm90YWJseSBvdXRwYWNlcyB0aGUgcmVzdCBvZiB0aGVzZSBwbGFjZXMgaW4gbnVtYmVyIG9mIGFycmVzdHMuIAoKIyMjIyBDcmltaW5hbGl0eQoKU29tZXRoaW5nIGVsc2UgSSdtIGludGVyZXN0ZWQgaW4gaXMgdGhlICJjcmltaW5hbGl0eSIgb2YgdGhvc2UgYXJyZXN0ZWQgaW4gdGhlIFNhbiBGcmFuY2lzY28gQXJlYSBvZiByZXNwb25zaWJpbGl0eS4gQWdhaW4gSSB3YW50IHRvIGxvb2sganVzdCBpbiB0aGUgY29udGV4dCBvZiB0aGUgY3VycmVudCBhZG1pbmlzdHJhdGlvbi4gVGhvc2Ugd2hvIGFyZSBhcnJlc3RlZCBhcmUgYXNzaWduZWQgdG8gb25lIG9mIHRocmVlIGNhdGVnb3JpZXMgb2YgY3JpbWluYWxpdHksIGJ1dCBJJ20gaW50ZXJlc3RlZCBpbiB0aGUgcHJvcG9ydGlvbiB0aGF0IHRob3NlIGNhdGVnb3JpZXMgc2hvdyB1cCBpbiBhcnJlc3RzLiAKCmBgYHtyfQpTRkFPUkFycmVzdENyaW1pbmFsaXR5MjAyNSA8LSBTRkFPUl9BZG1pbkFycmVzdCAlPiUKICBmaWx0ZXIoQXBwcmVoZW5zaW9uWWVhciA9PSAiMjAyNSIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUkFycmVzdENyaW1pbmFsaXR5MjAyNSkKYGBgCgpJIHdhbnQgdG8gc2VlIHRoaXMgdmlzdWFsbHksIHNvIGV2ZW4gdGhvdWdoIEknbSBub3QgYSBmYW4gb2YgcGllIGNoYXJzdHMgSSdtIGdvaW5nIHRvIGxvb2sgYXQgaXQgaW4gYSBwaWUgY2hhcnQuCgpgYGB7cn0KZ2dwbG90KFNGQU9SQXJyZXN0Q3JpbWluYWxpdHkyMDI1LCBhZXMoeD0iQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5IiwgeT1uLCBmaWxsPWBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iiwgd2lkdGg9MSwgY29sb3I9IndoaXRlIikgKwogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQ9MCkgKwogIGdndGl0bGUoIkFwcHJlaGVuc2lvbiBDcmltaW5hbGl0eSBTRkFPUiAyMDI1IikgKwogIHRoZW1lX3ZvaWQoKQpgYGAKCgpGb3IgdGhvc2UgYXJyZXN0ZWQgdGhlIG1ham9yaXR5IGFyZSBjb252aWN0ZWQgY3JpbWluYWxzLCBhY2NvcmRpbmcgdG8gdGhlIGRhdGEsIGJ1dCBpdCdzIG5vdGFibGUgdGhhdCBhIHNpemFibGUgY2h1bmsgYXJlIGNhdGVnb3JpemVkIHVuZGVyICJvdGhlciBpbW1pZ3JhdGlvbiB2aW9sYXRpb24uIiBBcnJlc3RzIGFyZSBzdXBwb3NlZCB0byByZXByZXNlbnQgaW5kaXZpZHVhbHMgaGF2ZSBhIHJlYWwgY2FzZSBhZ2FpbnN0IHRoZW0sIHNvIHRoZSBjb252aWN0ZWQgY3JpbWluYWwgY2F0ZWdvcnkgc2hvdWxkIHJlcHJlc2VudGVkIHRoZSBtYWpvcml0eS4gQW5kIHRoZXNlIGFycmVzdHMgYXJlIG5vdCB0aGUgdG90YWxpdHkgb2YgZGVwb3J0YXRpb25zLCBpZiB5b3UgbG9vayBhdCB0aGUgZGVwb3J0YXRpb24gZGF0YSBzZXQgaW4gYWRkaXRpb24gdG8gdGhpcyBhcnJlc3RzIGRhdGEsIHlvdSB3b3VsZCBmaW5kIHRoZSBtYWpvcml0eSBvZiBmb2xrcyBjb21pbmcgaW4gdG8gY29udGFjdCB3aXRoIElDRS9ESFMgZG8gbm90IGhhdmUgYW55IGNyaW1pbmFsIGNvbnZpY3Rpb25zLiBJdCdzIGFsc28gd29ydGggbm90aW5nIHRoYXQgdGhlIGNvbnZpY3RlZCBjcmltaW5hbCBjYXRlZ29yeSBkb2Vzbid0IGJyZWFrIGRvd24gZnVydGhlciBpbnRvIHdoYXQgY3JpbWVzIGZvbGtzIHdlcmUgY29udmljdGVkIG9mLiBPdGhlciByZXBvcnRpbmcgaGFzIGNvbmZpcm1lZCB0aGF0IHRoZXJlIGFyZSBtYW55IGZvbGtzIHdobyBlbmQgdXAgYXJyZXN0ZWQgd2hlcmUgdGhlIGJhc2lzIG9mIHRoZWlyIGNvbnZpY3Rpb24gaXMgYSB0cmFmZmljIHZpb2xhdGlvbi4gSSB0YWxrZWQgdG8gb25lIGxhd3llciBpbiB0aGUgQmF5IEFyZWEgd2hvIGNvbmZpcm1lZCB0aGV5IGhhZCBhIGNsaWVudCB3aGVyZSBhIHByaW9yIGNvbnZpY3Rpb24gY2FtZSBpbiB0aGUgZm9ybSBvZiBhIGNpdGF0aW9uIGZvciBmYWlsaW5nIHRvIHBheSBmb3IgQkFSVC4gQXJlIHRob3NlIGNyaW1lcyB0aGUgc2FtZSBhcyBtdXJkZXI/IE5vLCBidXQgdW5kZXIgdGhpcyBjYXRlZ29yaXphdGlvbiB0aGV5J3JlIGZsYXR0ZW5lZCBpbnRvIG9uZSBjYXRlZ29yeSB0b2dldGhlci4gCgpKdXN0IHRvIG1ha2Ugc3VyZSBteSBhbmFseXNpcyBpc24ndCBvZmYgSSdtIGdvaW5nIHRvIGNvbXBhcmUgU0YgaW4gMjAyNSB0byBhbGwgb2YgQ2FsaWZvcm5pYS4KCmBgYHtyfQpDQV9BcnJlc3RDcmltaW5hbGl0eTIwMjUgPC0gQ0FfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiKSAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5YCkgJT4lCiAgdGFsbHkoKSAKClZpZXcoQ0FfQXJyZXN0Q3JpbWluYWxpdHkyMDI1KQpgYGAKCkhlcmUgaXMgdGhhdCBpbmZvcm1hdGlvbiB2aXN1YWxpemVkOgoKYGBge3J9CmdncGxvdChDQV9BcnJlc3RDcmltaW5hbGl0eTIwMjUsIGFlcyh4PSJBcHByZWhlbnNpb24gQ3JpbWluYWxpdHkiLCB5PW4sIGZpbGw9YEFwcHJlaGVuc2lvbiBDcmltaW5hbGl0eWApKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCB3aWR0aD0xLCBjb2xvcj0id2hpdGUiKSArCiAgY29vcmRfcG9sYXIoInkiLCBzdGFydD0wKSArCiAgZ2d0aXRsZSgiQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5IEFsbCBvZiBDYWxpZm9ybmlhIDIwMjUiKSArCiAgdGhlbWVfdm9pZCgpCmBgYAoKVGhlIHByb3BvcnRpb25zIEkgZ2V0IGhlcmUgYXJlIHZlcnkgZGlmZmVyZW50LiBPdGhlciBJbW1pZ3JhdGlvbiBWaW9sYXRvciBpcyBuZWFybHkgdGhlIHNhbWUgdmFsdWUgYXMgQ29udmljdGVkIENyaW1pbmFsLiBJJ20gY3VyaW91cyBhcyB0byB3aGF0J3MgYXQgdGhlIHJvb3Qgb2YgdGhpcyBkaXNjcmVwYW5jeSBpbiBTYW4gRnJhbmNpc2NvLiBJIGRvIHdvbmRlciBpZiB0aGlzIGhhcyBzb21ldGhpbmcgdG8gZG8gd2l0aCB0aGUgbGFjayBvZiBpbmRpc2NyaW1pbmF0ZSByYWlkcyBpbiB0aGUgQmF5IEFyZWEsIHdoaWNoIG1lYW5zIHRoYXQgaW4gcGxhY2VzIGxpa2UgTEEgdGhlcmUgaXMgYSBtdWNoIGhpZ2hlciBwcm9wb3J0aW9uIG9mIHBlb3BsZSB3aG8gYXJlIGJlaW5nIHN3ZXB0IHVwIGJ5IHRoaXMgc3lzdGVtLgoKSSB3YW50IHRvIGRvIGEgdmlzdWFsaXphdGlvbiBzaG93aW5nIGhvdyBhcnJlc3QgY3JpbWluYWxpdHkgY2hhbmdlcyBieSBtb250aCB1bmRlciB0aGlzIGFkbWluaXN0cmF0aW9uIHNvIEknbSBnb2luZyB0byBmaWx0ZXIgdG8gbWFrZSBtdWx0aXBsZSB0YWJsZXM6CgpgYGB7cn0KU0ZBT1JKYW4yNUNyaW0gPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiLCBBcHByZWhlbnNpb25Nb250aCA9PSAiMSIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUkphbjI1Q3JpbSkKYGBgCgpgYGB7cn0KU0ZBT1JGZWIyNUNyaW0gPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiLCBBcHByZWhlbnNpb25Nb250aCA9PSAiMiIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUkZlYjI1Q3JpbSkKYGBgCgpgYGB7cn0KU0ZBT1JNYXIyNUNyaW0gPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiLCBBcHByZWhlbnNpb25Nb250aCA9PSAiMyIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUk1hcjI1Q3JpbSkKYGBgCgpgYGB7cn0KU0ZBT1JBcHIyNUNyaW0gPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiLCBBcHByZWhlbnNpb25Nb250aCA9PSAiNCIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUkFwcjI1Q3JpbSkKYGBgCgpgYGB7cn0KU0ZBT1JNYXkyNUNyaW0gPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiLCBBcHByZWhlbnNpb25Nb250aCA9PSAiNSIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUk1heTI1Q3JpbSkKYGBgCgpgYGB7cn0KU0ZBT1JKdW4yNUNyaW0gPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiLCBBcHByZWhlbnNpb25Nb250aCA9PSAiNiIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUkp1bjI1Q3JpbSkKYGBgCgpgYGB7cn0KU0ZBT1JKdWwyNUNyaW0gPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiLCBBcHByZWhlbnNpb25Nb250aCA9PSAiNyIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUkp1bDI1Q3JpbSkKYGBgCgpgYGB7cn0KU0ZBT1JBdWcyNUNyaW0gPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiLCBBcHByZWhlbnNpb25Nb250aCA9PSAiOCIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUkF1ZzI1Q3JpbSkKYGBgCgpgYGB7cn0KU0ZBT1JTZXB0MjVDcmltIDwtIFNGQU9SX0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihBcHByZWhlbnNpb25ZZWFyID09ICIyMDI1IiwgQXBwcmVoZW5zaW9uTW9udGggPT0gIjkiKSAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5YCkgJT4lCiAgdGFsbHkoKSAKClZpZXcoU0ZBT1JTZXB0MjVDcmltKQpgYGAKCmBgYHtyfQpTRkFPUk9jdDI1Q3JpbSA8LSBTRkFPUl9BZG1pbkFycmVzdCAlPiUKICBmaWx0ZXIoQXBwcmVoZW5zaW9uWWVhciA9PSAiMjAyNSIsIEFwcHJlaGVuc2lvbk1vbnRoID09ICIxMCIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUk9jdDI1Q3JpbSkKYGBgCgoKIyMjIyBBcnJlc3QgUGlja3VwIExvY2F0aW9uIGFuZCBBcHByZWhlbnNpb24gTWV0aG9kCgpgYGB7cn0KU0ZBT1JfQWRtaW5BcnJlc3QyMDI1IDwtU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiKSAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIE1ldGhvZGAsYEFwcHJlaGVuc2lvbiBTaXRlIExhbmRtYXJrYCkKCnZpZXcoU0ZBT1JfQWRtaW5BcnJlc3QyMDI1KQpgYGAKCkkgd2FudCB0byBsb29rIGF0IHdoZXJlIHRoZSBhcHByZWhlbnNpb24gbWV0aG9kIGlzIDI4N2cuCgpgYGB7cn0KU0ZBT1JfQWRtaW5BcnJlc3QyMDI1XzI4N2cgPC1TRkFPUl9BZG1pbkFycmVzdDIwMjUgJT4lCiAgZmlsdGVyKGBBcHByZWhlbnNpb24gTWV0aG9kYD09ICIyODcoZykgUHJvZ3JhbSIpCgp2aWV3KFNGQU9SX0FkbWluQXJyZXN0MjAyNV8yODdnKQpgYGAKCkkgd2FudCB0byBsb29rIGF0IGFwcHJlaGVuc2lvbiBtZXRob2QgaW52b2x2aW5nIGxvY2FsIGluY2FyY2VyYXRpb24KCmBgYHtyfQpTRkFPUl9BZG1pbkFycmVzdDIwMjVfbG9jYWwgPC0gU0ZBT1JfQWRtaW5BcnJlc3QyMDI1ICU+JQogIGZpbHRlcihgQXBwcmVoZW5zaW9uIE1ldGhvZGA9PSAiQ0FQIExvY2FsIEluY2FyY2VyYXRpb24iKQoKVmlldyAoU0ZBT1JfQWRtaW5BcnJlc3QyMDI1X2xvY2FsKQpgYGAKCk5vdyBJIHdhbnQgYSB0YWxseSBvZiBhcHByZWhlbnNpb24gc2l0ZSBsYW5kbWFya3MuCgpgYGB7cn0KU0ZBUExhbmRtYXJrcyA8LSBTRkFPUl9BZG1pbkFycmVzdDIwMjUgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBTaXRlIExhbmRtYXJrYCklPiUKICB0YWxseSgpCgp2aWV3KFNGQVBMYW5kbWFya3MpCgpgYGAKClRoZXNlIGFyZSB1bmZvcnR1bmF0ZWx5IHZhZ3VlLCBhbmQgdGhleSdyZSB3b3J0aCBsb29raW5nIGF0IGZvciBtZSBwZXJzb25hbGx5LCBidXQgdGhleSBkbyBub3QgbWFrZSBmb3IgYSBncmVhdCB2aXN1YWxpemF0aW9uLiAKCiMjIyMgTWFwcGluZyBBcnJlc3QgQU9SIGFnYWluc3QgZGV0ZW50aW9uIGZhY2lsaXRpZXMKCkknbSBnb2luZyB0byBzdGFydCBieSB0YWtpbmcgYSBzaGFwZSBmaWxlIG9mIHRoZSBBT1IgZmFjaWxpdGllcyBhbmQgcmVhZGluZyBpdCBpbi4KCmBgYHtyfQpJQ0VfQU9SIDwtIHN0X3JlYWQoIi9Vc2Vycy9lbGVhbm9ycHJpY2tldHRtb3JnYW4vRGVza3RvcC9EZXBvcnRhdGlvbkRhdGEvRVJPIGZpbGVzL2ljZS1hb3Itc2hwL2ljZS1hb3Itc2hwLnNocCIpClZpZXcoSUNFX0FPUikKYGBgCmBgYHtyfQpJQ0VfQU9SX0NMRUFOIDwtIElDRV9BT1IgJT4lCiAgZHJvcF9uYShvZmZjX25tKQoKVmlldyhJQ0VfQU9SX0NMRUFOKQpgYGAKClRoaXMgSSdtIGdvaW5nIHRvIHVzZSB0byBNYXAgaW4gUUdJUwoKYGBge3J9CnN0X3dyaXRlKElDRV9BT1JfQ0xFQU4sICJJQ0VfQU9SX0NMRUFOLnNocCIpCmBgYAoKIyMjIyBEZW1vZ3JhcGhpY3MgaW4gU0ZBT1IKCkdlbmRlciBCcmVha2Rvd24uCgpgYGB7cn0KU0ZBT1JBcnJlc3RHZW5kZXIyMDI1IDwtIFNGQU9SX0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihBcHByZWhlbnNpb25ZZWFyID09ICIyMDI1IikgJT4lCiAgZ3JvdXBfYnkoYEdlbmRlcmApICU+JQogIHRhbGx5KCkgCgpWaWV3KFNGQU9SQXJyZXN0R2VuZGVyMjAyNSkKCmBgYAoKYGBge3J9CmdncGxvdChTRkFPUkFycmVzdEdlbmRlcjIwMjUsIGFlcyh4PSJHZW5kZXIiLCB5PW4sIGZpbGw9YEdlbmRlcmApKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCB3aWR0aD0xLCBjb2xvcj0id2hpdGUiKSArCiAgY29vcmRfcG9sYXIoInkiLCBzdGFydD0wKSArCiAgZ2d0aXRsZSgiQXJyZXN0IEdlbmRlciBTRkFPUiAyMDI1IikgKwogIHRoZW1lX3ZvaWQoKQpgYGAKCgpBZ2UgQnJlYWtkb3duLgoKYGBge3J9ClNGQU9SX0FkbWluQXJyZXN0X0FnZTIwMjUgPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgbXV0YXRlKEFnZSA9IDIwMjUgLSBgQmlydGggWWVhcmApICU+JQogIGZpbHRlcihBcHByZWhlbnNpb25ZZWFyID09ICIyMDI1IikgJT4lCiAgZ3JvdXBfYnkoQWdlKSAgJT4lCiAgdGFsbHkoKQoKVmlldyhTRkFPUl9BZG1pbkFycmVzdF9BZ2UyMDI1KQpgYGAKClRoaXMgdGFibGUgaXMgbm90IHNvIHVzZWZ1bCwgSSB0aGluayBJJ2QgbGlrZSB0byBzZWUgaXQgdmlzdWFsbHkuCgpgYGB7cn0KZ2dwbG90KGRhdGE9U0ZBT1JfQWRtaW5BcnJlc3RfQWdlMjAyNSwgYWVzKHggPSBBZ2UsIHkgPW4pKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCB3aWR0aD0wLjUsIGZpbGw9ICJzdGVlbGJsdWUiKSArCiAgbGFicyggeCA9ICJBZ2UgUmFuZ2UiLCB5ID0gIk51bWJlciBvZiBBcnJlc3RzIikgKwogIGdndGl0bGUoIkFycmVzdHMgYnkgQWdlIFNGQU9SIikgKwogIHNjYWxlX3hfY29udGludW91cyhuLmJyZWFrcz0yMCkKYGBgCgpgYGB7cn0Kc3VtbWFyeShTRkFPUl9BZG1pbkFycmVzdF9BZ2UyMDI1JEFnZSkKYGBgCgoKIyMjIyBIb3cgTWFueSBBcnJlc3RzIHJlc3VsdCBpbiBEZXBvcnRhdGlvbgoKYGBge3J9ClNGQU9SRGVwYXJ0dXJlQ291bnRyeSA8LSBTRkFPUl9BZG1pbkFycmVzdCAlPiUKICBmaWx0ZXIoQXBwcmVoZW5zaW9uWWVhciA9PSAiMjAyNSIpICU+JQogIGdyb3VwX2J5KGBEZXBhcnR1cmUgQ291bnRyeWApICU+JQogIHRhbGx5KCkKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGE9U0ZBT1JEZXBhcnR1cmVDb3VudHJ5LCBhZXMoeCA9IGBEZXBhcnR1cmUgQ291bnRyeWAsIHkgPW4pKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCB3aWR0aD0wLjUsIGZpbGw9ICJzdGVlbGJsdWUiKSArCiAgbGFicyggeCA9ICJDb3VudHJ5IiwgeSA9ICJOdW1iZXIgb2YgQXJyZXN0cyIpICsKICBnZ3RpdGxlKCJEZXBhcnR1cmUgQ291bnRyeSBTRkFPUiAyMDI1IikgCmBgYAoKCmBgYHtyfQpTRkFPUl9BZG1pbkFycmVzdCAlPiUKICBmaWx0ZXIoQXBwcmVoZW5zaW9uWWVhciA9PSAiMjAyNSIpICU+JQogIGdyb3VwX2J5KGBDYXNlIFN0YXR1c2ApICU+JQogIHRhbGx5KCkKYGBgCgo=