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 Apprehension Criminality Case Status        Case Category     
 Min.   :2023-09-01 00:00:00   Length:377067      Mode:logical        Length:377067      Length:377067      Length:377067       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    Class :character         Class :character   Class :character  
 Median :2025-03-12 13:50:00   Mode  :character                       Mode  :character   Mode  :character   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                                                                                                                                                                                      
                                                                                                                                                                                                                  
 Departed Date                 Departure Country  Final Order Yes No Final Order Date               Birth Date          Birth Year   Citizenship Country    Gender          Apprehension Site Landmark Alien File Number 
 Min.   :1923-09-14 00:00:00   Length:377067      Length:377067      Min.   :1967-01-06 00:00:00   Length:377067      Min.   :1932   Length:377067       Length:377067      Length:377067              Length:377067     
 1st Qu.:2024-10-02 00:00:00   Class :character   Class :character   1st Qu.:2019-09-26 00:00:00   Class :character   1st Qu.:1983   Class :character    Class :character   Class :character           Class :character  
 Median :2025-05-04 00:00:00   Mode  :character   Mode  :character   Median :2024-06-20 00:00:00   Mode  :character   Median :1991   Mode  :character    Mode  :character   Mode  :character           Mode  :character  
 Mean   :2025-02-18 23:21:58                                         Mean   :2021-06-04 17:40:28                      Mean   :1990                                                                                       
 3rd Qu.:2025-08-04 00:00:00                                         3rd Qu.:2025-05-09 00:00:00                      3rd Qu.:1998                                                                                       
 Max.   :2025-10-15 00:00:00                                         Max.   :2025-10-16 00:00:00                      Max.   :2025                                                                                       
 NA's   :140929                                                      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 36,984 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 4,576 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 374,561 entries instead of the original 377067. 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. The Deportation Data Project does also release a “processed” version of their data that I could compare this too, BUT, they delete certain columns that in the processed data that I’m interested in looking at.

Checking for Consistency Issues

When looking at consistency issues, I’m looking at the columns that have characters. I have broken out below, by column, how I checked for issues with characters.

Apprehension State

There are 50 states in the US, so I’m looking for a result that gives back 50 rows, maybe 51 for arrests that take place in DC.

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

Here there are a couple consistency issues. Some rows fall under “ARMED FORCES - EUROPE,” “ARMED FORCES - THE AMERICAS,” and “ARMED SERVICES - THE PACIFIC,” all of which are not states in any traditional sense. I also 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)

From the ICE.gov website I’m expecting 25 AOR’s, so I want 25 rows back.

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 HQ Area of Responsibility, which doees appear on the ICE website, but doesn’t correspond to a specifc geography.

Final Program

I don’t know how many final program categories I’m expecting, so here I have to check in a more granular way that there aren’t spelling or capitalization variations.

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

Again I don’t have a set number of apprehension methods that I’m expecting from a data dictionary, so I am checking for spelling/capitalizaiton consistency.

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

Apprhension Criminality is assigned to one of three categories, so I want back 3 rows.

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

This looks consistent, but I am wary of the fact that there are no blanks in anyones purported criminality because these same rows can have a lot of missing information. ICE has incentive to overestimate in this data the proportion of people who do have criminal convictions.

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 9272 who are not in a category at all, which is confusing because one category is literally just for active cases. I’m concerned also about the 54 deaths listed.

Case Category

I don’t have a set number of case categories I’m looking for so this is a regular consistency check.

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

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

Departure Country

There US recognizes 197 independent states, and 193 member countries to the UN. I for sure don’t want the number of rows here to exceed 197.

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

I got back 193 rows which is in line with the number of UN member countries. 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

Same as with departure country I don’t want the number of countries to exceed 197.

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. One issue is that Serbia, Montenegro, and “Serbia and Montenegro” (which dissolved in 2006) all appear in the data. Similarly USSR and Yugoslavia also appear in the data. I imagine that these represent people who came to the US and during their time here those countries dissolved, which accounts for the extra rows. Additionally, there are 394 people whose citizenship country is listed as “unknown,” but no one has a blank entry for citizenship country.

Gender

Gender I expect 2 rows.

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

Apprehension Site Landmark I have very little expectations on what will come back and this is where I expect the majority of inconsistentcies to be.

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

Here I get back 5590 rows, and there are major differences in capitalization and usage of dashes. Some include the state they were in, others do not. Some also include the program they were in (287(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        Final Program Group        Apprehension Method   Apprehension Criminality 
                         0                      60154                     377067                       5887                          0                          0                          0                          0 
               Case Status              Case Category              Departed Date          Departure Country         Final Order Yes No           Final Order Date                 Birth Date                 Birth Year 
                      9372                       9373                     140929                     140983                       9372                     147872                          1                          1 
       Citizenship Country                     Gender Apprehension Site Landmark          Alien File Number                EID Case ID             EID Subject ID          Unique Identifier 
                         0                          0                       8767                       5410                       9372                          0                       5410 

Here what’s a big deal is that there are 5410 people missing an A number or a Unique Identifier. I am less worried because the EID subject ID has no missing data, but that is something to keep note of.

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 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.

Changes to Criminality by Month

After looking at the general summary of criminality information, I want to see how the criminality of who is arrested has changed in the SFAOR by month. The question I’d want answered is if the proportion of people being arrested who have criminal convictions is changing. So much reporting has said that regular people with no convictions are getting swept up in arrests under this administration. So, I started with SFAOR Admin Arrest Data, filtered it by the current year, and then for each month so far I had it give me the proportion of arrests based on criminality.

January

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

View(SFAORJan25Crim)

February

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

View(SFAORFeb25Crim)

March

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

View(SFAORMar25Crim)

April

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

View(SFAORApr25Crim)

May

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

View(SFAORMay25Crim)

June

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

View(SFAORJun25Crim)

July

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

View(SFAORJul25Crim)

August

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

View(SFAORAug25Crim)

September

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

View(SFAORSept25Crim)

October, but I’m noting that the October data is incomplete.

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

View(SFAOROct25Crim)

There was probably a faster way to iterate this process, but I took the results of each of these and made a spreadsheet to visualize.

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.

Demographics in SFAOR

This is the gender of SFAOR admin arrests in 2025.

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

View(SFAORArrestGender2025)

Here’s the gender information graphed

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()

This is an age breakdown of SFAOR admin arrests in 2025

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

View(SFAOR_AdminArrest_Age2025)

Here is that same information graphed.

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)

I want to know what the Median and Mean age of arrest are so I can incorporate them into a better graphic

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 

Where do Arrested People in the SFAOR Go?

I’m going to do some analysis with the intention of putting it into a prettier program, like flourish. The only surefire way to tell if an arrest results in a deportation is that there is a departure country or departed date listed. I want to start creating two new entities, one which is the SFAOR 2025 arrests that resulted in a deportation, and the other being the SFAOR 2025 arrests that did not result in a deportation. Here’s how I would make each of those.

Deported Data Set:

Deported_SFAOR_25 <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025") %>% 
  drop_na(`Departed Date`)

View(Deported_SFAOR_25)

Non Deported Data Set:

NotDeported_SFAOR_25 <- SFAOR_AdminArrest %>%
  filter(ApprehensionYear == "2025", is.na(`Departed Date`)) 
 
View(NotDeported_SFAOR_25)

I want to note that 2,086 arrests in the SFAOR resulted in deportation, and 1,756 did not. Now I want to look at the final program that people who were deported ended up in.

FPDeported_SFAOR_25 <- Deported_SFAOR_25 %>%
  group_by(`Final Program`) %>%
  tally()

View(FPDeported_SFAOR_25)

It’s not surprising that ERO Criminal Alien Program was the largest category because it’s the vaguest, so within that I wanted to see what the top apprehension methods were.

ERODeported_SFAOR_25 <- Deported_SFAOR_25 %>%
  filter(`Final Program`== "ERO Criminal Alien Program") %>%
  group_by(`Apprehension Method`) %>%
  tally()

View(ERODeported_SFAOR_25)

I also want to see how the apprehension method breakdown for people who were deported.

AMDeported_SFAOR_25 <- Deported_SFAOR_25 %>%
  group_by(`Apprehension Method`) %>%
  tally()

View(AMDeported_SFAOR_25)

Out of curiosity I do want to see the final program breakdown for people who were not deported.

FPNotDeported_SFAOR_25 <- NotDeported_SFAOR_25 %>%
  group_by(`Final Program`) %>%
  tally()

View(FPNotDeported_SFAOR_25)

For both groups I also want to see what the criminality breakdown looks like. Here first is the Deported Group’s criminality:

CrimDeported_SFAOR_25 <- Deported_SFAOR_25 %>%
  group_by(`Apprehension Criminality`) %>%
  tally()

View(CrimDeported_SFAOR_25)

And this is the non deported group’s criminality.

CrimNotDeported_SFAOR_25 <- NotDeported_SFAOR_25 %>%
  group_by(`Apprehension Criminality`) %>%
  tally()

View(CrimNotDeported_SFAOR_25)

Here it is interesting to note that the vast majority of people who are arrested and deported (for now) do seem to have a criminal conviction, but the arrested non deported category is many more folks with just immigration violations. This is worth noting. I did a bunch of these breakouts for the purposes of my own understanding, but as for making a visual that I think has more capacity to be informative, I’m going to work with the final program categorization to make a

LS0tCnRpdGxlOiAiSjIyMSBFUE0gRmluYWwgUHJvamVjdCDigJQgQWRtaW5pc3RyYXRpdmUgQXJyZXN0cyIKYXV0aG9yOiAiRWxsaWUgUHJpY2tldHQtTW9yZ2FuIgpkYXRlOiAiMjAyNS0xMi0xMCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgU2V0dXAgYW5kIExpYnJhcmllcwoKYGBge3J9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZXJyb3IgPSBUUlVFLCBjYWNoZT1UUlVFLCBhdXRvZGVwID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCBwcm9ncmVzc19iYXIgPSBGQUxTRSkKCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkodGlkeXZlcnNlKSAKbGlicmFyeShkcGx5cikgCmxpYnJhcnkoZ2dwbG90MikgCmxpYnJhcnkoa25pdHIpIApsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KGxtZTQpCmxpYnJhcnkoYm9vdCkKbGlicmFyeShnZ2VmZmVjdHMpIApsaWJyYXJ5KERlc2NUb29scykKbGlicmFyeSh0aWR5Y2Vuc3VzKQpsaWJyYXJ5KHhtbDIpCmxpYnJhcnkodG1hcCkKbGlicmFyeSh0bWFwdG9vbHMpCmxpYnJhcnkobGVhZmxldCkKbGlicmFyeShzZikKbGlicmFyeShsZWFmbGV0LmV4dHJhcykKbGlicmFyeShyYXN0ZXIpCmxpYnJhcnkodGlncmlzKQpsaWJyYXJ5KHNwKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShzdHJpbmdpKQpsaWJyYXJ5KGxlYWZsZWdlbmQpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoamFuaXRvcikKbGlicmFyeShnZ3JlcGVsKQpgYGAKCmBgYHtyfQpzZXR3ZCgiL1VzZXJzL2VsZWFub3Jwcmlja2V0dG1vcmdhbi9EZXNrdG9wL0RlcG9ydGF0aW9uRGF0YS8iKQpgYGAKCiMjIEltcG9ydGluZyBEYXRhCgpJJ20gc2tpcHBpbmcgNiBiZWNhdXNlIHRoZSBmaXJzdCA2IHJvd3Mgb2YgdGhlIGV4Y2VsIGZpbGUgaGF2ZSBzdW1tYXJ5IGluZm9ybWF0aW9uLCBidXQgdGhlIGRhdGEgaXRzZWxmIGRvZXNuJ3QgYWN0dWFsbHkgc3RhcnQuIFRoZW4gSSdtIHVzaW5nIFN1bW1hcnkgdG8gY2hlY2sgd2hhdCBteSB0aW1lIHJhbmdlIGlzLCBsb29raW5nIHNwZWNpZmljYWxseSBhdCB0aGUgQXBwcmVoZW5zaW9uIGNvbHVtbi4gCgpgYGB7cn0KQWRtaW5BcnJlc3QgPC0gcmVhZF9leGNlbCgiL1VzZXJzL2VsZWFub3Jwcmlja2V0dG1vcmdhbi9EZXNrdG9wL0RlcG9ydGF0aW9uRGF0YS9FUk8gQWRtaW4gQXJyZXN0c19MRVNBLVNUVS1GSU5BTCBSZWxlYXNlX3Jhdy54bHN4Iiwgc2tpcCA9IDYpClZpZXcoQWRtaW5BcnJlc3QpCnN1bW1hcnkoQWRtaW5BcnJlc3QpCmBgYAoKIyMgQ2xlYW5pbmcgdGhlIERhdGEKCiMjIyBDaGVja2luZyBmb3IgRHVwbGljYXRlcwoKVG8gY2hlY2sgZm9yIGR1cGxpY2F0ZXMgSSdtIGdvaW5nIHRvIGxvb2sgYXQgdGhlIHVuaXF1ZSBpZGVudGlmaWVyIGNvbHVtbi4gCgpgYGB7cn0KQWRtaW5BcnJlc3QgJT4lCiAgZ3JvdXBfYnkoYFVuaXF1ZSBJZGVudGlmaWVyYCkgJT4lCiAgZmlsdGVyKG4oKT09MikKCmBgYAoKSSBnZXQgYmFjayAzNiw5ODQgcm93cyB3aGVyZSB0aGUgVW5pcXVlIElkZW50aWZpZXIgcmVwZWF0ZWQgaXRzZWxmLiBCdXQgSSBjYW4gdGVsbCB0aGF0IHRoZXJlIGFyZSBjZXJ0YWluIGluc3RhbmNlcyB3aGVyZSB0aGUgc2FtZSBpZGVudGlmaWVyIGFwcGVhcnMgdHdpY2Ugd2l0aCBhIGRpZmZlcmVudCBhcHByZWhlbnNpb24gZGF0ZS4gU28gSSdtIGdvaW5nIHRvIHRyeSBhZ2FpbiBsb29raW5nIGF0IEFwcHJlaGVuc2lvbiBEYXRlIGluIGFkZGl0aW9uIHRvIHRoZSBVbmlxdWUgSWRlbnRpZmllciBjb2x1bW4uIAoKYGBge3J9CkFkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KGBVbmlxdWUgSWRlbnRpZmllcmAsIGBBcHByZWhlbnNpb24gRGF0ZWApICU+JQogIGZpbHRlcihuKCk9PTIpCmBgYAoKV2hlbiBJIGZpbHRlciBieSBib3RoIG9mIHRoZXNlIHRoaW5ncyBJIGdldCA0LDU3NiByb3dzLiBUaGF0IHN1Z2dlc3RzIHRoYXQgbWF5YmUgY2VydGFpbiBpbmRpdmlkdWFscyB3ZXJlIGFycmVzdGVkIHR3aWNlLCBvciBoYXZlIGJlZW4gaW4gdGhlIHN5c3RlbSBtdWx0aXBsZSB0aW1lcyBvdmVyIHRoZSBjb3Vyc2Ugb2YgbWFueSB5ZWFycywgdGhpcyBpcyBjbG9zZXIgdG8gdGhlIHRydWUgbnVtYmVyIG9mIGR1cGxpY2F0ZXMuIFNvIG5vdyBJJ20gZ29pbmcgdG8gcmVtb3ZlIHRob3NlIHBvdGVudGlhbCBkdXBsaWNhdGVzIHVzaW5nIHRoZSBkaXN0aW5jdCBmdW5jdGlvbi4gCgpgYGB7cn0KY2xlYW5lZF9BZG1pbkFycmVzdCA8LSBBZG1pbkFycmVzdCAlPiUKICBkaXN0aW5jdChgVW5pcXVlIElkZW50aWZpZXJgLGBBcHByZWhlbnNpb24gRGF0ZWAsIC5rZWVwX2FsbCA9IFRSVUUpClZpZXcoY2xlYW5lZF9BZG1pbkFycmVzdCkKYGBgCgpXaGVuIEkgcnVuIHRoaXMgSSBub3cgaGF2ZSAzNzQsNTYxIGVudHJpZXMgaW5zdGVhZCBvZiB0aGUgb3JpZ2luYWwgMzc3MDY3LiBJIHdvdWxkIHByb2JhYmx5IHN0aWxsIGFzayBhbiBleHBlcnQgd2hvIHdvcmtzIHdpdGggdGhpcyBkYXRhIGlmIHRoZXJlIGFyZSBvdGhlciB3YXlzIEkgbWlnaHQgbm90IGJlIGNhdGNoaW5nIGR1cGxpY2F0ZXMgYnV0IHRoaXMgbWFrZXMgdGhlIG1vc3Qgc2Vuc2UgdG8gbWUuIFRoZSBEZXBvcnRhdGlvbiBEYXRhIFByb2plY3QgZG9lcyBhbHNvIHJlbGVhc2UgYSAicHJvY2Vzc2VkIiB2ZXJzaW9uIG9mIHRoZWlyIGRhdGEgdGhhdCBJIGNvdWxkIGNvbXBhcmUgdGhpcyB0b28sIEJVVCwgdGhleSBkZWxldGUgY2VydGFpbiBjb2x1bW5zIHRoYXQgaW4gdGhlIHByb2Nlc3NlZCBkYXRhIHRoYXQgSSdtIGludGVyZXN0ZWQgaW4gbG9va2luZyBhdC4gCgojIyMgQ2hlY2tpbmcgZm9yIENvbnNpc3RlbmN5IElzc3VlcwoKV2hlbiBsb29raW5nIGF0IGNvbnNpc3RlbmN5IGlzc3VlcywgSSdtIGxvb2tpbmcgYXQgdGhlIGNvbHVtbnMgdGhhdCBoYXZlIGNoYXJhY3RlcnMuIEkgaGF2ZSBicm9rZW4gb3V0IGJlbG93LCBieSBjb2x1bW4sIGhvdyBJIGNoZWNrZWQgZm9yIGlzc3VlcyB3aXRoIGNoYXJhY3RlcnMuCgojIyMjIEFwcHJlaGVuc2lvbiBTdGF0ZQoKVGhlcmUgYXJlIDUwIHN0YXRlcyBpbiB0aGUgVVMsIHNvIEknbSBsb29raW5nIGZvciBhIHJlc3VsdCB0aGF0IGdpdmVzIGJhY2sgNTAgcm93cywgbWF5YmUgNTEgZm9yIGFycmVzdHMgdGhhdCB0YWtlIHBsYWNlIGluIERDLgoKYGBge3J9CmNsZWFuZWRfQWRtaW5BcnJlc3QgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBTdGF0ZWApICU+JQogIHRhbGx5KCkKYGBgCgpIZXJlIHRoZXJlIGFyZSBhIGNvdXBsZSBjb25zaXN0ZW5jeSBpc3N1ZXMuIFNvbWUgcm93cyBmYWxsIHVuZGVyICJBUk1FRCBGT1JDRVMgLSBFVVJPUEUsIiAiQVJNRUQgRk9SQ0VTIC0gVEhFIEFNRVJJQ0FTLCIgYW5kICJBUk1FRCBTRVJWSUNFUyAtIFRIRSBQQUNJRklDLCIgYWxsIG9mIHdoaWNoIGFyZSBub3Qgc3RhdGVzIGluIGFueSB0cmFkaXRpb25hbCBzZW5zZS4gSSBhbHNvIGhhdmUgbm8gaWRlYSB3aGF0IGRpZmZlcmVudGlhdGVzIGFybWVkIGZvcmNlcyB2cy4gc2VydmljZXMsIG5vciBhbSBJIGNsZWFyIGlmIHRoZXNlIGFyZSBhcnJlc3RzIHRoYXQgdG9vayBwbGFjZSBvbiBtaWxpdGFyeSBiYXNlcyBvciBhcyBhIHBhcnQgb2YgbWlsaXRhcnkgb3BlcmF0aW9ucy4gV29ydGggbm90aW5nIHRoYXQgd2UgaGF2ZSA2MiByb3dzLCBpbnN0ZWFkIG9mIDUwLCB3aGljaCBpcyBwYXJ0aWFsbHkgYmVjYXVzZSBvZiB0ZXJyaXRvcmllcyB1bmRlciBVUyBjb250cm9sIChpLmUuIFB1ZXJ0byBSaWNvLCBGZWRlcmF0ZWQgU3RhdGVzIG9mIE1pY3JvbmVzaWEsIEd1YW0sIGV0Yy4pIERpc3RyaWN0IG9mIENvbHVtYmlhIGlzIGFsc28gaXQncyBvd24gZW50cnksIGFuZCBpdCdzIG5vdCBhIHN0YXRlLiBUaGVyZSBhcmUgYWxzbyB0d28gbG9uZSBlbnRyaWVzIGluIGFyZWFzIG91dHNpZGUgb2YgVVMgY29udHJvbCwgb25lIGp1c3QgbGFiZWxlZCAiTUVYSUNPLCIgdGhlIG90aGVyIGxhYmVsZWQgIlRBTUFVTElQQVMsIiB3aGljaCBpcyBhIHRlcnJpdG9yeSBpbiBNZXhpY28uIFRob3NlIHNlZW0gbGlrZSBpbmRpdmlkdWFsIGRhdGEgZW50cnkgaXNzdWVzIG9yIG1pc2NhdGVnb3JpemF0aW9ucy4gQXNpZGUgZnJvbSB0aGF0LCB0aGUgc3RhdGVzIHRoZW1zZWx2ZXMgYXJlIHNwZWxsZWQgaW4gY29uc2lzdGVudCB3YXlzLiAKCiMjIyMgQU9SIChBcmVhIG9mIFJlc3BvbnNpYmlsaXR5KQoKRnJvbSB0aGUgSUNFLmdvdiB3ZWJzaXRlIEknbSBleHBlY3RpbmcgMjUgQU9SJ3MsIHNvIEkgd2FudCAyNSByb3dzIGJhY2suIAoKYGBge3J9CmNsZWFuZWRfQWRtaW5BcnJlc3QgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBBT1JgKSAlPiUKICB0YWxseSgpCgpgYGAKCkhlcmUgSSBnb3QgMjcgcm93cyBiYWNrLCBvbmUgY29ycmVzcG9uZGVkIHRvIE4vQSwgd2l0aCA1MjIzIGVudHJpZXMgbm90IGFzc2lnbmVkIHRvIGEgc3BlY2lmaWMgZ2VvZ3JhcGh5LiBUaGVyZSdzIGFsc28gYSBIUSBBcmVhIG9mIFJlc3BvbnNpYmlsaXR5LCB3aGljaCBkb2VlcyBhcHBlYXIgb24gdGhlIElDRSB3ZWJzaXRlLCBidXQgZG9lc24ndCBjb3JyZXNwb25kIHRvIGEgc3BlY2lmYyBnZW9ncmFwaHkuCgojIyMjIEZpbmFsIFByb2dyYW0KCkkgZG9uJ3Qga25vdyBob3cgbWFueSBmaW5hbCBwcm9ncmFtIGNhdGVnb3JpZXMgSSdtIGV4cGVjdGluZywgc28gaGVyZSBJIGhhdmUgdG8gY2hlY2sgaW4gYSBtb3JlIGdyYW51bGFyIHdheSB0aGF0IHRoZXJlIGFyZW4ndCBzcGVsbGluZyBvciBjYXBpdGFsaXphdGlvbiB2YXJpYXRpb25zLiAKCmBgYHtyfQpjbGVhbmVkX0FkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KGBGaW5hbCBQcm9ncmFtYCkgJT4lCiAgdGFsbHkoKQpgYGAKCkhlcmUgdGhlIG1vc3Qgb2J2aW91cyBpc3N1ZSB3aGljaCBwb3B1bGF0ZXMgZmlyc3QgaXMgd2hhdCdzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gIjI4N0cgUHJvZ3JhbSIgYW5kICIyODdnIFRhc2sgRm9yY2UuIiBCZWNhdXNlIG15IHByb2plY3QgaXMgaW4gQ2FsaWZvcm5pYSB3aGljaCBpcyAoYWxsZWdlZGx5KSBub3QgcGFydGljaXBhdGluZyBpbiAyODdnLCBJJ20gbm90IHdvcnJpZWQgYWJvdXQgdGhhdC4gSSB3b3VsZCB3YW50IHRvIGRvdWJsZSBjaGVjayB3aXRoIGFuIGV4cGVydCB0aGF0IHNvbWUgb2YgdGhlc2UgdGhpbmdzIGRvIG5vdCByZWZlciB0byB0aGUgc2FtZSBwcmFjdGljYWwgY2F0ZWdvcmllcy4gSSBhbSBjb25jZXJuZWQgYWJvdXQgdGhlIDQ4NyBKdXZlbmlsZXMgbGlzdGVkIGhlcmUuCgojIyMjIEZpbmFsIFByb2dyYW0gR3JvdXAKCkJlY2F1c2UgdGhpcyBpcyBJQ0UgZGF0YSwgSSB3b3VsZCBhc3N1bWUgZXZlcnl0aGluZyBpbiB0aGUgZmluYWwgcHJvZ3JhbSBncm91cCBjb2x1bW4gaXMgSUNFLCBidXQgSSdtIGp1c3QgZG91YmxlIGNoZWNraW5nLiAKCmBgYHtyfQpjbGVhbmVkX0FkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KGBGaW5hbCBQcm9ncmFtIEdyb3VwYCkgJT4lCiAgdGFsbHkoKQpgYGAKVGhhdCBwcm9kdWNlZCBqdXN0IG9uZSByb3csIHNvIHRoYXQncyBjb25zaXN0ZW50LiAKCiMjIyMgQXBwcmVoZW5zaW9uIE1ldGhvZAoKQWdhaW4gSSBkb24ndCBoYXZlIGEgc2V0IG51bWJlciBvZiBhcHByZWhlbnNpb24gbWV0aG9kcyB0aGF0IEknbSBleHBlY3RpbmcgZnJvbSBhIGRhdGEgZGljdGlvbmFyeSwgc28gSSBhbSBjaGVja2luZyBmb3Igc3BlbGxpbmcvY2FwaXRhbGl6YWl0b24gY29uc2lzdGVuY3kuCgpgYGB7cn0KY2xlYW5lZF9BZG1pbkFycmVzdCAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIE1ldGhvZGApICU+JQogIHRhbGx5KCkKYGBgCgpJbiB0ZXJtcyBvZiBob3cgdGhpbmdzIGFyZSBsaXRlcmFsbHkgc3BlbGxlZCB5ZXMgdGhlcmUgaXMgY29uc2lzdGVuY3kuIEluIHRlcm1zIG9mIHdoYXQgdGhlIGRhdGEgaXMgc2F5aW5nIGhlcmUsIEkgZG8gaGF2ZSBhIGxvdCBvZiBxdWVzdGlvbnMuIEZvciBleGFtcGxlIG9ubHkgb25lIHBlcnNvbiBpcyBsaXN0ZWQgYXMgYXJyZXN0ZWQgaW4gdGhlICJQcmVzZW50ZWQgRHVyaW5nIEluc3BlY3Rpb24iIGNhdGVnb3J5LCB3aGljaCBmZWVscyBsaWtlIGEgY29udHJhZGljdGlvbiB3aXRoIHRoZSBjb3VydGhvdXNlIGFuZCBmaWVsZCBvZmZpY2UgY2hlY2staW5zIGhhdmluZyBzbyBtYW55IGluZGl2aWR1YWxzIGdyYWJiZWQgYnkgSUNFLiBIb3dldmVyLCB0aG9zZSBtaWdodCBiZSBhIGRpZmZlcmVudCBjYXRlZ29yeSBvZiBlbmZvcmNlbWVudCB0aGF0J3MgaW5jbHVkZWQgaW4gYW5vdGhlciBkYXRhIHNldCAoaS5lLiBkZXRlbnRpb25zKS4gVGhpcyBpcyBwcm9iYWJseSBteSBmbGF3ZWQgdW5kZXJzdGFuZGluZyBvZiB0aGUgbGVnYWwgc3lzdGVtIGhlcmUsIGJ1dCBzdGlsbCBzb21ldGhpbmcgSSB3YW50IHRvIG5vdGUuIAoKIyMjIyBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHkKCkFwcHJoZW5zaW9uIENyaW1pbmFsaXR5IGlzIGFzc2lnbmVkIHRvIG9uZSBvZiB0aHJlZSBjYXRlZ29yaWVzLCBzbyBJIHdhbnQgYmFjayAzIHJvd3MuCgpgYGB7cn0KY2xlYW5lZF9BZG1pbkFycmVzdCAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5YCkgJT4lCiAgdGFsbHkoKQpgYGAKClRoaXMgbG9va3MgY29uc2lzdGVudCwgYnV0IEkgYW0gd2FyeSBvZiB0aGUgZmFjdCB0aGF0IHRoZXJlIGFyZSBubyBibGFua3MgaW4gYW55b25lcyBwdXJwb3J0ZWQgY3JpbWluYWxpdHkgYmVjYXVzZSB0aGVzZSBzYW1lIHJvd3MgY2FuIGhhdmUgYSBsb3Qgb2YgbWlzc2luZyBpbmZvcm1hdGlvbi4gSUNFIGhhcyBpbmNlbnRpdmUgdG8gb3ZlcmVzdGltYXRlIGluIHRoaXMgZGF0YSB0aGUgcHJvcG9ydGlvbiBvZiBwZW9wbGUgd2hvIGRvIGhhdmUgY3JpbWluYWwgY29udmljdGlvbnMuIAoKIyMjIyBDYXNlIFN0YXR1cwoKTm93IEknbGwgY2hlY2sgZm9yIGNhc2Ugc3RhdHVzOgoKYGBge3J9CmNsZWFuZWRfQWRtaW5BcnJlc3QgJT4lCiAgZ3JvdXBfYnkoYENhc2UgU3RhdHVzYCkgJT4lCiAgdGFsbHkoKQpgYGAKCkhlcmUgSSBnZXQgYmFjayAxNCByb3dzIHdpdGggY2F0ZWdvcmllcyBsaXN0ZWQuIFRoZSBmaXJzdCBjaHVuayBhcmUgbnVtYmVyZWQgc3RhcnRpbmcgYXQgMCwgYnV0IG5vdGFibHkgbWlzc2luZyAxIGFuZCAyLiBJIGRvbid0IGtub3cgd2hhdCB0aG9zZSBjYXRlZ29yaWVzIGNvdWxkIGJlLiBUaGVyZSBhcmUgOTI3MiB3aG8gYXJlIG5vdCBpbiBhIGNhdGVnb3J5IGF0IGFsbCwgd2hpY2ggaXMgY29uZnVzaW5nIGJlY2F1c2Ugb25lIGNhdGVnb3J5IGlzIGxpdGVyYWxseSBqdXN0IGZvciBhY3RpdmUgY2FzZXMuIEknbSBjb25jZXJuZWQgYWxzbyBhYm91dCB0aGUgNTQgZGVhdGhzIGxpc3RlZC4KCiMjIyMgQ2FzZSBDYXRlZ29yeQoKSSBkb24ndCBoYXZlIGEgc2V0IG51bWJlciBvZiBjYXNlIGNhdGVnb3JpZXMgSSdtIGxvb2tpbmcgZm9yIHNvIHRoaXMgaXMgYSByZWd1bGFyIGNvbnNpc3RlbmN5IGNoZWNrLiAKCmBgYHtyfQpjbGVhbmVkX0FkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KGBDYXNlIENhdGVnb3J5YCkgJT4lCiAgdGFsbHkoKQpgYGAKCkhlcmUgdGhlcmUgYXJlIG5vIGdsYXJpbmcgY29uc2lzdGVuY3kgaXNzdWVzIGV4Y2VwdCB0aGUgNDQxMiB1bmNhdGVnb3JpemVkIGNhc2VzLiAKCiMjIyMgRGVwYXJ0dXJlIENvdW50cnkKClRoZXJlIFVTIHJlY29nbml6ZXMgMTk3IGluZGVwZW5kZW50IHN0YXRlcywgYW5kIDE5MyBtZW1iZXIgY291bnRyaWVzIHRvIHRoZSBVTi4gSSBmb3Igc3VyZSBkb24ndCB3YW50IHRoZSBudW1iZXIgb2Ygcm93cyBoZXJlIHRvIGV4Y2VlZCAxOTcuCgpgYGB7cn0KY2xlYW5lZF9BZG1pbkFycmVzdCAlPiUKICBncm91cF9ieShgRGVwYXJ0dXJlIENvdW50cnlgKSAlPiUKICB0YWxseSgpCmBgYAoKSSBnb3QgYmFjayAxOTMgcm93cyB3aGljaCBpcyBpbiBsaW5lIHdpdGggdGhlIG51bWJlciBvZiBVTiBtZW1iZXIgY291bnRyaWVzLiBDbGlja2luZyB0aHJvdWdoIEkgZGlkbid0IHNlZSBhbnkgc3VwZXIgd2VpcmQgZHVwbGljYXRlcy4gT25lIHJvdyBpcyBOL0EgYnV0IGZyb20gbG9va2luZyBhdCB0aGUgb3RoZXIgY29sdW1ucyBpbiBjb25qdW5jdGlvbiwgSSB0aGluayBhIGRlcGFydHVyZSBjb3VudHJ5IGlzIG9ubHkgZW50ZXJlZCB3aGVuIHRoZSBkZXBhcnR1cmUgaGFwcGVucywgc28gdGhlIGFjdGl2ZSBjYXNlcyBkb24ndCBoYXZlIGEgZGVwYXJ0dXJlIGNvdW50cnkgbGlzdGVkLiAKCiMjIyMgRmluYWwgT3JkZXIgWWVzIG9yIE5vCgpOb3cgSSdsbCBjaGVjayBmaW5hbCBvcmRlciBZZXMgb3IgTm8gKGhvcGVmdWxseSAyIHJvd3MpLgoKYGBge3J9CmNsZWFuZWRfQWRtaW5BcnJlc3QgJT4lCiAgZ3JvdXBfYnkoYEZpbmFsIE9yZGVyIFllcyBOb2ApICU+JQogIHRhbGx5KCkKYGBgCkhlcmUgd2UgZ2V0IGJhY2sgWWVzLCBObywgb3IgQmxhbmsgKDQ0MTIgcm93cykuCgojIyMjIENpdGl6ZW5zaGlwIENvdW50cnkKClNhbWUgYXMgd2l0aCBkZXBhcnR1cmUgY291bnRyeSBJIGRvbid0IHdhbnQgdGhlIG51bWJlciBvZiBjb3VudHJpZXMgdG8gZXhjZWVkIDE5Ny4KCmBgYHtyfQpjbGVhbmVkX0FkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KGBDaXRpemVuc2hpcCBDb3VudHJ5YCkgJT4lCiAgdGFsbHkoKQpgYGAKCk15IGNpdGl6ZW5zaGlwIGNvdW50cmllcyBvdXRudW1iZXIgbXkgZGVwYXJ0dXJlIGNvdW50cmllcyBieSAzLCBJIHdvdWxkIHdhbnQgdG8gY29tcGFyZSB0aG9zZSBhbmQgc2VlIHdoZXJlIEkgaGF2ZSBhZGRpdGlvbmFsIGNpdGl6ZW5zaGlwIGJ1dCBub3QgZGVwYXJ0dXJlLiBPbmUgaXNzdWUgaXMgdGhhdCBTZXJiaWEsIE1vbnRlbmVncm8sIGFuZCAiU2VyYmlhIGFuZCBNb250ZW5lZ3JvIiAod2hpY2ggZGlzc29sdmVkIGluIDIwMDYpIGFsbCBhcHBlYXIgaW4gdGhlIGRhdGEuIFNpbWlsYXJseSBVU1NSIGFuZCBZdWdvc2xhdmlhIGFsc28gYXBwZWFyIGluIHRoZSBkYXRhLiBJIGltYWdpbmUgdGhhdCB0aGVzZSByZXByZXNlbnQgcGVvcGxlIHdobyBjYW1lIHRvIHRoZSBVUyBhbmQgZHVyaW5nIHRoZWlyIHRpbWUgaGVyZSB0aG9zZSBjb3VudHJpZXMgZGlzc29sdmVkLCB3aGljaCBhY2NvdW50cyBmb3IgdGhlIGV4dHJhIHJvd3MuIEFkZGl0aW9uYWxseSwgdGhlcmUgYXJlIDM5NCBwZW9wbGUgd2hvc2UgY2l0aXplbnNoaXAgY291bnRyeSBpcyBsaXN0ZWQgYXMgInVua25vd24sIiBidXQgbm8gb25lIGhhcyBhIGJsYW5rIGVudHJ5IGZvciBjaXRpemVuc2hpcCBjb3VudHJ5LgoKIyMjIyBHZW5kZXIKCkdlbmRlciBJIGV4cGVjdCAyIHJvd3MuCgpgYGB7cn0KY2xlYW5lZF9BZG1pbkFycmVzdCAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHRhbGx5KCkKYGBgCgpXZSBnZXQgYmFjayB0aHJlZSByb3dzOiBGZW1hbGUsIE1hbGUsIGFuZCBVbmtub3duLiBJbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHVua25vd24gaXMgd3JpdHRlbiBpbiwgYW5kIGlzbid0IGp1c3QgYSBibGFuay4gCgojIyMjIEFwcHJlaGVuc2lvbiBTaXRlIExhbmRtYXJrCgpBcHByZWhlbnNpb24gU2l0ZSBMYW5kbWFyayBJIGhhdmUgdmVyeSBsaXR0bGUgZXhwZWN0YXRpb25zIG9uIHdoYXQgd2lsbCBjb21lIGJhY2sgYW5kIHRoaXMgaXMgd2hlcmUgSSBleHBlY3QgdGhlIG1ham9yaXR5IG9mIGluY29uc2lzdGVudGNpZXMgdG8gYmUuIAoKYGBge3J9CmNsZWFuZWRfQWRtaW5BcnJlc3QgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBTaXRlIExhbmRtYXJrYCkgJT4lCiAgdGFsbHkoKQpgYGAKCkhlcmUgSSBnZXQgYmFjayA1NTkwIHJvd3MsIGFuZCB0aGVyZSBhcmUgbWFqb3IgZGlmZmVyZW5jZXMgaW4gY2FwaXRhbGl6YXRpb24gYW5kIHVzYWdlIG9mIGRhc2hlcy4gU29tZSBpbmNsdWRlIHRoZSBzdGF0ZSB0aGV5IHdlcmUgaW4sIG90aGVycyBkbyBub3QuIFNvbWUgYWxzbyBpbmNsdWRlIHRoZSBwcm9ncmFtIHRoZXkgd2VyZSBpbiAoMjg3KGcpLCBDQVAsIGV0Yy4pLiBGb3IgdGhlIHB1cnBvc2VzIG9mIG15IHByb2plY3QgSSdkIHByb2JhYmx5IHRha2UgdGhlIENhbGlmb3JuaWEgc3Vic2V0IGFuZCBjbGVhbiB0aGF0LCBidXQgdGhpcyB3b3VsZCBsaWtlbHkgYmUgdGhlIG1vc3Qgb25lcm91cyBwYXJ0IG9mIHdvcmtpbmcgd2l0aCB0aGlzIGRhdGEuIAoKIyMjIENoZWNraW5nIGZvciBNaXNzaW5nIERhdGEKCk5vdyB0byBjaGVjayBmb3IgbWlzc2luZyBkYXRhLCBJJ20gZ29pbmcgdG8gdXNlL3JlZmVyIHRvIHRoZSBvcmlnaW5hbCB1bmNsZWFuIGRhdGEgIkFkbWluQXJyZXN0IjoKCmBgYHtyfQpNaXNzaW5nRGF0YSA8LWNvbFN1bXMoaXMubmEoQWRtaW5BcnJlc3QpKQpwcmludChNaXNzaW5nRGF0YSkKYGBgCgpIZXJlIHdoYXQncyBhIGJpZyBkZWFsIGlzIHRoYXQgdGhlcmUgYXJlIDU0MTAgcGVvcGxlIG1pc3NpbmcgYW4gQSBudW1iZXIgb3IgYSBVbmlxdWUgSWRlbnRpZmllci4gSSBhbSBsZXNzIHdvcnJpZWQgYmVjYXVzZSB0aGUgRUlEIHN1YmplY3QgSUQgaGFzIG5vIG1pc3NpbmcgZGF0YSwgYnV0IHRoYXQgaXMgc29tZXRoaW5nIHRvIGtlZXAgbm90ZSBvZi4gCgojIyMgQWRkaXRpb25hbCBBbHRlcmluZwoKIyMjIyBDcmVhdGluZyBhIE5ldyBDb2x1bW4gdG8gTG9vayBhdCBUaW1lIG9mIEFycmVzdAoKSSB3YW50IHRvIG11dGF0ZSB0aGUgYXBwcmVoZW5zaW9uIGRhdGUgY29sdW1uIHNvIHRoYXQgSSBjYW4gZmlsdGVyIGxhdGVyIGJ5IHllYXIgYW5kIG1vbnRoLCBhbmQgZXZlbiBwb3RlbnRpYWxseSB0aGUgdGltZSBvZiBkYXkgYW4gYWRtaW5pc3RyYXRpdmUgYXJyZXN0IHRvb2sgcGxhY2UuCgpgYGB7cn0KbmV3X0FkbWluQXJyZXN0IDwtY2xlYW5lZF9BZG1pbkFycmVzdCU+JSAKICBtdXRhdGUoQXBwcmVoZW5zaW9uWWVhciA9IHllYXIoYEFwcHJlaGVuc2lvbiBEYXRlYCkpJT4lIAogIG11dGF0ZShBcHByZWhlbnNpb25Nb250aCA9IG1vbnRoKGBBcHByZWhlbnNpb24gRGF0ZWApKSU+JSAKICBtdXRhdGUoQXBwcmVoZW5zaW9uRGF5ID0gZGF5KGBBcHByZWhlbnNpb24gRGF0ZWApKSU+JSAKICBtdXRhdGUoQXBwcmVoZW5zaW9uSG91ciA9IGhvdXIoYEFwcHJlaGVuc2lvbiBEYXRlYCkpCgpWaWV3KG5ld19BZG1pbkFycmVzdCkKCmBgYAoKIyMjIyBCcmVha2luZyBvdXQgQ2FsaWZvcm5pYSBhbmQgU2FuIEZyYW5jaXNjbyBBcmVhIG9mIFJlc3BvbnNpYmlsaXR5IERhdGEuCgpOb3cgSSB3YW50IHRvIGxvb2sgYXQganVzdCBhZG1pbmlzdHJhdGl2ZSBhcnJlc3RzIGluIENhbGlmb3JuaWEsIHNvIEknbSBnb2luZyB0byBmaWx0ZXIgYnkgdGhlIGFwcHJlaGVuc2lvbiBzdGF0ZSBjb2x1bW4uCgpgYGB7cn0KQ0FfQWRtaW5BcnJlc3QgPC0gbmV3X0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihgQXBwcmVoZW5zaW9uIFN0YXRlYCA9PSAiQ0FMSUZPUk5JQSIpClZpZXcoQ0FfQWRtaW5BcnJlc3QpCgpgYGAKCkkgd2FudCB0byBmaWx0ZXIgdGhhdCBmdXJ0aGVyIHRvIGp1c3QgdGhlIEFkbWluaXN0cmF0aXZlIGFycmVzdHMgaW4gdGhlIFNGIEFyZWEgb2YgUmVzcG9uc2liaWxpdHksIGJlY2F1c2UgZXZlbiB0aG91Z2ggdGhhdCdzIGFjdHVhbGx5IGEgbG90IGxhcmdlciB0aGFuIHRoZSBnZW9ncmFwaGljIHNjb3BlIG15IHByb2plY3QgaXMgbG9va2luZyBhdCwgaXQgYXQgbGVhc3QgaW5jbHVkZXMgbXkgYXJlYSB0aGUgQmF5IEFyZWEuIAoKYGBge3J9ClNGQU9SX0FkbWluQXJyZXN0IDwtIENBX0FkbWluQXJyZXN0ICU+JSAKICBmaWx0ZXIoYEFwcHJlaGVuc2lvbiBBT1JgID09ICJTYW4gRnJhbmNpc2NvIEFyZWEgb2YgUmVzcG9uc2liaWxpdHkiKQpWaWV3KFNGQU9SX0FkbWluQXJyZXN0KQpgYGAKCiMjIEFuYWx5c2lzCgojIyMgQWRtaW5zaXRyYXRpdmUgQXJyZXN0cyBPdmVyIFRpbWUKCkEgcmVhbGx5IGJhc2ljIGNvbXBhcmlzb24gSSBtaWdodCBtYWtlIHRvIHN0YXJ0IGlzIGNvbXBhcmluZyB0aGUgbnVtYmVyIG9mIEFkbWluaXN0cmF0aXZlIEFycmVzdHMgYnkgeWVhci4KCmBgYHtyfQpTRkFPUl9BZG1pbkFycmVzdCAlPiUgCiAgZ3JvdXBfYnkoQXBwcmVoZW5zaW9uWWVhcikgJT4lIAogIHRhbGx5KCkKYGBgCgpCdXQgdGhlIHRhYmxlIEkgZ2V0IGhlcmUgYWN0dWFsbHkgaXNuJ3QgdGhhdCBpbmZvcm1hdGl2ZSBnaXZlbiB0aGF0IEkgb25seSBoYXZlIGRhdGEgZnJvbSB0aHJlZSB5ZWFycy4gQnV0IG1heWJlIEkganVzdCB3YW50IHRvIHNlZSB0aGUgY2hhbmdlIGluIHRpbWUgYnkgbW9udGggb2YganVzdCB0aGlzIG5ldyBhZG1pbmlzdHJhdGlvbiAoMjAyNSksIFNvIEknZCBsaWtlbHkgZG8gdGhlIGZvbGxvd2luZzoKCmBgYHtyfQpTRkFPUl9BZG1pbkFycmVzdGJ5TW9udGggPC1TRkFPUl9BZG1pbkFycmVzdCAlPiUgCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiKSAlPiUgCiAgZ3JvdXBfYnkoQXBwcmVoZW5zaW9uTW9udGgpICU+JSAKICB0YWxseSgpClZpZXcoU0ZBT1JfQWRtaW5BcnJlc3RieU1vbnRoKQoKYGBgCgpKdXN0IGxvb2tpbmcgYXQgdGhlIHRhYmxlIEkgc2VlIHRoZXJlJ3MgYW4gaW5jcmVhc2UgaW4gSnVuZSB3aGljaCBoZWxkIGluIEp1bHksIGJ1dCBpdCBtaWdodCBiZSBoZWxwZnVsIHRvIHZpc3VhbGl6ZSBpdCwgc28gSSdtIGdvaW5nIHRvIGxvb2sgYXQgcGxvdCBpdCBvdXQ6IAoKYGBge3J9CmdncGxvdChkYXRhPVNGQU9SX0FkbWluQXJyZXN0YnlNb250aCkgKwogIGdlb21fbGluZShhZXMoeD1BcHByZWhlbnNpb25Nb250aCwgeT1uKSkgKwogIHhsaW0oMSwxMSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzY2FsZXM6OmJyZWFrc19leHRlbmRlZChuID0gMTEpKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDgwMCksIGJyZWFrcyA9IGMoMCwxMDAsMjAwLDMwMCw0MDAsNTAwLDYwMCw3MDAsODAwKSkrCiAgbGFicyggeCA9ICJNb250aCIsIHkgPSAiTnVtYmVyIG9mIEFycmVzdHMiKSArCiAgZ2d0aXRsZSgiQWRtaW5pc3RyYXRpdmUgQXJyZXN0cyBieSBNb250aCIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKICAKYGBgCgojIyMjIEFkbWluaXN0cmF0aXZlIEFycmVzdHMgYnkgSG91cgoKQW5lY2RvdGFsbHksIEkndmUgYWxzbyBoZWFyZCB0aGlzIHRoaW5nIGZyb20gYSBudW1iZXIgb2YgYWR2b2NhdGVzIHRoYXQgSUNFIGFjdGlvbnMgKGFycmVzdHMpIHRlbmQgdG8gaGFwcGVuIGluIHRoZSBlYXJseSBtb3JuaW5nLiBJIHdhbnQgdG8gY2hlY2sgaWYgdGhhdCdzIHRydWUsIHNvIEknbSBnb2luZyB0byBsb29rIGF0IHRoZSBBcHByZWhlbnNpb25Ib3VyIGNvbHVtbiB0aGF0IEkgbXV0YXRlZCBvdXQgb2YgdGhlIG9yaWdpbmFsIEFwcHJlaGVuc2lvbiBEYXRlIGNvbHVtbi4gSXQncyBvbiBhIDI0IGhvdXIgY2xvY2sgKG5vIGFtL3BtKS4gSSdtIGdvaW5nIHRvIHVzZSB0aGUgQ0FfQWRtaW5BcnJlc3QgZGF0YSBiZWNhdXNlIGFjY29yZGluZyB0byBhZHZvY2F0ZXMgdGhpcyByZXByZXNlbnRzIElDRSBwb2xpY3kgc28gaXQgc2hvdWxkIGJlIHRydWUgYWNyb3NzIHRoZSBzdGF0ZS4gCgpgYGB7cn0KQ0FfQWRtaW5BcnJlc3RfYnlIb3VyIDwtIENBX0FkbWluQXJyZXN0ICU+JQogIGdyb3VwX2J5KEFwcHJlaGVuc2lvbkhvdXIpICU+JQogIHRhbGx5KCkKClZpZXcoQ0FfQWRtaW5BcnJlc3RfYnlIb3VyKQoKYGBgCgpUbyBzZWUgdGhhdCB2aXN1YWxseSBJJ20gZ29pbmcgdG8gY2hhcnQgaXQuIAoKYGBge3J9CmdncGxvdChkYXRhPUNBX0FkbWluQXJyZXN0X2J5SG91ciwgYWVzKHggPSBBcHByZWhlbnNpb25Ib3VyLCB5ID0gbikpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTAuNSwgZmlsbD0gInN0ZWVsYmx1ZSIpICsKICBsYWJzKCB4ID0gIkhvdXIgb2YgdGhlIERheSIsIHkgPSAiTnVtYmVyIG9mIEFycmVzdHMiKSArCiAgZ2d0aXRsZSgiQWRtaW5pc3RyYXRpdmUgQXJyZXN0cyBieSBIb3VyIG9mIHRoZSBEYXkgZnJvbSBTZXB0IDIwMjMgdGhyb3VnaCBPY3QgMjAyNSIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobi5icmVha3M9MjMpCmBgYApUaGlzIHNob3dzIHRoYXQgdGhlIG51bWJlciBvZiBhcnJlc3RzIHBlYWtzIGJldHdlbiA5IGFuZCAxMCBhbSwgYW5kIGlmIHRoZSBhY3R1YWwgYXJyZXN0cyBhcmUgdGFraW5nIHBsYWNlIGF0IHRoYXQgaG91ciB3ZSBjYW4gaW5mZXIgdGhhdCBJQ0UvREhTIGhhZCB0byBiZSBhY3RpdmUgYmVmb3JlIHRoZW4uIFRoZSBtYWpvcml0eSBvZiB0aGUgYWN0aXZpdHkgc2VlbXMgdG8gaGFwcGVuIGJldHdlZW4gN2FtIGFuZCAxcG0uCgojIyMjIENvdW50cmllcyBvZiBPcmlnaW4KCkFub3RoZXIgdGhpbmcgSSdtIGludGVyZXN0ZWQgaW4gaXMgdW5kZXIgdGhlIGN1cnJlbnQgYWRtaW5pc3RyYXRpb24sIHdoYXQgYXJlIHRoZSB0b3AgY291bnRyaWVzIG9mIG9yaWdpbiBmb3IgZm9sa3MgYmVpbmcgYXJyZXN0ZWQuIEknbSBpbnRlcmVzdGVkIGJvdGggc3RhdGV3aWRlIGFuZCBmb3IganVzdCB0aGUgU2FuIEZyYW5jaXNjbyBBT1IsIGJ1dCBJJ2xsIHN0YXJ0IHdpdGgganVzdCBDYWxpZm9ybmlhCgpgYGB7cn0KQ2FsaWZvcm5pYUNpdGl6ZW5zaGlwQ291bnRyeTIwMjUgPC0gQ0FfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiKSAlPiUKICBncm91cF9ieShgQ2l0aXplbnNoaXAgQ291bnRyeWApICU+JQogIHRhbGx5KCkgCgpWaWV3KENhbGlmb3JuaWFDaXRpemVuc2hpcENvdW50cnkyMDI1KQpgYGAKCldoZW4gSSBkbyB0aGlzIGFuZCBzb3J0IGJ5IHZhbHVlcyBteSB0b3AgMTAgY2l0aXplbnNoaXAgY291bnRyaWVzIGFyZSBNZXhpY28sIEd1YXRlbWFsYSwgRWwgU2FsdmFkb3IsIENvbG9tYmlhLCBIb25kdXJhcywgSW5kaWEsIFZlbmV6dWVsYSwgQ2hpbmEsIE5pY2FyYWd1YSBhbmQgUGVydS4gVG8gY29tcGFyZSB0aGlzIHRvIHRoZSBTRkFPUiBJJ20gZG9pbmcgYSBzaW1pbGFyIGFuYWx5c2lzCgoKYGBge3J9ClNGQU9SQ2l0aXplbnNoaXBDb3VudHJ5MjAyNSA8LSBTRkFPUl9BZG1pbkFycmVzdCAlPiUKICBmaWx0ZXIoQXBwcmVoZW5zaW9uWWVhciA9PSAiMjAyNSIpICU+JQogIGdyb3VwX2J5KGBDaXRpemVuc2hpcCBDb3VudHJ5YCkgJT4lCiAgdGFsbHkoKSAKClZpZXcoU0ZBT1JDaXRpemVuc2hpcENvdW50cnkyMDI1KQpgYGAKCldoZW4gSSBzb3J0IHRoaXMgdGFibGUgYnkgdGhlIGNvdW50LCBJIGdldCBzbGlnaHRseSBkaWZmZXJlbnQgcmVzdWx0cywgYnV0IHRoZXJlIGlzIGEgbG90IG9mIG92ZXJsYXAuIEluIHRoZSBTYW4gRnJhbmNpc2NvIEFyZWEgb2YgUmVzcG9uc2liaWxpdHkgdGhlIHRvcCAxMCBjaXRpemVuc2hpcCBjb3VudHJpZXMgZm9yIGFycmVzdGVkIGZvbGtzIGFyZSBNZXhpY28sIEluZGlhLCBHdWF0ZW1hbGEsIEVsIFNhbHZhZG9yLCBDb2xvbWJpYSwgSG9uZHVyYXMsIFBlcnUsIE5pY2FyYWd1YSwgVmVuZXp1ZWxhLCBhbmQgQ2hpbmEuIE1leGljbyBub3RhYmx5IG91dHBhY2VzIHRoZSByZXN0IG9mIHRoZXNlIHBsYWNlcyBpbiBudW1iZXIgb2YgYXJyZXN0cy4gCgojIyMjIENyaW1pbmFsaXR5CgpTb21ldGhpbmcgZWxzZSBJJ20gaW50ZXJlc3RlZCBpbiBpcyB0aGUgImNyaW1pbmFsaXR5IiBvZiB0aG9zZSBhcnJlc3RlZCBpbiB0aGUgU2FuIEZyYW5jaXNjbyBBcmVhIG9mIHJlc3BvbnNpYmlsaXR5LiBBZ2FpbiBJIHdhbnQgdG8gbG9vayBqdXN0IGluIHRoZSBjb250ZXh0IG9mIHRoZSBjdXJyZW50IGFkbWluaXN0cmF0aW9uLiBUaG9zZSB3aG8gYXJlIGFycmVzdGVkIGFyZSBhc3NpZ25lZCB0byBvbmUgb2YgdGhyZWUgY2F0ZWdvcmllcyBvZiBjcmltaW5hbGl0eSwgYnV0IEknbSBpbnRlcmVzdGVkIGluIHRoZSBwcm9wb3J0aW9uIHRoYXQgdGhvc2UgY2F0ZWdvcmllcyBzaG93IHVwIGluIGFycmVzdHMuIAoKYGBge3J9ClNGQU9SQXJyZXN0Q3JpbWluYWxpdHkyMDI1IDwtIFNGQU9SX0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihBcHByZWhlbnNpb25ZZWFyID09ICIyMDI1IikgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBDcmltaW5hbGl0eWApICU+JQogIHRhbGx5KCkgCgpWaWV3KFNGQU9SQXJyZXN0Q3JpbWluYWxpdHkyMDI1KQpgYGAKCkkgd2FudCB0byBzZWUgdGhpcyB2aXN1YWxseSwgc28gZXZlbiB0aG91Z2ggSSdtIG5vdCBhIGZhbiBvZiBwaWUgY2hhcnN0cyBJJ20gZ29pbmcgdG8gbG9vayBhdCBpdCBpbiBhIHBpZSBjaGFydC4KCmBgYHtyfQpnZ3Bsb3QoU0ZBT1JBcnJlc3RDcmltaW5hbGl0eTIwMjUsIGFlcyh4PSJBcHByZWhlbnNpb24gQ3JpbWluYWxpdHkiLCB5PW4sIGZpbGw9YEFwcHJlaGVuc2lvbiBDcmltaW5hbGl0eWApKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCB3aWR0aD0xLCBjb2xvcj0id2hpdGUiKSArCiAgY29vcmRfcG9sYXIoInkiLCBzdGFydD0wKSArCiAgZ2d0aXRsZSgiQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5IFNGQU9SIDIwMjUiKSArCiAgdGhlbWVfdm9pZCgpCmBgYAoKCkZvciB0aG9zZSBhcnJlc3RlZCB0aGUgbWFqb3JpdHkgYXJlIGNvbnZpY3RlZCBjcmltaW5hbHMsIGFjY29yZGluZyB0byB0aGUgZGF0YSwgYnV0IGl0J3Mgbm90YWJsZSB0aGF0IGEgc2l6YWJsZSBjaHVuayBhcmUgY2F0ZWdvcml6ZWQgdW5kZXIgIm90aGVyIGltbWlncmF0aW9uIHZpb2xhdGlvbi4iIEFycmVzdHMgYXJlIHN1cHBvc2VkIHRvIHJlcHJlc2VudCBpbmRpdmlkdWFscyBoYXZlIGEgcmVhbCBjYXNlIGFnYWluc3QgdGhlbSwgc28gdGhlIGNvbnZpY3RlZCBjcmltaW5hbCBjYXRlZ29yeSBzaG91bGQgcmVwcmVzZW50ZWQgdGhlIG1ham9yaXR5LiBBbmQgdGhlc2UgYXJyZXN0cyBhcmUgbm90IHRoZSB0b3RhbGl0eSBvZiBkZXBvcnRhdGlvbnMsIGlmIHlvdSBsb29rIGF0IHRoZSBkZXBvcnRhdGlvbiBkYXRhIHNldCBpbiBhZGRpdGlvbiB0byB0aGlzIGFycmVzdHMgZGF0YSwgeW91IHdvdWxkIGZpbmQgdGhlIG1ham9yaXR5IG9mIGZvbGtzIGNvbWluZyBpbiB0byBjb250YWN0IHdpdGggSUNFL0RIUyBkbyBub3QgaGF2ZSBhbnkgY3JpbWluYWwgY29udmljdGlvbnMuIEl0J3MgYWxzbyB3b3J0aCBub3RpbmcgdGhhdCB0aGUgY29udmljdGVkIGNyaW1pbmFsIGNhdGVnb3J5IGRvZXNuJ3QgYnJlYWsgZG93biBmdXJ0aGVyIGludG8gd2hhdCBjcmltZXMgZm9sa3Mgd2VyZSBjb252aWN0ZWQgb2YuIE90aGVyIHJlcG9ydGluZyBoYXMgY29uZmlybWVkIHRoYXQgdGhlcmUgYXJlIG1hbnkgZm9sa3Mgd2hvIGVuZCB1cCBhcnJlc3RlZCB3aGVyZSB0aGUgYmFzaXMgb2YgdGhlaXIgY29udmljdGlvbiBpcyBhIHRyYWZmaWMgdmlvbGF0aW9uLiBJIHRhbGtlZCB0byBvbmUgbGF3eWVyIGluIHRoZSBCYXkgQXJlYSB3aG8gY29uZmlybWVkIHRoZXkgaGFkIGEgY2xpZW50IHdoZXJlIGEgcHJpb3IgY29udmljdGlvbiBjYW1lIGluIHRoZSBmb3JtIG9mIGEgY2l0YXRpb24gZm9yIGZhaWxpbmcgdG8gcGF5IGZvciBCQVJULiBBcmUgdGhvc2UgY3JpbWVzIHRoZSBzYW1lIGFzIG11cmRlcj8gTm8sIGJ1dCB1bmRlciB0aGlzIGNhdGVnb3JpemF0aW9uIHRoZXkncmUgZmxhdHRlbmVkIGludG8gb25lIGNhdGVnb3J5IHRvZ2V0aGVyLiAKCkp1c3QgdG8gbWFrZSBzdXJlIG15IGFuYWx5c2lzIGlzbid0IG9mZiBJJ20gZ29pbmcgdG8gY29tcGFyZSBTRiBpbiAyMDI1IHRvIGFsbCBvZiBDYWxpZm9ybmlhLgoKYGBge3J9CkNBX0FycmVzdENyaW1pbmFsaXR5MjAyNSA8LSBDQV9BZG1pbkFycmVzdCAlPiUKICBmaWx0ZXIoQXBwcmVoZW5zaW9uWWVhciA9PSAiMjAyNSIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhDQV9BcnJlc3RDcmltaW5hbGl0eTIwMjUpCmBgYAoKSGVyZSBpcyB0aGF0IGluZm9ybWF0aW9uIHZpc3VhbGl6ZWQ6CgpgYGB7cn0KZ2dwbG90KENBX0FycmVzdENyaW1pbmFsaXR5MjAyNSwgYWVzKHg9IkFwcHJlaGVuc2lvbiBDcmltaW5hbGl0eSIsIHk9biwgZmlsbD1gQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5YCkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTEsIGNvbG9yPSJ3aGl0ZSIpICsKICBjb29yZF9wb2xhcigieSIsIHN0YXJ0PTApICsKICBnZ3RpdGxlKCJBcHByZWhlbnNpb24gQ3JpbWluYWxpdHkgQWxsIG9mIENhbGlmb3JuaWEgMjAyNSIpICsKICB0aGVtZV92b2lkKCkKYGBgCgpUaGUgcHJvcG9ydGlvbnMgSSBnZXQgaGVyZSBhcmUgZGlmZmVyZW50LiBPdGhlciBJbW1pZ3JhdGlvbiBWaW9sYXRvciBpcyBuZWFybHkgdGhlIHNhbWUgdmFsdWUgYXMgQ29udmljdGVkIENyaW1pbmFsLiBJJ20gY3VyaW91cyBhcyB0byB3aGF0J3MgYXQgdGhlIHJvb3Qgb2YgdGhpcyBkaXNjcmVwYW5jeSBpbiBTYW4gRnJhbmNpc2NvLiBJIGRvIHdvbmRlciBpZiB0aGlzIGhhcyBzb21ldGhpbmcgdG8gZG8gd2l0aCB0aGUgbGFjayBvZiBpbmRpc2NyaW1pbmF0ZSByYWlkcyBpbiB0aGUgQmF5IEFyZWEsIHdoaWNoIG1lYW5zIHRoYXQgaW4gcGxhY2VzIGxpa2UgTEEgdGhlcmUgaXMgYSBtdWNoIGhpZ2hlciBwcm9wb3J0aW9uIG9mIHBlb3BsZSB3aG8gYXJlIGJlaW5nIHN3ZXB0IHVwIGJ5IHRoaXMgc3lzdGVtLgoKIyMjIyBDaGFuZ2VzIHRvIENyaW1pbmFsaXR5IGJ5IE1vbnRoCgpBZnRlciBsb29raW5nIGF0IHRoZSBnZW5lcmFsIHN1bW1hcnkgb2YgY3JpbWluYWxpdHkgaW5mb3JtYXRpb24sIEkgd2FudCB0byBzZWUgaG93IHRoZSBjcmltaW5hbGl0eSBvZiB3aG8gaXMgYXJyZXN0ZWQgaGFzIGNoYW5nZWQgaW4gdGhlIFNGQU9SIGJ5IG1vbnRoLiBUaGUgcXVlc3Rpb24gSSdkIHdhbnQgYW5zd2VyZWQgaXMgaWYgdGhlIHByb3BvcnRpb24gb2YgcGVvcGxlIGJlaW5nIGFycmVzdGVkIHdobyBoYXZlIGNyaW1pbmFsIGNvbnZpY3Rpb25zIGlzIGNoYW5naW5nLiBTbyBtdWNoIHJlcG9ydGluZyBoYXMgc2FpZCB0aGF0IHJlZ3VsYXIgcGVvcGxlIHdpdGggbm8gY29udmljdGlvbnMgYXJlIGdldHRpbmcgc3dlcHQgdXAgaW4gYXJyZXN0cyB1bmRlciB0aGlzIGFkbWluaXN0cmF0aW9uLiBTbywgSSBzdGFydGVkIHdpdGggU0ZBT1IgQWRtaW4gQXJyZXN0IERhdGEsIGZpbHRlcmVkIGl0IGJ5IHRoZSBjdXJyZW50IHllYXIsIGFuZCB0aGVuIGZvciBlYWNoIG1vbnRoIHNvIGZhciBJIGhhZCBpdCBnaXZlIG1lIHRoZSBwcm9wb3J0aW9uIG9mIGFycmVzdHMgYmFzZWQgb24gY3JpbWluYWxpdHkuCgpKYW51YXJ5CgpgYGB7cn0KU0ZBT1JKYW4yNUNyaW0gPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiLCBBcHByZWhlbnNpb25Nb250aCA9PSAiMSIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUkphbjI1Q3JpbSkKYGBgCgpGZWJydWFyeQoKYGBge3J9ClNGQU9SRmViMjVDcmltIDwtIFNGQU9SX0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihBcHByZWhlbnNpb25ZZWFyID09ICIyMDI1IiwgQXBwcmVoZW5zaW9uTW9udGggPT0gIjIiKSAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5YCkgJT4lCiAgdGFsbHkoKSAKClZpZXcoU0ZBT1JGZWIyNUNyaW0pCmBgYAoKTWFyY2gKCmBgYHtyfQpTRkFPUk1hcjI1Q3JpbSA8LSBTRkFPUl9BZG1pbkFycmVzdCAlPiUKICBmaWx0ZXIoQXBwcmVoZW5zaW9uWWVhciA9PSAiMjAyNSIsIEFwcHJlaGVuc2lvbk1vbnRoID09ICIzIikgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBDcmltaW5hbGl0eWApICU+JQogIHRhbGx5KCkgCgpWaWV3KFNGQU9STWFyMjVDcmltKQpgYGAKCkFwcmlsCgpgYGB7cn0KU0ZBT1JBcHIyNUNyaW0gPC0gU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiLCBBcHByZWhlbnNpb25Nb250aCA9PSAiNCIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gQ3JpbWluYWxpdHlgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUkFwcjI1Q3JpbSkKYGBgCgpNYXkKCmBgYHtyfQpTRkFPUk1heTI1Q3JpbSA8LSBTRkFPUl9BZG1pbkFycmVzdCAlPiUKICBmaWx0ZXIoQXBwcmVoZW5zaW9uWWVhciA9PSAiMjAyNSIsIEFwcHJlaGVuc2lvbk1vbnRoID09ICI1IikgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBDcmltaW5hbGl0eWApICU+JQogIHRhbGx5KCkgCgpWaWV3KFNGQU9STWF5MjVDcmltKQpgYGAKCkp1bmUKCmBgYHtyfQpTRkFPUkp1bjI1Q3JpbSA8LSBTRkFPUl9BZG1pbkFycmVzdCAlPiUKICBmaWx0ZXIoQXBwcmVoZW5zaW9uWWVhciA9PSAiMjAyNSIsIEFwcHJlaGVuc2lvbk1vbnRoID09ICI2IikgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBDcmltaW5hbGl0eWApICU+JQogIHRhbGx5KCkgCgpWaWV3KFNGQU9SSnVuMjVDcmltKQpgYGAKCkp1bHkKCmBgYHtyfQpTRkFPUkp1bDI1Q3JpbSA8LSBTRkFPUl9BZG1pbkFycmVzdCAlPiUKICBmaWx0ZXIoQXBwcmVoZW5zaW9uWWVhciA9PSAiMjAyNSIsIEFwcHJlaGVuc2lvbk1vbnRoID09ICI3IikgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBDcmltaW5hbGl0eWApICU+JQogIHRhbGx5KCkgCgpWaWV3KFNGQU9SSnVsMjVDcmltKQpgYGAKCkF1Z3VzdAoKYGBge3J9ClNGQU9SQXVnMjVDcmltIDwtIFNGQU9SX0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihBcHByZWhlbnNpb25ZZWFyID09ICIyMDI1IiwgQXBwcmVoZW5zaW9uTW9udGggPT0gIjgiKSAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5YCkgJT4lCiAgdGFsbHkoKSAKClZpZXcoU0ZBT1JBdWcyNUNyaW0pCmBgYAoKU2VwdGVtYmVyCgpgYGB7cn0KU0ZBT1JTZXB0MjVDcmltIDwtIFNGQU9SX0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihBcHByZWhlbnNpb25ZZWFyID09ICIyMDI1IiwgQXBwcmVoZW5zaW9uTW9udGggPT0gIjkiKSAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5YCkgJT4lCiAgdGFsbHkoKSAKClZpZXcoU0ZBT1JTZXB0MjVDcmltKQpgYGAKCk9jdG9iZXIsIGJ1dCBJJ20gbm90aW5nIHRoYXQgdGhlIE9jdG9iZXIgZGF0YSBpcyBpbmNvbXBsZXRlLgoKYGBge3J9ClNGQU9ST2N0MjVDcmltIDwtIFNGQU9SX0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihBcHByZWhlbnNpb25ZZWFyID09ICIyMDI1IiwgQXBwcmVoZW5zaW9uTW9udGggPT0gIjEwIikgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBDcmltaW5hbGl0eWApICU+JQogIHRhbGx5KCkgCgpWaWV3KFNGQU9ST2N0MjVDcmltKQpgYGAKClRoZXJlIHdhcyBwcm9iYWJseSBhIGZhc3RlciB3YXkgdG8gaXRlcmF0ZSB0aGlzIHByb2Nlc3MsIGJ1dCBJIHRvb2sgdGhlIHJlc3VsdHMgb2YgZWFjaCBvZiB0aGVzZSBhbmQgbWFkZSBhIHNwcmVhZHNoZWV0IHRvIHZpc3VhbGl6ZS4gCgoKIyMjIyBBcnJlc3QgUGlja3VwIExvY2F0aW9uIGFuZCBBcHByZWhlbnNpb24gTWV0aG9kCgpgYGB7cn0KU0ZBT1JfQWRtaW5BcnJlc3QyMDI1IDwtU0ZBT1JfQWRtaW5BcnJlc3QgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiKSAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIE1ldGhvZGAsYEFwcHJlaGVuc2lvbiBTaXRlIExhbmRtYXJrYCkKCnZpZXcoU0ZBT1JfQWRtaW5BcnJlc3QyMDI1KQpgYGAKCkkgd2FudCB0byBsb29rIGF0IHdoZXJlIHRoZSBhcHByZWhlbnNpb24gbWV0aG9kIGlzIDI4N2cuCgpgYGB7cn0KU0ZBT1JfQWRtaW5BcnJlc3QyMDI1XzI4N2cgPC1TRkFPUl9BZG1pbkFycmVzdDIwMjUgJT4lCiAgZmlsdGVyKGBBcHByZWhlbnNpb24gTWV0aG9kYD09ICIyODcoZykgUHJvZ3JhbSIpCgp2aWV3KFNGQU9SX0FkbWluQXJyZXN0MjAyNV8yODdnKQpgYGAKCkkgd2FudCB0byBsb29rIGF0IGFwcHJlaGVuc2lvbiBtZXRob2QgaW52b2x2aW5nIGxvY2FsIGluY2FyY2VyYXRpb24KCmBgYHtyfQpTRkFPUl9BZG1pbkFycmVzdDIwMjVfbG9jYWwgPC0gU0ZBT1JfQWRtaW5BcnJlc3QyMDI1ICU+JQogIGZpbHRlcihgQXBwcmVoZW5zaW9uIE1ldGhvZGA9PSAiQ0FQIExvY2FsIEluY2FyY2VyYXRpb24iKQoKVmlldyAoU0ZBT1JfQWRtaW5BcnJlc3QyMDI1X2xvY2FsKQpgYGAKCk5vdyBJIHdhbnQgYSB0YWxseSBvZiBhcHByZWhlbnNpb24gc2l0ZSBsYW5kbWFya3MuCgpgYGB7cn0KU0ZBUExhbmRtYXJrcyA8LSBTRkFPUl9BZG1pbkFycmVzdDIwMjUgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBTaXRlIExhbmRtYXJrYCklPiUKICB0YWxseSgpCgp2aWV3KFNGQVBMYW5kbWFya3MpCgpgYGAKClRoZXNlIGFyZSB1bmZvcnR1bmF0ZWx5IHZhZ3VlLCBhbmQgdGhleSdyZSB3b3J0aCBsb29raW5nIGF0IGZvciBtZSBwZXJzb25hbGx5LCBidXQgdGhleSBkbyBub3QgbWFrZSBmb3IgYSBncmVhdCB2aXN1YWxpemF0aW9uLiAKCiMjIyMgRGVtb2dyYXBoaWNzIGluIFNGQU9SCgpUaGlzIGlzIHRoZSBnZW5kZXIgb2YgU0ZBT1IgYWRtaW4gYXJyZXN0cyBpbiAyMDI1LgoKYGBge3J9ClNGQU9SQXJyZXN0R2VuZGVyMjAyNSA8LSBTRkFPUl9BZG1pbkFycmVzdCAlPiUKICBmaWx0ZXIoQXBwcmVoZW5zaW9uWWVhciA9PSAiMjAyNSIpICU+JQogIGdyb3VwX2J5KGBHZW5kZXJgKSAlPiUKICB0YWxseSgpIAoKVmlldyhTRkFPUkFycmVzdEdlbmRlcjIwMjUpCgpgYGAKCkhlcmUncyB0aGUgZ2VuZGVyIGluZm9ybWF0aW9uIGdyYXBoZWQKCmBgYHtyfQpnZ3Bsb3QoU0ZBT1JBcnJlc3RHZW5kZXIyMDI1LCBhZXMoeD0iR2VuZGVyIiwgeT1uLCBmaWxsPWBHZW5kZXJgKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iiwgd2lkdGg9MSwgY29sb3I9IndoaXRlIikgKwogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQ9MCkgKwogIGdndGl0bGUoIkFycmVzdCBHZW5kZXIgU0ZBT1IgMjAyNSIpICsKICB0aGVtZV92b2lkKCkKYGBgCgpUaGlzIGlzIGFuIGFnZSBicmVha2Rvd24gb2YgU0ZBT1IgYWRtaW4gYXJyZXN0cyBpbiAyMDI1CgpgYGB7cn0KU0ZBT1JfQWRtaW5BcnJlc3RfQWdlMjAyNSA8LSBTRkFPUl9BZG1pbkFycmVzdCAlPiUKICBtdXRhdGUoQWdlID0gMjAyNSAtIGBCaXJ0aCBZZWFyYCkgJT4lCiAgZmlsdGVyKEFwcHJlaGVuc2lvblllYXIgPT0gIjIwMjUiKSAlPiUKICBncm91cF9ieShBZ2UpICAlPiUKICB0YWxseSgpCgpWaWV3KFNGQU9SX0FkbWluQXJyZXN0X0FnZTIwMjUpCmBgYAoKSGVyZSBpcyB0aGF0IHNhbWUgaW5mb3JtYXRpb24gZ3JhcGhlZC4KCmBgYHtyfQpnZ3Bsb3QoZGF0YT1TRkFPUl9BZG1pbkFycmVzdF9BZ2UyMDI1LCBhZXMoeCA9IEFnZSwgeSA9bikpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTAuNSwgZmlsbD0gInN0ZWVsYmx1ZSIpICsKICBsYWJzKCB4ID0gIkFnZSBSYW5nZSIsIHkgPSAiTnVtYmVyIG9mIEFycmVzdHMiKSArCiAgZ2d0aXRsZSgiQXJyZXN0cyBieSBBZ2UgU0ZBT1IiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKG4uYnJlYWtzPTIwKQpgYGAKCkkgd2FudCB0byBrbm93IHdoYXQgdGhlIE1lZGlhbiBhbmQgTWVhbiBhZ2Ugb2YgYXJyZXN0IGFyZSBzbyBJIGNhbiBpbmNvcnBvcmF0ZSB0aGVtIGludG8gYSBiZXR0ZXIgZ3JhcGhpYwoKYGBge3J9CnN1bW1hcnkoU0ZBT1JfQWRtaW5BcnJlc3RfQWdlMjAyNSRBZ2UpCmBgYAoKCiMjIyMgV2hlcmUgZG8gQXJyZXN0ZWQgUGVvcGxlIGluIHRoZSBTRkFPUiBHbz8KCkknbSBnb2luZyB0byBkbyBzb21lIGFuYWx5c2lzIHdpdGggdGhlIGludGVudGlvbiBvZiBwdXR0aW5nIGl0IGludG8gYSBwcmV0dGllciBwcm9ncmFtLCBsaWtlIGZsb3VyaXNoLiBUaGUgb25seSBzdXJlZmlyZSB3YXkgdG8gdGVsbCBpZiBhbiBhcnJlc3QgcmVzdWx0cyBpbiBhIGRlcG9ydGF0aW9uIGlzIHRoYXQgdGhlcmUgaXMgYSBkZXBhcnR1cmUgY291bnRyeSBvciBkZXBhcnRlZCBkYXRlIGxpc3RlZC4gSSB3YW50IHRvIHN0YXJ0IGNyZWF0aW5nIHR3byBuZXcgZW50aXRpZXMsIG9uZSB3aGljaCBpcyB0aGUgU0ZBT1IgMjAyNSBhcnJlc3RzIHRoYXQgcmVzdWx0ZWQgaW4gYSBkZXBvcnRhdGlvbiwgYW5kIHRoZSBvdGhlciBiZWluZyB0aGUgU0ZBT1IgMjAyNSBhcnJlc3RzIHRoYXQgZGlkIG5vdCByZXN1bHQgaW4gYSBkZXBvcnRhdGlvbi4gSGVyZSdzIGhvdyBJIHdvdWxkIG1ha2UgZWFjaCBvZiB0aG9zZS4KCkRlcG9ydGVkIERhdGEgU2V0OgoKYGBge3J9CkRlcG9ydGVkX1NGQU9SXzI1IDwtIFNGQU9SX0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihBcHByZWhlbnNpb25ZZWFyID09ICIyMDI1IikgJT4lIAogIGRyb3BfbmEoYERlcGFydGVkIERhdGVgKQoKVmlldyhEZXBvcnRlZF9TRkFPUl8yNSkKYGBgCgpOb24gRGVwb3J0ZWQgRGF0YSBTZXQ6IAoKYGBge3J9Ck5vdERlcG9ydGVkX1NGQU9SXzI1IDwtIFNGQU9SX0FkbWluQXJyZXN0ICU+JQogIGZpbHRlcihBcHByZWhlbnNpb25ZZWFyID09ICIyMDI1IiwgaXMubmEoYERlcGFydGVkIERhdGVgKSkgCiAKVmlldyhOb3REZXBvcnRlZF9TRkFPUl8yNSkKYGBgCgpJIHdhbnQgdG8gbm90ZSB0aGF0IDIsMDg2IGFycmVzdHMgaW4gdGhlIFNGQU9SIHJlc3VsdGVkIGluIGRlcG9ydGF0aW9uLCBhbmQgMSw3NTYgZGlkIG5vdC4gTm93IEkgd2FudCB0byBsb29rIGF0IHRoZSBmaW5hbCBwcm9ncmFtIHRoYXQgcGVvcGxlIHdobyB3ZXJlIGRlcG9ydGVkIGVuZGVkIHVwIGluLgoKYGBge3J9CkZQRGVwb3J0ZWRfU0ZBT1JfMjUgPC0gRGVwb3J0ZWRfU0ZBT1JfMjUgJT4lCiAgZ3JvdXBfYnkoYEZpbmFsIFByb2dyYW1gKSAlPiUKICB0YWxseSgpCgpWaWV3KEZQRGVwb3J0ZWRfU0ZBT1JfMjUpCmBgYAoKSXQncyBub3Qgc3VycHJpc2luZyB0aGF0IEVSTyBDcmltaW5hbCBBbGllbiBQcm9ncmFtIHdhcyB0aGUgbGFyZ2VzdCBjYXRlZ29yeSBiZWNhdXNlIGl0J3MgdGhlIHZhZ3Vlc3QsIHNvIHdpdGhpbiB0aGF0IEkgd2FudGVkIHRvIHNlZSB3aGF0IHRoZSB0b3AgYXBwcmVoZW5zaW9uIG1ldGhvZHMgd2VyZS4gCgpgYGB7cn0KRVJPRGVwb3J0ZWRfU0ZBT1JfMjUgPC0gRGVwb3J0ZWRfU0ZBT1JfMjUgJT4lCiAgZmlsdGVyKGBGaW5hbCBQcm9ncmFtYD09ICJFUk8gQ3JpbWluYWwgQWxpZW4gUHJvZ3JhbSIpICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gTWV0aG9kYCkgJT4lCiAgdGFsbHkoKQoKVmlldyhFUk9EZXBvcnRlZF9TRkFPUl8yNSkKYGBgCgoKSSBhbHNvIHdhbnQgdG8gc2VlIGhvdyB0aGUgYXBwcmVoZW5zaW9uIG1ldGhvZCBicmVha2Rvd24gZm9yIHBlb3BsZSB3aG8gd2VyZSBkZXBvcnRlZC4KCmBgYHtyfQpBTURlcG9ydGVkX1NGQU9SXzI1IDwtIERlcG9ydGVkX1NGQU9SXzI1ICU+JQogIGdyb3VwX2J5KGBBcHByZWhlbnNpb24gTWV0aG9kYCkgJT4lCiAgdGFsbHkoKQoKVmlldyhBTURlcG9ydGVkX1NGQU9SXzI1KQpgYGAKCk91dCBvZiBjdXJpb3NpdHkgSSBkbyB3YW50IHRvIHNlZSB0aGUgZmluYWwgcHJvZ3JhbSBicmVha2Rvd24gZm9yIHBlb3BsZSB3aG8gd2VyZSBub3QgZGVwb3J0ZWQuCgpgYGB7cn0KRlBOb3REZXBvcnRlZF9TRkFPUl8yNSA8LSBOb3REZXBvcnRlZF9TRkFPUl8yNSAlPiUKICBncm91cF9ieShgRmluYWwgUHJvZ3JhbWApICU+JQogIHRhbGx5KCkKClZpZXcoRlBOb3REZXBvcnRlZF9TRkFPUl8yNSkKYGBgCgpGb3IgYm90aCBncm91cHMgSSBhbHNvIHdhbnQgdG8gc2VlIHdoYXQgdGhlIGNyaW1pbmFsaXR5IGJyZWFrZG93biBsb29rcyBsaWtlLiBIZXJlIGZpcnN0IGlzIHRoZSBEZXBvcnRlZCBHcm91cCdzIGNyaW1pbmFsaXR5OgoKYGBge3J9CkNyaW1EZXBvcnRlZF9TRkFPUl8yNSA8LSBEZXBvcnRlZF9TRkFPUl8yNSAlPiUKICBncm91cF9ieShgQXBwcmVoZW5zaW9uIENyaW1pbmFsaXR5YCkgJT4lCiAgdGFsbHkoKQoKVmlldyhDcmltRGVwb3J0ZWRfU0ZBT1JfMjUpCmBgYAoKQW5kIHRoaXMgaXMgdGhlIG5vbiBkZXBvcnRlZCBncm91cCdzIGNyaW1pbmFsaXR5LiAKCmBgYHtyfQpDcmltTm90RGVwb3J0ZWRfU0ZBT1JfMjUgPC0gTm90RGVwb3J0ZWRfU0ZBT1JfMjUgJT4lCiAgZ3JvdXBfYnkoYEFwcHJlaGVuc2lvbiBDcmltaW5hbGl0eWApICU+JQogIHRhbGx5KCkKClZpZXcoQ3JpbU5vdERlcG9ydGVkX1NGQU9SXzI1KQpgYGAKCkhlcmUgaXQgaXMgaW50ZXJlc3RpbmcgdG8gbm90ZSB0aGF0IHRoZSB2YXN0IG1ham9yaXR5IG9mIHBlb3BsZSB3aG8gYXJlIGFycmVzdGVkIGFuZCBkZXBvcnRlZCAoZm9yIG5vdykgZG8gc2VlbSB0byBoYXZlIGEgY3JpbWluYWwgY29udmljdGlvbiwgYnV0IHRoZSBhcnJlc3RlZCBub24gZGVwb3J0ZWQgY2F0ZWdvcnkgaXMgbWFueSBtb3JlIGZvbGtzIHdpdGgganVzdCBpbW1pZ3JhdGlvbiB2aW9sYXRpb25zLiBUaGlzIGlzIHdvcnRoIG5vdGluZy4gSSBkaWQgYSBidW5jaCBvZiB0aGVzZSBicmVha291dHMgZm9yIHRoZSBwdXJwb3NlcyBvZiBteSBvd24gdW5kZXJzdGFuZGluZywgYnV0IGFzIGZvciBtYWtpbmcgYSB2aXN1YWwgdGhhdCBJIHRoaW5rIGhhcyBtb3JlIGNhcGFjaXR5IHRvIGJlIGluZm9ybWF0aXZlLCBJJ20gZ29pbmcgdG8gd29yayB3aXRoIHRoZSBmaW5hbCBwcm9ncmFtIGNhdGVnb3JpemF0aW9uIHRvIG1ha2UgYSAK